Skip to main content

mina_node_native/http_server/routes/
transaction.rs

1//! Transaction endpoints.
2//!
3//! - `GET /transaction-pool` - Get transaction pool
4//! - `GET /accounts` - Get all accounts
5//! - `POST /send-payment` - Send a payment transaction
6//! - `GET /best-chain-user-commands` - Get user commands from best chain
7
8use axum::{extract::State, Json};
9use utoipa_axum::{router::OpenApiRouter, routes};
10
11use mina_node::rpc::{
12    RpcInjectPayment, RpcLedgerSlimAccountsResponse, RpcTransactionInjectResponse,
13    RpcTransactionPoolResponse, RpcTransitionFrontierUserCommandsResponse,
14};
15
16use crate::http_server::{AppError, AppResult, AppState};
17
18/// Transaction routes
19pub fn routes() -> OpenApiRouter<AppState> {
20    OpenApiRouter::new()
21        .routes(routes!(transaction_pool))
22        .routes(routes!(accounts))
23        .routes(routes!(send_payment))
24        .routes(routes!(best_chain_user_commands))
25}
26
27/// Transaction pool
28#[utoipa::path(
29    get,
30    path = "/transaction-pool",
31    tag = "transaction",
32    responses(
33        (status = 200, description = "Transaction pool")
34    )
35)]
36async fn transaction_pool(
37    State(state): State<AppState>,
38) -> AppResult<Json<RpcTransactionPoolResponse>> {
39    state
40        .rpc_sender()
41        .transaction_pool()
42        .get()
43        .await
44        .map(Json)
45        .ok_or(AppError::ChannelDropped)
46}
47
48/// All accounts from latest ledger
49#[utoipa::path(
50    get,
51    path = "/accounts",
52    tag = "transaction",
53    responses(
54        (status = 200, description = "All accounts")
55    )
56)]
57async fn accounts(State(state): State<AppState>) -> AppResult<Json<RpcLedgerSlimAccountsResponse>> {
58    state
59        .rpc_sender()
60        .ledger()
61        .latest()
62        .accounts()
63        .all()
64        .await
65        .map(Json)
66        .ok_or(AppError::ChannelDropped)
67}
68
69/// Send payment transactions
70#[utoipa::path(
71    post,
72    path = "/send-payment",
73    tag = "transaction",
74    responses(
75        (status = 200, description = "Payment result")
76    )
77)]
78async fn send_payment(
79    State(state): State<AppState>,
80    Json(payments): Json<Vec<RpcInjectPayment>>,
81) -> AppResult<Json<RpcTransactionInjectResponse>> {
82    match state
83        .rpc_sender()
84        .transaction_pool()
85        .inject()
86        .payment(payments)
87        .await
88    {
89        Err(err) => Err(AppError::Internal(err)),
90        Ok(None) => Err(AppError::ChannelDropped),
91        Ok(Some(resp)) => Ok(Json(resp)),
92    }
93}
94
95/// User commands from best chain
96#[utoipa::path(
97    get,
98    path = "/best-chain-user-commands",
99    tag = "transaction",
100    responses(
101        (status = 200, description = "User commands from best chain")
102    )
103)]
104async fn best_chain_user_commands(
105    State(state): State<AppState>,
106) -> AppResult<Json<RpcTransitionFrontierUserCommandsResponse>> {
107    state
108        .rpc_sender()
109        .transition_frontier()
110        .best_chain()
111        .user_commands()
112        .await
113        .map(Json)
114        .ok_or(AppError::ChannelDropped)
115}