Skip to content

fix: sync approved CAIP networks before connection status transition#5639

Open
tomiir wants to merge 1 commit intomainfrom
tomiir/wc-reconnect-networks
Open

fix: sync approved CAIP networks before connection status transition#5639
tomiir wants to merge 1 commit intomainfrom
tomiir/wc-reconnect-networks

Conversation

@tomiir
Copy link
Copy Markdown
Collaborator

@tomiir tomiir commented Apr 10, 2026

Summary

  • Moved getApprovedCaipNetworksData + setApprovedCaipNetworksData to run before syncAccount() in syncWalletConnectAccount(), so approvedCaipNetworkIds and supportsAllNetworks are available in useAppKitNetwork at the moment the connection status transitions to connected
  • Scoped approved network sync to the if (sessionAddress) guard — namespaces without session data no longer overwrite with defaults
  • Added approved network sync in the accountChanged handler as a safety net for the wagmi reconnect path

Test plan

  • Connect via WalletConnect — verify approvedCaipNetworkIds and supportsAllNetworks are correct immediately on connected status
  • Refresh the page (reconnect) — verify values are still correct after reconnection
  • Verify non-WC connections (injected, coinbase) are unaffected

🤖 Generated with Claude Code

Move `getApprovedCaipNetworksData` and `setApprovedCaipNetworksData` to
run before `syncAccount()` in `syncWalletConnectAccount()`, ensuring
`approvedCaipNetworkIds` and `supportsAllNetworks` are available in
`useAppKitNetwork` at the moment the connection status transitions to
'connected'.

Also scope the approved network sync to the `if (sessionAddress)` guard
so namespaces without session data no longer overwrite with defaults,
and add approved network sync in the `accountChanged` handler as a
safety net for the wagmi reconnect path.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 10, 2026 14:13
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 10, 2026

⚠️ No Changeset found

Latest commit: e177a26

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 10, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
appkit-demo Ready Ready Preview, Comment Apr 10, 2026 2:17pm
appkit-gallery Ready Ready Preview, Comment Apr 10, 2026 2:17pm
appkit-headless-sample-app Ready Ready Preview, Comment Apr 10, 2026 2:17pm
appkit-laboratory Ready Ready Preview, Comment Apr 10, 2026 2:17pm
9 Skipped Deployments
Project Deployment Actions Updated (UTC)
appkit-basic-example Ignored Ignored Apr 10, 2026 2:17pm
appkit-basic-sign-client-example Ignored Ignored Apr 10, 2026 2:17pm
appkit-basic-up-example Ignored Ignored Apr 10, 2026 2:17pm
appkit-ethers5-bera Ignored Ignored Apr 10, 2026 2:17pm
appkit-nansen-demo Ignored Ignored Apr 10, 2026 2:17pm
appkit-wagmi-cdn-example Ignored Ignored Apr 10, 2026 2:17pm
ethereum-provider-wagmi-example Ignored Ignored Apr 10, 2026 2:17pm
next-wagmi-solana-bitcoin-example Ignored Ignored Apr 10, 2026 2:17pm
vue-wagmi-example Ignored Ignored Apr 10, 2026 2:17pm

Request Review

@github-actions
Copy link
Copy Markdown
Contributor

Visual Regression Test Results ✅ Passed

⚠️ 15 visual change(s) detected

Chromatic Build: https://www.chromatic.com/build?appId=6493191bf4b10fed8ca7353f&number=867
Storybook Preview: https://6493191bf4b10fed8ca7353f-yrcwqexwjc.chromatic.com/

👉 Please review the visual changes in Chromatic and accept or reject them.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adjusts WalletConnect reconnection/account-sync flow so approved CAIP networks (approvedCaipNetworkIds, supportsAllNetworks) are synchronized earlier, ensuring consumers (e.g., useAppKitNetwork) have correct network-approval state before the connection status transitions to connected.

Changes:

  • Sync approved CAIP network data before syncAccount() in syncWalletConnectAccount() to make approval state available earlier in the connection lifecycle.
  • Avoid syncing approved-network defaults for namespaces without WalletConnect session account data (if (sessionAddress) guard).
  • Add an approved-network sync in the accountChanged handler for WalletConnect as a reconnect safety net.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1270 to +1276
if (connector.type === UtilConstantsUtil.CONNECTOR_TYPE_WALLET_CONNECT) {
const approvedData = this.getApprovedCaipNetworksData()
ChainController.setApprovedCaipNetworksData(chainNamespace, {
approvedCaipNetworkIds: approvedData.approvedCaipNetworkIds,
supportsAllNetworks: approvedData.supportsAllNetworks
})
}
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getApprovedCaipNetworksData() derives WalletConnect/non-WalletConnect behavior from ProviderController.getProviderId(ChainController.state.activeChain). In this accountChanged handler we may be syncing for a non-active namespace (and potentially in multi-wallet scenarios where the active chain uses a different connector), which can cause WalletConnect sessions to be treated as non-WalletConnect and overwrite approved networks with { supportsAllNetworks: true, approvedCaipNetworkIds: [] }. Consider changing getApprovedCaipNetworksData to accept a chainNamespace (or provider type) and use ProviderController.getProviderId(chainNamespace) (or skip the providerId check since this block is already gated on WalletConnect), then pass the current chainNamespace here.

Copilot uses AI. Check for mistakes.
Comment on lines +1554 to +1557
const data = this.getApprovedCaipNetworksData()
ChainController.setApprovedCaipNetworksData(chainNamespace, {
approvedCaipNetworkIds: data.approvedCaipNetworkIds,
supportsAllNetworks: data.supportsAllNetworks
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getApprovedCaipNetworksData() checks the provider type of ChainController.state.activeChain, so calling it while iterating namespaces can yield default (non-WalletConnect) values if the active namespace’s providerId hasn’t been set yet (or if the active namespace is connected via a different connector in multi-wallet mode). This can store incorrect approved network data for the current chainNamespace. Prefer computing approved network data directly from the WalletConnect session here, or update getApprovedCaipNetworksData to take chainNamespace/providerType and use that instead of activeChain.

Suggested change
const data = this.getApprovedCaipNetworksData()
ChainController.setApprovedCaipNetworksData(chainNamespace, {
approvedCaipNetworkIds: data.approvedCaipNetworkIds,
supportsAllNetworks: data.supportsAllNetworks
const approvedCaipNetworkIds = Array.from(
new Set(
namespaceAccounts.map(account => {
const { chainId: approvedChainId } = ParseUtil.parseCaipAddress(account as CaipAddress)
return `${chainNamespace}:${approvedChainId}` as CaipNetworkId
})
)
)
const namespaceCaipNetworkIds = (this.getCaipNetworks() || [])
.filter(network => network.chainNamespace === chainNamespace)
.map(network => network.id)
const supportsAllNetworks =
namespaceCaipNetworkIds.length > 0 &&
namespaceCaipNetworkIds.every(networkId => approvedCaipNetworkIds.includes(networkId))
ChainController.setApprovedCaipNetworksData(chainNamespace, {
approvedCaipNetworkIds,
supportsAllNetworks

Copilot uses AI. Check for mistakes.
@github-actions
Copy link
Copy Markdown
Contributor

📦 Bundle Size Check

All bundles are within size limits

📊 View detailed bundle sizes

> @reown/appkit-monorepo@1.7.1 size /home/runner/work/appkit/appkit


> size-limit

@reown/appkit - Main Entry
Size limit:   80 kB
Size:         75.72 kB with all dependencies, minified and gzipped
Loading time: 1.5 s    on slow 3G
Running time: 1.8 s    on Snapdragon 410
Total time:   3.3 s
@reown/appkit/react
Size limit:   235 kB
Size:         234.88 kB with all dependencies, minified and gzipped
Loading time: 4.6 s     on slow 3G
Running time: 6.2 s     on Snapdragon 410
Total time:   10.8 s
@reown/appkit/vue
Size limit:   80 kB
Size:         75.72 kB with all dependencies, minified and gzipped
Loading time: 1.5 s    on slow 3G
Running time: 2.1 s    on Snapdragon 410
Total time:   3.6 s
@reown/appkit-scaffold-ui
Size limit:   220 kB
Size:         214.17 kB with all dependencies, minified and gzipped
Loading time: 4.2 s     on slow 3G
Running time: 3.9 s     on Snapdragon 410
Total time:   8.1 s
@reown/appkit-ui
Size limit:   500 kB
Size:         13.16 kB with all dependencies, minified and gzipped
Loading time: 258 ms   on slow 3G
Running time: 482 ms   on Snapdragon 410
Total time:   739 ms

@github-actions
Copy link
Copy Markdown
Contributor

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 78.46% 39721 / 50620
🔵 Statements 78.46% 39721 / 50620
🔵 Functions 76.27% 4254 / 5577
🔵 Branches 86.71% 9663 / 11144
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
packages/appkit/src/client/appkit-base-client.ts 72.74% 85.32% 76.69% 72.74% 184-190, 210, 223-226, 229, 241-242, 248-249, 252, 261, 308-309, 355-356, 394-395, 397-398, 403-404, 485-486, 522-528, 599-600, 622-637, 640, 674-675, 678, 719-723, 730-731, 734-735, 740-741, 752-775, 784-785, 802-822, 826-847, 850-876, 879-885, 888-894, 897-903, 906-912, 915-925, 928-934, 937-944, 958-967, 970-976, 979-980, 983-984, 1003-1004, 1027-1067, 1074-1086, 1092-1119, 1122-1132, 1164-1165, 1190-1191, 1196, 1211-1227, 1241, 1245-1253, 1271-1276, 1292-1293, 1312-1315, 1319-1320, 1322-1323, 1357-1359, 1363-1384, 1389-1390, 1398-1399, 1401-1402, 1496-1497, 1509-1510, 1515, 1538-1543, 1591, 1612-1613, 1622, 1624-1640, 1645, 1691-1692, 1704-1715, 1762-1779, 1824, 1830-1834, 1855-1870, 1873-1874, 1900-1903, 1939-1958, 1990, 2033-2034, 2040-2066, 2287-2288, 2325-2326, 2329-2330, 2346-2349, 2352-2353, 2373-2374, 2377-2378, 2399, 2420-2421, 2424-2434, 2438-2439, 2453, 2461, 2480-2481, 2487-2488, 2522-2527, 2545-2546, 2549-2550, 2597-2598, 2669-2670, 2673-2674, 2677-2680, 2683-2684, 2687-2688, 2691-2692, 2695-2696, 2699-2703, 2712-2721, 2730-2741, 1382, 2433
Generated in workflow #17053 for commit e177a26 by the Vitest Coverage Report Action

@Khizr97
Copy link
Copy Markdown

Khizr97 commented Apr 11, 2026

═══════════════════════════════════════════
SDET ANALYSIS REPORT
═══════════════════════════════════════════

🔬 SDET Report — appkit
<https://github.com/reown-com/appkit/pull/5639|PR #5639: fix: sync approved CAIP networks before connection status transition>
Repo: appkit | Author: tomiir
Merged: 11 Apr 2026 | Analyzed: 11 Apr 2026

📝 SUMMARY
This PR moves approved CAIP networks synchronization to occur before account sync and connection status transitions in WalletConnect flows. The changes introduce timing dependencies and state synchronization that need comprehensive testing.

🐛 BUG-PRONE PATTERNS
Found 4 patterns (1 high, 3 medium, 0 low)

🔴 [race-condition] packages/appkit/src/client/appkit-base-client.ts:1551
getApprovedCaipNetworksData() called twice in different execution paths - could lead to inconsistent state if data changes between calls
Suggested test: Mock getApprovedCaipNetworksData to return different values on successive calls and verify state consistency

🟠 [null-safety] packages/appkit/src/client/appkit-base-client.ts:1554
data.approvedCaipNetworkIds and data.supportsAllNetworks accessed without null checks after getApprovedCaipNetworksData()
Suggested test: Test with getApprovedCaipNetworksData returning null, undefined, or partial data structures

🟠 [state-mutation] packages/appkit/src/client/appkit-base-client.ts:1266
ChainController.setApprovedCaipNetworksData called in accountChanged handler - could overwrite user changes or create state conflicts
Suggested test: Verify that simultaneous approved network updates don't conflict with user-initiated network changes

🟠 [type-coercion] packages/appkit/src/client/appkit-base-client.ts:1269
connector.type compared with string constant without strict typing - could fail with undefined/null connector
Suggested test:

🧪 TEST SCENARIOS
🔴 [UNIT] accountChanged handler syncs approved networks for WalletConnect
File: packages/appkit/src/client/appkit-base-client.ts:1266
Input: connector with type WALLET_CONNECT, mock getApprovedCaipNetworksData() returning { approvedCaipNetworkIds: ['eip155:1', 'eip155:137'], supportsAllNetworks: false }
Expected: ChainController.setApprovedCaipNetworksData called with correct namespace and data before other sync operations

🔴 [UNIT] syncWalletConnectAccount syncs approved networks before syncAccount
File: packages/appkit/src/client/appkit-base-client.ts:1551
Input: sessionAddress = '0x123', mock getApprovedCaipNetworksData() returning test data
Expected: ChainController.setApprovedCaipNetworksData called before syncAccount, then syncAccount called with correct parameters

🔴 [INTEGRATION] WalletConnect connection has correct approved networks immediately on connected status
File: packages/appkit/src/client/appkit-base-client.ts:1551
Input: Complete WalletConnect connection flow with mocked session namespaces
Expected: Connection status transitions to connected with approvedCaipNetworkIds and supportsAllNetworks available in ChainController state

🟠 [UNIT] approved networks sync skipped when no sessionAddress
File: packages/appkit/src/client/appkit-base-client.ts:1551
Input: sessionAddress = undefined/null
Expected: ChainController.setApprovedCaipNetworksData not called, approved networks remain unchanged

🟠 [UNIT] non-WalletConnect connectors unaffected by approved networks sync
File: packages/appkit/src/client/appkit-base-client.ts:1266
Input: connector with type INJECTED or COINBASE_WALLET
Expected: ChainController.setApprovedCaipNetworksData not called in accountChanged handler

⚠️ COVERAGE GAPS
• packages/appkit/src/client/appkit-base-client.ts — no test file found, critical for wallet connection flows and state management

🔧 TECHNICAL EDGE CASES
• [race condition] packages/appkit/src/client/appkit-base-client.ts:1551
Concurrent calls to syncWalletConnectAccount could result in duplicate approved network sync calls
Test: Call syncWalletConnectAccount simultaneously from multiple contexts, verify ChainController.setApprovedCaipNetworksData called correct number of times

• [null reference] packages/appkit/src/client/appkit-base-client.ts:1266
connector parameter could be undefined in accountChanged handler when connection is unstable
Test: Call accountChanged handler with undefined connector and verify no null reference exceptions

• [error handling] packages/appkit/src/client/appkit-base-client.ts:1554
No error handling if getApprovedCaipNetworksData throws or ChainController.setApprovedCaipNetworksData fails
Test: Mock methods to throw errors and verify graceful degradation without breaking connection flow

• [boundary] packages/appkit/src/client/appkit-base-client.ts:1269
String comparison with UtilConstantsUtil.CONNECTOR_TYPE_WALLET_CONNECT might fail with case sensitivity or whitespace
Test: Test with connector.type having different casing, trailing spaces, or similar string variants

🎭 MOCKING NOTES
ChainController.setApprovedCaipNetworksData
Use vitest.fn() to mock and verify call order, parameters, and timing relative to other operations
getApprovedCaipNetworksData
Mock to return controlled test data and verify it's called at correct times in execution flow
UtilConstantsUtil.CONNECTOR_TYPE_WALLET_CONNECT
Mock constant to test different connector type scenarios and edge cases
syncAccount method
Mock to verify it's called after approved networks sync with correct timing and parameters

✅ TEST CHECKLIST
☐ Create appkit-base-client.test.ts with comprehensive test setup for WalletConnect flows
☐ Write unit test verifying approved networks sync occurs before syncAccount in syncWalletConnectAccount
☐ Add test for accountChanged handler only syncing approved networks for WalletConnect connectors
☐ Test edge case where getApprovedCaipNetworksData returns null/undefined data
☐ Create integration test for complete WalletConnect connection flow with network sync timing
☐ Add test verifying non-WalletConnect connectors don't trigger approved network sync
☐ Mock ChainController and verify call order and parameters in network sync operations
☐ Test concurrent syncWalletConnectAccount calls don't cause race conditions
☐ Verify error handling when approved network sync methods throw exceptions
☐ Add boundary tests for connector type string comparison edge cases


WalletConnect QA Agent

Copy link
Copy Markdown
Contributor

@enesozturk enesozturk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do this requires a unit test?

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.

4 participants