Skip to content

Commit 0fce8b4

Browse files
committed
feat: implement with-supported-chains hoc to ensure user stais connected to supported chains
1 parent 5a87705 commit 0fce8b4

File tree

2 files changed

+84
-5
lines changed

2 files changed

+84
-5
lines changed

src/app/layout.tsx

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import type { Metadata, Viewport } from 'next';
88
import config from '_config';
99

1010
import Footer from '@/components/footer';
11+
import WithSupportedChains from '@/components/hoc/with-supported-chains';
1112
import Navbar from '@/components/navbar';
1213
import { Toaster } from '@/components/ui/sonner';
1314
import RootProvider from '@/providers/root';
@@ -29,11 +30,13 @@ export default function RootLayout({ children }: { children: React.ReactNode })
2930
<html lang='en' suppressHydrationWarning>
3031
<body>
3132
<RootProvider>
32-
<div className='grid min-h-[100dvh] grid-rows-[auto_1fr_auto]'>
33-
<Navbar />
34-
{children}
35-
<Footer />
36-
</div>
33+
<WithSupportedChains>
34+
<div className='grid min-h-[100dvh] grid-rows-[auto_1fr_auto]'>
35+
<Navbar />
36+
{children}
37+
<Footer />
38+
</div>
39+
</WithSupportedChains>
3740

3841
<Toaster richColors closeButton pauseWhenPageIsHidden />
3942
</RootProvider>
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
'use client';
2+
3+
import React, { useCallback, useEffect, useState } from 'react';
4+
5+
import type { PropsWithChildren } from 'react';
6+
7+
import { Dialog, DialogContent, DialogPortal } from '@/components/ui/dialog';
8+
import useSwitchChain from '@/hooks/use-switch-chain';
9+
10+
import SwitchChainDialogContent from '../switch-chain/dialog-content';
11+
12+
type TWithSupportedChains = PropsWithChildren;
13+
14+
export default function WithSupportedChains({ children }: TWithSupportedChains) {
15+
const [isSwitchChainDialogOpen, setIsSwitchChainDialogOpen] = useState(false);
16+
17+
const {
18+
activeChainId,
19+
mainnetChains,
20+
testnetChains,
21+
variables,
22+
isError,
23+
isSuccess,
24+
isConnectedToSupportedChain,
25+
reset,
26+
onSwitchChain
27+
} = useSwitchChain();
28+
29+
const onDialogOpenChange = useCallback(
30+
(open: boolean) => {
31+
if (!isConnectedToSupportedChain) {
32+
return;
33+
}
34+
35+
setIsSwitchChainDialogOpen(open);
36+
},
37+
[isConnectedToSupportedChain, setIsSwitchChainDialogOpen]
38+
);
39+
40+
const onSwitchSuccessCallback = useCallback(() => {
41+
reset();
42+
onDialogOpenChange(false);
43+
setIsSwitchChainDialogOpen(false);
44+
}, [reset, onDialogOpenChange, setIsSwitchChainDialogOpen]);
45+
46+
useEffect(() => {
47+
if (isConnectedToSupportedChain) {
48+
onSwitchSuccessCallback();
49+
} else {
50+
setIsSwitchChainDialogOpen(true);
51+
}
52+
}, [isConnectedToSupportedChain, onSwitchSuccessCallback]);
53+
54+
return (
55+
<>
56+
<Dialog open={isSwitchChainDialogOpen} onOpenChange={onDialogOpenChange}>
57+
<DialogPortal>
58+
<DialogContent>
59+
<SwitchChainDialogContent
60+
activeChainId={activeChainId}
61+
pendingChainId={variables?.chainId ?? 0}
62+
isSwitchSuccess={isSuccess}
63+
isSwitchError={isError}
64+
mainnetChains={mainnetChains}
65+
testnetChains={testnetChains}
66+
description='Please switch to a supported chain.'
67+
onSwitchChain={onSwitchChain}
68+
/>
69+
</DialogContent>
70+
</DialogPortal>
71+
</Dialog>
72+
73+
{children}
74+
</>
75+
);
76+
}

0 commit comments

Comments
 (0)