

Client library to connect your app with forge powered blockchain node, all requests are sent over http/https, can be used in both Node.js and browser environment.
A GraphQLClient instance mainly supports 5 groups of methods that saves you time when read/write data from/to blockchain.
queries: query block/transaction/account/asset/chain/node data form the blockchain
mutations: send transaction to the blockchain, sendTx, all transactions should be signed before sending out to the blockchain
subscriptions: listen to changes of any data on the blockchain
senders: shortcut methods that takes a wallet and a tx object, then do the signing, and sending
encoders: shortcut methods that takes a wallet and a tx object, encode the transaction for later signing, used internally by senders
Table of Contents
Install
npm i @ocap/client -S
# OR
bun install @ocap/client
Usage
const Mcrypto = require('@ocap/mcrypto');
const GraphQLClient = require('@ocap/client');
const { fromRandom, WalletType } = require('@ocap/wallet');
const { hexToBytes } = require('@ocap/util');
const client = new GraphQLClient('http://localhost:8210/api');
console.log({
queries: client.getQueries(),
subscriptions: client.getSubscriptions(),
mutations: client.getMutations(),
senders: client.getTxSendMethods(),
encoders: client.getTxEncodeMethods(),
});
(async () => {
const chainInfo = await client.getChainInfo();
const forgeState = await client.getForgeState();
const block = await client.getBlock({ height: 2 });
console.log('getChainInfo', chainInfo);
console.log('getForgeState', forgeState);
console.log('getBlock', block);
const wallet = fromRandom(
WalletType({
role: Mcrypto.types.RoleType.ROLE_ACCOUNT,
pk: Mcrypto.types.KeyType.SECP256K1,
hash: Mcrypto.types.HashType.SHA3,
})
);
const hash = await client.declare({
moniker: 'username',
wallet,
});
console.log(hash);
})();
Subscriptions
subscribe / unsubscribe pull in @arcblock/ws (phoenix + ws), which is ~68 KB after minification. To keep the default browser bundle small, the websocket client is shipped as an optional install:
- Node /
@ocap/client/legacy — auto-installed by the constructor, call client.subscribe(topic, cb) directly.
- Browser — the default entry's
subscribe / unsubscribe throw until you install them explicitly:
import Client from '@ocap/client';
import { install as installSubscribe } from '@ocap/client/subscribe';
const client = new Client(endpoint);
installSubscribe(client);
client.subscribe('tx.create', (tx) => console.log(tx));
Apps that never need subscriptions pay zero bytes for this code path.
Subpath Exports
The package ships three subpath entries in addition to the default:
@ocap/client | Full CBOR-only client (queries, mutations, senders, encoders) | ~503 KB minified |
@ocap/client/encode | Tree-shakable encodeTx / decodeTx helpers — no GraphQL, no websockets | ~179 KB minified |
@ocap/client/subscribe | Optional websocket installer, see Subscriptions | ~68 KB minified |
@ocap/client/legacy | Protobuf wire-encoding client for chain nodes that still decode the legacy path | pulls in google-protobuf (~300 KB) |
All subpaths require a bundler that honors the exports field (webpack 5, Vite, esbuild, Rollup, Bun). For webpack 4 you must enable resolve.exportsFields.
Migration Notes
options.encoding — the default entry is CBOR-only. Passing new Client(endpoint, true, { encoding: 'protobuf' }) throws immediately. Import from @ocap/client/legacy when you need the protobuf path.
- Browser
subscribe / unsubscribe — now throw SUBSCRIBE_NOT_INSTALLED by default; see Subscriptions. Node and /legacy behavior is unchanged.
- Client-side factory validation —
createAssetFactory no longer runs isValidFactory before sending. Invalid factories surface as a chain-side RPC error instead of a local throw.
setGasPayer parsing — the GraphQL AST parse was replaced with a bounded regex. Queries with $tx variables (instead of the literal form the built-in sendTx uses) will silently skip the gas-payer headers.
Examples
Debugging
- If you are in Node.js:
DEBUG=@ocap/client node script.js
- If you are in browser:
localStorage.setItem('DEBUG', '@ocap/client')
Documentation
- Query arguments and response structure can be found here: QUERIES.md
- Complete method list can be found here: README.md