Skip to content

fix: resolve chainId race condition in preset flow#2436

Closed
kronosapiens wants to merge 1 commit intomainfrom
kronosapiens/debug-v0.13.9-regression
Closed

fix: resolve chainId race condition in preset flow#2436
kronosapiens wants to merge 1 commit intomainfrom
kronosapiens/debug-v0.13.9-regression

Conversation

@kronosapiens
Copy link
Contributor

@kronosapiens kronosapiens commented Feb 23, 2026

Problem

Users upgrading from v0.13.4 to v0.13.9 with preset-based configurations experience an indefinite loading screen — authentication and session registration are non-functional.

Root cause: v0.13.9 introduced isPoliciesResolved as a UI gate in app.tsx. For preset users, resolvePolicies returns isPoliciesResolved: false when either isConfigLoading is true or chainId is undefined. The chainId in the keychain is derived asynchronously (via RPC call), creating a race condition where the UI blocks on a value that hasn't resolved yet.

A secondary issue compounds this: the disconnect useEffect compares RPC URL strings (controller.rpcUrl() === urlRpcUrl). URL normalization differences (encoding, trailing slashes, different providers for the same chain) cause false-positive mismatches, triggering unnecessary disconnect loops that prevent recovery.

Fix

1. Pass chain_id as a URL parameter from all providers to the keychain.
The controller already knows the chainId synchronously at construction time. This passes it through the URL to the keychain iframe (and session/telegram/node redirect URLs), eliminating the need for an async RPC derivation on initial load.

2. Initialize chainId synchronously from the URL param in useConnectionValue.
The useState initializer reads chain_id from window.location.search, so chainId is immediately available when resolvePolicies runs — no more race condition.

3. Replace RPC URL string comparison with chain ID comparison in disconnect logic.
Comparing controller.chainId() === chainId instead of controller.rpcUrl() === urlRpcUrl avoids false-positive disconnects from URL normalization differences. Two different RPC endpoints for the same chain no longer trigger a disconnect.

Files changed

  • packages/controller/src/iframe/keychain.ts — Accept and forward chainId option as URL param
  • packages/controller/src/controller.ts — Pass selectedChain to KeychainIFrame
  • packages/controller/src/session/provider.ts — Add chain_id to session redirect URL
  • packages/controller/src/telegram/provider.ts — Add chain_id to telegram redirect URL
  • packages/controller/src/node/provider.ts — Add chain_id to node redirect URL
  • packages/keychain/src/hooks/connection.ts — Sync chainId init + chain ID disconnect comparison
  • packages/keychain/src/hooks/connection.test.ts — Updated disconnect tests for chain ID logic

Pass chain_id as URL parameter from all providers (controller, session, telegram, node) to the keychain iframe. Initialize chainId synchronously from the URL param to eliminate the race condition where isPoliciesResolved gates UI rendering on asynchronously-derived chainId.

Replace RPC URL string comparison with semantic chain ID comparison in disconnect logic to avoid false-positive disconnects from URL normalization differences (e.g., different RPC endpoints for same chain).

Fixes v0.13.9 regression where users upgrading with presets experience indefinite loading screen.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@vercel
Copy link

vercel bot commented Feb 23, 2026

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

Project Deployment Actions Updated (UTC)
controller-example-next Ready Ready Preview Feb 23, 2026 3:45pm
keychain Ready Ready Preview Feb 23, 2026 3:45pm
keychain-storybook Ready Ready Preview Feb 23, 2026 3:45pm

Request Review

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