use std::collections::BTreeMap;
use std::str::FromStr;
use cosmrs::tendermint::abci::Event;
use thiserror::Error;
use tonic::Status;
pub const BOLT_UPDATE_PRICE_EVENT_NAME: &str = "wasm-bolt_update_price";
pub const BOLT_UPDATE_PRICE_TRADING_PAIR: &str = "trading_pair";
pub const BOLT_UPDATE_PRICE_NEW_PRICE: &str = "new_price";
pub const BOLT_UPDATE_PRICE_EXPIRY_TIME: &str = "expiry_time";
pub const BOLT_SWAP_EVENT_NAME: &str = "wasm-bolt_swap";
pub const BOLT_SWAP_EVENT_AMOUNT_IN: &str = "amount_in";
pub const BOLT_SWAP_EVENT_DENOM_IN: &str = "denom_in";
pub const BOLT_SWAP_EVENT_AMOUNT_OUT: &str = "amount_out";
pub const BOLT_SWAP_EVENT_DENOM_OUT: &str = "denom_out";
pub const BOLT_SWAP_EVENT_PROTOCOL_FEE_AMOUNT: &str = "protocol_fee_amount";
pub const BOLT_SWAP_EVENT_LP_FEE_AMOUNT: &str = "lp_fee_amount";
pub const BOLT_SWAP_EVENT_PRICE: &str = "price";
pub const BOLT_SWAP_EVENT_CONTRACT_ADDRESS: &str = "_contract_address";
pub const BOLT_SWAP_EVENT_SENDER: &str = "sender";
pub const BOLT_WITHDRAW_BASE_EVENT_NAME: &str = "wasm-bolt_withdraw_base";
pub const BOLT_WITHDRAW_BASE_EVENT_WITHDRAWN_AMOUNT: &str = "withdrawn_amount";
pub const WASM_EVENT_CONTRACT_ADDRESS: &str = "_contract_address";
pub const BOLT_WITHDRAW_QUOTES_EVENT_NAME: &str = "wasm-bolt_withdraw_quotes";
pub const BOLT_WITHDRAW_QUOTES_EVENT_CONTRACT_ADDRESS: &str = "_contract_address";
pub const BOLT_WITHDRAW_QUOTES_EVENT_WITHDRAWN_QUOTES: &str = "withdrawn_quotes";
#[derive(Error, Debug)]
pub enum EventError {
#[error("Failed to find bolt event attribute")]
FailedToFindBoltEventAttribute,
#[error("Failed to parse bold event value")]
FailedToParseBoltEventValue,
}
pub fn event_key(event: &str, key: &str) -> String {
format!("{event}.{key}")
}
#[allow(clippy::result_large_err)]
pub fn get_events<'a>(
event: &str,
key: &str,
events: &'a BTreeMap<String, Vec<String>>,
) -> Result<&'a Vec<String>, Status> {
let event_key = event_key(event, key);
events
.get(&event_key)
.ok_or(Status::not_found(format!("Could not find {event_key}")))
}
#[allow(clippy::result_large_err)]
pub fn get_event<'a>(
event: &str,
key: &str,
events: &'a BTreeMap<String, Vec<String>>,
) -> Result<&'a str, Status> {
get_events(event, key, events).and_then(|events| {
if events.len() > 1 {
return Err(Status::internal(format!(
"Expected one event, got {}",
events.len()
)));
}
events
.first()
.map(|a| a.as_str())
.ok_or(Status::not_found("Event was empty"))
})
}
pub fn expected_contract(
event: &str,
contracts: &[String],
events: &BTreeMap<String, Vec<String>>,
) -> bool {
get_event(event, "_contract_address", events)
.ok()
.map(|contract| contracts.iter().any(|expected| expected == contract))
.unwrap_or(false)
}
pub fn get_attr_value_as_str<'a>(event: &'a Event, key: &str) -> Result<&'a str, EventError> {
let attribute = event
.attributes
.iter()
.find(|attr| attr.key_str().map(|k| k == key).unwrap_or(false))
.ok_or(EventError::FailedToFindBoltEventAttribute)?;
attribute
.value_str()
.map_err(|_| EventError::FailedToParseBoltEventValue)
}
pub fn get_attr_value_as_u128(event: &Event, key: &str) -> Result<u128, EventError> {
let value = get_attr_value_as_str(event, key)?;
value
.parse::<u128>()
.map_err(|_| EventError::FailedToParseBoltEventValue)
}
pub fn get_attr_value_as_coin(event: &Event, key: &str) -> Result<cosmwasm_std::Coin, EventError> {
let value = get_attr_value_as_str(event, key)?;
cosmwasm_std::Coin::from_str(value).map_err(|_| EventError::FailedToParseBoltEventValue)
}
pub fn get_attr_value_as_coins(
event: &Event,
key: &str,
) -> Result<Vec<cosmwasm_std::Coin>, EventError> {
let value = get_attr_value_as_str(event, key)?;
value
.split(',')
.map(|coin_value| {
cosmwasm_std::Coin::from_str(coin_value)
.map_err(|_| EventError::FailedToParseBoltEventValue)
})
.collect::<Result<Vec<_>, _>>()
}