Rust跨链DeFi插件库Astroport的使用,Astroport提供高效资产交换与流动性管理的智能合约解决方案

Astroport: 跨链DeFi插件库的使用

Astroport是一个提供高效资产交换与流动性管理的智能合约解决方案的Rust跨链DeFi插件库。以下是其主要功能和用法:

数据类型

AssetInfo

AssetInfo是一个便利包装器,用于表示代币是原生代币(来自特定链,如Terra的LUNA)还是非原生代币。它还返回该代币的合约地址。

pub enum AssetInfo {
    Token { contract_addr: Addr },
    NativeToken { denom: String },
}

Asset

包含资产信息和代币数量。

pub struct Asset {
    pub info: AssetInfo,
    pub amount: Uint128,
}

PairInfo

用于表示来自Pair-Info-Querier的响应数据。

pub struct PairInfo {
    pub asset_infos: [AssetInfo; 2],
    pub contract_addr: Addr,
    pub liquidity_token: String,
    pub pair_type: PairType,
}

查询器

Native Token Balance Querier

使用CosmWasm标准接口查询账户余额。

pub fn query_balance(
    querier: &QuerierWrapper,
    account_addr: impl Into<String>,
    denom: impl Into<String>,
) -> StdResult<Uint128>

Token Balance Querier

为查询CW20代币余额提供类似的查询接口。

pub fn query_token_balance(
    querier: &QuerierWrapper,
    contract_addr: impl Into<String>,
    account_addr: impl Into<String>,
) -> StdResult<Uint128>

Token Supply Querier

查询CW20代币的总供应量。

pub fn query_supply(
    querier: &QuerierWrapper,
    contract_addr: impl Into<String>,
) -> StdResult<Uint128>

Pair Info Querier

接受两个代币作为输入并返回交易对的信息。

pub fn query_pair_info(
    querier: &QuerierWrapper,
    factory_contract: impl Into<String>,
    asset_infos: &[AssetInfo; 2],
) -> StdResult<PairInfo>

交易对模拟

Simulate

模拟交换并返回输出金额、价差和佣金金额。

pub fn simulate(
    querier: &QuerierWrapper,
    pair_contract: impl Into<String>,
    offer_asset: &Asset,
) -> StdResult<SimulationResponse>

Reverse Simulate

模拟反向交换并返回输入金额、价差和佣金金额。

pub fn reverse_simulate(
    querier: &QuerierWrapper,
    pair_contract: impl Into<String>,
    offer_asset: &Asset,
) -> StdResult<ReverseSimulationResponse>

完整示例

以下是使用Astroport进行资产交换的完整示例:

use astroport::asset::{Asset, AssetInfo};
use astroport::pair::PairInfo;
use cosmwasm_std::{Addr, QuerierWrapper, StdResult, Uint128};

// 初始化资产信息
let asset1 = AssetInfo::Token {
    contract_addr: Addr::unchecked("token1_contract_addr"),
};
let asset2 = AssetInfo::NativeToken {
    denom: "uluna".to_string(),
};

// 查询交易对信息
let pair_info: PairInfo = query_pair_info(
    &querier,
    "factory_contract_addr",
    &[asset1.clone(), asset2.clone()],
)?;

// 准备交换资产
let offer_asset = Asset {
    info: asset1,
    amount: Uint128::from(1000000u128),
};

// 模拟交换
let simulation = simulate(&querier, pair_info.contract_addr, &offer_asset)?;

println!("模拟交换结果:");
println!("输出金额: {}", simulation.return_amount);
println!("价差: {}", simulation.spread_amount);
println!("佣金: {}", simulation.commission_amount);

// 反向模拟
let ask_asset = Asset {
    info: asset2,
    amount: Uint128::from(500000u128),
};

let reverse_simulation = reverse_simulate(&querier, pair_info.contract_addr, &ask_asset)?;

println!("\n反向模拟结果:");
println!("输入金额: {}", reverse_simulation.offer_amount);
println!("价差: {}", reverse_simulation.spread_amount);
println!("佣金: {}", reverse_simulation.commission_amount);

这个示例展示了如何使用Astroport库的核心功能进行资产交换模拟和反向模拟。通过query_pair_info获取交易对信息,然后使用simulatereverse_simulate来预测交换结果。

要使用该库,请在您的Cargo.toml中添加依赖:

astroport = "5.9.0"

1 回复

Rust跨链DeFi插件库Astroport的使用指南

Astroport简介

Astroport是一个基于Rust构建的跨链DeFi插件库,专注于提供高效的资产交换与流动性管理的智能合约解决方案。它旨在成为多链生态系统中的流动性中心,支持不同区块链网络间的资产无缝流动。

主要特性:

  • 跨链资产交换
  • 自动化流动性管理
  • 高效的智能合约执行
  • 可组合的DeFi模块
  • 支持多种资产类型

安装与配置

在Cargo.toml中添加依赖:

[dependencies]
astroport = { version = "0.5.0", features = ["full"] }

基本使用方法

1. 初始化Astroport客户端

use astroport::client::AstroportClient;
use astroport::types::Network;

let client = AstroportClient::new(
    Network::Terra, // 选择网络
    "https://terra-node.example.com" // 节点URL
).await?;

2. 创建流动性池

use astroport::asset::{Asset, AssetInfo};

let asset1 = Asset {
    info: AssetInfo::NativeToken {
        denom: "uluna".to_string(),
    },
    amount: 100_000u128.into(),
};

let asset2 = Asset {
    info: AssetInfo::Token {
        contract_addr: "terra1...".to_string(),
    },
    amount: 50_000u128.into(),
};

let pool_id = client.create_pool(
    "my_pool_label", // 池子标签
    &[asset1, asset2], // 初始资产
    0.3, // 交易费比例
    None // 可选的自定义参数
).await?;

3. 执行资产交换

use astroport::swap::SwapOperation;

let swap_result = client.swap(
    SwapOperation::NativeSwap {
        offer_denom: "uluna".to_string(),
        ask_denom: "uusd".to_string(),
    },
    1000u128.into(), // 交换数量
    None, // 最大价差(可选)
    None // 接收地址(可选
).await?;

4. 添加流动性

let liquidity_amounts = vec![
    (AssetInfo::NativeToken { denom: "uluna".to_string() }, 5000u128.into()),
    (AssetInfo::Token { contract_addr: "terra1...".to_string() }, 2500u128.into()),
];

let lp_tokens = client.add_liquidity(
    &pool_id,
    &liquidity_amounts,
    None, // 滑点容差(可选)
    None // 接收地址(可选)
).await?;

5. 移除流动性

let withdrawn_assets = client.remove_liquidity(
    &pool_id,
    lp_tokens.amount, // 要移除的LP代币数量
    None // 接收地址(可选)
).await?;

高级功能

跨链交换

use astroport::ibc::IbcChannel;

let cross_chain_swap = client.swap_with_ibc(
    SwapOperation::CrossChainSwap {
        offer_asset: AssetInfo::NativeToken { denom: "uluna".to_string() },
        ask_asset: AssetInfo::Token { 
            contract_addr: "osmosis1...".to_string() 
        },
        ibc_channel: IbcChannel::new("channel-42"),
    },
    1000u128.into(),
    None,
    None
).await?;

自定义流动性池参数

use astroport::pool::PoolParameters;

let params = PoolParameters {
    amp: 100, // 放大系数,影响曲线形状
    fee: 0.002, // 交易费
    admin_fee: 0.0005, // 管理员费
    withdraw_fee: 0.001, // 提款费
};

let custom_pool = client.create_pool(
    "custom_curve_pool",
    &[asset1, asset2],
    params,
    Some("terra1adminaddress...".to_string()) // 可选的管理员地址
).await?;

最佳实践

  1. 错误处理:始终处理智能合约调用的结果
match client.swap(/* ... */).await {
    Ok(result) => println!("Swap successful: {:?}", result),
    Err(e) => eprintln!("Swap failed: {}", e),
}
  1. Gas估算:在执行交易前估算gas
let gas_estimate = client.estimate_gas(
    &astroport::msg::ExecuteMsg::Swap { /* ... */ }
).await?;
  1. 事件监听:订阅池子事件
let mut events = client.subscribe_pool_events(&pool_id).await?;
while let Some(event) = events.next().await {
    println!("Pool event: {:?}", event);
}

安全注意事项

  1. 始终验证合约地址
  2. 设置合理的滑点容差
  3. 定期检查智能合约升级
  4. 使用官方发布的合约版本
  5. 在生产环境使用前充分测试

完整示例代码

use astroport::{
    client::AstroportClient,
    types::Network,
    asset::{Asset, AssetInfo},
    swap::SwapOperation,
    pool::PoolParameters
};
use tokio::runtime::Runtime;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let rt = Runtime::new()?;
    
    rt.block_on(async {
        // 1. 初始化客户端
        let client = AstroportClient::new(
            Network::Terra,
            "https://terra-node.example.com"
        ).await?;
        
        // 2. 创建流动性池
        let asset1 = Asset {
            info: AssetInfo::NativeToken {
                denom: "uluna".to_string(),
            },
            amount: 100_000u128.into(),
        };
        
        let asset2 = Asset {
            info: AssetInfo::Token {
                contract_addr: "terra1...".to_string(),
            },
            amount: 50_000u128.into(),
        };
        
        let pool_id = client.create_pool(
            "my_pool",
            &[asset1, asset2],
            0.3,
            None
        ).await?;
        
        // 3. 执行资产交换
        let swap_result = client.swap(
            SwapOperation::NativeSwap {
                offer_denom: "uluna".to_string(),
                ask_denom: "uusd".to_string(),
            },
            1000u128.into(),
            None,
            None
        ).await?;
        
        println!("Swap result: {:?}", swap_result);
        
        // 4. 添加流动性
        let liquidity_amounts = vec![
            (AssetInfo::NativeToken { denom: "uluna".to_string() }, 5000u128.into()),
            (AssetInfo::Token { contract_addr: "terra1...".to_string() }, 2500u128.into()),
        ];
        
        let lp_tokens = client.add_liquidity(
            &pool_id,
            &liquidity_amounts,
            None,
            None
        ).await?;
        
        println!("Received LP tokens: {:?}", lp_tokens);
        
        // 5. 移除流动性
        let withdrawn = client.remove_liquidity(
            &pool_id,
            lp_tokens.amount,
            None
        ).await?;
        
        println!("Withdrawn assets: {:?}", withdrawn);
        
        Ok(())
    })
}
回到顶部