Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Dialog } from '@chakra-ui/react'
import { type ReactElement, useState } from 'react'
import { type Hash, parseEther, type TransactionReceipt } from 'viem'
import { sepolia } from 'viem/chains'
import { useSendTransaction } from 'wagmi'
import Wrapper from '@/src/components/pageComponents/home/Examples/demos/TransactionButton/Wrapper'
import TransactionButton from '@/src/components/sharedComponents/TransactionButton'
Expand Down Expand Up @@ -46,7 +47,10 @@ const NativeToken = () => {
text="Demo transaction that sends 0.1 Sepolia ETH from / to your wallet."
title="Native token demo"
>
{/* chainId must be explicit: the parent WalletStatusVerifier already verified Sepolia,
but TransactionButton checks against appChainId without it. */}
<TransactionButton
chainId={sepolia.id}
labelSending="Sending 0.1 ETH..."
onMined={handleOnMined}
transaction={handleSendTransaction}
Expand Down
20 changes: 20 additions & 0 deletions src/components/sharedComponents/SignButton.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { render, screen } from '@testing-library/react'
import type { ReactNode } from 'react'
import { createElement } from 'react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import type { Web3Status } from '@/src/hooks/useWeb3Status'
import SignButton from './SignButton'

const mockSwitchChain = vi.fn()
Expand Down Expand Up @@ -45,6 +46,21 @@ vi.mock('wagmi', () => ({
const { useWalletStatus } = await import('@/src/hooks/useWalletStatus')
const mockedUseWalletStatus = vi.mocked(useWalletStatus)

const mockWeb3Status = {
readOnlyClient: undefined,
appChainId: 1,
address: '0xdeadbeef',
balance: undefined,
connectingWallet: false,
switchingChain: false,
isWalletConnected: true,
walletClient: undefined,
isWalletSynced: true,
walletChainId: 1,
switchChain: vi.fn(),
disconnect: vi.fn(),
} as unknown as Web3Status

const system = createSystem(defaultConfig)

const renderWithChakra = (ui: ReactNode) =>
Expand All @@ -63,6 +79,7 @@ describe('SignButton', () => {
targetChain: { id: 1, name: 'Ethereum' } as ReturnType<typeof useWalletStatus>['targetChain'],
targetChainId: 1,
switchChain: mockSwitchChain,
web3Status: mockWeb3Status,
})
Comment on lines 79 to 83
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The useWalletStatus mock returns web3Status as undefined via a cast. Since useWalletStatus now guarantees a real Web3Status object, this mock can hide runtime issues if the component starts using web3Status. Prefer returning a minimal but valid Web3Status stub instead of casting undefined.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in d8c5ae2. Replaced the undefined as unknown cast with a shared mockWeb3Status stub mirroring WalletStatusVerifier.test.tsx.


renderWithChakra(<SignButton message="Hello" />)
Expand All @@ -79,6 +96,7 @@ describe('SignButton', () => {
targetChain: { id: 1, name: 'Ethereum' } as ReturnType<typeof useWalletStatus>['targetChain'],
targetChainId: 1,
switchChain: mockSwitchChain,
web3Status: mockWeb3Status,
})
Comment on lines 96 to 100
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The useWalletStatus mock returns web3Status as undefined via a cast. Since useWalletStatus now guarantees a real Web3Status object, this mock can hide runtime issues if the component starts using web3Status. Prefer returning a minimal but valid Web3Status stub instead of casting undefined.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in d8c5ae2 as part of the shared mockWeb3Status stub rollout in this file.


renderWithChakra(
Expand All @@ -102,6 +120,7 @@ describe('SignButton', () => {
>['targetChain'],
targetChainId: 10,
switchChain: mockSwitchChain,
web3Status: mockWeb3Status,
})
Comment on lines 120 to 124
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The useWalletStatus mock returns web3Status as undefined via a cast. Since useWalletStatus now guarantees a real Web3Status object, this mock can hide runtime issues if the component starts using web3Status. Prefer returning a minimal but valid Web3Status stub instead of casting undefined.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in d8c5ae2 as part of the shared mockWeb3Status stub rollout in this file.


renderWithChakra(<SignButton message="Hello" />)
Expand All @@ -119,6 +138,7 @@ describe('SignButton', () => {
targetChain: { id: 1, name: 'Ethereum' } as ReturnType<typeof useWalletStatus>['targetChain'],
targetChainId: 1,
switchChain: mockSwitchChain,
web3Status: mockWeb3Status,
})
Comment on lines 138 to 142
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The useWalletStatus mock returns web3Status as undefined via a cast. Since useWalletStatus now guarantees a real Web3Status object, this mock can hide runtime issues if the component starts using web3Status. Prefer returning a minimal but valid Web3Status stub instead of casting undefined.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in d8c5ae2 as part of the shared mockWeb3Status stub rollout in this file.


renderWithChakra(<SignButton message="Hello" />)
Expand Down
3 changes: 2 additions & 1 deletion src/components/sharedComponents/TokenDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ type Props = ComponentPropsWithoutRef<'span'> & TokenDropdownProps
* @param {string} [props.placeholder] - Placeholder text for the search input.
* @param {number} [props.containerHeight] - Height of the virtualized tokens list.
* @param {number} [props.itemHeight] - Height of each item in the tokens list.
* @param {boolean} [props.showBalance] - Whether to show the token balance in the list.
* @param {boolean} [props.showBalance] - Whether to show the token balance column in each row.
* @param {boolean} [props.showTopTokens] - Whether to show the top tokens section in the list.
* @param {boolean} [props.sortByBalance] - Sort tokens with a positive balance to the top, ordered by USD value descending. Defaults to true when a wallet is connected.
* @param {ComponentPropsWithoutRef<'span'>} props.restProps - Additional props for the span element.
*
* @example
Expand Down
5 changes: 4 additions & 1 deletion src/components/sharedComponents/TokenInput/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,9 @@ type Props = FlexProps & TokenInputProps
* @param {number} [props.iconSize=32] - Optional size of the token icon in the list. Default is 32.
* @param {number} [props.itemHeight=64] - Optional height of each item in the list. Default is 64.
* @param {boolean} [props.showAddTokenButton=false] - Optional flag to allow adding a token. Default is false.
* @param {boolean} [props.showBalance=false] - Optional flag to show the token balance in the list. Default is false.
* @param {boolean} [props.showBalance=false] - Optional flag to show the token balance column in each row. Default is false.
* @param {boolean} [props.showTopTokens=false] - Optional flag to show the top tokens in the list. Default is false.
* @param {boolean} [props.sortByBalance] - Sort tokens with a positive balance to the top, ordered by USD value descending. Defaults to true when a wallet is connected.
*/
const TokenInput: FC<Props> = ({
containerHeight,
Expand All @@ -73,6 +74,7 @@ const TokenInput: FC<Props> = ({
showBalance,
showTopTokens,
singleToken,
sortByBalance,
thousandSeparator = true,
title,
tokenInput,
Expand Down Expand Up @@ -230,6 +232,7 @@ const TokenInput: FC<Props> = ({
showAddTokenButton={showAddTokenButton}
showBalance={showBalance}
showTopTokens={showTopTokens}
sortByBalance={sortByBalance}
>
<CloseButton
aria-label="Close"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,16 @@ const TokenBalance = withSuspenseAndRetry<TokenBalanceProps>(({ isLoading, token

if (hasExtensions) {
const balance = formatUnits((token.extensions?.balance ?? 0n) as bigint, token.decimals)
const value = (
Number.parseFloat((token.extensions?.priceUSD ?? '0') as string) * Number.parseFloat(balance)
).toFixed(2)
const priceUSD = token.extensions?.priceUSD as string | undefined
const usdLabel =
priceUSD !== undefined
? `$ ${(Number.parseFloat(priceUSD) * Number.parseFloat(balance)).toFixed(2)}`
: NO_PRICE_DATA_LABEL

return (
<Flex {...flexProps}>
<Box {...balanceBoxProps}>{balance}</Box>
<Box {...valueBoxProps}>$ {value}</Box>
<Box {...valueBoxProps}>{usdLabel}</Box>
</Flex>
)
}
Expand Down
12 changes: 9 additions & 3 deletions src/components/sharedComponents/TokenSelect/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export interface TokenSelectProps {
showAddTokenButton?: boolean
showTopTokens?: boolean
showBalance?: boolean
sortByBalance?: boolean
}

/** @ignore */
Expand All @@ -42,8 +43,9 @@ type Props = FlexProps & TokenSelectProps
* @param {number} [props.iconSize=32] - Optional size of the token icon in the list. Default is 32.
* @param {number} [props.itemHeight=64] - Optional height of each item in the list. Default is 64.
* @param {boolean} [props.showAddTokenButton=false] - Optional flag to allow adding a token. Default is false.
* @param {boolean} [props.showBalance=false] - Optional flag to show the token balance in the list. Default is false.
* @param {boolean} [props.showBalance=false] - Optional flag to show the token balance column in each row. Default is false.
* @param {boolean} [props.showTopTokens=false] - Optional flag to show the top tokens in the list. Default is false.
* @param {boolean} [props.sortByBalance] - Sort tokens with a positive balance to the top, ordered by USD value descending. Defaults to true when a wallet is connected.
*/
const TokenSelect = withSuspenseAndRetry<Props>(
({
Expand All @@ -59,9 +61,10 @@ const TokenSelect = withSuspenseAndRetry<Props>(
showAddTokenButton = false,
showBalance = false,
showTopTokens = false,
sortByBalance,
...restProps
}) => {
const { appChainId, walletChainId } = useWeb3Status()
const { appChainId, isWalletConnected, walletChainId } = useWeb3Status()

const [chainId, setChainId] = useState<Chain['id']>(() =>
getValidChainId({
Expand Down Expand Up @@ -122,9 +125,12 @@ const TokenSelect = withSuspenseAndRetry<Props>(
previousDepsRef.current = [appChainId, currentNetworkId, walletChainId]
}, [appChainId, currentNetworkId, networks, walletChainId])

const resolvedSortByBalance = sortByBalance ?? isWalletConnected

const { isLoadingBalances, tokensByChainId } = useTokens({
chainId,
withBalance: showBalance,
withBalance: showBalance || resolvedSortByBalance,
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sortByBalance is documented as a separate sorting toggle, but the current wiring only uses it to decide withBalance; useTokens will still sort whenever withBalance is true. This means sortByBalance={false} does not actually disable sorting when showBalance={true} (balances will be fetched and updateTokensBalances will sort). Consider passing an explicit sortByBalance flag into useTokens/updateTokensBalances (or conditionally applying the sort in TokenSelect) so consumers can independently choose to show the balance column without enabling sorting (and vice versa).

Suggested change
withBalance: showBalance || resolvedSortByBalance,
withBalance: showBalance || resolvedSortByBalance,
sortByBalance: resolvedSortByBalance,

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 0897b15. Added a sortByBalance parameter (default true) to useTokens, updateTokensBalances, and updateTokensWithRawBalances; the sort step is now skipped when false. TokenSelect passes sortByBalance: resolvedSortByBalance, so sortByBalance={false} with showBalance={true} now shows balances without reordering.

sortByBalance: resolvedSortByBalance,
})

const { searchResult, searchTerm, setSearchTerm } = useTokenSearch(
Expand Down
21 changes: 21 additions & 0 deletions src/components/sharedComponents/TransactionButton.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { ChakraProvider, createSystem, defaultConfig } from '@chakra-ui/react'
import { render, screen } from '@testing-library/react'
import { createElement, type ReactNode } from 'react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import type { Web3Status } from '@/src/hooks/useWeb3Status'
import TransactionButton from './TransactionButton'

const mockSwitchChain = vi.fn()
Expand Down Expand Up @@ -43,6 +44,21 @@ vi.mock('wagmi', () => ({
const { useWalletStatus } = await import('@/src/hooks/useWalletStatus')
const mockedUseWalletStatus = vi.mocked(useWalletStatus)

const mockWeb3Status = {
readOnlyClient: undefined,
appChainId: 1,
address: '0xdeadbeef',
balance: undefined,
connectingWallet: false,
switchingChain: false,
isWalletConnected: true,
walletClient: undefined,
isWalletSynced: true,
walletChainId: 1,
switchChain: vi.fn(),
disconnect: vi.fn(),
} as unknown as Web3Status

const system = createSystem(defaultConfig)

const renderWithChakra = (ui: ReactNode) =>
Expand All @@ -61,6 +77,7 @@ describe('TransactionButton', () => {
targetChain: { id: 1, name: 'Ethereum' } as ReturnType<typeof useWalletStatus>['targetChain'],
targetChainId: 1,
switchChain: mockSwitchChain,
web3Status: mockWeb3Status,
})
Comment on lines 77 to 81
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The useWalletStatus mock returns web3Status as undefined via a cast. Since useWalletStatus now guarantees a real Web3Status object, this mock can hide runtime issues if the component starts using web3Status. Prefer returning a minimal but valid Web3Status stub (as done in WalletStatusVerifier tests) instead of casting undefined.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 9f5b773. Replaced the undefined as unknown cast with a shared mockWeb3Status stub mirroring WalletStatusVerifier.test.tsx.


renderWithChakra(<TransactionButton transaction={mockTransaction}>Send</TransactionButton>)
Expand All @@ -77,6 +94,7 @@ describe('TransactionButton', () => {
targetChain: { id: 1, name: 'Ethereum' } as ReturnType<typeof useWalletStatus>['targetChain'],
targetChainId: 1,
switchChain: mockSwitchChain,
web3Status: mockWeb3Status,
})
Comment on lines 94 to 98
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The useWalletStatus mock returns web3Status as undefined via a cast. Since useWalletStatus now guarantees a real Web3Status object, this mock can hide runtime issues if the component starts using web3Status. Prefer returning a minimal but valid Web3Status stub instead of casting undefined.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 9f5b773 as part of the shared mockWeb3Status stub rollout in this file.


renderWithChakra(
Expand All @@ -102,6 +120,7 @@ describe('TransactionButton', () => {
>['targetChain'],
targetChainId: 10,
switchChain: mockSwitchChain,
web3Status: mockWeb3Status,
})
Comment on lines 120 to 124
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The useWalletStatus mock returns web3Status as undefined via a cast. Since useWalletStatus now guarantees a real Web3Status object, this mock can hide runtime issues if the component starts using web3Status. Prefer returning a minimal but valid Web3Status stub instead of casting undefined.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 9f5b773 as part of the shared mockWeb3Status stub rollout in this file.


renderWithChakra(<TransactionButton transaction={mockTransaction}>Send</TransactionButton>)
Expand All @@ -121,6 +140,7 @@ describe('TransactionButton', () => {
>['targetChain'],
targetChainId: 10,
switchChain: mockSwitchChain,
web3Status: mockWeb3Status,
})
Comment on lines 140 to 144
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The useWalletStatus mock returns web3Status as undefined via a cast. Since useWalletStatus now guarantees a real Web3Status object, this mock can hide runtime issues if the component starts using web3Status. Prefer returning a minimal but valid Web3Status stub instead of casting undefined.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 9f5b773 as part of the shared mockWeb3Status stub rollout in this file.


renderWithChakra(
Expand All @@ -144,6 +164,7 @@ describe('TransactionButton', () => {
targetChain: { id: 1, name: 'Ethereum' } as ReturnType<typeof useWalletStatus>['targetChain'],
targetChainId: 1,
switchChain: mockSwitchChain,
web3Status: mockWeb3Status,
})
Comment on lines 164 to 168
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The useWalletStatus mock returns web3Status as undefined via a cast. Since useWalletStatus now guarantees a real Web3Status object, this mock can hide runtime issues if the component starts using web3Status. Prefer returning a minimal but valid Web3Status stub instead of casting undefined.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 9f5b773 as part of the shared mockWeb3Status stub rollout in this file.


renderWithChakra(<TransactionButton transaction={mockTransaction}>Send ETH</TransactionButton>)
Expand Down
40 changes: 23 additions & 17 deletions src/components/sharedComponents/WalletStatusVerifier.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,26 @@ import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { createElement, type ReactNode } from 'react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import type { Web3Status } from '@/src/hooks/useWeb3Status'
import { useWeb3StatusConnected, WalletStatusVerifier } from './WalletStatusVerifier'

const mockSwitchChain = vi.fn()

const mockWeb3Status = {
readOnlyClient: undefined,
appChainId: 1,
address: '0xdeadbeef',
balance: undefined,
connectingWallet: false,
switchingChain: false,
isWalletConnected: true,
walletClient: undefined,
isWalletSynced: true,
walletChainId: 1,
switchChain: vi.fn(),
disconnect: vi.fn(),
} as unknown as Web3Status

vi.mock('@/src/hooks/useWalletStatus', () => ({
useWalletStatus: vi.fn(() => ({
isReady: false,
Expand All @@ -15,23 +31,7 @@ vi.mock('@/src/hooks/useWalletStatus', () => ({
targetChain: { id: 1, name: 'Ethereum' },
targetChainId: 1,
switchChain: mockSwitchChain,
})),
}))

vi.mock('@/src/hooks/useWeb3Status', () => ({
useWeb3Status: vi.fn(() => ({
readOnlyClient: {},
appChainId: 1,
address: '0xdeadbeef',
balance: undefined,
connectingWallet: false,
switchingChain: false,
isWalletConnected: true,
walletClient: undefined,
isWalletSynced: true,
walletChainId: 1,
switchChain: vi.fn(),
disconnect: vi.fn(),
web3Status: mockWeb3Status,
})),
}))

Expand Down Expand Up @@ -65,6 +65,7 @@ describe('WalletStatusVerifier', () => {
targetChain: { id: 1, name: 'Ethereum' } as ReturnType<typeof useWalletStatus>['targetChain'],
targetChainId: 1,
switchChain: mockSwitchChain,
web3Status: mockWeb3Status,
})

renderWithChakra(
Expand All @@ -87,6 +88,7 @@ describe('WalletStatusVerifier', () => {
targetChain: { id: 1, name: 'Ethereum' } as ReturnType<typeof useWalletStatus>['targetChain'],
targetChainId: 1,
switchChain: mockSwitchChain,
web3Status: mockWeb3Status,
})

renderWithChakra(
Expand All @@ -111,6 +113,7 @@ describe('WalletStatusVerifier', () => {
>['targetChain'],
targetChainId: 10,
switchChain: mockSwitchChain,
web3Status: mockWeb3Status,
})

renderWithChakra(
Expand All @@ -134,6 +137,7 @@ describe('WalletStatusVerifier', () => {
targetChain: { id: 1, name: 'Ethereum' } as ReturnType<typeof useWalletStatus>['targetChain'],
targetChainId: 1,
switchChain: mockSwitchChain,
web3Status: mockWeb3Status,
})

renderWithChakra(
Expand All @@ -159,6 +163,7 @@ describe('WalletStatusVerifier', () => {
>['targetChain'],
targetChainId: 10,
switchChain: mockSwitchChain,
web3Status: mockWeb3Status,
})

renderWithChakra(
Expand All @@ -179,6 +184,7 @@ describe('WalletStatusVerifier', () => {
targetChain: { id: 1, name: 'Ethereum' } as ReturnType<typeof useWalletStatus>['targetChain'],
targetChainId: 1,
switchChain: mockSwitchChain,
web3Status: mockWeb3Status,
})

const ChildComponent = () => {
Expand Down
5 changes: 2 additions & 3 deletions src/components/sharedComponents/WalletStatusVerifier.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { createContext, type FC, type ReactElement, type ReactNode, useContext } from 'react'
import SwitchChainButton from '@/src/components/sharedComponents/ui/SwitchChainButton'
import { useWalletStatus } from '@/src/hooks/useWalletStatus'
import { useWeb3Status, type Web3Status } from '@/src/hooks/useWeb3Status'
import type { Web3Status } from '@/src/hooks/useWeb3Status'
import type { ChainsIds } from '@/src/lib/networks.config'
import { ConnectWalletButton } from '@/src/providers/Web3Provider'
import type { RequiredNonNull } from '@/src/types/utils'
Expand Down Expand Up @@ -51,9 +51,8 @@ const WalletStatusVerifier: FC<WalletStatusVerifierProps> = ({
fallback = <ConnectWalletButton />,
switchChainLabel = 'Switch to',
}: WalletStatusVerifierProps) => {
const { needsConnect, needsChainSwitch, targetChain, targetChainId, switchChain } =
const { needsConnect, needsChainSwitch, targetChain, targetChainId, switchChain, web3Status } =
useWalletStatus({ chainId })
const web3Status = useWeb3Status()

if (needsConnect) {
return fallback
Expand Down
Loading
Loading