diff --git a/docs/developer-docs/defi/tokens/ledger/setup/icp_ledger_setup.mdx b/docs/developer-docs/defi/tokens/ledger/setup/icp_ledger_setup.mdx index 3309978f39..5641d7d16f 100644 --- a/docs/developer-docs/defi/tokens/ledger/setup/icp_ledger_setup.mdx +++ b/docs/developer-docs/defi/tokens/ledger/setup/icp_ledger_setup.mdx @@ -8,11 +8,9 @@ import { MarkdownChipRow } from "/src/components/Chip/MarkdownChipRow"; +The Internet Computer Protocol (ICP) implements management of its utility token (ticker "ICP") using a specialized canister, called the **ICP ledger canister**. It is a single ledger canister that runs alongside other canisters on a special subnet of the Internet Computer—the NNS subnet. The ICP ledger canister is a smart contract that holds **blocks**, each containing a single transaction. - -The Internet Computer Protocol (ICP) implements management of its utility token (ticker "ICP") using a specialized canister, called the **ICP ledger canister**. It is a single ledger canister that runs alongside other canisters on a special subnet of the Internet Computer - the NNS subnet. The ICP ledger canister is a smart contract that holds **blocks**, each containing a single transaction. - -These transactions either: +These transactions are either: - **Mint ICP tokens** for accounts. @@ -38,7 +36,7 @@ If you are working in a local development environment, i.e., with a local replic 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. +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 subaccounts of the same owner. In this context, you can think of principal identifiers as a rough equivalent to the hash of a user’s public key for Bitcoin or Ethereum. You use the corresponding secret key to sign messages and therefore authenticate to the ledger canister and operate on the principal’s account. Canisters can also have accounts in the ledger canister, in which case the address is derived from the canister’s principal. @@ -47,54 +45,56 @@ In this context, you can think of principal identifiers as a rough equivalent to The main reason for introducing accounts was to allow a principal to control multiple accounts. While this could be abstracted away for a user by the wallet software, this is not possible for canisters. ::: - ## Deploying the ledger locally -There are two ways of deploying an ICP ledger locally. -- Use [dfx-nns](/docs/current/developer-docs/developer-tools/cli-tools/cli-reference/dfx-nns) to deploy the entire NNS locally. Since the ICP ledger is part of the NNS, this command will also install an ICP ledger with canister ID `ryjl3-tyaaa-aaaaa-aaaba-cai`. This solution is fast and straightforward, but also more heavyweight. -- Deploy the ICP ledger `wasm` locally. This method is discussed and demonstrated in this guide, as it gives you more control over the deployment and is lightweight. +There are two ways of deploying an ICP ledger locally: -Deploying an ICP ledger locally gives you certain advantages over the default ledger from `dfx` that is installed with `dfx nns install`. For instance, you can define the `minting account`, you have control over the initialization arguments and you have control over which `wasm` version of the ICP ledger you want to interact with. +1. Use [`dfx nns`](/docs/current/developer-docs/developer-tools/cli-tools/cli-reference/dfx-nns) to deploy the entire NNS locally. Since the ICP ledger is part of the NNS, this command will also install an ICP ledger with canister ID `ryjl3-tyaaa-aaaaa-aaaba-cai`. This solution is fast and straightforward, but also more heavyweight. -The ICP ledger only exists on the mainnet and the `wasm` that is running on the mainnet is not meant to be used for other token deployments. It needs to be backward compatible and thus contains a lot of legacy code that should not be used when deploying a new ledger. +2. Deploy the ICP ledger locally using the canister's Wasm file. This method is discussed and demonstrated in this guide, as it gives you more control over the deployment and is lightweight. -If you want to deploy your own token or build an ICRC-1 ledger, have a look at the [guide on setting up an ICRC-1 ledger](/docs/current/developer-docs/defi/tokens/ledger/setup/icrc1_ledger_setup). +Deploying an ICP ledger locally using the Wasm or `.did` files gives you certain advantages over the default ledger from `dfx` that is installed with `dfx nns install`. For instance, you can define the `minting account`, you have control over the initialization arguments, and you have control over which Wasm version of the ICP ledger you want to interact with. -Follow the steps below to deploy your copy of the ledger canister to a local replica. +:::danger +The ICP ledger is not meant to be used for other token deployments because it needs to be backwards compatible and thus contains a lot of legacy code that should not be used when deploying a new ledger. -### Step 1: Make sure you use a recent version of the [IC SDK](/docs/current/developer-docs/getting-started/install). -If you don’t have the IC SDK installed, follow the instructions on the [installing the IC SDK](/docs/current/developer-docs/getting-started/install) section to install it. +If you want to deploy your own token, read the [guide on setting up an ICRC-1 ledger](/docs/current/developer-docs/defi/tokens/ledger/setup/icrc1_ledger_setup). +::: -### Step 2: Create a new dfx project with the command: +## Using `dfx nns install` -``` -dfx new icp_ledger_canister -cd icp_ledger_canister -``` +The [`dfx nns install`](/docs/current/developer-docs/developer-tools/cli-tools/cli-reference/dfx-nns) command can be used to deploy an instance of the entire NNS locally. The NNS includes the ICP ledger canister with canister ID `ryjl3-tyaaa-aaaaa-aaaba-cai`. -:::caution +## Using the most recent ICP ledger Wasm file -If using `dfx` version 0.17.1 or newer, choose 'Motoko' for the backend language, and 'No frontend canister' for the frontend language. + + -::: + Install the IC SDK. + + + -### Step 3: Determine the ledger file locations. +- #### Step 1: Create a new `dfx` project or open an existing project. -Go to the [releases overview](https://dashboard.internetcomputer.org/releases) and copy the latest replica binary revision. At the time of writing, this is `aba60ffbc46acfc8990bf4d5685c1360bd7026b9`. +- #### Step 2: Obtain the latest ledger Wasm and Candid files. -The URL for the ledger Wasm module is `https://download.dfinity.systems/ic//canisters/ledger-canister.wasm.gz`, so with the above revision it would be `https://download.dfinity.systems/ic/aba60ffbc46acfc8990bf4d5685c1360bd7026b9/canisters/ledger-canister.wasm.gz`. +Go to the [releases overview](https://dashboard.internetcomputer.org/releases) and copy the latest replica binary revision. -The URL for the ledger.did file is `https://raw.githubusercontent.com/dfinity/ic//rs/ledger_suite/icp/ledger.did`, so with the above revision it would be `https://raw.githubusercontent.com/dfinity/ic/aba60ffbc46acfc8990bf4d5685c1360bd7026b9/rs/ledger_suite/icp/ledger.did`. +The URL for the ledger Wasm module is `https://download.dfinity.systems/ic//canisters/ledger-canister.wasm.gz`. + +The URL for the ledger's Candid file is `https://raw.githubusercontent.com/dfinity/ic//rs/ledger_suite/icp/ledger.did`. #### Optional -If you want to make sure you have the latest ICP ledger files, you can run the following script. Please ensure that you have [`jq`](https://jqlang.github.io/jq/) installed as the script relies on it. +If you want to make sure you have the latest ICP ledger files, you can run the following script. Please ensure that you have [`jq`](https://jqlang.github.io/jq/) installed, as the script relies on it. + ``` sh curl -o download_latest_icp_ledger.sh "https://raw.githubusercontent.com/dfinity/ic/aba60ffbc46acfc8990bf4d5685c1360bd7026b9/rs/rosetta-api/scripts/download_latest_icp_ledger.sh" chmod +x download_latest_icp_ledger.sh ./download_latest_icp_ledger.sh ``` -### Step 4: Create a new identity that will work as a minting account: +- #### Step 3: Create a new identity that will work as a minting account. ``` sh dfx identity new minter @@ -102,22 +102,20 @@ dfx identity use minter echo $(dfx ledger account-id) ``` -Record the output of these commands as your minting 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. -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. +- #### Step 4: Switch back to your primary developer identity and record its ledger account identifier. ``` sh -dfx identity use default +dfx identity use MyIdentity echo $(dfx ledger account-id) ``` -Record the output of these commands as your default account ID. +Record the output of these commands as your developer account ID. -### Step 6: Configure the `dfx.json` file. +- #### Step 5: Configure the `dfx.json` file. -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: +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 `DEVELOPER_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. @@ -125,67 +123,104 @@ Open the `dfx.json` file in your project's directory. Replace the existing conte ``` json { - "canisters": { - "icp_ledger_canister": { - "type": "custom", - "candid": "https://raw.githubusercontent.com/dfinity/ic/aba60ffbc46acfc8990bf4d5685c1360bd7026b9/rs/ledger_suite/icp/ledger.did", - "wasm": "https://download.dfinity.systems/ic/aba60ffbc46acfc8990bf4d5685c1360bd7026b9/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\"; } })" - } - }, - "defaults": { - "build": { - "args": "", - "packtool": "" - } - }, - "output_env_file": ".env", - "version": 1 +  "canisters": { +    "icp_ledger_canister": { +      "type": "custom", +      "candid": "https://raw.githubusercontent.com/dfinity/ic/aba60ffbc46acfc8990bf4d5685c1360bd7026b9/rs/ledger_suite/icp/ledger.did", +      "wasm": "https://download.dfinity.systems/ic/aba60ffbc46acfc8990bf4d5685c1360bd7026b9/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\"; } })" +    } +  }, +  "defaults": { +    "build": { +      "args": "", +      "packtool": "" +    } +  }, +  "output_env_file": ".env", +  "version": 1 } ``` -If you chose to download the ICP ledger files with the script you need to replace the Candid and Wasm file entries: +:::danger +If you chose to download the ICP ledger files with the script, you need to replace the Candid and Wasm file entries: ```json ... "candid": icp_ledger.did, "wasm" : icp_ledger.wasm.gz, - ... +  ... ``` -This `dfx.json` file also defines the init arguments for the ledger canister: +::: + +This `dfx.json` file defines the init arguments for the ledger canister: - 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`. -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/). +### Init arguments + +You can also pass these init args to the canister [using the command line](/docs/current/developer-docs/developer-tools/cli-tools/advanced-dfx/init-args/#using-init_arg) or by [storing them in a file](/docs/current/developer-docs/developer-tools/cli-tools/advanced-dfx/init-args/#using-an-init_arg_file), then referencing that file in your `dfx.json` configuration: + +```json +{ +  "canisters": { +    "icp_ledger_canister": { +      "type": "custom", +      "candid": "https://raw.githubusercontent.com/dfinity/ic/aba60ffbc46acfc8990bf4d5685c1360bd7026b9/rs/ledger_suite/icp/ledger.did", +      "wasm": "https://download.dfinity.systems/ic/aba60ffbc46acfc8990bf4d5685c1360bd7026b9/canisters/ledger-canister.wasm.gz", +      "remote": { +        "id": { +          "ic": "ryjl3-tyaaa-aaaaa-aaaba-cai" +        } +      }, +      "init_arg_file" : "init-args.did" +    } +  }, +  "defaults": { +    "build": { +      "args": "", +      "packtool": "" +    } +  }, +  "output_env_file": ".env", +  "version": 1 +} +``` + +[Learn more about init args](/docs/current/developer-docs/developer-tools/cli-tools/advanced-dfx/init-args/). -### Step 7: Start a local replica. +- #### Step 6: Start a local replica. ``` sh dfx start --clean --background ``` -### Step 8: Deploy the ledger canister locally: +- #### Step 7: Deploy the ledger canister locally. :::caution -In this workflow, you cannot deploy this canister to the playground (using flag `dfx deploy --playground`) because it does not accept gzipped Wasm files. +You cannot deploy this canister to the playground (using the flag `dfx deploy --playground`) because it does not accept gzipped Wasm files. ::: ``` dfx deploy --specified-id ryjl3-tyaaa-aaaaa-aaaba-cai icp_ledger_canister ``` -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. +:::info +You are deploying the local ICP ledger canister to the same canister ID as the mainnet ledger canister. This is to facilitate switching between local and mainnet deployments. +::: + +Your local ICP ledger canister is up and running. You can now deploy other canisters that need to communicate with the ledger canister. -### Step 9: Interact with the canister. +- #### Step 8: Interact with the canister. You can interact with the canister by running CLI commands, such as: @@ -193,20 +228,8 @@ You can interact with the canister by running CLI commands, such as: dfx canister call icp_ledger_canister name ``` -This command will return the token's name, such as: - -``` -("Local ICP") -``` - Or, you can interact with it using the Candid UI by navigating to the URL provided when the canister was deployed, such as: ``` http://127.0.0.1:4943/?canisterId=bnz7o-iuaaa-aaaaa-qaaaa-cai&id=ryjl3-tyaaa-aaaaa-aaaba-cai -``` - -After navigating to this URL in a web browser, the Candid UI will resemble the following: - -![Candid UI](../../../_attachments/CandidUI.png) - -Your local ICP ledger canister is up and running. You can now deploy other canisters that need to communicate with the ledger canister. +``` \ No newline at end of file diff --git a/docs/developer-docs/defi/tokens/ledger/setup/icrc1_ledger_setup.mdx b/docs/developer-docs/defi/tokens/ledger/setup/icrc1_ledger_setup.mdx index d0692d5268..8dad6a4122 100644 --- a/docs/developer-docs/defi/tokens/ledger/setup/icrc1_ledger_setup.mdx +++ b/docs/developer-docs/defi/tokens/ledger/setup/icrc1_ledger_setup.mdx @@ -8,68 +8,60 @@ import { MarkdownChipRow } from "/src/components/Chip/MarkdownChipRow"; +ICRC-1 is a [token standard](https://github.com/dfinity/ICRC-1) used to create and deploy fungible tokens on the Internet Computer. Each token deployed on the network has its own dedicated ledger. Thus, deploying a new token that is ICRC-1-compatible is synonymous with deploying an ICRC-1 ledger. -This guide will show you how to deploy an ICRC-1 ledger locally and on the mainnet. ICRC-1 is a [token standard](https://github.com/dfinity/ICRC-1). Thus, deploying a new token that is ICRC-1-compatible is synonymous with deploying an ICRC-1 ledger. -The ICRC-1 ledger used in this guide is a reference implementation. This guide aims at showing you how to setup an existing ICRC-1 ledger implementation rather than how to build an ICRC-1 ledger yourself. +The ICRC-1 ledger used in this guide is a reference implementation used to demonstrate how to set up an existing ICRC-1 ledger implementation rather than how to build an ICRC-1 ledger yourself. +## Deploying the ICRC ledger locally -## Deploying the ledger locally + + -### Step 1: Make sure you use a recent version of the [IC SDK](/docs/current/developer-docs/getting-started/install). -If you don’t have the IC SDK installed, follow instructions on the [installing the IC SDK](/docs/current/developer-docs/getting-started/install) section to install it. + Install the IC SDK. -### Step 2: Create a new dfx project with the command: + + -``` -dfx new icrc1_ledger_canister -cd icrc1_ledger_canister -``` - -:::caution - -If using `dfx` version 0.17.1 or newer, choose 'Motoko' for the backend language, and 'No frontend canister' for the frontend language. +- #### Step 1: Create a new `dfx` project or open an existing project. -::: - -### Step 3: Determine ledger file locations. +- #### Step 2: Obtain the latest ledger Wasm and Candid files. -Search for [ledger-suite-icrc releases](https://github.com/dfinity/ic/releases?q=ledger-suite-icrc&expanded=false) and select the latest ICRC ledger suite release. At the time of writing, this is [`ledger-suite-icrc-2024-11-28`](https://github.com/dfinity/ic/releases/tag/ledger-suite-icrc-2024-11-28). +Search for [ledger-suite-icrc releases](https://github.com/dfinity/ic/releases?q=ledger-suite-icrc&expanded=false) and select the latest ICRC ledger suite release. -The URL for the ledger Wasm module is `https://github.com/dfinity/ic/releases/download//ic-icrc1-ledger.wasm.gz`, so with the above release it would be `https://github.com/dfinity/ic/releases/download/ledger-suite-icrc-2024-11-28/ic-icrc1-ledger.wasm.gz`. +The URL for the ledger Wasm module is `https://github.com/dfinity/ic/releases/download//ic-icrc1-ledger.wasm.gz`. -The URL for the ledger .did file is `https://github.com/dfinity/ic/releases/download//ledger.did`, so with the above release it would be `https://github.com/dfinity/ic/releases/download/ledger-suite-icrc-2024-11-28/ledger.did`. +The URL for the ledger Candid file is `https://github.com/dfinity/ic/releases/download//ledger.did`. +#### Optional +If you want to make sure you have the latest ICRC-1 ledger files, you can run the following script that downloads the files into your local directory: -#### Optional: -If you want to make sure you have the latest ICRC-1 ledger files you can run the following script that downloads the files into your local directory: ``` sh curl -o download_latest_icrc1_ledger.sh "https://raw.githubusercontent.com/dfinity/ic/aba60ffbc46acfc8990bf4d5685c1360bd7026b9/rs/rosetta-api/scripts/download_latest_icrc1_ledger.sh" chmod +x download_latest_icrc1_ledger.sh ./download_latest_icrc1_ledger.sh ``` -These files will be used by the `dfx.json` file as described in the next step. +- #### Step 4: Configure the `dfx.json` file. -### Step 4: Configure the `dfx.json` file. -Open the `dfx.json` file in your project's directory. Replace the existing content with the following and make sure you replace `` in the `candid` and `wasm` URLs as shown in step 3: +Open the `dfx.json` file in your project's directory. Replace the existing content with the following and make sure you replace `` in the `candid` and `wasm` URLs as shown in the previous step: ``` json { - "canisters": { - "icrc1_ledger_canister": { - "type": "custom", - "candid": "https://github.com/dfinity/ic/releases/download//ledger.did", - "wasm": "https://github.com/dfinity/ic/releases/download//ic-icrc1-ledger.wasm.gz" - } - }, - "defaults": { - "build": { - "args": "", - "packtool": "" - } - }, - "output_env_file": ".env", - "version": 1 +  "canisters": { +    "icrc1_ledger_canister": { +      "type": "custom", +      "candid": "https://github.com/dfinity/ic/releases/download//ledger.did", +      "wasm": "https://github.com/dfinity/ic/releases/download//ic-icrc1-ledger.wasm.gz" +    } +  }, +  "defaults": { +    "build": { +      "args": "", +      "packtool": "" +    } +  }, +  "output_env_file": ".env", +  "version": 1 } ``` @@ -79,16 +71,17 @@ If you chose to download the ICRC-1 ledger files with the script, you need to re ... "candid": "icrc1_ledger.did", "wasm" : "icrc1_ledger.wasm.gz" - ... +  ... ``` +:::info In an existing project you would only need to add the `icrc1_ledger_canister` canister to the `canisters` section instead of replacing the entire content of `dfx.json`. +::: ## Ledger test suite -There is a test suite available to [test ICRC-1 ledgers](https://github.com/dfinity/ICRC-1/tree/main/test). If you are building your own ICRC-1 repository, it might be helpful to run this test suite against your locally deployed ICRC-1 ledger, or import the test suite directly through a Rust crate and add the tests to your repository. You can find a reference implementation of integrating the [test suite to your repo](https://github.com/dfinity/ICRC-1/tree/main/test/ref). - +There is a test suite available for [ICRC-1 ledgers](https://github.com/dfinity/ICRC-1/tree/main/test). If you are building your own ICRC-1 repository, it might be helpful to run this test suite against your locally deployed ICRC-1 ledger, or import the test suite directly through a Rust crate and add the tests to your repository. You can find a reference implementation of integrating the [test suite to your repo](https://github.com/dfinity/ICRC-1/tree/main/test/ref). ## Next steps -Before you deploy your ledger canister, you will need to set some variables that you will pass to the canister during initialization that will create a new ICRC-1 or ICRC-2 token. To learn how to set these variables and deploy the ledger canister, see [create a token](/docs/developer-docs/defi/tokens/create.mdx). +Before you deploy your ledger canister, you will need to set some variables that you will pass to the canister during initialization that will create a new ICRC-1 or ICRC-2 token. To learn how to set these variables and deploy the ledger canister, see [create a token](/docs/developer-docs/defi/tokens/create.mdx). \ No newline at end of file diff --git a/docs/developer-docs/defi/tokens/ledger/usage/icp_ledger_usage.mdx b/docs/developer-docs/defi/tokens/ledger/usage/icp_ledger_usage.mdx index 58fa95467d..341206fd15 100644 --- a/docs/developer-docs/defi/tokens/ledger/usage/icp_ledger_usage.mdx +++ b/docs/developer-docs/defi/tokens/ledger/usage/icp_ledger_usage.mdx @@ -8,252 +8,79 @@ import { MarkdownChipRow } from "/src/components/Chip/MarkdownChipRow"; +How you interact with the ICP ledger is dependent on whether you want to interact with it from the command line, from your web app, or from another canister. Available workflows and tools include: -There are multiple ways to interact with the ICP ledger. They depend on whether you want to interact with the ICP ledger on mainnet, the `dfx ledger` default ICP ledger on a local network, or whether you have deployed your own local ledger version. Also, how you interact with the ICP ledger is dependent on whether you want to interact with it from the command line, from your web app, or from another canister. - -This guide will discuss the different ways to interact with the ICP ledger. In this guide, the following workflows will be covered: -- `dfx ledger`: the built in `dfx` shortcut for interacting with the ICP ledger. -- `dfx canister`: the generic canister call from `dfx`. +- `dfx ledger`: The `dfx` CLI command for interacting with the ICP ledger. +- `dfx canister`: A generic canister call using `dfx`. - [ledger-icp](https://github.com/dfinity/ic-js/tree/main/packages/ledger-icp) JavaScript library. -- `ic-cdk`: inter-canister calls for the ICP ledger. +- `ic-cdk`: Inter-canister calls for the ICP ledger. -## Interacting with ICP ledger via `dfx ledger` +## Interacting with the ICP ledger via `dfx ledger` -`dfx` provides a convenience command to interact with the ICP ledger canister and related functionality. You can find the documentation [here](/docs/current/developer-docs/developer-tools/cli-tools/cli-reference/dfx-ledger) or just enter the following command into your console: +`dfx` provides a convenience command to interact with the ICP ledger canister and related functionality: [`dfx ledger`](/docs/current/developer-docs/developer-tools/cli-tools/cli-reference/dfx-ledger). -``` bash -dfx ledger --help -``` +`dfx` does not come with an ICP ledger instance installed by default. To be able to use this command, you will need to install the [ICP ledger locally](/docs/developer-docs/defi/tokens/ledger/setup/icp_ledger_setup.mdx). -It's worth checking out the `--help` flag of the subcommands as well. -`dfx` does not come with an ICP ledger instance installed by default. To be able to use this command you will need to install the ICP ledger locally. You can do that by following this [guide](/docs/developer-docs/defi/tokens/ledger/setup/icp_ledger_setup.mdx) or by installing the NNS locally: -``` bash -dfx extension install nns -dfx nns install -``` -The ICP ledger will then run locally with the canister ID `ryjl3-tyaaa-aaaaa-aaaba-cai`. -Currently, `dfx` exposes only a subset of the ICP ledger functionality, namely `balance` and `transfer`. -Both commands provide a flag to specify a ledger canister id (`--ledger-canister-id`). This simplifies interacting with a local ledger deployment or other tokens that provide the same interface. If you do not specify the canister ID `dfx ledger` will assume you want to interact with a ICP ledger that has a canister ID of `ryjl3-tyaaa-aaaaa-aaaba-cai` or with the ICP ledger on the mainnet. For the latter, you need to specify the mainnet as the network of choice using the flag `--network ic`. - -:::info -Summary of different `dfx ledger` commands: -- `dfx ledger ...`: interact with the ICP ledger on your local network with canister ID `ryjl3-tyaaa-aaaaa-aaaba-cai`. -- `dfx ledger --network ic ...`: interact with the ICP ledger on the mainnet. -- `dfx ledger --ledger-canister-id ...`: interact with the [locally deployed](/docs/developer-docs/defi/tokens/ledger/setup/icp_ledger_setup.mdx) ICP ledger on your local network. -::: +Currently, `dfx ledger` only exposes a subset of the ICP ledger functionality, namely `balance` and `transfer`. -### Balance +View the [`dfx ledger`](/docs/current/developer-docs/developer-tools/cli-tools/cli-reference/dfx-ledger) documentation for all available `dfx ledger` commands and flags. -Get the ICP balance of a specific account: +## Interacting with the ICP ledger via `dfx canister` -``` bash -dfx ledger --network ic balance -``` +The ICP ledger canister ID is assumed to be `ryjl3-tyaaa-aaaaa-aaaba-cai`. If your locally deployed ICP ledger's canister ID is different, you will need to replace `ryjl3-tyaaa-aaaaa-aaaba-cai` with it. -The `` is encoded as a hex string. You can print the account id of the current `dfx` identity by running: +Use the following command syntax to interact with the ICP ledger via `dfx canister`: -```bash -dfx ledger account-id ``` - -In many cases you want to check the main account balance of a specific principal. You can combine the `balance` command with the `account-id` command, while specifying an `--of-principal` argument to yield this helpful command: - -``` bash -dfx ledger --network ic balance $(dfx ledger account-id --of-principal ) +dfx canister call ``` -### Transfer - -The transfer function can be used to transfer ICP from your account to another. +For example, to fetch the token symbol of the ICP ledger, call the `symbol` method: -``` bash -dfx ledger --network ic transfer --amount --memo -``` - -## Interacting with ICP ledger via `dfx canister` -For this subsection it is assumed that you have deployed an ICP ledger either locally or you want to communicate with the mainnet ICP ledger using `dfx canister`. The ICP ledger canister ID is assumed to be `ryjl3-tyaaa-aaaaa-aaaba-cai`, if your locally deployed ICP ledger's canister ID is different you will need to replace `ryjl3-tyaaa-aaaaa-aaaba-cai` with it. You can find all endpoints that can be called in the `icp_ledger.did` file. How to retrieve it is discussed in the [ICP local deployment guide](/docs/developer-docs/defi/tokens/ledger/setup/icp_ledger_setup.mdx). - -This guide will only go into the ICP ledger specific endpoints. To call the ICRC-1 endpoints you can have a look at [the ICRC-1 setup guide](/docs/current/developer-docs/defi/tokens/indexes). To find a more detailed description of the data types used in these commands you can have a look at [this guide](/docs/current/references/ledger#_getting_ledger_blocks). - -To fetch the symbol of the ICP ledger: ``` dfx canister call ryjl3-tyaaa-aaaaa-aaaba-cai symbol '()' ``` -This command returns the ICP symbol: -``` -(record { symbol = "ICP" }) -``` -To fetch the name of the ICP ledger: -``` -dfx canister call ryjl3-tyaaa-aaaaa-aaaba-cai name '()' -``` -This command returns the ICP name: -``` -(record { name = "Internet Computer" }) -``` +You can find all available methods listed within the ICP ledger canister's Candid file or view the [mainnet ICP ledger canister on the dashboard](https://dashboard.internetcomputer.org/canister/ryjl3-tyaaa-aaaaa-aaaba-cai). -To fetch the decimals of the ICP ledger: -``` -dfx canister call ryjl3-tyaaa-aaaaa-aaaba-cai decimals '()' -``` -This command returns the ICP decimals: -``` -(record { decimals = 8 : nat32 }) -``` -To handle a growing number of transactions within limited canister memory, a new archive canister is created when the history exceeds a threshold, migrating older transactions to it. +[View a more detailed description of the data types used in these commands](/docs/current/references/ledger#_getting_ledger_blocks). -To fetch the archives of the ICP ledger: -``` -dfx canister call ryjl3-tyaaa-aaaaa-aaaba-cai archives '()' -``` -If you are testing locally, no archive canisters should have been created yet: -``` -(record { archives = vec {} }) -``` -However, if you are testing on mainnet, the following archive canisters have been created as of the time of writing this document: -``` -( - record { - archives = vec { - record { canister_id = principal "qjdve-lqaaa-aaaaa-aaaeq-cai" }; - record { canister_id = principal "qsgjb-riaaa-aaaaa-aaaga-cai" }; - record { canister_id = principal "q4eej-kyaaa-aaaaa-aaaha-cai" }; - }; - }, -) -``` +## Interact with ICP ledger from your web application -To send tokens to the `AccountIdentifier` `d52f7f2b7277f025bcaa5c90b10d122274faba289` you can use the following commands. You will need to derive the `AccountIdentifier` by getting the principal first: -``` -dfx ledger account-id --of-principal -``` -You can get the principal of an identity by calling: -``` -dfx identity get-principal --identity -``` -If you have an identity called `default2` and you want to send ICP to this principals default `AccountIdentifier` you would call: - ``` -dfx identity get-principal --identity default2 -``` -This command will return: -``` -sckqo-e2vyl-4rqqu-5g4wf-pqskh-iynjm-46ixm-awluw-ucnqa-4sl6j-mqe -``` -If you plug this response value into the `account-id` command: -``` -dfx ledger account-id --of-principal sckqo-e2vyl-4rqqu-5g4wf-pqskh-iynjm-46ixm-awluw-ucnqa-4sl6j-mqe -``` -The following response will be returned: -``` -d52f7f2b7277f025bcaa5c90b10d122274faba289 -``` -You can bring all of these commands together to form a transfer transaction: -``` -export TO_ACCOUNT = "d52f7f2b7277f025bcaa5c90b10d122274faba2891bea519105309ae1f0af91d" -dfx canister call ryjl3-tyaaa-aaaaa-aaaba-cai transfer '(record { to = $(python3 -c 'print("vec{" + ";".join([str(b) for b in bytes.fromhex("'$TO_ACCOUNT'")]) + "}")'); memo = 1:nat64; amount = record {e8s = 200_000_000 }; fee = record { e8s = 10_000 }; })' -``` +In order to simplify working with the ICP ledger from JavaScript applications, you can use the [ledger-icp](https://github.com/dfinity/ic-js/tree/main/packages/ledger-icp) JavaScript library. -This command returns the block index in which this transaction took place. In this example, it was the first block: -``` -(variant { Ok = 1 : nat64 }) -``` -To get the balance of an `AccountIdentifier` you can call: -``` -dfx canister call ryjl3-tyaaa-aaaaa-aaaba-cai account_balance '(record { account = '$(python3 -c 'print("vec{" + ";".join([str(b) for b in bytes.fromhex("'$TO_ACCOUNT'")]) + "}")')' })' -``` -It returns the the balance in e8s of the `AccountIdentifier` `d52f7f2b7277f025bcaa5c90b10d122274faba2891bea519105309ae1f0af91d`. It should have a balance of 200 million as thats the amount you sent earlier: -``` -(record { e8s = 200_000_000 : nat64 }) -``` +:::info +To interact with the ICRC-1 endpoints of the ICP ledger, learn more about [interacting with an ICRC-1 ledger](/docs/current/developer-docs/defi/tokens/indexes). +::: -To query the created blocks from the ICP ledger you can call: -``` -dfx canister call ryjl3-tyaaa-aaaaa-aaaba-cai query_blocks '(record {start = 1:nat64; length = 1:nat64})' -``` +## Interacting with ICP from a canister (inter-canister calls via `ic-cdk`) -You will have to specify the first block to fetch and the number of blocks to fetch. -This command will return output that resembles the following: +View the [inter-canister call documentation] (/docs/developer-docs/backend/rust/intercanister) to see how you can call one canister from within another. -``` -( - record { - certificate = opt blob "\d9\d9\f7\a2dtree\83\01\83\01\83\01\83\02Hcanister\83\01\83\01\82\04X \05\8f\12\83V\ad(\b6q\e6\0b\60\d2\90\97<\a0\8c~\ea\a9\18\13j\fe<\bbH\1a^n1\83\02J\80\00\00\00\00\10\00\01\01\01\83\01\83\01\83\01\83\02Ncertified_data\82\03X \f5}\c2M\a6\87\fe\03N9H/4?\bd\a8\1c\ad\ba\0b\86,\98\8dx)\11\b9=*\b7\eb\82\04X \83\c5k\f1M\de=(\def\c6\92\b5\fc\9d\97\e9\dd\98[j\d7+\0f\e6\f8N\8a\8d\f3\dc\b2\82\04X l\96\c1\d2D\fe\c00\d5S\f6N\0b4q]\9do\d7\a00\90\a0\8e\c03K\f6\f2hT\fe\82\04X \99i\83\c5\0b\0ec\02\dd\d9{r\a8\cb\7f?\f5\03\04\88\b1QC\d0\15\9eR\87\da(\d6\08\82\04X \97\c3\ef\e5\dc\efyN\1b\cd\d3\a1\c2\bbE\84y@\fc(\ec\87\cb5yk\ef\d74\b5\ef\cf\82\04X S\ebWak\00\b4#\a3\94I+\b0\9a\dc\11\b5\ff\1a\96\b0\a7\cede8\1b\b8\16\1d\14\dd\82\04X \13\c86\94\98\d9\ae)\a7\e4\f3\19\97\08\a2\dc\a5\a5(v\90\f8a\19rL\aa\09\0c\1b\d5\d5\83\01\82\04X \17+O\f52\a3\22\7f\87S\9bop\a6\18\b1\16\e1\1f\19\c2\9e\1f\ea:\df-\e47/\1d\e0\83\02Dtime\82\03I\90\f9\8e\d7\a0\88\b6\c4\17isignatureX0\aa6/\f2b\9a\c1%\98\f6\e32\e0\de\11\0e(\fe\f9=\b09z\be\a3\e7\8aG\d0:\18k\e0o\ed\f3\ba\d2\84\17yAAx\9cm\bf\06"; - blocks = vec { - record { - transaction = record { - memo = 1 : nat64; - icrc1_memo = null; - operation = opt variant { - Transfer = record { - to = blob "\08.\cf.?dz\c6\00\f4?8\a6\83B\fb\a5\b8\e6\8b\08_\02Y+w\f3\98\08\a8\d2\b5"; - fee = record { e8s = 10_000 : nat64 }; - from = blob "\0amCu\816\9bTj\fd\efa<\a9\c0\81\a2R\ca,F\e7\ec)\e5\10\bc\10\b2\13\fa\27"; - amount = record { e8s = 200_000_000 : nat64 }; - } - }; - created_at_time = record { - timestamp_nanos = 1_695_815_275_230_210_000 : nat64; - }; - }; - timestamp = record { - timestamp_nanos = 1_695_815_275_230_210_000 : nat64; - }; - parent_hash = opt blob "\e6{0\db\a6\a5)1\17@\9d\e7h\ee\85\b0\91h>l\a2\fdxi\d3;x\85\bf\e7\d0a"; - }; - }; - chain_length = 6 : nat64; - first_block_index = 1 : nat64; - archived_blocks = vec {}; - }, -) -``` +Here is an example of how to fetch the token name from the ICP ledger using Rust and the `ic-cdk` [library](https://github.com/dfinity/cdk-rs) from within a canister: -To only query the encoded blocks from the ICP ledger you can call: ``` -dfx canister call ryjl3-tyaaa-aaaaa-aaaba-cai query_encoded_blocks '(record {start = 1:nat64; length = 1:nat64})' -``` -It is a similar format but you will only receive the CBOR encoded block: -``` -( - record { - certificate = opt blob "\d9\d9\f7\a2dtree\83\01\83\01\83\01\83\02Hcanister\83\01\83\01\82\04X \05\8f\12\83V\ad(\b6q\e6\0b\60\d2\90\97<\a0\8c~\ea\a9\18\13j\fe<\bbH\1a^n1\83\02J\80\00\00\00\00\10\00\01\01\01\83\01\83\01\83\01\83\02Ncertified_data\82\03X \f5}\c2M\a6\87\fe\03N9H/4?\bd\a8\1c\ad\ba\0b\86,\98\8dx)\11\b9=*\b7\eb\82\04X \83\c5k\f1M\de=(\def\c6\92\b5\fc\9d\97\e9\dd\98[j\d7+\0f\e6\f8N\8a\8d\f3\dc\b2\82\04X l\96\c1\d2D\fe\c00\d5S\f6N\0b4q]\9do\d7\a00\90\a0\8e\c03K\f6\f2hT\fe\82\04X \99i\83\c5\0b\0ec\02\dd\d9{r\a8\cb\7f?\f5\03\04\88\b1QC\d0\15\9eR\87\da(\d6\08\82\04X \97\c3\ef\e5\dc\efyN\1b\cd\d3\a1\c2\bbE\84y@\fc(\ec\87\cb5yk\ef\d74\b5\ef\cf\82\04X \aao\e5\85L\f7\0b\e3V\07\ed\27\88k\a5z\bd\abQ\aa=\dcc>m\0b\b1\88\ea\c8\f4\b7\82\04X \13\c86\94\98\d9\ae)\a7\e4\f3\19\97\08\a2\dc\a5\a5(v\90\f8a\19rL\aa\09\0c\1b\d5\d5\83\01\82\04X \17+O\f52\a3\22\7f\87S\9bop\a6\18\b1\16\e1\1f\19\c2\9e\1f\ea:\df-\e47/\1d\e0\83\02Dtime\82\03I\b8\c7\d9\f5\9a\8a\b6\c4\17isignatureX0\af\9e\c3\d1\e3\95\c8\1b\0c\b8\5cC\b0\fb\f9E\e0\eeJ\88\1f\e7%G\06\b8\ac\a4\14{\e1k\97\15\8d\8a0\c6\9d\86\a1\03\ef\02\b7\82A\f9"; - blocks = vec { - blob "\0a\22\0a \e6{0\db\a6\a5)1\17@\9d\e7h\ee\85\b0\91h>l\a2\fdxi\d3;x\85\bf\e7\d0a\12\0a\08\d0\cf\9c\e6\a0\e0\af\c4\17\1af\1aT\0a\22\0a \0amCu\816\9bTj\fd\efa<\a9\c0\81\a2R\ca,F\e7\ec)\e5\10\bc\10\b2\13\fa\27\12\22\0a \08.\cf.?dz\c6\00\f4?8\a6\83B\fb\a5\b8\e6\8b\08_\02Y+w\f3\98\08\a8\d2\b5\1a\05\08\80\84\af_\22\03\08\90N\22\02\08\012\0a\08\d0\cf\9c\e6\a0\e0\af\c4\17"; - }; - chain_length = 6 : nat64; - first_block_index = 1 : nat64; - archived_blocks = vec {}; - }, -) -``` - -## Interact with ICP ledger from your web application +// You will need the canister ID of the ICP ledger: `ryjl3-tyaaa-aaaaa-aaaba-cai`. -In order to simplify working with ICP ledger from JavaScript applications, you can use the [ledger-icp](https://github.com/dfinity/ic-js/tree/main/packages/ledger-icp) JavaScript library. -. -To interact with the ICRC-1 endpoints of the ICP ledger you can have a look at the guide on [interacting with an ICRC-1 ledger](/docs/current/developer-docs/defi/tokens/indexes). - -## Interacting with ICP from a canister (inter-canister calls via `ic-cdk`) -You can look at the documentation of [inter-canister calls] (/docs/developer-docs/backend/rust/intercanister) to see how you can interact with the another canister from inside a canister. This guide will give you a couple of examples on how to make such a call in the case of the ICP ledger. - -Here is an example on how fetch the name from the ICP ledger using Rust and the `ic-cdk` [library](https://github.com/dfinity/cdk-rs) from withing a canister: -``` -// You will need the principal of the ICP ledger. The canister id of the ICP ledger on mainnet and the dfx default ICP ledger locally is `ryjl3-tyaaa-aaaaa-aaaba-cai`. let ledger_id = Principal::from_text("ryjl3-tyaaa-aaaaa-aaaba-cai").unwrap(); + // The request object of the `icrc1_name` endpoint is empty. - let req = (); - let (res,): (String,) = - ic_cdk::call(ledger_id, "icrc1_name", (req,)) - .await.unwrap(); + +    let req = (); +    let (res,): (String,) = +        ic_cdk::call(ledger_id, "icrc1_name", (req,)) +            .await.unwrap(); ``` -For all other endpoints you can use the request and response structure from the `ledger.did` Candid file. How to retrieve the Candid file is explained in [the guide on deploying an ICP ledger locally](/docs/developer-docs/defi/tokens/ledger/setup/icp_ledger_setup.mdx). +You can find all available methods listed within the ICP ledger canister's Candid file or view the [mainnet ICP ledger canister on the dashboard](https://dashboard.internetcomputer.org/canister/ryjl3-tyaaa-aaaaa-aaaba-cai). ### `icrc-ledger-types` Rust crate -As explained in the [token standards](/docs/current/developer-docs/defi/tokens/token-standards), the ICP ledger supports all ICRC-1 endpoints. You will need to define the structures used for these endpoints. -To interact with ICRC-1 and ICRC-2 endpoints, the Rust crate [icrc-ledger-types](https://crates.io/crates/icrc-ledger-types) can be used. -This is true for the ICP ledger as well as any other canister that supports ICRC-1 or any of the ICRC-1 extension standards (i.e ICRC-2, ICRC-3,...). + +As explained in [token standards](/docs/current/developer-docs/defi/tokens/token-standards), the ICP ledger supports all ICRC-1 endpoints. You will need to define the structures used for these endpoints. + +To interact with the ICRC-1 and ICRC-2 endpoints, the Rust crate [icrc-ledger-types](https://crates.io/crates/icrc-ledger-types) can be used. +This is true for the ICP ledger as well as any other canister that supports ICRC-1 or any of the ICRC-1 extension standards (i.e., ICRC-2, ICRC-3,...). + The crate can be installed with the command: ``` @@ -268,43 +95,42 @@ icrc-ledger-types = "0.1.1" [View the documentation for this crate](https://docs.rs/icrc-ledger-types/0.1.1/icrc_ledger_types/). - ### Receiving ICP -If you want a canister to receive payment in ICP you need to make sure that the canister knows about the payment, because a transfer only involves the sender and the ledger canister. +If you want a canister to receive payment in ICP, you need to make sure that the canister knows about the payment because a transfer only involves the sender and the ledger canister. -There are currently two main patterns to achieve this. Furthermore, there is a [chartered working group](https://forum.dfinity.org/t/announcing-technical-working-groups/11781) on Ledger & Tokenization which is focused on defining a standard ledger/token interface as well payment flows. +There are currently two main patterns to achieve this. Furthermore, there is a [chartered working group](https://forum.dfinity.org/t/announcing-technical-working-groups/11781) on ledger and tokenization that is focused on defining a standard ledger token interface and payment flows. #### Direct notification by sender -In this pattern the sender notifies the receiver about the payment. However, the receiver needs to verify the payment by using the [`query_blocks` interface](/docs/current/references/ledger#_getting_ledger_blocks) of the ledger. +In this pattern, the sender notifies the receiver about the payment. However, the receiver needs to verify the payment by using the [`query_blocks` interface](/docs/current/references/ledger#_getting_ledger_blocks) of the ledger. + The following diagram shows a simplified illustration of this pattern: ```plantuml - participant Sender - participant "ICP Ledger" - participant Receiver - - Sender -> "ICP Ledger": transfer() - "ICP Ledger" --> Sender: blockNumber - Sender -> Receiver: notify(blockNumber) - Receiver -> "ICP Ledger": query_blocks(blockNumber) - "ICP Ledger" --> Receiver: block - Receiver -> Receiver: verify payment -``` +    participant Sender +    participant "ICP Ledger" +    participant Receiver +    Sender -> "ICP Ledger": transfer() +    "ICP Ledger" --> Sender: blockNumber +    Sender -> Receiver: notify(blockNumber) +    Receiver -> "ICP Ledger": query_blocks(blockNumber) +    "ICP Ledger" --> Receiver: block +    Receiver -> Receiver: verify payment +``` #### Notification by ICP ledger (currently disabled) -In this pattern the ledger itself notifies the receiver. Thereby, the receiver can trust the notification immediately. However, this flow is currently disabled because the call to the receiver is not yet implemented as a one-way call. +In this pattern, the ledger itself notifies the receiver. Thereby, the receiver can trust the notification immediately. However, this flow is currently disabled because the call to the receiver is not yet implemented as a one-way call. ```plantuml - participant Sender - participant "ICP Ledger" - participant Receiver - - Sender -> "ICP Ledger": transfer() - "ICP Ledger" --> Sender: blockNumber - Sender -> "ICP Ledger": notify(blockNumber, receiver) - "ICP Ledger" -> "Receiver": transaction_notification(details) -``` +    participant Sender +    participant "ICP Ledger" +    participant Receiver + +    Sender -> "ICP Ledger": transfer() +    "ICP Ledger" --> Sender: blockNumber +    Sender -> "ICP Ledger": notify(blockNumber, receiver) +    "ICP Ledger" -> "Receiver": transaction_notification(details) +``` \ No newline at end of file diff --git a/docs/developer-docs/defi/tokens/ledger/usage/icrc1_ledger_usage.mdx b/docs/developer-docs/defi/tokens/ledger/usage/icrc1_ledger_usage.mdx index e0fdda2854..3413fb44da 100644 --- a/docs/developer-docs/defi/tokens/ledger/usage/icrc1_ledger_usage.mdx +++ b/docs/developer-docs/defi/tokens/ledger/usage/icrc1_ledger_usage.mdx @@ -1,215 +1,87 @@ --- -keywords: [intermediate, tokens, icrc, tutorial, ledger] +keywords: [intermediate, tokens, icrc, icrc-1, icrc-2, icrc-3, icrc tokens, tutorial, ledger] --- import { MarkdownChipRow } from "/src/components/Chip/MarkdownChipRow"; -# Using the ICRC-1 ledger +# Using an ICRC-1 ledger +There are three primary methods used to interact with an ICRC-1 ledger: -There are two main ways to interact with an ICRC-1 ledger. -- `dfx canister`: The generic canister call from `dfx`. -- `ic-cdk`: Inter-canister calls for the ICRC-1 ledger. -- [`ledger-icrc-js`](https://github.com/dfinity/ic-js/tree/main/packages/ledger-icrc): A library for interfacing with ICRC-1 ledger on the Internet Computer. - -## ICRC-1 and ICRC-1 extension endpoints - -Whether your ICRC-1 ledger will have all the endpoints discussed in this tutorial will depend on if you chose to support any of the extensions of ICRC-1 (ICRC-2, ICRC-3,...). -This tutorial will go through the endpoints for ICRC-1 and the extension ICRC-2. If you have deployed an ICRC-1 ledger according to the [guide](/docs/developer-docs/defi/tokens/ledger/setup/icrc1_ledger_setup.mdx) you have to make sure that you have enabled the ICRC-2 standard, otherwise, the calls demonstrated in this guide will not work. - -You can always check which standards are supported by a certain ICRC-1 ledger by calling: - -``` -dfx canister call icrc1_ledger_canister icrc1_supported_standards '()' -``` - -The ICRC-1 ledger used in this guide also supports the extension ICRC-2: - -``` - -( - vec { - record { - url = "https://github.com/dfinity/ICRC-1/tree/main/standards/ICRC-1"; - name = "ICRC-1"; - }; - record { - url = "https://github.com/dfinity/ICRC-1/tree/main/standards/ICRC-2"; - name = "ICRC-2"; - }; - }, -) -``` - -The return values as well as the canister name `icrc1_ledger_canister` in this tutorial are specific to the deployed ICRC-1 ledger and thus may differ to your return values, depending on which values you chose during your [ICRC-1 ledger setup](/docs/developer-docs/defi/tokens/ledger/setup/icrc1_ledger_setup.mdx). - -### ICRC-1 endpoints - -To fetch the symbol of the ICRC-1 ledger: - -``` -dfx canister call icrc1_ledger_canister icrc1_symbol '()' -``` +- `dfx canister`: The generic canister call from `dfx` used to call a canister's methods. -This command returns: - -``` -("XMTK") -``` - -To fetch the decimals of the ICRC-1 ledger: - -``` -dfx canister call icrc1_ledger_canister icrc1_decimals '()' -``` - -This command returns: - -``` -(8 : nat8) -``` - -To fetch the metadata of the ICRC-1 ledger: - -``` -dfx canister call icrc1_ledger_canister icrc1_metadata '()' -``` - -This command returns: +- `ic-cdk`: Inter-canister calls for the ICRC-1 ledger. -``` -( - vec { - record { "icrc1:decimals"; variant { Nat = 8 : nat } }; - record { "icrc1:name"; variant { Text = "My Token" } }; - record { "icrc1:symbol"; variant { Text = "XMTK" } }; - record { "icrc1:fee"; variant { Nat = 10_000 : nat } }; - record { "icrc1:max_memo_length"; variant { Nat = 32 : nat } }; - }, -) -``` +- [`ledger-icrc-js`](https://github.com/dfinity/ic-js/tree/main/packages/ledger-icrc): A library for interfacing with an ICRC-1 ledger on the Internet Computer. -To fetch the total supply of the ICRC-1 ledger: +## Interact with an ICRC-1 canister using `dfx canister call` -``` -dfx canister call icrc1_ledger_canister icrc1_total_supply '()' -``` +### ICRC-1 -This command returns: +Use the following command syntax to interact with an ICRC-1 ledger via `dfx canister`: ``` -(10_000_000_000 : nat) +dfx canister call ``` -To fetch the fee of the ICRC-1 ledger: +For example, to fetch the token symbol of an ICRC-1 ledger, call the `icrc1_symbol` method: ``` -dfx canister call icrc1_ledger_canister icrc1_fee '()' +dfx canister call ss2fx-dyaaa-aaaar-qacoq-cai icrc1_symbol '()' ``` -This command returns: - -``` -(10_000 : nat) -``` +Whether your ICRC-1 ledger will have all available methods enabled will depend on if you choose to support any of the extensions of ICRC-1 (ICRC-2, ICRC-3,...). -To fetch the minting account of the ICRC-1 ledger: +You can always check which standards are supported by a certain ICRC-1 ledger by calling: ``` -dfx canister call icrc1_ledger_canister icrc1_minting_account '()' +dfx canister call icrc1_supported_standards '()' ``` -This command returns: +You can find all available methods for your ICRC-1 ledger within the ICRC-1 ledger canister's Candid file or, if your ICRC-1 ledger has been deployed to the mainnet, view your ICRC-1 ledger canister [on the dashboard](https://dashboard.internetcomputer.org/canisters). An example of an ICRC-1 ledger deployed on the mainnet that you can reference is the [ckETH ledger canister](https://dashboard.internetcomputer.org/canister/ss2fx-dyaaa-aaaar-qacoq-cai). -``` -( - opt record { - owner = principal "rrd6e-uoar3-ehz42-jxkun-ymmmv-jw4rn-re7se-5hymk-aoizl-bfb3j-uqe"; - subaccount = null; - }, -) -``` +View the [`dfx canister call` documentation](/docs/current/developer-docs/developer-tools/cli-tools/cli-reference/dfx-canister#dfx-canister-call) for more information on calling canister methods. -To fetch the balance of an account (DEFAULT account in this case, with no subaccount set) on the ICRC-1 ledger: -``` -dfx canister call icrc1_ledger_canister icrc1_balance_of "(record {owner = principal \"${DEFAULT}\"; })" -``` +### ICRC-2 -This command returns: +For ledgers that support ICRC-2, you can call ICRC-2 methods. ICRC-2 methods include those for `approve` workflows. For specifics, see the [ICRC-2 standard](https://github.com/dfinity/ICRC-1/tree/main/standards/ICRC-2#icrc2_approve). -``` -(10_000_000_000 : nat) -``` +View the [`dfx canister call` documentation](/docs/current/developer-docs/developer-tools/cli-tools/cli-reference/dfx-canister#dfx-canister-call) for more information on calling canister methods. -Transferring of tokens (from `DEFAULT` to the arbitrary principal `sckqo-e2vyl-4rqqu-5g4wf-pqskh-iynjm-46ixm-awluw-ucnqa-4sl6j-mqe`) on the ICRC-1 ledger: +## Interacting with an ICRC-1 ledger from your web application (`ledger-icrc-js`) -``` -dfx canister call icrc1_ledger_canister icrc1_transfer "(record { to = record { owner = principal \"sckqo-e2vyl-4rqqu-5g4wf-pqskh-iynjm-46ixm-awluw-ucnqa-4sl6j-mqe\";}; amount = 10_000;})" -``` +[View specifications and examples on how to use the `ledger-icrc-js` library to interact with ICRC-1 ledgers](https://github.com/dfinity/ic-js/tree/main/packages/ledger-icrc). -This command returns: +## Interacting with an ICRC-1 ledger from another canister (inter-canister calls via `ic-cdk`) -``` -(variant { Ok = 1 : nat }) -``` +View the [inter-canister call documentation] (/docs/developer-docs/backend/rust/intercanister) to see how you can call one canister from within another. -### ICRC-2 endpoints +Here is an example of how to fetch the token name from the ICP ledger using Rust and the `ic-cdk` [library](https://github.com/dfinity/cdk-rs) from within a canister: -To approve tokens to a certain spender (this guide uses the principal `sckqo-e2vyl-4rqqu-5g4wf-pqskh-iynjm-46ixm-awluw-ucnqa-4sl6j-mqe`) you can call: -``` -dfx canister call icrc1_ledger_canister icrc2_approve "(record { amount = 100_000; spender = record{owner = principal \"sckqo-e2vyl-4rqqu-5g4wf-pqskh-iynjm-46ixm-awluw-ucnqa-4sl6j-mqe\";} })" ``` +// You will need the canister ID of the ICRC ledger. -This command returns the block index of the transaction. Since this is the second transaction the index will be 2: +let ledger_id = Principal::from_text("ss2fx-dyaaa-aaaar-qacoq-cai").unwrap(); -``` -(variant { Ok = 2 : nat }) -``` +// The request object of the `icrc1_name` endpoint is empty. -To check the allowance of the spender `sckqo-e2vyl-4rqqu-5g4wf-pqskh-iynjm-46ixm-awluw-ucnqa-4sl6j-mqe` from the previous command you can call: -``` -dfx canister call icrc1_ledger_canister icrc2_allowance "(record { account = record{owner = principal "${DEFAULT}";}; spender = record{owner = principal "sckqo-e2vyl-4rqqu-5g4wf-pqskh-iynjm-46ixm-awluw-ucnqa-4sl6j-mqe";} })" +    let req = (); +    let (res,): (String,) = +        ic_cdk::call(ledger_id, "icrc1_name", (req,)) +            .await.unwrap(); ``` -This command will return the allowance of `sckqo-e2vyl-4rqqu-5g4wf-pqskh-iynjm-46ixm-awluw-ucnqa-4sl6j-mqe` for tokens approved by the `DEFAULT` principal. You should expect this to be the `100_000` tokens you approved earlier: -``` -(record { allowance = 100_000 : nat; expires_at = null }) -``` -Alternatively, you can also set the expiration date for approval. For specifics, see the [ICRC-2 standard](https://github.com/dfinity/ICRC-1/tree/main/standards/ICRC-2#icrc2_approve). +You can find all available methods for your ICRC-1 ledger within the ICRC-1 ledger canister's Candid file or, if your ICRC-1 ledger has been deployed to the mainnet, view your ICRC-1 ledger canister [on the dashboard](https://dashboard.internetcomputer.org/canisters). An example of an ICRC-1 ledger deployed on the mainnet that you can reference is the [ckETH ledger canister](https://dashboard.internetcomputer.org/canister/ss2fx-dyaaa-aaaar-qacoq-cai). -If the spender now wants to transfer tokens that were previously approved for the spender to a certain principal (in this case, use the arbitrary principal `7tmcj-ukheu-y6dvi-fhmxv-7qs5t-lwgh2-qzojr-vzt6m-maqv4-hvzlg-5qe`) you can call: -``` -dfx canister call icrc1_ledger_canister icrc2_transfer_from "(record { amount = 90_000; from = record{owner = principal \"${DEFAULT}\"}; to= record{owner = principal \"${DEFAULT}\"}; })" -``` -Note that you cannot transfer the entire allowance as the fee for making a transfer has to be substracted from the transferred amount. For the reference implementation the fee is `10_000` tokens. Thus, the maximum amount that can be transferred from `DEFAULT` to `7tmcj-ukheu-y6dvi-fhmxv-7qs5t-lwgh2-qzojr-vzt6m-maqv4-hvzlg-5qe` with the spender `sckqo-e2vyl-4rqqu-5g4wf-pqskh-iynjm-46ixm-awluw-ucnqa-4sl6j-mqe` is `90_000`. -The principal making this call has to be the spender, since they are the one that received the approval. -You will receive the block index as a return value: -``` -(variant { Ok = 3 : nat }) -``` -## Interacting with an ICRC-1 ledger from another canister (inter-canister calls via `ic-cdk`) -You can look at the documentation of [inter-canister calls](/docs/current/developer-docs/backend/rust/intercanister) to see how you can interact with another canister from inside a canister. This guide will give you a couple of examples of how to make such a call in the case of the ICRC-1 ledger. - -Here is an example of how to fetch the name from the ICRC-1 ledger using Rust and the `ic-cdk` [library](https://github.com/dfinity/cdk-rs) from within a canister: -You will need the principal of the ICRC-1 ledger. For this guide, take the canister ID that was used in the previous guide on [deploying an ICRC-1 ledger](/docs/developer-docs/defi/tokens/ledger/setup/icrc1_ledger_setup.mdx), which was `mxzaz-hqaaa-aaaar-qaada-cai`. -``` -let ledger_id = Principal::from_text("mxzaz-hqaaa-aaaar-qaada-cai").unwrap(); -// The request object of the `icrc1_name` endpoint is empty. - let req = (); - let (res,): (String,) = - ic_cdk::call(ledger_id, "icrc1_name", (req,)) - .await.unwrap(); -``` +### `icrc-ledger-types` Rust crate -For all other endpoints you can use the request and response structure from the `ledger.did` Candid file. How to retrieve the Candid file is explained in [the guide on deploying an ICRC-1 ledger locally](/docs/developer-docs/defi/tokens/ledger/setup/icrc1_ledger_setup.mdx). +To interact with the ICRC-1 and ICRC-2 endpoints, the Rust crate [icrc-ledger-types](https://crates.io/crates/icrc-ledger-types) can be used. +This is true for the ICP ledger as well as any other canister that supports ICRC-1 or any of the ICRC-1 extension standards (i.e., ICRC-2, ICRC-3,...). -### `icrc-ledger-types` Rust crate -To interact with ICRC-1 and ICRC-2 endpoints, the Rust crate [icrc-ledger-types](https://crates.io/crates/icrc-ledger-types) can be used. It provides data types, request types and response types as well as error types needed for interacting with ICRC-1 endpoints. -This is true for any canister that supports ICRC-1 or any of the ICRC-1 extension standards (i.e ICRC-2, ICRC-3,...). The crate can be installed with the command: ``` @@ -222,7 +94,4 @@ Or, it can be added to the `Cargo.toml` file: icrc-ledger-types = "0.1.1" ``` -View the documentation for [this crate](https://docs.rs/icrc-ledger-types/0.1.1/icrc_ledger_types/). - -## Interacting with an ICRC-1 ledger from your web application (`ledger-icrc-js`) -You will find specifications and examples on how to use the library to interact with ICRC-1 ledgers [here](https://github.com/dfinity/ic-js/tree/main/packages/ledger-icrc). +[View the documentation for this crate](https://docs.rs/icrc-ledger-types/0.1.1/icrc_ledger_types/).