From c5e053f6adc70506f981cced9063b7332c9f9a5b Mon Sep 17 00:00:00 2001 From: legobt <6wbvkn0j@anonaddy.me> Date: Wed, 23 Aug 2023 11:39:14 +0000 Subject: [PATCH 1/3] types: Make Data type-parameter optional in JsonRpcError This is in order to provide backwards-compatibility with code implemented towards v5.0.0. --- jest.config.js | 4 ++-- src/classes.ts | 10 ++++++++-- src/utils.ts | 8 ++++++++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/jest.config.js b/jest.config.js index 0acc5bf..449ffd5 100644 --- a/jest.config.js +++ b/jest.config.js @@ -47,8 +47,8 @@ module.exports = { global: { branches: 94.31, functions: 94.11, - lines: 97.05, - statements: 97.05, + lines: 97.11, + statements: 97.11, }, }, diff --git a/src/classes.ts b/src/classes.ts index 76dd5b9..b32d47e 100644 --- a/src/classes.ts +++ b/src/classes.ts @@ -5,7 +5,11 @@ import { } from '@metamask/utils'; import safeStringify from 'fast-safe-stringify'; -import { DataWithOptionalCause, serializeCause } from './utils'; +import type { + DataWithOptionalCause, + OptionalDataWithOptionalCause, +} from './utils'; +import { serializeCause } from './utils'; export type { SerializedJsonRpcError }; @@ -15,7 +19,9 @@ export type { SerializedJsonRpcError }; * * Permits any integer error code. */ -export class JsonRpcError extends Error { +export class JsonRpcError< + T extends OptionalDataWithOptionalCause, +> extends Error { public code: number; public data?: T; diff --git a/src/utils.ts b/src/utils.ts index c6f28c7..ee05d52 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -27,6 +27,14 @@ export type DataWithOptionalCause = cause: unknown; }; +/** + * A data object, that must be either: + * + * - A valid DataWithOptionalCause value. + * - undefined. + */ +export type OptionalDataWithOptionalCause = undefined | DataWithOptionalCause; + const FALLBACK_ERROR_CODE = errorCodes.rpc.internal; const FALLBACK_MESSAGE = 'Unspecified error message. This is a bug, please report it.'; From df1102a03e78e10197137146499ce2a631e6c22c Mon Sep 17 00:00:00 2001 From: legobt <6wbvkn0j@anonaddy.me> Date: Wed, 23 Aug 2023 13:34:06 +0000 Subject: [PATCH 2/3] Expand use of OptionalDataWithOptionalCause --- jest.config.js | 4 +-- src/classes.ts | 7 ++--- src/errors.ts | 69 ++++++++++++++++++++++++++++---------------------- 3 files changed, 43 insertions(+), 37 deletions(-) diff --git a/jest.config.js b/jest.config.js index 449ffd5..07be02e 100644 --- a/jest.config.js +++ b/jest.config.js @@ -47,8 +47,8 @@ module.exports = { global: { branches: 94.31, functions: 94.11, - lines: 97.11, - statements: 97.11, + lines: 97.13, + statements: 97.13, }, }, diff --git a/src/classes.ts b/src/classes.ts index b32d47e..da7e4aa 100644 --- a/src/classes.ts +++ b/src/classes.ts @@ -5,10 +5,7 @@ import { } from '@metamask/utils'; import safeStringify from 'fast-safe-stringify'; -import type { - DataWithOptionalCause, - OptionalDataWithOptionalCause, -} from './utils'; +import type { OptionalDataWithOptionalCause } from './utils'; import { serializeCause } from './utils'; export type { SerializedJsonRpcError }; @@ -87,7 +84,7 @@ export class JsonRpcError< * Permits integer error codes in the [ 1000 <= 4999 ] range. */ export class EthereumProviderError< - T extends DataWithOptionalCause, + T extends OptionalDataWithOptionalCause, > extends JsonRpcError { /** * Create an Ethereum Provider JSON-RPC error. diff --git a/src/errors.ts b/src/errors.ts index d3fca95..9fb80e0 100644 --- a/src/errors.ts +++ b/src/errors.ts @@ -1,19 +1,20 @@ import { JsonRpcError, EthereumProviderError } from './classes'; import { errorCodes } from './error-constants'; -import { DataWithOptionalCause, getMessageFromCode } from './utils'; +import { OptionalDataWithOptionalCause, getMessageFromCode } from './utils'; -type EthereumErrorOptions = { +type EthereumErrorOptions = { message?: string; data?: T; }; -type ServerErrorOptions = { +type ServerErrorOptions = { code: number; } & EthereumErrorOptions; -type CustomErrorArg = ServerErrorOptions; +type CustomErrorArg = + ServerErrorOptions; -type JsonRpcErrorsArg = +type JsonRpcErrorsArg = | EthereumErrorOptions | string; @@ -24,7 +25,7 @@ export const rpcErrors = { * @param arg - The error message or options bag. * @returns An instance of the {@link JsonRpcError} class. */ - parse: (arg?: JsonRpcErrorsArg) => + parse: (arg?: JsonRpcErrorsArg) => getJsonRpcError(errorCodes.rpc.parse, arg), /** @@ -33,7 +34,7 @@ export const rpcErrors = { * @param arg - The error message or options bag. * @returns An instance of the {@link JsonRpcError} class. */ - invalidRequest: ( + invalidRequest: ( arg?: JsonRpcErrorsArg, ) => getJsonRpcError(errorCodes.rpc.invalidRequest, arg), @@ -43,8 +44,9 @@ export const rpcErrors = { * @param arg - The error message or options bag. * @returns An instance of the {@link JsonRpcError} class. */ - invalidParams: (arg?: JsonRpcErrorsArg) => - getJsonRpcError(errorCodes.rpc.invalidParams, arg), + invalidParams: ( + arg?: JsonRpcErrorsArg, + ) => getJsonRpcError(errorCodes.rpc.invalidParams, arg), /** * Get a JSON RPC 2.0 Method Not Found (-32601) error. @@ -52,7 +54,7 @@ export const rpcErrors = { * @param arg - The error message or options bag. * @returns An instance of the {@link JsonRpcError} class. */ - methodNotFound: ( + methodNotFound: ( arg?: JsonRpcErrorsArg, ) => getJsonRpcError(errorCodes.rpc.methodNotFound, arg), @@ -62,8 +64,9 @@ export const rpcErrors = { * @param arg - The error message or options bag. * @returns An instance of the {@link JsonRpcError} class. */ - internal: (arg?: JsonRpcErrorsArg) => - getJsonRpcError(errorCodes.rpc.internal, arg), + internal: ( + arg?: JsonRpcErrorsArg, + ) => getJsonRpcError(errorCodes.rpc.internal, arg), /** * Get a JSON RPC 2.0 Server error. @@ -73,7 +76,9 @@ export const rpcErrors = { * @param opts - The error options bag. * @returns An instance of the {@link JsonRpcError} class. */ - server: (opts: ServerErrorOptions) => { + server: ( + opts: ServerErrorOptions, + ) => { if (!opts || typeof opts !== 'object' || Array.isArray(opts)) { throw new Error( 'Ethereum RPC Server errors must provide single object argument.', @@ -94,8 +99,9 @@ export const rpcErrors = { * @param arg - The error message or options bag. * @returns An instance of the {@link JsonRpcError} class. */ - invalidInput: (arg?: JsonRpcErrorsArg) => - getJsonRpcError(errorCodes.rpc.invalidInput, arg), + invalidInput: ( + arg?: JsonRpcErrorsArg, + ) => getJsonRpcError(errorCodes.rpc.invalidInput, arg), /** * Get an Ethereum JSON RPC Resource Not Found (-32001) error. @@ -103,7 +109,7 @@ export const rpcErrors = { * @param arg - The error message or options bag. * @returns An instance of the {@link JsonRpcError} class. */ - resourceNotFound: ( + resourceNotFound: ( arg?: JsonRpcErrorsArg, ) => getJsonRpcError(errorCodes.rpc.resourceNotFound, arg), @@ -113,7 +119,7 @@ export const rpcErrors = { * @param arg - The error message or options bag. * @returns An instance of the {@link JsonRpcError} class. */ - resourceUnavailable: ( + resourceUnavailable: ( arg?: JsonRpcErrorsArg, ) => getJsonRpcError(errorCodes.rpc.resourceUnavailable, arg), @@ -123,7 +129,7 @@ export const rpcErrors = { * @param arg - The error message or options bag. * @returns An instance of the {@link JsonRpcError} class. */ - transactionRejected: ( + transactionRejected: ( arg?: JsonRpcErrorsArg, ) => getJsonRpcError(errorCodes.rpc.transactionRejected, arg), @@ -133,7 +139,7 @@ export const rpcErrors = { * @param arg - The error message or options bag. * @returns An instance of the {@link JsonRpcError} class. */ - methodNotSupported: ( + methodNotSupported: ( arg?: JsonRpcErrorsArg, ) => getJsonRpcError(errorCodes.rpc.methodNotSupported, arg), @@ -143,8 +149,9 @@ export const rpcErrors = { * @param arg - The error message or options bag. * @returns An instance of the {@link JsonRpcError} class. */ - limitExceeded: (arg?: JsonRpcErrorsArg) => - getJsonRpcError(errorCodes.rpc.limitExceeded, arg), + limitExceeded: ( + arg?: JsonRpcErrorsArg, + ) => getJsonRpcError(errorCodes.rpc.limitExceeded, arg), }; export const providerErrors = { @@ -154,7 +161,7 @@ export const providerErrors = { * @param arg - The error message or options bag. * @returns An instance of the {@link EthereumProviderError} class. */ - userRejectedRequest: ( + userRejectedRequest: ( arg?: JsonRpcErrorsArg, ) => { return getEthProviderError(errorCodes.provider.userRejectedRequest, arg); @@ -166,7 +173,7 @@ export const providerErrors = { * @param arg - The error message or options bag. * @returns An instance of the {@link EthereumProviderError} class. */ - unauthorized: ( + unauthorized: ( arg?: JsonRpcErrorsArg, ) => { return getEthProviderError(errorCodes.provider.unauthorized, arg); @@ -178,7 +185,7 @@ export const providerErrors = { * @param arg - The error message or options bag. * @returns An instance of the {@link EthereumProviderError} class. */ - unsupportedMethod: ( + unsupportedMethod: ( arg?: JsonRpcErrorsArg, ) => { return getEthProviderError(errorCodes.provider.unsupportedMethod, arg); @@ -190,7 +197,7 @@ export const providerErrors = { * @param arg - The error message or options bag. * @returns An instance of the {@link EthereumProviderError} class. */ - disconnected: ( + disconnected: ( arg?: JsonRpcErrorsArg, ) => { return getEthProviderError(errorCodes.provider.disconnected, arg); @@ -202,7 +209,7 @@ export const providerErrors = { * @param arg - The error message or options bag. * @returns An instance of the {@link EthereumProviderError} class. */ - chainDisconnected: ( + chainDisconnected: ( arg?: JsonRpcErrorsArg, ) => { return getEthProviderError(errorCodes.provider.chainDisconnected, arg); @@ -214,7 +221,9 @@ export const providerErrors = { * @param opts - The error options bag. * @returns An instance of the {@link EthereumProviderError} class. */ - custom: (opts: CustomErrorArg) => { + custom: ( + opts: CustomErrorArg, + ) => { if (!opts || typeof opts !== 'object' || Array.isArray(opts)) { throw new Error( 'Ethereum Provider custom errors must provide single object argument.', @@ -237,7 +246,7 @@ export const providerErrors = { * @param arg - The error message or options bag. * @returns An instance of the {@link JsonRpcError} class. */ -function getJsonRpcError( +function getJsonRpcError( code: number, arg?: JsonRpcErrorsArg, ): JsonRpcError { @@ -252,7 +261,7 @@ function getJsonRpcError( * @param arg - The error message or options bag. * @returns An instance of the {@link EthereumProviderError} class. */ -function getEthProviderError( +function getEthProviderError( code: number, arg?: JsonRpcErrorsArg, ): EthereumProviderError { @@ -270,7 +279,7 @@ function getEthProviderError( * @param arg - The error message or options bag. * @returns A tuple containing the error message and optional data. */ -function parseOpts( +function parseOpts( arg?: JsonRpcErrorsArg, ): [message?: string | undefined, data?: T | undefined] { if (arg) { From e94a4f3ef923586e73946f134d11f87025b724ea Mon Sep 17 00:00:00 2001 From: legobt <6wbvkn0j@anonaddy.me> Date: Thu, 24 Aug 2023 01:40:51 +0000 Subject: [PATCH 3/3] fix/types: make cause actually optional in DataWithOptionalCause --- src/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils.ts b/src/utils.ts index ee05d52..fb613a3 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -24,7 +24,7 @@ export type DataWithOptionalCause = // an object with an index signature must be assignable to the index // signature's type. So we have to use `Json | unknown` instead. [key: string]: Json | unknown; - cause: unknown; + cause?: unknown; }; /**