Skip to content
IC Reactor

@ic-reactor/core

@ic-reactor/core is the client of ic-reactor 4. It sits on a module that candid-core-cli gen writes from a .did file, and it has no React in it. It gives you:

  • a client with query keys that carry the caller, TanStack Query options for reads and writes, and network resolution;
  • one error type that says whether a call may have executed;
  • strict helpers for token amounts;
  • a test client over an in-memory replica, in a separate entry.

It works in a browser, in Node and on a server. For React, add @ic-reactor/react. For Vite, add @ic-reactor/vite-plugin.

Terminal window
npm install @ic-reactor/core@beta @icp-sdk/core @tanstack/query-core
npm install --save-exact @candid-core/[email protected]
npm install @icp-sdk/auth # for Internet Identity

ic-reactor 4 is published under npm’s beta dist-tag, and latest is still 3.x until 4.0 GA. Install it as @ic-reactor/core@beta.

The generator is a separate dev dependency, pinned to the version that pairs with @candid-core/schema:

Terminal window
npm install --save-dev --save-exact @candid-core/[email protected]

See Getting started for the first read and write.

Node >=18.

Peer Range
@candid-core/schema exactly 0.3.0: the module candid-core-cli gen writes imports it
@icp-sdk/core ^6.1.0
@tanstack/query-core ^5.62.0
@noble/curves ^2.2.0, optional: only @ic-reactor/core/testing signs with it, and @icp-sdk/core installs it already

@icp-sdk/auth is not a peer. Install it when users sign in with Internet Identity: its AuthClient is an AuthLike as it is, see Auth.

The entry has 13 names: four at runtime and nine types. The export budget caps it at 13.

Export Kind What it is
createClient runtime Builds a client from a network and a caller. See The client.
isReactorError runtime Tests whether a thrown value is a ReactorError. See Errors.
parseUnits runtime Text to base units: parseUnits("1.5", 8) is 150000000n. See Values and units.
formatUnits runtime Base units to text, without losing digits. See Values and units.
Client type What createClient returns: canister, queryOptions, mutationOptions, queryKey, func, signIn, signOut, caller, authState, subscribe, queryClient, dispose.
ClientOptions type The argument of createClient: a network, and exactly one of identity and auth.
Network type "ic", "local", "env", or { host, rootKey?, name?, fetchRootKey? }.
AuthLike type What auth must be: the shape of an @icp-sdk/auth 10 AuthClient. See Auth.
AuthState type { status, principal }: who calls now, and why.
Canister type What client.canister<Actor>(actor, target) returns: one async method per Candid method.
CanisterTarget type { id } or { name }, each with an optional certified. See Reads.
ReactorError type The error every call rejects with. A type only: there is no class, so test with isReactorError.
ReactorErrorKind type The eight kinds of a ReactorError.

The signatures that matter most:

function createClient(options: ClientOptions): Client
type ClientOptions = {
readonly network: Network
readonly allowEnvConfig?: boolean
readonly fetch?: typeof globalThis.fetch
readonly maxDepth?: number
} & (
| { readonly identity: Identity | "anonymous"; readonly auth?: never }
| { readonly auth: () => AuthLike; readonly identity?: never }
)
function isReactorError(error: unknown): error is ReactorError<unknown>
function parseUnits(
text: string,
decimals: number,
options?: { signed?: boolean }
): bigint
function formatUnits(
value: bigint,
decimals: number,
options?: { maxFractionDigits?: number; minFractionDigits?: number }
): string

createClient does no work until it is used, so the same line runs in a server render and in a browser. It throws a TypeError for options that do not say who calls, say it twice, or name a network or maxDepth it cannot use.

A separate entry with two names. The main entry never imports it, so none of it reaches an app bundle.

Export Kind What it is
createTestClient runtime A real client over an in-memory replica, with mocked canisters and a sign-in a test controls.
TestHandlers type The handlers of a mocked canister, typed from the generated Actor.

See Testing.

The package exports exactly these names, from exactly two subpaths: . and ./testing (and ./package.json). Every name has one import path, so it does not re-export what lives elsewhere:

  • principal, isPrincipal and the Principal type come from @candid-core/schema.
  • skipToken, useQuery, useMutation, useSuspenseQuery, useInfiniteQuery, dehydrate and HydrationBoundary come from TanStack Query (@tanstack/react-query, or @tanstack/query-core outside React).

The tarball carries a guide for people and coding agents, written against this version: node_modules/@ic-reactor/core/llms.txt. It covers setup, values, reads, writes, errors and a complete React example. These pages go into more depth and agree with it.

Coming from 3.x? See Migrating from 3.x.