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}