diff --git a/docs/getting-started/build-a-wasm-file.mdx b/docs/getting-started/build-a-wasm-file.mdx new file mode 100644 index 000000000..2855ef6a7 --- /dev/null +++ b/docs/getting-started/build-a-wasm-file.mdx @@ -0,0 +1,16 @@ +--- +sidebar_position: 6 +title: Build a WASM File +--- + +To build a Soroban 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/[project-name].wasm +``` diff --git a/docs/getting-started/building-optimized-wasm.mdx b/docs/getting-started/build-an-optimized-wasm-file.mdx similarity index 96% rename from docs/getting-started/building-optimized-wasm.mdx rename to docs/getting-started/build-an-optimized-wasm-file.mdx index 926702e7e..67c0d8469 100644 --- a/docs/getting-started/building-optimized-wasm.mdx +++ b/docs/getting-started/build-an-optimized-wasm-file.mdx @@ -1,6 +1,6 @@ --- -sidebar_position: 4 -title: Building Optimized WASM +sidebar_position: 8 +title: Build an Optimized WASM File --- import Tabs from '@theme/Tabs'; diff --git a/docs/getting-started/install-soroban-cli.mdx b/docs/getting-started/install-soroban-cli.mdx deleted file mode 100644 index 8c581f5f4..000000000 --- a/docs/getting-started/install-soroban-cli.mdx +++ /dev/null @@ -1,42 +0,0 @@ ---- -sidebar_position: 2 -title: Install Soroban CLI ---- - -The Soroban CLI can execute WASM contracts in the same environment the contract -will execute on network, however in a local sandbox. - -Install the Soroban CLI using `cargo install`. - -```sh -cargo install --locked --git http://github.com/stellar/soroban-cli soroban-cli -``` - -:::caution -The `soroban-cli` is still in early development. Please report issues -[here](https://github.com/stellar/soroban-cli). -::: - -## Usage - -Run the `soroban-cli` command and you should see output like below. - -```sh -soroban-cli -``` - -``` -soroban-cli 0.0.1 - -USAGE: - soroban-cli - -OPTIONS: - -h, --help Print help information - -SUBCOMMANDS: - invoke Invoke a contract function in a WASM file - inspect Inspect a WASM file listing contract functions, meta, etc - deploy Deploy a WASM file as a contract - version Print version information -``` diff --git a/docs/getting-started/run-a-wasm-file.mdx b/docs/getting-started/run-a-wasm-file.mdx new file mode 100644 index 000000000..b3438ce59 --- /dev/null +++ b/docs/getting-started/run-a-wasm-file.mdx @@ -0,0 +1,28 @@ +--- +sidebar_position: 7 +title: Run a WASM File +--- + +If you have [`soroban-cli`] installed, you can invoke contract functions in a +WASM file. + +Using the code we wrote in [Write a Contract](write-a-contract.mdx) and the the +resulting `.wasm` file we built in [Build a WASM File](build-a-wasm-file.mdx) +run the following command to invoke the `hello` function with a single argument +`"friend"`. + +```sh +soroban-cli invoke \ + --file target/wasm32-unknown-unknown/release/first-project.wasm \ + --contract-id 1 + --fn hello + --arg friend +``` + +The following output should appear. + +``` +["Hello","friend"] +``` + +[`soroban-cli`]: install-soroban-cli.mdx diff --git a/docs/getting-started/setup.mdx b/docs/getting-started/setup.mdx index b64200e46..ef490acce 100644 --- a/docs/getting-started/setup.mdx +++ b/docs/getting-started/setup.mdx @@ -32,5 +32,46 @@ Many editors have support for Rust. Visit the following link to find out how to configure your editor: https://www.rust-lang.org/tools +## Install Soroban CLI + +The Soroban CLI can execute WASM contracts in the same environment the contract +will execute on network, however in a local sandbox. + +Install the Soroban CLI using `cargo install`. + +```sh +cargo install --locked --git http://github.com/stellar/soroban-cli soroban-cli +``` + +:::caution +The `soroban-cli` is still in early development. Please report issues +[here](https://github.com/stellar/soroban-cli). +::: + +### Usage + +Run the `soroban-cli` command and you should see output like below. + +```sh +soroban-cli +``` + +``` +soroban-cli 0.0.1 + +USAGE: + soroban-cli + +OPTIONS: + -h, --help Print help information + +SUBCOMMANDS: + invoke Invoke a contract function in a WASM file + inspect Inspect a WASM file listing contract functions, meta, etc + deploy Deploy a WASM file as a contract + version Print version information +``` + + [Rust]: https://www.rust-lang.org/ [Soroban CLI]: install-soroban-cli.mdx diff --git a/docs/getting-started/testing.mdx b/docs/getting-started/testing.mdx new file mode 100644 index 000000000..47867975a --- /dev/null +++ b/docs/getting-started/testing.mdx @@ -0,0 +1,97 @@ +--- +sidebar_position: 5 +title: Testing +--- + +Writing tests for Soroban contracts involves writing Rust code using the Rust +test facilitiaties 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). + +```rust +#![no_std] +use soroban_sdk::{contractimpl, vec, Env, Symbol, Vec}; + +pub struct Contract; + +#[contractimpl(export_if = "export")] +impl Contract { + pub fn hello(env: Env, to: Symbol) -> Vec { + const GREETING: Symbol = Symbol::from_str("Hello"); + vec![&env, GREETING, to] + } +} +``` + +A simple test will look like this. + +``` + +#[cfg(test)] +mod test { + use super::{Contract, hello}; + use soroban_sdk::{vec, Env, FixedBinary}; + + #[test] + fn test() { + let env = Env::default(); + let contract_id = FixedBinary::from_array(&env, [0; 32]); + env.register_contract(&contract_id, Contract); + + let words = hello::invoke(&env, &contract_id, &Symbol::from_str("Dev")); + assert_eq!( + words, + vec![&env, Symbol::from_str("Hello"), Symbol::from_str("Dev"),] + ); + } +} +``` + +In any test the first thing that is always required is an `Env`, which is the +Host environment that the contract will run it. + +```rust +let env = Env::default(); +``` + +Contracts must be registered with the environment with a contract ID, which is a +32-byte value. In many cases it is sufficient to use a simple zero ID, however +if the test will deploy the contract multiple times, or deploy multiple +contracts, each should use their own IDs. + +```rust +let contract_id = FixedBinary::from_array(&env, [0; 32]); +env.register_contract(&contract_id, HelloContract); +``` + +All public functions within an `impl` block that is annotated with the +`#[contractimpl]` attribute have an `invoke` function generated, that can be +used to invoke the contract function within the environment. + +```rust +let words = hello::invoke(&env, &contract_id, &Symbol::from_str("SourBun")); +``` + +The values returned by functions can be asserted on: +```rust +assert_eq!( + words, + vec![&env, Symbol::from_str("Hello"), Symbol::from_str("SourBun"),] +); +``` + +## 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. diff --git a/docs/getting-started/write-a-contract.mdx b/docs/getting-started/write-a-contract.mdx new file mode 100644 index 000000000..03ed2061f --- /dev/null +++ b/docs/getting-started/write-a-contract.mdx @@ -0,0 +1,64 @@ +--- +sidebar_position: 4 +title: Write a Contract +--- + +Once you have a project setup, like how we setup a project in [First +Project](first-project.mdx), 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, 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 [First Project](first-project.mdx) 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 their is no allocator and no heap memory in Soroban +contracts. The `soroban_sdk` provides a variety of types like `Vec`, `Map`, and +`BigInt`, `Binary`, `FixedBinary`, that all utilize the Host environments memory +and native capabilities. + +```rust +pub struct Contract; + +#[contractimpl(export_if = "export")] +impl Contract { + pub fn hello(env: Env, to: Symbol) -> Vec { + todo!() + } +} +``` + +Contract functions live inside a `impl` for a struct. The `impl` block is +annotated with `#[contractimpl]`, and the functions that are intended to be +called are assigned `pub` visibility and have an `Env` argument as their first +argument. + +Putting those pieces together a simple contract will look like this. + +```rust +#![no_std] +use soroban_sdk::{contractimpl, vec, Env, Symbol, Vec}; + +pub struct Contract; + +#[contractimpl(export_if = "export")] +impl Contract { + pub fn hello(env: Env, to: Symbol) -> Vec { + const GREETING: Symbol = Symbol::from_str("Hello"); + vec![&env, GREETING, to] + } +} +```