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