Туторіал ботів Полімаркет · Розділ 9 з 32
Читаємо ончейн-дані Полімаркет безпосередньо: баланси USDC/pUSD, читання контракту CTF для емісії результатів, події Оптимістичного оракула UMA щодо пропозицій/спорів, а також логи транзакцій Polygon - з кодом.
Що охоплює цей розділ
API Полімаркет зручні, але зрештою є лише зрештою узгодженими. Чейн - це джерело істини. У цьому розділі розбираємо ончейн-читання, які бот у продакшені використовує, щоб перевіряти власний облік: баланси pUSD, інвентар токенів результатів, події спорів UMA та стан контракту CTF. Підхід, до якого сходяться більшість ботів у продакшені, - «спершу API» для швидкості плюс періодична ончейн-звірка для коректності.
- Що живе ончейн (проти CLOB)
- Адреса контракту pUSD та ABI
- Conditional Tokens Framework (CTF)
- Оптимістичний оракул UMA: події пропозицій і спорів
- Читання логів подій Polygon (web3.py / ethers)
- Коли читати ончейн, а коли довіряти API
- Код: визначити спір UMA через підписку на події
Що живе ончейн (проти CLOB)
Дві машини станів, дві правди.
Ончейн (Polygon): баланси pUSD, інвентар токенів результатів (емісія ERC-1155 на кожен токен), схвалення дозволу, події пропозиції та спору в Оптимістичному оракулі UMA, події депозиту й виведення. З часом усе стає коректним; затримка становить один блок Polygon - приблизно 2 секунди.
CLOB (API Полімаркет): книга замовлень, нещодавні угоди, очікувані лімітні ордери, підтвердження зведень. У реальному часі, але зрештою узгоджений - зведення підтверджується раніше, ніж розраховується ERC-1155, що й породжує проблему фантомного виконання, описану в розділі 12.
Узгодження між ними має зрештою відбуватися завжди. Коли вони розходяться, чейн є джерелом істини. Бот, який довіряє лише CLOB, дрейфуватиме; бот, який довіряє лише чейну, торгуватиме повільно. Код продакшену використовує обидва: CLOB - для рішень, чутливих до швидкості, чейн - для періодичної звірки.
Адреса контракту pUSD та ABI
pUSD - це обгортка стейблкоїна Полімаркет, яка використовується з міграції V2 у 2026 році. Контракт за адресою 0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB в основній мережі Polygon є стандартним ERC-20.
Три важливі читання для бота:
balanceOf(proxy)- ваш доступний для витрат pUSD. Порівнюйте з тим, як CLOB бачить ваш баланс, при кожному перезапуску.allowance(proxy, exchange_contract)- чи можуть контракти біржі CTF/NegRisk витрачати ваш pUSD. Потрібно для зведення ордерів.- Підписка на подію
Transfer- виявляє депозит і виведення без опитування.
USDC (0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174) і далі лишається парою для виведення. Більшості ботів потрібні лише читання pUSD; USDC важливий тільки під час циклів депозиту/виведення.
Фреймворк умовних токенів (CTF)
Частки результатів - це токени ERC-1155, які випускає Gnosis Conditional Tokens Framework (CTF). Контракт CTF у Polygon за адресою 0x4D97DCd97eC945f40cF65F87097ACe5EA0476045 відстежує емісію для кожного position-id.
Три читання:
balanceOf(proxy, position_id)- скільки токенів результату ви фактично тримаєте для цього «ринок+результат».getOutcomeSlotCount(condition_id)- кількість результатів (2 для бінарного, N для мультирезультатного).payoutNumerators,payoutDenominator- встановлюються, коли UMA врегульовує ринок. Читаючи їх, ви дізнаєтеся, яка сторона виграла, ще до оновлення інтерфейсу в CLOB.
Position_id - це hash від (condition_id, outcome_index). Обчислюйте його на клієнті через хелпер getPositionId у CTF або відтворіть keccak-математику у своєму стеку.
Оптимістичний оракул UMA: події пропозицій і спорів
Оптимістичний оракул (OO) від UMA обробляє все врегулювання спорів Полімаркет. Є дві події, на які ваш бот може підписатися.
ProposePrice(requester, identifier, timestamp, ancillaryData, proposer, proposedPrice)- спрацьовує, коли бот Полімаркет пропонує результат.DisputePrice(requester, identifier, timestamp, ancillaryData, disputer)- спрацьовує, коли хтось оскаржує запропонований результат.
Адреса контракту OO: 0xeE3Afe347D5C74317041E2618C49534dAf887c24. Фільтруйте за адресою замовника Полімаркет.
Навіщо підписуватися: спір означає, що врегулювання тепер оскаржується і потребуватиме голосування UMA протягом 24-72 годин. У цей період ринок може бути призупинений для торгівлі. Бот, який тримає позиції в оспорюваному ринку, має знати про це негайно.
Читання логів подій Polygon (web3.py / ethers)
Дві референсні реалізації.
Python (web3.py):
from web3 import Web3
w3 = Web3(Web3.HTTPProvider(POLYGON_RPC))
ctf = w3.eth.contract(address=CTF_ADDR, abi=CTF_ABI)
filter = ctf.events.PayoutRedemption.create_filter(fromBlock="latest")
for event in filter.get_new_entries():
print(event["args"])
Node (ethers v6):
import { ethers } from "ethers";
const p = new ethers.JsonRpcProvider(POLYGON_RPC);
const ctf = new ethers.Contract(CTF_ADDR, CTF_ABI, p);
ctf.on("PayoutRedemption", (redeemer, collateral, parentId, conditionId) => {
console.log("redemption", { redeemer, conditionId });
});
Для безперервного моніторингу використовуйте транспорт WebSocket (wss://...) замість опитування HTTP - менше запитів і швидша доставка. Більшість платних провайдерів RPC включають WebSocket у початкові тарифи.
Коли читати ончейн, а коли довіряти API
Практичні правила з продакшену.
- Довіряйте API для: книги замовлень у реальному часі, нещодавніх угод, ваших власних очікуваних ордерів, метаданих ринку (slug, question, дата завершення), виявлення подій/ринків.
- Довіряйте чейну для: вашого власного балансу pUSD, вашого власного інвентарю токенів результатів, перевірки депозиту й виведення, результатів врегулювання, стану спору.
- Перевіряйте обидва для: будь-якої фінансової дії, яку бот записав як виконання - зіставляйте подію API «matched» з переказом CTF у чейні, щоб підтвердити розрахунок.
Правило 5 секунд очікування після купівлі (розділ 12) - це ончейн-реальність, що втручається в час API. Продаж GTC, поданий одразу після ринкової купівлі, побачить balance: 0 у перевірці чейну, навіть якщо CLOB щойно підтвердив зведення.
Код: визначити спір UMA через підписку на події
Приклад: відстежуйте пов'язані з Полімаркет спори UMA в реальному часі.
from web3 import Web3
w3 = Web3(Web3.WebsocketProvider(POLYGON_WSS))
oo = w3.eth.contract(address=UMA_OO_ADDR, abi=UMA_ABI)
POLY_REQUESTER = "0x..." # Полімаркет's UMA requester address
def on_dispute(event):
args = event["args"]
if args["requester"].lower() != POLY_REQUESTER.lower(): return
print(f"DISPUTE on Полімаркет market: ancillary={args['ancillaryData'][:40]}...")
# decode ancillaryData to recover the market question
event_filter = oo.events.DisputePrice.create_filter(fromBlock="latest")
while True:
for ev in event_filter.get_new_entries():
on_dispute(ev)
time.sleep(2)
Поле ancillaryData - це hex-кодований JSON-подібний текст, що містить питання ринку. Його декодування дає вам ідентифікатор, еквівалентний slug, щоб зіставити його з вашими відкритими позиціями.


