web3.js 教程
介绍
开发以太坊区块链应用程序,涉及到以下部分:
- 智能合约开发 – 使用 solidity 语言编写代码,部署到区块链。
- 网站或客户端开发 – 与区块链中的智能合约进行交互,读写数据。
在进行网站或客户端开发时,就需要用到 web3.js。
web3.js 库是一个 javascript 库,可以让你执行很多与区块链进行交互的任务,例如:
- 以太币转账
- 读写智能合约中的数据
- 创建智能合约
如果你有 web 开发背景,对使用 Ajax 与 web 服务器进行通信的机制应该很熟悉。与 Ajax 类似,可以使用 Web3.js 读写以太坊区块链。
区块链网络是一个点对点的对等网络,网络由各个节点相互连接构成,智能合约的代码与数据存储在区块链中。使用 web3.js 可以向区块链网络中某个以太坊节点发出请求,与区块链网络进行交互。
此过程如下图所示:
web3.js 使用 JSON RPC 与 Ethereum 区块链通信 (JSON RPC 即 JSON 远程调用),对区块链网络进行数据读写。
这有点像使用 jQuery ajax 库来读写 web 服务器上的数据。
web3.js 简介
Web3 是一套和以太坊节点进行通信的 API,如果我们需要基于以太坊来开发去中心化应用,就可能需要使用 web3(或者使用 ethers.js
),例如需要通过 Web3 来获取节点状态,获取账号信息,调用合约、监听合约事件等等。
web3.js 是 Web3 协议的 JavaScript 实现版本,其他的多个语言版本的实现有
- https://github.com/ethereum/web3.py
- https://github.com/airalab/hs-web3
- https://github.com/web3j/web3j
- https://github.com/mslinn/web3j-scala
- https://github.com/f-o-a-m/purescript-web3
- https://github.com/sc0Vu/web3.php
- https://github.com/digitaldonkey/ethereum-php
注意 web3.js 有两个不兼容的版本:0.20.x 及 1.0beta,1.0 对 0.20 版本做了重构。
web3
包含下面几个对象:
web3.eth
用来与以太坊区块链及合约的交互web3.shh
用来与 Whisper 协议相关交互web3.net
用来获取网络相关信息web3
主对象 包含一些工具
引入 web3
首先你需要将 web3 引入到应用工程中,可以通过如下几个方法:
- npm:
npm install web3
- bower:
bower install web3
- meteor:
meteor add ethereum:web3
- vanilla: 链接
dist/web3.min.js
然后你需要创建一个 web3 的实例,设置一个 provider。为了保证你不会覆盖一个已有的 provider(Mist 浏览器或安装了 MetaMak 的浏览器会提供 Provider),需要先检查是否 web3 实例已存在,示例代码如下:
if (typeof web3 !== 'undefined') {
web3 = new Web3(web3.currentProvider);
} else {
// set the provider you want from Web3.providers
web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
}
另外一种检查方式
// 检查是否是新的 MetaMask 或 DApp 浏览器
var web3Provider;
if (window.ethereum) {
web3Provider = window.ethereum;
try {
// 请求用户授权
await window.ethereum.enable();
} catch (error) {
// 用户不授权时
console.error("User denied account access")
}
} else if (window.web3) { // 老版 MetaMask Legacy dapp browsers...
web3Provider = window.web3.currentProvider;
} else {
web3Provider = new Web3.providers.HttpProvider('http://localhost:8545');
}
web3 = new Web3(web3Provider);
成功引入后,你现在可以使用 web3
对象的 API 了。
使用回调
由于这套 API 被设计来与本地的 RPC 结点交互,所有函数默认使用同步的 HTTP 的请求。
如果你想发起一个异步的请求。大多数函数允许传一个跟在参数列表后的可选的回调函数来支持异步,回调函数支持 Error优先 的风格。
web3.eth.getBlock(48, function(error, result){
if(!error)
console.log(JSON.stringify(result));
else
console.error(error);
})
批量请求
可以允许将多个请求放入队列,并一次执行。
注意:批量请求并不会更快,在某些情况下,同时发起多个异步请求,也许更快。
这里的批量请求主要目的是用来保证请求的串行执行。
var batch = web3.createBatch();
batch.add(web3.eth.getBalance.request('0x0000000000000000000000000000000000000000', 'latest', callback));
batch.add(web3.eth.contract(abi).at(address).balance.request(address, callback2));
batch.execute();
web3.js 中的大数处理
如果是一个数据类型的返回结果,通常会得到一个 BigNumber 对象,因为 Javascript 不能正确的处理 BigNumber,看看下面的例子:
"101010100324325345346456456456456456456"
// "101010100324325345346456456456456456456"
101010100324325345346456456456456456456
// 1.0101010032432535e+38
所以 web3.js 依赖 BigNumber https://github.com/MikeMcl/bignumber.js
var balance = new BigNumber('131242344353464564564574574567456');
// or var balance = web3.eth.getBalance(someAddress);
balance.plus(21).toString(10); // 转化为字符串
// "131242344353464564564574574567477"
下一个例子中,我们会看到,如果有 20 位以上的浮点值,仍会导致出错。所以推荐尽量让帐户余额以 wei 为单位,仅仅在需要向用户展示时,才转换为其它单位。
var balance = new BigNumber('13124.234435346456466666457455567456');
balance.plus(21).toString(10); // toString(10) converts it to a number string, but can only show upto 20 digits
// "13145.23443534645646666646" // your number will be truncated after the 20th digit