celestia_grpc/grpc/
celestia_tx.rs

1use std::fmt;
2use std::str::FromStr;
3
4#[cfg(all(target_arch = "wasm32", feature = "wasm-bindgen"))]
5use wasm_bindgen::prelude::*;
6
7use celestia_proto::celestia::core::v1::tx::{
8    TxStatusRequest as RawTxStatusRequest, TxStatusResponse as RawTxStatusResponse,
9};
10use celestia_types::Height;
11use celestia_types::hash::Hash;
12use celestia_types::state::ErrorCode;
13
14use crate::grpc::{FromGrpcResponse, IntoGrpcParam};
15use crate::{Error, Result};
16
17#[cfg(feature = "uniffi")]
18uniffi::use_remote_type!(celestia_types::Height);
19
20/// Response to a tx status query
21#[derive(Debug, Clone)]
22#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
23#[cfg_attr(
24    all(target_arch = "wasm32", feature = "wasm-bindgen"),
25    wasm_bindgen(getter_with_clone)
26)]
27pub struct TxStatusResponse {
28    /// Height of the block in which the transaction was committed.
29    #[cfg_attr(
30        all(target_arch = "wasm32", feature = "wasm-bindgen"),
31        wasm_bindgen(skip)
32    )]
33    pub height: Height,
34    /// Index of the transaction in block.
35    pub index: u32,
36    /// Execution_code is returned when the transaction has been committed
37    /// and returns whether it was successful or errored. A non zero
38    /// execution code indicates an error.
39    pub execution_code: ErrorCode,
40    /// Error log, if transaction failed.
41    pub error: String,
42    /// Status of the transaction.
43    pub status: TxStatus,
44}
45
46/// Represents state of the transaction in the mempool
47#[derive(Debug, Copy, Clone, PartialEq, Eq)]
48#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
49#[cfg_attr(all(target_arch = "wasm32", feature = "wasm-bindgen"), wasm_bindgen)]
50pub enum TxStatus {
51    /// The transaction is not known to the node, it could be never sent.
52    Unknown,
53    /// The transaction is still pending.
54    Pending,
55    /// The transaction was evicted from the mempool.
56    Evicted,
57    /// The transaction was rejected
58    Rejected,
59    /// The transaction was committed into the block.
60    Committed,
61}
62
63impl fmt::Display for TxStatus {
64    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65        let s = match self {
66            TxStatus::Unknown => "UNKNOWN",
67            TxStatus::Pending => "PENDING",
68            TxStatus::Evicted => "EVICTED",
69            TxStatus::Rejected => "REJECTED",
70            TxStatus::Committed => "COMMITTED",
71        };
72        write!(f, "{s}")
73    }
74}
75
76impl FromStr for TxStatus {
77    type Err = Error;
78
79    fn from_str(s: &str) -> Result<Self, Self::Err> {
80        match s {
81            "UNKNOWN" => Ok(TxStatus::Unknown),
82            "PENDING" => Ok(TxStatus::Pending),
83            "EVICTED" => Ok(TxStatus::Evicted),
84            "REJECTED" => Ok(TxStatus::Rejected),
85            "COMMITTED" => Ok(TxStatus::Committed),
86            _ => Err(Error::FailedToParseResponse),
87        }
88    }
89}
90
91#[cfg(all(target_arch = "wasm32", feature = "wasm-bindgen"))]
92#[wasm_bindgen]
93impl TxStatusResponse {
94    /// Height of the block in which the transaction was committed.
95    #[wasm_bindgen(getter)]
96    pub fn height(&self) -> u64 {
97        self.height.value()
98    }
99}
100
101impl TryFrom<RawTxStatusResponse> for TxStatusResponse {
102    type Error = Error;
103
104    fn try_from(value: RawTxStatusResponse) -> Result<TxStatusResponse, Self::Error> {
105        Ok(TxStatusResponse {
106            height: value.height.try_into()?,
107            index: value.index,
108            execution_code: value.execution_code.try_into()?,
109            error: value.error,
110            status: value.status.parse()?,
111        })
112    }
113}
114
115impl IntoGrpcParam<RawTxStatusRequest> for Hash {
116    fn into_parameter(self) -> RawTxStatusRequest {
117        RawTxStatusRequest {
118            tx_id: self.to_string(),
119        }
120    }
121}
122
123impl FromGrpcResponse<TxStatusResponse> for RawTxStatusResponse {
124    fn try_from_response(self) -> Result<TxStatusResponse> {
125        self.try_into()
126    }
127}