NFT منٹر ٹیوٹوریل
Web2 پس منظر سے آنے والے ڈیولپرز کے لیے سب سے بڑے چیلنجز میں سے ایک یہ جاننا ہے کہ اپنے اسمارٹ کانٹریکٹ کو فرنٹ اینڈ پروجیکٹ سے کیسے جوڑا جائے اور اس کے ساتھ کیسے تعامل (interact) کیا جائے۔
ایک NFT منٹر بنا کر — ایک سادہ UI جہاں آپ اپنے ڈیجیٹل اثاثے کا لنک، ایک عنوان، اور ایک تفصیل درج کر سکتے ہیں — آپ سیکھیں گے کہ:
- اپنے فرنٹ اینڈ پروجیکٹ کے ذریعے MetaMask سے کیسے جڑیں
- اپنے فرنٹ اینڈ سے اسمارٹ کانٹریکٹ کے میتھڈز کو کیسے کال کریں
- MetaMask کا استعمال کرتے ہوئے ٹرانزیکشنز پر کیسے دستخط کریں
اس ٹیوٹوریل میں، ہم React (opens in a new tab) کو اپنے فرنٹ اینڈ فریم ورک کے طور پر استعمال کریں گے۔ چونکہ یہ ٹیوٹوریل بنیادی طور پر Web3 ڈیولپمنٹ پر مرکوز ہے، اس لیے ہم React کی بنیادی باتوں کو سمجھانے میں زیادہ وقت صرف نہیں کریں گے۔ اس کے بجائے، ہم اپنے پروجیکٹ میں فعالیت (functionality) لانے پر توجہ مرکوز کریں گے۔
ایک شرط کے طور پر، آپ کو React کی ابتدائی سطح کی سمجھ ہونی چاہیے—یہ جاننا چاہیے کہ components، props، useState/useEffect، اور بنیادی فنکشن کالنگ کیسے کام کرتی ہے۔ اگر آپ نے پہلے کبھی ان اصطلاحات کے بارے میں نہیں سنا ہے، تو آپ یہ Intro to React tutorial (opens in a new tab) دیکھ سکتے ہیں۔ زیادہ بصری (visual) سیکھنے والوں کے لیے، ہم Net Ninja کی اس بہترین Full Modern React Tutorial (opens in a new tab) ویڈیو سیریز کی انتہائی سفارش کرتے ہیں۔
اور اگر آپ نے پہلے سے ایسا نہیں کیا ہے، تو آپ کو اس ٹیوٹوریل کو مکمل کرنے کے ساتھ ساتھ بلاک چین پر کچھ بھی بنانے کے لیے یقینی طور پر ایک Alchemy اکاؤنٹ کی ضرورت ہوگی۔ ایک مفت اکاؤنٹ کے لیے یہاں (opens in a new tab) سائن اپ کریں۔
مزید تاخیر کے بغیر، آئیے شروع کرتے ہیں!
NFTs بنانا 101
اس سے پہلے کہ ہم کسی کوڈ کو دیکھنا شروع کریں، یہ سمجھنا ضروری ہے کہ NFT بنانا کیسے کام کرتا ہے۔ اس میں دو مراحل شامل ہیں:
Ethereum بلاک چین پر ایک NFT اسمارٹ کانٹریکٹ شائع کریں
دو NFT اسمارٹ کانٹریکٹ معیارات کے درمیان سب سے بڑا فرق یہ ہے کہ ERC-1155 ایک ملٹی ٹوکن معیار ہے اور اس میں بیچ (batch) فعالیت شامل ہے، جبکہ ERC-721 ایک سنگل ٹوکن معیار ہے اور اس لیے ایک وقت میں صرف ایک ٹوکن کی منتقلی کو سپورٹ کرتا ہے۔
منٹنگ فنکشن کو کال کریں
عام طور پر، اس منٹنگ فنکشن کے لیے آپ کو دو متغیرات (variables) کو پیرامیٹرز کے طور پر پاس کرنے کی ضرورت ہوتی ہے، پہلا recipient، جو اس ایڈریس کی وضاحت کرتا ہے جو آپ کا تازہ ترین منٹ کیا گیا NFT وصول کرے گا، اور دوسرا NFT کا tokenURI، ایک اسٹرنگ جو ایک JSON دستاویز کو حل کرتی ہے جو NFT کے میٹا ڈیٹا کو بیان کرتی ہے۔
ایک NFT کا میٹا ڈیٹا واقعی وہ چیز ہے جو اسے زندہ کرتا ہے، جس سے اس میں خصوصیات شامل ہوتی ہیں، جیسے کہ نام، تفصیل، تصویر (یا مختلف ڈیجیٹل اثاثہ)، اور دیگر اوصاف۔ یہاں tokenURI کی ایک مثال (opens in a new tab) ہے، جس میں ایک NFT کا میٹا ڈیٹا شامل ہے۔
اس ٹیوٹوریل میں، ہم حصہ 2 پر توجہ مرکوز کرنے جا رہے ہیں، جو کہ ہمارے React UI کا استعمال کرتے ہوئے ایک موجودہ NFT کے اسمارٹ کانٹریکٹ منٹنگ فنکشن کو کال کرنا ہے۔
یہاں ایک لنک ہے (opens in a new tab) اس ERC-721 NFT اسمارٹ کانٹریکٹ کا جسے ہم اس ٹیوٹوریل میں کال کریں گے۔ اگر آپ یہ سیکھنا چاہتے ہیں کہ ہم نے اسے کیسے بنایا، تو ہم انتہائی سفارش کرتے ہیں کہ آپ ہمارا دوسرا ٹیوٹوریل، "How to Create an NFT" (opens in a new tab) دیکھیں۔
زبردست، اب جب کہ ہم سمجھ گئے ہیں کہ NFT بنانا کیسے کام کرتا ہے، آئیے اپنی اسٹارٹر فائلوں کو کلون کریں!
اسٹارٹر فائلوں کو کلون کریں
سب سے پہلے، اس پروجیکٹ کے لیے اسٹارٹر فائلیں حاصل کرنے کے لیے nft-minter-tutorial GitHub repository (opens in a new tab) پر جائیں۔ اس ریپوزٹری کو اپنے مقامی ماحول (local environment) میں کلون کریں۔
جب آپ اس کلون شدہ nft-minter-tutorial ریپوزٹری کو کھولیں گے، تو آپ دیکھیں گے کہ اس میں دو فولڈرز ہیں: minter-starter-files اور nft-minter۔
minter-starter-filesمیں اس پروجیکٹ کے لیے اسٹارٹر فائلیں (بنیادی طور پر React UI) شامل ہیں۔ اس ٹیوٹوریل میں، ہم اس ڈائرکٹری میں کام کریں گے، کیونکہ آپ سیکھیں گے کہ اس UI کو اپنے Ethereum والیٹ اور ایک NFT اسمارٹ کانٹریکٹ سے جوڑ کر کیسے زندہ کیا جائے۔nft-minterمیں مکمل شدہ ٹیوٹوریل شامل ہے اور یہ آپ کے لیے ایک حوالہ (reference) کے طور پر موجود ہے اگر آپ کہیں پھنس جائیں۔
اس کے بعد، اپنے کوڈ ایڈیٹر میں minter-starter-files کی اپنی کاپی کھولیں، اور پھر اپنے src فولڈر میں جائیں۔
ہم جو بھی کوڈ لکھیں گے وہ src فولڈر کے اندر ہوگا۔ ہم Minter.js جزو (component) میں ترمیم کریں گے اور اپنے پروجیکٹ کو Web3 فعالیت دینے کے لیے اضافی جاوا اسکرپٹ فائلیں لکھیں گے۔
مرحلہ 2: ہماری اسٹارٹر فائلوں کو چیک کریں
اس سے پہلے کہ ہم کوڈنگ شروع کریں، یہ چیک کرنا ضروری ہے کہ اسٹارٹر فائلوں میں ہمارے لیے پہلے سے کیا فراہم کیا گیا ہے۔
اپنے react پروجیکٹ کو چلائیں
آئیے اپنے براؤزر میں React پروجیکٹ کو چلا کر شروع کریں۔ React کی خوبصورتی یہ ہے کہ ایک بار جب ہمارا پروجیکٹ ہمارے براؤزر میں چل رہا ہوتا ہے، تو ہم جو بھی تبدیلیاں محفوظ کرتے ہیں وہ ہمارے براؤزر میں لائیو اپ ڈیٹ ہو جائیں گی۔
پروجیکٹ کو چلانے کے لیے، minter-starter-files فولڈر کی روٹ ڈائرکٹری میں جائیں، اور پروجیکٹ کی انحصار (dependencies) کو انسٹال کرنے کے لیے اپنے ٹرمینل میں npm install چلائیں:
cd minter-starter-filesnpm installایک بار جب وہ انسٹال ہو جائیں، تو اپنے ٹرمینل میں npm start چلائیں:
npm startایسا کرنے سے آپ کے براؤزر میں http://localhost:3000/ (opens in a new tab) کھلنا چاہیے، جہاں آپ کو ہمارے پروجیکٹ کا فرنٹ اینڈ نظر آئے گا۔ اس میں 3 فیلڈز ہونی چاہئیں: آپ کے NFT کے اثاثے کا لنک درج کرنے کی جگہ، اپنے NFT کا نام درج کریں، اور ایک تفصیل فراہم کریں۔
اگر آپ "Connect Wallet" یا "Mint NFT" بٹنوں پر کلک کرنے کی کوشش کرتے ہیں، تو آپ دیکھیں گے کہ وہ کام نہیں کرتے—ایسا اس لیے ہے کیونکہ ہمیں ابھی بھی ان کی فعالیت کو پروگرام کرنے کی ضرورت ہے! :)
Minter.js جزو (component)
نوٹ: یقینی بنائیں کہ آپ 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 کے ڈیجیٹل اثاثے کا لنک ہے
اسٹیٹ متغیرات کے بعد، آپ کو تین غیر نافذ شدہ (un-implemented) فنکشنز نظر آئیں گے: useEffect، connectWalletPressed، اور onMintPressed۔ آپ دیکھیں گے کہ یہ تمام فنکشنز async ہیں، ایسا اس لیے ہے کیونکہ ہم ان میں غیر مطابقت پذیر (asynchronous) API کالز کریں گے! ان کے نام ان کی فعالیت کے مطابق ہیں:
1useEffect(async () => {2 // TODO: لاگو کریں3}, [])45const connectWalletPressed = async () => {6 // TODO: لاگو کریں7}89const onMintPressed = async () => {10 // TODO: لاگو کریں11}سب دکھائیںuseEffect(opens in a new tab) - یہ ایک React ہک ہے جسے آپ کے جزو کے رینڈر ہونے کے بعد کال کیا جاتا ہے۔ چونکہ اس میں ایک خالی سرنی (array)[]پروپ پاس کیا گیا ہے (لائن 3 دیکھیں)، اس لیے اسے صرف جزو کے پہلے رینڈر پر کال کیا جائے گا۔ یہاں ہم اپنے والیٹ لسنر اور ایک اور والیٹ فنکشن کو کال کریں گے تاکہ ہمارے UI کو اپ ڈیٹ کیا جا سکے تاکہ یہ ظاہر ہو سکے کہ آیا کوئی والیٹ پہلے سے جڑا ہوا ہے۔connectWalletPressed- اس فنکشن کو صارف کے MetaMask والیٹ کو ہماری ڈیپ سے جوڑنے کے لیے کال کیا جائے گا۔onMintPressed- اس فنکشن کو صارف کا NFT منٹ کرنے کے لیے کال کیا جائے گا۔
اس فائل کے اختتام کے قریب، ہمارے پاس اپنے جزو کا UI ہے۔ اگر آپ اس کوڈ کو بغور دیکھیں، تو آپ دیکھیں گے کہ ہم اپنے url، name، اور description اسٹیٹ متغیرات کو اپ ڈیٹ کرتے ہیں جب ان کے متعلقہ ٹیکسٹ فیلڈز میں ان پٹ تبدیل ہوتا ہے۔
آپ یہ بھی دیکھیں گے کہ connectWalletPressed اور onMintPressed کو اس وقت کال کیا جاتا ہے جب بالترتیب mintButton اور walletButton IDs والے بٹنوں پر کلک کیا جاتا ہے۔
1// ہمارے کمپوننٹ کا UI2return (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>1415 <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 <input23 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 <input29 type="text"30 placeholder="e.g., My first NFT!"31 onChange={(event) => setName(event.target.value)}32 />33 <h2>✍️ Description: </h2>34 <input35 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 NFT42 </button>43 <p id="status">{status}</p>44 45</div>46)سب دکھائیںآخر میں، آئیے اس بات پر توجہ دیں کہ یہ Minter جزو کہاں شامل کیا گیا ہے۔
اگر آپ App.js فائل پر جاتے ہیں، جو کہ React میں مرکزی جزو ہے جو دیگر تمام اجزاء کے لیے ایک کنٹینر کے طور پر کام کرتا ہے، تو آپ دیکھیں گے کہ ہمارا Minter جزو لائن 7 پر شامل کیا گیا ہے۔
اس ٹیوٹوریل میں، ہم صرف Minter.js file میں ترمیم کریں گے اور اپنے src فولڈر میں فائلیں شامل کریں گے۔
اب جب کہ ہم سمجھ گئے ہیں کہ ہم کس چیز کے ساتھ کام کر رہے ہیں، آئیے اپنا Ethereum والیٹ سیٹ اپ کریں!
اپنا Ethereum والیٹ سیٹ اپ کریں
صارفین کو آپ کے اسمارٹ کانٹریکٹ کے ساتھ تعامل کرنے کے قابل ہونے کے لیے انہیں اپنے Ethereum والیٹ کو آپ کی ڈیپ سے جوڑنے کی ضرورت ہوگی۔
MetaMask ڈاؤن لوڈ کریں
اس ٹیوٹوریل کے لیے، ہم MetaMask کا استعمال کریں گے، جو براؤزر میں ایک ورچوئل والیٹ ہے جسے آپ کے Ethereum اکاؤنٹ کے ایڈریس کو منظم کرنے کے لیے استعمال کیا جاتا ہے۔ اگر آپ اس بارے میں مزید سمجھنا چاہتے ہیں کہ Ethereum پر ٹرانزیکشنز کیسے کام کرتی ہیں، تو یہ صفحہ دیکھیں۔
آپ یہاں (opens in a new tab) مفت میں MetaMask اکاؤنٹ ڈاؤن لوڈ اور بنا سکتے ہیں۔ جب آپ اکاؤنٹ بنا رہے ہوں، یا اگر آپ کے پاس پہلے سے اکاؤنٹ ہے، تو یقینی بنائیں کہ اوپری دائیں جانب "Ropsten Test Network" پر سوئچ کریں (تاکہ ہم حقیقی رقم کے ساتھ کام نہ کر رہے ہوں)۔
Faucet سے ایتھر شامل کریں
اپنے NFTs کو منٹ کرنے (یا Ethereum بلاک چین پر کسی بھی ٹرانزیکشن پر دستخط کرنے) کے لیے، ہمیں کچھ نقلی Eth کی ضرورت ہوگی۔ Eth حاصل کرنے کے لیے آپ Ropsten faucet (opens in a new tab) پر جا سکتے ہیں اور اپنا Ropsten اکاؤنٹ ایڈریس درج کر سکتے ہیں، پھر "Send Ropsten Eth" پر کلک کریں۔ آپ کو جلد ہی اپنے MetaMask اکاؤنٹ میں Eth نظر آنا چاہیے!
اپنا بیلنس چیک کریں
یہ دوہری جانچ کرنے کے لیے کہ ہمارا بیلنس موجود ہے، آئیے Alchemy’s composer tool (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 کو اعشاریہ (decimal) میں تبدیل کرتے ہیں تو ہمیں 1*10¹⁸ ملتا ہے جو 1 eth کے برابر ہے۔
شکر ہے! ہماری نقلی رقم پوری طرح موجود ہے!
MetaMask کو اپنے UI سے جوڑیں
اب جب کہ ہمارا MetaMask والیٹ سیٹ اپ ہو گیا ہے، آئیے اپنی ڈیپ کو اس سے جوڑیں!
چونکہ ہم MVC (opens in a new tab) پیراڈائم کی پیروی کرنا چاہتے ہیں، اس لیے ہم ایک الگ فائل بنانے جا رہے ہیں جس میں ہماری ڈیپ کی منطق (logic)، ڈیٹا، اور قواعد کو منظم کرنے کے لیے ہمارے فنکشنز شامل ہوں گے، اور پھر ان فنکشنز کو اپنے فرنٹ اینڈ (ہمارے 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 obj12 } 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 your27 browser.28 </a>29 </p>30 </span>31 ),32 }33 }34}سب دکھائیںآئیے تجزیہ کرتے ہیں کہ یہ کوڈ کیا کرتا ہے:
سب سے پہلے، ہمارا فنکشن چیک کرتا ہے کہ آیا آپ کے براؤزر میں window.ethereum فعال ہے۔
window.ethereum ایک عالمی API ہے جسے MetaMask اور دیگر والیٹ فراہم کنندگان کے ذریعے شامل کیا گیا ہے جو ویب سائٹس کو صارفین کے Ethereum اکاؤنٹس کی درخواست کرنے کی اجازت دیتا ہے۔ اگر منظور ہو جائے، تو یہ ان بلاک چینز سے ڈیٹا پڑھ سکتا ہے جن سے صارف جڑا ہوا ہے، اور تجویز کر سکتا ہے کہ صارف پیغامات اور ٹرانزیکشنز پر دستخط کرے۔ مزید معلومات کے لیے MetaMask docs (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"ایک سرنی (array) واپس کرے گا جس میں صارف کے وہ تمام اکاؤنٹ ایڈریسز شامل ہوں گے جو ڈیپ سے جڑے ہوئے ہیں۔ مجموعی طور پر، ہمارا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";34const Minter = (props) => {56 // سٹیٹ ویری ایبلز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 جزو سے کیسے الگ (abstract) کیا گیا ہے؟ یہ اس لیے ہے تاکہ ہم 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 your33 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}, [])غور کریں، ہم getCurrentWalletConnected کی اپنی کال کے جواب کا استعمال اپنے walletAddress اور status اسٹیٹ متغیرات کو اپ ڈیٹ کرنے کے لیے کرتے ہیں۔
ایک بار جب آپ یہ کوڈ شامل کر لیں، تو ہماری براؤزر ونڈو کو ریفریش کرنے کی کوشش کریں۔ بٹن کو یہ کہنا چاہیے کہ آپ جڑے ہوئے ہیں، اور آپ کے جڑے ہوئے والیٹ کے ایڈریس کا پیش نظارہ (preview) دکھانا چاہیے - یہاں تک کہ آپ کے ریفریش کرنے کے بعد بھی!
addWalletListener کو نافذ کریں
ہمارے ڈیپ والیٹ سیٹ اپ کا آخری مرحلہ والیٹ لسنر کو نافذ کرنا ہے تاکہ ہمارا UI اس وقت اپ ڈیٹ ہو جب ہمارے والیٹ کی اسٹیٹ تبدیل ہو، جیسے کہ جب صارف منقطع (disconnect) ہوتا ہے یا اکاؤنٹس تبدیل کرتا ہے۔
اپنی 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)56 addWalletListener()7}, [])اور لیجیے! ہم نے اپنی تمام والیٹ فعالیت کی پروگرامنگ مکمل کر لی ہے! اب جب کہ ہمارا والیٹ سیٹ اپ ہو گیا ہے، آئیے معلوم کرتے ہیں کہ اپنا NFT کیسے منٹ کیا جائے!
NFT میٹا ڈیٹا 101
تو یاد رکھیں وہ NFT میٹا ڈیٹا جس کے بارے میں ہم نے ابھی اس ٹیوٹوریل کے مرحلہ 0 میں بات کی تھی—یہ ایک NFT کو زندہ کرتا ہے، جس سے اس میں خصوصیات شامل ہوتی ہیں، جیسے کہ ایک ڈیجیٹل اثاثہ، نام، تفصیل، اور دیگر اوصاف۔
ہمیں اس میٹا ڈیٹا کو ایک JSON آبجیکٹ کے طور پر کنفیگر کرنے اور اسے اسٹور کرنے کی ضرورت ہوگی، تاکہ ہم اپنے اسمارٹ کانٹریکٹ کے mintNFT فنکشن کو کال کرتے وقت اسے tokenURI پیرامیٹر کے طور پر پاس کر سکیں۔
"Link to Asset"، "Name"، "Description" فیلڈز میں موجود متن ہمارے NFT کے میٹا ڈیٹا کی مختلف خصوصیات پر مشتمل ہوگا۔ ہم اس میٹا ڈیٹا کو ایک JSON آبجیکٹ کے طور پر فارمیٹ کریں گے، لیکن اس JSON آبجیکٹ کو ہم کہاں اسٹور کر سکتے ہیں اس کے لیے کچھ اختیارات ہیں:
- ہم اسے Ethereum بلاک چین پر اسٹور کر سکتے ہیں؛ تاہم، ایسا کرنا بہت مہنگا ہوگا۔
- ہم اسے ایک مرکزی (centralized) سرور پر اسٹور کر سکتے ہیں، جیسے AWS یا Firebase۔ لیکن یہ ہمارے غیر مرکزیت (decentralization) کے اصول کو شکست دے گا۔
- ہم 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 کلید اور خفیہ (secret) کو ایک ماحولیاتی (environment) فائل میں محفوظ طریقے سے اسٹور کر سکتے ہیں۔ آئیے آپ کی پروجیکٹ ڈائرکٹری میں dotenv package (opens in a new tab) انسٹال کریں۔
اپنے ٹرمینل میں ایک نیا ٹیب کھولیں (لوکل ہوسٹ چلانے والے سے الگ) اور یقینی بنائیں کہ آپ minter-starter-files فولڈر میں ہیں، پھر اپنے ٹرمینل میں درج ذیل کمانڈ چلائیں:
1npm install dotenv --saveاس کے بعد، اپنی کمانڈ لائن پر درج ذیل درج کر کے اپنے minter-starter-files کی روٹ ڈائرکٹری میں ایک .env فائل بنائیں:
1vim.envیہ آپ کی .env فائل کو vim (ایک ٹیکسٹ ایڈیٹر) میں کھول دے گا۔ اسے محفوظ کرنے کے لیے اپنے کی بورڈ پر اسی ترتیب میں "esc" + ":" + "q" دبائیں۔
اس کے بعد، VSCode میں، اپنی .env فائل پر جائیں اور اس میں اپنی Pinata API کلید اور API خفیہ شامل کریں، اس طرح:
1REACT_APP_PINATA_KEY = <pinata-api-key>2REACT_APP_PINATA_SECRET = <pinata-api-secret>فائل کو محفوظ کریں، اور پھر آپ اپنے JSON میٹا ڈیٹا کو IPFS پر اپ لوڈ کرنے کے لیے فنکشن لکھنا شروع کرنے کے لیے تیار ہیں!
pinJSONToIPFS کو نافذ کریں
خوش قسمتی سے ہمارے لیے، Pinata کے پاس ایک API specifically for uploading JSON data to IPFS (opens in a new tab) ہے اور axios کے ساتھ ایک آسان JavaScript مثال ہے جسے ہم کچھ معمولی ترامیم کے ساتھ استعمال کر سکتے ہیں۔
اپنے utils فولڈر میں، آئیے pinata.js نام کی ایک اور فائل بنائیں اور پھر .env فائل سے اپنا Pinata خفیہ اور کلید اس طرح امپورٹ کریں:
1require("dotenv").config()2const key = process.env.REACT_APP_PINATA_KEY3const secret = process.env.REACT_APP_PINATA_SECRETاس کے بعد، نیچے سے اضافی کوڈ کو اپنی pinata.js فائل میں پیسٹ کریں۔ پریشان نہ ہوں، ہم تجزیہ کریں گے کہ ہر چیز کا کیا مطلب ہے!
1require("dotenv").config()2const key = process.env.REACT_APP_PINATA_KEY3const secret = process.env.REACT_APP_PINATA_SECRET45const axios = require("axios")67export const pinJSONToIPFS = async (JSONBody) => {8 const url = `https://api.pinata.cloud/pinning/pinJSONToIPFS`9 // Pinata کو axios POST ریکویسٹ بھیج رہے ہیں ⬇️10 return axios11 .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 کے لیے ایک پرامس (promise) پر مبنی HTTP کلائنٹ ہے، جسے ہم Pinata سے درخواست کرنے کے لیے استعمال کریں گے۔
پھر ہمارے پاس اپنا غیر مطابقت پذیر فنکشن pinJSONToIPFS ہے، جو ایک JSONBody کو اپنے ان پٹ کے طور پر لیتا ہے اور اس کے ہیڈر میں Pinata api کلید اور خفیہ لیتا ہے، یہ سب ان کے pinJSONToIPFS API پر ایک POST درخواست کرنے کے لیے ہے۔
- اگر یہ POST درخواست کامیاب ہو جاتی ہے، تو ہمارا فنکشن ایک JSON آبجیکٹ واپس کرتا ہے جس میں
successبولین (boolean) true کے طور پر اور وہpinataUrlہوتا ہے جہاں ہمارا میٹا ڈیٹا پن کیا گیا تھا۔ ہم اس واپس کیے گئےpinataUrlکو اپنے اسمارٹ کانٹریکٹ کے منٹ فنکشن میںtokenURIان پٹ کے طور پر استعمال کریں گے۔ - اگر یہ پوسٹ درخواست ناکام ہو جاتی ہے، تو ہمارا فنکشن ایک JSON آبجیکٹ واپس کرتا ہے جس میں
successبولین false کے طور پر اور ایکmessageاسٹرنگ ہوتی ہے جو ہماری خرابی (error) کو بتاتی ہے۔
ہمارے connectWallet فنکشن کی واپسی کی اقسام کی طرح، ہم JSON آبجیکٹس واپس کر رہے ہیں تاکہ ہم ان کے پیرامیٹرز کا استعمال اپنے اسٹیٹ متغیرات اور UI کو اپ ڈیٹ کرنے کے لیے کر سکیں۔
اپنا اسمارٹ کانٹریکٹ لوڈ کریں
اب جب کہ ہمارے پاس اپنے pinJSONToIPFS فنکشن کے ذریعے اپنے NFT میٹا ڈیٹا کو IPFS پر اپ لوڈ کرنے کا ایک طریقہ ہے، ہمیں اپنے اسمارٹ کانٹریکٹ کی ایک مثال (instance) لوڈ کرنے کے طریقے کی ضرورت ہوگی تاکہ ہم اس کے mintNFT فنکشن کو کال کر سکیں۔
جیسا کہ ہم نے پہلے ذکر کیا، اس ٹیوٹوریل میں ہم this existing NFT smart contract (opens in a new tab) کا استعمال کریں گے؛ تاہم، اگر آپ یہ سیکھنا چاہتے ہیں کہ ہم نے اسے کیسے بنایا، یا خود ایک بنانا چاہتے ہیں، تو ہم انتہائی سفارش کرتے ہیں کہ آپ ہمارا دوسرا ٹیوٹوریل، "How to Create an NFT." (opens in a new tab) دیکھیں۔
کانٹریکٹ ABI
اگر آپ نے ہماری فائلوں کا بغور جائزہ لیا ہے، تو آپ نے دیکھا ہوگا کہ ہماری src ڈائرکٹری میں، ایک contract-abi.json فائل ہے۔ ایک ABI اس بات کی وضاحت کرنے کے لیے ضروری ہے کہ کوئی کانٹریکٹ کس فنکشن کو طلب (invoke) کرے گا اور ساتھ ہی یہ یقینی بنانے کے لیے کہ فنکشن اس فارمیٹ میں ڈیٹا واپس کرے گا جس کی آپ توقع کر رہے ہیں۔
ہمیں Ethereum بلاک چین سے جڑنے اور اپنے اسمارٹ کانٹریکٹ کو لوڈ کرنے کے لیے ایک Alchemy API کلید اور Alchemy Web3 API کی بھی ضرورت ہوگی۔
اپنی Alchemy API کلید بنائیں
اگر آپ کے پاس پہلے سے Alchemy اکاؤنٹ نہیں ہے، تو یہاں مفت میں سائن اپ کریں۔ (opens in a new tab)
ایک بار جب آپ Alchemy اکاؤنٹ بنا لیتے ہیں، تو آپ ایک ایپ بنا کر ایک API کلید تیار کر سکتے ہیں۔ یہ ہمیں Ropsten ٹیسٹ نیٹ ورک پر درخواستیں کرنے کی اجازت دے گا۔
نیویگیشن بار میں "Apps" پر ہوور (hover) کر کے اور "Create App" پر کلک کر کے اپنے Alchemy ڈیش بورڈ میں "Create App" صفحہ پر جائیں۔
اپنی ایپ کا نام رکھیں ہم نے "My First NFT!" کا انتخاب کیا، ایک مختصر تفصیل پیش کریں، اپنی ایپ کی بک کیپنگ کے لیے استعمال ہونے والے ماحول (Environment) کے لیے "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_KEY3const { createAlchemyWeb3 } = require("@alch/alchemy-web3")4const web3 = createAlchemyWeb3(alchemyKey)Alchemy Web3 (opens in a new tab) Web3.js (opens in a new tab) کے گرد ایک ریپر (wrapper) ہے، جو ایک web3 ڈیولپر کے طور پر آپ کی زندگی کو آسان بنانے کے لیے بہتر API میتھڈز اور دیگر اہم فوائد فراہم کرتا ہے۔ اسے اس طرح ڈیزائن کیا گیا ہے کہ کم سے کم کنفیگریشن کی ضرورت ہو تاکہ آپ اسے فوراً اپنی ایپ میں استعمال کرنا شروع کر سکیں!
اس کے بعد، آئیے اپنی فائل میں اپنا کانٹریکٹ ABI اور کانٹریکٹ ایڈریس شامل کریں۔
1require("dotenv").config()2const alchemyKey = process.env.REACT_APP_ALCHEMY_KEY3const { createAlchemyWeb3 } = require("@alch/alchemy-web3")4const web3 = createAlchemyWeb3(alchemyKey)56const contractABI = require("../contract-abi.json")7const contractAddress = "0x4C4a07F737Bf57F6632B6CAB089B78f62385aCaE"ایک بار جب ہمارے پاس یہ دونوں ہو جائیں، تو ہم اپنے منٹ فنکشن کی کوڈنگ شروع کرنے کے لیے تیار ہیں!
mintNFT فنکشن کو نافذ کریں
اپنی interact.js فائل کے اندر، آئیے اپنے فنکشن، mintNFT کی وضاحت کریں، جو اپنے نام کے مطابق ہمارا NFT منٹ کرے گا۔
چونکہ ہم متعدد غیر مطابقت پذیر کالز کریں گے (اپنے میٹا ڈیٹا کو IPFS پر پن کرنے کے لیے Pinata کو، اپنے اسمارٹ کانٹریکٹ کو لوڈ کرنے کے لیے Alchemy Web3 کو، اور اپنی ٹرانزیکشنز پر دستخط کرنے کے لیے MetaMask کو)، اس لیے ہمارا فنکشن بھی غیر مطابقت پذیر ہوگا۔
ہمارے فنکشن کے تین ان پٹس ہمارے ڈیجیٹل اثاثے کا url، name، اور description ہوں گے۔ connectWallet فنکشن کے نیچے درج ذیل فنکشن سگنیچر شامل کریں:
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 پر اپ لوڈ کرنا ہے!
ایسا کرنے کے لیے، ہمیں سب سے پہلے pinJSONToIPFS فنکشن کو اپنی interact.js فائل میں امپورٹ کرنے کی ضرورت ہے۔ 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 }910 // میٹا ڈیٹا بنائیں11 const metadata = new Object()12 metadata.name = name13 metadata.image = url14 metadata.description = description1516 // 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.pinataUrl25}سب دکھائیںغور کریں، ہم pinJSONToIPFS(metadata) کی اپنی کال کے جواب کو pinataResponse آبجیکٹ میں اسٹور کرتے ہیں۔ پھر، ہم کسی بھی خرابی کے لیے اس آبجیکٹ کو پارس (parse) کرتے ہیں۔
اگر کوئی خرابی ہے، تو ہم ایک JSON آبجیکٹ واپس کرتے ہیں جہاں success بولین false ہے اور ہماری status اسٹرنگ یہ پیغام دیتی ہے کہ ہماری کال ناکام ہو گئی۔ بصورت دیگر، ہم pinataResponse سے pinataURL نکالتے ہیں اور اسے اپنے tokenURI متغیر کے طور پر اسٹور کرتے ہیں۔
اب وقت آگیا ہے کہ ہم اس Alchemy Web3 API کا استعمال کرتے ہوئے اپنا اسمارٹ کانٹریکٹ لوڈ کریں جسے ہم نے اپنی فائل کے اوپری حصے میں شروع (initialize) کیا تھا۔ window.contract عالمی متغیر پر کانٹریکٹ سیٹ کرنے کے لیے mintNFT فنکشن کے نچلے حصے میں کوڈ کی درج ذیل لائن شامل کریں:
1window.contract = await new web3.eth.Contract(contractABI, contractAddress)ہمارے mintNFT فنکشن میں شامل کرنے والی آخری چیز ہماری Ethereum ٹرانزیکشن ہے:
1// اپنی ایتھیریم ٹرانزیکشن سیٹ اپ کریں2const transactionParameters = {3 to: contractAddress, // کنٹریکٹ کی اشاعت کے علاوہ ضروری ہے۔4 from: window.ethereum.selectedAddress, // صارف کے فعال ایڈریس سے مماثل ہونا چاہیے۔5 data: window.contract.methods6 .mintNFT(window.ethereum.selectedAddress, tokenURI)7 .encodeABI(), // NFT سمارٹ کنٹریکٹ کو کال کریں8}910// 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}سب دکھائیںاگر آپ پہلے سے ہی Ethereum ٹرانزیکشنز سے واقف ہیں، تو آپ دیکھیں گے کہ اس کی ساخت اس سے کافی ملتی جلتی ہے جو آپ نے دیکھی ہے۔
- سب سے پہلے، ہم اپنے ٹرانزیکشنز کے پیرامیٹرز سیٹ اپ کرتے ہیں۔
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اسٹرنگ خرابی کا پیغام دیتی ہے۔
- اگر ٹرانزیکشن کامیاب ہو جاتی ہے، تو فنکشن ایک JSON آبجیکٹ واپس کرے گا جہاں بولین
مجموعی طور پر، ہمارا 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 }910 // میٹا ڈیٹا بنائیں11 const metadata = new Object()12 metadata.name = name13 metadata.image = url14 metadata.description = description1516 // 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.pinataUrl2526 // سمارٹ کنٹریکٹ لوڈ کریں27 window.contract = await new web3.eth.Contract(contractABI, contractAddress) // loadContract();2829 // اپنی ایتھیریم ٹرانزیکشن سیٹ اپ کریں30 const transactionParameters = {31 to: contractAddress, // کنٹریکٹ کی اشاعت کے علاوہ ضروری ہے۔32 from: window.ethereum.selectedAddress, // صارف کے فعال ایڈریس سے مماثل ہونا چاہیے۔33 data: window.contract.methods34 .mintNFT(window.ethereum.selectedAddress, tokenURI)35 .encodeABI(), // NFT سمارٹ کنٹریکٹ کو کال کریں36 }3738 // 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 جزو سے جوڑنے کی ضرورت ہے...
mintNFT کو ہمارے Minter.js فرنٹ اینڈ سے جوڑیں
اپنی 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 کو ایک لائیو ویب سائٹ پر ڈیپلائے کریں
کیا آپ اپنے پروجیکٹ کو صارفین کے تعامل کے لیے لائیو کرنے کے لیے تیار ہیں؟ اپنے Minter کو ایک لائیو ویب سائٹ پر ڈیپلائے کرنے کے لیے یہ ٹیوٹوریل (opens in a new tab) دیکھیں۔
ایک آخری مرحلہ...
بلاک چین کی دنیا میں تہلکہ مچا دیں
مذاق کر رہا ہوں، آپ ٹیوٹوریل کے اختتام تک پہنچ گئے ہیں!
خلاصہ کرنے کے لیے، ایک NFT منٹر بنا کر، آپ نے کامیابی سے سیکھا کہ:
- اپنے فرنٹ اینڈ پروجیکٹ کے ذریعے MetaMask سے کیسے جڑیں
- اپنے فرنٹ اینڈ سے اسمارٹ کانٹریکٹ کے میتھڈز کو کیسے کال کریں
- MetaMask کا استعمال کرتے ہوئے ٹرانزیکشنز پر کیسے دستخط کریں
غالباً، آپ اپنے والیٹ میں اپنی ڈیپ کے ذریعے منٹ کیے گئے NFTs کو دکھانا چاہیں گے — لہذا ہمارا فوری ٹیوٹوریل How to View Your NFT in Your Wallet (opens in a new tab) ضرور دیکھیں!
اور، ہمیشہ کی طرح، اگر آپ کے کوئی سوالات ہیں، تو ہم Alchemy Discord (opens in a new tab) میں مدد کے لیے موجود ہیں۔ ہم یہ دیکھنے کے لیے بے تاب ہیں کہ آپ اس ٹیوٹوریل کے تصورات کو اپنے مستقبل کے پروجیکٹس میں کیسے لاگو کرتے ہیں!
صفحہ کی آخری اپ ڈیٹ: 25 فروری، 2026