[區塊鏈] 製作一個超簡單的 NFT 發行網站

在學習區塊鏈的技術,常常到了一個 NFT 發行的網站後,大班哥就開始思考背後的實作機制,是用什麼網頁技術與區塊鏈技術等等,

這篇文章會試圖用簡單的網頁框架跟 Web3 套件,搭建出一個簡單的 NFT 網站,包含可以鑄造 Mint 的功能。

Bigbenthings NFT 最終完成的網站截圖

什麼是 Mint 鑄造?

在了解這個大班哥簡易製作的「NFT 發行網站」以前,需要先知道 Mint 這個動作的目的,才會知道這個網站搭建的用意。

Mint 簡單來說:就是要把 NFT token 給 Mint 鑄造出來

而 NFT 是一種區塊鏈上的非同值化代幣,可以理解它是同一種 token 但卻可以有不同的價值,例如今天一張 100 元鈔票上有名人的簽名,它可能就會被別人用價值超過 100 元來購買,所以名稱才用 非同值化代幣 = NFT = non fungible token

那要如何才能取得區塊鏈上的 NFT呢?

可以直接跟區塊鏈上的智能合約互動取得,也就是我們剛剛解釋說的 Mint 鑄造出來,而大班哥搭建的網站就是提供使用者來做這件事

,來幫助想要 Mint NFT 的人可以透過網站的操作介面得到 NFT,可以幫你來跟區塊鏈互動,一般來說也稱這樣的網站為 DApp。





這個網站 DApp 所需的功能

  1. 檢查使用者的錢包 MetaMask 是否連接,如果沒有,使用者需要先連結錢包
  2. 讓使用者能夠 Mint 出 NFT ,所以預計會有一個按鈕讓使用者開始 「Mint」

技術原理與使用

要做好一個 NFT 發行網站,流程大致上是

Step 1. Smart Contract 智能合約開發 (上圖綠色區塊開始):

  • Solidity:編寫智能合約,透過 Compiler 編譯成 byte code,並產生 ABI
  • Remix:開發環境,可以方便把 byte code 部署(Deploy) 到乙太鏈或是測試鍊上

這部分主要是用 Solidity 這個語言做編寫開發,可以參考大班哥之前寫過的文章 Solidity – 實測簡單撰寫 NFT 發行用的寫智能合約

編寫完的程式碼,需要編譯 Compile 成 byte code,並部署 Deploy 到鍊上,之後就可以讓其他人互動

智能合約主要是決定發行 NFT 的內容,,例如 token 發行數量、鑄造價格、指到的圖片內容等,需要仔細設計非常重要。

Step 2. 網站開發(上圖黑色區塊開始)

  • HTML + CSS + jQuery: 開發網站前端 UI
  • Node.js:web server 開發

因為網站的介面只要能使用即可,不會有過多的設計,所以大班哥以下主要會著墨在 Web3.js 的介紹與應用

Step 3. 區塊鏈溝通 (上圖橘色區塊開始)

  • Web3.js:溝通以太坊區塊鏈,需安裝 MetaMask 的 chrome extension

這邊可以解釋一下 ABI (Application Binary Interface) 是什麼,他是一個 JSON 格式的檔案,

當我們合約變成 byte code 二進位檔案放到乙太方虛擬機 EVM 上後,還是需要與合約裡的 function 互動時,就需要透過 ABI 這個介面來 encode / decode ,讓 EVM 能夠理解,這就是 ABI 的重要性,

格式大概以下範例這樣:

[

    {
        "inputs": [
            {
                "internalType": "string",
                "name": "name",
                "type": "string"
            },
            {
                "internalType": "string",
                "name": "symbol",
                "type": "string"
            },
            {
                "internalType": "uint256",
                "name": "maxBigBenTokenSupply",
                "type": "uint256"
            }
        ],
        "stateMutability": "nonpayable",
        "type": "constructor"
    },
 
...




Web3.js 的介紹

web3.js 算是這篇文章的重點,要能打通網站區塊鏈上的智能合約互動就是靠它。

整個流程,就是使用者操作 DApp/ Web 網站,然後 Web3 套件透過走 JSON RPC 協定跟區塊鏈網路互動。

大班哥是使用 Ethereum 區塊鏈(以太坊) ,是一個點對點的節點網路,它存儲區塊鏈上所有數據和程式碼的 copy。Web3 套件允許我們使用 JSON RPC 向單個Ethereum節點發出請求,以便向網路讀取和寫入數據。這有點像使用帶有 JSON API 的 jQuery 來讀取和寫入Web 伺服器的數據。

以下會實際操作 Web3 的:

安裝 web3.js 套件

大班哥是用 Node.js 來當作 web server,所以安裝用 javascript 實作的 web3.js 套件

也可以直接用掛 CDN

<script src="https://cdnjs.cloudflare.com/ajax/libs/web3/1.7.1/web3.min.js"></script>

判斷使用者 Metamask 是否安裝

▼ 按確定使用者是否安裝 Metamask 套件,可以用 window.ethereum 來判斷

function detectMetaMask() {
    if (typeof window.ethereum !== 'undefined' && window.ethereum.isMetaMask) {    
        console.log("found window.ethereum!");                        
        return true
    } else {                
        return false
    }
}

連結你的錢包

▼ 如果使用者有安裝 Metamask 錢包,就可以請他授權錢包帳戶,以便後續互動

function connect() {
    ethereum
    .request({ method: 'eth_requestAccounts' })
    .then(handleAccountsChanged)
    .catch((error) => {
        if (error.code === 4001) {
            // EIP-1193 userRejectedRequest error
            console.log('Please connect to MetaMask.');
        } else {
            console.error(error);
        }
    });
}

Web3 的 Provider 選擇:

參考以下程式碼,是表示「選擇 Web3 的 Provider」 ,這邊大班哥是用 Metamask,

這邊可以理解最後那個要去跟 blockchain 溝通的人是誰,

為了在主網路上使用 JSON RPC 連接到以太坊 node,我們需要訪問以太坊節點。有幾種方法可以做到這一點。首先,使用 Geth Parity 運行自己的以太坊 node。但這需要你從區塊鏈下載大量數據並保持同步。這是非常麻煩的事。

所以為了方便可以使用 Infura 這樣的服務訪問以太坊 node 而無需自己運行。

Infura 是一項免費提供遠程以太坊節點的服務。你需要做的就是註冊後使用 API 密鑰和要連接到的網路的RPC URL。

像是 "https://mainnet.infura.io/YOUR_INFURA_API_KEY"

而大班哥這邊又是直接使用 Metamask 它本身就是使用 Infura 在跟區塊鏈互動,所以直接交給Metamask 管理即可,

可以參考 Metamask 官方的解釋

web3 = new Web3(window.ethereum);

Contract 物件的使用

▼ 參考以下程式碼,有了 web3 實體,可以透過他的 web3.eth 底下的工具來 new 出一個 Contract 物件,

Contract 必須要帶入兩個參數,

  1. ABI:關於 ABI 上面有解釋過這裡
  2. Address 合約地址:可以到 Metamask wallet 查看,是一串 0x12345… 開頭的字串

有了 contract 後,就是傳遞事件互動,即呼叫合約裡定義好的 function,可以分成:

  1. 需要有交易 tracsaction ETH :send()
  2. 單純呼叫事件:call()

以下程式碼是要 Mint token 需要支付 ETH,所以使用 send(),需要帶的參數

  1. from:你的錢包地址
  2. value:要 Mint 的 NFT 價錢
  3. gas:最高 gas 單位數
  4. gasPrice:每單位 gas 的 wei 值,所以最後 gas fee = gas * gasPrice
async function mintBigBenFun() {
    const contractBigBen = new web3.eth.Contract(
        abi,
        contactAddress
    );
    
    // Mint BigBenFun Token
    contractBigBen.methods.mintBigBenFun(1).send({
    from: walletAddress, // 錢包地址
    value: web3.utils.toWei('0.08', 'ether'), // 0.08 ETH
    gas: 400000, // 單位為 wei
    gasPrice: 21000000000 // 單位為 wei
    }).then(function (result) {
        // handle event
    });
}

其他詳細可以參考官方文件 https://web3js.readthedocs.io/en/v1.7.1/getting-started.html





Metamask 會丟出的 RPC 錯誤

1. RPC Error: Request of type ‘wallet_requestPermissions’ already pending for origin http://127.0.0.1:7000. Please wait.

這種情況可能是你的 Metamask 在需要授權時,處於未登入狀態,只需要輸入密碼後登入即可解決

2. RPC Error: MetaMask Tx Signature: User denied transaction signature.

發出的 transaction 被使用者拒絕,例如使用者看到 gas 太貴而按下「拒絕」

3. RPC Error: Invalid parameters: must provide an Ethereum address.

網站上未連結 (Connect) Metamask 錢包

網站 Demo

可以看到下面的螢幕錄影,一開始先按下右上角的 「Connect Wallet」連接並授權 Metamask 錢包,

之後按下中間紫色的「Mint 1 NFT」按鈕,Metamask 會彈出確定的視窗,顯示需要 0.08 ETH 跟 gas fee,

之後出現訊成功息即 Mint 到一張 BigBenThings 的 NFT。

Mint 成功後到 open sea 測試網上就可以看到 Bigbenthings NFT 囉





小結

在搭建這次網站時,認知到最多的是區塊鏈的知識跟技術太新了,常常在找到網路的資料並試著實作時,不管是前端技術或 web3.js,往往套件都會丟出已過時 depreacated 的警告,所以最保險的做法是直接去官方網站看文件確認最新的做法,也可避免掉資安的漏洞或是無法運作的情形,希望這次分享能讓想往 Web3 前進的朋友有更多一點的了解,以上分享。



尚未有留言,成為第一個留言的人吧!

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。

這個網站採用 Google reCAPTCHA 保護機制,這項服務遵循 Google 隱私權政策服務條款