Skip to main content
還沒有帳號?點擊這裡註冊 Polymarket 並完成入金,才能用錢包私鑰為訂單籤名、實際成交。
法律合規提醒:在使用 Polymarket 服務或 API 前,請確認您所在地區的法律規定。Polymarket 目前不支援比利時、法國、新加坡、泰國、中國大陸等地區,政策可能隨時變化。
Polymarket Subgraph 提供了一個強大的 GraphQL 接口,用於查詢 Polymarket 的鏈上數據。

什麼是 Subgraph?

Subgraph 是基於 The Graph 協議構建的索引服務,它:
  • 📊 索引區塊鏈數據
  • ⚡ 提供快速查詢
  • 🔍 支援複雜的數據關係
  • 🆓 免費使用
The Graph 是一個去中心化的索引協議,用於組織區塊鏈數據並使其易於訪問。

Polymarket Subgraph

Polymarket 維護了官方的 Subgraph,索引了:
  • 條件代幣合約數據
  • 市場創建和結算
  • 用戶頭寸和交易
  • 條件 ID 和位置 ID

Subgraph 端點

Polygon 主網
https://api.thegraph.com/subgraphs/name/polymarket/polymarket

為什麼使用 Subgraph?

相比直接查詢區塊鏈,Subgraph 提供:
特性直接查詢區塊鏈使用 Subgraph
速度
複雜查詢困難簡單
歷史數據需要掃描所有區塊已索引
關係查詢需要多次調用一次查詢
成本需要大量 RPC 調用免費

GraphQL 查詢示例

查詢市場信息

query {
  conditions(first: 5, orderBy: createdTimestamp, orderDirection: desc) {
    id
    oracle
    questionId
    outcomeSlotCount
    resolved
    payouts
    createdTimestamp
  }
}

查詢用戶頭寸

query UserPositions($userAddress: String!) {
  userPositions(where: { user: $userAddress }) {
    id
    position {
      id
      conditionIds
    }
    balance
    wrappedBalance
  }
}

查詢特定條件

query Condition($conditionId: String!) {
  condition(id: $conditionId) {
    id
    oracle
    questionId
    outcomeSlotCount
    resolved
    resolveTimestamp
    payouts
    positions {
      id
      collateralToken
      indexSets
    }
  }
}

Python 使用示例

import requests
import json

# Subgraph 端點
SUBGRAPH_URL = "https://api.thegraph.com/subgraphs/name/polymarket/polymarket"

def query_subgraph(query, variables=None):
    """
    查詢 Polymarket Subgraph
    """
    payload = {
        'query': query,
        'variables': variables or {}
    }
    
    response = requests.post(SUBGRAPH_URL, json=payload)
    return response.json()

# 查詢最近的條件
query = """
{
  conditions(first: 10, orderBy: createdTimestamp, orderDirection: desc) {
    id
    oracle
    questionId
    outcomeSlotCount
    resolved
    createdTimestamp
  }
}
"""

result = query_subgraph(query)
conditions = result['data']['conditions']

for condition in conditions:
    print(f"條件 ID: {condition['id'][:10]}...")
    print(f"結果數: {condition['outcomeSlotCount']}")
    print(f"已解決: {condition['resolved']}")
    print("---")

查詢用戶頭寸

def get_user_positions(user_address):
    """
    獲取用戶的所有頭寸
    """
    query = """
    query UserPositions($userAddress: String!) {
      userPositions(where: { user: $userAddress }) {
        id
        position {
          id
          conditionIds
          collateralToken {
            id
            symbol
          }
        }
        balance
        wrappedBalance
      }
    }
    """
    
    variables = {'userAddress': user_address.lower()}
    result = query_subgraph(query, variables)
    
    return result['data']['userPositions']

# 使用示例
user_address = "0x1234567890123456789012345678901234567890"
positions = get_user_positions(user_address)

for position in positions:
    print(f"頭寸 ID: {position['id'][:10]}...")
    print(f"餘額: {int(position['balance']) / 10**6} USDC")
    print("---")

TypeScript 使用示例

import axios from 'axios';

const SUBGRAPH_URL = 'https://api.thegraph.com/subgraphs/name/polymarket/polymarket';

interface SubgraphResponse<T> {
  data: T;
  errors?: any[];
}

async function querySubgraph<T>(
  query: string,
  variables?: Record<string, any>
): Promise<T> {
  const response = await axios.post<SubgraphResponse<T>>(SUBGRAPH_URL, {
    query,
    variables: variables || {},
  });
  
  if (response.data.errors) {
    throw new Error(JSON.stringify(response.data.errors));
  }
  
  return response.data.data;
}

// 查詢條件
interface Condition {
  id: string;
  oracle: string;
  questionId: string;
  outcomeSlotCount: number;
  resolved: boolean;
  createdTimestamp: string;
}

async function getRecentConditions(): Promise<Condition[]> {
  const query = `
    {
      conditions(first: 10, orderBy: createdTimestamp, orderDirection: desc) {
        id
        oracle
        questionId
        outcomeSlotCount
        resolved
        createdTimestamp
      }
    }
  `;
  
  const result = await querySubgraph<{ conditions: Condition[] }>(query);
  return result.conditions;
}

// 使用示例
getRecentConditions().then(conditions => {
  conditions.forEach(condition => {
    console.log(`條件 ID: ${condition.id.slice(0, 10)}...`);
    console.log(`已解決: ${condition.resolved}`);
    console.log('---');
  });
});

常見查詢模式

1. 分頁查詢

query PaginatedConditions($skip: Int!, $first: Int!) {
  conditions(
    first: $first
    skip: $skip
    orderBy: createdTimestamp
    orderDirection: desc
  ) {
    id
    questionId
    resolved
  }
}

2. 過濾查詢

query ResolvedConditions {
  conditions(where: { resolved: true }) {
    id
    resolveTimestamp
    payouts
  }
}

3. 關係查詢

query ConditionWithPositions($conditionId: String!) {
  condition(id: $conditionId) {
    id
    positions {
      id
      indexSets
      userPositions {
        user {
          id
        }
        balance
      }
    }
  }
}

數據模型

Condition(條件)

type Condition {
  id: ID!                      // 條件 ID
  oracle: Bytes!               // Oracle 地址
  questionId: Bytes!           // 問題 ID
  outcomeSlotCount: BigInt!    // 結果數量
  resolved: Boolean!           // 是否已解決
  resolveTimestamp: BigInt     // 解決時間戳
  payouts: [BigInt!]          // 支付向量
  positions: [Position!]!      // 相關頭寸
  createdTimestamp: BigInt!    // 創建時間戳
}

Position(頭寸)

type Position {
  id: ID!                      // 頭寸 ID
  collateralToken: CollateralToken!  // 抵押品代幣
  conditionIds: [Bytes!]!      // 條件 ID 列表
  indexSets: [BigInt!]!        // 索引集
  userPositions: [UserPosition!]!  // 用戶頭寸
}

UserPosition(用戶頭寸)

type UserPosition {
  id: ID!                      // 用戶頭寸 ID
  user: User!                  // 用戶
  position: Position!          // 頭寸
  balance: BigInt!             // 餘額
  wrappedBalance: BigInt!      // 包裝餘額
}

實用工具

監控市場結算

import time

def monitor_settlements():
    """
    監控市場結算
    """
    last_check = int(time.time())
    
    while True:
        query = """
        query RecentSettlements($timestamp: Int!) {
          conditions(
            where: { 
              resolved: true
              resolveTimestamp_gt: $timestamp
            }
            orderBy: resolveTimestamp
            orderDirection: desc
          ) {
            id
            questionId
            resolveTimestamp
            payouts
          }
        }
        """
        
        result = query_subgraph(query, {'timestamp': last_check})
        conditions = result['data']['conditions']
        
        if conditions:
            print(f"\n發現 {len(conditions)} 個新結算:")
            for condition in conditions:
                print(f"條件 ID: {condition['id'][:10]}...")
                print(f"支付: {condition['payouts']}")
                print("---")
            
            # 更新最後檢查時間
            last_check = int(conditions[0]['resolveTimestamp'])
        
        time.sleep(60)  # 每分鐘檢查一次

# 運行監控
# monitor_settlements()

性能優化

1. 限制欄位

只查詢需要的欄位:
# ✗ 差:查詢所有欄位
query {
  conditions(first: 100) {
    id
    oracle
    questionId
    outcomeSlotCount
    resolved
    resolveTimestamp
    payouts
    positions {
      id
      # ... 很多欄位
    }
  }
}

# ✓ 好:只查詢需要的欄位
query {
  conditions(first: 100) {
    id
    resolved
  }
}

2. 使用分頁

def get_all_conditions():
    """
    分頁獲取所有條件
    """
    all_conditions = []
    skip = 0
    first = 1000  # The Graph 最大限制
    
    while True:
        query = """
        query PaginatedConditions($skip: Int!, $first: Int!) {
          conditions(first: $first, skip: $skip) {
            id
            resolved
          }
        }
        """
        
        result = query_subgraph(query, {'skip': skip, 'first': first})
        conditions = result['data']['conditions']
        
        if not conditions:
            break
        
        all_conditions.extend(conditions)
        skip += first
        
        if len(conditions) < first:
            break
    
    return all_conditions

限制

注意事項
  1. 查詢限制:單次查詢最多返回 1000 條記錄
  2. 速率限制:公共端點有速率限制
  3. 延遲:Subgraph 可能有幾秒到幾分鐘的延遲
  4. 數據完整性:依賴於索引器的同步狀態

GraphQL Playground

你可以在 The Graph Explorer 中交互式地測試查詢:
https://thegraph.com/explorer/subgraph/polymarket/polymarket

下一步

參考資源