Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: ICP/ICRC ledger canister init args #3623

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 10 additions & 52 deletions docs/developer-docs/defi/tokens/create.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -27,76 +27,51 @@ To create a new ICRC-1 token, you will need to first download and configure a lo
The initialization arguments of the ICRC-1 ledger are not specified in the [standard](https://github.com/dfinity/ICRC-1/blob/main/standards/ICRC-1/README.md). Thus, the arguments defined in this section are dependent on the reference implementation of the ICRC-1 ledger. If you build your own ICRC-1 ledger, you may use different initialization arguments.
:::

To create a token, you will need to export several environmental variables. The full list can be found below:
To create a token, you will need to record several values. The full list can be found below:

#### `PRE_MINTED_TOKENS`

Amount of tokens that are minted during deployment for a specific account. In this tutorial, it will be the `DEFAULT` account.

```
export PRE_MINTED_TOKENS=10_000_000_000
dfx identity use default
export DEFAULT=$(dfx identity get-principal)
echo $(dfx identity get-principal)
```

#### `TRANSFER_FEE`

Fee that users of the ledger will have to pay anytime they want to make a transfer.

```
export TRANSFER_FEE=10_000
```

#### `ARCHIVE_CONTROLLER`

The [controller <GlossaryTooltip>principal</GlossaryTooltip>](/docs/current/developer-docs/defi/cycles/cycles-wallet#controller-and-custodian-roles) of the archive canisters.

```
dfx identity new archive_controller
dfx identity use archive_controller
export ARCHIVE_CONTROLLER=$(dfx identity get-principal)
echo $(dfx identity get-principal)
```

#### `TRIGGER_THRESHOLD`

The number of blocks to archive when the trigger threshold is exceeded.

```
export TRIGGER_THRESHOLD=2000
```

#### `CYCLE_FOR_ARCHIVE_CREATION`

The number of cycles that will be sent to the archive canister when it is created.

```
export CYCLE_FOR_ARCHIVE_CREATION=10000000000000
```

#### `NUM_OF_BLOCK_TO_ARCHIVE`

The number of blocks that will be archived.

```
export NUM_OF_BLOCK_TO_ARCHIVE=1000
```

#### `TOKEN_NAME`

The name of your token.

```
export TOKEN_NAME="My Token"
```

#### `TOKEN_SYMBOL`

The ticker symbol of your new token.

```
export TOKEN_SYMBOL="XMTK"
```

#### `MINTER`

The account of the principal responsible for minting and burning tokens (see the [ICRC-1 specification](https://github.com/dfinity/ICRC-1)). Transfers from the minting account will generate `Mint` transactions, resulting in the creation of new tokens. To mint tokens, the minting account must call the `icrc1_transfer` function, specifying the recipient in the 'to' value.
Expand All @@ -106,7 +81,7 @@ Transfers sent to the minting account will generate `Burn` transactions, destroy
```
dfx identity new minter
dfx identity use minter
export MINTER=$(dfx identity get-principal)
echo $(dfx identity get-principal)
```

#### `FEATURE_FLAGS`
Expand All @@ -115,13 +90,13 @@ A flag for enabling or disabling certain extension standards to the ICRC-1 stand

If you only want to support the ICRC-1 standard, then you can set the flag to `false`. If you want to also support the ICRC-2 standard, set it to `true`.

```
export FEATURE_FLAGS=false
```

## Edit the project's dfx.json file

Next, insert these environment variables into your project's `dfx.json` file as init arguments for your ledger canister:
Replace the existing content in the `dfx.json` with the following, updating the values of `TOKEN_SYMBOL`, `TOKEN_NAME`, `MINTER`, `TRANSFER_FEE`, `DEFAULT_ACCOUNT_ID `PRE_MINTED_TOKENS`, `NUM_OF_BLOCKS_TO_ARCHIVE`, `TRIGGER_THRESHOLD`, and `ARCHIVE_CONTROLLER` with the values obtained in the previous steps:

:::info
`dfx.json` does not support referring to values through environment variables. Values must be hardcoded in plain text.
:::

```json
{
Expand All @@ -130,25 +105,8 @@ Next, insert these environment variables into your project's `dfx.json` file as
"type": "custom",
"candid": "https://raw.githubusercontent.com/dfinity/ic/<REVISION>/rs/ledger_suite/icrc1/ledger/ledger.did",
"wasm": "https://download.dfinity.systems/ic/<REVISION>/canisters/ic-icrc1-ledger.wasm.gz",
"init_arg": "(variant {Init =
record {
     token_symbol = \"$TOKEN_SYMBOL\";
     token_name = \"$TOKEN_NAME\";
     minting_account = record { owner = principal \"$MINTER\" };
     transfer_fee = $TRANSFER_FEE;
     metadata = vec {};
     feature_flags = opt record{icrc2 = ${FEATURE_FLAGS}};
     initial_balances = vec { record { record { owner = principal \"$DEFAULT\"; }; \"$PRE_MINTED_TOKENS\"; }; };
     archive_options = record {
         num_blocks_to_archive = \"$NUM_OF_BLOCK_TO_ARCHIVE\";
         trigger_threshold = \"$TRIGGER_THRESHOLD\";
         controller_id = principal \"$ARCHIVE_CONTROLLER\";
         cycles_for_archive_creation = opt \"$CYCLE_FOR_ARCHIVE_CREATION\";
     };
 }
})"
"init_arg": "(variant {Init = record { token_symbol = "TOKEN_SYMBOL"; token_name = "TOKEN_NAME"; minting_account = record { owner = principal "MINTER" transfer_fee = TRANSFER_FEE; metadata = vec {}; feature_flags = opt record{icrc2 = false}; initial_balances = vec { record { record { owner = principal "DEFAULT_ACCOUNT_ID"; }; "PRE_MINTED_TOKENS"; }; }; archive_options = record { num_blocks_to_archive = "NUM_OF_BLOCK_TO_ARCHIVE"; trigger_threshold = "TRIGGER_THRESHOLD"; controller_id = principal "ARCHIVE_CONTROLLER"; cycles_for_archive_creation = opt "10000000000000"; }; }} })" },
},
},
"defaults": {
"build": {
"args": "",
Expand Down
89 changes: 39 additions & 50 deletions docs/developer-docs/defi/tokens/ledger/setup/icp_ledger_setup.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ If you are working in a local development environment, i.e., with a local replic

### Accounts

An ICP ledger account (see [ICRC-1 standard](/docs/current/developer-docs/defi/tokens/token-standards#icrc-1) belongs to and is controlled by the account owner, who must have a valid principal ID. No account can be owned by two or more principals (no "joint accounts"). However, since a principal can refer to an external user as well as to a canister, joint accounts can be implemented as canisters.
An ICP ledger account (see [ICRC-1 standard](/docs/current/developer-docs/defi/tokens/token-standards#icrc-1)) belongs to and is controlled by the account owner, who must have a valid principal ID. No account can be owned by two or more principals (no "joint accounts"). However, since a principal can refer to an external user as well as to a canister, joint accounts can be implemented as canisters.

An account on the ledger is represented and stored as an `AccountIdentifier`, which is derived from the principal ID and subaccount identifier by computing a hash of the two. The subaccount is an optional bitstring that helps distinguish between the different sub-accounts of the same owner.

Expand All @@ -48,8 +48,6 @@ The main reason for introducing accounts was to allow a principal to control mul
:::




## Deploying the ledger locally

There are two ways of deploying an ICP ledger locally.
Expand Down Expand Up @@ -96,9 +94,34 @@ chmod +x download_latest_icp_ledger.sh
./download_latest_icp_ledger.sh
```

### Step 4: Configure the `dfx.json` file.
### Step 4: Create a new identity that will work as a minting account:

``` sh
dfx identity new minter
dfx identity use minter
echo $(dfx ledger account-id)
```

Record the output of these commands as your minting account ID.

Transfers from the minting account will create `Mint` transactions. Transfers to the minting account will create `Burn` transactions.

### Step 5: Switch back to your default identity and record its ledger account identifier.

``` sh
dfx identity use default
echo $(dfx ledger account-id)
```

Record the output of these commands as your default account ID.

### Step 6: Configure the `dfx.json` file.

Open the `dfx.json` file in your project's directory. Replace the existing content with the following:
Open the `dfx.json` file in your project's directory. Replace the existing content with the following, updating the values of `MINTER_ACCOUNT_ID` and `DEFAULT_ACCOUNT_ID` with the values obtained in the previous steps:

:::info
`dfx.json` does not support referring to values through environment variables. Values must be hardcoded in plain text.
:::

``` json
{
Expand All @@ -111,7 +134,8 @@ Open the `dfx.json` file in your project's directory. Replace the existing conte
"id": {
"ic": "ryjl3-tyaaa-aaaaa-aaaba-cai"
}
}
},
"init_arg" : "(variant { Init = record { minting_account = "MINTER_ACCOUNT_ID"; initial_values = vec { record { "DEFAULT_ACCOUNT_ID"; record { e8s = 10_000_000_000 : nat64; }; }; }; send_whitelist = vec {}; transfer_fee = opt record { e8s = 10_000 : nat64; }; token_symbol = opt \"LICP\"; token_name = opt \"Local ICP\"; } })"
}
},
"defaults": {
Expand All @@ -134,29 +158,19 @@ If you chose to download the ICP ledger files with the script you need to replac
...
```

In an existing project you would only need to add the `icp_ledger_canister` canister to the `canisters` section.

### Step 5: Start a local replica.

``` sh
dfx start --clean --background
```

### Step 6: Create a new identity that will work as a minting account:
This `dfx.json` file also defines the init arguments for the ledger canister:

``` sh
dfx identity new minter
dfx identity use minter
export MINTER_ACCOUNT_ID=$(dfx ledger account-id)
```
- Sets the minting account to the account identifier you saved in a previous step (`MINTER_ACCOUNT_ID`).
- Mints 100 ICP tokens to the `DEFAULT_ACCOUNT_ID` (1 ICP is equal to 10^8 e8s).
- Sets the transfer fee to 0.0001 ICP.
- Names the token `Local ICP / LICP`.

Transfers from the minting account will create `Mint` transactions. Transfers to the minting account will create `Burn` transactions.
You can also pass these init args to the canister using the command line. [Learn more about init args](/docs/current/developer-docs/developer-tools/cli-tools/advanced-dfx/init-args/).

### Step 7: Switch back to your default identity and record its ledger account identifier.
### Step 7: Start a local replica.

``` sh
dfx identity use default
export DEFAULT_ACCOUNT_ID=$(dfx ledger account-id)
dfx start --clean --background
```

### Step 8: Deploy the ledger canister locally:
Expand All @@ -167,34 +181,9 @@ In this workflow, you cannot deploy this canister to the playground (using flag

```
dfx deploy --specified-id ryjl3-tyaaa-aaaaa-aaaba-cai icp_ledger_canister --argument "
(variant {
Init = record {
minting_account = \"$MINTER_ACCOUNT_ID\";
initial_values = vec {
record {
\"$DEFAULT_ACCOUNT_ID\";
record {
e8s = 10_000_000_000 : nat64;
};
};
};
send_whitelist = vec {};
transfer_fee = opt record {
e8s = 10_000 : nat64;
};
token_symbol = opt \"LICP\";
token_name = opt \"Local ICP\";
}
})
"
```

Take a moment to read the details of the call made above. Not only are you deploying the ICP ledger canister, you are also:
- Deploying the canister to the same canister ID as the mainnet ledger canister. This is to make it easier to switch between local and mainnet deployments.
- Setting the minting account to the account identifier you saved in a previous step (`MINTER_ACCOUNT_ID`).
- Minting 100 ICP tokens to the `DEFAULT_ACCOUNT_ID` (1 ICP is equal to 10^8 e8s).
- Setting the transfer fee to 0.0001 ICP.
- Naming the token `Local ICP / LICP`
Take a moment to read the details of the call made above. Not only are you deploying the ICP ledger canister, you are also deploying the canister to the same canister ID as the mainnet ledger canister. This is to make it easier to switch between local and mainnet deployments.

### Step 9: Interact with the canister.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,38 +50,29 @@ dfx canister install icp_ledger_canister --argument
Alternatively, you can pass these arguments to the canister directly in the `dfx.json` file:

```json
"canisters": {
"icp_ledger": {
{
"canisters": {
"icp_ledger_canister": {
"type": "custom",
"candid": "https://raw.githubusercontent.com/dfinity/ic/ec35ebd252d4ffb151d2cfceba3a86c4fb87c6d6/rs/rosetta-api/icp_ledger/ledger.did",
"wasm": "https://download.dfinity.systems/ic/ec35ebd252d4ffb151d2cfceba3a86c4fb87c6d6/canisters/ledger-canister.wasm.gz",
"candid": "https://raw.githubusercontent.com/dfinity/ic/d87954601e4b22972899e9957e800406a0a6b929/rs/rosetta-api/icp_ledger/ledger.did",
"wasm": "https://download.dfinity.systems/ic/d87954601e4b22972899e9957e800406a0a6b929/canisters/ledger-canister.wasm.gz",
"remote": {
"id": {
"ic": "ryjl3-tyaaa-aaaaa-aaaba-cai"
}
},
"init_arg": "(variant {
Init = record {
minting_account = \"$MINTER_ACCOUNT_ID\";
initial_values = vec {
record {
\"$DEFAULT_ACCOUNT_ID\";
record {
e8s = 10_000_000_000 : nat64;
};
};
};
send_whitelist = vec {};
transfer_fee = opt record {
e8s = 10_000 : nat64;
};
token_symbol = opt \"LICP\";
token_name = opt \"Local ICP\";
"init_arg" : "(variant { Init = record { minting_account = "MINTER_ACCOUNT_ID"; initial_values = vec { record { "DEFAULT_ACCOUNT_ID"; record { e8s = 10_000_000_000 : nat64; }; }; }; send_whitelist = vec {}; transfer_fee = opt record { e8s = 10_000 : nat64; }; token_symbol = opt \"LICP\"; token_name = opt \"Local ICP\"; } })"
}
})
"
},
...
},
"defaults": {
"build": {
"args": "",
"packtool": ""
}
},
"output_env_file": ".env",
"version": 1
}
```

## Using an `init_arg_file`
Expand All @@ -100,10 +91,10 @@ An example initialization argument file can be found below:
```did
(variant {
Init = record {
minting_account = "xxxxxxxxxx";
minting_account = "MINTER_ACCOUNT_ID";
initial_values = vec {
record {
"xxxxxxxxxx";
"DEFAULT_ACCOUNT_ID";
record {
e8s = 10_000_000_000 : nat64;
};
Expand Down Expand Up @@ -145,4 +136,4 @@ You can also specify the `init_arg_file` for each canister in the `dfx.json` fil

- Initialization arguments must be set individually for each canister, either through the CLI for `dfx.json`. To make this easier, `init_arg_file`s can be used, as detailed below.

- When using an argument file, values referenced as environment variables within the file will not be passed to the canister.
- When using `dfx.json` or an argument file, values referenced as environment variables within the file will not be passed to the canister.
Loading