use std::collections::{HashMap, HashSet};
use crate::api::{get_token_fee_info_with_client, GetTokenFeeInfoParams, TokenInfo};
use crate::error::Result;
use crate::grpc::{UnaryTransport, ValidatorApiClient};
pub(crate) fn normalize_contract_id(id: &str) -> String {
if !id.starts_with('$') {
return id.to_string();
}
if let Some((head, suffix)) = id[1..].rsplit_once('+') {
if head.contains('-') && suffix.len() == 6 && suffix.chars().all(|c| c.is_ascii_digit()) {
if let Some((chain, symbol)) = head.split_once('-') {
return format!(
"${}-{}+{}",
chain.to_lowercase(),
symbol.to_uppercase(),
suffix
);
}
}
if !head.contains('-') && suffix.len() == 4 && suffix.chars().all(|c| c.is_ascii_digit()) {
return format!("${}+{}", head.to_uppercase(), suffix);
}
}
id.to_string()
}
pub(crate) async fn get_token_info_map_with_client<T>(
contract_id: &str,
additional_contract_ids: &[String],
client: &ValidatorApiClient<T>,
) -> Result<HashMap<String, TokenInfo>>
where
T: UnaryTransport,
{
let mut contract_ids = HashSet::new();
contract_ids.insert(normalize_contract_id(contract_id));
for id in additional_contract_ids {
if !id.is_empty() {
contract_ids.insert(normalize_contract_id(id));
}
}
let response = get_token_fee_info_with_client(
GetTokenFeeInfoParams {
contract_ids: contract_ids.iter().cloned().collect(),
},
client,
)
.await?;
let mut map = HashMap::new();
for token in response.tokens {
let normalized = normalize_contract_id(&token.contract_id);
let token_info = TokenInfo {
contract_id: token.contract_id.clone(),
denomination: token.denomination.clone(),
rate: token.rate.clone(),
authorized: token.authorized,
allowed_fees: token.allowed_fees.clone(),
used_fees: token.used_fees.clone(),
contract_fees: token.contract_fees.clone(),
};
map.insert(token.contract_id.clone(), token_info.clone());
map.insert(normalized, token_info);
}
Ok(map)
}