Problems in creating a fully functional ICRC-1 token

I am trying to create an ICRC-1 token. I am using this github repository: GitHub - dfinity/ICRC-1: A fungible token standard developed by the Ledger & Tokenization working group for the IC..

I can install the canister with this code:

dfx canister --network ic install --mode reinstall icrc1-ledger --argument "(record {
token_symbol = \"Token\";
token_name = \"Token Name\";
minting_account = record { of = principal \"$PRINCIPAL\" };
transfer_fee = 10_000;
metadata = vec {};
initial_balances = vec {};
archive_options = record {
num_blocks_to_archive = 2000;
trigger_threshold = 1000;
controller_id = principal \"$PRINCIPAL\";
  };
},)"

After installing, im trying to look at the canister on ICScan but I don’t see any methods on the interface. Why are these missing and how to fix?

Also, I would like to pass the initial_mints as an argument when I install the canister:

dfx canister --network ic install --mode reinstall icrc1-ledger --argument "(record {
token_symbol = \"Token\";
token_name = \"Token Name\";
minting_account = record { of = principal \"$PRINCIPAL\" };
initial_mints =  [{ record { of = principal \"$PRINCIPAL\"}; 1_000_000_000}];
transfer_fee = 10_000;
metadata = vec {};
initial_balances = vec {};
archive_options = record {
num_blocks_to_archive = 2000;
trigger_threshold = 1000;
controller_id = principal \"$PRINCIPAL\";
  };
},)"

I get this error:

error: parser error
  ┌─ Candid argument:5:18
  │
5 │ initial_mints =   [{ record { of = principal \"$PRINCIPAL\"}; 1_000_000_000}];
  │                  ^ Unknown token [

Error: Failed to install wasm module to canister 'icrc1-ledger'.
Caused by: Failed to install wasm module to canister 'icrc1-ledger'.
  Failed to create argument blob.
    Invalid argument: Invalid Candid values: Candid parser error: Unknown token [ at 189..190

What am I doing wrong and what do I need to make the token fully functional? If you need more information I will be happy to provide it.

Thank you for your help!

2 Likes

Based on the above, along with this section of the Candid guide, I would try initial_mints = vec record { { owner = principal \"$PRINCIPAL\" }; 1_000_000_000; };

2 Likes

This has helped me, thank you so much. It had to be formatted like this

initial_mints = vec { record { owner = principal \"$PRINCIPAL\" ; 1_000_000_000}};

The icrc1_transfer method works but when I call the icrc1_balance_of method

dfx canister --network ic call icrc1-ledger icrc1_balance_of '(record { of=principal "myprincipalid" },)'

this error always comes up

Caused by: Failed update call.
  The Replica returned an error: code 3, message: "Canister _____ has no update method 'icrc1_balance_of'"

Also, I still don’t quite understand why I don’t have an interface when I look at the canister on ICScan. Is there something I’m missing?

Are you providing a path to the candid file for this canister?

If you’re up for it, you may want to try out GitHub - NatLabs/icrc1: A full implementation of the ICRC-1 fungible token standard. It should have archive functionality, as well as Rosetta servers. Also, we need testing.:grinning:

4 Likes

I have tried but I can’t get any further

  dfx deploy icrc1 --argument "( record {\
      name = \"<Token name>\"; \
      symbol = \"<Token>\"; \
      decimals = 6; \
      fee = 100; \
      max_supply = 1_000_000_000; \
      initial_balances =vec { record { owner = principal \"$PRINCIPAL\" ; 1_000_000_000}}; \
      advanced_settings = null; \
  })"

Everytime this error is coming up

Error: Failed while trying to deploy canisters.
Caused by: Failed while trying to deploy canisters.
  Failed while trying to install all canisters.
    Failed to install wasm module to canister 'icrc1'.
      Failed to create argument blob.
        Invalid data: Unable to serialize Candid values: record field 0 not found

It is probably due to the line with initial_balances. What am I doing wrong? @skilesare

Account is:

public type Account = {
        owner : Principal;
        subaccount : ?Subaccount;
    };

So you likely need:

initial_balances =vec { record{ record { owner = principal \"$PRINCIPAL\"; subaccount= null} ; 1_000_000_000}}}; \

It is a vec of tuples, so I think you do a tuple with a record without “name =”.

If that doesn’t work, let me know.

1 Like

I tried this but i get

Error: Failed while trying to deploy canisters.
Caused by: Failed while trying to deploy canisters.
  Failed while trying to install all canisters.
    Failed to install wasm module to canister 'icrc1'.
      Failed to create argument blob.
        Invalid argument: Invalid Candid values: Candid parser error: Unrecognized token `Semi` found at 302:303
Expected one of ")" or ","

After that I tried it with a curly bracket at the end less but I get:

Error: Failed while trying to deploy canisters.
Caused by: Failed while trying to deploy canisters.
  Failed while trying to install all canisters.
    Failed to install wasm module to canister 'icrc1'.
      Failed to create argument blob.
        Invalid data: Unable to serialize Candid values: type mismatch: 10000000 can not be of type opt Balance

@skilesare

Hey @mindfulanon,

There is an extra curly bracket at the end of 1_000_000_000. It should end with 2, not 3.

And from your initial arguments, I noticed that the min_burn_amount field is missing.
Try this and let me know if the error persists.

dfx deploy icrc1 --argument "( record {                     \
        name = \"<Token Name>\";                         \
        symbol = \"<Token>\";                           \
        decimals = 6;                                           \
        fee = 100;                                        \
        max_supply = 1_000_000_000_000;                         \
        initial_balances = vec {                                \
            record {                                            \
                record {                                        \
                    owner = principal \"$PRINCIPAL\";   \
                    subaccount = null;                          \
                };                                              \
                100_000_000_000                                 \
            }                                                   \
        };                                                      \
        min_burn_amount = 10_000;                           \
        minting_account = null;                                 \
        advanced_settings = null;                               \
    })"
1 Like

Thank you that helped!! It does make sense to format it as you did to avoid confusion. However, min_burn_amount does not need to be specified.

Two more question:

Why do I not see any methods on the candid interface?

How can I set a logo for the ICRC-1 token?

I just added another field to Types.mo, Token.mo and lib.mo called logo and I initialized the canister again with the new field logo and the base64 code of the logo as a parameter.

What am I doing wrong with my transfer method?


dfx canister --network ic call  icrc1 icrc1_transfer '(record{  
                    record{
                     from="principal abcd-....";
                     subaccount=null; 
                        };
                     record{
                       to="principal abcd-....";
                        subaccount = null; 
                        };
                    amount = 10_000_000
                })'            

  Invalid data: Unable to serialize Candid values: record field to not found

@tomijaga

It looks like you have the account signature wrong. I’m not at my desk, but I think if you fix that you might be good. Each account should have an owner and a sub account. The sub account can be no. The owner is a principal. Quotes go around the text to the principal but there’s a modifier before that text, that does not have quotes around it.

1 Like

Right, I have now changed that principal is outside the quote. Since ‘from’ is optional, I thought I might as well take it out. I keep getting the error

dfx canister --network ic call  icrc1 icrc1_transfer '(record{
                      record{
                       to= principal "abcd-...";
                        subaccount=null; 
                        };
                    amount = 10_000_000;
                },)'            

Error: Failed to create argument blob.
Caused by: Failed to create argument blob.
  Invalid data: Unable to serialize Candid values: record field to not found

grafik

Maybe I didn’t quite understand what you meant. If you could write me the command again I would be very grateful. @skilesare

It isn’t to it is owner:

record {to = record { owner = principal "xxxxxx"; subaccount=null}; from=....
1 Like

It worked, thank you so much!

Unfortunately, the logo is not shown to me.

I implemented the function myself and put in the Base64 code but it doesn’t seem to do its job
Token.mo

       public shared query func icrc1_logo() : async Text {
        ICRC1.logo(token);
    };

lib.mo

    public func logo(token : TokenData) : Text {
        token.logo;
    };

Types.mo

        icrc1_logo : shared query () -> async Text;

When i do

dfx canister  --network ic call icrc1 icrc1_logo

I get the base64 but it doesn’t show up as logo in icpswap or infinity wallet. What do I have to do for a logo? @skilesare

1 Like

Maybe ping @Maxfinity and he may know what format it is in.

Not sure this will help, but you can call get_metadata on the SNS-1 Governance canister using the IC dashboard, and see how it sets the logo string (“data:image/png;base64,…”)

1 Like

icrc1_logo isn’t part of the spec, so I’m not sure if it expects the same Base64 representation that SNS does, or if there are any limits to the image dimensions or size in bytes.

1 Like

Other functions work, such as the transfer, so I am confused. Could you explain me how to specify a path to the candid file for this canister? @paulyoung