Troubleshooting
Wagmi SDK — Troubleshooting
Common issues and solutions when integrating ONEpocket (formerly CROSSx) with wagmi.
useAccount() shows disconnected after page refresh
useAccount() shows disconnected after page refreshSymptom: SDK initialization succeeds (session is restored, address is loaded), but useAccount() still returns isConnected: false after a page refresh.
Cause: wagmi calls connector.setup() internally without await (fire-and-forget). If setup() has not finished SDK initialization by the time wagmi calls isAuthorized(), it returns false and wagmi skips reconnection.
Timeline (race condition):
1. wagmi: connector.setup() → fires sdk.initialize() (async, in progress)
2. wagmi: await isAuthorized() → sdk.isAuthenticated() → false ❌ (init not done)
3. wagmi: skip reconnect → useAccount() = disconnected
4. SDK: initialize() completes → too late, wagmi already gave up
Solution: This is resolved at the SDK level. The connector's isAuthorized() ensures SDK initialization (including session restore) completes before checking authentication state:
// Connector internals (automatic, no action needed)
async isAuthorized() {
await ensureSdkInitialized() // waits for initialize() to complete
return sdk.isAuthenticated() // now returns the correct value
}This behavior has been standard since v1.2.5 and is included in all 2.x releases — if you are on the current 2.x line, no action or workaround code is needed in your DApp.
If you were using a
SdkReconnectGuardworkaround from the v1.x era, you can safely remove it.
Legacy: SDK versions before v1.2.5
Only relevant if you are pinned to an old 1.x release and cannot upgrade — use this workaround component:
import { useEffect } from 'react'
import { useAccount } from 'wagmi'
import { reconnect } from 'wagmi/actions'
import { wagmiConfig } from './wagmi.config'
function SdkReconnectGuard({ sdk }: { sdk: CROSSxSDK }) {
const { status } = useAccount()
useEffect(() => {
if (status !== 'disconnected') return
if (sdk.isAuthenticated()) {
reconnect(wagmiConfig)
return
}
const unsubscribe = sdk.on('initialized', ({ restored }) => {
if (restored) reconnect(wagmiConfig)
})
return unsubscribe
}, [status])
return null
}Place it inside your WagmiProvider:
<WagmiProvider config={wagmiConfig}>
<QueryClientProvider client={queryClient}>
<SdkReconnectGuard sdk={sdk} />
<App />
</QueryClientProvider>
</WagmiProvider>Already logged in. Call signOut() first. error on reconnect
Already logged in. Call signOut() first. error on reconnectSymptom: After refresh, the app throws an error instead of restoring the session.
Cause: The connector attempted signInWithCreate() when the SDK was already authenticated but had no cached addresses.
Solution: This is handled automatically in the connector. When already authenticated, it first uses the cached sdk.getAddress() to recover wallet info. Only on an explicit user-initiated connect with no recoverable address does it sign out and start a fresh login; during automatic reconnect it never destroys the session.
If you see this error, ensure:
- You are using the latest
@nexus-cross/crossx-sdk-wagmipackage - You are not calling
sdk.signIn()manually while the connector is managing the session
Password modal appears on every page refresh
Symptom: The password prompt shows up each time the page is refreshed, even though the user already entered it.
Cause: The SDK's loadWalletAfterAuth() requires password verification to decrypt wallet keys. This is expected security behavior on the first load after refresh.
Solution: This is by design — the SDK verifies the wallet password once per session for security. The password is held in memory for the session duration and cleared on signOut() or page unload.
Wrong wallet address shown after refresh
Symptom: User selected wallet index 1, but after refresh, wallet index 0 is shown.
Cause: The selected wallet index was not persisted.
Solution: The connector automatically persists the wallet index and address in localStorage (keys: crossx-wallet-index, crossx-wallet-address). Ensure:
localStorageis available in your environment- If using SSR (e.g. Next.js), provide custom callbacks:
crossxConnector({
projectId: 'YOUR_PROJECT_ID',
appName: 'My DApp',
getStoredWalletIndex: () => {
// read from cookies or other SSR-safe storage
return Number(getCookie('crossx-wallet-index')) || 0
},
onWalletIndexChanged: (index) => {
setCookie('crossx-wallet-index', String(index))
},
getStoredWalletAddress: () => getCookie('crossx-wallet-address') ?? null,
onWalletAddressChanged: (address) => {
setCookie('crossx-wallet-address', address)
},
clearStoredWalletAddress: () => {
deleteCookie('crossx-wallet-address')
},
})Connector not found in useConnect()
useConnect()Symptom: connectors.find(c => c.id === 'crossx') returns undefined.
Cause: The connector was not added to the wagmi config.
Solution: Verify your createConfig call includes the ONEpocket connector:
import { createConfig, http } from 'wagmi'
import { crossxConnector } from '@nexus-cross/crossx-sdk-wagmi'
export const wagmiConfig = createConfig({
connectors: [
crossxConnector({
projectId: 'YOUR_PROJECT_ID',
appName: 'My DApp',
}),
],
chains: [oneMainnet],
transports: { [oneMainnet.id]: http() },
})Chain XXXXX is not configured error on switchChain
Chain XXXXX is not configured error on switchChainSymptom: Calling useSwitchChain throws Chain XXXXX is not configured.
Cause: The target chain is not included in the wagmi chains array.
Solution: Add all chains you need to both chains and transports:
export const wagmiConfig = createConfig({
connectors: [crossxConnector({ projectId: '...', appName: '...' })],
chains: [oneMainnet, oneTestnet], // ← include both
transports: {
[oneMainnet.id]: http(),
[oneTestnet.id]: http(), // ← transport for each chain
},
})Related
Updated 2 days ago