Getting Started
This guide takes you from a fresh checkout to a running OvercastApp that can
read the market, move funds in and out of your escrow vault, and talk to the
RFQ channel.
Prerequisites
- Node.js ≥ 20 and pnpm (the repo pins
pnpm@10.26.0). - A Solana wallet keypair (e.g. a standard
id.jsonfromsolana-keygen). - Access to a Solana RPC endpoint and an Overcast backend. For local
development the defaults are
http://127.0.0.1:8899(RPC) andhttp://127.0.0.1:3000(backend).
Install and build
The packages are not published to npm yet, so you build from source. The SDK
repo expects the on-chain program repo overcast-solana as a sibling
directory:
code/
├── overcast-solana/ # Anchor program + @overcast/solana-program
└── overcast-sdk/ # this repo
Build the program package first (anchor build + its build:ts in
overcast-solana), then:
cd overcast-sdk
pnpm install
pnpm -r run build
To use the SDK from your own project, depend on the built workspace packages
(e.g. via pnpm link or a file:/link: reference to
packages/overcast-core and packages/solana-client).
Create an OvercastApp
OvercastApp is the single entry point to the SDK. You hand it a
chain-specific factory — SolanaFactory — and get back one object that carries
every capability:
import { OvercastApp } from "@overcast/core";
import { SolanaFactory } from "@overcast/solana-client";
const factory = new SolanaFactory({
rpcUrl: "http://127.0.0.1:8899", // Solana RPC
backend: "http://127.0.0.1:3000", // Overcast backend (REST + RFQ socket)
privateKey: process.env.OVERCAST_KEYPAIR, // path, base58, or JSON byte array
});
const app = await OvercastApp.create({ factory });
console.log("wallet:", app.publicKey);
privateKey accepts the same formats everywhere in the SDK and CLI: a raw
byte array, the contents of a Solana id.json, or a base58-encoded secret
key. Omit it entirely for a read-only app — everything works except
signing (writes and RFQ).
Make your first calls
Read the market
// Curated, off-chain views from the backend:
const assets = await app.api.listAssets();
const options = await app.api.listOptions({});
// Direct on-chain reads:
const balance = await app.chain.balance(app.publicKey, assets[0].address);
Fund your escrow vault
All protocol payments (premiums, collateral, settlement) flow through your on-chain escrow vault, not your wallet directly. Deposit before you trade:
const { hash } = await app.chain.deposit({
depositor: app.publicKey,
mint: cashMint, // an allowlisted asset from app.api.listAssets()
amount: 1_000_000_000n, // native units, as bigint
});
console.log("deposited, tx:", hash);
Withdrawing is symmetric:
await app.chain.withdraw({
withdrawer: app.publicKey,
mint: cashMint,
amount: 500_000_000n,
});
Connect to the RFQ channel
The RFQ socket is lazy — it only connects the first time you touch app.rfq
(and requires a signer):
const rfq = app.rfq;
await rfq.registerRole("MAKER"); // or "TAKER"
rfq.onNewQuote = (quote) => console.log("quote received:", quote.quoteId);
const { rfqId } = await rfq.createRfq({
creator: app.publicKey,
request: { details }, // partial OptionDetails — everything except the premium
side: "MAKER",
});
What details looks like, who quotes whom, and how a quote becomes an
on-chain option is the subject of the next two guides:
- The RFQ lifecycle — the concepts.
- Build an RFQ quoter — the full quoting loop.
Amounts, IDs, and other conventions
A few conventions apply across the whole SDK:
- Amounts are
bigintin native units (the asset's smallest unit) in all canonical types. On the wire (socket + REST) they travel as decimal strings; the SDK converts for you. Helpers:parseUnits,formatUnits,toNativeAmount,toDisplayAmount. - IDs are base58 strings (
Id). Offers and options are content-addressed: their ID is the sha256 of a canonical byte encoding, computed bygetIdand byte-for-byte identical to the on-chain program's hashing. - Two signers exist. The chain signer signs Solana transactions; the
protocol signer (
Ed25519ProtocolSigner) signs offer IDs for the RFQ flow. Both are derived fromprivateKeyunless you override them.