From 782f196e8908e0bb64fd11bf1a36986bea8b6de6 Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Thu, 15 May 2025 16:11:55 +0700 Subject: [PATCH] feat(sdk): token purchase and set price transitions --- .../transition/fungible_tokens/mod.rs | 2 + .../transition/fungible_tokens/purchase.rs | 141 ++++++++++++++ .../transition/fungible_tokens/set_price.rs | 174 ++++++++++++++++++ 3 files changed, 317 insertions(+) create mode 100644 packages/rs-sdk/src/platform/transition/fungible_tokens/purchase.rs create mode 100644 packages/rs-sdk/src/platform/transition/fungible_tokens/set_price.rs diff --git a/packages/rs-sdk/src/platform/transition/fungible_tokens/mod.rs b/packages/rs-sdk/src/platform/transition/fungible_tokens/mod.rs index 71c24371ce2..eec8c140062 100644 --- a/packages/rs-sdk/src/platform/transition/fungible_tokens/mod.rs +++ b/packages/rs-sdk/src/platform/transition/fungible_tokens/mod.rs @@ -7,5 +7,7 @@ pub mod destroy; pub mod emergency_action; pub mod freeze; pub mod mint; +pub mod purchase; +pub mod set_price; pub mod transfer; pub mod unfreeze; diff --git a/packages/rs-sdk/src/platform/transition/fungible_tokens/purchase.rs b/packages/rs-sdk/src/platform/transition/fungible_tokens/purchase.rs new file mode 100644 index 00000000000..c85ae32144f --- /dev/null +++ b/packages/rs-sdk/src/platform/transition/fungible_tokens/purchase.rs @@ -0,0 +1,141 @@ +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::fee::Credits; +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::methods::StateTransitionCreationOptions; +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 purchase transitions +pub struct TokenDirectPurchaseTransitionBuilder<'a> { + data_contract: &'a DataContract, + token_position: TokenContractPosition, + actor_id: Identifier, + amount: TokenAmount, + total_agreed_price: Credits, + settings: Option, + user_fee_increase: Option, +} + +impl<'a> TokenDirectPurchaseTransitionBuilder<'a> { + /// Start building a purchase 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 purchase + /// + /// # Returns + /// + /// * `Self` - The new builder instance + pub fn new( + data_contract: &'a DataContract, + token_position: TokenContractPosition, + actor_id: Identifier, + amount: TokenAmount, + total_agreed_price: Credits, + ) -> Self { + // TODO: Validate token position + + Self { + data_contract, + token_position, + actor_id, + amount, + total_agreed_price, + settings: None, + user_fee_increase: None, + } + } + + /// Adds a user fee increase to the token purchase 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 purchase 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 + } + + /// Signs the token purchase 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 + pub async fn sign( + &self, + sdk: &Sdk, + identity_public_key: &IdentityPublicKey, + signer: &impl Signer, + platform_version: &PlatformVersion, + options: Option, + ) -> 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(), + true, + self.settings, + ) + .await?; + + let state_transition = BatchTransition::new_token_direct_purchase_transition( + token_id, + self.actor_id, + self.data_contract.id(), + self.token_position, + self.amount, + self.total_agreed_price, + identity_public_key, + identity_contract_nonce, + self.user_fee_increase.unwrap_or_default(), + signer, + platform_version, + options, + )?; + + Ok(state_transition) + } +} diff --git a/packages/rs-sdk/src/platform/transition/fungible_tokens/set_price.rs b/packages/rs-sdk/src/platform/transition/fungible_tokens/set_price.rs new file mode 100644 index 00000000000..51ff261d4e7 --- /dev/null +++ b/packages/rs-sdk/src/platform/transition/fungible_tokens/set_price.rs @@ -0,0 +1,174 @@ +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::methods::StateTransitionCreationOptions; +use dpp::state_transition::batch_transition::BatchTransition; +use dpp::state_transition::StateTransition; +use dpp::tokens::calculate_token_id; +use dpp::tokens::token_pricing_schedule::TokenPricingSchedule; +use dpp::version::PlatformVersion; + +/// A builder to configure and broadcast token change direct purchase price transitions +pub struct TokenChangeDirectPurchasePriceTransitionBuilder<'a> { + data_contract: &'a DataContract, + token_position: TokenContractPosition, + actor_id: Identifier, + token_pricing_schedule: Option, + public_note: Option, + settings: Option, + user_fee_increase: Option, + using_group_info: Option, +} + +impl<'a> TokenChangeDirectPurchasePriceTransitionBuilder<'a> { + /// Start building a change direct purchase price 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 change direct purchase price + /// + /// # Returns + /// + /// * `Self` - The new builder instance + pub fn new( + data_contract: &'a DataContract, + token_position: TokenContractPosition, + issuer_id: Identifier, + token_pricing_schedule: Option, + ) -> Self { + // TODO: Validate token position + + Self { + data_contract, + token_position, + actor_id: issuer_id, + token_pricing_schedule, + public_note: None, + settings: None, + user_fee_increase: None, + using_group_info: None, + } + } + + /// Adds a public note to the token change direct purchase price 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 change direct purchase price 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 change direct purchase price 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 change direct purchase price 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 + } + + /// Signs the token change direct purchase price 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 + pub async fn sign( + &self, + sdk: &Sdk, + identity_public_key: &IdentityPublicKey, + signer: &impl Signer, + platform_version: &PlatformVersion, + options: Option, + ) -> 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(), + true, + self.settings, + ) + .await?; + + let state_transition = BatchTransition::new_token_change_direct_purchase_price_transition( + token_id, + self.actor_id, + self.data_contract.id(), + self.token_position, + self.token_pricing_schedule.clone(), + self.public_note.clone(), + self.using_group_info, + identity_public_key, + identity_contract_nonce, + self.user_fee_increase.unwrap_or_default(), + signer, + platform_version, + options, + )?; + + Ok(state_transition) + } +}