Python Substrate Interface¶
概览¶
Python Substrate Interface库允许应用程序开发者查询Moonbeam节点并使用原生Python接口与节点的波卡或Substrate功能交互。您将在本文中找到可用功能的概述和一些常用代码示例以快速使用Python Substrate Interface与Moonbeam网络交互。
查看先决条件¶
在开始操作之前,您将需要准备以下内容:
- 具有拥有一定数量资金的账户。 您可以每24小时一次从Moonbase Alpha水龙头上获取DEV代币以在Moonbase Alpha上进行测试
- 要在Moonbeam或Moonriver网络上测试本指南中的示例,您可以从受支持的网络端点提供商之一获取您自己的端点和API密钥
- 安装
pip
注意事项
本教程示例基于Ubuntu 18.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常量,如BlockWeights
、DefaultBlocksPerRound
和ExistentialDeposit
。您可以使用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系统模块,如System
、Timestamp
和Balances
,可以查询提供账户和余额等基本信息。因为可用存储函数是从元数据中动态读取,所以您还可以查询Moonbeam自定义模块的存储信息,如ParachainStaking
和Democracy
,以获取指定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("enter-shortform-private-key-without-0x-prefix")
# Define the account mnenomic
mnemonic = "enter-account-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("enter-shortform-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',
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))
except SubstrateRequestException as e:
print("Failed to send: {}".format(e))
离线签署¶
您可以通过sign
函数使用密钥对签署交易负载或任何数据。这方式可用于离线签署交易。
-
首先,在线上设备生成签名负载:
# 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', call_params={ 'dest': '0x44236223aB4291b93EEd10E4B511B37a398DEE55', 'value': 1 * 10**18 } ) # Generate the signature payload signature_payload = ws_provider.generate_signature_payload(call=call)
-
在离线设备使用发送账户的私钥创建一个密钥对,并签署签名负载:
# Imports from substrateinterface import Keypair, KeypairType # Define the signature payload from the offline machine signature_payload = "signature payload from offline machine" # Define the shortform private key of the sender account privatekey = bytes.fromhex("enter-shortform-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)
-
在线上设备使用发送账户的公钥创建一个密钥对,并使用离线设备生成的签名提交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 = "generated signature from offline machine" # Construct a keypair with the Ethereum style wallet address of the sending account keypair = Keypair(public_key="enter-sender-wallet-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', call_params={ 'dest': '0x44236223aB4291b93EEd10E4B511B37a398DEE55', 'value': 1 * 10**18 } ) # Construct the signed extrinsic with the generated signature extrinsic = substrate.create_signed_extrinsic( call=call, keypair=keypair, signature=signature ) # Submit the signed extrinsic result = substrate.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调用以检查给定交易哈希的最终性,请参考共识和确定性页面的示例。
| Created: June 2, 2022