create_canister function
Creates a canister using the NNS ledger and the cycles-minting-canister.
Returns the new canister's Principal.
Transforms the icp_tokens
into cycles for the canister.
Use an optional from_subaccount_bytes
to use ICP in a subaccount of the caller
.
This function makes two calls. One for the ICP ledger to transfer ICP-tokens to the cycles-minter-canister's account,
and one for the cycles-minter-canister to trigger it to use that ICP to create a canister with cycles.
A scenario can occur where the first call to transfer ICP-tokens can succeed but the second call to notify the cycles-minter-canister can fail (due to network load or similar).
In this scenario, this function will print the Nat64(block_height)
of the first ICP-transfer call.
Use the block_height
of the first call to complete this canister-creation by calling this function again with the same caller
and from_subaccount_bytes
and with the block_height
parameter.
When the block_height
is not given, this function will make a new icp-transfer.
When the block_height
is given, this function will skip the first icp-transfer call, and will call the cycles-minter-canister with the given block_height
.
Implementation
Future<Principal> create_canister(Caller caller, IcpTokens icp_tokens, {Uint8List? from_subaccount_bytes, Nat64? block_height, String? subnet_type}) async {
Uint8List to_subaccount_bytes = principal_as_an_icpsubaccountbytes(caller.principal);
if (block_height == null) {
block_height = match_variant<Nat64>(await transfer_icp(
caller,
icp_id(SYSTEM_CANISTERS.cycles_mint.principal, subaccount_bytes: to_subaccount_bytes),
icp_tokens,
subaccount_bytes: from_subaccount_bytes,
memo: MEMO_CREATE_CANISTER_nat64,
), {
'Ok': (block_height) {
return block_height as Nat64;
},
'Err': (transfer_error) {
return match_variant<Never>(transfer_error as Variant, transfer_error_match_map);
}
});
print('block_height: ${block_height.value}');
} else {
print('using given block_height: ${block_height.value}');
}
Record notifycanisterarg = Record.of_the_map({
'controller' : caller.principal,
'block_index' : block_height,
'subnet_type': Option<Text>(value: subnet_type.nullmap((st)=>Text(st)), value_type: Text())
});
Variant notify_create_canister_result = c_backwards(await SYSTEM_CANISTERS.cycles_mint.call(
calltype: CallType.call,
method_name: 'notify_create_canister',
put_bytes: c_forwards([notifycanisterarg]),
caller: caller
))[0] as Variant;
return match_variant<Principal>(notify_create_canister_result, {
'Ok': (p) {
return p as Principal;
},
'Err': (notify_error) {
return match_variant<Never>(notify_error as Variant, cmc_notify_error_match_map);
}
});
}