Skip to content

Latest commit

 

History

History

icp_transfer

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 

README.md

ICP Transfer

ICP Transfer demonstrates how a canister can hold ICP and send it to other accounts using the ICP ledger.

Account identifiers

The ICP ledger identifies accounts with a 32-byte AccountIdentifier — a hash of a principal and an optional subaccount. Centralized exchanges (CEXs) use this format for deposit addresses; wallets and newer integrations typically prefer the ICRC-1 account format (principal + subaccount directly). AccountIdentifier::new(&principal, &subaccount) in Rust performs this conversion.

The example exposes three functions to make this concrete:

  • to_account_id_hex(principal, subaccount) — query returning the AccountIdentifier as a 64-char lowercase hex string, the format shown in block explorers and CEX deposit screens.
  • transfer_to_principal(amount, principal, subaccount) — calls AccountIdentifier::new internally. Use this when you have a principal.
  • transfer_to_account_id(amount, account_id_hex) — accepts the AccountIdentifier as a 64-char hex string (the format CEXs and block explorers provide). Validates the embedded CRC32 checksum before transferring.

The ICP ledger also supports the ICRC-1 standard via icrc1_transfer. For new token integrations that don't require AccountIdentifier compatibility, ICRC-1 is the recommended interface. A comprehensive ICRC ledger example is planned.

Build and deploy from the command line

Prerequisites

  • Node.js
  • icp-cli: npm install -g @icp-sdk/icp-cli @icp-sdk/ic-wasm

Deploy and test

icp network start -d
icp deploy
bash test.sh
icp network stop

bash test.sh funds the backend with 2 ICP, then:

  1. Compares icp identity account-id --format ledger with to_account_id_hex to verify CLI and backend compute the same AccountIdentifier.
  2. Calls transfer_to_principal — transfers 99_990_000 e8s (amount) + 10_000 e8s (fee) = exactly 1 ICP deducted from the backend; confirms both sides via icp token balance.
  3. Calls transfer_to_account_id with the hex string from step 1 — same 1 ICP deduction, confirming both transfer paths reach the same account and the backend balance reaches zero.

Security considerations and best practices

Refer to the security best practices for information on security and best practices for your ICP app. For this example the following aspects are particularly relevant: