Skip to content

Commit

Permalink
feat(sdk): added transfer transition to rs-sdk (#2289)
Browse files Browse the repository at this point in the history
  • Loading branch information
QuantumExplorer authored Oct 29, 2024
1 parent 90980d9 commit 244f5f9
Show file tree
Hide file tree
Showing 8 changed files with 224 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,57 @@
mod v0;

pub use v0::*;

use crate::state_transition::identity_credit_transfer_transition::IdentityCreditTransferTransition;
#[cfg(feature = "state-transition-signing")]
use crate::{
identity::{signer::Signer, Identity, IdentityPublicKey},
prelude::{IdentityNonce, UserFeeIncrease},
state_transition::{
identity_credit_transfer_transition::v0::IdentityCreditTransferTransitionV0,
StateTransition,
},
ProtocolError,
};
#[cfg(feature = "state-transition-signing")]
use platform_value::Identifier;
#[cfg(feature = "state-transition-signing")]
use platform_version::version::{FeatureVersion, PlatformVersion};

impl IdentityCreditTransferTransitionMethodsV0 for IdentityCreditTransferTransition {}
impl IdentityCreditTransferTransitionMethodsV0 for IdentityCreditTransferTransition {
#[cfg(feature = "state-transition-signing")]
fn try_from_identity<S: Signer>(
identity: &Identity,
to_identity_with_identifier: Identifier,
amount: u64,
user_fee_increase: UserFeeIncrease,
signer: S,
signing_withdrawal_key_to_use: Option<&IdentityPublicKey>,
nonce: IdentityNonce,
platform_version: &PlatformVersion,
version: Option<FeatureVersion>,
) -> Result<StateTransition, ProtocolError> {
match version.unwrap_or(
platform_version
.dpp
.state_transition_conversion_versions
.identity_to_identity_transfer_transition,
) {
0 => Ok(IdentityCreditTransferTransitionV0::try_from_identity(
identity,
to_identity_with_identifier,
amount,
user_fee_increase,
signer,
signing_withdrawal_key_to_use,
nonce,
platform_version,
version,
)?),
version => Err(ProtocolError::UnknownVersionMismatch {
method: "IdentityCreditTransferTransition::try_from_identity".to_string(),
known_versions: vec![0],
received: version,
}),
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,30 @@
#[cfg(feature = "state-transition-signing")]
use crate::{
identity::{signer::Signer, Identity, IdentityPublicKey},
prelude::{IdentityNonce, UserFeeIncrease},
state_transition::StateTransition,
ProtocolError,
};
use platform_value::Identifier;

Check warning on line 8 in packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/methods/v0/mod.rs

View workflow job for this annotation

GitHub Actions / Rust packages (drive) / Linting

unused import: `platform_value::Identifier`

warning: unused import: `platform_value::Identifier` --> packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/methods/v0/mod.rs:8:5 | 8 | use platform_value::Identifier; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(unused_imports)]` on by default

Check warning on line 8 in packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/methods/v0/mod.rs

View workflow job for this annotation

GitHub Actions / Rust packages (drive-abci) / Linting

unused import: `platform_value::Identifier`

warning: unused import: `platform_value::Identifier` --> packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/methods/v0/mod.rs:8:5 | 8 | use platform_value::Identifier; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(unused_imports)]` on by default

Check warning on line 8 in packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/methods/v0/mod.rs

View workflow job for this annotation

GitHub Actions / Rust packages (drive) / Linting

unused import: `platform_value::Identifier`

warning: unused import: `platform_value::Identifier` --> packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/methods/v0/mod.rs:8:5 | 8 | use platform_value::Identifier; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(unused_imports)]` on by default

Check warning on line 8 in packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/methods/v0/mod.rs

View workflow job for this annotation

GitHub Actions / Rust packages (drive-abci) / Linting

unused import: `platform_value::Identifier`

warning: unused import: `platform_value::Identifier` --> packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/methods/v0/mod.rs:8:5 | 8 | use platform_value::Identifier; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(unused_imports)]` on by default
#[cfg(feature = "state-transition-signing")]
use platform_version::version::{FeatureVersion, PlatformVersion};

use crate::state_transition::StateTransitionType;

pub trait IdentityCreditTransferTransitionMethodsV0 {
#[cfg(feature = "state-transition-signing")]
fn try_from_identity<S: Signer>(
identity: &Identity,
to_identity_with_identifier: Identifier,
amount: u64,
user_fee_increase: UserFeeIncrease,
signer: S,
signing_withdrawal_key_to_use: Option<&IdentityPublicKey>,
nonce: IdentityNonce,
platform_version: &PlatformVersion,
version: Option<FeatureVersion>,
) -> Result<StateTransition, ProtocolError>;

/// Get State Transition Type
fn get_type() -> StateTransitionType {
StateTransitionType::IdentityCreditTransfer
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,80 @@
#[cfg(feature = "state-transition-signing")]
use crate::{
identity::{
accessors::IdentityGettersV0, signer::Signer, Identity, IdentityPublicKey, KeyType,
Purpose, SecurityLevel,
},
prelude::{IdentityNonce, UserFeeIncrease},
state_transition::StateTransition,
ProtocolError,
};
use platform_value::Identifier;

Check warning on line 11 in packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/v0/v0_methods.rs

View workflow job for this annotation

GitHub Actions / Rust packages (drive) / Linting

unused import: `platform_value::Identifier`

warning: unused import: `platform_value::Identifier` --> packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/v0/v0_methods.rs:11:5 | 11 | use platform_value::Identifier; | ^^^^^^^^^^^^^^^^^^^^^^^^^^

Check warning on line 11 in packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/v0/v0_methods.rs

View workflow job for this annotation

GitHub Actions / Rust packages (drive-abci) / Linting

unused import: `platform_value::Identifier`

warning: unused import: `platform_value::Identifier` --> packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/v0/v0_methods.rs:11:5 | 11 | use platform_value::Identifier; | ^^^^^^^^^^^^^^^^^^^^^^^^^^

Check warning on line 11 in packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/v0/v0_methods.rs

View workflow job for this annotation

GitHub Actions / Rust packages (drive) / Linting

unused import: `platform_value::Identifier`

warning: unused import: `platform_value::Identifier` --> packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/v0/v0_methods.rs:11:5 | 11 | use platform_value::Identifier; | ^^^^^^^^^^^^^^^^^^^^^^^^^^

Check warning on line 11 in packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/v0/v0_methods.rs

View workflow job for this annotation

GitHub Actions / Rust packages (drive-abci) / Linting

unused import: `platform_value::Identifier`

warning: unused import: `platform_value::Identifier` --> packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/v0/v0_methods.rs:11:5 | 11 | use platform_value::Identifier; | ^^^^^^^^^^^^^^^^^^^^^^^^^^

use crate::state_transition::identity_credit_transfer_transition::methods::IdentityCreditTransferTransitionMethodsV0;
use crate::state_transition::identity_credit_transfer_transition::v0::IdentityCreditTransferTransitionV0;
use crate::state_transition::GetDataContractSecurityLevelRequirementFn;

Check warning on line 15 in packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/v0/v0_methods.rs

View workflow job for this annotation

GitHub Actions / Rust packages (drive) / Linting

unused import: `crate::state_transition::GetDataContractSecurityLevelRequirementFn`

warning: unused import: `crate::state_transition::GetDataContractSecurityLevelRequirementFn` --> packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/v0/v0_methods.rs:15:5 | 15 | use crate::state_transition::GetDataContractSecurityLevelRequirementFn; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Check warning on line 15 in packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/v0/v0_methods.rs

View workflow job for this annotation

GitHub Actions / Rust packages (drive-abci) / Linting

unused import: `crate::state_transition::GetDataContractSecurityLevelRequirementFn`

warning: unused import: `crate::state_transition::GetDataContractSecurityLevelRequirementFn` --> packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/v0/v0_methods.rs:15:5 | 15 | use crate::state_transition::GetDataContractSecurityLevelRequirementFn; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Check warning on line 15 in packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/v0/v0_methods.rs

View workflow job for this annotation

GitHub Actions / Rust packages (drive) / Linting

unused import: `crate::state_transition::GetDataContractSecurityLevelRequirementFn`

warning: unused import: `crate::state_transition::GetDataContractSecurityLevelRequirementFn` --> packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/v0/v0_methods.rs:15:5 | 15 | use crate::state_transition::GetDataContractSecurityLevelRequirementFn; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Check warning on line 15 in packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/v0/v0_methods.rs

View workflow job for this annotation

GitHub Actions / Rust packages (drive-abci) / Linting

unused import: `crate::state_transition::GetDataContractSecurityLevelRequirementFn`

warning: unused import: `crate::state_transition::GetDataContractSecurityLevelRequirementFn` --> packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/v0/v0_methods.rs:15:5 | 15 | use crate::state_transition::GetDataContractSecurityLevelRequirementFn; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#[cfg(feature = "state-transition-signing")]
use platform_version::version::{FeatureVersion, PlatformVersion};

impl IdentityCreditTransferTransitionMethodsV0 for IdentityCreditTransferTransitionV0 {
#[cfg(feature = "state-transition-signing")]
fn try_from_identity<S: Signer>(
identity: &Identity,
to_identity_with_identifier: Identifier,
amount: u64,
user_fee_increase: UserFeeIncrease,
signer: S,
signing_withdrawal_key_to_use: Option<&IdentityPublicKey>,
nonce: IdentityNonce,
_platform_version: &PlatformVersion,
_version: Option<FeatureVersion>,
) -> Result<StateTransition, ProtocolError> {
let mut transition: StateTransition = IdentityCreditTransferTransitionV0 {
identity_id: identity.id(),
recipient_id: to_identity_with_identifier,
amount,
nonce,
user_fee_increase,
signature_public_key_id: 0,
signature: Default::default(),
}
.into();

let identity_public_key = match signing_withdrawal_key_to_use {
Some(key) => {
if signer.can_sign_with(key) {
key
} else {
return Err(
ProtocolError::DesiredKeyWithTypePurposeSecurityLevelMissing(
"specified transfer public key cannot be used for signing".to_string(),
),
);
}
}
None => {
let key = identity
.get_first_public_key_matching(
Purpose::TRANSFER,
SecurityLevel::full_range().into(),
KeyType::all_key_types().into(),
true,
)
.ok_or_else(|| {
ProtocolError::DesiredKeyWithTypePurposeSecurityLevelMissing(
"no transfer public key".to_string(),
)
})?;
key
}
};

transition.sign_external(
identity_public_key,
&signer,
None::<GetDataContractSecurityLevelRequirementFn>,
)?;

impl IdentityCreditTransferTransitionMethodsV0 for IdentityCreditTransferTransitionV0 {}
Ok(transition)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub mod v2;
pub struct DPPStateTransitionConversionVersions {
pub identity_to_identity_create_transition: FeatureVersion,
pub identity_to_identity_top_up_transition: FeatureVersion,
pub identity_to_identity_transfer_transition: FeatureVersion,
pub identity_to_identity_withdrawal_transition: FeatureVersion,
pub identity_to_identity_create_transition_with_signer: FeatureVersion,
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pub const STATE_TRANSITION_CONVERSION_VERSIONS_V1: DPPStateTransitionConversionV
DPPStateTransitionConversionVersions {
identity_to_identity_create_transition: 0,
identity_to_identity_top_up_transition: 0,
identity_to_identity_transfer_transition: 0,
identity_to_identity_withdrawal_transition: 0,
identity_to_identity_create_transition_with_signer: 0,
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pub const STATE_TRANSITION_CONVERSION_VERSIONS_V2: DPPStateTransitionConversionV
DPPStateTransitionConversionVersions {
identity_to_identity_create_transition: 0,
identity_to_identity_top_up_transition: 0,
identity_to_identity_transfer_transition: 0,
identity_to_identity_withdrawal_transition: 1,
identity_to_identity_create_transition_with_signer: 0,
};
1 change: 1 addition & 0 deletions packages/rs-sdk/src/platform/transition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub mod put_document;
pub mod put_identity;
pub mod put_settings;
pub mod top_up_identity;
pub mod transfer;
pub mod transfer_document;
mod txid;
pub mod update_price_of_document;
Expand Down
67 changes: 67 additions & 0 deletions packages/rs-sdk/src/platform/transition/transfer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
use dpp::identifier::Identifier;
use dpp::identity::accessors::IdentityGettersV0;

use crate::platform::transition::broadcast::BroadcastStateTransition;
use crate::platform::transition::put_settings::PutSettings;
use crate::{Error, Sdk};
use dpp::identity::signer::Signer;
use dpp::identity::{Identity, IdentityPublicKey};
use dpp::state_transition::identity_credit_transfer_transition::methods::IdentityCreditTransferTransitionMethodsV0;
use dpp::state_transition::identity_credit_transfer_transition::IdentityCreditTransferTransition;
use dpp::state_transition::proof_result::StateTransitionProofResult;

#[async_trait::async_trait]
pub trait TransferToIdentity {
/// Function to transfer credits from an identity to another identity. Returns the final
/// identity balance.
///
/// If signing_transfer_key_to_use is not set, we will try to use one in the signer that is
/// available for the transfer.
async fn transfer_credits<S: Signer + Send>(
&self,
sdk: &Sdk,
to_identity_id: Identifier,
amount: u64,
signing_transfer_key_to_use: Option<&IdentityPublicKey>,
signer: S,
settings: Option<PutSettings>,
) -> Result<u64, Error>;
}

#[async_trait::async_trait]
impl TransferToIdentity for Identity {
async fn transfer_credits<S: Signer + Send>(
&self,
sdk: &Sdk,
to_identity_id: Identifier,
amount: u64,
signing_transfer_key_to_use: Option<&IdentityPublicKey>,
signer: S,
settings: Option<PutSettings>,
) -> Result<u64, Error> {
let new_identity_nonce = sdk.get_identity_nonce(self.id(), true, settings).await?;
let user_fee_increase = settings.and_then(|settings| settings.user_fee_increase);
let state_transition = IdentityCreditTransferTransition::try_from_identity(
self,
to_identity_id,
amount,
user_fee_increase.unwrap_or_default(),
signer,
signing_transfer_key_to_use,
new_identity_nonce,
sdk.version(),
None,
)?;

let result = state_transition.broadcast_and_wait(sdk, None).await?;

match result {
StateTransitionProofResult::VerifiedPartialIdentity(identity) => {
identity.balance.ok_or(Error::DapiClientError(
"expected an identity balance after transfer".to_string(),
))
}
_ => Err(Error::DapiClientError("proved a non identity".to_string())),
}
}
}

0 comments on commit 244f5f9

Please sign in to comment.