DEV Community

Malek
Malek

Posted on Edited on AI-assisted

أرسل أول معاملة على بلوكتشين «جنزير» بلغة بايثون في أقل من عشرين سطرًا

⁧لماذا هذا المقال؟⁩

⁧معظم سلاسل الكتل العامة توثيقها بالإنجليزية فقط، ومعظم أدوات التطوير فيها تفترض أنك تعرف الإيثيريوم مسبقًا. «جنزير» (Janzeer) سلسلة كتل من الطبقة الأولى أطلقتُ شبكتها الرئيسية في الأول من تشرين الأول/أكتوبر 2026، وفيها أمران يهمّان المطوّر العربي تحديدًا: التوثيق الرسمي كله بالعربية والإنجليزية معًا (الورقة البيضاء، دليل المطوّر، مرجع الواجهة)، ومجموعات تطوير رسمية بخمس لغات: بايثون، وتايب سكريبت، ودارت، وكوتلن، وغو، كلها مفتوحة المصدر برخصة Apache-2.0.⁩

⁧في هذا المقال نستخدم بايثون. في النهاية ستكون قد قرأت بيانات السلسلة، وأنشأت محفظة على جهازك، وأرسلت معاملة، وانتظرت حتى صارت نهائية — كل ذلك من سطر الأوامر.⁩

⁧ما الذي يميّز «جنزير» بكلمات قليلة؟⁩

  • ⁧لا تجميد (staking) ولا تفويض: من يريد التحقق من الكتل يشغّل عقدة ويدفع وديعة لمرة واحدة قدرها 2000 JNZ، ثم يكسب مكافأة الكتل التي ينتجها. لا تصويت ولا لجان.⁩
  • ⁧نهائية في كتلة واحدة: الكتلة كل 15 ثانية، وتُعتمد بتوافق BFT من مرحلتين (PREPARE ثم COMMIT). الكتلة المعتمدة نهائية؛ لا يوجد «عدد تأكيدات».⁩
  • ⁧معروض ثابت: 100 مليون JNZ، لا سكّ بعدها. مكافآت الكتل تُدفع من الخزانة.⁩
  • ⁧غير حافظ (non-custodial) بالتصميم: المفاتيح لا تغادر جهازك أبدًا، والعقدة لا تفعل سوى التحقق.⁩
  • ⁧الشبكة صغيرة وجديدة: سبعة مدقّقين نشطين اليوم، وقرابة مئتي ألف كتلة. أقول هذا بوضوح حتى لا يتوقع أحد شبكة بحجم الكبار.⁩

⁧ما الذي تحتاج إليه؟⁩

  • ⁧بايثون 3.10 أو أحدث على لينكس أو ماك أو ويندوز (العجلات جاهزة، لا حاجة إلى مترجم).⁩
  • ⁧حزمة janzeer-sdk من PyPI.⁩
  • ⁧لقراءة بيانات السلسلة لا تحتاج إلى شيء آخر. لإرسال معاملة تحتاج إلى بضع وحدات JNZ في محفظتك؛ أسهل طريقة اليوم هي لعبة jPong داخل تيليغرام (التي تدفع لمن يلعب) أو أن يحوّل لك أحدهم. لا يوجد صنبور (faucet) على الشبكة الرئيسية.⁩

⁧الخطوة 0: التثبيت⁩

pip install "janzeer-sdk[ws]"
Enter fullscreen mode Exit fullscreen mode

⁧اللاحقة [ws] تضيف دعم WebSocket للاشتراكات الحيّة؛ احذفها إن لم تكن تحتاج إليها.⁩

⁧الخطوة 1: اقرأ السلسلة (بلا مفاتيح وبلا رصيد)⁩

from janzeer import JanzeerClient, JanzeerRpc

NODE = "https://explorer.janzeer.org"
client = JanzeerClient(NODE)      # REST تحت ‎/api/v1
rpc = JanzeerRpc(NODE)            # JSON-RPC تحت ‎/rpc

info = client.info()
print("إصدار العقدة:", info["version"], "| الشبكة:", info["networkId"])
tip = rpc.get_tip()
print("آخر كتلة:", tip["height"], tip["hash"])
Enter fullscreen mode Exit fullscreen mode

⁧العقدة العامة explorer.janzeer.org هي نفسها التي يعمل عليها المستكشف. كل نتيجة تعود كقاموس أو قائمة بأسماء الحقول التي تستخدمها العقدة نفسها (blockHeight وsenderAddress وهكذا)، فلا توجد طبقة أسماء ثانية عليك حفظها.⁩

⁧الخطوة 2: أنشئ محفظة على جهازك⁩

from janzeer import Account, mnemonic

words = mnemonic.generate(128)            # 12 كلمة وفق BIP39
me = Account.from_mnemonic(words)
print(words)                              # احفظها في مكان آمن؛ من يملكها يملك المحفظة
print(me.checksum_address)
Enter fullscreen mode Exit fullscreen mode

⁧هذا كل ما يحدث: اشتقاق محلي. لم تُرسل أي كلمة إلى أي خادم. (العنوان الناتج يبدأ بـ 0x وطوله 20 بايتًا، لكنه ليس عنوان إيثيريوم: الاشتقاق مختلف.)⁩

⁧الخطوة 3: أرسل معاملة وانتظر النهائية⁩

from janzeer import Account, JanzeerClient, JanzeerRpc, TxBuilder, format_jnz, wait_for_finality

NODE = "https://explorer.janzeer.org"
client, rpc = JanzeerClient(NODE), JanzeerRpc(NODE)
me = Account.from_mnemonic("…الكلمات الاثنتا عشرة من الخطوة السابقة…")

print(me.checksum_address, format_jnz(client.balance(me.address)), "JNZ")

tx = me.sign_tx(TxBuilder.transfer(
    sender=me.address,
    to="0x598b1301acef3baba6ce25e38dd17b723f7b98b1",
    amount="1.25",                      # نص عشري، ليس float
    data="مرحبا من بايثون",
    nonce=client.nonce(me.address),
    network_id=client.info()["networkId"],
))
client.submit(tx)                       # HTTP 201 أو خطأ ذو نوع محدد
print("أُرسلت:", tx.hash)

final = wait_for_finality(rpc, tx.hash) # فتحة أو فتحتان من 15 ثانية
print("نهائية في الكتلة", final["blockHeight"])
print("https://explorer.janzeer.org/tx/" + tx.hash)
Enter fullscreen mode Exit fullscreen mode

⁧هذه هي عملية التكامل كاملة: اشتقاق ← رقم تسلسلي (nonce) ← بناء ← توقيع ← إرسال ← انتظار. حين تعود wait_for_finality تكون المعاملة في كتلة معتمدة، أي نهائية. افتح الرابط الأخير في المستكشف وسترى المعاملة ورسالتها.⁩

⁧لاحظ ثلاثة أشياء:⁩

  1. ⁧المبلغ نص "1.25" وليس 1.25. المكتبة ترفض float في كل مكان وترمي TypeError، لأن 0.1 لا يُمثَّل تمثيلًا دقيقًا بالثنائي، والدفع يجب ألّا يعتمد على طريقة طباعة الأعداد العشرية. المقبول: نص عشري، أو int للوحدات الكاملة، أو decimal.Decimal.⁩
  2. ⁧network_id يدخل في بصمة المعاملة، فمعاملة موقّعة لشبكة الاختبار لا يمكن إعادة تشغيلها على الشبكة الرئيسية.⁩
  3. ⁧الأخطاء مصنّفة: TxRejectedError وNonceMismatchError وRateLimitedError وغيرها، فبرنامجك يعرف ماذا حدث بدل أن يفسّر نصًا.⁩

⁧الخطوة 4 (اختيارية): شاهد الكتل الجديدة حيّة⁩

import asyncio
from janzeer import JanzeerRpcWs

async def main():
    ws = await JanzeerRpcWs.connect("wss://explorer.janzeer.org/rpc/ws")
    tip = await ws.get_tip()
    await ws.subscribe_new_blocks(
        {"fromHeight": tip["height"]},
        lambda b: print("كتلة", b["height"], b["hash"][:12], "معاملات:", b["transactionsCount"]),
    )
    await asyncio.sleep(60)
    await ws.close()

asyncio.run(main())
Enter fullscreen mode Exit fullscreen mode

⁧(المثال الكامل مع المعالجة الصحيحة للإنهاء موجود في examples/06_watch_new_blocks.py داخل المستودع، وقد كتبه مساهم من خارج المشروع.)⁩

⁧ماذا تقرأ بعد ذلك؟⁩

  • ⁧دليل المطوّر بالعربية: https://janzeer.org/docs — كل نقطة نهاية REST وكل دالة JSON-RPC، بالعربية والإنجليزية.⁩
  • ⁧المستودع: https://github.com/janzeerOrg/janzeer-sdk-python — ستة أمثلة جاهزة، وقضايا موسومة good first issue لمن يريد المساهمة.⁩
  • ⁧المجموعات الأخرى: تايب سكريبت (npm: janzeer-sdk)، دارت (pub.dev: janzeer_sdk)، كوتلن (Maven Central: org.janzeer)، غو.⁩
  • ⁧المستكشف: https://explorer.janzeer.org — وفيه صفحة «كيف تعمل السلسلة» برسم متحرك حيّ.⁩
  • ⁧القناة: https://t.me/janzeerorg — كل إعلان بالعربية والإنجليزية.⁩

Top comments (0)