ic_icrc_tx/parser/request/
mod.rs

1use base64::{engine::general_purpose, Engine};
2use candid::Decode;
3use icrc_ledger_types::icrc1::transfer::TransferArg;
4
5use crate::types::CanisterCall;
6
7/// Parses an ICRC1 transfer canister call.
8///
9/// This function takes a `CanisterCall` input, decodes the base64-encoded argument,
10/// and deserializes it into a `TransferArg` struct.
11///
12/// # Arguments
13///
14/// * `caniser_call_input` - The `CanisterCall` containing the base64-encoded transfer argument.
15///
16/// # Returns
17///
18/// A `TransferArg` struct containing the decoded transfer arguments.
19///
20/// # Panics
21///
22/// This function will panic if the base64 decoding or deserialization fails.
23pub fn parse_icrc1_transfer_arg(caniser_call_input: CanisterCall) -> TransferArg {
24    let transfer_arg_bytes = general_purpose::STANDARD
25        .decode(caniser_call_input.arg)
26        .unwrap();
27
28    let transfer_arg = Decode!(
29        &transfer_arg_bytes,
30        icrc_ledger_types::icrc1::transfer::TransferArg
31    )
32    .unwrap();
33    transfer_arg
34}
35
36#[cfg(test)]
37mod tests {
38    use super::*;
39    use candid::{Nat, Principal};
40    use icrc_ledger_types::icrc1::account::Account;
41
42    #[test]
43    fn test_parse_icrc1_transfer_arg() {
44        let canister_call_input = CanisterCall {
45            canister_id: "etik7-oiaaa-aaaar-qagia-cai".to_string(),
46            method: "icrc1_transfer".to_string(),
47            arg: "RElETAZsBvvKAQHG/LYCBLqJ5cIEAqLelOsGAoLz85EMBdijjKgNfWwCs7DawwNorYbKgwUCbgNte259bngBAAEdXdZAg85gOc3s6DkTiv7FBn9RDHSPT6rgmlsBGgIAAAAAAICt4gQ=".to_string(),
48        };
49
50        let transfer_arg = parse_icrc1_transfer_arg(canister_call_input);
51
52        println!("Decoded Arg: {:?}", transfer_arg);
53
54        assert_eq!(
55            transfer_arg.to,
56            Account {
57                owner: Principal::from_text(
58                    "6pfju-rc52z-aihtt-ahhg6-z2bzc-ofp5r-igp5i-qy5ep-j6vob-gs3ae-nae"
59                )
60                .unwrap(),
61                subaccount: None,
62            }
63        );
64        assert_eq!(transfer_arg.amount, Nat::from(10000000u64));
65        assert_eq!(transfer_arg.memo, None);
66        assert_eq!(transfer_arg.fee, None);
67        assert_eq!(transfer_arg.created_at_time, None);
68        assert_eq!(transfer_arg.from_subaccount, None);
69    }
70}