use candid::CandidType;
use serde::Deserialize;
use crate::{common::result::MotokoResult, identity::UserId, types::NftStorage};
use super::types::*;
#[derive(CandidType, Deserialize)]
pub struct ExtAllowanceArgs {
pub token: ExtTokenIdentifier,
pub owner: ExtUser,
pub spender: UserId,
}
pub type ExtAllowanceResult = MotokoResult<ExtBalance, ExtCommonError>;
#[derive(CandidType, Deserialize)]
pub struct ExtApproveArgs {
pub subaccount: Option<ExtSubaccount>, pub token: ExtTokenIdentifier,
pub allowance: ExtBalance,
pub spender: UserId,
}
pub trait ExtAllowance {
fn allowance(&self, args: ExtAllowanceArgs) -> ExtAllowanceResult;
fn approve(&mut self, args: ExtApproveArgs) -> bool;
}
impl ExtAllowance for NftStorage {
fn allowance(&self, args: ExtAllowanceArgs) -> ExtAllowanceResult {
let index = match super::utils::parse_token_index_with_self_canister(&args.token) {
Ok(index) => index as usize,
Err(e) => return MotokoResult::Err(e),
};
let owner = args.owner.to_account_identity();
match self.nfts.get(index) {
Some(nft) => {
if nft.owner.to_vec() != owner {
return MotokoResult::Err(ExtCommonError::Other(format!("Invalid owner")));
}
if let Some(approved) = nft.approved {
if approved == args.spender {
return MotokoResult::Ok(candid::Nat::from(1)); }
}
return MotokoResult::Ok(candid::Nat::from(0)); }
None => return MotokoResult::Err(ExtCommonError::InvalidToken(args.token)),
}
}
fn approve(&mut self, args: ExtApproveArgs) -> bool {
let index =
super::utils::parse_token_index_with_self_canister(&args.token).unwrap() as usize;
let caller = ExtUser::parse_account_identifier(&ic_cdk::api::caller(), &args.subaccount);
let spender = args.spender;
match self.nfts.get_mut(index) {
Some(nft) => {
if nft.owner.to_vec() != caller {
return false;
}
nft.approved = Some(spender);
true
}
None => false, }
}
}