4.1.10 Examples

Examples

以下是我们可能想要对web3执行的一些常见操作。

Looking up blocks

可以使用 <font color=red>web3.eth.getBlock</font> API通过数字或哈希查找区块。区块哈希应采用十六进制表示。区块号

# get a block by number
>>> web3.eth.getBlock(12345)
{
    'author': '0xad5c1768e5974c231b2148169da064e61910f31a',
    'difficulty': 735512610763,
    'extraData': '0x476574682f76312e302e302f6c696e75782f676f312e342e32',
    'gasLimit': 5000,
    'gasUsed': 0,
    'hash': '0x767c2bfb3bdee3f78676c1285cd757bcd5d8c272cef2eb30d9733800a78c0b6d',
    'logsBloom': '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
    'miner': '0xad5c1768e5974c231b2148169da064e61910f31a',
    'mixHash': '0x31d9ec7e3855aeba37fd92aa1639845e70b360a60f77f12eff530429ef8cfcba',
    'nonce': '0x549f882c5f356f85',
    'number': 12345,
    'parentHash': '0x4b3c1d7e65a507b62734feca1ee9f27a5379e318bd52ae62de7ba67dbeac66a3',
    'receiptsRoot': '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
    'sealFields': ['0x31d9ec7e3855aeba37fd92aa1639845e70b360a60f77f12eff530429ef8cfcba',
    '0x549f882c5f356f85'],
    'sha3Uncles': '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347',
    'size': 539,
    'stateRoot': '0xca495e22ed6b88c61714d129dbc8c94f5bf966ac581c09a57c0a72d0e55e7286',
    'timestamp': 1438367030,
    'totalDifficulty': 3862140487204603,
    'transactions': [],
    'transactionsRoot': '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
    'uncles': [],
}
# get a block by it's hash
>>> web3.eth.getBlock('0x767c2bfb3bdee3f78676c1285cd757bcd5d8c272cef2eb30d9733800a78c0b6d')
{...}

Getting the latest block

可以使用 <font color=red>web3.eth.getBlock</font> API 中的字符串 <font color=red>'latest'</font> 来检索最新的区块。

>>> web3.eth.getBlock('latest')
{...}

如果想知道最新的区块编号,可以使用 <font color=red>web3.eth.blockNumber</font> 属性。

>>> web3.eth.blockNumber
4194803

Currency conversions

Web3可以帮助我们在面额之间进行转换。支持以下面额。

denomination amount in wei
wei 1
kwei 1000
babbage 1000
femtoether 1000
mwei 1000000
lovelace 1000000
picoether 1000000
gwei 1000000000
shannon 1000000000
nanoether 1000000000
nano 1000000000
szabo 1000000000000
microether 1000000000000
micro 1000000000000
finney 1000000000000000
milliether 1000000000000000
milli 1000000000000000
ether 1000000000000000000
kether 1000000000000000000000
grand 1000000000000000000000
mether 1000000000000000000000000
gether 1000000000000000000000000000
tether 1000000000000000000000000000000
>>> web3.toWei('1', 'ether')
1000000000000000000
>>> web3.fromWei('1000000000000000000', 'ether')
Decimal('1')
>>> from_wei(123456789, 'ether')
Decimal('1.23456789E-10')

Looking up transactions

可以使用 <font color=red>web3.eth.getTransaction</font> 函数查找交易。

>>> web3.eth.getTransaction('0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060')
{
    'blockHash': '0x4e3a3754410177e6937ef1f84bba68ea139e8d1a2258c5f85db9f1cd715a1bdd',
    'blockNumber': 46147,
    'condition': None,
    'creates': None,
    'from': '0xa1e4380a3b1f749673e270229993ee55f35663b4',
    'gas': 21000,
    'gasPrice': 50000000000000,
    'hash': '0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060',
    'input': '0x',
    'networkId': None,
    'nonce': 0,
    'publicKey': '0x376fc429acc35e610f75b14bc96242b13623833569a5bb3d72c17be7e51da0bb58e48e2462a59897cead8ab88e78709f9d24fd6ec24d1456f43aae407a8970e4',
    'r': '0x88ff6cf0fefd94db46111149ae4bfc179e9b94721fffd821d38d16464b3f71d0',
    'raw': '0xf86780862d79883d2000825208945df9b87991262f6ba471f09758cde1c0fc1de734827a69801ca088ff6cf0fefd94db46111149ae4bfc179e9b94721fffd821d38d16464b3f71d0a045e0aff800961cfce805daef7016b9b675c137a6a41a548f7b60a3484c06a33a',
    's': '0x45e0aff800961cfce805daef7016b9b675c137a6a41a548f7b60a3484c06a33a',
    'standardV': '0x1',
    'to': '0x5df9b87991262f6ba471f09758cde1c0fc1de734',
    'transactionIndex': 0,
    'v': '0x1c',
    'value': 31337,
}

如果找不到给定哈希的交易,则此函数将返回 <font color=red>None</font>。

Working with Contracts

鉴于存储在 contract.sol 中的以下 solidity 源文件。

contract StoreVar {

    uint8 public _myVar;
    event MyEvent(uint indexed _var);

    function setVar(uint8 _var) public {
        _myVar = _var;
        MyEvent(_var);
    }

    function getVar() public view returns (uint8) {
        return _myVar;
    }

}

以下示例演示了一些事项:

  • 从 sol 文件编译合约。
  • 估算交易的 gas 成本。
  • 用合约函数进行交易。
  • 等待开采交易收据。
import sys
import time
import pprint

from web3.providers.eth_tester import EthereumTesterProvider
from web3 import Web3
from solc import compile_source


def compile_source_file(file_path):
   with open(file_path, 'r') as f:
      source = f.read()

   return compile_source(source)


def deploy_contract(w3, contract_interface):
    tx_hash = w3.eth.contract(
        abi=contract_interface['abi'],
        bytecode=contract_interface['bin']).deploy()

    address = w3.eth.getTransactionReceipt(tx_hash)['contractAddress']
    return address


def wait_for_receipt(w3, tx_hash, poll_interval):
   while True:
       tx_receipt = w3.eth.getTransactionReceipt(tx_hash)
       if tx_receipt:
         return tx_receipt
       time.sleep(poll_interval)


w3 = Web3(EthereumTesterProvider())

contract_source_path = 'contract.sol'
compiled_sol = compile_source_file('contract.sol')

contract_id, contract_interface = compiled_sol.popitem()

address = deploy_contract(w3, contract_interface)
print("Deployed {0} to: {1}\n".format(contract_id, address))

store_var_contract = w3.eth.contract(
   address=address,
   abi=contract_interface['abi'])

gas_estimate = store_var_contract.functions.setVar(255).estimateGas()
print("Gas estimate to transact with setVar: {0}\n".format(gas_estimate))

if gas_estimate < 100000:
  print("Sending transaction to setVar(255)\n")
  tx_hash = store_var_contract.functions.setVar(255).transact()
  receipt = wait_for_receipt(w3, tx_hash, 1)
  print("Transaction receipt mined: \n")
  pprint.pprint(dict(receipt))
else:
  print("Gas cost exceeds 100000")

Interacting with an ERC20 Contract

ERC20(正式的 EIP20)代币标准是以太坊中使用最广泛的标准。以下是检查ERC20代币合约当前状态的方法。

首先,创建表示ERC20合约的Python对象。对于这个例子,我们将检查 Unicorns 代币合约。

>>> import json
>>> from web3.auto.infura import w3

>>> ERC20_ABI = json.loads('[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_spender","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Approval","type":"event"}]')  # noqa: 501

# Address field should be the checksum address at which the ERC20 contract was deployed
>>> erc20 = w3.eth.contract(address='0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7', abi=ERC20_ABI)

获取有关ERC20合约当前状态的各种数据。

>>> erc20.functions.name().call()
'Unicorns'
>>> erc20.functions.symbol().call()
'🦄'
>>> erc20.functions.decimals().call()
0
>>> erc20.functions.totalSupply().call()
2039

获取帐户地址的余额。

>>> erc20.functions.balanceOf('0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb').call()
1

从帐户地址的令牌余额计算令牌计数。

>>> from decimal import Decimal

# Most applications expect *exact* results, so using the Decimal library,
# with default precision of 28, is usually sufficient to avoid any rounding error.
>>> decimals = erc20.functions.decimals().call()
>>> balance = erc20.functions.balanceOf('0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb').call()
>>> balance / Decimal(10 ** decimals)
Decimal('1')

余额始终是货币最小自然单位的整数(相当于 ether 的'wei')。代币余额通常仅用于后端计算。

代币计数可以是货币主要单位中的整数或分数(相当于 ether 的'eth')。代币计数通常在前端显示给用户,因为它更具可读性。

项目源代码

项目源代码会逐步上传到 Github,地址为 https://github.com/windstamp/jsonrpc

Contributor

  1. Windstamp, https://github.com/windstamp

Reference

  1. https://web3py.readthedocs.io/en/stable/
  2. http://web3py.readthedocs.io
  3. https://github.com/ethereum/web3.py
  4. https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
  5. https://etherscan.io/token/0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容