লিখেছেন মোঃ সাইফুল ইসলাম · জুলাই 1, 2022
উপরের 3-ঘন্টার ভিডিওতে একটি সম্পূর্ণ ব্লকচেইন অ্যাপ্লিকেশন তৈরি করতে আমি আপনাকে কাঁধে নিয়ে যাব। আপনি এই নির্দেশিকায় ধাপে ধাপে নির্দেশাবলী অনুসরণ করতে পারেন। আপনি যদি ইতিমধ্যেই মৌলিক বিষয়গুলি জানেন, তাহলে আপনি এড়িয়ে যেতে পারেন এবং এখনই অ্যাপটি কোডিং শুরু করতে পারেন!
সুচিপত্র
ভূমিকা
- আমরা কি নির্মাণ করতে যাচ্ছি?
- একটি ব্লকচেইন কি?
- একটি স্মার্ট চুক্তি কি?
- একটি ব্লকচেইন অ্যাপ কিভাবে কাজ করে?
টিউটোরিয়াল পদক্ষেপ
নির্ভরতা ইনস্টল করা হচ্ছে
- অংশ 1: প্রকল্প সেটআপ
- পার্ট 2: পণ্য বিক্রি করুন
- পার্ট 3: পণ্য কিনুন
- পার্ট 4: মার্কেটপ্লেস ওয়েবসাইট সেটআপ (ফ্রন্ট এন্ড)
- পার্ট 5: পণ্য বিক্রি করুন (সামনে)
- পার্ট 6: পণ্য কিনুন (ফ্রন্ট এন্ড)
- পার্ট 7: প্রজেক্ট স্থাপন করুন
আমরা কি নির্মাণ করতে যাচ্ছি?
আমরা তৈরি করব:
- সলিডিটি প্রোগ্রামিং ভাষার সাথে ইথেরিয়াম স্মার্ট চুক্তি
- আমরা জাভাস্ক্রিপ্টে স্মার্ট চুক্তির জন্য পরীক্ষা লিখব
- আমরা একটি ব্লকচেইনে স্মার্ট চুক্তিতে স্থাপন করব
- আমরা Web3.js এবং React.js সহ একটি ক্লায়েন্ট সাইড ওয়েবসাইট তৈরি করব যাতে ব্যবহারকারীরা স্মার্ট চুক্তির সাথে কথা বলতে পারে
একটি ব্লকচেইন কি?
আপনি কয়েকটি উপায়ে একটি ব্লকচেইন সম্পর্কে চিন্তা করতে পারেন:
- একটি দৈত্যাকার বিশ্বব্যাপী কম্পিউটার ছোট কম্পিউটার (নোড) দ্বারা গঠিত যা একসাথে কাজ করে।
- একটি নেটওয়ার্ক যা যে কেউ অর্থ পাঠাতে, প্রোগ্রাম চালানো ইত্যাদির জন্য সংযোগ করতে পারে...
- একটি ডাটাবেস যা আপনাকে তথ্য সংরক্ষণ এবং পুনরুদ্ধার করতে দেয়।
ব্লকচেইনগুলি এমন দায়িত্ব গ্রহণ করে যা ওয়েব সার্ভারগুলি সাধারণত করে:
একটি স্মার্ট চুক্তি কি?
কিভাবে একটি স্মার্ট চুক্তি কাজ করে?
একটি ব্লকচেইন অ্যাপ কিভাবে কাজ করে?
নির্ভরতা ইনস্টল করা
গণচেন ব্যক্তিগত ব্লকচেইন
নোড.জেএস
$ node -v
ট্রাফল ফ্রেমওয়ার্ক
ট্রাফল ফ্রেমওয়ার্কের সাথে আমরা যে সমস্ত কার্যকারিতা পাব তার একটি ওভারভিউ এখানে রয়েছে:
- স্মার্ট কন্ট্রাক্ট ম্যানেজমেন্ট - সলিডিটি প্রোগ্রামিং ল্যাঙ্গুয়েজ দিয়ে স্মার্ট কন্ট্রাক্ট লিখুন এবং ইথেরিয়াম ভার্টাল মেশিনে (ইভিএম) চালানো বাইটকোডে কম্পাইল করুন।
- স্বয়ংক্রিয় পরীক্ষা - আপনার স্মার্ট চুক্তিগুলির বিরুদ্ধে পরীক্ষাগুলি লিখুন যাতে তারা আপনার পছন্দ মতো আচরণ করে। এই পরীক্ষাগুলি জাভাস্ক্রিপ্ট বা সলিডিটিতে লেখা হতে পারে এবং পাবলিক ব্লকচেইন নেটওয়ার্ক সহ ট্রাফল দ্বারা কনফিগার করা যেকোনো নেটওয়ার্কের বিরুদ্ধে চালানো যেতে পারে।
- স্থাপনা এবং স্থানান্তর - স্থানান্তর করতে স্ক্রিপ্ট লিখুন এবং যেকোনো পাবলিক ইথেরিয়াম ব্লকচেইন নেটওয়ার্কে স্মার্ট চুক্তি স্থাপন করুন।
- নেটওয়ার্ক ম্যানেজমেন্ট - যেকোনো পাবলিক ইথেরিয়াম ব্লকচেইন নেটওয়ার্কের সাথে সংযোগ করুন, সেইসাথে আপনি বিকাশের উদ্দেশ্যে ব্যবহার করতে পারেন এমন কোনো ব্যক্তিগত ব্লকচেইন নেটওয়ার্কে।
- ডেভেলপমেন্ট কনসোল - ট্রাফল কনসোলের সাথে জাভাস্ক্রিপ্ট রানটাইম পরিবেশের মধ্যে স্মার্ট চুক্তির সাথে ইন্টারঅ্যাক্ট করুন। এটি করার জন্য আপনি আপনার নেটওয়ার্ক কনফিগারেশনের মধ্যে নির্দিষ্ট করেছেন এমন যেকোনো ব্লকচেইন নেটওয়ার্কের সাথে সংযোগ করতে পারেন।
- স্ক্রিপ্ট রানার - কাস্টম স্ক্রিপ্ট লিখুন যা জাভাস্ক্রিপ্ট সহ একটি পাবলিক ব্লকচেইন নেটওয়ার্কের বিরুদ্ধে চলতে পারে। আপনি এই ফাইলের ভিতরে যেকোনো ইচ্ছাকৃত কোড লিখতে পারেন এবং আপনার প্রকল্পের মধ্যে এটি চালাতে পারেন।
- ক্লায়েন্ট সাইড ডেভেলপমেন্ট - ক্লায়েন্ট সাইড অ্যাপ্লিকেশন হোস্ট করতে আপনার ট্রাফল প্রজেক্ট কনফিগার করুন যা ব্লকচেইনে নিয়োজিত আপনার স্মার্ট চুক্তির সাথে কথা বলে
$ npm install -g truffle@5.0.5
মেটামাস্ক ইথেরিয়াম ওয়ালেট
অংশ 1: প্রকল্প সেটআপ
$ git clone https://github.com/dappuniversity/starter_kit marketplace
$ cd marketplace
প্যাকেজ.json ফাইলের ভিতরে আপনার প্রয়োজনীয় সমস্ত নির্ভরতা রয়েছে:
{
"name": "eth-marketplace",
"version": "0.1.0",
"description": "An Ethereum Marketplace",
"author": "gregory@dappuniversity.com",
"dependencies": {
"babel-polyfill": "6.26.0",
"babel-preset-env": "1.7.0",
"babel-preset-es2015": "6.24.1",
"babel-preset-stage-2": "6.24.1",
"babel-preset-stage-3": "6.24.1",
"babel-register": "6.26.0",
"bootstrap": "4.3.1",
"chai": "4.2.0",
"chai-as-promised": "7.1.1",
"chai-bignumber": "3.0.0",
"react": "16.8.4",
"react-bootstrap": "1.0.0-beta.5",
"react-dom": "16.8.4",
"react-scripts": "2.1.3",
"truffle": "5.0.5",
"web3": "1.0.0-beta.55"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
]
}
$ npm install
require('babel-register');
require('babel-polyfill');
module.exports = {
networks: {
development: {
host: "127.0.0.1",
port: 7545,
network_id: "*" // Match any network id
},
},
contracts_directory: './src/contracts/',
contracts_build_directory: './src/abis/',
compilers: {
solc: {
optimizer: {
enabled: true,
runs: 200
}
}
}
}
$ touch src/contracts/Marketplace.sol
pragma solidity ^0.5.0;
contract Marketplace {
}
প্রথমে, আমরা সলিডিটি প্রোগ্রামিং ভাষার সংস্করণ ঘোষণা করে শুরু করি যা আমরা ব্যবহার করতে চাই। এর পরে, আমরা আমাদের স্মার্ট চুক্তি মার্কেটপ্লেস ঘোষণা করি। আমরা কোঁকড়া ধনুর্বন্ধনীর ভিতরে সমস্ত স্মার্ট চুক্তি কোড যোগ করব। চল এটা করি:
pragma solidity ^0.5.0;
contract Marketplace {
string public name;
}
এই কোডটি একটি "স্টেট ভেরিয়েবল" তৈরি করে, যার মান ব্লকচেইনে সংরক্ষণ করা হবে। আমরা পরিবর্তনশীল নামটিকে কল করব কারণ আমরা স্মার্ট চুক্তির (শুধু পরীক্ষার উদ্দেশ্যে) নাম সংরক্ষণ করতে এটি ব্যবহার করব। যেহেতু সলিডিটি একটি স্ট্যাটিক্যালি টাইপ করা প্রোগ্রামিং ভাষা, তাই ভেরিয়েবল ঘোষণা করার আগে আমাদের অবশ্যই স্ট্রিং ডেটাটাইপ ঘোষণা করতে হবে। অবশেষে, আমরা রাষ্ট্রীয় পরিবর্তনশীলকে সর্বজনীন ঘোষণা করি যাতে আমরা স্মার্ট চুক্তির বাইরে এর মান পড়তে পারি, যা আমরা মুহূর্তের জন্য করব।
এর পরে, চলুন এই ভেরিয়েবলের মান এভাবে সেট করি:
pragma solidity ^0.5.0;
contract Marketplace {
string public name;
constructor() public {
name = "Dapp University Marketplace";
}
}
আমরা কন্সট্রাক্টর ফাংশনের ভিতরে নামের মান নির্ধারণ করি। এটি একটি বিশেষ ফাংশন যা যখনই প্রথমবারের জন্য স্মার্ট চুক্তি তৈরি করা হয়, অর্থাৎ ব্লকচেইনে স্থাপন করা হয় তখন কল করা হয়। যখনই এটি স্থাপন করা হয়, এটি আমরা এখানে নির্দিষ্ট করা স্ট্রিংয়ের সাথে নামের মান সেট করবে।
এখন সবকিছু কাজ করেছে তা নিশ্চিত করতে স্মার্ট চুক্তিটি কম্পাইল করা যাক:
$ truffle compile
$ touch migrations/2_deploy_contracts.js
const Marketplace = artifacts.require("Marketplace");
module.exports = function(deployer) {
deployer.deploy(Marketplace);
};
এখন মাইগ্রেট এভাবে মাইগ্রেশন চালান:
$ truffle migrate
$ truffle console
marketplace = await Marketplace.deployed()
আপনার কনসোল অনির্ধারিত ফিরে আসতে পারে, কিন্তু এটা ঠিক আছে! আপনি এই মত আবার পরিবর্তনশীল নাম টাইপ করে স্মার্ট চুক্তির মান পেতে পারেন:
marketplace
marketplace.address
name = await marketplace.name()
name
হ্যাঁ! 🎉 আপনি সফলভাবে আপনার প্রকল্প সেট আপ করেছেন এবং ব্লকচেইনে একটি মৌলিক স্মার্ট চুক্তি স্থাপন করেছেন!
এখন স্মার্ট চুক্তির জন্য একটি পরীক্ষা লিখুন। স্মার্ট কন্ট্রাক্ট পরীক্ষা করা খুবই গুরুত্বপূর্ণ কারণ ব্লকচেইনে লাইভ হওয়ার আগে আপনাকে নিশ্চিত করতে হবে যে সেগুলি পুরোপুরি কাজ করছে। মনে রাখবেন, আপনি একবার তাদের স্থাপন করলে, তারা পরিবর্তন করতে পারবে না! আপনি শুধুমাত্র একটি নতুন অনুলিপি পুনরায় স্থাপন করতে পারেন.
এই মত স্মার্ট চুক্তি পরীক্ষার জন্য একটি নতুন ফাইল তৈরি করুন:
$ mkdir test
$ touch test/Marketplace.test.js
এই ফাইলের ভিতরে, নিম্নলিখিত কোড ব্যবহার করুন:
const Marketplace = artifacts.require('./Marketplace.sol')
contract('Marketplace', (accounts) => {
let marketplace
before(async () => {
marketplace = await Marketplace.deployed()
})
describe('deployment', async () => {
it('deploys successfully', async () => {
const address = await marketplace.address
assert.notEqual(address, 0x0)
assert.notEqual(address, '')
assert.notEqual(address, null)
assert.notEqual(address, undefined)
})
it('has a name', async () => {
const name = await marketplace.name()
assert.equal(name, 'Dapp University Marketplace')
})
})
})
আমাকে এই পরীক্ষা ব্যাখ্যা করা যাক. আমরা আমাদের সকল পরীক্ষা জাভাস্ক্রিপ্টে এই ফাইলের ভিতরে Mocha টেস্টিং ফ্রেমওয়ার্ক এবং Chai assertion লাইব্রেরি দিয়ে লিখি। এগুলি ট্রাফল ফ্রেমওয়ার্কের সাথে একত্রিত হয়। আমরা আমাদের স্মার্ট চুক্তির সাথে ক্লায়েন্ট-সাইড ইন্টারঅ্যাকশন অনুকরণ করতে জাভাস্ক্রিপ্টে এই সমস্ত পরীক্ষা লিখব, যেমনটি আমরা কনসোলে করেছি।
এই পরীক্ষা দুটি জিনিস করে:
- চেক করে যে স্মার্ট চুক্তির একটি ঠিকানা আছে, অর্থাৎ, এটি সফলভাবে নেটওয়ার্কে স্থাপন করা হয়েছে।
- এটি স্থাপন করার সময় নাম সেট করা হয়েছিল কিনা তা পরীক্ষা করে।
এখন, কমান্ড লাইন থেকে এইভাবে পরীক্ষা চালানো যাক:
দারূন কাজ! আপনি আটকে থাকলে, আরও স্পষ্টীকরণের জন্য ভিডিওটির এই অংশটি আবার দেখতে নির্দ্বিধায় দেখুন। আপনি এখানে সমস্ত কোডের একটি অনুলিপিও খুঁজে পেতে পারেন।
পার্ট 2: পণ্য বিক্রি করুন
টিউটোরিয়ালের এই অংশের জন্য সহগামী ভিডিও ফুটেজ 33:10 এ শুরু হয়। আপনি এখানে কোড খুঁজে পেতে পারেন.
এখন মার্কেটপ্লেস স্মার্ট কন্ট্রাক্ট তৈরি করা চালিয়ে যাওয়া যাক। আমরা প্রথম বৈশিষ্ট্যটি তৈরি করব, যা একজন ব্যবহারকারীকে বাজারে বিক্রয়ের জন্য একটি আইটেম তালিকাভুক্ত করার অনুমতি দেবে। এটি করার জন্য আমাদের এই জাতীয় কাঠামোর সাথে পণ্যটির মডেল করতে হবে:
struct Product {
uint id;
string name;
uint price;
address owner;
bool purchased;
}
সলিডিটি আপনাকে যেকোনো স্বেচ্ছাচারী বৈশিষ্ট্য সহ আপনার নিজস্ব ডেটা স্ট্রাকচার তৈরি করতে দেয়। যে আমরা একটি পণ্য struct তৈরি করে কাজ করেছি ঠিক কি. এটি একটি পণ্যের সমস্ত বৈশিষ্ট্য সংরক্ষণ করে যা আমাদের প্রয়োজন হবে, যেমন আইডি, নাম, দাম, মালিক এবং কেনা।
এর পরে, ব্লকচেইনে এই পণ্যগুলি সংরক্ষণ করার জন্য আমাদের একটি জায়গা দরকার। আমরা এইরকম সলিডিটির উপর একটি ম্যাপিং তৈরি করব:
mapping(uint => Product) public products;
ম্যাপিংগুলি কী মান-জোড়া সহ সহযোগী অ্যারে বা হ্যাশ টেবিলের মতো কাজ করে। ম্যাপিং-এ অনন্য কী রয়েছে যা অনন্য মান প্রদান করে। আমাদের ক্ষেত্রে, আমরা একটি কী হিসাবে একটি আইডি ব্যবহার করব এবং মানটি একটি পণ্যের কাঠামো হবে। এটি মূলত আমাদের একটি ডেটাবেসের মতো আইডি দ্বারা একটি পণ্য সন্ধান করার অনুমতি দেবে৷
এর পরে, আমরা একটি প্রোডাক্ট কাউন্ট কাউন্টার ক্যাশের সাথে স্মার্ট চুক্তিতে কতগুলি পণ্য বিদ্যমান রয়েছে তার ট্র্যাক রাখতে চাই:
uint public productCount = 0;
আমরা একটি কাউন্টার ক্যাশে ব্যবহার করি কারণ ম্যাপিংয়ে কতগুলি পণ্য বিদ্যমান তা জানার কোন উপায় নেই। আপনি Solidiy-এ ম্যাপিংয়ের "দৈর্ঘ্য" বা "আকার" পরীক্ষা করতে পারবেন না। সুতরাং আমরা যদি সমস্ত পণ্য আনতে চাই তবে আমাদের অবশ্যই সেগুলি পৃথকভাবে পড়তে হবে। আমরা কাউন্টার ক্যাশে ব্যবহার করব তা নির্ধারণ করতে যে এটি কতবার করতে পারে।
এই মুহুর্তে, আপনার স্মার্ট চুক্তিটি এইরকম হওয়া উচিত:
pragma solidity ^0.5.0;
contract Marketplace {
string public name;
uint public productCount = 0;
mapping(uint => Product) public products;
struct Product {
uint id;
string name;
uint price;
address owner;
bool purchased;
}
constructor() public {
name = "Dapp University Marketplace";
}
}
এর পরে, নতুন পণ্য তৈরি করার জন্য একটি ফাংশন তৈরি করা যাক। এই ফাংশনটি কিছু কাজ করবে:
- একটি struct সঙ্গে একটি নতুন পণ্য তৈরি করুন
- ম্যাপিং-এ স্ট্রাকট যোগ করুন এবং ব্লকচেইনে সংরক্ষণ করুন
- এমন একটি ইভেন্ট ট্রিগার করুন যা কাউকে একটি পণ্য তৈরি করা হয়েছে তা জানতে দেয়
আমরা এই ফাংশনটি তৈরি করতে পারি:
function createProduct(string memory _name, uint _price) public {
// Require a valid name
require(bytes(_name).length > 0);
// Require a valid price
require(_price > 0);
// Increment product count
productCount ++;
// Create the product
products[productCount] = Product(productCount, _name, _price, msg.sender, false);
// Trigger an event
emit ProductCreated(productCount, _name, _price, msg.sender, false);
}
আমাকে এই কোড ব্যাখ্যা করা যাক:
প্রথমত, আমরা একটি ফাংশন তৈরি করি যা গ্রহণ করে
name
price
যুক্তি. পণ্যের মূল্য ওয়েই, ইথারের ক্ষুদ্রতম উপবিভাগে প্রকাশ করা হয়েছে (সম্পূর্ণ ব্যাখ্যার জন্য ভিডিও দেখুন)।
- এর পরে, আমরা কিছু প্রয়োজনীয়তা যোগ করি যা ফাংশনটি কার্যকর করার আগে অবশ্যই সন্তুষ্ট হতে হবে। আমরা পরীক্ষা করি যে নামটি উপস্থিত রয়েছে এবং মূল্য 0-এর চেয়ে বেশি।
- এর পরে, আমরা ++ অপারেটরের সাথে পণ্যের সংখ্যা বাড়িয়ে একটি নতুন পণ্য আইডি তৈরি করি (এটি আগের মানের সাথে 1 যোগ করে)।
- তারপরে আমরা একটি নতুন পণ্য তৈরি করি এবং এটি ম্যাপিংয়ে যুক্ত করি। নোট করুন যে msg.sender হল পণ্য তৈরি করা ব্যবহারকারীর ঠিকানা।
- অবশেষে, আমরা একটি ইভেন্ট ট্রিগার করি যাতে সবাইকে জানানো হয় যে পণ্যটি সফলভাবে তৈরি করা হয়েছে।
এখন ইভেন্ট সংজ্ঞা যোগ করা যাক যাতে এটি ট্রিগার করা যায়:
event ProductCreated(
uint id,
string name,
uint price,
address owner,
bool purchased
);
ব্লকচেইনে একটি পণ্য তৈরি করা হয়েছে তা যাচাই করতে বহিরাগত গ্রাহকরা এই ইভেন্টের জন্য শুনতে পারেন। আমরা মুহূর্তের মধ্যে স্মার্ট চুক্তি পরীক্ষার ভিতরে এই ইভেন্টের জন্য পরীক্ষা করব।
এখন এই বিভাগের জন্য আপনার সম্পূর্ণ স্মার্ট চুক্তি কোড দেখতে এইরকম হওয়া উচিত:
pragma solidity ^0.5.0;
contract Marketplace {
string public name;
uint public productCount = 0;
mapping(uint => Product) public products;
struct Product {
uint id;
string name;
uint price;
address owner;
bool purchased;
}
event ProductCreated(
uint id,
string name,
uint price,
address owner,
bool purchased
);
constructor() public {
name = "Dapp University Marketplace";
}
function createProduct(string memory _name, uint _price) public {
// Require a valid name
require(bytes(_name).length > 0);
// Require a valid price
require(_price > 0);
// Increment product count
productCount ++;
// Create the product
products[productCount] = Product(productCount, _name, _price, msg.sender, false);
// Trigger an event
emit ProductCreated(productCount, _name, _price, msg.sender, false);
}
}
এই ফাংশনটি সঠিকভাবে কাজ করে তা নিশ্চিত করার জন্য এখন কিছু পরীক্ষা যোগ করা যাক। আপনার পরীক্ষা ফাইলের ভিতরে এই কোডটি ব্যবহার করুন:
const Marketplace = artifacts.require('./Marketplace.sol')
require('chai')
.use(require('chai-as-promised'))
.should()
contract('Marketplace', ([deployer, seller, buyer]) => {
let marketplace
before(async () => {
marketplace = await Marketplace.deployed()
})
describe('deployment', async () => {
it('deploys successfully', async () => {
const address = await marketplace.address
assert.notEqual(address, 0x0)
assert.notEqual(address, '')
assert.notEqual(address, null)
assert.notEqual(address, undefined)
})
it('has a name', async () => {
const name = await marketplace.name()
assert.equal(name, 'Dapp University Marketplace')
})
})
describe('products', async () => {
let result, productCount
before(async () => {
result = await marketplace.createProduct('iPhone X', web3.utils.toWei('1', 'Ether'), { from: seller })
productCount = await marketplace.productCount()
})
it('creates products', async () => {
// SUCCESS
assert.equal(productCount, 1)
const event = result.logs[0].args
assert.equal(event.id.toNumber(), productCount.toNumber(), 'id is correct')
assert.equal(event.name, 'iPhone X', 'name is correct')
assert.equal(event.price, '1000000000000000000', 'price is correct')
assert.equal(event.owner, seller, 'owner is correct')
assert.equal(event.purchased, false, 'purchased is correct')
// FAILURE: Product must have a name
await await marketplace.createProduct('', web3.utils.toWei('1', 'Ether'), { from: seller }).should.be.rejected;
// FAILURE: Product must have a price
await await marketplace.createProduct('iPhone X', 0, { from: seller }).should.be.rejected;
})
})
})
এর প্রতিটি নতুন অংশ পরীক্ষা করা যাক. প্রথমত, আমরা আমাদের টেস্ট স্যুটে এইরকম কিছু অতিরিক্ত টুল যোগ করি। আমরা ইতিমধ্যেই আমাদের package.json এ ইন্সটল করেছি:
require('chai')
.use(require('chai-as-promised'))
.should()
এরপরে, পরীক্ষার দৃশ্যে 3টি নতুন অ্যাকাউন্ট যোগ করুন, স্থাপনকারী, বিক্রেতা এবং ক্রেতা:
contract('Marketplace', ([deployer, seller, buyer]) => {
তারপরে, আমরা পণ্য তৈরির জন্য একটি নতুন পরীক্ষার উদাহরণ তৈরি করি:
describe('products', async () => {
let result, productCount
before(async () => {
result = await marketplace.createProduct('iPhone X', web3.utils.toWei('1', 'Ether'), { from: seller })
productCount = await marketplace.productCount()
})
//...
এটি একটি পূর্বের হুক দিয়ে পরীক্ষার উদাহরণ সেট আপ করে, যা প্রতিটি পরীক্ষা চালানোর আগে একটি পণ্য তৈরি করে। অবশেষে, আমরা এই মত পণ্য তৈরির জন্য একটি সম্পূর্ণ পরীক্ষা তৈরি করি:
it('creates products', async () => {
// SUCCESS
assert.equal(productCount, 1)
const event = result.logs[0].args
assert.equal(event.id.toNumber(), productCount.toNumber(), 'id is correct')
assert.equal(event.name, 'iPhone X', 'name is correct')
assert.equal(event.price, '1000000000000000000', 'price is correct')
assert.equal(event.owner, seller, 'owner is correct')
assert.equal(event.purchased, false, 'purchased is correct')
// FAILURE: Product must have a name
await await marketplace.createProduct('', web3.utils.toWei('1', 'Ether'), { from: seller }).should.be.rejected;
// FAILURE: Product must have a price
await await marketplace.createProduct('iPhone X', 0, { from: seller }).should.be.rejected;
})
প্রথমে, আমরা পরীক্ষা করি যে একটি পণ্য তৈরি করলে পণ্যের সংখ্যা 1 বৃদ্ধি পায়। তারপর, আমরা স্মার্ট চুক্তি ইভেন্ট লগগুলি পরীক্ষা করে দেখি যে পণ্যটি সঠিক মান দিয়ে তৈরি করা হয়েছে। আমরা ইভেন্ট লগগুলিকে এইভাবে খনন করি: result.logs[0].args (এই মানগুলি কেমন দেখাচ্ছে তা দেখতে কনসোলে লগ আউট করার চেষ্টা করুন)। আমরা পরীক্ষা করি যে এই সমস্ত মান সঠিক, যেমন আইডি, নাম, দাম, ইত্যাদি...
অবশেষে, আমরা ব্যর্থতার ক্ষেত্রে পরীক্ষা করি। উদাহরণস্বরূপ, আমরা নিশ্চিত করি যে ফাংশন কল ব্যর্থ হয় যদি কোন নাম না থাকে, বা মূল্য 0 এর কম বা সমান হয়।
মহান কাজ! আপনি আটকে থাকলে, আরও স্পষ্টীকরণের জন্য ভিডিওটির এই অংশটি আবার দেখতে নির্দ্বিধায় দেখুন। আপনি এখানে সমস্ত কোডের একটি অনুলিপিও খুঁজে পেতে পারেন।
পার্ট 3: পণ্য কিনুন
টিউটোরিয়ালের এই অংশের জন্য সহগামী ভিডিও ফুটেজ 01:01:07 এ শুরু হয়। আপনি এখানে কোড খুঁজে পেতে পারেন.
এখন পণ্য কেনার জন্য একটি ফাংশন তৈরি করা যাক। যখনই কেউ এই ফাংশনটিতে কল করবে, তারা যে পণ্যটি কিনতে চায় তার আইডি জমা দেবে (এটি আমাদের ক্লায়েন্ট সাইড অ্যাপ্লিকেশন দ্বারা পরিচালিত হবে)। উপরন্তু, যখন তারা এই ফাংশনটি কল করে তখন তারা পণ্য কেনার জন্য তাদের ওয়ালেট থেকে ইথেরিয়াম ক্রিপ্টোকারেন্সি পাঠাবে। আমরা এটি করার জন্য ফাংশন সেট আপ করব:
function purchaseProduct(uint _id) public payable {
// ...
}
লক্ষ্য করুন, আমরা এই ফাংশনটিকে প্রদেয় করেছি, যার অর্থ হল এটি ইথারাম ক্রিপ্টোকারেন্সি গ্রহণ করবে। আমরা মুহূর্তের মধ্যে কর্ম এটি দেখতে পাবেন. কারণ আমরা মালিককে অর্থপ্রদান করতে চাই, আমাদের অবশ্যই বিদ্যমান কাঠামো এবং ইভেন্ট আপডেট করতে হবে যাতে প্রদেয় টাইপ ঠিকানাটি ব্যবহার করা যায়:
struct Product {
uint id;
string name;
uint price;
address payable owner;
bool purchased;
}
event ProductCreated(
uint id,
string name,
uint price,
address payable owner,
bool purchased
);
এখন ফাংশনের ভিতরে কোডটি পূরণ করা যাক:
function purchaseProduct(uint _id) public payable {
// Fetch the product
Product memory _product = products[_id];
// Fetch the owner
address payable _seller = _product.owner;
// Make sure the product has a valid id
require(_product.id > 0 && _product.id <= productCount);
// Require that there is enough Ether in the transaction
require(msg.value >= _product.price);
// Require that the product has not been purchased already
require(!_product.purchased);
// Require that the buyer is not the seller
require(_seller != msg.sender);
// Transfer ownership to the buyer
_product.owner = msg.sender;
// Mark as purchased
_product.purchased = true;
// Update the product
products[_id] = _product;
// Pay the seller by sending them Ether
address(_seller).transfer(msg.value);
// Trigger an event
emit ProductPurchased(productCount, _product.name, _product.price, msg.sender, true);
}
আমাকে এই ফাংশন কি ব্যাখ্যা করা যাক.
প্রথমে, আমরা ম্যাপিং থেকে পণ্যটি নিয়ে আসি এবং মেমরিতে এটির একটি নতুন অনুলিপি তৈরি করি।
তারপর আমরা একটি পরিবর্তনশীল বর্তমান মালিক সংরক্ষণ. আমরা এই ফাংশনের ভিতরে পণ্যের মালিকানা হস্তান্তর করব, তাই আমাদের জানতে হবে আসল মালিক কে।
এর পরে, আমরা কয়েকটি প্রয়োজনীয়তা যোগ করি। আমরা একটি বৈধ আইডি পরীক্ষা করি, লেনদেনে পর্যাপ্ত ইথারাম ক্রিপ্টোকারেন্সি আছে, ক্রেতা বিক্রেতা নয় এবং পণ্যটি ইতিমধ্যে কেনা হয়নি।
তারপর আমরা লেনদেন সহজতর. আমরা ক্রেতার কাছে মালিকানা হস্তান্তর করি, পণ্যটিকে ক্রয় করা হিসাবে চিহ্নিত করি এবং পণ্যটিকে ম্যাপিংয়ে আবার যুক্ত করি। এর পরে, আমরা বিক্রেতার কাছে ক্রিপ্টোকারেন্সি পেমেন্ট পাঠাই। উল্লেখ্য, ইথার ক্রিপ্টোকারেন্সির পরিমাণ ফাংশনের মেটাডেটার সাথে সলিডিটিতে ট্র্যাক করা হয়। আমরা গ্লোবাল ভেরিয়েবল msg.sender দিয়ে এই মানটি অ্যাক্সেস করতে পারি। আবার, এই মানটি Wei-তে প্রকাশ করা হয়েছে (আরো ব্যাখ্যার জন্য ভিডিও দেখুন)।
সবশেষে, পণ্যটি সফলভাবে তৈরি হয়েছে বলে ঘোষণা করার জন্য আমরা একটি ইভেন্ট ট্রিগার করি।
এখন পণ্য বিক্রয়ের জন্য একটি নতুন ইভেন্ট তৈরি করা যাক। এটি প্রায় ঠিক ইভেন্টের মতো কাজ করবে যা আমরা শেষ বিভাগে তৈরি করেছি, শুধুমাত্র একটি ভিন্ন নাম:
event ProductPurchased(
uint id,
string name,
uint price,
address payable owner,
bool purchased
);
এখন এর মত ক্রয় পণ্য ফাংশনের জন্য একটি পরীক্ষা যোগ করা যাক:
it('sells products', async () => {
// Track the seller balance before purchase
let oldSellerBalance
oldSellerBalance = await web3.eth.getBalance(seller)
oldSellerBalance = new web3.utils.BN(oldSellerBalance)
// SUCCESS: Buyer makes purchase
result = await marketplace.purchaseProduct(productCount, { from: buyer, value: web3.utils.toWei('1', 'Ether')})
// Check logs
const event = result.logs[0].args
assert.equal(event.id.toNumber(), productCount.toNumber(), 'id is correct')
assert.equal(event.name, 'iPhone X', 'name is correct')
assert.equal(event.price, '1000000000000000000', 'price is correct')
assert.equal(event.owner, buyer, 'owner is correct')
assert.equal(event.purchased, true, 'purchased is correct')
// Check that seller received funds
let newSellerBalance
newSellerBalance = await web3.eth.getBalance(seller)
newSellerBalance = new web3.utils.BN(newSellerBalance)
let price
price = web3.utils.toWei('1', 'Ether')
price = new web3.utils.BN(price)
const exepectedBalance = oldSellerBalance.add(price)
assert.equal(newSellerBalance.toString(), exepectedBalance.toString())
// FAILURE: Tries to buy a product that does not exist, i.e., product must have valid id
await marketplace.purchaseProduct(99, { from: buyer, value: web3.utils.toWei('1', 'Ether')}).should.be.rejected; // FAILURE: Buyer tries to buy without enough ether
// FAILURE: Buyer tries to buy without enough ether
await marketplace.purchaseProduct(productCount, { from: buyer, value: web3.utils.toWei('0.5', 'Ether') }).should.be.rejected;
// FAILURE: Deployer tries to buy the product, i.e., product can't be purchased twice
await marketplace.purchaseProduct(productCount, { from: deployer, value: web3.utils.toWei('1', 'Ether') }).should.be.rejected;
// FAILURE: Buyer tries to buy again, i.e., buyer can't be the seller
await marketplace.purchaseProduct(productCount, { from: buyer, value: web3.utils.toWei('1', 'Ether') }).should.be.rejected;
})
এই পরীক্ষাটি অনেকটা sellProduct() ফাংশন টেস্টের মত কাজ করে। এটি কয়েকটি মূল জিনিস করে:
- পণ্যটি ক্রেতার কাছে হস্তান্তর করা হয়েছে কিনা তা পরীক্ষা করে
- চেক করে যে বিক্রেতা স্বয়ংক্রিয়ভাবে ইথার ক্রিপ্টোকারেন্সি ফান্ড পেয়েছেন
- আমরা ফাংশনের ভিতরে তাদের বিরুদ্ধে সুরক্ষা নিশ্চিত করতে সমস্ত ব্যর্থতার ক্ষেত্রে পরীক্ষা করে
এখন, কমান্ড লাইন থেকে এইভাবে পরীক্ষা চালানো যাক:
$ truffle test
🎉 হ্যাঁ, তারা পাস!
অবশেষে, আসুন নেটওয়ার্কে স্মার্ট চুক্তি স্থাপন করি যাতে আমরা পরবর্তী বিভাগে এটির সাথে ইন্টারঅ্যাক্ট করার জন্য ক্লায়েন্ট সাইড অ্যাপ্লিকেশন তৈরি করা শুরু করতে পারি। আমরা নেটওয়ার্কে স্মার্ট চুক্তিগুলি স্থানান্তর করতে --reset পতাকা দিয়ে আমাদের মাইগ্রেশনগুলি পুনরায় চালাতে পারি। এটি ব্লকচেইনে স্মার্ট চুক্তির একটি নতুন অনুলিপি তৈরি করবে:
$ truffle migrate --reset
চমৎকার কাজ! আপনি আটকে থাকলে, আরও স্পষ্টীকরণের জন্য ভিডিওটির এই অংশটি আবার দেখতে নির্দ্বিধায় দেখুন। আপনি এখানে সমস্ত কোডের একটি অনুলিপিও খুঁজে পেতে পারেন।
পার্ট 4: মার্কেটপ্লেস ওয়েবসাইট সেটআপ (ফ্রন্ট এন্ড)
টিউটোরিয়ালের এই অংশের সাথে ভিডিও ফুটেজ শুরু হয় 01:26:20 এ। আপনি এখানে কোড খুঁজে পেতে পারেন.
এখন মার্কেটপ্লেসের জন্য ক্লায়েন্ট সাইড অ্যাপ্লিকেশন তৈরি করা শুরু করা যাক। এই বিভাগে আমরা যা করব তা এখানে:
অ্যাপটি শুরু করুন এবং আমাদের ব্রাউজারে স্টার্টার কিট চালান
ব্লকচেইনের সাথে আমাদের ওয়েব ব্রাউজার সংযুক্ত করুন
ব্লকচেইনের সাথে আমাদের ওয়েব অ্যাপ সংযুক্ত করুন এবং মার্কেটপ্লেস স্মার্ট চুক্তির সাথে কথা বলা শুরু করুন
আমরা শুরু করার আগে, নিশ্চিত করুন যে আপনার ডেভেলপমেন্ট সার্ভার চলছে:
$ npm run start
এটি আপনার ওয়েব সার্ভার শুরু করবে এবং স্বয়ংক্রিয়ভাবে আপনার ব্রাউজারে ওয়েবসাইট খুলবে:
এই স্টার্টার কিটটি আমাদের অ্যাপ্লিকেশন তৈরি করার জন্য প্রয়োজনীয় সমস্ত কিছুর সাথে আসে:- ইন্টারফেস তৈরির জন্য React.js
- CSS না লিখে UI উপাদান তৈরি করার জন্য বুটস্ট্র্যাপ
- আমাদের অ্যাপ ব্লকচেইনের সাথে সংযুক্ত করার জন্য Web3.js
এখন আমাদের ওয়েব ব্রাউজারটিকে ব্লকচেইনের সাথে সংযুক্ত করা যাক। আমরা এর জন্য মেটামাস্ক ব্যবহার করব, যা আমরা টিউটোরিয়ালের নির্ভরতা বিভাগে ইনস্টল করেছি। এটি করার জন্য আমাদের দুটি জিনিস করতে হবে:
- আমাদের Ganache ব্যক্তিগত ব্লকচেইন উদাহরণের সাথে Metamask সংযোগ করুন
- Ganache থেকে Metamask-এ কিছু অ্যাকাউন্ট আমদানি করুন যাতে আমরা আমাদের মার্কেটপ্লেস অ্যাপ্লিকেশনের ব্যবহারকারী হিসাবে তাদের পক্ষে কাজ করতে পারি
আপনি ভিডিওতে এই সময়ে আমাকে মেটামাস্ক সেট আপ করতে দেখতে পারেন।
এর পরে, আমাকে সংক্ষেপে ব্যাখ্যা করতে দিন কেন আমরা আমাদের প্রকল্প তৈরি করতে React.js ব্যবহার করছি। আমাদের অ্যাপ্লিকেশনের সমস্ত ক্লায়েন্ট পার্শ্ব আচরণ পরিচালনা করার এবং ব্লকচেইন থেকে ডেটা সংরক্ষণ করার জন্য আমাদের একটি উপায় প্রয়োজন। এই সব হাত দিয়ে করার পরিবর্তে, React.js আমাদের কোডকে পুনঃব্যবহারযোগ্য উপাদানগুলিতে সংগঠিত করে এবং আমাদের অ্যাপ্লিকেশন স্টেটকে এর স্টেট অবজেক্টের সাথে পরিচালনা করে আমাদের এই ক্ষমতা দেয়। আপনি ভিডিওতে এই সময়ে React.js এর আমার সম্পূর্ণ ব্যাখ্যা দেখতে পারেন।
এখন আসুন একটি href="https://web3js.readthedocs.io/en/1.0/" target="_blank">Web3.js এর সাহায্যে আমাদের ক্লায়েন্ট সাইড অ্যাপ্লিকেশনটিকে ব্লকচেইনের সাথে সংযুক্ত করি। আমরা আমাদের প্রধান App.js কম্পোনেন্টে web3 ইম্পোর্ট করে এইভাবে শুরু করব:
import Web3 from 'web3'
এখন একটি নতুন ফাংশন তৈরি করা যাক যা যখনই আমাদের প্রতিক্রিয়া উপাদান লোড হবে তখন কল করা হবে। এখানের ভিতরে, আমরা একটি ফাংশনকে কল করব যা web3 ইনস্ট্যান্টিয়েট করে।
async componentWillMount() {
await this.loadWeb3()
}
এখন, আসুন loadWeb3() ফাংশন তৈরি করি যা এইভাবে সংযোগ তৈরি করবে:
async loadWeb3() {
if (window.ethereum) {
window.web3 = new Web3(window.ethereum)
await window.ethereum.enable()
}
else if (window.web3) {
window.web3 = new Web3(window.web3.currentProvider)
}
else {
window.alert('Non-Ethereum browser detected. You should consider trying MetaMask!')
}
}
এই ফাংশনটি ওয়েব ব্রাউজারে একটি Ethereum প্রদানকারীর উপস্থিতি সনাক্ত করে, যা আমাদের অ্যাপ্লিকেশনটিকে ব্লকচেইনের সাথে সংযুক্ত করতে দেয়। আপনি যদি এই ফাংশনের ভিতরে সবকিছু বুঝতে না পারেন তবে চিন্তা করবেন না। ঠিক আছে! এটি সরাসরি মেটামাস্কের নির্দেশাবলী থেকে নেওয়া হয়েছে। :)
এখন একটি ফাংশন তৈরি করা যাক যা ব্লকচেইন থেকে ডেটা লোড করে। আমরা প্রথমে এটিকে এভাবে কল করব:
async componentWillMount() {
await this.loadWeb3()
await this.loadBlockchainData()
}
এবং আমরা এটিকে এভাবে সংজ্ঞায়িত করব:
async loadBlockchainData() {
const web3 = window.web3
}
এখানের ভিতরে, আমরা একটি ভেরিয়েবলের সাথে সংরক্ষিত web3 সংযোগ সংযুক্ত করেছি। এখন মেটামাস্ক থেকে অ্যাকাউন্টগুলি নিয়ে আসা যাক এবং সেগুলিকে এইভাবে কনসোলে লগ করি:
async loadBlockchainData() {
const web3 = window.web3
const accounts = await web3.eth.getAccounts()
console.log(accounts)
}
এখন আপনার ব্রাউজারে যান এবং কনসোলে লগইন অ্যাকাউন্ট দেখুন!
এর পরে, আমরা এই অ্যাকাউন্টটিকে রিঅ্যাক্ট স্টেট অবজেক্টে সংরক্ষণ করতে যাচ্ছি যাতে আমরা পরে এটি ব্যবহার করতে পারি:
async loadBlockchainData() {
const web3 = window.web3
const accounts = await web3.eth.getAccounts()
console.log(accounts)
this.setState({ account: accounts[0] })
}
আমরা এখানে থাকাকালীন, স্টেট অবজেক্টের জন্য কিছু ডিফল্ট মান সেট করি। প্রতিক্রিয়া আমাদের এই মত করতে দেয়:
constructor(props) {
super(props)
this.state = {
account: '',
productCount: 0,
products: [],
loading: true
}
}
এখন আমরা Navbar এ পৃষ্ঠায় অ্যাকাউন্টের তালিকা করতে পারি। আমরা এখানে থাকাকালীন আমি এগিয়ে যেতে এবং Navbar-এর জন্য একটি নতুন উপাদান তৈরি করতে যাচ্ছি। আমি ভিডিওর শেষে এটি করি, তাই এটি কিছুটা শৃঙ্খলার বাইরে। যাইহোক, আমি মনে করি এটি করার সেরা সময়।
প্রথমে, App.js-এর মতো একই ডিরেক্টরির ভিতরে Navbar.js নামে একটি নতুন উপাদান তৈরি করুন। তারপর সেই ফাইলের ভিতরে এই কোডটি ব্যবহার করুন:
import React, { Component } from 'react';
class Navbar extends Component {
render() {
return (
<nav className="navbar navbar-dark fixed-top bg-dark flex-md-nowrap p-0 shadow">
<a
className="navbar-brand col-sm-3 col-md-2 mr-0"
href="http://www.dappuniversity.com/bootcamp"
target="_blank"
rel="noopener noreferrer"
>
Dapp University's Blockchain Marketplace
</a>
<ul className="navbar-nav px-3">
<li className="nav-item text-nowrap d-none d-sm-none d-sm-block">
<small className="text-white"><span id="account">{this.props.account}</span></small>
</li>
</ul>
</nav>
);
}
}
export default Navbar;
লক্ষ্য করুন যে এটি {this.props.account} এর সাথে অ্যাকাউন্টটি পড়ে। এটি প্রতিক্রিয়ার প্রপস অবজেক্ট ব্যবহার করে, যা সমস্ত প্রতিক্রিয়া উপাদানগুলির জন্য উপলব্ধ। যখন আমরা App.js এর ভিতরে রেন্ডার করি তখন আমাদের এই প্রপগুলিকে এই উপাদানটিতে পাস করতে হবে। এর পরের কাজ করা যাক.
এখন App.js এর শীর্ষে Navbar উপাদান আমদানি করুন:
import Navbar from './Navbar'
এখন পৃষ্ঠায় এটি রেন্ডার করা যাক. প্রথমে, সমস্ত পুরানো Navbar কোড মুছে দিন, এবং এটির সাথে এটি প্রতিস্থাপন করুন:
<Navbar account={this.state.account} />
লক্ষ্য করুন যে আমরা রিঅ্যাক্টের স্টেট অবজেক্ট থেকে অ্যাকাউন্টটি পড়ি, তারপর এটিকে প্রপসের মাধ্যমে Navbar কম্পোনেন্টে পাঠাই। এখন ওয়েব ব্রাউজারে আপনার অ্যাপে যান এবং পৃষ্ঠায় তালিকাভুক্ত অ্যাকাউন্টটি দেখুন!
এর পরে, মার্কেটপ্লেস স্মার্ট চুক্তিতে সংযোগ যোগ করা যাক। প্রথমে, আমরা App.js এর শীর্ষে স্মার্ট চুক্তি ABI আমদানি করব এইভাবে:
import Marketplace from '../abis/Marketplace.json'
এখন, স্মার্ট চুক্তি সংযোগ করতে loadBlockchainData() ফাংশন আপডেট করা যাক:
async loadBlockchainData() {
const web3 = window.web3
// Load account
const accounts = await web3.eth.getAccounts()
this.setState({ account: accounts[0] })
const networkId = await web3.eth.net.getId()
const networkData = Marketplace.networks[networkId]
if(networkData) {
const marketplace = web3.eth.Contract(Marketplace.abi, networkData.address)
console.log(marketplace)
} else {
window.alert('Marketplace contract not deployed to detected network.')
}
}
এই কোডটি কয়েকটি জিনিস করে:
- মেটামাস্কের সাথে আমরা কোন নেটওয়ার্কে সংযুক্ত আছি তা নির্ধারণ করতে নেটওয়ার্কআইডি পড়ে, যেমন, গানচে। উদাহরণ স্বরূপ প্রধান Ethereum নেটওয়ার্কের পরিবর্তে Ganache নেটওয়ার্কে নিয়োজিত স্মার্ট চুক্তিতে সংযোগ করতে আমরা এই নেটওয়ার্ক ID ব্যবহার করব।
- এর পরে, আমরা web3.js-এর সাথে web3.eth.Contract() এর সাথে স্মার্ট চুক্তিটি চালু করি। এটি করার জন্য আমাদের 2 টুকরো তথ্যের প্রয়োজন: স্মার্ট চুক্তি ABI, এবং ঠিকানা। আমরা এইমাত্র যে ফাইলটি আমদানি করেছি তা থেকে আমরা উভয়ই নিয়ে আসি।
- অবশেষে, যদি আমরা নেটওয়ার্কে স্মার্ট চুক্তি খুঁজে না পাই, আমরা ব্যবহারকারীকে সতর্ক করি। আপনি মেটামাস্কের প্রধান Ethereum নেটওয়ার্কে স্যুইচ করে এটি পরীক্ষা করতে পারেন (শুধু ফিরে যেতে ভুলবেন না)।
এখন আপনার চূড়ান্ত উপাদান এই মত হওয়া উচিত:
import React, { Component } from 'react';
import Web3 from 'web3'
import logo from '../logo.png';
import './App.css';
import Marketplace from '../abis/Marketplace.json'
import Navbar from './Navbar'
class App extends Component {
async componentWillMount() {
await this.loadWeb3()
await this.loadBlockchainData()
}
async loadWeb3() {
if (window.ethereum) {
window.web3 = new Web3(window.ethereum)
await window.ethereum.enable()
}
else if (window.web3) {
window.web3 = new Web3(window.web3.currentProvider)
}
else {
window.alert('Non-Ethereum browser detected. You should consider trying MetaMask!')
}
}
async loadBlockchainData() {
const web3 = window.web3
// Load account
const accounts = await web3.eth.getAccounts()
this.setState({ account: accounts[0] })
const networkId = await web3.eth.net.getId()
const networkData = Marketplace.networks[networkId]
if(networkData) {
const marketplace = web3.eth.Contract(Marketplace.abi, networkData.address)
console.log(marketplace)
} else {
window.alert('Marketplace contract not deployed to detected network.')
}
}
constructor(props) {
super(props)
this.state = {
account: '',
productCount: 0,
products: [],
loading: true
}
}
render() {
return (
<div>
<Navbar account={this.state.account} />
<div className="container-fluid mt-5">
<div className="row">
<main role="main" className="col-lg-12 d-flex text-center">
<div className="content mr-auto ml-auto">
<a
href="http://www.dappuniversity.com/bootcamp"
target="_blank"
rel="noopener noreferrer"
>
<img src={logo} className="App-logo" alt="logo" />
</a>
<h1>Dapp University Starter Kit</h1>
<p>
Edit <code>src/components/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="http://www.dappuniversity.com/bootcamp"
target="_blank"
rel="noopener noreferrer"
>
LEARN BLOCKCHAIN <u><b>NOW! </b></u>
</a>
</div>
</main>
</div>
</div>
</div>
);
}
}
export default App;
কি দারুন! আমরা এই বিভাগে খুব দ্রুত মাটি অনেক কভার. অনেক তথ্য থাকলে চিন্তা করবেন না। আরও স্পষ্টীকরণের জন্য ভিডিওর এই অংশটি পুনরায় দেখতে নির্দ্বিধায়৷ আপনি এখানে সমস্ত কোডের একটি অনুলিপিও খুঁজে পেতে পারেন।
পার্ট 5: পণ্য বিক্রি করুন (সামনে)
টিউটোরিয়ালের এই অংশের সাথে ভিডিও ফুটেজ শুরু হয় 01:53:10 এ। আপনি এখানে কোড খুঁজে পেতে পারেন.
এখন আমাদের মার্কেটপ্লেস ওয়েবসাইট থেকে পণ্য বিক্রি করার একটি উপায় তৈরি করা যাক। আমরা এই কাজগুলি করব:
- একটি প্রতিক্রিয়া উপাদান তৈরি করুন যা আমাদের কোডের জন্য স্ক্যাফোল্ড ধারণ করে, এমন একটি ফর্ম যা ব্যবহারকারীদের নতুন পণ্য তালিকাভুক্ত করতে দেয় এবং একটি টেবিল যা বিক্রয়ের জন্য পণ্যগুলি দেখায়।
- আমরা ফর্মটি ওয়্যার আপ করব যাতে ব্যবহারকারীরা তাদের পণ্যটি ব্লকচেইনে বিক্রয়ের জন্য তালিকাভুক্ত করতে পারে।
প্রথমে, আমাদের loadBlockchainData() ফাংশনে আরও কিছু ডেটা যোগ করা যাক। আমরা পণ্য গণনা পাব
async loadBlockchainData() {
const web3 = window.web3
// Load account
const accounts = await web3.eth.getAccounts()
this.setState({ account: accounts[0] })
const networkId = await web3.eth.net.getId()
const networkData = Marketplace.networks[networkId]
if(networkData) {
const marketplace = web3.eth.Contract(Marketplace.abi, networkData.address)
this.setState({ marketplace })
const productCount = await marketplace.methods.productCount().call()
console.log(productCount.toString())
this.setState({ loading: false})
} else {
window.alert('Marketplace contract not deployed to detected network.')
}
}
এর পরে, আমরা এমন একটি ফাংশন তৈরি করব যা এইরকম Web3.js-এর সাথে createProduct() ফাংশনকে কল করে ব্লকচেইনে পণ্য যোগ করে:
createProduct(name, price) {
this.setState({ loading: true })
this.state.marketplace.methods.createProduct(name, price).send({ from: this.state.account })
.once('receipt', (receipt) => {
this.setState({ loading: false })
})
আমাকে এই কোড ব্যাখ্যা করা যাক:
- প্রথমত, আমরা একটি জাভাস্ক্রিপ্ট ফাংশন তৈরি করি যা আমাদের স্মার্ট কন্ট্রাক্ট ফাংশনের মতো একই প্যারামিটার গ্রহণ করে
- তারপরে স্মার্ট কন্ট্রাক্ট ফাংশন কল করার আগে, আমরা প্রতিক্রিয়াকে বলি যে আমাদের অ্যাপ "লোড হচ্ছে" যাতে ব্যবহারকারী জানতে পারে যে ফাংশনটি জমা দেওয়া হয়েছে৷
- তারপর আমরা এই.this.state.marketplace.methods.createProduct(name, price).send({ from: this.state.account }). দিয়ে Web3.js-এর সাথে স্মার্ট কন্ট্রাক্ট ফাংশনকে কল করি। এটি ফাংশনটিকে কল করে এবং Web3 কে বলে যে বর্তমান অ্যাকাউন্টটি সেই ব্যবহারকারী যা এটিকে কল করছে৷
- অবশেষে, একবার লেনদেনের রসিদ পাওয়া গেলে, আমরা অ্যাপটিকে "লোড হচ্ছে" অবস্থা থেকে সরিয়ে দিই যাতে ব্যবহারকারী জানতে পারে ফাংশন কল সম্পূর্ণ হয়েছে।
এই ফাংশনটিকে ফর্মের সাথে কল করার জন্য, আমাদের অবশ্যই এটিকে কনস্ট্রাক্টরের ভিতরের উপাদানের সাথে এইভাবে আবদ্ধ করতে হবে:
constructor(props) {
// ...
this.createProduct = this.createProduct.bind(this)
}
এখন আমরা এটিকে সাব কম্পোনেন্টে পাঠাতে পারি। কিন্তু প্রথমে আমাদের এটি তৈরি করতে হবে! চলুন বর্তমান ডিরেক্টরিতে একটি নতুন ফাইল তৈরি করি যাকে বলা হয়.
Main.js
নিম্নলিখিত কোড সহ:
import React, { Component } from 'react';
class Main extends Component {
render() {
return (
<div id="content">
<h1>Add Product</h1>
<form onSubmit={(event) => {
event.preventDefault()
const name = this.productName.value
const price = window.web3.utils.toWei(this.productPrice.value.toString(), 'Ether')
this.props.createProduct(name, price)
}}>
<div className="form-group mr-sm-2">
<input
id="productName"
type="text"
ref={(input) => { this.productName = input }}
className="form-control"
placeholder="Product Name"
required />
</div>
<div className="form-group mr-sm-2">
<input
id="productPrice"
type="text"
ref={(input) => { this.productPrice = input }}
className="form-control"
placeholder="Product Price"
required />
</div>
<button type="submit" className="btn btn-primary">Add Product</button>
</form>
<p> </p>
<h2>Buy Product</h2>
<table className="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">Price</th>
<th scope="col">Owner</th>
<th scope="col"></th>
</tr>
</thead>
<tbody id="productList">
<tr>
<th scope="row">1</th>
<td>iPhone x</td>
<td>1 Eth</td>
<td>0x39C7BC5496f4eaaa1fF75d88E079C22f0519E7b9</td>
<td><button className="buyButton">Buy</button></td>
</tr>
<tr>
<th scope="row">2</th>
<td>Macbook Pro</td>
<td>3 eth</td>
<td>0x39C7BC5496f4eaaa1fF75d88E079C22f0519E7b9</td>
<td><button className="buyButton">Buy</button></td>
</tr>
<tr>
<th scope="row">3</th>
<td>Airpods</td>
<td>0.5 eth</td>
<td>0x39C7BC5496f4eaaa1fF75d88E079C22f0519E7b9</td>
<td><button className="buyButton">Buy</button></td>
</tr>
</tbody>
</table>
</div>
);
}
}
export default Main;
এই উপাদানটি মার্কেটপ্লেস UI এর জন্য সমস্ত ভারা যুক্ত করে। এটি একটি ফর্মও তৈরি করে যা createProduct() ফাংশনকে কল করে ব্লকচেইনে পণ্য যোগ করবে। ভিডিওতে এই কোডটির সম্পূর্ণ ব্যাখ্যা দেখতে বিনা দ্বিধায়।
কিন্তু এই উপাদানটি এখনও কাজ করবে না! আমাদের প্রথমে কিছু কাজ করতে হবে। App.js-এ ফিরে যান এবং ফাইলের শীর্ষে সদ্য তৈরি উপাদানটি এইভাবে আমদানি করুন:
import Main from './Main'
এখন এটি দিয়ে <main> HTML ট্যাগের ভিতরে সবকিছু প্রতিস্থাপন করুন:
<main role="main" className="col-lg-12 d-flex">
{ this.state.loading
? <div id="loader" className="text-center"><p className="text-center">Loading...</p></div>
: <Main createProduct={this.createProduct} />
}
</main>
যখনই অ্যাপটি লোড হবে তখন এটি নতুন তৈরি উপাদানটিকে পৃষ্ঠায় রেন্ডার করবে। যদি লোড হয়, তাহলে লোডার দেখাবে!
🎉 হ্যাঁ! এখন আপনার ব্রাউজারে যান এবং এই নতুন ফর্মের সাথে একটি পণ্য যোগ করার চেষ্টা করুন!
কি দারুন! আমরা এই বিভাগে খুব দ্রুত মাটি অনেক কভার. অনেক তথ্য থাকলে চিন্তা করবেন না। আরও স্পষ্টীকরণের জন্য ভিডিওর এই অংশটি পুনরায় দেখতে নির্দ্বিধায়৷ আপনি এখানে সমস্ত কোডের একটি অনুলিপিও খুঁজে পেতে পারেন।
পার্ট 6: পণ্য কিনুন (ফ্রন্ট এন্ড)
টিউটোরিয়ালের এই অংশের সাথে ভিডিও ফুটেজ শুরু হয় 02:11:53 এ। আপনি এখানে কোড খুঁজে পেতে পারেন.
এখন ব্যবহারকারীদের বাজারে পণ্য কেনার অনুমতি দিয়ে আমাদের অ্যাপটি শেষ করা যাক। আমরা এই বিভাগে দুটি জিনিস করব:
- পৃষ্ঠায় সমস্ত পণ্যের তালিকা করুন
- ব্যবহারকারীদের একটি বোতামে ক্লিক করে সেগুলি কিনতে অনুমতি দিন
প্রথমে, আসুন loadBlockchainData() ফাংশনের ভিতরে ব্লকচেইন থেকে সমস্ত পণ্য নিয়ে আসি এইভাবে:
const productCount = await marketplace.methods.productCount().call()
this.setState({ productCount })
// Load products
for (var i = 1; i <= productCount; i++) {
const product = await marketplace.methods.products(i).call()
this.setState({
products: [...this.state.products, product]
})
}
কতগুলি পণ্য বিদ্যমান তা নির্ধারণ করতে আমরা স্মার্ট কন্ট্রাক্টের ভিতরে যে কাউন্টার ক্যাশে তৈরি করেছি তা ব্যবহার করি, তারপরে আমরা প্রতিটি পণ্যকে আলাদাভাবে আনতে এবং এটিকে রিঅ্যাক্ট স্টেট অবজেক্টে সংরক্ষণ করতে একটি লুপ ব্যবহার করি। এই তথ্যের সাহায্যে, আমরা মুহূর্তের মধ্যে পৃষ্ঠায় পণ্য রেন্ডার করতে পারি।
এখন, proudct কেনার জন্য একটি ফাংশন তৈরি করা যাক:
purchaseProduct(id, price) {
this.setState({ loading: true })
this.state.marketplace.methods.purchaseProduct(id).send({ from: this.state.account, value: price })
.once('receipt', (receipt) => {
this.setState({ loading: false })
})
}
এখন কনস্ট্রাক্টরের ভিতরে ফাংশনটি আবদ্ধ করা যাক:
constructor(props) {
// ...
this.createProduct = this.createProduct.bind(this)
this.purchaseProduct = this.purchaseProduct.bind(this)
}
এখন আমরা প্রধান উপাদানে দুটি নতুন প্রপস পাস করব:
- পৃষ্ঠায় তালিকাভুক্ত করা যেতে পারে যে পণ্য সব
- purchaseProdct() ফাংশন যাতে এটি সাব কম্পোনেন্টে কল করা যায়
আমরা আমাদের কোড আপডেট করব যাতে এটি এইরকম দেখায়:
<main role="main" className="col-lg-12 d-flex">
{ this.state.loading
? <div id="loader" className="text-center"><p className="text-center">Loading...</p></div>
: <Main
products={this.state.products}
createProduct={this.createProduct}
purchaseProduct={this.purchaseProduct} />
}
</main>
অসাধারণ! এখন আসুন Main.js ফাইলের ভিতরে কোডটি আপডেট করি যাতে সমস্ত পণ্য তালিকাভুক্ত হয় এবং ব্যবহারকারীদের সেগুলি কেনার অনুমতি দেওয়া হয়। এটি দিয়ে <tbody> ট্যাগের ভিতরে সমস্ত কোড প্রতিস্থাপন করুন:
{ this.props.products.map((product, key) => {
return(
<tr key={key}>
<th scope="row">{product.id.toString()}</th>
<td>{product.name}</td>
<td>{window.web3.utils.fromWei(product.price.toString(), 'Ether')} Eth</td>
<td>{product.owner}</td>
<td>
{ !product.purchased
? <button
name={product.id}
value={product.price}
onClick={(event) => {
this.props.purchaseProduct(event.target.name, event.target.value)
}}
>
Buy
</button>
: null
}
</td>
</tr>
)
})}
এই কোডটি কয়েকটি জিনিস করে:
- সমস্ত পণ্যের মধ্য দিয়ে লুপ করে, এবং প্রতিটির জন্য অনন্য টেবিল সারি তৈরি করে
- একটি বোতাম যুক্ত করে যাতে পণ্যগুলি একক ক্লিকে কেনা যায়, আমরা এইমাত্র তৈরি করা purchaseProduct() ফাংশনটিকে কল করে৷
অসাধারণ! এখন আপনার ব্রাউজারে যান এবং একটি পণ্য কেনার চেষ্টা করুন!
FWEW ! আমরা অবশ্যই এই বিভাগে খুব দ্রুত অনেক তথ্য কভার করেছি... আপনি যদি প্রথমবার এটি না পান তবে চিন্তা করবেন না। আরও স্পষ্টীকরণের জন্য ভিডিওর এই অংশটি পুনরায় দেখতে নির্দ্বিধায়৷ আপনি এখানে সমস্ত কোডের একটি অনুলিপিও খুঁজে পেতে পারেন।
পার্ট 7: প্রজেক্ট স্থাপন করুন
টিউটোরিয়ালের এই অংশের সাথে ভিডিও ফুটেজ শুরু হয় 02:27:44 এ। আপনি এখানে কোড খুঁজে পেতে পারেন.
এখন আসুন আমাদের প্রকল্পকে একটি লাইভ ব্লকচেইনে স্থাপন করি। এই বিভাগের জন্য প্রতিটি ধাপ লেখার পরিবর্তে, আপনি যদি ভিডিওতে আমার সাথে অনুসরণ করেন তবে এটি সবচেয়ে ভাল কাজ করবে। আমি এই স্থাপনার জন্য একটি পৃথক ভিডিও যোগ করেছি যা আপনি এখানে দেখতে পারেন:
হুররে! 🎉 আপনি একটি ফুল-স্ট্যাক ব্লকচেইন অ্যাপ্লিকেশন তৈরি করেছেন! অভিনন্দন, আপনি এই টিউটোরিয়ালে এতদূর এসেছেন।
এই টিউটোরিয়াল দিয়ে খুশি? তারপরে আপনাকে এখানে আমার বিনামূল্যের প্রশিক্ষণে যোগদান করতে হবে যেখানে আমি আপনাকে দেখাব কিভাবে একটি বাস্তব বিশ্বের ব্লকচেইন অ্যাপ তৈরি করতে হয় যাতে আপনি একজন উচ্চ অর্থপ্রদানকারী ব্লকচেইন বিকাশকারী হতে পারেন!















No comments:
Post a Comment