1use crate::api::connection::DynRpcConnection;
10use crate::{model::*, notify::connection::ChannelConnection, RpcResult};
11use async_trait::async_trait;
12use downcast::{downcast_sync, AnySync};
13use kaspa_notify::{listener::ListenerId, scope::Scope, subscription::Command};
14use std::sync::Arc;
15
16pub const MAX_SAFE_WINDOW_SIZE: u32 = 10_000;
17
18#[async_trait]
24pub trait RpcApi: Sync + Send + AnySync {
25 async fn ping(&self) -> RpcResult<()> {
27 self.ping_call(None, PingRequest {}).await?;
28 Ok(())
29 }
30 async fn ping_call(&self, connection: Option<&DynRpcConnection>, request: PingRequest) -> RpcResult<PingResponse>;
31
32 async fn get_system_info(&self) -> RpcResult<GetSystemInfoResponse> {
35 Ok(self.get_system_info_call(None, GetSystemInfoRequest {}).await?)
36 }
37 async fn get_system_info_call(
38 &self,
39 connection: Option<&DynRpcConnection>,
40 request: GetSystemInfoRequest,
41 ) -> RpcResult<GetSystemInfoResponse>;
42
43 async fn get_connections(&self, include_profile_data: bool) -> RpcResult<GetConnectionsResponse> {
46 self.get_connections_call(None, GetConnectionsRequest { include_profile_data }).await
47 }
48 async fn get_connections_call(
49 &self,
50 connection: Option<&DynRpcConnection>,
51 request: GetConnectionsRequest,
52 ) -> RpcResult<GetConnectionsResponse>;
53
54 async fn get_metrics(
57 &self,
58 process_metrics: bool,
59 connection_metrics: bool,
60 bandwidth_metrics: bool,
61 consensus_metrics: bool,
62 storage_metrics: bool,
63 custom_metrics: bool,
64 ) -> RpcResult<GetMetricsResponse> {
65 self.get_metrics_call(
66 None,
67 GetMetricsRequest {
68 process_metrics,
69 connection_metrics,
70 bandwidth_metrics,
71 consensus_metrics,
72 storage_metrics,
73 custom_metrics,
74 },
75 )
76 .await
77 }
78 async fn get_metrics_call(
79 &self,
80 connection: Option<&DynRpcConnection>,
81 request: GetMetricsRequest,
82 ) -> RpcResult<GetMetricsResponse>;
83
84 async fn get_server_info(&self) -> RpcResult<GetServerInfoResponse> {
87 self.get_server_info_call(None, GetServerInfoRequest {}).await
88 }
89 async fn get_server_info_call(
90 &self,
91 connection: Option<&DynRpcConnection>,
92 request: GetServerInfoRequest,
93 ) -> RpcResult<GetServerInfoResponse>;
94
95 async fn get_sync_status(&self) -> RpcResult<bool> {
97 Ok(self.get_sync_status_call(None, GetSyncStatusRequest {}).await?.is_synced)
98 }
99 async fn get_sync_status_call(
100 &self,
101 connection: Option<&DynRpcConnection>,
102 request: GetSyncStatusRequest,
103 ) -> RpcResult<GetSyncStatusResponse>;
104
105 async fn get_current_network(&self) -> RpcResult<RpcNetworkType> {
109 Ok(self.get_current_network_call(None, GetCurrentNetworkRequest {}).await?.network)
110 }
111 async fn get_current_network_call(
112 &self,
113 connection: Option<&DynRpcConnection>,
114 request: GetCurrentNetworkRequest,
115 ) -> RpcResult<GetCurrentNetworkResponse>;
116
117 async fn submit_block(&self, block: RpcRawBlock, allow_non_daa_blocks: bool) -> RpcResult<SubmitBlockResponse> {
121 self.submit_block_call(None, SubmitBlockRequest::new(block, allow_non_daa_blocks)).await
122 }
123 async fn submit_block_call(
124 &self,
125 connection: Option<&DynRpcConnection>,
126 request: SubmitBlockRequest,
127 ) -> RpcResult<SubmitBlockResponse>;
128
129 async fn get_block_template(&self, pay_address: RpcAddress, extra_data: RpcExtraData) -> RpcResult<GetBlockTemplateResponse> {
133 self.get_block_template_call(None, GetBlockTemplateRequest::new(pay_address, extra_data)).await
134 }
135 async fn get_block_template_call(
136 &self,
137 connection: Option<&DynRpcConnection>,
138 request: GetBlockTemplateRequest,
139 ) -> RpcResult<GetBlockTemplateResponse>;
140
141 async fn get_peer_addresses(&self) -> RpcResult<GetPeerAddressesResponse> {
143 self.get_peer_addresses_call(None, GetPeerAddressesRequest {}).await
144 }
145 async fn get_peer_addresses_call(
146 &self,
147 connection: Option<&DynRpcConnection>,
148 request: GetPeerAddressesRequest,
149 ) -> RpcResult<GetPeerAddressesResponse>;
150
151 async fn get_sink(&self) -> RpcResult<GetSinkResponse> {
153 self.get_sink_call(None, GetSinkRequest {}).await
154 }
155 async fn get_sink_call(&self, connection: Option<&DynRpcConnection>, request: GetSinkRequest) -> RpcResult<GetSinkResponse>;
156
157 async fn get_mempool_entry(
159 &self,
160 transaction_id: RpcTransactionId,
161 include_orphan_pool: bool,
162 filter_transaction_pool: bool,
163 ) -> RpcResult<RpcMempoolEntry> {
164 Ok(self
165 .get_mempool_entry_call(None, GetMempoolEntryRequest::new(transaction_id, include_orphan_pool, filter_transaction_pool))
166 .await?
167 .mempool_entry)
168 }
169 async fn get_mempool_entry_call(
170 &self,
171 connection: Option<&DynRpcConnection>,
172 request: GetMempoolEntryRequest,
173 ) -> RpcResult<GetMempoolEntryResponse>;
174
175 async fn get_mempool_entries(&self, include_orphan_pool: bool, filter_transaction_pool: bool) -> RpcResult<Vec<RpcMempoolEntry>> {
177 Ok(self
178 .get_mempool_entries_call(None, GetMempoolEntriesRequest::new(include_orphan_pool, filter_transaction_pool))
179 .await?
180 .mempool_entries)
181 }
182 async fn get_mempool_entries_call(
183 &self,
184 connection: Option<&DynRpcConnection>,
185 request: GetMempoolEntriesRequest,
186 ) -> RpcResult<GetMempoolEntriesResponse>;
187
188 async fn get_connected_peer_info(&self) -> RpcResult<GetConnectedPeerInfoResponse> {
190 self.get_connected_peer_info_call(None, GetConnectedPeerInfoRequest {}).await
191 }
192 async fn get_connected_peer_info_call(
193 &self,
194 connection: Option<&DynRpcConnection>,
195 request: GetConnectedPeerInfoRequest,
196 ) -> RpcResult<GetConnectedPeerInfoResponse>;
197
198 async fn add_peer(&self, peer_address: RpcContextualPeerAddress, is_permanent: bool) -> RpcResult<()> {
202 self.add_peer_call(None, AddPeerRequest::new(peer_address, is_permanent)).await?;
203 Ok(())
204 }
205 async fn add_peer_call(&self, connection: Option<&DynRpcConnection>, request: AddPeerRequest) -> RpcResult<AddPeerResponse>;
206
207 async fn submit_transaction(&self, transaction: RpcTransaction, allow_orphan: bool) -> RpcResult<RpcTransactionId> {
209 Ok(self.submit_transaction_call(None, SubmitTransactionRequest { transaction, allow_orphan }).await?.transaction_id)
210 }
211 async fn submit_transaction_call(
212 &self,
213 connection: Option<&DynRpcConnection>,
214 request: SubmitTransactionRequest,
215 ) -> RpcResult<SubmitTransactionResponse>;
216
217 async fn submit_transaction_replacement(&self, transaction: RpcTransaction) -> RpcResult<SubmitTransactionReplacementResponse> {
221 self.submit_transaction_replacement_call(None, SubmitTransactionReplacementRequest { transaction }).await
222 }
223 async fn submit_transaction_replacement_call(
224 &self,
225 connection: Option<&DynRpcConnection>,
226 request: SubmitTransactionReplacementRequest,
227 ) -> RpcResult<SubmitTransactionReplacementResponse>;
228
229 async fn get_block(&self, hash: RpcHash, include_transactions: bool) -> RpcResult<RpcBlock> {
231 Ok(self.get_block_call(None, GetBlockRequest::new(hash, include_transactions)).await?.block)
232 }
233 async fn get_block_call(&self, connection: Option<&DynRpcConnection>, request: GetBlockRequest) -> RpcResult<GetBlockResponse>;
234
235 async fn get_subnetwork(&self, subnetwork_id: RpcSubnetworkId) -> RpcResult<GetSubnetworkResponse> {
237 self.get_subnetwork_call(None, GetSubnetworkRequest::new(subnetwork_id)).await
238 }
239 async fn get_subnetwork_call(
240 &self,
241 connection: Option<&DynRpcConnection>,
242 request: GetSubnetworkRequest,
243 ) -> RpcResult<GetSubnetworkResponse>;
244
245 async fn get_virtual_chain_from_block(
247 &self,
248 start_hash: RpcHash,
249 include_accepted_transaction_ids: bool,
250 ) -> RpcResult<GetVirtualChainFromBlockResponse> {
251 self.get_virtual_chain_from_block_call(
252 None,
253 GetVirtualChainFromBlockRequest::new(start_hash, include_accepted_transaction_ids),
254 )
255 .await
256 }
257 async fn get_virtual_chain_from_block_call(
258 &self,
259 connection: Option<&DynRpcConnection>,
260 request: GetVirtualChainFromBlockRequest,
261 ) -> RpcResult<GetVirtualChainFromBlockResponse>;
262
263 async fn get_blocks(
265 &self,
266 low_hash: Option<RpcHash>,
267 include_blocks: bool,
268 include_transactions: bool,
269 ) -> RpcResult<GetBlocksResponse> {
270 self.get_blocks_call(None, GetBlocksRequest::new(low_hash, include_blocks, include_transactions)).await
271 }
272 async fn get_blocks_call(&self, connection: Option<&DynRpcConnection>, request: GetBlocksRequest) -> RpcResult<GetBlocksResponse>;
273
274 async fn get_block_count(&self) -> RpcResult<GetBlockCountResponse> {
278 self.get_block_count_call(None, GetBlockCountRequest {}).await
279 }
280 async fn get_block_count_call(
281 &self,
282 connection: Option<&DynRpcConnection>,
283 request: GetBlockCountRequest,
284 ) -> RpcResult<GetBlockCountResponse>;
285
286 async fn get_block_dag_info(&self) -> RpcResult<GetBlockDagInfoResponse> {
288 self.get_block_dag_info_call(None, GetBlockDagInfoRequest {}).await
289 }
290 async fn get_block_dag_info_call(
291 &self,
292 connection: Option<&DynRpcConnection>,
293 request: GetBlockDagInfoRequest,
294 ) -> RpcResult<GetBlockDagInfoResponse>;
295
296 async fn resolve_finality_conflict(&self, finality_block_hash: RpcHash) -> RpcResult<()> {
298 self.resolve_finality_conflict_call(None, ResolveFinalityConflictRequest::new(finality_block_hash)).await?;
299 Ok(())
300 }
301 async fn resolve_finality_conflict_call(
302 &self,
303 connection: Option<&DynRpcConnection>,
304 request: ResolveFinalityConflictRequest,
305 ) -> RpcResult<ResolveFinalityConflictResponse>;
306
307 async fn shutdown(&self) -> RpcResult<()> {
309 self.shutdown_call(None, ShutdownRequest {}).await?;
310 Ok(())
311 }
312 async fn shutdown_call(&self, connection: Option<&DynRpcConnection>, request: ShutdownRequest) -> RpcResult<ShutdownResponse>;
313
314 async fn get_headers(&self, start_hash: RpcHash, limit: u64, is_ascending: bool) -> RpcResult<Vec<RpcHeader>> {
316 Ok(self.get_headers_call(None, GetHeadersRequest::new(start_hash, limit, is_ascending)).await?.headers)
317 }
318 async fn get_headers_call(
319 &self,
320 connection: Option<&DynRpcConnection>,
321 request: GetHeadersRequest,
322 ) -> RpcResult<GetHeadersResponse>;
323
324 async fn get_balance_by_address(&self, address: RpcAddress) -> RpcResult<u64> {
328 Ok(self.get_balance_by_address_call(None, GetBalanceByAddressRequest::new(address)).await?.balance)
329 }
330 async fn get_balance_by_address_call(
331 &self,
332 connection: Option<&DynRpcConnection>,
333 request: GetBalanceByAddressRequest,
334 ) -> RpcResult<GetBalanceByAddressResponse>;
335
336 async fn get_balances_by_addresses(&self, addresses: Vec<RpcAddress>) -> RpcResult<Vec<RpcBalancesByAddressesEntry>> {
338 Ok(self.get_balances_by_addresses_call(None, GetBalancesByAddressesRequest::new(addresses)).await?.entries)
339 }
340 async fn get_balances_by_addresses_call(
341 &self,
342 connection: Option<&DynRpcConnection>,
343 request: GetBalancesByAddressesRequest,
344 ) -> RpcResult<GetBalancesByAddressesResponse>;
345
346 async fn get_utxos_by_addresses(&self, addresses: Vec<RpcAddress>) -> RpcResult<Vec<RpcUtxosByAddressesEntry>> {
350 Ok(self.get_utxos_by_addresses_call(None, GetUtxosByAddressesRequest::new(addresses)).await?.entries)
351 }
352 async fn get_utxos_by_addresses_call(
353 &self,
354 connection: Option<&DynRpcConnection>,
355 request: GetUtxosByAddressesRequest,
356 ) -> RpcResult<GetUtxosByAddressesResponse>;
357
358 async fn get_sink_blue_score(&self) -> RpcResult<u64> {
360 Ok(self.get_sink_blue_score_call(None, GetSinkBlueScoreRequest {}).await?.blue_score)
361 }
362 async fn get_sink_blue_score_call(
363 &self,
364 connection: Option<&DynRpcConnection>,
365 request: GetSinkBlueScoreRequest,
366 ) -> RpcResult<GetSinkBlueScoreResponse>;
367
368 async fn ban(&self, ip: RpcIpAddress) -> RpcResult<()> {
370 self.ban_call(None, BanRequest::new(ip)).await?;
371 Ok(())
372 }
373 async fn ban_call(&self, connection: Option<&DynRpcConnection>, request: BanRequest) -> RpcResult<BanResponse>;
374
375 async fn unban(&self, ip: RpcIpAddress) -> RpcResult<()> {
377 self.unban_call(None, UnbanRequest::new(ip)).await?;
378 Ok(())
379 }
380 async fn unban_call(&self, connection: Option<&DynRpcConnection>, request: UnbanRequest) -> RpcResult<UnbanResponse>;
381
382 async fn get_info(&self) -> RpcResult<GetInfoResponse> {
384 self.get_info_call(None, GetInfoRequest {}).await
385 }
386 async fn get_info_call(&self, connection: Option<&DynRpcConnection>, request: GetInfoRequest) -> RpcResult<GetInfoResponse>;
387
388 async fn estimate_network_hashes_per_second(&self, window_size: u32, start_hash: Option<RpcHash>) -> RpcResult<u64> {
390 Ok(self
391 .estimate_network_hashes_per_second_call(None, EstimateNetworkHashesPerSecondRequest::new(window_size, start_hash))
392 .await?
393 .network_hashes_per_second)
394 }
395 async fn estimate_network_hashes_per_second_call(
396 &self,
397 connection: Option<&DynRpcConnection>,
398 request: EstimateNetworkHashesPerSecondRequest,
399 ) -> RpcResult<EstimateNetworkHashesPerSecondResponse>;
400
401 async fn get_mempool_entries_by_addresses(
403 &self,
404 addresses: Vec<RpcAddress>,
405 include_orphan_pool: bool,
406 filter_transaction_pool: bool,
407 ) -> RpcResult<Vec<RpcMempoolEntryByAddress>> {
408 Ok(self
409 .get_mempool_entries_by_addresses_call(
410 None,
411 GetMempoolEntriesByAddressesRequest::new(addresses, include_orphan_pool, filter_transaction_pool),
412 )
413 .await?
414 .entries)
415 }
416 async fn get_mempool_entries_by_addresses_call(
417 &self,
418 connection: Option<&DynRpcConnection>,
419 request: GetMempoolEntriesByAddressesRequest,
420 ) -> RpcResult<GetMempoolEntriesByAddressesResponse>;
421
422 async fn get_coin_supply(&self) -> RpcResult<GetCoinSupplyResponse> {
424 self.get_coin_supply_call(None, GetCoinSupplyRequest {}).await
425 }
426 async fn get_coin_supply_call(
427 &self,
428 connection: Option<&DynRpcConnection>,
429 request: GetCoinSupplyRequest,
430 ) -> RpcResult<GetCoinSupplyResponse>;
431
432 async fn get_daa_score_timestamp_estimate(&self, daa_scores: Vec<u64>) -> RpcResult<Vec<u64>> {
433 Ok(self.get_daa_score_timestamp_estimate_call(None, GetDaaScoreTimestampEstimateRequest { daa_scores }).await?.timestamps)
434 }
435 async fn get_daa_score_timestamp_estimate_call(
436 &self,
437 connection: Option<&DynRpcConnection>,
438 request: GetDaaScoreTimestampEstimateRequest,
439 ) -> RpcResult<GetDaaScoreTimestampEstimateResponse>;
440
441 async fn get_fee_estimate(&self) -> RpcResult<RpcFeeEstimate> {
445 Ok(self.get_fee_estimate_call(None, GetFeeEstimateRequest {}).await?.estimate)
446 }
447 async fn get_fee_estimate_call(
448 &self,
449 connection: Option<&DynRpcConnection>,
450 request: GetFeeEstimateRequest,
451 ) -> RpcResult<GetFeeEstimateResponse>;
452
453 async fn get_fee_estimate_experimental(&self, verbose: bool) -> RpcResult<GetFeeEstimateExperimentalResponse> {
454 self.get_fee_estimate_experimental_call(None, GetFeeEstimateExperimentalRequest { verbose }).await
455 }
456 async fn get_fee_estimate_experimental_call(
457 &self,
458 connection: Option<&DynRpcConnection>,
459 request: GetFeeEstimateExperimentalRequest,
460 ) -> RpcResult<GetFeeEstimateExperimentalResponse>;
461
462 async fn get_current_block_color(&self, hash: RpcHash) -> RpcResult<GetCurrentBlockColorResponse> {
464 Ok(self.get_current_block_color_call(None, GetCurrentBlockColorRequest { hash }).await?)
465 }
466 async fn get_current_block_color_call(
467 &self,
468 connection: Option<&DynRpcConnection>,
469 request: GetCurrentBlockColorRequest,
470 ) -> RpcResult<GetCurrentBlockColorResponse>;
471
472 fn register_new_listener(&self, connection: ChannelConnection) -> ListenerId;
477
478 async fn unregister_listener(&self, id: ListenerId) -> RpcResult<()>;
482
483 async fn start_notify(&self, id: ListenerId, scope: Scope) -> RpcResult<()>;
485
486 async fn stop_notify(&self, id: ListenerId, scope: Scope) -> RpcResult<()>;
488
489 async fn execute_subscribe_command(&self, id: ListenerId, scope: Scope, command: Command) -> RpcResult<()> {
492 match command {
493 Command::Start => self.start_notify(id, scope).await,
494 Command::Stop => self.stop_notify(id, scope).await,
495 }
496 }
497}
498
499pub type DynRpcService = Arc<dyn RpcApi>;
500
501downcast_sync!(dyn RpcApi);