1use std::sync::Arc;
2
3use near_api_types::errors::DataConversionError;
4use near_openapi_client::types::{
5 FunctionCallError, InternalError, RpcQueryError, RpcRequestValidationErrorKind,
6 RpcTransactionError,
7};
8
9#[derive(thiserror::Error, Debug)]
10pub enum QueryCreationError {
11 #[error("Staking pool factory account ID is not defined in the network config")]
12 StakingPoolFactoryNotDefined,
13}
14
15#[derive(thiserror::Error, Debug)]
16pub enum QueryError<RpcError: std::fmt::Debug + Send + Sync> {
17 #[error(transparent)]
18 QueryCreationError(#[from] QueryCreationError),
19 #[error("Unexpected response kind: expected {expected} type, but got {got:?}")]
20 UnexpectedResponse {
21 expected: &'static str,
22 got: &'static str,
24 },
25 #[error("Failed to deserialize response: {0}")]
26 DeserializeError(#[from] serde_json::Error),
27 #[error("Query error: {0:?}")]
28 QueryError(Box<RetryError<SendRequestError<RpcError>>>),
29 #[error("Internal error: failed to get response. Please submit a bug ticket")]
30 InternalErrorNoResponse,
31 #[error("Argument serialization error: {0}")]
32 ArgumentValidationError(#[from] ArgumentValidationError),
33 #[error("Failed to convert response: {0}")]
34 ConversionError(Box<dyn std::error::Error + Send + Sync>),
35}
36
37impl<RpcError: std::fmt::Debug + Send + Sync> From<RetryError<SendRequestError<RpcError>>>
38 for QueryError<RpcError>
39{
40 fn from(err: RetryError<SendRequestError<RpcError>>) -> Self {
41 Self::QueryError(Box::new(err))
42 }
43}
44
45#[derive(thiserror::Error, Debug)]
46pub enum MetaSignError {
47 #[error("Attempted to construct NonDelegateAction from Action::Delegate")]
48 DelegateActionIsNotSupported,
49
50 #[error(transparent)]
51 SignerError(#[from] SignerError),
52}
53
54#[derive(thiserror::Error, Debug)]
55pub enum PublicKeyError {
56 #[error("Public key is not available")]
57 PublicKeyIsNotAvailable,
58 #[cfg(feature = "ledger")]
59 #[error("Failed to cache public key: {0}")]
60 SetPublicKeyError(#[from] tokio::sync::SetError<crate::PublicKey>),
61}
62
63#[derive(thiserror::Error, Debug)]
64pub enum SignerError {
65 #[error(transparent)]
66 PublicKeyError(#[from] PublicKeyError),
67 #[error("Secret key is not available")]
68 SecretKeyIsNotAvailable,
69 #[error("Failed to fetch nonce: {0:?}")]
70 FetchNonceError(Box<QueryError<RpcQueryError>>),
71 #[error("IO error: {0}")]
72 IO(#[from] std::io::Error),
73
74 #[cfg(feature = "ledger")]
75 #[error(transparent)]
76 LedgerError(#[from] LedgerError),
77}
78
79#[derive(thiserror::Error, Debug)]
80pub enum SecretError {
81 #[error("Failed to process seed phrase: {0}")]
82 BIP39Error(#[from] bip39::Error),
83 #[error("Failed to derive key from seed phrase: Invalid Index")]
84 DeriveKeyInvalidIndex,
85 #[error(transparent)]
86 PublicKeyError(#[from] PublicKeyError),
87}
88
89#[derive(thiserror::Error, Debug)]
90pub enum AccessKeyFileError {
91 #[error("Failed to read access key file: {0}")]
92 ReadError(#[from] std::io::Error),
93 #[error("Failed to parse access key file: {0}")]
94 ParseError(#[from] serde_json::Error),
95 #[error(transparent)]
96 SecretError(#[from] SecretError),
97 #[error("Public key is not linked to the private key")]
98 PrivatePublicKeyMismatch,
99 #[error(transparent)]
100 PublicKeyError(#[from] PublicKeyError),
101}
102
103#[cfg(feature = "keystore")]
104#[derive(thiserror::Error, Debug)]
105pub enum KeyStoreError {
106 #[error(transparent)]
107 Keystore(#[from] keyring::Error),
108 #[error("Failed to query account keys: {0:?}")]
109 QueryError(QueryError<RpcQueryError>),
110 #[error("Failed to parse access key file: {0}")]
111 ParseError(#[from] serde_json::Error),
112 #[error(transparent)]
113 SecretError(#[from] SecretError),
114 #[error("Task execution error: {0}")]
115 TaskExecutionError(#[from] tokio::task::JoinError),
116}
117
118#[cfg(feature = "ledger")]
119#[derive(thiserror::Error, Debug)]
120pub enum LedgerError {
121 #[error(
122 "Buffer overflow on Ledger device occurred. \
123Transaction is too large for signature. \
124This is resolved in https://github.com/dj8yfo/app-near-rs . \
125The status is tracked in `About` section."
126 )]
127 BufferOverflow,
128 #[error("Ledger device error: {0:?}")]
129 LedgerError(near_ledger::NEARLedgerError),
130 #[error("IO error: {0}")]
131 IO(#[from] std::io::Error),
132 #[error("Task execution error: {0}")]
133 TaskExecutionError(#[from] tokio::task::JoinError),
134 #[error("Signature is not expected to fail on deserialization: {0}")]
135 SignatureDeserializationError(String),
136}
137
138#[cfg(feature = "ledger")]
139impl From<near_ledger::NEARLedgerError> for LedgerError {
140 fn from(err: near_ledger::NEARLedgerError) -> Self {
141 const SW_BUFFER_OVERFLOW: &str = "0x6990";
142
143 match err {
144 near_ledger::NEARLedgerError::APDUExchangeError(msg)
145 if msg.contains(SW_BUFFER_OVERFLOW) =>
146 {
147 Self::BufferOverflow
148 }
149 near_ledger_error => Self::LedgerError(near_ledger_error),
150 }
151 }
152}
153
154#[derive(thiserror::Error, Debug, Clone)]
155pub enum ArgumentValidationError {
156 #[error("Failed to serialize arguments as JSON: {0}")]
157 JsonSerializationError(Arc<serde_json::Error>),
158 #[error("Failed to serialize arguments as Borsh: {0}")]
159 BorshSerializationError(Arc<std::io::Error>),
160 #[error("Account creation error: {0}")]
161 AccountCreationError(#[from] AccountCreationError),
162 #[error("Multiple errors: {0:?}")]
163 MultipleErrors(Vec<ArgumentValidationError>),
164}
165
166impl ArgumentValidationError {
167 pub const fn multiple(errors: Vec<Self>) -> Self {
168 Self::MultipleErrors(errors)
169 }
170}
171
172impl From<serde_json::Error> for ArgumentValidationError {
173 fn from(err: serde_json::Error) -> Self {
174 Self::JsonSerializationError(Arc::new(err))
175 }
176}
177
178impl From<std::io::Error> for ArgumentValidationError {
179 fn from(err: std::io::Error) -> Self {
180 Self::BorshSerializationError(Arc::new(err))
181 }
182}
183
184#[derive(thiserror::Error, Debug, Clone)]
185pub enum AccountCreationError {
186 #[error("Top-level account is not allowed")]
187 TopLevelAccountIsNotAllowed,
188
189 #[error("Linkdrop is not defined in the network config")]
190 LinkdropIsNotDefined,
191
192 #[error("Account should be created as a sub-account of the signer or linkdrop account")]
193 AccountShouldBeSubAccountOfSignerOrLinkdrop,
194}
195
196#[derive(thiserror::Error, Debug)]
197pub enum FaucetError {
198 #[error(
199 "The <{0}> network config does not have a defined faucet (helper service) that can sponsor the creation of an account."
200 )]
201 FaucetIsNotDefined(String),
202 #[error("Failed to send message: {0}")]
203 SendError(#[from] reqwest::Error),
204}
205
206#[derive(thiserror::Error, Debug)]
207pub enum RetryError<E> {
208 #[error("No RPC endpoints are defined in the network config")]
209 NoRpcEndpoints,
210 #[error("Invalid API key: {0}")]
211 InvalidApiKey(#[from] reqwest::header::InvalidHeaderValue),
212 #[error("Request failed. Retries exhausted. Last error: {0}")]
213 RetriesExhausted(E),
214 #[error("Critical error: {0}")]
215 Critical(E),
216}
217
218#[derive(thiserror::Error, Debug)]
219pub enum ExecuteTransactionError {
220 #[error(transparent)]
221 ArgumentValidationError(#[from] ArgumentValidationError),
222
223 #[error("Pre-query error: {0:?}")]
224 PreQueryError(QueryError<RpcQueryError>),
225 #[error("Transaction validation error: {0}")]
226 ValidationError(#[from] ValidationError),
227 #[error("Meta-signing error: {0}")]
228 MetaSignError(#[from] MetaSignError),
229 #[error("Transaction signing error: {0}")]
230 SignerError(#[from] SignerError),
231
232 #[error("Transaction error: {0:?}")]
233 TransactionError(RetryError<SendRequestError<RpcTransactionError>>),
234 #[error("Data conversion error: {0}")]
235 DataConversionError(#[from] DataConversionError),
236}
237
238#[derive(thiserror::Error, Debug)]
239pub enum ExecuteMetaTransactionsError {
240 #[error(transparent)]
241 ArgumentValidationError(#[from] ArgumentValidationError),
242
243 #[error("Pre-query error: {0:?}")]
244 PreQueryError(QueryError<RpcQueryError>),
245 #[error("Transaction validation error: {0}")]
246 ValidationError(#[from] ValidationError),
247 #[error("Relayer is not defined in the network config")]
248 RelayerIsNotDefined,
249
250 #[error("Meta-signing error: {0}")]
251 SignError(#[from] MetaSignError),
252
253 #[error("Failed to send meta-transaction: {0}")]
254 SendError(#[from] reqwest::Error),
255}
256
257#[derive(thiserror::Error, Debug)]
258pub enum FTValidatorError {
259 #[deprecated(
260 since = "0.7.3",
261 note = "this error is unused as we are not falling if no metadata provided"
262 )]
263 #[error("Metadata is not provided")]
264 NoMetadata,
265 #[error("Decimals mismatch: expected {expected}, got {got}")]
266 DecimalsMismatch { expected: u8, got: u8 },
267 #[error("Storage deposit is needed")]
268 StorageDepositNeeded,
269}
270
271#[derive(thiserror::Error, Debug)]
273pub enum ValidationError {
274 #[error("Query error: {0:?}")]
275 QueryError(QueryError<RpcQueryError>),
276
277 #[error(transparent)]
278 ArgumentValidationError(#[from] ArgumentValidationError),
279
280 #[error("FT Validation Error: {0}")]
281 FTValidatorError(#[from] FTValidatorError),
282
283 #[error("Account creation error: {0}")]
284 AccountCreationError(#[from] AccountCreationError),
285}
286
287#[derive(thiserror::Error, Debug)]
288pub enum SendRequestError<RpcError: std::fmt::Debug + Send + Sync> {
289 #[error("Query creation error: {0}")]
290 RequestCreationError(#[from] QueryCreationError),
291 #[error("Transport error: {0}")]
292 TransportError(near_openapi_client::Error<()>),
293 #[error("Wasm execution failed with error: {0}")]
295 WasmExecutionError(#[from] FunctionCallError),
296 #[error("Internal error: {0:?}")]
297 InternalError(#[from] InternalError),
298 #[error("Request validation error: {0:?}")]
299 RequestValidationError(#[from] RpcRequestValidationErrorKind),
300 #[error("Server error: {0}")]
301 ServerError(RpcError),
302}
303
304impl<RpcError: std::fmt::Debug + Send + Sync> From<near_openapi_client::Error<()>>
313 for SendRequestError<RpcError>
314{
315 fn from(err: near_openapi_client::Error<()>) -> Self {
316 if let near_openapi_client::Error::InvalidResponsePayload(bytes, _error) = &err {
317 let error = serde_json::from_slice::<serde_json::Value>(bytes)
318 .unwrap_or_default()
319 .get("result")
320 .and_then(|result| result.get("error"))
321 .and_then(|message| message.as_str())
322 .and_then(|message| message.strip_prefix("wasm execution failed with error: "))
323 .and_then(|message| serde_dbgfmt::from_str::<FunctionCallError>(message).ok());
324 if let Some(error) = error {
325 return Self::WasmExecutionError(error);
326 }
327 }
328
329 Self::TransportError(err)
330 }
331}