智能合约 空投 nodejs调用web3js进行批量转账

======================

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文件。

  1. 创建文件夹,npm init。
  2. npm install安装各种依赖。或者待代码写完后,npm update,自动安装代码中所使用的所有依赖。不过自动安装的依赖版本可能比较老,可以等npm update后,再单独npm install需要高版本的依赖。
  3. 写代码。
  4. 步骤2,3可以颠倒,看个人习惯啦。
  5. node <文件名> 运行nodejs文件。也可以node <文件名> & 后台运行

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越高,成功速度越快,当然费用也越高。

                                      智能合约 空投 nodejs调用web3js进行批量转账_第1张图片

以我最近完成的一笔空投为例,我使用的gasLimit是60000,最终实际使用37976。我设定的gasPrice是10gwei。所以最终实际上付的gas = 37976 * 10gwei = 0.00037976ether。

给一个参考gasPrice和成功时间的网站:https://etherscan.io/gasTracker

3. nonce的概念:nonce指的是转账时,from转出方的钱包的第几次转出交易行为,从0开始计数。每次交易时要提供使用的nonce值。可以使用getTransactionCount获取下次交易要使用的nonce值。举个例子:

  1. 我有一个钱包a,又新创建一个新账户b,此时b的nonce是0。
  2. a向b转账3eth,此时b的nonce是0
  3. b向a转账0.5eth,此时使用的b的nonce是0,getTransactionCount()获取到b的nonce是1
  4. a向b转账1eth,此时获取到b的nonce是1
  5. b向a转账2eth,此时使用的b的nonce是1,getTransactionCount()获取到b的nonce值是2.

ps:

  1. 若提供的nonce值偏大,则交易一直处于untrack状态,直到把gap的nonce都使用后,该交易才会进行。
  2. 若提供的nonce偏小,报错nonce too low。
  3. 当一笔交易已发出,还未成功,即在pending状态时,可以使用相同nonce,提高gas,重新发送,将旧交易撤销,并发送新交易(成功率>50%,不一定能成功)。这个很有用。比如有一笔交易发错了,还未成功的时候,可以使用相同nonce,收款人是自己,发送0个代币或eth,提高gas,只需付手续费,就能把这个交易撤销(还是要花手续费的)。或者有个交易已经发出,但是gas比较低,一两天都没有成功,可以使用相同nonce,提高gas,相同的交易信息,重新发一遍,加快交易完成。
  4. nonce的错误:注意getTransactionCount只能获取到已经完成的交易数量。比如你现在已经完成1000笔,有10笔pending的交易,这时候你用getTransactionCount获取到的值应该是1001,若你用1001进行交易,可能就把原有的第1001笔交易给覆盖了,参考3。目前我没有找到解决方案,只能每次转账都记录nonce值。

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太少。

 

 

 

 

 

 

 

 

你可能感兴趣的:(智能合约,智能合约,空投,web3js,nodejs,批量转账)