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_KEYandOLYMPEX_PASSPHRASEin your server’s environment, andsign-request.tssaved next to your code.- Node.js 22.18 or later, which runs
.tsfiles 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
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.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 The fee is an estimate, and it runs low. It comes from the liquidity source’s
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.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. Nothing moves when you approve or create the order. At execution, Olympex pulls
approve replaces the allowance instead of adding to it, so approving only this order’s reserve would take it away from the others.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: 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
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
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
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 An order can stay
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.
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.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: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, withdeletedAtset, and it still appears in the list. - The same list request with the maker in lowercase returns
[]: theaccountTofilter matches case-sensitively. - The allowance is back to its value before step 4.
Common pitfalls
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.