Skip to content

Commit 5df5265

Browse files
docs: update call canister without candid mumbo jumbo in TypeScript (#705)
* docs: update call canister without candid mumbo jumbo in TypeScript Signed-off-by: David Dal Busco <david.dalbusco@outlook.com> * 📄 Update LLMs.txt snapshot for PR review --------- Signed-off-by: David Dal Busco <david.dalbusco@outlook.com> Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
1 parent 22d6e51 commit 5df5265

2 files changed

Lines changed: 29 additions & 28 deletions

File tree

.llms-snapshots/llms-full.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6387,11 +6387,11 @@ typescript/calls/├── src/│ ├── satellite/ # TypeScript
63876387
Here’s the actual TypeScript logic from `index.ts` and `services.ts`:
63886388

63896389
```
6390-
// src/satellite/index.tsimport { Principal } from "@icp-sdk/core/principal";import { type AssertSetDoc, defineAssert, defineHook, type OnSetDoc} from "@junobuild/functions";import { IcrcLedgerDid } from "@junobuild/functions/canisters/ledger/icrc";import { id } from "@junobuild/functions/ic-cdk";import { decodeDocData } from "@junobuild/functions/sdk";import { COLLECTION_REQUEST, ICP_LEDGER_ID } from "../constants/app.constants";import { RequestData, RequestDataSchema } from "../types/request";import { assertWalletBalance, setRequestProcessed, transferIcpFromWallet} from "./services";export const assertSetDoc = defineAssert<AssertSetDoc>({ collections: [COLLECTION_REQUEST], assert: (context) => { // We validate that the data submitted for create or update matches the expected schema. const person = decodeDocData<RequestData>(context.data.data.proposed.data); RequestDataSchema.parse(person); }});export const onSetDoc = defineHook<OnSetDoc>({ collections: [COLLECTION_REQUEST], run: async (context) => { // ############### // Init data // ############### const { data: { key, data: { after: { version } } } } = context; const data = decodeDocData<RequestData>(context.data.data.after.data); const { amount: requestAmount, fee } = data; const ledgerId = ICP_LEDGER_ID; const fromAccount: IcrcLedgerDid.Account = { owner: Principal.fromUint8Array(context.caller), subaccount: [] }; // ############### // Check current account balance. This way the process can stop early on // ############### await assertWalletBalance({ ledgerId, fromAccount, amount: requestAmount, fee }); // ############### // The request is about to be processed by transferring the amount via the ICP ledger. // We update the status beforehand. Since the function is atomic, a failed transfer reverts everything. // This avoids a case where the transfer succeeds but the status isn't updated — even if unlikely. // This is for demo only. In production, proper error handling and bookkeeping would be required. // ############### setRequestProcessed({ key, version, data }); // ############### // Transfer from wallet to satellite. // ############### const toAccount: IcrcLedgerDid.Account = { owner: id(), subaccount: [] }; await transferIcpFromWallet({ ledgerId, fromAccount, toAccount, amount: requestAmount, fee }); console.log(`${requestAmount} ICP transferred to Satellite 🥳`); }});
6390+
// src/satellite/index.tsimport { Principal } from "@icp-sdk/core/principal";import { type AssertSetDoc, defineAssert, defineHook, type OnSetDoc} from "@junobuild/functions";import { type Account, encodeIcrcAccount} from "@junobuild/functions/canisters/ledger/icrc";import { id } from "@junobuild/functions/ic-cdk";import { decodeDocData } from "@junobuild/functions/sdk";import { COLLECTION_REQUEST, ICP_LEDGER_ID } from "../constants/app.constants";import { RequestData, RequestDataSchema } from "../types/request";import { assertWalletBalance, setRequestProcessed, transferIcpFromWallet} from "./services";export const assertSetDoc = defineAssert<AssertSetDoc>({ collections: [COLLECTION_REQUEST], assert: (context) => { // We validate that the data submitted for create or update matches the expected schema. const person = decodeDocData<RequestData>(context.data.data.proposed.data); RequestDataSchema.parse(person); }});export const onSetDoc = defineHook<OnSetDoc>({ collections: [COLLECTION_REQUEST], run: async (context) => { // ############### // Init data // ############### const { data: { key, data: { after: { version } } } } = context; const data = decodeDocData<RequestData>(context.data.data.after.data); const { amount: requestAmount, fee } = data; const ledgerId = ICP_LEDGER_ID; const fromAccount: Account = { owner: Principal.fromUint8Array(context.caller) }; // ############### // Check current account balance. This way the process can stop early on // ############### await assertWalletBalance({ ledgerId, fromAccount, amount: requestAmount, fee }); // ############### // The request is about to be processed by transferring the amount via the ICP ledger. // We update the status beforehand. Since the function is atomic, a failed transfer reverts everything. // This avoids a case where the transfer succeeds but the status isn't updated — even if unlikely. // This is for demo only. In production, proper error handling and bookkeeping would be required. // ############### setRequestProcessed({ key, version, data }); // ############### // Transfer from wallet to satellite. // ############### const toAccount: Account = { owner: id() }; await transferIcpFromWallet({ ledgerId, fromAccount, toAccount, amount: requestAmount, fee }); console.log(`${requestAmount} ICP transferred to Satellite 🥳`); }});
63916391
```
63926392

63936393
```
6394-
// src/satellite/services.tsexport const assertWalletBalance = async ({ ledgerId, fromAccount, amount, fee}: { ledgerId: Principal; fromAccount: IcrcLedgerDid.Account; amount: bigint; fee: bigint | undefined;}) => { const { icrc1BalanceOf } = new IcrcLedgerCanister({ canisterId: ledgerId }); const balance = await icrc1BalanceOf({ account: fromAccount }); const total = amount + (fee ?? IC_TRANSACTION_FEE_ICP); if (balance < total) { const encodedAccountText = encodeIcrcAccount({ owner: fromAccount.owner, subaccount: fromNullable(fromAccount.subaccount) }); throw new Error( `Balance ${balance} is smaller than ${total} for account ${encodedAccountText}.` ); }};export const transferIcpFromWallet = async ({ ledgerId, fromAccount, amount, fee, toAccount}: { ledgerId: Principal; fromAccount: IcrcLedgerDid.Account; toAccount: IcrcLedgerDid.Account; amount: bigint; fee: bigint | undefined;}): Promise<IcrcLedgerDid.Tokens> => { const args: IcrcLedgerDid.TransferFromArgs = { amount, from: fromAccount, to: toAccount, created_at_time: toNullable(), fee: toNullable(fee), memo: toNullable(), spender_subaccount: toNullable() }; const { icrc2TransferFrom } = new IcrcLedgerCanister({ canisterId: ledgerId }); const result = await icrc2TransferFrom({ args }); if ("Err" in result) { throw new Error( `Failed to transfer ICP from wallet: ${JSON.stringify(result, jsonReplacer)}` ); } return result.Ok;};export const setRequestProcessed = ({ key, data: currentData, version: originalVersion}: { key: string; data: RequestData; version: bigint | undefined;}) => { const updateData: RequestData = { ...currentData, status: "processed" }; const data = encodeDocData(updateData); const doc: SetDoc = { data, version: originalVersion }; setDocStore({ caller: id(), collection: COLLECTION_REQUEST, doc, key });};
6394+
// src/satellite/services.tsimport { Principal } from "@icp-sdk/core/principal";import { IcrcLedgerCanister, type Account, type TransferFromArgs, type Tokens} from "@junobuild/functions/canisters/ledger/icrc";export const assertWalletBalance = async ({ ledgerId, fromAccount, amount, fee}: { ledgerId: Principal; fromAccount: Account; amount: bigint; fee: bigint | undefined;}) => { const { icrc1BalanceOf } = new IcrcLedgerCanister({ canisterId: ledgerId }); const balance = await icrc1BalanceOf({ account: fromAccount }); const total = amount + (fee ?? 10_000n); if (balance < total) { const encodedAccountText = encodeIcrcAccount(fromAccount); throw new Error( `Balance ${balance} is smaller than ${total} for account ${encodedAccountText}.` ); }};export const transferIcpFromWallet = async ({ ledgerId, fromAccount, toAccount, amount, fee}: { ledgerId: Principal; fromAccount: Account; toAccount: Account; amount: bigint; fee: bigint | undefined;}): Promise<Tokens> => { const args: TransferFromArgs = { amount, from: fromAccount, to: toAccount, fee }; const { icrc2TransferFrom } = new IcrcLedgerCanister({ canisterId: ledgerId }); const result = await icrc2TransferFrom({ args }); if ("Err" in result) { throw new Error( `Failed to transfer ICP from wallet: ${JSON.stringify(result, jsonReplacer)}` ); } return result.Ok;};export const setRequestProcessed = ({ key, data: currentData, version: originalVersion}: { key: string; data: RequestData; version: bigint | undefined;}) => { const updateData: RequestData = { ...currentData, status: "processed" }; const data = encodeDocData(updateData); const doc: SetDoc = { data, version: originalVersion }; setDocStore({ caller: id(), collection: COLLECTION_REQUEST, doc, key });};
63956395
```
63966396

63976397
**Explanation:**

docs/examples/functions/typescript/canister-calls.mdx

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,10 @@ import {
8686
defineHook,
8787
type OnSetDoc
8888
} from "@junobuild/functions";
89-
import { IcrcLedgerDid } from "@junobuild/functions/canisters/ledger/icrc";
89+
import {
90+
type Account,
91+
encodeIcrcAccount
92+
} from "@junobuild/functions/canisters/ledger/icrc";
9093
import { id } from "@junobuild/functions/ic-cdk";
9194
import { decodeDocData } from "@junobuild/functions/sdk";
9295
import { COLLECTION_REQUEST, ICP_LEDGER_ID } from "../constants/app.constants";
@@ -129,9 +132,8 @@ export const onSetDoc = defineHook<OnSetDoc>({
129132

130133
const ledgerId = ICP_LEDGER_ID;
131134

132-
const fromAccount: IcrcLedgerDid.Account = {
133-
owner: Principal.fromUint8Array(context.caller),
134-
subaccount: []
135+
const fromAccount: Account = {
136+
owner: Principal.fromUint8Array(context.caller)
135137
};
136138

137139
// ###############
@@ -161,9 +163,8 @@ export const onSetDoc = defineHook<OnSetDoc>({
161163
// Transfer from wallet to satellite.
162164
// ###############
163165

164-
const toAccount: IcrcLedgerDid.Account = {
165-
owner: id(),
166-
subaccount: []
166+
const toAccount: Account = {
167+
owner: id()
167168
};
168169

169170
await transferIcpFromWallet({
@@ -181,30 +182,33 @@ export const onSetDoc = defineHook<OnSetDoc>({
181182

182183
```ts
183184
// src/satellite/services.ts
185+
import { Principal } from "@icp-sdk/core/principal";
186+
import {
187+
IcrcLedgerCanister,
188+
type Account,
189+
type TransferFromArgs,
190+
type Tokens
191+
} from "@junobuild/functions/canisters/ledger/icrc";
192+
184193
export const assertWalletBalance = async ({
185194
ledgerId,
186195
fromAccount,
187196
amount,
188197
fee
189198
}: {
190199
ledgerId: Principal;
191-
fromAccount: IcrcLedgerDid.Account;
200+
fromAccount: Account;
192201
amount: bigint;
193202
fee: bigint | undefined;
194203
}) => {
195204
const { icrc1BalanceOf } = new IcrcLedgerCanister({ canisterId: ledgerId });
196205

197-
const balance = await icrc1BalanceOf({
198-
account: fromAccount
199-
});
206+
const balance = await icrc1BalanceOf({ account: fromAccount });
200207

201-
const total = amount + (fee ?? IC_TRANSACTION_FEE_ICP);
208+
const total = amount + (fee ?? 10_000n);
202209

203210
if (balance < total) {
204-
const encodedAccountText = encodeIcrcAccount({
205-
owner: fromAccount.owner,
206-
subaccount: fromNullable(fromAccount.subaccount)
207-
});
211+
const encodedAccountText = encodeIcrcAccount(fromAccount);
208212

209213
throw new Error(
210214
`Balance ${balance} is smaller than ${total} for account ${encodedAccountText}.`
@@ -215,24 +219,21 @@ export const assertWalletBalance = async ({
215219
export const transferIcpFromWallet = async ({
216220
ledgerId,
217221
fromAccount,
222+
toAccount,
218223
amount,
219-
fee,
220-
toAccount
224+
fee
221225
}: {
222226
ledgerId: Principal;
223-
fromAccount: IcrcLedgerDid.Account;
224-
toAccount: IcrcLedgerDid.Account;
227+
fromAccount: Account;
228+
toAccount: Account;
225229
amount: bigint;
226230
fee: bigint | undefined;
227-
}): Promise<IcrcLedgerDid.Tokens> => {
228-
const args: IcrcLedgerDid.TransferFromArgs = {
231+
}): Promise<Tokens> => {
232+
const args: TransferFromArgs = {
229233
amount,
230234
from: fromAccount,
231235
to: toAccount,
232-
created_at_time: toNullable(),
233-
fee: toNullable(fee),
234-
memo: toNullable(),
235-
spender_subaccount: toNullable()
236+
fee
236237
};
237238

238239
const { icrc2TransferFrom } = new IcrcLedgerCanister({

0 commit comments

Comments
 (0)