Using the ICP ledger
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:
dfx ledger
: Thedfx
CLI command for interacting with the ICP ledger.dfx canister
: A generic canister call usingdfx
.- ledger-icp JavaScript library.
ic-cdk
: Inter-canister calls for the ICP ledger.
Interacting with the ICP ledger via dfx ledger
dfx
provides a convenience command to interact with the ICP ledger canister and related functionality: dfx ledger
.
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.
Currently, dfx ledger
only exposes a subset of the ICP ledger functionality, namely balance
and transfer
.
View the dfx ledger
documentation for all available dfx ledger
commands and flags.
Interacting with the ICP ledger via 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.
Use the following command syntax to interact with the ICP ledger via dfx canister
:
dfx canister call <canister-id> <method-name> <arguments>
For example, to fetch the token symbol of the ICP ledger, call the symbol
method:
dfx canister call ryjl3-tyaaa-aaaaa-aaaba-cai symbol '()'
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.
View a more detailed description of the data types used in these commands.
Interact with ICP ledger from your web application
In order to simplify working with the ICP ledger from JavaScript applications, you can use the ledger-icp JavaScript library.
To interact with the ICRC-1 endpoints of the ICP ledger, learn more about interacting with an ICRC-1 ledger.
Interacting with ICP from a canister (inter-canister calls via ic-cdk
)
View the [inter-canister call documentation] (/docs/developer-docs/backend/rust/intercanister) to see how you can call one canister from within another.
Here is an example of how to fetch the token name from the ICP ledger using Rust and the ic-cdk
library from within a canister:
// You will need the canister ID of the ICP ledger: `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();
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.
icrc-ledger-types
Rust crate
As explained in 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 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:
cargo add icrc-ledger-types
Or, it can be added to the Cargo.toml
file:
icrc-ledger-types = "0.1.1"
View the documentation for this crate.
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.
There are currently two main patterns to achieve this. Furthermore, there is a chartered working group 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 of the ledger.
The following diagram shows a simplified illustration of this pattern:
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.