diff --git a/packages/dapi/lib/externalApis/drive/fetchProofForStateTransitionFactory.js b/packages/dapi/lib/externalApis/drive/fetchProofForStateTransitionFactory.js index 0d50ddd67a7..35d9fd34e69 100644 --- a/packages/dapi/lib/externalApis/drive/fetchProofForStateTransitionFactory.js +++ b/packages/dapi/lib/externalApis/drive/fetchProofForStateTransitionFactory.js @@ -3,13 +3,21 @@ const { GetProofsRequest, }, } = require('@dashevo/dapi-grpc'); -const { StateTransitionTypes } = require('@dashevo/wasm-dpp'); + +const { + StateTransitionTypes, + TokenTransition, + DocumentTransition, + TokenTransitionType, +} = require('@dashevo/wasm-dpp'); +const { GetDataContractRequest } = require('@dashevo/dapi-grpc/clients/platform/v0/web/platform_pb'); /** * @param {PlatformPromiseClient} driveClient + * @param {DashPlatformProtocol} dpp * @return {fetchProofForStateTransition} */ -function fetchProofForStateTransitionFactory(driveClient) { +function fetchProofForStateTransitionFactory(driveClient, dpp) { /** * @typedef {fetchProofForStateTransition} * @param {AbstractStateTransition} stateTransition @@ -22,25 +30,160 @@ function fetchProofForStateTransitionFactory(driveClient) { const requestV0 = new GetProofsRequestV0(); + let dataContractsCache = {}; + if (stateTransition.isDocumentStateTransition()) { - const { DocumentRequest } = GetProofsRequestV0; + const { + DocumentRequest, + IdentityTokenBalanceRequest, + IdentityTokenInfoRequest, + TokenStatusRequest, + } = GetProofsRequestV0; - const documentsList = stateTransition.getTransitions().map((documentTransition) => { - const documentRequest = new DocumentRequest(); - documentRequest.setContractId(documentTransition.getDataContractId().toBuffer()); - documentRequest.setDocumentType(documentTransition.getType()); - documentRequest.setDocumentId(documentTransition.getId().toBuffer()); + const documentsList = []; + const identityTokenBalancesList = []; + const identityTokenInfosList = []; + const tokenStatusesList = []; - const status = documentTransition.hasPrefundedBalance() - ? DocumentRequest.DocumentContestedStatus.CONTESTED - : DocumentRequest.DocumentContestedStatus.NOT_CONTESTED; + for (const batchedTransition of stateTransition.getTransitions()) { + if (batchedTransition instanceof TokenTransition) { + switch (batchedTransition.getTransitionType()) { + case TokenTransitionType.Burn: { + const request = new IdentityTokenBalanceRequest({ + tokenId: batchedTransition.getTokenId() + .toBuffer(), + identityId: stateTransition.getOwnerId() + .toBuffer(), + }); - documentRequest.setDocumentContestedStatus(status); + identityTokenBalancesList.push(request); + break; + } + case TokenTransitionType.Mint: { + // Fetch data contract to determine correct recipient identity + const dataContractId = batchedTransition.getDataContractId(); + const dataContractIdString = dataContractId.toString(); - return documentRequest; - }); + if (!dataContractsCache[dataContractIdString]) { + const dataContractRequestV0 = new GetDataContractRequest.GetDataContractRequestV0({ + id: dataContractId.toBuffer(), + }); + + const dataContractRequest = new GetDataContractRequest(); + dataContractRequest.setV0(dataContractRequestV0); + + const dataContractResponse = await driveClient.getDataContract(dataContractRequest); + + const dataContractBuffer = Buffer.from( + dataContractResponse.getV0().getDataContract_asU8(), + ); + + dataContractsCache[dataContractIdString] = await dpp.dataContract + .createFromBuffer(dataContractBuffer); + } + + const dataContract = dataContractsCache[dataContractIdString]; + + const tokenConfiguration = dataContract.getTokenConfiguration( + batchedTransition.getTokenContractPosition(), + ); + + const request = new IdentityTokenBalanceRequest({ + tokenId: batchedTransition.getTokenId() + .toBuffer(), + identityId: batchedTransition.toTransition().getRecipientId(tokenConfiguration) + .toBuffer(), + }); + + identityTokenBalancesList.push(request); + break; + } + case TokenTransitionType.Transfer: { + const requestSender = new IdentityTokenBalanceRequest({ + tokenId: batchedTransition.getTokenId() + .toBuffer(), + identityId: stateTransition.getOwnerId().toBuffer(), + }); + + const requestRecipient = new IdentityTokenBalanceRequest({ + tokenId: batchedTransition.getTokenId() + .toBuffer(), + identityId: batchedTransition.toTransition().getRecipientId() + .toBuffer(), + }); + + identityTokenBalancesList.push(requestSender, requestRecipient); + break; + } + case TokenTransitionType.DestroyFrozenFunds: { + const request = new IdentityTokenBalanceRequest({ + tokenId: batchedTransition.getTokenId() + .toBuffer(), + identityId: batchedTransition.toTransition().getFrozenIdentityId() + .toBuffer(), + }); + + identityTokenBalancesList.push(request); + break; + } + case TokenTransitionType.EmergencyAction: + { + const request = new TokenStatusRequest({ + tokenId: batchedTransition.getTokenId() + .toBuffer(), + }); - requestV0.setDocumentsList(documentsList); + tokenStatusesList.push(request); + break; + } + case TokenTransitionType.Freeze: + case TokenTransitionType.Unfreeze: { + const request = new IdentityTokenInfoRequest({ + tokenId: batchedTransition.getTokenId() + .toBuffer(), + identityId: batchedTransition.toTransition().getFrozenIdentityId() + .toBuffer(), + }); + + identityTokenInfosList.push(request); + break; + } + default: + throw new Error(`Unsupported token transition type ${batchedTransition.getTransitionType()}`); + } + } else if (batchedTransition instanceof DocumentTransition) { + const documentRequest = new DocumentRequest(); + documentRequest.setContractId(batchedTransition.getDataContractId().toBuffer()); + documentRequest.setDocumentType(batchedTransition.getType()); + documentRequest.setDocumentId(batchedTransition.getId().toBuffer()); + + const status = batchedTransition.hasPrefundedBalance() + ? DocumentRequest.DocumentContestedStatus.CONTESTED + : DocumentRequest.DocumentContestedStatus.NOT_CONTESTED; + + documentRequest.setDocumentContestedStatus(status); + + documentsList.push(documentRequest); + } else { + throw new Error(`Unsupported batched transition type ${batchedTransition.constructor.name}`); + } + } + + if (documentsList.length > 0) { + requestV0.setDocumentsList(documentsList); + } + + if (identityTokenBalancesList.length > 0) { + requestV0.setIdentityTokenBalancesList(identityTokenBalancesList); + } + + if (identityTokenInfosList.length > 0) { + requestV0.setIdentityTokenInfosList(identityTokenInfosList); + } + + if (tokenStatusesList.length > 0) { + requestV0.setTokenStatusesList(tokenStatusesList); + } } if (stateTransition.isIdentityStateTransition()) { const { IdentityRequest } = GetProofsRequestV0; diff --git a/packages/rs-dpp/src/data_contract/mod.rs b/packages/rs-dpp/src/data_contract/mod.rs index 818bc3f621e..9fc8e03a839 100644 --- a/packages/rs-dpp/src/data_contract/mod.rs +++ b/packages/rs-dpp/src/data_contract/mod.rs @@ -50,7 +50,7 @@ use crate::version::{FeatureVersion, PlatformVersion}; use crate::ProtocolError; use crate::ProtocolError::{PlatformDeserializationError, PlatformSerializationError}; -use crate::data_contract::associated_token::token_configuration::TokenConfiguration; +pub use crate::data_contract::associated_token::token_configuration::TokenConfiguration; use crate::data_contract::group::Group; use crate::data_contract::v0::DataContractV0; use crate::data_contract::v1::DataContractV1; diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/token_transfer_transition/v0/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/token_transfer_transition/v0/mod.rs index 0f3da97343e..54fc9f55ff6 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/token_transfer_transition/v0/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/token_transfer_transition/v0/mod.rs @@ -12,6 +12,13 @@ use platform_value::Identifier; #[cfg(feature = "state-transition-serde-conversion")] use serde::{Deserialize, Serialize}; +pub type SharedEncryptedNote = (SenderKeyIndex, RecipientKeyIndex, Vec); +pub type PrivateEncryptedNote = ( + RootEncryptionKeyIndex, + DerivationEncryptionKeyIndex, + Vec, +); + mod property_names { pub const AMOUNT: &str = "$amount"; pub const RECIPIENT_OWNER_ID: &str = "recipientOwnerId"; @@ -53,15 +60,11 @@ pub struct TokenTransferTransitionV0 { feature = "state-transition-serde-conversion", serde(rename = "sharedEncryptedNote") )] - pub shared_encrypted_note: Option<(SenderKeyIndex, RecipientKeyIndex, Vec)>, + pub shared_encrypted_note: Option, /// An optional private encrypted note #[cfg_attr( feature = "state-transition-serde-conversion", serde(rename = "privateEncryptedNote") )] - pub private_encrypted_note: Option<( - RootEncryptionKeyIndex, - DerivationEncryptionKeyIndex, - Vec, - )>, + pub private_encrypted_note: Option, } diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/token_transfer_transition/v0/v0_methods.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/token_transfer_transition/v0/v0_methods.rs index ce0c6d2723c..5f8875f3df3 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/token_transfer_transition/v0/v0_methods.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/token_transfer_transition/v0/v0_methods.rs @@ -3,6 +3,7 @@ use crate::prelude::{DerivationEncryptionKeyIndex, RecipientKeyIndex, RootEncryp use crate::state_transition::batch_transition::batched_transition::token_transfer_transition::TokenTransferTransitionV0; use crate::state_transition::batch_transition::token_base_transition::token_base_transition_accessors::TokenBaseTransitionAccessors; use crate::state_transition::batch_transition::token_base_transition::TokenBaseTransition; +use crate::state_transition::batch_transition::token_transfer_transition::{PrivateEncryptedNote, SharedEncryptedNote}; impl TokenBaseTransitionAccessors for TokenTransferTransitionV0 { fn base(&self) -> &TokenBaseTransition { @@ -44,16 +45,13 @@ pub trait TokenTransferTransitionV0Methods: TokenBaseTransitionAccessors { fn set_public_note(&mut self, public_note: Option); /// Returns the `shared_encrypted_note` field of the `TokenTransferTransitionV0`. - fn shared_encrypted_note(&self) -> Option<&(SenderKeyIndex, RecipientKeyIndex, Vec)>; + fn shared_encrypted_note(&self) -> Option<&SharedEncryptedNote>; /// Returns the owned `shared_encrypted_note` field of the `TokenTransferTransitionV0`. - fn shared_encrypted_note_owned(self) -> Option<(SenderKeyIndex, RecipientKeyIndex, Vec)>; + fn shared_encrypted_note_owned(self) -> Option; /// Sets the value of the `shared_encrypted_note` field in the `TokenTransferTransitionV0`. - fn set_shared_encrypted_note( - &mut self, - shared_encrypted_note: Option<(SenderKeyIndex, RecipientKeyIndex, Vec)>, - ); + fn set_shared_encrypted_note(&mut self, shared_encrypted_note: Option); /// Returns the `private_encrypted_note` field of the `TokenTransferTransitionV0`. fn private_encrypted_note( @@ -74,26 +72,15 @@ pub trait TokenTransferTransitionV0Methods: TokenBaseTransitionAccessors { )>; /// Sets the value of the `private_encrypted_note` field in the `TokenTransferTransitionV0`. - fn set_private_encrypted_note( - &mut self, - private_encrypted_note: Option<( - RootEncryptionKeyIndex, - DerivationEncryptionKeyIndex, - Vec, - )>, - ); + fn set_private_encrypted_note(&mut self, private_encrypted_note: Option); /// Returns all notes (public, shared, and private) as owned values in a tuple. fn notes_owned( self, ) -> ( Option, - Option<(SenderKeyIndex, RecipientKeyIndex, Vec)>, - Option<( - RootEncryptionKeyIndex, - DerivationEncryptionKeyIndex, - Vec, - )>, + Option, + Option, ); /// Returns all notes (public, shared, and private) as cloned values in a tuple. @@ -142,18 +129,15 @@ impl TokenTransferTransitionV0Methods for TokenTransferTransitionV0 { self.public_note = public_note; } - fn shared_encrypted_note(&self) -> Option<&(SenderKeyIndex, RecipientKeyIndex, Vec)> { + fn shared_encrypted_note(&self) -> Option<&SharedEncryptedNote> { self.shared_encrypted_note.as_ref() } - fn shared_encrypted_note_owned(self) -> Option<(SenderKeyIndex, RecipientKeyIndex, Vec)> { + fn shared_encrypted_note_owned(self) -> Option { self.shared_encrypted_note } - fn set_shared_encrypted_note( - &mut self, - shared_encrypted_note: Option<(SenderKeyIndex, RecipientKeyIndex, Vec)>, - ) { + fn set_shared_encrypted_note(&mut self, shared_encrypted_note: Option) { self.shared_encrypted_note = shared_encrypted_note; } @@ -177,14 +161,7 @@ impl TokenTransferTransitionV0Methods for TokenTransferTransitionV0 { self.private_encrypted_note } - fn set_private_encrypted_note( - &mut self, - private_encrypted_note: Option<( - RootEncryptionKeyIndex, - DerivationEncryptionKeyIndex, - Vec, - )>, - ) { + fn set_private_encrypted_note(&mut self, private_encrypted_note: Option) { self.private_encrypted_note = private_encrypted_note; } @@ -192,12 +169,8 @@ impl TokenTransferTransitionV0Methods for TokenTransferTransitionV0 { self, ) -> ( Option, - Option<(SenderKeyIndex, RecipientKeyIndex, Vec)>, - Option<( - RootEncryptionKeyIndex, - DerivationEncryptionKeyIndex, - Vec, - )>, + Option, + Option, ) { ( self.public_note, diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/token_transfer_transition/v0_methods.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/token_transfer_transition/v0_methods.rs index 12da036c9f4..81cd4a1e46d 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/token_transfer_transition/v0_methods.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/token_transfer_transition/v0_methods.rs @@ -4,6 +4,7 @@ use crate::state_transition::batch_transition::batched_transition::token_transfe use crate::state_transition::batch_transition::token_base_transition::token_base_transition_accessors::TokenBaseTransitionAccessors; use crate::state_transition::batch_transition::TokenTransferTransition; use crate::state_transition::batch_transition::token_base_transition::TokenBaseTransition; +use crate::state_transition::batch_transition::token_transfer_transition::{PrivateEncryptedNote, SharedEncryptedNote}; impl TokenBaseTransitionAccessors for TokenTransferTransition { fn base(&self) -> &TokenBaseTransition { @@ -75,22 +76,19 @@ impl TokenTransferTransitionV0Methods for TokenTransferTransition { } } - fn shared_encrypted_note(&self) -> Option<&(SenderKeyIndex, RecipientKeyIndex, Vec)> { + fn shared_encrypted_note(&self) -> Option<&SharedEncryptedNote> { match self { TokenTransferTransition::V0(v0) => v0.shared_encrypted_note.as_ref(), } } - fn shared_encrypted_note_owned(self) -> Option<(SenderKeyIndex, RecipientKeyIndex, Vec)> { + fn shared_encrypted_note_owned(self) -> Option { match self { TokenTransferTransition::V0(v0) => v0.shared_encrypted_note, } } - fn set_shared_encrypted_note( - &mut self, - shared_encrypted_note: Option<(SenderKeyIndex, RecipientKeyIndex, Vec)>, - ) { + fn set_shared_encrypted_note(&mut self, shared_encrypted_note: Option) { match self { TokenTransferTransition::V0(v0) => v0.shared_encrypted_note = shared_encrypted_note, } @@ -120,14 +118,7 @@ impl TokenTransferTransitionV0Methods for TokenTransferTransition { } } - fn set_private_encrypted_note( - &mut self, - private_encrypted_note: Option<( - RootEncryptionKeyIndex, - DerivationEncryptionKeyIndex, - Vec, - )>, - ) { + fn set_private_encrypted_note(&mut self, private_encrypted_note: Option) { match self { TokenTransferTransition::V0(v0) => v0.private_encrypted_note = private_encrypted_note, } @@ -138,12 +129,8 @@ impl TokenTransferTransitionV0Methods for TokenTransferTransition { self, ) -> ( Option, - Option<(SenderKeyIndex, RecipientKeyIndex, Vec)>, - Option<( - RootEncryptionKeyIndex, - DerivationEncryptionKeyIndex, - Vec, - )>, + Option, + Option, ) { match self { TokenTransferTransition::V0(v0) => ( diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/methods/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/methods/mod.rs index c4ee2c72510..7523e6d5f4e 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/methods/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/methods/mod.rs @@ -24,6 +24,9 @@ use crate::prelude::{ use crate::state_transition::batch_transition::batched_transition::BatchedTransition; use crate::state_transition::batch_transition::methods::v0::DocumentsBatchTransitionMethodsV0; use crate::state_transition::batch_transition::methods::v1::DocumentsBatchTransitionMethodsV1; +use crate::state_transition::batch_transition::token_transfer_transition::{ + PrivateEncryptedNote, SharedEncryptedNote, +}; use crate::state_transition::batch_transition::BatchTransition; #[cfg(feature = "state-transition-signing")] use crate::state_transition::batch_transition::{BatchTransitionV0, BatchTransitionV1}; @@ -561,12 +564,8 @@ impl DocumentsBatchTransitionMethodsV1 for BatchTransition { amount: TokenAmount, recipient_id: Identifier, public_note: Option, - shared_encrypted_note: Option<(SenderKeyIndex, RecipientKeyIndex, Vec)>, - private_encrypted_note: Option<( - RootEncryptionKeyIndex, - DerivationEncryptionKeyIndex, - Vec, - )>, + shared_encrypted_note: Option, + private_encrypted_note: Option, identity_public_key: &IdentityPublicKey, identity_contract_nonce: IdentityNonce, user_fee_increase: UserFeeIncrease, diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/methods/v1/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/methods/v1/mod.rs index 83d0be8635b..75c9d8b5ca3 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/methods/v1/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/methods/v1/mod.rs @@ -14,6 +14,9 @@ use crate::prelude::{ SenderKeyIndex, UserFeeIncrease, }; use crate::state_transition::batch_transition::accessors::DocumentsBatchTransitionAccessorsV0; +use crate::state_transition::batch_transition::token_transfer_transition::{ + PrivateEncryptedNote, SharedEncryptedNote, +}; #[cfg(feature = "state-transition-signing")] use crate::state_transition::StateTransition; #[cfg(feature = "state-transition-signing")] @@ -76,12 +79,8 @@ pub trait DocumentsBatchTransitionMethodsV1: DocumentsBatchTransitionAccessorsV0 amount: TokenAmount, recipient_id: Identifier, public_note: Option, - shared_encrypted_note: Option<(SenderKeyIndex, RecipientKeyIndex, Vec)>, - private_encrypted_note: Option<( - RootEncryptionKeyIndex, - DerivationEncryptionKeyIndex, - Vec, - )>, + shared_encrypted_note: Option, + private_encrypted_note: Option, identity_public_key: &IdentityPublicKey, identity_contract_nonce: IdentityNonce, user_fee_increase: UserFeeIncrease, diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/v1/v0_methods.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/v1/v0_methods.rs index c3dbdfa9c3f..dbc9d33af07 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/v1/v0_methods.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/v1/v0_methods.rs @@ -79,6 +79,8 @@ use crate::state_transition::batch_transition::token_freeze_transition::TokenFre #[cfg(feature = "state-transition-signing")] use crate::state_transition::batch_transition::token_mint_transition::TokenMintTransitionV0; #[cfg(feature = "state-transition-signing")] +use crate::state_transition::batch_transition::token_transfer_transition::{PrivateEncryptedNote, SharedEncryptedNote}; +#[cfg(feature = "state-transition-signing")] use crate::state_transition::batch_transition::token_transfer_transition::TokenTransferTransitionV0; #[cfg(feature = "state-transition-signing")] use crate::state_transition::batch_transition::token_unfreeze_transition::TokenUnfreezeTransitionV0; @@ -582,12 +584,8 @@ impl DocumentsBatchTransitionMethodsV1 for BatchTransitionV1 { amount: TokenAmount, recipient_id: Identifier, public_note: Option, - shared_encrypted_note: Option<(SenderKeyIndex, RecipientKeyIndex, Vec)>, - private_encrypted_note: Option<( - RootEncryptionKeyIndex, - DerivationEncryptionKeyIndex, - Vec, - )>, + shared_encrypted_note: Option, + private_encrypted_note: Option, identity_public_key: &IdentityPublicKey, identity_contract_nonce: IdentityNonce, user_fee_increase: UserFeeIncrease, diff --git a/packages/rs-dpp/src/tokens/token_event.rs b/packages/rs-dpp/src/tokens/token_event.rs index dd13b2fe9ef..5de7b5c8820 100644 --- a/packages/rs-dpp/src/tokens/token_event.rs +++ b/packages/rs-dpp/src/tokens/token_event.rs @@ -15,12 +15,13 @@ use platform_version::version::PlatformVersion; use std::collections::BTreeMap; pub type TokenEventPublicNote = Option; -pub type TokenEventSharedEncryptedNote = Option<(SenderKeyIndex, RecipientKeyIndex, Vec)>; +pub type TokenEventSharedEncryptedNote = Option; pub type TokenEventPersonalEncryptedNote = Option<( RootEncryptionKeyIndex, DerivationEncryptionKeyIndex, Vec, )>; +use crate::state_transition::batch_transition::token_transfer_transition::SharedEncryptedNote; use crate::serialization::PlatformSerializableWithPlatformVersion; use crate::tokens::emergency_action::TokenEmergencyAction; use crate::ProtocolError; diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/token_transition/token_transfer_transition_action/mod.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/token_transition/token_transfer_transition_action/mod.rs index 9202c66a24e..dfe33f1a82e 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/token_transition/token_transfer_transition_action/mod.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/token_transition/token_transfer_transition_action/mod.rs @@ -3,6 +3,7 @@ use derive_more::From; use crate::state_transition_action::batch::batched_transition::token_transition::token_base_transition_action::TokenBaseTransitionAction; use dpp::identifier::Identifier; use dpp::prelude::{DerivationEncryptionKeyIndex, RecipientKeyIndex, RootEncryptionKeyIndex, SenderKeyIndex}; +use dpp::state_transition::batch_transition::token_transfer_transition::{PrivateEncryptedNote, SharedEncryptedNote}; /// transformer module pub mod transformer; @@ -61,22 +62,19 @@ impl TokenTransferTransitionActionAccessorsV0 for TokenTransferTransitionAction } } - fn shared_encrypted_note(&self) -> Option<&(SenderKeyIndex, RecipientKeyIndex, Vec)> { + fn shared_encrypted_note(&self) -> Option<&SharedEncryptedNote> { match self { TokenTransferTransitionAction::V0(v0) => v0.shared_encrypted_note(), } } - fn shared_encrypted_note_owned(self) -> Option<(SenderKeyIndex, RecipientKeyIndex, Vec)> { + fn shared_encrypted_note_owned(self) -> Option { match self { TokenTransferTransitionAction::V0(v0) => v0.shared_encrypted_note_owned(), } } - fn set_shared_encrypted_note( - &mut self, - shared_encrypted_note: Option<(SenderKeyIndex, RecipientKeyIndex, Vec)>, - ) { + fn set_shared_encrypted_note(&mut self, shared_encrypted_note: Option) { match self { TokenTransferTransitionAction::V0(v0) => { v0.set_shared_encrypted_note(shared_encrypted_note) @@ -108,14 +106,7 @@ impl TokenTransferTransitionActionAccessorsV0 for TokenTransferTransitionAction } } - fn set_private_encrypted_note( - &mut self, - private_encrypted_note: Option<( - RootEncryptionKeyIndex, - DerivationEncryptionKeyIndex, - Vec, - )>, - ) { + fn set_private_encrypted_note(&mut self, private_encrypted_note: Option) { match self { TokenTransferTransitionAction::V0(v0) => { v0.set_private_encrypted_note(private_encrypted_note) @@ -127,12 +118,8 @@ impl TokenTransferTransitionActionAccessorsV0 for TokenTransferTransitionAction &self, ) -> ( Option, - Option<(SenderKeyIndex, RecipientKeyIndex, Vec)>, - Option<( - RootEncryptionKeyIndex, - DerivationEncryptionKeyIndex, - Vec, - )>, + Option, + Option, ) { match self { TokenTransferTransitionAction::V0(v0) => v0.notes(), @@ -143,12 +130,8 @@ impl TokenTransferTransitionActionAccessorsV0 for TokenTransferTransitionAction self, ) -> ( Option, - Option<(SenderKeyIndex, RecipientKeyIndex, Vec)>, - Option<( - RootEncryptionKeyIndex, - DerivationEncryptionKeyIndex, - Vec, - )>, + Option, + Option, ) { match self { TokenTransferTransitionAction::V0(v0) => v0.notes_owned(), diff --git a/packages/rs-drive/src/state_transition_action/batch/batched_transition/token_transition/token_transfer_transition_action/v0/mod.rs b/packages/rs-drive/src/state_transition_action/batch/batched_transition/token_transition/token_transfer_transition_action/v0/mod.rs index 962053117f8..b5766e16a36 100644 --- a/packages/rs-drive/src/state_transition_action/batch/batched_transition/token_transition/token_transfer_transition_action/v0/mod.rs +++ b/packages/rs-drive/src/state_transition_action/batch/batched_transition/token_transition/token_transfer_transition_action/v0/mod.rs @@ -7,7 +7,7 @@ use dpp::prelude::{ DerivationEncryptionKeyIndex, IdentityNonce, RecipientKeyIndex, RootEncryptionKeyIndex, SenderKeyIndex, }; - +use dpp::state_transition::batch_transition::token_transfer_transition::{PrivateEncryptedNote, SharedEncryptedNote}; use crate::drive::contract::DataContractFetchInfo; use crate::state_transition_action::batch::batched_transition::token_transition::token_base_transition_action::{ TokenBaseTransitionAction, TokenBaseTransitionActionAccessorsV0, @@ -25,7 +25,7 @@ pub struct TokenTransferTransitionActionV0 { /// The public note pub public_note: Option, /// An optional shared encrypted note - pub shared_encrypted_note: Option<(SenderKeyIndex, RecipientKeyIndex, Vec)>, + pub shared_encrypted_note: Option, /// An optional private encrypted note pub private_encrypted_note: Option<( RootEncryptionKeyIndex, @@ -88,16 +88,13 @@ pub trait TokenTransferTransitionActionAccessorsV0 { fn set_public_note(&mut self, public_note: Option); /// Returns the shared encrypted note, if present - fn shared_encrypted_note(&self) -> Option<&(SenderKeyIndex, RecipientKeyIndex, Vec)>; + fn shared_encrypted_note(&self) -> Option<&SharedEncryptedNote>; /// Consumes the `TokenTransferTransitionActionV0` and returns the shared encrypted note, if present - fn shared_encrypted_note_owned(self) -> Option<(SenderKeyIndex, RecipientKeyIndex, Vec)>; + fn shared_encrypted_note_owned(self) -> Option; /// Sets the shared encrypted note - fn set_shared_encrypted_note( - &mut self, - shared_encrypted_note: Option<(SenderKeyIndex, RecipientKeyIndex, Vec)>, - ); + fn set_shared_encrypted_note(&mut self, shared_encrypted_note: Option); /// Returns the private encrypted note, if present fn private_encrypted_note( @@ -118,38 +115,23 @@ pub trait TokenTransferTransitionActionAccessorsV0 { )>; /// Sets the private encrypted note - fn set_private_encrypted_note( - &mut self, - private_encrypted_note: Option<( - RootEncryptionKeyIndex, - DerivationEncryptionKeyIndex, - Vec, - )>, - ); + fn set_private_encrypted_note(&mut self, private_encrypted_note: Option); /// All notes fn notes_owned( self, ) -> ( Option, - Option<(SenderKeyIndex, RecipientKeyIndex, Vec)>, - Option<( - RootEncryptionKeyIndex, - DerivationEncryptionKeyIndex, - Vec, - )>, + Option, + Option, ); /// All notes fn notes( &self, ) -> ( Option, - Option<(SenderKeyIndex, RecipientKeyIndex, Vec)>, - Option<( - RootEncryptionKeyIndex, - DerivationEncryptionKeyIndex, - Vec, - )>, + Option, + Option, ); } @@ -182,18 +164,15 @@ impl TokenTransferTransitionActionAccessorsV0 for TokenTransferTransitionActionV self.public_note = public_note; } - fn shared_encrypted_note(&self) -> Option<&(SenderKeyIndex, RecipientKeyIndex, Vec)> { + fn shared_encrypted_note(&self) -> Option<&SharedEncryptedNote> { self.shared_encrypted_note.as_ref() } - fn shared_encrypted_note_owned(self) -> Option<(SenderKeyIndex, RecipientKeyIndex, Vec)> { + fn shared_encrypted_note_owned(self) -> Option { self.shared_encrypted_note } - fn set_shared_encrypted_note( - &mut self, - shared_encrypted_note: Option<(SenderKeyIndex, RecipientKeyIndex, Vec)>, - ) { + fn set_shared_encrypted_note(&mut self, shared_encrypted_note: Option) { self.shared_encrypted_note = shared_encrypted_note; } @@ -217,14 +196,7 @@ impl TokenTransferTransitionActionAccessorsV0 for TokenTransferTransitionActionV self.private_encrypted_note } - fn set_private_encrypted_note( - &mut self, - private_encrypted_note: Option<( - RootEncryptionKeyIndex, - DerivationEncryptionKeyIndex, - Vec, - )>, - ) { + fn set_private_encrypted_note(&mut self, private_encrypted_note: Option) { self.private_encrypted_note = private_encrypted_note; } @@ -232,12 +204,8 @@ impl TokenTransferTransitionActionAccessorsV0 for TokenTransferTransitionActionV &self, ) -> ( Option, - Option<(SenderKeyIndex, RecipientKeyIndex, Vec)>, - Option<( - RootEncryptionKeyIndex, - DerivationEncryptionKeyIndex, - Vec, - )>, + Option, + Option, ) { ( self.public_note.clone(), @@ -250,12 +218,8 @@ impl TokenTransferTransitionActionAccessorsV0 for TokenTransferTransitionActionV self, ) -> ( Option, - Option<(SenderKeyIndex, RecipientKeyIndex, Vec)>, - Option<( - RootEncryptionKeyIndex, - DerivationEncryptionKeyIndex, - Vec, - )>, + Option, + Option, ) { ( self.public_note, diff --git a/packages/rs-sdk/src/platform/transition.rs b/packages/rs-sdk/src/platform/transition.rs index c82a494d2df..234537179de 100644 --- a/packages/rs-sdk/src/platform/transition.rs +++ b/packages/rs-sdk/src/platform/transition.rs @@ -17,3 +17,6 @@ pub mod waitable; pub mod withdraw_from_identity; pub use txid::TxId; + +mod builder; +pub mod fungible_tokens; diff --git a/packages/rs-sdk/src/platform/transition/builder.rs b/packages/rs-sdk/src/platform/transition/builder.rs new file mode 100644 index 00000000000..6c4549561d4 --- /dev/null +++ b/packages/rs-sdk/src/platform/transition/builder.rs @@ -0,0 +1,95 @@ +use crate::platform::transition::broadcast::BroadcastStateTransition; +use crate::platform::transition::put_settings::PutSettings; +use crate::platform::Identifier; +use crate::{Error, Sdk}; +use dpp::balances::credits::TokenAmount; +use dpp::identity::signer::Signer; +use dpp::identity::IdentityPublicKey; +use dpp::state_transition::StateTransition; +use dpp::version::PlatformVersion; + +/// Trait for building state transitions +pub trait StateTransitionBuilder { + /// Returns the settings for the state transition + /// + /// # Returns + /// + /// * `Option` - The settings, if any + fn settings(&self) -> Option; + + /// Signs the state transition + /// + /// # Arguments + /// + /// * `sdk` - The SDK instance + /// * `identity_public_key` - The public key of the identity + /// * `signer` - The signer instance + /// * `platform_version` - The platform version + /// + /// # Returns + /// + /// * `Result` - The signed state transition or an error + async fn sign( + &self, + sdk: &Sdk, + identity_public_key: &IdentityPublicKey, + signer: &impl Signer, + platform_version: &PlatformVersion, + ) -> Result; + + /// Broadcasts the state transition + /// + /// # Arguments + /// + /// * `sdk` - The SDK instance + /// * `identity_public_key` - The public key of the identity + /// * `signer` - The signer instance + /// * `platform_version` - The platform version + /// + /// # Returns + /// + /// * `Result` - The broadcasted state transition or an error + async fn broadcast( + &self, + sdk: &Sdk, + identity_public_key: &IdentityPublicKey, + signer: &impl Signer, + platform_version: &PlatformVersion, + ) -> Result { + let state_transition = self + .sign(sdk, identity_public_key, signer, platform_version) + .await?; + + state_transition.broadcast(sdk, self.settings()).await?; + + Ok(state_transition) + } + + /// Broadcasts the state transition and waits for the result + /// + /// # Arguments + /// + /// * `sdk` - The SDK instance + /// * `identity_public_key` - The public key of the identity + /// * `signer` - The signer instance + /// * `platform_version` - The platform version + /// + /// # Returns + /// + /// * `Result<(Identifier, TokenAmount), Error>` - The result of the broadcasted state transition or an error + async fn broadcast_and_wait_for_result( + &self, + sdk: &Sdk, + identity_public_key: &IdentityPublicKey, + signer: &impl Signer, + platform_version: &PlatformVersion, + ) -> Result<(Identifier, TokenAmount), Error> { + let state_transition = self + .broadcast(sdk, identity_public_key, signer, platform_version) + .await?; + + state_transition + .wait_for_response(sdk, self.settings()) + .await + } +} diff --git a/packages/rs-sdk/src/platform/transition/fungible_tokens/burn.rs b/packages/rs-sdk/src/platform/transition/fungible_tokens/burn.rs new file mode 100644 index 00000000000..f0595d18410 --- /dev/null +++ b/packages/rs-sdk/src/platform/transition/fungible_tokens/burn.rs @@ -0,0 +1,177 @@ +use crate::platform::transition::builder::StateTransitionBuilder; +use crate::platform::transition::put_settings::PutSettings; +use crate::platform::Identifier; +use crate::{Error, Sdk}; +use dpp::balances::credits::TokenAmount; +use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::data_contract::{DataContract, TokenContractPosition}; +use dpp::group::GroupStateTransitionInfoStatus; +use dpp::identity::signer::Signer; +use dpp::identity::IdentityPublicKey; +use dpp::prelude::UserFeeIncrease; +use dpp::state_transition::batch_transition::methods::v1::DocumentsBatchTransitionMethodsV1; +use dpp::state_transition::batch_transition::BatchTransition; +use dpp::state_transition::StateTransition; +use dpp::tokens::calculate_token_id; +use dpp::version::PlatformVersion; + +/// A builder to configure and broadcast token burn transitions +pub struct TokenBurnTransitionBuilder<'a> { + data_contract: &'a DataContract, + token_position: TokenContractPosition, + owner_id: Identifier, + amount: TokenAmount, + public_note: Option, + settings: Option, + user_fee_increase: Option, + using_group_info: Option, +} + +impl<'a> TokenBurnTransitionBuilder<'a> { + /// Creates a new `TokenBurnTransitionBuilder` + /// + /// # Arguments + /// + /// * `data_contract` - A reference to the data contract + /// * `token_position` - The position of the token in the contract + /// * `owner_id` - The identifier of the token owner + /// * `amount` - The amount of tokens to burn + pub fn new( + data_contract: &'a DataContract, + token_position: TokenContractPosition, + owner_id: Identifier, + amount: TokenAmount, + ) -> Self { + Self { + data_contract, + token_position, + owner_id, + amount, + public_note: None, + settings: None, + user_fee_increase: None, + using_group_info: None, + } + } + + /// Adds a public note to the token burn transition + /// + /// # Arguments + /// + /// * `note` - The public note to add + /// + /// # Returns + /// + /// * `Self` - The updated builder + pub fn with_public_note(mut self, note: String) -> Self { + self.public_note = Some(note); + self + } + + /// Adds a user fee increase to the token burn transition + /// + /// # Arguments + /// + /// * `user_fee_increase` - The user fee increase to add + /// + /// # Returns + /// + /// * `Self` - The updated builder + pub fn with_user_fee_increase(mut self, user_fee_increase: UserFeeIncrease) -> Self { + self.user_fee_increase = Some(user_fee_increase); + self + } + + /// Adds group information to the token burn transition + /// + /// # Arguments + /// + /// * `group_info` - The group information to add + /// + /// # Returns + /// + /// * `Self` - The updated builder + pub fn with_using_group_info(mut self, group_info: GroupStateTransitionInfoStatus) -> Self { + self.using_group_info = Some(group_info); + self + } + + /// Adds settings to the token burn transition + /// + /// # Arguments + /// + /// * `settings` - The settings to add + /// + /// # Returns + /// + /// * `Self` - The updated builder + pub fn with_settings(mut self, settings: PutSettings) -> Self { + self.settings = Some(settings); + self + } +} + +impl StateTransitionBuilder for TokenBurnTransitionBuilder<'_> { + /// Returns the settings for the token burn transition + /// + /// # Returns + /// + /// * `Option` - The settings, if any + fn settings(&self) -> Option { + self.settings + } + + /// Signs the token burn transition + /// + /// # Arguments + /// + /// * `sdk` - The SDK instance + /// * `identity_public_key` - The public key of the identity + /// * `signer` - The signer instance + /// * `platform_version` - The platform version + /// + /// # Returns + /// + /// * `Result` - The signed state transition or an error + async fn sign( + &self, + sdk: &Sdk, + identity_public_key: &IdentityPublicKey, + signer: &impl Signer, + platform_version: &PlatformVersion, + ) -> Result { + let token_id = Identifier::from(calculate_token_id( + self.data_contract.id().as_bytes(), + self.token_position, + )); + + let identity_contract_nonce = sdk + .get_identity_contract_nonce( + self.owner_id, + self.data_contract.id(), + false, + self.settings, + ) + .await?; + + let state_transition = BatchTransition::new_token_burn_transition( + token_id, + self.owner_id, + self.data_contract.id(), + self.token_position, + self.amount, + self.public_note.clone(), + self.using_group_info, + identity_public_key, + identity_contract_nonce, + self.user_fee_increase.unwrap_or_default(), + signer, + platform_version, + None, + None, + None, + )?; + + Ok(state_transition) + } +} diff --git a/packages/rs-sdk/src/platform/transition/fungible_tokens/destroy.rs b/packages/rs-sdk/src/platform/transition/fungible_tokens/destroy.rs new file mode 100644 index 00000000000..e82e4becbe0 --- /dev/null +++ b/packages/rs-sdk/src/platform/transition/fungible_tokens/destroy.rs @@ -0,0 +1,185 @@ +use crate::platform::transition::builder::StateTransitionBuilder; +use crate::platform::transition::put_settings::PutSettings; +use crate::platform::Identifier; +use crate::{Error, Sdk}; +use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::data_contract::{DataContract, TokenContractPosition}; +use dpp::group::GroupStateTransitionInfoStatus; +use dpp::identity::signer::Signer; +use dpp::identity::IdentityPublicKey; +use dpp::prelude::UserFeeIncrease; +use dpp::state_transition::batch_transition::methods::v1::DocumentsBatchTransitionMethodsV1; +use dpp::state_transition::batch_transition::BatchTransition; +use dpp::state_transition::StateTransition; +use dpp::tokens::calculate_token_id; +use dpp::version::PlatformVersion; + +/// A builder to configure and broadcast token destroy funds transitions +pub struct TokenDestroyFrozenFundsTransitionBuilder<'a> { + data_contract: &'a DataContract, + token_position: TokenContractPosition, + actor_id: Identifier, + frozen_identity_id: Identifier, + public_note: Option, + settings: Option, + user_fee_increase: Option, + using_group_info: Option, +} + +impl<'a> TokenDestroyFrozenFundsTransitionBuilder<'a> { + /// Start building a mint tokens request for the provided DataContract. + /// + /// # Arguments + /// + /// * `data_contract` - A reference to the data contract + /// * `token_position` - The position of the token in the contract + /// * `actor_id` - The identifier of the actor + /// * `frozen_identity_id` - The identifier of the frozen identity + /// + /// # Returns + /// + /// * `Self` - The new builder instance + pub fn new( + data_contract: &'a DataContract, + token_position: TokenContractPosition, + actor_id: Identifier, + frozen_identity_id: Identifier, + ) -> Self { + // TODO: Validate token position + + Self { + data_contract, + token_position, + actor_id, + frozen_identity_id, + public_note: None, + settings: None, + user_fee_increase: None, + using_group_info: None, + } + } + + /// Adds a public note to the token destroy transition + /// + /// # Arguments + /// + /// * `note` - The public note to add + /// + /// # Returns + /// + /// * `Self` - The updated builder + pub fn with_public_note(mut self, note: String) -> Self { + self.public_note = Some(note); + self + } + + /// Adds a user fee increase to the token destroy transition + /// + /// # Arguments + /// + /// * `user_fee_increase` - The user fee increase to add + /// + /// # Returns + /// + /// * `Self` - The updated builder + pub fn with_user_fee_increase(mut self, user_fee_increase: UserFeeIncrease) -> Self { + self.user_fee_increase = Some(user_fee_increase); + self + } + + /// Adds group information to the token destroy transition + /// + /// # Arguments + /// + /// * `group_info` - The group information to add + /// + /// # Returns + /// + /// * `Self` - The updated builder + pub fn with_using_group_info(mut self, group_info: GroupStateTransitionInfoStatus) -> Self { + self.using_group_info = Some(group_info); + + // TODO: Simplify group actions automatically find position if group action is required + + self + } + + /// Adds settings to the token destroy transition + /// + /// # Arguments + /// + /// * `settings` - The settings to add + /// + /// # Returns + /// + /// * `Self` - The updated builder + pub fn with_settings(mut self, settings: PutSettings) -> Self { + self.settings = Some(settings); + self + } +} + +impl StateTransitionBuilder for TokenDestroyFrozenFundsTransitionBuilder<'_> { + /// Returns the settings for the token destroy transition + /// + /// # Returns + /// + /// * `Option` - The settings, if any + fn settings(&self) -> Option { + self.settings + } + + /// Signs the token destroy transition + /// + /// # Arguments + /// + /// * `sdk` - The SDK instance + /// * `identity_public_key` - The public key of the identity + /// * `signer` - The signer instance + /// * `platform_version` - The platform version + /// + /// # Returns + /// + /// * `Result` - The signed state transition or an error + async fn sign( + &self, + sdk: &Sdk, + identity_public_key: &IdentityPublicKey, + signer: &impl Signer, + platform_version: &PlatformVersion, + ) -> Result { + let token_id = Identifier::from(calculate_token_id( + self.data_contract.id().as_bytes(), + self.token_position, + )); + + let identity_contract_nonce = sdk + .get_identity_contract_nonce( + self.actor_id, + self.data_contract.id(), + false, + self.settings, + ) + .await?; + + let state_transition = BatchTransition::new_token_destroy_frozen_funds_transition( + token_id, + self.actor_id, + self.data_contract.id(), + self.token_position, + self.frozen_identity_id, + self.public_note.clone(), + self.using_group_info, + identity_public_key, + identity_contract_nonce, + self.user_fee_increase.unwrap_or_default(), + signer, + platform_version, + None, + None, + None, + )?; + + Ok(state_transition) + } +} diff --git a/packages/rs-sdk/src/platform/transition/fungible_tokens/emergency_action.rs b/packages/rs-sdk/src/platform/transition/fungible_tokens/emergency_action.rs new file mode 100644 index 00000000000..b8c45390cd9 --- /dev/null +++ b/packages/rs-sdk/src/platform/transition/fungible_tokens/emergency_action.rs @@ -0,0 +1,214 @@ +use crate::platform::transition::builder::StateTransitionBuilder; +use crate::platform::transition::put_settings::PutSettings; +use crate::platform::Identifier; +use crate::{Error, Sdk}; +use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::data_contract::{DataContract, TokenContractPosition}; +use dpp::group::GroupStateTransitionInfoStatus; +use dpp::identity::signer::Signer; +use dpp::identity::IdentityPublicKey; +use dpp::prelude::UserFeeIncrease; +use dpp::state_transition::batch_transition::methods::v1::DocumentsBatchTransitionMethodsV1; +use dpp::state_transition::batch_transition::BatchTransition; +use dpp::state_transition::StateTransition; +use dpp::tokens::calculate_token_id; +use dpp::tokens::emergency_action::TokenEmergencyAction; +use dpp::version::PlatformVersion; + +/// A builder to configure and broadcast emergency action transitions +pub struct TokenEmergencyActionTransitionBuilder<'a> { + data_contract: &'a DataContract, + token_position: TokenContractPosition, + actor_id: Identifier, + action: TokenEmergencyAction, + public_note: Option, + settings: Option, + user_fee_increase: Option, + using_group_info: Option, +} + +impl<'a> TokenEmergencyActionTransitionBuilder<'a> { + /// Start building a pause tokens request for the provided DataContract. + /// + /// # Arguments + /// + /// * `data_contract` - A reference to the data contract + /// * `token_position` - The position of the token in the contract + /// * `actor_id` - The identifier of the actor + /// + /// # Returns + /// + /// * `Self` - The new builder instance + pub fn pause( + data_contract: &'a DataContract, + token_position: TokenContractPosition, + actor_id: Identifier, + ) -> Self { + // TODO: Validate token position + + Self { + data_contract, + token_position, + actor_id, + action: TokenEmergencyAction::Pause, + public_note: None, + settings: None, + user_fee_increase: None, + using_group_info: None, + } + } + + /// Start building a resume tokens request for the provided DataContract. + /// + /// # Arguments + /// + /// * `data_contract` - A reference to the data contract + /// * `token_position` - The position of the token in the contract + /// * `actor_id` - The identifier of the actor + /// + /// # Returns + /// + /// * `Self` - The new builder instance + pub fn resume( + data_contract: &'a DataContract, + token_position: TokenContractPosition, + actor_id: Identifier, + ) -> Self { + // TODO: Validate token position + + Self { + data_contract, + token_position, + actor_id, + action: TokenEmergencyAction::Resume, + public_note: None, + settings: None, + user_fee_increase: None, + using_group_info: None, + } + } + + /// Adds a public note to the token emergency action transition + /// + /// # Arguments + /// + /// * `note` - The public note to add + /// + /// # Returns + /// + /// * `Self` - The updated builder + pub fn with_public_note(mut self, note: String) -> Self { + self.public_note = Some(note); + self + } + + /// Adds a user fee increase to the token emergency action transition + /// + /// # Arguments + /// + /// * `user_fee_increase` - The user fee increase to add + /// + /// # Returns + /// + /// * `Self` - The updated builder + pub fn with_user_fee_increase(mut self, user_fee_increase: UserFeeIncrease) -> Self { + self.user_fee_increase = Some(user_fee_increase); + self + } + + /// Adds group information to the token emergency action transition + /// + /// # Arguments + /// + /// * `group_info` - The group information to add + /// + /// # Returns + /// + /// * `Self` - The updated builder + pub fn with_using_group_info(mut self, group_info: GroupStateTransitionInfoStatus) -> Self { + self.using_group_info = Some(group_info); + + // TODO: Simplify group actions automatically find position if group action is required + + self + } + + /// Adds settings to the token emergency action transition + /// + /// # Arguments + /// + /// * `settings` - The settings to add + /// + /// # Returns + /// + /// * `Self` - The updated builder + pub fn with_settings(mut self, settings: PutSettings) -> Self { + self.settings = Some(settings); + self + } +} + +impl StateTransitionBuilder for TokenEmergencyActionTransitionBuilder<'_> { + /// Returns the settings for the token emergency action transition + /// + /// # Returns + /// + /// * `Option` - The settings, if any + fn settings(&self) -> Option { + self.settings + } + + /// Signs the token emergency action transition + /// + /// # Arguments + /// + /// * `sdk` - The SDK instance + /// * `identity_public_key` - The public key of the identity + /// * `signer` - The signer instance + /// * `platform_version` - The platform version + /// + /// # Returns + /// + /// * `Result` - The signed state transition or an error + async fn sign( + &self, + sdk: &Sdk, + identity_public_key: &IdentityPublicKey, + signer: &impl Signer, + platform_version: &PlatformVersion, + ) -> Result { + let token_id = Identifier::from(calculate_token_id( + self.data_contract.id().as_bytes(), + self.token_position, + )); + + let identity_contract_nonce = sdk + .get_identity_contract_nonce( + self.actor_id, + self.data_contract.id(), + false, + self.settings, + ) + .await?; + + let state_transition = BatchTransition::new_token_emergency_action_transition( + token_id, + self.actor_id, + self.data_contract.id(), + self.token_position, + self.action, + self.public_note.clone(), + self.using_group_info, + identity_public_key, + identity_contract_nonce, + self.user_fee_increase.unwrap_or_default(), + signer, + platform_version, + None, + None, + None, + )?; + + Ok(state_transition) + } +} diff --git a/packages/rs-sdk/src/platform/transition/fungible_tokens/freeze.rs b/packages/rs-sdk/src/platform/transition/fungible_tokens/freeze.rs new file mode 100644 index 00000000000..0ac89e66c2d --- /dev/null +++ b/packages/rs-sdk/src/platform/transition/fungible_tokens/freeze.rs @@ -0,0 +1,185 @@ +use crate::platform::transition::builder::StateTransitionBuilder; +use crate::platform::transition::put_settings::PutSettings; +use crate::platform::Identifier; +use crate::{Error, Sdk}; +use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::data_contract::{DataContract, TokenContractPosition}; +use dpp::group::GroupStateTransitionInfoStatus; +use dpp::identity::signer::Signer; +use dpp::identity::IdentityPublicKey; +use dpp::prelude::UserFeeIncrease; +use dpp::state_transition::batch_transition::methods::v1::DocumentsBatchTransitionMethodsV1; +use dpp::state_transition::batch_transition::BatchTransition; +use dpp::state_transition::StateTransition; +use dpp::tokens::calculate_token_id; +use dpp::version::PlatformVersion; + +/// A builder to configure and broadcast token freeze transitions +pub struct TokenFreezeTransitionBuilder<'a> { + data_contract: &'a DataContract, + token_position: TokenContractPosition, + actor_id: Identifier, + freeze_identity_id: Identifier, + public_note: Option, + settings: Option, + user_fee_increase: Option, + using_group_info: Option, +} + +impl<'a> TokenFreezeTransitionBuilder<'a> { + /// Start building a mint tokens request for the provided DataContract. + /// + /// # Arguments + /// + /// * `data_contract` - A reference to the data contract + /// * `token_position` - The position of the token in the contract + /// * `actor_id` - The identifier of the actor + /// * `freeze_identity_id` - The identifier of the frozen identity + /// + /// # Returns + /// + /// * `Self` - The new builder instance + pub fn new( + data_contract: &'a DataContract, + token_position: TokenContractPosition, + actor_id: Identifier, + freeze_identity_id: Identifier, + ) -> Self { + // TODO: Validate token position + + Self { + data_contract, + token_position, + actor_id, + freeze_identity_id, + public_note: None, + settings: None, + user_fee_increase: None, + using_group_info: None, + } + } + + /// Adds a public note to the token freeze transition + /// + /// # Arguments + /// + /// * `note` - The public note to add + /// + /// # Returns + /// + /// * `Self` - The updated builder + pub fn with_public_note(mut self, note: String) -> Self { + self.public_note = Some(note); + self + } + + /// Adds a user fee increase to the token freeze transition + /// + /// # Arguments + /// + /// * `user_fee_increase` - The user fee increase to add + /// + /// # Returns + /// + /// * `Self` - The updated builder + pub fn with_user_fee_increase(mut self, user_fee_increase: UserFeeIncrease) -> Self { + self.user_fee_increase = Some(user_fee_increase); + self + } + + /// Adds group information to the token freeze transition + /// + /// # Arguments + /// + /// * `group_info` - The group information to add + /// + /// # Returns + /// + /// * `Self` - The updated builder + pub fn with_using_group_info(mut self, group_info: GroupStateTransitionInfoStatus) -> Self { + self.using_group_info = Some(group_info); + + // TODO: Simplify group actions automatically find position if group action is required + + self + } + + /// Adds settings to the token freeze transition + /// + /// # Arguments + /// + /// * `settings` - The settings to add + /// + /// # Returns + /// + /// * `Self` - The updated builder + pub fn with_settings(mut self, settings: PutSettings) -> Self { + self.settings = Some(settings); + self + } +} + +impl StateTransitionBuilder for TokenFreezeTransitionBuilder<'_> { + /// Returns the settings for the token freeze transition + /// + /// # Returns + /// + /// * `Option` - The settings, if any + fn settings(&self) -> Option { + self.settings + } + + /// Signs the token freeze transition + /// + /// # Arguments + /// + /// * `sdk` - The SDK instance + /// * `identity_public_key` - The public key of the identity + /// * `signer` - The signer instance + /// * `platform_version` - The platform version + /// + /// # Returns + /// + /// * `Result` - The signed state transition or an error + async fn sign( + &self, + sdk: &Sdk, + identity_public_key: &IdentityPublicKey, + signer: &impl Signer, + platform_version: &PlatformVersion, + ) -> Result { + let token_id = Identifier::from(calculate_token_id( + self.data_contract.id().as_bytes(), + self.token_position, + )); + + let identity_contract_nonce = sdk + .get_identity_contract_nonce( + self.actor_id, + self.data_contract.id(), + false, + self.settings, + ) + .await?; + + let state_transition = BatchTransition::new_token_freeze_transition( + token_id, + self.actor_id, + self.data_contract.id(), + self.token_position, + self.freeze_identity_id, + self.public_note.clone(), + self.using_group_info, + identity_public_key, + identity_contract_nonce, + self.user_fee_increase.unwrap_or_default(), + signer, + platform_version, + None, + None, + None, + )?; + + Ok(state_transition) + } +} diff --git a/packages/rs-sdk/src/platform/transition/fungible_tokens/mint.rs b/packages/rs-sdk/src/platform/transition/fungible_tokens/mint.rs new file mode 100644 index 00000000000..380f7cfe21d --- /dev/null +++ b/packages/rs-sdk/src/platform/transition/fungible_tokens/mint.rs @@ -0,0 +1,206 @@ +use crate::platform::transition::builder::StateTransitionBuilder; +use crate::platform::transition::put_settings::PutSettings; +use crate::platform::Identifier; +use crate::{Error, Sdk}; +use dpp::balances::credits::TokenAmount; +use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::data_contract::{DataContract, TokenContractPosition}; +use dpp::group::GroupStateTransitionInfoStatus; +use dpp::identity::signer::Signer; +use dpp::identity::IdentityPublicKey; +use dpp::prelude::UserFeeIncrease; +use dpp::state_transition::batch_transition::methods::v1::DocumentsBatchTransitionMethodsV1; +use dpp::state_transition::batch_transition::BatchTransition; +use dpp::state_transition::StateTransition; +use dpp::tokens::calculate_token_id; +use dpp::version::PlatformVersion; + +/// A builder to configure and broadcast token mint transitions +pub struct TokenMintTransitionBuilder<'a> { + data_contract: &'a DataContract, + token_position: TokenContractPosition, + issuer_id: Identifier, + amount: TokenAmount, + recipient_id: Option, + public_note: Option, + settings: Option, + user_fee_increase: Option, + using_group_info: Option, +} + +impl<'a> TokenMintTransitionBuilder<'a> { + /// Start building a mint tokens request for the provided DataContract. + /// + /// # Arguments + /// + /// * `data_contract` - A reference to the data contract + /// * `token_position` - The position of the token in the contract + /// * `issuer_id` - The identifier of the issuer + /// * `amount` - The amount of tokens to mint + /// + /// # Returns + /// + /// * `Self` - The new builder instance + pub fn new( + data_contract: &'a DataContract, + token_position: TokenContractPosition, + issuer_id: Identifier, + amount: TokenAmount, + ) -> Self { + // TODO: Validate token position + + Self { + data_contract, + token_position, + issuer_id, + amount, + recipient_id: None, + public_note: None, + settings: None, + user_fee_increase: None, + using_group_info: None, + } + } + + /// Sets the recipient identity ID for the minted tokens + /// + /// # Arguments + /// + /// * `issued_to_id` - The identifier of the recipient + /// + /// # Returns + /// + /// * `Self` - The updated builder + pub fn issued_to_identity_id(mut self, issued_to_id: Identifier) -> Self { + self.recipient_id = Some(issued_to_id); + + // TODO: Validate with minting_allow_choosing_destination + + self + } + + /// Adds a public note to the token mint transition + /// + /// # Arguments + /// + /// * `note` - The public note to add + /// + /// # Returns + /// + /// * `Self` - The updated builder + pub fn with_public_note(mut self, note: String) -> Self { + self.public_note = Some(note); + self + } + + /// Adds a user fee increase to the token mint transition + /// + /// # Arguments + /// + /// * `user_fee_increase` - The user fee increase to add + /// + /// # Returns + /// + /// * `Self` - The updated builder + pub fn with_user_fee_increase(mut self, user_fee_increase: UserFeeIncrease) -> Self { + self.user_fee_increase = Some(user_fee_increase); + self + } + + /// Adds group information to the token mint transition + /// + /// # Arguments + /// + /// * `group_info` - The group information to add + /// + /// # Returns + /// + /// * `Self` - The updated builder + pub fn with_using_group_info(mut self, group_info: GroupStateTransitionInfoStatus) -> Self { + self.using_group_info = Some(group_info); + + // TODO: Simplify group actions automatically find position if group action is required + + self + } + + /// Adds settings to the token mint transition + /// + /// # Arguments + /// + /// * `settings` - The settings to add + /// + /// # Returns + /// + /// * `Self` - The updated builder + pub fn with_settings(mut self, settings: PutSettings) -> Self { + self.settings = Some(settings); + self + } +} + +impl StateTransitionBuilder for TokenMintTransitionBuilder<'_> { + /// Returns the settings for the token mint transition + /// + /// # Returns + /// + /// * `Option` - The settings, if any + fn settings(&self) -> Option { + self.settings + } + + /// Signs the token mint transition + /// + /// # Arguments + /// + /// * `sdk` - The SDK instance + /// * `identity_public_key` - The public key of the identity + /// * `signer` - The signer instance + /// * `platform_version` - The platform version + /// + /// # Returns + /// + /// * `Result` - The signed state transition or an error + async fn sign( + &self, + sdk: &Sdk, + identity_public_key: &IdentityPublicKey, + signer: &impl Signer, + platform_version: &PlatformVersion, + ) -> Result { + let token_id = Identifier::from(calculate_token_id( + self.data_contract.id().as_bytes(), + self.token_position, + )); + + let identity_contract_nonce = sdk + .get_identity_contract_nonce( + self.issuer_id, + self.data_contract.id(), + false, + self.settings, + ) + .await?; + + let state_transition = BatchTransition::new_token_mint_transition( + token_id, + self.issuer_id, + self.data_contract.id(), + self.token_position, + self.amount, + self.recipient_id, + self.public_note.clone(), + self.using_group_info, + identity_public_key, + identity_contract_nonce, + self.user_fee_increase.unwrap_or_default(), + signer, + platform_version, + None, + None, + None, + )?; + + Ok(state_transition) + } +} diff --git a/packages/rs-sdk/src/platform/transition/fungible_tokens/mod.rs b/packages/rs-sdk/src/platform/transition/fungible_tokens/mod.rs new file mode 100644 index 00000000000..add8db703aa --- /dev/null +++ b/packages/rs-sdk/src/platform/transition/fungible_tokens/mod.rs @@ -0,0 +1,9 @@ +//! Fungible token state transitions + +pub mod burn; +pub mod destroy; +pub mod emergency_action; +pub mod freeze; +pub mod mint; +pub mod transfer; +pub mod unfreeze; diff --git a/packages/rs-sdk/src/platform/transition/fungible_tokens/transfer.rs b/packages/rs-sdk/src/platform/transition/fungible_tokens/transfer.rs new file mode 100644 index 00000000000..6908c8864d0 --- /dev/null +++ b/packages/rs-sdk/src/platform/transition/fungible_tokens/transfer.rs @@ -0,0 +1,214 @@ +use crate::platform::transition::builder::StateTransitionBuilder; +use crate::platform::transition::put_settings::PutSettings; +use crate::platform::Identifier; +use crate::{Error, Sdk}; +use dpp::balances::credits::TokenAmount; +use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::data_contract::{DataContract, TokenContractPosition}; +use dpp::identity::signer::Signer; +use dpp::identity::IdentityPublicKey; +use dpp::prelude::UserFeeIncrease; +use dpp::state_transition::batch_transition::methods::v1::DocumentsBatchTransitionMethodsV1; +use dpp::state_transition::batch_transition::token_transfer_transition::{ + PrivateEncryptedNote, SharedEncryptedNote, +}; +use dpp::state_transition::batch_transition::BatchTransition; +use dpp::state_transition::StateTransition; +use dpp::tokens::calculate_token_id; +use dpp::version::PlatformVersion; + +/// A builder to configure and broadcast token transfer transitions +pub struct TokenTransferTransitionBuilder<'a> { + data_contract: &'a DataContract, + token_position: TokenContractPosition, + issuer_id: Identifier, + amount: TokenAmount, + recipient_id: Identifier, + public_note: Option, + shared_encrypted_note: Option, + private_encrypted_note: Option, + settings: Option, + user_fee_increase: Option, +} + +impl<'a> TokenTransferTransitionBuilder<'a> { + /// Start building a mint tokens request for the provided DataContract. + /// + /// # Arguments + /// + /// * `data_contract` - A reference to the data contract + /// * `token_position` - The position of the token in the contract + /// * `sender_id` - The identifier of the sender + /// * `recipient_id` - The identifier of the recipient + /// * `amount` - The amount of tokens to transfer + /// + /// # Returns + /// + /// * `Self` - The new builder instance + pub fn new( + data_contract: &'a DataContract, + token_position: TokenContractPosition, + sender_id: Identifier, + recipient_id: Identifier, + amount: TokenAmount, + ) -> Self { + // TODO: Validate token position + + Self { + data_contract, + token_position, + issuer_id: sender_id, + amount, + recipient_id, + public_note: None, + settings: None, + user_fee_increase: None, + private_encrypted_note: None, + shared_encrypted_note: None, + } + } + + /// Adds a shared encrypted note to the token transfer transition + /// + /// # Arguments + /// + /// * `shared_encrypted_note` - The shared encrypted note to add + /// + /// # Returns + /// + /// * `Self` - The updated builder + pub fn with_shared_encrypted_note( + mut self, + shared_encrypted_note: SharedEncryptedNote, + ) -> Self { + self.shared_encrypted_note = Some(shared_encrypted_note); + self + } + + /// Adds a public note to the token transfer transition + /// + /// # Arguments + /// + /// * `note` - The public note to add + /// + /// # Returns + /// + /// * `Self` - The updated builder + pub fn with_public_note(mut self, note: String) -> Self { + self.public_note = Some(note); + self + } + + /// Adds a private encrypted note to the token transfer transition + /// + /// # Arguments + /// + /// * `private_encrypted_note` - The private encrypted note to add + /// + /// # Returns + /// + /// * `Self` - The updated builder + pub fn with_private_encrypted_note( + mut self, + private_encrypted_note: PrivateEncryptedNote, + ) -> Self { + self.private_encrypted_note = Some(private_encrypted_note); + + self + } + + /// Adds a user fee increase to the token transfer transition + /// + /// # Arguments + /// + /// * `user_fee_increase` - The user fee increase to add + /// + /// # Returns + /// + /// * `Self` - The updated builder + pub fn with_user_fee_increase(mut self, user_fee_increase: UserFeeIncrease) -> Self { + self.user_fee_increase = Some(user_fee_increase); + self + } + + /// Adds settings to the token transfer transition + /// + /// # Arguments + /// + /// * `settings` - The settings to add + /// + /// # Returns + /// + /// * `Self` - The updated builder + pub fn with_settings(mut self, settings: PutSettings) -> Self { + self.settings = Some(settings); + self + } +} + +impl StateTransitionBuilder for TokenTransferTransitionBuilder<'_> { + /// Returns the settings for the token transfer transition + /// + /// # Returns + /// + /// * `Option` - The settings, if any + fn settings(&self) -> Option { + self.settings + } + + /// Signs the token transfer transition + /// + /// # Arguments + /// + /// * `sdk` - The SDK instance + /// * `identity_public_key` - The public key of the identity + /// * `signer` - The signer instance + /// * `platform_version` - The platform version + /// + /// # Returns + /// + /// * `Result` - The signed state transition or an error + async fn sign( + &self, + sdk: &Sdk, + identity_public_key: &IdentityPublicKey, + signer: &impl Signer, + platform_version: &PlatformVersion, + ) -> Result { + let token_id = Identifier::from(calculate_token_id( + self.data_contract.id().as_bytes(), + self.token_position, + )); + + let identity_contract_nonce = sdk + .get_identity_contract_nonce( + self.issuer_id, + self.data_contract.id(), + false, + self.settings, + ) + .await?; + + let state_transition = BatchTransition::new_token_transfer_transition( + token_id, + self.issuer_id, + self.data_contract.id(), + self.token_position, + self.amount, + self.recipient_id, + self.public_note.clone(), + self.shared_encrypted_note.clone(), + self.private_encrypted_note.clone(), + identity_public_key, + identity_contract_nonce, + self.user_fee_increase.unwrap_or_default(), + signer, + platform_version, + None, + None, + None, + )?; + + Ok(state_transition) + } +} diff --git a/packages/rs-sdk/src/platform/transition/fungible_tokens/unfreeze.rs b/packages/rs-sdk/src/platform/transition/fungible_tokens/unfreeze.rs new file mode 100644 index 00000000000..6cb837a18e1 --- /dev/null +++ b/packages/rs-sdk/src/platform/transition/fungible_tokens/unfreeze.rs @@ -0,0 +1,185 @@ +use crate::platform::transition::builder::StateTransitionBuilder; +use crate::platform::transition::put_settings::PutSettings; +use crate::platform::Identifier; +use crate::{Error, Sdk}; +use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::data_contract::{DataContract, TokenContractPosition}; +use dpp::group::GroupStateTransitionInfoStatus; +use dpp::identity::signer::Signer; +use dpp::identity::IdentityPublicKey; +use dpp::prelude::UserFeeIncrease; +use dpp::state_transition::batch_transition::methods::v1::DocumentsBatchTransitionMethodsV1; +use dpp::state_transition::batch_transition::BatchTransition; +use dpp::state_transition::StateTransition; +use dpp::tokens::calculate_token_id; +use dpp::version::PlatformVersion; + +/// A builder to configure and broadcast token unfreeze transitions +pub struct TokenUnfreezeTransitionBuilder<'a> { + data_contract: &'a DataContract, + token_position: TokenContractPosition, + actor_id: Identifier, + unfreeze_identity_id: Identifier, + public_note: Option, + settings: Option, + user_fee_increase: Option, + using_group_info: Option, +} + +impl<'a> TokenUnfreezeTransitionBuilder<'a> { + /// Start building a mint tokens request for the provided DataContract. + /// + /// # Arguments + /// + /// * `data_contract` - A reference to the data contract + /// * `token_position` - The position of the token in the contract + /// * `actor_id` - The identifier of the actor + /// * `unfreeze_identity_id` - The identifier of the identity to unfreeze + /// + /// # Returns + /// + /// * `Self` - The new builder instance + pub fn new( + data_contract: &'a DataContract, + token_position: TokenContractPosition, + actor_id: Identifier, + unfreeze_identity_id: Identifier, + ) -> Self { + // TODO: Validate token position + + Self { + data_contract, + token_position, + actor_id, + unfreeze_identity_id, + public_note: None, + settings: None, + user_fee_increase: None, + using_group_info: None, + } + } + + /// Adds a public note to the token unfreeze transition + /// + /// # Arguments + /// + /// * `note` - The public note to add + /// + /// # Returns + /// + /// * `Self` - The updated builder + pub fn with_public_note(mut self, note: String) -> Self { + self.public_note = Some(note); + self + } + + /// Adds a user fee increase to the token unfreeze transition + /// + /// # Arguments + /// + /// * `user_fee_increase` - The user fee increase to add + /// + /// # Returns + /// + /// * `Self` - The updated builder + pub fn with_user_fee_increase(mut self, user_fee_increase: UserFeeIncrease) -> Self { + self.user_fee_increase = Some(user_fee_increase); + self + } + + /// Adds group information to the token unfreeze transition + /// + /// # Arguments + /// + /// * `group_info` - The group information to add + /// + /// # Returns + /// + /// * `Self` - The updated builder + pub fn with_using_group_info(mut self, group_info: GroupStateTransitionInfoStatus) -> Self { + self.using_group_info = Some(group_info); + + // TODO: Simplify group actions automatically find position if group action is required + + self + } + + /// Adds settings to the token unfreeze transition + /// + /// # Arguments + /// + /// * `settings` - The settings to add + /// + /// # Returns + /// + /// * `Self` - The updated builder + pub fn with_settings(mut self, settings: PutSettings) -> Self { + self.settings = Some(settings); + self + } +} + +impl StateTransitionBuilder for TokenUnfreezeTransitionBuilder<'_> { + /// Returns the settings for the token unfreeze transition + /// + /// # Returns + /// + /// * `Option` - The settings, if any + fn settings(&self) -> Option { + self.settings + } + + /// Signs the token unfreeze transition + /// + /// # Arguments + /// + /// * `sdk` - The SDK instance + /// * `identity_public_key` - The public key of the identity + /// * `signer` - The signer instance + /// * `platform_version` - The platform version + /// + /// # Returns + /// + /// * `Result` - The signed state transition or an error + async fn sign( + &self, + sdk: &Sdk, + identity_public_key: &IdentityPublicKey, + signer: &impl Signer, + platform_version: &PlatformVersion, + ) -> Result { + let token_id = Identifier::from(calculate_token_id( + self.data_contract.id().as_bytes(), + self.token_position, + )); + + let identity_contract_nonce = sdk + .get_identity_contract_nonce( + self.actor_id, + self.data_contract.id(), + false, + self.settings, + ) + .await?; + + let state_transition = BatchTransition::new_token_unfreeze_transition( + token_id, + self.actor_id, + self.data_contract.id(), + self.token_position, + self.unfreeze_identity_id, + self.public_note.clone(), + self.using_group_info, + identity_public_key, + identity_contract_nonce, + self.user_fee_increase.unwrap_or_default(), + signer, + platform_version, + None, + None, + None, + )?; + + Ok(state_transition) + } +} diff --git a/packages/wasm-dpp/Cargo.toml b/packages/wasm-dpp/Cargo.toml index d7575a859ce..32e609e1cd0 100644 --- a/packages/wasm-dpp/Cargo.toml +++ b/packages/wasm-dpp/Cargo.toml @@ -40,6 +40,7 @@ dpp = { path = "../rs-dpp", default-features = false, features = [ "extended-document", "document-value-conversion", "document-json-conversion", + "system_contracts" ] } itertools = { version = "0.13" } log = { version = "0.4.6" } diff --git a/packages/wasm-dpp/src/data_contract/data_contract.rs b/packages/wasm-dpp/src/data_contract/data_contract.rs index e0b2232f52b..0a077c0da86 100644 --- a/packages/wasm-dpp/src/data_contract/data_contract.rs +++ b/packages/wasm-dpp/src/data_contract/data_contract.rs @@ -7,10 +7,11 @@ pub use serde::{Deserialize, Serialize}; use wasm_bindgen::prelude::*; use dpp::data_contract::schema::DataContractSchemaMethodsV0; -use dpp::data_contract::DataContract; +use dpp::data_contract::{DataContract, TokenContractPosition}; use dpp::platform_value::{platform_value, Value}; use dpp::data_contract::accessors::v0::{DataContractV0Getters, DataContractV0Setters}; +use dpp::data_contract::accessors::v1::DataContractV1Getters; use dpp::data_contract::config::DataContractConfig; use dpp::data_contract::conversion::json::DataContractJsonConversionMethodsV0; use dpp::data_contract::conversion::value::v0::DataContractValueConversionMethodsV0; @@ -22,6 +23,7 @@ use dpp::serialization::PlatformSerializableWithPlatformVersion; use dpp::version::PlatformVersion; use dpp::ProtocolError; +use crate::data_contract::tokens::TokenConfigurationWasm; use crate::identifier::identifier_from_js_value; use crate::metadata::MetadataWasm; use crate::utils::get_bool_from_options; @@ -448,6 +450,18 @@ impl DataContractWasm { .with_js_error() .map(Into::into) } + + #[wasm_bindgen(js_name=getTokenConfiguration)] + pub fn token_configuration( + &self, + token_contract_position: TokenContractPosition, + ) -> Result { + self.inner + .expected_token_configuration(token_contract_position) + .map_err(ProtocolError::from) + .with_js_error() + .map(|token_configuration| token_configuration.clone().into()) + } } impl Inner for DataContractWasm { diff --git a/packages/wasm-dpp/src/data_contract/mod.rs b/packages/wasm-dpp/src/data_contract/mod.rs index baf6fb394a5..76458e5eb06 100644 --- a/packages/wasm-dpp/src/data_contract/mod.rs +++ b/packages/wasm-dpp/src/data_contract/mod.rs @@ -8,6 +8,7 @@ pub mod errors; mod state_transition; mod data_contract_facade; +pub mod tokens; // mod index; pub use data_contract_facade::DataContractFacadeWasm; diff --git a/packages/wasm-dpp/src/data_contract/tokens.rs b/packages/wasm-dpp/src/data_contract/tokens.rs new file mode 100644 index 00000000000..90f12e7f8de --- /dev/null +++ b/packages/wasm-dpp/src/data_contract/tokens.rs @@ -0,0 +1,18 @@ +use dpp::data_contract::TokenConfiguration; +use wasm_bindgen::prelude::wasm_bindgen; + +#[derive(Debug, Clone)] +#[wasm_bindgen(js_name = "TokenConfiguration")] +pub struct TokenConfigurationWasm(TokenConfiguration); + +impl From for TokenConfigurationWasm { + fn from(value: TokenConfiguration) -> Self { + Self(value) + } +} + +impl Into for TokenConfigurationWasm { + fn into(self) -> TokenConfiguration { + self.0 + } +} diff --git a/packages/wasm-dpp/src/document/state_transition/batch_transition/mod.rs b/packages/wasm-dpp/src/document/state_transition/batch_transition/mod.rs index 6dfadbf9852..2101f9cf7ba 100644 --- a/packages/wasm-dpp/src/document/state_transition/batch_transition/mod.rs +++ b/packages/wasm-dpp/src/document/state_transition/batch_transition/mod.rs @@ -30,6 +30,8 @@ use dpp::state_transition::batch_transition::batched_transition::BatchedTransiti use dpp::state_transition::batch_transition::methods::v0::DocumentsBatchTransitionMethodsV0; use crate::batch_transition::batched_transition::BatchedTransitionWasm; +use crate::batch_transition::document_transition::DocumentTransitionWasm; +use crate::batch_transition::token_transition::TokenTransitionWasm; use dpp::state_transition::StateTransitionIdentitySigned; mod batched_transition; @@ -106,8 +108,11 @@ impl BatchTransitionWasm { let array = js_sys::Array::new(); for tr in self.0.transitions_iter() { - let transition: BatchedTransitionWasm = tr.to_owned_transition().into(); - array.push(&transition.into()); + let js_value = match tr.to_owned_transition() { + BatchedTransition::Token(doc) => TokenTransitionWasm::from(doc).into(), + BatchedTransition::Document(tok) => DocumentTransitionWasm::from(tok).into(), + }; + array.push(&js_value); } array diff --git a/packages/wasm-dpp/src/document/state_transition/batch_transition/token_transition/burn.rs b/packages/wasm-dpp/src/document/state_transition/batch_transition/token_transition/burn.rs new file mode 100644 index 00000000000..d3b31f9f889 --- /dev/null +++ b/packages/wasm-dpp/src/document/state_transition/batch_transition/token_transition/burn.rs @@ -0,0 +1,12 @@ +use dpp::state_transition::batch_transition::TokenBurnTransition; +use wasm_bindgen::prelude::wasm_bindgen; + +#[wasm_bindgen(js_name=TokenBurnTransition)] +#[derive(Debug, Clone)] +pub struct TokenBurnTransitionWasm(TokenBurnTransition); + +impl From for TokenBurnTransitionWasm { + fn from(value: TokenBurnTransition) -> Self { + Self(value) + } +} diff --git a/packages/wasm-dpp/src/document/state_transition/batch_transition/token_transition/config.rs b/packages/wasm-dpp/src/document/state_transition/batch_transition/token_transition/config.rs new file mode 100644 index 00000000000..10712d3cd8a --- /dev/null +++ b/packages/wasm-dpp/src/document/state_transition/batch_transition/token_transition/config.rs @@ -0,0 +1,12 @@ +use dpp::state_transition::batch_transition::TokenConfigUpdateTransition; +use wasm_bindgen::prelude::wasm_bindgen; + +#[wasm_bindgen(js_name=TokenConfigUpdateTransition)] +#[derive(Debug, Clone)] +pub struct TokenConfigUpdateTransitionWasm(TokenConfigUpdateTransition); + +impl From for TokenConfigUpdateTransitionWasm { + fn from(value: TokenConfigUpdateTransition) -> Self { + Self(value) + } +} diff --git a/packages/wasm-dpp/src/document/state_transition/batch_transition/token_transition/destroy.rs b/packages/wasm-dpp/src/document/state_transition/batch_transition/token_transition/destroy.rs new file mode 100644 index 00000000000..71d9a7f6195 --- /dev/null +++ b/packages/wasm-dpp/src/document/state_transition/batch_transition/token_transition/destroy.rs @@ -0,0 +1,22 @@ +use crate::identifier::IdentifierWrapper; +use wasm_bindgen::prelude::wasm_bindgen; +use dpp::state_transition::batch_transition::token_destroy_frozen_funds_transition::v0::v0_methods::TokenDestroyFrozenFundsTransitionV0Methods; +use dpp::state_transition::batch_transition::TokenDestroyFrozenFundsTransition; + +#[wasm_bindgen(js_name=TokenDestroyFrozenFundsTransition)] +#[derive(Debug, Clone)] +pub struct TokenDestroyFrozenFundsTransitionWasm(TokenDestroyFrozenFundsTransition); + +impl From for TokenDestroyFrozenFundsTransitionWasm { + fn from(value: TokenDestroyFrozenFundsTransition) -> Self { + Self(value) + } +} + +#[wasm_bindgen] +impl TokenDestroyFrozenFundsTransitionWasm { + #[wasm_bindgen(js_name=getFrozenIdentityId)] + pub fn frozen_identity_id(&self) -> IdentifierWrapper { + self.0.frozen_identity_id().into() + } +} diff --git a/packages/wasm-dpp/src/document/state_transition/batch_transition/token_transition/emergency_action.rs b/packages/wasm-dpp/src/document/state_transition/batch_transition/token_transition/emergency_action.rs new file mode 100644 index 00000000000..ba704f005af --- /dev/null +++ b/packages/wasm-dpp/src/document/state_transition/batch_transition/token_transition/emergency_action.rs @@ -0,0 +1,12 @@ +use dpp::state_transition::batch_transition::TokenEmergencyActionTransition; +use wasm_bindgen::prelude::wasm_bindgen; + +#[wasm_bindgen(js_name=TokenEmergencyActionTransition)] +#[derive(Debug, Clone)] +pub struct TokenEmergencyActionTransitionWasm(TokenEmergencyActionTransition); + +impl From for TokenEmergencyActionTransitionWasm { + fn from(value: TokenEmergencyActionTransition) -> Self { + Self(value) + } +} diff --git a/packages/wasm-dpp/src/document/state_transition/batch_transition/token_transition/freeze.rs b/packages/wasm-dpp/src/document/state_transition/batch_transition/token_transition/freeze.rs new file mode 100644 index 00000000000..5957967fe50 --- /dev/null +++ b/packages/wasm-dpp/src/document/state_transition/batch_transition/token_transition/freeze.rs @@ -0,0 +1,22 @@ +use crate::identifier::IdentifierWrapper; +use dpp::state_transition::batch_transition::token_freeze_transition::v0::v0_methods::TokenFreezeTransitionV0Methods; +use dpp::state_transition::batch_transition::TokenFreezeTransition; +use wasm_bindgen::prelude::wasm_bindgen; + +#[wasm_bindgen(js_name=TokenFreezeTransition)] +#[derive(Debug, Clone)] +pub struct TokenFreezeTransitionWasm(TokenFreezeTransition); + +impl From for TokenFreezeTransitionWasm { + fn from(value: TokenFreezeTransition) -> Self { + Self(value) + } +} + +#[wasm_bindgen] +impl TokenFreezeTransitionWasm { + #[wasm_bindgen(js_name=getFrozenIdentityId)] + pub fn frozen_identity_id(&self) -> IdentifierWrapper { + self.0.frozen_identity_id().into() + } +} diff --git a/packages/wasm-dpp/src/document/state_transition/batch_transition/token_transition/mint.rs b/packages/wasm-dpp/src/document/state_transition/batch_transition/token_transition/mint.rs new file mode 100644 index 00000000000..0edb35f6368 --- /dev/null +++ b/packages/wasm-dpp/src/document/state_transition/batch_transition/token_transition/mint.rs @@ -0,0 +1,31 @@ +use crate::identifier::IdentifierWrapper; +use crate::tokens::TokenConfigurationWasm; +use crate::utils::WithJsError; +use dpp::state_transition::batch_transition::token_mint_transition::v0::v0_methods::TokenMintTransitionV0Methods; +use dpp::state_transition::batch_transition::TokenMintTransition; +use wasm_bindgen::prelude::wasm_bindgen; +use wasm_bindgen::JsValue; + +#[wasm_bindgen(js_name=TokenMintTransition)] +#[derive(Debug, Clone)] +pub struct TokenMintTransitionWasm(TokenMintTransition); + +impl From for TokenMintTransitionWasm { + fn from(value: TokenMintTransition) -> Self { + Self(value) + } +} + +#[wasm_bindgen] +impl TokenMintTransitionWasm { + #[wasm_bindgen(js_name=getRecipientId)] + pub fn recipient_id( + &self, + token_configuration: TokenConfigurationWasm, + ) -> Result { + self.0 + .recipient_id(&token_configuration.into()) + .with_js_error() + .map(Into::into) + } +} diff --git a/packages/wasm-dpp/src/document/state_transition/batch_transition/token_transition/mod.rs b/packages/wasm-dpp/src/document/state_transition/batch_transition/token_transition/mod.rs index 7b10fb55c14..8a0fb050c00 100644 --- a/packages/wasm-dpp/src/document/state_transition/batch_transition/token_transition/mod.rs +++ b/packages/wasm-dpp/src/document/state_transition/batch_transition/token_transition/mod.rs @@ -1,5 +1,55 @@ -use dpp::state_transition::batch_transition::batched_transition::token_transition::TokenTransition; +mod burn; +mod config; +mod destroy; +mod emergency_action; +mod freeze; +mod mint; +mod transfer; +mod unfreeze; + +use crate::batch_transition::token_transition::burn::TokenBurnTransitionWasm; +use crate::batch_transition::token_transition::config::TokenConfigUpdateTransitionWasm; +use crate::batch_transition::token_transition::destroy::TokenDestroyFrozenFundsTransitionWasm; +use crate::batch_transition::token_transition::emergency_action::TokenEmergencyActionTransitionWasm; +use crate::batch_transition::token_transition::freeze::TokenFreezeTransitionWasm; +use crate::batch_transition::token_transition::mint::TokenMintTransitionWasm; +use crate::batch_transition::token_transition::transfer::TokenTransferTransitionWasm; +use crate::batch_transition::token_transition::unfreeze::TokenUnfreezeTransitionWasm; +use crate::identifier::IdentifierWrapper; +use dpp::state_transition::batch_transition::batched_transition::token_transition::{ + TokenTransition, TokenTransitionV0Methods, +}; +use dpp::state_transition::batch_transition::token_base_transition::v0::v0_methods::TokenBaseTransitionV0Methods; +use js_sys::Number; use wasm_bindgen::prelude::wasm_bindgen; +use wasm_bindgen::JsValue; + +#[wasm_bindgen] +pub enum TokenTransitionType { + Burn, + Mint, + Transfer, + Freeze, + Unfreeze, + DestroyFrozenFunds, + EmergencyAction, + ConfigUpdate, +} + +impl From<&TokenTransition> for TokenTransitionType { + fn from(t: &TokenTransition) -> Self { + match t { + TokenTransition::Burn(_) => TokenTransitionType::Burn, + TokenTransition::Mint(_) => TokenTransitionType::Mint, + TokenTransition::Transfer(_) => TokenTransitionType::Transfer, + TokenTransition::Freeze(_) => TokenTransitionType::Freeze, + TokenTransition::Unfreeze(_) => TokenTransitionType::Unfreeze, + TokenTransition::DestroyFrozenFunds(_) => TokenTransitionType::DestroyFrozenFunds, + TokenTransition::EmergencyAction(_) => TokenTransitionType::EmergencyAction, + TokenTransition::ConfigUpdate(_) => TokenTransitionType::ConfigUpdate, + } + } +} #[wasm_bindgen(js_name=TokenTransition)] #[derive(Debug, Clone)] @@ -16,3 +66,52 @@ impl From for TokenTransition { t.0 } } + +#[wasm_bindgen] +impl TokenTransitionWasm { + #[wasm_bindgen(js_name=getTransitionType)] + pub fn transition_type(&self) -> TokenTransitionType { + TokenTransitionType::from(&self.0) + } + + #[wasm_bindgen(js_name=getTokenId)] + pub fn token_id(&self) -> IdentifierWrapper { + self.0.base().token_id().into() + } + + #[wasm_bindgen(js_name=getTokenContractPosition)] + pub fn token_contract_position(&self) -> Number { + self.0.base().token_contract_position().into() + } + + #[wasm_bindgen(js_name=getDataContractId)] + pub fn data_contract_id(&self) -> IdentifierWrapper { + self.0.base().data_contract_id().into() + } + + #[wasm_bindgen(js_name=toTransition)] + pub fn to_transition(&self) -> JsValue { + match &self.0 { + TokenTransition::Burn(burn) => TokenBurnTransitionWasm::from(burn.clone()).into(), + TokenTransition::Mint(mint) => TokenMintTransitionWasm::from(mint.clone()).into(), + TokenTransition::Transfer(transfer) => { + TokenTransferTransitionWasm::from(transfer.clone()).into() + } + TokenTransition::Freeze(freeze) => { + TokenFreezeTransitionWasm::from(freeze.clone()).into() + } + TokenTransition::Unfreeze(unfreeze) => { + TokenUnfreezeTransitionWasm::from(unfreeze.clone()).into() + } + TokenTransition::DestroyFrozenFunds(destroy_frozen_funds) => { + TokenDestroyFrozenFundsTransitionWasm::from(destroy_frozen_funds.clone()).into() + } + TokenTransition::EmergencyAction(emergency_action) => { + TokenEmergencyActionTransitionWasm::from(emergency_action.clone()).into() + } + TokenTransition::ConfigUpdate(config_update) => { + TokenConfigUpdateTransitionWasm::from(config_update.clone()).into() + } + } + } +} diff --git a/packages/wasm-dpp/src/document/state_transition/batch_transition/token_transition/transfer.rs b/packages/wasm-dpp/src/document/state_transition/batch_transition/token_transition/transfer.rs new file mode 100644 index 00000000000..316a16a2d4f --- /dev/null +++ b/packages/wasm-dpp/src/document/state_transition/batch_transition/token_transition/transfer.rs @@ -0,0 +1,22 @@ +use crate::identifier::IdentifierWrapper; +use dpp::state_transition::batch_transition::token_transfer_transition::v0::v0_methods::TokenTransferTransitionV0Methods; +use dpp::state_transition::batch_transition::TokenTransferTransition; +use wasm_bindgen::prelude::wasm_bindgen; + +#[wasm_bindgen(js_name=TokenTransferTransition)] +#[derive(Debug, Clone)] +pub struct TokenTransferTransitionWasm(TokenTransferTransition); + +impl From for TokenTransferTransitionWasm { + fn from(value: TokenTransferTransition) -> Self { + Self(value) + } +} + +#[wasm_bindgen] +impl TokenTransferTransitionWasm { + #[wasm_bindgen(js_name=getRecipientId)] + pub fn recipient_id(&self) -> IdentifierWrapper { + self.0.recipient_id().into() + } +} diff --git a/packages/wasm-dpp/src/document/state_transition/batch_transition/token_transition/unfreeze.rs b/packages/wasm-dpp/src/document/state_transition/batch_transition/token_transition/unfreeze.rs new file mode 100644 index 00000000000..72d65555db8 --- /dev/null +++ b/packages/wasm-dpp/src/document/state_transition/batch_transition/token_transition/unfreeze.rs @@ -0,0 +1,22 @@ +use crate::identifier::IdentifierWrapper; +use dpp::state_transition::batch_transition::token_unfreeze_transition::v0::v0_methods::TokenUnfreezeTransitionV0Methods; +use dpp::state_transition::batch_transition::TokenUnfreezeTransition; +use wasm_bindgen::prelude::wasm_bindgen; + +#[wasm_bindgen(js_name=TokenUnfreezeTransition)] +#[derive(Debug, Clone)] +pub struct TokenUnfreezeTransitionWasm(TokenUnfreezeTransition); + +impl From for TokenUnfreezeTransitionWasm { + fn from(value: TokenUnfreezeTransition) -> Self { + Self(value) + } +} + +#[wasm_bindgen] +impl TokenUnfreezeTransitionWasm { + #[wasm_bindgen(js_name=getFrozenIdentityId)] + pub fn frozen_identity_id(&self) -> IdentifierWrapper { + self.0.frozen_identity_id().into() + } +}