1#![allow(unreachable_patterns)]
3
4use base64::{prelude::BASE64_STANDARD, Engine};
5use near_api_types::NearToken;
6use near_openapi_client::types::{
7 RpcBlockError, RpcQueryError, RpcTransactionError, RpcValidatorError,
8};
9use reqwest::StatusCode;
10
11use crate::{config::RetryResponse, errors::SendRequestError};
12
13pub fn to_base64(input: &[u8]) -> String {
14 BASE64_STANDARD.encode(input)
15}
16
17pub fn from_base64(encoded: &str) -> Result<Vec<u8>, base64::DecodeError> {
18 BASE64_STANDARD.decode(encoded)
19}
20
21pub const fn near_data_to_near_token(data: near_api_types::Data<u128>) -> NearToken {
23 NearToken::from_yoctonear(data.data)
24}
25
26pub fn to_retry_error<T, E: std::fmt::Debug + Send + Sync>(
33 err: SendRequestError<E>,
34 is_critical_t: impl Fn(&SendRequestError<E>) -> bool,
35) -> RetryResponse<T, SendRequestError<E>> {
36 if is_critical_t(&err) {
37 RetryResponse::Critical(err)
38 } else {
39 RetryResponse::Retry(err)
40 }
41}
42
43pub fn is_critical_blocks_error(err: &SendRequestError<RpcBlockError>) -> bool {
44 is_critical_json_rpc_error(err, |err| match err {
45 RpcBlockError::UnknownBlock { .. }
46 | RpcBlockError::NotSyncedYet
47 | RpcBlockError::InternalError { .. } => false,
48 _ => false,
49 })
50}
51
52pub fn is_critical_validator_error(err: &SendRequestError<RpcValidatorError>) -> bool {
53 is_critical_json_rpc_error(err, |err| match err {
54 RpcValidatorError::UnknownEpoch
55 | RpcValidatorError::ValidatorInfoUnavailable
56 | RpcValidatorError::InternalError { .. } => false,
57 _ => false,
58 })
59}
60pub fn is_critical_query_error(err: &SendRequestError<RpcQueryError>) -> bool {
61 is_critical_json_rpc_error(err, |err| match err {
62 RpcQueryError::NoSyncedBlocks
63 | RpcQueryError::UnavailableShard { .. }
64 | RpcQueryError::UnknownBlock { .. }
65 | RpcQueryError::InternalError { .. } => false,
66
67 RpcQueryError::GarbageCollectedBlock { .. }
68 | RpcQueryError::InvalidAccount { .. }
69 | RpcQueryError::UnknownAccount { .. }
70 | RpcQueryError::NoContractCode { .. }
71 | RpcQueryError::TooLargeContractState { .. }
72 | RpcQueryError::UnknownAccessKey { .. }
73 | RpcQueryError::ContractExecutionError { .. }
74 | RpcQueryError::UnknownGasKey { .. } => true,
75
76 RpcQueryError::NoGlobalContractCode { .. } => false,
78 _ => false,
79 })
80}
81
82pub fn is_critical_transaction_error(err: &SendRequestError<RpcTransactionError>) -> bool {
83 is_critical_json_rpc_error(err, |err| match err {
84 RpcTransactionError::TimeoutError | RpcTransactionError::RequestRouted { .. } => false,
85 RpcTransactionError::InvalidTransaction { .. }
86 | RpcTransactionError::DoesNotTrackShard
87 | RpcTransactionError::UnknownTransaction { .. }
88 | RpcTransactionError::InternalError { .. } => true,
89 _ => false,
90 })
91}
92
93fn is_critical_json_rpc_error<RpcError: std::fmt::Debug + Send + Sync>(
94 err: &SendRequestError<RpcError>,
95 is_critical_t: impl Fn(&RpcError) -> bool,
96) -> bool {
97 match err {
98 SendRequestError::ServerError(rpc_error) => is_critical_t(rpc_error),
99 SendRequestError::WasmExecutionError(_) => true,
100 SendRequestError::InternalError { .. } => false,
101 SendRequestError::RequestValidationError(_) => true,
102 SendRequestError::RequestCreationError(_) => true,
103 SendRequestError::TransportError(error) => match error {
104 near_openapi_client::Error::InvalidRequest(_)
105 | near_openapi_client::Error::CommunicationError(_)
106 | near_openapi_client::Error::InvalidUpgrade(_)
107 | near_openapi_client::Error::ResponseBodyError(_)
108 | near_openapi_client::Error::InvalidResponsePayload(_, _)
109 | near_openapi_client::Error::UnexpectedResponse(_)
110 | near_openapi_client::Error::Custom(_) => true,
111
112 near_openapi_client::Error::ErrorResponse(response_value) => {
113 #[allow(clippy::match_like_matches_macro)]
115 match response_value.status() {
116 StatusCode::REQUEST_TIMEOUT
117 | StatusCode::TOO_MANY_REQUESTS
118 | StatusCode::INTERNAL_SERVER_ERROR
119 | StatusCode::BAD_GATEWAY
120 | StatusCode::SERVICE_UNAVAILABLE
121 | StatusCode::GATEWAY_TIMEOUT => false,
122 _ => true,
123 }
124 }
125 _ => false,
126 },
127 _ => false,
128 }
129}