Ledger Local Setup
If you are working in a local development environment, i.e with a local replica instead of the public Internet Computer, you can't access the ICP ledger. In order to test your application that integrates with the ICP ledger locally, you need to deploy a local ledger canister. However, this local ledger canister won't have the history and balances of the live ICP ledger. Follow the steps below to deploy your copy of the ledger canister to a local replica.
Get a pre-built Ledger canister module and Candid interface files.
export IC_VERSION=dd3a710b03bd3ae10368a91b255571d012d1ec2f
curl -o ledger.wasm.gz https://download.dfinity.systems/ic/${IC_VERSION}/canisters/ledger-canister_notify-method.wasm.gz
gunzip ledger.wasm.gz
curl -o ledger.private.did https://raw.githubusercontent.com/dfinity/ic/${IC_VERSION}/rs/rosetta-api/ledger.did
curl -o ledger.public.did https://raw.githubusercontent.com/dfinity/ic/${IC_VERSION}/rs/rosetta-api/ledger_canister/ledger.didnoteThe
IC_VERSION
variable is a commit hash from the http://github.com/dfinity/ic repository.Make sure you use a recent version of DFX. If you don’t have DFX installed, follow instructions on the Installing the SDK section to install it.
If you don’t have a DFX project yet, follow these instructions to create a new DFX project: dfx-new
Copy the file you obtained at the first step (
ledger.wasm
,ledger.private.did
,ledger.public.did
) into the root of your project.Add the following canister definition to the
dfx.json
file in your project:{
"canisters": {
"ledger": {
"type": "custom",
"wasm": "ledger.wasm",
"candid": "ledger.private.did"
}
}
}Configure your replica to run a
System
subnet. Modifydfx.json
to include:{
"defaults":{
"replica": {
"subnet_type":"system"
}
}
}Start a local replica.
dfx start --background
Create a new identity that will work as a minting account:
dfx identity new minter
dfx identity use minter
export MINT_ACC=$(dfx ledger account-id)Transfers from the minting account will create
Mint
transactions. Transfers to the minting account will createBurn
transactions.Switch back to your default identity and record its ledger account identifier.
dfx identity use default
export LEDGER_ACC=$(dfx ledger account-id)Deploy the ledger canister to your network.
dfx deploy ledger --argument '(record {minting_account = "'${MINT_ACC}'"; initial_values = vec { record { "'${LEDGER_ACC}'"; record { e8s=100_000_000_000 } }; }; send_whitelist = vec {}})'
If you want to setup the ledger in a way that matches the production deployment, you should deploy it with archiving enabled. In this setup, the ledger canister dynamically creates new canisters to store old blocks. We recommend using this setup if you are planning to exercise the interface for fetching blocks.
Obtain the principal of the identity you use for development. This principal will be the controller of archive canisters.
dfx identity use default
export ARCHIVE_CONTROLLER=$(dfx identity get-principal)Deploy the ledger canister with archiving options:
dfx deploy ledger --argument '(record {minting_account = "'${MINT_ACC}'"; initial_values = vec { record { "'${LEDGER_ACC}'"; record { e8s=100_000_000_000 } }; }; send_whitelist = vec {}; archive_options = opt record { trigger_threshold = 2000; num_blocks_to_archive = 1000; controller_id = principal "'${ARCHIVE_CONTROLLER}'" }})'
You may want to set
trigger_threshold
andnum_blocks_to_archive
options to low values (e.g., 10 and 5) to trigger archivation after only a few blocks.Update the canister definition in the
dfx.json
file to use the public Candid interface:{
"canisters": {
"ledger": {
"type": "custom",
"wasm": "ledger.wasm",
- "candid": "ledger.private.did"
+ "candid": "ledger.public.did"
}
}
}Update the canister definition in the
dfx.json
file to specify a remote id for the ledger. This will prevent dfx from deploying your own ledger in case you decide to deploy your project to the Internet Computer:"ledger": {
"type": "custom",
"candid": "ledger.public.did",
"wasm": "ledger.wasm",
"remote": {
"candid": "ledger.public.did",
"id": {
"ic": "ryjl3-tyaaa-aaaaa-aaaba-cai"
}
}
}Check that the Ledger canister is healthy. Execute the following command:
dfx canister call ledger account_balance '(record { account = '$(python3 -c 'print("vec{" + ";".join([str(b) for b in bytes.fromhex("'$LEDGER_ACC'")]) + "}")')' })'
The output should look like the following:
(record { e8s = 100_000_000_000 : nat64 })
Your local ICP ledger canister is up and running now. You can now deploy other canisters that need to communicate with the ledger canister.