Skip to content
IC Reactor

TypeScript Demo

Pure TypeScript example showing IC Reactor without React, for Node.js or other non-React environments.

  • Reactor usage without React hooks
  • Direct callMethod for queries and mutations
  • getQueryOptions() for manual query execution
  • Works in Node.js, Deno, or any JavaScript runtime
  • Command-line interface example
src/main.ts
import { ClientManager, Reactor } from "@ic-reactor/core"
import { QueryClient } from "@tanstack/query-core"
import { ledgerIdlFactory } from "./declarations/ledger"
import type { Ledger } from "./declarations/ledger.type"
const queryClient = new QueryClient()
const clientManager = new ClientManager({
agentOptions: { host: "https://ic0.app" },
queryClient,
})
const ledgerReactor = new Reactor<Ledger>({
clientManager,
canisterId: "ryjl3-tyaaa-aaaaa-aaaba-cai",
idlFactory: ledgerIdlFactory,
name: "Ledger",
})
async function callLedger() {
// Query method — fetchQuery goes through the cache
const name = await ledgerReactor.fetchQuery({ functionName: "icrc1_name" })
console.log("Token name:", name)
// Query with args — callMethod bypasses the cache
const balance = await ledgerReactor.callMethod({
functionName: "icrc1_balance_of",
args: [{ owner: principal, subaccount: [] }],
})
console.log("Balance:", balance)
// Update method (mutation)
const blockIndex = await ledgerReactor.callMethod({
functionName: "icrc1_transfer",
args: [
{
to: { owner: recipientPrincipal, subaccount: [] },
amount: 100_000_000n, // 1 ICP in e8s
fee: [],
memo: [],
created_at_time: [],
from_subaccount: [],
},
],
})
console.log("Transfer block index:", blockIndex)
// Mark every cached query for this canister stale after a write: mounted
// queries refetch, but the entries stay, and fetchQuery (cache-first) still
// returns them until they are refetched
await ledgerReactor.invalidateQueries()
}
async function fetchName() {
// Get query options for manual execution
const queryOptions = ledgerReactor.getQueryOptions({
functionName: "icrc1_name",
})
// Execute with QueryClient. The wrapper runs the fetch again when a sign-in
// or sign-out overtakes it, instead of returning the previous principal's data
const result = await ledgerReactor.clientManager.fetchAcrossIdentitySwitch(
() => queryClient.fetchQuery(queryOptions)
)
// Or prefetch for later
await queryClient.prefetchQuery(queryOptions)
}
Terminal window
pnpm add @ic-reactor/core @icp-sdk/core @tanstack/query-core