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.
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. Returnstype(uint256).maxif 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.
Parameters: Same as limitBid, but uses baseAmount instead of rawAmount.
| Parameter | Usage for Ask |
|---|---|
rawAmount | Not used (set to 0) |
baseAmount | Amount 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.
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.
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.
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)
Tip
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.
Warning
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)¶
View Complete Minimal ABI
[
{
"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": []
}
]
Note
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" }]
}
]
Tip
See the Order Lifecycle Tutorial for a complete Python example using these ABIs.