Skip to content

Web3.py Python代码库

概览

Web3.py是一组代码库,允许开发者使用Python,并通过HTTP、IPC或WebSocket协议与以太坊节点交互。Moonbeam拥有与以太坊相似的API供用户使用,其与以太坊风格的JSON-RPC调用完全兼容。因此,开发者可以利用此兼容特性并使用Web3.py库与Moonbeam节点交互,与在以太坊操作相同。

在本教程中,您将学习如何使用Web3.py库在Moonbase Alpha上发送交易和部署合约。本教程也同样适用于MoonbeamMoonriverMoonbeam开发节点

查看先决条件

在开始本教程示例之前,您将需要提前准备以下内容:

  • 具有拥有一定数量资金的账户。 您可以每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:

  1. 导入web3代码库
  2. Web3(Web3.HTTPProvider())方法创建一个web3provider并提供一个网络终端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

接下来,您将为此文件创建脚本并完成以下步骤:

  1. 设置Web3提供者
  2. 定义address_fromaddress_to变量
  3. 使用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

接下来,您将为此文件创建脚本并完成以下步骤:

  1. 添加导入,包含Web3.py和rpc_gas_price_strategy,将会用于以下步骤以获得交易使用的Gas价格
  2. 设置Web3提供者
  3. 定义account_from,包括private_keyaddress_to变量。此处需要私钥以签署交易。请注意:此处操作仅用于演示目的,请勿将您的私钥存储在Python文件中
  4. 使用Web3.py Gas Price API设置gas价格策略。在本示例中,您将使用导入的rpc_gas_price_strategy
  5. 使用web3.eth.account.sign_transaction函数创建和签署交易,传入交易的noncegasgasPricetovalue以及发送者的private_key。您可以通过web3.eth.get_transaction_count函数并传入发送者地址获取nonce。您可以通过web3.eth.generate_gas_price函数预设gasPrice。您可以通过web3.to_wei函数将数字格式化成以Wei为单位的易读数字
  6. 使用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脚本为发送地址和接收地址查看余额是否变化。整体操作流程如下所示:

Send Tx Web3py

部署合约

在下几个部分中您将要编译和部署的合约是一个简单的增量合约,命名为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

接下来,您将为此文件创建脚本并完成以下步骤:

  1. 导入solcx程序包
  2. (可选)如果您还未安装Solidity编译器,您可以通过solcx.install_solc函数进行安装
  3. 使用solcx.compile_files函数编译Incrementer.sol函数
  4. 导出合约的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

接下来,您将为此文件创建脚本并完成以下步骤:

  1. 添加导入,包含Web3.py以及ABI和Incrementer.sol合约的字节码
  2. 设置Web3提供者
  3. 定义account_from,包括private_key变量。此私钥将用于签署交易。请注意:此处操作仅用于演示目的,请勿将您的私钥存储在Python文件中
  4. 使用web3.eth.contract函数并传入合约的ABI和字节码创建合约实例
  5. 使用合约实例并传入需要增量的数值创建构造交易。在本示例中,您可以将数值设置为5。随后,您将使用build_transaction函数传入交易信息,包括发送者的fromnonce。您可以通过web3.eth.get_transaction_count函数获取nonce
  6. 使用web3.eth.account.sign_transaction函数签署交易并传入构造交易和发送者的private_key
  7. 使用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

如果成功,合约地址将显示在终端。

Deploy Contract Web3py

读取合约数据(调用函数)

调用函数是无需修改合约存储(更改变量)的交互类型,这意味着无需发送交易,只需读取已部署合约的各种存储变量。

首先,您需要创建一个文件并命名为get.py

touch get.py

接下来,您可以遵循以下步骤创建脚本:

  1. 添加导入,包含Web3.py以及ABI和Incrementer.sol合约的字节码
  2. 设置Web3提供者
  3. 定义部署合约中的contract_address
  4. 使用web3.eth.contract函数并传入已部署合约的ABI和地址创建合约实例
  5. 使用合约实例,您随后可以调用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.pyreset.py

touch increment.py reset.py

接下来,打开increment.py文件并执行以下步骤以创建脚本:

  1. 添加导入,包含Web3.py以及ABI和Incrementer.sol合约的字节码
  2. 设置Web3提供者
  3. 定义account_from,包括private_key、已部署合约contract_address以及要增量的value。此私钥将用于签署交易。请注意:此处操作仅用于演示目的,请勿将您的私钥存储在Python文件中
  4. 使用web3.eth.Contract函数并传入已部署合约的ABI和地址以创建合约实例
  5. 使用合约实例和传入要增量的数值创建构造交易。随后,您将使用build_transaction函数传入交易信息,包括发送者的from地址和nonce。您可以通过web3.eth.get_transaction_count函数获取nonce
  6. 使用web3.eth.account.sign_transaction函数签署交易并传入增量交易和发送者的private_key
  7. 使用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脚本以确保数值如预期变化:

Increment Contract Web3py

接下来,您可以打开reset.py文件并执行以下步骤以创建脚本:

  1. 添加导入,包含Web3.py以及ABI和Incrementer.sol合约的字节码
  2. 设置Web3提供者
  3. 定义account_from,包括private_key和已部署合约contract_address。此私钥将用于签署交易。请注意:此处操作仅用于演示目的,请勿将您的私钥存储在Python文件中
  4. 使用web3.eth.contract函数并传入已部署合约的ABI和地址以创建合约实例
  5. 使用合约实例构建重置交易。随后,您将使用build_transaction函数传入交易信息,包括发送者的from地址和nonce。您可以通过web3.eth.get_transaction_count函数获取nonce
  6. 使用web3.eth.account.sign_transaction函数签署交易并传入重置交易和发送者的private_key
  7. 使用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脚本以确保数值如预期变化:

Reset Contract Web3py

本网站的所有信息由第三方提供,仅供参考之用。Moonbeam文档网站(https://docs.moonbeam.network/)上列出和描述的任何项目与Moonbeam立场无关。Moonbeam Foundation不保证网站信息的准确性、完整性或真实性。如使用或依赖本网站信息,需自行承担相关风险,Moonbeam Foundation不承担任何责任和义务。这些材料的所有陈述和/或意见由提供方个人或实体负责,与Moonbeam Foundation立场无关,概不构成任何投资建议。对于任何特定事项或情况,应寻求专业权威人士的建议。此处的信息可能会包含或链接至第三方提供的信息与/或第三方服务(包括任何第三方网站等)。这类链接网站不受Moonbeam Foundation控制。Moonbeam Foundation对此类链接网站的内容(包括此类链接网站上包含的任何信息或资料)概不负责也不认可。这些链接内容仅为方便访客而提供,Moonbeam Foundation对因您使用此信息或任何第三方网站或服务提供的信息而产生的所有责任概不负责。
Last update: January 25, 2024
| Created: March 21, 2022