diff --git a/bin/darkfid2/src/rpc.rs b/bin/darkfid2/src/rpc.rs index 17e1d29a0..a31a6224d 100644 --- a/bin/darkfid2/src/rpc.rs +++ b/bin/darkfid2/src/rpc.rs @@ -72,6 +72,8 @@ impl RequestHandler for Darkfid { // =================== Some("tx.simulate") => return self.tx_simulate(req.id, params).await, Some("tx.broadcast") => return self.tx_broadcast(req.id, params).await, + Some("tx.pending") => return self.tx_pending(req.id, params).await, + Some("tx.clean_pending") => return self.tx_pending(req.id, params).await, // ============== // Invalid method diff --git a/bin/darkfid2/src/rpc_tx.rs b/bin/darkfid2/src/rpc_tx.rs index de57b00de..4444bd53d 100644 --- a/bin/darkfid2/src/rpc_tx.rs +++ b/bin/darkfid2/src/rpc_tx.rs @@ -21,7 +21,10 @@ use log::error; use serde_json::{json, Value}; use darkfi::{ - rpc::jsonrpc::{ErrorCode::InvalidParams, JsonError, JsonResponse, JsonResult}, + rpc::jsonrpc::{ + ErrorCode::{InternalError, InvalidParams}, + JsonError, JsonResponse, JsonResult, + }, tx::Transaction, }; @@ -143,4 +146,72 @@ impl Darkfid { let tx_hash = tx.hash().to_string(); JsonResponse::new(json!(tx_hash), id).into() } + + // RPCAPI: + // Queries the node pending transactions store to retrieve all transactions. + // Returns a vector of serialized `Transaction` objects. + // + // --> {"jsonrpc": "2.0", "method": "tx.pending", "params": [], "id": 1} + // <-- {"jsonrpc": "2.0", "result": "[TxHash,...]", "id": 1} + pub async fn tx_pending(&self, id: Value, params: &[Value]) -> JsonResult { + if !params.is_empty() { + return JsonError::new(InvalidParams, None, id).into() + } + + if !(*self.synced.lock().await) { + error!("[RPC] tx.transfer: Blockchain is not synced"); + return server_error(RpcError::NotSynced, id, None) + } + + let validator = self.validator.read().await; + let pending_txs = match validator.blockchain.get_pending_txs() { + Ok(v) => { + drop(validator); + v + } + Err(e) => { + error!("[RPC] blockchain.get_pending_txs: Failed fetching pending txs: {}", e); + return JsonError::new(InternalError, None, id).into() + } + }; + let pending_txs: Vec = pending_txs.iter().map(|x| x.hash().to_string()).collect(); + JsonResponse::new(json!(pending_txs), id).into() + } + + // RPCAPI: + // Queries the node pending transactions store to remove all transactions. + // Returns a vector of serialized `Transaction` objects. + // + // --> {"jsonrpc": "2.0", "method": "tx.clean_pending", "params": [], "id": 1} + // <-- {"jsonrpc": "2.0", "result": "[TxHash,...]", "id": 1} + pub async fn tx_clean_pending(&self, id: Value, params: &[Value]) -> JsonResult { + if !params.is_empty() { + return JsonError::new(InvalidParams, None, id).into() + } + + if !(*self.synced.lock().await) { + error!("[RPC] tx.transfer: Blockchain is not synced"); + return server_error(RpcError::NotSynced, id, None) + } + + let validator = self.validator.read().await; + let pending_txs = match validator.blockchain.get_pending_txs() { + Ok(v) => v, + Err(e) => { + error!("[RPC] blockchain.get_pending_txs: Failed fetching pending txs: {}", e); + return JsonError::new(InternalError, None, id).into() + } + }; + + match validator.blockchain.remove_pending_txs(&pending_txs) { + Ok(()) => drop(validator), + Err(e) => { + error!("[RPC] blockchain.get_pending_txs: Failed fetching pending txs: {}", e); + return JsonError::new(InternalError, None, id).into() + } + }; + + let pending_txs: Vec = pending_txs.iter().map(|x| x.hash().to_string()).collect(); + JsonResponse::new(json!(pending_txs), id).into() + } }