feat(tron): re-enable WalletConnect adapter#780
Conversation
Register WalletConnectAdapter via resolveTronWalletConnectConfig, which forces a 'tron' storage prefix to isolate the session from the EVM connector — without it eip155 namespaces leak in and wallets connect as EVM.
🦋 Changeset detectedLatest commit: d395ad0 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
E2E Examples — all passedAll examples passed in the latest run. |
E2E Playground resultsDetails
📥 Download full HTML report (open the run → Artifacts → |
|
📦 Preview published under the Install the exact version(s) — npm i @lifi/widget-provider-tron@0.0.0-preview-6cc63bac
npm i @lifi/widget@0.0.0-preview-6cc63bac |
🔍 QA Review — EMB-435Ticket: EMB-435 — Investigate WalletConnect modal closing immediately in Widget v4 What this PR doesThis PR re-enables the Tron WalletConnect adapter that was previously stubbed out in Re-review — item resolution
Code verification summary
options: {
projectId: defaultProjectId,
...config?.options,
// Forced last: a distinct prefix keeps the EVM connector's eip155
// namespaces (shared project id) out of the Tron session proposal.
customStoragePrefix: 'tron', // ← H-1 FIXED: after spread, cannot be overridden
},network: `${network.charAt(0).toUpperCase()}${network.slice(1)}`, // ← H-2 FIXED: always normalisedBoth fixes are confirmed in the current HEAD. Changeset
Minor residual note: The changeset still says "The resolver always forces Acceptance Criteria — final assessment
✅ Verdict: PassAll critical and high items are resolved. The Tron WalletConnect re-enablement is technically sound:
The open items (M-1 unit test infrastructure, M-2 public docs) are tracked and accepted with appropriate justifications consistent with the codebase's current conventions. 🤖 Automated QA review by lifi-qa-agent. Powered by Claude. |
There was a problem hiding this comment.
Requesting changes on 6 items — each requires either a code fix or an explicit acceptance comment with justification before this review is considered complete.
| # | Severity | Type | Issue / File |
|---|---|---|---|
| 1 | 🔴 Critical | Scope gap | EVM WalletConnect flash-and-close not addressed — packages/wallet-management/src/utils/elements.ts and EthereumListItemButton.tsx |
| 2 | 🔴 High | Code | customStoragePrefix overridable vs. changeset claim of "always forces" — packages/widget-provider-tron/src/config/walletConnect.ts |
| 3 | 🔴 High | Code | network input not normalised — lowercase values produce invalid CAIP ID — packages/widget-provider-tron/src/config/walletConnect.ts |
| 4 | 🟠 Medium | Test gap | packages/widget-provider-tron/src/config/walletConnect.test.ts (new) |
| 5 | 🟠 Medium | Documentation | Public docs not updated for TronProviderConfig.walletConnect new API surface |
| 6 | 🟠 Medium | Code | createTronAdapters signature change not noted in changeset for direct callers |
1. [Critical] EVM WalletConnect flash-and-close not addressed
The partner's original complaint (WalletConnect modal flashes open and closes when clicking WalletConnect in the widget) is caused by createWalletConnectElement() in EthereumListItemButton.tsx injecting a <w3m-modal> element into the widget's MUI dialog. AppKit adopts this stale element instead of mounting its own on document.body, and AppKit's ModalController transitions it back to open: false immediately. Thomas Faber's analysis in the Linear comments identifies exactly this mechanism and proposes dropping the injection. As verified on main today, packages/wallet-management/src/utils/elements.ts and EthereumListItemButton.tsx still contain this code unchanged. This PR only fixes the Tron WC session-bleed issue. After this PR merges, EVM WalletConnect will still flash and close for the partner. Either include Thomas Faber's fix here, or open a separate linked PR before the ticket is closed.
2. [High] customStoragePrefix overridable — changeset says "always forces"
In resolveTronWalletConnectConfig:
options: {
projectId: defaultProjectId,
customStoragePrefix: 'tron',
...config?.options, // ← caller can override customStoragePrefix
},The changeset states the resolver "always forces options.customStoragePrefix to 'tron'" but because ...config?.options is spread after, any caller passing config.options.customStoragePrefix silently overrides it, re-introducing the namespace bleed. Decide: (a) if override is intentional, update the changeset/comment to say "defaults to 'tron'" and add a JSDoc warning; (b) if it must be forced, move customStoragePrefix: 'tron' after ...config?.options.
3. [High] network input not normalised
network: config?.network ?? 'Mainnet',Only applies 'Mainnet' when the field is absent. A caller passing { network: 'mainnet' } (lowercase) gets an invalid CAIP chain ID at the adapter level — exactly the bug the defaultWidgetConfig.ts fix in this PR corrects for the playground. Normalise the value (.replace(/^\w/, c => c.toUpperCase())) or validate and throw/warn, so new integrators don't hit this silently.
4. [Medium] Test gap — walletConnect.test.ts (new)
- Missing:
walletConnect: undefined/false→ returnsundefined - Missing:
walletConnect: true→{ network: 'Mainnet', options: { customStoragePrefix: 'tron', projectId: '...' } } - Missing: explicit
networkvalue preserved (e.g.'Shasta') - Missing:
options.customStoragePrefixoverride behaviour (clarifies H-2 intent) - Missing: caller
projectIdoverrides default
5. [Medium] Public docs not updated
TronProviderConfig.walletConnect (WalletConnectAdapterConfig | boolean) is a new public API. The PR checklist item for public-docs is explicitly unchecked. At minimum document: what true means, what a config object can contain, and the network capitalisation requirement.
6. [Medium] createTronAdapters signature change not noted in changeset
createTronAdapters is a public export. Its signature changed from () => Adapter[] to (walletConnect?: WalletConnectAdapterConfig) => Adapter[]. The changeset focuses on TronProviderConfig.walletConnect but doesn't mention that direct callers of createTronAdapters must pass the new parameter to get WalletConnect support. Add a note for direct callers.
💡 Once you've addressed the items above, re-apply the "Agent Review Request" label to trigger an automated re-review.
🔴 C-1 — Out of scope, and the EVM issue is already resolvedThis is built on Thomas Faber's 2026-06-09 hypothesis (the
So the EVM flash-and-close was an integrator-side missing-dependency issue, not a widget bug, and 🔴 H-1 — FixedGood catch on the spread order. 🔴 H-2 — Fixed
🟠 M-1 — Won't add (consistency)None of the 🟠 M-3 — DoneChangeset now notes that 🟠 M-2 — AcknowledgedPublic-docs update for 🟢 L-1 — Leaving as-isThe default |
There was a problem hiding this comment.
Could you revert these lockfile changes if they are unrelated?
| return { | ||
| ...config, | ||
| // Lowercase yields an invalid `tron:<name>` CAIP id upstream. | ||
| network: `${network.charAt(0).toUpperCase()}${network.slice(1)}`, |
There was a problem hiding this comment.
How do you think, is there a way we could prevent users from passing a network name with the wrong casing?
I mean without capitalizing the first letter on our side. Maybe with some constant/enum?
I am thinking there is still a possibility they would pass 'MAINNET' - and then it would be invalid as well.
- match network names case-insensitively, snap to canonical ChainNetwork value - add resolveTronWalletConnectConfig tests - revert unrelated lockfile dev-tooling bumps
|
e2e tested the flow with wallet connect on both evm and tron and it works! There are a couple of findings I had and I don't know if you can do anything about it @tomiiide. Finding 1 — Tron and EVM resolve to the same address
Result:Same wallet address is used for EVM and TRON Root cause:the wrapper's address extractor doesn't filter by namespace. In const accounts = Object.values(session.namespaces).flatMap(ns => ns.accounts);
const account = accounts[0]; // first account from ANY namespace
const address = account.split(':')[2]; // "eip155:1:0x95.." -> "0x95.."It takes
Finding 2 — a previously-connected WC wallet disappears after a while; refresh re-opens the QRRepro: connect both an EVM and a Tron wallet via WalletConnect, use the widget for a few minutes. One of the two wallets vanishes from the connected list; on refresh, its QR pops up again. Root cause: the two WalletConnect cores silently share one storage namespace. The branch's "storage isolation" (
Why refresh → QROn reload each adapter rehydrates from storage and auto-connects; the Tron adapter does Why it also disappears live, no refresh (same root cause; exact trigger less pinned)Once the victim core loses its backing state (symkey/subscription), its still-live session is torn down and it emits Notes
Fix (in our control, doesn't need the third-party wrapper)Since the Tron wrapper drops the prefix, isolate the EVM side instead — set Confirm at runtimeDevTools → Application → IndexedDB ( |

Which Linear task is linked to this PR?
https://linear.app/lifi-linear/issue/EMB-435/investigate-walletconnect-modal-closing-immediately-in-widget-v4
Why was it implemented this way?
WalletConnect was previously stubbed out in the Tron provider (createTronAdapters() registered no WC adapter) because of a "No accounts found in session" error: the upstream @tronweb3/tronwallet-adapters WalletConnect adapter uses the same WalletConnect Cloud project id and origin as the EVM provider, so the EVM connector's persisted eip155 namespaces bled into the Tron session proposal and wallets connected as EVM.
This re-enables it by registering WalletConnectAdapter through a new resolveTronWalletConnectConfig helper
(packages/widget-provider-tron/src/config/walletConnect.ts) that:
for the session-bleed bug. Integrators can still override it via options.
is disabled.
Limitation
From my tests, only two wallets work over wallet connect.
Other wallets confirmed in these issues:
tronweb3/tronwallet-adapter#3
tronweb3/tronwallet-adapter#37
tronweb3/tronwallet-adapter#82 (comment)
I confirmed this by patching the wallet connect library to log the connection details
Connection logs from Token pocket
Connection logs from metamask over wallet connect
Metamask only sends EVM connections over walletconnect.

Visual showcase (Screenshots or Videos)
Checklist before requesting a review