To confirm, you are trying to tie a transaction specific to a product. Let’s say Customer A buys Product A from Customer B using ICP. You would like to tie this transaction?
You can do the following:
- When a user calls a
transferfunction, it should return the block number specific to the transaction such as:
(variant { Ok = 2 : nat })
- You can create a Hashmap (if using Motoko) to store the block number with the product ID. For example:
import HashMap "mo:base/HashMap";
import Text "mo:base/Text";
let map = HashMap.HashMap<Text, Nat>(5, Text.equal, Text.hash);
map.put("productA", blockNumber);
- Putting this together, I imagine you can something like this (Please test this):
import Icrc1Ledger "canister:icrc1_ledger_canister";
import Debug "mo:base/Debug";
import Result "mo:base/Result";
import Error "mo:base/Error";
import HashMap "mo:base/HashMap";
actor {
// Define the ProductName type
type ProductName = Text;
type TransferArgs = {
amount : Nat;
toAccount : Icrc1Ledger.Account;
productName : ProductName;
};
let map = HashMap.HashMap<Text, Nat>(5, Text.equal, Text.hash);
public shared func transfer(args : TransferArgs) : async Result.Result<Icrc1Ledger.BlockIndex, Text> {
Debug.print(
"Transferring "
# debug_show (args.amount)
# " tokens to account "
# debug_show (args.toAccount)
# " for product "
# debug_show (args.productName)
);
let transferArgs : Icrc1Ledger.TransferArg = {
// can be used to distinguish between transactions
memo = null;
// the amount we want to transfer
amount = args.amount;
// we want to transfer tokens from the default subaccount of the canister
from_subaccount = null;
// if not specified, the default fee for the canister is used
fee = null;
// the account we want to transfer tokens to
to = args.toAccount;
// a timestamp indicating when the transaction was created by the caller; if it is not specified by the caller then this is set to the current ICP time
created_at_time = null;
};
try {
// initiate the transfer
let transferResult = await Icrc1Ledger.icrc1_transfer(transferArgs);
// check if the transfer was successful
switch (transferResult) {
case (#Err(transferError)) {
return #err("Couldn't transfer funds:\n" # debug_show (transferError));
};
case (#Ok(blockIndex)) {
map.put(args.productName, blockIndex); // Use args.productName
return #ok blockIndex;
};
};
} catch (error : Error) {
// catch any errors that might occur during the transfer
return #err("Reject message: " # Error.message(error));
};
};
};