عقد Hello World الذكي للمبتدئين - Fullstack
هذا الدليل مخصص لك إذا كنت جديدًا في تطوير البلوكتشين ولا تعرف من أين تبدأ أو كيفية نشر العقود الذكية والتفاعل معها. سوف نستعرض إنشاء ونشر عقد ذكي بسيط على شبكة اختبار جيرلي باستخدام ميتاماسك (opens in a new tab)، وسوليديتي (opens in a new tab)، وهارد هات (opens in a new tab)، وألكيمي (opens in a new tab).
ستحتاج إلى حساب ألكيمي لإكمال هذا الدرس التعليمي. سجّل للحصول على حساب مجاني (opens in a new tab).
إذا كانت لديك أسئلة في أي وقت، فلا تتردد في التواصل معنا في ألكيمي ديسكورد (opens in a new tab)!
الجزء 1 - إنشاء ونشر عقدك الذكي باستخدام هارد هات
الاتصال بشبكة إيثريوم
هناك طرق عديدة لتقديم طلبات إلى سلسلة إيثريوم. للتبسيط، سنستخدم حسابًا مجانيًا على ألكيمي، وهي منصة لمطوري البلوكتشين وواجهة برمجة تطبيقات (API) تسمح لنا بالتواصل مع سلسلة إيثريوم دون تشغيل عقدة بأنفسنا. تحتوي ألكيمي أيضًا على أدوات للمطورين للمراقبة والتحليلات؛ وسنستفيد من هذه الأدوات في هذا الدرس التعليمي لفهم ما يحدث خلف الكواليس في نشر عقدنا الذكي.
إنشاء تطبيقك ومفتاح API الخاص بك
بمجرد إنشاء حساب ألكيمي، يمكنك إنشاء مفتاح API عن طريق إنشاء تطبيق. سيسمح لك هذا بتقديم طلبات إلى شبكة اختبار جيرلي. إذا لم تكن على دراية بشبكات الاختبار، يمكنك قراءة دليل ألكيمي لاختيار شبكة (opens in a new tab).
في لوحة تحكم ألكيمي، ابحث عن القائمة المنسدلة التطبيقات في شريط التنقل وانقر على إنشاء تطبيق.
أطلق على تطبيقك اسم 'Hello World' واكتب وصفًا قصيرًا. حدد مرحلي كبيئتك و جيرلي كشبكتك.
ملاحظة: تأكد من تحديد جيرلي، وإلا فلن ينجح هذا الدرس التعليمي.
انقر على إنشاء تطبيق. سيظهر تطبيقك في الجدول أدناه.
إنشاء حساب إيثريوم
أنت بحاجة إلى حساب إيثريوم لإرسال واستقبال المعاملات. سنستخدم ميتاماسك، وهي محفظة افتراضية في المتصفح تتيح للمستخدمين إدارة عنوان حساب إيثريوم الخاص بهم.
يمكنك تنزيل وإنشاء حساب ميتاماسك مجانًا هنا (opens in a new tab). عندما تقوم بإنشاء حساب، أو إذا كان لديك حساب بالفعل، تأكد من التبديل إلى "شبكة اختبار جيرلي" في الجزء العلوي الأيمن (حتى لا نتعامل بأموال حقيقية).
الخطوة 4: إضافة إيثر من صنبور (Faucet)
لنشر عقدك الذكي على شبكة الاختبار، ستحتاج إلى بعض من عملات ETH المزيفة. للحصول على ETH على شبكة جيرلي، انتقل إلى سبيل جيرلي وأدخل عنوان حساب جيرلي الخاص بك. لاحظ أن سُبُل جيرلي قد تكون غير موثوقة بعض الشيء في الآونة الأخيرة - راجع صفحة شبكات الاختبار للحصول على قائمة بالخيارات التي يمكنك تجربتها:
ملاحظة: بسبب ازدحام الشبكة، قد يستغرق هذا بعض الوقت. ``
الخطوة 5: التحقق من رصيدك
للتأكد من وجود ETH في محفظتك، دعنا نُجرِ طلب eth_getBalance (opens in a new tab) باستخدام أداة الملحن من ألكيمي (opens in a new tab). This will return the amount of ETH in our wallet. لمعرفة المزيد، راجع الدرس التعليمي القصير من ألكيمي حول كيفية استخدام أداة الملحن (opens in a new tab).
أدخل عنوان حساب ميتاماسك الخاص بك وانقر على إرسال طلب. سترى استجابة تشبه مقتطف الشفرة أدناه.
1{ "jsonrpc": "2.0", "id": 0, "result": "0x2B5E3AF16B1880000" }ملاحظة: هذه النتيجة بـ wei، وليس بـ ETH. يُستخدم Wei كأصغر فئة من الإيثر._
Phew! Our fake money is all there.
الخطوة 6: تهيئة مشروعنا
أولًا، سنحتاج إلى إنشاء مجلد لمشروعنا. انتقل إلى سطر الأوامر وأدخل ما يلي.
1mkdir hello-world2cd hello-worldالآن بعد أن أصبحنا داخل مجلد مشروعنا، سنستخدم npm init لتهيئة المشروع.
إذا لم يكن لديك npm مثبتًا بعد، فاتبع هذه الإرشادات لتثبيت نود.جي إس وnpm (opens in a new tab).
لغرض هذا الدرس التعليمي، لا يهم كيف تجيب على أسئلة التهيئة. إليك كيف فعلنا ذلك كمرجع:
1اسم الحزمة: (hello-world)2الإصدار: (1.0.0)3الوصف: عقد Hello World الذكي4نقطة الدخول: (index.js)5أمر الاختبار:6مستودع git:7الكلمات المفتاحية:8المؤلف:9الرخصة: (ISC)10
11على وشك الكتابة إلى /Users/.../.../.../hello-world/package.json:12
13{14 "name": "hello-world",15 "version": "1.0.0",16 "description": "عقد Hello World الذكي",17 "main": "index.js",18 "scripts": {19 "test": "echo \"Error: no test specified\" && exit 1"20 },21 "author": "",22 "license": "ISC"23}وافق على package.json ونحن على استعداد للبدء!
الخطوة 7: تنزيل هارد هات
يعتبر Hardhat بيئة تطوير لترجمة (Compile) ونشر واختبار وتصحيح أخطاء برامج Ethereum الخاصة بك. فهو يساعد المطورين عند بناء العقود الذكية والتطبيقات اللامركزية (DApps) محلياً قبل النشر على الشبكة الحية.
داخل مشروعنا hello-world، قم بتشغيل:
1npm install --save-dev hardhatراجع هذه الصفحة لمزيد من التفاصيل حول إرشادات التثبيت (opens in a new tab).
الخطوة 8: إنشاء مشروع هارد هات
داخل مجلد مشروع hello-world، قم بتشغيل:
1npx hardhatيجب أن ترى بعد ذلك رسالة ترحيب وخياراً لاختيار ما تريد القيام به. اختر "create an empty hardhat.config.js":
1888 888 888 888 8882888 888 888 888 8883888 888 888 888 88848888888888 8888b. 888d888 .d88888 88888b. 8888b. 8888885888 888 "88b 888P" d88" 888 888 "88b "88b 8886888 888 .d888888 888 888 888 888 888 .d888888 8887888 888 888 888 888 Y88b 888 888 888 888 888 Y88b.8888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y8889
10👷 مرحبًا بك في Hardhat v2.0.11 👷11
12ماذا تريد أن تفعل؟ …13إنشاء مشروع نموذجي14❯ إنشاء ملف hardhat.config.js فارغ15خروجسيؤدي هذا إلى إنشاء ملف hardhat.config.js في المشروع. سنستخدم هذا لاحقًا في الدرس التعليمي لتحديد إعداد مشروعنا.
الخطوة 9: إضافة مجلدات المشروع
للحفاظ على تنظيم المشروع، لنقم بإنشاء مجلدين جديدين. في سطر الأوامر، انتقل إلى الدليل الجذر لمشروع hello-world واكتب:
1mkdir contracts2mkdir scriptscontracts/هو المكان الذي سنحتفظ فيه بملف كود عقد Hello World الذكي الخاص بناscripts/هو المكان الذي سنحتفظ فيه بالبرامج النصية لنشر عقدنا والتفاعل معه
الخطوة 10: كتابة عقدنا
قد تسأل نفسك، متى سنكتب الكود؟ حان الوقت!
افتح مشروع hello-world في محرر النصوص المفضل لديك. تُكتب العقود الذكية بشكل شائع بلغة سوليديتي، والتي سنستخدمها لكتابة عقدنا الذكي.
- انتقل إلى مجلد
contractsوأنشئ ملفًا جديدًا باسمHelloWorld.sol - أدناه هو عقد Hello World ذكي نموذجي سنستخدمه في هذا الدرس التعليمي. انسخ المحتويات أدناه إلى ملف
HelloWorld.sol.
ملاحظة: تأكد من قراءة التعليقات لفهم ما يفعله هذا العقد.
1// يحدد إصدار Solidity، باستخدام الإصدار الدلالي.2// اعرف المزيد: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma3pragma solidity >=0.7.3;4
5// يُعرّف عقدًا باسم 'HelloWorld'.6// العقد هو مجموعة من الوظائف والبيانات (حالته). بمجرد نشره، يقيم العقد في عنوان محدد على بلوكتشين إيثريوم. اعرف المزيد: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html7contract HelloWorld {8
9 //يتم إصداره عند استدعاء دالة التحديث10 //تعد أحداث العقود الذكية وسيلة لعقدك لإبلاغ الواجهة الأمامية لتطبيقك بحدوث شيء ما على البلوكتشين، والتي يمكن أن "تستمع" لأحداث معينة وتتخذ إجراءات عند حدوثها.11 event UpdatedMessages(string oldStr, string newStr);12
13 // يصرح عن متغير حالة 'message' من النوع 'string'.14 // متغيرات الحالة هي متغيرات تُخزن قيمها بشكل دائم في تخزين العقد. الكلمة المفتاحية 'public' تجعل المتغيرات قابلة للوصول من خارج العقد وتنشئ دالة يمكن للعقود أو العملاء الآخرين استدعاؤها للوصول إلى القيمة.15 string public message;16
17 // على غرار العديد من اللغات الكائنية التوجه القائمة على الأصناف، المُنشئ هو دالة خاصة تُنفذ فقط عند إنشاء العقد.18 // تُستخدم المُنشئات لتهيئة بيانات العقد. اعرف المزيد:https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors19 constructor(string memory initMessage) {20
21 // يقبل وسيط سلسلة 'initMessage' ويضبط القيمة في متغير التخزين 'message' الخاص بالعقد).22 message = initMessage;23 }24
25 // دالة عامة تقبل وسيط سلسلة وتُحدّث متغير التخزين 'message'.26 function update(string memory newMessage) public {27 string memory oldMsg = message;28 message = newMessage;29 emit UpdatedMessages(oldMsg, newMessage);30 }31}هذا عقد ذكي أساسي يخزن رسالة عند الإنشاء. يمكن تحديثه عن طريق استدعاء دالة update.
الخطوة 11: ربط ميتاماسك وألكيمي بمشروعك
لقد أنشأنا محفظة ميتاماسك وحساب ألكيمي وكتبنا عقدنا الذكي، والآن حان وقت ربط الثلاثة.
كل معاملة تُرسل من محفظتك تتطلب توقيعًا باستخدام مفتاحك الخاص الفريد. لتزويد برنامجنا بهذا الإذن، يمكننا تخزين مفتاحنا الخاص بأمان في ملف بيئة. سنقوم أيضًا بتخزين مفتاح API لـ ألكيمي هنا.
لمعرفة المزيد حول إرسال المعاملات، راجع هذا الدرس التعليمي (opens in a new tab) حول إرسال المعاملات باستخدام web3.
أولاً، قم بتثبيت حزمة dotenv في مجلد مشروعك:
1npm install dotenv --saveبعد ذلك، قم بإنشاء ملف .env في الدليل الجذر للمشروع. أضف مفتاح ميتاماسك الخاص بك وعنوان URL لـ HTTP ألكيمي API إليه.
يجب تسمية ملف البيئة الخاص بك .env وإلا فلن يتم التعرف عليه كملف بيئة.
لا تسميه process.env أو .env-custom أو أي شيء آخر.
- اتبع هذه الإرشادات (opens in a new tab) لتصدير مفتاحك الخاص
- انظر أدناه للحصول على عنوان URL لـ HTTP ألكيمي API
يجب أن يبدو ملف .env الخاص بك هكذا:
1API_URL = "https://eth-goerli.alchemyapi.io/v2/your-api-key"2PRIVATE_KEY = "your-metamask-private-key"لربط هذه الأشياء بالكود الخاص بنا، سنشير إلى هذه المتغيرات في ملف hardhat.config.js الخاص بنا في الخطوة 13.
الخطوة 12: تثبيت إيثرز.جي إس
إيثرز.جي إس هي مكتبة تسهل التفاعل وإجراء الطلبات إلى إيثريوم عن طريق تغليف طرق JSON-RPC القياسية (opens in a new tab) بأساليب أكثر سهولة للمستخدم.
يسمح لنا هارد هات بدمج المكونات الإضافية (opens in a new tab) للحصول على أدوات إضافية ووظائف موسعة. سنستفيد من مكون Ethers الإضافي (opens in a new tab) لنشر العقد.
In your project directory type:
npm install --save-dev @nomiclabs/hardhat-ethers "ethers@^5.0.0"الخطوة 13: تحديث hardhat.config.js
لقد أضفنا العديد من التبعيات والإضافات حتى الآن، والآن نحن بحاجة إلى تحديث hardhat.config.js حتى يتعرف مشروعنا عليها جميعًا.
قم بتحديث hardhat.config.js الخاص بك ليبدو هكذا:
1/**2 * @type import('hardhat/config').HardhatUserConfig3 */4
5require("dotenv").config()6require("@nomiclabs/hardhat-ethers")7
8const { API_URL, PRIVATE_KEY } = process.env9
10module.exports = {11 solidity: "0.7.3",12 defaultNetwork: "goerli",13 networks: {14 hardhat: {},15 goerli: {16 url: API_URL,17 accounts: [`0x${PRIVATE_KEY}`],18 },19 },20}الخطوة 14: تجميع عقدنا
للتأكد من أن كل شيء يعمل حتى الآن، لنقم بترجمة العقد الخاص بنا. مهمة compile هي إحدى مهام Hardhat المضمنة.
From the command line run:
npx hardhat compileقد تحصل على تحذير حول SPDX license identifier not provided in source file، ولكن لا داعي للقلق بشأن ذلك — نأمل أن يبدو كل شيء آخر جيدًا! إذا لم يكن الأمر كذلك، يمكنك دائمًا إرسال رسالة في ألكيمي discord (opens in a new tab).
الخطوة 15: كتابة سكريبت النشر الخاص بنا
الآن بعد أن تمت كتابة العقد الخاص بنا وأصبح ملف التكوين جاهزاً، حان الوقت لكتابة سكربت نشر العقد.
انتقل إلى مجلد scripts/ وأنشئ ملفًا جديدًا باسم deploy.js، مع إضافة المحتويات التالية إليه:
1async function main() {2 const HelloWorld = await ethers.getContractFactory("HelloWorld")3
4 // ابدأ النشر، مع إرجاع وعد يتم حله إلى كائن عقد5 const hello_world = await HelloWorld.deploy("Hello World!")6 console.log("تم نشر العقد على العنوان:", hello_world.address)7}8
9main()10 .then(() => process.exit(0))11 .catch((error) => {12 console.error(error)13 process.exit(1)14 })يقوم هارد هات بعمل رائع في شرح ما يفعله كل من هذه الأسطر من الكود في درس العقود التعليمي (opens in a new tab)، وقد اعتمدنا شروحاتهم هنا.
1const HelloWorld = await ethers.getContractFactory("HelloWorld")ContractFactory في ethers.js هو تجريد يستخدم لنشر عقود ذكية جديدة، لذا فإن HelloWorld هنا هو مصنع (opens in a new tab) لمثيلات عقد hello world الخاص بنا. عند استخدام مكون hardhat-ethers الإضافي، يتم توصيل مثيلات ContractFactory وContract بالموقع الأول (المالك) افتراضيًا.
1const hello_world = await HelloWorld.deploy()سيؤدي استدعاء deploy() على ContractFactory إلى بدء النشر، وإرجاع Promise يتم حله إلى كائن Contract. This is the object that has a method for each of our smart contract functions.
الخطوة 16: نشر عقدنا
We’re finally ready to deploy our smart contract! انتقل إلى سطر الأوامر وقم بتشغيل:
npx hardhat run scripts/deploy.js --network goerliYou should then see something like:
تم نشر العقد على العنوان: 0x6cd7d44516a20882cEa2DE9f205bF401c0d23570يرجى حفظ هذا العنوان. سوف نستخدمه لاحقًا في الدرس التعليمي.
إذا انتقلنا إلى جيرلي etherscan (opens in a new tab) وبحثنا عن عنوان عقدنا، فسنتمكن من رؤية أنه تم نشره بنجاح. The transaction will look something like this:
يجب أن يتطابق عنوان From مع عنوان حساب ميتاماسك الخاص بك، وسيظهر في عنوان To عبارة إنشاء عقد. إذا نقرنا على المعاملة، فسنرى عنوان عقدنا في حقل To.
تهانينا! لقد نشرت للتو عقدًا ذكيًا على شبكة اختبار إيثريوم.
لفهم ما يجري خلف الكواليس، دعنا ننتقل إلى علامة تبويب المستكشف في لوحة تحكم ألكيمي (opens in a new tab). إذا كان لديك العديد من تطبيقات ألكيمي، فتأكد من التصفية حسب التطبيق وتحديد Hello World.
هنا سترى عددًا من طرق JSON-RPC التي أنشأتها هارد هات/Ethers لنا خلف الكواليس عندما استدعينا دالة .deploy(). هناك طريقتان مهمتان هنا هما eth_sendRawTransaction (opens in a new tab)، وهو طلب لكتابة عقدنا على سلسلة جيرلي، وeth_getTransactionByHash (opens in a new tab)، وهو طلب لقراءة معلومات حول معاملتنا بالنظر إلى التجزئة (الهاش). لمعرفة المزيد حول إرسال المعاملات، راجع الدرس التعليمي الخاص بنا حول إرسال المعاملات باستخدام ويب3.
الجزء 2: التفاعل مع عقدك الذكي
الآن بعد أن نجحنا في نشر عقد ذكي على شبكة جيرلي، دعنا نتعلم كيفية التفاعل معه.
إنشاء ملف interact.js
هذا هو الملف الذي سنكتب فيه سكريبت التفاعل الخاص بنا. سنستخدم مكتبة إيثرز.جي إس التي قمت بتثبيتها مسبقًا في الجزء 1.
داخل مجلد scripts/، قم بإنشاء ملف جديد باسم interact.js وأضف الكود التالي:
1// interact.js2
3const API_KEY = process.env.API_KEY4const PRIVATE_KEY = process.env.PRIVATE_KEY5const CONTRACT_ADDRESS = process.env.CONTRACT_ADDRESSتحديث ملف .env الخاص بك
سنستخدم متغيرات بيئة جديدة، لذلك نحتاج إلى تعريفها في ملف .env الذي أنشأناه سابقًا.
سنحتاج إلى إضافة تعريف لـ API_KEY الخاص بـ ألكيمي وCONTRACT_ADDRESS حيث تم نشر عقدك الذكي.
يجب أن يبدو ملف .env الخاص بك كالتالي:
# .env
API_URL = "https://eth-goerli.alchemyapi.io/v2/<your-api-key>"API_KEY = "<your-api-key>"PRIVATE_KEY = "<your-metamask-private-key>"CONTRACT_ADDRESS = "0x<your contract address>"احصل على واجهة التطبيق الثنائية (ABI) الخاصة بعقدك
واجهة التطبيق الثنائية () الخاصة بعقدنا هي الواجهة للتفاعل مع عقدنا الذكي. يقوم هارد هات تلقائيًا بإنشاء واجهة التطبيق الثنائية (ABI) وحفظها في HelloWorld.json. لاستخدام واجهة التطبيق الثنائية (ABI)، سنحتاج إلى تحليل المحتويات عن طريق إضافة الأسطر التالية من الكود إلى ملف interact.js الخاص بنا:
1// interact.js2const contract = require("../artifacts/contracts/HelloWorld.sol/HelloWorld.json")إذا كنت تريد رؤية واجهة ABI، فيمكنك طباعتها على وحدة التحكم الخاصة بك:
1console.log(JSON.stringify(contract.abi))لرؤية واجهة التطبيق الثنائية (ABI) مطبوعة على وحدة التحكم، انتقل إلى الطرفية وقم بتشغيل:
npx hardhat run scripts/interact.jsإنشاء مثيل من عقدك
للتفاعل مع عقدنا، نحتاج إلى إنشاء مثيل للعقد في الكود الخاص بنا. للقيام بذلك باستخدام إيثرز.جي إس، سنحتاج إلى العمل مع ثلاثة مفاهيم:
- Provider - مزود عقدة يمنحك حق الوصول للقراءة والكتابة إلى البلوكتشين
- Signer - يمثل حساب إيثريوم يمكنه توقيع المعاملات
- Contract - كائن إيثرز.جي إس يمثل عقدًا محددًا منشورًا على السلسلة
سنستخدم واجهة التطبيق الثنائية (ABI) الخاصة بالعقد من الخطوة السابقة لإنشاء مثيل العقد الخاص بنا:
1// interact.js2
3// Provider4const alchemyProvider = new ethers.providers.AlchemyProvider(5 (network = "goerli"),6 API_KEY7)8
9// Signer10const signer = new ethers.Wallet(PRIVATE_KEY, alchemyProvider)11
12// Contract13const helloWorldContract = new ethers.Contract(14 CONTRACT_ADDRESS,15 contract.abi,16 signer17)اعرف المزيد عن Providers وSigners وContracts في توثيق ethers.js (opens in a new tab).
قراءة الرسالة الأولية
هل تتذكر عندما نشرنا عقدنا مع initMessage = "Hello world!"؟ سنقوم الآن بقراءة تلك الرسالة المخزنة في عقدنا الذكي وطباعتها على وحدة التحكم.
في جافا سكريبت، تُستخدم الدوال غير المتزامنة عند التفاعل مع الشبكات. لمعرفة المزيد عن الدوال غير المتزامنة، اقرأ هذا المقال على Medium (opens in a new tab).
استخدم الكود أدناه لاستدعاء دالة message في عقدنا الذكي وقراءة الرسالة الأولية:
1// interact.js2
3// ...4
5async function main() {6 const message = await helloWorldContract.message()7 console.log("The message is: " + message)8}9main()بعد تشغيل الملف باستخدام npx hardhat run scripts/interact.js في الطرفية، يجب أن نرى هذه الاستجابة:
1الرسالة هي: Hello world!تهانينا! لقد قرأت بنجاح بيانات العقد الذكي من بلوكتشين إيثريوم، أحسنت!
تحديث الرسالة
بدلاً من مجرد قراءة الرسالة، يمكننا أيضًا تحديث الرسالة المحفوظة في عقدنا الذكي باستخدام دالة update! رائع، أليس كذلك؟
لتحديث الرسالة، يمكننا استدعاء دالة update مباشرة على كائن العقد المنشأ:
1// interact.js2
3// ...4
5async function main() {6 const message = await helloWorldContract.message()7 console.log("الرسالة هي: " + message)8
9 console.log("جارٍ تحديث الرسالة...")10 const tx = await helloWorldContract.update("هذه هي الرسالة الجديدة.")11 await tx.wait()12}13main()لاحظ أننا في السطر 11، نقوم باستدعاء .wait() على كائن المعاملة المرجع. يضمن هذا أن السكريبت الخاص بنا ينتظر حتى يتم تعدين المعاملة على البلوكتشين قبل الخروج من الدالة. إذا لم يتم تضمين استدعاء .wait()، فقد لا يرى السكريبت قيمة message المحدثة في العقد.
قراءة الرسالة الجديدة
يجب أن تكون قادرًا على تكرار الخطوة السابقة لقراءة قيمة message المحدثة. خذ لحظة وانظر ما إذا كان بإمكانك إجراء التغييرات اللازمة لطباعة تلك القيمة الجديدة!
إذا كنت بحاجة إلى تلميح، فإليك كيف يجب أن يبدو ملف interact.js الخاص بك في هذه المرحلة:
1// interact.js2
3const API_KEY = process.env.API_KEY4const PRIVATE_KEY = process.env.PRIVATE_KEY5const CONTRACT_ADDRESS = process.env.CONTRACT_ADDRESS6
7const contract = require("../artifacts/contracts/HelloWorld.sol/HelloWorld.json")8
9// provider - Alchemy10const alchemyProvider = new ethers.providers.AlchemyProvider(11 (network = "goerli"),12 API_KEY13)14
15// signer - you16const signer = new ethers.Wallet(PRIVATE_KEY, alchemyProvider)17
18// contract instance19const helloWorldContract = new ethers.Contract(20 CONTRACT_ADDRESS,21 contract.abi,22 signer23)24
25async function main() {26 const message = await helloWorldContract.message()27 console.log("الرسالة هي: " + message)28
29 console.log("جارٍ تحديث الرسالة...")30 const tx = await helloWorldContract.update("هذه هي الرسالة الجديدة")31 await tx.wait()32
33 const newMessage = await helloWorldContract.message()34 console.log("الرسالة الجديدة هي: " + newMessage)35}36
37main()الآن فقط قم بتشغيل السكريبت وستتمكن من رؤية الرسالة القديمة، وحالة التحديث، والرسالة الجديدة مطبوعة في الطرفية الخاصة بك!
npx hardhat run scripts/interact.js --network goerli
1الرسالة هي: Hello World!2جارٍ تحديث الرسالة...3الرسالة الجديدة هي: هذه هي الرسالة الجديدة.أثناء تشغيل هذا السكريبت، قد تلاحظ أن خطوة جارٍ تحديث الرسالة... تستغرق بعض الوقت للتحميل قبل تحميل الرسالة الجديدة. هذا بسبب عملية التعدين؛ إذا كنت مهتمًا بتتبع المعاملات أثناء تعدينها، فقم بزيارة ألكيمي mempool (opens in a new tab) لرؤية حالة المعاملة. إذا تم إسقاط المعاملة، فمن المفيد أيضًا التحقق من جيرلي إيثرسكان (opens in a new tab) والبحث عن تجزئة (هاش) معاملتك.
الجزء 3: نشر عقدك الذكي على إيثرسكان
لقد قمت بكل العمل الشاق لإحياء عقدك الذكي؛ الآن حان الوقت لمشاركته مع العالم!
من خلال التحقق من عقدك الذكي على إيثرسكان، يمكن لأي شخص عرض الكود المصدري الخاص بك والتفاعل مع عقدك الذكي. هيا بنا نبدأ!
الخطوة 1: إنشاء مفتاح API على حساب إيثرسكان الخاص بك
مفتاح API الخاص بـ إيثرسكان ضروري للتحقق من أنك تملك العقد الذكي الذي تحاول نشره.
إذا لم يكن لديك حساب إيثرسكان بالفعل، سجل للحصول على حساب (opens in a new tab).
بمجرد تسجيل الدخول، ابحث عن اسم المستخدم الخاص بك في شريط التنقل، مرر فوقه وحدد زر ملفي الشخصي.
في صفحة ملفك الشخصي، يجب أن ترى شريط تنقل جانبي. من شريط التنقل الجانبي، حدد مفاتيح API. بعد ذلك، اضغط على زر "إضافة" لإنشاء مفتاح API جديد، وسمّي تطبيقك hello-world واضغط على زر إنشاء مفتاح API جديد.
يجب أن يظهر مفتاح API الجديد الخاص بك في جدول مفاتيح API. انسخ مفتاح API إلى الحافظة.
بعد ذلك، نحتاج إلى إضافة مفتاح API الخاص بـ إيثرسكان إلى ملف .env الخاص بنا.
بعد إضافته، يجب أن يبدو ملف .env الخاص بك كالتالي:
1API_URL = "https://eth-goerli.alchemyapi.io/v2/your-api-key"2PUBLIC_KEY = "your-public-account-address"3PRIVATE_KEY = "your-private-account-address"4CONTRACT_ADDRESS = "your-contract-address"5ETHERSCAN_API_KEY = "your-etherscan-key"العقود الذكية المنشورة بواسطة هارد هات
تثبيت hardhat-etherscan
نشر عقدك على إيثرسكان باستخدام هارد هات أمر بسيط. ستحتاج أولاً إلى تثبيت المكون الإضافي hardhat-etherscan للبدء. سيقوم hardhat-etherscan تلقائيًا بالتحقق من الكود المصدري للعقد الذكي وواجهة التطبيق الثنائية (ABI) على إيثرسكان. لإضافة هذا، في دليل hello-world قم بتشغيل:
1npm install --save-dev @nomiclabs/hardhat-etherscanبمجرد التثبيت، قم بتضمين العبارة التالية في الجزء العلوي من hardhat.config.js الخاص بك، وأضف خيارات تكوين إيثرسكان:
1// hardhat.config.js2
3require("dotenv").config()4require("@nomiclabs/hardhat-ethers")5require("@nomiclabs/hardhat-etherscan")6
7const { API_URL, PRIVATE_KEY, ETHERSCAN_API_KEY } = process.env8
9module.exports = {10 solidity: "0.7.3",11 defaultNetwork: "goerli",12 networks: {13 hardhat: {},14 goerli: {15 url: API_URL,16 accounts: [`0x${PRIVATE_KEY}`],17 },18 },19 etherscan: {20 // مفتاح API الخاص بك لـ Etherscan21 // احصل على واحد من https://etherscan.io/22 apiKey: ETHERSCAN_API_KEY,23 },24}التحقق من عقدك الذكي على إيثرسكان
تأكد من حفظ جميع الملفات وتكوين جميع متغيرات .env بشكل صحيح.
قم بتشغيل مهمة verify، مع تمرير عنوان العقد، والشبكة التي تم نشره عليها:
1npx hardhat verify --network goerli DEPLOYED_CONTRACT_ADDRESS 'Hello World!'تأكد من أن DEPLOYED_CONTRACT_ADDRESS هو عنوان عقدك الذكي المنشور على شبكة اختبار جيرلي. أيضًا، يجب أن يكون الوسيط الأخير ('Hello World!') هو نفس قيمة السلسلة المستخدمة أثناء خطوة النشر في الجزء 1.
إذا سارت الأمور على ما يرام، سترى الرسالة التالية في الطرفية:
1تم إرسال الكود المصدري للعقد بنجاح2contracts/HelloWorld.sol:HelloWorld at 0xdeployed-contract-address3للتحقق على Etherscan. في انتظار نتيجة التحقق...4
5تم التحقق من العقد HelloWorld بنجاح على Etherscan.6https://goerli.etherscan.io/address/<contract-address>#contractsتهانينا! الكود المصدري لعقدك الذكي موجود على إيثرسكان!
تحقق من عقدك الذكي على إيثرسكان!
عندما تنتقل إلى الرابط الموجود في الطرفية، يجب أن تكون قادرًا على رؤية الكود المصدري لعقدك الذكي وواجهة التطبيق الثنائية (ABI) منشورة على إيثرسكان!
يا للروعة - لقد فعلتها يا بطل! الآن يمكن لأي شخص استدعاء عقدك الذكي أو الكتابة إليه! لا يسعنا الانتظار لرؤية ما ستبنيه بعد ذلك!
الجزء 4 - دمج عقدك الذكي مع الواجهة الأمامية
بحلول نهاية هذا الدرس التعليمي، ستعرف كيفية:
- توصيل محفظة ميتاماسك بتطبيقك اللامركزي
- قراءة البيانات من عقدك الذكي باستخدام واجهة برمجة تطبيقات ألكيمي ويب3 (opens in a new tab)
- توقيع معاملات إيثريوم باستخدام ميتاماسك
بالنسبة لهذا التطبيق اللامركزي، سنستخدم رياكت (opens in a new tab) كإطار عمل للواجهة الأمامية؛ ومع ذلك، من المهم ملاحظة أننا لن نقضي الكثير من الوقت في تحليل أساسياته، حيث سنركز في الغالب على جلب وظائف ويب3 إلى مشروعنا.
كمتطلب أساسي، يجب أن يكون لديك فهم على مستوى المبتدئين لـ رياكت. إذا لم يكن الأمر كذلك، نوصي بإكمال الدرس التعليمي الرسمي للمقدمة إلى رياكت (opens in a new tab).
استنساخ ملفات البداية
أولاً، انتقل إلى مستودع غيت هاب hello-world-part-four (opens in a new tab) للحصول على الملفات المبدئية لهذا المشروع وانسخ هذا المستودع إلى جهازك المحلي.
افتح المستودع المنسوخ محليًا. لاحظ أنه يحتوي على مجلدين: starter-files و completed.
starter-files- سنعمل في هذا الدليل، وسنقوم بتوصيل واجهة المستخدم بمحفظة إيثريوم الخاصة بك وبالعقد الذكي الذي نشرناه على إيثرسكان في الجزء 3.- يحتوي
completedعلى الدرس التعليمي الكامل ويجب استخدامه فقط كمرجع إذا واجهتك مشكلة.
بعد ذلك، افتح نسختك من starter-files في محرر الكود المفضل لديك، ثم انتقل إلى مجلد src.
ستكون جميع الأكواد التي سنكتبها ضمن مجلد src. سنقوم بتحرير مكون HelloWorld.js وملفات جافا سكريبت util/interact.js لإعطاء مشروعنا وظائف ويب3.
تحقق من الملفات المبدئية
قبل أن نبدأ في البرمجة، دعنا نستكشف ما هو متاح لنا في الملفات المبدئية.
تشغيل مشروع رياكت الخاص بك
لنبدأ بتشغيل مشروع React في المتصفح. جمال React هو أنه بمجرد تشغيل مشروعنا في المتصفح، سيتم تحديث أي تغييرات نحفظها مباشرة في المتصفح.
لتشغيل المشروع، انتقل إلى الدليل الجذر لمجلد starter-files، ثم قم بتشغيل npm install في الطرفية لتثبيت تبعيات المشروع:
cd starter-filesnpm installبمجرد الانتهاء من تثبيتها، قم بتشغيل npm start في الطرفية الخاصة بك:
npm startيجب أن يؤدي ذلك إلى فتح http://localhost:3000/ (opens in a new tab) في متصفحك، حيث سترى الواجهة الأمامية لمشروعنا. يجب أن يتكون من حقل واحد (مكان لتحديث الرسالة المخزنة في عقدك الذكي)، وزر "توصيل المحفظة"، وزر "تحديث".
إذا حاولت النقر على أي من الزرين، ستلاحظ أنهما لا يعملان - وهذا لأننا ما زلنا بحاجة إلى برمجة وظائفهما.
مكون HelloWorld.js
دعنا نعد إلى مجلد src في محررنا ونفتح ملف HelloWorld.js. من المهم جداً أن نفهم كل شيء في هذا الملف، لأنه مكون React الأساسي الذي سنعمل عليه.
في الجزء العلوي من هذا الملف، ستلاحظ أن لدينا العديد من عبارات الاستيراد الضرورية لتشغيل مشروعنا، بما في ذلك مكتبة رياكت، وخطافات useEffect وuseState، وبعض العناصر من ./util/interact.js (سنصفها بمزيد من التفصيل قريبًا!)، وشعار ألكيمي.
1// HelloWorld.js2
3import React from "react"4import { useEffect, useState } from "react"5import {6 helloWorldContract,7 connectWallet,8 updateMessage,9 loadCurrentMessage,10 getCurrentWalletConnected,11} from "./util/interact.js"12
13import alchemylogo from "./alchemylogo.svg"بعد ذلك، لدينا متغيرات الحالة التي سنقوم بتحديثها بعد أحداث معينة.
1// HelloWorld.js2
3//متغيرات الحالة4const [walletAddress, setWallet] = useState("")5const [status, setStatus] = useState("")6const [message, setMessage] = useState("لا يوجد اتصال بالشبكة.")7const [newMessage, setNewMessage] = useState("")إليك ما يمثله كل متغير من المتغيرات:
walletAddress- سلسلة نصية تخزن عنوان محفظة المستخدمstatus- سلسلة تخزن رسالة مفيدة توجه المستخدم حول كيفية التفاعل مع التطبيق اللامركزيmessage- سلسلة تخزن الرسالة الحالية في العقد الذكيnewMessage- سلسلة تخزن الرسالة الجديدة التي سيتم كتابتها في العقد الذكي
بعد متغيرات الحالة، سترى خمس دوال غير منفذة: useEffect، addSmartContractListener، addWalletListener، connectWalletPressed، وonUpdatePressed. سنشرح ما تفعله أدناه:
1// HelloWorld.js2
3//يتم استدعاؤها مرة واحدة فقط4useEffect(async () => {5 //TODO: implement6}, [])7
8function addSmartContractListener() {9 //TODO: implement10}11
12function addWalletListener() {13 //TODO: implement14}15
16const connectWalletPressed = async () => {17 //TODO: implement18}19
20const onUpdatePressed = async () => {21 //TODO: implement22}useEffect(opens in a new tab)- هو خطاف رياكت يتم استدعاؤه بعد عرض مكونك. نظرًا لأنه يحتوي على خاصية مصفوفة فارغة[]تم تمريرها إليه (انظر السطر 4)، فسيتم استدعاؤه فقط عند العرض الأول للمكون. هنا سنقوم بتحميل الرسالة الحالية المخزنة في عقدنا الذكي، واستدعاء مستمعي العقد الذكي والمحفظة، وتحديث واجهة المستخدم لتعكس ما إذا كانت المحفظة متصلة بالفعل.addSmartContractListener- تقوم هذه الدالة بإعداد مستمع سيراقب حدثUpdatedMessagesالخاص بعقد HelloWorld ويقوم بتحديث واجهة المستخدم عند تغيير الرسالة في عقدنا الذكي.addWalletListener- تقوم هذه الدالة بإعداد مستمع يكتشف التغييرات في حالة محفظة ميتاماسك للمستخدم، مثل عندما يقوم المستخدم بقطع اتصال محفظته أو تبديل العناوين.connectWalletPressed- سيتم استدعاء هذه الدالة لتوصيل محفظة ميتاماسك للمستخدم بتطبيقنا اللامركزي.onUpdatePressed- سيتم استدعاء هذه الدالة عندما يرغب المستخدم في تحديث الرسالة المخزنة في العقد الذكي.
بالقرب من نهاية هذا الملف، لدينا واجهة المستخدم (UI) الخاصة بمكوننا.
1// HelloWorld.js2
3//واجهة المستخدم الخاصة بمكوننا4return (5 <div id="container">6 <img id="logo" src={alchemylogo}></img>7 <button id="walletButton" onClick={connectWalletPressed}>8 {walletAddress.length > 0 ? (9 "متصل: " +10 String(walletAddress).substring(0, 6) +11 "..." +12 String(walletAddress).substring(38)13 ) : (14 <span>توصيل المحفظة</span>15 )}16 </button>17
18 <h2 style={{ paddingTop: "50px" }}>الرسالة الحالية:</h2>19 <p>{message}</p>20
21 <h2 style={{ paddingTop: "18px" }}>رسالة جديدة:</h2>22
23 <div>24 <input25 type="text"26 placeholder="قم بتحديث الرسالة في عقدك الذكي."27 onChange={(e) => setNewMessage(e.target.value)}28 value={newMessage}29 />30 <p id="status">{status}</p>31
32 <button id="publishButton" onClick={onUpdatePressed}>33 تحديث34 </button>35</div>36 37</div>38)إذا قمت بفحص هذا الكود بعناية، ستلاحظ أين نستخدم متغيرات الحالة المختلفة في واجهة المستخدم لدينا:
- في الأسطر 6-12، إذا كانت محفظة المستخدم متصلة (أي
walletAddress.length > 0)، فإننا نعرض نسخة مختصرة منwalletAddressللمستخدم في الزر الذي يحمل المعرف "walletButton"؛ وإلا فإنه يقول ببساطة "توصيل المحفظة". - في السطر 17، نعرض الرسالة الحالية المخزنة في العقد الذكي، والتي يتم التقاطها في سلسلة
message. - في الأسطر 23-26، نستخدم مكونًا متحكمًا فيه (opens in a new tab) لتحديث متغير الحالة
newMessageعند تغير الإدخال في حقل النص.
بالإضافة إلى متغيرات الحالة لدينا، سترى أيضًا أن دوال connectWalletPressed وonUpdatePressed يتم استدعاؤها عند النقر على الأزرار التي تحمل المعرفات publishButton وwalletButton على التوالي.
أخيرًا، دعنا نتناول أين يتم إضافة مكون HelloWorld.js هذا.
إذا انتقلت إلى ملف App.js، وهو المكون الرئيسي في رياكت الذي يعمل كحاوية لجميع المكونات الأخرى، فسترى أن مكون HelloWorld.js الخاص بنا يتم إدخاله في السطر 7.
أخيرًا وليس آخرًا، دعنا نتحقق من ملف آخر تم توفيره لك، وهو ملف interact.js.
ملف interact.js
نظرًا لأننا نريد الالتزام بنموذج M-V-C (opens in a new tab)، سنحتاج إلى ملف منفصل يحتوي على جميع وظائفنا لإدارة المنطق والبيانات وقواعد تطبيقنا اللامركزي، ثم نكون قادرين على تصدير هذه الوظائف إلى واجهتنا الأمامية (مكون HelloWorld.js الخاص بنا).
👆🏽هذا هو الغرض الدقيق من ملف interact.js الخاص بنا!
انتقل إلى مجلد util في دليل src الخاص بك، وستلاحظ أننا قمنا بتضمين ملف يسمى interact.js سيحتوي على جميع وظائف ومتغيرات التفاعل مع العقد الذكي والمحفظة.
1// interact.js2
3//export const helloWorldContract;4
5export const loadCurrentMessage = async () => {}6
7export const connectWallet = async () => {}8
9const getCurrentWalletConnected = async () => {}10
11export const updateMessage = async (message) => {}ستلاحظ في الجزء العلوي من الملف أننا قمنا بالتعليق على كائن helloWorldContract. لاحقًا في هذا الدرس التعليمي، سنقوم بإلغاء التعليق على هذا الكائن وإنشاء مثيل لعقدنا الذكي في هذا المتغير، والذي سنقوم بعد ذلك بتصديره إلى مكون HelloWorld.js الخاص بنا.
الدوال الأربع غير المنفذة بعد كائن helloWorldContract تقوم بما يلي:
loadCurrentMessage- تعالج هذه الدالة منطق تحميل الرسالة الحالية المخزنة في العقد الذكي. ستقوم بإجراء استدعاء قراءة إلى عقد Hello World الذكي باستخدام واجهة برمجة تطبيقات ألكيمي ويب3 (opens in a new tab).connectWallet- ستقوم هذه الدالة بتوصيل ميتاماسك الخاص بالمستخدم بتطبيقنا اللامركزي.getCurrentWalletConnected- ستتحقق هذه الدالة مما إذا كان حساب إيثريوم متصلاً بالفعل بتطبيقنا اللامركزي عند تحميل الصفحة وتقوم بتحديث واجهة المستخدم لدينا وفقًا لذلك.updateMessage- ستقوم هذه الدالة بتحديث الرسالة المخزنة في العقد الذكي. ستقوم بإجراء استدعاء كتابة إلى عقد Hello World الذكي، لذلك سيتعين على محفظة ميتاماسك الخاصة بالمستخدم توقيع معاملة إيثريوم لتحديث الرسالة.
الآن بعد أن فهمنا ما نعمل به، دعنا نكتشف كيفية القراءة من عقدنا الذكي!
الخطوة 3: القراءة من عقدك الذكي
للقراءة من عقدك الذكي، ستحتاج إلى الإعداد بنجاح:
- اتصال API بسلسلة إيثريوم
- مثيل محمل من عقدك الذكي
- دالة لاستدعاء دالة عقدك الذكي
- مستمع لمراقبة التحديثات عندما تتغير البيانات التي تقرأها من العقد الذكي
قد يبدو هذا كثيرًا من الخطوات، لكن لا تقلق! سوف نرشدك خلال كيفية القيام بكل منها خطوة بخطوة! :)
إنشاء اتصال API بسلسلة إيثريوم
هل تتذكر كيف استخدمنا في الجزء 2 من هذا الدرس التعليمي مفتاح ألكيمي ويب3 الخاص بنا للقراءة من عقدنا الذكي (opens in a new tab)؟ ستحتاج أيضًا إلى مفتاح ألكيمي ويب3 في تطبيقك اللامركزي للقراءة من السلسلة.
إذا لم يكن لديك بالفعل، فقم أولاً بتثبيت ألكيمي ويب3 (opens in a new tab) عن طريق الانتقال إلى الدليل الجذر لـ starter-files وتشغيل ما يلي في الطرفية:
1npm install @alch/alchemy-web3ألكيمي ويب3 (opens in a new tab) هو غلاف حول ويب3.جي إس (opens in a new tab)، يوفر طرق API محسنة ومزايا أخرى حاسمة لجعل حياتك كمطور web3 أسهل. It is designed to require minimal configuration so you can start using it in your app right away!
بعد ذلك، قم بتثبيت حزمة dotenv (opens in a new tab) في دليل مشروعك، حتى يكون لدينا مكان آمن لتخزين مفتاح API الخاص بنا بعد جلبه.
1npm install dotenv --saveبالنسبة لتطبيقنا اللامركزي، سنستخدم مفتاح API الخاص بـ Websockets بدلاً من مفتاح API الخاص بـ HTTP، حيث سيسمح لنا بإعداد مستمع يكتشف متى تتغير الرسالة المخزنة في العقد الذكي.
بمجرد حصولك على مفتاح API الخاص بك، قم بإنشاء ملف .env في الدليل الجذر الخاص بك وأضف عنوان URL الخاص بـ ألكيمي Websockets إليه. بعد ذلك، يجب أن يبدو ملف .env الخاص بك كما يلي:
1REACT_APP_ALCHEMY_KEY = wss://eth-goerli.ws.alchemyapi.io/v2/<key>الآن، نحن جاهزون لإعداد نقطة نهاية ألكيمي ويب3 في تطبيقنا اللامركزي! دعنا نعد إلى interact.js الخاص بنا، الموجود داخل مجلد util الخاص بنا ونضيف الكود التالي في الجزء العلوي من الملف:
1// interact.js2
3require("dotenv").config()4const alchemyKey = process.env.REACT_APP_ALCHEMY_KEY5const { createAlchemyWeb3 } = require("@alch/alchemy-web3")6const web3 = createAlchemyWeb3(alchemyKey)7
8//export const helloWorldContract;أعلاه، قمنا أولاً باستيراد مفتاح ألكيمي من ملف .env الخاص بنا ثم قمنا بتمرير alchemyKey الخاص بنا إلى createAlchemyWeb3 لإنشاء نقطة نهاية ألكيمي ويب3 الخاصة بنا.
مع جاهزية نقطة النهاية هذه، حان الوقت لتحميل عقدنا الذكي!
تحميل عقد Hello World الذكي الخاص بك
لتحميل عقد Hello World الذكي الخاص بك، ستحتاج إلى عنوان العقد الخاص به وواجهة التطبيق الثنائية (ABI)، وكلاهما يمكن العثور عليهما على إيثرسكان إذا أكملت الجزء 3 من هذا الدرس التعليمي.
كيفية الحصول على واجهة التطبيق الثنائية (ABI) الخاصة بعقدك من إيثرسكان
إذا تخطيت الجزء 3 من هذا الدرس التعليمي، يمكنك استخدام عقد HelloWorld بالعنوان 0x6f3f635A9762B47954229Ea479b4541eAF402A6A (opens in a new tab). يمكن العثور على واجهة التطبيق الثنائية (ABI) الخاصة به هنا (opens in a new tab).
واجهة التطبيق الثنائية (ABI) للعقد ضرورية لتحديد الدالة التي سيستدعيها العقد وكذلك لضمان أن الدالة ستعيد البيانات بالتنسيق الذي تتوقعه. بمجرد نسخ واجهة التطبيق الثنائية (ABI) الخاصة بعقدنا، دعنا نحفظها كملف JSON يسمى contract-abi.json في دليل src الخاص بك.
يجب تخزين contract-abi.json في مجلد src الخاص بك.
مسلحين بعنوان عقدنا، وواجهة التطبيق الثنائية (ABI)، ونقطة نهاية ألكيمي ويب3، يمكننا استخدام طريقة العقد (opens in a new tab) لتحميل مثيل من عقدنا الذكي. استورد واجهة التطبيق الثنائية (ABI) الخاصة بعقدك إلى ملف interact.js وأضف عنوان عقدك.
1// interact.js2
3const contractABI = require("../contract-abi.json")4const contractAddress = "0x6f3f635A9762B47954229Ea479b4541eAF402A6A"يمكننا الآن أخيرًا إلغاء التعليق على متغير helloWorldContract الخاص بنا، وتحميل العقد الذكي باستخدام نقطة نهاية AlchemyWeb3 الخاصة بنا:
1// interact.js2export const helloWorldContract = new web3.eth.Contract(3 contractABI,4 contractAddress5)لتلخيص ذلك، يجب أن تبدو الأسطر الـ 12 الأولى من interact.js الخاص بك الآن كما يلي:
1// interact.js2
3require("dotenv").config()4const alchemyKey = process.env.REACT_APP_ALCHEMY_KEY5const { createAlchemyWeb3 } = require("@alch/alchemy-web3")6const web3 = createAlchemyWeb3(alchemyKey)7
8const contractABI = require("../contract-abi.json")9const contractAddress = "0x6f3f635A9762B47954229Ea479b4541eAF402A6A"10
11export const helloWorldContract = new web3.eth.Contract(12 contractABI,13 contractAddress14)الآن بعد أن قمنا بتحميل عقدنا، يمكننا تنفيذ دالة loadCurrentMessage الخاصة بنا!
تنفيذ loadCurrentMessage في ملف interact.js الخاص بك
هذه الدالة بسيطة جدًا. سنقوم بإجراء استدعاء web3 غير متزامن بسيط للقراءة من عقدنا. ستعيد دالتنا الرسالة المخزنة في العقد الذكي:
قم بتحديث loadCurrentMessage في ملف interact.js الخاص بك إلى ما يلي:
1// interact.js2
3export const loadCurrentMessage = async () => {4 const message = await helloWorldContract.methods.message().call()5 return message6}نظرًا لأننا نريد عرض هذا العقد الذكي في واجهة المستخدم لدينا، فلنقم بتحديث دالة useEffect في مكون HelloWorld.js الخاص بنا إلى ما يلي:
1// HelloWorld.js2
3//يتم استدعاؤها مرة واحدة فقط4useEffect(async () => {5 const message = await loadCurrentMessage()6 setMessage(message)7}, [])لاحظ أننا نريد فقط استدعاء loadCurrentMessage مرة واحدة أثناء العرض الأول للمكون. سنقوم قريبًا بتنفيذ addSmartContractListener لتحديث واجهة المستخدم تلقائيًا بعد تغيير الرسالة في العقد الذكي.
قبل أن نتعمق في المستمع الخاص بنا، دعنا نتحقق مما لدينا حتى الآن! احفظ ملفي HelloWorld.js وinteract.js، ثم انتقل إلى http://localhost:3000/ (opens in a new tab)
ستلاحظ أن الرسالة الحالية لم تعد تقول "لا يوجد اتصال بالشبكة." بدلاً من ذلك، تعكس الرسالة المخزنة في العقد الذكي. رائع!
يجب أن تعكس واجهة المستخدم الخاصة بك الآن الرسالة المخزنة في العقد الذكي
والآن بالحديث عن هذا المستمع...
تنفيذ addSmartContractListener
إذا عدت بذاكرتك إلى ملف HelloWorld.sol الذي كتبناه في الجزء 1 من هذه السلسلة التعليمية (opens in a new tab)، ستتذكر أن هناك حدث عقد ذكي يسمى UpdatedMessages يتم إصداره بعد استدعاء دالة update في عقدنا الذكي (انظر الأسطر 9 و27):
1// HelloWorld.sol2
3// يحدد إصدار Solidity، باستخدام الإصدار الدلالي.4// اعرف المزيد: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma5pragma solidity ^0.7.3;6
7// يُعرّف عقدًا باسم 'HelloWorld'.8// العقد هو مجموعة من الوظائف والبيانات (حالته). بمجرد نشره، يقيم العقد في عنوان محدد على بلوكتشين إيثريوم. اعرف المزيد: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html9contract HelloWorld {10
11 //يتم إصداره عند استدعاء دالة التحديث12 //تعد أحداث العقود الذكية وسيلة لعقدك لإبلاغ الواجهة الأمامية لتطبيقك بحدوث شيء ما على البلوكتشين، والتي يمكن أن "تستمع" لأحداث معينة وتتخذ إجراءات عند حدوثها.13 event UpdatedMessages(string oldStr, string newStr);14
15 // يصرح عن متغير حالة 'message' من النوع 'string'.16 // متغيرات الحالة هي متغيرات تُخزن قيمها بشكل دائم في تخزين العقد. الكلمة المفتاحية 'public' تجعل المتغيرات قابلة للوصول من خارج العقد وتنشئ دالة يمكن للعقود أو العملاء الآخرين استدعاؤها للوصول إلى القيمة.17 string public message;18
19 // على غرار العديد من اللغات الكائنية التوجه القائمة على الأصناف، المُنشئ هو دالة خاصة تُنفذ فقط عند إنشاء العقد.20 // تُستخدم المُنشئات لتهيئة بيانات العقد. اعرف المزيد:https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors21 constructor(string memory initMessage) {22
23 // يقبل وسيط سلسلة 'initMessage' ويضبط القيمة في متغير التخزين 'message' الخاص بالعقد).24 message = initMessage;25 }26
27 // دالة عامة تقبل وسيط سلسلة وتُحدّث متغير التخزين 'message'.28 function update(string memory newMessage) public {29 string memory oldMsg = message;30 message = newMessage;31 emit UpdatedMessages(oldMsg, newMessage);32 }33}تعد أحداث العقود الذكية وسيلة لعقدك لإبلاغ تطبيق الواجهة الأمامية بحدوث شيء ما (أي، كان هناك حدث) على البلوكتشين، والذي يمكن أن "يستمع" لأحداث معينة ويتخذ إجراءات عند حدوثها.
ستستمع دالة addSmartContractListener بشكل خاص لحدث UpdatedMessages الخاص بعقد Hello World الذكي، وستقوم بتحديث واجهة المستخدم لدينا لعرض الرسالة الجديدة.
عدّل addSmartContractListener إلى ما يلي:
1// HelloWorld.js2
3function addSmartContractListener() {4 helloWorldContract.events.UpdatedMessages({}, (error, data) => {5 if (error) {6 setStatus("😥 " + error.message)7 } else {8 setMessage(data.returnValues[1])9 setNewMessage("")10 setStatus("🎉 تم تحديث رسالتك!")11 }12 })13}دعنا نحلل ما يحدث عندما يكتشف المستمع حدثًا:
- إذا حدث خطأ عند إصدار الحدث، فسينعكس ذلك في واجهة المستخدم عبر متغير الحالة
statusالخاص بنا. - وإلا، سنستخدم كائن
dataالمرجع.data.returnValuesهي مصفوفة مفهرسة من الصفر حيث يخزن العنصر الأول في المصفوفة الرسالة السابقة ويخزن العنصر الثاني الرسالة المحدثة. بشكل عام، عند وقوع حدث ناجح، سنقوم بتعيين سلسلةmessageالخاصة بنا إلى الرسالة المحدثة، ومسح سلسلةnewMessage، وتحديث متغير الحالةstatusالخاص بنا ليعكس أنه تم نشر رسالة جديدة على عقدنا الذكي.
أخيرًا، دعنا نستدعي المستمع الخاص بنا في دالة useEffect الخاصة بنا حتى يتم تهيئته عند العرض الأول لمكون HelloWorld.js. بشكل عام، يجب أن تبدو دالة useEffect الخاصة بك كما يلي:
1// HelloWorld.js2
3useEffect(async () => {4 const message = await loadCurrentMessage()5 setMessage(message)6 addSmartContractListener()7}, [])الآن بعد أن أصبحنا قادرين على القراءة من عقدنا الذكي، سيكون من الرائع معرفة كيفية الكتابة إليه أيضًا! ومع ذلك، للكتابة إلى تطبيقنا اللامركزي، يجب أن تكون لدينا أولاً محفظة إيثريوم متصلة به.
لذا، بعد ذلك، سنتناول إعداد محفظة إيثريوم الخاصة بنا (ميتاماسك) ثم توصيلها بتطبيقنا اللامركزي!
الخطوة 4: إعداد محفظة إيثريوم الخاصة بك
لكتابة أي شيء على سلسلة إيثريوم، يجب على المستخدمين توقيع المعاملات باستخدام المفاتيح الخاصة بمحافظهم الافتراضية. في هذا الدرس التعليمي، سنستخدم ميتاماسك (opens in a new tab)، وهي محفظة افتراضية في المتصفح تُستخدم لإدارة عنوان حساب إيثريوم الخاص بك، لأنها تجعل توقيع المعاملات هذا سهلاً للغاية للمستخدم النهائي.
إذا كنت ترغب في فهم المزيد حول كيفية عمل المعاملات على إيثريوم، فراجع هذه الصفحة من مؤسسة إيثريوم.
تنزيل ميتاماسك
يمكنك تنزيل وإنشاء حساب ميتاماسك مجانًا هنا (opens in a new tab). عندما تقوم بإنشاء حساب، أو إذا كان لديك حساب بالفعل، تأكد من التبديل إلى "شبكة اختبار جيرلي" في الجزء العلوي الأيمن (حتى لا نتعامل بأموال حقيقية).
إضافة الإيثر من سبيل
لتوقيع معاملة على بلوكتشين إيثريوم، سنحتاج إلى بعض من عملات الإيثر المزيفة. للحصول على إيثر، يمكنك الذهاب إلى FaucETH (opens in a new tab) وإدخال عنوان حساب جيرلي الخاص بك، والنقر على "طلب الأموال"، ثم تحديد "إيثريوم Testnet جيرلي" في القائمة المنسدلة وأخيرًا النقر على زر "طلب الأموال" مرة أخرى. You should see Eth in your ميتاماسك account soon after!
تحقق من رصيدك
للتأكد مرة أخرى من وجود رصيدنا، لنجري طلب eth_getBalance (opens in a new tab) باستخدام أداة الإنشاء من Alchemy (opens in a new tab). سيعيد هذا كمية ETH في محفظتنا. بعد إدخال عنوان حساب MetaMask الخاص بك والنقر على "Send Request"، يجب أن ترى استجابة مثل هذه:
1{"jsonrpc": "2.0", "id": 0, "result": "0xde0b6b3a7640000"}ملاحظة: هذه النتيجة بوحدة wei وليست ETH. تُستخدم wei كأصغر وحدة لـ ether. التحويل من wei إلى ETH هو: 1 ETH = 10¹⁸ wei. لذا إذا قمنا بتحويل 0xde0b6b3a7640000 إلى النظام العشري فسنحصل على 1*10¹⁸ وهو ما يعادل 1 ETH.
Phew! Our fake money is all there! 🤑
الخطوة 5: توصيل ميتاماسك بواجهة المستخدم الخاصة بك
الآن بعد أن تم إعداد محفظة MetaMask الخاصة بنا، لنقم بتوصيل تطبيقنا اللامركزي (DApp) بها!
دالة connectWallet
في ملف interact.js الخاص بنا، لنقم بتنفيذ دالة connectWallet، والتي يمكننا بعد ذلك استدعاؤها في مكون HelloWorld.js الخاص بنا.
دعنا نعدل connectWallet إلى ما يلي:
1// interact.js2
3export const connectWallet = async () => {4 if (window.ethereum) {5 try {6 const addressArray = await window.ethereum.request({7 method: "eth_requestAccounts",8 })9 const obj = {10 status: "👆🏽 اكتب رسالة في حقل النص أعلاه.",11 address: addressArray[0],12 }13 return obj14 } catch (err) {15 return {16 address: "",17 status: "😥 " + err.message,18 }19 }20 } else {21 return {22 address: "",23 status: (24 <span>25 <p>26 {" "}27 🦊 <a target="_blank" href={`https://metamask.io/download`}>28 يجب عليك تثبيت MetaMask، وهي محفظة إيثريوم افتراضية، في متصفحك.29 </a>30 </p>31 </span>32 ),33 }34 }35}إذن ما الذي يفعله هذا الكود الضخم بالضبط؟
حسنًا، أولاً، يتحقق مما إذا كان window.ethereum ممكّنًا في متصفحك.
window.ethereum هو واجهة برمجة تطبيقات (API) عالمية يتم إدراجها بواسطة ميتاماسك ومقدمي المحافظ الآخرين والتي تسمح لمواقع الويب بطلب حسابات إيثريوم الخاصة بالمستخدمين. في حالة الموافقة، يمكنه قراءة البيانات من البلوكتشين التي يتصل بها المستخدم، واقتراح أن يقوم المستخدم بتوقيع الرسائل والمعاملات . اطلع على مستندات ميتاماسك (opens in a new tab) لمزيد من المعلومات!
إذا كان window.ethereum غير موجود، فهذا يعني أن ميتاماسك غير مثبت. ينتج عن هذا إرجاع كائن JSON، حيث يكون address المرجع سلسلة فارغة، وكائن status JSX يبلغ بأن المستخدم يجب أن يقوم بتثبيت ميتاماسك.
الآن إذا كان window.ethereum موجودًا، فهنا تصبح الأمور مثيرة للاهتمام.
باستخدام حلقة try/catch، سنحاول الاتصال بـ MetaMask عن طريق استدعاء window.ethereum.request({ method: "eth_requestAccounts" }); (opens in a new tab). سيؤدي استدعاء هذه الدالة إلى فتح MetaMask في المتصفح، حيث سيُطلب من المستخدم توصيل محفظته بتطبيقك اللامركزي.
- إذا اختار المستخدم الاتصال، فإن
method: "eth_requestAccounts"ستعيد مصفوفة تحتوي على جميع عناوين حسابات المستخدم المتصلة بالتطبيق اللامركزي. إجمالاً، ستعيد دالةconnectWalletالخاصة بنا كائن JSON يحتوي على أولaddressفي هذه المصفوفة (انظر السطر 9) ورسالةstatusتحث المستخدم على كتابة رسالة إلى العقد الذكي. - إذا رفض المستخدم الاتصال، فسيحتوي كائن JSON على سلسلة فارغة لـ
addressالمرجع ورسالةstatusتعكس أن المستخدم رفض الاتصال.
الآن بعد أن كتبنا دالة connectWallet هذه، فإن الخطوة التالية هي استدعاؤها في مكون HelloWorld.js الخاص بنا.
إضافة دالة connectWallet إلى مكون واجهة المستخدم HelloWorld.js الخاص بك
انتقل إلى دالة connectWalletPressed في HelloWorld.js، وقم بتحديثها إلى ما يلي:
1// HelloWorld.js2
3const connectWalletPressed = async () => {4 const walletResponse = await connectWallet()5 setStatus(walletResponse.status)6 setWallet(walletResponse.address)7}هل تلاحظ كيف يتم تجريد معظم وظائفنا بعيدًا عن مكون HelloWorld.js من ملف interact.js؟ This is so we comply with the M-V-C paradigm!
في connectWalletPressed، نقوم ببساطة بإجراء استدعاء await لدالة connectWallet المستوردة، وباستخدام استجابتها، نقوم بتحديث متغيري status و walletAddress عبر خطافات الحالة الخاصة بهما.
الآن، دعنا نحفظ كلا الملفين (HelloWorld.js وinteract.js) ونختبر واجهة المستخدم الخاصة بنا حتى الآن.
افتح متصفحك على صفحة http://localhost:3000/ (opens in a new tab)، واضغط على زر "توصيل المحفظة" في الجزء العلوي الأيمن من الصفحة.
إذا كان لديك MetaMask مثبتاً، فيجب أن يُطلب منك توصيل محفظتك بتطبيقك اللامركزي. اقبل الدعوة للاتصال.
يجب أن ترى أن زر المحفظة يعكس الآن أن عنوانك متصل! يا سلام 🔥
بعد ذلك، حاول تحديث الصفحة... هذا غريب. Our wallet button is prompting us to connect ميتاماسك, even though it is already connected...
لكن لا تخف! يمكننا معالجة ذلك بسهولة (هل فهمت التورية؟) من خلال تنفيذ getCurrentWalletConnected، والذي سيتحقق مما إذا كان العنوان متصلاً بالفعل بتطبيقنا اللامركزي وتحديث واجهة المستخدم لدينا وفقًا لذلك!
دالة getCurrentWalletConnected
قم بتحديث دالة getCurrentWalletConnected في ملف interact.js إلى ما يلي:
1// interact.js2
3export const getCurrentWalletConnected = async () => {4 if (window.ethereum) {5 try {6 const addressArray = await window.ethereum.request({7 method: "eth_accounts",8 })9 if (addressArray.length > 0) {10 return {11 address: addressArray[0],12 status: "👆🏽 اكتب رسالة في حقل النص أعلاه.",13 }14 } else {15 return {16 address: "",17 status: "🦊 اتصل بـ MetaMask باستخدام الزر العلوي الأيمن.",18 }19 }20 } catch (err) {21 return {22 address: "",23 status: "😥 " + err.message,24 }25 }26 } else {27 return {28 address: "",29 status: (30 <span>31 <p>32 {" "}33 🦊 <a target="_blank" href={`https://metamask.io/download`}>34 يجب عليك تثبيت MetaMask، وهي محفظة إيثريوم افتراضية، في متصفحك.35 </a>36 </p>37 </span>38 ),39 }40 }41}هذا الكود مشابه جدًا لدالة connectWallet التي كتبناها للتو في الخطوة السابقة.
الفرق الرئيسي هو أنه بدلاً من استدعاء الطريقة eth_requestAccounts، التي تفتح ميتاماسك للمستخدم لربط محفظته، هنا نستدعي الطريقة eth_accounts، التي تعيد ببساطة مصفوفة تحتوي على عناوين ميتاماسك المتصلة حاليًا بتطبيقنا اللامركزي (dapp).
لرؤية هذه الدالة قيد التنفيذ، دعنا نستدعيها في دالة useEffect الخاصة بمكون HelloWorld.js الخاص بنا:
1// HelloWorld.js2
3useEffect(async () => {4 const message = await loadCurrentMessage()5 setMessage(message)6 addSmartContractListener()7
8 const { address, status } = await getCurrentWalletConnected()9 setWallet(address)10 setStatus(status)11}, [])لاحظ أننا نستخدم استجابة استدعائنا لـ getCurrentWalletConnected لتحديث متغيرات الحالة walletAddress و status.
الآن بعد أن أضفت هذا الكود، دعنا نحاول تحديث نافذة متصفحنا.
جميل! يجب أن يظهر الزر أنك متصل، ويعرض معاينة لعنوان محفظتك المتصلة - حتى بعد تحديث الصفحة!
تنفيذ addWalletListener
الخطوة الأخيرة في إعداد محفظة تطبيقنا اللامركزي هي تنفيذ مصغي المحفظة (Wallet Listener) بحيث يتم تحديث واجهة المستخدم الخاصة بنا عند تغير حالة المحفظة، مثل قيام المستخدم بقطع الاتصال أو تبديل الحسابات.
في ملف HelloWorld.js الخاص بك، قم بتعديل دالة addWalletListener الخاصة بك على النحو التالي:
1// HelloWorld.js2
3function addWalletListener() {4 if (window.ethereum) {5 window.ethereum.on("accountsChanged", (accounts) => {6 if (accounts.length > 0) {7 setWallet(accounts[0])8 setStatus("👆🏽 اكتب رسالة في حقل النص أعلاه.")9 } else {10 setWallet("")11 setStatus("🦊 اتصل بـ MetaMask باستخدام الزر العلوي الأيمن.")12 }13 })14 } else {15 setStatus(16 <p>17 {" "}18 🦊 <a target="_blank" href={`https://metamask.io/download`}>19 يجب عليك تثبيت MetaMask، وهي محفظة إيثريوم افتراضية، في متصفحك.20 </a>21 </p>22 )23 }24}أراهن أنك لست بحاجة إلى مساعدتنا لفهم ما يحدث هنا في هذه المرحلة، ولكن لأغراض الشمولية، دعنا نحلل الأمر بسرعة:
- أولاً، تتحقق دالتنا مما إذا كان
window.ethereumممكّنًا (أي أن ميتاماسك مثبت).- إذا لم يكن كذلك، فإننا ببساطة نضبط متغير الحالة
statusعلى سلسلة JSX التي تحث المستخدم على تثبيت ميتاماسك. - إذا كان ممكّنًا، فإننا ننشئ المستمع
window.ethereum.on("accountsChanged")في السطر 3 الذي يستمع لتغيرات الحالة في محفظة ميتاماسك، والتي تشمل عندما يربط المستخدم حسابًا إضافيًا بالتطبيق اللامركزي (dapp)، أو يبدل الحسابات، أو يفصل حسابًا. إذا كان هناك حساب واحد على الأقل متصل، يتم تحديث متغير الحالةwalletAddressكأول حساب في مصفوفةaccountsالتي يعيدها المستمع. بخلاف ذلك، يتم تعيينwalletAddressكسلسلة فارغة.
- إذا لم يكن كذلك، فإننا ببساطة نضبط متغير الحالة
أخيرًا وليس آخرًا، يجب أن نستدعيها في دالة useEffect الخاصة بنا:
1// HelloWorld.js2
3useEffect(async () => {4 const message = await loadCurrentMessage()5 setMessage(message)6 addSmartContractListener()7
8 const { address, status } = await getCurrentWalletConnected()9 setWallet(address)10 setStatus(status)11
12 addWalletListener()13}, [])وهذا كل شيء! لقد أكملنا بنجاح برمجة جميع وظائف محفظتنا! الآن إلى مهمتنا الأخيرة: تحديث الرسالة المخزنة في عقدنا الذكي!
الخطوة 6: تنفيذ دالة updateMessage
حسنًا يا رفاق، لقد وصلنا إلى المرحلة النهائية! في updateMessage من ملف interact.js الخاص بك، سنقوم بما يلي:
- تأكد من أن الرسالة التي نرغب في نشرها في عقدنا الذكي صالحة
- توقيع معاملتنا باستخدام ميتاماسك
- استدعاء هذه الدالة من مكون الواجهة الأمامية HelloWorld.js الخاص بنا
لن يستغرق هذا وقتًا طويلاً؛ دعنا ننهي هذا التطبيق اللامركزي!
معالجة أخطاء الإدخال
بطبيعة الحال، من المنطقي أن يكون هناك نوع من معالجة أخطاء الإدخال في بداية الدالة.
سنريد أن تعود دالتنا مبكرًا إذا لم يكن هناك امتداد ميتاماسك مثبت، أو لم تكن هناك محفظة متصلة (أي أن address الذي تم تمريره هو سلسلة فارغة)، أو كانت message سلسلة فارغة. دعنا نضيف معالجة الأخطاء التالية إلى updateMessage:
1// interact.js2
3export const updateMessage = async (address, message) => {4 if (!window.ethereum || address === null) {5 return {6 status:7 "💡 قم بتوصيل محفظة MetaMask الخاصة بك لتحديث الرسالة على البلوكتشين.",8 }9 }10
11 if (message.trim() === "") {12 return {13 status: "❌ لا يمكن أن تكون رسالتك سلسلة فارغة.",14 }15 }16}الآن بعد أن أصبحت لديها معالجة مناسبة لأخطاء الإدخال، حان الوقت لتوقيع المعاملة عبر ميتاماسك!
توقيع معاملتنا
إذا كنت مرتاحًا بالفعل مع معاملات إيثريوم التقليدية على الويب 3، فإن الكود الذي سنكتبه بعد ذلك سيكون مألوفًا جدًا. أسفل كود معالجة أخطاء الإدخال، أضف ما يلي إلى updateMessage:
1// interact.js2
3//إعداد معلمات المعاملة4const transactionParameters = {5 to: contractAddress, // مطلوب باستثناء أثناء نشر العقود.6 from: address, // يجب أن يتطابق مع عنوان المستخدم النشط.7 data: helloWorldContract.methods.update(message).encodeABI(),8}9
10//توقيع المعاملة11try {12 const txHash = await window.ethereum.request({13 method: "eth_sendTransaction",14 params: [transactionParameters],15 })16 return {17 status: (18 <span>19 ✅{" "}20 <a target="_blank" href={`https://goerli.etherscan.io/tx/${txHash}`}>21 عرض حالة معاملتك على Etherscan!22 </a>23 <br />24 ℹ️ بمجرد التحقق من المعاملة بواسطة الشبكة، سيتم تحديث الرسالة تلقائيًا.25 </span>26 ),27 }28} catch (error) {29 return {30 status: "😥 " + error.message,31 }32}دعنا نحلل ما يحدث. أولاً، نقوم بإعداد معلمات معاملاتنا، حيث:
toيحدد عنوان المستلم (عقدنا الذكي)fromيحدد موقع المعاملة، وهو متغيرaddressالذي مررناه إلى دالتناdataتحتوي على استدعاء طريقةupdateالخاصة بعقد Hello World الذكي، وتتلقى متغير سلسلةmessageكمدخل
بعد ذلك، نقوم باستدعاء await، window.ethereum.request، حيث نطلب من ميتاماسك توقيع المعاملة. لاحظ، في السطرين 11 و 12، أننا نحدد طريقة eth الخاصة بنا، eth_sendTransaction ونمرر transactionParameters الخاصة بنا.
في هذه المرحلة، سيفتح MetaMask في المتصفح، ويطلب من المستخدم التوقيع على المعاملة أو رفضها.
- إذا كانت المعاملة ناجحة، فستعيد الدالة كائن JSON حيث تحث سلسلة
statusJSX المستخدم على التحقق من إيثرسكان لمزيد من المعلومات حول معاملتهم. - إذا فشلت المعاملة، فستعيد الدالة كائن JSON حيث تنقل سلسلة
statusرسالة الخطأ.
بشكل عام، يجب أن تبدو دالة updateMessage الخاصة بنا كما يلي:
1// interact.js2
3export const updateMessage = async (address, message) => {4 //معالجة أخطاء الإدخال5 if (!window.ethereum || address === null) {6 return {7 status:8 "💡 قم بتوصيل محفظة MetaMask الخاصة بك لتحديث الرسالة على البلوكتشين.",9 }10 }11
12 if (message.trim() === "") {13 return {14 status: "❌ لا يمكن أن تكون رسالتك سلسلة فارغة.",15 }16 }17
18 //إعداد معلمات المعاملة19 const transactionParameters = {20 to: contractAddress, // مطلوب باستثناء أثناء نشر العقود.21 from: address, // يجب أن يتطابق مع عنوان المستخدم النشط.22 data: helloWorldContract.methods.update(message).encodeABI(),23 }24
25 //توقيع المعاملة26 try {27 const txHash = await window.ethereum.request({28 method: "eth_sendTransaction",29 params: [transactionParameters],30 })31 return {32 status: (33 <span>34 ✅{" "}35 <a target="_blank" href={`https://goerli.etherscan.io/tx/${txHash}`}>36 عرض حالة معاملتك على Etherscan!37 </a>38 <br />39 ℹ️ بمجرد التحقق من المعاملة بواسطة الشبكة، سيتم تحديث الرسالة تلقائيًا.40 </span>41 ),42 }43 } catch (error) {44 return {45 status: "😥 " + error.message,46 }47 }48}أخيرًا وليس آخرًا، نحتاج إلى توصيل دالة updateMessage الخاصة بنا بمكون HelloWorld.js.
توصيل updateMessage بالواجهة الأمامية لـ HelloWorld.js
يجب أن تقوم دالة onUpdatePressed الخاصة بنا باستدعاء await لدالة updateMessage المستوردة وتعديل متغير الحالة status ليعكس ما إذا كانت معاملتنا قد نجحت أم فشلت:
1// HelloWorld.js2
3const onUpdatePressed = async () => {4 const { status } = await updateMessage(walletAddress, newMessage)5 setStatus(status)6}إنه نظيف وبسيط للغاية. وخمن ماذا... تطبيقك اللامركزي اكتمل!!!
انطلق واختبر زر التحديث!
أنشئ تطبيقك اللامركزي المخصص
لقد وصلت إلى نهاية الدرس التعليمي! لتلخيص ذلك، تعلمت كيفية:
- توصيل محفظة ميتاماسك بمشروع تطبيقك اللامركزي
- قراءة البيانات من عقدك الذكي باستخدام واجهة برمجة تطبيقات ألكيمي ويب3 (opens in a new tab)
- توقيع معاملات إيثريوم باستخدام ميتاماسك
أنت الآن مجهز بالكامل لتطبيق المهارات من هذا الدرس التعليمي لبناء مشروع تطبيق لامركزي مخصص خاص بك! كما هو الحال دائمًا، إذا كانت لديك أي أسئلة، فلا تتردد في التواصل معنا للحصول على المساعدة في ألكيمي ديسكورد (opens in a new tab). 🧙♂️
بمجرد إكمال هذا الدرس التعليمي، أخبرنا كيف كانت تجربتك أو إذا كان لديك أي ملاحظات عن طريق الإشارة إلينا على تويتر @alchemyplatform (opens in a new tab)!
آخر تحديث للصفحة: 3 مارس 2026





