Skip to main content
A limit order sells amount of one token for another. The order executes when the market price of inTokenAddress, in outTokenAddress, reaches priceTrigger or better. Olympex executes it from the maker’s wallet, so the wallet first approves the Olympex order contract and signs the token pair. This guide sells 0.5 WETH for USDC on Polygon at 4,200 USDC per WETH, follows the order, then cancels it and lowers the allowance.
You need API credentials and the signing helper from Sign requests, and a wallet on Polygon that holds WETH and POL for gas. Order signatures and allowances explains what the wallet’s signature and allowance let Olympex do: read it before you run this with real funds.

Prerequisites

  • OLYMPEX_API_KEY_ID, OLYMPEX_SECRET_KEY and OLYMPEX_PASSPHRASE in your server’s environment, and sign-request.ts saved next to your code.
  • Node.js 22.18 or later, which runs .ts files directly, in an ES module project (npm pkg set type=module), and ethers v6 (npm install ethers).
  • An RPC URL for Polygon, as POLYGON_RPC_URL.
  • A wallet that is an externally owned account (EOA), with its private key in WALLET_PRIVATE_KEY. It holds the WETH to sell plus a little more for the execution fee, and POL for its approval transactions. Smart-contract wallets (Safe, ERC-4337) can’t sign orders: only 65-byte ECDSA signatures are accepted.

Steps

A limit order is a real trade. Olympex executes it from the wallet when the market reaches priceTrigger or better, and execution moves funds on mainnet. Use a small amount from a dedicated wallet and a price you’re willing to trade at.
1

Set up and check the chain

The snippets in these steps form one script, create-limit-order.ts. Run it with node create-limit-order.ts.GET /chains returns the IDs of the chains Olympex has enabled, as integers. Check your chain there instead of hard-coding the list. Limit orders and DCA execute only on the chains in ORDER_CONTRACTS, where the Olympex order contract is deployed.
GET requests have no body: the helper signs the empty string. On Polygon the order contract is 0x50186B03dc7315271FB58da0d3b9f2c65A51dA76. It’s not the contractToApprove that POST /swap returns, which is for swaps.
2

Resolve the tokens with GET /tokens

GET /tokens returns every token Olympex lists on a chain, with its address, symbol, name and decimals. Match tokens by address, never by symbol, and compare addresses case-insensitively: their casing varies.
The list holds hundreds of tokens and changes rarely, so cache it on your side, for example for 24 hours, instead of calling it for every order.Limit orders need each token’s real symbol (step 6). A listed symbol can differ from the token contract’s symbol(): a few carry a numeric suffix that tells tokens with the same symbol apart, such as STRK_1, and a few differ in case. findToken trims the symbol and drops a trailing _<number>. To be certain, read symbol() from the token contract instead.The token you sell must be an ERC-20. To sell a chain’s native token, wrap it first: WETH (0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2) on Ethereum, WBNB (0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c) on BNB Chain or WPOL (0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270) on Polygon. ERC-20 tokens whose transfer and approve don’t return a boolean can’t be sold either: USDT isn’t supported as the token you sell in limit orders or DCA on Ethereum. Neither are fee-on-transfer tokens.
3

Estimate the execution fee with POST /quotes

Olympex pays the gas to execute the order and takes it back from the maker in the token sold, as a second transfer. So the allowance you grant must cover amount plus that fee. Estimate the fee with POST /quotes and "includeGasInfo": true: dataFeeTransaction.transactionFeeInToken is the fee in human-readable units of the token sold.
The fee is an estimate, and it runs low. It comes from the liquidity source’s estimatedGas, which covers only the source’s part of the route, not the Olympex contracts, and gas prices move between now and execution. So add a buffer: this guide requests the quote with gasMultiplier HIGH, which scales the gas estimate 4×, so transactionFeeInToken and valueToApprove (amount plus the fee) already include it. Size the buffer to how much gas prices move on your chain.gasPriceGwei is the chain’s gas price in whole gwei, rounded up, the form quotes take, and the order stores it as its gasPrice in step 6. On a chain whose gas price is below 1 gwei, it rounds up to "1", above the real price.
4

Approve the order contract

Read the wallet’s current allowance for the order contract, then approve that value plus this order’s reserve. The allowance is shared: every open limit order and active DCA strategy that sells the same token on the same chain draws on it. approve replaces the allowance instead of adding to it, so approving only this order’s reserve would take it away from the others.
Nothing moves when you approve or create the order. At execution, Olympex pulls amount through the order contract, swaps it, sends all the output to the maker, and takes the fee. The wallet must still hold amount plus the fee then, or the order can’t execute.The allowance is the on-chain limit on what Olympex can move from the wallet. Approve only what your open orders need, and never an unlimited amount.
5

Sign the token pair

The maker signs the pair once: keccak256(abi.encodePacked(maker, maker, tokenIn, tokenOut)), signed with personal_sign over its 32 raw bytes. Save this helper as sign-order-pair.ts:
sign-order-pair.ts
Then sign WETH for USDC:
Olympex doesn’t check the signature when you create the order: a wrong one makes execution fail later. The self-check in signOrderPair catches the usual mistake, signing the hex string instead of the bytes. Address casing doesn’t change the hash.The signature lets the Olympex order contract swap WETH for USDC from this wallet. It doesn’t bind an amount, price, expiry, chain or order: Olympex enforces those when it executes. It stays valid after you cancel, and the same signature serves limit orders and DCA strategies that sell WETH for USDC. Selling USDC for WETH needs its own signature, because the token order is part of the hash.
6

Create the order with POST /limit-order

POST /limit-order stores the order as pending. Olympex first checks that it has a reference price for the pair.Don’t send any other field: the ones Olympex sets as it executes the order, such as status and txHash, return 400 VALIDATION_ERROR.
Response
The response returns chainId, amount, price and priceTrigger as numbers. Symbols can come back normalized: WETH returns as ETH, WBNB as BNB and WPOL as POL. Any other returned symbol that isn’t the one you sent means Olympex prices the order from another token’s market: the check above cancels such an order. deletedAt is an empty string until the order is cancelled.If Olympex finds no reference price for the pair, the call fails with 400 VALIDATION_ERROR “Not exist reference price for this pair WETH/USDC”, with the symbols you sent, and no order is created. The error can be temporary, so retry later with backoff before you rule the pair out. See Reference price.Each successful call creates a new order, and Olympex ignores any id you send. If the call times out or fails with a 5xx, don’t send it again: the order may exist. List your orders first, and match on the expired value your script generated:
7

Follow the order with GET /limit-order/{id}

Olympex doesn’t notify you when an order changes: poll GET /limit-order/{id}.Treat any other value as not final, and give your poller a cap: an order can stay in a status that isn’t final.
An order can stay pending until the market reaches its price, so poll at an interval that suits your product, and route the GET through your retry wrapper: GET is safe to repeat. GET /limit-order lists every order created with your API key, with the optional filters status, chainId and accountTo. It ignores any other query parameter, so a misspelt filter returns every order. Send each filter once: a parameter sent twice matches nothing.
To change the price, amount, expiry, slippage or gas price of a pending order, send only those fields to PATCH /limit-order/{id}. Send price and priceTrigger together: a PATCH with only priceTrigger leaves price unchanged. If you change amount, change the allowance with it. To change the tokens, the chain or the maker, cancel the order and create a new one. On an order that is no longer pending, the PATCH fails with 409 CONFLICT.
8

Cancel the order and lower the allowance

DELETE /limit-order/{id} cancels a pending order: its status becomes cancelled and deletedAt records the time of the call. The order stays readable and stays in the list. A DELETE on an order that is no longer pending, including one you already cancelled, fails with 409 CONFLICT.Cancelling doesn’t touch your allowance, and the pair signature stays valid. Lower the allowance by this order’s reserve, and keep what your other open orders need:
If execution starts after your last poll, the DELETE fails with 409 CONFLICT: read the order again and handle its new status. When an order completes or fails, set the allowance to what your remaining open orders and active DCA strategies need. To stop everything that sells WETH on Polygon at once, set the allowance to 0.

Verify

Run these at the end of the script:
  • The order is cancelled, with deletedAt set, and it still appears in the list.
  • The same list request with the maker in lowercase returns []: the accountTo filter matches case-sensitively.
  • The allowance is back to its value before step 4.

Common pitfalls

Signing the hex string. Sign the 32 bytes of the hash (getBytes(inner)), not its hex string. Olympex accepts either when you create the order, but a signature over the string makes execution fail. Check every signature with verifyMessage before you send it.
An allowance that covers only amount. The fee is taken in the token sold, on top of amount. Approve amount plus the fee estimate with a buffer, or the order can’t execute. The quote’s estimate leaves out the Olympex contracts, so don’t approve it without a buffer.
Wrong token symbols. tokenASymbol and tokenBSymbol must be the tokens’ real symbols. Olympex doesn’t check them against the token contracts: a real but wrong symbol, such as WBTC on a WETH order, is accepted, and the order is priced from that token’s market. Drop list suffixes such as _1, and check the symbols the response returns.
Overwriting a shared allowance. Limit orders and DCA strategies that sell the same token on the same chain share one allowance. Approve the sum they need: approving one order’s amount on its own takes the allowance away from the others.
Retrying a create. Each successful POST /limit-order creates a new order, and a timeout doesn’t tell you whether one was created. List your orders before you send it again, or you can end up with two live orders on the same allowance.
Tokens the order contract can’t sell. Native tokens (wrap them first), USDT on Ethereum and fee-on-transfer tokens can’t be the token you sell.
An unlimited approval. The pair signature stays valid after you cancel, so the allowance is the only on-chain limit on what Olympex can move from the wallet. Keep it to what your open orders need.

What’s next

Limit orders

Order terms, statuses and the reference price.

Order signatures and allowances

What the signature and the allowance let Olympex do.

Run a DCA strategy

Spend a token in equal orders over time.

Create a limit order reference

Every field of POST /limit-order.