Skip to content

Commit d89a652

Browse files
committed
fix: address PR feedback for token ledgers guide
- Fix icp.yaml config: use build/steps/pre-built with url + init_args instead of invalid recipe/type/custom (dfx-ism) - Add missing Motoko imports (Array, Nat8) in subaccount snippet - Add icrc1_balance_of examples (Rust + Motoko) - Add candid language tag to Account type code fence - Remove unused caller capture from Motoko approveSpender - Rebase on main to drop stale reverse-diffs
1 parent ddcdbe1 commit d89a652

1 file changed

Lines changed: 54 additions & 10 deletions

File tree

docs/guides/defi/token-ledgers.md

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ All of these ledgers are ICRC-1 and ICRC-2 compatible. For chain-key token speci
3434

3535
The `icrc1_transfer` function sends tokens from the calling canister's account to a destination account. Every ICRC-1 ledger uses the same `Account` type:
3636

37-
```
37+
```candid
3838
{ owner: Principal; subaccount: ?Blob } // 32-byte subaccount, null = default
3939
```
4040

@@ -175,6 +175,49 @@ icp canister call ryjl3-tyaaa-aaaaa-aaaba-cai icrc1_fee '()' -e ic
175175

176176
Always set `created_at_time` to enable deduplication. Without it, two identical transfers submitted within 24 hours both execute.
177177

178+
### Checking balances
179+
180+
Query an account's balance with `icrc1_balance_of`. This is a query call — fast and free.
181+
182+
#### Rust
183+
184+
```rust
185+
use candid::{Nat, Principal};
186+
use icrc_ledger_types::icrc1::account::Account;
187+
use ic_cdk::call::Call;
188+
189+
async fn get_balance(ledger: Principal, owner: Principal) -> Result<Nat, String> {
190+
let account = Account { owner, subaccount: None };
191+
192+
let (balance,): (Nat,) =
193+
Call::unbounded_wait(ledger, "icrc1_balance_of")
194+
.with_arg(account)
195+
.await
196+
.map_err(|e| format!("Call failed: {:?}", e))?
197+
.candid_tuple()
198+
.map_err(|e| format!("Decode failed: {:?}", e))?;
199+
200+
Ok(balance)
201+
}
202+
```
203+
204+
#### Motoko
205+
206+
```motoko
207+
persistent actor {
208+
209+
type Account = { owner : Principal; subaccount : ?Blob };
210+
211+
transient let icpLedger = actor ("ryjl3-tyaaa-aaaaa-aaaba-cai") : actor {
212+
icrc1_balance_of : shared query (Account) -> async Nat;
213+
};
214+
215+
public func getBalance(owner : Principal) : async Nat {
216+
await icpLedger.icrc1_balance_of({ owner = owner; subaccount = null })
217+
};
218+
}
219+
```
220+
178221
## Approve and transfer-from (ICRC-2)
179222

180223
ICRC-2 adds an approve/transferFrom pattern, similar to ERC-20 on Ethereum. The token owner first approves a spender for a certain amount, then the spender calls `icrc2_transfer_from` to move tokens. This is a two-step flow — calling `transfer_from` without a prior approval fails with `InsufficientAllowance`.
@@ -312,7 +355,7 @@ persistent actor {
312355
icrc2_transfer_from : shared (TransferFromArg) -> async { #Ok : Nat; #Err : TransferFromError };
313356
};
314357
315-
public shared ({ caller }) func approveSpender(spender : Principal, amount : Nat) : async Nat {
358+
public func approveSpender(spender : Principal, amount : Nat) : async Nat {
316359
let now = Nat64.fromNat(Int.abs(Time.now()));
317360
let result = await icpLedger.icrc2_approve({
318361
from_subaccount = null;
@@ -384,6 +427,8 @@ fn deposit_account(canister: Principal, user: Principal) -> Account {
384427
```motoko
385428
import Principal "mo:core/Principal";
386429
import Blob "mo:core/Blob";
430+
import Array "mo:core/Array";
431+
import Nat8 "mo:core/Nat8";
387432
388433
type Account = { owner : Principal; subaccount : ?Blob };
389434
@@ -429,14 +474,13 @@ To test token operations locally, deploy an ICRC-1 ledger on your local replica.
429474

430475
```yaml
431476
canisters:
432-
icrc1_ledger:
433-
name: icrc1_ledger
434-
recipe:
435-
type: custom
436-
candid: "https://github.com/dfinity/ic/releases/download/<RELEASE_TAG>/ledger.did"
437-
wasm: "https://github.com/dfinity/ic/releases/download/<RELEASE_TAG>/ic-icrc1-ledger.wasm.gz"
438-
config:
439-
init_arg_file: "icrc1_ledger_init.args"
477+
- name: icrc1_ledger
478+
build:
479+
steps:
480+
- type: pre-built
481+
url: "https://github.com/dfinity/ic/releases/download/<RELEASE_TAG>/ic-icrc1-ledger.wasm.gz"
482+
init_args:
483+
path: icrc1_ledger_init.args
440484
```
441485
442486
Create `icrc1_ledger_init.args` with your principal. Replace `YOUR_PRINCIPAL` with the output of `icp identity principal`:

0 commit comments

Comments
 (0)