1pub mod msgs {
2
3    use cosmwasm_schema::{cw_serde, QueryResponses};
4    use cosmwasm_std::Decimal;
5    use cw_asset::AssetInfo;
6
7    use crate::{
8        common::{AssetType, PriceType, UpdateOption},
9        pool::definitions::{InterestType, LoanDurationType, SwapInfo},
10    };
11
12    use super::definitions::{Config, PoolInfo};
13
14    #[cw_serde]
15    pub struct InstantiateMsg {
16        pub admin: String,
17        pub code_id_pool: u64,
18        pub code_id_cw20: Option<u64>,
19        pub code_id_indexer: u64,
20        pub code_id_oracle: u64,
21        pub pyth_addr: Option<String>,
22        pub collector_addr: String,
23        pub close_position_fee: Decimal,
24        pub protocol_fee: Decimal,
25        pub autoclose_enable: bool,
26        pub oracle_assets_precision_sub: u8
27    }
28
29    #[cw_serde]
30    pub enum ExecuteMsg {
31        CreatePool(CreatePoolMsg),
32        UpdateConfig(UpdateConfigMsg),
33        UpdatePoolConfig(UpdatePoolConfigMsg),
34    }
35
36    #[cw_serde]
37    #[derive(QueryResponses)]
38    pub enum QueryMsg {
39        #[returns(Config)]
40        Config {},
41        #[returns(PoolInfo)]
42        Pool { id: u64 },
43        #[returns(Vec<PoolInfo>)]
44        Pools {
45            start_after: Option<u64>,
46            limit: Option<u32>,
47        },
48        #[returns(PoolInfo)]
49        PoolFromLp { lp: String },
50    }
51
52    #[cw_serde]
53    pub struct MigrateMsg {}
54
55    #[cw_serde]
56    pub struct CreatePoolMsg {
57        pub collateral: AssetInfo,
58        pub core: AssetInfo,
59        pub price_type: PriceType,
60        pub interest_type: InterestType,
61        pub loan_duration_type: LoanDurationType,
62        pub initial_ltv: Decimal,
63        pub lp_type: AssetType,
64        pub allow_early_close_uncollateralized: bool,
65        pub swap_info: SwapInfo,
66    }
67
68    #[cw_serde]
69    #[derive(Default)]
70    pub struct UpdateConfigMsg {
71        pub admin: Option<String>,
72        pub code_id_pool: Option<u64>,
73        pub code_id_cw20: Option<UpdateOption<u64>>,
74        pub oracle_addr: Option<String>,
75        pub collector_addr: Option<String>,
76        pub indexer_addr: Option<String>,
77        pub close_position_fee: Option<Decimal>,
78        pub protocol_fee: Option<Decimal>,
79        pub autoclose_enable: Option<bool>,
80    }
81
82    #[cw_serde]
83    #[derive(Default)]
84    pub struct UpdatePoolConfigMsg {
85        pub pool_id: u64,
86        pub price_type: Option<PriceType>,
87        pub interest_type: Option<InterestType>,
88        pub loan_duration_type: Option<LoanDurationType>,
89        pub initial_ltv: Option<Decimal>,
90        pub allow_early_close_uncollateralized: Option<bool>,
91        pub swap_info: Option<SwapInfo>,
92        pub factory: Option<String>,
93    }
94}
95
96pub mod definitions {
97    use cosmwasm_schema::cw_serde;
98    use cosmwasm_std::{Addr, Decimal, StdError, StdResult};
99
100    use crate::{pool::definitions::PoolConfig, traits::AssertOwner};
101
102    #[cw_serde]
103    pub struct Config {
104        pub admin: Addr,
105        pub code_id_pool: u64,
106        pub code_id_cw20: Option<u64>,
107        pub counter_pool: u64,
108        pub oracle_addr: Addr,
109        pub collector_addr: Addr,
110        pub indexer_addr: Addr,
111        pub close_position_fee: Decimal,
112        pub protocol_fee: Decimal,
113        pub autoclose_enable: bool,
114    }
115
116    #[allow(clippy::too_many_arguments)]
117    impl Config {
118        pub fn new(
119            admin: Addr,
120            code_id_pool: u64,
121            collector_addr: Addr,
122            code_id_cw20: Option<u64>,
123            close_position_fee: Decimal,
124            protocol_fee: Decimal,
125            autoclose_enable: bool,
126        ) -> Config {
127            Config {
128                admin,
129                code_id_pool,
130                counter_pool: 0,
131                oracle_addr: Addr::unchecked(""),
132                collector_addr,
133                code_id_cw20,
134                indexer_addr: Addr::unchecked(""),
135                close_position_fee,
136                protocol_fee,
137                autoclose_enable,
138            }
139        }
140
141        pub fn validate(&self) -> StdResult<()> {
142            if self.close_position_fee > Decimal::one() {
143                return Err(StdError::generic_err(
144                    "close_position_fee must be lesser then or equal 1",
145                ));
146            }
147
148            if self.protocol_fee > Decimal::one() {
149                return Err(StdError::generic_err(
150                    "protocol_fee must be lesser then or equal 1",
151                ));
152            }
153
154            Ok(())
155        }
156    }
157
158    impl AssertOwner for Config {
159        fn get_admin(&self) -> Addr {
160            self.admin.clone()
161        }
162    }
163
164    #[cw_serde]
165    pub struct PoolInfo {
166        pub config: PoolConfig,
167        pub address: Addr,
168        pub id: u64,
169    }
170}
171
172#[cfg(test)]
173
174mod test {
175    use rhaki_cw_plus::math::IntoDecimal;
176
177    use crate::{
178        common::{AssetType, PriceType},
179        factory::msgs::{CreatePoolMsg, ExecuteMsg},
180        pool::definitions::{LoanDurationType, SwapInfo},
181    };
182
183    #[test]
184    pub fn test() {
185        let a = ExecuteMsg::CreatePool(CreatePoolMsg {
186            collateral: cw_asset::AssetInfoBase::Native("usdc".to_string()),
187            core: cw_asset::AssetInfoBase::Native("btc".to_string()),
188            price_type: PriceType::Oracle,
189            interest_type: crate::pool::definitions::InterestType::Quadratic {
190                a: "100".into_decimal(),
191                c: "5".into_decimal(),
192            },
193            loan_duration_type: LoanDurationType::Fixed(30 * 86_400),
194            initial_ltv: "0.7".into_decimal(),
195            lp_type: AssetType::Token,
196            allow_early_close_uncollateralized: false,
197            swap_info: SwapInfo::OnlyFromcore {
198                fee: "0.05".into_decimal(),
199            },
200        });
201
202        let b = serde_json::to_string_pretty(&a).unwrap();
203
204        println!("{b}")
205    }
206}