From 2afafe7fbc4434b911ec90c80f70f16284d74e29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thoralf=20M=C3=BCller?= Date: Tue, 14 Oct 2025 10:56:45 +0200 Subject: [PATCH 1/8] feat: add tx_command_results example --- .../go/examples/tx_command_results/main.go | 76 +++++++++++++++++++ bindings/kotlin/examples/TxCommandResults.kt | 68 +++++++++++++++++ .../python/examples/tx_command_results.py | 64 ++++++++++++++++ .../iota-sdk/examples/tx_command_results.rs | 56 ++++++++++++++ 4 files changed, 264 insertions(+) create mode 100644 bindings/go/examples/tx_command_results/main.go create mode 100644 bindings/kotlin/examples/TxCommandResults.kt create mode 100644 bindings/python/examples/tx_command_results.py create mode 100644 crates/iota-sdk/examples/tx_command_results.rs 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..90942445d --- /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.AddressFromHex("0x1") + 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..d94a7e561 --- /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.fromHex("0x1") + 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..42e7ea117 --- /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.from_hex("0x1") + 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..d90a2b9c3 --- /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::ONE, "u64", "max") + .arguments((0u64, 1000u64)) + // Assign a name to the result of this command + .name("res0"); + builder + .move_call(Address::ONE, "u64", "max") + .arguments((1000u64, 2000u64)) + .name("res1"); + + builder + // Use the named results of previous commands to use as arguments + .split_coins(Argument::Gas, vec![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, vec![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(()) +} From ce6e4f54113aa72b5d369886a13aa7cd3b00ff90 Mon Sep 17 00:00:00 2001 From: Thoralf-M <46689931+Thoralf-M@users.noreply.github.com> Date: Tue, 14 Oct 2025 13:40:29 +0200 Subject: [PATCH 2/8] Apply suggestions from code review Co-authored-by: DaughterOfMars --- crates/iota-sdk/examples/tx_command_results.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/iota-sdk/examples/tx_command_results.rs b/crates/iota-sdk/examples/tx_command_results.rs index d90a2b9c3..fe4116673 100644 --- a/crates/iota-sdk/examples/tx_command_results.rs +++ b/crates/iota-sdk/examples/tx_command_results.rs @@ -29,12 +29,12 @@ async fn main() -> Result<()> { builder // Use the named results of previous commands to use as arguments - .split_coins(Argument::Gas, vec![res("res0"), res("res1")]) + .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, vec![res("coin0"), res("coin1")]); + builder.transfer_objects(sender_address, [res("coin0"), res("coin1")]); let tx = builder.to_owned().finish().await?; From ad713609b4a2e3511da019fad2580bd53a91dfe9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thoralf=20M=C3=BCller?= Date: Tue, 14 Oct 2025 13:55:47 +0200 Subject: [PATCH 3/8] update to latest changes --- bindings/go/examples/tx_command_results/main.go | 2 +- bindings/kotlin/examples/TxCommandResults.kt | 2 +- bindings/python/examples/tx_command_results.py | 2 +- crates/iota-sdk/examples/tx_command_results.rs | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/bindings/go/examples/tx_command_results/main.go b/bindings/go/examples/tx_command_results/main.go index 90942445d..9dad8617a 100644 --- a/bindings/go/examples/tx_command_results/main.go +++ b/bindings/go/examples/tx_command_results/main.go @@ -16,7 +16,7 @@ func main() { builder := sdk.TransactionBuilderInit(sender, client) - packageAddr, _ := sdk.AddressFromHex("0x1") + packageAddr := sdk.AddressStdLib() moduleName, _ := sdk.NewIdentifier("u64") functionName, _ := sdk.NewIdentifier("max") builder.MoveCall( diff --git a/bindings/kotlin/examples/TxCommandResults.kt b/bindings/kotlin/examples/TxCommandResults.kt index d94a7e561..0385b95b8 100644 --- a/bindings/kotlin/examples/TxCommandResults.kt +++ b/bindings/kotlin/examples/TxCommandResults.kt @@ -15,7 +15,7 @@ fun main() = runBlocking { val builder = TransactionBuilder.init(sender, client) - val packageAddr = Address.fromHex("0x1") + val packageAddr = Address.stdLib() val moduleName = Identifier("u64") val functionName = Identifier("max") diff --git a/bindings/python/examples/tx_command_results.py b/bindings/python/examples/tx_command_results.py index 42e7ea117..3987a2e74 100644 --- a/bindings/python/examples/tx_command_results.py +++ b/bindings/python/examples/tx_command_results.py @@ -13,7 +13,7 @@ async def main(): builder = await TransactionBuilder.init(sender, client) - package_addr = Address.from_hex("0x1") + package_addr = Address.std_lib() module_name = Identifier("u64") function_name = Identifier("max") diff --git a/crates/iota-sdk/examples/tx_command_results.rs b/crates/iota-sdk/examples/tx_command_results.rs index fe4116673..1d1f856ba 100644 --- a/crates/iota-sdk/examples/tx_command_results.rs +++ b/crates/iota-sdk/examples/tx_command_results.rs @@ -18,12 +18,12 @@ async fn main() -> Result<()> { let mut builder = TransactionBuilder::new(sender_address).with_client(client.clone()); builder - .move_call(Address::ONE, "u64", "max") + .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::ONE, "u64", "max") + .move_call(Address::STD_LIB, "u64", "max") .arguments((1000u64, 2000u64)) .name("res1"); From bcca522ac39ad71089ac3d508872b20dc6dbe1aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thoralf=20M=C3=BCller?= Date: Tue, 14 Oct 2025 13:56:08 +0200 Subject: [PATCH 4/8] fmt with 4 spaces --- bindings/kotlin/examples/TxCommandResults.kt | 98 ++++++++++---------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/bindings/kotlin/examples/TxCommandResults.kt b/bindings/kotlin/examples/TxCommandResults.kt index 0385b95b8..259b3be4d 100644 --- a/bindings/kotlin/examples/TxCommandResults.kt +++ b/bindings/kotlin/examples/TxCommandResults.kt @@ -5,64 +5,64 @@ import iota_sdk.* import kotlinx.coroutines.runBlocking fun main() = runBlocking { - try { - val client = GraphQlClient.newDevnet() + try { + val client = GraphQlClient.newDevnet() - val sender = - Address.fromHex( - "0x611830d3641a68f94a690dcc25d1f4b0dac948325ac18f6dd32564371735f32c" - ) + val sender = + Address.fromHex( + "0x611830d3641a68f94a690dcc25d1f4b0dac948325ac18f6dd32564371735f32c" + ) - val builder = TransactionBuilder.init(sender, client) + val builder = TransactionBuilder.init(sender, client) - val packageAddr = Address.stdLib() - val moduleName = Identifier("u64") - val functionName = Identifier("max") + 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(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.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"), - ) + 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() + // Use named results as arguments + builder.transferObjects( + sender, + listOf(PtbArgument.res("coin0"), PtbArgument.res("coin1")), + ) - println("Signing Digest: ${hexEncode(txn.signingDigest())}") - println("Txn Bytes: ${base64Encode(txn.bcsSerialize())}") + val txn = builder.finish() - val res = client.dryRunTx(txn, false) - if (res.error != null) { - throw Exception("Failed to send tx: ${res.error}") - } + println("Signing Digest: ${hexEncode(txn.signingDigest())}") + println("Txn Bytes: ${base64Encode(txn.bcsSerialize())}") - println("Tx dry run was successful!") - } catch (e: Exception) { - e.printStackTrace() + 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() + } } From 783acbadf4a63539ed9840f59f6d8475e165e9e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thoralf=20M=C3=BCller?= Date: Thu, 16 Oct 2025 12:15:45 +0200 Subject: [PATCH 5/8] remove .to_owned() --- crates/iota-sdk/examples/tx_command_results.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/iota-sdk/examples/tx_command_results.rs b/crates/iota-sdk/examples/tx_command_results.rs index 1d1f856ba..07c4524fc 100644 --- a/crates/iota-sdk/examples/tx_command_results.rs +++ b/crates/iota-sdk/examples/tx_command_results.rs @@ -36,7 +36,7 @@ async fn main() -> Result<()> { // Use named results as arguments builder.transfer_objects(sender_address, [res("coin0"), res("coin1")]); - let tx = builder.to_owned().finish().await?; + let tx = builder.finish().await?; println!("Signing Digest: {}", hex::encode(tx.signing_digest())); println!( From f7d3ca04c3d3f20e1246b65f25c8903a2617ff9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thoralf=20M=C3=BCller?= Date: Thu, 16 Oct 2025 13:47:01 +0200 Subject: [PATCH 6/8] provide false directly --- bindings/go/examples/tx_command_results/main.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bindings/go/examples/tx_command_results/main.go b/bindings/go/examples/tx_command_results/main.go index 9dad8617a..a99219cbb 100644 --- a/bindings/go/examples/tx_command_results/main.go +++ b/bindings/go/examples/tx_command_results/main.go @@ -62,8 +62,7 @@ func main() { 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) + res, err := client.DryRunTx(txn, false) if err.(*sdk.SdkFfiError) != nil { log.Fatalf("Failed to send tx: %v", err) } From bbb0042cb65aa3b94acd91792d9214448ff7786e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thoralf=20M=C3=BCller?= Date: Thu, 16 Oct 2025 15:12:04 +0200 Subject: [PATCH 7/8] Use to base64 method --- bindings/go/examples/tx_command_results/main.go | 4 ++-- bindings/kotlin/examples/TxCommandResults.kt | 2 +- bindings/python/examples/tx_command_results.py | 2 +- crates/iota-sdk/examples/tx_command_results.rs | 5 +---- 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/bindings/go/examples/tx_command_results/main.go b/bindings/go/examples/tx_command_results/main.go index a99219cbb..6140bb9d9 100644 --- a/bindings/go/examples/tx_command_results/main.go +++ b/bindings/go/examples/tx_command_results/main.go @@ -55,12 +55,12 @@ func main() { log.Fatalf("Failed to create transaction: %v", err) } - txnBytes, err := txn.BcsSerialize() + txnBase64, err := txn.ToBase64() 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)) + log.Printf("Txn Bytes: %v", txnBase64) res, err := client.DryRunTx(txn, false) if err.(*sdk.SdkFfiError) != nil { diff --git a/bindings/kotlin/examples/TxCommandResults.kt b/bindings/kotlin/examples/TxCommandResults.kt index 259b3be4d..2bc90ef0c 100644 --- a/bindings/kotlin/examples/TxCommandResults.kt +++ b/bindings/kotlin/examples/TxCommandResults.kt @@ -54,7 +54,7 @@ fun main() = runBlocking { val txn = builder.finish() println("Signing Digest: ${hexEncode(txn.signingDigest())}") - println("Txn Bytes: ${base64Encode(txn.bcsSerialize())}") + println("Txn Bytes: ${txn.toBase64()}") val res = client.dryRunTx(txn, false) if (res.error != null) { diff --git a/bindings/python/examples/tx_command_results.py b/bindings/python/examples/tx_command_results.py index 3987a2e74..53e49c43e 100644 --- a/bindings/python/examples/tx_command_results.py +++ b/bindings/python/examples/tx_command_results.py @@ -49,7 +49,7 @@ async def main(): txn = await builder.finish() print("Signing Digest:", hex_encode(txn.signing_digest())) - print("Txn Bytes:", base64_encode(txn.bcs_serialize())) + print("Txn Bytes:", txn.to_base64()) res = await client.dry_run_tx(txn, False) if res.error is not None: diff --git a/crates/iota-sdk/examples/tx_command_results.rs b/crates/iota-sdk/examples/tx_command_results.rs index 07c4524fc..ab12f804e 100644 --- a/crates/iota-sdk/examples/tx_command_results.rs +++ b/crates/iota-sdk/examples/tx_command_results.rs @@ -39,10 +39,7 @@ async fn main() -> Result<()> { let tx = builder.finish().await?; println!("Signing Digest: {}", hex::encode(tx.signing_digest())); - println!( - "Tx Bytes: {}", - base64ct::Base64::encode_string(&bcs::to_bytes(&tx)?) - ); + println!("Tx Bytes: {}", tx.to_base64()?); let res = client.dry_run_tx(&tx, false).await?; From 8896c5bb987716f4483bc170bec5102ddf646bc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thoralf=20M=C3=BCller?= Date: Thu, 16 Oct 2025 15:16:28 +0200 Subject: [PATCH 8/8] rm unused import --- crates/iota-sdk/examples/tx_command_results.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/iota-sdk/examples/tx_command_results.rs b/crates/iota-sdk/examples/tx_command_results.rs index ab12f804e..e6726fb50 100644 --- a/crates/iota-sdk/examples/tx_command_results.rs +++ b/crates/iota-sdk/examples/tx_command_results.rs @@ -3,7 +3,6 @@ use std::str::FromStr; -use base64ct::Encoding; use eyre::Result; use iota_graphql_client::Client; use iota_transaction_builder::{TransactionBuilder, res, unresolved::Argument};