decimals الجيتون على TON: لماذا USDT = 6 وليس 9
نشرح decimals الجيتون على TON: لماذا USDT = 6 ومعظم الجيتونات = 9، وكيف يعيد get_jetton_info قيمة decimals، ولماذا يكسر الرقم الخاطئ الأرصدة والمبادلات
تكتب وكيلًا يعرض رصيد USDT. تسحب رصيد محفظة الجيتون فتحصل على 5000000، وتقسمه على 10^9 — فيظهر على الشاشة 0.005 USDT بدل 5 USDT الصادقة. المعاملات تمرّ، وRPC يستجيب، وget-method يعيد رقمًا — ومع ذلك أخطأ المبلغ بمقدار 1000 ضعف بالضبط. والذنب ذنبُ رقم واحد يكتبه الجميع تقريبًا ثابتًا في الكود بحكم العادة: decimals.
إن كنت توصّل وكيل ذكاء اصطناعي بشبكة TON أو تحسب مبالغ الجيتونات يدويًا، فإن decimals هو أول ما يجب أن تفهمه قبل أي رصيد أو مبادلة. لنستعرض لماذا لدى USDT قيمة decimals = 6 لا الـ 9 المألوفة في TON، ومن أين يأتي هذا الرقم أصلًا، وكيف تحصل عليه باستدعاء واحد دون تخمين.
decimals الجيتون على TON: الوحدات الخام في مقابل الرقم الذي يقرأه البشر
البلوكتشين لا يعرف تخزين الكسور. إطلاقًا. وعلى TON، كما في كل مكان تقريبًا، يوجد أي مبلغ داخل العقد بوصفه عددًا صحيحًا — أي ما يسمّى الوحدات الخام (أصغر وحدة غير قابلة للتجزئة). لا وجود لـ 5.5 في قاموس العقد ولا يمكن أن يوجد — بل عدد صحيح مثل 5500000 فحسب.
ولكي تحصل من هذا العدد الصحيح على المبلغ الذي يراه الإنسان، تحتاج إلى مقياس. وهذا المقياس هو decimals بعينه — أُسّ العشرة الذي أُزيح به العدد المخزَّن بالنسبة إلى المبلغ المقروء بشريًا:
human = raw / 10^decimals
raw = human * 10^decimals
والتشبيه بسيط. النقود في محفظتك بالدولارات، لكن محاسبة البنك تحسب كل شيء بالسنتات، بأعداد صحيحة: 100 سنت = 1 دولار، أي decimals = 2. فإن أردت أن تعرض للإنسان دولارات، قسّمت السنتات على 10^2 = 100. والأمر نفسه مع الجيتونات، لكن بأُسّ عشرة مختلف.
والنقطة الجوهرية: البلوكتشين نفسه لا يعرف أين تقع «الفاصلة» في الرقم. فهو يتعامل مع وحدات خام صحيحة. أما أين توضع الفاصلة عند العرض للمستخدم فقرارٌ يتخذه العميل بقراءة decimals من بيانات الجيتون الوصفية. أخطأت في decimals — انزاحت الفاصلة، وفقد المبلغ معناه تمامًا.
USDT decimals على TON = 6، ومعظم الجيتونات = 9
رقمان يجب حفظهما:
- USDT (Tether) على TON ←
decimals = 6. أي أن1 USDT = 1 000 000 وحدة خام. - معظم جيتونات TON الأخرى ←
decimals = 9. وهذه القيمة نفسها هي الافتراضية: فإن لم يُذكر حقلdecimalsفي البيانات الوصفية أصلًا، وجب على العميل بحكم المعيار أن يعتبره مساويًا لـ9.
ومن أين جاءت التسعة؟ إن GRAM نفسه (Toncoin سابقًا، أُعيدت تسميته في يونيو 2026 — أما الشبكة فما زالت تُسمّى TON) له 9 خانات: 1 GRAM = 10^9 نانوغرام، و«النانو» هنا هو الوحدة الخام بعينها. وقد ورث معيار جيتونات TON هذه القيمة بوصفها الافتراضية، فصارت الغالبية الساحقة من التوكنات في الشبكة تعيش بـ decimals = 9 تحديدًا. ويعتاد المطورون كتابة / 1e9 دون نظر.
أما USDT فضيف قادم من عالم Ethereum، حيث لـ Tether تاريخيًا 6 خانات. وقد أبقى المُصدِر على الدقة المعتادة في TON أيضًا. لذلك فإن USDT هو ذلك الاستثناء الذي يتعثّر به تقريبًا كل من «كتب 9 ثابتة في الكود» — وهو بالضبط أكثر الجيتونات تداولًا في المدفوعات.
لنحسب ثمن الخطأ. لنفترض أن في محفظة الجيتون 5 000 000 وحدة خام من USDT:
- الصواب (
decimals = 6):5 000 000 / 10^6 = 5 USDT؛ - الخطأ (
decimals = 9):5 000 000 / 10^9 = 0.005.
خطأ بمقدار 10^(9−6) = 1000 ضعف بالضبط. والعكس صحيح: إذا أدخل المستخدم «أرسل 5 USDT» وضربتَ أنت في 10^9، فستحاول تحريك ألف ضعف المبلغ. وبالنسبة إلى بوت مدفوعات، هذا هو الفرق بين «تمّ الدفع» و«مرفوض».
من أين يأتي decimals: بيانات الجيتون الوصفية ومعيار TEP-64
من المهم أن تفهم: decimals ليس حقلًا في كود المحفظة ولا ثابتًا في البروتوكول. إنه جزء من البيانات الوصفية لجيتون بعينه، الموصوفة في معيار TEP-64 (Token Data Standard). فكل جيتون يعلن بنفسه عن decimals الخاص به، واسمه، ورمزه، وصورته.
ويسمح TEP-64 بتخزين البيانات الوصفية بثلاث صيغ:
- on-chain — كل الحقول موجودة في قاموس (dictionary) داخل عقد الجيتون مباشرةً؛ ولا حاجة إلى تنزيل أي شيء؛
- off-chain — في العقد رابط (
uri) فقط، بينما JSON بكامل حقوله (name،symbol،decimals،image) موجود على هذا الـ URI على خادم ويب أو على IPFS؛ - semi-chain (هجينة) — جزء من الحقول في القاموس على السلسلة، وجزء عبر الـ
uri؛ فينزّل العميل المحتوى off-chain ويدمجه مع القيم المأخوذة من القاموس.
وقاعدة الدمج في TEP-64 كالتالي: إذا وُجد المفتاح uri في القاموس، وجب على العميل أن ينزّل المحتوى off-chain من الرابط وأن يدمجه مع القيم المأخوذة من القاموس على السلسلة. ولكل صيغة كلفة قراءة مختلفة: on-chain تُقرأ بـ get-method واحد، أما off-chain فتتطلب طلب HTTP إضافيًا. ومعالجة هذه الحالات الثلاث يدويًا متعة قائمة بذاتها — وهنا بالضبط يريحك أن تتولّى أداة واحدة الأمر نيابةً عنك.
بيانات USDT الوصفية: كيف يعيد get_jetton_info قيمة decimals = 6
يخزّن USDT على TON بياناته الوصفية بصيغة off-chain: ففي عقد ماستر الجيتون رابطٌ إلى JSON خارج السلسلة، وفي هذا الـ JSON نفسه دُوّنت name وsymbol، والأهم من ذلك كله decimals = 6. ولكي يجمّع العميل بطاقة الجيتون بصدق، عليه أن يقرأ العقد، ويستخرج الرابط، وينزّل الـ JSON منه، ويحلّل حقوله.
ولستَ مضطرًا إلى استحضار صيغة TEP-64 في ذهنك وتحليل خلايا القاموس يدويًا: فهذا بالضبط هو العمل الذي تتولّاه أداة واحدة. إذ يذهب get_jetton_info إلى العقد بنفسه، ويحلّل البيانات الوصفية، ويعيد decimals = 6 جاهزة — وعليها يُبنى الحساب كله.
كيف تحصل على decimals باستدعاء واحد: get_jetton_info
بدلًا من قراءة القاموس يدويًا، وتمييز الصيغة (on/off/semi-chain)، والذهاب إلى الـ URI، ودمج الـ JSON — هناك get_jetton_info. إنها أداة من خادم MCP التابع لـ TONNode: تستقبل عنوان عقد ماستر الجيتون وتعيد البيانات الوصفية مجمّعة — الاسم والرمز وdecimals والمعروض الكلي.
وTONNode خادم MCP مُستضاف لشبكة TON. أما MCP (Model Context Protocol) فهو المعيار الذي يستدعي عبره وكلاء الذكاء الاصطناعي (Claude وCursor وChatGPT/Codex وأي عميل MCP آخر) الأدوات. للربط مجانًا محليًا، مع مجموعة القراءة الكاملة:
{
"mcpServers": {
"ton": { "command": "npx", "args": ["-y", "@tonnode/mcp"] }
}
}
حزمة @tonnode/mcp مفتوحة المصدر (MIT)، وتعمل عبر بروتوكول ADNL الأصلي في TON، دون طبقات HTTP وسيطة. وبعدها يكفي الوكيلَ طلبٌ عادي بلغة البشر:
عبر أداة
get_jetton_infoاعرف قيمةdecimalsلجيتون USDT على TON (عنوان عقد الماستر هو كذا) واحسب كم تساوي بالـ USDT المقروءة بشريًا لرصيد قدره 5 000 000 وحدة خام.
سيعيد get_jetton_info القيمة decimals = 6، وعليها — لا على افتراض — يُبنى كل ما يلي من حساب. والاستدعاء نفسه لأي جيتون آخر سيعيد قيمته الخاصة (9 في الغالب، لكن التحقق واجب دائمًا). والقاعدة الأهم:
لا تكتب
9ثابتة في الكود. اقرأdecimalsمنget_jetton_infoلكل جيتون على حدة.
ستنجح التسعة مع معظم التوكنات وستنكسر بصمت مع USDT — وهو بالضبط الجيتون الذي تدور فيه أموال حقيقية في أغلب الأحيان. أما لماذا يحتاج وكيل الذكاء الاصطناعي أصلًا إلى وصول MCP مخصّص إلى TON بدل RPC عام محدود، فمشروح في مقال خادم MCP للوكلاء على TON.
لماذا يكسر decimals الخاطئ الأرصدة والمبادلات
decimals ليس تجميلًا للعرض. فهو يدخل في كل موضع يعبر فيه المبلغ حدود «الخام ⇄ الإنسان»، والخطأ يمتدّ عندئذٍ إلى المسار الحسابي كله.
الأرصدة
يعيد get_jetton_balance رصيد الجيتون بالوحدات الخام (وعنوان محفظة الجيتون المطلوب يُحسب على السلسلة، فلا حاجة إلى أن تبحث عنه بنفسك). وهذا العدد الصحيح لا يعني شيئًا بذاته بدون decimals — لا يمكن عرضه للمستخدم عرضًا صحيحًا قبل أن تقسمه على 10^decimals:
raw = 5 000 000
decimals = 6 → 5 USDT ✅
decimals = 9 → 0.005 ❌ (أقل بـ 1000 مرة)
والترتيب الصحيح داخل الوكيل: أولًا get_jetton_info ← خذ decimals، ثم get_jetton_balance ← اقسم الخام على 10^decimals. أما كيف تصطدم اللايت-سيرفرات العامة بحدودها عند طلبات القراءة هذه تحديدًا، ففي تحليل حدود اللايت-سيرفرات العامة في TON.
المبادلات
يعطي get_swap_quote عرض سعر ثابتًا من DEX لمبادلة GRAM ⇄ جيتون (عبر بروتوكول Omniston، بسيولة STON.fi + DeDust) — والمبلغ المُدخَل وتقدير المبلغ المستلَم كلاهما أيضًا بالوحدات الخام للجيتون. وهنا يضرب decimals الخاطئ مرتين. لنفترض أن المستخدم يريد مبادلة 10 USDT: عند decimals = 6 يجب تمرير 10 000 000 وحدة خام إلى عرض السعر. وإن طبّقت 9 خطأً — فقد طلبت 10 000 000 000 وحدة خام، أي مبادلة بقيمة 10 000 USDT غير موجودة في المحفظة أصلًا. أما الخطأ المعكوس عند تحليل الردّ فسيخفض المبلغ المتوقَّع ألف مرة، فيظنّ المستخدم أن سعر الصرف مُجحِف.
والمبدأ نفسه يسري في عروض الأسعار عبر السلاسل وفي أي معاملة كانت: كل شيء على البلوكتشين بوحدات خام صحيحة، والجسر الوحيد إلى المبالغ التي يقرأها البشر هو decimals الصحيح.
التحقق عمليًا: get_jetton_balance وget_swap_quote
لنجمّع سيناريو قصيرًا يمرّره الوكيل بنفسه، دون رقم واحد مكتوب ثابتًا في الكود.
السيناريو خطوة بخطوة
1. اعرف decimals. get_jetton_info(USDT master) → decimals = 6.
2. اقرأ الرصيد. get_jetton_balance(المالك, USDT master) → 5 000 000 (خام). نحسب: 5 000 000 / 10^6 = 5 USDT. ولو أخذنا 9 لحصلنا على 0.005. وهذه إشارتك التحذيرية: إن رأيت رقمًا ضئيلًا على غير المتوقع عند USDT، فتحقّق أولًا مما إذا كنت قد طبّقت 9 بدل 6.
3. اطلب عرض السعر. نريد مبادلة 5 USDT بـ GRAM. وبالوحدات الخام هذا يساوي 5 × 10^6 = 5 000 000 — وهذا بالضبط ما نمرّره إلى get_swap_quote. والنتيجة ستأتي بالخام أيضًا، وGRAM من 9 خانات، أي أننا نقسم الردّ على 10^9 كي نعرضه للمستخدم.
4. لا تثق بالبيانات الوصفية؟ يمكنك التحقق على السلسلة مباشرةً. فـ run_get_method يستدعي أي get-method للقراءة فقط في العقد — وبالطريقة نفسها يمكنك سحب get_jetton_data من عقد الماستر والتأكد من تطابق الأرقام. هذا أكثر مرونة، لكنه يتطلب معرفة صيغة TEP-64 وتحليل القاموس يدويًا؛ وحين تهمّ السرعة والموثوقية، يغلق get_jetton_info الموضوع بردٍّ واحد. أما اختلاف مزوّدي RPC في TON من حيث الوصول إلى get-methods والأرشيف، ففي مقارنة صادقة لمزوّدي RPC في TON.
مطالبة الوكيل
وتبدو المطالبة الخاصة بالسيناريو كله عادية تمامًا:
خذ USDT على TON. عبر
get_jetton_infoاقرأdecimals. وعبرget_jetton_balanceخذ رصيدي بالوحدات الخام وحوّله إلى USDT مقروءة بشريًا. ثم عبرget_swap_quoteاحسب عرض سعر لمبادلة 5 USDT بـ GRAM — ولا تنسَ تحويل 5 USDT إلى وحدات خام حسبdecimalsالتي قرأتها.
وثمة تفصيلة أخرى تخصّ سيناريوهات الوكلاء: أدوات المبادلة في TONNode غير احتجازية بصرامة. فالخادم لا يوقّع أبدًا ولا يحتفظ بالمفاتيح — إذ يعيد build_swap_tx رسالة TonConnect غير موقّعة، توقّعها محفظة المستخدم. وحتى decimals الصحيح لا يمنح الخادم أي تحكّم بالأموال: فهو يحسب ويجمّع المعاملة فحسب. أما أين تضيع الميلي ثانية والتأخيرات في المبادلات على TON، ففي تحليل التداول السريع على TON.
باختصار
decimalsهو أُسّ العشرة بين الوحدات الخام في البلوكتشين والمبلغ المقروء بشريًا:human = raw / 10^decimals.- الافتراضي في TON هو 9 خانات؛ أما USDT فله 6 (
1 USDT = 1 000 000وحدة خام). والخلط بينهما = خطأ بمقدار 1000 ضعف. decimalsيعيش في البيانات الوصفية للجيتون (TEP-64) لا في الكود. وبيانات USDT الوصفية مخزَّنة off-chain، ومع ذلك يعيدget_jetton_infoالقيمةdecimals = 6بردٍّ واحد.- لا تكتب
9ثابتة في الكود. اقرأdecimalsعبرget_jetton_infoوابنِ عليها كل الأرصدة (get_jetton_balance) وعروض الأسعار (get_swap_quote).
احصل على مفتاح Hobby المجاني (60 طلبًا/دقيقة، بلا بطاقة) واقرأ decimals أي جيتون عبر get_jetton_info الآن: https://tonnode.io/dashboard?plan=hobby
امنح وكيلك الوصول إلى TON
16 أداة MCP: قراءة ومبادلات غير وصائية وعبر السلاسل ومحافظ. الباقة المجانية — 60 طلب/دقيقة، بلا بطاقة.