Repository Public
1/**2 * Venue adapter contract (docs/v4/DERIVATIVES-ARCHITECTURE.md, "venue.ts"). Interfaces only: adapters live in `venues/<venue>/`.3 * Adapters BUILD and VERIFY actions; they never hold a key. Signing is injected.4 */5import type { DecStr } from './decimal.ts';6import type { AccountState, Book, Candle, Fill, FundingPayment, Instrument, Order, OrderRequest, Position, PublicTrade, Ticker, VenueId } from './models.ts';78export interface Capabilities { marketData: boolean; account: boolean; orders: boolean; orderTypes: OrderRequest['type'][];9 tif: OrderRequest['tif'][]; modify: boolean; leverage: boolean; marginModes: ('cross' | 'isolated')[]; subaccounts: boolean;10 testnet: boolean; stream: boolean; notes: string[] }1112export interface VenueAdapter {13 readonly id: VenueId; readonly network: 'mainnet' | 'testnet'; readonly capabilities: Capabilities;14 instruments(): Promise<Instrument[]>;15 tickers(): Promise<Ticker[]>;16 book(symbol: string, depth?: number): Promise<Book>;17 trades(symbol: string, limit?: number): Promise<PublicTrade[]>;18 candles(symbol: string, interval: '1m' | '5m' | '15m' | '1h' | '4h' | '1d', o: { start?: number; end?: number; limit?: number }): Promise<Candle[]>;19 fundingHistory(symbol: string, o: { start: number; end?: number }): Promise<{ ts: number; rate: DecStr; premium: DecStr | null }[]>;20 // account (read): `account` is the venue's account identifier (an EVM address on Hyperliquid/GMX, a dydx1… address + subaccount on dYdX)21 account(account: string): Promise<AccountState>;22 positions(account: string): Promise<Position[]>;23 openOrders(account: string): Promise<Order[]>;24 orderHistory(account: string, o?: { limit?: number }): Promise<Order[]>;25 fills(account: string, o?: { start?: number; limit?: number }): Promise<Fill[]>;26 funding(account: string, o?: { start?: number }): Promise<FundingPayment[]>;27 /** subscribe to live data; returns an unsubscribe function. Reconnects by itself and reports gaps through onStatus. */28 stream?(sub: { type: 'book' | 'trades' | 'ticker'; symbol: string } | { type: 'account'; account: string },29 on: (ev: unknown) => void, onStatus: (s: 'connected' | 'reconnecting' | 'stale') => void): () => void;30 // trading: adapters BUILD and VERIFY actions; they never hold a key. Signing is injected.31 trading?: VenueTrading;32}3334export interface SignRequest { venue: VenueId; network: 'mainnet' | 'testnet'; kind: string; payload: unknown } // typed per venue3536export interface VenueTrading {37 /** canonical, venue-ready action for an order + the exact bytes/typed data to sign; pure, no network */38 buildOrder(req: OrderRequest, ctx: { instrument: Instrument; nonce: number }): { action: unknown; sign: SignRequest };39 buildCancel(o: { instrument: Instrument; venueOrderId?: string; clientId?: string; nonce: number }): { action: unknown; sign: SignRequest };40 /** independent re-derivation used by the signer: what does this signed payload do? throws if it is not exactly an order/cancel */41 describe(sign: SignRequest): { kind: 'order' | 'cancel' | 'leverage' | 'approve_agent' | 'other'; orders?: OrderRequest[]; detail: Record<string, unknown> };42 submit(action: unknown, signature: unknown, nonce: number): Promise<{ accepted: boolean; venueOrderIds: string[]; error: string | null; raw: unknown }>;43}4445// names used by the venue adapters46export type StreamSub = { type: 'book' | 'trades' | 'ticker'; symbol: string } | { type: 'account'; account: string };47export type StreamStatus = 'connected' | 'reconnecting' | 'stale';48