levana_perpswap_cosmos/contracts/market/
history.rs1use crate::prelude::*;
3
4pub mod events {
6 use super::*;
7 use crate::constants::event_key;
8 use crate::contracts::market::entry::{
9 LpAction, LpActionKind, PositionAction, PositionActionKind,
10 };
11 use crate::contracts::market::position::PositionId;
12
13 pub struct TradeVolumeEvent {
15 pub volume_usd: Usd,
17 }
18
19 impl From<TradeVolumeEvent> for Event {
20 fn from(src: TradeVolumeEvent) -> Self {
21 Event::new("history-trade-volume")
22 .add_attribute("volume-usd", src.volume_usd.to_string())
23 }
24 }
25 impl TryFrom<Event> for TradeVolumeEvent {
26 type Error = anyhow::Error;
27
28 fn try_from(evt: Event) -> anyhow::Result<Self> {
29 Ok(TradeVolumeEvent {
30 volume_usd: evt.decimal_attr("volume-usd")?,
31 })
32 }
33 }
34
35 pub struct PnlEvent {
37 pub pnl: Signed<Collateral>,
39 pub pnl_usd: Signed<Usd>,
41 }
42
43 impl From<PnlEvent> for Event {
44 fn from(src: PnlEvent) -> Self {
45 Event::new("history-pnl")
46 .add_attribute("pnl", src.pnl.to_string())
47 .add_attribute("pnl-usd", src.pnl_usd.to_string())
48 }
49 }
50 impl TryFrom<Event> for PnlEvent {
51 type Error = anyhow::Error;
52
53 fn try_from(evt: Event) -> anyhow::Result<Self> {
54 Ok(PnlEvent {
55 pnl: evt.number_attr("pnl")?,
56 pnl_usd: evt.number_attr("pnl-usd")?,
57 })
58 }
59 }
60
61 pub struct PositionActionEvent {
63 pub pos_id: PositionId,
65 pub action: PositionAction,
67 }
68
69 impl From<PositionActionEvent> for Event {
70 fn from(src: PositionActionEvent) -> Self {
71 let evt = Event::new("history-position-action")
72 .add_attribute(event_key::POS_ID, src.pos_id.to_string())
73 .add_attribute(
74 event_key::POSITION_ACTION_KIND,
75 match src.action.kind {
76 PositionActionKind::Open => "open",
77 PositionActionKind::Update => "update",
78 PositionActionKind::Close => "close",
79 PositionActionKind::Transfer => "transfer",
80 },
81 )
82 .add_attribute(
83 event_key::POSITION_ACTION_TIMESTAMP,
84 src.action.timestamp.to_string(),
85 )
86 .add_attribute(
87 event_key::POSITION_ACTION_COLLATERAL,
88 src.action.collateral.to_string(),
89 )
90 .add_attribute(
91 event_key::POSITION_ACTION_TRANSFER,
92 src.action.transfer_collateral.to_string(),
93 );
94
95 let evt = match src.action.price_timestamp {
96 Some(price_timestamp) => evt.add_attribute(
97 event_key::POSITION_ACTION_PRICE_TIMESTAMP,
98 price_timestamp.to_string(),
99 ),
100 None => evt,
101 };
102
103 let evt = match src.action.leverage {
104 Some(leverage) => {
105 evt.add_attribute(event_key::POSITION_ACTION_LEVERAGE, leverage.to_string())
106 }
107 None => evt,
108 };
109 let evt = match src.action.max_gains {
110 Some(max_gains) => {
111 evt.add_attribute(event_key::POSITION_ACTION_MAX_GAINS, max_gains.to_string())
112 }
113 None => evt,
114 };
115
116 let evt = match src.action.trade_fee {
117 None => evt,
118 Some(trade_fee) => {
119 evt.add_attribute(event_key::POSITION_ACTION_TRADE_FEE, trade_fee.to_string())
120 }
121 };
122
123 let evt = match src.action.delta_neutrality_fee {
124 None => evt,
125 Some(delta_neutrality_fee) => evt.add_attribute(
126 event_key::POSITION_ACTION_DELTA_NEUTRALITY_FEE,
127 delta_neutrality_fee.to_string(),
128 ),
129 };
130
131 let evt = match src.action.old_owner {
132 None => evt,
133 Some(old_owner) => evt.add_attribute(
134 event_key::POSITION_ACTION_OLD_OWNER,
135 old_owner.into_string(),
136 ),
137 };
138
139 let evt = match src.action.take_profit_trader {
140 None => evt,
141 Some(take_profit_trader) => evt.add_attribute(
142 event_key::TAKE_PROFIT_OVERRIDE,
143 take_profit_trader.to_string(),
144 ),
145 };
146
147 let evt = match src.action.stop_loss_override {
148 None => evt,
149 Some(stop_loss_override) => evt.add_attribute(
150 event_key::STOP_LOSS_OVERRIDE,
151 stop_loss_override.to_string(),
152 ),
153 };
154
155 match src.action.new_owner {
156 None => evt,
157 Some(new_owner) => evt.add_attribute(
158 event_key::POSITION_ACTION_NEW_OWNER,
159 new_owner.into_string(),
160 ),
161 }
162 }
163 }
164
165 impl TryFrom<Event> for PositionActionEvent {
166 type Error = anyhow::Error;
167
168 fn try_from(evt: Event) -> anyhow::Result<Self> {
169 let pos_id = PositionId::new(evt.u64_attr(event_key::POS_ID)?);
170 Ok(PositionActionEvent {
171 pos_id,
172 action: PositionAction {
173 id: Some(pos_id),
174 kind: evt.map_attr_result(event_key::POSITION_ACTION_KIND, |s| match s {
175 "open" => Ok(PositionActionKind::Open),
176 "update" => Ok(PositionActionKind::Update),
177 "close" => Ok(PositionActionKind::Close),
178 "transfer" => Ok(PositionActionKind::Transfer),
179 _ => Err(PerpError::unimplemented().into()),
180 })?,
181 timestamp: evt.timestamp_attr(event_key::POSITION_ACTION_TIMESTAMP)?,
182 price_timestamp: evt
183 .try_timestamp_attr(event_key::POSITION_ACTION_PRICE_TIMESTAMP)?,
184 collateral: evt.decimal_attr(event_key::POSITION_ACTION_COLLATERAL)?,
185 transfer_collateral: evt.signed_attr(event_key::POSITION_ACTION_TRANSFER)?,
186 leverage: evt.try_leverage_to_base_attr(event_key::POSITION_ACTION_LEVERAGE)?,
187 max_gains: evt
188 .try_map_attr(event_key::POSITION_ACTION_MAX_GAINS, |value| {
189 MaxGainsInQuote::try_from(value)
190 })
191 .transpose()?,
192 trade_fee: evt.try_decimal_attr(event_key::POSITION_ACTION_TRADE_FEE)?,
193 delta_neutrality_fee: evt
194 .try_number_attr(event_key::POSITION_ACTION_DELTA_NEUTRALITY_FEE)?,
195 old_owner: evt.try_unchecked_addr_attr(event_key::POSITION_ACTION_OLD_OWNER)?,
196 new_owner: evt.try_unchecked_addr_attr(event_key::POSITION_ACTION_NEW_OWNER)?,
197 take_profit_trader: evt
198 .try_map_attr(event_key::TAKE_PROFIT_OVERRIDE, |s| {
199 TakeProfitTrader::try_from(s)
200 })
201 .transpose()?,
202 stop_loss_override: evt
203 .try_price_base_in_quote(event_key::STOP_LOSS_OVERRIDE)?,
204 },
205 })
206 }
207 }
208
209 pub struct LpActionEvent {
211 pub addr: Addr,
213 pub action: LpAction,
215 pub action_id: u64,
217 }
218
219 impl From<LpActionEvent> for Event {
220 fn from(src: LpActionEvent) -> Self {
221 let event = Event::new("history-lp-action")
222 .add_attribute(event_key::LP_ACTION_ADDRESS, src.addr.to_string())
223 .add_attribute(event_key::LP_ACTION_ID, src.action_id.to_string())
224 .add_attribute(
225 event_key::LP_ACTION_KIND,
226 match src.action.kind {
227 LpActionKind::DepositLp => "deposit-lp",
228 LpActionKind::DepositXlp => "deposit-xlp",
229 LpActionKind::ReinvestYieldLp => "reinvest-yield-lp",
230 LpActionKind::ReinvestYieldXlp => "reinvest-yield-xlp",
231 LpActionKind::UnstakeXlp => "unstake-xlp",
232 LpActionKind::Withdraw => "withdraw",
233 LpActionKind::ClaimYield => "claim-yield",
234 LpActionKind::CollectLp => "collect-lp",
235 },
236 )
237 .add_attribute(
238 event_key::LP_ACTION_TIMESTAMP,
239 src.action.timestamp.to_string(),
240 )
241 .add_attribute(
242 event_key::LP_ACTION_COLLATERAL,
243 src.action.collateral.to_string(),
244 )
245 .add_attribute(
246 event_key::LP_ACTION_COLLATERAL_USD,
247 src.action.collateral_usd.to_string(),
248 );
249 match src.action.tokens {
250 Some(tokens) => {
251 event.add_attribute(event_key::LP_ACTION_TOKENS, tokens.to_string())
252 }
253 None => event,
254 }
255 }
256 }
257
258 impl TryFrom<Event> for LpActionEvent {
259 type Error = anyhow::Error;
260
261 fn try_from(evt: Event) -> anyhow::Result<Self> {
262 Ok(LpActionEvent {
263 addr: evt.unchecked_addr_attr(event_key::LP_ACTION_ADDRESS)?,
264 action_id: evt.u64_attr(event_key::LP_ACTION_ID)?,
265 action: LpAction {
266 kind: evt.map_attr_result(event_key::LP_ACTION_KIND, |s| match s {
267 "deposit-lp" => Ok(LpActionKind::DepositLp),
268 "deposit-xlp" => Ok(LpActionKind::DepositXlp),
269 "reinvest-yield-lp" => Ok(LpActionKind::ReinvestYieldLp),
270 "reinvest-yield-xlp" => Ok(LpActionKind::ReinvestYieldXlp),
271 "unstake-xlp" => Ok(LpActionKind::UnstakeXlp),
272 "withdraw" => Ok(LpActionKind::Withdraw),
273 "claim-yield" => Ok(LpActionKind::ClaimYield),
274 "collect-lp" => Ok(LpActionKind::CollectLp),
275 _ => Err(PerpError::unimplemented().into()),
276 })?,
277 timestamp: evt.timestamp_attr(event_key::LP_ACTION_TIMESTAMP)?,
278 tokens: evt.try_decimal_attr(event_key::LP_ACTION_TOKENS)?,
279 collateral: evt.decimal_attr(event_key::LP_ACTION_COLLATERAL)?,
280 collateral_usd: evt.decimal_attr(event_key::LP_ACTION_COLLATERAL_USD)?,
281 },
282 })
283 }
284 }
285
286 pub struct LpDepositEvent {
288 pub deposit: Collateral,
290 pub deposit_usd: Usd,
292 }
293
294 impl From<LpDepositEvent> for Event {
295 fn from(src: LpDepositEvent) -> Self {
296 Event::new("history-lp-deposit")
297 .add_attribute("deposit", src.deposit.to_string())
298 .add_attribute("deposit-usd", src.deposit_usd.to_string())
299 }
300 }
301 impl TryFrom<Event> for LpDepositEvent {
302 type Error = anyhow::Error;
303
304 fn try_from(evt: Event) -> anyhow::Result<Self> {
305 Ok(LpDepositEvent {
306 deposit: evt.decimal_attr("deposit")?,
307 deposit_usd: evt.decimal_attr("deposit-usd")?,
308 })
309 }
310 }
311
312 pub struct LpYieldEvent {
314 pub addr: Addr,
316 pub r#yield: Collateral,
318 pub yield_usd: Usd,
320 }
321
322 impl From<LpYieldEvent> for Event {
323 fn from(
324 LpYieldEvent {
325 addr,
326 r#yield,
327 yield_usd,
328 }: LpYieldEvent,
329 ) -> Self {
330 Event::new("history-lp-yield")
331 .add_attribute("addr", addr.to_string())
332 .add_attribute("yield", r#yield.to_string())
333 .add_attribute("yield-usd", yield_usd.to_string())
334 }
335 }
336 impl TryFrom<Event> for LpYieldEvent {
337 type Error = anyhow::Error;
338
339 fn try_from(evt: Event) -> anyhow::Result<Self> {
340 Ok(LpYieldEvent {
341 addr: evt.unchecked_addr_attr("addr")?,
342 r#yield: evt.decimal_attr("yield")?,
343 yield_usd: evt.decimal_attr("yield-usd")?,
344 })
345 }
346 }
347}