Skip to main content

RFQ Quoting with the CLI

overcast quote is a complete RFQ quoter in one command: it connects to the RFQ channel as TAKER, prices every incoming RFQ, and submits signed quotes until you hit Ctrl-C. You choose the brain — the built-in Black-Scholes pricer, or your own strategy behind a local webhook.

Setup checklist

  1. Configure OVERCAST_KEYPAIR, SOLANA_RPC_URL, OVERCAST_BACKEND_URL (configuration).

  2. overcast assets — find the cash mint (e.g. USDC).

  3. Hold that SPL token in your wallet, then fund your vault:

    overcast deposit --mint <cash-mint> --amount <n>
    overcast balance --mint <cash-mint>

    Premiums are paid from the vault. A quoter that connects but can't fill is almost always one that skipped this step.

  4. Run it:

    overcast quote

Built-in Black-Scholes pricer

With no webhook configured, quote prices each RFQ itself:

FlagDefaultMeaning
-s, --spread0.02Your edge over fair value, as a fraction
--vol0.8Annualized implied volatility fallback
--rate0Annualized risk-free rate

How it prices: it identifies the single cash (stablecoin) leg — cash settlement means a covered call, cash collateral means a cash-secured put — derives the strike from the two amounts, pulls spot from CoinGecko (falling back to the backend's last known price), uses the asset's implied volatility when the backend provides one (else --vol), computes Black-Scholes fair value, and quotes it plus your spread. RFQs it can't price (no single cash leg, no spot price, already expired) are skipped.

Bring your own strategy: the webhook

To keep your pricing logic in your own process — any language, any framework — point quote at a local HTTP endpoint:

overcast quote --webhook-url http://127.0.0.1:9000/quote --webhook-timeout 5000

(OVERCAST_QUOTE_WEBHOOK_URL works as the env-var equivalent.)

The CLI POSTs every RFQ lifecycle event to your endpoint as a JSON envelope:

{
"type": "newRfq",
"timestamp": 1767225600000,
"maker": "<your quoter public key>",
"data": { "rfqId": "…", "details": { "…": "curated partial details" } }
}

with headers X-Overcast-Event and X-Overcast-Timestamp. Event types are newRfq, newQuote, quoteAccepted, rfqCancelled, rfqExpired, and error — but only newRfq is actionable. Your reply to it drives the quote:

{ "action": "quote", "premium": { "premiumAsset": "<mint>", "premiumAmount": "12500000" } }

or

{ "action": "skip", "reason": "outside my risk limits" }

Amounts are decimal strings in native units. A 204, a non-2xx status, a timeout, or malformed JSON all safely count as skip. Your endpoint supplies only the premium — the CLI remains authoritative over every other term, builds the offer, and signs it.

A machine-readable contract lives in the repo under packages/overcast-cli/webhook-contract/ — TypeScript declarations (overcast-quote-webhook.d.ts), a JSON schema, and a runnable example handler (example/webhook.mjs). A minimal Express handler:

app.post("/quote", (req, res) => {
const event = req.body;
if (event.type !== "newRfq") return res.status(204).end();

const premium = myPricer(event.data.details);
if (!premium) return res.json({ action: "skip" });

res.json({ action: "quote", premium });
});

When you outgrow the CLI

The webhook gives you custom pricing; for custom everything (inventory management, hedging, multi-venue) build directly on the SDK — the entire loop the CLI runs is about forty lines.