一个不想写后台的前端不是一个好全栈,前端也可以玩转区块链Web3.js开发。 老吴(北京志顶科技有限公司技术总监、区块链专家)针对前端工程师如何玩转Web3.js开发后端钱包这一主题,分享了自己开发后端钱包的实战经历,并慷慨地奉献了全部代码,给予了前端工程师一个近距离接触区块链开发的契机。 那么,一个前端工程师为什么要接触区块链?如何利用Web3.js开发后端红包的呢?在以太坊开发实战中,应该了解哪些概念?老吴又会在Web3.js编码方面分享给我们一些什么干货呢?希望以下内容对你有所帮助。
作者 | 老吴(北京志顶科技有限公司技术总监、区块链专家)
整理 | kou
以下为老吴在CSDN主办,区块链大本营、EthFans、柏链道捷(PDJ Education)、极客帮创投协办的「第 7 期 CSDN 区块链技术沙龙」上的发言内容,区块链大本营在不改变原意的情况下作了精心整理。
目前,有很多前端工程师存在后端转型需求,部分人还致力于向全栈工程师发展,而结合以太坊Web3会让这种转型变得更加容易,更有机会,因为区块链以太坊开发者属于稀缺性人才。
我今天主要分享的是我个人在区块链DApp开发中的实战经历,一个前端工程师如何成功转型做后端?又如何基于Web3.js开发一个后端钱包呢?
首先,我会带大家了解一下Web3和Web3.js到底是什么,在以太坊开发过程中,我们需要掌握哪些常用的基本概念;
其次,我会重点讲一下Web3.js的两个版本(v 0.2x.x和v1.0-beta),尤其是v1.0-beta,我会详细的介绍v1.0-beta的模块功能;
在这之后,我会简单分享一下Web3.js编码阶段中的一些干货;
最后,和我一起,开始Web3.js开发实战吧!
Web时代的互联网主要用于传递信息,是信息的载体。
Web2.0开启了Web交互大时代,涌现出了很多优秀的交互平台及产品。
以太坊的出现重新定义了Web3,使之成为基于区块链进行价值传递的基础网络与价值网络。
Web3.js是以太坊提供的一个JavaScript库,它封装了以太坊的RPC通信API,提供了一系列与区块链交互方法,使JavaScript与以太坊交互变得简单。
以太坊节点通过JSON-RPC提供外部访问接口,Web3.js是基于JavaScript和Node.js的JSON-RPC封装
JSON-RPC是一个无状态、轻量级的远程过程调用协议(RPC),与传输协议无关,可使用socket、HTTP或者其它协议,它使用JSON(RFC4627)作为数据格式。
那么,在学习以太坊开发过程中,我们需要了解哪些概念呢?主要包括以下四点:区块(Block)、交易(Transaction)、合约(Contract)和账户(Account)。
以太坊中区块是交易的载体,而交易则记载了账户间的信息互动。智能合约则是运行在以太坊虚拟机(EVM)上的应用。
区块:是交易的载体,包含区块数(blockNumber)、块哈希(blockHash)、交易等属性;
交易:包含在区块中,包含发起方(from)、交易对手方(to)、交易金额(Value)、哈希(Hash)等属性;
账户:账户和智能合约一样都是以太坊作为第二代区块链的标志,说到账户会包含很多概念,是账户私钥的密文,我们可以通过密码(password)解密私钥,只有拿到私钥之后才能对交易进行签名。
这里需要着重强调是,以太坊交易的状态保存在交易凭证(TransactionReceipt)中,而且即使交易被12次确认也不意味着交易在业务层面的成功,这只代表交易已经被矿工打包并在以太坊虚拟机上执行。
举一个例子,如果一个用户账户上除了以太币(ETH)之外还有其他代币,我们发起了一笔TPC(代币定价活动)的代币转账交易。此时,交易会被正常挖矿打包并得到确认,但是最终的交易结果却是失败,因为用户账户上的余额不足。
合约:运行在以太坊的应用,既然是应用那么就包含编码、编译、部署、执行等方面,智能合约的出现使得人人都可以拥有自己的代币(Token Coin)。
对于Web3.js开发者而言,与合约打交道的时候很多,假如我们发行了一个ERC20的代币,想要查询某一账户该代币的余额则就需要在合约层面执行ERC20合约的标准方法balanceOf,而转账交易则需要调用合约里的transfer函数。
v0.2x.x对于JSONRPC的封装不够完善,基于v0.2x.x开发我们不得不借助一些第三方的封装,比如: accounts,v0.2x.x官方文档中就推荐使用第三方的accounts封装。
这里我们不是说第三方的封装就不能用或者比官方的封装差,而这从侧面反应了v0.2x.x的不完善,这并不利于我们的后续开发和维护,会提供我们的开发成本降低我们的开发效率。
在我们的钱包开发选型时,综合各种因素,最终选择了Web3.js v1.0。即使在开发基于Web的以太坊应用时,有条件的情况下,我也建议大家选用1.0,我们可以基于express构建Node.js Webserver来给我们的Web应用提供服务。
我开发的钱包服务共有三大服务,监听服务、交易服务和HTTP服务,其中HTTP服务就是基于express构建的,结合Spring Cloud / Nodejs client注册到交易网关上,提供了非常稳定的服务支撑。
安全也是一个非常重要的因素,前段时间以太坊爆出一个非常严重的安全问题,某些应用开发者通过unlockAccount方式解锁账户以便于基于该解锁账户进行各类交易,但是交易完成后并没有lockAccount,那么这一波漏洞被有心的黑客发现并利用,不间断的盗取了unlockAccount上的大量以太坊,造成了巨大损失。
Web3.js对象包含以太坊开发的一些基本单元,其中Eth和Utils为最常用的单元。Eth单元中则封装以太坊交易的核心模块,包括Subscribe、Contract、Accounts、Iban、Abi等。
Subscribe – 订阅接口,可以通过该模块的接口订阅/监听新区块、日志等,注意该模块为WebSocket模式独有;
Contract – 合约接口,与智能合约部署、调用相关,开发Token类应用(或者DAPP)的玩家多多关注;;
Accounts – 账户接口,用户新建账户、账户交易签名等等
Abi – 主要用于以太坊执行智能合约函数的数据编码,后续会详细分享。
安装以太坊官方钱包(安装后包含geth节点)
下载地址:https://github.com/ethereum/mist/releases
我们不论进行哪类开发,都需要部署开发环境,运行一个demo输出一个hello world! 详见https://Node.js.org/en/
Web3.js开发也不例外,也需要部署开发环境。其实部署以太坊开发环境非常简单,只需要我们下载一个以太坊官方钱包,并以正确的命令启动geth就可以了。
钱包包含两部分,以太坊节点geth和钱包管理客户端Ethereum Wallet
Etherscan是以太坊官方推出的区块链浏览器、以太坊统计分析平台、去中心化智能合约平台,里边包罗万象是我们进行以太坊开发的好助手。可以查询交易、查询账户、查询合约、查询合约交易、查询正在打包的交易、查询交易打包时间等等。
需要注意的是,使用ehterscan的时候要分清我们是在哪个网络上做的交易。
预计算的Gas与交易实际使用的Gas可能是不同,最主要的原因在于某些交易在以太坊执行的时候,Gas是根据执行函数的参数动态调整的。Number used once或Number once的缩写,在密码学中Nonce是一个只被使用一次的任意或非重复的随机数值。
gasPrice是需要我们谨慎对待的参数,因为在gasLimit一定的情况下,gasPrice越高交易就会被矿工越早打包,在不同的业务场景我们可以适当调整gasPrice的取值,通常的做法是在默认gasPrice上提高10%。
接下来,我们看一下运行以下代码返回的一些错误:
out of gas:你给的矿工费不够, 提高gasLimit
Insufficient funds forgas * price + value :交易发送账户的以太坊余额不够了,或者是你的以太坊余额不足以支付矿工费了(合约部署、通证转账)
not mined within 50blocks(Transaction was not mined within750 seconds):对不起,矿工很忙,挖矿打包要排队,最近50块可能轮不到你的交易了,但是这并不意味着你的交易会失败,那会不会打包呢?通常是会被打包的,只是等的时间长而已。记录transactionHash可以通过etherscan查看交易状态,也可以额外写个程序通过getTransaction/getTransactionReceipt获取最终交易状态
对于以太坊来说查询交易是开放的,不需要基于账户进行交易签名。
JavaScript中数字的最大长度−9007199254740992 and 9007199254740992 (即正负2的53次方),超过这个区间的数字需要转换为BigNumber操作。
以下为ERC20 Token余额查询的代码实例:
LoadAccount是我们进行以太坊转账交易的基础。Nonce默认值为getTransactionCount。
1)载入以太坊账户
2)获取Nonce,以太坊转账
1)dataEncoder
这是一个通用的智能合约ABI函数数据编码处理类,主要是调用web3.eth.abi.encodeFunctionCall对智能合约函数进行数据打包,而打包的数据则作为转账交易的参数。换句话讲就是,告诉EVM执行合约的哪个函数参数是怎样的。
2)EstimateGas
ContractWrapper是对基础合约函数的封装,这段代码封装了计算执行合约交易所需的Gas。主要调用myContract.methods.myMethod([param1[,param2[, ...]]]).estimateGas(options[, callback])
3)transfer
我们为什么要计算Gas?为什么不直接把gasLimit设置为4000000上限?因为以太坊交易是基于gasLimit先扣取费用的,如果所有交易都设置为gas上限,可以想象如果发起多笔交易的时候,对账户的ether余额来说是有相当压力的。
最后,附上以上分享的项目代码:https://github.com/nerverwind/web3-example
作者简介:
老吴,北京志顶科技有限公司技术总监(前端),区块链专家,资深全栈工程师。长期从事区块链应用开发研究,有丰富的Java、PHP、Javascript、Node.js区块链实战经验,近期主要基于Node.js进行以太坊钱包服务开发。
注:本文为区块链大本营(ID:blockchain_camp)原创,未经授权不得擅自转载,如要转载请联系营长,微信:qk15732632926