diff --git a/bindings/go/examples/get_transaction/main.go b/bindings/go/examples/get_transaction/main.go new file mode 100644 index 000000000..98b48f36f --- /dev/null +++ b/bindings/go/examples/get_transaction/main.go @@ -0,0 +1,37 @@ +// Copyright (c) 2025 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "fmt" + "log" + + sdk "bindings/iota_sdk_ffi" +) + +func main() { + client := sdk.GraphQlClientNewDevnet() + digest, err := sdk.DigestFromBase58("Agug2GETToZj4Ncw3RJn2KgDUEpVQKG1WaTZVcLcqYnf") + if err != nil { + log.Fatalf("Failed to parse digest: %v", err) + } + + signed_transaction, err := client.Transaction(digest) + if err.(*sdk.SdkFfiError) != nil { + log.Fatalf("Failed to get transaction: %v", err) + } + fmt.Printf("Signed Transaction: %v\n", signed_transaction); + + transaction_effects, err := client.TransactionEffects(digest) + if err.(*sdk.SdkFfiError) != nil { + log.Fatalf("Failed to get transaction effects: %v", err) + } + fmt.Printf("Transaction Effects: %v\n", transaction_effects); + + transaction_data_effects, err := client.TransactionDataEffects(digest) + if err.(*sdk.SdkFfiError) != nil { + log.Fatalf("Failed to get transaction data effects: %v", err) + } + fmt.Printf("Transaction Data Effects: %v\n", transaction_data_effects); +} \ No newline at end of file diff --git a/bindings/kotlin/examples/GetTransaction.kt b/bindings/kotlin/examples/GetTransaction.kt new file mode 100644 index 000000000..dcdc79858 --- /dev/null +++ b/bindings/kotlin/examples/GetTransaction.kt @@ -0,0 +1,25 @@ +// Copyright (c) 2025 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import iota_sdk.GraphQlClient +import iota_sdk.Digest +import kotlinx.coroutines.runBlocking + +fun main() = runBlocking { + try { + val client = GraphQlClient.newDevnet() + val digest = Digest.fromBase58("Agug2GETToZj4Ncw3RJn2KgDUEpVQKG1WaTZVcLcqYnf") + + val signedTransaction = client.transaction(digest) + println("Signed Transaction: ${signedTransaction?.toString()}\n") + + val transactionEffects = client.transactionEffects(digest) + println("Transaction Effects: ${transactionEffects?.toString()}\n") + + val transactionDataEffects = client.transactionDataEffects(digest) + println("Transaction Data Effects: ${transactionDataEffects?.toString()}\n") + } catch (e: Exception) { + e.printStackTrace() + kotlin.system.exitProcess(1) + } +} diff --git a/bindings/python/examples/get_transaction.py b/bindings/python/examples/get_transaction.py new file mode 100644 index 000000000..c002b1070 --- /dev/null +++ b/bindings/python/examples/get_transaction.py @@ -0,0 +1,22 @@ +# Copyright (c) 2025 IOTA Stiftung +# SPDX-License-Identifier: Apache-2.0 + +from lib.iota_sdk_ffi import * + +import asyncio + +async def main(): + client = GraphQlClient.new_devnet() + digest = Digest.from_base58("Agug2GETToZj4Ncw3RJn2KgDUEpVQKG1WaTZVcLcqYnf") + + signed_transaction = await client.transaction(digest) + print(f"Signed Transaction: `{signed_transaction}`\n") + + transaction_effects = await client.transaction_effects(digest) + print(f"Transaction Effects: `{transaction_effects}`\n") + + transaction_data_effects = await client.transaction_data_effects(digest) + print(f"Transaction Data Effects: `{transaction_data_effects}`\n") + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/crates/iota-sdk-graphql-client/src/lib.rs b/crates/iota-sdk-graphql-client/src/lib.rs index aaf7aa2e7..c601e4cb7 100644 --- a/crates/iota-sdk-graphql-client/src/lib.rs +++ b/crates/iota-sdk-graphql-client/src/lib.rs @@ -19,8 +19,8 @@ use error::{Error, Kind}; use futures::Stream; use iota_types::{ Address, CheckpointSequenceNumber, CheckpointSummary, Digest, IdentifierRef, MovePackage, - Object, ObjectId, SignedTransaction, StructTag, Transaction, TransactionEffects, - TransactionKind, TypeTag, UserSignature, + Object, ObjectId, SenderSignedTransaction, SignedTransaction, StructTag, Transaction, + TransactionEffects, TransactionKind, TypeTag, UserSignature, framework::Coin, iota_names::{NameFormat, NameRegistration, name::Name}, }; @@ -1130,24 +1130,17 @@ impl Client { }); let response = self.run_query(&operation).await?; - match response - .transaction_block - .map(|tx| (tx.bcs, tx.effects, tx.signatures)) - { - Some((Some(bcs), Some(effects), Some(sigs))) => { + match response.transaction_block.map(|tx| (tx.bcs, tx.effects)) { + Some((Some(bcs), Some(effects))) => { let bcs = base64ct::Base64::decode_vec(bcs.0.as_str())?; let effects = base64ct::Base64::decode_vec(effects.bcs.unwrap().0.as_str())?; - let signatures = sigs - .iter() - .map(|s| UserSignature::from_base64(&s.0)) - .collect::, _>>()?; - let transaction: Transaction = bcs::from_bytes(&bcs)?; - let tx = SignedTransaction { - transaction, - signatures, - }; + let transaction: SenderSignedTransaction = bcs::from_bytes(&bcs)?; let effects: TransactionEffects = bcs::from_bytes(&effects)?; - Ok(Some(TransactionDataEffects { tx, effects })) + + Ok(Some(TransactionDataEffects { + tx: transaction.0, + effects, + })) } _ => Ok(None), } @@ -1252,26 +1245,19 @@ impl Client { txc.nodes .into_iter() .map(|node| { - let (Some(bcs), Some(effects), Some(sigs)) = - (node.bcs, node.effects, node.signatures) - else { + let (Some(bcs), Some(effects)) = (node.bcs, node.effects) else { return Err(Error::empty_response_error()); }; let bcs = base64ct::Base64::decode_vec(bcs.0.as_str())?; let effects = base64ct::Base64::decode_vec(effects.bcs.as_ref().unwrap().0.as_str())?; - - let sigs = sigs - .iter() - .map(|s| UserSignature::from_base64(&s.0)) - .collect::, _>>()?; - let tx: Transaction = bcs::from_bytes(&bcs)?; - let tx = SignedTransaction { - transaction: tx, - signatures: sigs, - }; + let transaction: SenderSignedTransaction = bcs::from_bytes(&bcs)?; let effects: TransactionEffects = bcs::from_bytes(&effects)?; - Ok(TransactionDataEffects { tx, effects }) + + Ok(TransactionDataEffects { + tx: transaction.0, + effects, + }) }) .collect::>>()? }; @@ -1676,12 +1662,12 @@ impl Client { mod tests { use base64ct::Encoding; use futures::StreamExt; - use iota_types::{Address, Ed25519PublicKey, ObjectId, TypeTag}; + use iota_types::{Address, Digest, Ed25519PublicKey, ObjectId, TypeTag}; use tokio::time; use crate::{ BcsName, Client, DEVNET_HOST, Direction, LOCAL_HOST, MAINNET_HOST, PaginationFilter, - TESTNET_HOST, faucet::FaucetClient, + TESTNET_HOST, faucet::FaucetClient, query_types::TransactionsFilter, }; const NUM_COINS_FROM_FAUCET: usize = 5; @@ -2308,4 +2294,35 @@ mod tests { client.rpc_server() ); } + + #[tokio::test] + async fn test_transaction_data_effects() { + let client = Client::new_devnet(); + + client + .transaction_data_effects( + Digest::from_base58("Agug2GETToZj4Ncw3RJn2KgDUEpVQKG1WaTZVcLcqYnf").unwrap(), + ) + .await + .unwrap() + .unwrap(); + } + + #[tokio::test] + async fn test_transactions_data_effects() { + let client = Client::new_devnet(); + + client + .transactions_data_effects( + TransactionsFilter { + transaction_ids: Some(vec![ + "Agug2GETToZj4Ncw3RJn2KgDUEpVQKG1WaTZVcLcqYnf".to_string(), + ]), + ..Default::default() + }, + PaginationFilter::default(), + ) + .await + .unwrap(); + } } diff --git a/crates/iota-sdk-graphql-client/src/query_types/transaction.rs b/crates/iota-sdk-graphql-client/src/query_types/transaction.rs index ad1b03890..7875dd7b1 100644 --- a/crates/iota-sdk-graphql-client/src/query_types/transaction.rs +++ b/crates/iota-sdk-graphql-client/src/query_types/transaction.rs @@ -138,7 +138,6 @@ pub struct TransactionBlock { pub struct TransactionBlockWithEffects { pub bcs: Option, pub effects: Option, - pub signatures: Option>, } #[derive(cynic::QueryFragment, Debug)] diff --git a/crates/iota-sdk/examples/get_transaction.rs b/crates/iota-sdk/examples/get_transaction.rs new file mode 100644 index 000000000..98d2792e5 --- /dev/null +++ b/crates/iota-sdk/examples/get_transaction.rs @@ -0,0 +1,28 @@ +// Copyright (c) 2025 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +use iota_graphql_client::{Client, error::Result}; +use iota_types::Digest; + +#[tokio::main] +async fn main() -> Result<()> { + let client = Client::new_devnet(); + let digest = Digest::from_base58("Agug2GETToZj4Ncw3RJn2KgDUEpVQKG1WaTZVcLcqYnf")?; + + let signed_transaction = client.transaction(digest).await?.expect("tx not found"); + println!("Signed Transaction: {signed_transaction:#?}\n"); + + let transaction_effects = client + .transaction_effects(digest) + .await? + .expect("tx not found"); + println!("Transaction Effects: {transaction_effects:#?}\n"); + + let transaction_data_effects = client + .transaction_data_effects(digest) + .await? + .expect("tx not found"); + println!("Transaction Data Effects: {transaction_data_effects:#?}"); + + Ok(()) +}