@metamask-previews/network-controller 22.1.1-preview-bd04b248 → 22.1.1-preview-3fc797ab

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.
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=abstract-rpc-service.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abstract-rpc-service.cjs","sourceRoot":"","sources":["../../src/rpc-service/abstract-rpc-service.ts"],"names":[],"mappings":"","sourcesContent":["import type { ServicePolicy } from '@metamask/controller-utils';\nimport type {\n Json,\n JsonRpcParams,\n JsonRpcRequest,\n JsonRpcResponse,\n} from '@metamask/utils';\n\nimport type { FetchOptions } from './shared';\n\n/**\n * The interface for a service class responsible for making a request to an RPC\n * endpoint.\n */\nexport type AbstractRpcService = Partial<\n Pick<ServicePolicy, 'onBreak' | 'onRetry' | 'onDegraded'>\n> & {\n request<Params extends JsonRpcParams, Result extends Json>(\n jsonRpcRequest: JsonRpcRequest<Params>,\n fetchOptions?: FetchOptions,\n ): Promise<JsonRpcResponse<Result | null>>;\n};\n"]}
@@ -0,0 +1,11 @@
1
+ import type { ServicePolicy } from "@metamask/controller-utils";
2
+ import type { Json, JsonRpcParams, JsonRpcRequest, JsonRpcResponse } from "@metamask/utils";
3
+ import type { FetchOptions } from "./shared.cjs";
4
+ /**
5
+ * The interface for a service class responsible for making a request to an RPC
6
+ * endpoint.
7
+ */
8
+ export type AbstractRpcService = Partial<Pick<ServicePolicy, 'onBreak' | 'onRetry' | 'onDegraded'>> & {
9
+ request<Params extends JsonRpcParams, Result extends Json>(jsonRpcRequest: JsonRpcRequest<Params>, fetchOptions?: FetchOptions): Promise<JsonRpcResponse<Result | null>>;
10
+ };
11
+ //# sourceMappingURL=abstract-rpc-service.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abstract-rpc-service.d.cts","sourceRoot":"","sources":["../../src/rpc-service/abstract-rpc-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,mCAAmC;AAChE,OAAO,KAAK,EACV,IAAI,EACJ,aAAa,EACb,cAAc,EACd,eAAe,EAChB,wBAAwB;AAEzB,OAAO,KAAK,EAAE,YAAY,EAAE,qBAAiB;AAE7C;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG,OAAO,CACtC,IAAI,CAAC,aAAa,EAAE,SAAS,GAAG,SAAS,GAAG,YAAY,CAAC,CAC1D,GAAG;IACF,OAAO,CAAC,MAAM,SAAS,aAAa,EAAE,MAAM,SAAS,IAAI,EACvD,cAAc,EAAE,cAAc,CAAC,MAAM,CAAC,EACtC,YAAY,CAAC,EAAE,YAAY,GAC1B,OAAO,CAAC,eAAe,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;CAC5C,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { ServicePolicy } from "@metamask/controller-utils";
2
+ import type { Json, JsonRpcParams, JsonRpcRequest, JsonRpcResponse } from "@metamask/utils";
3
+ import type { FetchOptions } from "./shared.mjs";
4
+ /**
5
+ * The interface for a service class responsible for making a request to an RPC
6
+ * endpoint.
7
+ */
8
+ export type AbstractRpcService = Partial<Pick<ServicePolicy, 'onBreak' | 'onRetry' | 'onDegraded'>> & {
9
+ request<Params extends JsonRpcParams, Result extends Json>(jsonRpcRequest: JsonRpcRequest<Params>, fetchOptions?: FetchOptions): Promise<JsonRpcResponse<Result | null>>;
10
+ };
11
+ //# sourceMappingURL=abstract-rpc-service.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abstract-rpc-service.d.mts","sourceRoot":"","sources":["../../src/rpc-service/abstract-rpc-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,mCAAmC;AAChE,OAAO,KAAK,EACV,IAAI,EACJ,aAAa,EACb,cAAc,EACd,eAAe,EAChB,wBAAwB;AAEzB,OAAO,KAAK,EAAE,YAAY,EAAE,qBAAiB;AAE7C;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG,OAAO,CACtC,IAAI,CAAC,aAAa,EAAE,SAAS,GAAG,SAAS,GAAG,YAAY,CAAC,CAC1D,GAAG;IACF,OAAO,CAAC,MAAM,SAAS,aAAa,EAAE,MAAM,SAAS,IAAI,EACvD,cAAc,EAAE,cAAc,CAAC,MAAM,CAAC,EACtC,YAAY,CAAC,EAAE,YAAY,GAC1B,OAAO,CAAC,eAAe,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;CAC5C,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=abstract-rpc-service.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abstract-rpc-service.mjs","sourceRoot":"","sources":["../../src/rpc-service/abstract-rpc-service.ts"],"names":[],"mappings":"","sourcesContent":["import type { ServicePolicy } from '@metamask/controller-utils';\nimport type {\n Json,\n JsonRpcParams,\n JsonRpcRequest,\n JsonRpcResponse,\n} from '@metamask/utils';\n\nimport type { FetchOptions } from './shared';\n\n/**\n * The interface for a service class responsible for making a request to an RPC\n * endpoint.\n */\nexport type AbstractRpcService = Partial<\n Pick<ServicePolicy, 'onBreak' | 'onRetry' | 'onDegraded'>\n> & {\n request<Params extends JsonRpcParams, Result extends Json>(\n jsonRpcRequest: JsonRpcRequest<Params>,\n fetchOptions?: FetchOptions,\n ): Promise<JsonRpcResponse<Result | null>>;\n};\n"]}
@@ -0,0 +1,256 @@
1
+ "use strict";
2
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
3
+ if (kind === "m") throw new TypeError("Private method is not writable");
4
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
5
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
6
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
7
+ };
8
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
9
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
10
+ 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");
11
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
+ };
13
+ var __importDefault = (this && this.__importDefault) || function (mod) {
14
+ return (mod && mod.__esModule) ? mod : { "default": mod };
15
+ };
16
+ var _RpcService_instances, _RpcService_fetch, _RpcService_endpointUrl, _RpcService_fetchOptions, _RpcService_policy, _RpcService_getDefaultFetchOptions, _RpcService_getCompleteFetchOptions, _RpcService_executePolicy;
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.RpcService = exports.NETWORK_UNREACHABLE_ERRORS = void 0;
19
+ const controller_utils_1 = require("@metamask/controller-utils");
20
+ const rpc_errors_1 = require("@metamask/rpc-errors");
21
+ const utils_1 = require("@metamask/utils");
22
+ const deepmerge_1 = __importDefault(require("deepmerge"));
23
+ /**
24
+ * The list of error messages that represent a failure to reach the network.
25
+ *
26
+ * This list was derived from Sindre Sorhus's `is-network-error` package:
27
+ * <https://github.com/sindresorhus/is-network-error/blob/7bbfa8be9482ce1427a21fbff60e3ee1650dd091/index.js>
28
+ */
29
+ exports.NETWORK_UNREACHABLE_ERRORS = new Set([
30
+ 'network error',
31
+ 'Failed to fetch',
32
+ 'NetworkError when attempting to fetch resource.',
33
+ 'The Internet connection appears to be offline.',
34
+ 'Load failed',
35
+ 'Network request failed',
36
+ 'fetch failed',
37
+ 'terminated', // Undici (Node.js)
38
+ ]);
39
+ /**
40
+ * Determines whether the given error represents a failure to reach the network
41
+ * after request parameters have been validated.
42
+ *
43
+ * This is somewhat difficult to verify because JavaScript engines (and in
44
+ * some cases libraries) produce slightly different error messages for this
45
+ * particular scenario, and we need to account for this.
46
+ *
47
+ * @param error - The error.
48
+ * @returns True if the error indicates that the network is unreachable, and
49
+ * false otherwise.
50
+ */
51
+ function isNetworkUnreachableError(error) {
52
+ return (error instanceof TypeError && exports.NETWORK_UNREACHABLE_ERRORS.has(error.message));
53
+ }
54
+ exports.default = isNetworkUnreachableError;
55
+ /**
56
+ * Guarantees a URL, even given a string. This is useful for checking components
57
+ * of that URL.
58
+ *
59
+ * @param endpointUrlOrUrlString - Either a URL object or a string that
60
+ * represents the URL of an endpoint.
61
+ * @returns A URL object.
62
+ */
63
+ function getNormalizedEndpointUrl(endpointUrlOrUrlString) {
64
+ return endpointUrlOrUrlString instanceof URL
65
+ ? endpointUrlOrUrlString
66
+ : new URL(endpointUrlOrUrlString);
67
+ }
68
+ /**
69
+ * This class is responsible for making a request to an endpoint that implements
70
+ * the JSON-RPC protocol. It is designed to gracefully handle network and server
71
+ * failures, retrying requests using exponential backoff. It also offers a hook
72
+ * which can used to respond to slow requests.
73
+ */
74
+ class RpcService {
75
+ /**
76
+ * Constructs a new RpcService object.
77
+ *
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 encode 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
+ */
90
+ constructor({ fetch: givenFetch, btoa: givenBtoa, endpointUrl, fetchOptions = {}, }) {
91
+ _RpcService_instances.add(this);
92
+ /**
93
+ * The function used to make an HTTP request.
94
+ */
95
+ _RpcService_fetch.set(this, void 0);
96
+ /**
97
+ * The URL of the RPC endpoint.
98
+ */
99
+ _RpcService_endpointUrl.set(this, void 0);
100
+ /**
101
+ * A common set of options that the request options will extend.
102
+ */
103
+ _RpcService_fetchOptions.set(this, void 0);
104
+ /**
105
+ * The policy that wraps the request.
106
+ */
107
+ _RpcService_policy.set(this, void 0);
108
+ __classPrivateFieldSet(this, _RpcService_fetch, givenFetch, "f");
109
+ __classPrivateFieldSet(this, _RpcService_endpointUrl, getNormalizedEndpointUrl(endpointUrl), "f");
110
+ __classPrivateFieldSet(this, _RpcService_fetchOptions, __classPrivateFieldGet(this, _RpcService_instances, "m", _RpcService_getDefaultFetchOptions).call(this, __classPrivateFieldGet(this, _RpcService_endpointUrl, "f"), fetchOptions, givenBtoa), "f");
111
+ const policy = (0, controller_utils_1.createServicePolicy)({
112
+ maxRetries: 4,
113
+ maxConsecutiveFailures: 15,
114
+ retryFilterPolicy: (0, controller_utils_1.handleWhen)((error) => {
115
+ return (
116
+ // Ignore errors where the request failed to establish
117
+ isNetworkUnreachableError(error) ||
118
+ // Ignore server sent HTML error pages or truncated JSON responses
119
+ error.message.includes('not valid JSON') ||
120
+ // Ignore server overload errors
121
+ error.message.includes('Gateway timeout') ||
122
+ ((0, utils_1.hasProperty)(error, 'code') &&
123
+ (error.code === 'ETIMEDOUT' || error.code === 'ECONNRESET')));
124
+ }),
125
+ });
126
+ __classPrivateFieldSet(this, _RpcService_policy, policy, "f");
127
+ }
128
+ /**
129
+ * Listens for when the retry policy underlying this RPC service retries the
130
+ * request.
131
+ *
132
+ * @param listener - The callback to be called when the retry occurs.
133
+ * @returns What {@link ServicePolicy.onRetry} returns.
134
+ * @see {@link createServicePolicy}
135
+ */
136
+ onRetry(listener) {
137
+ return __classPrivateFieldGet(this, _RpcService_policy, "f").onRetry(listener);
138
+ }
139
+ /**
140
+ * Listens for when the circuit breaker policy underlying this RPC service
141
+ * detects a broken circuit.
142
+ *
143
+ * @param listener - The callback to be called when the circuit is broken.
144
+ * @returns What {@link ServicePolicy.onBreak} returns.
145
+ * @see {@link createServicePolicy}
146
+ */
147
+ onBreak(listener) {
148
+ return __classPrivateFieldGet(this, _RpcService_policy, "f").onBreak(listener);
149
+ }
150
+ /**
151
+ * Listens for when the policy underlying this RPC service detects a slow
152
+ * request.
153
+ *
154
+ * @param listener - The callback to be called when the request is slow.
155
+ * @returns What {@link ServicePolicy.onDegraded} returns.
156
+ * @see {@link createServicePolicy}
157
+ */
158
+ onDegraded(listener) {
159
+ return __classPrivateFieldGet(this, _RpcService_policy, "f").onDegraded(listener);
160
+ }
161
+ async request(jsonRpcRequest, fetchOptions = {}) {
162
+ const completeFetchOptions = __classPrivateFieldGet(this, _RpcService_instances, "m", _RpcService_getCompleteFetchOptions).call(this, jsonRpcRequest, fetchOptions);
163
+ return await __classPrivateFieldGet(this, _RpcService_instances, "m", _RpcService_executePolicy).call(this, jsonRpcRequest, completeFetchOptions);
164
+ }
165
+ }
166
+ exports.RpcService = RpcService;
167
+ _RpcService_fetch = new WeakMap(), _RpcService_endpointUrl = new WeakMap(), _RpcService_fetchOptions = new WeakMap(), _RpcService_policy = new WeakMap(), _RpcService_instances = new WeakSet(), _RpcService_getDefaultFetchOptions = function _RpcService_getDefaultFetchOptions(endpointUrl, fetchOptions, givenBtoa) {
168
+ if (endpointUrl.username && endpointUrl.password) {
169
+ const authString = `${endpointUrl.username}:${endpointUrl.password}`;
170
+ const encodedCredentials = givenBtoa(authString);
171
+ return (0, deepmerge_1.default)(fetchOptions, {
172
+ headers: { Authorization: `Basic ${encodedCredentials}` },
173
+ });
174
+ }
175
+ return fetchOptions;
176
+ }, _RpcService_getCompleteFetchOptions = function _RpcService_getCompleteFetchOptions(jsonRpcRequest, fetchOptions) {
177
+ const defaultOptions = {
178
+ method: 'POST',
179
+ headers: {
180
+ Accept: 'application/json',
181
+ 'Content-Type': 'application/json',
182
+ },
183
+ };
184
+ const mergedOptions = (0, deepmerge_1.default)(defaultOptions, (0, deepmerge_1.default)(__classPrivateFieldGet(this, _RpcService_fetchOptions, "f"), fetchOptions));
185
+ const { id, jsonrpc, method, params } = jsonRpcRequest;
186
+ const body = JSON.stringify({
187
+ id,
188
+ jsonrpc,
189
+ method,
190
+ params,
191
+ });
192
+ return { ...mergedOptions, body };
193
+ }, _RpcService_executePolicy =
194
+ /**
195
+ * Makes the request using the Cockatiel policy that this service creates.
196
+ *
197
+ * @param jsonRpcRequest - The JSON-RPC request to send to the endpoint.
198
+ * @param fetchOptions - The options for `fetch`; will be combined with the
199
+ * fetch options passed to the constructor
200
+ * @returns The decoded JSON-RPC response from the endpoint.
201
+ * @throws A "method not found" error if the response status is 405.
202
+ * @throws A rate limiting error if the response HTTP status is 429.
203
+ * @throws A timeout error if the response HTTP status is 503 or 504.
204
+ * @throws A generic error if the response HTTP status is not 2xx but also not
205
+ * 405, 429, 503, or 504.
206
+ */
207
+ async function _RpcService_executePolicy(jsonRpcRequest, fetchOptions) {
208
+ return await __classPrivateFieldGet(this, _RpcService_policy, "f").execute(async () => {
209
+ const response = await __classPrivateFieldGet(this, _RpcService_fetch, "f").call(this, __classPrivateFieldGet(this, _RpcService_endpointUrl, "f"), fetchOptions);
210
+ if (response.status === 405) {
211
+ throw rpc_errors_1.rpcErrors.methodNotFound();
212
+ }
213
+ if (response.status === 429) {
214
+ throw rpc_errors_1.rpcErrors.internal({ message: 'Request is being rate limited.' });
215
+ }
216
+ if (response.status === 503 || response.status === 504) {
217
+ throw rpc_errors_1.rpcErrors.internal({
218
+ message: 'Gateway timeout. The request took too long to process. This can happen when querying logs over too wide a block range.',
219
+ });
220
+ }
221
+ const text = await response.text();
222
+ if (jsonRpcRequest.method === 'eth_getBlockByNumber' &&
223
+ text === 'Not Found') {
224
+ return {
225
+ id: jsonRpcRequest.id,
226
+ jsonrpc: jsonRpcRequest.jsonrpc,
227
+ result: null,
228
+ };
229
+ }
230
+ // Type annotation: We assume that if this response is valid JSON, it's a
231
+ // valid JSON-RPC response.
232
+ let json;
233
+ try {
234
+ json = JSON.parse(text);
235
+ }
236
+ catch (error) {
237
+ if (error instanceof SyntaxError) {
238
+ throw rpc_errors_1.rpcErrors.internal({
239
+ message: 'Could not parse response as it is not valid JSON',
240
+ data: text,
241
+ });
242
+ }
243
+ else {
244
+ throw error;
245
+ }
246
+ }
247
+ if (!response.ok) {
248
+ throw rpc_errors_1.rpcErrors.internal({
249
+ message: `Non-200 status code: '${response.status}'`,
250
+ data: json,
251
+ });
252
+ }
253
+ return json;
254
+ });
255
+ };
256
+ //# sourceMappingURL=rpc-service.cjs.map
@@ -0,0 +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 { createServicePolicy, handleWhen } 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 { 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 * 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 encode 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 */\n constructor({\n fetch: givenFetch,\n btoa: givenBtoa,\n endpointUrl,\n fetchOptions = {},\n }: {\n fetch: typeof fetch;\n btoa: typeof btoa;\n endpointUrl: URL | string;\n fetchOptions?: FetchOptions;\n }) {\n this.#fetch = givenFetch;\n this.#endpointUrl = getNormalizedEndpointUrl(endpointUrl);\n this.#fetchOptions = this.#getDefaultFetchOptions(\n this.#endpointUrl,\n fetchOptions,\n givenBtoa,\n );\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 retry policy underlying this RPC service retries the\n * 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(listener: Parameters<ServicePolicy['onRetry']>[0]) {\n return this.#policy.onRetry(listener);\n }\n\n /**\n * Listens for when the circuit breaker policy underlying this RPC service\n * detects a broken circuit.\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(listener: Parameters<ServicePolicy['onBreak']>[0]) {\n return this.#policy.onBreak(listener);\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(listener: Parameters<ServicePolicy['onDegraded']>[0]) {\n return this.#policy.onDegraded(listener);\n }\n\n /**\n * Makes a request to the RPC endpoint.\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.\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 return await this.#executePolicy<Params, Result>(\n jsonRpcRequest,\n completeFetchOptions,\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"]}
@@ -0,0 +1,121 @@
1
+ import type { ServicePolicy } from "@metamask/controller-utils";
2
+ import type { JsonRpcRequest } from "@metamask/utils";
3
+ import { type Json, type JsonRpcParams, type JsonRpcResponse } from "@metamask/utils";
4
+ import type { AbstractRpcService } from "./abstract-rpc-service.cjs";
5
+ import type { FetchOptions } from "./shared.cjs";
6
+ /**
7
+ * The list of error messages that represent a failure to reach the network.
8
+ *
9
+ * This list was derived from Sindre Sorhus's `is-network-error` package:
10
+ * <https://github.com/sindresorhus/is-network-error/blob/7bbfa8be9482ce1427a21fbff60e3ee1650dd091/index.js>
11
+ */
12
+ export declare const NETWORK_UNREACHABLE_ERRORS: Set<string>;
13
+ /**
14
+ * Determines whether the given error represents a failure to reach the network
15
+ * after request parameters have been validated.
16
+ *
17
+ * This is somewhat difficult to verify because JavaScript engines (and in
18
+ * some cases libraries) produce slightly different error messages for this
19
+ * particular scenario, and we need to account for this.
20
+ *
21
+ * @param error - The error.
22
+ * @returns True if the error indicates that the network is unreachable, and
23
+ * false otherwise.
24
+ */
25
+ export default function isNetworkUnreachableError(error: unknown): boolean;
26
+ /**
27
+ * This class is responsible for making a request to an endpoint that implements
28
+ * the JSON-RPC protocol. It is designed to gracefully handle network and server
29
+ * failures, retrying requests using exponential backoff. It also offers a hook
30
+ * which can used to respond to slow requests.
31
+ */
32
+ export declare class RpcService implements AbstractRpcService {
33
+ #private;
34
+ /**
35
+ * Constructs a new RpcService object.
36
+ *
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 encode 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
+ */
49
+ constructor({ fetch: givenFetch, btoa: givenBtoa, endpointUrl, fetchOptions, }: {
50
+ fetch: typeof fetch;
51
+ btoa: typeof btoa;
52
+ endpointUrl: URL | string;
53
+ fetchOptions?: FetchOptions;
54
+ });
55
+ /**
56
+ * Listens for when the retry policy underlying this RPC service retries the
57
+ * request.
58
+ *
59
+ * @param listener - The callback to be called when the retry occurs.
60
+ * @returns What {@link ServicePolicy.onRetry} returns.
61
+ * @see {@link createServicePolicy}
62
+ */
63
+ onRetry(listener: Parameters<ServicePolicy['onRetry']>[0]): import("cockatiel").IDisposable;
64
+ /**
65
+ * Listens for when the circuit breaker policy underlying this RPC service
66
+ * detects a broken circuit.
67
+ *
68
+ * @param listener - The callback to be called when the circuit is broken.
69
+ * @returns What {@link ServicePolicy.onBreak} returns.
70
+ * @see {@link createServicePolicy}
71
+ */
72
+ onBreak(listener: Parameters<ServicePolicy['onBreak']>[0]): import("cockatiel").IDisposable;
73
+ /**
74
+ * Listens for when the policy underlying this RPC service detects a slow
75
+ * request.
76
+ *
77
+ * @param listener - The callback to be called when the request is slow.
78
+ * @returns What {@link ServicePolicy.onDegraded} returns.
79
+ * @see {@link createServicePolicy}
80
+ */
81
+ onDegraded(listener: Parameters<ServicePolicy['onDegraded']>[0]): void;
82
+ /**
83
+ * Makes a request to the RPC endpoint.
84
+ *
85
+ * This overload is specifically designed for `eth_getBlockByNumber`, which
86
+ * can return a `result` of `null` despite an expected `Result` being
87
+ * provided.
88
+ *
89
+ * @param jsonRpcRequest - The JSON-RPC request to send to the endpoint.
90
+ * @param fetchOptions - An options bag for {@link fetch} which further
91
+ * specifies the request.
92
+ * @returns The decoded JSON-RPC response from the endpoint.
93
+ * @throws A "method not found" error if the response status is 405.
94
+ * @throws A rate limiting error if the response HTTP status is 429.
95
+ * @throws A timeout error if the response HTTP status is 503 or 504.
96
+ * @throws A generic error if the response HTTP status is not 2xx but also not
97
+ * 405, 429, 503, or 504.
98
+ */
99
+ request<Params extends JsonRpcParams, Result extends Json>(jsonRpcRequest: JsonRpcRequest<Params> & {
100
+ method: 'eth_getBlockByNumber';
101
+ }, fetchOptions?: FetchOptions): Promise<JsonRpcResponse<Result> | JsonRpcResponse<null>>;
102
+ /**
103
+ * Makes a request to the RPC endpoint.
104
+ *
105
+ * This overload is designed for all RPC methods except for
106
+ * `eth_getBlockByNumber`, which are expected to return a `result` of the
107
+ * expected `Result`.
108
+ *
109
+ * @param jsonRpcRequest - The JSON-RPC request to send to the endpoint.
110
+ * @param fetchOptions - An options bag for {@link fetch} which further
111
+ * specifies the request.
112
+ * @returns The decoded JSON-RPC response from the endpoint.
113
+ * @throws A "method not found" error if the response status is 405.
114
+ * @throws A rate limiting error if the response HTTP status is 429.
115
+ * @throws A timeout error if the response HTTP status is 503 or 504.
116
+ * @throws A generic error if the response HTTP status is not 2xx but also not
117
+ * 405, 429, 503, or 504.
118
+ */
119
+ request<Params extends JsonRpcParams, Result extends Json>(jsonRpcRequest: JsonRpcRequest<Params>, fetchOptions?: FetchOptions): Promise<JsonRpcResponse<Result>>;
120
+ }
121
+ //# sourceMappingURL=rpc-service.d.cts.map
@@ -0,0 +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;AAGhE,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,YAAY,EAAE,qBAAiB;AAE7C;;;;;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;;IAqBnD;;;;;;;;;;;;;;OAcG;gBACS,EACV,KAAK,EAAE,UAAU,EACjB,IAAI,EAAE,SAAS,EACf,WAAW,EACX,YAAiB,GAClB,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;KAC7B;IA4BD;;;;;;;OAOG;IACH,OAAO,CAAC,QAAQ,EAAE,UAAU,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IAIzD;;;;;;;OAOG;IACH,OAAO,CAAC,QAAQ,EAAE,UAAU,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IAIzD;;;;;;;OAOG;IACH,UAAU,CAAC,QAAQ,EAAE,UAAU,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;IAI/D;;;;;;;;;;;;;;;;OAgBG;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;;;;;;;;;;;;;;;;OAgBG;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;CA6JpC"}
@@ -0,0 +1,121 @@
1
+ import type { ServicePolicy } from "@metamask/controller-utils";
2
+ import type { JsonRpcRequest } from "@metamask/utils";
3
+ import { type Json, type JsonRpcParams, type JsonRpcResponse } from "@metamask/utils";
4
+ import type { AbstractRpcService } from "./abstract-rpc-service.mjs";
5
+ import type { FetchOptions } from "./shared.mjs";
6
+ /**
7
+ * The list of error messages that represent a failure to reach the network.
8
+ *
9
+ * This list was derived from Sindre Sorhus's `is-network-error` package:
10
+ * <https://github.com/sindresorhus/is-network-error/blob/7bbfa8be9482ce1427a21fbff60e3ee1650dd091/index.js>
11
+ */
12
+ export declare const NETWORK_UNREACHABLE_ERRORS: Set<string>;
13
+ /**
14
+ * Determines whether the given error represents a failure to reach the network
15
+ * after request parameters have been validated.
16
+ *
17
+ * This is somewhat difficult to verify because JavaScript engines (and in
18
+ * some cases libraries) produce slightly different error messages for this
19
+ * particular scenario, and we need to account for this.
20
+ *
21
+ * @param error - The error.
22
+ * @returns True if the error indicates that the network is unreachable, and
23
+ * false otherwise.
24
+ */
25
+ export default function isNetworkUnreachableError(error: unknown): boolean;
26
+ /**
27
+ * This class is responsible for making a request to an endpoint that implements
28
+ * the JSON-RPC protocol. It is designed to gracefully handle network and server
29
+ * failures, retrying requests using exponential backoff. It also offers a hook
30
+ * which can used to respond to slow requests.
31
+ */
32
+ export declare class RpcService implements AbstractRpcService {
33
+ #private;
34
+ /**
35
+ * Constructs a new RpcService object.
36
+ *
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 encode 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
+ */
49
+ constructor({ fetch: givenFetch, btoa: givenBtoa, endpointUrl, fetchOptions, }: {
50
+ fetch: typeof fetch;
51
+ btoa: typeof btoa;
52
+ endpointUrl: URL | string;
53
+ fetchOptions?: FetchOptions;
54
+ });
55
+ /**
56
+ * Listens for when the retry policy underlying this RPC service retries the
57
+ * request.
58
+ *
59
+ * @param listener - The callback to be called when the retry occurs.
60
+ * @returns What {@link ServicePolicy.onRetry} returns.
61
+ * @see {@link createServicePolicy}
62
+ */
63
+ onRetry(listener: Parameters<ServicePolicy['onRetry']>[0]): import("cockatiel").IDisposable;
64
+ /**
65
+ * Listens for when the circuit breaker policy underlying this RPC service
66
+ * detects a broken circuit.
67
+ *
68
+ * @param listener - The callback to be called when the circuit is broken.
69
+ * @returns What {@link ServicePolicy.onBreak} returns.
70
+ * @see {@link createServicePolicy}
71
+ */
72
+ onBreak(listener: Parameters<ServicePolicy['onBreak']>[0]): import("cockatiel").IDisposable;
73
+ /**
74
+ * Listens for when the policy underlying this RPC service detects a slow
75
+ * request.
76
+ *
77
+ * @param listener - The callback to be called when the request is slow.
78
+ * @returns What {@link ServicePolicy.onDegraded} returns.
79
+ * @see {@link createServicePolicy}
80
+ */
81
+ onDegraded(listener: Parameters<ServicePolicy['onDegraded']>[0]): void;
82
+ /**
83
+ * Makes a request to the RPC endpoint.
84
+ *
85
+ * This overload is specifically designed for `eth_getBlockByNumber`, which
86
+ * can return a `result` of `null` despite an expected `Result` being
87
+ * provided.
88
+ *
89
+ * @param jsonRpcRequest - The JSON-RPC request to send to the endpoint.
90
+ * @param fetchOptions - An options bag for {@link fetch} which further
91
+ * specifies the request.
92
+ * @returns The decoded JSON-RPC response from the endpoint.
93
+ * @throws A "method not found" error if the response status is 405.
94
+ * @throws A rate limiting error if the response HTTP status is 429.
95
+ * @throws A timeout error if the response HTTP status is 503 or 504.
96
+ * @throws A generic error if the response HTTP status is not 2xx but also not
97
+ * 405, 429, 503, or 504.
98
+ */
99
+ request<Params extends JsonRpcParams, Result extends Json>(jsonRpcRequest: JsonRpcRequest<Params> & {
100
+ method: 'eth_getBlockByNumber';
101
+ }, fetchOptions?: FetchOptions): Promise<JsonRpcResponse<Result> | JsonRpcResponse<null>>;
102
+ /**
103
+ * Makes a request to the RPC endpoint.
104
+ *
105
+ * This overload is designed for all RPC methods except for
106
+ * `eth_getBlockByNumber`, which are expected to return a `result` of the
107
+ * expected `Result`.
108
+ *
109
+ * @param jsonRpcRequest - The JSON-RPC request to send to the endpoint.
110
+ * @param fetchOptions - An options bag for {@link fetch} which further
111
+ * specifies the request.
112
+ * @returns The decoded JSON-RPC response from the endpoint.
113
+ * @throws A "method not found" error if the response status is 405.
114
+ * @throws A rate limiting error if the response HTTP status is 429.
115
+ * @throws A timeout error if the response HTTP status is 503 or 504.
116
+ * @throws A generic error if the response HTTP status is not 2xx but also not
117
+ * 405, 429, 503, or 504.
118
+ */
119
+ request<Params extends JsonRpcParams, Result extends Json>(jsonRpcRequest: JsonRpcRequest<Params>, fetchOptions?: FetchOptions): Promise<JsonRpcResponse<Result>>;
120
+ }
121
+ //# sourceMappingURL=rpc-service.d.mts.map
@@ -0,0 +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;AAGhE,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,YAAY,EAAE,qBAAiB;AAE7C;;;;;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;;IAqBnD;;;;;;;;;;;;;;OAcG;gBACS,EACV,KAAK,EAAE,UAAU,EACjB,IAAI,EAAE,SAAS,EACf,WAAW,EACX,YAAiB,GAClB,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;KAC7B;IA4BD;;;;;;;OAOG;IACH,OAAO,CAAC,QAAQ,EAAE,UAAU,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IAIzD;;;;;;;OAOG;IACH,OAAO,CAAC,QAAQ,EAAE,UAAU,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IAIzD;;;;;;;OAOG;IACH,UAAU,CAAC,QAAQ,EAAE,UAAU,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;IAI/D;;;;;;;;;;;;;;;;OAgBG;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;;;;;;;;;;;;;;;;OAgBG;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;CA6JpC"}
@@ -0,0 +1,255 @@
1
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
2
+ if (kind === "m") throw new TypeError("Private method is not writable");
3
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
4
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
5
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
6
+ };
7
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
8
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
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
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
+ };
12
+ var _RpcService_instances, _RpcService_fetch, _RpcService_endpointUrl, _RpcService_fetchOptions, _RpcService_policy, _RpcService_getDefaultFetchOptions, _RpcService_getCompleteFetchOptions, _RpcService_executePolicy;
13
+ function $importDefault(module) {
14
+ if (module?.__esModule) {
15
+ return module.default;
16
+ }
17
+ return module;
18
+ }
19
+ import { createServicePolicy, handleWhen } from "@metamask/controller-utils";
20
+ import { rpcErrors } from "@metamask/rpc-errors";
21
+ import { hasProperty } from "@metamask/utils";
22
+ import $deepmerge from "deepmerge";
23
+ const deepmerge = $importDefault($deepmerge);
24
+ /**
25
+ * The list of error messages that represent a failure to reach the network.
26
+ *
27
+ * This list was derived from Sindre Sorhus's `is-network-error` package:
28
+ * <https://github.com/sindresorhus/is-network-error/blob/7bbfa8be9482ce1427a21fbff60e3ee1650dd091/index.js>
29
+ */
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
+ ]);
40
+ /**
41
+ * Determines whether the given error represents a failure to reach the network
42
+ * after request parameters have been validated.
43
+ *
44
+ * This is somewhat difficult to verify because JavaScript engines (and in
45
+ * some cases libraries) produce slightly different error messages for this
46
+ * particular scenario, and we need to account for this.
47
+ *
48
+ * @param error - The error.
49
+ * @returns True if the error indicates that the network is unreachable, and
50
+ * false otherwise.
51
+ */
52
+ export default function isNetworkUnreachableError(error) {
53
+ return (error instanceof TypeError && NETWORK_UNREACHABLE_ERRORS.has(error.message));
54
+ }
55
+ /**
56
+ * Guarantees a URL, even given a string. This is useful for checking components
57
+ * of that URL.
58
+ *
59
+ * @param endpointUrlOrUrlString - Either a URL object or a string that
60
+ * represents the URL of an endpoint.
61
+ * @returns A URL object.
62
+ */
63
+ function getNormalizedEndpointUrl(endpointUrlOrUrlString) {
64
+ return endpointUrlOrUrlString instanceof URL
65
+ ? endpointUrlOrUrlString
66
+ : new URL(endpointUrlOrUrlString);
67
+ }
68
+ /**
69
+ * This class is responsible for making a request to an endpoint that implements
70
+ * the JSON-RPC protocol. It is designed to gracefully handle network and server
71
+ * failures, retrying requests using exponential backoff. It also offers a hook
72
+ * which can used to respond to slow requests.
73
+ */
74
+ export class RpcService {
75
+ /**
76
+ * Constructs a new RpcService object.
77
+ *
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 encode 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
+ */
90
+ constructor({ fetch: givenFetch, btoa: givenBtoa, endpointUrl, fetchOptions = {}, }) {
91
+ _RpcService_instances.add(this);
92
+ /**
93
+ * The function used to make an HTTP request.
94
+ */
95
+ _RpcService_fetch.set(this, void 0);
96
+ /**
97
+ * The URL of the RPC endpoint.
98
+ */
99
+ _RpcService_endpointUrl.set(this, void 0);
100
+ /**
101
+ * A common set of options that the request options will extend.
102
+ */
103
+ _RpcService_fetchOptions.set(this, void 0);
104
+ /**
105
+ * The policy that wraps the request.
106
+ */
107
+ _RpcService_policy.set(this, void 0);
108
+ __classPrivateFieldSet(this, _RpcService_fetch, givenFetch, "f");
109
+ __classPrivateFieldSet(this, _RpcService_endpointUrl, getNormalizedEndpointUrl(endpointUrl), "f");
110
+ __classPrivateFieldSet(this, _RpcService_fetchOptions, __classPrivateFieldGet(this, _RpcService_instances, "m", _RpcService_getDefaultFetchOptions).call(this, __classPrivateFieldGet(this, _RpcService_endpointUrl, "f"), fetchOptions, givenBtoa), "f");
111
+ const policy = createServicePolicy({
112
+ maxRetries: 4,
113
+ maxConsecutiveFailures: 15,
114
+ retryFilterPolicy: handleWhen((error) => {
115
+ return (
116
+ // Ignore errors where the request failed to establish
117
+ isNetworkUnreachableError(error) ||
118
+ // Ignore server sent HTML error pages or truncated JSON responses
119
+ error.message.includes('not valid JSON') ||
120
+ // Ignore server overload errors
121
+ error.message.includes('Gateway timeout') ||
122
+ (hasProperty(error, 'code') &&
123
+ (error.code === 'ETIMEDOUT' || error.code === 'ECONNRESET')));
124
+ }),
125
+ });
126
+ __classPrivateFieldSet(this, _RpcService_policy, policy, "f");
127
+ }
128
+ /**
129
+ * Listens for when the retry policy underlying this RPC service retries the
130
+ * request.
131
+ *
132
+ * @param listener - The callback to be called when the retry occurs.
133
+ * @returns What {@link ServicePolicy.onRetry} returns.
134
+ * @see {@link createServicePolicy}
135
+ */
136
+ onRetry(listener) {
137
+ return __classPrivateFieldGet(this, _RpcService_policy, "f").onRetry(listener);
138
+ }
139
+ /**
140
+ * Listens for when the circuit breaker policy underlying this RPC service
141
+ * detects a broken circuit.
142
+ *
143
+ * @param listener - The callback to be called when the circuit is broken.
144
+ * @returns What {@link ServicePolicy.onBreak} returns.
145
+ * @see {@link createServicePolicy}
146
+ */
147
+ onBreak(listener) {
148
+ return __classPrivateFieldGet(this, _RpcService_policy, "f").onBreak(listener);
149
+ }
150
+ /**
151
+ * Listens for when the policy underlying this RPC service detects a slow
152
+ * request.
153
+ *
154
+ * @param listener - The callback to be called when the request is slow.
155
+ * @returns What {@link ServicePolicy.onDegraded} returns.
156
+ * @see {@link createServicePolicy}
157
+ */
158
+ onDegraded(listener) {
159
+ return __classPrivateFieldGet(this, _RpcService_policy, "f").onDegraded(listener);
160
+ }
161
+ async request(jsonRpcRequest, fetchOptions = {}) {
162
+ const completeFetchOptions = __classPrivateFieldGet(this, _RpcService_instances, "m", _RpcService_getCompleteFetchOptions).call(this, jsonRpcRequest, fetchOptions);
163
+ return await __classPrivateFieldGet(this, _RpcService_instances, "m", _RpcService_executePolicy).call(this, jsonRpcRequest, completeFetchOptions);
164
+ }
165
+ }
166
+ _RpcService_fetch = new WeakMap(), _RpcService_endpointUrl = new WeakMap(), _RpcService_fetchOptions = new WeakMap(), _RpcService_policy = new WeakMap(), _RpcService_instances = new WeakSet(), _RpcService_getDefaultFetchOptions = function _RpcService_getDefaultFetchOptions(endpointUrl, fetchOptions, givenBtoa) {
167
+ if (endpointUrl.username && endpointUrl.password) {
168
+ const authString = `${endpointUrl.username}:${endpointUrl.password}`;
169
+ const encodedCredentials = givenBtoa(authString);
170
+ return deepmerge(fetchOptions, {
171
+ headers: { Authorization: `Basic ${encodedCredentials}` },
172
+ });
173
+ }
174
+ return fetchOptions;
175
+ }, _RpcService_getCompleteFetchOptions = function _RpcService_getCompleteFetchOptions(jsonRpcRequest, fetchOptions) {
176
+ const defaultOptions = {
177
+ method: 'POST',
178
+ headers: {
179
+ Accept: 'application/json',
180
+ 'Content-Type': 'application/json',
181
+ },
182
+ };
183
+ const mergedOptions = deepmerge(defaultOptions, deepmerge(__classPrivateFieldGet(this, _RpcService_fetchOptions, "f"), fetchOptions));
184
+ const { id, jsonrpc, method, params } = jsonRpcRequest;
185
+ const body = JSON.stringify({
186
+ id,
187
+ jsonrpc,
188
+ method,
189
+ params,
190
+ });
191
+ return { ...mergedOptions, body };
192
+ }, _RpcService_executePolicy =
193
+ /**
194
+ * Makes the request using the Cockatiel policy that this service creates.
195
+ *
196
+ * @param jsonRpcRequest - The JSON-RPC request to send to the endpoint.
197
+ * @param fetchOptions - The options for `fetch`; will be combined with the
198
+ * fetch options passed to the constructor
199
+ * @returns The decoded JSON-RPC response from the endpoint.
200
+ * @throws A "method not found" error if the response status is 405.
201
+ * @throws A rate limiting error if the response HTTP status is 429.
202
+ * @throws A timeout error if the response HTTP status is 503 or 504.
203
+ * @throws A generic error if the response HTTP status is not 2xx but also not
204
+ * 405, 429, 503, or 504.
205
+ */
206
+ async function _RpcService_executePolicy(jsonRpcRequest, fetchOptions) {
207
+ return await __classPrivateFieldGet(this, _RpcService_policy, "f").execute(async () => {
208
+ const response = await __classPrivateFieldGet(this, _RpcService_fetch, "f").call(this, __classPrivateFieldGet(this, _RpcService_endpointUrl, "f"), fetchOptions);
209
+ if (response.status === 405) {
210
+ throw rpcErrors.methodNotFound();
211
+ }
212
+ if (response.status === 429) {
213
+ throw rpcErrors.internal({ message: 'Request is being rate limited.' });
214
+ }
215
+ if (response.status === 503 || response.status === 504) {
216
+ throw rpcErrors.internal({
217
+ message: 'Gateway timeout. The request took too long to process. This can happen when querying logs over too wide a block range.',
218
+ });
219
+ }
220
+ const text = await response.text();
221
+ if (jsonRpcRequest.method === 'eth_getBlockByNumber' &&
222
+ text === 'Not Found') {
223
+ return {
224
+ id: jsonRpcRequest.id,
225
+ jsonrpc: jsonRpcRequest.jsonrpc,
226
+ result: null,
227
+ };
228
+ }
229
+ // Type annotation: We assume that if this response is valid JSON, it's a
230
+ // valid JSON-RPC response.
231
+ let json;
232
+ try {
233
+ json = JSON.parse(text);
234
+ }
235
+ catch (error) {
236
+ if (error instanceof SyntaxError) {
237
+ throw rpcErrors.internal({
238
+ message: 'Could not parse response as it is not valid JSON',
239
+ data: text,
240
+ });
241
+ }
242
+ else {
243
+ throw error;
244
+ }
245
+ }
246
+ if (!response.ok) {
247
+ throw rpcErrors.internal({
248
+ message: `Non-200 status code: '${response.status}'`,
249
+ data: json,
250
+ });
251
+ }
252
+ return json;
253
+ });
254
+ };
255
+ //# sourceMappingURL=rpc-service.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rpc-service.mjs","sourceRoot":"","sources":["../../src/rpc-service/rpc-service.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ServicePolicy } from '@metamask/controller-utils';\nimport { createServicePolicy, handleWhen } 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 { 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 * 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 encode 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 */\n constructor({\n fetch: givenFetch,\n btoa: givenBtoa,\n endpointUrl,\n fetchOptions = {},\n }: {\n fetch: typeof fetch;\n btoa: typeof btoa;\n endpointUrl: URL | string;\n fetchOptions?: FetchOptions;\n }) {\n this.#fetch = givenFetch;\n this.#endpointUrl = getNormalizedEndpointUrl(endpointUrl);\n this.#fetchOptions = this.#getDefaultFetchOptions(\n this.#endpointUrl,\n fetchOptions,\n givenBtoa,\n );\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 retry policy underlying this RPC service retries the\n * 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(listener: Parameters<ServicePolicy['onRetry']>[0]) {\n return this.#policy.onRetry(listener);\n }\n\n /**\n * Listens for when the circuit breaker policy underlying this RPC service\n * detects a broken circuit.\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(listener: Parameters<ServicePolicy['onBreak']>[0]) {\n return this.#policy.onBreak(listener);\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(listener: Parameters<ServicePolicy['onDegraded']>[0]) {\n return this.#policy.onDegraded(listener);\n }\n\n /**\n * Makes a request to the RPC endpoint.\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.\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 return await this.#executePolicy<Params, Result>(\n jsonRpcRequest,\n completeFetchOptions,\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"]}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=shared.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.cjs","sourceRoot":"","sources":["../../src/rpc-service/shared.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * Equivalent to the built-in `FetchOptions` type, but renamed for clarity.\n */\nexport type FetchOptions = RequestInit;\n"]}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Equivalent to the built-in `FetchOptions` type, but renamed for clarity.
3
+ */
4
+ export type FetchOptions = RequestInit;
5
+ //# sourceMappingURL=shared.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.d.cts","sourceRoot":"","sources":["../../src/rpc-service/shared.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,WAAW,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Equivalent to the built-in `FetchOptions` type, but renamed for clarity.
3
+ */
4
+ export type FetchOptions = RequestInit;
5
+ //# sourceMappingURL=shared.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.d.mts","sourceRoot":"","sources":["../../src/rpc-service/shared.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,WAAW,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=shared.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.mjs","sourceRoot":"","sources":["../../src/rpc-service/shared.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * Equivalent to the built-in `FetchOptions` type, but renamed for clarity.\n */\nexport type FetchOptions = RequestInit;\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask-previews/network-controller",
3
- "version": "22.1.1-preview-bd04b248",
3
+ "version": "22.1.1-preview-3fc797ab",
4
4
  "description": "Provides an interface to the currently selected network via a MetaMask-compatible provider object",
5
5
  "keywords": [
6
6
  "MetaMask",