Skip to content

Python Substrate Interface

概览

Python Substrate Interface库允许应用程序开发者查询Moonbeam节点并使用原生Python接口与节点的波卡或Substrate功能交互。您将在本文中找到可用功能的概述和一些常用代码示例以快速使用Python Substrate Interface与Moonbeam网络交互。

查看先决条件

在开始操作之前,您将需要准备以下内容:

  • 具有拥有一定数量资金的账户。 您可以每24小时一次从Moonbase Alpha水龙头上获取DEV代币以在Moonbase Alpha上进行测试
  • 要在Moonbeam或Moonriver网络上测试本指南中的示例,您可以从受支持的网络端点提供商之一获取您自己的端点和API密钥
  • 安装pip

注意事项

本教程示例基于Ubuntu 22.04和MacOS的环境,用户需根据其所使用的Windows版本进行微调。

安装Python Substrate Interface

您可以通过pip为您的项目安装Python Substrate Interface库。在您的项目目录中运行以下命令:

pip install substrate-interface

创建一个API提供商实例

与ETH API库相似,您必须先将Python Substrate Interface API的API实例进行实例化。使用您想要交互的Moonbeam网络的websocket端点创建WsProvider

要在Moonbeam或Moonriver网络上测试本指南中的示例,您可以从受支持的网络端点提供商之一获取您自己的端点和API密钥。

# Imports
from substrateinterface import SubstrateInterface

# Construct the API provider
ws_provider = SubstrateInterface(
    url="INSERT_WSS_API_ENDPOINT",
)
# Imports
from substrateinterface import SubstrateInterface

# Construct the API provider
ws_provider = SubstrateInterface(
    url="INSERT_WSS_API_ENDPOINT",
)
# Imports
from substrateinterface import SubstrateInterface

# Construct the API provider
ws_provider = SubstrateInterface(
    url="wss://wss.api.moonbase.moonbeam.network",
)
# Import
from substrateinterface import SubstrateInterface

# Construct the API provider
ws_provider = SubstrateInterface(
    url="ws://127.0.0.1:9944",
)   

查询信息

在这一部分,您将学习如何使用Python Substrate Interface库查询Moonbeam网络的链上信息。

访问Runtime常量

元数据中提供了所有的runtime常量,如BlockWeightsDefaultBlocksPerRoundExistentialDeposit。您可以使用get_metadata_constants函数查看Moonbeam网络中元数据的可用runtime常数列表。

元数据中的可用runtime常量可以通过get_constant函数查询。

# Imports
from substrateinterface import SubstrateInterface

# Construct the API provider
ws_provider = SubstrateInterface(
    url="wss://wss.api.moonbase.moonbeam.network",
)   

# List of available runtime constants in the metadata
constant_list = ws_provider.get_metadata_constants()
print(constant_list)

# Retrieve the Existential Deposit constant on Moonbeam, which is 0
constant = ws_provider.get_constant("Balances", "ExistentialDeposit")
print(constant.value)

检索区块和Extrinsics

您可以使用Python Substrate Interface API检索Moonbeam网络的基本信息,如区块和extrinsics。

您可以使用get_block函数检索区块。您也可以访问区块中的extrinsics和数据字段,这是一个Python字典。

您可以使用get_block_header函数检索区块头。

# Imports
from substrateinterface import SubstrateInterface

# Construct the API provider
ws_provider = SubstrateInterface(
    url="wss://wss.api.moonbase.moonbeam.network",
)

# Retrieve the latest block
block = ws_provider.get_block()

# Retrieve the latest finalized block
block = ws_provider.get_block_header(finalized_only=True)

# Retrieve a block given its Substrate block hash
block_hash = "0xa499d4ebccdabe31218d232460c0f8b91bd08f72aca25f9b25b04b6dfb7a2acb"
block = ws_provider.get_block(block_hash=block_hash)

# Iterate through the extrinsics inside the block
for extrinsic in block["extrinsics"]:
    if "address" in extrinsic:
        signed_by_address = extrinsic["address"].value
    else:
        signed_by_address = None
    print(
        "\nPallet: {}\nCall: {}\nSigned by: {}".format(
            extrinsic["call"]["call_module"].name,
            extrinsic["call"]["call_function"].name,
            signed_by_address,
        )
    )

注意事项

上述代码示例中所使用的区块哈希是Substrate区块哈希。假设您在Python Substrate Interface中使用的标准方法为原语的Substrate版本,如区块或交易哈希(tx hash)。

订阅新的区块头

您还可以修改上述示例以使用基于订阅的模型来监听新的区块头。

# Imports
from substrateinterface import SubstrateInterface

# Construct the API provider
ws_provider = SubstrateInterface(
    url="wss://wss.api.moonbase.moonbeam.network",
)


def subscription_handler(obj, update_nr, subscription_id):
    print(f"New block #{obj['header']['number']}")

    if update_nr > 10:
        return {
            "message": "Subscription will cancel when a value is returned",
            "updates_processed": update_nr,
        }


result = ws_provider.subscribe_block_headers(subscription_handler)

查询存储信息

您可以使用get_metadata_storage_functions查看Moonbeam网络中元数据的可用存储函数列表。

通过query函数可以查询通过存储函数在元数据中提供的链状态。

Substrate系统模块,如SystemTimestampBalances,可以查询提供账户和余额等基本信息。因为可用存储函数是从元数据中动态读取,所以您还可以查询Moonbeam自定义模块的存储信息,如ParachainStakingDemocracy,以获取指定Moonbeam网络的状态信息。

# Imports
from substrateinterface import SubstrateInterface

# Construct the API provider
ws_provider = SubstrateInterface(
    url="wss://wss.api.moonbase.moonbeam.network",
)

# List of available storage functions in the metadata
method_list = ws_provider.get_metadata_storage_functions()
print(method_list)

# Query basic account information
account_info = ws_provider.query(
    module="System",
    storage_function="Account",
    params=["0x578002f699722394afc52169069a1FfC98DA36f1"],
)
# Log the account nonce
print(account_info.value["nonce"])
# Log the account free balance
print(account_info.value["data"]["free"])

# Query candidate pool information from Moonbeam's Parachain Staking module
candidate_pool_info = ws_provider.query(
    module="ParachainStaking", storage_function="CandidatePool", params=[]
)
print(candidate_pool_info)

签署和交易

创建密钥对

Python Substrate Interface中的密钥对是用于任何数据的签署,包括转账、消息或合约交互。

您可以从短格式私钥或助记词创建密钥对实例。以Moonbeam网络而言,您还需要将KeypairType指定为KeypairType.ECDSA

# Imports
from substrateinterface import Keypair, KeypairType

# Define the shortform private key
privatekey = bytes.fromhex("INSERT_PRIVATE_KEY_WITHOUT_0X_PREFIX")

# Define the account mnenomic
mnemonic = "INSERT_MNEMONIC"

# Generate the keypair from shortform private key
keypair = Keypair.create_from_private_key(privatekey, crypto_type=KeypairType.ECDSA)

# Generate the keypair from mnemonic
keypair = Keypair.create_from_mnemonic(mnemonic, crypto_type=KeypairType.ECDSA)

发起和发送交易

compose_call函数可以用于组成调用负载,以作为未签署的extrinsic或提案使用。

通过create_signed_extrinsic函数使用密钥对签署负载。

使用submit_extrinsic函数提交签署的extrinsic。

此函数也将返回ExtrinsicReceipt,其中包含extrinsic的链上执行信息。如果您需要检查接收方信息,您可以在提交extrinsic时将wait_for_inclusion设置为True,等待extrinsic成功包含在区块中。

以下示例代码将显示发送交易的一个完整示例。

# Imports
from substrateinterface import SubstrateInterface, Keypair, KeypairType
from substrateinterface.exceptions import SubstrateRequestException

# Construct the API provider
ws_provider = SubstrateInterface(
    url="wss://wss.api.moonbase.moonbeam.network",
)

# Define the shortform private key of the sending account
privatekey = bytes.fromhex("INSERT_PRIVATE_KEY_WITHOUT_0X_PREFIX")

# Generate the keypair
keypair = Keypair.create_from_private_key(privatekey, crypto_type=KeypairType.ECDSA)

# Form a transaction call
call = ws_provider.compose_call(
    call_module="Balances",
    call_function="transfer_allow_death",
    call_params={
        "dest": "0x44236223aB4291b93EEd10E4B511B37a398DEE55",
        "value": 1 * 10**18,
    },
)

# Form a signed extrinsic
extrinsic = ws_provider.create_signed_extrinsic(call=call, keypair=keypair)

# Submit the extrinsic
try:
    receipt = ws_provider.submit_extrinsic(extrinsic, wait_for_inclusion=True)
    print(
        "Extrinsic '{}' sent and included in block '{}'".format(
            receipt.extrinsic_hash, receipt.block_hash
        )
    )

离线签署

您可以通过sign函数使用密钥对签署交易负载或任何数据。这方式可用于离线签署交易。

  1. 首先,在线上设备生成签名负载:

    # Imports
    from substrateinterface import SubstrateInterface
    
    # Construct the API provider
    ws_provider = SubstrateInterface(
        url="wss://wss.api.moonbase.moonbeam.network",
    )
    
    # Construct a transaction call
    call = ws_provider.compose_call(
        call_module="Balances",
        call_function="transfer_allow_death",
        call_params={
            "dest": "0x44236223aB4291b93EEd10E4B511B37a398DEE55",
            "value": 1 * 10**18,
        },
    )
    
    # Generate the signature payload
    signature_payload = ws_provider.generate_signature_payload(call=call)
    
  2. 在离线设备使用发送账户的私钥创建一个密钥对,并签署签名负载:

    # Imports
    from substrateinterface import Keypair, KeypairType
    
    # Define the signature payload from the offline machine
    signature_payload = "INSERT_SIGNATURE_PAYLOAD"
    
    # Define the shortform private key of the sender account
    privatekey = bytes.fromhex("INSERT_PRIVATE_KEY_WITHOUT_0X_PREFIX")
    
    # Generate the keypair from shortform private key
    keypair = Keypair.create_from_private_key(privatekey, crypto_type=KeypairType.ECDSA)
    
    # Sign the signature_payload 
    signature = keypair.sign(signature_payload)
    
  3. 在线上设备使用发送账户的公钥创建一个密钥对,并使用离线设备生成的签名提交extrinsic:

    # Imports
    from substrateinterface import SubstrateInterface, Keypair, KeypairType
    
    # Construct the API provider
    ws_provider = SubstrateInterface(
        url="wss://wss.api.moonbase.moonbeam.network",
    ) 
    
    # Define the signature from the offline machine
    signature_payload = "INSERT_SIGNATURE_PAYLOAD"
    
    # Construct a keypair with the Ethereum style wallet address of the sending account
    keypair = Keypair(public_key="INSERT_ADDRESS_WITHOUT_0X", crypto_type=KeypairType.ECDSA)
    
    # Construct the same transaction call that was signed
    call = ws_provider.compose_call(
        call_module="Balances",
        call_function="transfer_allow_death",
        call_params={
            "dest": "0x44236223aB4291b93EEd10E4B511B37a398DEE55",
            "value": 1 * 10**18,
        },
    )
    
    # Construct the signed extrinsic with the generated signature
    extrinsic = ws_provider.create_signed_extrinsic(
        call=call, keypair=keypair, signature=signature
    )
    
    # Submit the signed extrinsic
    result = ws_provider.submit_extrinsic(extrinsic=extrinsic)
    
    # Print the execution result
    print(result.extrinsic_hash)
    

自定义RPC请求

您也可以使用rpc_request函数创建自定义RPC请求。

这对于与Moonbeam的ETH JSON-RPC端点或Moonbeam的自定义RPC端点交互特别有效。

关于如何通过Python Substrate Interface使用自定义RPC调用以检查给定交易哈希的最终性,请参考共识和确定性页面的示例。

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