跳至主要内容

如何撰寫與部署 NFT (NFT 教學系列第 1/3 部分)

ERC-721
Alchemy
Solidity
smart contracts
新手
Sumi Mudgil
2021年4月22日
21 分鐘閱讀

隨著 NFT 將區塊鏈帶入公眾視野,現在正是您親自了解這股熱潮的絕佳機會,只要在以太坊區塊鏈上發佈您自己的 NFT 合約 (ERC-721 代幣) 即可!

Alchemy 非常自豪能為 NFT 領域中最頂尖的品牌提供技術支援,包括 Makersplace (最近在佳士得拍賣會上以 6900 萬美元創下數位藝術品銷售記錄)、Dapper Labs (NBA Top Shot 和 CryptoKitties 的創造者)、OpenSea (全球最大的 NFT 市場)、Zora、Super Rare、NFTfi、Foundation、Enjin、Origin Protocol、Immutable 等等。

在本教學中,我們將逐步解說如何使用 MetaMask (opens in a new tab)Solidity (opens in a new tab)Hardhat (opens in a new tab)Pinata (opens in a new tab)Alchemy (opens in a new tab) 在 Sepolia 測試網上建立與部署 ERC-721 智慧合約(如果您還不了解這些術語的含義,請別擔心——我們會一一解釋!)。

在這個教學的第二部分,我們將會瀏覽如何使用我們的智慧型合約去件至一個NFT,在第三部分我們將解釋如何在MeraMask查閱你的NFT。

當然,如果您在任何時候有任何問題,請隨時到 Alchemy Discord (opens in a new tab) 提問,或造訪 Alchemy 的 NFT API 文件 (opens in a new tab)

第 1 步:連線至以太坊網路

有很多方法可以向以太坊區塊鏈發出請求,但為了簡化流程,我們將使用 Alchemy (opens in a new tab) 的免費帳戶。它是一個區塊鏈開發人員平台與 API,可讓我們在不需執行自有節點的情況下與以太坊鏈進行通訊。

在這個教學裡,我們也將會使用Alchemy的開發者工具監控與分析了解我們的智慧型合約部署方式 如果您還沒有 Alchemy 帳戶,可以點擊此處 (opens in a new tab)免費註冊。

第 2 步:建立您的應用程式 (和 API 金鑰)

一旦你已經創建好一個Alchemy的帳戶,你可以通過建立一個程式來生成一個API鑰匙。 這將讓我們能向 Sepolia 測試網發出請求。 如果您想深入了解測試網,請參閱本指南 (opens in a new tab)

  1. 將滑鼠移至標題列上方的"Apps"以及點選"Create App"以前往到在你的Alchemy Dashboard 上的"Create App"頁面。

建立您的應用程式

  1. 為您的應用程式命名 (我們選擇「My First NFT!」)、提供簡短描述、在「Chain」欄位選取「Ethereum」,並為您的網路選取「Sepolia」。 自「合併」後,其他測試網皆已棄用。

設定並發布您的應用程式

  1. 點擊「創建程式」然後就好了! 你的程式應該會在下列圖表中出現。

第 3 步:建立以太坊帳戶 (地址)

我們需要一個乙太坊帳戶去接收或發送交易。 為此教學,我們將會使用 MetaMask。它是一個在瀏覽器上管理你的乙太坊帳戶地址的虛擬錢包。 如果您想深入了解以太坊上的交易如何運作,請參閱以太坊基金會的此頁面

您可以在這裡 (opens in a new tab)免費下載並建立 MetaMask 帳戶。 建立帳戶時,或如果您已有帳戶,請務必在右上角切換至「Sepolia 測試網」(這樣我們就不用處理真實貨幣)。

將 Sepolia 設為您的網路

第 4 步:從水龍頭取得以太幣

為了部屬我們的智慧型合約到測試網上,我們將會需要一些假的以太幣(ETH)。 若要取得 ETH,您可以前往由 Alchemy 託管的 Sepolia Faucet (opens in a new tab),登入並輸入您的帳戶地址,然後點擊「Send Me ETH」。 接著你應蓋到你的MetaMask帳戶確認你的ETH!

第 5 步:檢查您的餘額

為了再次確認我們的餘額,我們將使用 Alchemy 的編輯器工具 (opens in a new tab) 發出 eth_getBalance (opens in a new tab) 請求。 這將會回傳你的錢包裡的餘額。 在你輸入自己的MetaMask帳戶地址,並且點下「寄送請求」後,你理應會看見一個這樣子的回應:

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

注意:此結果以 wei 為單位,而非 ETH。 Wei是一個被用來計算以太最少分數的單位。 「1 eth = 1018 wei」他是這樣轉換的。 所以如果我們轉換0xde0b6b3a7640000到十進制,我們將會獲得1*1018wei,這剛好是1ETH。

哈! 我們的假錢都在這。

第 6 步:初始化我們的專案

首先,我們需要一個資料夾給我們的專案。 前往到你的指令介面(powershell, cmd 或 Terminal) 接著輸入:

1mkdir my-nft
2cd my-nft

現在我們已經在我們的專案資料夾底下了,接著我們將會使用npm去初始化我們的專案。 如果您尚未安裝 npm,請遵循這些指示 (opens in a new tab) (我們也需要 Node.js (opens in a new tab),所以也請一併下載!)。

1npm init

你如何回答安裝問題並不重要,這是我們提供的參考:

1 package name: (my-nft)
2 version: (1.0.0)
3 description: My first NFT!
4 entry point: (index.js)
5 test command:
6 git repository:
7 keywords:
8 author:
9 license: (ISC)
10 About to write to /Users/thesuperb1/Desktop/my-nft/package.json:
11
12 {
13 "name": "my-nft",
14 "version": "1.0.0",
15 "description": "My first NFT!",
16 "main": "index.js",
17 "scripts": {
18 "test": "echo \"Error: no test specified\" && exit 1"
19 },
20 "author": "",
21 "license": "ISC"
22 }
顯示全部

同意創建package.json,接著我們已經準備好開始了!

第 7 步:安裝 Hardhat (opens in a new tab)

Hardhat 是一個開發環境,提供你去編譯、部屬、測試、以及除錯你的以太坊軟體。 它能協助開發人員在部署至即時鏈之前,於本機建立智慧合約和去中心化應用程式。

在我們的 my-nft 專案下執行:

1npm install --save-dev hardhat

如需更多安裝指示 (opens in a new tab)的詳細資訊,請查看此頁面。

第 8 步:建立 Hardhat 專案

在你的專案資料夾下執行:

1npx hardhat

你接下來會看到歡迎訊息以及關於你想做什麼的選項。 選擇"create an empty hardhat.config.js":

1888 888 888 888 888
2888 888 888 888 888
3888 888 888 888 888
48888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888
5888 888 "88b 888P" d88" 888 888 "88b "88b 888
6888 888 .d888888 888 888 888 888 888 .d888888 888
7888 888 888 888 888 Y88b 888 888 888 888 888 Y88b.
8888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888
9👷 Welcome to Hardhat v2.0.11 👷‍
10? What do you want to do? …
11Create a sample project
12❯ Create an empty hardhat.config.js
13Quit
顯示全部

這將會摻生一個 hardhat.config.js file 給我們。

第 9 步:新增專案資料夾

為了保持我們的資料夾的結構性,我們將會創建兩個資料夾。 在你的指令介面返回到到專案資料夾,接著輸入:

1mkdir contracts
2mkdir scripts
  • contracts/ 是放置我們智慧型合約程式碼的地方

  • scripts/ 是我們部屬我們的智慧型合約的地方

第 10 步:撰寫我們的合約

現在我們的環境已經設定好了,接下來是更令人興奮的部分:撰寫我們的智慧合約程式碼!

在您偏好的編輯器中開啟 my-nft 專案 (我們推薦 VSCode (opens in a new tab))。 我們撰寫智慧型合約的語言稱作 Solidity 這將是我們使用去撰寫 MyNFT.sol智慧型合約。

  1. 前往 contracts 資料夾,並建立一個名為 MyNFT.sol 的新檔案

  2. 以下是我們的 NFT 智慧合約程式碼,此程式碼以 OpenZeppelin (opens in a new tab) 函式庫的 ERC-721 實作為基礎。 複製與貼上下面的內容到你的MyNFT.sol檔案。

    1//合約基於 [https://docs.openzeppelin.com/contracts/3.x/erc721](https://docs.openzeppelin.com/contracts/3.x/erc721)
    2// SPDX-License-Identifier: MIT
    3pragma solidity ^0.8.0;
    4
    5import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
    6import "@openzeppelin/contracts/utils/Counters.sol";
    7import "@openzeppelin/contracts/access/Ownable.sol";
    8import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
    9
    10contract MyNFT is ERC721URIStorage, Ownable {
    11 using Counters for Counters.Counter;
    12 Counters.Counter private _tokenIds;
    13
    14 constructor() ERC721("MyNFT", "NFT") {}
    15
    16 function mintNFT(address recipient, string memory tokenURI)
    17 public onlyOwner
    18 returns (uint256)
    19 {
    20 _tokenIds.increment();
    21
    22 uint256 newItemId = _tokenIds.current();
    23 _mint(recipient, newItemId);
    24 _setTokenURI(newItemId, tokenURI);
    25
    26 return newItemId;
    27 }
    28}
    顯示全部
  3. 因為我們繼承了 OpenZeppelin 合約函式庫的類別,所以請在命令列中執行 npm install @openzeppelin/contracts^4.0.0,將函式庫安裝至我們的資料夾中。

那麼,這段程式碼的確切功用是什麼? 讓我們拆解他,一行一行解說。

在智慧合約的頂部,我們匯入了三個 OpenZeppelin (opens in a new tab) 智慧合約類別:

  • @openzeppelin/contracts/token/ERC721/ERC721.sol 包含了ERC-721的執行標準,我們的智慧型合約將會繼承他。 要成為一個有效的非同質化代幣 (NFT),你的智慧型合約必須執行所有在ERR-721標準裡的方法。 若要深入了解繼承的 ERC-721 函式,請參閱此處 (opens in a new tab)的介面定義。

  • @openzeppelin/contracts/utils/Counters.sol 提供一個儘可以逐一遞減或遞增的計數器。 我們的智慧型合約使用一個計數器去持續追蹤所有NFT的鑄造數與設定一個唯一的ID在每一個新NFT。 (每一個被鑄造的NFT都要用一個智慧型合約分配一個唯一的ID -- 我們的ID在這裡只有使用NFT總數來決定。 舉一個例子,我們鑄造的第一個NFT擁有一個「1」的ID,第二個則是「2」,依此類推。)

  • @openzeppelin/contracts/access/Ownable.sol 會在我們的智慧合約上設定存取權控制 (opens in a new tab),如此一來,只有智慧合約的擁有者 (也就是您) 可以鑄造 NFT。 (編註: 包括使用權控制指示一種偏好。 如果你不喜歡有人可以使用你的智慧型合約鑄造NFT,移除在第十行的的"Ownable",以及第17行的"onlyOwner"。)

在引入以上函式庫後,我們有我們傳統的NFT智慧型合約,程式碼意外的短,他只包刮一個計數器,一個構建函數,和一個函式! 這要歸功於我們繼承的 OpenZeppelin 合約,它實作了我們建立 NFT 所需的大部分方法,例如傳回 NFT 擁有者的 ownerOf,以及將 NFT 擁有權從一個帳戶轉移至另一個帳戶的 transferFrom

在我們的 ERC-721 的建構函數裡(constractor),你可能會注意到我們傳入了兩個字串,"MyNFT" 和 "NFT"。 第一個變數是智慧型合約名稱,第二個則是他的代號(象徵 symbol)。 你可以為每一個變數命名。

最後,我們有了函式 mintNFT(address recipient, string memory tokenURI),可以用來鑄造 NFT! 你可能會注意到這個函數傳入了兩個變數:

  • address recipient 會指定接收您剛鑄造好的 NFT 的地址

  • string memory tokenURI 是一個字串,應解析為描述 NFT 元資料的 JSON 文件。 NFT的後設數據(metadata) 實際上是使其生存的原因,允許它具有可配置的屬性,例如名稱,描述,圖像和其他屬性。 在這個教學的第二部份我們將會解釋如何設定這個後設資料(metadata)。

mintNFT 會從繼承的 ERC-721 函式庫呼叫一些方法,並最終傳回一個數字,此數字代表新鑄造的 NFT 的 ID。

第 11 步:將 MetaMask 和 Alchemy 連線至您的專案

現在,我們已經創建了一個MetaMask錢包、Alchemy帳戶,並編寫了我們的智慧型合約,是時候將這三者連接起來了。

每一個從你的虛擬錢包送出的交易都需要用你的私鑰簽名。 為了給予程式這個權限,我們可以把私鑰(還有 Alchemy API key)存在環境檔案中。

若要深入了解傳送交易,請參閱這篇關於使用 web3 傳送交易的教學文章

首先,安裝 dotenv 套件。

1npm install dotenv --save

然後,在我們專案的根目錄中建立一個 .env 檔案,並在其中新增您的 MetaMask 私鑰和 HTTP Alchemy API URL。

複製您的 Alchemy API URL

您的 .env 檔案現在應該會像這樣:

1API_URL="https://eth-sepolia.g.alchemy.com/v2/your-api-key"
2PRIVATE_KEY="your-metamask-private-key"

為了將這些變數實際連線至我們的程式碼,我們會在第 13 步的 hardhat.config.js 檔案中參考這些變數。

第 12 步:安裝 Ethers.js

Ethers.js 是一個函式庫,它將標準 JSON-RPC 方法包裝成更方便使用者使用的方法,讓與以太坊互動和發出請求變得更簡單。

Hardhat 讓整合外掛程式 (opens in a new tab)以取得額外工具和擴充功能變得超級簡單。 我們將利用 Ethers plugin (opens in a new tab) 進行合約部署 (Ethers.js (opens in a new tab) 有一些非常簡潔的合約部署方法)。

在你的專案目錄輸入:

1npm install --save-dev @nomiclabs/hardhat-ethers ethers@^5.0.0

我們會在下一步 hardhat.config.js 將 ethers 納入進來。

第 13 步:更新 hardhat.config.js

我們目前已經新增了幾個套件,現在則是要更新 hardhat.config.js ,告訴專案我們要用它們。

將 hardhat.config.js 更新成如下方:

1 /**
2 * @type import('hardhat/config').HardhatUserConfig
3 */
4 require('dotenv').config();
5 require("@nomiclabs/hardhat-ethers");
6 const { API_URL, PRIVATE_KEY } = process.env;
7 module.exports = {
8 solidity: "0.8.1",
9 defaultNetwork: "sepolia",
10 networks: {
11 hardhat: {},
12 sepolia: {
13 url: API_URL,
14 accounts: [`0x${PRIVATE_KEY}`]
15 }
16 },
17 }
顯示全部

第 14 步:編譯我們的合約

為了確認一切運作正常,我們來編譯合約。 編譯任務是安全帽的內部任務之一

在命令列工具輸入:

1npx hardhat compile

你可能會看到關於“源文件中未提供SPDX許可證識別碼”的警告,但是不用擔心,希望其他的看起來都正常 如果沒有,您隨時可以在 Alchemy discord (opens in a new tab) 中傳送訊息。

第 15 步:撰寫我們的部署腳本

現在我們已經寫好了合約,並且也搞定配置檔案。現在我們該來撰寫部署合約的腳本。

前往 scripts/ 資料夾並建立一個名為 deploy.js 的新檔案,在其中加入以下內容:

1async function main() {
2 const MyNFT = await ethers.getContractFactory("MyNFT")
3
4 // 開始部署,傳回一個解析為合約物件的 promise
5 const myNFT = await MyNFT.deploy()
6 await myNFT.deployed()
7 console.log("Contract deployed to address:", myNFT.address)
8}
9
10main()
11 .then(() => process.exit(0))
12 .catch((error) => {
13 console.error(error)
14 process.exit(1)
15 })
顯示全部

Hardhat 在其合約教學文章 (opens in a new tab)中詳細地解釋了每一行程式碼的作用,我們在此採用了他們的解釋。

1const MyNFT = await ethers.getContractFactory("MyNFT");

Ethers.js 中的 ContractFactory 是用於部署新智慧型合約的抽象對象。所以這裡的MyNFT是我們NFT合約實例的工廠 使用 hardhat-ethers 插件时,ContractFactory 和合約實例默認與第一個簽名帳戶相連。

1const myNFT = await MyNFT.deploy();

調用 ContractFactory 程式碼中的 deploy() 函數會啟動合約部署,然後返回解析為合約的Promise。 這就是和我們的智慧型合約函數有一對一的方法的物件。

第 16 步:部署我們的合約

我們終於準備好要部署合約了! 返回你專案目錄的根目錄,在命令行中於行:

1npx hardhat --network sepolia run scripts/deploy.js

你會看到像這樣的輸出:

1合約已部署至地址:0x4C5266cCc4b3F426965d2f51b6D910325a0E7650

如果我們前往 Sepolia etherscan (opens in a new tab) 並搜尋我們的合約地址,我們應該能夠看到它已成功部署。 如果你沒立即看到它,請稍等片刻,因為它可能需要一些時間。 這個交易執行看起來會像這樣:

在 Etherscan 上檢視您的交易地址

「From」地址應與您的 MetaMask 帳戶地址相符,而「To」地址將顯示「Contract Creation」。 如果我們電機進入交易,我們將在“To”字段中看到我們的合約地址:

在 Etherscan 上檢視您的合約地址

太棒了! 您剛剛已將您的 NFT 智慧合約部署到以太坊 (測試網) 鏈上了!

為了了解幕後情況,讓我們前往 Alchemy 儀表板 (opens in a new tab)中的「Explorer」分頁。 如果你有多個Alchemy應用程序,請確保按應用程序篩選,然後選擇“MyNFT”。

使用 Alchemy 的 Explorer 儀表板檢視「幕後」進行的呼叫

在這裡你會看到Hardhat/Ethers 替我們在後端完成的一系列JSON-RPC調用,當我們調用.deploy() 函數時候。 這裡要特別提出兩個重要的呼叫:eth_sendRawTransaction 是將我們的智慧合約實際寫入 Sepolia 鏈的請求;eth_getTransactionByHash 則是在給定哈希的情況下讀取交易資訊的請求 (這是傳送交易時的典型模式)。 若要深入了解傳送交易,請參閱這篇關於使用 Web3 傳送交易的教學文章。

以上即為這個教程的第1部分全部內容。 在第 2 部分,我們將透過鑄造 NFT 來實際與我們的智慧合約互動,而在第 3 部分,我們將示範如何在您的以太坊錢包中檢視您的 NFT

頁面最後更新時間: 2025年12月5日

這個使用教學對你有幫助嗎?