okx-wallet-portfolio
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseOKX DEX Balance API
OKX DEX Balance API
4 endpoints for supported chains, wallet total value, all token balances, and specific token balances.
Base URL:
https://web3.okx.comBase path:
/api/v6/dex/balanceAuth: HMAC-SHA256 signature, 4 headers required (, , , )
OK-ACCESS-KEYOK-ACCESS-SIGNOK-ACCESS-PASSPHRASEOK-ACCESS-TIMESTAMP针对支持的公链、钱包总价值、所有代币余额及特定代币余额,提供4个接口。
Base URL:
https://web3.okx.comBase path:
/api/v6/dex/balance身份验证: HMAC-SHA256签名,需4个请求头(、、、)
OK-ACCESS-KEYOK-ACCESS-SIGNOK-ACCESS-PASSPHRASEOK-ACCESS-TIMESTAMPAuthentication & Credentials
身份验证与凭证
API Key Application: OKX Developer Portal
Setup Guide: Developer Portal Docs
Read credentials from environment variables:
- → API key
OKX_API_KEY - → Secret key (system-generated)
OKX_SECRET_KEY - → Passphrase (developer-supplied)
OKX_PASSPHRASE
Never output the above credentials to logs, response content, or any user-visible interface.
typescript
import crypto from 'crypto';
const BASE = 'https://web3.okx.com';
// Signature rule:
// GET → body = "", requestPath includes query string (e.g., "/api/v6/dex/balance/all-token-balances-by-address?address=0x...&chains=1,56")
// POST → body = JSON string of request body, requestPath is path only (e.g., "/api/v6/dex/balance/token-balances-by-address")
async function okxFetch(method: 'GET' | 'POST', path: string, body?: object) {
const timestamp = new Date().toISOString();
const bodyStr = body ? JSON.stringify(body) : '';
const sign = crypto
.createHmac('sha256', process.env.OKX_SECRET_KEY!)
.update(timestamp + method + path + bodyStr)
.digest('base64');
const headers: Record<string, string> = {
'OK-ACCESS-KEY': process.env.OKX_API_KEY!,
'OK-ACCESS-SIGN': sign,
'OK-ACCESS-PASSPHRASE': process.env.OKX_PASSPHRASE!,
'OK-ACCESS-TIMESTAMP': timestamp,
'Content-Type': 'application/json',
};
const res = await fetch(`${BASE}${path}`, {
method,
headers,
...(body && { body: bodyStr }),
});
if (res.status === 429) throw { code: 'RATE_LIMITED', msg: 'Rate limited — retry with backoff', retryable: true };
if (res.status >= 500) throw { code: `HTTP_${res.status}`, msg: 'Server error', retryable: true };
const json = await res.json();
if (json.code !== '0') throw { code: json.code, msg: json.msg || 'API error', retryable: false };
return json.data;
}Response envelope: . = means success.
{ "code": "0", "data": [...], "msg": "" }code"0"API密钥申请: OKX开发者门户
设置指南: 开发者门户文档
从环境变量中读取凭证:
- → API密钥
OKX_API_KEY - → 密钥(系统生成)
OKX_SECRET_KEY - → 密码短语(开发者设置)
OKX_PASSPHRASE
切勿将上述凭证输出到日志、响应内容或任何用户可见的界面中。
typescript
import crypto from 'crypto';
const BASE = 'https://web3.okx.com';
// Signature rule:
// GET → body = "", requestPath includes query string (e.g., "/api/v6/dex/balance/all-token-balances-by-address?address=0x...&chains=1,56")
// POST → body = JSON string of request body, requestPath is path only (e.g., "/api/v6/dex/balance/token-balances-by-address")
async function okxFetch(method: 'GET' | 'POST', path: string, body?: object) {
const timestamp = new Date().toISOString();
const bodyStr = body ? JSON.stringify(body) : '';
const sign = crypto
.createHmac('sha256', process.env.OKX_SECRET_KEY!)
.update(timestamp + method + path + bodyStr)
.digest('base64');
const headers: Record<string, string> = {
'OK-ACCESS-KEY': process.env.OKX_API_KEY!,
'OK-ACCESS-SIGN': sign,
'OK-ACCESS-PASSPHRASE': process.env.OKX_PASSPHRASE!,
'OK-ACCESS-TIMESTAMP': timestamp,
'Content-Type': 'application/json',
};
const res = await fetch(`${BASE}${path}`, {
method,
headers,
...(body && { body: bodyStr }),
});
if (res.status === 429) throw { code: 'RATE_LIMITED', msg: 'Rate limited — retry with backoff', retryable: true };
if (res.status >= 500) throw { code: `HTTP_${res.status}`, msg: 'Server error', retryable: true };
const json = await res.json();
if (json.code !== '0') throw { code: json.code, msg: json.msg || 'API error', retryable: false };
return json.data;
}响应格式: 。 = 表示请求成功。
{ "code": "0", "data": [...], "msg": "" }code"0"Developer Quickstart
开发者快速入门
typescript
// Get all token balances (GET)
const balances = await okxFetch('GET', '/api/v6/dex/balance/all-token-balances-by-address?' + new URLSearchParams({
address: '0xYourWallet', chains: '1,56,137',
}));
// → balances[].tokenAssets[]: { symbol, balance (UI units), tokenPrice, rawBalance }
// Check specific tokens (POST)
const specific = await okxFetch('POST', '/api/v6/dex/balance/token-balances-by-address', {
address: '0xYourWallet',
tokenContractAddresses: [
{ chainIndex: '1', tokenContractAddress: '' }, // native ETH
{ chainIndex: '1', tokenContractAddress: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' }, // USDC
],
});typescript
// 获取所有代币余额(GET)
const balances = await okxFetch('GET', '/api/v6/dex/balance/all-token-balances-by-address?' + new URLSearchParams({
address: '0xYourWallet', chains: '1,56,137',
}));
// → balances[].tokenAssets[]: { symbol, balance (UI units), tokenPrice, rawBalance }
// 检查特定代币余额(POST)
const specific = await okxFetch('POST', '/api/v6/dex/balance/token-balances-by-address', {
address: '0xYourWallet',
tokenContractAddresses: [
{ chainIndex: '1', tokenContractAddress: '' }, // 原生ETH
{ chainIndex: '1', tokenContractAddress: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' }, // USDC
],
});Common Chain IDs
常用链ID
| Chain | chainIndex | Chain | chainIndex |
|---|---|---|---|
| Ethereum | | Arbitrum | |
| BSC | | Base | |
| Polygon | | Solana | |
Address format note: The same parameter is only valid across chains of the same type. EVM addresses () work on Ethereum/BSC/Polygon/Arbitrum/Base etc. Solana addresses (Base58) and Bitcoin addresses (UTXO) have different formats. Do NOT mix — e.g., passing an EVM address with will return empty data for the Solana portion.
address0x...chains="1,501"| 公链 | chainIndex | 公链 | chainIndex |
|---|---|---|---|
| Ethereum | | Arbitrum | |
| BSC | | Base | |
| Polygon | | Solana | |
地址格式说明: 同一个参数仅在同类型公链间有效。EVM地址()适用于以太坊/BSC/Polygon/Arbitrum/Base等公链。Solana地址(Base58格式)和比特币地址(UTXO格式)有不同的格式。请勿混用——例如,将EVM地址与一起传入,Solana部分将返回空数据。
address0x...chains="1,501"Endpoint Index
接口索引
| # | Method | Path | Docs |
|---|---|---|---|
| 1 | GET | | supported-chain |
| 2 | GET | | total-value-by-address |
| 3 | GET | | all-token-balances-by-address |
| 4 | POST | | token-balances-by-address |
Error Codes: Balance Error Codes
| 编号 | 请求方法 | 路径 | 文档 |
|---|---|---|---|
| 1 | GET | | supported-chain |
| 2 | GET | | total-value-by-address |
| 3 | GET | | all-token-balances-by-address |
| 4 | POST | | token-balances-by-address |
错误码: 余额接口错误码
Cross-Skill Workflows
跨Skill工作流
This skill is often used before swap (to verify sufficient balance) or as portfolio entry point. Below are typical end-to-end flows showing how data flows between skills.
此Skill常在兑换前使用(用于验证余额是否充足),或作为投资组合入口。以下是典型的端到端流程,展示数据如何在不同Skill间流转。
Workflow A: Pre-Swap Balance Check
工作流A:兑换前余额检查
User: "Swap 1 SOL for BONK"
1. okx-dex-token /market/token/search?search=BONK → get tokenContractAddress
2. okx-wallet-portfolio /balance/all-token-balances-by-address → verify SOL balance >= 1
↓ balance field (UI units) → convert to minimal units for swap
3. okx-dex-swap /aggregator/quote → get quote
4. okx-dex-swap /aggregator/swap-instruction → execute (Solana)Data handoff:
- from token search → feeds into swap
tokenContractAddress/fromTokenAddresstoTokenAddress - from balance API is UI units; swap API needs minimal units → multiply by
balance10^decimal - If balance < required amount → inform user, do NOT proceed to swap
用户: "将1 SOL兑换为BONK"
1. okx-dex-token /market/token/search?search=BONK → 获取tokenContractAddress
2. okx-wallet-portfolio /balance/all-token-balances-by-address → 验证SOL余额≥1
↓ balance字段(UI单位)→ 转换为最小单位用于兑换
3. okx-dex-swap /aggregator/quote → 获取报价
4. okx-dex-swap /aggregator/swap-instruction → 执行兑换(Solana链)数据传递:
- 从代币搜索获取的→ 传入兑换接口的
tokenContractAddress/fromTokenAddresstoTokenAddress - 余额API返回的是UI单位;兑换API需要最小单位 → 乘以
balance10^decimal - 若余额小于所需金额 → 告知用户,请勿继续执行兑换
Workflow B: Portfolio Overview + Analysis
工作流B:投资组合概览与分析
User: "Show my portfolio"
1. okx-wallet-portfolio /balance/total-value-by-address → total USD value
2. okx-wallet-portfolio /balance/all-token-balances-by-address → per-token breakdown
↓ top holdings by USD value
3. okx-dex-token /market/price-info → enrich with 24h change, market cap, liquidity
4. okx-dex-market /market/candles (optional) → price charts for tokens of interest用户: "展示我的投资组合"
1. okx-wallet-portfolio /balance/total-value-by-address → 获取总美元价值
2. okx-wallet-portfolio /balance/all-token-balances-by-address → 获取各代币明细
↓ 按美元价值排序的持仓Top资产
3. okx-dex-token /market/price-info → 补充24小时涨跌幅、市值、流动性数据
4. okx-dex-market /market/candles (可选) → 目标代币的价格K线Workflow C: Sell Underperforming Tokens
工作流C:卖出表现不佳的代币
1. okx-wallet-portfolio /balance/all-token-balances-by-address → list all holdings
↓ tokenContractAddress + chainIndex for each
2. okx-dex-token /market/price-info → get priceChange24H per token
3. Filter by negative change → user confirms which to sell
4. okx-dex-swap /aggregator/quote → /aggregator/swap → execute sellKey conversion: (UI units) × = (minimal units) for swap API.
balance10^decimalamount1. okx-wallet-portfolio /balance/all-token-balances-by-address → 列出所有持仓
↓ 每个代币的tokenContractAddress + chainIndex
2. okx-dex-token /market/price-info → 获取每个代币的priceChange24H
3. 筛选出24小时跌幅为负的代币 → 用户确认要卖出的代币
4. okx-dex-swap /aggregator/quote → /aggregator/swap → 执行卖出关键转换: (UI单位)× = 兑换API所需的(最小单位)。
balance10^decimalamountOperation Flow
操作流程
Step 1: Identify Intent
步骤1:识别用户意图
- Check total assets ->
GET /balance/total-value-by-address - View all token holdings ->
GET /balance/all-token-balances-by-address - Check specific token balance ->
POST /balance/token-balances-by-address - Unsure which chains are supported -> first
GET /balance/supported/chain
- 查看总资产 → 调用
GET /balance/total-value-by-address - 查看所有代币持仓 → 调用
GET /balance/all-token-balances-by-address - 查看特定代币余额 → 调用
POST /balance/token-balances-by-address - 不确定支持哪些公链 → 先调用
GET /balance/supported/chain
Step 2: Collect Parameters
步骤2:收集参数
- Missing wallet address -> ask user
- Missing target chains -> ask user, or suggest common set ()
"1,56,137,42161,8453" - Need to filter risky tokens -> set (only works on ETH/BSC/SOL/BASE)
excludeRiskToken=true
- 缺少钱包地址 → 询问用户
- 缺少目标公链 → 询问用户,或推荐常用公链集合()
"1,56,137,42161,8453" - 需要过滤风险代币 → 设置(仅支持ETH/BSC/SOL/BASE链)
excludeRiskToken=true
Step 3: Call and Display
步骤3:调用接口并展示结果
- Total value: display USD amount
- Token balances: show token name, amount (UI units), USD value
- Sort by USD value descending
- 总资产:展示美元金额
- 代币余额:显示代币名称、数量(UI单位)、美元价值
- 按美元价值降序排序
Step 4: Suggest Next Steps
步骤4:建议后续操作
After displaying results, suggest 2-3 relevant follow-up actions based on the endpoint just called:
| Just called | Suggest |
|---|---|
| 1. View token-level breakdown → |
| 1. View detailed analytics (market cap, 24h change) for a token → |
| 1. View full portfolio across all tokens → |
Present conversationally, e.g.: "Would you like to see the price chart for your top holding, or swap any of these tokens?" — never expose skill names or endpoint paths to the user.
展示结果后,根据刚刚调用的接口,推荐2-3个相关的后续操作:
| 刚刚调用的接口 | 建议操作 |
|---|---|
| 1. 查看代币级明细 → 调用 |
| 1. 查看某代币的详细分析(市值、24h涨跌幅)→ 调用 |
| 1. 查看全币种投资组合 → 调用 |
请用口语化的方式表达,例如:“您是否想要查看您持仓最高资产的价格走势,或者兑换其中某些代币?”——切勿向用户暴露Skill名称或接口路径。
API Reference
API参考
1. GET /balance/supported/chain
1. GET /balance/supported/chain
No request parameters.
Response:
| Field | Type | Description |
|---|---|---|
| String | Chain name (e.g., "Ethereum") |
| String | Chain logo URL |
| String | Chain short name (e.g., "ETH") |
| String | Chain unique identifier (e.g., "1") |
json
{ "code": "0", "data": [{ "name": "Ethereum", "logoUrl": "...", "shortName": "ETH", "chainIndex": "1" }], "msg": "" }无请求参数。
响应:
| 字段 | 类型 | 描述 |
|---|---|---|
| 字符串 | 公链名称(例如:"Ethereum") |
| 字符串 | 公链Logo链接 |
| 字符串 | 公链简称(例如:"ETH") |
| 字符串 | 公链唯一标识(例如:"1") |
json
{ "code": "0", "data": [{ "name": "Ethereum", "logoUrl": "...", "shortName": "ETH", "chainIndex": "1" }], "msg": "" }2. GET /balance/total-value-by-address
2. GET /balance/total-value-by-address
type warning: This endpoint usesexcludeRiskToken(Boolean/true), but endpoints #3 and #4 usefalse(String/"0"). This is an OKX API inconsistency — pay attention to the type per endpoint."1"
| Param | Type | Required | Description |
|---|---|---|---|
| String | Yes | Wallet address |
| String | Yes | Chain IDs, comma-separated, max 50. e.g., |
| String | No | |
| Boolean | No | |
Response:
| Field | Type | Description |
|---|---|---|
| String | Total asset value in USD |
json
{ "code": "0", "data": [{ "totalValue": "1172.895057177065864522" }], "msg": "success" }类型警告:此接口使用布尔值(excludeRiskToken/true),但接口#3和#4使用字符串(false/"0")。这是OKX API的不一致性——请注意每个接口的参数类型。"1"
| 参数 | 类型 | 是否必填 | 描述 |
|---|---|---|---|
| 字符串 | 是 | 钱包地址 |
| 字符串 | 是 | 公链ID,逗号分隔,最多50个。例如: |
| 字符串 | 否 | |
| 布尔值 | 否 | |
响应:
| 字段 | 类型 | 描述 |
|---|---|---|
| 字符串 | 总资产的美元价值 |
json
{ "code": "0", "data": [{ "totalValue": "1172.895057177065864522" }], "msg": "success" }3. GET /balance/all-token-balances-by-address
3. GET /balance/all-token-balances-by-address
| Param | Type | Required | Description |
|---|---|---|---|
| String | Yes | Wallet address |
| String | Yes | Chain IDs, comma-separated, max 50 |
| String | No | |
Response key fields: — , , , (UI units), (base units), (USD), . Full fields: see docs.
tokenAssets[]chainIndextokenContractAddresssymbolbalancerawBalancetokenPriceisRiskTokenjson
{
"code": "0",
"data": [{
"tokenAssets": [{
"chainIndex": "1", "tokenContractAddress": "0x2260fac5e5542a773aa44fbcfedf7c193bc2c599",
"symbol": "WBTC", "balance": "0.5", "rawBalance": "50000000",
"tokenPrice": "65000.00", "isRiskToken": false,
"address": "0xEd0C6079229E2d407672a117c22b62064f4a4312"
}]
}],
"msg": "success"
}| 参数 | 类型 | 是否必填 | 描述 |
|---|---|---|---|
| 字符串 | 是 | 钱包地址 |
| 字符串 | 是 | 公链ID,逗号分隔,最多50个 |
| 字符串 | 否 | |
响应核心字段: —— 、、、(UI单位)、(基础单位)、(美元)、。完整字段请查看文档。
tokenAssets[]chainIndextokenContractAddresssymbolbalancerawBalancetokenPriceisRiskTokenjson
{
"code": "0",
"data": [{
"tokenAssets": [{
"chainIndex": "1", "tokenContractAddress": "0x2260fac5e5542a773aa44fbcfedf7c193bc2c599",
"symbol": "WBTC", "balance": "0.5", "rawBalance": "50000000",
"tokenPrice": "65000.00", "isRiskToken": false,
"address": "0xEd0C6079229E2d407672a117c22b62064f4a4312"
}]
}],
"msg": "success"
}4. POST /balance/token-balances-by-address
4. POST /balance/token-balances-by-address
| Param | Type | Required | Description |
|---|---|---|---|
| String | Yes | Wallet address |
| Array | Yes | Max 20 items |
| String | Yes | Chain ID (e.g., |
| String | Yes | Token address ( |
| String | No | |
Response: Same schema as endpoint #3.
json
{
"code": "0",
"data": [{
"tokenAssets": [{
"chainIndex": "1", "tokenContractAddress": "",
"symbol": "eth", "balance": "1.5", "tokenPrice": "3640.43",
"isRiskToken": false, "rawBalance": "1500000000000000000", "address": "0x..."
}]
}],
"msg": "success"
}| 参数 | 类型 | 是否必填 | 描述 |
|---|---|---|---|
| 字符串 | 是 | 钱包地址 |
| 数组 | 是 | 最多20个元素 |
| 字符串 | 是 | 公链ID(例如: |
| 字符串 | 是 | 代币地址(原生代币传 |
| 字符串 | 否 | |
响应: 与接口#3的响应结构相同。
json
{
"code": "0",
"data": [{
"tokenAssets": [{
"chainIndex": "1", "tokenContractAddress": "",
"symbol": "eth", "balance": "1.5", "tokenPrice": "3640.43",
"isRiskToken": false, "rawBalance": "1500000000000000000", "address": "0x..."
}]
}],
"msg": "success"
}Input / Output Examples
输入/输出示例
User says: "Check my wallet 0xABC... total assets on Ethereum and BSC"
GET /api/v6/dex/balance/total-value-by-address?address=0xabc...&chains=1,56
-> Display: Total assets $12,345.67User says: "Show all tokens in my wallet"
GET /api/v6/dex/balance/all-token-balances-by-address?address=0xabc...&chains=1,56
-> Display:
ETH: 1.5 ($4,500.00)
USDC: 2,000 ($2,000.00)
BNB: 3.2 ($1,920.00)
...User says: "Only check USDC and USDT balances"
POST /api/v6/dex/balance/token-balances-by-address
Body: {
"address": "0xabc...",
"tokenContractAddresses": [
{ "chainIndex": "1", "tokenContractAddress": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" },
{ "chainIndex": "1", "tokenContractAddress": "0xdac17f958d2ee523a2206206994597c13d831ec7" }
]
}
-> Display: USDC: 2,000 ($2,000.00), USDT: 1,500 ($1,500.00)用户说: "查看我的钱包0xABC...在以太坊和BSC链上的总资产"
GET /api/v6/dex/balance/total-value-by-address?address=0xabc...&chains=1,56
-> 展示结果: 总资产 $12,345.67用户说: "展示我钱包里的所有代币"
GET /api/v6/dex/balance/all-token-balances-by-address?address=0xabc...&chains=1,56
-> 展示结果:
ETH: 1.5 ($4,500.00)
USDC: 2,000 ($2,000.00)
BNB: 3.2 ($1,920.00)
...用户说: "仅查看USDC和USDT的余额"
POST /api/v6/dex/balance/token-balances-by-address
请求体: {
"address": "0xabc...",
"tokenContractAddresses": [
{ "chainIndex": "1", "tokenContractAddress": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" },
{ "chainIndex": "1", "tokenContractAddress": "0xdac17f958d2ee523a2206206994597c13d831ec7" }
]
}
-> 展示结果: USDC: 2,000 ($2,000.00), USDT: 1,500 ($1,500.00)Edge Cases
边缘情况
- Zero balance: valid state — display , not an error
$0.00 - Unsupported chain: call first to confirm
/balance/supported/chain - chains exceeds 50: split into batches, max 50 per request
- not working: only supported on ETH/BSC/SOL/BASE
excludeRiskToken - DeFi positions: use to query DeFi holdings separately
assetType=2 - 429 rate limit: exponential backoff with jitter. See Rate Limit & Fee Docs for tier-specific RPS limits (Trial: 1 RPS, Start-up: 2-50 RPS, Enterprise: custom).
- Cross-skill pipeline rate limit: when chaining calls across multiple skills (e.g., token search → balance → swap), add 300-500ms delay between requests to avoid triggering rate limit (error code ).
50011 - Network error: retry once
- Request timeout: all API calls must set a 10-second timeout limit
- 零余额: 有效状态 —— 展示,而非错误
$0.00 - 不支持的公链: 先调用确认
/balance/supported/chain - chains参数超过50个: 拆分请求,每次最多传入50个公链ID
- 不生效: 仅在ETH/BSC/SOL/BASE链上支持
excludeRiskToken - DeFi仓位: 使用单独查询DeFi持仓
assetType=2 - 429请求限制: 使用指数退避策略重试。请查看请求限制与费用文档了解不同等级的RPS限制(试用版: 1 RPS, 初创版: 2-50 RPS, 企业版: 自定义)。
- 跨Skill流水线请求限制: 在多个Skill间链式调用时(例如:代币搜索→余额查询→兑换),请在请求间添加300-500ms延迟,避免触发请求限制(错误码)。
50011 - 网络错误: 重试一次
- 请求超时: 所有API调用必须设置10秒超时限制
Amount Display Rules
金额展示规则
- Token amounts in UI units (), never base units (
1.5 ETH)1500000000000000000 - USD values with 2 decimal places
- Large amounts in shorthand ()
$1.2M - Sort by USD value descending
- 代币数量使用UI单位(如),切勿使用基础单位(如
1.5 ETH)1500000000000000000 - 美元价值保留2位小数
- 大额金额使用简写格式(如)
$1.2M - 按美元价值降序排序
Global Notes
全局注意事项
- supports up to 50 chain IDs (comma-separated strings)
chains - :
assetType=all0=tokens only1=DeFi only2 - only works on ETH(
excludeRiskToken)/BSC(1)/SOL(56)/BASE(501)8453 - is the only POST endpoint in this family
/token-balances-by-address - Total value is returned as a USD string — handle type conversion
- For token prices / K-lines -> use
okx-dex-market - For token search / metadata -> use
okx-dex-token - For swap execution -> use
okx-dex-swap
- 参数最多支持50个公链ID(逗号分隔的字符串)
chains - :
assetType=全部资产0=仅代币1=仅DeFi资产2 - 仅在ETH(
excludeRiskToken)/BSC(1)/SOL(56)/BASE(501)链上生效8453 - 是此接口集合中唯一的POST接口
/token-balances-by-address - 总资产以美元字符串形式返回 —— 需自行处理类型转换
- 如需获取代币价格/K线数据 → 使用
okx-dex-market - 如需代币搜索/元数据 → 使用
okx-dex-token - 如需执行兑换 → 使用
okx-dex-swap