zera-sdk 0.1.0

Rust SDK for ZERA transactions, validator APIs, and bridge workflows
Documentation
use prost::Message;
use zera_proto::zera_txn::{
    CoinTxn, ContractUpdateTxn, GovernanceVote, InstrumentContract, SmartContractExecuteTxn,
};

use crate::error::Result;
use crate::grpc::transport::{unary, GrpcWebTransport, UnaryTransport};
use crate::tx::{transaction_hash_hex, BaseTxnAccess, TxnRoute};
use crate::types::RpcConfig;

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SubmitTransactionResult {
    pub success: bool,
    pub hash: Option<String>,
}

#[derive(Clone)]
pub struct TransactionClient<T = GrpcWebTransport> {
    transport: T,
}

#[derive(Clone, PartialEq, Message)]
struct EmptyResponse {}

impl TransactionClient<GrpcWebTransport> {
    pub fn new(config: RpcConfig) -> Result<Self> {
        Ok(Self {
            transport: GrpcWebTransport::new(config)?,
        })
    }
}

impl<T> TransactionClient<T>
where
    T: UnaryTransport,
{
    pub fn with_transport(transport: T) -> Self {
        Self { transport }
    }

    pub async fn submit_transaction<MessageType>(
        &self,
        txn: &MessageType,
    ) -> Result<SubmitTransactionResult>
    where
        MessageType: Message + TxnRoute + BaseTxnAccess,
    {
        let _: EmptyResponse = unary(&self.transport, &MessageType::rpc_path(), txn).await?;
        Ok(SubmitTransactionResult {
            success: true,
            hash: transaction_hash_hex(txn),
        })
    }

    pub async fn submit_coin_transaction(&self, txn: &CoinTxn) -> Result<SubmitTransactionResult> {
        self.submit_transaction(txn).await
    }

    pub async fn submit_governance_vote(
        &self,
        txn: &GovernanceVote,
    ) -> Result<SubmitTransactionResult> {
        self.submit_transaction(txn).await
    }

    pub async fn submit_smart_contract_execute(
        &self,
        txn: &SmartContractExecuteTxn,
    ) -> Result<SubmitTransactionResult> {
        self.submit_transaction(txn).await
    }

    pub async fn submit_contract(
        &self,
        txn: &InstrumentContract,
    ) -> Result<SubmitTransactionResult> {
        self.submit_transaction(txn).await
    }

    pub async fn submit_contract_update(
        &self,
        txn: &ContractUpdateTxn,
    ) -> Result<SubmitTransactionResult> {
        self.submit_transaction(txn).await
    }
}

pub async fn submit_transaction<MessageType>(txn: &MessageType, config: RpcConfig) -> Result<String>
where
    MessageType: Message + TxnRoute + BaseTxnAccess,
{
    let client = TransactionClient::new(config)?;
    let result = client.submit_transaction(txn).await?;
    Ok(result
        .hash
        .unwrap_or_else(|| "Transaction submitted (no hash available)".to_string()))
}