如何构建 Web3 网站应用?看这一篇就够了
共 16931字,需浏览 34分钟
·
2022-03-04 00:30
通常来说我们认为 Web1.0 是使用用户名和密码进行登录的应用,而 Web2.0 是使用第三方登录,例如 Facebook、Google、微信等等,而 Web3 则是使用进行钱包登录,用户产生的所有价值都属于用户自己。
那么究竟 Web3.0 是一个什么样子的呢?接下来我们用一个简单的示例来体验下如何开发一个完整的 Web3.0 网站应用。
合约
首先打开终端,创建一个名为 hello-web3
的目录,在该目录下面初始化 hardhat
:
➜ mkdir hello-web3 && cd hello-web3
➜ npx hardhat init
Hardhat
是一套完整的 Ethereum 的本地开发套件,我们可以通过它进行智能合约的测试和部署。
这里我们选择创建一个 sample 类型的项目,其他保持默认配置即可,初始化完成后我们可以使用 VSCode
打开项目目录,默认的项目结构如下图所示:
先将项目的 contracts
和 scripts
目录下面的文件移除,我们从0开始编写一个智能合约。在 contracts
目录下面创建一个名为 Counter.sol
的文件,.sol
是 Solidity 语言的文件名后缀,然后我们就可以开始在该文件中编写代码了,一般合约一开始都会有一句版权声明,然后会定义使用 solidity 的版本号,为了测试方便一般我们也会导入 console.log()
这个工具包:
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;
import "hardhat/console.sol";
从上面的代码使用习惯上可以看出,Solidity 和 JavaScript 比较相似。
接下来我们就可以定义合约了,使用 contract
关键字,比如这里我们定义一个名为 Counter
的合约,并在合约里面定义一个名为 counts
的 state 变量,用来保存计数器的数据,然后使用 constructor()
定义一个构造函数,在函数体内将 counts
变量初始化为0,不过在获取定义变量的时候不再需要大家熟知的 this
关键字了:
contract Counter {
uint256 counts;
constructor() {
counts = 0;
}
}
我们想要实现的一个功能是用户在前端页面上点击一个按钮然后计数器就+1
,所以除了上面的变量定义之外,我们还需要定义一个计数器增加的函数 add()
,同样还要获取计数器的数据,也需要定义一个 getCounts()
的函数:
contract Counter {
uint256 counts;
constructor() {
counts = 0;
}
function add() public {
counts = counts + 1;
}
function getCounts() public view returns (uint256) {
return counts;
}
}
在定义函数的时候,函数名后面我们添加了一个 public
关键字,表示当前合约函数可以被外部调用,另外一个函数在获取变量值的时候还添加了一个 view
关键字,表示该函数只是读取数据,并不会涉及到交易(可以理解为调用这个函数不用花 gas 费用)。
到这里我们的第一个简单的智能合约就编写完成了,完整的合约代码如下所示:
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;
import "hardhat/console.sol";
contract Counter {
uint256 counts;
constructor() {
counts = 0;
}
function add() public {
counts = counts + 1;
}
function getCounts() public view returns (uint256) {
return counts;
}
}
测试
智能合约编写完成后,接下来我们需要来对这份合约进行测试。
首先在 scripts
目录下面新增一个名为 run.js
的文件,在文件中定义一个 main 函数,注意要加上 async
关键字,因为函数内的很多语句执行都需要等待,所以一般我们会使用 async/await
的模式去编写,先将 Counter 这份智能合约获取到,获取到后将合约部署到区块链上去,由于上链需要一段时间,所以一般还需要加上一句判断是否部署完成的代码,用来确保智能合约部署完成了,部署完成后我们就可以获取到合约的地址了,代码如下所示:
// 可选的,通过 `node