Skip to content

Commit b06dd07

Browse files
committed
resolve conflicts
2 parents b13cfd3 + 93e8bae commit b06dd07

8 files changed

Lines changed: 414 additions & 51 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,5 @@ next-env.d.ts
4242

4343
package-lock.json
4444
bun.lock
45+
opencode.json
46+
ENOKI_INTEGRATION.md

app/layout.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { Metadata } from "next";
22
import { Anton, Inter } from "next/font/google";
3-
import { SuiProviders } from "@/components/SuiProviders";
3+
import { EnokiProviders } from "@/components/providers/EnokiProviders";
44
import "./globals.css";
55
import "@mysten/dapp-kit/dist/index.css";
66

@@ -57,7 +57,7 @@ export default function RootLayout({
5757
className={`${anton.variable} ${inter.variable} antialiased`}
5858
suppressHydrationWarning
5959
>
60-
<SuiProviders>{children}</SuiProviders>
60+
<EnokiProviders>{children}</EnokiProviders>
6161
</body>
6262
</html>
6363
);

bun.lock

Lines changed: 280 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

components/SuiProviders.tsx

Lines changed: 0 additions & 34 deletions
This file was deleted.

components/WalletConnectButton.tsx

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,61 @@
11
"use client";
22

3-
import { ConnectButton, useCurrentAccount } from "@mysten/dapp-kit";
3+
import { ConnectButton, useCurrentAccount, useDisconnectWallet } from "@mysten/dapp-kit";
4+
import { useState, useCallback } from "react";
45

56
export function WalletConnectButton() {
67
const account = useCurrentAccount();
8+
const { mutate: disconnect } = useDisconnectWallet();
9+
const [isMenuOpen, setIsMenuOpen] = useState(false);
710

8-
// Format địa chỉ: 0x1234...5678
911
const formatAddress = (address: string) => {
1012
return `${address.slice(0, 6)}...${address.slice(-4)}`;
1113
};
1214

15+
const handleDisconnect = useCallback(() => {
16+
// Clear session storage to fix redirect_uri mismatch on re-login
17+
sessionStorage.clear();
18+
disconnect();
19+
setIsMenuOpen(false);
20+
}, [disconnect]);
21+
1322
return (
14-
<ConnectButton
15-
connectText="Launch App"
16-
className="sui-wallet-button"
17-
>
18-
{account && (
19-
<div className="bg-black dark:bg-white text-white dark:text-black px-5 py-2 rounded-full font-bold text-sm uppercase hover:scale-105 transition-transform flex items-center gap-2">
20-
<span className="material-icons text-base">account_balance_wallet</span>
21-
<span>{formatAddress(account.address)}</span>
23+
<div className="relative">
24+
<ConnectButton connectText="Launch App" className="sui-wallet-button">
25+
{account && (
26+
<button
27+
onClick={() => setIsMenuOpen(!isMenuOpen)}
28+
className="bg-black dark:bg-white text-white dark:text-black px-5 py-2 rounded-full font-bold text-sm uppercase hover:scale-105 transition-transform flex items-center gap-2"
29+
>
30+
<span className="material-icons text-base">account_balance_wallet</span>
31+
<span>{formatAddress(account.address)}</span>
32+
<span className="material-icons text-sm">
33+
{isMenuOpen ? "expand_less" : "expand_more"}
34+
</span>
35+
</button>
36+
)}
37+
</ConnectButton>
38+
39+
{/* Dropdown menu */}
40+
{isMenuOpen && account && (
41+
<div className="absolute right-0 top-full mt-2 bg-white dark:bg-gray-800 rounded-lg shadow-lg border border-gray-200 dark:border-gray-700 py-2 min-w-[150px] z-50">
42+
<button
43+
onClick={handleDisconnect}
44+
className="w-full px-4 py-2 text-left text-sm text-red-600 hover:bg-gray-100 dark:hover:bg-gray-700 flex items-center gap-2"
45+
>
46+
<span className="material-icons text-sm">logout</span>
47+
Disconnect
48+
</button>
2249
</div>
2350
)}
24-
</ConnectButton>
51+
52+
{/* Click outside to close */}
53+
{isMenuOpen && (
54+
<div
55+
className="fixed inset-0 z-40"
56+
onClick={() => setIsMenuOpen(false)}
57+
/>
58+
)}
59+
</div>
2560
);
2661
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
"use client";
2+
3+
import { ReactNode, useEffect } from "react";
4+
import {
5+
createNetworkConfig,
6+
SuiClientProvider,
7+
WalletProvider,
8+
useSuiClientContext,
9+
} from "@mysten/dapp-kit";
10+
import { getFullnodeUrl } from "@mysten/sui/client";
11+
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
12+
import { isEnokiNetwork, registerEnokiWallets } from "@mysten/enoki";
13+
import { enokiConfig } from "@/config/enoki";
14+
import "@mysten/dapp-kit/dist/index.css";
15+
16+
const { networkConfig } = createNetworkConfig({
17+
testnet: { url: getFullnodeUrl("testnet") },
18+
mainnet: { url: getFullnodeUrl("mainnet") },
19+
});
20+
21+
const queryClient = new QueryClient({
22+
defaultOptions: {
23+
queries: {
24+
refetchOnWindowFocus: false,
25+
retry: false,
26+
},
27+
},
28+
});
29+
30+
function RegisterEnokiWallets() {
31+
const { client, network } = useSuiClientContext();
32+
33+
useEffect(() => {
34+
if (!isEnokiNetwork(network)) return;
35+
36+
const redirectUrl =
37+
typeof window !== "undefined"
38+
? `${window.location.origin}`
39+
: "http://localhost:3000";
40+
41+
const { unregister } = registerEnokiWallets({
42+
apiKey: enokiConfig.apiKey,
43+
providers: {
44+
google: {
45+
clientId: enokiConfig.googleClientId,
46+
redirectUrl,
47+
},
48+
},
49+
client,
50+
network,
51+
});
52+
53+
return unregister;
54+
}, [client, network]);
55+
56+
return null;
57+
}
58+
59+
export function EnokiProviders({ children }: { children: ReactNode }) {
60+
return (
61+
<QueryClientProvider client={queryClient}>
62+
<SuiClientProvider networks={networkConfig} defaultNetwork="testnet">
63+
<RegisterEnokiWallets />
64+
<WalletProvider autoConnect={true}>{children}</WalletProvider>
65+
</SuiClientProvider>
66+
</QueryClientProvider>
67+
);
68+
}

config/enoki.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export const enokiConfig = {
2+
apiKey: process.env.NEXT_PUBLIC_ENOKI_API_KEY!,
3+
googleClientId: process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID!,
4+
network: (process.env.NEXT_PUBLIC_SUI_NETWORK || "testnet") as "mainnet" | "testnet",
5+
rpcUrl: process.env.NEXT_PUBLIC_SUI_RPC_URL!,
6+
};

package.json

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,21 @@
99
"lint": "eslint"
1010
},
1111
"dependencies": {
12+
"@mysten/bcs": "^1.9.2",
1213
"@mysten/dapp-kit": "^0.20.0",
14+
"@mysten/enoki": "^0.13.0",
15+
"@mysten/kiosk": "^0.14.6",
16+
"@mysten/payment-kit": "^0.0.20",
1317
"@mysten/sui": "^1.45.2",
18+
"@mysten/walrus": "^0.9.0",
19+
"@mysten/zksend": "^0.14.12",
1420
"@tanstack/react-query": "^5.90.18",
1521
"class-variance-authority": "^0.7.1",
1622
"clsx": "^2.1.1",
17-
"gsap": "^3.13.0",
1823
"lucide-react": "^0.562.0",
24+
"gsap": "^3.14.2",
25+
"jwt-decode": "^4.0.0",
26+
"motion": "^12.26.2",
1927
"next": "16.1.3",
2028
"react": "19.2.3",
2129
"react-dom": "19.2.3",
@@ -41,4 +49,4 @@
4149
"sharp",
4250
"unrs-resolver"
4351
]
44-
}
52+
}

0 commit comments

Comments
 (0)