মূল কন্টেন্টে যান

NFT মিন্টার টিউটোরিয়াল

Solidity
NFT
Alchemy
স্মার্ট কন্ট্রাক্ট
ফ্রন্টএন্ড
Pinata
ERC-721
ইন্টারমিডিয়েট
smudgil
৬ অক্টোবর, ২০২১
28 মিনিট পড়া

Web2 ব্যাকগ্রাউন্ড থেকে আসা ডেভেলপারদের জন্য অন্যতম বড় চ্যালেঞ্জ হলো কীভাবে আপনার স্মার্ট কন্ট্রাক্টকে একটি ফ্রন্টএন্ড প্রজেক্টের সাথে সংযুক্ত করতে হয় এবং এর সাথে ইন্টারঅ্যাক্ট করতে হয় তা বের করা।

একটি NFT মিন্টার তৈরি করার মাধ্যমে — একটি সাধারণ UI যেখানে আপনি আপনার ডিজিটাল অ্যাসেটের লিংক, একটি শিরোনাম এবং একটি বিবরণ ইনপুট করতে পারবেন — আপনি শিখবেন কীভাবে:

  • আপনার ফ্রন্টএন্ড প্রজেক্টের মাধ্যমে MetaMask-এ সংযুক্ত হতে হয়
  • আপনার ফ্রন্টএন্ড থেকে স্মার্ট কন্ট্রাক্ট মেথড কল করতে হয়
  • MetaMask ব্যবহার করে লেনদেন সাইন করতে হয়

এই টিউটোরিয়ালে, আমরা আমাদের ফ্রন্টএন্ড ফ্রেমওয়ার্ক হিসেবে React (opens in a new tab) ব্যবহার করব। যেহেতু এই টিউটোরিয়ালটি মূলত ওয়েব3 (Web3) ডেভেলপমেন্টের ওপর নিবদ্ধ, তাই আমরা React-এর মৌলিক বিষয়গুলো ব্যাখ্যা করতে খুব বেশি সময় ব্যয় করব না। এর পরিবর্তে, আমরা আমাদের প্রজেক্টে কার্যকারিতা আনার দিকে মনোযোগ দেব।

পূর্বশর্ত হিসেবে, আপনার React সম্পর্কে প্রাথমিক স্তরের ধারণা থাকা উচিত—কম্পোনেন্ট, প্রপস, useState/useEffect এবং বেসিক ফাংশন কলিং কীভাবে কাজ করে তা জানা উচিত। আপনি যদি আগে কখনো এই শব্দগুলো না শুনে থাকেন, তবে আপনি এই Intro to React tutorial (opens in a new tab) দেখতে পারেন। যারা ভিজ্যুয়ালি শিখতে বেশি পছন্দ করেন, তাদের জন্য আমরা Net Ninja-এর এই চমৎকার Full Modern React Tutorial (opens in a new tab) ভিডিও সিরিজটি দেখার জন্য জোরালোভাবে সুপারিশ করছি।

আর যদি আপনি ইতিমধ্যে তা না করে থাকেন, তবে এই টিউটোরিয়ালটি সম্পন্ন করতে এবং ব্লকচেইন-এ যেকোনো কিছু তৈরি করতে আপনার অবশ্যই একটি Alchemy একাউন্ট প্রয়োজন হবে। এখানে (opens in a new tab) একটি ফ্রি একাউন্ট তৈরি করুন।

আর কথা না বাড়িয়ে, চলুন শুরু করা যাক!

NFT তৈরি করা 101

আমরা কোনো কোড দেখার আগে, একটি NFT তৈরি করা কীভাবে কাজ করে তা বোঝা গুরুত্বপূর্ণ। এর দুটি ধাপ রয়েছে:

ইথিরিয়াম ব্লকচেইন-এ একটি NFT স্মার্ট কন্ট্রাক্ট পাবলিশ করা

দুটি NFT স্মার্ট কন্ট্রাক্ট স্ট্যান্ডার্ডের মধ্যে সবচেয়ে বড় পার্থক্য হলো ERC-1155 একটি মাল্টি-টোকেন স্ট্যান্ডার্ড এবং এতে ব্যাচ কার্যকারিতা অন্তর্ভুক্ত রয়েছে, যেখানে ERC-721 একটি সিঙ্গেল-টোকেন স্ট্যান্ডার্ড এবং তাই এটি একবারে কেবল একটি টোকেন ট্রান্সফার সমর্থন করে।

মিন্টিং ফাংশন কল করা

সাধারণত, এই মিন্টিং ফাংশনে প্যারামিটার হিসেবে দুটি ভেরিয়েবল পাস করতে হয়, প্রথমটি হলো recipient, যা সেই এডড্রেস নির্দিষ্ট করে যা আপনার নতুন মিন্ট করা NFT গ্রহণ করবে, এবং দ্বিতীয়টি হলো NFT-এর tokenURI, একটি স্ট্রিং যা NFT-এর মেটাডাটা বর্ণনা করে এমন একটি JSON ডকুমেন্টে রিজলভ হয়।

একটি NFT-এর মেটাডাটাই মূলত এটিকে জীবন্ত করে তোলে, যার ফলে এর নাম, বিবরণ, ছবি (বা ভিন্ন ডিজিটাল অ্যাসেট) এবং অন্যান্য বৈশিষ্ট্যের মতো প্রপার্টি থাকতে পারে। এখানে একটি tokenURI-এর উদাহরণ (opens in a new tab) দেওয়া হলো, যাতে একটি NFT-এর মেটাডাটা রয়েছে।

এই টিউটোরিয়ালে, আমরা ২য় অংশের ওপর ফোকাস করব, আমাদের React UI ব্যবহার করে একটি বিদ্যমান NFT-এর স্মার্ট কন্ট্রাক্ট মিন্টিং ফাংশন কল করা।

এই টিউটোরিয়ালে আমরা যে ERC-721 NFT স্মার্ট কন্ট্রাক্টটি কল করব তার একটি লিংক এখানে দেওয়া হলো (opens in a new tab)। আপনি যদি জানতে চান আমরা এটি কীভাবে তৈরি করেছি, তবে আমরা জোরালোভাবে সুপারিশ করছি যে আপনি আমাদের অন্য টিউটোরিয়াল, "How to Create an NFT" (opens in a new tab) দেখে নিন।

চমৎকার, এখন যেহেতু আমরা বুঝতে পেরেছি কীভাবে একটি NFT তৈরি করা কাজ করে, চলুন আমাদের স্টার্টার ফাইলগুলো ক্লোন করি!

স্টার্টার ফাইলগুলো ক্লোন করুন

প্রথমে, এই প্রজেক্টের স্টার্টার ফাইলগুলো পেতে nft-minter-tutorial GitHub রিপোজিটরিতে (opens in a new tab) যান। এই রিপোজিটরিটি আপনার লোকাল এনভায়রনমেন্টে ক্লোন করুন।

আপনি যখন এই ক্লোন করা nft-minter-tutorial রিপোজিটরিটি খুলবেন, তখন আপনি দেখতে পাবেন যে এতে দুটি ফোল্ডার রয়েছে: minter-starter-files এবং nft-minter

  • minter-starter-files-এ এই প্রজেক্টের স্টার্টার ফাইলগুলো (মূলত React UI) রয়েছে। এই টিউটোরিয়ালে, আমরা এই ডিরেক্টরিতে কাজ করব, কারণ আপনি শিখবেন কীভাবে এই UI-কে আপনার ইথিরিয়াম ওয়ালেট এবং একটি NFT স্মার্ট কন্ট্রাক্ট-এর সাথে সংযুক্ত করে জীবন্ত করে তুলতে হয়।
  • nft-minter-এ সম্পূর্ণ টিউটোরিয়ালটি রয়েছে এবং এটি আপনার জন্য একটি রেফারেন্স হিসেবে দেওয়া হয়েছে যদি আপনি কোথাও আটকে যান।

এরপর, আপনার কোড এডিটরে minter-starter-files-এর কপিটি খুলুন এবং তারপর আপনার src ফোল্ডারে নেভিগেট করুন।

আমরা যে কোডগুলো লিখব তার সবই src ফোল্ডারের অধীনে থাকবে। আমরা Minter.js কম্পোনেন্টটি এডিট করব এবং আমাদের প্রজেক্টে ওয়েব3 (Web3) কার্যকারিতা দেওয়ার জন্য অতিরিক্ত জাভাস্ক্রিপ্ট ফাইল লিখব।

ধাপ 2: আমাদের স্টার্টার ফাইলগুলো দেখে নিন

কোডিং শুরু করার আগে, স্টার্টার ফাইলগুলোতে আমাদের জন্য ইতিমধ্যে কী দেওয়া আছে তা দেখে নেওয়া গুরুত্বপূর্ণ।

আপনার react প্রজেক্টটি চালু করুন

চলুন আমাদের ব্রাউজারে React প্রজেক্টটি রান করার মাধ্যমে শুরু করি। React-এর সৌন্দর্য হলো একবার আমাদের প্রজেক্ট ব্রাউজারে রান করলে, আমরা যে পরিবর্তনগুলো সেভ করব তা ব্রাউজারে লাইভ আপডেট হবে।

প্রজেক্টটি রান করতে, minter-starter-files ফোল্ডারের রুট ডিরেক্টরিতে নেভিগেট করুন এবং প্রজেক্টের ডিপেন্ডেন্সিগুলো ইনস্টল করতে আপনার টার্মিনালে npm install রান করুন:

cd minter-starter-files
npm install

সেগুলো ইনস্টল হওয়া শেষ হলে, আপনার টার্মিনালে npm start রান করুন:

npm start

এটি করার ফলে আপনার ব্রাউজারে http://localhost:3000/ (opens in a new tab) খুলবে, যেখানে আপনি আমাদের প্রজেক্টের ফ্রন্টএন্ড দেখতে পাবেন। এতে 3টি ফিল্ড থাকা উচিত: আপনার NFT-এর অ্যাসেটের লিংক ইনপুট করার জায়গা, আপনার NFT-এর নাম এন্টার করার জায়গা এবং একটি বিবরণ দেওয়ার জায়গা।

আপনি যদি "Connect Wallet" বা "Mint NFT" বোতামগুলোতে ক্লিক করার চেষ্টা করেন, তবে আপনি লক্ষ্য করবেন যে সেগুলো কাজ করছে না—এর কারণ হলো আমাদের এখনও সেগুলোর কার্যকারিতা প্রোগ্রাম করতে হবে! :)

Minter.js কম্পোনেন্ট

নোট: নিশ্চিত করুন যে আপনি minter-starter-files ফোল্ডারে আছেন এবং nft-minter ফোল্ডারে নেই!

চলুন আমাদের এডিটরে src ফোল্ডারে ফিরে যাই এবং Minter.js ফাইলটি খুলি। এই ফাইলের সবকিছু বোঝা আমাদের জন্য অত্যন্ত গুরুত্বপূর্ণ, কারণ এটিই সেই প্রাথমিক React কম্পোনেন্ট যা নিয়ে আমরা কাজ করব।

এই ফাইলের একেবারে ওপরে, আমাদের স্টেট (state) ভেরিয়েবলগুলো রয়েছে যা আমরা নির্দিষ্ট ইভেন্টের পরে আপডেট করব।

1// স্টেট ভেরিয়েবল
2const [walletAddress, setWallet] = useState("")
3const [status, setStatus] = useState("")
4const [name, setName] = useState("")
5const [description, setDescription] = useState("")
6const [url, setURL] = useState("")

React স্টেট ভেরিয়েবল বা স্টেট হুক সম্পর্কে কখনো শোনেননি? এই (opens in a new tab) ডক্সগুলো দেখে নিন।

প্রতিটি ভেরিয়েবল যা উপস্থাপন করে তা নিচে দেওয়া হলো:

  • walletAddress - একটি স্ট্রিং যা ব্যবহারকারীর ওয়ালেট এডড্রেস স্টোর করে
  • status - একটি স্ট্রিং যাতে UI-এর নিচে প্রদর্শন করার জন্য একটি মেসেজ থাকে
  • name - একটি স্ট্রিং যা NFT-এর নাম স্টোর করে
  • description - একটি স্ট্রিং যা NFT-এর বিবরণ স্টোর করে
  • url - একটি স্ট্রিং যা NFT-এর ডিজিটাল অ্যাসেটের একটি লিংক

স্টেট ভেরিয়েবলগুলোর পরে, আপনি তিনটি ইমপ্লিমেন্ট না করা ফাংশন দেখতে পাবেন: useEffect, connectWalletPressed, এবং onMintPressed। আপনি লক্ষ্য করবেন যে এই সমস্ত ফাংশনগুলো async, এর কারণ হলো আমরা এগুলোতে অ্যাসিনক্রোনাস API কল করব! তাদের নামগুলো তাদের কার্যকারিতার সাথেই সামঞ্জস্যপূর্ণ:

1useEffect(async () => {
2 // TODO: ইমপ্লিমেন্ট করুন
3}, [])
4
5const connectWalletPressed = async () => {
6 // TODO: ইমপ্লিমেন্ট করুন
7}
8
9const onMintPressed = async () => {
10 // TODO: ইমপ্লিমেন্ট করুন
11}
সব দেখান
  • useEffect (opens in a new tab) - এটি একটি React হুক যা আপনার কম্পোনেন্ট রেন্ডার হওয়ার পরে কল করা হয়। যেহেতু এতে একটি খালি অ্যারে [] প্রপ পাস করা হয়েছে (লাইন 3 দেখুন), এটি কেবল কম্পোনেন্টের প্রথম রেন্ডারেই কল করা হবে। এখানে আমরা আমাদের ওয়ালেট লিসেনার এবং অন্য একটি ওয়ালেট ফাংশন কল করব যাতে আমাদের UI আপডেট করে দেখানো যায় যে কোনো ওয়ালেট ইতিমধ্যে সংযুক্ত আছে কি না।
  • connectWalletPressed - ব্যবহারকারীর MetaMask ওয়ালেটকে আমাদের ডিএ্যাপ-এর সাথে সংযুক্ত করতে এই ফাংশনটি কল করা হবে।
  • onMintPressed - ব্যবহারকারীর NFT মিন্ট করতে এই ফাংশনটি কল করা হবে।

এই ফাইলের শেষের দিকে, আমাদের কম্পোনেন্টের UI রয়েছে। আপনি যদি এই কোডটি মনোযোগ সহকারে স্ক্যান করেন, তবে আপনি লক্ষ্য করবেন যে আমরা আমাদের url, name, এবং description স্টেট ভেরিয়েবলগুলো আপডেট করি যখন তাদের সংশ্লিষ্ট টেক্সট ফিল্ডের ইনপুট পরিবর্তিত হয়।

আপনি আরও দেখতে পাবেন যে connectWalletPressed এবং onMintPressed কল করা হয় যখন যথাক্রমে mintButton এবং walletButton আইডিযুক্ত বোতামগুলোতে ক্লিক করা হয়।

1// আমাদের কম্পোনেন্টের UI
2return (
3 <div className="Minter">
4 <button id="walletButton" onClick={connectWalletPressed}>
5 {walletAddress.length > 0 ? (
6 "Connected: " +
7 String(walletAddress).substring(0, 6) +
8 "..." +
9 String(walletAddress).substring(38)
10 ) : (
11 <span>Connect Wallet</span>
12 )}
13 </button>
14
15 <br></br>
16 <h1 id="title">🧙‍♂️ Alchemy NFT Minter</h1>
17 <p>
18 Simply add your asset's link, name, and description, then press "Mint."
19 </p>
20 <form>
21 <h2>🖼 Link to asset: </h2>
22 <input
23 type="text"
24 placeholder="e.g., https://gateway.pinata.cloud/ipfs/<hash>"
25 onChange={(event) => setURL(event.target.value)}
26 />
27 <h2>🤔 Name: </h2>
28 <input
29 type="text"
30 placeholder="e.g., My first NFT!"
31 onChange={(event) => setName(event.target.value)}
32 />
33 <h2>✍️ Description: </h2>
34 <input
35 type="text"
36 placeholder="e.g., Even cooler than cryptokitties ;)"
37 onChange={(event) => setDescription(event.target.value)}
38 />
39 </form>
40 <button id="mintButton" onClick={onMintPressed}>
41 Mint NFT
42 </button>
43 <p id="status">{status}</p>
44
45</div>
46)
সব দেখান

অবশেষে, চলুন দেখি এই Minter কম্পোনেন্টটি কোথায় যোগ করা হয়েছে।

আপনি যদি App.js ফাইলে যান, যা React-এর প্রধান কম্পোনেন্ট এবং অন্যান্য সমস্ত কম্পোনেন্টের জন্য একটি কন্টেইনার হিসেবে কাজ করে, তবে আপনি দেখতে পাবেন যে আমাদের Minter কম্পোনেন্টটি 7 নম্বর লাইনে ইনজেক্ট করা হয়েছে।

এই টিউটোরিয়ালে, আমরা কেবল Minter.js file এডিট করব এবং আমাদের src ফোল্ডারে ফাইল যোগ করব।

এখন যেহেতু আমরা বুঝতে পেরেছি আমরা কী নিয়ে কাজ করছি, চলুন আমাদের ইথিরিয়াম ওয়ালেট সেট আপ করি!

আপনার ইথিরিয়াম ওয়ালেট সেট আপ করুন

ব্যবহারকারীদের আপনার স্মার্ট কন্ট্রাক্ট-এর সাথে ইন্টারঅ্যাক্ট করতে সক্ষম হওয়ার জন্য তাদের ইথিরিয়াম ওয়ালেটকে আপনার ডিএ্যাপ-এর সাথে সংযুক্ত করতে হবে।

MetaMask ডাউনলোড করুন

এই টিউটোরিয়ালের জন্য, আমরা MetaMask ব্যবহার করব, যা ব্রাউজারে একটি ভার্চুয়াল ওয়ালেট এবং আপনার ইথিরিয়াম একাউন্ট এডড্রেস পরিচালনা করতে ব্যবহৃত হয়। ইথিরিয়ামে লেনদেন কীভাবে কাজ করে সে সম্পর্কে আপনি যদি আরও বুঝতে চান, তবে এই পেজটি দেখে নিন।

আপনি এখানে (opens in a new tab) বিনামূল্যে একটি MetaMask একাউন্ট ডাউনলোড এবং তৈরি করতে পারেন। আপনি যখন একটি একাউন্ট তৈরি করছেন, বা আপনার যদি ইতিমধ্যে একটি একাউন্ট থাকে, তবে নিশ্চিত করুন যে আপনি ওপরের ডানদিকে “Ropsten Test Network”-এ স্যুইচ করেছেন (যাতে আমরা আসল টাকা নিয়ে কাজ না করি)।

একটি ফাসেট থেকে ইথার যোগ করুন

আমাদের NFT মিন্ট করতে (বা ইথিরিয়াম ব্লকচেইন-এ কোনো লেনদেন সাইন করতে), আমাদের কিছু ফেক Eth প্রয়োজন হবে। Eth পেতে আপনি Ropsten ফাসেট (opens in a new tab)-এ যেতে পারেন এবং আপনার Ropsten একাউন্ট এডড্রেস এন্টার করতে পারেন, তারপর “Send Ropsten Eth.”-এ ক্লিক করুন। এর কিছুক্ষণ পরেই আপনার MetaMask একাউন্টে Eth দেখতে পাওয়া উচিত!

আপনার ব্যালেন্স চেক করুন

আমাদের ব্যালেন্স সেখানে আছে কি না তা ডাবল চেক করতে, চলুন Alchemy-এর কম্পোজার টুল (opens in a new tab) ব্যবহার করে একটি eth_getBalance (opens in a new tab) রিকোয়েস্ট করি। এটি আমাদের ওয়ালেটে থাকা Eth-এর পরিমাণ রিটার্ন করবে। আপনার MetaMask একাউন্ট এডড্রেস ইনপুট করার পর এবং “Send Request”-এ ক্লিক করার পর, আপনার এরকম একটি রেসপন্স দেখা উচিত:

1{"jsonrpc": "2.0", "id": 0, "result": "0xde0b6b3a7640000"}

নোট: এই ফলাফলটি wei-তে, eth-এ নয়। Wei ইথারের ক্ষুদ্রতম একক হিসেবে ব্যবহৃত হয়। wei থেকে eth-এ রূপান্তর হলো: 1 eth = 10¹⁸ wei। সুতরাং আমরা যদি 0xde0b6b3a7640000-কে ডেসিমালে রূপান্তর করি তবে আমরা 1*10¹⁸ পাই যা 1 eth-এর সমান।

যাক! আমাদের ফেক টাকা সব সেখানেই আছে!

আপনার UI-এর সাথে MetaMask সংযুক্ত করুন

এখন যেহেতু আমাদের MetaMask ওয়ালেট সেট আপ করা হয়েছে, চলুন আমাদের ডিএ্যাপ-কে এর সাথে সংযুক্ত করি!

যেহেতু আমরা MVC (opens in a new tab) প্যারাডাইম অনুসরণ করতে চাই, তাই আমরা একটি আলাদা ফাইল তৈরি করতে যাচ্ছি যাতে আমাদের ডিএ্যাপ-এর লজিক, ডাটা এবং নিয়মগুলো পরিচালনা করার জন্য আমাদের ফাংশনগুলো থাকবে এবং তারপর সেই ফাংশনগুলোকে আমাদের ফ্রন্টএন্ডে (আমাদের Minter.js কম্পোনেন্ট) পাস করব।

connectWallet ফাংশন

এটি করার জন্য, চলুন আপনার src ডিরেক্টরিতে utils নামে একটি নতুন ফোল্ডার তৈরি করি এবং এর ভেতরে interact.js নামে একটি ফাইল যোগ করি, যাতে আমাদের সমস্ত ওয়ালেট এবং স্মার্ট কন্ট্রাক্ট ইন্টারঅ্যাকশন ফাংশন থাকবে।

আমাদের interact.js ফাইলে, আমরা একটি connectWallet ফাংশন লিখব, যা আমরা পরে আমাদের Minter.js কম্পোনেন্টে ইমপোর্ট এবং কল করব।

আপনার interact.js ফাইলে, নিচের কোডটি যোগ করুন

1export const connectWallet = async () => {
2 if (window.ethereum) {
3 try {
4 const addressArray = await window.ethereum.request({
5 method: "eth_requestAccounts",
6 })
7 const obj = {
8 status: "👆🏽 Write a message in the text-field above.",
9 address: addressArray[0],
10 }
11 return obj
12 } catch (err) {
13 return {
14 address: "",
15 status: "😥 " + err.message,
16 }
17 }
18 } else {
19 return {
20 address: "",
21 status: (
22 <span>
23 <p>
24 {" "}
25 🦊 <a target="_blank" href={`https://metamask.io/download`}>
26 You must install MetaMask, a virtual Ethereum wallet, in your
27 browser.
28 </a>
29 </p>
30 </span>
31 ),
32 }
33 }
34}
সব দেখান

চলুন বিশ্লেষণ করি এই কোডটি কী করে:

প্রথমে, আমাদের ফাংশনটি চেক করে যে আপনার ব্রাউজারে window.ethereum এনাবল করা আছে কি না।

window.ethereum হলো MetaMask এবং অন্যান্য ওয়ালেট প্রোভাইডারদের দ্বারা ইনজেক্ট করা একটি গ্লোবাল API যা ওয়েবসাইটগুলোকে ব্যবহারকারীদের ইথিরিয়াম একাউন্টের জন্য রিকোয়েস্ট করার অনুমতি দেয়। অনুমোদিত হলে, এটি ব্যবহারকারী যে ব্লকচেইন-এর সাথে সংযুক্ত আছে তা থেকে ডাটা পড়তে পারে এবং ব্যবহারকারীকে মেসেজ ও লেনদেন সাইন করার পরামর্শ দিতে পারে। আরও তথ্যের জন্য MetaMask ডক্স (opens in a new tab) দেখে নিন!

যদি window.ethereum উপস্থিত না থাকে, তবে এর অর্থ হলো MetaMask ইনস্টল করা নেই। এর ফলে একটি JSON অবজেক্ট রিটার্ন হয়, যেখানে রিটার্ন করা address হলো একটি খালি স্ট্রিং, এবং status JSX অবজেক্টটি জানায় যে ব্যবহারকারীকে অবশ্যই MetaMask ইনস্টল করতে হবে।

আমরা যে ফাংশনগুলো লিখব তার বেশিরভাগই JSON অবজেক্ট রিটার্ন করবে যা আমরা আমাদের স্টেট ভেরিয়েবল এবং UI আপডেট করতে ব্যবহার করতে পারি।

এখন যদি window.ethereum উপস্থিত থাকে, তবে তখনই বিষয়টি আকর্ষণীয় হয়ে ওঠে।

একটি try/catch লুপ ব্যবহার করে, আমরা window.ethereum.request({ method: "eth_requestAccounts" }); (opens in a new tab) কল করার মাধ্যমে MetaMask-এর সাথে সংযুক্ত হওয়ার চেষ্টা করব। এই ফাংশনটি কল করলে ব্রাউজারে MetaMask খুলবে, যার মাধ্যমে ব্যবহারকারীকে তাদের ওয়ালেটকে আপনার ডিএ্যাপ-এর সাথে সংযুক্ত করার জন্য প্রম্পট করা হবে।

  • যদি ব্যবহারকারী সংযুক্ত হওয়া বেছে নেন, তবে method: "eth_requestAccounts" একটি অ্যারে রিটার্ন করবে যাতে ডিএ্যাপ-এর সাথে সংযুক্ত ব্যবহারকারীর সমস্ত একাউন্ট এডড্রেস থাকবে। সব মিলিয়ে, আমাদের connectWallet ফাংশনটি একটি JSON অবজেক্ট রিটার্ন করবে যাতে এই অ্যারের প্রথম address (লাইন 9 দেখুন) এবং একটি status মেসেজ থাকবে যা ব্যবহারকারীকে স্মার্ট কন্ট্রাক্ট-এ একটি মেসেজ লেখার জন্য প্রম্পট করে।
  • যদি ব্যবহারকারী কানেকশনটি প্রত্যাখ্যান করেন, তবে JSON অবজেক্টটিতে রিটার্ন করা address-এর জন্য একটি খালি স্ট্রিং এবং একটি status মেসেজ থাকবে যা প্রতিফলিত করে যে ব্যবহারকারী কানেকশনটি প্রত্যাখ্যান করেছেন।

আপনার Minter.js UI কম্পোনেন্টে connectWallet ফাংশন যোগ করুন

এখন যেহেতু আমরা এই connectWallet ফাংশনটি লিখেছি, চলুন এটিকে আমাদের Minter.js. কম্পোনেন্টের সাথে সংযুক্ত করি।

প্রথমে, আমাদের Minter.js ফাইলের একেবারে ওপরে import { connectWallet } from "./utils/interact.js"; যোগ করে আমাদের ফাংশনটিকে আমাদের Minter.js ফাইলে ইমপোর্ট করতে হবে। আপনার Minter.js-এর প্রথম 11 লাইন এখন এরকম হওয়া উচিত:

1import { useEffect, useState } from "react";
2import { connectWallet } from "./utils/interact.js";
3
4const Minter = (props) => {
5
6 // স্টেট ভেরিয়েবল
7 const [walletAddress, setWallet] = useState("");
8 const [status, setStatus] = useState("");
9 const [name, setName] = useState("");
10 const [description, setDescription] = useState("");
11 const [url, setURL] = useState("");
সব দেখান

তারপর, আমাদের connectWalletPressed ফাংশনের ভেতরে, আমরা আমাদের ইমপোর্ট করা connectWallet ফাংশনটি কল করব, ঠিক এভাবে:

1const connectWalletPressed = async () => {
2 const walletResponse = await connectWallet()
3 setStatus(walletResponse.status)
4 setWallet(walletResponse.address)
5}

লক্ষ্য করেছেন কীভাবে আমাদের বেশিরভাগ কার্যকারিতা interact.js ফাইল থেকে আমাদের Minter.js কম্পোনেন্ট থেকে অ্যাবস্ট্রাক্ট করা হয়েছে? এটি করা হয়েছে যাতে আমরা M-V-C প্যারাডাইম মেনে চলি!

connectWalletPressed-এ, আমরা কেবল আমাদের ইমপোর্ট করা connectWallet ফাংশনে একটি await কল করি এবং এর রেসপন্স ব্যবহার করে, আমরা তাদের স্টেট হুকগুলোর মাধ্যমে আমাদের status এবং walletAddress ভেরিয়েবলগুলো আপডেট করি।

এখন, চলুন Minter.js এবং interact.js উভয় ফাইল সেভ করি এবং এ পর্যন্ত আমাদের UI টেস্ট করে দেখি।

localhost:3000-এ আপনার ব্রাউজার খুলুন এবং পেজের ওপরের ডানদিকে "Connect Wallet" বোতাম টিপুন।

আপনার যদি MetaMask ইনস্টল করা থাকে, তবে আপনাকে আপনার ওয়ালেটকে আপনার ডিএ্যাপ-এর সাথে সংযুক্ত করার জন্য প্রম্পট করা হবে। সংযুক্ত হওয়ার আমন্ত্রণটি গ্রহণ করুন।

আপনার দেখা উচিত যে ওয়ালেট বোতামটি এখন প্রতিফলিত করছে যে আপনার এডড্রেস সংযুক্ত আছে।

এরপর, পেজটি রিফ্রেশ করার চেষ্টা করুন... এটি অদ্ভুত। আমাদের ওয়ালেট বোতামটি আমাদের MetaMask সংযুক্ত করার জন্য প্রম্পট করছে, যদিও এটি ইতিমধ্যে সংযুক্ত আছে...

তবে চিন্তা করবেন না! আমরা getCurrentWalletConnected নামের একটি ফাংশন ইমপ্লিমেন্ট করার মাধ্যমে সহজেই এটি ঠিক করতে পারি, যা চেক করবে যে কোনো এডড্রেস ইতিমধ্যে আমাদের ডিএ্যাপ-এর সাথে সংযুক্ত আছে কি না এবং সেই অনুযায়ী আমাদের UI আপডেট করবে!

getCurrentWalletConnected ফাংশন

আপনার interact.js ফাইলে, নিচের getCurrentWalletConnected ফাংশনটি যোগ করুন:

1export const getCurrentWalletConnected = async () => {
2 if (window.ethereum) {
3 try {
4 const addressArray = await window.ethereum.request({
5 method: "eth_accounts",
6 })
7 if (addressArray.length > 0) {
8 return {
9 address: addressArray[0],
10 status: "👆🏽 Write a message in the text-field above.",
11 }
12 } else {
13 return {
14 address: "",
15 status: "🦊 Connect to MetaMask using the top right button.",
16 }
17 }
18 } catch (err) {
19 return {
20 address: "",
21 status: "😥 " + err.message,
22 }
23 }
24 } else {
25 return {
26 address: "",
27 status: (
28 <span>
29 <p>
30 {" "}
31 🦊 <a target="_blank" href={`https://metamask.io/download`}>
32 You must install MetaMask, a virtual Ethereum wallet, in your
33 browser.
34 </a>
35 </p>
36 </span>
37 ),
38 }
39 }
40}
সব দেখান

এই কোডটি আমরা একটু আগে লেখা connectWallet ফাংশনের খুবই কাছাকাছি।

প্রধান পার্থক্য হলো eth_requestAccounts মেথড কল করার পরিবর্তে, যা ব্যবহারকারীর ওয়ালেট সংযুক্ত করার জন্য MetaMask খোলে, এখানে আমরা eth_accounts মেথড কল করি, যা কেবল বর্তমানে আমাদের ডিএ্যাপ-এর সাথে সংযুক্ত MetaMask এডড্রেসগুলো ধারণকারী একটি অ্যারে রিটার্ন করে।

এই ফাংশনটি কীভাবে কাজ করে তা দেখতে, চলুন এটিকে আমাদের Minter.js কম্পোনেন্টের useEffect ফাংশনে কল করি।

আমরা connectWallet-এর জন্য যেমনটি করেছিলাম, আমাদের অবশ্যই এই ফাংশনটিকে আমাদের interact.js ফাইল থেকে আমাদের Minter.js ফাইলে ইমপোর্ট করতে হবে, ঠিক এভাবে:

1import { useEffect, useState } from "react"
2import {
3 connectWallet,
4 getCurrentWalletConnected, // এখানে ইমপোর্ট করুন
5} from "./utils/interact.js"

এখন, আমরা কেবল এটিকে আমাদের useEffect ফাংশনে কল করব:

1useEffect(async () => {
2 const { address, status } = await getCurrentWalletConnected()
3 setWallet(address)
4 setStatus(status)
5}, [])

লক্ষ্য করুন, আমরা আমাদের walletAddress এবং status স্টেট ভেরিয়েবলগুলো আপডেট করতে getCurrentWalletConnected-এ আমাদের কলের রেসপন্স ব্যবহার করি।

একবার আপনি এই কোডটি যোগ করার পর, আমাদের ব্রাউজার উইন্ডোটি রিফ্রেশ করার চেষ্টা করুন। বোতামটিতে বলা উচিত যে আপনি সংযুক্ত আছেন এবং আপনার সংযুক্ত ওয়ালেটের এডড্রেস-এর একটি প্রিভিউ দেখানো উচিত - এমনকি আপনি রিফ্রেশ করার পরেও!

addWalletListener ইমপ্লিমেন্ট করুন

আমাদের ডিএ্যাপ ওয়ালেট সেটআপের চূড়ান্ত ধাপ হলো ওয়ালেট লিসেনার ইমপ্লিমেন্ট করা যাতে আমাদের ওয়ালেটের স্টেট পরিবর্তিত হলে আমাদের UI আপডেট হয়, যেমন যখন ব্যবহারকারী ডিসকানেক্ট করে বা একাউন্ট স্যুইচ করে।

আপনার Minter.js ফাইলে, addWalletListener নামের একটি ফাংশন যোগ করুন যা দেখতে নিচের মতো:

1function addWalletListener() {
2 if (window.ethereum) {
3 window.ethereum.on("accountsChanged", (accounts) => {
4 if (accounts.length > 0) {
5 setWallet(accounts[0])
6 setStatus("👆🏽 Write a message in the text-field above.")
7 } else {
8 setWallet("")
9 setStatus("🦊 Connect to MetaMask using the top right button.")
10 }
11 })
12 } else {
13 setStatus(
14 <p>
15 {" "}
16 🦊 <a target="_blank" href={`https://metamask.io/download`}>
17 You must install MetaMask, a virtual Ethereum wallet, in your browser.
18 </a>
19 </p>
20 )
21 }
22}
সব দেখান

চলুন দ্রুত বিশ্লেষণ করি এখানে কী ঘটছে:

  • প্রথমে, আমাদের ফাংশনটি চেক করে যে window.ethereum এনাবল করা আছে কি না (অর্থাৎ, MetaMask ইনস্টল করা আছে কি না)।
    • যদি না থাকে, তবে আমরা কেবল আমাদের status স্টেট ভেরিয়েবলটিকে একটি JSX স্ট্রিংয়ে সেট করি যা ব্যবহারকারীকে MetaMask ইনস্টল করার জন্য প্রম্পট করে।
    • যদি এটি এনাবল করা থাকে, তবে আমরা 3 নম্বর লাইনে লিসেনার window.ethereum.on("accountsChanged") সেট আপ করি যা MetaMask ওয়ালেটে স্টেট পরিবর্তনের জন্য অপেক্ষা করে, যার মধ্যে রয়েছে যখন ব্যবহারকারী ডিএ্যাপ-এ একটি অতিরিক্ত একাউন্ট সংযুক্ত করে, একাউন্ট স্যুইচ করে বা কোনো একাউন্ট ডিসকানেক্ট করে। যদি অন্তত একটি একাউন্ট সংযুক্ত থাকে, তবে walletAddress স্টেট ভেরিয়েবলটি লিসেনার দ্বারা রিটার্ন করা accounts অ্যারের প্রথম একাউন্ট হিসেবে আপডেট করা হয়। অন্যথায়, walletAddress একটি খালি স্ট্রিং হিসেবে সেট করা হয়।

অবশেষে, আমাদের অবশ্যই এটিকে আমাদের useEffect ফাংশনে কল করতে হবে:

1useEffect(async () => {
2 const { address, status } = await getCurrentWalletConnected()
3 setWallet(address)
4 setStatus(status)
5
6 addWalletListener()
7}, [])

এবং ব্যাস! আমরা আমাদের সমস্ত ওয়ালেট কার্যকারিতা প্রোগ্রামিং সম্পন্ন করেছি! এখন যেহেতু আমাদের ওয়ালেট সেট আপ করা হয়েছে, চলুন বের করি কীভাবে আমাদের NFT মিন্ট করতে হয়!

NFT মেটাডাটা 101

সুতরাং এই টিউটোরিয়ালের 0 ধাপে আমরা যে NFT মেটাডাটা নিয়ে কথা বলেছিলাম তা মনে করুন—এটি একটি NFT-কে জীবন্ত করে তোলে, যার ফলে এর ডিজিটাল অ্যাসেট, নাম, বিবরণ এবং অন্যান্য বৈশিষ্ট্যের মতো প্রপার্টি থাকতে পারে।

আমাদের এই মেটাডাটাকে একটি JSON অবজেক্ট হিসেবে কনফিগার করতে হবে এবং এটি স্টোর করতে হবে, যাতে আমরা আমাদের স্মার্ট কন্ট্রাক্ট-এর mintNFT ফাংশন কল করার সময় এটিকে tokenURI প্যারামিটার হিসেবে পাস করতে পারি।

"Link to Asset", "Name", "Description" ফিল্ডের টেক্সটগুলো আমাদের NFT-এর মেটাডাটার বিভিন্ন প্রপার্টি গঠন করবে। আমরা এই মেটাডাটাকে একটি JSON অবজেক্ট হিসেবে ফরম্যাট করব, তবে আমরা এই JSON অবজেক্টটি কোথায় স্টোর করতে পারি তার জন্য কয়েকটি অপশন রয়েছে:

  • আমরা এটি ইথিরিয়াম ব্লকচেইন-এ স্টোর করতে পারি; তবে, এটি করা খুব ব্যয়বহুল হবে।
  • আমরা এটি AWS বা Firebase-এর মতো একটি সেন্ট্রালাইজড সার্ভারে স্টোর করতে পারি। কিন্তু এটি আমাদের ডিসেন্ট্রালাইজড নীতিকে ব্যাহত করবে।
  • আমরা IPFS ব্যবহার করতে পারি, যা একটি ডিস্ট্রিবিউটেড ফাইল সিস্টেমে ডাটা স্টোর এবং শেয়ার করার জন্য একটি ডিসেন্ট্রালাইজড প্রটোকল এবং পিয়ার-টু-পিয়ার নেটওয়ার্ক। যেহেতু এই প্রটোকলটি ডিসেন্ট্রালাইজড এবং ফ্রি, তাই এটি আমাদের সেরা অপশন!

IPFS-এ আমাদের মেটাডাটা স্টোর করতে, আমরা Pinata (opens in a new tab) ব্যবহার করব, যা একটি সুবিধাজনক IPFS API এবং টুলকিট। পরবর্তী ধাপে, আমরা ঠিক কীভাবে এটি করতে হয় তা ব্যাখ্যা করব!

IPFS-এ আপনার মেটাডাটা পিন করতে Pinata ব্যবহার করুন

আপনার যদি Pinata (opens in a new tab) একাউন্ট না থাকে, তবে এখানে (opens in a new tab) একটি ফ্রি একাউন্টের জন্য সাইন আপ করুন এবং আপনার ইমেইল ও একাউন্ট ভেরিফাই করার ধাপগুলো সম্পন্ন করুন।

আপনার Pinata API কি তৈরি করুন

https://pinata.cloud/keys (opens in a new tab) পেজে নেভিগেট করুন, তারপর ওপরের "New Key" বোতামটি নির্বাচন করুন, Admin উইজেটটি এনাবল হিসেবে সেট করুন এবং আপনার কি-এর নাম দিন।

এরপর আপনাকে আপনার API তথ্যসহ একটি পপআপ দেখানো হবে। এটি কোনো নিরাপদ জায়গায় রাখতে ভুলবেন না।

এখন যেহেতু আমাদের কি সেট আপ করা হয়েছে, চলুন এটিকে আমাদের প্রজেক্টে যোগ করি যাতে আমরা এটি ব্যবহার করতে পারি।

একটি .env ফাইল তৈরি করুন

আমরা একটি এনভায়রনমেন্ট ফাইলে আমাদের Pinata কি এবং সিক্রেট নিরাপদে স্টোর করতে পারি। চলুন আপনার প্রজেক্ট ডিরেক্টরিতে dotenv প্যাকেজ (opens in a new tab) ইনস্টল করি।

আপনার টার্মিনালে একটি নতুন ট্যাব খুলুন (লোকাল হোস্ট রান করা ট্যাবটি থেকে আলাদা) এবং নিশ্চিত করুন যে আপনি minter-starter-files ফোল্ডারে আছেন, তারপর আপনার টার্মিনালে নিচের কমান্ডটি রান করুন:

1npm install dotenv --save

এরপর, আপনার কমান্ড লাইনে নিচের কোডটি এন্টার করে আপনার minter-starter-files-এর রুট ডিরেক্টরিতে একটি .env ফাইল তৈরি করুন:

1vim.env

এটি vim (একটি টেক্সট এডিটর)-এ আপনার .env ফাইলটি পপ ওপেন করবে। এটি সেভ করতে আপনার কীবোর্ডে ক্রমানুসারে "esc" + ":" + "q" চাপুন।

এরপর, VSCode-এ, আপনার .env ফাইলে নেভিগেট করুন এবং এতে আপনার Pinata API কি এবং API সিক্রেট যোগ করুন, ঠিক এভাবে:

1REACT_APP_PINATA_KEY = <pinata-api-key>
2REACT_APP_PINATA_SECRET = <pinata-api-secret>

ফাইলটি সেভ করুন, এবং তারপর আপনি IPFS-এ আপনার JSON মেটাডাটা আপলোড করার জন্য ফাংশন লেখা শুরু করতে প্রস্তুত!

pinJSONToIPFS ইমপ্লিমেন্ট করুন

আমাদের জন্য সৌভাগ্যের বিষয় হলো, Pinata-এর কাছে IPFS-এ JSON ডাটা আপলোড করার জন্য বিশেষভাবে একটি API (opens in a new tab) এবং axios-সহ একটি সুবিধাজনক জাভাস্ক্রিপ্ট উদাহরণ রয়েছে যা আমরা সামান্য কিছু পরিবর্তন করে ব্যবহার করতে পারি।

আপনার utils ফোল্ডারে, চলুন pinata.js নামে আরেকটি ফাইল তৈরি করি এবং তারপর .env ফাইল থেকে আমাদের Pinata সিক্রেট এবং কি ইমপোর্ট করি, ঠিক এভাবে:

1require("dotenv").config()
2const key = process.env.REACT_APP_PINATA_KEY
3const secret = process.env.REACT_APP_PINATA_SECRET

এরপর, নিচের অতিরিক্ত কোডটি আপনার pinata.js ফাইলে পেস্ট করুন। চিন্তা করবেন না, আমরা সবকিছুর অর্থ বিশ্লেষণ করব!

1require("dotenv").config()
2const key = process.env.REACT_APP_PINATA_KEY
3const secret = process.env.REACT_APP_PINATA_SECRET
4
5const axios = require("axios")
6
7export const pinJSONToIPFS = async (JSONBody) => {
8 const url = `https://api.pinata.cloud/pinning/pinJSONToIPFS`
9 // Pinata-তে axios POST রিকোয়েস্ট করা হচ্ছে ⬇️
10 return axios
11 .post(url, JSONBody, {
12 headers: {
13 pinata_api_key: key,
14 pinata_secret_api_key: secret,
15 },
16 })
17 .then(function (response) {
18 return {
19 success: true,
20 pinataUrl:
21 "https://gateway.pinata.cloud/ipfs/" + response.data.IpfsHash,
22 }
23 })
24 .catch(function (error) {
25 console.log(error)
26 return {
27 success: false,
28 message: error.message,
29 }
30 })
31}
সব দেখান

তাহলে এই কোডটি ঠিক কী করে?

প্রথমে, এটি axios (opens in a new tab) ইমপোর্ট করে, যা ব্রাউজার এবং node.js-এর জন্য একটি প্রমিস-ভিত্তিক HTTP ক্লায়েন্ট, যা আমরা Pinata-তে একটি রিকোয়েস্ট করতে ব্যবহার করব।

তারপর আমাদের অ্যাসিনক্রোনাস ফাংশন pinJSONToIPFS রয়েছে, যা ইনপুট হিসেবে একটি JSONBody এবং এর হেডারে Pinata api কি এবং সিক্রেট নেয়, এই সবকিছু তাদের pinJSONToIPFS API-তে একটি POST রিকোয়েস্ট করার জন্য।

  • যদি এই POST রিকোয়েস্টটি সফল হয়, তবে আমাদের ফাংশনটি success বুলিয়ান true হিসেবে এবং pinataUrl যেখানে আমাদের মেটাডাটা পিন করা হয়েছিল তা সহ একটি JSON অবজেক্ট রিটার্ন করে। আমরা রিটার্ন করা এই pinataUrl-কে আমাদের স্মার্ট কন্ট্রাক্ট-এর মিন্ট ফাংশনে tokenURI ইনপুট হিসেবে ব্যবহার করব।
  • যদি এই পোস্ট রিকোয়েস্টটি ব্যর্থ হয়, তবে আমাদের ফাংশনটি success বুলিয়ান false হিসেবে এবং একটি message স্ট্রিং সহ একটি JSON অবজেক্ট রিটার্ন করে যা আমাদের এরর জানায়।

আমাদের connectWallet ফাংশনের রিটার্ন টাইপের মতো, আমরা JSON অবজেক্ট রিটার্ন করছি যাতে আমরা আমাদের স্টেট ভেরিয়েবল এবং UI আপডেট করতে তাদের প্যারামিটারগুলো ব্যবহার করতে পারি।

আপনার স্মার্ট কন্ট্রাক্ট লোড করুন

এখন যেহেতু আমাদের pinJSONToIPFS ফাংশনের মাধ্যমে IPFS-এ আমাদের NFT মেটাডাটা আপলোড করার একটি উপায় আছে, তাই আমাদের স্মার্ট কন্ট্রাক্ট-এর একটি ইনস্ট্যান্স লোড করার একটি উপায় প্রয়োজন হবে যাতে আমরা এর mintNFT ফাংশন কল করতে পারি।

যেমনটি আমরা আগে উল্লেখ করেছি, এই টিউটোরিয়ালে আমরা এই বিদ্যমান NFT স্মার্ট কন্ট্রাক্টটি (opens in a new tab) ব্যবহার করব; তবে, আপনি যদি জানতে চান আমরা এটি কীভাবে তৈরি করেছি, বা নিজে একটি তৈরি করতে চান, তবে আমরা জোরালোভাবে সুপারিশ করছি যে আপনি আমাদের অন্য টিউটোরিয়াল, "How to Create an NFT." (opens in a new tab) দেখে নিন।

কন্ট্রাক্ট ABI

আপনি যদি আমাদের ফাইলগুলো মনোযোগ সহকারে পরীক্ষা করে থাকেন, তবে আপনি লক্ষ্য করবেন যে আমাদের src ডিরেক্টরিতে একটি contract-abi.json ফাইল রয়েছে। একটি কন্ট্রাক্ট কোন ফাংশনটি ইনভোক করবে তা নির্দিষ্ট করার পাশাপাশি ফাংশনটি আপনার প্রত্যাশিত ফরম্যাটে ডাটা রিটার্ন করবে তা নিশ্চিত করার জন্য একটি ABI প্রয়োজনীয়।

ইথিরিয়াম ব্লকচেইন-এর সাথে সংযুক্ত হতে এবং আমাদের স্মার্ট কন্ট্রাক্ট লোড করতে আমাদের একটি Alchemy API কি এবং Alchemy Web3 API-এরও প্রয়োজন হবে।

আপনার Alchemy API কি তৈরি করুন

আপনার যদি ইতিমধ্যে একটি Alchemy একাউন্ট না থাকে, তবে এখানে বিনামূল্যে সাইন আপ করুন। (opens in a new tab)

একবার আপনি একটি Alchemy একাউন্ট তৈরি করার পর, আপনি একটি অ্যাপ তৈরি করে একটি API কি জেনারেট করতে পারেন। এটি আমাদের Ropsten টেস্টনেট-এ রিকোয়েস্ট করার অনুমতি দেবে।

ন্যাভ বারে “Apps”-এর ওপর হোভার করে এবং “Create App”-এ ক্লিক করে আপনার Alchemy ড্যাশবোর্ডে “Create App” পেজে নেভিগেট করুন।

আপনার অ্যাপের নাম দিন, আমরা "My First NFT!" বেছে নিয়েছি, একটি সংক্ষিপ্ত বিবরণ দিন, আপনার অ্যাপ বুককিপিংয়ের জন্য ব্যবহৃত এনভায়রনমেন্টের জন্য “Staging” নির্বাচন করুন এবং আপনার নেটওয়ার্ক-এর জন্য “Ropsten” বেছে নিন।

“Create app”-এ ক্লিক করুন এবং ব্যাস! আপনার অ্যাপটি নিচের টেবিলে উপস্থিত হওয়া উচিত।

চমৎকার, এখন যেহেতু আমরা আমাদের HTTP Alchemy API URL তৈরি করেছি, এটি আপনার ক্লিপবোর্ডে কপি করুন...

…এবং তারপর চলুন এটিকে আমাদের .env ফাইলে যোগ করি। সব মিলিয়ে, আপনার .env ফাইলটি এরকম হওয়া উচিত:

1REACT_APP_PINATA_KEY = <pinata-key>
2REACT_APP_PINATA_SECRET = <pinata-secret>
3REACT_APP_ALCHEMY_KEY = https: // eth-ropsten.alchemyapi.io/v2/<alchemy-key>

এখন যেহেতু আমাদের কাছে আমাদের কন্ট্রাক্ট ABI এবং আমাদের Alchemy API কি রয়েছে, আমরা Alchemy Web3 (opens in a new tab) ব্যবহার করে আমাদের স্মার্ট কন্ট্রাক্ট লোড করতে প্রস্তুত।

আপনার Alchemy Web3 এন্ডপয়েন্ট এবং কন্ট্রাক্ট সেট আপ করুন

প্রথমে, যদি আপনার কাছে এটি ইতিমধ্যে না থাকে, তবে আপনাকে টার্মিনালে হোম ডিরেক্টরি: nft-minter-tutorial-এ নেভিগেট করে Alchemy Web3 (opens in a new tab) ইনস্টল করতে হবে:

1cd ..
2npm install @alch/alchemy-web3

এরপর চলুন আমাদের interact.js ফাইলে ফিরে যাই। ফাইলের একেবারে ওপরে, আপনার .env ফাইল থেকে আপনার Alchemy কি ইমপোর্ট করতে এবং আপনার Alchemy Web3 এন্ডপয়েন্ট সেট আপ করতে নিচের কোডটি যোগ করুন:

1require("dotenv").config()
2const alchemyKey = process.env.REACT_APP_ALCHEMY_KEY
3const { createAlchemyWeb3 } = require("@alch/alchemy-web3")
4const web3 = createAlchemyWeb3(alchemyKey)

Alchemy Web3 (opens in a new tab) হলো Web3.js (opens in a new tab)-এর চারপাশে একটি র‍্যাপার, যা একজন ওয়েব3 (web3) ডেভেলপার হিসেবে আপনার জীবনকে সহজ করতে উন্নত API মেথড এবং অন্যান্য গুরুত্বপূর্ণ সুবিধা প্রদান করে। এটি এমনভাবে ডিজাইন করা হয়েছে যাতে ন্যূনতম কনফিগারেশনের প্রয়োজন হয়, ফলে আপনি এখনই আপনার অ্যাপে এটি ব্যবহার করা শুরু করতে পারেন!

এরপর, চলুন আমাদের ফাইলে আমাদের কন্ট্রাক্ট ABI এবং কন্ট্রাক্ট এডড্রেস যোগ করি।

1require("dotenv").config()
2const alchemyKey = process.env.REACT_APP_ALCHEMY_KEY
3const { createAlchemyWeb3 } = require("@alch/alchemy-web3")
4const web3 = createAlchemyWeb3(alchemyKey)
5
6const contractABI = require("../contract-abi.json")
7const contractAddress = "0x4C4a07F737Bf57F6632B6CAB089B78f62385aCaE"

একবার আমাদের কাছে এই দুটি জিনিস চলে এলে, আমরা আমাদের মিন্ট ফাংশন কোডিং শুরু করতে প্রস্তুত!

mintNFT ফাংশন ইমপ্লিমেন্ট করুন

আপনার interact.js ফাইলের ভেতরে, চলুন আমাদের ফাংশন, mintNFT ডিফাইন করি, যা নাম অনুযায়ী আমাদের NFT মিন্ট করবে।

যেহেতু আমরা অসংখ্য অ্যাসিনক্রোনাস কল করব (IPFS-এ আমাদের মেটাডাটা পিন করতে Pinata-তে, আমাদের স্মার্ট কন্ট্রাক্ট লোড করতে Alchemy Web3-তে এবং আমাদের লেনদেন সাইন করতে MetaMask-এ), তাই আমাদের ফাংশনটিও অ্যাসিনক্রোনাস হবে।

আমাদের ফাংশনের তিনটি ইনপুট হবে আমাদের ডিজিটাল অ্যাসেটের url, name, এবং descriptionconnectWallet ফাংশনের নিচে নিচের ফাংশন সিগনেচারটি যোগ করুন:

1export const mintNFT = async (url, name, description) => {}

ইনপুট এরর হ্যান্ডলিং

স্বাভাবিকভাবেই, ফাংশনের শুরুতে কোনো ধরনের ইনপুট এরর হ্যান্ডলিং থাকাটা যৌক্তিক, যাতে আমাদের ইনপুট প্যারামিটারগুলো সঠিক না হলে আমরা এই ফাংশন থেকে বেরিয়ে আসতে পারি। আমাদের ফাংশনের ভেতরে, চলুন নিচের কোডটি যোগ করি:

1export const mintNFT = async (url, name, description) => {
2 // এরর হ্যান্ডলিং
3 if (url.trim() == "" || name.trim() == "" || description.trim() == "") {
4 return {
5 success: false,
6 status: "❗Please make sure all fields are completed before minting.",
7 }
8 }
9}
সব দেখান

মূলত, যদি ইনপুট প্যারামিটারগুলোর কোনোটি একটি খালি স্ট্রিং হয়, তবে আমরা একটি JSON অবজেক্ট রিটার্ন করি যেখানে success বুলিয়ান false হয় এবং status স্ট্রিংটি জানায় যে আমাদের UI-এর সমস্ত ফিল্ড অবশ্যই সম্পূর্ণ হতে হবে।

IPFS-এ মেটাডাটা আপলোড করুন

একবার আমরা জেনে গেলে যে আমাদের মেটাডাটা সঠিকভাবে ফরম্যাট করা হয়েছে, পরবর্তী ধাপ হলো এটিকে একটি JSON অবজেক্টে র‍্যাপ করা এবং আমাদের লেখা pinJSONToIPFS-এর মাধ্যমে IPFS-এ আপলোড করা!

এটি করার জন্য, প্রথমে আমাদের interact.js ফাইলে pinJSONToIPFS ফাংশনটি ইমপোর্ট করতে হবে। interact.js-এর একেবারে ওপরে, চলুন যোগ করি:

1import { pinJSONToIPFS } from "./pinata.js"

মনে রাখবেন যে pinJSONToIPFS একটি JSON বডি নেয়। তাই এটিতে কল করার আগে, আমাদের url, name, এবং description প্যারামিটারগুলোকে একটি JSON অবজেক্টে ফরম্যাট করতে হবে।

চলুন metadata নামের একটি JSON অবজেক্ট তৈরি করতে আমাদের কোড আপডেট করি এবং তারপর এই metadata প্যারামিটার দিয়ে pinJSONToIPFS-এ একটি কল করি:

1export const mintNFT = async (url, name, description) => {
2 // এরর হ্যান্ডলিং
3 if (url.trim() == "" || name.trim() == "" || description.trim() == "") {
4 return {
5 success: false,
6 status: "❗Please make sure all fields are completed before minting.",
7 }
8 }
9
10 // মেটাডেটা তৈরি করুন
11 const metadata = new Object()
12 metadata.name = name
13 metadata.image = url
14 metadata.description = description
15
16 // pinata কল করুন
17 const pinataResponse = await pinJSONToIPFS(metadata)
18 if (!pinataResponse.success) {
19 return {
20 success: false,
21 status: "😢 Something went wrong while uploading your tokenURI.",
22 }
23 }
24 const tokenURI = pinataResponse.pinataUrl
25}
সব দেখান

লক্ষ্য করুন, আমরা pinJSONToIPFS(metadata)-এ আমাদের কলের রেসপন্স pinataResponse অবজেক্টে স্টোর করি। তারপর, আমরা কোনো এররের জন্য এই অবজেক্টটি পার্স করি।

যদি কোনো এরর থাকে, তবে আমরা একটি JSON অবজেক্ট রিটার্ন করি যেখানে success বুলিয়ান false হয় এবং আমাদের status স্ট্রিংটি জানায় যে আমাদের কল ব্যর্থ হয়েছে। অন্যথায়, আমরা pinataResponse থেকে pinataURL এক্সট্র্যাক্ট করি এবং এটিকে আমাদের tokenURI ভেরিয়েবল হিসেবে স্টোর করি।

এখন আমাদের ফাইলের ওপরে ইনিশিয়ালাইজ করা Alchemy Web3 API ব্যবহার করে আমাদের স্মার্ট কন্ট্রাক্ট লোড করার সময় এসেছে। window.contract গ্লোবাল ভেরিয়েবলে কন্ট্রাক্ট সেট করতে mintNFT ফাংশনের নিচে কোডের নিচের লাইনটি যোগ করুন:

1window.contract = await new web3.eth.Contract(contractABI, contractAddress)

আমাদের mintNFT ফাংশনে যোগ করার শেষ জিনিসটি হলো আমাদের ইথিরিয়াম লেনদেন:

1// আপনার ইথিরিয়াম ট্রানজ্যাকশন সেট আপ করুন
2const transactionParameters = {
3 to: contractAddress, // কন্ট্রাক্ট পাবলিকেশন ছাড়া অন্যান্য ক্ষেত্রে প্রয়োজনীয়।
4 from: window.ethereum.selectedAddress, // অবশ্যই ব্যবহারকারীর সক্রিয় ঠিকানার সাথে মিলতে হবে।
5 data: window.contract.methods
6 .mintNFT(window.ethereum.selectedAddress, tokenURI)
7 .encodeABI(), // NFT স্মার্ট কন্ট্রাক্টে কল করুন
8}
9
10// MetaMask-এর মাধ্যমে ট্রানজ্যাকশন সাইন করুন
11try {
12 const txHash = await window.ethereum.request({
13 method: "eth_sendTransaction",
14 params: [transactionParameters],
15 })
16 return {
17 success: true,
18 status:
19 "✅ Check out your transaction on Etherscan: https://ropsten.etherscan.io/tx/" +
20 txHash,
21 }
22} catch (error) {
23 return {
24 success: false,
25 status: "😥 Something went wrong: " + error.message,
26 }
27}
সব দেখান

আপনি যদি ইতিমধ্যে ইথিরিয়াম লেনদেন-এর সাথে পরিচিত হন, তবে আপনি লক্ষ্য করবেন যে এর স্ট্রাকচারটি আপনি যা দেখেছেন তার মতোই।

  • প্রথমে, আমরা আমাদের লেনদেন প্যারামিটারগুলো সেট আপ করি।
    • to প্রাপকের এডড্রেস নির্দিষ্ট করে (আমাদের স্মার্ট কন্ট্রাক্ট)
    • from লেনদেন-এর সাইনার নির্দিষ্ট করে (MetaMask-এ ব্যবহারকারীর সংযুক্ত এডড্রেস: window.ethereum.selectedAddress)
    • data-তে আমাদের স্মার্ট কন্ট্রাক্ট mintNFT মেথডের কল থাকে, যা ইনপুট হিসেবে আমাদের tokenURI এবং ব্যবহারকারীর ওয়ালেট এডড্রেস, window.ethereum.selectedAddress গ্রহণ করে
  • তারপর, আমরা একটি await কল করি, window.ethereum.request, যেখানে আমরা MetaMask-কে লেনদেন সাইন করতে বলি। লক্ষ্য করুন, এই রিকোয়েস্টে, আমরা আমাদের eth মেথড (eth_SentTransaction) নির্দিষ্ট করছি এবং আমাদের transactionParameters পাস করছি। এই পর্যায়ে, ব্রাউজারে MetaMask খুলবে এবং ব্যবহারকারীকে লেনদেন সাইন বা প্রত্যাখ্যান করার জন্য প্রম্পট করবে।
    • যদি লেনদেন সফল হয়, তবে ফাংশনটি একটি JSON অবজেক্ট রিটার্ন করবে যেখানে বুলিয়ান success true হিসেবে সেট করা থাকে এবং status স্ট্রিংটি ব্যবহারকারীকে তাদের লেনদেন সম্পর্কে আরও তথ্যের জন্য Etherscan চেক করার জন্য প্রম্পট করে।
    • যদি লেনদেন ব্যর্থ হয়, তবে ফাংশনটি একটি JSON অবজেক্ট রিটার্ন করবে যেখানে success বুলিয়ান false হিসেবে সেট করা থাকে এবং status স্ট্রিংটি এরর মেসেজ জানায়।

সব মিলিয়ে, আমাদের mintNFT ফাংশনটি এরকম হওয়া উচিত:

1export const mintNFT = async (url, name, description) => {
2 // এরর হ্যান্ডলিং
3 if (url.trim() == "" || name.trim() == "" || description.trim() == "") {
4 return {
5 success: false,
6 status: "❗Please make sure all fields are completed before minting.",
7 }
8 }
9
10 // মেটাডেটা তৈরি করুন
11 const metadata = new Object()
12 metadata.name = name
13 metadata.image = url
14 metadata.description = description
15
16 // pinata পিন রিকোয়েস্ট
17 const pinataResponse = await pinJSONToIPFS(metadata)
18 if (!pinataResponse.success) {
19 return {
20 success: false,
21 status: "😢 Something went wrong while uploading your tokenURI.",
22 }
23 }
24 const tokenURI = pinataResponse.pinataUrl
25
26 // স্মার্ট কন্ট্রাক্ট লোড করুন
27 window.contract = await new web3.eth.Contract(contractABI, contractAddress) // loadContract();
28
29 // আপনার ইথিরিয়াম ট্রানজ্যাকশন সেট আপ করুন
30 const transactionParameters = {
31 to: contractAddress, // কন্ট্রাক্ট পাবলিকেশন ছাড়া অন্যান্য ক্ষেত্রে প্রয়োজনীয়।
32 from: window.ethereum.selectedAddress, // অবশ্যই ব্যবহারকারীর সক্রিয় ঠিকানার সাথে মিলতে হবে।
33 data: window.contract.methods
34 .mintNFT(window.ethereum.selectedAddress, tokenURI)
35 .encodeABI(), // NFT স্মার্ট কন্ট্রাক্টে কল করুন
36 }
37
38 // MetaMask-এর মাধ্যমে ট্রানজ্যাকশন সাইন করুন
39 try {
40 const txHash = await window.ethereum.request({
41 method: "eth_sendTransaction",
42 params: [transactionParameters],
43 })
44 return {
45 success: true,
46 status:
47 "✅ Check out your transaction on Etherscan: https://ropsten.etherscan.io/tx/" +
48 txHash,
49 }
50 } catch (error) {
51 return {
52 success: false,
53 status: "😥 Something went wrong: " + error.message,
54 }
55 }
56}
সব দেখান

এটি একটি বিশাল ফাংশন! এখন, আমাদের কেবল আমাদের mintNFT ফাংশনটিকে আমাদের Minter.js কম্পোনেন্টের সাথে সংযুক্ত করতে হবে...

আমাদের Minter.js ফ্রন্টএন্ডের সাথে mintNFT সংযুক্ত করুন

আপনার Minter.js ফাইলটি খুলুন এবং ওপরের import { connectWallet, getCurrentWalletConnected } from "./utils/interact.js"; লাইনটি আপডেট করে নিচের মতো করুন:

1import {
2 connectWallet,
3 getCurrentWalletConnected,
4 mintNFT,
5} from "./utils/interact.js"

অবশেষে, আপনার ইমপোর্ট করা mintNFT ফাংশনে await কল করতে onMintPressed ফাংশনটি ইমপ্লিমেন্ট করুন এবং আমাদের লেনদেন সফল হয়েছে নাকি ব্যর্থ হয়েছে তা প্রতিফলিত করতে status স্টেট ভেরিয়েবলটি আপডেট করুন:

1const onMintPressed = async () => {
2 const { status } = await mintNFT(url, name, description)
3 setStatus(status)
4}

একটি লাইভ ওয়েবসাইটে আপনার NFT ডিপ্লয় করুন

ব্যবহারকারীদের ইন্টারঅ্যাক্ট করার জন্য আপনার প্রজেক্ট লাইভ করতে প্রস্তুত? একটি লাইভ ওয়েবসাইটে আপনার মিন্টার ডিপ্লয় করার জন্য এই টিউটোরিয়ালটি (opens in a new tab) দেখে নিন।

শেষ একটি ধাপ...

ব্লকচেইন দুনিয়ায় ঝড় তুলুন

মজা করছিলাম, আপনি টিউটোরিয়ালের শেষ প্রান্তে পৌঁছে গেছেন!

সংক্ষেপে বলতে গেলে, একটি NFT মিন্টার তৈরি করার মাধ্যমে, আপনি সফলভাবে শিখেছেন কীভাবে:

  • আপনার ফ্রন্টএন্ড প্রজেক্টের মাধ্যমে MetaMask-এ সংযুক্ত হতে হয়
  • আপনার ফ্রন্টএন্ড থেকে স্মার্ট কন্ট্রাক্ট মেথড কল করতে হয়
  • MetaMask ব্যবহার করে লেনদেন সাইন করতে হয়

সম্ভবত, আপনি আপনার ডিএ্যাপ-এর মাধ্যমে মিন্ট করা NFT-গুলো আপনার ওয়ালেটে দেখাতে চাইবেন — তাই আমাদের দ্রুত টিউটোরিয়াল How to View Your NFT in Your Wallet (opens in a new tab) দেখতে ভুলবেন না!

এবং, বরাবরের মতো, আপনার যদি কোনো প্রশ্ন থাকে, তবে আমরা Alchemy Discord (opens in a new tab)-এ সাহায্য করার জন্য আছি। এই টিউটোরিয়ালের কনসেপ্টগুলো আপনি আপনার ভবিষ্যতের প্রজেক্টগুলোতে কীভাবে প্রয়োগ করেন তা দেখার জন্য আমরা অধীর আগ্রহে অপেক্ষা করছি!

পেজ সর্বশেষ আপডেট: ২৫ ফেব্রুয়ারী, ২০২৬

এই টিউটোরিয়ালটি কি সহায়ক ছিল?