@metamask/network-controller 22.2.0 → 23.0.0

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.
Files changed (70) hide show
  1. package/CHANGELOG.md +68 -1
  2. package/dist/NetworkController.cjs +63 -30
  3. package/dist/NetworkController.cjs.map +1 -1
  4. package/dist/NetworkController.d.cts +89 -5
  5. package/dist/NetworkController.d.cts.map +1 -1
  6. package/dist/NetworkController.d.mts +89 -5
  7. package/dist/NetworkController.d.mts.map +1 -1
  8. package/dist/NetworkController.mjs +63 -30
  9. package/dist/NetworkController.mjs.map +1 -1
  10. package/dist/create-auto-managed-network-client.cjs +26 -6
  11. package/dist/create-auto-managed-network-client.cjs.map +1 -1
  12. package/dist/create-auto-managed-network-client.d.cts +12 -2
  13. package/dist/create-auto-managed-network-client.d.cts.map +1 -1
  14. package/dist/create-auto-managed-network-client.d.mts +12 -2
  15. package/dist/create-auto-managed-network-client.d.mts.map +1 -1
  16. package/dist/create-auto-managed-network-client.mjs +26 -6
  17. package/dist/create-auto-managed-network-client.mjs.map +1 -1
  18. package/dist/create-network-client.cjs +56 -17
  19. package/dist/create-network-client.cjs.map +1 -1
  20. package/dist/create-network-client.d.cts +13 -2
  21. package/dist/create-network-client.d.cts.map +1 -1
  22. package/dist/create-network-client.d.mts +13 -2
  23. package/dist/create-network-client.d.mts.map +1 -1
  24. package/dist/create-network-client.mjs +56 -17
  25. package/dist/create-network-client.mjs.map +1 -1
  26. package/dist/index.cjs +3 -1
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.d.cts +3 -1
  29. package/dist/index.d.cts.map +1 -1
  30. package/dist/index.d.mts +3 -1
  31. package/dist/index.d.mts.map +1 -1
  32. package/dist/index.mjs +1 -0
  33. package/dist/index.mjs.map +1 -1
  34. package/dist/rpc-service/abstract-rpc-service.cjs.map +1 -1
  35. package/dist/rpc-service/abstract-rpc-service.d.cts +5 -39
  36. package/dist/rpc-service/abstract-rpc-service.d.cts.map +1 -1
  37. package/dist/rpc-service/abstract-rpc-service.d.mts +5 -39
  38. package/dist/rpc-service/abstract-rpc-service.d.mts.map +1 -1
  39. package/dist/rpc-service/abstract-rpc-service.mjs.map +1 -1
  40. package/dist/rpc-service/rpc-service-chain.cjs +10 -23
  41. package/dist/rpc-service/rpc-service-chain.cjs.map +1 -1
  42. package/dist/rpc-service/rpc-service-chain.d.cts +10 -35
  43. package/dist/rpc-service/rpc-service-chain.d.cts.map +1 -1
  44. package/dist/rpc-service/rpc-service-chain.d.mts +10 -35
  45. package/dist/rpc-service/rpc-service-chain.d.mts.map +1 -1
  46. package/dist/rpc-service/rpc-service-chain.mjs +10 -23
  47. package/dist/rpc-service/rpc-service-chain.mjs.map +1 -1
  48. package/dist/rpc-service/rpc-service-requestable.cjs +3 -0
  49. package/dist/rpc-service/rpc-service-requestable.cjs.map +1 -0
  50. package/dist/rpc-service/rpc-service-requestable.d.cts +47 -0
  51. package/dist/rpc-service/rpc-service-requestable.d.cts.map +1 -0
  52. package/dist/rpc-service/rpc-service-requestable.d.mts +47 -0
  53. package/dist/rpc-service/rpc-service-requestable.d.mts.map +1 -0
  54. package/dist/rpc-service/rpc-service-requestable.mjs +2 -0
  55. package/dist/rpc-service/rpc-service-requestable.mjs.map +1 -0
  56. package/dist/rpc-service/rpc-service.cjs +108 -47
  57. package/dist/rpc-service/rpc-service.cjs.map +1 -1
  58. package/dist/rpc-service/rpc-service.d.cts +63 -27
  59. package/dist/rpc-service/rpc-service.d.cts.map +1 -1
  60. package/dist/rpc-service/rpc-service.d.mts +63 -27
  61. package/dist/rpc-service/rpc-service.d.mts.map +1 -1
  62. package/dist/rpc-service/rpc-service.mjs +106 -45
  63. package/dist/rpc-service/rpc-service.mjs.map +1 -1
  64. package/dist/types.cjs.map +1 -1
  65. package/dist/types.d.cts +11 -6
  66. package/dist/types.d.cts.map +1 -1
  67. package/dist/types.d.mts +11 -6
  68. package/dist/types.d.mts.map +1 -1
  69. package/dist/types.mjs.map +1 -1
  70. package/package.json +8 -6
@@ -1 +1 @@
1
- {"version":3,"file":"rpc-service.cjs","sourceRoot":"","sources":["../../src/rpc-service/rpc-service.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ServicePolicy } from '@metamask/controller-utils';\nimport {\n CircuitState,\n createServicePolicy,\n handleWhen,\n} from '@metamask/controller-utils';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport type { JsonRpcRequest } from '@metamask/utils';\nimport {\n hasProperty,\n type Json,\n type JsonRpcParams,\n type JsonRpcResponse,\n} from '@metamask/utils';\nimport deepmerge from 'deepmerge';\n\nimport type { AbstractRpcService } from './abstract-rpc-service';\nimport type { AddToCockatielEventData, FetchOptions } from './shared';\n\n/**\n * The list of error messages that represent a failure to reach the network.\n *\n * This list was derived from Sindre Sorhus's `is-network-error` package:\n * <https://github.com/sindresorhus/is-network-error/blob/7bbfa8be9482ce1427a21fbff60e3ee1650dd091/index.js>\n */\nexport const NETWORK_UNREACHABLE_ERRORS = new Set([\n 'network error', // Chrome\n 'Failed to fetch', // Chrome\n 'NetworkError when attempting to fetch resource.', // Firefox\n 'The Internet connection appears to be offline.', // Safari 16\n 'Load failed', // Safari 17+\n 'Network request failed', // `cross-fetch`\n 'fetch failed', // Undici (Node.js)\n 'terminated', // Undici (Node.js)\n]);\n\n/**\n * Determines whether the given error represents a failure to reach the network\n * after request parameters have been validated.\n *\n * This is somewhat difficult to verify because JavaScript engines (and in\n * some cases libraries) produce slightly different error messages for this\n * particular scenario, and we need to account for this.\n *\n * @param error - The error.\n * @returns True if the error indicates that the network is unreachable, and\n * false otherwise.\n */\nexport default function isNetworkUnreachableError(error: unknown) {\n return (\n error instanceof TypeError && NETWORK_UNREACHABLE_ERRORS.has(error.message)\n );\n}\n\n/**\n * Guarantees a URL, even given a string. This is useful for checking components\n * of that URL.\n *\n * @param endpointUrlOrUrlString - Either a URL object or a string that\n * represents the URL of an endpoint.\n * @returns A URL object.\n */\nfunction getNormalizedEndpointUrl(endpointUrlOrUrlString: URL | string): URL {\n return endpointUrlOrUrlString instanceof URL\n ? endpointUrlOrUrlString\n : new URL(endpointUrlOrUrlString);\n}\n\n/**\n * This class is responsible for making a request to an endpoint that implements\n * the JSON-RPC protocol. It is designed to gracefully handle network and server\n * failures, retrying requests using exponential backoff. It also offers a hook\n * which can used to respond to slow requests.\n */\nexport class RpcService implements AbstractRpcService {\n /**\n * The function used to make an HTTP request.\n */\n readonly #fetch: typeof fetch;\n\n /**\n * The URL of the RPC endpoint.\n */\n readonly #endpointUrl: URL;\n\n /**\n * A common set of options that the request options will extend.\n */\n readonly #fetchOptions: FetchOptions;\n\n /**\n * An RPC service that represents a failover endpoint which will be invoked\n * while the circuit for _this_ service is open.\n */\n readonly #failoverService: AbstractRpcService | undefined;\n\n /**\n * The policy that wraps the request.\n */\n readonly #policy: ServicePolicy;\n\n /**\n * Constructs a new RpcService object.\n *\n * @param args - The arguments.\n * @param args.fetch - A function that can be used to make an HTTP request.\n * If your JavaScript environment supports `fetch` natively, you'll probably\n * want to pass that; otherwise you can pass an equivalent (such as `fetch`\n * via `node-fetch`).\n * @param args.btoa - A function that can be used to convert a binary string\n * into base-64. Used to encode authorization credentials.\n * @param args.endpointUrl - The URL of the RPC endpoint.\n * @param args.fetchOptions - A common set of options that will be used to\n * make every request. Can be overridden on the request level (e.g. to add\n * headers).\n * @param args.failoverService - An RPC service that represents a failover\n * endpoint which will be invoked while the circuit for _this_ service is\n * open.\n */\n constructor({\n fetch: givenFetch,\n btoa: givenBtoa,\n endpointUrl,\n fetchOptions = {},\n failoverService,\n }: {\n fetch: typeof fetch;\n btoa: typeof btoa;\n endpointUrl: URL | string;\n fetchOptions?: FetchOptions;\n failoverService?: AbstractRpcService;\n }) {\n this.#fetch = givenFetch;\n this.#endpointUrl = getNormalizedEndpointUrl(endpointUrl);\n this.#fetchOptions = this.#getDefaultFetchOptions(\n this.#endpointUrl,\n fetchOptions,\n givenBtoa,\n );\n this.#failoverService = failoverService;\n\n const policy = createServicePolicy({\n maxRetries: 4,\n maxConsecutiveFailures: 15,\n retryFilterPolicy: handleWhen((error) => {\n return (\n // Ignore errors where the request failed to establish\n isNetworkUnreachableError(error) ||\n // Ignore server sent HTML error pages or truncated JSON responses\n error.message.includes('not valid JSON') ||\n // Ignore server overload errors\n error.message.includes('Gateway timeout') ||\n (hasProperty(error, 'code') &&\n (error.code === 'ETIMEDOUT' || error.code === 'ECONNRESET'))\n );\n }),\n });\n this.#policy = policy;\n }\n\n /**\n * Listens for when the RPC service retries the request.\n *\n * @param listener - The callback to be called when the retry occurs.\n * @returns What {@link ServicePolicy.onRetry} returns.\n * @see {@link createServicePolicy}\n */\n onRetry(\n listener: AddToCockatielEventData<\n Parameters<ServicePolicy['onRetry']>[0],\n { endpointUrl: string }\n >,\n ) {\n return this.#policy.onRetry((data) => {\n listener({ ...data, endpointUrl: this.#endpointUrl.toString() });\n });\n }\n\n /**\n * Listens for when the RPC service retries the request too many times in a\n * row.\n *\n * @param listener - The callback to be called when the circuit is broken.\n * @returns What {@link ServicePolicy.onBreak} returns.\n * @see {@link createServicePolicy}\n */\n onBreak(\n listener: AddToCockatielEventData<\n Parameters<ServicePolicy['onBreak']>[0],\n { endpointUrl: string }\n >,\n ) {\n return this.#policy.onBreak((data) => {\n listener({ ...data, endpointUrl: this.#endpointUrl.toString() });\n });\n }\n\n /**\n * Listens for when the policy underlying this RPC service detects a slow\n * request.\n *\n * @param listener - The callback to be called when the request is slow.\n * @returns What {@link ServicePolicy.onDegraded} returns.\n * @see {@link createServicePolicy}\n */\n onDegraded(\n listener: AddToCockatielEventData<\n Parameters<ServicePolicy['onDegraded']>[0],\n { endpointUrl: string }\n >,\n ) {\n return this.#policy.onDegraded(() => {\n listener({ endpointUrl: this.#endpointUrl.toString() });\n });\n }\n\n /**\n * Makes a request to the RPC endpoint. If the circuit is open because this\n * request has failed too many times, the request is forwarded to a failover\n * service (if provided).\n *\n * This overload is specifically designed for `eth_getBlockByNumber`, which\n * can return a `result` of `null` despite an expected `Result` being\n * provided.\n *\n * @param jsonRpcRequest - The JSON-RPC request to send to the endpoint.\n * @param fetchOptions - An options bag for {@link fetch} which further\n * specifies the request.\n * @returns The decoded JSON-RPC response from the endpoint.\n * @throws A \"method not found\" error if the response status is 405.\n * @throws A rate limiting error if the response HTTP status is 429.\n * @throws A timeout error if the response HTTP status is 503 or 504.\n * @throws A generic error if the response HTTP status is not 2xx but also not\n * 405, 429, 503, or 504.\n */\n async request<Params extends JsonRpcParams, Result extends Json>(\n jsonRpcRequest: JsonRpcRequest<Params> & { method: 'eth_getBlockByNumber' },\n fetchOptions?: FetchOptions,\n ): Promise<JsonRpcResponse<Result> | JsonRpcResponse<null>>;\n\n /**\n * Makes a request to the RPC endpoint. If the circuit is open because this\n * request has failed too many times, the request is forwarded to a failover\n * service (if provided).\n *\n * This overload is designed for all RPC methods except for\n * `eth_getBlockByNumber`, which are expected to return a `result` of the\n * expected `Result`.\n *\n * @param jsonRpcRequest - The JSON-RPC request to send to the endpoint.\n * @param fetchOptions - An options bag for {@link fetch} which further\n * specifies the request.\n * @returns The decoded JSON-RPC response from the endpoint.\n * @throws A \"method not found\" error if the response status is 405.\n * @throws A rate limiting error if the response HTTP status is 429.\n * @throws A timeout error if the response HTTP status is 503 or 504.\n * @throws A generic error if the response HTTP status is not 2xx but also not\n * 405, 429, 503, or 504.\n */\n async request<Params extends JsonRpcParams, Result extends Json>(\n jsonRpcRequest: JsonRpcRequest<Params>,\n fetchOptions?: FetchOptions,\n ): Promise<JsonRpcResponse<Result>>;\n\n async request<Params extends JsonRpcParams, Result extends Json>(\n jsonRpcRequest: JsonRpcRequest<Params>,\n fetchOptions: FetchOptions = {},\n ): Promise<JsonRpcResponse<Result | null>> {\n const completeFetchOptions = this.#getCompleteFetchOptions(\n jsonRpcRequest,\n fetchOptions,\n );\n\n try {\n return await this.#executePolicy<Params, Result>(\n jsonRpcRequest,\n completeFetchOptions,\n );\n } catch (error) {\n if (\n this.#policy.circuitBreakerPolicy.state === CircuitState.Open &&\n this.#failoverService !== undefined\n ) {\n return await this.#failoverService.request(\n jsonRpcRequest,\n completeFetchOptions,\n );\n }\n throw error;\n }\n }\n\n /**\n * Constructs a default set of options to `fetch`.\n *\n * If a username and password are present in the URL, they are extracted to an\n * Authorization header.\n *\n * @param endpointUrl - The endpoint URL.\n * @param fetchOptions - The options to `fetch`.\n * @param givenBtoa - An implementation of `btoa`.\n * @returns The default fetch options.\n */\n #getDefaultFetchOptions(\n endpointUrl: URL,\n fetchOptions: FetchOptions,\n givenBtoa: (stringToEncode: string) => string,\n ): FetchOptions {\n if (endpointUrl.username && endpointUrl.password) {\n const authString = `${endpointUrl.username}:${endpointUrl.password}`;\n const encodedCredentials = givenBtoa(authString);\n return deepmerge(fetchOptions, {\n headers: { Authorization: `Basic ${encodedCredentials}` },\n });\n }\n\n return fetchOptions;\n }\n\n /**\n * Constructs a final set of options to pass to `fetch`. Note that the method\n * defaults to `post`, and the JSON-RPC request is automatically JSON-encoded.\n *\n * @param jsonRpcRequest - The JSON-RPC request.\n * @param fetchOptions - Custom `fetch` options.\n * @returns The complete set of `fetch` options.\n */\n #getCompleteFetchOptions<Params extends JsonRpcParams>(\n jsonRpcRequest: JsonRpcRequest<Params>,\n fetchOptions: FetchOptions,\n ): FetchOptions {\n const defaultOptions = {\n method: 'POST',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n },\n };\n const mergedOptions = deepmerge(\n defaultOptions,\n deepmerge(this.#fetchOptions, fetchOptions),\n );\n\n const { id, jsonrpc, method, params } = jsonRpcRequest;\n const body = JSON.stringify({\n id,\n jsonrpc,\n method,\n params,\n });\n\n return { ...mergedOptions, body };\n }\n\n /**\n * Makes the request using the Cockatiel policy that this service creates.\n *\n * @param jsonRpcRequest - The JSON-RPC request to send to the endpoint.\n * @param fetchOptions - The options for `fetch`; will be combined with the\n * fetch options passed to the constructor\n * @returns The decoded JSON-RPC response from the endpoint.\n * @throws A \"method not found\" error if the response status is 405.\n * @throws A rate limiting error if the response HTTP status is 429.\n * @throws A timeout error if the response HTTP status is 503 or 504.\n * @throws A generic error if the response HTTP status is not 2xx but also not\n * 405, 429, 503, or 504.\n */\n async #executePolicy<\n Params extends JsonRpcParams,\n Result extends Json,\n Request extends JsonRpcRequest = JsonRpcRequest<Params>,\n >(\n jsonRpcRequest: Request,\n fetchOptions: FetchOptions,\n ): Promise<JsonRpcResponse<Result> | JsonRpcResponse<null>> {\n return await this.#policy.execute(async () => {\n const response = await this.#fetch(this.#endpointUrl, fetchOptions);\n\n if (response.status === 405) {\n throw rpcErrors.methodNotFound();\n }\n\n if (response.status === 429) {\n throw rpcErrors.internal({ message: 'Request is being rate limited.' });\n }\n\n if (response.status === 503 || response.status === 504) {\n throw rpcErrors.internal({\n message:\n 'Gateway timeout. The request took too long to process. This can happen when querying logs over too wide a block range.',\n });\n }\n\n const text = await response.text();\n\n if (\n jsonRpcRequest.method === 'eth_getBlockByNumber' &&\n text === 'Not Found'\n ) {\n return {\n id: jsonRpcRequest.id,\n jsonrpc: jsonRpcRequest.jsonrpc,\n result: null,\n };\n }\n\n // Type annotation: We assume that if this response is valid JSON, it's a\n // valid JSON-RPC response.\n let json: JsonRpcResponse<Result>;\n try {\n json = JSON.parse(text);\n } catch (error) {\n if (error instanceof SyntaxError) {\n throw rpcErrors.internal({\n message: 'Could not parse response as it is not valid JSON',\n data: text,\n });\n } else {\n throw error;\n }\n }\n\n if (!response.ok) {\n throw rpcErrors.internal({\n message: `Non-200 status code: '${response.status}'`,\n data: json,\n });\n }\n\n return json;\n });\n }\n}\n"]}
1
+ {"version":3,"file":"rpc-service.cjs","sourceRoot":"","sources":["../../src/rpc-service/rpc-service.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n CreateServicePolicyOptions,\n ServicePolicy,\n} from '@metamask/controller-utils';\nimport {\n CircuitState,\n createServicePolicy,\n handleWhen,\n} from '@metamask/controller-utils';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport type { JsonRpcRequest } from '@metamask/utils';\nimport {\n hasProperty,\n type Json,\n type JsonRpcParams,\n type JsonRpcResponse,\n} from '@metamask/utils';\nimport deepmerge from 'deepmerge';\n\nimport type { AbstractRpcService } from './abstract-rpc-service';\nimport type { AddToCockatielEventData, FetchOptions } from './shared';\n\n/**\n * Options for the RpcService constructor.\n */\nexport type RpcServiceOptions = {\n /**\n * A function that can be used to convert a binary string into a\n * base64-encoded ASCII string. Used to encode authorization credentials.\n */\n btoa: typeof btoa;\n /**\n * The URL of the RPC endpoint to hit.\n */\n endpointUrl: URL | string;\n /**\n * An RPC service that represents a failover endpoint which will be invoked\n * while the circuit for _this_ service is open.\n */\n failoverService?: AbstractRpcService;\n /**\n * A function that can be used to make an HTTP request. If your JavaScript\n * environment supports `fetch` natively, you'll probably want to pass that;\n * otherwise you can pass an equivalent (such as `fetch` via `node-fetch`).\n */\n fetch: typeof fetch;\n /**\n * A common set of options that will be used to make every request. Can be\n * overridden on the request level (e.g. to add headers).\n */\n fetchOptions?: FetchOptions;\n /**\n * Options to pass to `createServicePolicy`. Note that `retryFilterPolicy` is\n * not accepted, as it is overwritten. See {@link createServicePolicy}.\n */\n policyOptions?: Omit<CreateServicePolicyOptions, 'retryFilterPolicy'>;\n};\n\n/**\n * The maximum number of times that a failing service should be re-run before\n * giving up.\n */\nexport const DEFAULT_MAX_RETRIES = 4;\n\n/**\n * The maximum number of times that the service is allowed to fail before\n * pausing further retries. This is set to a value such that if given a\n * service that continually fails, the policy needs to be executed 3 times\n * before further retries are paused.\n */\nexport const DEFAULT_MAX_CONSECUTIVE_FAILURES = (1 + DEFAULT_MAX_RETRIES) * 3;\n\n/**\n * The list of error messages that represent a failure to connect to the network.\n *\n * This list was derived from Sindre Sorhus's `is-network-error` package:\n * <https://github.com/sindresorhus/is-network-error/blob/7bbfa8be9482ce1427a21fbff60e3ee1650dd091/index.js>\n */\nexport const CONNECTION_ERRORS = [\n // Chrome\n {\n constructorName: 'TypeError',\n pattern: /network error/u,\n },\n // Chrome\n {\n constructorName: 'TypeError',\n pattern: /Failed to fetch/u,\n },\n // Firefox\n {\n constructorName: 'TypeError',\n pattern: /NetworkError when attempting to fetch resource\\./u,\n },\n // Safari 16\n {\n constructorName: 'TypeError',\n pattern: /The Internet connection appears to be offline\\./u,\n },\n // Safari 17+\n {\n constructorName: 'TypeError',\n pattern: /Load failed/u,\n },\n // `cross-fetch`\n {\n constructorName: 'TypeError',\n pattern: /Network request failed/u,\n },\n // `node-fetch`\n {\n constructorName: 'FetchError',\n pattern: /request to (.+) failed/u,\n },\n // Undici (Node.js)\n {\n constructorName: 'TypeError',\n pattern: /fetch failed/u,\n },\n // Undici (Node.js)\n {\n constructorName: 'TypeError',\n pattern: /terminated/u,\n },\n];\n\n/**\n * Determines whether the given error represents a failure to reach the network\n * after request parameters have been validated.\n *\n * This is somewhat difficult to verify because JavaScript engines (and in\n * some cases libraries) produce slightly different error messages for this\n * particular scenario, and we need to account for this.\n *\n * @param error - The error.\n * @returns True if the error indicates that the network cannot be connected to,\n * and false otherwise.\n */\nexport function isConnectionError(error: unknown) {\n if (!(typeof error === 'object' && error !== null && 'message' in error)) {\n return false;\n }\n\n const { message } = error;\n\n return (\n typeof message === 'string' &&\n !isNockError(message) &&\n CONNECTION_ERRORS.some(({ constructorName, pattern }) => {\n return (\n error.constructor.name === constructorName && pattern.test(message)\n );\n })\n );\n}\n\n/**\n * Determines whether the given error message refers to a Nock error.\n *\n * It's important that if we failed to mock a request in a test, the resulting\n * error does not cause the request to be retried so that we can see it right\n * away.\n *\n * @param message - The error message to test.\n * @returns True if the message indicates a missing Nock mock, false otherwise.\n */\nfunction isNockError(message: string) {\n return message.includes('Nock:');\n}\n\n/**\n * Guarantees a URL, even given a string. This is useful for checking components\n * of that URL.\n *\n * @param endpointUrlOrUrlString - Either a URL object or a string that\n * represents the URL of an endpoint.\n * @returns A URL object.\n */\nfunction getNormalizedEndpointUrl(endpointUrlOrUrlString: URL | string): URL {\n return endpointUrlOrUrlString instanceof URL\n ? endpointUrlOrUrlString\n : new URL(endpointUrlOrUrlString);\n}\n\n/**\n * This class is responsible for making a request to an endpoint that implements\n * the JSON-RPC protocol. It is designed to gracefully handle network and server\n * failures, retrying requests using exponential backoff. It also offers a hook\n * which can used to respond to slow requests.\n */\nexport class RpcService implements AbstractRpcService {\n /**\n * The function used to make an HTTP request.\n */\n readonly #fetch: typeof fetch;\n\n /**\n * The URL of the RPC endpoint.\n */\n readonly endpointUrl: URL;\n\n /**\n * A common set of options that the request options will extend.\n */\n readonly #fetchOptions: FetchOptions;\n\n /**\n * An RPC service that represents a failover endpoint which will be invoked\n * while the circuit for _this_ service is open.\n */\n readonly #failoverService: RpcServiceOptions['failoverService'];\n\n /**\n * The policy that wraps the request.\n */\n readonly #policy: ServicePolicy;\n\n /**\n * Constructs a new RpcService object.\n *\n * @param options - The options. See {@link RpcServiceOptions}.\n */\n constructor(options: RpcServiceOptions) {\n const {\n btoa: givenBtoa,\n endpointUrl,\n failoverService,\n fetch: givenFetch,\n fetchOptions = {},\n policyOptions = {},\n } = options;\n\n this.#fetch = givenFetch;\n this.endpointUrl = getNormalizedEndpointUrl(endpointUrl);\n this.#fetchOptions = this.#getDefaultFetchOptions(\n this.endpointUrl,\n fetchOptions,\n givenBtoa,\n );\n this.#failoverService = failoverService;\n\n const policy = createServicePolicy({\n maxRetries: DEFAULT_MAX_RETRIES,\n maxConsecutiveFailures: DEFAULT_MAX_CONSECUTIVE_FAILURES,\n ...policyOptions,\n retryFilterPolicy: handleWhen((error) => {\n return (\n // Ignore errors where the request failed to establish\n isConnectionError(error) ||\n // Ignore server sent HTML error pages or truncated JSON responses\n error.message.includes('not valid JSON') ||\n // Ignore server overload errors\n error.message.includes('Gateway timeout') ||\n (hasProperty(error, 'code') &&\n (error.code === 'ETIMEDOUT' || error.code === 'ECONNRESET'))\n );\n }),\n });\n this.#policy = policy;\n }\n\n /**\n * Listens for when the RPC service retries the request.\n *\n * @param listener - The callback to be called when the retry occurs.\n * @returns What {@link ServicePolicy.onRetry} returns.\n * @see {@link createServicePolicy}\n */\n onRetry(\n listener: AddToCockatielEventData<\n Parameters<ServicePolicy['onRetry']>[0],\n { endpointUrl: string }\n >,\n ) {\n return this.#policy.onRetry((data) => {\n listener({ ...data, endpointUrl: this.endpointUrl.toString() });\n });\n }\n\n /**\n * Listens for when the RPC service retries the request too many times in a\n * row.\n *\n * @param listener - The callback to be called when the circuit is broken.\n * @returns What {@link ServicePolicy.onBreak} returns.\n * @see {@link createServicePolicy}\n */\n onBreak(\n listener: AddToCockatielEventData<\n Parameters<ServicePolicy['onBreak']>[0],\n { endpointUrl: string; failoverEndpointUrl?: string }\n >,\n ) {\n return this.#policy.onBreak((data) => {\n listener({\n ...data,\n endpointUrl: this.endpointUrl.toString(),\n failoverEndpointUrl: this.#failoverService\n ? this.#failoverService.endpointUrl.toString()\n : undefined,\n });\n });\n }\n\n /**\n * Listens for when the policy underlying this RPC service detects a slow\n * request.\n *\n * @param listener - The callback to be called when the request is slow.\n * @returns What {@link ServicePolicy.onDegraded} returns.\n * @see {@link createServicePolicy}\n */\n onDegraded(\n listener: AddToCockatielEventData<\n Parameters<ServicePolicy['onDegraded']>[0],\n { endpointUrl: string }\n >,\n ) {\n return this.#policy.onDegraded(() => {\n listener({ endpointUrl: this.endpointUrl.toString() });\n });\n }\n\n /**\n * Makes a request to the RPC endpoint. If the circuit is open because this\n * request has failed too many times, the request is forwarded to a failover\n * service (if provided).\n *\n * This overload is specifically designed for `eth_getBlockByNumber`, which\n * can return a `result` of `null` despite an expected `Result` being\n * provided.\n *\n * @param jsonRpcRequest - The JSON-RPC request to send to the endpoint.\n * @param fetchOptions - An options bag for {@link fetch} which further\n * specifies the request.\n * @returns The decoded JSON-RPC response from the endpoint.\n * @throws A \"method not found\" error if the response status is 405.\n * @throws A rate limiting error if the response HTTP status is 429.\n * @throws A timeout error if the response HTTP status is 503 or 504.\n * @throws A generic error if the response HTTP status is not 2xx but also not\n * 405, 429, 503, or 504.\n */\n async request<Params extends JsonRpcParams, Result extends Json>(\n jsonRpcRequest: JsonRpcRequest<Params> & { method: 'eth_getBlockByNumber' },\n fetchOptions?: FetchOptions,\n ): Promise<JsonRpcResponse<Result> | JsonRpcResponse<null>>;\n\n /**\n * Makes a request to the RPC endpoint. If the circuit is open because this\n * request has failed too many times, the request is forwarded to a failover\n * service (if provided).\n *\n * This overload is designed for all RPC methods except for\n * `eth_getBlockByNumber`, which are expected to return a `result` of the\n * expected `Result`.\n *\n * @param jsonRpcRequest - The JSON-RPC request to send to the endpoint.\n * @param fetchOptions - An options bag for {@link fetch} which further\n * specifies the request.\n * @returns The decoded JSON-RPC response from the endpoint.\n * @throws A \"method not found\" error if the response status is 405.\n * @throws A rate limiting error if the response HTTP status is 429.\n * @throws A timeout error if the response HTTP status is 503 or 504.\n * @throws A generic error if the response HTTP status is not 2xx but also not\n * 405, 429, 503, or 504.\n */\n async request<Params extends JsonRpcParams, Result extends Json>(\n jsonRpcRequest: JsonRpcRequest<Params>,\n fetchOptions?: FetchOptions,\n ): Promise<JsonRpcResponse<Result>>;\n\n async request<Params extends JsonRpcParams, Result extends Json>(\n jsonRpcRequest: JsonRpcRequest<Params>,\n fetchOptions: FetchOptions = {},\n ): Promise<JsonRpcResponse<Result | null>> {\n const completeFetchOptions = this.#getCompleteFetchOptions(\n jsonRpcRequest,\n fetchOptions,\n );\n\n try {\n return await this.#executePolicy<Params, Result>(\n jsonRpcRequest,\n completeFetchOptions,\n );\n } catch (error) {\n if (\n this.#policy.circuitBreakerPolicy.state === CircuitState.Open &&\n this.#failoverService !== undefined\n ) {\n return await this.#failoverService.request(\n jsonRpcRequest,\n completeFetchOptions,\n );\n }\n throw error;\n }\n }\n\n /**\n * Constructs a default set of options to `fetch`.\n *\n * If a username and password are present in the URL, they are extracted to an\n * Authorization header.\n *\n * @param endpointUrl - The endpoint URL.\n * @param fetchOptions - The options to `fetch`.\n * @param givenBtoa - An implementation of `btoa`.\n * @returns The default fetch options.\n */\n #getDefaultFetchOptions(\n endpointUrl: URL,\n fetchOptions: FetchOptions,\n givenBtoa: (stringToEncode: string) => string,\n ): FetchOptions {\n if (endpointUrl.username && endpointUrl.password) {\n const authString = `${endpointUrl.username}:${endpointUrl.password}`;\n const encodedCredentials = givenBtoa(authString);\n return deepmerge(fetchOptions, {\n headers: { Authorization: `Basic ${encodedCredentials}` },\n });\n }\n\n return fetchOptions;\n }\n\n /**\n * Constructs a final set of options to pass to `fetch`. Note that the method\n * defaults to `post`, and the JSON-RPC request is automatically JSON-encoded.\n *\n * @param jsonRpcRequest - The JSON-RPC request.\n * @param fetchOptions - Custom `fetch` options.\n * @returns The complete set of `fetch` options.\n */\n #getCompleteFetchOptions<Params extends JsonRpcParams>(\n jsonRpcRequest: JsonRpcRequest<Params>,\n fetchOptions: FetchOptions,\n ): FetchOptions {\n const defaultOptions = {\n method: 'POST',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n },\n };\n const mergedOptions = deepmerge(\n defaultOptions,\n deepmerge(this.#fetchOptions, fetchOptions),\n );\n\n const { id, jsonrpc, method, params } = jsonRpcRequest;\n const body = JSON.stringify({\n id,\n jsonrpc,\n method,\n params,\n });\n\n return { ...mergedOptions, body };\n }\n\n /**\n * Makes the request using the Cockatiel policy that this service creates.\n *\n * @param jsonRpcRequest - The JSON-RPC request to send to the endpoint.\n * @param fetchOptions - The options for `fetch`; will be combined with the\n * fetch options passed to the constructor\n * @returns The decoded JSON-RPC response from the endpoint.\n * @throws A \"method not found\" error if the response status is 405.\n * @throws A rate limiting error if the response HTTP status is 429.\n * @throws A timeout error if the response HTTP status is 503 or 504.\n * @throws A generic error if the response HTTP status is not 2xx but also not\n * 405, 429, 503, or 504.\n */\n async #executePolicy<\n Params extends JsonRpcParams,\n Result extends Json,\n Request extends JsonRpcRequest = JsonRpcRequest<Params>,\n >(\n jsonRpcRequest: Request,\n fetchOptions: FetchOptions,\n ): Promise<JsonRpcResponse<Result> | JsonRpcResponse<null>> {\n return await this.#policy.execute(async () => {\n const response = await this.#fetch(this.endpointUrl, fetchOptions);\n\n if (response.status === 405) {\n throw rpcErrors.methodNotFound();\n }\n\n if (response.status === 429) {\n throw rpcErrors.internal({ message: 'Request is being rate limited.' });\n }\n\n if (response.status === 503 || response.status === 504) {\n throw rpcErrors.internal({\n message:\n 'Gateway timeout. The request took too long to process. This can happen when querying logs over too wide a block range.',\n });\n }\n\n const text = await response.text();\n\n if (\n jsonRpcRequest.method === 'eth_getBlockByNumber' &&\n text === 'Not Found'\n ) {\n return {\n id: jsonRpcRequest.id,\n jsonrpc: jsonRpcRequest.jsonrpc,\n result: null,\n };\n }\n\n // Type annotation: We assume that if this response is valid JSON, it's a\n // valid JSON-RPC response.\n let json: JsonRpcResponse<Result>;\n try {\n json = JSON.parse(text);\n } catch (error) {\n if (error instanceof SyntaxError) {\n throw rpcErrors.internal({\n message: 'Could not parse response as it is not valid JSON',\n data: text,\n });\n } else {\n throw error;\n }\n }\n\n if (!response.ok) {\n throw rpcErrors.internal({\n message: `Non-200 status code: '${response.status}'`,\n data: json,\n });\n }\n\n return json;\n });\n }\n}\n"]}
@@ -1,15 +1,65 @@
1
- import type { ServicePolicy } from "@metamask/controller-utils";
1
+ import type { CreateServicePolicyOptions, ServicePolicy } from "@metamask/controller-utils";
2
2
  import type { JsonRpcRequest } from "@metamask/utils";
3
3
  import { type Json, type JsonRpcParams, type JsonRpcResponse } from "@metamask/utils";
4
4
  import type { AbstractRpcService } from "./abstract-rpc-service.cjs";
5
5
  import type { AddToCockatielEventData, FetchOptions } from "./shared.cjs";
6
6
  /**
7
- * The list of error messages that represent a failure to reach the network.
7
+ * Options for the RpcService constructor.
8
+ */
9
+ export type RpcServiceOptions = {
10
+ /**
11
+ * A function that can be used to convert a binary string into a
12
+ * base64-encoded ASCII string. Used to encode authorization credentials.
13
+ */
14
+ btoa: typeof btoa;
15
+ /**
16
+ * The URL of the RPC endpoint to hit.
17
+ */
18
+ endpointUrl: URL | string;
19
+ /**
20
+ * An RPC service that represents a failover endpoint which will be invoked
21
+ * while the circuit for _this_ service is open.
22
+ */
23
+ failoverService?: AbstractRpcService;
24
+ /**
25
+ * A function that can be used to make an HTTP request. If your JavaScript
26
+ * environment supports `fetch` natively, you'll probably want to pass that;
27
+ * otherwise you can pass an equivalent (such as `fetch` via `node-fetch`).
28
+ */
29
+ fetch: typeof fetch;
30
+ /**
31
+ * A common set of options that will be used to make every request. Can be
32
+ * overridden on the request level (e.g. to add headers).
33
+ */
34
+ fetchOptions?: FetchOptions;
35
+ /**
36
+ * Options to pass to `createServicePolicy`. Note that `retryFilterPolicy` is
37
+ * not accepted, as it is overwritten. See {@link createServicePolicy}.
38
+ */
39
+ policyOptions?: Omit<CreateServicePolicyOptions, 'retryFilterPolicy'>;
40
+ };
41
+ /**
42
+ * The maximum number of times that a failing service should be re-run before
43
+ * giving up.
44
+ */
45
+ export declare const DEFAULT_MAX_RETRIES = 4;
46
+ /**
47
+ * The maximum number of times that the service is allowed to fail before
48
+ * pausing further retries. This is set to a value such that if given a
49
+ * service that continually fails, the policy needs to be executed 3 times
50
+ * before further retries are paused.
51
+ */
52
+ export declare const DEFAULT_MAX_CONSECUTIVE_FAILURES: number;
53
+ /**
54
+ * The list of error messages that represent a failure to connect to the network.
8
55
  *
9
56
  * This list was derived from Sindre Sorhus's `is-network-error` package:
10
57
  * <https://github.com/sindresorhus/is-network-error/blob/7bbfa8be9482ce1427a21fbff60e3ee1650dd091/index.js>
11
58
  */
12
- export declare const NETWORK_UNREACHABLE_ERRORS: Set<string>;
59
+ export declare const CONNECTION_ERRORS: {
60
+ constructorName: string;
61
+ pattern: RegExp;
62
+ }[];
13
63
  /**
14
64
  * Determines whether the given error represents a failure to reach the network
15
65
  * after request parameters have been validated.
@@ -19,10 +69,10 @@ export declare const NETWORK_UNREACHABLE_ERRORS: Set<string>;
19
69
  * particular scenario, and we need to account for this.
20
70
  *
21
71
  * @param error - The error.
22
- * @returns True if the error indicates that the network is unreachable, and
23
- * false otherwise.
72
+ * @returns True if the error indicates that the network cannot be connected to,
73
+ * and false otherwise.
24
74
  */
25
- export default function isNetworkUnreachableError(error: unknown): boolean;
75
+ export declare function isConnectionError(error: unknown): boolean;
26
76
  /**
27
77
  * This class is responsible for making a request to an endpoint that implements
28
78
  * the JSON-RPC protocol. It is designed to gracefully handle network and server
@@ -31,31 +81,16 @@ export default function isNetworkUnreachableError(error: unknown): boolean;
31
81
  */
32
82
  export declare class RpcService implements AbstractRpcService {
33
83
  #private;
84
+ /**
85
+ * The URL of the RPC endpoint.
86
+ */
87
+ readonly endpointUrl: URL;
34
88
  /**
35
89
  * Constructs a new RpcService object.
36
90
  *
37
- * @param args - The arguments.
38
- * @param args.fetch - A function that can be used to make an HTTP request.
39
- * If your JavaScript environment supports `fetch` natively, you'll probably
40
- * want to pass that; otherwise you can pass an equivalent (such as `fetch`
41
- * via `node-fetch`).
42
- * @param args.btoa - A function that can be used to convert a binary string
43
- * into base-64. Used to encode authorization credentials.
44
- * @param args.endpointUrl - The URL of the RPC endpoint.
45
- * @param args.fetchOptions - A common set of options that will be used to
46
- * make every request. Can be overridden on the request level (e.g. to add
47
- * headers).
48
- * @param args.failoverService - An RPC service that represents a failover
49
- * endpoint which will be invoked while the circuit for _this_ service is
50
- * open.
91
+ * @param options - The options. See {@link RpcServiceOptions}.
51
92
  */
52
- constructor({ fetch: givenFetch, btoa: givenBtoa, endpointUrl, fetchOptions, failoverService, }: {
53
- fetch: typeof fetch;
54
- btoa: typeof btoa;
55
- endpointUrl: URL | string;
56
- fetchOptions?: FetchOptions;
57
- failoverService?: AbstractRpcService;
58
- });
93
+ constructor(options: RpcServiceOptions);
59
94
  /**
60
95
  * Listens for when the RPC service retries the request.
61
96
  *
@@ -76,6 +111,7 @@ export declare class RpcService implements AbstractRpcService {
76
111
  */
77
112
  onBreak(listener: AddToCockatielEventData<Parameters<ServicePolicy['onBreak']>[0], {
78
113
  endpointUrl: string;
114
+ failoverEndpointUrl?: string;
79
115
  }>): import("cockatiel").IDisposable;
80
116
  /**
81
117
  * Listens for when the policy underlying this RPC service detects a slow
@@ -1 +1 @@
1
- {"version":3,"file":"rpc-service.d.cts","sourceRoot":"","sources":["../../src/rpc-service/rpc-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,mCAAmC;AAOhE,OAAO,KAAK,EAAE,cAAc,EAAE,wBAAwB;AACtD,OAAO,EAEL,KAAK,IAAI,EACT,KAAK,aAAa,EAClB,KAAK,eAAe,EACrB,wBAAwB;AAGzB,OAAO,KAAK,EAAE,kBAAkB,EAAE,mCAA+B;AACjE,OAAO,KAAK,EAAE,uBAAuB,EAAE,YAAY,EAAE,qBAAiB;AAEtE;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,aASrC,CAAC;AAEH;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,OAAO,UAAU,yBAAyB,CAAC,KAAK,EAAE,OAAO,WAI/D;AAgBD;;;;;GAKG;AACH,qBAAa,UAAW,YAAW,kBAAkB;;IA2BnD;;;;;;;;;;;;;;;;;OAiBG;gBACS,EACV,KAAK,EAAE,UAAU,EACjB,IAAI,EAAE,SAAS,EACf,WAAW,EACX,YAAiB,EACjB,eAAe,GAChB,EAAE;QACD,KAAK,EAAE,OAAO,KAAK,CAAC;QACpB,IAAI,EAAE,OAAO,IAAI,CAAC;QAClB,WAAW,EAAE,GAAG,GAAG,MAAM,CAAC;QAC1B,YAAY,CAAC,EAAE,YAAY,CAAC;QAC5B,eAAe,CAAC,EAAE,kBAAkB,CAAC;KACtC;IA6BD;;;;;;OAMG;IACH,OAAO,CACL,QAAQ,EAAE,uBAAuB,CAC/B,UAAU,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,EACvC;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,CACxB;IAOH;;;;;;;OAOG;IACH,OAAO,CACL,QAAQ,EAAE,uBAAuB,CAC/B,UAAU,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,EACvC;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,CACxB;IAOH;;;;;;;OAOG;IACH,UAAU,CACR,QAAQ,EAAE,uBAAuB,CAC/B,UAAU,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,EAC1C;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,CACxB;IAOH;;;;;;;;;;;;;;;;;;OAkBG;IACG,OAAO,CAAC,MAAM,SAAS,aAAa,EAAE,MAAM,SAAS,IAAI,EAC7D,cAAc,EAAE,cAAc,CAAC,MAAM,CAAC,GAAG;QAAE,MAAM,EAAE,sBAAsB,CAAA;KAAE,EAC3E,YAAY,CAAC,EAAE,YAAY,GAC1B,OAAO,CAAC,eAAe,CAAC,MAAM,CAAC,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IAE3D;;;;;;;;;;;;;;;;;;OAkBG;IACG,OAAO,CAAC,MAAM,SAAS,aAAa,EAAE,MAAM,SAAS,IAAI,EAC7D,cAAc,EAAE,cAAc,CAAC,MAAM,CAAC,EACtC,YAAY,CAAC,EAAE,YAAY,GAC1B,OAAO,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;CA0KpC"}
1
+ {"version":3,"file":"rpc-service.d.cts","sourceRoot":"","sources":["../../src/rpc-service/rpc-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,0BAA0B,EAC1B,aAAa,EACd,mCAAmC;AAOpC,OAAO,KAAK,EAAE,cAAc,EAAE,wBAAwB;AACtD,OAAO,EAEL,KAAK,IAAI,EACT,KAAK,aAAa,EAClB,KAAK,eAAe,EACrB,wBAAwB;AAGzB,OAAO,KAAK,EAAE,kBAAkB,EAAE,mCAA+B;AACjE,OAAO,KAAK,EAAE,uBAAuB,EAAE,YAAY,EAAE,qBAAiB;AAEtE;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;;OAGG;IACH,IAAI,EAAE,OAAO,IAAI,CAAC;IAClB;;OAEG;IACH,WAAW,EAAE,GAAG,GAAG,MAAM,CAAC;IAC1B;;;OAGG;IACH,eAAe,CAAC,EAAE,kBAAkB,CAAC;IACrC;;;;OAIG;IACH,KAAK,EAAE,OAAO,KAAK,CAAC;IACpB;;;OAGG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B;;;OAGG;IACH,aAAa,CAAC,EAAE,IAAI,CAAC,0BAA0B,EAAE,mBAAmB,CAAC,CAAC;CACvE,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAErC;;;;;GAKG;AACH,eAAO,MAAM,gCAAgC,QAAgC,CAAC;AAE9E;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB;;;GA8C7B,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,WAgB/C;AA8BD;;;;;GAKG;AACH,qBAAa,UAAW,YAAW,kBAAkB;;IAMnD;;OAEG;IACH,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAC;IAkB1B;;;;OAIG;gBACS,OAAO,EAAE,iBAAiB;IAuCtC;;;;;;OAMG;IACH,OAAO,CACL,QAAQ,EAAE,uBAAuB,CAC/B,UAAU,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,EACvC;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,CACxB;IAOH;;;;;;;OAOG;IACH,OAAO,CACL,QAAQ,EAAE,uBAAuB,CAC/B,UAAU,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,EACvC;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,mBAAmB,CAAC,EAAE,MAAM,CAAA;KAAE,CACtD;IAaH;;;;;;;OAOG;IACH,UAAU,CACR,QAAQ,EAAE,uBAAuB,CAC/B,UAAU,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,EAC1C;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,CACxB;IAOH;;;;;;;;;;;;;;;;;;OAkBG;IACG,OAAO,CAAC,MAAM,SAAS,aAAa,EAAE,MAAM,SAAS,IAAI,EAC7D,cAAc,EAAE,cAAc,CAAC,MAAM,CAAC,GAAG;QAAE,MAAM,EAAE,sBAAsB,CAAA;KAAE,EAC3E,YAAY,CAAC,EAAE,YAAY,GAC1B,OAAO,CAAC,eAAe,CAAC,MAAM,CAAC,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IAE3D;;;;;;;;;;;;;;;;;;OAkBG;IACG,OAAO,CAAC,MAAM,SAAS,aAAa,EAAE,MAAM,SAAS,IAAI,EAC7D,cAAc,EAAE,cAAc,CAAC,MAAM,CAAC,EACtC,YAAY,CAAC,EAAE,YAAY,GAC1B,OAAO,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;CA0KpC"}
@@ -1,15 +1,65 @@
1
- import type { ServicePolicy } from "@metamask/controller-utils";
1
+ import type { CreateServicePolicyOptions, ServicePolicy } from "@metamask/controller-utils";
2
2
  import type { JsonRpcRequest } from "@metamask/utils";
3
3
  import { type Json, type JsonRpcParams, type JsonRpcResponse } from "@metamask/utils";
4
4
  import type { AbstractRpcService } from "./abstract-rpc-service.mjs";
5
5
  import type { AddToCockatielEventData, FetchOptions } from "./shared.mjs";
6
6
  /**
7
- * The list of error messages that represent a failure to reach the network.
7
+ * Options for the RpcService constructor.
8
+ */
9
+ export type RpcServiceOptions = {
10
+ /**
11
+ * A function that can be used to convert a binary string into a
12
+ * base64-encoded ASCII string. Used to encode authorization credentials.
13
+ */
14
+ btoa: typeof btoa;
15
+ /**
16
+ * The URL of the RPC endpoint to hit.
17
+ */
18
+ endpointUrl: URL | string;
19
+ /**
20
+ * An RPC service that represents a failover endpoint which will be invoked
21
+ * while the circuit for _this_ service is open.
22
+ */
23
+ failoverService?: AbstractRpcService;
24
+ /**
25
+ * A function that can be used to make an HTTP request. If your JavaScript
26
+ * environment supports `fetch` natively, you'll probably want to pass that;
27
+ * otherwise you can pass an equivalent (such as `fetch` via `node-fetch`).
28
+ */
29
+ fetch: typeof fetch;
30
+ /**
31
+ * A common set of options that will be used to make every request. Can be
32
+ * overridden on the request level (e.g. to add headers).
33
+ */
34
+ fetchOptions?: FetchOptions;
35
+ /**
36
+ * Options to pass to `createServicePolicy`. Note that `retryFilterPolicy` is
37
+ * not accepted, as it is overwritten. See {@link createServicePolicy}.
38
+ */
39
+ policyOptions?: Omit<CreateServicePolicyOptions, 'retryFilterPolicy'>;
40
+ };
41
+ /**
42
+ * The maximum number of times that a failing service should be re-run before
43
+ * giving up.
44
+ */
45
+ export declare const DEFAULT_MAX_RETRIES = 4;
46
+ /**
47
+ * The maximum number of times that the service is allowed to fail before
48
+ * pausing further retries. This is set to a value such that if given a
49
+ * service that continually fails, the policy needs to be executed 3 times
50
+ * before further retries are paused.
51
+ */
52
+ export declare const DEFAULT_MAX_CONSECUTIVE_FAILURES: number;
53
+ /**
54
+ * The list of error messages that represent a failure to connect to the network.
8
55
  *
9
56
  * This list was derived from Sindre Sorhus's `is-network-error` package:
10
57
  * <https://github.com/sindresorhus/is-network-error/blob/7bbfa8be9482ce1427a21fbff60e3ee1650dd091/index.js>
11
58
  */
12
- export declare const NETWORK_UNREACHABLE_ERRORS: Set<string>;
59
+ export declare const CONNECTION_ERRORS: {
60
+ constructorName: string;
61
+ pattern: RegExp;
62
+ }[];
13
63
  /**
14
64
  * Determines whether the given error represents a failure to reach the network
15
65
  * after request parameters have been validated.
@@ -19,10 +69,10 @@ export declare const NETWORK_UNREACHABLE_ERRORS: Set<string>;
19
69
  * particular scenario, and we need to account for this.
20
70
  *
21
71
  * @param error - The error.
22
- * @returns True if the error indicates that the network is unreachable, and
23
- * false otherwise.
72
+ * @returns True if the error indicates that the network cannot be connected to,
73
+ * and false otherwise.
24
74
  */
25
- export default function isNetworkUnreachableError(error: unknown): boolean;
75
+ export declare function isConnectionError(error: unknown): boolean;
26
76
  /**
27
77
  * This class is responsible for making a request to an endpoint that implements
28
78
  * the JSON-RPC protocol. It is designed to gracefully handle network and server
@@ -31,31 +81,16 @@ export default function isNetworkUnreachableError(error: unknown): boolean;
31
81
  */
32
82
  export declare class RpcService implements AbstractRpcService {
33
83
  #private;
84
+ /**
85
+ * The URL of the RPC endpoint.
86
+ */
87
+ readonly endpointUrl: URL;
34
88
  /**
35
89
  * Constructs a new RpcService object.
36
90
  *
37
- * @param args - The arguments.
38
- * @param args.fetch - A function that can be used to make an HTTP request.
39
- * If your JavaScript environment supports `fetch` natively, you'll probably
40
- * want to pass that; otherwise you can pass an equivalent (such as `fetch`
41
- * via `node-fetch`).
42
- * @param args.btoa - A function that can be used to convert a binary string
43
- * into base-64. Used to encode authorization credentials.
44
- * @param args.endpointUrl - The URL of the RPC endpoint.
45
- * @param args.fetchOptions - A common set of options that will be used to
46
- * make every request. Can be overridden on the request level (e.g. to add
47
- * headers).
48
- * @param args.failoverService - An RPC service that represents a failover
49
- * endpoint which will be invoked while the circuit for _this_ service is
50
- * open.
91
+ * @param options - The options. See {@link RpcServiceOptions}.
51
92
  */
52
- constructor({ fetch: givenFetch, btoa: givenBtoa, endpointUrl, fetchOptions, failoverService, }: {
53
- fetch: typeof fetch;
54
- btoa: typeof btoa;
55
- endpointUrl: URL | string;
56
- fetchOptions?: FetchOptions;
57
- failoverService?: AbstractRpcService;
58
- });
93
+ constructor(options: RpcServiceOptions);
59
94
  /**
60
95
  * Listens for when the RPC service retries the request.
61
96
  *
@@ -76,6 +111,7 @@ export declare class RpcService implements AbstractRpcService {
76
111
  */
77
112
  onBreak(listener: AddToCockatielEventData<Parameters<ServicePolicy['onBreak']>[0], {
78
113
  endpointUrl: string;
114
+ failoverEndpointUrl?: string;
79
115
  }>): import("cockatiel").IDisposable;
80
116
  /**
81
117
  * Listens for when the policy underlying this RPC service detects a slow
@@ -1 +1 @@
1
- {"version":3,"file":"rpc-service.d.mts","sourceRoot":"","sources":["../../src/rpc-service/rpc-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,mCAAmC;AAOhE,OAAO,KAAK,EAAE,cAAc,EAAE,wBAAwB;AACtD,OAAO,EAEL,KAAK,IAAI,EACT,KAAK,aAAa,EAClB,KAAK,eAAe,EACrB,wBAAwB;AAGzB,OAAO,KAAK,EAAE,kBAAkB,EAAE,mCAA+B;AACjE,OAAO,KAAK,EAAE,uBAAuB,EAAE,YAAY,EAAE,qBAAiB;AAEtE;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,aASrC,CAAC;AAEH;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,OAAO,UAAU,yBAAyB,CAAC,KAAK,EAAE,OAAO,WAI/D;AAgBD;;;;;GAKG;AACH,qBAAa,UAAW,YAAW,kBAAkB;;IA2BnD;;;;;;;;;;;;;;;;;OAiBG;gBACS,EACV,KAAK,EAAE,UAAU,EACjB,IAAI,EAAE,SAAS,EACf,WAAW,EACX,YAAiB,EACjB,eAAe,GAChB,EAAE;QACD,KAAK,EAAE,OAAO,KAAK,CAAC;QACpB,IAAI,EAAE,OAAO,IAAI,CAAC;QAClB,WAAW,EAAE,GAAG,GAAG,MAAM,CAAC;QAC1B,YAAY,CAAC,EAAE,YAAY,CAAC;QAC5B,eAAe,CAAC,EAAE,kBAAkB,CAAC;KACtC;IA6BD;;;;;;OAMG;IACH,OAAO,CACL,QAAQ,EAAE,uBAAuB,CAC/B,UAAU,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,EACvC;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,CACxB;IAOH;;;;;;;OAOG;IACH,OAAO,CACL,QAAQ,EAAE,uBAAuB,CAC/B,UAAU,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,EACvC;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,CACxB;IAOH;;;;;;;OAOG;IACH,UAAU,CACR,QAAQ,EAAE,uBAAuB,CAC/B,UAAU,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,EAC1C;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,CACxB;IAOH;;;;;;;;;;;;;;;;;;OAkBG;IACG,OAAO,CAAC,MAAM,SAAS,aAAa,EAAE,MAAM,SAAS,IAAI,EAC7D,cAAc,EAAE,cAAc,CAAC,MAAM,CAAC,GAAG;QAAE,MAAM,EAAE,sBAAsB,CAAA;KAAE,EAC3E,YAAY,CAAC,EAAE,YAAY,GAC1B,OAAO,CAAC,eAAe,CAAC,MAAM,CAAC,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IAE3D;;;;;;;;;;;;;;;;;;OAkBG;IACG,OAAO,CAAC,MAAM,SAAS,aAAa,EAAE,MAAM,SAAS,IAAI,EAC7D,cAAc,EAAE,cAAc,CAAC,MAAM,CAAC,EACtC,YAAY,CAAC,EAAE,YAAY,GAC1B,OAAO,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;CA0KpC"}
1
+ {"version":3,"file":"rpc-service.d.mts","sourceRoot":"","sources":["../../src/rpc-service/rpc-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,0BAA0B,EAC1B,aAAa,EACd,mCAAmC;AAOpC,OAAO,KAAK,EAAE,cAAc,EAAE,wBAAwB;AACtD,OAAO,EAEL,KAAK,IAAI,EACT,KAAK,aAAa,EAClB,KAAK,eAAe,EACrB,wBAAwB;AAGzB,OAAO,KAAK,EAAE,kBAAkB,EAAE,mCAA+B;AACjE,OAAO,KAAK,EAAE,uBAAuB,EAAE,YAAY,EAAE,qBAAiB;AAEtE;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;;OAGG;IACH,IAAI,EAAE,OAAO,IAAI,CAAC;IAClB;;OAEG;IACH,WAAW,EAAE,GAAG,GAAG,MAAM,CAAC;IAC1B;;;OAGG;IACH,eAAe,CAAC,EAAE,kBAAkB,CAAC;IACrC;;;;OAIG;IACH,KAAK,EAAE,OAAO,KAAK,CAAC;IACpB;;;OAGG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B;;;OAGG;IACH,aAAa,CAAC,EAAE,IAAI,CAAC,0BAA0B,EAAE,mBAAmB,CAAC,CAAC;CACvE,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAErC;;;;;GAKG;AACH,eAAO,MAAM,gCAAgC,QAAgC,CAAC;AAE9E;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB;;;GA8C7B,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,WAgB/C;AA8BD;;;;;GAKG;AACH,qBAAa,UAAW,YAAW,kBAAkB;;IAMnD;;OAEG;IACH,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAC;IAkB1B;;;;OAIG;gBACS,OAAO,EAAE,iBAAiB;IAuCtC;;;;;;OAMG;IACH,OAAO,CACL,QAAQ,EAAE,uBAAuB,CAC/B,UAAU,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,EACvC;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,CACxB;IAOH;;;;;;;OAOG;IACH,OAAO,CACL,QAAQ,EAAE,uBAAuB,CAC/B,UAAU,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,EACvC;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,mBAAmB,CAAC,EAAE,MAAM,CAAA;KAAE,CACtD;IAaH;;;;;;;OAOG;IACH,UAAU,CACR,QAAQ,EAAE,uBAAuB,CAC/B,UAAU,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,EAC1C;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,CACxB;IAOH;;;;;;;;;;;;;;;;;;OAkBG;IACG,OAAO,CAAC,MAAM,SAAS,aAAa,EAAE,MAAM,SAAS,IAAI,EAC7D,cAAc,EAAE,cAAc,CAAC,MAAM,CAAC,GAAG;QAAE,MAAM,EAAE,sBAAsB,CAAA;KAAE,EAC3E,YAAY,CAAC,EAAE,YAAY,GAC1B,OAAO,CAAC,eAAe,CAAC,MAAM,CAAC,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IAE3D;;;;;;;;;;;;;;;;;;OAkBG;IACG,OAAO,CAAC,MAAM,SAAS,aAAa,EAAE,MAAM,SAAS,IAAI,EAC7D,cAAc,EAAE,cAAc,CAAC,MAAM,CAAC,EACtC,YAAY,CAAC,EAAE,YAAY,GAC1B,OAAO,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;CA0KpC"}
@@ -9,7 +9,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
9
9
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
10
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
11
  };
12
- var _RpcService_instances, _RpcService_fetch, _RpcService_endpointUrl, _RpcService_fetchOptions, _RpcService_failoverService, _RpcService_policy, _RpcService_getDefaultFetchOptions, _RpcService_getCompleteFetchOptions, _RpcService_executePolicy;
12
+ var _RpcService_instances, _RpcService_fetch, _RpcService_fetchOptions, _RpcService_failoverService, _RpcService_policy, _RpcService_getDefaultFetchOptions, _RpcService_getCompleteFetchOptions, _RpcService_executePolicy;
13
13
  function $importDefault(module) {
14
14
  if (module?.__esModule) {
15
15
  return module.default;
@@ -22,21 +22,70 @@ import { hasProperty } from "@metamask/utils";
22
22
  import $deepmerge from "deepmerge";
23
23
  const deepmerge = $importDefault($deepmerge);
24
24
  /**
25
- * The list of error messages that represent a failure to reach the network.
25
+ * The maximum number of times that a failing service should be re-run before
26
+ * giving up.
27
+ */
28
+ export const DEFAULT_MAX_RETRIES = 4;
29
+ /**
30
+ * The maximum number of times that the service is allowed to fail before
31
+ * pausing further retries. This is set to a value such that if given a
32
+ * service that continually fails, the policy needs to be executed 3 times
33
+ * before further retries are paused.
34
+ */
35
+ export const DEFAULT_MAX_CONSECUTIVE_FAILURES = (1 + DEFAULT_MAX_RETRIES) * 3;
36
+ /**
37
+ * The list of error messages that represent a failure to connect to the network.
26
38
  *
27
39
  * This list was derived from Sindre Sorhus's `is-network-error` package:
28
40
  * <https://github.com/sindresorhus/is-network-error/blob/7bbfa8be9482ce1427a21fbff60e3ee1650dd091/index.js>
29
41
  */
30
- export const NETWORK_UNREACHABLE_ERRORS = new Set([
31
- 'network error',
32
- 'Failed to fetch',
33
- 'NetworkError when attempting to fetch resource.',
34
- 'The Internet connection appears to be offline.',
35
- 'Load failed',
36
- 'Network request failed',
37
- 'fetch failed',
38
- 'terminated', // Undici (Node.js)
39
- ]);
42
+ export const CONNECTION_ERRORS = [
43
+ // Chrome
44
+ {
45
+ constructorName: 'TypeError',
46
+ pattern: /network error/u,
47
+ },
48
+ // Chrome
49
+ {
50
+ constructorName: 'TypeError',
51
+ pattern: /Failed to fetch/u,
52
+ },
53
+ // Firefox
54
+ {
55
+ constructorName: 'TypeError',
56
+ pattern: /NetworkError when attempting to fetch resource\./u,
57
+ },
58
+ // Safari 16
59
+ {
60
+ constructorName: 'TypeError',
61
+ pattern: /The Internet connection appears to be offline\./u,
62
+ },
63
+ // Safari 17+
64
+ {
65
+ constructorName: 'TypeError',
66
+ pattern: /Load failed/u,
67
+ },
68
+ // `cross-fetch`
69
+ {
70
+ constructorName: 'TypeError',
71
+ pattern: /Network request failed/u,
72
+ },
73
+ // `node-fetch`
74
+ {
75
+ constructorName: 'FetchError',
76
+ pattern: /request to (.+) failed/u,
77
+ },
78
+ // Undici (Node.js)
79
+ {
80
+ constructorName: 'TypeError',
81
+ pattern: /fetch failed/u,
82
+ },
83
+ // Undici (Node.js)
84
+ {
85
+ constructorName: 'TypeError',
86
+ pattern: /terminated/u,
87
+ },
88
+ ];
40
89
  /**
41
90
  * Determines whether the given error represents a failure to reach the network
42
91
  * after request parameters have been validated.
@@ -46,11 +95,32 @@ export const NETWORK_UNREACHABLE_ERRORS = new Set([
46
95
  * particular scenario, and we need to account for this.
47
96
  *
48
97
  * @param error - The error.
49
- * @returns True if the error indicates that the network is unreachable, and
50
- * false otherwise.
98
+ * @returns True if the error indicates that the network cannot be connected to,
99
+ * and false otherwise.
51
100
  */
52
- export default function isNetworkUnreachableError(error) {
53
- return (error instanceof TypeError && NETWORK_UNREACHABLE_ERRORS.has(error.message));
101
+ export function isConnectionError(error) {
102
+ if (!(typeof error === 'object' && error !== null && 'message' in error)) {
103
+ return false;
104
+ }
105
+ const { message } = error;
106
+ return (typeof message === 'string' &&
107
+ !isNockError(message) &&
108
+ CONNECTION_ERRORS.some(({ constructorName, pattern }) => {
109
+ return (error.constructor.name === constructorName && pattern.test(message));
110
+ }));
111
+ }
112
+ /**
113
+ * Determines whether the given error message refers to a Nock error.
114
+ *
115
+ * It's important that if we failed to mock a request in a test, the resulting
116
+ * error does not cause the request to be retried so that we can see it right
117
+ * away.
118
+ *
119
+ * @param message - The error message to test.
120
+ * @returns True if the message indicates a missing Nock mock, false otherwise.
121
+ */
122
+ function isNockError(message) {
123
+ return message.includes('Nock:');
54
124
  }
55
125
  /**
56
126
  * Guarantees a URL, even given a string. This is useful for checking components
@@ -75,31 +145,14 @@ export class RpcService {
75
145
  /**
76
146
  * Constructs a new RpcService object.
77
147
  *
78
- * @param args - The arguments.
79
- * @param args.fetch - A function that can be used to make an HTTP request.
80
- * If your JavaScript environment supports `fetch` natively, you'll probably
81
- * want to pass that; otherwise you can pass an equivalent (such as `fetch`
82
- * via `node-fetch`).
83
- * @param args.btoa - A function that can be used to convert a binary string
84
- * into base-64. Used to encode authorization credentials.
85
- * @param args.endpointUrl - The URL of the RPC endpoint.
86
- * @param args.fetchOptions - A common set of options that will be used to
87
- * make every request. Can be overridden on the request level (e.g. to add
88
- * headers).
89
- * @param args.failoverService - An RPC service that represents a failover
90
- * endpoint which will be invoked while the circuit for _this_ service is
91
- * open.
148
+ * @param options - The options. See {@link RpcServiceOptions}.
92
149
  */
93
- constructor({ fetch: givenFetch, btoa: givenBtoa, endpointUrl, fetchOptions = {}, failoverService, }) {
150
+ constructor(options) {
94
151
  _RpcService_instances.add(this);
95
152
  /**
96
153
  * The function used to make an HTTP request.
97
154
  */
98
155
  _RpcService_fetch.set(this, void 0);
99
- /**
100
- * The URL of the RPC endpoint.
101
- */
102
- _RpcService_endpointUrl.set(this, void 0);
103
156
  /**
104
157
  * A common set of options that the request options will extend.
105
158
  */
@@ -113,17 +166,19 @@ export class RpcService {
113
166
  * The policy that wraps the request.
114
167
  */
115
168
  _RpcService_policy.set(this, void 0);
169
+ const { btoa: givenBtoa, endpointUrl, failoverService, fetch: givenFetch, fetchOptions = {}, policyOptions = {}, } = options;
116
170
  __classPrivateFieldSet(this, _RpcService_fetch, givenFetch, "f");
117
- __classPrivateFieldSet(this, _RpcService_endpointUrl, getNormalizedEndpointUrl(endpointUrl), "f");
118
- __classPrivateFieldSet(this, _RpcService_fetchOptions, __classPrivateFieldGet(this, _RpcService_instances, "m", _RpcService_getDefaultFetchOptions).call(this, __classPrivateFieldGet(this, _RpcService_endpointUrl, "f"), fetchOptions, givenBtoa), "f");
171
+ this.endpointUrl = getNormalizedEndpointUrl(endpointUrl);
172
+ __classPrivateFieldSet(this, _RpcService_fetchOptions, __classPrivateFieldGet(this, _RpcService_instances, "m", _RpcService_getDefaultFetchOptions).call(this, this.endpointUrl, fetchOptions, givenBtoa), "f");
119
173
  __classPrivateFieldSet(this, _RpcService_failoverService, failoverService, "f");
120
174
  const policy = createServicePolicy({
121
- maxRetries: 4,
122
- maxConsecutiveFailures: 15,
175
+ maxRetries: DEFAULT_MAX_RETRIES,
176
+ maxConsecutiveFailures: DEFAULT_MAX_CONSECUTIVE_FAILURES,
177
+ ...policyOptions,
123
178
  retryFilterPolicy: handleWhen((error) => {
124
179
  return (
125
180
  // Ignore errors where the request failed to establish
126
- isNetworkUnreachableError(error) ||
181
+ isConnectionError(error) ||
127
182
  // Ignore server sent HTML error pages or truncated JSON responses
128
183
  error.message.includes('not valid JSON') ||
129
184
  // Ignore server overload errors
@@ -143,7 +198,7 @@ export class RpcService {
143
198
  */
144
199
  onRetry(listener) {
145
200
  return __classPrivateFieldGet(this, _RpcService_policy, "f").onRetry((data) => {
146
- listener({ ...data, endpointUrl: __classPrivateFieldGet(this, _RpcService_endpointUrl, "f").toString() });
201
+ listener({ ...data, endpointUrl: this.endpointUrl.toString() });
147
202
  });
148
203
  }
149
204
  /**
@@ -156,7 +211,13 @@ export class RpcService {
156
211
  */
157
212
  onBreak(listener) {
158
213
  return __classPrivateFieldGet(this, _RpcService_policy, "f").onBreak((data) => {
159
- listener({ ...data, endpointUrl: __classPrivateFieldGet(this, _RpcService_endpointUrl, "f").toString() });
214
+ listener({
215
+ ...data,
216
+ endpointUrl: this.endpointUrl.toString(),
217
+ failoverEndpointUrl: __classPrivateFieldGet(this, _RpcService_failoverService, "f")
218
+ ? __classPrivateFieldGet(this, _RpcService_failoverService, "f").endpointUrl.toString()
219
+ : undefined,
220
+ });
160
221
  });
161
222
  }
162
223
  /**
@@ -169,7 +230,7 @@ export class RpcService {
169
230
  */
170
231
  onDegraded(listener) {
171
232
  return __classPrivateFieldGet(this, _RpcService_policy, "f").onDegraded(() => {
172
- listener({ endpointUrl: __classPrivateFieldGet(this, _RpcService_endpointUrl, "f").toString() });
233
+ listener({ endpointUrl: this.endpointUrl.toString() });
173
234
  });
174
235
  }
175
236
  async request(jsonRpcRequest, fetchOptions = {}) {
@@ -186,7 +247,7 @@ export class RpcService {
186
247
  }
187
248
  }
188
249
  }
189
- _RpcService_fetch = new WeakMap(), _RpcService_endpointUrl = new WeakMap(), _RpcService_fetchOptions = new WeakMap(), _RpcService_failoverService = new WeakMap(), _RpcService_policy = new WeakMap(), _RpcService_instances = new WeakSet(), _RpcService_getDefaultFetchOptions = function _RpcService_getDefaultFetchOptions(endpointUrl, fetchOptions, givenBtoa) {
250
+ _RpcService_fetch = new WeakMap(), _RpcService_fetchOptions = new WeakMap(), _RpcService_failoverService = new WeakMap(), _RpcService_policy = new WeakMap(), _RpcService_instances = new WeakSet(), _RpcService_getDefaultFetchOptions = function _RpcService_getDefaultFetchOptions(endpointUrl, fetchOptions, givenBtoa) {
190
251
  if (endpointUrl.username && endpointUrl.password) {
191
252
  const authString = `${endpointUrl.username}:${endpointUrl.password}`;
192
253
  const encodedCredentials = givenBtoa(authString);
@@ -228,7 +289,7 @@ _RpcService_fetch = new WeakMap(), _RpcService_endpointUrl = new WeakMap(), _Rpc
228
289
  */
229
290
  async function _RpcService_executePolicy(jsonRpcRequest, fetchOptions) {
230
291
  return await __classPrivateFieldGet(this, _RpcService_policy, "f").execute(async () => {
231
- const response = await __classPrivateFieldGet(this, _RpcService_fetch, "f").call(this, __classPrivateFieldGet(this, _RpcService_endpointUrl, "f"), fetchOptions);
292
+ const response = await __classPrivateFieldGet(this, _RpcService_fetch, "f").call(this, this.endpointUrl, fetchOptions);
232
293
  if (response.status === 405) {
233
294
  throw rpcErrors.methodNotFound();
234
295
  }