{
  "id": "surf.hyperliquid.trades",
  "object": "tool",
  "name": "Closed Trades",
  "summary": "Returns a wallet's closed round-trip trades — one row per open→close position lifecycle, with realized per-trade P&L (gross, net = gross − fees, fees, and funding_pnl as a separate field that net EXCLUDES), entry/exit price, size, and hold time.",
  "description": "Returns a wallet's closed round-trip trades — one row per open→close position lifecycle, with realized per-trade P&L (gross, net = gross − fees, fees, and funding_pnl as a separate field that net EXCLUDES), entry/exit price, size, and hold time. Newest close first. This is the journal / calendar / attribution source; for fill-level executions use /hyperliquid/fills instead. Returns EVERY closed trade in the window — it does NOT filter by symbol or direction (a symbol/direction query param is ignored, not applied); for per-symbol / per-direction rollups use /hyperliquid/trades/aggregate, or /hyperliquid/fills for symbol-scoped fills. funding_pnl is 0 for warehouse rows and populated only on the live tail, so a funding-inclusive total is incomplete before the watermark. Cursor-paged over the full history (warehouse + a live gap-fill for the most recent days): follow meta.next_cursor to page back. The cursor is a complete continuation token (it encodes the window + position), so pass it with only address and limit — combining it with from/to is rejected. from/to (Unix seconds or a date) bound the window on the first page. A wallet with an extremely large live (post-warehouse) trade history may require a from/to window. NOTE: Surf's own document declares symbol, direction, dex on this endpoint while also stating they are rejected, so they are deliberately NOT accepted here.\n\nRaw surf#hyperliquid/trades endpoint: input is { body, queryParams, pathParams } as the provider documents them (https://docs.asksurf.ai/data-api/hyperliquid/trades).",
  "category": "lookup",
  "hosted_by": "Surf",
  "runtime": "partner",
  "side_effects": false,
  "status": "live",
  "credits": 0,
  "price": null,
  "providers": [
    {
      "id": "surf",
      "name": "Surf",
      "price": null,
      "own_key_only": true
    }
  ],
  "mcp_name": "surf_hyperliquid_trades",
  "input_schema": {
    "type": "object",
    "properties": {
      "queryParams": {
        "type": "object",
        "properties": {
          "address": {
            "type": "string",
            "minLength": 1,
            "description": "Wallet address: a 0x EVM address or an ENS name (e.g. vitalik.eth). Solana addresses are not supported."
          },
          "from": {
            "type": "string",
            "minLength": 1,
            "description": "Window start: Unix seconds, an ISO datetime (2026-03-01T12:00:00Z), or a bare date (= midnight UTC). Omit for the full history. Example: 2026-03-01."
          },
          "to": {
            "type": "string",
            "minLength": 1,
            "description": "Window end, inclusive: Unix seconds, an ISO datetime, or a bare date — a bare date means the END of that UTC day, so from=X&to=X covers the whole day X. Defaults to now. Example: 2026-03-01."
          },
          "cursor": {
            "type": "string",
            "minLength": 1,
            "description": "Opaque continuation token from a previous response's meta.next_cursor. It encodes the window, position, and address, so pass it with only address + limit — and only with the address it was issued for. Tokens are single-use opaque values: identical requests mint different tokens that decode to the same position."
          },
          "limit": {
            "default": 20,
            "type": "integer",
            "minimum": 1,
            "maximum": 100,
            "description": "Page size (1-100). Defaults to 20."
          }
        },
        "required": [
          "address"
        ],
        "additionalProperties": false
      }
    },
    "required": [
      "queryParams"
    ],
    "additionalProperties": false
  },
  "kind": "endpoint"
}