okx-dex-market-price
从 OKX DEX 市场价格 API (v6) 获取代币价格。当用户想要执行以下操作时,请使用此技能: 1. 获取支持的 EVM/Solana 链上一种或多种代币的最新价格 2.投资组合或UI批量查询代币价格(每次请求最多100个代币) 3. 构建需要实时DEX市场价格数据的应用 核心价值:使用 JSON 正文正确验证 POST 请求、HMAC-SHA256 签名 包括预哈希中的主体,以及批量请求/响应的正确处理。
安装 / 下载方式
TotalClaw CLI推荐
totalclaw install totalclaw:totalclaw~li-zoe-x-market-test-pricecURL直接下载,无需登录
curl -fsSL https://skills.taituai.com/api/skills/totalclaw%3Atotalclaw~li-zoe-x-market-test-price/file -o li-zoe-x-market-test-price.md## 概述(中文)
从 OKX DEX 市场价格 API (v6) 获取代币价格。当用户想要执行以下操作时,请使用此技能:
1. 获取支持的 EVM/Solana 链上一种或多种代币的最新价格
2.投资组合或UI批量查询代币价格(每次请求最多100个代币)
3. 构建需要实时DEX市场价格数据的应用
核心价值:使用 JSON 正文正确验证 POST 请求、HMAC-SHA256 签名
包括预哈希中的主体,以及批量请求/响应的正确处理。
## 原文
# OKX DEX Market Price API Skill
## Overview
This skill generates production-ready code for fetching **token prices** from the **OKX DEX Market Price API v6**. The API returns the latest price for one or more tokens on a given chain. It is a **batch endpoint**: you send a list of `(chainIndex, tokenContractAddress)` and receive a list of price results.
**Key capabilities:**
- Authenticated **POST** API requests with HMAC-SHA256 signing (prehash includes request body)
- **Batch support**: 1–100 tokens per request
- Multi-chain support (Ethereum, BSC, Polygon, Arbitrum, Base, Solana, etc.)
- Response includes `time` (price timestamp in ms) and `price` (string for precision)
## Prerequisites
### Required Credentials
- `OKX_ACCESS_KEY` — API key
- `OKX_SECRET_KEY` — Secret key for HMAC signing
- `OKX_PASSPHRASE` — Account passphrase
### Environment
- **Python**: `requests`, `hmac`, `hashlib`, `base64`, `datetime`, `json` (stdlib except `requests`)
- **Node.js**: `axios` or `node-fetch`, built-in `crypto`
- No blockchain dependencies (read-only HTTP API)
### API Endpoint
```
POST https://web3.okx.com/api/v6/dex/market/price
```
## Workflow
### Step 1: Validate User Input
1. **Request body** — Must be a **JSON array** of 1–100 objects. Each object:
- `chainIndex` (String, required): Supported chain ID, e.g. `"1"` = Ethereum, `"56"` = BSC.
- `tokenContractAddress` (String, required): Token contract address.
- **EVM**: 42-character hex, **all lowercase** (e.g. `0x382bb369d343125bfb2117af9c149795c6c65c50`).
- **Native token** (ETH, BNB, etc.): use `0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee`.
- Solana: base58 address.
2. **Batch size** — Between 1 and 100 (inclusive). Empty array or >100 items will result in API error.
### Step 2: Construct Authentication Headers (POST)
OKX API requires HMAC-SHA256 signed requests. For **POST**, the **body is part of the prehash**.
**Headers:**
```
Content-Type: application/json
OK-ACCESS-KEY: <api_key>
OK-ACCESS-SIGN: <hmac_signature>
OK-ACCESS-PASSPHRASE: <passphrase>
OK-ACCESS-TIMESTAMP: <iso8601_timestamp>
```
**Signing algorithm (POST):**
```
timestamp = ISO 8601 UTC (e.g. "2025-01-15T12:00:00.000Z")
request_path = "/api/v6/dex/market/price" // no query string for this endpoint
body = exact JSON string that will be sent (e.g. '[{"chainIndex":"1","tokenContractAddress":"0x..."}]'
prehash = timestamp + "POST" + request_path + body
signature = Base64(HMAC-SHA256(secret_key, prehash))
```
**CRITICAL for POST:**
- The **body** must be the **exact** JSON string (same as sent). No extra spaces; use canonical JSON (e.g. no extra whitespace).
- Method is uppercase `"POST"`.
- Request path is **without** query string (this endpoint has no query params).
### Step 3: Send Request and Parse Response
**Request body example:**
```json
[
{ "chainIndex": "1", "tokenContractAddress": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" },
{ "chainIndex": "56", "tokenContractAddress": "0x382bb369d343125bfb2117af9c149795c6c65c50" }
]
```
**Success response structure:**
```json
{
"code": "0",
"data": [
{
"chainIndex": "1",
"tokenContractAddress": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"time": "1716892020000",
"price": "1.00012345"
}
],
"msg": ""
}
```
**Fields:**
- `code`: `"0"` = success; non-zero = error (see `msg`).
- `data`: Array of price objects, one per requested token (order may match request).
- `chainIndex`, `tokenContractAddress`: Echo of request.
- `time`: Price timestamp in **Unix milliseconds** (string).
- `price`: Latest token price (string to preserve precision).
### Step 4: Format Output for User
- Convert `price` (string) to number only when needed for display/math to avoid precision loss.
- Use `time` for “price as of” display (e.g. convert ms to local time).
- If `code !== "0"`, surface `msg` and do not treat as success.
## Best Practices
### Security
- **Never hardcode** API credentials; use environment variables or secure config.
- **Never log** secret key or raw signature.
- Validate `tokenContractAddress` format (EVM hex length/case, Solana base58) before sending.
### POST body and signing
- Use **identical** JSON string for both signing and request body (no re-pretty-print between sign and send).
- In Python: `json.dumps(payload, separators=(',', ':'))` for deterministic output.
- In JavaScript: `JSON.stringify(payload)` — ensure no trailing spaces.
### Error handling
- Check `response["code"] == "0"` before using `data`.
- Empty or invalid `tokenParamList` (e.g. empty list or >100 items) returns param error.
- HTTP 401 = auth failure (check prehash: timestamp + "POST" + path + body).
- HTTP 429 = rate limit; implement backoff.
### Rate limits
- Respect OKX rate limits; cache prices when polling frequently.
## Examples
### Example 1: Python — Batch get token prices
```python
import os
import json
import hmac
import hashlib
import base64
import requests
from datetime import datetime, timezone
API_KEY = os.environ["OKX_ACCESS_KEY"]
SECRET_KEY = os.environ["OKX_SECRET_KEY"]
PASSPHRASE = os.environ["OKX_PASSPHRASE"]
BASE_URL = "https://web3.okx.com"
PRICE_PATH = "/api/v6/dex/market/price"
def get_prices(token_param_list):
# 1–100 items
if not token_param_list or len(token_param_list) > 100:
raise ValueError("token_param_list must have 1–100 items")
body = json.dumps(token_param_list, separators=(',', ':'))
timestamp = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z"
prehash = timestamp + "POST" + PRICE_PATH + body
signature = base64.b64encode(
hmac.new(SECRET_KEY.encode(), prehash.encode(), hashlib.sha256).digest()
).decode()
headers = {
"Content-Type": "application/json",
"OK-ACCESS-KEY": API_KEY,
"OK-ACCESS-SIGN": signature,
"OK-ACCESS-PASSPHRASE": PASSPHRASE,
"OK-ACCESS-TIMESTAMP": timestamp,
}
resp = requests.post(BASE_URL + PRICE_PATH, headers=headers, data=body, timeout=30)
resp.raise_for_status()
data = resp.json()
if data.get("code") != "0":
raise Exception(f"OKX API error: {data.get('msg', 'Unknown')}")
return data.get("data", [])
# One token on Ethereum (USDC)
payload = [{"chainIndex": "1", "tokenContractAddress": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"}]
prices = get_prices(payload)
for p in prices:
print(f"{p['tokenContractAddress']} @ {p['time']}: {p['price']}")
```
### Example 2: Node.js — POST with body in prehash
```javascript
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;
const BASE = "https://web3.okx.com";
const PATH = "/api/v6/dex/market/price";
function getPrices(tokenParamList) {
const body = JSON.stringify(tokenParamList);
const timestamp = new Date().toISOString();
const prehash = timestamp + "POST" + PATH + body;
const signature = crypto.createHmac("sha256", SECRET_KEY).update(prehash).digest("base64");
const options = {
method: "POST",
headers: {
"Content-Type": "application/json",
"OK-ACCESS-KEY": API_KEY,
"OK-ACCESS-SIGN": signature,
"OK-ACCESS-PASSPHRASE": PASSPHRASE,
"OK-ACCESS-TIMESTAMP": timestamp,
},
};
return new Promise((resolve, reject) => {
const req = https.request(BASE + PATH, options, (res) => {
let data = "";
res.on("data", (chunk) => (data += chunk));
res.on("end", () => {
const json = JSON.parse(data);
if (json.code !== "0") reject(new Error(json.msg || "API error"));
else resolve(json.data || []);
});
});
req.on("error", reject);