use zera_proto::zera_txn::{
AllowanceTxn, BaseTxn, BurnSbttxn, CoinTxn, ComplianceTxn, ContractUpdateTxn, DelegatedTxn,
ExpenseRatioTxn, FastQuorumTxn, GovernanceProposal, GovernanceVote, InstrumentContract,
ItemizedMintTxn, MintTxn, Nfttxn, PublicKey, QuashTxn, RevokeTxn, SmartContractExecuteTxn,
SmartContractInstantiateTxn, SmartContractTxn, TransferAuthentication,
};
pub trait BaseTxnAccess {
fn base(&self) -> Option<&BaseTxn>;
fn base_mut(&mut self) -> Option<&mut BaseTxn>;
}
pub trait CoinTxnAccess {
fn auth_mut(&mut self) -> Option<&mut TransferAuthentication>;
}
pub trait TypedTransaction {
const TYPE_NAME: &'static str;
}
pub trait TxnRoute: TypedTransaction {
const RPC_METHOD: &'static str;
fn rpc_path() -> String {
crate::grpc::paths::txn_path(Self::RPC_METHOD)
}
}
pub fn transaction_hash_hex<T>(txn: &T) -> Option<String>
where
T: BaseTxnAccess,
{
txn.base()
.and_then(|base| base.hash.as_ref().map(|bytes| hex_encode(bytes)))
}
pub fn first_public_key(base: &BaseTxn) -> Option<&PublicKey> {
base.public_key.as_ref()
}
fn hex_encode(bytes: &[u8]) -> String {
let mut output = String::with_capacity(bytes.len() * 2);
for byte in bytes {
output.push_str(&format!("{byte:02x}"));
}
output
}
macro_rules! impl_base_access {
($type:ty) => {
impl BaseTxnAccess for $type {
fn base(&self) -> Option<&BaseTxn> {
self.base.as_ref()
}
fn base_mut(&mut self) -> Option<&mut BaseTxn> {
self.base.as_mut()
}
}
};
}
macro_rules! impl_typed_route {
($type:ty, $type_name:expr, $rpc_method:expr) => {
impl TypedTransaction for $type {
const TYPE_NAME: &'static str = $type_name;
}
impl TxnRoute for $type {
const RPC_METHOD: &'static str = $rpc_method;
}
};
}
impl CoinTxnAccess for CoinTxn {
fn auth_mut(&mut self) -> Option<&mut TransferAuthentication> {
self.auth.as_mut()
}
}
impl_base_access!(CoinTxn);
impl_base_access!(MintTxn);
impl_base_access!(ItemizedMintTxn);
impl_base_access!(InstrumentContract);
impl_base_access!(GovernanceProposal);
impl_base_access!(GovernanceVote);
impl_base_access!(SmartContractTxn);
impl_base_access!(SmartContractExecuteTxn);
impl_base_access!(SmartContractInstantiateTxn);
impl_base_access!(ExpenseRatioTxn);
impl_base_access!(Nfttxn);
impl_base_access!(ContractUpdateTxn);
impl_base_access!(DelegatedTxn);
impl_base_access!(QuashTxn);
impl_base_access!(FastQuorumTxn);
impl_base_access!(RevokeTxn);
impl_base_access!(ComplianceTxn);
impl_base_access!(BurnSbttxn);
impl_base_access!(AllowanceTxn);
impl_typed_route!(CoinTxn, "zera_txn.CoinTXN", "Coin");
impl_typed_route!(MintTxn, "zera_txn.MintTXN", "Mint");
impl_typed_route!(ItemizedMintTxn, "zera_txn.ItemizedMintTXN", "ItemMint");
impl_typed_route!(
InstrumentContract,
"zera_txn.InstrumentContract",
"Contract"
);
impl_typed_route!(
GovernanceProposal,
"zera_txn.GovernanceProposal",
"GovernProposal"
);
impl_typed_route!(GovernanceVote, "zera_txn.GovernanceVote", "GovernVote");
impl_typed_route!(
SmartContractTxn,
"zera_txn.SmartContractTXN",
"SmartContract"
);
impl_typed_route!(
SmartContractExecuteTxn,
"zera_txn.SmartContractExecuteTXN",
"SmartContractExecute"
);
impl_typed_route!(
SmartContractInstantiateTxn,
"zera_txn.SmartContractInstantiateTXN",
"SmartContractInstantiate"
);
impl_typed_route!(ExpenseRatioTxn, "zera_txn.ExpenseRatioTXN", "ExpenseRatio");
impl_typed_route!(Nfttxn, "zera_txn.NFTTXN", "NFT");
impl_typed_route!(
ContractUpdateTxn,
"zera_txn.ContractUpdateTXN",
"ContractUpdate"
);
impl_typed_route!(DelegatedTxn, "zera_txn.DelegatedTXN", "DelegatedVoting");
impl_typed_route!(QuashTxn, "zera_txn.QuashTXN", "Quash");
impl_typed_route!(FastQuorumTxn, "zera_txn.FastQuorumTXN", "FastQuorum");
impl_typed_route!(RevokeTxn, "zera_txn.RevokeTXN", "Revoke");
impl_typed_route!(ComplianceTxn, "zera_txn.ComplianceTXN", "Compliance");
impl_typed_route!(BurnSbttxn, "zera_txn.BurnSBTTXN", "BurnSBT");
impl_typed_route!(AllowanceTxn, "zera_txn.AllowanceTXN", "Allowance");