这是一个向Python开发人员介绍Web3.py(一个区块链/以太坊库)的基础知识的教程。我们知道在以太坊链上创建钱包是没有成本的,这就意味着我们可以通过以太坊寻找到许多获利的机会,比如通过多个钱包领取空投,参加IDO等等。那如果我们参加活动需要1000个钱包帐号,如果一个个手工操作的话,这样不仅会导致过程很繁琐可能最后的人工成本比收益高使我们错过很多的机会。目前有好几个平台提供在线网页端批量转账(个人不建议使用,毕竟转账是需要提供钱包密钥的会导致密钥泄露丢失财产)

所以,本次教程我将通过Web3.py与以太坊合约进行交互并完成交易。

一、什么是Web3.py

    Web3.py是连接以太坊的python库,它常见于去中心化应用程序 (dapps) 中,用于帮助发送交易、与智能合约交互、读取块数据以及各种其他用例。它的API从web3.js中派生而来,如果你用过web3.js,你会对它的API很熟悉。

一、初始化你的 Web3 实例,连接到对应的链RPC,比如eth,bsc,heco,okex等等。这里我写了一篇文章,收藏了各个链的rpc(rpc节点大全)

from web3 import Web3
my_provider = Web3(HTTPProvider("https://bsc-dataseed1.binance.org/"))

二、以太坊转账等上链操作,对于以太坊来说都是一笔交易,发送交易关键参数如下。

(1)、nonce – 这是账号的一个交易计数。

(2)、to – 目标账户。

(3)、value – 要发送的eth,bnb金额(根据链区分)。这个值必须以十六进制表示,单位必须是wei。我们可以使用Web3.js工具w3.toWei()转换单位。

(4)、gasLimit – 交易能消耗Gas的上限。像这样的基本交易总是要花费460869单位的Gas。

(5)、gasPrice – Gas价格,这里是 5Gwei。

txn_dict = {
            'to': self.to_address,
            'value': self.w3.toWei(amount_in_wei, 'wei'),
            'gas': 460869,
            'gasPrice': self.w3.toWei('5', 'gwei'),
            'nonce': nonce,
            'chainId': 56
}

三、交易关键方法

(1)、初始化您的合同对象

(2)、建立交易

(3)、使用signTransaction()签署交易

(4)、使用sendRawTransaction()广播事务

四、这里是我写好的一个在bsc链上批量转账BNB的demo 。one  -> many

privateJson.json格式:

{
        "privateKey": "XXXXXXXXXXXXXXXXX",
        "address": "XXXXXXXXXXXXXXXXXXXXXXXX"
    }

total.json格式:

[{
        "privateKey": "XXXXXXXXXXXXXXXXX",
        "address": "XXXXXXXXXXXXXXXXXXXXXXXX"
    }
]
import time
from web3 import Web3, HTTPProvider
import json
class BSC:
    def __init__(self, wallet_address, wallet_private_key, to_address='输入你默认转账的接收地址'):
        self.w3 = Web3(HTTPProvider("https://bsc-dataseed1.binance.org/"))
        self.wallet_address = wallet_address
        self.wallet_private_key = wallet_private_key
        self.to_address = to_address
    def send_ether_to_contract_BNB(self, amount_in_ether):
        if len(self.to_address) <= 0:
            print("接收为空!请检查")
            return
        amount_in_wei = self.w3.toWei(amount_in_ether, 'ether');
        nonce = self.w3.eth.getTransactionCount(self.wallet_address)
        txn_dict = {
            'to': self.to_address,
            'value': self.w3.toWei(amount_in_wei, 'wei'),
            'gas': 460869,
            'gasPrice': self.w3.toWei('5', 'gwei'),
            'nonce': nonce,
            'chainId': 56
        }
        signed_txn = self.w3.eth.account.signTransaction(txn_dict, self.wallet_private_key)
        txn_hash = self.w3.eth.sendRawTransaction(signed_txn.rawTransaction)
        txn_receipt = None
        count = 0
        while txn_receipt is None and (count < 30):
            try:
                txn_receipt = self.w3.eth.getTransactionReceipt(txn_hash)
                print(txn_receipt)
            except:
                pass
            time.sleep(5)
        if txn_receipt is None:
            return {'status': 'failed', 'error': 'timeout'}
        return {'status': 'added', 'txn_receipt': txn_receipt}
single_transfer_amount = 0.1
def run():
    with open("total.json", 'r') as f:
        readJson = json.loads(f.read())
    wallet_private_key = readJson[0]["privateKey"]
    wallet_address = readJson[0]["address"]
    print("本次转出钱包地址:" + wallet_address)
    for addressArr in readJson:
        to_address = addressArr["address"]
        print("本次转入钱包地址:" + to_address)
        bsc = BSC(wallet_address, wallet_private_key, to_address)
        bnb_account = float(bsc.w3.fromWei(bsc.w3.eth.getBalance(to_address),"ether"))
        bsc.send_ether_to_contract_BNB(single_transfer_amount)
run()

五、这里是我写好的一个在bsc链上批量回转的转账BNB的demo 。 many  -> one

import time
from web3 import Web3, HTTPProvider
import json
class BSC:
    def __init__(self, wallet_address, wallet_private_key, to_address='输入你默认转账的接收地址'):
        self.w3 = Web3(HTTPProvider("https://bsc-dataseed1.binance.org/"))
        self.wallet_address = wallet_address
        self.wallet_private_key = wallet_private_key
        self.to_address = to_address
    def send_ether_to_contract_BNB(self, amount_in_ether):
        if len(self.to_address) <= 0:
            print("接收为空!请检查")
            return
        amount_in_wei = self.w3.toWei(amount_in_ether, 'ether');
        nonce = self.w3.eth.getTransactionCount(self.wallet_address)
        txn_dict = {
            'to': self.to_address,
            'value': self.w3.toWei(amount_in_wei, 'wei'),
            'gas': 460869,
            'gasPrice': self.w3.toWei('5', 'gwei'),
            'nonce': nonce,
            'chainId': 56
        }
        signed_txn = self.w3.eth.account.signTransaction(txn_dict, self.wallet_private_key)
        txn_hash = self.w3.eth.sendRawTransaction(signed_txn.rawTransaction)
        txn_receipt = None
        count = 0
        while txn_receipt is None and (count < 30):
            try:
                txn_receipt = self.w3.eth.getTransactionReceipt(txn_hash)
                print(txn_receipt)
            except:
                pass
            time.sleep(5)
        if txn_receipt is None:
            return {'status': 'failed', 'error': 'timeout'}
        return {'status': 'added', 'txn_receipt': txn_receipt}
def run():
    to_address = "输入你默认转账的接收地址"
    with open("test_total.json", 'r') as f:
        readJson = json.loads(f.read())
    for addressArr in readJson:
        wallet_private_key = addressArr["privateKey"]
        wallet_address = addressArr["address"]
        print("本次转出钱包地址:" + wallet_address)
        print("本次转入钱包地址:" + to_address)
        bsc = BSC(wallet_address, wallet_private_key, to_address)
        bnb_account = float(bsc.w3.fromWei(bsc.w3.eth.getBalance(wallet_address),"ether"))
        bsc.send_ether_to_contract_BNB(bnb_account-0.005)
run()