use std::fmt;
use cosmwasm_schema::{cw_serde, QueryResponses};
use cosmwasm_std::{Addr, Coin, Decimal, Deps, StdError, StdResult, Uint128};
use cw_ownable::{cw_ownable_execute, cw_ownable_query};
use crate::coin::is_factory_token;
use crate::fee::PoolFee;
#[cw_serde]
pub enum SwapOperation {
MantraSwap {
token_in_denom: String,
token_out_denom: String,
pool_identifier: String,
},
}
impl SwapOperation {
pub fn get_input_asset_info(&self) -> &String {
match self {
SwapOperation::MantraSwap { token_in_denom, .. } => token_in_denom,
}
}
pub fn get_target_asset_info(&self) -> String {
match self {
SwapOperation::MantraSwap {
token_out_denom, ..
} => token_out_denom.clone(),
}
}
pub fn get_pool_identifer(&self) -> String {
match self {
SwapOperation::MantraSwap {
pool_identifier, ..
} => pool_identifier.clone(),
}
}
}
impl fmt::Display for SwapOperation {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
SwapOperation::MantraSwap {
token_in_denom,
token_out_denom,
pool_identifier,
} => write!(
f,
"MantraSwap {{ token_in_info: {token_in_denom}, token_out_info: {token_out_denom}, pool_identifier: {pool_identifier} }}"
),
}
}
}
#[cw_serde]
pub struct PoolInfo {
pub pool_identifier: String,
pub asset_denoms: Vec<String>,
pub lp_denom: String,
pub asset_decimals: Vec<u8>,
pub assets: Vec<Coin>,
pub pool_type: PoolType,
pub pool_fees: PoolFee,
pub status: PoolStatus,
}
#[cw_serde]
pub enum PoolType {
StableSwap {
amp: u64,
},
ConstantProduct,
}
impl PoolType {
pub fn get_label(&self) -> &str {
match self {
PoolType::ConstantProduct => "ConstantProduct",
PoolType::StableSwap { .. } => "StableSwap",
}
}
}
#[cw_serde]
pub struct PoolStatus {
pub swaps_enabled: bool,
pub deposits_enabled: bool,
pub withdrawals_enabled: bool,
}
impl Default for PoolStatus {
fn default() -> Self {
PoolStatus {
swaps_enabled: true,
deposits_enabled: true,
withdrawals_enabled: true,
}
}
}
#[cw_serde]
pub struct Config {
pub fee_collector_addr: Addr,
pub farm_manager_addr: Addr,
pub pool_creation_fee: Coin,
}
#[cw_serde]
pub struct InstantiateMsg {
pub fee_collector_addr: String,
pub farm_manager_addr: String,
pub pool_creation_fee: Coin,
}
#[cw_serde]
pub struct MigrateMsg {}
#[cw_ownable_execute]
#[cw_serde]
pub enum ExecuteMsg {
CreatePool {
asset_denoms: Vec<String>,
asset_decimals: Vec<u8>,
pool_fees: PoolFee,
pool_type: PoolType,
pool_identifier: Option<String>,
},
ProvideLiquidity {
slippage_tolerance: Option<Decimal>,
max_spread: Option<Decimal>,
receiver: Option<String>,
pool_identifier: String,
unlocking_duration: Option<u64>,
lock_position_identifier: Option<String>,
},
Swap {
ask_asset_denom: String,
belief_price: Option<Decimal>,
max_spread: Option<Decimal>,
receiver: Option<String>,
pool_identifier: String,
},
WithdrawLiquidity { pool_identifier: String },
ExecuteSwapOperations {
operations: Vec<SwapOperation>,
minimum_receive: Option<Uint128>,
receiver: Option<String>,
max_spread: Option<Decimal>,
},
UpdateConfig {
fee_collector_addr: Option<String>,
farm_manager_addr: Option<String>,
pool_creation_fee: Option<Coin>,
feature_toggle: Option<FeatureToggle>,
},
}
#[cw_ownable_query]
#[cw_serde]
#[derive(QueryResponses)]
pub enum QueryMsg {
#[returns(ConfigResponse)]
Config {},
#[returns(AssetDecimalsResponse)]
AssetDecimals {
pool_identifier: String,
denom: String,
},
#[returns(SimulationResponse)]
Simulation {
offer_asset: Coin,
ask_asset_denom: String,
pool_identifier: String,
},
#[returns(ReverseSimulationResponse)]
ReverseSimulation {
ask_asset: Coin,
offer_asset_denom: String,
pool_identifier: String,
},
#[returns(SimulateSwapOperationsResponse)]
SimulateSwapOperations {
offer_amount: Uint128,
operations: Vec<SwapOperation>,
},
#[returns(ReverseSimulateSwapOperationsResponse)]
ReverseSimulateSwapOperations {
ask_amount: Uint128,
operations: Vec<SwapOperation>,
},
#[returns(PoolsResponse)]
Pools {
pool_identifier: Option<String>,
start_after: Option<String>,
limit: Option<u32>,
},
}
#[cw_serde]
pub struct ConfigResponse {
pub config: Config,
}
#[cw_serde]
pub struct PoolsResponse {
pub pools: Vec<PoolInfoResponse>,
}
#[cw_serde]
pub struct PoolInfoResponse {
pub pool_info: PoolInfo,
pub total_share: Coin,
}
#[cw_serde]
pub struct AssetDecimalsResponse {
pub pool_identifier: String,
pub denom: String,
pub decimals: u8,
}
#[cw_serde]
pub struct SimulationResponse {
pub return_amount: Uint128,
pub spread_amount: Uint128,
pub swap_fee_amount: Uint128,
pub protocol_fee_amount: Uint128,
pub burn_fee_amount: Uint128,
pub extra_fees_amount: Uint128,
}
#[cw_serde]
pub struct ReverseSimulationResponse {
pub offer_amount: Uint128,
pub spread_amount: Uint128,
pub swap_fee_amount: Uint128,
pub protocol_fee_amount: Uint128,
pub burn_fee_amount: Uint128,
pub extra_fees_amount: Uint128,
}
#[cw_serde]
pub struct FeatureToggle {
pub pool_identifier: String,
pub withdrawals_enabled: Option<bool>,
pub deposits_enabled: Option<bool>,
pub swaps_enabled: Option<bool>,
}
#[cw_serde]
pub struct SimulateSwapOperationsResponse {
pub return_amount: Uint128,
pub spreads: Vec<Coin>,
pub swap_fees: Vec<Coin>,
pub protocol_fees: Vec<Coin>,
pub burn_fees: Vec<Coin>,
pub extra_fees: Vec<Coin>,
}
#[cw_serde]
pub struct ReverseSimulateSwapOperationsResponse {
pub offer_amount: Uint128,
pub spreads: Vec<Coin>,
pub swap_fees: Vec<Coin>,
pub protocol_fees: Vec<Coin>,
pub burn_fees: Vec<Coin>,
pub extra_fees: Vec<Coin>,
}
pub fn get_total_share(deps: &Deps, liquidity_asset: String) -> StdResult<Uint128> {
if is_factory_token(liquidity_asset.as_str()) {
return Ok(deps.querier.query_supply(&liquidity_asset)?.amount);
}
Err(StdError::generic_err("Invalid LP token"))
}