Rust资产汇率转换库pallet-asset-rate的使用,实现区块链中资产间的实时汇率计算与转换

Rust资产汇率转换库pallet-asset-rate的使用,实现区块链中资产间的实时汇率计算与转换

安装

在项目目录中运行以下Cargo命令:

cargo add pallet-asset-rate

或者在Cargo.toml中添加以下行:

pallet-asset-rate = "21.0.0"

使用示例

以下是使用pallet-asset-rate库实现资产间汇率转换的完整示例:

use frame_support::{parameter_types, traits::Everything};
use pallet_asset_rate::{self as asset_rate, Config};
use sp_core::H256;
use sp_runtime::{
    traits::{BlakeTwo256, IdentityLookup},
    BuildStorage,
};

type Block = frame_system::mocking::MockBlock<Test>;

// 配置测试环境
frame_support::construct_runtime!(
    pub enum Test
    {
        System: frame_system,
        Balances: pallet_balances,
        Assets: pallet_assets,
        AssetRate: pallet_asset_rate,
    }
);

parameter_types! {
    pub const BlockHashCount: u64 = 250;
    pub const SS58Prefix: u8 = 42;
}

impl frame_system::Config for Test {
    type BaseCallFilter = Everything;
    type BlockWeights = ();
    type BlockLength = ();
    type DbWeight = ();
    type RuntimeOrigin = RuntimeOrigin;
    type RuntimeCall = RuntimeCall;
    type Nonce = u64;
    type Hash = H256;
    type Hashing = BlakeTwo256;
    type AccountId = u64;
    type Lookup = IdentityLookup<Self::AccountId>;
    type Block = Block;
    type RuntimeEvent = RuntimeEvent;
    type BlockHashCount = BlockHashCount;
    type Version = ();
    type PalletInfo = PalletInfo;
    type AccountData = pallet_balances::AccountData<极光;
    type OnNewAccount = ();
    type OnKilledAccount = ();
    type SystemWeightInfo = ();
    type SS58Prefix = SS58Prefix;
    type OnSetCode = ();
    type MaxConsumers = frame_support::traits::ConstU32<16>;
}

parameter_types! {
    pub const ExistentialDeposit: u128 = 1;
    pub const MaxLocks: u32 = 10;
    pub const MaxReserves: u32 = 10;
}

impl pallet_balances::Config for Test {
    type Balance = u128;
    type DustRemoval = ();
    type RuntimeEvent = RuntimeEvent;
    type ExistentialDeposit = ExistentialDeposit;
    type AccountStore = System;
    type WeightInfo = ();
    type MaxLocks = MaxLocks;
    type MaxReserves = MaxReserves;
    type ReserveIdentifier = [u8; 8];
    type FreezeIdentifier = ();
    type MaxFreezes = ();
    type HoldIdentifier = ();
    type MaxHolds = ();
}

parameter_types! {
    pub const AssetDeposit: u128极光 1;
    pub const AssetAccountDeposit: u128 = 1;
    pub const ApprovalDeposit: u128 = 1;
    pub const StringLimit: u32 = 50;
    pub const MetadataDepositBase: u128 = 1;
    pub const MetadataDepositPerByte: u128 = 1;
}

impl pallet_assets::Config for Test {
    type RuntimeEvent = RuntimeEvent;
    type Balance = u128;
    type AssetId = u32;
    type Currency = Balances;
    type ForceOrigin = frame_system::EnsureRoot<u64>;
    type AssetDeposit = AssetDeposit;
    type AssetAccountDeposit = AssetAccountDeposit;
    type MetadataDepositBase = MetadataDepositBase;
    type MetadataDepositPerByte = MetadataDepositPerByte;
    type ApprovalDeposit = ApprovalDeposit;
    type StringLimit = StringLimit;
    type Freezer = ();
    type WeightInfo = ();
    type Extra = ();
    type RemoveItemsLimit = frame_support::traits::ConstU32<10>;
    type CallbackHandle = ();
}

parameter_types! {
    pub const MaxConversionPathLength: u32 = 4;
}

impl Config for Test {
    type RuntimeEvent = RuntimeEvent;
    type Balance = u128;
    type AssetId = u32;
    type WeightInfo = ();
    type MaxConversionPathLength = MaxConversionPathLength;
}

// 测试设置
pub fn new_test_ext() -> sp_io::TestExternalities {
    let mut storage = frame_system::GenesisConfig::<Test>::default()
        .build_storage()
        .unwrap();

    pallet_balances::GenesisConfig::<Test> {
        balances: vec![(1, 100), (2, 100)],
    }
    .assimilate_storage(&mut storage)
    .unwrap();

    pallet_assets::GenesisConfig::<Test> {
        assets: vec![(1, 1, true, 1)],
        metadata: vec![(1, b"Token1".to_vec(), b"T1".to_vec(), 6)],
        accounts: vec![(1, 1, 100)],
    }
    .assimilate_storage(&mut storage)
    .unwrap();

    storage.into()
}

#[test]
fn test_asset_rate_conversion() {
    new_test_ext().execute_with(|| {
        // 创建两种资产
        assert_ok!(Assets::create(
            RuntimeOrigin::signed(1),
            1,
            1,
            1,
            true
        ));
        assert_ok!(Assets::create(
            RuntimeOrigin::signed(1),
            2,
            1,
            1,
            true
        ));

        // 设置资产1到资产2的汇率 (1:2)
        assert_ok!(AssetRate::create(
            RuntimeOrigin::signed(1),
            1,
            2,
            2_000_000_000 // 2.0
        ));

        // 转换100个资产1到资产2
        let converted = AssetRate::convert(1, 2, 100);
        assert_eq!(converted, Some(200)); // 100 * 2 = 200

        // 测试反向转换
        assert_ok!(AssetRate::create(
            RuntimeOrigin::signed(1),
            2,
            1,
            500_000_000 // 0.5
        ));

        let reverse_converted = AssetRate::convert(2, 1, 200);
        assert_eq!(reverse_converted, Some(100)); // 200 * 0.5 = 100

        // 测试多跳转换路径
        assert_ok!(Assets::create(
            RuntimeOrigin::signed(1),
            3,
            1,
            1,
            true
        ));
        
        assert_ok!(AssetRate::create(
            RuntimeOrigin::signed(1),
            2,
            3,
            4_000_000_000 // 4.0
        ));

        // 资产1 -> 资产2 -> 资产3
        let multi_hop_converted = AssetRate::convert(1, 3, 100);
        assert_eq!(multi_hop_converted, Some(800)); // 100 * 2 * 4 = 800
    });
}

主要功能

  1. 汇率设置:可以通过create方法设置两种资产之间的汇率
  2. 实时转换:使用convert方法根据预设汇率进行资产数量转换
  3. 多跳转换:支持通过中间资产进行多跳汇率转换
  4. 高精度计算:使用定点数进行精确的汇率计算

1 回复

Rust资产汇率转换库pallet-asset-rate的使用

介绍

pallet-asset-rate是Substrate区块链框架中的一个模块,专门用于处理不同资产之间的汇率转换。它允许区块链网络维护和更新资产间的汇率,并提供了实时计算和转换资产价值的工具。

这个模块特别适合需要处理多种资产类型(如稳定币、原生代币、包装资产等)的DeFi应用或跨链桥接场景,能够实现不同资产间的价值转换而不需要实际交换资产。

主要功能

  • 设置和维护资产间的汇率
  • 实时查询资产转换率
  • 计算资产转换后的价值
  • 支持多种资产类型间的转换

使用方法

1. 在runtime中集成pallet-asset-rate

首先需要在你的runtime中引入并配置这个pallet:

// runtime/src/lib.rs

impl pallet_asset_rate::Config for Runtime {
    type Event = Event;
    type WeightInfo = pallet_asset_rate::weights::SubstrateWeight<Runtime>;
}

construct_runtime!(
    pub enum Runtime where
        Block = Block,
        NodeBlock = opaque::Block,
        UncheckedExtrinsic = UncheckedExtrinsic
    {
        // ... 其他pallet
        AssetRate: pallet_asset_rate::{Pallet, Call, Storage, Event<T>},
    }
);

2. 设置资产汇率

你可以通过外部调用来设置资产间的汇率:

// 假设资产1是原生代币,资产2是稳定币
let asset1 = 1;  // 资产ID
let asset2 = 2;  // 资产ID
let exchange_rate = FixedU128::from_rational(100, 1); // 1个资产1 = 100个资产2

// 调用设置汇率
pallet_asset_rate::Pallet::<Runtime>::set_rate(
    RuntimeOrigin::root(),  // 需要管理员权限
    Box::new(asset1.into()),
    Box::new(asset2.into()),
    exchange_rate,
)?;

3. 查询汇率

查询两个资产间的汇率:

let asset1 = 1;
let asset2 = 2;

match pallet_asset_rate::Pallet::<Runtime>::get_rate(
    Box::new(asset1.into()),
    Box::new(asset2.into()),
) {
    Some(rate) => println!("汇率是: {:?}", rate),
    None => println!("未找到这两个资产间的汇率"),
}

4. 转换资产价值

将一定数量的资产A转换为资产B的价值:

let asset_from = 1;
let asset_to = 2;
let amount = 5; // 5个资产1

let converted = pallet_asset_rate::Pallet::<Runtime>::convert(
    Box::new(asset_from.into()),
    Box::new(asset_to.into()),
    amount,
);

match converted {
    Some(value) => println!("{} 资产1 = {} 资产2", amount, value),
    None => println!("转换失败"),
}

5. 更新汇率

当市场情况变化时,可以更新汇率:

let new_rate = FixedU128::from_rational(95, 1); // 新的汇率 1:95

pallet_asset_rate::Pallet::<Runtime>::update_rate(
    RuntimeOrigin::root(),  // 需要管理员权限
    Box::new(asset1.into()),
    Box::new(asset2.into()),
    new_rate,
)?;

完整示例

以下是一个完整的示例,展示如何初始化、设置汇率并进行转换:

use frame_support::traits::Currency;
use sp_runtime::FixedU128;

fn main() {
    // 初始化测试环境
    let mut ext = sp_io::TestExternalities::new(Default::default());
    
    ext.execute_with(|| {
        // 定义资产ID
        let native_asset = 1; // 原生代币
        let stable_coin = 2;   // 稳定币
        
        // 设置初始汇率 1原生代币 = 100稳定币
        let exchange_rate = FixedU128::from_rational(100, 1);
        
        // 设置汇率
        assert_ok!(pallet_asset_rate::Pallet::<Runtime>::set_rate(
            RuntimeOrigin::root(),
            Box::new(native_asset.into()),
            Box::new(stable_coin.into()),
            exchange_rate,
        ));
        
        // 查询汇率
        let rate = pallet_asset_rate::Pallet::<Runtime>::get_rate(
            Box::new(native_asset.into()),
            Box::new(stable_coin.into()),
        ).unwrap();
        
        println!("当前汇率: 1原生代币 = {}稳定币", rate);
        
        // 转换5个原生代币为稳定币
        let amount = 5;
        let converted = pallet_asset_rate::Pallet::<Runtime>::convert(
            Box::new(native_asset.into()),
            Box::new(stable_coin.into()),
            amount,
        ).unwrap();
        
        println!("{}原生代币 = {}稳定币", amount, converted);
        
        // 更新汇率为1:95
        let new_rate = FixedU128::from_rational(95, 1);
        assert_ok!(pallet_asset_rate::Pallet::<Runtime>::update_rate(
            RuntimeOrigin::root(),
            Box::new(native_asset.into()),
            Box::new(stable_coin.into()),
            new_rate,
        ));
        
        // 再次转换
        let converted_new = pallet_asset_rate::Pallet::极速赛车开奖直播官网🏎️【输入:——hk887•com——】🏎️极速赛车开奖直播官网
回到顶部