@metamask-previews/network-controller 21.0.0-preview-367cb1da → 21.0.0-preview-cf09c0a
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/dist/NetworkController.cjs +1373 -0
- package/dist/NetworkController.cjs.map +1 -0
- package/dist/{types/NetworkController.d.ts → NetworkController.d.cts} +14 -14
- package/dist/NetworkController.d.cts.map +1 -0
- package/dist/NetworkController.d.mts +636 -0
- package/dist/NetworkController.d.mts.map +1 -0
- package/dist/NetworkController.mjs +1345 -23
- package/dist/NetworkController.mjs.map +1 -1
- package/dist/constants.cjs +32 -0
- package/dist/constants.cjs.map +1 -0
- package/dist/{types/constants.d.ts → constants.d.cts} +1 -1
- package/dist/constants.d.cts.map +1 -0
- package/dist/constants.d.mts +28 -0
- package/dist/constants.d.mts.map +1 -0
- package/dist/constants.mjs +28 -9
- package/dist/constants.mjs.map +1 -1
- package/dist/create-auto-managed-network-client.cjs +134 -0
- package/dist/create-auto-managed-network-client.cjs.map +1 -0
- package/dist/{types/create-auto-managed-network-client.d.ts → create-auto-managed-network-client.d.cts} +2 -2
- package/dist/create-auto-managed-network-client.d.cts.map +1 -0
- package/dist/create-auto-managed-network-client.d.mts +47 -0
- package/dist/create-auto-managed-network-client.d.mts.map +1 -0
- package/dist/create-auto-managed-network-client.mjs +129 -9
- package/dist/create-auto-managed-network-client.mjs.map +1 -1
- package/dist/create-network-client.cjs +146 -0
- package/dist/create-network-client.cjs.map +1 -0
- package/dist/{types/create-network-client.d.ts → create-network-client.d.cts} +2 -2
- package/dist/create-network-client.d.cts.map +1 -0
- package/dist/create-network-client.d.mts +19 -0
- package/dist/create-network-client.d.mts.map +1 -0
- package/dist/create-network-client.mjs +143 -7
- package/dist/create-network-client.mjs.map +1 -1
- package/dist/index.cjs +27 -0
- package/dist/index.cjs.map +1 -0
- package/dist/{types/index.d.ts → index.d.cts} +9 -9
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +9 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +3 -28
- package/dist/index.mjs.map +1 -1
- package/dist/logger.cjs +7 -0
- package/dist/logger.cjs.map +1 -0
- package/dist/{types/logger.d.ts → logger.d.cts} +2 -2
- 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 +3 -9
- package/dist/logger.mjs.map +1 -1
- package/dist/types.cjs +12 -0
- package/dist/types.cjs.map +1 -0
- package/dist/{types/types.d.ts → types.d.cts} +5 -5
- package/dist/types.d.cts.map +1 -0
- package/dist/types.d.mts +41 -0
- package/dist/types.d.mts.map +1 -0
- package/dist/types.mjs +8 -7
- package/dist/types.mjs.map +1 -1
- package/package.json +12 -7
- package/dist/NetworkController.js +0 -25
- package/dist/NetworkController.js.map +0 -1
- package/dist/chunk-2QJYHWIP.mjs +0 -15
- package/dist/chunk-2QJYHWIP.mjs.map +0 -1
- package/dist/chunk-AU4UVIPZ.mjs +0 -11
- package/dist/chunk-AU4UVIPZ.mjs.map +0 -1
- package/dist/chunk-BV3ZGWII.mjs +0 -1485
- package/dist/chunk-BV3ZGWII.mjs.map +0 -1
- package/dist/chunk-E4V6XEBR.js +0 -125
- package/dist/chunk-E4V6XEBR.js.map +0 -1
- package/dist/chunk-KHZTS7TF.js +0 -11
- package/dist/chunk-KHZTS7TF.js.map +0 -1
- package/dist/chunk-LLMZDA4Q.js +0 -99
- package/dist/chunk-LLMZDA4Q.js.map +0 -1
- package/dist/chunk-TZA3CBEI.mjs +0 -99
- package/dist/chunk-TZA3CBEI.mjs.map +0 -1
- package/dist/chunk-U43RY4MY.mjs +0 -125
- package/dist/chunk-U43RY4MY.mjs.map +0 -1
- package/dist/chunk-VGYLDDJB.js +0 -9
- package/dist/chunk-VGYLDDJB.js.map +0 -1
- package/dist/chunk-VTLOAS2R.mjs +0 -9
- package/dist/chunk-VTLOAS2R.mjs.map +0 -1
- package/dist/chunk-XUI43LEZ.mjs +0 -30
- package/dist/chunk-XUI43LEZ.mjs.map +0 -1
- package/dist/chunk-YOHMQPGM.js +0 -1485
- package/dist/chunk-YOHMQPGM.js.map +0 -1
- package/dist/chunk-Z4BLTVTB.js +0 -30
- package/dist/chunk-Z4BLTVTB.js.map +0 -1
- package/dist/chunk-ZKNI7MD3.js +0 -15
- package/dist/chunk-ZKNI7MD3.js.map +0 -1
- package/dist/constants.js +0 -10
- package/dist/constants.js.map +0 -1
- package/dist/create-auto-managed-network-client.js +0 -10
- package/dist/create-auto-managed-network-client.js.map +0 -1
- package/dist/create-network-client.js +0 -9
- package/dist/create-network-client.js.map +0 -1
- package/dist/index.js +0 -29
- package/dist/index.js.map +0 -1
- package/dist/logger.js +0 -10
- package/dist/logger.js.map +0 -1
- package/dist/tsconfig.build.tsbuildinfo +0 -1
- package/dist/types/NetworkController.d.ts.map +0 -1
- package/dist/types/constants.d.ts.map +0 -1
- package/dist/types/create-auto-managed-network-client.d.ts.map +0 -1
- package/dist/types/create-network-client.d.ts.map +0 -1
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/logger.d.ts.map +0 -1
- package/dist/types/types.d.ts.map +0 -1
- package/dist/types.js +0 -8
- package/dist/types.js.map +0 -1
|
@@ -0,0 +1,1373 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
26
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
27
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
28
|
+
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");
|
|
29
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
30
|
+
};
|
|
31
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
32
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
33
|
+
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");
|
|
34
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
35
|
+
};
|
|
36
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
37
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
38
|
+
};
|
|
39
|
+
var _NetworkController_instances, _NetworkController_ethQuery, _NetworkController_infuraProjectId, _NetworkController_previouslySelectedNetworkClientId, _NetworkController_providerProxy, _NetworkController_blockTrackerProxy, _NetworkController_autoManagedNetworkClientRegistry, _NetworkController_autoManagedNetworkClient, _NetworkController_log, _NetworkController_networkConfigurationsByNetworkClientId, _NetworkController_refreshNetwork, _NetworkController_getLatestBlock, _NetworkController_determineEIP1559Compatibility, _NetworkController_validateNetworkFields, _NetworkController_determineNetworkConfigurationToPersist, _NetworkController_registerNetworkClientsAsNeeded, _NetworkController_unregisterNetworkClientsAsNeeded, _NetworkController_updateNetworkConfigurations, _NetworkController_ensureAutoManagedNetworkClientRegistryPopulated, _NetworkController_createAutoManagedNetworkClientRegistry, _NetworkController_applyNetworkSelection;
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
exports.NetworkController = exports.selectAvailableNetworkClientIds = exports.getAvailableNetworkClientIds = exports.getNetworkConfigurations = exports.getDefaultNetworkControllerState = exports.knownKeysOf = exports.RpcEndpointType = void 0;
|
|
42
|
+
const base_controller_1 = require("@metamask/base-controller");
|
|
43
|
+
const controller_utils_1 = require("@metamask/controller-utils");
|
|
44
|
+
const eth_query_1 = __importDefault(require("@metamask/eth-query"));
|
|
45
|
+
const rpc_errors_1 = require("@metamask/rpc-errors");
|
|
46
|
+
const swappable_obj_proxy_1 = require("@metamask/swappable-obj-proxy");
|
|
47
|
+
const utils_1 = require("@metamask/utils");
|
|
48
|
+
const assert_1 = require("assert");
|
|
49
|
+
const reselect_1 = require("reselect");
|
|
50
|
+
const URI = __importStar(require("uri-js"));
|
|
51
|
+
const util_1 = require("util");
|
|
52
|
+
const uuid_1 = require("uuid");
|
|
53
|
+
const constants_1 = require("./constants.cjs");
|
|
54
|
+
const create_auto_managed_network_client_1 = require("./create-auto-managed-network-client.cjs");
|
|
55
|
+
const logger_1 = require("./logger.cjs");
|
|
56
|
+
const types_1 = require("./types.cjs");
|
|
57
|
+
const debugLog = (0, logger_1.createModuleLogger)(logger_1.projectLogger, 'NetworkController');
|
|
58
|
+
const INFURA_URL_REGEX = /^https:\/\/(?<networkName>[^.]+)\.infura\.io\/v\d+\/(?<apiKey>.+)$/u;
|
|
59
|
+
/**
|
|
60
|
+
* The type of an RPC endpoint.
|
|
61
|
+
*
|
|
62
|
+
* @see {@link CustomRpcEndpoint}
|
|
63
|
+
* @see {@link InfuraRpcEndpoint}
|
|
64
|
+
*/
|
|
65
|
+
var RpcEndpointType;
|
|
66
|
+
(function (RpcEndpointType) {
|
|
67
|
+
RpcEndpointType["Custom"] = "custom";
|
|
68
|
+
RpcEndpointType["Infura"] = "infura";
|
|
69
|
+
})(RpcEndpointType || (exports.RpcEndpointType = RpcEndpointType = {}));
|
|
70
|
+
/**
|
|
71
|
+
* `Object.keys()` is intentionally generic: it returns the keys of an object,
|
|
72
|
+
* but it cannot make guarantees about the contents of that object, so the type
|
|
73
|
+
* of the keys is merely `string[]`. While this is technically accurate, it is
|
|
74
|
+
* also unnecessary if we have an object that we own and whose contents are
|
|
75
|
+
* known exactly.
|
|
76
|
+
*
|
|
77
|
+
* TODO: Move to @metamask/utils.
|
|
78
|
+
*
|
|
79
|
+
* @param object - The object.
|
|
80
|
+
* @returns The keys of an object, typed according to the type of the object
|
|
81
|
+
* itself.
|
|
82
|
+
*/
|
|
83
|
+
// TODO: Either fix this lint violation or explain why it's necessary to ignore.
|
|
84
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
85
|
+
function knownKeysOf(
|
|
86
|
+
// TODO: Replace `any` with type
|
|
87
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
88
|
+
object) {
|
|
89
|
+
return Object.keys(object);
|
|
90
|
+
}
|
|
91
|
+
exports.knownKeysOf = knownKeysOf;
|
|
92
|
+
/**
|
|
93
|
+
* Type guard for determining whether the given value is an error object with a
|
|
94
|
+
* `code` property, such as an instance of Error.
|
|
95
|
+
*
|
|
96
|
+
* TODO: Move this to @metamask/utils.
|
|
97
|
+
*
|
|
98
|
+
* @param error - The object to check.
|
|
99
|
+
* @returns True if `error` has a `code`, false otherwise.
|
|
100
|
+
*/
|
|
101
|
+
function isErrorWithCode(error) {
|
|
102
|
+
return typeof error === 'object' && error !== null && 'code' in error;
|
|
103
|
+
}
|
|
104
|
+
const controllerName = 'NetworkController';
|
|
105
|
+
/**
|
|
106
|
+
* Constructs a value for the state property `networkConfigurationsByChainId`
|
|
107
|
+
* which will be used if it has not been provided to the constructor.
|
|
108
|
+
*
|
|
109
|
+
* @returns The default value for `networkConfigurationsByChainId`.
|
|
110
|
+
*/
|
|
111
|
+
function getDefaultNetworkConfigurationsByChainId() {
|
|
112
|
+
return Object.values(controller_utils_1.InfuraNetworkType).reduce((obj, infuraNetworkType) => {
|
|
113
|
+
const chainId = controller_utils_1.ChainId[infuraNetworkType];
|
|
114
|
+
const rpcEndpointUrl =
|
|
115
|
+
// False negative - this is a string.
|
|
116
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
117
|
+
`https://${infuraNetworkType}.infura.io/v3/{infuraProjectId}`;
|
|
118
|
+
const networkConfiguration = {
|
|
119
|
+
blockExplorerUrls: [],
|
|
120
|
+
chainId,
|
|
121
|
+
defaultRpcEndpointIndex: 0,
|
|
122
|
+
name: controller_utils_1.NetworkNickname[infuraNetworkType],
|
|
123
|
+
nativeCurrency: controller_utils_1.NetworksTicker[infuraNetworkType],
|
|
124
|
+
rpcEndpoints: [
|
|
125
|
+
{
|
|
126
|
+
networkClientId: infuraNetworkType,
|
|
127
|
+
type: RpcEndpointType.Infura,
|
|
128
|
+
url: rpcEndpointUrl,
|
|
129
|
+
},
|
|
130
|
+
],
|
|
131
|
+
};
|
|
132
|
+
return { ...obj, [chainId]: networkConfiguration };
|
|
133
|
+
}, {});
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Constructs properties for the NetworkController state whose values will be
|
|
137
|
+
* used if not provided to the constructor.
|
|
138
|
+
*
|
|
139
|
+
* @returns The default NetworkController state.
|
|
140
|
+
*/
|
|
141
|
+
function getDefaultNetworkControllerState() {
|
|
142
|
+
const networksMetadata = {};
|
|
143
|
+
const networkConfigurationsByChainId = getDefaultNetworkConfigurationsByChainId();
|
|
144
|
+
return {
|
|
145
|
+
selectedNetworkClientId: controller_utils_1.InfuraNetworkType.mainnet,
|
|
146
|
+
networksMetadata,
|
|
147
|
+
networkConfigurationsByChainId,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
exports.getDefaultNetworkControllerState = getDefaultNetworkControllerState;
|
|
151
|
+
/**
|
|
152
|
+
* Get a list of all network configurations.
|
|
153
|
+
*
|
|
154
|
+
* @param state - NetworkController state
|
|
155
|
+
* @returns A list of all available network configurations
|
|
156
|
+
*/
|
|
157
|
+
function getNetworkConfigurations(state) {
|
|
158
|
+
return Object.values(state.networkConfigurationsByChainId);
|
|
159
|
+
}
|
|
160
|
+
exports.getNetworkConfigurations = getNetworkConfigurations;
|
|
161
|
+
/**
|
|
162
|
+
* Get a list of all available client IDs from a list of
|
|
163
|
+
* network configurations
|
|
164
|
+
* @param networkConfigurations - The array of network configurations
|
|
165
|
+
* @returns A list of all available client IDs
|
|
166
|
+
*/
|
|
167
|
+
function getAvailableNetworkClientIds(networkConfigurations) {
|
|
168
|
+
return networkConfigurations.flatMap((networkConfiguration) => networkConfiguration.rpcEndpoints.map((rpcEndpoint) => rpcEndpoint.networkClientId));
|
|
169
|
+
}
|
|
170
|
+
exports.getAvailableNetworkClientIds = getAvailableNetworkClientIds;
|
|
171
|
+
exports.selectAvailableNetworkClientIds = (0, reselect_1.createSelector)([getNetworkConfigurations], getAvailableNetworkClientIds);
|
|
172
|
+
/**
|
|
173
|
+
* Determines whether the given URL is valid by attempting to parse it.
|
|
174
|
+
*
|
|
175
|
+
* @param url - The URL to test.
|
|
176
|
+
* @returns True if the URL is valid, false otherwise.
|
|
177
|
+
*/
|
|
178
|
+
function isValidUrl(url) {
|
|
179
|
+
const uri = URI.parse(url);
|
|
180
|
+
return (uri.error === undefined && (uri.scheme === 'http' || uri.scheme === 'https'));
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Given an Infura API URL, extracts the subdomain that identifies the Infura
|
|
184
|
+
* network.
|
|
185
|
+
*
|
|
186
|
+
* @param rpcEndpointUrl - The URL to operate on.
|
|
187
|
+
* @returns The Infura network name that the URL references.
|
|
188
|
+
* @throws if the URL is not an Infura API URL, or if an Infura network is not
|
|
189
|
+
* present in the URL.
|
|
190
|
+
*/
|
|
191
|
+
function deriveInfuraNetworkNameFromRpcEndpointUrl(rpcEndpointUrl) {
|
|
192
|
+
const match = INFURA_URL_REGEX.exec(rpcEndpointUrl);
|
|
193
|
+
if (match?.groups) {
|
|
194
|
+
if ((0, controller_utils_1.isInfuraNetworkType)(match.groups.networkName)) {
|
|
195
|
+
return match.groups.networkName;
|
|
196
|
+
}
|
|
197
|
+
throw new Error(`Unknown Infura network '${match.groups.networkName}'`);
|
|
198
|
+
}
|
|
199
|
+
throw new Error('Could not derive Infura network from RPC endpoint URL');
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Performs a series of checks that the given NetworkController state is
|
|
203
|
+
* internally consistent — that all parts of state that are supposed to match in
|
|
204
|
+
* fact do — so that working with the state later on doesn't cause unexpected
|
|
205
|
+
* errors.
|
|
206
|
+
*
|
|
207
|
+
* In the case of NetworkController, there are several parts of state that need
|
|
208
|
+
* to match. For instance, `defaultRpcEndpointIndex` needs to match an entry
|
|
209
|
+
* within `rpcEndpoints`, and `selectedNetworkClientId` needs to point to an RPC
|
|
210
|
+
* endpoint within a network configuration.
|
|
211
|
+
*
|
|
212
|
+
* @param state - The NetworkController state to verify.
|
|
213
|
+
* @throws if the state is invalid in some way.
|
|
214
|
+
*/
|
|
215
|
+
function validateNetworkControllerState(state) {
|
|
216
|
+
const networkConfigurationEntries = Object.entries(state.networkConfigurationsByChainId);
|
|
217
|
+
const networkClientIds = (0, exports.selectAvailableNetworkClientIds)(state);
|
|
218
|
+
if (networkConfigurationEntries.length === 0) {
|
|
219
|
+
throw new Error('NetworkController state is invalid: `networkConfigurationsByChainId` cannot be empty');
|
|
220
|
+
}
|
|
221
|
+
for (const [chainId, networkConfiguration] of networkConfigurationEntries) {
|
|
222
|
+
if (chainId !== networkConfiguration.chainId) {
|
|
223
|
+
throw new Error(`NetworkController state has invalid \`networkConfigurationsByChainId\`: Network configuration '${networkConfiguration.name}' is filed under '${chainId}' which does not match its \`chainId\` of '${networkConfiguration.chainId}'`);
|
|
224
|
+
}
|
|
225
|
+
const isInvalidDefaultBlockExplorerUrlIndex = networkConfiguration.blockExplorerUrls.length > 0
|
|
226
|
+
? networkConfiguration.defaultBlockExplorerUrlIndex === undefined ||
|
|
227
|
+
networkConfiguration.blockExplorerUrls[networkConfiguration.defaultBlockExplorerUrlIndex] === undefined
|
|
228
|
+
: networkConfiguration.defaultBlockExplorerUrlIndex !== undefined;
|
|
229
|
+
if (isInvalidDefaultBlockExplorerUrlIndex) {
|
|
230
|
+
throw new Error(`NetworkController state has invalid \`networkConfigurationsByChainId\`: Network configuration '${networkConfiguration.name}' has a \`defaultBlockExplorerUrlIndex\` that does not refer to an entry in \`blockExplorerUrls\``);
|
|
231
|
+
}
|
|
232
|
+
if (networkConfiguration.rpcEndpoints[networkConfiguration.defaultRpcEndpointIndex] === undefined) {
|
|
233
|
+
throw new Error(`NetworkController state has invalid \`networkConfigurationsByChainId\`: Network configuration '${networkConfiguration.name}' has a \`defaultRpcEndpointIndex\` that does not refer to an entry in \`rpcEndpoints\``);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
if ([...new Set(networkClientIds)].length < networkClientIds.length) {
|
|
237
|
+
throw new Error('NetworkController state has invalid `networkConfigurationsByChainId`: Every RPC endpoint across all network configurations must have a unique `networkClientId`');
|
|
238
|
+
}
|
|
239
|
+
if (!networkClientIds.includes(state.selectedNetworkClientId)) {
|
|
240
|
+
throw new Error(`NetworkController state is invalid: \`selectedNetworkClientId\` ${(0, util_1.inspect)(state.selectedNetworkClientId)} does not refer to an RPC endpoint within a network configuration`);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Transforms a map of chain ID to network configuration to a map of network
|
|
245
|
+
* client ID to network configuration.
|
|
246
|
+
*
|
|
247
|
+
* @param networkConfigurationsByChainId - The network configurations, keyed by
|
|
248
|
+
* chain ID.
|
|
249
|
+
* @returns The network configurations, keyed by network client ID.
|
|
250
|
+
*/
|
|
251
|
+
function buildNetworkConfigurationsByNetworkClientId(networkConfigurationsByChainId) {
|
|
252
|
+
return new Map(Object.values(networkConfigurationsByChainId).flatMap((networkConfiguration) => {
|
|
253
|
+
return networkConfiguration.rpcEndpoints.map((rpcEndpoint) => {
|
|
254
|
+
return [rpcEndpoint.networkClientId, networkConfiguration];
|
|
255
|
+
});
|
|
256
|
+
}));
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Controller that creates and manages an Ethereum network provider.
|
|
260
|
+
*/
|
|
261
|
+
class NetworkController extends base_controller_1.BaseController {
|
|
262
|
+
constructor({ messenger, state, infuraProjectId, log, }) {
|
|
263
|
+
const initialState = { ...getDefaultNetworkControllerState(), ...state };
|
|
264
|
+
validateNetworkControllerState(initialState);
|
|
265
|
+
if (!infuraProjectId || typeof infuraProjectId !== 'string') {
|
|
266
|
+
throw new Error('Invalid Infura project ID');
|
|
267
|
+
}
|
|
268
|
+
super({
|
|
269
|
+
name: controllerName,
|
|
270
|
+
metadata: {
|
|
271
|
+
selectedNetworkClientId: {
|
|
272
|
+
persist: true,
|
|
273
|
+
anonymous: false,
|
|
274
|
+
},
|
|
275
|
+
networksMetadata: {
|
|
276
|
+
persist: true,
|
|
277
|
+
anonymous: false,
|
|
278
|
+
},
|
|
279
|
+
networkConfigurationsByChainId: {
|
|
280
|
+
persist: true,
|
|
281
|
+
anonymous: false,
|
|
282
|
+
},
|
|
283
|
+
},
|
|
284
|
+
messenger,
|
|
285
|
+
state: initialState,
|
|
286
|
+
});
|
|
287
|
+
_NetworkController_instances.add(this);
|
|
288
|
+
_NetworkController_ethQuery.set(this, void 0);
|
|
289
|
+
_NetworkController_infuraProjectId.set(this, void 0);
|
|
290
|
+
_NetworkController_previouslySelectedNetworkClientId.set(this, void 0);
|
|
291
|
+
_NetworkController_providerProxy.set(this, void 0);
|
|
292
|
+
_NetworkController_blockTrackerProxy.set(this, void 0);
|
|
293
|
+
_NetworkController_autoManagedNetworkClientRegistry.set(this, void 0);
|
|
294
|
+
_NetworkController_autoManagedNetworkClient.set(this, void 0);
|
|
295
|
+
_NetworkController_log.set(this, void 0);
|
|
296
|
+
_NetworkController_networkConfigurationsByNetworkClientId.set(this, void 0);
|
|
297
|
+
__classPrivateFieldSet(this, _NetworkController_infuraProjectId, infuraProjectId, "f");
|
|
298
|
+
__classPrivateFieldSet(this, _NetworkController_log, log, "f");
|
|
299
|
+
__classPrivateFieldSet(this, _NetworkController_previouslySelectedNetworkClientId, this.state.selectedNetworkClientId, "f");
|
|
300
|
+
__classPrivateFieldSet(this, _NetworkController_networkConfigurationsByNetworkClientId, buildNetworkConfigurationsByNetworkClientId(this.state.networkConfigurationsByChainId), "f");
|
|
301
|
+
this.messagingSystem.registerActionHandler(
|
|
302
|
+
// TODO: Either fix this lint violation or explain why it's necessary to ignore.
|
|
303
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
304
|
+
`${this.name}:getEthQuery`, () => {
|
|
305
|
+
return __classPrivateFieldGet(this, _NetworkController_ethQuery, "f");
|
|
306
|
+
});
|
|
307
|
+
this.messagingSystem.registerActionHandler(
|
|
308
|
+
// TODO: Either fix this lint violation or explain why it's necessary to ignore.
|
|
309
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
310
|
+
`${this.name}:getNetworkClientById`, this.getNetworkClientById.bind(this));
|
|
311
|
+
this.messagingSystem.registerActionHandler(
|
|
312
|
+
// TODO: Either fix this lint violation or explain why it's necessary to ignore.
|
|
313
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
314
|
+
`${this.name}:getEIP1559Compatibility`, this.getEIP1559Compatibility.bind(this));
|
|
315
|
+
this.messagingSystem.registerActionHandler(
|
|
316
|
+
// TODO: Either fix this lint violation or explain why it's necessary to ignore.
|
|
317
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
318
|
+
`${this.name}:setActiveNetwork`, this.setActiveNetwork.bind(this));
|
|
319
|
+
this.messagingSystem.registerActionHandler(
|
|
320
|
+
// TODO: Either fix this lint violation or explain why it's necessary to ignore.
|
|
321
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
322
|
+
`${this.name}:setProviderType`, this.setProviderType.bind(this));
|
|
323
|
+
this.messagingSystem.registerActionHandler(
|
|
324
|
+
// TODO: Either fix this lint violation or explain why it's necessary to ignore.
|
|
325
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
326
|
+
`${this.name}:findNetworkClientIdByChainId`, this.findNetworkClientIdByChainId.bind(this));
|
|
327
|
+
this.messagingSystem.registerActionHandler(
|
|
328
|
+
// TODO: Either fix this lint violation or explain why it's necessary to ignore.
|
|
329
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
330
|
+
`${this.name}:getNetworkConfigurationByChainId`, this.getNetworkConfigurationByChainId.bind(this));
|
|
331
|
+
this.messagingSystem.registerActionHandler(
|
|
332
|
+
// ESLint is mistaken here; `name` is a string.
|
|
333
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
334
|
+
`${this.name}:getNetworkConfigurationByNetworkClientId`, this.getNetworkConfigurationByNetworkClientId.bind(this));
|
|
335
|
+
this.messagingSystem.registerActionHandler(
|
|
336
|
+
// TODO: Either fix this lint violation or explain why it's necessary to ignore.
|
|
337
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
338
|
+
`${this.name}:getSelectedNetworkClient`, this.getSelectedNetworkClient.bind(this));
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Accesses the provider and block tracker for the currently selected network.
|
|
342
|
+
* @returns The proxy and block tracker proxies.
|
|
343
|
+
* @deprecated This method has been replaced by `getSelectedNetworkClient` (which has a more easily used return type) and will be removed in a future release.
|
|
344
|
+
*/
|
|
345
|
+
getProviderAndBlockTracker() {
|
|
346
|
+
return {
|
|
347
|
+
provider: __classPrivateFieldGet(this, _NetworkController_providerProxy, "f"),
|
|
348
|
+
blockTracker: __classPrivateFieldGet(this, _NetworkController_blockTrackerProxy, "f"),
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Accesses the provider and block tracker for the currently selected network.
|
|
353
|
+
*
|
|
354
|
+
* @returns an object with the provider and block tracker proxies for the currently selected network.
|
|
355
|
+
*/
|
|
356
|
+
getSelectedNetworkClient() {
|
|
357
|
+
if (__classPrivateFieldGet(this, _NetworkController_providerProxy, "f") && __classPrivateFieldGet(this, _NetworkController_blockTrackerProxy, "f")) {
|
|
358
|
+
return {
|
|
359
|
+
provider: __classPrivateFieldGet(this, _NetworkController_providerProxy, "f"),
|
|
360
|
+
blockTracker: __classPrivateFieldGet(this, _NetworkController_blockTrackerProxy, "f"),
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
return undefined;
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Internally, the Infura and custom network clients are categorized by type
|
|
367
|
+
* so that when accessing either kind of network client, TypeScript knows
|
|
368
|
+
* which type to assign to the network client. For some cases it's more useful
|
|
369
|
+
* to be able to access network clients by ID instead of by type and then ID,
|
|
370
|
+
* so this function makes that possible.
|
|
371
|
+
*
|
|
372
|
+
* @returns The network clients registered so far, keyed by ID.
|
|
373
|
+
*/
|
|
374
|
+
getNetworkClientRegistry() {
|
|
375
|
+
const autoManagedNetworkClientRegistry = __classPrivateFieldGet(this, _NetworkController_instances, "m", _NetworkController_ensureAutoManagedNetworkClientRegistryPopulated).call(this);
|
|
376
|
+
return Object.assign({}, autoManagedNetworkClientRegistry[types_1.NetworkClientType.Infura], autoManagedNetworkClientRegistry[types_1.NetworkClientType.Custom]);
|
|
377
|
+
}
|
|
378
|
+
getNetworkClientById(networkClientId) {
|
|
379
|
+
if (!networkClientId) {
|
|
380
|
+
throw new Error('No network client ID was provided.');
|
|
381
|
+
}
|
|
382
|
+
const autoManagedNetworkClientRegistry = __classPrivateFieldGet(this, _NetworkController_instances, "m", _NetworkController_ensureAutoManagedNetworkClientRegistryPopulated).call(this);
|
|
383
|
+
if ((0, controller_utils_1.isInfuraNetworkType)(networkClientId)) {
|
|
384
|
+
const infuraNetworkClient = autoManagedNetworkClientRegistry[types_1.NetworkClientType.Infura][networkClientId];
|
|
385
|
+
// This is impossible to reach
|
|
386
|
+
/* istanbul ignore if */
|
|
387
|
+
if (!infuraNetworkClient) {
|
|
388
|
+
throw new Error(
|
|
389
|
+
// TODO: Either fix this lint violation or explain why it's necessary to ignore.
|
|
390
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
391
|
+
`No Infura network client was found with the ID "${networkClientId}".`);
|
|
392
|
+
}
|
|
393
|
+
return infuraNetworkClient;
|
|
394
|
+
}
|
|
395
|
+
const customNetworkClient = autoManagedNetworkClientRegistry[types_1.NetworkClientType.Custom][networkClientId];
|
|
396
|
+
if (!customNetworkClient) {
|
|
397
|
+
throw new Error(
|
|
398
|
+
// TODO: Either fix this lint violation or explain why it's necessary to ignore.
|
|
399
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
400
|
+
`No custom network client was found with the ID "${networkClientId}".`);
|
|
401
|
+
}
|
|
402
|
+
return customNetworkClient;
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Ensures that network clients for Infura and custom RPC endpoints have been
|
|
406
|
+
* created. Then, consulting state, initializes and establishes the currently
|
|
407
|
+
* selected network client.
|
|
408
|
+
*/
|
|
409
|
+
async initializeProvider() {
|
|
410
|
+
__classPrivateFieldGet(this, _NetworkController_instances, "m", _NetworkController_applyNetworkSelection).call(this, this.state.selectedNetworkClientId);
|
|
411
|
+
await this.lookupNetwork();
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* Refreshes the network meta with EIP-1559 support and the network status
|
|
415
|
+
* based on the given network client ID.
|
|
416
|
+
*
|
|
417
|
+
* @param networkClientId - The ID of the network client to update.
|
|
418
|
+
*/
|
|
419
|
+
async lookupNetworkByClientId(networkClientId) {
|
|
420
|
+
const isInfura = (0, controller_utils_1.isInfuraNetworkType)(networkClientId);
|
|
421
|
+
let updatedNetworkStatus;
|
|
422
|
+
let updatedIsEIP1559Compatible;
|
|
423
|
+
try {
|
|
424
|
+
updatedIsEIP1559Compatible = await __classPrivateFieldGet(this, _NetworkController_instances, "m", _NetworkController_determineEIP1559Compatibility).call(this, networkClientId);
|
|
425
|
+
updatedNetworkStatus = constants_1.NetworkStatus.Available;
|
|
426
|
+
}
|
|
427
|
+
catch (error) {
|
|
428
|
+
debugLog('NetworkController: lookupNetworkByClientId: ', error);
|
|
429
|
+
// TODO: mock ethQuery.sendAsync to throw error without error code
|
|
430
|
+
/* istanbul ignore else */
|
|
431
|
+
if (isErrorWithCode(error)) {
|
|
432
|
+
let responseBody;
|
|
433
|
+
if (isInfura &&
|
|
434
|
+
(0, utils_1.hasProperty)(error, 'message') &&
|
|
435
|
+
typeof error.message === 'string') {
|
|
436
|
+
try {
|
|
437
|
+
responseBody = JSON.parse(error.message);
|
|
438
|
+
}
|
|
439
|
+
catch {
|
|
440
|
+
// error.message must not be JSON
|
|
441
|
+
__classPrivateFieldGet(this, _NetworkController_log, "f")?.warn('NetworkController: lookupNetworkByClientId: json parse error: ', error);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
if ((0, utils_1.isPlainObject)(responseBody) &&
|
|
445
|
+
responseBody.error === constants_1.INFURA_BLOCKED_KEY) {
|
|
446
|
+
updatedNetworkStatus = constants_1.NetworkStatus.Blocked;
|
|
447
|
+
}
|
|
448
|
+
else if (error.code === rpc_errors_1.errorCodes.rpc.internal) {
|
|
449
|
+
updatedNetworkStatus = constants_1.NetworkStatus.Unknown;
|
|
450
|
+
__classPrivateFieldGet(this, _NetworkController_log, "f")?.warn('NetworkController: lookupNetworkByClientId: rpc internal error: ', error);
|
|
451
|
+
}
|
|
452
|
+
else {
|
|
453
|
+
updatedNetworkStatus = constants_1.NetworkStatus.Unavailable;
|
|
454
|
+
__classPrivateFieldGet(this, _NetworkController_log, "f")?.warn('NetworkController: lookupNetworkByClientId: ', error);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
else if (typeof Error !== 'undefined' &&
|
|
458
|
+
(0, utils_1.hasProperty)(error, 'message') &&
|
|
459
|
+
typeof error.message === 'string' &&
|
|
460
|
+
error.message.includes('No custom network client was found with the ID')) {
|
|
461
|
+
throw error;
|
|
462
|
+
}
|
|
463
|
+
else {
|
|
464
|
+
debugLog('NetworkController - could not determine network status', error);
|
|
465
|
+
updatedNetworkStatus = constants_1.NetworkStatus.Unknown;
|
|
466
|
+
__classPrivateFieldGet(this, _NetworkController_log, "f")?.warn('NetworkController: lookupNetworkByClientId: ', error);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
this.update((state) => {
|
|
470
|
+
if (state.networksMetadata[networkClientId] === undefined) {
|
|
471
|
+
state.networksMetadata[networkClientId] = {
|
|
472
|
+
status: constants_1.NetworkStatus.Unknown,
|
|
473
|
+
EIPS: {},
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
const meta = state.networksMetadata[networkClientId];
|
|
477
|
+
meta.status = updatedNetworkStatus;
|
|
478
|
+
if (updatedIsEIP1559Compatible === undefined) {
|
|
479
|
+
delete meta.EIPS[1559];
|
|
480
|
+
}
|
|
481
|
+
else {
|
|
482
|
+
meta.EIPS[1559] = updatedIsEIP1559Compatible;
|
|
483
|
+
}
|
|
484
|
+
});
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Persists the following metadata about the given or selected network to
|
|
488
|
+
* state:
|
|
489
|
+
*
|
|
490
|
+
* - The status of the network, namely, whether it is available, geo-blocked
|
|
491
|
+
* (Infura only), or unavailable, or whether the status is unknown
|
|
492
|
+
* - Whether the network supports EIP-1559, or whether it is unknown
|
|
493
|
+
*
|
|
494
|
+
* Note that it is possible for the network to be switched while this data is
|
|
495
|
+
* being collected. If that is the case, no metadata for the (now previously)
|
|
496
|
+
* selected network will be updated.
|
|
497
|
+
*
|
|
498
|
+
* @param networkClientId - The ID of the network client to update.
|
|
499
|
+
* If no ID is provided, uses the currently selected network.
|
|
500
|
+
*/
|
|
501
|
+
async lookupNetwork(networkClientId) {
|
|
502
|
+
if (networkClientId) {
|
|
503
|
+
await this.lookupNetworkByClientId(networkClientId);
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
506
|
+
if (!__classPrivateFieldGet(this, _NetworkController_ethQuery, "f")) {
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
const isInfura = __classPrivateFieldGet(this, _NetworkController_autoManagedNetworkClient, "f")?.configuration.type ===
|
|
510
|
+
types_1.NetworkClientType.Infura;
|
|
511
|
+
let networkChanged = false;
|
|
512
|
+
const listener = () => {
|
|
513
|
+
networkChanged = true;
|
|
514
|
+
this.messagingSystem.unsubscribe('NetworkController:networkDidChange', listener);
|
|
515
|
+
};
|
|
516
|
+
this.messagingSystem.subscribe('NetworkController:networkDidChange', listener);
|
|
517
|
+
let updatedNetworkStatus;
|
|
518
|
+
let updatedIsEIP1559Compatible;
|
|
519
|
+
try {
|
|
520
|
+
const isEIP1559Compatible = await __classPrivateFieldGet(this, _NetworkController_instances, "m", _NetworkController_determineEIP1559Compatibility).call(this, this.state.selectedNetworkClientId);
|
|
521
|
+
updatedNetworkStatus = constants_1.NetworkStatus.Available;
|
|
522
|
+
updatedIsEIP1559Compatible = isEIP1559Compatible;
|
|
523
|
+
}
|
|
524
|
+
catch (error) {
|
|
525
|
+
// TODO: mock ethQuery.sendAsync to throw error without error code
|
|
526
|
+
/* istanbul ignore else */
|
|
527
|
+
if (isErrorWithCode(error)) {
|
|
528
|
+
let responseBody;
|
|
529
|
+
if (isInfura &&
|
|
530
|
+
(0, utils_1.hasProperty)(error, 'message') &&
|
|
531
|
+
typeof error.message === 'string') {
|
|
532
|
+
try {
|
|
533
|
+
responseBody = JSON.parse(error.message);
|
|
534
|
+
}
|
|
535
|
+
catch (parseError) {
|
|
536
|
+
// error.message must not be JSON
|
|
537
|
+
__classPrivateFieldGet(this, _NetworkController_log, "f")?.warn('NetworkController: lookupNetwork: json parse error', parseError);
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
if ((0, utils_1.isPlainObject)(responseBody) &&
|
|
541
|
+
responseBody.error === constants_1.INFURA_BLOCKED_KEY) {
|
|
542
|
+
updatedNetworkStatus = constants_1.NetworkStatus.Blocked;
|
|
543
|
+
}
|
|
544
|
+
else if (error.code === rpc_errors_1.errorCodes.rpc.internal) {
|
|
545
|
+
updatedNetworkStatus = constants_1.NetworkStatus.Unknown;
|
|
546
|
+
__classPrivateFieldGet(this, _NetworkController_log, "f")?.warn('NetworkController: lookupNetwork: rpc internal error', error);
|
|
547
|
+
}
|
|
548
|
+
else {
|
|
549
|
+
updatedNetworkStatus = constants_1.NetworkStatus.Unavailable;
|
|
550
|
+
__classPrivateFieldGet(this, _NetworkController_log, "f")?.warn('NetworkController: lookupNetwork: ', error);
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
else {
|
|
554
|
+
debugLog('NetworkController - could not determine network status', error);
|
|
555
|
+
updatedNetworkStatus = constants_1.NetworkStatus.Unknown;
|
|
556
|
+
__classPrivateFieldGet(this, _NetworkController_log, "f")?.warn('NetworkController: lookupNetwork: ', error);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
if (networkChanged) {
|
|
560
|
+
// If the network has changed, then `lookupNetwork` either has been or is
|
|
561
|
+
// in the process of being called, so we don't need to go further.
|
|
562
|
+
return;
|
|
563
|
+
}
|
|
564
|
+
this.messagingSystem.unsubscribe('NetworkController:networkDidChange', listener);
|
|
565
|
+
this.update((state) => {
|
|
566
|
+
const meta = state.networksMetadata[state.selectedNetworkClientId];
|
|
567
|
+
meta.status = updatedNetworkStatus;
|
|
568
|
+
if (updatedIsEIP1559Compatible === undefined) {
|
|
569
|
+
delete meta.EIPS[1559];
|
|
570
|
+
}
|
|
571
|
+
else {
|
|
572
|
+
meta.EIPS[1559] = updatedIsEIP1559Compatible;
|
|
573
|
+
}
|
|
574
|
+
});
|
|
575
|
+
if (isInfura) {
|
|
576
|
+
if (updatedNetworkStatus === constants_1.NetworkStatus.Available) {
|
|
577
|
+
this.messagingSystem.publish('NetworkController:infuraIsUnblocked');
|
|
578
|
+
}
|
|
579
|
+
else if (updatedNetworkStatus === constants_1.NetworkStatus.Blocked) {
|
|
580
|
+
this.messagingSystem.publish('NetworkController:infuraIsBlocked');
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
else {
|
|
584
|
+
// Always publish infuraIsUnblocked regardless of network status to
|
|
585
|
+
// prevent consumers from being stuck in a blocked state if they were
|
|
586
|
+
// previously connected to an Infura network that was blocked
|
|
587
|
+
this.messagingSystem.publish('NetworkController:infuraIsUnblocked');
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* Convenience method to update provider network type settings.
|
|
592
|
+
*
|
|
593
|
+
* @param type - Human readable network name.
|
|
594
|
+
* @deprecated This has been replaced by `setActiveNetwork`, and will be
|
|
595
|
+
* removed in a future release
|
|
596
|
+
*/
|
|
597
|
+
async setProviderType(type) {
|
|
598
|
+
assert_1.strict.notStrictEqual(type, controller_utils_1.NetworkType.rpc,
|
|
599
|
+
// TODO: Either fix this lint violation or explain why it's necessary to ignore.
|
|
600
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
601
|
+
`NetworkController - cannot call "setProviderType" with type "${controller_utils_1.NetworkType.rpc}". Use "setActiveNetwork"`);
|
|
602
|
+
assert_1.strict.ok((0, controller_utils_1.isInfuraNetworkType)(type),
|
|
603
|
+
// TODO: Either fix this lint violation or explain why it's necessary to ignore.
|
|
604
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
605
|
+
`Unknown Infura provider type "${type}".`);
|
|
606
|
+
await this.setActiveNetwork(type);
|
|
607
|
+
}
|
|
608
|
+
/**
|
|
609
|
+
* Changes the selected network.
|
|
610
|
+
*
|
|
611
|
+
* @param networkClientId - The ID of a network client that will be used to
|
|
612
|
+
* make requests.
|
|
613
|
+
* @param options - Options for this method.
|
|
614
|
+
* @param options.updateState - Allows for updating state.
|
|
615
|
+
* @throws if no network client is associated with the given
|
|
616
|
+
* network client ID.
|
|
617
|
+
*/
|
|
618
|
+
async setActiveNetwork(networkClientId, options = {}) {
|
|
619
|
+
__classPrivateFieldSet(this, _NetworkController_previouslySelectedNetworkClientId, this.state.selectedNetworkClientId, "f");
|
|
620
|
+
await __classPrivateFieldGet(this, _NetworkController_instances, "m", _NetworkController_refreshNetwork).call(this, networkClientId, options);
|
|
621
|
+
}
|
|
622
|
+
/**
|
|
623
|
+
* Determines whether the network supports EIP-1559 by checking whether the
|
|
624
|
+
* latest block has a `baseFeePerGas` property, then updates state
|
|
625
|
+
* appropriately.
|
|
626
|
+
*
|
|
627
|
+
* @param networkClientId - The networkClientId to fetch the correct provider against which to check 1559 compatibility.
|
|
628
|
+
* @returns A promise that resolves to true if the network supports EIP-1559
|
|
629
|
+
* , false otherwise, or `undefined` if unable to determine the compatibility.
|
|
630
|
+
*/
|
|
631
|
+
async getEIP1559Compatibility(networkClientId) {
|
|
632
|
+
if (networkClientId) {
|
|
633
|
+
return this.get1559CompatibilityWithNetworkClientId(networkClientId);
|
|
634
|
+
}
|
|
635
|
+
if (!__classPrivateFieldGet(this, _NetworkController_ethQuery, "f")) {
|
|
636
|
+
return false;
|
|
637
|
+
}
|
|
638
|
+
const { EIPS } = this.state.networksMetadata[this.state.selectedNetworkClientId];
|
|
639
|
+
if (EIPS[1559] !== undefined) {
|
|
640
|
+
return EIPS[1559];
|
|
641
|
+
}
|
|
642
|
+
const isEIP1559Compatible = await __classPrivateFieldGet(this, _NetworkController_instances, "m", _NetworkController_determineEIP1559Compatibility).call(this, this.state.selectedNetworkClientId);
|
|
643
|
+
this.update((state) => {
|
|
644
|
+
if (isEIP1559Compatible !== undefined) {
|
|
645
|
+
state.networksMetadata[state.selectedNetworkClientId].EIPS[1559] =
|
|
646
|
+
isEIP1559Compatible;
|
|
647
|
+
}
|
|
648
|
+
});
|
|
649
|
+
return isEIP1559Compatible;
|
|
650
|
+
}
|
|
651
|
+
async get1559CompatibilityWithNetworkClientId(networkClientId) {
|
|
652
|
+
let metadata = this.state.networksMetadata[networkClientId];
|
|
653
|
+
if (metadata === undefined) {
|
|
654
|
+
await this.lookupNetwork(networkClientId);
|
|
655
|
+
metadata = this.state.networksMetadata[networkClientId];
|
|
656
|
+
}
|
|
657
|
+
const { EIPS } = metadata;
|
|
658
|
+
// may want to include some 'freshness' value - something to make sure we refetch this from time to time
|
|
659
|
+
return EIPS[1559];
|
|
660
|
+
}
|
|
661
|
+
/**
|
|
662
|
+
* Ensures that the provider and block tracker proxies are pointed to the
|
|
663
|
+
* currently selected network and refreshes the metadata for the
|
|
664
|
+
*/
|
|
665
|
+
async resetConnection() {
|
|
666
|
+
await __classPrivateFieldGet(this, _NetworkController_instances, "m", _NetworkController_refreshNetwork).call(this, this.state.selectedNetworkClientId);
|
|
667
|
+
}
|
|
668
|
+
/**
|
|
669
|
+
* Returns the network configuration that has been filed under the given chain
|
|
670
|
+
* ID.
|
|
671
|
+
*
|
|
672
|
+
* @param chainId - The chain ID to use as a key.
|
|
673
|
+
* @returns The network configuration if one exists, or undefined.
|
|
674
|
+
*/
|
|
675
|
+
getNetworkConfigurationByChainId(chainId) {
|
|
676
|
+
return this.state.networkConfigurationsByChainId[chainId];
|
|
677
|
+
}
|
|
678
|
+
/**
|
|
679
|
+
* Returns the network configuration that contains an RPC endpoint with the
|
|
680
|
+
* given network client ID.
|
|
681
|
+
*
|
|
682
|
+
* @param networkClientId - The network client ID to use as a key.
|
|
683
|
+
* @returns The network configuration if one exists, or undefined.
|
|
684
|
+
*/
|
|
685
|
+
getNetworkConfigurationByNetworkClientId(networkClientId) {
|
|
686
|
+
return __classPrivateFieldGet(this, _NetworkController_networkConfigurationsByNetworkClientId, "f").get(networkClientId);
|
|
687
|
+
}
|
|
688
|
+
/**
|
|
689
|
+
* Creates and registers network clients for the collection of Infura and
|
|
690
|
+
* custom RPC endpoints that can be used to make requests for a particular
|
|
691
|
+
* chain, storing the given configuration object in state for later reference.
|
|
692
|
+
*
|
|
693
|
+
* @param fields - The object that describes the new network/chain and lists
|
|
694
|
+
* the RPC endpoints which front that chain.
|
|
695
|
+
* @returns The newly added network configuration.
|
|
696
|
+
* @throws if any part of `fields` would produce invalid state.
|
|
697
|
+
* @see {@link NetworkConfiguration}
|
|
698
|
+
*/
|
|
699
|
+
addNetwork(fields) {
|
|
700
|
+
const { rpcEndpoints: setOfRpcEndpointFields } = fields;
|
|
701
|
+
const autoManagedNetworkClientRegistry = __classPrivateFieldGet(this, _NetworkController_instances, "m", _NetworkController_ensureAutoManagedNetworkClientRegistryPopulated).call(this);
|
|
702
|
+
__classPrivateFieldGet(this, _NetworkController_instances, "m", _NetworkController_validateNetworkFields).call(this, {
|
|
703
|
+
mode: 'add',
|
|
704
|
+
networkFields: fields,
|
|
705
|
+
autoManagedNetworkClientRegistry,
|
|
706
|
+
});
|
|
707
|
+
const networkClientOperations = setOfRpcEndpointFields.map((defaultOrCustomRpcEndpointFields) => {
|
|
708
|
+
const rpcEndpoint = defaultOrCustomRpcEndpointFields.type === RpcEndpointType.Custom
|
|
709
|
+
? {
|
|
710
|
+
...defaultOrCustomRpcEndpointFields,
|
|
711
|
+
networkClientId: (0, uuid_1.v4)(),
|
|
712
|
+
}
|
|
713
|
+
: defaultOrCustomRpcEndpointFields;
|
|
714
|
+
return {
|
|
715
|
+
type: 'add',
|
|
716
|
+
rpcEndpoint,
|
|
717
|
+
};
|
|
718
|
+
});
|
|
719
|
+
const newNetworkConfiguration = __classPrivateFieldGet(this, _NetworkController_instances, "m", _NetworkController_determineNetworkConfigurationToPersist).call(this, {
|
|
720
|
+
networkFields: fields,
|
|
721
|
+
networkClientOperations,
|
|
722
|
+
});
|
|
723
|
+
__classPrivateFieldGet(this, _NetworkController_instances, "m", _NetworkController_registerNetworkClientsAsNeeded).call(this, {
|
|
724
|
+
networkFields: fields,
|
|
725
|
+
networkClientOperations,
|
|
726
|
+
autoManagedNetworkClientRegistry,
|
|
727
|
+
});
|
|
728
|
+
this.update((state) => {
|
|
729
|
+
__classPrivateFieldGet(this, _NetworkController_instances, "m", _NetworkController_updateNetworkConfigurations).call(this, {
|
|
730
|
+
state,
|
|
731
|
+
mode: 'add',
|
|
732
|
+
networkFields: fields,
|
|
733
|
+
networkConfigurationToPersist: newNetworkConfiguration,
|
|
734
|
+
});
|
|
735
|
+
});
|
|
736
|
+
__classPrivateFieldSet(this, _NetworkController_networkConfigurationsByNetworkClientId, buildNetworkConfigurationsByNetworkClientId(this.state.networkConfigurationsByChainId), "f");
|
|
737
|
+
this.messagingSystem.publish(`${controllerName}:networkAdded`, newNetworkConfiguration);
|
|
738
|
+
return newNetworkConfiguration;
|
|
739
|
+
}
|
|
740
|
+
/**
|
|
741
|
+
* Updates the configuration for a previously stored network filed under the
|
|
742
|
+
* given chain ID, creating + registering new network clients to represent RPC
|
|
743
|
+
* endpoints that have been added and destroying + unregistering existing
|
|
744
|
+
* network clients for RPC endpoints that have been removed.
|
|
745
|
+
*
|
|
746
|
+
* Note that if `chainId` is changed, then all network clients associated with
|
|
747
|
+
* that chain will be removed and re-added, even if none of the RPC endpoints
|
|
748
|
+
* have changed.
|
|
749
|
+
*
|
|
750
|
+
* @param chainId - The chain ID associated with an existing network.
|
|
751
|
+
* @param fields - The object that describes the updates to the network/chain,
|
|
752
|
+
* including the new set of RPC endpoints which should front that chain.
|
|
753
|
+
* @param options - Options to provide.
|
|
754
|
+
* @param options.replacementSelectedRpcEndpointIndex - Usually you cannot
|
|
755
|
+
* remove an RPC endpoint that is being represented by the currently selected
|
|
756
|
+
* network client. This option allows you to specify another RPC endpoint
|
|
757
|
+
* (either an existing one or a new one) that should be used to select a new
|
|
758
|
+
* network instead.
|
|
759
|
+
* @returns The updated network configuration.
|
|
760
|
+
* @throws if `chainId` does not refer to an existing network configuration,
|
|
761
|
+
* if any part of `fields` would produce invalid state, etc.
|
|
762
|
+
* @see {@link NetworkConfiguration}
|
|
763
|
+
*/
|
|
764
|
+
async updateNetwork(chainId, fields, { replacementSelectedRpcEndpointIndex, } = {}) {
|
|
765
|
+
const existingNetworkConfiguration = this.state.networkConfigurationsByChainId[chainId];
|
|
766
|
+
if (existingNetworkConfiguration === undefined) {
|
|
767
|
+
throw new Error(`Could not update network: Cannot find network configuration for chain ${(0, util_1.inspect)(chainId)}`);
|
|
768
|
+
}
|
|
769
|
+
const existingChainId = chainId;
|
|
770
|
+
const { chainId: newChainId, rpcEndpoints: setOfNewRpcEndpointFields } = fields;
|
|
771
|
+
const autoManagedNetworkClientRegistry = __classPrivateFieldGet(this, _NetworkController_instances, "m", _NetworkController_ensureAutoManagedNetworkClientRegistryPopulated).call(this);
|
|
772
|
+
__classPrivateFieldGet(this, _NetworkController_instances, "m", _NetworkController_validateNetworkFields).call(this, {
|
|
773
|
+
mode: 'update',
|
|
774
|
+
networkFields: fields,
|
|
775
|
+
existingNetworkConfiguration,
|
|
776
|
+
autoManagedNetworkClientRegistry,
|
|
777
|
+
});
|
|
778
|
+
const networkClientOperations = [];
|
|
779
|
+
for (const newRpcEndpointFields of setOfNewRpcEndpointFields) {
|
|
780
|
+
const existingRpcEndpointForNoop = existingNetworkConfiguration.rpcEndpoints.find((rpcEndpoint) => {
|
|
781
|
+
return (rpcEndpoint.type === newRpcEndpointFields.type &&
|
|
782
|
+
rpcEndpoint.url === newRpcEndpointFields.url &&
|
|
783
|
+
(rpcEndpoint.networkClientId ===
|
|
784
|
+
newRpcEndpointFields.networkClientId ||
|
|
785
|
+
newRpcEndpointFields.networkClientId === undefined));
|
|
786
|
+
});
|
|
787
|
+
const existingRpcEndpointForReplaceWhenChainChanged = existingNetworkConfiguration.rpcEndpoints.find((rpcEndpoint) => {
|
|
788
|
+
return ((rpcEndpoint.type === RpcEndpointType.Infura &&
|
|
789
|
+
newRpcEndpointFields.type === RpcEndpointType.Infura) ||
|
|
790
|
+
(rpcEndpoint.type === newRpcEndpointFields.type &&
|
|
791
|
+
rpcEndpoint.networkClientId ===
|
|
792
|
+
newRpcEndpointFields.networkClientId &&
|
|
793
|
+
rpcEndpoint.url === newRpcEndpointFields.url));
|
|
794
|
+
});
|
|
795
|
+
const existingRpcEndpointForReplaceWhenChainNotChanged = existingNetworkConfiguration.rpcEndpoints.find((rpcEndpoint) => {
|
|
796
|
+
return (rpcEndpoint.type === newRpcEndpointFields.type &&
|
|
797
|
+
(rpcEndpoint.url === newRpcEndpointFields.url ||
|
|
798
|
+
rpcEndpoint.networkClientId ===
|
|
799
|
+
newRpcEndpointFields.networkClientId));
|
|
800
|
+
});
|
|
801
|
+
if (newChainId !== existingChainId &&
|
|
802
|
+
existingRpcEndpointForReplaceWhenChainChanged !== undefined) {
|
|
803
|
+
const newRpcEndpoint = newRpcEndpointFields.type === RpcEndpointType.Infura
|
|
804
|
+
? newRpcEndpointFields
|
|
805
|
+
: { ...newRpcEndpointFields, networkClientId: (0, uuid_1.v4)() };
|
|
806
|
+
networkClientOperations.push({
|
|
807
|
+
type: 'replace',
|
|
808
|
+
oldRpcEndpoint: existingRpcEndpointForReplaceWhenChainChanged,
|
|
809
|
+
newRpcEndpoint,
|
|
810
|
+
});
|
|
811
|
+
}
|
|
812
|
+
else if (existingRpcEndpointForNoop !== undefined) {
|
|
813
|
+
let newRpcEndpoint;
|
|
814
|
+
if (existingRpcEndpointForNoop.type === RpcEndpointType.Infura) {
|
|
815
|
+
newRpcEndpoint = existingRpcEndpointForNoop;
|
|
816
|
+
}
|
|
817
|
+
else {
|
|
818
|
+
// `networkClientId` shouldn't be missing at this point; if it is,
|
|
819
|
+
// that's a mistake, so fill it back in
|
|
820
|
+
newRpcEndpoint = Object.assign({}, newRpcEndpointFields, {
|
|
821
|
+
networkClientId: existingRpcEndpointForNoop.networkClientId,
|
|
822
|
+
});
|
|
823
|
+
}
|
|
824
|
+
networkClientOperations.push({
|
|
825
|
+
type: 'noop',
|
|
826
|
+
rpcEndpoint: newRpcEndpoint,
|
|
827
|
+
});
|
|
828
|
+
}
|
|
829
|
+
else if (existingRpcEndpointForReplaceWhenChainNotChanged !== undefined) {
|
|
830
|
+
let newRpcEndpoint;
|
|
831
|
+
/* istanbul ignore if */
|
|
832
|
+
if (newRpcEndpointFields.type === RpcEndpointType.Infura) {
|
|
833
|
+
// This case can't actually happen. If we're here, it means that some
|
|
834
|
+
// part of the RPC endpoint changed. But there is no part of an Infura
|
|
835
|
+
// RPC endpoint that can be changed (as it would immediately make that
|
|
836
|
+
// RPC endpoint self-inconsistent). This is just here to appease
|
|
837
|
+
// TypeScript.
|
|
838
|
+
newRpcEndpoint = newRpcEndpointFields;
|
|
839
|
+
}
|
|
840
|
+
else {
|
|
841
|
+
newRpcEndpoint = {
|
|
842
|
+
...newRpcEndpointFields,
|
|
843
|
+
networkClientId: (0, uuid_1.v4)(),
|
|
844
|
+
};
|
|
845
|
+
}
|
|
846
|
+
networkClientOperations.push({
|
|
847
|
+
type: 'replace',
|
|
848
|
+
oldRpcEndpoint: existingRpcEndpointForReplaceWhenChainNotChanged,
|
|
849
|
+
newRpcEndpoint,
|
|
850
|
+
});
|
|
851
|
+
}
|
|
852
|
+
else {
|
|
853
|
+
const newRpcEndpoint = newRpcEndpointFields.type === RpcEndpointType.Infura
|
|
854
|
+
? newRpcEndpointFields
|
|
855
|
+
: { ...newRpcEndpointFields, networkClientId: (0, uuid_1.v4)() };
|
|
856
|
+
const networkClientOperation = {
|
|
857
|
+
type: 'add',
|
|
858
|
+
rpcEndpoint: newRpcEndpoint,
|
|
859
|
+
};
|
|
860
|
+
networkClientOperations.push(networkClientOperation);
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
for (const existingRpcEndpoint of existingNetworkConfiguration.rpcEndpoints) {
|
|
864
|
+
if (!networkClientOperations.some((networkClientOperation) => {
|
|
865
|
+
const otherRpcEndpoint = networkClientOperation.type === 'replace'
|
|
866
|
+
? networkClientOperation.oldRpcEndpoint
|
|
867
|
+
: networkClientOperation.rpcEndpoint;
|
|
868
|
+
return (otherRpcEndpoint.type === existingRpcEndpoint.type &&
|
|
869
|
+
otherRpcEndpoint.networkClientId ===
|
|
870
|
+
existingRpcEndpoint.networkClientId &&
|
|
871
|
+
otherRpcEndpoint.url === existingRpcEndpoint.url);
|
|
872
|
+
})) {
|
|
873
|
+
const networkClientOperation = {
|
|
874
|
+
type: 'remove',
|
|
875
|
+
rpcEndpoint: existingRpcEndpoint,
|
|
876
|
+
};
|
|
877
|
+
networkClientOperations.push(networkClientOperation);
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
const updatedNetworkConfiguration = __classPrivateFieldGet(this, _NetworkController_instances, "m", _NetworkController_determineNetworkConfigurationToPersist).call(this, {
|
|
881
|
+
networkFields: fields,
|
|
882
|
+
networkClientOperations,
|
|
883
|
+
});
|
|
884
|
+
if (replacementSelectedRpcEndpointIndex === undefined &&
|
|
885
|
+
networkClientOperations.some((networkClientOperation) => {
|
|
886
|
+
return (networkClientOperation.type === 'remove' &&
|
|
887
|
+
networkClientOperation.rpcEndpoint.networkClientId ===
|
|
888
|
+
this.state.selectedNetworkClientId);
|
|
889
|
+
}) &&
|
|
890
|
+
!networkClientOperations.some((networkClientOperation) => {
|
|
891
|
+
return (networkClientOperation.type === 'replace' &&
|
|
892
|
+
networkClientOperation.oldRpcEndpoint.networkClientId ===
|
|
893
|
+
this.state.selectedNetworkClientId);
|
|
894
|
+
})) {
|
|
895
|
+
throw new Error(
|
|
896
|
+
// False negative - this is a string.
|
|
897
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
898
|
+
`Could not update network: Cannot update RPC endpoints in such a way that the selected network '${this.state.selectedNetworkClientId}' would be removed without a replacement. Choose a different RPC endpoint as the selected network via the \`replacementSelectedRpcEndpointIndex\` option.`);
|
|
899
|
+
}
|
|
900
|
+
__classPrivateFieldGet(this, _NetworkController_instances, "m", _NetworkController_registerNetworkClientsAsNeeded).call(this, {
|
|
901
|
+
networkFields: fields,
|
|
902
|
+
networkClientOperations,
|
|
903
|
+
autoManagedNetworkClientRegistry,
|
|
904
|
+
});
|
|
905
|
+
const replacementSelectedRpcEndpointWithIndex = networkClientOperations
|
|
906
|
+
.map((networkClientOperation, index) => [networkClientOperation, index])
|
|
907
|
+
.find(([networkClientOperation, _index]) => {
|
|
908
|
+
return (networkClientOperation.type === 'replace' &&
|
|
909
|
+
networkClientOperation.oldRpcEndpoint.networkClientId ===
|
|
910
|
+
this.state.selectedNetworkClientId);
|
|
911
|
+
});
|
|
912
|
+
const correctedReplacementSelectedRpcEndpointIndex = replacementSelectedRpcEndpointIndex ??
|
|
913
|
+
replacementSelectedRpcEndpointWithIndex?.[1];
|
|
914
|
+
let rpcEndpointToSelect;
|
|
915
|
+
if (correctedReplacementSelectedRpcEndpointIndex !== undefined) {
|
|
916
|
+
rpcEndpointToSelect =
|
|
917
|
+
updatedNetworkConfiguration.rpcEndpoints[correctedReplacementSelectedRpcEndpointIndex];
|
|
918
|
+
if (rpcEndpointToSelect === undefined) {
|
|
919
|
+
throw new Error(`Could not update network: \`replacementSelectedRpcEndpointIndex\` ${correctedReplacementSelectedRpcEndpointIndex} does not refer to an entry in \`rpcEndpoints\``);
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
if (rpcEndpointToSelect &&
|
|
923
|
+
rpcEndpointToSelect.networkClientId !== this.state.selectedNetworkClientId) {
|
|
924
|
+
await this.setActiveNetwork(rpcEndpointToSelect.networkClientId, {
|
|
925
|
+
updateState: (state) => {
|
|
926
|
+
__classPrivateFieldGet(this, _NetworkController_instances, "m", _NetworkController_updateNetworkConfigurations).call(this, {
|
|
927
|
+
state,
|
|
928
|
+
mode: 'update',
|
|
929
|
+
networkFields: fields,
|
|
930
|
+
networkConfigurationToPersist: updatedNetworkConfiguration,
|
|
931
|
+
existingNetworkConfiguration,
|
|
932
|
+
});
|
|
933
|
+
},
|
|
934
|
+
});
|
|
935
|
+
}
|
|
936
|
+
else {
|
|
937
|
+
this.update((state) => {
|
|
938
|
+
__classPrivateFieldGet(this, _NetworkController_instances, "m", _NetworkController_updateNetworkConfigurations).call(this, {
|
|
939
|
+
state,
|
|
940
|
+
mode: 'update',
|
|
941
|
+
networkFields: fields,
|
|
942
|
+
networkConfigurationToPersist: updatedNetworkConfiguration,
|
|
943
|
+
existingNetworkConfiguration,
|
|
944
|
+
});
|
|
945
|
+
});
|
|
946
|
+
}
|
|
947
|
+
__classPrivateFieldSet(this, _NetworkController_networkConfigurationsByNetworkClientId, buildNetworkConfigurationsByNetworkClientId(this.state.networkConfigurationsByChainId), "f");
|
|
948
|
+
__classPrivateFieldGet(this, _NetworkController_instances, "m", _NetworkController_unregisterNetworkClientsAsNeeded).call(this, {
|
|
949
|
+
networkClientOperations,
|
|
950
|
+
autoManagedNetworkClientRegistry,
|
|
951
|
+
});
|
|
952
|
+
return updatedNetworkConfiguration;
|
|
953
|
+
}
|
|
954
|
+
/**
|
|
955
|
+
* Destroys and unregisters the network identified by the given chain ID, also
|
|
956
|
+
* removing the associated network configuration from state.
|
|
957
|
+
*
|
|
958
|
+
* @param chainId - The chain ID associated with an existing network.
|
|
959
|
+
* @throws if `chainId` does not refer to an existing network configuration,
|
|
960
|
+
* or if the currently selected network is being removed.
|
|
961
|
+
* @see {@link NetworkConfiguration}
|
|
962
|
+
*/
|
|
963
|
+
removeNetwork(chainId) {
|
|
964
|
+
const existingNetworkConfiguration = this.state.networkConfigurationsByChainId[chainId];
|
|
965
|
+
if (existingNetworkConfiguration === undefined) {
|
|
966
|
+
throw new Error(`Cannot find network configuration for chain ${(0, util_1.inspect)(chainId)}`);
|
|
967
|
+
}
|
|
968
|
+
if (existingNetworkConfiguration.rpcEndpoints.some((rpcEndpoint) => rpcEndpoint.networkClientId === this.state.selectedNetworkClientId)) {
|
|
969
|
+
throw new Error(`Cannot remove the currently selected network`);
|
|
970
|
+
}
|
|
971
|
+
const autoManagedNetworkClientRegistry = __classPrivateFieldGet(this, _NetworkController_instances, "m", _NetworkController_ensureAutoManagedNetworkClientRegistryPopulated).call(this);
|
|
972
|
+
const networkClientOperations = existingNetworkConfiguration.rpcEndpoints.map((rpcEndpoint) => {
|
|
973
|
+
return {
|
|
974
|
+
type: 'remove',
|
|
975
|
+
rpcEndpoint,
|
|
976
|
+
};
|
|
977
|
+
});
|
|
978
|
+
__classPrivateFieldGet(this, _NetworkController_instances, "m", _NetworkController_unregisterNetworkClientsAsNeeded).call(this, {
|
|
979
|
+
networkClientOperations,
|
|
980
|
+
autoManagedNetworkClientRegistry,
|
|
981
|
+
});
|
|
982
|
+
this.update((state) => {
|
|
983
|
+
__classPrivateFieldGet(this, _NetworkController_instances, "m", _NetworkController_updateNetworkConfigurations).call(this, {
|
|
984
|
+
state,
|
|
985
|
+
mode: 'remove',
|
|
986
|
+
existingNetworkConfiguration,
|
|
987
|
+
});
|
|
988
|
+
});
|
|
989
|
+
__classPrivateFieldSet(this, _NetworkController_networkConfigurationsByNetworkClientId, buildNetworkConfigurationsByNetworkClientId(this.state.networkConfigurationsByChainId), "f");
|
|
990
|
+
}
|
|
991
|
+
/**
|
|
992
|
+
* Assuming that the network has been previously switched, switches to this
|
|
993
|
+
* new network.
|
|
994
|
+
*
|
|
995
|
+
* If the network has not been previously switched, this method is equivalent
|
|
996
|
+
* to {@link resetConnection}.
|
|
997
|
+
*/
|
|
998
|
+
async rollbackToPreviousProvider() {
|
|
999
|
+
await __classPrivateFieldGet(this, _NetworkController_instances, "m", _NetworkController_refreshNetwork).call(this, __classPrivateFieldGet(this, _NetworkController_previouslySelectedNetworkClientId, "f"));
|
|
1000
|
+
}
|
|
1001
|
+
/**
|
|
1002
|
+
* Deactivates the controller, stopping any ongoing polling.
|
|
1003
|
+
*
|
|
1004
|
+
* In-progress requests will not be aborted.
|
|
1005
|
+
*/
|
|
1006
|
+
async destroy() {
|
|
1007
|
+
await __classPrivateFieldGet(this, _NetworkController_blockTrackerProxy, "f")?.destroy();
|
|
1008
|
+
}
|
|
1009
|
+
/**
|
|
1010
|
+
* Merges the given backup data into controller state.
|
|
1011
|
+
*
|
|
1012
|
+
* @param backup - The data that has been backed up.
|
|
1013
|
+
* @param backup.networkConfigurationsByChainId - Network configurations,
|
|
1014
|
+
* keyed by chain ID.
|
|
1015
|
+
*/
|
|
1016
|
+
loadBackup({ networkConfigurationsByChainId, }) {
|
|
1017
|
+
this.update((state) => {
|
|
1018
|
+
state.networkConfigurationsByChainId = {
|
|
1019
|
+
...state.networkConfigurationsByChainId,
|
|
1020
|
+
...networkConfigurationsByChainId,
|
|
1021
|
+
};
|
|
1022
|
+
});
|
|
1023
|
+
}
|
|
1024
|
+
/**
|
|
1025
|
+
* Searches for a network configuration ID with the given ChainID and returns it.
|
|
1026
|
+
*
|
|
1027
|
+
* @param chainId - ChainId to search for
|
|
1028
|
+
* @returns networkClientId of the network configuration with the given chainId
|
|
1029
|
+
*/
|
|
1030
|
+
findNetworkClientIdByChainId(chainId) {
|
|
1031
|
+
const networkClients = this.getNetworkClientRegistry();
|
|
1032
|
+
const networkClientEntry = Object.entries(networkClients).find(([_, networkClient]) => networkClient.configuration.chainId === chainId);
|
|
1033
|
+
if (networkClientEntry === undefined) {
|
|
1034
|
+
throw new Error("Couldn't find networkClientId for chainId");
|
|
1035
|
+
}
|
|
1036
|
+
return networkClientEntry[0];
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
exports.NetworkController = NetworkController;
|
|
1040
|
+
_NetworkController_ethQuery = new WeakMap(), _NetworkController_infuraProjectId = new WeakMap(), _NetworkController_previouslySelectedNetworkClientId = new WeakMap(), _NetworkController_providerProxy = new WeakMap(), _NetworkController_blockTrackerProxy = new WeakMap(), _NetworkController_autoManagedNetworkClientRegistry = new WeakMap(), _NetworkController_autoManagedNetworkClient = new WeakMap(), _NetworkController_log = new WeakMap(), _NetworkController_networkConfigurationsByNetworkClientId = new WeakMap(), _NetworkController_instances = new WeakSet(), _NetworkController_refreshNetwork =
|
|
1041
|
+
/**
|
|
1042
|
+
* Executes a series of steps to switch the network:
|
|
1043
|
+
*
|
|
1044
|
+
* 1. Notifies subscribers via the messenger that the network is about to be
|
|
1045
|
+
* switched (and, really, that the global provider and block tracker proxies
|
|
1046
|
+
* will be re-pointed to a new network).
|
|
1047
|
+
* 2. Looks up a known and preinitialized network client matching the given
|
|
1048
|
+
* ID and uses it to re-point the aforementioned provider and block tracker
|
|
1049
|
+
* proxies.
|
|
1050
|
+
* 3. Notifies subscribers via the messenger that the network has switched.
|
|
1051
|
+
* 4. Captures metadata for the newly switched network in state.
|
|
1052
|
+
*
|
|
1053
|
+
* @param networkClientId - The ID of a network client that requests will be
|
|
1054
|
+
* routed through (either the name of an Infura network or the ID of a custom
|
|
1055
|
+
* network configuration).
|
|
1056
|
+
* @param options - Options for this method.
|
|
1057
|
+
* @param options.updateState - Allows for updating state.
|
|
1058
|
+
*/
|
|
1059
|
+
async function _NetworkController_refreshNetwork(networkClientId, options = {}) {
|
|
1060
|
+
this.messagingSystem.publish('NetworkController:networkWillChange', this.state);
|
|
1061
|
+
__classPrivateFieldGet(this, _NetworkController_instances, "m", _NetworkController_applyNetworkSelection).call(this, networkClientId, options);
|
|
1062
|
+
this.messagingSystem.publish('NetworkController:networkDidChange', this.state);
|
|
1063
|
+
await this.lookupNetwork();
|
|
1064
|
+
}, _NetworkController_getLatestBlock = function _NetworkController_getLatestBlock(networkClientId) {
|
|
1065
|
+
if (networkClientId === undefined) {
|
|
1066
|
+
networkClientId = this.state.selectedNetworkClientId;
|
|
1067
|
+
}
|
|
1068
|
+
const networkClient = this.getNetworkClientById(networkClientId);
|
|
1069
|
+
const ethQuery = new eth_query_1.default(networkClient.provider);
|
|
1070
|
+
return new Promise((resolve, reject) => {
|
|
1071
|
+
ethQuery.sendAsync({ method: 'eth_getBlockByNumber', params: ['latest', false] }, (error, block) => {
|
|
1072
|
+
if (error) {
|
|
1073
|
+
reject(error);
|
|
1074
|
+
}
|
|
1075
|
+
else {
|
|
1076
|
+
// TODO: Validate this type
|
|
1077
|
+
resolve(block);
|
|
1078
|
+
}
|
|
1079
|
+
});
|
|
1080
|
+
});
|
|
1081
|
+
}, _NetworkController_determineEIP1559Compatibility =
|
|
1082
|
+
/**
|
|
1083
|
+
* Retrieves and checks the latest block from the currently selected
|
|
1084
|
+
* network; if the block has a `baseFeePerGas` property, then we know
|
|
1085
|
+
* that the network supports EIP-1559; otherwise it doesn't.
|
|
1086
|
+
*
|
|
1087
|
+
* @param networkClientId - The networkClientId to fetch the correct provider against which to check 1559 compatibility
|
|
1088
|
+
* @returns A promise that resolves to `true` if the network supports EIP-1559,
|
|
1089
|
+
* `false` otherwise, or `undefined` if unable to retrieve the last block.
|
|
1090
|
+
*/
|
|
1091
|
+
async function _NetworkController_determineEIP1559Compatibility(networkClientId) {
|
|
1092
|
+
const latestBlock = await __classPrivateFieldGet(this, _NetworkController_instances, "m", _NetworkController_getLatestBlock).call(this, networkClientId);
|
|
1093
|
+
if (!latestBlock) {
|
|
1094
|
+
return undefined;
|
|
1095
|
+
}
|
|
1096
|
+
return latestBlock.baseFeePerGas !== undefined;
|
|
1097
|
+
}, _NetworkController_validateNetworkFields = function _NetworkController_validateNetworkFields(args) {
|
|
1098
|
+
const { mode, networkFields, autoManagedNetworkClientRegistry } = args;
|
|
1099
|
+
const existingNetworkConfiguration = 'existingNetworkConfiguration' in args
|
|
1100
|
+
? args.existingNetworkConfiguration
|
|
1101
|
+
: null;
|
|
1102
|
+
const errorMessagePrefix = mode === 'update' ? 'Could not update network' : 'Could not add network';
|
|
1103
|
+
if (!(0, utils_1.isStrictHexString)(networkFields.chainId) ||
|
|
1104
|
+
!(0, controller_utils_1.isSafeChainId)(networkFields.chainId)) {
|
|
1105
|
+
throw new Error(`${errorMessagePrefix}: Invalid \`chainId\` ${(0, util_1.inspect)(networkFields.chainId)} (must start with "0x" and not exceed the maximum)`);
|
|
1106
|
+
}
|
|
1107
|
+
if (existingNetworkConfiguration === null ||
|
|
1108
|
+
networkFields.chainId !== existingNetworkConfiguration.chainId) {
|
|
1109
|
+
const existingNetworkConfigurationViaChainId = this.state.networkConfigurationsByChainId[networkFields.chainId];
|
|
1110
|
+
if (existingNetworkConfigurationViaChainId !== undefined) {
|
|
1111
|
+
if (existingNetworkConfiguration === null) {
|
|
1112
|
+
throw new Error(
|
|
1113
|
+
// False negative - these are strings.
|
|
1114
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
1115
|
+
`Could not add network for chain ${args.networkFields.chainId} as another network for that chain already exists ('${existingNetworkConfigurationViaChainId.name}')`);
|
|
1116
|
+
}
|
|
1117
|
+
else {
|
|
1118
|
+
throw new Error(
|
|
1119
|
+
// False negative - these are strings.
|
|
1120
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
1121
|
+
`Cannot move network from chain ${existingNetworkConfiguration.chainId} to ${networkFields.chainId} as another network for that chain already exists ('${existingNetworkConfigurationViaChainId.name}')`);
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
const isInvalidDefaultBlockExplorerUrlIndex = networkFields.blockExplorerUrls.length > 0
|
|
1126
|
+
? networkFields.defaultBlockExplorerUrlIndex === undefined ||
|
|
1127
|
+
networkFields.blockExplorerUrls[networkFields.defaultBlockExplorerUrlIndex] === undefined
|
|
1128
|
+
: networkFields.defaultBlockExplorerUrlIndex !== undefined;
|
|
1129
|
+
if (isInvalidDefaultBlockExplorerUrlIndex) {
|
|
1130
|
+
throw new Error(`${errorMessagePrefix}: \`defaultBlockExplorerUrlIndex\` must refer to an entry in \`blockExplorerUrls\``);
|
|
1131
|
+
}
|
|
1132
|
+
if (networkFields.rpcEndpoints.length === 0) {
|
|
1133
|
+
throw new Error(`${errorMessagePrefix}: \`rpcEndpoints\` must be a non-empty array`);
|
|
1134
|
+
}
|
|
1135
|
+
for (const rpcEndpointFields of networkFields.rpcEndpoints) {
|
|
1136
|
+
if (!isValidUrl(rpcEndpointFields.url)) {
|
|
1137
|
+
throw new Error(`${errorMessagePrefix}: An entry in \`rpcEndpoints\` has invalid URL ${(0, util_1.inspect)(rpcEndpointFields.url)}`);
|
|
1138
|
+
}
|
|
1139
|
+
const networkClientId = 'networkClientId' in rpcEndpointFields
|
|
1140
|
+
? rpcEndpointFields.networkClientId
|
|
1141
|
+
: undefined;
|
|
1142
|
+
if (rpcEndpointFields.type === RpcEndpointType.Custom &&
|
|
1143
|
+
networkClientId !== undefined &&
|
|
1144
|
+
(0, controller_utils_1.isInfuraNetworkType)(networkClientId)) {
|
|
1145
|
+
throw new Error(
|
|
1146
|
+
// This is a string.
|
|
1147
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
1148
|
+
`${errorMessagePrefix}: Custom RPC endpoint '${rpcEndpointFields.url}' has invalid network client ID '${networkClientId}'`);
|
|
1149
|
+
}
|
|
1150
|
+
if (mode === 'update' &&
|
|
1151
|
+
networkClientId !== undefined &&
|
|
1152
|
+
rpcEndpointFields.type === RpcEndpointType.Custom &&
|
|
1153
|
+
!Object.values(autoManagedNetworkClientRegistry).some((networkClientsById) => networkClientId in networkClientsById)) {
|
|
1154
|
+
throw new Error(`${errorMessagePrefix}: RPC endpoint '${
|
|
1155
|
+
// This is a string.
|
|
1156
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
1157
|
+
rpcEndpointFields.url}' refers to network client ${(0, util_1.inspect)(networkClientId)} that does not exist`);
|
|
1158
|
+
}
|
|
1159
|
+
if (networkFields.rpcEndpoints.some((otherRpcEndpointFields) => otherRpcEndpointFields !== rpcEndpointFields &&
|
|
1160
|
+
URI.equal(otherRpcEndpointFields.url, rpcEndpointFields.url))) {
|
|
1161
|
+
throw new Error(`${errorMessagePrefix}: Each entry in rpcEndpoints must have a unique URL`);
|
|
1162
|
+
}
|
|
1163
|
+
const networkConfigurationsForOtherChains = Object.values(this.state.networkConfigurationsByChainId).filter((networkConfiguration) => existingNetworkConfiguration
|
|
1164
|
+
? networkConfiguration.chainId !==
|
|
1165
|
+
existingNetworkConfiguration.chainId
|
|
1166
|
+
: true);
|
|
1167
|
+
for (const networkConfiguration of networkConfigurationsForOtherChains) {
|
|
1168
|
+
const rpcEndpoint = networkConfiguration.rpcEndpoints.find((existingRpcEndpoint) => URI.equal(rpcEndpointFields.url, existingRpcEndpoint.url));
|
|
1169
|
+
if (rpcEndpoint) {
|
|
1170
|
+
throw new Error(mode === 'update'
|
|
1171
|
+
? // False negative - these are strings.
|
|
1172
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
1173
|
+
`Could not update network to point to same RPC endpoint as existing network for chain ${networkConfiguration.chainId} ('${networkConfiguration.name}')`
|
|
1174
|
+
: // False negative - these are strings.
|
|
1175
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
1176
|
+
`Could not add network that points to same RPC endpoint as existing network for chain ${networkConfiguration.chainId} ('${networkConfiguration.name}')`);
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
if ([...new Set(networkFields.rpcEndpoints)].length <
|
|
1181
|
+
networkFields.rpcEndpoints.length) {
|
|
1182
|
+
throw new Error(`${errorMessagePrefix}: Each entry in rpcEndpoints must be unique`);
|
|
1183
|
+
}
|
|
1184
|
+
const networkClientIds = networkFields.rpcEndpoints
|
|
1185
|
+
.map((rpcEndpoint) => 'networkClientId' in rpcEndpoint
|
|
1186
|
+
? rpcEndpoint.networkClientId
|
|
1187
|
+
: undefined)
|
|
1188
|
+
.filter((networkClientId) => networkClientId !== undefined);
|
|
1189
|
+
if ([...new Set(networkClientIds)].length < networkClientIds.length) {
|
|
1190
|
+
throw new Error(`${errorMessagePrefix}: Each entry in rpcEndpoints must have a unique networkClientId`);
|
|
1191
|
+
}
|
|
1192
|
+
const infuraRpcEndpoints = networkFields.rpcEndpoints.filter((rpcEndpointFields) => rpcEndpointFields.type === RpcEndpointType.Infura);
|
|
1193
|
+
if (infuraRpcEndpoints.length > 1) {
|
|
1194
|
+
throw new Error(`${errorMessagePrefix}: There cannot be more than one Infura RPC endpoint`);
|
|
1195
|
+
}
|
|
1196
|
+
const soleInfuraRpcEndpoint = infuraRpcEndpoints[0];
|
|
1197
|
+
if (soleInfuraRpcEndpoint) {
|
|
1198
|
+
const infuraNetworkName = deriveInfuraNetworkNameFromRpcEndpointUrl(soleInfuraRpcEndpoint.url);
|
|
1199
|
+
const infuraNetworkNickname = controller_utils_1.NetworkNickname[infuraNetworkName];
|
|
1200
|
+
const infuraChainId = controller_utils_1.ChainId[infuraNetworkName];
|
|
1201
|
+
if (networkFields.chainId !== infuraChainId) {
|
|
1202
|
+
throw new Error(mode === 'add'
|
|
1203
|
+
? // This is a string.
|
|
1204
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
1205
|
+
`Could not add network with chain ID ${networkFields.chainId} and Infura RPC endpoint for '${infuraNetworkNickname}' which represents ${infuraChainId}, as the two conflict`
|
|
1206
|
+
: // This is a string.
|
|
1207
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
1208
|
+
`Could not update network with chain ID ${networkFields.chainId} and Infura RPC endpoint for '${infuraNetworkNickname}' which represents ${infuraChainId}, as the two conflict`);
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
if (networkFields.rpcEndpoints[networkFields.defaultRpcEndpointIndex] ===
|
|
1212
|
+
undefined) {
|
|
1213
|
+
throw new Error(`${errorMessagePrefix}: \`defaultRpcEndpointIndex\` must refer to an entry in \`rpcEndpoints\``);
|
|
1214
|
+
}
|
|
1215
|
+
}, _NetworkController_determineNetworkConfigurationToPersist = function _NetworkController_determineNetworkConfigurationToPersist({ networkFields, networkClientOperations, }) {
|
|
1216
|
+
const rpcEndpointsToPersist = networkClientOperations
|
|
1217
|
+
.filter((networkClientOperation) => {
|
|
1218
|
+
return (networkClientOperation.type === 'add' ||
|
|
1219
|
+
networkClientOperation.type === 'noop');
|
|
1220
|
+
})
|
|
1221
|
+
.map((networkClientOperation) => networkClientOperation.rpcEndpoint)
|
|
1222
|
+
.concat(networkClientOperations
|
|
1223
|
+
.filter((networkClientOperation) => {
|
|
1224
|
+
return networkClientOperation.type === 'replace';
|
|
1225
|
+
})
|
|
1226
|
+
.map((networkClientOperation) => networkClientOperation.newRpcEndpoint));
|
|
1227
|
+
return { ...networkFields, rpcEndpoints: rpcEndpointsToPersist };
|
|
1228
|
+
}, _NetworkController_registerNetworkClientsAsNeeded = function _NetworkController_registerNetworkClientsAsNeeded({ networkFields, networkClientOperations, autoManagedNetworkClientRegistry, }) {
|
|
1229
|
+
const addedRpcEndpoints = networkClientOperations
|
|
1230
|
+
.filter((networkClientOperation) => {
|
|
1231
|
+
return networkClientOperation.type === 'add';
|
|
1232
|
+
})
|
|
1233
|
+
.map((networkClientOperation) => networkClientOperation.rpcEndpoint)
|
|
1234
|
+
.concat(networkClientOperations
|
|
1235
|
+
.filter((networkClientOperation) => {
|
|
1236
|
+
return networkClientOperation.type === 'replace';
|
|
1237
|
+
})
|
|
1238
|
+
.map((networkClientOperation) => networkClientOperation.newRpcEndpoint));
|
|
1239
|
+
for (const addedRpcEndpoint of addedRpcEndpoints) {
|
|
1240
|
+
if (addedRpcEndpoint.type === RpcEndpointType.Infura) {
|
|
1241
|
+
autoManagedNetworkClientRegistry[types_1.NetworkClientType.Infura][addedRpcEndpoint.networkClientId] = (0, create_auto_managed_network_client_1.createAutoManagedNetworkClient)({
|
|
1242
|
+
type: types_1.NetworkClientType.Infura,
|
|
1243
|
+
chainId: networkFields.chainId,
|
|
1244
|
+
network: addedRpcEndpoint.networkClientId,
|
|
1245
|
+
infuraProjectId: __classPrivateFieldGet(this, _NetworkController_infuraProjectId, "f"),
|
|
1246
|
+
ticker: networkFields.nativeCurrency,
|
|
1247
|
+
});
|
|
1248
|
+
}
|
|
1249
|
+
else {
|
|
1250
|
+
autoManagedNetworkClientRegistry[types_1.NetworkClientType.Custom][addedRpcEndpoint.networkClientId] = (0, create_auto_managed_network_client_1.createAutoManagedNetworkClient)({
|
|
1251
|
+
type: types_1.NetworkClientType.Custom,
|
|
1252
|
+
chainId: networkFields.chainId,
|
|
1253
|
+
rpcUrl: addedRpcEndpoint.url,
|
|
1254
|
+
ticker: networkFields.nativeCurrency,
|
|
1255
|
+
});
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
}, _NetworkController_unregisterNetworkClientsAsNeeded = function _NetworkController_unregisterNetworkClientsAsNeeded({ networkClientOperations, autoManagedNetworkClientRegistry, }) {
|
|
1259
|
+
const removedRpcEndpoints = networkClientOperations
|
|
1260
|
+
.filter((networkClientOperation) => {
|
|
1261
|
+
return networkClientOperation.type === 'remove';
|
|
1262
|
+
})
|
|
1263
|
+
.map((networkClientOperation) => networkClientOperation.rpcEndpoint)
|
|
1264
|
+
.concat(networkClientOperations
|
|
1265
|
+
.filter((networkClientOperation) => {
|
|
1266
|
+
return networkClientOperation.type === 'replace';
|
|
1267
|
+
})
|
|
1268
|
+
.map((networkClientOperation) => networkClientOperation.oldRpcEndpoint));
|
|
1269
|
+
for (const rpcEndpoint of removedRpcEndpoints) {
|
|
1270
|
+
const networkClient = this.getNetworkClientById(rpcEndpoint.networkClientId);
|
|
1271
|
+
networkClient.destroy();
|
|
1272
|
+
delete autoManagedNetworkClientRegistry[networkClient.configuration.type][rpcEndpoint.networkClientId];
|
|
1273
|
+
}
|
|
1274
|
+
}, _NetworkController_updateNetworkConfigurations = function _NetworkController_updateNetworkConfigurations(args) {
|
|
1275
|
+
const { state, mode } = args;
|
|
1276
|
+
if (mode === 'remove' ||
|
|
1277
|
+
(mode === 'update' &&
|
|
1278
|
+
args.networkFields.chainId !==
|
|
1279
|
+
args.existingNetworkConfiguration.chainId)) {
|
|
1280
|
+
delete state.networkConfigurationsByChainId[args.existingNetworkConfiguration.chainId];
|
|
1281
|
+
}
|
|
1282
|
+
if (mode === 'add' || mode === 'update') {
|
|
1283
|
+
state.networkConfigurationsByChainId[args.networkFields.chainId] =
|
|
1284
|
+
args.networkConfigurationToPersist;
|
|
1285
|
+
}
|
|
1286
|
+
}, _NetworkController_ensureAutoManagedNetworkClientRegistryPopulated = function _NetworkController_ensureAutoManagedNetworkClientRegistryPopulated() {
|
|
1287
|
+
return (__classPrivateFieldSet(this, _NetworkController_autoManagedNetworkClientRegistry, __classPrivateFieldGet(this, _NetworkController_autoManagedNetworkClientRegistry, "f") ?? __classPrivateFieldGet(this, _NetworkController_instances, "m", _NetworkController_createAutoManagedNetworkClientRegistry).call(this), "f"));
|
|
1288
|
+
}, _NetworkController_createAutoManagedNetworkClientRegistry = function _NetworkController_createAutoManagedNetworkClientRegistry() {
|
|
1289
|
+
const chainIds = knownKeysOf(this.state.networkConfigurationsByChainId);
|
|
1290
|
+
const networkClientsWithIds = chainIds.flatMap((chainId) => {
|
|
1291
|
+
const networkConfiguration = this.state.networkConfigurationsByChainId[chainId];
|
|
1292
|
+
return networkConfiguration.rpcEndpoints.map((rpcEndpoint) => {
|
|
1293
|
+
if (rpcEndpoint.type === RpcEndpointType.Infura) {
|
|
1294
|
+
const infuraNetworkName = deriveInfuraNetworkNameFromRpcEndpointUrl(rpcEndpoint.url);
|
|
1295
|
+
return [
|
|
1296
|
+
rpcEndpoint.networkClientId,
|
|
1297
|
+
(0, create_auto_managed_network_client_1.createAutoManagedNetworkClient)({
|
|
1298
|
+
type: types_1.NetworkClientType.Infura,
|
|
1299
|
+
network: infuraNetworkName,
|
|
1300
|
+
infuraProjectId: __classPrivateFieldGet(this, _NetworkController_infuraProjectId, "f"),
|
|
1301
|
+
chainId: networkConfiguration.chainId,
|
|
1302
|
+
ticker: networkConfiguration.nativeCurrency,
|
|
1303
|
+
}),
|
|
1304
|
+
];
|
|
1305
|
+
}
|
|
1306
|
+
return [
|
|
1307
|
+
rpcEndpoint.networkClientId,
|
|
1308
|
+
(0, create_auto_managed_network_client_1.createAutoManagedNetworkClient)({
|
|
1309
|
+
type: types_1.NetworkClientType.Custom,
|
|
1310
|
+
chainId: networkConfiguration.chainId,
|
|
1311
|
+
rpcUrl: rpcEndpoint.url,
|
|
1312
|
+
ticker: networkConfiguration.nativeCurrency,
|
|
1313
|
+
}),
|
|
1314
|
+
];
|
|
1315
|
+
});
|
|
1316
|
+
});
|
|
1317
|
+
return networkClientsWithIds.reduce((obj, [networkClientId, networkClient]) => {
|
|
1318
|
+
return {
|
|
1319
|
+
...obj,
|
|
1320
|
+
[networkClient.configuration.type]: {
|
|
1321
|
+
...obj[networkClient.configuration.type],
|
|
1322
|
+
[networkClientId]: networkClient,
|
|
1323
|
+
},
|
|
1324
|
+
};
|
|
1325
|
+
}, {
|
|
1326
|
+
[types_1.NetworkClientType.Custom]: {},
|
|
1327
|
+
[types_1.NetworkClientType.Infura]: {},
|
|
1328
|
+
});
|
|
1329
|
+
}, _NetworkController_applyNetworkSelection = function _NetworkController_applyNetworkSelection(networkClientId, { updateState, } = {}) {
|
|
1330
|
+
const autoManagedNetworkClientRegistry = __classPrivateFieldGet(this, _NetworkController_instances, "m", _NetworkController_ensureAutoManagedNetworkClientRegistryPopulated).call(this);
|
|
1331
|
+
let autoManagedNetworkClient;
|
|
1332
|
+
if ((0, controller_utils_1.isInfuraNetworkType)(networkClientId)) {
|
|
1333
|
+
const possibleAutoManagedNetworkClient = autoManagedNetworkClientRegistry[types_1.NetworkClientType.Infura][networkClientId];
|
|
1334
|
+
// This is impossible to reach
|
|
1335
|
+
/* istanbul ignore if */
|
|
1336
|
+
if (!possibleAutoManagedNetworkClient) {
|
|
1337
|
+
throw new Error(`No Infura network client found with ID ${(0, util_1.inspect)(networkClientId)}`);
|
|
1338
|
+
}
|
|
1339
|
+
autoManagedNetworkClient = possibleAutoManagedNetworkClient;
|
|
1340
|
+
}
|
|
1341
|
+
else {
|
|
1342
|
+
const possibleAutoManagedNetworkClient = autoManagedNetworkClientRegistry[types_1.NetworkClientType.Custom][networkClientId];
|
|
1343
|
+
if (!possibleAutoManagedNetworkClient) {
|
|
1344
|
+
throw new Error(`No network client found with ID ${(0, util_1.inspect)(networkClientId)}`);
|
|
1345
|
+
}
|
|
1346
|
+
autoManagedNetworkClient = possibleAutoManagedNetworkClient;
|
|
1347
|
+
}
|
|
1348
|
+
__classPrivateFieldSet(this, _NetworkController_autoManagedNetworkClient, autoManagedNetworkClient, "f");
|
|
1349
|
+
this.update((state) => {
|
|
1350
|
+
state.selectedNetworkClientId = networkClientId;
|
|
1351
|
+
if (state.networksMetadata[networkClientId] === undefined) {
|
|
1352
|
+
state.networksMetadata[networkClientId] = {
|
|
1353
|
+
status: constants_1.NetworkStatus.Unknown,
|
|
1354
|
+
EIPS: {},
|
|
1355
|
+
};
|
|
1356
|
+
}
|
|
1357
|
+
updateState?.(state);
|
|
1358
|
+
});
|
|
1359
|
+
if (__classPrivateFieldGet(this, _NetworkController_providerProxy, "f")) {
|
|
1360
|
+
__classPrivateFieldGet(this, _NetworkController_providerProxy, "f").setTarget(__classPrivateFieldGet(this, _NetworkController_autoManagedNetworkClient, "f").provider);
|
|
1361
|
+
}
|
|
1362
|
+
else {
|
|
1363
|
+
__classPrivateFieldSet(this, _NetworkController_providerProxy, (0, swappable_obj_proxy_1.createEventEmitterProxy)(__classPrivateFieldGet(this, _NetworkController_autoManagedNetworkClient, "f").provider), "f");
|
|
1364
|
+
}
|
|
1365
|
+
if (__classPrivateFieldGet(this, _NetworkController_blockTrackerProxy, "f")) {
|
|
1366
|
+
__classPrivateFieldGet(this, _NetworkController_blockTrackerProxy, "f").setTarget(__classPrivateFieldGet(this, _NetworkController_autoManagedNetworkClient, "f").blockTracker);
|
|
1367
|
+
}
|
|
1368
|
+
else {
|
|
1369
|
+
__classPrivateFieldSet(this, _NetworkController_blockTrackerProxy, (0, swappable_obj_proxy_1.createEventEmitterProxy)(__classPrivateFieldGet(this, _NetworkController_autoManagedNetworkClient, "f").blockTracker, { eventFilter: 'skipInternal' }), "f");
|
|
1370
|
+
}
|
|
1371
|
+
__classPrivateFieldSet(this, _NetworkController_ethQuery, new eth_query_1.default(__classPrivateFieldGet(this, _NetworkController_providerProxy, "f")), "f");
|
|
1372
|
+
};
|
|
1373
|
+
//# sourceMappingURL=NetworkController.cjs.map
|