1use std::net::SocketAddr;
4
5use crate::api_trait::MassaApiServer;
6use crate::{ApiServer, ApiV2, StopHandle, API};
7use async_trait::async_trait;
8use futures::future::{self, Either};
9use futures::StreamExt;
10use jsonrpsee::core::{client::Error as JsonRpseeError, RpcResult, SubscriptionResult};
11use jsonrpsee::{PendingSubscriptionSink, SubscriptionMessage};
12use massa_api_exports::config::APIConfig;
13use massa_api_exports::error::ApiError;
14use massa_api_exports::page::{PageRequest, PagedVec, PagedVecV2};
15use massa_api_exports::ApiRequest;
16use massa_consensus_exports::{ConsensusBroadcasts, ConsensusController};
17use massa_execution_exports::ExecutionController;
18use massa_models::address::Address;
19use massa_models::block_id::BlockId;
20use massa_models::slot::Slot;
21use massa_models::timeslots::get_latest_block_slot_at_timestamp;
22use massa_models::version::Version;
23use massa_pool_exports::PoolBroadcasts;
24use massa_time::MassaTime;
25use serde::Serialize;
26use tokio_stream::wrappers::BroadcastStream;
27
28impl API<ApiV2> {
29 pub fn new(
31 consensus_controller: Box<dyn ConsensusController>,
32 consensus_broadcasts: ConsensusBroadcasts,
33 execution_controller: Box<dyn ExecutionController>,
34 pool_broadcasts: PoolBroadcasts,
35 api_settings: APIConfig,
36 version: Version,
37 ) -> Self {
38 API(ApiV2 {
39 consensus_controller,
40 consensus_broadcasts,
41 execution_controller,
42 pool_broadcasts,
43 api_settings,
44 version,
45 })
46 }
47}
48
49#[async_trait]
50impl ApiServer for API<ApiV2> {
51 async fn serve(
52 self,
53 url: &SocketAddr,
54 api_config: &APIConfig,
55 ) -> Result<StopHandle, JsonRpseeError> {
56 crate::serve(self.into_rpc(), url, api_config).await
57 }
58}
59
60#[doc(hidden)]
61#[async_trait]
62impl MassaApiServer for API<ApiV2> {
63 async fn get_largest_stakers(
64 &self,
65 api_request: Option<ApiRequest>,
66 ) -> RpcResult<PagedVecV2<(Address, u64)>> {
67 let cfg = self.0.api_settings.clone();
68
69 let now = MassaTime::now();
70
71 let latest_block_slot_at_timestamp_result = get_latest_block_slot_at_timestamp(
72 cfg.thread_count,
73 cfg.t0,
74 cfg.genesis_timestamp,
75 now,
76 );
77
78 let curr_cycle = match latest_block_slot_at_timestamp_result {
79 Ok(Some(cur_slot)) if cur_slot.period <= self.0.api_settings.last_start_period => {
80 Slot::new(self.0.api_settings.last_start_period, 0).get_cycle(cfg.periods_per_cycle)
81 }
82 Ok(Some(cur_slot)) => cur_slot.get_cycle(cfg.periods_per_cycle),
83 Ok(None) => 0,
84 Err(e) => return Err(ApiError::ModelsError(e).into()),
85 };
86
87 let mut staker_vec = self
88 .0
89 .execution_controller
90 .get_cycle_active_rolls(curr_cycle)
91 .into_iter()
92 .collect::<Vec<(Address, u64)>>();
93
94 staker_vec
95 .sort_by(|&(_, roll_counts_a), &(_, roll_counts_b)| roll_counts_b.cmp(&roll_counts_a));
96
97 const DEFAULT_PAGE_LIMIT: usize = 50;
100 let page_request = api_request
101 .and_then(|request| request.page_request)
102 .or(Some(PageRequest {
103 offset: 0,
104 limit: DEFAULT_PAGE_LIMIT,
105 }));
106 let paged_vec = PagedVec::new(staker_vec, page_request);
107
108 Ok(paged_vec.into())
109 }
110
111 async fn get_next_block_best_parents(&self) -> RpcResult<Vec<(BlockId, u64)>> {
112 Ok(self.0.consensus_controller.get_best_parents())
113 }
114
115 async fn get_version(&self) -> RpcResult<Version> {
116 Ok(self.0.version)
117 }
118
119 async fn subscribe_new_blocks(&self, pending: PendingSubscriptionSink) -> SubscriptionResult {
120 broadcast_via_ws(self.0.consensus_broadcasts.block_sender.clone(), pending).await
121 }
122
123 async fn subscribe_new_blocks_headers(
124 &self,
125 pending: PendingSubscriptionSink,
126 ) -> SubscriptionResult {
127 broadcast_via_ws(
128 self.0.consensus_broadcasts.block_header_sender.clone(),
129 pending,
130 )
131 .await
132 }
133
134 async fn subscribe_new_filled_blocks(
135 &self,
136 pending: PendingSubscriptionSink,
137 ) -> SubscriptionResult {
138 broadcast_via_ws(
139 self.0.consensus_broadcasts.filled_block_sender.clone(),
140 pending,
141 )
142 .await
143 }
144
145 async fn subscribe_new_operations(
146 &self,
147 pending: PendingSubscriptionSink,
148 ) -> SubscriptionResult {
149 broadcast_via_ws(self.0.pool_broadcasts.operation_sender.clone(), pending).await
150 }
151}
152
153async fn broadcast_via_ws<T: Serialize + Send + Clone + 'static>(
155 sender: tokio::sync::broadcast::Sender<T>,
156 pending: PendingSubscriptionSink,
157) -> SubscriptionResult {
158 let sink = pending.accept().await?;
159 let closed = sink.closed();
160 let stream = BroadcastStream::new(sender.subscribe());
161 futures::pin_mut!(closed, stream);
162
163 loop {
164 match future::select(closed, stream.next()).await {
165 Either::Left((_, _)) => break Ok(()),
167
168 Either::Right((Some(Ok(item)), c)) => {
170 let notif = SubscriptionMessage::from_json(&item)?;
171
172 if sink.send(notif).await.is_err() {
173 break Ok(());
174 }
175
176 closed = c;
177 }
178
179 Either::Right((Some(Err(e)), _)) => break Err(e.into()),
181
182 Either::Right((None, _)) => break Ok(()),
184 }
185 }
186}