diff --git a/.claude/settings.local.json b/.claude/settings.local.json
index b8092c79..bdaef3f3 100644
--- a/.claude/settings.local.json
+++ b/.claude/settings.local.json
@@ -16,7 +16,8 @@
"Bash(node:*)",
"Bash(npx tsc:*)",
"Bash(pnpm add:*)",
- "WebFetch(domain:www.heroui.com)"
+ "WebFetch(domain:www.heroui.com)",
+ "WebSearch"
],
"deny": []
}
diff --git a/app/layout.tsx b/app/layout.tsx
index e94421fc..69471197 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -2,6 +2,7 @@ import './global.css';
import GoogleAnalytics from '@/components/GoogleAnalytics/GoogleAnalytics';
import { ClientProviders } from '@/components/providers/ClientProviders';
+import { QueryProvider } from '@/components/providers/QueryProvider';
import RiskNotificationModal from '@/components/RiskNotificationModal';
import OnchainProviders from '@/OnchainProviders';
@@ -30,12 +31,14 @@ export default function RootLayout({ children }: { children: React.ReactNode })
>
-
-
- {children}
-
-
-
+
+
+
+ {children}
+
+
+
+
diff --git a/src/OnchainProviders.tsx b/src/OnchainProviders.tsx
index 348da33b..ae69556a 100644
--- a/src/OnchainProviders.tsx
+++ b/src/OnchainProviders.tsx
@@ -1,8 +1,7 @@
'use client';
-import { ReactNode, useMemo } from 'react';
+import { ReactNode } from 'react';
import { RainbowKitProvider, darkTheme, lightTheme } from '@rainbow-me/rainbowkit';
-import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { WagmiProvider } from 'wagmi';
import { createWagmiConfig } from '@/store/createWagmiConfig';
import { ConnectRedirectProvider } from './components/providers/ConnectRedirectProvider';
@@ -10,68 +9,45 @@ import { CustomRpcProvider, useCustomRpcContext } from './components/providers/C
type Props = { children: ReactNode };
-const queryClient = new QueryClient({
- defaultOptions: {
- queries: {
- retry: (failureCount, error) => {
- // Don't retry on GraphQL errors, network errors, or client errors
- if (
- error?.message?.includes('GraphQL') ||
- error?.message?.includes('Network response was not ok')
- ) {
- return false;
- }
- // Retry up to 2 times for other errors
- return failureCount < 2;
- },
- retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000),
- // Prevent queries from throwing and crashing the app
- throwOnError: false,
- },
- mutations: {
- // Prevent mutations from throwing and crashing the app
- throwOnError: false,
- },
- },
-});
const projectId = process.env.NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID ?? '';
+if (!projectId) {
+ if (process.env.NODE_ENV !== 'production') {
+ console.warn('NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID is not set; WagmiProvider disabled.');
+ }
+ throw new Error('NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID is not set');
+}
-// eslint-disable-next-line @typescript-eslint/promise-function-async
-function WagmiConfigProvider({ children }: Props) {
- const { customRpcUrls, rpcConfigVersion } = useCustomRpcContext();
-
- // Create wagmi config with custom RPCs, recreating when RPC config changes
- const wagmiConfig = useMemo(() => {
- return createWagmiConfig(projectId, customRpcUrls);
- }, [customRpcUrls, rpcConfigVersion]);
+const staticWagmiConfig = createWagmiConfig(projectId);
- if (!projectId) {
- if (process.env.NODE_ENV !== 'production') {
- console.warn('NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID is not set; WagmiProvider disabled.');
- }
- return children;
- }
+function WagmiConfigProvider({ children }: Props) {
+ const { customRpcUrls } = useCustomRpcContext();
+
+ // Only use dynamic config when custom RPCs are explicitly set
+ const hasCustomRpcs = Object.keys(customRpcUrls).length > 0;
+ const wagmiConfig = hasCustomRpcs
+ ? createWagmiConfig(projectId, customRpcUrls)
+ : staticWagmiConfig;
return (
-
-
-
- {children}
-
-
+
+
+
+ {children}
+
+
);
}
diff --git a/src/components/layout/header/Navbar.tsx b/src/components/layout/header/Navbar.tsx
index e5106492..85e7db22 100644
--- a/src/components/layout/header/Navbar.tsx
+++ b/src/components/layout/header/Navbar.tsx
@@ -102,7 +102,11 @@ export function Navbar() {
>
)}
-
+
{error && {error}
}
diff --git a/src/hooks/useTransactionWithToast.tsx b/src/hooks/useTransactionWithToast.tsx
index c34a8465..33c49b02 100644
--- a/src/hooks/useTransactionWithToast.tsx
+++ b/src/hooks/useTransactionWithToast.tsx
@@ -33,12 +33,10 @@ export function useTransactionWithToast({
error: txError,
sendTransactionAsync,
} = useSendTransaction();
- const { isLoading: isConfirming, isSuccess: isConfirmed } = useWaitForTransactionReceipt({
+ const { isLoading: isConfirming, isSuccess: isConfirmed, isError } = useWaitForTransactionReceipt({
hash,
});
- console.log('isConfirming', isConfirming);
-
const onClick = useCallback(() => {
if (hash) {
// if chainId is not supported, use 1
@@ -58,7 +56,7 @@ export function useTransactionWithToast({
},
);
}
- }, [isConfirming, pendingText, pendingDescription, toastId, onClick]);
+ }, [isConfirming, pendingText, pendingDescription, toastId, onClick, hash]);
useEffect(() => {
if (isConfirmed) {
@@ -80,9 +78,9 @@ export function useTransactionWithToast({
onSuccess();
}
}
- if (txError) {
+ if (isError || txError) {
toast.update(toastId, {
- render: ,
+ render: ,
type: 'error',
isLoading: false,
autoClose: 5000,
@@ -91,7 +89,9 @@ export function useTransactionWithToast({
});
}
}, [
+ hash,
isConfirmed,
+ isError,
txError,
successText,
successDescription,
@@ -99,8 +99,6 @@ export function useTransactionWithToast({
toastId,
onClick,
onSuccess,
- toast,
- hash,
]);
return { sendTransactionAsync, sendTransaction, isConfirming, isConfirmed };