ic_papi_guard/guards/
patron_pays_icrc2_cycles.rs1use super::{PaymentError, PaymentGuardTrait};
3use candid::Nat;
4use ic_cycles_ledger_client::WithdrawFromArgs;
5use ic_papi_api::{
6 caller::TokenAmount, cycles::cycles_ledger_canister_id, principal2account, Account,
7};
8
9pub struct PatronPaysIcrc2CyclesPaymentGuard {
12 pub patron: Account,
14}
15
16impl PaymentGuardTrait for PatronPaysIcrc2CyclesPaymentGuard {
17 async fn deduct(&self, fee: TokenAmount) -> Result<(), PaymentError> {
18 let own_canister_id = ic_cdk::api::id();
19 let caller = ic_cdk::caller();
20 let spender_subaccount = Some(principal2account(&caller));
21 if self.patron.owner == own_canister_id {
23 return Err(PaymentError::InvalidPatron);
24 }
25 ic_cycles_ledger_client::Service(cycles_ledger_canister_id())
28 .withdraw_from(&WithdrawFromArgs {
29 to: own_canister_id,
30 amount: Nat::from(fee),
31 from: self.patron.clone(),
32 spender_subaccount,
33 created_at_time: None,
34 })
35 .await
36 .map_err(|(rejection_code, string)| {
37 eprintln!(
38 "Failed to reach ledger canister at {}: {rejection_code:?}: {string}",
39 cycles_ledger_canister_id()
40 );
41 PaymentError::LedgerUnreachable {
42 ledger: cycles_ledger_canister_id(),
43 }
44 })?
45 .0
46 .map_err(|error| {
47 eprintln!(
48 "Failed to withdraw from ledger canister at {}: {error:?}",
49 cycles_ledger_canister_id()
50 );
51 PaymentError::LedgerWithdrawFromError {
52 ledger: cycles_ledger_canister_id(),
53 error,
54 }
55 })
56 .map(|_| ())
57 }
58}