@stacks/rpc-client
v2.0.1
Published
Typed JavaScript/TypeScript client for Stacks core RPC endpoints.
Keywords
Readme
@stacks/rpc-client
Typed JavaScript/TypeScript client for the Stacks core RPC API.
This package is generated from the Stacks core OpenAPI definition and ships as ESM-first with CJS compatibility.
Install
npm install @stacks/rpc-clientRuntime and Development Targets
- Runtime support: Node
>=22 - Local development baseline: Node
24
Quick Start
import { createCoreRpcClient } from "@stacks/rpc-client";
const client = createCoreRpcClient({
baseUrl: "http://localhost:20443",
authToken: process.env.STACKS_RPC_AUTH_TOKEN,
});
const info = await client.request("GET", "/v2/info");
console.log(info.stacks_tip_height);Usage with @stacks/network
createCoreRpcClient accepts a @stacks/network instance directly, so you can
reuse an existing network configuration without duplicating the base URL or
custom fetch:
import { createCoreRpcClient } from "@stacks/rpc-client";
import { STACKS_TESTNET } from "@stacks/network";
const client = createCoreRpcClient(STACKS_TESTNET);
const info = await client.request("GET", "/v2/info");A second overrides argument lets you layer on options like authToken while
still deriving everything else from the network:
const client = createCoreRpcClient(STACKS_TESTNET, {
authToken: process.env.STACKS_RPC_AUTH_TOKEN,
});Custom Headers
Use the headers option to attach an API key or any other custom headers to
every outgoing request:
const client = createCoreRpcClient({
baseUrl: "https://api.hiro.so",
headers: {
"x-api-key": process.env.STACKS_API_KEY,
},
});This also works alongside @stacks/network:
const client = createCoreRpcClient(STACKS_TESTNET, {
headers: { "x-api-key": process.env.STACKS_API_KEY },
});Example RPC Calls
Every call through client.request() is fully typed — the path autocompletes
and the return type matches the OpenAPI schema.
Get node info
const info = await client.request("GET", "/v2/info");
// info is typed as NodeInfo
console.log(info.stacks_tip_height, info.burn_block_height);Get PoX details
const pox = await client.request("GET", "/v2/pox");
// pox is typed as PoxInfo
console.log(pox.reward_cycle_length, pox.next_cycle);Fetch account data
const account = await client.request("GET", "/v2/accounts/{address}", {
params: { path: { address: "SP2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKNRV9EJ7" } },
});
// account is typed as AccountData
console.log(account.balance, account.nonce);Call a read-only contract function (authenticated)
const result = await client.request(
"POST",
"/v2/contracts/call-read/{deployer_address}/{contract_name}/{function_name}",
{
params: {
path: {
deployer_address: "SP2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKNRV9EJ7",
contract_name: "my-contract",
function_name: "get-balance",
},
},
body: { sender: "SP2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKNRV9EJ7", arguments: [] },
},
);
// result is typed as ReadOnlyFunctionResult
console.log(result.okay, result.result);Using Exported Types
All response schemas are re-exported as named types so you can annotate your own code without reaching into the generated schema:
import type { NodeInfo, PoxInfo, AccountData } from "@stacks/rpc-client";
function summarize(info: NodeInfo, pox: PoxInfo): string {
return `tip=${info.stacks_tip_height} cycle=${pox.reward_cycle_id}`;
}You can also derive the response type for any endpoint using CoreRpcResponse:
import type { CoreRpcResponse } from "@stacks/rpc-client";
type PoxResponse = CoreRpcResponse<"GET", "/v2/pox">;Error Handling
Failed requests throw a CoreRpcError with structured metadata:
import { CoreRpcError, createCoreRpcClient } from "@stacks/rpc-client";
const client = createCoreRpcClient();
try {
await client.request("POST", "/v3/block_proposal", { body: {} });
} catch (error) {
if (error instanceof CoreRpcError) {
console.error(error.status); // HTTP status code
console.error(error.url); // request URL
console.error(error.details); // parsed error body
}
}Auth Behavior
authToken is attached to the authorization header only for RPC endpoints
that declare rpcAuth in the spec.
Raw Client Access
When you need full control over the response (headers, streaming, middleware),
use client.raw — the underlying openapi-fetch client:
const { data, error, response } = await client.raw.GET("/v2/info");
console.log(response.headers.get("x-request-id"));Usage (CJS)
const { createCoreRpcClient } = require("@stacks/rpc-client");
const client = createCoreRpcClient({
baseUrl: "http://localhost:20443",
});
client.request("GET", "/v2/info").then(console.log);Generation Workflow
Types are generated by openapi-typescript from a pinned upstream URL:
https://raw.githubusercontent.com/stacks-network/stacks-core/d7f37b5388b490427d6705e17a9b016aee8fccb0/docs/rpc/openapi.yaml
Commands:
npm run generate
npm run generate:checkgenerate:check fails when checked-in generated output is stale.
Scripts
npm run typecheck
npm test
npm run build
npm pack --dry-runGenerator Alternatives
openapi-typescript+openapi-fetch(current choice): minimal runtime, high type safety, flexible wrapper layer.- OpenAPI Generator
typescript-fetch: fuller generated SDK surface, but heavier and more verbose output. - Orval: useful when you want opinionated API client generation (often frontend-focused workflows).
