EQ وUQ وraw: صيغ عناوين TON ولماذا يرتدّ الإيداع
EQ وUQ وraw: صيغ عناوين TON، والفرق بين bounceable وnon-bounceable، ولماذا يرتدّ أول إيداع على محفظة جديدة عائدًا إلى المُرسِل.
يولّد المطوّر محفظةً جديدة، وينسخ العنوان، ويرسل إليه أول 5 GRAM للغاز — وبعد دقيقة تعود العملات إلى المحفظة المُرسِلة. ورصيد العنوان الجديد: صفر. لا خطأ، ولا «reverted»، والمعاملة نجحت. الأموال ببساطة… ارتدّت. وفي مجموعات TON هذه شكوى كلاسيكية: «أرسلتُ إلى عنواني أنا — ولم يصل». والسبب في الغالب واحد: خلطٌ بين صيغ العنوان وعَلَم bounceable.
لنستعرض بالوقائع ما هي صيغ عناوين TON — EQ وUQ وraw، وما الفرق بين bounceable وnon-bounceable، ولماذا يعود أول إيداع على محفظة جديدة إلى المُرسِل. وسأريك في الأثناء كيف تتحقق من ذلك كله باستدعاء أداة واحدة من وكيل ذكاء اصطناعي، دون تركيب SDK ولا تشغيل عقدة.
ثلاث صيغ لعنوان TON: raw وEQ وUQ — ما الفرق
تحت غطاء أي عنوان في TON يقبع الشيء نفسه: رقم الـworkchain إضافةً إلى هاش بطول 256 بت لـstate init الخاص بالعقد. وهذه هي صيغة raw:
0:83dfd552e63729b472fcbcc8c45ebcc6691702558b68ec7527e1ba403a0f31a8
فعلى يسار النقطتين الـworkchain (وعادةً 0 وهو الأساسي، و-1 هو الـmasterchain)، وعلى يمينها الهاش بطول 256 بت بصيغة hex. صيغة صريحة لا لبس فيها، لكنها بلا مجموع تحقّق: تخطئ في محرف واحد فتحصل على عنوان آخر يبدو صالحًا. وصيغة raw تحديدًا هي ما تنتظره عادةً دوال get في العقود والأدوات منخفضة المستوى، أما المستخدمون فنادرًا ما تُعرض عليهم.
والتمثيل الثاني هو user-friendly: تلك المحارف الـ48 بترميز base64url التي تراها في المحافظ ومستكشفات البلوكتشين:
EQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqB2N (bounceable)
UQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqEBI (non-bounceable)
وهو يضمّ الزوج نفسه «workchain + هاش»، إضافةً إلى بايت أعلام ومجموع تحقّق CRC16 في النهاية. وCRC يلتقط الأخطاء المطبعية: فالعنوان التالف لا يجتاز التحقق أصلًا قبل الإرسال. ومن بايت الأعلام هذا تحديدًا تنشأ البادئتان EQ وUQ.
والأهم أن تستوعب هذا فورًا:
- raw وuser-friendly طريقتان لكتابة العنوان نفسه.
- EQ وUQ صيغتان لعنوان user-friendly واحد، لا تختلفان إلا في عَلَم واحد بالضبط.
أي أن EQ… وUQ… لمحفظة واحدة تشيران إلى هاش raw واحد بعينه، والعقد نفسه، والرصيد نفسه. فليستا محفظتين مختلفتين ولا حسابين مختلفين. والفرق كامنٌ في بتّ واحد يعبّر عن نيّة المُرسِل.
bounceable (EQ) مقابل non-bounceable (UQ): ماذا يعني العَلَم
بايت الأعلام ذاك داخل العنوان user-friendly هو ما يحدّد البادئة:
| العَلَم | الوسم | البادئة (mainnet) | البادئة (testnet) |
|---|---|---|---|
| bounceable | 0x11 |
EQ |
kQ |
| non-bounceable | 0x51 |
UQ |
0Q |
وفي شبكة الاختبار يُضاف 0x80 إلى الوسم — ومن هنا جاءت البادئتان الغريبتان kQ و0Q. لكن ما يعنينا هو معنى العَلَم، لا حساب الأوسام.
bounceable (EQ) تعني حرفيًا: «إن ساء شيء ما في الطرف المستقبِل — فأعِد العملات إليّ». وهي حماية للعقود الذكية. فحين ترسل أموالًا إلى عقد يُفترض أن يعالجها، لكنه يفشل بخطأ، أو لم يُنشر بعد، أو لم يكفِه الغاز — فأنت لا تريد أن تعلق العملات في الفراغ. وآلية bounce تعيدها إلى المُرسِل بعد خصم العمولة.
non-bounceable (UQ) تعني العكس: «سلّم واترك، مهما كان الحال». لا إعادة على الإطلاق — العملات تستقرّ على العنوان وحسب.
وفي التحويلات اليومية بين الأشخاص لا يكاد الفرق يُلاحَظ — إلى أن نصل إلى حالة واحدة بعينها.
لماذا يرتدّ أول إيداع على محفظة غير منشورة
وهذه هي المصيدة تحديدًا. ففي TON يوجد عنوان المحفظة قبل أن يُنشر عقد المحفظة فعليًا في البلوكتشين. فالعنوان هاش حتمي مشتقّ من كود العقد وبياناته الابتدائية (المفتاح العام)، ولذلك تعرفه فور توليد العبارة السرّية (mnemonic) دون اتصال بالشبكة إطلاقًا. لكن قبل أن تمرّ على العنوان أول معاملة، يبقى الحساب في حالة uninit (غير مُهيّأ): العنوان موجود، أما كود العقد فلا وجود له.
والآن انظر ما الذي يجري في تحويل bounceable:
- ترسل إلى عنوان uninit هذا تحويلًا بصيغة EQ (bounceable).
- تحاول الشبكة تسليم العملات و«استدعاء» العقد المستقبِل. لكن لا أحد يستقبلها — فلا عقد على العنوان.
- تنطلق آلية bounce: ما دام التسليم قد فشل، فالعملات تعود إلى المُرسِل بعد خصم العمولة.
والنتيجة هي ذلك «الارتداد» عينه. المعاملة نجحت، لكن رصيد المحفظة الجديدة بقي صفرًا، والأموال عادت من حيث أتت. لم يسرق أحد شيئًا، والشبكة عملت تمامًا كما صُمّمت — أنت فقط استخدمت صيغة bounceable في موضع ما كان ينبغي أن تستخدمها فيه.
وماذا لو أُرسل التحويل نفسه بصيغة UQ (non-bounceable)؟
- تحاول الشبكة تسليم العملات إلى عنوان uninit.
- آلية bounce معطّلة بالعَلَم — فلا حاجة إلى الإعادة.
- العملات تبقى على العنوان، رغم أن العقد لم يُنشر بعد.
وهكذا تكون المحفظة قد شُحنت. ولاحقًا، حين ترسل منها أول معاملة صادرة، سيُنشر معها كود العقد — ويصبح الحساب active. ومن تلك اللحظة يستقبل بلا قلق أي تحويل، بما في ذلك bounceable. فقاعدة UQ حاسمة لأول إيداع فقط في محفظة لم تُنشر بعد.
والخبر السار أن المنظومة تسدّ هذه الثغرة تدريجيًا نيابةً عن المستخدم. فمحافظ v5r1 وعددٌ من التطبيقات تعرض العنوان افتراضيًا بصيغة non-bounceable (UQ) تحديدًا — كي لا يفقد المبتدئ أول إيداع. لكن ما إن تتعامل مع العناوين برمجيًا — من الخادم الخلفي، أو من سكربت، أو من وكيل ذكاء اصطناعي — حتى تعود مسؤولية العَلَم إليك.
كيف ترسل أول تحويل بشكل صحيح: UQ بدل EQ
والقاعدة العملية تتلخّص في سطر واحد:
أول إيداع على محفظة جديدة (uninit) يكون دائمًا على UQ. وبعد ذلك افعل ما شئت.
وأما المنطق المفصّل لأي خدمة ترسل أموالًا إلى المستخدم:
- عنوان المستلم في حالة uninit ← أرسل على UQ (non-bounceable).
- العنوان active ← يمكن الإرسال على EQ (bounceable).
- ترسل إلى عقد ذكي (DEX، أو jetton minter، أو escrow) ← EQ، كي تعود الأموال عند الخطأ.
والمشكلة أن EQ لا تختلف عن UQ «بالعين المجرّدة» إلا بمحرف واحد في البادئة، أما حالة uninit/active فلا تظهر من العنوان إطلاقًا. وكِلا الفحصين لا بدّ أن يتمّ برمجيًا. وهنا لست مضطرًا إلى إضافة @ton/ton إلى مشروعك، وتشغيل مزوّد، وتفكيك الخلايا (cells) — فكلا السؤالين تحسمهما أداتان من خادم MCP، يستدعيهما وكيل الذكاء الاصطناعي بنفسه.
وإن كان موضوع توليد المحفظة وأول إيداع فيها جديدًا عليك — فله شرح مستقل في دليل إنشاء محفظة TON.
parse_address: تحويل العناوين والتحقق منها دون اتصال باستدعاء واحد
parse_address أداة تعمل دون اتصال من TONNode، خادم MCP المُستضاف لشبكة TON. تفكّ ترميز العنوان، وتعيد حساب الصيغ، وتتحقق من CRC16، دون أي اتصال بالشبكة: فهي لا تحتاج عقدة ولا مفتاحًا — إنها رياضيات صرفة على سلسلة نصية، ولذلك فورية ولا تستهلك من حصّة الطلبات.
وما تجيده:
- تحويل
EQ ⇄ UQ ⇄ rawفي أي اتجاه؛ - التحقق من صلاحية العنوان (هل يتطابق مجموع التحقق)؛
- إظهار عَلَم bounceable ورقم الـworkchain.
وMCP (أي Model Context Protocol) معيارٌ يتيح لوكلاء الذكاء الاصطناعي (Claude، وCursor، وChatGPT/Codex، وأي عميل MCP) استدعاء الأدوات. ويُوصَل خادم MCP بإدخال واحد في إعدادات العميل. وهذه هي النسخة المحلية المجانية بمجموعة أدوات القراءة كاملةً:
{
"mcpServers": {
"ton": {
"command": "npx",
"args": ["-y", "@tonnode/mcp"]
}
}
}
ثم يكفي الوكيلَ أمرٌ نصي عادي:
خذ العنوان
EQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqB2Nوأظهره بصيغتَي non-bounceable (UQ) وraw. وتحقق من صلاحية مجموع التحقق.
فيستدعي الوكيل parse_address ويعيد نسخة UQ للمحفظة نفسها، وهاش raw، وحالة الصلاحية. دون أي تلاعب يدوي بترميز base64url ولا خطر الخطأ المطبعي في 48 محرفًا.
get_account_state: كيف تعرف إن كانت المحفظة منشورة قبل الإرسال
ولا تنتهي المسألة عند الصيغة — إذ عليك أن تعرف كذلك في أي حالة العنوان: active أم uninit. وهذا سؤال أون-تشين، ويجيب عنه get_account_state. فالأداة تعيد حالة الحساب، والأعلام، وبيانات آخر معاملة.
والمنطق قبل إرسال أول تحويل:
- أعاد
get_account_stateالقيمة uninit ← العنوان لم يُنشر بعد ← نرسل على UQ. - أعاد active ← المحفظة منشورة ← يمكن الإرسال بلا قلق على EQ.
والأمر النصي للوكيل:
تحقق عبر get_account_state إن كان العنوان
UQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqEBIمنشورًا. وإن كانت الحالة uninit — فذكّرني بأن أول إيداع يجب أن يُرسل بصيغة UQ.
وهكذا تتكوّن السلسلة: generate_wallet ينشئ المحفظة (بالإصدارات v3r2/v4/v5r1/highload_v3) ويسلّم العنوان الذي يكون لحظة الإنشاء uninit بشكل مضمون — فالشبكة لا تعرفه بعد. ومعنى ذلك أن أول إيداع عليه يذهب حصرًا على UQ. وقبل الإرسال يؤكّد get_account_state أن العنوان uninit فعلًا، ويضمن parse_address أنك أخذت التمثيل non-bounceable تحديدًا. ومن المفيد بعد الإيداع استدعاء get_balance للتأكد من أن العملات استقرّت على العنوان ولم ترتدّ.
ونقطة مهمة بشأن التوليد: generate_wallet يعيد العبارة السرّية والمفاتيح والعنوان إلى المستخدم — فالخادم لا يخزّنها ولا يوقّع شيئًا نيابةً عنك. وهذه آلية غير احتجازية، وهي سارية على كل أدوات المبادلة والعمليات عبر السلاسل والمحفظة.
توضيح اصطلاحي صغير: GRAM هي Toncoin بعد إعادة التسمية (أُعيدت التسمية في يونيو 2026)، أما الشبكة نفسها فما زالت تُسمّى TON.
قائمة تحقّق: كيف لا تفقد أول إيداع على TON
خوارزمية قصيرة لكل تحويل أول إلى محفظة جديدة:
- ولّدتَ العنوان (
generate_walletأو الـSDK الخاص بك) — اعتبره uninit افتراضيًا. - تحقق من الحالة عبر
get_account_state:uninitأمactive. - إن كانت uninit — حوّل عنوان المستلم إلى UQ عبر
parse_addressوأرسل أول إيداع إليه وحده. - إن كانت active — يمكن استخدام
EQ، بل هي مفضّلة للعقود. - إلى العقود الذكية أرسل دائمًا bounceable (
EQ)، كي تعود الأموال عند الإخفاق. - بعد الإيداع تحقق عبر
get_balance— يجب أن تكون العملات قد استقرّت على العنوان لا أن تكون قد ارتدّت. - تذكّر:
EQوUQهما المحفظة نفسها (هاش raw واحد)؛ فأنت لا تختار عنوانًا، بل تختار سلوكًا عند فشل التسليم.
وكلا الفحصين الأساسيين — parse_address (دون اتصال) وget_account_state (أون-تشين) — متاحان فورًا، دون بنية تحتية خاصة بك. خذ مفتاح Hobby المجاني (60 طلبًا/دقيقة، دون بطاقة بنكية) واستدعِ الأداتين مباشرةً من وكيل الذكاء الاصطناعي: https://tonnode.io/dashboard?plan=hobby.
وبالنهج نفسه يسهل بعدها حلّ مهام مجاورة: التقاط مدفوعات USDT الواردة على TON، أو قراءة رصيد USDT باستدعاء واحد، أو استدعاء دالة get في عقد دون SDK. فصيغ العناوين هي الأساس الذي يقوم عليه كل ما سواه: افهم EQ/UQ مرة واحدة — ولن يباغتك الإيداع «المرتدّ» بعدها أبدًا.
امنح وكيلك الوصول إلى TON
16 أداة MCP: قراءة ومبادلات غير وصائية وعبر السلاسل ومحافظ. الباقة المجانية — 60 طلب/دقيقة، بلا بطاقة.