use std::sync::Arc;
use async_trait::async_trait;
use candid::{Encode, Nat, Principal};
use ex3_canister_client::agent_call_wrapper::{query, update, Ex3Agent};
use crate::types::Subaccount;
use crate::{BlockResult, CanisterResult, OperationResult, QueryBlocksResult, DFT};
type CanisterId = Principal;
type BlockHeight = Nat;
#[derive(Debug)]
pub struct DFTClient {
pub token_id: Arc<CanisterId>,
pub agent: Arc<Ex3Agent>,
}
impl DFTClient {
pub fn new(dft_id: CanisterId, agent: Arc<Ex3Agent>) -> Self {
Self {
token_id: Arc::new(dft_id),
agent,
}
}
}
#[async_trait]
impl DFT for DFTClient {
async fn block_by_height(&self, block_height: &BlockHeight) -> CanisterResult<BlockResult> {
let args = Encode!(&block_height).unwrap();
query(&self.token_id, "blockByHeight", args, &self.agent).await
}
async fn blocks_by_query(
&self,
start: &BlockHeight,
count: &usize,
) -> CanisterResult<QueryBlocksResult> {
let args = Encode!(&start, &count).unwrap();
query(&self.token_id, "blocksByQuery", args, &self.agent).await
}
async fn transfer_from(
&self,
spender_sub_account: Option<Subaccount>,
from: String,
to: String,
value: Nat,
created_at: Option<u64>,
) -> CanisterResult<OperationResult> {
let args = Encode!(&spender_sub_account, &from, &to, &value, &created_at).unwrap();
update(&self.token_id, "transferFrom", args, &self.agent).await
}
async fn transfer(
&self,
from_sub_account: Option<Subaccount>,
to: String,
value: Nat,
created_at: Option<u64>,
) -> CanisterResult<OperationResult> {
let args = Encode!(&from_sub_account, &to, &value, &created_at).unwrap();
update(&self.token_id, "transfer", args, &self.agent).await
}
async fn balance_of(&self, token_holder: String) -> CanisterResult<Nat> {
let args = Encode!(&token_holder).unwrap();
query(&self.token_id, "balanceOf", args, &self.agent).await
}
}