دليل Polymarket Bot · الفصل 9 من 32
اقرأ بيانات Polymarket على السلسلة مباشرة: أرصدة USDC/pUSD، وقراءات عقد CTF لعرض إجمالي المعروض من النتائج، وأحداث UMA Optimistic Oracle المقترحة والمتنازع عليها، وسجلات معاملات Polygon - مع الكود.
ما الذي يغطيه هذا الفصل
واجهات Polymarket البرمجية APIs مريحة لكنها تتسم في النهاية بالتناسق المتأخر eventually consistent. أما السلسلة فهي المرجع النهائي. يستعرض هذا الفصل عمليات القراءة من السلسلة التي يستخدمها bot في بيئة الإنتاج للتحقق من سجلاته الداخلية: أرصدة pUSD، ومخزون رموز النتائج، وأحداث نزاعات UMA، وحالة عقد CTF. النمط الذي تنتهي إليه معظم bots في الإنتاج هو الاعتماد أولًا على API للسرعة، ثم إجراء تسوية دورية مع السلسلة لضمان الدقة.
- ما الذي يوجد على السلسلة (مقابل CLOB)
- عنوان عقد pUSD وABI
- Conditional Tokens Framework (CTF)
- UMA Optimistic Oracle: الأحداث المقترحة والمتنازع عليها
- قراءة سجلات أحداث Polygon (web3.py / ethers)
- متى تقرأ من السلسلة ومتى تثق في API
- الكود: اكتشاف نزاع UMA عبر الاشتراك في الأحداث
ما الذي يوجد على السلسلة (مقابل CLOB)
هناك حالتا machine state، وهناك حقيقتان.
على السلسلة (Polygon): أرصدة pUSD، ومخزون رموز النتائج (عرض ERC-1155 لكل token)، وعمليات الموافقة allowance approvals، واقتراحات UMA Optimistic Oracle والنزاعات، وأحداث الإيداع والسحب. تكون صحيحة في النهاية؛ وزمن التأخير هو كتلة Polygon واحدة تقريبًا (~2 ثوانٍ).
CLOB (Polymarket API): دفتر الأوامر، والتداولات الأخيرة، وأوامر limit المعلقة، وإقرارات المطابقة match acknowledgments. في الزمن الحقيقي لكن مع تناسق متأخر eventually consistent - يتم تأكيد المطابقة قبل استقرار ERC-1155، ما ينتج مشكلة fill الشبح phantom-fill التي نغطيها في الفصل 12.
ينبغي أن يتقارب الاثنان دائمًا. وعندما يختلفان، تكون السلسلة هي المرجع النهائي. أي bot يعتمد فقط على CLOB سيتعرض للانحراف؛ وأي bot يعتمد فقط على السلسلة سيتداول ببطء. يستخدم كود الإنتاج الاثنين معًا: CLOB للقرارات الحساسة للسرعة، والسلسلة للتسوية الدورية والتأكد من الصحة.
عنوان عقد pUSD وABI
pUSD هو غلاف العملة المستقرة الخاص بـ Polymarket والمستخدم منذ ترحيل V2 في 2025. العقد الموجود على Polygon mainnet عند 0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB هو ERC-20 قياسي.
ثلاث قراءات مهمة لأي bot:
balanceOf(proxy)- رصيد pUSD القابل للإنفاق لديك. قارنه برؤية CLOB لرصيدك عند كل إعادة تشغيل.allowance(proxy, exchange_contract)- ما إذا كانت عقود exchange الخاصة بـ CTF/NegRisk تستطيع إنفاق pUSD الخاص بك. هذا مطلوب لمطابقة الأوامر.- الاشتراك في حدث
Transfer- يكتشف الإيداعات والسحوبات دون الحاجة إلى polling.
يبقى USDC (0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174) هو زوج الخروج off-ramp. معظم bots تحتاج فقط إلى قراءات pUSD؛ أما USDC فيهم فقط أثناء دورات الإيداع/السحب.
Conditional Tokens Framework (CTF)
حصص النتائج هي رموز ERC-1155 يتم سكّها بواسطة Conditional Tokens Framework (CTF) الخاص بـ Gnosis. عقد 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). احسبه من جهة العميل client-side عبر helper getPositionId الخاص بـ CTF أو أعد تنفيذ keccak math داخل stack الخاص بك.
UMA Optimistic Oracle: الأحداث المقترحة والمتنازع عليها
يتولى UMA Optimistic Oracle (OO) كل عمليات حل النزاعات في Polymarket. هناك حدثان قد ترغب في الاشتراك بهما في bot الخاص بك.
ProposePrice(requester, identifier, timestamp, ancillaryData, proposer, proposedPrice)- يُطلق عندما يقترح bot تابع لـ Polymarket نتيجة معينة.DisputePrice(requester, identifier, timestamp, ancillaryData, disputer)- يُطلق عندما يعترض أحدهم على النتيجة المقترحة.
عنوان عقد OO: 0xeE3Afe347D5C74317041E2618C49534dAf887c24. صفِّ الأحداث بحسب عنوان requester الخاص بـ Polymarket.
لماذا الاشتراك: النزاع يعني أن التسوية أصبحت محل اعتراض وستحتاج إلى تصويت UMA خلال 24-72 ساعة. خلال هذه النافذة قد يتم إيقاف السوق مؤقتًا عن التداول. يجب أن يعرف bot الذي يحمل مراكز في سوق متنازع عليه ذلك فورًا.
قراءة سجلات أحداث 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 - طلبات أقل وتسليم أسرع. معظم مزودي RPC المدفوعين يتضمنون WebSocket ضمن الخطط الابتدائية.
متى تقرأ من السلسلة ومتى تثق في API
قواعد عملية من بيئة الإنتاج.
- ثق في API من أجل: دفتر الأوامر في الزمن الحقيقي، والتداولات الأخيرة، وأوامرك المعلقة، وبيانات تعريف السوق (slug، السؤال، تاريخ الانتهاء)، واكتشاف الأحداث/الأسواق.
- ثق في السلسلة من أجل: رصيد pUSD الخاص بك، ومخزون رموز النتائج الخاص بك، والتحقق من الإيداع والسحب، ونتائج التسوية، وحالة النزاع.
- قارن بين الاثنين من أجل: أي شيء مالي سجله bot كـ fill - طابق حدث "matched" من API مع نقل CTF على السلسلة للتأكد من التسوية.
قاعدة انتظار 5 ثوانٍ بعد الشراء (الفصل 12) هي تدخل حقيقة السلسلة في زمن API. أي أمر GTC بيع يُرسل مباشرة بعد شراء في السوق سيُظهر balance: 0 من فحص السلسلة حتى لو كانت CLOB قد طابقت قبل لحظات.
الكود: اكتشاف نزاع UMA عبر الاشتراك في الأحداث
مرجع: راقب نزاعات 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 هو نص مشفّر hex ومنطقي الشكل JSON-ish يحتوي على سؤال السوق. يتيح لك فك ترميزه استرجاع المعرّف المكافئ لـ slug للمقارنة مع مراكزك المفتوحة.














