简介
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 代币授权其他合约操作你的代币。
运行步骤
- 使用
pip install web3
安装依赖。 - 替换示例代码中的
provider_url
为你自己的 Infura URL,private_key
为你自己钱包的私钥。 - 运行脚本,按照注释执行不同的功能。
注意事项
- 安全性:不要在公开环境中暴露私钥,建议使用环境变量或安全存储机制。
- Gas 设置:确保设置合理的
gas
和gasPrice
,以避免交易失败或花费过多的gas
费。 - 监听事件:
listen_for_events
可能会持续运行,适用于需要实时监控智能合约事件的场景。
转载请注明出处,侵权必究