NFT Minter Öğreticisi
Web2 arka planından gelen geliştiriciler için en büyük zorluklardan biri, akıllı bağlantınızı bir ön uç projesine nasıl bağlayacağınızı ve onunla nasıl etkileşimde bulunacağınızı anlamaktır.
Dijital varlığınıza bir bağlantı, bir başlık ve bir açıklama girebileceğiniz basit bir kullanıcı arayüzü olan bir NFT minter oluşturarak şunları nasıl yapacağınızı öğreneceksiniz:
- Ön uç projeniz aracılığıyla MetaMask'a bağlanma
- Ön ucunuzdan akıllı sözleşme yöntemlerini çağırma
- MetaMask kullanarak işlemleri imzalama
Bu öğreticide, ön uç çerçevemiz olarak React(opens in a new tab) kullanacağız. Bu eğitim öncelikle Web3 geliştirmeye odaklandığından, React temellerini açıklamak için fazla zaman harcamayacağız. Bunun yerine, projemize işlevsellik getirmeye odaklanacağız.
Bir ön koşul olarak, başlangıç düzeyinde bir React anlayışına sahip olmalısınız; bileşenlerin, donanımların, useState/useEffect ve temel fonksiyon çağırmanın nasıl çalıştığını bilmeniz gerekir. Bu terimlerden herhangi birini daha önce hiç duymadıysanız, bu React'e Giriş eğitimine(opens in a new tab) göz atmak isteyebilirsiniz. Daha görsel öğrenenler için Net Ninja'nın bu mükemmel Tam Modern React Eğitimi(opens in a new tab) video dizisini şiddetle tavsiye ediyoruz.
Ve henüz yapmadıysanız, bu öğreticiyi tamamlamak ve blok zincirinde herhangi bir şey oluşturmak için kesinlikle bir Alchemy hesabına ihtiyacınız olacak. Buradan(opens in a new tab) ücretsiz bir hesap için kaydolun.
Lafı fazla uzatmadan başlayalım!
NFT Yapma 101
Herhangi bir koda bakmaya başlamadan önce, bir NFT yapmanın nasıl çalıştığını anlamak önemlidir. İki adım içerir:
Ethereum blok zincirinde bir NFT akıllı sözleşmesi yayınlayın
İki NFT akıllı iletişim standardı arasındaki en büyük fark, ERC-1155'in çok token'lı bir standart olması ve toplu işlevsellik içermesi; ERC-721'in ise tek token'lı bir standart olması ve bu nedenle bir seferde yalnızca bir token'ın aktarılmasını desteklemesidir.
Basma fonksiyonunu çağırın
Genellikle, bu mint (basma) fonksiyonu, parametre olarak iki değişken girmenizi gerektirir: İlk olarak, yeni basılmış NFT'nizi alacak adresi belirten recipient
ve ikinci olarak NFT'nin meta verilerini açıklayan bir JSON belgesine çözümlenen bir dize olan NFT'nin tokenURI
'ı.
Bir NFT'nin meta verileri gerçekten onu hayata geçiren şeydir ve bir isim, açıklama, görüntü (veya farklı dijital varlık) ve diğer nitelikler gibi özelliklere sahip olmasına izin verir. İşte bir NFT'nin meta verilerini içeren bir tokenURI örneği(opens in a new tab).
Bu öğreticide, React UI'ımızı kullanarak mevcut bir NFT'nin akıllı sözleşme basım fonksiyonunu çağırarak 2. bölüme odaklanacağız.
Bu öğreticide çağıracağımız ERC-721 NFT akıllı sözleşmesinin bağlantısı(opens in a new tab). Bunu nasıl yaptığımızı öğrenmek istiyorsanız, diğer öğreticimiz "Bir NFT Nasıl Oluşturulur"(opens in a new tab)a göz atmanızı şiddetle tavsiye ederiz.
Harika, şimdi bir NFT yapmanın nasıl çalıştığını anladığımıza göre, başlangıç dosyalarımızı klonlayalım!
Başlangıç dosyalarını klonlayın
İlk olarak, bu proje için başlangıç dosyalarını almak için nft-minter-tutorial GitHub deposuna(opens in a new tab) gidin. Bu depoyu yerel ortamınıza klonlayın.=
Bu klonlanmış nft-minter-tutorial
deposunu açtığınızda, iki klasör içerdiğini fark edeceksiniz: minter-starter-files
ve nft-minter
.
minter-starter-files
, bu proje için başlangıç dosyalarını (esas olarak React UI'ını) içerir. Bu öğreticide, bu dizinde çalışarak bu kullanıcı arayüzünü Ethereum cüzdanınıza ve bir NFT akıllı sözleşmesine bağlayarak nasıl hayata geçireceğinizi öğreneceğiz.nft-minter
, tamamlanmış öğreticinin tamamını içerir ve takılırsanız size referans olması için oradadır.
Ardından, kod düzenleyicinizde minter-starter-files
kopyanızı açın ve ardından src
klasörünüze gidin.
Yazacağımız tüm kodlar src
klasörünün altında yer alacaktır. Projemize Web3 işlevselliği kazandırmak için Minter.js
bileşenini düzenleyeceğiz ve ek javascript dosyaları yazacağız.
2. Adım: Başlangıç dosyalarımıza göz atın
Kodlamaya başlamadan önce, başlangıç dosyalarında bizim için nelerin sağlandığını kontrol etmek önemlidir.
React projenizi çalıştırın
Tarayıcımızda React projesini çalıştırarak başlayalım. React'in güzelliği, projemizi tarayıcımızda çalıştırdıktan sonra, kaydettiğimiz tüm değişikliklerin tarayıcımızda canlı olarak güncellenmesidir.
Projeyi çalıştırmak için minter-starter-files
klasörünün kök dizinine gidin ve projenin bağımlılıklarını yüklemek için terminalinizde npm install
komutunu çalıştırın:
cd minter-starter-filesnpm install
Bunların kurulumu tamamlandıktan sonra terminalinizde npm start
komutunu çalıştırın:
npm start
Bunu yapmak, tarayıcınızda projemizin ön ucunu göreceğiniz http://localhost:3000/ adresini açmalıdır. 3 alandan oluşmalıdır: NFT'nizin varlığına bir bağlantı yerleştireceğiniz, NFT'nizin adını gireceğiniz ve bir açıklama sağlayabileceğiniz bir yer.
"Connect Wallet" (Cüzdanı Bağla) veya "Mint NFT" (NFT Bas) düğmelerinE tıklamayı denerseniz, çalışmadıklarını fark edeceksiniz. Çünkü hâlâ işlevlerini kodlamamız gerekiyor! :)
Minter.js bileşeni
NOT: nft-minter
klasöründe değil, minter-starter-files
klasöründe olduğunuzdan emin olun!
Editörümüzdeki src
klasörüne geri dönelim ve Minter.js
dosyasını açalım. Üzerinde çalışacağımız birincil React bileşeni olduğu için bu dosyadaki her şeyi anlamamız çok önemlidir.
Bu dosyamızın en üstünde, belirli olaylardan sonra güncelleyeceğimiz durum değişkenlerimiz var.
1//State variables2const [walletAddress, setWallet] = useState("")3const [status, setStatus] = useState("")4const [name, setName] = useState("")5const [description, setDescription] = useState("")6const [url, setURL] = useState("")
React durum değişkenlerini veya durum kancalarını hiç duymadınız mı? Bu(opens in a new tab) belgelere göz atın.
Değişkenlerin her birinin temsil ettiği şey:
walletAddress
- kullanıcının cüzdan adresini saklayan bir dizestatus
- kullanıcı arayüzünün altında görüntülenecek bir mesaj içeren bir dizename
- NFT'nin adını saklayan bir dizedescription
- NFT'nin açıklamasını saklayan bir dizeurl
- NFT'nin dijital varlığına bağlantı olan bir dize
Durum değişkenlerinden sonra, uygulanmamış üç fonksiyon göreceksiniz: useEffect
, connectWalletPressed
ve onMintPressed
. Tüm bu fonksiyonların async
olduğunu fark edeceksiniz, çünkü bu fonksiyonlarda eşzamansız API çağrıları yapacağız! Adları, fonksiyonlarıyla aynıdır:
1useEffect(async () => {2 //TODO: implement3}, [])45const connectWalletPressed = async () => {6 //TODO: implement7}89const onMintPressed = async () => {10 //TODO: implement11}Tümünü göster
useEffect
(opens in a new tab) - bu, bileşeniniz oluşturulduktan sonra çağrılan bir React kancasıdır. İçine geçirilen boş bir[]
dizisine sahip olduğundan (3. satıra bakın), yalnızca bileşenin ilk oluşturmasında çağrılır. Burada, bir cüzdanın zaten bağlı olup olmadığını yansıtacak şekilde kullanıcı arayüzünü güncellemek için cüzdan dinleyicimizi ve başka bir cüzdan fonksiyonunu çağıracağız.connectWalletPressed
- bu fonksiyon, kullanıcının MetaMask cüzdanını merkeziyetsiz uygulamamıza bağlamak için çağrılır.onMintPressed
- bu fonksiyon, kullanıcının NFT'sini basmak için çağrılır.
Bu dosyanın sonuna doğru, bileşenimizin kullanıcı arayüzü bulunuyor. Bu kodu dikkatli bir şekilde tararsanız, url
, ad
ve description
durum değişkenlerimizi, bunlara denk gelen metin alanları değiştiğinde güncellediğimizi fark edeceksiniz.
Ayrıca, sırasıyla mintButton
ve walletButton
kimliklerine sahip düğmelere tıklandığında connectWalletPressed
ve onMintPressed
'in çağrıldığını göreceksiniz.
1//the UI of our component2return (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 </div>45)Tümünü göster
Son olarak bu Minter bileşeninin nereye eklendiğine değinelim.
React'teki diğer tüm bileşenler için bir kapsayıcı görevi gören ana bileşen olan App.js
dosyasına giderseniz, Minter bileşenimizin 7. satıra enjekte edildiğini göreceksiniz.
Bu öğreticide, yalnızca Minter.js file
'ı düzenleyeceğiz ve src
klasörümüze dosyalar ekleyeceğiz.
Artık ne üzerinde çalıştığımızı anladığımıza göre, Ethereum cüzdanımızı oluşturalım!
: Ethereum cüzdanınızı kurun
Kullanıcıların akıllı sözleşmenizle etkileşime girebilmeleri için Ethereum cüzdanlarını merkeziyetsiz uygulamanıza bağlamaları gerekir.
MetaMask'i indirin
Bu öğretici için, Ethereum hesap adresinizi yönetmek için kullanılan tarayıcıda sanal bir cüzdan olan MetaMask'ı kullanacağız. Ethereum'daki işlemlerin nasıl çalıştığı hakkında daha fazla bilgi edinmek istiyorsanız, bu sayfaya bakın.
Buradan(opens in a new tab) ücretsiz olarak bir MetaMask hesabı indirebilir ve oluşturabilirsiniz. Bir hesap oluşturuyorsanız veya zaten bir hesabınız varsa, sağ üstteki "Ropsten Test Ağı"na geçtiğinizden emin olun (böylece gerçek parayla uğraşmayız).
Bir Musluktan ether ekleyin
NFT'lerimizi basmak (veya Ethereum blok zincirindeki herhangi bir işlemi imzalamak) için biraz sahte Eth'e ihtiyacımız olacak. Eth almak için Ropsten musluğuna(opens in a new tab) gidebilir ve Ropsten hesap adresinizi girip "Send Ropsten Eth"e (Ropsten Eth Gönder) tıklayabilirsiniz Kısa bir süre sonra MetaMask hesabınızda Eth'i görmelisiniz!
Bakiyenizi kontrol edin
Bakiyemizin yerinde olduğundan emin olmak için Alchemy'nin düzenleyici aracını(opens in a new tab) kullanarak bir eth_getBalance(opens in a new tab) isteği oluşturalım. Bu, cüzdanımızdaki Eth miktarını döndürür. MetaMask hesap adresinizi girdikten ve "Send Request"e tıkladıktan sonra aşağıdaki gibi bir yanıt görmelisiniz:
1{"jsonrpc": "2.0", "id": 0, "result": "0xde0b6b3a7640000"}
NOT: Bu sonuç eth değil wei hâlindedir. Wei, ether'ın en küçük birimi olarak kullanılır. Wei'den eth'e dönüşüm: 1 eth = 10¹⁸ wei. Yani 0xde0b6b3a7640000'ı ondalık sayıya dönüştürürsek 1*10¹⁸ elde ederiz, bu da 1 eth'e eşittir.
Vay be! Tüm sahte paramız yerli yerinde!
MetaMask'i kullanıcı arayüzünüze bağlayın
Artık MetaMask cüzdanımız kurulduğuna göre, merkeziyetsiz uygulamamızı ona bağlayalım!
MVC(opens in a new tab) paradigmasını kurala bağlamak istediğimiz için merkeziyetsiz uygulamamızın mantığını, verilerini ve kurallarını yönetmek amacıyla fonksiyonlarımızı içeren ayrı bir dosya oluşturacağız ve ardından bu fonksiyonları ön ucumuza (Minter.js bileşenimiz) aktaracağız.
connectWallet
fonksiyonu
Bunu yapmak için src
dizininizde utils
adında yeni bir klasör oluşturalım ve içine tüm cüzdan ve akıllı sözleşme etkileşim fonksiyonlarımızı içerecek interact.js
adlı bir dosya ekleyelim.
interact.js
dosyamızda, bir connectWallet
fonksiyonu yazacağız ve bunu daha sonra içe aktarıp Minter.js
bileşenimizde çağıracağız.
interact.js
dosyanıza aşağıdakini ekleyin
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.html`}>26 You must install MetaMask, a virtual Ethereum wallet, in your27 browser.28 </a>29 </p>30 </span>31 ),32 }33 }34}Tümünü göster
Şimdi bu kodun ne yaptığını inceleyelim:
İlk olarak, fonksiyonumuz tarayıcınızda window.ethereum
'un etkin olup olmadığını kontrol eder.
window.ethereum
, MetaMask ve diğer cüzdan sağlayıcıları tarafından enjekte edilen ve web sitelerinin kullanıcıların Ethereum hesaplarını talep etmesine izin veren küresel bir API'dir. Onaylanırsa, kullanıcının bağlı olduğu blok zincirlerinden verileri okuyabilir ve kullanıcının mesajları ve işlemleri imzalamasını önerebilir. Daha fazla bilgi için MetaMask belgelerine(opens in a new tab) göz atın!
window.ethereum
yoksa, MetaMask kurulu değil demektir. Bu, bir JSON nesnesinin döndürülmesiyle sonuçlanır; burada döndürülen address
boş bir dizedir ve status
JSX nesnesi, kullanıcının MetaMask'i yüklemesi gerektiğini bildirir.
Yazdığımız fonksiyonların çoğu, durum değişkenlerimizi ve kullanıcı arayüzünü güncellemek için kullanabileceğimiz JSON nesnelerini döndürecek.
Şimdi, eğer window.ethereum
varsa, işte o zaman işler ilginçleşiyor.
Bir deneme/yakalama döngüsü kullanarak, [window.ethereum.request({ method: "eth_requestAccounts" });](https://docs.metamask.io/guide/rpc-api.html#eth-requestaccounts)
öğesini çağırarak MetaMask'e bağlanmaya çalışacağız. Bu fonksiyonun çağrılması, tarayıcıda MetaMask'i açar ve bu sayede kullanıcıdan cüzdanını merkeziyetsiz uygulamanıza bağlaması istenir.
- Kullanıcı bağlanmayı seçerse,
method: "eth_requestAccounts"
, kullanıcının merkeziyetsiz uygulamaya bağlı tüm hesap adreslerini içeren bir dizi döndürür. Toplamda,connectWallet
fonksiyonumuz bu dizideki ilkaddress
'i içeren bir JSON nesnesi (9. satıra bakın) ve kullanıcıdan akıllı sözleşmeye bir mesaj yazmasını isteyen birstatus
mesajı döndürür. - Kullanıcı bağlantıyı reddederse, JSON nesnesi, döndürülen
address
için boş bir dize ve kullanıcının bağlantıyı reddettiğini yansıtan birstatus
mesajı içerir.
Minter.js UI Bileşeninize connectWallet fonksiyonu ekleyin
Şimdi bu connectWallet
fonksiyonunu yazdığımıza göre, onu Minter.js.
bileşenimize bağlayalım.
İlk olarak, Minter.js
dosyasının en üstüne import { connectWallet } from "./utils/interact.js";
öğesini ekleyerek fonksiyonumuzu Minter.js
dosyamıza aktarmamız gerekecek. Minter.js
dosyasının ilk 11 satırı şimdi şöyle görünmelidir:
1import { useEffect, useState } from "react";2import { connectWallet } from "./utils/interact.js";34const Minter = (props) => {56 //State variables7 const [walletAddress, setWallet] = useState("");8 const [status, setStatus] = useState("");9 const [name, setName] = useState("");10 const [description, setDescription] = useState("");11 const [url, setURL] = useState("");Tümünü göster
Ardından, connectWalletPressed
fonksiyonumuzun içinde, içe aktarılan connectWallet
fonksiyonumuzu şöyle çağıracağız:
1const connectWalletPressed = async () => {2 const walletResponse = await connectWallet()3 setStatus(walletResponse.status)4 setWallet(walletResponse.address)5}
Fonksiyonlarımızın çoğunun interact.js
dosyasındaki Minter.js
bileşenimizden nasıl soyutlandığını gördünüz mü? Bu, M-V-C paradigmasına uymamız içindir!
connectWalletPressed
'de, içe aktarılan connectWallet
fonksiyonumuza bir bekleme çağrısı yaparız ve yanıtını kullanarak durum kancaları aracılığıyla status
ve walletAddress
değişkenlerimizi güncelleriz.
Şimdi, Minter.js
ve interact.js
dosyalarını kaydedelim ve şu ana kadarki kullanıcı arayüzümüzü test edelim.
Tarayıcınızı localhost:3000 üzerinde açın ve sayfanın sağ üst köşesindeki "Connect Wallet" düğmesine basın.
MetaMask yüklüyse, cüzdanınızı merkeziyetsiz uygulamanıza bağlamanız istenecektir. Bağlanmak için daveti kabul edin.
Cüzdan düğmesinin artık adresinizin bağlı olduğunu yansıttığını görmelisiniz.
Ardından, sayfayı yenilemeyi deneyin... Garip. Cüzdan düğmemiz zaten bağlı olmasına rağmen MetaMask'i bağlamamızı istiyor...
Ama merak etmeyin! getCurrentWalletConnected
adlı bir fonksiyonu uygulayarak bunu kolayca düzeltebiliriz; bu, bir adresin merkeziyetsiz uygulamamıza zaten bağlı olup olmadığını kontrol edecek ve kullanıcı arayüzünü buna göre güncelleyecektir!
GetCurrentWalletConnected fonksiyonu
interact.js
dosyanıza aşağıdaki getCurrentWalletConnected
fonksiyonunu ekleyin:
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.html`}>32 You must install MetaMask, a virtual Ethereum wallet, in your33 browser.34 </a>35 </p>36 </span>37 ),38 }39 }40}Tümünü göster
Bu kod, az önce yazdığımız connectWallet
fonksiyonuna çok benzer.
Temel fark, kullanıcının cüzdanını bağlaması için MetaMask'i açan eth_requestAccounts
yöntemini çağırmak yerine, burada yalnızca şu anda merkeziyetsiz uygulamamıza bağlı olan MetaMask adreslerini içeren bir dizi döndüren eth_accounts
yöntemini çağırmamızdır.
Bu fonksiyonu çalışırken görmek için, onu Minter.js
bileşenimizin useEffect
fonksiyonunda çağıralım.
connectWallet
için yaptığımız gibi, bu fonksiyonu interact.js
dosyamızdan Minter.js
dosyamıza şu şekilde aktarmalıyız:
1import { useEffect, useState } from "react"2import {3 connectWallet,4 getCurrentWalletConnected, //import here5} from "./utils/interact.js"
Şimdi onu useEffect
fonksiyonumuzda çağırıyoruz:
1useEffect(async () => {2 const { address, status } = await getCurrentWalletConnected()3 setWallet(address)4 setStatus(status)5}, [])
Dikkat edin, walletAddress
ve status
durum değişkenlerimizi güncellemek için getCurrentWalletConnected
çağrımızın yanıtını kullanıyoruz.
Bu kodu ekledikten sonra tarayıcı penceremizi yenilemeyi deneyin. Düğme, bağlı olduğunuzu söylemeli ve yeniledikten sonra bile bağlı cüzdanınızın adresinin bir önizlemesini göstermelidir!
AddWalletListener'ı uygulayın
Merkeziyetsiz uygulama cüzdanı kurulumumuzun son adımı, örneğin kullanıcı bağlantısını keserek veya hesap değiştirerek cüzdanımızın durumunu değiştirdiğinde kullanıcı arayüzümüzün güncellenmesi için cüzdan dinleyicisini uygulamaktır.
Minter.js
dosyanıza aşağıdakine benzeyen bir addWalletListener
fonksiyonu ekleyin:
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.html`}>17 You must install MetaMask, a virtual Ethereum wallet, in your browser.18 </a>19 </p>20 )21 }22}Tümünü göster
Burada neler olduğunu hızlıca çözelim:
- İlk olarak, fonksiyonumuz
window.ethereum
'un etkin olup olmadığını kontrol eder (yani MetaMask kurulu olup olmadığını).- Değilse,
status
durum değişkenimizi, kullanıcının MetaMask'i yüklemesini isteyen bir JSX dizesine ayarlamamız yeterlidir. - Etkinleştirilirse, 3. satırda
window.ethereum.on("accountsChanged")
dinleyicisini kurarız ve bu dinleyici MetaMask cüzdanındaki, kullanıcının merkeziyetsiz uygulamaya ek bir hesap bağladığı, hesapları değiştirdiği veya bir hesabın bağlantısını kestiği anları da içeren durum değişikliklerini dinler. Bağlı en az bir hesap varsa,walletAddress
durum değişkeni, dinleyici tarafından döndürülenaccounts
dizisindeki ilk hesap olarak güncellenir. Aksi takdirde,walletAddress
boş bir dize olarak ayarlanır.
- Değilse,
Son olarak, onu useEffect
fonksiyonumuzda çağırmalıyız:
1useEffect(async () => {2 const { address, status } = await getCurrentWalletConnected()3 setWallet(address)4 setStatus(status)56 addWalletListener()7}, [])
İşte oldu! Cüzdan fonksiyonlarımızın tümünü programlamayı tamamladık! Cüzdanımız kurulduğuna göre, şimdi NFT'mizi nasıl basacağımızı bulalım!
NFT Meta Verileri 101
Bu öğreticinin 0. Adımında bahsettiğimiz NFT meta verilerini hatırlayın; dijital varlık, ad, açıklama ve diğer nitelikler gibi özelliklere sahip olmasını sağlayarak bir NFT'ye hayat verirler.
Bu meta verileri bir JSON nesnesi olarak yapılandırmamız ve saklamamız gerekecek, böylece akıllı sözleşmemizin mintNFT
fonksiyonunu çağırırken tokenURI
parametresi olarak iletebiliriz.
"Link to Asset" (Varlığa Bağlantı), "Name" (Ad) ve "Description" (Açıklama) alanlarındaki metin, NFT'mizin meta verisinin farklı özelliklerini oluşturacaktır. Bu meta verileri bir JSON nesnesi olarak biçimlendireceğiz, ancak bu JSON nesnesini nerede depolayabileceğimiz konusunda birkaç seçenek var:
- Bunu Ethereum blok zincirinde saklayabiliriz ama bunu yapmak çok pahalı olacaktır.
- AWS veya Firebase gibi merkezi bir sunucuda depolayabiliriz. Ancak bu, merkeziyetsizlik anlayışımızı bozar.
- Dağıtılmış bir dosya sisteminde veri depolamak ve paylaşmak için merkeziyetsiz bir protokol ve eşler arası ağ olan IPFS'yi kullanabiliriz. Bu protokol merkeziyetsiz ve ücretsiz olduğu için en iyi seçeneğimizdir!
Meta verilerimizi IPFS'de depolamak için, uygun bir IPFS API'si ve araç takımı olan Pinata(opens in a new tab)'yı kullanacağız. Bir sonraki adımda, bunun tam olarak nasıl yapılacağını açıklayacağız!
Meta verilerinizi IPFS'ye sabitlemek için Pinata'yı kullanın
Pinata(opens in a new tab) hesabınız yoksa, buradan(opens in a new tab) ücretsiz bir hesap için kaydolun ve e-postanızla hesabınızı doğrulamak için adımları tamamlayın.
Pinata API anahtarınızı oluşturun
https://pinata.cloud/keys(opens in a new tab) sayfasına gidin, ardından üst kısımdaki "New Key" (Yeni Anahtar) düğmesini seçin, Yönetici widget'ını ayarlayın etkinleştirin ve anahtarınızı adlandırın.
Ardından, API bilgilerinizi içeren bir açılır pencere gösterilecektir. Bunu güvenli bir yere koyduğunuzdan emin olun.
Artık anahtarımız ayarlandığına göre onu kullanabilmek için projemize ekleyelim.
Bir .env dosyası oluşturun
Pinata anahtarımızı ve sırrımızı bir ortam dosyasında güvenle saklayabiliriz. Proje dizininize dotenv paketini(opens in a new tab) yükleyelim.
Terminalinizde (yerel ana bilgisayarı çalıştırandan ayrı) yeni bir sekme açın ve minter-starter-files
klasöründe olduğunuzdan emin olun, ardından terminalinizde aşağıdaki komutu çalıştırın:
1npm install dotenv --save
Ardından, komut satırınıza aşağıdakileri girerek minter-starter-files
kök dizininde bir .env
dosyası oluşturun:
1vim.env
Bu, .env
dosyanızı vim (bir metin editörü) içinde açacaktır. Kaydetmek için klavyenizdeki "esc" + ":" + "q" tuşlarına bu sırayla basın.
Ardından, VSCode'da .env
dosyanıza gidin ve Pinata API anahtarınızı ve API sırrınızı şu şekilde ekleyin:
1REACT_APP_PINATA_KEY = <pinata-api-key>2REACT_APP_PINATA_SECRET = <pinata-api-secret>
Dosyayı kaydettikten sonra JSON meta verilerinizi IPFS'ye yüklemek için fonksiyonu yazmaya başlamaya hazırsınız!
PinJSONToIPFS'yi uygulayın
Neyse ki, Pinata'nın özellikle JSON verilerini IPFS'ye yüklemek için bir API'si(opens in a new tab) ve axios örneğiyle bazı ufak değişiklikler yaparak birlikte kullanabileceğimiz uygun bir JavaScript'i var.
utils
klasörünüzde pinata.js
adında başka bir dosya oluşturalım ve ardından .env dosyasından Pinata sırrımızı ve anahtarımızı şu şekilde içe aktaralım:
1require("dotenv").config()2const key = process.env.REACT_APP_PINATA_KEY3const secret = process.env.REACT_APP_PINATA_SECRET
Ardından, aşağıdaki ek kodu pinata.js
dosyanıza yapıştırın. Endişelenmeyin, her şeyin ne anlama geldiğini anlatacağız!
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 //making axios POST request to Pinata ⬇️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}Tümünü göster
Peki bu kod tam olarak ne yapıyor?
İlk olarak, Pinata'ya bir istekte bulunmak için kullanacağımız tarayıcı ve node.js için söz tabanlı bir HTTP istemcisi olan axios(opens in a new tab)'u içe aktarır.
Ardından, pinJSONToIPFS
API'lerine bir POST isteği yapmak için girişi olarak bir JSONBody
ve başlığında Pinata api anahtarını ve sırrını alan eş zamansız fonksiyonumuz pinJSONToIPFS
'ye sahibiz.
- Bu POST isteği başarılı olursa, işlevimiz
success
boolean'ı true olarak ve meta verilerimizin sabitlendiğipinataUrl
ile bir JSON nesnesi döndürür. Akıllı sözleşmemizin mint fonksiyonunatokenURI
girişi olarak döndürülen bupinataUrl
öğesini kullanacağız. - Bu post isteği başarısız olursa, fonksiyonumuz
success
boolean'ı false olan bir JSON nesnesi ve hatamızı ileten birmessage
dizesi döndürür.
connectWallet
fonksiyon dönüş türlerimizde olduğu gibi, durum değişkenlerimizi ve kullanıcı arayüzünü güncellemek amacıyla parametrelerini kullanabilmemiz için JSON nesneleri döndürüyoruz.
Akıllı sözleşmenizi yükleyin
Artık pinJSONToIPFS
fonksiyonumuz aracılığıyla NFT meta verilerimizi IPFS'ye yüklemenin bir yolu olduğuna göre, mintNFT
fonksiyonunu çağırabilmemiz için akıllı sözleşmemizin bir örneğini yüklemenin bir yoluna ihtiyacımız olacak.
Daha önce bahsettiğimiz gibi, bu öğreticide bu mevcut NFT akıllı sözleşmesini(opens in a new tab) kullanacağız; ancak, bunu nasıl yaptığımızı öğrenmek veya kendiniz yapmak istiyorsanız, diğer "Bir NFT Nasıl Oluşturulur?"(opens in a new tab) öğreticimize göz atmanızı şiddetle tavsiye ederiz.
Sözleşme ABI'ı
Dosyalarımızı yakından incelediyseniz, src
dizinimizde bir contract-abi.json
dosyası olduğunu fark etmişsinizdir. Bir sözleşmenin hangi fonksiyonu çağıracağını belirlemek ve fonksiyonun beklediğiniz biçimde veri döndürmesini sağlamak için bir ABI gereklidir.
Ayrıca Ethereum blok zincirine bağlanmak ve akıllı sözleşmemizi yüklemek için bir Alchemy API anahtarına ve Alchemy Web3 API'sine ihtiyacımız olacak.
Alchemy API anahtarınızı oluşturun
Henüz bir Alchemy hesabınız yoksa, buradan ücretsiz kaydolun.(opens in a new tab)
Bir Alchemy hesabı oluşturduktan sonra, bir uygulama oluşturarak bir API anahtarı oluşturabilirsiniz. Bu, Ropsten test ağına istekte bulunmamıza izin verecektir.
İmlecinizi gezinme çubuğundaki "Apps"in (Uygulamalar) üzerine gelip "Create App"e (Uygulama Oluştur) tıklayarak Alchemy Gösterge Panelinizdeki "Create App" sayfasına gidin.
Uygulamanıza bir ad verin (biz, "İlk NFT'm!"i seçtik), kısa bir açıklama yazın, Environment (Ortam) için "Staging"i (Hazırlama) seçin (uygulamanızın muhasebesi için kullanılır) ve network (ağ) için "Ropsten"i seçin.
"Create app"e (Uygulama oluştur) tıklamanız yeterlidir! Uygulamanız aşağıdaki tabloda görünmelidir.
Harika, şimdi HTTP Alchemy API URL'mizi oluşturduğumuza göre, onu panonuza kopyalayın...
…ve sonra onu .env
dosyamıza ekleyelim. Toplamda, .env dosyanız şöyle görünmelidir:
1REACT_APP_PINATA_KEY = <pinata-key>2REACT_APP_PINATA_SECRET = <pinata-secret>3REACT_APP_ALCHEMY_KEY = https://eth-ropsten.alchemyapi.io/v2/<alchemy-key>
Artık sözleşme ABI'ımız ve Alchemy API anahtarımız olduğuna göre, Alchemy Web3(opens in a new tab) kullanarak akıllı sözleşmemizi yüklemeye hazırız.
Alchemy Web3 uç noktanızı ve sözleşmenizi ayarlayın
Öncelikle, henüz sahip değilseniz ana dizine giderek Alchemy Web3(opens in a new tab)'ü yüklemeniz gerekir: terminalde nft-minter-tutorial
:
1cd ..2npm install @alch/alchemy-web3
Şimdi interact.js
dosyamıza geri dönelim. Alchemy anahtarınızı .env dosyanızdan içe aktarmak için dosyanın en üstüne aşağıdaki kodu ekleyin ve Alchemy Web3 uç noktanızı ayarlayın:
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) paketleyicisidir. Bir web3 geliştiricisi olarak hayatınızı kolaylaştıracak gelişmiş API yöntemleri ve diğer önemli avantajlar sağlar. Uygulamanızda hemen kullanmaya başlayabilmeniz için minimum yapılandırma gerektirecek şekilde tasarlanmıştır!
Ardından sözleşme ABI'ımızı ve sözleşme adresimizi dosyamıza ekleyelim.
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"
Her ikisine de sahip olduğumuzda, mint fonksiyonumuzu kodlamaya başlamaya hazırız!
mintNFT fonksiyonunu uygulayın
interact.js
dosyanızın içinde, NFT'mizi aynı adla basacak olan mintNFT
fonksiyonumuzu tanımlayalım.
Çok sayıda eş zamansız çağrı yapacağımız için (meta verilerimizi IPFS'ye sabitlemek için Pinata'ya, akıllı sözleşmemizi yüklemek için Alchemy Web3'e ve işlemlerimizi imzalamak için MetaMask'e), fonksiyonumuz da eş zamansız olacaktır.
Fonksiyonumuzun üç girdisi, dijital varlığımızın url
'si, name
'i ve description
'ı olacaktır. connectWallet
fonksiyonunun altına aşağıdaki fonksiyon imzasını ekleyin:
1export const mintNFT = async (url, name, description) => {}
Girdi hatası işleme
Doğal olarak, girdi parametrelerimiz doğru değilse bu fonksiyondan çıkmak için fonksiyonun başlangıcında bir tür girdi hatası işlemeye sahip olmak mantıklıdır. Fonksiyonumuzun içine aşağıdaki kodu ekleyelim:
1export const mintNFT = async (url, name, description) => {2 //error handling3 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}Tümünü göster
Girdi parametrelerinden herhangi biri boş bir dizeyse, o zaman success
boolean'ın false olduğu bir JSON nesnesi döndürürüz ve status
dizesi, Kullanıcı Arayüzündeki tüm alanların eksiksiz olması gerektiğini aktarır.
Meta verileri IPFS'ye yükleyin
Meta verilerimizin doğru şekilde biçimlendirildiğini öğrendikten sonraki adım, onu bir JSON nesnesi olarak paketlemek ve yazdığımız pinJSONToIPFS
aracılığıyla IPFS'ye yüklemektir!
Bunu yapmak için önce pinJSONToIPFS
fonksiyonunu interact.js
dosyamıza aktarmamız gerekiyor. interact.js
dosyasının en üstüne şunu ekleyelim:
1import { pinJSONToIPFS } from "./pinata.js"
pinJSONToIPFS
öğesinin bir JSON gövdesi aldığını hatırlayın. Bu nedenle onu çağırmadan önce url
, name
ve description
parametrelerimizi bir JSON nesnesi olarak biçimlendirmemiz gerekecek.
metadata
adında bir JSON nesnesi oluşturmak için kodumuzu güncelleyelim ve ardından bu metadata
parametresiyle pinJSONToIPFS
'a bir çağrı yapalım:
1export const mintNFT = async (url, name, description) => {2 //error handling3 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 //make metadata11 const metadata = new Object()12 metadata.name = name13 metadata.image = url14 metadata.description = description1516 //make pinata call17 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}Tümünü göster
Dikkat edin, pinJSONToIPFS(metadata)
çağrımızın yanıtını pinataResponse
nesnesinde saklıyoruz. Ardından, bu nesneyi herhangi bir hata için ayrıştırırız.
Bir hata varsa, success
boolean'ın false olduğu bir JSON nesnesi döndürürüz ve status
dizemiz çağrımızın başarısız olduğunu aktarır. Aksi takdirde, pinataURL
'u pinataResponse
'tan çıkarırız ve onu tokenURI
değişkenimiz olarak saklarız.
Şimdi dosyamızın başında başlattığımız Alchemy Web3 API'sini kullanarak akıllı sözleşmemizi yükleme zamanı. Sözleşmeyi window.contract
global değişkeninde ayarlamak için mintNFT
fonksiyonunun altına aşağıdaki kod satırını ekleyin:
1window.contract = await new web3.eth.Contract(contractABI, contractAddress)
mintNFT
fonksiyonumuza eklenecek son şey Ethereum işlemimizdir:
1//set up your Ethereum transaction2const transactionParameters = {3 to: contractAddress, // Required except during contract publications.4 from: window.ethereum.selectedAddress, // must match user's active address.5 data: window.contract.methods6 .mintNFT(window.ethereum.selectedAddress, tokenURI)7 .encodeABI(), //make call to NFT smart contract8}910//sign the transaction via MetaMask11try {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}Tümünü göster
Ethereum işlemlerine zaten aşinaysanız, yapının gördüklerinize oldukça benzer olduğunu fark edeceksiniz.
- İlk olarak işlem parametrelerimizi oluşturuyoruz.
to
alıcı adresini belirtir (akıllı sözleşmemiz)from
, işlemi imzalayanı belirtir (kullanıcının MetaMask'a bağlı adresi:window.ethereum.selectedAddress
)data
,tokenURI
'ımızı ve kullanıcının cüzdan adresi olanwindow.ethereum.selectedAddress
'i girdi olarak alan akıllı sözleşmemintNFT
yöntemimize yapılan çağrıyı içerir
- Ardından, MetaMask'ten işlemi imzalamasını istediğimiz
window.ethereum.request
adlı bir bekleme çağrısı yaparız. Dikkat edin, bu istekte eth yöntemimizi (eth_SentTransaction) belirtiyoruz vetransactionParameters
'ımızı aktarıyoruz. Bu noktada, MetaMask tarayıcıda açılır ve kullanıcıdan işlemi imzalamasını veya reddetmesini ister.- İşlem başarılı olursa fonksiyon,
success
boolean'ının true olarak ayarlandığı bir JSON nesnesi döndürür vestatus
dizesi kullanıcıdan işlemleri hakkında daha fazla bilgi için Etherscan'i kontrol etmesini ister. - İşlem başarısız olursa fonksiyon,
success
boolean'ının false olarak ayarlandığı bir JSON nesnesi döndürür vestatus
dizesi hata mesajını aktarır.
- İşlem başarılı olursa fonksiyon,
Toplamda, mintNFT
fonksiyonumuz şöyle görünmelidir:
1export const mintNFT = async (url, name, description) => {2 //error handling3 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 //make metadata11 const metadata = new Object()12 metadata.name = name13 metadata.image = url14 metadata.description = description1516 //pinata pin request17 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 //load smart contract27 window.contract = await new web3.eth.Contract(contractABI, contractAddress) //loadContract();2829 //set up your Ethereum transaction30 const transactionParameters = {31 to: contractAddress, // Required except during contract publications.32 from: window.ethereum.selectedAddress, // must match user's active address.33 data: window.contract.methods34 .mintNFT(window.ethereum.selectedAddress, tokenURI)35 .encodeABI(), //make call to NFT smart contract36 }3738 //sign transaction via MetaMask39 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}Tümünü göster
Bu dev bir fonksiyon! Şimdi, mintNFT
fonksiyonumuzu Minter.js
bileşenimize bağlamamız gerekiyor...
MintNFT'yi Minter.js ön ucumuza bağlayın
Minter.js
dosyanızı açın ve en üstteki import { connectWallet, getCurrentWalletConnected } from "./utils/interact.js";
satırını şu şekilde güncelleyin:
1import {2 connectWallet,3 getCurrentWalletConnected,4 mintNFT,5} from "./utils/interact.js"
Son olarak, içe aktarılan mintNFT
fonksiyonunuza bekleme çağrısı yapmak için onMintPressed
fonksiyonunu uygulayın ve işlemimizin başarılı mı yoksa başarısız mı olduğunu yansıtmak için status
durum değişkenini güncelleyin:
1const onMintPressed = async () => {2 const { status } = await mintNFT(url, name, description)3 setStatus(status)4}
NFT'nizi yayındaki bir web sitesinde yayınlayın
Kullanıcıların etkileşim kurması için projenizi yayınlamaya hazır mısınız? Minter'ınızı canlı bir web sitesine dağıtmak için bu öğreticiye(opens in a new tab) göz atın.
Son bir adım...
Blok zinciri dünyasını kasıp kavurun
Şaka yapıyorum, öğreticiyi tamamladınız!
Özetlemek gerekirse, bir NFT minter oluşturarak şunları nasıl yapacağınızı başarıyla öğrendiniz:
- Ön uç projeniz aracılığıyla MetaMask'a bağlanma
- Ön ucunuzdan akıllı sözleşme yöntemlerini arama
- MetaMask kullanarak işlemleri imzalama
Muhtemelen, cüzdanınızda merkeziyetsiz uygulamanız aracılığıyla basılan NFT'leri gösterebilmek istersiniz. Bu nedenle NFT'nizi Cüzdanınızda Görüntüleme(opens in a new tab) adlı hızlı öğreticimize göz atmayı unutmayın!
Ve her zaman olduğu gibi, herhangi bir sorunuz olursa Alchemy Discord(opens in a new tab)'da size yardım etmeye hazırız. Bu öğreticideki kavramları gelecekteki projelerinize nasıl uygulayacağınızı görmek için sabırsızlanıyoruz!
Son düzenleme: @wackerow(opens in a new tab), 7 Mayıs 2024