Skip to main content

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.json from solana-keygen).
  • Access to a Solana RPC endpoint and an Overcast backend. For local development the defaults are http://127.0.0.1:8899 (RPC) and http://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:

Amounts, IDs, and other conventions

A few conventions apply across the whole SDK:

  • Amounts are bigint in 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 by getId and 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 from privateKey unless you override them.