Error creating canisters using the notify_create_canister method

Just for example the call code (this is for clarity) In reality, a call from the front-end
Screenshot from the command line at the bottom
Do I understand correctly that there is no way to specify the Principal of the user?(which is long)
The initialization canister has the required number of ICP and cycles for operations. ICP are written off, no creation occurs. As tests, I tried to specify the canister principal - the creation is successful, but they remain without the canister controller.

    public func create_canister_with_icp_test(amount: Nat): async Principal {
        let user = Principal.fromText("3sq5w-t7zis-qf3wl-vgvih-byre2-ttswt-vzupn-6mnpw-mju7l-jhbfi-hae");
        let caller = Principal.fromText("mxjrx-tiaaa-aaaah-aaoxq-cai");
        return await financing.create_canister(user, caller, amount);
    };

Creation initialization code:

public func create_canister(
                owner: Principal,
                caller: Principal,
                icp_amount: Nat) : async Principal{
            var amount = Nat64.fromNat(icp_amount);
            assert(amount > (Const.transfer_icp_fee + 2_000_000));
            let time = { timestamp_nanos = Nat64.fromNat(Int.abs(Time.now())) };
            let amount_res = { e8s = amount - (Const.transfer_icp_fee + 1_000_000)};
            var can = Principal.fromBlob(Blob.fromArrayMut(Array.init(32, 0 : Nat8)));
            var transfer_res: TransferResult = #Err(#TxCreatedInFuture);
           
            let subaccount = Tools.principalToSubAccount(caller); // work
            let to_cycles = Tools.principalToAccount(principal_public_coinage, ?subaccount);
            
            try{
                transfer_res := await public_ledger.transfer({
                    to = to_cycles;
                    fee = { e8s = Const.transfer_icp_fee; };
                    memo = Const.create_canister_memo;
                    from_subaccount = null;
                    // from_subaccount = ?subaccount;
                    created_at_time = ?time;
                    amount = amount_res;
                });
                switch(transfer_res){
                    case(#Err(e)){
                        return can;
                    };
                    case(#Ok(height)){
                        let ncca : NotifyCreateCanisterResult = await public_coinage.notify_create_canister({
                            block_index = height;
                            controller = owner;
                        });
                        switch(ncca){
                            case(#Err(e)){
                                return can;
                            };
                            case(#Ok(p)){
                                can := p;
                                return can;
                            };
                        };
                        return can;
                    };
                };
            }
            catch(e){ 
                return can;
            };
        };

HI @Safik ,
I’m not sure what Principal.fromText does, but I’m guessing it doesn’t do the right thing since it seems you get a principal that’s too long. What I think you want here is a function that takes the textual encoding of a principal and returns a hex encoding. Take a look at the principal section in the interface specification. In that section there is a specification for how the textual encoding is computed – you basically need to revert that. There are also examples for bash scripts that encode/decode a principal.

Looking at the code, it’s also not very clear to me what is the intention: I think you want the user to be the controller of the canister you are creating. In this case, the subaccount to which you are transferring to should also encode user and not caller.

I hope this helps.

1 Like

Hi! bogwar
Thanks for the reply.

1 Like