> For the complete documentation index, see [llms.txt](https://gotts.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://gotts.gitbook.io/docs/gotts-safe-mcp-server/mcp-server/04-tools-trading.md).

# Trading Tools

> **Package**: `packages/safe/` | **Prerequisites**: [02-architecture.md](/docs/gotts-safe-mcp-server/mcp-server/02-architecture.md)
>
> Trading tools and approval/permit tools (Phase 2). For other tool categories, see the [README](/docs/gotts-safe-mcp-server/mcp-server.md).

***

## Trading Tools

#### `get_quote`

Get a price quote for a swap. Does not execute -- returns quote details for agent review.

**Parameters**:

| Name                | Type     | Required | Description                                                      |
| ------------------- | -------- | -------- | ---------------------------------------------------------------- |
| `tokenIn`           | `string` | Yes      | Input token symbol or address                                    |
| `tokenOut`          | `string` | Yes      | Output token symbol or address                                   |
| `amount`            | `string` | Yes      | Amount of input token (human-readable, e.g., "500" for 500 USDC) |
| `chain`             | `string` | Yes      | Chain name or chain ID                                           |
| `type`              | `string` | No       | "exactIn" (default) or "exactOut"                                |
| `slippageTolerance` | `number` | No       | Slippage tolerance in basis points. Default: 50 (0.5%).          |
| `routingPreference` | `string` | No       | "auto" (default), "v2", "v3", "v4", "uniswapx"                   |

**Returns**:

```json
{
  "quoteId": "q_abc123",
  "tokenIn": {
    "symbol": "USDC",
    "address": "0xA0b8...",
    "amount": "500.000000",
    "amountRaw": "500000000"
  },
  "tokenOut": {
    "symbol": "WETH",
    "address": "0xC02a...",
    "amount": "0.154012",
    "amountRaw": "154012000000000000"
  },
  "executionPrice": "3246.03",
  "midPrice": "3245.67",
  "priceImpact": "0.01%",
  "route": [{ "pool": "USDC/WETH 0.05%", "version": "v3", "percentage": 100 }],
  "estimatedGas": "150000",
  "estimatedGasUsd": "0.45",
  "minimumReceived": "0.153242",
  "slippageTolerance": "0.50%",
  "routingPreference": "auto",
  "validFor": "30s",
  "timestamp": "2026-02-06T12:00:00Z"
}
```

**Error Cases**:

* `INSUFFICIENT_LIQUIDITY`: Not enough liquidity for the requested amount
* `TOKEN_NOT_FOUND`: Token not recognized on this chain
* `AMOUNT_TOO_SMALL`: Amount below minimum tradeable threshold
* `ROUTING_ERROR`: Could not find a valid route

**Implementation**:

* **API path** (when `GOTTS_UNISWAP_API_KEY` is set): `POST /v1/quote` with `{ tokenIn, tokenOut, tokenInChainId, tokenOutChainId, type, amount, swapper, slippageTolerance, autoSlippage, protocols }`. Response includes `routing` type (`CLASSIC`, `DUTCH_V2`, `DUTCH_V3`, `PRIORITY`, `WRAP`, `UNWRAP`, `BRIDGE`) which determines the execution path. Response also includes `permitData` when Permit2 approval is needed.
* **SDK path** (when no API key): `@uniswap/smart-order-router` `AlphaRouter.route()` for optimal routing across V2/V3/V4 pools.
* The `routing` field is included in the response JSON. A `permitRequired` boolean indicates whether Permit2 signing is needed before execution.

**Memory Hints** (when `learning` profile active): The response includes an additional `memoryHints` array of advisory strings derived from past episodes and insights for this token pair and chain. These are informational only — they do not alter the quote.

```json
{
  "memoryHints": [
    "Historical avg slippage for USDC→WETH on Base: 0.02% (well below 0.5% tolerance)",
    "V3 0.05% pool has outperformed 0.30% for amounts under $5K in 8 of last 10 episodes"
  ]
}
```

***

#### `execute_swap`

Execute a token swap. Runs the full pipeline: quote, safety checks, simulate, sign, broadcast, confirm.

**Parameters**:

| Name                | Type      | Required | Description                                                  |
| ------------------- | --------- | -------- | ------------------------------------------------------------ |
| `tokenIn`           | `string`  | Yes      | Input token symbol or address                                |
| `tokenOut`          | `string`  | Yes      | Output token symbol or address                               |
| `amount`            | `string`  | Yes      | Amount of input token (human-readable)                       |
| `chain`             | `string`  | Yes      | Chain name or chain ID                                       |
| `slippageTolerance` | `number`  | No       | Slippage in basis points. Default: 50 (0.5%).                |
| `deadline`          | `number`  | No       | Tx deadline in seconds from now. Default: 300 (5 min).       |
| `routingPreference` | `string`  | No       | "auto" (default), "v2", "v3", "v4", "uniswapx"               |
| `skipSimulation`    | `boolean` | No       | Skip pre-flight simulation. Default: false. NOT RECOMMENDED. |

**Returns**:

```json
{
  "status": "success",
  "txHash": "0xDEAD...",
  "blockNumber": 19234567,
  "gasUsed": "145000",
  "gasPrice": "3.2 gwei",
  "gasCostUsd": "0.42",
  "tokenIn": {
    "symbol": "USDC",
    "amount": "500.000000"
  },
  "tokenOut": {
    "symbol": "WETH",
    "amount": "0.153856"
  },
  "executionPrice": "3249.34",
  "priceImpact": "0.01%",
  "slippage": "0.10%",
  "route": [{ "pool": "USDC/WETH 0.05%", "version": "v3", "percentage": 100 }],
  "explorerUrl": "https://etherscan.io/tx/0xDEAD...",
  "safetyChecks": {
    "tokenAllowlistPassed": true,
    "spendingLimitPassed": true,
    "rateLimitPassed": true,
    "balanceCheckPassed": true,
    "simulationPassed": true,
    "slippageGuardPassed": true
  }
}
```

**Error Cases**:

* `SAFETY_TOKEN_NOT_ALLOWED`: Token not on allowlist
* `SAFETY_SPENDING_LIMIT_EXCEEDED`: Would exceed per-tx or daily spending limit
* `SAFETY_RATE_LIMIT_EXCEEDED`: Too many operations in the time window
* `SAFETY_INSUFFICIENT_BALANCE`: Not enough balance (including gas reserve)
* `SAFETY_SIMULATION_FAILED`: Pre-flight simulation reverted
* `SAFETY_SIMULATION_DIVERGED`: Simulated output diverged from quote by more than tolerance
* `SAFETY_SLIPPAGE_TOO_HIGH`: Quote slippage exceeds configured maximum
* `SAFETY_NONCE_CONFLICT`: Duplicate transaction detected
* `TX_REVERTED`: Transaction was broadcast but reverted on-chain
* `TX_TIMEOUT`: Transaction was not mined within the deadline

**Implementation**:

The full API-first execution flow (when `GOTTS_UNISWAP_API_KEY` is set):

1. `POST /check_approval` — get approval tx if needed, broadcast it
2. `POST /quote` — get best route + `permitData`
3. Safety middleware validation (unchanged — all 7 checks run)
4. If `permitData` present: sign EIP-712 typed data via wallet
5. Route by `routing` type:
   * `CLASSIC` / `WRAP` / `UNWRAP` / `BRIDGE` → `POST /swap` with `{ quote, signature, permitData }` → broadcast returned `TransactionRequest`
   * `DUTCH_V2` / `DUTCH_V3` / `PRIORITY` → `POST /order` with `{ signature, quote }` → gasless, no broadcast needed
6. **Critical rules**: `signature` and `permitData` must both be present or both omitted. Never set either to `null`. Validate `swap.data` is non-empty (`""` or `"0x"` are invalid) before broadcast. Apply 10-20% gas buffer to `gasLimit` from API response.

**SDK fallback path** (when no API key): smart-order-router → Universal Router SDK calldata encoding → sign → broadcast.

Response includes `routing` type and `gasless: boolean` indicating whether the order was submitted gaslessly via UniswapX.

#### Memory-Augmented Execution (DeFi Brain)

When the `learning` profile is active (`TOOL_PROFILE=trader,learning`), `execute_swap` follows a 5-step memory-augmented lifecycle:

1. **RETRIEVE**: Before execution, the memory middleware embeds the swap parameters (tokenIn, tokenOut, amount, chain) and retrieves top-k similar episodes from LanceDB + relevant insights from SQLite (confidence ≥ `GOTTS_MEMORY_CONFIDENCE_THRESHOLD`).
2. **AUGMENT**: Memory may adjust **soft parameters only** — e.g., recommend tighter slippage tolerance if past episodes show consistently low slippage for this pair, or suggest timing delays if VPIN-related insights indicate high toxicity windows. Memory **cannot** override safety limits, spending caps, token allowlist, or simulation requirements.
3. **EXECUTE**: Normal execution pipeline (unchanged — all 7 safety checks run).
4. **REFLECT**: After settlement, generate a structured reflection comparing predicted vs actual outcome (slippage, price impact, gas, route quality).
5. **STORE**: Store the episode in LanceDB with outcome, reflection, chain, and tokenPair metadata.

The response JSON includes an additional `memoryContext` field when the learning profile is active:

```json
{
  "memoryContext": {
    "episodesRetrieved": 3,
    "insightsApplied": 1,
    "adjustments": [
      "Slippage tolerance tightened from 50bps to 30bps based on 3 similar episodes (avg actual: 0.02%)"
    ],
    "episodeStored": "ep_a1b2c3d4"
  }
}
```

***

#### `submit_uniswapx_order`

Submit a UniswapX Dutch auction order for potentially better execution through off-chain fillers.

**Parameters**:

| Name             | Type     | Required | Description                                            |
| ---------------- | -------- | -------- | ------------------------------------------------------ |
| `tokenIn`        | `string` | Yes      | Input token symbol or address                          |
| `tokenOut`       | `string` | Yes      | Output token symbol or address                         |
| `amount`         | `string` | Yes      | Amount of input token (human-readable)                 |
| `chain`          | `string` | Yes      | Chain name or chain ID                                 |
| `orderType`      | `string` | No       | "dutch" (default) or "priority"                        |
| `decayStartTime` | `number` | No       | Seconds from now for price decay to begin. Default: 0. |
| `decayEndTime`   | `number` | No       | Seconds from now for price decay to end. Default: 300. |

**Returns**:

```json
{
  "orderId": "0xORDER...",
  "status": "submitted",
  "orderType": "dutch",
  "tokenIn": { "symbol": "USDC", "amount": "1000.000000" },
  "tokenOut": { "symbol": "WETH", "amount": "0.308024" },
  "startAmount": "0.310000",
  "endAmount": "0.305000",
  "decayStartTime": "2026-02-06T12:00:00Z",
  "decayEndTime": "2026-02-06T12:05:00Z",
  "signature": "0xSIG...",
  "statusUrl": "https://api.uniswap.org/v2/orders?orderId=0xORDER..."
}
```

**Implementation**: When API key available, uses `POST /quote` with `protocols: ["UNISWAPX_V2"]` then `POST /order`. Minimum trade size on L2: \~1000 USDC equivalent. No native token input supported. Supported chains: Ethereum, Arbitrum, Base, Unichain.

***

#### `get_uniswapx_order_status`

Check the status of a submitted UniswapX order.

**Parameters**:

| Name      | Type     | Required | Description                                    |
| --------- | -------- | -------- | ---------------------------------------------- |
| `orderId` | `string` | Yes      | Order ID returned from `submit_uniswapx_order` |
| `chain`   | `string` | Yes      | Chain name or chain ID                         |

**Returns**:

```json
{
  "orderId": "0xORDER...",
  "status": "filled",
  "fillTxHash": "0xFILL...",
  "fillerAddress": "0xFILLER...",
  "amountIn": "1000.000000",
  "amountOut": "0.309123",
  "fillPrice": "3234.89",
  "filledAt": "2026-02-06T12:01:23Z",
  "explorerUrl": "https://etherscan.io/tx/0xFILL..."
}
```

***

#### `submit_cross_chain_intent`

Submit an ERC-7683 cross-chain intent for cross-chain swaps. The intent is fulfilled by the ERC-7683 filler network.

**Parameters**:

| Name               | Type     | Required | Description                                                    |
| ------------------ | -------- | -------- | -------------------------------------------------------------- |
| `tokenIn`          | `string` | Yes      | Input token symbol or address                                  |
| `tokenOut`         | `string` | Yes      | Output token symbol or address                                 |
| `amount`           | `string` | Yes      | Amount of input token (human-readable)                         |
| `sourceChain`      | `string` | Yes      | Source chain name or ID                                        |
| `destinationChain` | `string` | Yes      | Destination chain name or ID                                   |
| `recipient`        | `string` | No       | Recipient address on destination chain. Default: agent wallet. |
| `fillDeadline`     | `number` | No       | Seconds from now for fill deadline. Default: 3600 (1 hour).    |

**Returns**:

```json
{
  "intentId": "0xINTENT...",
  "status": "submitted",
  "sourceChain": "ethereum",
  "destinationChain": "base",
  "tokenIn": {
    "symbol": "USDC",
    "address": "0xA0b8...",
    "amount": "1000.000000",
    "chain": "ethereum"
  },
  "tokenOut": {
    "symbol": "WETH",
    "address": "0x4200...",
    "amount": "0.307500",
    "chain": "base"
  },
  "fillDeadline": "2026-02-06T13:00:00Z",
  "orderType": "GaslessCrossChainOrder",
  "originTxHash": "0xORIGIN...",
  "trackingUrl": "https://erc7683.org/intent/0xINTENT..."
}
```

**Error Cases**:

* `CROSS_CHAIN_NOT_SUPPORTED`: Source or destination chain not supported for ERC-7683
* `FILLER_NETWORK_UNAVAILABLE`: No fillers available for this route
* `AMOUNT_TOO_SMALL`: Below minimum for cross-chain intent

**Implementation**: When API key available, uses `POST /quote` with `x-chained-actions-enabled: true` header and different `tokenInChainId`/`tokenOutChainId`. Handle `BRIDGE` routing (single tx via `/swap`) or `CHAINED` routing (multi-step via `/plan` endpoint: `POST /plan` → broadcast source tx → `PATCH /plan/:planId` with tx hash → poll `GET /plan/:planId` for completion).

***

#### `claim_lp_rewards`

> **Canonical definition**: See [05-tools-liquidity.md](/docs/gotts-safe-mcp-server/mcp-server/05-tools-liquidity.md#claim_lp_rewards). Listed here for completeness as it is invoked during trading workflows (e.g., post-swap reward harvesting).

***

## Approval and Permit Tools

#### `check_allowance`

Check if a token is approved for spending by the Universal Router (or Permit2).

**Parameters**:

| Name      | Type     | Required | Description                                    |
| --------- | -------- | -------- | ---------------------------------------------- |
| `token`   | `string` | Yes      | Token symbol or address                        |
| `chain`   | `string` | Yes      | Chain name or chain ID                         |
| `spender` | `string` | No       | Spender address. Default: Permit2 contract.    |
| `owner`   | `string` | No       | Token owner. Default: configured agent wallet. |

**Returns**:

```json
{
  "token": "USDC",
  "tokenAddress": "0xA0b8...",
  "chain": "ethereum",
  "owner": "0x1234...",
  "spender": "0x000000000022D473030F116dDEE9F6B43aC78BA3",
  "spenderLabel": "Permit2",
  "allowance": "115792089237316195423570985008687907853269984665640564039457584007913129639935",
  "allowanceHuman": "unlimited",
  "isApproved": true,
  "approvalNeeded": false
}
```

***

#### `approve_token`

Approve a token for spending by Permit2 (or a specific spender).

**Parameters**:

| Name      | Type     | Required | Description                                        |
| --------- | -------- | -------- | -------------------------------------------------- |
| `token`   | `string` | Yes      | Token symbol or address                            |
| `chain`   | `string` | Yes      | Chain name or chain ID                             |
| `amount`  | `string` | No       | Approval amount. Default: max uint256 (unlimited). |
| `spender` | `string` | No       | Spender address. Default: Permit2 contract.        |

**Returns**:

```json
{
  "status": "success",
  "txHash": "0xAPPR...",
  "token": "USDC",
  "spender": "Permit2",
  "amount": "unlimited",
  "explorerUrl": "https://etherscan.io/tx/0xAPPR..."
}
```

***

#### `sign_permit2`

Create a Permit2 signature for gasless token approvals to the Universal Router.

**Parameters**:

| Name         | Type     | Required | Description                                                    |
| ------------ | -------- | -------- | -------------------------------------------------------------- |
| `token`      | `string` | Yes      | Token symbol or address                                        |
| `amount`     | `string` | Yes      | Amount to permit (human-readable)                              |
| `chain`      | `string` | Yes      | Chain name or chain ID                                         |
| `spender`    | `string` | No       | Spender (typically Universal Router). Default: auto-detected.  |
| `expiration` | `number` | No       | Permit expiration in seconds from now. Default: 1800 (30 min). |

**Returns**:

```json
{
  "token": "USDC",
  "amount": "500.000000",
  "spender": "0x3fC91A3afd70395Cd496C647d5a6CC9D4B2b7FAD",
  "spenderLabel": "Universal Router",
  "nonce": 0,
  "deadline": 1738843800,
  "signature": "0xSIG...",
  "permitData": {
    "domain": {
      "name": "Permit2",
      "chainId": 1,
      "verifyingContract": "0x0000..."
    },
    "types": {},
    "values": {}
  }
}
```

***

#### `batch_permit2`

Create a batch Permit2 signature for multiple tokens in one signature (useful before multi-token LP operations).

**Parameters**:

| Name         | Type     | Required | Description                                           |
| ------------ | -------- | -------- | ----------------------------------------------------- |
| `tokens`     | `array`  | Yes      | Array of `{ token: string, amount: string }` objects  |
| `chain`      | `string` | Yes      | Chain name or chain ID                                |
| `spender`    | `string` | No       | Spender. Default: Universal Router.                   |
| `expiration` | `number` | No       | Permit expiration in seconds from now. Default: 1800. |

**Returns**:

```json
{
  "tokens": [
    { "symbol": "USDC", "amount": "5000.000000" },
    { "symbol": "WETH", "amount": "1.540000000000000000" }
  ],
  "spender": "Universal Router",
  "signature": "0xBATCHSIG...",
  "nonce": 1,
  "deadline": 1738843800
}
```

***
