From e667e6372bc08a85ca499dd8b9758fcd64447f09 Mon Sep 17 00:00:00 2001 From: elizabethengelman <4752801+elizabethengelman@users.noreply.github.com> Date: Wed, 15 Jan 2025 13:58:10 -0500 Subject: [PATCH 1/9] Updates to hello-world.mdx to match current init behavior --- .../getting-started/hello-world.mdx | 61 +++++++++++-------- 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/docs/build/smart-contracts/getting-started/hello-world.mdx b/docs/build/smart-contracts/getting-started/hello-world.mdx index b6582da17..84e54e3d3 100644 --- a/docs/build/smart-contracts/getting-started/hello-world.mdx +++ b/docs/build/smart-contracts/getting-started/hello-world.mdx @@ -37,11 +37,12 @@ The `init` command will create a Rust workspace project, using the recommended s ├── Cargo.toml ├── README.md └── contracts - └── hello_world - ├── Cargo.toml - └── src - ├── lib.rs - └── test.rs + ├── hello_world + │   ├── Cargo.toml + │   ├── Makefile + │   ├── src + │   │   ├── lib.rs + │   │   └── test.rs ``` ### Cargo.toml @@ -60,7 +61,7 @@ members = [ ] [workspace.dependencies] -soroban-sdk = "20.3.2" +soroban-sdk = "22" ``` :::info @@ -150,14 +151,14 @@ All contracts should begin with `#![no_std]` to ensure that the Rust standard li The contract imports the types and macros that it needs from the `soroban-sdk` crate. ```rust -use soroban_sdk::{contract, contractimpl, symbol_short, vec, Env, Symbol, Vec}; +use soroban_sdk::{contract, contractimpl, vec, Env, String, Vec}; ``` 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. Primitive values like `u128`, `i128`, `u64`, `i64`, `u32`, `i32`, and `bool` can also be used. Floats and floating point math are not supported. Contract inputs must not be references. -The `#[contract]` attribute designates the Contract struct as the type to which contract functions are associated. This implies that the struct will have contract functions implemented for it. +The `#[contract]` attribute designates the `HelloContract` struct as the type to which contract functions are associated. This implies that the struct will have contract functions implemented for it. ```rust #[contract] @@ -169,8 +170,8 @@ Contract functions are defined within an `impl` block for the struct, which is a ```rust #[contractimpl] impl HelloContract { - pub fn hello(env: Env, to: Symbol) -> Vec { - vec![&env, symbol_short!("Hello"), to] + pub fn hello(env: Env, to: String) -> Vec { + vec![&env, String::from_str(&env, "Hello"), to] } } ``` @@ -179,15 +180,15 @@ Putting those pieces together a simple contract looks like this. ```rust title="contracts/hello_world/src/lib.rs" #![no_std] -use soroban_sdk::{contract, contractimpl, symbol_short, vec, Env, Symbol, Vec}; +use soroban_sdk::{contract, contractimpl, vec, Env, String, Vec}; #[contract] pub struct HelloContract; #[contractimpl] impl HelloContract { - pub fn hello(env: Env, to: Symbol) -> Vec { - vec![&env, symbol_short!("Hello"), to] + pub fn hello(env: Env, to: String) -> Vec { + vec![&env, String::from_str(&env, "Hello"), to] } } @@ -200,22 +201,22 @@ Note the `mod test` line at the bottom, this will tell Rust to compile and run t 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 our HelloContract, a simple test will look like this. +Given our `HelloContract`, a simple test will look like this. ```rust #![no_std] -use soroban_sdk::{contract, contractimpl, symbol_short, vec, Env, Symbol, Vec}; +use soroban_sdk::{contract, contractimpl, vec, Env, String, Vec}; #[contract] pub struct HelloContract; #[contractimpl] impl HelloContract { - pub fn hello(env: Env, to: Symbol) -> Vec { - vec![&env, symbol_short!("Hello"), to] + pub fn hello(env: Env, to: String) -> Vec { + vec![&env, String::from_str(&env, "Hello"), to] } } @@ -229,18 +230,22 @@ mod test; #![cfg(test)] use super::*; -use soroban_sdk::{symbol_short, vec, Env}; +use soroban_sdk::{vec, Env, String}; #[test] fn test() { let env = Env::default(); - let contract_id = env.register_contract(None, HelloContract); + let contract_id = env.register(HelloContract, ()); let client = HelloContractClient::new(&env, &contract_id); - let words = client.hello(&symbol_short!("Dev")); + let words = client.hello(&String::from_str(&env, "Dev")); assert_eq!( words, - vec![&env, symbol_short!("Hello"), symbol_short!("Dev"),] + vec![ + &env, + String::from_str(&env, "Hello"), + String::from_str(&env, "Dev"), + ] ); } ``` @@ -264,16 +269,20 @@ All public functions within an `impl` block that is annotated with the `#[contra ```rust let client = HelloContractClient::new(&env, &contract_id); -let words = client.hello(&symbol_short!("Dev")); +let words = client.hello(&String::from_str(&env, "Dev")); ``` The values returned by functions can be asserted on: ```rust -assert_eq!( - words, - vec![&env, symbol_short!("Hello"), symbol_short!("Dev"),] -); + assert_eq!( + words, + vec![ + &env, + String::from_str(&env, "Hello"), + String::from_str(&env, "Dev"), + ] + ); ``` ## Run the Tests From 4ecd7fb8687d14bb9e51105465f88b5ec7ac0182 Mon Sep 17 00:00:00 2001 From: elizabethengelman <4752801+elizabethengelman@users.noreply.github.com> Date: Wed, 15 Jan 2025 15:37:07 -0500 Subject: [PATCH 2/9] Updates to storing-data.mdx to copy increment code over placeholder code --- .../getting-started/storing-data.mdx | 49 +++++++++++-------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/docs/build/smart-contracts/getting-started/storing-data.mdx b/docs/build/smart-contracts/getting-started/storing-data.mdx index a17536345..8ab6ee256 100644 --- a/docs/build/smart-contracts/getting-started/storing-data.mdx +++ b/docs/build/smart-contracts/getting-started/storing-data.mdx @@ -27,27 +27,27 @@ This tutorial assumes that you've already completed the previous steps in Gettin ## Adding the increment contract -The `stellar contract init` command allows us to initialize a new project with any of the example contracts from the [soroban-examples](https://github.com/stellar/soroban-examples) repo, using the `--name` flag, to specify a new contract's name. +In addition to creating a new project, the `stellar contract init` command also allows us to initialize a new contract workspace within an existing project. In this example, we're going to initialize a new contract and use the `--name` flag to specify the name of our new contract, `increment`. -It will not overwrite existing files unless we explicily pass in `--ovewrite` flag. Run the command with a `--name` flag to add an `increment` contract to our project. From inside our `soroban-hello-world` directory, run: +This command will not overwrite existing files unless we explicitly pass in the `--overwrite` flag. From within our `soroban-hello-world` directory, run: ```sh stellar contract init . --name increment ``` -This will create a new `contracts/increment` directory with the following files: +This creates a new `contracts/increment` directory with placeholder code in `src/lib.rs` and `src/test.rs`, which we'll replace with our new increment contract and corresponding tests. ``` └── contracts ├── increment - ├── Cargo.lock ├── Cargo.toml + ├── Makefile └── src ├── lib.rs └── test.rs ``` -The following code was added to `contracts/increment/src/lib.rs`. We'll go over it in more detail below. However, in order to use the increment contract code, you will need to copy and paste the `lib.rs` and `test.rs` into `src`. +We will go through the contract code in more detail below, but for now, replace the placeholder code in `contracts/increment/src/lib.rs` with the following. ```rust #![no_std] @@ -56,13 +56,13 @@ use soroban_sdk::{contract, contractimpl, log, symbol_short, Env, Symbol}; const COUNTER: Symbol = symbol_short!("COUNTER"); #[contract] -pub struct IncrementorContract; +pub struct IncrementContract; #[contractimpl] -impl IncrementorContract { - /// Increment an internal counter; return the new value. +impl IncrementContract { + /// Increment increments an internal counter, and returns the value. pub fn increment(env: Env) -> u32 { - let mut count: u32 = env.storage().instance().get(&COUNTER).unwrap_or(0); + let mut count: u32 = env.storage().instance().get(&COUNTER).unwrap_or(0); // If no value set, assume 0. count += 1; @@ -150,21 +150,22 @@ Check that it built: ls target/wasm32-unknown-unknown/release/*.wasm ``` -You should see both `hello_world.wasm` and `soroban_increment_contract.wasm`. +You should see both `hello_world.wasm` and `increment.wasm`. ## Tests -The following test has been added to the `contracts/increment/src/test.rs` file. +Replace the placeholder code in `contracts/increment/src/test.rs` with the following increment test code. -```rust title="contracts/incrementor/src/test.rs" -use crate::{IncrementorContract, IncrementorContractClient}; +```rust title="contracts/increment/src/test.rs" +#![cfg(test)] +use crate::{IncrementContract, IncrementContractClient}; use soroban_sdk::Env; #[test] -fn increment() { +fn test() { let env = Env::default(); - let contract_id = env.register_contract(None, IncrementorContract); - let client = IncrementorContractClient::new(&env, &contract_id); + let contract_id = env.register(IncrementContract, ()); + let client = IncrementContractClient::new(&env, &contract_id); assert_eq!(client.increment(), 1); assert_eq!(client.increment(), 2); @@ -188,14 +189,20 @@ If you want to see the output of the `log!` call, run the tests with `--nocaptur cargo test -- --nocapture ``` -You should see the output: +You should see the the diagnostic log events with the count data in the output: ``` running 1 test -count: U32(0) -count: U32(1) -count: U32(2) -test test::incrementor ... ok +[Diagnostic Event] contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM, + topics:[log], + data:["count: {}", 1] +[Diagnostic Event] contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM, + topics:[log], + data:["count: {}", 2] +[Diagnostic Event] contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM, + topics:[log], + data:["count: {}", 3] +test test::test ... ok ``` ## Take it further From 608d5177d707633aa6b8d0bf48261c455fac5872 Mon Sep 17 00:00:00 2001 From: elizabethengelman <4752801+elizabethengelman@users.noreply.github.com> Date: Wed, 15 Jan 2025 15:51:57 -0500 Subject: [PATCH 3/9] Updates to deploy-increment-contract.mdx --- .../getting-started/deploy-increment-contract.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/build/smart-contracts/getting-started/deploy-increment-contract.mdx b/docs/build/smart-contracts/getting-started/deploy-increment-contract.mdx index 29d26e123..8fc690653 100644 --- a/docs/build/smart-contracts/getting-started/deploy-increment-contract.mdx +++ b/docs/build/smart-contracts/getting-started/deploy-increment-contract.mdx @@ -39,7 +39,7 @@ You can run these two steps separately. Let's try it with the Increment contract stellar contract install \ --network testnet \ --source alice \ - --wasm target/wasm32-unknown-unknown/release/soroban_increment_contract.wasm + --wasm target/wasm32-unknown-unknown/release/increment.wasm ``` @@ -57,7 +57,7 @@ stellar contract install ` -This returns the hash of the Wasm bytes, like `6ddb28e0980f643bb97350f7e3bacb0ff1fe74d846c6d4f2c625e766210fbb5b`. Now you can use `--wasm-hash` with `deploy` rather than `--wasm`: +This returns the hash of the Wasm bytes, like `6ddb28e0980f643bb97350f7e3bacb0ff1fe74d846c6d4f2c625e766210fbb5b`. Now you can use `--wasm-hash` with `deploy` rather than `--wasm. Make sure to replace the example wasm hash with your own. From a8bfda91d596c7cc625a37762b3e31201a9ca9f9 Mon Sep 17 00:00:00 2001 From: elizabethengelman <4752801+elizabethengelman@users.noreply.github.com> Date: Thu, 16 Jan 2025 10:33:26 -0500 Subject: [PATCH 4/9] Add --alias when deploying --- .../getting-started/deploy-increment-contract.mdx | 6 ++++-- .../getting-started/deploy-to-testnet.mdx | 12 ++++++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/docs/build/smart-contracts/getting-started/deploy-increment-contract.mdx b/docs/build/smart-contracts/getting-started/deploy-increment-contract.mdx index 8fc690653..8e4ff6840 100644 --- a/docs/build/smart-contracts/getting-started/deploy-increment-contract.mdx +++ b/docs/build/smart-contracts/getting-started/deploy-increment-contract.mdx @@ -67,7 +67,8 @@ This returns the hash of the Wasm bytes, like `6ddb28e0980f643bb97350f7e3bacb0ff stellar contract deploy \ --wasm-hash 6ddb28e0980f643bb97350f7e3bacb0ff1fe74d846c6d4f2c625e766210fbb5b \ --source alice \ - --network testnet + --network testnet \ + --alias increment ``` @@ -78,7 +79,8 @@ stellar contract deploy \ stellar contract deploy ` --wasm-hash 6ddb28e0980f643bb97350f7e3bacb0ff1fe74d846c6d4f2c625e766210fbb5b ` --source alice ` - --network testnet + --network testnet ` + --alias increment ``` diff --git a/docs/build/smart-contracts/getting-started/deploy-to-testnet.mdx b/docs/build/smart-contracts/getting-started/deploy-to-testnet.mdx index 1a287dead..c50955e1c 100644 --- a/docs/build/smart-contracts/getting-started/deploy-to-testnet.mdx +++ b/docs/build/smart-contracts/getting-started/deploy-to-testnet.mdx @@ -41,7 +41,8 @@ To deploy your HelloWorld contract, run the following command: stellar contract deploy \ --wasm target/wasm32-unknown-unknown/release/hello_world.wasm \ --source alice \ - --network testnet + --network testnet \ + --alias hello_world ``` @@ -52,7 +53,8 @@ stellar contract deploy \ stellar contract deploy ` --wasm target/wasm32-unknown-unknown/release/hello_world.wasm ` --source alice ` - --network testnet + --network testnet ` + --alias hello_world ``` @@ -61,6 +63,12 @@ stellar contract deploy ` This returns the contract's id, starting with a `C`. In this example, we're going to use `CACDYF3CYMJEJTIVFESQYZTN67GO2R5D5IUABTCUG3HXQSRXCSOROBAN`, so replace it with your actual contract id. +:::tip + +We used the `--alias` flag in this deploy command which will create a `.stellar/contract-ids/hello_world.json` file that maps the alias `hello_world` to the contract id and network. This allows us to refer to this contract as its alias instead the contract id. + +::: + ## Interact Using the code we wrote in [Write a Contract](./hello-world.mdx#contract-source-code) and the resulting `.wasm` file we built in [Build](hello-world.mdx#build-the-contract), run the following command to invoke the `hello` function. From 3b50e4d38620af1bb86e6a57aa7458baefaee96c Mon Sep 17 00:00:00 2001 From: elizabethengelman <4752801+elizabethengelman@users.noreply.github.com> Date: Thu, 16 Jan 2025 15:35:23 -0500 Subject: [PATCH 5/9] Update dapp-frontend.mdx --- docs/build/apps/dapp-frontend.mdx | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/docs/build/apps/dapp-frontend.mdx b/docs/build/apps/dapp-frontend.mdx index a60cc175e..bf25ad954 100644 --- a/docs/build/apps/dapp-frontend.mdx +++ b/docs/build/apps/dapp-frontend.mdx @@ -19,11 +19,13 @@ Let's get started. You're going to need [Node.js](https://nodejs.org/en/download/package-manager/) v18.14.1 or greater. If you haven't yet, install it now. -We want to initialize our current project as an Astro project. To do this, we can clone a template. You can find Soroban templates on GitHub by [searching for repositories that start with "soroban-template-"](https://github.com/search?q=%22soroban-template-%22&type=repositories). For this tutorial, we'll use [stellar/soroban-template-astro](https://github.com/stellar/soroban-template-astro). We'll also use a tool called [degit](https://github.com/Rich-Harris/degit) to clone the template without its git history. This will allow us to set it up as our own git project. +We want to create an Astro project with the contracts from the previous lesson. To do this, we can clone a template. You can find Soroban templates on GitHub by [searching for repositories that start with "soroban-template-"](https://github.com/search?q=%22soroban-template-%22&type=repositories). For this tutorial, we'll use [stellar/soroban-template-astro](https://github.com/stellar/soroban-template-astro). We'll also use a tool called [degit](https://github.com/Rich-Harris/degit) to clone the template without its git history. This will allow us to set it up as our own git project. -Since you have `node` and its package manager `npm` installed, you also have `npx`. Make sure you're no longer in your `soroban-hello-world` directory and then run: +Since you have `node` and its package manager `npm` installed, you also have `npx`. -``` +We're going to create a new project directory with this template to make things easier in this tutorial, so make sure you're no longer in your `soroban-hello-world` directory and then run: + +```sh npx degit stellar/soroban-template-astro first-soroban-app cd first-soroban-app git init @@ -56,7 +58,11 @@ This project has the following directory structure, which we'll go over in more └── tsconfig.json ``` -The `contracts` are the same ones you walked through in the previous steps of the tutorial. +The `contracts` are the same ones you walked through in the previous steps of the tutorial. Since we already deployed these contracts with aliases, we can reuse the generated contract ID files by copying them from the `soroban-hello-world/.stellar` directory into this project: + +```sh +cp -R ../soroban-hello-world/.stellar/ .stellar +``` ## Generate an NPM package for the Hello World contract @@ -67,17 +73,23 @@ This is going to use the CLI command `stellar contract bindings typescript`: ```bash stellar contract bindings typescript \ --network testnet \ - --contract-id $(cat .stellar/contract-ids/hello_world.txt) \ + --contract-id hello_world \ --output-dir packages/hello_world ``` +:::tip + +Notice that we were able to use the contract alias, `hello-world`, in place of the contract id! + +::: + This project is set up as an NPM Workspace, and so the `hello_world` client library was generated in the `packages` directory at `packages/hello_world`. We attempt to keep the code in these generated libraries readable, so go ahead and look around. Open up the new `packages/hello_world` directory in your editor. If you've built or contributed to Node projects, it will all look familiar. You'll see a `package.json` file, a `src` directory, a `tsconfig.json`, and even a README. ## Generate an NPM package for the Increment contract -Though we can run `soroban contract bindings typescript` for each of our contracts individually, the [soroban-template-astro](https://github.com/stellar/soroban-astro-template) that we used as our template includes a very handy `initialize.js` script that will handle this for all of the contracts in our `contracts` directory. +Though we can run `soroban contract bindings typescript` for each of our contracts individually, the [soroban-template-astro](https://github.com/stellar/soroban-astro-template) project that we used as our template includes a very handy `initialize.js` script that will handle this for all of the contracts in our `contracts` directory. In addition to generating the NPM packages, `initialize.js` will also: @@ -408,7 +420,7 @@ Now you're ready to sign the call to `increment`! ### Call `increment` -Now we can import the `increment` contract client from `soroban_increment_contract` and start using it. We'll again create a new Astro component. Create a new file at `src/components/Counter.astro` with the following contents: +Now we can import the `increment` contract client from `contracts/increment.ts` and start using it. We'll again create a new Astro component. Create a new file at `src/components/Counter.astro` with the following contents: ```html title="src/components/Counter.astro" Incrementor
@@ -417,8 +429,8 @@ Current value: ???