Web3.py是面向以太坊区块链的Python库,用于和区块链进行数据互动。无论是普通转账,还是智能合约的写入,都可以认为是一笔交易(Transaction)。在区块链世界,可导致区块链数据发生变化的数据,可简单理解为一笔“交易”。
有两类方法可以用于发送一笔交易。 send_transaction() 和 send_raw_transaction().下面简单阐述一下这两类方法的区别。
A. 希望线下签署交易或者发送已签署的交易
sign_transaction + send_raw_transaction()
B. 打算所有交易都用同一个账户来发起,并节省一些代码行
B1. 设置construct_sign_and_send_raw_middleware(), 然后:
B2. 发送交易send_transaction()
C. 或者还可以
如果希望部署智能合约或者希望和智能合约互动,则可以:
C.1. 使用transact(), 底层还是自动调用的send_transaction()
C.2. 构建build_transaction() + 签署sign_transaction + 发送send_raw_transaction()
from web3 import Web3, HTTPProvider
import os
# 创建一个web3实例.
w3 = Web3(HTTPProvider("http://localhost:8545"))
print(f'w3 connected: {w3.is_connected()}')
pk = os.environ.get('PRIVATE_KEY')
print(f'pk: {pk}')
to_addr = "0x0000000000000000000000000000000000000000"
acct2 = w3.eth.account.from_key(pk)
print(f'acct2 address {acct2.address}')
#1. 构建一个新的交易
transaction = {
"from": acct2.address,
"to": to_addr,
"value": w3.to_wei(3,'ether'),
"nonce": w3.eth.get_transaction_count(acct2.address),
"gasPrice": (w3.eth.gas_price + 100000),
"gas": 21000,
}
#2. 用相应的私钥来签署交易
signed = w3.eth.account.sign_transaction(transaction, pk)
print(f'\nrawTrannsaction {signed.rawTransaction.hex()}')
#3. 发送已签署的交易
#balance = w3.eth.get_balance(acct2.address)
#print(f'\nbefore tx, balance at acct2 {acct2.address} is {balance}')
tx_hash = w3.eth.send_raw_transaction(signed.rawTransaction)
tx = w3.eth.get_transaction(tx_hash)
assert tx["from"] == acct2.address
#4. 查阅审视必要的结果
print(f'\ntransaction: {tx}\n')
balance = w3.eth.get_balance(acct2.address)
print(f'balance at acct2 {acct2.address} is {balance}')
balance = w3.eth.get_balance(to_addr)
print(f'balance at to_addr {to_addr} is {balance}')
这里有一点点违反直觉,需要注意的地方。send_transaction处理的是更原始的文本数据,如下:
({“from”:account,
“to": receiver,
"value": someEther})
相反,send_raw_transaction处理的,反而是对以上文本数据进行签署后,生成的数据(16进制形式)。 这里的raw,理解为“半生半熟”即可。