還沒有帳號?點擊這裡註冊 Polymarket 並完成入金,才能用錢包私鑰為訂單籤名、實際成交。
法律合規提醒:在使用 Polymarket 服務或 API 前,請確認您所在地區的法律規定。Polymarket 目前不支援比利時、法國、新加坡、泰國、中國大陸等地區,政策可能隨時變化。
什麼是 Subgraph?
Subgraph 是基於 The Graph 協議構建的索引服務,它:- 📊 索引區塊鏈數據
- ⚡ 提供快速查詢
- 🔍 支援複雜的數據關係
- 🆓 免費使用
The Graph 是一個去中心化的索引協議,用於組織區塊鏈數據並使其易於訪問。
Polymarket Subgraph
Polymarket 維護了官方的 Subgraph,索引了:- 條件代幣合約數據
- 市場創建和結算
- 用戶頭寸和交易
- 條件 ID 和位置 ID
Subgraph 端點
Polygon 主網:Copy
https://api.thegraph.com/subgraphs/name/polymarket/polymarket
為什麼使用 Subgraph?
相比直接查詢區塊鏈,Subgraph 提供:| 特性 | 直接查詢區塊鏈 | 使用 Subgraph |
|---|---|---|
| 速度 | 慢 | 快 |
| 複雜查詢 | 困難 | 簡單 |
| 歷史數據 | 需要掃描所有區塊 | 已索引 |
| 關係查詢 | 需要多次調用 | 一次查詢 |
| 成本 | 需要大量 RPC 調用 | 免費 |
GraphQL 查詢示例
查詢市場信息
Copy
query {
conditions(first: 5, orderBy: createdTimestamp, orderDirection: desc) {
id
oracle
questionId
outcomeSlotCount
resolved
payouts
createdTimestamp
}
}
查詢用戶頭寸
Copy
query UserPositions($userAddress: String!) {
userPositions(where: { user: $userAddress }) {
id
position {
id
conditionIds
}
balance
wrappedBalance
}
}
查詢特定條件
Copy
query Condition($conditionId: String!) {
condition(id: $conditionId) {
id
oracle
questionId
outcomeSlotCount
resolved
resolveTimestamp
payouts
positions {
id
collateralToken
indexSets
}
}
}
Python 使用示例
Copy
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("---")
查詢用戶頭寸
Copy
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 使用示例
Copy
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. 分頁查詢
Copy
query PaginatedConditions($skip: Int!, $first: Int!) {
conditions(
first: $first
skip: $skip
orderBy: createdTimestamp
orderDirection: desc
) {
id
questionId
resolved
}
}
2. 過濾查詢
Copy
query ResolvedConditions {
conditions(where: { resolved: true }) {
id
resolveTimestamp
payouts
}
}
3. 關係查詢
Copy
query ConditionWithPositions($conditionId: String!) {
condition(id: $conditionId) {
id
positions {
id
indexSets
userPositions {
user {
id
}
balance
}
}
}
}
數據模型
Condition(條件)
Copy
type Condition {
id: ID! // 條件 ID
oracle: Bytes! // Oracle 地址
questionId: Bytes! // 問題 ID
outcomeSlotCount: BigInt! // 結果數量
resolved: Boolean! // 是否已解決
resolveTimestamp: BigInt // 解決時間戳
payouts: [BigInt!] // 支付向量
positions: [Position!]! // 相關頭寸
createdTimestamp: BigInt! // 創建時間戳
}
Position(頭寸)
Copy
type Position {
id: ID! // 頭寸 ID
collateralToken: CollateralToken! // 抵押品代幣
conditionIds: [Bytes!]! // 條件 ID 列表
indexSets: [BigInt!]! // 索引集
userPositions: [UserPosition!]! // 用戶頭寸
}
UserPosition(用戶頭寸)
Copy
type UserPosition {
id: ID! // 用戶頭寸 ID
user: User! // 用戶
position: Position! // 頭寸
balance: BigInt! // 餘額
wrappedBalance: BigInt! // 包裝餘額
}
實用工具
監控市場結算
Copy
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. 限制欄位
只查詢需要的欄位:Copy
# ✗ 差:查詢所有欄位
query {
conditions(first: 100) {
id
oracle
questionId
outcomeSlotCount
resolved
resolveTimestamp
payouts
positions {
id
# ... 很多欄位
}
}
}
# ✓ 好:只查詢需要的欄位
query {
conditions(first: 100) {
id
resolved
}
}
2. 使用分頁
Copy
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
限制
注意事項:
- 查詢限制:單次查詢最多返回 1000 條記錄
- 速率限制:公共端點有速率限制
- 延遲:Subgraph 可能有幾秒到幾分鐘的延遲
- 數據完整性:依賴於索引器的同步狀態
GraphQL Playground
你可以在 The Graph Explorer 中交互式地測試查詢:Copy
https://thegraph.com/explorer/subgraph/polymarket/polymarket
下一步
參考資源
- The Graph 文檔:https://thegraph.com/docs
- GraphQL 教程:https://graphql.org/learn/
- Polymarket Subgraph:https://thegraph.com/explorer/subgraph/polymarket/polymarket