Examples in Rust
The examples for wallet.rs are located in the library's repository. To get access to them, clone the wallet.rs
repository:
git clone -b production https://github.com/iotaledger/wallet.rs.git
cd wallet.rs
You can list all available examples by running the following command:
cargo run --example # lists the available examples
To run an example, you can use the following command, replacing transfer with the desired example:
cargo run --example transfer # execute the `transfer` example
You can find all examples in the examples
subfolder of the project.
Backup and Restore
- Create an account manager and set a password:
let manager = AccountManager::builder().finish().await.unwrap();
manager.set_stronghold_password("password").await.unwrap();
manager.store_mnemonic(SignerType::Stronghold, None).await.unwrap();
- Create your account:
let client_options = ClientOptionsBuilder::new()
.with_node("https://api.lb-0.h.chrysalis-devnet.iota.cafe")?
.build()
.unwrap();
let account_handle = manager
.create_account(client_options)?
.alias("alias")
.initialise()
.await?;
let id = account_handle.id().await;
- You can secure your account in a backup file:
// backup the stored accounts to ./backup/${backup_name}
let backup_path = manager.backup("./backup").await?;
- You can import the backup later, or in another application using the following snippet:
manager.import_accounts(backup_path, "password").await?;
let imported_account_handle = manager.get_account(&id).await?;
let account = account_handle.read().await;
let imported_account = imported_account_handle.read().await;
That's it! You can now backup and restore your account!
You can see the full code for the example in the wallet.rs
repository
Transfer
You use the following example to generate an account and transfer funds.
// Copyright 2021 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0
//! cargo run --example transfer --release
use iota_wallet::{
account_manager::AccountManager,
address::{parse, OutputKind},
client::ClientOptionsBuilder,
message::Transfer,
signing::SignerType,
};
use std::num::NonZeroU64;
#[tokio::main]
async fn main() -> iota_wallet::Result<()> {
let manager = AccountManager::builder().finish().await.unwrap();
manager.set_stronghold_password("password").await.unwrap();
// Get account or create a new one
let account_alias = "alias";
let account = match manager.get_account(account_alias).await {
Ok(account) => account,
_ => {
// first we'll create an example account and store it
manager.store_mnemonic(SignerType::Stronghold, None).await.unwrap();
let client_options = ClientOptionsBuilder::new()
.with_node("https://api.lb-0.h.chrysalis-devnet.iota.cafe")?
.build()
.unwrap();
manager
.create_account(client_options)?
.alias(account_alias)
.initialise()
.await?
}
};
let address = account.generate_address().await?;
println!(
"Send iotas from the faucet to {} and press enter after the transaction got confirmed",
address.address().to_bech32()
);
let mut input = String::new();
std::io::stdin().read_line(&mut input).unwrap();
println!("Sending transfer...");
let message = account
.transfer(
Transfer::builder(
parse("atoi1qzt0nhsf38nh6rs4p6zs5knqp6psgha9wsv74uajqgjmwc75ugupx3y7x0r")?,
NonZeroU64::new(10000000).unwrap(),
Some(OutputKind::SignatureLockedDustAllowance),
)
.finish(),
)
.await?;
println!("Message sent: {}", message.id());
Ok(())
}
Events
wallet.rs
library is able to listen to several supported event. As soon as the event occurs, a provided callback will be triggered.
You can use the following example to fetch an existing Account and listen to transaction events related to that Account :
// Copyright 2021 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0
//! cargo run --example event --release
use iota_wallet::{
account::AccountHandle, account_manager::AccountManager, address::Address, client::ClientOptionsBuilder,
event::on_balance_change, signing::SignerType, Error, Result,
};
use reqwest::Client;
use std::collections::HashMap;
#[tokio::main]
async fn main() -> Result<()> {
let stronghold_password = "password".to_string();
let account_alias = "alice".to_string();
let node_url = "https://api.lb-1.h.chrysalis-devnet.iota.cafe/".to_string();
let faucet_url = "https://faucet.chrysalis-devnet.iota.cafe".to_string();
let account_manager: AccountManager = AccountManager::builder().finish().await?;
account_manager.set_stronghold_password(stronghold_password).await?;
// If no account was previously created, we create one. Otherwise, recover from local storage
// This ensures that the script can be run multiple times
let account: AccountHandle = match account_manager.get_account(&account_alias).await {
Ok(account) => account,
_ => {
account_manager.store_mnemonic(SignerType::Stronghold, None).await?;
let client_options = ClientOptionsBuilder::new().with_node(&node_url)?.build()?;
account_manager
.create_account(client_options)?
.alias(account_alias)
.initialise()
.await?
}
};
// Possible events are: on_balance_change, on_broadcast, on_confirmation_state_change, on_error,
// on_migration_progress, on_new_transaction, on_reattachment, on_stronghold_status_change,
// on_transfer_progress,
on_balance_change(move |event| {
println!("BalanceEvent: {:?}", event);
println!("Press enter to exit");
})
.await;
let address = account.generate_address().await?;
println!("Requesting funds from the faucet to {}", address.address().to_bech32());
get_funds(&address, &faucet_url).await?;
// Wait for event before exit
let mut exit = String::new();
std::io::stdin().read_line(&mut exit).unwrap();
Ok(())
}
// Requests a testnet funds transaction to our generated address
// This API is rate limited: only a request every minute is allowed
async fn get_funds(address: &Address, faucet_url: &str) -> Result<()> {
let mut body = HashMap::new();
body.insert("address", address.address().to_bech32());
let faucet_response = Client::new()
.post(format!("{}/api/plugins/faucet/enqueue", faucet_url))
.json(&body)
.send()
.await
.map_err(|e| Error::ClientError(Box::new(e.into())))?;
println!(
"{}",
faucet_response
.text()
.await
.map_err(|e| Error::ClientError(Box::new(e.into())))?
);
println!("Requested funds");
Ok(())
}
Logger
// Copyright 2020 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0
//! cargo run --example logger --release
use iota_client::common::logger::{logger_init, LoggerConfig, LoggerOutputConfigBuilder};
use iota_wallet::{account_manager::AccountManager, client::ClientOptionsBuilder, signing::SignerType};
use log::LevelFilter;
use std::time::Instant;
#[tokio::main]
async fn main() -> iota_wallet::Result<()> {
// Generates a wallet.log file with logs for debugging
let output_config = LoggerOutputConfigBuilder::new()
.name("wallet.log")
.level_filter(LevelFilter::Debug);
let config = LoggerConfig::build().with_output(output_config).finish();
logger_init(config).unwrap();
let manager = AccountManager::builder()
.with_storage("./backup", None)?
.with_skip_polling()
.finish()
.await?;
manager.set_stronghold_password("password").await?;
// Get account or create a new one
let account_alias = "logger";
let account = match manager.get_account(account_alias).await {
Ok(account) => account,
_ => {
// first we'll create an example account and store it
manager.store_mnemonic(SignerType::Stronghold, None).await.unwrap();
let client_options = ClientOptionsBuilder::new()
.with_node("https://api.lb-0.h.chrysalis-devnet.iota.cafe")?
.build()
.unwrap();
manager
.create_account(client_options)?
.alias(account_alias)
.initialise()
.await?
}
};
let now = Instant::now();
account.sync().await.execute().await?;
println!("Syncing took: {:.2?}", now.elapsed());
println!("Balance: {:?}", account.balance().await?);
let addresses = account.list_unspent_addresses().await?;
println!("Addresses: {}", addresses.len());
let address = account.generate_address().await?;
println!("Generated a new address: {:?}", address);
Ok(())
}