From c5d5b3639dc6f52c0b6717aff05224d3475d28ae Mon Sep 17 00:00:00 2001 From: Lukasz Rubaszewski <117115317+lrubasze@users.noreply.github.com> Date: Mon, 11 Nov 2024 19:02:10 +0100 Subject: [PATCH] Implement mempool/transaction endpoint --- .../src/mesh_api/conversions/common.rs | 4 ++ .../src/mesh_api/conversions/hashes.rs | 17 ++++++++ .../src/mesh_api/handlers/mempool.rs | 40 +++++++++++++++++++ .../mesh-api-server/src/mesh_api/server.rs | 2 +- 4 files changed, 62 insertions(+), 1 deletion(-) diff --git a/core-rust/mesh-api-server/src/mesh_api/conversions/common.rs b/core-rust/mesh-api-server/src/mesh_api/conversions/common.rs index 17279efa5b..1f1b8647b6 100644 --- a/core-rust/mesh-api-server/src/mesh_api/conversions/common.rs +++ b/core-rust/mesh-api-server/src/mesh_api/conversions/common.rs @@ -1,5 +1,9 @@ use crate::prelude::*; +pub fn from_hex>(v: T) -> Result, ExtractionError> { + hex::decode(v).map_err(|_| ExtractionError::InvalidHex) +} + pub fn to_mesh_api_operation( mapping_context: &MappingContext, database: &StateManagerDatabase, diff --git a/core-rust/mesh-api-server/src/mesh_api/conversions/hashes.rs b/core-rust/mesh-api-server/src/mesh_api/conversions/hashes.rs index 6d58bb07ba..6c9a848c39 100644 --- a/core-rust/mesh-api-server/src/mesh_api/conversions/hashes.rs +++ b/core-rust/mesh-api-server/src/mesh_api/conversions/hashes.rs @@ -9,3 +9,20 @@ pub fn to_api_transaction_hash_bech32m( .encode(hash) .map_err(|err| MappingError::InvalidTransactionHash { encode_error: err }) } + +pub fn extract_transaction_intent_hash( + context: &ExtractionContext, + hash_str: String, +) -> Result { + from_hex(&hash_str) + .ok() + .and_then(|bytes| Hash::try_from(bytes.as_slice()).ok()) + .map(TransactionIntentHash::from_hash) + .or_else(|| { + context + .transaction_hash_decoder + .validate_and_decode(&hash_str) + .ok() + }) + .ok_or(ExtractionError::InvalidHash) +} diff --git a/core-rust/mesh-api-server/src/mesh_api/handlers/mempool.rs b/core-rust/mesh-api-server/src/mesh_api/handlers/mempool.rs index 3f5d122a94..6d5e04ee1b 100644 --- a/core-rust/mesh-api-server/src/mesh_api/handlers/mempool.rs +++ b/core-rust/mesh-api-server/src/mesh_api/handlers/mempool.rs @@ -20,3 +20,43 @@ pub(crate) async fn handle_mempool( .collect::, MappingError>>()?, ))) } + +pub(crate) async fn handle_mempool_transaction( + state: State, + Json(request): Json, +) -> Result, ResponseError> { + assert_matching_network(&request.network_identifier, &state.network)?; + + let extraction_context = ExtractionContext::new(&state.network); + let mapping_context = MappingContext::new(&state.network); + let mempool = state.state_manager.mempool.read(); + + let intent_hash = extract_transaction_intent_hash( + &extraction_context, + request.transaction_identifier.hash.clone(), + ) + .map_err(|err| err.into_response_error("intent_hash"))?; + + if mempool + .get_notarized_transaction_hashes_for_intent(&intent_hash) + .is_empty() + { + return Err( + ResponseError::from(ApiError::TransactionNotFound).with_details(format!( + "transaction {} not found in mempool transactions", + &request.transaction_identifier.hash + )), + ); + } + + // TODO:MESH prepare transaction estimates + let transaction = models::Transaction::new( + models::TransactionIdentifier::new(to_api_transaction_hash_bech32m( + &mapping_context, + &intent_hash, + )?), + vec![], + ); + + Ok(Json(models::MempoolTransactionResponse::new(transaction))) +} diff --git a/core-rust/mesh-api-server/src/mesh_api/server.rs b/core-rust/mesh-api-server/src/mesh_api/server.rs index 946fa66034..21d0e0c291 100644 --- a/core-rust/mesh-api-server/src/mesh_api/server.rs +++ b/core-rust/mesh-api-server/src/mesh_api/server.rs @@ -109,7 +109,7 @@ pub async fn create_server( .route("/block/transaction", post(handle_block_transaction)) // TODO:MESH mempool .route("/mempool", post(handle_mempool)) - .route("/mempool/transaction", post(handle_endpoint_todo)) + .route("/mempool/transaction", post(handle_mempool_transaction)) .route("/construction/derive", post(handle_endpoint_todo)) .route("/construction/preprocess", post(handle_endpoint_todo)) .route("/construction/metadata", post(handle_endpoint_todo))