Skip to main content

SDK Overview

The White Rabbit SDK provides two clients for building on-chain automation:

ClientKey typeWhat it does
WorkspaceClientws_... workspace keyExecute any component standalone
WorkflowClientws_... workspace key + workflowIdTrigger and inspect workflow runs

Install

npm install caller-sdk

WorkspaceClient — execute components

import { WorkspaceClient, ComponentModule } from 'caller-sdk';

const workspace = new WorkspaceClient({ apiKey: process.env.WR_API_KEY! });

.promise() — wait for result

Submits the component and opens an SSE stream. Resolves with typed output on completion — no polling needed.

const result = await workspace
.call(ComponentModule.GET_EVM_ACCOUNT_BALANCE, {
jsonRpcUrl: 'https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY',
tokenAddress: '0x0000000000000000000000000000000000000000',
account: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
})
.promise();

console.log(result.balance); // "1000000000000000000"

.execute() — fire and track

Returns immediately with an execution record. Use this with webhook callbacks or when you'll poll/stream the result separately.

const execution = await workspace
.call(ComponentModule.WAIT_FOR_EVM_TRANSACTION, {
jsonRpcUrl: 'https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY',
transactionHash: '0xabc123...',
})
.execute({
callbackUrl: 'https://your-app.com/webhooks/wr',
callbackSecret: process.env.WR_CALLBACK_SECRET,
});

console.log(execution.id); // track via /executions/:id
console.log(execution.status); // "CREATED" — running asynchronously
info

Without waitForMs, .execute() always returns status: "CREATED". The component runs in the background. Use .promise() for direct results, or set callbackUrl for webhook delivery.


WorkflowClient — run workflows

import { WorkflowClient } from 'caller-sdk';

const workflow = new WorkflowClient({
apiKey: process.env.WR_API_KEY!,
workflowId: process.env.WR_WORKFLOW_ID!,
});

Trigger and wait

const { runId } = await workflow.trigger();
const run = await workflow.waitForRun(runId);

console.log(run.status); // "COMPLETED"
console.log(run.totalUsage); // credits consumed

Stream live progress

const sub = workflow.stream(runId, {
onUpdate(event) {
console.log(event.status, event.output.pendingStageCount);
},
});
// sub.close() to unsubscribe early

ComponentModule enum

All workspace.call() calls take a ComponentModule enum value — not a raw string. This ensures type-safe inputs and outputs:

import { ComponentModule } from 'caller-sdk';

// ✓ Correct — fully typed inputs and outputs
workspace.call(ComponentModule.RANDOM_UUID, {}).promise();

// ✗ Avoid — bypasses type safety
workspace.call('RANDOM_UUID' as ComponentModule, {}).promise();

Browse the full enum → Component Library


Response shape

interface ExecuteComponentResponse {
id: string;
module: string;
status: 'CREATED' | 'EXECUTING' | 'COMPLETED' | 'FAILED';
completed: boolean;
output: unknown | null; // typed by ComponentModule when using .promise()
error: unknown | null;
totalUsage: number;
callback: {
url: string | null;
signed: boolean;
signatureAlgorithm: 'hmac-sha256-v1' | null;
headerNames: string[];
deliveredAt: string | null;
lastAttemptAt: string | null;
attemptCount: number;
lastError: unknown | null;
};
createdAt: string;
updatedAt: string;
}

Error handling

Input validation happens synchronously before any network call — no await needed to catch it:

import { WorkspaceClient, ComponentModule, CallerSDKError } from 'caller-sdk';

const workspace = new WorkspaceClient({ apiKey: process.env.WR_API_KEY! });

try {
// Throws synchronously if inputs don't match the schema
const result = await workspace
.call(ComponentModule.BROADCAST_EVM_TRANSACTION, {
jsonRpcUrl: 'https://rpc.example.com',
signedTransaction: '0x...',
})
.promise();
} catch (err) {
if (err instanceof CallerSDKError) {
console.error(err.message); // Human-readable
console.error(err.details); // Zod errors or API error body
}
}

HTTP error codes:

CodeMeaning
400Validation error — check message field
401Missing or invalid API key
402Insufficient credits
429Rate limit exceeded — check Retry-After header
502Upstream microservice unavailable

Next steps