赞
踩
1. 阅读本文需要了解区块链基本原理及术语,掌握solidity的基本用法。
2. 文本会介绍合约如何应用在前端及web3.js的常用api
你肯定很好奇什么是web3.js?第一反应听起来就是个js库(好吧,确实是这样...),我的任务就是告诉你为什么Dapp需要用到这个库,以及这个库是怎么和合约联合工作的。
以太坊网络是由节点组成,每一个节点都包含了一份区块链的拷贝。当你想要调用一份智能合约的某个方法时,你需要去从其中一个节点中查找并告诉这个节点:
1.想要调用的这个智能合约的地址
2.你想要调用的方法以及传入的参数
以太坊节点只能识别一种叫做JSON-RPC的语言,不要紧张,我们不需要了解这门语言怎么写。web3.js是以太坊提供的一个js库,它封装了以太坊的JSON RPC API,提供了一系列和区块链交互的js对象与函数,包括了查看网络状态、查看本地账户、查看交易、发送交易、编译、部署智能合约等。
下面我们开始正文部分。建议配合:https://cryptozombies.io/zh/lesson/6/chapter/1 食用更加。(本文实际也是在读了这篇教程后的一个总结)
在web3.js里设置web3的provider,告诉代码该和哪个节点交互来处理我们的读写。你可以运行自己的以太坊节点来做privider,但显然,可以更简单一点
1.1 Infura
一个服务,它维护了很多以太节点并提供了一个缓存层实现告诉读取。用infura作为节点提供者,你可以不用自己运营节点就能向以太坊发送、接受信息。引用方法如下:
var web3 = new Web3(new Web3.providers.WebsocketProvider("wss://mainnet.infura.io/ws"));
1.2 Metamask
一个chrome和firefox的插件。metamask默认使用infura的服务器作为web3提供者,在此基础上,能让用户安全的维护他们的以太坊账户和私钥。
使用:该插件把它的web3提供者注入到浏览器的全局js对象web3中,所以可以通过检查web3是否存在,存在就使用当前provider作为提供者。
示例代码:
- window.addEventListener('load', function() {
-
- // 检查web3是否已经注入到(Mist/MetaMask)
- if (typeof web3 !== 'undefined') {
- // 使用 Mist/MetaMask 的提供者
- web3js = new Web3(web3.currentProvider);
- } else {
- // 处理用户没安装的情况, 比如显示一个消息
- // 告诉他们要安装 MetaMask 来使用我们的应用
- }
-
- // 现在你可以启动你的应用并自由访问 Web3.js:
- startApp()
-
- })
1.3 获取metamask用户中的账户
metamask允许用户在扩展中管理多个账户,用户可以随时切换账户,一旦切换账户,就需要相应更新界面。示例:
- //通过这句可以获取当前web3的账户
- var userAccount = web3.eth.accounts[0]
-
- //如果切换账户,可以用setInterval去刷新
- var accountInterval = setInterval(function() {
- // 检查账户是否切换
- if (web3.eth.accounts[0] !== userAccount) {
- userAccount = web3.eth.accounts[0];
- // 调用一些方法来更新界面
- updateInterface();
- }
- }, 100);
-
- //显然教程里给的这个方法会消耗一个计时器资源,其实可以监听切换账号的事件,如果事件发生,就刷新一次页面。
web3.js需要两个参数调用智能合约:address、ABI
2.1 两个参数
address:即你部署智能合约在以太坊后,获得的一个在以太坊上的永久地址。(合约部署不在本文介绍范围)
ABI:一个二进制接口。 以json格式表示合约的方法。当你在以太坊部署合约时,编译器也会给你ABI
2.2 连接合约
- // 实例化目标合约
- //将myABI,myContractAddress替换成你想要连接的合约abi和地址即可
- var myContract = new web3js.eth.Contract(myABI, myContractAddress);
2.3 合约函数调用
2.3.1 call()
call用来调用view和pure。只运行在本地节点,不耗gas。调用示例:
- //myContract是前面定义的目标合约
- //yourWantMethod 是你想要调用的方法的名称,123为传入该方法的参数
- myContract.methods.yourWantMethod(123).call()
2.3.2 send()
send将创建一个事务并改变区块链上的数据,会消耗gas,并会要求弹出对话框请求用户使用metamask对事务签名。所以当调用的函数非pure或view时,需要用send,但尽量避免,因为要花钱啊!调用用例:
myContract.methods.yourWantMethod(123).send()
相比call函数,send一个事务需要一个from来表明谁在调用这个函数(对呀solidity的msg.sender),这样metamask才会弹出提示让他们对事务签名。因为send是要写到区块链中的,所以在用户send到事务被包含进区块之前有一个不可忽略的延迟,所以这里需要异步处理。示例:
- function createRandomZombie(name) {
- // 这将需要一段时间,所以在界面中告诉用户这一点
- // 事务被发送出去了
- $("#txStatus").text("正在区块链上创建僵尸,这将需要一会儿...");
- // 把事务发送到我们的合约:
- return cryptoZombies.methods.createRandomZombie(name)
- .send({ from: userAccount })
- .on("receipt", function(receipt) {
- $("#txStatus").text("成功生成了 " + name + "!");
- // 事务被区块链接受了,重新渲染界面
- getZombiesByOwner(userAccount).then(displayZombies);
- })
- .on("error", function(error) {
- $("#txStatus").text(error);
- });
- }
一些关于send函数的补充 :
- //receipt在合约被包含进区块后触发
- //error在事务未被包含进以太坊上触发
- //可以在调用send的时候指定gas和gasprice
- .send({from: userAccount, gas: 300000});
- // 同时send中发送的应该是以wei为单位发送,1ether等于10^18wei,转换方法如下
- web3js.utils.toWei("1","ether");
- //在send函数中
- .send({ from: userAccount, value: web3js.utils.toWei("0.001","ether") })
直接看代码就明白了:
- //假设你的目标合约中定义了一个事件监听叫做NewZombie;
- cryptoZombies.events.NewZombie()
- .on("data", function(event) {
- let zombie = event.returnValues;
- console.log("一个新僵尸诞生了!", zombie.zombieId, zombie.name, zombie.dna);
- }).on('error', console.error);
3.1 indexed关键字的用法
可以看成是一个过滤字段,用于筛选仅和当前用户有关的字段。用例:
- //合约里有如下transfer事件
- event Transfer(address indexed _from, address indexed _to, uint256 _tokenId);
-
- //监听该事件,过滤掉只要 userAccount
- cryptoZombies.events.Transfer({ filter: { _to: userAccount } })
- .on("data", function(event) {
- let data = event.returnValues;
- // 当前用户更新!更新界面来显示
- }).on('error', console.error);
3.2 查询过去的事件 getPastEvents(fromBlock,toBlock)。block指以太坊区块编号
- cryptoZombies.getPastEvents("NewZombie", { fromBlock: 0, toBlock: 'latest' })
- .then(function(events) {
- // events 是可以用来遍历的 `event` 对象
- });
以上,你知道了web3.js怎么去调合约。
参考文献:
https://share.cryptozombies.io/zh/lesson/6/chapter/1 一个非常不错的入门教程
http://web3.tryblockchain.org/Web3.js-api-refrence.html Web3.js API中文文档
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。