零基础用python开发区块链(三web3.py)

简介

web3.py 是一个 Python 库,用于与以太坊区块链进行交互。它支持以太坊的各种功能,例如查询区块、发送交易、调用智能合约、与钱包交互等。web3.py 是基于 JavaScript 库 web3.js 的 Python 版本,广泛应用于构建以太坊 DApps 和与区块链交互的脚本。

核心功能

  • 账户管理:生成钱包、管理账户、签名消息和交易。
  • 交易:发送和签署交易,查询交易状态。
  • 智能合约:部署、调用合约,监听合约事件。
  • 区块链数据:查询区块、交易、账户余额等数据。

安装 web3.py

首先,确保你已经安装了 Python 和 pip。然后安装 web3.py

pip install web3

连接到以太坊网络

web3.py 允许你连接到各种以太坊节点(如本地节点、Infura 或 Alchemy 提供的远程节点)。以下是如何连接到 Infura 节点的示例。

from web3 import Web3

# 使用 Infura 的 URL 连接到以太坊网络
infura_url = 'https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID'
w3 = Web3(Web3.HTTPProvider(infura_url))

# 检查是否连接成功
if w3.isConnected():
    print("Connected to Ethereum network")
else:
    print("Failed to connect")

在这里,将 YOUR_INFURA_PROJECT_ID 替换为你从 Infura 获取的项目 ID。

1. 查询账户余额

使用 web3.py 可以轻松查询以太坊地址的余额。

address = '0xYourEthereumAddress'
balance = w3.eth.get_balance(address)
# 以太坊的最小单位是 Wei,转换为 Ether
ether_balance = w3.fromWei(balance, 'ether')
print(f"Account balance: {ether_balance} ETH")

2. 发送 ETH 转账

以下是如何通过 web3.py 从一个账户向另一个账户转账 ETH 的示例。你需要提供私钥、发送方和接收方地址。

from web3 import Web3

# 连接到 Infura 节点
infura_url = 'https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID'
w3 = Web3(Web3.HTTPProvider(infura_url))

# 设置发送者地址和私钥
from_address = '0xYourFromAddress'
private_key = 'YourPrivateKey'
to_address = '0xRecipientAddress'

# 获取发送者地址的 nonce
nonce = w3.eth.getTransactionCount(from_address)

# 构建交易
tx = {
    'nonce': nonce,
    'to': to_address,
    'value': w3.toWei(0.01, 'ether'),  # 转账金额
    'gas': 2000000,
    'gasPrice': w3.toWei('50', 'gwei'),  # gas 价格
    'chainId': 1  # 以太坊主网的 chain ID
}

# 使用私钥签署交易
signed_tx = w3.eth.account.sign_transaction(tx, private_key)

# 发送交易并获取交易哈希
tx_hash = w3.eth.sendRawTransaction(signed_tx.rawTransaction)
print(f"Transaction hash: {w3.toHex(tx_hash)}")

3. 与智能合约交互

3.1 部署智能合约

如果你有合约的 ABI(Application Binary Interface)和合约地址,可以使用 web3.py 与其交互。假设我们有一个简单的 ERC-20 合约的 ABI 和地址。

contract_abi = [
    # 这里粘贴合约的 ABI
]

contract_address = '0xContractAddress'
contract = w3.eth.contract(address=contract_address, abi=contract_abi)
3.2 调用智能合约的只读方法

假设我们调用一个 ERC-20 合约的 balanceOf 方法,查询某个地址的余额。

address_to_query = '0xSomeAddress'
balance = contract.functions.balanceOf(address_to_query).call()
print(f"Balance: {balance} tokens")
3.3 调用智能合约的写方法

对于需要改变区块链状态的合约调用(如转账代币),需要签署和发送交易。假设我们调用 transfer 方法,将代币发送给另一个地址。

# 获取发送者地址的 nonce
nonce = w3.eth.getTransactionCount(from_address)

# 构建代币转账交易
tx = contract.functions.transfer(to_address, 1000).buildTransaction({
    'nonce': nonce,
    'gas': 2000000,
    'gasPrice': w3.toWei('50', 'gwei'),
    'chainId': 1
})

# 使用私钥签署交易
signed_tx = w3.eth.account.sign_transaction(tx, private_key)

# 发送交易并获取交易哈希
tx_hash = w3.eth.sendRawTransaction(signed_tx.rawTransaction)
print(f"Transaction hash: {w3.toHex(tx_hash)}")

4. 查询区块链数据

你可以使用 web3.py 来查询以太坊区块链上的各种数据,如区块、交易和事件。

查询区块信息
latest_block = w3.eth.get_block('latest')
print(f"Latest block: {latest_block}")

查询交易详情

tx_hash = '0xTransactionHash'
transaction = w3.eth.get_transaction(tx_hash)
print(f"Transaction details: {transaction}")

5. 监听事件

你可以使用 web3.py 监听智能合约的事件。例如,监听某个合约的代币转账事件。

# 定义事件过滤器
transfer_filter = contract.events.Transfer.createFilter(fromBlock='latest')

# 轮询新事件
while True:
    for event in transfer_filter.get_new_entries():
        print(f"Transfer event: {event}")

web3.py 是一个功能强大的工具,可以用于与以太坊网络交互,支持发送交易、查询区块链数据、调用智能合约等。以下是常见的应用场景:

  • ETH 转账:通过私钥签署交易并发送 ETH。
  • 与智能合约交互:调用合约的读写方法,监听合约事件。
  • 查询区块链数据:查询区块、交易、账户余额等。

完整示例

from web3 import Web3
from web3.middleware import geth_poa_middleware

class EthereumDemon:
    def __init__(self, provider_url, private_key=None):
        self.w3 = Web3(Web3.HTTPProvider(provider_url))

        # 如果是PoA网络(如Binance Smart Chain),需要添加此中间件
        self.w3.middleware_onion.inject(geth_poa_middleware, layer=0)

        # 检查连接状态
        if not self.w3.isConnected():
            raise Exception("Failed to connect to Ethereum node")
        
        self.private_key = private_key
        self.from_address = self.w3.eth.account.privateKeyToAccount(private_key).address if private_key else None
    
    # 查询账户余额
    def get_balance(self, address):
        balance = self.w3.eth.get_balance(address)
        return self.w3.fromWei(balance, 'ether')
    
    # 发送ETH转账
    def send_eth(self, to_address, amount_in_ether):
        nonce = self.w3.eth.getTransactionCount(self.from_address)
        tx = {
            'nonce': nonce,
            'to': to_address,
            'value': self.w3.toWei(amount_in_ether, 'ether'),
            'gas': 2000000,
            'gasPrice': self.w3.toWei('50', 'gwei'),
            'chainId': 1  # 以太坊主网的chain ID为1
        }

        signed_tx = self.w3.eth.account.sign_transaction(tx, self.private_key)
        tx_hash = self.w3.eth.sendRawTransaction(signed_tx.rawTransaction)
        return self.w3.toHex(tx_hash)

    # 加载智能合约
    def load_contract(self, contract_address, contract_abi):
        return self.w3.eth.contract(address=contract_address, abi=contract_abi)

    # 调用智能合约的读方法(如balanceOf)
    def read_contract(self, contract, function_name, *args):
        contract_function = getattr(contract.functions, function_name)
        return contract_function(*args).call()

    # 调用智能合约的写方法(如transfer)
    def write_contract(self, contract, function_name, *args):
        nonce = self.w3.eth.getTransactionCount(self.from_address)
        contract_function = getattr(contract.functions, function_name)
        tx = contract_function(*args).buildTransaction({
            'nonce': nonce,
            'gas': 2000000,
            'gasPrice': self.w3.toWei('50', 'gwei'),
            'chainId': 1
        })

        signed_tx = self.w3.eth.account.sign_transaction(tx, self.private_key)
        tx_hash = self.w3.eth.sendRawTransaction(signed_tx.rawTransaction)
        return self.w3.toHex(tx_hash)

    # 监听智能合约事件
    def listen_for_events(self, contract, event_name):
        event_filter = getattr(contract.events, event_name).createFilter(fromBlock='latest')

        print(f"Listening for {event_name} events...")
        while True:
            for event in event_filter.get_new_entries():
                print(f"New {event_name} event: {event}")
    
    # 授权智能合约方法
    def approve(self, contract, spender_address, amount):
        return self.write_contract(contract, 'approve', spender_address, amount)

# 使用实例
if __name__ == "__main__":
    provider_url = 'https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID'
    private_key = 'YOUR_PRIVATE_KEY'

    demon = EthereumDemon(provider_url, private_key)

    # 1. 查询账户余额
    my_address = '0xYourEthereumAddress'
    balance = demon.get_balance(my_address)
    print(f"Balance: {balance} ETH")

    # 2. 转账ETH
    to_address = '0xRecipientAddress'
    tx_hash = demon.send_eth(to_address, 0.01)  # 转账0.01 ETH
    print(f"Transaction hash: {tx_hash}")

    # 3. 调用智能合约 - 读方法
    contract_address = '0xContractAddress'
    contract_abi = [...]  # 合约的ABI
    contract = demon.load_contract(contract_address, contract_abi)
    balance_of_address = demon.read_contract(contract, 'balanceOf', '0xAddressToQuery')
    print(f"Token balance: {balance_of_address}")

    # 4. 调用智能合约 - 写方法
    tx_hash = demon.write_contract(contract, 'transfer', to_address, 1000)  # 转账1000代币
    print(f"Transaction hash: {tx_hash}")

    # 5. 监听合约事件
    demon.listen_for_events(contract, 'Transfer')

代码解释

1. __init__ 函数:

初始化 EthereumDemon 类,连接到以太坊网络(例如通过 Infura)。支持使用私钥以允许签名交易。

2. get_balance 函数:

查询指定地址的 ETH 余额,并返回以 ether 为单位的余额。

3. send_eth 函数:

执行 ETH 的转账交易,要求提供接收者地址和转账金额(以 ETH 为单位),并返回交易哈希。

4. load_contract 函数:

根据合约地址和 ABI 加载智能合约对象。

5. read_contract 函数:

调用智能合约的只读方法,例如查询代币余额 (balanceOf)。

6. write_contract 函数:

调用智能合约的写方法,例如转账代币或其他需要改变链上状态的操作。

7. listen_for_events 函数:

监听智能合约事件,打印每次发生的事件。

8. approve 函数:

为智能合约授权操作,常用于 ERC-20 代币授权其他合约操作你的代币。

 运行步骤

  1. 使用 pip install web3 安装依赖。
  2. 替换示例代码中的 provider_url 为你自己的 Infura URL,private_key 为你自己钱包的私钥。
  3. 运行脚本,按照注释执行不同的功能。

注意事项

  • 安全性:不要在公开环境中暴露私钥,建议使用环境变量或安全存储机制。
  • Gas 设置:确保设置合理的 gasgasPrice,以避免交易失败或花费过多的 gas 费。
  • 监听事件listen_for_events 可能会持续运行,适用于需要实时监控智能合约事件的场景。

转载请注明出处,侵权必究

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值