@imtbl/sdk 1.4.0-alpha.2 → 1.4.1-alpha.1

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 (51) hide show
  1. package/dist/blockchain_data.js +2 -2
  2. package/dist/browser/checkout/BridgeWidget-cf957c15.js +1 -0
  3. package/dist/browser/checkout/OnRampWidget-83d73134.js +1 -0
  4. package/dist/browser/checkout/SaleWidget-ad8b7642.js +2 -0
  5. package/dist/browser/checkout/SpendingCapHero-0a0f9fd0.js +1 -0
  6. package/dist/browser/checkout/SwapWidget-7c0a1017.js +1 -0
  7. package/dist/browser/checkout/TopUpView-3b2e045d.js +1 -0
  8. package/dist/browser/checkout/WalletWidget-381ddb8f.js +1 -0
  9. package/dist/browser/checkout/{auto-track-1bf3a0ee.js → auto-track-8b6baf69.js} +1 -1
  10. package/dist/browser/checkout/balance-1493691b.js +1 -0
  11. package/dist/browser/checkout/index-1c33f972.js +1 -0
  12. package/dist/browser/checkout/{index-942c822d.js → index-287f0ec7.js} +1 -1
  13. package/dist/browser/checkout/{index-3272becd.js → index-531bae54.js} +1 -1
  14. package/dist/browser/checkout/{index-d9cfe478.js → index-696631eb.js} +9 -9
  15. package/dist/browser/checkout/{index-8562ab3b.js → index-b7b99467.js} +1 -1
  16. package/dist/browser/checkout/{index-9a5fbaa1.js → index-e7272f1c.js} +12 -12
  17. package/dist/browser/checkout/{index-6ee5fac7.js → index-feece362.js} +1 -1
  18. package/dist/browser/checkout/{index.umd-956dbfb2.js → index.umd-bcb0582f.js} +1 -1
  19. package/dist/browser/checkout/{retry-81ddd897.js → retry-86e4cf9a.js} +1 -1
  20. package/dist/browser/checkout/sdk.js +4 -4
  21. package/dist/browser/checkout/{useTransakEvents-8580b8ed.js → useTransakEvents-a01463cc.js} +2 -2
  22. package/dist/browser/checkout/widgets.js +1 -1
  23. package/dist/checkout.js +4 -4
  24. package/dist/config.js +1 -1
  25. package/dist/index.browser.js +4 -4
  26. package/dist/index.cjs +6 -6
  27. package/dist/index.js +6 -6
  28. package/dist/orderbook.js +1 -1
  29. package/dist/passport.js +3 -3
  30. package/dist/x.js +2 -2
  31. package/package.json +1 -1
  32. package/dist/browser/checkout/BridgeWidget-52ba2210.js +0 -2753
  33. package/dist/browser/checkout/BridgeWidget-fffec54f.js +0 -1
  34. package/dist/browser/checkout/OnRampWidget-04677711.js +0 -288
  35. package/dist/browser/checkout/OnRampWidget-b1c1cc52.js +0 -1
  36. package/dist/browser/checkout/SaleWidget-8b73504f.js +0 -1610
  37. package/dist/browser/checkout/SaleWidget-e9cc4cb2.js +0 -2
  38. package/dist/browser/checkout/SpendingCapHero-43c9cf8c.js +0 -9
  39. package/dist/browser/checkout/SpendingCapHero-af71a6f5.js +0 -1
  40. package/dist/browser/checkout/SwapWidget-45ff8dfa.js +0 -1
  41. package/dist/browser/checkout/SwapWidget-e52876ac.js +0 -1461
  42. package/dist/browser/checkout/TopUpView-590c2c4c.js +0 -365
  43. package/dist/browser/checkout/TopUpView-ff09517a.js +0 -1
  44. package/dist/browser/checkout/WalletWidget-9c4c62e4.js +0 -760
  45. package/dist/browser/checkout/WalletWidget-ed0bd774.js +0 -1
  46. package/dist/browser/checkout/balance-e5a26a9d.js +0 -1
  47. package/dist/browser/checkout/balance-e5d785aa.js +0 -182
  48. package/dist/browser/checkout/index-1405c4f4.js +0 -1
  49. package/dist/browser/checkout/index-4511315b.js +0 -5638
  50. package/dist/browser/checkout/retry-254e3478.js +0 -58
  51. package/dist/browser/checkout/useTransakEvents-54a554e5.js +0 -150
@@ -1,2753 +0,0 @@
1
- import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
- import { IMMUTABLE_API_BASE_URL, ChainId, ChainName, ChainSlug, WalletProviderName, IMTBLWidgetEvents, BridgeEventType, TokenFilterTypes, GasEstimateType, CheckoutErrorType } from '@imtbl/checkout-sdk';
3
- import { createContext, useState, useEffect, useMemo, useContext, useCallback, useRef, useReducer } from 'react';
4
- import { C as CryptoFiatContext, a as CryptoFiatActions, b as CryptoFiatProvider, T as TopUpView } from './TopUpView-590c2c4c.js';
5
- import { JsonRpcProvider } from '@ethersproject/providers';
6
- import { ad as text, aq as BridgeWidgetViews, ar as PASSPORT_URL, q as networkIcon$3, r as logoColour$2, as as networkName, u as useAnalytics, U as UserJourney, V as ViewContext, b as ViewActions, at as isMetaMaskProvider, j as isPassportProvider, au as AXELAR_SCAN_URL, x as calculateCryptoToFiat, E as EventTargetContext, l as getL1ChainId, k as getL2ChainId, av as createAndConnectToProvider, a as SimpleLayout, H as HeaderNavigation, F as FooterLogo, aw as DEFAULT_TRANSACTIONS_RETRY_POLICY, L as LoadingView, B as ButtonNavigationStyles, ax as ETH_TOKEN_SYMBOL, ay as getEthTokenImage, af as getImxTokenImage, t as tokenValueFormat, h as formatZeroAmount, m as isNativeToken, N as NATIVE, ag as DEFAULT_QUOTE_REFRESH_INTERVAL, ah as amountInputValidation, al as IMX_TOKEN_SYMBOL, S as SharedViews, aj as DEFAULT_TOKEN_DECIMALS, az as CHECKOUT_CDN_BASE_URL, A as heroBackGroundStyles, G as heroImageStyles, c as SimpleTextBody, am as FooterButton, aA as WITHDRAWAL_CLAIM_GAS_LIMIT, v as viewReducer, i as initialViewState, d as StatusView, f as StatusType, K as ErrorView } from './index-4511315b.js';
7
- import { ImmutableConfiguration } from '@imtbl/config';
8
- import { BridgeConfiguration, TokenBridge, ETH_SEPOLIA_TO_ZKEVM_TESTNET, ETH_SEPOLIA_TO_ZKEVM_DEVNET, ETH_MAINNET_TO_ZKEVM_MAINNET } from '@imtbl/bridge-sdk';
9
- import { MenuItem, Drawer, Select, Box, ShimmerBox, Body, Button, Link, Icon, EllipsizedText, Accordion, Divider, Logo, Heading, ButtCon, CloudImage, PriceDisplay, Badge } from '@biom3/react';
10
- import axios, { HttpStatusCode } from 'axios';
11
- import { r as retry, u as useInterval } from './retry-254e3478.js';
12
- import { useTranslation } from 'react-i18next';
13
- import { b as FormControlWrapper, S as SelectForm, T as TextInputForm, F as FeesBreakdown, a as TransactionRejected, g as getAllowedBalances, W as WalletApproveHero } from './balance-e5d785aa.js';
14
- import { formatUnits } from 'ethers/lib/utils';
15
- import { utils, BigNumber } from 'ethers';
16
- import { useRive, Layout, Fit } from '@rive-app/react-canvas';
17
-
18
- const CACHE_DATA_TTL = 60; // seconds
19
- /**
20
- * Checkout API class provides a client abstraction for the Checkout API.
21
- */
22
- class CheckoutApi {
23
- url;
24
- ttl;
25
- env;
26
- cacheMap;
27
- setCache(key, data) {
28
- this.cacheMap[key] = { data, ttl: new Date().getTime() + this.ttl * 1000 };
29
- }
30
- getCache(key) {
31
- const d = this.cacheMap[key];
32
- if (!d || d.ttl <= new Date().getTime())
33
- return null;
34
- return d.data;
35
- }
36
- /**
37
- * Checkout API constructor
38
- * @param env target chain
39
- * @param ttl cache TTL
40
- */
41
- constructor(params) {
42
- this.env = params.env;
43
- this.url = `${IMMUTABLE_API_BASE_URL[this.env]}/checkout`;
44
- this.cacheMap = {};
45
- this.ttl = params.ttl !== undefined ? params.ttl : CACHE_DATA_TTL;
46
- }
47
- /**
48
- * isHttpError verifies if the error is a HTTP error
49
- * @param err error to evaluate
50
- */
51
- static isHttpError = (err) => 'code' in err;
52
- /**
53
- * getTransactions fetches a list of blockchain transactions.
54
- * @param txType transaction type
55
- * @param fromAddress transactions executed from address
56
- */
57
- async getTransactions(params) {
58
- const { txType, fromAddress } = params;
59
- try {
60
- const url = `${this.url}/v1/transactions?from_address=${fromAddress}&tx_type=${txType}`;
61
- // Cache response data to prevent unnecessary requests
62
- const cached = this.getCache(url);
63
- if (cached)
64
- return Promise.resolve(cached);
65
- const response = await axios.get(url);
66
- if (response.status >= 400) {
67
- return Promise.reject({
68
- code: response.status,
69
- message: response.statusText,
70
- });
71
- }
72
- const { data } = response;
73
- this.setCache(url, data);
74
- return Promise.resolve(data);
75
- }
76
- catch (err) {
77
- let code = HttpStatusCode.InternalServerError;
78
- let message = 'InternalServerError';
79
- if (axios.isAxiosError(err)) {
80
- code = err.response?.status || code;
81
- message = err.message;
82
- }
83
- return Promise.reject({ code, message });
84
- }
85
- }
86
- }
87
-
88
- /* eslint-disable @typescript-eslint/naming-convention */
89
- var TransactionType;
90
- (function (TransactionType) {
91
- TransactionType["BRIDGE"] = "bridge";
92
- })(TransactionType || (TransactionType = {}));
93
- const TransactionStatus = {
94
- IN_PROGRESS: 'in_progress',
95
- WITHDRAWAL_PENDING: 'withdrawal_pending',
96
- };
97
-
98
- function getChainNameById(chainId) {
99
- switch (chainId) {
100
- case ChainId.ETHEREUM: return ChainName.ETHEREUM;
101
- case ChainId.IMTBL_ZKEVM_TESTNET: return ChainName.IMTBL_ZKEVM_TESTNET;
102
- case ChainId.IMTBL_ZKEVM_MAINNET: return ChainName.IMTBL_ZKEVM_MAINNET;
103
- case ChainId.IMTBL_ZKEVM_DEVNET: return ChainName.IMTBL_ZKEVM_DEVNET;
104
- case ChainId.SEPOLIA: return ChainName.SEPOLIA;
105
- default: return '';
106
- }
107
- }
108
- function getChainSlugById(chainId) {
109
- switch (chainId) {
110
- case ChainId.ETHEREUM: return ChainSlug.ETHEREUM;
111
- case ChainId.IMTBL_ZKEVM_TESTNET: return ChainSlug.IMTBL_ZKEVM_TESTNET;
112
- case ChainId.IMTBL_ZKEVM_MAINNET: return ChainSlug.IMTBL_ZKEVM_MAINNET;
113
- case ChainId.IMTBL_ZKEVM_DEVNET: return ChainSlug.IMTBL_ZKEVM_DEVNET;
114
- case ChainId.SEPOLIA: return ChainSlug.SEPOLIA;
115
- default: return '';
116
- }
117
- }
118
- function getChainIdBySlug(chainSlug) {
119
- switch (chainSlug) {
120
- case ChainSlug.ETHEREUM: return ChainId.ETHEREUM;
121
- case ChainSlug.IMTBL_ZKEVM_TESTNET: return ChainId.IMTBL_ZKEVM_TESTNET;
122
- case ChainSlug.IMTBL_ZKEVM_MAINNET: return ChainId.IMTBL_ZKEVM_MAINNET;
123
- case ChainSlug.IMTBL_ZKEVM_DEVNET: return ChainId.IMTBL_ZKEVM_DEVNET;
124
- case ChainSlug.SEPOLIA: return ChainId.SEPOLIA;
125
- default: return 0;
126
- }
127
- }
128
-
129
- const initialBridgeState = {
130
- web3Provider: null,
131
- walletProviderName: null,
132
- from: null,
133
- to: null,
134
- tokenBridge: null,
135
- tokenBalances: [],
136
- allowedTokens: [],
137
- token: null,
138
- amount: '0',
139
- };
140
- var BridgeActions;
141
- (function (BridgeActions) {
142
- BridgeActions["SET_WALLETS_AND_NETWORKS"] = "SET_WALLETS_AND_NETWORKS";
143
- BridgeActions["SET_WALLET_PROVIDER_NAME"] = "SET_WALLET_PROVIDER_NAME";
144
- BridgeActions["SET_PROVIDER"] = "SET_PROVIDER";
145
- BridgeActions["SET_TOKEN_BRIDGE"] = "SET_TOKEN_BRIDGE";
146
- BridgeActions["SET_TOKEN_BALANCES"] = "SET_TOKEN_BALANCES";
147
- BridgeActions["SET_ALLOWED_TOKENS"] = "SET_ALLOWED_TOKENS";
148
- BridgeActions["SET_TOKEN_AND_AMOUNT"] = "SET_TOKEN_AND_AMOUNT";
149
- })(BridgeActions || (BridgeActions = {}));
150
- // eslint-disable-next-line @typescript-eslint/naming-convention
151
- const BridgeContext = createContext({
152
- bridgeState: { ...initialBridgeState, checkout: {} },
153
- bridgeDispatch: () => { },
154
- });
155
- BridgeContext.displayName = 'BridgeContext'; // help with debugging Context in browser
156
- const bridgeReducer = (state, action) => {
157
- switch (action.payload.type) {
158
- case BridgeActions.SET_WALLETS_AND_NETWORKS:
159
- return {
160
- ...state,
161
- from: action.payload.from,
162
- to: action.payload.to,
163
- };
164
- case BridgeActions.SET_WALLET_PROVIDER_NAME:
165
- return {
166
- ...state,
167
- walletProviderName: action.payload.walletProviderName,
168
- };
169
- case BridgeActions.SET_PROVIDER:
170
- return {
171
- ...state,
172
- web3Provider: action.payload.web3Provider,
173
- };
174
- case BridgeActions.SET_TOKEN_BRIDGE:
175
- return {
176
- ...state,
177
- tokenBridge: action.payload.tokenBridge,
178
- };
179
- case BridgeActions.SET_TOKEN_BALANCES:
180
- return {
181
- ...state,
182
- tokenBalances: action.payload.tokenBalances,
183
- };
184
- case BridgeActions.SET_ALLOWED_TOKENS:
185
- return {
186
- ...state,
187
- allowedTokens: action.payload.allowedTokens,
188
- };
189
- case BridgeActions.SET_TOKEN_AND_AMOUNT:
190
- return {
191
- ...state,
192
- token: action.payload.token,
193
- amount: action.payload.amount,
194
- };
195
- default:
196
- return state;
197
- }
198
- };
199
-
200
- function WalletItem({ testId, walletProviderName, onWalletClick, loading, }) {
201
- const { t } = useTranslation();
202
- const [showLoadingIcon, setShowLoadingIcon] = useState(false);
203
- const logo = {
204
- [WalletProviderName.PASSPORT]: 'PassportSymbolOutlined',
205
- [WalletProviderName.METAMASK]: 'MetaMaskSymbol',
206
- };
207
- return (jsxs(MenuItem, { testId: `${testId}-wallet-list-${walletProviderName}`, size: "medium", emphasized: true, onClick: async () => {
208
- if (loading)
209
- return;
210
- setShowLoadingIcon(true);
211
- // let the parent handle errors
212
- try {
213
- await onWalletClick(walletProviderName);
214
- }
215
- finally {
216
- setShowLoadingIcon(false);
217
- }
218
- }, children: [jsx(MenuItem.FramedLogo, { logo: logo[walletProviderName], sx: { backgroundColor: 'base.color.translucent.standard.200' } }), jsx(MenuItem.Label, { size: "medium", children: t(`wallets.${walletProviderName}.heading`) }), showLoadingIcon && (jsx(MenuItem.StatefulButtCon, { state: "loading", icon: "Loading" }))] }));
219
- }
220
-
221
- const walletItemListStyles = {
222
- display: 'flex',
223
- flexDirection: 'column',
224
- gap: 'base.spacing.x1',
225
- };
226
-
227
- function WalletDrawer({ testId, drawerText, walletOptions, showWalletSelectorTarget, showDrawer, setShowDrawer, onWalletItemClick, }) {
228
- const [walletItemLoading, setWalletItemLoading] = useState(false);
229
- const { heading, defaultText } = drawerText;
230
- const handleWalletItemClick = async (name) => {
231
- setWalletItemLoading(true);
232
- try {
233
- await onWalletItemClick(name);
234
- }
235
- catch (err) {
236
- // eslint-disable-next-line no-console
237
- console.error(err);
238
- }
239
- finally {
240
- setWalletItemLoading(false);
241
- }
242
- };
243
- return (jsxs(Drawer, { headerBarTitle: heading, size: "full", onCloseDrawer: () => {
244
- if (walletItemLoading)
245
- return;
246
- setShowDrawer(false);
247
- }, visible: showDrawer, children: [showWalletSelectorTarget
248
- && (jsx(Drawer.Target, { children: jsx(FormControlWrapper, { testId: `${testId}-wallet-form-control`, textAlign: "left", children: jsx(Select, { testId: `${testId}-wallet-select`, defaultLabel: defaultText ?? '', size: "large", targetClickOveride: () => setShowDrawer(true) }) }) })), jsx(Drawer.Content, { sx: walletItemListStyles, children: walletOptions.map((walletProviderName) => (jsx(WalletItem, { testId: testId, loading: walletItemLoading, walletProviderName: walletProviderName, onWalletClick: handleWalletItemClick }, walletProviderName))) })] }));
249
- }
250
-
251
- const sendBridgeTransactionSentEvent = (eventTarget, transactionHash) => {
252
- const successEvent = new CustomEvent(IMTBLWidgetEvents.IMTBL_BRIDGE_WIDGET_EVENT, {
253
- detail: {
254
- type: BridgeEventType.TRANSACTION_SENT,
255
- data: {
256
- transactionHash,
257
- },
258
- },
259
- });
260
- // eslint-disable-next-line no-console
261
- console.log('bridge success ', eventTarget, successEvent);
262
- if (eventTarget !== undefined)
263
- eventTarget.dispatchEvent(successEvent);
264
- };
265
- const sendBridgeFailedEvent = (eventTarget, reason) => {
266
- const failedEvent = new CustomEvent(IMTBLWidgetEvents.IMTBL_BRIDGE_WIDGET_EVENT, {
267
- detail: {
268
- type: BridgeEventType.FAILURE,
269
- data: {
270
- reason,
271
- timestamp: new Date().getTime(),
272
- },
273
- },
274
- });
275
- // eslint-disable-next-line no-console
276
- console.log('bridge failed ', eventTarget, failedEvent);
277
- if (eventTarget !== undefined)
278
- eventTarget.dispatchEvent(failedEvent);
279
- };
280
- function sendBridgeWidgetCloseEvent(eventTarget) {
281
- const closeWidgetEvent = new CustomEvent(IMTBLWidgetEvents.IMTBL_BRIDGE_WIDGET_EVENT, {
282
- detail: {
283
- type: BridgeEventType.CLOSE_WIDGET,
284
- data: {},
285
- },
286
- });
287
- // eslint-disable-next-line no-console
288
- console.log('bridge close ', eventTarget, closeWidgetEvent);
289
- if (eventTarget !== undefined)
290
- eventTarget.dispatchEvent(closeWidgetEvent);
291
- }
292
- const sendBridgeClaimWithdrawalSuccessEvent = (eventTarget, transactionHash) => {
293
- const successEvent = new CustomEvent(IMTBLWidgetEvents.IMTBL_BRIDGE_WIDGET_EVENT, {
294
- detail: {
295
- type: BridgeEventType.CLAIM_WITHDRAWAL_SUCCESS,
296
- data: {
297
- transactionHash,
298
- },
299
- },
300
- });
301
- // eslint-disable-next-line no-console
302
- console.log('bridge claim withdrawal success event:', eventTarget, successEvent);
303
- if (eventTarget !== undefined)
304
- eventTarget.dispatchEvent(successEvent);
305
- };
306
- const sendBridgeClaimWithdrawalFailedEvent = (eventTarget, transactionHash, reason) => {
307
- const failedEvent = new CustomEvent(IMTBLWidgetEvents.IMTBL_BRIDGE_WIDGET_EVENT, {
308
- detail: {
309
- type: BridgeEventType.CLAIM_WITHDRAWAL_FAILURE,
310
- data: {
311
- transactionHash,
312
- reason,
313
- timestamp: new Date().getTime(),
314
- },
315
- },
316
- });
317
- // eslint-disable-next-line no-console
318
- console.log('bridge claim withdrawal failed event:', eventTarget, failedEvent);
319
- if (eventTarget !== undefined)
320
- eventTarget.dispatchEvent(failedEvent);
321
- };
322
-
323
- function Shimmer() {
324
- return (jsxs(Box, { sx: {
325
- pt: 'base.spacing.x5',
326
- px: 'base.spacing.x4',
327
- }, children: [jsx(ShimmerBox, { sx: {
328
- h: 'base.spacing.x4',
329
- w: 'base.spacing.x32',
330
- mb: 'base.spacing.x2',
331
- mt: 'base.spacing.x2',
332
- } }), jsx(Box, { sx: { mb: 'base.spacing.x5' }, children: jsx(MenuItem, { shimmer: true, emphasized: true, size: "small" }) }), jsx(Box, { sx: { mb: 'base.spacing.x5' }, children: jsx(MenuItem, { shimmer: true, emphasized: true, size: "small" }) }), jsx(Box, { sx: { mb: 'base.spacing.x5' }, children: jsx(MenuItem, { shimmer: true, emphasized: true, size: "small" }) })] }));
333
- }
334
-
335
- const transactionsContainerStyle = {
336
- px: 'base.spacing.x4',
337
- display: 'flex',
338
- flexDirection: 'column',
339
- height: '100%',
340
- };
341
- const transactionsListContainerStyle = {
342
- flexGrow: '1',
343
- flexShrink: '0',
344
- flexBasis: '0',
345
- };
346
- const supportBoxContainerStyle = {
347
- flexGrow: '0',
348
- flexShrink: '1',
349
- mt: 'base.spacing.x2',
350
- };
351
-
352
- const containerStyle = {
353
- bg: 'base.color.translucent.emphasis.100',
354
- borderRadius: 'base.borderRadius.x4',
355
- display: 'flex',
356
- alignItems: 'center',
357
- justifyContent: 'center',
358
- flexDirection: 'column',
359
- height: '100%',
360
- px: 'base.spacing.x5',
361
- };
362
-
363
- function EmptyStateNotConnected({ openWalletDrawer }) {
364
- const { t } = useTranslation();
365
- return (jsxs(Box, { sx: containerStyle, children: [jsx(Body, { sx: { mb: 'base.spacing.x8' }, children: t('views.TRANSACTIONS.status.emptyState.notConnected.body') }), jsx(Button, { variant: "secondary", size: "medium", testId: "transactions-connect-wallet-button", onClick: openWalletDrawer, children: t('views.TRANSACTIONS.status.emptyState.notConnected.buttonText') })] }));
366
- }
367
-
368
- const supportMessageBoxStyle = {
369
- backgroundColor: 'base.color.neutral.800',
370
- px: 'base.spacing.x4',
371
- p: 'base.spacing.x5',
372
- borderRadius: 'base.borderRadius.x6',
373
- };
374
- const bodyStyle = {
375
- color: 'base.color.text.secondary',
376
- };
377
-
378
- function SupportMessage({ checkout, isPassport, }) {
379
- const { support: { body1, body2, body3, supportLink, passport, }, } = text.views[BridgeWidgetViews.TRANSACTIONS];
380
- const [passportLink, setPassportLink] = useState('');
381
- useEffect(() => {
382
- if (!checkout)
383
- return;
384
- setPassportLink(PASSPORT_URL[checkout.config.environment]);
385
- }, [checkout]);
386
- return (jsx(Box, { sx: supportMessageBoxStyle, children: jsxs(Box, { sx: {
387
- display: 'flex',
388
- flexDirection: 'column',
389
- }, children: [jsxs(Box, { children: [jsx(Body, { size: "small", children: body1 }), jsxs(Body, { size: "small", sx: bodyStyle, children: [body2, jsx(Link, { size: "small", rc: jsx("a", { target: "_blank", href: supportLink, rel: "noreferrer" }), children: body3 })] })] }), isPassport && (jsxs(Body, { size: "small", sx: bodyStyle, children: [passport.body1, ' ', jsx(Link, { size: "small", rc: jsx("a", { target: "_blank", href: passportLink, rel: "noreferrer" }), children: passport.body2 })] }))] }) }));
390
- }
391
-
392
- const containerStyles$4 = {
393
- display: 'flex',
394
- flexDirection: 'column',
395
- borderRadius: 'base.borderRadius.x4',
396
- bg: 'base.color.translucent.emphasis.100',
397
- };
398
- const actionsContainerStyles = {
399
- p: 'base.spacing.x3',
400
- d: 'flex',
401
- justifyContent: 'space-between',
402
- position: 'relative',
403
- };
404
- const actionsLayoutStyles = {
405
- display: 'flex',
406
- flexGrow: '1',
407
- alignItems: 'center',
408
- gap: 'base.spacing.x2',
409
- };
410
-
411
- function TransactionDetails({ transaction }) {
412
- const fromChain = getChainIdBySlug(transaction.details.from_chain);
413
- const toChain = getChainIdBySlug(transaction.details.to_chain);
414
- return (jsxs(Box, { sx: {
415
- display: 'flex',
416
- px: 'base.spacing.x4',
417
- gap: 'base.spacing.x2',
418
- }, children: [jsx(Icon, { icon: networkIcon$3[fromChain], sx: {
419
- w: 'base.icon.size.250',
420
- fill: logoColour$2[fromChain],
421
- }, variant: "bold" }), jsxs(Box, { sx: {
422
- display: 'flex',
423
- flexDirection: 'column',
424
- flexGrow: '1',
425
- }, children: [jsx(Body, { size: "xxSmall", sx: { color: 'base.color.translucent.standard.900' }, children: networkName[fromChain] }), jsx(EllipsizedText, { size: "xxSmall", sx: { color: 'base.color.translucent.standard.600' }, text: transaction.details.from_address })] }), jsx(Box, { sx: { flexGrow: '1' } }), jsx(Icon, { icon: "ArrowForward", sx: {
426
- w: 'base.icon.size.250',
427
- fill: 'base.color.brand.4',
428
- } }), jsx(Box, { sx: { flexGrow: '1' } }), jsx(Icon, { icon: networkIcon$3[toChain], sx: {
429
- w: 'base.icon.size.250',
430
- fill: logoColour$2[toChain],
431
- }, variant: "bold" }), jsxs(Box, { sx: {
432
- display: 'flex',
433
- flexDirection: 'column',
434
- flexGrow: '1',
435
- }, children: [jsx(Body, { size: "xxSmall", sx: { color: 'base.color.translucent.standard.900' }, children: networkName[toChain] }), jsx(EllipsizedText, { size: "xxSmall", sx: { color: 'base.color.translucent.standard.600' }, text: transaction.details.to_address })] })] }));
436
- }
437
-
438
- function TransactionItem({ label, details, transaction, fiatAmount, amount, }) {
439
- const { track } = useAnalytics();
440
- const txnDetailsLink = useMemo(() => `${details.link}${details.hash}`, [details]);
441
- const handleDetailsLinkClick = (event, linkDetail) => {
442
- event.stopPropagation(); // prevent expanding accordian
443
- track({
444
- userJourney: UserJourney.BRIDGE,
445
- screen: 'TransactionItem',
446
- control: 'Details',
447
- controlType: 'Link',
448
- extras: {
449
- linkDetail,
450
- },
451
- });
452
- };
453
- return (jsx(Box, { testId: `transaction-item-${transaction.blockchain_metadata.transaction_hash}`, sx: containerStyles$4, children: jsxs(Accordion, { chevronSide: "right", sx: {
454
- button: {
455
- p: 'base.spacing.x1',
456
- },
457
- article: {
458
- pr: 'base.spacing.x10',
459
- },
460
- }, onExpandChange: (expanded) => expanded
461
- && track({
462
- userJourney: UserJourney.BRIDGE,
463
- screen: 'TransactionItem',
464
- control: 'Accordion',
465
- controlType: 'Button',
466
- }), children: [jsx(Accordion.TargetLeftSlot, { sx: { pr: 'base.spacing.x2' }, children: jsxs(MenuItem, { size: "xSmall", children: [jsx(MenuItem.FramedIcon, { icon: "Coins", circularFrame: true }), jsx(MenuItem.Label, { children: label }), jsx(MenuItem.Caption, { children: jsx(Link, { size: "xSmall", rc: (jsx("a", { target: "_blank", href: txnDetailsLink, rel: "noreferrer", onClick: (e) => handleDetailsLinkClick(e, details) })), children: details.text }) }), jsx(MenuItem.PriceDisplay, { fiatAmount: fiatAmount, price: amount })] }) }), jsxs(Accordion.ExpandedContent, { sx: {
467
- pr: '0',
468
- pl: '0',
469
- mb: 'base.spacing.x3',
470
- gap: '0',
471
- }, children: [jsx(Divider, { size: "xSmall", sx: {
472
- px: 'base.spacing.x2',
473
- } }), jsx(TransactionDetails, { transaction: transaction })] })] }) }));
474
- }
475
-
476
- const transactionsListStyle = (showPassportLink) => {
477
- let height = 440;
478
- if (showPassportLink) {
479
- height -= 20;
480
- }
481
- return {
482
- backgroundColor: 'base.color.neutral.800',
483
- px: 'base.spacing.x4',
484
- pt: 'base.spacing.x5',
485
- pb: 'base.spacing.x4',
486
- borderRadius: 'base.borderRadius.x6',
487
- h: `${height}px`,
488
- w: '100%',
489
- overflowY: 'scroll',
490
- };
491
- };
492
- const containerStyles$3 = {
493
- borderRadius: 'base.borderRadius.x4',
494
- display: 'flex',
495
- flexDirection: 'column',
496
- gap: 'base.spacing.x5',
497
- };
498
-
499
- function TransactionItemWithdrawPending({ label, transaction, fiatAmount, amount, }) {
500
- const { viewDispatch } = useContext(ViewContext);
501
- const { track } = useAnalytics();
502
- const translation = useTranslation();
503
- const dateNowUnixMs = useMemo(() => new Date().getTime(), []);
504
- const withdrawalReadyDate = useMemo(() => (transaction.details.current_status.withdrawal_ready_at
505
- ? new Date(transaction.details.current_status.withdrawal_ready_at)
506
- : undefined), [transaction]);
507
- const requiresWithdrawalClaim = transaction.details.current_status.status === TransactionStatus.WITHDRAWAL_PENDING;
508
- const relativeTimeFormat = new Intl.RelativeTimeFormat(translation[1].language || 'en', { numeric: 'auto' });
509
- const delayTimeString = useMemo(() => {
510
- if (!requiresWithdrawalClaim || withdrawalReadyDate === undefined)
511
- return '';
512
- const timeDiffMins = (withdrawalReadyDate.getTime() - dateNowUnixMs) / (60 * 1000);
513
- if (timeDiffMins <= 1)
514
- return 'in 1 minute';
515
- if (timeDiffMins < 60) {
516
- return relativeTimeFormat.format(Math.ceil(timeDiffMins), 'minute');
517
- }
518
- const timeDiffHours = timeDiffMins / 60; // hours
519
- if (timeDiffMins < 60 * 24) {
520
- return relativeTimeFormat.format(Math.ceil(timeDiffHours), 'hour');
521
- }
522
- const timeDiffDays = timeDiffHours / 24; // days
523
- return relativeTimeFormat.format(Math.ceil(timeDiffDays), 'day');
524
- }, [dateNowUnixMs, translation[1].language]);
525
- const withdrawalReadyToClaim = withdrawalReadyDate ? withdrawalReadyDate.getTime() < dateNowUnixMs : false;
526
- const actionMessage = useMemo(() => (withdrawalReadyToClaim === true
527
- ? translation.t('views.TRANSACTIONS.status.withdrawalPending.withdrawalReadyText')
528
- : `${translation.t('views.TRANSACTIONS.status.withdrawalPending.withdrawalDelayText')} ${delayTimeString}`), [delayTimeString, translation[1].language]);
529
- const handleWithdrawalClaimClick = () => {
530
- viewDispatch({
531
- payload: {
532
- type: ViewActions.UPDATE_VIEW,
533
- view: {
534
- type: BridgeWidgetViews.CLAIM_WITHDRAWAL,
535
- transaction,
536
- },
537
- },
538
- });
539
- };
540
- return (jsxs(Box, { testId: `transaction-item-${transaction.blockchain_metadata.transaction_hash}`, sx: containerStyles$4, children: [requiresWithdrawalClaim && (jsxs(Fragment, { children: [jsxs(Box, { sx: actionsContainerStyles, children: [jsxs(Box, { sx: actionsLayoutStyles, children: [jsx(Icon, { icon: "Alert", variant: "bold", sx: {
541
- fill: withdrawalReadyToClaim
542
- ? 'base.color.status.fatal.bright'
543
- : 'base.color.status.attention.bright',
544
- w: 'base.icon.size.200',
545
- } }), jsx(Body, { testId: `transaction-item-${transaction.blockchain_metadata.transaction_hash}-action-message`, size: "xSmall", sx: { color: 'base.color.text.secondary' }, children: actionMessage })] }), requiresWithdrawalClaim && withdrawalReadyToClaim && (jsx(Button, { testId: `transaction-item-${transaction.blockchain_metadata.transaction_hash}-action-button`, variant: "primary", size: "small", onClick: handleWithdrawalClaimClick, children: translation.t('views.TRANSACTIONS.status.withdrawalPending.actionButtonText') }))] }), jsx(Divider, { size: "small", sx: { color: 'base.color.translucent.emphasis.300', opacity: 0.1 } })] })), jsxs(Accordion, { chevronSide: "right", sx: {
546
- button: {
547
- p: 'base.spacing.x1',
548
- },
549
- article: {
550
- pr: 'base.spacing.x10',
551
- },
552
- borderTopRightRadius: '0',
553
- borderTopLeftRadius: '0',
554
- }, onExpandChange: (expanded) => expanded
555
- && track({
556
- userJourney: UserJourney.BRIDGE,
557
- screen: 'TransactionItem',
558
- control: 'Accordion',
559
- controlType: 'Button',
560
- }), children: [jsx(Accordion.TargetLeftSlot, { sx: { pr: 'base.spacing.x2' }, children: jsxs(MenuItem, { size: "xSmall", children: [jsx(MenuItem.FramedIcon, { icon: "Coins", circularFrame: true }), jsx(MenuItem.Label, { children: label }), jsx(MenuItem.Caption, { children: translation.t('views.TRANSACTIONS.status.withdrawalPending.caption') }), jsx(MenuItem.PriceDisplay, { fiatAmount: fiatAmount, price: amount })] }) }), jsxs(Accordion.ExpandedContent, { sx: {
561
- pr: '0',
562
- pl: '0',
563
- mb: 'base.spacing.x3',
564
- gap: '0',
565
- }, children: [jsx(Divider, { size: "xSmall", sx: {
566
- px: 'base.spacing.x2',
567
- } }), jsx(TransactionDetails, { transaction: transaction })] })] })] }));
568
- }
569
-
570
- const headingStyles = {
571
- display: 'flex',
572
- flexDirection: 'row',
573
- justifyContent: 'space-between',
574
- alignItems: 'center',
575
- p: 'base.spacing.x2',
576
- pb: 'base.spacing.x4',
577
- };
578
-
579
- function ChangeWallet({ onChangeWalletClick, }) {
580
- const { t } = useTranslation();
581
- const { bridgeState: { from } } = useContext(BridgeContext);
582
- const { track } = useAnalytics();
583
- const walletAddress = from?.walletAddress || '';
584
- const isMetaMask = isMetaMaskProvider(from?.web3Provider);
585
- const isPassport = isPassportProvider(from?.web3Provider);
586
- const handleChangeWalletClick = () => {
587
- track({
588
- userJourney: UserJourney.BRIDGE,
589
- screen: BridgeWidgetViews.TRANSACTIONS,
590
- controlType: 'Button',
591
- control: 'Pressed',
592
- });
593
- onChangeWalletClick();
594
- };
595
- return (jsxs(Box, { sx: headingStyles, children: [jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 'base.spacing.x1' }, children: [isMetaMask && !isPassport && jsx(Logo, { logo: "MetaMaskSymbol", sx: { width: 'base.icon.size.400' } }), !isMetaMask && isPassport && (jsx(Logo, { logo: "PassportSymbolOutlined", sx: {
596
- width: 'base.icon.size.400',
597
- pr: 'base.spacing.x1',
598
- } })), jsx(EllipsizedText, { leftSideLength: 6, rightSideLength: 4, text: walletAddress })] }), jsx(Button, { size: "small", variant: "tertiary", onClick: handleChangeWalletClick, children: t('views.TRANSACTIONS.changeWallet.buttonText') })] }));
599
- }
600
-
601
- function TransactionList({ checkout, transactions, knownTokenMap, isPassport, changeWallet, }) {
602
- const { cryptoFiatState } = useContext(CryptoFiatContext);
603
- const { t } = useTranslation();
604
- const { fiatPricePrefix, } = text.views[BridgeWidgetViews.TRANSACTIONS];
605
- const [link, setLink] = useState('');
606
- useEffect(() => {
607
- if (!checkout)
608
- return;
609
- setLink(AXELAR_SCAN_URL[checkout.config.environment]);
610
- }, [checkout]);
611
- const sortWithdrawalPendingFirst = useCallback((txnA, txnB) => {
612
- if (txnA.details.current_status.status === TransactionStatus.WITHDRAWAL_PENDING
613
- && txnB.details.current_status.status !== TransactionStatus.WITHDRAWAL_PENDING)
614
- return -1;
615
- if (txnA.details.current_status.status === txnB.details.current_status.status)
616
- return 0;
617
- return 1;
618
- }, []);
619
- return (jsxs(Box, { sx: transactionsListStyle(isPassport), children: [jsx(ChangeWallet, { onChangeWalletClick: changeWallet }), jsx(Box, { testId: "move-transaction-list", sx: containerStyles$3, children: transactions
620
- .sort(sortWithdrawalPendingFirst)
621
- .map((transaction) => {
622
- const hash = transaction.blockchain_metadata.transaction_hash;
623
- const tokens = knownTokenMap[transaction.details.from_chain];
624
- const token = tokens[transaction.details.from_token_address.toLowerCase()];
625
- const amount = formatUnits(transaction.details.amount, token.decimals);
626
- const fiat = calculateCryptoToFiat(amount, token.symbol, cryptoFiatState.conversions);
627
- if (transaction.details.current_status.status === TransactionStatus.WITHDRAWAL_PENDING) {
628
- return (jsx(TransactionItemWithdrawPending, { label: token.name, transaction: transaction, fiatAmount: `${fiatPricePrefix}${fiat}`, amount: amount }, hash));
629
- }
630
- return (jsx(TransactionItem, { label: token.name, details: { text: t('views.TRANSACTIONS.status.inProgress.stepInfo'), link, hash }, transaction: transaction, fiatAmount: `${fiatPricePrefix}${fiat}`, amount: amount }, hash));
631
- }) })] }));
632
- }
633
-
634
- const containerStyles$2 = {
635
- backgroundColor: 'base.color.neutral.800',
636
- px: 'base.spacing.x4',
637
- pt: 'base.spacing.x5',
638
- pb: 'base.spacing.x4',
639
- borderRadius: 'base.borderRadius.x6',
640
- h: '100%',
641
- w: '100%',
642
- display: 'flex',
643
- flexDirection: 'column',
644
- };
645
- const noTransactionsContainerStyle = {
646
- display: 'flex',
647
- flexDirection: 'column',
648
- justifyContent: 'center',
649
- alignItems: 'center',
650
- padding: 'base.spacing.x5',
651
- flex: 1,
652
- };
653
- const noTransactionsBodyStyle = {
654
- mb: 'base.spacing.x8',
655
- color: 'base.color.text.secondary',
656
- };
657
- const passportBodyStyle = {
658
- color: 'base.color.text.secondary',
659
- };
660
-
661
- function NoTransactions({ checkout, isPassport, changeWallet, }) {
662
- const { page } = useAnalytics();
663
- const { t } = useTranslation();
664
- const [passportLink, setPassportLink] = useState('');
665
- useEffect(() => {
666
- if (!checkout)
667
- return;
668
- setPassportLink(PASSPORT_URL[checkout.config.environment]);
669
- }, [checkout]);
670
- useEffect(() => {
671
- page({
672
- userJourney: UserJourney.BRIDGE,
673
- screen: 'NoTransactions',
674
- });
675
- }, []);
676
- return (jsxs(Box, { sx: containerStyles$2, children: [jsx(ChangeWallet, { onChangeWalletClick: changeWallet }), jsxs(Box, { sx: noTransactionsContainerStyle, children: [jsx(Body, { size: "small", sx: noTransactionsBodyStyle, children: t('views.TRANSACTIONS.status.noTransactions.body') }), isPassport && (jsxs(Body, { size: "small", sx: passportBodyStyle, children: [t('views.TRANSACTIONS.status.noTransactions.passport.body'), ' ', jsx(Link, { size: "small", rc: jsx("a", { target: "_blank", href: passportLink, rel: "noreferrer" }), children: t('views.TRANSACTIONS.status.noTransactions.passport.link') })] }))] })] }));
677
- }
678
-
679
- function Transactions({ onBackButtonClick }) {
680
- const { eventTargetState: { eventTarget } } = useContext(EventTargetContext);
681
- const { cryptoFiatDispatch } = useContext(CryptoFiatContext);
682
- const { bridgeDispatch, bridgeState: { checkout, from } } = useContext(BridgeContext);
683
- const { page } = useAnalytics();
684
- const { t } = useTranslation();
685
- const { track } = useAnalytics();
686
- const [loading, setLoading] = useState(true);
687
- const [knownTokenMap, setKnownTokenMap] = useState(undefined);
688
- const [txs, setTxs] = useState([]);
689
- const [showWalletDrawer, setShowWalletDrawer] = useState(false);
690
- const isPassport = isPassportProvider(from?.web3Provider);
691
- // Fetch the tokens for the root chain using the allowed tokens.
692
- // In case this list does not have all the tokens, there is logic
693
- // built into the <TransactionsList /> component to fetch the
694
- // the missing data.
695
- const rootChainTokensHashmap = useCallback(async () => {
696
- if (!checkout)
697
- return {};
698
- const rootChainId = getL1ChainId(checkout.config);
699
- try {
700
- const tokens = (await checkout.getTokenAllowList({ type: TokenFilterTypes.BRIDGE, chainId: rootChainId })).tokens ?? [];
701
- return tokens.reduce((out, current) => {
702
- // eslint-disable-next-line no-param-reassign
703
- out[current.address.toLowerCase()] = current;
704
- return out;
705
- }, {});
706
- }
707
- catch (e) {
708
- // eslint-disable-next-line no-console
709
- console.error(e);
710
- return [];
711
- }
712
- }, [checkout]);
713
- // Fetch the tokens for the root chain using the user balances tokens.
714
- // In case this list does not have all the tokens, there is logic
715
- // built into the <TransactionsList /> component to fetch the
716
- // the missing data.
717
- const childChainTokensHashmap = useCallback(async () => {
718
- if (!from?.web3Provider)
719
- return {};
720
- if (!from?.walletAddress)
721
- return {};
722
- const childChainId = getL2ChainId(checkout.config);
723
- try {
724
- const data = await checkout.getAllBalances({
725
- provider: from?.web3Provider,
726
- walletAddress: from?.walletAddress,
727
- chainId: childChainId,
728
- });
729
- return data.balances.reduce((out, current) => {
730
- // eslint-disable-next-line no-param-reassign
731
- out[current.token.address.toLowerCase()] = current.token;
732
- return out;
733
- }, {});
734
- }
735
- catch (e) {
736
- // eslint-disable-next-line no-console
737
- console.error(e);
738
- return [];
739
- }
740
- }, [checkout, from]);
741
- const updateAndConnectProvider = useCallback(async (walletProviderName) => {
742
- track({
743
- userJourney: UserJourney.BRIDGE,
744
- screen: 'EmptyStateNotConnected',
745
- control: 'WalletProvider',
746
- controlType: 'Select',
747
- extras: {
748
- walletProviderName,
749
- },
750
- });
751
- try {
752
- const localProvider = await createAndConnectToProvider(checkout, walletProviderName, true);
753
- const network = await localProvider.getNetwork();
754
- const address = await localProvider?.getSigner().getAddress() ?? '';
755
- setTxs([]);
756
- bridgeDispatch({
757
- payload: {
758
- type: BridgeActions.SET_WALLETS_AND_NETWORKS,
759
- from: {
760
- web3Provider: localProvider,
761
- walletAddress: address.toLowerCase(),
762
- network: network.chainId,
763
- },
764
- to: null,
765
- },
766
- });
767
- }
768
- catch (error) {
769
- // eslint-disable-next-line no-console
770
- console.error(error);
771
- }
772
- finally {
773
- setShowWalletDrawer(false);
774
- }
775
- }, [checkout, from]);
776
- const getTokensDetails = async (tokensWithChainSlug) => {
777
- const rootChainName = getChainSlugById(getL1ChainId(checkout.config));
778
- const childChainName = getChainSlugById(getL2ChainId(checkout.config));
779
- const [rootData, childData] = await Promise.all([
780
- rootChainTokensHashmap(),
781
- childChainTokensHashmap(),
782
- ]);
783
- // Fetch the data for the missing tokens: tokensWithChainSlug
784
- const missingTokens = {};
785
- Object.entries(tokensWithChainSlug).forEach(([key, value]) => {
786
- if ((tokensWithChainSlug[key] === rootChainName && !rootData[key])
787
- || (tokensWithChainSlug[key] === childChainName && !childData[key]))
788
- missingTokens[key] = value;
789
- });
790
- // Root provider is always L1
791
- const rootProvider = new JsonRpcProvider(checkout.config.networkMap.get(getL1ChainId(checkout.config))?.rpcUrls[0]);
792
- // Child provider is always L2
793
- const childProvider = new JsonRpcProvider(checkout.config.networkMap.get(getL2ChainId(checkout.config))?.rpcUrls[0]);
794
- const rootTokenInfoPromises = [];
795
- const childTokenInfoPromises = [];
796
- Object.entries(missingTokens).forEach(([tokenAddress, chainName]) => {
797
- if (chainName === rootChainName) {
798
- // Root provider
799
- rootTokenInfoPromises.push(checkout.getTokenInfo({
800
- provider: rootProvider,
801
- tokenAddress,
802
- }));
803
- }
804
- else {
805
- // child provider
806
- childTokenInfoPromises.push(checkout.getTokenInfo({
807
- provider: childProvider,
808
- tokenAddress,
809
- }));
810
- }
811
- });
812
- const rootTokenInfo = await Promise.allSettled(rootTokenInfoPromises);
813
- const childTokenInfo = await Promise.allSettled(childTokenInfoPromises);
814
- (rootTokenInfo.filter((result) => result.status === 'fulfilled'))
815
- .forEach((result) => {
816
- const resp = result;
817
- rootData[resp.value.address.toLowerCase()] = resp.value;
818
- });
819
- (childTokenInfo.filter((result) => result.status === 'fulfilled'))
820
- .forEach((result) => {
821
- const resp = result;
822
- childData[resp.value.address.toLowerCase()] = resp.value;
823
- });
824
- const allTokenSymbols = [];
825
- Object.values(rootData).forEach((token) => allTokenSymbols.push(token.symbol.toLowerCase()));
826
- Object.values(childData).forEach((token) => allTokenSymbols.push(token.symbol.toLowerCase()));
827
- cryptoFiatDispatch({
828
- payload: {
829
- type: CryptoFiatActions.SET_TOKEN_SYMBOLS,
830
- tokenSymbols: allTokenSymbols,
831
- },
832
- });
833
- return { [rootChainName]: rootData, [childChainName]: childData };
834
- };
835
- const getTransactionsDetails = useCallback(async (env, address) => {
836
- const client = new CheckoutApi({ env });
837
- return client.getTransactions({ txType: TransactionType.BRIDGE, fromAddress: address });
838
- }, []);
839
- const fetchData = useCallback(async () => {
840
- if (!from?.walletAddress)
841
- return undefined;
842
- const localTxs = await getTransactionsDetails(checkout.config.environment, from?.walletAddress);
843
- const tokensWithChainSlug = {};
844
- localTxs.result.forEach((txn) => {
845
- tokensWithChainSlug[txn.details.from_token_address] = txn.details.from_chain;
846
- });
847
- return {
848
- tokens: await getTokensDetails(tokensWithChainSlug),
849
- transactions: localTxs.result,
850
- };
851
- }, [from, getTransactionsDetails]);
852
- const walletOptions = useMemo(() => {
853
- const options = [WalletProviderName.METAMASK];
854
- if (checkout.passport) {
855
- options.push(WalletProviderName.PASSPORT);
856
- }
857
- return options;
858
- }, [checkout]);
859
- // Fetch all the data at once
860
- useEffect(() => {
861
- (async () => {
862
- setLoading(true);
863
- const data = await retry(fetchData, DEFAULT_TRANSACTIONS_RETRY_POLICY);
864
- if (!data) {
865
- setLoading(false);
866
- return;
867
- }
868
- const knownTxs = data.transactions.filter((txn) => {
869
- const tokens = data.tokens[txn.details.from_chain];
870
- if (!tokens)
871
- return false;
872
- const token = tokens[txn.details.from_token_address.toLowerCase()];
873
- if (!token)
874
- return false;
875
- return true;
876
- });
877
- setKnownTokenMap(data.tokens);
878
- setTxs(knownTxs);
879
- setLoading(false);
880
- })();
881
- }, [from?.walletAddress, checkout]);
882
- useEffect(() => {
883
- page({
884
- userJourney: UserJourney.BRIDGE,
885
- screen: 'Transactions',
886
- });
887
- }, []);
888
- return (jsx(SimpleLayout, { testId: "bridge-view", header: (jsx(HeaderNavigation, { showBack: true, onBackButtonClick: onBackButtonClick, title: t('views.TRANSACTIONS.layoutHeading'), onCloseButtonClick: () => sendBridgeWidgetCloseEvent(eventTarget) })), footer: jsx(FooterLogo, {}), children: jsxs(Box, { sx: transactionsContainerStyle, children: [jsxs(Box, { sx: transactionsListContainerStyle, children: [!from?.web3Provider && (jsx(EmptyStateNotConnected, { openWalletDrawer: () => setShowWalletDrawer(true) })), from?.web3Provider && loading && (jsx(Shimmer, {})), from?.web3Provider && !loading && txs.length > 0 && knownTokenMap && (jsx(TransactionList, { checkout: checkout, transactions: txs, knownTokenMap: knownTokenMap, isPassport: isPassport, changeWallet: () => setShowWalletDrawer(true) })), from?.web3Provider && !loading && txs.length === 0 && (jsx(NoTransactions, { checkout: checkout, isPassport: isPassport, changeWallet: () => setShowWalletDrawer(true) }))] }), from?.web3Provider && txs.length > 0 && (jsx(Box, { sx: supportBoxContainerStyle, children: jsx(SupportMessage, { checkout: checkout, isPassport: isPassport }) })), jsx(WalletDrawer, { testId: "select-wallet-drawer", drawerText: {
889
- heading: t('views.TRANSACTIONS.walletSelection.heading'),
890
- }, showWalletSelectorTarget: false, walletOptions: walletOptions, showDrawer: showWalletDrawer, setShowDrawer: (show) => { setShowWalletDrawer(show); }, onWalletItemClick: updateAndConnectProvider })] }) }));
891
- }
892
-
893
- function ClaimWithdrawalInProgress({ transactionResponse }) {
894
- const { t } = useTranslation();
895
- const { viewDispatch } = useContext(ViewContext);
896
- const { page } = useAnalytics();
897
- useEffect(() => {
898
- page({
899
- userJourney: UserJourney.BRIDGE,
900
- screen: 'ClaimWithdrawalInProgress',
901
- });
902
- }, []);
903
- useEffect(() => {
904
- if (!transactionResponse)
905
- return;
906
- (async () => {
907
- try {
908
- const receipt = await transactionResponse.wait();
909
- if (receipt.status === 1) {
910
- viewDispatch({
911
- payload: {
912
- type: ViewActions.UPDATE_VIEW,
913
- view: {
914
- type: BridgeWidgetViews.CLAIM_WITHDRAWAL_SUCCESS,
915
- transactionHash: receipt.transactionHash,
916
- },
917
- },
918
- });
919
- return;
920
- }
921
- viewDispatch({
922
- payload: {
923
- type: ViewActions.UPDATE_VIEW,
924
- view: {
925
- type: BridgeWidgetViews.CLAIM_WITHDRAWAL_FAILURE,
926
- transactionHash: receipt.transactionHash,
927
- reason: 'Transaction failed',
928
- },
929
- },
930
- });
931
- }
932
- catch (error) {
933
- // eslint-disable-next-line no-console
934
- console.error(error);
935
- viewDispatch({
936
- payload: {
937
- type: ViewActions.UPDATE_VIEW,
938
- view: {
939
- type: BridgeWidgetViews.CLAIM_WITHDRAWAL_FAILURE,
940
- transactionHash: '',
941
- reason: 'Transaction failed',
942
- },
943
- },
944
- });
945
- }
946
- })();
947
- }, [transactionResponse]);
948
- return jsx(LoadingView, { loadingText: t('views.CLAIM_WITHDRAWAL.IN_PROGRESS.loading.text'), showFooterLogo: true });
949
- }
950
-
951
- function abbreviateAddress(address) {
952
- if (!address)
953
- return '';
954
- return address.substring(0, 6).concat('...').concat(address.substring(address.length - 4));
955
- }
956
-
957
- const brigdeWalletWrapperStyles = {
958
- height: '100%',
959
- display: 'flex',
960
- flexDirection: 'column',
961
- paddingX: 'base.spacing.x4',
962
- };
963
- const bridgeHeadingStyles = {
964
- paddingTop: 'base.spacing.x10',
965
- paddingBottom: 'base.spacing.x4',
966
- };
967
- const submitButtonWrapperStyles = {
968
- display: 'flex',
969
- flexDirection: 'column',
970
- paddingY: 'base.spacing.x6',
971
- };
972
-
973
- const logoColour$1 = {
974
- [ChainId.IMTBL_ZKEVM_DEVNET]: 'base.color.text.link.primary',
975
- [ChainId.IMTBL_ZKEVM_TESTNET]: 'base.color.text.link.primary',
976
- [ChainId.IMTBL_ZKEVM_MAINNET]: 'base.color.text.link.primary',
977
- [ChainId.ETHEREUM]: 'base.color.accent.5',
978
- [ChainId.SEPOLIA]: 'base.color.accent.5',
979
- };
980
- const networkItemStyles = (chainId) => ({
981
- backgroundColor: logoColour$1[chainId],
982
- // eslint-disable-next-line @typescript-eslint/naming-convention
983
- '& svg': {
984
- fill: 'base.color.brand.2',
985
- },
986
- });
987
-
988
- const networkIcon$2 = {
989
- [ChainId.IMTBL_ZKEVM_DEVNET]: 'Immutable',
990
- [ChainId.IMTBL_ZKEVM_MAINNET]: 'Immutable',
991
- [ChainId.IMTBL_ZKEVM_TESTNET]: 'Immutable',
992
- [ChainId.ETHEREUM]: 'EthToken',
993
- [ChainId.SEPOLIA]: 'EthToken',
994
- };
995
- function NetworkItem({ testId, chainId, chainName, onNetworkClick, }) {
996
- return (jsxs(MenuItem, { testId: `${testId}-network-list-${chainId}`, size: "medium", emphasized: true, onClick: async () => {
997
- await onNetworkClick(chainId);
998
- }, sx: { marginBottom: 'base.spacing.x1' }, children: [jsx(MenuItem.FramedIcon, { icon: networkIcon$2[chainId], circularFrame: true, sx: networkItemStyles(chainId) }), jsx(MenuItem.Label, { size: "medium", children: chainName })] }));
999
- }
1000
-
1001
- const logoColour = {
1002
- [ChainId.IMTBL_ZKEVM_DEVNET]: 'base.color.text.link.primary',
1003
- [ChainId.IMTBL_ZKEVM_TESTNET]: 'base.color.text.link.primary',
1004
- [ChainId.IMTBL_ZKEVM_MAINNET]: 'base.color.text.link.primary',
1005
- [ChainId.ETHEREUM]: 'base.color.accent.5',
1006
- [ChainId.SEPOLIA]: 'base.color.accent.5',
1007
- };
1008
- const walletButtonOuterStyles = {
1009
- width: '100%',
1010
- backgroundColor: 'base.color.translucent.emphasis.100',
1011
- borderRadius: 'base.borderRadius.x4',
1012
- paddingX: 'base.spacing.x3',
1013
- paddingY: 'base.spacing.x5',
1014
- display: 'flex',
1015
- flexDirection: 'row',
1016
- gap: 'base.spacing.x4',
1017
- alignItems: 'center',
1018
- // eslint-disable-next-line @typescript-eslint/naming-convention
1019
- '&:hover': {
1020
- cursor: 'pointer',
1021
- backgroundColor: 'base.color.translucent.emphasis.200',
1022
- },
1023
- };
1024
- const walletLogoStyles = (walletName) => ({
1025
- width: 'base.icon.size.500',
1026
- padding: walletName === WalletProviderName.PASSPORT ? 'base.spacing.x1' : '',
1027
- backgroundColor: 'base.color.translucent.standard.200',
1028
- borderRadius: 'base.borderRadius.x2',
1029
- });
1030
- const walletCaptionStyles = { color: 'base.color.text.secondary' };
1031
- const networkButtonStyles = {
1032
- paddingY: 'base.spacing.x6',
1033
- borderRadius: 'base.borderRadius.x18',
1034
- };
1035
- const networkIconStyles = (chainId) => ({
1036
- fill: 'base.color.brand.2',
1037
- width: 'base.icon.size.300',
1038
- backgroundColor: logoColour[chainId],
1039
- borderRadius: '100%',
1040
- padding: 'base.spacing.x1',
1041
- });
1042
-
1043
- const networkIcon$1 = {
1044
- [ChainId.IMTBL_ZKEVM_DEVNET]: 'Immutable',
1045
- [ChainId.IMTBL_ZKEVM_MAINNET]: 'Immutable',
1046
- [ChainId.IMTBL_ZKEVM_TESTNET]: 'Immutable',
1047
- [ChainId.ETHEREUM]: 'EthToken',
1048
- [ChainId.SEPOLIA]: 'EthToken',
1049
- };
1050
- const walletLogo = {
1051
- [WalletProviderName.PASSPORT]: 'PassportSymbolOutlined',
1052
- [WalletProviderName.METAMASK]: 'MetaMaskSymbol',
1053
- };
1054
- function WalletNetworkButton({ testId, walletName, walletAddress, chainId, disableNetworkButton = false, onWalletClick, onNetworkClick, }) {
1055
- const networkName = getChainNameById(chainId);
1056
- const walletHeading = walletName === WalletProviderName.METAMASK ? 'Metamask' : 'Passport';
1057
- return (jsxs(Box, { testId: `${testId}-${walletName}-${chainId}-button-wrapper`, sx: walletButtonOuterStyles, onClick: onWalletClick, children: [jsx(Logo, { logo: walletLogo[walletName], sx: walletLogoStyles(walletName) }), jsxs(Box, { sx: {
1058
- display: 'flex',
1059
- flexDirection: 'column',
1060
- flex: 1,
1061
- }, children: [jsx(Heading, { size: "xSmall", children: walletHeading }), jsx(Body, { size: "xSmall", sx: walletCaptionStyles, children: walletAddress })] }), jsxs(Button, { testId: `${testId}-network-${chainId}-button`, size: "small", disabled: disableNetworkButton, onClick: (e) => {
1062
- // stop propogation so onWalletClick is not triggered
1063
- e.stopPropagation();
1064
- onNetworkClick(e);
1065
- }, variant: "tertiary", sx: networkButtonStyles, children: [jsx(Button.Icon, { icon: networkIcon$1[chainId], sx: networkIconStyles(chainId) }), networkName] })] }));
1066
- }
1067
-
1068
- const testId$1 = 'wallet-network-selector';
1069
- function WalletAndNetworkSelector() {
1070
- const { t } = useTranslation();
1071
- const { bridgeState: { checkout, from, to, }, bridgeDispatch, } = useContext(BridgeContext);
1072
- const { viewDispatch } = useContext(ViewContext);
1073
- const { track } = useAnalytics();
1074
- // calculating l1/l2 chains to work with based on Checkout environment
1075
- const l1NetworkChainId = getL1ChainId(checkout.config);
1076
- const l1NetworkName = getChainNameById(l1NetworkChainId);
1077
- const imtblZkEvmNetworkChainId = getL2ChainId(checkout.config);
1078
- const imtblZkEvmNetworkName = getChainNameById(imtblZkEvmNetworkChainId);
1079
- const passportCache = useRef();
1080
- /** From wallet and from network local state */
1081
- const [fromWalletDrawerOpen, setFromWalletDrawerOpen] = useState(false);
1082
- const [fromNetworkDrawerOpen, setFromNetworkDrawerOpen] = useState(false);
1083
- const [fromWalletWeb3Provider, setFromWalletWeb3Provider] = useState();
1084
- const [fromNetwork, setFromNetwork] = useState();
1085
- const [fromWalletAddress, setFromWalletAddress] = useState('');
1086
- /** To wallet local state */
1087
- const [toWalletDrawerOpen, setToWalletDrawerOpen] = useState(false);
1088
- const [toWalletWeb3Provider, setToWalletWeb3Provider] = useState();
1089
- const [toNetwork, setToNetwork] = useState();
1090
- const [toWalletAddress, setToWalletAddress] = useState('');
1091
- /* Derived state */
1092
- const isFromWalletAndNetworkSelected = fromWalletWeb3Provider && fromNetwork;
1093
- const isToWalletAndNetworkSelected = toWalletWeb3Provider && toNetwork;
1094
- const fromWalletProviderName = useMemo(() => {
1095
- if (!fromWalletWeb3Provider)
1096
- return null;
1097
- return isPassportProvider(fromWalletWeb3Provider)
1098
- ? WalletProviderName.PASSPORT
1099
- : WalletProviderName.METAMASK;
1100
- }, [fromWalletWeb3Provider]);
1101
- const toWalletProviderName = useMemo(() => {
1102
- if (!fromWalletWeb3Provider)
1103
- return null;
1104
- return isPassportProvider(toWalletWeb3Provider)
1105
- ? WalletProviderName.PASSPORT
1106
- : WalletProviderName.METAMASK;
1107
- }, [toWalletWeb3Provider]);
1108
- const fromWalletSelectorOptions = useMemo(() => {
1109
- const options = [WalletProviderName.METAMASK];
1110
- if (checkout.passport) {
1111
- options.push(WalletProviderName.PASSPORT);
1112
- }
1113
- return options;
1114
- }, [checkout]);
1115
- const toWalletSelectorOptions = useMemo(() => {
1116
- const options = [WalletProviderName.METAMASK];
1117
- if (checkout.passport
1118
- && fromNetwork === l1NetworkChainId
1119
- && fromWalletProviderName === WalletProviderName.METAMASK) {
1120
- options.push(WalletProviderName.PASSPORT);
1121
- }
1122
- return options;
1123
- }, [checkout, fromNetwork, fromWalletProviderName]);
1124
- useEffect(() => {
1125
- if (!from || !to)
1126
- return;
1127
- if (fromWalletAddress !== from?.walletAddress) {
1128
- track({
1129
- userJourney: UserJourney.BRIDGE,
1130
- screen: 'WalletAndNetwork',
1131
- control: 'FromWallet',
1132
- controlType: 'Select',
1133
- extras: {
1134
- walletAddress: from?.walletAddress,
1135
- },
1136
- });
1137
- }
1138
- if (fromNetwork !== from?.network) {
1139
- track({
1140
- userJourney: UserJourney.BRIDGE,
1141
- screen: 'WalletAndNetwork',
1142
- control: 'FromNetwork',
1143
- controlType: 'Select',
1144
- extras: {
1145
- chainId: from?.network,
1146
- },
1147
- });
1148
- }
1149
- if (toWalletAddress !== to?.walletAddress) {
1150
- track({
1151
- userJourney: UserJourney.BRIDGE,
1152
- screen: 'WalletAndNetwork',
1153
- control: 'ToWallet',
1154
- controlType: 'Select',
1155
- extras: {
1156
- walletAddress: to?.walletAddress,
1157
- },
1158
- });
1159
- }
1160
- if (toNetwork !== to?.network) {
1161
- track({
1162
- userJourney: UserJourney.BRIDGE,
1163
- screen: 'WalletAndNetwork',
1164
- control: 'ToNetwork',
1165
- controlType: 'Select',
1166
- extras: {
1167
- chainId: to?.network,
1168
- },
1169
- });
1170
- }
1171
- // add local state from context values
1172
- // if user has clicked back button
1173
- setFromWalletWeb3Provider(from.web3Provider);
1174
- setFromWalletAddress(from.walletAddress.toLowerCase());
1175
- setFromNetwork(from.network);
1176
- setToWalletWeb3Provider(to.web3Provider);
1177
- setToWalletAddress(to.walletAddress.toLowerCase());
1178
- setToNetwork(to.network);
1179
- bridgeDispatch({
1180
- payload: {
1181
- type: BridgeActions.SET_WALLETS_AND_NETWORKS,
1182
- from: null,
1183
- to: null,
1184
- },
1185
- });
1186
- }, [from, to]);
1187
- const createProviderAndConnect = useCallback(async (walletProviderName) => {
1188
- let web3Provider;
1189
- try {
1190
- web3Provider = await createAndConnectToProvider(checkout, walletProviderName);
1191
- if (walletProviderName === WalletProviderName.PASSPORT) {
1192
- passportCache.current = web3Provider;
1193
- }
1194
- return web3Provider;
1195
- }
1196
- catch (error) {
1197
- // eslint-disable-next-line no-console
1198
- console.error(error);
1199
- throw error;
1200
- }
1201
- }, [checkout]);
1202
- function clearToWalletSelections() {
1203
- setToWalletWeb3Provider(null);
1204
- setToNetwork(null);
1205
- }
1206
- /* --------------------------- */
1207
- /* --- Handling selections --- */
1208
- /* --------------------------- */
1209
- const handleFromWalletConnection = useCallback(async (walletProviderName) => {
1210
- clearToWalletSelections();
1211
- let provider;
1212
- if (walletProviderName === WalletProviderName.PASSPORT && passportCache.current) {
1213
- provider = passportCache.current;
1214
- }
1215
- if (!provider) {
1216
- try {
1217
- provider = await createProviderAndConnect(walletProviderName);
1218
- }
1219
- catch (error) {
1220
- return;
1221
- }
1222
- }
1223
- setFromWalletWeb3Provider(provider);
1224
- const address = await provider.getSigner().getAddress();
1225
- setFromWalletAddress(address.toLowerCase());
1226
- /** if Passport skip from network selector and default to zkEVM */
1227
- if (isPassportProvider(provider)) {
1228
- setFromNetwork(imtblZkEvmNetworkChainId);
1229
- setFromWalletDrawerOpen(false);
1230
- return;
1231
- }
1232
- /**
1233
- * Force the selection of network
1234
- * by clearing the fromNetwork
1235
- * and opening the network drawer
1236
- */
1237
- setFromNetwork(null);
1238
- setFromWalletDrawerOpen(false);
1239
- setTimeout(() => setFromNetworkDrawerOpen(true), 500);
1240
- }, [fromWalletProviderName, passportCache.current]);
1241
- const handleFromNetworkSelection = useCallback(async (chainId) => {
1242
- if (!fromWalletWeb3Provider)
1243
- return;
1244
- clearToWalletSelections();
1245
- if (isPassportProvider(fromWalletWeb3Provider)) {
1246
- setFromNetworkDrawerOpen(false);
1247
- setFromNetwork(chainId);
1248
- return;
1249
- }
1250
- const currentNetwork = await fromWalletWeb3Provider?.getNetwork();
1251
- if (currentNetwork?.chainId === chainId) {
1252
- setFromNetworkDrawerOpen(false);
1253
- setFromNetwork(chainId);
1254
- return;
1255
- }
1256
- let switchNetwork;
1257
- try {
1258
- switchNetwork = await checkout.switchNetwork({ provider: fromWalletWeb3Provider, chainId });
1259
- setFromWalletWeb3Provider(switchNetwork.provider);
1260
- setFromNetworkDrawerOpen(false);
1261
- setFromNetwork(switchNetwork.network.chainId);
1262
- }
1263
- catch (err) {
1264
- // eslint-disable-next-line no-console
1265
- console.error(err);
1266
- }
1267
- }, [
1268
- checkout,
1269
- fromWalletWeb3Provider,
1270
- fromWalletProviderName,
1271
- fromNetwork,
1272
- ]);
1273
- const handleToWalletSelection = useCallback(async (selectedToWalletProviderName) => {
1274
- if (fromWalletProviderName === selectedToWalletProviderName) {
1275
- // if same from wallet and to wallet, just use the existing fromWalletLocalWeb3Provider
1276
- setToWalletWeb3Provider(fromWalletWeb3Provider);
1277
- const address = await fromWalletWeb3Provider.getSigner().getAddress();
1278
- setToWalletAddress(address.toLowerCase());
1279
- }
1280
- else {
1281
- let toWalletProvider;
1282
- if (selectedToWalletProviderName === WalletProviderName.PASSPORT && passportCache.current) {
1283
- toWalletProvider = passportCache.current;
1284
- }
1285
- if (!toWalletProvider) {
1286
- try {
1287
- toWalletProvider = await createProviderAndConnect(selectedToWalletProviderName);
1288
- }
1289
- catch (error) {
1290
- return;
1291
- }
1292
- }
1293
- setToWalletWeb3Provider(toWalletProvider);
1294
- const address = await toWalletProvider.getSigner().getAddress();
1295
- setToWalletAddress(address.toLowerCase());
1296
- }
1297
- // toNetwork is always the opposite of fromNetwork
1298
- const theToNetwork = fromNetwork === l1NetworkChainId ? imtblZkEvmNetworkChainId : l1NetworkChainId;
1299
- setToNetwork(theToNetwork);
1300
- setToWalletDrawerOpen(false);
1301
- }, [
1302
- fromWalletProviderName,
1303
- fromNetwork,
1304
- fromWalletWeb3Provider,
1305
- passportCache.current,
1306
- ]);
1307
- const handleSubmitDetails = useCallback(() => {
1308
- if (!fromWalletWeb3Provider || !fromNetwork || !toWalletWeb3Provider || !toNetwork)
1309
- return;
1310
- bridgeDispatch({
1311
- payload: {
1312
- type: BridgeActions.SET_TOKEN_BALANCES,
1313
- tokenBalances: [],
1314
- },
1315
- });
1316
- bridgeDispatch({
1317
- payload: {
1318
- type: BridgeActions.SET_ALLOWED_TOKENS,
1319
- allowedTokens: [],
1320
- },
1321
- });
1322
- bridgeDispatch({
1323
- payload: {
1324
- type: BridgeActions.SET_WALLETS_AND_NETWORKS,
1325
- from: {
1326
- web3Provider: fromWalletWeb3Provider,
1327
- walletAddress: fromWalletAddress.toLowerCase(),
1328
- network: fromNetwork,
1329
- },
1330
- to: {
1331
- web3Provider: toWalletWeb3Provider,
1332
- walletAddress: toWalletAddress.toLowerCase(),
1333
- network: toNetwork,
1334
- },
1335
- },
1336
- });
1337
- track({
1338
- userJourney: UserJourney.BRIDGE,
1339
- screen: 'WalletAndNetwork',
1340
- control: 'Next',
1341
- controlType: 'Button',
1342
- extras: {
1343
- fromWalletAddress,
1344
- fromNetwork,
1345
- fromWallet: {
1346
- address: fromWalletAddress,
1347
- isPassportWallet: isPassportProvider(fromWalletWeb3Provider),
1348
- isMetaMask: isMetaMaskProvider(fromWalletWeb3Provider),
1349
- },
1350
- toWalletAddress,
1351
- toNetwork,
1352
- toWallet: {
1353
- address: toWalletAddress,
1354
- isPassportWallet: isPassportProvider(toWalletWeb3Provider),
1355
- isMetaMask: isMetaMaskProvider(toWalletWeb3Provider),
1356
- },
1357
- },
1358
- });
1359
- viewDispatch({
1360
- payload: {
1361
- type: ViewActions.UPDATE_VIEW,
1362
- view: { type: BridgeWidgetViews.BRIDGE_FORM },
1363
- },
1364
- });
1365
- }, [
1366
- fromWalletWeb3Provider,
1367
- fromNetwork,
1368
- fromWalletAddress,
1369
- toWalletWeb3Provider,
1370
- toNetwork,
1371
- toWalletAddress,
1372
- ]);
1373
- return (jsxs(Box, { testId: testId$1, sx: brigdeWalletWrapperStyles, children: [jsx(Heading, { testId: `${testId$1}-heading`, size: "small", weight: "regular", sx: bridgeHeadingStyles, children: t('views.WALLET_NETWORK_SELECTION.heading') }), jsx(Heading, { size: "xSmall", sx: { paddingBottom: 'base.spacing.x2' }, children: t('views.WALLET_NETWORK_SELECTION.fromFormInput.heading') }), jsx(WalletDrawer, { testId: `${testId$1}-from`, drawerText: {
1374
- heading: t('views.WALLET_NETWORK_SELECTION.fromFormInput.walletSelectorHeading'),
1375
- defaultText: t('views.WALLET_NETWORK_SELECTION.fromFormInput.selectDefaultText'),
1376
- }, showWalletSelectorTarget: !isFromWalletAndNetworkSelected, walletOptions: fromWalletSelectorOptions, showDrawer: fromWalletDrawerOpen, setShowDrawer: setFromWalletDrawerOpen, onWalletItemClick: handleFromWalletConnection }), isFromWalletAndNetworkSelected && fromWalletProviderName && (jsxs(Box, { sx: { display: 'flex', flexDirection: 'column', gap: 'base.spacing.x10' }, children: [jsx(WalletNetworkButton, { testId: testId$1, walletName: fromWalletProviderName, walletAddress: abbreviateAddress(fromWalletAddress), chainId: fromNetwork, onWalletClick: () => {
1377
- setFromWalletDrawerOpen(true);
1378
- }, onNetworkClick: () => setFromNetworkDrawerOpen(true) }), jsxs(Box, { children: [jsx(Heading, { size: "xSmall", sx: { paddingBottom: 'base.spacing.x2' }, children: t('views.WALLET_NETWORK_SELECTION.toFormInput.heading') }), jsx(WalletDrawer, { testId: `${testId$1}-to`, drawerText: {
1379
- heading: t('views.WALLET_NETWORK_SELECTION.toFormInput.walletSelectorHeading'),
1380
- defaultText: t('views.WALLET_NETWORK_SELECTION.toFormInput.selectDefaultText'),
1381
- }, showWalletSelectorTarget: !isToWalletAndNetworkSelected, walletOptions: toWalletSelectorOptions, showDrawer: toWalletDrawerOpen, setShowDrawer: setToWalletDrawerOpen, onWalletItemClick: handleToWalletSelection })] })] })), jsx(Drawer, { headerBarTitle: t('views.WALLET_NETWORK_SELECTION.fromFormInput.networkSelectorHeading'), size: "full", onCloseDrawer: () => {
1382
- setFromNetworkDrawerOpen(false);
1383
- }, visible: fromNetworkDrawerOpen, children: jsxs(Drawer.Content, { children: [jsx(NetworkItem, { testId: testId$1, chainName: imtblZkEvmNetworkName, onNetworkClick: handleFromNetworkSelection, chainId: imtblZkEvmNetworkChainId }, imtblZkEvmNetworkName), fromWalletProviderName === WalletProviderName.METAMASK && (jsx(NetworkItem, { testId: testId$1, chainName: l1NetworkName, onNetworkClick: handleFromNetworkSelection, chainId: l1NetworkChainId }, l1NetworkName))] }) }), isToWalletAndNetworkSelected && toWalletProviderName && (jsxs(Box, { sx: {
1384
- flex: 1,
1385
- display: 'flex',
1386
- flexDirection: 'column',
1387
- justifyContent: 'space-between',
1388
- }, children: [jsx(WalletNetworkButton, { testId: testId$1, walletName: toWalletProviderName, walletAddress: abbreviateAddress(toWalletAddress), chainId: toNetwork, disableNetworkButton: true, onWalletClick: () => {
1389
- setToWalletDrawerOpen(true);
1390
- },
1391
- // eslint-disable-next-line no-console
1392
- onNetworkClick: () => { } }), jsx(Box, { sx: submitButtonWrapperStyles, children: jsx(Button, { testId: `${testId$1}-submit-button`, size: "large", onClick: handleSubmitDetails, children: t('views.WALLET_NETWORK_SELECTION.submitButton.text') }) })] }))] }));
1393
- }
1394
-
1395
- function WalletNetworkSelectionView() {
1396
- const { t } = useTranslation();
1397
- const { viewDispatch } = useContext(ViewContext);
1398
- const { eventTargetState: { eventTarget } } = useContext(EventTargetContext);
1399
- const { page } = useAnalytics();
1400
- useEffect(() => {
1401
- page({
1402
- userJourney: UserJourney.BRIDGE,
1403
- screen: 'WalletNetworkSelection',
1404
- });
1405
- }, []);
1406
- return (jsx(SimpleLayout, { testId: "bridge-view", header: (jsx(HeaderNavigation, { title: t('views.WALLET_NETWORK_SELECTION.layoutHeading'), onCloseButtonClick: () => sendBridgeWidgetCloseEvent(eventTarget), rightActions: (jsx(ButtCon, { icon: "Minting", sx: ButtonNavigationStyles(), onClick: () => {
1407
- viewDispatch({
1408
- payload: {
1409
- type: ViewActions.UPDATE_VIEW,
1410
- view: { type: BridgeWidgetViews.TRANSACTIONS },
1411
- },
1412
- });
1413
- }, testId: "move-transactions-button" })) })), footer: jsx(FooterLogo, {}), children: jsx(WalletAndNetworkSelector, {}) }));
1414
- }
1415
-
1416
- function validateToken(fromToken) {
1417
- const { validation } = text.views[BridgeWidgetViews.BRIDGE_FORM];
1418
- if (!fromToken)
1419
- return validation.noTokenSelected;
1420
- return '';
1421
- }
1422
- function validateAmount(amount, balance) {
1423
- const { validation } = text.views[BridgeWidgetViews.BRIDGE_FORM];
1424
- if (!amount || parseFloat(amount) === 0)
1425
- return validation.noAmountInputted;
1426
- if (balance && Number(amount) > Number(balance))
1427
- return validation.insufficientBalance;
1428
- return '';
1429
- }
1430
-
1431
- const bridgeFormWrapperStyles = {
1432
- height: '100%',
1433
- display: 'flex',
1434
- flexDirection: 'column',
1435
- justifyContent: 'space-between',
1436
- paddingTop: 'base.spacing.x10',
1437
- };
1438
- const formInputsContainerStyles = {
1439
- paddingTop: 'base.spacing.x4',
1440
- display: 'flex',
1441
- gap: 'base.spacing.x1',
1442
- };
1443
- const bridgeFormButtonContainerStyles = {
1444
- display: 'flex',
1445
- flexDirection: 'column',
1446
- paddingY: 'base.spacing.x6',
1447
- paddingX: 'base.spacing.x4',
1448
- };
1449
- const gasAmountAccordionStyles = {
1450
- backgroundColor: 'base.color.translucent.emphasis.100',
1451
- };
1452
- const gasAmountHeadingStyles$1 = {
1453
- marginBottom: 'base.spacing.x4',
1454
- color: 'base.color.text.secondary',
1455
- };
1456
- const bridgeButtonIconLoadingStyle$1 = {
1457
- width: 'base.icon.size.400',
1458
- };
1459
-
1460
- const containerStyles$1 = {
1461
- display: 'flex',
1462
- flexDirection: 'column',
1463
- alignItems: 'center',
1464
- paddingTop: 'base.spacing.x6',
1465
- paddingBottom: 'base.spacing.x1',
1466
- height: '100%',
1467
- };
1468
- const contentTextStyles$1 = {
1469
- color: 'base.color.text.secondary',
1470
- fontFamily: 'base.font.family.heading.secondary',
1471
- textAlign: 'center',
1472
- marginTop: '15px',
1473
- };
1474
- const actionButtonContainerStyles$1 = {
1475
- display: 'flex',
1476
- flexDirection: 'column',
1477
- justifyContent: 'center',
1478
- gap: 'base.spacing.x2',
1479
- height: '100%',
1480
- width: '100%',
1481
- };
1482
- const actionButtonStyles$1 = {
1483
- width: '100%',
1484
- height: 'base.spacing.x16',
1485
- };
1486
- const logoContainerStyles = {
1487
- display: 'flex',
1488
- flexDirection: 'column',
1489
- justifyContent: 'center',
1490
- alignItems: 'center',
1491
- paddingTop: 'base.spacing.x6',
1492
- };
1493
-
1494
- function NotEnoughGas({ environment, onCloseDrawer, visible, showHeaderBar, walletAddress, showAdjustAmount, tokenSymbol, onAddCoinsClick, }) {
1495
- const { content, buttons } = text.drawers.notEnoughGas;
1496
- const [isCopied, setIsCopied] = useState(false);
1497
- const ethLogo = getEthTokenImage(environment);
1498
- const imxLogo = getImxTokenImage(environment);
1499
- const heading = tokenSymbol === ETH_TOKEN_SYMBOL ? `${content.eth.heading}` : `${content.imx.heading}`;
1500
- const body = tokenSymbol === ETH_TOKEN_SYMBOL ? `${content.eth.body}` : `${content.imx.body}`;
1501
- const handleCopy = useCallback(() => {
1502
- if (walletAddress && walletAddress !== '') {
1503
- navigator.clipboard.writeText(walletAddress);
1504
- }
1505
- setIsCopied(true);
1506
- setTimeout(() => {
1507
- setIsCopied(false);
1508
- }, 3000);
1509
- }, [walletAddress]);
1510
- return (jsx(Drawer, { headerBarTitle: undefined, size: "full", onCloseDrawer: onCloseDrawer, visible: visible, showHeaderBar: showHeaderBar, children: jsx(Drawer.Content, { children: jsxs(Box, { testId: "not-enough-gas-bottom-sheet", sx: containerStyles$1, children: [jsx(CloudImage, { imageUrl: tokenSymbol === ETH_TOKEN_SYMBOL
1511
- ? ethLogo
1512
- : imxLogo, sx: { w: 'base.icon.size.600', h: 'base.icon.size.600' } }), jsx(Heading, { size: "small", sx: contentTextStyles$1, testId: "not-enough-gas-heading", children: heading }), jsx(Body, { sx: contentTextStyles$1, children: body }), jsxs(Box, { sx: actionButtonContainerStyles$1, children: [showAdjustAmount && (jsx(Button, { testId: "not-enough-gas-adjust-amount-button", sx: actionButtonStyles$1, variant: "tertiary", onClick: onCloseDrawer, children: buttons.adjustAmount })), tokenSymbol === ETH_TOKEN_SYMBOL
1513
- ? (jsxs(Button, { testId: "not-enough-gas-copy-address-button", sx: actionButtonStyles$1, variant: "tertiary", onClick: handleCopy, children: [buttons.copyAddress, jsx(Button.Icon, { icon: isCopied ? 'Tick' : 'CopyText' })] }))
1514
- : (jsx(Button, { testId: "not-enough-gas-add-imx-button", sx: actionButtonStyles$1, variant: "tertiary", onClick: onAddCoinsClick, children: buttons.addMoreImx })), jsx(Button, { sx: actionButtonStyles$1, variant: "tertiary", onClick: onCloseDrawer, testId: "not-enough-gas-cancel-button", children: buttons.cancel })] }), jsx(Box, { sx: logoContainerStyles, children: jsx(Logo, { testId: "footer-logo-image", logo: "ImmutableHorizontalLockup", sx: { width: 'base.spacing.x25' } }) })] }) }) }));
1515
- }
1516
-
1517
- function TokenSelectShimmer({ sx }) {
1518
- return (jsxs(Box, { sx: {
1519
- ...sx,
1520
- paddingTop: '0',
1521
- marginTop: 'base.spacing.x4',
1522
- }, rc: jsx("div", {}), children: [jsx(Box, { sx: {
1523
- display: 'flex',
1524
- backgroundColor: '#F3F3F30A',
1525
- borderRadius: '8px',
1526
- }, children: jsx(Box, { sx: {
1527
- minw: '170px',
1528
- height: '64px',
1529
- // eslint-disable-next-line @typescript-eslint/naming-convention
1530
- WebkitMaskPosition: 'left center',
1531
- // eslint-disable-next-line @typescript-eslint/naming-convention
1532
- WebkitMaskRepeat: 'no-repeat',
1533
- // eslint-disable-next-line @typescript-eslint/naming-convention
1534
- WebkitMaskSize: 'contain',
1535
- // eslint-disable-next-line @typescript-eslint/naming-convention,max-len
1536
- WebkitMaskImage: 'url(\'data:image/svg+xml;utf8, <svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none"><path d="M154.75 39q1.65 0 2.85-1.15 1.15-1.15 1.15-2.85v-4q0-1.65-1.15-2.8-1.2-1.2-2.85-1.2h-93.6q-2.3 0-3.85 1.2-1.55 1.15-1.55 2.8v4q0 1.7 1.55 2.85Q58.85 39 61.15 39h93.6m-111.7-3.35q.2-1.3.2-2.65 0-1.35-.2-2.65-.75-4.9-4.5-8.65-4.7-4.7-11.3-4.7-6.65 0-11.3 4.7-4.7 4.7-4.7 11.3 0 6.65 4.7 11.3Q20.6 49 27.25 49q6.6 0 11.3-4.7 3.75-3.7 4.5-8.65Z" id="a"/></svg>\')',
1537
- }, rc: jsx("span", {}), children: jsx(ShimmerBox, { rc: jsx("span", {}) }) }) }), jsx(Box, { sx: {
1538
- display: 'flex',
1539
- width: '100%',
1540
- backgroundColor: '#F3F3F30A',
1541
- borderRadius: '8px',
1542
- }, children: jsx(Box, { sx: {
1543
- width: '100%',
1544
- height: '64px',
1545
- // eslint-disable-next-line @typescript-eslint/naming-convention
1546
- WebkitMaskPosition: 'right center',
1547
- // eslint-disable-next-line @typescript-eslint/naming-convention
1548
- WebkitMaskRepeat: 'no-repeat',
1549
- // eslint-disable-next-line @typescript-eslint/naming-convention
1550
- WebkitMaskSize: 'contain',
1551
- // eslint-disable-next-line @typescript-eslint/naming-convention,max-len
1552
- WebkitMaskImage: 'url(\'data:image/svg+xml;utf8, <svg xmlns="http://www.w3.org/2000/svg" width="196" height="96"><path d="M182.85 55.2Q181.65 54 180 54h-56q-1.7 0-2.85 1.2Q120 56.35 120 58v4q0 1.7 1.15 2.85Q122.3 66 124 66h56q1.65 0 2.85-1.15Q184 63.7 184 62v-4q0-1.65-1.15-2.8m0-22Q181.65 32 180 32H68q-1.7 0-2.85 1.2Q64 34.35 64 36v8q0 1.7 1.15 2.85Q66.3 48 68 48h112q1.65 0 2.85-1.15Q184 45.7 184 44v-8q0-1.65-1.15-2.8Z" id="a"/></svg>\')',
1553
- }, rc: jsx("span", {}), children: jsx(ShimmerBox, { rc: jsx("span", {}) }) }) })] }));
1554
- }
1555
-
1556
- function BridgeForm(props) {
1557
- const { t } = useTranslation();
1558
- const { bridgeDispatch, bridgeState: { tokenBridge, tokenBalances, allowedTokens, checkout, from, to, amount, token, }, } = useContext(BridgeContext);
1559
- const { cryptoFiatState, cryptoFiatDispatch } = useContext(CryptoFiatContext);
1560
- const { viewDispatch } = useContext(ViewContext);
1561
- const { testId, defaultAmount, defaultTokenAddress, isTokenBalancesLoading, } = props;
1562
- const { track } = useAnalytics();
1563
- // Form state
1564
- const [formAmount, setFormAmount] = useState(defaultAmount || '');
1565
- const [amountError, setAmountError] = useState('');
1566
- const [formToken, setFormToken] = useState();
1567
- const [tokenError, setTokenError] = useState('');
1568
- const [amountFiatValue, setAmountFiatValue] = useState('');
1569
- const [editing, setEditing] = useState(false);
1570
- const [loading, setLoading] = useState(false);
1571
- const hasSetDefaultState = useRef(false);
1572
- const tokenBalanceSubtext = formToken
1573
- ? `${t('views.BRIDGE_FORM.content.availableBalancePrefix')} ${tokenValueFormat(formToken?.formattedBalance)}`
1574
- : '';
1575
- // Fee estimates & transactions
1576
- const [isFetching, setIsFetching] = useState(false);
1577
- const [estimates, setEstimates] = useState(undefined);
1578
- const [gasFee, setGasFee] = useState('');
1579
- const [gasFeeFiatValue, setGasFeeFiatValue] = useState('');
1580
- const [tokensOptions, setTokensOptions] = useState([]);
1581
- const [showFeeBreakdown, setShowFeeBreakdown] = useState(false);
1582
- // Not enough ETH to cover gas
1583
- const [showNotEnoughGasDrawer, setShowNotEnoughGasDrawer] = useState(false);
1584
- const [walletAddress, setWalletAddress] = useState('');
1585
- // user rejects transaction
1586
- const [showTxnRejectedState, setShowTxnRejectedState] = useState(false);
1587
- const formatTokenOptionsId = useCallback((symbol, address) => {
1588
- if (!address)
1589
- return symbol.toLowerCase();
1590
- return `${symbol.toLowerCase()}-${address.toLowerCase()}`;
1591
- }, []);
1592
- const gasFiatAmount = `${t('views.BRIDGE_FORM.fees.fiatPricePrefix')} ${gasFeeFiatValue}`;
1593
- useEffect(() => {
1594
- if (tokenBalances.length === 0)
1595
- return;
1596
- // WT-1350 removing ETH as possible bridge option from being selected
1597
- // balance > 0 AND token is not ETH
1598
- const options = tokenBalances
1599
- .filter((tokenBalance) => tokenBalance.balance.gt(0))
1600
- .map((tokenBalance) => ({
1601
- id: formatTokenOptionsId(tokenBalance.token.symbol, tokenBalance.token.address),
1602
- name: tokenBalance.token.name,
1603
- symbol: tokenBalance.token.symbol,
1604
- icon: tokenBalance.token.icon,
1605
- balance: {
1606
- formattedFiatAmount: cryptoFiatState.conversions.size === 0 ? formatZeroAmount('')
1607
- : calculateCryptoToFiat(tokenBalance.formattedBalance, tokenBalance.token.symbol, cryptoFiatState.conversions),
1608
- formattedAmount: tokenValueFormat(tokenBalance.formattedBalance),
1609
- },
1610
- }));
1611
- setTokensOptions(options);
1612
- if (!hasSetDefaultState.current) {
1613
- hasSetDefaultState.current = true;
1614
- if (defaultTokenAddress) {
1615
- setFormToken(tokenBalances.find((b) => (isNativeToken(b.token.address) && defaultTokenAddress?.toLocaleUpperCase() === NATIVE)
1616
- || (b.token.address?.toLowerCase() === defaultTokenAddress?.toLowerCase())));
1617
- }
1618
- }
1619
- }, [
1620
- tokenBalances,
1621
- cryptoFiatState.conversions,
1622
- defaultTokenAddress,
1623
- hasSetDefaultState.current,
1624
- formatTokenOptionsId,
1625
- formatZeroAmount,
1626
- ]);
1627
- useEffect(() => {
1628
- // This useEffect is for populating the form
1629
- // with values from context when the user
1630
- // has selected the back button from the review screen
1631
- if (!amount || !token)
1632
- return;
1633
- setFormAmount(amount);
1634
- for (let i = 0; i < tokenBalances.length; i++) {
1635
- const balance = tokenBalances[i];
1636
- if (balance.token.address === token.address) {
1637
- setFormToken(balance);
1638
- break;
1639
- }
1640
- }
1641
- bridgeDispatch({
1642
- payload: {
1643
- type: BridgeActions.SET_TOKEN_AND_AMOUNT,
1644
- token: null,
1645
- amount: '',
1646
- },
1647
- });
1648
- }, [amount, token, tokenBalances]);
1649
- const selectedOption = useMemo(() => (formToken && formToken.token
1650
- ? formatTokenOptionsId(formToken.token.symbol, formToken.token.address)
1651
- : undefined), [formToken, tokenBalances, cryptoFiatState.conversions, formatTokenOptionsId]);
1652
- const canFetchEstimates = () => {
1653
- if (Number.isNaN(parseFloat(formAmount)))
1654
- return false;
1655
- if (parseFloat(formAmount) <= 0)
1656
- return false;
1657
- if (!formToken)
1658
- return false;
1659
- if (isFetching)
1660
- return false;
1661
- if (!from || !from.walletAddress)
1662
- return false;
1663
- if (!to || !to.walletAddress)
1664
- return false;
1665
- return true;
1666
- };
1667
- const fetchEstimates = async (silently = false) => {
1668
- if (!canFetchEstimates())
1669
- return;
1670
- // setIsFetching within this if statement
1671
- // to allow the user to edit the form
1672
- // even if a new quote is fetching silently
1673
- if (!silently) {
1674
- setLoading(true);
1675
- setIsFetching(true);
1676
- }
1677
- // Prevent silently fetching and set a new fee estimate
1678
- // if the user has updated and the widget is already
1679
- // fetching or the user is updating the inputs.
1680
- if ((silently && (loading || editing)) || !checkout)
1681
- return;
1682
- const tokenIsNative = isNativeToken(formToken?.token.address);
1683
- const amountToBridge = tokenIsNative
1684
- ? utils.parseUnits(formAmount)
1685
- : utils.parseUnits(formAmount, formToken?.token.decimals);
1686
- const tokenAddress = tokenIsNative ? NATIVE.toUpperCase() : formToken?.token.address;
1687
- const [unsignedApproveTransaction, unsignedTransaction] = await Promise.all([
1688
- tokenBridge.getUnsignedApproveBridgeTx({
1689
- senderAddress: from.walletAddress,
1690
- token: tokenAddress ?? NATIVE.toUpperCase(),
1691
- amount: amountToBridge,
1692
- sourceChainId: from.network.toString(),
1693
- destinationChainId: to.network.toString(),
1694
- }),
1695
- tokenBridge.getUnsignedBridgeTx({
1696
- senderAddress: from.walletAddress,
1697
- recipientAddress: to.walletAddress,
1698
- token: tokenAddress ?? NATIVE.toUpperCase(),
1699
- amount: amountToBridge,
1700
- sourceChainId: from.network.toString(),
1701
- destinationChainId: to.network.toString(),
1702
- gasMultiplier: 1.1,
1703
- }),
1704
- ]);
1705
- const transactionFeeData = unsignedTransaction.feeData;
1706
- const { totalFees, approvalFee } = transactionFeeData;
1707
- let rawTotalFees = totalFees;
1708
- if (!unsignedApproveTransaction.unsignedTx) {
1709
- rawTotalFees = totalFees.sub(approvalFee);
1710
- }
1711
- const gasEstimateResult = {
1712
- gasEstimateType: GasEstimateType.BRIDGE_TO_L2,
1713
- fees: { totalFees: rawTotalFees },
1714
- token: checkout.config.networkMap.get(from.network)?.nativeCurrency,
1715
- };
1716
- setEstimates(gasEstimateResult);
1717
- const estimatedAmount = utils.formatUnits(gasEstimateResult?.fees?.totalFees || 0, DEFAULT_TOKEN_DECIMALS);
1718
- setGasFee(estimatedAmount);
1719
- setGasFeeFiatValue(calculateCryptoToFiat(estimatedAmount, gasEstimateResult?.token?.symbol || '', cryptoFiatState.conversions));
1720
- if (!silently) {
1721
- setLoading(false);
1722
- setIsFetching(false);
1723
- }
1724
- };
1725
- const insufficientFundsForGas = useMemo(() => {
1726
- const nativeTokenBalance = tokenBalances
1727
- .find((balance) => isNativeToken(balance.token.address));
1728
- if (!nativeTokenBalance) {
1729
- return true;
1730
- }
1731
- const tokenIsNative = isNativeToken(formToken?.token.address);
1732
- const gasAmount = utils.parseUnits(gasFee.length !== 0 ? gasFee : '0');
1733
- const additionalAmount = tokenIsNative && !Number.isNaN(parseFloat(formAmount))
1734
- ? utils.parseUnits(formAmount)
1735
- : BigNumber.from('0');
1736
- return gasAmount.add(additionalAmount).gt(nativeTokenBalance.balance);
1737
- }, [gasFee, tokenBalances, formToken, formAmount]);
1738
- // Silently refresh the quote
1739
- useInterval(() => fetchEstimates(true), DEFAULT_QUOTE_REFRESH_INTERVAL);
1740
- useEffect(() => {
1741
- if (editing)
1742
- return;
1743
- (async () => await fetchEstimates())();
1744
- }, [formAmount, formToken, editing]);
1745
- const onTextInputFocus = () => {
1746
- setEditing(true);
1747
- };
1748
- const handleBridgeAmountChange = (value) => {
1749
- setFormAmount(value);
1750
- if (amountError) {
1751
- const validateAmountError = validateAmount(value, formToken?.formattedBalance);
1752
- setAmountError(validateAmountError);
1753
- }
1754
- if (!formToken)
1755
- return;
1756
- setAmountFiatValue(calculateCryptoToFiat(value, formToken.token.symbol, cryptoFiatState.conversions));
1757
- };
1758
- const handleAmountInputBlur = (value) => {
1759
- setEditing(false);
1760
- setFormAmount(value);
1761
- if (amountError) {
1762
- const validateAmountError = validateAmount(value, formToken?.formattedBalance);
1763
- setAmountError(validateAmountError);
1764
- }
1765
- if (!formToken)
1766
- return;
1767
- setAmountFiatValue(calculateCryptoToFiat(value, formToken.token.symbol, cryptoFiatState.conversions));
1768
- };
1769
- const handleSelectTokenChange = (value) => {
1770
- const selected = tokenBalances.find((tokenBalance) => (value === formatTokenOptionsId(tokenBalance.token.symbol, tokenBalance.token.address)));
1771
- if (!selected)
1772
- return;
1773
- setFormToken(selected);
1774
- setTokenError('');
1775
- };
1776
- useEffect(() => {
1777
- cryptoFiatDispatch({
1778
- payload: {
1779
- type: CryptoFiatActions.SET_TOKEN_SYMBOLS,
1780
- tokenSymbols: allowedTokens.map((allowedToken) => allowedToken.symbol),
1781
- },
1782
- });
1783
- }, [cryptoFiatDispatch, allowedTokens]);
1784
- useEffect(() => {
1785
- if (!formAmount)
1786
- return;
1787
- if (!formToken)
1788
- return;
1789
- setAmountFiatValue(calculateCryptoToFiat(formAmount, formToken.token.symbol, cryptoFiatState.conversions));
1790
- }, [formAmount, formToken]);
1791
- useEffect(() => {
1792
- (async () => {
1793
- if (!from?.web3Provider)
1794
- return;
1795
- const address = await from.web3Provider.getSigner().getAddress();
1796
- setWalletAddress((previous) => {
1797
- if (previous !== '' && previous !== address) {
1798
- setFormToken(undefined);
1799
- }
1800
- return address;
1801
- });
1802
- })();
1803
- }, [from?.web3Provider, tokenBalances]);
1804
- const bridgeFormValidator = useCallback(() => {
1805
- const validateTokenError = validateToken(formToken);
1806
- const validateAmountError = validateAmount(formAmount, formToken?.formattedBalance);
1807
- if (validateTokenError)
1808
- setTokenError(validateTokenError);
1809
- if (validateAmountError)
1810
- setAmountError(validateAmountError);
1811
- if (validateTokenError || validateAmountError)
1812
- return false;
1813
- return true;
1814
- }, [formToken, formAmount, setTokenError, setAmountError]);
1815
- const submitBridge = useCallback(async () => {
1816
- if (!bridgeFormValidator())
1817
- return;
1818
- if (!checkout || !from?.web3Provider || !formToken)
1819
- return;
1820
- if (insufficientFundsForGas) {
1821
- setShowNotEnoughGasDrawer(true);
1822
- return;
1823
- }
1824
- track({
1825
- userJourney: UserJourney.BRIDGE,
1826
- screen: 'TokenAmount',
1827
- control: 'Review',
1828
- controlType: 'Button',
1829
- extras: {
1830
- tokenAddress: formToken.token.address,
1831
- amount: formAmount,
1832
- },
1833
- });
1834
- bridgeDispatch({
1835
- payload: {
1836
- type: BridgeActions.SET_TOKEN_AND_AMOUNT,
1837
- token: formToken.token,
1838
- amount: formAmount,
1839
- },
1840
- });
1841
- viewDispatch({
1842
- payload: {
1843
- type: ViewActions.UPDATE_VIEW,
1844
- view: {
1845
- type: BridgeWidgetViews.BRIDGE_REVIEW,
1846
- },
1847
- },
1848
- });
1849
- }, [
1850
- checkout,
1851
- from?.web3Provider,
1852
- bridgeFormValidator,
1853
- insufficientFundsForGas,
1854
- formToken,
1855
- ]);
1856
- const retrySubmitBridge = async () => {
1857
- setShowTxnRejectedState(false);
1858
- await submitBridge();
1859
- };
1860
- return (jsxs(Box, { testId: testId, sx: bridgeFormWrapperStyles, children: [jsxs(Box, { sx: { paddingX: 'base.spacing.x4' }, children: [jsx(Heading, { testId: `${testId}-content-heading`, size: "small", weight: "regular", sx: { paddingBottom: 'base.spacing.x4' }, children: t('views.BRIDGE_FORM.content.title') }), (!defaultTokenAddress || !isTokenBalancesLoading) && (jsxs(Box, { sx: formInputsContainerStyles, children: [jsx(SelectForm, { testId: "bridge-token", options: tokensOptions, optionsLoading: isTokenBalancesLoading, coinSelectorHeading: t('views.BRIDGE_FORM.bridgeForm.from.selectorTitle'), selectedOption: selectedOption, subtext: tokenBalanceSubtext, textAlign: "left", errorMessage: tokenError, onSelectChange: (option) => handleSelectTokenChange(option), disabled: isFetching }), jsx(TextInputForm, { testId: "bridge-amount", value: formAmount, placeholder: t('views.BRIDGE_FORM.bridgeForm.from.inputPlaceholder'), subtext: `${t('views.BRIDGE_FORM.content.fiatPricePrefix')} $${formatZeroAmount(amountFiatValue, true)}`, validator: amountInputValidation, onTextInputFocus: onTextInputFocus, onTextInputChange: (value) => handleBridgeAmountChange(value), onTextInputBlur: (value) => handleAmountInputBlur(value), textAlign: "right", errorMessage: amountError, disabled: isFetching })] })), defaultTokenAddress && isTokenBalancesLoading && (jsx(TokenSelectShimmer, { sx: formInputsContainerStyles })), gasFee && (jsx(Box, { sx: { paddingY: 'base.spacing.x2' }, children: jsxs(Accordion, { targetClickOveride: () => setShowFeeBreakdown(true), sx: gasAmountAccordionStyles, children: [jsx(Accordion.TargetLeftSlot, { children: jsx(Body, { size: "medium", sx: gasAmountHeadingStyles$1, children: t('views.BRIDGE_FORM.fees.title') }) }), jsx(Accordion.TargetRightSlot, { children: jsx(PriceDisplay, { testId: "bridge-gas-fee__priceDisplay", fiatAmount: `${t('views.BRIDGE_FORM.fees.fiatPricePrefix')} ${gasFeeFiatValue}`, price: `${estimates?.token?.symbol} ${tokenValueFormat(gasFee)}` }) })] }) }))] }), jsx(FeesBreakdown, { totalFiatAmount: gasFiatAmount, totalAmount: gasFee, tokenSymbol: estimates?.token?.symbol ?? '', fees: [
1861
- {
1862
- label: t('drawers.feesBreakdown.fees.gas.label'),
1863
- fiatAmount: gasFiatAmount,
1864
- amount: gasFee,
1865
- },
1866
- ], visible: showFeeBreakdown, onCloseDrawer: () => setShowFeeBreakdown(false) }), jsxs(Box, { sx: bridgeFormButtonContainerStyles, children: [jsx(Button, { testId: `${testId}-button`, variant: "primary", onClick: submitBridge, disabled: loading, size: "large", children: loading ? (jsx(Button.Icon, { icon: "Loading", sx: bridgeButtonIconLoadingStyle$1 })) : t('views.BRIDGE_FORM.bridgeForm.buttonText') }), jsx(TransactionRejected, { visible: showTxnRejectedState, showHeaderBar: false, onCloseDrawer: () => setShowTxnRejectedState(false), onRetry: retrySubmitBridge }), jsx(NotEnoughGas, { environment: checkout.config.environment, visible: showNotEnoughGasDrawer, showHeaderBar: false, onCloseDrawer: () => setShowNotEnoughGasDrawer(false), walletAddress: walletAddress, showAdjustAmount: isNativeToken(formToken?.token.address), tokenSymbol: from?.network === getL1ChainId(checkout?.config)
1867
- ? ETH_TOKEN_SYMBOL
1868
- : IMX_TOKEN_SYMBOL, onAddCoinsClick: () => {
1869
- viewDispatch({
1870
- payload: {
1871
- type: ViewActions.UPDATE_VIEW,
1872
- view: {
1873
- type: SharedViews.TOP_UP_VIEW,
1874
- },
1875
- },
1876
- });
1877
- } })] })] }));
1878
- }
1879
-
1880
- const REFRESH_TOKENS_INTERVAL_MS = 10000;
1881
- function Bridge({ amount, tokenAddress }) {
1882
- const { t } = useTranslation();
1883
- const { bridgeState, bridgeDispatch } = useContext(BridgeContext);
1884
- const { checkout, from } = bridgeState;
1885
- const { eventTargetState: { eventTarget } } = useContext(EventTargetContext);
1886
- const [isTokenBalancesLoading, setIsTokenBalancesLoading] = useState(false);
1887
- const showBackButton = true;
1888
- const { page } = useAnalytics();
1889
- useEffect(() => {
1890
- if (amount || tokenAddress) {
1891
- page({
1892
- userJourney: UserJourney.BRIDGE,
1893
- screen: 'TokenAmount',
1894
- extras: {
1895
- amount,
1896
- tokenAddress,
1897
- },
1898
- });
1899
- }
1900
- }, []);
1901
- // This is used to refresh the balances after the Bridge widget
1902
- // has been loaded so that processing transfers will be eventually
1903
- // reflected.
1904
- const refreshBalances = useCallback(async () => {
1905
- if (!checkout || !from?.web3Provider)
1906
- return;
1907
- try {
1908
- const tokensAndBalances = await getAllowedBalances({
1909
- checkout,
1910
- provider: from.web3Provider,
1911
- allowTokenListType: TokenFilterTypes.BRIDGE,
1912
- // Skip retry given that in this case it is not needed;
1913
- // refreshBalances will be, automatically, called again
1914
- // after REFRESH_TOKENS_INTERVAL_MS.
1915
- retryPolicy: { retryIntervalMs: 0, retries: 0 },
1916
- });
1917
- // Why? Check getAllowedBalances
1918
- if (tokensAndBalances === undefined)
1919
- return;
1920
- bridgeDispatch({
1921
- payload: {
1922
- type: BridgeActions.SET_TOKEN_BALANCES,
1923
- tokenBalances: tokensAndBalances.allowedBalances,
1924
- },
1925
- });
1926
- bridgeDispatch({
1927
- payload: {
1928
- type: BridgeActions.SET_ALLOWED_TOKENS,
1929
- allowedTokens: tokensAndBalances.allowList.tokens,
1930
- },
1931
- });
1932
- // Ignore errors given that this is a background refresh
1933
- // and the logic will retry anyways.
1934
- }
1935
- catch (e) {
1936
- // eslint-disable-next-line no-console
1937
- console.debug(e);
1938
- }
1939
- }, [checkout, from?.web3Provider]);
1940
- useInterval(refreshBalances, REFRESH_TOKENS_INTERVAL_MS);
1941
- useEffect(() => {
1942
- if (!checkout || !from?.web3Provider)
1943
- return;
1944
- setIsTokenBalancesLoading(true);
1945
- refreshBalances().finally(() => setIsTokenBalancesLoading(false));
1946
- }, [checkout, from?.web3Provider]);
1947
- return (jsx(SimpleLayout, { testId: "bridge-view", header: (jsx(HeaderNavigation, { showBack: showBackButton, title: t('views.BRIDGE_FORM.header.title'), onCloseButtonClick: () => sendBridgeWidgetCloseEvent(eventTarget) })), footer: jsx(FooterLogo, {}), children: jsx(BridgeForm, { testId: "bridge-form", defaultAmount: amount, defaultTokenAddress: tokenAddress, isTokenBalancesLoading: isTokenBalancesLoading }) }));
1948
- }
1949
-
1950
- const topMenuItemStyles = {
1951
- borderBottomLeftRadius: '0px',
1952
- borderBottomRightRadius: '0px',
1953
- marginBottom: '2px',
1954
- };
1955
- const bottomMenuItemStyles = {
1956
- borderTopLeftRadius: '0px',
1957
- borderTopRightRadius: '0px',
1958
- backgroundColor: 'base.color.translucent.emphasis.100',
1959
- };
1960
- const bridgeReviewWrapperStyles = {
1961
- height: '100%',
1962
- display: 'flex',
1963
- flexDirection: 'column',
1964
- paddingX: 'base.spacing.x4',
1965
- };
1966
- const bridgeReviewHeadingStyles = {
1967
- paddingTop: 'base.spacing.x10',
1968
- paddingBottom: 'base.spacing.x4',
1969
- };
1970
- const arrowIconWrapperStyles = {
1971
- display: 'flex',
1972
- flexDirection: 'column',
1973
- alignItems: 'center',
1974
- paddingY: 'base.spacing.x1',
1975
- };
1976
- const arrowIconStyles = {
1977
- width: 'base.icon.size.300',
1978
- transform: 'rotate(270deg)',
1979
- };
1980
- const gasAmountHeadingStyles = {
1981
- marginBottom: 'base.spacing.x4',
1982
- color: 'base.color.text.secondary',
1983
- };
1984
- const bridgeButtonIconLoadingStyle = {
1985
- width: 'base.icon.size.400',
1986
- };
1987
-
1988
- const networkIcon = {
1989
- [ChainId.IMTBL_ZKEVM_DEVNET]: 'Immutable',
1990
- [ChainId.IMTBL_ZKEVM_MAINNET]: 'Immutable',
1991
- [ChainId.IMTBL_ZKEVM_TESTNET]: 'Immutable',
1992
- [ChainId.ETHEREUM]: 'EthToken',
1993
- [ChainId.SEPOLIA]: 'EthToken',
1994
- };
1995
- const logo = {
1996
- [WalletProviderName.PASSPORT]: 'PassportSymbolOutlined',
1997
- [WalletProviderName.METAMASK]: 'MetaMaskSymbol',
1998
- };
1999
- const testId = 'bridge-review-summary';
2000
- function BridgeReviewSummary() {
2001
- const { t } = useTranslation();
2002
- const { viewDispatch } = useContext(ViewContext);
2003
- const { bridgeState: { checkout, tokenBridge, from, to, token, amount, }, } = useContext(BridgeContext);
2004
- const { track } = useAnalytics();
2005
- const { cryptoFiatState } = useContext(CryptoFiatContext);
2006
- const [showFeeBreakdown, setShowFeeBreakdown] = useState(false);
2007
- const [loading, setLoading] = useState(false);
2008
- const [estimates, setEstimates] = useState(undefined);
2009
- const [gasFee, setGasFee] = useState('');
2010
- const [gasFeeFiatValue, setGasFeeFiatValue] = useState('');
2011
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
2012
- const [approveTransaction, setApproveTransaction] = useState(undefined);
2013
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
2014
- const [transaction, setTransaction] = useState(undefined);
2015
- const walletProviderName = (provider) => (isPassportProvider(provider)
2016
- ? WalletProviderName.PASSPORT
2017
- : WalletProviderName.METAMASK);
2018
- const displayAmount = useMemo(() => (token?.symbol ? `${token?.symbol} ${amount}` : `${amount}`), [token, amount]);
2019
- const fromFiatAmount = useMemo(() => {
2020
- if (!amount || !token)
2021
- return '';
2022
- return calculateCryptoToFiat(amount, token.symbol, cryptoFiatState.conversions);
2023
- }, [token, amount]);
2024
- const fromAddress = useMemo(() => {
2025
- if (!from)
2026
- return '-';
2027
- return from.walletAddress;
2028
- }, [from]);
2029
- const fromWalletProviderName = useMemo(() => walletProviderName(from?.web3Provider), [from]);
2030
- const fromNetwork = useMemo(() => from && from.network, [from]);
2031
- const toAddress = useMemo(() => {
2032
- if (!to)
2033
- return '-';
2034
- return to.walletAddress;
2035
- }, [to]);
2036
- const toWalletProviderName = useMemo(() => walletProviderName(to?.web3Provider), [to]);
2037
- const toNetwork = useMemo(() => to?.network, [to]);
2038
- const fetchGasEstimate = useCallback(async () => {
2039
- if (!tokenBridge || !amount || !from || !to || !token)
2040
- return;
2041
- const [unsignedApproveTransaction, unsignedTransaction] = await Promise.all([
2042
- tokenBridge.getUnsignedApproveBridgeTx({
2043
- senderAddress: fromAddress,
2044
- token: token.address ?? NATIVE.toUpperCase(),
2045
- amount: utils.parseUnits(amount, token.decimals),
2046
- sourceChainId: from?.network.toString(),
2047
- destinationChainId: to?.network.toString(),
2048
- }),
2049
- tokenBridge.getUnsignedBridgeTx({
2050
- senderAddress: fromAddress,
2051
- recipientAddress: toAddress,
2052
- token: token.address ?? NATIVE.toUpperCase(),
2053
- amount: utils.parseUnits(amount, token.decimals),
2054
- sourceChainId: from?.network.toString(),
2055
- destinationChainId: to?.network.toString(),
2056
- gasMultiplier: 1.1,
2057
- }),
2058
- ]);
2059
- setApproveTransaction(unsignedApproveTransaction);
2060
- setTransaction(unsignedTransaction);
2061
- // todo: add approval gas fees
2062
- const transactionFeeData = unsignedTransaction.feeData;
2063
- const { totalFees, approvalFee } = transactionFeeData;
2064
- let rawTotalFees = totalFees;
2065
- if (!unsignedApproveTransaction.unsignedTx) {
2066
- rawTotalFees = totalFees.sub(approvalFee);
2067
- }
2068
- const gasEstimateResult = {
2069
- gasEstimateType: GasEstimateType.BRIDGE_TO_L2,
2070
- fees: { totalFees: rawTotalFees },
2071
- token: checkout.config.networkMap.get(from.network)?.nativeCurrency,
2072
- };
2073
- setEstimates(gasEstimateResult);
2074
- const estimatedAmount = utils.formatUnits(gasEstimateResult?.fees.totalFees || 0, DEFAULT_TOKEN_DECIMALS);
2075
- setGasFee(estimatedAmount);
2076
- setGasFeeFiatValue(calculateCryptoToFiat(estimatedAmount, gasEstimateResult?.token?.symbol || '', cryptoFiatState.conversions));
2077
- }, [checkout, tokenBridge]);
2078
- useInterval(() => fetchGasEstimate(), DEFAULT_QUOTE_REFRESH_INTERVAL);
2079
- useEffect(() => {
2080
- (async () => {
2081
- setLoading(true);
2082
- await fetchGasEstimate();
2083
- setLoading(false);
2084
- })();
2085
- }, []);
2086
- const submitBridge = useCallback(async () => {
2087
- if (!approveTransaction || !transaction)
2088
- return;
2089
- track({
2090
- userJourney: UserJourney.BRIDGE,
2091
- screen: 'Summary',
2092
- control: 'Submit',
2093
- controlType: 'Button',
2094
- extras: {
2095
- fromWalletAddress: fromAddress,
2096
- fromNetwork,
2097
- fromWallet: {
2098
- address: fromAddress,
2099
- isPassportWallet: isPassportProvider(from?.web3Provider),
2100
- isMetaMask: isMetaMaskProvider(from?.web3Provider),
2101
- },
2102
- toWalletAddress: toAddress,
2103
- toNetwork,
2104
- toWallet: {
2105
- address: toAddress,
2106
- isPassportWallet: isPassportProvider(to?.web3Provider),
2107
- isMetaMask: isMetaMaskProvider(to?.web3Provider),
2108
- },
2109
- amount,
2110
- fiatAmount: fromFiatAmount,
2111
- tokenAddress: token?.address,
2112
- },
2113
- });
2114
- viewDispatch({
2115
- payload: {
2116
- type: ViewActions.UPDATE_VIEW,
2117
- view: {
2118
- type: BridgeWidgetViews.APPROVE_TRANSACTION,
2119
- approveTransaction,
2120
- transaction,
2121
- },
2122
- },
2123
- });
2124
- }, [viewDispatch, approveTransaction, transaction]);
2125
- return (jsxs(Box, { testId: testId, sx: bridgeReviewWrapperStyles, children: [jsx(Heading, { testId: `${testId}-heading`, size: "small", weight: "regular", sx: bridgeReviewHeadingStyles, children: t('views.BRIDGE_REVIEW.heading') }), jsxs(MenuItem, { testId: `${testId}-from-amount`, size: "small", emphasized: true, sx: topMenuItemStyles, children: [jsx(MenuItem.Label, { size: "small", sx: { marginBottom: 'base.spacing.x4', fontWeight: 'bold' }, children: t('views.BRIDGE_REVIEW.fromLabel.amountHeading') }), jsx(MenuItem.Caption, {}), jsx(MenuItem.PriceDisplay, { use: jsx(Heading, { size: "xSmall", weight: "light" }), price: displayAmount ?? '-', fiatAmount: `${t('views.BRIDGE_REVIEW.fiatPricePrefix')}${fromFiatAmount}` })] }), jsxs(MenuItem, { testId: `${testId}-from-address`, size: "xSmall", emphasized: true, sx: bottomMenuItemStyles, children: [fromWalletProviderName && (jsx(MenuItem.FramedLogo, { logo: logo[fromWalletProviderName], sx: { backgroundColor: 'base.color.translucent.standard.200' } })), jsxs(MenuItem.Label, { children: [jsx("strong", { children: t('views.BRIDGE_REVIEW.fromLabel.heading') }), ' ', jsx(Body, { size: "small", sx: {
2126
- color: 'base.color.text.secondary',
2127
- }, children: abbreviateAddress(fromAddress ?? '') })] }), fromNetwork && (jsx(MenuItem.IntentIcon, { icon: networkIcon[fromNetwork], sx: networkIconStyles(fromNetwork) }))] }), jsx(Box, { sx: arrowIconWrapperStyles, children: jsx(Icon, { icon: "ArrowBackward", sx: arrowIconStyles }) }), jsxs(MenuItem, { testId: `${testId}-to-address`, size: "xSmall", emphasized: true, sx: topMenuItemStyles, children: [toWalletProviderName && (jsx(MenuItem.FramedLogo, { logo: logo[toWalletProviderName], sx: { backgroundColor: 'base.color.translucent.standard.200' } })), jsxs(MenuItem.Label, { children: [jsx("strong", { children: t('views.BRIDGE_REVIEW.toLabel.heading') }), ' ', jsx(Body, { size: "small", sx: {
2128
- color: 'base.color.text.secondary',
2129
- }, children: abbreviateAddress(toAddress ?? '') })] }), toNetwork && (jsx(MenuItem.IntentIcon, { icon: networkIcon[toNetwork], sx: networkIconStyles(toNetwork) }))] }), gasFee && (jsxs(Accordion, { targetClickOveride: () => setShowFeeBreakdown(true), sx: bottomMenuItemStyles, children: [jsx(Accordion.TargetLeftSlot, { children: jsx(Body, { size: "medium", sx: gasAmountHeadingStyles, children: t('views.BRIDGE_REVIEW.fees.heading') }) }), jsx(Accordion.TargetRightSlot, { children: jsx(PriceDisplay, { testId: `${testId}-gas-amount__priceDisplay`, fiatAmount: `${t('views.BRIDGE_REVIEW.fiatPricePrefix')}${gasFeeFiatValue}`, price: `${estimates?.token?.symbol} ${tokenValueFormat(gasFee)}` ?? '-' }) })] })), jsx(Box, { sx: {
2130
- flex: 1,
2131
- display: 'flex',
2132
- flexDirection: 'column',
2133
- justifyContent: 'flex-end',
2134
- paddingY: 'base.spacing.x6',
2135
- width: '100%',
2136
- }, children: jsx(Button, { size: "large", sx: { width: '100%' }, onClick: submitBridge, disabled: loading, testId: `${testId}__submit-button`, children: loading ? (jsx(Button.Icon, { icon: "Loading", sx: bridgeButtonIconLoadingStyle })) : t('views.BRIDGE_REVIEW.submitButton.buttonText') }) }), jsx(FeesBreakdown, { totalFiatAmount: `${t('views.BRIDGE_REVIEW.fiatPricePrefix')}${gasFeeFiatValue}`, totalAmount: gasFee, tokenSymbol: estimates?.token?.symbol || '', fees: [
2137
- {
2138
- label: t('drawers.feesBreakdown.fees.gas.label'),
2139
- fiatAmount: `${t('views.BRIDGE_REVIEW.fiatPricePrefix')}${gasFeeFiatValue}`,
2140
- amount: gasFee,
2141
- },
2142
- ], visible: showFeeBreakdown, onCloseDrawer: () => setShowFeeBreakdown(false) })] }));
2143
- }
2144
-
2145
- function BridgeReview() {
2146
- const { t } = useTranslation();
2147
- const { eventTargetState: { eventTarget } } = useContext(EventTargetContext);
2148
- const { page } = useAnalytics();
2149
- useEffect(() => {
2150
- page({
2151
- userJourney: UserJourney.BRIDGE,
2152
- screen: 'Review',
2153
- });
2154
- }, []);
2155
- return (jsx(SimpleLayout, { testId: "bridge-review", header: (jsx(HeaderNavigation, { showBack: true, title: t('views.BRIDGE_REVIEW.layoutHeading'), onCloseButtonClick: () => sendBridgeWidgetCloseEvent(eventTarget) })), footer: (jsx(FooterLogo, {})), children: jsx(BridgeReviewSummary, {}) }));
2156
- }
2157
-
2158
- function RocketHero({ environment, }) {
2159
- const { RiveComponent } = useRive({
2160
- src: `${CHECKOUT_CDN_BASE_URL[environment]}/v1/blob/img/rocket.riv`,
2161
- autoplay: true,
2162
- layout: new Layout({ fit: Fit.Cover }),
2163
- stateMachines: 'State Machine 1',
2164
- });
2165
- return (jsx(Box, { sx: { ...heroBackGroundStyles, background: 'base.color.translucent.emphasis.100' }, children: jsx(Box, { sx: heroImageStyles, rc: jsx(RiveComponent, {}) }) }));
2166
- }
2167
-
2168
- function MoveInProgress({ transactionHash }) {
2169
- const { t } = useTranslation();
2170
- const { eventTargetState: { eventTarget } } = useContext(EventTargetContext);
2171
- const { page } = useAnalytics();
2172
- const { cryptoFiatState } = useContext(CryptoFiatContext);
2173
- const { viewDispatch } = useContext(ViewContext);
2174
- const { bridgeState: { checkout, from, to, token, amount, }, } = useContext(BridgeContext);
2175
- useEffect(() => {
2176
- sendBridgeTransactionSentEvent(eventTarget, transactionHash);
2177
- const fiatAmount = calculateCryptoToFiat(amount, token?.symbol ?? '', cryptoFiatState.conversions);
2178
- page({
2179
- userJourney: UserJourney.BRIDGE,
2180
- screen: 'InProgress',
2181
- extras: {
2182
- fromWalletAddress: from?.walletAddress,
2183
- toWalletAddress: to?.walletAddress,
2184
- amount,
2185
- fiatAmount,
2186
- tokenAddress: token?.address,
2187
- },
2188
- });
2189
- }, []);
2190
- return (jsx(SimpleLayout, { testId: "move-in-progress-view", header: (jsx(HeaderNavigation, { transparent: true, onCloseButtonClick: () => sendBridgeWidgetCloseEvent(eventTarget), rightActions: (jsxs(Fragment, { children: [jsx(ButtCon, { icon: "Minting", sx: ButtonNavigationStyles(), onClick: () => {
2191
- viewDispatch({
2192
- payload: {
2193
- type: ViewActions.UPDATE_VIEW,
2194
- view: { type: BridgeWidgetViews.TRANSACTIONS },
2195
- },
2196
- });
2197
- }, testId: "settings-button" }), jsx(Badge, { isAnimated: true, variant: "guidance", sx: {
2198
- position: 'absolute',
2199
- right: 'base.spacing.x14',
2200
- top: 'base.spacing.x1',
2201
- } })] })) })), footer: (jsx(FooterLogo, {})), heroContent: jsx(RocketHero, { environment: checkout.config.environment }), floatHeader: true, children: jsxs(SimpleTextBody, { heading: t('views.IN_PROGRESS.heading'), children: [t('views.IN_PROGRESS.body1'), jsx("br", {}), jsx("br", {}), t('views.IN_PROGRESS.body2')] }) }));
2202
- }
2203
-
2204
- function ApproveTransaction({ approveTransaction, transaction }) {
2205
- const { t } = useTranslation();
2206
- const { bridgeState } = useContext(BridgeContext);
2207
- const { checkout, from, } = bridgeState;
2208
- const { viewDispatch } = useContext(ViewContext);
2209
- const { eventTargetState: { eventTarget } } = useContext(EventTargetContext);
2210
- const { page } = useAnalytics();
2211
- useEffect(() => {
2212
- page({
2213
- userJourney: UserJourney.BRIDGE,
2214
- screen: 'ApproveTransaction',
2215
- });
2216
- }, []);
2217
- // Local state
2218
- const [actionDisabled, setActionDisabled] = useState(false);
2219
- const [txProcessing, setTxProcessing] = useState(false);
2220
- const [loading, setLoading] = useState(false);
2221
- const [rejectedBridge, setRejectedBridge] = useState(false);
2222
- // Common error view function
2223
- const showErrorView = useCallback(() => {
2224
- viewDispatch({
2225
- payload: {
2226
- type: ViewActions.UPDATE_VIEW,
2227
- view: {
2228
- type: SharedViews.ERROR_VIEW,
2229
- error: new Error('No checkout object or no provider object found'),
2230
- },
2231
- },
2232
- });
2233
- }, [viewDispatch]);
2234
- const goBack = useCallback(() => {
2235
- viewDispatch({
2236
- payload: {
2237
- type: ViewActions.GO_BACK,
2238
- },
2239
- });
2240
- }, [viewDispatch]);
2241
- const handleExceptions = (err) => {
2242
- if (err.type === CheckoutErrorType.UNPREDICTABLE_GAS_LIMIT) {
2243
- viewDispatch({
2244
- payload: {
2245
- type: ViewActions.UPDATE_VIEW,
2246
- view: {
2247
- type: BridgeWidgetViews.BRIDGE_FAILURE,
2248
- reason: 'Unpredictable gas limit',
2249
- },
2250
- },
2251
- });
2252
- return;
2253
- }
2254
- if (err.type === CheckoutErrorType.TRANSACTION_FAILED
2255
- || err.type === CheckoutErrorType.INSUFFICIENT_FUNDS
2256
- || (err.receipt && err.receipt.status === 0)) {
2257
- let reason = 'Transaction failed';
2258
- if (err.type === CheckoutErrorType.INSUFFICIENT_FUNDS)
2259
- reason = 'Insufficient funds';
2260
- if (err.receipt && err.receipt.status === 0)
2261
- reason = 'Transaction failed to settle on chain';
2262
- viewDispatch({
2263
- payload: {
2264
- type: ViewActions.UPDATE_VIEW,
2265
- view: {
2266
- type: BridgeWidgetViews.BRIDGE_FAILURE,
2267
- reason,
2268
- },
2269
- },
2270
- });
2271
- return;
2272
- }
2273
- viewDispatch({
2274
- payload: {
2275
- type: ViewActions.UPDATE_VIEW,
2276
- view: {
2277
- type: SharedViews.ERROR_VIEW,
2278
- error: err,
2279
- },
2280
- },
2281
- });
2282
- };
2283
- const handleApproveBridgeClick = useCallback(async () => {
2284
- let bridgeRejected = false;
2285
- if (!checkout || !from?.web3Provider || !transaction) {
2286
- showErrorView();
2287
- return;
2288
- }
2289
- if (actionDisabled)
2290
- return;
2291
- setActionDisabled(true);
2292
- // Approvals as required
2293
- if (approveTransaction.unsignedTx) {
2294
- try {
2295
- setTxProcessing(true);
2296
- const approveSpendingResult = await checkout.sendTransaction({
2297
- provider: from.web3Provider,
2298
- transaction: approveTransaction.unsignedTx,
2299
- });
2300
- const approvalReceipt = await approveSpendingResult.transactionResponse.wait();
2301
- if (approvalReceipt.status !== 1) {
2302
- viewDispatch({
2303
- payload: {
2304
- type: ViewActions.UPDATE_VIEW,
2305
- view: {
2306
- type: BridgeWidgetViews.BRIDGE_FAILURE,
2307
- reason: 'Transaction failed to settle on chain',
2308
- },
2309
- },
2310
- });
2311
- return;
2312
- }
2313
- }
2314
- catch (error) {
2315
- setTxProcessing(false);
2316
- if (error.type === CheckoutErrorType.USER_REJECTED_REQUEST_ERROR) {
2317
- setRejectedBridge(true);
2318
- bridgeRejected = true;
2319
- }
2320
- else {
2321
- handleExceptions(error);
2322
- }
2323
- }
2324
- finally {
2325
- setActionDisabled(false);
2326
- }
2327
- }
2328
- try {
2329
- if (bridgeRejected)
2330
- return;
2331
- setTxProcessing(true);
2332
- const sendResult = await checkout.sendTransaction({
2333
- provider: from.web3Provider,
2334
- transaction: transaction.unsignedTx,
2335
- });
2336
- setLoading(true);
2337
- const receipt = await sendResult.transactionResponse.wait();
2338
- if (receipt.status === 0) {
2339
- viewDispatch({
2340
- payload: {
2341
- type: ViewActions.UPDATE_VIEW,
2342
- view: {
2343
- type: BridgeWidgetViews.BRIDGE_FAILURE,
2344
- reason: 'Approval transaction failed to settle on chain',
2345
- },
2346
- },
2347
- });
2348
- return;
2349
- }
2350
- viewDispatch({
2351
- payload: {
2352
- type: ViewActions.UPDATE_VIEW,
2353
- view: {
2354
- type: BridgeWidgetViews.IN_PROGRESS,
2355
- transactionHash: receipt.transactionHash,
2356
- },
2357
- },
2358
- });
2359
- }
2360
- catch (error) {
2361
- if (error.type === CheckoutErrorType.USER_REJECTED_REQUEST_ERROR) {
2362
- setRejectedBridge(true);
2363
- }
2364
- else {
2365
- handleExceptions(error);
2366
- }
2367
- }
2368
- finally {
2369
- setLoading(false);
2370
- setTxProcessing(false);
2371
- setActionDisabled(false);
2372
- }
2373
- }, [
2374
- checkout,
2375
- from,
2376
- showErrorView,
2377
- viewDispatch,
2378
- transaction,
2379
- approveTransaction,
2380
- actionDisabled,
2381
- ]);
2382
- return (jsxs(Fragment, { children: [loading && (jsx(LoadingView, { loadingText: t('views.APPROVE_TRANSACTION.loadingView.text'), showFooterLogo: true })), !loading && (jsx(SimpleLayout, { header: (jsx(HeaderNavigation, { transparent: true, showBack: true, onCloseButtonClick: () => sendBridgeWidgetCloseEvent(eventTarget), onBackButtonClick: goBack })), floatHeader: true, heroContent: jsx(WalletApproveHero, {}), footer: (jsxs(Box, { sx: { width: '100%', flexDirection: 'column' }, children: [jsx(FooterButton, { loading: txProcessing, actionText: t(`views.APPROVE_TRANSACTION.${rejectedBridge ? 'footer.retryText' : 'footer.buttonText'}`), onActionClick: handleApproveBridgeClick }), jsx(FooterLogo, {})] })), children: jsx(SimpleTextBody, { heading: t('views.APPROVE_TRANSACTION.content.heading'), children: jsx(Box, { children: t('views.APPROVE_TRANSACTION.content.body') }) }) }))] }));
2383
- }
2384
-
2385
- const containerStyles = {
2386
- display: 'flex',
2387
- flexDirection: 'column',
2388
- alignItems: 'center',
2389
- paddingTop: 'base.spacing.x6',
2390
- paddingBottom: 'base.spacing.x1',
2391
- height: '100%',
2392
- };
2393
- const contentTextStyles = {
2394
- color: 'base.color.text.secondary',
2395
- fontFamily: 'base.font.family.heading.secondary',
2396
- textAlign: 'center',
2397
- marginTop: '15px',
2398
- };
2399
- const actionButtonContainerStyles = {
2400
- display: 'flex',
2401
- flexDirection: 'column',
2402
- justifyContent: 'center',
2403
- gap: 'base.spacing.x2',
2404
- height: '100%',
2405
- width: '100%',
2406
- };
2407
- const actionButtonStyles = {
2408
- width: '100%',
2409
- height: 'base.spacing.x16',
2410
- };
2411
-
2412
- function NotEnoughEthToWithdraw({ visible, onClose, onChangeAccount, }) {
2413
- const { t } = useTranslation();
2414
- const { bridgeState: { checkout } } = useContext(BridgeContext);
2415
- const ethLogo = getEthTokenImage(checkout.config.environment);
2416
- return (jsx(Drawer, { headerBarTitle: undefined, size: "full", onCloseDrawer: onClose, visible: visible, showHeaderBar: false, children: jsx(Drawer.Content, { children: jsxs(Box, { testId: "not-enough-eth-drawer", sx: containerStyles, children: [jsx(CloudImage, { imageUrl: ethLogo, sx: { w: 'base.icon.size.600', h: 'base.icon.size.600' } }), jsx(Heading, { size: "small", sx: contentTextStyles, testId: "not-enough-gas-heading", children: `${t('drawers.notEnoughEthWithdrawal.content.heading1')} ${ETH_TOKEN_SYMBOL} ${t('drawers.notEnoughEthWithdrawal.content.heading2')}` }), jsx(Body, { sx: contentTextStyles, children: `${t('drawers.notEnoughEthWithdrawal.content.body1')} ${ETH_TOKEN_SYMBOL} ${t('drawers.notEnoughEthWithdrawal.content.body2')}` }), jsxs(Box, { sx: actionButtonContainerStyles, children: [jsx(Button, { testId: "not-enough-eth-drawer-retry-button", sx: actionButtonStyles, variant: "tertiary", onClick: onChangeAccount, children: t('drawers.notEnoughEthWithdrawal.buttons.retry') }), jsx(Button, { sx: actionButtonStyles, variant: "tertiary", onClick: onClose, testId: "not-enough-eth-drawer-dismiss-button", children: t('drawers.notEnoughEthWithdrawal.buttons.dismiss') })] })] }) }) }));
2417
- }
2418
-
2419
- function ClaimWithdrawal({ transaction }) {
2420
- const { t } = useTranslation();
2421
- const { bridgeState: { checkout, tokenBridge, from } } = useContext(BridgeContext);
2422
- const { viewDispatch } = useContext(ViewContext);
2423
- const { eventTargetState: { eventTarget } } = useContext(EventTargetContext);
2424
- const { page } = useAnalytics();
2425
- useEffect(() => {
2426
- page({
2427
- userJourney: UserJourney.BRIDGE,
2428
- screen: 'ClaimWithdrawal',
2429
- });
2430
- }, []);
2431
- const [txProcessing, setTxProcessing] = useState(false);
2432
- const [loading, setLoading] = useState(false);
2433
- const [hasWithdrawError, setHasWithdrawError] = useState(false);
2434
- const [withdrawalResponse, setWithdrawalResponse] = useState();
2435
- const [showNotEnoughEthDrawer, setShowNotEnoughEthDrawer] = useState(false);
2436
- const goBack = useCallback(() => {
2437
- viewDispatch({
2438
- payload: {
2439
- type: ViewActions.GO_BACK,
2440
- },
2441
- });
2442
- }, [viewDispatch]);
2443
- /**
2444
- * This effect should load the transaction that should be ready to be withdrawn.
2445
- * There should be a receiver -> details.to_address AND
2446
- * there should be an index -> details.current_status.index
2447
- */
2448
- useEffect(() => {
2449
- const getWithdrawalTxn = async () => {
2450
- if (!tokenBridge || !transaction || transaction.details.current_status?.index === undefined)
2451
- return;
2452
- // get withdrawal transaction from the token bridge by receipient address and index
2453
- setLoading(true);
2454
- try {
2455
- const flowRateWithdrawTxnResponse = await tokenBridge?.getFlowRateWithdrawTx({
2456
- recipient: transaction.details.to_address,
2457
- index: transaction.details.current_status.index,
2458
- });
2459
- setWithdrawalResponse(flowRateWithdrawTxnResponse);
2460
- }
2461
- catch (err) {
2462
- // eslint-disable-next-line no-console
2463
- console.log(err);
2464
- }
2465
- finally {
2466
- setLoading(false);
2467
- }
2468
- };
2469
- getWithdrawalTxn();
2470
- }, [tokenBridge, transaction]);
2471
- const handleWithdrawalClaimClick = useCallback(async ({ forceChangeAccount }) => {
2472
- if (!checkout || !tokenBridge || !from?.web3Provider || !withdrawalResponse)
2473
- return;
2474
- if (!withdrawalResponse.pendingWithdrawal.canWithdraw || !withdrawalResponse.unsignedTx) {
2475
- // eslint-disable-next-line max-len, no-console
2476
- console.log(`Unable to process withdrawal transaction as it is not ready yet. Delay timeout at ${withdrawalResponse.pendingWithdrawal.timeoutEnd} `);
2477
- return;
2478
- }
2479
- let providerToUse = from?.web3Provider;
2480
- const l1ChainId = getL1ChainId(checkout.config);
2481
- setTxProcessing(true);
2482
- if (isPassportProvider(from?.web3Provider) || forceChangeAccount) {
2483
- // user should switch to MetaMask
2484
- try {
2485
- const createProviderResult = await checkout.createProvider({ walletProviderName: WalletProviderName.METAMASK });
2486
- const connectResult = await checkout.connect({
2487
- provider: createProviderResult.provider,
2488
- requestWalletPermissions: true,
2489
- });
2490
- providerToUse = connectResult.provider;
2491
- setShowNotEnoughEthDrawer(false);
2492
- }
2493
- catch (err) {
2494
- // eslint-disable-next-line no-console
2495
- console.log(err);
2496
- setHasWithdrawError(true);
2497
- setTxProcessing(false);
2498
- return;
2499
- }
2500
- }
2501
- /**
2502
- * Gas fee estimation and balance checks are done on a best effort basis.
2503
- * If for some reason the balance calls fail or gas fee data calls fail
2504
- * don't block the transaction from being submitted.
2505
- */
2506
- let gasEstimate;
2507
- let ethGasCostWei = null;
2508
- try {
2509
- try {
2510
- gasEstimate = await providerToUse.estimateGas(withdrawalResponse.unsignedTx);
2511
- }
2512
- catch (err) {
2513
- gasEstimate = BigNumber.from(WITHDRAWAL_CLAIM_GAS_LIMIT);
2514
- }
2515
- let feeData = null;
2516
- try {
2517
- feeData = await providerToUse.getFeeData();
2518
- }
2519
- catch (err) {
2520
- // eslint-disable-next-line no-console
2521
- console.log(err);
2522
- }
2523
- let gasPriceInWei = null;
2524
- if (feeData && feeData.lastBaseFeePerGas && feeData.maxPriorityFeePerGas) {
2525
- gasPriceInWei = feeData.lastBaseFeePerGas.add(feeData.maxPriorityFeePerGas);
2526
- }
2527
- else if (feeData && feeData.gasPrice) {
2528
- gasPriceInWei = feeData.gasPrice;
2529
- }
2530
- if (gasPriceInWei) {
2531
- ethGasCostWei = gasEstimate.mul(gasPriceInWei);
2532
- }
2533
- }
2534
- catch (err) {
2535
- // eslint-disable-next-line no-console
2536
- console.log(err);
2537
- }
2538
- // get L1 balances and do check for enough ETH to cover gas
2539
- try {
2540
- const balancesResult = await checkout.getAllBalances({
2541
- provider: providerToUse,
2542
- chainId: l1ChainId,
2543
- });
2544
- const ethBalance = balancesResult.balances.find((balance) => isNativeToken(balance.token.address));
2545
- if (!ethBalance || ethBalance.balance.lt(ethGasCostWei)) {
2546
- setShowNotEnoughEthDrawer(true);
2547
- setTxProcessing(false);
2548
- return;
2549
- }
2550
- }
2551
- catch (err) {
2552
- // eslint-disable-next-line no-console
2553
- console.log(err);
2554
- }
2555
- // check that provider is connected to L1
2556
- const network = await providerToUse.getNetwork();
2557
- if (network.chainId !== l1ChainId) {
2558
- try {
2559
- const switchNetworkResult = await checkout.switchNetwork({
2560
- provider: providerToUse,
2561
- chainId: l1ChainId,
2562
- });
2563
- providerToUse = switchNetworkResult.provider;
2564
- }
2565
- catch (err) {
2566
- setHasWithdrawError(true);
2567
- setLoading(false);
2568
- // eslint-disable-next-line no-console
2569
- console.log(err);
2570
- return;
2571
- }
2572
- }
2573
- // send transaction to wallet for signing
2574
- try {
2575
- const response = await checkout.sendTransaction({
2576
- provider: providerToUse,
2577
- transaction: withdrawalResponse.unsignedTx,
2578
- });
2579
- viewDispatch({
2580
- payload: {
2581
- type: ViewActions.UPDATE_VIEW,
2582
- view: {
2583
- type: BridgeWidgetViews.CLAIM_WITHDRAWAL_IN_PROGRESS,
2584
- transactionResponse: response.transactionResponse,
2585
- },
2586
- },
2587
- });
2588
- }
2589
- catch (err) {
2590
- // eslint-disable-next-line no-console
2591
- console.log(err);
2592
- setHasWithdrawError(true);
2593
- setTxProcessing(false);
2594
- }
2595
- finally {
2596
- setTxProcessing(false);
2597
- }
2598
- }, [tokenBridge, from, withdrawalResponse]);
2599
- return (jsxs(SimpleLayout, { testId: "claim-withdrawal", header: (jsx(HeaderNavigation, { transparent: true, showBack: true, onCloseButtonClick: () => sendBridgeWidgetCloseEvent(eventTarget), onBackButtonClick: goBack })), floatHeader: true, heroContent: jsx(WalletApproveHero, {}), footer: (jsxs(Box, { sx: {
2600
- width: '100%',
2601
- display: 'flex',
2602
- flexDirection: 'column',
2603
- }, children: [jsx(Box, { sx: {
2604
- pb: 'base.spacing.x5',
2605
- px: 'base.spacing.x6',
2606
- width: '100%',
2607
- display: 'flex',
2608
- flexDirection: 'column',
2609
- }, children: jsx(Button, { testId: "claim-withdrawal-continue-button", size: "large", variant: "primary", disabled: loading, onClick: () => ((txProcessing || loading)
2610
- ? undefined
2611
- : handleWithdrawalClaimClick({ forceChangeAccount: true })), children: loading || txProcessing ? (jsx(Button.Icon, { icon: "Loading", sx: { width: 'base.icon.size.400' } })) : t(`views.CLAIM_WITHDRAWAL.${hasWithdrawError ? 'footer.retryText' : 'footer.buttonText'}`) }) }), jsx(FooterLogo, {})] })), children: [jsxs(SimpleTextBody, { heading: `${t('views.CLAIM_WITHDRAWAL.content.heading')} ${getChainNameById(getL1ChainId(checkout.config))}`, children: [jsx(Box, { sx: { display: 'flex', flexWrap: 'wrap', pb: 'base.spacing.x1' }, children: t('views.CLAIM_WITHDRAWAL.content.body') }), jsxs(Box, { children: [t('views.CLAIM_WITHDRAWAL.content.body2'), jsx(EllipsizedText, { text: transaction.details.to_address.toLowerCase() ?? '' })] })] }), jsx(NotEnoughEthToWithdraw, { visible: showNotEnoughEthDrawer, onClose: () => setShowNotEnoughEthDrawer(false), onChangeAccount: () => handleWithdrawalClaimClick({ forceChangeAccount: true }) })] }));
2612
- }
2613
-
2614
- function BridgeWidget({ checkout, web3Provider, config, amount, tokenAddress, }) {
2615
- const { t } = useTranslation();
2616
- const { environment, isOnRampEnabled, isSwapEnabled, isBridgeEnabled, } = config;
2617
- const { eventTargetState: { eventTarget } } = useContext(EventTargetContext);
2618
- const { page } = useAnalytics();
2619
- const [viewState, viewDispatch] = useReducer(viewReducer, {
2620
- ...initialViewState,
2621
- view: { type: BridgeWidgetViews.WALLET_NETWORK_SELECTION },
2622
- history: [{ type: BridgeWidgetViews.WALLET_NETWORK_SELECTION }],
2623
- });
2624
- const [bridgeState, bridgeDispatch] = useReducer(bridgeReducer, {
2625
- ...initialBridgeState,
2626
- checkout,
2627
- web3Provider: web3Provider ?? null,
2628
- tokenBridge: (() => {
2629
- let bridgeInstance = ETH_SEPOLIA_TO_ZKEVM_TESTNET;
2630
- if (checkout.config.isDevelopment)
2631
- bridgeInstance = ETH_SEPOLIA_TO_ZKEVM_DEVNET;
2632
- if (checkout.config.isProduction)
2633
- bridgeInstance = ETH_MAINNET_TO_ZKEVM_MAINNET;
2634
- // Root provider is always L1
2635
- const rootProvider = new JsonRpcProvider(checkout.config.networkMap.get(getL1ChainId(checkout.config))?.rpcUrls[0]);
2636
- // Child provider is always L2
2637
- const childProvider = new JsonRpcProvider(checkout.config.networkMap.get(getL2ChainId(checkout.config))?.rpcUrls[0]);
2638
- const bridgeConfiguration = new BridgeConfiguration({
2639
- baseConfig: new ImmutableConfiguration({ environment: checkout.config.environment }),
2640
- bridgeInstance,
2641
- rootProvider,
2642
- childProvider,
2643
- });
2644
- return new TokenBridge(bridgeConfiguration);
2645
- })(),
2646
- });
2647
- const viewReducerValues = useMemo(() => ({ viewState, viewDispatch }), [viewState, viewDispatch]);
2648
- const bridgeReducerValues = useMemo(() => ({ bridgeState, bridgeDispatch }), [bridgeState, bridgeDispatch]);
2649
- const goBackToWalletNetworkSelectorClearState = useCallback(() => {
2650
- bridgeDispatch({
2651
- payload: {
2652
- type: BridgeActions.SET_WALLETS_AND_NETWORKS,
2653
- from: null,
2654
- to: null,
2655
- },
2656
- });
2657
- bridgeDispatch({
2658
- payload: {
2659
- type: BridgeActions.SET_TOKEN_AND_AMOUNT,
2660
- amount: '',
2661
- token: null,
2662
- },
2663
- });
2664
- viewDispatch({
2665
- payload: {
2666
- type: ViewActions.GO_BACK_TO,
2667
- view: { type: BridgeWidgetViews.WALLET_NETWORK_SELECTION },
2668
- },
2669
- });
2670
- }, [viewDispatch]);
2671
- const goBackToWalletNetworkSelector = useCallback(() => {
2672
- viewDispatch({
2673
- payload: {
2674
- type: ViewActions.GO_BACK_TO,
2675
- view: { type: BridgeWidgetViews.WALLET_NETWORK_SELECTION },
2676
- },
2677
- });
2678
- }, [viewDispatch]);
2679
- const updateToTransactionsPage = useCallback(() => {
2680
- viewDispatch({
2681
- payload: {
2682
- type: ViewActions.UPDATE_VIEW,
2683
- view: {
2684
- type: BridgeWidgetViews.TRANSACTIONS,
2685
- },
2686
- },
2687
- });
2688
- }, [viewDispatch]);
2689
- const goBackToReview = useCallback(() => {
2690
- viewDispatch({
2691
- payload: {
2692
- type: ViewActions.GO_BACK_TO,
2693
- view: { type: BridgeWidgetViews.BRIDGE_REVIEW },
2694
- },
2695
- });
2696
- }, [viewDispatch]);
2697
- useEffect(() => {
2698
- (async () => {
2699
- bridgeDispatch({
2700
- payload: {
2701
- type: BridgeActions.SET_PROVIDER,
2702
- web3Provider: web3Provider ?? null,
2703
- },
2704
- });
2705
- })();
2706
- }, [web3Provider]);
2707
- return (jsx(ViewContext.Provider, { value: viewReducerValues, children: jsx(BridgeContext.Provider, { value: bridgeReducerValues, children: jsxs(CryptoFiatProvider, { environment: environment, children: [viewState.view.type === BridgeWidgetViews.WALLET_NETWORK_SELECTION && (jsx(WalletNetworkSelectionView, {})), viewState.view.type === BridgeWidgetViews.BRIDGE_FORM && (jsx(Bridge, { amount: amount, tokenAddress: tokenAddress })), viewState.view.type === BridgeWidgetViews.BRIDGE_REVIEW && (jsx(BridgeReview, {})), viewState.view.type === BridgeWidgetViews.IN_PROGRESS && (jsx(MoveInProgress, { transactionHash: viewState.view.transactionHash })), viewState.view.type === BridgeWidgetViews.BRIDGE_FAILURE
2708
- && (jsx(StatusView, { testId: "bridge-fail", statusText: t('views.BRIDGE_FAILURE.bridgeFailureText.statusText'), actionText: t('views.BRIDGE_FAILURE.bridgeFailureText.actionText'), onActionClick: goBackToReview, statusType: StatusType.FAILURE, onRenderEvent: () => {
2709
- let reason = '';
2710
- if (viewState.view.type === BridgeWidgetViews.BRIDGE_FAILURE) {
2711
- reason = viewState.view.reason;
2712
- }
2713
- page({
2714
- userJourney: UserJourney.BRIDGE,
2715
- screen: 'Failed',
2716
- extras: {
2717
- reason,
2718
- },
2719
- });
2720
- sendBridgeFailedEvent(eventTarget, reason);
2721
- } })), viewState.view.type === BridgeWidgetViews.APPROVE_TRANSACTION && (jsx(ApproveTransaction, { approveTransaction: viewState.view.approveTransaction, transaction: viewState.view.transaction })), viewState.view.type === BridgeWidgetViews.TRANSACTIONS && (jsx(Transactions, { onBackButtonClick: goBackToWalletNetworkSelector })), viewState.view.type === BridgeWidgetViews.CLAIM_WITHDRAWAL && (jsx(ClaimWithdrawal, { transaction: viewState.view.transaction })), viewState.view.type === SharedViews.ERROR_VIEW && (jsx(ErrorView, { actionText: t('views.ERROR_VIEW.actionText'), onActionClick: goBackToWalletNetworkSelectorClearState, onCloseClick: () => sendBridgeWidgetCloseEvent(eventTarget), errorEventAction: () => {
2722
- page({
2723
- userJourney: UserJourney.BRIDGE,
2724
- screen: 'Error',
2725
- });
2726
- } })), viewState.view.type === SharedViews.TOP_UP_VIEW && (jsx(TopUpView, { analytics: { userJourney: UserJourney.BRIDGE }, widgetEvent: IMTBLWidgetEvents.IMTBL_BRIDGE_WIDGET_EVENT, checkout: checkout, provider: web3Provider, showOnrampOption: isOnRampEnabled, showSwapOption: isSwapEnabled, showBridgeOption: isBridgeEnabled, onCloseButtonClick: () => sendBridgeWidgetCloseEvent(eventTarget) })), viewState.view.type === BridgeWidgetViews.CLAIM_WITHDRAWAL_IN_PROGRESS && (jsx(ClaimWithdrawalInProgress, { transactionResponse: viewState.view.transactionResponse })), viewState.view.type === BridgeWidgetViews.CLAIM_WITHDRAWAL_SUCCESS && (jsx(StatusView, { statusText: t('views.CLAIM_WITHDRAWAL.IN_PROGRESS.success.text'), actionText: t('views.CLAIM_WITHDRAWAL.IN_PROGRESS.success.actionText'), onRenderEvent: () => {
2727
- page({
2728
- userJourney: UserJourney.BRIDGE,
2729
- screen: 'ClaimWithdrawalSuccess',
2730
- });
2731
- sendBridgeClaimWithdrawalSuccessEvent(eventTarget, viewState.view.transactionHash);
2732
- }, onActionClick: updateToTransactionsPage, statusType: StatusType.SUCCESS, testId: "claim-withdrawal-success-view" })), viewState.view.type === BridgeWidgetViews.CLAIM_WITHDRAWAL_FAILURE && (jsx(StatusView, { statusText: t('views.CLAIM_WITHDRAWAL.IN_PROGRESS.failure.text'), actionText: t('views.CLAIM_WITHDRAWAL.IN_PROGRESS.failure.actionText'), onRenderEvent: () => {
2733
- let reason = '';
2734
- if (viewState.view.type === BridgeWidgetViews.CLAIM_WITHDRAWAL_FAILURE) {
2735
- reason = viewState.view.reason;
2736
- }
2737
- page({
2738
- userJourney: UserJourney.BRIDGE,
2739
- screen: 'ClaimWithdrawalFailure',
2740
- extras: {
2741
- reason,
2742
- },
2743
- });
2744
- sendBridgeClaimWithdrawalFailedEvent(eventTarget, viewState.view.transactionHash, 'Transaction failed');
2745
- }, onActionClick: updateToTransactionsPage, statusType: StatusType.FAILURE, onCloseClick: () => sendBridgeWidgetCloseEvent(eventTarget), testId: "claim-withdrawal-fail-view" }))] }) }) }));
2746
- }
2747
-
2748
- var BridgeWidget$1 = /*#__PURE__*/Object.freeze({
2749
- __proto__: null,
2750
- default: BridgeWidget
2751
- });
2752
-
2753
- export { BridgeWidget as B, BridgeWidget$1 as a, getChainNameById as g };