iota_rosetta/
lib.rs

1// Copyright (c) Mysten Labs, Inc.
2// Modifications Copyright (c) 2024 IOTA Stiftung
3// SPDX-License-Identifier: Apache-2.0
4
5use std::{net::SocketAddr, sync::Arc};
6
7use axum::{Extension, Router, routing::post};
8use iota_sdk::IotaClient;
9use once_cell::sync::Lazy;
10use tracing::info;
11
12use crate::{
13    errors::Error,
14    state::{CheckpointBlockProvider, OnlineServerContext},
15    types::{Currency, IotaEnv},
16};
17
18/// This lib implements the Rosetta online and offline server defined by the [Rosetta API Spec](https://www.rosetta-api.org/docs/Reference.html)
19mod account;
20mod block;
21mod construction;
22mod errors;
23mod network;
24pub mod operations;
25mod state;
26pub mod types;
27
28pub static IOTA: Lazy<Currency> = Lazy::new(|| Currency {
29    symbol: "IOTA".to_string(),
30    decimals: 9,
31});
32
33pub struct RosettaOnlineServer {
34    env: IotaEnv,
35    context: OnlineServerContext,
36}
37
38impl RosettaOnlineServer {
39    pub fn new(env: IotaEnv, client: IotaClient) -> Self {
40        let blocks = Arc::new(CheckpointBlockProvider::new(client.clone()));
41        Self {
42            env,
43            context: OnlineServerContext::new(client, blocks),
44        }
45    }
46
47    pub async fn serve(self, addr: SocketAddr) {
48        // Online endpoints
49        let app = Router::new()
50            .route("/account/balance", post(account::balance))
51            .route("/account/coins", post(account::coins))
52            .route("/block", post(block::block))
53            .route("/block/transaction", post(block::transaction))
54            .route("/construction/submit", post(construction::submit))
55            .route("/construction/metadata", post(construction::metadata))
56            .route("/network/status", post(network::status))
57            .route("/network/list", post(network::list))
58            .route("/network/options", post(network::options))
59            .layer(Extension(self.env))
60            .with_state(self.context);
61
62        let listener = tokio::net::TcpListener::bind(&addr).await.unwrap();
63
64        info!(
65            "IOTA Rosetta online server listening on {}",
66            listener.local_addr().unwrap()
67        );
68        axum::serve(listener, app).await.unwrap();
69    }
70}
71
72pub struct RosettaOfflineServer {
73    env: IotaEnv,
74}
75
76impl RosettaOfflineServer {
77    pub fn new(env: IotaEnv) -> Self {
78        Self { env }
79    }
80
81    pub async fn serve(self, addr: SocketAddr) {
82        // Online endpoints
83        let app = Router::new()
84            .route("/construction/derive", post(construction::derive))
85            .route("/construction/payloads", post(construction::payloads))
86            .route("/construction/combine", post(construction::combine))
87            .route("/construction/preprocess", post(construction::preprocess))
88            .route("/construction/hash", post(construction::hash))
89            .route("/construction/parse", post(construction::parse))
90            .route("/network/list", post(network::list))
91            .route("/network/options", post(network::options))
92            .layer(Extension(self.env));
93        let listener = tokio::net::TcpListener::bind(&addr).await.unwrap();
94
95        info!(
96            "IOTA Rosetta offline server listening on {}",
97            listener.local_addr().unwrap()
98        );
99        axum::serve(listener, app).await.unwrap();
100    }
101}