@metamask/bridge-controller 1.0.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -1
- package/dist/bridge-controller.cjs +81 -48
- package/dist/bridge-controller.cjs.map +1 -1
- package/dist/bridge-controller.d.cts +2 -5
- package/dist/bridge-controller.d.cts.map +1 -1
- package/dist/bridge-controller.d.mts +2 -5
- package/dist/bridge-controller.d.mts.map +1 -1
- package/dist/bridge-controller.mjs +69 -36
- package/dist/bridge-controller.mjs.map +1 -1
- package/dist/constants/bridge.cjs +13 -12
- package/dist/constants/bridge.cjs.map +1 -1
- package/dist/constants/bridge.d.cts +6 -0
- package/dist/constants/bridge.d.cts.map +1 -1
- package/dist/constants/bridge.d.mts +6 -0
- package/dist/constants/bridge.d.mts.map +1 -1
- package/dist/constants/bridge.mjs +12 -11
- package/dist/constants/bridge.mjs.map +1 -1
- package/dist/types.cjs +2 -0
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +20 -6
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +20 -6
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs +2 -0
- package/dist/types.mjs.map +1 -1
- package/dist/utils/fetch.cjs +11 -10
- package/dist/utils/fetch.cjs.map +1 -1
- package/dist/utils/fetch.d.cts.map +1 -1
- package/dist/utils/fetch.d.mts.map +1 -1
- package/dist/utils/fetch.mjs +12 -11
- package/dist/utils/fetch.mjs.map +1 -1
- package/dist/utils/validators.d.cts +1 -1
- package/dist/utils/validators.d.mts +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,11 +7,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [2.0.0]
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Mobile feature flags ([#5359](https://github.com/MetaMask/core/pull/5359))
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- **BREAKING:** Change `BridgeController` state structure to have all fields at root of state ([#5406](https://github.com/MetaMask/core/pull/5406))
|
|
19
|
+
- **BREAKING:** Change `BridgeController` state defaults to `null` instead of `undefined` ([#5406](https://github.com/MetaMask/core/pull/5406))
|
|
20
|
+
|
|
10
21
|
## [1.0.0]
|
|
11
22
|
|
|
12
23
|
### Added
|
|
13
24
|
|
|
14
25
|
- Initial release ([#5317](https://github.com/MetaMask/core/pull/5317))
|
|
15
26
|
|
|
16
|
-
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/bridge-controller@
|
|
27
|
+
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/bridge-controller@2.0.0...HEAD
|
|
28
|
+
[2.0.0]: https://github.com/MetaMask/core/compare/@metamask/bridge-controller@1.0.0...@metamask/bridge-controller@2.0.0
|
|
17
29
|
[1.0.0]: https://github.com/MetaMask/core/releases/tag/@metamask/bridge-controller@1.0.0
|
|
@@ -18,15 +18,42 @@ const polling_controller_1 = require("@metamask/polling-controller");
|
|
|
18
18
|
const utils_1 = require("@metamask/utils");
|
|
19
19
|
const ethers_1 = require("ethers");
|
|
20
20
|
const bridge_1 = require("./constants/bridge.cjs");
|
|
21
|
-
const bridge_2 = require("./constants/bridge.cjs");
|
|
22
21
|
const chains_1 = require("./constants/chains.cjs");
|
|
23
22
|
const types_1 = require("./types.cjs");
|
|
24
23
|
const balance_1 = require("./utils/balance.cjs");
|
|
25
|
-
const
|
|
24
|
+
const bridge_2 = require("./utils/bridge.cjs");
|
|
26
25
|
const fetch_1 = require("./utils/fetch.cjs");
|
|
27
26
|
const quote_1 = require("./utils/quote.cjs");
|
|
28
27
|
const metadata = {
|
|
29
|
-
|
|
28
|
+
bridgeFeatureFlags: {
|
|
29
|
+
persist: false,
|
|
30
|
+
anonymous: false,
|
|
31
|
+
},
|
|
32
|
+
quoteRequest: {
|
|
33
|
+
persist: false,
|
|
34
|
+
anonymous: false,
|
|
35
|
+
},
|
|
36
|
+
quotes: {
|
|
37
|
+
persist: false,
|
|
38
|
+
anonymous: false,
|
|
39
|
+
},
|
|
40
|
+
quotesInitialLoadTime: {
|
|
41
|
+
persist: false,
|
|
42
|
+
anonymous: false,
|
|
43
|
+
},
|
|
44
|
+
quotesLastFetched: {
|
|
45
|
+
persist: false,
|
|
46
|
+
anonymous: false,
|
|
47
|
+
},
|
|
48
|
+
quotesLoadingStatus: {
|
|
49
|
+
persist: false,
|
|
50
|
+
anonymous: false,
|
|
51
|
+
},
|
|
52
|
+
quoteFetchError: {
|
|
53
|
+
persist: false,
|
|
54
|
+
anonymous: false,
|
|
55
|
+
},
|
|
56
|
+
quotesRefreshCount: {
|
|
30
57
|
persist: false,
|
|
31
58
|
anonymous: false,
|
|
32
59
|
},
|
|
@@ -35,14 +62,12 @@ const RESET_STATE_ABORT_MESSAGE = 'Reset controller state';
|
|
|
35
62
|
class BridgeController extends (0, polling_controller_1.StaticIntervalPollingController)() {
|
|
36
63
|
constructor({ messenger, state, clientId, getLayer1GasFee, fetchFn, }) {
|
|
37
64
|
super({
|
|
38
|
-
name:
|
|
65
|
+
name: bridge_1.BRIDGE_CONTROLLER_NAME,
|
|
39
66
|
metadata,
|
|
40
67
|
messenger,
|
|
41
68
|
state: {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
...state,
|
|
45
|
-
},
|
|
69
|
+
...(0, bridge_2.getDefaultBridgeControllerState)(),
|
|
70
|
+
...state,
|
|
46
71
|
},
|
|
47
72
|
});
|
|
48
73
|
_BridgeController_instances.add(this);
|
|
@@ -58,22 +83,21 @@ class BridgeController extends (0, polling_controller_1.StaticIntervalPollingCon
|
|
|
58
83
|
this.stopAllPolling();
|
|
59
84
|
__classPrivateFieldGet(this, _BridgeController_abortController, "f")?.abort('Quote request updated');
|
|
60
85
|
const updatedQuoteRequest = {
|
|
61
|
-
...
|
|
86
|
+
...bridge_1.DEFAULT_BRIDGE_CONTROLLER_STATE.quoteRequest,
|
|
62
87
|
...paramsToUpdate,
|
|
63
88
|
};
|
|
64
89
|
this.update((state) => {
|
|
65
|
-
state.
|
|
66
|
-
state.
|
|
67
|
-
state.
|
|
68
|
-
|
|
69
|
-
state.
|
|
70
|
-
|
|
71
|
-
state.
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
bridge_2.DEFAULT_BRIDGE_CONTROLLER_STATE.quotesInitialLoadTime;
|
|
90
|
+
state.quoteRequest = updatedQuoteRequest;
|
|
91
|
+
state.quotes = bridge_1.DEFAULT_BRIDGE_CONTROLLER_STATE.quotes;
|
|
92
|
+
state.quotesLastFetched =
|
|
93
|
+
bridge_1.DEFAULT_BRIDGE_CONTROLLER_STATE.quotesLastFetched;
|
|
94
|
+
state.quotesLoadingStatus =
|
|
95
|
+
bridge_1.DEFAULT_BRIDGE_CONTROLLER_STATE.quotesLoadingStatus;
|
|
96
|
+
state.quoteFetchError = bridge_1.DEFAULT_BRIDGE_CONTROLLER_STATE.quoteFetchError;
|
|
97
|
+
state.quotesRefreshCount =
|
|
98
|
+
bridge_1.DEFAULT_BRIDGE_CONTROLLER_STATE.quotesRefreshCount;
|
|
99
|
+
state.quotesInitialLoadTime =
|
|
100
|
+
bridge_1.DEFAULT_BRIDGE_CONTROLLER_STATE.quotesInitialLoadTime;
|
|
77
101
|
});
|
|
78
102
|
if ((0, quote_1.isValidQuoteRequest)(updatedQuoteRequest)) {
|
|
79
103
|
__classPrivateFieldSet(this, _BridgeController_quotesFirstFetched, Date.now(), "f");
|
|
@@ -103,32 +127,41 @@ class BridgeController extends (0, polling_controller_1.StaticIntervalPollingCon
|
|
|
103
127
|
this.stopAllPolling();
|
|
104
128
|
__classPrivateFieldGet(this, _BridgeController_abortController, "f")?.abort(RESET_STATE_ABORT_MESSAGE);
|
|
105
129
|
this.update((state) => {
|
|
106
|
-
state.
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
130
|
+
// Cannot do direct assignment to state, i.e. state = {... }, need to manually assign each field
|
|
131
|
+
state.quoteRequest = bridge_1.DEFAULT_BRIDGE_CONTROLLER_STATE.quoteRequest;
|
|
132
|
+
state.quotesInitialLoadTime =
|
|
133
|
+
bridge_1.DEFAULT_BRIDGE_CONTROLLER_STATE.quotesInitialLoadTime;
|
|
134
|
+
state.quotes = bridge_1.DEFAULT_BRIDGE_CONTROLLER_STATE.quotes;
|
|
135
|
+
state.quotesLastFetched =
|
|
136
|
+
bridge_1.DEFAULT_BRIDGE_CONTROLLER_STATE.quotesLastFetched;
|
|
137
|
+
state.quotesLoadingStatus =
|
|
138
|
+
bridge_1.DEFAULT_BRIDGE_CONTROLLER_STATE.quotesLoadingStatus;
|
|
139
|
+
state.quoteFetchError = bridge_1.DEFAULT_BRIDGE_CONTROLLER_STATE.quoteFetchError;
|
|
140
|
+
state.quotesRefreshCount =
|
|
141
|
+
bridge_1.DEFAULT_BRIDGE_CONTROLLER_STATE.quotesRefreshCount;
|
|
142
|
+
// Keep feature flags
|
|
143
|
+
const originalFeatureFlags = state.bridgeFeatureFlags;
|
|
144
|
+
state.bridgeFeatureFlags = originalFeatureFlags;
|
|
111
145
|
});
|
|
112
146
|
};
|
|
113
147
|
this.setBridgeFeatureFlags = async () => {
|
|
114
148
|
const bridgeFeatureFlags = await (0, fetch_1.fetchBridgeFeatureFlags)(__classPrivateFieldGet(this, _BridgeController_clientId, "f"), __classPrivateFieldGet(this, _BridgeController_fetchFn, "f"));
|
|
115
149
|
this.update((state) => {
|
|
116
|
-
state.
|
|
150
|
+
state.bridgeFeatureFlags = bridgeFeatureFlags;
|
|
117
151
|
});
|
|
118
152
|
this.setIntervalLength(bridgeFeatureFlags[types_1.BridgeFeatureFlagsKey.EXTENSION_CONFIG].refreshRate);
|
|
119
153
|
};
|
|
120
154
|
_BridgeController_fetchBridgeQuotes.set(this, async ({ networkClientId: _networkClientId, updatedQuoteRequest, }) => {
|
|
121
|
-
const {
|
|
155
|
+
const { bridgeFeatureFlags, quotesInitialLoadTime, quotesRefreshCount } = this.state;
|
|
122
156
|
__classPrivateFieldGet(this, _BridgeController_abortController, "f")?.abort('New quote request');
|
|
123
157
|
__classPrivateFieldSet(this, _BridgeController_abortController, new AbortController(), "f");
|
|
124
158
|
if (updatedQuoteRequest.srcChainId === updatedQuoteRequest.destChainId) {
|
|
125
159
|
return;
|
|
126
160
|
}
|
|
127
161
|
this.update((state) => {
|
|
128
|
-
state.
|
|
129
|
-
state.
|
|
130
|
-
state.
|
|
131
|
-
bridge_2.DEFAULT_BRIDGE_CONTROLLER_STATE.quoteFetchError;
|
|
162
|
+
state.quotesLoadingStatus = types_1.RequestStatus.LOADING;
|
|
163
|
+
state.quoteRequest = updatedQuoteRequest;
|
|
164
|
+
state.quoteFetchError = bridge_1.DEFAULT_BRIDGE_CONTROLLER_STATE.quoteFetchError;
|
|
132
165
|
});
|
|
133
166
|
try {
|
|
134
167
|
const quotes = await (0, fetch_1.fetchBridgeQuotes)(updatedQuoteRequest,
|
|
@@ -139,8 +172,8 @@ class BridgeController extends (0, polling_controller_1.StaticIntervalPollingCon
|
|
|
139
172
|
__classPrivateFieldGet(this, _BridgeController_abortController, "f").signal, __classPrivateFieldGet(this, _BridgeController_clientId, "f"), __classPrivateFieldGet(this, _BridgeController_fetchFn, "f"));
|
|
140
173
|
const quotesWithL1GasFees = await __classPrivateFieldGet(this, _BridgeController_appendL1GasFees, "f").call(this, quotes);
|
|
141
174
|
this.update((state) => {
|
|
142
|
-
state.
|
|
143
|
-
state.
|
|
175
|
+
state.quotes = quotesWithL1GasFees;
|
|
176
|
+
state.quotesLoadingStatus = types_1.RequestStatus.FETCHED;
|
|
144
177
|
});
|
|
145
178
|
}
|
|
146
179
|
catch (error) {
|
|
@@ -150,15 +183,15 @@ class BridgeController extends (0, polling_controller_1.StaticIntervalPollingCon
|
|
|
150
183
|
return;
|
|
151
184
|
}
|
|
152
185
|
this.update((state) => {
|
|
153
|
-
state.
|
|
186
|
+
state.quoteFetchError =
|
|
154
187
|
error instanceof Error ? error.message : 'Unknown error';
|
|
155
|
-
state.
|
|
188
|
+
state.quotesLoadingStatus = types_1.RequestStatus.ERROR;
|
|
156
189
|
});
|
|
157
190
|
console.log('Failed to fetch bridge quotes', error);
|
|
158
191
|
}
|
|
159
192
|
finally {
|
|
160
|
-
const { maxRefreshCount } =
|
|
161
|
-
const updatedQuotesRefreshCount =
|
|
193
|
+
const { maxRefreshCount } = bridgeFeatureFlags[types_1.BridgeFeatureFlagsKey.EXTENSION_CONFIG];
|
|
194
|
+
const updatedQuotesRefreshCount = quotesRefreshCount + 1;
|
|
162
195
|
// Stop polling if the maximum number of refreshes has been reached
|
|
163
196
|
if (updatedQuoteRequest.insufficientBal ||
|
|
164
197
|
(!updatedQuoteRequest.insufficientBal &&
|
|
@@ -168,12 +201,12 @@ class BridgeController extends (0, polling_controller_1.StaticIntervalPollingCon
|
|
|
168
201
|
// Update quote fetching stats
|
|
169
202
|
const quotesLastFetched = Date.now();
|
|
170
203
|
this.update((state) => {
|
|
171
|
-
state.
|
|
204
|
+
state.quotesInitialLoadTime =
|
|
172
205
|
updatedQuotesRefreshCount === 1 && __classPrivateFieldGet(this, _BridgeController_quotesFirstFetched, "f")
|
|
173
206
|
? quotesLastFetched - __classPrivateFieldGet(this, _BridgeController_quotesFirstFetched, "f")
|
|
174
|
-
:
|
|
175
|
-
state.
|
|
176
|
-
state.
|
|
207
|
+
: quotesInitialLoadTime;
|
|
208
|
+
state.quotesLastFetched = quotesLastFetched;
|
|
209
|
+
state.quotesRefreshCount = updatedQuotesRefreshCount;
|
|
177
210
|
});
|
|
178
211
|
}
|
|
179
212
|
});
|
|
@@ -201,7 +234,7 @@ class BridgeController extends (0, polling_controller_1.StaticIntervalPollingCon
|
|
|
201
234
|
});
|
|
202
235
|
return {
|
|
203
236
|
...quoteResponse,
|
|
204
|
-
l1GasFeesInHexWei: (0,
|
|
237
|
+
l1GasFeesInHexWei: (0, bridge_2.sumHexes)(approvalL1GasFees, tradeL1GasFees),
|
|
205
238
|
};
|
|
206
239
|
}
|
|
207
240
|
return quoteResponse;
|
|
@@ -221,7 +254,7 @@ class BridgeController extends (0, polling_controller_1.StaticIntervalPollingCon
|
|
|
221
254
|
const ethersProvider = new ethers_1.BrowserProvider(provider);
|
|
222
255
|
const contract = new ethers_1.Contract(contractAddress, metamask_eth_abis_1.abiERC20, ethersProvider);
|
|
223
256
|
const { address: walletAddress } = __classPrivateFieldGet(this, _BridgeController_instances, "m", _BridgeController_getSelectedAccount).call(this);
|
|
224
|
-
const allowance = await contract.allowance(walletAddress,
|
|
257
|
+
const allowance = await contract.allowance(walletAddress, bridge_1.METABRIDGE_CHAIN_TO_ADDRESS_MAP[chainId]);
|
|
225
258
|
return allowance.toString();
|
|
226
259
|
};
|
|
227
260
|
this.setIntervalLength(bridge_1.REFRESH_INTERVAL_MS);
|
|
@@ -230,10 +263,10 @@ class BridgeController extends (0, polling_controller_1.StaticIntervalPollingCon
|
|
|
230
263
|
__classPrivateFieldSet(this, _BridgeController_clientId, clientId, "f");
|
|
231
264
|
__classPrivateFieldSet(this, _BridgeController_fetchFn, fetchFn, "f");
|
|
232
265
|
// Register action handlers
|
|
233
|
-
this.messagingSystem.registerActionHandler(`${
|
|
234
|
-
this.messagingSystem.registerActionHandler(`${
|
|
235
|
-
this.messagingSystem.registerActionHandler(`${
|
|
236
|
-
this.messagingSystem.registerActionHandler(`${
|
|
266
|
+
this.messagingSystem.registerActionHandler(`${bridge_1.BRIDGE_CONTROLLER_NAME}:setBridgeFeatureFlags`, this.setBridgeFeatureFlags.bind(this));
|
|
267
|
+
this.messagingSystem.registerActionHandler(`${bridge_1.BRIDGE_CONTROLLER_NAME}:updateBridgeQuoteRequestParams`, this.updateBridgeQuoteRequestParams.bind(this));
|
|
268
|
+
this.messagingSystem.registerActionHandler(`${bridge_1.BRIDGE_CONTROLLER_NAME}:resetState`, this.resetState.bind(this));
|
|
269
|
+
this.messagingSystem.registerActionHandler(`${bridge_1.BRIDGE_CONTROLLER_NAME}:getBridgeERC20Allowance`, this.getBridgeERC20Allowance.bind(this));
|
|
237
270
|
}
|
|
238
271
|
}
|
|
239
272
|
exports.BridgeController = BridgeController;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge-controller.cjs","sourceRoot":"","sources":["../src/bridge-controller.ts"],"names":[],"mappings":"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","sourcesContent":["import type { StateMetadata } from '@metamask/base-controller';\nimport type { ChainId } from '@metamask/controller-utils';\nimport { abiERC20 } from '@metamask/metamask-eth-abis';\nimport type { NetworkClientId } from '@metamask/network-controller';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport type { TransactionParams } from '@metamask/transaction-controller';\nimport { numberToHex } from '@metamask/utils';\nimport type { Hex } from '@metamask/utils';\nimport { BrowserProvider, Contract } from 'ethers';\n\nimport type { BridgeClientId } from './constants/bridge';\nimport { REFRESH_INTERVAL_MS } from './constants/bridge';\nimport {\n BRIDGE_CONTROLLER_NAME,\n DEFAULT_BRIDGE_CONTROLLER_STATE,\n METABRIDGE_CHAIN_TO_ADDRESS_MAP,\n} from './constants/bridge';\nimport { CHAIN_IDS } from './constants/chains';\nimport {\n type L1GasFees,\n type QuoteRequest,\n type QuoteResponse,\n type TxData,\n type BridgeControllerState,\n BridgeFeatureFlagsKey,\n RequestStatus,\n} from './types';\nimport type { BridgeControllerMessenger, FetchFunction } from './types';\nimport { hasSufficientBalance } from './utils/balance';\nimport { getDefaultBridgeControllerState, sumHexes } from './utils/bridge';\nimport { fetchBridgeFeatureFlags, fetchBridgeQuotes } from './utils/fetch';\nimport { isValidQuoteRequest } from './utils/quote';\n\nconst metadata: StateMetadata<{ bridgeState: BridgeControllerState }> = {\n bridgeState: {\n persist: false,\n anonymous: false,\n },\n};\n\nconst RESET_STATE_ABORT_MESSAGE = 'Reset controller state';\n\n/** The input to start polling for the {@link BridgeController} */\ntype BridgePollingInput = {\n networkClientId: NetworkClientId;\n updatedQuoteRequest: QuoteRequest;\n};\n\nexport class BridgeController extends StaticIntervalPollingController<BridgePollingInput>()<\n typeof BRIDGE_CONTROLLER_NAME,\n { bridgeState: BridgeControllerState },\n BridgeControllerMessenger\n> {\n #abortController: AbortController | undefined;\n\n #quotesFirstFetched: number | undefined;\n\n readonly #clientId: string;\n\n readonly #getLayer1GasFee: (params: {\n transactionParams: TransactionParams;\n chainId: ChainId;\n }) => Promise<string>;\n\n readonly #fetchFn: FetchFunction;\n\n constructor({\n messenger,\n state,\n clientId,\n getLayer1GasFee,\n fetchFn,\n }: {\n messenger: BridgeControllerMessenger;\n state?: Partial<BridgeControllerState>;\n clientId: BridgeClientId;\n getLayer1GasFee: (params: {\n transactionParams: TransactionParams;\n chainId: ChainId;\n }) => Promise<string>;\n fetchFn: FetchFunction;\n }) {\n super({\n name: BRIDGE_CONTROLLER_NAME,\n metadata,\n messenger,\n state: {\n bridgeState: {\n ...getDefaultBridgeControllerState(),\n ...state,\n },\n },\n });\n\n this.setIntervalLength(REFRESH_INTERVAL_MS);\n\n this.#abortController = new AbortController();\n this.#getLayer1GasFee = getLayer1GasFee;\n this.#clientId = clientId;\n this.#fetchFn = fetchFn;\n\n // Register action handlers\n this.messagingSystem.registerActionHandler(\n `${BRIDGE_CONTROLLER_NAME}:setBridgeFeatureFlags`,\n this.setBridgeFeatureFlags.bind(this),\n );\n this.messagingSystem.registerActionHandler(\n `${BRIDGE_CONTROLLER_NAME}:updateBridgeQuoteRequestParams`,\n this.updateBridgeQuoteRequestParams.bind(this),\n );\n this.messagingSystem.registerActionHandler(\n `${BRIDGE_CONTROLLER_NAME}:resetState`,\n this.resetState.bind(this),\n );\n this.messagingSystem.registerActionHandler(\n `${BRIDGE_CONTROLLER_NAME}:getBridgeERC20Allowance`,\n this.getBridgeERC20Allowance.bind(this),\n );\n }\n\n _executePoll = async (pollingInput: BridgePollingInput) => {\n await this.#fetchBridgeQuotes(pollingInput);\n };\n\n updateBridgeQuoteRequestParams = async (\n paramsToUpdate: Partial<QuoteRequest>,\n ) => {\n this.stopAllPolling();\n this.#abortController?.abort('Quote request updated');\n\n const updatedQuoteRequest = {\n ...DEFAULT_BRIDGE_CONTROLLER_STATE.quoteRequest,\n ...paramsToUpdate,\n };\n\n this.update((state) => {\n state.bridgeState.quoteRequest = updatedQuoteRequest;\n state.bridgeState.quotes = DEFAULT_BRIDGE_CONTROLLER_STATE.quotes;\n state.bridgeState.quotesLastFetched =\n DEFAULT_BRIDGE_CONTROLLER_STATE.quotesLastFetched;\n state.bridgeState.quotesLoadingStatus =\n DEFAULT_BRIDGE_CONTROLLER_STATE.quotesLoadingStatus;\n state.bridgeState.quoteFetchError =\n DEFAULT_BRIDGE_CONTROLLER_STATE.quoteFetchError;\n state.bridgeState.quotesRefreshCount =\n DEFAULT_BRIDGE_CONTROLLER_STATE.quotesRefreshCount;\n state.bridgeState.quotesInitialLoadTime =\n DEFAULT_BRIDGE_CONTROLLER_STATE.quotesInitialLoadTime;\n });\n\n if (isValidQuoteRequest(updatedQuoteRequest)) {\n this.#quotesFirstFetched = Date.now();\n const walletAddress = this.#getSelectedAccount().address;\n const srcChainIdInHex = numberToHex(updatedQuoteRequest.srcChainId);\n\n const insufficientBal =\n paramsToUpdate.insufficientBal ||\n !(await this.#hasSufficientBalance(updatedQuoteRequest));\n\n const networkClientId = this.#getSelectedNetworkClientId(srcChainIdInHex);\n this.startPolling({\n networkClientId,\n updatedQuoteRequest: {\n ...updatedQuoteRequest,\n walletAddress,\n insufficientBal,\n },\n });\n }\n };\n\n readonly #hasSufficientBalance = async (quoteRequest: QuoteRequest) => {\n const walletAddress = this.#getSelectedAccount().address;\n const srcChainIdInHex = numberToHex(quoteRequest.srcChainId);\n const provider = this.#getSelectedNetworkClient()?.provider;\n\n return (\n provider &&\n (await hasSufficientBalance(\n provider,\n walletAddress,\n quoteRequest.srcTokenAddress,\n quoteRequest.srcTokenAmount,\n srcChainIdInHex,\n ))\n );\n };\n\n resetState = () => {\n this.stopAllPolling();\n this.#abortController?.abort(RESET_STATE_ABORT_MESSAGE);\n\n this.update((state) => {\n state.bridgeState = {\n ...DEFAULT_BRIDGE_CONTROLLER_STATE,\n quotes: [],\n bridgeFeatureFlags: state.bridgeState.bridgeFeatureFlags,\n };\n });\n };\n\n setBridgeFeatureFlags = async () => {\n const bridgeFeatureFlags = await fetchBridgeFeatureFlags(\n this.#clientId,\n this.#fetchFn,\n );\n this.update((state) => {\n state.bridgeState.bridgeFeatureFlags = bridgeFeatureFlags;\n });\n this.setIntervalLength(\n bridgeFeatureFlags[BridgeFeatureFlagsKey.EXTENSION_CONFIG].refreshRate,\n );\n };\n\n readonly #fetchBridgeQuotes = async ({\n networkClientId: _networkClientId,\n updatedQuoteRequest,\n }: BridgePollingInput) => {\n const { bridgeState } = this.state;\n this.#abortController?.abort('New quote request');\n this.#abortController = new AbortController();\n if (updatedQuoteRequest.srcChainId === updatedQuoteRequest.destChainId) {\n return;\n }\n this.update((state) => {\n state.bridgeState.quotesLoadingStatus = RequestStatus.LOADING;\n state.bridgeState.quoteRequest = updatedQuoteRequest;\n state.bridgeState.quoteFetchError =\n DEFAULT_BRIDGE_CONTROLLER_STATE.quoteFetchError;\n });\n\n try {\n const quotes = await fetchBridgeQuotes(\n updatedQuoteRequest,\n // AbortController is always defined by this line, because we assign it a few lines above,\n // not sure why Jest thinks it's not\n // Linters accurately say that it's defined\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.#abortController!.signal as AbortSignal,\n this.#clientId,\n this.#fetchFn,\n );\n\n const quotesWithL1GasFees = await this.#appendL1GasFees(quotes);\n\n this.update((state) => {\n state.bridgeState.quotes = quotesWithL1GasFees;\n state.bridgeState.quotesLoadingStatus = RequestStatus.FETCHED;\n });\n } catch (error) {\n const isAbortError = (error as Error).name === 'AbortError';\n const isAbortedDueToReset = error === RESET_STATE_ABORT_MESSAGE;\n if (isAbortedDueToReset || isAbortError) {\n return;\n }\n\n this.update((state) => {\n state.bridgeState.quoteFetchError =\n error instanceof Error ? error.message : 'Unknown error';\n state.bridgeState.quotesLoadingStatus = RequestStatus.ERROR;\n });\n console.log('Failed to fetch bridge quotes', error);\n } finally {\n const { maxRefreshCount } =\n bridgeState.bridgeFeatureFlags[BridgeFeatureFlagsKey.EXTENSION_CONFIG];\n\n const updatedQuotesRefreshCount = bridgeState.quotesRefreshCount + 1;\n // Stop polling if the maximum number of refreshes has been reached\n if (\n updatedQuoteRequest.insufficientBal ||\n (!updatedQuoteRequest.insufficientBal &&\n updatedQuotesRefreshCount >= maxRefreshCount)\n ) {\n this.stopAllPolling();\n }\n\n // Update quote fetching stats\n const quotesLastFetched = Date.now();\n this.update((state) => {\n state.bridgeState.quotesInitialLoadTime =\n updatedQuotesRefreshCount === 1 && this.#quotesFirstFetched\n ? quotesLastFetched - this.#quotesFirstFetched\n : bridgeState.quotesInitialLoadTime;\n state.bridgeState.quotesLastFetched = quotesLastFetched;\n state.bridgeState.quotesRefreshCount = updatedQuotesRefreshCount;\n });\n }\n };\n\n readonly #appendL1GasFees = async (\n quotes: QuoteResponse[],\n ): Promise<(QuoteResponse & L1GasFees)[]> => {\n return await Promise.all(\n quotes.map(async (quoteResponse) => {\n const { quote, trade, approval } = quoteResponse;\n const chainId = numberToHex(quote.srcChainId) as ChainId;\n if (\n [CHAIN_IDS.OPTIMISM.toString(), CHAIN_IDS.BASE.toString()].includes(\n chainId,\n )\n ) {\n const getTxParams = (txData: TxData) => ({\n from: txData.from,\n to: txData.to,\n value: txData.value,\n data: txData.data,\n gasLimit: txData.gasLimit?.toString(),\n });\n const approvalL1GasFees = approval\n ? await this.#getLayer1GasFee({\n transactionParams: getTxParams(approval),\n chainId,\n })\n : '0';\n const tradeL1GasFees = await this.#getLayer1GasFee({\n transactionParams: getTxParams(trade),\n chainId,\n });\n return {\n ...quoteResponse,\n l1GasFeesInHexWei: sumHexes(approvalL1GasFees, tradeL1GasFees),\n };\n }\n return quoteResponse;\n }),\n );\n };\n\n #getSelectedAccount() {\n return this.messagingSystem.call('AccountsController:getSelectedAccount');\n }\n\n #getSelectedNetworkClient() {\n const { selectedNetworkClientId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n const networkClient = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n selectedNetworkClientId,\n );\n return networkClient;\n }\n\n #getSelectedNetworkClientId(chainId: Hex) {\n return this.messagingSystem.call(\n 'NetworkController:findNetworkClientIdByChainId',\n chainId,\n );\n }\n\n /**\n *\n * @param contractAddress - The address of the ERC20 token contract\n * @param chainId - The hex chain ID of the bridge network\n * @returns The atomic allowance of the ERC20 token contract\n */\n getBridgeERC20Allowance = async (\n contractAddress: string,\n chainId: Hex,\n ): Promise<string> => {\n const provider = this.#getSelectedNetworkClient()?.provider;\n if (!provider) {\n throw new Error('No provider found');\n }\n\n const ethersProvider = new BrowserProvider(provider);\n const contract = new Contract(contractAddress, abiERC20, ethersProvider);\n const { address: walletAddress } = this.#getSelectedAccount();\n const allowance: bigint = await contract.allowance(\n walletAddress,\n METABRIDGE_CHAIN_TO_ADDRESS_MAP[chainId],\n );\n return allowance.toString();\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"bridge-controller.cjs","sourceRoot":"","sources":["../src/bridge-controller.ts"],"names":[],"mappings":"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","sourcesContent":["import type { StateMetadata } from '@metamask/base-controller';\nimport type { ChainId } from '@metamask/controller-utils';\nimport { abiERC20 } from '@metamask/metamask-eth-abis';\nimport type { NetworkClientId } from '@metamask/network-controller';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport type { TransactionParams } from '@metamask/transaction-controller';\nimport { numberToHex } from '@metamask/utils';\nimport type { Hex } from '@metamask/utils';\nimport { BrowserProvider, Contract } from 'ethers';\n\nimport type { BridgeClientId } from './constants/bridge';\nimport {\n BRIDGE_CONTROLLER_NAME,\n DEFAULT_BRIDGE_CONTROLLER_STATE,\n METABRIDGE_CHAIN_TO_ADDRESS_MAP,\n REFRESH_INTERVAL_MS,\n} from './constants/bridge';\nimport { CHAIN_IDS } from './constants/chains';\nimport {\n type L1GasFees,\n type QuoteRequest,\n type QuoteResponse,\n type TxData,\n type BridgeControllerState,\n type BridgeControllerMessenger,\n type FetchFunction,\n BridgeFeatureFlagsKey,\n RequestStatus,\n} from './types';\nimport { hasSufficientBalance } from './utils/balance';\nimport { getDefaultBridgeControllerState, sumHexes } from './utils/bridge';\nimport { fetchBridgeFeatureFlags, fetchBridgeQuotes } from './utils/fetch';\nimport { isValidQuoteRequest } from './utils/quote';\n\nconst metadata: StateMetadata<BridgeControllerState> = {\n bridgeFeatureFlags: {\n persist: false,\n anonymous: false,\n },\n quoteRequest: {\n persist: false,\n anonymous: false,\n },\n quotes: {\n persist: false,\n anonymous: false,\n },\n quotesInitialLoadTime: {\n persist: false,\n anonymous: false,\n },\n quotesLastFetched: {\n persist: false,\n anonymous: false,\n },\n quotesLoadingStatus: {\n persist: false,\n anonymous: false,\n },\n quoteFetchError: {\n persist: false,\n anonymous: false,\n },\n quotesRefreshCount: {\n persist: false,\n anonymous: false,\n },\n};\n\nconst RESET_STATE_ABORT_MESSAGE = 'Reset controller state';\n\n/** The input to start polling for the {@link BridgeController} */\ntype BridgePollingInput = {\n networkClientId: NetworkClientId;\n updatedQuoteRequest: QuoteRequest;\n};\n\nexport class BridgeController extends StaticIntervalPollingController<BridgePollingInput>()<\n typeof BRIDGE_CONTROLLER_NAME,\n BridgeControllerState,\n BridgeControllerMessenger\n> {\n #abortController: AbortController | undefined;\n\n #quotesFirstFetched: number | undefined;\n\n readonly #clientId: string;\n\n readonly #getLayer1GasFee: (params: {\n transactionParams: TransactionParams;\n chainId: ChainId;\n }) => Promise<string>;\n\n readonly #fetchFn: FetchFunction;\n\n constructor({\n messenger,\n state,\n clientId,\n getLayer1GasFee,\n fetchFn,\n }: {\n messenger: BridgeControllerMessenger;\n state?: Partial<BridgeControllerState>;\n clientId: BridgeClientId;\n getLayer1GasFee: (params: {\n transactionParams: TransactionParams;\n chainId: ChainId;\n }) => Promise<string>;\n fetchFn: FetchFunction;\n }) {\n super({\n name: BRIDGE_CONTROLLER_NAME,\n metadata,\n messenger,\n state: {\n ...getDefaultBridgeControllerState(),\n ...state,\n },\n });\n\n this.setIntervalLength(REFRESH_INTERVAL_MS);\n\n this.#abortController = new AbortController();\n this.#getLayer1GasFee = getLayer1GasFee;\n this.#clientId = clientId;\n this.#fetchFn = fetchFn;\n\n // Register action handlers\n this.messagingSystem.registerActionHandler(\n `${BRIDGE_CONTROLLER_NAME}:setBridgeFeatureFlags`,\n this.setBridgeFeatureFlags.bind(this),\n );\n this.messagingSystem.registerActionHandler(\n `${BRIDGE_CONTROLLER_NAME}:updateBridgeQuoteRequestParams`,\n this.updateBridgeQuoteRequestParams.bind(this),\n );\n this.messagingSystem.registerActionHandler(\n `${BRIDGE_CONTROLLER_NAME}:resetState`,\n this.resetState.bind(this),\n );\n this.messagingSystem.registerActionHandler(\n `${BRIDGE_CONTROLLER_NAME}:getBridgeERC20Allowance`,\n this.getBridgeERC20Allowance.bind(this),\n );\n }\n\n _executePoll = async (pollingInput: BridgePollingInput) => {\n await this.#fetchBridgeQuotes(pollingInput);\n };\n\n updateBridgeQuoteRequestParams = async (\n paramsToUpdate: Partial<QuoteRequest>,\n ) => {\n this.stopAllPolling();\n this.#abortController?.abort('Quote request updated');\n\n const updatedQuoteRequest = {\n ...DEFAULT_BRIDGE_CONTROLLER_STATE.quoteRequest,\n ...paramsToUpdate,\n };\n\n this.update((state) => {\n state.quoteRequest = updatedQuoteRequest;\n state.quotes = DEFAULT_BRIDGE_CONTROLLER_STATE.quotes;\n state.quotesLastFetched =\n DEFAULT_BRIDGE_CONTROLLER_STATE.quotesLastFetched;\n state.quotesLoadingStatus =\n DEFAULT_BRIDGE_CONTROLLER_STATE.quotesLoadingStatus;\n state.quoteFetchError = DEFAULT_BRIDGE_CONTROLLER_STATE.quoteFetchError;\n state.quotesRefreshCount =\n DEFAULT_BRIDGE_CONTROLLER_STATE.quotesRefreshCount;\n state.quotesInitialLoadTime =\n DEFAULT_BRIDGE_CONTROLLER_STATE.quotesInitialLoadTime;\n });\n\n if (isValidQuoteRequest(updatedQuoteRequest)) {\n this.#quotesFirstFetched = Date.now();\n const walletAddress = this.#getSelectedAccount().address;\n const srcChainIdInHex = numberToHex(updatedQuoteRequest.srcChainId);\n\n const insufficientBal =\n paramsToUpdate.insufficientBal ||\n !(await this.#hasSufficientBalance(updatedQuoteRequest));\n\n const networkClientId = this.#getSelectedNetworkClientId(srcChainIdInHex);\n this.startPolling({\n networkClientId,\n updatedQuoteRequest: {\n ...updatedQuoteRequest,\n walletAddress,\n insufficientBal,\n },\n });\n }\n };\n\n readonly #hasSufficientBalance = async (quoteRequest: QuoteRequest) => {\n const walletAddress = this.#getSelectedAccount().address;\n const srcChainIdInHex = numberToHex(quoteRequest.srcChainId);\n const provider = this.#getSelectedNetworkClient()?.provider;\n\n return (\n provider &&\n (await hasSufficientBalance(\n provider,\n walletAddress,\n quoteRequest.srcTokenAddress,\n quoteRequest.srcTokenAmount,\n srcChainIdInHex,\n ))\n );\n };\n\n resetState = () => {\n this.stopAllPolling();\n this.#abortController?.abort(RESET_STATE_ABORT_MESSAGE);\n\n this.update((state) => {\n // Cannot do direct assignment to state, i.e. state = {... }, need to manually assign each field\n state.quoteRequest = DEFAULT_BRIDGE_CONTROLLER_STATE.quoteRequest;\n state.quotesInitialLoadTime =\n DEFAULT_BRIDGE_CONTROLLER_STATE.quotesInitialLoadTime;\n state.quotes = DEFAULT_BRIDGE_CONTROLLER_STATE.quotes;\n state.quotesLastFetched =\n DEFAULT_BRIDGE_CONTROLLER_STATE.quotesLastFetched;\n state.quotesLoadingStatus =\n DEFAULT_BRIDGE_CONTROLLER_STATE.quotesLoadingStatus;\n state.quoteFetchError = DEFAULT_BRIDGE_CONTROLLER_STATE.quoteFetchError;\n state.quotesRefreshCount =\n DEFAULT_BRIDGE_CONTROLLER_STATE.quotesRefreshCount;\n\n // Keep feature flags\n const originalFeatureFlags = state.bridgeFeatureFlags;\n state.bridgeFeatureFlags = originalFeatureFlags;\n });\n };\n\n setBridgeFeatureFlags = async () => {\n const bridgeFeatureFlags = await fetchBridgeFeatureFlags(\n this.#clientId,\n this.#fetchFn,\n );\n this.update((state) => {\n state.bridgeFeatureFlags = bridgeFeatureFlags;\n });\n this.setIntervalLength(\n bridgeFeatureFlags[BridgeFeatureFlagsKey.EXTENSION_CONFIG].refreshRate,\n );\n };\n\n readonly #fetchBridgeQuotes = async ({\n networkClientId: _networkClientId,\n updatedQuoteRequest,\n }: BridgePollingInput) => {\n const { bridgeFeatureFlags, quotesInitialLoadTime, quotesRefreshCount } =\n this.state;\n this.#abortController?.abort('New quote request');\n this.#abortController = new AbortController();\n if (updatedQuoteRequest.srcChainId === updatedQuoteRequest.destChainId) {\n return;\n }\n this.update((state) => {\n state.quotesLoadingStatus = RequestStatus.LOADING;\n state.quoteRequest = updatedQuoteRequest;\n state.quoteFetchError = DEFAULT_BRIDGE_CONTROLLER_STATE.quoteFetchError;\n });\n\n try {\n const quotes = await fetchBridgeQuotes(\n updatedQuoteRequest,\n // AbortController is always defined by this line, because we assign it a few lines above,\n // not sure why Jest thinks it's not\n // Linters accurately say that it's defined\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.#abortController!.signal as AbortSignal,\n this.#clientId,\n this.#fetchFn,\n );\n\n const quotesWithL1GasFees = await this.#appendL1GasFees(quotes);\n\n this.update((state) => {\n state.quotes = quotesWithL1GasFees;\n state.quotesLoadingStatus = RequestStatus.FETCHED;\n });\n } catch (error) {\n const isAbortError = (error as Error).name === 'AbortError';\n const isAbortedDueToReset = error === RESET_STATE_ABORT_MESSAGE;\n if (isAbortedDueToReset || isAbortError) {\n return;\n }\n\n this.update((state) => {\n state.quoteFetchError =\n error instanceof Error ? error.message : 'Unknown error';\n state.quotesLoadingStatus = RequestStatus.ERROR;\n });\n console.log('Failed to fetch bridge quotes', error);\n } finally {\n const { maxRefreshCount } =\n bridgeFeatureFlags[BridgeFeatureFlagsKey.EXTENSION_CONFIG];\n\n const updatedQuotesRefreshCount = quotesRefreshCount + 1;\n // Stop polling if the maximum number of refreshes has been reached\n if (\n updatedQuoteRequest.insufficientBal ||\n (!updatedQuoteRequest.insufficientBal &&\n updatedQuotesRefreshCount >= maxRefreshCount)\n ) {\n this.stopAllPolling();\n }\n\n // Update quote fetching stats\n const quotesLastFetched = Date.now();\n this.update((state) => {\n state.quotesInitialLoadTime =\n updatedQuotesRefreshCount === 1 && this.#quotesFirstFetched\n ? quotesLastFetched - this.#quotesFirstFetched\n : quotesInitialLoadTime;\n state.quotesLastFetched = quotesLastFetched;\n state.quotesRefreshCount = updatedQuotesRefreshCount;\n });\n }\n };\n\n readonly #appendL1GasFees = async (\n quotes: QuoteResponse[],\n ): Promise<(QuoteResponse & L1GasFees)[]> => {\n return await Promise.all(\n quotes.map(async (quoteResponse) => {\n const { quote, trade, approval } = quoteResponse;\n const chainId = numberToHex(quote.srcChainId) as ChainId;\n if (\n [CHAIN_IDS.OPTIMISM.toString(), CHAIN_IDS.BASE.toString()].includes(\n chainId,\n )\n ) {\n const getTxParams = (txData: TxData) => ({\n from: txData.from,\n to: txData.to,\n value: txData.value,\n data: txData.data,\n gasLimit: txData.gasLimit?.toString(),\n });\n const approvalL1GasFees = approval\n ? await this.#getLayer1GasFee({\n transactionParams: getTxParams(approval),\n chainId,\n })\n : '0';\n const tradeL1GasFees = await this.#getLayer1GasFee({\n transactionParams: getTxParams(trade),\n chainId,\n });\n return {\n ...quoteResponse,\n l1GasFeesInHexWei: sumHexes(approvalL1GasFees, tradeL1GasFees),\n };\n }\n return quoteResponse;\n }),\n );\n };\n\n #getSelectedAccount() {\n return this.messagingSystem.call('AccountsController:getSelectedAccount');\n }\n\n #getSelectedNetworkClient() {\n const { selectedNetworkClientId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n const networkClient = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n selectedNetworkClientId,\n );\n return networkClient;\n }\n\n #getSelectedNetworkClientId(chainId: Hex) {\n return this.messagingSystem.call(\n 'NetworkController:findNetworkClientIdByChainId',\n chainId,\n );\n }\n\n /**\n *\n * @param contractAddress - The address of the ERC20 token contract\n * @param chainId - The hex chain ID of the bridge network\n * @returns The atomic allowance of the ERC20 token contract\n */\n getBridgeERC20Allowance = async (\n contractAddress: string,\n chainId: Hex,\n ): Promise<string> => {\n const provider = this.#getSelectedNetworkClient()?.provider;\n if (!provider) {\n throw new Error('No provider found');\n }\n\n const ethersProvider = new BrowserProvider(provider);\n const contract = new Contract(contractAddress, abiERC20, ethersProvider);\n const { address: walletAddress } = this.#getSelectedAccount();\n const allowance: bigint = await contract.allowance(\n walletAddress,\n METABRIDGE_CHAIN_TO_ADDRESS_MAP[chainId],\n );\n return allowance.toString();\n };\n}\n"]}
|
|
@@ -4,8 +4,7 @@ import type { TransactionParams } from "@metamask/transaction-controller";
|
|
|
4
4
|
import type { Hex } from "@metamask/utils";
|
|
5
5
|
import type { BridgeClientId } from "./constants/bridge.cjs";
|
|
6
6
|
import { BRIDGE_CONTROLLER_NAME } from "./constants/bridge.cjs";
|
|
7
|
-
import { type QuoteRequest, type BridgeControllerState } from "./types.cjs";
|
|
8
|
-
import type { BridgeControllerMessenger, FetchFunction } from "./types.cjs";
|
|
7
|
+
import { type QuoteRequest, type BridgeControllerState, type BridgeControllerMessenger, type FetchFunction } from "./types.cjs";
|
|
9
8
|
/** The input to start polling for the {@link BridgeController} */
|
|
10
9
|
type BridgePollingInput = {
|
|
11
10
|
networkClientId: NetworkClientId;
|
|
@@ -26,9 +25,7 @@ declare const BridgeController_base: (abstract new (...args: any[]) => {
|
|
|
26
25
|
stopPollingByPollingToken(pollingToken: string): void;
|
|
27
26
|
onPollingComplete(input: BridgePollingInput, callback: (input: BridgePollingInput) => void): void;
|
|
28
27
|
}) & typeof import("@metamask/base-controller").BaseController;
|
|
29
|
-
export declare class BridgeController extends BridgeController_base<typeof BRIDGE_CONTROLLER_NAME, {
|
|
30
|
-
bridgeState: BridgeControllerState;
|
|
31
|
-
}, BridgeControllerMessenger> {
|
|
28
|
+
export declare class BridgeController extends BridgeController_base<typeof BRIDGE_CONTROLLER_NAME, BridgeControllerState, BridgeControllerMessenger> {
|
|
32
29
|
#private;
|
|
33
30
|
constructor({ messenger, state, clientId, getLayer1GasFee, fetchFn, }: {
|
|
34
31
|
messenger: BridgeControllerMessenger;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge-controller.d.cts","sourceRoot":"","sources":["../src/bridge-controller.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,mCAAmC;AAE1D,OAAO,KAAK,EAAE,eAAe,EAAE,qCAAqC;AAEpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,yCAAyC;AAE1E,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAG3C,OAAO,KAAK,EAAE,cAAc,EAAE,+BAA2B;
|
|
1
|
+
{"version":3,"file":"bridge-controller.d.cts","sourceRoot":"","sources":["../src/bridge-controller.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,mCAAmC;AAE1D,OAAO,KAAK,EAAE,eAAe,EAAE,qCAAqC;AAEpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,yCAAyC;AAE1E,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAG3C,OAAO,KAAK,EAAE,cAAc,EAAE,+BAA2B;AACzD,OAAO,EACL,sBAAsB,EAIvB,+BAA2B;AAE5B,OAAO,EAEL,KAAK,YAAY,EAGjB,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,EAC9B,KAAK,aAAa,EAGnB,oBAAgB;AA2CjB,kEAAkE;AAClE,KAAK,kBAAkB,GAAG;IACxB,eAAe,EAAE,eAAe,CAAC;IACjC,mBAAmB,EAAE,YAAY,CAAC;CACnC,CAAC;;;;;;;;;;;;;;;;AAEF,qBAAa,gBAAiB,SAAQ,sBACpC,OAAO,sBAAsB,EAC7B,qBAAqB,EACrB,yBAAyB,CAC1B;;gBAca,EACV,SAAS,EACT,KAAK,EACL,QAAQ,EACR,eAAe,EACf,OAAO,GACR,EAAE;QACD,SAAS,EAAE,yBAAyB,CAAC;QACrC,KAAK,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;QACvC,QAAQ,EAAE,cAAc,CAAC;QACzB,eAAe,EAAE,CAAC,MAAM,EAAE;YACxB,iBAAiB,EAAE,iBAAiB,CAAC;YACrC,OAAO,EAAE,OAAO,CAAC;SAClB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;QACtB,OAAO,EAAE,aAAa,CAAC;KACxB;IAqCD,YAAY,iBAAwB,kBAAkB,mBAEpD;IAEF,8BAA8B,mBACZ,QAAQ,YAAY,CAAC,mBA2CrC;IAmBF,UAAU,aAsBR;IAEF,qBAAqB,sBAWnB;IA0IF;;;;;OAKG;IACH,uBAAuB,oBACJ,MAAM,WACd,GAAG,KACX,QAAQ,MAAM,CAAC,CAchB;CACH"}
|
|
@@ -4,8 +4,7 @@ import type { TransactionParams } from "@metamask/transaction-controller";
|
|
|
4
4
|
import type { Hex } from "@metamask/utils";
|
|
5
5
|
import type { BridgeClientId } from "./constants/bridge.mjs";
|
|
6
6
|
import { BRIDGE_CONTROLLER_NAME } from "./constants/bridge.mjs";
|
|
7
|
-
import { type QuoteRequest, type BridgeControllerState } from "./types.mjs";
|
|
8
|
-
import type { BridgeControllerMessenger, FetchFunction } from "./types.mjs";
|
|
7
|
+
import { type QuoteRequest, type BridgeControllerState, type BridgeControllerMessenger, type FetchFunction } from "./types.mjs";
|
|
9
8
|
/** The input to start polling for the {@link BridgeController} */
|
|
10
9
|
type BridgePollingInput = {
|
|
11
10
|
networkClientId: NetworkClientId;
|
|
@@ -26,9 +25,7 @@ declare const BridgeController_base: (abstract new (...args: any[]) => {
|
|
|
26
25
|
stopPollingByPollingToken(pollingToken: string): void;
|
|
27
26
|
onPollingComplete(input: BridgePollingInput, callback: (input: BridgePollingInput) => void): void;
|
|
28
27
|
}) & typeof import("@metamask/base-controller").BaseController;
|
|
29
|
-
export declare class BridgeController extends BridgeController_base<typeof BRIDGE_CONTROLLER_NAME, {
|
|
30
|
-
bridgeState: BridgeControllerState;
|
|
31
|
-
}, BridgeControllerMessenger> {
|
|
28
|
+
export declare class BridgeController extends BridgeController_base<typeof BRIDGE_CONTROLLER_NAME, BridgeControllerState, BridgeControllerMessenger> {
|
|
32
29
|
#private;
|
|
33
30
|
constructor({ messenger, state, clientId, getLayer1GasFee, fetchFn, }: {
|
|
34
31
|
messenger: BridgeControllerMessenger;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge-controller.d.mts","sourceRoot":"","sources":["../src/bridge-controller.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,mCAAmC;AAE1D,OAAO,KAAK,EAAE,eAAe,EAAE,qCAAqC;AAEpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,yCAAyC;AAE1E,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAG3C,OAAO,KAAK,EAAE,cAAc,EAAE,+BAA2B;
|
|
1
|
+
{"version":3,"file":"bridge-controller.d.mts","sourceRoot":"","sources":["../src/bridge-controller.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,mCAAmC;AAE1D,OAAO,KAAK,EAAE,eAAe,EAAE,qCAAqC;AAEpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,yCAAyC;AAE1E,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAG3C,OAAO,KAAK,EAAE,cAAc,EAAE,+BAA2B;AACzD,OAAO,EACL,sBAAsB,EAIvB,+BAA2B;AAE5B,OAAO,EAEL,KAAK,YAAY,EAGjB,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,EAC9B,KAAK,aAAa,EAGnB,oBAAgB;AA2CjB,kEAAkE;AAClE,KAAK,kBAAkB,GAAG;IACxB,eAAe,EAAE,eAAe,CAAC;IACjC,mBAAmB,EAAE,YAAY,CAAC;CACnC,CAAC;;;;;;;;;;;;;;;;AAEF,qBAAa,gBAAiB,SAAQ,sBACpC,OAAO,sBAAsB,EAC7B,qBAAqB,EACrB,yBAAyB,CAC1B;;gBAca,EACV,SAAS,EACT,KAAK,EACL,QAAQ,EACR,eAAe,EACf,OAAO,GACR,EAAE;QACD,SAAS,EAAE,yBAAyB,CAAC;QACrC,KAAK,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;QACvC,QAAQ,EAAE,cAAc,CAAC;QACzB,eAAe,EAAE,CAAC,MAAM,EAAE;YACxB,iBAAiB,EAAE,iBAAiB,CAAC;YACrC,OAAO,EAAE,OAAO,CAAC;SAClB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;QACtB,OAAO,EAAE,aAAa,CAAC;KACxB;IAqCD,YAAY,iBAAwB,kBAAkB,mBAEpD;IAEF,8BAA8B,mBACZ,QAAQ,YAAY,CAAC,mBA2CrC;IAmBF,UAAU,aAsBR;IAEF,qBAAqB,sBAWnB;IA0IF;;;;;OAKG;IACH,uBAAuB,oBACJ,MAAM,WACd,GAAG,KACX,QAAQ,MAAM,CAAC,CAchB;CACH"}
|
|
@@ -14,8 +14,7 @@ import { abiERC20 } from "@metamask/metamask-eth-abis";
|
|
|
14
14
|
import { StaticIntervalPollingController } from "@metamask/polling-controller";
|
|
15
15
|
import { numberToHex } from "@metamask/utils";
|
|
16
16
|
import { BrowserProvider, Contract } from "ethers";
|
|
17
|
-
import { REFRESH_INTERVAL_MS } from "./constants/bridge.mjs";
|
|
18
|
-
import { BRIDGE_CONTROLLER_NAME, DEFAULT_BRIDGE_CONTROLLER_STATE, METABRIDGE_CHAIN_TO_ADDRESS_MAP } from "./constants/bridge.mjs";
|
|
17
|
+
import { BRIDGE_CONTROLLER_NAME, DEFAULT_BRIDGE_CONTROLLER_STATE, METABRIDGE_CHAIN_TO_ADDRESS_MAP, REFRESH_INTERVAL_MS } from "./constants/bridge.mjs";
|
|
19
18
|
import { CHAIN_IDS } from "./constants/chains.mjs";
|
|
20
19
|
import { BridgeFeatureFlagsKey, RequestStatus } from "./types.mjs";
|
|
21
20
|
import { hasSufficientBalance } from "./utils/balance.mjs";
|
|
@@ -23,7 +22,35 @@ import { getDefaultBridgeControllerState, sumHexes } from "./utils/bridge.mjs";
|
|
|
23
22
|
import { fetchBridgeFeatureFlags, fetchBridgeQuotes } from "./utils/fetch.mjs";
|
|
24
23
|
import { isValidQuoteRequest } from "./utils/quote.mjs";
|
|
25
24
|
const metadata = {
|
|
26
|
-
|
|
25
|
+
bridgeFeatureFlags: {
|
|
26
|
+
persist: false,
|
|
27
|
+
anonymous: false,
|
|
28
|
+
},
|
|
29
|
+
quoteRequest: {
|
|
30
|
+
persist: false,
|
|
31
|
+
anonymous: false,
|
|
32
|
+
},
|
|
33
|
+
quotes: {
|
|
34
|
+
persist: false,
|
|
35
|
+
anonymous: false,
|
|
36
|
+
},
|
|
37
|
+
quotesInitialLoadTime: {
|
|
38
|
+
persist: false,
|
|
39
|
+
anonymous: false,
|
|
40
|
+
},
|
|
41
|
+
quotesLastFetched: {
|
|
42
|
+
persist: false,
|
|
43
|
+
anonymous: false,
|
|
44
|
+
},
|
|
45
|
+
quotesLoadingStatus: {
|
|
46
|
+
persist: false,
|
|
47
|
+
anonymous: false,
|
|
48
|
+
},
|
|
49
|
+
quoteFetchError: {
|
|
50
|
+
persist: false,
|
|
51
|
+
anonymous: false,
|
|
52
|
+
},
|
|
53
|
+
quotesRefreshCount: {
|
|
27
54
|
persist: false,
|
|
28
55
|
anonymous: false,
|
|
29
56
|
},
|
|
@@ -36,10 +63,8 @@ export class BridgeController extends StaticIntervalPollingController() {
|
|
|
36
63
|
metadata,
|
|
37
64
|
messenger,
|
|
38
65
|
state: {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
...state,
|
|
42
|
-
},
|
|
66
|
+
...getDefaultBridgeControllerState(),
|
|
67
|
+
...state,
|
|
43
68
|
},
|
|
44
69
|
});
|
|
45
70
|
_BridgeController_instances.add(this);
|
|
@@ -59,17 +84,16 @@ export class BridgeController extends StaticIntervalPollingController() {
|
|
|
59
84
|
...paramsToUpdate,
|
|
60
85
|
};
|
|
61
86
|
this.update((state) => {
|
|
62
|
-
state.
|
|
63
|
-
state.
|
|
64
|
-
state.
|
|
87
|
+
state.quoteRequest = updatedQuoteRequest;
|
|
88
|
+
state.quotes = DEFAULT_BRIDGE_CONTROLLER_STATE.quotes;
|
|
89
|
+
state.quotesLastFetched =
|
|
65
90
|
DEFAULT_BRIDGE_CONTROLLER_STATE.quotesLastFetched;
|
|
66
|
-
state.
|
|
91
|
+
state.quotesLoadingStatus =
|
|
67
92
|
DEFAULT_BRIDGE_CONTROLLER_STATE.quotesLoadingStatus;
|
|
68
|
-
state.
|
|
69
|
-
|
|
70
|
-
state.bridgeState.quotesRefreshCount =
|
|
93
|
+
state.quoteFetchError = DEFAULT_BRIDGE_CONTROLLER_STATE.quoteFetchError;
|
|
94
|
+
state.quotesRefreshCount =
|
|
71
95
|
DEFAULT_BRIDGE_CONTROLLER_STATE.quotesRefreshCount;
|
|
72
|
-
state.
|
|
96
|
+
state.quotesInitialLoadTime =
|
|
73
97
|
DEFAULT_BRIDGE_CONTROLLER_STATE.quotesInitialLoadTime;
|
|
74
98
|
});
|
|
75
99
|
if (isValidQuoteRequest(updatedQuoteRequest)) {
|
|
@@ -100,32 +124,41 @@ export class BridgeController extends StaticIntervalPollingController() {
|
|
|
100
124
|
this.stopAllPolling();
|
|
101
125
|
__classPrivateFieldGet(this, _BridgeController_abortController, "f")?.abort(RESET_STATE_ABORT_MESSAGE);
|
|
102
126
|
this.update((state) => {
|
|
103
|
-
state.
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
127
|
+
// Cannot do direct assignment to state, i.e. state = {... }, need to manually assign each field
|
|
128
|
+
state.quoteRequest = DEFAULT_BRIDGE_CONTROLLER_STATE.quoteRequest;
|
|
129
|
+
state.quotesInitialLoadTime =
|
|
130
|
+
DEFAULT_BRIDGE_CONTROLLER_STATE.quotesInitialLoadTime;
|
|
131
|
+
state.quotes = DEFAULT_BRIDGE_CONTROLLER_STATE.quotes;
|
|
132
|
+
state.quotesLastFetched =
|
|
133
|
+
DEFAULT_BRIDGE_CONTROLLER_STATE.quotesLastFetched;
|
|
134
|
+
state.quotesLoadingStatus =
|
|
135
|
+
DEFAULT_BRIDGE_CONTROLLER_STATE.quotesLoadingStatus;
|
|
136
|
+
state.quoteFetchError = DEFAULT_BRIDGE_CONTROLLER_STATE.quoteFetchError;
|
|
137
|
+
state.quotesRefreshCount =
|
|
138
|
+
DEFAULT_BRIDGE_CONTROLLER_STATE.quotesRefreshCount;
|
|
139
|
+
// Keep feature flags
|
|
140
|
+
const originalFeatureFlags = state.bridgeFeatureFlags;
|
|
141
|
+
state.bridgeFeatureFlags = originalFeatureFlags;
|
|
108
142
|
});
|
|
109
143
|
};
|
|
110
144
|
this.setBridgeFeatureFlags = async () => {
|
|
111
145
|
const bridgeFeatureFlags = await fetchBridgeFeatureFlags(__classPrivateFieldGet(this, _BridgeController_clientId, "f"), __classPrivateFieldGet(this, _BridgeController_fetchFn, "f"));
|
|
112
146
|
this.update((state) => {
|
|
113
|
-
state.
|
|
147
|
+
state.bridgeFeatureFlags = bridgeFeatureFlags;
|
|
114
148
|
});
|
|
115
149
|
this.setIntervalLength(bridgeFeatureFlags[BridgeFeatureFlagsKey.EXTENSION_CONFIG].refreshRate);
|
|
116
150
|
};
|
|
117
151
|
_BridgeController_fetchBridgeQuotes.set(this, async ({ networkClientId: _networkClientId, updatedQuoteRequest, }) => {
|
|
118
|
-
const {
|
|
152
|
+
const { bridgeFeatureFlags, quotesInitialLoadTime, quotesRefreshCount } = this.state;
|
|
119
153
|
__classPrivateFieldGet(this, _BridgeController_abortController, "f")?.abort('New quote request');
|
|
120
154
|
__classPrivateFieldSet(this, _BridgeController_abortController, new AbortController(), "f");
|
|
121
155
|
if (updatedQuoteRequest.srcChainId === updatedQuoteRequest.destChainId) {
|
|
122
156
|
return;
|
|
123
157
|
}
|
|
124
158
|
this.update((state) => {
|
|
125
|
-
state.
|
|
126
|
-
state.
|
|
127
|
-
state.
|
|
128
|
-
DEFAULT_BRIDGE_CONTROLLER_STATE.quoteFetchError;
|
|
159
|
+
state.quotesLoadingStatus = RequestStatus.LOADING;
|
|
160
|
+
state.quoteRequest = updatedQuoteRequest;
|
|
161
|
+
state.quoteFetchError = DEFAULT_BRIDGE_CONTROLLER_STATE.quoteFetchError;
|
|
129
162
|
});
|
|
130
163
|
try {
|
|
131
164
|
const quotes = await fetchBridgeQuotes(updatedQuoteRequest,
|
|
@@ -136,8 +169,8 @@ export class BridgeController extends StaticIntervalPollingController() {
|
|
|
136
169
|
__classPrivateFieldGet(this, _BridgeController_abortController, "f").signal, __classPrivateFieldGet(this, _BridgeController_clientId, "f"), __classPrivateFieldGet(this, _BridgeController_fetchFn, "f"));
|
|
137
170
|
const quotesWithL1GasFees = await __classPrivateFieldGet(this, _BridgeController_appendL1GasFees, "f").call(this, quotes);
|
|
138
171
|
this.update((state) => {
|
|
139
|
-
state.
|
|
140
|
-
state.
|
|
172
|
+
state.quotes = quotesWithL1GasFees;
|
|
173
|
+
state.quotesLoadingStatus = RequestStatus.FETCHED;
|
|
141
174
|
});
|
|
142
175
|
}
|
|
143
176
|
catch (error) {
|
|
@@ -147,15 +180,15 @@ export class BridgeController extends StaticIntervalPollingController() {
|
|
|
147
180
|
return;
|
|
148
181
|
}
|
|
149
182
|
this.update((state) => {
|
|
150
|
-
state.
|
|
183
|
+
state.quoteFetchError =
|
|
151
184
|
error instanceof Error ? error.message : 'Unknown error';
|
|
152
|
-
state.
|
|
185
|
+
state.quotesLoadingStatus = RequestStatus.ERROR;
|
|
153
186
|
});
|
|
154
187
|
console.log('Failed to fetch bridge quotes', error);
|
|
155
188
|
}
|
|
156
189
|
finally {
|
|
157
|
-
const { maxRefreshCount } =
|
|
158
|
-
const updatedQuotesRefreshCount =
|
|
190
|
+
const { maxRefreshCount } = bridgeFeatureFlags[BridgeFeatureFlagsKey.EXTENSION_CONFIG];
|
|
191
|
+
const updatedQuotesRefreshCount = quotesRefreshCount + 1;
|
|
159
192
|
// Stop polling if the maximum number of refreshes has been reached
|
|
160
193
|
if (updatedQuoteRequest.insufficientBal ||
|
|
161
194
|
(!updatedQuoteRequest.insufficientBal &&
|
|
@@ -165,12 +198,12 @@ export class BridgeController extends StaticIntervalPollingController() {
|
|
|
165
198
|
// Update quote fetching stats
|
|
166
199
|
const quotesLastFetched = Date.now();
|
|
167
200
|
this.update((state) => {
|
|
168
|
-
state.
|
|
201
|
+
state.quotesInitialLoadTime =
|
|
169
202
|
updatedQuotesRefreshCount === 1 && __classPrivateFieldGet(this, _BridgeController_quotesFirstFetched, "f")
|
|
170
203
|
? quotesLastFetched - __classPrivateFieldGet(this, _BridgeController_quotesFirstFetched, "f")
|
|
171
|
-
:
|
|
172
|
-
state.
|
|
173
|
-
state.
|
|
204
|
+
: quotesInitialLoadTime;
|
|
205
|
+
state.quotesLastFetched = quotesLastFetched;
|
|
206
|
+
state.quotesRefreshCount = updatedQuotesRefreshCount;
|
|
174
207
|
});
|
|
175
208
|
}
|
|
176
209
|
});
|