Skip to content

DEX 交易 API(0x Swap)

通过 0x 协议进行去中心化交易所交易。跨 100+ DEX 的最优执行路由,支持 Permit2 和 Gasless V2。需要认证(API Key 或 x402 支付)。按 $0.001/次 计费,执行交换另需链上 gas。

认证

两种方式均支持 — 所有请求通过 x402 链上结算:

方式Header描述
API KeyAuthorization: Bearer sk-...平台自动从你的 HD 钱包签名 x402
私钥(x402)通过 SDK 自动Agent 直接从自身钱包签名 x402

详见 Agent 支付(x402) 了解完整详情。

基础 URL

https://api.jarvisclaw.ai/v1/marketplace/dex

定价

认证(API Key 或 x402)是访问 DEX 端点的必要条件。

范围价格
所有 DEX 端点,任意方法$0.001/次

除按次费用外,提交交易还需支付标准链上 gas。Gasless 交换可以消除受支持代币的 gas 部分,但不免除 按次调用费。

这些端点并非免费

早前文档和部分价格列表称 DEX 交易免费,这是不准确的 —— 每次 DEX 调用都会计费。精确扣费金额 请读响应中的 price.amount

关于链

这里有两个容易混淆的概念:

支付 —— 你如何为这次调用付费Base(eip155:8453)和 Solana,均为 USDC
交换目标 —— 你传入的 chainId透传给上游 0x 路由

无论在哪条链上交换,付费都发生在 Base 或 Solana。网关不维护自己的交换目标链白名单 —— chainId 是直接透传的,哪些值可用由上游路由在调用时决定。8453(Base)已验证。 需要其他链请直接发送并检查响应,不要假定支持。

端点

方法端点描述价格
GET/price参考交换价格(无承诺)$0.001/次
GET/quote确认报价,含 calldata + Permit2 数据$0.001/次
POST/gasless/submit提交已签名的 gasless 交换$0.001/次
GET/gasless/status/:tradeHash跟踪 gasless 交换状态$0.001/次
POST/swap/permit2/quotePermit2 交换报价$0.001/次
POST/swap/permit2/execute执行 Permit2 交换$0.001/次

获取价格

GET /v1/marketplace/dex/price

获取代币交换的参考价格,无需承诺。用于 UI 显示或交易前检查。

参数

参数类型必填描述
sellTokenstring要卖出的代币合约地址
buyTokenstring要买入的代币合约地址
sellAmountstring以基本单位表示的卖出数量(例如 1000000 = 1 USDC)
chainIdinteger目标链 ID
takerstringTaker 钱包地址(用于更准确的报价)

响应

json
{
  "buyAmount": "415000000000000000",
  "sellAmount": "1000000000",
  "price": "0.000415",
  "sources": [
    {"name": "Uniswap_V3", "proportion": "0.8"},
    {"name": "SushiSwap", "proportion": "0.2"}
  ],
  "gas": "150000",
  "estimatedGas": "150000"
}

获取报价

GET /v1/marketplace/dex/quote

获取确认报价,含可执行的 calldata 和 Permit2 签名数据。

参数

参数类型必填描述
sellTokenstring要卖出的代币合约地址
buyTokenstring要买入的代币合约地址
sellAmountstring以基本单位表示的卖出数量
chainIdinteger目标链 ID
takerstringTaker 钱包地址

响应

json
{
  "buyAmount": "415000000000000000",
  "sellAmount": "1000000000",
  "to": "0x...",
  "data": "0x...",
  "value": "0",
  "gas": "200000",
  "permit2": {
    "eip712": { "...EIP-712 typed data..." }
  }
}

提交 Gasless 交换

POST /v1/marketplace/dex/gasless/submit

提交已签名的 gasless 交换。需要对报价的 Permit2 EIP-712 数据进行签名。

请求体

json
{
  "trade": { "...完整的报价对象..." },
  "signature": "0xYourEIP712Signature..."
}

响应

json
{
  "tradeHash": "0x9f8e7d6c5b4a3210...",
  "status": "submitted"
}

查询 Gasless 交换状态

GET /v1/marketplace/dex/gasless/status/:tradeHash

响应

json
{
  "tradeHash": "0x9f8e7d6c5b4a3210...",
  "status": "confirmed",
  "txHash": "0xabc123...",
  "blockNumber": 12345678
}

状态值: submittedpendingconfirmed | failed


代码示例

bash
# 获取参考价格
curl "https://api.jarvisclaw.ai/v1/marketplace/dex/price?\
chainId=8453&\
sellToken=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913&\
buyToken=0x4200000000000000000000000000000000000006&\
sellAmount=1000000000&\
taker=0xYourWalletAddress" \
  -H "Authorization: Bearer sk-your-api-key"

# 提交 gasless 交换
curl -X POST https://api.jarvisclaw.ai/v1/marketplace/dex/gasless/submit \
  -H "Authorization: Bearer sk-your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "trade": { "...报价对象..." },
    "signature": "0xYourEIP712Signature..."
  }'

# 检查 gasless 交换状态
curl "https://api.jarvisclaw.ai/v1/marketplace/dex/gasless/status/0x9f8e7d6c5b4a3210" \
  -H "Authorization: Bearer sk-your-api-key"
python
import requests
import time

BASE = "https://api.jarvisclaw.ai/v1/marketplace/dex"
HEADERS = {"Authorization": "Bearer sk-your-api-key"}

# Base 链上的代币地址
USDC_BASE = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
WETH_BASE = "0x4200000000000000000000000000000000000006"

# 1. 获取 1000 USDC -> WETH 的参考价格
resp = requests.get(f"{BASE}/price", headers=HEADERS, params={
    "chainId": 8453,
    "sellToken": USDC_BASE,
    "buyToken": WETH_BASE,
    "sellAmount": "1000000000",  # 1000 USDC (6 位小数)
})
price = resp.json()
print(f"买入数量: {price['buyAmount']} wei WETH")
print(f"路由经过: {[s['name'] for s in price['sources']]}")

# 2. 获取确认报价
resp = requests.get(f"{BASE}/quote", headers=HEADERS, params={
    "chainId": 8453,
    "sellToken": USDC_BASE,
    "buyToken": WETH_BASE,
    "sellAmount": "1000000000",
    "taker": "0xYourWalletAddress",
})
quote = resp.json()

# 3. 签名 EIP-712 permit2 数据(需要 eth_account)
# signature = sign_eip712(quote["permit2"]["eip712"], private_key)

# 4. 提交 gasless 交换
resp = requests.post(f"{BASE}/gasless/submit", headers=HEADERS, json={
    "trade": quote,
    "signature": "0x<your-eip712-signature>",
})
trade_hash = resp.json()["tradeHash"]

# 5. 轮询状态
while True:
    resp = requests.get(f"{BASE}/gasless/status/{trade_hash}", headers=HEADERS)
    status = resp.json()
    if status["status"] == "confirmed":
        print(f"交换已确认!TX: {status['txHash']}")
        break
    elif status["status"] == "failed":
        print("交换失败")
        break
    time.sleep(2)
python
from jarvisclaw import MarketplaceClient

# x402 Agent — 自动使用 USDC 支付 $0.001/次 的调用费
client = MarketplaceClient(private_key="0x<agent-wallet-private-key>")

USDC_BASE = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
WETH_BASE = "0x4200000000000000000000000000000000000006"

# 获取价格($0.001 — 通过 x402 结算)
price = client.call("dex", "/price", params={
    "chainId": 8453,
    "sellToken": USDC_BASE,
    "buyToken": WETH_BASE,
    "sellAmount": "1000000000",
})
print(f"价格: {price['buyAmount']} wei 对应 1000 USDC")

# 获取确认报价
quote = client.call("dex", "/quote", params={
    "chainId": 8453,
    "sellToken": USDC_BASE,
    "buyToken": WETH_BASE,
    "sellAmount": "1000000000",
    "taker": "0xYourWalletAddress",
})

# 提交 gasless 交换(外部签名 permit2 后)
result = client.call("dex", "/gasless/submit", method="POST", json={
    "trade": quote,
    "signature": "0x<signed-permit2>",
})
print(f"交易哈希: {result['tradeHash']}")

# 轮询状态
status = client.call("dex", f"/gasless/status/{result['tradeHash']}")
print(f"状态: {status['status']}")
go
package main

import (
    "context"
    "fmt"
    "time"

    jarvisclaw "github.com/api-jarvisclaw/go-sdk/v2"
)

func main() {
    mc, _ := jarvisclaw.NewMarketplaceClient(jarvisclaw.WithAPIKey("sk-your-api-key"))
    ctx := context.Background()

    usdcBase := "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
    wethBase := "0x4200000000000000000000000000000000000006"

    // 1. 获取参考价格
    price, err := mc.Call(ctx, "dex", "/price", jarvisclaw.WithParams(map[string]string{
        "chainId":    "8453",
        "sellToken":  usdcBase,
        "buyToken":   wethBase,
        "sellAmount": "1000000000",
    }))
    if err != nil {
        panic(err)
    }
    fmt.Printf("买入数量: %s wei\n", price["buyAmount"])

    // 2. 获取确认报价
    quote, err := mc.Call(ctx, "dex", "/quote", jarvisclaw.WithParams(map[string]string{
        "chainId":    "8453",
        "sellToken":  usdcBase,
        "buyToken":   wethBase,
        "sellAmount": "1000000000",
        "taker":      "0xYourWalletAddress",
    }))
    if err != nil {
        panic(err)
    }

    // 3. 签名 EIP-712 数据(外部处理)
    // signature := signEIP712(quote["permit2"], privateKey)

    // 4. 提交 gasless 交换
    result, _ := mc.Post(ctx, "dex", "/gasless/submit", map[string]interface{}{
        "trade":     quote,
        "signature": "0x<signed-permit2>",
    })
    fmt.Printf("交易哈希: %s\n", result["tradeHash"])

    // 5. 轮询状态
    for {
        status, _ := mc.Call(ctx, "dex", "/gasless/status/"+result["tradeHash"].(string), nil)
        if status["status"] == "confirmed" {
            fmt.Printf("已确认!TX: %s\n", status["txHash"])
            break
        }
        time.Sleep(2 * time.Second)
    }
}
go
package main

import (
    "context"
    "fmt"

    jarvisclaw "github.com/api-jarvisclaw/go-sdk/v2"
)

func main() {
    // x402 Agent 钱包 — 通过 Base 上的 USDC 按调用付费 (Chain ID 8453)
    mc, _ := jarvisclaw.NewMarketplaceClient(jarvisclaw.WithPrivateKey("0x<evm-private-key>"))
    ctx := context.Background()

    usdcBase := "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
    wethBase := "0x4200000000000000000000000000000000000006"

    // 获取参考价格
    price, _ := mc.Call(ctx, "dex", "/price", jarvisclaw.WithParams(map[string]string{
        "chainId":    "8453",
        "sellToken":  usdcBase,
        "buyToken":   wethBase,
        "sellAmount": "1000000000",
    }))
    fmt.Printf("1000 USDC -> %s wei WETH\n", price["buyAmount"])

    // 获取报价
    quote, _ := mc.Call(ctx, "dex", "/quote", jarvisclaw.WithParams(map[string]string{
        "chainId":    "8453",
        "sellToken":  usdcBase,
        "buyToken":   wethBase,
        "sellAmount": "1000000000",
        "taker":      "0xYourWalletAddress",
    }))

    // 签名 + 提交 gasless 交换
    result, _ := mc.Post(ctx, "dex", "/gasless/submit", map[string]interface{}{
        "trade":     quote,
        "signature": "0x<signed-permit2>",
    })
    fmt.Printf("已提交: %s\n", result["tradeHash"])
}

错误

网关层错误是扁平结构 —— 只有一个 error 字符串,没有嵌套 code:

json
{ "error": "service 'dex' is at capacity, please retry in a moment" }
HTTP含义处理
401缺少或无效的 API Key / x402 签名检查 Authorization,或让 SDK 重新签名
402结算失败 —— 无法支付本次调用充值后重试
403余额不足充值,或检查你的支出限额
404路径不存在对照上面的端点表核对
429并发请求过多退避后重试
502上游路由失败重试;持续失败说明上游宕机
503服务暂时不可用稍后重试

交换本身的失败 —— 流动性不足、报价过期、代币地址无效、签名验证失败、未知 tradeHash、 或 chainId 不受支持 —— 由上游 0x 路由抛出并原样透传,其结构和文案是上游的,不是我们的。


限制

  • 支付仅限 Base 或 Solana — 无论在哪条链上交换,调用费都以 Base 或 Solana 上的 USDC 支付
  • 交换目标链由上游路由决定chainId 透传给上游;8453 已验证,其他链取决于路由
  • Gasless 需要 Permit2 — 只有获得 Permit2 批准的代币才能使用 gasless 交换(大多数 ERC-20 代币支持)
  • 报价 30 秒过期 — 报价具有时效性;请及时签名并提交
  • 无限价订单 — 仅支持即时市价交换;不支持条件或定时订单
  • 大额交易的价格影响 — 超过 $100k 的交换可能因 DEX 流动性深度而产生显著滑点
  • 需要代币地址 — 使用合约地址而非符号;在目标链上验证地址
  • 仅基本单位 — 所有数量都使用代币的最小面额(USDC 为 6 位小数,ETH/WETH 为 18 位小数)
  • 无部分成交 — 整笔交易执行或回滚;不支持部分执行