Skip to content

fix(wallet): enforce active chain on connect so balances are consistent#158

Merged
Nic-dorman merged 1 commit into
mainfrom
fix/v2-474-wallet-chain-mismatch
Jun 10, 2026
Merged

fix(wallet): enforce active chain on connect so balances are consistent#158
Nic-dorman merged 1 commit into
mainfrom
fix/v2-474-wallet-chain-mismatch

Conversation

@Nic-dorman

Copy link
Copy Markdown
Contributor

Fixes the inconsistent ETH balance reported in GH #85.

Root cause

The Payment Wallet panel reads balances on a fixed chain (getActiveChainId() — Arbitrum One on mainnet, the manifest chain on devnet), while the Reown AppKit account modal shows the balance on the wallet's actually-connected chain. When a wallet connected on a different chain, the two disagreed — our panel showed the Arbitrum One balance (e.g. 0.1200 ETH) while AppKit showed 0.000 ETH on the wallet's real chain. The chain was only reconciled at payment time (ensureActiveChain in utils/payment.ts), never at connect.

Fix

Move the reconciliation to connect time. The AppKit watcher (composables/useWallet.ts::syncFromAppKit) now switches the wallet onto getActiveChainId() before reading balances. If the switch doesn't complete (wallet declines, or the target chain isn't one AppKit knows), it fails soft and raises a "wrong network" banner with a Switch network button — never breaks connect.

Devnet-safe (no impact on manifest testing)

  • VITE_DEVNET=1 local-Anvil builds skip AppKit entirely → the watcher (and this code) never runs.
  • The direct-key devnet wallet is skipped via the existing _devnetWalletKeySet guard — it always sits on the manifest chain.
  • The one path it touches — custom manifest without a key + WalletConnect wallet — targets getActiveChainId() (= the manifest chain, e.g. Sepolia), which is correct.

Changes

  • composables/useWallet.ts — new ensureActiveChain() (mirrors payment.ts), wired into the connect watcher.
  • stores/wallet.tswrongNetwork flag, reset on disconnect.
  • pages/wallet.vue — wrong-network banner + Switch button.
  • locales/en.json — two new strings (other locales fall back to EN, fallbackWarn: false).

Verification

  • vitest run — 30/30 pass.
  • nuxi typecheck — clean.
  • Manual: connect a wallet sitting on a non-target chain that holds ETH on Arbitrum One; confirm the connect-time switch fires and both surfaces then match; decline the switch and confirm the banner + Switch button.

Release note

Not for the v0.8.2-rc.1 line — this is post-soak / next-cycle work.

🤖 Generated with Claude Code

The Payment Wallet panel reads ETH/ANT/USDC balances on a fixed chain
(getActiveChainId — Arbitrum One on mainnet, the manifest chain on
devnet), while the Reown AppKit account modal shows the balance on the
wallet's actually-connected chain. When a wallet connected on a
different chain, the two surfaces disagreed — our panel showed the
Arbitrum One balance while AppKit showed ~0 on, say, mainnet/Sepolia
(GH #85 / V2-474). The chain was only reconciled at payment time
(ensureActiveChain in utils/payment.ts), never at connect.

Move that reconciliation to connect time: the AppKit watcher now
switches the wallet onto getActiveChainId() before reading balances.
If the switch doesn't complete (wallet declines, or the target chain
isn't one AppKit knows), it fails soft and raises a "wrong network"
banner with a Switch button instead of breaking connect.

Devnet-safe: VITE_DEVNET builds skip AppKit entirely (watcher never
runs), and the direct-key devnet wallet is skipped via the existing
_devnetWalletKeySet guard — it always sits on the manifest chain.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Nic-dorman Nic-dorman merged commit 2c1ef8f into main Jun 10, 2026
4 checks passed
@Nic-dorman Nic-dorman deleted the fix/v2-474-wallet-chain-mismatch branch June 10, 2026 13:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant