unc_jsonrpc_primitives/types/
transactions.rs

1use serde_json::Value;
2use unc_primitives::hash::CryptoHash;
3use unc_primitives::types::AccountId;
4
5#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
6pub struct RpcSendTransactionRequest {
7    #[serde(rename = "signed_tx_base64")]
8    pub signed_transaction: unc_primitives::transaction::SignedTransaction,
9    #[serde(default)]
10    pub wait_until: unc_primitives::views::TxExecutionStatus,
11}
12
13#[derive(Debug, serde::Serialize, serde::Deserialize)]
14pub struct RpcTransactionStatusRequest {
15    #[serde(flatten)]
16    pub transaction_info: TransactionInfo,
17    #[serde(default)]
18    pub wait_until: unc_primitives::views::TxExecutionStatus,
19}
20
21#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
22#[serde(untagged)]
23pub enum TransactionInfo {
24    Transaction(SignedTransaction),
25    TransactionId { tx_hash: CryptoHash, sender_account_id: AccountId },
26}
27
28#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
29pub enum SignedTransaction {
30    #[serde(rename = "signed_tx_base64")]
31    SignedTransaction(unc_primitives::transaction::SignedTransaction),
32}
33
34#[derive(thiserror::Error, Debug, serde::Serialize, serde::Deserialize, Clone)]
35#[serde(tag = "name", content = "info", rename_all = "SCREAMING_SNAKE_CASE")]
36pub enum RpcTransactionError {
37    #[error("An error happened during transaction execution: {context:?}")]
38    InvalidTransaction {
39        #[serde(skip_serializing)]
40        context: unc_primitives::errors::InvalidTxError,
41    },
42    #[error("Node doesn't track this shard. Cannot determine whether the transaction is valid")]
43    DoesNotTrackShard,
44    #[error("Transaction with hash {transaction_hash} was routed")]
45    RequestRouted { transaction_hash: unc_primitives::hash::CryptoHash },
46    #[error("Transaction {requested_transaction_hash} doesn't exist")]
47    UnknownTransaction { requested_transaction_hash: unc_primitives::hash::CryptoHash },
48    #[error("The node reached its limits. Try again later. More details: {debug_info}")]
49    InternalError { debug_info: String },
50    #[error("Timeout")]
51    TimeoutError,
52}
53
54#[derive(serde::Serialize, serde::Deserialize, Debug)]
55pub struct RpcTransactionResponse {
56    #[serde(flatten)]
57    pub final_execution_outcome: Option<unc_primitives::views::FinalExecutionOutcomeViewEnum>,
58    pub final_execution_status: unc_primitives::views::TxExecutionStatus,
59}
60
61#[derive(serde::Serialize, serde::Deserialize, Debug)]
62pub struct RpcBroadcastTxSyncResponse {
63    pub transaction_hash: unc_primitives::hash::CryptoHash,
64}
65
66impl TransactionInfo {
67    pub fn from_signed_tx(tx: unc_primitives::transaction::SignedTransaction) -> Self {
68        Self::Transaction(SignedTransaction::SignedTransaction(tx))
69    }
70
71    pub fn to_signed_tx(&self) -> Option<&unc_primitives::transaction::SignedTransaction> {
72        match self {
73            TransactionInfo::Transaction(tx) => match tx {
74                SignedTransaction::SignedTransaction(tx) => Some(tx),
75            },
76            TransactionInfo::TransactionId { .. } => None,
77        }
78    }
79
80    pub fn to_tx_hash_and_account(&self) -> (CryptoHash, &AccountId) {
81        match self {
82            TransactionInfo::Transaction(tx) => match tx {
83                SignedTransaction::SignedTransaction(tx) => {
84                    (tx.get_hash(), &tx.transaction.signer_id)
85                }
86            },
87            TransactionInfo::TransactionId { tx_hash, sender_account_id } => {
88                (*tx_hash, sender_account_id)
89            }
90        }
91    }
92}
93
94impl From<unc_primitives::transaction::SignedTransaction> for TransactionInfo {
95    fn from(transaction_info: unc_primitives::transaction::SignedTransaction) -> Self {
96        Self::Transaction(SignedTransaction::SignedTransaction(transaction_info))
97    }
98}
99
100impl From<unc_primitives::views::TxStatusView> for RpcTransactionResponse {
101    fn from(view: unc_primitives::views::TxStatusView) -> Self {
102        Self {
103            final_execution_outcome: view.execution_outcome,
104            final_execution_status: view.status,
105        }
106    }
107}
108
109impl From<RpcTransactionError> for crate::errors::RpcError {
110    fn from(error: RpcTransactionError) -> Self {
111        let error_data = match &error {
112            RpcTransactionError::InvalidTransaction { context } => {
113                if let Ok(value) =
114                    serde_json::to_value(crate::errors::ServerError::TxExecutionError(
115                        unc_primitives::errors::TxExecutionError::InvalidTxError(context.clone()),
116                    ))
117                {
118                    value
119                } else {
120                    Value::String(error.to_string())
121                }
122            }
123            _ => Value::String(error.to_string()),
124        };
125
126        let error_data_value = match serde_json::to_value(error) {
127            Ok(value) => value,
128            Err(err) => {
129                return Self::new_internal_error(
130                    None,
131                    format!("Failed to serialize RpcTransactionError: {:?}", err),
132                )
133            }
134        };
135
136        Self::new_internal_or_handler_error(Some(error_data), error_data_value)
137    }
138}