lotus_dex_std/pool_manager.rs
1use std::fmt;
2
3use cosmwasm_schema::{cw_serde, QueryResponses};
4use cosmwasm_std::{Addr, Coin, Decimal, Deps, StdError, StdResult, Uint128};
5use cw_ownable::{cw_ownable_execute, cw_ownable_query};
6
7use crate::coin::is_factory_token;
8use crate::fee::PoolFee;
9
10/// The type of swap operation to perform.
11#[cw_serde]
12pub enum SwapOperation {
13 /// A swap operation that uses the LotusSwap router.
14 LotusSwap {
15 /// The token denom to swap in.
16 token_in_denom: String,
17 /// The token denom returning from the swap.
18 token_out_denom: String,
19 /// The identifier of the pool to use for the swap.
20 pool_identifier: String,
21 },
22}
23
24impl SwapOperation {
25 /// Retrieves the `token_in_denom` used for this swap operation.
26 pub fn get_input_asset_info(&self) -> &String {
27 match self {
28 SwapOperation::LotusSwap { token_in_denom, .. } => token_in_denom,
29 }
30 }
31
32 pub fn get_target_asset_info(&self) -> String {
33 match self {
34 SwapOperation::LotusSwap {
35 token_out_denom, ..
36 } => token_out_denom.clone(),
37 }
38 }
39
40 pub fn get_pool_identifer(&self) -> String {
41 match self {
42 SwapOperation::LotusSwap {
43 pool_identifier, ..
44 } => pool_identifier.clone(),
45 }
46 }
47}
48
49impl fmt::Display for SwapOperation {
50 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
51 match self {
52 SwapOperation::LotusSwap {
53 token_in_denom,
54 token_out_denom,
55 pool_identifier,
56 } => write!(
57 f,
58 "LotusSwap {{ token_in_info: {token_in_denom}, token_out_info: {token_out_denom}, pool_identifier: {pool_identifier} }}"
59 ),
60 }
61 }
62}
63
64/// Contains the pool information
65#[cw_serde]
66pub struct PoolInfo {
67 /// The identifier for the pool.
68 pub pool_identifier: String,
69 /// The asset denoms for the pool.
70 pub asset_denoms: Vec<String>,
71 /// The LP denom of the pool.
72 pub lp_denom: String,
73 /// The decimals for the given asset denoms, provided in the same order as asset_denoms.
74 pub asset_decimals: Vec<u8>,
75 /// The total amount of assets in the pool.
76 pub assets: Vec<Coin>,
77 /// The fees for the pool.
78 pub pool_fees: PoolFee,
79 /// The status of the pool
80 pub status: PoolStatus,
81}
82
83/// The pool status tells what actions are enabled for this pool.
84#[cw_serde]
85pub struct PoolStatus {
86 /// Whether swaps are enabled
87 pub swaps_enabled: bool,
88 /// Whether deposits are enabled
89 pub deposits_enabled: bool,
90 /// Whether withdrawals are enabled
91 pub withdrawals_enabled: bool,
92}
93
94impl Default for PoolStatus {
95 fn default() -> Self {
96 PoolStatus {
97 swaps_enabled: true,
98 deposits_enabled: true,
99 withdrawals_enabled: true,
100 }
101 }
102}
103
104/// The contract configuration.
105#[cw_serde]
106pub struct Config {
107 /// The address where the collected fees go to.
108 pub fee_collector_addr: Addr,
109 /// How much it costs to create a pool. It helps prevent spamming of new pools.
110 pub pool_creation_fee: Coin,
111}
112
113#[cw_serde]
114pub struct InstantiateMsg {
115 /// The address where the collected fees go to.
116 pub fee_collector_addr: String,
117 /// How much it costs to create a pool. It helps prevent spamming of new pools.
118 pub pool_creation_fee: Coin,
119}
120
121#[cw_serde]
122pub struct MigrateMsg {}
123
124#[cw_ownable_execute]
125#[cw_serde]
126pub enum ExecuteMsg {
127 /// Creates a new pool.
128 CreatePool {
129 /// The asset denoms for the pool.
130 asset_denoms: Vec<String>,
131 /// The decimals for the given asset denoms, provided in the same order as `asset_denoms`.
132 asset_decimals: Vec<u8>,
133 /// The fees for the pool.
134 pool_fees: PoolFee,
135 /// The identifier for the pool.
136 pool_identifier: Option<String>,
137 },
138 /// Provides liquidity to the pool
139 ProvideLiquidity {
140 /// A percentage value representing the acceptable slippage for the operation.
141 /// When provided, if the slippage exceeds this value, the liquidity provision will not be
142 /// executed.
143 slippage_tolerance: Option<Decimal>,
144 /// The receiver of the LP
145 receiver: Option<String>,
146 /// The identifier for the pool to provide liquidity for.
147 pool_identifier: String,
148 },
149 /// Swap an offer asset to the other
150 Swap {
151 /// The return asset of the swap.
152 ask_asset_denom: String,
153 /// The minimum amount of the output (i.e., final swap operation token) required for the message to succeed.
154 minimum_receive: Option<Uint128>,
155 /// The recipient of the output tokens. If not provided, the tokens will be sent to the sender
156 /// of the message.
157 receiver: Option<String>,
158 /// The identifier for the pool to swap in.
159 pool_identifier: String,
160 },
161 /// Withdraws liquidity from the pool.
162 WithdrawLiquidity { pool_identifier: String },
163 /// Execute multiple [`SwapOperation`]s to allow for multi-hop swaps.
164 ExecuteSwapOperations {
165 /// The operations that should be performed in sequence.
166 ///
167 /// The amount in each swap will be the output from the previous swap.
168 ///
169 /// The first swap will use whatever funds are sent in the MessageInfo.
170 operations: Vec<SwapOperation>,
171 /// The minimum amount of the output (i.e., final swap operation token) required for the message to succeed.
172 minimum_receive: Option<Uint128>,
173 /// The (optional) recipient of the output tokens.
174 ///
175 /// If left unspecified, tokens will be sent to the sender of the message.
176 receiver: Option<String>,
177 },
178 /// Updates the configuration of the contract.
179 /// If a field is not specified (i.e., set to `None`), it will not be modified.
180 UpdateConfig {
181 /// The new fee collector contract address.
182 fee_collector_addr: Option<String>,
183 /// The new fee that must be paid when a pool is created.
184 pool_creation_fee: Option<Coin>,
185 /// Toggles features for a given pool, allowing fine-tuned
186 /// control over which operations are allowed, i.e. swap, deposits, withdrawals
187 feature_toggle: Option<FeatureToggle>,
188 },
189}
190
191#[cw_ownable_query]
192#[cw_serde]
193#[derive(QueryResponses)]
194pub enum QueryMsg {
195 /// Retrieves the contract's config.
196 #[returns(ConfigResponse)]
197 Config {},
198 /// Retrieves the decimals for the given asset.
199 #[returns(AssetDecimalsResponse)]
200 AssetDecimals {
201 /// The pool identifier to do the query for.
202 pool_identifier: String,
203 /// The queried denom in the given pool_identifier.
204 denom: String,
205 },
206 /// Simulates a swap.
207 #[returns(SimulationResponse)]
208 Simulation {
209 /// The offer asset to swap.
210 offer_asset: Coin,
211 /// The ask asset denom to get.
212 ask_asset_denom: String,
213 /// The pool identifier to swap in.
214 pool_identifier: String,
215 },
216 /// Simulates a reverse swap, i.e. given the ask asset, how much of the offer asset is needed
217 /// to perform the swap.
218 #[returns(ReverseSimulationResponse)]
219 ReverseSimulation {
220 /// The ask asset to get after the swap.
221 ask_asset: Coin,
222 /// The offer asset denom to input.
223 offer_asset_denom: String,
224 /// The pool identifier to swap in.
225 pool_identifier: String,
226 },
227 /// Simulates swap operations.
228 #[returns(SimulateSwapOperationsResponse)]
229 SimulateSwapOperations {
230 /// The amount to swap.
231 offer_amount: Uint128,
232 /// The operations to perform.
233 operations: Vec<SwapOperation>,
234 },
235 /// Simulates a reverse swap operations, i.e. given the ask asset, how much of the offer asset
236 /// is needed to perform the swap.
237 #[returns(ReverseSimulateSwapOperationsResponse)]
238 ReverseSimulateSwapOperations {
239 /// The amount to get after the swap.
240 ask_amount: Uint128,
241 /// The operations to perform.
242 operations: Vec<SwapOperation>,
243 },
244 /// Retrieves the pool information for the given pool identifier.
245 #[returns(PoolsResponse)]
246 Pools {
247 /// An optional parameter specifying the pool identifier to do the query for. If not
248 /// provided, it will return all pools based on the pagination parameters.
249 pool_identifier: Option<String>,
250 /// An optional parameter specifying what pool (identifier) to start searching after.
251 start_after: Option<String>,
252 /// The amount of pools to return. If unspecified, will default to a value specified by
253 /// the contract.
254 limit: Option<u32>,
255 },
256}
257
258/// The response for the `Config` query.
259#[cw_serde]
260pub struct ConfigResponse {
261 /// The contract configuration.
262 pub config: Config,
263}
264
265/// The response for the `Pools` query.
266#[cw_serde]
267pub struct PoolsResponse {
268 /// The pools information responses.
269 pub pools: Vec<PoolInfoResponse>,
270}
271
272#[cw_serde]
273pub struct PoolInfoResponse {
274 /// The pool information for the given pool identifier.
275 pub pool_info: PoolInfo,
276 /// The total LP tokens in the pool.
277 pub total_share: Coin,
278}
279
280/// The response for the `AssetDecimals` query.
281#[cw_serde]
282pub struct AssetDecimalsResponse {
283 /// The pool identifier to do the query for.
284 pub pool_identifier: String,
285 /// The queried denom in the given pool_identifier.
286 pub denom: String,
287 /// The decimals for the requested denom.
288 pub decimals: u8,
289}
290
291/// SimulationResponse returns swap simulation response
292#[cw_serde]
293pub struct SimulationResponse {
294 /// The return amount of the ask asset given the offer amount.
295 pub return_amount: Uint128,
296 /// The swap fee amount of the swap.
297 pub swap_fee_amount: Uint128,
298 /// The protocol fee amount of the swap.
299 pub protocol_fee_amount: Uint128,
300 /// The burn fee amount of the swap.
301 pub burn_fee_amount: Uint128,
302}
303
304/// ReverseSimulationResponse returns reverse swap simulation response
305#[cw_serde]
306pub struct ReverseSimulationResponse {
307 /// The amount of the offer asset needed to get the ask amount.
308 pub offer_amount: Uint128,
309 /// The swap fee amount of the swap.
310 pub swap_fee_amount: Uint128,
311 /// The protocol fee amount of the swap.
312 pub protocol_fee_amount: Uint128,
313 /// The burn fee amount of the swap.
314 pub burn_fee_amount: Uint128,
315}
316
317/// Pool feature toggle, can control whether swaps, deposits, and withdrawals are enabled.
318#[cw_serde]
319pub struct FeatureToggle {
320 /// The identifier of the pool to toggle the status of.
321 pub pool_identifier: String,
322 /// Whether or not swaps are enabled
323 pub withdrawals_enabled: Option<bool>,
324 /// Whether or not deposits are enabled
325 pub deposits_enabled: Option<bool>,
326 /// Whether or not swaps are enabled
327 pub swaps_enabled: Option<bool>,
328}
329
330/// The response for the `SimulateSwapOperations` query.
331#[cw_serde]
332pub struct SimulateSwapOperationsResponse {
333 /// The return amount of the ask asset after the swap operations.
334 pub return_amount: Uint128,
335 /// The swap fees of the swap.
336 pub swap_fees: Vec<Coin>,
337 /// The protocol fees of the swap.
338 pub protocol_fees: Vec<Coin>,
339 /// The burn fees of the swap.
340 pub burn_fees: Vec<Coin>,
341 /// The extra fees of the swap.
342 pub extra_fees: Vec<Coin>,
343}
344
345/// The response for the `ReverseSimulateSwapOperations` query.
346#[cw_serde]
347pub struct ReverseSimulateSwapOperationsResponse {
348 /// The amount of the initial token needed to get the final token after the swap operations.
349 pub offer_amount: Uint128,
350 /// The swap fees of the swap.
351 pub swap_fees: Vec<Coin>,
352 /// The protocol fees of the swap.
353 pub protocol_fees: Vec<Coin>,
354 /// The burn fees of the swap.
355 pub burn_fees: Vec<Coin>,
356}
357
358/// Gets the total supply of the given liquidity asset
359pub fn get_total_share(deps: &Deps, liquidity_asset: String) -> StdResult<Uint128> {
360 if is_factory_token(liquidity_asset.as_str()) {
361 //bank query total
362 return Ok(deps.querier.query_supply(&liquidity_asset)?.amount);
363 }
364
365 Err(StdError::generic_err("Invalid LP token"))
366}