Web3.py Python代码库¶
概览¶
Web3.py是一组代码库,允许开发者使用Python,并通过HTTP、IPC或WebSocket协议与以太坊节点交互。Moonbeam拥有与以太坊相似的API供用户使用,其与以太坊风格的JSON RPC调用完全兼容。因此,开发者可以利用此兼容特性并使用Web3.py库与Moonbeam节点交互,与在以太坊操作相同。
在本教程中,您将学习如何使用Web3.py库在Moonbase Alpha上发送交易和部署合约。本教程也同样适用于Moonbeam、Moonriver或Moonbeam开发节点。
查看先决条件¶
在开始本教程示例之前,您将需要提前准备以下内容:
- 具有拥有一定数量资金的账户。 您可以每24小时一次从Moonbase Alpha水龙头上获取DEV代币以在Moonbase Alpha上进行测试
- 要在Moonbeam或Moonriver网络上测试本指南中的示例,您可以从受支持的网络端点提供商之一获取您自己的端点和API密钥。
注意事项
本教程示例基于Ubuntu 18.04和MacOS的环境,用户需根据其所使用的Windows版本进行微调。
创建Python项目¶
首先,您需要创建一个目录,以存储您在本教程中将要创建的所有文件:
mkdir web3-examples && cd web3-examples
在本教程中,您将需要安装Web3.py代码库和Solidity编译器。您可以通过运行以下命令来安装两者的安装包:
pip3 install web3 py-solc-x
在Moonbeam上设置Web3.py¶
您可以为任何Moonbeam网络配置Web3.py。 要为Moonbeam或Moonriver网络配置您的项目,您可以从受支持的网络端点提供商之一获取您自己的端点和API密钥。
每个网络最简单的设置方式如下所示:
from web3 import Web3
web3 = Web3(Web3.HTTPProvider('INSERT_RPC_API_ENDPOINT')) # Insert your RPC URL here
from web3 import Web3
web3 = Web3(Web3.HTTPProvider('INSERT_RPC_API_ENDPOINT')) # Insert your RPC URL here
from web3 import Web3
web3 = Web3(Web3.HTTPProvider('https://rpc.api.moonbase.moonbeam.network'))
from web3 import Web3
web3 = Web3(Web3.HTTPProvider('http://127.0.0.1:9944'))
发送交易¶
在这一部分,您将需要创建一些脚本。第一个脚本将用于发送交易前查看账户余额。第二个脚本将执行交易。
您也可以使用余额脚本在交易发送后查看账户余额。
查看余额脚本¶
您仅需要一个文件以查看交易发送前后两个地址的余额。首先,您可以运行以下命令创建一个balances.py
文件:
touch balances.py
接下来,您将为此文件创建脚本并完成以下步骤:
-
定义
address_from
和address_to
变量 -
使用
web3.eth.get_balance
函数获取账户余额并使用web3.from_wei
格式化结果
# 1. Add import
from web3 import Web3
# 1. Add the Web3 provider logic here:
provider_rpc = {
'development': 'http://localhost:9944',
'alphanet': 'https://rpc.api.moonbase.moonbeam.network',
}
web3 = Web3(Web3.HTTPProvider(provider_rpc['development'])) # Change to correct network
# 2. Create address variables
address_from = 'ADDRESS_FROM_HERE'
address_to = 'ADDRESS_TO_HERE'
# 3. Fetch balance data
balance_from = web3.from_wei(web3.eth.getBalance(address_from), 'ether')
balance_to = web3.from_wei(web3.eth.getBalance(address_to), 'ether')
print(f'The balance of { address_from } is: { balance_from } ETH')
print(f'The balance of { address_to } is: { balance_to } ETH')
您可以运行以下命令以运行脚本并获取账户余额:
python3 balances.py
如果成功,发送地址和接收地址的余额将以ETH为单位显示在终端。
发送交易脚本¶
您仅需要一个文件即可在账户之间执行交易。在本示例中,您将从拥有私钥的发送地址转移1个DEV Token至另一个地址。首先,您可以运行以下命令创建一个transaction.py
文件:
touch transaction.py
接下来,您将为此文件创建脚本并完成以下步骤:
-
导入将在接下来的步骤中使用的
rpc_gas_price_strategy
以获取用于交易的gas价格 -
定义
account_from
,包括private_key
和address_to
变量。此处需要私钥以签署交易。请注意:此处操作仅用于演示目的,请勿将您的私钥存储在Python文件中 -
使用Web3.py Gas Price API设置gas价格策略。在本示例中,您将使用导入的
rpc_gas_price_strategy
-
使用
web3.eth.account.sign_transaction
函数创建和签署交易,传入交易的nonce
、gas
、gasPrice
、to
和value
以及发送者的private_key
。您可以通过web3.eth.get_transaction_count
函数并传入发送者地址获取nonce
。您可以通过web3.eth.generate_gas_price
函数预设gasPrice
。您可以通过web3.to_wei
函数将数字格式化成以Wei为单位的易读数字 -
使用
web3.eth.send_raw_transaction
函数发送已签署交易,然后使用web3.eth.wait_for_transaction_receipt
函数等待获取交易回执
# 1. Add imports
from web3.gas_strategies.rpc import rpc_gas_price_strategy
from web3 import Web3
# 2. Add the Web3 provider logic here:
provider_rpc = {
'development': 'http://localhost:9944',
'alphanet': 'https://rpc.api.moonbase.moonbeam.network',
}
web3 = Web3(Web3.HTTPProvider(provider_rpc['development'])) # Change to correct network
# 3. Create address variables
account_from = {
'private_key': 'YOUR_PRIVATE_KEY_HERE',
'address': 'PUBLIC_ADDRESS_OF_PK_HERE',
}
address_to = 'ADDRESS_TO_HERE'
print(
f'Attempting to send transaction from { account_from["address"] } to { address_to }'
)
# 4. Set the gas price strategy
web3.eth.set_gas_price_strategy(rpc_gas_price_strategy)
# 5. Sign tx with PK
tx_create = web3.eth.account.sign_transaction(
{
'nonce': web3.eth.get_transaction_count(account_from['address']),
'gasPrice': web3.eth.generate_gas_price(),
'gas': 21000,
'to': address_to,
'value': web3.to_wei('1', 'ether'),
},
account_from['private_key'],
)
# 6. Send tx and wait for receipt
tx_hash = web3.eth.send_raw_transaction(tx_create.rawTransaction)
tx_receipt = web3.eth.wait_for_transaction_receipt(tx_hash)
print(f'Transaction successful with hash: { tx_receipt.transactionHash.hex() }')
您可以在终端运行以下命令以运行脚本:
python3 transaction.py
如果交易成功,您将在终端看到显示的交易哈希。
您也可以使用balances.py
脚本为发送地址和接收地址查看余额是否变化。整体操作流程如下所示:
部署合约¶
在下几个部分中您将要编译和部署的合约是一个简单的增量合约,命名为Incrementer.sol
。您可以先为合约创建一个文件:
touch Incrementer.sol
接下来,您可以添加Solidity代码至文件:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Incrementer {
uint256 public number;
constructor(uint256 _initialNumber) {
number = _initialNumber;
}
function increment(uint256 _value) public {
number = number + _value;
}
function reset() public {
number = 0;
}
}
constructor
函数将在合约部署时运行,设置存储在链上的数字变量的初始值(默认值为0)。increment
函数将提供的_value
添加至当前数字,但是需要发送一个交易以修改存储的数据。最后,reset
函数将存储的数值重置为零。
注意事项
此合约为简单示例,仅供演示使用,其数值无实际意义。
编译合约脚本¶
在这一部分,您将创建一个脚本,此脚本使用Solidity编译器为Incrementer.sol
合约输出字节码和接口(ABI)。首先,您可以运行以下命令创建一个compile.py
文件:
touch compile.py
接下来,您将为此文件创建脚本并完成以下步骤:
-
导入
solcx
程序包 -
(可选)如果您还未安装Solidity编译器,您可以通过
solcx.install_solc
函数进行安装 -
使用
solcx.compile_files
函数编译Incrementer.sol
函数 -
导出合约的ABI和字节码
# 1. Import solcx
import solcx
# 2. If you haven't already installed the Solidity compiler, uncomment the following line
# solcx.install_solc()
# 3. Compile contract
temp_file = solcx.compile_files(
'Incrementer.sol',
output_values=['abi', 'bin'],
# solc_version='0.8.19'
)
# 4. Export contract data
abi = temp_file['Incrementer.sol:Incrementer']['abi']
bytecode = temp_file['Incrementer.sol:Incrementer']['bin']
部署合约脚本¶
有了用于编译Incrementer.sol
合约的脚本,您就可以使用结果以发送部署的签名交易。首先,您可以为部署的脚本创建一个名为deploy.py
的文件:
touch deploy.py
接下来,您将为此文件创建脚本并完成以下步骤:
-
导入ABI和字节码
-
定义
account_from
,包括private_key
变量。此私钥将用于签署交易。请注意:此处操作仅用于演示目的,请勿将您的私钥存储在Python文件中 -
使用
web3.eth.contract
函数并传入合约的ABI和字节码创建合约实例 -
使用合约实例并传入需要增量的数值创建构造交易。在本示例中,您可以将数值设置为
5
。随后,您将使用build_transaction
函数传入交易信息,包括发送者的from
和nonce
。您可以通过web3.eth.get_transaction_count
函数获取nonce
-
使用
web3.eth.account.sign_transaction
函数签署交易并传入构造交易和发送者的private_key
-
使用
web3.eth.send_raw_transaction
函数发送已签署交易,然后使用web3.eth.wait_for_transaction_receipt
函数等待获取交易回执
# 1. Add imports
from compile import abi, bytecode
from web3 import Web3
# 2. Add the Web3 provider logic here:
provider_rpc = {
'development': 'http://localhost:9944',
'alphanet': 'https://rpc.api.moonbase.moonbeam.network',
}
web3 = Web3(Web3.HTTPProvider(provider_rpc['development'])) # Change to correct network
# 3. Create address variable
account_from = {
'private_key': 'YOUR_PRIVATE_KEY_HERE',
'address': 'PUBLIC_ADDRESS_OF_PK_HERE',
}
print(f'Attempting to deploy from account: { account_from["address"] }')
# 4. Create contract instance
Incrementer = web3.eth.contract(abi=abi, bytecode=bytecode)
# 5. Build constructor tx
construct_txn = Incrementer.constructor(5).build_transaction(
{
'from': account_from['address'],
'nonce': web3.eth.get_transaction_count(account_from['address']),
}
)
# 6. Sign tx with PK
tx_create = web3.eth.account.sign_transaction(construct_txn, account_from['private_key'])
# 7. Send tx and wait for receipt
tx_hash = web3.eth.send_raw_transaction(tx_create.rawTransaction)
tx_receipt = web3.eth.wait_for_transaction_receipt(tx_hash)
print(f'Contract deployed at address: { tx_receipt.contractAddress }')
您可以在终端运行以下命令以运行脚本:
python3 deploy.py
如果成功,合约地址将显示在终端。
读取合约数据(调用函数){: #read-contract-data }¶
调用函数是无需修改合约存储(更改变量)的交互类型,这意味着无需发送交易,只需读取已部署合约的各种存储变量。
首先,您需要创建一个文件并命名为get.py
:
touch get.py
接下来,您可以遵循以下步骤创建脚本:
-
导入ABI
-
定义
account_from
,包括private_key
变量。此私钥将用于签署交易。请注意:此处操作仅用于演示目的,请勿将您的私钥存储在Python文件中 -
使用
web3.eth.contract
函数并传入已部署合约的ABI和地址创建合约实例 -
使用合约实例,您随后可以调用
number
函数
# 1. Import the ABI
from compile import abi
from web3 import Web3
# 2. Add the Web3 provider logic here:
provider_rpc = {
'development': 'http://localhost:9944',
'alphanet': 'https://rpc.api.moonbase.moonbeam.network',
}
web3 = Web3(Web3.HTTPProvider(provider_rpc['development'])) # Change to correct network
# 3. Create address variable
contract_address = 'CONTRACT_ADDRESS_HERE'
print(f'Making a call to contract at address: { contract_address }')
# 4. Create contract instance
Incrementer = web3.eth.contract(address=contract_address, abi=abi)
# 5. Call Contract
number = Incrementer.functions.number().call()
print(f'The current number stored is: { number } ')
您可以在终端运行以下命令以运行脚本:
python3 get.py
如果成功,数值将显示在终端。
交互合约(发送函数){: #interact-with-contract }¶
发送函数是修改合约存储(更改变量)的交互类型,这意味着需要签署和发送交易。在这一部分,您将创建两个脚本:一个是增量,另一个是重置增量器。首先,您可以为每个脚本创建一个文件,并分别命名为increment.py
和reset.py
:
touch increment.py reset.py
接下来,打开increment.py
文件并执行以下步骤以创建脚本:
-
导出ABI
-
定义
account_from
,包括private_key
、已部署合约contract_address
以及要增量的value
。此私钥将用于签署交易。请注意:此处操作仅用于演示目的,请勿将您的私钥存储在Python文件中 -
使用
web3.eth.Contract
函数并传入已部署合约的ABI和地址以创建合约实例 -
使用合约实例和传入要增量的数值创建构造交易。随后,您将使用
build_transaction
函数传入交易信息,包括发送者的from
地址和nonce
。您可以通过web3.eth.get_transaction_count
函数获取nonce
-
使用
web3.eth.account.sign_transaction
函数签署交易并传入增量交易和发送者的private_key
-
使用
web3.eth.send_raw_transaction
函数发送已签署交易,然后使用web3.eth.wait_for_transaction_receipt
函数等待获取交易回执
# 1. Add imports
from compile import abi
from web3 import Web3
# 2. Add the Web3 provider logic here:
provider_rpc = {
'development': 'http://localhost:9944',
'alphanet': 'https://rpc.api.moonbase.moonbeam.network',
}
web3 = Web3(Web3.HTTPProvider(provider_rpc['development'])) # Change to correct network
# 3. Create variables
account_from = {
'private_key': 'YOUR_PRIVATE_KEY_HERE',
'address': 'PUBLIC_ADDRESS_OF_PK_HERE',
}
contract_address = 'CONTRACT_ADDRESS_HERE'
value = 3
print(
f'Calling the increment by { value } function in contract at address: { contract_address }'
)
# 4. Create contract instance
Incrementer = web3.eth.contract(address=contract_address, abi=abi)
# 5. Build increment tx
increment_tx = Incrementer.functions.increment(value).build_transaction(
{
'from': account_from['address'],
'nonce': web3.eth.get_transaction_count(account_from['address']),
}
)
# 6. Sign tx with PK
tx_create = web3.eth.account.sign_transaction(increment_tx, account_from['private_key'])
# 7. Send tx and wait for receipt
tx_hash = web3.eth.send_raw_transaction(tx_create.rawTransaction)
tx_receipt = web3.eth.wait_for_transaction_receipt(tx_hash)
print(f'Tx successful with hash: { tx_receipt.transactionHash.hex() }')
您可以在终端运行以下命令以运行脚本:
python3 increment.py
如果成功,交易哈希将显示在终端。您可以在increment.py
脚本旁边使用get.py
脚本以确保数值如预期变化:
接下来,您可以打开reset.py
文件并执行以下步骤以创建脚本:
-
导入ABI
-
定义
account_from
,包括private_key
和已部署合约contract_address
。此私钥将用于签署交易。请注意:此处操作仅用于演示目的,请勿将您的私钥存储在Python文件中 -
使用
web3.eth.contract
函数并传入已部署合约的ABI和地址以创建合约实例 -
使用合约实例构建重置交易。随后,您将使用
build_transaction
函数传入交易信息,包括发送者的from
地址和nonce
。您可以通过web3.eth.get_transaction_count
函数获取nonce
-
使用
web3.eth.account.sign_transaction
函数签署交易并传入重置交易和发送者的private_key
-
使用
web3.eth.send_raw_transaction
函数发送已签署交易,然后使用web3.eth.wait_for_transaction_receipt
函数等待获取交易回执
# 1. Add imports
from compile import abi
from web3 import Web3
# 2. Add the Web3 provider logic here:
provider_rpc = {
'development': 'http://localhost:9944',
'alphanet': 'https://rpc.api.moonbase.moonbeam.network',
}
web3 = Web3(Web3.HTTPProvider(provider_rpc['development'])) # Change to correct network
# 3. Create variables
account_from = {
'private_key': 'YOUR_PRIVATE_KEY_HERE',
'address': 'PUBLIC_ADDRESS_OF_PK_HERE',
}
contract_address = 'CONTRACT_ADDRESS_HERE'
print(f'Calling the reset function in contract at address: { contract_address }')
# 4. Create contract instance
Incrementer = web3.eth.contract(address=contract_address, abi=abi)
# 5. Build reset tx
reset_tx = Incrementer.functions.reset().build_transaction(
{
'from': account_from['address'],
'nonce': web3.eth.get_transaction_count(account_from['address']),
}
)
# 6. Sign tx with PK
tx_create = web3.eth.account.sign_transaction(reset_tx, account_from['private_key'])
# 7. Send tx and wait for receipt
tx_hash = web3.eth.send_raw_transaction(tx_create.rawTransaction)
tx_receipt = web3.eth.wait_for_transaction_receipt(tx_hash)
print(f'Tx successful with hash: { tx_receipt.transactionHash.hex() }')
您可以在终端运行以下命令以运行脚本:
python3 reset.py
如果成功,交易哈希将显示在终端。您可以在reset.py
脚本旁边使用get.py
脚本以确保数值如预期变化:
| Created: March 21, 2022