use std::sync::Arc;
use axum::{Extension, Json, http::StatusCode};
use log::{debug, warn};
use serde::{Deserialize, Serialize};
use tari_core::{base_node::rpc::query_service, chain_storage::BlockchainBackend, mempool::service::MempoolHandle};
use tari_transaction_components::rpc::models::TxSubmissionResponseV1;
use crate::http::handler::ErrorResponse;
pub mod submit_transaction;
const LOG_TARGET: &str = "c::base_node::rpc::http::handler::json_rpc";
pub async fn handle<B: BlockchainBackend + 'static>(
Extension(query_service): Extension<Arc<query_service::Service<B>>>,
Extension(mempool_service): Extension<MempoolHandle>,
Json(request): Json<JsonRpcRequest>,
) -> Result<Json<JsonRpcResponse>, (StatusCode, Json<ErrorResponse>)> {
debug!(target: LOG_TARGET, "Received JSON-RPC request: {request:?}");
match request.method.as_str() {
"submit_transaction" => {
let tx = request.params.get("transaction").ok_or_else(|| {
(
StatusCode::BAD_REQUEST,
Json(ErrorResponse::new("Missing transaction parameter".to_string())),
)
})?;
let transaction = serde_json::from_value(tx.clone())
.map_err(|e| (StatusCode::BAD_REQUEST, Json(ErrorResponse::new(e.to_string()))))?;
let version: u64 = request.params.get("version").and_then(|v| v.as_u64()).unwrap_or(1);
match submit_transaction::handle(query_service.clone(), &mut (mempool_service.clone()), transaction).await {
Ok(response) => {
let result = if version >= 2 {
serde_json::to_value(response).unwrap_or_else(|e| {
warn!(target: LOG_TARGET, "Failed to serialize response: {e}");
serde_json::Value::Null
})
} else {
serde_json::to_value(TxSubmissionResponseV1::from(response)).unwrap_or_else(|e| {
warn!(target: LOG_TARGET, "Failed to serialize V1 response: {e}");
serde_json::Value::Null
})
};
Ok(Json(JsonRpcResponse {
result,
error: None,
id: request.id,
}))
},
Err(e) => {
debug!(target: LOG_TARGET, "Error submitting transaction: {e}");
Ok(Json(JsonRpcResponse {
result: serde_json::Value::Null,
error: Some(e.to_string()),
id: request.id,
}))
},
}
},
_ => Err((
StatusCode::BAD_REQUEST,
Json(ErrorResponse::new("Method not found".to_string())),
)),
}
}
#[derive(Deserialize, Debug, Serialize)]
pub struct JsonRpcRequest {
pub jsonrpc: String,
pub id: String,
pub method: String,
pub params: serde_json::Value,
}
#[derive(Serialize, Debug)]
pub struct JsonRpcResponse {
pub result: serde_json::Value,
pub error: Option<String>,
pub id: String,
}