Waffle لائبریری کے ساتھ سادہ اسمارٹ کنٹریکٹ کی جانچ
اس ٹیوٹوریل میں آپ سیکھیں گے کہ کیسے
- والیٹ بیلنس کی تبدیلیوں کی جانچ کریں
- مخصوص دلائل کے ساتھ ایونٹس کے اخراج کی جانچ کریں
- اس بات کی تصدیق کریں کہ ٹرانزیکشن کو واپس کر دیا گیا تھا
مفروضات
- آپ ایک نیا JavaScript یا TypeScript پروجیکٹ بنا سکتے ہیں
- آپ کو JavaScript میں ٹیسٹ کا کچھ بنیادی تجربہ ہے
- آپ نے کچھ پیکیج مینیجرز جیسے yarn یا npm کا استعمال کیا ہے
- آپ کو اسمارٹ کنٹریکٹس اور Solidity کا بہت بنیادی علم ہے
شروعات کرنا
یہ ٹیوٹوریل yarn کا استعمال کرتے ہوئے ٹیسٹ سیٹ اپ اور رن کا مظاہرہ کرتا ہے، لیکن اگر آپ npm کو ترجیح دیتے ہیں تو کوئی مسئلہ نہیں ہے - میں سرکاری Waffle ڈاکیومینٹیشنopens in a new tab کے مناسب حوالے فراہم کروں گا۔
ڈیپینڈینسیز انسٹال کریں
اپنے پروجیکٹ کی ڈیو ڈیپینڈینسیز میں ethereum-waffle اور typescript ڈیپینڈینسیز کو شامل کریںopens in a new tab۔
yarn add --dev ethereum-waffle ts-node typescript @types/jestمثالی اسمارٹ کنٹریکٹ
ٹیوٹوریل کے دوران ہم ایک سادہ اسمارٹ کنٹریکٹ کی مثال - EtherSplitter پر کام کریں گے۔ یہ کسی کو کچھ wei بھیجنے اور اسے دو پہلے سے طے شدہ ریسیورز کے درمیان برابر تقسیم کرنے کی اجازت دینے کے علاوہ زیادہ کچھ نہیں کرتا ہے۔ اسپلٹ فنکشن کے لیے wei کی تعداد کا جفت ہونا ضروری ہے، ورنہ یہ واپس ہو جائے گا۔ دونوں ریسیورز کے لیے یہ ایک wei ٹرانسفر کرتا ہے جس کے بعد Transfer ایونٹ کا اخراج ہوتا ہے۔
EtherSplitter کوڈ کے اسنیپٹ کو src/EtherSplitter.sol میں رکھیں۔
1pragma solidity ^0.6.0;23contract EtherSplitter {4 address payable receiver1;5 address payable receiver2;67 event Transfer(address from, address to, uint256 amount);89 constructor(address payable _address1, address payable _address2) public {10 receiver1 = _address1;11 receiver2 = _address2;12 }1314 function split() public payable {15 require(msg.value % 2 == 0, 'Uneven wei amount not allowed');16 receiver1.transfer(msg.value / 2);17 emit Transfer(msg.sender, receiver1, msg.value / 2);18 receiver2.transfer(msg.value / 2);19 emit Transfer(msg.sender, receiver2, msg.value / 2);20 }21}سب دکھائیںکنٹریکٹ کو کمپائل کریں
کنٹریکٹ کو کمپائلopens in a new tab کرنے کے لیے، package.json فائل میں درج ذیل اندراج شامل کریں:
1"scripts": {2 "build": "waffle"3 }اگلا، پروجیکٹ روٹ ڈائرکٹری میں Waffle کنفیگریشن فائل - waffle.json - بنائیں اور پھر وہاں درج ذیل کنفیگریشن پیسٹ کریں:
1{2 "compilerType": "solcjs",3 "compilerVersion": "0.6.2",4 "sourceDirectory": "./src",5 "outputDirectory": "./build"6}yarn build چلائیں۔ نتیجے کے طور پر، build ڈائرکٹری JSON فارمیٹ میں EtherSplitter کمپائلڈ کنٹریکٹ کے ساتھ ظاہر ہوگی۔
ٹیسٹ سیٹ اپ
Waffle کے ساتھ ٹیسٹنگ کے لیے Chai matchers اور Mocha کا استعمال ضروری ہے، لہذا آپ کو انہیں اپنے پروجیکٹ میں شاملopens in a new tab کرنے کی ضرورت ہے۔ اپنی package.json فائل کو اپ ڈیٹ کریں اور اسکرپٹس حصے میں test اندراج شامل کریں:
1"scripts": {2 "build": "waffle",3 "test": "export NODE_ENV=test && mocha -r ts-node/register 'test/**/*.test.ts'"4 }اگر آپ اپنے ٹیسٹ ایگزیکیوٹopens in a new tab کرنا چاہتے ہیں تو صرف yarn test چلائیں۔
جانچ
اب test ڈائرکٹری بنائیں اور نئی فائل test\EtherSplitter.test.ts بنائیں۔
نیچے دیے گئے اسنیپٹ کو کاپی کریں اور اسے ہماری ٹیسٹ فائل میں پیسٹ کریں۔
1import { expect, use } from "chai"2import { Contract } from "ethers"3import { deployContract, MockProvider, solidity } from "ethereum-waffle"4import EtherSplitter from "../build/EtherSplitter.json"56use(solidity)78describe("Ether Splitter", () => {9 const [sender, receiver1, receiver2] = new MockProvider().getWallets()10 let splitter: Contract1112 beforeEach(async () => {13 splitter = await deployContract(sender, EtherSplitter, [14 receiver1.address,15 receiver2.address,16 ])17 })1819 // add the tests here20})سب دکھائیںشروع کرنے سے پہلے چند باتیں۔
MockProvider بلاک چین کا ایک موک ورژن فراہم کرتا ہے۔ یہ موک والیٹس بھی فراہم کرتا ہے جو EtherSplitter کنٹریکٹ کی جانچ کے لیے ہماری خدمت کریں گے۔ ہم پرووائڈر پر getWallets() میتھڈ کو کال کرکے دس والیٹس تک حاصل کرسکتے ہیں۔ مثال میں، ہم تین والیٹس حاصل کرتے ہیں - بھیجنے والے (sender) کے لیے اور دو وصول کنندگان (receivers) کے لیے۔
اگلا، ہم 'splitter' نامی ایک متغیر کا اعلان کرتے ہیں - یہ ہمارا موک EtherSplitter کنٹریکٹ ہے۔ یہ deployContract میتھڈ کے ذریعہ ہر ایک ٹیسٹ کے ایگزیکیوشن سے پہلے بنایا جاتا ہے۔ یہ میتھڈ پہلے پیرامیٹر کے طور پر پاس کیے گئے والیٹ (ہمارے معاملے میں بھیجنے والے کا والیٹ) سے ایک کنٹریکٹ کی تعیناتی کی نقل کرتا ہے۔ دوسرا پیرامیٹر ٹیسٹ شدہ کنٹریکٹ کا ABI اور بائٹ کوڈ ہے - ہم وہاں build ڈائرکٹری سے کمپائل شدہ EtherSplitter کنٹریکٹ کی json فائل پاس کرتے ہیں۔ تیسرا پیرامیٹر کنٹریکٹ کے کنسٹرکٹر دلائل کے ساتھ ایک ارے ہے، جو ہمارے معاملے میں، دو وصول کنندگان کے ایڈریس ہیں۔
changeBalances
سب سے پہلے، ہم یہ چیک کریں گے کہ آیا اسپلٹ میتھڈ واقعی وصول کنندگان کے والیٹس کے بیلنس کو تبدیل کرتا ہے۔ اگر ہم بھیجنے والے کے اکاؤنٹ سے 50 wei کو اسپلٹ کرتے ہیں، تو ہم توقع کریں گے کہ دونوں وصول کنندگان کے بیلنس میں 25 wei کا اضافہ ہوگا۔ ہم Waffle کا changeBalances میچر استعمال کریں گے:
1it("Changes accounts balances", async () => {2 await expect(() => splitter.split({ value: 50 })).to.changeBalances(3 [receiver1, receiver2],4 [25, 25]5 )6})میچر کے پہلے پیرامیٹر کے طور پر، ہم وصول کنندگان کے والیٹس کا ایک ارے پاس کرتے ہیں، اور دوسرے کے طور پر - متعلقہ اکاؤنٹس پر متوقع اضافے کا ایک ارے۔
اگر ہم کسی ایک مخصوص والیٹ کا بیلنس چیک کرنا چاہتے ہیں، تو ہم changeBalance میچر بھی استعمال کر سکتے ہیں، جس کے لیے ارے پاس کرنے کی ضرورت نہیں ہے، جیسا کہ نیچے دی گئی مثال میں ہے:
1it("Changes account balance", async () => {2 await expect(() => splitter.split({ value: 50 })).to.changeBalance(3 receiver1,4 255 )6})نوٹ کریں کہ changeBalance اور changeBalances دونوں صورتوں میں ہم اسپلٹ فنکشن کو کال بیک کے طور پر پاس کرتے ہیں کیونکہ میچر کو کال سے پہلے اور بعد میں بیلنس کی حالت تک رسائی کی ضرورت ہوتی ہے۔
اگلا، ہم جانچیں گے کہ کیا Transfer ایونٹ ہر wei کی منتقلی کے بعد خارج ہوا تھا۔ ہم Waffle سے ایک اور میچر کی طرف رجوع کریں گے:
Emit
1it("Emits event on the transfer to the first receiver", async () => {2 await expect(splitter.split({ value: 50 }))3 .to.emit(splitter, "Transfer")4 .withArgs(sender.address, receiver1.address, 25)5})67it("Emits event on the transfer to the second receiver", async () => {8 await expect(splitter.split({ value: 50 }))9 .to.emit(splitter, "Transfer")10 .withArgs(sender.address, receiver2.address, 25)11})سب دکھائیںemit میچر ہمیں یہ چیک کرنے کی اجازت دیتا ہے کہ آیا کسی کنٹریکٹ نے میتھڈ کال کرنے پر کوئی ایونٹ خارج کیا ہے۔ emit میچر کے پیرامیٹرز کے طور پر، ہم وہ موک کنٹریکٹ فراہم کرتے ہیں جس کے بارے میں ہم پیش گوئی کرتے ہیں کہ وہ ایونٹ خارج کرے گا، اس ایونٹ کے نام کے ساتھ۔ ہمارے معاملے میں، موک کنٹریکٹ splitter ہے اور ایونٹ کا نام - Transfer ہے۔ ہم ان دلائل کی درست قدروں کی بھی تصدیق کر سکتے ہیں جن کے ساتھ ایونٹ خارج کیا گیا تھا - ہم withArgs میچر کو اتنے ہی دلائل پاس کرتے ہیں، جتنے ہمارے ایونٹ کے اعلان کی توقع ہے۔ EtherSplitter کنٹریکٹ کے معاملے میں، ہم بھیجنے والے اور وصول کنندہ کے ایڈریس کے ساتھ منتقل شدہ wei رقم کو پاس کرتے ہیں۔
revertedWith
آخری مثال کے طور پر، ہم یہ چیک کریں گے کہ آیا wei کی غیر مساوی تعداد کی صورت میں ٹرانزیکشن کو واپس کر دیا گیا تھا۔ ہم revertedWith میچر استعمال کریں گے:
1it("Reverts when Vei amount uneven", async () => {2 await expect(splitter.split({ value: 51 })).to.be.revertedWith(3 "Uneven wei amount not allowed"4 )5})یہ ٹیسٹ، اگر پاس ہو جاتا ہے، تو ہمیں یقین دلائے گا کہ ٹرانزیکشن واقعی واپس کر دی گئی تھی۔ تاہم، require اسٹیٹمنٹ میں ہمارے پاس کیے گئے پیغامات اور revertedWith میں ہماری توقع کے پیغام کے درمیان ایک عین مطابق مماثلت بھی ہونی چاہیے۔ اگر ہم EtherSplitter کنٹریکٹ کے کوڈ پر واپس جائیں، تو wei رقم کے لیے require اسٹیٹمنٹ میں، ہم یہ پیغام فراہم کرتے ہیں: 'Uneven wei amount not allowed'۔ یہ اس پیغام سے میل کھاتا ہے جس کی ہم اپنے ٹیسٹ میں توقع کرتے ہیں۔ اگر وہ برابر نہ ہوتے تو ٹیسٹ فیل ہو جاتا۔
مبارک ہو!
آپ نے Waffle کے ساتھ اسمارٹ کنٹریکٹس کی جانچ کی طرف اپنا پہلا بڑا قدم اٹھایا ہے!
صفحہ کی آخری تازہ کاری: 17 دسمبر، 2025