Waffle: متحرک نقالی اور کانٹریکٹ کالز کی جانچ
یہ ٹیوٹوریل کس بارے میں ہے؟
اس ٹیوٹوریل میں آپ سیکھیں گے کہ کیسے:
- متحرک نقالی کا استعمال
- اسمارٹ کانٹریکٹس کے درمیان تعاملات کی جانچ کریں
مفروضے:
- آپ پہلے ہی جانتے ہیں کہ
Solidityمیں ایک سادہ اسمارٹ کانٹریکٹ کیسے لکھنا ہے - آپ
JavaScriptاورTypeScriptسے واقف ہیں - آپ نے دوسرے
Waffleٹیوٹوریلز کیے ہیں یا اس کے بارے میں کچھ جانتے ہیں
متحرک نقالی
متحرک نقالی کیوں مفید ہے؟ خیر، یہ ہمیں انٹیگریشن ٹیسٹ کے بجائے یونٹ ٹیسٹ لکھنے کی اجازت دیتا ہے۔ اس کا کیا مطلب ہے؟ اس کا مطلب ہے کہ ہمیں اسمارٹ کانٹریکٹس کے انحصار کے بارے میں فکر کرنے کی ضرورت نہیں ہے، اس طرح ہم ان سب کو مکمل تنہائی میں جانچ سکتے ہیں۔ آئیے میں آپ کو دکھاتا ہوں کہ آپ اسے ٹھیک ٹھیک کیسے کر سکتے ہیں۔
1. پروجیکٹ**
شروع کرنے سے پہلے ہمیں ایک سادہ node.js پروجیکٹ تیار کرنے کی ضرورت ہے:
mkdir dynamic-mockingcd dynamic-mockingmkdir contracts srcyarn init# or if you're using npmnpm initآئیے ٹائپ اسکرپٹ اور ٹیسٹ ڈیپینڈنسیز - mocha اور chai شامل کرنے کے ساتھ شروع کرتے ہیں:
yarn add --dev @types/chai @types/mocha chai mocha ts-node typescript# or if you're using npmnpm install @types/chai @types/mocha chai mocha ts-node typescript --save-devاب آئیے Waffle اور ethers شامل کریں:
yarn add --dev ethereum-waffle ethers# or if you're using npmnpm install ethereum-waffle ethers --save-devآپ کے پروجیکٹ کی ساخت اب اس طرح نظر آنی چاہئے:
1.2├── contracts3├── package.json4└── test2. اسمارٹ کانٹریکٹ**
متحرک نقالی شروع کرنے کے لیے، ہمیں انحصار کے ساتھ ایک اسمارٹ کانٹریکٹ کی ضرورت ہے۔ فکر نہ کریں، میں نے آپ کا کام آسان کر دیا ہے!
یہاں Solidity میں لکھا گیا ایک سادہ اسمارٹ کانٹریکٹ ہے جس کا واحد مقصد یہ جانچنا ہے کہ کیا ہم امیر ہیں۔ یہ جانچنے کے لیے ERC20 ٹوکن کا استعمال کرتا ہے کہ آیا ہمارے پاس کافی ٹوکن ہیں۔ اسے ./contracts/AmIRichAlready.sol میں ڈالیں۔
1pragma solidity ^0.6.2;23interface IERC20 {4 function balanceOf(address account) external view returns (uint256);5}67contract AmIRichAlready {8 IERC20 private tokenContract;9 uint public richness = 1000000 * 10 ** 18;1011 constructor (IERC20 _tokenContract) public {12 tokenContract = _tokenContract;13 }1415 function check() public view returns (bool) {16 uint balance = tokenContract.balanceOf(msg.sender);17 return balance > richness;18 }19}سب دکھائیںچونکہ ہم متحرک نقالی کا استعمال کرنا چاہتے ہیں اس لیے ہمیں پورے ERC20 کی ضرورت نہیں ہے، یہی وجہ ہے کہ ہم صرف ایک فنکشن کے ساتھ IERC20 انٹرفیس کا استعمال کر رہے ہیں۔
اب اس کانٹریکٹ کو بنانے کا وقت ہے! اس کے لیے ہم Waffle کا استعمال کریں گے۔ سب سے پہلے، ہم ایک سادہ waffle.json کنفگ فائل بنانے جا رہے ہیں جو کمپائلیشن کے اختیارات کی وضاحت کرتی ہے۔
1{2 "compilerType": "solcjs",3 "compilerVersion": "0.6.2",4 "sourceDirectory": "./contracts",5 "outputDirectory": "./build"6}اب ہم Waffle کے ساتھ کانٹریکٹ بنانے کے لیے تیار ہیں:
npx waffleآسان ہے، ہے نا؟ build/ فولڈر میں کانٹریکٹ اور انٹرفیس سے مطابقت رکھنے والی دو فائلیں ظاہر ہوئیں۔ ہم انہیں بعد میں جانچ کے لیے استعمال کریں گے۔
3. جانچ**
آئیے اصل جانچ کے لیے AmIRichAlready.test.ts نامی ایک فائل بنائیں۔ سب سے پہلے، ہمیں امپورٹس کو سنبھالنا ہوگا۔ ہمیں بعد میں ان کی ضرورت ہوگی:
1import { expect, use } from "chai"2import { Contract, utils, Wallet } from "ethers"3import {4 deployContract,5 deployMockContract,6 MockProvider,7 solidity,8} from "ethereum-waffle"JS ڈیپینڈنسیز کے علاوہ، ہمیں اپنے بنائے ہوئے کانٹریکٹ اور انٹرفیس کو امپورٹ کرنے کی ضرورت ہے:
1import IERC20 from "../build/IERC20.json"2import AmIRichAlready from "../build/AmIRichAlready.json"Waffle جانچ کے لیے chai کا استعمال کرتا ہے۔ تاہم، اس کا استعمال کرنے سے پہلے، ہمیں Waffle کے میچرز کو خود chai میں انجیکٹ کرنا ہوگا:
1use(solidity)ہمیں beforeEach() فنکشن کو لاگو کرنے کی ضرورت ہے جو ہر ٹیسٹ سے پہلے کانٹریکٹ کی حالت کو ری سیٹ کرے گا۔ آئیے پہلے سوچیں کہ ہمیں وہاں کیا ضرورت ہے۔ ایک کانٹریکٹ کو تعینات کرنے کے لیے ہمیں دو چیزوں کی ضرورت ہے: ایک والیٹ اور ایک تعینات شدہ ERC20 کانٹریکٹ تاکہ اسے AmIRichAlready کانٹریکٹ کے لیے ایک دلیل کے طور پر پاس کیا جا سکے۔
سب سے پہلے ہم ایک والیٹ بناتے ہیں:
1const [wallet] = new MockProvider().getWallets()پھر ہمیں ایک ERC20 کانٹریکٹ تعینات کرنے کی ضرورت ہے۔ یہاں مشکل حصہ ہے - ہمارے پاس صرف ایک انٹرفیس ہے۔ یہ وہ حصہ ہے جہاں Waffle ہمیں بچانے کے لیے آتا ہے۔ Waffle میں ایک جادوئی deployMockContract() فنکشن ہے جو صرف انٹرفیس کے abi کا استعمال کرتے ہوئے ایک کانٹریکٹ بناتا ہے:
1const mockERC20 = await deployMockContract(wallet, IERC20.abi)اب والیٹ اور تعینات شدہ ERC20 دونوں کے ساتھ، ہم آگے بڑھ کر AmIRichAlready کانٹریکٹ تعینات کر سکتے ہیں:
1const contract = await deployContract(wallet, AmIRichAlready, [2 mockERC20.address,3])ان سب کے ساتھ، ہمارا beforeEach() فنکشن ختم ہو گیا ہے۔ اب تک آپ کی AmIRichAlready.test.ts فائل اس طرح نظر آنی چاہیے:
1import { expect, use } from "chai"2import { Contract, utils, Wallet } from "ethers"3import {4 deployContract,5 deployMockContract,6 MockProvider,7 solidity,8} from "ethereum-waffle"910import IERC20 from "../build/IERC20.json"11import AmIRichAlready from "../build/AmIRichAlready.json"1213use(solidity)1415describe("Am I Rich Already", () => {16 let mockERC20: Contract17 let contract: Contract18 let wallet: Wallet1920 beforeEach(async () => {21 ;[wallet] = new MockProvider().getWallets()22 mockERC20 = await deployMockContract(wallet, IERC20.abi)23 contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address])24 })25})سب دکھائیںآئیے AmIRichAlready کانٹریکٹ کے لیے پہلا ٹیسٹ لکھیں۔ آپ کے خیال میں ہمارا ٹیسٹ کس بارے میں ہونا چاہئے؟ ہاں، آپ صحیح ہیں! ہمیں یہ جانچنا چاہئے کہ کیا ہم پہلے ہی امیر ہیں :)
لیکن ایک سیکنڈ رکیں۔ ہمارا نقلی کانٹریکٹ کیسے جانے گا کہ کون سی قدریں واپس کرنی ہیں؟ ہم نے balanceOf() فنکشن کے لیے کوئی منطق نافذ نہیں کی ہے۔ ایک بار پھر، Waffle یہاں مدد کر سکتا ہے۔ ہمارے نقلی کانٹریکٹ میں اب کچھ نئی فینسی چیزیں ہیں:
1await mockERC20.mock.<nameOfMethod>.returns(<value>)2await mockERC20.mock.<nameOfMethod>.withArgs(<arguments>).returns(<value>)اس علم کے ساتھ ہم آخر کار اپنا پہلا ٹیسٹ لکھ سکتے ہیں:
1it("returns false if the wallet has less than 1000000 tokens", async () => {2 await mockERC20.mock.balanceOf.returns(utils.parseEther("999999"))3 expect(await contract.check()).to.be.equal(false)4})آئیے اس ٹیسٹ کو حصوں میں تقسیم کرتے ہیں:
- ہم نے اپنے نقلی ERC20 کانٹریکٹ کو ہمیشہ 999999 ٹوکنز کا بیلنس واپس کرنے کے لیے سیٹ کیا ہے۔
- جانچیں کہ کیا
contract.check()طریقہfalseواپس کرتا ہے۔
ہم اسے چلانے کے لیے تیار ہیں:
تو ٹیسٹ کام کرتا ہے، لیکن... اب بھی بہتری کی گنجائش ہے۔ balanceOf() فنکشن ہمیشہ 999999 واپس کرے گا۔ ہم ایک والیٹ کی وضاحت کرکے اسے بہتر بنا سکتے ہیں جس کے لئے فنکشن کو کچھ واپس کرنا چاہئے - بالکل ایک حقیقی کانٹریکٹ کی طرح:
1it("returns false if the wallet has less than 1000001 tokens", async () => {2 await mockERC20.mock.balanceOf3 .withArgs(wallet.address)4 .returns(utils.parseEther("999999"))5 expect(await contract.check()).to.be.equal(false)6})اب تک، ہم نے صرف اس معاملے کی جانچ کی ہے جہاں ہم کافی امیر نہیں ہیں۔ اس کے بجائے آئیے اس کے برعکس جانچتے ہیں:
1it("returns true if the wallet has at least 1000001 tokens", async () => {2 await mockERC20.mock.balanceOf3 .withArgs(wallet.address)4 .returns(utils.parseEther("1000001"))5 expect(await contract.check()).to.be.equal(true)6})آپ ٹیسٹ چلاتے ہیں...
... اور یہ ہو گیا! ہمارا کانٹریکٹ ارادے کے مطابق کام کرتا نظر آتا ہے :)
کانٹریکٹ کالز کی جانچ
آئیے اس کا خلاصہ کریں جو ہم نے اب تک کیا ہے۔ ہم نے اپنے AmIRichAlready کانٹریکٹ کی فعالیت کی جانچ کی ہے اور یہ ٹھیک سے کام کرتا نظر آتا ہے۔ اس کا مطلب ہے کہ ہمارا کام ہو گیا، ٹھیک ہے؟ بالکل نہیں! Waffle ہمیں اپنے کانٹریکٹ کو مزید جانچنے کی اجازت دیتا ہے۔ لیکن ٹھیک ٹھیک کیسے؟ خیر، Waffle کے آرسینل میں calledOnContract() اور calledOnContractWith() میچرز ہیں۔ وہ ہمیں یہ جانچنے کی اجازت دیں گے کہ آیا ہمارے کانٹریکٹ نے ERC20 نقلی کانٹریکٹ کو کال کیا ہے۔ ان میچرز میں سے ایک کے ساتھ ایک بنیادی ٹیسٹ یہ ہے:
1it("checks if contract called balanceOf on the ERC20 token", async () => {2 await mockERC20.mock.balanceOf.returns(utils.parseEther("999999"))3 await contract.check()4 expect("balanceOf").to.be.calledOnContract(mockERC20)5})ہم مزید آگے جا سکتے ہیں اور اس ٹیسٹ کو دوسرے میچر کے ساتھ بہتر بنا سکتے ہیں جس کے بارے میں میں نے آپ کو بتایا تھا:
1it("checks if contract called balanceOf with certain wallet on the ERC20 token", async () => {2 await mockERC20.mock.balanceOf3 .withArgs(wallet.address)4 .returns(utils.parseEther("999999"))5 await contract.check()6 expect("balanceOf").to.be.calledOnContractWith(mockERC20, [wallet.address])7})آئیے جانچتے ہیں کہ کیا ٹیسٹ درست ہیں:
بہت اچھا، تمام ٹیسٹ پاس ہو گئے ہیں۔
Waffle کے ساتھ کانٹریکٹ کالز کی جانچ بہت آسان ہے۔ اور یہاں بہترین حصہ ہے۔ یہ میچرز عام اور نقلی دونوں کانٹریکٹس کے ساتھ کام کرتے ہیں! یہ اس لیے ہے کہ Waffle کوڈ انجیکٹ کرنے کے بجائے EVM کالز کو ریکارڈ اور فلٹر کرتا ہے، جیسا کہ دیگر ٹیکنالوجیز کے لیے مقبول ٹیسٹنگ لائبریریوں کا معاملہ ہے۔
اختتامی لکیر
مبارک ہو! اب آپ جانتے ہیں کہ کانٹریکٹ کالز کی جانچ کرنے اور کانٹریکٹس کو متحرک طور پر نقل کرنے کے لیے Waffle کا استعمال کیسے کرنا ہے۔ دریافت کرنے کے لیے اور بھی بہت سی دلچسپ خصوصیات ہیں۔ میں Waffle کی دستاویزات میں گہرائی سے جانے کی تجویز کرتا ہوں۔
Waffle کی دستاویزات یہاںopens in a new tab دستیاب ہے۔
اس ٹیوٹوریل کا سورس کوڈ یہاںopens in a new tab پایا جا سکتا ہے۔
ٹیوٹوریلز جن میں آپ کو بھی دلچسپی ہو سکتی ہے:
صفحہ کی آخری تازہ کاری: 27 فروری، 2024


