كتابة ونشر أول برنامج (Program) على شبكة Solana المحلية

دقائق القراءة: 6

كتابة ونشر أول برنامج (Program) على شبكة Solana المحلية

يختلف تطوير التطبيقات اللامركزية على Solana عن النمط الشائع في شبكات EVM مثل Ethereum. ففي Solana لا نسمّي الكود المنشور عقداً ذكياً فقط، بل غالباً يُشار إليه باسم Program. هذا النموذج مبني على فصل المنطق عن الحسابات Accounts، وهو ما يمنح الشبكة سرعة عالية ومرونة كبيرة في معالجة المعاملات.

إذا كنت قد قرأت سابقاً مقال استكشاف البلوكتشين البديلة: لماذا يفضل المطورون Solana للسرعة العالية؟ فستدرك أن الأداء في Solana ليس مجرد ميزة تسويقية، بل نتيجة مباشرة لبنية تنفيذ مختلفة. كما أن فهم أساسيات Rust يساعد كثيراً، خاصة بعد مراجعة نظرة سريعة على لغة Rust: أساسيات لبرمجة العقود الذكية على شبكة Solana، ثم تجهيز البيئة كما في تثبيت بيئة عمل Solana وإطار عمل Anchor لتسهيل كتابة العقود.

في هذا المقال سنبني برنامجاً بسيطاً على الشبكة المحلية Localnet باستخدام Anchor، ثم نترجمه وننشره ونختبره محلياً. الهدف ليس فقط تنفيذ الخطوات، بل فهم كيف يتفاعل Program مع الحسابات، ولماذا تعد إدارة البيانات في Solana مختلفة جذرياً عن العقود التقليدية.

فهم بنية البرنامج على شبكة Solana

في شبكات كثيرة يحتفظ العقد الذكي بحالته داخلياً، لكن في Solana يتم تخزين البيانات داخل حسابات مستقلة، بينما يتولى Program منطق القراءة والتعديل. هذا التصميم يعني أنك تحتاج من البداية إلى التفكير في بنية الحسابات، الصلاحيات، وحجم البيانات المخزنة.

إطار Anchor يخفف كثيراً من التعقيد عبر توفير وحدات جاهزة للتعامل مع التسلسل Serialization، التحقق من الحسابات، وإدارة أوامر النشر والاختبار. لذلك يُعد الخيار الأفضل للمبتدئ الجاد وللمطور المحترف الذي يريد سرعة إنتاجية عالية دون التضحية بالوضوح.

إنشاء مشروع Anchor جديد

بعد تثبيت الأدوات المطلوبة مثل Rust وSolana CLI وAnchor CLI، أنشئ المشروع بالأمر التالي من الطرفية:

anchor init hello_solana
cd hello_solana

سينشئ هذا الأمر هيكل مشروع يحتوي على مجلد programs لملفات البرنامج، ومجلد tests للاختبارات، وملف Anchor.toml الذي يحدد إعدادات الشبكة والمعرفات.

الملف البرمجي الأساسي

افتح الملف داخل المسار programs/hello_solana/src/lib.rs واستبدل محتواه ببرنامج بسيط يخزن رسالة نصية وعدّاداً.

use anchor_lang::prelude::*;

declare_id!("11111111111111111111111111111111");

#[program]
pub mod hello_solana {
    use super::*;

    pub fn initialize(ctx: Context<Initialize>, message: String) -> Result<()> {
        let greeting_account = &mut ctx.accounts.greeting_account;
        greeting_account.message = message;
        greeting_account.counter = 1;
        greeting_account.author = ctx.accounts.user.key();
        Ok(())
    }

    pub fn update_message(ctx: Context<UpdateMessage>, message: String) -> Result<()> {
        let greeting_account = &mut ctx.accounts.greeting_account;
        greeting_account.message = message;
        greeting_account.counter += 1;
        Ok(())
    }
}

#[derive(Accounts)]
pub struct Initialize<'info> {
    #[account(init, payer = user, space = 8 + 4 + 100 + 8 + 32)]
    pub greeting_account: Account<'info, GreetingAccount>,

    #[account(mut)]
    pub user: Signer<'info>,

    pub system_program: Program<'info, System>,
}

#[derive(Accounts)]
pub struct UpdateMessage<'info> {
    #[account(mut, has_one = author)]
    pub greeting_account: Account<'info, GreetingAccount>,

    pub author: Signer<'info>,
}

#[account]
pub struct GreetingAccount {
    pub message: String,
    pub counter: u64,
    pub author: Pubkey,
}

رغم أن المقتطف مكتوب بلغة Rust، إلا أن وضعه داخل صندوق الشيفرة الموحّد يحافظ على التوافق مع المحرر المطلوب. وظيفته بسيطة: الدالة initialize تنشئ حساباً جديداً وتخزن الرسالة الأولى، بينما تقوم update_message بتحديث النص وزيادة العداد.

لماذا نحدد مساحة الحساب يدوياً؟

على عكس بعض بيئات Smart Contracts التي تتوسع فيها الذاكرة منطقياً، فإن حسابات Solana تحتاج إلى مساحة محددة مسبقاً عند الإنشاء. لهذا استخدمنا القيمة 8 + 4 + 100 + 8 + 32.

  • 8 بايت للتمييز الداخلي discriminator.
  • 4 بايت لطول السلسلة النصية.
  • 100 بايت كمجال مخصص للرسالة.
  • 8 بايت للمتغير u64.
  • 32 بايت للمفتاح العام Pubkey.

أحد أشهر الأخطاء عند تطوير برامج Solana هو تخصيص مساحة أصغر من البيانات الحقيقية. هذا لا يؤدي فقط إلى فشل التنفيذ، بل قد يجبرك لاحقاً على إعادة تصميم الحسابات من البداية. احسب المساحة بدقة، واترك هامشاً منطقياً إذا كانت السلاسل النصية قابلة للنمو.

تشغيل الشبكة المحلية وترجمة البرنامج

الآن نحتاج إلى تشغيل مدقق محلي solana-test-validator حتى نحاكي الشبكة على جهازك. افتح نافذة طرفية مستقلة ونفذ:

solana-test-validator

بعدها، من داخل المشروع، تأكد أن الإعدادات تشير إلى localnet، ثم نفذ أمر الترجمة:

anchor build

سينتج عن هذه الخطوة ملف البرنامج المترجم ومعرفاً يتم حقنه تلقائياً داخل ملفات المشروع. إذا ظهرت أخطاء تتعلق بالإصدارات، فغالباً هناك عدم توافق بين Anchor وSolana CLI، وهي مشكلة شائعة يجب حلها قبل متابعة النشر.

نشر البرنامج على الشبكة المحلية

بعد نجاح الترجمة، يمكنك تنفيذ عملية النشر باستخدام:

anchor deploy

يقوم هذا الأمر برفع ملف Program إلى شبكة Localnet وتحديث المعرّف الفعلي المستخدم أثناء الاستدعاءات. عملياً، هذه المرحلة تماثل نشر عقد على شبكة تجريبية، لكن بكلفة صفرية تقريباً وسرعة عالية جداً، ما يجعلها مثالية للتجربة السريعة وتصحيح الأخطاء.

الحصول على رصيد محلي للتجارب

إذا احتجت إلى تمويل المحفظة المحلية، يمكنك طلب رصيد عبر:

solana airdrop 2

هذه الآلية تشبه فكرة المقال الحصول على عملات تجريبية مجانية (Faucet) للبدء في نشر واختبار العقود الذكية، لكن في بيئة Solana Localnet يتم ذلك محلياً وبصورة أسرع.

اختبار البرنامج واستدعاء التعليمات

يولّد Anchor اختبارات مبدئية داخل مجلد tests. يمكنك كتابة اختبار يقوم بإنشاء الحساب ثم تحديث الرسالة. هذا يقرّبك من عقلية التطوير الاحترافي المشابهة لما ناقشناه في اختبار العقود الذكية محلياً: كتابة اختبارات الوحدة (Unit Tests) باستخدام Chai & Mocha، حتى لو كانت الأدوات هنا مختلفة.

anchor test

عند نجاح الاختبار ستتأكد من أن الدالة initialize أنشأت الحساب، وأن update_message عدّلت القيمة ورفعت العداد. هذا الاختبار المبكر مهم جداً قبل التفكير بربط البرنامج مع واجهة أمامية أو نقله لاحقاً إلى Devnet.

من منظور أمني، لا تعتمد على اختبار نجاح المسار السعيد فقط. اختبر أيضاً حالات الفشل مثل توقيع مستخدم غير مخول، أو محاولة تمرير حساب غير متوافق مع قيود has_one. هذا النوع من الاختبارات المبكرة يختصر كثيراً من أخطاء الإنتاج.

فروقات مهمة بين Solana و Solidity في النشر المحلي

إذا كنت قادماً من عالم Solidity ومحرر Remix IDE: كتابة ونشر أول عقد ذكي (Smart Contract) على المتصفح مباشرة أو من بيئات مثل الانتقال إلى بيئة العمل الاحترافية: تثبيت إطار عمل Hardhat باستخدام Node.js، فهناك ثلاث نقاط يجب الانتباه لها:

  1. البيانات ليست داخل الكود نفسه، بل داخل حسابات تمرر صراحة مع كل استدعاء.
  2. إدارة المساحة والتمويل الأولي للحسابات عنصر أساسي في التصميم.
  3. الصلاحيات تتحقق غالباً عبر بنية الحسابات والتوقيعات، لا عبر msg.sender كما هو شائع في بيئات أخرى.

هذا الاختلاف لا يجعل Solana أصعب بالضرورة، لكنه يفرض طريقة تفكير أدق في هندسة البيانات وسير المعاملات منذ البداية.

خاتمة عملية

كتابة ونشر أول Program على شبكة Solana المحلية هو الخطوة التي تنقلك من الفهم النظري إلى الاستيعاب الحقيقي لبنية الشبكة. أنت هنا لا تنشر مجرد كود، بل تتعلم كيف تُصمم الحسابات، وتحدد المساحات، وتربط التعليمات بالتوقيعات المناسبة، وتختبر كل ذلك في بيئة آمنة وسريعة.

بعد إتقان هذا المسار المحلي، تصبح جاهزاً للانتقال إلى Devnet، ثم بناء واجهات أمامية تتفاعل مع البرنامج، تماماً كما نفعل في عالم هندسة الويب اللامركزي (Web3.js & Ethers.js): كيف نربط الواجهات بالعقود الذكية؟ ولكن بأدوات مخصصة لمنظومة Solana. وهذه هي البداية الحقيقية لبناء DApps عالية الأداء على واحدة من أسرع الشبكات في عالم Web3.

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *