מדריך בוט Polymarket · פרק 9 מתוך 32
קראו נתוני on-chain של Polymarket ישירות: יתרות USDC/pUSD, קריאות מחוזה CTF עבור היצע התוצאות, אירועי proposed/disputed של UMA Optimistic Oracle, ולוגים של טרנזקציות ב-Polygon - עם קוד.
מה מכסה הפרק הזה
ה-API של Polymarket נוח, אבל הוא eventually consistent. ה-chain הוא הסמכות. הפרק הזה עובר על קריאות ה-on-chain שבוט פרודקשן משתמש בהן כדי לאמת את הנהלת החשבונות שלו עצמו: יתרות pUSD, מלאי טוקני תוצאות, אירועי מחלוקת של UMA, ומצב חוזה CTF. הדפוס שרוב בוטי הפרודקשן מתכנסים אליו הוא API-first למהירות, יחד עם reconciliation תקופתי על ה-chain לצורך דיוק.
- מה חי על ה-chain (לעומת ב-CLOB)
- כתובת חוזה pUSD ו-ABI
- Conditional Tokens Framework (CTF)
- UMA Optimistic Oracle: אירועי proposed ו-disputed
- קריאת event logs ב-Polygon (web3.py / ethers)
- מתי לקרוא מה-chain ומתי לסמוך על ה-API
- קוד: זיהוי מחלוקת של UMA באמצעות event subscription
מה חי על ה-chain (לעומת ב-CLOB)
שתי מכונות מצב, שתי אמיתות.
On-chain (Polygon): יתרות pUSD, מלאי טוקני תוצאות (היצע ERC-1155 לכל טוקן), approvals של allowance, אירועי proposals ו-disputes ב-UMA Optimistic Oracle, ואירועי הפקדה ומשיכה. נכון בסופו של דבר; ה-latency הוא בלוק אחד ב-Polygon, בערך 2 שניות.
CLOB (Polymarket API): order book, עסקאות אחרונות, orders מוגבלים ממתינים, ואישורי match. בזמן אמת אבל eventually consistent - ה-match מאושר לפני שה-ERC-1155 נסגר, וזה יוצר את בעיית phantom-fill שמכוסה בפרק 12.
השניים צריכים תמיד להתכנס. כשיש ביניהם סטייה, ה-chain הוא הסמכות. בוט שסומך רק על ה-CLOB יסטה; בוט שסומך רק על ה-chain יסחור לאט. קוד פרודקשן משתמש בשניהם: CLOB להחלטות קריטיות למהירות, chain ל-reconciliation תקופתי.
כתובת חוזה pUSD ו-ABI
pUSD הוא ה-stablecoin wrapper של Polymarket, בשימוש מאז ה-migration של V2 ב-2025. החוזה ב-Polygon mainnet בכתובת 0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB הוא ERC-20 סטנדרטי.
שלוש קריאות שחשובות לבוט:
balanceOf(proxy)- ה-pUSD הזמין שלכם להוצאה. השוו מול התצוגה של ה-CLOB על היתרה שלכם בכל restart.allowance(proxy, exchange_contract)- האם חוזי ה-CTF/NegRisk exchange יכולים להשתמש ב-pUSD שלכם. נדרש לצורך התאמת orders.Transferevent subscription - מזהה הפקדות ומשיכות בלי polling.
USDC (0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174) נשאר צמד ה-off-ramp. רוב הבוטים צריכים רק קריאות pUSD; USDC רלוונטי רק במהלך מחזורי הפקדה/משיכה.
Conditional Tokens Framework (CTF)
מניות התוצאה הן טוקני ERC-1155 שמוטבעים על ידי Conditional Tokens Framework (CTF) של Gnosis. חוזה ה-CTF ב-Polygon בכתובת 0x4D97DCd97eC945f40cF65F87097ACe5EA0476045 עוקב אחרי ההיצע לכל position-id.
שלוש קריאות:
balanceOf(proxy, position_id)- כמה טוקני תוצאה באמת מחזיקים עבור אותו market+outcome.getOutcomeSlotCount(condition_id)- מספר התוצאות (2 לבינארי, N ל-multi-outcome).payoutNumerators,payoutDenominator- נקבעים כשה-UMA פותר את ה-market. קריאתם אומרת לכם איזה צד ניצח לפני שה-UI של ה-CLOB מתעדכן.
ה-position_id הוא hash של (condition_id, outcome_index). חשבו אותו בצד הלקוח באמצעות helper של getPositionId של ה-CTF, או שחזרו את חישוב ה-keccak ב-stack שלכם.
UMA Optimistic Oracle: אירועי proposed ו-disputed
ה-Optimistic Oracle (OO) של UMA מטפל בכל הליך פתרון המחלוקות של Polymarket. שני אירועים שכדאי לבוט להירשם אליהם.
ProposePrice(requester, identifier, timestamp, ancillaryData, proposer, proposedPrice)- מופעל כאשר בוט של Polymarket מציע תוצאה.DisputePrice(requester, identifier, timestamp, ancillaryData, disputer)- מופעל כאשר מישהו מערער על התוצאה המוצעת.
כתובת חוזה ה-OO: 0xeE3Afe347D5C74317041E2618C49534dAf887c24. סננו לפי כתובת ה-requester של Polymarket.
למה להירשם: מחלוקת אומרת שה-resolution עכשיו שנוי במחלוקת ויידרש עליו vote של UMA במשך 24-72 שעות. במהלך החלון הזה, ייתכן שה-market ייעצר למסחר. בוט שמחזיק פוזיציות ב-market שנוי במחלוקת צריך לדעת זאת מיד.
קריאת event logs ב-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 transport (wss://...) במקום HTTP polling - פחות requests ואספקה מהירה יותר. רוב ספקי ה-RPC בתשלום כוללים WebSocket ב-tierים הראשונים.
מתי לקרוא מה-chain ומתי לסמוך על ה-API
כללים מעשיים מהפרודקשן.
- סמכו על ה-API עבור: order book בזמן אמת, עסקאות אחרונות, ה-orders הממתינים שלכם, metadata של ה-market (slug, question, end date), discovery של events/markets.
- סמכו על ה-chain עבור: יתרת pUSD שלכם, מלאי טוקני התוצאה שלכם, אימות של הפקדות ומשיכות, תוצאות resolution, מצב מחלוקת.
- בצעו cross-check לשניהם עבור: כל דבר פיננסי שה-bot רשם כ-fill - התאימו את אירוע ה-"matched" של ה-API ל-transfer של ה-CTF ב-chain כדי לאמת settlement.
כלל ההמתנה של 5 שניות אחרי קנייה (פרק 12) הוא מציאות ה-on-chain שחודרת אל זמן ה-API. sell מסוג GTC שנשלח מיד אחרי קנייה ב-market יראה balance: 0 בבדיקת ה-chain, למרות שה-CLOB התאים לפני רגע.
קוד: זיהוי מחלוקת של UMA באמצעות event subscription
הפניה: מעקב בזמן אמת אחרי מחלוקות UMA הקשורות ל-Polymarket.
from web3 import Web3
w3 = Web3(Web3.WebsocketProvider(POLYGON_WSS))
oo = w3.eth.contract(address=UMA_OO_ADDR, abi=UMA_ABI)
POLY_REQUESTER = "0x..." # Polymarket's UMA requester address
def on_dispute(event):
args = event["args"]
if args["requester"].lower() != POLY_REQUESTER.lower(): return
print(f"DISPUTE on Polymarket 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 הוא טקסט בסגנון JSON שמקודד בהקס, ומכיל את שאלת ה-market. פענוח שלו נותן לכם את המזהה המקביל ל-slug כדי לבצע cross-reference מול הפוזיציות הפתוחות שלכם.












