1use std::time::Duration;
4
5use super::create_channel;
6use super::{CanRetry, TransportClient, TransportError, TransportRequest};
7use super::{CoreGrpcClient, PlatformGrpcClient};
8use crate::connection_pool::{ConnectionPool, PoolPrefix};
9use crate::{request_settings::AppliedRequestSettings, RequestSettings, Uri};
10use dapi_grpc::core::v0::{self as core_proto};
11use dapi_grpc::platform::v0::{self as platform_proto};
12use dapi_grpc::tonic::{IntoRequest, Streaming};
13use futures::{future::BoxFuture, FutureExt, TryFutureExt};
14
15impl TransportClient for PlatformGrpcClient {
16 fn with_uri(uri: Uri, pool: &ConnectionPool) -> Result<Self, TransportError> {
17 Ok(pool
18 .get_or_create(PoolPrefix::Platform, &uri, None, || {
19 match create_channel(uri.clone(), None) {
20 Ok(channel) => Ok(Self::new(channel).into()),
21 Err(e) => Err(dapi_grpc::tonic::Status::invalid_argument(format!(
22 "channel creation failed: {}",
23 e
24 ))),
25 }
26 })?
27 .into())
28 }
29
30 fn with_uri_and_settings(
31 uri: Uri,
32 settings: &AppliedRequestSettings,
33 pool: &ConnectionPool,
34 ) -> Result<Self, TransportError> {
35 Ok(pool
36 .get_or_create(
37 PoolPrefix::Platform,
38 &uri,
39 Some(settings),
40 || match create_channel(uri.clone(), Some(settings)) {
41 Ok(channel) => {
42 let mut client = Self::new(channel);
43 if let Some(max_size) = settings.max_decoding_message_size {
44 client = client.max_decoding_message_size(max_size);
45 }
46 Ok(client.into())
47 }
48 Err(e) => Err(dapi_grpc::tonic::Status::invalid_argument(format!(
49 "Channel creation failed: {}",
50 e
51 ))),
52 },
53 )?
54 .into())
55 }
56}
57
58impl TransportClient for CoreGrpcClient {
59 fn with_uri(uri: Uri, pool: &ConnectionPool) -> Result<Self, TransportError> {
60 Ok(pool
61 .get_or_create(PoolPrefix::Core, &uri, None, || {
62 match create_channel(uri.clone(), None) {
63 Ok(channel) => Ok(Self::new(channel).into()),
64 Err(e) => Err(dapi_grpc::tonic::Status::invalid_argument(format!(
65 "Channel creation failed: {}",
66 e
67 ))),
68 }
69 })?
70 .into())
71 }
72
73 fn with_uri_and_settings(
74 uri: Uri,
75 settings: &AppliedRequestSettings,
76 pool: &ConnectionPool,
77 ) -> Result<Self, TransportError> {
78 Ok(pool
79 .get_or_create(
80 PoolPrefix::Core,
81 &uri,
82 Some(settings),
83 || match create_channel(uri.clone(), Some(settings)) {
84 Ok(channel) => {
85 let mut client = Self::new(channel);
86 if let Some(max_size) = settings.max_decoding_message_size {
87 client = client.max_decoding_message_size(max_size);
88 }
89 Ok(client.into())
90 }
91 Err(e) => Err(dapi_grpc::tonic::Status::invalid_argument(format!(
92 "Channel creation failed: {}",
93 e
94 ))),
95 },
96 )?
97 .into())
98 }
99}
100
101impl CanRetry for dapi_grpc::tonic::Status {
102 fn can_retry(&self) -> bool {
103 let code = self.code();
104
105 use dapi_grpc::tonic::Code::*;
106
107 matches!(
108 code,
109 Ok | DataLoss
110 | Cancelled
111 | Unknown
112 | DeadlineExceeded
113 | ResourceExhausted
114 | Aborted
115 | Internal
116 | Unavailable
117 | Unimplemented
147 )
148 }
149
150 fn rate_limit_ban_duration(&self) -> Option<std::time::Duration> {
167 use crate::dapi_client::{MAX_RATE_LIMIT_BAN_SECS, MIN_RATE_LIMIT_BAN_SECS};
168 use dapi_grpc::tonic::Code;
169 if self.code() != Code::ResourceExhausted {
170 return None;
171 }
172 let secs = self
173 .metadata()
174 .get("ratelimit-reset")
175 .and_then(|v| v.to_str().ok())
176 .and_then(|s| s.trim().parse::<u64>().ok())
177 .filter(|&s| s > 0)?;
178 Some(std::time::Duration::from_secs(
179 secs.clamp(MIN_RATE_LIMIT_BAN_SECS, MAX_RATE_LIMIT_BAN_SECS),
180 ))
181 }
182}
183
184macro_rules! impl_transport_request_grpc {
217 ($request:ty, $response:ty, $client:ty, $settings:expr, $($method:tt)+) => {
218 impl TransportRequest for $request {
219 type Client = $client;
220
221 type Response = $response;
222
223 const SETTINGS_OVERRIDES: RequestSettings = $settings;
224
225 fn method_name(&self) -> &'static str {
226 stringify!($($method)+)
227 }
228
229 fn execute_transport<'c>(
230 self,
231 client: &'c mut Self::Client,
232 settings: &AppliedRequestSettings,
233 ) -> BoxFuture<'c, Result<Self::Response, TransportError>>
234 {
235 let mut grpc_request = self.into_request();
236
237 if !settings.timeout.is_zero() {
238 grpc_request.set_timeout(settings.timeout);
239 }
240
241 client
242 .$($method)+(grpc_request)
243 .map_err(TransportError::Grpc)
244 .map_ok(|response| response.into_inner())
245 .boxed()
246 }
247 }
248 };
249}
250
251const STREAMING_TIMEOUT: Duration = Duration::from_secs(5 * 60);
254
255impl_transport_request_grpc!(
256 platform_proto::GetIdentityRequest,
257 platform_proto::GetIdentityResponse,
258 PlatformGrpcClient,
259 RequestSettings::default(),
260 get_identity
261);
262
263impl_transport_request_grpc!(
264 platform_proto::GetDocumentsRequest,
265 platform_proto::GetDocumentsResponse,
266 PlatformGrpcClient,
267 RequestSettings::default(),
268 get_documents
269);
270
271impl_transport_request_grpc!(
272 platform_proto::GetDataContractRequest,
273 platform_proto::GetDataContractResponse,
274 PlatformGrpcClient,
275 RequestSettings::default(),
276 get_data_contract
277);
278
279impl_transport_request_grpc!(
280 platform_proto::GetConsensusParamsRequest,
281 platform_proto::GetConsensusParamsResponse,
282 PlatformGrpcClient,
283 RequestSettings::default(),
284 get_consensus_params
285);
286
287impl_transport_request_grpc!(
288 platform_proto::GetDataContractHistoryRequest,
289 platform_proto::GetDataContractHistoryResponse,
290 PlatformGrpcClient,
291 RequestSettings::default(),
292 get_data_contract_history
293);
294
295impl_transport_request_grpc!(
296 platform_proto::GetDocumentHistoryRequest,
297 platform_proto::GetDocumentHistoryResponse,
298 PlatformGrpcClient,
299 RequestSettings::default(),
300 get_document_history
301);
302
303impl_transport_request_grpc!(
304 platform_proto::BroadcastStateTransitionRequest,
305 platform_proto::BroadcastStateTransitionResponse,
306 PlatformGrpcClient,
307 RequestSettings::default(),
308 broadcast_state_transition
309);
310
311impl_transport_request_grpc!(
312 platform_proto::WaitForStateTransitionResultRequest,
313 platform_proto::WaitForStateTransitionResultResponse,
314 PlatformGrpcClient,
315 RequestSettings {
316 timeout: Some(Duration::from_secs(30)),
317 retries: Some(3),
318 ban_failed_address: None,
319 connect_timeout: None,
320 max_decoding_message_size: None,
321 },
322 wait_for_state_transition_result
323);
324
325impl_transport_request_grpc!(
326 platform_proto::GetIdentityByPublicKeyHashRequest,
327 platform_proto::GetIdentityByPublicKeyHashResponse,
328 PlatformGrpcClient,
329 RequestSettings::default(),
330 get_identity_by_public_key_hash
331);
332
333impl_transport_request_grpc!(
334 platform_proto::GetIdentityBalanceRequest,
335 platform_proto::GetIdentityBalanceResponse,
336 PlatformGrpcClient,
337 RequestSettings::default(),
338 get_identity_balance
339);
340
341impl_transport_request_grpc!(
342 platform_proto::GetIdentitiesBalancesRequest,
343 platform_proto::GetIdentitiesBalancesResponse,
344 PlatformGrpcClient,
345 RequestSettings::default(),
346 get_identities_balances
347);
348
349impl_transport_request_grpc!(
350 platform_proto::GetIdentityNonceRequest,
351 platform_proto::GetIdentityNonceResponse,
352 PlatformGrpcClient,
353 RequestSettings::default(),
354 get_identity_nonce
355);
356
357impl_transport_request_grpc!(
358 platform_proto::GetIdentityContractNonceRequest,
359 platform_proto::GetIdentityContractNonceResponse,
360 PlatformGrpcClient,
361 RequestSettings::default(),
362 get_identity_contract_nonce
363);
364
365impl_transport_request_grpc!(
366 platform_proto::GetIdentityBalanceAndRevisionRequest,
367 platform_proto::GetIdentityBalanceAndRevisionResponse,
368 PlatformGrpcClient,
369 RequestSettings::default(),
370 get_identity_balance_and_revision
371);
372
373impl_transport_request_grpc!(
374 platform_proto::GetIdentitiesContractKeysRequest,
375 platform_proto::GetIdentitiesContractKeysResponse,
376 PlatformGrpcClient,
377 RequestSettings::default(),
378 get_identities_contract_keys
379);
380
381impl_transport_request_grpc!(
382 platform_proto::GetIdentityKeysRequest,
383 platform_proto::GetIdentityKeysResponse,
384 PlatformGrpcClient,
385 RequestSettings::default(),
386 get_identity_keys
387);
388
389impl_transport_request_grpc!(
390 platform_proto::GetEpochsInfoRequest,
391 platform_proto::GetEpochsInfoResponse,
392 PlatformGrpcClient,
393 RequestSettings::default(),
394 get_epochs_info
395);
396
397impl_transport_request_grpc!(
398 platform_proto::GetFinalizedEpochInfosRequest,
399 platform_proto::GetFinalizedEpochInfosResponse,
400 PlatformGrpcClient,
401 RequestSettings::default(),
402 get_finalized_epoch_infos
403);
404
405impl_transport_request_grpc!(
406 platform_proto::GetProtocolVersionUpgradeStateRequest,
407 platform_proto::GetProtocolVersionUpgradeStateResponse,
408 PlatformGrpcClient,
409 RequestSettings::default(),
410 get_protocol_version_upgrade_state
411);
412
413impl_transport_request_grpc!(
414 platform_proto::GetProtocolVersionUpgradeVoteStatusRequest,
415 platform_proto::GetProtocolVersionUpgradeVoteStatusResponse,
416 PlatformGrpcClient,
417 RequestSettings::default(),
418 get_protocol_version_upgrade_vote_status
419);
420
421impl_transport_request_grpc!(
422 platform_proto::GetDataContractsRequest,
423 platform_proto::GetDataContractsResponse,
424 PlatformGrpcClient,
425 RequestSettings::default(),
426 get_data_contracts
427);
428
429impl_transport_request_grpc!(
431 platform_proto::GetContestedResourcesRequest,
432 platform_proto::GetContestedResourcesResponse,
433 PlatformGrpcClient,
434 RequestSettings::default(),
435 get_contested_resources
436);
437
438impl_transport_request_grpc!(
440 platform_proto::GetContestedResourceVoteStateRequest,
441 platform_proto::GetContestedResourceVoteStateResponse,
442 PlatformGrpcClient,
443 RequestSettings::default(),
444 get_contested_resource_vote_state
445);
446
447impl_transport_request_grpc!(
449 platform_proto::GetContestedResourceVotersForIdentityRequest,
450 platform_proto::GetContestedResourceVotersForIdentityResponse,
451 PlatformGrpcClient,
452 RequestSettings::default(),
453 get_contested_resource_voters_for_identity
454);
455impl_transport_request_grpc!(
457 platform_proto::GetContestedResourceIdentityVotesRequest,
458 platform_proto::GetContestedResourceIdentityVotesResponse,
459 PlatformGrpcClient,
460 RequestSettings::default(),
461 get_contested_resource_identity_votes
462);
463impl_transport_request_grpc!(
465 platform_proto::GetVotePollsByEndDateRequest,
466 platform_proto::GetVotePollsByEndDateResponse,
467 PlatformGrpcClient,
468 RequestSettings::default(),
469 get_vote_polls_by_end_date
470);
471
472impl_transport_request_grpc!(
474 platform_proto::GetEvonodesProposedEpochBlocksByIdsRequest,
475 platform_proto::GetEvonodesProposedEpochBlocksResponse,
476 PlatformGrpcClient,
477 RequestSettings::default(),
478 get_evonodes_proposed_epoch_blocks_by_ids
479);
480
481impl_transport_request_grpc!(
483 platform_proto::GetEvonodesProposedEpochBlocksByRangeRequest,
484 platform_proto::GetEvonodesProposedEpochBlocksResponse,
485 PlatformGrpcClient,
486 RequestSettings::default(),
487 get_evonodes_proposed_epoch_blocks_by_range
488);
489
490impl_transport_request_grpc!(
492 platform_proto::GetPrefundedSpecializedBalanceRequest,
493 platform_proto::GetPrefundedSpecializedBalanceResponse,
494 PlatformGrpcClient,
495 RequestSettings::default(),
496 get_prefunded_specialized_balance
497);
498
499impl_transport_request_grpc!(
501 platform_proto::GetPathElementsRequest,
502 platform_proto::GetPathElementsResponse,
503 PlatformGrpcClient,
504 RequestSettings::default(),
505 get_path_elements
506);
507
508impl_transport_request_grpc!(
510 platform_proto::GetTotalCreditsInPlatformRequest,
511 platform_proto::GetTotalCreditsInPlatformResponse,
512 PlatformGrpcClient,
513 RequestSettings::default(),
514 get_total_credits_in_platform
515);
516
517impl_transport_request_grpc!(
519 platform_proto::GetCurrentQuorumsInfoRequest,
520 platform_proto::GetCurrentQuorumsInfoResponse,
521 PlatformGrpcClient,
522 RequestSettings::default(),
523 get_current_quorums_info
524);
525
526impl_transport_request_grpc!(
528 platform_proto::GetShieldedEncryptedNotesRequest,
529 platform_proto::GetShieldedEncryptedNotesResponse,
530 PlatformGrpcClient,
531 RequestSettings::default(),
532 get_shielded_encrypted_notes
533);
534
535impl_transport_request_grpc!(
537 platform_proto::GetShieldedAnchorsRequest,
538 platform_proto::GetShieldedAnchorsResponse,
539 PlatformGrpcClient,
540 RequestSettings::default(),
541 get_shielded_anchors
542);
543
544impl_transport_request_grpc!(
546 platform_proto::GetMostRecentShieldedAnchorRequest,
547 platform_proto::GetMostRecentShieldedAnchorResponse,
548 PlatformGrpcClient,
549 RequestSettings::default(),
550 get_most_recent_shielded_anchor
551);
552
553impl_transport_request_grpc!(
555 platform_proto::GetShieldedPoolStateRequest,
556 platform_proto::GetShieldedPoolStateResponse,
557 PlatformGrpcClient,
558 RequestSettings::default(),
559 get_shielded_pool_state
560);
561
562impl_transport_request_grpc!(
564 platform_proto::GetShieldedNotesCountRequest,
565 platform_proto::GetShieldedNotesCountResponse,
566 PlatformGrpcClient,
567 RequestSettings::default(),
568 get_shielded_notes_count
569);
570
571impl_transport_request_grpc!(
573 platform_proto::GetShieldedNullifiersRequest,
574 platform_proto::GetShieldedNullifiersResponse,
575 PlatformGrpcClient,
576 RequestSettings::default(),
577 get_shielded_nullifiers
578);
579
580impl_transport_request_grpc!(
583 core_proto::GetTransactionRequest,
584 core_proto::GetTransactionResponse,
585 CoreGrpcClient,
586 RequestSettings::default(),
587 get_transaction
588);
589
590impl_transport_request_grpc!(
591 core_proto::GetBlockchainStatusRequest,
592 core_proto::GetBlockchainStatusResponse,
593 CoreGrpcClient,
594 RequestSettings::default(),
595 get_blockchain_status
596);
597
598impl_transport_request_grpc!(
599 core_proto::BroadcastTransactionRequest,
600 core_proto::BroadcastTransactionResponse,
601 CoreGrpcClient,
602 RequestSettings::default(),
603 broadcast_transaction
604);
605
606impl_transport_request_grpc!(
607 core_proto::TransactionsWithProofsRequest,
608 Streaming<core_proto::TransactionsWithProofsResponse>,
609 CoreGrpcClient,
610 RequestSettings {
611 timeout: Some(STREAMING_TIMEOUT),
612 ban_failed_address: None,
613 connect_timeout: None,
614 retries: None,
615 max_decoding_message_size: None,
616 },
617 subscribe_to_transactions_with_proofs
618);
619
620impl_transport_request_grpc!(
621 core_proto::MasternodeListRequest,
622 Streaming<core_proto::MasternodeListResponse>,
623 CoreGrpcClient,
624 RequestSettings {
625 timeout: Some(STREAMING_TIMEOUT),
626 ..RequestSettings::default()
627 },
628 subscribe_to_masternode_list
629);
630
631impl_transport_request_grpc!(
633 platform_proto::GetStatusRequest,
634 platform_proto::GetStatusResponse,
635 PlatformGrpcClient,
636 RequestSettings::default(),
637 get_status
638);
639
640impl_transport_request_grpc!(
642 platform_proto::GetIdentityByNonUniquePublicKeyHashRequest,
643 platform_proto::GetIdentityByNonUniquePublicKeyHashResponse,
644 PlatformGrpcClient,
645 RequestSettings::default(),
646 get_identity_by_non_unique_public_key_hash
647);
648
649impl_transport_request_grpc!(
651 platform_proto::GetIdentityTokenBalancesRequest,
652 platform_proto::GetIdentityTokenBalancesResponse,
653 PlatformGrpcClient,
654 RequestSettings::default(),
655 get_identity_token_balances
656);
657
658impl_transport_request_grpc!(
660 platform_proto::GetIdentitiesTokenBalancesRequest,
661 platform_proto::GetIdentitiesTokenBalancesResponse,
662 PlatformGrpcClient,
663 RequestSettings::default(),
664 get_identities_token_balances
665);
666
667impl_transport_request_grpc!(
669 platform_proto::GetIdentityTokenInfosRequest,
670 platform_proto::GetIdentityTokenInfosResponse,
671 PlatformGrpcClient,
672 RequestSettings::default(),
673 get_identity_token_infos
674);
675
676impl_transport_request_grpc!(
678 platform_proto::GetIdentitiesTokenInfosRequest,
679 platform_proto::GetIdentitiesTokenInfosResponse,
680 PlatformGrpcClient,
681 RequestSettings::default(),
682 get_identities_token_infos
683);
684
685impl_transport_request_grpc!(
687 platform_proto::GetTokenStatusesRequest,
688 platform_proto::GetTokenStatusesResponse,
689 PlatformGrpcClient,
690 RequestSettings::default(),
691 get_token_statuses
692);
693
694impl_transport_request_grpc!(
696 platform_proto::GetTokenPreProgrammedDistributionsRequest,
697 platform_proto::GetTokenPreProgrammedDistributionsResponse,
698 PlatformGrpcClient,
699 RequestSettings::default(),
700 get_token_pre_programmed_distributions
701);
702
703impl_transport_request_grpc!(
705 platform_proto::GetTokenTotalSupplyRequest,
706 platform_proto::GetTokenTotalSupplyResponse,
707 PlatformGrpcClient,
708 RequestSettings::default(),
709 get_token_total_supply
710);
711
712impl_transport_request_grpc!(
714 platform_proto::GetGroupInfoRequest,
715 platform_proto::GetGroupInfoResponse,
716 PlatformGrpcClient,
717 RequestSettings::default(),
718 get_group_info
719);
720
721impl_transport_request_grpc!(
723 platform_proto::GetGroupInfosRequest,
724 platform_proto::GetGroupInfosResponse,
725 PlatformGrpcClient,
726 RequestSettings::default(),
727 get_group_infos
728);
729
730impl_transport_request_grpc!(
732 platform_proto::GetGroupActionsRequest,
733 platform_proto::GetGroupActionsResponse,
734 PlatformGrpcClient,
735 RequestSettings::default(),
736 get_group_actions
737);
738
739impl_transport_request_grpc!(
741 platform_proto::GetGroupActionSignersRequest,
742 platform_proto::GetGroupActionSignersResponse,
743 PlatformGrpcClient,
744 RequestSettings::default(),
745 get_group_action_signers
746);
747
748impl_transport_request_grpc!(
750 platform_proto::GetTokenDirectPurchasePricesRequest,
751 platform_proto::GetTokenDirectPurchasePricesResponse,
752 PlatformGrpcClient,
753 RequestSettings::default(),
754 get_token_direct_purchase_prices
755);
756
757impl_transport_request_grpc!(
759 platform_proto::GetTokenContractInfoRequest,
760 platform_proto::GetTokenContractInfoResponse,
761 PlatformGrpcClient,
762 RequestSettings::default(),
763 get_token_contract_info
764);
765
766impl_transport_request_grpc!(
768 platform_proto::GetTokenPerpetualDistributionLastClaimRequest,
769 platform_proto::GetTokenPerpetualDistributionLastClaimResponse,
770 PlatformGrpcClient,
771 RequestSettings::default(),
772 get_token_perpetual_distribution_last_claim
773);
774
775impl_transport_request_grpc!(
777 platform_proto::GetAddressInfoRequest,
778 platform_proto::GetAddressInfoResponse,
779 PlatformGrpcClient,
780 RequestSettings::default(),
781 get_address_info
782);
783
784impl_transport_request_grpc!(
786 platform_proto::GetAddressesInfosRequest,
787 platform_proto::GetAddressesInfosResponse,
788 PlatformGrpcClient,
789 RequestSettings::default(),
790 get_addresses_infos
791);
792
793impl_transport_request_grpc!(
795 platform_proto::GetAddressesTrunkStateRequest,
796 platform_proto::GetAddressesTrunkStateResponse,
797 PlatformGrpcClient,
798 RequestSettings::default(),
799 get_addresses_trunk_state
800);
801
802impl_transport_request_grpc!(
804 platform_proto::GetAddressesBranchStateRequest,
805 platform_proto::GetAddressesBranchStateResponse,
806 PlatformGrpcClient,
807 RequestSettings::default(),
808 get_addresses_branch_state
809);
810
811impl_transport_request_grpc!(
813 platform_proto::GetRecentAddressBalanceChangesRequest,
814 platform_proto::GetRecentAddressBalanceChangesResponse,
815 PlatformGrpcClient,
816 RequestSettings::default(),
817 get_recent_address_balance_changes
818);
819
820impl_transport_request_grpc!(
822 platform_proto::GetRecentCompactedAddressBalanceChangesRequest,
823 platform_proto::GetRecentCompactedAddressBalanceChangesResponse,
824 PlatformGrpcClient,
825 RequestSettings {
826 max_decoding_message_size: Some(16 * 1024 * 1024),
829 ..RequestSettings::default()
830 },
831 get_recent_compacted_address_balance_changes
832);