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),
    }
}

功能说明

  1. 提名池信息查询: 通过get_pool_info_at方法可以查询特定区块高度的质押池信息
  2. 活跃池列表及详细信息: 通过get_all_active_pools_info方法获取所有活跃质押池及其详细信息
  3. 运行时集成: 与Substrate运行时无缝集成,支持区块链状态查询
  4. 区块高度支持: 可以查询特定区块高度的池信息

注意事项

  • 使用时需要确保您的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)
}

注意事项

  1. 使用前确保你的链已经正确配置了pallet-nomination-pools
  2. 提名池功能通常需要与Staking模块配合使用
  3. 注意权限控制,特别是池的创建和管理操作
  4. 考虑池成员的最小和最大数量限制
  5. 注意奖励分配机制的公平性

通过pallet-nomination-pools-runtime-api,开发者可以方便地在Substrate链上实现提名质押功能,为用户提供更灵活的质押选项。

回到顶部