Skills okx-dex-quote
git clone https://github.com/openclaw/skills
T=$(mktemp -d) && git clone --depth=1 https://github.com/openclaw/skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/aaronllee/dex-quote" ~/.claude/skills/clawdbot-skills-okx-dex-quote && rm -rf "$T"
skills/aaronllee/dex-quote/SKILL.mdOKX DEX Aggregator Quote Skill
Overview
This skill generates production-ready code for fetching optimal swap quotes from the OKX DEX Aggregator API v6. The API finds the best price across multiple DEX protocols (Uniswap, SushiSwap, Curve, etc.) and returns detailed routing information including price impact, gas estimates, and token safety flags.
Key capabilities:
- Authenticated API requests with HMAC-SHA256 signing
- Correct handling of token decimals and amount formatting
- Support for
(fixed input) andexactIn
(fixed output) swap modesexactOut - Multi-chain support (Ethereum, BSC, Arbitrum, Base, Solana, and 20+ chains)
- Price impact protection and honeypot detection
- Fee/commission splitting configuration
Prerequisites
Required Credentials
Users must have an OKX Web3 API key set. The skill needs three values:
— API keyOKX_ACCESS_KEY
— Secret key for HMAC signingOKX_SECRET_KEY
— Account passphraseOKX_PASSPHRASE
Environment
- Python:
,requests
,hmac
,hashlib
,base64
(all stdlib exceptdatetime
)requests - Node.js:
oraxios
, built-innode-fetchcrypto - No additional blockchain dependencies required (this is a read-only quote endpoint)
API Endpoint
GET https://web3.okx.com/api/v6/dex/aggregator/quote
Workflow
Step 1: Validate User Input
Before constructing the API call, validate:
-
Chain ID (
) — Must be a supported chain. Common values:chainIndex
= Ethereum1
= BSC56
= Polygon137
= Arbitrum42161
= Base8453
= Unichain130
= Solana501
-
Token addresses — Must be valid contract addresses or the native token placeholder:
- Native tokens (ETH, BNB, etc.):
0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee - Contract tokens: Full 42-character hex address (EVM) or base58 (Solana)
- Native tokens (ETH, BNB, etc.):
-
Amount — MUST include token decimals. This is the #1 source of errors:
- 1 ETH (18 decimals) →
"1000000000000000000" - 1 USDT (6 decimals) →
"1000000" - 1 WBTC (8 decimals) →
"100000000" - Formula:
amount_raw = human_amount * (10 ** token_decimals)
- 1 ETH (18 decimals) →
-
Swap mode —
(default) orexactInexactOut
only supported on: Ethereum, Base, BSC, ArbitrumexactOut
only works with Uniswap V2/V3 poolsexactOut
Step 2: Construct Authentication Headers
OKX API requires HMAC-SHA256 signed requests with 4 headers:
OK-ACCESS-KEY: <api_key> OK-ACCESS-SIGN: <hmac_signature> OK-ACCESS-PASSPHRASE: <passphrase> OK-ACCESS-TIMESTAMP: <iso8601_timestamp>
Signing algorithm:
timestamp = ISO 8601 UTC time (e.g., "2025-01-15T12:00:00.000Z") prehash = timestamp + "GET" + request_path_with_query signature = Base64(HMAC-SHA256(secret_key, prehash))
CRITICAL: The
request_path_with_query must include the full path starting from /api/... plus the query string. Example:
/api/v6/dex/aggregator/quote?chainIndex=1&amount=1000000000000000000&fromTokenAddress=0xeee...&toTokenAddress=0xa0b...
Step 3: Send Request and Parse Response
Success response structure:
{ "code": "0", "data": [{ "chainIndex": "1", "fromToken": { "tokenSymbol": "ETH", "decimal": "18", ... }, "toToken": { "tokenSymbol": "USDC", "decimal": "6", ... }, "fromTokenAmount": "1000000000000000000", "toTokenAmount": "3521432100", "dexRouterList": [...], "tradeFee": "2.45", "estimateGasFee": "150000", "priceImpactPercent": "-0.12" }], "msg": "" }
Key fields to extract:
— The amount you'll receive (in raw units with decimals)toTokenAmount
— Estimated network fee in USDtradeFee
— Negative = losing value; large negative = dangerpriceImpactPercent
— Routing path through various DEX protocolsdexRouterList
/fromToken.isHoneyPot
— Scam token flagtoToken.isHoneyPot
/fromToken.taxRate
— Token buy/sell taxtoToken.taxRate
Step 4: Format Output for User
Convert raw amounts back to human-readable:
human_amount = raw_amount / (10 ** decimal)
Always display:
- Exchange rate (e.g., "1 ETH = 3,521.43 USDC")
- Price impact percentage with warning if > 3%
- Estimated gas fee in USD
- Routing summary (which DEXes are used)
- Honeypot warnings if detected
- Token tax rates if > 0
Best Practices
Security
- NEVER hardcode API credentials in generated code. Always use environment variables or config files.
- NEVER log the secret key or signature in debug output.
- Validate all token addresses against expected format before sending.
- Check
flag on both tokens and warn the user prominently.isHoneyPot
Amount Handling
- Always use string type for amounts to avoid floating-point precision loss.
- Python: Use
for amount calculations, neverint()
.float() - JavaScript: Use
or string math for amounts > 2^53.BigInt - When user provides a human-readable amount like "1.5 ETH", convert:
.str(int(1.5 * 10**18))
Error Handling
- Check
before accessing data.response["code"] == "0" - Common error codes:
- Non-zero code with
= API error (e.g., insufficient liquidity, invalid params)msg - HTTP 401 = Authentication failure (check signature algorithm)
- HTTP 429 = Rate limited
- Non-zero code with
- If
ispriceImpactPercent
, warn that price impact couldn't be calculated.null
Rate Limits
- Respect OKX rate limits. For production use, implement exponential backoff.
- Cache quotes if polling repeatedly (quotes are valid for ~15-30 seconds).
Optional Parameters Usage
— Use when you want to restrict to specific DEXes (e.g., only Uniswap).dexIds
— Only for Solana; forces single-pool routing.directRoute=true
— Set to a sensible default likepriceImpactProtectionPercent
for safety. Set to10
to disable.100
— For integrators taking commission. Max 3% (EVM) or 10% (Solana). Up to 9 decimal places.feePercent
Examples
Example 1: Python — Get ETH to USDC Quote on Ethereum
import os, hmac, hashlib, base64, requests from datetime import datetime, timezone from urllib.parse import urlencode API_KEY = os.environ["OKX_ACCESS_KEY"] SECRET_KEY = os.environ["OKX_SECRET_KEY"] PASSPHRASE = os.environ["OKX_PASSPHRASE"] def get_okx_quote(chain_index, from_token, to_token, amount, swap_mode="exactIn"): base_url = "https://web3.okx.com" path = "/api/v6/dex/aggregator/quote" params = { "chainIndex": chain_index, "fromTokenAddress": from_token, "toTokenAddress": to_token, "amount": amount, "swapMode": swap_mode, } query_string = urlencode(params) request_path = f"{path}?{query_string}" # Generate timestamp and signature timestamp = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z" prehash = timestamp + "GET" + request_path signature = base64.b64encode( hmac.new(SECRET_KEY.encode(), prehash.encode(), hashlib.sha256).digest() ).decode() headers = { "OK-ACCESS-KEY": API_KEY, "OK-ACCESS-SIGN": signature, "OK-ACCESS-PASSPHRASE": PASSPHRASE, "OK-ACCESS-TIMESTAMP": timestamp, } resp = requests.get(base_url + request_path, headers=headers) resp.raise_for_status() data = resp.json() if data["code"] != "0": raise Exception(f"OKX API error: {data['msg']}") return data["data"][0] # Swap 1 ETH -> USDC on Ethereum ETH = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" USDC = "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" amount = str(1 * 10**18) # 1 ETH in wei quote = get_okx_quote("1", ETH, USDC, amount) to_decimals = int(quote["toToken"]["decimal"]) received = int(quote["toTokenAmount"]) / (10 ** to_decimals) print(f"You will receive: {received:,.2f} {quote['toToken']['tokenSymbol']}") print(f"Price impact: {quote['priceImpactPercent']}%") print(f"Gas fee (USD): ${quote['tradeFee']}") print(f"Honeypot check: {'WARNING' if quote['toToken']['isHoneyPot'] else 'Safe'}")
Example 2: Node.js — Get Quote with Commission Fee
const crypto = require("crypto"); const https = require("https"); const API_KEY = process.env.OKX_ACCESS_KEY; const SECRET_KEY = process.env.OKX_SECRET_KEY; const PASSPHRASE = process.env.OKX_PASSPHRASE; function getQuote(chainIndex, fromToken, toToken, amount, options = {}) { const params = new URLSearchParams({ chainIndex, fromTokenAddress: fromToken, toTokenAddress: toToken, amount, swapMode: options.swapMode || "exactIn", ...(options.feePercent && { feePercent: options.feePercent }), ...(options.priceImpactProtectionPercent && { priceImpactProtectionPercent: options.priceImpactProtectionPercent, }), }); const path = `/api/v6/dex/aggregator/quote?${params}`; const timestamp = new Date().toISOString(); const prehash = timestamp + "GET" + path; const signature = crypto .createHmac("sha256", SECRET_KEY) .update(prehash) .digest("base64"); return new Promise((resolve, reject) => { const req = https.get( `https://web3.okx.com${path}`, { headers: { "OK-ACCESS-KEY": API_KEY, "OK-ACCESS-SIGN": signature, "OK-ACCESS-PASSPHRASE": PASSPHRASE, "OK-ACCESS-TIMESTAMP": timestamp, }, }, (res) => { let body = ""; res.on("data", (chunk) => (body += chunk)); res.on("end", () => { const data = JSON.parse(body); if (data.code !== "0") reject(new Error(`OKX: ${data.msg}`)); else resolve(data.data[0]); }); } ); req.on("error", reject); }); }
Example 3: Understanding the Routing Path
Router: ETH -> WBTC -> USDC dexRouterList shows: - 55% ETH -> WBTC via Uniswap V4 - 30% ETH -> USDC via Uniswap V4 (direct) - WBTC -> USDC via Euler (73%) + Uniswap V4 (27%) This means the aggregator splits the trade across multiple paths to minimize price impact and maximize output.
Troubleshooting
| Problem | Cause | Solution |
|---|---|---|
| Signature mismatch | Verify prehash string is exactly . Check secret key encoding. |
| Amount too small | Missing decimal conversion | Multiply human amount by . 1 USDT = , not . |
| Invalid token address | Wrong chain/address combo | Verify the token exists on the specified chain. Use native token placeholder for ETH/BNB/etc. |
very negative (< -10%) | Low liquidity or large trade | Reduce trade size or split across multiple transactions. |
| Scam token detected | Do NOT proceed with the swap. Warn the user immediately. |
not working | Unsupported chain/protocol | Only works on Ethereum, Base, BSC, Arbitrum with Uniswap V2/V3. |
| Token has built-in tax | Factor tax into expected output. E.g., 5% tax means receiving 5% less. |
Empty | No liquidity path found | Try a different token pair, smaller amount, or different chain. |
is non-zero | General API error | Read field for details. Common: rate limit, maintenance, invalid params. |
Reference: Common Chain IDs
| Chain | chainIndex |
|---|---|
| Ethereum | 1 |
| BSC | 56 |
| Polygon | 137 |
| Arbitrum | 42161 |
| Optimism | 10 |
| Avalanche | 43114 |
| Base | 8453 |
| Solana | 501 |
| Unichain | 130 |
Reference: Common Token Addresses (Ethereum)
| Token | Address | Decimals |
|---|---|---|
| ETH (native) | | 18 |
| USDT | | 6 |
| USDC | | 6 |
| WETH | | 18 |
| WBTC | | 8 |
| DAI | | 18 |
Reference: Request Parameters Summary
| Parameter | Required | Description |
|---|---|---|
| Yes | Chain ID (e.g., for Ethereum) |
| Yes | Amount in raw units (with decimals) |
| Yes | or |
| Yes | Sell token contract address |
| Yes | Buy token contract address |
| No | Comma-separated DEX IDs to restrict routing |
| No | for single-pool only (Solana only) |
| No | Max allowed price impact 0-100 (default 90) |
| No | Commission fee percentage for integrators |