Skip to main content

bolt_cw_sdk/
events.rs

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
78/// Useful filter function for contracts
79pub 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        // Default to false if the event doesnt exist
88        .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}