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
获取交易对信息,然后使用simulate
和reverse_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?;
最佳实践
- 错误处理:始终处理智能合约调用的结果
match client.swap(/* ... */).await {
Ok(result) => println!("Swap successful: {:?}", result),
Err(e) => eprintln!("Swap failed: {}", e),
}
- Gas估算:在执行交易前估算gas
let gas_estimate = client.estimate_gas(
&astroport::msg::ExecuteMsg::Swap { /* ... */ }
).await?;
- 事件监听:订阅池子事件
let mut events = client.subscribe_pool_events(&pool_id).await?;
while let Some(event) = events.next().await {
println!("Pool event: {:?}", event);
}
安全注意事项
- 始终验证合约地址
- 设置合理的滑点容差
- 定期检查智能合约升级
- 使用官方发布的合约版本
- 在生产环境使用前充分测试
完整示例代码
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(())
})
}