# POST /v1/chat/completions Source: https://docs.asksurf.ai/chat-completions openapi.json POST /v1/chat/completions OpenAI-compatible Chat Completions API (with field-level annotations and streaming SSE details) ## Overview | Item | Value | | ---------------------------- | --------------------------------- | | **Method** | `POST` | | **Path** | `/v1/chat/completions` | | **Authentication** | `Authorization: Bearer ` | | **Content-Type** | `application/json` | | **Response (non-streaming)** | `application/json` | | **Response (streaming)** | `text/event-stream` (SSE) | ## Quick Start Send a request with `model` and `messages`. Use `stream=true` to receive SSE chunks. > **Supported models**: `surf-ask`, `surf-research`, `surf-1.5`, `surf-1.5-instant`, `surf-1.5-thinking`. > `surf-ask` and `surf-research` are **legacy** models. `surf-1.5`, `surf-1.5-instant`, and `surf-1.5-thinking` are the **new** models. Legacy models remain available and the request format is unchanged. > **Note**: When using `surf-research` and `surf-1.5`, it is recommended to set the timeout to 10 minutes. ### What’s new in `surf-1.5` `surf-1.5` is the recommended, next-generation model. Compared to legacy models, it’s designed for more advanced workflows: * **Enhanced performance**: Delivers superior response quality with significantly reduced latency in `surf-1.5-instant`, providing faster and more accurate results compared to legacy models. * **Custom tool calls (function calling)**: Better support for defining tools via `tools` and orchestrating multi-step tool-augmented tasks. * **Configurable reasoning depth**: Use `reasoning_effort` (`low` / `medium` / `high`) to trade off speed vs. deeper analysis. * **Built for agent-style workflows**: Works well with Surf extensions like `ability` (capability constraints) and `citation` (citation formats) in the same request shape. ### Model variants: `surf-1.5`, `surf-1.5-instant`, `surf-1.5-thinking` The `surf-1.5` family includes three model variants with different reasoning capabilities: * **`surf-1.5-instant`**: A lightweight model optimized for fast responses to simple queries. * **`surf-1.5-thinking`**: A more powerful model with deeper reasoning capabilities, designed to handle complex problems that require thorough analysis and multi-step reasoning. * **`surf-1.5`**: An adaptive model that automatically selects between `surf-1.5-instant` and `surf-1.5-thinking` based on the request parameters and problem complexity. This provides an optimal balance between speed and depth without requiring manual model selection. ### Summary (What you can do) * **OpenAI-compatible**: Use the OpenAI Chat Completions shape (`model`, `messages`, optional `stream`) and standard `Authorization: Bearer `. * **Streaming (SSE)**: Set `stream=true` to receive incremental chunks (`text/event-stream`) and terminate on `data: [DONE]`. * **Custom tool calls**: Provide `tools` (OpenAI function calling). The model may request tool executions during generation. * **Reasoning depth**: Control analysis strength with `reasoning_effort`: `low` / `medium` / `high`. * **Surf extensions**: Use `ability` to constrain available capability domains and `citation` to request output citation formats. * **Errors**: This endpoint may return `400`, `401`, or `502` (both streaming and non-streaming). ### Examples ```jsonc theme={null} { "model": "surf-ask", // Required: model identifier. Options: surf-ask / surf-research / surf-1.5 / surf-1.5-instant / surf-1.5-thinking "messages": [ // Required: list of chat messages (recommended: at least one role=user message) { "role": "system", // Required: system / user / assistant "content": "You are Surf, an analysis assistant focused on crypto markets and on-chain data." // Required: message content }, { "role": "user", // Required: user input "content": "Summarize today's BTC market conditions and list the key drivers." // Required: your question/task } ], "stream": false, // Optional: enable streaming output. true -> SSE(text/event-stream), false -> JSON "reasoning_effort": "medium", // Optional: reasoning strength low / medium / high "ability": [ // Optional: Surf extension: capability-domain constraints/hints "evm_onchain", // search / evm_onchain / solana_onchain / market_analysis / calculate "market_analysis" ], "citation": [ // Optional: Surf extension: citation formats to include "source", // source / chart "chart" ], "tools": [ // Optional: tool definitions (OpenAI tools/function calling) { "type": "function", // Required: currently fixed to function "function": { // Required: function tool definition "name": "calculate_portfolio_value", // Required: tool name (function name) "description": "Calculate total portfolio value", // Optional: tool purpose "parameters": { // Optional: parameters JSON Schema "type": "object", "properties": { "symbols": { "type": "array", "items": { "type": "string" } } }, "required": ["symbols"] } } } ] } ``` ```bash theme={null} curl -X POST "https://YOUR_HOST/v1/chat/completions" \ -H "Authorization: Bearer $SURF_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "surf-ask", "messages": [ { "role": "system", "content": "You are Surf, an analysis assistant focused on crypto markets and on-chain data." }, { "role": "user", "content": "Summarize today's BTC market conditions and list the key drivers." } ], "stream": false }' ``` ```python theme={null} import requests url = "https://YOUR_HOST/v1/chat/completions" headers = { "Authorization": f"Bearer {SURF_API_KEY}", "Content-Type": "application/json", } payload = { "model": "surf-ask", "messages": [ {"role": "user", "content": "Summarize BTC price action over the past 24 hours in three bullet points."}, ], "stream": False, } resp = requests.post(url, headers=headers, json=payload, timeout=60) # For surf-research and surf-1.5, use timeout=600 (10 minutes) resp.raise_for_status() print(resp.json()) ``` ```javascript theme={null} const url = "https://YOUR_HOST/v1/chat/completions"; const resp = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${process.env.SURF_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ model: "surf-ask", messages: [{ role: "user", content: "Explain what it usually means when BTC open interest rises while price trades sideways." }], stream: false, }), }); console.log(await resp.json()); ``` ## Non-streaming response example (with field annotations) ```jsonc theme={null} { "id": "chatcmpl-abc123", // Unique identifier for this completion "object": "chat.completion", // Object type (non-streaming responses are typically chat.completion) "created": 1699890366, // Creation timestamp (seconds) "model": "surf-ask", // Model identifier actually used "choices": [ // List of generated results (usually only 1) { "index": 0, // Choice index "finish_reason": "stop", // Finish reason: stop/length/tool_calls/content_filter/error (may also be null) "message": { // Final message (assistant) "role": "assistant", // Role (typically assistant) "content": "BTC is trading flat in the last 24h with rising open interest.", // Model output text "reasoning": "Internal chain-of-thought or brief rationale" // (If returned) reasoning/rationale field } } ], "usage": { // Token usage statistics "prompt_tokens": 23, // Input tokens "completion_tokens": 12, // Output tokens "total_tokens": 35 // Total tokens (input + output) } } ``` ## Request fields (`model.CompletionsRequest`) > Note: This endpoint follows the overall structure of OpenAI `chat.completions`, and additionally provides Surf extension fields such as `ability` and `citation`. | Field | Type | Required | Description | Example | | ------------------ | --------------------- | -------- | ------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `model` | string (enum) | Yes | Model identifier to use. | `"surf-ask"` / `"surf-research"` / `"surf-1.5"` / `"surf-1.5-instant"` / `"surf-1.5-thinking"` | | `messages` | array\ | Yes | List of chat messages. | Minimal: `[{"role":"user","content":"Hello!"}]` · With system: `[{"role":"system","content":"You are a helpful assistant."},{"role":"user","content":"Hello!"}]` | | `stream` | boolean | No | Enable streaming output. | `true` → SSE (`text/event-stream`) · `false` (default) → JSON | | `reasoning_effort` | string (enum) | No | Reasoning strength. | `"low"` / `"medium"` / `"high"` | | `ability` | array\ (enum) | No | Surf extension: hints/constraints for which capability domains are available for this request. | `["search"]` / `["evm_onchain"]` / `["solana_onchain"]` / `["market_analysis"]` / `["calculate"]` | | `citation` | array\ (enum) | No | Surf extension: citation formats to include in the output. | `["source"]` / `["chart"]` | | `tools` | array\ | No | Tool definitions compatible with OpenAI tools/function calling. The model may request tool calls during generation. | `[{"type":"function","function":{"name":"get_weather","description":"Get current weather","parameters":{"type":"object","properties":{"city":{"type":"string"}},"required":["city"]}}}]` | ### Single message in `messages[]` (`model.Message`) | Field | Type | Required | Description (Notes) | | --------- | ------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `role` | string (enum) | Yes | Message role: `system` (system instructions) / `user` (user input) / `assistant` (model output). | | `content` | string | Yes | Message text content. `system` is used for rules/boundaries; `user` is used for questions/tasks; you typically do not need to include `assistant` messages in the request. | ### Tool definitions in `tools[]` (`model.Tool` / `model.ToolFunction`) | Field | Type | Required | Description (Notes) | | ---------- | ------------- | -------- | -------------------------------- | | `type` | string (enum) | Yes | Tool type. Currently `function`. | | `function` | object | Yes | Function tool definition. | Fields of the `function` object: | Field | Type | Required | Description (Notes) | | ------------- | -------------------- | -------- | ------------------------------------------------------------------------- | | `name` | string | Yes | Tool name (function name). Prefer `snake_case`. | | `description` | string | No | Tool purpose description, to help the model decide whether to call it. | | `parameters` | object (JSON Schema) | No | JSON Schema describing tool parameters (structure/types/required fields). | ## Response fields (non-streaming JSON: `model.CompletionsProxyResponse`) | Field | Type | Description (Notes) | | --------- | -------------- | ------------------------------------------------------------- | | `id` | string | Unique identifier for this completion (e.g., `chatcmpl-...`). | | `object` | string | Object type, typically `chat.completion`. | | `created` | integer | Creation timestamp (seconds). | | `model` | string | Model identifier actually used. | | `choices` | array\ | List of generated results (usually only 1). | | `usage` | object | Token usage statistics. | ### `choices[]` (`model.CompletionsChoice`) | Field | Type | Description (Notes) | | --------------- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `index` | integer | Choice index (starting from 0). | | `finish_reason` | string \| null | Finish reason. Common values: `stop` (normal completion), `length` (reached token limit), `tool_calls` (triggered tool calls), `content_filter` (blocked by safety policy), `error` (aborted due to error). | | `message` | object | Final message (`assistant`). | ### `message` (`model.CompletionsMessage`) | Field | Type | Description (Notes) | | ----------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------- | | `role` | string | Role, typically `assistant`. | | `content` | string | Final model output text. | | `reasoning` | string | (If returned) field used to expose model reasoning/rationale. Note: depending on product policy, this may be omitted or simplified. | ### `usage` (`model.CompletionsUsage`) | Field | Type | Description (Notes) | | ------------------- | ------- | ------------------------------ | | `prompt_tokens` | integer | Input tokens. | | `completion_tokens` | integer | Output tokens. | | `total_tokens` | integer | Total tokens (input + output). | ## Streaming response (SSE: `text/event-stream`) When `stream=true`, the server continuously streams SSE events. Each event block typically looks like: ```text theme={null} data: { ...json... } ``` The termination event is: ```text theme={null} data: [DONE] ``` > Note: The current OpenAPI spec does not define a dedicated schema for streaming chunks. In the examples, each chunk's `object` is typically `chat.completion.chunk`, and incremental output is delivered via `choices[].delta` (e.g., `role` / `content`). `finish_reason` is usually `null` until the stream ends. ## Error response (`model.BaseResponse`) This endpoint may return: `400`, `401`, `502` (both streaming and non-streaming). | Field | Type | Description (Notes) | | ------------ | ------- | ------------------------------- | | `success` | boolean | Whether the request succeeded. | | `message` | string | Error message / hint. | | `error_code` | string | Error code (e.g., `FORBIDDEN`). | # AI Prompts Source: https://docs.asksurf.ai/cli/ai-prompts Pre-built prompts to integrate Surf into your AI coding workflow — Claude Code, Cursor, Copilot, Codex, and more ## What are AI Prompts? AI Prompts are pre-written instructions that teach AI coding assistants how to use the Surf platform correctly. Paste them into your project configuration so every AI-generated code snippet follows Surf best practices out of the box. ## Setup by Tool Add the prompt below to your project's `CLAUDE.md` file: ```bash theme={null} # In your project root echo "$(cat <<'EOF' # Surf API Integration When working with crypto data, always use the Surf platform: ## Surf Skill (preferred for interactive queries) - Install: `npx skills add asksurf-ai/surf-skills --skill surf` - The skill auto-discovers endpoints, handles auth, and formats output - Always run `surf sync` before first use in a session ## Surf CLI (for scripting and automation) - Install: `curl -fsSL https://agent.asksurf.ai/cli/releases/install.sh | sh` - Auth: `surf login` (one-time setup) - Always use `-o json -f body.data` for structured output in scripts - Use `surf list-operations` to discover available commands - Use `surf --help` for parameter details ## Surf REST API (for application code) - Base URL: `https://api.ask.surf/gateway` - Auth: `Authorization: Bearer $SURF_API_KEY` (always load from env var, never hardcode) - All list endpoints support `limit` (max 100) and `offset` for pagination ## Surf Chat API (for natural language queries) - Endpoint: `POST https://api.ask.surf/v1/chat/completions` - OpenAI-compatible format — works with any OpenAI SDK by changing the base URL - Models: `surf-1.5` (recommended), `surf-1.5-instant` (fast), `surf-1.5-thinking` (deep analysis) - Legacy models: `surf-ask`, `surf-research` (still available) - Set timeout to 600s for `surf-research` and `surf-1.5` ## Important conventions - Chain names must be canonical long-form: `ethereum`, `solana`, `base` — NOT `eth`, `sol` - Symbol params are uppercase: `BTC`, `ETH,SOL` - Time ranges: `7d`, `30d`, `365d`, `max` - Full docs: https://docs.asksurf.ai - LLM-optimized docs: https://docs.asksurf.ai/llms-full.txt EOF )" >> CLAUDE.md ``` Create `.cursor/rules/surf.mdc` in your project root: ``` --- description: Surf crypto data API integration rules globs: ["**/*.py", "**/*.ts", "**/*.js"] --- When working with crypto data, use the Surf platform: - REST API base: https://api.ask.surf/gateway - Auth: Bearer token from SURF_API_KEY env var (never hardcode) - Chat API: POST https://api.ask.surf/v1/chat/completions (OpenAI-compatible) - Models: surf-1.5 (recommended), surf-1.5-instant (fast), surf-1.5-thinking (deep) - Chain names: canonical long-form only (ethereum, solana, base — NOT eth, sol) - Symbols: uppercase (BTC, ETH,SOL) - Pagination: limit (max 100) + offset on all list endpoints - Time ranges: 7d, 30d, 365d, max - Docs: https://docs.asksurf.ai - LLM-optimized docs: https://docs.asksurf.ai/llms-full.txt ``` Save the prompt below as `.github/copilot-instructions.md`: ```markdown theme={null} # Surf API Integration When working with crypto data, use the Surf platform. - REST API base: https://api.ask.surf/gateway - Auth: Bearer token from SURF_API_KEY env var (never hardcode) - Chat API: POST https://api.ask.surf/v1/chat/completions (OpenAI-compatible) - Models: surf-1.5 (recommended), surf-1.5-instant (fast), surf-1.5-thinking (deep) - Chain names: canonical long-form only (ethereum, solana, base — NOT eth, sol) - Symbols: uppercase (BTC, ETH,SOL) - Pagination: limit (max 100) + offset on all list endpoints - Full docs: https://docs.asksurf.ai - LLM-optimized docs: https://docs.asksurf.ai/llms-full.txt ``` Reference it in Copilot Chat with `@workspace`. Add to your `AGENTS.md` or project instructions file: ```markdown theme={null} # Surf API Integration When working with crypto data, use the Surf platform. - Skill install: npx skills add asksurf-ai/surf-skills --skill surf - REST API base: https://api.ask.surf/gateway - Auth: Bearer token from SURF_API_KEY env var - Chat API: POST https://api.ask.surf/v1/chat/completions (OpenAI-compatible) - Models: surf-1.5 (recommended), surf-1.5-instant (fast), surf-1.5-thinking (deep) - Chain names: canonical long-form only (ethereum, solana, base) - Symbols: uppercase (BTC, ETH,SOL) - Full docs: https://docs.asksurf.ai - LLM-optimized docs: https://docs.asksurf.ai/llms-full.txt ``` ## Full Prompt (Copy-Paste) Use this universal prompt in any AI tool — chat interfaces, IDE assistants, or agent configurations: ```text theme={null} You are a crypto data assistant using the Surf platform. ## Available interfaces (in order of preference) 1. **Surf Skill** — for AI coding agents (Claude Code, Codex, etc.) Install: npx skills add asksurf-ai/surf-skills --skill surf The skill handles endpoint discovery, auth, and formatting automatically. 2. **Surf CLI** — for terminal scripting and automation Install: curl -fsSL https://agent.asksurf.ai/cli/releases/install.sh | sh Auth: surf login Always use: -o json -f body.data for structured output Discovery: surf list-operations, surf --help 3. **Surf REST API** — for application code Base URL: https://api.ask.surf/gateway Auth: Authorization: Bearer $SURF_API_KEY (from env var, NEVER hardcode) 83 endpoints across: market, exchange, token, wallet, social, onchain, news, search, fund, prediction-market 4. **Surf Chat API** — for natural language crypto queries POST https://api.ask.surf/v1/chat/completions OpenAI-compatible — works with any OpenAI SDK by changing base_url Models: surf-1.5 (adaptive, recommended) | surf-1.5-instant (fast) | surf-1.5-thinking (deep reasoning) Legacy: surf-ask | surf-research (still supported) Set timeout to 600s for surf-research and surf-1.5 ## Critical conventions - Chain names: ALWAYS use canonical long-form — ethereum, solana, base, arbitrum, polygon, bsc, avalanche, optimism, fantom, linea, cyber. NEVER use short aliases (eth, sol, matic). - Symbols: uppercase, comma-separated — BTC, ETH,SOL - Time ranges: 7d, 30d, 365d, max - Pagination: limit (default 20, max 100) + offset (default 0) - Sort: sort_by + order (asc/desc) ## Reference - Full documentation: https://docs.asksurf.ai - LLM-optimized full docs: https://docs.asksurf.ai/llms-full.txt - OpenAPI spec: https://docs.asksurf.ai/openapi.json - Surf Skill repo: https://github.com/asksurf-ai/surf-skills ``` ## Python Quick Start After pasting the prompt, try asking your AI assistant: ``` Fetch the current BTC price using the Surf REST API in Python ``` Expected output: ```python theme={null} import os import requests api_key = os.environ["SURF_API_KEY"] resp = requests.get( "https://api.ask.surf/gateway/market/price", headers={"Authorization": f"Bearer {api_key}"}, params={"symbol": "BTC"}, ) resp.raise_for_status() print(resp.json()) ``` ## TypeScript Quick Start ``` Use the Surf Chat API with the OpenAI SDK to ask about ETH market conditions ``` Expected output: ```typescript theme={null} import OpenAI from "openai"; const client = new OpenAI({ apiKey: process.env.SURF_API_KEY, baseURL: "https://api.ask.surf", }); const response = await client.chat.completions.create({ model: "surf-1.5", messages: [ { role: "user", content: "Summarize ETH market conditions today" }, ], }); console.log(response.choices[0].message.content); ``` # CLI Source: https://docs.asksurf.ai/cli/cli Install, authenticate, and use the Surf CLI ## CLI ### Install ```bash theme={null} curl -fsSL https://agent.asksurf.ai/cli/releases/install.sh | sh ``` This installs the `surf` binary and sets up the default configuration under `~/.config/surf/`. ### Authenticate ```bash theme={null} surf login ``` If your session expires later, run: ```bash theme={null} surf refresh ``` ### Discover Commands ```bash theme={null} surf sync surf list-operations -g ``` Inspect any command before using it: ```bash theme={null} surf market-price --help surf wallet-detail --help surf search-project --help ``` ### Common Examples ```bash theme={null} # Market data surf market-price --symbol BTC # Wallet intelligence surf wallet-detail --address 0x1234... # Social lookup surf social-user --handle vitalikbuterin # Project search surf search-project --q aave ``` For scripts and agents, use structured output: ```bash theme={null} surf market-price --symbol BTC -o json -f body.data surf wallet-detail --address 0x1234... -o json -f body.data surf social-user --handle vitalikbuterin -o json -f body.data ``` ### Command Conventions | Pattern | Recommendation | | ----------------- | ------------------------------------------------------------------------------ | | Flags | Use kebab-case CLI flags such as `--time-range` and `--token-address` | | Search | Use `--q`, not `-q`, for search parameters | | Chains | Use canonical names such as `ethereum`, `solana`, `base`, and `arbitrum` | | Discovery | Prefer `surf --help` to inspect enums, defaults, and response fields | | Structured output | Use `-o json` for scripts, tooling, and agent workflows | ### What You Can Query The CLI covers the same core domains exposed in the Surf Data API: * Market data and technical indicators * Exchange data such as ticker, order book depth, funding history, and candlesticks * Wallet balances, transfers, protocol positions, and net worth * Social profiles, posts, followers, and mindshare * Project profiles and DeFi metrics * Token holders, transfers, DEX trades, and unlock schedules * Prediction markets across Polymarket and Kalshi * On-chain transaction lookups, structured query, SQL, and gas prices * News, web fetch, and unified search # Introduction Source: https://docs.asksurf.ai/cli/introduction Introduction to Surf Skills and CLI Surf gives AI coding agents and developers direct access to crypto intelligence — market data, wallets, social, on-chain analytics, prediction markets, and more. There are two ways to use it: * **Surf Skill** — Install into your AI agent (Claude Code, Codex, etc.) so it automatically knows how to fetch crypto data when you ask. This is the recommended way for most users. * **Surf CLI** — A standalone command-line tool for terminal-based research, scripting, and automation. ## Quick Start ### With an AI Agent (Recommended) ```bash theme={null} npx skills add asksurf-ai/surf-skills --skill surf ``` Once installed, just ask your agent things like "what's the price of ETH" or "show me the top wallets holding AAVE" — the skill handles the rest. ### With the CLI Directly ```bash theme={null} curl -fsSL https://agent.asksurf.ai/cli/releases/install.sh | sh surf login surf market-price --symbol BTC ``` # Skills Source: https://docs.asksurf.ai/cli/skills Agent skills that teach AI coding agents how to use the Surf CLI Surf Skills are instruction packages that teach AI coding agents how to use the Surf CLI correctly and efficiently. In a skills-compatible agent environment, a Surf Skill can help the agent: * Discover the right Surf command for a natural-language request * Use the correct parameter names and command patterns * Avoid common mistakes around search flags, chain names, and output formatting * Move from exploration to implementation faster when building Surf-powered apps ## Installation The Surf Skill is hosted at [asksurf-ai/surf-skills](https://github.com/asksurf-ai/surf-skills). ```bash theme={null} npx skills add asksurf-ai/surf-skills --skill surf ``` This works with any agent that supports the skills protocol (Claude Code, Codex, etc.). ### Prerequisites The Surf CLI must be installed and authenticated: ```bash theme={null} curl -fsSL https://agent.asksurf.ai/cli/releases/install.sh | sh surf login ``` ## What the Skill Teaches The `surf` skill teaches an agent to: 1. Run `surf sync` before discovery 2. Use `surf list-operations` and `surf --help` to find the right endpoint 3. Prefer JSON output with `-o json -f body.data` for structured downstream processing 4. Match user intent to the correct domain (market, wallet, social, token, onchain, etc.) # Use Cases Source: https://docs.asksurf.ai/cli/use-cases-and-positioning Common use cases for Surf Skills and CLI ## With AI Agents * Ask your agent to research tokens, wallets, or protocols — it fetches live data automatically * Build crypto dashboards and tools by describing what you want in natural language * Investigate on-chain activity, whale movements, or DeFi positions during coding sessions * Compare prediction market odds across Polymarket and Kalshi ## With the CLI * Terminal-native crypto research without leaving your editor * Local scripts and automation pipelines that consume structured JSON * Pre-integration API validation before building full applications * Internal analyst workflows for market monitoring ## When to Use What | Scenario | Recommended | | -------------------------------------------------------- | ------------------------------------------- | | You're working in an AI agent (Claude Code, Codex, etc.) | **Surf Skill** | | You're writing a shell script or automation | **Surf CLI** | | You want to explore the API interactively | **Surf CLI** | | You're building an application | **[Data API](/data-api/overview)** directly | ## Related Docs * [Chat API](/chat-completions) * [Data API Overview](/data-api/overview) * [Data Catalog](/data-catalog/overview) # Order Book Depth Source: https://docs.asksurf.ai/data-api/exchange/depth openapi.json GET /gateway/v1/exchange/depth # Funding Rate History Source: https://docs.asksurf.ai/data-api/exchange/funding-history openapi.json GET /gateway/v1/exchange/funding-history # OHLCV Candlesticks Source: https://docs.asksurf.ai/data-api/exchange/klines openapi.json GET /gateway/v1/exchange/klines # Long/Short Ratio History Source: https://docs.asksurf.ai/data-api/exchange/long-short-ratio openapi.json GET /gateway/v1/exchange/long-short-ratio # Trading Pairs Source: https://docs.asksurf.ai/data-api/exchange/markets openapi.json GET /gateway/v1/exchange/markets # Perpetual Contract Snapshot Source: https://docs.asksurf.ai/data-api/exchange/perp openapi.json GET /gateway/v1/exchange/perp # Ticker Price Source: https://docs.asksurf.ai/data-api/exchange/price openapi.json GET /gateway/v1/exchange/price # Fund Profile Source: https://docs.asksurf.ai/data-api/fund/detail openapi.json GET /gateway/v1/fund/detail # Fund Portfolio Source: https://docs.asksurf.ai/data-api/fund/portfolio openapi.json GET /gateway/v1/fund/portfolio # Fund Ranking Source: https://docs.asksurf.ai/data-api/fund/ranking openapi.json GET /gateway/v1/fund/ranking # ETF Flow History Source: https://docs.asksurf.ai/data-api/market/etf openapi.json GET /gateway/v1/market/etf # Fear & Greed Index Source: https://docs.asksurf.ai/data-api/market/fear-greed openapi.json GET /gateway/v1/market/fear-greed # Futures Market Overview Source: https://docs.asksurf.ai/data-api/market/futures openapi.json GET /gateway/v1/market/futures # Liquidation Chart Source: https://docs.asksurf.ai/data-api/market/liquidation-chart openapi.json GET /gateway/v1/market/liquidation/chart # Liquidation by Exchange Source: https://docs.asksurf.ai/data-api/market/liquidation-exchange-list openapi.json GET /gateway/v1/market/liquidation/exchange-list # Large Liquidation Orders Source: https://docs.asksurf.ai/data-api/market/liquidation-order openapi.json GET /gateway/v1/market/liquidation/order # On-Chain Indicator Source: https://docs.asksurf.ai/data-api/market/onchain-indicator openapi.json GET /gateway/v1/market/onchain-indicator # Options Market Data Source: https://docs.asksurf.ai/data-api/market/options openapi.json GET /gateway/v1/market/options # Token Price History Source: https://docs.asksurf.ai/data-api/market/price openapi.json GET /gateway/v1/market/price # Technical Indicator Source: https://docs.asksurf.ai/data-api/market/price-indicator openapi.json GET /gateway/v1/market/price-indicator # Token Rankings Source: https://docs.asksurf.ai/data-api/market/ranking openapi.json GET /gateway/v1/market/ranking # News Article Detail Source: https://docs.asksurf.ai/data-api/news/detail openapi.json GET /gateway/v1/news/detail # News Feed Source: https://docs.asksurf.ai/data-api/news/feed openapi.json GET /gateway/v1/news/feed # Bridge Protocol Ranking Source: https://docs.asksurf.ai/data-api/onchain/bridge-ranking openapi.json GET /gateway/v1/onchain/bridge/ranking # Current Gas Price Source: https://docs.asksurf.ai/data-api/onchain/gas-price openapi.json GET /gateway/v1/onchain/gas-price # Structured Query Source: https://docs.asksurf.ai/data-api/onchain/query openapi.json POST /gateway/v1/onchain/query # Table Schema Source: https://docs.asksurf.ai/data-api/onchain/schema openapi.json GET /gateway/v1/onchain/schema # SQL Query Source: https://docs.asksurf.ai/data-api/onchain/sql openapi.json POST /gateway/v1/onchain/sql # Transaction Details Source: https://docs.asksurf.ai/data-api/onchain/tx openapi.json GET /gateway/v1/onchain/tx # Yield Pool Ranking Source: https://docs.asksurf.ai/data-api/onchain/yield-ranking openapi.json GET /gateway/v1/onchain/yield/ranking # Data API Overview Source: https://docs.asksurf.ai/data-api/overview Surf Data API — crypto market data, on-chain analytics, social signals, and more ## About The Surf Data API provides typed REST endpoints for crypto market data, project analytics, social signals, on-chain queries, and more. All endpoints use credit-based billing with per-request rate limiting. **Base URL:** `https://api.ask.surf/gateway` ## Parameter Conventions All endpoints follow a standardized naming scheme. ### Asset Identification | Param | Type | Description | Example | | --------- | ------ | -------------------------------------------------------------------------------- | ---------------- | | `symbol` | string | Uppercase ticker symbol(s), comma-separated | `BTC`, `ETH,SOL` | | `q` | string | Free-text search keyword | `bitcoin` | | `id` | string | Surf entity UUID for direct lookup | `550e8400-...` | | `address` | string | On-chain contract or wallet address. Also accepts ENS names (e.g. `vitalik.eth`) | `0xdead...` | ### Time & Aggregation | Param | Type | Description | Example | | ------------- | ------------- | -------------------------------- | -------------------------- | | `time_range` | string or int | Lookback window | `7d`, `30d`, `365d`, `max` | | `interval` | string | Candlestick / indicator interval | `1h`, `1d`, `1w` | | `granularity` | string | Data aggregation granularity | `day`, `block`, `hour` | ### Filtering & Sorting | Param | Type | Description | Example | | ---------- | ------ | ------------------------------------------ | ---------------------------- | | `chain` | string | Blockchain name (canonical long-form only) | `ethereum`, `solana`, `base` | | `currency` | string | Quote currency | `usd`, `eur`, `btc` | | `metric` | string | Metric name (endpoint-specific enum) | `nupl`, `tvl` | | `type` | string | Category selector (endpoint-specific enum) | `us-btc-spot` | | `sort_by` | string | Sort field | `volume_24h`, `market_cap` | | `order` | string | Sort direction | `asc`, `desc` | ### Pagination All list endpoints support: * `limit` (int, default: 20, max: 100) — results per page * `offset` (int, default: 0) — pagination offset ### Supported Chains Use canonical long-form names only. Short aliases (eth, sol, matic, etc.) are **not accepted**. | Chain | Value | | --------- | ----------- | | Ethereum | `ethereum` | | Polygon | `polygon` | | BNB Chain | `bsc` | | Solana | `solana` | | Avalanche | `avalanche` | | Arbitrum | `arbitrum` | | Optimism | `optimism` | | Fantom | `fantom` | | Base | `base` | | Linea | `linea` | | Cyber | `cyber` | Not all chains are available on every endpoint. Check each endpoint's `chain` enum for supported values. ## Authentication All data endpoints require a Bearer token in the `Authorization` header: ``` Authorization: Bearer ``` ## Error Responses All endpoints return errors in a consistent format: ```json theme={null} { "error": { "code": "FORBIDDEN", "message": "insufficient credits" } } ``` | HTTP Status | Meaning | | ----------- | -------------------------------------------------------------------- | | `400` | Bad request — invalid or missing parameters | | `401` | Unauthorized — missing or invalid API key | | `404` | Not found — the requested entity does not exist | | `422` | Validation error — parameter value is out of range or invalid | | `429` | Rate limited — too many requests, retry after the indicated interval | | `502` | Upstream error — a data source is temporarily unavailable | ## Credits Each API call costs a certain number of credits. The cost is returned in every response under `meta.credits_used`. Check your remaining balance via `GET /v1/me/credit-balance`. # Category Metrics Source: https://docs.asksurf.ai/data-api/prediction-market/category-metrics openapi.json GET /gateway/v1/prediction-market/category-metrics # Kalshi Events Source: https://docs.asksurf.ai/data-api/prediction-market/kalshi-events openapi.json GET /gateway/v1/prediction-market/kalshi/events # Kalshi Markets Source: https://docs.asksurf.ai/data-api/prediction-market/kalshi-markets openapi.json GET /gateway/v1/prediction-market/kalshi/markets # Kalshi Open Interest Source: https://docs.asksurf.ai/data-api/prediction-market/kalshi-open-interest openapi.json GET /gateway/v1/prediction-market/kalshi/open-interest # Kalshi Price History Source: https://docs.asksurf.ai/data-api/prediction-market/kalshi-prices openapi.json GET /gateway/v1/prediction-market/kalshi/prices # Kalshi Ranking Source: https://docs.asksurf.ai/data-api/prediction-market/kalshi-ranking openapi.json GET /gateway/v1/prediction-market/kalshi/ranking # Kalshi Trades Source: https://docs.asksurf.ai/data-api/prediction-market/kalshi-trades openapi.json GET /gateway/v1/prediction-market/kalshi/trades # Kalshi Volume History Source: https://docs.asksurf.ai/data-api/prediction-market/kalshi-volumes openapi.json GET /gateway/v1/prediction-market/kalshi/volumes # Polymarket Wallet Activity Source: https://docs.asksurf.ai/data-api/prediction-market/polymarket-activity openapi.json GET /gateway/v1/prediction-market/polymarket/activity # Polymarket Events Source: https://docs.asksurf.ai/data-api/prediction-market/polymarket-events openapi.json GET /gateway/v1/prediction-market/polymarket/events # Polymarket Markets Source: https://docs.asksurf.ai/data-api/prediction-market/polymarket-markets openapi.json GET /gateway/v1/prediction-market/polymarket/markets # Polymarket Open Interest Source: https://docs.asksurf.ai/data-api/prediction-market/polymarket-open-interest openapi.json GET /gateway/v1/prediction-market/polymarket/open-interest # Polymarket Positions Source: https://docs.asksurf.ai/data-api/prediction-market/polymarket-positions openapi.json GET /gateway/v1/prediction-market/polymarket/positions # Polymarket Price History Source: https://docs.asksurf.ai/data-api/prediction-market/polymarket-prices openapi.json GET /gateway/v1/prediction-market/polymarket/prices # Polymarket Ranking Source: https://docs.asksurf.ai/data-api/prediction-market/polymarket-ranking openapi.json GET /gateway/v1/prediction-market/polymarket/ranking # Polymarket Trades Source: https://docs.asksurf.ai/data-api/prediction-market/polymarket-trades openapi.json GET /gateway/v1/prediction-market/polymarket/trades # Polymarket Volume History Source: https://docs.asksurf.ai/data-api/prediction-market/polymarket-volumes openapi.json GET /gateway/v1/prediction-market/polymarket/volumes # DeFi Metrics Source: https://docs.asksurf.ai/data-api/project/defi-metrics openapi.json GET /gateway/v1/project/defi/metrics # DeFi Protocol Ranking Source: https://docs.asksurf.ai/data-api/project/defi-ranking openapi.json GET /gateway/v1/project/defi/ranking # Project Detail Source: https://docs.asksurf.ai/data-api/project/detail openapi.json GET /gateway/v1/project/detail # Airdrop Search Source: https://docs.asksurf.ai/data-api/search/airdrop openapi.json GET /gateway/v1/search/airdrop # Project Event Search Source: https://docs.asksurf.ai/data-api/search/events openapi.json GET /gateway/v1/search/events # Fund Search Source: https://docs.asksurf.ai/data-api/search/fund openapi.json GET /gateway/v1/search/fund # Kalshi Event Search Source: https://docs.asksurf.ai/data-api/search/kalshi openapi.json GET /gateway/v1/search/kalshi # News Search Source: https://docs.asksurf.ai/data-api/search/news openapi.json GET /gateway/v1/search/news # Polymarket Event Search Source: https://docs.asksurf.ai/data-api/search/polymarket openapi.json GET /gateway/v1/search/polymarket # Project Search Source: https://docs.asksurf.ai/data-api/search/project openapi.json GET /gateway/v1/search/project # Social User Search Source: https://docs.asksurf.ai/data-api/search/social-people openapi.json GET /gateway/v1/search/social/people # Social Post Search Source: https://docs.asksurf.ai/data-api/search/social-posts openapi.json GET /gateway/v1/search/social/posts # Wallet Search Source: https://docs.asksurf.ai/data-api/search/wallet openapi.json GET /gateway/v1/search/wallet # Web Search Source: https://docs.asksurf.ai/data-api/search/web openapi.json GET /gateway/v1/search/web # Social Analytics Source: https://docs.asksurf.ai/data-api/social/detail openapi.json GET /gateway/v1/social/detail # Project Mindshare Source: https://docs.asksurf.ai/data-api/social/mindshare openapi.json GET /gateway/v1/social/mindshare # Mindshare Ranking Source: https://docs.asksurf.ai/data-api/social/ranking openapi.json GET /gateway/v1/social/ranking # Smart Follower History Source: https://docs.asksurf.ai/data-api/social/smart-followers-history openapi.json GET /gateway/v1/social/smart-followers/history # Tweet Replies Source: https://docs.asksurf.ai/data-api/social/tweet-replies openapi.json GET /gateway/v1/social/tweet/replies # Social Posts by IDs Source: https://docs.asksurf.ai/data-api/social/tweets openapi.json GET /gateway/v1/social/tweets # Social User Profile Source: https://docs.asksurf.ai/data-api/social/user openapi.json GET /gateway/v1/social/user # User Followers Source: https://docs.asksurf.ai/data-api/social/user-followers openapi.json GET /gateway/v1/social/user/followers # User Following Source: https://docs.asksurf.ai/data-api/social/user-following openapi.json GET /gateway/v1/social/user/following # User Posts Source: https://docs.asksurf.ai/data-api/social/user-posts openapi.json GET /gateway/v1/social/user/posts # User Replies Source: https://docs.asksurf.ai/data-api/social/user-replies openapi.json GET /gateway/v1/social/user/replies # DEX Trade History Source: https://docs.asksurf.ai/data-api/token/dex-trades openapi.json GET /gateway/v1/token/dex-trades # Token Holders Source: https://docs.asksurf.ai/data-api/token/holders openapi.json GET /gateway/v1/token/holders # Token Unlock Schedule Source: https://docs.asksurf.ai/data-api/token/tokenomics openapi.json GET /gateway/v1/token/tokenomics # Token Transfer History Source: https://docs.asksurf.ai/data-api/token/transfers openapi.json GET /gateway/v1/token/transfers # Wallet Detail Source: https://docs.asksurf.ai/data-api/wallet/detail openapi.json GET /gateway/v1/wallet/detail # Transaction History Source: https://docs.asksurf.ai/data-api/wallet/history openapi.json GET /gateway/v1/wallet/history # Wallet Labels (Batch) Source: https://docs.asksurf.ai/data-api/wallet/labels-batch openapi.json GET /gateway/v1/wallet/labels/batch # Net Worth History Source: https://docs.asksurf.ai/data-api/wallet/net-worth openapi.json GET /gateway/v1/wallet/net-worth # DeFi Protocol Positions Source: https://docs.asksurf.ai/data-api/wallet/protocols openapi.json GET /gateway/v1/wallet/protocols # Wallet Transfers Source: https://docs.asksurf.ai/data-api/wallet/transfers openapi.json GET /gateway/v1/wallet/transfers # Web Page Fetch Source: https://docs.asksurf.ai/data-api/web/fetch openapi.json GET /gateway/v1/web/fetch # Bridges Source: https://docs.asksurf.ai/data-catalog/bridges Cross-chain bridge volume aggregated daily. **1 tables** in this category. ## Tables | View Name | Database | Source | ORDER BY | | --------------------------- | -------- | ----------------------------- | -------------------------------------------- | | `agent.bridge_volume_daily` | `agent` | `bridges.bridge_volume_daily` | `block_date, project, version, source_chain` | ## Related Tables * `agent.ethereum_chain_daily` * `agent.ethereum_prices_day` ## Sample Queries ### 1. Bridge volume by protocol this week ```sql theme={null} SELECT bridge_name, count() AS transfers, sum(deposit_amount_raw) AS total_raw FROM bridges_ethereum.deposits WHERE block_date >= today() - 7 GROUP BY bridge_name ORDER BY transfers DESC ``` ## Table Schemas ### `agent.bridge_volume_daily` Daily cross-chain bridge volume in USD with directional flow tracking. One row per (block\_date, project, version, source\_chain, destination\_chain). Each row is a directional flow: deposits contribute (ethereum, X) rows, withdrawals contribute (X, ethereum) rows. Covers Across, Polygon, USDT0, Lighter, Mayan, and other bridges with USD pricing from hourly prices. **Engine**: MergeTree | **Partition**: `toYYYYMM(block_date)` | **ORDER BY**: `block_date, project, version, source_chain` | Column | Type | Description | | ------------------- | --------- | ----------------------------------------------------------------------------------- | | `block_date` | `Date` | UTC block date | | `blockchain` | `String` | Blockchain network name | | `project` | `String` | Bridge protocol name (lowercase): across, polygon, arbitrum, usdt0, lighter, mayan. | | `version` | `String` | Bridge protocol version. | | `source_chain` | `String` | Origin chain of the bridged funds. | | `destination_chain` | `String` | Target chain of the bridged funds. | | `volume_usd` | `Float64` | Total USD value bridged. Priced at hourly rate (toStartOfHour). | | `tx_count` | `UInt64` | Number of bridge transactions in this direction on this day. | * Each row is directional — (Ethereum, Arbitrum) is a separate row from (Arbitrum, Ethereum) * For total bridge volume regardless of direction: sum both directions * Filter source\_chain or destination\_chain for chain-specific inflow/outflow analysis * volume\_usd uses hourly price at bridge time — more precise than daily price * Ethereum-centric — only covers bridges with Ethereum as one endpoint * Not all bridge protocols are indexed — newer or smaller bridges may be missing * USD pricing from hourly CoinGecko — same limitations as DEX prices * Mayan bridge uses a separate volume model with different source methodology # Chain Metrics Source: https://docs.asksurf.ai/data-catalog/chain-metrics Daily chain-level aggregates including transaction counts, active addresses, gas usage, and contract deployments. **3 tables** in this category. ## Tables | View Name | Database | Source | ORDER BY | | ---------------------------- | -------- | ------------------------------ | -------- | | `agent.ethereum_chain_daily` | `agent` | `chain_metrics_ethereum.daily` | `—` | | `agent.base_chain_daily` | `agent` | `chain_metrics_base.daily` | `—` | | `agent.arbitrum_chain_daily` | `agent` | `chain_metrics_arbitrum.daily` | `—` | ## Related Tables * `agent.arbitrum_dex_trades` * `agent.arbitrum_tvl_daily` * `agent.base_dex_trades` * `agent.base_tvl_daily` * `agent.ethereum_dex_trades` * `agent.ethereum_staking_daily` * `agent.ethereum_tvl_daily` ## Table Schemas ### `agent.ethereum_chain_daily` Daily chain-level activity metrics in the style of Artemis ez\_metrics. Transaction counts, active addresses (HLL approximate), gas usage, native value transferred, and contract deployments. * active\_senders and active\_receivers use HLL (uniq) — approximately 2% error margin * avg\_gas\_price\_gwei is the mean effective gas price in Gwei — not a median or percentile * total\_native\_transferred is in native units (ETH/BNB), not USD * contract\_deployments counts transactions where receipt\_contract\_address is non-empty * HLL-based active\_senders/receivers are \~2% approximate — not exact unique counts * Does not distinguish EOA vs contract senders * No USD valuation of native transfers — join with prices table manually * L2 gas pricing may not reflect actual user cost (excludes L1 data fees) ### `agent.base_chain_daily` Daily chain-level activity metrics in the style of Artemis ez\_metrics. Transaction counts, active addresses (HLL approximate), gas usage, native value transferred, and contract deployments. * active\_senders and active\_receivers use HLL (uniq) — approximately 2% error margin * Base is an L2 — avg\_gas\_price\_gwei reflects L2 execution gas only, not L1 data costs * total\_native\_transferred is in ETH (Base uses bridged ETH as native token) * contract\_deployments on Base are typically higher than Ethereum mainnet due to lower gas costs * HLL-based active\_senders/receivers are \~2% approximate * L2 gas price does not reflect actual user cost (excludes L1 data posting fees) * No USD valuation of native transfers ### `agent.arbitrum_chain_daily` Daily chain-level activity metrics in the style of Artemis ez\_metrics. Transaction counts, active addresses (HLL approximate), gas usage, native value transferred, and contract deployments. * active\_senders and active\_receivers use HLL (uniq) — approximately 2% error margin * Arbitrum is an L2 — avg\_gas\_price\_gwei reflects L2 execution gas only, not L1 data costs * total\_native\_transferred is in ETH (Arbitrum uses bridged ETH as native token) * HLL-based active\_senders/receivers are \~2% approximate * L2 gas price does not reflect actual user cost (excludes L1 data posting fees) * No USD valuation of native transfers # Curated Analytics Source: https://docs.asksurf.ai/data-catalog/curated-analytics Dashboard-ready pre-computed analytics — whale trades, hot markets, leaderboards, and daily reports. **11 tables** in this category. ## Tables | View Name | Database | Source | ORDER BY | | ------------------------------------ | --------- | ------------------------------------------------------- | --------------------- | | `curated.polymarket_market_ranking` | `curated` | `polymarket_polygon.market_ranking` | `condition_id` | | `curated.polymarket_whale_trades` | `curated` | `polymarket_polygon.whale_trades_enriched` | `—` | | `curated.polymarket_hot_markets` | `curated` | `polymarket_polygon.hot_markets` | `—` | | `curated.polymarket_leaderboard` | `curated` | `polymarket_polygon.leaderboard` | `—` | | `curated.polymarket_market_report` | `curated` | `polymarket_polygon.market_report_daily_v5` | `date, condition_id` | | `curated.kalshi_market_report` | `curated` | `kalshi.market_report_mv` | `date, market_ticker` | | `curated.kalshi_daily_categorized` | `curated` | `kalshi.market_daily_categorized` | `date, market_ticker` | | `curated.prediction_category_daily` | `curated` | `prediction_markets.category_daily` | `—` | | `curated.prediction_matched_markets` | `curated` | `prediction_markets.matched_markets` | `—` | | `curated.prediction_matched_daily` | `curated` | `prediction_markets.matched_daily` | `—` | | `curated.eigenlayer_operator_shares` | `curated` | `eigenlayer_ethereum.operator_shares_cumulative_by_day` | `—` | ## Related Tables * `curated.ethereum_staking_daily` * `curated.ethereum_tvl_daily` * `curated.kalshi_market_details` * `curated.polymarket_market_details` * `curated.polymarket_open_interest_daily` * `curated.polymarket_positions` * `curated.polymarket_trades` * `curated.polymarket_volume_daily` * `curated.prediction_markets_daily` ## Sample Queries ### 1. Daily volume by platform ```sql theme={null} SELECT date, source, sum(notional_volume_usd) AS volume, sum(open_interest_usd) AS oi FROM agent.prediction_markets_daily WHERE date >= today() - 30 GROUP BY date, source ORDER BY date DESC, source ``` ### 2. Daily ETH staked by entity ```sql theme={null} SELECT toDate(block_time) AS day, entity, sum(amount_staked) AS eth_staked FROM staking_ethereum.deposits WHERE block_date >= today() - 30 GROUP BY day, entity ORDER BY day DESC, eth_staked DESC LIMIT 50 ``` ## Table Schemas ### `curated.polymarket_market_ranking` Pre-computed denormalized market ranking table for Polymarket. One row per condition\_id with market metadata (question, status, dates, tags, link), latest volume, OI, and category/subcategory. Rebuilt on each dbt run. Designed for backend ranking queries. **Engine**: MergeTree | **ORDER BY**: `condition_id` | Column | Type | Description | | --------------------- | --------------- | ------------------------------------------- | | `condition_id` | `String` | Market condition identifier. Primary key. | | `event_slug` | `String` | Parent event identifier. | | `question` | `String` | Market question text. | | `active` | `UInt8` | True if market is currently tradeable. | | `closed` | `UInt8` | True if trading has been halted. | | `resolved_at` | `DateTime64(3)` | | | `market_end_date` | `DateTime` | Scheduled market end date. | | `polymarket_link` | `String` | Direct URL to the market on polymarket.com. | | `tags` | `String` | Array of tags. | | `category` | `String` | Paradigm-compatible market category. | | `subcategory` | `String` | Market subcategory. | | `notional_volume_usd` | `Float64` | All-time or latest-date notional volume. | | `open_interest_usd` | `Float64` | Latest OI snapshot. | * One row per condition\_id (outcome\_index=0 deduplication applied) * notional\_volume\_usd and open\_interest\_usd are from the LATEST available date * Has bloom filter indexes on category — efficient for category filtering * active and closed have set indexes — efficient boolean filtering * tags is an array — use hasAny() for tag-based filtering * Point-in-time snapshot — rebuilt on each pipeline run, no historical versions * Volume and OI are from the latest report date, not lifetime totals ### `curated.polymarket_whale_trades` Large Polymarket trades enriched with market metadata, category, wallet age context, and whale tier classification. Includes maker/taker wallet creation date and age in days. Pre-filtered for high-value trades only. * whale\_tier classifies trades by size — filter for specific tiers * Pre-enriched with category, outcome\_label, question — no additional JOINs needed * Includes wallet age context — useful for distinguishing new accounts from veterans * Filter by block\_date for partition pruning * Only includes trades above the whale threshold — small trades excluded * Wallet age context depends on proxy registry coverage ### `curated.polymarket_hot_markets` Most active Polymarket markets by trading activity in the last 7 days. Pre-computed VIEW with trade count, volume, and unique trader count per condition. Enriched with title, category, and subcategory. * This is a VIEW — results are always current (last 7 days from query time) * Ordered by volume\_usd DESC — top markets appear first * Pre-enriched with title, category, subcategory — no additional JOINs needed * Rolling 7-day window only — no historical hot market snapshots * VIEW executes on query — may be slower than materialized tables for repeated access ### `curated.polymarket_leaderboard` All-time Polymarket trader leaderboard with per-address PnL, volume, positions, and win/loss record. Aggregated from user\_positions across all markets. Volume is one-sided deduped shares traded. PnL is cost-basis methodology. * Sort by pnl DESC for most profitable traders, or by volume DESC for most active * positions\_won / (positions\_won + positions\_lost) gives win rate (exclude open) * Volume is one-sided (validated against Polymarket API within 1%) * PnL uses cost-basis accounting (validated within 0.2%) * Uses proxy wallet addresses — no mapping to main wallets or user identities * All-time aggregation only — no time-windowed leaderboards in this table * PnL depends on position resolution — open positions have unrealized PnL not captured here * Model may be disabled (enabled=false) — check availability before relying on it ### `curated.polymarket_market_report` Daily per-condition market report for Polymarket with notional volume and open interest. One row per (condition\_id, date). The primary building block for aggregated volume/OI views and cross-platform comparison. Uses Paradigm-compatible methodology. **Engine**: MergeTree | **Partition**: `toYYYYMM(date)` | **ORDER BY**: `date, condition_id` | Column | Type | Description | | --------------------- | --------- | ---------------------------------------------------------------- | | `date` | `Date` | Report date. | | `condition_id` | `String` | Market condition identifier. | | `notional_volume_usd` | `Float64` | One-sided notional volume in USD for this condition on this day. | | `daily_oi_change_usd` | `Float64` | Daily net change in open interest (USD) | | `open_interest_usd` | `Float64` | Cumulative OI for this condition on this day. | | `status` | `String` | Market status (active, closed, resolved) | * 70M rows — always filter on date * condition\_id + date is the unique grain * notional\_volume\_usd is one-sided (Paradigm methodology) * Use prediction\_markets\_daily for pre-aggregated cross-platform comparison instead of rolling your own * Large table — always partition-prune with date filters * Per-condition, not per-market — a multi-outcome market has multiple condition\_ids ### `curated.kalshi_market_report` Daily per-market Kalshi report with volume, open interest, and trade counts. Materialized view for efficient querying. The Kalshi analog of polymarket\_market\_report. Used as the base for categorized reports and cross-platform comparison. **Engine**: MergeTree | **Partition**: `toYYYYMM(date)` | **ORDER BY**: `date, market_ticker` | Column | Type | Description | | ---------------- | --------------- | ----------------------------------------- | | `date` | `Date` | Report date. | | `event_ticker` | `String` | Event ticker (Kalshi) | | `market_ticker` | `String` | Kalshi market ticker (unique identifier). | | `title` | `String` | Market title | | `event_title` | `String` | Event title | | `event_subtitle` | `String` | | | `daily_volume` | `UInt64` | Daily contract volume | | `total_volume` | `UInt64` | Cumulative total volume | | `open_interest` | `Float64` | End-of-day open interest (contracts) | | `status` | `String` | Market status (active, closed, resolved) | | `payout_type` | `String` | | | `start_time` | `DateTime64(3)` | | | `end_time` | `DateTime64(3)` | | | `close_time` | `DateTime64(3)` | | | `result` | `String` | Market result (if resolved) | | `category` | `String` | Market category | | `subcategory` | `String` | Market subcategory | * 16.8M rows — always filter on date * report\_ticker resolves series via coalesce(events.series\_ticker, prefix decoding) * MVE (parlay) markets have a different structure — series\_ticker from ticker prefix * This is a materialized view (MV) — reads are efficient but may have slight lag * Materialized view — slight update lag compared to base tables * MVE markets may have different volume accounting than regular markets ### `curated.kalshi_daily_categorized` Daily Kalshi volume and OI pre-aggregated by Paradigm-compatible category taxonomy. One row per (date, category, subcategory). Ready for dashboard consumption without additional aggregation. The Kalshi equivalent of the categorized Polymarket report. **Engine**: MergeTree | **Partition**: `toYYYYMM(date)` | **ORDER BY**: `date, market_ticker` | Column | Type | Description | | ------------------- | --------- | -------------------------------------------------------------------- | | `date` | `Date` | Report date. | | `series_ticker` | `String` | | | `event_ticker` | `String` | Event ticker (Kalshi) | | `market_ticker` | `String` | Unique market identifier (Kalshi) | | `title` | `String` | Market title | | `category` | `String` | Paradigm-compatible category (e.g., 'Sports', 'Politics', 'Crypto'). | | `subcategory` | `String` | Finer subdivision (e.g., 'NFL', 'NBA', 'Presidential'). | | `daily_volume_usd` | `UInt64` | | | `open_interest_usd` | `Float64` | Cumulative open interest (USD) | | `status` | `String` | Market status (active, closed, resolved) | * Already aggregated by category — efficient for dashboard queries * category and subcategory follow Paradigm taxonomy for cross-platform consistency * Compare directly with Polymarket categorized reports using same taxonomy * Category assignment quality depends on upstream categorization model * Some markets may be categorized as 'Exotics' or empty — especially MVE markets ### `curated.prediction_category_daily` Cross-platform daily volume, OI, and market count by category. Extends prediction\_markets\_daily with count(DISTINCT market) per category. One row per (date, source, category, subcategory). Used by the prediction markets dashboard for category breakdowns and time series. * market\_count gives the number of distinct markets active in each category per day * source is 'Kalshi' or 'Polymarket' * volume\_usd and open\_interest\_usd are aggregated to category level * Only includes dates where both platforms have data * Same date restriction as prediction\_markets\_daily — both platforms must have data * Category 'UNKNOWN' appears for uncategorized markets ### `curated.prediction_matched_markets` Same-event market pairs across Polymarket and Kalshi, exposed as a curated dashboard-ready view. Each row is a one-to-one (condition\_id, market\_ticker) pair with match confidence, type, and live volume/OI from both platforms. * Pre-enriched with metadata from both platforms — no additional JOINs needed for display * match\_type 'exact' = same question, 'related' = same event different angle * confidence 75-100 — filter for 90+ for highest-quality matches * Curated view of agent.prediction\_markets\_matched\_markets — same coverage limitations * Not all markets are matched — only those with cross-platform equivalents ### `curated.prediction_matched_daily` Daily cross-platform volume and OI comparison for matched Polymarket-Kalshi market pairs. Dashboard-ready curated view with side-by-side daily metrics. One row per (condition\_id, market\_ticker, date). * Filter on date for partition pruning * Compare polymarket\_volume\_usd vs kalshi\_volume\_usd for relative platform activity * JOIN with prediction\_matched\_markets for match quality metadata * Only matched markets — unmatched activity excluded * Date coverage limited to overlap period with data on both platforms ### `curated.eigenlayer_operator_shares` Daily cumulative operator shares for EigenLayer restaking. One row per (operator, strategy, date) with a running sum of delegated shares. Gap-filled daily from 2024-02-01 onward using a date series CROSS JOIN. Useful for tracking operator growth, strategy popularity, and restaking trends. **Engine**: MergeTree | Column | Type | Description | | ------------------------- | -------- | ------------------------------------------------------------------- | | `operator` | `String` | EigenLayer operator address. | | `strategy` | `String` | EigenLayer strategy contract address. | | `date` | `Date` | Calendar date (gap-filled daily). | | `cumulative_daily_shares` | `Int128` | Running sum of shares delegated to this operator for this strategy. | * cumulative\_daily\_shares is a running sum — for daily delta, use window functions: current - lagInFrame() * operator is the node operator address — not the delegator address * strategy is the EigenLayer strategy contract address — join with strategy metadata for names * Gap-filled: every (operator, strategy) pair has a row for every day since 2024-02-01 * Shares are in raw units — conversion to USD requires strategy-specific pricing logic * Operator identity (name) is not in this table — requires external mapping * Data starts from 2024-02-01 — pre-mainnet activity not included * Table materialization means slight delay from latest on-chain state # DEX Trades Source: https://docs.asksurf.ai/data-catalog/dex-trades Enriched swap events across 6 chains with token symbols, USD amounts, and protocol attribution. **6 tables** in this category. ## Tables | View Name | Database | Source | ORDER BY | | --------------------------- | -------- | --------------------- | -------------------------------- | | `agent.ethereum_dex_trades` | `agent` | `dex_ethereum.trades` | `block_time, tx_hash, evt_index` | | `agent.base_dex_trades` | `agent` | `dex_base.trades` | `block_time, tx_hash, evt_index` | | `agent.arbitrum_dex_trades` | `agent` | `dex_arbitrum.trades` | `block_time, tx_hash, evt_index` | | `agent.bsc_dex_trades` | `agent` | `dex_bnb.trades` | `block_time, tx_hash, evt_index` | | `agent.tron_dex_trades` | `agent` | `dex_tron.trades` | `block_time, tx_hash, evt_index` | | `agent.hyperevm_dex_trades` | `agent` | `dex_hyperevm.trades` | `block_time, tx_hash, evt_index` | ## Related Tables * `agent.arbitrum_prices_day` * `agent.base_prices_day` * `agent.ethereum_erc20` * `agent.ethereum_fees_daily` * `agent.ethereum_prices_day` * `agent.hyperliquid_market_data` * `agent.hyperliquid_perp_meta` ## Sample Queries ### 1. Top 10 DEX protocols by volume today ```sql theme={null} SELECT project, sum(amount_usd) AS volume_usd FROM agent.ethereum_dex_trades WHERE block_date = today() - 1 GROUP BY project ORDER BY volume_usd DESC LIMIT 10 ``` ### 2. Uniswap V3 WETH/USDC trades in the last 24 hours ```sql theme={null} SELECT block_time, token_bought_symbol, token_sold_symbol, token_bought_amount, token_sold_amount, amount_usd FROM agent.ethereum_dex_trades WHERE project = 'uniswap' AND version = '3' AND token_pair = 'USDC-WETH' AND block_date >= today() - 1 ORDER BY block_time DESC LIMIT 20 ``` ## Table Schemas ### `agent.ethereum_dex_trades` Enriched DEX swap events with token symbols, decimals, USD amounts, and protocol attribution. One row per swap event. Combines decoded events from all supported DEX protocols on this chain. **Engine**: MergeTree | **Partition**: `toYYYYMM(block_date)` | **ORDER BY**: `block_time, tx_hash, evt_index` | Column | Type | Description | | -------------------------- | ------------------- | ------------------------------------------------------------------------------------------------------ | | `blockchain` | `String` | Blockchain network name | | `project` | `String` | Protocol name (lowercase): uniswap, sushiswap, curve, pancakeswap, aerodrome, etc. | | `version` | `String` | Protocol version string: '1', '2', '3', 'v3', 'slipstream', etc. | | `block_month` | `Date` | UTC block month (partition key) | | `block_date` | `Date` | Partition key. Always filter on this column for performance. | | `block_time` | `DateTime64(3)` | UTC block timestamp | | `block_number` | `UInt64` | Block number | | `token_bought_symbol` | `Nullable(String)` | Symbol of token received | | `token_sold_symbol` | `Nullable(String)` | Symbol of token sent | | `token_pair` | `String` | Alphabetically sorted pair string (e.g., 'ETH-USDC'). Useful for GROUP BY. | | `token_bought_amount` | `Float64` | Human-readable amount (divided by token decimals). Null if decimals unknown. | | `token_sold_amount` | `Nullable(Float64)` | Human-readable amount (divided by token decimals). Null if decimals unknown. | | `token_bought_amount_raw` | `UInt256` | Raw token received amount (pre-decimal) | | `token_sold_amount_raw` | `Nullable(UInt256)` | Raw token sent amount (pre-decimal) | | `amount_usd` | `Nullable(Float64)` | One-sided USD value of token\_sold. Prices from CoinGecko hourly + DEX VWAP. Null for unpriced tokens. | | `token_bought_address` | `Nullable(String)` | Bought token contract address | | `token_sold_address` | `Nullable(String)` | Sold token contract address | | `taker` | `String` | EOA that initiated the swap transaction, not the router/aggregator contract | | `maker` | `Nullable(String)` | Liquidity pool address that provided the other side of the trade | | `project_contract_address` | `String` | Pool or router contract address | | `tx_hash` | `String` | Transaction hash | | `tx_from` | `String` | Transaction sender (EOA) | | `tx_to` | `String` | Transaction recipient | | `evt_index` | `UInt32` | Event log index in transaction | * amount\_usd is one-sided (token\_sold value) following DefiLlama methodology — multiply by 2 for two-sided * Filter by project + version for protocol-specific analysis (e.g., project='uniswap', version='3') * taker is the EOA that initiated the swap, not the router contract * token\_pair is alphabetically sorted (ETH-USDC not USDC-ETH) for consistent grouping * Use block\_date for daily aggregations — it is the partition key * No aggregator attribution — a swap routed through 1inch still shows as the underlying DEX * USD prices from CoinGecko hourly — illiquid or brand-new tokens may have null amount\_usd * Does not include limit orders, RFQ fills, or off-chain matching ### `agent.base_dex_trades` Enriched DEX swap events with token symbols, decimals, USD amounts, and protocol attribution. One row per swap event. Combines decoded events from all supported DEX protocols on this chain. **Engine**: MergeTree | **Partition**: `toYYYYMM(block_date)` | **ORDER BY**: `block_time, tx_hash, evt_index` | Column | Type | Description | | -------------------------- | ------------------- | ------------------------------------------------------------------------------------------------------ | | `blockchain` | `String` | Blockchain network name | | `project` | `String` | Protocol name (lowercase): uniswap, sushiswap, curve, pancakeswap, aerodrome, etc. | | `version` | `String` | Protocol version string: '1', '2', '3', 'v3', 'slipstream', etc. | | `block_month` | `Date` | UTC block month (partition key) | | `block_date` | `Date` | Partition key. Always filter on this column for performance. | | `block_time` | `DateTime64(3)` | UTC block timestamp | | `block_number` | `UInt64` | Block number | | `token_bought_symbol` | `Nullable(String)` | Symbol of token received | | `token_sold_symbol` | `Nullable(String)` | Symbol of token sent | | `token_pair` | `String` | Alphabetically sorted pair string (e.g., 'ETH-USDC'). Useful for GROUP BY. | | `token_bought_amount` | `Float64` | Human-readable amount (divided by token decimals). Null if decimals unknown. | | `token_sold_amount` | `Float64` | Human-readable amount (divided by token decimals). Null if decimals unknown. | | `token_bought_amount_raw` | `UInt256` | Raw token received amount (pre-decimal) | | `token_sold_amount_raw` | `UInt256` | Raw token sent amount (pre-decimal) | | `amount_usd` | `Nullable(Float64)` | One-sided USD value of token\_sold. Prices from CoinGecko hourly + DEX VWAP. Null for unpriced tokens. | | `token_bought_address` | `String` | Bought token contract address | | `token_sold_address` | `String` | Sold token contract address | | `taker` | `String` | EOA that initiated the swap transaction, not the router/aggregator contract | | `maker` | `Nullable(String)` | Liquidity pool address that provided the other side of the trade | | `project_contract_address` | `String` | Pool or router contract address | | `tx_hash` | `String` | Transaction hash | | `tx_from` | `String` | Transaction sender (EOA) | | `tx_to` | `String` | Transaction recipient | | `evt_index` | `UInt32` | Event log index in transaction | * amount\_usd is one-sided (token\_sold value) following DefiLlama methodology — multiply by 2 for two-sided * Filter by project + version for protocol-specific analysis (e.g., project='uniswap', version='3') * taker is the EOA that initiated the swap, not the router contract * token\_pair is alphabetically sorted (ETH-USDC not USDC-ETH) for consistent grouping * Use block\_date for daily aggregations — it is the partition key * No aggregator attribution — a swap routed through 1inch still shows as the underlying DEX * USD prices from CoinGecko hourly — illiquid or brand-new tokens may have null amount\_usd * Does not include limit orders, RFQ fills, or off-chain matching ### `agent.arbitrum_dex_trades` Enriched DEX swap events with token symbols, decimals, USD amounts, and protocol attribution. One row per swap event. Combines decoded events from all supported DEX protocols on this chain. **Engine**: MergeTree | **Partition**: `toYYYYMM(block_date)` | **ORDER BY**: `block_time, tx_hash, evt_index` | Column | Type | Description | | -------------------------- | ------------------- | ------------------------------------------------------------------------------------------------------ | | `blockchain` | `String` | Blockchain network name | | `project` | `String` | Protocol name (lowercase): uniswap, sushiswap, curve, pancakeswap, aerodrome, etc. | | `version` | `String` | Protocol version string: '1', '2', '3', 'v3', 'slipstream', etc. | | `block_month` | `Date` | UTC block month (partition key) | | `block_date` | `Date` | Partition key. Always filter on this column for performance. | | `block_time` | `DateTime64(3)` | UTC block timestamp | | `block_number` | `UInt64` | Block number | | `token_bought_symbol` | `Nullable(String)` | Symbol of token received | | `token_sold_symbol` | `Nullable(String)` | Symbol of token sent | | `token_pair` | `String` | Alphabetically sorted pair string (e.g., 'ETH-USDC'). Useful for GROUP BY. | | `token_bought_amount` | `Float64` | Human-readable amount (divided by token decimals). Null if decimals unknown. | | `token_sold_amount` | `Float64` | Human-readable amount (divided by token decimals). Null if decimals unknown. | | `token_bought_amount_raw` | `UInt256` | Raw token received amount (pre-decimal) | | `token_sold_amount_raw` | `UInt256` | Raw token sent amount (pre-decimal) | | `amount_usd` | `Nullable(Float64)` | One-sided USD value of token\_sold. Prices from CoinGecko hourly + DEX VWAP. Null for unpriced tokens. | | `token_bought_address` | `String` | Bought token contract address | | `token_sold_address` | `String` | Sold token contract address | | `taker` | `String` | EOA that initiated the swap transaction, not the router/aggregator contract | | `maker` | `Nullable(String)` | Liquidity pool address that provided the other side of the trade | | `project_contract_address` | `String` | Pool or router contract address | | `tx_hash` | `String` | Transaction hash | | `tx_from` | `String` | Transaction sender (EOA) | | `tx_to` | `String` | Transaction recipient | | `evt_index` | `UInt64` | Event log index in transaction | * amount\_usd is one-sided (token\_sold value) following DefiLlama methodology — multiply by 2 for two-sided * Filter by project + version for protocol-specific analysis (e.g., project='uniswap', version='3') * taker is the EOA that initiated the swap, not the router contract * token\_pair is alphabetically sorted (ETH-USDC not USDC-ETH) for consistent grouping * Use block\_date for daily aggregations — it is the partition key * No aggregator attribution — a swap routed through 1inch still shows as the underlying DEX * USD prices from CoinGecko hourly — illiquid or brand-new tokens may have null amount\_usd * Does not include limit orders, RFQ fills, or off-chain matching ### `agent.bsc_dex_trades` Enriched DEX swap events with token symbols, decimals, USD amounts, and protocol attribution. One row per swap event. Combines decoded events from all supported DEX protocols on this chain. **Engine**: MergeTree | **Partition**: `toYYYYMM(block_date)` | **ORDER BY**: `block_time, tx_hash, evt_index` | Column | Type | Description | | -------------------------- | ------------------- | ------------------------------------------------------------------------------------------------------ | | `blockchain` | `String` | Blockchain network name | | `project` | `String` | Protocol name (lowercase): uniswap, sushiswap, curve, pancakeswap, aerodrome, etc. | | `version` | `String` | Protocol version string: '1', '2', '3', 'v3', 'slipstream', etc. | | `block_month` | `Date` | UTC block month (partition key) | | `block_date` | `Date` | Partition key. Always filter on this column for performance. | | `block_time` | `DateTime` | UTC block timestamp | | `block_number` | `UInt64` | Block number | | `token_bought_symbol` | `Nullable(String)` | Symbol of token received | | `token_sold_symbol` | `Nullable(String)` | Symbol of token sent | | `token_pair` | `String` | Alphabetically sorted pair string (e.g., 'ETH-USDC'). Useful for GROUP BY. | | `token_bought_amount` | `Float64` | Human-readable amount (divided by token decimals). Null if decimals unknown. | | `token_sold_amount` | `Float64` | Human-readable amount (divided by token decimals). Null if decimals unknown. | | `token_bought_amount_raw` | `UInt256` | Raw token received amount (pre-decimal) | | `token_sold_amount_raw` | `UInt256` | Raw token sent amount (pre-decimal) | | `amount_usd` | `Nullable(Float64)` | One-sided USD value of token\_sold. Prices from CoinGecko hourly + DEX VWAP. Null for unpriced tokens. | | `token_bought_address` | `String` | Bought token contract address | | `token_sold_address` | `String` | Sold token contract address | | `taker` | `String` | EOA that initiated the swap transaction, not the router/aggregator contract | | `maker` | `String` | Liquidity pool address that provided the other side of the trade | | `project_contract_address` | `String` | Pool or router contract address | | `tx_hash` | `String` | Transaction hash | | `tx_from` | `String` | Transaction sender (EOA) | | `tx_to` | `String` | Transaction recipient | | `evt_index` | `UInt64` | Event log index in transaction | * amount\_usd is one-sided (token\_sold value) following DefiLlama methodology — multiply by 2 for two-sided * This is the LARGEST dex\_trades table (\~4B rows) — always use tight block\_date filters * PancakeSwap dominates BSC DEX volume — filter by project='pancakeswap' for protocol-specific analysis * taker is the EOA that initiated the swap, not the router contract * No aggregator attribution — a swap routed through 1inch still shows as the underlying DEX * USD prices from CoinGecko hourly — illiquid or brand-new tokens may have null amount\_usd * Does not include limit orders, RFQ fills, or off-chain matching ### `agent.tron_dex_trades` Enriched DEX swap events with token symbols, decimals, USD amounts, and protocol attribution. One row per swap event. Combines decoded events from all supported DEX protocols on this chain. **Engine**: MergeTree | **Partition**: `toYYYYMM(block_date)` | **ORDER BY**: `block_time, tx_hash, evt_index` | Column | Type | Description | | -------------------------- | ------------------- | ------------------------------------------------------------------------------------------------------ | | `blockchain` | `String` | Blockchain network name | | `project` | `String` | Protocol name (lowercase): uniswap, sushiswap, curve, pancakeswap, aerodrome, etc. | | `version` | `String` | Protocol version string: '1', '2', '3', 'v3', 'slipstream', etc. | | `block_month` | `Date` | UTC block month (partition key) | | `block_date` | `Date` | Partition key. Always filter on this column for performance. | | `block_time` | `DateTime64(3)` | UTC block timestamp | | `block_number` | `UInt64` | Block number | | `token_bought_symbol` | `Nullable(String)` | Symbol of token received | | `token_sold_symbol` | `Nullable(String)` | Symbol of token sent | | `token_pair` | `String` | Alphabetically sorted pair string (e.g., 'ETH-USDC'). Useful for GROUP BY. | | `token_bought_amount` | `Float64` | Human-readable amount (divided by token decimals). Null if decimals unknown. | | `token_sold_amount` | `Float64` | Human-readable amount (divided by token decimals). Null if decimals unknown. | | `token_bought_amount_raw` | `UInt256` | Raw token received amount (pre-decimal) | | `token_sold_amount_raw` | `UInt256` | Raw token sent amount (pre-decimal) | | `amount_usd` | `Nullable(Float64)` | One-sided USD value of token\_sold. Prices from CoinGecko hourly + DEX VWAP. Null for unpriced tokens. | | `token_bought_address` | `String` | Bought token contract address | | `token_sold_address` | `String` | Sold token contract address | | `taker` | `String` | EOA that initiated the swap transaction, not the router/aggregator contract | | `maker` | `String` | Liquidity pool address that provided the other side of the trade | | `project_contract_address` | `String` | Pool or router contract address | | `tx_hash` | `String` | Transaction hash | | `tx_from` | `String` | Transaction sender (EOA) | | `tx_to` | `String` | Transaction recipient | | `evt_index` | `UInt32` | Event log index in transaction | * amount\_usd is one-sided (token\_sold value) following DefiLlama methodology * Tron addresses use base58 format (T...) not hex — keep this in mind for address filters * SunSwap dominates Tron DEX volume * No aggregator attribution — a swap routed through 1inch still shows as the underlying DEX * USD prices from CoinGecko hourly — illiquid or brand-new tokens may have null amount\_usd * Does not include limit orders, RFQ fills, or off-chain matching ### `agent.hyperevm_dex_trades` Enriched DEX swap events with token symbols, decimals, USD amounts, and protocol attribution. One row per swap event. Combines decoded events from all supported DEX protocols on this chain. **Engine**: MergeTree | **Partition**: `toYYYYMM(block_date)` | **ORDER BY**: `block_time, tx_hash, evt_index` | Column | Type | Description | | -------------------------- | ------------------- | ------------------------------------------------------------------------------------------------------ | | `blockchain` | `String` | Blockchain network name | | `project` | `String` | Protocol name (lowercase): uniswap, sushiswap, curve, pancakeswap, aerodrome, etc. | | `version` | `String` | Protocol version string: '1', '2', '3', 'v3', 'slipstream', etc. | | `block_month` | `Date` | UTC block month (partition key) | | `block_date` | `Date` | Partition key. Always filter on this column for performance. | | `block_time` | `DateTime64(3)` | UTC block timestamp | | `block_number` | `UInt64` | Block number | | `token_bought_symbol` | `String` | Symbol of token received | | `token_sold_symbol` | `String` | Symbol of token sent | | `token_pair` | `String` | Alphabetically sorted pair string (e.g., 'ETH-USDC'). Useful for GROUP BY. | | `token_bought_amount` | `Float64` | Human-readable amount (divided by token decimals). Null if decimals unknown. | | `token_sold_amount` | `Float64` | Human-readable amount (divided by token decimals). Null if decimals unknown. | | `token_bought_amount_raw` | `UInt256` | Raw token received amount (pre-decimal) | | `token_sold_amount_raw` | `UInt256` | Raw token sent amount (pre-decimal) | | `amount_usd` | `Nullable(Float64)` | One-sided USD value of token\_sold. Prices from CoinGecko hourly + DEX VWAP. Null for unpriced tokens. | | `token_bought_address` | `String` | Bought token contract address | | `token_sold_address` | `String` | Sold token contract address | | `taker` | `String` | EOA that initiated the swap transaction, not the router/aggregator contract | | `maker` | `Nullable(String)` | Liquidity pool address that provided the other side of the trade | | `project_contract_address` | `String` | Pool or router contract address | | `tx_hash` | `String` | Transaction hash | | `tx_from` | `String` | Transaction sender (EOA) | | `tx_to` | `String` | Transaction recipient | | `evt_index` | `UInt32` | Event log index in transaction | * amount\_usd is one-sided (token\_sold value) following DefiLlama methodology * HyperEVM is the EVM-compatible layer on Hyperliquid — distinct from perp trading data * Newer chain — data starts from HyperEVM launch, coverage may be thinner than Ethereum * No aggregator attribution — a swap routed through 1inch still shows as the underlying DEX * USD prices from CoinGecko hourly — illiquid or brand-new tokens may have null amount\_usd * Does not include limit orders, RFQ fills, or off-chain matching # Hyperliquid Source: https://docs.asksurf.ai/data-catalog/hyperliquid Perpetual futures market data, funding rates, and contract metadata from Hyperliquid L1. **3 tables** in this category. ## Tables | View Name | Database | Source | ORDER BY | | --------------------------------- | -------- | --------------------------- | --------------------- | | `agent.hyperliquid_market_data` | `agent` | `hyperliquid.market_data` | `coin, snapshot_time` | | `agent.hyperliquid_funding_rates` | `agent` | `hyperliquid.funding_rates` | `coin, time` | | `agent.hyperliquid_perp_meta` | `agent` | `hyperliquid.perp_meta` | `coin` | ## Related Tables * `agent.hyperevm_dex_trades` ## Sample Queries ### 1. Get recent Transfer events for USDC ```sql theme={null} SELECT * FROM ethereum.event_logs WHERE topics[1] = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef' AND address = '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' ORDER BY block_number DESC LIMIT 10 ``` ### 2. Count transactions per day for the last week ```sql theme={null} SELECT block_date, count() AS tx_count FROM ethereum.transactions WHERE block_date >= today() - 7 GROUP BY block_date ORDER BY block_date ``` ## Table Schemas ### `agent.hyperliquid_market_data` Hourly perpetual futures market snapshots from Hyperliquid Info API. Includes funding rates, open interest, prices (oracle, mark, mid), 24h volume, and premium for all listed perpetual contracts. ReplacingMergeTree — use FINAL. **Engine**: ReplacingMergeTree | **Partition**: `toYYYYMM(snapshot_date)` | **ORDER BY**: `coin, snapshot_time` | Column | Type | Description | | --------------- | ------------------- | --------------------------------------------------------------------------- | | `snapshot_time` | `DateTime64(3)` | Hourly snapshot timestamp (DateTime64). | | `coin` | `String` | Perpetual contract ticker (e.g., 'BTC', 'ETH', 'SOL'). Links to perp\_meta. | | `funding` | `Float64` | Current predicted funding rate (per-hour). Positive = longs pay shorts. | | `open_interest` | `Float64` | Total open interest in contract units (not USD). | | `prev_day_px` | `Float64` | Previous day's closing price. | | `day_ntl_vlm` | `Float64` | 24-hour notional volume in USD. | | `premium` | `Nullable(Float64)` | Basis premium (mark - oracle). Nullable. | | `oracle_px` | `Float64` | Oracle price (external reference, typically Pyth/Chainlink). | | `mark_px` | `Float64` | Mark price (used for margin and liquidation calculations). | | `mid_px` | `Nullable(Float64)` | Mid price of the order book. Nullable. | | `impact_bid_px` | `Nullable(Float64)` | Price for a standard-size market sell. Nullable — indicates depth. | | `impact_ask_px` | `Nullable(Float64)` | Price for a standard-size market buy. Nullable — indicates depth. | | `snapshot_date` | `Date` | Date of the snapshot (partition key). | * Use FINAL when querying — this is a ReplacingMergeTree table * snapshot\_time is hourly — one snapshot per (coin, hour) * day\_ntl\_vlm is 24h notional volume in USD at snapshot time * funding is the current predicted funding rate (annualize by multiplying by 8760) * open\_interest is in contract units, not USD — multiply by mark\_px for USD OI * Hourly snapshots only — no tick-level or trade-level data * ReplacingMergeTree — always use FINAL for consistent reads * OI is in contract units, not USD — requires multiplication by price * Not all fields are always populated (mid\_px, impact\_bid/ask\_px can be null) ### `agent.hyperliquid_funding_rates` Historical funding rate settlements for Hyperliquid perpetual contracts. Every 1-hour funding event is recorded with the settlement rate and premium. ReplacingMergeTree — use FINAL. **Engine**: ReplacingMergeTree | **Partition**: `toYYYYMM(funding_date)` | **ORDER BY**: `coin, time` | Column | Type | Description | | -------------- | --------------- | -------------------------------------------------------------------- | | `time` | `DateTime64(3)` | Settlement timestamp (DateTime64). | | `coin` | `String` | Perpetual contract ticker (e.g., 'BTC', 'ETH'). Links to perp\_meta. | | `funding_rate` | `Float64` | Settlement funding rate. Positive = longs pay shorts. | | `premium` | `Float64` | Mark-to-oracle premium at settlement time. | | `funding_date` | `Date` | Date of the funding settlement (partition key). | * Use FINAL when querying — ReplacingMergeTree table * funding\_rate is per-settlement-period (hourly). Annualize: rate \* 8760 * premium tracks the basis between mark and oracle price at settlement * For average daily funding: avg(funding\_rate) grouped by funding\_date and coin * ReplacingMergeTree — use FINAL for deduplication * Funding rates are per-hour settlements — not continuous * Historical backfill depth depends on when the pipeline was started ### `agent.hyperliquid_perp_meta` Perpetual contract metadata for all listed Hyperliquid perps. Small dimension table with coin name, size decimals, and maximum leverage. Updated on each market data ingestion run. **Engine**: ReplacingMergeTree | **ORDER BY**: `coin` | Column | Type | Description | | -------------- | --------------- | ------------------------------------------------------------------- | | `coin` | `String` | Perpetual contract ticker (e.g., 'BTC', 'ETH', 'SOL'). Primary key. | | `sz_decimals` | `UInt8` | Number of decimal places for position/order sizing. | | `max_leverage` | `UInt16` | Maximum leverage allowed for this contract. | | `updated_at` | `DateTime64(3)` | Last metadata refresh timestamp. | * Small table (\~229 rows) — safe to SELECT \* or use in subqueries without filtering * JOIN with market\_data or funding\_rates ON coin for enrichment * sz\_decimals determines the minimum trade size increment for each contract * Only covers perpetual contracts — no spot or options metadata * Max leverage may change over time — only current value is stored # Lending & Staking Source: https://docs.asksurf.ai/data-catalog/lending-staking Protocol-level daily activity aggregates for lending and staking protocols. **2 tables** in this category. ## Tables | View Name | Database | Source | ORDER BY | | ------------------------------ | -------- | ------------------------ | -------- | | `agent.ethereum_lending_daily` | `agent` | `lending_ethereum.daily` | `—` | | `agent.ethereum_staking_daily` | `agent` | `staking_ethereum.daily` | `—` | ## Related Tables * `agent.ethereum_fees_daily` * `agent.ethereum_prices_day` * `agent.ethereum_tvl_daily` * `agent.ethereum_yields_daily` ## Table Schemas ### `agent.ethereum_lending_daily` Protocol-level daily lending activity metrics aligned with DefiLlama format. One row per (project, version, block\_date). Covers deposits, withdrawals, borrows, repayments, and liquidations with USD volumes and participant counts. Sources from 15+ lending protocols (Aave v1/v2/v3, Compound, Morpho, Spark, etc.). * deposit\_volume\_usd and borrow\_volume\_usd are daily FLOW (activity), not outstanding STOCK * For net deposits: deposit\_volume\_usd - withdraw\_volume\_usd * liquidation\_volume\_usd combines supply-side + borrow-side liquidation amounts * active\_depositors and active\_borrowers are daily unique counts (not cumulative) * Cross-reference with tvl\_daily for utilization analysis * Activity metrics only — for outstanding balances, use TVL tables * USD pricing via CoinGecko — same coverage gaps as other USD-denominated tables * Not all lending protocols are covered — new or niche protocols may be missing ### `agent.ethereum_staking_daily` Ethereum beacon chain staking flows by entity, aggregated daily. One row per (entity, entity\_category, block\_date). Tracks deposits, withdrawals (full + partial), net flow in both ETH and USD. Entity attribution maps validators to staking providers (Lido, Coinbase, Rocket Pool, etc.). * entity is the staking provider name (e.g., 'Lido', 'Coinbase', 'Rocket Pool') * entity\_category groups providers (e.g., 'liquid\_staking', 'cex', 'solo', 'staking\_pool') * net\_flow\_eth = deposits\_eth - withdrawals\_eth (positive = net staking inflow) * USD values use WETH price from CoinGecko — null on days with missing ETH price * Entity attribution is best-effort — some validators are unattributed ('unknown') * Does not include consensus rewards, only deposit/withdrawal flows * Partial withdrawals (skimming) and full withdrawals are combined in withdrawals\_eth # Data Catalog Source: https://docs.asksurf.ai/data-catalog/overview 58 analyst-ready ClickHouse tables for crypto data analysis > **58 tables** across 11 categories, available via a readonly ClickHouse account. The Surf Data Catalog documents all tables available to agents and analysts. Tables are organized into categories and exposed as ClickHouse views in the `agent` and `curated` databases. ## Connection | Setting | Value | | ---------------------- | ------------------------------------------------------ | | **Protocol** | ClickHouse HTTP interface (port 8443, TLS) | | **User** | `agent` (readonly) | | **Databases** | `agent` (enriched tables), `curated` (analytics views) | | **Max execution time** | 120s | | **Max memory** | 16GB | | **Max result rows** | 1M | ## Quick Start ```sql theme={null} -- Top DEX protocols by volume yesterday SELECT project, sum(amount_usd) AS volume_usd FROM agent.ethereum_dex_trades WHERE block_date = today() - 1 GROUP BY project ORDER BY volume_usd DESC LIMIT 10 ``` Always filter on `block_date` first — it is the partition key for most tables and enables ClickHouse to skip entire partitions. ## Categories | Category | Tables | Description | | ------------------------------------------------------ | ------ | -------------------------------------------------------------------------------------------------------------------------- | | [DEX Trades](/data-catalog/dex-trades) | 6 | Enriched swap events across 6 chains with token symbols, USD amounts, and protocol attribution. | | [Prices](/data-catalog/prices) | 3 | Daily token prices combining CoinGecko data and DEX VWAP calculations. | | [Token Metadata](/data-catalog/token-metadata) | 1 | ERC-20 contract registry mapping addresses to symbols, names, and decimals. | | [Transfers](/data-catalog/transfers) | 5 | ERC-20 and native token transfers enriched with symbols and USD pricing. | | [TVL / Fees / Yields](/data-catalog/tvl-fees-yields) | 6 | Protocol-level daily aggregates for total value locked, fee revenue, and yield rates. | | [Lending & Staking](/data-catalog/lending-staking) | 2 | Protocol-level daily activity aggregates for lending and staking protocols. | | [Bridges](/data-catalog/bridges) | 1 | Cross-chain bridge volume aggregated daily. | | [Prediction Markets](/data-catalog/prediction-markets) | 17 | Polymarket, Kalshi, and cross-platform prediction market data — trades, market details, prices, volume, and open interest. | | [Curated Analytics](/data-catalog/curated-analytics) | 11 | Dashboard-ready pre-computed analytics — whale trades, hot markets, leaderboards, and daily reports. | | [Hyperliquid](/data-catalog/hyperliquid) | 3 | Perpetual futures market data, funding rates, and contract metadata from Hyperliquid L1. | | [Chain Metrics](/data-catalog/chain-metrics) | 3 | Daily chain-level aggregates including transaction counts, active addresses, gas usage, and contract deployments. | ## Query Best Practices 1. Always filter on block\_date — partition pruning is the #1 performance lever 2. Use LIMIT liberally during exploration; remove for final aggregation 3. Pre-filter in CTEs before JOINing — ClickHouse puts RIGHT side into hash table 4. Use IN (SELECT ...) instead of JOIN when you only need existence checks 5. Avoid SELECT \* on billion-row tables — project only needed columns 6. For ReplacingMergeTree tables, always use FINAL to get deduplicated rows 7. Date range first, then entity filters — this matches partition layout 8. Use toStartOfWeek/toStartOfMonth for time-series rollups, not GROUP BY toString(block\_date) 9. When counting unique addresses, uniq() is faster than count(DISTINCT) and equally accurate 10. For cross-table analysis, filter each table independently in CTEs before joining 11. Handle NULLs explicitly — use ifNull(col, default) or coalesce(). ClickHouse 3-valued logic silently drops NULL rows in WHERE filters. 12. FINAL syntax: FROM table\_name alias FINAL (not FROM table\_name FINAL alias). Place FINAL after the alias. ## Entity Linking Common join patterns across tables: * `token_address -> symbol: JOIN agent.ethereum_erc20 ON contract_address` * `condition_id -> market_question: JOIN agent.polymarket_market_details ON condition_id` * `market_ticker -> category: Use curated.kalshi_daily_categorized (pre-joined)` * `coin -> max_leverage: JOIN agent.hyperliquid_perp_meta ON coin` * `project + version -> TVL: JOIN agent.ethereum_tvl_daily ON (project, version, block_date)` ## Data Freshness | Pipeline | Schedule | Typical Lag | | ----------------- | -------------- | ----------- | | Ethereum raw (BQ) | 12:00 UTC | \~1 day | | Base raw (cryo) | Sensor (6h) | \~6 hours | | Arbitrum raw (BQ) | 12:30 UTC | \~1 day | | Polygon raw (BQ) | Every 30 min | \~1 hour | | TRON raw (BQ) | 13:30 UTC | \~1 day | | Bitcoin raw (BQ) | 14:00 UTC | \~1 day | | HyperEVM (S3) | 13:00 UTC | \~1 day | | CoinGecko prices | Hourly | \~1 hour | | RPC snapshots | Daily | \~1 day | | Kalshi API | Every 6h | \~6 hours | | Polymarket (BQ) | 03:00 UTC | \~1 day | | dbt models | Post-ingestion | +30 min | Check freshness for any table: ```sql theme={null} SELECT max(block_date) FROM agent. ``` # Prediction Markets Source: https://docs.asksurf.ai/data-catalog/prediction-markets Polymarket, Kalshi, and cross-platform prediction market data — trades, market details, prices, volume, and open interest. **17 tables** in this category. ## Tables | View Name | Database | Source | ORDER BY | | ------------------------------------------ | -------- | ----------------------------------------------- | -------------------------------- | | `agent.polymarket_trades` | `agent` | `polymarket_polygon.market_trades` | `block_time, tx_hash, evt_index` | | `agent.polymarket_market_details` | `agent` | `polymarket_polygon.market_details` | `condition_id, token_id` | | `agent.polymarket_events` | `agent` | `polymarket_polygon.events` | `—` | | `agent.polymarket_prices_daily` | `agent` | `polymarket_polygon.market_prices_daily` | `—` | | `agent.polymarket_prices_hourly` | `agent` | `polymarket_polygon.market_prices_hourly` | `—` | | `agent.polymarket_prices_latest` | `agent` | `polymarket_polygon.market_prices_latest` | `token_id` | | `agent.polymarket_volume_daily` | `agent` | `polymarket_polygon.market_volume_daily` | `condition_id, block_date` | | `agent.polymarket_volume_hourly` | `agent` | `polymarket_polygon.market_volume_hourly` | `condition_id, block_hour` | | `agent.polymarket_rolling_metrics` | `agent` | `polymarket_polygon.market_rolling_metrics` | `—` | | `agent.polymarket_open_interest_daily` | `agent` | `polymarket_polygon.market_open_interest_daily` | `condition_id, block_date` | | `agent.polymarket_user_activity` | `agent` | `polymarket_polygon.user_activity_v2` | `account, token_id, block_time` | | `agent.kalshi_market_details` | `agent` | `kalshi.market_details` | `market_ticker` | | `agent.kalshi_trades` | `agent` | `kalshi.trades` | `ticker, created_time, trade_id` | | `agent.prediction_markets_daily` | `agent` | `prediction_markets.daily` | `—` | | `agent.prediction_markets_matched_markets` | `agent` | `prediction_markets.matched_markets` | `—` | | `agent.prediction_markets_matched_daily` | `agent` | `prediction_markets.matched_daily` | `—` | | `agent.polymarket_positions` | `agent` | `None` | `—` | ## Related Tables * `agent.kalshi_daily_categorized` * `agent.kalshi_market_report` * `agent.prediction_category_daily` ## Sample Queries ### 1. Daily volume by platform ```sql theme={null} SELECT date, source, sum(notional_volume_usd) AS volume, sum(open_interest_usd) AS oi FROM agent.prediction_markets_daily WHERE date >= today() - 30 GROUP BY date, source ORDER BY date DESC, source ``` ## Table Schemas ### `agent.polymarket_trades` Individual Polymarket trade events (OrderFilled) with USD amounts, maker/taker addresses, condition IDs, and outcome context. One row per trade event. The primary source for Polymarket volume and trading activity analysis. **Engine**: MergeTree | **Partition**: `toYYYYMM(block_date)` | **ORDER BY**: `block_time, tx_hash, evt_index` | Column | Type | Description | | --------------------- | --------------- | ------------------------------------------------------------- | | `block_date` | `Date` | Partition key. Always filter on this. | | `block_time` | `DateTime64(3)` | Trade timestamp. | | `block_number` | `UInt64` | Block number | | `tx_hash` | `String` | Transaction hash | | `evt_index` | `UInt32` | Event log index in transaction | | `exchange_address` | `String` | | | `protocol` | `String` | | | `project` | `String` | Protocol name | | `order_hash` | `String` | | | `maker_address` | `String` | Maker (liquidity provider) address. | | `taker_address` | `String` | Taker (liquidity consumer) address. | | `maker_asset_id` | `String` | | | `taker_asset_id` | `String` | | | `maker_amount_filled` | `UInt256` | | | `taker_amount_filled` | `UInt256` | | | `fee_raw` | `UInt256` | | | `outcome_token_id` | `String` | | | `shares` | `Float64` | | | `amount_usd` | `Float64` | Trade notional value in USD (one-sided). | | `price` | `Float64` | Token price in USD | | `fee_usd` | `Float64` | | | `condition_id` | `String` | Unique market condition identifier. Links to market\_details. | | `question` | `String` | | | `outcome_index` | `UInt8` | | | `outcome_label` | `String` | | | `category` | `String` | Market category | | `market_slug` | `String` | | | `market_end_date` | `DateTime` | | | `neg_risk` | `UInt8` | | | `question_id` | `String` | | | `event_slug` | `String` | | | `event_title` | `String` | Event title | * account = maker captures both sides of a trade — do NOT fan out to both maker and taker * This follows Paradigm methodology: each OrderFilled with account=maker is one-sided volume * 934M rows — always filter on block\_date or block\_time ranges * condition\_id links to market\_details for market question and metadata * JOIN with polymarket\_market\_details ON condition\_id for market enrichment * On-chain trades only — off-chain order book and cancellations not included * Pipeline lag: Polygon BQ export runs every 1h, typical lag \~1 hour * No aggregator/frontend attribution — all trades appear as CTF Exchange events ### `agent.polymarket_market_details` Polymarket market metadata dimension table. Contains market questions, descriptions, event groupings, resolution status, end dates, tags, and Polymarket links. One row per (condition\_id, outcome\_index) — use outcome\_index=0 for one row per condition. **Engine**: MergeTree | **ORDER BY**: `condition_id, token_id` | Column | Type | Description | | ------------------------- | --------------- | --------------------------------------------------------------------------------------------- | | `condition_id` | `String` | Primary market identifier. Links to all other Polymarket tables. | | `question_id` | `String` | Groups related conditions into a single question (e.g., 'Will X win?' has Yes/No conditions). | | `question` | `String` | Market question text (e.g., 'Will Bitcoin reach \$100K by December 2026?'). | | `market_description` | `String` | Longer market description with resolution criteria. | | `token_id` | `String` | | | `outcome_index` | `UInt8` | 0 or 1. Use 0 for deduplication (one row per condition). | | `outcome_label` | `String` | | | `token_outcome_name` | `String` | | | `category` | `String` | Market category | | `market_slug` | `String` | | | `event_slug` | `String` | URL-safe event identifier for Polymarket links. | | `event_title` | `String` | Parent event title grouping multiple markets. | | `market_end_date` | `DateTime` | Scheduled market end date. | | `neg_risk` | `UInt8` | Boolean. True = this is a neg-risk (multi-outcome) market. | | `active` | `UInt8` | Boolean. True = market is currently open for trading. | | `closed` | `UInt8` | Boolean. True = market has been closed (trading halted). | | `archived` | `UInt8` | | | `volume_total` | `Float64` | | | `liquidity` | `Float64` | | | `resolved_at` | `DateTime64(3)` | Resolution timestamp. Null if unresolved. | | `created_at` | `DateTime` | | | `updated_at` | `DateTime` | | | `market_id` | `UInt64` | | | `start_time` | `DateTime` | | | `close_time` | `DateTime` | | | `game_start_time` | `DateTime` | | | `tags` | `String` | Array of category tags. | | `volume_1wk` | `Float64` | | | `volume_1mo` | `Float64` | | | `volume_1yr` | `Float64` | | | `resolution_source` | `String` | | | `image` | `String` | | | `icon` | `String` | | | `neg_risk_market_id` | `String` | | | `event_description` | `String` | | | `event_start_time` | `DateTime` | | | `event_image` | `String` | | | `event_resolution_source` | `String` | | | `status` | `String` | Market status (active, closed, resolved) | | `winning_outcome_index` | `Int8` | | | `polymarket_link` | `String` | Direct URL to this market on polymarket.com. | * Filter outcome\_index = 0 for one row per condition (avoids duplicates) * question is the market title/question text * active=true means the market is currently tradeable * closed=true means the market has stopped trading (may or may not be resolved) * Tags is an array — use hasAny(tags, \['politics']) for tag filtering * condition\_id is the primary join key to trades, positions, volume, and OI tables * Metadata reflects current state — does not track historical changes to descriptions or end dates * category/subcategory not directly in this table — join with curated ranking or category tables ### `agent.polymarket_events` Polymarket event-level metadata. Events group related markets (conditions) under a single theme (e.g., "2026 US Presidential Election" groups multiple candidate-specific markets). Useful for navigating the market hierarchy. * Events contain multiple conditions — join with market\_details on event\_slug for full expansion * Useful for building hierarchical market browsers (event -> conditions -> trades) * Not all markets belong to events — some standalone markets have no parent event ### `agent.polymarket_prices_daily` Daily outcome token prices for Polymarket markets. Tracks the probability (price) of each outcome over time. Useful for building price charts and tracking market sentiment evolution. * Price represents implied probability (0-1 range, where 1.0 = 100% chance) * Combine with market\_details for market question context * For binary markets, only one outcome price is needed (the other is 1 - price) * Daily granularity only — no intraday price snapshots available in this table * Prices reflect last trade of day, not volume-weighted average ### `agent.polymarket_prices_hourly` Hourly CLOB mid-prices per Polymarket outcome token. Provides intraday price (implied probability) resolution for building higher-frequency charts and detecting rapid sentiment shifts. * Prices represent implied probability (0-1 range). Multiply by 100 for percentage. * Filter on block\_date first for partition pruning, then narrow by hour if needed * For binary markets, one outcome price is sufficient — the other is 1 - price * JOIN with polymarket\_market\_details ON condition\_id for market question context * Mid-prices from CLOB — may be stale for illiquid markets with wide spreads * Not volume-weighted — reflects order book mid, not trade-weighted average ### `agent.polymarket_prices_latest` Latest snapshot price per Polymarket outcome token. A convenience view that returns the most recent price for each condition, eliminating the need for argMax() queries against the full prices table. **Engine**: MergeTree | **ORDER BY**: `token_id` | Column | Type | Description | | --------------- | --------- | ----------------------- | | `token_id` | `String` | | | `condition_id` | `String` | Polymarket condition ID | | `question` | `String` | | | `outcome_index` | `UInt8` | | | `outcome_label` | `String` | | | `last_updated` | `Date` | | | `latest_price` | `Float64` | | * One row per condition — no time filter needed * Equivalent to argMax(price, timestamp) from the full prices table but pre-computed * JOIN with polymarket\_market\_details ON condition\_id for enrichment * Point-in-time snapshot — reflects the most recent pipeline run, not tick-level * Stale for markets with no recent trading activity ### `agent.polymarket_volume_daily` Daily aggregated trading volume per Polymarket market condition. Pre-computed from individual trades for efficient time-series queries. One row per (condition\_id, block\_date). **Engine**: MergeTree | **Partition**: `toYYYYMM(block_date)` | **ORDER BY**: `condition_id, block_date` | Column | Type | Description | | --------------------- | --------- | ---------------------------------------------- | | `block_date` | `Date` | Date of the volume observation. | | `condition_id` | `String` | Market condition identifier. | | `trade_count` | `UInt64` | | | `notional_volume_usd` | `Float64` | Daily notional trading volume (one-sided, USD) | * Much faster than aggregating polymarket\_trades for daily volume — prefer this table * JOIN with market\_details ON condition\_id for market context * For platform-level total volume, sum across all conditions per day * Granularity is daily only — for intraday volume, use polymarket\_trades directly ### `agent.polymarket_volume_hourly` Hourly trading volume per Polymarket condition. Pre-aggregated from individual trades for efficient intraday volume analysis without scanning the full trades table. **Engine**: MergeTree | **Partition**: `toYYYYMM(toDate(block_hour))` | **ORDER BY**: `condition_id, block_hour` | Column | Type | Description | | --------------------- | ---------- | ---------------------------------------------- | | `block_hour` | `DateTime` | | | `condition_id` | `String` | Polymarket condition ID | | `trade_count` | `UInt64` | | | `notional_volume_usd` | `Float64` | Daily notional trading volume (one-sided, USD) | * Filter on block\_date for partition pruning, then refine by hour * Much faster than aggregating polymarket\_trades hourly * JOIN with polymarket\_market\_details ON condition\_id for market context * Hourly granularity only — for sub-hour analysis, use polymarket\_trades ### `agent.polymarket_rolling_metrics` Pre-computed rolling window metrics for Polymarket markets (e.g., 7-day volume, 30-day volume, trailing unique traders). Useful for ranking and screening markets by recent activity without expensive window function queries. * Pre-computed rolling windows are much faster than manual window functions on trades * Use for market ranking and filtering — then drill into volume\_daily or trades for details * Rolling window definitions are fixed — cannot customize the window period * Updated periodically, not real-time ### `agent.polymarket_open_interest_daily` Cumulative open interest per Polymarket condition derived from on-chain events (splits, merges, redemptions, conversions). SPARSE: only has rows on days with events, not every calendar day. Requires gap-fill logic for time series. **Engine**: MergeTree | **Partition**: `toYYYYMM(block_date)` | **ORDER BY**: `condition_id, block_date` | Column | Type | Description | | ---------------------- | --------- | ---------------------------------------------------------------------------------------------- | | `block_date` | `Date` | Date of the OI change event. SPARSE — not every day has a row. | | `condition_id` | `String` | Market condition identifier. | | `daily_net_change_raw` | `Int256` | | | `daily_net_change_usd` | `Float64` | | | `open_interest_raw` | `Int256` | | | `open_interest_usd` | `Float64` | Cumulative OI in USD for this condition on this date. Can be negative for neg-risk conditions. | * SPARSE data — use argMax(open\_interest\_usd, block\_date) per condition to gap-fill (carry forward) * Do NOT use HAVING last\_oi > 0 — some conditions legitimately have negative OI (neg-risk markets) * Do NOT filter by market resolution status — resolved markets' OI decreases naturally via PayoutRedemption * For global OI: sum(argMax(open\_interest\_usd, block\_date)) across all conditions * Neg-risk markets: individual conditions can have large negative OI — the group total across sibling conditions is correct * Do NOT apply neg\_risk correction (sum/count(DISTINCT condition\_id)) — the raw sum is already correct * Sparse — only rows on days with OI-affecting events, not a continuous daily series * \~5% undercount vs Polymarket subgraph due to \~97K conditions missing from decoded events * Individual neg-risk condition OI can be large negative — always sum across sibling conditions for market-level OI ### `agent.polymarket_user_activity` Per-user trade activity on Polymarket including buy/sell counts, volume, and realized PnL. Aggregated by (address, condition\_id) to show each user's activity within each market. **Engine**: MergeTree | **Partition**: `toYYYYMM(block_date)` | **ORDER BY**: `account, token_id, block_time` | Column | Type | Description | | -------------- | --------------- | ------------------------------------------ | | `block_date` | `Date` | UTC block date | | `block_time` | `DateTime64(3)` | UTC block timestamp | | `block_number` | `UInt64` | Block number | | `tx_hash` | `String` | Transaction hash | | `evt_index` | `UInt32` | Event log index in transaction | | `account` | `String` | | | `token_id` | `String` | | | `event_type` | `String` | | | `side` | `String` | | | `amount` | `Float64` | Amount in display units (decimal-adjusted) | | `price` | `Float64` | Token price in USD | | `amount_usd` | `Float64` | USD value of transfer | * Filter by address for single-wallet analysis * account = maker follows Paradigm methodology — captures both sides correctly * JOIN with polymarket\_market\_details ON condition\_id for market context * Aggregated per (address, condition\_id) — sum across conditions for total user activity * Uses proxy wallet addresses — no mapping to user identities * PnL is realized only — does not include unrealized gains on open positions ### `agent.kalshi_market_details` Kalshi market metadata and snapshot data. Contains market tickers, titles, categories, settlement details, and status. Kalshi uses a three-level hierarchy: series -> events -> markets. MVE (parlay) markets skip the event layer. **Engine**: MergeTree | **ORDER BY**: `market_ticker` | Column | Type | Description | | ------------------------ | --------------- | ---------------------------------------------------- | | `market_ticker` | `String` | Unique market identifier (Kalshi) | | `event_ticker` | `String` | Parent event ticker. Empty for MVE (parlay) markets. | | `event_title` | `String` | Event title | | `event_subtitle` | `String` | | | `title` | `String` | Market title/question text. | | `start_time` | `DateTime64(3)` | | | `end_time` | `DateTime64(3)` | | | `close_time` | `DateTime64(3)` | | | `category` | `String` | Market category | | `subcategory` | `String` | Market subcategory | | `payout_type` | `String` | | | `status` | `String` | Market status: 'active', 'closed', 'settled', etc. | | `last_price` | `Float64` | | | `total_volume` | `UInt64` | Cumulative total volume | | `daily_volume` | `UInt64` | Daily contract volume | | `open_interest` | `Float64` | End-of-day open interest (contracts) | | `result` | `String` | Market result (if resolved) | | `yes_bid` | `Float64` | | | `yes_ask` | `Float64` | | | `no_bid` | `Float64` | | | `no_ask` | `Float64` | | | `last_day_open_interest` | `Float64` | | * Kalshi hierarchy: series -> events -> markets. MVE markets skip the event layer * event\_ticker links to events; series\_ticker from events links to series * For MVE markets, derive series\_ticker from splitByChar('-', ticker)\[1] * Use FINAL if the underlying table is ReplacingMergeTree * Large table (55.6M rows) due to historical snapshots — filter by status or date range * MVE (parlay) markets have different structure than regular markets — see Kalshi data model docs * Centralized exchange data — no on-chain verification possible ### `agent.kalshi_trades` Individual Kalshi trade events. Each row represents a single fill on the Kalshi exchange with price, quantity, side, and market ticker. The raw trade-level data source for Kalshi volume analysis. **Engine**: ReplacingMergeTree | **Partition**: `toYYYYMM(trade_date)` | **ORDER BY**: `ticker, created_time, trade_id` | Column | Type | Description | | --------------- | --------------- | ----------- | | `trade_id` | `String` | | | `ticker` | `String` | | | `num_contracts` | `UInt32` | | | `taker_side` | `String` | | | `maker_side` | `String` | | | `yes_price` | `Float64` | | | `no_price` | `Float64` | | | `trade_date` | `Date` | | | `created_time` | `DateTime64(3)` | | * Filter on date or created\_time for partition pruning * ticker links to kalshi\_market\_details for market metadata * Price is in cents (0-100 range for binary markets) * count is the number of contracts in the fill * Centralized exchange data — no on-chain verification * Trade history depth depends on Kalshi API availability * No user/wallet attribution — trades are anonymous ### `agent.prediction_markets_daily` Unified daily prediction market volume and open interest across Kalshi and Polymarket. One row per (date, source, category, subcategory). Uses Paradigm-compatible category taxonomy. Only includes dates where BOTH platforms have data to avoid partial comparisons. * source is 'Kalshi' or 'Polymarket' — filter for single-platform or compare both * Both platforms must have data for a date to appear — gaps mean one platform had no data * notional\_volume\_usd is one-sided volume in USD * open\_interest\_usd is cumulative OI in USD * For total market volume: sum both sources * Only dates with data from BOTH platforms — single-platform activity on gap days is lost * Category taxonomy depends on upstream categorization models — some markets may be 'UNKNOWN' * Volume methodology may differ slightly between platforms (both aim for one-sided) ### `agent.prediction_markets_matched_markets` Polymarket-to-Kalshi matched market pairs. Each row is a strict one-to-one (condition\_id, market\_ticker) pair linking the same event across platforms. Enriched with live volume and OI from both sides. Generated via LLM matching (Grok) with confidence scoring. * match\_type is 'exact' (same question) or 'related' (same event, different angle) * confidence ranges from 75-100 — higher is more reliable * One-to-one mapping — no fan-out or duplication * JOIN with platform-specific tables for additional enrichment * Coverage depends on LLM matching quality — not all markets are matched * Confidence threshold at 75+ — some lower-confidence matches may be excluded * Seed-based — new markets require re-running the matching pipeline ### `agent.prediction_markets_matched_daily` Daily volume and open interest comparison for matched Polymarket-Kalshi market pairs. One row per (condition\_id, market\_ticker, date) with side-by-side volume and OI from both platforms. The time-series companion to matched\_markets. * Filter on date for partition pruning * Compare polymarket\_volume\_usd vs kalshi\_volume\_usd for platform share on matched events * JOIN with prediction\_markets\_matched\_markets for match metadata (confidence, match\_type) * Only includes matched markets — unmatched markets on either platform are excluded * Date coverage limited to overlap period where both platforms have data ### `agent.polymarket_positions` Current Polymarket user positions with market context. A custom view that JOINs user\_positions\_v2 (on-chain position tracking) with market\_details for enrichment. Shows open positions with balance, PnL, cost basis, and market metadata. Filters to positions with net\_shares > 0.000001 (non-dust). * Filter by address for wallet-specific portfolio view * holdings\_usd = net\_shares \* value\_per\_share (current market value of position) * pnl is the realized + unrealized PnL for this position * cost\_basis is the total USD spent acquiring the position * avg\_buy\_price is the volume-weighted average entry price * resolution\_status shows if the market has resolved (won/lost/open) * Current state snapshot — does not track historical position changes * Only shows positions with net\_shares > 0.000001 — fully closed positions are excluded * Proxy wallet address, not the user's main wallet — address mapping not included # Prices Source: https://docs.asksurf.ai/data-catalog/prices Daily token prices combining CoinGecko data and DEX VWAP calculations. **3 tables** in this category. ## Tables | View Name | Database | Source | ORDER BY | | --------------------------- | -------- | --------------------- | ------------------------------ | | `agent.ethereum_prices_day` | `agent` | `prices_ethereum.day` | `contract_address, block_date` | | `agent.base_prices_day` | `agent` | `prices_base.day` | `contract_address, block_date` | | `agent.arbitrum_prices_day` | `agent` | `prices_arbitrum.day` | `contract_address, block_date` | ## Related Tables * `agent.arbitrum_dex_trades` * `agent.base_dex_trades` * `agent.ethereum_dex_trades` * `agent.ethereum_erc20` ## Sample Queries ### 1. ETH daily price for the last 30 days ```sql theme={null} SELECT block_date, price FROM agent.ethereum_prices_day WHERE symbol = 'WETH' AND block_date >= today() - 30 ORDER BY block_date ``` ## Table Schemas ### `agent.ethereum_prices_day` Daily token prices combining CoinGecko hourly snapshots and DEX VWAP calculations. One row per (contract\_address, block\_date, source). Prefer source='coingecko' when available. **Engine**: MergeTree | **Partition**: `toYYYYMM(block_date)` | **ORDER BY**: `contract_address, block_date` | Column | Type | Description | | ------------------ | --------- | ------------------------------------------------------------------------------------------------ | | `block_date` | `Date` | UTC block date | | `blockchain` | `String` | Blockchain network name | | `contract_address` | `String` | Token contract address (lowercase hex). Zero address for native token. | | `decimals` | `Int64` | Token decimals (from erc20 metadata). Needed when converting raw amounts. | | `symbol` | `String` | Token symbol. May be null for unregistered tokens. | | `price` | `Float64` | USD price. CoinGecko source is hourly snapshot; DEX VWAP is volume-weighted from on-chain swaps. | | `volume_usd` | `Float64` | Trading volume in USD | | `source` | `String` | 'coingecko' or 'dex\_vwap'. Prefer coingecko for stable reference; dex\_vwap fills gaps. | * Use argMax(price, source = 'coingecko') to prefer CoinGecko over DEX VWAP when both exist * JOIN on (contract\_address, block\_date) for daily valuations * WETH contract (0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2) is the ETH price proxy on Ethereum * Coverage gaps exist for illiquid/new tokens — always handle NULL prices * CoinGecko prices are hourly snapshots, not tick-level — intraday precision is limited * DEX VWAP can be skewed by low-liquidity pools or wash trading * New tokens may have no price for the first few days after deployment * Stablecoins may show slight depegs in CoinGecko data during volatility ### `agent.base_prices_day` Daily token prices combining CoinGecko hourly snapshots and DEX VWAP calculations. One row per (contract\_address, block\_date, source). Prefer source='coingecko' when available. **Engine**: MergeTree | **Partition**: `toYYYYMM(block_date)` | **ORDER BY**: `contract_address, block_date` | Column | Type | Description | | ------------------ | ------------------- | ------------------------------------------------------------------------------------------------ | | `block_date` | `Date` | UTC block date | | `blockchain` | `String` | Blockchain network name | | `contract_address` | `String` | Token contract address (lowercase hex). Zero address for native token. | | `decimals` | `Int64` | Token decimals (from erc20 metadata). Needed when converting raw amounts. | | `symbol` | `String` | Token symbol. May be null for unregistered tokens. | | `price` | `Nullable(Float64)` | USD price. CoinGecko source is hourly snapshot; DEX VWAP is volume-weighted from on-chain swaps. | | `volume_usd` | `Float64` | Trading volume in USD | | `source` | `String` | 'coingecko' or 'dex\_vwap'. Prefer coingecko for stable reference; dex\_vwap fills gaps. | * Use argMax(price, source = 'coingecko') to prefer CoinGecko over DEX VWAP when both exist * JOIN on (contract\_address, block\_date) for daily valuations * WETH contract (0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2) is the ETH price proxy on Ethereum * Coverage gaps exist for illiquid/new tokens — always handle NULL prices * CoinGecko prices are hourly snapshots, not tick-level — intraday precision is limited * DEX VWAP can be skewed by low-liquidity pools or wash trading * New tokens may have no price for the first few days after deployment * Stablecoins may show slight depegs in CoinGecko data during volatility ### `agent.arbitrum_prices_day` Daily token prices combining CoinGecko hourly snapshots and DEX VWAP calculations. One row per (contract\_address, block\_date, source). Prefer source='coingecko' when available. **Engine**: MergeTree | **Partition**: `toYYYYMM(block_date)` | **ORDER BY**: `contract_address, block_date` | Column | Type | Description | | ------------------ | ------------------- | ------------------------------------------------------------------------------------------------ | | `block_date` | `Date` | UTC block date | | `blockchain` | `String` | Blockchain network name | | `contract_address` | `String` | Token contract address (lowercase hex). Zero address for native token. | | `decimals` | `Int64` | Token decimals (from erc20 metadata). Needed when converting raw amounts. | | `symbol` | `String` | Token symbol. May be null for unregistered tokens. | | `price` | `Nullable(Float64)` | USD price. CoinGecko source is hourly snapshot; DEX VWAP is volume-weighted from on-chain swaps. | | `volume_usd` | `Float64` | Trading volume in USD | | `source` | `String` | 'coingecko' or 'dex\_vwap'. Prefer coingecko for stable reference; dex\_vwap fills gaps. | * Use argMax(price, source = 'coingecko') to prefer CoinGecko over DEX VWAP when both exist * JOIN on (contract\_address, block\_date) for daily valuations * WETH contract (0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2) is the ETH price proxy on Ethereum * Coverage gaps exist for illiquid/new tokens — always handle NULL prices * CoinGecko prices are hourly snapshots, not tick-level — intraday precision is limited * DEX VWAP can be skewed by low-liquidity pools or wash trading * New tokens may have no price for the first few days after deployment * Stablecoins may show slight depegs in CoinGecko data during volatility # Token Metadata Source: https://docs.asksurf.ai/data-catalog/token-metadata ERC-20 contract registry mapping addresses to symbols, names, and decimals. **1 tables** in this category. ## Tables | View Name | Database | Source | ORDER BY | | ---------------------- | -------- | -------------- | ------------------ | | `agent.ethereum_erc20` | `agent` | `tokens.erc20` | `contract_address` | ## Related Tables * `agent.ethereum_dex_trades` * `agent.ethereum_prices_day` * `agent.ethereum_transfers` ## Table Schemas ### `agent.ethereum_erc20` ERC-20 token metadata registry: contract address, symbol, name, and decimals. Used as a dimension table for enriching addresses into human-readable token info. **Engine**: MergeTree | **ORDER BY**: `contract_address` | Column | Type | Description | | ------------------ | ------------------ | --------------------------------------------------------------------------------------------- | | `blockchain` | `String` | Blockchain network name | | `contract_address` | `String` | Lowercase hex token contract address. Primary key for joins. | | `symbol` | `Nullable(String)` | Token ticker symbol (e.g., USDC, WETH). Not unique — multiple contracts can share a symbol. | | `name` | `Nullable(String)` | Full token name (e.g., 'USD Coin', 'Wrapped Ether'). | | `decimals` | `Nullable(Int64)` | Token decimals (typically 18 for ETH-like, 6 for USDC/USDT). Used for amount\_raw conversion. | * This is a small dimension table — safe to use in subqueries or JOINs without filtering * contract\_address is lowercase hex — ensure your join keys are also lowercase * Some tokens have duplicate symbols (multiple USDT contracts exist) — always join on address, not symbol * Ethereum-only. Other chains do not have a separate erc20 metadata table exposed. * May not include every token — new or very obscure tokens might be missing * Symbol and name are from deployment — tokens can rebrand but this table reflects original metadata # Transfers Source: https://docs.asksurf.ai/data-catalog/transfers ERC-20 and native token transfers enriched with symbols and USD pricing. **5 tables** in this category. ## Tables | View Name | Database | Source | ORDER BY | | -------------------------- | -------- | --------------------------- | ---------------------------------------------------- | | `agent.ethereum_transfers` | `agent` | `tokens_ethereum.transfers` | `contract_address, block_number, tx_hash, evt_index` | | `agent.base_transfers` | `agent` | `tokens_base.transfers` | `contract_address, block_number, tx_hash, evt_index` | | `agent.arbitrum_transfers` | `agent` | `tokens_arbitrum.transfers` | `contract_address, block_number, tx_hash, evt_index` | | `agent.bsc_transfers` | `agent` | `tokens_bsc.transfers` | `—` | | `agent.tron_transfers` | `agent` | `tokens_tron.transfers` | `contract_address, block_number, tx_hash, evt_index` | ## Related Tables * `agent.arbitrum_prices_day` * `agent.base_prices_day` * `agent.ethereum_erc20` * `agent.ethereum_prices_day` ## Sample Queries ### 1. Largest USDC transfers today ```sql theme={null} SELECT block_time, `from`, `to`, amount, amount_usd FROM agent.ethereum_transfers WHERE symbol = 'USDC' AND block_date = today() - 1 ORDER BY amount_usd DESC LIMIT 20 ``` ## Table Schemas ### `agent.ethereum_transfers` ERC-20 Transfer events plus native token (ETH/BNB/TRX) trace-based transfers. Includes WETH wrap/unwrap. Enriched with tx\_from, tx\_to, tx\_index from transaction lookup. One row per transfer event or trace. **Engine**: MergeTree | **Partition**: `toYYYYMM(block_date)` | **ORDER BY**: `contract_address, block_number, tx_hash, evt_index` | Column | Type | Description | | ------------------ | ------------------- | ------------------------------------------------------------------------------------------ | | `blockchain` | `String` | Blockchain network name | | `block_month` | `Date` | UTC block month (partition key) | | `block_date` | `Date` | UTC block date | | `block_time` | `DateTime64(3)` | UTC block timestamp | | `block_number` | `UInt64` | Block number | | `tx_hash` | `String` | Transaction hash | | `evt_index` | `UInt32` | Event log index in transaction | | `trace_address` | `Array(Int64)` | Non-empty for native trace-based transfers. Empty string for event-based ERC-20 transfers. | | `token_standard` | `String` | 'erc20' for ERC-20 Transfer events, 'native' for ETH/BNB/TRX trace transfers. | | `tx_from` | `String` | Transaction sender (EOA that signed the tx). From transaction lookup. | | `tx_to` | `String` | Transaction recipient (first-level contract called). From transaction lookup. | | `tx_index` | `UInt32` | Transaction index in block | | `from` | `String` | Transfer sender address. | | `to` | `String` | Transfer recipient address. | | `contract_address` | `String` | Token contract address. Zero address (0x0000...0000) for native token transfers. | | `symbol` | `String` | Token symbol | | `amount_raw` | `UInt256` | Raw uint256 transfer amount. Divide by 10^decimals for human-readable value. | | `amount` | `Float64` | Amount in display units (decimal-adjusted) | | `price_usd` | `Float64` | USD price at transfer time | | `amount_usd` | `Nullable(Float64)` | USD value of transfer | * These tables are VERY large (billions of rows) — always filter on block\_date first * token\_standard is 'erc20' or 'native' — filter accordingly * amount\_raw is uint256 before decimal adjustment — divide by 10^decimals for human-readable amounts * JOIN with ethereum\_erc20 on contract\_address for symbol and decimals * For net flows: SUM(amount\_raw) WHERE to=addr minus SUM(amount\_raw) WHERE from=addr * No USD amounts — join with prices tables for valuation * Native transfers from trace data may include internal contract-to-contract transfers * Does not include ERC-721 (NFT) or ERC-1155 (multi-token) transfers * amount\_raw is raw — you must know the token's decimals to interpret correctly ### `agent.base_transfers` ERC-20 Transfer events plus native token (ETH/BNB/TRX) trace-based transfers. Includes WETH wrap/unwrap. Enriched with tx\_from, tx\_to, tx\_index from transaction lookup. One row per transfer event or trace. **Engine**: MergeTree | **Partition**: `toYYYYMM(block_date)` | **ORDER BY**: `contract_address, block_number, tx_hash, evt_index` | Column | Type | Description | | ------------------ | ------------------- | ------------------------------------------------------------------------------------------ | | `blockchain` | `String` | Blockchain network name | | `block_month` | `Date` | UTC block month (partition key) | | `block_date` | `Date` | UTC block date | | `block_time` | `DateTime64(3)` | UTC block timestamp | | `block_number` | `UInt64` | Block number | | `tx_hash` | `String` | Transaction hash | | `evt_index` | `UInt32` | Event log index in transaction | | `trace_address` | `Array(Int64)` | Non-empty for native trace-based transfers. Empty string for event-based ERC-20 transfers. | | `token_standard` | `String` | 'erc20' for ERC-20 Transfer events, 'native' for ETH/BNB/TRX trace transfers. | | `tx_from` | `String` | Transaction sender (EOA that signed the tx). From transaction lookup. | | `tx_to` | `String` | Transaction recipient (first-level contract called). From transaction lookup. | | `tx_index` | `UInt32` | Transaction index in block | | `from` | `String` | Transfer sender address. | | `to` | `String` | Transfer recipient address. | | `contract_address` | `String` | Token contract address. Zero address (0x0000...0000) for native token transfers. | | `symbol` | `String` | Token symbol | | `amount_raw` | `UInt256` | Raw uint256 transfer amount. Divide by 10^decimals for human-readable value. | | `amount` | `Float64` | Amount in display units (decimal-adjusted) | | `price_usd` | `Float64` | USD price at transfer time | | `amount_usd` | `Nullable(Float64)` | USD value of transfer | * This table has 7.5B+ rows — ALWAYS use tight block\_date filters * token\_standard is 'erc20' or 'native' — filter accordingly * amount\_raw is uint256 before decimal adjustment — divide by 10^decimals * Base native token is ETH (bridged), same decimals as Ethereum ETH * No USD amounts — join with prices tables for valuation * Native transfers from trace data may include internal contract-to-contract transfers * Does not include ERC-721 (NFT) or ERC-1155 (multi-token) transfers * amount\_raw is raw — you must know the token's decimals to interpret correctly ### `agent.arbitrum_transfers` ERC-20 Transfer events plus native token (ETH/BNB/TRX) trace-based transfers. Includes WETH wrap/unwrap. Enriched with tx\_from, tx\_to, tx\_index from transaction lookup. One row per transfer event or trace. **Engine**: MergeTree | **Partition**: `toYYYYMM(block_date)` | **ORDER BY**: `contract_address, block_number, tx_hash, evt_index` | Column | Type | Description | | ------------------ | ------------------- | ------------------------------------------------------------------------------------------ | | `blockchain` | `String` | Blockchain network name | | `block_month` | `Date` | UTC block month (partition key) | | `block_date` | `Date` | UTC block date | | `block_time` | `DateTime64(3)` | UTC block timestamp | | `block_number` | `UInt64` | Block number | | `tx_hash` | `String` | Transaction hash | | `evt_index` | `UInt32` | Event log index in transaction | | `trace_address` | `Array(Int64)` | Non-empty for native trace-based transfers. Empty string for event-based ERC-20 transfers. | | `token_standard` | `String` | 'erc20' for ERC-20 Transfer events, 'native' for ETH/BNB/TRX trace transfers. | | `tx_from` | `String` | Transaction sender (EOA that signed the tx). From transaction lookup. | | `tx_to` | `String` | Transaction recipient (first-level contract called). From transaction lookup. | | `tx_index` | `UInt32` | Transaction index in block | | `from` | `String` | Transfer sender address. | | `to` | `String` | Transfer recipient address. | | `contract_address` | `String` | Token contract address. Zero address (0x0000...0000) for native token transfers. | | `symbol` | `String` | Token symbol | | `amount_raw` | `UInt256` | Raw uint256 transfer amount. Divide by 10^decimals for human-readable value. | | `amount` | `Float64` | Amount in display units (decimal-adjusted) | | `price_usd` | `Float64` | USD price at transfer time | | `amount_usd` | `Nullable(Float64)` | USD value of transfer | * These tables are VERY large (billions of rows) — always filter on block\_date first * token\_standard is 'erc20' or 'native' — filter accordingly * amount\_raw is uint256 before decimal adjustment — divide by 10^decimals for human-readable amounts * JOIN with ethereum\_erc20 on contract\_address for symbol and decimals * For net flows: SUM(amount\_raw) WHERE to=addr minus SUM(amount\_raw) WHERE from=addr * No USD amounts — join with prices tables for valuation * Native transfers from trace data may include internal contract-to-contract transfers * Does not include ERC-721 (NFT) or ERC-1155 (multi-token) transfers * amount\_raw is raw — you must know the token's decimals to interpret correctly ### `agent.bsc_transfers` ERC-20 Transfer events plus native token (ETH/BNB/TRX) trace-based transfers. Includes WETH wrap/unwrap. Enriched with tx\_from, tx\_to, tx\_index from transaction lookup. One row per transfer event or trace. * BSC transfer tables can be very large — always filter on block\_date first * Native token is BNB, not ETH — 18 decimals * amount\_raw is uint256 before decimal adjustment * No USD amounts — join with prices tables for valuation * Native transfers from trace data may include internal contract-to-contract transfers * Does not include ERC-721 (NFT) or ERC-1155 (multi-token) transfers * amount\_raw is raw — you must know the token's decimals to interpret correctly ### `agent.tron_transfers` ERC-20 Transfer events plus native token (ETH/BNB/TRX) trace-based transfers. Includes WETH wrap/unwrap. Enriched with tx\_from, tx\_to, tx\_index from transaction lookup. One row per transfer event or trace. **Engine**: MergeTree | **Partition**: `toYYYYMM(block_date)` | **ORDER BY**: `contract_address, block_number, tx_hash, evt_index` | Column | Type | Description | | ------------------ | ------------------- | ------------------------------------------------------------------------------------------ | | `blockchain` | `String` | Blockchain network name | | `block_month` | `Date` | UTC block month (partition key) | | `block_date` | `Date` | UTC block date | | `block_time` | `DateTime64(3)` | UTC block timestamp | | `block_number` | `UInt64` | Block number | | `tx_hash` | `String` | Transaction hash | | `evt_index` | `UInt32` | Event log index in transaction | | `trace_address` | `Array(Int64)` | Non-empty for native trace-based transfers. Empty string for event-based ERC-20 transfers. | | `token_standard` | `String` | 'erc20' for ERC-20 Transfer events, 'native' for ETH/BNB/TRX trace transfers. | | `tx_from` | `String` | Transaction sender (EOA that signed the tx). From transaction lookup. | | `tx_to` | `String` | Transaction recipient (first-level contract called). From transaction lookup. | | `tx_index` | `UInt32` | Transaction index in block | | `from` | `String` | Transfer sender address. | | `to` | `String` | Transfer recipient address. | | `contract_address` | `String` | Token contract address. Zero address (0x0000...0000) for native token transfers. | | `symbol` | `String` | Token symbol | | `amount_raw` | `UInt256` | Raw uint256 transfer amount. Divide by 10^decimals for human-readable value. | | `amount` | `Float64` | Amount in display units (decimal-adjusted) | | `price_usd` | `Nullable(Float64)` | USD price at transfer time | | `amount_usd` | `Nullable(Float64)` | USD value of transfer | * 4.6B rows — ALWAYS filter on block\_date * Tron addresses use base58 format (T...) not hex * Native token is TRX (6 decimals for energy, but TRX transfers use sun = 1e-6) * USDT on Tron is extremely high volume — can dominate results if not filtered * No USD amounts — join with prices tables for valuation * Native transfers from trace data may include internal contract-to-contract transfers * Does not include ERC-721 (NFT) or ERC-1155 (multi-token) transfers * amount\_raw is raw — you must know the token's decimals to interpret correctly # TVL / Fees / Yields Source: https://docs.asksurf.ai/data-catalog/tvl-fees-yields Protocol-level daily aggregates for total value locked, fee revenue, and yield rates. **6 tables** in this category. ## Tables | View Name | Database | Source | ORDER BY | | ----------------------------- | -------- | ----------------------- | ------------------------------ | | `agent.ethereum_tvl_daily` | `agent` | `tvl_ethereum.daily` | `project, version, block_date` | | `agent.base_tvl_daily` | `agent` | `tvl_base.daily` | `project, version, block_date` | | `agent.arbitrum_tvl_daily` | `agent` | `tvl_arbitrum.daily` | `project, version, block_date` | | `agent.tron_tvl_daily` | `agent` | `tvl_tron.daily` | `project, version, block_date` | | `agent.ethereum_fees_daily` | `agent` | `fees_ethereum.daily` | `project, version, block_date` | | `agent.ethereum_yields_daily` | `agent` | `yields_ethereum.daily` | `project, version, block_date` | ## Related Tables * `agent.ethereum_lending_daily` * `agent.ethereum_prices_day` ## Sample Queries ### 1. Top protocols by TVL ```sql theme={null} SELECT project, version, tvl_usd FROM agent.ethereum_tvl_daily WHERE block_date = ( SELECT max(block_date) FROM agent.ethereum_tvl_daily ) ORDER BY tvl_usd DESC LIMIT 20 ``` ### 2. Top protocols by daily fees ```sql theme={null} SELECT project, version, daily_fees_usd, daily_revenue_usd, daily_supply_side_revenue_usd FROM agent.ethereum_fees_daily WHERE block_date = ( SELECT max(block_date) FROM agent.ethereum_fees_daily ) ORDER BY daily_fees_usd DESC LIMIT 20 ``` ### 3. Top yielding pools today ```sql theme={null} SELECT project, symbol, pool_meta, apy, tvl_usd FROM agent.ethereum_yields_daily WHERE block_date = ( SELECT max(block_date) FROM agent.ethereum_yields_daily ) AND tvl_usd > 1000000 ORDER BY apy DESC LIMIT 20 ``` ## Table Schemas ### `agent.ethereum_tvl_daily` Protocol-level daily Total Value Locked aggregated across all pools and strategies. One row per (project, version, block\_date). Priced using CoinGecko daily prices. **Engine**: MergeTree | **Partition**: `toYYYYMM(block_date)` | **ORDER BY**: `project, version, block_date` | Column | Type | Description | | ------------ | ------------------- | ------------------------------------------------------------------------------------------ | | `blockchain` | `String` | Blockchain network name | | `project` | `String` | Protocol name (lowercase): uniswap, aave, lido, eigenlayer, curve, etc. | | `version` | `String` | Protocol version string. Empty for single-version protocols. | | `block_date` | `Date` | Partition key. Carry-forward gap-fill ensures every day has a value. | | `tvl_usd` | `Nullable(Float64)` | Total deposited value in USD. CoinGecko pricing only — may undercount for unpriced tokens. | * tvl\_usd is the protocol-level total — individual pool/token breakdowns are in upstream models * TVL uses CoinGecko-only pricing. Unpriced tokens create gaps (see known\_gaps below) * For total chain TVL: SELECT block\_date, sum(tvl\_usd) FROM ethereum\_tvl\_daily GROUP BY block\_date * Cross-reference with fees\_daily and yields\_daily for protocol profitability analysis * CoinGecko-only pricing — tokens not listed on CoinGecko are valued at \$0 * Known gaps: Maverick V1 (\~14% undercount), KyberSwap Elastic (\~111% overcount, dead protocol) * Borrow-side balances excluded — this is supply-side TVL only * New protocols require manual model creation before appearing ### `agent.base_tvl_daily` Protocol-level daily Total Value Locked aggregated across all pools and strategies. One row per (project, version, block\_date). Priced using CoinGecko daily prices. **Engine**: MergeTree | **Partition**: `toYYYYMM(block_date)` | **ORDER BY**: `project, version, block_date` | Column | Type | Description | | ------------ | ------------------- | ------------------------------------------------------------------------------------------ | | `blockchain` | `String` | Blockchain network name | | `project` | `String` | Protocol name (lowercase): uniswap, aave, lido, eigenlayer, curve, etc. | | `version` | `String` | Protocol version string. Empty for single-version protocols. | | `block_date` | `Date` | Partition key. Carry-forward gap-fill ensures every day has a value. | | `tvl_usd` | `Nullable(Float64)` | Total deposited value in USD. CoinGecko pricing only — may undercount for unpriced tokens. | * tvl\_usd is the protocol-level total — individual pool/token breakdowns are in upstream models * TVL uses CoinGecko-only pricing. Unpriced tokens create gaps (see known\_gaps below) * For total chain TVL: SELECT block\_date, sum(tvl\_usd) FROM ethereum\_tvl\_daily GROUP BY block\_date * Cross-reference with fees\_daily and yields\_daily for protocol profitability analysis * CoinGecko-only pricing — tokens not listed on CoinGecko are valued at \$0 * Known gaps: Maverick V1 (\~14% undercount), KyberSwap Elastic (\~111% overcount, dead protocol) * Borrow-side balances excluded — this is supply-side TVL only * New protocols require manual model creation before appearing ### `agent.arbitrum_tvl_daily` Protocol-level daily Total Value Locked aggregated across all pools and strategies. One row per (project, version, block\_date). Priced using CoinGecko daily prices. **Engine**: MergeTree | **Partition**: `toYYYYMM(block_date)` | **ORDER BY**: `project, version, block_date` | Column | Type | Description | | ------------ | ------------------- | ------------------------------------------------------------------------------------------ | | `blockchain` | `String` | Blockchain network name | | `project` | `String` | Protocol name (lowercase): uniswap, aave, lido, eigenlayer, curve, etc. | | `version` | `String` | Protocol version string. Empty for single-version protocols. | | `block_date` | `Date` | Partition key. Carry-forward gap-fill ensures every day has a value. | | `tvl_usd` | `Nullable(Float64)` | Total deposited value in USD. CoinGecko pricing only — may undercount for unpriced tokens. | * This table was recently added and may have zero or very few rows initially * Check SELECT count() and max(block\_date) before building queries against it * Newly added — may have incomplete protocol coverage or zero rows * Same CoinGecko-only pricing limitations as Ethereum TVL ### `agent.tron_tvl_daily` Protocol-level daily Total Value Locked aggregated across all pools and strategies. One row per (project, version, block\_date). Priced using CoinGecko daily prices. **Engine**: MergeTree | **Partition**: `toYYYYMM(block_date)` | **ORDER BY**: `project, version, block_date` | Column | Type | Description | | ------------ | ------------------- | ------------------------------------------------------------------------------------------ | | `blockchain` | `String` | Blockchain network name | | `project` | `String` | Protocol name (lowercase): uniswap, aave, lido, eigenlayer, curve, etc. | | `version` | `String` | Protocol version string. Empty for single-version protocols. | | `block_date` | `Date` | Partition key. Carry-forward gap-fill ensures every day has a value. | | `tvl_usd` | `Nullable(Float64)` | Total deposited value in USD. CoinGecko pricing only — may undercount for unpriced tokens. | * Smaller coverage than Ethereum — fewer protocols indexed on Tron * JustLend is the dominant lending protocol on Tron * CoinGecko-only pricing — tokens not listed on CoinGecko are valued at \$0 * Known gaps: Maverick V1 (\~14% undercount), KyberSwap Elastic (\~111% overcount, dead protocol) * Borrow-side balances excluded — this is supply-side TVL only * New protocols require manual model creation before appearing ### `agent.ethereum_fees_daily` Protocol-level daily fee and revenue metrics following the DefiLlama 6-field standard. Aggregated from 35+ individual protocol fee models. One row per (project, version, block\_date). Covers DEX trading fees, lending interest, staking commissions, and yield protocol fees. **Engine**: MergeTree | **Partition**: `toYYYYMM(block_date)` | **ORDER BY**: `project, version, block_date` | Column | Type | Description | | ------------------------------- | ------------------- | ----------------------------------------------------------------------- | | `blockchain` | `String` | Blockchain network name | | `project` | `String` | Protocol name (lowercase). Same naming as tvl\_daily and yields\_daily. | | `version` | `String` | Protocol version. Same naming as tvl\_daily. | | `block_date` | `Date` | UTC block date | | `daily_fees_usd` | `Nullable(Float64)` | Total fees generated by the protocol on this day (all sources). | | `daily_user_fees_usd` | `Nullable(Float64)` | Fees directly paid by end users (trading fees, borrow interest, etc.). | | `daily_revenue_usd` | `Nullable(Float64)` | Revenue accruing to the protocol and its token holders. | | `daily_protocol_revenue_usd` | `Nullable(Float64)` | Revenue accruing to the protocol treasury. | | `daily_holders_revenue_usd` | `Nullable(Float64)` | Revenue accruing to governance token holders (buybacks, dividends). | | `daily_supply_side_revenue_usd` | `Nullable(Float64)` | Revenue accruing to liquidity providers, lenders, or stakers. | * daily\_fees\_usd = total fees generated (user\_fees + protocol\_revenue + supply\_side) * daily\_revenue\_usd = protocol\_revenue + holders\_revenue (excludes supply-side) * daily\_supply\_side\_revenue\_usd = fees earned by LPs/lenders/stakers * Filter by project for protocol-specific analysis (e.g., project='uniswap') * Cross-reference with tvl\_daily for fee/TVL ratio (protocol efficiency) * Coverage depends on individual protocol models — not every DeFi protocol is included * Fee calculations use on-chain events + CoinGecko pricing — same price gaps as TVL * Some protocol fees (off-chain, governance-voted distributions) may not be captured ### `agent.ethereum_yields_daily` Pool-level daily yield and APY data across 37 Ethereum DeFi protocols. One row per (project, version, pool\_address, token\_address, block\_date). Includes base APY, reward APY, borrow rates, TVL, impermanent loss metrics, and 7d/30d rolling statistics. **Engine**: MergeTree | **Partition**: `toYYYYMM(block_date)` | **ORDER BY**: `project, version, block_date` | Column | Type | Description | | ------------------- | ------------------- | ------------------------------------------------------------------------------- | | `blockchain` | `String` | Blockchain network name | | `project` | `String` | Protocol name | | `version` | `String` | Protocol version | | `block_date` | `Date` | UTC block date | | `pool_address` | `String` | Smart contract address of the pool/vault/market. | | `token_address` | `Nullable(String)` | Token contract address | | `symbol` | `Nullable(String)` | Token symbol for the asset in this yield position. | | `pool_meta` | `String` | Human-readable pool description (e.g., 'WETH-USDC 0.3%'). | | `apy` | `Nullable(Float64)` | Total annualized yield (base + reward). Can be negative for borrow-heavy pools. | | `apy_base` | `Nullable(Float64)` | Organic yield from protocol fees/interest (excludes token incentives). | | `apy_reward` | `Float64` | Yield from liquidity mining / token incentive programs. | | `tvl_usd` | `Nullable(Float64)` | Pool-level TVL for this specific pool and token. CoinGecko-priced. | | `il_7d` | `Float64` | 7-day impermanent loss estimate (as a fraction, e.g., -0.005 = -0.5%). | | `apy_base_7d` | `Nullable(Float64)` | 7-day rolling average base APY | | `apy_base_borrow` | `Float64` | Borrow APY (lending protocols) | | `apy_reward_borrow` | `Float64` | Borrow reward APY | | `total_supply_usd` | `Nullable(Float64)` | Total supply-side value (lending markets). | | `total_borrow_usd` | `Float64` | Total borrow-side value (lending markets). | | `apy_pct_1d` | `Nullable(Float64)` | 1-day APY percentage change. | | `apy_pct_7d` | `Nullable(Float64)` | 7-day APY percentage change. | | `apy_pct_30d` | `Nullable(Float64)` | 30-day APY percentage change. | | `apy_mean_30d` | `Nullable(Float64)` | 30-day rolling mean APY — smoothed metric for trend analysis. | | `stablecoin` | `Nullable(UInt8)` | 1 if the pool is stablecoin-denominated, 0 otherwise. | | `il_risk` | `String` | Impermanent loss risk flag. Relevant for AMM LP positions. | | `exposure` | `String` | Exposure type descriptor for the yield position. | | `volume_usd_1d` | `Float64` | 1-day trading volume for this pool (AMM pools only). | | `volume_usd_7d` | `Float64` | 7-day trading volume for this pool (AMM pools only). | * Filter by stablecoin=1 for stablecoin-only yield analysis * apy is the headline rate (base + reward). apy\_base is organic, apy\_reward is incentivized * Use apy\_mean\_30d for smoothed comparison — daily apy can be volatile * tvl\_usd gives pool-level TVL context for the yield — low TVL + high APY = risky * il\_risk column flags pools with impermanent loss exposure * apy\_base\_borrow and apy\_reward\_borrow are lending market borrow-side rates * APY calculations vary by protocol — some use trailing 7d fees, others use instantaneous rates * Reward APY depends on token prices — can swing wildly with governance token volatility * Not all pools are covered — new or very small pools may be missing * Historical backfill depth varies by protocol # Overview Source: https://docs.asksurf.ai/overview Surf — AI-powered crypto intelligence for agents and developers ## What is Surf Surf is an AI-powered crypto intelligence platform that gives agents and developers unified access to on-chain data, market analytics, social sentiment, and prediction markets — across **40+ blockchains** and **200+ data sources**. ## How to Use Surf Install into your AI agent for automatic crypto data access Natural language queries via chat completions 83 RESTful endpoints across 12 domains ### Quick Start with an AI Agent ```bash theme={null} npx skills add asksurf-ai/surf-skills --skill surf ``` Once installed, just ask your agent things like "what's the price of ETH" or "show me the top Polymarket markets" — the skill handles discovery, authentication, and data fetching automatically. ### Quick Start with the CLI ```bash theme={null} curl -fsSL https://agent.asksurf.ai/cli/releases/install.sh | sh surf login surf market-price --symbol BTC ``` ## Platform Coverage * **Market** — prices, rankings, technical indicators, fear & greed, liquidations, futures, options, ETFs * **Exchange** — order books, candlesticks, funding rates, long/short ratios * **Wallet** — balances, transfers, DeFi positions, net worth, labels * **Social** — Twitter/X profiles, posts, followers, mindshare, sentiment * **Token** — holders, DEX trades, transfers, unlock schedules * **Project** — profiles, DeFi TVL, protocol metrics * **Prediction Markets** — Polymarket and Kalshi markets, trades, prices, open interest * **On-chain** — transaction lookup, SQL queries, gas prices, bridge and yield rankings * **News & Search** — cross-domain entity search, news feed, web fetch ## Additional Resources Terminal-based research and agent integration 58 analyst-ready ClickHouse tables for direct SQL access