explorerd/rpc/transactions.rs
1/* This file is part of DarkFi (https://dark.fi)
2 *
3 * Copyright (C) 2020-2025 Dyne.org foundation
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Affero General Public License as
7 * published by the Free Software Foundation, either version 3 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17 */
18
19use tinyjson::JsonValue;
20
21use darkfi::{rpc::jsonrpc::parse_json_array_string, Result};
22use darkfi_sdk::tx::TransactionHash;
23
24use crate::{error::ExplorerdError, Explorerd};
25
26impl Explorerd {
27 // RPCAPI:
28 // Queries the database to retrieve the transactions corresponding to the provided block header hash.
29 // Returns the readable transactions upon success.
30 //
31 // **Params:**
32 // * `array[0]`: `String` Block header hash
33 //
34 // **Returns:**
35 // * Array of `TransactionRecord` encoded into a JSON.
36 //
37 // **Example API Usage:**
38 // --> {"jsonrpc": "2.0", "method": "transactions.get_transactions_by_header_hash", "params": ["5cc...2f9"], "id": 1}
39 // <-- {"jsonrpc": "2.0", "result": {...}, "id": 1}
40 pub async fn transactions_get_transactions_by_header_hash(
41 &self,
42 params: &JsonValue,
43 ) -> Result<JsonValue> {
44 // Extract header hash
45 let header_hash = parse_json_array_string("header_hash", 0, params)?;
46
47 // Retrieve transactions by header hash
48 let transactions = self.service.get_transactions_by_header_hash(&header_hash)?;
49
50 // Convert transactions into a JSON array, return result
51 Ok(JsonValue::Array(transactions.iter().map(|tx| tx.to_json_array()).collect()))
52 }
53
54 // RPCAPI:
55 // Queries the database to retrieve the transaction corresponding to the provided hash.
56 // Returns the readable transaction upon success.
57 //
58 // **Params:**
59 // * `array[0]`: `String` Transaction hash
60 //
61 // **Returns:**
62 // * `TransactionRecord` encoded into a JSON.
63 //
64 // **Example API Usage:**
65 // --> {"jsonrpc": "2.0", "method": "transactions.get_transaction_by_hash", "params": ["7e7...b4d"], "id": 1}
66 // <-- {"jsonrpc": "2.0", "result": {...}, "id": 1}
67 pub async fn transactions_get_transaction_by_hash(
68 &self,
69 params: &JsonValue,
70 ) -> Result<JsonValue> {
71 // Extract transaction hash
72 let tx_hash_str = parse_json_array_string("tx_hash", 0, params)?;
73
74 // Convert the provided hash into a `TransactionHash` instance
75 let tx_hash = tx_hash_str
76 .parse::<TransactionHash>()
77 .map_err(|_| ExplorerdError::InvalidTxHash(tx_hash_str.to_string()))?;
78
79 // Retrieve the transaction by its hash, returning the result as a JsonValue array
80 match self.service.get_transaction_by_hash(&tx_hash)? {
81 Some(transaction) => Ok(transaction.to_json_array()),
82 None => Ok(JsonValue::Array(vec![])),
83 }
84 }
85}
86
87#[cfg(test)]
88/// Test module for validating the functionality of RPC methods related to explorer transactions.
89/// Focuses on ensuring proper error handling for invalid parameters across several use cases,
90/// including cases with missing values, unsupported types, and unparsable inputs.
91mod tests {
92
93 use crate::test_utils::{
94 setup, validate_invalid_rpc_header_hash, validate_invalid_rpc_tx_hash,
95 };
96
97 #[test]
98 /// Tests the handling of invalid parameters for the `transactions.get_transactions_by_header_hash` JSON-RPC method.
99 /// Verifies that missing and an invalid `header_hash` value results in an appropriate error.
100 fn test_transactions_get_transactions_by_header_hash() {
101 smol::block_on(async {
102 // Define the RPC method name
103 let rpc_method = "transactions.get_transactions_by_header_hash";
104
105 // Set up the explorerd
106 let explorerd = setup();
107
108 // Validate when provided with an invalid header hash
109 validate_invalid_rpc_header_hash(&explorerd, rpc_method);
110 });
111 }
112 #[test]
113 /// Tests the handling of invalid parameters for the `transactions.get_transaction_by_hash` JSON-RPC method.
114 /// Verifies that missing and an invalid `tx_hash` value results in an appropriate error.
115 fn test_transactions_get_transaction_by_hash() {
116 smol::block_on(async {
117 // Define the RPC method name
118 let rpc_method = "transactions.get_transaction_by_hash";
119
120 // Set up the explorerd
121 let explorerd = setup();
122
123 // Validate when provided with an invalid tx hash
124 validate_invalid_rpc_tx_hash(&explorerd, rpc_method);
125 });
126 }
127}