@metamask-previews/network-controller 36.0.0-preview-4f4c98e → 36.0.0-preview-5b293ee50
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.
- package/CHANGELOG.md +0 -5
- package/dist/NetworkController-method-action-types.cjs +7 -0
- package/dist/NetworkController-method-action-types.cjs.map +1 -0
- package/dist/{NetworkController-method-action-types.d.ts → NetworkController-method-action-types.d.cts} +2 -2
- package/dist/NetworkController-method-action-types.d.cts.map +1 -0
- package/dist/NetworkController-method-action-types.d.mts +268 -0
- package/dist/NetworkController-method-action-types.d.mts.map +1 -0
- package/dist/{NetworkController-method-action-types.js → NetworkController-method-action-types.mjs} +1 -1
- package/dist/NetworkController-method-action-types.mjs.map +1 -0
- package/dist/NetworkController.cjs +1599 -0
- package/dist/NetworkController.cjs.map +1 -0
- package/dist/{NetworkController.d.ts → NetworkController.d.cts} +29 -37
- package/dist/NetworkController.d.cts.map +1 -0
- package/dist/NetworkController.d.mts +956 -0
- package/dist/NetworkController.d.mts.map +1 -0
- package/dist/{NetworkController.js → NetworkController.mjs} +29 -20
- package/dist/NetworkController.mjs.map +1 -0
- package/dist/constants.cjs +46 -0
- package/dist/constants.cjs.map +1 -0
- package/dist/{constants.d.ts → constants.d.cts} +1 -1
- package/dist/constants.d.cts.map +1 -0
- package/dist/constants.d.mts +42 -0
- package/dist/constants.d.mts.map +1 -0
- package/dist/{constants.js → constants.mjs} +1 -1
- package/dist/constants.mjs.map +1 -0
- package/dist/create-auto-managed-network-client.cjs +149 -0
- package/dist/create-auto-managed-network-client.cjs.map +1 -0
- package/dist/{create-auto-managed-network-client.d.ts → create-auto-managed-network-client.d.cts} +7 -7
- package/dist/create-auto-managed-network-client.d.cts.map +1 -0
- package/dist/create-auto-managed-network-client.d.mts +74 -0
- package/dist/create-auto-managed-network-client.d.mts.map +1 -0
- package/dist/{create-auto-managed-network-client.js → create-auto-managed-network-client.mjs} +2 -2
- package/dist/create-auto-managed-network-client.mjs.map +1 -0
- package/dist/create-network-client.cjs +439 -0
- package/dist/create-network-client.cjs.map +1 -0
- package/dist/{create-network-client.d.ts → create-network-client.d.cts} +7 -7
- package/dist/create-network-client.d.cts.map +1 -0
- package/dist/create-network-client.d.mts +60 -0
- package/dist/create-network-client.d.mts.map +1 -0
- package/dist/{create-network-client.js → create-network-client.mjs} +14 -15
- package/dist/create-network-client.mjs.map +1 -0
- package/dist/index.cjs +31 -0
- package/dist/index.cjs.map +1 -0
- package/dist/{index.d.ts → index.d.cts} +16 -16
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +16 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +6 -0
- package/dist/index.mjs.map +1 -0
- package/dist/logger.cjs +7 -0
- package/dist/logger.cjs.map +1 -0
- package/dist/logger.d.cts +5 -0
- package/dist/logger.d.cts.map +1 -0
- package/dist/logger.d.mts +5 -0
- package/dist/logger.d.mts.map +1 -0
- package/dist/logger.mjs +4 -0
- package/dist/logger.mjs.map +1 -0
- package/dist/rpc-service/abstract-rpc-service.cjs +3 -0
- package/dist/rpc-service/abstract-rpc-service.cjs.map +1 -0
- package/dist/rpc-service/{abstract-rpc-service.d.ts → abstract-rpc-service.d.cts} +2 -2
- package/dist/rpc-service/abstract-rpc-service.d.cts.map +1 -0
- package/dist/rpc-service/abstract-rpc-service.d.mts +17 -0
- package/dist/rpc-service/abstract-rpc-service.d.mts.map +1 -0
- package/dist/rpc-service/abstract-rpc-service.mjs +2 -0
- package/dist/rpc-service/abstract-rpc-service.mjs.map +1 -0
- package/dist/rpc-service/rpc-service-chain.cjs +304 -0
- package/dist/rpc-service/rpc-service-chain.cjs.map +1 -0
- package/dist/rpc-service/{rpc-service-chain.d.ts → rpc-service-chain.d.cts} +6 -6
- package/dist/rpc-service/rpc-service-chain.d.cts.map +1 -0
- package/dist/rpc-service/rpc-service-chain.d.mts +169 -0
- package/dist/rpc-service/rpc-service-chain.d.mts.map +1 -0
- package/dist/rpc-service/{rpc-service-chain.js → rpc-service-chain.mjs} +4 -4
- package/dist/rpc-service/rpc-service-chain.mjs.map +1 -0
- package/dist/rpc-service/rpc-service-requestable.cjs +3 -0
- package/dist/rpc-service/rpc-service-requestable.cjs.map +1 -0
- package/dist/rpc-service/{rpc-service-requestable.d.ts → rpc-service-requestable.d.cts} +4 -4
- package/dist/rpc-service/rpc-service-requestable.d.cts.map +1 -0
- package/dist/rpc-service/rpc-service-requestable.d.mts +63 -0
- package/dist/rpc-service/rpc-service-requestable.d.mts.map +1 -0
- package/dist/rpc-service/rpc-service-requestable.mjs +2 -0
- package/dist/rpc-service/rpc-service-requestable.mjs.map +1 -0
- package/dist/rpc-service/rpc-service.cjs +540 -0
- package/dist/rpc-service/rpc-service.cjs.map +1 -0
- package/dist/rpc-service/{rpc-service.d.ts → rpc-service.d.cts} +6 -6
- package/dist/rpc-service/rpc-service.d.cts.map +1 -0
- package/dist/rpc-service/rpc-service.d.mts +247 -0
- package/dist/rpc-service/rpc-service.d.mts.map +1 -0
- package/dist/rpc-service/{rpc-service.js → rpc-service.mjs} +14 -6
- package/dist/rpc-service/rpc-service.mjs.map +1 -0
- package/dist/rpc-service/shared.cjs +3 -0
- package/dist/rpc-service/shared.cjs.map +1 -0
- package/dist/rpc-service/{shared.d.ts → shared.d.cts} +2 -2
- package/dist/rpc-service/shared.d.cts.map +1 -0
- package/dist/rpc-service/shared.d.mts +32 -0
- package/dist/rpc-service/shared.d.mts.map +1 -0
- package/dist/rpc-service/shared.mjs +2 -0
- package/dist/rpc-service/shared.mjs.map +1 -0
- package/dist/rpc-service-analytics.cjs +180 -0
- package/dist/rpc-service-analytics.cjs.map +1 -0
- package/dist/{rpc-service-analytics.d.ts → rpc-service-analytics.d.cts} +3 -3
- package/dist/rpc-service-analytics.d.cts.map +1 -0
- package/dist/rpc-service-analytics.d.mts +85 -0
- package/dist/rpc-service-analytics.d.mts.map +1 -0
- package/dist/{rpc-service-analytics.js → rpc-service-analytics.mjs} +4 -4
- package/dist/rpc-service-analytics.mjs.map +1 -0
- package/dist/selectors.cjs +16 -0
- package/dist/selectors.cjs.map +1 -0
- package/dist/{selectors.d.ts → selectors.d.cts} +2 -2
- package/dist/selectors.d.cts.map +1 -0
- package/dist/selectors.d.mts +22 -0
- package/dist/selectors.d.mts.map +1 -0
- package/dist/{selectors.js → selectors.mjs} +1 -1
- package/dist/selectors.mjs.map +1 -0
- package/dist/types.cjs +12 -0
- package/dist/types.cjs.map +1 -0
- package/dist/{types.d.ts → types.d.cts} +5 -5
- package/dist/types.d.cts.map +1 -0
- package/dist/types.d.mts +49 -0
- package/dist/types.d.mts.map +1 -0
- package/dist/{types.js → types.mjs} +1 -1
- package/dist/types.mjs.map +1 -0
- package/package.json +19 -15
- package/dist/NetworkController-method-action-types.d.ts.map +0 -1
- package/dist/NetworkController-method-action-types.js.map +0 -1
- package/dist/NetworkController.d.ts.map +0 -1
- package/dist/NetworkController.js.map +0 -1
- package/dist/constants.d.ts.map +0 -1
- package/dist/constants.js.map +0 -1
- package/dist/create-auto-managed-network-client.d.ts.map +0 -1
- package/dist/create-auto-managed-network-client.js.map +0 -1
- package/dist/create-network-client.d.ts.map +0 -1
- package/dist/create-network-client.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -6
- package/dist/index.js.map +0 -1
- package/dist/logger.d.ts +0 -4
- package/dist/logger.d.ts.map +0 -1
- package/dist/logger.js +0 -4
- package/dist/logger.js.map +0 -1
- package/dist/rpc-service/abstract-rpc-service.d.ts.map +0 -1
- package/dist/rpc-service/abstract-rpc-service.js +0 -2
- package/dist/rpc-service/abstract-rpc-service.js.map +0 -1
- package/dist/rpc-service/rpc-service-chain.d.ts.map +0 -1
- package/dist/rpc-service/rpc-service-chain.js.map +0 -1
- package/dist/rpc-service/rpc-service-requestable.d.ts.map +0 -1
- package/dist/rpc-service/rpc-service-requestable.js +0 -2
- package/dist/rpc-service/rpc-service-requestable.js.map +0 -1
- package/dist/rpc-service/rpc-service.d.ts.map +0 -1
- package/dist/rpc-service/rpc-service.js.map +0 -1
- package/dist/rpc-service/shared.d.ts.map +0 -1
- package/dist/rpc-service/shared.js +0 -2
- package/dist/rpc-service/shared.js.map +0 -1
- package/dist/rpc-service-analytics.d.ts.map +0 -1
- package/dist/rpc-service-analytics.js.map +0 -1
- package/dist/selectors.d.ts.map +0 -1
- package/dist/selectors.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rpc-service-requestable.cjs","sourceRoot":"","sources":["../../src/rpc-service/rpc-service-requestable.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 {\n CockatielEventToEventListenerWithData,\n ExcludeCockatielEventData,\n ExtendCockatielEventData,\n ExtractCockatielEventData,\n FetchOptions,\n} from './shared.js';\n\n/**\n * The interface for a service class responsible for making a request to a\n * target, whether that is a single RPC endpoint or an RPC endpoint in an RPC\n * service chain.\n *\n * @deprecated Don't use this interface (it will be removed in an upcoming major\n * version). If you need to take an \"RPC-service-like\" argument, it's best to\n * declare which properties you're interested in rather than accepting the\n * entire RPC service interface.\n */\nexport type RpcServiceRequestable = {\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: CockatielEventToEventListenerWithData<\n ServicePolicy['onRetry'],\n { endpointUrl: string }\n >,\n ): ReturnType<ServicePolicy['onRetry']>;\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: (\n data: ExcludeCockatielEventData<\n ExtendCockatielEventData<\n ExtractCockatielEventData<ServicePolicy['onBreak']>,\n { endpointUrl: string }\n >,\n 'isolated'\n >,\n ) => void,\n ): ReturnType<ServicePolicy['onBreak']>;\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: CockatielEventToEventListenerWithData<\n ServicePolicy['onDegraded'],\n { endpointUrl: string; rpcMethodName: string }\n >,\n ): ReturnType<ServicePolicy['onDegraded']>;\n\n /**\n * Listens for when the policy underlying this RPC service is available.\n *\n * @param listener - The callback to be called when the request is available.\n * @returns What {@link ServicePolicy.onDegraded} returns.\n * @see {@link createServicePolicy}\n */\n onAvailable(\n listener: CockatielEventToEventListenerWithData<\n ServicePolicy['onAvailable'],\n { endpointUrl: string }\n >,\n ): ReturnType<ServicePolicy['onAvailable']>;\n\n /**\n * Makes a request to the target.\n */\n request<Params extends JsonRpcParams, Result extends Json>(\n jsonRpcRequest: Readonly<JsonRpcRequest<Params>>,\n fetchOptions?: FetchOptions,\n ): Promise<JsonRpcResponse<Result | null>>;\n};\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { ServicePolicy } from
|
|
2
|
-
import type { Json, JsonRpcParams, JsonRpcRequest, JsonRpcResponse } from
|
|
3
|
-
import type { CockatielEventToEventListenerWithData, ExcludeCockatielEventData, ExtendCockatielEventData, ExtractCockatielEventData, FetchOptions } from
|
|
1
|
+
import type { ServicePolicy } from "@metamask/controller-utils";
|
|
2
|
+
import type { Json, JsonRpcParams, JsonRpcRequest, JsonRpcResponse } from "@metamask/utils";
|
|
3
|
+
import type { CockatielEventToEventListenerWithData, ExcludeCockatielEventData, ExtendCockatielEventData, ExtractCockatielEventData, FetchOptions } from "./shared.cjs";
|
|
4
4
|
/**
|
|
5
5
|
* The interface for a service class responsible for making a request to a
|
|
6
6
|
* target, whether that is a single RPC endpoint or an RPC endpoint in an RPC
|
|
@@ -60,4 +60,4 @@ export type RpcServiceRequestable = {
|
|
|
60
60
|
*/
|
|
61
61
|
request<Params extends JsonRpcParams, Result extends Json>(jsonRpcRequest: Readonly<JsonRpcRequest<Params>>, fetchOptions?: FetchOptions): Promise<JsonRpcResponse<Result | null>>;
|
|
62
62
|
};
|
|
63
|
-
//# sourceMappingURL=rpc-service-requestable.d.
|
|
63
|
+
//# sourceMappingURL=rpc-service-requestable.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rpc-service-requestable.d.cts","sourceRoot":"","sources":["../../src/rpc-service/rpc-service-requestable.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,EACV,qCAAqC,EACrC,yBAAyB,EACzB,wBAAwB,EACxB,yBAAyB,EACzB,YAAY,EACb,qBAAoB;AAErB;;;;;;;;;GASG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC;;;;;;OAMG;IACH,OAAO,CACL,QAAQ,EAAE,qCAAqC,CAC7C,aAAa,CAAC,SAAS,CAAC,EACxB;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,CACxB,GACA,UAAU,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC;IAExC;;;;;;;OAOG;IACH,OAAO,CACL,QAAQ,EAAE,CACR,IAAI,EAAE,yBAAyB,CAC7B,wBAAwB,CACtB,yBAAyB,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,EACnD;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,CACxB,EACD,UAAU,CACX,KACE,IAAI,GACR,UAAU,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC;IAExC;;;;;;;OAOG;IACH,UAAU,CACR,QAAQ,EAAE,qCAAqC,CAC7C,aAAa,CAAC,YAAY,CAAC,EAC3B;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAC/C,GACA,UAAU,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC;IAE3C;;;;;;OAMG;IACH,WAAW,CACT,QAAQ,EAAE,qCAAqC,CAC7C,aAAa,CAAC,aAAa,CAAC,EAC5B;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,CACxB,GACA,UAAU,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,CAAC;IAE5C;;OAEG;IACH,OAAO,CAAC,MAAM,SAAS,aAAa,EAAE,MAAM,SAAS,IAAI,EACvD,cAAc,EAAE,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,EAChD,YAAY,CAAC,EAAE,YAAY,GAC1B,OAAO,CAAC,eAAe,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;CAC5C,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { ServicePolicy } from "@metamask/controller-utils";
|
|
2
|
+
import type { Json, JsonRpcParams, JsonRpcRequest, JsonRpcResponse } from "@metamask/utils";
|
|
3
|
+
import type { CockatielEventToEventListenerWithData, ExcludeCockatielEventData, ExtendCockatielEventData, ExtractCockatielEventData, FetchOptions } from "./shared.mjs";
|
|
4
|
+
/**
|
|
5
|
+
* The interface for a service class responsible for making a request to a
|
|
6
|
+
* target, whether that is a single RPC endpoint or an RPC endpoint in an RPC
|
|
7
|
+
* service chain.
|
|
8
|
+
*
|
|
9
|
+
* @deprecated Don't use this interface (it will be removed in an upcoming major
|
|
10
|
+
* version). If you need to take an "RPC-service-like" argument, it's best to
|
|
11
|
+
* declare which properties you're interested in rather than accepting the
|
|
12
|
+
* entire RPC service interface.
|
|
13
|
+
*/
|
|
14
|
+
export type RpcServiceRequestable = {
|
|
15
|
+
/**
|
|
16
|
+
* Listens for when the RPC service retries the request.
|
|
17
|
+
*
|
|
18
|
+
* @param listener - The callback to be called when the retry occurs.
|
|
19
|
+
* @returns What {@link ServicePolicy.onRetry} returns.
|
|
20
|
+
* @see {@link createServicePolicy}
|
|
21
|
+
*/
|
|
22
|
+
onRetry(listener: CockatielEventToEventListenerWithData<ServicePolicy['onRetry'], {
|
|
23
|
+
endpointUrl: string;
|
|
24
|
+
}>): ReturnType<ServicePolicy['onRetry']>;
|
|
25
|
+
/**
|
|
26
|
+
* Listens for when the RPC service retries the request too many times in a
|
|
27
|
+
* row.
|
|
28
|
+
*
|
|
29
|
+
* @param listener - The callback to be called when the circuit is broken.
|
|
30
|
+
* @returns What {@link ServicePolicy.onBreak} returns.
|
|
31
|
+
* @see {@link createServicePolicy}
|
|
32
|
+
*/
|
|
33
|
+
onBreak(listener: (data: ExcludeCockatielEventData<ExtendCockatielEventData<ExtractCockatielEventData<ServicePolicy['onBreak']>, {
|
|
34
|
+
endpointUrl: string;
|
|
35
|
+
}>, 'isolated'>) => void): ReturnType<ServicePolicy['onBreak']>;
|
|
36
|
+
/**
|
|
37
|
+
* Listens for when the policy underlying this RPC service detects a slow
|
|
38
|
+
* request.
|
|
39
|
+
*
|
|
40
|
+
* @param listener - The callback to be called when the request is slow.
|
|
41
|
+
* @returns What {@link ServicePolicy.onDegraded} returns.
|
|
42
|
+
* @see {@link createServicePolicy}
|
|
43
|
+
*/
|
|
44
|
+
onDegraded(listener: CockatielEventToEventListenerWithData<ServicePolicy['onDegraded'], {
|
|
45
|
+
endpointUrl: string;
|
|
46
|
+
rpcMethodName: string;
|
|
47
|
+
}>): ReturnType<ServicePolicy['onDegraded']>;
|
|
48
|
+
/**
|
|
49
|
+
* Listens for when the policy underlying this RPC service is available.
|
|
50
|
+
*
|
|
51
|
+
* @param listener - The callback to be called when the request is available.
|
|
52
|
+
* @returns What {@link ServicePolicy.onDegraded} returns.
|
|
53
|
+
* @see {@link createServicePolicy}
|
|
54
|
+
*/
|
|
55
|
+
onAvailable(listener: CockatielEventToEventListenerWithData<ServicePolicy['onAvailable'], {
|
|
56
|
+
endpointUrl: string;
|
|
57
|
+
}>): ReturnType<ServicePolicy['onAvailable']>;
|
|
58
|
+
/**
|
|
59
|
+
* Makes a request to the target.
|
|
60
|
+
*/
|
|
61
|
+
request<Params extends JsonRpcParams, Result extends Json>(jsonRpcRequest: Readonly<JsonRpcRequest<Params>>, fetchOptions?: FetchOptions): Promise<JsonRpcResponse<Result | null>>;
|
|
62
|
+
};
|
|
63
|
+
//# sourceMappingURL=rpc-service-requestable.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rpc-service-requestable.d.mts","sourceRoot":"","sources":["../../src/rpc-service/rpc-service-requestable.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,EACV,qCAAqC,EACrC,yBAAyB,EACzB,wBAAwB,EACxB,yBAAyB,EACzB,YAAY,EACb,qBAAoB;AAErB;;;;;;;;;GASG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC;;;;;;OAMG;IACH,OAAO,CACL,QAAQ,EAAE,qCAAqC,CAC7C,aAAa,CAAC,SAAS,CAAC,EACxB;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,CACxB,GACA,UAAU,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC;IAExC;;;;;;;OAOG;IACH,OAAO,CACL,QAAQ,EAAE,CACR,IAAI,EAAE,yBAAyB,CAC7B,wBAAwB,CACtB,yBAAyB,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,EACnD;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,CACxB,EACD,UAAU,CACX,KACE,IAAI,GACR,UAAU,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC;IAExC;;;;;;;OAOG;IACH,UAAU,CACR,QAAQ,EAAE,qCAAqC,CAC7C,aAAa,CAAC,YAAY,CAAC,EAC3B;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAC/C,GACA,UAAU,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC;IAE3C;;;;;;OAMG;IACH,WAAW,CACT,QAAQ,EAAE,qCAAqC,CAC7C,aAAa,CAAC,aAAa,CAAC,EAC5B;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,CACxB,GACA,UAAU,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,CAAC;IAE5C;;OAEG;IACH,OAAO,CAAC,MAAM,SAAS,aAAa,EAAE,MAAM,SAAS,IAAI,EACvD,cAAc,EAAE,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,EAChD,YAAY,CAAC,EAAE,YAAY,GAC1B,OAAO,CAAC,eAAe,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;CAC5C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rpc-service-requestable.mjs","sourceRoot":"","sources":["../../src/rpc-service/rpc-service-requestable.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 {\n CockatielEventToEventListenerWithData,\n ExcludeCockatielEventData,\n ExtendCockatielEventData,\n ExtractCockatielEventData,\n FetchOptions,\n} from './shared.js';\n\n/**\n * The interface for a service class responsible for making a request to a\n * target, whether that is a single RPC endpoint or an RPC endpoint in an RPC\n * service chain.\n *\n * @deprecated Don't use this interface (it will be removed in an upcoming major\n * version). If you need to take an \"RPC-service-like\" argument, it's best to\n * declare which properties you're interested in rather than accepting the\n * entire RPC service interface.\n */\nexport type RpcServiceRequestable = {\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: CockatielEventToEventListenerWithData<\n ServicePolicy['onRetry'],\n { endpointUrl: string }\n >,\n ): ReturnType<ServicePolicy['onRetry']>;\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: (\n data: ExcludeCockatielEventData<\n ExtendCockatielEventData<\n ExtractCockatielEventData<ServicePolicy['onBreak']>,\n { endpointUrl: string }\n >,\n 'isolated'\n >,\n ) => void,\n ): ReturnType<ServicePolicy['onBreak']>;\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: CockatielEventToEventListenerWithData<\n ServicePolicy['onDegraded'],\n { endpointUrl: string; rpcMethodName: string }\n >,\n ): ReturnType<ServicePolicy['onDegraded']>;\n\n /**\n * Listens for when the policy underlying this RPC service is available.\n *\n * @param listener - The callback to be called when the request is available.\n * @returns What {@link ServicePolicy.onDegraded} returns.\n * @see {@link createServicePolicy}\n */\n onAvailable(\n listener: CockatielEventToEventListenerWithData<\n ServicePolicy['onAvailable'],\n { endpointUrl: string }\n >,\n ): ReturnType<ServicePolicy['onAvailable']>;\n\n /**\n * Makes a request to the target.\n */\n request<Params extends JsonRpcParams, Result extends Json>(\n jsonRpcRequest: Readonly<JsonRpcRequest<Params>>,\n fetchOptions?: FetchOptions,\n ): Promise<JsonRpcResponse<Result | null>>;\n};\n"]}
|
|
@@ -0,0 +1,540 @@
|
|
|
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_currentRpcMethodName, _RpcService_currentTraceId, _RpcService_fetch, _RpcService_fetchOptions, _RpcService_logger, _RpcService_policy, _RpcService_getDefaultFetchOptions, _RpcService_getCompleteFetchOptions, _RpcService_executeAndProcessRequest;
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.RpcService = exports.isConnectionResetError = exports.isTimeoutError = exports.isHttpServerError = exports.isJsonParseError = exports.isConnectionError = exports.CUSTOM_RPC_ERRORS = exports.CONNECTION_ERRORS = exports.DEFAULT_MAX_CONSECUTIVE_FAILURES = exports.DEFAULT_MAX_RETRIES = 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 cockatiel_1 = require("cockatiel");
|
|
23
|
+
const deepmerge_1 = __importDefault(require("deepmerge"));
|
|
24
|
+
const logger_js_1 = require("../logger.cjs");
|
|
25
|
+
const log = (0, logger_js_1.createModuleLogger)(logger_js_1.projectLogger, 'RpcService');
|
|
26
|
+
/**
|
|
27
|
+
* The maximum number of times that a failing service should be re-run before
|
|
28
|
+
* giving up.
|
|
29
|
+
*
|
|
30
|
+
* Note: This is not used in production and should be removed.
|
|
31
|
+
*/
|
|
32
|
+
exports.DEFAULT_MAX_RETRIES = 4;
|
|
33
|
+
/**
|
|
34
|
+
* The maximum number of times that the service is allowed to fail before
|
|
35
|
+
* pausing further retries. This is set to a value such that if given a
|
|
36
|
+
* service that continually fails, the policy needs to be executed 3 times
|
|
37
|
+
* before further retries are paused.
|
|
38
|
+
*/
|
|
39
|
+
exports.DEFAULT_MAX_CONSECUTIVE_FAILURES = (1 + exports.DEFAULT_MAX_RETRIES) * 3;
|
|
40
|
+
/**
|
|
41
|
+
* The list of error messages that represent a failure to connect to the network.
|
|
42
|
+
*
|
|
43
|
+
* This list was derived from Sindre Sorhus's `is-network-error` package:
|
|
44
|
+
* <https://github.com/sindresorhus/is-network-error/blob/7bbfa8be9482ce1427a21fbff60e3ee1650dd091/index.js>
|
|
45
|
+
*/
|
|
46
|
+
exports.CONNECTION_ERRORS = [
|
|
47
|
+
// Chrome
|
|
48
|
+
{
|
|
49
|
+
constructorName: 'TypeError',
|
|
50
|
+
pattern: /network error/u,
|
|
51
|
+
},
|
|
52
|
+
// Chrome
|
|
53
|
+
{
|
|
54
|
+
constructorName: 'TypeError',
|
|
55
|
+
pattern: /Failed to fetch/u,
|
|
56
|
+
},
|
|
57
|
+
// Firefox
|
|
58
|
+
{
|
|
59
|
+
constructorName: 'TypeError',
|
|
60
|
+
pattern: /NetworkError when attempting to fetch resource\./u,
|
|
61
|
+
},
|
|
62
|
+
// Safari 16
|
|
63
|
+
{
|
|
64
|
+
constructorName: 'TypeError',
|
|
65
|
+
pattern: /The Internet connection appears to be offline\./u,
|
|
66
|
+
},
|
|
67
|
+
// Safari 17+
|
|
68
|
+
{
|
|
69
|
+
constructorName: 'TypeError',
|
|
70
|
+
pattern: /Load failed/u,
|
|
71
|
+
},
|
|
72
|
+
// `cross-fetch`
|
|
73
|
+
{
|
|
74
|
+
constructorName: 'TypeError',
|
|
75
|
+
pattern: /Network request failed/u,
|
|
76
|
+
},
|
|
77
|
+
// `node-fetch`
|
|
78
|
+
{
|
|
79
|
+
constructorName: 'FetchError',
|
|
80
|
+
pattern: /request to (.+) failed/u,
|
|
81
|
+
},
|
|
82
|
+
// Undici (Node.js)
|
|
83
|
+
{
|
|
84
|
+
constructorName: 'TypeError',
|
|
85
|
+
pattern: /fetch failed/u,
|
|
86
|
+
},
|
|
87
|
+
// Undici (Node.js)
|
|
88
|
+
{
|
|
89
|
+
constructorName: 'TypeError',
|
|
90
|
+
pattern: /terminated/u,
|
|
91
|
+
},
|
|
92
|
+
];
|
|
93
|
+
/**
|
|
94
|
+
* Custom JSON-RPC error codes for specific cases.
|
|
95
|
+
*
|
|
96
|
+
* These should be moved to `@metamask/rpc-errors` eventually.
|
|
97
|
+
*/
|
|
98
|
+
exports.CUSTOM_RPC_ERRORS = {
|
|
99
|
+
unauthorized: -32006,
|
|
100
|
+
httpClientError: -32080,
|
|
101
|
+
};
|
|
102
|
+
/**
|
|
103
|
+
* Determines whether the given error represents a failure to reach the network
|
|
104
|
+
* after request parameters have been validated.
|
|
105
|
+
*
|
|
106
|
+
* This is somewhat difficult to verify because JavaScript engines (and in
|
|
107
|
+
* some cases libraries) produce slightly different error messages for this
|
|
108
|
+
* particular scenario, and we need to account for this.
|
|
109
|
+
*
|
|
110
|
+
* @param error - The error.
|
|
111
|
+
* @returns True if the error indicates that the network cannot be connected to,
|
|
112
|
+
* and false otherwise.
|
|
113
|
+
*/
|
|
114
|
+
function isConnectionError(error) {
|
|
115
|
+
if (!(typeof error === 'object' && error !== null && 'message' in error)) {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
const { message } = error;
|
|
119
|
+
return (typeof message === 'string' &&
|
|
120
|
+
!isNockError(message) &&
|
|
121
|
+
exports.CONNECTION_ERRORS.some(({ constructorName, pattern }) => {
|
|
122
|
+
return (error.constructor.name === constructorName && pattern.test(message));
|
|
123
|
+
}));
|
|
124
|
+
}
|
|
125
|
+
exports.isConnectionError = isConnectionError;
|
|
126
|
+
/**
|
|
127
|
+
* Determines whether the given error message refers to a Nock error.
|
|
128
|
+
*
|
|
129
|
+
* It's important that if we failed to mock a request in a test, the resulting
|
|
130
|
+
* error does not cause the request to be retried so that we can see it right
|
|
131
|
+
* away.
|
|
132
|
+
*
|
|
133
|
+
* @param message - The error message to test.
|
|
134
|
+
* @returns True if the message indicates a missing Nock mock, false otherwise.
|
|
135
|
+
*/
|
|
136
|
+
function isNockError(message) {
|
|
137
|
+
return message.includes('Nock:');
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Determine whether the given error message indicates a failure to parse JSON.
|
|
141
|
+
*
|
|
142
|
+
* This is different in tests vs. implementation code because it may manifest as
|
|
143
|
+
* a FetchError or a SyntaxError.
|
|
144
|
+
*
|
|
145
|
+
* @param error - The error object to test.
|
|
146
|
+
* @returns True if the error indicates a JSON parse error, false otherwise.
|
|
147
|
+
*/
|
|
148
|
+
function isJsonParseError(error) {
|
|
149
|
+
return (error instanceof SyntaxError ||
|
|
150
|
+
/invalid json/iu.test((0, utils_1.getErrorMessage)(error)));
|
|
151
|
+
}
|
|
152
|
+
exports.isJsonParseError = isJsonParseError;
|
|
153
|
+
/**
|
|
154
|
+
* Determines whether the given error represents a HTTP server error
|
|
155
|
+
* (502, 503, or 504) that should be retried.
|
|
156
|
+
*
|
|
157
|
+
* @param error - The error object to test.
|
|
158
|
+
* @returns True if the error has an httpStatus of 502, 503, or 504.
|
|
159
|
+
*/
|
|
160
|
+
function isHttpServerError(error) {
|
|
161
|
+
return ('httpStatus' in error &&
|
|
162
|
+
(error.httpStatus === 502 ||
|
|
163
|
+
error.httpStatus === 503 ||
|
|
164
|
+
error.httpStatus === 504));
|
|
165
|
+
}
|
|
166
|
+
exports.isHttpServerError = isHttpServerError;
|
|
167
|
+
/**
|
|
168
|
+
* Determines whether the given error has a `code` property of `ETIMEDOUT`.
|
|
169
|
+
*
|
|
170
|
+
* @param error - The error object to test.
|
|
171
|
+
* @returns True if the error code is `ETIMEDOUT`.
|
|
172
|
+
*/
|
|
173
|
+
function isTimeoutError(error) {
|
|
174
|
+
return (0, utils_1.hasProperty)(error, 'code') && error.code === 'ETIMEDOUT';
|
|
175
|
+
}
|
|
176
|
+
exports.isTimeoutError = isTimeoutError;
|
|
177
|
+
/**
|
|
178
|
+
* Determines whether the given error has a `code` property of `ECONNRESET`.
|
|
179
|
+
*
|
|
180
|
+
* @param error - The error object to test.
|
|
181
|
+
* @returns True if the error code is `ECONNRESET`.
|
|
182
|
+
*/
|
|
183
|
+
function isConnectionResetError(error) {
|
|
184
|
+
return (0, utils_1.hasProperty)(error, 'code') && error.code === 'ECONNRESET';
|
|
185
|
+
}
|
|
186
|
+
exports.isConnectionResetError = isConnectionResetError;
|
|
187
|
+
/**
|
|
188
|
+
* Guarantees a URL, even given a string. This is useful for checking components
|
|
189
|
+
* of that URL.
|
|
190
|
+
*
|
|
191
|
+
* @param endpointUrlOrUrlString - Either a URL object or a string that
|
|
192
|
+
* represents the URL of an endpoint.
|
|
193
|
+
* @returns A URL object.
|
|
194
|
+
*/
|
|
195
|
+
function getNormalizedEndpointUrl(endpointUrlOrUrlString) {
|
|
196
|
+
return endpointUrlOrUrlString instanceof URL
|
|
197
|
+
? endpointUrlOrUrlString
|
|
198
|
+
: new URL(endpointUrlOrUrlString);
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Strips username and password from a URL.
|
|
202
|
+
*
|
|
203
|
+
* @param url - The URL to strip credentials from.
|
|
204
|
+
* @returns A new URL object with credentials removed.
|
|
205
|
+
*/
|
|
206
|
+
function stripCredentialsFromUrl(url) {
|
|
207
|
+
const strippedUrl = new URL(url.toString());
|
|
208
|
+
strippedUrl.username = '';
|
|
209
|
+
strippedUrl.password = '';
|
|
210
|
+
return strippedUrl;
|
|
211
|
+
}
|
|
212
|
+
const INFURA_NON_FAILURE_HTTP_STATUS_CODES = [400, 429];
|
|
213
|
+
/**
|
|
214
|
+
* Predicate function that determines if an error from Infura is treated as a service failure.
|
|
215
|
+
*
|
|
216
|
+
* @param error - The error.
|
|
217
|
+
* @returns True if the error should be treated as a service policy failure. Most errors are treated like failures,
|
|
218
|
+
* with the exception of certain HTTP status codes.
|
|
219
|
+
*/
|
|
220
|
+
function isServiceFailureInfura(error) {
|
|
221
|
+
if (typeof error === 'object' &&
|
|
222
|
+
error !== null &&
|
|
223
|
+
(0, utils_1.hasProperty)(error, 'httpStatus') &&
|
|
224
|
+
typeof error.httpStatus === 'number') {
|
|
225
|
+
return !INFURA_NON_FAILURE_HTTP_STATUS_CODES.includes(error.httpStatus);
|
|
226
|
+
}
|
|
227
|
+
// If the error is not an object, or doesn't have a numeric httpStatus
|
|
228
|
+
// property, consider it a service failure (e.g., network errors, timeouts,
|
|
229
|
+
// etc.)
|
|
230
|
+
return true;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* This class is responsible for making a request to an endpoint that implements
|
|
234
|
+
* the JSON-RPC protocol. It is designed to gracefully handle network and server
|
|
235
|
+
* failures, retrying requests using exponential backoff. It also offers a hook
|
|
236
|
+
* which can used to respond to slow requests.
|
|
237
|
+
*/
|
|
238
|
+
class RpcService {
|
|
239
|
+
/**
|
|
240
|
+
* Constructs a new RpcService object.
|
|
241
|
+
*
|
|
242
|
+
* @param options - The options. See {@link RpcServiceOptions}.
|
|
243
|
+
*/
|
|
244
|
+
constructor(options) {
|
|
245
|
+
_RpcService_instances.add(this);
|
|
246
|
+
/**
|
|
247
|
+
* The RPC method name of the current request being processed. This is passed
|
|
248
|
+
* to `onDegraded` event listeners.
|
|
249
|
+
*
|
|
250
|
+
* Initialised to `''` so the type is `string` throughout the event chain.
|
|
251
|
+
* The empty string is unreachable in practice because the method name is
|
|
252
|
+
* guaranteed to be set after the current request is completed but before
|
|
253
|
+
* any `onDegraded` callbacks are called.
|
|
254
|
+
*/
|
|
255
|
+
_RpcService_currentRpcMethodName.set(this, '');
|
|
256
|
+
/**
|
|
257
|
+
* The trace ID from the `X-Trace-Id` response header of the most recent
|
|
258
|
+
* request. Passed to `onDegraded` event listeners for debugging.
|
|
259
|
+
*
|
|
260
|
+
* `undefined` when no response has been received yet or when the response
|
|
261
|
+
* did not include the header.
|
|
262
|
+
*/
|
|
263
|
+
_RpcService_currentTraceId.set(this, void 0);
|
|
264
|
+
/**
|
|
265
|
+
* The function used to make an HTTP request.
|
|
266
|
+
*/
|
|
267
|
+
_RpcService_fetch.set(this, void 0);
|
|
268
|
+
/**
|
|
269
|
+
* A common set of options that the request options will extend.
|
|
270
|
+
*/
|
|
271
|
+
_RpcService_fetchOptions.set(this, void 0);
|
|
272
|
+
/**
|
|
273
|
+
* A `loglevel` logger.
|
|
274
|
+
*/
|
|
275
|
+
_RpcService_logger.set(this, void 0);
|
|
276
|
+
/**
|
|
277
|
+
* The policy that wraps the request.
|
|
278
|
+
*/
|
|
279
|
+
_RpcService_policy.set(this, void 0);
|
|
280
|
+
const { btoa: givenBtoa, endpointUrl, fetch: givenFetch, logger, fetchOptions = {}, policyOptions = {}, isOffline, } = options;
|
|
281
|
+
__classPrivateFieldSet(this, _RpcService_fetch, givenFetch, "f");
|
|
282
|
+
const normalizedUrl = getNormalizedEndpointUrl(endpointUrl);
|
|
283
|
+
__classPrivateFieldSet(this, _RpcService_fetchOptions, __classPrivateFieldGet(this, _RpcService_instances, "m", _RpcService_getDefaultFetchOptions).call(this, normalizedUrl, fetchOptions, givenBtoa), "f");
|
|
284
|
+
this.endpointUrl = stripCredentialsFromUrl(normalizedUrl);
|
|
285
|
+
__classPrivateFieldSet(this, _RpcService_logger, logger, "f");
|
|
286
|
+
const isInfura = normalizedUrl.hostname.endsWith('.infura.io');
|
|
287
|
+
__classPrivateFieldSet(this, _RpcService_policy, (0, controller_utils_1.createServicePolicy)({
|
|
288
|
+
maxRetries: exports.DEFAULT_MAX_RETRIES,
|
|
289
|
+
maxConsecutiveFailures: exports.DEFAULT_MAX_CONSECUTIVE_FAILURES,
|
|
290
|
+
...policyOptions,
|
|
291
|
+
isServiceFailure: isInfura ? isServiceFailureInfura : undefined,
|
|
292
|
+
retryFilterPolicy: (0, controller_utils_1.handleWhen)((error) => {
|
|
293
|
+
// If user is offline, don't retry any errors
|
|
294
|
+
// This prevents degraded/break callbacks from being triggered
|
|
295
|
+
if (isOffline()) {
|
|
296
|
+
return false;
|
|
297
|
+
}
|
|
298
|
+
return (
|
|
299
|
+
// Ignore errors where the request failed to establish
|
|
300
|
+
isConnectionError(error) ||
|
|
301
|
+
// Ignore server sent HTML error pages or truncated JSON responses
|
|
302
|
+
isJsonParseError(error) ||
|
|
303
|
+
// Ignore server overload errors
|
|
304
|
+
isHttpServerError(error) ||
|
|
305
|
+
// Ignore timeout errors
|
|
306
|
+
isTimeoutError(error) ||
|
|
307
|
+
// Ignore connection reset errors
|
|
308
|
+
isConnectionResetError(error));
|
|
309
|
+
}),
|
|
310
|
+
}), "f");
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Resets the underlying composite Cockatiel policy.
|
|
314
|
+
*
|
|
315
|
+
* This is useful in a collection of RpcServices where some act as failovers
|
|
316
|
+
* for others where you effectively want to invalidate the failovers when the
|
|
317
|
+
* primary recovers.
|
|
318
|
+
*/
|
|
319
|
+
resetPolicy() {
|
|
320
|
+
__classPrivateFieldGet(this, _RpcService_policy, "f").reset();
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* @returns The state of the underlying circuit.
|
|
324
|
+
*/
|
|
325
|
+
getCircuitState() {
|
|
326
|
+
return __classPrivateFieldGet(this, _RpcService_policy, "f").getCircuitState();
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Listens for when the RPC service retries the request.
|
|
330
|
+
*
|
|
331
|
+
* @param listener - The callback to be called when the retry occurs.
|
|
332
|
+
* @returns What {@link ServicePolicy.onRetry} returns.
|
|
333
|
+
* @see {@link createServicePolicy}
|
|
334
|
+
*/
|
|
335
|
+
onRetry(listener) {
|
|
336
|
+
return __classPrivateFieldGet(this, _RpcService_policy, "f").onRetry((data) => {
|
|
337
|
+
listener({ ...data, endpointUrl: this.endpointUrl.toString() });
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Listens for when the RPC service retries the request too many times in a
|
|
342
|
+
* row, causing the underlying circuit to break.
|
|
343
|
+
*
|
|
344
|
+
* @param listener - The callback to be called when the circuit is broken.
|
|
345
|
+
* @returns What {@link ServicePolicy.onBreak} returns.
|
|
346
|
+
* @see {@link createServicePolicy}
|
|
347
|
+
*/
|
|
348
|
+
onBreak(listener) {
|
|
349
|
+
return __classPrivateFieldGet(this, _RpcService_policy, "f").onBreak((data) => {
|
|
350
|
+
// `{ isolated: true }` is a special object that shows up when `isolate`
|
|
351
|
+
// is called on the circuit breaker. Usually `isolate` is used to hold the
|
|
352
|
+
// circuit open, but we (ab)use this method in `createServicePolicy` to
|
|
353
|
+
// reset the circuit breaker policy. When we do this, we don't want to
|
|
354
|
+
// call `onBreak` handlers, because then it causes
|
|
355
|
+
// `NetworkController:rpcEndpointUnavailable` and
|
|
356
|
+
// `NetworkController:rpcEndpointChainUnavailable` to be published. So we
|
|
357
|
+
// have to ignore that object here. The consequence is that `isolate`
|
|
358
|
+
// doesn't function the way it is intended, at least in the context of an
|
|
359
|
+
// RpcService. However, we are making a bet that we won't need to use it
|
|
360
|
+
// other than how we are already using it.
|
|
361
|
+
if (!('isolated' in data)) {
|
|
362
|
+
listener({
|
|
363
|
+
...data,
|
|
364
|
+
endpointUrl: this.endpointUrl.toString(),
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Listens for when the policy underlying this RPC service detects a slow
|
|
371
|
+
* request.
|
|
372
|
+
*
|
|
373
|
+
* @param listener - The callback to be called when the request is slow.
|
|
374
|
+
* @returns What {@link ServicePolicy.onDegraded} returns.
|
|
375
|
+
* @see {@link createServicePolicy}
|
|
376
|
+
*/
|
|
377
|
+
onDegraded(listener) {
|
|
378
|
+
return __classPrivateFieldGet(this, _RpcService_policy, "f").onDegraded((data) => {
|
|
379
|
+
listener({
|
|
380
|
+
...data,
|
|
381
|
+
endpointUrl: this.endpointUrl.toString(),
|
|
382
|
+
rpcMethodName: __classPrivateFieldGet(this, _RpcService_currentRpcMethodName, "f"),
|
|
383
|
+
traceId: __classPrivateFieldGet(this, _RpcService_currentTraceId, "f"),
|
|
384
|
+
});
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Listens for when the policy underlying this RPC service is available.
|
|
389
|
+
*
|
|
390
|
+
* @param listener - The callback to be called when the request is available.
|
|
391
|
+
* @returns What {@link ServicePolicy.onAvailable} returns.
|
|
392
|
+
* @see {@link createServicePolicy}
|
|
393
|
+
*/
|
|
394
|
+
onAvailable(listener) {
|
|
395
|
+
return __classPrivateFieldGet(this, _RpcService_policy, "f").onAvailable(() => {
|
|
396
|
+
listener({ endpointUrl: this.endpointUrl.toString() });
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
async request(
|
|
400
|
+
// The request object may be frozen and must not be mutated.
|
|
401
|
+
jsonRpcRequest, fetchOptions = {}) {
|
|
402
|
+
const completeFetchOptions = __classPrivateFieldGet(this, _RpcService_instances, "m", _RpcService_getCompleteFetchOptions).call(this, jsonRpcRequest, fetchOptions);
|
|
403
|
+
return await __classPrivateFieldGet(this, _RpcService_instances, "m", _RpcService_executeAndProcessRequest).call(this, completeFetchOptions, jsonRpcRequest.method);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
exports.RpcService = RpcService;
|
|
407
|
+
_RpcService_currentRpcMethodName = new WeakMap(), _RpcService_currentTraceId = new WeakMap(), _RpcService_fetch = new WeakMap(), _RpcService_fetchOptions = new WeakMap(), _RpcService_logger = new WeakMap(), _RpcService_policy = new WeakMap(), _RpcService_instances = new WeakSet(), _RpcService_getDefaultFetchOptions = function _RpcService_getDefaultFetchOptions(endpointUrl, fetchOptions, givenBtoa) {
|
|
408
|
+
if (endpointUrl.username && endpointUrl.password) {
|
|
409
|
+
const authString = `${endpointUrl.username}:${endpointUrl.password}`;
|
|
410
|
+
const encodedCredentials = givenBtoa(authString);
|
|
411
|
+
return (0, deepmerge_1.default)(fetchOptions, {
|
|
412
|
+
headers: { Authorization: `Basic ${encodedCredentials}` },
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
return fetchOptions;
|
|
416
|
+
}, _RpcService_getCompleteFetchOptions = function _RpcService_getCompleteFetchOptions(jsonRpcRequest, fetchOptions) {
|
|
417
|
+
const defaultOptions = {
|
|
418
|
+
method: 'POST',
|
|
419
|
+
headers: {
|
|
420
|
+
Accept: 'application/json',
|
|
421
|
+
'Content-Type': 'application/json',
|
|
422
|
+
},
|
|
423
|
+
};
|
|
424
|
+
const mergedOptions = (0, deepmerge_1.default)(defaultOptions, (0, deepmerge_1.default)(__classPrivateFieldGet(this, _RpcService_fetchOptions, "f"), fetchOptions));
|
|
425
|
+
const { id, jsonrpc, method, params } = jsonRpcRequest;
|
|
426
|
+
const body = JSON.stringify({
|
|
427
|
+
id,
|
|
428
|
+
jsonrpc,
|
|
429
|
+
method,
|
|
430
|
+
params,
|
|
431
|
+
});
|
|
432
|
+
return { ...mergedOptions, body };
|
|
433
|
+
}, _RpcService_executeAndProcessRequest =
|
|
434
|
+
/**
|
|
435
|
+
* Makes the request using the Cockatiel policy that this service creates.
|
|
436
|
+
*
|
|
437
|
+
* @param fetchOptions - The options for `fetch`; will be combined with the
|
|
438
|
+
* fetch options passed to the constructor
|
|
439
|
+
* @param rpcMethodName - The JSON-RPC method name of the current request.
|
|
440
|
+
* @returns The decoded JSON-RPC response from the endpoint.
|
|
441
|
+
* @throws An "authorized" JSON-RPC error (code -32006) if the response HTTP status is 401.
|
|
442
|
+
* @throws A "rate limiting" JSON-RPC error (code -32005) if the response HTTP status is 429.
|
|
443
|
+
* @throws A "resource unavailable" JSON-RPC error (code -32002) if the response HTTP status is 402, 404, or any 5xx.
|
|
444
|
+
* @throws A generic HTTP client JSON-RPC error (code -32050) for any other 4xx HTTP status codes.
|
|
445
|
+
* @throws A "parse" JSON-RPC error (code -32700) if the response is not valid JSON.
|
|
446
|
+
*/
|
|
447
|
+
async function _RpcService_executeAndProcessRequest(fetchOptions, rpcMethodName) {
|
|
448
|
+
let response;
|
|
449
|
+
try {
|
|
450
|
+
log(`[${this.endpointUrl}] Circuit state`, __classPrivateFieldGet(this, _RpcService_policy, "f").getCircuitState());
|
|
451
|
+
const jsonDecodedResponse = await __classPrivateFieldGet(this, _RpcService_policy, "f").execute(async (context) => {
|
|
452
|
+
// Reset response so that if this attempt throws before
|
|
453
|
+
// assigning a new response, the finally block does not read
|
|
454
|
+
// a stale response from a previous attempt.
|
|
455
|
+
response = undefined;
|
|
456
|
+
try {
|
|
457
|
+
log('REQUEST INITIATED:', this.endpointUrl.toString(), '::', fetchOptions,
|
|
458
|
+
// @ts-expect-error This property _is_ here, the type of
|
|
459
|
+
// ServicePolicy is just wrong.
|
|
460
|
+
`(attempt ${context.attempt + 1})`);
|
|
461
|
+
response = await __classPrivateFieldGet(this, _RpcService_fetch, "f").call(this, this.endpointUrl, fetchOptions);
|
|
462
|
+
if (!response.ok) {
|
|
463
|
+
throw new controller_utils_1.HttpError(response.status);
|
|
464
|
+
}
|
|
465
|
+
log('REQUEST SUCCESSFUL:', this.endpointUrl.toString(), response.status);
|
|
466
|
+
return await response.json();
|
|
467
|
+
}
|
|
468
|
+
finally {
|
|
469
|
+
// Track the RPC method and trace ID for the request that has just
|
|
470
|
+
// taken place. We pass these properties to `onDegraded` event
|
|
471
|
+
// listeners.
|
|
472
|
+
//
|
|
473
|
+
// We set these properties after the request completes and not
|
|
474
|
+
// before the request starts to account for race conditions. That
|
|
475
|
+
// is, if there are two requests that are being performed
|
|
476
|
+
// concurrently, and the second request fails fast but the first
|
|
477
|
+
// request succeeds slowly, when `onDegraded` is called we want it
|
|
478
|
+
// to include the first request as the RPC method, not the second.
|
|
479
|
+
//
|
|
480
|
+
// Also, we set these properties within a `finally` block inside of
|
|
481
|
+
// the function passed to `policy.execute` to ensure that they are
|
|
482
|
+
// set before `onDegraded` gets called, no matter the outcome of
|
|
483
|
+
// the request.
|
|
484
|
+
__classPrivateFieldSet(this, _RpcService_currentRpcMethodName, rpcMethodName, "f");
|
|
485
|
+
__classPrivateFieldSet(this, _RpcService_currentTraceId, response?.headers.get('X-Trace-Id') ?? undefined, "f");
|
|
486
|
+
}
|
|
487
|
+
});
|
|
488
|
+
this.lastError = undefined;
|
|
489
|
+
return jsonDecodedResponse;
|
|
490
|
+
}
|
|
491
|
+
catch (error) {
|
|
492
|
+
log('REQUEST ERROR:', this.endpointUrl.toString(), error);
|
|
493
|
+
this.lastError =
|
|
494
|
+
error instanceof Error ? error : new Error((0, utils_1.getErrorMessage)(error));
|
|
495
|
+
if (error instanceof controller_utils_1.HttpError) {
|
|
496
|
+
const status = error.httpStatus;
|
|
497
|
+
if (status === 401) {
|
|
498
|
+
throw new rpc_errors_1.JsonRpcError(exports.CUSTOM_RPC_ERRORS.unauthorized, 'Unauthorized.', {
|
|
499
|
+
httpStatus: status,
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
if (status === 429) {
|
|
503
|
+
throw rpc_errors_1.rpcErrors.limitExceeded({
|
|
504
|
+
message: 'Request is being rate limited.',
|
|
505
|
+
data: {
|
|
506
|
+
httpStatus: status,
|
|
507
|
+
},
|
|
508
|
+
});
|
|
509
|
+
}
|
|
510
|
+
if (status >= 500 || status === 402 || status === 404) {
|
|
511
|
+
throw rpc_errors_1.rpcErrors.resourceUnavailable({
|
|
512
|
+
message: 'RPC endpoint not found or unavailable.',
|
|
513
|
+
data: {
|
|
514
|
+
httpStatus: status,
|
|
515
|
+
},
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
// Handle all other 4xx errors as generic HTTP client errors
|
|
519
|
+
throw new rpc_errors_1.JsonRpcError(exports.CUSTOM_RPC_ERRORS.httpClientError, 'RPC endpoint returned HTTP client error.', {
|
|
520
|
+
httpStatus: status,
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
else if (isJsonParseError(error)) {
|
|
524
|
+
throw rpc_errors_1.rpcErrors.parse({
|
|
525
|
+
message: 'RPC endpoint did not return JSON.',
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
else if (error instanceof controller_utils_1.BrokenCircuitError) {
|
|
529
|
+
__classPrivateFieldGet(this, _RpcService_logger, "f")?.warn(error);
|
|
530
|
+
const remainingCircuitOpenDuration = __classPrivateFieldGet(this, _RpcService_policy, "f").getRemainingCircuitOpenDuration();
|
|
531
|
+
const formattedRemainingCircuitOpenDuration = Intl.NumberFormat(undefined, { maximumFractionDigits: 2 }).format((remainingCircuitOpenDuration ?? __classPrivateFieldGet(this, _RpcService_policy, "f").circuitBreakDuration) /
|
|
532
|
+
utils_1.Duration.Minute);
|
|
533
|
+
throw rpc_errors_1.rpcErrors.resourceUnavailable({
|
|
534
|
+
message: `RPC endpoint returned too many errors, retrying in ${formattedRemainingCircuitOpenDuration} minutes. Consider using a different RPC endpoint.`,
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
throw error;
|
|
538
|
+
}
|
|
539
|
+
};
|
|
540
|
+
//# sourceMappingURL=rpc-service.cjs.map
|