levana_perpswap_cosmos/contracts/
vault.rs1use super::cw20::Cw20ReceiveMsg;
3use anyhow::{ensure, Result};
4use cosmwasm_std::{Addr, Api, Uint128};
5use serde::{Deserialize, Deserializer};
6use std::{collections::HashMap, fmt};
7
8#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
10#[serde(rename_all = "snake_case")]
11pub struct InstantiateMsg {
12 pub usdc_denom: UsdcAssetInit,
14
15 pub governance: String,
17
18 pub markets_allocation_bps: HashMap<String, u16>,
20}
21
22#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
24#[serde(rename_all = "snake_case")]
25pub enum UsdcAsset {
26 CW20(Addr),
28 Native(String),
30}
31#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
33#[serde(rename_all = "snake_case")]
34pub enum UsdcAssetInit {
35 CW20 {
37 address: String,
39 },
40 Native {
42 denom: String,
44 },
45}
46
47impl fmt::Display for UsdcAsset {
48 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
49 match self {
50 UsdcAsset::CW20(addr) => write!(f, "{}", addr),
51 UsdcAsset::Native(denom) => write!(f, "{}", denom),
52 }
53 }
54}
55
56impl UsdcAsset {
57 pub fn from_init(api: &dyn Api, init: UsdcAssetInit) -> Result<Self> {
59 match init {
60 UsdcAssetInit::CW20 { address } => {
61 let addr = api.addr_validate(&address)?;
62 Ok(UsdcAsset::CW20(addr))
63 }
64 UsdcAssetInit::Native { denom } => {
65 ensure!(!denom.is_empty(), "Native denom cannot be empty");
66 Ok(UsdcAsset::Native(denom))
67 }
68 }
69 }
70}
71
72#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
74#[serde(rename_all = "snake_case")]
75pub struct Config {
76 pub usdc_denom: UsdcAsset,
78
79 pub governance: Addr,
81
82 #[serde(deserialize_with = "deserialize_markets_allocation_bps")]
84 pub markets_allocation_bps: HashMap<Addr, u16>,
85
86 pub paused: bool,
88}
89
90#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
92#[serde(rename_all = "snake_case")]
93pub enum ExecuteMsg {
94 Deposit {},
96
97 Receive(Cw20ReceiveMsg),
99
100 RequestWithdrawal {
102 amount: Uint128,
104 },
105
106 RedistributeFunds {},
108
109 CollectYield {},
111
112 ProcessWithdrawal {},
114
115 WithdrawFromMarket {
117 market: String,
119 amount: Uint128,
121 },
122
123 EmergencyPause {},
125
126 ResumeOperations {},
128
129 UpdateAllocations {
131 #[serde(deserialize_with = "deserialize_markets_allocation_bps")]
133 new_allocations: HashMap<Addr, u16>,
134 },
135
136 AddMarket {
138 market: String,
140 },
141}
142
143#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
145#[serde(rename_all = "snake_case")]
146pub enum QueryMsg {
147 GetVaultBalance {},
149
150 GetPendingWithdrawal {
152 user: String,
154 },
155
156 GetTotalAssets {},
158
159 GetMarketAllocations {
161 start_after: Option<String>,
163 },
164
165 GetConfig {},
167}
168
169fn deserialize_markets_allocation_bps<'de, D>(
170 deserializer: D,
171) -> Result<HashMap<Addr, u16>, D::Error>
172where
173 D: Deserializer<'de>,
174{
175 let string_map = HashMap::<String, u16>::deserialize(deserializer)?;
176 let addr_map = string_map
177 .into_iter()
178 .map(|(k, v)| (Addr::unchecked(k), v))
179 .collect();
180 Ok(addr_map)
181}