Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions packages/rs-dapi-client/src/transport/grpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions packages/rs-drive-proof-verifier/src/proof.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
use crate::error::MapGroveDbError;
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::tokens::contract_info::TokenContractInfo;
use dpp::version::PlatformVersion;
use drive::drive::Drive;

impl FromProof<GetTokenContractInfoRequest> for TokenContractInfo {
type Request = GetTokenContractInfoRequest;
type Response = GetTokenContractInfoResponse;

fn maybe_from_proof_with_metadata<'a, I: Into<Self::Request>, O: Into<Self::Response>>(
request: I,
response: O,
_network: Network,
platform_version: &PlatformVersion,
provider: &'a dyn ContextProvider,
) -> Result<(Option<Self>, 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, metadata, proof))
}
}
16 changes: 16 additions & 0 deletions packages/rs-sdk/src/mock/requests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -387,6 +388,21 @@ impl MockResponse for TokenStatuses {
}
}

impl MockResponse for TokenContractInfo {
fn mock_serialize(&self, sdk: &MockDashPlatformSdk) -> Vec<u8> {
platform_encode_to_vec(self, BINCODE_CONFIG, sdk.version())
.expect("encode TokenContractInfo")
}

fn mock_deserialize(sdk: &MockDashPlatformSdk, buf: &[u8]) -> Self
where
Self: Sized,
{
platform_versioned_decode_from_slice(buf, BINCODE_CONFIG, sdk.version())
.expect("decode TokenContractInfo")
}
}

impl MockResponse for TotalSingleTokenBalance {
fn mock_serialize(&self, _sdk: &MockDashPlatformSdk) -> Vec<u8> {
bincode::encode_to_vec(self, BINCODE_CONFIG).expect("encode vec of data")
Expand Down
4 changes: 4 additions & 0 deletions packages/rs-sdk/src/platform/fetch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -298,3 +298,7 @@ impl Fetch for Vote {
impl Fetch for RewardDistributionMoment {
type Request = platform_proto::GetTokenPerpetualDistributionLastClaimRequest;
}

impl Fetch for dpp::tokens::contract_info::TokenContractInfo {
type Request = platform_proto::GetTokenContractInfoRequest;
}
2 changes: 2 additions & 0 deletions packages/rs-sdk/src/platform/tokens/mod.rs
Original file line number Diff line number Diff line change
@@ -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
Expand Down
32 changes: 32 additions & 0 deletions packages/rs-sdk/src/platform/tokens/token_contract_info.rs
Original file line number Diff line number Diff line change
@@ -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<GetTokenContractInfoRequest> for TokenContractInfoQuery {
fn query(self, prove: bool) -> Result<GetTokenContractInfoRequest, Error> {
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<GetTokenContractInfoRequest> for Identifier {
fn query(self, prove: bool) -> Result<GetTokenContractInfoRequest, Error> {
TokenContractInfoQuery { token_id: self }.query(prove)
}
}
1 change: 1 addition & 0 deletions packages/rs-sdk/tests/fetch/tokens/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod identity_token_balances;
mod token_contract_info;
mod token_info;
mod token_status;
mod token_total_supply;
75 changes: 75 additions & 0 deletions packages/rs-sdk/tests/fetch/tokens/token_contract_info.rs
Original file line number Diff line number Diff line change
@@ -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 dpp::tokens::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<TokenContractInfo>)
.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<TokenContractInfo>)
.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);
}
}
}
Loading