From f0fc48463f3e92ce82d63078803532830f189c2e Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Wed, 11 Jun 2025 16:50:23 +0700 Subject: [PATCH 1/4] feat(sdk): fetch token contract info --- packages/rs-dapi-client/src/transport/grpc.rs | 9 +++++++++ packages/rs-drive-proof-verifier/src/proof.rs | 1 + packages/rs-drive-proof-verifier/src/types.rs | 2 ++ packages/rs-sdk/src/mock/requests.rs | 17 +++++++++++++++++ packages/rs-sdk/src/platform/fetch.rs | 4 ++++ packages/rs-sdk/src/platform/tokens/mod.rs | 2 ++ packages/rs-sdk/tests/fetch/tokens/mod.rs | 1 + 7 files changed, 36 insertions(+) diff --git a/packages/rs-dapi-client/src/transport/grpc.rs b/packages/rs-dapi-client/src/transport/grpc.rs index a5428409625..77c56eeb7e8 100644 --- a/packages/rs-dapi-client/src/transport/grpc.rs +++ b/packages/rs-dapi-client/src/transport/grpc.rs @@ -606,6 +606,15 @@ impl_transport_request_grpc!( get_token_direct_purchase_prices ); +// rpc getTokenContractInfo(GetTokenContractInfoRequest) returns (GetTokenContractInfoResponse); +impl_transport_request_grpc!( + platform_proto::GetTokenContractInfoRequest, + platform_proto::GetTokenContractInfoResponse, + PlatformGrpcClient, + RequestSettings::default(), + get_token_contract_info +); + // rpc getTokenPerpetualDistributionLastClaimRequest(GetTokenPerpetualDistributionLastClaimRequest) returns (GetTokenPerpetualDistributionLastClaimResponse); impl_transport_request_grpc!( platform_proto::GetTokenPerpetualDistributionLastClaimRequest, diff --git a/packages/rs-drive-proof-verifier/src/proof.rs b/packages/rs-drive-proof-verifier/src/proof.rs index dd7d523d6bf..26df9deb900 100644 --- a/packages/rs-drive-proof-verifier/src/proof.rs +++ b/packages/rs-drive-proof-verifier/src/proof.rs @@ -1,5 +1,6 @@ pub mod groups; pub mod identity_token_balance; +pub mod token_contract_info; pub mod token_direct_purchase; pub mod token_info; pub mod token_perpetual_distribution_last_claim; diff --git a/packages/rs-drive-proof-verifier/src/types.rs b/packages/rs-drive-proof-verifier/src/types.rs index 8cd6db254b6..4938ae2ad47 100644 --- a/packages/rs-drive-proof-verifier/src/types.rs +++ b/packages/rs-drive-proof-verifier/src/types.rs @@ -11,6 +11,8 @@ pub mod evonode_status; pub mod groups; /// Identity token balance pub mod identity_token_balance; +/// Token contract info +pub mod token_contract_info; /// Token info pub mod token_info; /// Token status diff --git a/packages/rs-sdk/src/mock/requests.rs b/packages/rs-sdk/src/mock/requests.rs index d3646fb374e..1828f2f0b2d 100644 --- a/packages/rs-sdk/src/mock/requests.rs +++ b/packages/rs-sdk/src/mock/requests.rs @@ -28,6 +28,7 @@ use drive_proof_verifier::types::groups::GroupActions; use drive_proof_verifier::types::identity_token_balance::{ IdentitiesTokenBalances, IdentityTokenBalances, }; +use drive_proof_verifier::types::token_contract_info::TokenContractInfo; use drive_proof_verifier::types::token_info::{IdentitiesTokenInfos, IdentityTokenInfos}; use drive_proof_verifier::types::token_status::TokenStatuses; use drive_proof_verifier::types::{ @@ -387,6 +388,22 @@ impl MockResponse for TokenStatuses { } } +impl MockResponse for TokenContractInfo { + fn mock_serialize(&self, sdk: &MockDashPlatformSdk) -> Vec { + platform_encode_to_vec(&self.0, BINCODE_CONFIG, sdk.version()) + .expect("encode TokenContractInfo") + } + + fn mock_deserialize(sdk: &MockDashPlatformSdk, buf: &[u8]) -> Self + where + Self: Sized, + { + let inner = platform_versioned_decode_from_slice(buf, BINCODE_CONFIG, sdk.version()) + .expect("decode TokenContractInfo"); + TokenContractInfo(inner) + } +} + impl MockResponse for TotalSingleTokenBalance { fn mock_serialize(&self, _sdk: &MockDashPlatformSdk) -> Vec { bincode::encode_to_vec(self, BINCODE_CONFIG).expect("encode vec of data") diff --git a/packages/rs-sdk/src/platform/fetch.rs b/packages/rs-sdk/src/platform/fetch.rs index b1e6433a578..18cf9e19562 100644 --- a/packages/rs-sdk/src/platform/fetch.rs +++ b/packages/rs-sdk/src/platform/fetch.rs @@ -298,3 +298,7 @@ impl Fetch for Vote { impl Fetch for RewardDistributionMoment { type Request = platform_proto::GetTokenPerpetualDistributionLastClaimRequest; } + +impl Fetch for drive_proof_verifier::types::token_contract_info::TokenContractInfo { + type Request = platform_proto::GetTokenContractInfoRequest; +} diff --git a/packages/rs-sdk/src/platform/tokens/mod.rs b/packages/rs-sdk/src/platform/tokens/mod.rs index f6950b3d815..b1c05f465ac 100644 --- a/packages/rs-sdk/src/platform/tokens/mod.rs +++ b/packages/rs-sdk/src/platform/tokens/mod.rs @@ -1,6 +1,8 @@ pub mod builders; /// Identity token balances queries pub mod identity_token_balances; +/// Token contract info query +pub mod token_contract_info; /// Identity token balances queries pub mod token_info; /// Token status query diff --git a/packages/rs-sdk/tests/fetch/tokens/mod.rs b/packages/rs-sdk/tests/fetch/tokens/mod.rs index 97980c259b2..14f980c3a5d 100644 --- a/packages/rs-sdk/tests/fetch/tokens/mod.rs +++ b/packages/rs-sdk/tests/fetch/tokens/mod.rs @@ -1,4 +1,5 @@ mod identity_token_balances; +mod token_contract_info; mod token_info; mod token_status; mod token_total_supply; From 748798b0410a682361dcf081342ff3bc42525f62 Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Wed, 11 Jun 2025 16:52:13 +0700 Subject: [PATCH 2/4] add files --- .../src/proof/token_contract_info.rs | 58 ++++++++++++++ .../src/types/token_contract_info.rs | 21 ++++++ .../platform/tokens/token_contract_info.rs | 32 ++++++++ .../tests/fetch/tokens/token_contract_info.rs | 75 +++++++++++++++++++ 4 files changed, 186 insertions(+) create mode 100644 packages/rs-drive-proof-verifier/src/proof/token_contract_info.rs create mode 100644 packages/rs-drive-proof-verifier/src/types/token_contract_info.rs create mode 100644 packages/rs-sdk/src/platform/tokens/token_contract_info.rs create mode 100644 packages/rs-sdk/tests/fetch/tokens/token_contract_info.rs diff --git a/packages/rs-drive-proof-verifier/src/proof/token_contract_info.rs b/packages/rs-drive-proof-verifier/src/proof/token_contract_info.rs new file mode 100644 index 00000000000..adc6ce38f29 --- /dev/null +++ b/packages/rs-drive-proof-verifier/src/proof/token_contract_info.rs @@ -0,0 +1,58 @@ +use crate::error::MapGroveDbError; +use crate::types::token_contract_info::TokenContractInfo; +use crate::verify::verify_tenderdash_proof; +use crate::{ContextProvider, Error, FromProof}; +use dapi_grpc::platform::v0::{ + get_token_contract_info_request, GetTokenContractInfoRequest, GetTokenContractInfoResponse, + Proof, ResponseMetadata, +}; +use dapi_grpc::platform::VersionedGrpcResponse; +use dpp::dashcore::Network; +use dpp::version::PlatformVersion; +use drive::drive::Drive; + +impl FromProof for TokenContractInfo { + type Request = GetTokenContractInfoRequest; + type Response = GetTokenContractInfoResponse; + + fn maybe_from_proof_with_metadata<'a, I: Into, O: Into>( + request: I, + response: O, + _network: Network, + platform_version: &PlatformVersion, + provider: &'a dyn ContextProvider, + ) -> Result<(Option, ResponseMetadata, Proof), Error> + where + Self: Sized + 'a, + { + let request: Self::Request = request.into(); + let response: Self::Response = response.into(); + + let token_id = match request.version.ok_or(Error::EmptyVersion)? { + get_token_contract_info_request::Version::V0(v0) => { + <[u8; 32]>::try_from(v0.token_id).map_err(|_| Error::RequestError { + error: "can't convert token_id to [u8; 32]".to_string(), + })? + } + }; + + let metadata = response + .metadata() + .or(Err(Error::EmptyResponseMetadata))? + .clone(); + + let proof = response.proof_owned().or(Err(Error::NoProofInResult))?; + + let (root_hash, result) = Drive::verify_token_contract_info( + &proof.grovedb_proof, + token_id, + false, + platform_version, + ) + .map_drive_error(&proof, &metadata)?; + + verify_tenderdash_proof(&proof, &metadata, &root_hash, provider)?; + + Ok((result.map(Into::into), metadata, proof)) + } +} \ No newline at end of file diff --git a/packages/rs-drive-proof-verifier/src/types/token_contract_info.rs b/packages/rs-drive-proof-verifier/src/types/token_contract_info.rs new file mode 100644 index 00000000000..61dc6d7a430 --- /dev/null +++ b/packages/rs-drive-proof-verifier/src/types/token_contract_info.rs @@ -0,0 +1,21 @@ +//! Token contract info types +//! +//! This module contains types for retrieving token contract information from proofs. + +use dpp::tokens::contract_info::TokenContractInfo as DppTokenContractInfo; + +/// Token contract info +#[derive(Debug, Clone, PartialEq)] +pub struct TokenContractInfo(pub DppTokenContractInfo); + +impl From for TokenContractInfo { + fn from(info: DppTokenContractInfo) -> Self { + TokenContractInfo(info) + } +} + +impl From for DppTokenContractInfo { + fn from(info: TokenContractInfo) -> Self { + info.0 + } +} \ No newline at end of file diff --git a/packages/rs-sdk/src/platform/tokens/token_contract_info.rs b/packages/rs-sdk/src/platform/tokens/token_contract_info.rs new file mode 100644 index 00000000000..30724048fdd --- /dev/null +++ b/packages/rs-sdk/src/platform/tokens/token_contract_info.rs @@ -0,0 +1,32 @@ +use crate::platform::{Identifier, Query}; +use crate::Error; +use dapi_grpc::platform::v0::get_token_contract_info_request::GetTokenContractInfoRequestV0; +use dapi_grpc::platform::v0::{get_token_contract_info_request, GetTokenContractInfoRequest}; + +#[derive(Debug, Clone)] +/// Query to fetch contract info for a specific token +pub struct TokenContractInfoQuery { + /// Token ID + pub token_id: Identifier, +} + +impl Query for TokenContractInfoQuery { + fn query(self, prove: bool) -> Result { + let request = GetTokenContractInfoRequest { + version: Some(get_token_contract_info_request::Version::V0( + GetTokenContractInfoRequestV0 { + token_id: self.token_id.to_vec(), + prove, + }, + )), + }; + + Ok(request) + } +} + +impl Query for Identifier { + fn query(self, prove: bool) -> Result { + TokenContractInfoQuery { token_id: self }.query(prove) + } +} \ No newline at end of file diff --git a/packages/rs-sdk/tests/fetch/tokens/token_contract_info.rs b/packages/rs-sdk/tests/fetch/tokens/token_contract_info.rs new file mode 100644 index 00000000000..5d96d33aaa7 --- /dev/null +++ b/packages/rs-sdk/tests/fetch/tokens/token_contract_info.rs @@ -0,0 +1,75 @@ +use crate::fetch::common::setup_logs; +use dash_sdk::platform::tokens::token_contract_info::TokenContractInfoQuery; +use dash_sdk::platform::{Fetch, Identifier, Query}; +use dash_sdk::Sdk; +use drive_proof_verifier::types::token_contract_info::TokenContractInfo; + +#[tokio::test] +async fn test_token_contract_info_fetch_by_identifier() { + setup_logs(); + + let mut sdk = Sdk::new_mock(); + let token_id = Identifier::from_bytes(&[1u8; 32]).unwrap(); + + // Set up mock expectation + sdk.mock() + .expect_fetch(token_id, None as Option) + .await + .unwrap(); + + // Test fetching by identifier directly + let result = TokenContractInfo::fetch_by_identifier(&sdk, token_id).await; + assert!(result.is_ok()); + assert!(result.unwrap().is_none()); // Mock returns None as expected +} + +#[tokio::test] +async fn test_token_contract_info_fetch_with_query() { + setup_logs(); + + let mut sdk = Sdk::new_mock(); + let token_id = Identifier::from_bytes(&[2u8; 32]).unwrap(); + + let query = TokenContractInfoQuery { token_id }; + + // Set up mock expectation + sdk.mock() + .expect_fetch(query.clone(), None as Option) + .await + .unwrap(); + + // Test fetching with explicit query + let result = TokenContractInfo::fetch(&sdk, query).await; + assert!(result.is_ok()); + assert!(result.unwrap().is_none()); // Mock returns None as expected +} + +#[tokio::test] +async fn test_token_contract_info_query_prove_true() { + let token_id = Identifier::from_bytes(&[3u8; 32]).unwrap(); + let query = TokenContractInfoQuery { token_id }; + + let request = query.query(true).unwrap(); + + match request.version.unwrap() { + dapi_grpc::platform::v0::get_token_contract_info_request::Version::V0(v0) => { + assert_eq!(v0.token_id, token_id.to_vec()); + assert!(v0.prove); + } + } +} + +#[tokio::test] +async fn test_token_contract_info_query_prove_false() { + let token_id = Identifier::from_bytes(&[4u8; 32]).unwrap(); + let query = TokenContractInfoQuery { token_id }; + + let request = query.query(false).unwrap(); + + match request.version.unwrap() { + dapi_grpc::platform::v0::get_token_contract_info_request::Version::V0(v0) => { + assert_eq!(v0.token_id, token_id.to_vec()); + assert!(!v0.prove); + } + } +} From 1b358f78ac1bfbaaa48475105f5e108f1c4384a2 Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Wed, 11 Jun 2025 17:12:35 +0700 Subject: [PATCH 3/4] fix: remove unneeded proof verifier wrapper --- .../src/proof/token_contract_info.rs | 4 ++-- packages/rs-drive-proof-verifier/src/types.rs | 2 -- .../src/types/token_contract_info.rs | 21 ------------------- packages/rs-sdk/src/mock/requests.rs | 9 ++++---- packages/rs-sdk/src/platform/fetch.rs | 2 +- .../tests/fetch/tokens/token_contract_info.rs | 2 +- 6 files changed, 8 insertions(+), 32 deletions(-) delete mode 100644 packages/rs-drive-proof-verifier/src/types/token_contract_info.rs diff --git a/packages/rs-drive-proof-verifier/src/proof/token_contract_info.rs b/packages/rs-drive-proof-verifier/src/proof/token_contract_info.rs index adc6ce38f29..c845847f7d1 100644 --- a/packages/rs-drive-proof-verifier/src/proof/token_contract_info.rs +++ b/packages/rs-drive-proof-verifier/src/proof/token_contract_info.rs @@ -1,5 +1,4 @@ use crate::error::MapGroveDbError; -use crate::types::token_contract_info::TokenContractInfo; use crate::verify::verify_tenderdash_proof; use crate::{ContextProvider, Error, FromProof}; use dapi_grpc::platform::v0::{ @@ -8,6 +7,7 @@ use dapi_grpc::platform::v0::{ }; use dapi_grpc::platform::VersionedGrpcResponse; use dpp::dashcore::Network; +use dpp::tokens::contract_info::TokenContractInfo; use dpp::version::PlatformVersion; use drive::drive::Drive; @@ -53,6 +53,6 @@ impl FromProof for TokenContractInfo { verify_tenderdash_proof(&proof, &metadata, &root_hash, provider)?; - Ok((result.map(Into::into), metadata, proof)) + Ok((result, metadata, proof)) } } \ No newline at end of file diff --git a/packages/rs-drive-proof-verifier/src/types.rs b/packages/rs-drive-proof-verifier/src/types.rs index 4938ae2ad47..8cd6db254b6 100644 --- a/packages/rs-drive-proof-verifier/src/types.rs +++ b/packages/rs-drive-proof-verifier/src/types.rs @@ -11,8 +11,6 @@ pub mod evonode_status; pub mod groups; /// Identity token balance pub mod identity_token_balance; -/// Token contract info -pub mod token_contract_info; /// Token info pub mod token_info; /// Token status diff --git a/packages/rs-drive-proof-verifier/src/types/token_contract_info.rs b/packages/rs-drive-proof-verifier/src/types/token_contract_info.rs deleted file mode 100644 index 61dc6d7a430..00000000000 --- a/packages/rs-drive-proof-verifier/src/types/token_contract_info.rs +++ /dev/null @@ -1,21 +0,0 @@ -//! Token contract info types -//! -//! This module contains types for retrieving token contract information from proofs. - -use dpp::tokens::contract_info::TokenContractInfo as DppTokenContractInfo; - -/// Token contract info -#[derive(Debug, Clone, PartialEq)] -pub struct TokenContractInfo(pub DppTokenContractInfo); - -impl From for TokenContractInfo { - fn from(info: DppTokenContractInfo) -> Self { - TokenContractInfo(info) - } -} - -impl From for DppTokenContractInfo { - fn from(info: TokenContractInfo) -> Self { - info.0 - } -} \ No newline at end of file diff --git a/packages/rs-sdk/src/mock/requests.rs b/packages/rs-sdk/src/mock/requests.rs index 1828f2f0b2d..3a1031931ff 100644 --- a/packages/rs-sdk/src/mock/requests.rs +++ b/packages/rs-sdk/src/mock/requests.rs @@ -4,6 +4,7 @@ use dpp::bincode::config::standard; use dpp::data_contract::associated_token::token_perpetual_distribution::reward_distribution_moment::RewardDistributionMoment; use dpp::data_contract::group::Group; use dpp::group::group_action::GroupAction; +use dpp::tokens::contract_info::TokenContractInfo; use dpp::tokens::info::IdentityTokenInfo; use dpp::tokens::status::TokenStatus; use dpp::tokens::token_pricing_schedule::TokenPricingSchedule; @@ -28,7 +29,6 @@ use drive_proof_verifier::types::groups::GroupActions; use drive_proof_verifier::types::identity_token_balance::{ IdentitiesTokenBalances, IdentityTokenBalances, }; -use drive_proof_verifier::types::token_contract_info::TokenContractInfo; use drive_proof_verifier::types::token_info::{IdentitiesTokenInfos, IdentityTokenInfos}; use drive_proof_verifier::types::token_status::TokenStatuses; use drive_proof_verifier::types::{ @@ -390,7 +390,7 @@ impl MockResponse for TokenStatuses { impl MockResponse for TokenContractInfo { fn mock_serialize(&self, sdk: &MockDashPlatformSdk) -> Vec { - platform_encode_to_vec(&self.0, BINCODE_CONFIG, sdk.version()) + platform_encode_to_vec(self, BINCODE_CONFIG, sdk.version()) .expect("encode TokenContractInfo") } @@ -398,9 +398,8 @@ impl MockResponse for TokenContractInfo { where Self: Sized, { - let inner = platform_versioned_decode_from_slice(buf, BINCODE_CONFIG, sdk.version()) - .expect("decode TokenContractInfo"); - TokenContractInfo(inner) + platform_versioned_decode_from_slice(buf, BINCODE_CONFIG, sdk.version()) + .expect("decode TokenContractInfo") } } diff --git a/packages/rs-sdk/src/platform/fetch.rs b/packages/rs-sdk/src/platform/fetch.rs index 18cf9e19562..9e66a8883cd 100644 --- a/packages/rs-sdk/src/platform/fetch.rs +++ b/packages/rs-sdk/src/platform/fetch.rs @@ -299,6 +299,6 @@ impl Fetch for RewardDistributionMoment { type Request = platform_proto::GetTokenPerpetualDistributionLastClaimRequest; } -impl Fetch for drive_proof_verifier::types::token_contract_info::TokenContractInfo { +impl Fetch for dpp::tokens::contract_info::TokenContractInfo { type Request = platform_proto::GetTokenContractInfoRequest; } diff --git a/packages/rs-sdk/tests/fetch/tokens/token_contract_info.rs b/packages/rs-sdk/tests/fetch/tokens/token_contract_info.rs index 5d96d33aaa7..edbe3c315e0 100644 --- a/packages/rs-sdk/tests/fetch/tokens/token_contract_info.rs +++ b/packages/rs-sdk/tests/fetch/tokens/token_contract_info.rs @@ -2,7 +2,7 @@ use crate::fetch::common::setup_logs; use dash_sdk::platform::tokens::token_contract_info::TokenContractInfoQuery; use dash_sdk::platform::{Fetch, Identifier, Query}; use dash_sdk::Sdk; -use drive_proof_verifier::types::token_contract_info::TokenContractInfo; +use dpp::tokens::contract_info::TokenContractInfo; #[tokio::test] async fn test_token_contract_info_fetch_by_identifier() { From 2aa22a318ba0846634b35ced003478978a4b21a0 Mon Sep 17 00:00:00 2001 From: pauldelucia Date: Wed, 11 Jun 2025 17:34:03 +0700 Subject: [PATCH 4/4] fmt --- .../rs-drive-proof-verifier/src/proof/token_contract_info.rs | 2 +- packages/rs-sdk/src/platform/tokens/token_contract_info.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/rs-drive-proof-verifier/src/proof/token_contract_info.rs b/packages/rs-drive-proof-verifier/src/proof/token_contract_info.rs index c845847f7d1..35f2d1e402d 100644 --- a/packages/rs-drive-proof-verifier/src/proof/token_contract_info.rs +++ b/packages/rs-drive-proof-verifier/src/proof/token_contract_info.rs @@ -55,4 +55,4 @@ impl FromProof for TokenContractInfo { Ok((result, metadata, proof)) } -} \ No newline at end of file +} diff --git a/packages/rs-sdk/src/platform/tokens/token_contract_info.rs b/packages/rs-sdk/src/platform/tokens/token_contract_info.rs index 30724048fdd..deaae35e8de 100644 --- a/packages/rs-sdk/src/platform/tokens/token_contract_info.rs +++ b/packages/rs-sdk/src/platform/tokens/token_contract_info.rs @@ -29,4 +29,4 @@ impl Query for Identifier { fn query(self, prove: bool) -> Result { TokenContractInfoQuery { token_id: self }.query(prove) } -} \ No newline at end of file +}