@dodoex/wallet-web3-react 0.0.1-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/babel.config.js +9 -0
  2. package/dist/index.js +72 -0
  3. package/dist/types/ClientProvider.d.ts +2 -0
  4. package/dist/types/LangProvider.d.ts +11 -0
  5. package/dist/types/WalletConnect/AccountPage.d.ts +11 -0
  6. package/dist/types/WalletConnect/ActivityList.d.ts +20 -0
  7. package/dist/types/WalletConnect/ConnectAlchemy/index.d.ts +6 -0
  8. package/dist/types/WalletConnect/ConnectAlchemy/useConnectAlchemy.d.ts +12 -0
  9. package/dist/types/WalletConnect/ConnectLedger/ErrorDialog.d.ts +4 -0
  10. package/dist/types/WalletConnect/ConnectLedger/LoadingDialog.d.ts +3 -0
  11. package/dist/types/WalletConnect/ConnectLedger/LockedDialog.d.ts +4 -0
  12. package/dist/types/WalletConnect/ConnectLedger/ProtocolDialog.d.ts +6 -0
  13. package/dist/types/WalletConnect/ConnectLedger/SelectAddressDialog.d.ts +8 -0
  14. package/dist/types/WalletConnect/ConnectLedger/SelectPathDialog.d.ts +5 -0
  15. package/dist/types/WalletConnect/ConnectLedger/helper.d.ts +2 -0
  16. package/dist/types/WalletConnect/ConnectLedger/index.d.ts +6 -0
  17. package/dist/types/WalletConnect/ConnectPage.d.ts +9 -0
  18. package/dist/types/WalletConnect/HasBalanceTokenList.d.ts +4 -0
  19. package/dist/types/WalletConnect/ReceiveTokenPage.d.ts +4 -0
  20. package/dist/types/WalletConnect/SendTokenPage.d.ts +5 -0
  21. package/dist/types/WalletConnect/WalletDialog.d.ts +6 -0
  22. package/dist/types/WalletConnectProvider.d.ts +72 -0
  23. package/dist/types/components/AddressWithLinkAndCopy.d.ts +28 -0
  24. package/dist/types/components/Dialog.d.ts +15 -0
  25. package/dist/types/components/TokenLogo.d.ts +26 -0
  26. package/dist/types/components/WalletTag.d.ts +7 -0
  27. package/dist/types/constants/localstorage.d.ts +6 -0
  28. package/dist/types/hooks/useConnectWalet.d.ts +30 -0
  29. package/dist/types/hooks/useFetchFiatPrice.d.ts +3 -0
  30. package/dist/types/hooks/useFetchTokensBalance.d.ts +14 -0
  31. package/dist/types/hooks/useHasBalanceTokenList.d.ts +21 -0
  32. package/dist/types/hooks/useTransactionList.d.ts +272 -0
  33. package/dist/types/index.d.ts +4 -0
  34. package/dist/types/utils/formatter.d.ts +20 -0
  35. package/dist/types/utils/time.d.ts +3 -0
  36. package/dist/types/utils/utils.d.ts +2 -0
  37. package/lingui.config.ts +13 -0
  38. package/locales/en.po +251 -0
  39. package/locales/en.ts +1 -0
  40. package/locales/zh.po +249 -0
  41. package/locales/zh.ts +1 -0
  42. package/package.json +68 -0
  43. package/rollup.config.mjs +64 -0
  44. package/src/ClientProvider.tsx +15 -0
  45. package/src/LangProvider.tsx +32 -0
  46. package/src/WalletConnect/AccountPage.tsx +535 -0
  47. package/src/WalletConnect/ActivityList.tsx +597 -0
  48. package/src/WalletConnect/ConnectAlchemy/index.tsx +246 -0
  49. package/src/WalletConnect/ConnectAlchemy/useConnectAlchemy.ts +101 -0
  50. package/src/WalletConnect/ConnectLedger/ErrorDialog.tsx +61 -0
  51. package/src/WalletConnect/ConnectLedger/LoadingDialog.tsx +106 -0
  52. package/src/WalletConnect/ConnectLedger/LockedDialog.tsx +54 -0
  53. package/src/WalletConnect/ConnectLedger/ProtocolDialog.tsx +61 -0
  54. package/src/WalletConnect/ConnectLedger/SelectAddressDialog.tsx +326 -0
  55. package/src/WalletConnect/ConnectLedger/SelectPathDialog.tsx +68 -0
  56. package/src/WalletConnect/ConnectLedger/helper.ts +14 -0
  57. package/src/WalletConnect/ConnectLedger/index.tsx +89 -0
  58. package/src/WalletConnect/ConnectPage.tsx +459 -0
  59. package/src/WalletConnect/HasBalanceTokenList.tsx +201 -0
  60. package/src/WalletConnect/ReceiveTokenPage.tsx +143 -0
  61. package/src/WalletConnect/SendTokenPage.tsx +249 -0
  62. package/src/WalletConnect/WalletDialog.tsx +72 -0
  63. package/src/WalletConnectProvider.tsx +54 -0
  64. package/src/components/AddressWithLinkAndCopy.tsx +200 -0
  65. package/src/components/Dialog.tsx +155 -0
  66. package/src/components/TokenLogo.tsx +165 -0
  67. package/src/components/WalletTag.tsx +113 -0
  68. package/src/constants/localstorage.ts +22 -0
  69. package/src/hooks/useConnectWalet.ts +144 -0
  70. package/src/hooks/useFetchFiatPrice.ts +51 -0
  71. package/src/hooks/useFetchTokensBalance.ts +52 -0
  72. package/src/hooks/useHasBalanceTokenList.ts +157 -0
  73. package/src/hooks/useTransactionList.ts +87 -0
  74. package/src/index.tsx +4 -0
  75. package/src/utils/formatter.ts +102 -0
  76. package/src/utils/time.ts +21 -0
  77. package/src/utils/utils.ts +8 -0
  78. package/tsconfig.json +22 -0
@@ -0,0 +1,459 @@
1
+ import React from 'react';
2
+ import WalletWeb3, { useWalletStore, WalletType } from '@dodoex/wallet-web3';
3
+ import { useConnectWallet, WalletItem } from '../hooks/useConnectWalet';
4
+ import { alpha, Box, ButtonBase, Checkbox, useTheme } from '@dodoex/components';
5
+ import { useWalletConnectContext } from '../WalletConnectProvider';
6
+ import WalletTag from '../components/WalletTag';
7
+ import { ArrowRight, More } from '@dodoex/icons';
8
+ import { Trans } from '@lingui/macro';
9
+ import ConnectLedger from './ConnectLedger';
10
+ import { checkAlchemyCache } from './ConnectAlchemy/useConnectAlchemy';
11
+ import ConnectAlchemy from './ConnectAlchemy';
12
+ import { DialogTitle } from '../components/Dialog';
13
+
14
+ const walletGroupStyle = {
15
+ display: 'grid',
16
+ gap: 12,
17
+ gridTemplateColumns: 'repeat(1, 1fr)',
18
+ alignItems: 'start',
19
+ px: 8,
20
+ py: 6,
21
+ };
22
+
23
+ function WalletGroupItem({
24
+ chainId,
25
+ wallet,
26
+ loggedIn,
27
+ matchChain,
28
+ selectedChainId,
29
+ disabled,
30
+ activeWalletType,
31
+ installed,
32
+ disabledClick,
33
+ onShowLedgerConnect,
34
+ onShowAlchemyConnect,
35
+ }: {
36
+ chainId?: number;
37
+ wallet: WalletItem;
38
+ loggedIn: boolean;
39
+ matchChain: boolean;
40
+ selectedChainId: number | undefined;
41
+ disabled?: boolean;
42
+ activeWalletType?: WalletType;
43
+ installed?: boolean;
44
+ disabledClick: () => void;
45
+ onShowLedgerConnect: () => void;
46
+ onShowAlchemyConnect: () => void;
47
+ }) {
48
+ const theme = useTheme();
49
+ const isChecked =
50
+ loggedIn &&
51
+ activeWalletType === wallet.currentType &&
52
+ (matchChain || activeWalletType.toLocaleLowerCase() === 'walletconnect');
53
+
54
+ const [loading, setLoading] = React.useState(false);
55
+ const { connectTimeout, onConnectTimeout, switchNetwork, onConnected } =
56
+ useWalletConnectContext();
57
+ return (
58
+ <Box
59
+ component={ButtonBase}
60
+ sx={{
61
+ display: 'flex',
62
+ justifyContent: 'space-between',
63
+ p: theme.spacing(10, 12),
64
+ width: '100%',
65
+ color: 'text.primary',
66
+ borderRadius: 8,
67
+ opacity: disabled ? 0.3 : 1,
68
+ '&:hover': {
69
+ backgroundColor: theme.palette.background.tag,
70
+ },
71
+ }}
72
+ onClick={async () => {
73
+ if (disabled) {
74
+ disabledClick();
75
+ return;
76
+ }
77
+ if (isChecked) {
78
+ return;
79
+ }
80
+ if (wallet.currentType === WalletType.LedgerUSB) {
81
+ if (wallet.disabled) return;
82
+ onShowLedgerConnect();
83
+ return;
84
+ }
85
+ if (wallet.currentType === WalletType.Alchemy) {
86
+ if (wallet.disabled) return;
87
+ const hasCache = await checkAlchemyCache(chainId ?? 1);
88
+ if (!hasCache) {
89
+ onShowAlchemyConnect();
90
+ return;
91
+ }
92
+ }
93
+ setLoading(true);
94
+ let timeout: NodeJS.Timeout | undefined = undefined;
95
+ try {
96
+ await Promise.race([
97
+ (async () => {
98
+ if (
99
+ switchNetwork &&
100
+ wallet.currentType === activeWalletType &&
101
+ (!matchChain || !loggedIn) &&
102
+ selectedChainId
103
+ ) {
104
+ const res = await switchNetwork(selectedChainId);
105
+ if (res !== undefined) {
106
+ setLoading(false);
107
+ return;
108
+ }
109
+ }
110
+ if (wallet.onClick) {
111
+ try {
112
+ await wallet.onClick();
113
+ const connectedChainId = useWalletStore.getState().chainId;
114
+ if (onConnected) {
115
+ onConnected(connectedChainId, wallet);
116
+ }
117
+ } finally {
118
+ setLoading(false);
119
+ }
120
+ }
121
+ })(),
122
+ onConnectTimeout
123
+ ? new Promise(
124
+ (_, reject) =>
125
+ (timeout = setTimeout(() => {
126
+ onConnectTimeout();
127
+ reject();
128
+ }, connectTimeout ?? 15000)),
129
+ )
130
+ : undefined,
131
+ ]);
132
+ } catch (error) {
133
+ setLoading(false);
134
+ throw error;
135
+ }
136
+ if (timeout) {
137
+ clearTimeout(timeout);
138
+ }
139
+ }}
140
+ >
141
+ <Box
142
+ sx={{
143
+ position: 'relative',
144
+ display: 'flex',
145
+ alignItems: 'center',
146
+ gap: 12,
147
+ justifyContent: 'center',
148
+ typography: 'body1',
149
+ fontWeight: 600,
150
+ }}
151
+ >
152
+ <Box
153
+ component="img"
154
+ src={wallet.icon}
155
+ sx={{
156
+ width: 40,
157
+ height: 40,
158
+ borderRadius: 12,
159
+ border: 'solid 1px',
160
+ borderColor: 'border.main',
161
+ }}
162
+ />
163
+ {wallet.title}
164
+ </Box>
165
+ <WalletTag
166
+ loading={loading}
167
+ wallet={wallet}
168
+ isChecked={isChecked}
169
+ installed={!!installed}
170
+ />
171
+ </Box>
172
+ );
173
+ }
174
+
175
+ function ConnectPage({
176
+ chainId,
177
+ account,
178
+ walletWeb3,
179
+ showOtherInjectWallet,
180
+ onClose,
181
+ }: {
182
+ chainId: number;
183
+ account?: string;
184
+ walletWeb3?: WalletWeb3;
185
+ showOtherInjectWallet?: boolean;
186
+ onClose: () => void;
187
+ }) {
188
+ const theme = useTheme();
189
+ const highlightBackgroundColor =
190
+ theme.palette.mode === 'dark' ? alpha('#F1F902', 0.1) : '#F1F902';
191
+ const { termsOfServiceLink, chainId: needConnectChainId } =
192
+ useWalletConnectContext();
193
+
194
+ const selectedChainId = needConnectChainId ?? chainId;
195
+
196
+ const [isDisabledClick, setIsDisabledClick] = React.useState(false);
197
+ const [showLedgerConnect, setShowLedgerConnect] = React.useState(false);
198
+ const [showAlchemyConnect, setShowAlchemyConnect] = React.useState(false);
199
+ const disabledClick = React.useCallback(() => {
200
+ setIsDisabledClick(true);
201
+ const time = setTimeout(() => {
202
+ setIsDisabledClick(false);
203
+ }, 1800);
204
+
205
+ return () => {
206
+ clearTimeout(time);
207
+ };
208
+ }, []);
209
+
210
+ const {
211
+ walletList,
212
+ userReadAndChecked,
213
+ handleChangeUserReadAndChecked,
214
+ activeWalletType,
215
+ } = useConnectWallet({
216
+ walletWeb3,
217
+ matchTestChain: true,
218
+ showOtherInjectWallet,
219
+ selectedChainId,
220
+ hasTermsOfServiceLink: !!termsOfServiceLink,
221
+ });
222
+ const [showAllWallet, setShowAllWallet] = React.useState(false);
223
+ const showWalletList = React.useMemo(() => {
224
+ if (showAllWallet) return walletList;
225
+ return walletList.slice(0, 6);
226
+ }, [walletList, showAllWallet]);
227
+ const morePriorityWalletList = React.useMemo(() => {
228
+ return walletList.slice(6, 9);
229
+ }, [walletList]);
230
+
231
+ return (
232
+ <>
233
+ <DialogTitle onClose={onClose}>
234
+ <Trans>Connect Wallet</Trans>
235
+ </DialogTitle>
236
+ <Box
237
+ sx={{
238
+ height: '100%',
239
+ display: 'flex',
240
+ flexDirection: 'column',
241
+ overflow: 'hidden',
242
+ pb: termsOfServiceLink ? 0 : 20,
243
+ }}
244
+ >
245
+ <Box
246
+ sx={{
247
+ overflowY: 'auto',
248
+ }}
249
+ >
250
+ <Box
251
+ sx={{
252
+ ...walletGroupStyle,
253
+ }}
254
+ >
255
+ {showWalletList.map((wallet) => {
256
+ return (
257
+ <WalletGroupItem
258
+ key={wallet.title}
259
+ wallet={wallet}
260
+ disabled={!userReadAndChecked}
261
+ loggedIn={!!account}
262
+ selectedChainId={selectedChainId}
263
+ matchChain={selectedChainId === chainId}
264
+ activeWalletType={activeWalletType}
265
+ installed={wallet.isInstalled}
266
+ disabledClick={disabledClick}
267
+ onShowLedgerConnect={() => setShowLedgerConnect(true)}
268
+ onShowAlchemyConnect={() => setShowAlchemyConnect(true)}
269
+ />
270
+ );
271
+ })}
272
+ </Box>
273
+ {morePriorityWalletList.length ? (
274
+ <Box
275
+ sx={{
276
+ mx: 20,
277
+ display: 'flex',
278
+ justifyContent: 'center',
279
+ position: 'relative',
280
+ opacity: userReadAndChecked ? 1 : 0.5,
281
+ }}
282
+ >
283
+ <Box
284
+ sx={{
285
+ position: 'absolute',
286
+ top: '50%',
287
+ right: 0,
288
+ left: 0,
289
+ height: '1px',
290
+ backgroundColor: 'border.main',
291
+ transform: 'translateY(-50%)',
292
+ }}
293
+ />
294
+ {showAllWallet ? (
295
+ <Box
296
+ component={ButtonBase}
297
+ disabled={!userReadAndChecked}
298
+ sx={{
299
+ position: 'relative',
300
+ padding: theme.spacing(0, 12),
301
+ height: 34,
302
+ borderRadius: 20,
303
+ backgroundColor: 'background.paper',
304
+ border: 'solid 1px',
305
+ borderColor: 'border.main',
306
+ '&:hover': {
307
+ backgroundColor: 'background.paperContrast',
308
+ },
309
+ }}
310
+ onClick={() => setShowAllWallet(false)}
311
+ >
312
+ <Box
313
+ component={ArrowRight}
314
+ sx={{
315
+ color: 'text.secondary',
316
+ transform: 'rotate(-90deg)',
317
+ }}
318
+ />
319
+ </Box>
320
+ ) : (
321
+ <Box
322
+ component={ButtonBase}
323
+ disabled={!userReadAndChecked}
324
+ sx={{
325
+ position: 'relative',
326
+ display: 'flex',
327
+ alignItems: 'center',
328
+ padding: theme.spacing(0, 12),
329
+ height: 34,
330
+ borderRadius: 20,
331
+ border: 'solid 1px',
332
+ borderColor: 'border.main',
333
+ backgroundColor: 'background.paper',
334
+ typography: 'h6',
335
+ color: 'text.secondary',
336
+ '&:hover': {
337
+ backgroundColor: 'background.paperContrast',
338
+ },
339
+ }}
340
+ onClick={() => setShowAllWallet(true)}
341
+ >
342
+ <Trans>More Wallets</Trans>
343
+ {morePriorityWalletList.map((item, index) => {
344
+ return (
345
+ <Box
346
+ key={item.title}
347
+ component="img"
348
+ src={item.icon}
349
+ alt="icon"
350
+ sx={{
351
+ width: 18,
352
+ height: 18,
353
+ ...(index !== 0
354
+ ? {
355
+ position: 'relative',
356
+ left: -2,
357
+ }
358
+ : {
359
+ ml: 12,
360
+ }),
361
+ }}
362
+ />
363
+ );
364
+ })}
365
+ <Box
366
+ sx={{
367
+ width: 18,
368
+ height: 18,
369
+ display: 'flex',
370
+ justifyContent: 'center',
371
+ alignItems: 'center',
372
+ backgroundColor: 'background.paperContrast',
373
+ borderRadius: '50%',
374
+ }}
375
+ >
376
+ <Box
377
+ component={More}
378
+ sx={{
379
+ width: 18,
380
+ height: 18,
381
+ }}
382
+ />
383
+ </Box>
384
+ <Box
385
+ component={ArrowRight}
386
+ sx={{
387
+ transform: 'rotate(90deg)',
388
+ }}
389
+ />
390
+ </Box>
391
+ )}
392
+ </Box>
393
+ ) : (
394
+ ''
395
+ )}
396
+ <ConnectLedger
397
+ on={showLedgerConnect}
398
+ chainId={selectedChainId}
399
+ onClose={() => setShowLedgerConnect(false)}
400
+ onConnect={(path, account) => {
401
+ walletList
402
+ .find((wallet) => wallet.currentType === WalletType.LedgerUSB)
403
+ ?.onClick({
404
+ ledgerParams: {
405
+ path,
406
+ account,
407
+ },
408
+ });
409
+ }}
410
+ />
411
+ {!!walletWeb3 && (
412
+ <ConnectAlchemy
413
+ open={showAlchemyConnect}
414
+ setOpen={setShowAlchemyConnect}
415
+ walletWeb3={walletWeb3}
416
+ />
417
+ )}
418
+ </Box>
419
+ {!!termsOfServiceLink && (
420
+ <Checkbox
421
+ checked={userReadAndChecked}
422
+ onChange={(evt: any) =>
423
+ handleChangeUserReadAndChecked(evt.target.checked)
424
+ }
425
+ label={
426
+ <Box
427
+ sx={{
428
+ typography: 'body2',
429
+ '& a': {
430
+ fontWeight: 600,
431
+ color: 'primary.main',
432
+ // textDecoration: 'underline',
433
+ },
434
+ }}
435
+ >
436
+ {termsOfServiceLink}
437
+ </Box>
438
+ }
439
+ sx={{
440
+ m: 0,
441
+ p: 20,
442
+ alignItems: 'flex-start',
443
+ display: 'flex',
444
+ backgroundColor: isDisabledClick
445
+ ? highlightBackgroundColor
446
+ : 'transparent',
447
+ '& > span': {
448
+ p: 0,
449
+ mr: 8,
450
+ },
451
+ }}
452
+ />
453
+ )}
454
+ </Box>
455
+ </>
456
+ );
457
+ }
458
+
459
+ export default ConnectPage;
@@ -0,0 +1,201 @@
1
+ import {
2
+ Box,
3
+ EmptyDataIcon,
4
+ LoadingSkeleton,
5
+ Skeleton,
6
+ TooltipToast,
7
+ useTheme,
8
+ } from '@dodoex/components';
9
+ import { Trans } from '@lingui/macro';
10
+ import { ArrowTopRightBorder, Copy } from '@dodoex/icons';
11
+ import copy from 'copy-to-clipboard';
12
+ import { increaseArray } from '../utils/utils';
13
+ import { useWalletConnectContext } from '../WalletConnectProvider';
14
+ import TokenLogo from '../components/TokenLogo';
15
+ import { formatReadableNumber, formatShortNumber } from '../utils/formatter';
16
+ import { useHasBalanceTokenList } from '../hooks/useHasBalanceTokenList';
17
+
18
+ export default function HasBalanceTokenList({
19
+ balanceListData,
20
+ }: {
21
+ balanceListData: ReturnType<typeof useHasBalanceTokenList>;
22
+ }) {
23
+ const theme = useTheme();
24
+ const { onClickToken, getChain } = useWalletConnectContext();
25
+ return (
26
+ <div>
27
+ {balanceListData.tokenLoading &&
28
+ increaseArray(3).map((_, i) => (
29
+ <Skeleton
30
+ key={i}
31
+ width="100%"
32
+ height={40}
33
+ sx={{
34
+ mx: 20,
35
+ my: 16,
36
+ }}
37
+ />
38
+ ))}
39
+ {!balanceListData.tokenLoading && !balanceListData.hasBalanceList.length && (
40
+ <Box
41
+ sx={{
42
+ display: 'flex',
43
+ alignItems: 'center',
44
+ flexDirection: 'column',
45
+ gap: 12,
46
+ mt: 56,
47
+ color: 'text.secondary',
48
+ }}
49
+ >
50
+ <EmptyDataIcon />
51
+ <Trans>No tokens</Trans>
52
+ </Box>
53
+ )}
54
+ {balanceListData.hasBalanceList.map((token) => {
55
+ return (
56
+ <Box
57
+ key={token.address}
58
+ sx={{
59
+ display: 'flex',
60
+ justifyContent: 'space-between',
61
+ alignItems: 'center',
62
+ gap: 12,
63
+ px: 20,
64
+ py: 16,
65
+ overflow: 'hidden',
66
+ ...(onClickToken
67
+ ? {
68
+ cursor: 'pointer',
69
+ '&:hover': {
70
+ backgroundColor: 'hover.default',
71
+ '& .token-operate': {
72
+ display: 'flex',
73
+ },
74
+ },
75
+ }
76
+ : {}),
77
+ }}
78
+ onClick={() => {
79
+ if (onClickToken) {
80
+ onClickToken(token);
81
+ }
82
+ }}
83
+ >
84
+ <Box
85
+ sx={{
86
+ display: 'flex',
87
+ alignItems: 'center',
88
+ gap: 12,
89
+ }}
90
+ >
91
+ <TokenLogo
92
+ address={token.address}
93
+ chainId={token.chainId}
94
+ logoURI={token.logoURI}
95
+ width={40}
96
+ height={40}
97
+ />
98
+ <div>
99
+ <Box
100
+ sx={{
101
+ display: 'flex',
102
+ alignItems: 'center',
103
+ gap: 4,
104
+ }}
105
+ >
106
+ {token.name}
107
+ <Box
108
+ className="token-operate"
109
+ sx={{
110
+ display: 'flex',
111
+ alignItems: 'center',
112
+ gap: 4,
113
+ [theme.breakpoints.up('tablet')]: {
114
+ display: 'none',
115
+ },
116
+ }}
117
+ >
118
+ <TooltipToast arrow={false} title={<Trans>Copied</Trans>}>
119
+ <Box
120
+ component={Copy}
121
+ sx={{
122
+ width: 14,
123
+ height: 14,
124
+ cursor: 'pointer',
125
+ color: 'text.secondary',
126
+ '&:hover': {
127
+ color: 'text.primary',
128
+ },
129
+ }}
130
+ onClick={() => {
131
+ copy(token.address);
132
+ }}
133
+ />
134
+ </TooltipToast>
135
+ <Box
136
+ component="a"
137
+ href={`https://${getChain(token.chainId)?.scanUrl}${
138
+ token.address ? `/address/${token.address}` : ''
139
+ }`}
140
+ rel="noopener noreferrer"
141
+ target="_blank"
142
+ sx={{
143
+ display: 'flex',
144
+ width: 14,
145
+ height: 14,
146
+ color: 'text.secondary',
147
+ '&:hover': {
148
+ color: 'text.primary',
149
+ },
150
+ }}
151
+ onClick={(evt) => {
152
+ evt.stopPropagation();
153
+ }}
154
+ >
155
+ <Box
156
+ component={ArrowTopRightBorder}
157
+ sx={{
158
+ width: 14,
159
+ height: 14,
160
+ }}
161
+ />
162
+ </Box>
163
+ </Box>
164
+ </Box>
165
+ <div className="text-sm text-secondary">
166
+ {`${formatReadableNumber({ input: token.balance })} ${
167
+ token.symbol
168
+ }`}
169
+ </div>
170
+ </div>
171
+ </Box>
172
+ <LoadingSkeleton
173
+ loading={balanceListData.fiatPriceQuery.isLoading}
174
+ loadingProps={{
175
+ width: 100,
176
+ }}
177
+ title={
178
+ token.fiatPriceBalance
179
+ ? `$${formatReadableNumber({
180
+ input: token.fiatPriceBalance,
181
+ })}`
182
+ : undefined
183
+ }
184
+ sx={{
185
+ overflow: 'hidden',
186
+ textOverflow: 'ellipsis',
187
+ whiteSpace: 'nowrap',
188
+ typography: 'h5',
189
+ }}
190
+ >
191
+ $
192
+ {token.fiatPriceBalance
193
+ ? formatShortNumber(token.fiatPriceBalance)
194
+ : '-'}
195
+ </LoadingSkeleton>
196
+ </Box>
197
+ );
198
+ })}
199
+ </div>
200
+ );
201
+ }