# About XPress

#### What is XPress?

XPress is a fully on-chain order book exchange built on Sonic, offering unmatched decentralization, transparency, and composability by processing all orders directly on-chain. At launch, XPress will focus on spot trading. Plans for future enhancements include  introducing LP tokens to enable passive liquidity provisioning and adding perpetual and margin trading capabilities.

#### Why XPress?

Although automated market makers (AMMs) dominate the on-chain DEX market, we consider the central limit order book (CLOB) model to be superior. By offering price-time priority, CLOBs encourage competition among liquidity providers, enabling them to achieve tighter spreads compared to AMMs.

The limited adoption of CLOBs on-chain stems from two key challenges: first, traditional matching algorithms typically have linear complexity, which can exceed gas limits for blocks or contract calls. Second, gas fees on many blockchains remain relatively high.

XPress addresses these issues with an innovative matching algorithm that uses logarithmic complexity, enabling efficient order processing in a fixed number of steps. Moreover, advancements in blockchain infrastructure have significantly reduced costs. For instance, Sonic’s low gas fees—only $0.0001 per transaction—make XPress an affordable and scalable solution for on-chain trading.


# Order Book

XPress protocol's order book is fully on-chain and works similarly to centralized exchanges. Orders are matched based on price-time priority.

In contrast to some other on-chain order books, there is no upper bound on the number of orders that can be simultaneously placed on XPress.

All prices allow up to 6 digits of precision, enabling tick sizes of less than 0.001%.


# Order Types

**Order Types:**

* **Market:** An order that executes immediately at the current market price.
* **Limit:** An order that executes at the selected limit price or better.

**Order Options:**

* **Post Only (ALO):** An order that is added to the order book but doesn’t execute immediately. It is only executed as a resting order.
* **Immediate or Cancel (IOC):** An order that will be canceled if it is not immediately filled.


# Fees

In the first phase of mainnet trading, fees are set at 3 bps for Takers and 0 bps for Makers.


# Prices and Precision

XPress standard contracts support up to 6-digit precision for the prices of trading pairs.

\
The table below shows the tick sizes for the current trading pairs on XPress.

| Pair        | Tick size     |
| ----------- | ------------- |
| S-USDC.e    | 0.0001 USDC.e |
| WETH-USDC.e | 0.1 USDC.e    |


# Gas costs

Since XPress is a fully on-chain order book exchange, each order placement is associated with a gas fee.

The table below contains the median gas costs of most common operations on XPress on-chain order book, and corresponding dollar equivalent on Sonic.

| Operation           | Gas Units | Gas Cost in $ on Sonic |
| ------------------- | --------- | ---------------------- |
| Market Order (Swap) | 100,000   | \~$0.0001              |
| Place Limit Order   | 200,000   | \~$0.0001              |


# Audits

XPress spot central limit order book contracts are audited by MixBytes.


# Overview

The LP Vault on the XPress Protocol provides a mechanism for passive liquidity provision within the ecosystem. Liquidity providers (LPs) deposit funds into the LP Vault, which is used to support trading activities on the XPress Protocol. In return, LPs earn a share of fees generated from trading and market-making activities.&#x20;

The LP Vault aims to offer an efficient and passive liquidity solution while maintaining a stable and balanced pool of assets. It uses a dynamic fee structure and governance to ensure fair rewards for LPs and robust trading support.


# Token Composition

The LP Vault consists of three assets with the following fixed target allocations:

* S: 35%
* WETH: 15%
* WBTC: 15%
* USDC: 35%

These weights represent the ideal balance of the vault’s liquidity pool. Deposits and withdrawals are managed to encourage maintaining these target levels, with dynamic fees applied to enforce this balance.


# Deposits & Withdrawals

* Deposits: Users can deposit liquidity into the LP Vault using any single token from the supported assets (S, WETH, or USDC.e). The system automatically adjusts the pool to incorporate the deposit.
* Withdrawals: Users can withdraw liquidity in any supported token, subject to available liquidity in the vault.

A base fee of 0.1% applies to all deposits and withdrawals, with an additional dynamic fee ranging from -0.1% to +0.1% based on the transaction’s impact on target weights.


# API

This section describes methods for interacting with the Xpress platform. These methods are categorized into three types.

* Contract API: All trades are executed within contracts on Sonic. To set an order, you call the contract entry point.
* The HTTP API allows you to retrieve information about past and current prices, orders, and trades.
* The WebSocket API is used to receive events about recent changes.

Interaction is available on mainnet with:

* two market contracts [SUSDC](https://sonicscan.org/address/0xc7723fe3df538f76a063eb5e62867960d236accf) and [ETHUSDC](https://sonicscan.org/address/0x75aba7081182a2b1f3b0ead47c074e800805941e)​
* HTTP base endpoint <https://api.xpressprotocol.com>[​](https://api.xpressprotocol.com)
* WebSocket endpoint `wss://sockets.xpressprotocol.com`


# Contract API

All trades and token transfers are executed in the contract.

You can trade tokens from deposits in the market contract or from token ledgers.&#x20;

Market contracts represent a pair of tokens, named X and Y, or base and quote. All token amounts and prices are scaled by corresponding scaling factors unless otherwise stated. Also see [Contract-to-human scaling transformation](/for-developers/api/common-objects#contract-to-human-scaling-transformation).

## depositTokens

Move funds to the market contract to trade them.

### Parameters

<table><thead><tr><th width="190">Parameter</th><th width="110">Type</th><th>Description</th></tr></thead><tbody><tr><td>token_x_amount</td><td>uint128</td><td>the amount of token X to deposit</td></tr><tr><td>token_y_amount</td><td>uint128</td><td>the amount of token Y to deposit</td></tr></tbody></table>

## withdrawTokens

Move funds from market contracts to token ledgers.

### Parameters

<table><thead><tr><th width="190">Parameter</th><th width="110">Type</th><th>Description</th></tr></thead><tbody><tr><td>withdraw_all</td><td>bool</td><td>if set to True, withdraws all the trader's tokens; otherwise, uses the specified amounts.</td></tr><tr><td>token_x_amount</td><td>uint128</td><td>the amount of token X to withdraw (ignored if withdraw_all is true)</td></tr><tr><td>token_y_amount</td><td>uint128</td><td>the amount of token Y to withdraw (ignored if withdraw_all is true)</td></tr></tbody></table>

## placeOrder

Create an order in the market contract. The function supports receiving the native token instead of the corresponding wrapped token.

### Parameters

<table><thead><tr><th width="244">Parameter</th><th width="92">Type</th><th>Description</th></tr></thead><tbody><tr><td>isAsk</td><td>bool</td><td>true if the order is a sell order, false if it is a buy order</td></tr><tr><td>quantity</td><td>uint128</td><td>the amount of the base token in the order</td></tr><tr><td>price</td><td>uint56</td><td>the price per token in the order, no more than 6 significant digits</td></tr><tr><td>max_commission</td><td>uint128</td><td>the maximum commission, which may include passive and/or aggressive fees</td></tr><tr><td>market_only</td><td>bool</td><td>indicates if the order should be executed only against existing orders in the market</td></tr><tr><td>post_only</td><td>bool</td><td>indicates if the order should be posted only and not executed immediately</td></tr><tr><td>transfer_executed_tokens</td><td>bool</td><td>flag for transferring executed tokens (true) or crediting them to the balance (false)</td></tr><tr><td>expires</td><td>uint256</td><td>the time at which the order will expire</td></tr></tbody></table>

## placeOrder

Overloaded version. Create an order in the market contract with the permitted approval.

### Parameters

<table><thead><tr><th width="244">Parameter</th><th width="92">Type</th><th>Description</th></tr></thead><tbody><tr><td>isAsk</td><td>bool</td><td>true if the order is a sell order, false if it is a buy order</td></tr><tr><td>quantity</td><td>uint128</td><td>the amount of the base token in the order</td></tr><tr><td>price</td><td>uint56</td><td>the price per token in the order, no more than 6 significant digits</td></tr><tr><td>max_commission</td><td>uint128</td><td>the maximum commission, which may include passive and/or aggressive fees</td></tr><tr><td>amount_to_approve</td><td>uint128</td><td>the amount of  the token permitted by the signature</td></tr><tr><td>market_only</td><td>bool</td><td>indicates if the order should be executed only against existing orders in the market</td></tr><tr><td>post_only</td><td>bool</td><td>indicates if the order should be posted only and not executed immediately</td></tr><tr><td>transfer_executed_tokens</td><td>bool</td><td>flag for transferring executed tokens (true) or crediting them to the balance (false)</td></tr><tr><td>expires</td><td>uint256</td><td>the time at which the order will expire</td></tr><tr><td>v</td><td>uint8</td><td>the component V of the signature</td></tr><tr><td>r</td><td>bytes32</td><td>the component R of the signature</td></tr><tr><td>s</td><td>bytes32</td><td>the component S of the signature</td></tr></tbody></table>

## placeMarketOrderWithTargetValue

Create a market order by specifying the exact value of token Y. The function supports receiving the native token instead of the corresponding wrapped token.

### Parameters

<table><thead><tr><th width="244">Parameter</th><th width="92">Type</th><th>Description</th></tr></thead><tbody><tr><td>isAsk</td><td>bool</td><td>true if the order is a sell order, false if it is a buy order</td></tr><tr><td>target_token_y_value</td><td>uint128</td><td>the amount of the quote token to be spent by the order</td></tr><tr><td>price</td><td>uint56</td><td>the price per token in the order, no more than 6 significant digits</td></tr><tr><td>max_commission</td><td>uint128</td><td>the maximum commission</td></tr><tr><td>transfer_executed_tokens</td><td>bool</td><td>flag for transferring executed tokens (true) or crediting them to the balance (false)</td></tr><tr><td>expires</td><td>uint256</td><td>the time at which the order will expire</td></tr></tbody></table>

## placeMarketOrderWithTargetValue

Overloaded version. Create a market order by specifying the exact value of token Y with the permitted approval.

### Parameters

<table><thead><tr><th width="244">Parameter</th><th width="92">Type</th><th>Description</th></tr></thead><tbody><tr><td>isAsk</td><td>bool</td><td>true if the order is a sell order, false if it is a buy order</td></tr><tr><td>target_token_y_value</td><td>uint128</td><td>the amount of the quote token to be spent by the order</td></tr><tr><td>price</td><td>uint56</td><td>the price per token in the order, no more than 6 significant digits</td></tr><tr><td>max_commission</td><td>uint128</td><td>the maximum commission</td></tr><tr><td>amount_to_approve</td><td>uint128</td><td>the amount of  the token permitted by the signature</td></tr><tr><td>transfer_executed_tokens</td><td>bool</td><td>flag for transferring executed tokens (true) or crediting them to the balance (false)</td></tr><tr><td>expires</td><td>uint256</td><td>the time at which the order will expire</td></tr><tr><td>v</td><td>uint8</td><td>the component V of the signature</td></tr><tr><td>r</td><td>bytes32</td><td>the component R of the signature</td></tr><tr><td>s</td><td>bytes32</td><td>the component S of the signature</td></tr></tbody></table>

## changeOrder

Claiming/canceling an existing order and creating a new one in the same (bid/ask) direction.

### Parameters

<table><thead><tr><th width="190">Parameter</th><th width="110">Type</th><th>Description</th></tr></thead><tbody><tr><td>old_order_id</td><td>uint64</td><td>the identifier of the order to modify, a new order id will be assigned to the order</td></tr><tr><td>new_quantity</td><td>uint128</td><td>the amount of tokens for the new order</td></tr><tr><td>new_price</td><td>uint56</td><td>the price per token in the order, no more than 6 significant digits</td></tr><tr><td>max_commission</td><td>uint128</td><td>the maximum commission, which may include passive and/or aggressive fees</td></tr><tr><td>post_only</td><td>bool</td><td>indicates if the order should be posted only and not executed immediately</td></tr><tr><td>transfer_tokens</td><td>bool</td><td>if true, tokens will be transferred to the order owner</td></tr><tr><td>expires</td><td>uint256</td><td>the time at which the order will expire</td></tr></tbody></table>

## claimOrder

Allows a trader to claim or cancel the order.

### Parameters

<table><thead><tr><th width="190">Parameter</th><th width="110">Type</th><th>Description</th></tr></thead><tbody><tr><td>order_id</td><td>uint64</td><td>the identifier of the order to claim</td></tr><tr><td>transfer_tokens</td><td>bool</td><td>if true, transfers the tokens to the trader's address</td></tr><tr><td>expires</td><td>uint256</td><td>the time at which the order will expire</td></tr></tbody></table>


# Common objects

HTTP and WS API operates with almost identical objects.

## Trade

<table><thead><tr><th width="135">Property</th><th width="213">Type</th><th>Description</th></tr></thead><tbody><tr><td>tradeId</td><td>string</td><td>the unique trade identifier</td></tr><tr><td>direction</td><td>values "buy" or "sell"</td><td>identifies trade direction</td></tr><tr><td>price</td><td>string represents BigInt</td><td>price per token in the order</td></tr><tr><td>size</td><td>string represents BigInt</td><td>token quantity filled by trade</td></tr><tr><td>timestamp</td><td>number</td><td>block timestamp when the trade was concluded</td></tr><tr><td>txnHash</td><td>string</td><td>transaction in which the trade was concluded</td></tr></tbody></table>

## Order

<table><thead><tr><th width="148">Property</th><th width="213">Type</th><th>Description</th></tr></thead><tbody><tr><td>orderId</td><td>string</td><td>the order identifier</td></tr><tr><td>type</td><td>"limit" or "market"</td><td>"market" orders execute when placed</td></tr><tr><td>owner</td><td>string</td><td>a user placed the order</td></tr><tr><td>side</td><td>"bid" or "ask"</td><td>buy or sell order direction</td></tr><tr><td>price</td><td>string represents BigInt</td><td>price per token in the order </td></tr><tr><td>size</td><td>string represents BigInt</td><td>token quantity that's not filled</td></tr><tr><td>origSize</td><td>string represents BigInt</td><td>order token quantity placed by user</td></tr><tr><td>claimed</td><td>string represents BigInt</td><td>number of tokens in the order sent to the user by calling claimOrder</td></tr><tr><td>createdAt</td><td>number represents a timestamp</td><td>when the order was created</td></tr><tr><td>lastTouched</td><td>number represents a timestamp</td><td>when the order was updated</td></tr><tr><td>txnHash</td><td>string</td><td>transaction hash in which the order was created</td></tr><tr><td>status</td><td>one of "open", "filled", "claimed" or "cancel"</td><td>represents order lifecycle status</td></tr><tr><td>fee</td><td>string represents BigInt</td><td>fee for market execution</td></tr><tr><td>market</td><td>object containing a field id</td><td>a market identifier where the order was placed</td></tr></tbody></table>

## Orderbook Level

<table><thead><tr><th width="145">Property</th><th width="213">Type</th><th>Description</th></tr></thead><tbody><tr><td>price</td><td>string represents BigInt</td><td>token price, level identifier</td></tr><tr><td>size</td><td>string represents BigInt</td><td>sum of sizes in orders corresponding to the requested aggregation</td></tr><tr><td>lastTouched</td><td>number represents a timestamp</td><td>when the level was updated</td></tr></tbody></table>

## Order Fill

<table><thead><tr><th width="148">Property</th><th width="231">Type</th><th>Description</th></tr></thead><tbody><tr><td>id</td><td>string</td><td>the order fill identifier</td></tr><tr><td>orderId</td><td>string</td><td>the order that was filled</td></tr><tr><td>tradeId</td><td>string</td><td>trade identifier when a part of the order is filled</td></tr><tr><td>type</td><td>"limit" or "market"</td><td>an order type</td></tr><tr><td>owner</td><td>string</td><td>a user placed the order</td></tr><tr><td>side</td><td>"bid" or "ask"</td><td>an order side</td></tr><tr><td>price</td><td>string represents BigInt</td><td>price per token in the order </td></tr><tr><td>size</td><td>string represents BigInt</td><td>token quantity that was filled in the trade</td></tr><tr><td>txnHash</td><td>string</td><td>transaction hash in which the order was filled</td></tr><tr><td>market</td><td>object containing a field id</td><td>a market identifier where the order was placed</td></tr></tbody></table>

## Candle

<table><thead><tr><th width="144">Property</th><th width="264">Type</th><th>Description</th></tr></thead><tbody><tr><td>market</td><td>object containing field id</td><td>a market identifier to which the candle is related</td></tr><tr><td>resolution</td><td>one of "15", "60", "240" or "1D"</td><td>represents a candle time interval </td></tr><tr><td>time</td><td>number represents a timestamp</td><td>with the resolution makes up a candle identifier</td></tr><tr><td>open</td><td>string</td><td>an open price</td></tr><tr><td>high</td><td>string</td><td>a high price</td></tr><tr><td>low</td><td>string</td><td>a low price</td></tr><tr><td>close</td><td>string</td><td>a close price</td></tr><tr><td>volume</td><td>string</td><td>a sum of trade sizes</td></tr><tr><td>lastTouched</td><td>number represents timestamp</td><td>when the candle was updated</td></tr></tbody></table>

## Market

<table><thead><tr><th width="206">Property</th><th width="213">Type</th><th>Description</th></tr></thead><tbody><tr><td>id</td><td>string</td><td>the market identifier</td></tr><tr><td>name</td><td>string</td><td>the name of a market</td></tr><tr><td>symbol</td><td>string</td><td>the market short name</td></tr><tr><td>baseToken</td><td><a href="#token">token</a> object</td><td>the. X token of the market pair</td></tr><tr><td>quoteToken</td><td><a href="#token">token</a> object</td><td>the. Y token of the market pair</td></tr><tr><td>orderbookAddress</td><td>string</td><td>a market contract address</td></tr><tr><td>aggregations</td><td>array of numbers</td><td>market aggregation types</td></tr><tr><td>coinMarketCapId</td><td>string</td><td>a pair identifier at <a href="https://coinmarketcap.com/">https://coinmarketcap.com/</a></td></tr><tr><td>lowPrice24h</td><td>string</td><td>a lowest day price</td></tr><tr><td>highPrice24h</td><td>string</td><td>a highest day price</td></tr><tr><td>lastPrice</td><td>string</td><td>a last trade price</td></tr><tr><td>price24h</td><td>string</td><td>the price one day ago</td></tr><tr><td>bestAsk</td><td>string</td><td>the lowest ask price in an order book</td></tr><tr><td>bestBid</td><td>string</td><td>the highest bid price in an order book</td></tr><tr><td>tradingVolume24h</td><td>string</td><td>the sum of trade sizes from the last day</td></tr><tr><td>supportsNativeToken</td><td>boolean</td><td>indicates if one of the tokens is native</td></tr><tr><td>isNativeTokenX</td><td>boolean</td><td>indicates which token is native</td></tr><tr><td>tokenXScalingFactor</td><td>number</td><td>scaling applied to the base token in contract API</td></tr><tr><td>tokenYScalingFactor</td><td>number</td><td>scaling applied to the quote token in contract API</td></tr><tr><td>priceScalingFactor</td><td>number</td><td>scaling applied to the price in contract API</td></tr><tr><td>totalSupply</td><td>string</td><td>total supply data from CoinMarketCap</td></tr><tr><td>lastTouched</td><td>timestamp</td><td>when the market object was updated</td></tr><tr><td>aggressiveFee</td><td>string</td><td>the fee rate for market orders</td></tr><tr><td>passiveFee</td><td>string</td><td>the fee rate for limit orders</td></tr><tr><td>passiveOrderPayout</td><td>string</td><td>the payout rate for limit orders</td></tr></tbody></table>

## Token

<table><thead><tr><th width="187">Property</th><th width="231">Type</th><th>Description</th></tr></thead><tbody><tr><td>id</td><td>string</td><td>the token identifier</td></tr><tr><td>name</td><td>string</td><td>the name of a token</td></tr><tr><td>symbol</td><td>string</td><td>the token short name</td></tr><tr><td>contractAddress</td><td>string</td><td>a token ledger address</td></tr><tr><td>decimals</td><td>number</td><td>a decimals parameter in token contract</td></tr><tr><td>roundingDecimals</td><td>number</td><td>the precision of the displayed token amount</td></tr><tr><td>supportsPermit</td><td>boolean</td><td>indicates whether the token supports permit approval</td></tr></tbody></table>

## Contract-to-human scaling transformation

As mentioned in Contract API section all token amounts and prices are scaled by corresponding scaling factors  It performs in this manner. The market API object has fields `tokenXScalingFactor. tokenYScalingFactor, priceScalingFactor`. If we want to calculate the human-readable value of the price, we should divide it by 10 raised to the power of the negative price scaling factor.&#x20;

E.g., the price value 6780 for the SUSDC market with a `priceScalingFactor` of 4 is the 0.678 human-readable price.

The same transformation says that a size of 1,234,567 for the SUSDC market with a `priceScalingFactor` of 3 is actually 1,234.567 S.


# HTTP API

All endpoints use HTTP GET requests with several URL parameters. All responses are encoded in JSON format.

## Content

* [trades](#trades)
* [orders](#orders)
* [orderbook](#orderbook)
* [fills](#fills)
* [candles](#candles)
* [markets](#markets)
* [user-balances](#user-balances)

## `/trades`

Fetch market trades from recent to oldest.

### Request parameters

<table><thead><tr><th width="173">Parameter</th><th width="231">Required?</th><th>Description</th></tr></thead><tbody><tr><td>market</td><td>required</td><td>a market contract address</td></tr><tr><td>limit</td><td>optional</td><td>max number of trades , default is 100</td></tr></tbody></table>

### Response

An array of [trade](/for-developers/api/common-objects#trade) objects.

## `/orders`

Fetch user orders.

### Request parameters

<table><thead><tr><th width="173">Parameter</th><th width="231">Required?</th><th>Description</th></tr></thead><tbody><tr><td>market</td><td>required</td><td>a market contract address</td></tr><tr><td>user</td><td>required</td><td>a user address</td></tr><tr><td>limit</td><td>optional</td><td>max number of orders , default is 100</td></tr></tbody></table>

### Response

An array of [order](/for-developers/api/common-objects#order) objects.

## `/orderbook`

Fetch the current state of the market order book.

### Request parameters

<table><thead><tr><th width="173">Parameter</th><th width="231">Required?</th><th>Description</th></tr></thead><tbody><tr><td>market</td><td>required</td><td>a market contract address</td></tr><tr><td>aggregation</td><td>optional</td><td>one of market aggregation, if not set max, aggregation is used</td></tr><tr><td>limit</td><td>optional</td><td>max number of levels in asks and bids , default is 100</td></tr></tbody></table>

### Response

Object with fields:

<table><thead><tr><th width="173">Property</th><th width="231">Type</th><th>Description</th></tr></thead><tbody><tr><td>timestamp</td><td>number represents timestamp</td><td>the update time</td></tr><tr><td>levels</td><td>object with fields"asks" and "bids"</td><td>Each field is a sorted array of order book <a href="/pages/XzTq7I4ynKs738OPF8w2#orderbook-level">level</a> objects; asks are sorted in ascending order by price, and bids are sorted in descending order.</td></tr></tbody></table>

## `/fills`

Get executed parts of user orders.

### Request parameters

<table><thead><tr><th width="173">Parameter</th><th width="231">Required?</th><th>Description</th></tr></thead><tbody><tr><td>market</td><td>required</td><td>a market contract address</td></tr><tr><td>user</td><td>required</td><td>a user address</td></tr><tr><td>limit</td><td>optional</td><td>max number of objects in response, default is 100</td></tr></tbody></table>

### Response

An array of order [fill](broken://pages/2PBdZoCtMHo8UeAejfF4#order-fill) objects descending by a timestamp field.

## `/candles`

Get executed parts of user orders.

### Request parameters

<table><thead><tr><th width="173">Parameter</th><th width="231">Required?</th><th>Description</th></tr></thead><tbody><tr><td>market</td><td>required</td><td>a market contract address</td></tr><tr><td>resolution</td><td>required</td><td>one of <a href="/pages/XzTq7I4ynKs738OPF8w2#candle">candle</a> object resolution</td></tr><tr><td>fromTime</td><td>optional</td><td>a lower bound of candle time</td></tr><tr><td>toTime</td><td>optional</td><td>an upper limit of candle time</td></tr></tbody></table>

### Response

An array of [candle](/for-developers/api/common-objects#candle) objects ascending by a time field.

## `/markets`

### Request parameters

<table><thead><tr><th width="173">Parameter</th><th width="231">Required?</th><th>Description</th></tr></thead><tbody><tr><td>market</td><td>optional</td><td>a market contract address</td></tr></tbody></table>

### Response

An array of [market](/for-developers/api/common-objects#market) objects.

## `/user-balances`

### Request parameters

<table><thead><tr><th width="173">Parameter</th><th width="231">Required?</th><th>Description</th></tr></thead><tbody><tr><td>user</td><td>required</td><td>a user address</td></tr></tbody></table>

### Response

An object with a key "balances" and a value that is an array of objects:

<table><thead><tr><th width="175">Property</th><th width="152">Type</th><th>Description</th></tr></thead><tbody><tr><td>token</td><td>string</td><td>a token symbol</td></tr><tr><td>tokenAddress</td><td>string</td><td>a token address</td></tr><tr><td>hold</td><td>number</td><td>amount of tokens locked in orders</td></tr><tr><td>total</td><td>number</td><td>amount of hold tokens plus a deposit in market contract</td></tr></tbody></table>


# Websocket API

If you connect to the WebSocket endpoint, you can subscribe to some channels and receive updates about objects.

Updates come in the form of a full object and can substitute existing objects by their object identifier.

The common form of messages received is

```
{
    "channel": // channel name
    "data": // depends on the channel
}
```

In several subscriptions, specifically `market, trades, userOrders, orderbook, userFills` (in other words, except `candles`), the client receives history objects as events, which are similar to those from calling the corresponding HTTP API with the default limit parameter.

## Subscriptions

* [trades](#trades)
* [userOrders](#userorders)
* [orderbook](#orderbook)
* [userFills](#userfills)
* [candles](#candles)
* [market](#market)

## `trades`

### Subscription parameters

<table><thead><tr><th width="173">Parameter</th><th width="155">Type</th><th>Description</th></tr></thead><tbody><tr><td>channel</td><td>string "trades"</td><td>the channel name</td></tr><tr><td>market</td><td>string</td><td>a market contract address</td></tr></tbody></table>

### Event data

A [trade](/for-developers/api/common-objects#trade) object

## `userOrders`

### Subscription parameters

<table><thead><tr><th width="173">Parameter</th><th width="193">Type</th><th>Description</th></tr></thead><tbody><tr><td>channel</td><td>string "userOrders"</td><td>the channel name</td></tr><tr><td>market</td><td>string</td><td>a market contract address</td></tr><tr><td>user</td><td>string</td><td>a user address</td></tr></tbody></table>

### Event data

An [order](/for-developers/api/common-objects#order) object.

## `orderbook`

### Subscription parameters

<table><thead><tr><th width="173">Parameter</th><th width="193">Type</th><th>Description</th></tr></thead><tbody><tr><td>channel</td><td>string "orderbook"</td><td>the channel name</td></tr><tr><td>market</td><td>string</td><td>a market contract address</td></tr><tr><td>aggregation</td><td>number</td><td>an order book level of aggregation</td></tr></tbody></table>

### Event data

An object:

<table><thead><tr><th width="173">Property</th><th width="231">Type</th><th>Description</th></tr></thead><tbody><tr><td>aggregation</td><td>string represents an aggregation of the market</td><td>an order book aggregation level</td></tr><tr><td>levels</td><td>object with fields"asks" and "bids"</td><td>Each field is a sorted array of order book <a href="/pages/XzTq7I4ynKs738OPF8w2#orderbook-level">level</a> objects; asks are sorted in ascending order by price, and bids are sorted in descending order.</td></tr></tbody></table>

## `userFills`

### Subscription parameters

<table><thead><tr><th width="173">Parameter</th><th width="193">Type</th><th>Description</th></tr></thead><tbody><tr><td>channel</td><td>string "userFills"</td><td>the channel name</td></tr><tr><td>market</td><td>string</td><td>a market contract address</td></tr><tr><td>user</td><td>string</td><td>a user address</td></tr></tbody></table>

### Event data

An object with keys representing user addresses and values as arrays of [order fill](/for-developers/api/common-objects#order-fill) objects.

## `candles`

### Subscription parameters

<table><thead><tr><th width="173">Parameter</th><th width="193">Type</th><th>Description</th></tr></thead><tbody><tr><td>channel</td><td>string "candles"</td><td>the channel name</td></tr><tr><td>market</td><td>string</td><td>a market contract address</td></tr><tr><td>resolution</td><td>string</td><td>one of the candle object's resolutions</td></tr></tbody></table>

### Event data

An object with keys representing a resolution and  the values being [candle](/for-developers/api/common-objects#candle) objects.

## `market`

### Subscription parameters

<table><thead><tr><th width="173">Parameter</th><th width="193">Type</th><th>Description</th></tr></thead><tbody><tr><td>channel</td><td>string "market"</td><td>the channel name</td></tr><tr><td>market</td><td>string</td><td>a market contract address</td></tr></tbody></table>

### Event data

An array of [market](/for-developers/api/common-objects#market) objects.


# SDK

The [SDK](https://github.com/longgammalabs/onchain-lob-sdk) provides interfaces to communicate with the Onchain LOB API. Here is a description of the TypeScript version of the SDK.

The main object to start with is `OnchainLobClient`. It holds information about the Onchain LOB API endpoints and the user transaction signing interface.

All methods to interact with the spot market are available in the `OnchainLobSpot` class.

The SDK also provides type and interface definitions for the objects used.

## Getting Started

### Prerequisites

* [Node.js](https://nodejs.org) version 20.10.0 or later
* [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) or [Yarn](https://yarnpkg.com/)

### Installation

1. Install the SDK package

   ```sh
   npm install onchain-lob-sdk
   ```
2. Install the [ws](https://github.com/websockets/ws) package if you going to use it in the Node.js environment

   ```sh
   npm install ws
   ```


# OnchainLobClient

## Overview

The `OnchainLobClient` class is a central component for interacting with the Onchain LOB API. It manages the connection to the Onchain LOB API and provides methods to interact with the Onchain LOB Spot contracts.

## Constructor

### `constructor(options: Readonly<OnchainLobClientOptions>)`

Creates a new instance of the `OnchainLobClient`.

**Parameters:**

| Parameter                      | Type             | Description                                                                                                      |
| ------------------------------ | ---------------- | ---------------------------------------------------------------------------------------------------------------- |
| `apiBaseUrl`                   | `string`         | The base URL for the Onchain LOB API.                                                                            |
| `webSocketApiBaseUrl`          | `string`         | The base URL for the Onchain LOB WebSocket API.                                                                  |
| `signer`                       | `Signer \| null` | The ethers signer used for signing transactions.                                                                 |
| `webSocketConnectImmediately?` | `boolean`        | Whether to connect to the WebSocket immediately after creating the `OnchainLobClient` (default is true).         |
| `autoWaitTransaction?`         | `boolean`        | Whether to automatically wait for transactions to be confirmed.                                                  |
| `fastWaitTransaction?`         | `boolean`        | Whether to use a fast algorithm for waiting for transactions to be confirmed.                                    |
| `fastWaitTransactionInterval?` | `number`         | Interval between requests in milliseconds when using a fast algorithm for waiting for transaction confirmations. |
| `fastWaitTransactionTimeout?`  | `number`         | Timeout in milliseconds when using a fast algorithm for waiting for transaction confirmations.                   |

## Properties

### `spot: OnchainLobSpot`

An instance of `OnchainLobSpot` that provides API functions to interact with the Onchain LOB Spot contracts.

## Methods

### `setSigner(signer: Signer | null): void`

Sets or unsets the signer for the `OnchainLobClient`.

**Parameters:**

* `signer` (Signer): The signer to set.

## Example Usage

```typescript
import { OnchainLobClient, OnchainLobClientOptions } from 'onchain-lob-sdk';

const options: OnchainLobClientOptions = {
  apiBaseUrl: 'https://api.xpressprotocol.com',
  webSocketApiBaseUrl: 'wss://sockets.xpressprotocol.com',
  signer: null,
  webSocketConnectImmediately: false,
};

const onchainLobClient = new OnchainLobClient(options);

// If you need to use user-oriented methods, set a signer or provider:
// newSigner = new ethers.Wallet(<yourPrivateKey>, <provider>);
onchainLobClient.setSigner(newSigner);
```


# OnchainLobSpot

## Overview

The `OnchainLobSpot` class is designed for interacting with the Onchain LOB Spot API. It provides methods for retrieving market information, subscribing to market updates, placing orders, managing user orders and fills, and more.

## Common contract transaction parameters

The following parameters are common across contract transaction methods:

* `gasLimit`: (optional) Transaction gas limit. If not provided, the value is estimated via `eth_estimateGas` call.
* `maxFeePerGas`: (optional) The maximum fee per unit of gas willing to be paid for the transaction. Calculated as `baseFeePerGas + maxPriorityFeePerGas`. If not provided, obtained via `eth_maxPriorityFeePerGas` call.
* `maxPriorityFeePerGas`: (optional) The maximum price of the consumed gas to be included as a tip to the validator. If not provided, obtained via `eth_maxPriorityFeePerGas` call.
* `nonce`: (optional) Transaction nonce (counter). If not provided, obtained via `eth_getTransactionCount` call.

## approveTokens

```typescript
async approveTokens({ market, token, amount }: ApproveSpotParams): Promise<ContractTransactionResponse>
```

Approves the specified amount of tokens for the corresponding market contract.

* `market`: The market identifier.
* `token`: The token to be approved.
* `amount`: The amount of tokens to approve. If `bigint` is provided, then the token's contract unit is used. If `BigNumber` is provided, then the scaled unit with the token's decimals is used.

## depositTokens

```typescript
async depositTokens({ market, token, amount }: DepositSpotParams): Promise<ContractTransactionResponse>
```

Deposits the specified amount of tokens to the corresponding market contract.

* `market`: The market identifier.
* `token`: The token to be deposited.
* `amount`: The amount of tokens to deposit. The Onchain LOB scaled units are used.

## withdrawTokens

```typescript
async withdrawTokens({ market, aseTokenAmount, quoteTokenAmount, withdrawAll }: WithdrawSpotParams): Promise<ContractTransactionResponse>
```

Withdraws the specified amount of tokens or all tokens from the corresponding market contract.

* `market`: The market identifier.
* `baseTokenAmount`: The amount of base tokens to withdraw. If `bigint` is provided, then the token's contract unit is used. If `BigNumber` is provided, then the scaled unit with the token's decimals is used. Optional if `withdrawAll` is true.
* `quoteTokenAmount`: The amount of quote tokens to withdraw. If `bigint` is provided, then the token's contract unit is used. If `BigNumber` is provided, then the scaled unit with the token's decimals is used. Optional if `withdrawAll` is true.
* `withdrawAll`: A flag indicating whether to withdraw all tokens. If true, `baseTokenAmount` and `quoteTokenAmount` are ignored.

## setClaimableStatus

```typescript
async setClaimableStatus({ market, status }: SetClaimableStatusParams): Promise<ContractTransactionResponse>
```

Sets the claimable status for the corresponding market contract.

* `market`: The market identifier.
* `status`: The claimable status to be set.

## placeOrder

```typescript
async placeOrder({ market, type, side, size, price, transferExecutedTokens, maxCommission, nativeTokenToSend, useNativeToken }: PlaceOrderSpotParams): Promise<ContractTransactionResponse>
```

Places a new order in the corresponding market contract. It can place limit or market order and use native token if market supports it.

* `market`: The market identifier.
* `type`: The type of the order (limit, limit\_post\_only, ioc or market\_execution).
* `side`: The order side (buy or sell).
* `size`: The size of the order.
* `price`: The price of the order.
* `transferExecutedTokens`: Whether to transfer executed tokens automatically.
* `maxCommission`: The upper bound of commission to pay.
* `nativeTokenToSend`: The amount of native token to send.
* `useNativeToken`: Use native token for the transaction instead of the wrapped token.

### Type parameter value

There are four types of order execution behavior:

* `limit`: place in the order book or execute and place with the specified price,
* `limit_post_only`: place or cancel the order,
* `ioc`: execute order with the indicated price or better, the remainder is cancelled,
* `market_execution`: execute the full order size, price parameter is omitted.

## placeOrderWithPermit

```typescript
async placeOrderWithPermit({ market, type, side, size, price, permit, transferExecutedTokens, maxCommission }: PlaceOrderWithPermitSpotParams): Promise<ContractTransactionResponse>
```

Places a new order with a permit in the corresponding market contract if the token supports ERC20Permit interface.

* `market`: The market identifier.
* `type`: The type of the order (limit, limit\_post\_only, ioc or market\_execution).
* `side`: The order side (buy or sell).
* `size`: The size of the order.
* `price`: The price of the order.
* `permit`: The quantity of tokens to permit for the order. Ussually the same value as the approve value.
* `transferExecutedTokens`: Whether to transfer executed tokens automatically.
* `maxCommission`: The upper bound of commission to pay.

This method allows placing an order with a permit, which is useful for tokens that support permit functionality, enabling gasless approvals.

## placeMarketOrderWithTargetValue

```typescript
async placeMarketOrderWithTargetValue({ market, type, side, price, size, targetValue, maxCommission, nativeTokenToSend }: PlaceMarketOrderWithTargetValueParams): Promise<ContractTransactionResponse>
```

Places a market order with a target value of the quote token in the corresponding market contract.

* `market`: The market identifier.
* `type`: The type of the order (ioc or market\_execution).
* `side`: The order side (buy or sell).
* `price`: The price of the order.
* `size`: The quote token value to spend.
* `targetValue`: The quote token value to spend.
* `maxCommission`: The upper bound of commission to pay.
* `nativeTokenToSend`: The amount of native token to send. Use native token for the transaction instead of the wrapped token.

This method allows placing a market order by specifying the target value of the quote token, which is useful for executing orders based on a specific value rather than base token quantity.

## placeMarketOrderWithTargetValueWithPermit

```typescript
async placeMarketOrderWithTargetValueWithPermit({ market, type, side, price, size, permit, maxCommission, transferExecutedTokens }: PlaceMarketOrderWithTargetValueWithPermitParams): Promise<ContractTransactionResponse>
```

Places a market order with a target value of the quote token and a permit in the corresponding market contract.

* `market`: The market identifier.
* `type`: The type of the order (ioc or market\_execution).
* `side`: The order side (buy or sell).
* `price`: The price of the order.
* `size`: The quote token value to spend.
* `permit`: The quantity of tokens to permit for the order. Usually the same value as the approve value.
* `maxCommission`: The upper bound of commission to pay.
* `transferExecutedTokens`: Whether to transfer executed tokens automatically.

The same action as in `placeMarketOrderWithTargetValue` but it uses a token that supports permit.

## claimOrder

```typescript
async claimOrder({ market, orderId, transferExecutedTokens }: ClaimOrderSpotParams): Promise<ContractTransactionResponse>
```

Claims an order or fully cancels it in the corresponding market contract.

* `market`: The market identifier.
* `orderId`: The unique identifier of the order to be claimed.
* `transferExecutedTokens`: Whether to transfer executed tokens automatically.

## changeOrder

```typescript
async changeOrder({ market, orderId, newSize, newPrice, type, maxCommission, transferExecutedTokens }: ChangeOrderSpotParams): Promise<ContractTransactionResponse>
```

Changes an existing order in the corresponding market contract.

* `market`: The market identifier.
* `orderId`: The unique identifier of the order to be changed.
* `newSize`: The new size of the order.
* `newPrice`: The new price of the order.
* `type`: The type of the order (e.g., limit, limit\_post\_only).
* `transferExecutedTokens`: Whether to transfer executed tokens automatically.
* `maxCommission`: The upper bound of commission to pay.

## batchPlaceOrder

```typescript
async batchPlaceOrder({ market, type, orderParams: Array<{ side, size, price}>, transferExecutedTokens }: ChangeOrderSpotParams): Promise<ContractTransactionResponse>
```

Places multiple orders in the corresponding market contract.

* `market`: The market identifier.
* `type`: The type of the orders (limit, limit\_post\_only).
* `orderParams`: Orders to place:
  * `side`: the side of the order (ask or bid).
  * `size`: the size of the order.
  * `price`: the price of the order.
* `transferExecutedTokens`: Whether to transfer executed tokens automatically.

This method does not support sending native token. Approve the wrapped token that is specified in the market object.

## batchClaim

```typescript
async batchClaim({ market, claimParams: Array<{ orderId, address }>, onlyClaim }: ChangeOrderSpotParams): Promise<ContractTransactionResponse>
```

Claims or cancels specified orders.

* `market`: The market identifier.
* `orderParams`: Orders to place:
  * `orderId`: the id of the order to claim or cancel.
  * `address`: the owner of the order.
* `onlyClaim`: Whether to claim or cancel orders (`true` to claim).

## batchChangeOrder

```typescript
async batchChangeOrder({ market, type, orderParams: Array<{ newSize, newPrice}>, transferExecutedTokens }: ChangeOrderSpotParams): Promise<ContractTransactionResponse>
```

Changes multiple orders in the corresponding market contract.

* `market`: The market identifier.
* `type`: The type of the orders (limit, limit\_post\_only).
* `orderParams`: Orders to change:
  * `orderId`: the id of the order.
  * `newSize`: the new size of the order.
  * `newPrice`: the new price of the order.
* `transferExecutedTokens`: Whether to transfer executed tokens automatically.

This method cancels existing orders and places new ones. The new orders will each have new order ids.

## getMarket

```typescript
async getMarket({ market }: GetMarketParams): Promise<Market | undefined>
```

Retrieves the market information for the specified market.

* `market`: The market identifier.

## getMarkets

```typescript
async getMarkets({ market }: GetMarketsParams): Promise<Market[]>
```

Retrieves the markets.

* `market`: Optional market identifier to filter results.

## getTokens

```typescript
async getTokens({ token }: GetTokensParams): Promise<Token[]>
```

Retrieves the tokens.

* `token`: Optional token identifier to filter results.

## getOrderbook

```typescript
async getOrderbook({ market, aggregation, limit }: GetOrderbookParams): Promise<Orderbook>
```

Retrieves the orderbook for the specified market.

* `market`: The market identifier.
* `aggregation`: Optional level of price aggregation.
* `limit`: Optional limit on the number of orders to retrieve.

## getOrders

```typescript
async getOrders({ market, user, limit, status }: GetOrdersParams): Promise<Order[]>
```

Retrieves the orders for the specified market.

* `market`: The market identifier.
* `user`: The user's address.
* `limit`: Optional limit on the number of orders to retrieve.
* `status`: Optional filter for order status.

## getOrderHistory

```typescript
async getOrderHistory({ market, user, limit }: GetOrderHistoryParams): Promise<OrderHistory[]>
```

Retrieves the order history for the specified market.

* `market`: The market identifier.
* `user`: The user's address.
* `limit`: Optional limit on the number of orders to retrieve.

## getTrades

```typescript
async getTrades({ market, limit }: GetTradesParams): Promise<Trade[]>
```

Retrieves the trades for the specified market.

* `market`: The market identifier.
* `limit`: Optional limit on the number of trades to retrieve.

## getFills

```typescript
async getFills({ market, user, limit }: GetFillsParams): Promise<Fill[]>
```

Retrieves the fills for the specified market.

* `market`: The market identifier.
* `user`: The user's address.
* `limit`: Optional limit on the number of fills to retrieve.

## getCandles

```typescript
async getCandles({ market, resolution, fromTime, toTime }: GetCandlesParams): Promise<Candle[]>
```

Retrieves the candles for the specified market and resolution.

* `market`: The market identifier.
* `resolution`: The time resolution for the candles.
* `fromTime`: Optional start time for the candle data.
* `toTime`: Optional end time for the candle data.

## events

The `OnchainLobSpot.events` property defines various events that you can listen to for real-time updates. These events include:

* `marketUpdated`: Triggered when there is an update in the market.
* `orderbookUpdated`: Triggered when there is an update in the order book.
* `tradesUpdated`: Triggered when a new trade occurs.
* `userFillUpdated`: Triggered when a fill is updated.
* `userOrderUpdated`: Triggered when an order is updated.
* `userOrderHistoryUpdated`: Triggered when an order history is updated.
* `candleUpdated`: Triggered when new candle data is available.
* `allMarketsUpdated`: Triggered when there is an update across any market.
* `subscriptionError`: Triggered when there is an error related to a subscription.

You can add event listeners to these events to handle real-time data as it comes in. Events start coming after ypu subscribe to them with certain methods

## OnchainLobSpot Subscription Methods

The OnchainLobSpot class also includes methods for subscribing to and unsubscribing from various market updates, such as `subscribeToMarket`, `unsubscribeFromMarket`, `subscribeToOrderbook`, `unsubscribeFromOrderbook`, etc. These methods interact with the WebSocket API to provide real-time updates.

## Market Subscriptions

### subscribeToMarket

```typescript
subscribeToMarket({ market }: { market: string }): void
```

Subscribes to updates for a specific market.

### unsubscribeFromMarket

```typescript
unsubscribeFromMarket({ market }: { market: string }): void
```

Unsubscribes from updates for a specific market.

### subscribeToAllMarkets

```typescript
subscribeToAllMarkets(): void
```

Subscribes to updates for all markets.

### unsubscribeFromAllMarkets

```typescript
unsubscribeFromAllMarkets(): void
```

Unsubscribes from updates for all markets.

## Orderbook Subscriptions

### subscribeToOrderbook

```typescript
subscribeToOrderbook({ market, aggregation }: { market: string, aggregation: number }): void
```

Subscribes to orderbook updates for a specific market.

### unsubscribeFromOrderbook

```typescript
unsubscribeFromOrderbook({ market, aggregation }: { market: string, aggregation: number }): void
```

Unsubscribes from orderbook updates for a specific market.

## Trade Subscriptions

### subscribeToTrades

```typescript
subscribeToTrades({ market }: { market: string }): void
```

Subscribes to trade updates for a specific market.

### unsubscribeFromTrades

```typescript
unsubscribeFromTrades({ market }: { market: string }): void
```

Unsubscribes from trade updates for a specific market.

## User Order Subscriptions

### subscribeToUserOrders

```typescript
subscribeToUserOrders({ user, market }: { user: string, market?: string }): void
```

Subscribes to user order updates for a specific market and user.

### unsubscribeFromUserOrders

```typescript
unsubscribeFromUserOrders({ user, market }: { user: string, market?: string }): void
```

Unsubscribes from user order updates for a specific market and user.

## User Order History Subscriptions

### subscribeToUserOrderHistory

```typescript
subscribeToUserOrderHistory({ user, market }: { user: string, market?: string }): void
```

Subscribes to user order history updates for a specific market and user.

### unsubscribeFromUserOrderHistory

```typescript
unsubscribeFromUserOrderHistory({ user, market }: { user: string, market?: string }): void
```

Unsubscribes from user order history updates for a specific market and user.

## User Fill Subscriptions

### subscribeToUserFills

```typescript
subscribeToUserFills({ user, market }: { user: string, market?: string }): void
```

Subscribes to user fill updates for a specific market and user.

### unsubscribeFromUserFills

```typescript
unsubscribeFromUserFills({ user, market }: { user: string, market?: string }): void
```

Unsubscribes from user fill updates for a specific market and user.

## Candle Subscriptions

### subscribeToCandles

```typescript
subscribeToCandles({ market, resolution }: { market: string, resolution: CandleResolution }): void
```

Subscribes to candle updates for a specific market and resolution.

### unsubscribeFromCandles

```typescript
unsubscribeFromCandles({ market, resolution }: { market: string, resolution: CandleResolution }): void
```

Unsubscribes from candle updates for a specific market and resolution.

## Examples

### Post a new order (view with HTTP API)

```ts
import { ethers, type ContractTransactionResponse } from 'ethers';
import { OnchainLobClient } from 'onchain-lob-sdk';

// wallet = new ethers.Wallet(<yourPrivateKey>, <provider>);

const onchainLobClient = new OnchainLobClient({
  apiBaseUrl: 'https://api-dev.xpressprotocol.com',
  webSocketApiBaseUrl: 'wss://sockets-dev.xpressprotocol.com',
  signerOrProvider: wallet,
});

const market = '<orderbookAddress>';
let tx: ContractTransactionResponse;

// Approve tokens for the future order
tx = await onchainLobClient.spot.approveTokens({
  market,
  amount: new BigNumber(45.123),
  isBaseToken: true
});
console.log(tx.hash);

// Create a new order
tx = await onchainLobClient.spot.placeOrder({
  market,
  type: 'limit',
  side: 'ask',
  size: new BigNumber(45.123),
  price: new BigNumber(1.17),
  maxCommission: new bigNumber(0.1)
});
console.log(tx.hash);

// Get user orders
const orders = await onchainLobClient.spot.getOrders({ market, user: wallet.address });
console.log(orders);

// Find the new order
const newOrder = orders.find(o => o.txnHash === tx.hash);
console.log(newOrder);
```

### Post a new order (view with WebSockets)

```ts
import { ethers, type ContractTransactionResponse } from 'ethers';
import { OnchainLobClient } from 'onchain-lob-sdk';

// wallet = new ethers.Wallet(<yourPrivateKey>, <provider>);

const onchainLobClient = new OnchainLobClient({
  apiBaseUrl: 'https://api-dev.xpressprotocol.com',
  webSocketApiBaseUrl: 'wss://sockets-dev.xpressprotocol.com',
  signer: wallet,
});

const market = '<orderbookAddress>';
let tx: ContractTransactionResponse | undefined;
const user = wallet.address;

async function waitTx(): Promise<void> {
  while (!tx) {
    await new Promise(resolve => setTimeout(resolve, 100));
  }
}

// Subscribe to orders
client.spot.events.userOrdersUpdated.addListener(async (_, __, orders) => {
  await waitTx();

  const newOrder = orders.find(o => o.txnHash === tx!.hash);
  if (newOrder) {
    console.log(newOrder);
  }
});
client.spot.subscribeToUserOrders({ market, user });

// Approve tokens for the future order
tx = await onchainLobClient.spot.approveTokens({
  market,
  amount: new BigNumber(45.123),
  isBaseToken: true
});
console.log(tx.hash);

// Create a new order
tx = await onchainLobClient.spot.placeOrder({
  market,
  type: 'limit',
  side: 'ask',
  size: new BigNumber(45.123),
  price: new BigNumber(1.17)
  maxCommission: new bigNumber(0.1)
});
console.log(tx.hash);
```

### getOrderbook

Returns snapshot of the orderbook.

```ts
const orderbook = await onchainLobClient.spot.getOrderbook({
  market: '<orderbookAddress>', // The address of the orderbook
  aggregation: 4, // Number of rounding decimals [optional]
  limit: 10, // Levels for each side [20 by default]
});
```

### getOrders

Returns user's orders.

```ts
const orders = await onchainLobClient.spot.getOrders({
  market: '<orderbookAddress>', // The address of the orderbook
  user: '<userAddress>', // The address of the user
  limit: 10, // Number of orders to retrieve [100 by default]
  status: 'open', // Order statuses to filter by
});
```

### getOrderHistory

Returns user's order history.

```ts
const orderHistory = await onchainLobClient.spot.getOrderHistory({
  market: '<orderbookAddress>', // The address of the orderbook
  user: '<userAddress>', // The address of the user
  limit: 10, // Number of history logs to retrieve [100 by default]
});
```

### getTrades

Returns last trades.

```ts
const trades = await onchainLobClient.spot.getTrades({
  market: '<orderbookAddress>', // The address of the orderbook
  limit: 10, // Number of trades to retrieve [100 by default]
});
```

### getFills

Returns user's fills.

```ts
const fills = await onchainLobClient.spot.getFills({
  market: '<orderbookAddress>', // The address of the orderbook
  user: '<userAddress>', // The address of the user
  limit: 10, // Number of fills to retrieve [100 by default]
});
```

### getMarkets

Returns market data.

```ts
const markets = await onchainLobClient.spot.getMarkets({
  market: '<orderbookAddress>', // The address of the orderbook
});
// If the market is not provided, data for all markets will be returned.
const allMarkets = await onchainLobClient.spot.getMarkets({
});
```


# Router Integration

To make the integration of XPress with third-party router protocols seamless, we've open-sourced a sample router implementation.&#x20;

This implementation serves as a reference guide for developers looking to connect their protocols to XPress orderbooks.

<https://github.com/longgammalabs/onchain-lob-router>


