thirdweb 5.80.1-nightly-ce3e850fdbf34911e20919ecc2674e4a63f08fa3-20241226000321 → 5.80.1-nightly-a7b6cb3211e8b5232e77965cb8dd8ff96b369424-20241228000338

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 (66) hide show
  1. package/dist/cjs/gas/fee-data.js +1 -1
  2. package/dist/cjs/gas/fee-data.js.map +1 -1
  3. package/dist/cjs/react/web/ui/ConnectWallet/ConnectButton.js +11 -0
  4. package/dist/cjs/react/web/ui/ConnectWallet/ConnectButton.js.map +1 -1
  5. package/dist/cjs/react/web/ui/ConnectWallet/Details.js +59 -16
  6. package/dist/cjs/react/web/ui/ConnectWallet/Details.js.map +1 -1
  7. package/dist/cjs/react/web/ui/ConnectWallet/NetworkSelector.js +48 -24
  8. package/dist/cjs/react/web/ui/ConnectWallet/NetworkSelector.js.map +1 -1
  9. package/dist/cjs/react/web/ui/components/ChainActiveDot.js +20 -0
  10. package/dist/cjs/react/web/ui/components/ChainActiveDot.js.map +1 -0
  11. package/dist/cjs/react/web/ui/components/ChainIcon.js +24 -29
  12. package/dist/cjs/react/web/ui/components/ChainIcon.js.map +1 -1
  13. package/dist/cjs/react/web/ui/components/fallbackChainIcon.js +9 -0
  14. package/dist/cjs/react/web/ui/components/fallbackChainIcon.js.map +1 -0
  15. package/dist/cjs/react/web/ui/prebuilt/Chain/icon.js +44 -28
  16. package/dist/cjs/react/web/ui/prebuilt/Chain/icon.js.map +1 -1
  17. package/dist/cjs/version.js +1 -1
  18. package/dist/esm/gas/fee-data.js +1 -1
  19. package/dist/esm/gas/fee-data.js.map +1 -1
  20. package/dist/esm/react/web/ui/ConnectWallet/ConnectButton.js +11 -0
  21. package/dist/esm/react/web/ui/ConnectWallet/ConnectButton.js.map +1 -1
  22. package/dist/esm/react/web/ui/ConnectWallet/Details.js +59 -17
  23. package/dist/esm/react/web/ui/ConnectWallet/Details.js.map +1 -1
  24. package/dist/esm/react/web/ui/ConnectWallet/NetworkSelector.js +45 -21
  25. package/dist/esm/react/web/ui/ConnectWallet/NetworkSelector.js.map +1 -1
  26. package/dist/esm/react/web/ui/components/ChainActiveDot.js +17 -0
  27. package/dist/esm/react/web/ui/components/ChainActiveDot.js.map +1 -0
  28. package/dist/esm/react/web/ui/components/ChainIcon.js +22 -28
  29. package/dist/esm/react/web/ui/components/ChainIcon.js.map +1 -1
  30. package/dist/esm/react/web/ui/components/fallbackChainIcon.js +6 -0
  31. package/dist/esm/react/web/ui/components/fallbackChainIcon.js.map +1 -0
  32. package/dist/esm/react/web/ui/prebuilt/Chain/icon.js +42 -28
  33. package/dist/esm/react/web/ui/prebuilt/Chain/icon.js.map +1 -1
  34. package/dist/esm/version.js +1 -1
  35. package/dist/types/react/core/hooks/connection/ConnectButtonProps.d.ts +5 -0
  36. package/dist/types/react/core/hooks/connection/ConnectButtonProps.d.ts.map +1 -1
  37. package/dist/types/react/web/ui/ConnectWallet/ConnectButton.d.ts +11 -0
  38. package/dist/types/react/web/ui/ConnectWallet/ConnectButton.d.ts.map +1 -1
  39. package/dist/types/react/web/ui/ConnectWallet/Details.d.ts +34 -1
  40. package/dist/types/react/web/ui/ConnectWallet/Details.d.ts.map +1 -1
  41. package/dist/types/react/web/ui/ConnectWallet/NetworkSelector.d.ts +46 -1
  42. package/dist/types/react/web/ui/ConnectWallet/NetworkSelector.d.ts.map +1 -1
  43. package/dist/types/react/web/ui/components/ChainActiveDot.d.ts +10 -0
  44. package/dist/types/react/web/ui/components/ChainActiveDot.d.ts.map +1 -0
  45. package/dist/types/react/web/ui/components/ChainIcon.d.ts +8 -0
  46. package/dist/types/react/web/ui/components/ChainIcon.d.ts.map +1 -1
  47. package/dist/types/react/web/ui/components/fallbackChainIcon.d.ts +6 -0
  48. package/dist/types/react/web/ui/components/fallbackChainIcon.d.ts.map +1 -0
  49. package/dist/types/react/web/ui/prebuilt/Chain/icon.d.ts +18 -0
  50. package/dist/types/react/web/ui/prebuilt/Chain/icon.d.ts.map +1 -1
  51. package/dist/types/version.d.ts +1 -1
  52. package/package.json +1 -1
  53. package/src/gas/fee-data.ts +1 -1
  54. package/src/react/core/hooks/connection/ConnectButtonProps.ts +6 -0
  55. package/src/react/web/ui/ConnectWallet/ConnectButton.tsx +11 -0
  56. package/src/react/web/ui/ConnectWallet/Details.test.tsx +55 -0
  57. package/src/react/web/ui/ConnectWallet/Details.tsx +176 -98
  58. package/src/react/web/ui/ConnectWallet/NetworkSelector.test.tsx +189 -0
  59. package/src/react/web/ui/ConnectWallet/NetworkSelector.tsx +117 -76
  60. package/src/react/web/ui/components/ChainActiveDot.tsx +17 -0
  61. package/src/react/web/ui/components/ChainIcon.test.tsx +60 -0
  62. package/src/react/web/ui/components/ChainIcon.tsx +27 -31
  63. package/src/react/web/ui/components/fallbackChainIcon.ts +6 -0
  64. package/src/react/web/ui/prebuilt/Chain/icon.test.tsx +150 -0
  65. package/src/react/web/ui/prebuilt/Chain/icon.tsx +53 -31
  66. package/src/version.ts +1 -1
@@ -9,7 +9,15 @@ import {
9
9
  TextAlignJustifyIcon,
10
10
  } from "@radix-ui/react-icons";
11
11
  import { useQuery } from "@tanstack/react-query";
12
- import { type JSX, useCallback, useContext, useEffect, useState } from "react";
12
+ import {
13
+ type Dispatch,
14
+ type JSX,
15
+ type SetStateAction,
16
+ useCallback,
17
+ useContext,
18
+ useEffect,
19
+ useState,
20
+ } from "react";
13
21
  import { trackPayEvent } from "../../../../analytics/track/pay.js";
14
22
  import type { Chain } from "../../../../chains/types.js";
15
23
  import type { ThirdwebClient } from "../../../../client/client.js";
@@ -51,11 +59,7 @@ import type {
51
59
  ConnectButton_detailsModalOptions,
52
60
  PayUIOptions,
53
61
  } from "../../../core/hooks/connection/ConnectButtonProps.js";
54
- import {
55
- useChainFaucets,
56
- useChainIconUrl,
57
- useChainName,
58
- } from "../../../core/hooks/others/useChainQuery.js";
62
+ import { useChainFaucets } from "../../../core/hooks/others/useChainQuery.js";
59
63
  import { useActiveAccount } from "../../../core/hooks/wallets/useActiveAccount.js";
60
64
  import { useActiveWallet } from "../../../core/hooks/wallets/useActiveWallet.js";
61
65
  import { useActiveWalletChain } from "../../../core/hooks/wallets/useActiveWalletChain.js";
@@ -70,7 +74,7 @@ import type {
70
74
  import { hasSmartAccount } from "../../../core/utils/isSmartWallet.js";
71
75
  import { useWalletInfo } from "../../../core/utils/wallet.js";
72
76
  import { WalletUIStatesProvider } from "../../providers/wallet-ui-states-provider.js";
73
- import { ChainIcon } from "../components/ChainIcon.js";
77
+ import { ChainActiveDot } from "../components/ChainActiveDot.js";
74
78
  import { CopyIcon } from "../components/CopyIcon.js";
75
79
  import { IconContainer } from "../components/IconContainer.js";
76
80
  import { Modal } from "../components/Modal.js";
@@ -81,6 +85,7 @@ import { ToolTip } from "../components/Tooltip.js";
81
85
  import { WalletImage } from "../components/WalletImage.js";
82
86
  import { Container, Line } from "../components/basic.js";
83
87
  import { Button, IconButton } from "../components/buttons.js";
88
+ import { fallbackChainIcon } from "../components/fallbackChainIcon.js";
84
89
  import { Link, Text } from "../components/text.js";
85
90
  import { fadeInAnimation } from "../design-system/animations.js";
86
91
  import { StyledButton } from "../design-system/elements.js";
@@ -95,6 +100,9 @@ import {
95
100
  import { AccountBlobbie } from "../prebuilt/Account/blobbie.js";
96
101
  import { AccountName } from "../prebuilt/Account/name.js";
97
102
  import { AccountProvider } from "../prebuilt/Account/provider.js";
103
+ import { ChainIcon } from "../prebuilt/Chain/icon.js";
104
+ import { ChainName } from "../prebuilt/Chain/name.js";
105
+ import { ChainProvider } from "../prebuilt/Chain/provider.js";
98
106
  import type { LocaleId } from "../types.js";
99
107
  import { MenuButton, MenuLink } from "./MenuButton.js";
100
108
  import { ScreenSetupContext, useSetupScreen } from "./Modal/screen.js";
@@ -386,8 +394,6 @@ export function DetailsModal(props: {
386
394
  const theme = parseTheme(props.theme);
387
395
 
388
396
  const activeWallet = useActiveWallet();
389
- const chainIconQuery = useChainIconUrl(walletChain);
390
- const chainNameQuery = useChainName(walletChain);
391
397
  const chainFaucetsQuery = useChainFaucets(walletChain);
392
398
 
393
399
  const disableSwitchChain = !activeWallet?.switchChain;
@@ -417,93 +423,6 @@ export function DetailsModal(props: {
417
423
  }
418
424
  }, [activeAccount, closeModal]);
419
425
 
420
- const networkSwitcherButton = (
421
- <MenuButton
422
- type="button"
423
- disabled={disableSwitchChain}
424
- onClick={() => {
425
- setScreen("network-switcher");
426
- }}
427
- data-variant="primary"
428
- >
429
- <div
430
- style={{
431
- display: "flex",
432
- alignItems: "center",
433
- position: "relative",
434
- }}
435
- >
436
- {!chainIconQuery.isLoading ? (
437
- <ChainIcon
438
- chainIconUrl={chainIconQuery.url}
439
- size={iconSize.md}
440
- active
441
- client={client}
442
- />
443
- ) : (
444
- <Skeleton height={`${iconSize.md}px`} width={`${iconSize.md}px`} />
445
- )}
446
- </div>
447
-
448
- {chainNameQuery.isLoading ? (
449
- <Skeleton height="16px" width="150px" />
450
- ) : (
451
- <Text color="primaryText" size="md" multiline>
452
- {chainNameQuery.name || `Unknown chain #${walletChain?.id}`}
453
- <Text color="secondaryText" size="xs">
454
- {props.showBalanceInFiat ? (
455
- <>
456
- <AccountBalance
457
- fallbackComponent={<Skeleton height="1em" width="70px" />}
458
- loadingComponent={<Skeleton height="1em" width="70px" />}
459
- chain={walletChain}
460
- tokenAddress={
461
- props.displayBalanceToken?.[Number(walletChain?.id)]
462
- }
463
- formatFn={(props: AccountBalanceInfo) =>
464
- formatAccountTokenBalance({ ...props, decimals: 7 })
465
- }
466
- />{" "}
467
- <AccountBalance
468
- loadingComponent={<Skeleton height="1em" width="30px" />}
469
- chain={walletChain}
470
- tokenAddress={
471
- props.displayBalanceToken?.[Number(walletChain?.id)]
472
- }
473
- formatFn={(props: AccountBalanceInfo) =>
474
- ` (${formatAccountFiatBalance({ ...props, decimals: 3 })})`
475
- }
476
- showBalanceInFiat="USD"
477
- />
478
- </>
479
- ) : (
480
- <AccountBalance
481
- fallbackComponent={<Skeleton height="1em" width="100px" />}
482
- loadingComponent={<Skeleton height="1em" width="100px" />}
483
- formatFn={(props: AccountBalanceInfo) =>
484
- formatAccountTokenBalance({ ...props, decimals: 7 })
485
- }
486
- chain={walletChain}
487
- tokenAddress={
488
- props.displayBalanceToken?.[Number(walletChain?.id)]
489
- }
490
- />
491
- )}
492
- </Text>
493
- </Text>
494
- )}
495
-
496
- <StyledChevronRightIcon
497
- width={iconSize.sm}
498
- height={iconSize.sm}
499
- style={{
500
- flexShrink: 0,
501
- marginLeft: "auto",
502
- }}
503
- />
504
- </MenuButton>
505
- );
506
-
507
426
  const { hideSendFunds, hideReceiveFunds, hideBuyFunds } =
508
427
  props.detailsModal || {};
509
428
 
@@ -749,7 +668,13 @@ export function DetailsModal(props: {
749
668
  }}
750
669
  >
751
670
  {/* Network Switcher */}
752
- {networkSwitcherButton}
671
+ <NetworkSwitcherButton
672
+ client={props.client}
673
+ setScreen={() => setScreen("network-switcher")}
674
+ disableSwitchChain={disableSwitchChain}
675
+ showBalanceInFiat={props.detailsModal?.showBalanceInFiat}
676
+ displayBalanceToken={props.displayBalanceToken}
677
+ />
753
678
 
754
679
  {/* Transactions */}
755
680
  <MenuButton
@@ -1084,6 +1009,9 @@ export function DetailsModal(props: {
1084
1009
  setOpen={(_open) => {
1085
1010
  if (!_open) {
1086
1011
  closeModal();
1012
+ if (props.detailsModal?.onClose) {
1013
+ props.detailsModal?.onClose(screen);
1014
+ }
1087
1015
  }
1088
1016
  }}
1089
1017
  >
@@ -1099,6 +1027,136 @@ export function DetailsModal(props: {
1099
1027
  );
1100
1028
  }
1101
1029
 
1030
+ /**
1031
+ * When this button is clicked, it will switch to the screen where users
1032
+ * can select a chain to switch to.
1033
+ * @internal
1034
+ */
1035
+ export function NetworkSwitcherButton(props: {
1036
+ setScreen: Dispatch<SetStateAction<"network-switcher">>;
1037
+ disableSwitchChain: boolean;
1038
+ displayBalanceToken: Record<number, string> | undefined;
1039
+ client: ThirdwebClient;
1040
+ showBalanceInFiat?: SupportedFiatCurrency;
1041
+ }) {
1042
+ const { disableSwitchChain, setScreen, showBalanceInFiat, client } = props;
1043
+ const walletChain = useActiveWalletChain();
1044
+ if (!walletChain) {
1045
+ return null;
1046
+ }
1047
+ return (
1048
+ <MenuButton
1049
+ type="button"
1050
+ disabled={disableSwitchChain}
1051
+ onClick={() => {
1052
+ setScreen("network-switcher");
1053
+ }}
1054
+ data-variant="primary"
1055
+ className="tw-internal-network-switcher-button"
1056
+ >
1057
+ <ChainProvider chain={walletChain}>
1058
+ <div
1059
+ style={{
1060
+ display: "flex",
1061
+ alignItems: "center",
1062
+ position: "relative",
1063
+ }}
1064
+ >
1065
+ <Container
1066
+ style={{
1067
+ position: "relative",
1068
+ display: "flex",
1069
+ flexShrink: 0,
1070
+ alignItems: "center",
1071
+ }}
1072
+ >
1073
+ <ChainIcon
1074
+ client={client}
1075
+ loadingComponent={
1076
+ <Skeleton
1077
+ height={`${iconSize.md}px`}
1078
+ width={`${iconSize.md}px`}
1079
+ />
1080
+ }
1081
+ fallbackComponent={
1082
+ <img
1083
+ src={fallbackChainIcon}
1084
+ alt=""
1085
+ style={{
1086
+ width: `${iconSize.md}px`,
1087
+ height: `${iconSize.md}px`,
1088
+ }}
1089
+ />
1090
+ }
1091
+ style={{
1092
+ width: `${iconSize.md}px`,
1093
+ height: `${iconSize.md}px`,
1094
+ }}
1095
+ />
1096
+ <ChainActiveDot className="tw-chain-active-dot-details-button" />
1097
+ </Container>
1098
+ </div>
1099
+
1100
+ <Text color="primaryText" size="md" multiline>
1101
+ <ChainName
1102
+ loadingComponent={<Skeleton height="16px" width="150px" />}
1103
+ fallbackComponent={<span>Unknown chain #{walletChain?.id}</span>}
1104
+ />
1105
+ <Text color="secondaryText" size="xs">
1106
+ {showBalanceInFiat ? (
1107
+ <>
1108
+ <AccountBalance
1109
+ fallbackComponent={<Skeleton height="1em" width="70px" />}
1110
+ loadingComponent={<Skeleton height="1em" width="70px" />}
1111
+ chain={walletChain}
1112
+ tokenAddress={
1113
+ props.displayBalanceToken?.[Number(walletChain?.id)]
1114
+ }
1115
+ formatFn={(props: AccountBalanceInfo) =>
1116
+ formatAccountTokenBalance({ ...props, decimals: 7 })
1117
+ }
1118
+ />{" "}
1119
+ <AccountBalance
1120
+ loadingComponent={<Skeleton height="1em" width="30px" />}
1121
+ chain={walletChain}
1122
+ tokenAddress={
1123
+ props.displayBalanceToken?.[Number(walletChain?.id)]
1124
+ }
1125
+ formatFn={(props: AccountBalanceInfo) =>
1126
+ ` (${formatAccountFiatBalance({ ...props, decimals: 3 })})`
1127
+ }
1128
+ showBalanceInFiat="USD"
1129
+ />
1130
+ </>
1131
+ ) : (
1132
+ <AccountBalance
1133
+ fallbackComponent={<Skeleton height="1em" width="100px" />}
1134
+ loadingComponent={<Skeleton height="1em" width="100px" />}
1135
+ formatFn={(props: AccountBalanceInfo) =>
1136
+ formatAccountTokenBalance({ ...props, decimals: 7 })
1137
+ }
1138
+ chain={walletChain}
1139
+ tokenAddress={
1140
+ props.displayBalanceToken?.[Number(walletChain?.id)]
1141
+ }
1142
+ />
1143
+ )}
1144
+ </Text>
1145
+ </Text>
1146
+ </ChainProvider>
1147
+
1148
+ <StyledChevronRightIcon
1149
+ width={iconSize.sm}
1150
+ height={iconSize.sm}
1151
+ style={{
1152
+ flexShrink: 0,
1153
+ marginLeft: "auto",
1154
+ }}
1155
+ />
1156
+ </MenuButton>
1157
+ );
1158
+ }
1159
+
1102
1160
  const WalletInfoButton = /* @__PURE__ */ StyledButton((_) => {
1103
1161
  const theme = useCustomTheme();
1104
1162
  return {
@@ -1125,7 +1183,10 @@ const WalletInfoButton = /* @__PURE__ */ StyledButton((_) => {
1125
1183
  };
1126
1184
  });
1127
1185
 
1128
- const StyledChevronRightIcon = /* @__PURE__ */ styled(
1186
+ /**
1187
+ * @internal Export for tests
1188
+ */
1189
+ export const StyledChevronRightIcon = /* @__PURE__ */ styled(
1129
1190
  /* @__PURE__ */ ChevronRightIcon,
1130
1191
  )(() => {
1131
1192
  const theme = useCustomTheme();
@@ -1614,12 +1675,19 @@ export type UseWalletDetailsModalOptions = {
1614
1675
  * Note: Not all tokens are resolvable to a fiat value. In that case, nothing will be shown.
1615
1676
  */
1616
1677
  showBalanceInFiat?: SupportedFiatCurrency;
1678
+
1679
+ /**
1680
+ * The callback function for when the modal is closed
1681
+ * @param screen The name of the screen that was being shown when user closed the modal
1682
+ */
1683
+ onClose?: (screen: string) => void;
1617
1684
  };
1618
1685
 
1619
1686
  /**
1620
1687
  * Hook to open the Wallet Details Modal that shows various information about the connected wallet and allows users to perform various actions like sending funds, receiving funds, switching networks, Buying tokens, etc.
1621
1688
  *
1622
1689
  * @example
1690
+ * ### Basic usage
1623
1691
  * ```tsx
1624
1692
  * import { createThirdwebClient } from "thirdweb";
1625
1693
  * import { useWalletDetailsModal } from "thirdweb/react";
@@ -1638,6 +1706,15 @@ export type UseWalletDetailsModalOptions = {
1638
1706
  * return <button onClick={handleClick}> Show Wallet Details </button>
1639
1707
  * }
1640
1708
  * ```
1709
+ *
1710
+ * ### Callback for when the modal is closed
1711
+ * ```tsx
1712
+ * detailsModal.open({
1713
+ * client,
1714
+ * onClose: (screen: string) => console.log({ screen })
1715
+ * });
1716
+ * ```
1717
+ *
1641
1718
  * @wallet
1642
1719
  */
1643
1720
  export function useWalletDetailsModal() {
@@ -1672,6 +1749,7 @@ export function useWalletDetailsModal() {
1672
1749
  hideReceiveFunds: props.hideReceiveFunds,
1673
1750
  hideSendFunds: props.hideSendFunds,
1674
1751
  assetTabs: props.assetTabs,
1752
+ onClose: props.onClose,
1675
1753
  }}
1676
1754
  displayBalanceToken={props.displayBalanceToken}
1677
1755
  theme={props.theme || "dark"}
@@ -0,0 +1,189 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { render, screen, waitFor } from "~test/react-render.js";
3
+ import { TEST_CLIENT } from "~test/test-clients.js";
4
+ import { base } from "../../../../chains/chain-definitions/base.js";
5
+ import { ethereum } from "../../../../chains/chain-definitions/ethereum.js";
6
+ import { useActiveWalletChain } from "../../../../react/core/hooks/wallets/useActiveWalletChain.js";
7
+ import {
8
+ ChainButton,
9
+ NetworkButton,
10
+ NetworkList,
11
+ type NetworkSelectorChainProps,
12
+ SectionLabel,
13
+ StyledMagnifyingGlassIcon,
14
+ TabButton,
15
+ } from "./NetworkSelector.js";
16
+ import en from "./locale/en.js";
17
+
18
+ const client = TEST_CLIENT;
19
+
20
+ describe("NetworkSelector", () => {
21
+ it("StyledMagnifyingGlassIcon should render a svg element", () => {
22
+ const { container } = render(<StyledMagnifyingGlassIcon />);
23
+ const svg = container.querySelector("svg");
24
+ expect(svg).toBeTruthy();
25
+ });
26
+
27
+ it("NetworkButton should render a button", () => {
28
+ const { container } = render(<NetworkButton />);
29
+ const button = container.querySelector("button");
30
+ expect(button).toBeTruthy();
31
+ });
32
+
33
+ it("SectionLabel should render a <p>", () => {
34
+ const { container } = render(<SectionLabel />);
35
+ const p = container.querySelector("p");
36
+ expect(p).toBeTruthy();
37
+ });
38
+
39
+ it("TabButton should render a button", () => {
40
+ const { container } = render(<TabButton />);
41
+ const button = container.querySelector("button");
42
+ expect(button).toBeTruthy();
43
+ });
44
+
45
+ it("ChainButton should render ChainIcon", async () => {
46
+ const { container } = render(
47
+ <ChainButton
48
+ chain={ethereum}
49
+ onClick={() => {}}
50
+ confirming={true}
51
+ switchingFailed={false}
52
+ client={client}
53
+ connectLocale={en}
54
+ />,
55
+ );
56
+ await waitFor(
57
+ () => {
58
+ const image = container.querySelector("img");
59
+ expect(image).toBeTruthy();
60
+ expect(
61
+ image?.src.includes("QmcxZHpyJa8T4i63xqjPYrZ6tKrt55tZJpbXcjSDKuKaf9"),
62
+ ).toBe(true);
63
+ },
64
+ {
65
+ timeout: 10000,
66
+ },
67
+ );
68
+ });
69
+
70
+ it("ChainButton should render ChainName", async () => {
71
+ render(
72
+ <ChainButton
73
+ chain={ethereum}
74
+ onClick={() => {}}
75
+ confirming={true}
76
+ switchingFailed={true}
77
+ client={client}
78
+ connectLocale={en}
79
+ />,
80
+ );
81
+ await waitFor(
82
+ () =>
83
+ expect(
84
+ screen.getByText("Ethereum", {
85
+ exact: true,
86
+ selector: "span",
87
+ }),
88
+ ).toBeInTheDocument(),
89
+ { timeout: 2000 },
90
+ );
91
+ });
92
+
93
+ it("ChainButton should render ChainActiveDot if active prop is set to true", async () => {
94
+ vi.mock(
95
+ "../../../../react/core/hooks/wallets/useActiveWalletChain.js",
96
+ () => ({
97
+ useActiveWalletChain: vi.fn(),
98
+ }),
99
+ );
100
+ vi.mocked(useActiveWalletChain).mockReturnValue(ethereum);
101
+ const { container } = render(
102
+ <ChainButton
103
+ chain={ethereum}
104
+ onClick={() => {}}
105
+ confirming={true}
106
+ switchingFailed={true}
107
+ client={client}
108
+ connectLocale={en}
109
+ />,
110
+ );
111
+ await waitFor(() => {
112
+ const dot = container.querySelector(
113
+ ".tw-chain-active-dot-button-network-selector",
114
+ );
115
+ expect(dot).toBeTruthy();
116
+ });
117
+ });
118
+
119
+ it("ChainButton should still render ChainName if both `confirming` and switchingFailed` are false", async () => {
120
+ const { container } = render(
121
+ <ChainButton
122
+ chain={ethereum}
123
+ onClick={() => {}}
124
+ confirming={false}
125
+ switchingFailed={false}
126
+ client={client}
127
+ connectLocale={en}
128
+ />,
129
+ );
130
+
131
+ await waitFor(
132
+ () => {
133
+ const element = container.querySelector(
134
+ ".tw-chain-icon-none-confirming",
135
+ );
136
+ expect(element).toBeTruthy();
137
+ },
138
+ { timeout: 1500 },
139
+ );
140
+ });
141
+
142
+ it("NetworkList should render ChainIcon by default", async () => {
143
+ render(
144
+ <NetworkList
145
+ client={client}
146
+ chains={[ethereum, base]}
147
+ connectLocale={en}
148
+ onSwitch={() => {}}
149
+ />,
150
+ );
151
+
152
+ await waitFor(
153
+ () => {
154
+ expect(
155
+ screen.getByText("Ethereum", {
156
+ exact: true,
157
+ selector: "span",
158
+ }),
159
+ ).toBeInTheDocument();
160
+ expect(
161
+ screen.getByText("Base", {
162
+ exact: true,
163
+ selector: "span",
164
+ }),
165
+ ).toBeInTheDocument();
166
+ },
167
+ { timeout: 3000 },
168
+ );
169
+ });
170
+
171
+ it("NetworkList should render the custom `renderChain`", () => {
172
+ const CustomRender: React.FC<NetworkSelectorChainProps> = (props) => {
173
+ return <span className="_test_">{props.chain.name}</span>;
174
+ };
175
+
176
+ const { container } = render(
177
+ <NetworkList
178
+ renderChain={CustomRender}
179
+ client={client}
180
+ chains={[ethereum, base]}
181
+ connectLocale={en}
182
+ onSwitch={() => {}}
183
+ />,
184
+ );
185
+
186
+ const spans = container.querySelectorAll("span._test_");
187
+ expect(spans.length).toBe(2);
188
+ });
189
+ });