use hedera_proto::services;
use hedera_proto::services::{
TokenFreezeStatus,
TokenKycStatus,
TokenPauseStatus,
};
use prost::Message;
use time::{
Duration,
OffsetDateTime,
};
use crate::protobuf::ToProtobuf;
use crate::token::custom_fees::AnyCustomFee;
use crate::{
AccountId,
FromProtobuf,
Key,
LedgerId,
TokenId,
TokenSupplyType,
TokenType,
};
#[derive(Debug, Clone)]
#[cfg_attr(feature = "ffi", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "ffi", serde(rename_all = "camelCase"))]
pub struct TokenInfo {
pub token_id: TokenId,
pub name: String,
pub symbol: String,
pub decimals: u32,
pub total_supply: u64,
pub treasury_account_id: AccountId,
pub admin_key: Option<Key>,
pub kyc_key: Option<Key>,
pub freeze_key: Option<Key>,
pub wipe_key: Option<Key>,
pub supply_key: Option<Key>,
pub fee_schedule_key: Option<Key>,
pub default_freeze_status: Option<bool>,
pub default_kyc_status: Option<bool>,
pub is_deleted: bool,
pub auto_renew_account: Option<AccountId>,
#[cfg_attr(
feature = "ffi",
serde(with = "serde_with::As::<Option<serde_with::DurationSeconds<i64>>>")
)]
pub auto_renew_period: Option<Duration>,
#[cfg_attr(
feature = "ffi",
serde(with = "serde_with::As::<Option<serde_with::TimestampNanoSeconds>>")
)]
pub expiration_time: Option<OffsetDateTime>,
pub token_memo: String,
pub token_type: TokenType,
pub supply_type: TokenSupplyType,
pub max_supply: u64,
pub custom_fees: Vec<AnyCustomFee>,
pub pause_key: Option<Key>,
pub pause_status: Option<bool>,
pub ledger_id: LedgerId,
}
impl TokenInfo {
pub fn from_bytes(bytes: &[u8]) -> crate::Result<Self> {
FromProtobuf::<services::TokenInfo>::from_bytes(bytes)
}
#[must_use]
pub fn to_bytes(&self) -> Vec<u8> {
let default_freeze_status = match self.default_freeze_status {
Some(true) => TokenFreezeStatus::Frozen as i32,
Some(false) => TokenFreezeStatus::Unfrozen as i32,
None => TokenFreezeStatus::FreezeNotApplicable as i32,
};
let default_kyc_status = match self.default_kyc_status {
Some(true) => TokenKycStatus::Granted as i32,
Some(false) => TokenKycStatus::Revoked as i32,
None => TokenKycStatus::KycNotApplicable as i32,
};
services::TokenInfo {
token_id: Some(self.token_id.to_protobuf()),
name: self.name.clone(),
symbol: self.symbol.clone(),
decimals: self.decimals,
total_supply: self.total_supply,
treasury: Some(self.treasury_account_id.to_protobuf()),
admin_key: self.admin_key.to_protobuf(),
kyc_key: self.kyc_key.to_protobuf(),
freeze_key: self.freeze_key.to_protobuf(),
wipe_key: self.wipe_key.to_protobuf(),
supply_key: self.supply_key.to_protobuf(),
default_freeze_status,
default_kyc_status,
deleted: self.is_deleted,
auto_renew_account: self.auto_renew_account.to_protobuf(),
auto_renew_period: self.auto_renew_period.to_protobuf(),
expiry: self.expiration_time.to_protobuf(),
memo: self.token_memo.clone(),
token_type: self.token_type.to_protobuf() as i32,
supply_type: self.supply_type.to_protobuf() as i32,
max_supply: self.max_supply as i64,
fee_schedule_key: self.fee_schedule_key.to_protobuf(),
custom_fees: self.custom_fees.to_protobuf(),
pause_key: self.pause_key.to_protobuf(),
pause_status: match self.pause_status {
Some(true) => TokenPauseStatus::Paused as i32,
Some(false) => TokenPauseStatus::Unpaused as i32,
None => TokenPauseStatus::PauseNotApplicable as i32,
},
ledger_id: self.ledger_id.to_bytes(),
}
.encode_to_vec()
}
}
impl FromProtobuf<services::response::Response> for TokenInfo {
#[allow(deprecated)]
fn from_protobuf(pb: services::response::Response) -> crate::Result<Self>
where
Self: Sized,
{
let response = pb_getv!(pb, TokenGetInfo, services::response::Response);
let info = pb_getf!(response, token_info)?;
Self::from_protobuf(info)
}
}
impl FromProtobuf<services::TokenInfo> for TokenInfo {
fn from_protobuf(pb: services::TokenInfo) -> crate::Result<Self>
where
Self: Sized,
{
let token_type = TokenType::from_protobuf(pb.token_type())?;
let token_supply_type = TokenSupplyType::from_protobuf(pb.supply_type())?;
let token_id = pb_getf!(pb, token_id)?;
let default_kyc_status = match pb.default_kyc_status() {
TokenKycStatus::KycNotApplicable => None,
TokenKycStatus::Granted => Some(true),
TokenKycStatus::Revoked => Some(false),
};
let default_freeze_status = match pb.default_freeze_status() {
TokenFreezeStatus::FreezeNotApplicable => None,
TokenFreezeStatus::Frozen => Some(true),
TokenFreezeStatus::Unfrozen => Some(false),
};
let pause_status = match pb.pause_status() {
TokenPauseStatus::PauseNotApplicable => None,
TokenPauseStatus::Paused => Some(true),
TokenPauseStatus::Unpaused => Some(false),
};
let auto_renew_account_id = Option::from_protobuf(pb.auto_renew_account)?;
let treasury_account_id = pb_getf!(pb, treasury)?;
let ledger_id = LedgerId::from_bytes(pb.ledger_id);
Ok(Self {
token_id: TokenId::from_protobuf(token_id)?,
name: pb.name,
symbol: pb.symbol,
decimals: pb.decimals,
total_supply: pb.total_supply,
treasury_account_id: AccountId::from_protobuf(treasury_account_id)?,
admin_key: Option::from_protobuf(pb.admin_key)?,
kyc_key: Option::from_protobuf(pb.kyc_key)?,
freeze_key: Option::from_protobuf(pb.freeze_key)?,
wipe_key: Option::from_protobuf(pb.wipe_key)?,
supply_key: Option::from_protobuf(pb.supply_key)?,
default_freeze_status,
default_kyc_status,
is_deleted: pb.deleted,
auto_renew_account: auto_renew_account_id,
auto_renew_period: pb.auto_renew_period.map(Into::into),
expiration_time: pb.expiry.map(Into::into),
token_memo: pb.memo,
token_type,
supply_type: token_supply_type,
max_supply: pb.max_supply as u64,
fee_schedule_key: Option::from_protobuf(pb.fee_schedule_key)?,
custom_fees: Vec::from_protobuf(pb.custom_fees)?, pause_key: Option::from_protobuf(pb.pause_key)?,
pause_status,
ledger_id,
})
}
}