OKX DEX
Swaps tokens on-chain through the OKX DEX aggregator API, with wallets derived from the configured mnemonic (EVM chains, Tron, Solana, TON, Aptos, SUI, Starknet). Only market swaps on a single chain are supported; tickers, K-lines, trades and token lists come from the OKX DEX market API. API credentials default to the platform's built-in project credentials and can be replaced with your own OKX API credentials via exchange.IO("config", ...) (apply for them on the OKX developer portal https://web3.okx.com/onchainos/dev-portal; the source of each field is described under that command). Each chain always uses the first account of the mnemonic (m/44'/60'/0'/0/0 on EVM chains); choosing another account index or importing a private key is not supported.
Names and Configuration
exchange.GetName(): OKX_DEX (Spot); aliases: OKX Web3.
| Field | Required | Description |
|---|---|---|
| Mnemonic Phrase | Yes | The wallet mnemonic (BIP39, 12 or 24 words; private keys are not supported) from which the wallet address on each chain is derived, using only the first account of each chain (see the notes for the derivation paths). The OKX API credentials are not entered here; see exchange.IO("config", ...). |
Trading Pairs and Contract Codes
Pair examples: 1:ETH_USD, 501:SOL_USD, 1:ETH_1:USDC
Symbols are written as <chain>:<token>_USD (for example 1:ETH_USD, 501:SOL_USD) for tickers, K-lines and trades; orders (swaps) use the two-sided form <chain>:<token>_<chain>:<token>, for example 1:ETH_1:USDC, with both sides on the same chain. The chain may be the OKX chain index or a chain name (ETH, SOL, TRX, APT, SUI, TON, STRK, etc.; register other aliases with regChain).
A token may be a token name or a contract address (such as 1:0xa0b8..._USD). Token names are case-sensitive (OKX treats BAX and BAx as two tokens). Several contracts sharing one name on the same chain (for example GALA's old and new contracts) are left out of the token list and cannot be used by name; use the contract address, or bind the name to an address with regToken.
Exchange-specific IO Commands
| Command | Arguments | Description | Returns |
|---|---|---|---|
config | string(JSON) | Set the OKX API credentials; the fields ApiKey, SecretKey, Passphrase and Project are all required. (more below the table) | true on success. |
key | string | Replace the wallet mnemonic (12 or 24 words) at runtime; the current wallet is kept if parsing fails. | true on success. |
address | [chainIndex] | Get the wallet address on a chain (the chain may be a chain index or a chain name); Ethereum (1) when omitted. | — |
addresses | — | Export the wallet addresses on all chains. | An object keyed by chain index with the addresses as values. |
slippage | [number] | Read without an argument, set with one; swap slippage in percent, range (0, 50], default 0.5. | The current value when reading (a string such as "0.5"), true when set. |
gasLevel | [string] | Read without an argument, set with one; gas level: average (default), fast, slow. | The current value when reading, true when set. |
gasMultiplier | [number] | Read without an argument, set with one; multiplier of the gas limit of EVM transactions (≥1, default 1.5). | The current value when reading, true when set. |
allChainBalance | [bool] | Read without an argument, set with one; whether exchange.GetAssets() queries balances on all chains (only Ethereum by default); when on, Equity of exchange.GetAccount() also covers all chains. (more below the table) | The current value when reading, true when set. |
rpc | [chain[, url]] | Query or set custom RPC addresses per chain; chain must be the chain index (such as 1, 501), a chain name has no effect. (more below the table) | true when set or deleted. |
regChain | chainId, alias | Register a chain alias that can then replace the chain index in symbols. Aliases are case-insensitive, must not contain _ or :, and are at most 20 characters. | true on success. |
regToken | chainId, alias, address | Bind a token name to a contract address on a chain (chainId must be the chain index); a bound name takes precedence over the OKX token list and is case-insensitive when used; naming rules as for regChain. | true on success. |
quote | symbol, amount | Read-only quote preview (two-sided symbol, for example 1:USDC_1:ETH, both sides on one chain); amount is the quantity of the first token (spent), and the slippage setting applies; no on-chain transaction is built. | {toAmount, fromAmount, priceImpact, estimateGasFee, routerList, info}: toAmount and fromAmount are token amounts scaled by decimals (numbers); priceImpact (percent) and estimateGasFee are strings as given by OKX; routerList is the route array (each item has dexProtocol.dexName, dexProtocol.percent and more); info is the raw data of the OKX quote API as a JSON string. |
allowance | symbol[, spender] | Query the wallet's ERC-20 allowance for the spender (first token of the symbol, or just <chain>:<token> such as 1:USDC); without a spender, the OKX DEX approval contract is used. (more below the table) | The allowance, as a decimal string in the smallest unit. |
approve | symbol[, amount] | ERC-20 approval for the first token of the symbol (or just <chain>:<token>; EVM chains only); amount is in token units (scaled by the token's decimals), the maximum amount when omitted; waits for the transaction to be confirmed (up to 60 seconds). | The transaction hash. |
signTx | tx, chainIndex | Sign only, without broadcasting. (more below the table) | The signed transaction (a string). |
broadcast | signedTx, chainIndex | Broadcast a signed transaction. | {txHash, orderId} |
marketSupportedChains | — | Read-only list of chains supported by the market API. | — |
balanceSupportedChains | — | Read-only list of chains supported by the balance API. | — |
swapSupportedChains | — | Read-only list of chains supported by the swap API. | The raw array of the OKX API; each item has chainIndex, chainName and dexTokenApproveAddress (the approval contract). |
broadcastSupportedChains | — | Read-only list of chains supported by the broadcast API. | — |
tokenSearch | chains, search | Search tokens by name or address (chains is a comma-separated list of chain indexes); returns the raw data of the OKX API. | An array; each item has chainIndex, tokenSymbol, tokenName, tokenContractAddress, decimal, price, liquidity and more (all strings). |
allTokens | chainIndex | List all swappable tokens on a chain; returns the raw data of the OKX API. | An array; each item has tokenSymbol, tokenName, tokenContractAddress, decimals and more. |
The rest of the longer descriptions in the table:
config: Without it the platform's built-in project credentials are used (one rate limit shared by all users, so frequent queries run into HTTP 429 more easily).
Apply for credentials on the OKX developer portal: https://web3.okx.com/onchainos/dev-portal (the old /build/dev-portal address no longer works). After logging in, create a project, then create an API key under it: Project is the project's Project ID; ApiKey and SecretKey are the API key and secret key generated with the API key (the secret key is shown only once, at creation); Passphrase is the passphrase you set when creating the API key. This SecretKey is the OKX API secret, unrelated to the wallet mnemonic entered in the configuration.
allChainBalance: The all-chain query groups chains by wallet address (EVM chains share one address, up to 50 chains per request; every other chain is queried on its own) and waits 1 second between consecutive requests to stay under the rate limit, so one query takes over ten seconds (exchange.GetAccount()also queries the valuation, doubling the requests); do not poll it frequently.rpc: Without arguments returns all, with only a chain returns that chain's address (an empty string if not set), an empty url deletes it. On EVM chains, allowance queries (allowanceand the automatic check before orders) require an RPC, which also backs up OKX's nonce API when it fails; Solana, Tron, SUI and TON signing query on-chain state through the chain's public node when none is configured. Unichain (130) comes with its official RPC preset.allowance: EVM chains only; configure the chain's RPC withexchange.IO("rpc", chainIndex, url)first; the native coin has no allowance and fails.signTx:txis the transaction JSON (a string or an object);chainIndexmay be a chain index or a chain name. On EVM chains the transaction needsto,dataandgas(orgasLimit), optionallyvalue,gasPriceandmaxPriorityFeePerGas(the same as thetxreturned by the OKX swap API): the nonce is looked up automatically, the gas limit is multiplied bygasMultiplier, and a missinggasPriceis queried through the chain's RPC.
For the common commands api, base and currency see exchange.IO.
Common Usage
Preview a quote before swapping (read-only, no transaction)
javascript
function main() {
// How much ETH 100 USDC buys on Ethereum (chain index 1)
var q = exchange.IO("quote", "1:USDC_1:ETH", 100)
if (!q) {
Log("Quote failed:", GetLastError())
return
}
Log("spend:", q.fromAmount, "USDC", "receive:", q.toAmount, "ETH")
Log("price:", q.fromAmount / q.toAmount, "price impact (%):", q.priceImpact,
"estimated gas:", q.estimateGasFee)
for (var i = 0; i < q.routerList.length; i++) {
var p = q.routerList[i].dexProtocol
Log("route:", p.dexName, p.percent + "%")
}
var info = JSON.parse(q.info) // raw data of the OKX quote API
Log("trade fee (USD):", info.tradeFee)
}
Configure an RPC, check the allowance, swap at market, then query the result
javascript
function main() {
// Allowance queries and the automatic approval before orders need the chain's RPC
exchange.IO("rpc", 1, "https://ethereum-rpc.publicnode.com")
exchange.IO("slippage", 1) // 1% slippage
exchange.IO("gasLevel", "fast")
var allowance = exchange.IO("allowance", "1:USDC") // decimal string, smallest unit
Log("USDC allowance:", allowance)
if (Number(allowance) < 20e6) { // USDC has 6 decimals
// Approve 100 USDC only (unlimited without an amount); returns the hash once mined
Log("approval tx:", exchange.IO("approve", "1:USDC", 100))
}
// For a buy the amount is the second token spent: spend 20 USDC on ETH
var id = exchange.CreateOrder("1:ETH_1:USDC", "buy", -1, 20)
if (!id) {
Log("Swap failed:", GetLastError())
return
}
for (var i = 0; i < 20; i++) {
var o = exchange.GetOrder(id)
if (o && o.Status != ORDER_STATE_PENDING) {
Log("status:", o.Status, "ETH bought:", o.DealAmount, "average price:", o.AvgPrice)
break
}
Sleep(3000)
}
}
Search tokens, bind a name to a contract address and register a chain alias
javascript
function main() {
// Search USDC on Base (chain index 8453); returns the raw data of the OKX API
var rows = exchange.IO("tokenSearch", "8453", "USDC")
if (!rows || rows.length == 0) {
Log("Nothing found:", GetLastError())
return
}
for (var i = 0; i < rows.length; i++) {
var r = rows[i]
Log(r.chainIndex, r.tokenSymbol, r.tokenName, r.tokenContractAddress)
}
var all = exchange.IO("allTokens", "8453") // every swappable token on Base
Log("swappable tokens:", all.length, "first:", all[0].tokenSymbol)
// Chain alias: MYBASE:USDC_USD works from now on (aliases are case-insensitive)
exchange.IO("regChain", 8453, "mybase")
// Bind the name USDC to the first contract found; it takes precedence over OKX's list
exchange.IO("regToken", 8453, "USDC", rows[0].tokenContractAddress)
var q = exchange.IO("quote", "MYBASE:USDC_MYBASE:ETH", 10)
Log("ETH for 10 USDC:", q ? q.toAmount : GetLastError())
}
List the wallet's addresses on each chain, the chains each API supports and the balances on all chains
javascript
function main() {
Log("Ethereum:", exchange.IO("address"), "Solana:", exchange.IO("address", "SOL"))
var addrs = exchange.IO("addresses") // {chainIndex: address}
Log("Base:", addrs["8453"], "Tron:", addrs["195"])
var chains = exchange.IO("swapSupportedChains")
for (var i = 0; i < chains.length; i++) {
Log("swappable:", chains[i].chainIndex, chains[i].chainName)
}
Log("market API chains:", exchange.IO("marketSupportedChains").length,
"balance API:", exchange.IO("balanceSupportedChains").length,
"broadcast API:", exchange.IO("broadcastSupportedChains").length)
// GetAssets covers Ethereum only by default; switch to all chains (10+ s, do not poll)
exchange.IO("allChainBalance", true)
var assets = exchange.GetAssets()
for (var j = 0; assets && j < assets.length; j++) {
Log(assets[j].Currency, assets[j].Amount)
}
}
Get the transaction from the OKX swap API, sign it and broadcast it yourself
javascript
function main() {
var chain = "1"
var wallet = exchange.IO("address", chain)
// The transaction for swapping 1 USDC to ETH (amount in the smallest unit);
// spending an ERC-20 needs an approval first, see the example above
var r = exchange.IO("api", "GET", "/api/v6/dex/aggregator/swap", {
chainIndex: chain,
amount: "1000000",
fromTokenAddress: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
toTokenAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
slippagePercent: "0.5",
userWalletAddress: wallet
})
if (!r || r.code != "0") {
Log("Getting the transaction failed:", r ? r.msg : GetLastError())
return
}
// tx has to, data, value, gas, gasPrice etc.; signing looks up the nonce and
// multiplies the gas limit by gasMultiplier
var signed = exchange.IO("signTx", r.data[0].tx, chain)
if (!signed) {
Log("Signing failed:", GetLastError())
return
}
var res = exchange.IO("broadcast", signed, chain)
Log("tx hash:", res.txHash, "OKX order id:", res.orderId)
}
Function Support
Not supported (the call fails with an error and returns null): exchange.GetDepth, exchange.GetOrders, exchange.GetHistoryOrders, exchange.CancelOrder, exchange.ModifyOrder, exchange.CreateConditionOrder, exchange.ModifyConditionOrder, exchange.CancelConditionOrder, exchange.GetConditionOrder, exchange.GetConditionOrders, exchange.GetHistoryConditionOrders.
Served through a fallback:
exchange.GetRecords: Native periods are 1m, 3m, 5m, 15m, 30m, 1h, 2h, 4h, 6h, 12h, 1d, 3d, 1w, 1M, 3M; other periods are synthesized by the docker.
Notes
- Only market orders (
priceof -1) are supported; limit orders fail, and cross-chain swaps are not supported. For a sell,amountis the quantity of the symbol's first token; for a buy, it is the quantity of the second token (the amount spent). The order ID is<symbol>,<transaction hash>; query the swap result withexchange.GetOrder(). - Order extra parameters are passed as-is to the OKX DEX swap API (for example
slippagePercentoverrides the slippage for that order); swaps on Solana carry nogasLeveland setcomputeUnitPriceandcomputeUnitLimitautomatically instead, which can also be given in the extra parameters. - For a swap that spends an ERC-20 token (not the native coin) on an EVM chain, the allowance is checked before the order, and if it is insufficient an unlimited approval transaction is sent and confirmed first; checking the allowance needs an RPC for that chain, and the order fails if none is configured with
exchange.IO("rpc", chainIndex, url). exchange.GetOrder()queries OKX's swap record by transaction hash, with quantities measured in the first token (base token) of the symbol in the order ID, the same way for buys and sells: a swap that receives the base token is a buy and one that spends it is a sell (Type);Amountis the quantity of the token spent (for a buy, the quote token spent, as theamountof the order);DealAmountis the quantity of base token traded (bought for a buy, sold for a sell);AvgPriceis quote token ÷ base token.DealAmountandAvgPriceare given only once the swap succeeded and are 0 when it failed or is not finished; while the transaction is not yet indexed the order is reported as pending.- On Solana, OKX's swap record leaves the received token's amount empty;
exchange.GetOrder()then reads it from the transaction on chain (the wallet's balance before and after the swap, via the Solana node set withexchange.IO("rpc", "501", url)or the public mainnet node). Until the node has indexed the transaction the order is reported as pending, so poll again. - When OKX rate-limits a request (HTTP 429, error code 50011), the request waits 1, 2 and 4 seconds and is retried, at most 3 times, before the error is reported.
- There is no order book and no resting orders on-chain:
exchange.GetDepth(),exchange.GetOrders(),exchange.CancelOrder()and similar functions report an error and return null. exchange.GetTickers()returns the tokens of the 24h volume leaderboard on Ethereum (chain index 1), not all tokens;exchange.GetMarkets()lists the swappable tokens on Ethereum (tokens sharing a name on the same chain are left out).exchange.GetAssets()queries balances on Ethereum only by default, with asset names written aschain:token(an asset for which OKX gives no token name uses its contract address in place of the name); useexchange.IO("allChainBalance", true)for all chains.exchange.GetAccount()queries the chains of the two tokens of the current pair and takesStocks(left token) andBalance(right token; 0 when quoted inUSD) by chain index and contract address, whether the pair is written with chain indexes, chain names or contract addresses.- The wallet can only be derived from the mnemonic, always with the first account of each chain; choosing an account index or importing a private key is not supported. EVM chains (Ethereum, BSC, Base, Arbitrum and others share one address) use
m/44'/60'/0'/0/0, which is account 1 of the mnemonic in wallets such as MetaMask; accounts 2 and later cannot be used. Other chains: ETCm/44'/61'/0'/0/0; Tronm/44'/195'/0'/0/0; Bitcoinm/86'/0'/0'/0/0(Taproot addressbc1p…); Litecoinm/49'/2'/0'/0/0(P2SH-SegWit); Dogecoinm/44'/3'/0'/0/0, Dashm/44'/5'/0'/0/0, Bitcoin Cashm/44'/145'/0'/0/0; Osmosism/44'/118'/0'/0/0; Stacksm/44'/5757'/0'/0/0; Solanam/44'/501'/0'/0'; Aptosm/44'/637'/0'/0'/0'; SUIm/44'/784'/0'/0'/0'; TONm/44'/607'/0'(W5R1 wallet contract address); Starknet derivesm/44'/9004'/0'/0/0from the EVM private key as the seed. Check an address withexchange.IO("address", chain).