@metamask-previews/bridge-controller 13.0.0-preview-cf47a367 → 13.0.0-preview-4fb8ceeb

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/bridge-controller.cjs +56 -4
  3. package/dist/bridge-controller.cjs.map +1 -1
  4. package/dist/bridge-controller.d.cts +1 -1
  5. package/dist/bridge-controller.d.cts.map +1 -1
  6. package/dist/bridge-controller.d.mts +1 -1
  7. package/dist/bridge-controller.d.mts.map +1 -1
  8. package/dist/bridge-controller.mjs +57 -5
  9. package/dist/bridge-controller.mjs.map +1 -1
  10. package/dist/constants/bridge.cjs +1 -0
  11. package/dist/constants/bridge.cjs.map +1 -1
  12. package/dist/constants/bridge.d.cts.map +1 -1
  13. package/dist/constants/bridge.d.mts.map +1 -1
  14. package/dist/constants/bridge.mjs +1 -0
  15. package/dist/constants/bridge.mjs.map +1 -1
  16. package/dist/index.cjs +5 -1
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.d.cts +2 -1
  19. package/dist/index.d.cts.map +1 -1
  20. package/dist/index.d.mts +2 -1
  21. package/dist/index.d.mts.map +1 -1
  22. package/dist/index.mjs +2 -1
  23. package/dist/index.mjs.map +1 -1
  24. package/dist/selectors.cjs +210 -0
  25. package/dist/selectors.cjs.map +1 -0
  26. package/dist/selectors.d.cts +1332 -0
  27. package/dist/selectors.d.cts.map +1 -0
  28. package/dist/selectors.d.mts +1332 -0
  29. package/dist/selectors.d.mts.map +1 -0
  30. package/dist/selectors.mjs +206 -0
  31. package/dist/selectors.mjs.map +1 -0
  32. package/dist/types.cjs.map +1 -1
  33. package/dist/types.d.cts +35 -9
  34. package/dist/types.d.cts.map +1 -1
  35. package/dist/types.d.mts +35 -9
  36. package/dist/types.d.mts.map +1 -1
  37. package/dist/types.mjs.map +1 -1
  38. package/dist/utils/assets.cjs +28 -0
  39. package/dist/utils/assets.cjs.map +1 -0
  40. package/dist/utils/assets.d.cts +9 -0
  41. package/dist/utils/assets.d.cts.map +1 -0
  42. package/dist/utils/assets.d.mts +9 -0
  43. package/dist/utils/assets.d.mts.map +1 -0
  44. package/dist/utils/assets.mjs +23 -0
  45. package/dist/utils/assets.mjs.map +1 -0
  46. package/dist/utils/caip-formatters.cjs +25 -1
  47. package/dist/utils/caip-formatters.cjs.map +1 -1
  48. package/dist/utils/caip-formatters.d.cts +10 -0
  49. package/dist/utils/caip-formatters.d.cts.map +1 -1
  50. package/dist/utils/caip-formatters.d.mts +10 -0
  51. package/dist/utils/caip-formatters.d.mts.map +1 -1
  52. package/dist/utils/caip-formatters.mjs +25 -2
  53. package/dist/utils/caip-formatters.mjs.map +1 -1
  54. package/dist/utils/fetch.cjs +61 -1
  55. package/dist/utils/fetch.cjs.map +1 -1
  56. package/dist/utils/fetch.d.cts +21 -1
  57. package/dist/utils/fetch.d.cts.map +1 -1
  58. package/dist/utils/fetch.d.mts +21 -1
  59. package/dist/utils/fetch.d.mts.map +1 -1
  60. package/dist/utils/fetch.mjs +59 -0
  61. package/dist/utils/fetch.mjs.map +1 -1
  62. package/dist/utils/quote.cjs +177 -1
  63. package/dist/utils/quote.cjs.map +1 -1
  64. package/dist/utils/quote.d.cts +62 -1
  65. package/dist/utils/quote.d.cts.map +1 -1
  66. package/dist/utils/quote.d.mts +62 -1
  67. package/dist/utils/quote.d.mts.map +1 -1
  68. package/dist/utils/quote.mjs +164 -0
  69. package/dist/utils/quote.mjs.map +1 -1
  70. package/package.json +8 -3
package/CHANGELOG.md CHANGED
@@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ### Added
11
+
12
+ - BREAKING: Bump dependency bignumber.js to ^9.1.2 ([#5614](https://github.com/MetaMask/core/pull/5614))
13
+ - BREAKING: Bump dependency reselect to ^5.1.1 ([#5614](https://github.com/MetaMask/core/pull/5614))
14
+ - BREAKING: Bump dependency @metamask/assets-controllers to ^56.0.0 ([#5614](https://github.com/MetaMask/core/pull/5614))
15
+ - assetExchangeRates added to BridgeController state to support tokens which are not supported by assets controllers ([#5614](https://github.com/MetaMask/core/pull/5614))
16
+ - selectExchangeRateByChainIdAndAddress selector added, which looks up exchange rates from assets and bridge controller states ([#5614](https://github.com/MetaMask/core/pull/5614))
17
+ - selectBridgeQuotes selecor added, which returns sorted quotes including their metadata ([#5614](https://github.com/MetaMask/core/pull/5614))
18
+
19
+ ### Changed
20
+
21
+ - BREAKING: Change TokenAmountValues key types from BigNumber to string ([#5614](https://github.com/MetaMask/core/pull/5614))
22
+ - BREAKING: getState actions have been added to AllowedActions and clients need to update controller initializations ([#5614](https://github.com/MetaMask/core/pull/5614))
23
+
10
24
  ## [13.0.0]
11
25
 
12
26
  ### Changed
@@ -10,18 +10,19 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
10
10
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
11
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
12
  };
13
- var _BridgeController_instances, _BridgeController_abortController, _BridgeController_quotesFirstFetched, _BridgeController_clientId, _BridgeController_getLayer1GasFee, _BridgeController_fetchFn, _BridgeController_config, _BridgeController_hasSufficientBalance, _BridgeController_setIntervalLength, _BridgeController_fetchBridgeQuotes, _BridgeController_appendL1GasFees, _BridgeController_appendSolanaFees, _BridgeController_getMultichainSelectedAccount, _BridgeController_getSelectedNetworkClientId, _BridgeController_getSelectedNetworkClient;
13
+ var _BridgeController_instances, _BridgeController_abortController, _BridgeController_quotesFirstFetched, _BridgeController_clientId, _BridgeController_getLayer1GasFee, _BridgeController_fetchFn, _BridgeController_config, _BridgeController_fetchAssetExchangeRates, _BridgeController_hasSufficientBalance, _BridgeController_setIntervalLength, _BridgeController_fetchBridgeQuotes, _BridgeController_appendL1GasFees, _BridgeController_appendSolanaFees, _BridgeController_getMultichainSelectedAccount, _BridgeController_getSelectedNetworkClientId, _BridgeController_getSelectedNetworkClient;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.BridgeController = void 0;
16
16
  const contracts_1 = require("@ethersproject/contracts");
17
17
  const providers_1 = require("@ethersproject/providers");
18
18
  const metamask_eth_abis_1 = require("@metamask/metamask-eth-abis");
19
19
  const polling_controller_1 = require("@metamask/polling-controller");
20
- const snaps_utils_1 = require("@metamask/snaps-utils");
21
20
  const utils_1 = require("@metamask/utils");
22
21
  const bridge_1 = require("./constants/bridge.cjs");
23
22
  const chains_1 = require("./constants/chains.cjs");
23
+ const selectors_1 = require("./selectors.cjs");
24
24
  const types_1 = require("./types.cjs");
25
+ const assets_1 = require("./utils/assets.cjs");
25
26
  const balance_1 = require("./utils/balance.cjs");
26
27
  const bridge_2 = require("./utils/bridge.cjs");
27
28
  const caip_formatters_1 = require("./utils/caip-formatters.cjs");
@@ -60,6 +61,10 @@ const metadata = {
60
61
  persist: false,
61
62
  anonymous: false,
62
63
  },
64
+ assetExchangeRates: {
65
+ persist: false,
66
+ anonymous: false,
67
+ },
63
68
  };
64
69
  const RESET_STATE_ABORT_MESSAGE = 'Reset controller state';
65
70
  class BridgeController extends (0, polling_controller_1.StaticIntervalPollingController)() {
@@ -103,6 +108,7 @@ class BridgeController extends (0, polling_controller_1.StaticIntervalPollingCon
103
108
  state.quotesInitialLoadTime =
104
109
  bridge_1.DEFAULT_BRIDGE_CONTROLLER_STATE.quotesInitialLoadTime;
105
110
  });
111
+ await __classPrivateFieldGet(this, _BridgeController_fetchAssetExchangeRates, "f").call(this, updatedQuoteRequest).catch((error) => console.warn('Failed to fetch asset exchange rates', error));
106
112
  if ((0, quote_1.isValidQuoteRequest)(updatedQuoteRequest)) {
107
113
  __classPrivateFieldSet(this, _BridgeController_quotesFirstFetched, Date.now(), "f");
108
114
  const providerConfig = __classPrivateFieldGet(this, _BridgeController_instances, "m", _BridgeController_getSelectedNetworkClient).call(this)?.configuration;
@@ -134,6 +140,49 @@ class BridgeController extends (0, polling_controller_1.StaticIntervalPollingCon
134
140
  });
135
141
  }
136
142
  };
143
+ /**
144
+ * Fetches the exchange rates for the assets in the quote request if they are not already in the state
145
+ * In addition to the selected tokens, this also fetches the native asset for the source and destination chains
146
+ *
147
+ * @param quoteRequest - The quote request
148
+ * @param quoteRequest.srcChainId - The source chain ID
149
+ * @param quoteRequest.srcTokenAddress - The source token address
150
+ * @param quoteRequest.destChainId - The destination chain ID
151
+ * @param quoteRequest.destTokenAddress - The destination token address
152
+ */
153
+ _BridgeController_fetchAssetExchangeRates.set(this, async ({ srcChainId, srcTokenAddress, destChainId, destTokenAddress, }) => {
154
+ const assetIds = new Set();
155
+ const exchangeRateSources = {
156
+ ...this.messagingSystem.call('MultichainAssetsRatesController:getState'),
157
+ ...this.messagingSystem.call('CurrencyRateController:getState'),
158
+ ...this.messagingSystem.call('TokenRatesController:getState'),
159
+ ...this.state,
160
+ };
161
+ if (srcTokenAddress &&
162
+ srcChainId &&
163
+ !(0, selectors_1.selectIsAssetExchangeRateInState)(exchangeRateSources, srcChainId, srcTokenAddress)) {
164
+ (0, assets_1.getAssetIdsForToken)(srcTokenAddress, srcChainId).forEach(assetIds.add);
165
+ }
166
+ if (destTokenAddress &&
167
+ destChainId &&
168
+ !(0, selectors_1.selectIsAssetExchangeRateInState)(exchangeRateSources, destChainId, destTokenAddress)) {
169
+ (0, assets_1.getAssetIdsForToken)(destTokenAddress, destChainId).forEach(assetIds.add);
170
+ }
171
+ const currency = this.messagingSystem.call('CurrencyRateController:getState').currentCurrency;
172
+ const pricesByAssetId = await (0, fetch_1.fetchAssetPrices)({
173
+ assetIds,
174
+ currencies: new Set([currency]),
175
+ clientId: __classPrivateFieldGet(this, _BridgeController_clientId, "f"),
176
+ fetchFn: __classPrivateFieldGet(this, _BridgeController_fetchFn, "f"),
177
+ });
178
+ const exchangeRates = (0, assets_1.toExchangeRates)(currency, pricesByAssetId);
179
+ this.update((state) => {
180
+ state.assetExchangeRates = {
181
+ ...state.assetExchangeRates,
182
+ ...exchangeRates,
183
+ };
184
+ });
185
+ });
137
186
  _BridgeController_hasSufficientBalance.set(this, async (quoteRequest) => {
138
187
  const walletAddress = __classPrivateFieldGet(this, _BridgeController_instances, "m", _BridgeController_getMultichainSelectedAccount).call(this)?.address;
139
188
  const srcChainIdInHex = (0, caip_formatters_1.formatChainIdToHex)(quoteRequest.srcChainId);
@@ -162,6 +211,8 @@ class BridgeController extends (0, polling_controller_1.StaticIntervalPollingCon
162
211
  state.quoteFetchError = bridge_1.DEFAULT_BRIDGE_CONTROLLER_STATE.quoteFetchError;
163
212
  state.quotesRefreshCount =
164
213
  bridge_1.DEFAULT_BRIDGE_CONTROLLER_STATE.quotesRefreshCount;
214
+ state.assetExchangeRates =
215
+ bridge_1.DEFAULT_BRIDGE_CONTROLLER_STATE.assetExchangeRates;
165
216
  // Keep feature flags
166
217
  const originalFeatureFlags = state.bridgeFeatureFlags;
167
218
  state.bridgeFeatureFlags = originalFeatureFlags;
@@ -293,9 +344,10 @@ class BridgeController extends (0, polling_controller_1.StaticIntervalPollingCon
293
344
  const selectedAccount = __classPrivateFieldGet(this, _BridgeController_instances, "m", _BridgeController_getMultichainSelectedAccount).call(this);
294
345
  if (selectedAccount?.metadata?.snap?.id && typeof trade === 'string') {
295
346
  const { value: fees } = (await this.messagingSystem.call('SnapController:handleRequest', {
347
+ // TODO fix these types
296
348
  snapId: selectedAccount.metadata.snap.id,
297
349
  origin: 'metamask',
298
- handler: snaps_utils_1.HandlerType.OnRpcRequest,
350
+ handler: 'onRpcRequest',
299
351
  request: {
300
352
  method: 'getFeeForTransaction',
301
353
  params: {
@@ -343,7 +395,7 @@ class BridgeController extends (0, polling_controller_1.StaticIntervalPollingCon
343
395
  }
344
396
  }
345
397
  exports.BridgeController = BridgeController;
346
- _BridgeController_abortController = new WeakMap(), _BridgeController_quotesFirstFetched = new WeakMap(), _BridgeController_clientId = new WeakMap(), _BridgeController_getLayer1GasFee = new WeakMap(), _BridgeController_fetchFn = new WeakMap(), _BridgeController_config = new WeakMap(), _BridgeController_hasSufficientBalance = new WeakMap(), _BridgeController_setIntervalLength = new WeakMap(), _BridgeController_fetchBridgeQuotes = new WeakMap(), _BridgeController_appendL1GasFees = new WeakMap(), _BridgeController_appendSolanaFees = new WeakMap(), _BridgeController_instances = new WeakSet(), _BridgeController_getMultichainSelectedAccount = function _BridgeController_getMultichainSelectedAccount() {
398
+ _BridgeController_abortController = new WeakMap(), _BridgeController_quotesFirstFetched = new WeakMap(), _BridgeController_clientId = new WeakMap(), _BridgeController_getLayer1GasFee = new WeakMap(), _BridgeController_fetchFn = new WeakMap(), _BridgeController_config = new WeakMap(), _BridgeController_fetchAssetExchangeRates = new WeakMap(), _BridgeController_hasSufficientBalance = new WeakMap(), _BridgeController_setIntervalLength = new WeakMap(), _BridgeController_fetchBridgeQuotes = new WeakMap(), _BridgeController_appendL1GasFees = new WeakMap(), _BridgeController_appendSolanaFees = new WeakMap(), _BridgeController_instances = new WeakSet(), _BridgeController_getMultichainSelectedAccount = function _BridgeController_getMultichainSelectedAccount() {
347
399
  return this.messagingSystem.call('AccountsController:getSelectedMultichainAccount');
348
400
  }, _BridgeController_getSelectedNetworkClientId = function _BridgeController_getSelectedNetworkClientId() {
349
401
  const { selectedNetworkClientId } = this.messagingSystem.call('NetworkController:getState');
@@ -1 +1 @@
1
- {"version":3,"file":"bridge-controller.cjs","sourceRoot":"","sources":["../src/bridge-controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AACA,wDAAoD;AACpD,wDAAwD;AAGxD,mEAAuD;AAEvD,qEAA+E;AAE/E,uDAAoD;AAEpD,2CAA8C;AAG9C,mDAO4B;AAC5B,mDAA+C;AAE/C,uCASiB;AACjB,iDAAuD;AACvD,+CAIwB;AACxB,iEAIiC;AACjC,6CAA2E;AAC3E,6CAAoD;AAEpD,MAAM,QAAQ,GAAyC;IACrD,kBAAkB,EAAE;QAClB,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;KACjB;IACD,YAAY,EAAE;QACZ,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;KACjB;IACD,MAAM,EAAE;QACN,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;KACjB;IACD,qBAAqB,EAAE;QACrB,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;KACjB;IACD,iBAAiB,EAAE;QACjB,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;KACjB;IACD,mBAAmB,EAAE;QACnB,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;KACjB;IACD,eAAe,EAAE;QACf,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;KACjB;IACD,kBAAkB,EAAE;QAClB,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;KACjB;CACF,CAAC;AAEF,MAAM,yBAAyB,GAAG,wBAAwB,CAAC;AAQ3D,MAAa,gBAAiB,SAAQ,IAAA,oDAA+B,GAIpE;IAkBC,YAAY,EACV,SAAS,EACT,KAAK,EACL,QAAQ,EACR,eAAe,EACf,OAAO,EACP,MAAM,GAaP;QACC,KAAK,CAAC;YACJ,IAAI,EAAE,+BAAsB;YAC5B,QAAQ;YACR,SAAS;YACT,KAAK,EAAE;gBACL,GAAG,IAAA,wCAA+B,GAAE;gBACpC,GAAG,KAAK;aACT;SACF,CAAC,CAAC;;QA7CL,oDAA8C;QAE9C,uDAAwC;QAE/B,6CAAkB;QAElB,oDAGa;QAEb,4CAAwB;QAExB,2CAEP;QA2DF,iBAAY,GAAG,KAAK,EAAE,YAAgC,EAAE,EAAE;YACxD,MAAM,uBAAA,IAAI,2CAAmB,MAAvB,IAAI,EAAoB,YAAY,CAAC,CAAC;QAC9C,CAAC,CAAC;QAEF,mCAA8B,GAAG,KAAK,EACpC,cAA4C,EAC5C,EAAE;YACF,IAAI,CAAC,cAAc,EAAE,CAAC;YACtB,uBAAA,IAAI,yCAAiB,EAAE,KAAK,CAAC,uBAAuB,CAAC,CAAC;YAEtD,MAAM,mBAAmB,GAAG;gBAC1B,GAAG,wCAA+B,CAAC,YAAY;gBAC/C,GAAG,cAAc;aAClB,CAAC;YAEF,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;gBACpB,KAAK,CAAC,YAAY,GAAG,mBAAmB,CAAC;gBACzC,KAAK,CAAC,MAAM,GAAG,wCAA+B,CAAC,MAAM,CAAC;gBACtD,KAAK,CAAC,iBAAiB;oBACrB,wCAA+B,CAAC,iBAAiB,CAAC;gBACpD,KAAK,CAAC,mBAAmB;oBACvB,wCAA+B,CAAC,mBAAmB,CAAC;gBACtD,KAAK,CAAC,eAAe,GAAG,wCAA+B,CAAC,eAAe,CAAC;gBACxE,KAAK,CAAC,kBAAkB;oBACtB,wCAA+B,CAAC,kBAAkB,CAAC;gBACrD,KAAK,CAAC,qBAAqB;oBACzB,wCAA+B,CAAC,qBAAqB,CAAC;YAC1D,CAAC,CAAC,CAAC;YAEH,IAAI,IAAA,2BAAmB,EAAC,mBAAmB,CAAC,EAAE;gBAC5C,uBAAA,IAAI,wCAAuB,IAAI,CAAC,GAAG,EAAE,MAAA,CAAC;gBACtC,MAAM,cAAc,GAAG,uBAAA,IAAI,+EAA0B,MAA9B,IAAI,CAA4B,EAAE,aAAa,CAAC;gBAEvE,IAAI,eAAoC,CAAC;gBACzC,IAAI,IAAA,wBAAe,EAAC,mBAAmB,CAAC,UAAU,CAAC,EAAE;oBACnD,mEAAmE;oBACnE,eAAe,GAAG,cAAc,CAAC,eAAe,CAAC;iBAClD;qBAAM,IAAI,cAAc,EAAE,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,EAAE;oBACvD,yEAAyE;oBACzE,mIAAmI;oBACnI,eAAe,GAAG,IAAI,CAAC;iBACxB;qBAAM;oBACL,8DAA8D;oBAC9D,eAAe;wBACb,cAAc,CAAC,eAAe;4BAC9B,CAAC,CAAC,MAAM,uBAAA,IAAI,8CAAsB,MAA1B,IAAI,EAAuB,mBAAmB,CAAC,CAAC,CAAC;iBAC5D;gBAED,MAAM,eAAe,GAAG,uBAAA,IAAI,iFAA4B,MAAhC,IAAI,CAA8B,CAAC;gBAC3D,qEAAqE;gBACrE,uBAAA,IAAI,2CAAmB,MAAvB,IAAI,CAAqB,CAAC;gBAC1B,IAAI,CAAC,YAAY,CAAC;oBAChB,eAAe;oBACf,mBAAmB,EAAE;wBACnB,GAAG,mBAAmB;wBACtB,eAAe;qBAChB;iBACF,CAAC,CAAC;aACJ;QACH,CAAC,CAAC;QAEO,iDAAwB,KAAK,EACpC,YAAiC,EACjC,EAAE;YACF,MAAM,aAAa,GAAG,uBAAA,IAAI,mFAA8B,MAAlC,IAAI,CAAgC,EAAE,OAAO,CAAC;YACpE,MAAM,eAAe,GAAG,IAAA,oCAAkB,EAAC,YAAY,CAAC,UAAU,CAAC,CAAC;YACpE,MAAM,QAAQ,GAAG,uBAAA,IAAI,+EAA0B,MAA9B,IAAI,CAA4B,EAAE,QAAQ,CAAC;YAC5D,MAAM,yBAAyB,GAAG,IAAA,8CAA4B,EAC5D,YAAY,CAAC,eAAe,CAC7B,CAAC;YAEF,OAAO,CACL,QAAQ;gBACR,aAAa;gBACb,yBAAyB;gBACzB,YAAY,CAAC,cAAc;gBAC3B,eAAe;gBACf,CAAC,MAAM,IAAA,8BAAoB,EACzB,QAAQ,EACR,aAAa,EACb,yBAAyB,EACzB,YAAY,CAAC,cAAc,EAC3B,eAAe,CAChB,CAAC,CACH,CAAC;QACJ,CAAC,EAAC;QAEF,eAAU,GAAG,GAAG,EAAE;YAChB,IAAI,CAAC,cAAc,EAAE,CAAC;YACtB,uBAAA,IAAI,yCAAiB,EAAE,KAAK,CAAC,yBAAyB,CAAC,CAAC;YAExD,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;gBACpB,gGAAgG;gBAChG,KAAK,CAAC,YAAY,GAAG,wCAA+B,CAAC,YAAY,CAAC;gBAClE,KAAK,CAAC,qBAAqB;oBACzB,wCAA+B,CAAC,qBAAqB,CAAC;gBACxD,KAAK,CAAC,MAAM,GAAG,wCAA+B,CAAC,MAAM,CAAC;gBACtD,KAAK,CAAC,iBAAiB;oBACrB,wCAA+B,CAAC,iBAAiB,CAAC;gBACpD,KAAK,CAAC,mBAAmB;oBACvB,wCAA+B,CAAC,mBAAmB,CAAC;gBACtD,KAAK,CAAC,eAAe,GAAG,wCAA+B,CAAC,eAAe,CAAC;gBACxE,KAAK,CAAC,kBAAkB;oBACtB,wCAA+B,CAAC,kBAAkB,CAAC;gBAErD,qBAAqB;gBACrB,MAAM,oBAAoB,GAAG,KAAK,CAAC,kBAAkB,CAAC;gBACtD,KAAK,CAAC,kBAAkB,GAAG,oBAAoB,CAAC;YAClD,CAAC,CAAC,CAAC;QACL,CAAC,CAAC;QAEF,0BAAqB,GAAG,KAAK,IAAI,EAAE;YACjC,MAAM,kBAAkB,GAAG,MAAM,IAAA,+BAAuB,EACtD,uBAAA,IAAI,kCAAU,EACd,uBAAA,IAAI,iCAAS,EACb,uBAAA,IAAI,gCAAQ,CAAC,sBAAsB,IAAI,iCAAwB,CAChE,CAAC;YACF,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;gBACpB,KAAK,CAAC,kBAAkB,GAAG,kBAAkB,CAAC;YAChD,CAAC,CAAC,CAAC;YACH,uBAAA,IAAI,2CAAmB,MAAvB,IAAI,CAAqB,CAAC;QAC5B,CAAC,CAAC;QAEF;;WAEG;QACM,8CAAqB,GAAG,EAAE;YACjC,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC;YACvB,MAAM,EAAE,UAAU,EAAE,GAAG,KAAK,CAAC,YAAY,CAAC;YAC1C,MAAM,mBAAmB,GAAG,UAAU;gBACpC,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC,6BAAqB,CAAC,gBAAgB,CAAC,CAAC,MAAM,CACrE,IAAA,qCAAmB,EAAC,UAAU,CAAC,CAChC,EAAE,WAAW;gBAChB,CAAC,CAAC,SAAS,CAAC;YACd,MAAM,kBAAkB,GACtB,KAAK,CAAC,kBAAkB,CAAC,6BAAqB,CAAC,gBAAgB,CAAC;iBAC7D,WAAW,CAAC;YACjB,IAAI,CAAC,iBAAiB,CAAC,mBAAmB,IAAI,kBAAkB,CAAC,CAAC;QACpE,CAAC,EAAC;QAEO,8CAAqB,KAAK,EAAE,EACnC,eAAe,EAAE,gBAAgB,EACjC,mBAAmB,GACA,EAAE,EAAE;YACvB,MAAM,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,GACrE,IAAI,CAAC,KAAK,CAAC;YACb,uBAAA,IAAI,yCAAiB,EAAE,KAAK,CAAC,mBAAmB,CAAC,CAAC;YAClD,uBAAA,IAAI,qCAAoB,IAAI,eAAe,EAAE,MAAA,CAAC;YAE9C,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;gBACpB,KAAK,CAAC,mBAAmB,GAAG,qBAAa,CAAC,OAAO,CAAC;gBAClD,KAAK,CAAC,YAAY,GAAG,mBAAmB,CAAC;gBACzC,KAAK,CAAC,eAAe,GAAG,wCAA+B,CAAC,eAAe,CAAC;YAC1E,CAAC,CAAC,CAAC;YAEH,IAAI;gBACF,MAAM,MAAM,GAAG,MAAM,IAAA,yBAAiB,EACpC,mBAAmB;gBACnB,0FAA0F;gBAC1F,oCAAoC;gBACpC,2CAA2C;gBAC3C,oEAAoE;gBACpE,uBAAA,IAAI,yCAAkB,CAAC,MAAqB,EAC5C,uBAAA,IAAI,kCAAU,EACd,uBAAA,IAAI,iCAAS,EACb,uBAAA,IAAI,gCAAQ,CAAC,sBAAsB,IAAI,iCAAwB,CAChE,CAAC;gBAEF,MAAM,mBAAmB,GAAG,MAAM,uBAAA,IAAI,yCAAiB,MAArB,IAAI,EAAkB,MAAM,CAAC,CAAC;gBAChE,MAAM,oBAAoB,GAAG,MAAM,uBAAA,IAAI,0CAAkB,MAAtB,IAAI,EAAmB,MAAM,CAAC,CAAC;gBAElE,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;oBACpB,KAAK,CAAC,MAAM,GAAG,mBAAmB,IAAI,oBAAoB,IAAI,MAAM,CAAC;oBACrE,KAAK,CAAC,mBAAmB,GAAG,qBAAa,CAAC,OAAO,CAAC;gBACpD,CAAC,CAAC,CAAC;aACJ;YAAC,OAAO,KAAK,EAAE;gBACd,MAAM,YAAY,GAAI,KAAe,CAAC,IAAI,KAAK,YAAY,CAAC;gBAC5D,MAAM,mBAAmB,GAAG,KAAK,KAAK,yBAAyB,CAAC;gBAChE,IAAI,mBAAmB,IAAI,YAAY,EAAE;oBACvC,OAAO;iBACR;gBAED,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;oBACpB,KAAK,CAAC,eAAe;wBACnB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;oBAC3D,KAAK,CAAC,mBAAmB,GAAG,qBAAa,CAAC,KAAK,CAAC;oBAChD,KAAK,CAAC,MAAM,GAAG,wCAA+B,CAAC,MAAM,CAAC;gBACxD,CAAC,CAAC,CAAC;gBACH,OAAO,CAAC,GAAG,CAAC,+BAA+B,EAAE,KAAK,CAAC,CAAC;aACrD;oBAAS;gBACR,MAAM,EAAE,eAAe,EAAE,GACvB,kBAAkB,CAAC,6BAAqB,CAAC,gBAAgB,CAAC,CAAC;gBAE7D,MAAM,yBAAyB,GAAG,kBAAkB,GAAG,CAAC,CAAC;gBACzD,mEAAmE;gBACnE,IACE,mBAAmB,CAAC,eAAe;oBACnC,CAAC,CAAC,mBAAmB,CAAC,eAAe;wBACnC,yBAAyB,IAAI,eAAe,CAAC,EAC/C;oBACA,IAAI,CAAC,cAAc,EAAE,CAAC;iBACvB;gBAED,8BAA8B;gBAC9B,MAAM,iBAAiB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBACrC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;oBACpB,KAAK,CAAC,qBAAqB;wBACzB,yBAAyB,KAAK,CAAC,IAAI,uBAAA,IAAI,4CAAoB;4BACzD,CAAC,CAAC,iBAAiB,GAAG,uBAAA,IAAI,4CAAoB;4BAC9C,CAAC,CAAC,qBAAqB,CAAC;oBAC5B,KAAK,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;oBAC5C,KAAK,CAAC,kBAAkB,GAAG,yBAAyB,CAAC;gBACvD,CAAC,CAAC,CAAC;aACJ;QACH,CAAC,EAAC;QAEO,4CAAmB,KAAK,EAC/B,MAAuB,EAC6B,EAAE;YACtD,oEAAoE;YACpE,MAAM,gBAAgB,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE;gBACjD,MAAM,OAAO,GAAG,IAAA,qCAAmB,EAAC,KAAK,CAAC,UAAU,CAAC,CAAC;gBACtD,OAAO,CAAC,CAAC,kBAAS,CAAC,QAAQ,EAAE,kBAAS,CAAC,IAAI,CAAC;qBACzC,GAAG,CAAC,qCAAmB,CAAC;qBACxB,QAAQ,CAAC,OAAO,CAAC,CAAC;YACvB,CAAC,CAAC,CAAC;YAEH,wEAAwE;YACxE,IAAI,CAAC,gBAAgB,EAAE;gBACrB,OAAO,MAAM,OAAO,CAAC,GAAG,CACtB,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE;oBACjC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,aAAa,CAAC;oBACjD,MAAM,OAAO,GAAG,IAAA,mBAAW,EAAC,KAAK,CAAC,UAAU,CAAY,CAAC;oBAEzD,MAAM,WAAW,GAAG,CAAC,MAAc,EAAE,EAAE,CAAC,CAAC;wBACvC,IAAI,EAAE,MAAM,CAAC,IAAI;wBACjB,EAAE,EAAE,MAAM,CAAC,EAAE;wBACb,KAAK,EAAE,MAAM,CAAC,KAAK;wBACnB,IAAI,EAAE,MAAM,CAAC,IAAI;wBACjB,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE;qBACtC,CAAC,CAAC;oBACH,MAAM,iBAAiB,GAAG,QAAQ;wBAChC,CAAC,CAAC,MAAM,uBAAA,IAAI,yCAAiB,MAArB,IAAI,EAAkB;4BAC1B,iBAAiB,EAAE,WAAW,CAAC,QAAQ,CAAC;4BACxC,OAAO;yBACR,CAAC;wBACJ,CAAC,CAAC,GAAG,CAAC;oBACR,MAAM,cAAc,GAAG,MAAM,uBAAA,IAAI,yCAAiB,MAArB,IAAI,EAAkB;wBACjD,iBAAiB,EAAE,WAAW,CAAC,KAAK,CAAC;wBACrC,OAAO;qBACR,CAAC,CAAC;oBACH,OAAO;wBACL,GAAG,aAAa;wBAChB,iBAAiB,EAAE,IAAA,iBAAQ,EAAC,iBAAiB,EAAE,cAAc,CAAC;qBAC/D,CAAC;gBACJ,CAAC,CAAC,CACH,CAAC;aACH;YAED,OAAO,SAAS,CAAC;QACnB,CAAC,EAAC;QAEO,6CAAoB,KAAK,EAChC,MAAuB,EAC8B,EAAE;YACvD,wDAAwD;YACxD,IACE,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,IAAA,wBAAe,EAAC,UAAU,CAAC,CAAC,EACxE;gBACA,OAAO,SAAS,CAAC;aAClB;YAED,OAAO,MAAM,OAAO,CAAC,GAAG,CACtB,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE;gBACjC,MAAM,EAAE,KAAK,EAAE,GAAG,aAAa,CAAC;gBAChC,MAAM,eAAe,GAAG,uBAAA,IAAI,mFAA8B,MAAlC,IAAI,CAAgC,CAAC;gBAE7D,IAAI,eAAe,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;oBACpE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,IAAI,CAAC,eAAe,CAAC,IAAI,CACtD,8BAA8B,EAC9B;wBACE,MAAM,EAAE,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAY;wBAClD,MAAM,EAAE,UAAU;wBAClB,OAAO,EAAE,yBAAW,CAAC,YAAY;wBACjC,OAAO,EAAE;4BACP,MAAM,EAAE,sBAAsB;4BAC9B,MAAM,EAAE;gCACN,WAAW,EAAE,KAAK;gCAClB,KAAK,EAAE,eAAe,CAAC,OAAO,CAAC,KAAK;6BACrC;yBACF;qBACF,CACF,CAAsB,CAAC;oBAExB,OAAO;wBACL,GAAG,aAAa;wBAChB,oBAAoB,EAAE,IAAI;qBAC3B,CAAC;iBACH;gBACD,OAAO,aAAa,CAAC;YACvB,CAAC,CAAC,CACH,CAAC;QACJ,CAAC,EAAC;QAwBF;;;;;WAKG;QACH,4BAAuB,GAAG,KAAK,EAC7B,eAAuB,EACvB,OAAY,EACK,EAAE;YACnB,MAAM,QAAQ,GAAG,uBAAA,IAAI,+EAA0B,MAA9B,IAAI,CAA4B,EAAE,QAAQ,CAAC;YAC5D,IAAI,CAAC,QAAQ,EAAE;gBACb,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;aACtC;YAED,MAAM,cAAc,GAAG,IAAI,wBAAY,CAAC,QAAQ,CAAC,CAAC;YAClD,MAAM,QAAQ,GAAG,IAAI,oBAAQ,CAAC,eAAe,EAAE,4BAAQ,EAAE,cAAc,CAAC,CAAC;YACzE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,GAC9B,uBAAA,IAAI,mFAA8B,MAAlC,IAAI,CAAgC,IAAI,EAAE,CAAC;YAC7C,MAAM,SAAS,GAAc,MAAM,QAAQ,CAAC,SAAS,CACnD,aAAa,EACb,wCAA+B,CAAC,OAAO,CAAC,CACzC,CAAC;YACF,OAAO,SAAS,CAAC,QAAQ,EAAE,CAAC;QAC9B,CAAC,CAAC;QAzXA,IAAI,CAAC,iBAAiB,CAAC,4BAAmB,CAAC,CAAC;QAE5C,uBAAA,IAAI,qCAAoB,IAAI,eAAe,EAAE,MAAA,CAAC;QAC9C,uBAAA,IAAI,qCAAoB,eAAe,MAAA,CAAC;QACxC,uBAAA,IAAI,8BAAa,QAAQ,MAAA,CAAC;QAC1B,uBAAA,IAAI,6BAAY,OAAO,MAAA,CAAC;QACxB,uBAAA,IAAI,4BAAW,MAAM,IAAI,EAAE,MAAA,CAAC;QAE5B,2BAA2B;QAC3B,IAAI,CAAC,eAAe,CAAC,qBAAqB,CACxC,GAAG,+BAAsB,wBAAwB,EACjD,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CACtC,CAAC;QACF,IAAI,CAAC,eAAe,CAAC,qBAAqB,CACxC,GAAG,+BAAsB,iCAAiC,EAC1D,IAAI,CAAC,8BAA8B,CAAC,IAAI,CAAC,IAAI,CAAC,CAC/C,CAAC;QACF,IAAI,CAAC,eAAe,CAAC,qBAAqB,CACxC,GAAG,+BAAsB,aAAa,EACtC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAC3B,CAAC;QACF,IAAI,CAAC,eAAe,CAAC,qBAAqB,CACxC,GAAG,+BAAsB,0BAA0B,EACnD,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC,CACxC,CAAC;IACJ,CAAC;CAiWF;AA9aD,4CA8aC;;IA9CG,OAAO,IAAI,CAAC,eAAe,CAAC,IAAI,CAC9B,iDAAiD,CAClD,CAAC;AACJ,CAAC;IAGC,MAAM,EAAE,uBAAuB,EAAE,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAC3D,4BAA4B,CAC7B,CAAC;IACF,OAAO,uBAAuB,CAAC;AACjC,CAAC;IAGC,MAAM,uBAAuB,GAAG,uBAAA,IAAI,iFAA4B,MAAhC,IAAI,CAA8B,CAAC;IACnE,MAAM,aAAa,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAC7C,wCAAwC,EACxC,uBAAuB,CACxB,CAAC;IACF,OAAO,aAAa,CAAC;AACvB,CAAC","sourcesContent":["import type { BigNumber } from '@ethersproject/bignumber';\nimport { Contract } from '@ethersproject/contracts';\nimport { Web3Provider } from '@ethersproject/providers';\nimport 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 SnapId } from '@metamask/snaps-sdk';\nimport { HandlerType } from '@metamask/snaps-utils';\nimport type { TransactionParams } from '@metamask/transaction-controller';\nimport { numberToHex } from '@metamask/utils';\nimport type { Hex } from '@metamask/utils';\n\nimport {\n type BridgeClientId,\n BRIDGE_CONTROLLER_NAME,\n BRIDGE_PROD_API_BASE_URL,\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 type { GenericQuoteRequest, SolanaFees } from './types';\nimport {\n type L1GasFees,\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 {\n getDefaultBridgeControllerState,\n isSolanaChainId,\n sumHexes,\n} from './utils/bridge';\nimport {\n formatAddressToCaipReference,\n formatChainIdToCaip,\n formatChainIdToHex,\n} from './utils/caip-formatters';\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: GenericQuoteRequest;\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 readonly #config: {\n customBridgeApiBaseUrl?: string;\n };\n\n constructor({\n messenger,\n state,\n clientId,\n getLayer1GasFee,\n fetchFn,\n config,\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 config?: {\n customBridgeApiBaseUrl?: string;\n };\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 this.#config = config ?? {};\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<GenericQuoteRequest>,\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 providerConfig = this.#getSelectedNetworkClient()?.configuration;\n\n let insufficientBal: boolean | undefined;\n if (isSolanaChainId(updatedQuoteRequest.srcChainId)) {\n // If the source chain is not an EVM network, use value from params\n insufficientBal = paramsToUpdate.insufficientBal;\n } else if (providerConfig?.rpcUrl?.includes('tenderly')) {\n // If the rpcUrl is a tenderly fork (e2e tests), set insufficientBal=true\n // The bridge-api filters out quotes if the balance on mainnet is insufficient so this override allows quotes to always be returned\n insufficientBal = true;\n } else {\n // Otherwise query the src token balance from the RPC provider\n insufficientBal =\n paramsToUpdate.insufficientBal ??\n !(await this.#hasSufficientBalance(updatedQuoteRequest));\n }\n\n const networkClientId = this.#getSelectedNetworkClientId();\n // Set refresh rate based on the source chain before starting polling\n this.#setIntervalLength();\n this.startPolling({\n networkClientId,\n updatedQuoteRequest: {\n ...updatedQuoteRequest,\n insufficientBal,\n },\n });\n }\n };\n\n readonly #hasSufficientBalance = async (\n quoteRequest: GenericQuoteRequest,\n ) => {\n const walletAddress = this.#getMultichainSelectedAccount()?.address;\n const srcChainIdInHex = formatChainIdToHex(quoteRequest.srcChainId);\n const provider = this.#getSelectedNetworkClient()?.provider;\n const normalizedSrcTokenAddress = formatAddressToCaipReference(\n quoteRequest.srcTokenAddress,\n );\n\n return (\n provider &&\n walletAddress &&\n normalizedSrcTokenAddress &&\n quoteRequest.srcTokenAmount &&\n srcChainIdInHex &&\n (await hasSufficientBalance(\n provider,\n walletAddress,\n normalizedSrcTokenAddress,\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 this.#config.customBridgeApiBaseUrl ?? BRIDGE_PROD_API_BASE_URL,\n );\n this.update((state) => {\n state.bridgeFeatureFlags = bridgeFeatureFlags;\n });\n this.#setIntervalLength();\n };\n\n /**\n * Sets the interval length based on the source chain\n */\n readonly #setIntervalLength = () => {\n const { state } = this;\n const { srcChainId } = state.quoteRequest;\n const refreshRateOverride = srcChainId\n ? state.bridgeFeatureFlags[BridgeFeatureFlagsKey.EXTENSION_CONFIG].chains[\n formatChainIdToCaip(srcChainId)\n ]?.refreshRate\n : undefined;\n const defaultRefreshRate =\n state.bridgeFeatureFlags[BridgeFeatureFlagsKey.EXTENSION_CONFIG]\n .refreshRate;\n this.setIntervalLength(refreshRateOverride ?? defaultRefreshRate);\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\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 this.#config.customBridgeApiBaseUrl ?? BRIDGE_PROD_API_BASE_URL,\n );\n\n const quotesWithL1GasFees = await this.#appendL1GasFees(quotes);\n const quotesWithSolanaFees = await this.#appendSolanaFees(quotes);\n\n this.update((state) => {\n state.quotes = quotesWithL1GasFees ?? quotesWithSolanaFees ?? quotes;\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 state.quotes = DEFAULT_BRIDGE_CONTROLLER_STATE.quotes;\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)[] | undefined> => {\n // Indicates whether some of the quotes are not for optimism or base\n const hasInvalidQuotes = quotes.some(({ quote }) => {\n const chainId = formatChainIdToCaip(quote.srcChainId);\n return ![CHAIN_IDS.OPTIMISM, CHAIN_IDS.BASE]\n .map(formatChainIdToCaip)\n .includes(chainId);\n });\n\n // Only append L1 gas fees if all quotes are for either optimism or base\n if (!hasInvalidQuotes) {\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\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 );\n }\n\n return undefined;\n };\n\n readonly #appendSolanaFees = async (\n quotes: QuoteResponse[],\n ): Promise<(QuoteResponse & SolanaFees)[] | undefined> => {\n // Return early if some of the quotes are not for solana\n if (\n quotes.some(({ quote: { srcChainId } }) => !isSolanaChainId(srcChainId))\n ) {\n return undefined;\n }\n\n return await Promise.all(\n quotes.map(async (quoteResponse) => {\n const { trade } = quoteResponse;\n const selectedAccount = this.#getMultichainSelectedAccount();\n\n if (selectedAccount?.metadata?.snap?.id && typeof trade === 'string') {\n const { value: fees } = (await this.messagingSystem.call(\n 'SnapController:handleRequest',\n {\n snapId: selectedAccount.metadata.snap.id as SnapId,\n origin: 'metamask',\n handler: HandlerType.OnRpcRequest,\n request: {\n method: 'getFeeForTransaction',\n params: {\n transaction: trade,\n scope: selectedAccount.options.scope,\n },\n },\n },\n )) as { value: string };\n\n return {\n ...quoteResponse,\n solanaFeesInLamports: fees,\n };\n }\n return quoteResponse;\n }),\n );\n };\n\n #getMultichainSelectedAccount() {\n return this.messagingSystem.call(\n 'AccountsController:getSelectedMultichainAccount',\n );\n }\n\n #getSelectedNetworkClientId() {\n const { selectedNetworkClientId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n return selectedNetworkClientId;\n }\n\n #getSelectedNetworkClient() {\n const selectedNetworkClientId = this.#getSelectedNetworkClientId();\n const networkClient = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n selectedNetworkClientId,\n );\n return networkClient;\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 Web3Provider(provider);\n const contract = new Contract(contractAddress, abiERC20, ethersProvider);\n const { address: walletAddress } =\n this.#getMultichainSelectedAccount() ?? {};\n const allowance: BigNumber = 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":";;;;;;;;;;;;;;;AACA,wDAAoD;AACpD,wDAAwD;AAGxD,mEAAuD;AAEvD,qEAA+E;AAG/E,2CAAwD;AAExD,mDAO4B;AAC5B,mDAA+C;AAC/C,+CAA+D;AAE/D,uCASiB;AACjB,+CAAsE;AACtE,iDAAuD;AACvD,+CAIwB;AACxB,iEAIiC;AACjC,6CAIuB;AACvB,6CAAoD;AAEpD,MAAM,QAAQ,GAAyC;IACrD,kBAAkB,EAAE;QAClB,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;KACjB;IACD,YAAY,EAAE;QACZ,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;KACjB;IACD,MAAM,EAAE;QACN,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;KACjB;IACD,qBAAqB,EAAE;QACrB,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;KACjB;IACD,iBAAiB,EAAE;QACjB,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;KACjB;IACD,mBAAmB,EAAE;QACnB,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;KACjB;IACD,eAAe,EAAE;QACf,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;KACjB;IACD,kBAAkB,EAAE;QAClB,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;KACjB;IACD,kBAAkB,EAAE;QAClB,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;KACjB;CACF,CAAC;AAEF,MAAM,yBAAyB,GAAG,wBAAwB,CAAC;AAQ3D,MAAa,gBAAiB,SAAQ,IAAA,oDAA+B,GAIpE;IAkBC,YAAY,EACV,SAAS,EACT,KAAK,EACL,QAAQ,EACR,eAAe,EACf,OAAO,EACP,MAAM,GAaP;QACC,KAAK,CAAC;YACJ,IAAI,EAAE,+BAAsB;YAC5B,QAAQ;YACR,SAAS;YACT,KAAK,EAAE;gBACL,GAAG,IAAA,wCAA+B,GAAE;gBACpC,GAAG,KAAK;aACT;SACF,CAAC,CAAC;;QA7CL,oDAA8C;QAE9C,uDAAwC;QAE/B,6CAAkB;QAElB,oDAGa;QAEb,4CAAwB;QAExB,2CAEP;QA2DF,iBAAY,GAAG,KAAK,EAAE,YAAgC,EAAE,EAAE;YACxD,MAAM,uBAAA,IAAI,2CAAmB,MAAvB,IAAI,EAAoB,YAAY,CAAC,CAAC;QAC9C,CAAC,CAAC;QAEF,mCAA8B,GAAG,KAAK,EACpC,cAA4C,EAC5C,EAAE;YACF,IAAI,CAAC,cAAc,EAAE,CAAC;YACtB,uBAAA,IAAI,yCAAiB,EAAE,KAAK,CAAC,uBAAuB,CAAC,CAAC;YAEtD,MAAM,mBAAmB,GAAG;gBAC1B,GAAG,wCAA+B,CAAC,YAAY;gBAC/C,GAAG,cAAc;aAClB,CAAC;YAEF,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;gBACpB,KAAK,CAAC,YAAY,GAAG,mBAAmB,CAAC;gBACzC,KAAK,CAAC,MAAM,GAAG,wCAA+B,CAAC,MAAM,CAAC;gBACtD,KAAK,CAAC,iBAAiB;oBACrB,wCAA+B,CAAC,iBAAiB,CAAC;gBACpD,KAAK,CAAC,mBAAmB;oBACvB,wCAA+B,CAAC,mBAAmB,CAAC;gBACtD,KAAK,CAAC,eAAe,GAAG,wCAA+B,CAAC,eAAe,CAAC;gBACxE,KAAK,CAAC,kBAAkB;oBACtB,wCAA+B,CAAC,kBAAkB,CAAC;gBACrD,KAAK,CAAC,qBAAqB;oBACzB,wCAA+B,CAAC,qBAAqB,CAAC;YAC1D,CAAC,CAAC,CAAC;YAEH,MAAM,uBAAA,IAAI,iDAAyB,MAA7B,IAAI,EAA0B,mBAAmB,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CACvE,OAAO,CAAC,IAAI,CAAC,sCAAsC,EAAE,KAAK,CAAC,CAC5D,CAAC;YAEF,IAAI,IAAA,2BAAmB,EAAC,mBAAmB,CAAC,EAAE;gBAC5C,uBAAA,IAAI,wCAAuB,IAAI,CAAC,GAAG,EAAE,MAAA,CAAC;gBACtC,MAAM,cAAc,GAAG,uBAAA,IAAI,+EAA0B,MAA9B,IAAI,CAA4B,EAAE,aAAa,CAAC;gBAEvE,IAAI,eAAoC,CAAC;gBACzC,IAAI,IAAA,wBAAe,EAAC,mBAAmB,CAAC,UAAU,CAAC,EAAE;oBACnD,mEAAmE;oBACnE,eAAe,GAAG,cAAc,CAAC,eAAe,CAAC;iBAClD;qBAAM,IAAI,cAAc,EAAE,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,EAAE;oBACvD,yEAAyE;oBACzE,mIAAmI;oBACnI,eAAe,GAAG,IAAI,CAAC;iBACxB;qBAAM;oBACL,8DAA8D;oBAC9D,eAAe;wBACb,cAAc,CAAC,eAAe;4BAC9B,CAAC,CAAC,MAAM,uBAAA,IAAI,8CAAsB,MAA1B,IAAI,EAAuB,mBAAmB,CAAC,CAAC,CAAC;iBAC5D;gBAED,MAAM,eAAe,GAAG,uBAAA,IAAI,iFAA4B,MAAhC,IAAI,CAA8B,CAAC;gBAC3D,qEAAqE;gBACrE,uBAAA,IAAI,2CAAmB,MAAvB,IAAI,CAAqB,CAAC;gBAC1B,IAAI,CAAC,YAAY,CAAC;oBAChB,eAAe;oBACf,mBAAmB,EAAE;wBACnB,GAAG,mBAAmB;wBACtB,eAAe;qBAChB;iBACF,CAAC,CAAC;aACJ;QACH,CAAC,CAAC;QAEF;;;;;;;;;WASG;QACM,oDAA2B,KAAK,EAAE,EACzC,UAAU,EACV,eAAe,EACf,WAAW,EACX,gBAAgB,GACa,EAAE,EAAE;YACjC,MAAM,QAAQ,GAAuB,IAAI,GAAG,EAAE,CAAC;YAE/C,MAAM,mBAAmB,GAAG;gBAC1B,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,0CAA0C,CAAC;gBACxE,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,iCAAiC,CAAC;gBAC/D,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,+BAA+B,CAAC;gBAC7D,GAAG,IAAI,CAAC,KAAK;aACd,CAAC;YAEF,IACE,eAAe;gBACf,UAAU;gBACV,CAAC,IAAA,4CAAgC,EAC/B,mBAAmB,EACnB,UAAU,EACV,eAAe,CAChB,EACD;gBACA,IAAA,4BAAmB,EAAC,eAAe,EAAE,UAAU,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;aACxE;YACD,IACE,gBAAgB;gBAChB,WAAW;gBACX,CAAC,IAAA,4CAAgC,EAC/B,mBAAmB,EACnB,WAAW,EACX,gBAAgB,CACjB,EACD;gBACA,IAAA,4BAAmB,EAAC,gBAAgB,EAAE,WAAW,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;aAC1E;YAED,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CACxC,iCAAiC,CAClC,CAAC,eAAe,CAAC;YAElB,MAAM,eAAe,GAAG,MAAM,IAAA,wBAAgB,EAAC;gBAC7C,QAAQ;gBACR,UAAU,EAAE,IAAI,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;gBAC/B,QAAQ,EAAE,uBAAA,IAAI,kCAAU;gBACxB,OAAO,EAAE,uBAAA,IAAI,iCAAS;aACvB,CAAC,CAAC;YACH,MAAM,aAAa,GAAG,IAAA,wBAAe,EAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;YACjE,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;gBACpB,KAAK,CAAC,kBAAkB,GAAG;oBACzB,GAAG,KAAK,CAAC,kBAAkB;oBAC3B,GAAG,aAAa;iBACjB,CAAC;YACJ,CAAC,CAAC,CAAC;QACL,CAAC,EAAC;QAEO,iDAAwB,KAAK,EACpC,YAAiC,EACjC,EAAE;YACF,MAAM,aAAa,GAAG,uBAAA,IAAI,mFAA8B,MAAlC,IAAI,CAAgC,EAAE,OAAO,CAAC;YACpE,MAAM,eAAe,GAAG,IAAA,oCAAkB,EAAC,YAAY,CAAC,UAAU,CAAC,CAAC;YACpE,MAAM,QAAQ,GAAG,uBAAA,IAAI,+EAA0B,MAA9B,IAAI,CAA4B,EAAE,QAAQ,CAAC;YAC5D,MAAM,yBAAyB,GAAG,IAAA,8CAA4B,EAC5D,YAAY,CAAC,eAAe,CAC7B,CAAC;YAEF,OAAO,CACL,QAAQ;gBACR,aAAa;gBACb,yBAAyB;gBACzB,YAAY,CAAC,cAAc;gBAC3B,eAAe;gBACf,CAAC,MAAM,IAAA,8BAAoB,EACzB,QAAQ,EACR,aAAa,EACb,yBAAyB,EACzB,YAAY,CAAC,cAAc,EAC3B,eAAe,CAChB,CAAC,CACH,CAAC;QACJ,CAAC,EAAC;QAEF,eAAU,GAAG,GAAG,EAAE;YAChB,IAAI,CAAC,cAAc,EAAE,CAAC;YACtB,uBAAA,IAAI,yCAAiB,EAAE,KAAK,CAAC,yBAAyB,CAAC,CAAC;YAExD,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;gBACpB,gGAAgG;gBAChG,KAAK,CAAC,YAAY,GAAG,wCAA+B,CAAC,YAAY,CAAC;gBAClE,KAAK,CAAC,qBAAqB;oBACzB,wCAA+B,CAAC,qBAAqB,CAAC;gBACxD,KAAK,CAAC,MAAM,GAAG,wCAA+B,CAAC,MAAM,CAAC;gBACtD,KAAK,CAAC,iBAAiB;oBACrB,wCAA+B,CAAC,iBAAiB,CAAC;gBACpD,KAAK,CAAC,mBAAmB;oBACvB,wCAA+B,CAAC,mBAAmB,CAAC;gBACtD,KAAK,CAAC,eAAe,GAAG,wCAA+B,CAAC,eAAe,CAAC;gBACxE,KAAK,CAAC,kBAAkB;oBACtB,wCAA+B,CAAC,kBAAkB,CAAC;gBACrD,KAAK,CAAC,kBAAkB;oBACtB,wCAA+B,CAAC,kBAAkB,CAAC;gBAErD,qBAAqB;gBACrB,MAAM,oBAAoB,GAAG,KAAK,CAAC,kBAAkB,CAAC;gBACtD,KAAK,CAAC,kBAAkB,GAAG,oBAAoB,CAAC;YAClD,CAAC,CAAC,CAAC;QACL,CAAC,CAAC;QAEF,0BAAqB,GAAG,KAAK,IAAI,EAAE;YACjC,MAAM,kBAAkB,GAAG,MAAM,IAAA,+BAAuB,EACtD,uBAAA,IAAI,kCAAU,EACd,uBAAA,IAAI,iCAAS,EACb,uBAAA,IAAI,gCAAQ,CAAC,sBAAsB,IAAI,iCAAwB,CAChE,CAAC;YACF,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;gBACpB,KAAK,CAAC,kBAAkB,GAAG,kBAAkB,CAAC;YAChD,CAAC,CAAC,CAAC;YACH,uBAAA,IAAI,2CAAmB,MAAvB,IAAI,CAAqB,CAAC;QAC5B,CAAC,CAAC;QAEF;;WAEG;QACM,8CAAqB,GAAG,EAAE;YACjC,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC;YACvB,MAAM,EAAE,UAAU,EAAE,GAAG,KAAK,CAAC,YAAY,CAAC;YAC1C,MAAM,mBAAmB,GAAG,UAAU;gBACpC,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC,6BAAqB,CAAC,gBAAgB,CAAC,CAAC,MAAM,CACrE,IAAA,qCAAmB,EAAC,UAAU,CAAC,CAChC,EAAE,WAAW;gBAChB,CAAC,CAAC,SAAS,CAAC;YACd,MAAM,kBAAkB,GACtB,KAAK,CAAC,kBAAkB,CAAC,6BAAqB,CAAC,gBAAgB,CAAC;iBAC7D,WAAW,CAAC;YACjB,IAAI,CAAC,iBAAiB,CAAC,mBAAmB,IAAI,kBAAkB,CAAC,CAAC;QACpE,CAAC,EAAC;QAEO,8CAAqB,KAAK,EAAE,EACnC,eAAe,EAAE,gBAAgB,EACjC,mBAAmB,GACA,EAAE,EAAE;YACvB,MAAM,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,GACrE,IAAI,CAAC,KAAK,CAAC;YACb,uBAAA,IAAI,yCAAiB,EAAE,KAAK,CAAC,mBAAmB,CAAC,CAAC;YAClD,uBAAA,IAAI,qCAAoB,IAAI,eAAe,EAAE,MAAA,CAAC;YAE9C,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;gBACpB,KAAK,CAAC,mBAAmB,GAAG,qBAAa,CAAC,OAAO,CAAC;gBAClD,KAAK,CAAC,YAAY,GAAG,mBAAmB,CAAC;gBACzC,KAAK,CAAC,eAAe,GAAG,wCAA+B,CAAC,eAAe,CAAC;YAC1E,CAAC,CAAC,CAAC;YAEH,IAAI;gBACF,MAAM,MAAM,GAAG,MAAM,IAAA,yBAAiB,EACpC,mBAAmB;gBACnB,0FAA0F;gBAC1F,oCAAoC;gBACpC,2CAA2C;gBAC3C,oEAAoE;gBACpE,uBAAA,IAAI,yCAAkB,CAAC,MAAqB,EAC5C,uBAAA,IAAI,kCAAU,EACd,uBAAA,IAAI,iCAAS,EACb,uBAAA,IAAI,gCAAQ,CAAC,sBAAsB,IAAI,iCAAwB,CAChE,CAAC;gBAEF,MAAM,mBAAmB,GAAG,MAAM,uBAAA,IAAI,yCAAiB,MAArB,IAAI,EAAkB,MAAM,CAAC,CAAC;gBAChE,MAAM,oBAAoB,GAAG,MAAM,uBAAA,IAAI,0CAAkB,MAAtB,IAAI,EAAmB,MAAM,CAAC,CAAC;gBAElE,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;oBACpB,KAAK,CAAC,MAAM,GAAG,mBAAmB,IAAI,oBAAoB,IAAI,MAAM,CAAC;oBACrE,KAAK,CAAC,mBAAmB,GAAG,qBAAa,CAAC,OAAO,CAAC;gBACpD,CAAC,CAAC,CAAC;aACJ;YAAC,OAAO,KAAK,EAAE;gBACd,MAAM,YAAY,GAAI,KAAe,CAAC,IAAI,KAAK,YAAY,CAAC;gBAC5D,MAAM,mBAAmB,GAAG,KAAK,KAAK,yBAAyB,CAAC;gBAChE,IAAI,mBAAmB,IAAI,YAAY,EAAE;oBACvC,OAAO;iBACR;gBAED,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;oBACpB,KAAK,CAAC,eAAe;wBACnB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;oBAC3D,KAAK,CAAC,mBAAmB,GAAG,qBAAa,CAAC,KAAK,CAAC;oBAChD,KAAK,CAAC,MAAM,GAAG,wCAA+B,CAAC,MAAM,CAAC;gBACxD,CAAC,CAAC,CAAC;gBACH,OAAO,CAAC,GAAG,CAAC,+BAA+B,EAAE,KAAK,CAAC,CAAC;aACrD;oBAAS;gBACR,MAAM,EAAE,eAAe,EAAE,GACvB,kBAAkB,CAAC,6BAAqB,CAAC,gBAAgB,CAAC,CAAC;gBAE7D,MAAM,yBAAyB,GAAG,kBAAkB,GAAG,CAAC,CAAC;gBACzD,mEAAmE;gBACnE,IACE,mBAAmB,CAAC,eAAe;oBACnC,CAAC,CAAC,mBAAmB,CAAC,eAAe;wBACnC,yBAAyB,IAAI,eAAe,CAAC,EAC/C;oBACA,IAAI,CAAC,cAAc,EAAE,CAAC;iBACvB;gBAED,8BAA8B;gBAC9B,MAAM,iBAAiB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBACrC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;oBACpB,KAAK,CAAC,qBAAqB;wBACzB,yBAAyB,KAAK,CAAC,IAAI,uBAAA,IAAI,4CAAoB;4BACzD,CAAC,CAAC,iBAAiB,GAAG,uBAAA,IAAI,4CAAoB;4BAC9C,CAAC,CAAC,qBAAqB,CAAC;oBAC5B,KAAK,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;oBAC5C,KAAK,CAAC,kBAAkB,GAAG,yBAAyB,CAAC;gBACvD,CAAC,CAAC,CAAC;aACJ;QACH,CAAC,EAAC;QAEO,4CAAmB,KAAK,EAC/B,MAAuB,EAC6B,EAAE;YACtD,oEAAoE;YACpE,MAAM,gBAAgB,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE;gBACjD,MAAM,OAAO,GAAG,IAAA,qCAAmB,EAAC,KAAK,CAAC,UAAU,CAAC,CAAC;gBACtD,OAAO,CAAC,CAAC,kBAAS,CAAC,QAAQ,EAAE,kBAAS,CAAC,IAAI,CAAC;qBACzC,GAAG,CAAC,qCAAmB,CAAC;qBACxB,QAAQ,CAAC,OAAO,CAAC,CAAC;YACvB,CAAC,CAAC,CAAC;YAEH,wEAAwE;YACxE,IAAI,CAAC,gBAAgB,EAAE;gBACrB,OAAO,MAAM,OAAO,CAAC,GAAG,CACtB,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE;oBACjC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,aAAa,CAAC;oBACjD,MAAM,OAAO,GAAG,IAAA,mBAAW,EAAC,KAAK,CAAC,UAAU,CAAY,CAAC;oBAEzD,MAAM,WAAW,GAAG,CAAC,MAAc,EAAE,EAAE,CAAC,CAAC;wBACvC,IAAI,EAAE,MAAM,CAAC,IAAI;wBACjB,EAAE,EAAE,MAAM,CAAC,EAAE;wBACb,KAAK,EAAE,MAAM,CAAC,KAAK;wBACnB,IAAI,EAAE,MAAM,CAAC,IAAI;wBACjB,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE;qBACtC,CAAC,CAAC;oBACH,MAAM,iBAAiB,GAAG,QAAQ;wBAChC,CAAC,CAAC,MAAM,uBAAA,IAAI,yCAAiB,MAArB,IAAI,EAAkB;4BAC1B,iBAAiB,EAAE,WAAW,CAAC,QAAQ,CAAC;4BACxC,OAAO;yBACR,CAAC;wBACJ,CAAC,CAAC,GAAG,CAAC;oBACR,MAAM,cAAc,GAAG,MAAM,uBAAA,IAAI,yCAAiB,MAArB,IAAI,EAAkB;wBACjD,iBAAiB,EAAE,WAAW,CAAC,KAAK,CAAC;wBACrC,OAAO;qBACR,CAAC,CAAC;oBACH,OAAO;wBACL,GAAG,aAAa;wBAChB,iBAAiB,EAAE,IAAA,iBAAQ,EAAC,iBAAiB,EAAE,cAAc,CAAC;qBAC/D,CAAC;gBACJ,CAAC,CAAC,CACH,CAAC;aACH;YAED,OAAO,SAAS,CAAC;QACnB,CAAC,EAAC;QAEO,6CAAoB,KAAK,EAChC,MAAuB,EAC8B,EAAE;YACvD,wDAAwD;YACxD,IACE,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,IAAA,wBAAe,EAAC,UAAU,CAAC,CAAC,EACxE;gBACA,OAAO,SAAS,CAAC;aAClB;YAED,OAAO,MAAM,OAAO,CAAC,GAAG,CACtB,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE;gBACjC,MAAM,EAAE,KAAK,EAAE,GAAG,aAAa,CAAC;gBAChC,MAAM,eAAe,GAAG,uBAAA,IAAI,mFAA8B,MAAlC,IAAI,CAAgC,CAAC;gBAE7D,IAAI,eAAe,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;oBACpE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,IAAI,CAAC,eAAe,CAAC,IAAI,CACtD,8BAA8B,EAC9B;wBACE,uBAAuB;wBACvB,MAAM,EAAE,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAW;wBACjD,MAAM,EAAE,UAAU;wBAClB,OAAO,EAAE,cAAuB;wBAChC,OAAO,EAAE;4BACP,MAAM,EAAE,sBAAsB;4BAC9B,MAAM,EAAE;gCACN,WAAW,EAAE,KAAK;gCAClB,KAAK,EAAE,eAAe,CAAC,OAAO,CAAC,KAAK;6BACrC;yBACF;qBACF,CACF,CAAsB,CAAC;oBAExB,OAAO;wBACL,GAAG,aAAa;wBAChB,oBAAoB,EAAE,IAAI;qBAC3B,CAAC;iBACH;gBACD,OAAO,aAAa,CAAC;YACvB,CAAC,CAAC,CACH,CAAC;QACJ,CAAC,EAAC;QAwBF;;;;;WAKG;QACH,4BAAuB,GAAG,KAAK,EAC7B,eAAuB,EACvB,OAAY,EACK,EAAE;YACnB,MAAM,QAAQ,GAAG,uBAAA,IAAI,+EAA0B,MAA9B,IAAI,CAA4B,EAAE,QAAQ,CAAC;YAC5D,IAAI,CAAC,QAAQ,EAAE;gBACb,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;aACtC;YAED,MAAM,cAAc,GAAG,IAAI,wBAAY,CAAC,QAAQ,CAAC,CAAC;YAClD,MAAM,QAAQ,GAAG,IAAI,oBAAQ,CAAC,eAAe,EAAE,4BAAQ,EAAE,cAAc,CAAC,CAAC;YACzE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,GAC9B,uBAAA,IAAI,mFAA8B,MAAlC,IAAI,CAAgC,IAAI,EAAE,CAAC;YAC7C,MAAM,SAAS,GAAc,MAAM,QAAQ,CAAC,SAAS,CACnD,aAAa,EACb,wCAA+B,CAAC,OAAO,CAAC,CACzC,CAAC;YACF,OAAO,SAAS,CAAC,QAAQ,EAAE,CAAC;QAC9B,CAAC,CAAC;QAncA,IAAI,CAAC,iBAAiB,CAAC,4BAAmB,CAAC,CAAC;QAE5C,uBAAA,IAAI,qCAAoB,IAAI,eAAe,EAAE,MAAA,CAAC;QAC9C,uBAAA,IAAI,qCAAoB,eAAe,MAAA,CAAC;QACxC,uBAAA,IAAI,8BAAa,QAAQ,MAAA,CAAC;QAC1B,uBAAA,IAAI,6BAAY,OAAO,MAAA,CAAC;QACxB,uBAAA,IAAI,4BAAW,MAAM,IAAI,EAAE,MAAA,CAAC;QAE5B,2BAA2B;QAC3B,IAAI,CAAC,eAAe,CAAC,qBAAqB,CACxC,GAAG,+BAAsB,wBAAwB,EACjD,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CACtC,CAAC;QACF,IAAI,CAAC,eAAe,CAAC,qBAAqB,CACxC,GAAG,+BAAsB,iCAAiC,EAC1D,IAAI,CAAC,8BAA8B,CAAC,IAAI,CAAC,IAAI,CAAC,CAC/C,CAAC;QACF,IAAI,CAAC,eAAe,CAAC,qBAAqB,CACxC,GAAG,+BAAsB,aAAa,EACtC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAC3B,CAAC;QACF,IAAI,CAAC,eAAe,CAAC,qBAAqB,CACxC,GAAG,+BAAsB,0BAA0B,EACnD,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC,CACxC,CAAC;IACJ,CAAC;CA2aF;AAxfD,4CAwfC;;IA9CG,OAAO,IAAI,CAAC,eAAe,CAAC,IAAI,CAC9B,iDAAiD,CAClD,CAAC;AACJ,CAAC;IAGC,MAAM,EAAE,uBAAuB,EAAE,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAC3D,4BAA4B,CAC7B,CAAC;IACF,OAAO,uBAAuB,CAAC;AACjC,CAAC;IAGC,MAAM,uBAAuB,GAAG,uBAAA,IAAI,iFAA4B,MAAhC,IAAI,CAA8B,CAAC;IACnE,MAAM,aAAa,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAC7C,wCAAwC,EACxC,uBAAuB,CACxB,CAAC;IACF,OAAO,aAAa,CAAC;AACvB,CAAC","sourcesContent":["import type { BigNumber } from '@ethersproject/bignumber';\nimport { Contract } from '@ethersproject/contracts';\nimport { Web3Provider } from '@ethersproject/providers';\nimport 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 type { CaipAssetType } from '@metamask/utils';\nimport { numberToHex, type Hex } from '@metamask/utils';\n\nimport {\n type BridgeClientId,\n BRIDGE_CONTROLLER_NAME,\n BRIDGE_PROD_API_BASE_URL,\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 { selectIsAssetExchangeRateInState } from './selectors';\nimport type { GenericQuoteRequest, SolanaFees } from './types';\nimport {\n type L1GasFees,\n type QuoteResponse,\n type TxData,\n type BridgeControllerState,\n type BridgeControllerMessenger,\n type FetchFunction,\n BridgeFeatureFlagsKey,\n RequestStatus,\n} from './types';\nimport { getAssetIdsForToken, toExchangeRates } from './utils/assets';\nimport { hasSufficientBalance } from './utils/balance';\nimport {\n getDefaultBridgeControllerState,\n isSolanaChainId,\n sumHexes,\n} from './utils/bridge';\nimport {\n formatAddressToCaipReference,\n formatChainIdToCaip,\n formatChainIdToHex,\n} from './utils/caip-formatters';\nimport {\n fetchAssetPrices,\n fetchBridgeFeatureFlags,\n fetchBridgeQuotes,\n} 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 assetExchangeRates: {\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: GenericQuoteRequest;\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 readonly #config: {\n customBridgeApiBaseUrl?: string;\n };\n\n constructor({\n messenger,\n state,\n clientId,\n getLayer1GasFee,\n fetchFn,\n config,\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 config?: {\n customBridgeApiBaseUrl?: string;\n };\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 this.#config = config ?? {};\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<GenericQuoteRequest>,\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 await this.#fetchAssetExchangeRates(updatedQuoteRequest).catch((error) =>\n console.warn('Failed to fetch asset exchange rates', error),\n );\n\n if (isValidQuoteRequest(updatedQuoteRequest)) {\n this.#quotesFirstFetched = Date.now();\n const providerConfig = this.#getSelectedNetworkClient()?.configuration;\n\n let insufficientBal: boolean | undefined;\n if (isSolanaChainId(updatedQuoteRequest.srcChainId)) {\n // If the source chain is not an EVM network, use value from params\n insufficientBal = paramsToUpdate.insufficientBal;\n } else if (providerConfig?.rpcUrl?.includes('tenderly')) {\n // If the rpcUrl is a tenderly fork (e2e tests), set insufficientBal=true\n // The bridge-api filters out quotes if the balance on mainnet is insufficient so this override allows quotes to always be returned\n insufficientBal = true;\n } else {\n // Otherwise query the src token balance from the RPC provider\n insufficientBal =\n paramsToUpdate.insufficientBal ??\n !(await this.#hasSufficientBalance(updatedQuoteRequest));\n }\n\n const networkClientId = this.#getSelectedNetworkClientId();\n // Set refresh rate based on the source chain before starting polling\n this.#setIntervalLength();\n this.startPolling({\n networkClientId,\n updatedQuoteRequest: {\n ...updatedQuoteRequest,\n insufficientBal,\n },\n });\n }\n };\n\n /**\n * Fetches the exchange rates for the assets in the quote request if they are not already in the state\n * In addition to the selected tokens, this also fetches the native asset for the source and destination chains\n *\n * @param quoteRequest - The quote request\n * @param quoteRequest.srcChainId - The source chain ID\n * @param quoteRequest.srcTokenAddress - The source token address\n * @param quoteRequest.destChainId - The destination chain ID\n * @param quoteRequest.destTokenAddress - The destination token address\n */\n readonly #fetchAssetExchangeRates = async ({\n srcChainId,\n srcTokenAddress,\n destChainId,\n destTokenAddress,\n }: Partial<GenericQuoteRequest>) => {\n const assetIds: Set<CaipAssetType> = new Set();\n\n const exchangeRateSources = {\n ...this.messagingSystem.call('MultichainAssetsRatesController:getState'),\n ...this.messagingSystem.call('CurrencyRateController:getState'),\n ...this.messagingSystem.call('TokenRatesController:getState'),\n ...this.state,\n };\n\n if (\n srcTokenAddress &&\n srcChainId &&\n !selectIsAssetExchangeRateInState(\n exchangeRateSources,\n srcChainId,\n srcTokenAddress,\n )\n ) {\n getAssetIdsForToken(srcTokenAddress, srcChainId).forEach(assetIds.add);\n }\n if (\n destTokenAddress &&\n destChainId &&\n !selectIsAssetExchangeRateInState(\n exchangeRateSources,\n destChainId,\n destTokenAddress,\n )\n ) {\n getAssetIdsForToken(destTokenAddress, destChainId).forEach(assetIds.add);\n }\n\n const currency = this.messagingSystem.call(\n 'CurrencyRateController:getState',\n ).currentCurrency;\n\n const pricesByAssetId = await fetchAssetPrices({\n assetIds,\n currencies: new Set([currency]),\n clientId: this.#clientId,\n fetchFn: this.#fetchFn,\n });\n const exchangeRates = toExchangeRates(currency, pricesByAssetId);\n this.update((state) => {\n state.assetExchangeRates = {\n ...state.assetExchangeRates,\n ...exchangeRates,\n };\n });\n };\n\n readonly #hasSufficientBalance = async (\n quoteRequest: GenericQuoteRequest,\n ) => {\n const walletAddress = this.#getMultichainSelectedAccount()?.address;\n const srcChainIdInHex = formatChainIdToHex(quoteRequest.srcChainId);\n const provider = this.#getSelectedNetworkClient()?.provider;\n const normalizedSrcTokenAddress = formatAddressToCaipReference(\n quoteRequest.srcTokenAddress,\n );\n\n return (\n provider &&\n walletAddress &&\n normalizedSrcTokenAddress &&\n quoteRequest.srcTokenAmount &&\n srcChainIdInHex &&\n (await hasSufficientBalance(\n provider,\n walletAddress,\n normalizedSrcTokenAddress,\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 state.assetExchangeRates =\n DEFAULT_BRIDGE_CONTROLLER_STATE.assetExchangeRates;\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 this.#config.customBridgeApiBaseUrl ?? BRIDGE_PROD_API_BASE_URL,\n );\n this.update((state) => {\n state.bridgeFeatureFlags = bridgeFeatureFlags;\n });\n this.#setIntervalLength();\n };\n\n /**\n * Sets the interval length based on the source chain\n */\n readonly #setIntervalLength = () => {\n const { state } = this;\n const { srcChainId } = state.quoteRequest;\n const refreshRateOverride = srcChainId\n ? state.bridgeFeatureFlags[BridgeFeatureFlagsKey.EXTENSION_CONFIG].chains[\n formatChainIdToCaip(srcChainId)\n ]?.refreshRate\n : undefined;\n const defaultRefreshRate =\n state.bridgeFeatureFlags[BridgeFeatureFlagsKey.EXTENSION_CONFIG]\n .refreshRate;\n this.setIntervalLength(refreshRateOverride ?? defaultRefreshRate);\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\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 this.#config.customBridgeApiBaseUrl ?? BRIDGE_PROD_API_BASE_URL,\n );\n\n const quotesWithL1GasFees = await this.#appendL1GasFees(quotes);\n const quotesWithSolanaFees = await this.#appendSolanaFees(quotes);\n\n this.update((state) => {\n state.quotes = quotesWithL1GasFees ?? quotesWithSolanaFees ?? quotes;\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 state.quotes = DEFAULT_BRIDGE_CONTROLLER_STATE.quotes;\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)[] | undefined> => {\n // Indicates whether some of the quotes are not for optimism or base\n const hasInvalidQuotes = quotes.some(({ quote }) => {\n const chainId = formatChainIdToCaip(quote.srcChainId);\n return ![CHAIN_IDS.OPTIMISM, CHAIN_IDS.BASE]\n .map(formatChainIdToCaip)\n .includes(chainId);\n });\n\n // Only append L1 gas fees if all quotes are for either optimism or base\n if (!hasInvalidQuotes) {\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\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 );\n }\n\n return undefined;\n };\n\n readonly #appendSolanaFees = async (\n quotes: QuoteResponse[],\n ): Promise<(QuoteResponse & SolanaFees)[] | undefined> => {\n // Return early if some of the quotes are not for solana\n if (\n quotes.some(({ quote: { srcChainId } }) => !isSolanaChainId(srcChainId))\n ) {\n return undefined;\n }\n\n return await Promise.all(\n quotes.map(async (quoteResponse) => {\n const { trade } = quoteResponse;\n const selectedAccount = this.#getMultichainSelectedAccount();\n\n if (selectedAccount?.metadata?.snap?.id && typeof trade === 'string') {\n const { value: fees } = (await this.messagingSystem.call(\n 'SnapController:handleRequest',\n {\n // TODO fix these types\n snapId: selectedAccount.metadata.snap.id as never,\n origin: 'metamask',\n handler: 'onRpcRequest' as never,\n request: {\n method: 'getFeeForTransaction',\n params: {\n transaction: trade,\n scope: selectedAccount.options.scope,\n },\n },\n },\n )) as { value: string };\n\n return {\n ...quoteResponse,\n solanaFeesInLamports: fees,\n };\n }\n return quoteResponse;\n }),\n );\n };\n\n #getMultichainSelectedAccount() {\n return this.messagingSystem.call(\n 'AccountsController:getSelectedMultichainAccount',\n );\n }\n\n #getSelectedNetworkClientId() {\n const { selectedNetworkClientId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n return selectedNetworkClientId;\n }\n\n #getSelectedNetworkClient() {\n const selectedNetworkClientId = this.#getSelectedNetworkClientId();\n const networkClient = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n selectedNetworkClientId,\n );\n return networkClient;\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 Web3Provider(provider);\n const contract = new Contract(contractAddress, abiERC20, ethersProvider);\n const { address: walletAddress } =\n this.#getMultichainSelectedAccount() ?? {};\n const allowance: BigNumber = await contract.allowance(\n walletAddress,\n METABRIDGE_CHAIN_TO_ADDRESS_MAP[chainId],\n );\n return allowance.toString();\n };\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  import type { ChainId } from "@metamask/controller-utils";
2
2
  import type { NetworkClientId } from "@metamask/network-controller";
3
3
  import type { TransactionParams } from "@metamask/transaction-controller";
4
- import type { Hex } from "@metamask/utils";
4
+ import { type Hex } from "@metamask/utils";
5
5
  import { type BridgeClientId, BRIDGE_CONTROLLER_NAME } from "./constants/bridge.cjs";
6
6
  import type { GenericQuoteRequest } from "./types.cjs";
7
7
  import { type BridgeControllerState, type BridgeControllerMessenger, type FetchFunction } from "./types.cjs";
@@ -1 +1 @@
1
- {"version":3,"file":"bridge-controller.d.cts","sourceRoot":"","sources":["../src/bridge-controller.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,mCAAmC;AAE1D,OAAO,KAAK,EAAE,eAAe,EAAE,qCAAqC;AAIpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,yCAAyC;AAE1E,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAE3C,OAAO,EACL,KAAK,cAAc,EACnB,sBAAsB,EAKvB,+BAA2B;AAE5B,OAAO,KAAK,EAAE,mBAAmB,EAAc,oBAAgB;AAC/D,OAAO,EAIL,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,EAC9B,KAAK,aAAa,EAGnB,oBAAgB;AAoDjB,kEAAkE;AAClE,KAAK,kBAAkB,GAAG;IACxB,eAAe,EAAE,eAAe,CAAC;IACjC,mBAAmB,EAAE,mBAAmB,CAAC;CAC1C,CAAC;;;;;;;;;;;;;;;;AAEF,qBAAa,gBAAiB,SAAQ,sBACpC,OAAO,sBAAsB,EAC7B,qBAAqB,EACrB,yBAAyB,CAC1B;;gBAkBa,EACV,SAAS,EACT,KAAK,EACL,QAAQ,EACR,eAAe,EACf,OAAO,EACP,MAAM,GACP,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;QACvB,MAAM,CAAC,EAAE;YACP,sBAAsB,CAAC,EAAE,MAAM,CAAC;SACjC,CAAC;KACH;IAsCD,YAAY,iBAAwB,kBAAkB,mBAEpD;IAEF,8BAA8B,mBACZ,QAAQ,mBAAmB,CAAC,mBAsD5C;IA4BF,UAAU,aAsBR;IAEF,qBAAqB,sBAUnB;IA6MF;;;;;OAKG;IACH,uBAAuB,oBACJ,MAAM,WACd,GAAG,KACX,QAAQ,MAAM,CAAC,CAehB;CACH"}
1
+ {"version":3,"file":"bridge-controller.d.cts","sourceRoot":"","sources":["../src/bridge-controller.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,mCAAmC;AAE1D,OAAO,KAAK,EAAE,eAAe,EAAE,qCAAqC;AAEpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,yCAAyC;AAE1E,OAAO,EAAe,KAAK,GAAG,EAAE,wBAAwB;AAExD,OAAO,EACL,KAAK,cAAc,EACnB,sBAAsB,EAKvB,+BAA2B;AAG5B,OAAO,KAAK,EAAE,mBAAmB,EAAc,oBAAgB;AAC/D,OAAO,EAIL,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,EAC9B,KAAK,aAAa,EAGnB,oBAAgB;AA6DjB,kEAAkE;AAClE,KAAK,kBAAkB,GAAG;IACxB,eAAe,EAAE,eAAe,CAAC;IACjC,mBAAmB,EAAE,mBAAmB,CAAC;CAC1C,CAAC;;;;;;;;;;;;;;;;AAEF,qBAAa,gBAAiB,SAAQ,sBACpC,OAAO,sBAAsB,EAC7B,qBAAqB,EACrB,yBAAyB,CAC1B;;gBAkBa,EACV,SAAS,EACT,KAAK,EACL,QAAQ,EACR,eAAe,EACf,OAAO,EACP,MAAM,GACP,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;QACvB,MAAM,CAAC,EAAE;YACP,sBAAsB,CAAC,EAAE,MAAM,CAAC;SACjC,CAAC;KACH;IAsCD,YAAY,iBAAwB,kBAAkB,mBAEpD;IAEF,8BAA8B,mBACZ,QAAQ,mBAAmB,CAAC,mBA0D5C;IA+FF,UAAU,aAwBR;IAEF,qBAAqB,sBAUnB;IA8MF;;;;;OAKG;IACH,uBAAuB,oBACJ,MAAM,WACd,GAAG,KACX,QAAQ,MAAM,CAAC,CAehB;CACH"}
@@ -1,7 +1,7 @@
1
1
  import type { ChainId } from "@metamask/controller-utils";
2
2
  import type { NetworkClientId } from "@metamask/network-controller";
3
3
  import type { TransactionParams } from "@metamask/transaction-controller";
4
- import type { Hex } from "@metamask/utils";
4
+ import { type Hex } from "@metamask/utils";
5
5
  import { type BridgeClientId, BRIDGE_CONTROLLER_NAME } from "./constants/bridge.mjs";
6
6
  import type { GenericQuoteRequest } from "./types.mjs";
7
7
  import { type BridgeControllerState, type BridgeControllerMessenger, type FetchFunction } from "./types.mjs";
@@ -1 +1 @@
1
- {"version":3,"file":"bridge-controller.d.mts","sourceRoot":"","sources":["../src/bridge-controller.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,mCAAmC;AAE1D,OAAO,KAAK,EAAE,eAAe,EAAE,qCAAqC;AAIpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,yCAAyC;AAE1E,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAE3C,OAAO,EACL,KAAK,cAAc,EACnB,sBAAsB,EAKvB,+BAA2B;AAE5B,OAAO,KAAK,EAAE,mBAAmB,EAAc,oBAAgB;AAC/D,OAAO,EAIL,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,EAC9B,KAAK,aAAa,EAGnB,oBAAgB;AAoDjB,kEAAkE;AAClE,KAAK,kBAAkB,GAAG;IACxB,eAAe,EAAE,eAAe,CAAC;IACjC,mBAAmB,EAAE,mBAAmB,CAAC;CAC1C,CAAC;;;;;;;;;;;;;;;;AAEF,qBAAa,gBAAiB,SAAQ,sBACpC,OAAO,sBAAsB,EAC7B,qBAAqB,EACrB,yBAAyB,CAC1B;;gBAkBa,EACV,SAAS,EACT,KAAK,EACL,QAAQ,EACR,eAAe,EACf,OAAO,EACP,MAAM,GACP,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;QACvB,MAAM,CAAC,EAAE;YACP,sBAAsB,CAAC,EAAE,MAAM,CAAC;SACjC,CAAC;KACH;IAsCD,YAAY,iBAAwB,kBAAkB,mBAEpD;IAEF,8BAA8B,mBACZ,QAAQ,mBAAmB,CAAC,mBAsD5C;IA4BF,UAAU,aAsBR;IAEF,qBAAqB,sBAUnB;IA6MF;;;;;OAKG;IACH,uBAAuB,oBACJ,MAAM,WACd,GAAG,KACX,QAAQ,MAAM,CAAC,CAehB;CACH"}
1
+ {"version":3,"file":"bridge-controller.d.mts","sourceRoot":"","sources":["../src/bridge-controller.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,mCAAmC;AAE1D,OAAO,KAAK,EAAE,eAAe,EAAE,qCAAqC;AAEpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,yCAAyC;AAE1E,OAAO,EAAe,KAAK,GAAG,EAAE,wBAAwB;AAExD,OAAO,EACL,KAAK,cAAc,EACnB,sBAAsB,EAKvB,+BAA2B;AAG5B,OAAO,KAAK,EAAE,mBAAmB,EAAc,oBAAgB;AAC/D,OAAO,EAIL,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,EAC9B,KAAK,aAAa,EAGnB,oBAAgB;AA6DjB,kEAAkE;AAClE,KAAK,kBAAkB,GAAG;IACxB,eAAe,EAAE,eAAe,CAAC;IACjC,mBAAmB,EAAE,mBAAmB,CAAC;CAC1C,CAAC;;;;;;;;;;;;;;;;AAEF,qBAAa,gBAAiB,SAAQ,sBACpC,OAAO,sBAAsB,EAC7B,qBAAqB,EACrB,yBAAyB,CAC1B;;gBAkBa,EACV,SAAS,EACT,KAAK,EACL,QAAQ,EACR,eAAe,EACf,OAAO,EACP,MAAM,GACP,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;QACvB,MAAM,CAAC,EAAE;YACP,sBAAsB,CAAC,EAAE,MAAM,CAAC;SACjC,CAAC;KACH;IAsCD,YAAY,iBAAwB,kBAAkB,mBAEpD;IAEF,8BAA8B,mBACZ,QAAQ,mBAAmB,CAAC,mBA0D5C;IA+FF,UAAU,aAwBR;IAEF,qBAAqB,sBAUnB;IA8MF;;;;;OAKG;IACH,uBAAuB,oBACJ,MAAM,WACd,GAAG,KACX,QAAQ,MAAM,CAAC,CAehB;CACH"}
@@ -9,20 +9,21 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
9
9
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
10
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
11
  };
12
- var _BridgeController_instances, _BridgeController_abortController, _BridgeController_quotesFirstFetched, _BridgeController_clientId, _BridgeController_getLayer1GasFee, _BridgeController_fetchFn, _BridgeController_config, _BridgeController_hasSufficientBalance, _BridgeController_setIntervalLength, _BridgeController_fetchBridgeQuotes, _BridgeController_appendL1GasFees, _BridgeController_appendSolanaFees, _BridgeController_getMultichainSelectedAccount, _BridgeController_getSelectedNetworkClientId, _BridgeController_getSelectedNetworkClient;
12
+ var _BridgeController_instances, _BridgeController_abortController, _BridgeController_quotesFirstFetched, _BridgeController_clientId, _BridgeController_getLayer1GasFee, _BridgeController_fetchFn, _BridgeController_config, _BridgeController_fetchAssetExchangeRates, _BridgeController_hasSufficientBalance, _BridgeController_setIntervalLength, _BridgeController_fetchBridgeQuotes, _BridgeController_appendL1GasFees, _BridgeController_appendSolanaFees, _BridgeController_getMultichainSelectedAccount, _BridgeController_getSelectedNetworkClientId, _BridgeController_getSelectedNetworkClient;
13
13
  import { Contract } from "@ethersproject/contracts";
14
14
  import { Web3Provider } from "@ethersproject/providers";
15
15
  import { abiERC20 } from "@metamask/metamask-eth-abis";
16
16
  import { StaticIntervalPollingController } from "@metamask/polling-controller";
17
- import { HandlerType } from "@metamask/snaps-utils";
18
17
  import { numberToHex } from "@metamask/utils";
19
18
  import { BRIDGE_CONTROLLER_NAME, BRIDGE_PROD_API_BASE_URL, DEFAULT_BRIDGE_CONTROLLER_STATE, METABRIDGE_CHAIN_TO_ADDRESS_MAP, REFRESH_INTERVAL_MS } from "./constants/bridge.mjs";
20
19
  import { CHAIN_IDS } from "./constants/chains.mjs";
20
+ import { selectIsAssetExchangeRateInState } from "./selectors.mjs";
21
21
  import { BridgeFeatureFlagsKey, RequestStatus } from "./types.mjs";
22
+ import { getAssetIdsForToken, toExchangeRates } from "./utils/assets.mjs";
22
23
  import { hasSufficientBalance } from "./utils/balance.mjs";
23
24
  import { getDefaultBridgeControllerState, isSolanaChainId, sumHexes } from "./utils/bridge.mjs";
24
25
  import { formatAddressToCaipReference, formatChainIdToCaip, formatChainIdToHex } from "./utils/caip-formatters.mjs";
25
- import { fetchBridgeFeatureFlags, fetchBridgeQuotes } from "./utils/fetch.mjs";
26
+ import { fetchAssetPrices, fetchBridgeFeatureFlags, fetchBridgeQuotes } from "./utils/fetch.mjs";
26
27
  import { isValidQuoteRequest } from "./utils/quote.mjs";
27
28
  const metadata = {
28
29
  bridgeFeatureFlags: {
@@ -57,6 +58,10 @@ const metadata = {
57
58
  persist: false,
58
59
  anonymous: false,
59
60
  },
61
+ assetExchangeRates: {
62
+ persist: false,
63
+ anonymous: false,
64
+ },
60
65
  };
61
66
  const RESET_STATE_ABORT_MESSAGE = 'Reset controller state';
62
67
  export class BridgeController extends StaticIntervalPollingController() {
@@ -100,6 +105,7 @@ export class BridgeController extends StaticIntervalPollingController() {
100
105
  state.quotesInitialLoadTime =
101
106
  DEFAULT_BRIDGE_CONTROLLER_STATE.quotesInitialLoadTime;
102
107
  });
108
+ await __classPrivateFieldGet(this, _BridgeController_fetchAssetExchangeRates, "f").call(this, updatedQuoteRequest).catch((error) => console.warn('Failed to fetch asset exchange rates', error));
103
109
  if (isValidQuoteRequest(updatedQuoteRequest)) {
104
110
  __classPrivateFieldSet(this, _BridgeController_quotesFirstFetched, Date.now(), "f");
105
111
  const providerConfig = __classPrivateFieldGet(this, _BridgeController_instances, "m", _BridgeController_getSelectedNetworkClient).call(this)?.configuration;
@@ -131,6 +137,49 @@ export class BridgeController extends StaticIntervalPollingController() {
131
137
  });
132
138
  }
133
139
  };
140
+ /**
141
+ * Fetches the exchange rates for the assets in the quote request if they are not already in the state
142
+ * In addition to the selected tokens, this also fetches the native asset for the source and destination chains
143
+ *
144
+ * @param quoteRequest - The quote request
145
+ * @param quoteRequest.srcChainId - The source chain ID
146
+ * @param quoteRequest.srcTokenAddress - The source token address
147
+ * @param quoteRequest.destChainId - The destination chain ID
148
+ * @param quoteRequest.destTokenAddress - The destination token address
149
+ */
150
+ _BridgeController_fetchAssetExchangeRates.set(this, async ({ srcChainId, srcTokenAddress, destChainId, destTokenAddress, }) => {
151
+ const assetIds = new Set();
152
+ const exchangeRateSources = {
153
+ ...this.messagingSystem.call('MultichainAssetsRatesController:getState'),
154
+ ...this.messagingSystem.call('CurrencyRateController:getState'),
155
+ ...this.messagingSystem.call('TokenRatesController:getState'),
156
+ ...this.state,
157
+ };
158
+ if (srcTokenAddress &&
159
+ srcChainId &&
160
+ !selectIsAssetExchangeRateInState(exchangeRateSources, srcChainId, srcTokenAddress)) {
161
+ getAssetIdsForToken(srcTokenAddress, srcChainId).forEach(assetIds.add);
162
+ }
163
+ if (destTokenAddress &&
164
+ destChainId &&
165
+ !selectIsAssetExchangeRateInState(exchangeRateSources, destChainId, destTokenAddress)) {
166
+ getAssetIdsForToken(destTokenAddress, destChainId).forEach(assetIds.add);
167
+ }
168
+ const currency = this.messagingSystem.call('CurrencyRateController:getState').currentCurrency;
169
+ const pricesByAssetId = await fetchAssetPrices({
170
+ assetIds,
171
+ currencies: new Set([currency]),
172
+ clientId: __classPrivateFieldGet(this, _BridgeController_clientId, "f"),
173
+ fetchFn: __classPrivateFieldGet(this, _BridgeController_fetchFn, "f"),
174
+ });
175
+ const exchangeRates = toExchangeRates(currency, pricesByAssetId);
176
+ this.update((state) => {
177
+ state.assetExchangeRates = {
178
+ ...state.assetExchangeRates,
179
+ ...exchangeRates,
180
+ };
181
+ });
182
+ });
134
183
  _BridgeController_hasSufficientBalance.set(this, async (quoteRequest) => {
135
184
  const walletAddress = __classPrivateFieldGet(this, _BridgeController_instances, "m", _BridgeController_getMultichainSelectedAccount).call(this)?.address;
136
185
  const srcChainIdInHex = formatChainIdToHex(quoteRequest.srcChainId);
@@ -159,6 +208,8 @@ export class BridgeController extends StaticIntervalPollingController() {
159
208
  state.quoteFetchError = DEFAULT_BRIDGE_CONTROLLER_STATE.quoteFetchError;
160
209
  state.quotesRefreshCount =
161
210
  DEFAULT_BRIDGE_CONTROLLER_STATE.quotesRefreshCount;
211
+ state.assetExchangeRates =
212
+ DEFAULT_BRIDGE_CONTROLLER_STATE.assetExchangeRates;
162
213
  // Keep feature flags
163
214
  const originalFeatureFlags = state.bridgeFeatureFlags;
164
215
  state.bridgeFeatureFlags = originalFeatureFlags;
@@ -290,9 +341,10 @@ export class BridgeController extends StaticIntervalPollingController() {
290
341
  const selectedAccount = __classPrivateFieldGet(this, _BridgeController_instances, "m", _BridgeController_getMultichainSelectedAccount).call(this);
291
342
  if (selectedAccount?.metadata?.snap?.id && typeof trade === 'string') {
292
343
  const { value: fees } = (await this.messagingSystem.call('SnapController:handleRequest', {
344
+ // TODO fix these types
293
345
  snapId: selectedAccount.metadata.snap.id,
294
346
  origin: 'metamask',
295
- handler: HandlerType.OnRpcRequest,
347
+ handler: 'onRpcRequest',
296
348
  request: {
297
349
  method: 'getFeeForTransaction',
298
350
  params: {
@@ -339,7 +391,7 @@ export class BridgeController extends StaticIntervalPollingController() {
339
391
  this.messagingSystem.registerActionHandler(`${BRIDGE_CONTROLLER_NAME}:getBridgeERC20Allowance`, this.getBridgeERC20Allowance.bind(this));
340
392
  }
341
393
  }
342
- _BridgeController_abortController = new WeakMap(), _BridgeController_quotesFirstFetched = new WeakMap(), _BridgeController_clientId = new WeakMap(), _BridgeController_getLayer1GasFee = new WeakMap(), _BridgeController_fetchFn = new WeakMap(), _BridgeController_config = new WeakMap(), _BridgeController_hasSufficientBalance = new WeakMap(), _BridgeController_setIntervalLength = new WeakMap(), _BridgeController_fetchBridgeQuotes = new WeakMap(), _BridgeController_appendL1GasFees = new WeakMap(), _BridgeController_appendSolanaFees = new WeakMap(), _BridgeController_instances = new WeakSet(), _BridgeController_getMultichainSelectedAccount = function _BridgeController_getMultichainSelectedAccount() {
394
+ _BridgeController_abortController = new WeakMap(), _BridgeController_quotesFirstFetched = new WeakMap(), _BridgeController_clientId = new WeakMap(), _BridgeController_getLayer1GasFee = new WeakMap(), _BridgeController_fetchFn = new WeakMap(), _BridgeController_config = new WeakMap(), _BridgeController_fetchAssetExchangeRates = new WeakMap(), _BridgeController_hasSufficientBalance = new WeakMap(), _BridgeController_setIntervalLength = new WeakMap(), _BridgeController_fetchBridgeQuotes = new WeakMap(), _BridgeController_appendL1GasFees = new WeakMap(), _BridgeController_appendSolanaFees = new WeakMap(), _BridgeController_instances = new WeakSet(), _BridgeController_getMultichainSelectedAccount = function _BridgeController_getMultichainSelectedAccount() {
343
395
  return this.messagingSystem.call('AccountsController:getSelectedMultichainAccount');
344
396
  }, _BridgeController_getSelectedNetworkClientId = function _BridgeController_getSelectedNetworkClientId() {
345
397
  const { selectedNetworkClientId } = this.messagingSystem.call('NetworkController:getState');
@@ -1 +1 @@
1
- {"version":3,"file":"bridge-controller.mjs","sourceRoot":"","sources":["../src/bridge-controller.ts"],"names":[],"mappings":";;;;;;;;;;;;AACA,OAAO,EAAE,QAAQ,EAAE,iCAAiC;AACpD,OAAO,EAAE,YAAY,EAAE,iCAAiC;AAGxD,OAAO,EAAE,QAAQ,EAAE,oCAAoC;AAEvD,OAAO,EAAE,+BAA+B,EAAE,qCAAqC;AAE/E,OAAO,EAAE,WAAW,EAAE,8BAA8B;AAEpD,OAAO,EAAE,WAAW,EAAE,wBAAwB;AAG9C,OAAO,EAEL,sBAAsB,EACtB,wBAAwB,EACxB,+BAA+B,EAC/B,+BAA+B,EAC/B,mBAAmB,EACpB,+BAA2B;AAC5B,OAAO,EAAE,SAAS,EAAE,+BAA2B;AAE/C,OAAO,EAOL,qBAAqB,EACrB,aAAa,EACd,oBAAgB;AACjB,OAAO,EAAE,oBAAoB,EAAE,4BAAwB;AACvD,OAAO,EACL,+BAA+B,EAC/B,eAAe,EACf,QAAQ,EACT,2BAAuB;AACxB,OAAO,EACL,4BAA4B,EAC5B,mBAAmB,EACnB,kBAAkB,EACnB,oCAAgC;AACjC,OAAO,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,0BAAsB;AAC3E,OAAO,EAAE,mBAAmB,EAAE,0BAAsB;AAEpD,MAAM,QAAQ,GAAyC;IACrD,kBAAkB,EAAE;QAClB,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;KACjB;IACD,YAAY,EAAE;QACZ,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;KACjB;IACD,MAAM,EAAE;QACN,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;KACjB;IACD,qBAAqB,EAAE;QACrB,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;KACjB;IACD,iBAAiB,EAAE;QACjB,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;KACjB;IACD,mBAAmB,EAAE;QACnB,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;KACjB;IACD,eAAe,EAAE;QACf,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;KACjB;IACD,kBAAkB,EAAE;QAClB,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;KACjB;CACF,CAAC;AAEF,MAAM,yBAAyB,GAAG,wBAAwB,CAAC;AAQ3D,MAAM,OAAO,gBAAiB,SAAQ,+BAA+B,EAIpE;IAkBC,YAAY,EACV,SAAS,EACT,KAAK,EACL,QAAQ,EACR,eAAe,EACf,OAAO,EACP,MAAM,GAaP;QACC,KAAK,CAAC;YACJ,IAAI,EAAE,sBAAsB;YAC5B,QAAQ;YACR,SAAS;YACT,KAAK,EAAE;gBACL,GAAG,+BAA+B,EAAE;gBACpC,GAAG,KAAK;aACT;SACF,CAAC,CAAC;;QA7CL,oDAA8C;QAE9C,uDAAwC;QAE/B,6CAAkB;QAElB,oDAGa;QAEb,4CAAwB;QAExB,2CAEP;QA2DF,iBAAY,GAAG,KAAK,EAAE,YAAgC,EAAE,EAAE;YACxD,MAAM,uBAAA,IAAI,2CAAmB,MAAvB,IAAI,EAAoB,YAAY,CAAC,CAAC;QAC9C,CAAC,CAAC;QAEF,mCAA8B,GAAG,KAAK,EACpC,cAA4C,EAC5C,EAAE;YACF,IAAI,CAAC,cAAc,EAAE,CAAC;YACtB,uBAAA,IAAI,yCAAiB,EAAE,KAAK,CAAC,uBAAuB,CAAC,CAAC;YAEtD,MAAM,mBAAmB,GAAG;gBAC1B,GAAG,+BAA+B,CAAC,YAAY;gBAC/C,GAAG,cAAc;aAClB,CAAC;YAEF,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;gBACpB,KAAK,CAAC,YAAY,GAAG,mBAAmB,CAAC;gBACzC,KAAK,CAAC,MAAM,GAAG,+BAA+B,CAAC,MAAM,CAAC;gBACtD,KAAK,CAAC,iBAAiB;oBACrB,+BAA+B,CAAC,iBAAiB,CAAC;gBACpD,KAAK,CAAC,mBAAmB;oBACvB,+BAA+B,CAAC,mBAAmB,CAAC;gBACtD,KAAK,CAAC,eAAe,GAAG,+BAA+B,CAAC,eAAe,CAAC;gBACxE,KAAK,CAAC,kBAAkB;oBACtB,+BAA+B,CAAC,kBAAkB,CAAC;gBACrD,KAAK,CAAC,qBAAqB;oBACzB,+BAA+B,CAAC,qBAAqB,CAAC;YAC1D,CAAC,CAAC,CAAC;YAEH,IAAI,mBAAmB,CAAC,mBAAmB,CAAC,EAAE;gBAC5C,uBAAA,IAAI,wCAAuB,IAAI,CAAC,GAAG,EAAE,MAAA,CAAC;gBACtC,MAAM,cAAc,GAAG,uBAAA,IAAI,+EAA0B,MAA9B,IAAI,CAA4B,EAAE,aAAa,CAAC;gBAEvE,IAAI,eAAoC,CAAC;gBACzC,IAAI,eAAe,CAAC,mBAAmB,CAAC,UAAU,CAAC,EAAE;oBACnD,mEAAmE;oBACnE,eAAe,GAAG,cAAc,CAAC,eAAe,CAAC;iBAClD;qBAAM,IAAI,cAAc,EAAE,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,EAAE;oBACvD,yEAAyE;oBACzE,mIAAmI;oBACnI,eAAe,GAAG,IAAI,CAAC;iBACxB;qBAAM;oBACL,8DAA8D;oBAC9D,eAAe;wBACb,cAAc,CAAC,eAAe;4BAC9B,CAAC,CAAC,MAAM,uBAAA,IAAI,8CAAsB,MAA1B,IAAI,EAAuB,mBAAmB,CAAC,CAAC,CAAC;iBAC5D;gBAED,MAAM,eAAe,GAAG,uBAAA,IAAI,iFAA4B,MAAhC,IAAI,CAA8B,CAAC;gBAC3D,qEAAqE;gBACrE,uBAAA,IAAI,2CAAmB,MAAvB,IAAI,CAAqB,CAAC;gBAC1B,IAAI,CAAC,YAAY,CAAC;oBAChB,eAAe;oBACf,mBAAmB,EAAE;wBACnB,GAAG,mBAAmB;wBACtB,eAAe;qBAChB;iBACF,CAAC,CAAC;aACJ;QACH,CAAC,CAAC;QAEO,iDAAwB,KAAK,EACpC,YAAiC,EACjC,EAAE;YACF,MAAM,aAAa,GAAG,uBAAA,IAAI,mFAA8B,MAAlC,IAAI,CAAgC,EAAE,OAAO,CAAC;YACpE,MAAM,eAAe,GAAG,kBAAkB,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;YACpE,MAAM,QAAQ,GAAG,uBAAA,IAAI,+EAA0B,MAA9B,IAAI,CAA4B,EAAE,QAAQ,CAAC;YAC5D,MAAM,yBAAyB,GAAG,4BAA4B,CAC5D,YAAY,CAAC,eAAe,CAC7B,CAAC;YAEF,OAAO,CACL,QAAQ;gBACR,aAAa;gBACb,yBAAyB;gBACzB,YAAY,CAAC,cAAc;gBAC3B,eAAe;gBACf,CAAC,MAAM,oBAAoB,CACzB,QAAQ,EACR,aAAa,EACb,yBAAyB,EACzB,YAAY,CAAC,cAAc,EAC3B,eAAe,CAChB,CAAC,CACH,CAAC;QACJ,CAAC,EAAC;QAEF,eAAU,GAAG,GAAG,EAAE;YAChB,IAAI,CAAC,cAAc,EAAE,CAAC;YACtB,uBAAA,IAAI,yCAAiB,EAAE,KAAK,CAAC,yBAAyB,CAAC,CAAC;YAExD,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;gBACpB,gGAAgG;gBAChG,KAAK,CAAC,YAAY,GAAG,+BAA+B,CAAC,YAAY,CAAC;gBAClE,KAAK,CAAC,qBAAqB;oBACzB,+BAA+B,CAAC,qBAAqB,CAAC;gBACxD,KAAK,CAAC,MAAM,GAAG,+BAA+B,CAAC,MAAM,CAAC;gBACtD,KAAK,CAAC,iBAAiB;oBACrB,+BAA+B,CAAC,iBAAiB,CAAC;gBACpD,KAAK,CAAC,mBAAmB;oBACvB,+BAA+B,CAAC,mBAAmB,CAAC;gBACtD,KAAK,CAAC,eAAe,GAAG,+BAA+B,CAAC,eAAe,CAAC;gBACxE,KAAK,CAAC,kBAAkB;oBACtB,+BAA+B,CAAC,kBAAkB,CAAC;gBAErD,qBAAqB;gBACrB,MAAM,oBAAoB,GAAG,KAAK,CAAC,kBAAkB,CAAC;gBACtD,KAAK,CAAC,kBAAkB,GAAG,oBAAoB,CAAC;YAClD,CAAC,CAAC,CAAC;QACL,CAAC,CAAC;QAEF,0BAAqB,GAAG,KAAK,IAAI,EAAE;YACjC,MAAM,kBAAkB,GAAG,MAAM,uBAAuB,CACtD,uBAAA,IAAI,kCAAU,EACd,uBAAA,IAAI,iCAAS,EACb,uBAAA,IAAI,gCAAQ,CAAC,sBAAsB,IAAI,wBAAwB,CAChE,CAAC;YACF,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;gBACpB,KAAK,CAAC,kBAAkB,GAAG,kBAAkB,CAAC;YAChD,CAAC,CAAC,CAAC;YACH,uBAAA,IAAI,2CAAmB,MAAvB,IAAI,CAAqB,CAAC;QAC5B,CAAC,CAAC;QAEF;;WAEG;QACM,8CAAqB,GAAG,EAAE;YACjC,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC;YACvB,MAAM,EAAE,UAAU,EAAE,GAAG,KAAK,CAAC,YAAY,CAAC;YAC1C,MAAM,mBAAmB,GAAG,UAAU;gBACpC,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC,qBAAqB,CAAC,gBAAgB,CAAC,CAAC,MAAM,CACrE,mBAAmB,CAAC,UAAU,CAAC,CAChC,EAAE,WAAW;gBAChB,CAAC,CAAC,SAAS,CAAC;YACd,MAAM,kBAAkB,GACtB,KAAK,CAAC,kBAAkB,CAAC,qBAAqB,CAAC,gBAAgB,CAAC;iBAC7D,WAAW,CAAC;YACjB,IAAI,CAAC,iBAAiB,CAAC,mBAAmB,IAAI,kBAAkB,CAAC,CAAC;QACpE,CAAC,EAAC;QAEO,8CAAqB,KAAK,EAAE,EACnC,eAAe,EAAE,gBAAgB,EACjC,mBAAmB,GACA,EAAE,EAAE;YACvB,MAAM,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,GACrE,IAAI,CAAC,KAAK,CAAC;YACb,uBAAA,IAAI,yCAAiB,EAAE,KAAK,CAAC,mBAAmB,CAAC,CAAC;YAClD,uBAAA,IAAI,qCAAoB,IAAI,eAAe,EAAE,MAAA,CAAC;YAE9C,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;gBACpB,KAAK,CAAC,mBAAmB,GAAG,aAAa,CAAC,OAAO,CAAC;gBAClD,KAAK,CAAC,YAAY,GAAG,mBAAmB,CAAC;gBACzC,KAAK,CAAC,eAAe,GAAG,+BAA+B,CAAC,eAAe,CAAC;YAC1E,CAAC,CAAC,CAAC;YAEH,IAAI;gBACF,MAAM,MAAM,GAAG,MAAM,iBAAiB,CACpC,mBAAmB;gBACnB,0FAA0F;gBAC1F,oCAAoC;gBACpC,2CAA2C;gBAC3C,oEAAoE;gBACpE,uBAAA,IAAI,yCAAkB,CAAC,MAAqB,EAC5C,uBAAA,IAAI,kCAAU,EACd,uBAAA,IAAI,iCAAS,EACb,uBAAA,IAAI,gCAAQ,CAAC,sBAAsB,IAAI,wBAAwB,CAChE,CAAC;gBAEF,MAAM,mBAAmB,GAAG,MAAM,uBAAA,IAAI,yCAAiB,MAArB,IAAI,EAAkB,MAAM,CAAC,CAAC;gBAChE,MAAM,oBAAoB,GAAG,MAAM,uBAAA,IAAI,0CAAkB,MAAtB,IAAI,EAAmB,MAAM,CAAC,CAAC;gBAElE,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;oBACpB,KAAK,CAAC,MAAM,GAAG,mBAAmB,IAAI,oBAAoB,IAAI,MAAM,CAAC;oBACrE,KAAK,CAAC,mBAAmB,GAAG,aAAa,CAAC,OAAO,CAAC;gBACpD,CAAC,CAAC,CAAC;aACJ;YAAC,OAAO,KAAK,EAAE;gBACd,MAAM,YAAY,GAAI,KAAe,CAAC,IAAI,KAAK,YAAY,CAAC;gBAC5D,MAAM,mBAAmB,GAAG,KAAK,KAAK,yBAAyB,CAAC;gBAChE,IAAI,mBAAmB,IAAI,YAAY,EAAE;oBACvC,OAAO;iBACR;gBAED,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;oBACpB,KAAK,CAAC,eAAe;wBACnB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;oBAC3D,KAAK,CAAC,mBAAmB,GAAG,aAAa,CAAC,KAAK,CAAC;oBAChD,KAAK,CAAC,MAAM,GAAG,+BAA+B,CAAC,MAAM,CAAC;gBACxD,CAAC,CAAC,CAAC;gBACH,OAAO,CAAC,GAAG,CAAC,+BAA+B,EAAE,KAAK,CAAC,CAAC;aACrD;oBAAS;gBACR,MAAM,EAAE,eAAe,EAAE,GACvB,kBAAkB,CAAC,qBAAqB,CAAC,gBAAgB,CAAC,CAAC;gBAE7D,MAAM,yBAAyB,GAAG,kBAAkB,GAAG,CAAC,CAAC;gBACzD,mEAAmE;gBACnE,IACE,mBAAmB,CAAC,eAAe;oBACnC,CAAC,CAAC,mBAAmB,CAAC,eAAe;wBACnC,yBAAyB,IAAI,eAAe,CAAC,EAC/C;oBACA,IAAI,CAAC,cAAc,EAAE,CAAC;iBACvB;gBAED,8BAA8B;gBAC9B,MAAM,iBAAiB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBACrC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;oBACpB,KAAK,CAAC,qBAAqB;wBACzB,yBAAyB,KAAK,CAAC,IAAI,uBAAA,IAAI,4CAAoB;4BACzD,CAAC,CAAC,iBAAiB,GAAG,uBAAA,IAAI,4CAAoB;4BAC9C,CAAC,CAAC,qBAAqB,CAAC;oBAC5B,KAAK,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;oBAC5C,KAAK,CAAC,kBAAkB,GAAG,yBAAyB,CAAC;gBACvD,CAAC,CAAC,CAAC;aACJ;QACH,CAAC,EAAC;QAEO,4CAAmB,KAAK,EAC/B,MAAuB,EAC6B,EAAE;YACtD,oEAAoE;YACpE,MAAM,gBAAgB,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE;gBACjD,MAAM,OAAO,GAAG,mBAAmB,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;gBACtD,OAAO,CAAC,CAAC,SAAS,CAAC,QAAQ,EAAE,SAAS,CAAC,IAAI,CAAC;qBACzC,GAAG,CAAC,mBAAmB,CAAC;qBACxB,QAAQ,CAAC,OAAO,CAAC,CAAC;YACvB,CAAC,CAAC,CAAC;YAEH,wEAAwE;YACxE,IAAI,CAAC,gBAAgB,EAAE;gBACrB,OAAO,MAAM,OAAO,CAAC,GAAG,CACtB,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE;oBACjC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,aAAa,CAAC;oBACjD,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,CAAC,UAAU,CAAY,CAAC;oBAEzD,MAAM,WAAW,GAAG,CAAC,MAAc,EAAE,EAAE,CAAC,CAAC;wBACvC,IAAI,EAAE,MAAM,CAAC,IAAI;wBACjB,EAAE,EAAE,MAAM,CAAC,EAAE;wBACb,KAAK,EAAE,MAAM,CAAC,KAAK;wBACnB,IAAI,EAAE,MAAM,CAAC,IAAI;wBACjB,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE;qBACtC,CAAC,CAAC;oBACH,MAAM,iBAAiB,GAAG,QAAQ;wBAChC,CAAC,CAAC,MAAM,uBAAA,IAAI,yCAAiB,MAArB,IAAI,EAAkB;4BAC1B,iBAAiB,EAAE,WAAW,CAAC,QAAQ,CAAC;4BACxC,OAAO;yBACR,CAAC;wBACJ,CAAC,CAAC,GAAG,CAAC;oBACR,MAAM,cAAc,GAAG,MAAM,uBAAA,IAAI,yCAAiB,MAArB,IAAI,EAAkB;wBACjD,iBAAiB,EAAE,WAAW,CAAC,KAAK,CAAC;wBACrC,OAAO;qBACR,CAAC,CAAC;oBACH,OAAO;wBACL,GAAG,aAAa;wBAChB,iBAAiB,EAAE,QAAQ,CAAC,iBAAiB,EAAE,cAAc,CAAC;qBAC/D,CAAC;gBACJ,CAAC,CAAC,CACH,CAAC;aACH;YAED,OAAO,SAAS,CAAC;QACnB,CAAC,EAAC;QAEO,6CAAoB,KAAK,EAChC,MAAuB,EAC8B,EAAE;YACvD,wDAAwD;YACxD,IACE,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,EACxE;gBACA,OAAO,SAAS,CAAC;aAClB;YAED,OAAO,MAAM,OAAO,CAAC,GAAG,CACtB,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE;gBACjC,MAAM,EAAE,KAAK,EAAE,GAAG,aAAa,CAAC;gBAChC,MAAM,eAAe,GAAG,uBAAA,IAAI,mFAA8B,MAAlC,IAAI,CAAgC,CAAC;gBAE7D,IAAI,eAAe,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;oBACpE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,IAAI,CAAC,eAAe,CAAC,IAAI,CACtD,8BAA8B,EAC9B;wBACE,MAAM,EAAE,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAY;wBAClD,MAAM,EAAE,UAAU;wBAClB,OAAO,EAAE,WAAW,CAAC,YAAY;wBACjC,OAAO,EAAE;4BACP,MAAM,EAAE,sBAAsB;4BAC9B,MAAM,EAAE;gCACN,WAAW,EAAE,KAAK;gCAClB,KAAK,EAAE,eAAe,CAAC,OAAO,CAAC,KAAK;6BACrC;yBACF;qBACF,CACF,CAAsB,CAAC;oBAExB,OAAO;wBACL,GAAG,aAAa;wBAChB,oBAAoB,EAAE,IAAI;qBAC3B,CAAC;iBACH;gBACD,OAAO,aAAa,CAAC;YACvB,CAAC,CAAC,CACH,CAAC;QACJ,CAAC,EAAC;QAwBF;;;;;WAKG;QACH,4BAAuB,GAAG,KAAK,EAC7B,eAAuB,EACvB,OAAY,EACK,EAAE;YACnB,MAAM,QAAQ,GAAG,uBAAA,IAAI,+EAA0B,MAA9B,IAAI,CAA4B,EAAE,QAAQ,CAAC;YAC5D,IAAI,CAAC,QAAQ,EAAE;gBACb,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;aACtC;YAED,MAAM,cAAc,GAAG,IAAI,YAAY,CAAC,QAAQ,CAAC,CAAC;YAClD,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,eAAe,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAC;YACzE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,GAC9B,uBAAA,IAAI,mFAA8B,MAAlC,IAAI,CAAgC,IAAI,EAAE,CAAC;YAC7C,MAAM,SAAS,GAAc,MAAM,QAAQ,CAAC,SAAS,CACnD,aAAa,EACb,+BAA+B,CAAC,OAAO,CAAC,CACzC,CAAC;YACF,OAAO,SAAS,CAAC,QAAQ,EAAE,CAAC;QAC9B,CAAC,CAAC;QAzXA,IAAI,CAAC,iBAAiB,CAAC,mBAAmB,CAAC,CAAC;QAE5C,uBAAA,IAAI,qCAAoB,IAAI,eAAe,EAAE,MAAA,CAAC;QAC9C,uBAAA,IAAI,qCAAoB,eAAe,MAAA,CAAC;QACxC,uBAAA,IAAI,8BAAa,QAAQ,MAAA,CAAC;QAC1B,uBAAA,IAAI,6BAAY,OAAO,MAAA,CAAC;QACxB,uBAAA,IAAI,4BAAW,MAAM,IAAI,EAAE,MAAA,CAAC;QAE5B,2BAA2B;QAC3B,IAAI,CAAC,eAAe,CAAC,qBAAqB,CACxC,GAAG,sBAAsB,wBAAwB,EACjD,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CACtC,CAAC;QACF,IAAI,CAAC,eAAe,CAAC,qBAAqB,CACxC,GAAG,sBAAsB,iCAAiC,EAC1D,IAAI,CAAC,8BAA8B,CAAC,IAAI,CAAC,IAAI,CAAC,CAC/C,CAAC;QACF,IAAI,CAAC,eAAe,CAAC,qBAAqB,CACxC,GAAG,sBAAsB,aAAa,EACtC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAC3B,CAAC;QACF,IAAI,CAAC,eAAe,CAAC,qBAAqB,CACxC,GAAG,sBAAsB,0BAA0B,EACnD,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC,CACxC,CAAC;IACJ,CAAC;CAiWF;;IA9CG,OAAO,IAAI,CAAC,eAAe,CAAC,IAAI,CAC9B,iDAAiD,CAClD,CAAC;AACJ,CAAC;IAGC,MAAM,EAAE,uBAAuB,EAAE,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAC3D,4BAA4B,CAC7B,CAAC;IACF,OAAO,uBAAuB,CAAC;AACjC,CAAC;IAGC,MAAM,uBAAuB,GAAG,uBAAA,IAAI,iFAA4B,MAAhC,IAAI,CAA8B,CAAC;IACnE,MAAM,aAAa,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAC7C,wCAAwC,EACxC,uBAAuB,CACxB,CAAC;IACF,OAAO,aAAa,CAAC;AACvB,CAAC","sourcesContent":["import type { BigNumber } from '@ethersproject/bignumber';\nimport { Contract } from '@ethersproject/contracts';\nimport { Web3Provider } from '@ethersproject/providers';\nimport 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 SnapId } from '@metamask/snaps-sdk';\nimport { HandlerType } from '@metamask/snaps-utils';\nimport type { TransactionParams } from '@metamask/transaction-controller';\nimport { numberToHex } from '@metamask/utils';\nimport type { Hex } from '@metamask/utils';\n\nimport {\n type BridgeClientId,\n BRIDGE_CONTROLLER_NAME,\n BRIDGE_PROD_API_BASE_URL,\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 type { GenericQuoteRequest, SolanaFees } from './types';\nimport {\n type L1GasFees,\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 {\n getDefaultBridgeControllerState,\n isSolanaChainId,\n sumHexes,\n} from './utils/bridge';\nimport {\n formatAddressToCaipReference,\n formatChainIdToCaip,\n formatChainIdToHex,\n} from './utils/caip-formatters';\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: GenericQuoteRequest;\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 readonly #config: {\n customBridgeApiBaseUrl?: string;\n };\n\n constructor({\n messenger,\n state,\n clientId,\n getLayer1GasFee,\n fetchFn,\n config,\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 config?: {\n customBridgeApiBaseUrl?: string;\n };\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 this.#config = config ?? {};\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<GenericQuoteRequest>,\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 providerConfig = this.#getSelectedNetworkClient()?.configuration;\n\n let insufficientBal: boolean | undefined;\n if (isSolanaChainId(updatedQuoteRequest.srcChainId)) {\n // If the source chain is not an EVM network, use value from params\n insufficientBal = paramsToUpdate.insufficientBal;\n } else if (providerConfig?.rpcUrl?.includes('tenderly')) {\n // If the rpcUrl is a tenderly fork (e2e tests), set insufficientBal=true\n // The bridge-api filters out quotes if the balance on mainnet is insufficient so this override allows quotes to always be returned\n insufficientBal = true;\n } else {\n // Otherwise query the src token balance from the RPC provider\n insufficientBal =\n paramsToUpdate.insufficientBal ??\n !(await this.#hasSufficientBalance(updatedQuoteRequest));\n }\n\n const networkClientId = this.#getSelectedNetworkClientId();\n // Set refresh rate based on the source chain before starting polling\n this.#setIntervalLength();\n this.startPolling({\n networkClientId,\n updatedQuoteRequest: {\n ...updatedQuoteRequest,\n insufficientBal,\n },\n });\n }\n };\n\n readonly #hasSufficientBalance = async (\n quoteRequest: GenericQuoteRequest,\n ) => {\n const walletAddress = this.#getMultichainSelectedAccount()?.address;\n const srcChainIdInHex = formatChainIdToHex(quoteRequest.srcChainId);\n const provider = this.#getSelectedNetworkClient()?.provider;\n const normalizedSrcTokenAddress = formatAddressToCaipReference(\n quoteRequest.srcTokenAddress,\n );\n\n return (\n provider &&\n walletAddress &&\n normalizedSrcTokenAddress &&\n quoteRequest.srcTokenAmount &&\n srcChainIdInHex &&\n (await hasSufficientBalance(\n provider,\n walletAddress,\n normalizedSrcTokenAddress,\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 this.#config.customBridgeApiBaseUrl ?? BRIDGE_PROD_API_BASE_URL,\n );\n this.update((state) => {\n state.bridgeFeatureFlags = bridgeFeatureFlags;\n });\n this.#setIntervalLength();\n };\n\n /**\n * Sets the interval length based on the source chain\n */\n readonly #setIntervalLength = () => {\n const { state } = this;\n const { srcChainId } = state.quoteRequest;\n const refreshRateOverride = srcChainId\n ? state.bridgeFeatureFlags[BridgeFeatureFlagsKey.EXTENSION_CONFIG].chains[\n formatChainIdToCaip(srcChainId)\n ]?.refreshRate\n : undefined;\n const defaultRefreshRate =\n state.bridgeFeatureFlags[BridgeFeatureFlagsKey.EXTENSION_CONFIG]\n .refreshRate;\n this.setIntervalLength(refreshRateOverride ?? defaultRefreshRate);\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\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 this.#config.customBridgeApiBaseUrl ?? BRIDGE_PROD_API_BASE_URL,\n );\n\n const quotesWithL1GasFees = await this.#appendL1GasFees(quotes);\n const quotesWithSolanaFees = await this.#appendSolanaFees(quotes);\n\n this.update((state) => {\n state.quotes = quotesWithL1GasFees ?? quotesWithSolanaFees ?? quotes;\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 state.quotes = DEFAULT_BRIDGE_CONTROLLER_STATE.quotes;\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)[] | undefined> => {\n // Indicates whether some of the quotes are not for optimism or base\n const hasInvalidQuotes = quotes.some(({ quote }) => {\n const chainId = formatChainIdToCaip(quote.srcChainId);\n return ![CHAIN_IDS.OPTIMISM, CHAIN_IDS.BASE]\n .map(formatChainIdToCaip)\n .includes(chainId);\n });\n\n // Only append L1 gas fees if all quotes are for either optimism or base\n if (!hasInvalidQuotes) {\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\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 );\n }\n\n return undefined;\n };\n\n readonly #appendSolanaFees = async (\n quotes: QuoteResponse[],\n ): Promise<(QuoteResponse & SolanaFees)[] | undefined> => {\n // Return early if some of the quotes are not for solana\n if (\n quotes.some(({ quote: { srcChainId } }) => !isSolanaChainId(srcChainId))\n ) {\n return undefined;\n }\n\n return await Promise.all(\n quotes.map(async (quoteResponse) => {\n const { trade } = quoteResponse;\n const selectedAccount = this.#getMultichainSelectedAccount();\n\n if (selectedAccount?.metadata?.snap?.id && typeof trade === 'string') {\n const { value: fees } = (await this.messagingSystem.call(\n 'SnapController:handleRequest',\n {\n snapId: selectedAccount.metadata.snap.id as SnapId,\n origin: 'metamask',\n handler: HandlerType.OnRpcRequest,\n request: {\n method: 'getFeeForTransaction',\n params: {\n transaction: trade,\n scope: selectedAccount.options.scope,\n },\n },\n },\n )) as { value: string };\n\n return {\n ...quoteResponse,\n solanaFeesInLamports: fees,\n };\n }\n return quoteResponse;\n }),\n );\n };\n\n #getMultichainSelectedAccount() {\n return this.messagingSystem.call(\n 'AccountsController:getSelectedMultichainAccount',\n );\n }\n\n #getSelectedNetworkClientId() {\n const { selectedNetworkClientId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n return selectedNetworkClientId;\n }\n\n #getSelectedNetworkClient() {\n const selectedNetworkClientId = this.#getSelectedNetworkClientId();\n const networkClient = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n selectedNetworkClientId,\n );\n return networkClient;\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 Web3Provider(provider);\n const contract = new Contract(contractAddress, abiERC20, ethersProvider);\n const { address: walletAddress } =\n this.#getMultichainSelectedAccount() ?? {};\n const allowance: BigNumber = 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.mjs","sourceRoot":"","sources":["../src/bridge-controller.ts"],"names":[],"mappings":";;;;;;;;;;;;AACA,OAAO,EAAE,QAAQ,EAAE,iCAAiC;AACpD,OAAO,EAAE,YAAY,EAAE,iCAAiC;AAGxD,OAAO,EAAE,QAAQ,EAAE,oCAAoC;AAEvD,OAAO,EAAE,+BAA+B,EAAE,qCAAqC;AAG/E,OAAO,EAAE,WAAW,EAAY,wBAAwB;AAExD,OAAO,EAEL,sBAAsB,EACtB,wBAAwB,EACxB,+BAA+B,EAC/B,+BAA+B,EAC/B,mBAAmB,EACpB,+BAA2B;AAC5B,OAAO,EAAE,SAAS,EAAE,+BAA2B;AAC/C,OAAO,EAAE,gCAAgC,EAAE,wBAAoB;AAE/D,OAAO,EAOL,qBAAqB,EACrB,aAAa,EACd,oBAAgB;AACjB,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,2BAAuB;AACtE,OAAO,EAAE,oBAAoB,EAAE,4BAAwB;AACvD,OAAO,EACL,+BAA+B,EAC/B,eAAe,EACf,QAAQ,EACT,2BAAuB;AACxB,OAAO,EACL,4BAA4B,EAC5B,mBAAmB,EACnB,kBAAkB,EACnB,oCAAgC;AACjC,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,iBAAiB,EAClB,0BAAsB;AACvB,OAAO,EAAE,mBAAmB,EAAE,0BAAsB;AAEpD,MAAM,QAAQ,GAAyC;IACrD,kBAAkB,EAAE;QAClB,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;KACjB;IACD,YAAY,EAAE;QACZ,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;KACjB;IACD,MAAM,EAAE;QACN,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;KACjB;IACD,qBAAqB,EAAE;QACrB,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;KACjB;IACD,iBAAiB,EAAE;QACjB,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;KACjB;IACD,mBAAmB,EAAE;QACnB,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;KACjB;IACD,eAAe,EAAE;QACf,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;KACjB;IACD,kBAAkB,EAAE;QAClB,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;KACjB;IACD,kBAAkB,EAAE;QAClB,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;KACjB;CACF,CAAC;AAEF,MAAM,yBAAyB,GAAG,wBAAwB,CAAC;AAQ3D,MAAM,OAAO,gBAAiB,SAAQ,+BAA+B,EAIpE;IAkBC,YAAY,EACV,SAAS,EACT,KAAK,EACL,QAAQ,EACR,eAAe,EACf,OAAO,EACP,MAAM,GAaP;QACC,KAAK,CAAC;YACJ,IAAI,EAAE,sBAAsB;YAC5B,QAAQ;YACR,SAAS;YACT,KAAK,EAAE;gBACL,GAAG,+BAA+B,EAAE;gBACpC,GAAG,KAAK;aACT;SACF,CAAC,CAAC;;QA7CL,oDAA8C;QAE9C,uDAAwC;QAE/B,6CAAkB;QAElB,oDAGa;QAEb,4CAAwB;QAExB,2CAEP;QA2DF,iBAAY,GAAG,KAAK,EAAE,YAAgC,EAAE,EAAE;YACxD,MAAM,uBAAA,IAAI,2CAAmB,MAAvB,IAAI,EAAoB,YAAY,CAAC,CAAC;QAC9C,CAAC,CAAC;QAEF,mCAA8B,GAAG,KAAK,EACpC,cAA4C,EAC5C,EAAE;YACF,IAAI,CAAC,cAAc,EAAE,CAAC;YACtB,uBAAA,IAAI,yCAAiB,EAAE,KAAK,CAAC,uBAAuB,CAAC,CAAC;YAEtD,MAAM,mBAAmB,GAAG;gBAC1B,GAAG,+BAA+B,CAAC,YAAY;gBAC/C,GAAG,cAAc;aAClB,CAAC;YAEF,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;gBACpB,KAAK,CAAC,YAAY,GAAG,mBAAmB,CAAC;gBACzC,KAAK,CAAC,MAAM,GAAG,+BAA+B,CAAC,MAAM,CAAC;gBACtD,KAAK,CAAC,iBAAiB;oBACrB,+BAA+B,CAAC,iBAAiB,CAAC;gBACpD,KAAK,CAAC,mBAAmB;oBACvB,+BAA+B,CAAC,mBAAmB,CAAC;gBACtD,KAAK,CAAC,eAAe,GAAG,+BAA+B,CAAC,eAAe,CAAC;gBACxE,KAAK,CAAC,kBAAkB;oBACtB,+BAA+B,CAAC,kBAAkB,CAAC;gBACrD,KAAK,CAAC,qBAAqB;oBACzB,+BAA+B,CAAC,qBAAqB,CAAC;YAC1D,CAAC,CAAC,CAAC;YAEH,MAAM,uBAAA,IAAI,iDAAyB,MAA7B,IAAI,EAA0B,mBAAmB,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CACvE,OAAO,CAAC,IAAI,CAAC,sCAAsC,EAAE,KAAK,CAAC,CAC5D,CAAC;YAEF,IAAI,mBAAmB,CAAC,mBAAmB,CAAC,EAAE;gBAC5C,uBAAA,IAAI,wCAAuB,IAAI,CAAC,GAAG,EAAE,MAAA,CAAC;gBACtC,MAAM,cAAc,GAAG,uBAAA,IAAI,+EAA0B,MAA9B,IAAI,CAA4B,EAAE,aAAa,CAAC;gBAEvE,IAAI,eAAoC,CAAC;gBACzC,IAAI,eAAe,CAAC,mBAAmB,CAAC,UAAU,CAAC,EAAE;oBACnD,mEAAmE;oBACnE,eAAe,GAAG,cAAc,CAAC,eAAe,CAAC;iBAClD;qBAAM,IAAI,cAAc,EAAE,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,EAAE;oBACvD,yEAAyE;oBACzE,mIAAmI;oBACnI,eAAe,GAAG,IAAI,CAAC;iBACxB;qBAAM;oBACL,8DAA8D;oBAC9D,eAAe;wBACb,cAAc,CAAC,eAAe;4BAC9B,CAAC,CAAC,MAAM,uBAAA,IAAI,8CAAsB,MAA1B,IAAI,EAAuB,mBAAmB,CAAC,CAAC,CAAC;iBAC5D;gBAED,MAAM,eAAe,GAAG,uBAAA,IAAI,iFAA4B,MAAhC,IAAI,CAA8B,CAAC;gBAC3D,qEAAqE;gBACrE,uBAAA,IAAI,2CAAmB,MAAvB,IAAI,CAAqB,CAAC;gBAC1B,IAAI,CAAC,YAAY,CAAC;oBAChB,eAAe;oBACf,mBAAmB,EAAE;wBACnB,GAAG,mBAAmB;wBACtB,eAAe;qBAChB;iBACF,CAAC,CAAC;aACJ;QACH,CAAC,CAAC;QAEF;;;;;;;;;WASG;QACM,oDAA2B,KAAK,EAAE,EACzC,UAAU,EACV,eAAe,EACf,WAAW,EACX,gBAAgB,GACa,EAAE,EAAE;YACjC,MAAM,QAAQ,GAAuB,IAAI,GAAG,EAAE,CAAC;YAE/C,MAAM,mBAAmB,GAAG;gBAC1B,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,0CAA0C,CAAC;gBACxE,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,iCAAiC,CAAC;gBAC/D,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,+BAA+B,CAAC;gBAC7D,GAAG,IAAI,CAAC,KAAK;aACd,CAAC;YAEF,IACE,eAAe;gBACf,UAAU;gBACV,CAAC,gCAAgC,CAC/B,mBAAmB,EACnB,UAAU,EACV,eAAe,CAChB,EACD;gBACA,mBAAmB,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;aACxE;YACD,IACE,gBAAgB;gBAChB,WAAW;gBACX,CAAC,gCAAgC,CAC/B,mBAAmB,EACnB,WAAW,EACX,gBAAgB,CACjB,EACD;gBACA,mBAAmB,CAAC,gBAAgB,EAAE,WAAW,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;aAC1E;YAED,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CACxC,iCAAiC,CAClC,CAAC,eAAe,CAAC;YAElB,MAAM,eAAe,GAAG,MAAM,gBAAgB,CAAC;gBAC7C,QAAQ;gBACR,UAAU,EAAE,IAAI,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;gBAC/B,QAAQ,EAAE,uBAAA,IAAI,kCAAU;gBACxB,OAAO,EAAE,uBAAA,IAAI,iCAAS;aACvB,CAAC,CAAC;YACH,MAAM,aAAa,GAAG,eAAe,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;YACjE,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;gBACpB,KAAK,CAAC,kBAAkB,GAAG;oBACzB,GAAG,KAAK,CAAC,kBAAkB;oBAC3B,GAAG,aAAa;iBACjB,CAAC;YACJ,CAAC,CAAC,CAAC;QACL,CAAC,EAAC;QAEO,iDAAwB,KAAK,EACpC,YAAiC,EACjC,EAAE;YACF,MAAM,aAAa,GAAG,uBAAA,IAAI,mFAA8B,MAAlC,IAAI,CAAgC,EAAE,OAAO,CAAC;YACpE,MAAM,eAAe,GAAG,kBAAkB,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;YACpE,MAAM,QAAQ,GAAG,uBAAA,IAAI,+EAA0B,MAA9B,IAAI,CAA4B,EAAE,QAAQ,CAAC;YAC5D,MAAM,yBAAyB,GAAG,4BAA4B,CAC5D,YAAY,CAAC,eAAe,CAC7B,CAAC;YAEF,OAAO,CACL,QAAQ;gBACR,aAAa;gBACb,yBAAyB;gBACzB,YAAY,CAAC,cAAc;gBAC3B,eAAe;gBACf,CAAC,MAAM,oBAAoB,CACzB,QAAQ,EACR,aAAa,EACb,yBAAyB,EACzB,YAAY,CAAC,cAAc,EAC3B,eAAe,CAChB,CAAC,CACH,CAAC;QACJ,CAAC,EAAC;QAEF,eAAU,GAAG,GAAG,EAAE;YAChB,IAAI,CAAC,cAAc,EAAE,CAAC;YACtB,uBAAA,IAAI,yCAAiB,EAAE,KAAK,CAAC,yBAAyB,CAAC,CAAC;YAExD,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;gBACpB,gGAAgG;gBAChG,KAAK,CAAC,YAAY,GAAG,+BAA+B,CAAC,YAAY,CAAC;gBAClE,KAAK,CAAC,qBAAqB;oBACzB,+BAA+B,CAAC,qBAAqB,CAAC;gBACxD,KAAK,CAAC,MAAM,GAAG,+BAA+B,CAAC,MAAM,CAAC;gBACtD,KAAK,CAAC,iBAAiB;oBACrB,+BAA+B,CAAC,iBAAiB,CAAC;gBACpD,KAAK,CAAC,mBAAmB;oBACvB,+BAA+B,CAAC,mBAAmB,CAAC;gBACtD,KAAK,CAAC,eAAe,GAAG,+BAA+B,CAAC,eAAe,CAAC;gBACxE,KAAK,CAAC,kBAAkB;oBACtB,+BAA+B,CAAC,kBAAkB,CAAC;gBACrD,KAAK,CAAC,kBAAkB;oBACtB,+BAA+B,CAAC,kBAAkB,CAAC;gBAErD,qBAAqB;gBACrB,MAAM,oBAAoB,GAAG,KAAK,CAAC,kBAAkB,CAAC;gBACtD,KAAK,CAAC,kBAAkB,GAAG,oBAAoB,CAAC;YAClD,CAAC,CAAC,CAAC;QACL,CAAC,CAAC;QAEF,0BAAqB,GAAG,KAAK,IAAI,EAAE;YACjC,MAAM,kBAAkB,GAAG,MAAM,uBAAuB,CACtD,uBAAA,IAAI,kCAAU,EACd,uBAAA,IAAI,iCAAS,EACb,uBAAA,IAAI,gCAAQ,CAAC,sBAAsB,IAAI,wBAAwB,CAChE,CAAC;YACF,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;gBACpB,KAAK,CAAC,kBAAkB,GAAG,kBAAkB,CAAC;YAChD,CAAC,CAAC,CAAC;YACH,uBAAA,IAAI,2CAAmB,MAAvB,IAAI,CAAqB,CAAC;QAC5B,CAAC,CAAC;QAEF;;WAEG;QACM,8CAAqB,GAAG,EAAE;YACjC,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC;YACvB,MAAM,EAAE,UAAU,EAAE,GAAG,KAAK,CAAC,YAAY,CAAC;YAC1C,MAAM,mBAAmB,GAAG,UAAU;gBACpC,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC,qBAAqB,CAAC,gBAAgB,CAAC,CAAC,MAAM,CACrE,mBAAmB,CAAC,UAAU,CAAC,CAChC,EAAE,WAAW;gBAChB,CAAC,CAAC,SAAS,CAAC;YACd,MAAM,kBAAkB,GACtB,KAAK,CAAC,kBAAkB,CAAC,qBAAqB,CAAC,gBAAgB,CAAC;iBAC7D,WAAW,CAAC;YACjB,IAAI,CAAC,iBAAiB,CAAC,mBAAmB,IAAI,kBAAkB,CAAC,CAAC;QACpE,CAAC,EAAC;QAEO,8CAAqB,KAAK,EAAE,EACnC,eAAe,EAAE,gBAAgB,EACjC,mBAAmB,GACA,EAAE,EAAE;YACvB,MAAM,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,GACrE,IAAI,CAAC,KAAK,CAAC;YACb,uBAAA,IAAI,yCAAiB,EAAE,KAAK,CAAC,mBAAmB,CAAC,CAAC;YAClD,uBAAA,IAAI,qCAAoB,IAAI,eAAe,EAAE,MAAA,CAAC;YAE9C,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;gBACpB,KAAK,CAAC,mBAAmB,GAAG,aAAa,CAAC,OAAO,CAAC;gBAClD,KAAK,CAAC,YAAY,GAAG,mBAAmB,CAAC;gBACzC,KAAK,CAAC,eAAe,GAAG,+BAA+B,CAAC,eAAe,CAAC;YAC1E,CAAC,CAAC,CAAC;YAEH,IAAI;gBACF,MAAM,MAAM,GAAG,MAAM,iBAAiB,CACpC,mBAAmB;gBACnB,0FAA0F;gBAC1F,oCAAoC;gBACpC,2CAA2C;gBAC3C,oEAAoE;gBACpE,uBAAA,IAAI,yCAAkB,CAAC,MAAqB,EAC5C,uBAAA,IAAI,kCAAU,EACd,uBAAA,IAAI,iCAAS,EACb,uBAAA,IAAI,gCAAQ,CAAC,sBAAsB,IAAI,wBAAwB,CAChE,CAAC;gBAEF,MAAM,mBAAmB,GAAG,MAAM,uBAAA,IAAI,yCAAiB,MAArB,IAAI,EAAkB,MAAM,CAAC,CAAC;gBAChE,MAAM,oBAAoB,GAAG,MAAM,uBAAA,IAAI,0CAAkB,MAAtB,IAAI,EAAmB,MAAM,CAAC,CAAC;gBAElE,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;oBACpB,KAAK,CAAC,MAAM,GAAG,mBAAmB,IAAI,oBAAoB,IAAI,MAAM,CAAC;oBACrE,KAAK,CAAC,mBAAmB,GAAG,aAAa,CAAC,OAAO,CAAC;gBACpD,CAAC,CAAC,CAAC;aACJ;YAAC,OAAO,KAAK,EAAE;gBACd,MAAM,YAAY,GAAI,KAAe,CAAC,IAAI,KAAK,YAAY,CAAC;gBAC5D,MAAM,mBAAmB,GAAG,KAAK,KAAK,yBAAyB,CAAC;gBAChE,IAAI,mBAAmB,IAAI,YAAY,EAAE;oBACvC,OAAO;iBACR;gBAED,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;oBACpB,KAAK,CAAC,eAAe;wBACnB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;oBAC3D,KAAK,CAAC,mBAAmB,GAAG,aAAa,CAAC,KAAK,CAAC;oBAChD,KAAK,CAAC,MAAM,GAAG,+BAA+B,CAAC,MAAM,CAAC;gBACxD,CAAC,CAAC,CAAC;gBACH,OAAO,CAAC,GAAG,CAAC,+BAA+B,EAAE,KAAK,CAAC,CAAC;aACrD;oBAAS;gBACR,MAAM,EAAE,eAAe,EAAE,GACvB,kBAAkB,CAAC,qBAAqB,CAAC,gBAAgB,CAAC,CAAC;gBAE7D,MAAM,yBAAyB,GAAG,kBAAkB,GAAG,CAAC,CAAC;gBACzD,mEAAmE;gBACnE,IACE,mBAAmB,CAAC,eAAe;oBACnC,CAAC,CAAC,mBAAmB,CAAC,eAAe;wBACnC,yBAAyB,IAAI,eAAe,CAAC,EAC/C;oBACA,IAAI,CAAC,cAAc,EAAE,CAAC;iBACvB;gBAED,8BAA8B;gBAC9B,MAAM,iBAAiB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBACrC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;oBACpB,KAAK,CAAC,qBAAqB;wBACzB,yBAAyB,KAAK,CAAC,IAAI,uBAAA,IAAI,4CAAoB;4BACzD,CAAC,CAAC,iBAAiB,GAAG,uBAAA,IAAI,4CAAoB;4BAC9C,CAAC,CAAC,qBAAqB,CAAC;oBAC5B,KAAK,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;oBAC5C,KAAK,CAAC,kBAAkB,GAAG,yBAAyB,CAAC;gBACvD,CAAC,CAAC,CAAC;aACJ;QACH,CAAC,EAAC;QAEO,4CAAmB,KAAK,EAC/B,MAAuB,EAC6B,EAAE;YACtD,oEAAoE;YACpE,MAAM,gBAAgB,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE;gBACjD,MAAM,OAAO,GAAG,mBAAmB,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;gBACtD,OAAO,CAAC,CAAC,SAAS,CAAC,QAAQ,EAAE,SAAS,CAAC,IAAI,CAAC;qBACzC,GAAG,CAAC,mBAAmB,CAAC;qBACxB,QAAQ,CAAC,OAAO,CAAC,CAAC;YACvB,CAAC,CAAC,CAAC;YAEH,wEAAwE;YACxE,IAAI,CAAC,gBAAgB,EAAE;gBACrB,OAAO,MAAM,OAAO,CAAC,GAAG,CACtB,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE;oBACjC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,aAAa,CAAC;oBACjD,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,CAAC,UAAU,CAAY,CAAC;oBAEzD,MAAM,WAAW,GAAG,CAAC,MAAc,EAAE,EAAE,CAAC,CAAC;wBACvC,IAAI,EAAE,MAAM,CAAC,IAAI;wBACjB,EAAE,EAAE,MAAM,CAAC,EAAE;wBACb,KAAK,EAAE,MAAM,CAAC,KAAK;wBACnB,IAAI,EAAE,MAAM,CAAC,IAAI;wBACjB,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE;qBACtC,CAAC,CAAC;oBACH,MAAM,iBAAiB,GAAG,QAAQ;wBAChC,CAAC,CAAC,MAAM,uBAAA,IAAI,yCAAiB,MAArB,IAAI,EAAkB;4BAC1B,iBAAiB,EAAE,WAAW,CAAC,QAAQ,CAAC;4BACxC,OAAO;yBACR,CAAC;wBACJ,CAAC,CAAC,GAAG,CAAC;oBACR,MAAM,cAAc,GAAG,MAAM,uBAAA,IAAI,yCAAiB,MAArB,IAAI,EAAkB;wBACjD,iBAAiB,EAAE,WAAW,CAAC,KAAK,CAAC;wBACrC,OAAO;qBACR,CAAC,CAAC;oBACH,OAAO;wBACL,GAAG,aAAa;wBAChB,iBAAiB,EAAE,QAAQ,CAAC,iBAAiB,EAAE,cAAc,CAAC;qBAC/D,CAAC;gBACJ,CAAC,CAAC,CACH,CAAC;aACH;YAED,OAAO,SAAS,CAAC;QACnB,CAAC,EAAC;QAEO,6CAAoB,KAAK,EAChC,MAAuB,EAC8B,EAAE;YACvD,wDAAwD;YACxD,IACE,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,EACxE;gBACA,OAAO,SAAS,CAAC;aAClB;YAED,OAAO,MAAM,OAAO,CAAC,GAAG,CACtB,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE;gBACjC,MAAM,EAAE,KAAK,EAAE,GAAG,aAAa,CAAC;gBAChC,MAAM,eAAe,GAAG,uBAAA,IAAI,mFAA8B,MAAlC,IAAI,CAAgC,CAAC;gBAE7D,IAAI,eAAe,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;oBACpE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,IAAI,CAAC,eAAe,CAAC,IAAI,CACtD,8BAA8B,EAC9B;wBACE,uBAAuB;wBACvB,MAAM,EAAE,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAW;wBACjD,MAAM,EAAE,UAAU;wBAClB,OAAO,EAAE,cAAuB;wBAChC,OAAO,EAAE;4BACP,MAAM,EAAE,sBAAsB;4BAC9B,MAAM,EAAE;gCACN,WAAW,EAAE,KAAK;gCAClB,KAAK,EAAE,eAAe,CAAC,OAAO,CAAC,KAAK;6BACrC;yBACF;qBACF,CACF,CAAsB,CAAC;oBAExB,OAAO;wBACL,GAAG,aAAa;wBAChB,oBAAoB,EAAE,IAAI;qBAC3B,CAAC;iBACH;gBACD,OAAO,aAAa,CAAC;YACvB,CAAC,CAAC,CACH,CAAC;QACJ,CAAC,EAAC;QAwBF;;;;;WAKG;QACH,4BAAuB,GAAG,KAAK,EAC7B,eAAuB,EACvB,OAAY,EACK,EAAE;YACnB,MAAM,QAAQ,GAAG,uBAAA,IAAI,+EAA0B,MAA9B,IAAI,CAA4B,EAAE,QAAQ,CAAC;YAC5D,IAAI,CAAC,QAAQ,EAAE;gBACb,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;aACtC;YAED,MAAM,cAAc,GAAG,IAAI,YAAY,CAAC,QAAQ,CAAC,CAAC;YAClD,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,eAAe,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAC;YACzE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,GAC9B,uBAAA,IAAI,mFAA8B,MAAlC,IAAI,CAAgC,IAAI,EAAE,CAAC;YAC7C,MAAM,SAAS,GAAc,MAAM,QAAQ,CAAC,SAAS,CACnD,aAAa,EACb,+BAA+B,CAAC,OAAO,CAAC,CACzC,CAAC;YACF,OAAO,SAAS,CAAC,QAAQ,EAAE,CAAC;QAC9B,CAAC,CAAC;QAncA,IAAI,CAAC,iBAAiB,CAAC,mBAAmB,CAAC,CAAC;QAE5C,uBAAA,IAAI,qCAAoB,IAAI,eAAe,EAAE,MAAA,CAAC;QAC9C,uBAAA,IAAI,qCAAoB,eAAe,MAAA,CAAC;QACxC,uBAAA,IAAI,8BAAa,QAAQ,MAAA,CAAC;QAC1B,uBAAA,IAAI,6BAAY,OAAO,MAAA,CAAC;QACxB,uBAAA,IAAI,4BAAW,MAAM,IAAI,EAAE,MAAA,CAAC;QAE5B,2BAA2B;QAC3B,IAAI,CAAC,eAAe,CAAC,qBAAqB,CACxC,GAAG,sBAAsB,wBAAwB,EACjD,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CACtC,CAAC;QACF,IAAI,CAAC,eAAe,CAAC,qBAAqB,CACxC,GAAG,sBAAsB,iCAAiC,EAC1D,IAAI,CAAC,8BAA8B,CAAC,IAAI,CAAC,IAAI,CAAC,CAC/C,CAAC;QACF,IAAI,CAAC,eAAe,CAAC,qBAAqB,CACxC,GAAG,sBAAsB,aAAa,EACtC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAC3B,CAAC;QACF,IAAI,CAAC,eAAe,CAAC,qBAAqB,CACxC,GAAG,sBAAsB,0BAA0B,EACnD,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC,CACxC,CAAC;IACJ,CAAC;CA2aF;;IA9CG,OAAO,IAAI,CAAC,eAAe,CAAC,IAAI,CAC9B,iDAAiD,CAClD,CAAC;AACJ,CAAC;IAGC,MAAM,EAAE,uBAAuB,EAAE,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAC3D,4BAA4B,CAC7B,CAAC;IACF,OAAO,uBAAuB,CAAC;AACjC,CAAC;IAGC,MAAM,uBAAuB,GAAG,uBAAA,IAAI,iFAA4B,MAAhC,IAAI,CAA8B,CAAC;IACnE,MAAM,aAAa,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAC7C,wCAAwC,EACxC,uBAAuB,CACxB,CAAC;IACF,OAAO,aAAa,CAAC;AACvB,CAAC","sourcesContent":["import type { BigNumber } from '@ethersproject/bignumber';\nimport { Contract } from '@ethersproject/contracts';\nimport { Web3Provider } from '@ethersproject/providers';\nimport 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 type { CaipAssetType } from '@metamask/utils';\nimport { numberToHex, type Hex } from '@metamask/utils';\n\nimport {\n type BridgeClientId,\n BRIDGE_CONTROLLER_NAME,\n BRIDGE_PROD_API_BASE_URL,\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 { selectIsAssetExchangeRateInState } from './selectors';\nimport type { GenericQuoteRequest, SolanaFees } from './types';\nimport {\n type L1GasFees,\n type QuoteResponse,\n type TxData,\n type BridgeControllerState,\n type BridgeControllerMessenger,\n type FetchFunction,\n BridgeFeatureFlagsKey,\n RequestStatus,\n} from './types';\nimport { getAssetIdsForToken, toExchangeRates } from './utils/assets';\nimport { hasSufficientBalance } from './utils/balance';\nimport {\n getDefaultBridgeControllerState,\n isSolanaChainId,\n sumHexes,\n} from './utils/bridge';\nimport {\n formatAddressToCaipReference,\n formatChainIdToCaip,\n formatChainIdToHex,\n} from './utils/caip-formatters';\nimport {\n fetchAssetPrices,\n fetchBridgeFeatureFlags,\n fetchBridgeQuotes,\n} 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 assetExchangeRates: {\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: GenericQuoteRequest;\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 readonly #config: {\n customBridgeApiBaseUrl?: string;\n };\n\n constructor({\n messenger,\n state,\n clientId,\n getLayer1GasFee,\n fetchFn,\n config,\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 config?: {\n customBridgeApiBaseUrl?: string;\n };\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 this.#config = config ?? {};\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<GenericQuoteRequest>,\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 await this.#fetchAssetExchangeRates(updatedQuoteRequest).catch((error) =>\n console.warn('Failed to fetch asset exchange rates', error),\n );\n\n if (isValidQuoteRequest(updatedQuoteRequest)) {\n this.#quotesFirstFetched = Date.now();\n const providerConfig = this.#getSelectedNetworkClient()?.configuration;\n\n let insufficientBal: boolean | undefined;\n if (isSolanaChainId(updatedQuoteRequest.srcChainId)) {\n // If the source chain is not an EVM network, use value from params\n insufficientBal = paramsToUpdate.insufficientBal;\n } else if (providerConfig?.rpcUrl?.includes('tenderly')) {\n // If the rpcUrl is a tenderly fork (e2e tests), set insufficientBal=true\n // The bridge-api filters out quotes if the balance on mainnet is insufficient so this override allows quotes to always be returned\n insufficientBal = true;\n } else {\n // Otherwise query the src token balance from the RPC provider\n insufficientBal =\n paramsToUpdate.insufficientBal ??\n !(await this.#hasSufficientBalance(updatedQuoteRequest));\n }\n\n const networkClientId = this.#getSelectedNetworkClientId();\n // Set refresh rate based on the source chain before starting polling\n this.#setIntervalLength();\n this.startPolling({\n networkClientId,\n updatedQuoteRequest: {\n ...updatedQuoteRequest,\n insufficientBal,\n },\n });\n }\n };\n\n /**\n * Fetches the exchange rates for the assets in the quote request if they are not already in the state\n * In addition to the selected tokens, this also fetches the native asset for the source and destination chains\n *\n * @param quoteRequest - The quote request\n * @param quoteRequest.srcChainId - The source chain ID\n * @param quoteRequest.srcTokenAddress - The source token address\n * @param quoteRequest.destChainId - The destination chain ID\n * @param quoteRequest.destTokenAddress - The destination token address\n */\n readonly #fetchAssetExchangeRates = async ({\n srcChainId,\n srcTokenAddress,\n destChainId,\n destTokenAddress,\n }: Partial<GenericQuoteRequest>) => {\n const assetIds: Set<CaipAssetType> = new Set();\n\n const exchangeRateSources = {\n ...this.messagingSystem.call('MultichainAssetsRatesController:getState'),\n ...this.messagingSystem.call('CurrencyRateController:getState'),\n ...this.messagingSystem.call('TokenRatesController:getState'),\n ...this.state,\n };\n\n if (\n srcTokenAddress &&\n srcChainId &&\n !selectIsAssetExchangeRateInState(\n exchangeRateSources,\n srcChainId,\n srcTokenAddress,\n )\n ) {\n getAssetIdsForToken(srcTokenAddress, srcChainId).forEach(assetIds.add);\n }\n if (\n destTokenAddress &&\n destChainId &&\n !selectIsAssetExchangeRateInState(\n exchangeRateSources,\n destChainId,\n destTokenAddress,\n )\n ) {\n getAssetIdsForToken(destTokenAddress, destChainId).forEach(assetIds.add);\n }\n\n const currency = this.messagingSystem.call(\n 'CurrencyRateController:getState',\n ).currentCurrency;\n\n const pricesByAssetId = await fetchAssetPrices({\n assetIds,\n currencies: new Set([currency]),\n clientId: this.#clientId,\n fetchFn: this.#fetchFn,\n });\n const exchangeRates = toExchangeRates(currency, pricesByAssetId);\n this.update((state) => {\n state.assetExchangeRates = {\n ...state.assetExchangeRates,\n ...exchangeRates,\n };\n });\n };\n\n readonly #hasSufficientBalance = async (\n quoteRequest: GenericQuoteRequest,\n ) => {\n const walletAddress = this.#getMultichainSelectedAccount()?.address;\n const srcChainIdInHex = formatChainIdToHex(quoteRequest.srcChainId);\n const provider = this.#getSelectedNetworkClient()?.provider;\n const normalizedSrcTokenAddress = formatAddressToCaipReference(\n quoteRequest.srcTokenAddress,\n );\n\n return (\n provider &&\n walletAddress &&\n normalizedSrcTokenAddress &&\n quoteRequest.srcTokenAmount &&\n srcChainIdInHex &&\n (await hasSufficientBalance(\n provider,\n walletAddress,\n normalizedSrcTokenAddress,\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 state.assetExchangeRates =\n DEFAULT_BRIDGE_CONTROLLER_STATE.assetExchangeRates;\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 this.#config.customBridgeApiBaseUrl ?? BRIDGE_PROD_API_BASE_URL,\n );\n this.update((state) => {\n state.bridgeFeatureFlags = bridgeFeatureFlags;\n });\n this.#setIntervalLength();\n };\n\n /**\n * Sets the interval length based on the source chain\n */\n readonly #setIntervalLength = () => {\n const { state } = this;\n const { srcChainId } = state.quoteRequest;\n const refreshRateOverride = srcChainId\n ? state.bridgeFeatureFlags[BridgeFeatureFlagsKey.EXTENSION_CONFIG].chains[\n formatChainIdToCaip(srcChainId)\n ]?.refreshRate\n : undefined;\n const defaultRefreshRate =\n state.bridgeFeatureFlags[BridgeFeatureFlagsKey.EXTENSION_CONFIG]\n .refreshRate;\n this.setIntervalLength(refreshRateOverride ?? defaultRefreshRate);\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\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 this.#config.customBridgeApiBaseUrl ?? BRIDGE_PROD_API_BASE_URL,\n );\n\n const quotesWithL1GasFees = await this.#appendL1GasFees(quotes);\n const quotesWithSolanaFees = await this.#appendSolanaFees(quotes);\n\n this.update((state) => {\n state.quotes = quotesWithL1GasFees ?? quotesWithSolanaFees ?? quotes;\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 state.quotes = DEFAULT_BRIDGE_CONTROLLER_STATE.quotes;\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)[] | undefined> => {\n // Indicates whether some of the quotes are not for optimism or base\n const hasInvalidQuotes = quotes.some(({ quote }) => {\n const chainId = formatChainIdToCaip(quote.srcChainId);\n return ![CHAIN_IDS.OPTIMISM, CHAIN_IDS.BASE]\n .map(formatChainIdToCaip)\n .includes(chainId);\n });\n\n // Only append L1 gas fees if all quotes are for either optimism or base\n if (!hasInvalidQuotes) {\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\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 );\n }\n\n return undefined;\n };\n\n readonly #appendSolanaFees = async (\n quotes: QuoteResponse[],\n ): Promise<(QuoteResponse & SolanaFees)[] | undefined> => {\n // Return early if some of the quotes are not for solana\n if (\n quotes.some(({ quote: { srcChainId } }) => !isSolanaChainId(srcChainId))\n ) {\n return undefined;\n }\n\n return await Promise.all(\n quotes.map(async (quoteResponse) => {\n const { trade } = quoteResponse;\n const selectedAccount = this.#getMultichainSelectedAccount();\n\n if (selectedAccount?.metadata?.snap?.id && typeof trade === 'string') {\n const { value: fees } = (await this.messagingSystem.call(\n 'SnapController:handleRequest',\n {\n // TODO fix these types\n snapId: selectedAccount.metadata.snap.id as never,\n origin: 'metamask',\n handler: 'onRpcRequest' as never,\n request: {\n method: 'getFeeForTransaction',\n params: {\n transaction: trade,\n scope: selectedAccount.options.scope,\n },\n },\n },\n )) as { value: string };\n\n return {\n ...quoteResponse,\n solanaFeesInLamports: fees,\n };\n }\n return quoteResponse;\n }),\n );\n };\n\n #getMultichainSelectedAccount() {\n return this.messagingSystem.call(\n 'AccountsController:getSelectedMultichainAccount',\n );\n }\n\n #getSelectedNetworkClientId() {\n const { selectedNetworkClientId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n return selectedNetworkClientId;\n }\n\n #getSelectedNetworkClient() {\n const selectedNetworkClientId = this.#getSelectedNetworkClientId();\n const networkClient = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n selectedNetworkClientId,\n );\n return networkClient;\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 Web3Provider(provider);\n const contract = new Contract(contractAddress, abiERC20, ethersProvider);\n const { address: walletAddress } =\n this.#getMultichainSelectedAccount() ?? {};\n const allowance: BigNumber = await contract.allowance(\n walletAddress,\n METABRIDGE_CHAIN_TO_ADDRESS_MAP[chainId],\n );\n return allowance.toString();\n };\n}\n"]}