use crate::asset::{Asset, AssetInfo};
use cosmwasm_schema::{cw_serde, QueryResponses};
use cosmwasm_std::{Addr, Binary, Decimal, Uint128};
use cw20::Cw20ReceiveMsg;
use std::fmt::{Display, Formatter, Result};
pub const TWAP_PRECISION: u16 = 9u16;
#[cw_serde]
pub enum PoolType {
StableSwap {},
Weighted {},
Custom(String),
}
impl Display for PoolType {
fn fmt(&self, fmt: &mut Formatter) -> Result {
match self {
PoolType::Weighted {} => fmt.write_str("weighted"),
PoolType::StableSwap {} => fmt.write_str("stable-swap"),
PoolType::Custom(pool_type) => fmt.write_str(format!("custom-{}", pool_type).as_str()),
}
}
}
#[cw_serde]
pub enum SwapType {
GiveIn {},
GiveOut {},
Custom(String),
}
impl Display for SwapType {
fn fmt(&self, fmt: &mut Formatter) -> Result {
match self {
SwapType::GiveIn {} => fmt.write_str("give-in"),
SwapType::GiveOut {} => fmt.write_str("give-out"),
SwapType::Custom(swap_type) => fmt.write_str(format!("custom-{}", swap_type).as_str()),
}
}
}
pub const FEE_PRECISION: u16 = 10_000u16;
const MAX_TOTAL_FEE_BPS: u16 = 1_000u16;
const MAX_PROTOCOL_FEE_PERCENT: u16 = 100u16;
#[cw_serde]
pub struct FeeInfo {
pub total_fee_bps: u16,
pub protocol_fee_percent: u16,
}
impl FeeInfo {
pub fn valid_fee_info(&self) -> bool {
self.total_fee_bps <= MAX_TOTAL_FEE_BPS
&& self.protocol_fee_percent <= MAX_PROTOCOL_FEE_PERCENT
}
pub fn calculate_total_fee_breakup(&self, total_fee: Uint128) -> Uint128 {
let protocol_fee: Uint128 =
total_fee * Decimal::from_ratio(self.protocol_fee_percent, Uint128::from(100u128));
protocol_fee
}
}
#[cw_serde]
pub struct NativeAssetPrecisionInfo {
pub denom: String,
pub precision: u8,
}
#[cw_serde]
pub struct Config {
pub owner: Addr,
pub whitelisted_addresses: Vec<Addr>,
pub lp_token_code_id: Option<u64>,
pub fee_collector: Option<Addr>,
pub auto_stake_impl: AutoStakeImpl,
pub pool_creation_fee: PoolCreationFee,
pub next_pool_id: Uint128,
pub paused: PauseInfo,
}
#[cw_serde]
pub enum AllowPoolInstantiation {
Everyone,
OnlyWhitelistedAddresses,
Nobody,
}
impl Display for AllowPoolInstantiation {
fn fmt(&self, fmt: &mut Formatter) -> Result {
match self {
AllowPoolInstantiation::Everyone => fmt.write_str("everyone"),
AllowPoolInstantiation::OnlyWhitelistedAddresses => {
fmt.write_str("only-whitelisted-addresses")
}
AllowPoolInstantiation::Nobody => fmt.write_str("nobody"),
}
}
}
#[cw_serde]
pub struct PoolTypeConfig {
pub code_id: u64,
pub pool_type: PoolType,
pub default_fee_info: FeeInfo,
pub allow_instantiation: AllowPoolInstantiation,
pub paused: PauseInfo,
}
#[cw_serde]
pub struct TmpPoolInfo {
pub code_id: u64,
pub pool_id: Uint128,
pub lp_token_addr: Option<Addr>,
pub fee_info: FeeInfo,
pub assets: Vec<Asset>,
pub native_asset_precisions: Vec<NativeAssetPrecisionInfo>,
pub pool_type: PoolType,
pub init_params: Option<Binary>,
}
#[cw_serde]
pub struct PoolInfo {
pub pool_id: Uint128,
pub pool_addr: Addr,
pub lp_token_addr: Addr,
pub fee_info: FeeInfo,
pub assets: Vec<Asset>,
pub pool_type: PoolType,
pub paused: PauseInfo,
}
#[cw_serde]
#[derive(Default)]
pub struct PauseInfo {
pub swap: bool,
pub deposit: bool,
pub imbalanced_withdraw: bool,
}
#[cw_serde]
pub enum PoolCreationFee {
Disabled,
Enabled {
fee: Asset
}
}
impl Default for PoolCreationFee {
fn default() -> Self {
PoolCreationFee::Disabled
}
}
impl Display for PauseInfo {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
f.write_str(format!("swap: {}, deposit: {}", self.swap, self.deposit).as_str())
}
}
#[cw_serde]
pub struct SingleSwapRequest {
pub pool_id: Uint128,
pub asset_in: AssetInfo,
pub asset_out: AssetInfo,
pub swap_type: SwapType,
pub amount: Uint128,
}
#[cw_serde]
pub enum AutoStakeImpl {
None,
Multistaking {
contract_addr: Addr,
}
}
impl Display for AutoStakeImpl {
fn fmt(&self, fmt: &mut Formatter) -> Result {
match &self {
AutoStakeImpl::None => fmt.write_str("none"),
AutoStakeImpl::Multistaking { contract_addr } => {
fmt.write_str(format!("multistaking: {}", contract_addr).as_str())
}
}
}
}
#[cw_serde]
pub struct InstantiateMsg {
pub owner: String,
pub pool_configs: Vec<PoolTypeConfig>,
pub lp_token_code_id: Option<u64>,
pub fee_collector: Option<String>,
pub pool_creation_fee: PoolCreationFee,
pub auto_stake_impl: AutoStakeImpl
}
#[cw_serde]
pub enum PauseInfoUpdateType {
PoolId(Uint128),
PoolType(PoolType)
}
#[cw_serde]
pub enum ExecuteMsg {
Receive(Cw20ReceiveMsg),
UpdateConfig {
lp_token_code_id: Option<u64>,
fee_collector: Option<String>,
pool_creation_fee: Option<PoolCreationFee>,
auto_stake_impl: Option<AutoStakeImpl>,
paused: Option<PauseInfo>,
},
AddAddressToWhitelist {
address: String
},
RemoveAddressFromWhitelist {
address: String
},
UpdatePauseInfo {
update_type: PauseInfoUpdateType,
pause_info: PauseInfo,
},
UpdatePoolTypeConfig {
pool_type: PoolType,
allow_instantiation: Option<AllowPoolInstantiation>,
new_fee_info: Option<FeeInfo>,
paused: Option<PauseInfo>,
},
AddToRegistry {
new_pool_type_config: PoolTypeConfig,
},
CreatePoolInstance {
pool_type: PoolType,
asset_infos: Vec<AssetInfo>,
native_asset_precisions: Vec<NativeAssetPrecisionInfo>,
fee_info: Option<FeeInfo>,
init_params: Option<Binary>,
},
UpdatePoolConfig {
pool_id: Uint128,
fee_info: Option<FeeInfo>,
paused: Option<PauseInfo>,
},
UpdatePoolParams {
pool_id: Uint128,
params: Binary,
},
JoinPool {
pool_id: Uint128,
recipient: Option<String>,
assets: Option<Vec<Asset>>,
min_lp_to_receive: Option<Uint128>,
auto_stake: Option<bool>,
},
Swap {
swap_request: SingleSwapRequest,
recipient: Option<String>,
min_receive: Option<Uint128>,
max_spend: Option<Uint128>,
},
ProposeNewOwner {
new_owner: String,
expires_in: u64,
},
DropOwnershipProposal {},
ClaimOwnership {},
}
#[cw_serde]
pub enum Cw20HookMsg {
ExitPool {
pool_id: Uint128,
recipient: Option<String>,
exit_type: ExitType,
},
}
#[cw_serde]
pub enum ExitType {
ExactLpBurn {
lp_to_burn: Uint128,
min_assets_out: Option<Vec<Asset>>,
},
ExactAssetsOut {
assets_out: Vec<Asset>,
max_lp_to_burn: Option<Uint128>,
}
}
#[cw_serde]
#[derive(QueryResponses)]
pub enum QueryMsg {
#[returns[ConfigResponse]]
Config {},
#[returns(PoolTypeConfigResponse)]
QueryRegistry { pool_type: PoolType },
#[returns(Vec<PoolInfoResponse>)]
Pools { start_after: Option<Uint128>, limit: Option<u32> },
#[returns(PoolInfoResponse)]
GetPoolById { pool_id: Uint128 },
#[returns(PoolInfoResponse)]
GetPoolByAddress { pool_addr: String },
#[returns(PoolInfoResponse)]
GetPoolByLpTokenAddress { lp_token_addr: String },
}
#[cw_serde]
pub enum MigrateMsg {
V1_1 {
updated_pool_type_configs: Vec<PoolTypeConfig>,
}
}
pub type ConfigResponse = Config;
#[cw_serde]
pub struct AssetFeeBreakup {
pub asset_info: AssetInfo,
pub total_fee: Uint128,
pub protocol_fee: Uint128,
}
pub type PoolTypeConfigResponse = Option<PoolTypeConfig>;
pub type PoolInfoResponse = PoolInfo;