@metamask/bridge-controller 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/LICENSE +20 -0
  3. package/README.md +15 -0
  4. package/dist/bridge-controller.cjs +249 -0
  5. package/dist/bridge-controller.cjs.map +1 -0
  6. package/dist/bridge-controller.d.cts +56 -0
  7. package/dist/bridge-controller.d.cts.map +1 -0
  8. package/dist/bridge-controller.d.mts +56 -0
  9. package/dist/bridge-controller.d.mts.map +1 -0
  10. package/dist/bridge-controller.mjs +245 -0
  11. package/dist/bridge-controller.mjs.map +1 -0
  12. package/dist/constants/bridge.cjs +60 -0
  13. package/dist/constants/bridge.cjs.map +1 -0
  14. package/dist/constants/bridge.d.cts +23 -0
  15. package/dist/constants/bridge.d.cts.map +1 -0
  16. package/dist/constants/bridge.d.mts +23 -0
  17. package/dist/constants/bridge.d.mts.map +1 -0
  18. package/dist/constants/bridge.mjs +57 -0
  19. package/dist/constants/bridge.mjs.map +1 -0
  20. package/dist/constants/chains.cjs +168 -0
  21. package/dist/constants/chains.cjs.map +1 -0
  22. package/dist/constants/chains.d.cts +156 -0
  23. package/dist/constants/chains.d.cts.map +1 -0
  24. package/dist/constants/chains.d.mts +156 -0
  25. package/dist/constants/chains.d.mts.map +1 -0
  26. package/dist/constants/chains.mjs +165 -0
  27. package/dist/constants/chains.mjs.map +1 -0
  28. package/dist/constants/swaps.cjs +5 -0
  29. package/dist/constants/swaps.cjs.map +1 -0
  30. package/dist/constants/swaps.d.cts +2 -0
  31. package/dist/constants/swaps.d.cts.map +1 -0
  32. package/dist/constants/swaps.d.mts +2 -0
  33. package/dist/constants/swaps.d.mts.map +1 -0
  34. package/dist/constants/swaps.mjs +2 -0
  35. package/dist/constants/swaps.mjs.map +1 -0
  36. package/dist/constants/tokens.cjs +109 -0
  37. package/dist/constants/tokens.cjs.map +1 -0
  38. package/dist/constants/tokens.d.cts +73 -0
  39. package/dist/constants/tokens.d.cts.map +1 -0
  40. package/dist/constants/tokens.d.mts +73 -0
  41. package/dist/constants/tokens.d.mts.map +1 -0
  42. package/dist/constants/tokens.mjs +106 -0
  43. package/dist/constants/tokens.mjs.map +1 -0
  44. package/dist/index.cjs +26 -0
  45. package/dist/index.cjs.map +1 -0
  46. package/dist/index.d.cts +9 -0
  47. package/dist/index.d.cts.map +1 -0
  48. package/dist/index.d.mts +9 -0
  49. package/dist/index.d.mts.map +1 -0
  50. package/dist/index.mjs +6 -0
  51. package/dist/index.mjs.map +1 -0
  52. package/dist/types.cjs +77 -0
  53. package/dist/types.cjs.map +1 -0
  54. package/dist/types.d.cts +232 -0
  55. package/dist/types.d.cts.map +1 -0
  56. package/dist/types.d.mts +232 -0
  57. package/dist/types.d.mts.map +1 -0
  58. package/dist/types.mjs +74 -0
  59. package/dist/types.mjs.map +1 -0
  60. package/dist/utils/balance.cjs +31 -0
  61. package/dist/utils/balance.cjs.map +1 -0
  62. package/dist/utils/balance.d.cts +6 -0
  63. package/dist/utils/balance.d.cts.map +1 -0
  64. package/dist/utils/balance.d.mts +6 -0
  65. package/dist/utils/balance.d.mts.map +1 -0
  66. package/dist/utils/balance.mjs +25 -0
  67. package/dist/utils/balance.mjs.map +1 -0
  68. package/dist/utils/bridge.cjs +81 -0
  69. package/dist/utils/bridge.cjs.map +1 -0
  70. package/dist/utils/bridge.d.cts +31 -0
  71. package/dist/utils/bridge.d.cts.map +1 -0
  72. package/dist/utils/bridge.d.mts +31 -0
  73. package/dist/utils/bridge.d.mts.map +1 -0
  74. package/dist/utils/bridge.mjs +71 -0
  75. package/dist/utils/bridge.mjs.map +1 -0
  76. package/dist/utils/fetch.cjs +122 -0
  77. package/dist/utils/fetch.cjs.map +1 -0
  78. package/dist/utils/fetch.d.cts +33 -0
  79. package/dist/utils/fetch.d.cts.map +1 -0
  80. package/dist/utils/fetch.d.mts +33 -0
  81. package/dist/utils/fetch.d.mts.map +1 -0
  82. package/dist/utils/fetch.mjs +115 -0
  83. package/dist/utils/fetch.mjs.map +1 -0
  84. package/dist/utils/quote.cjs +27 -0
  85. package/dist/utils/quote.cjs.map +1 -0
  86. package/dist/utils/quote.d.cts +3 -0
  87. package/dist/utils/quote.d.cts.map +1 -0
  88. package/dist/utils/quote.d.mts +3 -0
  89. package/dist/utils/quote.d.mts.map +1 -0
  90. package/dist/utils/quote.mjs +23 -0
  91. package/dist/utils/quote.mjs.map +1 -0
  92. package/dist/utils/validators.cjs +112 -0
  93. package/dist/utils/validators.cjs.map +1 -0
  94. package/dist/utils/validators.d.cts +30 -0
  95. package/dist/utils/validators.d.cts.map +1 -0
  96. package/dist/utils/validators.d.mts +30 -0
  97. package/dist/utils/validators.d.mts.map +1 -0
  98. package/dist/utils/validators.mjs +104 -0
  99. package/dist/utils/validators.mjs.map +1 -0
  100. package/package.json +86 -0
@@ -0,0 +1,245 @@
1
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
2
+ if (kind === "m") throw new TypeError("Private method is not writable");
3
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
4
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
5
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
6
+ };
7
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
8
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
9
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
+ };
12
+ var _BridgeController_instances, _BridgeController_abortController, _BridgeController_quotesFirstFetched, _BridgeController_clientId, _BridgeController_getLayer1GasFee, _BridgeController_fetchFn, _BridgeController_hasSufficientBalance, _BridgeController_fetchBridgeQuotes, _BridgeController_appendL1GasFees, _BridgeController_getSelectedAccount, _BridgeController_getSelectedNetworkClient, _BridgeController_getSelectedNetworkClientId;
13
+ import { abiERC20 } from "@metamask/metamask-eth-abis";
14
+ import { StaticIntervalPollingController } from "@metamask/polling-controller";
15
+ import { numberToHex } from "@metamask/utils";
16
+ import { BrowserProvider, Contract } from "ethers";
17
+ import { REFRESH_INTERVAL_MS } from "./constants/bridge.mjs";
18
+ import { BRIDGE_CONTROLLER_NAME, DEFAULT_BRIDGE_CONTROLLER_STATE, METABRIDGE_CHAIN_TO_ADDRESS_MAP } from "./constants/bridge.mjs";
19
+ import { CHAIN_IDS } from "./constants/chains.mjs";
20
+ import { BridgeFeatureFlagsKey, RequestStatus } from "./types.mjs";
21
+ import { hasSufficientBalance } from "./utils/balance.mjs";
22
+ import { getDefaultBridgeControllerState, sumHexes } from "./utils/bridge.mjs";
23
+ import { fetchBridgeFeatureFlags, fetchBridgeQuotes } from "./utils/fetch.mjs";
24
+ import { isValidQuoteRequest } from "./utils/quote.mjs";
25
+ const metadata = {
26
+ bridgeState: {
27
+ persist: false,
28
+ anonymous: false,
29
+ },
30
+ };
31
+ const RESET_STATE_ABORT_MESSAGE = 'Reset controller state';
32
+ export class BridgeController extends StaticIntervalPollingController() {
33
+ constructor({ messenger, state, clientId, getLayer1GasFee, fetchFn, }) {
34
+ super({
35
+ name: BRIDGE_CONTROLLER_NAME,
36
+ metadata,
37
+ messenger,
38
+ state: {
39
+ bridgeState: {
40
+ ...getDefaultBridgeControllerState(),
41
+ ...state,
42
+ },
43
+ },
44
+ });
45
+ _BridgeController_instances.add(this);
46
+ _BridgeController_abortController.set(this, void 0);
47
+ _BridgeController_quotesFirstFetched.set(this, void 0);
48
+ _BridgeController_clientId.set(this, void 0);
49
+ _BridgeController_getLayer1GasFee.set(this, void 0);
50
+ _BridgeController_fetchFn.set(this, void 0);
51
+ this._executePoll = async (pollingInput) => {
52
+ await __classPrivateFieldGet(this, _BridgeController_fetchBridgeQuotes, "f").call(this, pollingInput);
53
+ };
54
+ this.updateBridgeQuoteRequestParams = async (paramsToUpdate) => {
55
+ this.stopAllPolling();
56
+ __classPrivateFieldGet(this, _BridgeController_abortController, "f")?.abort('Quote request updated');
57
+ const updatedQuoteRequest = {
58
+ ...DEFAULT_BRIDGE_CONTROLLER_STATE.quoteRequest,
59
+ ...paramsToUpdate,
60
+ };
61
+ this.update((state) => {
62
+ state.bridgeState.quoteRequest = updatedQuoteRequest;
63
+ state.bridgeState.quotes = DEFAULT_BRIDGE_CONTROLLER_STATE.quotes;
64
+ state.bridgeState.quotesLastFetched =
65
+ DEFAULT_BRIDGE_CONTROLLER_STATE.quotesLastFetched;
66
+ state.bridgeState.quotesLoadingStatus =
67
+ DEFAULT_BRIDGE_CONTROLLER_STATE.quotesLoadingStatus;
68
+ state.bridgeState.quoteFetchError =
69
+ DEFAULT_BRIDGE_CONTROLLER_STATE.quoteFetchError;
70
+ state.bridgeState.quotesRefreshCount =
71
+ DEFAULT_BRIDGE_CONTROLLER_STATE.quotesRefreshCount;
72
+ state.bridgeState.quotesInitialLoadTime =
73
+ DEFAULT_BRIDGE_CONTROLLER_STATE.quotesInitialLoadTime;
74
+ });
75
+ if (isValidQuoteRequest(updatedQuoteRequest)) {
76
+ __classPrivateFieldSet(this, _BridgeController_quotesFirstFetched, Date.now(), "f");
77
+ const walletAddress = __classPrivateFieldGet(this, _BridgeController_instances, "m", _BridgeController_getSelectedAccount).call(this).address;
78
+ const srcChainIdInHex = numberToHex(updatedQuoteRequest.srcChainId);
79
+ const insufficientBal = paramsToUpdate.insufficientBal ||
80
+ !(await __classPrivateFieldGet(this, _BridgeController_hasSufficientBalance, "f").call(this, updatedQuoteRequest));
81
+ const networkClientId = __classPrivateFieldGet(this, _BridgeController_instances, "m", _BridgeController_getSelectedNetworkClientId).call(this, srcChainIdInHex);
82
+ this.startPolling({
83
+ networkClientId,
84
+ updatedQuoteRequest: {
85
+ ...updatedQuoteRequest,
86
+ walletAddress,
87
+ insufficientBal,
88
+ },
89
+ });
90
+ }
91
+ };
92
+ _BridgeController_hasSufficientBalance.set(this, async (quoteRequest) => {
93
+ const walletAddress = __classPrivateFieldGet(this, _BridgeController_instances, "m", _BridgeController_getSelectedAccount).call(this).address;
94
+ const srcChainIdInHex = numberToHex(quoteRequest.srcChainId);
95
+ const provider = __classPrivateFieldGet(this, _BridgeController_instances, "m", _BridgeController_getSelectedNetworkClient).call(this)?.provider;
96
+ return (provider &&
97
+ (await hasSufficientBalance(provider, walletAddress, quoteRequest.srcTokenAddress, quoteRequest.srcTokenAmount, srcChainIdInHex)));
98
+ });
99
+ this.resetState = () => {
100
+ this.stopAllPolling();
101
+ __classPrivateFieldGet(this, _BridgeController_abortController, "f")?.abort(RESET_STATE_ABORT_MESSAGE);
102
+ this.update((state) => {
103
+ state.bridgeState = {
104
+ ...DEFAULT_BRIDGE_CONTROLLER_STATE,
105
+ quotes: [],
106
+ bridgeFeatureFlags: state.bridgeState.bridgeFeatureFlags,
107
+ };
108
+ });
109
+ };
110
+ this.setBridgeFeatureFlags = async () => {
111
+ const bridgeFeatureFlags = await fetchBridgeFeatureFlags(__classPrivateFieldGet(this, _BridgeController_clientId, "f"), __classPrivateFieldGet(this, _BridgeController_fetchFn, "f"));
112
+ this.update((state) => {
113
+ state.bridgeState.bridgeFeatureFlags = bridgeFeatureFlags;
114
+ });
115
+ this.setIntervalLength(bridgeFeatureFlags[BridgeFeatureFlagsKey.EXTENSION_CONFIG].refreshRate);
116
+ };
117
+ _BridgeController_fetchBridgeQuotes.set(this, async ({ networkClientId: _networkClientId, updatedQuoteRequest, }) => {
118
+ const { bridgeState } = this.state;
119
+ __classPrivateFieldGet(this, _BridgeController_abortController, "f")?.abort('New quote request');
120
+ __classPrivateFieldSet(this, _BridgeController_abortController, new AbortController(), "f");
121
+ if (updatedQuoteRequest.srcChainId === updatedQuoteRequest.destChainId) {
122
+ return;
123
+ }
124
+ this.update((state) => {
125
+ state.bridgeState.quotesLoadingStatus = RequestStatus.LOADING;
126
+ state.bridgeState.quoteRequest = updatedQuoteRequest;
127
+ state.bridgeState.quoteFetchError =
128
+ DEFAULT_BRIDGE_CONTROLLER_STATE.quoteFetchError;
129
+ });
130
+ try {
131
+ const quotes = await fetchBridgeQuotes(updatedQuoteRequest,
132
+ // AbortController is always defined by this line, because we assign it a few lines above,
133
+ // not sure why Jest thinks it's not
134
+ // Linters accurately say that it's defined
135
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
136
+ __classPrivateFieldGet(this, _BridgeController_abortController, "f").signal, __classPrivateFieldGet(this, _BridgeController_clientId, "f"), __classPrivateFieldGet(this, _BridgeController_fetchFn, "f"));
137
+ const quotesWithL1GasFees = await __classPrivateFieldGet(this, _BridgeController_appendL1GasFees, "f").call(this, quotes);
138
+ this.update((state) => {
139
+ state.bridgeState.quotes = quotesWithL1GasFees;
140
+ state.bridgeState.quotesLoadingStatus = RequestStatus.FETCHED;
141
+ });
142
+ }
143
+ catch (error) {
144
+ const isAbortError = error.name === 'AbortError';
145
+ const isAbortedDueToReset = error === RESET_STATE_ABORT_MESSAGE;
146
+ if (isAbortedDueToReset || isAbortError) {
147
+ return;
148
+ }
149
+ this.update((state) => {
150
+ state.bridgeState.quoteFetchError =
151
+ error instanceof Error ? error.message : 'Unknown error';
152
+ state.bridgeState.quotesLoadingStatus = RequestStatus.ERROR;
153
+ });
154
+ console.log('Failed to fetch bridge quotes', error);
155
+ }
156
+ finally {
157
+ const { maxRefreshCount } = bridgeState.bridgeFeatureFlags[BridgeFeatureFlagsKey.EXTENSION_CONFIG];
158
+ const updatedQuotesRefreshCount = bridgeState.quotesRefreshCount + 1;
159
+ // Stop polling if the maximum number of refreshes has been reached
160
+ if (updatedQuoteRequest.insufficientBal ||
161
+ (!updatedQuoteRequest.insufficientBal &&
162
+ updatedQuotesRefreshCount >= maxRefreshCount)) {
163
+ this.stopAllPolling();
164
+ }
165
+ // Update quote fetching stats
166
+ const quotesLastFetched = Date.now();
167
+ this.update((state) => {
168
+ state.bridgeState.quotesInitialLoadTime =
169
+ updatedQuotesRefreshCount === 1 && __classPrivateFieldGet(this, _BridgeController_quotesFirstFetched, "f")
170
+ ? quotesLastFetched - __classPrivateFieldGet(this, _BridgeController_quotesFirstFetched, "f")
171
+ : bridgeState.quotesInitialLoadTime;
172
+ state.bridgeState.quotesLastFetched = quotesLastFetched;
173
+ state.bridgeState.quotesRefreshCount = updatedQuotesRefreshCount;
174
+ });
175
+ }
176
+ });
177
+ _BridgeController_appendL1GasFees.set(this, async (quotes) => {
178
+ return await Promise.all(quotes.map(async (quoteResponse) => {
179
+ const { quote, trade, approval } = quoteResponse;
180
+ const chainId = numberToHex(quote.srcChainId);
181
+ if ([CHAIN_IDS.OPTIMISM.toString(), CHAIN_IDS.BASE.toString()].includes(chainId)) {
182
+ const getTxParams = (txData) => ({
183
+ from: txData.from,
184
+ to: txData.to,
185
+ value: txData.value,
186
+ data: txData.data,
187
+ gasLimit: txData.gasLimit?.toString(),
188
+ });
189
+ const approvalL1GasFees = approval
190
+ ? await __classPrivateFieldGet(this, _BridgeController_getLayer1GasFee, "f").call(this, {
191
+ transactionParams: getTxParams(approval),
192
+ chainId,
193
+ })
194
+ : '0';
195
+ const tradeL1GasFees = await __classPrivateFieldGet(this, _BridgeController_getLayer1GasFee, "f").call(this, {
196
+ transactionParams: getTxParams(trade),
197
+ chainId,
198
+ });
199
+ return {
200
+ ...quoteResponse,
201
+ l1GasFeesInHexWei: sumHexes(approvalL1GasFees, tradeL1GasFees),
202
+ };
203
+ }
204
+ return quoteResponse;
205
+ }));
206
+ });
207
+ /**
208
+ *
209
+ * @param contractAddress - The address of the ERC20 token contract
210
+ * @param chainId - The hex chain ID of the bridge network
211
+ * @returns The atomic allowance of the ERC20 token contract
212
+ */
213
+ this.getBridgeERC20Allowance = async (contractAddress, chainId) => {
214
+ const provider = __classPrivateFieldGet(this, _BridgeController_instances, "m", _BridgeController_getSelectedNetworkClient).call(this)?.provider;
215
+ if (!provider) {
216
+ throw new Error('No provider found');
217
+ }
218
+ const ethersProvider = new BrowserProvider(provider);
219
+ const contract = new Contract(contractAddress, abiERC20, ethersProvider);
220
+ const { address: walletAddress } = __classPrivateFieldGet(this, _BridgeController_instances, "m", _BridgeController_getSelectedAccount).call(this);
221
+ const allowance = await contract.allowance(walletAddress, METABRIDGE_CHAIN_TO_ADDRESS_MAP[chainId]);
222
+ return allowance.toString();
223
+ };
224
+ this.setIntervalLength(REFRESH_INTERVAL_MS);
225
+ __classPrivateFieldSet(this, _BridgeController_abortController, new AbortController(), "f");
226
+ __classPrivateFieldSet(this, _BridgeController_getLayer1GasFee, getLayer1GasFee, "f");
227
+ __classPrivateFieldSet(this, _BridgeController_clientId, clientId, "f");
228
+ __classPrivateFieldSet(this, _BridgeController_fetchFn, fetchFn, "f");
229
+ // Register action handlers
230
+ this.messagingSystem.registerActionHandler(`${BRIDGE_CONTROLLER_NAME}:setBridgeFeatureFlags`, this.setBridgeFeatureFlags.bind(this));
231
+ this.messagingSystem.registerActionHandler(`${BRIDGE_CONTROLLER_NAME}:updateBridgeQuoteRequestParams`, this.updateBridgeQuoteRequestParams.bind(this));
232
+ this.messagingSystem.registerActionHandler(`${BRIDGE_CONTROLLER_NAME}:resetState`, this.resetState.bind(this));
233
+ this.messagingSystem.registerActionHandler(`${BRIDGE_CONTROLLER_NAME}:getBridgeERC20Allowance`, this.getBridgeERC20Allowance.bind(this));
234
+ }
235
+ }
236
+ _BridgeController_abortController = new WeakMap(), _BridgeController_quotesFirstFetched = new WeakMap(), _BridgeController_clientId = new WeakMap(), _BridgeController_getLayer1GasFee = new WeakMap(), _BridgeController_fetchFn = new WeakMap(), _BridgeController_hasSufficientBalance = new WeakMap(), _BridgeController_fetchBridgeQuotes = new WeakMap(), _BridgeController_appendL1GasFees = new WeakMap(), _BridgeController_instances = new WeakSet(), _BridgeController_getSelectedAccount = function _BridgeController_getSelectedAccount() {
237
+ return this.messagingSystem.call('AccountsController:getSelectedAccount');
238
+ }, _BridgeController_getSelectedNetworkClient = function _BridgeController_getSelectedNetworkClient() {
239
+ const { selectedNetworkClientId } = this.messagingSystem.call('NetworkController:getState');
240
+ const networkClient = this.messagingSystem.call('NetworkController:getNetworkClientById', selectedNetworkClientId);
241
+ return networkClient;
242
+ }, _BridgeController_getSelectedNetworkClientId = function _BridgeController_getSelectedNetworkClientId(chainId) {
243
+ return this.messagingSystem.call('NetworkController:findNetworkClientIdByChainId', chainId);
244
+ };
245
+ //# sourceMappingURL=bridge-controller.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge-controller.mjs","sourceRoot":"","sources":["../src/bridge-controller.ts"],"names":[],"mappings":"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","sourcesContent":["import type { StateMetadata } from '@metamask/base-controller';\nimport type { ChainId } from '@metamask/controller-utils';\nimport { abiERC20 } from '@metamask/metamask-eth-abis';\nimport type { NetworkClientId } from '@metamask/network-controller';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport type { TransactionParams } from '@metamask/transaction-controller';\nimport { numberToHex } from '@metamask/utils';\nimport type { Hex } from '@metamask/utils';\nimport { BrowserProvider, Contract } from 'ethers';\n\nimport type { BridgeClientId } from './constants/bridge';\nimport { REFRESH_INTERVAL_MS } from './constants/bridge';\nimport {\n BRIDGE_CONTROLLER_NAME,\n DEFAULT_BRIDGE_CONTROLLER_STATE,\n METABRIDGE_CHAIN_TO_ADDRESS_MAP,\n} from './constants/bridge';\nimport { CHAIN_IDS } from './constants/chains';\nimport {\n type L1GasFees,\n type QuoteRequest,\n type QuoteResponse,\n type TxData,\n type BridgeControllerState,\n BridgeFeatureFlagsKey,\n RequestStatus,\n} from './types';\nimport type { BridgeControllerMessenger, FetchFunction } from './types';\nimport { hasSufficientBalance } from './utils/balance';\nimport { getDefaultBridgeControllerState, sumHexes } from './utils/bridge';\nimport { fetchBridgeFeatureFlags, fetchBridgeQuotes } from './utils/fetch';\nimport { isValidQuoteRequest } from './utils/quote';\n\nconst metadata: StateMetadata<{ bridgeState: BridgeControllerState }> = {\n bridgeState: {\n persist: false,\n anonymous: false,\n },\n};\n\nconst RESET_STATE_ABORT_MESSAGE = 'Reset controller state';\n\n/** The input to start polling for the {@link BridgeController} */\ntype BridgePollingInput = {\n networkClientId: NetworkClientId;\n updatedQuoteRequest: QuoteRequest;\n};\n\nexport class BridgeController extends StaticIntervalPollingController<BridgePollingInput>()<\n typeof BRIDGE_CONTROLLER_NAME,\n { bridgeState: BridgeControllerState },\n BridgeControllerMessenger\n> {\n #abortController: AbortController | undefined;\n\n #quotesFirstFetched: number | undefined;\n\n readonly #clientId: string;\n\n readonly #getLayer1GasFee: (params: {\n transactionParams: TransactionParams;\n chainId: ChainId;\n }) => Promise<string>;\n\n readonly #fetchFn: FetchFunction;\n\n constructor({\n messenger,\n state,\n clientId,\n getLayer1GasFee,\n fetchFn,\n }: {\n messenger: BridgeControllerMessenger;\n state?: Partial<BridgeControllerState>;\n clientId: BridgeClientId;\n getLayer1GasFee: (params: {\n transactionParams: TransactionParams;\n chainId: ChainId;\n }) => Promise<string>;\n fetchFn: FetchFunction;\n }) {\n super({\n name: BRIDGE_CONTROLLER_NAME,\n metadata,\n messenger,\n state: {\n bridgeState: {\n ...getDefaultBridgeControllerState(),\n ...state,\n },\n },\n });\n\n this.setIntervalLength(REFRESH_INTERVAL_MS);\n\n this.#abortController = new AbortController();\n this.#getLayer1GasFee = getLayer1GasFee;\n this.#clientId = clientId;\n this.#fetchFn = fetchFn;\n\n // Register action handlers\n this.messagingSystem.registerActionHandler(\n `${BRIDGE_CONTROLLER_NAME}:setBridgeFeatureFlags`,\n this.setBridgeFeatureFlags.bind(this),\n );\n this.messagingSystem.registerActionHandler(\n `${BRIDGE_CONTROLLER_NAME}:updateBridgeQuoteRequestParams`,\n this.updateBridgeQuoteRequestParams.bind(this),\n );\n this.messagingSystem.registerActionHandler(\n `${BRIDGE_CONTROLLER_NAME}:resetState`,\n this.resetState.bind(this),\n );\n this.messagingSystem.registerActionHandler(\n `${BRIDGE_CONTROLLER_NAME}:getBridgeERC20Allowance`,\n this.getBridgeERC20Allowance.bind(this),\n );\n }\n\n _executePoll = async (pollingInput: BridgePollingInput) => {\n await this.#fetchBridgeQuotes(pollingInput);\n };\n\n updateBridgeQuoteRequestParams = async (\n paramsToUpdate: Partial<QuoteRequest>,\n ) => {\n this.stopAllPolling();\n this.#abortController?.abort('Quote request updated');\n\n const updatedQuoteRequest = {\n ...DEFAULT_BRIDGE_CONTROLLER_STATE.quoteRequest,\n ...paramsToUpdate,\n };\n\n this.update((state) => {\n state.bridgeState.quoteRequest = updatedQuoteRequest;\n state.bridgeState.quotes = DEFAULT_BRIDGE_CONTROLLER_STATE.quotes;\n state.bridgeState.quotesLastFetched =\n DEFAULT_BRIDGE_CONTROLLER_STATE.quotesLastFetched;\n state.bridgeState.quotesLoadingStatus =\n DEFAULT_BRIDGE_CONTROLLER_STATE.quotesLoadingStatus;\n state.bridgeState.quoteFetchError =\n DEFAULT_BRIDGE_CONTROLLER_STATE.quoteFetchError;\n state.bridgeState.quotesRefreshCount =\n DEFAULT_BRIDGE_CONTROLLER_STATE.quotesRefreshCount;\n state.bridgeState.quotesInitialLoadTime =\n DEFAULT_BRIDGE_CONTROLLER_STATE.quotesInitialLoadTime;\n });\n\n if (isValidQuoteRequest(updatedQuoteRequest)) {\n this.#quotesFirstFetched = Date.now();\n const walletAddress = this.#getSelectedAccount().address;\n const srcChainIdInHex = numberToHex(updatedQuoteRequest.srcChainId);\n\n const insufficientBal =\n paramsToUpdate.insufficientBal ||\n !(await this.#hasSufficientBalance(updatedQuoteRequest));\n\n const networkClientId = this.#getSelectedNetworkClientId(srcChainIdInHex);\n this.startPolling({\n networkClientId,\n updatedQuoteRequest: {\n ...updatedQuoteRequest,\n walletAddress,\n insufficientBal,\n },\n });\n }\n };\n\n readonly #hasSufficientBalance = async (quoteRequest: QuoteRequest) => {\n const walletAddress = this.#getSelectedAccount().address;\n const srcChainIdInHex = numberToHex(quoteRequest.srcChainId);\n const provider = this.#getSelectedNetworkClient()?.provider;\n\n return (\n provider &&\n (await hasSufficientBalance(\n provider,\n walletAddress,\n quoteRequest.srcTokenAddress,\n quoteRequest.srcTokenAmount,\n srcChainIdInHex,\n ))\n );\n };\n\n resetState = () => {\n this.stopAllPolling();\n this.#abortController?.abort(RESET_STATE_ABORT_MESSAGE);\n\n this.update((state) => {\n state.bridgeState = {\n ...DEFAULT_BRIDGE_CONTROLLER_STATE,\n quotes: [],\n bridgeFeatureFlags: state.bridgeState.bridgeFeatureFlags,\n };\n });\n };\n\n setBridgeFeatureFlags = async () => {\n const bridgeFeatureFlags = await fetchBridgeFeatureFlags(\n this.#clientId,\n this.#fetchFn,\n );\n this.update((state) => {\n state.bridgeState.bridgeFeatureFlags = bridgeFeatureFlags;\n });\n this.setIntervalLength(\n bridgeFeatureFlags[BridgeFeatureFlagsKey.EXTENSION_CONFIG].refreshRate,\n );\n };\n\n readonly #fetchBridgeQuotes = async ({\n networkClientId: _networkClientId,\n updatedQuoteRequest,\n }: BridgePollingInput) => {\n const { bridgeState } = this.state;\n this.#abortController?.abort('New quote request');\n this.#abortController = new AbortController();\n if (updatedQuoteRequest.srcChainId === updatedQuoteRequest.destChainId) {\n return;\n }\n this.update((state) => {\n state.bridgeState.quotesLoadingStatus = RequestStatus.LOADING;\n state.bridgeState.quoteRequest = updatedQuoteRequest;\n state.bridgeState.quoteFetchError =\n DEFAULT_BRIDGE_CONTROLLER_STATE.quoteFetchError;\n });\n\n try {\n const quotes = await fetchBridgeQuotes(\n updatedQuoteRequest,\n // AbortController is always defined by this line, because we assign it a few lines above,\n // not sure why Jest thinks it's not\n // Linters accurately say that it's defined\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.#abortController!.signal as AbortSignal,\n this.#clientId,\n this.#fetchFn,\n );\n\n const quotesWithL1GasFees = await this.#appendL1GasFees(quotes);\n\n this.update((state) => {\n state.bridgeState.quotes = quotesWithL1GasFees;\n state.bridgeState.quotesLoadingStatus = RequestStatus.FETCHED;\n });\n } catch (error) {\n const isAbortError = (error as Error).name === 'AbortError';\n const isAbortedDueToReset = error === RESET_STATE_ABORT_MESSAGE;\n if (isAbortedDueToReset || isAbortError) {\n return;\n }\n\n this.update((state) => {\n state.bridgeState.quoteFetchError =\n error instanceof Error ? error.message : 'Unknown error';\n state.bridgeState.quotesLoadingStatus = RequestStatus.ERROR;\n });\n console.log('Failed to fetch bridge quotes', error);\n } finally {\n const { maxRefreshCount } =\n bridgeState.bridgeFeatureFlags[BridgeFeatureFlagsKey.EXTENSION_CONFIG];\n\n const updatedQuotesRefreshCount = bridgeState.quotesRefreshCount + 1;\n // Stop polling if the maximum number of refreshes has been reached\n if (\n updatedQuoteRequest.insufficientBal ||\n (!updatedQuoteRequest.insufficientBal &&\n updatedQuotesRefreshCount >= maxRefreshCount)\n ) {\n this.stopAllPolling();\n }\n\n // Update quote fetching stats\n const quotesLastFetched = Date.now();\n this.update((state) => {\n state.bridgeState.quotesInitialLoadTime =\n updatedQuotesRefreshCount === 1 && this.#quotesFirstFetched\n ? quotesLastFetched - this.#quotesFirstFetched\n : bridgeState.quotesInitialLoadTime;\n state.bridgeState.quotesLastFetched = quotesLastFetched;\n state.bridgeState.quotesRefreshCount = updatedQuotesRefreshCount;\n });\n }\n };\n\n readonly #appendL1GasFees = async (\n quotes: QuoteResponse[],\n ): Promise<(QuoteResponse & L1GasFees)[]> => {\n return await Promise.all(\n quotes.map(async (quoteResponse) => {\n const { quote, trade, approval } = quoteResponse;\n const chainId = numberToHex(quote.srcChainId) as ChainId;\n if (\n [CHAIN_IDS.OPTIMISM.toString(), CHAIN_IDS.BASE.toString()].includes(\n chainId,\n )\n ) {\n const getTxParams = (txData: TxData) => ({\n from: txData.from,\n to: txData.to,\n value: txData.value,\n data: txData.data,\n gasLimit: txData.gasLimit?.toString(),\n });\n const approvalL1GasFees = approval\n ? await this.#getLayer1GasFee({\n transactionParams: getTxParams(approval),\n chainId,\n })\n : '0';\n const tradeL1GasFees = await this.#getLayer1GasFee({\n transactionParams: getTxParams(trade),\n chainId,\n });\n return {\n ...quoteResponse,\n l1GasFeesInHexWei: sumHexes(approvalL1GasFees, tradeL1GasFees),\n };\n }\n return quoteResponse;\n }),\n );\n };\n\n #getSelectedAccount() {\n return this.messagingSystem.call('AccountsController:getSelectedAccount');\n }\n\n #getSelectedNetworkClient() {\n const { selectedNetworkClientId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n const networkClient = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n selectedNetworkClientId,\n );\n return networkClient;\n }\n\n #getSelectedNetworkClientId(chainId: Hex) {\n return this.messagingSystem.call(\n 'NetworkController:findNetworkClientIdByChainId',\n chainId,\n );\n }\n\n /**\n *\n * @param contractAddress - The address of the ERC20 token contract\n * @param chainId - The hex chain ID of the bridge network\n * @returns The atomic allowance of the ERC20 token contract\n */\n getBridgeERC20Allowance = async (\n contractAddress: string,\n chainId: Hex,\n ): Promise<string> => {\n const provider = this.#getSelectedNetworkClient()?.provider;\n if (!provider) {\n throw new Error('No provider found');\n }\n\n const ethersProvider = new BrowserProvider(provider);\n const contract = new Contract(contractAddress, abiERC20, ethersProvider);\n const { address: walletAddress } = this.#getSelectedAccount();\n const allowance: bigint = await contract.allowance(\n walletAddress,\n METABRIDGE_CHAIN_TO_ADDRESS_MAP[chainId],\n );\n return allowance.toString();\n };\n}\n"]}
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.METABRIDGE_CHAIN_TO_ADDRESS_MAP = exports.DEFAULT_BRIDGE_CONTROLLER_STATE = exports.BRIDGE_CONTROLLER_NAME = exports.DEFAULT_MAX_REFRESH_COUNT = exports.REFRESH_INTERVAL_MS = exports.BRIDGE_MM_FEE_RATE = exports.BRIDGE_DEFAULT_SLIPPAGE = exports.BRIDGE_PREFERRED_GAS_ESTIMATE = exports.BRIDGE_QUOTE_MAX_RETURN_DIFFERENCE_PERCENTAGE = exports.BRIDGE_QUOTE_MAX_ETA_SECONDS = exports.METABRIDGE_ETHEREUM_ADDRESS = exports.ETH_USDT_ADDRESS = exports.BridgeClientId = exports.BRIDGE_PROD_API_BASE_URL = exports.BRIDGE_DEV_API_BASE_URL = exports.ALLOWED_BRIDGE_CHAIN_IDS = void 0;
4
+ const ethers_1 = require("ethers");
5
+ const chains_1 = require("./chains.cjs");
6
+ const types_1 = require("../types.cjs");
7
+ // TODO read from feature flags
8
+ exports.ALLOWED_BRIDGE_CHAIN_IDS = [
9
+ chains_1.CHAIN_IDS.MAINNET,
10
+ chains_1.CHAIN_IDS.BSC,
11
+ chains_1.CHAIN_IDS.POLYGON,
12
+ chains_1.CHAIN_IDS.ZKSYNC_ERA,
13
+ chains_1.CHAIN_IDS.AVALANCHE,
14
+ chains_1.CHAIN_IDS.OPTIMISM,
15
+ chains_1.CHAIN_IDS.ARBITRUM,
16
+ chains_1.CHAIN_IDS.LINEA_MAINNET,
17
+ chains_1.CHAIN_IDS.BASE,
18
+ ];
19
+ exports.BRIDGE_DEV_API_BASE_URL = 'https://bridge.dev-api.cx.metamask.io';
20
+ exports.BRIDGE_PROD_API_BASE_URL = 'https://bridge.api.cx.metamask.io';
21
+ var BridgeClientId;
22
+ (function (BridgeClientId) {
23
+ BridgeClientId["EXTENSION"] = "extension";
24
+ BridgeClientId["MOBILE"] = "mobile";
25
+ })(BridgeClientId || (exports.BridgeClientId = BridgeClientId = {}));
26
+ exports.ETH_USDT_ADDRESS = '0xdac17f958d2ee523a2206206994597c13d831ec7';
27
+ exports.METABRIDGE_ETHEREUM_ADDRESS = '0x0439e60F02a8900a951603950d8D4527f400C3f1';
28
+ exports.BRIDGE_QUOTE_MAX_ETA_SECONDS = 60 * 60; // 1 hour
29
+ exports.BRIDGE_QUOTE_MAX_RETURN_DIFFERENCE_PERCENTAGE = 0.5; // if a quote returns in x times less return than the best quote, ignore it
30
+ exports.BRIDGE_PREFERRED_GAS_ESTIMATE = 'high';
31
+ exports.BRIDGE_DEFAULT_SLIPPAGE = 0.5;
32
+ exports.BRIDGE_MM_FEE_RATE = 0.875;
33
+ exports.REFRESH_INTERVAL_MS = 30 * 1000;
34
+ exports.DEFAULT_MAX_REFRESH_COUNT = 5;
35
+ exports.BRIDGE_CONTROLLER_NAME = 'BridgeController';
36
+ exports.DEFAULT_BRIDGE_CONTROLLER_STATE = {
37
+ bridgeFeatureFlags: {
38
+ [types_1.BridgeFeatureFlagsKey.EXTENSION_CONFIG]: {
39
+ refreshRate: exports.REFRESH_INTERVAL_MS,
40
+ maxRefreshCount: exports.DEFAULT_MAX_REFRESH_COUNT,
41
+ support: false,
42
+ chains: {},
43
+ },
44
+ },
45
+ quoteRequest: {
46
+ walletAddress: undefined,
47
+ srcTokenAddress: ethers_1.ZeroAddress,
48
+ slippage: exports.BRIDGE_DEFAULT_SLIPPAGE,
49
+ },
50
+ quotesInitialLoadTime: undefined,
51
+ quotes: [],
52
+ quotesLastFetched: undefined,
53
+ quotesLoadingStatus: undefined,
54
+ quoteFetchError: undefined,
55
+ quotesRefreshCount: 0,
56
+ };
57
+ exports.METABRIDGE_CHAIN_TO_ADDRESS_MAP = {
58
+ [chains_1.CHAIN_IDS.MAINNET]: exports.METABRIDGE_ETHEREUM_ADDRESS,
59
+ };
60
+ //# sourceMappingURL=bridge.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge.cjs","sourceRoot":"","sources":["../../src/constants/bridge.ts"],"names":[],"mappings":";;;AACA,mCAAqC;AAErC,yCAAqC;AAErC,wCAAiD;AAEjD,+BAA+B;AAClB,QAAA,wBAAwB,GAAG;IACtC,kBAAS,CAAC,OAAO;IACjB,kBAAS,CAAC,GAAG;IACb,kBAAS,CAAC,OAAO;IACjB,kBAAS,CAAC,UAAU;IACpB,kBAAS,CAAC,SAAS;IACnB,kBAAS,CAAC,QAAQ;IAClB,kBAAS,CAAC,QAAQ;IAClB,kBAAS,CAAC,aAAa;IACvB,kBAAS,CAAC,IAAI;CACf,CAAC;AAIW,QAAA,uBAAuB,GAAG,uCAAuC,CAAC;AAClE,QAAA,wBAAwB,GAAG,mCAAmC,CAAC;AAE5E,IAAY,cAGX;AAHD,WAAY,cAAc;IACxB,yCAAuB,CAAA;IACvB,mCAAiB,CAAA;AACnB,CAAC,EAHW,cAAc,8BAAd,cAAc,QAGzB;AAEY,QAAA,gBAAgB,GAAG,4CAA4C,CAAC;AAChE,QAAA,2BAA2B,GACtC,4CAA4C,CAAC;AAClC,QAAA,4BAA4B,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,SAAS;AACjD,QAAA,6CAA6C,GAAG,GAAG,CAAC,CAAC,2EAA2E;AAEhI,QAAA,6BAA6B,GAAG,MAAM,CAAC;AACvC,QAAA,uBAAuB,GAAG,GAAG,CAAC;AAC9B,QAAA,kBAAkB,GAAG,KAAK,CAAC;AAC3B,QAAA,mBAAmB,GAAG,EAAE,GAAG,IAAI,CAAC;AAChC,QAAA,yBAAyB,GAAG,CAAC,CAAC;AAE9B,QAAA,sBAAsB,GAAG,kBAAkB,CAAC;AAC5C,QAAA,+BAA+B,GAA0B;IACpE,kBAAkB,EAAE;QAClB,CAAC,6BAAqB,CAAC,gBAAgB,CAAC,EAAE;YACxC,WAAW,EAAE,2BAAmB;YAChC,eAAe,EAAE,iCAAyB;YAC1C,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,EAAE;SACX;KACF;IACD,YAAY,EAAE;QACZ,aAAa,EAAE,SAAS;QACxB,eAAe,EAAE,oBAAW;QAC5B,QAAQ,EAAE,+BAAuB;KAClC;IACD,qBAAqB,EAAE,SAAS;IAChC,MAAM,EAAE,EAAE;IACV,iBAAiB,EAAE,SAAS;IAC5B,mBAAmB,EAAE,SAAS;IAC9B,eAAe,EAAE,SAAS;IAC1B,kBAAkB,EAAE,CAAC;CACtB,CAAC;AAEW,QAAA,+BAA+B,GAAwB;IAClE,CAAC,kBAAS,CAAC,OAAO,CAAC,EAAE,mCAA2B;CACjD,CAAC","sourcesContent":["import type { Hex } from '@metamask/utils';\nimport { ZeroAddress } from 'ethers';\n\nimport { CHAIN_IDS } from './chains';\nimport type { BridgeControllerState } from '../types';\nimport { BridgeFeatureFlagsKey } from '../types';\n\n// TODO read from feature flags\nexport const ALLOWED_BRIDGE_CHAIN_IDS = [\n CHAIN_IDS.MAINNET,\n CHAIN_IDS.BSC,\n CHAIN_IDS.POLYGON,\n CHAIN_IDS.ZKSYNC_ERA,\n CHAIN_IDS.AVALANCHE,\n CHAIN_IDS.OPTIMISM,\n CHAIN_IDS.ARBITRUM,\n CHAIN_IDS.LINEA_MAINNET,\n CHAIN_IDS.BASE,\n];\n\nexport type AllowedBridgeChainIds = (typeof ALLOWED_BRIDGE_CHAIN_IDS)[number];\n\nexport const BRIDGE_DEV_API_BASE_URL = 'https://bridge.dev-api.cx.metamask.io';\nexport const BRIDGE_PROD_API_BASE_URL = 'https://bridge.api.cx.metamask.io';\n\nexport enum BridgeClientId {\n EXTENSION = 'extension',\n MOBILE = 'mobile',\n}\n\nexport const ETH_USDT_ADDRESS = '0xdac17f958d2ee523a2206206994597c13d831ec7';\nexport const METABRIDGE_ETHEREUM_ADDRESS =\n '0x0439e60F02a8900a951603950d8D4527f400C3f1';\nexport const BRIDGE_QUOTE_MAX_ETA_SECONDS = 60 * 60; // 1 hour\nexport const BRIDGE_QUOTE_MAX_RETURN_DIFFERENCE_PERCENTAGE = 0.5; // if a quote returns in x times less return than the best quote, ignore it\n\nexport const BRIDGE_PREFERRED_GAS_ESTIMATE = 'high';\nexport const BRIDGE_DEFAULT_SLIPPAGE = 0.5;\nexport const BRIDGE_MM_FEE_RATE = 0.875;\nexport const REFRESH_INTERVAL_MS = 30 * 1000;\nexport const DEFAULT_MAX_REFRESH_COUNT = 5;\n\nexport const BRIDGE_CONTROLLER_NAME = 'BridgeController';\nexport const DEFAULT_BRIDGE_CONTROLLER_STATE: BridgeControllerState = {\n bridgeFeatureFlags: {\n [BridgeFeatureFlagsKey.EXTENSION_CONFIG]: {\n refreshRate: REFRESH_INTERVAL_MS,\n maxRefreshCount: DEFAULT_MAX_REFRESH_COUNT,\n support: false,\n chains: {},\n },\n },\n quoteRequest: {\n walletAddress: undefined,\n srcTokenAddress: ZeroAddress,\n slippage: BRIDGE_DEFAULT_SLIPPAGE,\n },\n quotesInitialLoadTime: undefined,\n quotes: [],\n quotesLastFetched: undefined,\n quotesLoadingStatus: undefined,\n quoteFetchError: undefined,\n quotesRefreshCount: 0,\n};\n\nexport const METABRIDGE_CHAIN_TO_ADDRESS_MAP: Record<Hex, string> = {\n [CHAIN_IDS.MAINNET]: METABRIDGE_ETHEREUM_ADDRESS,\n};\n"]}
@@ -0,0 +1,23 @@
1
+ import type { Hex } from "@metamask/utils";
2
+ import type { BridgeControllerState } from "../types.cjs";
3
+ export declare const ALLOWED_BRIDGE_CHAIN_IDS: ("0x1" | "0xe708" | "0x2105" | "0x38" | "0xa" | "0x89" | "0xa86a" | "0xa4b1" | "0x144")[];
4
+ export type AllowedBridgeChainIds = (typeof ALLOWED_BRIDGE_CHAIN_IDS)[number];
5
+ export declare const BRIDGE_DEV_API_BASE_URL = "https://bridge.dev-api.cx.metamask.io";
6
+ export declare const BRIDGE_PROD_API_BASE_URL = "https://bridge.api.cx.metamask.io";
7
+ export declare enum BridgeClientId {
8
+ EXTENSION = "extension",
9
+ MOBILE = "mobile"
10
+ }
11
+ export declare const ETH_USDT_ADDRESS = "0xdac17f958d2ee523a2206206994597c13d831ec7";
12
+ export declare const METABRIDGE_ETHEREUM_ADDRESS = "0x0439e60F02a8900a951603950d8D4527f400C3f1";
13
+ export declare const BRIDGE_QUOTE_MAX_ETA_SECONDS: number;
14
+ export declare const BRIDGE_QUOTE_MAX_RETURN_DIFFERENCE_PERCENTAGE = 0.5;
15
+ export declare const BRIDGE_PREFERRED_GAS_ESTIMATE = "high";
16
+ export declare const BRIDGE_DEFAULT_SLIPPAGE = 0.5;
17
+ export declare const BRIDGE_MM_FEE_RATE = 0.875;
18
+ export declare const REFRESH_INTERVAL_MS: number;
19
+ export declare const DEFAULT_MAX_REFRESH_COUNT = 5;
20
+ export declare const BRIDGE_CONTROLLER_NAME = "BridgeController";
21
+ export declare const DEFAULT_BRIDGE_CONTROLLER_STATE: BridgeControllerState;
22
+ export declare const METABRIDGE_CHAIN_TO_ADDRESS_MAP: Record<Hex, string>;
23
+ //# sourceMappingURL=bridge.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge.d.cts","sourceRoot":"","sources":["../../src/constants/bridge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAI3C,OAAO,KAAK,EAAE,qBAAqB,EAAE,qBAAiB;AAItD,eAAO,MAAM,wBAAwB,2FAUpC,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG,CAAC,OAAO,wBAAwB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE9E,eAAO,MAAM,uBAAuB,0CAA0C,CAAC;AAC/E,eAAO,MAAM,wBAAwB,sCAAsC,CAAC;AAE5E,oBAAY,cAAc;IACxB,SAAS,cAAc;IACvB,MAAM,WAAW;CAClB;AAED,eAAO,MAAM,gBAAgB,+CAA+C,CAAC;AAC7E,eAAO,MAAM,2BAA2B,+CACM,CAAC;AAC/C,eAAO,MAAM,4BAA4B,QAAU,CAAC;AACpD,eAAO,MAAM,6CAA6C,MAAM,CAAC;AAEjE,eAAO,MAAM,6BAA6B,SAAS,CAAC;AACpD,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAC3C,eAAO,MAAM,kBAAkB,QAAQ,CAAC;AACxC,eAAO,MAAM,mBAAmB,QAAY,CAAC;AAC7C,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAE3C,eAAO,MAAM,sBAAsB,qBAAqB,CAAC;AACzD,eAAO,MAAM,+BAA+B,EAAE,qBAoB7C,CAAC;AAEF,eAAO,MAAM,+BAA+B,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,CAE/D,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { Hex } from "@metamask/utils";
2
+ import type { BridgeControllerState } from "../types.mjs";
3
+ export declare const ALLOWED_BRIDGE_CHAIN_IDS: ("0x1" | "0xe708" | "0x2105" | "0x38" | "0xa" | "0x89" | "0xa86a" | "0xa4b1" | "0x144")[];
4
+ export type AllowedBridgeChainIds = (typeof ALLOWED_BRIDGE_CHAIN_IDS)[number];
5
+ export declare const BRIDGE_DEV_API_BASE_URL = "https://bridge.dev-api.cx.metamask.io";
6
+ export declare const BRIDGE_PROD_API_BASE_URL = "https://bridge.api.cx.metamask.io";
7
+ export declare enum BridgeClientId {
8
+ EXTENSION = "extension",
9
+ MOBILE = "mobile"
10
+ }
11
+ export declare const ETH_USDT_ADDRESS = "0xdac17f958d2ee523a2206206994597c13d831ec7";
12
+ export declare const METABRIDGE_ETHEREUM_ADDRESS = "0x0439e60F02a8900a951603950d8D4527f400C3f1";
13
+ export declare const BRIDGE_QUOTE_MAX_ETA_SECONDS: number;
14
+ export declare const BRIDGE_QUOTE_MAX_RETURN_DIFFERENCE_PERCENTAGE = 0.5;
15
+ export declare const BRIDGE_PREFERRED_GAS_ESTIMATE = "high";
16
+ export declare const BRIDGE_DEFAULT_SLIPPAGE = 0.5;
17
+ export declare const BRIDGE_MM_FEE_RATE = 0.875;
18
+ export declare const REFRESH_INTERVAL_MS: number;
19
+ export declare const DEFAULT_MAX_REFRESH_COUNT = 5;
20
+ export declare const BRIDGE_CONTROLLER_NAME = "BridgeController";
21
+ export declare const DEFAULT_BRIDGE_CONTROLLER_STATE: BridgeControllerState;
22
+ export declare const METABRIDGE_CHAIN_TO_ADDRESS_MAP: Record<Hex, string>;
23
+ //# sourceMappingURL=bridge.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge.d.mts","sourceRoot":"","sources":["../../src/constants/bridge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAI3C,OAAO,KAAK,EAAE,qBAAqB,EAAE,qBAAiB;AAItD,eAAO,MAAM,wBAAwB,2FAUpC,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG,CAAC,OAAO,wBAAwB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE9E,eAAO,MAAM,uBAAuB,0CAA0C,CAAC;AAC/E,eAAO,MAAM,wBAAwB,sCAAsC,CAAC;AAE5E,oBAAY,cAAc;IACxB,SAAS,cAAc;IACvB,MAAM,WAAW;CAClB;AAED,eAAO,MAAM,gBAAgB,+CAA+C,CAAC;AAC7E,eAAO,MAAM,2BAA2B,+CACM,CAAC;AAC/C,eAAO,MAAM,4BAA4B,QAAU,CAAC;AACpD,eAAO,MAAM,6CAA6C,MAAM,CAAC;AAEjE,eAAO,MAAM,6BAA6B,SAAS,CAAC;AACpD,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAC3C,eAAO,MAAM,kBAAkB,QAAQ,CAAC;AACxC,eAAO,MAAM,mBAAmB,QAAY,CAAC;AAC7C,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAE3C,eAAO,MAAM,sBAAsB,qBAAqB,CAAC;AACzD,eAAO,MAAM,+BAA+B,EAAE,qBAoB7C,CAAC;AAEF,eAAO,MAAM,+BAA+B,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,CAE/D,CAAC"}
@@ -0,0 +1,57 @@
1
+ import { ZeroAddress } from "ethers";
2
+ import { CHAIN_IDS } from "./chains.mjs";
3
+ import { BridgeFeatureFlagsKey } from "../types.mjs";
4
+ // TODO read from feature flags
5
+ export const ALLOWED_BRIDGE_CHAIN_IDS = [
6
+ CHAIN_IDS.MAINNET,
7
+ CHAIN_IDS.BSC,
8
+ CHAIN_IDS.POLYGON,
9
+ CHAIN_IDS.ZKSYNC_ERA,
10
+ CHAIN_IDS.AVALANCHE,
11
+ CHAIN_IDS.OPTIMISM,
12
+ CHAIN_IDS.ARBITRUM,
13
+ CHAIN_IDS.LINEA_MAINNET,
14
+ CHAIN_IDS.BASE,
15
+ ];
16
+ export const BRIDGE_DEV_API_BASE_URL = 'https://bridge.dev-api.cx.metamask.io';
17
+ export const BRIDGE_PROD_API_BASE_URL = 'https://bridge.api.cx.metamask.io';
18
+ export var BridgeClientId;
19
+ (function (BridgeClientId) {
20
+ BridgeClientId["EXTENSION"] = "extension";
21
+ BridgeClientId["MOBILE"] = "mobile";
22
+ })(BridgeClientId || (BridgeClientId = {}));
23
+ export const ETH_USDT_ADDRESS = '0xdac17f958d2ee523a2206206994597c13d831ec7';
24
+ export const METABRIDGE_ETHEREUM_ADDRESS = '0x0439e60F02a8900a951603950d8D4527f400C3f1';
25
+ export const BRIDGE_QUOTE_MAX_ETA_SECONDS = 60 * 60; // 1 hour
26
+ export const BRIDGE_QUOTE_MAX_RETURN_DIFFERENCE_PERCENTAGE = 0.5; // if a quote returns in x times less return than the best quote, ignore it
27
+ export const BRIDGE_PREFERRED_GAS_ESTIMATE = 'high';
28
+ export const BRIDGE_DEFAULT_SLIPPAGE = 0.5;
29
+ export const BRIDGE_MM_FEE_RATE = 0.875;
30
+ export const REFRESH_INTERVAL_MS = 30 * 1000;
31
+ export const DEFAULT_MAX_REFRESH_COUNT = 5;
32
+ export const BRIDGE_CONTROLLER_NAME = 'BridgeController';
33
+ export const DEFAULT_BRIDGE_CONTROLLER_STATE = {
34
+ bridgeFeatureFlags: {
35
+ [BridgeFeatureFlagsKey.EXTENSION_CONFIG]: {
36
+ refreshRate: REFRESH_INTERVAL_MS,
37
+ maxRefreshCount: DEFAULT_MAX_REFRESH_COUNT,
38
+ support: false,
39
+ chains: {},
40
+ },
41
+ },
42
+ quoteRequest: {
43
+ walletAddress: undefined,
44
+ srcTokenAddress: ZeroAddress,
45
+ slippage: BRIDGE_DEFAULT_SLIPPAGE,
46
+ },
47
+ quotesInitialLoadTime: undefined,
48
+ quotes: [],
49
+ quotesLastFetched: undefined,
50
+ quotesLoadingStatus: undefined,
51
+ quoteFetchError: undefined,
52
+ quotesRefreshCount: 0,
53
+ };
54
+ export const METABRIDGE_CHAIN_TO_ADDRESS_MAP = {
55
+ [CHAIN_IDS.MAINNET]: METABRIDGE_ETHEREUM_ADDRESS,
56
+ };
57
+ //# sourceMappingURL=bridge.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge.mjs","sourceRoot":"","sources":["../../src/constants/bridge.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,eAAe;AAErC,OAAO,EAAE,SAAS,EAAE,qBAAiB;AAErC,OAAO,EAAE,qBAAqB,EAAE,qBAAiB;AAEjD,+BAA+B;AAC/B,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,SAAS,CAAC,OAAO;IACjB,SAAS,CAAC,GAAG;IACb,SAAS,CAAC,OAAO;IACjB,SAAS,CAAC,UAAU;IACpB,SAAS,CAAC,SAAS;IACnB,SAAS,CAAC,QAAQ;IAClB,SAAS,CAAC,QAAQ;IAClB,SAAS,CAAC,aAAa;IACvB,SAAS,CAAC,IAAI;CACf,CAAC;AAIF,MAAM,CAAC,MAAM,uBAAuB,GAAG,uCAAuC,CAAC;AAC/E,MAAM,CAAC,MAAM,wBAAwB,GAAG,mCAAmC,CAAC;AAE5E,MAAM,CAAN,IAAY,cAGX;AAHD,WAAY,cAAc;IACxB,yCAAuB,CAAA;IACvB,mCAAiB,CAAA;AACnB,CAAC,EAHW,cAAc,KAAd,cAAc,QAGzB;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,4CAA4C,CAAC;AAC7E,MAAM,CAAC,MAAM,2BAA2B,GACtC,4CAA4C,CAAC;AAC/C,MAAM,CAAC,MAAM,4BAA4B,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,SAAS;AAC9D,MAAM,CAAC,MAAM,6CAA6C,GAAG,GAAG,CAAC,CAAC,2EAA2E;AAE7I,MAAM,CAAC,MAAM,6BAA6B,GAAG,MAAM,CAAC;AACpD,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAAG,CAAC;AAC3C,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,CAAC;AACxC,MAAM,CAAC,MAAM,mBAAmB,GAAG,EAAE,GAAG,IAAI,CAAC;AAC7C,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC;AAE3C,MAAM,CAAC,MAAM,sBAAsB,GAAG,kBAAkB,CAAC;AACzD,MAAM,CAAC,MAAM,+BAA+B,GAA0B;IACpE,kBAAkB,EAAE;QAClB,CAAC,qBAAqB,CAAC,gBAAgB,CAAC,EAAE;YACxC,WAAW,EAAE,mBAAmB;YAChC,eAAe,EAAE,yBAAyB;YAC1C,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,EAAE;SACX;KACF;IACD,YAAY,EAAE;QACZ,aAAa,EAAE,SAAS;QACxB,eAAe,EAAE,WAAW;QAC5B,QAAQ,EAAE,uBAAuB;KAClC;IACD,qBAAqB,EAAE,SAAS;IAChC,MAAM,EAAE,EAAE;IACV,iBAAiB,EAAE,SAAS;IAC5B,mBAAmB,EAAE,SAAS;IAC9B,eAAe,EAAE,SAAS;IAC1B,kBAAkB,EAAE,CAAC;CACtB,CAAC;AAEF,MAAM,CAAC,MAAM,+BAA+B,GAAwB;IAClE,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,2BAA2B;CACjD,CAAC","sourcesContent":["import type { Hex } from '@metamask/utils';\nimport { ZeroAddress } from 'ethers';\n\nimport { CHAIN_IDS } from './chains';\nimport type { BridgeControllerState } from '../types';\nimport { BridgeFeatureFlagsKey } from '../types';\n\n// TODO read from feature flags\nexport const ALLOWED_BRIDGE_CHAIN_IDS = [\n CHAIN_IDS.MAINNET,\n CHAIN_IDS.BSC,\n CHAIN_IDS.POLYGON,\n CHAIN_IDS.ZKSYNC_ERA,\n CHAIN_IDS.AVALANCHE,\n CHAIN_IDS.OPTIMISM,\n CHAIN_IDS.ARBITRUM,\n CHAIN_IDS.LINEA_MAINNET,\n CHAIN_IDS.BASE,\n];\n\nexport type AllowedBridgeChainIds = (typeof ALLOWED_BRIDGE_CHAIN_IDS)[number];\n\nexport const BRIDGE_DEV_API_BASE_URL = 'https://bridge.dev-api.cx.metamask.io';\nexport const BRIDGE_PROD_API_BASE_URL = 'https://bridge.api.cx.metamask.io';\n\nexport enum BridgeClientId {\n EXTENSION = 'extension',\n MOBILE = 'mobile',\n}\n\nexport const ETH_USDT_ADDRESS = '0xdac17f958d2ee523a2206206994597c13d831ec7';\nexport const METABRIDGE_ETHEREUM_ADDRESS =\n '0x0439e60F02a8900a951603950d8D4527f400C3f1';\nexport const BRIDGE_QUOTE_MAX_ETA_SECONDS = 60 * 60; // 1 hour\nexport const BRIDGE_QUOTE_MAX_RETURN_DIFFERENCE_PERCENTAGE = 0.5; // if a quote returns in x times less return than the best quote, ignore it\n\nexport const BRIDGE_PREFERRED_GAS_ESTIMATE = 'high';\nexport const BRIDGE_DEFAULT_SLIPPAGE = 0.5;\nexport const BRIDGE_MM_FEE_RATE = 0.875;\nexport const REFRESH_INTERVAL_MS = 30 * 1000;\nexport const DEFAULT_MAX_REFRESH_COUNT = 5;\n\nexport const BRIDGE_CONTROLLER_NAME = 'BridgeController';\nexport const DEFAULT_BRIDGE_CONTROLLER_STATE: BridgeControllerState = {\n bridgeFeatureFlags: {\n [BridgeFeatureFlagsKey.EXTENSION_CONFIG]: {\n refreshRate: REFRESH_INTERVAL_MS,\n maxRefreshCount: DEFAULT_MAX_REFRESH_COUNT,\n support: false,\n chains: {},\n },\n },\n quoteRequest: {\n walletAddress: undefined,\n srcTokenAddress: ZeroAddress,\n slippage: BRIDGE_DEFAULT_SLIPPAGE,\n },\n quotesInitialLoadTime: undefined,\n quotes: [],\n quotesLastFetched: undefined,\n quotesLoadingStatus: undefined,\n quoteFetchError: undefined,\n quotesRefreshCount: 0,\n};\n\nexport const METABRIDGE_CHAIN_TO_ADDRESS_MAP: Record<Hex, string> = {\n [CHAIN_IDS.MAINNET]: METABRIDGE_ETHEREUM_ADDRESS,\n};\n"]}