看到网上很多关于以太坊批量转账的文章,都没有一篇完整的代码实例讲解一下关于ETH批量转账的实现,想当年我也是因为这样费了大量时间去从头开始了解ETH才搞定的,而有时候我们做开发的需求并不需要去精通一样东西,只需要知道怎么用就行,效率嘛,最重要,对吧,而有可能因为效率耽误了进程而被领导批头一顿大骂,一天心情都没了,还怎么好好工作对吧。
看图这肯定是你们需要的,我是基于eth ropsten测试。
ropsten.etherscan.io/tx/0xe382252b45073788e015d6d7e3e4847cef540ed24fa0e4c3ec43f8adaf4cd210
图中从form转账转入多个地址to里面实现了3笔转账,实际消耗0.2退回0.78多余不用的
好了,需求分析完毕,我们开始
首先要做eth开发,你得先了解web3.js,你想要开发智能合约得了解solidity,你想用python开发eth得了解web3py,你想要搭建私链得了解geth、以太坊的网络和parity
至于详细的解说我这里就不啰嗦了,你都搜索到批量转账了说明你已经有一定开发基础了。
至于从solidity智能合约编译到部署到调用,我这里就懒得讲了,网上有更多详细的教程。
这里有一个歪果仁开源的一套批量转账dapp,里面有详细的eth转账和token代币转账的代码实现,可以去参考,它也有详细的说明文档,还打包成了DAPP供你测试
github.com/rstormsf/multisender
而它是基于we3.js开发的,这里我们主要讲web3py的开发,开发我们需要测试账户,需要ETH余额,还有用于we3连接的私链节点。
这里我使用的是infura的ropsten测试网络
至于测试账户,我使用的是Metamask metamask.io插件
ropsten需要领取测试币,领取方法
点击右上角的头像,创建账户,或者选择默认账户
点中间选择 ropsten测试网络
点击Buy按钮
点击获取记得得到测试币,每次一个,最多5个
好了,账户有了,我们还需要转账的私钥
点击右边的...竖着的3个点,即可查看账户详情
然后导出私钥即可
接下来就是使用we3py实现转账操作,直接上代码
#!/usr/bin/python3
# -*- coding: utf-8 -*-
from web3 import Web3
import json
#这里我使用的是infura的ropsten测试网络
web3 = Web3(Web3.HTTPProvider("https://ropsten.infura.io/v3/cf9f29fb4f674714be8047085920bbd9"))
# Metamask转账账户
fromAddress = web3.toChecksumAddress("0xa22fAF9Ad34c9B7b7dFc1520CBffc3fe4dEe1EE8")
# Metamask账户私钥
private_key = "0x6442818855fd7dc3429351a8c35fee52245a26880e5e0ea638fa69322a9fe781"
# 定义批量转账合约
multiSenderAddr = web3.toChecksumAddress("0xa5025faba6e70b84f74e9b1113e5f7f4e7f4859f")
multiSenderAbi = []
with open("./abis/StormMultisender.json", 'r', encoding='utf8') as data:
multiSenderAbi = json.load(data)
#定义智能合约对象
multi_sender = web3.eth.contract(address=multiSenderAddr, abi=multiSenderAbi)
#取得当前汽体价格
gas_price = web3.eth.gasPrice
# 取得转账账户的交易nonce数据
nonce = web3.eth.getTransactionCount(fromAddress)
# 转账eth
addresses_to_send = ["0x5844de50Cf99F95ca073AC7B205f9C0C75E827A8", "0x8775039fCa840bde05519E4a743B2973F3C30B24"]
balances_to_send = [web3.toWei(0.1, "ether"), web3.toWei(0.1, "ether")]
# 构建交易数据
txn = multi_sender.functions.multisendEther(addresses_to_send, balances_to_send).buildTransaction({
"from": fromAddress,
"gasPrice": web3.toHex(web3.toWei(90, "Gwei")),# 指定汽体价格
"gas": web3.toHex(210000),# 限制使用汽体最大量
"value": web3.toHex(web3.toWei(1, "ether")),# 发送总额必须大于转账金额+手续费否则会打包失败
"nonce": nonce # 防重放nonce,这个是必须的
})
print(txn)
# 发送交易
signed_txn = web3.eth.account.signTransaction(txn, private_key=private_key)
# 发送到网络打包,如果报错 already known 就是上一笔交易正在打包,需要打包完成才能下一笔
web3.eth.sendRawTransaction(signed_txn.rawTransaction)
# 取得转账哈希
txhash = web3.toHex(web3.sha3(signed_txn.rawTransaction))
# 打印交易哈希类似 0xe382252b45073788e015d6d7e3e4847cef540ed24fa0e4c3ec43f8adaf4cd210
print(txhash)
代码里需要注意一下,./abis/StormMultisender.json这个文件是该智能合约得ABI数据,获得方式在它的github源码里github.com/rstormsf/multisender/tree/master/src/abis
也可以通过ropsten.etherscan.io浏览器查询0xa5025faba6e70b84f74e9b1113e5f7f4e7f4859f这个地址获得合约得ABI
还需要注意buildTransaction里的参数value的转账数量必须大于你批量转账的数量并加上可能消耗的eth手续费,否则会打包失败
可以在构建交易数据 txn之前加入以下代码计算可能消耗的 gas
# 构建转账数据
encodedData = multi_sender.encodeABI(fn_name="multisendToken",args=[token_address, addresses_to_send, balances_to_send])
# 取得需要消耗的汽体,这里时灵时不灵,经常报错
gas = web3.eth.estimateGas({
"from": fromAddress,
"data": encodedData,
"value": web3.toHex(web3.toWei(0.1, "ether")),
"to": multiSenderAddr
})
这里合约是使用它已经部署好的合约地址进行测试,有兴趣自己编译合约并上线部署成自己专用合约的可以参考它的源码目录下 multisender/contracts/flats/UpgradebleStormSender_flat.sol
这个文件,然后拷贝到remix.ethereum.org 编译测试,参考其multisendToken和multisendEther这两个方法