How to Go From ckBTC to ICP to Cycles?

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;
  };
};
2 Likes

What is that n supposed to be? and what happens if I didn’t supply the created_at_time value? Sorry I know this is supposed to be asked on a new post.

Also, the address I should ICP to, will be rkp4c-7iaaa-aaaaa-aaaca-cai right? or should I convert it from Principal to Account with null subaccount?

edit: sorry I shouldve read the NNS Ledger documentation.

Ah, right, should have scratched that line. It’s part of circumventing some deduplication logic if you’re triggering multiple transfers at once. Please disregard unless you run into errors because of deduplication. Time.now() should be just fine

1 Like