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 22.04和MacOS的环境,用户需根据其所使用的Windows版本进行微调。
创建Python项目¶
首先,您需要创建一个目录,以存储您在本教程中将要创建的所有文件:
mkdir web3-examples && cd web3-examples
在本教程中,您将需要安装Web3.py代码库和Solidity编译器。您可以通过运行以下命令来安装两者的安装包:
pip3 install web3 py-solc-x solc-select
在Moonbeam上设置Web3.py¶
在这个文章中,您将会创建多个用来实现不同功能的脚本;比如发送交易,部署智能合约,与已部署的智能合约交互。在大部的脚本中您都需要创建一个Web3.py provider来与网路互动。
要为Moonbeam或Moonriver网络配置您的项目,您可以从受支持的网络端点提供商之一获取您自己的端点和API密钥。
您需要通过以下步骤来创建一个provider:
- 导入
web3
代码库 - 用
Web3(Web3.HTTPProvider())
方法创建一个web3
provider并提供一个网络终端URL
# 1. 导入web3.py
from web3 import Web3
# 2. 创建web3.py provider
web3 = Web3(Web3.HTTPProvider("INSERT_RPC_API_ENDPOINT")) # Insert your RPC URL here
# 1. 导入web3.py
from web3 import Web3
# 2. 创建web3.py provider
web3 = Web3(Web3.HTTPProvider("INSERT_RPC_API_ENDPOINT")) # Insert your RPC URL here
# 1. 导入web3.py
from web3 import Web3
# 2. 创建web3.py provider
web3 = Web3(Web3.HTTPProvider("https://rpc.api.moonbase.moonbeam.network"))
# 1. 导入web3.py
from web3 import Web3
# 2. 创建web3.py provider
web3 = Web3(Web3.HTTPProvider("http://127.0.0.1:9944"))
您可以记下这个代码范例,您将在之后部分的脚本示例中使到它。
发送交易¶
在这一部分,您将需要创建一些脚本。第一个脚本将用于发送交易前查看账户余额。第二个脚本将执行交易。
您也可以使用余额脚本在交易发送后查看账户余额。
查看余额脚本¶
您仅需要一个文件以查看交易发送前后两个地址的余额。首先,您可以运行以下命令创建一个balances.py
文件:
touch balances.py
接下来,您将为此文件创建脚本并完成以下步骤:
- 设置Web3提供者
- 定义
address_from
和address_to
变量 - 使用
web3.eth.get_balance
函数获取账户余额并使用web3.from_wei
格式化结果
from web3 import Web3
# 1. Add the Web3 provider logic here:
provider_rpc = {
"development": "http://localhost:9944",
"moonbase": "https://rpc.api.moonbase.moonbeam.network",
}
web3 = Web3(Web3.HTTPProvider(provider_rpc["moonbase"])) # Change to correct network
# 2. Create address variables
address_from = 'INSERT_FROM_ADDRESS'
address_to = 'INSERT_TO_ADDRESS'
# 3. Fetch balance data
balance_from = web3.from_wei(
web3.eth.get_balance(Web3.to_checksum_address(address_from)), "ether"
)
balance_to = web3.from_wei(
web3.eth.get_balance(Web3.to_checksum_address(address_to)), "ether"
)
print(f"The balance of { address_from } is: { balance_from } DEV")
print(f"The balance of { address_to } is: { balance_to } DEV")
您可以运行以下命令以运行脚本并获取账户余额:
python3 balances.py
如果成功,发送地址和接收地址的余额将以ETH为单位显示在终端。
发送交易脚本¶
您仅需要一个文件即可在账户之间执行交易。在本示例中,您将从拥有私钥的发送地址转移1个DEV Token至另一个地址。首先,您可以运行以下命令创建一个transaction.py
文件:
touch transaction.py
接下来,您将为此文件创建脚本并完成以下步骤:
- 添加导入,包含Web3.py和
rpc_gas_price_strategy
,将会用于以下步骤以获得交易使用的Gas价格 - 设置Web3提供者
- 定义
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",
"moonbase": "https://rpc.api.moonbase.moonbeam.network",
}
web3 = Web3(Web3.HTTPProvider(provider_rpc["moonbase"])) # Change to correct network
# 3. Create address variables
account_from = {
'private_key': 'INSERT_YOUR_PRIVATE_KEY',
'address': 'INSERT_PUBLIC_ADDRESS_OF_PK',
}
address_to = 'INSERT_TO_ADDRESS'
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(
Web3.to_checksum_address(account_from["address"])
),
"gasPrice": web3.eth.generate_gas_price(),
"gas": 21000,
"to": Web3.to_checksum_address(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
脚本为发送地址和接收地址查看余额是否变化。整体操作流程如下所示:
部署合约¶
编译合约脚本¶
在这一部分,您将创建一个脚本,此脚本使用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']
注意事项
如果您遇到Solc is not installed
报错,反注释代码示例的第二步并运行它。
部署合约脚本¶
有了用于编译Incrementer.sol
合约的脚本,您就可以使用结果以发送部署的签名交易。首先,您可以为部署的脚本创建一个名为deploy.py
的文件:
touch deploy.py
接下来,您将为此文件创建脚本并完成以下步骤:
- 添加导入,包含Web3.py以及ABI和
Incrementer.sol
合约的字节码 - 设置Web3提供者
- 定义
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",
"moonbase": "https://rpc.api.moonbase.moonbeam.network",
}
web3 = Web3(Web3.HTTPProvider(provider_rpc["moonbase"])) # Change to correct network
# 3. Create address variable
account_from = {
'private_key': 'INSERT_YOUR_PRIVATE_KEY',
'address': 'INSERT_PUBLIC_ADDRESS_OF_PK',
}
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": Web3.to_checksum_address(account_from["address"]),
"nonce": web3.eth.get_transaction_count(
Web3.to_checksum_address(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
如果成功,合约地址将显示在终端。
读取合约数据(调用函数)¶
调用函数是无需修改合约存储(更改变量)的交互类型,这意味着无需发送交易,只需读取已部署合约的各种存储变量。
首先,您需要创建一个文件并命名为get.py
:
touch get.py
接下来,您可以遵循以下步骤创建脚本:
- 添加导入,包含Web3.py以及ABI和
Incrementer.sol
合约的字节码 - 设置Web3提供者
- 定义部署合约中的contract_address
- 使用
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",
"moonbase": "https://rpc.api.moonbase.moonbeam.network",
}
web3 = Web3(Web3.HTTPProvider(provider_rpc["moonbase"])) # Change to correct network
# 3. Create address variable
contract_address = 'INSERT_CONTRACT_ADDRESS'
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
如果成功,数值将显示在终端。
交互合约(发送函数)¶
发送函数是修改合约存储(更改变量)的交互类型,这意味着需要签署和发送交易。在这一部分,您将创建两个脚本:一个是增量,另一个是重置增量器。首先,您可以为每个脚本创建一个文件,并分别命名为increment.py
和reset.py
:
touch increment.py reset.py
接下来,打开increment.py
文件并执行以下步骤以创建脚本:
- 添加导入,包含Web3.py以及ABI和
Incrementer.sol
合约的字节码 - 设置Web3提供者
- 定义
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",
"moonbase": "https://rpc.api.moonbase.moonbeam.network",
}
web3 = Web3(Web3.HTTPProvider(provider_rpc["moonbase"])) # Change to correct network
# 3. Create variables
account_from = {
'private_key': 'INSERT_YOUR_PRIVATE_KEY',
'address': 'INSERT_PUBLIC_ADDRESS_OF_PK',
}
contract_address = 'INSERT_CONTRACT_ADDRESS'
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": Web3.to_checksum_address(account_from["address"]),
"nonce": web3.eth.get_transaction_count(
Web3.to_checksum_address(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
文件并执行以下步骤以创建脚本:
- 添加导入,包含Web3.py以及ABI和
Incrementer.sol
合约的字节码 - 设置Web3提供者
- 定义
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",
"moonbase": "https://rpc.api.moonbase.moonbeam.network",
}
web3 = Web3(Web3.HTTPProvider(provider_rpc["moonbase"])) # Change to correct network
# 3. Create variables
account_from = {
'private_key': 'INSERT_YOUR_PRIVATE_KEY',
'address': 'INSERT_PUBLIC_ADDRESS_OF_PK',
}
contract_address = 'INSERT_CONTRACT_ADDRESS'
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": Web3.to_checksum_address(account_from["address"]),
"nonce": web3.eth.get_transaction_count(
Web3.to_checksum_address(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
脚本以确保数值如预期变化: