diff --git a/bindings/go/examples/tx_command_results/main.go b/bindings/go/examples/tx_command_results/main.go new file mode 100644 index 000000000..9dad8617a --- /dev/null +++ b/bindings/go/examples/tx_command_results/main.go @@ -0,0 +1,76 @@ +// Copyright (c) 2025 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "log" + + sdk "bindings/iota_sdk_ffi" +) + +func main() { + client := sdk.GraphQlClientNewDevnet() + + sender, _ := sdk.AddressFromHex("0x611830d3641a68f94a690dcc25d1f4b0dac948325ac18f6dd32564371735f32c") + + builder := sdk.TransactionBuilderInit(sender, client) + + packageAddr := sdk.AddressStdLib() + moduleName, _ := sdk.NewIdentifier("u64") + functionName, _ := sdk.NewIdentifier("max") + builder.MoveCall( + packageAddr, + moduleName, + functionName, + []*sdk.PtbArgument{sdk.PtbArgumentU64(0), sdk.PtbArgumentU64(1000)}, + nil, + // Assign a name to the result of this command + []string{"res0"}, + ) + + builder.MoveCall( + packageAddr, + moduleName, + functionName, + []*sdk.PtbArgument{sdk.PtbArgumentU64(1000), sdk.PtbArgumentU64(2000)}, + nil, + // Assign a name to the result of this command + []string{"res1"}, + ) + + builder.SplitCoins( + sdk.PtbArgumentGas(), + // Use the named results of previous commands to use as arguments + []*sdk.PtbArgument{sdk.PtbArgumentRes("res0"), sdk.PtbArgumentRes("res1")}, + // For nested results, a tuple or vec can be used to name them + []string{"coin0", "coin1"}, + ) + + // Use named results as arguments + builder.TransferObjects(sender, []*sdk.PtbArgument{sdk.PtbArgumentRes("coin0"), sdk.PtbArgumentRes("coin1")}) + + txn, err := builder.Finish() + if err.(*sdk.SdkFfiError) != nil { + log.Fatalf("Failed to create transaction: %v", err) + } + + txnBytes, err := txn.BcsSerialize() + if err != nil { + log.Fatalf("Failed to serialize transaction: %v", err) + } + log.Printf("Signing Digest: %v", sdk.HexEncode(txn.SigningDigest())) + log.Printf("Txn Bytes: %v", sdk.Base64Encode(txnBytes)) + + skipChecks := bool(false) + res, err := client.DryRunTx(txn, &skipChecks) + if err.(*sdk.SdkFfiError) != nil { + log.Fatalf("Failed to send tx: %v", err) + } + + if res.Error != nil { + log.Fatalf("Failed to send tx: %v", *res.Error) + } + + log.Print("Tx dry run was successful!") +} diff --git a/bindings/kotlin/examples/TxCommandResults.kt b/bindings/kotlin/examples/TxCommandResults.kt new file mode 100644 index 000000000..259b3be4d --- /dev/null +++ b/bindings/kotlin/examples/TxCommandResults.kt @@ -0,0 +1,68 @@ +// Copyright (c) 2025 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import iota_sdk.* +import kotlinx.coroutines.runBlocking + +fun main() = runBlocking { + try { + val client = GraphQlClient.newDevnet() + + val sender = + Address.fromHex( + "0x611830d3641a68f94a690dcc25d1f4b0dac948325ac18f6dd32564371735f32c" + ) + + val builder = TransactionBuilder.init(sender, client) + + val packageAddr = Address.stdLib() + val moduleName = Identifier("u64") + val functionName = Identifier("max") + + builder.moveCall( + packageAddr, + moduleName, + functionName, + listOf(PtbArgument.u64(0u), PtbArgument.u64(1000u)), + // Assign a name to the result of this command + names = listOf("res0"), + ) + + builder.moveCall( + packageAddr, + moduleName, + functionName, + listOf(PtbArgument.u64(1000u), PtbArgument.u64(2000u)), + // Assign a name to the result of this command + names = listOf("res1"), + ) + + builder.splitCoins( + PtbArgument.gas(), + // Use the named results of previous commands to use as arguments + listOf(PtbArgument.res("res0"), PtbArgument.res("res1")), + // For nested results, a tuple or vec can be used to name them + listOf("coin0", "coin1"), + ) + + // Use named results as arguments + builder.transferObjects( + sender, + listOf(PtbArgument.res("coin0"), PtbArgument.res("coin1")), + ) + + val txn = builder.finish() + + println("Signing Digest: ${hexEncode(txn.signingDigest())}") + println("Txn Bytes: ${base64Encode(txn.bcsSerialize())}") + + val res = client.dryRunTx(txn, false) + if (res.error != null) { + throw Exception("Failed to send tx: ${res.error}") + } + + println("Tx dry run was successful!") + } catch (e: Exception) { + e.printStackTrace() + } +} diff --git a/bindings/python/examples/tx_command_results.py b/bindings/python/examples/tx_command_results.py new file mode 100644 index 000000000..3987a2e74 --- /dev/null +++ b/bindings/python/examples/tx_command_results.py @@ -0,0 +1,64 @@ +# Copyright (c) 2025 IOTA Stiftung +# SPDX-License-Identifier: Apache-2.0 + +from lib.iota_sdk_ffi import * + +import asyncio + +async def main(): + try: + client = GraphQlClient.new_devnet() + + sender = Address.from_hex("0x611830d3641a68f94a690dcc25d1f4b0dac948325ac18f6dd32564371735f32c") + + builder = await TransactionBuilder.init(sender, client) + + package_addr = Address.std_lib() + module_name = Identifier("u64") + function_name = Identifier("max") + + builder.move_call( + package_addr, + module_name, + function_name, + [PtbArgument.u64(0), PtbArgument.u64(1000)], + # Assign a name to the result of this command + names=["res0"], + ) + + builder.move_call( + package_addr, + module_name, + function_name, + [PtbArgument.u64(1000), PtbArgument.u64(2000)], + # Assign a name to the result of this command + names=["res1"], + ) + + builder.split_coins( + PtbArgument.gas(), + # Use the named results of previous commands as arguments + [PtbArgument.res("res0"), PtbArgument.res("res1")], + # For nested results, a tuple or vec can be used to name them + ["coin0", "coin1"], + ) + + # Use named results as arguments + builder.transfer_objects(sender, [PtbArgument.res("coin0"), PtbArgument.res("coin1")]) + + txn = await builder.finish() + + print("Signing Digest:", hex_encode(txn.signing_digest())) + print("Txn Bytes:", base64_encode(txn.bcs_serialize())) + + res = await client.dry_run_tx(txn, False) + if res.error is not None: + raise Exception("Failed to send tx:", res.error) + + print("Tx dry run was successful!") + + except Exception as e: + print(f"Error: {e}") + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/crates/iota-sdk/examples/tx_command_results.rs b/crates/iota-sdk/examples/tx_command_results.rs new file mode 100644 index 000000000..1d1f856ba --- /dev/null +++ b/crates/iota-sdk/examples/tx_command_results.rs @@ -0,0 +1,56 @@ +// Copyright (c) 2025 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +use std::str::FromStr; + +use base64ct::Encoding; +use eyre::Result; +use iota_graphql_client::Client; +use iota_transaction_builder::{TransactionBuilder, res, unresolved::Argument}; +use iota_types::Address; + +#[tokio::main] +async fn main() -> Result<()> { + let client = Client::new_devnet(); + + let sender_address = + Address::from_str("0x611830d3641a68f94a690dcc25d1f4b0dac948325ac18f6dd32564371735f32c")?; + + let mut builder = TransactionBuilder::new(sender_address).with_client(client.clone()); + builder + .move_call(Address::STD_LIB, "u64", "max") + .arguments((0u64, 1000u64)) + // Assign a name to the result of this command + .name("res0"); + builder + .move_call(Address::STD_LIB, "u64", "max") + .arguments((1000u64, 2000u64)) + .name("res1"); + + builder + // Use the named results of previous commands to use as arguments + .split_coins(Argument::Gas, [res("res0"), res("res1")]) + // For nested results, a tuple or vec can be used to name them + .name(vec!["coin0", "coin1"]); + + // Use named results as arguments + builder.transfer_objects(sender_address, [res("coin0"), res("coin1")]); + + let tx = builder.to_owned().finish().await?; + + println!("Signing Digest: {}", hex::encode(tx.signing_digest())); + println!( + "Tx Bytes: {}", + base64ct::Base64::encode_string(&bcs::to_bytes(&tx)?) + ); + + let res = client.dry_run_tx(&tx, false).await?; + + if let Some(err) = res.error { + eyre::bail!("Failed to send tx: {err}"); + } + + println!("Tx dry run was successful!"); + + Ok(()) +}