Skip to content

Commit

Permalink
feat(iota-sdk): add pay_iota example (#1978)
Browse files Browse the repository at this point in the history
* Add pay_iota example

* Refactor utils

* Capitalize comments

* Use client method

* Rename variable

* Update crates/iota-sdk/examples/pay_iota.rs

---------

Co-authored-by: Thibault Martinez <[email protected]>
  • Loading branch information
Thoralf-M and thibault-martinez authored Aug 26, 2024
1 parent 30df2be commit 3632ee8
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 21 deletions.
69 changes: 69 additions & 0 deletions crates/iota-sdk/examples/pay_iota.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Copyright (c) 2024 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

//! This example shows how to pay IOTAs to another address.
//!
//! cargo run --example pay_iota
mod utils;

use iota_config::{iota_config_dir, IOTA_KEYSTORE_FILENAME};
use iota_keys::keystore::{AccountKeystore, FileBasedKeystore};
use iota_sdk::{
rpc_types::IotaTransactionBlockResponseOptions,
types::{quorum_driver_types::ExecuteTransactionRequestType, transaction::Transaction},
};
use shared_crypto::intent::Intent;
use utils::setup_for_write;

#[tokio::main]
async fn main() -> Result<(), anyhow::Error> {
// 1) Get the Iota client, the sender and recipient that we will use
// for the transaction
let (iota, sender, recipient) = setup_for_write().await?;

// 2) Get the coin we will use as gas and for the payment
let coins = iota
.coin_read_api()
.get_coins(sender, None, None, None)
.await?;
let gas_coin = coins.data.into_iter().next().unwrap();

let gas_budget = 5_000_000;

// 3) Build the transaction data, to transfer 1_000 NANOS from the gas coin to
// the recipient address
let tx_data = iota
.transaction_builder()
.pay_iota(
sender,
vec![gas_coin.coin_object_id],
vec![recipient],
vec![1_000],
gas_budget,
)
.await?;

// 4) Sign transaction
let keystore = FileBasedKeystore::new(&iota_config_dir()?.join(IOTA_KEYSTORE_FILENAME))?;
let signature = keystore.sign_secure(&sender, &tx_data, Intent::iota_transaction())?;

// 5) Execute the transaction
println!("Executing the transaction...");
let transaction_response = iota
.quorum_driver_api()
.execute_transaction_block(
Transaction::from_data(tx_data, vec![signature]),
IotaTransactionBlockResponseOptions::full_content(),
Some(ExecuteTransactionRequestType::WaitForLocalExecution),
)
.await?;

println!("Transaction sent {}", transaction_response.digest);
println!("Object changes:");
for object_change in transaction_response.object_changes.unwrap() {
println!("{:?}", object_change);
}

Ok(())
}
26 changes: 13 additions & 13 deletions crates/iota-sdk/examples/programmable_transactions_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,55 +34,55 @@ use utils::setup_for_write;

#[tokio::main]
async fn main() -> Result<(), anyhow::Error> {
// 1) get the Iota client, the sender and recipient that we will use
// for the transaction, and find the coin we use as gas
// 1) Get the Iota client, the sender and recipient that we will use
// for the transaction
let (iota, sender, recipient) = setup_for_write().await?;

// we need to find the coin we will use as gas
// We need to find the coin we will use as gas
let coins = iota
.coin_read_api()
.get_coins(sender, None, None, None)
.await?;
let coin = coins.data.into_iter().next().unwrap();

// programmable transactions allows the user to bundle a number of actions into
// Programmable transactions allows the user to bundle a number of actions into
// one transaction
let mut ptb = ProgrammableTransactionBuilder::new();

// 2) split coin
// the amount we want in the new coin, 1000 NANOS
// 2) Split coin
// The amount we want in the new coin, 1000 NANOS
let split_coin_amount = ptb.pure(1000u64)?; // note that we need to specify the u64 type
ptb.command(Command::SplitCoins(
Argument::GasCoin,
vec![split_coin_amount],
));

// 3) transfer the new coin to a different address
// 3) Transfer the new coin to a different address
let argument_address = ptb.pure(recipient)?;
ptb.command(Command::TransferObjects(
vec![Argument::Result(0)],
argument_address,
));

// finish building the transaction block by calling finish on the ptb
let builder = ptb.finish();
// Finish building the transaction block by calling finish on the ptb
let transaction = ptb.finish();

let gas_budget = 5_000_000;
let gas_price = iota.read_api().get_reference_gas_price().await?;
// create the transaction data that will be sent to the network
// Create the transaction data that will be sent to the network
let tx_data = TransactionData::new_programmable(
sender,
vec![coin.object_ref()],
builder,
transaction,
gas_budget,
gas_price,
);

// 4) sign transaction
// 4) Sign transaction
let keystore = FileBasedKeystore::new(&iota_config_dir()?.join(IOTA_KEYSTORE_FILENAME))?;
let signature = keystore.sign_secure(&sender, &tx_data, Intent::iota_transaction())?;

// 5) execute the transaction
// 5) Execute the transaction
print!("Executing the transaction...");
let transaction_response = iota
.quorum_driver_api()
Expand Down
11 changes: 3 additions & 8 deletions crates/iota-sdk/examples/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ pub async fn setup_for_read() -> Result<(IotaClient, IotaAddress), anyhow::Error
}

/// Request tokens from the Faucet for the given address
#[allow(unused_assignments)]
pub async fn request_tokens_from_faucet(
address: IotaAddress,
iota_client: &IotaClient,
Expand Down Expand Up @@ -127,10 +126,8 @@ pub async fn request_tokens_from_faucet(

println!("Faucet request task id: {task_id}");

let mut coin_id = "".to_string();

// wait for the faucet to finish the batch of token requests
loop {
let coin_id = loop {
let resp = client
.get(format!("{IOTA_FAUCET_BASE_URL}/v1/status/{task_id}"))
.send()
Expand All @@ -139,20 +136,18 @@ pub async fn request_tokens_from_faucet(
if text.contains("SUCCEEDED") {
let resp_json: serde_json::Value = serde_json::from_str(&text).unwrap();

coin_id = <&str>::clone(
break <&str>::clone(
&resp_json
.pointer("/status/transferred_gas_objects/sent/0/id")
.unwrap()
.as_str()
.unwrap(),
)
.to_string();

break;
} else {
tokio::time::sleep(Duration::from_secs(1)).await;
}
}
};

// wait until the fullnode has the coin object, and check if it has the same
// owner
Expand Down

0 comments on commit 3632ee8

Please sign in to comment.