Skip to content

Commit 06457f5

Browse files
author
Bingle Kruger
committed
chore: Fix Solana Connection
1 parent 6dd484d commit 06457f5

File tree

5 files changed

+179
-72
lines changed

5 files changed

+179
-72
lines changed

ntc-web/components/WalletBalance.tsx

+32-19
Original file line numberDiff line numberDiff line change
@@ -16,51 +16,64 @@
1616
* along with this program. If not, see <https://www.gnu.org/licenses/>.
1717
*/
1818

19+
// components/WalletBalance.tsx
1920
"use client";
2021

2122
import { useEffect, useState } from "react";
2223
import { useWallet } from "@solana/wallet-adapter-react";
23-
import { Connection, clusterApiUrl, LAMPORTS_PER_SOL } from "@solana/web3.js";
24+
import { LAMPORTS_PER_SOL } from "@solana/web3.js";
25+
import { useSolanaConnection } from "@/lib/solanaConnection";
2426

2527
const WalletBalance = () => {
2628
const { publicKey, connected } = useWallet();
29+
const connection = useSolanaConnection();
2730
const [balance, setBalance] = useState<number | null>(null);
28-
const connection = new Connection(clusterApiUrl("devnet"));
31+
const [isLoading, setIsLoading] = useState(false);
2932

30-
// Function to fetch wallet balance
3133
const fetchBalance = async () => {
32-
if (!publicKey) return;
34+
if (!publicKey || !connection) return;
35+
36+
setIsLoading(true);
3337
try {
3438
const lamports = await connection.getBalance(publicKey);
3539
setBalance(lamports / LAMPORTS_PER_SOL);
3640
} catch (error) {
3741
console.error("Error fetching balance:", error);
42+
setBalance(null);
43+
} finally {
44+
setIsLoading(false);
3845
}
3946
};
4047

41-
// Fetch balance when the component mounts or wallet connects
4248
useEffect(() => {
4349
if (connected && publicKey) {
4450
fetchBalance();
45-
}
46-
}, [connected, publicKey]);
4751

48-
// Listen for wallet transactions and refresh balance
49-
useEffect(() => {
50-
const handleWalletTransaction = () => {
51-
console.log("Wallet transaction detected, refreshing balance...");
52-
fetchBalance();
53-
};
52+
// Subscribe to account changes
53+
const subscriptionId = connection.onAccountChange(
54+
publicKey,
55+
() => {
56+
console.log("Balance update detected");
57+
fetchBalance();
58+
},
59+
"confirmed"
60+
);
5461

55-
window.addEventListener("walletTransaction", handleWalletTransaction);
56-
return () => {
57-
window.removeEventListener("walletTransaction", handleWalletTransaction);
58-
};
59-
}, []);
62+
return () => {
63+
connection.removeAccountChangeListener(subscriptionId);
64+
};
65+
}
66+
}, [connected, publicKey, connection]);
6067

6168
return (
6269
<span className="text-sm font-bold">
63-
{balance !== null ? `${balance.toFixed(2)} SOL` : "Loading..."}
70+
{isLoading ? (
71+
"Loading..."
72+
) : balance !== null ? (
73+
`${balance.toFixed(2)} SOL`
74+
) : (
75+
"Error loading balance"
76+
)}
6477
</span>
6578
);
6679
};

ntc-web/components/WalletConnector.tsx

+51-51
Original file line numberDiff line numberDiff line change
@@ -24,65 +24,61 @@ import { useWallet } from "@solana/wallet-adapter-react";
2424
import { WalletMultiButton } from "@solana/wallet-adapter-react-ui";
2525
import { useUser } from "@clerk/nextjs";
2626
import { Copy } from "lucide-react";
27-
import WalletBalance from "@/components/WalletBalance";
28-
import { Connection, clusterApiUrl } from "@solana/web3.js";
27+
import WalletBalance from "@/components/WalletBalance";
28+
import { useSolanaConnection } from "@/lib/solanaConnection";
2929

3030
const WalletConnector = () => {
3131
const { publicKey, connected, disconnect } = useWallet();
3232
const { user } = useUser();
33+
const connection = useSolanaConnection();
3334
const [isLinked, setIsLinked] = useState<boolean>(false);
3435
const [loadingLinkStatus, setLoadingLinkStatus] = useState<boolean>(true);
3536

36-
const connection = new Connection(clusterApiUrl("devnet"));
37-
38-
// Fetch the current wallet link status from your API
3937
useEffect(() => {
4038
async function fetchWalletStatus() {
41-
const res = await fetch("/api/wallet");
42-
if (res.ok) {
43-
const data = await res.json();
44-
setIsLinked(!!data.walletAddress);
39+
try {
40+
const res = await fetch("/api/wallet");
41+
if (res.ok) {
42+
const data = await res.json();
43+
setIsLinked(!!data.walletAddress);
44+
}
45+
} catch (error) {
46+
console.error("Error fetching wallet status:", error);
47+
} finally {
48+
setLoadingLinkStatus(false);
4549
}
46-
setLoadingLinkStatus(false);
4750
}
51+
4852
if (user) {
4953
fetchWalletStatus();
5054
}
5155
}, [user]);
5256

53-
// Add listener for transactions affecting the wallet
54-
useEffect(() => {
55-
if (!publicKey || !connected) return;
56-
57-
const listenerId = connection.onAccountChange(publicKey, () => {
58-
console.log("🔄 Wallet transaction detected! Refreshing balance...");
59-
window.dispatchEvent(new Event("walletTransaction")); // Dispatch event for balance update
60-
});
61-
62-
return () => {
63-
connection.removeAccountChangeListener(listenerId);
64-
};
65-
}, [publicKey, connected]);
66-
67-
// Call API to link wallet
6857
const handleLinkWallet = async () => {
6958
if (!publicKey) return;
70-
const res = await fetch("/api/wallet", {
71-
method: "POST",
72-
headers: { "Content-Type": "application/json" },
73-
body: JSON.stringify({ walletAddress: publicKey.toBase58() }),
74-
});
75-
if (res.ok) {
76-
setIsLinked(true);
59+
try {
60+
const res = await fetch("/api/wallet", {
61+
method: "POST",
62+
headers: { "Content-Type": "application/json" },
63+
body: JSON.stringify({ walletAddress: publicKey.toBase58() }),
64+
});
65+
if (res.ok) {
66+
setIsLinked(true);
67+
}
68+
} catch (error) {
69+
console.error("Error linking wallet:", error);
7770
}
7871
};
7972

80-
// Unlink wallet (and optionally disconnect)
8173
const handleUnlinkWallet = async () => {
82-
const res = await fetch("/api/wallet", { method: "DELETE" });
83-
if (res.ok) {
84-
setIsLinked(false);
85-
disconnect();
74+
try {
75+
const res = await fetch("/api/wallet", { method: "DELETE" });
76+
if (res.ok) {
77+
setIsLinked(false);
78+
disconnect();
79+
}
80+
} catch (error) {
81+
console.error("Error unlinking wallet:", error);
8682
}
8783
};
8884

@@ -96,13 +92,11 @@ const WalletConnector = () => {
9692
<div className="flex items-center space-x-4">
9793
{connected && publicKey ? (
9894
<>
99-
{/* Display SOL balance using WalletBalance component */}
10095
<WalletBalance />
101-
102-
{/* Display wallet address */}
96+
10397
<div className="flex items-center space-x-2">
10498
<span className="text-sm font-mono">
105-
{publicKey.toBase58().slice(0, 8) + "..." + publicKey.toBase58().slice(-8)}
99+
{publicKey.toBase58().slice(0, 8)}...{publicKey.toBase58().slice(-8)}
106100
</span>
107101
<button
108102
onClick={handleCopyAddress}
@@ -113,16 +107,22 @@ const WalletConnector = () => {
113107
</button>
114108
</div>
115109

116-
{/* Link/Unlink wallet */}
117-
{!loadingLinkStatus && !isLinked && (
118-
<button onClick={handleLinkWallet} className="px-2 py-1 bg-green-500 text-white rounded">
119-
Link Wallet
120-
</button>
121-
)}
122-
{!loadingLinkStatus && isLinked && (
123-
<button onClick={handleUnlinkWallet} className="px-2 py-1 bg-red-500 text-white rounded">
124-
Unlink Wallet
125-
</button>
110+
{!loadingLinkStatus && (
111+
isLinked ? (
112+
<button
113+
onClick={handleUnlinkWallet}
114+
className="px-2 py-1 bg-red-500 text-white rounded hover:bg-red-600 transition-colors"
115+
>
116+
Unlink Wallet
117+
</button>
118+
) : (
119+
<button
120+
onClick={handleLinkWallet}
121+
className="px-2 py-1 bg-green-500 text-white rounded hover:bg-green-600 transition-colors"
122+
>
123+
Link Wallet
124+
</button>
125+
)
126126
)}
127127
</>
128128
) : (

ntc-web/lib/solanaConnection.ts

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/**
2+
* Nautilus Trusted Compute
3+
* Copyright (C) 2025 Nautilus
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU Affero General Public License as published
7+
* by the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU Affero General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Affero General Public License
16+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
*/
18+
19+
// lib/solanaConnection.ts
20+
import { Connection, clusterApiUrl } from "@solana/web3.js";
21+
import { useConnection } from "@solana/wallet-adapter-react";
22+
import { create } from 'zustand';
23+
24+
// Connection configuration
25+
export const SOLANA_NETWORK = "devnet";
26+
export const SOLANA_ENDPOINT = clusterApiUrl(SOLANA_NETWORK);
27+
28+
// Create a single connection instance
29+
export const connection = new Connection(SOLANA_ENDPOINT, "processed");
30+
31+
// Custom hook for using the connection consistently
32+
export function useSolanaConnection() {
33+
const { connection } = useConnection();
34+
return connection;
35+
}
36+
37+
// Define state shape
38+
type State = {
39+
isConnecting: boolean;
40+
lastError: string | null;
41+
}
42+
43+
// Define actions
44+
type Actions = {
45+
setConnecting: (isConnecting: boolean) => void;
46+
setError: (error: string | null) => void;
47+
}
48+
49+
// Combine state and actions
50+
type ConnectionState = State & Actions;
51+
52+
// Create store with explicit type annotations
53+
export const useConnectionStore = create<ConnectionState>((set: (
54+
fn: (state: ConnectionState) => ConnectionState
55+
) => void) => ({
56+
isConnecting: false,
57+
lastError: null,
58+
setConnecting: (isConnecting: boolean) =>
59+
set((state) => ({ ...state, isConnecting })),
60+
setError: (error: string | null) =>
61+
set((state) => ({ ...state, lastError: error }))
62+
}));

ntc-web/package-lock.json

+32-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ntc-web/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@
5252
"react-dom": "^19.0.0",
5353
"shadcn-ui": "^0.9.4",
5454
"tailwind-merge": "^2.6.0",
55-
"tailwindcss-animate": "^1.0.7"
55+
"tailwindcss-animate": "^1.0.7",
56+
"zustand": "^5.0.3"
5657
},
5758
"devDependencies": {
5859
"@eslint/eslintrc": "^3",

0 commit comments

Comments
 (0)