@solana/errors 8.6.0 → 8.7.0-canary-20261102161207

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,6 +10,7 @@ import {
10
10
  SOLANA_ERROR__JSON_RPC__SERVER_ERROR_BLOCK_STATUS_NOT_AVAILABLE_YET,
11
11
  SOLANA_ERROR__JSON_RPC__SERVER_ERROR_FILTER_TRANSACTION_NOT_FOUND,
12
12
  SOLANA_ERROR__JSON_RPC__SERVER_ERROR_KEY_EXCLUDED_FROM_SECONDARY_INDEX,
13
+ SOLANA_ERROR__JSON_RPC__SERVER_ERROR_LEADER_SCHEDULE_IDENTITY_NOT_FOUND,
13
14
  SOLANA_ERROR__JSON_RPC__SERVER_ERROR_LONG_TERM_STORAGE_SLOT_SKIPPED,
14
15
  SOLANA_ERROR__JSON_RPC__SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE,
15
16
  SOLANA_ERROR__JSON_RPC__SERVER_ERROR_SLOT_SKIPPED,
@@ -130,6 +131,7 @@ export function getSolanaErrorFromJsonRpcError(putativeErrorResponse: unknown):
130
131
  case SOLANA_ERROR__JSON_RPC__SERVER_ERROR_BLOCK_STATUS_NOT_AVAILABLE_YET:
131
132
  case SOLANA_ERROR__JSON_RPC__SERVER_ERROR_FILTER_TRANSACTION_NOT_FOUND:
132
133
  case SOLANA_ERROR__JSON_RPC__SERVER_ERROR_KEY_EXCLUDED_FROM_SECONDARY_INDEX:
134
+ case SOLANA_ERROR__JSON_RPC__SERVER_ERROR_LEADER_SCHEDULE_IDENTITY_NOT_FOUND:
133
135
  case SOLANA_ERROR__JSON_RPC__SERVER_ERROR_LONG_TERM_STORAGE_SLOT_SKIPPED:
134
136
  case SOLANA_ERROR__JSON_RPC__SERVER_ERROR_SLOT_SKIPPED:
135
137
  case SOLANA_ERROR__JSON_RPC__SERVER_ERROR_TRANSACTION_PRECOMPILE_VERIFICATION_FAILURE:
@@ -141,8 +143,13 @@ export function getSolanaErrorFromJsonRpcError(putativeErrorResponse: unknown):
141
143
  errorContext = { __serverMessage: message };
142
144
  break;
143
145
  default:
144
- if (typeof data === 'object' && !Array.isArray(data)) {
146
+ if (typeof data === 'object' && data !== null && !Array.isArray(data)) {
145
147
  errorContext = data;
148
+ } else {
149
+ // No structured data. Keep the server message so it's not lost; this
150
+ // matters most for codes that this version of the library doesn't know
151
+ // about (eg. one introduced by a newer RPC server).
152
+ errorContext = { __serverMessage: message };
146
153
  }
147
154
  }
148
155
  out = new SolanaError(code as SolanaErrorCode, errorContext as SolanaErrorContext[SolanaErrorCode]);
@@ -20,6 +20,15 @@ export function getHumanReadableErrorMessage<TErrorCode extends SolanaErrorCode>
20
20
  code: TErrorCode,
21
21
  context: object = {},
22
22
  ): string {
23
+ if (!(code in SolanaErrorMessages)) {
24
+ // A code that this version of the library has no message for, such as a JSON-RPC error
25
+ // code introduced by a newer RPC server. Report the code rather than throwing, along with
26
+ // the server's own message if one was captured.
27
+ return '__serverMessage' in context
28
+ ? // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
29
+ `Unknown Solana error code: ${code} (${context.__serverMessage})`
30
+ : `Unknown Solana error code: ${code}`;
31
+ }
23
32
  const messageFormatString = SolanaErrorMessages[code];
24
33
  if (messageFormatString.length === 0) {
25
34
  return '';
package/src/messages.ts CHANGED
@@ -168,6 +168,7 @@ import {
168
168
  SOLANA_ERROR__JSON_RPC__SERVER_ERROR_EPOCH_REWARDS_PERIOD_ACTIVE,
169
169
  SOLANA_ERROR__JSON_RPC__SERVER_ERROR_FILTER_TRANSACTION_NOT_FOUND,
170
170
  SOLANA_ERROR__JSON_RPC__SERVER_ERROR_KEY_EXCLUDED_FROM_SECONDARY_INDEX,
171
+ SOLANA_ERROR__JSON_RPC__SERVER_ERROR_LEADER_SCHEDULE_IDENTITY_NOT_FOUND,
171
172
  SOLANA_ERROR__JSON_RPC__SERVER_ERROR_LONG_TERM_STORAGE_SLOT_SKIPPED,
172
173
  SOLANA_ERROR__JSON_RPC__SERVER_ERROR_LONG_TERM_STORAGE_UNREACHABLE,
173
174
  SOLANA_ERROR__JSON_RPC__SERVER_ERROR_MIN_CONTEXT_SLOT_NOT_REACHED,
@@ -618,6 +619,7 @@ export const SolanaErrorMessages: Readonly<{
618
619
  'Epoch rewards period still active at slot $slot',
619
620
  [SOLANA_ERROR__JSON_RPC__SERVER_ERROR_FILTER_TRANSACTION_NOT_FOUND]: '$__serverMessage',
620
621
  [SOLANA_ERROR__JSON_RPC__SERVER_ERROR_KEY_EXCLUDED_FROM_SECONDARY_INDEX]: '$__serverMessage',
622
+ [SOLANA_ERROR__JSON_RPC__SERVER_ERROR_LEADER_SCHEDULE_IDENTITY_NOT_FOUND]: '$__serverMessage',
621
623
  [SOLANA_ERROR__JSON_RPC__SERVER_ERROR_LONG_TERM_STORAGE_SLOT_SKIPPED]: '$__serverMessage',
622
624
  [SOLANA_ERROR__JSON_RPC__SERVER_ERROR_LONG_TERM_STORAGE_UNREACHABLE]:
623
625
  'Failed to query long-term storage; please try again',
@@ -2,9 +2,55 @@ import {
2
2
  SOLANA_ERROR__JSON_RPC__SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE,
3
3
  SOLANA_ERROR__TRANSACTION__FAILED_WHEN_SIMULATING_TO_ESTIMATE_COMPUTE_LIMIT,
4
4
  SOLANA_ERROR__TRANSACTION__FAILED_WHEN_SIMULATING_TO_ESTIMATE_RESOURCE_LIMITS,
5
- SolanaErrorCode,
5
+ SolanaErrorCodeWithSimulationResult,
6
6
  } from './codes';
7
- import { isSolanaError } from './error';
7
+ import { isSolanaError, SolanaError } from './error';
8
+
9
+ // Typed as a record so that the compiler fails whenever this list and the
10
+ // `SolanaErrorCodeWithSimulationResult` union drift apart, in either direction.
11
+ const SIMULATION_ERROR_CODES: Readonly<Record<SolanaErrorCodeWithSimulationResult, true>> = {
12
+ [SOLANA_ERROR__JSON_RPC__SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE]: true,
13
+ [SOLANA_ERROR__TRANSACTION__FAILED_WHEN_SIMULATING_TO_ESTIMATE_COMPUTE_LIMIT]: true,
14
+ [SOLANA_ERROR__TRANSACTION__FAILED_WHEN_SIMULATING_TO_ESTIMATE_RESOURCE_LIMITS]: true,
15
+ };
16
+
17
+ /**
18
+ * A type guard that returns `true` if the input is a {@link SolanaError} thrown because a
19
+ * transaction simulation failed.
20
+ *
21
+ * When this returns `true`, TypeScript will refine the error's
22
+ * {@link SolanaError#context | `context`} to the simulation result (eg. `logs` and
23
+ * `unitsConsumed`). The underlying transaction error, if any, is available as the error's `cause`.
24
+ *
25
+ * The following error codes are considered simulation errors:
26
+ * - {@link SOLANA_ERROR__JSON_RPC__SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE}
27
+ * - {@link SOLANA_ERROR__TRANSACTION__FAILED_WHEN_SIMULATING_TO_ESTIMATE_COMPUTE_LIMIT}
28
+ * - {@link SOLANA_ERROR__TRANSACTION__FAILED_WHEN_SIMULATING_TO_ESTIMATE_RESOURCE_LIMITS}
29
+ *
30
+ * @param e - The value to check.
31
+ * @return `true` if the input is a simulation error, `false` otherwise.
32
+ *
33
+ * @example
34
+ * Reading the simulation logs of a failed transaction.
35
+ * ```ts
36
+ * import { isSimulationError } from '@solana/errors';
37
+ *
38
+ * try {
39
+ * await sendTransaction(signedTransaction);
40
+ * } catch (e) {
41
+ * if (isSimulationError(e)) {
42
+ * console.log('Simulation failed due to:', e.cause);
43
+ * console.log('Simulation logs:', e.context.logs);
44
+ * }
45
+ * throw e;
46
+ * }
47
+ * ```
48
+ *
49
+ * @see {@link unwrapSimulationError}
50
+ */
51
+ export function isSimulationError(e: unknown): e is SolanaError<SolanaErrorCodeWithSimulationResult> {
52
+ return isSolanaError(e) && e.context.__code in SIMULATION_ERROR_CODES;
53
+ }
8
54
 
9
55
  /**
10
56
  * Extracts the underlying cause from a simulation-related error.
@@ -16,10 +62,7 @@ import { isSolanaError } from './error';
16
62
  *
17
63
  * If the provided error is not a simulation-related error, it is returned unchanged.
18
64
  *
19
- * The following error codes are considered simulation errors:
20
- * - {@link SOLANA_ERROR__JSON_RPC__SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE}
21
- * - {@link SOLANA_ERROR__TRANSACTION__FAILED_WHEN_SIMULATING_TO_ESTIMATE_COMPUTE_LIMIT}
22
- * - {@link SOLANA_ERROR__TRANSACTION__FAILED_WHEN_SIMULATING_TO_ESTIMATE_RESOURCE_LIMITS}
65
+ * See {@link isSimulationError} for the list of error codes considered simulation errors.
23
66
  *
24
67
  * @param error - The error to unwrap.
25
68
  * @return The underlying cause if the error is a simulation error, otherwise the original error.
@@ -38,12 +81,7 @@ import { isSolanaError } from './error';
38
81
  * ```
39
82
  */
40
83
  export function unwrapSimulationError(error: unknown): unknown {
41
- const simulationCodes: SolanaErrorCode[] = [
42
- SOLANA_ERROR__JSON_RPC__SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE,
43
- SOLANA_ERROR__TRANSACTION__FAILED_WHEN_SIMULATING_TO_ESTIMATE_COMPUTE_LIMIT,
44
- SOLANA_ERROR__TRANSACTION__FAILED_WHEN_SIMULATING_TO_ESTIMATE_RESOURCE_LIMITS,
45
- ];
46
- if (isSolanaError(error) && !!error.cause && simulationCodes.includes(error.context.__code)) {
84
+ if (isSimulationError(error) && !!error.cause) {
47
85
  return error.cause;
48
86
  }
49
87
  return error;