======================
2018年11月更新,已换工作方向,不再做智能合约相关
======================
4月底换了份工作,新公司发行了一个基于eth的代币。现在我的工作内容除了写网站后端,还负责空投。
在空投这方面,目前我使用的方法有两种:使用nodejs调用web3js接口,或者使用java调用web3j。
前段时间公司代币要上fcoin交易所,我负责向45000个地址进行空投,用的是github代码批量空投的加强版。平时公司有点小活动,向百以内的中奖者发奖的时候,我都是直接用的批量空投这段代码。这篇文章讲一下怎么使用nodejs调用web3js进行空投。
代码我已经上传到github(web3版本号1.0.0-beta.34)。一个是批量进行空投,另一个是单次进行转账。web3js api:
for English: https://web3js.readthedocs.io/en/1.0/ (推荐使用,中文版的翻译比较奇怪,而且更新不及时)
for Chinese: http://web3.tryblockchain.org/
如果只是使用,而且有js基础的,可以直接配合api看代码。如果想看我踩了那些坑,还有(比较)详细讲解的,可以继续往后看。
下边的讲解都是基于mac os 系统。首先简单讲一下怎么运行nodejs文件。
web3js的各种坑:
1. 版本问题:刚开始写的时候,网上查到一些简单现成的代码。但是运行总是出错。问题在哪里呢?版本!web3js在不同版本里,语法,接口是有不一样的。举几个例子,这时候就体会到了api的重要性。面向api编程吧。
var privateKey = new Buffer("", 'hex'); |
var privateKey = new Buffer.from("", 'hex'); |
|
web3.sendRawTransaction |
web3.sendSignedTransaction |
|
let MyContract = web3.eth.contract(abi); let contractInstance = MyContract.at(contractAddr); |
let contractInstance = new web3.eth.Contract(abi, contractAddr); |
|
web3.sha3(function签名) |
web3.utils.sha3(function签名) |
2. 转账的时候,转账发起人要付gas手续费,使用以太来支付。这里有两个概念:gasPrice和gasLimit。gasLimit意思是为了完成这笔转账,你愿意付多少份钱。gasPrice是每份值多少ether。最终使用的gas = gasPrice * 实际使用的gasLimit。使用同种代币转账时,使用的gasLimit大约是固定的(举个例子,我现在公司的代币转账,我固定gasLimt为60000,实际用的gasLimt是37976和52848左右,特别固定,这两种情况二选一)。使用的gasPrice越高,成功速度越快,当然费用也越高。
以我最近完成的一笔空投为例,我使用的gasLimit是60000,最终实际使用37976。我设定的gasPrice是10gwei。所以最终实际上付的gas = 37976 * 10gwei = 0.00037976ether。
给一个参考gasPrice和成功时间的网站:https://etherscan.io/gasTracker
3. nonce的概念:nonce指的是转账时,from转出方的钱包的第几次转出交易行为,从0开始计数。每次交易时要提供使用的nonce值。可以使用getTransactionCount获取下次交易要使用的nonce值。举个例子:
ps:
4. ropsten和mainnet使用相同接口得到的返回信息和报错不一样:刚开始智能合约开发时候,这个绝对是排行在web3版本造成代码调试出err之后的大坑第二名!写空投的时候,我一直都是在ropsten上进行测试。自己在ropsten上发行了一个BTA的代币,创建了5个测试账号,天天互相发币玩。本以为各种坑,各种报错都已经模拟到,但是!但是!当要上线前,改成mainnet,what?怎么各种错!连相同error的报错信息都长得不一样!这真是很坑了。
5. 检验转账是否成功(前提:已经发出到以太坊):sendSignedTransaction的回调里有(err, value)。个人的理解是,如果这个err能抓到的错误,就没有发送到以太坊。这个地方出现错误,根据我的经验,肯定是代码写错了(大多都是代码有问题,参数没给够),nonce太低,或钱包钱不够了。如果这个err没抓到错误,生成了txhash,那就发送到以太坊了。不过不一定能成功,原因有gas太低等。交易成功时间取决于你给的gas多少和以太坊拥堵情况,参考6。sendSignedTransaction有一个eventEmitter叫做receipt,它是有等待时间的。如果超过750秒还没有成功,或者50个区块没有被mined,它就报错了
Transaction was not mined within 50 blocks, please make sure your transaction was properly send. Be aware that it might still be mined!
但这只是他的回调不监视这个交易了而已,还是有可能成功的。需要自己根据txhash查询。所以,保存txhash很重要,可以使用getTransaction进行检查。
注意:这里有个坑:ropsten和mainnet的返回结果结构不一样。要做成批量自动化校验的,要注意这个问题。
6. 估计gasPrice:使用estimateGas接口。参数
web3.eth.estimateGas({
"from" : fromAddr,
"nonce": noncehex,
"to" : contractAddress,
"data" : data
})
很奇怪的是,这个接口估算出的值,在mainnet上特别好使,在ropsten上,会报错gas太少。