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()))
}