Skip to main content

Market Router

The Market Router is the primary entry point for all trading operations on Sera. It provides a user-friendly interface for placing orders, executing trades, and claiming proceeds. Address (Sepolia): 0x82bfe1b31b6c1c3d201a0256416a18d93331d99e

Limit Orders

limitBid

Places a limit buy order on the order book.
function limitBid(LimitOrderParams calldata params) external payable returns (uint256)
Parameters:
struct LimitOrderParams {
    address market;       // Market (OrderBook) address
    uint64 deadline;      // Unix timestamp - tx reverts after this
    address user;         // Address to receive proceeds
    uint16 priceIndex;    // Price book index
    uint64 rawAmount;     // Quote amount in raw units
    bool postOnly;        // If true, reverts if order would fill
    bool useNative;       // If true, use native token
    uint256 baseAmount;   // Not used for bids (set to 0)
}
Returns:
  • uint256 - The order index. Returns type(uint256).max if order was fully filled.
Example:
const params = {
  market: "0x...",
  deadline: Math.floor(Date.now() / 1000) + 3600,
  user: userAddress,
  priceIndex: 6500,
  rawAmount: 1000000n,
  postOnly: false,
  useNative: false,
  baseAmount: 0n
};

const orderId = await router.limitBid(params);

limitAsk

Places a limit sell order on the order book.
function limitAsk(LimitOrderParams calldata params) external payable returns (uint256)
Parameters: Same as limitBid, but uses baseAmount instead of rawAmount.
ParameterUsage for Ask
rawAmountNot used (set to 0)
baseAmountAmount of base tokens to sell
Example:
const params = {
  market: "0x...",
  deadline: Math.floor(Date.now() / 1000) + 3600,
  user: userAddress,
  priceIndex: 6600,
  rawAmount: 0n,
  postOnly: false,
  useNative: false,
  baseAmount: ethers.parseUnits("100", 18)  // 100 tokens
};

const orderId = await router.limitAsk(params);

limitOrder

Places multiple limit orders in a single transaction.
function limitOrder(
    GeneralLimitOrderParams[] calldata limitOrderParamsList,
    ClaimOrderParams[] calldata claimParamsList
) external payable returns (uint256[] memory orderIds)
Parameters:
struct GeneralLimitOrderParams {
    LimitOrderParams params;
    bool isBid;  // true for bid, false for ask
}
Example:
const orders = [
  { params: bidParams1, isBid: true },
  { params: askParams1, isBid: false },
  { params: bidParams2, isBid: true }
];

const claimParams = [];  // Optional: claim orders first

const orderIds = await router.limitOrder(orders, claimParams);

Market Orders

marketBid

Executes a market buy order immediately against existing asks.
function marketBid(MarketOrderParams calldata params) external payable
Parameters:
struct MarketOrderParams {
    address market;          // Market address
    uint64 deadline;         // Unix timestamp
    address user;            // Recipient of purchased tokens
    uint16 limitPriceIndex;  // Maximum price willing to pay
    uint64 rawAmount;        // Max quote to spend (if expendInput)
    bool expendInput;        // If true, spend all input tokens
    bool useNative;          // If true, use ETH
    uint256 baseAmount;      // Min base to receive (if expendInput)
}
Example - Spend exactly 100 USDC:
const params = {
  market: "0x...",
  deadline: Math.floor(Date.now() / 1000) + 300,
  user: userAddress,
  limitPriceIndex: 7000,  // Max price
  rawAmount: 100n,        // Spend 100 raw units
  expendInput: true,
  useNative: false,
  baseAmount: 90n         // Receive at least 90 base tokens
};

await router.marketBid(params);

marketAsk

Executes a market sell order immediately against existing bids.
function marketAsk(MarketOrderParams calldata params) external payable
Example - Sell exactly 100 tokens:
const params = {
  market: "0x...",
  deadline: Math.floor(Date.now() / 1000) + 300,
  user: userAddress,
  limitPriceIndex: 6000,  // Min price
  rawAmount: 95n,         // Receive at least 95 quote
  expendInput: true,
  useNative: false,
  baseAmount: ethers.parseUnits("100", 18)  // Sell 100 tokens
};

await router.marketAsk(params);

Claiming

claim

Claims proceeds from filled orders across multiple markets.
function claim(
    uint64 deadline,
    ClaimOrderParams[] calldata paramsList
) external
Parameters:
struct ClaimOrderParams {
    address market;
    OrderKey[] orderKeys;
}

struct OrderKey {
    uint16 priceIndex;
    uint256 orderIndex;
    bool isBid;
}
Example:
const claimParams = [{
  market: "0x...",
  orderKeys: [
    { priceIndex: 6500, orderIndex: 42, isBid: true },
    { priceIndex: 6500, orderIndex: 43, isBid: true }
  ]
}];

await router.claim(
  Math.floor(Date.now() / 1000) + 3600,
  claimParams
);

Combined Operations

limitBidAfterClaim

Claims orders first, then places a new bid using the claimed proceeds.
function limitBidAfterClaim(
    ClaimOrderParams[] calldata claimParamsList,
    LimitOrderParams calldata limitOrderParams
) external payable returns (uint256)
Use combined operations to save gas when reinvesting proceeds into new orders.

limitAskAfterClaim

Claims orders first, then places a new ask.
function limitAskAfterClaim(
    ClaimOrderParams[] calldata claimParamsList,
    LimitOrderParams calldata limitOrderParams
) external payable returns (uint256)

marketBidAfterClaim

Claims orders first, then executes a market buy.
function marketBidAfterClaim(
    ClaimOrderParams[] calldata claimParamsList,
    MarketOrderParams calldata marketOrderParams
) external payable

marketAskAfterClaim

Claims orders first, then executes a market sell.
function marketAskAfterClaim(
    ClaimOrderParams[] calldata claimParamsList,
    MarketOrderParams calldata marketOrderParams
) external payable

View Functions

isRegisteredMarket

Checks if a market is registered with the router.
function isRegisteredMarket(address market) external view returns (bool)
Only trade on registered markets. Unregistered markets may be malicious.

Minimal ABI Reference

For integrating with the Market Router in JavaScript/TypeScript or Python, use these minimal ABI definitions:

JSON ABI (for ethers.js, web3.js, web3.py)

[
  {
    "name": "limitBid",
    "type": "function",
    "stateMutability": "payable",
    "inputs": [
      {
        "name": "params",
        "type": "tuple",
        "components": [
          { "name": "market", "type": "address" },
          { "name": "deadline", "type": "uint64" },
          { "name": "claimBounty", "type": "uint32" },
          { "name": "user", "type": "address" },
          { "name": "priceIndex", "type": "uint16" },
          { "name": "rawAmount", "type": "uint64" },
          { "name": "postOnly", "type": "bool" },
          { "name": "useNative", "type": "bool" },
          { "name": "baseAmount", "type": "uint256" }
        ]
      }
    ],
    "outputs": [{ "name": "", "type": "uint256" }]
  },
  {
    "name": "limitAsk",
    "type": "function",
    "stateMutability": "payable",
    "inputs": [
      {
        "name": "params",
        "type": "tuple",
        "components": [
          { "name": "market", "type": "address" },
          { "name": "deadline", "type": "uint64" },
          { "name": "claimBounty", "type": "uint32" },
          { "name": "user", "type": "address" },
          { "name": "priceIndex", "type": "uint16" },
          { "name": "rawAmount", "type": "uint64" },
          { "name": "postOnly", "type": "bool" },
          { "name": "useNative", "type": "bool" },
          { "name": "baseAmount", "type": "uint256" }
        ]
      }
    ],
    "outputs": [{ "name": "", "type": "uint256" }]
  },
  {
    "name": "marketBid",
    "type": "function",
    "stateMutability": "payable",
    "inputs": [
      {
        "name": "params",
        "type": "tuple",
        "components": [
          { "name": "market", "type": "address" },
          { "name": "deadline", "type": "uint64" },
          { "name": "user", "type": "address" },
          { "name": "limitPriceIndex", "type": "uint16" },
          { "name": "rawAmount", "type": "uint64" },
          { "name": "expendInput", "type": "bool" },
          { "name": "useNative", "type": "bool" },
          { "name": "baseAmount", "type": "uint256" }
        ]
      }
    ],
    "outputs": []
  },
  {
    "name": "marketAsk",
    "type": "function",
    "stateMutability": "payable",
    "inputs": [
      {
        "name": "params",
        "type": "tuple",
        "components": [
          { "name": "market", "type": "address" },
          { "name": "deadline", "type": "uint64" },
          { "name": "user", "type": "address" },
          { "name": "limitPriceIndex", "type": "uint16" },
          { "name": "rawAmount", "type": "uint64" },
          { "name": "expendInput", "type": "bool" },
          { "name": "useNative", "type": "bool" },
          { "name": "baseAmount", "type": "uint256" }
        ]
      }
    ],
    "outputs": []
  },
  {
    "name": "claim",
    "type": "function",
    "stateMutability": "nonpayable",
    "inputs": [
      { "name": "deadline", "type": "uint64" },
      {
        "name": "paramsList",
        "type": "tuple[]",
        "components": [
          { "name": "market", "type": "address" },
          {
            "name": "orderKeys",
            "type": "tuple[]",
            "components": [
              { "name": "isBid", "type": "bool" },
              { "name": "priceIndex", "type": "uint16" },
              { "name": "orderIndex", "type": "uint256" }
            ]
          }
        ]
      }
    ],
    "outputs": []
  }
]
The claimBounty field in limit order params is reserved for future use. Always set it to 0.

ERC20 Token ABI

For token approvals before trading:
[
  {
    "name": "approve",
    "type": "function",
    "inputs": [
      { "name": "spender", "type": "address" },
      { "name": "amount", "type": "uint256" }
    ],
    "outputs": [{ "name": "", "type": "bool" }]
  },
  {
    "name": "allowance",
    "type": "function",
    "stateMutability": "view",
    "inputs": [
      { "name": "owner", "type": "address" },
      { "name": "spender", "type": "address" }
    ],
    "outputs": [{ "name": "", "type": "uint256" }]
  },
  {
    "name": "balanceOf",
    "type": "function",
    "stateMutability": "view",
    "inputs": [{ "name": "account", "type": "address" }],
    "outputs": [{ "name": "", "type": "uint256" }]
  },
  {
    "name": "decimals",
    "type": "function",
    "stateMutability": "view",
    "inputs": [],
    "outputs": [{ "name": "", "type": "uint8" }]
  },
  {
    "name": "symbol",
    "type": "function",
    "stateMutability": "view",
    "inputs": [],
    "outputs": [{ "name": "", "type": "string" }]
  }
]
See the Order Lifecycle Tutorial for a complete Python example using these ABIs.