当前位置:   article > 正文

Dapp初探之Web3.js入门_android 原生开发dapp 调用web3.js

android 原生开发dapp 调用web3.js
  •  前言

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 食用更加。(本文实际也是在读了这篇教程后的一个总结)

  •  正文

     1. Web3 Provider

              在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作为提供者。

                     示例代码:

  1. window.addEventListener('load', function() {
  2. // 检查web3是否已经注入到(Mist/MetaMask)
  3. if (typeof web3 !== 'undefined') {
  4. // 使用 Mist/MetaMask 的提供者
  5. web3js = new Web3(web3.currentProvider);
  6. } else {
  7. // 处理用户没安装的情况, 比如显示一个消息
  8. // 告诉他们要安装 MetaMask 来使用我们的应用
  9. }
  10. // 现在你可以启动你的应用并自由访问 Web3.js:
  11. startApp()
  12. })

              1.3  获取metamask用户中的账户

                     metamask允许用户在扩展中管理多个账户,用户可以随时切换账户,一旦切换账户,就需要相应更新界面。示例:

  1. //通过这句可以获取当前web3的账户
  2. var userAccount = web3.eth.accounts[0]
  3. //如果切换账户,可以用setInterval去刷新
  4. var accountInterval = setInterval(function() {
  5. // 检查账户是否切换
  6. if (web3.eth.accounts[0] !== userAccount) {
  7. userAccount = web3.eth.accounts[0];
  8. // 调用一些方法来更新界面
  9. updateInterface();
  10. }
  11. }, 100);
  12. //显然教程里给的这个方法会消耗一个计时器资源,其实可以监听切换账号的事件,如果事件发生,就刷新一次页面。

 

       2.调用合约

               web3.js需要两个参数调用智能合约:address、ABI

               2.1 两个参数

                     address:即你部署智能合约在以太坊后,获得的一个在以太坊上的永久地址。(合约部署不在本文介绍范围)

                     ABI:一个二进制接口。   以json格式表示合约的方法。当你在以太坊部署合约时,编译器也会给你ABI 

               2.2 连接合约

  1. // 实例化目标合约
  2. //将myABI,myContractAddress替换成你想要连接的合约abi和地址即可
  3. var myContract = new web3js.eth.Contract(myABI, myContractAddress);

               2.3 合约函数调用 

                     2.3.1  call()

                       call用来调用view和pure。只运行在本地节点,不耗gas。调用示例:

  1. //myContract是前面定义的目标合约
  2. //yourWantMethod 是你想要调用的方法的名称,123为传入该方法的参数
  3. 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到事务被包含进区块之前有一个不可忽略的延迟,所以这里需要异步处理。示例:

  1. function createRandomZombie(name) {
  2. // 这将需要一段时间,所以在界面中告诉用户这一点
  3. // 事务被发送出去了
  4. $("#txStatus").text("正在区块链上创建僵尸,这将需要一会儿...");
  5. // 把事务发送到我们的合约:
  6. return cryptoZombies.methods.createRandomZombie(name)
  7. .send({ from: userAccount })
  8. .on("receipt", function(receipt) {
  9. $("#txStatus").text("成功生成了 " + name + "!");
  10. // 事务被区块链接受了,重新渲染界面
  11. getZombiesByOwner(userAccount).then(displayZombies);
  12. })
  13. .on("error", function(error) {
  14. $("#txStatus").text(error);
  15. });
  16. }

            一些关于send函数的补充 :

  1. //receipt在合约被包含进区块后触发
  2. //error在事务未被包含进以太坊上触发
  3. //可以在调用send的时候指定gas和gasprice
  4. .send({from: userAccount, gas: 300000});
  5. // 同时send中发送的应该是以wei为单位发送,1ether等于10^18wei,转换方法如下
  6. web3js.utils.toWei("1","ether");
  7. //在send函数中
  8. .send({ from: userAccount, value: web3js.utils.toWei("0.001","ether") })

3.事件监听   

   直接看代码就明白了:

  1. //假设你的目标合约中定义了一个事件监听叫做NewZombie;
  2. cryptoZombies.events.NewZombie()
  3. .on("data", function(event) {
  4. let zombie = event.returnValues;
  5. console.log("一个新僵尸诞生了!", zombie.zombieId, zombie.name, zombie.dna);
  6. }).on('error', console.error);

3.1 indexed关键字的用法   

      可以看成是一个过滤字段,用于筛选仅和当前用户有关的字段。用例:

  1. //合约里有如下transfer事件
  2. event Transfer(address indexed _from, address indexed _to, uint256 _tokenId);
  3. //监听该事件,过滤掉只要 userAccount
  4. cryptoZombies.events.Transfer({ filter: { _to: userAccount } })
  5. .on("data", function(event) {
  6. let data = event.returnValues;
  7. // 当前用户更新!更新界面来显示
  8. }).on('error', console.error);

 3.2 查询过去的事件 getPastEvents(fromBlock,toBlock)。block指以太坊区块编号

  1. cryptoZombies.getPastEvents("NewZombie", { fromBlock: 0, toBlock: 'latest' })
  2. .then(function(events) {
  3. // events 是可以用来遍历的 `event` 对象
  4. });

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/419586
推荐阅读
相关标签
  

闽ICP备14008679号