Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
333 changes: 276 additions & 57 deletions docs/Cargo.lock

Large diffs are not rendered by default.

3 changes: 0 additions & 3 deletions docs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,4 @@ miden-client = { version = "0.14", features = ["testing", "tonic"] }
miden-client-sqlite-store = { version = "0.14", package = "miden-client-sqlite-store" }
miden-protocol = { version = "0.14" }
rand = { version = "0.9" }
serde = { version = "1", features = ["derive"] }
serde_json = { version = "1.0", features = ["raw_value"] }
tokio = { version = "1.48", features = ["rt-multi-thread", "net", "macros", "fs"] }
rand_chacha = "0.9.0"
1 change: 1 addition & 0 deletions docs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@
#![doc = include_str!("rust-client/creating_notes_in_masm_tutorial.md")]
#![doc = include_str!("rust-client/delegated_proving_tutorial.md")]
#![doc = include_str!("rust-client/network_transactions_tutorial.md")]
#![doc = include_str!("rust-client/oracle_tutorial.md")]
153 changes: 44 additions & 109 deletions docs/src/rust-client/counter_contract_tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,7 @@ miden-client = { version = "0.14", features = ["testing", "tonic"] }
miden-client-sqlite-store = { version = "0.14", package = "miden-client-sqlite-store" }
miden-protocol = { version = "0.14" }
rand = { version = "0.9" }
serde = { version = "1", features = ["derive"] }
serde_json = { version = "1.0", features = ["raw_value"] }
tokio = { version = "1.46", features = ["rt-multi-thread", "net", "macros", "fs"] }
rand_chacha = "0.9.0"
```

### Set up your `src/main.rs` file
Expand All @@ -54,50 +51,23 @@ In the previous section, we explained how to instantiate the Miden client. We ca
Copy and paste the following code into your `src/main.rs` file:

```rust no_run
use miden_client::auth::NoAuth;
use miden_client::transaction::TransactionKernel;
use rand::RngCore;
use std::{fs, path::Path, sync::Arc};
use std::{path::PathBuf, sync::Arc};

use miden_client::{
address::NetworkId,
assembly::{
Assembler,
CodeBuilder,
DefaultSourceManager,
Module,
ModuleKind,
Path as AssemblyPath,
account::{
component::AccountComponentMetadata, AccountBuilder, AccountComponent, AccountStorageMode,
AccountType, StorageSlot, StorageSlotName,
},
address::NetworkId,
auth::NoAuth,
builder::ClientBuilder,
keystore::FilesystemKeyStore,
rpc::{Endpoint, GrpcClient},
transaction::TransactionRequestBuilder,
ClientError,
ClientError, Word,
};
use miden_client_sqlite_store::ClientBuilderSqliteExt;
use miden_client::{
account::{
component::AccountComponentMetadata, AccountBuilder, AccountComponent, AccountStorageMode,
AccountType, StorageSlot, StorageSlotName,
},
Word,
};

fn create_library(
library_path: &str,
source_code: &str,
) -> Result<std::sync::Arc<miden_client::assembly::Library>, Box<dyn std::error::Error>> {
let source_manager = Arc::new(DefaultSourceManager::default());
let assembler = TransactionKernel::assembler_with_source_manager(source_manager.clone());
let module = Module::parser(ModuleKind::Library).parse_str(
AssemblyPath::new(library_path),
source_code,
source_manager,
)?;
let library = assembler.assemble_library([module])?;
Ok(library)
}

#[tokio::main]
async fn main() -> Result<(), ClientError> {
Expand All @@ -107,10 +77,10 @@ async fn main() -> Result<(), ClientError> {
let rpc_client = Arc::new(GrpcClient::new(&endpoint, timeout_ms));

// Initialize keystore
let keystore_path = std::path::PathBuf::from("./keystore");
let keystore_path = PathBuf::from("./keystore");
let keystore = Arc::new(FilesystemKeyStore::new(keystore_path).unwrap());

let store_path = std::path::PathBuf::from("./store.sqlite3");
let store_path = PathBuf::from("./store.sqlite3");

let mut client = ClientBuilder::new()
.rpc(rpc_client)
Expand Down Expand Up @@ -256,15 +226,17 @@ To build the counter contract copy and paste the following code at the end of yo
// -------------------------------------------------------------------------
println!("\n[STEP 1] Creating counter contract.");

// Load the MASM file for the counter contract
let counter_path = Path::new("../masm/accounts/counter.masm");
let counter_code = fs::read_to_string(counter_path).unwrap();
// Load the MASM file for the counter contract. `include_str!` resolves at
// compile time relative to this source file, so the binary is independent of
// the working directory it is run from.
let counter_code = include_str!("../masm/accounts/counter.masm");

// Compile the account code into `AccountComponent` with one storage slot
// Compile the account code into `AccountComponent` with one storage slot.
let counter_slot_name =
StorageSlotName::new("miden::tutorials::counter").expect("valid slot name");
let component_code = CodeBuilder::new()
.compile_component_code("external_contract::counter_contract", &counter_code)
let component_code = client
.code_builder()
.compile_component_code("external_contract::counter_contract", counter_code)
.unwrap();
let counter_component = AccountComponent::new(
component_code,
Expand Down Expand Up @@ -324,21 +296,15 @@ Paste the following code at the end of your `src/main.rs` file:
println!("\n[STEP 2] Call Counter Contract With Script");

// Load the MASM script referencing the increment procedure
let script_path = Path::new("../masm/scripts/counter_script.masm");
let script_code = fs::read_to_string(script_path).unwrap();

// Create a library from the counter contract code
let account_component_lib = create_library(
"external_contract::counter_contract",
&counter_code,
)
.unwrap();
let script_code = include_str!("../masm/scripts/counter_script.masm");

// Compile the script with the counter contract code linked as a module
// on the same `CodeBuilder` chain.
let tx_script = client
.code_builder()
.with_dynamically_linked_library(&account_component_lib)
.with_linked_module("external_contract::counter_contract", counter_code)
.unwrap()
.compile_tx_script(&script_code)
.compile_tx_script(script_code)
.unwrap();

// Build a transaction request with the custom script
Expand Down Expand Up @@ -384,50 +350,23 @@ println!(
The final `src/main.rs` file should look like this:

```rust no_run
use miden_client::auth::NoAuth;
use miden_client::transaction::TransactionKernel;
use rand::RngCore;
use std::{fs, path::Path, sync::Arc};
use std::{path::PathBuf, sync::Arc};

use miden_client::{
address::NetworkId,
assembly::{
Assembler,
CodeBuilder,
DefaultSourceManager,
Module,
ModuleKind,
Path as AssemblyPath,
account::{
component::AccountComponentMetadata, AccountBuilder, AccountComponent, AccountStorageMode,
AccountType, StorageSlot, StorageSlotName,
},
address::NetworkId,
auth::NoAuth,
builder::ClientBuilder,
keystore::FilesystemKeyStore,
rpc::{Endpoint, GrpcClient},
transaction::TransactionRequestBuilder,
ClientError,
ClientError, Word,
};
use miden_client_sqlite_store::ClientBuilderSqliteExt;
use miden_client::{
account::{
component::AccountComponentMetadata, AccountBuilder, AccountComponent, AccountStorageMode,
AccountType, StorageSlot, StorageSlotName,
},
Word,
};

fn create_library(
library_path: &str,
source_code: &str,
) -> Result<std::sync::Arc<miden_client::assembly::Library>, Box<dyn std::error::Error>> {
let source_manager = Arc::new(DefaultSourceManager::default());
let assembler = TransactionKernel::assembler_with_source_manager(source_manager.clone());
let module = Module::parser(ModuleKind::Library).parse_str(
AssemblyPath::new(library_path),
source_code,
source_manager,
)?;
let library = assembler.assemble_library([module])?;
Ok(library)
}

#[tokio::main]
async fn main() -> Result<(), ClientError> {
Expand All @@ -437,10 +376,10 @@ async fn main() -> Result<(), ClientError> {
let rpc_client = Arc::new(GrpcClient::new(&endpoint, timeout_ms));

// Initialize keystore
let keystore_path = std::path::PathBuf::from("./keystore");
let keystore_path = PathBuf::from("./keystore");
let keystore = Arc::new(FilesystemKeyStore::new(keystore_path).unwrap());

let store_path = std::path::PathBuf::from("./store.sqlite3");
let store_path = PathBuf::from("./store.sqlite3");

let mut client = ClientBuilder::new()
.rpc(rpc_client)
Expand All @@ -458,15 +397,17 @@ async fn main() -> Result<(), ClientError> {
// -------------------------------------------------------------------------
println!("\n[STEP 1] Creating counter contract.");

// Load the MASM file for the counter contract
let counter_path = Path::new("../masm/accounts/counter.masm");
let counter_code = fs::read_to_string(counter_path).unwrap();
// Load the MASM file for the counter contract. `include_str!` resolves at
// compile time relative to this source file, so the binary is independent
// of the working directory it is run from.
let counter_code = include_str!("../masm/accounts/counter.masm");

// Compile the account code into `AccountComponent` with one storage slot
// Compile the account code into `AccountComponent` with one storage slot.
let counter_slot_name =
StorageSlotName::new("miden::tutorials::counter").expect("valid slot name");
let component_code = CodeBuilder::new()
.compile_component_code("external_contract::counter_contract", &counter_code)
let component_code = client
.code_builder()
.compile_component_code("external_contract::counter_contract", counter_code)
.unwrap();
let counter_component = AccountComponent::new(
component_code,
Expand Down Expand Up @@ -503,21 +444,15 @@ async fn main() -> Result<(), ClientError> {
println!("\n[STEP 2] Call Counter Contract With Script");

// Load the MASM script referencing the increment procedure
let script_path = Path::new("../masm/scripts/counter_script.masm");
let script_code = fs::read_to_string(script_path).unwrap();

// Create a library from the counter contract code
let account_component_lib = create_library(
"external_contract::counter_contract",
&counter_code,
)
.unwrap();
let script_code = include_str!("../masm/scripts/counter_script.masm");

// Compile the script with the counter contract code linked as a module
// on the same `CodeBuilder` chain.
let tx_script = client
.code_builder()
.with_dynamically_linked_library(&account_component_lib)
.with_linked_module("external_contract::counter_contract", counter_code)
.unwrap()
.compile_tx_script(&script_code)
.compile_tx_script(script_code)
.unwrap();

// Build a transaction request with the custom script
Expand Down
15 changes: 6 additions & 9 deletions docs/src/rust-client/create_deploy_tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,7 @@ miden-client = { version = "0.14", features = ["testing", "tonic"] }
miden-client-sqlite-store = { version = "0.14", package = "miden-client-sqlite-store" }
miden-protocol = { version = "0.14" }
rand = { version = "0.9" }
serde = { version = "1", features = ["derive"] }
serde_json = { version = "1.0", features = ["raw_value"] }
tokio = { version = "1.46", features = ["rt-multi-thread", "net", "macros", "fs"] }
rand_chacha = "0.9.0"
```

## Step 2: Initialize the client
Expand All @@ -72,7 +69,7 @@ Copy and paste the following code into your `src/main.rs` file.
```rust no_run
use miden_client::auth::{AuthSchemeId, AuthSingleSig};
use rand::RngCore;
use std::sync::Arc;
use std::{path::PathBuf, sync::Arc};
use tokio::time::Duration;

use miden_client::{
Expand Down Expand Up @@ -105,10 +102,10 @@ async fn main() -> Result<(), ClientError> {
let rpc_client = Arc::new(GrpcClient::new(&endpoint, timeout_ms));

// Initialize keystore
let keystore_path = std::path::PathBuf::from("./keystore");
let keystore_path = PathBuf::from("./keystore");
let keystore = Arc::new(FilesystemKeyStore::new(keystore_path).unwrap());

let store_path = std::path::PathBuf::from("./store.sqlite3");
let store_path = PathBuf::from("./store.sqlite3");

let mut client = ClientBuilder::new()
.rpc(rpc_client)
Expand Down Expand Up @@ -242,7 +239,7 @@ Your updated `main()` function in `src/main.rs` should look like this:
```rust no_run
use miden_client::auth::{AuthSchemeId, AuthSingleSig};
use rand::RngCore;
use std::sync::Arc;
use std::{path::PathBuf, sync::Arc};
use tokio::time::Duration;

use miden_client::{
Expand Down Expand Up @@ -275,10 +272,10 @@ async fn main() -> Result<(), ClientError> {
let rpc_client = Arc::new(GrpcClient::new(&endpoint, timeout_ms));

// Initialize keystore
let keystore_path = std::path::PathBuf::from("./keystore");
let keystore_path = PathBuf::from("./keystore");
let keystore = Arc::new(FilesystemKeyStore::new(keystore_path).unwrap());

let store_path = std::path::PathBuf::from("./store.sqlite3");
let store_path = PathBuf::from("./store.sqlite3");

let mut client = ClientBuilder::new()
.rpc(rpc_client)
Expand Down
23 changes: 12 additions & 11 deletions docs/src/rust-client/creating_notes_in_masm_tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,7 @@ miden-client = { version = "0.14", features = ["testing", "tonic"] }
miden-client-sqlite-store = { version = "0.14", package = "miden-client-sqlite-store" }
miden-protocol = { version = "0.14" }
rand = { version = "0.9" }
serde = { version = "1", features = ["derive"] }
serde_json = { version = "1.0", features = ["raw_value"] }
tokio = { version = "1.46", features = ["rt-multi-thread", "net", "macros", "fs"] }
rand_chacha = "0.9.0"
```

## Step 2: Write the Note Script
Expand All @@ -80,7 +77,7 @@ masm/
└── notes/
```

Inside the `masm/notes/` directory, create the file `iterative_output_note.masm`:
Inside the `masm/notes/` directory, create the file `iterative_output_note.masm`. Note scripts in v0.14.5+ are compiled as libraries; the `@note_script` attribute marks the entrypoint procedure.

```masm
use miden::protocol::active_note
Expand All @@ -97,8 +94,10 @@ const ASSET_HALF_VALUE_PTR=8 # half-amount ASSET_VALUE stored here
const ACCOUNT_ID_PREFIX=12 # storage: [prefix, suffix, tag, 0]
const TAG=14 # = ACCOUNT_ID_PREFIX + 2

# => []
begin
#! Inputs: []
#! Outputs: []
@note_script
pub proc main
# Drop word if user accidentally pushes note_args
dropw
# => []
Expand Down Expand Up @@ -204,7 +203,7 @@ Copy and paste the following code into your `src/main.rs` file.
```rust no_run
use miden_client::auth::{AuthSchemeId, AuthSingleSig};
use rand::RngCore;
use std::{fs, path::Path, sync::Arc};
use std::{path::PathBuf, sync::Arc};
use tokio::time::{sleep, Duration};

use miden_client::{
Expand Down Expand Up @@ -312,10 +311,10 @@ async fn main() -> Result<(), ClientError> {
let rpc_client = Arc::new(GrpcClient::new(&endpoint, timeout_ms));

// Initialize keystore
let keystore_path = std::path::PathBuf::from("./keystore");
let keystore_path = PathBuf::from("./keystore");
let keystore = Arc::new(FilesystemKeyStore::new(keystore_path).unwrap());

let store_path = std::path::PathBuf::from("./store.sqlite3");
let store_path = PathBuf::from("./store.sqlite3");

let mut client = ClientBuilder::new()
.rpc(rpc_client)
Expand Down Expand Up @@ -395,13 +394,15 @@ async fn main() -> Result<(), ClientError> {
// -------------------------------------------------------------------------
println!("\n[STEP 3] Create iterative output note");

let code = fs::read_to_string(Path::new("../masm/notes/iterative_output_note.masm")).unwrap();
// `include_str!` resolves at compile time relative to this source file,
// so the binary is independent of the working directory it is run from.
let code = include_str!("../masm/notes/iterative_output_note.masm");
let serial_num = client.rng().draw_word();

// Create note metadata and tag
let tag = NoteTag::new(0);
let metadata = NoteMetadata::new(alice_account.id(), NoteType::Public).with_tag(tag);
let note_script = client.code_builder().compile_note_script(&code).unwrap();
let note_script = client.code_builder().compile_note_script(code).unwrap();
let note_storage = NoteStorage::new(vec![
alice_account.id().prefix().as_felt(),
alice_account.id().suffix(),
Expand Down
Loading
Loading