You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
refactor(motoko/icp_transfer): call the ICP ledger via canister: import + --actor-id-alias (#1455)
Replace the hand-written ICP ledger actor type (and the hardcoded
`actor("ryjl3-…")` reference) with a typed `canister:icp_ledger` import bound
by moc's `--actor-id-alias`. All ledger types now come from the ledger's
official Candid interface — nothing is hand-declared.
Why `--actor-id-alias` (and not `--actor-env-alias` or generated bindings):
the ICP ledger lives at the *same, fixed, well-known* principal
(ryjl3-tyaaa-aaaaa-aaaba-cai) on both mainnet and the local development
network. When the target id is fixed and universal, binding it at compile time
is the simplest correct choice — no per-environment env-var injection needed
(that's what `--actor-env-alias` is for), and no runtime `actor(id)`
construction (that's for targets chosen at runtime).
- candid/icp_ledger.did — the ledger's official interface, from the
ledger-suite-icp-2025-08-29 release (`ledger.did`).
- mops.toml — `--actor-id-alias icp_ledger ryjl3-tyaaa-aaaaa-aaaba-cai candid/icp_ledger.did`.
- backend/app.mo — `import IcpLedger "canister:icp_ledger"`; types are now
`IcpLedger.Tokens` / `IcpLedger.TransferArgs` / …; removed the hand-written
Tokens/SubAccount/BlockIndex/AccountIdentifier/LedgerTransferArgs/TransferError/
TransferResult and the `actor("ryjl3-…")` line.
Verified end-to-end: `icp deploy && bash test.sh` — all 3 tests pass (real ICP
transfers via the imported ledger, with correct balance deltas).
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: motoko/icp_transfer/README.md
+8Lines changed: 8 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -14,6 +14,14 @@ The example exposes three functions to make this concrete:
14
14
15
15
> The ICP ledger also supports the [ICRC-1](https://github.com/dfinity/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.
16
16
17
+
## Calling the ICP ledger
18
+
19
+
The backend reaches the ledger through the typed import `import IcpLedger "canister:icp_ledger"` — no ledger types are declared in the code. Because the ICP ledger lives at the **same well-known principal** (`ryjl3-tyaaa-aaaaa-aaaba-cai`) on both mainnet and the local development network, the `--actor-id-alias` flag in `mops.toml` binds the import to that fixed id and types it against the ledger's official Candid interface (`candid/icp_ledger.did`). The request/response types (`IcpLedger.Tokens`, `IcpLedger.TransferArgs`, …) come straight from that interface.
20
+
21
+
> `--actor-id-alias` fits here because the target's id is *fixed and universal*. When a target's id varies per environment, `--actor-env-alias` resolves it from an injected env var instead; when the target is chosen at runtime, generate bindings and construct `actor(principal)` per call.
22
+
23
+
`candid/icp_ledger.did` is the ledger's own interface, taken from the [ICP ledger suite release](https://github.com/dfinity/ic/releases/tag/ledger-suite-icp-2025-08-29) (`ledger.did`). To refresh it after a new ledger release, download the `ledger.did` asset from that release.
0 commit comments