CypherClient is the SDK entrypoint. Construction is cheap and synchronous - no RPC calls until you call a method.
import { Connection } from "@solana/web3.js";
import { CypherClient, keypairToWallet } from "@cypher-zk/sdk";
const client = new CypherClient({
connection: new Connection("https://api.devnet.solana.com", "confirmed"),
wallet: keypairToWallet(keypair),
cluster: "devnet",
});Constructor options
connection Connection required
A @solana/web3.js Connection pointed at your target cluster. Pin @solana/web3.js to ^1.95.4 - the SDK is not compatible with v2 or @solana/kit.
wallet Wallet required
An Anchor-compatible wallet. Use keypairToWallet(keypair) for scripts, or pass a browser wallet adapter directly (they already implement the Wallet interface). Use readonlyWallet(pubkey) when the user is not connected.
interface Wallet {
publicKey: PublicKey;
signTransaction<T>(tx: T): Promise<T>;
signAllTransactions<T>(txs: T[]): Promise<T[]>;
}cluster 'devnet' | 'mainnet' | 'localnet' | ClusterConfig
Cluster preset for Arcium-specific configuration. If omitted, the SDK infers from the connection's RPC URL. Pass a full ClusterConfig to override the RPC, Arcium cluster offset, or expected mint.
interface ClusterConfig {
name: "devnet" | "mainnet" | "localnet";
rpc: string;
arciumClusterOffset: number;
expectedMint: PublicKey;
}commitment Commitment
Commitment used by the underlying Anchor provider. Defaults to "confirmed".
programId PublicKey
Override the program ID. Only needed for local redeployments with a fresh keypair. Defaults to the ID from the synced IDL.
tokenProgram PublicKey
The SPL token program owning the accepted mint. Defaults to auto-detection on the first globalState.fetch(). Pass TOKEN_2022_PROGRAM_ID explicitly to skip the detection RPC call.
confirmOptions ConfirmOptions
Extra options forwarded to the Anchor provider (e.g., skipPreflight).
rpcOptions Partial\<BatchOptions\>
Tunables for the SDK's bulk RPC reads — chunking, concurrency, and retry policy. Defaults are conservative enough for free-tier RPCs; bump concurrency on paid plans (Helius, Triton) to speed up large list views.
interface BatchOptions {
chunkSize: number; // default 100 (Solana RPC cap)
concurrency: number; // default 5
retries: number; // default 3
retryBaseMs: number; // default 200 — exponential backoff
commitment?: Commitment;
}const client = new CypherClient({
connection,
wallet,
cluster: "devnet",
rpcOptions: { concurrency: 10 }, // Helius / Triton paid tiers
});Available since v0.8.8.
Namespaces
CypherClient exposes high-level namespaces as read-only properties.
client
actions
placeBet(inputs)
createMarket(inputs)
createMarketMulti(inputs)
cancelMarket(inputs)
withdrawCreatorFunds(inputs)
resolveMarket(inputs)
claimPayout(inputs)
claimRefund(inputs)
flagResolution(inputs)
finalizeResolution(inputs)
adminOverrideResolution(inputs)
markets
fetch(marketId)
fetchByPda(pda)
all()
byCreator(creator)
byState(state)
byIds(ids)
positions
fetch(market, user, betIndex?)
byUser(user)
forMarket(market)
globalState
fetch(opts?)
invalidate()
lpPositions
fetch(market, creator)
byProvider(provider)
marketQuestions
fetch(market)
fetchMany(markets)
events
subscribeAll(callback, opts?)
subscribe(name, callback, opts?)
onMarketCreated(callback, opts?)
onBetPlaced(callback, opts?)
onMarketResolved(callback, opts?)
pollEvents(opts?)
parseLogs(logs)
client.actions
High-level action helpers. Each orchestrates a full flow: validate → encrypt (if needed) → build instructions → send transaction → await Arcium callback → refetch.
client.markets
Account fetch helpers for MarketAccount.
| Method | Description |
|---|---|
fetch(marketId) |
Fetch by numeric ID |
fetchByPda(pda) |
Fetch by public key |
all() |
All markets |
byCreator(creator) |
Filter by creator |
byState(state) |
Filter by state enum value |
byIds(ids) |
Fetch a known list of markets (mixed bigint/number/PublicKey). Routes through the batched RPC layer with chunking, concurrency, and retries. v0.8.8+ |
client.positions
Account fetch helpers for EncryptedPositionAccount.
| Method | Description |
|---|---|
fetch(market, user, betIndex?) |
Single position (defaults betIndex to 0n) |
byUser(user) |
All positions across all markets |
forMarket(market) |
All positions on a single market |
client.globalState
| Method | Description |
|---|---|
fetch(opts?) |
Fetch singleton GlobalState (cached per client instance) |
invalidate() |
Clear cache; next fetch() hits RPC |
Pass { refresh: true } to bypass the cache: client.globalState.fetch({ refresh: true }).
client.lpPositions
| Method | Description |
|---|---|
fetch(market, creator) |
LP position for a market/creator pair |
byProvider(provider) |
All LP positions for a creator |
client.marketQuestions
| Method | Description |
|---|---|
fetch(market) |
Fetch the MarketQuestion PDA for a market (v0.2+ markets only) |
fetchMany(markets) |
Batch-fetch questions for many markets in chunked RPC calls. Returns Map<marketPdaBase58, questionString>. v0.8.8+ |
client.events
| Method | Description |
|---|---|
subscribeAll(callback, opts?) |
WebSocket subscription to all events |
subscribe(name, callback, opts?) |
Typed subscription to a single event name |
onMarketCreated(callback, opts?) |
Convenience typed listener |
onBetPlaced(callback, opts?) |
Convenience typed listener |
onMarketResolved(callback, opts?) |
Convenience typed listener |
onMarketCancelled(callback, opts?) |
Convenience typed listener |
onCreatorWithdrawn(callback, opts?) |
Convenience typed listener |
onPayoutClaimed(callback, opts?) |
Convenience typed listener |
onRefundClaimed(callback, opts?) |
Convenience typed listener |
pollEvents(opts?) |
Poll-based event fetch (no WebSocket required) |
parseLogs(logs) |
Parse raw transaction log strings into typed events |
Wallet helpers
keypairToWallet
Wraps a Keypair as an Anchor-compatible Wallet. Use this for Node scripts, tests, and CLIs.
import { Keypair } from "@solana/web3.js";
import { CypherClient, keypairToWallet } from "@cypher-zk/sdk";
const keypair = Keypair.fromSecretKey(secretKeyBytes);
const client = new CypherClient({
connection,
wallet: keypairToWallet(keypair),
cluster: "devnet",
});readonlyWallet
Creates a wallet that can sign nothing - only fetch operations work. Calling signTransaction or signAllTransactions throws a ReadonlyWalletError. Use it before the user connects their browser wallet.
import { readonlyWallet } from "@cypher-zk/sdk";
const client = new CypherClient({
connection,
wallet: readonlyWallet(someFallbackPublicKey),
cluster: "devnet",
});Detect the read-only case in a mutation handler to show a "connect wallet" prompt instead of leaking the SDK detail:
import { ReadonlyWalletError } from "@cypher-zk/sdk";
placeBet.mutate(inputs, {
onError: (err) => {
if (err instanceof ReadonlyWalletError) {
toast.error("Connect your wallet to place a bet.");
return;
}
toast.error(err.message);
},
});See Errors → ReadonlyWalletError for the full type.