unc_jsonrpc_primitives/types/
transactions.rs1use 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}