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