From 52131d2fc8c1675b3828f9c4c54dc837e276b6cb Mon Sep 17 00:00:00 2001 From: pasta Date: Tue, 6 Jan 2026 13:31:34 -0600 Subject: [PATCH] feat(wasm-sdk): add transitionHash to all state transition functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add hex-encoded transaction ID (transitionHash) to the return value of all state transition functions in the WASM SDK. This allows users to reference and track transactions after broadcast. Functions updated: - Identity: identityCreate, identityTopUp, identityCreditTransfer, identityCreditWithdrawal, identityUpdate - Tokens: all 10 token functions via format_token_result helper - Contracts: contractCreate, contractUpdate - Documents: documentCreate, documentReplace, documentDelete, documentTransfer, documentPurchase, documentSetPrice Also extracts proof data where available: - identityCreditTransfer: senderNewBalance, recipientNewBalance 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .../src/state_transitions/contracts/mod.rs | 42 +++- .../src/state_transitions/documents/mod.rs | 110 ++++++++- .../src/state_transitions/identity/mod.rs | 222 +++++++++++++++--- .../src/state_transitions/tokens/mod.rs | 100 ++++++-- 4 files changed, 416 insertions(+), 58 deletions(-) diff --git a/packages/wasm-sdk/src/state_transitions/contracts/mod.rs b/packages/wasm-sdk/src/state_transitions/contracts/mod.rs index 176d829878..0e0d3c3320 100644 --- a/packages/wasm-sdk/src/state_transitions/contracts/mod.rs +++ b/packages/wasm-sdk/src/state_transitions/contracts/mod.rs @@ -10,8 +10,11 @@ use dash_sdk::dpp::identity::{KeyType, Purpose}; use dash_sdk::dpp::platform_value::string_encoding::Encoding; use dash_sdk::dpp::state_transition::data_contract_update_transition::methods::DataContractUpdateTransitionMethodsV0; use dash_sdk::dpp::state_transition::data_contract_update_transition::DataContractUpdateTransition; +use dash_sdk::dpp::state_transition::proof_result::StateTransitionProofResult; +use dash_sdk::dpp::state_transition::StateTransition; use dash_sdk::platform::transition::broadcast::BroadcastStateTransition; use dash_sdk::platform::transition::put_contract::PutContract; +use dash_sdk::platform::transition::waitable::Waitable; use dash_sdk::platform::Fetch; use js_sys; use simple_signer::SingleKeySigner; @@ -129,11 +132,24 @@ impl WasmSdk { let signer = SingleKeySigner::from_string(&private_key_wif, self.network()) .map_err(WasmSdkError::invalid_argument)?; - // Create and broadcast the contract - let created_contract = data_contract - .put_to_platform_and_wait_for_response(&sdk, matching_key, &signer, None) + // Create the state transition (to get transaction hash) + let state_transition = data_contract + .put_to_platform(&sdk, matching_key, &signer, None) .await?; + // Get transaction hash before broadcasting + let transaction_id_hex = + state_transition + .transaction_id() + .map(hex::encode) + .map_err(|e| { + WasmSdkError::generic(format!("Failed to compute transaction ID: {}", e)) + })?; + + // Broadcast and wait for the contract to be created + let created_contract = + DataContract::wait_for_response(&sdk, state_transition, None).await?; + // Create JavaScript result object let result_obj = js_sys::Object::new(); @@ -180,6 +196,13 @@ impl WasmSdk { ) .map_err(|e| WasmSdkError::generic(format!("Failed to set documentTypes: {:?}", e)))?; + js_sys::Reflect::set( + &result_obj, + &JsValue::from_str("transitionHash"), + &JsValue::from_str(&transaction_id_hex), + ) + .map_err(|e| WasmSdkError::generic(format!("Failed to set transitionHash: {:?}", e)))?; + js_sys::Reflect::set( &result_obj, &JsValue::from_str("message"), @@ -354,11 +377,16 @@ impl WasmSdk { .map_err(|e| WasmSdkError::generic(format!("Failed to create update transition: {}", e)))?; // Broadcast the transition - use dash_sdk::dpp::state_transition::proof_result::StateTransitionProofResult; let result = state_transition .broadcast_and_wait::(&sdk, None) .await?; + // Get transaction hash (consumes state_transition - no clone needed) + let st: StateTransition = state_transition.into(); + let transaction_id_hex = st.transaction_id().map(hex::encode).map_err(|e| { + WasmSdkError::generic(format!("Failed to compute transaction ID: {}", e)) + })?; + // Extract updated contract from result let updated_version = match result { StateTransitionProofResult::VerifiedDataContract(contract) => contract.version(), @@ -386,6 +414,12 @@ impl WasmSdk { &JsValue::from_f64(updated_version as f64), ) .map_err(|e| WasmSdkError::generic(format!("Failed to set version: {:?}", e)))?; + js_sys::Reflect::set( + &result_obj, + &JsValue::from_str("transitionHash"), + &JsValue::from_str(&transaction_id_hex), + ) + .map_err(|e| WasmSdkError::generic(format!("Failed to set transitionHash: {:?}", e)))?; js_sys::Reflect::set( &result_obj, &JsValue::from_str("message"), diff --git a/packages/wasm-sdk/src/state_transitions/documents/mod.rs b/packages/wasm-sdk/src/state_transitions/documents/mod.rs index bf12acd5d0..fedda51a19 100644 --- a/packages/wasm-sdk/src/state_transitions/documents/mod.rs +++ b/packages/wasm-sdk/src/state_transitions/documents/mod.rs @@ -326,6 +326,12 @@ impl WasmSdk { .await .map_err(|e| WasmSdkError::generic(format!("Failed to broadcast transition: {}", e)))?; + // Get transaction hash (consumes state_transition - no clone needed) + let st: StateTransition = state_transition.into(); + let transaction_id_hex = st.transaction_id().map(hex::encode).map_err(|e| { + WasmSdkError::generic(format!("Failed to compute transaction ID: {}", e)) + })?; + // Log the result for debugging tracing::debug!( target = "wasm_sdk", @@ -361,6 +367,13 @@ impl WasmSdk { ) .unwrap(); + js_sys::Reflect::set( + &js_result, + &JsValue::from_str("transitionHash"), + &JsValue::from_str(&transaction_id_hex), + ) + .unwrap(); + js_sys::Reflect::set( &js_result, &JsValue::from_str("documentId"), @@ -470,6 +483,13 @@ impl WasmSdk { ) .unwrap(); + js_sys::Reflect::set( + &js_result, + &JsValue::from_str("transitionHash"), + &JsValue::from_str(&transaction_id_hex), + ) + .unwrap(); + js_sys::Reflect::set( &js_result, &JsValue::from_str("documentId"), @@ -497,6 +517,13 @@ impl WasmSdk { ) .unwrap(); + js_sys::Reflect::set( + &js_result, + &JsValue::from_str("transitionHash"), + &JsValue::from_str(&transaction_id_hex), + ) + .unwrap(); + js_sys::Reflect::set( &js_result, &JsValue::from_str("documentId"), @@ -525,6 +552,13 @@ impl WasmSdk { ) .unwrap(); + js_sys::Reflect::set( + &js_result, + &JsValue::from_str("transitionHash"), + &JsValue::from_str(&transaction_id_hex), + ) + .unwrap(); + js_sys::Reflect::set( &js_result, &JsValue::from_str("documentId"), @@ -670,6 +704,12 @@ impl WasmSdk { .await .map_err(|e| WasmSdkError::generic(format!("Failed to broadcast transition: {}", e)))?; + // Get transaction hash (consumes state_transition - no clone needed) + let st: StateTransition = state_transition.into(); + let transaction_id_hex = st.transaction_id().map(hex::encode).map_err(|e| { + WasmSdkError::generic(format!("Failed to compute transaction ID: {}", e)) + })?; + // Convert result to JsValue based on the type match proof_result { StateTransitionProofResult::VerifiedDocuments(documents) => { @@ -685,6 +725,13 @@ impl WasmSdk { ) .unwrap(); + js_sys::Reflect::set( + &js_result, + &JsValue::from_str("transitionHash"), + &JsValue::from_str(&transaction_id_hex), + ) + .unwrap(); + js_sys::Reflect::set( &js_result, &JsValue::from_str("documentId"), @@ -794,6 +841,13 @@ impl WasmSdk { ) .unwrap(); + js_sys::Reflect::set( + &js_result, + &JsValue::from_str("transitionHash"), + &JsValue::from_str(&transaction_id_hex), + ) + .unwrap(); + js_sys::Reflect::set( &js_result, &JsValue::from_str("documentId"), @@ -821,6 +875,13 @@ impl WasmSdk { ) .unwrap(); + js_sys::Reflect::set( + &js_result, + &JsValue::from_str("transitionHash"), + &JsValue::from_str(&transaction_id_hex), + ) + .unwrap(); + js_sys::Reflect::set( &js_result, &JsValue::from_str("documentId"), @@ -849,6 +910,13 @@ impl WasmSdk { ) .unwrap(); + js_sys::Reflect::set( + &js_result, + &JsValue::from_str("transitionHash"), + &JsValue::from_str(&transaction_id_hex), + ) + .unwrap(); + js_sys::Reflect::set( &js_result, &JsValue::from_str("documentId"), @@ -987,11 +1055,23 @@ impl WasmSdk { .await .map_err(|e| WasmSdkError::generic(format!("Failed to broadcast: {}", e)))?; + // Get transaction hash + let transaction_id_hex = + state_transition + .transaction_id() + .map(hex::encode) + .map_err(|e| { + WasmSdkError::generic(format!("Failed to compute transaction ID: {}", e)) + })?; + // Return the result with document ID Self::build_js_result_object( "DocumentDeleted", &document_id_base58, - vec![("deleted", JsValue::from_bool(true))], + vec![ + ("transitionHash", JsValue::from_str(&transaction_id_hex)), + ("deleted", JsValue::from_bool(true)), + ], ) } @@ -1118,11 +1198,21 @@ impl WasmSdk { // Broadcast the state transition state_transition.broadcast(&sdk, None).await?; + // Get transaction hash + let transaction_id_hex = + state_transition + .transaction_id() + .map(hex::encode) + .map_err(|e| { + WasmSdkError::generic(format!("Failed to compute transaction ID: {}", e)) + })?; + // Return the result with document ID and new owner Self::build_js_result_object( "DocumentTransferred", &document_id_base58, vec![ + ("transitionHash", JsValue::from_str(&transaction_id_hex)), ("newOwnerId", JsValue::from_str(&recipient_base58)), ("transferred", JsValue::from_bool(true)), ], @@ -1264,11 +1354,18 @@ impl WasmSdk { .await .map_err(|e| WasmSdkError::generic(format!("Failed to broadcast purchase: {}", e)))?; + // Get transaction hash (consumes transition - no clone needed) + let st: StateTransition = transition.into(); + let transaction_id_hex = st.transaction_id().map(hex::encode).map_err(|e| { + WasmSdkError::generic(format!("Failed to compute transaction ID: {}", e)) + })?; + // Handle the proof result match proof_result { StateTransitionProofResult::VerifiedDocuments(documents) => { // Document purchase was successful let mut additional_fields = vec![ + ("transitionHash", JsValue::from_str(&transaction_id_hex)), ("status", JsValue::from_str("success")), ("newOwnerId", JsValue::from_str(&buyer_base58)), ("pricePaid", JsValue::from_f64(price as f64)), @@ -1297,6 +1394,7 @@ impl WasmSdk { "DocumentPurchased", &document_id_base58, vec![ + ("transitionHash", JsValue::from_str(&transaction_id_hex)), ("status", JsValue::from_str("success")), ("message", JsValue::from_str("Document purchase processed")), ], @@ -1430,11 +1528,21 @@ impl WasmSdk { // Broadcast the state transition state_transition.broadcast(&sdk, None).await?; + // Get transaction hash + let transaction_id_hex = + state_transition + .transaction_id() + .map(hex::encode) + .map_err(|e| { + WasmSdkError::generic(format!("Failed to compute transaction ID: {}", e)) + })?; + // Return the result with document ID and price Self::build_js_result_object( "DocumentPriceSet", &document_id_base58, vec![ + ("transitionHash", JsValue::from_str(&transaction_id_hex)), ("price", JsValue::from_f64(price as f64)), ("priceSet", JsValue::from_bool(true)), ], diff --git a/packages/wasm-sdk/src/state_transitions/identity/mod.rs b/packages/wasm-sdk/src/state_transitions/identity/mod.rs index 8d137fb758..be75f7b914 100644 --- a/packages/wasm-sdk/src/state_transitions/identity/mod.rs +++ b/packages/wasm-sdk/src/state_transitions/identity/mod.rs @@ -3,6 +3,7 @@ use crate::queries::utils::identifier_from_js; use crate::sdk::WasmSdk; use dash_sdk::dpp::dashcore::PrivateKey; use dash_sdk::dpp::identity::accessors::IdentityGettersV0; +use dash_sdk::dpp::identity::core_script::CoreScript; use dash_sdk::dpp::identity::identity_public_key::accessors::v0::IdentityPublicKeyGettersV0; use dash_sdk::dpp::identity::{Identity, IdentityPublicKey, KeyType, Purpose, SecurityLevel}; use dash_sdk::dpp::platform_value::{string_encoding::Encoding, BinaryData, Identifier}; @@ -10,9 +11,18 @@ use dash_sdk::dpp::prelude::AssetLockProof; use dash_sdk::dpp::prelude::UserFeeIncrease; use dash_sdk::dpp::state_transition::identity_credit_transfer_transition::methods::IdentityCreditTransferTransitionMethodsV0; use dash_sdk::dpp::state_transition::identity_credit_transfer_transition::IdentityCreditTransferTransition; +use dash_sdk::dpp::state_transition::identity_credit_withdrawal_transition::methods::{ + IdentityCreditWithdrawalTransitionMethodsV0, PreferredKeyPurposeForSigningWithdrawal, +}; +use dash_sdk::dpp::state_transition::identity_credit_withdrawal_transition::IdentityCreditWithdrawalTransition; +use dash_sdk::dpp::state_transition::identity_topup_transition::methods::IdentityTopUpTransitionMethodsV0; +use dash_sdk::dpp::state_transition::identity_topup_transition::IdentityTopUpTransition; +use dash_sdk::dpp::state_transition::proof_result::StateTransitionProofResult; +use dash_sdk::dpp::state_transition::StateTransition; +use dash_sdk::dpp::withdrawal::Pooling; use dash_sdk::platform::transition::broadcast::BroadcastStateTransition; use dash_sdk::platform::transition::put_identity::PutIdentity; -use dash_sdk::platform::transition::top_up_identity::TopUpIdentity; +use dash_sdk::platform::transition::waitable::Waitable; use dash_sdk::platform::Fetch; use js_sys; use simple_signer::{signer::SimpleSigner, SingleKeySigner}; @@ -593,18 +603,12 @@ impl WasmSdk { // Use the SimpleSigner we built with all the identity keys // The signer now contains all private keys for signing each public key individually - // Put identity to platform and wait - let created_identity = match identity - .put_to_platform_and_wait_for_response( - &sdk, - asset_lock_proof, - &private_key, - &signer, - None, - ) + // Put identity to platform (returns StateTransition) + let state_transition = match identity + .put_to_platform(&sdk, asset_lock_proof, &private_key, &signer, None) .await { - Ok(identity) => identity, + Ok(st) => st, Err(e) => { // Extract more detailed error information let error_msg = format!("Failed to create identity: {}", e); @@ -615,6 +619,22 @@ impl WasmSdk { } }; + // Get transaction hash + let transaction_id_hex = + state_transition + .transaction_id() + .map(hex::encode) + .map_err(|e| { + WasmSdkError::generic(format!("Failed to compute transaction ID: {}", e)) + })?; + + // Wait for response + let created_identity = Identity::wait_for_response(&sdk, state_transition, None) + .await + .map_err(|e| { + WasmSdkError::generic(format!("Failed to wait for identity creation: {}", e)) + })?; + // Create JavaScript result object let result_obj = js_sys::Object::new(); @@ -624,6 +644,12 @@ impl WasmSdk { &JsValue::from_str("success"), ) .map_err(|e| WasmSdkError::generic(format!("Failed to set status: {:?}", e)))?; + js_sys::Reflect::set( + &result_obj, + &JsValue::from_str("transitionHash"), + &JsValue::from_str(&transaction_id_hex), + ) + .map_err(|e| WasmSdkError::generic(format!("Failed to set transitionHash: {:?}", e)))?; js_sys::Reflect::set( &result_obj, &JsValue::from_str("identityId"), @@ -736,16 +762,40 @@ impl WasmSdk { // Get the initial balance let initial_balance = identity.balance(); - // Top up the identity - let new_balance = match identity - .top_up_identity(&sdk, asset_lock_proof, &private_key, None, None) + // Create the top up transition + let state_transition = IdentityTopUpTransition::try_from_identity( + &identity, + asset_lock_proof, + private_key.inner.as_ref(), + UserFeeIncrease::default(), + sdk.version(), + None, + ) + .map_err(|e| WasmSdkError::generic(format!("Failed to create top up transition: {}", e)))?; + + // Broadcast and wait for result + let proof_result: StateTransitionProofResult = state_transition + .broadcast_and_wait(&sdk, None) .await - { - Ok(balance) => balance, - Err(e) => { - let error_msg = format!("Failed to top up identity: {}", e); - error!(target : "wasm_sdk", % error_msg); - return Err(WasmSdkError::from(e)); + .map_err(|e| WasmSdkError::generic(format!("Failed to top up identity: {}", e)))?; + + // Get transaction hash + let st: StateTransition = state_transition.into(); + let transaction_id_hex = st.transaction_id().map(hex::encode).map_err(|e| { + WasmSdkError::generic(format!("Failed to compute transaction ID: {}", e)) + })?; + + // Extract new balance from proof result + let new_balance = match proof_result { + StateTransitionProofResult::VerifiedPartialIdentity(partial_identity) => { + partial_identity.balance.ok_or_else(|| { + WasmSdkError::generic("Expected identity balance in proof result") + })? + } + _ => { + return Err(WasmSdkError::generic( + "Unexpected proof result type for identity top up", + )); } }; @@ -760,6 +810,12 @@ impl WasmSdk { &JsValue::from_str("success"), ) .map_err(|e| WasmSdkError::generic(format!("Failed to set status: {:?}", e)))?; + js_sys::Reflect::set( + &result_obj, + &JsValue::from_str("transitionHash"), + &JsValue::from_str(&transaction_id_hex), + ) + .map_err(|e| WasmSdkError::generic(format!("Failed to set transitionHash: {:?}", e)))?; js_sys::Reflect::set( &result_obj, &JsValue::from_str("identityId"), @@ -935,12 +991,26 @@ impl WasmSdk { })?; // Broadcast the transition - use dash_sdk::dpp::state_transition::proof_result::StateTransitionProofResult; - let _result = state_transition + let proof_result = state_transition .broadcast_and_wait::(&sdk, None) .await .map_err(|e| WasmSdkError::generic(format!("Failed to broadcast transfer: {}", e)))?; + // Get transaction hash (consumes state_transition - no clone needed) + let st: StateTransition = state_transition.into(); + let transaction_id_hex = st.transaction_id().map(hex::encode).map_err(|e| { + WasmSdkError::generic(format!("Failed to compute transaction ID: {}", e)) + })?; + + // Extract balances from proof result + let (sender_new_balance, recipient_new_balance) = match proof_result { + StateTransitionProofResult::VerifiedBalanceTransfer( + sender_partial, + recipient_partial, + ) => (sender_partial.balance, recipient_partial.balance), + _ => (None, None), + }; + // Create JavaScript result object let result_obj = js_sys::Object::new(); @@ -968,6 +1038,32 @@ impl WasmSdk { &JsValue::from_f64(amount as f64), ) .map_err(|e| WasmSdkError::generic(format!("Failed to set amount: {:?}", e)))?; + js_sys::Reflect::set( + &result_obj, + &JsValue::from_str("transitionHash"), + &JsValue::from_str(&transaction_id_hex), + ) + .map_err(|e| WasmSdkError::generic(format!("Failed to set transitionHash: {:?}", e)))?; + if let Some(balance) = sender_new_balance { + js_sys::Reflect::set( + &result_obj, + &JsValue::from_str("senderNewBalance"), + &JsValue::from_f64(balance as f64), + ) + .map_err(|e| { + WasmSdkError::generic(format!("Failed to set senderNewBalance: {:?}", e)) + })?; + } + if let Some(balance) = recipient_new_balance { + js_sys::Reflect::set( + &result_obj, + &JsValue::from_str("recipientNewBalance"), + &JsValue::from_f64(balance as f64), + ) + .map_err(|e| { + WasmSdkError::generic(format!("Failed to set recipientNewBalance: {:?}", e)) + })?; + } js_sys::Reflect::set( &result_obj, &JsValue::from_str("message"), @@ -1109,23 +1205,58 @@ impl WasmSdk { let signer = SingleKeySigner::from_string(&private_key_wif, self.network()) .map_err(WasmSdkError::invalid_argument)?; - // Import the withdraw trait - use dash_sdk::platform::transition::withdraw_from_identity::WithdrawFromIdentity; - - // Perform the withdrawal - let remaining_balance = identity - .withdraw( - &sdk, - Some(address), - amount, - core_fee_per_byte, - Some(matching_key), - signer, - None, - ) + // Get identity nonce + let new_identity_nonce = sdk + .get_identity_nonce(identity.id(), true, None) + .await + .map_err(|e| WasmSdkError::generic(format!("Failed to get identity nonce: {}", e)))?; + + // Create the withdrawal transition + let script = CoreScript::new(address.script_pubkey()); + let state_transition = IdentityCreditWithdrawalTransition::try_from_identity( + &identity, + Some(script), + amount, + Pooling::Never, + core_fee_per_byte.unwrap_or(1), + UserFeeIncrease::default(), + signer, + Some(matching_key), + PreferredKeyPurposeForSigningWithdrawal::TransferPreferred, + new_identity_nonce, + sdk.version(), + None, + ) + .map_err(|e| { + WasmSdkError::generic(format!("Failed to create withdrawal transition: {}", e)) + })?; + + // Broadcast and wait for result + let proof_result: StateTransitionProofResult = state_transition + .broadcast_and_wait(&sdk, None) .await .map_err(|e| WasmSdkError::generic(format!("Withdrawal failed: {}", e)))?; + // Get transaction hash + let st: StateTransition = state_transition.into(); + let transaction_id_hex = st.transaction_id().map(hex::encode).map_err(|e| { + WasmSdkError::generic(format!("Failed to compute transaction ID: {}", e)) + })?; + + // Extract remaining balance from proof result + let remaining_balance = match proof_result { + StateTransitionProofResult::VerifiedPartialIdentity(partial_identity) => { + partial_identity.balance.ok_or_else(|| { + WasmSdkError::generic("Expected identity balance in proof result") + })? + } + _ => { + return Err(WasmSdkError::generic( + "Unexpected proof result type for withdrawal", + )); + } + }; + // Create JavaScript result object let result_obj = js_sys::Object::new(); @@ -1135,6 +1266,12 @@ impl WasmSdk { &JsValue::from_str("success"), ) .map_err(|e| WasmSdkError::generic(format!("Failed to set status: {:?}", e)))?; + js_sys::Reflect::set( + &result_obj, + &JsValue::from_str("transitionHash"), + &JsValue::from_str(&transaction_id_hex), + ) + .map_err(|e| WasmSdkError::generic(format!("Failed to set transitionHash: {:?}", e)))?; js_sys::Reflect::set( &result_obj, &JsValue::from_str("identityId"), @@ -1325,12 +1462,17 @@ impl WasmSdk { .map_err(|e| WasmSdkError::generic(format!("Failed to create update transition: {}", e)))?; // Broadcast the transition - use dash_sdk::dpp::state_transition::proof_result::StateTransitionProofResult; let result = state_transition .broadcast_and_wait::(&sdk, None) .await .map_err(|e| WasmSdkError::generic(format!("Failed to broadcast update: {}", e)))?; + // Get transaction hash (consumes state_transition - no clone needed) + let st: StateTransition = state_transition.into(); + let transaction_id_hex = st.transaction_id().map(hex::encode).map_err(|e| { + WasmSdkError::generic(format!("Failed to compute transaction ID: {}", e)) + })?; + // Extract updated identity from result let updated_revision = match result { StateTransitionProofResult::VerifiedIdentity(updated_identity) => { @@ -1375,6 +1517,12 @@ impl WasmSdk { &JsValue::from_f64(disabled_keys_count as f64), ) .map_err(|e| WasmSdkError::generic(format!("Failed to set disabledKeys: {:?}", e)))?; + js_sys::Reflect::set( + &result_obj, + &JsValue::from_str("transitionHash"), + &JsValue::from_str(&transaction_id_hex), + ) + .map_err(|e| WasmSdkError::generic(format!("Failed to set transitionHash: {:?}", e)))?; js_sys::Reflect::set( &result_obj, &JsValue::from_str("message"), diff --git a/packages/wasm-sdk/src/state_transitions/tokens/mod.rs b/packages/wasm-sdk/src/state_transitions/tokens/mod.rs index 0bf5aaaa21..2d292a655d 100644 --- a/packages/wasm-sdk/src/state_transitions/tokens/mod.rs +++ b/packages/wasm-sdk/src/state_transitions/tokens/mod.rs @@ -12,6 +12,7 @@ use dash_sdk::dpp::prelude::UserFeeIncrease; use dash_sdk::dpp::state_transition::batch_transition::methods::v1::DocumentsBatchTransitionMethodsV1; use dash_sdk::dpp::state_transition::batch_transition::BatchTransition; use dash_sdk::dpp::state_transition::proof_result::StateTransitionProofResult; +use dash_sdk::dpp::state_transition::StateTransition; use dash_sdk::dpp::tokens::calculate_token_id; use dash_sdk::platform::transition::broadcast::BroadcastStateTransition; use dash_sdk::platform::Fetch; @@ -92,13 +93,15 @@ impl WasmSdk { fn format_token_result( &self, proof_result: StateTransitionProofResult, + transaction_id_hex: &str, ) -> Result { match proof_result { StateTransitionProofResult::VerifiedTokenBalance(recipient_id, new_balance) => { to_json_compatible(&serde_json::json!({ "type": "VerifiedTokenBalance", "recipientId": recipient_id.to_string(Encoding::Base58), - "newBalance": new_balance.to_string() + "newBalance": new_balance.to_string(), + "transitionHash": transaction_id_hex })) .map_err(|e| { WasmSdkError::serialization(format!("Failed to serialize result: {}", e)) @@ -108,7 +111,8 @@ impl WasmSdk { to_json_compatible(&serde_json::json!({ "type": "VerifiedTokenActionWithDocument", "documentId": doc.id().to_string(Encoding::Base58), - "message": "Token operation recorded successfully" + "message": "Token operation recorded successfully", + "transitionHash": transaction_id_hex })) .map_err(|e| { WasmSdkError::serialization(format!("Failed to serialize result: {}", e)) @@ -118,7 +122,8 @@ impl WasmSdk { to_json_compatible(&serde_json::json!({ "type": "VerifiedTokenGroupActionWithDocument", "groupPower": power, - "document": doc.is_some() + "document": doc.is_some(), + "transitionHash": transaction_id_hex })) .map_err(|e| { WasmSdkError::serialization(format!("Failed to serialize result: {}", e)) @@ -132,7 +137,8 @@ impl WasmSdk { "type": "VerifiedTokenGroupActionWithTokenBalance", "groupPower": power, "status": format!("{:?}", status), - "balance": balance.map(|b| b.to_string()) + "balance": balance.map(|b| b.to_string()), + "transitionHash": transaction_id_hex })) .map_err(|e| WasmSdkError::serialization(format!("Failed to serialize result: {}", e))), _ => Err(WasmSdkError::generic( @@ -237,8 +243,14 @@ impl WasmSdk { .broadcast_and_wait::(&sdk, None) .await?; + // Get transaction hash (consumes state_transition - no clone needed) + let st: StateTransition = state_transition.into(); + let transaction_id_hex = st.transaction_id().map(hex::encode).map_err(|e| { + WasmSdkError::generic(format!("Failed to compute transaction ID: {}", e)) + })?; + // Format and return result - self.format_token_result(proof_result) + self.format_token_result(proof_result, &transaction_id_hex) } /// Burn tokens, permanently removing them from circulation. @@ -322,8 +334,14 @@ impl WasmSdk { .broadcast_and_wait::(&sdk, None) .await?; + // Get transaction hash (consumes state_transition - no clone needed) + let st: StateTransition = state_transition.into(); + let transaction_id_hex = st.transaction_id().map(hex::encode).map_err(|e| { + WasmSdkError::generic(format!("Failed to compute transaction ID: {}", e)) + })?; + // Format and return result - self.format_token_result(proof_result) + self.format_token_result(proof_result, &transaction_id_hex) } /// Transfer tokens between identities. @@ -419,8 +437,14 @@ impl WasmSdk { .broadcast_and_wait::(&sdk, None) .await?; + // Get transaction hash (consumes state_transition - no clone needed) + let st: StateTransition = state_transition.into(); + let transaction_id_hex = st.transaction_id().map(hex::encode).map_err(|e| { + WasmSdkError::generic(format!("Failed to compute transaction ID: {}", e)) + })?; + // Format and return result - self.format_token_result(proof_result) + self.format_token_result(proof_result, &transaction_id_hex) } /// Freeze tokens for a specific identity. @@ -514,8 +538,14 @@ impl WasmSdk { .broadcast_and_wait::(&sdk, None) .await?; + // Get transaction hash (consumes state_transition - no clone needed) + let st: StateTransition = state_transition.into(); + let transaction_id_hex = st.transaction_id().map(hex::encode).map_err(|e| { + WasmSdkError::generic(format!("Failed to compute transaction ID: {}", e)) + })?; + // Format and return result - self.format_token_result(proof_result) + self.format_token_result(proof_result, &transaction_id_hex) } /// Unfreeze tokens for a specific identity. @@ -612,8 +642,14 @@ impl WasmSdk { .broadcast_and_wait::(&sdk, None) .await?; + // Get transaction hash (consumes state_transition - no clone needed) + let st: StateTransition = state_transition.into(); + let transaction_id_hex = st.transaction_id().map(hex::encode).map_err(|e| { + WasmSdkError::generic(format!("Failed to compute transaction ID: {}", e)) + })?; + // Format and return result - self.format_token_result(proof_result) + self.format_token_result(proof_result, &transaction_id_hex) } /// Destroy frozen tokens. @@ -710,8 +746,14 @@ impl WasmSdk { .broadcast_and_wait::(&sdk, None) .await?; + // Get transaction hash (consumes state_transition - no clone needed) + let st: StateTransition = state_transition.into(); + let transaction_id_hex = st.transaction_id().map(hex::encode).map_err(|e| { + WasmSdkError::generic(format!("Failed to compute transaction ID: {}", e)) + })?; + // Format and return result - self.format_token_result(proof_result) + self.format_token_result(proof_result, &transaction_id_hex) } /// Set or update the price for direct token purchases. @@ -861,6 +903,12 @@ impl WasmSdk { .broadcast_and_wait::(&sdk, None) .await?; + // Get transaction hash (consumes state_transition - no clone needed) + let st: StateTransition = state_transition.into(); + let transaction_id_hex = st.transaction_id().map(hex::encode).map_err(|e| { + WasmSdkError::generic(format!("Failed to compute transaction ID: {}", e)) + })?; + // Format and return result based on the proof result type match proof_result { StateTransitionProofResult::VerifiedTokenPricingSchedule(owner_id, schedule) => { @@ -882,7 +930,8 @@ impl WasmSdk { "prices": price_map }) } - }) + }), + "transitionHash": transaction_id_hex })) .map_err(|e| { WasmSdkError::serialization(format!("Failed to serialize result: {}", e)) @@ -911,10 +960,11 @@ impl WasmSdk { "prices": price_map }) } - }) + }), + "transitionHash": transaction_id_hex })) .map_err(|e| WasmSdkError::serialization(format!("Failed to serialize result: {}", e))), - _ => self.format_token_result(proof_result), + _ => self.format_token_result(proof_result, &transaction_id_hex), } } @@ -1061,8 +1111,14 @@ impl WasmSdk { .await .map_err(|e| WasmSdkError::generic(format!("Failed to broadcast transition: {}", e)))?; + // Get transaction hash (consumes state_transition - no clone needed) + let st: StateTransition = state_transition.into(); + let transaction_id_hex = st.transaction_id().map(hex::encode).map_err(|e| { + WasmSdkError::generic(format!("Failed to compute transaction ID: {}", e)) + })?; + // Format and return result - self.format_token_result(proof_result) + self.format_token_result(proof_result, &transaction_id_hex) } /// Claim tokens from a distribution @@ -1164,8 +1220,14 @@ impl WasmSdk { .broadcast_and_wait::(&sdk, None) .await?; + // Get transaction hash (consumes state_transition - no clone needed) + let st: StateTransition = state_transition.into(); + let transaction_id_hex = st.transaction_id().map(hex::encode).map_err(|e| { + WasmSdkError::generic(format!("Failed to compute transaction ID: {}", e)) + })?; + // Format and return result - self.format_token_result(proof_result) + self.format_token_result(proof_result, &transaction_id_hex) } /// Update token configuration settings. @@ -1402,7 +1464,13 @@ impl WasmSdk { .broadcast_and_wait::(&sdk, None) .await?; + // Get transaction hash (consumes state_transition - no clone needed) + let st: StateTransition = state_transition.into(); + let transaction_id_hex = st.transaction_id().map(hex::encode).map_err(|e| { + WasmSdkError::generic(format!("Failed to compute transaction ID: {}", e)) + })?; + // Format and return result - self.format_token_result(proof_result) + self.format_token_result(proof_result, &transaction_id_hex) } }