Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/pretty-clubs-press.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@solana/errors': minor
---

Mark the `cause` deprecated for `SOLANA_ERROR__INSTRUCTION_PLANS__FAILED_TO_EXECUTE_TRANSACTION_PLAN` error
18 changes: 17 additions & 1 deletion packages/errors/src/__typetests__/error-typetest.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as SolanaErrorCodeModule from '../codes';
import { SolanaErrorCode, SolanaErrorCodeWithCause } from '../codes';
import { SolanaErrorContext } from '../context';
import { isSolanaError, SolanaError } from '../error';
import { isSolanaError, SolanaError, SolanaErrorWithDeprecatedCause } from '../error';

const { SOLANA_ERROR__TRANSACTION__FEE_PAYER_SIGNATURE_MISSING, SOLANA_ERROR__TRANSACTION__SIGNATURES_MISSING } =
SolanaErrorCodeModule;
Expand Down Expand Up @@ -66,3 +66,19 @@ null as unknown as SolanaErrorContext satisfies {
// Special errors have a nested `cause` property that is an optional `SolanaError`
const errorWithCause = null as unknown as SolanaError<SolanaErrorCodeWithCause>;
errorWithCause.cause satisfies SolanaError | undefined;

// Errors that have a deprecated `cause` property should satisfy `SolanaErrorWithDeprecatedCause`
// when narrowed with `isSolanaError`
{
const e = null as unknown;
if (isSolanaError(e)) {
// @ts-expect-error Not all SolanaErrors have deprecated cause
e satisfies SolanaErrorWithDeprecatedCause;
}
// This one does
if (isSolanaError(e, SolanaErrorCodeModule.SOLANA_ERROR__INSTRUCTION_PLANS__FAILED_TO_EXECUTE_TRANSACTION_PLAN)) {
e satisfies SolanaErrorWithDeprecatedCause;
// context still works
e.context.transactionPlanResult satisfies unknown;
Comment thread
mcintyre94 marked this conversation as resolved.
Dismissed
}
}
7 changes: 7 additions & 0 deletions packages/errors/src/codes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -624,3 +624,10 @@ export type SolanaErrorCode =
* `cause`.
*/
export type SolanaErrorCodeWithCause = typeof SOLANA_ERROR__JSON_RPC__SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE;

/**
* Errors of this type have a deprecated `cause` property. Consumers should use the error's
* `context` instead to access relevant error information.
*/
export type SolanaErrorCodeWithDeprecatedCause =
typeof SOLANA_ERROR__INSTRUCTION_PLANS__FAILED_TO_EXECUTE_TRANSACTION_PLAN;
27 changes: 26 additions & 1 deletion packages/errors/src/error.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,24 @@
import { SolanaErrorCode, SolanaErrorCodeWithCause } from './codes';
import { SolanaErrorCode, SolanaErrorCodeWithCause, SolanaErrorCodeWithDeprecatedCause } from './codes';
import { SolanaErrorContext } from './context';
import { getErrorMessage } from './message-formatter';

/**
* A variant of {@link SolanaError} where the `cause` property is deprecated.
*
* This type is returned by {@link isSolanaError} when checking for error codes in
* {@link SolanaErrorCodeWithDeprecatedCause}. Accessing `cause` on these errors will show
* a deprecation warning in IDEs that support JSDoc `@deprecated` tags.
*/
export interface SolanaErrorWithDeprecatedCause<
TErrorCode extends SolanaErrorCodeWithDeprecatedCause = SolanaErrorCodeWithDeprecatedCause,
> extends Omit<SolanaError<TErrorCode>, 'cause'> {
/**
* @deprecated The `cause` property is deprecated for this error code.
* Use the error's `context` property instead to access relevant error information.
*/
readonly cause?: unknown;
}

/**
* A type guard that returns `true` if the input is a {@link SolanaError}, optionally with a
* particular error code.
Expand Down Expand Up @@ -44,6 +61,14 @@ import { getErrorMessage } from './message-formatter';
* }
* ```
*/
export function isSolanaError<TErrorCode extends SolanaErrorCodeWithDeprecatedCause>(
e: unknown,
code: TErrorCode,
): e is SolanaErrorWithDeprecatedCause<TErrorCode>;
export function isSolanaError<TErrorCode extends SolanaErrorCode>(
e: unknown,
code?: TErrorCode,
): e is SolanaError<TErrorCode>;
export function isSolanaError<TErrorCode extends SolanaErrorCode>(
e: unknown,
/**
Expand Down
2 changes: 1 addition & 1 deletion packages/errors/src/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ export const SolanaErrorMessages: Readonly<{
[SOLANA_ERROR__INSTRUCTION_PLANS__NON_DIVISIBLE_TRANSACTION_PLANS_NOT_SUPPORTED]:
'This transaction plan executor does not support non-divisible sequential plans. To support them, you may create your own executor such that multi-transaction atomicity is preserved — e.g. by targetting RPCs that support transaction bundles.',
[SOLANA_ERROR__INSTRUCTION_PLANS__FAILED_TO_EXECUTE_TRANSACTION_PLAN]:
'The provided transaction plan failed to execute. See the `transactionPlanResult` attribute and the `cause` error for more details.',
'The provided transaction plan failed to execute. See the `transactionPlanResult` attribute for more details. Note that the `cause` property is deprecated, and a future version will not set it.',
[SOLANA_ERROR__INSTRUCTION_PLANS__MESSAGE_CANNOT_ACCOMMODATE_PLAN]:
'The provided message has insufficient capacity to accommodate the next instruction(s) in this plan. Expected at least $numBytesRequired free byte(s), got $numFreeBytes byte(s).',
[SOLANA_ERROR__INVARIANT_VIOLATION__INVALID_TRANSACTION_PLAN_KIND]: 'Invalid transaction plan kind: $kind.',
Expand Down
Loading