Skip to content

Commit

Permalink
[documentation]: #6 Move the Rust examples to this repository
Browse files Browse the repository at this point in the history
Signed-off-by: 6r1d <[email protected]>
  • Loading branch information
6r1d committed Sep 13, 2023
1 parent 4100a65 commit 73a6592
Show file tree
Hide file tree
Showing 13 changed files with 627 additions and 0 deletions.
1 change: 1 addition & 0 deletions Rust/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
target/
30 changes: 30 additions & 0 deletions Rust/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
[package]
name = "iroha_2_examples"
version = "0.1.0"
edition = "2021"

authors = ["Iroha 2 team <https://github.com/orgs/soramitsu/teams/iroha2>"]
description = "Example repository for Iroha 2 ledger"
repository = "https://github.com/hyperledger/iroha-2-examples"
documentation = "https://hyperledger.github.io/iroha-2-docs"
homepage = "https://iroha.tech"

license = "Apache-2.0"
keywords = ["blockchain", "crypto", "iroha", "ledger"]
categories = ["cryptography::cryptocurrencies"]

[dependencies]
iroha = { "git" = "https://github.com/hyperledger/iroha.git", branch = "iroha2-dev" }
iroha_crypto = { "git" = "https://github.com/hyperledger/iroha.git", branch = "iroha2-dev" }
iroha_client = { "git" = "https://github.com/hyperledger/iroha.git", branch = "iroha2-dev" }
iroha_config = { "git" = "https://github.com/hyperledger/iroha.git", branch = "iroha2-dev" }
iroha_data_model = { "git" = "https://github.com/hyperledger/iroha.git", branch = "iroha2-dev" }
iroha_genesis = { "git" = "https://github.com/hyperledger/iroha.git", branch = "iroha2-dev" }
test_network = { "git" = "https://github.com/hyperledger/iroha.git", branch = "iroha2-dev" }

eyre = "0.6.8"

serde = { version = "1.0.151", default-features = false }
serde_json = { version = "1.0.91", default-features = false }

tokio = "1.23.0"
23 changes: 23 additions & 0 deletions Rust/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Rust examples for Iroha 2

This directory contains the examples from the [Rust tutorial](https://hyperledger.github.io/iroha-2-docs/guide/rust.html#_2-configuring-iroha-2).

## Running the examples

To run the examples, you need to install [`cargo-nextest`](https://nexte.st/) first.

```bash
cargo install cargo-nextest
```

After it is installed, type:

```bash
cargo nextest run
```

You'll Cargo install the packages that are needed for the tests and the test code will run.

## Extending the example set

Simply add a file with Rust code to the [`examples`](./examples/) directory. It will be launched by `cargo-nextest` on its next run.
21 changes: 21 additions & 0 deletions Rust/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"PUBLIC_KEY": "ed01207233BFC89DCBD68C19FDE6CE6158225298EC1131B6A130D1AEB454C1AB5183C0",
"PRIVATE_KEY": {
"digest_function": "ed25519",
"payload": "9ac47abf59b356e0bd7dcbbbb4dec080e302156a48ca907e47cb6aea1d32719e7233bfc89dcbd68c19fde6ce6158225298ec1131b6a130d1aeb454c1ab5183c0"
},
"ACCOUNT_ID": "alice@wonderland",
"BASIC_AUTH": {
"web_login": "mad_hatter",
"password": "ilovetea"
},
"TORII_API_URL": "http://127.0.0.1:8080/",
"TORII_TELEMETRY_URL": "http://127.0.0.1:8180/",
"TRANSACTION_TIME_TO_LIVE_MS": 100000,
"TRANSACTION_STATUS_TIMEOUT_MS": 15000,
"TRANSACTION_LIMITS": {
"max_instruction_number": 4096,
"max_wasm_size_bytes": 4194304
},
"ADD_TRANSACTION_NONCE": false
}
28 changes: 28 additions & 0 deletions Rust/examples/client_account_definition.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use eyre::{Error};

fn main() {
account_definition_test()
.expect("Account definition example is expected to work correctly");

println!("Account definition example works!");
}

fn account_definition_test() -> Result<(), Error> {
// #region account_definition_comparison
use iroha_data_model::prelude::AccountId;

// Create an `iroha_data_model::AccountId` instance
// with a DomainId instance and a Domain ID for an account
let longhand_account_id = AccountId::new("white_rabbit".parse()?, "looking_glass".parse()?);
let account_id: AccountId = "white_rabbit@looking_glass"
.parse()
.expect("Valid, because the string contains no whitespace, has a single '@' character and is not empty after");

// Check that two ways to define an account match
assert_eq!(account_id, longhand_account_id);

// #endregion account_definition_comparison

// Finish the test successfully
Ok(())
}
83 changes: 83 additions & 0 deletions Rust/examples/client_account_registration.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
use std::fs::File;
use eyre::{Error, WrapErr};
use iroha_config::client::Configuration;

fn main() {
let config = load_configuration()
.expect("Configuration should be loading normally");
account_registration_test(&config)
.expect("Account registration example is expected to work correctly");
println!("Account registration example works!");
}

fn load_configuration() -> Result<Configuration, Error> {
// #region rust_config_load
let config_loc = "./config.json";
let file = File::open(config_loc)
.wrap_err(format!("Unable to load the configuration file at `{}`", config_loc))
.expect("Config file is loading normally.");
let config: Configuration = serde_json::from_reader(file)
.wrap_err(format!("Failed to parse `{}`", config_loc))
.expect("Verified in tests");
// #endregion rust_config_load

// Return the configuration normally
Ok(config)
}

// This function imitates the user sharing a public key.
// It generates a new public key for a new account.
// Normally, it is generated by Kagami.
fn get_key_from_white_rabbit() -> iroha_crypto::PublicKey {
use iroha_crypto::KeyPair;

let (public_key, _) = KeyPair::generate()
.expect("Failed to generate KeyPair")
.into();

public_key
}

fn account_registration_test(config: &Configuration) -> Result<(), Error> {
// #region register_account_crates
use iroha_client::client::Client;
use iroha_data_model::{
metadata::UnlimitedMetadata,
prelude::{Account, AccountId, InstructionBox, RegisterBox},
};
// #endregion register_account_crates

// Create an Iroha client
let iroha_client: Client = Client::new(&config)?;

// #region register_account_create
// Create an AccountId instance by providing the account and domain name
let account_id: AccountId = "white_rabbit@looking_glass"
.parse()
.expect("Valid, because the string contains no whitespace, has a single '@' character and is not empty after");
// #endregion register_account_create

// Use a public key that was shared by the white_rabbit.
let public_key = get_key_from_white_rabbit();

// #region register_account_generate
// Generate a new account
let create_account = RegisterBox::new(Account::new(account_id, [public_key]));
// #endregion register_account_generate

// #region register_account_prepare_tx
// Prepare a transaction using the
// Account's RegisterBox
let metadata = UnlimitedMetadata::new();
let instructions: Vec<InstructionBox> = vec![create_account.into()];
let tx = iroha_client.build_transaction(instructions, metadata)?;
// #endregion register_account_prepare_tx

// #region register_account_submit_tx
// Submit a prepared account registration transaction
iroha_client.submit_transaction(&tx)?;
// #endregion register_account_submit_tx

// Finish the test successfully
Ok(())
}
85 changes: 85 additions & 0 deletions Rust/examples/client_asset_burning.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
use std::fs::File;
use eyre::{Error, WrapErr};
use iroha_config::client::Configuration;

fn main() {
let config = load_configuration()
.expect("Configuration should be loading normally");
asset_burning_test(&config)
.expect("Asset burning example is expected to work correctly");

println!("Asset burning example works!");
}

fn load_configuration() -> Result<Configuration, Error> {
// #region rust_config_load
let config_loc = "./config.json";
let file = File::open(config_loc)
.wrap_err(format!("Unable to load the configuration file at `{}`", config_loc))
.expect("Config file is loading normally.");
let config: Configuration = serde_json::from_reader(file)
.wrap_err(format!("Failed to parse `{}`", config_loc))
.expect("Verified in tests");
// #endregion rust_config_load

// Return the configuration normally
Ok(config)
}

fn asset_burning_test(config: &Configuration) -> Result<(), Error> {
// #region burn_asset_crates
use std::str::FromStr;

use iroha_client::client::Client;
use iroha_data_model::{
prelude::{AccountId, AssetDefinitionId, AssetId, BurnBox, ToValue},
IdBox,
};
// #endregion burn_asset_crates

// Create an Iroha client
let iroha_client: Client = Client::new(&config)?;

// #region burn_asset_define_asset_account
// Define the instances of an Asset and Account
let roses = AssetDefinitionId::from_str("rose#wonderland")
.expect("Valid, because the string contains no whitespace, has a single '#' character and is not empty after");
let alice: AccountId = "alice@wonderland".parse()
.expect("Valid, because the string contains no whitespace, has a single '@' character and is not empty after");
// #endregion burn_asset_define_asset_account

// #region burn_asset_burn
// Burn the Asset instance
let burn_roses = BurnBox::new(
10_u32.to_value(),
IdBox::AssetId(AssetId::new(roses, alice)),
);
// #endregion burn_asset_burn

// #region burn_asset_submit_tx
iroha_client
.submit(burn_roses)
.wrap_err("Failed to submit transaction")?;
// #endregion burn_asset_submit_tx

// #region burn_asset_burn_alt
// Burn the Asset instance (alternate syntax).
// The syntax is `asset_name#asset_domain#account_name@account_domain`,
// or `roses.to_string() + "#" + alice.to_string()`.
// The `##` is a short-hand for the rose `which belongs to the same domain as the account
// to which it belongs to.
let burn_roses_alt = BurnBox::new(
10_u32.to_value(),
IdBox::AssetId("rose##alice@wonderland".parse()?),
);
// #endregion burn_asset_burn_alt

// #region burn_asset_submit_tx_alt
iroha_client
.submit(burn_roses_alt)
.wrap_err("Failed to submit transaction")?;
// #endregion burn_asset_submit_tx_alt

// Finish the test successfully
Ok(())
}
85 changes: 85 additions & 0 deletions Rust/examples/client_asset_minting.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
use std::fs::File;
use eyre::{Error, WrapErr};
use iroha_config::client::Configuration;

fn main() {
let config = load_configuration()
.expect("Configuration should be loading normally");
asset_minting_test(&config)
.expect("Asset minting example is expected to work correctly");

println!("Asset minting example works!");
}

fn load_configuration() -> Result<Configuration, Error> {
// #region rust_config_load
let config_loc = "./config.json";
let file = File::open(config_loc)
.wrap_err(format!("Unable to load the configuration file at `{}`", config_loc))
.expect("Config file is loading normally.");
let config: Configuration = serde_json::from_reader(file)
.wrap_err(format!("Failed to parse `{}`", config_loc))
.expect("Verified in tests");
// #endregion rust_config_load

// Return the configuration normally
Ok(config)
}

fn asset_minting_test(config: &Configuration) -> Result<(), Error> {
// #region mint_asset_crates
use std::str::FromStr;

use iroha_client::client::Client;
use iroha_data_model::{
prelude::{AccountId, AssetDefinitionId, AssetId, MintBox, ToValue},
IdBox,
};
// #endregion mint_asset_crates

// Create an Iroha client
let iroha_client: Client = Client::new(&config)?;

// Define the instances of an Asset and Account
// #region mint_asset_define_asset_account
let roses = AssetDefinitionId::from_str("rose#wonderland")
.expect("Valid, because the string contains no whitespace, has a single '#' character and is not empty after");
let alice: AccountId = "alice@wonderland".parse()
.expect("Valid, because the string contains no whitespace, has a single '@' character and is not empty after");
// #endregion mint_asset_define_asset_account

// Mint the Asset instance
// #region mint_asset_mint
let mint_roses = MintBox::new(
42_u32.to_value(),
IdBox::AssetId(AssetId::new(roses, alice)),
);
// #endregion mint_asset_mint

// #region mint_asset_submit_tx
iroha_client
.submit(mint_roses)
.wrap_err("Failed to submit transaction")?;
// #endregion mint_asset_submit_tx

// #region mint_asset_mint_alt
// Mint the Asset instance (alternate syntax).
// The syntax is `asset_name#asset_domain#account_name@account_domain`,
// or `roses.to_string() + "#" + alice.to_string()`.
// The `##` is a short-hand for the rose `which belongs to the same domain as the account
// to which it belongs to.
let mint_roses_alt = MintBox::new(
10_u32.to_value(),
IdBox::AssetId("rose##alice@wonderland".parse()?),
);
// #endregion mint_asset_mint_alt

// #region mint_asset_submit_tx_alt
iroha_client
.submit(mint_roses_alt)
.wrap_err("Failed to submit transaction")?;
// #endregion mint_asset_submit_tx_alt

// Finish the test successfully
Ok(())
}
Loading

0 comments on commit 73a6592

Please sign in to comment.