Here’s a snippet from one of my canisters. It uses ICP to notify_create_canister
, but it shouldn’t be too hard to adapt it to use notify_top_up
instead.
// transfer some ICP to CMC
let ledger_response = await LEDGER.transfer({
memo = CANISTER_CREATE_MEMO;
from_subaccount = null;
to = CMC_CREATE_ADDRESS;
amount = { e8s = amount_e8s };
fee = { e8s = 10_000 };
created_at_time = ?{
timestamp_nanos = Nat64.fromNat(Int.abs(Time.now()) - Nat64.toNat(n));
};
});
switch ledger_response {
case (#Ok(blockIndex)) {
block_index := blockIndex;
};
case (#Err(#TxDuplicate(rec))) {
add_to_latest_create_errors("TxDuplicate Error");
// not that bad. can continue
block_index := rec.duplicate_of;
};
case (#Err(#InsufficientFunds(_))) {
add_to_latest_create_errors("Not enough ICP balance to create canister.");
return;
};
case (#Err(#TxCreatedInFuture)) {
add_to_latest_create_errors("TxCreatedInFuture Error");
return;
};
case (#Err(#TxTooOld(_))) {
add_to_latest_create_errors("TxTooOld Error");
return;
};
case (#Err(#BadFee(_))) {
add_to_latest_create_errors("Bad Fee. Unreachable.");
return;
};
};
// notify_create
let cmc_response = await CMC.notify_create_canister({
block_index = block_index;
controller = THIS_CANISTERS_PRINCIPAL;
});
switch cmc_response {
case (#Ok(new_canister_id)) {
ignore Queue.pushBack(canisters_reserve, new_canister_id);
};
case (#Err(#Refunded({ reason; block_index }))) {
add_to_latest_create_errors("Refunded because " # reason);
return;
};
case (#Err(#Processing)) {
add_to_latest_create_errors("Error: still processing");
return;
};
case (#Err(#InvalidTransaction(reason))) {
add_to_latest_create_errors("InvalidTransaction Error " # reason);
return;
};
case (#Err(#Other({ error_code; error_message }))) {
add_to_latest_create_errors("Other Error " # error_message);
return;
};
case (#Err(#TransactionTooOld(_))) {
add_to_latest_create_errors("TransactionTooOld Error");
return;
};
};