ic_papi_guard/guards/
caller_pays_icrc2_tokens.rs1use super::{PaymentError, PaymentGuardTrait};
7use candid::{Nat, Principal};
8use ic_cycles_ledger_client::TransferFromArgs;
9use ic_papi_api::{caller::TokenAmount, Account};
10
11pub struct CallerPaysIcrc2TokensPaymentGuard {
12 pub ledger: Principal,
14}
15
16impl PaymentGuardTrait for CallerPaysIcrc2TokensPaymentGuard {
17 async fn deduct(&self, cost: TokenAmount) -> Result<(), PaymentError> {
18 let caller = ic_cdk::api::caller();
19 ic_cycles_ledger_client::Service(self.ledger)
20 .icrc_2_transfer_from(&TransferFromArgs {
21 from: Account {
22 owner: caller,
23 subaccount: None,
24 },
25 to: Account {
26 owner: ic_cdk::api::id(),
27 subaccount: None,
28 },
29 amount: Nat::from(cost),
30 spender_subaccount: None,
31 created_at_time: None,
32 memo: None,
33 fee: None,
34 })
35 .await
36 .map_err(|(rejection_code, string)| {
37 eprintln!(
38 "Failed to reach ledger canister at {}: {rejection_code:?}: {string}",
39 self.ledger
40 );
41 PaymentError::LedgerUnreachable {
42 ledger: self.ledger,
43 }
44 })?
45 .0
46 .map_err(|error| {
47 eprintln!(
48 "Failed to withdraw from ledger canister at {}: {error:?}",
49 self.ledger
50 );
51 PaymentError::LedgerTransferFromError {
52 ledger: self.ledger,
53 error,
54 }
55 })
56 .map(|_| ())
57 }
58}