useMarket
Trading Pairs
(params?) => Promise<GetTradingPairsResponse>
Fetch paginated list of trading pairs.Returns:
{ tradingPairs: TradingPair[], page, pageSize, total, totalPages }(symbol: string) => Promise<TradingPair | undefined>
Get a specific trading pair by symbol. Resolves
undefined on a miss (never throws), so guard the result before dereferencing. The hook forwards only symbol; to disambiguate a symbol listed in both SPOT and MARGIN, call sdk.market.getTradingPairBySymbol(symbol, marketType) on the core SDK directly.Market Data
(tradingPairId: string, interval: Interval, params?: GetCandlesticksParams) => Promise<Candlestick[]>
Fetch OHLCV candlestick data for a trading pair.Parameters:
tradingPairId: string - Trading pair UUID (usegetTradingPairBySymbolto get this)interval:"1m" | "5m" | "15m" | "1h" | "4h" | "1d"params?: Optional query parametersstartTime?: number - Unix timestamp in msendTime?: number - Unix timestamp in mslimit?: number - Max candlesticks (default: 350, max: 500)priceType?:"trade" | "mark" | "reference"- price series to chart."trade"(default) is the trade-derived OHLCV series;"mark"is the close-only mark-price series for margin pairs (each candle’s open/high/low/close are the minute’s closing mark, volume0)."mark"on a spot pair returns a400;"reference"is full OHLC of the mark price over each bucket with volume0, for charting markets with little trading; like"mark"it is margin-only (a spot pair returns a400), and a margin pair with no reference history returns no candles
(pairId: string) => Promise<MarketMetadata>
Fetch market metadata for a trading pair including current price, volume, and statistics.Parameters:
pairId: string - Trading pair UUID
MarketMetadata object with market statisticsAll market metadata fields are nullable. Markets without trade history will return null for price and volume fields.Fields (all nullable):lastPrice: string | null- Most recent trade price (null if no trades)lastPriceTimestamp: number | null- Timestamp of last tradehigh24h: string | null- 24-hour high price (null if insufficient data)low24h: string | null- 24-hour low price (null if insufficient data)volume24h: string | null- 24-hour trading volume in base-asset units (null if insufficient data)quoteVolume24h?: string | null- 24-hour trading volume in quote-token (USDC) unitspriceChange24h: string | null- 24-hour price changepriceChangePercent24h: string | null- 24-hour price change percentagemarketInitializationTimestamp: number | null- When market was initialized
Perp Market Data
For margin concepts, see Margin. For full type shapes, see the TypeScript Market reference.(tradingPairId: string) => Promise<PerpMarketConfig>
Static perp config:
minLeverage, maxLeverage, base initial/maintenance margin ratios, fundingIntervalSeconds, riskTiers, liquidationFeeBps, fundingImpactNotional.(tradingPairId: string) => Promise<PerpMarketSummary>
Aggregate snapshot:
markPrice, indexPrice, 24h stats (base-asset volume24h and quote-token quoteVolume24h), openInterest (one-sided LONG base-asset open interest, each contract counted once; alias of openInterestBase), openInterestBase, openInterestNotional (base × mark, in quote units), currentFundingRate, nextFundingTime.(tradingPairId: string) => Promise<MarkPrice>
Live mark price (oracle reference). Returns
{ markPrice, oracleProvider, regime, updatedAt, ... }.(tradingPairId: string) => Promise<IndexPrice>
Live index price with provider components. Returns
{ indexPrice, components: IndexComponent[], updatedAt }.(tradingPairId: string) => Promise<FundingState>
Current and estimated next funding rate plus settlement time.
(tradingPairId: string, params?: ListFundingHistoryParams) => Promise<ListFundingHistoryResponse>
Settled funding history for one pair. Cursor-paginated:
pageSize 1 to 1000 (default 50), pageToken, orderBy (ASC/DESC, default DESC), optional startTime/endTime. There is no page: the SDK rejects one with a ValidationError before sending. Follow nextPageToken until it comes back "".(tradingPairId: string) => Promise<OpenInterest>
Current one-sided LONG open interest (each contract counted once) in base-asset units and notional.
(tradingPairId: string) => Promise<TraderMetrics>
Current public long/short account counts, account shares and ratio, and active-trader aggregates for a margin pair. Accounts are classified by net position across OPEN risk buckets; no account IDs are exposed. Position metrics are suppressed when either side has fewer than five margin accounts; within each active-trader window, all three counts are null if any cohort is below five users, or while the server’s active-trader history does not yet reach back to the window’s start (briefly, after that history is first built). Activity counts include system user IDs on liquidation and ADL fills. Responses may be reused for up to 30 seconds per pair, and ratios/shares are rounded to six decimal places.
(tradingPairId: string, params: GetTradeFlowParams) => Promise<TradeFlow>
Bounded taker buy/sell quote notional and cumulative volume delta. Use
1m, 5m, or 1h buckets and Unix-millisecond startTime (inclusive) / endTime (exclusive); requests are limited to seven days and 2,048 buckets. All executed trades, including liquidation and ADL fills, are included. Empty buckets are omitted and notional remains in the pair’s quote asset; ratios are rounded to six decimal places.(tradingPairId: string, params?: ListLiquidationEventsParams) => Promise<ListLiquidationEventsResponse>
Newest-first public per-fill liquidation history for one margin pair. Optional
startTime is inclusive and endTime is exclusive; page size defaults to 50 and is capped at 1,000. Event rows include wallet, position side, base size, event-time mark, and notional in the quote asset. Use useLiquidationFeed to combine the newest page with live events and recover missed rows after reconnect.(tradingPairId: string, params: GetLiquidationMetricsParams) => Promise<LiquidationMetrics>
UTC-aligned long/short summaries for
1m, 5m, or 1h intervals. Requests cover at most seven days and 2,048 buckets; eventCount counts persisted rows, and mark notionals sum each row at its own event-time mark in quote units.useInstruments
instrument channel, wrapping sdk.ws.instruments(). No authentication is required.
On subscribe the channel delivers a snapshot of every listed market (inactive ones flagged isActive: false), then live change frames. Every frame carries a market’s full current configuration rather than a delta, so the hook keeps one terminal-state entry per trading pair: each live event replaces that market’s entry outright, and each snapshot replaces the whole map — it is the authoritative market set at the moment it was taken.
Three change kinds are emitted today: listing (a market became tradable), delisting (deactivated), and config_change. config_change covers a narrow set of edits — tick size, quantity step, order-size bounds, category, and a perp market’s margin ladder (riskTiers, with changedFields naming risk_tiers). An edit to fees emits nothing. halt and unhalt are defined on InstrumentChangeKind for wire-forward-compatibility with a future market-regime producer and are not emitted by the admin trading-pair path — keep a default branch, but do not build behavior on them yet. The subscription is torn down on unmount, and re-established when sdk.ws or tradingPairId changes.
Detected broadcast lag closes the entire socket with code 1013, including an instrument-only connection. A dropped update may belong to a market that never emits again, so continuing from the retained tail cannot repair every key. With automatic reconnect enabled, the core client resubscribes and this hook replaces its market set when a fresh instrument snapshot arrives.
A reconnect request or onResync callback is not proof that the snapshot succeeded. If the snapshot is unavailable, or a decision requires independently refreshed configuration, reconcile over REST. No single endpoint carries every field this channel does, so an unfiltered hook requires multiple requests:
sdk.market.getPaginatedTradingPairs(), walkingpageuntil you have every market (one page can omit some), coversisActive,tickSize,quantityStepSize,minOrderSize,maxOrderSize,category,marketType, andmaxLeverage.sdk.market.getPerpMarketConfig(tradingPairId)covers the two remaining perp fields, which the pair list does not carry — and note the rename: this channel’sinitialMarginRate/maintenanceMarginRateareinitialMarginRatio/maintenanceMarginRatiothere. It is scoped to one pair, so following every market costs one request per perp market.
useInstruments call keeps its own state, so mounting the hook in two components subscribes twice. If both resolve to the same channel — both omitting tradingPairId, or both passing the same id — the second joins a channel the client already holds, which the server does not re-snapshot; the core helper replays its cached baseline to it instead. Mounts with different filters are distinct subscriptions and each get their own server snapshot. Either way the baseline arrives asynchronously, like a real snapshot, so instruments is empty on the first render — render an empty list, not a spinner keyed on subscribed.
Parameters
string
Optional trading pair UUID to filter on. Omit it to follow every market. An empty string is rejected by the underlying core helper and surfaces through
error.Return Values
InstrumentEventData[]
Current configuration of every market seen on the channel, ordered by
symbol and then by tradingPairId — a spot and a perp market sharing a symbol keep a stable order. Sorting uses plain codepoint comparison, so the order does not shift with the runtime locale.An inactive market stays in the list carrying isActive: false rather than disappearing — whether it was delisted while the subscription was live or arrived inactive in the snapshot — so a consumer can tell “no longer tradable” from “never seen” and still resolve the metadata of positions, orders and history on it. Filter on isActive for the tradable set. A market absent from a snapshot is a different case — it is no longer listed at all, so it leaves the list with that snapshot.Record<string, InstrumentEventData>
The same entries keyed by trading pair UUID, for direct lookup.
boolean
Whether a subscription to the instrument channel is currently registered. This is not a connection indicator: the client accepts subscriptions while the socket is down and sends them on the next open, so
true means “registered”, not “receiving”.Error | null
A rejected subscription request. The core helper validates its arguments synchronously — passing an empty
tradingPairId is the reachable case — so treat this as a bad-usage signal.It is deliberately not a transport signal: the client registers handlers regardless of socket state and logs malformed-frame failures internally, so connection loss and unparseable frames never appear here. Drive connection UI from the client’s own status and resync callbacks instead.() => void
Clear the current error state.
InstrumentEventData from @0xmonaco/types: change, tradingPairId, symbol, isActive, tickSize, quantityStepSize, minOrderSize, maxOrderSize, marketType, category, changedFields, updatedAt, plus the perp-only maxLeverage, initialMarginRate, and maintenanceMarginRate (omitted on spot markets). See the channel reference for the wire shape.
What makes the reconnect self-repairing is that the core helper delivers the snapshot as its own array rather than as per-market events, so the hook can tell where the baseline ends and drop entries missing from it. If a fresh snapshot is unavailable, the REST reconciliation above remains application-owned; reconnect does not itself fetch those endpoints.
Example
Following one market
useOHLCV
New in v0.5.5 - Real-time candlestick data with WebSocket updates
Usage
Parameters
string
required
UUID of the trading pair. Get from
sdk.market.getTradingPairBySymbol().'SPOT' | 'MARGIN'
required
Trading mode for OHLCV data. Pass
"MARGIN" for a perp market’s candles.'1m' | '5m' | '15m' | '1h' | '4h' | '1d'
required
Candlestick time interval.
GetCandlesticksParams
Optional parameters for initial data fetch:
limit- Number of candlesticks to fetch (max 500)startTime- Start timestamp for rangeendTime- End timestamp for range
Return Values
Candlestick[]
Array of candlestick data, sorted by time (oldest first). Updates in real-time via WebSocket.
boolean
true while fetching initial candlestick data from REST API, false once loaded.boolean
true after the OHLCV channel handler is registered, false otherwise. This does not report socket connection or channel delivery state.Error | null
Error object if subscription or fetch fails,
null otherwise.() => void
Dismisses the current error. It does not retry the fetch or re-register the handler.
Candlestick Data Structure
Features
Hybrid Data Loading
- Initial REST Fetch: Fetches historical candlesticks via REST API
- WebSocket Updates: Subscribes to real-time updates after initial load
- Automatic Merging: New candlesticks are automatically appended or update the last candle if timestamps match
Stable Subscriptions
- No data jitter: Prevents state updates after component unmount
- Proper cleanup: WebSocket automatically unsubscribes when component unmounts
- Race condition prevention: Cancellation flag prevents stale updates
Basic Example
Different Time Intervals
Fetch Historical Data
Error Handling
Display Latest Price
Calculate Price Change
Integration with Chart Libraries
Notes
- The hook automatically manages WebSocket subscriptions and cleanup
- Candlesticks are updated in real-time when the WebSocket receives new events
- If the last candlestick has the same timestamp as an incoming update, it’s replaced; otherwise, a new candle is appended
- Component unmounting automatically unsubscribes from the WebSocket channel
See Also
- WebSocket API - Low-level OHLCV WebSocket channel
- TypeScript SDK - Core SDK WebSocket methods
- useMarket - Get trading pair metadata
useOrderbook
Parameters
string
required
Trading pair UUID. Get this from
sdk.market.getTradingPairBySymbol('BTC/USDC').'SPOT' | 'MARGIN'
required
Trading mode for the orderbook subscription. Use
'SPOT' for spot markets and 'MARGIN' for perp markets.number
required
Price level grouping magnitude. Valid values:
0.000001, 0.00001, 0.0001, 0.001, 0.01, 0.1, 1, 10, 100, 1000, 10000'BASE' | 'QUOTE'
required
Quantity denomination.
BASE shows quantities in base token, QUOTE multiplies by price.number
default:"10"
Price levels per side for the initial REST read (max: 1000). The live stream replaces that read within moments with its own grouped book, so a deeper read only helps the first render. Above 100 levels each mount or parameter change also draws on the deep orderbook read budget. For a full live book, use
useDepth.Return Values
OrderbookEvent | null
Current orderbook snapshot with bids, asks, best prices, and volumesProperties:
tradingPairId: Trading pair ID (UUID)tradingMode: “SPOT” | “MARGIN”bids: Array of{ price, quantity, orderCount }asks: Array of{ price, quantity, orderCount }bestBid(optional): Best bid pricebestAsk(optional): Best ask pricebidVolume(optional): Total bid volumeaskVolume(optional): Total ask volumepriceChange: Price change info (optional) -{ side, oldPrice?, newPrice?, levelRemoved, levelAdded }baseDecimals: Base token decimalsquoteDecimals: Quote token decimalstimestamp: Snapshot timestampsequence: Sequence number; its basis can change across snapshots, so compare it only between updates that follow the same snapshotbookSeq,prevBookSeq(optional): the book’s sequence, as decimal strings, when the server renders the book from the market-data service (see Book sequence)
boolean
Whether currently subscribed to real-time updates
Error | null
Connection or subscription error if any
() => void
Clear the current error
Example
How It Works
- Initial Load: Fetches orderbook snapshot via REST API
- Real-time Updates: Subscribes to WebSocket for live updates
- Auto-cleanup: Unsubscribes when component unmounts or params change
useDepth
sdk.ws.depth: one market’s exact, ungrouped book, up to 1000 levels per side, from the depth channel. The subscribe-time snapshot is the base, linked updates are applied to it, and a gap rebuilds it from a fresh snapshot. For a grouped book, use useOrderbook; for only the top of book, useBbo.
Parameters
string
required
Trading pair UUID. Get this from
sdk.market.getTradingPairBySymbol('BTC/USDC').'SPOT' | 'MARGIN'
required
The market’s trading mode.
Return Values
DepthBook | null
The current book, or
null until the first snapshot arrives and while the book is being rebuilt.tradingPairId,tradingModebookSeq: the book’s sequence, a u64 as a decimal stringbids,asks: arrays of{ price, quantity, orderCount }, best firstbidsComplete,asksComplete:falsewhen levels beyond the last one held are unknownstale: the latest update was published while the service lagged the exchangetimestampMs(optional): exchange time of the latest update
boolean
Whether a subscription is active.
'gap' | 'snapshot_unavailable' | 'truncated' | 'disconnected' | null
Why the book was last discarded to be rebuilt, if it has been. See
LocalBookOptions.{ code: string; message: string } | null
The server’s rejection of the subscription, if any. An invalid trading pair ID or mode is reported here with code
INVALID_ARGUMENT.Example
useBbo
sdk.ws.bbo: one market’s top of book from the bbo channel, which sends a frame whenever the best bid or ask price or size changes. Takes the same tradingPairId and tradingMode as useDepth, and returns the same subscribed, lastResync (why the top of book was last discarded to be rebuilt) and error fields.
Bbo | null
The current top of book, or
null until the first snapshot arrives and while it is being rebuilt.tradingPairId,tradingModebookSeq: the book’s sequence, a u64 as a decimal stringbestBid,bidQty,bestAsk,askQty: decimal strings, ornullfor an empty sidestale: the latest update was published while the service lagged the exchangetimestampMs(optional): exchange time of the latest update
useTradeFeed
Parameters
string
required
Trading pair UUID. Get this from
sdk.market.getTradingPairBySymbol('ETH/USDC').The trade feed maintains a fixed limit of 50 trades. This limit is not configurable and is enforced internally to optimize memory and performance.
Return Values
TradeEvent[]
Array of recent trades (newest first). Fixed at 50 trades maximum.
boolean
Whether currently subscribed to the trading pair. Will be false if SDK is not yet initialized.
boolean
Whether the initial trades are being fetched via REST API.
Error | null
WebSocket error if any
Example
useLiquidationFeed
useLiquidationFeed returns the newest persisted liquidation events for one margin pair and merges the public WebSocket stream into the same list.
market_liquidations:{tradingPairId} for live updates. When the server confirms or restores the subscription, it pages through the full gap from the latest seen event timestamp; if there is no checkpoint, it reads only the newest page. A gap read stops once it has fetched the newest 500 events, the most the hook keeps. Because storage can lag the live stream, the hook repeats the read from the newest stored event it has seen, waiting 1, 2, 4 and then 8 seconds after each read finishes (so roughly 1, 3, 7 and 15 seconds after the first). It stops early once stored history contains the first live event received after the subscription was confirmed, or, when no live event has arrived, once two repeats in a row find nothing new. It merges recovered rows with live updates, deduplicates by eventId, and keeps the newest 500 events, dropping older ones. The stream has no snapshot. Timestamps are Unix milliseconds, sizes and prices are decimal strings, and markNotional uses the event’s captured mark in the quote asset.
useFees
Methods
(params: SimulateFeeParams) => Promise<SimulateFeeResponse>
Calculate exact fees for an order before placing it. Requires authentication.Parameters:
tradingPairId: string - Trading pair UUIDside: “BUY” | “SELL” - Order sideprice: string - Price per unitquantity: string - Quantity to tradeorderType: “LIMIT” | “MARKET” (optional) - Defaults to LIMIT behaviour if omitted. Pass"MARKET"to get a slippage-adjustedbuyOrderLockAmountslippageToleranceBps: number (optional, 0–1000) - Slippage tolerance in basis points. Only valid withorderType: "MARKET". Default:1000(10%), matching the protective price band
notional: string - Total order value (price × quantity)monacoTakerFee: string - Monaco protocol taker feemonacoTakerFeeBpsExact: string | null - Monaco taker rate, from your tier or the assigned or custom rate on your wallet, as a decimal bps string (e.g."6.5") — the exact rate the ledger charges this caller;monacoTakerFeeisprice × quantityat this rate, truncated to the quote token’s decimalsmonacoMakerRebateBpsExact: string | null - Monaco maker rate, from your tier or the assigned or custom rate on your wallet, as a decimal bps string (negative = rebate, e.g."-1") — the exact rate the ledger credits this callermonacoMakerRebate: string - Monaco maker rebate (negative = rebate)applicationTakerFee: string - Application taker feeapplicationTakerFeeBps: number - Application fee in basis pointsapplicationName: string | null - Application name (if applicable)totalTakerFees: string - Total fees for taker (monaco + application)takerTotalPayment: string - Total amount taker must paymakerTotalReceipt: string - Total amount received if the order fills as the maker: notional minus the maker fee (a rebate adds) minusapplicationMakerFeeapplicationMakerFee?: string - Application maker add-on if the order fills as the maker, paid on top of the maker fee or rebateapplicationMakerFeeBps?: number - Application maker add-on in basis points: the rate an order placed now would storebuyOrderLockAmount: string | null - Amount to lock for BUY orders. For MARKET orders includes slippage buffermaxQuantity: string | null - Maximum quantity affordable at the given price, after fees. Use this for the 100% balance slidermaxQuantityRaw: string | null - Same value in raw (smallest unit) formatslippageToleranceBps: number | null - Slippage tolerance used in the calculation, echoed back.nullfor LIMIT orders
notional, each fee and rebate, and the totals totalTakerFees, takerTotalPayment and makerTotalReceipt, which are sums of the truncated parts. A rebate smaller than one atomic unit reads 0.(params: GetMyFeeTierParams) => Promise<GetMyFeeTierResponse>
Look up your current fee tier, the rates that apply to you on a pair and why, rolling 14-day volumes, and the pair’s six-row fee schedule. Requires authentication. The volumes and the tier they earn are wallet-wide: they sum the wallet’s trades across every application it trades through, so they read the same from any application.Parameters:
tradingPairId: string - Trading pair UUID whose fee schedule to return
currentTierLevel: number - Tier1(lowest volume) through6(highest) your rates come from, or the tierweightedVolume14dearns whenrateSourceiscustomweightedVolume14d: string - Weighted 14-day volume (perp + 2.5× spot) the tier resolves fromspotVolume14d: string - Rolling 14-day spot volumeperpVolume14d: string - Rolling 14-day perp volumevolumeToNextTier: string | null - Additional weighted volume needed to reach the next tier, counted from the volume the current tier resolved from; omitted at tier 6 and unlessrateSourceisvolumenextTierLevel: number | null - Next tier level; omitted at tier 6 and unlessrateSourceisvolumefeeSchedule: FeeTierScheduleRow[] - The pair’s six rows, ascending by tier. Each row:tierLevel(number),minVolumeThreshold(string),makerFeeBps(string — human bps, negative = rebate),takerFeeBps(string — human bps)rateSource:"volume"|"tier_override"|"custom"- Why this rate applies: the tier your 14-day volume earns, an assigned tier, or custom rates assigned to your wallet. See Custom and assigned ratesmakerFeeBps: string - Effective maker rate for the requested pair, in decimal basis points; negative is a rebate, positive is a feetakerFeeBps: string - Effective taker rate for the requested pair, in decimal basis points
(tradingPairId: string) => Promise<GetFeeScheduleResponse>
Read a trading pair’s Monaco fee tier schedule. Public: needs no authentication, so it works before the user signs in.Parameters:
tradingPairId: string - Trading pair UUID whose fee schedule to return
tradingPairId: string - The trading pair the schedule belongs tofeeSchedule: FeeTierScheduleRow[] - The pair’s tiers, ascending by tier level. Each row:tierLevel(number),minVolumeThreshold(string),makerFeeBps(string — human bps, negative = rebate),takerFeeBps(string — human bps)
Example
Fee Breakdown
Monaco uses a maker-taker fee model:
Use
simulateFees before placing orders to show users exact costs upfront.
