Rust提名池运行时API库pallet-nomination-pools-runtime-api的使用,赋能Substrate区块链提名质押功能
Rust提名池运行时API库pallet-nomination-pools-runtime-api的使用,赋能Substrate区块链提名质押功能
以下是关于pallet-nomination-pools-runtime-api
库的详细信息和使用示例:
基本信息
- 描述: 提名池pallet的运行时API定义
- 许可证: Apache-2.0
- 版本: 38.0.0
- 大小: 26.1 KiB
- 仓库: paritytech/polkadot-sdk
安装
在您的项目目录中运行以下Cargo命令:
cargo add pallet-nomination-pools-runtime-api
或者在您的Cargo.toml中添加以下行:
pallet-nomination-pools-runtime-api = "38.0.0"
使用示例
以下是使用pallet-nomination-pools-runtime-api
的完整示例代码:
// 引入必要的库
use pallet_nomination_pools_runtime_api::{
NominationPoolsApi, Error as NominationPoolsApiError,
};
use sp_api::ProvideRuntimeApi;
use sp_runtime::{generic::BlockId, traits::Block as BlockT};
use substrate_frame_rpc_system::AccountId;
// 定义一个结构体来封装提名池API
pub struct NominationPoolsClient<Block, Client> {
client: Client,
_marker: std::marker::PhantomData<Block>,
}
impl<Block, Client> NominationPoolsClient<Block, Client>
where
Block: BlockT,
Client: ProvideRuntimeApi<Block>,
Client::Api: NominationPoolsApi<Block>,
{
// 创建新的客户端实例
pub fn new(client: Client) -> Self {
Self {
client,
_marker: Default::default(),
}
}
// 获取指定账户的质押池信息
pub fn get_pool_info(
&self,
account_id: AccountId,
at: Option<BlockId<Block>>,
) -> Result<Option<PoolInfo>, NominationPoolsApiError> {
let api = self.client.runtime_api();
let at = BlockId::hash(at.unwrap_or_else(||
self.client.info().best_hash
));
api.get_pool_info(&at, account_id)
}
// 获取所有活跃质押池的列表
pub fn get_active_pools(
&self,
at: Option<BlockId<Block>>,
) -> Result<Vec<AccountId>, NominationPoolsApiError> {
let api = self.client.runtime_api();
let at = BlockId::hash(at.unwrap_or_else(||
self.client.info().best_hash
));
api.get_active_pools(&at)
}
}
// 定义PoolInfo结构体
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct PoolInfo {
pub points: u128, // 池中的点数
pub state: PoolState, // 池的当前状态
pub member_counter: u32, // 池中成员数量
// 其他相关字段...
}
// 定义PoolState枚举
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum PoolState {
Open, // 池开放供加入
Blocked, // 池被阻止
Destroying, // 池正在销毁中
}
完整示例demo
以下是更完整的示例代码,展示如何在Substrate链中使用提名池API:
use std::sync::Arc;
// 引入必要的库
use pallet_nomination_pools_runtime_api::{
NominationPoolsApi, Error as NominationPoolsApiError,
};
use sp_api::{ApiExt, ProvideRuntimeApi};
use sp_blockchain::HeaderBackend;
use sp_runtime::{
generic::BlockId,
traits::{Block as BlockT, Header as HeaderT},
};
use substrate_frame_rpc_system::AccountId;
/// 提名池API客户端实现
pub struct NominationPoolsRuntimeApi<Block: BlockT, Client> {
client: Arc<Client>,
_marker: std::marker::PhantomData<Block>,
}
impl<Block, Client> NominationPoolsRuntimeApi<Block, Client>
where
Block: BlockT,
Client: ProvideRuntimeApi<Block> + HeaderBackend<Block> + 'static,
Client::Api: NominationPoolsApi<Block>,
{
/// 创建新的API实例
pub fn new(client: Arc<Client>) -> Self {
Self {
client,
_marker: Default::default(),
}
}
/// 获取指定区块高度的质押池信息
pub fn get_pool_info_at(
&self,
account_id: AccountId,
block_number: <Block::Header as HeaderT>::Number,
) -> Result<Option<PoolInfo>, NominationPoolsApiError> {
let block_hash = self.client.hash(block_number)?
.ok_or_else(|| NominationPoolsApiError::BlockNotFound)?;
let api = self.client.runtime_api();
api.get_pool_info(&BlockId::hash(block_hash), account_id)
}
/// 获取所有活跃池的最新信息
pub fn get_all_active_pools_info(
&self,
) -> Result<Vec<(AccountId, PoolInfo)>, NominationPoolsApiError> {
let best_hash = self.client.info().best_hash;
let api = self.client.runtime_api();
let active_pools = api.get_active_pools(&BlockId::hash(best_hash))?;
let mut result = Vec::new();
for pool_account in active_pools {
if let Some(pool_info) = api.get_pool_info(&BlockId::hash(best_hash), pool_account.clone())? {
result.push((pool_account, pool_info));
}
}
Ok(result)
}
}
/// 扩展的PoolInfo结构体,包含更多字段
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct PoolInfo {
pub points: u128, // 池中的总点数
pub state: PoolState, // 池状态
pub member_counter: u32, // 成员数量
pub rewards: Option<u128>, // 待分配奖励
pub commission: Option<u8>, // 佣金比例
}
/// 扩展的池状态
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum PoolState {
Open, // 开放状态,可接受新成员
Blocked, // 被阻止状态
Destroying, // 正在销毁
Closed, // 已关闭
}
/// 示例:如何使用API客户端
fn example_usage<Block: BlockT, Client>(
client: Arc<Client>,
account_id: AccountId,
) where
Client: ProvideRuntimeApi<Block> + HeaderBackend<Block> + 'static,
Client::Api: NominationPoolsApi<Block>,
{
let api = NominationPoolsRuntimeApi::new(client);
// 获取单个池信息
match api.get_pool_info_at(account_id.clone(), 12345.into()) {
Ok(Some(info)) => println!("池信息: {:?}", info),
Ok(None) => println!("未找到池信息"),
Err(e) => println!("查询失败: {:?}", e),
}
// 获取所有活跃池信息
match api.get_all_active_pools_info() {
Ok(pools) => {
println!("找到 {} 个活跃池:", pools.len());
for (account, info) in pools {
println!("账户: {}, 信息: {:?}", account, info);
}
}
Err(e) => println!("获取活跃池失败: {:?}", e),
}
}
功能说明
- 提名池信息查询: 通过
get_pool_info_at
方法可以查询特定区块高度的质押池信息 - 活跃池列表及详细信息: 通过
get_all_active_pools_info
方法获取所有活跃质押池及其详细信息 - 运行时集成: 与Substrate运行时无缝集成,支持区块链状态查询
- 区块高度支持: 可以查询特定区块高度的池信息
注意事项
- 使用时需要确保您的Substrate链已经包含了
pallet-nomination-pools
- 所有API调用都需要指定区块哈希或使用最新区块
- 错误处理应考虑到
NominationPoolsApiError
可能的各种情况 - 需要正确处理异步操作,特别是在实际生产环境中使用
- 确保客户端已正确初始化并连接到链节点
这个库为Substrate区块链提供了完整的提名质押池运行时API接口,使得开发者可以方便地在自己的应用或服务中集成质押池功能。
1 回复
Rust提名池运行时API库pallet-nomination-pools-runtime-api的使用
概述
pallet-nomination-pools-runtime-api
是Substrate区块链框架中的一个重要组件,它为提名池(nomination pools)功能提供了运行时API接口。这个库使得开发者可以在Substrate链上实现提名质押功能,允许用户将他们的代币汇集在一起进行质押,共享奖励。
主要功能
- 提供提名池的创建和管理接口
- 实现代币的质押和奖励分配机制
- 支持池成员的加入和退出
- 提供池状态查询功能
使用方法
1. 添加依赖
首先,你需要在项目的Cargo.toml
文件中添加依赖:
[dependencies]
pallet-nomination-pools-runtime-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" }
2. 实现Runtime API
在你的运行时中实现提名池的Runtime API:
use pallet_nomination_pools_runtime_api::{NominationPoolsApi, Error};
impl NominationPoolsApi<Block> for Runtime {
fn pool_member_status(
who: &AccountId,
) -> Result<PoolMember<Balance>, Error> {
NominationPools::pool_member_status(who)
}
fn pool_points(
pool_id: PoolId,
) -> Result<PoolPoints, Error> {
NominationPools::pool_points(pool_id)
}
}
3. 创建提名池
use frame_support::dispatch::DispatchResult;
pub fn create_pool(
origin: OriginFor<T>,
amount: BalanceOf<T>,
root: T::AccountId,
nominator: T::AccountId,
state_toggler: T::AccountId,
) -> DispatchResult {
// 调用提名池模块的创建函数
pallet_nomination_pools::Pallet::<T>::create(
origin,
amount,
root,
nominator,
state_toggler,
)
}
4. 加入提名池
pub fn join_pool(
origin: OriginFor<T>,
pool_id: PoolId,
amount: BalanceOf<T>,
) -> DispatchResult {
pallet_nomination-pools::Pallet::<T>::join(
origin,
pool_id,
amount,
)
}
5. 查询池信息
use pallet_nomination_pools_runtime_api::PoolMember;
pub fn get_pool_member(
who: T::AccountId,
) -> Result<PoolMember<BalanceOf<T>>, Error> {
<Runtime as NominationPoolsApi<Block>>::pool_member_status(&who)
}
示例代码
下面是一个完整的示例,展示如何使用提名池API:
use frame_support::{decl_module, decl_storage, dispatch::DispatchResult};
use frame_system::ensure_signed;
use pallet_nomination_pools_runtime_api::{NominationPoolsApi, PoolMember, Error};
pub trait Config: frame_system::Config + pallet_nomination_pools::Config {}
decl_storage! {
trait Store for Module<T: Config> as NominationPoolsExample {
// 可以添加自定义存储项
}
}
decl_module! {
pub struct Module<T: Config> for enum Call where origin: T::Origin {
/// 创建新的提名池
#[weight = 10_000]
pub fn create_pool(
origin,
amount: T::Balance,
root: T::AccountId,
nominator: T::AccountId,
state_toggler: T::AccountId,
) -> DispatchResult {
let who = ensure_signed(origin)?;
pallet_nomination_pools::Pallet::<T>::create(
who.into(),
amount,
root,
nominator,
state_toggler,
)
}
/// 查询池成员状态
#[weight = 10_000]
pub fn get_member_status(
origin,
member: T::AccountId,
) -> Result<PoolMember<T::Balance>, Error> {
let _ = ensure_signed(origin)?;
<Runtime as NominationPoolsApi<Block>>::pool_member_status(&member)
}
}
}
完整示例代码
以下是一个更完整的示例,展示如何集成提名池API到运行时中:
//! 提名池运行时API集成示例
use frame_support::{
construct_runtime, parameter_types,
traits::{ConstU32, ConstU64},
weights::Weight,
};
use frame_system::EnsureRoot;
use pallet_nomination_pools::{
BondExtra, BondedPools, Config, CurrentEra, LastPoolId, MaxPoolMembers,
MaxPoolMembersPerPool, MaxPools, MinCreateBond, MinJoinBond, Pallet as NominationPools,
PoolMembers, PoolRoles, RewardPools, SubPoolsStorage,
};
use sp_runtime::{
traits::{AccountIdConversion, BlakeTwo256, IdentifyAccount, Verify},
MultiSignature, RuntimeDebug,
};
// 运行时配置
pub struct Runtime;
parameter_types! {
pub const MaxNominations: u32 = 16;
pub const MaxUnlockingChunks: u32 = 32;
pub const MaxPools: u32 = 1_000;
pub const MaxPoolMembers: u32 = 10_000;
pub const MaxPoolMembersPerPool: u32 = 1_000;
pub const MinCreateBond: Balance = 10 * DOLLARS;
pub const MinJoinBond: Balance = 1 * DOLLARS;
}
impl Config for Runtime {
type Event = Event;
type WeightInfo = ();
type Currency = Balances;
type RewardCounter = RewardCounter;
type BalanceToU256 = BalanceToU256;
type U256ToBalance = U256ToBalance;
type PostUnbondingPoolsWindow = PostUnbondingPoolsWindow;
type MaxUnbonding = MaxUnbonding;
type MaxPointsToBalance = MaxPointsToBalance;
type MaxPools = MaxPools;
type MaxPoolMembers = MaxPoolMembers;
type MaxPoolMembersPerPool = MaxPoolMembersPerPool;
type MinCreateBond = MinCreateBond;
type MinJoinBond = MinJoinBond;
type PalletId = PalletsPoolId;
type AdminOrigin = EnsureRoot<AccountId>;
}
// 实现NominationPoolsApi
impl pallet_nomination_pools_runtime_api::NominationPoolsApi<Block> for Runtime {
fn pool_member_status(who: &AccountId) -> Result<PoolMember<Balance>, Error> {
NominationPools::pool_member_status(who)
}
fn pool_points(pool_id: PoolId) -> Result<PoolPoints, Error> {
NominationPools::pool_points(pool_id)
}
}
// 创建提名池的调用示例
pub fn create_pool_example() -> DispatchResult {
let root = AccountId::new([1u8; 32]);
let nominator = AccountId::new([2u8; 32]);
let state_toggler = AccountId::new([3u8; 32]);
let initial_amount = 100 * DOLLARS;
NominationPools::<Runtime>::create(
RawOrigin::Signed(root.clone()).into(),
initial_amount,
root,
nominator,
state_toggler,
)
}
// 加入提名池的调用示例
pub fn join_pool_example(who: AccountId, pool_id: PoolId, amount: Balance) -> DispatchResult {
NominationPools::<Runtime>::join(
RawOrigin::Signed(who).into(),
pool_id,
amount,
)
}
// 查询池成员状态的调用示例
pub fn get_pool_member_example(who: AccountId) -> Result<PoolMember<Balance>, Error> {
<Runtime as pallet_nomination_pools_runtime_api::NominationPoolsApi<Block>>::pool_member_status(&who)
}
注意事项
- 使用前确保你的链已经正确配置了
pallet-nomination-pools
- 提名池功能通常需要与Staking模块配合使用
- 注意权限控制,特别是池的创建和管理操作
- 考虑池成员的最小和最大数量限制
- 注意奖励分配机制的公平性
通过pallet-nomination-pools-runtime-api
,开发者可以方便地在Substrate链上实现提名质押功能,为用户提供更灵活的质押选项。