
اتریوم (ethereum) به ما اجازه ساخت برنامه غیر متمرکز (dapp) را میدهد. تفاوت اصلی بین یک برنامه عادی و یک برنامه غیر متمرکز این است که در برنامه غیر متمرکز مادامی که از قراردادهای هوشمند دیگر توسعه یافته بر روی شبکه اصلی اتریوم بهره میبرید، لازم نیست که بک اند (backend) را نصب کنید.
به همین خاطر است که فرانت اند (frontend) نقش برجستهای دارد. آن مسئول تغییر داده به بایت (byte) و تغییر بایت به داده از قراردادهای هوشمند، مدیریت تعاملات با کیف پول و طبق معمول مدیریت تجربه کاری است. طراحی یک برنامه غیر متمرکز به صورتی است که از فراخوانیهای JSON-RPC استفاده میکند و میتواند یک ارتباط سوکت را برای دریافت به روز رسانیها باز کند.
همچنان که میبینید چیزهایی را در اینجا باید تنظیم کرد، اما نگران نباشید؛ این اکوسیستم در چند ماه گذشته بسیار تکامل یافته است.
پیشنیازها برای ساخت برنامه غیر متمرکز با قرارداد هوشمند اتریوم
در خلال این راهنما، من چنین فرض میکنم که شما از قبل موارد زیر را دارید:
۱- کیف پولی که متصل به یک نود Geth باشد: سادهترین رویکرد، نصب متامسک (MetaMask) است که در نتیجه آن میتوانید از زیرساخت Infura بدون نصب استفاده کنید.
۲- داشتن مقداری اتریوم در اکانت خود: وقتی که با استفاده از اتریوم در حال توسعه هستید، توصیه میکنم که به شبکه آزمایشی بروید و از اتر تستی استفاده کنید. اگر نیاز به وجوهی برای آزمایش دارید، میتوانید به یک فاست (faucet) مراجعه کنید.
۳- درک اساسی React: من شما را مرحله به مرحله راهنمایی میکنم؛ اما من چنین فرض میکنم که شما نحوه کار React را میدانید. اگر در جایی مشکلی دارید با React Documentation مشورت کنید.
۴- داشتن یک محیط مناسب React: من این راهنما را با Typescript نوشتهام، اما تنها چند چیز تایپ شده است و با کمترین تغییرات میتوانید آنها را در جاوا اسکریپت هم مورد استفاده قرار دهید. من از Parcel.js استفاده کردهام؛ اما میتوانید با خیال راحت از Create react App و یا یک بسته نرم افزاری اپلیکیشن شبکهای دیگر استفاده کنید.
اتصال به شبکه اصلی اتریوم
زمانی که متامسک را آماده کردید، باید از web3-react برای مدیریت تعامل با شبکه استفاده کنید. این برای شما استفاده مفید useWeb3React را فراهم میآورد که شامل استفادههای مفید زیادی برای کار با اتریوم است.
سپس به یک پروایدر (provider) نیاز خواهید داشت. پروایدر یک اتصال را به بلاک چین اتریوم جدا میکند، که میتوان از آن برای پرس و جو و ارسال تراکنشهای تغییر وضعیت تایید شده استفاده کرد.
من در اینجا از web3Provider از Ether.js استفاده میکنم.
به نظر میرسد که این پروایدر ما از قبل تعدادی کتابخانه دارد، اما وقتی که با اتریوم تعامل میکند، شما باید دادههای جاوا اسکریپت را به سالیدیتی ترجمه کنید. وقتی میخواهید یک اقدامی را اجرا کنید، لازم است که تراکنشها را تایید کنید. Ether.js به شیوه ظریفی این عملکردها را فراهم میکند.
بعد از آن، ما برای یک یادداشت کوچک hello world آماده هستیم و بررسی میکنیم که آیا همه چیزهای لازم را داریم یا نه:
اگر کارتان را به خوبی انجام داده باشید، چیزی مانند زیر به دست میآید:
چگونه باید به دادهها از طریق شبکه اصلی اتریوم دسترسی داشته باشیم؟
من برای مدیریت دسترسی به داده از SWR استفاده میکنم.
این چیزی است که من میخواهم به آن برسم.
حال بیایید به آشکار کردن این فن بپردازیم. SWR زمان عکس العمل را کاهش میدهد و یک استراتژی بیاعتبارسازی حافظه نهان HTTP است که توسط RFC ۵۸۶۱ محبوبیت یافته است.
SWR ابتدا دادهها را از حافظه نهان برمیگرداند و سپس درخواست دسترسی را ارسال میکند و در نهایت دوباره با دادههای به روز میآید. به این ترتیب میبینید که ساز و کارها در یک برنامه غیر متمرکز بسیار با اپلیکیشنهای عادی تفاوت دارد.
SWR یک key را میپذیرد و در پشت صحنه به حل آن اقدام میکند.
برای انجام این کار، SWR اجازه انتقال fetcher را میدهد که توانایی حل key را دارد. پیام hello world در SWR بر اساس درخواستهای REST API است.
چیزی که در مورد SWR شایان توجه است، این است که تنها پیشنیاز برای ساخت یک fetcher این است که قادر به بازگرداندن تعهد باشد.
بنابراین اولین پیادهسازی من از یک fetcher برای اتریوم به صورت زیر است:
همان طور که میبینید، آن یک partially applied function است. به این شیوه، وقتی که در حال تنظیم fetcher هستیم، میتوانیم library را وارد کنیم. بعدا هر زمان که key تغییر پیدا میکند، تابع با باز گرداندن تعهد مورد نیاز قابل حل خواهد بود.
حالا من میتوانم مولفه <Balance/> خود را ایجاد کنم:
شیء موجودی که برگردانده شده به صورت BigNumber است.
همانطور که میبینید، عدد قالب نیافته و بسیار بزرگ است. دلیل این امر این است که سالیدیتی از عدد صحیحی تا ۲۵۶ بیت استفاده میکند.
برای نمایش عدد به شکلی که برای انسان هم قابل خواندن باشد، راهحل استفاده از یکی از کاربردهای Ether.js است:
اینک میتوانم بر روی مولفه <Balance/> خود دوباره کار کنم و فرمت BitInt را به شکلی قابل خواندن برای انسان درآورم.
چگونه دادهها را به صورت آنی به روز کنیم؟
SWR یک تابع mutate را به معرض نمایش میگذارد تا حافظه نهان داخلی را به روز کند.
این تابع به صورت خودکار به کلیدی وابسته است که از آن ایجاد شده است. آن دو پارامتر را میپذیرد که این دو پارامتر دادههای جدید و شرط شروع اعتبارسنجی هستند.
همچنان که پیشبینی میشد، رویدادهای سالیدیتی مفهوم کوچکی را بر بالای عملکرد ثبت ماشین مجازی اتریوم ایجاد میکنند. انواع مختلف برنامه غیر متمرکز میتوانند مشترک شوند و از این رویدادها مطلع شوند.
Ether.js دارای یک API ساده برای مشترک شدن در یک رویداد است:
حال بیایید که هر دو رویکرد را در یک مولفه <Balance/> جدید با هم ترکیب کنیم.
در ابتدا، SWR موجودی حساب را در دسترس قرار میدهد و سپس هر زمان که یک واقعه block دریافت کند، از mutate برای شروع دسترسی مجدد استفاده خواهد کرد.
در پایین، نمایش سریعی از دو کیف پول اتریوم آورده شده که در حال مبادله مقداری اتر هستند.
چگونه با یک قرارداد هوشمند تعامل داشته باشیم؟
تا به حال، مبانی استفاده از SWR را روشن ساختهایم و متوجه شدهایم که چگونه یک فرخوانی اصلی را از طریق web3provider انجام دهیم. حال به توضیح این میپردازیم که چگونه در یک برنامه غیر متمرکز میتوان به تعامل با قرارداد هوشمند پرداخت.
Ether.js به مدیریت تعامل قرارداد هوشمند با استفاده از Contract Application Binary Interface میپردازد که توسط کامپایلر سالیدیتی (solidity compiler) ایجاد شده است.
Contract Application Binary Interface روش استاندارد برای تعامل با قراردادها در اکوسیستم اتریوم و در فضای یک برنامه غیر متمرکز است.
به عنوان مثال، قرارداد هوشمند ساده زیر را در نظر داشته باشید:
این ABI ایجاد شده است:
برای استفاده از ABI، میتوان مستقیما آنها را به داخل کد کپی کرد و در هر جا که لازم باشد، آنها را داخل کرد. در اینجا، ما از یک ERC20 ABI استاندارد استفاده میکنیم زیرا میخواهیم موجودی دو توکن را بازیابی کنیم. این دو توکن DAI و MKR هستند.
مرحله بعدی ایجاد مولفه <TokenBalance/> است:
حال اگر متمرکز شویم، میبینیم که دو تفاوت اصلی وجود دارد:
تعریف کلید
این کلید لازم است که به جای method با یک address اتریوم شروع شود. به همین دلیل، fetcher میتواند آنچه را که میخواهیم به آن دسترسی داشته باشیم، شناسایی کرده و از ABI استفاده کند. بیایید fetcher را بر طبق آن اصلاح مجدد کنیم:
حال ما یک fetcher عمومی داریم که قابلیت تعامل با فراخوانیهای JSON-RPC از اتریوم در یک برنامه غیر متمرکز را دارد.
فیلترهای لگاریتمی
جنبه دیگری در <TokenBalance/>، نحوه مطلع شدن از رویدادهای ERC20 است. Ether.js روشی مفید برای تنظیم یک فیلتر بر اساس موضوعها و نام رویداد را فراهم میکند.
زمانی که یک قرارداد را با ABI ساختید، میتوانید فیلتر را به نمونه کتابخانه انتقال دهید.
حال ما همه قطعات را داریم و باید آنها را در کنار هم قرار دهیم.
من چند مقدار ثابت را تنظیم کردهام تا به روشی خوب بتوانم مولفه TokenBalance خود را طراحی کنم.
زمانی که این مقادیر ثابت را داشته باشیم، طراحی توکنهای تنظیم شده به داخل مولفه خود آسان است:
همه چیزها تنظیم شد. اینک ما یک کیف پول اتریوم داریم که موجودی اتر و دیگر توکنها را بارگذاری میکند. اگر کاربر به دریافت و ارسال وجوه اقدام کند، سطح کاربری کیف پول به روز میشود.
اصلاح
اجازه دهید هر مولفه را در فایل جداگانهای انتقال دهیم و fetcher را با استفاده از پروایدر SWRConfig به صورت عمومی موجود سازیم.
با استفاده از SWRConfig، میتوانیم بعضی گزینهها را مثل همیشه به صورت موجود تنظیم کنیم و بنابراین میتوانیم استفاده راحتتری از SWR داشته باشیم.
نتیجهگیری
اگر میخواهید استراتژی دسترسی به دادههای خود را با یک برنامه غیر متمرکز اتریوم ساده و موثر کنید، SWR و Ether.js دو کتابخانه خوب برای استفاده هستند. مزایای اصلی آنها برای یک برنامه غیر متمرکز به صورت زیر است:
- رویکردی اعلانی دارند.
- دادهها همیشه از طریق سوکتهای شبکه یا گزینههای SWR به روز هستند.
- برای مدیریت وضعیت، لازم نیست که همه چیز را از ابتدا شروع کنیم.