From a181402f40d2c9dfe5569c33fc5dd1e519e28e47 Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Thu, 19 Mar 2026 12:48:41 +0100 Subject: [PATCH 1/5] docs: token standards reference --- docs/reference/token-standards.md | 344 +++++++++++++++++++++++++++++- 1 file changed, 334 insertions(+), 10 deletions(-) diff --git a/docs/reference/token-standards.md b/docs/reference/token-standards.md index fb79cab9..5b7a0482 100644 --- a/docs/reference/token-standards.md +++ b/docs/reference/token-standards.md @@ -6,16 +6,340 @@ sidebar: icskills: [icrc-ledger, wallet-integration] --- -TODO: Write content for this page. +ICP uses the ICRC standard family for tokens and token-related operations. ICRC stands for Internet Computer Request for Comments. Standards are proposed by the [ICRC working group](https://github.com/dfinity/ICRC), refined through community consensus, and adopted or rejected through NNS governance proposals. While ICRC standards can cover any topic (services, canister calls, authentication), this page focuses on the token and wallet signer standards. - -Reference for ICP token standards. Document ICRC-1 (fungible token transfers, balances, metadata), ICRC-2 (approve/transferFrom), ICRC-3 (transaction log/history), ICRC-7 (NFT standard), and related standards (ICRC-21/25/27/29/49 for wallet signers). Include standard interfaces, canonical ledger canister IDs, and compliance requirements. +## Standards overview - -- Portal: defi/tokens/token-standards files -- icskills: icrc-ledger, wallet-integration +| Standard | Purpose | Extends | Status | +|----------|---------|---------|--------| +| [ICRC-1](#icrc-1-fungible-tokens) | Fungible token base standard | -- | Adopted | +| [ICRC-2](#icrc-2-approve-and-transfer-from) | Approve and transfer-from for fungible tokens | ICRC-1 | Adopted | +| [ICRC-3](#icrc-3-transaction-log) | Transaction log and block archive | ICRC-1 | Adopted | +| [ICRC-7](#icrc-7-non-fungible-tokens) | Non-fungible token (NFT) base standard | -- | Adopted | +| [ICRC-37](#icrc-37-nft-approvals) | Approve and transfer-from for NFTs | ICRC-7 | Adopted | +| [ICRC-21](#wallet-signer-standards) | Canister call consent messages | -- | Adopted | +| [ICRC-25](#wallet-signer-standards) | Signer interaction (permissions) | -- | Adopted | +| [ICRC-27](#wallet-signer-standards) | Account discovery | -- | Adopted | +| [ICRC-29](#wallet-signer-standards) | Window PostMessage transport | -- | Adopted | +| [ICRC-49](#wallet-signer-standards) | Call canister via signer | -- | Adopted | - -- guides/defi/token-ledgers -- practical token operations -- guides/defi/wallet-integration -- ICRC signer standards -- guides/defi/chain-key-tokens -- ckBTC/ckETH are ICRC-1 tokens +## ICRC-1: Fungible tokens + +ICRC-1 is the base standard for fungible tokens on ICP. It defines transfer, balance, and metadata interfaces. The standard intentionally excludes certain features — transaction notifications, block structure, and pre-signed transactions — which are provided by extension standards (ICRC-2, ICRC-3). + +A ledger can report which extensions it supports through the `icrc1_supported_standards` endpoint. + +### Account model + +An ICRC-1 account consists of two parts: + +- **`owner`** — a `Principal` identifying the account holder +- **`subaccount`** — an optional 32-byte `Blob` that defaults to all zeros when omitted + +This means a single principal can control up to 2^256 distinct accounts by varying the subaccount. + +```candid +type Account = record { + owner : principal; + subaccount : opt blob; +}; +``` + +### Core methods + +| Method | Signature | Description | +|--------|-----------|-------------| +| `icrc1_transfer` | `(TransferArg) -> (variant { Ok : nat; Err : TransferError })` | Transfer tokens between accounts | +| `icrc1_balance_of` | `(Account) -> (nat) query` | Return the balance of an account | +| `icrc1_total_supply` | `() -> (nat) query` | Return the total token supply | +| `icrc1_metadata` | `() -> (vec record { text; Value }) query` | Return token metadata entries | +| `icrc1_name` | `() -> (text) query` | Return the token name | +| `icrc1_symbol` | `() -> (text) query` | Return the token symbol | +| `icrc1_decimals` | `() -> (nat8) query` | Return the number of decimals | +| `icrc1_fee` | `() -> (nat) query` | Return the default transfer fee | +| `icrc1_minting_account` | `() -> (opt Account) query` | Return the minting account | +| `icrc1_supported_standards` | `() -> (vec record { name : text; url : text }) query` | Return supported standard extensions | + +### Transfer arguments + +```candid +type TransferArg = record { + from_subaccount : opt blob; + to : Account; + amount : nat; + fee : opt nat; + memo : opt blob; + created_at_time : opt nat64; +}; +``` + +Setting `created_at_time` enables deduplication — the ledger rejects duplicate transfers submitted within a 24-hour window. Without it, identical transfers both execute. + +### Transfer errors + +```candid +type TransferError = variant { + BadFee : record { expected_fee : nat }; + BadBurn : record { min_burn_amount : nat }; + InsufficientFunds : record { balance : nat }; + TooOld; + CreatedInFuture : record { ledger_time : nat64 }; + Duplicate : record { duplicate_of : nat }; + TemporarilyUnavailable; + GenericError : record { error_code : nat; message : text }; +}; +``` + +### Metadata entries + +| Key | Type | Example | +|-----|------|---------| +| `icrc1:symbol` | `Text` | `"ICP"` | +| `icrc1:name` | `Text` | `"Internet Computer"` | +| `icrc1:decimals` | `Nat` | `8` | +| `icrc1:fee` | `Nat` | `10000` | + +### Canonical ledger canister IDs + +| Token | Ledger canister ID | Fee | Decimals | +|-------|-------------------|-----|----------| +| ICP | `ryjl3-tyaaa-aaaaa-aaaba-cai` | 10,000 e8s (0.0001 ICP) | 8 | +| ckBTC | `mxzaz-hqaaa-aaaar-qaada-cai` | 10 satoshis | 8 | +| ckETH | `ss2fx-dyaaa-aaaar-qacoq-cai` | 2,000,000,000,000 wei (0.000002 ETH) | 18 | + +Index canisters (for transaction history): + +| Token | Index canister ID | +|-------|------------------| +| ICP | `qhbym-qaaaa-aaaaa-aaafq-cai` | +| ckBTC | `n5wcd-faaaa-aaaar-qaaea-cai` | +| ckETH | `s3zol-vqaaa-aaaar-qacpa-cai` | + +[Read the full ICRC-1 standard](https://github.com/dfinity/ICRC-1/tree/main/standards/ICRC-1) + +## ICRC-2: Approve and transfer-from + +ICRC-2 extends ICRC-1 with an approve/transfer-from workflow, similar to ERC-20 allowances on Ethereum. An account owner delegates spending authority to a third party, who can then transfer tokens on the owner's behalf. + +The workflow has two steps: + +1. The account owner calls `icrc2_approve` to authorize a spender for up to X tokens. +2. The spender calls `icrc2_transfer_from` to move tokens from the owner's account. Multiple transfers are allowed as long as the total does not exceed the approved amount. + +### Methods + +| Method | Signature | Description | +|--------|-----------|-------------| +| `icrc2_approve` | `(ApproveArg) -> (variant { Ok : nat; Err : ApproveError })` | Authorize a spender for a token amount | +| `icrc2_transfer_from` | `(TransferFromArg) -> (variant { Ok : nat; Err : TransferFromError })` | Transfer tokens on behalf of the owner | +| `icrc2_allowance` | `(AllowanceArg) -> (Allowance) query` | Query the remaining allowance for a spender | + +### Approve arguments + +```candid +type ApproveArg = record { + from_subaccount : opt blob; + spender : Account; + amount : nat; + expected_allowance : opt nat; + expires_at : opt nat64; + fee : opt nat; + memo : opt blob; + created_at_time : opt nat64; +}; +``` + +The `expected_allowance` field provides protection against race conditions — the call fails if the current allowance does not match the expected value. The `expires_at` field sets a deadline (in nanoseconds since the Unix epoch) after which the approval is no longer valid. + +### Approve errors + +```candid +type ApproveError = variant { + BadFee : record { expected_fee : nat }; + InsufficientFunds : record { balance : nat }; + AllowanceChanged : record { current_allowance : nat }; + Expired : record { ledger_time : nat64 }; + TooOld; + CreatedInFuture : record { ledger_time : nat64 }; + Duplicate : record { duplicate_of : nat }; + TemporarilyUnavailable; + GenericError : record { error_code : nat; message : text }; +}; +``` + +### Transfer-from arguments + +```candid +type TransferFromArg = record { + spender_subaccount : opt blob; + from : Account; + to : Account; + amount : nat; + fee : opt nat; + memo : opt blob; + created_at_time : opt nat64; +}; +``` + +### Transfer-from errors + +```candid +type TransferFromError = variant { + BadFee : record { expected_fee : nat }; + BadBurn : record { min_burn_amount : nat }; + InsufficientFunds : record { balance : nat }; + InsufficientAllowance : record { allowance : nat }; + TooOld; + CreatedInFuture : record { ledger_time : nat64 }; + Duplicate : record { duplicate_of : nat }; + TemporarilyUnavailable; + GenericError : record { error_code : nat; message : text }; +}; +``` + +### Allowance query + +```candid +type AllowanceArg = record { + account : Account; + spender : Account; +}; + +type Allowance = record { + allowance : nat; + expires_at : opt nat64; +}; +``` + +### Common use cases + +- **DEX integrations** — a DEX canister is approved to pull tokens from a user's account during a swap. +- **Subscription payments** — a service canister is approved for recurring token withdrawals. +- **Escrow** — an intermediary canister holds approval to release tokens when conditions are met. + +ICP, ckBTC, and ckETH all implement ICRC-2. + +[Read the full ICRC-2 standard](https://github.com/dfinity/ICRC-1/tree/main/standards/ICRC-2) + +## ICRC-3: Transaction log + +ICRC-3 extends ICRC-1 with a standardized transaction log interface. It defines how ledgers expose their block history, enabling clients and index canisters to retrieve and verify transaction records. + +### Methods + +| Method | Signature | Description | +|--------|-----------|-------------| +| `icrc3_get_transactions` | `(GetTransactionsRequest) -> (GetTransactionsResponse) query` | Retrieve transactions from the ledger or its archive canisters | +| `icrc3_get_blocks` | `(vec GetBlocksRequest) -> (GetBlocksResult) query` | Retrieve blocks by index range | +| `icrc3_get_tip_certificate` | `() -> (opt DataCertificate) query` | Return a certificate for the last block hash | +| `icrc3_supported_block_types` | `() -> (vec BlockType) query` | List the block types the ledger produces | + +### Block schema + +ICRC-3 blocks use a generic value representation. Each block contains: + +- **`phash`** — hash of the previous block (absent for the genesis block) +- **`btype`** — block type string (e.g., `"1xfer"` for ICRC-1 transfers, `"2approve"` for ICRC-2 approvals) +- **`ts`** — timestamp in nanoseconds +- **Transaction-specific fields** — vary by block type (e.g., `from`, `to`, `amt` for transfers) + +Standard block types include: + +| Block type | Standard | Description | +|------------|----------|-------------| +| `1xfer` | ICRC-1 | Transfer | +| `1burn` | ICRC-1 | Burn | +| `1mint` | ICRC-1 | Mint | +| `2approve` | ICRC-2 | Approval | +| `2xfer` | ICRC-2 | Transfer-from | + +[Read the full ICRC-3 standard](https://github.com/dfinity/ICRC-1/tree/main/standards/ICRC-3) + +## ICRC-7: Non-fungible tokens + +ICRC-7 defines the base standard for non-fungible tokens (NFTs) on ICP. It can be used to create and manage NFT collections. Like ICRC-1 for fungible tokens, ICRC-7 is intentionally minimal and excludes transaction notifications, block structure, and pre-signed transactions — these can be added through extensions. + +ICRC-7 uses the same account model as ICRC-1 (principal + optional 32-byte subaccount). + +### Core methods + +| Method | Signature | Description | +|--------|-----------|-------------| +| `icrc7_collection_metadata` | `() -> (vec record { text; Value }) query` | Return collection metadata | +| `icrc7_name` | `() -> (text) query` | Return collection name | +| `icrc7_symbol` | `() -> (text) query` | Return collection symbol | +| `icrc7_total_supply` | `() -> (nat) query` | Return total number of tokens | +| `icrc7_supply_cap` | `() -> (opt nat) query` | Return maximum supply (if set) | +| `icrc7_token_metadata` | `(vec nat) -> (vec opt vec record { text; Value }) query` | Return metadata for specific token IDs | +| `icrc7_owner_of` | `(vec nat) -> (vec opt Account) query` | Return the owner of specific token IDs | +| `icrc7_balance_of` | `(vec Account) -> (vec nat) query` | Return the number of tokens owned by each account | +| `icrc7_tokens` | `(opt nat, opt nat) -> (vec nat) query` | List token IDs with pagination | +| `icrc7_tokens_of` | `(Account, opt nat, opt nat) -> (vec nat) query` | List token IDs owned by an account | +| `icrc7_transfer` | `(vec TransferArg) -> (vec opt TransferResult)` | Batch transfer tokens | + +### Collection metadata + +| Key | Type | Description | +|-----|------|-------------| +| `icrc7:symbol` | `Text` | Token symbol | +| `icrc7:name` | `Text` | Token name | +| `icrc7:description` | `Text` | Collection description | +| `icrc7:logo` | `Text` | URL of the collection logo | +| `icrc7:total_supply` | `Nat` | Current number of tokens | +| `icrc7:supply_cap` | `Nat` | Maximum number of tokens (optional) | + +[Read the full ICRC-7 standard](https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-7/ICRC-7.md) + +## ICRC-37: NFT approvals + +ICRC-37 extends ICRC-7 with an approval workflow for NFTs, analogous to how ICRC-2 extends ICRC-1 for fungible tokens. It adds support for creating approvals, revoking approvals, querying approval state, and executing transfers based on approvals. + +A ledger that implements ICRC-37 must also implement all ICRC-7 methods. Support for ICRC-37 is optional for ICRC-7 ledgers. + +### Methods + +| Method | Signature | Description | +|--------|-----------|-------------| +| `icrc37_approve_tokens` | `(vec ApproveTokenArg) -> (vec opt ApproveTokenResult)` | Approve a spender for specific token IDs | +| `icrc37_approve_collection` | `(vec ApproveCollectionArg) -> (vec opt ApproveCollectionResult)` | Approve a spender for all tokens in the collection | +| `icrc37_revoke_token_approvals` | `(vec RevokeTokenApprovalArg) -> (vec opt RevokeTokenApprovalResult)` | Revoke approvals for specific tokens | +| `icrc37_revoke_collection_approvals` | `(vec RevokeCollectionApprovalArg) -> (vec opt RevokeCollectionApprovalResult)` | Revoke collection-level approvals | +| `icrc37_is_approved` | `(vec IsApprovedArg) -> (vec bool) query` | Check if a spender is approved for specific tokens | +| `icrc37_get_token_approvals` | `(nat, opt nat, opt nat) -> (vec TokenApproval) query` | List approvals for a token ID | +| `icrc37_get_collection_approvals` | `(Account, opt nat, opt nat) -> (vec CollectionApproval) query` | List collection-level approvals | +| `icrc37_transfer_from` | `(vec TransferFromArg) -> (vec opt TransferFromResult)` | Transfer tokens using an approval | + +### Additional metadata + +| Key | Type | Description | +|-----|------|-------------| +| `icrc37:max_approvals_per_token_or_collection` | `Nat` | Maximum active approvals allowed per principal or token | +| `icrc37:max_revoke_approvals` | `Nat` | Maximum approvals that can be revoked in one call (optional) | + +[Read the full ICRC-37 standard](https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-37/ICRC-37.md) + +## Wallet signer standards + +The ICRC signer standards define how wallets interact with dApps on ICP. They use a popup-based model where every action requires explicit user approval, communicated via JSON-RPC 2.0 over `window.postMessage`. + +| Standard | Purpose | +|----------|---------| +| **ICRC-21** | Canister call consent messages — enables canisters to provide human-readable descriptions of what a call will do, displayed to the user before signing | +| **ICRC-25** | Signer interaction standard — defines the permission lifecycle (`granted`, `denied`, `ask_on_use`) for signer methods | +| **ICRC-27** | Account discovery — allows dApps to request the list of accounts available in the wallet | +| **ICRC-29** | Window PostMessage transport — defines the communication channel between dApp and signer using `window.postMessage` | +| **ICRC-49** | Call canister — allows dApps to request the signer to execute a canister call on behalf of the user | + +These standards are distinct from delegation-based authentication (such as Internet Identity). The signer model requires per-action user approval and does not create sessions or delegated identities. + +For implementation details and code examples, see the [wallet integration guide](../guides/defi/wallet-integration.md). + +## Next steps + +- [Token ledgers guide](../guides/defi/token-ledgers.md) — deploy and interact with ICRC-1/ICRC-2 ledgers +- [Chain-key tokens guide](../guides/defi/chain-key-tokens.md) — work with ckBTC, ckETH, and other chain-key tokens +- [Wallet integration guide](../guides/defi/wallet-integration.md) — integrate wallet signer standards into your dApp +- [ICRC-1 standard specification](https://github.com/dfinity/ICRC-1/tree/main/standards/ICRC-1) — full specification on GitHub +- [ICRC-7 standard specification](https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-7/ICRC-7.md) — full NFT specification on GitHub + + From 06cd0ec845172b46530f0a8705dfeafbfb567870 Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Thu, 19 Mar 2026 12:56:28 +0100 Subject: [PATCH 2/5] docs: add icskills to Upstream comment in token standards --- docs/reference/token-standards.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/token-standards.md b/docs/reference/token-standards.md index 5b7a0482..97ae5f32 100644 --- a/docs/reference/token-standards.md +++ b/docs/reference/token-standards.md @@ -342,4 +342,4 @@ For implementation details and code examples, see the [wallet integration guide] - [ICRC-1 standard specification](https://github.com/dfinity/ICRC-1/tree/main/standards/ICRC-1) — full specification on GitHub - [ICRC-7 standard specification](https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-7/ICRC-7.md) — full NFT specification on GitHub - + From 92cee23a496ce757f0009f908a2a392b7dff606a Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Thu, 19 Mar 2026 13:54:51 +0100 Subject: [PATCH 3/5] docs: address review feedback for token standards reference MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove non-existent icrc3_get_transactions method - Add missing icrc3_get_archives method - Add archive model explanation - Add proposed block types table (ICRC-122/123/124/152/153/154) - Note that anyone can define custom block types - Rename section to "Canonical ledger canister IDs" → "Common ICRC-1 ledgers" with honest framing about DFINITY-maintained vs ecosystem tokens - Add link to ICP Dashboard token registry - Add dynamic fee note with icrc1_fee reference - Reorder opening paragraph to lead with developer context --- docs/reference/_attachments/ic.did | 678 +++++++++++++++++++++++++++++ docs/reference/token-standards.md | 45 +- 2 files changed, 713 insertions(+), 10 deletions(-) create mode 100644 docs/reference/_attachments/ic.did diff --git a/docs/reference/_attachments/ic.did b/docs/reference/_attachments/ic.did new file mode 100644 index 00000000..f412d699 --- /dev/null +++ b/docs/reference/_attachments/ic.did @@ -0,0 +1,678 @@ +type canister_id = principal; +type wasm_module = blob; +type snapshot_id = blob; + +type log_visibility = variant { + controllers; + public; + allowed_viewers : vec principal; +}; + +type environment_variable = record { + name: text; + value: text; +}; + +type canister_settings = record { + controllers : opt vec principal; + compute_allocation : opt nat; + memory_allocation : opt nat; + freezing_threshold : opt nat; + reserved_cycles_limit : opt nat; + log_visibility : opt log_visibility; + wasm_memory_limit : opt nat; + wasm_memory_threshold : opt nat; + environment_variables : opt vec environment_variable; +}; + +type definite_canister_settings = record { + controllers : vec principal; + compute_allocation : nat; + memory_allocation : nat; + freezing_threshold : nat; + reserved_cycles_limit : nat; + log_visibility : log_visibility; + wasm_memory_limit : nat; + wasm_memory_threshold : nat; + environment_variables : vec environment_variable; +}; + +type change_origin = variant { + from_user : record { + user_id : principal; + }; + from_canister : record { + canister_id : canister_id; + canister_version : opt nat64; + }; +}; + +type change_details = variant { + creation : record { + controllers : vec principal; + environment_variables_hash : opt blob; + }; + code_uninstall; + code_deployment : record { + mode : variant { install; reinstall; upgrade }; + module_hash : blob; + }; + load_snapshot : record { + from_canister_id : opt principal; + snapshot_id : snapshot_id; + canister_version : nat64; + taken_at_timestamp : nat64; + source : variant { + taken_from_canister : reserved; + metadata_upload : reserved; + }; + }; + controllers_change : record { + controllers : vec principal; + }; + rename_canister : record { + canister_id : canister_id; + total_num_changes : nat64; + rename_to : record { + canister_id : canister_id; + version : nat64; + total_num_changes : nat64; + }; + requested_by : principal; + }; +}; + +type change = record { + timestamp_nanos : nat64; + canister_version : nat64; + origin : change_origin; + details : change_details; +}; + +type chunk_hash = record { + hash : blob; +}; + +type http_header = record { + name : text; + value : text; +}; + +type http_request_result = record { + status : nat; + headers : vec http_header; + body : blob; +}; + +type ecdsa_curve = variant { + secp256k1; +}; + +type vetkd_curve = variant { + bls12_381_g2; +}; + +type schnorr_algorithm = variant { + bip340secp256k1; + ed25519; +}; + +type satoshi = nat64; + +type bitcoin_network = variant { + mainnet; + testnet; +}; + +type bitcoin_address = text; + +type bitcoin_block_hash = blob; + +type bitcoin_block_header = blob; + +type millisatoshi_per_byte = nat64; + +type bitcoin_block_height = nat32; + +type outpoint = record { + txid : blob; + vout : nat32; +}; + +type utxo = record { + outpoint : outpoint; + value : satoshi; + height : nat32; +}; + +type bitcoin_get_utxos_args = record { + address : bitcoin_address; + network : bitcoin_network; + filter : opt variant { + min_confirmations : nat32; + page : blob; + }; +}; + +type bitcoin_get_utxos_result = record { + utxos : vec utxo; + tip_block_hash : bitcoin_block_hash; + tip_height : bitcoin_block_height; + next_page : opt blob; +}; + +type bitcoin_get_balance_args = record { + address : bitcoin_address; + network : bitcoin_network; + min_confirmations : opt nat32; +}; + +type bitcoin_get_balance_result = satoshi; + +type bitcoin_get_current_fee_percentiles_args = record { + network : bitcoin_network; +}; + +type bitcoin_get_current_fee_percentiles_result = vec millisatoshi_per_byte; + +type bitcoin_send_transaction_args = record { + transaction : blob; + network : bitcoin_network; +}; + +type bitcoin_get_block_headers_args = record { + start_height : bitcoin_block_height; + end_height : opt bitcoin_block_height; + network : bitcoin_network; +}; + +type bitcoin_get_block_headers_result = record { + tip_height : bitcoin_block_height; + block_headers : vec bitcoin_block_header; +}; + +type node_metrics = record { + node_id : principal; + num_blocks_proposed_total : nat64; + num_block_failures_total : nat64; +}; + +type create_canister_args = record { + settings : opt canister_settings; + sender_canister_version : opt nat64; +}; + +type create_canister_result = record { + canister_id : canister_id; +}; + +type update_settings_args = record { + canister_id : canister_id; + settings : canister_settings; + sender_canister_version : opt nat64; +}; + +type upload_chunk_args = record { + canister_id : canister_id; + chunk : blob; +}; + +type clear_chunk_store_args = record { + canister_id : canister_id; +}; + +type stored_chunks_args = record { + canister_id : canister_id; +}; + +type canister_install_mode = variant { + install; + reinstall; + upgrade : opt record { + skip_pre_upgrade : opt bool; + wasm_memory_persistence : opt variant { + keep; + replace; + }; + }; +}; + +type install_code_args = record { + mode : canister_install_mode; + canister_id : canister_id; + wasm_module : wasm_module; + arg : blob; + sender_canister_version : opt nat64; +}; + +type install_chunked_code_args = record { + mode : canister_install_mode; + target_canister : canister_id; + store_canister : opt canister_id; + chunk_hashes_list : vec chunk_hash; + wasm_module_hash : blob; + arg : blob; + sender_canister_version : opt nat64; +}; + +type uninstall_code_args = record { + canister_id : canister_id; + sender_canister_version : opt nat64; +}; + +type start_canister_args = record { + canister_id : canister_id; +}; + +type stop_canister_args = record { + canister_id : canister_id; +}; + +type canister_status_args = record { + canister_id : canister_id; +}; + +type canister_status_result = record { + status : variant { + running; + stopping; + stopped; + }; + ready_for_migration : bool; + version : nat64; + settings : definite_canister_settings; + module_hash : opt blob; + memory_size : nat; + memory_metrics : record { + wasm_memory_size : nat; + stable_memory_size : nat; + global_memory_size : nat; + wasm_binary_size : nat; + custom_sections_size : nat; + canister_history_size : nat; + wasm_chunk_store_size : nat; + snapshots_size : nat; + }; + cycles : nat; + reserved_cycles : nat; + idle_cycles_burned_per_day : nat; + query_stats : record { + num_calls_total : nat; + num_instructions_total : nat; + request_payload_bytes_total : nat; + response_payload_bytes_total : nat; + }; +}; + +type canister_info_args = record { + canister_id : canister_id; + num_requested_changes : opt nat64; +}; + +type canister_info_result = record { + total_num_changes : nat64; + recent_changes : vec change; + module_hash : opt blob; + controllers : vec principal; +}; + +type canister_metadata_args = record { + canister_id : canister_id; + name : text; +}; + +type canister_metadata_result = record { + value : blob; +}; + +type delete_canister_args = record { + canister_id : canister_id; +}; + +type deposit_cycles_args = record { + canister_id : canister_id; +}; + +type http_request_args = record { + url : text; + max_response_bytes : opt nat64; + method : variant { get; head; post; put; delete }; + headers : vec http_header; + body : opt blob; + transform : opt record { + function : func(record { response : http_request_result; context : blob }) -> (http_request_result) query; + context : blob; + }; + is_replicated : opt bool; +}; + +type ecdsa_public_key_args = record { + canister_id : opt canister_id; + derivation_path : vec blob; + key_id : record { curve : ecdsa_curve; name : text }; +}; + +type ecdsa_public_key_result = record { + public_key : blob; + chain_code : blob; +}; + +type sign_with_ecdsa_args = record { + message_hash : blob; + derivation_path : vec blob; + key_id : record { curve : ecdsa_curve; name : text }; +}; + +type sign_with_ecdsa_result = record { + signature : blob; +}; + +type schnorr_public_key_args = record { + canister_id : opt canister_id; + derivation_path : vec blob; + key_id : record { algorithm : schnorr_algorithm; name : text }; +}; + +type schnorr_public_key_result = record { + public_key : blob; + chain_code : blob; +}; + +type schnorr_aux = variant { + bip341 : record { + merkle_root_hash : blob; + }; +}; + +type sign_with_schnorr_args = record { + message : blob; + derivation_path : vec blob; + key_id : record { algorithm : schnorr_algorithm; name : text }; + aux : opt schnorr_aux; +}; + +type sign_with_schnorr_result = record { + signature : blob; +}; + +type vetkd_public_key_args = record { + canister_id : opt canister_id; + context : blob; + key_id : record { curve : vetkd_curve; name : text }; +}; + +type vetkd_public_key_result = record { + public_key : blob; +}; + +type vetkd_derive_key_args = record { + input : blob; + context : blob; + transport_public_key : blob; + key_id : record { curve : vetkd_curve; name : text }; +}; + +type vetkd_derive_key_result = record { + encrypted_key : blob; +}; + +type node_metrics_history_args = record { + subnet_id : principal; + start_at_timestamp_nanos : nat64; +}; + +type node_metrics_history_result = vec record { + timestamp_nanos : nat64; + node_metrics : vec node_metrics; +}; + +type subnet_info_args = record { + subnet_id : principal; +}; + +type subnet_info_result = record { + replica_version : text; + registry_version : nat64; +}; + +type provisional_create_canister_with_cycles_args = record { + amount : opt nat; + settings : opt canister_settings; + specified_id : opt canister_id; + sender_canister_version : opt nat64; +}; + +type provisional_create_canister_with_cycles_result = record { + canister_id : canister_id; +}; + +type provisional_top_up_canister_args = record { + canister_id : canister_id; + amount : nat; +}; + +type raw_rand_result = blob; + +type stored_chunks_result = vec chunk_hash; + +type upload_chunk_result = chunk_hash; + +type snapshot = record { + id : snapshot_id; + taken_at_timestamp : nat64; + total_size : nat64; +}; + +type take_canister_snapshot_args = record { + canister_id : canister_id; + replace_snapshot : opt snapshot_id; + uninstall_code : opt bool; + sender_canister_version : opt nat64; +}; + +type take_canister_snapshot_result = snapshot; + +type load_canister_snapshot_args = record { + canister_id : canister_id; + snapshot_id : snapshot_id; + sender_canister_version : opt nat64; +}; + +type list_canister_snapshots_args = record { + canister_id : canister_id; +}; + +type list_canister_snapshots_result = vec snapshot; + +type delete_canister_snapshot_args = record { + canister_id : canister_id; + snapshot_id : snapshot_id; +}; + +type fetch_canister_logs_args = record { + canister_id : canister_id; +}; + +type canister_log_record = record { + idx : nat64; + timestamp_nanos : nat64; + content : blob; +}; + +type fetch_canister_logs_result = record { + canister_log_records : vec canister_log_record; +}; + +type read_canister_snapshot_metadata_args = record { + canister_id : canister_id; + snapshot_id : snapshot_id; +}; + +type read_canister_snapshot_metadata_response = record { + source : variant { + taken_from_canister: reserved; + metadata_upload : reserved; + }; + taken_at_timestamp : nat64; + wasm_module_size : nat64; + globals : vec variant { + i32 : int32; + i64 : int64; + f32 : float32; + f64 : float64; + v128 : nat; + }; + wasm_memory_size : nat64; + stable_memory_size : nat64; + wasm_chunk_store : vec record { + hash : blob; + }; + canister_version : nat64; + certified_data : blob; + global_timer : opt variant { + inactive; + active : nat64; + }; + on_low_wasm_memory_hook_status : opt variant { + condition_not_satisfied; + ready; + executed; + }; +}; + +type read_canister_snapshot_data_args = record { + canister_id : canister_id; + snapshot_id : snapshot_id; + kind : variant { + wasm_module : record { + offset : nat64; + size : nat64; + }; + wasm_memory : record { + offset : nat64; + size : nat64; + }; + stable_memory : record { + offset : nat64; + size : nat64; + }; + wasm_chunk : record { + hash : blob; + }; + }; +}; + +type read_canister_snapshot_data_response = record { + chunk : blob; +}; + +type upload_canister_snapshot_metadata_args = record { + canister_id : canister_id; + replace_snapshot : opt snapshot_id; + wasm_module_size : nat64; + globals : vec variant { + i32 : int32; + i64 : int64; + f32 : float32; + f64 : float64; + v128 : nat; + }; + wasm_memory_size : nat64; + stable_memory_size : nat64; + certified_data : blob; + global_timer : opt variant { + inactive; + active : nat64; + }; + on_low_wasm_memory_hook_status : opt variant { + condition_not_satisfied; + ready; + executed; + }; +}; + +type upload_canister_snapshot_metadata_response = record { + snapshot_id : snapshot_id; +}; + +type upload_canister_snapshot_data_args = record { + canister_id : canister_id; + snapshot_id : snapshot_id; + kind : variant { + wasm_module : record { + offset : nat64; + }; + wasm_memory : record { + offset : nat64; + }; + stable_memory : record { + offset : nat64; + }; + wasm_chunk; + }; + chunk : blob; +}; + +service ic : { + create_canister : (create_canister_args) -> (create_canister_result); + update_settings : (update_settings_args) -> (); + upload_chunk : (upload_chunk_args) -> (upload_chunk_result); + clear_chunk_store : (clear_chunk_store_args) -> (); + stored_chunks : (stored_chunks_args) -> (stored_chunks_result); + install_code : (install_code_args) -> (); + install_chunked_code : (install_chunked_code_args) -> (); + uninstall_code : (uninstall_code_args) -> (); + start_canister : (start_canister_args) -> (); + stop_canister : (stop_canister_args) -> (); + canister_status : (canister_status_args) -> (canister_status_result) query; + delete_canister : (delete_canister_args) -> (); + deposit_cycles : (deposit_cycles_args) -> (); + raw_rand : () -> (raw_rand_result); + http_request : (http_request_args) -> (http_request_result); + + // Public canister data + canister_info : (canister_info_args) -> (canister_info_result); + canister_metadata : (canister_metadata_args) -> (canister_metadata_result); + + // Threshold ECDSA signature + ecdsa_public_key : (ecdsa_public_key_args) -> (ecdsa_public_key_result); + sign_with_ecdsa : (sign_with_ecdsa_args) -> (sign_with_ecdsa_result); + + // Threshold Schnorr signature + schnorr_public_key : (schnorr_public_key_args) -> (schnorr_public_key_result); + sign_with_schnorr : (sign_with_schnorr_args) -> (sign_with_schnorr_result); + + // Threshold key derivation + vetkd_public_key : (vetkd_public_key_args) -> (vetkd_public_key_result); + vetkd_derive_key : (vetkd_derive_key_args) -> (vetkd_derive_key_result); + + // bitcoin interface + bitcoin_get_balance : (bitcoin_get_balance_args) -> (bitcoin_get_balance_result); + bitcoin_get_utxos : (bitcoin_get_utxos_args) -> (bitcoin_get_utxos_result); + bitcoin_send_transaction : (bitcoin_send_transaction_args) -> (); + bitcoin_get_current_fee_percentiles : (bitcoin_get_current_fee_percentiles_args) -> (bitcoin_get_current_fee_percentiles_result); + bitcoin_get_block_headers : (bitcoin_get_block_headers_args) -> (bitcoin_get_block_headers_result); + + // metrics interface + node_metrics_history : (node_metrics_history_args) -> (node_metrics_history_result); + + // subnet info + subnet_info : (subnet_info_args) -> (subnet_info_result); + + // provisional interfaces for the pre-ledger world + provisional_create_canister_with_cycles : (provisional_create_canister_with_cycles_args) -> (provisional_create_canister_with_cycles_result); + provisional_top_up_canister : (provisional_top_up_canister_args) -> (); + + // Canister snapshots + take_canister_snapshot : (take_canister_snapshot_args) -> (take_canister_snapshot_result); + load_canister_snapshot : (load_canister_snapshot_args) -> (); + read_canister_snapshot_metadata : (read_canister_snapshot_metadata_args) -> (read_canister_snapshot_metadata_response); + read_canister_snapshot_data : (read_canister_snapshot_data_args) -> (read_canister_snapshot_data_response); + upload_canister_snapshot_metadata : (upload_canister_snapshot_metadata_args) -> (upload_canister_snapshot_metadata_response); + upload_canister_snapshot_data : (upload_canister_snapshot_data_args) -> (); + list_canister_snapshots : (list_canister_snapshots_args) -> (list_canister_snapshots_result); + delete_canister_snapshot : (delete_canister_snapshot_args) -> (); + + // canister logging + fetch_canister_logs : (fetch_canister_logs_args) -> (fetch_canister_logs_result) query; +}; diff --git a/docs/reference/token-standards.md b/docs/reference/token-standards.md index 97ae5f32..64d16dbd 100644 --- a/docs/reference/token-standards.md +++ b/docs/reference/token-standards.md @@ -6,7 +6,9 @@ sidebar: icskills: [icrc-ledger, wallet-integration] --- -ICP uses the ICRC standard family for tokens and token-related operations. ICRC stands for Internet Computer Request for Comments. Standards are proposed by the [ICRC working group](https://github.com/dfinity/ICRC), refined through community consensus, and adopted or rejected through NNS governance proposals. While ICRC standards can cover any topic (services, canister calls, authentication), this page focuses on the token and wallet signer standards. +ICP uses the ICRC standard family for tokens and token-related operations. This page covers the token standards (ICRC-1 through ICRC-37) and wallet signer standards (ICRC-21 through ICRC-49) that developers need to build DeFi applications, wallets, and token integrations. + +ICRC stands for Internet Computer Request for Comments. Standards are proposed by the [ICRC working group](https://github.com/dfinity/ICRC), refined through community consensus, and adopted or rejected through NNS governance proposals. ## Standards overview @@ -99,14 +101,18 @@ type TransferError = variant { | `icrc1:decimals` | `Nat` | `8` | | `icrc1:fee` | `Nat` | `10000` | -### Canonical ledger canister IDs +### Common ICRC-1 ledgers + +The following are DFINITY-maintained ledgers. Many other ICRC-1 tokens exist on ICP — see the [ICP Dashboard token list](https://dashboard.internetcomputer.org/tokens) for a comprehensive registry. Anyone can deploy an ICRC-1 compliant ledger. -| Token | Ledger canister ID | Fee | Decimals | -|-------|-------------------|-----|----------| +| Token | Ledger canister ID | Default fee | Decimals | +|-------|-------------------|-------------|----------| | ICP | `ryjl3-tyaaa-aaaaa-aaaba-cai` | 10,000 e8s (0.0001 ICP) | 8 | | ckBTC | `mxzaz-hqaaa-aaaar-qaada-cai` | 10 satoshis | 8 | | ckETH | `ss2fx-dyaaa-aaaar-qacoq-cai` | 2,000,000,000,000 wei (0.000002 ETH) | 18 | +> Fees can change through governance proposals. Always call `icrc1_fee` to get the current fee rather than hardcoding these values. + Index canisters (for transaction history): | Token | Index canister ID | @@ -225,25 +231,31 @@ ICP, ckBTC, and ckETH all implement ICRC-2. ICRC-3 extends ICRC-1 with a standardized transaction log interface. It defines how ledgers expose their block history, enabling clients and index canisters to retrieve and verify transaction records. +### Archive model + +Ledgers store recent blocks directly and move older blocks to **archive canisters** to manage memory. When fetching blocks, `icrc3_get_blocks` returns blocks the ledger holds directly plus callbacks to fetch archived blocks from the appropriate archive canister. Use `icrc3_get_archives` to discover all archive canisters and the block ranges they hold. + ### Methods | Method | Signature | Description | |--------|-----------|-------------| -| `icrc3_get_transactions` | `(GetTransactionsRequest) -> (GetTransactionsResponse) query` | Retrieve transactions from the ledger or its archive canisters | -| `icrc3_get_blocks` | `(vec GetBlocksRequest) -> (GetBlocksResult) query` | Retrieve blocks by index range | -| `icrc3_get_tip_certificate` | `() -> (opt DataCertificate) query` | Return a certificate for the last block hash | -| `icrc3_supported_block_types` | `() -> (vec BlockType) query` | List the block types the ledger produces | +| `icrc3_get_blocks` | `(vec record { start : nat; length : nat }) -> (GetBlocksResult) query` | Retrieve blocks by index range; returns callbacks for archived blocks | +| `icrc3_get_archives` | `(GetArchivesArgs) -> (vec record { canister_id; start; end }) query` | List archive canisters and the block ranges they hold | +| `icrc3_get_tip_certificate` | `() -> (opt DataCertificate) query` | Return a certificate for the last block hash and index | +| `icrc3_supported_block_types` | `() -> (vec record { block_type : text; url : text }) query` | List the block types the ledger produces | ### Block schema -ICRC-3 blocks use a generic value representation. Each block contains: +ICRC-3 blocks use a generic `Value` representation that preserves all data for verification. Each block contains: - **`phash`** — hash of the previous block (absent for the genesis block) - **`btype`** — block type string (e.g., `"1xfer"` for ICRC-1 transfers, `"2approve"` for ICRC-2 approvals) - **`ts`** — timestamp in nanoseconds - **Transaction-specific fields** — vary by block type (e.g., `from`, `to`, `amt` for transfers) -Standard block types include: +### Adopted block types + +Block type identifiers follow the naming convention `` (e.g., `1xfer` for ICRC-1 transfer). Anyone can define new block types for custom standards following this convention. | Block type | Standard | Description | |------------|----------|-------------| @@ -253,6 +265,19 @@ Standard block types include: | `2approve` | ICRC-2 | Approval | | `2xfer` | ICRC-2 | Transfer-from | +### Proposed block types + +The following block types are currently in the ICRC proposal process and not yet adopted: + +| Block type(s) | Proposal | Status | +|---------------|----------|--------| +| ICRC-122 | [Ledger notification blocks](https://github.com/dfinity/ICRC/pull/125) | Proposed | +| ICRC-123 | [Batch call blocks](https://github.com/dfinity/ICRC/pull/134) | Proposed | +| ICRC-124 | [Canister management blocks](https://github.com/dfinity/ICRC/pull/135) | Proposed | +| ICRC-152 | [RWA compliance blocks](https://github.com/dfinity/ICRC/pull/156) | Proposed | +| ICRC-153 | [RWA regulatory blocks](https://github.com/dfinity/ICRC/pull/157) | Proposed | +| ICRC-154 | [RWA lifecycle blocks](https://github.com/dfinity/ICRC/pull/158) | Proposed | + [Read the full ICRC-3 standard](https://github.com/dfinity/ICRC-1/tree/main/standards/ICRC-3) ## ICRC-7: Non-fungible tokens From b3bc67bd5dd39347bc8093c77c8712ec2f6e8f1e Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Thu, 19 Mar 2026 13:55:39 +0100 Subject: [PATCH 4/5] fix: remove ic.did accidentally included from PR #32 branch --- docs/reference/_attachments/ic.did | 678 ----------------------------- 1 file changed, 678 deletions(-) delete mode 100644 docs/reference/_attachments/ic.did diff --git a/docs/reference/_attachments/ic.did b/docs/reference/_attachments/ic.did deleted file mode 100644 index f412d699..00000000 --- a/docs/reference/_attachments/ic.did +++ /dev/null @@ -1,678 +0,0 @@ -type canister_id = principal; -type wasm_module = blob; -type snapshot_id = blob; - -type log_visibility = variant { - controllers; - public; - allowed_viewers : vec principal; -}; - -type environment_variable = record { - name: text; - value: text; -}; - -type canister_settings = record { - controllers : opt vec principal; - compute_allocation : opt nat; - memory_allocation : opt nat; - freezing_threshold : opt nat; - reserved_cycles_limit : opt nat; - log_visibility : opt log_visibility; - wasm_memory_limit : opt nat; - wasm_memory_threshold : opt nat; - environment_variables : opt vec environment_variable; -}; - -type definite_canister_settings = record { - controllers : vec principal; - compute_allocation : nat; - memory_allocation : nat; - freezing_threshold : nat; - reserved_cycles_limit : nat; - log_visibility : log_visibility; - wasm_memory_limit : nat; - wasm_memory_threshold : nat; - environment_variables : vec environment_variable; -}; - -type change_origin = variant { - from_user : record { - user_id : principal; - }; - from_canister : record { - canister_id : canister_id; - canister_version : opt nat64; - }; -}; - -type change_details = variant { - creation : record { - controllers : vec principal; - environment_variables_hash : opt blob; - }; - code_uninstall; - code_deployment : record { - mode : variant { install; reinstall; upgrade }; - module_hash : blob; - }; - load_snapshot : record { - from_canister_id : opt principal; - snapshot_id : snapshot_id; - canister_version : nat64; - taken_at_timestamp : nat64; - source : variant { - taken_from_canister : reserved; - metadata_upload : reserved; - }; - }; - controllers_change : record { - controllers : vec principal; - }; - rename_canister : record { - canister_id : canister_id; - total_num_changes : nat64; - rename_to : record { - canister_id : canister_id; - version : nat64; - total_num_changes : nat64; - }; - requested_by : principal; - }; -}; - -type change = record { - timestamp_nanos : nat64; - canister_version : nat64; - origin : change_origin; - details : change_details; -}; - -type chunk_hash = record { - hash : blob; -}; - -type http_header = record { - name : text; - value : text; -}; - -type http_request_result = record { - status : nat; - headers : vec http_header; - body : blob; -}; - -type ecdsa_curve = variant { - secp256k1; -}; - -type vetkd_curve = variant { - bls12_381_g2; -}; - -type schnorr_algorithm = variant { - bip340secp256k1; - ed25519; -}; - -type satoshi = nat64; - -type bitcoin_network = variant { - mainnet; - testnet; -}; - -type bitcoin_address = text; - -type bitcoin_block_hash = blob; - -type bitcoin_block_header = blob; - -type millisatoshi_per_byte = nat64; - -type bitcoin_block_height = nat32; - -type outpoint = record { - txid : blob; - vout : nat32; -}; - -type utxo = record { - outpoint : outpoint; - value : satoshi; - height : nat32; -}; - -type bitcoin_get_utxos_args = record { - address : bitcoin_address; - network : bitcoin_network; - filter : opt variant { - min_confirmations : nat32; - page : blob; - }; -}; - -type bitcoin_get_utxos_result = record { - utxos : vec utxo; - tip_block_hash : bitcoin_block_hash; - tip_height : bitcoin_block_height; - next_page : opt blob; -}; - -type bitcoin_get_balance_args = record { - address : bitcoin_address; - network : bitcoin_network; - min_confirmations : opt nat32; -}; - -type bitcoin_get_balance_result = satoshi; - -type bitcoin_get_current_fee_percentiles_args = record { - network : bitcoin_network; -}; - -type bitcoin_get_current_fee_percentiles_result = vec millisatoshi_per_byte; - -type bitcoin_send_transaction_args = record { - transaction : blob; - network : bitcoin_network; -}; - -type bitcoin_get_block_headers_args = record { - start_height : bitcoin_block_height; - end_height : opt bitcoin_block_height; - network : bitcoin_network; -}; - -type bitcoin_get_block_headers_result = record { - tip_height : bitcoin_block_height; - block_headers : vec bitcoin_block_header; -}; - -type node_metrics = record { - node_id : principal; - num_blocks_proposed_total : nat64; - num_block_failures_total : nat64; -}; - -type create_canister_args = record { - settings : opt canister_settings; - sender_canister_version : opt nat64; -}; - -type create_canister_result = record { - canister_id : canister_id; -}; - -type update_settings_args = record { - canister_id : canister_id; - settings : canister_settings; - sender_canister_version : opt nat64; -}; - -type upload_chunk_args = record { - canister_id : canister_id; - chunk : blob; -}; - -type clear_chunk_store_args = record { - canister_id : canister_id; -}; - -type stored_chunks_args = record { - canister_id : canister_id; -}; - -type canister_install_mode = variant { - install; - reinstall; - upgrade : opt record { - skip_pre_upgrade : opt bool; - wasm_memory_persistence : opt variant { - keep; - replace; - }; - }; -}; - -type install_code_args = record { - mode : canister_install_mode; - canister_id : canister_id; - wasm_module : wasm_module; - arg : blob; - sender_canister_version : opt nat64; -}; - -type install_chunked_code_args = record { - mode : canister_install_mode; - target_canister : canister_id; - store_canister : opt canister_id; - chunk_hashes_list : vec chunk_hash; - wasm_module_hash : blob; - arg : blob; - sender_canister_version : opt nat64; -}; - -type uninstall_code_args = record { - canister_id : canister_id; - sender_canister_version : opt nat64; -}; - -type start_canister_args = record { - canister_id : canister_id; -}; - -type stop_canister_args = record { - canister_id : canister_id; -}; - -type canister_status_args = record { - canister_id : canister_id; -}; - -type canister_status_result = record { - status : variant { - running; - stopping; - stopped; - }; - ready_for_migration : bool; - version : nat64; - settings : definite_canister_settings; - module_hash : opt blob; - memory_size : nat; - memory_metrics : record { - wasm_memory_size : nat; - stable_memory_size : nat; - global_memory_size : nat; - wasm_binary_size : nat; - custom_sections_size : nat; - canister_history_size : nat; - wasm_chunk_store_size : nat; - snapshots_size : nat; - }; - cycles : nat; - reserved_cycles : nat; - idle_cycles_burned_per_day : nat; - query_stats : record { - num_calls_total : nat; - num_instructions_total : nat; - request_payload_bytes_total : nat; - response_payload_bytes_total : nat; - }; -}; - -type canister_info_args = record { - canister_id : canister_id; - num_requested_changes : opt nat64; -}; - -type canister_info_result = record { - total_num_changes : nat64; - recent_changes : vec change; - module_hash : opt blob; - controllers : vec principal; -}; - -type canister_metadata_args = record { - canister_id : canister_id; - name : text; -}; - -type canister_metadata_result = record { - value : blob; -}; - -type delete_canister_args = record { - canister_id : canister_id; -}; - -type deposit_cycles_args = record { - canister_id : canister_id; -}; - -type http_request_args = record { - url : text; - max_response_bytes : opt nat64; - method : variant { get; head; post; put; delete }; - headers : vec http_header; - body : opt blob; - transform : opt record { - function : func(record { response : http_request_result; context : blob }) -> (http_request_result) query; - context : blob; - }; - is_replicated : opt bool; -}; - -type ecdsa_public_key_args = record { - canister_id : opt canister_id; - derivation_path : vec blob; - key_id : record { curve : ecdsa_curve; name : text }; -}; - -type ecdsa_public_key_result = record { - public_key : blob; - chain_code : blob; -}; - -type sign_with_ecdsa_args = record { - message_hash : blob; - derivation_path : vec blob; - key_id : record { curve : ecdsa_curve; name : text }; -}; - -type sign_with_ecdsa_result = record { - signature : blob; -}; - -type schnorr_public_key_args = record { - canister_id : opt canister_id; - derivation_path : vec blob; - key_id : record { algorithm : schnorr_algorithm; name : text }; -}; - -type schnorr_public_key_result = record { - public_key : blob; - chain_code : blob; -}; - -type schnorr_aux = variant { - bip341 : record { - merkle_root_hash : blob; - }; -}; - -type sign_with_schnorr_args = record { - message : blob; - derivation_path : vec blob; - key_id : record { algorithm : schnorr_algorithm; name : text }; - aux : opt schnorr_aux; -}; - -type sign_with_schnorr_result = record { - signature : blob; -}; - -type vetkd_public_key_args = record { - canister_id : opt canister_id; - context : blob; - key_id : record { curve : vetkd_curve; name : text }; -}; - -type vetkd_public_key_result = record { - public_key : blob; -}; - -type vetkd_derive_key_args = record { - input : blob; - context : blob; - transport_public_key : blob; - key_id : record { curve : vetkd_curve; name : text }; -}; - -type vetkd_derive_key_result = record { - encrypted_key : blob; -}; - -type node_metrics_history_args = record { - subnet_id : principal; - start_at_timestamp_nanos : nat64; -}; - -type node_metrics_history_result = vec record { - timestamp_nanos : nat64; - node_metrics : vec node_metrics; -}; - -type subnet_info_args = record { - subnet_id : principal; -}; - -type subnet_info_result = record { - replica_version : text; - registry_version : nat64; -}; - -type provisional_create_canister_with_cycles_args = record { - amount : opt nat; - settings : opt canister_settings; - specified_id : opt canister_id; - sender_canister_version : opt nat64; -}; - -type provisional_create_canister_with_cycles_result = record { - canister_id : canister_id; -}; - -type provisional_top_up_canister_args = record { - canister_id : canister_id; - amount : nat; -}; - -type raw_rand_result = blob; - -type stored_chunks_result = vec chunk_hash; - -type upload_chunk_result = chunk_hash; - -type snapshot = record { - id : snapshot_id; - taken_at_timestamp : nat64; - total_size : nat64; -}; - -type take_canister_snapshot_args = record { - canister_id : canister_id; - replace_snapshot : opt snapshot_id; - uninstall_code : opt bool; - sender_canister_version : opt nat64; -}; - -type take_canister_snapshot_result = snapshot; - -type load_canister_snapshot_args = record { - canister_id : canister_id; - snapshot_id : snapshot_id; - sender_canister_version : opt nat64; -}; - -type list_canister_snapshots_args = record { - canister_id : canister_id; -}; - -type list_canister_snapshots_result = vec snapshot; - -type delete_canister_snapshot_args = record { - canister_id : canister_id; - snapshot_id : snapshot_id; -}; - -type fetch_canister_logs_args = record { - canister_id : canister_id; -}; - -type canister_log_record = record { - idx : nat64; - timestamp_nanos : nat64; - content : blob; -}; - -type fetch_canister_logs_result = record { - canister_log_records : vec canister_log_record; -}; - -type read_canister_snapshot_metadata_args = record { - canister_id : canister_id; - snapshot_id : snapshot_id; -}; - -type read_canister_snapshot_metadata_response = record { - source : variant { - taken_from_canister: reserved; - metadata_upload : reserved; - }; - taken_at_timestamp : nat64; - wasm_module_size : nat64; - globals : vec variant { - i32 : int32; - i64 : int64; - f32 : float32; - f64 : float64; - v128 : nat; - }; - wasm_memory_size : nat64; - stable_memory_size : nat64; - wasm_chunk_store : vec record { - hash : blob; - }; - canister_version : nat64; - certified_data : blob; - global_timer : opt variant { - inactive; - active : nat64; - }; - on_low_wasm_memory_hook_status : opt variant { - condition_not_satisfied; - ready; - executed; - }; -}; - -type read_canister_snapshot_data_args = record { - canister_id : canister_id; - snapshot_id : snapshot_id; - kind : variant { - wasm_module : record { - offset : nat64; - size : nat64; - }; - wasm_memory : record { - offset : nat64; - size : nat64; - }; - stable_memory : record { - offset : nat64; - size : nat64; - }; - wasm_chunk : record { - hash : blob; - }; - }; -}; - -type read_canister_snapshot_data_response = record { - chunk : blob; -}; - -type upload_canister_snapshot_metadata_args = record { - canister_id : canister_id; - replace_snapshot : opt snapshot_id; - wasm_module_size : nat64; - globals : vec variant { - i32 : int32; - i64 : int64; - f32 : float32; - f64 : float64; - v128 : nat; - }; - wasm_memory_size : nat64; - stable_memory_size : nat64; - certified_data : blob; - global_timer : opt variant { - inactive; - active : nat64; - }; - on_low_wasm_memory_hook_status : opt variant { - condition_not_satisfied; - ready; - executed; - }; -}; - -type upload_canister_snapshot_metadata_response = record { - snapshot_id : snapshot_id; -}; - -type upload_canister_snapshot_data_args = record { - canister_id : canister_id; - snapshot_id : snapshot_id; - kind : variant { - wasm_module : record { - offset : nat64; - }; - wasm_memory : record { - offset : nat64; - }; - stable_memory : record { - offset : nat64; - }; - wasm_chunk; - }; - chunk : blob; -}; - -service ic : { - create_canister : (create_canister_args) -> (create_canister_result); - update_settings : (update_settings_args) -> (); - upload_chunk : (upload_chunk_args) -> (upload_chunk_result); - clear_chunk_store : (clear_chunk_store_args) -> (); - stored_chunks : (stored_chunks_args) -> (stored_chunks_result); - install_code : (install_code_args) -> (); - install_chunked_code : (install_chunked_code_args) -> (); - uninstall_code : (uninstall_code_args) -> (); - start_canister : (start_canister_args) -> (); - stop_canister : (stop_canister_args) -> (); - canister_status : (canister_status_args) -> (canister_status_result) query; - delete_canister : (delete_canister_args) -> (); - deposit_cycles : (deposit_cycles_args) -> (); - raw_rand : () -> (raw_rand_result); - http_request : (http_request_args) -> (http_request_result); - - // Public canister data - canister_info : (canister_info_args) -> (canister_info_result); - canister_metadata : (canister_metadata_args) -> (canister_metadata_result); - - // Threshold ECDSA signature - ecdsa_public_key : (ecdsa_public_key_args) -> (ecdsa_public_key_result); - sign_with_ecdsa : (sign_with_ecdsa_args) -> (sign_with_ecdsa_result); - - // Threshold Schnorr signature - schnorr_public_key : (schnorr_public_key_args) -> (schnorr_public_key_result); - sign_with_schnorr : (sign_with_schnorr_args) -> (sign_with_schnorr_result); - - // Threshold key derivation - vetkd_public_key : (vetkd_public_key_args) -> (vetkd_public_key_result); - vetkd_derive_key : (vetkd_derive_key_args) -> (vetkd_derive_key_result); - - // bitcoin interface - bitcoin_get_balance : (bitcoin_get_balance_args) -> (bitcoin_get_balance_result); - bitcoin_get_utxos : (bitcoin_get_utxos_args) -> (bitcoin_get_utxos_result); - bitcoin_send_transaction : (bitcoin_send_transaction_args) -> (); - bitcoin_get_current_fee_percentiles : (bitcoin_get_current_fee_percentiles_args) -> (bitcoin_get_current_fee_percentiles_result); - bitcoin_get_block_headers : (bitcoin_get_block_headers_args) -> (bitcoin_get_block_headers_result); - - // metrics interface - node_metrics_history : (node_metrics_history_args) -> (node_metrics_history_result); - - // subnet info - subnet_info : (subnet_info_args) -> (subnet_info_result); - - // provisional interfaces for the pre-ledger world - provisional_create_canister_with_cycles : (provisional_create_canister_with_cycles_args) -> (provisional_create_canister_with_cycles_result); - provisional_top_up_canister : (provisional_top_up_canister_args) -> (); - - // Canister snapshots - take_canister_snapshot : (take_canister_snapshot_args) -> (take_canister_snapshot_result); - load_canister_snapshot : (load_canister_snapshot_args) -> (); - read_canister_snapshot_metadata : (read_canister_snapshot_metadata_args) -> (read_canister_snapshot_metadata_response); - read_canister_snapshot_data : (read_canister_snapshot_data_args) -> (read_canister_snapshot_data_response); - upload_canister_snapshot_metadata : (upload_canister_snapshot_metadata_args) -> (upload_canister_snapshot_metadata_response); - upload_canister_snapshot_data : (upload_canister_snapshot_data_args) -> (); - list_canister_snapshots : (list_canister_snapshots_args) -> (list_canister_snapshots_result); - delete_canister_snapshot : (delete_canister_snapshot_args) -> (); - - // canister logging - fetch_canister_logs : (fetch_canister_logs_args) -> (fetch_canister_logs_result) query; -}; From 278941c8ce45a95d32cbb145678edb38fc9f8d94 Mon Sep 17 00:00:00 2001 From: Marco Walz Date: Thu, 19 Mar 2026 13:56:24 +0100 Subject: [PATCH 5/5] docs: remove fee column from ledger table, fees are dynamic --- docs/reference/token-standards.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/reference/token-standards.md b/docs/reference/token-standards.md index 64d16dbd..1741b275 100644 --- a/docs/reference/token-standards.md +++ b/docs/reference/token-standards.md @@ -105,13 +105,13 @@ type TransferError = variant { The following are DFINITY-maintained ledgers. Many other ICRC-1 tokens exist on ICP — see the [ICP Dashboard token list](https://dashboard.internetcomputer.org/tokens) for a comprehensive registry. Anyone can deploy an ICRC-1 compliant ledger. -| Token | Ledger canister ID | Default fee | Decimals | -|-------|-------------------|-------------|----------| -| ICP | `ryjl3-tyaaa-aaaaa-aaaba-cai` | 10,000 e8s (0.0001 ICP) | 8 | -| ckBTC | `mxzaz-hqaaa-aaaar-qaada-cai` | 10 satoshis | 8 | -| ckETH | `ss2fx-dyaaa-aaaar-qacoq-cai` | 2,000,000,000,000 wei (0.000002 ETH) | 18 | +| Token | Ledger canister ID | Decimals | +|-------|-------------------|----------| +| ICP | `ryjl3-tyaaa-aaaaa-aaaba-cai` | 8 | +| ckBTC | `mxzaz-hqaaa-aaaar-qaada-cai` | 8 | +| ckETH | `ss2fx-dyaaa-aaaar-qacoq-cai` | 18 | -> Fees can change through governance proposals. Always call `icrc1_fee` to get the current fee rather than hardcoding these values. +> Fees can change at any time. Always call `icrc1_fee` to get the current fee rather than hardcoding values. Index canisters (for transaction history):