use zera_proto::zera_api::{TokenFeeInfo, TokenFeeInfoResponse};
use crate::error::{Result, ZeraError};
use crate::grpc::{UnaryTransport, ValidatorApiClient};
use crate::types::RpcConfig;
use crate::utils::token::normalize_contract_id;
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct GetTokenFeeInfoParams {
pub contract_ids: Vec<String>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct TokenInfo {
pub contract_id: String,
pub denomination: String,
pub rate: String,
pub authorized: bool,
pub allowed_fees: String,
pub used_fees: String,
pub contract_fees: Option<zera_proto::zera_txn::ContractFees>,
}
pub async fn get_token_fee_info(
params: GetTokenFeeInfoParams,
config: RpcConfig,
) -> Result<TokenFeeInfoResponse> {
let client = ValidatorApiClient::new(config)?;
get_token_fee_info_with_client(params, &client).await
}
pub async fn get_token_fee_info_with_client<T>(
params: GetTokenFeeInfoParams,
client: &ValidatorApiClient<T>,
) -> Result<TokenFeeInfoResponse>
where
T: UnaryTransport,
{
let mut response = client
.get_token_fee_info(¶ms.contract_ids)
.await
.map_err(|error| {
ZeraError::Rpc(format!(
"Failed to get token fee info from validator: {error}"
))
})?;
for token in &mut response.tokens {
normalize_token(token);
}
Ok(response)
}
pub async fn get_token_info_for_single(contract_id: &str, config: RpcConfig) -> Result<TokenInfo> {
let client = ValidatorApiClient::new(config)?;
get_token_info_for_single_with_client(contract_id, &client).await
}
pub async fn get_token_info_for_single_with_client<T>(
contract_id: &str,
client: &ValidatorApiClient<T>,
) -> Result<TokenInfo>
where
T: UnaryTransport,
{
if contract_id.trim().is_empty() {
return Err(ZeraError::InvalidInput(
"Contract ID is required".to_string(),
));
}
let normalized_contract_id = normalize_contract_id(contract_id);
let response = get_token_fee_info_with_client(
GetTokenFeeInfoParams {
contract_ids: vec![normalized_contract_id.clone()],
},
client,
)
.await?;
let token = response
.tokens
.into_iter()
.find(|token| {
token.contract_id == normalized_contract_id
|| normalize_contract_id(&token.contract_id) == normalized_contract_id
})
.ok_or_else(|| {
ZeraError::Rpc(format!(
"Token information not found for contract ID: {normalized_contract_id}"
))
})?;
Ok(TokenInfo {
contract_id: token.contract_id,
denomination: token.denomination,
rate: token.rate,
authorized: token.authorized,
allowed_fees: token.allowed_fees,
used_fees: token.used_fees,
contract_fees: token.contract_fees,
})
}
fn normalize_token(token: &mut TokenFeeInfo) {
if token.rate.is_empty() {
token.rate = "0".to_string();
}
if token.denomination.is_empty() {
token.denomination = "1".to_string();
}
if token.allowed_fees.is_empty() {
token.allowed_fees = "0".to_string();
}
if token.used_fees.is_empty() {
token.used_fees = "0".to_string();
}
if let Some(contract_fees) = token.contract_fees.as_mut() {
if contract_fees.fee.is_empty() {
contract_fees.fee = "0".to_string();
}
if contract_fees.burn.is_empty() {
contract_fees.burn = "0".to_string();
}
if contract_fees.validator.is_empty() {
contract_fees.validator = "0".to_string();
}
}
}