Skip to content

DEX Trading API (0x Swap)

Decentralized exchange trading via 0x protocol. Best-execution routing across 100+ DEXes with Permit2 and Gasless V2. FREE for all callers — you only pay on-chain gas fees.

Base URL

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

Pricing

All DEX endpoints are free. No JarvisClaw fees — only standard on-chain gas costs for submitted transactions. Gasless swaps eliminate even gas fees for supported tokens.

Supported Chains

ChainChain IDGasless Support
Ethereum1Yes
Base8453Yes
Polygon137Yes
Arbitrum42161Yes
Optimism10Yes

Endpoints

MethodEndpointDescriptionPrice
GET/priceIndicative swap price (no commitment)Free
GET/quoteFirm quote with calldata + Permit2 dataFree
POST/gasless/submitSubmit a signed gasless swapFree
GET/gasless/status/:tradeHashTrack gasless swap statusFree

Get Price

GET /v1/marketplace/dex/price

Get an indicative price for a token swap without committing. Use for UI display or pre-trade checks.

Parameters

ParameterTypeRequiredDescription
sellTokenstringYesToken contract address to sell
buyTokenstringYesToken contract address to buy
sellAmountstringYesAmount to sell in base units (e.g., 1000000 = 1 USDC)
chainIdintegerYesTarget chain ID
takerstringNoTaker wallet address (improves routing)

Response

json
{
  "chainId": 8453,
  "sellToken": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
  "buyToken": "0x4200000000000000000000000000000000000006",
  "sellAmount": "1000000000",
  "buyAmount": "385000000000000000",
  "price": "0.000385",
  "sources": [
    { "name": "Uniswap_V3", "proportion": "0.75" },
    { "name": "Aerodrome", "proportion": "0.25" }
  ],
  "estimatedGas": "145000",
  "gasPrice": "50000000"
}

Get Quote

GET /v1/marketplace/dex/quote

Get a firm quote with transaction calldata ready for signing. Includes EIP-712 typed data for Permit2 gasless swaps.

Parameters

ParameterTypeRequiredDescription
sellTokenstringYesToken contract address to sell
buyTokenstringYesToken contract address to buy
sellAmountstringYesAmount to sell in base units
chainIdintegerYesTarget chain ID
takerAddressstringYesTaker wallet address (required for quote)

Response

json
{
  "chainId": 8453,
  "sellToken": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
  "buyToken": "0x4200000000000000000000000000000000000006",
  "sellAmount": "1000000000",
  "buyAmount": "384500000000000000",
  "to": "0xDef1C0ded9bec7F1a1670819833240f027b25EfF",
  "data": "0x415565b0000000000000000000...",
  "value": "0",
  "gas": "185000",
  "gasPrice": "50000000",
  "permit2": {
    "type": "Permit2",
    "hash": "0x1234abcd...",
    "eip712": {
      "types": { "...": "..." },
      "domain": { "...": "..." },
      "message": { "...": "..." },
      "primaryType": "PermitWitnessTransferFrom"
    }
  },
  "validTo": 1717243800
}

Quote Expiry

Quotes are valid for 30 seconds. After expiry, you must request a new quote.


Submit Gasless Swap

POST /v1/marketplace/dex/gasless/submit

Submit a signed gasless swap. The relayer pays gas on your behalf — the taker pays nothing beyond the swap amount.

Request

json
{
  "trade": {
    "chainId": 8453,
    "sellToken": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    "buyToken": "0x4200000000000000000000000000000000000006",
    "sellAmount": "1000000000",
    "buyAmount": "384500000000000000",
    "to": "0xDef1C0ded9bec7F1a1670819833240f027b25EfF",
    "data": "0x415565b0...",
    "permit2": { "...": "..." }
  },
  "signature": "0xabcdef1234567890..."
}

Parameters

ParameterTypeRequiredDescription
tradeobjectYesFull quote object from /quote response
signaturestringYesEIP-712 signature from taker wallet

Response

json
{
  "tradeHash": "0x9f8e7d6c5b4a3210...",
  "status": "submitted",
  "createdAt": "2025-06-01T15:30:00Z"
}

Track Gasless Swap Status

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

Poll the status of a submitted gasless swap.

Path Parameters

ParameterTypeRequiredDescription
tradeHashstringYesTrade hash from submit response

Response

json
{
  "tradeHash": "0x9f8e7d6c5b4a3210...",
  "status": "confirmed",
  "txHash": "0xabc123def456...",
  "blockNumber": 18500000,
  "gasUsed": "142000"
}

Status values: submitted, pending, confirmed, failed


Examples

bash
# Get indicative price (1000 USDC -> WETH on Base)
curl "https://api.jarvisclaw.ai/v1/marketplace/dex/price?\
chainId=8453&\
sellToken=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913&\
buyToken=0x4200000000000000000000000000000000000006&\
sellAmount=1000000000" \
  -H "Authorization: Bearer sk-your-api-key"

# Get firm quote (requires takerAddress)
curl "https://api.jarvisclaw.ai/v1/marketplace/dex/quote?\
chainId=8453&\
sellToken=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913&\
buyToken=0x4200000000000000000000000000000000000006&\
sellAmount=1000000000&\
takerAddress=0xYourWalletAddress" \
  -H "Authorization: Bearer sk-your-api-key"

# Submit gasless swap
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": { "...quote object..." },
    "signature": "0xYourEIP712Signature..."
  }'

# Check gasless swap status
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"}

# Token addresses on Base
USDC_BASE = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
WETH_BASE = "0x4200000000000000000000000000000000000006"

# 1. Get indicative price for 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 decimals)
})
price = resp.json()
print(f"Buy amount: {price['buyAmount']} wei WETH")
print(f"Routed via: {[s['name'] for s in price['sources']]}")

# 2. Get firm quote
resp = requests.get(f"{BASE}/quote", headers=HEADERS, params={
    "chainId": 8453,
    "sellToken": USDC_BASE,
    "buyToken": WETH_BASE,
    "sellAmount": "1000000000",
    "takerAddress": "0xYourWalletAddress",
})
quote = resp.json()

# 3. Sign the EIP-712 permit2 data (requires eth_account)
# signature = sign_eip712(quote["permit2"]["eip712"], private_key)

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

# 5. Poll status
while True:
    resp = requests.get(f"{BASE}/gasless/status/{trade_hash}", headers=HEADERS)
    status = resp.json()
    if status["status"] == "confirmed":
        print(f"Swap confirmed! TX: {status['txHash']}")
        break
    elif status["status"] == "failed":
        print("Swap failed")
        break
    time.sleep(2)
python
from jarvisclaw import Client

# x402 agent — pays with USDC automatically (DEX endpoints are free anyway)
client = Client(private_key="0x<agent-wallet-private-key>")

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

# Get price (free — no payment triggered)
price = client.get("/v1/marketplace/dex/price", params={
    "chainId": 8453,
    "sellToken": USDC_BASE,
    "buyToken": WETH_BASE,
    "sellAmount": "1000000000",
})
print(f"Price: {price['buyAmount']} wei for 1000 USDC")

# Get firm quote
quote = client.get("/v1/marketplace/dex/quote", params={
    "chainId": 8453,
    "sellToken": USDC_BASE,
    "buyToken": WETH_BASE,
    "sellAmount": "1000000000",
    "takerAddress": "0xYourWalletAddress",
})

# Submit gasless (after signing permit2 externally)
result = client.post("/v1/marketplace/dex/gasless/submit", json={
    "trade": quote,
    "signature": "0x<signed-permit2>",
})
print(f"Trade hash: {result['tradeHash']}")

# Poll status
status = client.get(f"/v1/marketplace/dex/gasless/status/{result['tradeHash']}")
print(f"Status: {status['status']}")
go
package main

import (
    "fmt"
    "time"

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

func main() {
    client := jarvisclaw.NewClient(jarvisclaw.WithAPIKey("sk-your-api-key"))

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

    // 1. Get indicative price
    var price struct {
        BuyAmount    string `json:"buyAmount"`
        SellAmount   string `json:"sellAmount"`
        EstimatedGas string `json:"estimatedGas"`
    }
    err := client.GetJSON("/v1/marketplace/dex/price", map[string]string{
        "chainId":    "8453",
        "sellToken":  usdcBase,
        "buyToken":   wethBase,
        "sellAmount": "1000000000",
    }, &price)
    if err != nil {
        panic(err)
    }
    fmt.Printf("Buy amount: %s wei\n", price.BuyAmount)

    // 2. Get firm quote
    var quote map[string]interface{}
    err = client.GetJSON("/v1/marketplace/dex/quote", map[string]string{
        "chainId":      "8453",
        "sellToken":    usdcBase,
        "buyToken":     wethBase,
        "sellAmount":   "1000000000",
        "takerAddress": "0xYourWalletAddress",
    }, &quote)
    if err != nil {
        panic(err)
    }

    // 3. Sign permit2 EIP-712 data and submit gasless swap
    // signature := signEIP712(quote["permit2"], privateKey)

    var submit struct {
        TradeHash string `json:"tradeHash"`
        Status    string `json:"status"`
    }
    err = client.PostJSON("/v1/marketplace/dex/gasless/submit", map[string]interface{}{
        "trade":     quote,
        "signature": "0x<your-eip712-signature>",
    }, &submit)
    if err != nil {
        panic(err)
    }
    fmt.Printf("Trade hash: %s\n", submit.TradeHash)

    // 4. Poll status
    for {
        var status struct {
            Status string `json:"status"`
            TxHash string `json:"txHash"`
        }
        _ = client.GetJSON(
            fmt.Sprintf("/v1/marketplace/dex/gasless/status/%s", submit.TradeHash),
            nil, &status,
        )
        if status.Status == "confirmed" {
            fmt.Printf("Confirmed! TX: %s\n", status.TxHash)
            break
        }
        time.Sleep(2 * time.Second)
    }
}
go
package main

import (
    "fmt"

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

func main() {
    // x402 agent — DEX endpoints are free, but x402 auth still works
    client, err := jarvisclaw.NewClient(
        jarvisclaw.WithPrivateKey("0x<agent-wallet-private-key>"),
    )
    if err != nil {
        panic(err)
    }

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

    // Get price
    var price struct {
        BuyAmount string `json:"buyAmount"`
        Price     string `json:"price"`
    }
    _ = client.GetJSON("/v1/marketplace/dex/price", map[string]string{
        "chainId":    "8453",
        "sellToken":  usdcBase,
        "buyToken":   wethBase,
        "sellAmount": "1000000000",
    }, &price)
    fmt.Printf("1000 USDC -> %s wei WETH\n", price.BuyAmount)

    // Get quote
    var quote map[string]interface{}
    _ = client.GetJSON("/v1/marketplace/dex/quote", map[string]string{
        "chainId":      "8453",
        "sellToken":    usdcBase,
        "buyToken":     wethBase,
        "sellAmount":   "1000000000",
        "takerAddress": "0xYourWalletAddress",
    }, &quote)

    // Sign + submit gasless swap
    var result struct {
        TradeHash string `json:"tradeHash"`
    }
    _ = client.PostJSON("/v1/marketplace/dex/gasless/submit", map[string]interface{}{
        "trade":     quote,
        "signature": "0x<signed-permit2>",
    }, &result)
    fmt.Printf("Submitted: %s\n", result.TradeHash)
}

Errors

CodeErrorDescription
400insufficient_liquidityNot enough liquidity across available DEXes for this trade
400unsupported_chainChain ID not in supported list (1, 8453, 137, 42161, 10)
410price_expiredQuote expired (30s lifetime) — request a new one
400invalid_tokenToken address is not a valid contract on the specified chain
400invalid_amountSell amount is zero or exceeds token supply
400invalid_signatureEIP-712 signature verification failed
404trade_not_foundUnknown tradeHash in gasless status check

Limitations

  • 5 chains only — Ethereum (1), Base (8453), Polygon (137), Arbitrum (42161), Optimism (10)
  • Gasless requires Permit2 — Only tokens with Permit2 approval can use gasless swaps (most ERC-20s support this)
  • 30s quote expiry — Quotes are time-sensitive; sign and submit promptly
  • No limit orders — Only immediate market swaps; no conditional or scheduled orders
  • Price impact on large trades — Swaps over $100k may experience significant slippage due to DEX liquidity depth
  • Token addresses required — Use contract addresses, not symbols; verify addresses on the target chain
  • Base units only — All amounts are in the token's smallest denomination (6 decimals for USDC, 18 for ETH/WETH)
  • No partial fills — Entire trade executes or reverts; no partial execution

Pay per call. No subscription. No rate limits.