@@ -42,10 +42,11 @@ import {
4242 useActiveAccount ,
4343 useActiveWallet ,
4444 useActiveWalletChain ,
45+ useActiveWalletConnectionStatus ,
4546 useSwitchActiveWalletChain ,
4647 useWalletBalance ,
4748} from "thirdweb/react" ;
48- import { privateKeyToAccount } from "thirdweb/wallets" ;
49+ import { type Wallet , privateKeyToAccount } from "thirdweb/wallets" ;
4950import { getFaucetClaimAmount } from "../../app/(app)/api/testnet-faucet/claim/claim-amount" ;
5051import { useAllChainsData } from "../../hooks/chains/allChains" ;
5152import { useV5DashboardChain } from "../../lib/v5-adapter" ;
@@ -78,6 +79,7 @@ function useIsNetworkMismatch(txChainId: number) {
7879type MistmatchButtonProps = React . ComponentProps < typeof Button > & {
7980 txChainId : number ;
8081 isLoggedIn : boolean ;
82+ isPending : boolean ;
8183} ;
8284
8385export const MismatchButton = forwardRef <
@@ -93,6 +95,7 @@ export const MismatchButton = forwardRef<
9395 const client = useThirdwebClient ( ) ;
9496 const pathname = usePathname ( ) ;
9597 const txChain = useV5DashboardChain ( txChainId ) ;
98+ const connectionStatus = useActiveWalletConnectionStatus ( ) ;
9699
97100 const txChainBalance = useWalletBalance ( {
98101 address : account ?. address ,
@@ -101,14 +104,39 @@ export const MismatchButton = forwardRef<
101104 } ) ;
102105
103106 const networksMismatch = useIsNetworkMismatch ( txChainId ) ;
107+ const switchNetwork = useSwitchActiveWalletChain ( ) ;
108+
109+ const showSwitchChainPopover =
110+ networksMismatch && wallet && ! canSwitchNetworkWithoutConfirmation ( wallet ) ;
111+
104112 const [ isMismatchPopoverOpen , setIsMismatchPopoverOpen ] = useState ( false ) ;
105113 const trackEvent = useTrack ( ) ;
106114
107115 const chainId = activeWalletChain ?. id ;
108116
117+ const switchNetworkMutation = useMutation ( {
118+ mutationFn : switchNetwork ,
119+ } ) ;
120+
109121 const eventRef =
110122 useRef < React . MouseEvent < HTMLButtonElement , MouseEvent > > ( undefined ) ;
111123
124+ if ( connectionStatus === "connecting" ) {
125+ return (
126+ < Button
127+ className = { props . className }
128+ size = { props . size }
129+ asChild
130+ variant = "outline"
131+ >
132+ < div >
133+ < Spinner className = "size-4 shrink-0" />
134+ Connecting Wallet
135+ </ div >
136+ </ Button >
137+ ) ;
138+ }
139+
112140 if ( ! wallet || ! chainId || ! isLoggedIn ) {
113141 return (
114142 < Button className = { props . className } size = { props . size } asChild >
@@ -129,16 +157,19 @@ export const MismatchButton = forwardRef<
129157
130158 const disabled =
131159 buttonProps . disabled ||
160+ switchNetworkMutation . isPending ||
132161 // if user is about to trigger a transaction on txChain, but txChainBalance is not yet loaded and is required before proceeding
133- ( ! networksMismatch && txChainBalance . isPending && isBalanceRequired ) ;
162+ ( ! showSwitchChainPopover && txChainBalance . isPending && isBalanceRequired ) ;
163+
164+ const showSpinner = props . isPending || switchNetworkMutation . isPending ;
134165
135166 return (
136167 < >
137168 < Popover
138169 open = { isMismatchPopoverOpen }
139170 onOpenChange = { ( v ) => {
140171 if ( v ) {
141- if ( networksMismatch ) {
172+ if ( showSwitchChainPopover ) {
142173 setIsMismatchPopoverOpen ( true ) ;
143174 }
144175 } else {
@@ -149,14 +180,17 @@ export const MismatchButton = forwardRef<
149180 < PopoverTrigger asChild >
150181 < Button
151182 { ...buttonProps }
183+ className = { cn ( "gap-2 disabled:opacity-100" , buttonProps . className ) }
152184 disabled = { disabled }
153185 type = {
154- networksMismatch || notEnoughBalance ? "button" : buttonProps . type
186+ showSwitchChainPopover || notEnoughBalance
187+ ? "button"
188+ : buttonProps . type
155189 }
156- onClick = { ( e ) => {
190+ onClick = { async ( e ) => {
157191 e . stopPropagation ( ) ;
158192
159- if ( networksMismatch ) {
193+ if ( showSwitchChainPopover ) {
160194 eventRef . current = e ;
161195 return ;
162196 }
@@ -171,13 +205,20 @@ export const MismatchButton = forwardRef<
171205 return ;
172206 }
173207
208+ // in case of in-app or smart wallet wallet, the user is not prompted to switch the network
209+ // we have to do it programmatically
210+ if ( activeWalletChain ?. id !== txChain . id ) {
211+ await switchNetworkMutation . mutateAsync ( txChain ) ;
212+ }
213+
174214 if ( buttonProps . onClick ) {
175215 return buttonProps . onClick ( e ) ;
176216 }
177217 } }
178218 ref = { ref }
179219 >
180220 { buttonProps . children }
221+ { showSpinner && < Spinner className = "size-4 shrink-0" /> }
181222 </ Button >
182223 </ PopoverTrigger >
183224 < PopoverContent className = "min-w-[350px]" side = "top" sideOffset = { 10 } >
@@ -545,3 +586,7 @@ const GetLocalHostTestnetFunds: React.FC = () => {
545586 </ Button >
546587 ) ;
547588} ;
589+
590+ function canSwitchNetworkWithoutConfirmation ( wallet : Wallet ) {
591+ return wallet . id === "inApp" || wallet . id === "smart" ;
592+ }
0 commit comments