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
-
Configure
OVERCAST_KEYPAIR,SOLANA_RPC_URL,OVERCAST_BACKEND_URL(configuration). -
overcast assets— find the cash mint (e.g. USDC). -
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.
-
Run it:
overcast quote
Built-in Black-Scholes pricer
With no webhook configured, quote prices each RFQ itself:
| Flag | Default | Meaning |
|---|---|---|
-s, --spread | 0.02 | Your edge over fair value, as a fraction |
--vol | 0.8 | Annualized implied volatility fallback |
--rate | 0 | Annualized 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.