From b28dfa7ecb29b44e6df8e8f97fc41dad73440823 Mon Sep 17 00:00:00 2001 From: Tyler van der Hoeven Date: Tue, 7 Feb 2023 16:32:46 -0500 Subject: [PATCH] Reorg (#290) * Change SDK section to Reference section * Adding JS SDK to list of SDKs * Adding Overcat's Python SDK to list of SDKs * Moving Networks -> Futurenet to Reference section * Moving Releases to Reference section * Delete Networks from main nav Networks now lives under Reference section * Deleting as Releases now live in Reference section * Changing sidebar position Temporary, this will eventually move to How-To Guides * Update byo.mdx * Edited Quick Start to 1. Hello World Includes Tutorials -> Create a Project / Write a Contract / Test / Build / Run on Sandbox / Optimizing Builds * Move Storing Data from Examples to Getting Started * Move Deploy to Local Network to Getting Started Moved this section from Tutorials to Getting Started * Move Freighter wallet tutorial to Getting Started * Update and rename 6.-connect-Freighter-wallet.mdx to 4. Connect Freighter Wallet * Move Deploy to Futurenet to Getting Started * Rename 4. Connect Freighter Wallet to 4. Connect Freighter Wallet.mdx * Moved to Getting Started * Moved to Getting Started Removing this section * Moved to Getting Started Removing this as it has been moved to Getting Started * Moved to Getting Started -> Hello World * Moved to Getting Started -> Hello World * Moved to Getting Started -> Hello World * Moved to Getting Started -> Hello World * Moved to Getting Started -> Hello World * Moved to Getting Started -> Hello World * Moved to Getting Started Removing due to this section being moved * Update Examples to How-To Guides * Move BYO SDK to How-To Guides * Moved to How-To Guides * Moved invoking contracts with transactions to How-To Guides * Removing because it's moved to How-To Guides * Moved Token Interface to Token How-To Guide * Remove Token Interface Token Interface has been moved to How-To Guides -> Token * Move Stellar Asset Contract to How-To Guides * Delete docs/built-in-contracts directory Moved to How-To Guides * Move Stellar FAQs to Learn * Delete faq.mdx Moved to Learn * Update authorization.mdx Alphabetize sidebar * Update contract-lifecycle.mdx Alphabetizing sidebar * Update custom-types.mdx Alphabetizing sidebar * Update rust-dialect.mdx Alphabetizing sidebar * Update debugging.mdx Alphabetizing sidebar * Update environment-concepts.mdx Alphabetizing sidebar * Update errors.mdx Alphabetizing sidebar * Update events.mdx Alphabetizing sidebar * Update gas-and-metering.mdx Alphabetizing sidebar * Update interacting-with-contracts.mdx Alphabetizing sidebar * Update persisting-data.mdx Alphabetizing sidebar * Update high-level-overview.mdx Update spelling * formatting * formatting * formatting * formatting * Update faq.mdx * fixed broken links * fix broken links * fix broken links * moar link fixes * fixed some broken links * added sorobanathon homepage * add google tag manager * Content edits made * back to original * Content Edit * button location * Content & Eligibility guidelines added * Update sorobanathon.js * update all admonitions such that prettier doesn't yell * Lots of formatting * --prose-wrap preserve * Update releases.mdx * update prettier * fixed the callouts * formatting * fix module import * Update sorobanathon.js * Fixed Reorg PR Fixed links, moved sections, deleted double sections * Update index.js * Updating Sorobanathon Info * Fixed links Many links. * Formatting * Change SDK section to Reference section * Adding JS SDK to list of SDKs * Adding Overcat's Python SDK to list of SDKs * Moving Networks -> Futurenet to Reference section * Moving Releases to Reference section * Delete Networks from main nav Networks now lives under Reference section * Deleting as Releases now live in Reference section * Changing sidebar position Temporary, this will eventually move to How-To Guides * Update byo.mdx * formatting * fix broken links * Edited Quick Start to 1. Hello World Includes Tutorials -> Create a Project / Write a Contract / Test / Build / Run on Sandbox / Optimizing Builds * Move Storing Data from Examples to Getting Started * Move Deploy to Local Network to Getting Started Moved this section from Tutorials to Getting Started * Move Freighter wallet tutorial to Getting Started * Update and rename 6.-connect-Freighter-wallet.mdx to 4. Connect Freighter Wallet * Move Deploy to Futurenet to Getting Started * Rename 4. Connect Freighter Wallet to 4. Connect Freighter Wallet.mdx * Moved to Getting Started Removing this as it has been moved to Getting Started * Moved to Getting Started -> Hello World * Moved to Getting Started -> Hello World * formatting * fix broken links * moar link fixes * Update Examples to How-To Guides * Move BYO SDK to How-To Guides * Moved invoking contracts with transactions to How-To Guides * Moved Token Interface to Token How-To Guide * Remove Token Interface Token Interface has been moved to How-To Guides -> Token * Move Stellar Asset Contract to How-To Guides * Delete docs/built-in-contracts directory Moved to How-To Guides * formatting * fixed broken links * Move Stellar FAQs to Learn * Update authorization.mdx Alphabetize sidebar * Update contract-lifecycle.mdx Alphabetizing sidebar * Update custom-types.mdx Alphabetizing sidebar * Update rust-dialect.mdx Alphabetizing sidebar * Update debugging.mdx Alphabetizing sidebar * Update environment-concepts.mdx Alphabetizing sidebar * Update errors.mdx Alphabetizing sidebar * Update events.mdx Alphabetizing sidebar * Update gas-and-metering.mdx Alphabetizing sidebar * Update interacting-with-contracts.mdx Alphabetizing sidebar * Update persisting-data.mdx Alphabetizing sidebar * Update high-level-overview.mdx Update spelling * formatting * Update faq.mdx * fixed some broken links * Update releases.mdx * update prettier * fixed the callouts * formatting * fix module import * Fixed Reorg PR Fixed links, moved sections, deleted double sections * Fixed links Many links. * Formatting * Merge cleanup * More cleanup * Formatting * some small design tweaks * copy tweaks --------- Co-authored-by: Bri <92327786+briwylde08@users.noreply.github.com> Co-authored-by: Anuxhya <36203801+achallagundla@users.noreply.github.com> --- docs/faq.mdx | 50 -- .../connect-freighter-wallet.mdx | 18 + .../deploy-to-a-local-network.mdx} | 54 +-- .../deploy-to-futurenet.mdx | 51 +-- docs/getting-started/hello-world.mdx | 427 ++++++++++++++++++ docs/getting-started/quick-start.mdx | 183 -------- docs/getting-started/storing-data.mdx | 207 +++++++++ docs/tutorials/_category_.json | 7 - docs/tutorials/build-optimized.mdx | 89 ---- docs/tutorials/build.mdx | 38 -- docs/tutorials/create-a-project.mdx | 151 ------- .../invoking-contracts-with-transactions.mdx | 119 ----- docs/tutorials/run-on-sandbox.mdx | 41 -- docs/tutorials/testing.mdx | 112 ----- docs/tutorials/write-a-contract.mdx | 65 --- 15 files changed, 685 insertions(+), 927 deletions(-) delete mode 100644 docs/faq.mdx create mode 100644 docs/getting-started/connect-freighter-wallet.mdx rename docs/{tutorials/deploy-to-local-network.mdx => getting-started/deploy-to-a-local-network.mdx} (60%) rename docs/{tutorials => getting-started}/deploy-to-futurenet.mdx (57%) create mode 100644 docs/getting-started/hello-world.mdx delete mode 100644 docs/getting-started/quick-start.mdx create mode 100644 docs/getting-started/storing-data.mdx delete mode 100644 docs/tutorials/_category_.json delete mode 100644 docs/tutorials/build-optimized.mdx delete mode 100644 docs/tutorials/build.mdx delete mode 100644 docs/tutorials/create-a-project.mdx delete mode 100644 docs/tutorials/invoking-contracts-with-transactions.mdx delete mode 100644 docs/tutorials/run-on-sandbox.mdx delete mode 100644 docs/tutorials/testing.mdx delete mode 100644 docs/tutorials/write-a-contract.mdx diff --git a/docs/faq.mdx b/docs/faq.mdx deleted file mode 100644 index 13b6afee6..000000000 --- a/docs/faq.mdx +++ /dev/null @@ -1,50 +0,0 @@ ---- -sidebar_position: 100 -title: Soroban on Stellar FAQ ---- - -:::caution - -Soroban's Stellar integration is under active-development and may change. - -::: - -### What is Soroban to Stellar? Is it a new blockchain? - -Soroban is not a new blockchain. Soroban is a Smart contract platform that is integrated into the existing Stellar blockchain. It is an _additive_ feature that lives alongside, and doesn't replace, the existing set of Stellar operations. - -### How do I invoke a Soroban contract on Stellar? - -A Soroban contract can be invoked by submitting a transaction that contains the new operation: `InvokeContractOp`. - -### Can Soroban contracts use Stellar accounts for authentication? - -Yes. Stellar accounts are shared with Soroban. Smart contacts have access to Stellar account signer configuration and know the source account that directly invoked them in a transaction. Check out the Auth and Advanced Auth examples for more information. - -### Can Soroban contracts interact with Stellar Assets? - -Yes. Soroban contains a built-in Stellar Asset Contract that is able to interact -with classic trustlines. Read more about this [here](built-in-contracts/stellar-asset-contract.mdx). - -### Do Issuers of Stellar Assets maintain their authorization over an asset that has been sent to a non-account identifer in Soroban? (AUTH_REQUIRED, AUTH_REVOCABLE, AUTH_CLAWBACK) - -Yes. Issuers retain the same level of control on Soroban as they have on Classic. This functionality is accessible through a set of admin functions (clawback, set_auth) on the built-in Stellar Asset Contract. - -### Can Soroban contracts interact with any other Stellar operations? - -No. Aside from the interactions with Accounts and Assets as mentioned above. This means that Soroban contracts can not interact with SDEX, AMMs, Claimable Balances or Sponsorships. - -### Does the Stellar base reserve apply to Soroban contracts? - -No. Soroban has a different fee structure and ledger entries that are allocated by Soroban contracts do not add to an account's required minimal balance. - -### Should I issue my token as a Stellar Asset or a custom Soroban token? - -We recommend, to the extent possible, issuing tokens as Stellar assets. These -tokens will benefit from being interopable with the existing ecosystem of tools -available in the Stellar ecosystem, as well as being more performant because the -Stellar Asset Contract is built into the host. - -### Haven't found what you're looking for? - -Join #soroban on the Stellar developer discord diff --git a/docs/getting-started/connect-freighter-wallet.mdx b/docs/getting-started/connect-freighter-wallet.mdx new file mode 100644 index 000000000..a0e29e632 --- /dev/null +++ b/docs/getting-started/connect-freighter-wallet.mdx @@ -0,0 +1,18 @@ +--- +sidebar_position: 6 +title: 4. Connect Freighter Wallet +--- + +## Signing Transactions with Freighter + +If you're building a JS dapp, easily sign Soroban transactions using the [Freighter browser extension](https://www.freighter.app/) and its corresponding client library [@stellar/freighter-api](https://www.npmjs.com/package/@stellar/freighter-api): + +1. Install the Freighter browser extension. + +2. Create a keypair or import an existing account using a mnemonic phrase to complete setup. + +3. Next, switch to Experimental Mode to enable the Soroban SDK. In the extension, click the gear in the lower right corner and then navigate to `Preferences`. Toggle on `Experimental Mode`. + +4. Now, you can use the `signTransaction` [method](https://docs.freighter.app/docs/guide/usingFreighterNode) from `@stellar/freighter-api` in your dapp to sign Soroban XDR's using the account in Freighter. + +Upon calling `signTransaction`, Freighter will open and prompt the user to sign the transaction. Approving the transaction will return the signed XDR to the requesting dapp. diff --git a/docs/tutorials/deploy-to-local-network.mdx b/docs/getting-started/deploy-to-a-local-network.mdx similarity index 60% rename from docs/tutorials/deploy-to-local-network.mdx rename to docs/getting-started/deploy-to-a-local-network.mdx index dcf7db5f1..8874260a2 100644 --- a/docs/tutorials/deploy-to-local-network.mdx +++ b/docs/getting-started/deploy-to-a-local-network.mdx @@ -1,30 +1,24 @@ --- -sidebar_position: 8 -title: Deploy to a Local Network +sidebar_position: 5 +title: 3. Deploy to a Local Network --- -If you have Docker installed, you can run a local standalone network with the -[Stellar Quickstart] Docker image. +If you have Docker installed, you can run a local standalone network with the [Stellar Quickstart] Docker image. -The Quickstart image is a single container that runs everything you need to test -against a fully featured network. It contains: +The Quickstart image is a single container that runs everything you need to test against a fully featured network. It contains: -- Stellar Core – Node software that runs the network, coordinates consensus, and - finalizes ledgers. +- Stellar Core – Node software that runs the network, coordinates consensus, and finalizes ledgers. - Soroban RPC server – JSON RPC server for interacting with Soroban contracts. - Horizon server – HTTP API for access ledger state and historical transactions. -- Friendbot server – HTTP API for creating and funding new accounts on test - networks. +- Friendbot server – HTTP API for creating and funding new accounts on test networks. :::info -It's also possible to run a contract in the local sandbox environment without a -network using just the [`soroban-cli`]. See [Run on Sandbox] for more details. +It's also possible to run a contract in the local sandbox environment without a network using just the [`soroban-cli`]. See [Run on Sandbox] for more details. ::: -To run a local standalone network with the Stellar Quickstart Docker image, -run the following command. +To run a local standalone network with the Stellar Quickstart Docker image, run the following command. ```sh docker run --rm -it \ @@ -41,30 +35,21 @@ Once the image is started you can check its status by querying the Horizon API: curl http://localhost:8000 ``` -Generate a key for use on the local sandbox environment by going to the [Stellar -Laboratory]. Make note of both the `G...` and `S...` keys. The `G...` key is the -public key and will also be the account ID. The `S...` key is the secret key and -is that you use to control the account. +Generate a key for use on the local sandbox environment by going to the [Stellar Laboratory]. Make note of both the `G...` and `S...` keys. The `G...` key is the public key and will also be the account ID. The `S...` key is the secret key and is that you use to control the account. :::tip -It's a good practice to never use the same keys for testing and development that -you use do for the public Stellar network. Generate new keys for testing and -development and avoid ever using them for other purposes. +It's a good practice to never use the same keys for testing and development that you use do for the public Stellar network. Generate new keys for testing and development and avoid ever using them for other purposes. ::: -Create an account on the local sandbox environment by making a request to the -local Friendbot. Specify as the `addr` the `G...` key of your account. +Create an account on the local sandbox environment by making a request to the local Friendbot. Specify as the `addr` the `G...` key of your account. ```sh curl "http://localhost:8000/friendbot?addr=G..." ``` -Once you have an account on the network, we'll use the code we wrote in [Write a -Contract] and the resulting `.wasm` file we built in [Build] as our contract to -deploy. Run the following commands to deploy the contract to the network. Use -the `S...` key as the secret key. +Once you have an account on the network, we'll use the code we wrote in [Write a Contract] and the resulting `.wasm` file we built in [Build] as our contract to deploy. Run the following commands to deploy the contract to the network. Use the `S...` key as the secret key. ```sh soroban deploy \ @@ -76,11 +61,7 @@ soroban deploy \ :::tip -It's good practice to avoid entering secret keys on the command line. You can -also specify the secret key by setting the environment variable -`SOROBAN_SECRET_KEY`. The [`soroban-cli`] is still in development and in the -future there will be other secure ways to provide a secret key, such as via -hardware keys. +It's good practice to avoid entering secret keys on the command line. You can also specify the secret key by setting the environment variable `SOROBAN_SECRET_KEY`. The [`soroban-cli`] is still in development and in the future there will be other secure ways to provide a secret key, such as via hardware keys. ::: @@ -90,8 +71,7 @@ A contract ID will be outputted. cd4dae2c409c433b1e1d83994a20214d3e5f60bdd3a817978d8aa7c797864313 ``` -Using the contract ID that was outputted, use the [`soroban-cli`] to invoke the -`hello` function with a single argument `friend`. +Using the contract ID that was outputted, use the [`soroban-cli`] to invoke the `hello` function with a single argument `friend`. ```sh soroban invoke \ @@ -109,10 +89,10 @@ The following output should appear. ["Hello", "friend"] ``` -[Write a Contract]: write-a-contract +[Write a Contract]: hello-world#write-a-contract [Run on a Local Network]: run-on-local-network -[Build]: build +[Build]: hello-world#build [`soroban-cli`]: ../getting-started/setup#install-the-soroban-cli [Stellar Laboratory]: https://laboratory.stellar.org/#account-creator?network=test -[Run on Sandbox]: run-on-sandbox +[Run on Sandbox]: hello-world#run-on-sandbox [Stellar Quickstart]: https://github.com/stellar/quickstart diff --git a/docs/tutorials/deploy-to-futurenet.mdx b/docs/getting-started/deploy-to-futurenet.mdx similarity index 57% rename from docs/tutorials/deploy-to-futurenet.mdx rename to docs/getting-started/deploy-to-futurenet.mdx index e14a4bb62..4dce42719 100644 --- a/docs/tutorials/deploy-to-futurenet.mdx +++ b/docs/getting-started/deploy-to-futurenet.mdx @@ -1,23 +1,19 @@ --- -sidebar_position: 9 -title: Deploy to Futurenet +sidebar_position: 7 +title: 5. Deploy to Futurenet --- -If you have Docker installed, you can run a local node with the [Stellar -Quickstart] Docker image that joins the [Futurenet] network, and then use that -local node to deploy. +If you have Docker installed, you can run a local node with the [Stellar Quickstart] Docker image that joins the [Futurenet] network, and then use that local node to deploy. -[Futurenet]: ../networks/futurenet +[Futurenet]: ../reference/futurenet :::info -It's also possible to run a contract in the local sandbox environment without a -network using just the [`soroban-cli`]. See [Run on Sandbox] for more details. +It's also possible to run a contract in the local sandbox environment without a network using just the [`soroban-cli`]. See [Run on Sandbox] for more details. ::: -To run a local node for the [Futurenet] network with the Stellar Quickstart -Docker image, run the following command. +To run a local node for the [Futurenet] network with the Stellar Quickstart Docker image, run the following command. ```sh docker run --rm -it \ @@ -34,33 +30,23 @@ Once the image is started you can check its status by querying the Horizon API: curl http://localhost:8000 ``` -It takes sometime to join a remote network. Monitor the output of that endpoint -until you see the `core_latest_ledger` become a number above zero. +It takes sometime to join a remote network. Monitor the output of that endpoint until you see the `core_latest_ledger` become a number above zero. -Generate a key by going to the [Stellar Laboratory]. Make note of both the -`G...` and `S...` keys. The `G...` key is the public key and will also be the -account ID. The `S...` key is the secret key and is that you use to control the -account. +Generate a key by going to the [Stellar Laboratory]. Make note of both the `G...` and `S...` keys. The `G...` key is the public key and will also be the account ID. The `S...` key is the secret key and is that you use to control the account. :::tip -It's a good practice to never use the same keys for testing and development that -you use for the public Stellar network. Generate new keys for testing and -development and avoid ever using them for other purposes. +It's a good practice to never use the same keys for testing and development that you use for the public Stellar network. Generate new keys for testing and development and avoid ever using them for other purposes. ::: -Create an account on the [Futurenet] network by making a request to the -Friendbot. Specify as the `addr` the `G...` key of your account. +Create an account on the [Futurenet] network by making a request to the Friendbot. Specify as the `addr` the `G...` key of your account. ```sh curl "https://friendbot-futurenet.stellar.org/?addr=G..." ``` -Once you have an account on the network, we'll use the code we wrote in [Write a -Contract] and the resulting `.wasm` file we built in [Build] as our contract to -deploy. Run the following commands to deploy the contract to the network. Use -the `S...` key as the secret key. +Once you have an account on the network, we'll use the code we wrote in [Write a Contract] and the resulting `.wasm` file we built in [Build] as our contract to deploy. Run the following commands to deploy the contract to the network. Use the `S...` key as the secret key. ```sh soroban deploy \ @@ -72,11 +58,7 @@ soroban deploy \ :::tip -It's good practice to avoid entering secret keys on the command line. You can -also specify the secret key by setting the environment variable -`SOROBAN_SECRET_KEY`. The [`soroban-cli`] is still in development and in the -future there will be other secure ways to provide a secret key, such as via -hardware keys. +It's good practice to avoid entering secret keys on the command line. You can also specify the secret key by setting the environment variable `SOROBAN_SECRET_KEY`. The [`soroban-cli`] is still in development and in the future there will be other secure ways to provide a secret key, such as via hardware keys. ::: @@ -86,8 +68,7 @@ A contract ID will be outputted. cd4dae2c409c433b1e1d83994a20214d3e5f60bdd3a817978d8aa7c797864313 ``` -Using the contract ID that was outputted, use the [`soroban-cli`] to invoke the -`hello` function with a single argument `friend`. +Using the contract ID that was outputted, use the [`soroban-cli`] to invoke the `hello` function with a single argument `friend`. ```sh soroban invoke \ @@ -105,10 +86,10 @@ The following output should appear. ["Hello", "friend"] ``` -[Write a Contract]: write-a-contract +[Write a Contract]: hello-world#write-a-contract [Run on a Local Network]: run-on-local-network -[Build]: build +[Build]: hello-world#build [`soroban-cli`]: ../getting-started/setup#install-the-soroban-cli [Stellar Laboratory]: https://laboratory.stellar.org/#account-creator?network=test -[Run on Sandbox]: run-on-sandbox +[Run on Sandbox]: hello-world#run-on-sandbox [Stellar Quickstart]: https://github.com/stellar/quickstart diff --git a/docs/getting-started/hello-world.mdx b/docs/getting-started/hello-world.mdx new file mode 100644 index 000000000..4720467b1 --- /dev/null +++ b/docs/getting-started/hello-world.mdx @@ -0,0 +1,427 @@ +--- +sidebar_position: 3 +title: 1. Hello World +--- + +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + +Once you've [Setup] your development environment, you're ready to create your first Soroban contract. + +[Setup]: setup.mdx + +## Create New Project + +Create a new Rust library using the `cargo new` command. + +```sh +cargo new --lib [project-name] +``` + +Open the `Cargo.toml`, it should look something like this: + +```toml title="Cargo.toml" +[package] +name = "project-name" +version = "0.1.0" +edition = "2021" +``` + +### Configure the Library Type + +Add the `crate-type` configuration, required for building contracts. + +```toml +[lib] +crate-type = ["cdylib"] +``` + +### Import `soroban-sdk` and Features + +Add the following sections to the `Cargo.toml` that will import the `soroban-sdk`, and configure a set of features explained below. + +:::caution + +The `soroban-sdk` is in early development. Report issues [here](https://github.com/stellar/rs-soroban-sdk/issues/new/choose). + +::: + +```toml +[dependencies] +soroban-sdk = "0.4.2" + +[dev_dependencies] +soroban-sdk = { version = "0.4.2", features = ["testutils"] } + +[features] +testutils = ["soroban-sdk/testutils"] +``` + +The `features` list includes a `testutils` feature, which will cause additional test utilities to be generated for calling the contract in tests. + +:::info + +The `testutils` test utilities are automatically enabled inside [Rust unit tests] inside the same crate as your contract. If you write tests from another crate, you'll need to require the `testutils` feature for those tests and enable the `testutils` feature when running your tests with `cargo test --features testutils` to be able to use those test utilities. + +::: + +### Configure the `release` Profile + +Configuring the `release` profile to optimize the contract build is critical. Soroban contracts have a maximum size of 256KB. Rust programs, even small ones, without these configurations almost always exceed this size. + +Add the following to your `Cargo.toml` and use the `release` profile when building. + +```toml +[profile.release] +opt-level = "z" +overflow-checks = true +debug = 0 +strip = "symbols" +debug-assertions = false +panic = "abort" +codegen-units = 1 +lto = true +``` + +### Configure the `release-with-logs` Profile + +Configuring a `release-with-logs` profile can be useful for if you need to build a `.wasm` that has logs enabled for printing debug logs when using the [`soroban-cli`]. Note that this is not necessary to access debug logs in tests or to use a step-through-debugger. + +Add the following to your `Cargo.toml` and use the `release-with-logs` profile when you need logs. + +```toml +[profile.release-with-logs] +inherits = "release" +debug-assertions = true +``` + +See the [logging example] for more information about how to log. + +[logging example]: ../how-to guides/logging.mdx + +### Wrapping it Up + +The steps below should produce a `Cargo.toml` that looks like so. + +```toml title="Cargo.toml" +[package] +name = "project-name" +version = "0.1.0" +edition = "2022" + +[lib] +crate-type = ["cdylib"] + +[features] +testutils = ["soroban-sdk/testutils"] + +[dependencies] +soroban-sdk = "0.4.2" + +[dev_dependencies] +soroban-sdk = { version = "0.4.2", features = ["testutils"] } + +[profile.release] +opt-level = "z" +overflow-checks = true +debug = 0 +strip = "symbols" +debug-assertions = false +panic = "abort" +codegen-units = 1 +lto = true + +[profile.release-with-logs] +inherits = "release" +debug-assertions = true +``` + +[Rust unit tests]: https://doc.rust-lang.org/rust-by-example/testing/unit_testing.html +[Rust integration tests]: https://doc.rust-lang.org/rust-by-example/testing/integration_testing.html +[`soroban-cli`]: ../getting-started/setup#install-the-soroban-cli + +## Write a Contract + +Once you've created a project, writing a contract involves writing Rust code in the projects `lib.rs` file. + +```rust +#![no_std] +``` + +All contracts should begin with `#![no_std]` to ensure that the Rust standard library is not included in the build. The Rust standard library is large and not well suited to being deployed into small programs like those deployed to blockchains. + +```rust +use soroban_sdk::{contractimpl, symbol, vec, Env, Symbol, Vec}; +``` + +The contract will need to import the types and macros that it needs from the `soroban-sdk` crate. Take a look at [Create a Project] to see how to setup a project. + +Many of the types available in typical Rust programs, such as `std::vec::Vec`, are not available, as there is no allocator and no heap memory in Soroban contracts. The `soroban-sdk` provides a variety of types like `Vec`, `Map`, `Bytes`, `BytesN`, `Symbol`, that all utilize the Soroban environment's memory and native capabilities. + +```rust +pub struct Contract; + +#[contractimpl] +impl Contract { + pub fn hello(env: Env, to: Symbol) -> Vec { + todo!() + } +} +``` + +Contract functions live inside an `impl` for a struct. The `impl` block is annotated with `#[contractimpl]`. Functions that are intended to be called externally should be marked with `pub` visibility. The first argument can be an `Env` argument to get a copy of the Soroban environment, which is necessary for most things. + +Putting those pieces together a simple contract will look like this. + +```rust title="src/lib.rs" +#![no_std] +use soroban_sdk::{contractimpl, symbol, vec, Env, Symbol, Vec}; + +pub struct Contract; + +#[contractimpl] +impl Contract { + pub fn hello(env: Env, to: Symbol) -> Vec { + vec![&env, symbol!("Hello"), to] + } +} +``` + +## Testing + +Writing tests for Soroban contracts involves writing Rust code using the test facilities and toolchain that you'd use for testing any Rust code. + +Given a simple contract like the contract demonstrated in the Write a Contract section, a simple test will look like this. + + + + +```rust +#![no_std] +use soroban_sdk::{contractimpl, symbol, vec, Env, Symbol, Vec}; + +pub struct Contract; + +#[contractimpl] +impl Contract { + pub fn hello(env: Env, to: Symbol) -> Vec { + vec![&env, symbol!("Hello"), to] + } +} + +#[cfg(test)] +mod test; +``` + + + + +```rust +#![cfg(test)] + +use super::{Contract, ContractClient}; +use soroban_sdk::{symbol, vec, Env}; + +#[test] +fn test() { + let env = Env::default(); + let contract_id = env.register_contract(None, Contract); + let client = ContractClient::new(&env, &contract_id); + + let words = client.hello(&symbol!("Dev")); + assert_eq!( + words, + vec![&env, symbol!("Hello"), symbol!("Dev"),] + ); +} +``` + + + + +In any test the first thing that is always required is an `Env`, which is the Soroban environment that the contract will run inside of. + +```rust +let env = Env::default(); +``` + +The contract is registered with the environment using the contract type. Contracts can specify a fixed contract ID as the first argument, or provide `None` and one will be generated. + +```rust +let contract_id = env.register_contract(None, Contract); +``` + +All public functions within an `impl` block that is annotated with the `#[contractimpl]` attribute have a corresponding function generated in a generated client type. The client type will be named the same as the contract type with `Client` appended. For example, in our contract the contract type is `Contract`, and the client is named `ContractClient`. + +```rust +let client = ContractClient::new(&env, &contract_id); +let words = client.hello(&symbol!("Dev")); +``` + +The values returned by functions can be asserted on: + +```rust +assert_eq!( + words, + vec![&env, symbol!("Hello"), symbol!("Dev"),] +); +``` + +### Run the Tests + +Run `cargo test` and watch the contract run. You should see the following output: + +```sh +cargo test +``` + +``` +running 1 test +test test::test ... ok +``` + +Try changing the values in the test to see how it works. + +[Rust unit test]: https://doc.rust-lang.org/rust-by-example/testing/unit_testing.html +[Rust integration test]: https://doc.rust-lang.org/rust-by-example/testing/integration_testing.html + +## Build + +To build a Soroban contract to deploy or run, use the `cargo build` command. + +```sh +cargo build --target wasm32-unknown-unknown --release +``` + +:::tip + +Use the `release` profile outlined in [Configure the Release Profile], otherwise the contract will exceed Soroban's size limits. + +::: + +A `.wasm` file will be outputted in the `target` directory. The `.wasm` file is the built contract. + +``` +target/wasm32-unknown-unknown/release/[project-name].wasm +``` + +The `.wasm` file contains the logic of the contract, as well as the contract's specification that can be imported into other contracts who wish to call it. This is the only artifact needed to deploy the contract, share the interface with others, or integration test against the contract. + +:::tip + +To further optimize builds to be as small as possible, see [Optimizing Builds]. + +::: + +[Configure the Release Profile]: #configure-the-release-profile +[Optimizing Builds]: #optimizing-builds + +## Run on Sandbox + +If you have the [`soroban-cli`] installed, you can run contracts in a local sandbox environment. + +The Soroban sandbox environment is the same Soroban environment that runs on Stellar networks, but it runs without nodes, and without the other features you find on a Stellar network. + +:::info + +It's also possible to run a contract on a fully featured local network. See [Deploy to a Local Network] for more details. + +::: + +Using the code we wrote in [Write a Contract] and the resulting `.wasm` file we built in [Build] run the following command to invoke the `hello` function with a single argument `friend`. + +```sh +soroban invoke \ + --wasm target/wasm32-unknown-unknown/release/[project-name].wasm \ + --id 1 \ + --fn hello \ + --arg friend +``` + +The following output should appear. + +```json +["Hello", "friend"] +``` + +[Write a Contract]: #write-a-contract +[Deploy to a Local Network]: deploy-to-a-local-network +[Build]: #build +[`soroban-cli`]: ../getting-started/setup#install-the-soroban-cli + +## Optimizing Builds + +Building optimized contracts to be as small as possible requires some additional tools, and requires installing the `nightly` Rust toolchain and `wasm-opt`. + +:::tip + +Building optimized contracts is only necessary when deploying to a network with fees or when analyzing and profiling a contract to get it as small as possible. If you're just starting out writing a contract, these steps are not necessary. See [Build] for details on how to build for development. + +::: + +[Build]: #build + +### Install Rust `nightly` + +To install the nightly Rust toolchain use [`rustup`]. + +[`rustup`]: ../getting-started/setup#install-rust + +```sh +rustup install nightly +rustup target add --toolchain nightly wasm32-unknown-unknown +rustup component add --toolchain nightly rust-src +``` + +### Install `wasm-opt` + +To install `wasm-opt`, install [`binaryen`]. Depending on your operating system there may be different ways to install it. + +[`binaryen`]: https://github.com/WebAssembly/binaryen + + + + +```sh +brew install binaryen +``` + + + + +For distributions that use `apt`: + +```sh +sudo apt install binaryen +``` + +For other distributions see: +https://github.com/WebAssembly/binaryen/releases + + + + +For install options see: https://github.com/WebAssembly/binaryen/releases + + + + +### Build with `nightly` and `wasm-opt` + +Build your contract using nightly. The additional options instruct the compiler to remove unnecessary information from the contract. + +```sh +cargo +nightly build \ + --target wasm32-unknown-unknown \ + --release \ + -Z build-std=std,panic_abort \ + -Z build-std-features=panic_immediate_abort +``` + +Use `wasm-opt` to further minimize the size of the `.wasm`. + +```sh +wasm-opt -Oz \ + target/wasm32-unknown-unknown/release/first_project.wasm \ + -o target/wasm32-unknown-unknown/release/first_project_optimized.wasm +``` diff --git a/docs/getting-started/quick-start.mdx b/docs/getting-started/quick-start.mdx deleted file mode 100644 index 2f3fe9cea..000000000 --- a/docs/getting-started/quick-start.mdx +++ /dev/null @@ -1,183 +0,0 @@ ---- -sidebar_position: 3 -title: Quick Start ---- - -Once you've [Setup] your development environment, you're ready to create your -first Soroban contract. - -[Setup]: setup.mdx - -## Create New Project - -Start by creating a new Rust library using the `cargo new` command. - -```sh -cargo new --lib first-project -``` - -Open the `Cargo.toml`, it should look something like this: - -```toml title="Cargo.toml" -[package] -name = "first-project" -version = "0.1.0" -edition = "2021" -``` - -## Add `soroban-sdk` Dependency - -Add the following sections to the `Cargo.toml` that will import the `soroban-sdk`. - -:::info - -Report issues and share feedback about the `soroban-sdk` -[here](https://github.com/stellar/rs-soroban-sdk/issues/new/choose). - -::: - -```toml -[lib] -crate-type = ["cdylib"] - -[features] -testutils = ["soroban-sdk/testutils"] - -[dependencies] -soroban-sdk = "0.4.2" - -[dev_dependencies] -soroban-sdk = { version = "0.4.2", features = ["testutils"] } - -[profile.release] -opt-level = "z" -overflow-checks = true -debug = 0 -strip = "symbols" -debug-assertions = false -panic = "abort" -codegen-units = 1 -lto = true - -[profile.release-with-logs] -inherits = "release" -debug-assertions = true -``` - -The `features` list includes a `testutils` feature, which will cause additional -test utilities to be generated for calling the contract in tests. - -:::info - -The `testutils` test utilities are automatically enabled inside [Rust unit -tests] inside the same crate as your contract. If you write [Rust integration -tests], or write tests from another crate, you'll need to add `#[cfg(feature = -"testutils")]` to those tests and enable the `testutils` feature when running -your tests with `cargo test --features testutils` to be able to use those test -utilities. - -::: - -The config for the `release` profile configures the Rust toolchain to produce -smaller contracts when built with the `--release` or `--profile release` option. - -The config for the `release-with-logs` profile enables contract logs when -building with `--profile release-with-logs` option. See the [logging example] -for more details. - -[logging example]: ../examples/logging - -## Write the Code - -Open the `src/lib.rs` file, and copy-paste the following code. - -```rust -#![no_std] -use soroban_sdk::{contractimpl, symbol, vec, Env, Symbol, Vec}; - -pub struct Contract; - -#[contractimpl] -impl Contract { - pub fn hello(env: Env, to: Symbol) -> Vec { - vec![&env, symbol!("Hello"), to] - } -} - -#[cfg(test)] -mod test { - use super::{Contract, ContractClient}; - use soroban_sdk::{symbol, vec, Env}; - - #[test] - fn test() { - let env = Env::default(); - let contract_id = env.register_contract(None, Contract); - let client = ContractClient::new(&env, &contract_id); - - let words = client.hello(&symbol!("Dev")); - assert_eq!( - words, - vec![&env, symbol!("Hello"), symbol!("Dev"),] - ); - } -} -``` - -## Run the Tests - -Run `cargo test` and watch the contract run. You should see the following output: - -```sh -cargo test -``` - -``` -running 1 test -test test::test ... ok -``` - -Try changing the values in the test to see how it works. - -## Build the Contract - -To build the contract into a `.wasm` file, use the `cargo build` command. - -```sh -cargo build --target wasm32-unknown-unknown --release -``` - -A `.wasm` file should be outputted in the `target` directory: - -``` -target/wasm32-unknown-unknown/release/first_project.wasm -``` - -:::info - -Hyphens in Rust crate names are replaced by underscores in code and generated file names, so `first-project` is outputted as `first_project.wasm`. - -::: - -## Run the Contract - -If you have [`soroban-cli`] installed, you can invoke contract functions in the -contract. - -```sh -soroban invoke \ - --wasm target/wasm32-unknown-unknown/release/first_project.wasm \ - --id 1 \ - --fn hello \ - --arg friend -``` - -You should see the following output: - -```json -["Hello", "friend"] -``` - -[`soroban-cli`]: setup#install-the-soroban-cli -[Rust unit tests]: https://doc.rust-lang.org/rust-by-example/testing/unit_testing.html -[Rust integration tests]: https://doc.rust-lang.org/rust-by-example/testing/integration_testing.html diff --git a/docs/getting-started/storing-data.mdx b/docs/getting-started/storing-data.mdx new file mode 100644 index 000000000..6a38e9365 --- /dev/null +++ b/docs/getting-started/storing-data.mdx @@ -0,0 +1,207 @@ +--- +sidebar_position: 4 +title: 2. Storing Data +--- + +The [increment example] demonstrates how to write a simple contract that stores data, with a single function that increments an internal counter and returns the value. + +[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)][oigp] +[oigp]: https://gitpod.io/#https://github.com/stellar/soroban-examples/tree/v0.4.2 + +[increment example]: https://github.com/stellar/soroban-examples/tree/v0.4.2/increment + +## Run the Example + +First go through the [Setup] process to get your development environment configured, then clone the `v0.4.2` tag of `soroban-examples` repository: + +[Setup]: setup.mdx + +``` +git clone -b v0.4.2 https://github.com/stellar/soroban-examples +``` + +Or, skip the development environment setup and open this example in [Gitpod][oigp]. + +To run the tests for the example, navigate to the `increment` directory, and use `cargo test`. + +``` +cd increment +cargo test -- --nocapture +``` + +You should see the output: + +``` +running 1 test +count: U32(0) +count: U32(1) +count: U32(2) +test test::test ... ok +``` + +## Code + +```rust title="increment/src/lib.rs" +const COUNTER: Symbol = symbol!("COUNTER"); + +pub struct IncrementContract; + +#[contractimpl] +impl IncrementContract { + pub fn increment(env: Env) -> u32 { + let mut count: u32 = env + .storage() + .get(COUNTER) + .unwrap_or(Ok(0)) // If no value set, assume 0. + .unwrap(); // Panic if the value of COUNTER is not u32. + log!(&env, "count: {}", count); + count += 1; + env.storage().set(COUNTER, count); + count + } +} +``` + +Ref: https://github.com/stellar/soroban-examples/tree/v0.4.2/increment + +## How it Works + +Open the `increment/src/lib.rs` file to follow along. + +### Contract Data Keys + +Contract data is associated with a key. The key is the value that can be used at a later time to lookup the value. + +`Symbol`s are a space and execution efficient value to use as static keys or names of things. They can also be used as short strings. When produced using `symbol!(...)` they are computed at compile time and stored in code as a 64-bit value. Their maximum character length is 10. + +```rust +const COUNTER: Symbol = symbol!("COUNTER"); +``` + +### Contract Data Access + +The `Env` `data()` function is used to retrieve access and update a counter. The executing contract is the only contract that can query or modify contract data that it has stored. The data stored is viewable on ledger anywhere the ledger is viewable, but contracts executing within the Soroban environment are restricted to their own data. + +The `get()` function gets the current value associated with the counter key. + +```rust +let mut count: u32 = env + .storage() + .get(COUNTER) + .unwrap_or(Ok(0)) // If no value set, assume 0. + .unwrap(); // Panic if the value of COUNTER is not u32. +``` + +If no value is currently stored, the value given to `unwrap_or(...)` is returned instead. + +Values stored as contract data and retrieved are transmitted from the environment and expanded into the type specified. In this case a `u32`. If the value can be expanded the type returned will be an `Ok(u32)`, otherwise the type returned will be an `Err(_)`. The final `unwrap()` in the above code snippet is assuming the value will always be a `u32`. If a developer caused it to be some other type a panic would occur at the unwrap. + +The `set()` function stores the new count value against the key, replacing the existing value. + +```rust +env.storage().set(COUNTER, count); +``` + +## Tests + +Open the `increment/src/test.rs` file to follow along. + +```rust title="increment/src/test.rs" +#[test] +fn test() { + let env = Env::default(); + let contract_id = env.register_contract(None, IncrementContract); + let client = IncrementContractClient::new(&env, &contract_id); + + assert_eq!(client.increment(), 1); + assert_eq!(client.increment(), 2); + assert_eq!(client.increment(), 3); +} +``` + +In any test the first thing that is always required is an `Env`, which is the Soroban environment that the contract will run in. + +```rust +let env = Env::default(); +``` + +The contract is registered with the environment using the contract type. + +```rust +let contract_id = env.register_contract(None, IncrementContract); +``` + +All public functions within an `impl` block that is annotated with the `#[contractimpl]` attribute have a corresponding function generated in a generated client type. The client type will be named the same as the contract type with `Client` appended. For example, in our contract the contract type is `IncrementContract`, and the client is named `IncrementContractClient`. + +```rust +let client = IncrementContractClient::new(&env, &contract_id); +``` + +The values returned by functions can be asserted on: + +```rust +assert_eq!(client.increment(), 1); +``` + +## Build the Contract + +To build the contract, use the `cargo build` command. + +```sh +cargo build --target wasm32-unknown-unknown --release +``` + +A `.wasm` file should be outputted in the `../target` directory: + +``` +../target/wasm32-unknown-unknown/release/soroban_increment_contract.wasm +``` + +## Run the Contract + +If you have [`soroban-cli`] installed, you can invoke contract functions in the WASM using it. + +```sh +soroban invoke \ + --wasm ../target/wasm32-unknown-unknown/release/soroban_increment_contract.wasm \ + --id 1 \ + --fn increment +``` + +The following output should occur using the code above. + +``` +1 +``` + +Rerun the invoke with the `--footprint` option to view the [footprint] of the invocation, which is the ledger entries that the contract will have read or written to. + +```sh +soroban invoke \ + --wasm ../target/wasm32-unknown-unknown/release/soroban_increment_contract.wasm \ + --id 1 \ + --fn increment \ + --footprint +``` + +``` +Footprint: {"readOnly":[{"contractData":{"contractId":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],"key":{"static":"ledgerKeyContractCode"}}}],"readWrite":[{"contractData":{"contractId":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],"key":{"symbol":[67,79,85,78,84,69,82]}}}]} +``` + +:::info + +Soroban is a pre-release and at this time outputs footprints in an unstable JSON format. + +::: + +[footprint]: ../learn/persisting-data.mdx#footprints-and-parallel-contention + +Run it a few more times to watch the count change. + +Use the `soroban` to inspect what the counter is after a few runs. + +```sh +soroban read --id 1 --key COUNTER +``` + +[`soroban-cli`]: ../getting-started/setup#install-the-soroban-cli diff --git a/docs/tutorials/_category_.json b/docs/tutorials/_category_.json deleted file mode 100644 index 74f2f1406..000000000 --- a/docs/tutorials/_category_.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "position": 30, - "label": "Tutorials", - "link": { - "type": "generated-index" - } -} diff --git a/docs/tutorials/build-optimized.mdx b/docs/tutorials/build-optimized.mdx deleted file mode 100644 index efb72fe33..000000000 --- a/docs/tutorials/build-optimized.mdx +++ /dev/null @@ -1,89 +0,0 @@ ---- -sidebar_position: 11 -title: Optimizing Builds ---- - -import Tabs from "@theme/Tabs"; -import TabItem from "@theme/TabItem"; - -Building optimized contracts to be as small as possible requires some additional -tools, and requires installing the `nightly` Rust toolchain and `wasm-opt`. - -:::tip - -Building optimized contracts is only necessary when deploying to a network with -fees or when analyzing and profiling a contract to get it as small as possible. -If you're just starting out writing a contract, these steps are not necessary. -See [Build] for details on how to build for development. - -::: - -[Build]: build.mdx - -### Install Rust `nightly` - -To install the nightly Rust toolchain use [`rustup`]. - -[`rustup`]: ../getting-started/setup#install-rust - -```sh -rustup install nightly -rustup target add --toolchain nightly wasm32-unknown-unknown -rustup component add --toolchain nightly rust-src -``` - -### Install `wasm-opt` - -To install `wasm-opt`, install [`binaryen`]. Depending on your operating system -there may be different ways to install it. - -[`binaryen`]: https://github.com/WebAssembly/binaryen - - - - -```sh -brew install binaryen -``` - - - - -For distributions that use `apt`: - -```sh -sudo apt install binaryen -``` - -For other distributions see: -https://github.com/WebAssembly/binaryen/releases - - - - -For install options see: -https://github.com/WebAssembly/binaryen/releases - - - - -### Build with `nightly` and `wasm-opt` - -Build your contract using nightly. The additional options instruct the compiler -to remove unnecessary information from the contract. - -```sh -cargo +nightly build \ - --target wasm32-unknown-unknown \ - --release \ - -Z build-std=std,panic_abort \ - -Z build-std-features=panic_immediate_abort -``` - -Use `wasm-opt` to further minimize the size of the `.wasm`. - -```sh -wasm-opt -Oz \ - target/wasm32-unknown-unknown/release/first_project.wasm \ - -o target/wasm32-unknown-unknown/release/first_project_optimized.wasm -``` diff --git a/docs/tutorials/build.mdx b/docs/tutorials/build.mdx deleted file mode 100644 index b351bf251..000000000 --- a/docs/tutorials/build.mdx +++ /dev/null @@ -1,38 +0,0 @@ ---- -sidebar_position: 6 -title: Build ---- - -To build a Soroban contract to deploy or run, use the `cargo build` command. - -```sh -cargo build --target wasm32-unknown-unknown --release -``` - -:::tip - -Use the `release` profile outlined in [Configure the Release Profile], otherwise -the contract will exceed Soroban's size limits. - -::: - -A `.wasm` file will be outputted in the `target` directory. The `.wasm` file is -the built contract. - -``` -target/wasm32-unknown-unknown/release/[project-name].wasm -``` - -The `.wasm` file contains the logic of the contract, as well as the contract's -specification that can be imported into other contracts who wish to call it. -This is the only artifact needed to deploy the contract, share the interface -with others, or integration test against the contract. - -:::tip - -To further optimize builds to be as small as possible, see [Optimizing Builds]. - -::: - -[Configure the Release Profile]: create-a-project#configure-the-release-profile -[Optimizing Builds]: build-optimized diff --git a/docs/tutorials/create-a-project.mdx b/docs/tutorials/create-a-project.mdx deleted file mode 100644 index 2ba56f608..000000000 --- a/docs/tutorials/create-a-project.mdx +++ /dev/null @@ -1,151 +0,0 @@ ---- -sidebar_position: 1 -title: Create a Project ---- - -Once you've [Setup] your development environment, you're ready to create Soroban -contracts. Creating projects is done using the Rust tool, `cargo`. - -[Setup]: ../getting-started/setup.mdx - -Create a new Rust library using the `cargo new` command. - -```sh -cargo new --lib [project-name] -``` - -Open the `Cargo.toml`, it should look something like this: - -```toml title="Cargo.toml" -[package] -name = "project-name" -version = "0.1.0" -edition = "2021" -``` - -## Configure the Library Type - -Add the `crate-type` configuration, required for building contracts. - -```toml -[lib] -crate-type = ["cdylib"] -``` - -## Import `soroban-sdk` and Features - -Add the following sections to the `Cargo.toml` that will import the -`soroban-sdk`, and configure a set of features explained below. - -:::caution - -The `soroban-sdk` is in early development. Report issues -[here](https://github.com/stellar/rs-soroban-sdk/issues/new/choose). - -::: - -```toml -[dependencies] -soroban-sdk = "0.4.2" - -[dev_dependencies] -soroban-sdk = { version = "0.4.2", features = ["testutils"] } - -[features] -testutils = ["soroban-sdk/testutils"] -``` - -The `features` list includes a `testutils` feature, which will cause additional -test utilities to be generated for calling the contract in tests. - -:::info - -The `testutils` test utilities are automatically enabled inside [Rust unit -tests] inside the same crate as your contract. If you write tests from another -crate, you'll need to require the `testutils` feature for those tests and enable -the `testutils` feature when running your tests with `cargo test ---features testutils` to be able to use those test utilities. - -::: - -## Configure the `release` Profile - -Configuring the `release` profile to optimize the contract build is critical. -Soroban contracts have a maximum size of 256KB. Rust programs, even small ones, -without these configurations almost always exceed this size. - -Add the following to your `Cargo.toml` and use the `release` profile when -building. - -```toml -[profile.release] -opt-level = "z" -overflow-checks = true -debug = 0 -strip = "symbols" -debug-assertions = false -panic = "abort" -codegen-units = 1 -lto = true -``` - -## Configure the `release-with-logs` Profile - -Configuring a `release-with-logs` profile can be useful for if you need to build -a `.wasm` that has logs enabled for printing debug logs when using the -[`soroban-cli`]. Note that this is not necessary to access debug logs in tests -or to use a step-through-debugger. - -Add the following to your `Cargo.toml` and use the `release-with-logs` profile -when you need logs. - -```toml -[profile.release-with-logs] -inherits = "release" -debug-assertions = true -``` - -See the [logging example] for more information about how to log. - -[logging example]: ../examples/logging.mdx - -## Wrapping it Up - -The steps below should produce a `Cargo.toml` that looks like so. - -```toml title="Cargo.toml" -[package] -name = "project-name" -version = "0.1.0" -edition = "2022" - -[lib] -crate-type = ["cdylib"] - -[features] -testutils = ["soroban-sdk/testutils"] - -[dependencies] -soroban-sdk = "0.4.2" - -[dev_dependencies] -soroban-sdk = { version = "0.4.2", features = ["testutils"] } - -[profile.release] -opt-level = "z" -overflow-checks = true -debug = 0 -strip = "symbols" -debug-assertions = false -panic = "abort" -codegen-units = 1 -lto = true - -[profile.release-with-logs] -inherits = "release" -debug-assertions = true -``` - -[Rust unit tests]: https://doc.rust-lang.org/rust-by-example/testing/unit_testing.html -[Rust integration tests]: https://doc.rust-lang.org/rust-by-example/testing/integration_testing.html -[`soroban-cli`]: ../getting-started/setup#install-the-soroban-cli diff --git a/docs/tutorials/invoking-contracts-with-transactions.mdx b/docs/tutorials/invoking-contracts-with-transactions.mdx deleted file mode 100644 index 2ac446627..000000000 --- a/docs/tutorials/invoking-contracts-with-transactions.mdx +++ /dev/null @@ -1,119 +0,0 @@ ---- -sidebar_position: 11 -title: Invoking and Creating Contracts with Stellar Transactions ---- - -Stellar supports invoking and deploying contracts with a new Operation named `InvokeHostFunctionOp`. The [`soroban-cli`] abstracts these details away from the -user, but SDKs do not yet and if you're building a dapp you'll probably find yourself building the XDR transaction to submit to the network. - -The `InvokeHostFunctionOp` can be used to perform the following Soroban -operations: - -- Invoke contract functions. -- Install WASM of the new contracts. -- Deploy new contracts using the installed WASM or built-in implementations ( - this currently includes only the [token contract](../built-in-contracts/stellar-asset-contract.mdx)). - -[`soroban-cli`]: ../getting-started/setup#install-the-soroban-cli - -## InvokeHostFunctionOp - -The XDR of `HostFunction` and `InvokeHostFunctionOp` below can be found -[here](https://github.com/stellar/stellar-xdr/blob/026c9cd074bdb28ddde8ee52f2a4502d9e518a09/Stellar-transaction.x#L523-L539) - -```c++ -union HostFunction switch (HostFunctionType type) -{ -case HOST_FUNCTION_TYPE_INVOKE_CONTRACT: - SCVec invokeArgs; -case HOST_FUNCTION_TYPE_CREATE_CONTRACT: - CreateContractArgs createContractArgs; -case HOST_FUNCTION_TYPE_INSTALL_CONTRACT_CODE: - InstallContractCodeArgs installContractCodeArgs; -}; - -struct InvokeHostFunctionOp -{ - // The host function to invoke - HostFunction function; - // The footprint for this invocation - LedgerFootprint footprint; -}; -``` - -### Function - -The `function` in `InvokeHostFunctionOp` will be executed by the Soroban host -environment. The function arguments are passed as function-dependent XDR. The -options are: - -1. `HOST_FUNCTION_TYPE_INVOKE_CONTRACT` - - This will call the `call_n` host function, invoking a contract function. - - `invokeArgs` is expected to contain the contract id, contract function - name, and the parameters to the contract function being invoked. -2. `HOST_FUNCTION_TYPE_INSTALL_CONTRACT_CODE` - - This will install the contract WASM using the provided `code` blob: - ```c++ - struct InstallContractCodeArgs - { - opaque code; - }; - ``` -3. `HOST_FUNCTION_TYPE_CREATE_CONTRACT` - - This will create a contract instance in the network using the specified - `source` and build a 32-byte contract identifer based on `contractID` value. - ```c++ - struct CreateContractArgs - { - ContractID contractID; - SCContractCode source; - }; - ``` - - `source` can be either a reference to the hash of the installed WASM (to - be more precise, a SHA-256 hash of the `InstallContractCodeArgs` from the operation above) or just specify that a built-in contract has to be used: - ```c++ - union SCContractCode switch (SCContractCodeType type) - { - case SCCONTRACT_CODE_WASM_REF: - Hash wasm_id; - case SCCONTRACT_CODE_TOKEN: - void; - }; - ``` - -- `contractID` is defined as following: - ```c++ - union ContractID switch (ContractIDType type) - { - case CONTRACT_ID_FROM_SOURCE_ACCOUNT: - uint256 salt; - case CONTRACT_ID_FROM_ED25519_PUBLIC_KEY: - struct - { - uint256 key; - Signature signature; - uint256 salt; - } fromEd25519PublicKey; - case CONTRACT_ID_FROM_ASSET: - Asset asset; - }; - ``` -- The parameters of this value define which the hash preimage that is then hashed - with SHA-256 to get the ID of the created contract. -- `CONTRACT_ID_FROM_SOURCE_ACCOUNT` specifies that the contract ID will be created - using the Stellar source account and the provided salt. The contract ID - preimage used is [`ENVELOPE_TYPE_CONTRACT_ID_FROM_SOURCE_ACCOUNT`](https://github.com/stellar/stellar-xdr/blob/026c9cd074bdb28ddde8ee52f2a4502d9e518a09/Stellar-transaction.x#L643-L649). -- `CONTRACT_ID_FROM_ASSET` specifies that the contract will be created using - the Stellar asset. This is only suported when - `source == SCCONTRACT_CODE_TOKEN`. Note, that the asset doesn't need to exist - when this is applied, however the issuer of the asset will be the initial - token administrator. The contract ID preimage used is [`ENVELOPE_TYPE_CONTRACT_ID_FROM_ASSET`](https://github.com/stellar/stellar-xdr/blob/026c9cd074bdb28ddde8ee52f2a4502d9e518a09/Stellar-transaction.x#L637-L642). -- `CONTRACT_ID_FROM_ED25519_PUBLIC_KEY` specified that the contract will be - created using a public ED25519 key. Since this operation is not tied to any - on-chain entity, this also has to contain an ED25519 signature of SHA256 hash of [`ENVELOPE_TYPE_CREATE_CONTRACT_ARGS`](https://github.com/stellar/stellar-xdr/blob/026c9cd074bdb28ddde8ee52f2a4502d9e518a09/Stellar-transaction.x#L650-L656) XDR - preimage. The contract ID preimage used is [`ENVELOPE_TYPE_CONTRACT_ID_FROM_ED25519`](https://github.com/stellar/stellar-xdr/blob/026c9cd074bdb28ddde8ee52f2a4502d9e518a09/Stellar-transaction.x#L623-L629). - -### Footprint - -The footprint must contain the `LedgerKeys` that will be read and/or written. More -information about the footprint can be found in the advanced section of [interacting with contracts](../learn/interacting-with-contracts#storage-footprint-and-preflight). diff --git a/docs/tutorials/run-on-sandbox.mdx b/docs/tutorials/run-on-sandbox.mdx deleted file mode 100644 index 2cc3237cf..000000000 --- a/docs/tutorials/run-on-sandbox.mdx +++ /dev/null @@ -1,41 +0,0 @@ ---- -sidebar_position: 7 -title: Run on Sandbox ---- - -If you have the [`soroban-cli`] installed, you can run contracts in a local -sandbox environment. - -The Soroban sandbox environment is the same Soroban environment that runs on -Stellar networks, but it runs without nodes, and without the other features you -find on a Stellar network. - -:::info - -It's also possible to run a contract on a fully featured local network. See -[Deploy to a Local Network] for more details. - -::: - -Using the code we wrote in [Write a Contract] and the resulting `.wasm` file -we built in [Build] run the following command to invoke the `hello` -function with a single argument `friend`. - -```sh -soroban invoke \ - --wasm target/wasm32-unknown-unknown/release/[project-name].wasm \ - --id 1 \ - --fn hello \ - --arg friend -``` - -The following output should appear. - -```json -["Hello", "friend"] -``` - -[Write a Contract]: write-a-contract -[Deploy to a Local Network]: deploy-to-local-network -[Build]: build -[`soroban-cli`]: ../getting-started/setup#install-the-soroban-cli diff --git a/docs/tutorials/testing.mdx b/docs/tutorials/testing.mdx deleted file mode 100644 index 248a458a5..000000000 --- a/docs/tutorials/testing.mdx +++ /dev/null @@ -1,112 +0,0 @@ ---- -sidebar_position: 5 -title: Testing ---- - -import Tabs from "@theme/Tabs"; -import TabItem from "@theme/TabItem"; - -Writing tests for Soroban contracts involves writing Rust code using the test -facilities and toolchain that you'd use for testing any Rust code. - -Given a simple contract like the contract demonstrated in [Write a -Contract](write-a-contract.mdx), a simple test will look like this. - - - - -```rust -#![no_std] -use soroban_sdk::{contractimpl, symbol, vec, Env, Symbol, Vec}; - -pub struct Contract; - -#[contractimpl] -impl Contract { - pub fn hello(env: Env, to: Symbol) -> Vec { - vec![&env, symbol!("Hello"), to] - } -} - -#[cfg(test)] -mod test; -``` - - - - -```rust -#![cfg(test)] - -use super::{Contract, ContractClient}; -use soroban_sdk::{symbol, vec, Env}; - -#[test] -fn test() { - let env = Env::default(); - let contract_id = env.register_contract(None, Contract); - let client = ContractClient::new(&env, &contract_id); - - let words = client.hello(&symbol!("Dev")); - assert_eq!( - words, - vec![&env, symbol!("Hello"), symbol!("Dev"),] - ); -} -``` - - - - -In any test the first thing that is always required is an `Env`, which is the -Soroban environment that the contract will run inside of. - -```rust -let env = Env::default(); -``` - -The contract is registered with the environment using the contract type. -Contracts can specify a fixed contract ID as the first argument, or provide -`None` and one will be generated. - -```rust -let contract_id = env.register_contract(None, Contract); -``` - -All public functions within an `impl` block that is annotated with the -`#[contractimpl]` attribute have a corresponding function generated in a -generated client type. The client type will be named the same as the contract -type with `Client` appended. For example, in our contract the contract type is -`Contract`, and the client is named `ContractClient`. - -```rust -let client = ContractClient::new(&env, &contract_id); -let words = client.hello(&symbol!("Dev")); -``` - -The values returned by functions can be asserted on: - -```rust -assert_eq!( - words, - vec![&env, symbol!("Hello"), symbol!("Dev"),] -); -``` - -## Run the Tests - -Run `cargo test` and watch the contract run. You should see the following output: - -```sh -cargo test -``` - -``` -running 1 test -test test::test ... ok -``` - -Try changing the values in the test to see how it works. - -[Rust unit test]: https://doc.rust-lang.org/rust-by-example/testing/unit_testing.html -[Rust integration test]: https://doc.rust-lang.org/rust-by-example/testing/integration_testing.html diff --git a/docs/tutorials/write-a-contract.mdx b/docs/tutorials/write-a-contract.mdx deleted file mode 100644 index 2d377cd4c..000000000 --- a/docs/tutorials/write-a-contract.mdx +++ /dev/null @@ -1,65 +0,0 @@ ---- -sidebar_position: 4 -title: Write a Contract ---- - -Once you have a project setup, like how we setup a project in [Create a Project], writing a contract involves writing Rust code in -the projects `lib.rs` file. - -```rust -#![no_std] -``` - -All contracts should begin with `#![no_std]` to ensure that the Rust standard -library is not included in the build. The Rust standard library is large and not -well suited to being deployed into small programs like those deployed to -blockchains. - -```rust -use soroban_sdk::{contractimpl, symbol, vec, Env, Symbol, Vec}; -``` - -The contract will need to import the types and macros that it needs from the -`soroban-sdk` crate. Take a look at [Create a Project] to see -how to setup a project. - -Many of the types available in typical Rust programs, such as `std::vec::Vec`, -are not available, as there is no allocator and no heap memory in Soroban -contracts. The `soroban-sdk` provides a variety of types like `Vec`, `Map`, -`Bytes`, `BytesN`, `Symbol`, that all utilize the Soroban environment's memory -and native capabilities. - -```rust -pub struct Contract; - -#[contractimpl] -impl Contract { - pub fn hello(env: Env, to: Symbol) -> Vec { - todo!() - } -} -``` - -Contract functions live inside an `impl` for a struct. The `impl` block is -annotated with `#[contractimpl]`. Functions that are intended to be called -externally should be marked with `pub` visibility. The first argument can be -an `Env` argument to get a copy of the Soroban environment, which is necessary -for most things. - -Putting those pieces together a simple contract will look like this. - -```rust title="src/lib.rs" -#![no_std] -use soroban_sdk::{contractimpl, symbol, vec, Env, Symbol, Vec}; - -pub struct Contract; - -#[contractimpl] -impl Contract { - pub fn hello(env: Env, to: Symbol) -> Vec { - vec![&env, symbol!("Hello"), to] - } -} -``` - -[Create a Project]: create-a-project.mdx