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
- Windstamp, https://github.com/windstamp