diff --git a/contracts/examples/multisig/interact/src/multisig_interact.rs b/contracts/examples/multisig/interact/src/multisig_interact.rs index d80ab639f7..65b6c0dbb1 100644 --- a/contracts/examples/multisig/interact/src/multisig_interact.rs +++ b/contracts/examples/multisig/interact/src/multisig_interact.rs @@ -5,10 +5,7 @@ mod multisig_interact_state; mod multisig_interact_wegld; use clap::Parser; -use multisig::{ - multisig_perform::ProxyTrait as _, multisig_propose::ProxyTrait as _, multisig_proxy, - ProxyTrait as _, -}; +use multisig::multisig_proxy; use multisig_interact_config::Config; use multisig_interact_state::State; use multiversx_sc_scenario::{ @@ -25,7 +22,7 @@ use multiversx_sc_snippets::{ api::StaticApi, bech32, scenario_format::interpret_trait::InterpreterContext, scenario_model::*, ContractInfo, }, - tokio, Interactor, InteractorPrepareAsync, StepBuffer, + tokio, Interactor, InteractorPrepareAsync, }; const SYSTEM_SC_BECH32: &str = "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u"; @@ -238,8 +235,8 @@ impl MultisigInteract { } async fn perform_action(&mut self, action_id: usize, gas_expr: u64) { - if !self.quorum_reached(action_id).await && !self.sign(action_id).await { - return; + if !self.quorum_reached(action_id).await { + self.sign(&[action_id]).await } println!("quorum reached for action `{action_id}`"); @@ -257,36 +254,43 @@ impl MultisigInteract { println!("successfully performed action `{action_id}`"); } - async fn perform_actions(&mut self, actions: Vec, gas_expr: &str) { - let mut steps = Vec::new(); - for action_id in actions.iter() { - if !self.quorum_reached(*action_id).await && !self.sign(*action_id).await { - continue; + async fn perform_actions(&mut self, action_ids: Vec, gas_expr: u64) { + let multisig_address = self.state.multisig().to_address(); + + let mut actions_no_quorum_reached = Vec::new(); + for &action_id in &action_ids { + if self.quorum_reached(action_id).await { + println!("quorum reached for action `{action_id}`"); + } else { + actions_no_quorum_reached.push(action_id) } - println!("quorum reached for action `{action_id}`"); + } - let typed_sc_call = ScCallStep::new() - .call(self.state.multisig().perform_action_endpoint(action_id)) - .from(&self.wallet_address) - .gas_limit(gas_expr); + self.sign(&actions_no_quorum_reached).await; - steps.push(typed_sc_call); + let from = &self.wallet_address; + let mut buffer = self.interactor.homogenous_call_buffer(); + for action_id in action_ids { + buffer.push_tx(|tx| { + tx.from(from) + .to(&multisig_address) + .gas(gas_expr) + .typed(multisig_proxy::MultisigProxy) + .perform_action_endpoint(action_id) + .returns(ReturnsResult) + }); } - self.interactor - .multi_sc_exec(StepBuffer::from_sc_call_vec(&mut steps)) - .await; + let deployed_addresses = buffer.run().await; - for (i, action_id) in actions.iter().enumerate() { - if !steps[i].response().is_success() { + for (action_id, address) in deployed_addresses.iter().enumerate() { + println!("successfully performed action `{action_id}`"); + if address.is_some() { println!( - "perform action `{action_id}` failed with: {}", - steps[i].response().tx_error - ); - continue; + "new deployed address for action `{action_id}: {:#?}`", + address.clone().into_option().unwrap() + ) } - - println!("successfully performed action `{action_id}`"); } } @@ -314,42 +318,45 @@ impl MultisigInteract { .await } - async fn sign(&mut self, action_id: usize) -> bool { - println!("signing action `{action_id}`..."); - let mut steps = Vec::new(); - for signer in self.board().iter() { - if self.signed(signer, action_id).await { - println!( - "{} - already signed action `{action_id}`", - bech32::encode(signer) - ); - continue; + async fn sign(&mut self, action_ids: &[usize]) { + println!("signing actions `{action_ids:?}`..."); + let multisig_address = self.state.multisig().to_address(); + + let mut pending_signers = Vec::<(Address, usize)>::new(); + for &action_id in action_ids { + for signer in self.board().iter() { + if self.signed(signer, action_id).await { + println!( + "{} - already signed action `{action_id}`", + bech32::encode(signer) + ); + } else { + pending_signers.push((signer.clone(), action_id)); + } } + } - let typed_sc_call = ScCallStep::new() - .call(self.state.multisig().sign(action_id)) - .from(signer) - .gas_limit("15,000,000"); - - steps.push(typed_sc_call); + let mut buffer = self.interactor.homogenous_call_buffer(); + for (signer, action_id) in pending_signers { + buffer.push_tx(|tx| { + tx.from(signer) + .to(&multisig_address) + .gas(15_000_000u64) + .typed(multisig_proxy::MultisigProxy) + .sign(action_id) + }); } - self.interactor - .multi_sc_exec(StepBuffer::from_sc_call_vec(&mut steps)) - .await; + buffer.run().await; - for step in steps.iter() { - if !step.response().is_success() { - println!( - "perform sign `{action_id}` failed with: {}", - step.response().tx_error - ); - return false; - } - } + println!("successfully performed sign action `{action_ids:?}`"); + } - println!("successfully performed sign action `{action_id}`"); - true + async fn sign_if_quorum_not_reached(&mut self, action_id: usize) { + if !self.quorum_reached(action_id).await { + self.sign(&[action_id]).await; + } + println!("quorum reached for action `{action_id}`"); } async fn dns_register(&mut self, name: &str) { diff --git a/contracts/examples/multisig/interact/src/multisig_interact_nfts.rs b/contracts/examples/multisig/interact/src/multisig_interact_nfts.rs index 62314ef63c..61788f99af 100644 --- a/contracts/examples/multisig/interact/src/multisig_interact_nfts.rs +++ b/contracts/examples/multisig/interact/src/multisig_interact_nfts.rs @@ -71,10 +71,7 @@ impl MultisigInteract { println!("perfoming issue collection with all roles action `{action_id}`..."); - if !self.quorum_reached(action_id).await && !self.sign(action_id).await { - return; - } - println!("quorum reached for action `{action_id}`"); + self.sign_if_quorum_not_reached(action_id).await; let new_token_id = self .interactor @@ -127,10 +124,8 @@ impl MultisigInteract { println!("perfoming issue collection action `{action_id}`..."); - if !self.quorum_reached(action_id).await && !self.sign(action_id).await { - return; - } - println!("quorum reached for action `{action_id}`"); + self.sign_if_quorum_not_reached(action_id).await; + let new_token_id = self .interactor .tx() @@ -189,17 +184,20 @@ impl MultisigInteract { println!("creating items..."); let multisig_address = self.state.multisig().to_address(); - let mut steps = Vec::new(); + let mut buffer = self.interactor.homogenous_call_buffer(); for item_index in 0..NUM_ITEMS { let item_name = format!("Test collection item #{item_index}"); let image_cid = format!( "https://ipfs.io/ipfs/QmYyAaEf1phJS5mN6wfou5de5GbpUddBxTY1VekKcjd5PC/nft{item_index:02}.png" ); - let typed_sc_call = ScCallStep::new() - .call( - self.state.multisig().propose_async_call( + buffer.push_tx(|tx| { + tx.from(&self.wallet_address) + .to(&multisig_address) + .gas(10_000_000u64) + .typed(multisig_proxy::MultisigProxy) + .propose_async_call( &multisig_address, 0u64, FunctionCall::new("ESDTNFTCreate") @@ -210,34 +208,16 @@ impl MultisigInteract { .argument(&Empty) .argument(&METADATA) .argument(&image_cid), - ), - ) - .from(&self.wallet_address) - .gas_limit("10,000,000"); - - steps.push(typed_sc_call); + ) + .returns(ReturnsResult) + }); } - self.interactor - .multi_sc_exec(StepBuffer::from_sc_call_vec(&mut steps)) - .await; - - let mut actions = Vec::new(); - for step in steps.iter() { - let result = step.result(); - if result.is_err() { - println!( - "propose ESDTNFTCreate failed with: {}", - result.err().unwrap() - ); - return; - } - - let action_id = result.unwrap(); + let action_ids = buffer.run().await; + for action_id in action_ids.iter() { println!("successfully proposed ESDTNFTCreate action `{action_id}`"); - actions.push(action_id); } - self.perform_actions(actions, "30,000,000").await; + self.perform_actions(action_ids, 30_000_000u64).await; } } diff --git a/contracts/examples/multisig/src/multisig_perform.rs b/contracts/examples/multisig/src/multisig_perform.rs index ef7a3ec257..3024df2696 100644 --- a/contracts/examples/multisig/src/multisig_perform.rs +++ b/contracts/examples/multisig/src/multisig_perform.rs @@ -167,15 +167,13 @@ pub trait MultisigPerformModule: &call_data.endpoint_name, call_data.arguments.as_multi(), ); - self.tx() - .to(&call_data.to) + .to(call_data.to) + .egld(call_data.egld_amount) + .gas(gas) .raw_call(call_data.endpoint_name) .arguments_raw(call_data.arguments.into()) - .gas(gas) - .egld(&call_data.egld_amount) .transfer_execute(); - OptionalValue::None }, Action::SendAsyncCall(call_data) => { @@ -214,15 +212,14 @@ pub trait MultisigPerformModule: ); let new_address = self .tx() + .egld(amount) .gas(gas_left) - .egld(&amount) .raw_deploy() - .arguments_raw(arguments.into()) .from_source(source) .code_metadata(code_metadata) + .arguments_raw(arguments.into()) .returns(ReturnsNewManagedAddress) .sync_call(); - OptionalValue::Some(new_address) }, Action::SCUpgradeFromSource { @@ -242,16 +239,15 @@ pub trait MultisigPerformModule: gas_left, arguments.as_multi(), ); - self.tx() - .to(&sc_address) + .to(sc_address) + .egld(amount) + .gas(gas_left) .raw_upgrade() - .arguments_raw(arguments.into()) - .egld(&amount) .from_source(source) .code_metadata(code_metadata) + .arguments_raw(arguments.into()) .upgrade_async_call_and_exit(); - OptionalValue::None }, } diff --git a/framework/scenario/src/scenario/model/transaction/tx_response.rs b/framework/scenario/src/scenario/model/transaction/tx_response.rs index 440db8258a..984d9ed810 100644 --- a/framework/scenario/src/scenario/model/transaction/tx_response.rs +++ b/framework/scenario/src/scenario/model/transaction/tx_response.rs @@ -208,11 +208,13 @@ impl TxResponse { let is_issue_semi_fungible = prev_tx.data.starts_with("issueSemiFungible@"); let is_issue_non_fungible = prev_tx.data.starts_with("issueNonFungible@"); let is_register_meta_esdt = prev_tx.data.starts_with("registerMetaESDT@"); + let is_register_and_set_all_roles_esdt = prev_tx.data.starts_with("registerAndSetAllRoles@"); if !is_issue_fungible && !is_issue_semi_fungible && !is_issue_non_fungible && !is_register_meta_esdt + && !is_register_and_set_all_roles_esdt { continue; } @@ -2370,4 +2372,266 @@ mod tests { assert_eq!(tx_response.new_issued_token_identifier, expected) } + + #[test] + fn test_multisig_issue_nft_and_set_all_roles() { + let data = r#" +{ + "data": { + "transaction": { + "type": "normal", + "processingTypeOnSource": "SCInvoking", + "processingTypeOnDestination": "SCInvoking", + "hash": "08582bc19734ad82d7390be88463c948e5d9f026f4b8f0bfc57620957c3433bd", + "nonce": 53, + "round": 3050972, + "epoch": 1246, + "value": "0", + "receiver": "erd1qqqqqqqqqqqqqpgqrp3n58vp2dmcaur4whazxngvuhac4xwqa4sq2pjl73", + "sender": "erd1uv40ahysflse896x4ktnh6ecx43u7cmy9wnxnvcyp7deg299a4sq6vaywa", + "gasPrice": 1000000000, + "gasLimit": 80000000, + "gasUsed": 80000000, + "data": "cGVyZm9ybUFjdGlvbkAwMQ==", + "signature": "cb67645595cee5f7967d8d85af05bb7db73e80d9b97611796819249d87cd174b69b4abfc2a3fbe52df1aec965bdea921f7eb34d2b1118aa480699ad1dc85790a", + "sourceShard": 0, + "destinationShard": 0, + "blockNonce": 2984930, + "blockHash": "644ae8703b826a23e89429953919ec37f875e34a547ea9f7edd53fb71a99c746", + "notarizedAtSourceInMetaNonce": 2988311, + "NotarizedAtSourceInMetaHash": "4f608a72e654dd9f466801cd489be8ee1a73fbcd77b128559cd46182d3b9455a", + "notarizedAtDestinationInMetaNonce": 2988311, + "notarizedAtDestinationInMetaHash": "4f608a72e654dd9f466801cd489be8ee1a73fbcd77b128559cd46182d3b9455a", + "miniblockType": "TxBlock", + "miniblockHash": "c5a73671bc1d37835ddd15b926157721bc83203ec4e00cd48ae0d46015cb5f0b", + "hyperblockNonce": 2988311, + "hyperblockHash": "4f608a72e654dd9f466801cd489be8ee1a73fbcd77b128559cd46182d3b9455a", + "timestamp": 1712305832, + "smartContractResults": [ + { + "hash": "b0b3c8df519c33b314c0ee3d25abae6f17c4432fb3382676ce17a42690811cff", + "nonce": 0, + "value": 50000000000000000, + "receiver": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "sender": "erd1qqqqqqqqqqqqqpgqrp3n58vp2dmcaur4whazxngvuhac4xwqa4sq2pjl73", + "data": "registerAndSetAllRoles@54657374436f6c6c656374696f6e31@54455354434f4c4c31@4e4654@@98fa4ff554b9c6990ce577fbb816a271f690dcbd6b148f6583fe7692868ae538@08582bc19734ad82d7390be88463c948e5d9f026f4b8f0bfc57620957c3433bd@5e2338", + "prevTxHash": "08582bc19734ad82d7390be88463c948e5d9f026f4b8f0bfc57620957c3433bd", + "originalTxHash": "08582bc19734ad82d7390be88463c948e5d9f026f4b8f0bfc57620957c3433bd", + "gasLimit": 73052300, + "gasPrice": 1000000000, + "callType": 1, + "originalSender": "erd1uv40ahysflse896x4ktnh6ecx43u7cmy9wnxnvcyp7deg299a4sq6vaywa", + "operation": "transfer", + "function": "registerAndSetAllRoles" + }, + { + "hash": "5ae4f74e134e4fa63c8b92e06ff12b2a4b544233d01d80db6a922af35ee55356", + "nonce": 1, + "value": 196430610000000, + "receiver": "erd1qqqqqqqqqqqqqpgqrp3n58vp2dmcaur4whazxngvuhac4xwqa4sq2pjl73", + "sender": "erd1qqqqqqqqqqqqqpgqrp3n58vp2dmcaur4whazxngvuhac4xwqa4sq2pjl73", + "data": "@6f6b", + "prevTxHash": "c4a24b01b48d32308636310e2d335d6ed1f34dcbdfc1133aed7995e78e831c18", + "originalTxHash": "08582bc19734ad82d7390be88463c948e5d9f026f4b8f0bfc57620957c3433bd", + "gasLimit": 0, + "gasPrice": 1000000000, + "callType": 0, + "operation": "transfer", + "isRefund": true + }, + { + "hash": "7589c1ad622d8a9ab2f186731fc82aeeab0aea5a8198cb94b6eba85a966e7962", + "nonce": 0, + "value": 0, + "receiver": "erd1llllllllllllllllllllllllllllllllllllllllllllllllluqq2m3f0f", + "sender": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "data": "ESDTSetBurnRoleForAll@54455354434f4c4c312d356161383063", + "prevTxHash": "b0b3c8df519c33b314c0ee3d25abae6f17c4432fb3382676ce17a42690811cff", + "originalTxHash": "08582bc19734ad82d7390be88463c948e5d9f026f4b8f0bfc57620957c3433bd", + "gasLimit": 0, + "gasPrice": 1000000000, + "callType": 0, + "originalSender": "erd1uv40ahysflse896x4ktnh6ecx43u7cmy9wnxnvcyp7deg299a4sq6vaywa", + "logs": { + "address": "erd1llllllllllllllllllllllllllllllllllllllllllllllllluqq2m3f0f", + "events": [ + { + "address": "erd1llllllllllllllllllllllllllllllllllllllllllllllllluqq2m3f0f", + "identifier": "completedTxEvent", + "topics": [ + "sLPI31GcM7MUwO49JauubxfEQy+zOCZ2zhekJpCBHP8=" + ] + } + ] + }, + "operation": "transfer" + }, + { + "hash": "86d1ec3365ea1311dbde2f2366de4ea8627d7e49c29a974578c0869b66903cbc", + "nonce": 0, + "value": 0, + "receiver": "erd1qqqqqqqqqqqqqpgqrp3n58vp2dmcaur4whazxngvuhac4xwqa4sq2pjl73", + "sender": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "data": "ESDTSetRole@54455354434f4c4c312d356161383063@45534454526f6c654e4654437265617465@45534454526f6c654e46544275726e@45534454526f6c654e465455706461746541747472696275746573@45534454526f6c654e4654416464555249", + "prevTxHash": "b0b3c8df519c33b314c0ee3d25abae6f17c4432fb3382676ce17a42690811cff", + "originalTxHash": "08582bc19734ad82d7390be88463c948e5d9f026f4b8f0bfc57620957c3433bd", + "gasLimit": 0, + "gasPrice": 1000000000, + "callType": 0, + "originalSender": "erd1uv40ahysflse896x4ktnh6ecx43u7cmy9wnxnvcyp7deg299a4sq6vaywa", + "logs": { + "address": "erd1qqqqqqqqqqqqqpgqrp3n58vp2dmcaur4whazxngvuhac4xwqa4sq2pjl73", + "events": [ + { + "address": "erd1qqqqqqqqqqqqqpgqrp3n58vp2dmcaur4whazxngvuhac4xwqa4sq2pjl73", + "identifier": "ESDTSetRole", + "topics": [ + "VEVTVENPTEwxLTVhYTgwYw==", + "", + "", + "RVNEVFJvbGVORlRDcmVhdGU=", + "RVNEVFJvbGVORlRCdXJu", + "RVNEVFJvbGVORlRVcGRhdGVBdHRyaWJ1dGVz", + "RVNEVFJvbGVORlRBZGRVUkk=" + ] + }, + { + "address": "erd1qqqqqqqqqqqqqpgqrp3n58vp2dmcaur4whazxngvuhac4xwqa4sq2pjl73", + "identifier": "completedTxEvent", + "topics": [ + "sLPI31GcM7MUwO49JauubxfEQy+zOCZ2zhekJpCBHP8=" + ] + } + ] + }, + "operation": "ESDTSetRole", + "function": "ESDTSetRole" + }, + { + "hash": "c4a24b01b48d32308636310e2d335d6ed1f34dcbdfc1133aed7995e78e831c18", + "nonce": 0, + "value": 0, + "receiver": "erd1qqqqqqqqqqqqqpgqrp3n58vp2dmcaur4whazxngvuhac4xwqa4sq2pjl73", + "sender": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "data": "@00@54455354434f4c4c312d356161383063@3ec73c55022548038bbe06c0639156b3db70b7c770955e340f14fcfcd45df06a@98fa4ff554b9c6990ce577fbb816a271f690dcbd6b148f6583fe7692868ae538@08582bc19734ad82d7390be88463c948e5d9f026f4b8f0bfc57620957c3433bd@00", + "prevTxHash": "b0b3c8df519c33b314c0ee3d25abae6f17c4432fb3382676ce17a42690811cff", + "originalTxHash": "08582bc19734ad82d7390be88463c948e5d9f026f4b8f0bfc57620957c3433bd", + "gasLimit": 23052300, + "gasPrice": 1000000000, + "callType": 2, + "originalSender": "erd1uv40ahysflse896x4ktnh6ecx43u7cmy9wnxnvcyp7deg299a4sq6vaywa", + "logs": { + "address": "erd1qqqqqqqqqqqqqpgqrp3n58vp2dmcaur4whazxngvuhac4xwqa4sq2pjl73", + "events": [ + { + "address": "erd1qqqqqqqqqqqqqpgqrp3n58vp2dmcaur4whazxngvuhac4xwqa4sq2pjl73", + "identifier": "callBack", + "topics": [ + "YXN5bmNDYWxsU3VjY2Vzcw==", + "VEVTVENPTEwxLTVhYTgwYw==" + ], + "additionalData": [ + "" + ] + }, + { + "address": "erd1qqqqqqqqqqqqqpgqrp3n58vp2dmcaur4whazxngvuhac4xwqa4sq2pjl73", + "identifier": "completedTxEvent", + "topics": [ + "sLPI31GcM7MUwO49JauubxfEQy+zOCZ2zhekJpCBHP8=" + ] + } + ] + }, + "operation": "transfer" + } + ], + "logs": { + "address": "erd1qqqqqqqqqqqqqpgqrp3n58vp2dmcaur4whazxngvuhac4xwqa4sq2pjl73", + "events": [ + { + "address": "erd1qqqqqqqqqqqqqpgqrp3n58vp2dmcaur4whazxngvuhac4xwqa4sq2pjl73", + "identifier": "performAction", + "topics": [ + "c3RhcnRQZXJmb3JtQWN0aW9u" + ], + "data": "AAAAAQYAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAL//wAAAAexorwuxQAAAAAAFnJlZ2lzdGVyQW5kU2V0QWxsUm9sZXMAAAAEAAAAD1Rlc3RDb2xsZWN0aW9uMQAAAAlURVNUQ09MTDEAAAADTkZUAAAAAAAAAATjKv7ckE/hk5dGrZc76zg1Y89jZCumabMED5uUKKXtYLE6AXQjw2bK/4zs+3ehJhChMPSIgTQSLHk3/q4NbX0XOvjZyUI7JXfGJSciwdkCEqQRH3ID+XRPdvz6HQoxADOyoRVVzlIeSUTgmrF1SdhbSH3NJshLUBejnjGjZwiJug==", + "additionalData": [ + "AAAAAQYAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAL//wAAAAexorwuxQAAAAAAFnJlZ2lzdGVyQW5kU2V0QWxsUm9sZXMAAAAEAAAAD1Rlc3RDb2xsZWN0aW9uMQAAAAlURVNUQ09MTDEAAAADTkZUAAAAAAAAAATjKv7ckE/hk5dGrZc76zg1Y89jZCumabMED5uUKKXtYLE6AXQjw2bK/4zs+3ehJhChMPSIgTQSLHk3/q4NbX0XOvjZyUI7JXfGJSciwdkCEqQRH3ID+XRPdvz6HQoxADOyoRVVzlIeSUTgmrF1SdhbSH3NJshLUBejnjGjZwiJug==" + ] + }, + { + "address": "erd1qqqqqqqqqqqqqpgqrp3n58vp2dmcaur4whazxngvuhac4xwqa4sq2pjl73", + "identifier": "performAction", + "topics": [ + "cGVyZm9ybUFzeW5jQ2FsbA==", + "AQ==", + "AAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAC//8=", + "saK8LsUAAA==", + "BGa4HQ==", + "cmVnaXN0ZXJBbmRTZXRBbGxSb2xlcw==", + "VGVzdENvbGxlY3Rpb24x", + "VEVTVENPTEwx", + "TkZU", + "" + ], + "additionalData": [ + "" + ] + }, + { + "address": "erd1qqqqqqqqqqqqqpgqrp3n58vp2dmcaur4whazxngvuhac4xwqa4sq2pjl73", + "identifier": "transferValueOnly", + "topics": [ + "saK8LsUAAA==", + "AAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAC//8=" + ], + "data": "QXN5bmNDYWxs", + "additionalData": [ + "QXN5bmNDYWxs", + "cmVnaXN0ZXJBbmRTZXRBbGxSb2xlcw==", + "VGVzdENvbGxlY3Rpb24x", + "VEVTVENPTEwx", + "TkZU", + "" + ] + }, + { + "address": "erd1qqqqqqqqqqqqqpgqrp3n58vp2dmcaur4whazxngvuhac4xwqa4sq2pjl73", + "identifier": "writeLog", + "topics": [ + "4yr+3JBP4ZOXRq2XO+s4NWPPY2QrpmmzBA+blCil7WA=" + ], + "data": "QDZmNmI=", + "additionalData": [ + "QDZmNmI=" + ] + } + ] + }, + "status": "success", + "operation": "transfer", + "function": "performAction", + "initiallyPaidFee": "873260000000000", + "fee": "873260000000000", + "chainID": "D", + "version": 1, + "options": 0 + } + }, + "code": "successful" +} + "#; + + let tx_on_network: TransactionOnNetwork = serde_json::from_str::(data) + .unwrap() + .data + .unwrap() + .transaction; + let tx_response = TxResponse::from_network_tx(tx_on_network); + + let expected = Some("TESTCOLL1-5aa80c".to_string()); + + assert_eq!(tx_response.new_issued_token_identifier, expected) + } } diff --git a/sdk/core/src/data/transaction.rs b/sdk/core/src/data/transaction.rs index 452f0d3679..2df6f37d87 100644 --- a/sdk/core/src/data/transaction.rs +++ b/sdk/core/src/data/transaction.rs @@ -132,6 +132,7 @@ pub struct TransactionInfoData { // TransactionInfo holds a transaction info response from the network #[derive(Debug, Clone, Serialize, Deserialize)] pub struct TransactionInfo { + #[serde(default)] pub error: String, pub code: String, pub data: Option,