Canisters
The following functions can be used to interact with well-known Internet Computer canisters from your serverless functions.
The Canisters API is provided by the @junobuild/functions library.
To add it to your project:
- npm
- yarn
- pnpm
npm i @junobuild/functions
yarn add @junobuild/functions
pnpm add @junobuild/functions
You have to follow the pace of the Juno release to ensure compatibility. Refer to the maintenance guide for instructions.
Overviewโ
The @junobuild/functions/canisters module provides a unified interface for interacting with core Internet Computer canisters from within your Juno serverless functions. It offers:
- โ๏ธ Type-safe interfaces for well-known IC canisters
- ๐งฉ Modular structure with independent sub-packages
- ๐ Up-to-date Candid declarations and types
- ๐งช Battle-tested through production applications
Available Canistersโ
Import Structureโ
Each canister is available as a sub-entry. Import the desired module directly from its entry point:
| Canister(s) | Import | Status |
|---|---|---|
| ICP Ledger | @junobuild/functions/canisters/ledger/icp | โ Canister + Declarations |
| ICRC Ledger | @junobuild/functions/canisters/ledger/icrc | โ Canister + Declarations |
| CMC | @junobuild/functions/canisters/cmc | โ Canister + Declarations |
| ckBTC | @junobuild/functions/canisters/ckbtc | ๐ฆ Declarations Only |
| ckETH | @junobuild/functions/canisters/cketh | ๐ฆ Declarations Only |
| IC Management | @junobuild/functions/canisters/ic-management | ๐ฆ Declarations Only |
| NNS | @junobuild/functions/canisters/nns | ๐ฆ Declarations Only |
| SNS | @junobuild/functions/canisters/sns | ๐ฆ Declarations Only |
ICP Ledgerโ
You can interact with the ICP Ledger through the class IcpLedgerCanister.
transferโ
Sends ICP using the Ledger canister transfer method.
transfer(params: {
args: IcpLedgerDid.TransferArgs
}): Promise<IcpLedgerDid.TransferResult>
Parameters:โ
args: The ledger transfer argumentsto: Destination account identifier (AccountIdentifier)amount: Transfer amount object withe8s(bigint)fee: Fee object withe8s(bigint)memo: Optional transfer memo (bigint)from_subaccount: Optional subaccount (Uint8Array | number[])created_at_time: Optional timestamp object withtimestamp_nanos(bigint)
Returns:โ
Promise<IcpLedgerDid.TransferResult>: The result of the ICP transfer- On success:
{ Ok: bigint }(block height) - On error:
{ Err: TransferError }
Example:โ
import { IcpLedgerCanister } from "@junobuild/functions/canisters/ledger/icp";
export const onExecute = async () => {
const ledger = new IcpLedgerCanister();
const result = await ledger.transfer({
args: {
to: "destination-account-identifier",
amount: { e8s: 100_000_000n }, // 1 ICP
fee: { e8s: 10_000n },
memo: 0n
}
});
if ("Ok" in result) {
console.log("Transfer successful, block height:", result.Ok);
} else {
console.error("Transfer failed:", result.Err);
}
};
ICRC Ledgerโ
Interact with ICRC compatible ledgers through the class IcrcLedgerCanister.
icrc1BalanceOfโ
Returns the balance of an ICRC account.
icrc1BalanceOf(params: {
account: IcrcLedgerDid.Account
}): Promise<IcrcLedgerDid.Tokens>
Parameters:โ
account: The account to queryowner: Principal of the account ownersubaccount: Optional subaccount (Uint8Array | number[])
Returns:โ
Promise<IcrcLedgerDid.Tokens>: The token balance (bigint)
Example:โ
import { IcrcLedgerCanister } from "@junobuild/functions/canisters/ledger/icrc";
import { Principal } from "@dfinity/principal";
export const onExecute = async () => {
const ledger = new IcrcLedgerCanister({
canisterId: "your-icrc-ledger-canister-id"
});
const balance = await ledger.icrc1BalanceOf({
account: {
owner: Principal.fromText("user-principal"),
subaccount: []
}
});
console.log("Balance:", balance);
};
icrc1Transferโ
Transfers tokens using the ICRC-1 icrc1_transfer method.
icrc1Transfer(params: {
args: IcrcLedgerDid.TransferArg
}): Promise<IcrcLedgerDid.TransferResult>
Parameters:โ
args: Transfer argumentsto: Destination account (Account object)amount: Transfer amount (bigint)fee: Optional fee (bigint)memo: Optional memo (Uint8Array | number[])from_subaccount: Optional subaccount (Uint8Array | number[])created_at_time: Optional timestamp (bigint)
Returns:โ
Promise<IcrcLedgerDid.TransferResult>: The result of the transfer- On success:
{ Ok: bigint }(block index) - On error:
{ Err: TransferError }
Example:โ
import { IcrcLedgerCanister } from "@junobuild/functions/canisters/ledger/icrc";
import { Principal } from "@dfinity/principal";
export const onExecute = async () => {
const ledger = new IcrcLedgerCanister({
canisterId: "your-icrc-ledger-canister-id"
});
const result = await ledger.icrc1Transfer({
args: {
to: {
owner: Principal.fromText("recipient-principal"),
subaccount: []
},
amount: 1_000_000n,
fee: 10_000n
}
});
if ("Ok" in result) {
console.log("Transfer successful, block index:", result.Ok);
} else {
console.error("Transfer failed:", result.Err);
}
};
icrc2TransferFromโ
Transfers tokens using the ICRC-2 icrc2_transfer_from method.
Allows transferring tokens from another user's account when an approval has previously been granted via icrc2_approve.
icrc2TransferFrom(params: {
args: IcrcLedgerDid.TransferFromArgs
}): Promise<IcrcLedgerDid.TransferFromResult>
Parameters:โ
args: Transfer-from argumentsfrom: Source account (Account object)to: Destination account (Account object)amount: Transfer amount (bigint)fee: Optional fee (bigint)memo: Optional memo (Uint8Array | number[])spender_subaccount: Optional spender subaccount (Uint8Array | number[])created_at_time: Optional timestamp (bigint)
Returns:โ
Promise<IcrcLedgerDid.TransferFromResult>: The result of the transfer-from operation- On success:
{ Ok: bigint }(block index) - On error:
{ Err: TransferFromError }
Example:โ
import { IcrcLedgerCanister } from "@junobuild/functions/canisters/ledger/icrc";
import { Principal } from "@dfinity/principal";
export const onExecute = async () => {
const ledger = new IcrcLedgerCanister({
canisterId: "your-icrc-ledger-canister-id"
});
const result = await ledger.icrc2TransferFrom({
args: {
from: {
owner: Principal.fromText("source-principal"),
subaccount: []
},
to: {
owner: Principal.fromText("destination-principal"),
subaccount: []
},
amount: 500_000n
}
});
if ("Ok" in result) {
console.log("Transfer from successful, block index:", result.Ok);
} else {
console.error("Transfer from failed:", result.Err);
}
};
Cycle Minting Canister (CMC)โ
Interact with the Cycle Minting Canister to convert ICP into cycles using the class CMCCanister.
notifyTopUpโ
Notifies the Cycle Minting Canister that a top-up transfer has been completed.
After sending ICP to the CMC top-up account for a canister, the transfer is recorded on the ledger. The CMC does not automatically convert that ICP into cycles โ you must call this function to let the CMC know which transaction to process.
The CMC will then convert the ICP from the given ledger block into cycles and add them to the specified canister.
notifyTopUp(params: {
args: CmcDid.NotifyTopUpArg
}): Promise<CmcDid.NotifyTopUpResult>
Parameters:โ
args: Arguments containing:block_index: The ledger block index of the ICP transfer (bigint)canister_id: The canister ID that should receive the cycles (Principal)
Returns:โ
Promise<CmcDid.NotifyTopUpResult>: The result of the CMC conversion and deposit- On success:
{ Ok: bigint }(cycles deposited) - On error:
{ Err: NotifyError }
Example:โ
import { CMCCanister } from "@junobuild/functions/canisters/cmc";
import { IcpLedgerCanister } from "@junobuild/functions/canisters/ledger/icp";
import { Principal } from "@dfinity/principal";
export const onExecute = async () => {
// Step 1: Send ICP to the CMC top-up account
const ledger = new IcpLedgerCanister();
const transferResult = await ledger.transfer({
args: {
to: "cmc-top-up-account-identifier",
amount: { e8s: 100_000_000n }, // 1 ICP
fee: { e8s: 10_000n },
memo: 0n
}
});
if ("Err" in transferResult) {
console.error("Transfer failed:", transferResult.Err);
return;
}
const blockIndex = transferResult.Ok;
// Step 2: Notify the CMC to convert the ICP to cycles
const cmc = new CMCCanister();
const notifyResult = await cmc.notifyTopUp({
args: {
block_index: blockIndex,
canister_id: Principal.fromText("your-canister-id")
}
});
if ("Ok" in notifyResult) {
console.log("Cycles deposited:", notifyResult.Ok);
} else {
console.error("Notify failed:", notifyResult.Err);
}
};
Declarations-Only Exportsโ
The following canisters currently provide Candid type definitions and IDL declarations only. You can use these with the call function for custom interactions.
ckBTCโ
import {
CkBTCBitcoinIdl,
CkBTCMinterIdl,
type CkBTCBitcoinDid,
type CkBTCMinterDid
} from "@junobuild/functions/canisters/ckbtc";
ckETHโ
import {
CkETHMinterIdl,
CkETHOrchestratorIdl,
type CkETHMinterDid,
type CkETHOrchestratorDid
} from "@junobuild/functions/canisters/cketh";
IC Managementโ
import {
IcManagementIdl,
type IcManagementDid
} from "@junobuild/functions/canisters/ic-management";
NNSโ
import {
NnsGovernanceIdl,
NnsSnsWasmIdl,
type NnsGovernanceDid,
type NnsSnsWasmDid
} from "@junobuild/functions/canisters/nns";
SNSโ
import {
NnsSnsWasmIdl,
SnsGovernanceIdl,
SnsRootIdl,
SnsSwapIdl,
type SnsGovernanceDid,
type SnsRootDid,
type SnsSwapDid
} from "@junobuild/functions/canisters/sns";
Usage with call()โ
You can use these type definitions with the call function to interact with any canister:
import { call } from "@junobuild/functions/ic-cdk";
import {
IcManagementIdl,
type IcManagementDid
} from "@junobuild/functions/canisters/ic-management";
export const onExecute = async () => {
const status = await call<IcManagementDid.CanisterStatusResult>({
canisterId: "aaaaa-aa", // Management canister
method: "canister_status",
args: [
[IcManagementIdl.CanisterIdRecord, { canister_id: "your-canister-id" }]
],
result: IcManagementIdl.CanisterStatusResult
});
console.log("Canister status:", status);
};
Notesโ
- All canister classes use the call function internally to communicate with the Internet Computer.
- The caller's identity is automatically determined by the serverless function execution context.
- For admin operations, you can use the id function to get the Satellite's principal, which has admin privileges.
- Error handling follows the Result pattern: check for
OkorErrproperties in the response.