
web3.py库学习笔记python与以太坊区块链交互的库通过web3.py可以构建去中心化应用、智能合约交互等。pip install web3安装一、配置web3库需要依托以太坊节点建立连接将这类连接统称为Providers并且存在多种配置方式。安装web3.py后就需要配置Provider和要用到的中间件。一ProviderTest Provider测试用的Providereth-tester用于入门和快速开发。内置存有以太币的测试账户并会将每一笔交易即时纳入区块中。fromweb3importWeb3,EthereumTesterProvider w3Web3(EthereumTesterProvider())w3.is_connected()输出TrueEthereumTesterProvider需要通过pip install web3[tester]安装Local Provider与以太坊进行交互最安全的方式是在自有硬件设备上运行以太坊客户端。对于本地运行的节点IPC 连接是安全性最高的选择同时也支持 HTTP 与 WebSocket 配置。主流客户端 Geth 默认开放 8545 端口用于处理 HTTP 请求8546 端口用于处理 WebSocket 请求。可按照下述方式连接本地节点:fromweb3importWeb3,AsyncWeb3# IPC 连接w3Web3(Web3.IPCProvider(./path/to/filename.ipc))w3.is_connected()# 输出True# HTTP 连接w3Web3(Web3.HTTPProvider(http://127.0.0.1:8545))w3.is_connected()# 输出True# Async HTTP 连接w3AsyncWeb3(Web3.AsyncHTTPProvider(http://127.0.0.1:8545))awaitw3.is_connected()# 输出True# WebSocket 连接w3awaitAsyncWeb3(AsyncWeb3.WebSocketProvider(ws://127.0.0.1:8546))awaitw3.is_connected()# 输出True# Async IPC 连接w3AsyncWeb3(AsyncWeb3.AsyncIPCProvider(./path/to/filename.ipc))awaitw3.is_connected()# 输出TrueRemote Provider可以通过指定端点来连接远程节点和本地节点的操作方式一致fromweb3importWeb3,AsyncWeb3# HTTP 连接w3Web3(Web3.HTTPProvider(https://your-provider-url))w3AsyncWeb3(AsyncWeb3.AsyncHTTPProvider(https://your-provider-url))w3awaitAsyncWeb3(AsyncWeb3.WebSocketProvider(wss://your-provider-url))web3库自带以下内置ProviderHTTPProvider用于连接基于HTTP与HTTPS协议的JSON-RPC服务器。IPCProvider用于连接基于IPC套接字的JSON-RPC服务器。AsyncHTTPProvider以异步方式连接基于HTTP与HTTPS协议的JSON-RPC服务器。AsyncIPCProvider通过持久连接以异步方式连接基于IPC套接字的JSON-RPC服务器。WebSocketProvider通过持久连接以异步方式连接基于WebSocket的JSON-RPC服务器。二中间件web3.py中间件采用洋葱模型每一层中间件作用于provider的incoming request和outgoing response。默认内置了多款中间件可以对中间件进行新增、注入、替换操作也可以移除、停用任意一款中间件- gas_price_strategy- ens_name_to_address- attrdict- validation- gas_estimate默认配置定义在web3/manager.py文件的get_default_middleware()方法中。AttributeDict用于将JSON-RPC响应转换为Python属性字典方便后续操作。class web3.middleware.AttributeDictMiddlewareENS Name to Address Resolution用于将将以太坊域名服务ENS域名解析为其指向的地址。例如w3.eth.send_transaction 函数支持在发送方from与接收方to字段中使用后缀为.eth的域名。class web3.middleware.ENSNameToAddressMiddlewareGas Price Strategy若已设置gas price策略且条件适用系统会为交易附加gasPrice参数。class web3.middleware.GasPriceStrategyMiddlewareBuffered Gas Estimate若交易参数中未设置gas参数本中间件会补充gas预估数值。设定规则为min(w3.eth.estimate_gas gas_buffer, gas_limit)其中gas_buffer默认数值为100000。classweb3.middleware.BufferedGasEstimateMiddlewareValidation用于验证交易参数是否符合要求。class web3.middleware.ValidationMiddleware使用示例# Anvil 默认使用 POA 共识注入 POA 中间件以正确解析区块w3.middleware_onion.inject(ExtraDataToPOAMiddleware,layer0)# 注入到中间件栈的 最外层 最先执行。中间件是洋葱结构layer 越小越靠外以太坊客户端geth在开发模式与Goerli测试网中采用了PoA原型机制该原型机制与以太坊黄皮书规范存在偏差。黄皮书规定每个区块内的额外数据字段长度上限为32字节而geth的PoA机制使用的数据长度超出了该限制因此此中间件会在返回区块数据前对其做小幅修改。二、API接口一基础APIWeb3类内置了诸多便捷的工具函数编解码工具Web3.is_encodable()Web3.to_bytes()Web3.to_hex()Web3.to_int()Web3.to_json()Web3.to_text()地址工具Web3.is_address()Web3.is_checksum_address()Web3.to_checksum_address()货币单位转换Web3.from_wei()Web3.to_wei()密码哈希运算Web3.keccak()Web3.solidity_keccak()二web3.eth 接口与以太坊交互最常用的接口均收纳在web3.eth命名空间下。数据获取查询账户余额get_balance、交易信息get_transaction以及区块数据get_block是web3.py最基础的常用操作。接口列表:web3.eth.get_balance()web3.eth.get_block()web3.eth.get_block_transaction_count()web3.eth.get_code()web3.eth.get_proof()web3.eth.get_storage_at()web3.eth.get_transaction()web3.eth.get_transaction_by_block()web3.eth.get_transaction_count()web3.eth.get_uncle_by_block()web3.eth.get_uncle_count()交易发送绝大多数常规场景可使用send_transaction接口或是sign_transaction和 send_raw_transaction组合。接口列表:web3.eth.send_transaction()web3.eth.sign_transaction()web3.eth.send_raw_transaction()web3.eth.replace_transaction()web3.eth.modify_transaction()web3.eth.wait_for_transaction_receipt()web3.eth.get_transaction_receipt()web3.eth.sign()web3.eth.sign_typed_data()web3.eth.estimate_gas()web3.eth.generate_gas_price()web3.eth.set_gas_price_strategy()三、合约web3.py 能够协助部署已发布的智能合约、读取合约数据或是调用合约中的函数。部署合约的前提是合约已完成编译且能够获取对应的字节码与应用二进制接口ABI。编译工作可在Remix平台完成也可借助Ape等各类合约开发框架实现。合约对象实例化完成后调用constructor中的transact方法即可部署合约实例ExampleContractw3.eth.contract(abiabi,bytecodebytecode)tx_hashExampleContract.constructor().transact()tx_receiptw3.eth.wait_for_transaction_receipt(tx_hash)tx_receipt.contractAddress0x8a22225eD7eD460D7ee3842bce2402B9deaD23D3将已部署合约加载至Contract对象后便可通过functions命名空间调用该合约内置函数deployed_contractw3.eth.contract(addresstx_receipt.contractAddress,abiabi)deployed_contract.functions.myFunction(42).transact()若需读取合约数据或是在本地预览交易执行结果无需在区块链网络上实际执行交易可以使用ContractFunction.call调用方法也可选用更为简洁的ContractCaller语法# Using ContractFunction.calldeployed_contract.functions.getMyValue().call()42# Using ContractCallerdeployed_contract.caller().getMyValue()42API列表web3.eth.contract()Contract.addressContract.abiContract.bytecodeContract.bytecode_runtimeContract.functionsContract.eventsContract.fallbackContract.constructor()Contract.encode_abi()web3.contract.ContractFunctionweb3.contract.ContractEvents四、事件、日志、过滤器如果想要对新挖出的区块或是合约触发的特定事件做出响应可以使用get_logs, subscriptions, 或者filters。API列表web3.eth.subscribe()web3.eth.filter()web3.eth.get_filter_changes()web3.eth.get_filter_logs()web3.eth.uninstall_filter()web3.eth.get_logs()Contract.events.your_event_name.create_filter()Contract.events.your_event_name.build_filter()Filter.get_new_entries()Filter.get_all_entries()Filter.get_all_entries()Filter.format_entry()Filter.is_valid_entry()五、网路API可从web3.net对象中获取一些基本的网路属性web3.net.listeningweb3.net.peer_countweb3.net.version六、其他ERC20 是以太坊上的代币标准 Ethereum Request for Comments #20定义了一组所有代币必须实现的函数接口。常见的 ERC20 代币USDT、USDC、UNI、LINK 等。ERC20 规定的核心函数包括balanceOf(address) 查询某地址的代币余额transfer(address, uint256) 转账approve(address, uint256) 授权他人使用你的代币transferFrom(address, address, uint256) 被授权人代为转账ERC20 代币本身就是一个智能合约 部署在以太坊上有自己的合约地址。代币余额不是存在你的钱包里而是记录在代币合约的存储中。abi Application Binary Interface应用二进制接口ABI是合约的函数说明书 ——告诉外部程序如何调用合约的函数。它描述了函数类型type: 定义函数的类型如function、“constructor”、“fallback”、“receive”(接收以太币)等。函数名称name: 帮助识别函数。函数参数inputs: 数组对象每个对象包括参数名称、参数类型、components如果是tuple类型。返回类型outputs: 指定函数调用返回的数据类型类似inputs。stateMutability: 定义函数是否会修改合约状态如nonpayable、“payable”、“view”、pure等。合约存储槽合约的存储槽storage slots是合约状态变量的存储位置。每个合约都有一个存储槽每个状态变量都有一个对应的存储槽合约的状态变量按声明顺序依次占用槽位。