Indicative Quotes
Indicative quotes let market makers signal liquidity offchain without committing onchain orders. A maker publishes bid/ask prices and sizes to Velocity's WebSocket endpoint, where they feed:
- UI display: takers see available liquidity before placing orders
- Aggregator routing: Jupiter and other aggregators factor indicative liquidity into routing decisions
- Price discovery: helps establish fair prices in thin markets
When to use indicative quotes:
- Showing liquidity without paying transaction fees for onchain orders
- Market making in lower-volume markets where onchain orders may sit unfilled
- Attracting taker flow with prices tighter than the resting book
- Running a JIT-only strategy while staying visible in the orderbook
Important: indicative quotes are not firm commitments. They signal intent and carry no obligation to fill at the published prices. When a taker actually places an order, the fill happens through the normal JIT auction or DLOB flow.
Setup
Endpoint is provisional. wss://dlob.velocity.exchange/quotes/ws below follows Velocity's <sub>.velocity.exchange hosted-endpoint convention but hasn't been confirmed as the final production URL. Check with the team before hardcoding it.
Construct the IndicativeQuotesSender with the WebSocket endpoint and a signing keypair, then connect:
import { IndicativeQuotesSender } from "@velocity-exchange/sdk";import {
IndicativeQuotesSender,
PRICE_PRECISION,
BASE_PRECISION,
BN,
convertToNumber,
loadKeypair,
} from "@velocity-exchange/sdk";
// Constructor takes the WebSocket endpoint and the signing keypair (for auth)
const keypair = loadKeypair("<KEYPAIR_PATH>");
const quoter = new IndicativeQuotesSender(
"wss://dlob.velocity.exchange/quotes/ws",
keypair
);// Connects to WebSocket, authenticates via challenge-response with the keypair
await quoter.connect();Publishing quotes
Call setQuote to publish or update the indicative quote for a market. The WebSocket server broadcasts it to all subscribers: UI, aggregators, and anything else listening.
quoter.setQuote({
bidPrice: new BN(bid * PRICE_PRECISION.toNumber()),
askPrice: new BN(ask * PRICE_PRECISION.toNumber()),
bidBaseAssetAmount: new BN(bidSize * BASE_PRECISION.toNumber()),
askBaseAssetAmount: new BN(askSize * BASE_PRECISION.toNumber()),
marketIndex,
isOracleOffset: false,
});Complete example: publish quotes that track oracle
This example publishes indicative quotes at a fixed spread around the oracle price, updating every second:
import {
IndicativeQuotesSender,
PRICE_PRECISION,
BASE_PRECISION,
BN,
convertToNumber,
loadKeypair,
} from "@velocity-exchange/sdk";
const marketIndex = 0; // SOL-PERP
const spread = 0.25; // $0.25 on each side
const quoteSize = 10; // 10 SOL per side
const keypair = loadKeypair("<KEYPAIR_PATH>");
const quoter = new IndicativeQuotesSender("wss://dlob.velocity.exchange/quotes/ws", keypair);
await quoter.connect();
// Update quotes periodically
setInterval(() => {
const oracle = velocityClient.getOracleDataForPerpMarket(marketIndex);
const oraclePrice = convertToNumber(oracle.price, PRICE_PRECISION);
const bidPrice = oraclePrice - spread;
const askPrice = oraclePrice + spread;
quoter.setQuote({
bidPrice: new BN(Math.round(bidPrice * PRICE_PRECISION.toNumber())),
askPrice: new BN(Math.round(askPrice * PRICE_PRECISION.toNumber())),
bidBaseAssetAmount: new BN(Math.round(quoteSize * BASE_PRECISION.toNumber())),
askBaseAssetAmount: new BN(Math.round(quoteSize * BASE_PRECISION.toNumber())),
marketIndex,
isOracleOffset: false,
});
console.log(`Published indicative: bid $${bidPrice.toFixed(2)} / ask $${askPrice.toFixed(2)} (${quoteSize} SOL each side)`);
}, 1_000);Using oracle offsets
With isOracleOffset: true, the bidPrice and askPrice are interpreted as offsets from the oracle price rather than absolute prices. This is analogous to oracle offset orders, and the quote floats with the oracle automatically.
const spreadOffset = 0.25; // $0.25 from oracle
quoter.setQuote({
bidPrice: new BN(Math.round(-spreadOffset * PRICE_PRECISION.toNumber())), // oracle - $0.25
askPrice: new BN(Math.round(spreadOffset * PRICE_PRECISION.toNumber())), // oracle + $0.25
bidBaseAssetAmount: new BN(Math.round(10 * BASE_PRECISION.toNumber())),
askBaseAssetAmount: new BN(Math.round(10 * BASE_PRECISION.toNumber())),
marketIndex: 0,
isOracleOffset: true,
});Stopping quotes
To stop publishing quotes for a specific market, send a quote with any field set to null. The sender detects incomplete quotes and deletes the stored quote for that market:
// Stop quoting market 0; setting any required field to null triggers deletion
quoter.setQuote({
bidPrice: null,
askPrice: null,
bidBaseAssetAmount: null,
askBaseAssetAmount: null,
marketIndex: 0,
});How indicative quotes appear in the orderbook
Indicative quotes show up in the L2 orderbook on requests carrying includeIndicative=true. They're merged with DLOB and vAMM liquidity at each price level, giving takers a fuller picture of available depth.
Gotchas
- Indicative ≠ committed: aggregators and UIs display indicative quotes as available liquidity, but there's no onchain enforcement. Quotes that get published but not honored leave takers with slippage and degrade the maker's standing with routing algorithms.
- WebSocket reconnection: if the WebSocket connection drops, the indicative quotes disappear from the orderbook. Implement auto-reconnect and re-publish quotes on reconnection.
- Oracle offset mode simplifies maintenance: with
isOracleOffset: true, an oracle move needs no republish. Only update when changing spread or size. This mirrors oracle offset orders for onchain quoting. - Rate limiting: the DLOB WebSocket server may throttle rapid
setQuoteupdates. Publishing every second is sufficient for most use cases. - Null fields to clear: sending
nullfor price/size fields removes the quote. This matters for graceful shutdown: clear indicative quotes before stopping the bot to avoid showing phantom liquidity.
Related
- DLOB MM: Resting onchain orders (committed liquidity)
- Orderbook & Matching: How indicative vs committed liquidity works in the L2 API
- JIT-only MM: Pair indicative quotes with JIT fills
- Bot Architecture: Graceful shutdown and reconnection patterns