1use std::collections::BTreeMap;
2use std::str::FromStr;
3
4use cosmrs::tendermint::abci::Event;
5use thiserror::Error;
6use tonic::Status;
7
8pub const BOLT_UPDATE_PRICE_EVENT_NAME: &str = "wasm-bolt_update_price";
9pub const BOLT_UPDATE_PRICE_TRADING_PAIR: &str = "trading_pair";
10pub const BOLT_UPDATE_PRICE_NEW_PRICE: &str = "new_price";
11pub const BOLT_UPDATE_PRICE_EXPIRY_TIME: &str = "expiry_time";
12
13pub const BOLT_SWAP_EVENT_NAME: &str = "wasm-bolt_swap";
14pub const BOLT_SWAP_EVENT_AMOUNT_IN: &str = "amount_in";
15pub const BOLT_SWAP_EVENT_DENOM_IN: &str = "denom_in";
16pub const BOLT_SWAP_EVENT_AMOUNT_OUT: &str = "amount_out";
17pub const BOLT_SWAP_EVENT_DENOM_OUT: &str = "denom_out";
18pub const BOLT_SWAP_EVENT_PROTOCOL_FEE_AMOUNT: &str = "protocol_fee_amount";
19pub const BOLT_SWAP_EVENT_LP_FEE_AMOUNT: &str = "lp_fee_amount";
20pub const BOLT_SWAP_EVENT_PRICE: &str = "price";
21pub const BOLT_SWAP_EVENT_CONTRACT_ADDRESS: &str = "_contract_address";
22pub const BOLT_SWAP_EVENT_SENDER: &str = "sender";
23
24pub const BOLT_WITHDRAW_BASE_EVENT_NAME: &str = "wasm-bolt_withdraw_base";
25pub const BOLT_WITHDRAW_BASE_EVENT_WITHDRAWN_AMOUNT: &str = "withdrawn_amount";
26pub const WASM_EVENT_CONTRACT_ADDRESS: &str = "_contract_address";
27
28pub const BOLT_WITHDRAW_QUOTES_EVENT_NAME: &str = "wasm-bolt_withdraw_quotes";
29pub const BOLT_WITHDRAW_QUOTES_EVENT_CONTRACT_ADDRESS: &str = "_contract_address";
30pub const BOLT_WITHDRAW_QUOTES_EVENT_WITHDRAWN_QUOTES: &str = "withdrawn_quotes";
31
32#[derive(Error, Debug)]
33pub enum EventError {
34 #[error("Failed to find bolt event attribute")]
35 FailedToFindBoltEventAttribute,
36 #[error("Failed to parse bold event value")]
37 FailedToParseBoltEventValue,
38}
39
40pub fn event_key(event: &str, key: &str) -> String {
41 format!("{event}.{key}")
42}
43
44#[allow(clippy::result_large_err)]
45pub fn get_events<'a>(
46 event: &str,
47 key: &str,
48 events: &'a BTreeMap<String, Vec<String>>,
49) -> Result<&'a Vec<String>, Status> {
50 let event_key = event_key(event, key);
51
52 events
53 .get(&event_key)
54 .ok_or(Status::not_found(format!("Could not find {event_key}")))
55}
56
57#[allow(clippy::result_large_err)]
58pub fn get_event<'a>(
59 event: &str,
60 key: &str,
61 events: &'a BTreeMap<String, Vec<String>>,
62) -> Result<&'a str, Status> {
63 get_events(event, key, events).and_then(|events| {
64 if events.len() > 1 {
65 return Err(Status::internal(format!(
66 "Expected one event, got {}",
67 events.len()
68 )));
69 }
70
71 events
72 .first()
73 .map(|a| a.as_str())
74 .ok_or(Status::not_found("Event was empty"))
75 })
76}
77
78pub fn expected_contract(
80 event: &str,
81 contracts: &[String],
82 events: &BTreeMap<String, Vec<String>>,
83) -> bool {
84 get_event(event, "_contract_address", events)
85 .ok()
86 .map(|contract| contracts.iter().any(|expected| expected == contract))
87 .unwrap_or(false)
89}
90
91pub fn get_attr_value_as_str<'a>(event: &'a Event, key: &str) -> Result<&'a str, EventError> {
92 let attribute = event
93 .attributes
94 .iter()
95 .find(|attr| attr.key_str().map(|k| k == key).unwrap_or(false))
96 .ok_or(EventError::FailedToFindBoltEventAttribute)?;
97 attribute
98 .value_str()
99 .map_err(|_| EventError::FailedToParseBoltEventValue)
100}
101
102pub fn get_attr_value_as_u128(event: &Event, key: &str) -> Result<u128, EventError> {
103 let value = get_attr_value_as_str(event, key)?;
104 value
105 .parse::<u128>()
106 .map_err(|_| EventError::FailedToParseBoltEventValue)
107}
108
109pub fn get_attr_value_as_coin(event: &Event, key: &str) -> Result<cosmwasm_std::Coin, EventError> {
110 let value = get_attr_value_as_str(event, key)?;
111 cosmwasm_std::Coin::from_str(value).map_err(|_| EventError::FailedToParseBoltEventValue)
112}
113
114pub fn get_attr_value_as_coins(
115 event: &Event,
116 key: &str,
117) -> Result<Vec<cosmwasm_std::Coin>, EventError> {
118 let value = get_attr_value_as_str(event, key)?;
119 value
120 .split(',')
121 .map(|coin_value| {
122 cosmwasm_std::Coin::from_str(coin_value)
123 .map_err(|_| EventError::FailedToParseBoltEventValue)
124 })
125 .collect::<Result<Vec<_>, _>>()
126}