作為一個前端開發,如何轉型web3開發,dapp開發。?

web3.0時代正悄悄來臨。如果你想開發一個web3項目,或者想要未來從事web3工作,充實自己的web3履歷,本文就是一篇很好的DApp開發技術入門教程。

這篇文章的主要內容包括:

智能合約創建和部署

Solidity語言入門

hardhat框架使用及本地環境搭建

本文較長,包括 20 余張圖片、1 個 Hello-World 版本的 web3項目示例,以及完整的項目程式碼及註釋。如果現在你正在使用手機閱讀,建議先收藏本文;之後打開電腦,沿著本文的思路,仔細閱讀。

一、Hardhat 是什麼?

Hardhat框架,是一個以太坊DApp開發的本地整合開發套件。經常與之對比的是 Hardhat vs Truffle。相比其它作為web3基礎設施的開發工具,Hardhat 更加輕量,採用外掛化的思想,非常適合作為新手dapp開發入門的工具。

Hardhat框架,一個輕量級DApp開發套件

二、環境準備 —— 安裝 Node.js

在使用 Hardhat 進行開發以前,首先需要在本地安裝 Node 環境。

nodejs下載

這裡是nodejs官網的下載地址,根據自己操作系統的配置,選擇合適的版本下載。

這裡要注意,如果電腦上已經安裝過,記得升級到 node v14 及以上的版本,更早的版本不支持 Hardhat。

看一下是否安裝成功,分別輸入:

nodejs安裝是否成功

我這裡是 Windows 系統,用 PowerShell 執行一下上面幾條命令,可以看到已經安裝成功了。

三、開始第一個web3項目

1. 初始化

首先創建一個目錄 hardhat-demo,進到這個目錄里,執行 npx hardhat init 命令:

這時會問你幾個問題,一路回車即可。

使用Hardhat初始化web3項目

npx hardhat init 的作用是:按照模板創建了一個示例項目。當出現 「Project created」 字樣時,代表項目創建成功。

可以看到,在上面的 截圖里,提示了我們要安裝依賴。為了能讓這個示例項目跑起來,還需要安裝幾個依賴模塊:

安裝完以後,這個目錄下的文件應該有這些:

Hardhat初始化DApp項目的目錄結構

這樣,你就成功完成了第一個步驟。

2. 項目中的文件作用

創建好這個示例項目以後,這裡來分析一下這些文件的作用。這一部分略微有一些枯燥,你也可以先閱讀「3. 智能合約的編譯、部署和測試」這一部分,之後再來看這些文件的作用。

① node_modules/、package-lock.json 和 package.json

這些是 node 項目的必須組成部分,包括了項目的配置資訊、安裝的依賴模塊等,這裡可以先無視。

② contracts/Greeter.sol

這個文件是項目中的重點,叫智能合約文件。什麼是智能合約呢?你可以把智能合約,同樣理解為一種可以運行的 程式。只不過這個 程式比較特殊,它是運行在以太坊的 EVM 虛擬機 環境上。並且, 程式本身、 程式的輸入輸出、運行結果等,對所有人可見。

Solidity語言,是智能合約開發的主流語言之一。Solidity語言的入門教程,不是本文涉及的重點,這裡只是簡單提一下。

簡單用 Java 類比一下:

原來你寫了一段 Java 程式碼,放進一個源文件叫作 HelloWorld.java,用 javac 執行編譯,最終在自己的電腦或者 伺服器上,被 JVM 虛擬機執行;現在寫了一段 Greeter.sol 程式碼,它也可以被編譯,被執行,只不過運行環境變成了以太坊的 EVM

初始化項目以後,自動生成的程式碼是這樣的:

第 1 行 pragma solidity ^0.8.0;,聲明了 License,比如 GPL-3.0;

第 2 行 pragma solidity ^0.8.0;,聲明了編譯器版本,這裡面強制指定了版本不得低於 0.8.0,也不能高於 0.9.0;

第 4 行 import"hardhat/console.sol"; 導入了其它合約文件,這裡面的 hardhat/console.sol 文件,是 Hardhat 框架自帶的,是一個用於方便調試的合約文件,源碼在這裡;

第 6 行 contract Greeter 開始,就是合約的主體部分。從結構上看,它很像是在 C++ 或者 Java 中定義一個類,也包括了欄位變數、構造方法、讀方法、寫方法等。這裡面出現了幾個特殊的關鍵字:

contract :聲明一個合約;

memory:和 storage 關鍵字相反,代表了變數只會臨時放在記憶體中,不會存儲在合約的狀態中;

view:聲明該方法為只讀方法,不會改變合約本身的狀態。

③ scripts/sample_scripts.js

這個 JavaScript 文件的作用,是將剛才的 Greeter.sol 智能合約編譯並部署到鏈上。

在註釋中寫上了各行程式碼的作用。這裡要注意幾點:

合約的部署需要一定的時間,因為使用 await greeter.deployed() 非同步方法,等待合約部署完成。

用 Java 程式碼類比一下:Greeter 這個合約像是一個類,而每次部署得到的 greeter 像是 new 了一個類的對象。因此每次部署,都會生成出不同的對象,得到的合約地址也就不同。

④ test/sample_test.js

單元測試對於 web3開發來說同樣重要。sample_test.js 這個文件就是一個單元測試的文件,使用了 chai 這個測試框架:

⑤ hardhat.config.js

接下來,我們會啟動 HardHat,進行區塊鏈本地環境的搭建部署。在正式啟動之前,需要進行一些配置。hardhat.config.js 這個文件,就是在 Hardhat 啟動時,默認要讀取的配置文件。

這裡可以看到,文件的內容可以分為 3 個部分:

聲明依賴的模塊。

聲明啟動時執行的任務:在官方文檔裡面有更加詳細的說明,這裡的示例 task 的作用是:啟動 Hardhat 時, 列印出本地這條鏈的默認帳戶。

聲明配置項:更詳細的說明可以參考官方文檔,這裡說明一下常見配置的含義:

在「1. 初始化」中,執行了 npx hardhat init 以後,會生成出一個默認的配置文件。一般來說,使用這個默認配置即可,不需要更改。

這裡面有一個問題,上面的配置中,同時出現了 localhost 和 hardhat 兩種網路。它們有什麼不同呢?這裡暫時先不提,在 「3. 智能合約的編譯、部署和測試」這一部分中,你就會找到答案。

這樣,項目中各個文件的作用就介紹完畢。可能略微有點枯燥,馬上就可以進入實戰環節了。

3. 智能合約的編譯、部署和測試

① MetaMask錢包下載、安裝及帳戶新建

MetaMask 是什麼呢?它是一個以太坊生態下的錢包,可以管理你的帳戶,支持多種網路。

MetaMask錢包本質上是一個瀏覽器外掛,這裡有它的下載地址(可能需要科學上網),然後像正常添加其它瀏覽器外掛一樣,添加上去就好。

MetaMask外掛

接下來可以通過助記詞的方式,生成一個新帳戶;也可以通過粘貼私鑰的方式,導入你原有的帳戶。

MetaMask錢包導入帳戶

這樣,我們的 MetaMask 錢包就準備好了。

② 在本地網路上部署合約

接下來我們要啟動一個本地區塊鏈網路節點。

首先打開一個 Terminal/Powershell 窗口,執行 npx hardhat node 命令:

Hardhat啟動本地區塊鏈網路節點

這個命令的作用是:按照 hardhat.config.js 中聲明的配置,啟動一個本地區塊鏈網路的節點。在每次啟動時,默認會提供 20 個錢包帳戶和私鑰,每個錢包提供 10000 個 ETH 做測試。

可以看到,Hardhat 啟動時,把這 20 個帳戶的資訊 列印了出來。為什麼會 列印帳戶資訊呢?因為在 hardhat.config.js 中定義了這個執行任務;如果你忘記了,可以回過頭看一下。

啟動成功了,還可以用 MetaMask 這個錢包再驗證一下。

新增一個 localhost 網路,注意鏈 ID 要和 hardhat.config.js 中的 chainId 相同,默認是 31337.

MetaMask Localhost本地網路配置

導入一個帳戶,這裡我選擇了那 20 個自動帳戶中的第 1 個,把私鑰粘貼進去。

這裡注意一下,這些帳戶僅僅是為了本地測試使用,千萬不要在以太坊主網使用這些帳戶地址!切記!

現在,本地網路環境已經就緒,我們把 contracts/Greeter.sol 部署到本地網路上。

打開另一個 Terminal/PowerShell,執行 npx hardhat run .\scripts\sample-script.js --network localhost:

於是會執行 scripts/sample_scripts.js 中的 main 方法,並且 列印出了 Greeter 這個合約的部署地址。

使用Hardhat部署智能合約到本地區塊鏈網路上

同樣地,在啟動本地網路的窗口中,也可以看到剛才這個合約的部署情況:

Hardhat部署智能合約成功

在部署合約時,會執行 constructor 構造函數,所以 console.log(“Deploying a Greeter with greeting:”, _greeting); 這句被執行並 列印出來。

部署合約需要消耗 gas,所以可以看到第一個帳戶中的餘額不再是 10000 個 ETH 了(默認使用第一個帳戶來操作):

MetaMask查看帳戶

再執行一次 npx hardhat run .\scripts\sample-script.js --network localhost,會發現雖然是同一份合約程式碼,但是合約地址發生了變化:

Hardhat部署同一份智能合約程式碼

正如在 「③ scripts/sample_scripts.js」 中所說,用 Java 程式碼類比一下:Greeter 這個合約像是一個類,而每次部署得到的 greeter 像是一個類的對象,因此每次部署,生成出了不同的對象,得到的合約地址也就不同。

我們把 scripts/sample_scripts.js 稍作修改,就可以得到web3版本的 Hello World 了:

到這步為止,我們的 Greeter 合約就成功在本地網路上部署好了,也成功使用 MetaMask 錢包,進行了本地網路連接、測試帳戶導入。

③ Hardhat 其它常見的命令

剛才我們學習了 Hardhat框架的 2 個命令:

npx hardhat node 命令,啟動區塊鏈網路一個本地節點

npx hardhat run .\scripts\sample-script.js --network localhost 命令,把合約部署到了本地網路上。

這一部分,會說明一下其它 Hardhat 的實用命令。

npx hardhat test

這個命令用於執行單元測試,在示例中,也就是運行了 test/sample_test.js 這個文件:

使用Hardhat進行Web3技術開發:單元測試

這代表測試成功。我們稍微修改一下 sample_test.js 文件:

再次執行命令,就會發現測試失敗了:

使用Hardhat進行Web3項目開發:單元測試失敗情況

你可能會問一個問題:在 sample_test.js 的程式碼中,同樣出現了合約的部署語句,那麼這個合約是被部署到了哪裡呢?再次被部署到了 localhost 這個本地網路上嗎?

答案是否定的。

還記得在 「⑤ hardhat.config.js」 一節中提過,有兩個很相似的網路配置: localhost 和 hardhat。當執行 npx hardhat test 命令時,會內置創建 hardhat 網路,並在 hardhat 網路上完成合約部署、方法調用等,不會部署在 localhost 網路上。這一點一定要注意。

npx hardhat console

這個命令的作用是啟動一個控制台 程式,方便互動式輸入輸出。例如輸入 config 查看配置情況:

使用Hardhat進行web3開發:啟動控制台console

在 sample_scripts.js 中的程式碼語句,可以換成在 console 中執行:

使用Hardhat進行web3開發:啟動控制台console

npx hardhat compile

在執行 npx hardhat run .\scripts\sample-script.js --network localhost 部署合約的時候,其實 hardhat 偷偷幫你做了一件事情:編譯。

我們把 artifacts 和 cache 目錄刪掉,現在的目錄結構應該是這樣:

Dapp開發:項目目錄結構

現在我們執行 npx hardhat compile 命令,執行成功后,會發現剛才刪掉的 artifacts 和 cache 目錄,又重新生成出來了。

使用Hardhat進行智能合約的編譯

所以,這個命令的作用就是編譯。cache 是編譯出來的緩存資料夾。artifacts 目錄下的文件很重要,看一下 artifacts/contracts/Greeter.sol/Greeter.json 這個文件:

這個文件和原始文件 contracts/Greeter.sol 有點兒像,又有點兒不像。它就是源文件編譯出來的樣子。這個文件很重要,我們之後還會用到它。

npx hardhat clean

這個命令和 npx hardhat compile 的作用恰好相反,是把編譯出來的文件清理一下。

最後,還有一個重要的命令,叫作 npx hardhat help,這條命令會展示 npx hardhat 系列命令的用法:當你忘記的時候,就可以用這條命令查詢一下。

使用Hardhat進行區塊鏈項目開發:查看幫助help

四、結語

這就到了結語部分?

是的。跟隨本文,你已經掌握了 Hardhat 開發框架的基本用法;創建了一個web3項目;編寫修改了智能合約;執行了單元測試;啟動運行了本地區塊鏈節點;將合約文件成功進行編譯和部署;還安裝了 MetaMask 錢包,並連接了本地網路和測試帳戶進行測試。

但是,現在這個項目,和我們編寫的第一個 C++ Hello-World 控制台 程式一樣,還缺乏一個對用戶友好的前端頁面。如何快速編寫一個前端頁面?如何連接用戶錢包?如果調用智能合約的方法?這些會放在下一篇文章中進行講解。