> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cdp.coinbase.com/llms.txt
> Use this file to discover all available pages before exploring further.

# GMGN Plugin

> Token swap quotes and on-chain market intelligence for Base via GMGN API. Requires shell to generate auth parameters; returns unsigned calldata for send_calls execution.

# GMGN Plugin

> \[!IMPORTANT]
> Complete the Wallet MCP onboarding flow defined in `SKILL.md` before calling any GMGN endpoint. The user's wallet address — passed as `from_address` in every quote call — is fetched lazily when needed.

## Overview

GMGN is a trading platform providing token swap routing and on-chain market intelligence for Base mainnet. This plugin calls the GMGN HTTP API via `web_request` to obtain full unsigned transaction calldata from the quote endpoint, then submits it through `send_calls` — no server-side key binding or additional MCP server required.

**Shell requirement:** Every request requires a Unix timestamp (±5 s accuracy) and a fresh UUID v4 as auth parameters. These must be generated via shell commands (`date +%s` and `uuidgen`) to guarantee correctness. This plugin only runs on CLI harnesses (Claude Code, Codex) where shell access is available.

Three capabilities are exposed:

* **Swap quotes** — returns complete unsigned calldata (`data.tx.to/value/data`) and ERC-20 approval transactions (`data.tx.approve_txs`) ready for `send_calls`
* **Gas prices** — current low/average/high fee tiers for Base
* **Trending tokens** — top tokens ranked by swap activity, volume, and holder count

**Chain:** Base mainnet (chainId `8453`)

***

## Auth

All requests require the `X-APIKEY` header and two query parameters generated via shell:

| Parameter | Description | Shell command |
| - | - | - |
| `timestamp` | Current Unix timestamp in seconds (valid window ±5 s) | `date +%s` |
| `client_id` | Fresh UUID v4 per request (replay protection, 7 s window) | `uuidgen \| tr '[:upper:]' '[:lower:]'` |

Generate before every request:

```bash theme={null}
TS=$(date +%s)
CID=$(uuidgen | tr '[:upper:]' '[:lower:]')
```

A public API key is available for all read-only operations:

```
X-APIKEY: gmgn_basesolbscethmonadtron
```

***

## Surface Routing

| Capability | Tool | Notes |
| - | - | - |
| Generate auth params | shell (`bash`) | `date +%s` for timestamp; `uuidgen` for client\_id — required before every request |
| Swap quote | `web_request` | `GET /v1/trade/quote` — returns unsigned calldata |
| Gas price | `web_request` | `GET /v1/trade/gas_price` |
| Trending tokens | `web_request` | `GET /v1/market/rank` |
| Execute swap | `send_calls` | Uses calldata from quote response — no signing required |

All HTTP calls go to `openapi.gmgn.ai` (in the `allowlist`). Shell is required for auth parameter generation.

***

## Endpoints

Base URL: `https://openapi.gmgn.ai`

### 1. `GET /v1/trade/quote` — Swap Quote + Calldata

Returns the full unsigned transaction ready for `send_calls`. This is the primary endpoint for executing swaps.

Query parameters:

| Parameter | Required | Description |
| - | - | - |
| `chain` | Yes | `base` |
| `from_address` | Yes | User's wallet address |
| `input_token` | Yes | Input token contract address (`0x000...000` for native ETH) |
| `output_token` | Yes | Output token contract address |
| `input_amount` | Yes | Input amount in base units (USDC: × 1e6, ETH: × 1e18) |
| `slippage` | Yes | Integer 0–100 (e.g., `5` = 5%). See [Risks & Warnings](#risks--warnings). |
| `timestamp` | Yes | Auth: Unix seconds |
| `client_id` | Yes | Auth: fresh UUID v4 |

Example request (swap 0.00001 ETH → token):

```
GET https://openapi.gmgn.ai/v1/trade/quote?chain=base&from_address=0xc76d...&input_token=0x0000000000000000000000000000000000000000&output_token=0xc2c1e0b7c401e6217193732272444d928646eba3&input_amount=10000000000000&slippage=5&timestamp=<ts>&client_id=<uuid>
X-APIKEY: gmgn_basesolbscethmonadtron
```

**Response `data` fields:**

Top-level summary fields:

| Field | Description |
| - | - |
| `input_token` | Input token contract address |
| `output_token` | Output token contract address |
| `input_amount` | Input amount (base units) |
| `output_amount` | Expected output amount (base units) |
| `min_output_amount` | Minimum output after slippage (base units) |
| `slippage` | Slippage percentage |
| `tx` | Full unsigned transaction object (see below) |

`data.tx` fields (the full unsigned transaction for `send_calls`):

| Field | Description |
| - | - |
| `tx.to` | Router contract address — use as `to` in `send_calls` |
| `tx.value` | Native ETH to send in wei (string) — use as `value` in `send_calls` |
| `tx.data` | Encoded calldata — use as `data` in `send_calls` |
| `tx.approve_txs` | Approval transactions to send before the swap (empty for native ETH input) |
| `tx.amount_in` | Input amount (base units) |
| `tx.amount_out` | Expected output amount (base units) |
| `tx.amount_min_out` | Minimum output after slippage (base units) |
| `tx.amount_in_usd` | Input value in USD |
| `tx.amount_out_usd` | Expected output value in USD |
| `tx.amount_in_decimals` | Input token decimals |
| `tx.amount_out_decimals` | Output token decimals |
| `tx.gas_limit` | Estimated gas limit (string) |
| `tx.deadline` | Transaction deadline (Unix timestamp) |
| `tx.chain_id` | Chain ID (`8453` for Base) |

Example response:

```json theme={null}
{
  "code": 0,
  "data": {
    "input_token": "0x0000000000000000000000000000000000000000",
    "output_token": "0xc2c1e0b7c401e6217193732272444d928646eba3",
    "input_amount": "10000000000000",
    "output_amount": "18500572860253689774247",
    "min_output_amount": "17575544217241005285535",
    "slippage": 5,
    "tx": {
      "chain_id": 8453,
      "to": "0xd8Ba9D1a99Fc21f0ECA24e9b85737c28A194a4E2",
      "from_address": "0xc76d1aabf25142f15010e992cb07bb81a8b5ae63",
      "slippage": 5,
      "value": "10000000000000",
      "amount_in": "10000000000000",
      "amount_out": "18500572860253689774247",
      "amount_min_out": "17575544217241005285535",
      "input_token_address": "0x0000000000000000000000000000000000000000",
      "output_token_address": "0xc2c1e0b7c401e6217193732272444d928646eba3",
      "token_in_usd_price": "1671.39",
      "token_out_usd_price": "0.00000088214833000000",
      "amount_in_usd": "0.0167139",
      "amount_out_usd": "0.01632024945271611581069006805751",
      "amount_in_decimals": 18,
      "amount_out_decimals": 18,
      "gas_limit": "922086",
      "data": "0xeffbec13...",
      "approve_txs": [],
      "deadline": 1781266225
    }
  }
}
```

Convert to human-readable: `data.tx.amount_out / 10^data.tx.amount_out_decimals`, `data.tx.amount_min_out / 10^data.tx.amount_out_decimals`.

***

### 2. `GET /v1/trade/gas_price` — Gas Price

Returns current recommended gas price tiers for Base.

Query parameters:

| Parameter | Required | Description |
| - | - | - |
| `chain` | Yes | `base` |
| `timestamp` | Yes | Auth: Unix seconds |
| `client_id` | Yes | Auth: fresh UUID v4 |

Key response fields under `data`:

| Field | Description |
| - | - |
| `low` / `average` / `high` | Gas price tiers in wei |
| `low_estimate_time` / `average_estimate_time` / `high_estimate_time` | Estimated confirmation time (seconds) |
| `suggest_base_fee` | Suggested EIP-1559 base fee (wei) |
| `average_prio_fee` | Average priority fee (wei) |
| `native_token_usd_price` | ETH price in USD |

***

### 3. `GET /v1/market/rank` — Trending Tokens

Returns top trending tokens on Base ranked by swap activity.

Query parameters:

| Parameter | Required | Default | Description |
| - | - | - | - |
| `chain` | Yes | — | `base` |
| `interval` | No | `1h` | Time window: `1m` / `5m` / `1h` / `6h` / `24h` |
| `limit` | No | `10` | Number of results (1–100) |
| `order_by` | No | `default` | Sort field: `default` / `swaps` / `volume` / `marketcap` / `holder_count` / `change1h` |
| `direction` | No | `desc` | `asc` / `desc` |
| `filters` | No | `not_honeypot,verified,renounced` | Safety filters (repeatable): `not_honeypot`, `verified`, `renounced`, `has_social`, `not_wash_trading` |
| `timestamp` | Yes | — | Auth: Unix seconds |
| `client_id` | Yes | — | Auth: fresh UUID v4 |

Response: `data.rank` array with token address, symbol, price (USD), market cap, 1h/24h price change, swap count, volume, holder count, and liquidity.

***

## Orchestration

### Swap Flow: "Swap 0.00001 ETH for Token X on Base"

```text theme={null}
1. get_wallets -> user address (from_address)

2. shell: TS=$(date +%s) && CID=$(uuidgen | tr '[:upper:]' '[:lower:]')

3. web_request GET /v1/trade/quote
     ?chain=base
     &from_address=<address>
     &input_token=0x0000000000000000000000000000000000000000   (native ETH)
     &output_token=<token_address>
     &input_amount=<amount_in_wei>
     &slippage=5
     &timestamp=$TS&client_id=$CID
   Headers: X-APIKEY: gmgn_basesolbscethmonadtron

4. Present quote to user:
     Input:           data.tx.amount_in / 10^data.tx.amount_in_decimals  (+ data.tx.amount_in_usd)
     Expected output: data.tx.amount_out / 10^data.tx.amount_out_decimals (+ data.tx.amount_out_usd)
     Minimum output:  data.tx.amount_min_out / 10^data.tx.amount_out_decimals
     Check slippage against Risks & Warnings before proceeding.

5. Confirm with user before submitting.

6. See Submission section to build and send the calls.
```

### Market Discovery Flow: "What Tokens Are Trending on Base?"

```text theme={null}
1. shell: TS=$(date +%s) && CID=$(uuidgen | tr '[:upper:]' '[:lower:]')
2. web_request GET /v1/market/rank?chain=base&interval=1h&limit=10&order_by=volume&timestamp=$TS&client_id=$CID
   Headers: X-APIKEY: gmgn_basesolbscethmonadtron
3. Present the top tokens: name, symbol, price, 1h change, volume, holder count
4. Optionally follow up with GET /v1/trade/quote for any token the user wants to buy
```

***

## Submission

Build the `send_calls` payload from the quote response:

```javascript theme={null}
approvalCalls = data.tx.approve_txs.map((t) => ({
  to: t.to,
  value: t.value ?? "0x0",
  data: t.data,
}));
swapCall = { to: data.tx.to, value: data.tx.value, data: data.tx.data };
calls = [...approvalCalls, swapCall];
```

If `data.tx.approve_txs` is empty (native ETH input), omit the approval call and send only the swap call.

```json theme={null}
{
  "chain": "base",
  "calls": [
    { "to": "<approve_tx.to>", "value": "0x0", "data": "<approve_tx.data>" },
    {
      "to": "<data.tx.to>",
      "value": "<data.tx.value>",
      "data": "<data.tx.data>"
    }
  ]
}
```

Call `send_calls("base", calls)`, then `get_request_status` only after the user acts on the approval link.

***

## Example Prompts

**Swap 0.00001 ETH for a token on Base**

1. `get_wallets` → address.
2. `web_request GET /v1/trade/quote` with `input_token=0x000...000` (native ETH), `input_amount=10000000000000`, target token as `output_token`, `slippage=5`.
3. Display expected and minimum output, USD values.
4. Build approval + swap calls from `data.tx.approve_txs` and `data.tx.to/value/data`.
5. `send_calls("base", [...approvalCalls, swapCall])`.

**Swap 100 USDC for ETH on Base**

1. `get_wallets` → address.
2. `web_request GET /v1/trade/quote` with `input_token=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` (USDC), `input_amount=100000000` (100 × 1e6), `output_token=0x0000000000000000000000000000000000000000`.
3. USDC requires an ERC-20 approval — include `data.tx.approve_txs[0]` before the swap call.
4. `send_calls("base", calls)`.

**Show trending tokens on Base**

1. `web_request GET /v1/market/rank?chain=base&interval=1h&limit=10&order_by=volume`.
2. Present token list with price, change, and volume.

**What's the price to buy token X with 50 USDC?**

1. `get_wallets` → address.
2. `web_request GET /v1/trade/quote` with USDC as input, target token as output, `input_amount=50000000`.
3. Show `data.tx.amount_out_usd`, effective price (`data.tx.amount_in_usd / (data.tx.amount_out / 10^data.tx.amount_out_decimals)`), and slippage impact.

***

## Risks & Warnings

### Slippage

| Tolerance | Level | Action |
| - | - | - |
| ≤ 1% | Normal | Proceed. |
| > 1% and ≤ 5% | Elevated | Mention the value and ask the user to confirm. |
| > 5% and ≤ 20% | High | Warn that the trade can fill significantly below quote and is a likely sandwich target. Require explicit confirmation. |
| > 20% | Very high | Strongly warn; do not submit without the user re-confirming the exact number. |

### Low Liquidity

For meme tokens with low liquidity, higher slippage (10–20%) is common. Always warn the user and require explicit confirmation before proceeding. Thin markets increase the risk of severe price impact and sandwich attacks.

### Quote Expiry

Quotes expire at `data.tx.deadline` (Unix timestamp). If the user has not confirmed within \~30 seconds, re-fetch the quote before submitting. Submitting an expired quote will cause the transaction to revert on-chain.

***

## Notes

* Native ETH address: `0x0000000000000000000000000000000000000000`
* USDC on Base: `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913`
* WETH on Base: `0x4200000000000000000000000000000000000006`
* Token amounts are in base units. Use `data.tx.amount_in_decimals` / `data.tx.amount_out_decimals` from the quote response to convert to human-readable values.
* `data.tx.data` is unsigned calldata — pass it directly to `send_calls`; never sign or modify it.
* `data.tx.approve_txs` handles ERC-20 allowances. It is empty when the input is native ETH or when a sufficient allowance already exists.
* `timestamp` must be within ±5 seconds of server time. `client_id` must be a fresh UUID per request.
* Use `chain: "base"` (not numeric chain ID) with `send_calls`.
