Skip to content

fix(chains): separate deleted-chain display fallback#221

Draft
tansawit wants to merge 11 commits intomainfrom
fix/deleted-chain-display-fallback
Draft

fix(chains): separate deleted-chain display fallback#221
tansawit wants to merge 11 commits intomainfrom
fix/deleted-chain-display-fallback

Conversation

@tansawit
Copy link
Copy Markdown
Contributor

@tansawit tansawit commented Apr 7, 2026

Summary

  • separate deleted-chain display fallbacks from active Initia registry lookups
  • introduce a display-only deleted-chain type so callers must narrow before accessing endpoint metadata
  • update OP withdrawal history surfaces to handle deleted chains without crashing

Context

Verification

  • pnpm --filter @initia/interwovenkit-react test
  • pnpm --filter @initia/interwovenkit-react typecheck

Note

Medium Risk
Touches chain-resolution and bridge exact-fee validation paths; mistakes could surface as missing links/withdrawal data or incorrect fee-check behavior, but changes are localized and covered by new unit tests.

Overview
Adds a distinct display-only deleted-chain fallback (ResolvedChain + isDeletedChain) and splits lookups into useFindChain (active registry only) vs useFindChainDisplay (profiles-based fallback).

Updates consumers to handle unavailable chains gracefully: ExplorerLink now renders non-clickable text for deleted/missing chains (and strips anchor-only attrs), and OP withdrawals surfaces show an informational message instead of throwing.

Bridge exact-fee checking is refactored to a shared shouldCheckExactFee helper and now uses useChainEnabled/resolveEnabledChainState to only fetch chain registry data when needed, with added tests for both the gating logic and enabled-query state handling.

Reviewed by Cursor Bugbot for commit 1a4217c. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • New Features

    • UI now uses a display-aware chain lookup so removed networks render a clear display-only fallback (logo/name) instead of failing.
    • Components gracefully handle conditional loading of chain info to avoid unexpected errors during fetches.
  • Bug Fixes

    • Claimable and Withdrawals views show an informative message when a chain is removed.
    • Explorer links render as non-clickable text for unavailable chains and omit link-only attributes to avoid broken or misleading links.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 7, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 72dc150f-bb35-4f26-8272-83ac15ba8e44

📥 Commits

Reviewing files that changed from the base of the PR and between dc0a412 and 1a4217c.

📒 Files selected for processing (2)
  • packages/interwovenkit-react/src/components/ExplorerLink.tsx
  • packages/interwovenkit-react/src/data/chains.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/interwovenkit-react/src/data/chains.ts
  • packages/interwovenkit-react/src/components/ExplorerLink.tsx

Walkthrough

Added a display-aware chain resolver returning either active registry chains or compact deleted-chain fallbacks, plus a type guard and enabled-state utilities. Updated UI components and ExplorerLink to use the new resolver and handle deleted-chain display/fallback cases.

Changes

Cohort / File(s) Summary
Chain Data Layer
packages/interwovenkit-react/src/data/chains.ts
Added DeletedChainFallback interface, ResolvedChain union, isDeletedChain() type guard, useFindChainDisplay() (registry-or-fallback), preserved useFindChain() (registry-only), and new enabled/loading helpers (useInitiaRegistryEnabled internal, resolveEnabledChainState, useChainEnabled).
Bridge UI Components
packages/interwovenkit-react/src/pages/bridge/op/ClaimableList.tsx, packages/interwovenkit-react/src/pages/bridge/op/Withdrawals.tsx
Replaced useFindChain() with useFindChainDisplay(). Withdrawals now detects deleted chains via isDeletedChain() and renders an informational FormHelp instead of header/withdrawal list when deleted; selection-prompt behavior unchanged.
Explorer Link
packages/interwovenkit-react/src/components/ExplorerLink.tsx
Switched to useFindChainDisplay() and isDeletedChain(); returns a non-link <span> fallback when lookup fails or chain is deleted, stripping anchor-only attributes before spreading. Builds and renders <a> only after successful chain resolution and URL construction. (EOF newline missing in file.)

Sequence Diagram(s)

sequenceDiagram
    participant UI as Component (Claimable/Withdrawals/ExplorerLink)
    participant Hook as useFindChainDisplay
    participant Registry as Active Registry
    participant Profiles as profiles.json (deleted-chain fallback)
    UI->>Hook: request chainId
    Hook->>Registry: lookup chainId
    alt found in registry
        Registry-->>Hook: NormalizedChain
    else not found
        Hook->>Profiles: lookup deleted-chain display info
        Profiles-->>Hook: DeletedChainFallback
    end
    Hook-->>UI: ResolvedChain (NormalizedChain | DeletedChainFallback)
    alt ResolvedChain is deleted
        UI-->>UI: render informational fallback / non-link span
    else ResolvedChain active
        UI->>UI: build explorer URL & render link/header/content
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 I found a chain that hopped away at night,
So I stitched a badge and kept its name polite.
Logos and names still softly gleam,
Even when registries end the stream.
The rabbit shows it gently — display done right.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: introducing a separated deleted-chain display fallback mechanism to handle deleted chains without crashing.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/deleted-chain-display-fallback
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch fix/deleted-chain-display-fallback

Comment @coderabbitai help to get the list of available commands and usage tips.

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages bot commented Apr 7, 2026

Deploying interwovenkit with  Cloudflare Pages  Cloudflare Pages

Latest commit: 1a4217c
Status: ✅  Deploy successful!
Preview URL: https://81fdda8c.interwovenkit.pages.dev
Branch Preview URL: https://fix-deleted-chain-display-fa.interwovenkit.pages.dev

View logs

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages bot commented Apr 7, 2026

Deploying interwovenkit-testnet with  Cloudflare Pages  Cloudflare Pages

Latest commit: 1a4217c
Status: ✅  Deploy successful!
Preview URL: https://17c7bf9c.interwovenkit-testnet.pages.dev
Branch Preview URL: https://fix-deleted-chain-display-fa.interwovenkit-testnet.pages.dev

View logs

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages bot commented Apr 7, 2026

Deploying interwovenkit-staging with  Cloudflare Pages  Cloudflare Pages

Latest commit: 1a4217c
Status: ✅  Deploy successful!
Preview URL: https://1d236fe2.interwovenkit-staging.pages.dev
Branch Preview URL: https://fix-deleted-chain-display-fa.interwovenkit-staging.pages.dev

View logs

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/interwovenkit-react/src/data/chains.ts (1)

149-152: Avoid duplicate registry lookups inside useFindChainDisplay.

This hook calls useInitiaRegistry() directly and indirectly again through useLayer1(). Prefer deriving layer1 from the local chains value to keep one source and reduce extra query subscriptions/suspense coupling.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/interwovenkit-react/src/data/chains.ts` around lines 149 - 152,
useFindChainDisplay currently calls useInitiaRegistry() as chains and also calls
useLayer1(), causing duplicate registry lookups; change it to derive layer1 from
the local chains value instead of calling useLayer1() so there’s a single source
of truth and no extra subscriptions. Locate the useFindChainDisplay function and
remove the direct call to useLayer1(), compute the layer1 value from the chains
variable returned by useInitiaRegistry() (or from the appropriate field on
chains), and update any subsequent logic that references layer1 to use this
derived value.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/interwovenkit-react/src/data/chains.ts`:
- Around line 157-160: The current useFindChainDisplay implementation throws
when a chainId is missing from both the active registry and the profiles array
(the block that does const profile = profiles.find(...); if (!profile) throw new
Error(...)), which causes render-time crashes in components like ClaimableList
and Withdrawals; change this behavior to return a safe fallback display object
instead of throwing (e.g., { chainId, name: `Unknown chain (${chainId})`,
shortName: 'Unknown', color: '#999', icon: 'unknown' } or similar minimal
display fields your UI expects) so renders can continue, and keep the existing
lookup logic for registry/profile but replace the throw with the fallback return
in useFindChainDisplay.

---

Nitpick comments:
In `@packages/interwovenkit-react/src/data/chains.ts`:
- Around line 149-152: useFindChainDisplay currently calls useInitiaRegistry()
as chains and also calls useLayer1(), causing duplicate registry lookups; change
it to derive layer1 from the local chains value instead of calling useLayer1()
so there’s a single source of truth and no extra subscriptions. Locate the
useFindChainDisplay function and remove the direct call to useLayer1(), compute
the layer1 value from the chains variable returned by useInitiaRegistry() (or
from the appropriate field on chains), and update any subsequent logic that
references layer1 to use this derived value.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4a76289e-fb03-4247-b2d2-0b157a074008

📥 Commits

Reviewing files that changed from the base of the PR and between 303ecf4 and 3a78280.

📒 Files selected for processing (3)
  • packages/interwovenkit-react/src/data/chains.ts
  • packages/interwovenkit-react/src/pages/bridge/op/ClaimableList.tsx
  • packages/interwovenkit-react/src/pages/bridge/op/Withdrawals.tsx

Comment thread packages/interwovenkit-react/src/data/chains.ts
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Removed fallback in useFindChain breaks OP withdrawal history items
    • ExplorerLink now resolves chains through useFindChainDisplay and falls back to a non-clickable span for deleted chains instead of throwing.

Create PR

Or push these changes by commenting:

@cursor push 6d29aed7a3
Preview (6d29aed7a3)
diff --git a/packages/interwovenkit-react/src/components/ExplorerLink.tsx b/packages/interwovenkit-react/src/components/ExplorerLink.tsx
--- a/packages/interwovenkit-react/src/components/ExplorerLink.tsx
+++ b/packages/interwovenkit-react/src/components/ExplorerLink.tsx
@@ -2,7 +2,7 @@
 import xss from "xss"
 import { IconExternalLink } from "@initia/icons-react"
 import { truncate } from "@initia/utils"
-import { useChain } from "@/data/chains"
+import { isDeletedChain, useFindChainDisplay } from "@/data/chains"
 import { buildExplorerUrl, sanitizeLink } from "./explorer"
 import styles from "./ExplorerLink.module.css"
 
@@ -19,9 +19,12 @@
 
 const ExplorerLink = ({ chainId, txHash, accountAddress, pathSuffix, ...props }: Props) => {
   const { showIcon, className, children, onClick, ...attrs } = props
-  const chain = useChain(chainId)
+  const findChain = useFindChainDisplay()
+  const chain = findChain(chainId)
 
-  const url = buildExplorerUrl(chain, { txHash, accountAddress, pathSuffix })
+  const url = isDeletedChain(chain)
+    ? undefined
+    : buildExplorerUrl(chain, { txHash, accountAddress, pathSuffix })
   const defaultText = txHash ? truncate(txHash) : accountAddress ? truncate(accountAddress) : ""
   const text = children ?? defaultText

You can send follow-ups to the cloud agent here.

Comment thread packages/interwovenkit-react/src/data/chains.ts
Base automatically changed from fix/exp-301-bridge-preview-chain-fix to main April 7, 2026 10:13
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/interwovenkit-react/src/components/ExplorerLink.tsx`:
- Around line 26-30: The fallback renderer renderFallback currently spreads
attrs (AnchorHTMLAttributes<HTMLAnchorElement>) onto a <span>, which can add
anchor-only props; instead, restrict what is passed to the span by creating a
safeAttrs object (or destructuring) that only includes valid
span/ARIA/interaction props (e.g., id, className handled separately, style,
role, tabIndex, onClick, and any aria-* props) and exclude anchor-only keys like
target, rel, download, ping, referrerPolicy, hreflang, media, type; update
renderFallback to spread safeAttrs rather than attrs and keep anchor-specific
attrs for the anchor-rendering path (use the same pattern around the anchor
rendering code to use the full attrs when rendering <a>).
🪄 Autofix (Beta)

✅ Autofix completed


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0fd96329-8581-47fc-a530-005823921975

📥 Commits

Reviewing files that changed from the base of the PR and between 3a78280 and 51a8ec7.

📒 Files selected for processing (1)
  • packages/interwovenkit-react/src/components/ExplorerLink.tsx

Comment thread packages/interwovenkit-react/src/components/ExplorerLink.tsx
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 7, 2026

Note

Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it.

Fixes Applied Successfully

Fixed 1 file(s) based on 1 unresolved review comment.

Files modified:

  • packages/interwovenkit-react/src/components/ExplorerLink.tsx

Commit: dc0a412cf6810b6c9b686152b9d8bd52e80aee56

The changes have been pushed to the fix/deleted-chain-display-fallback branch.

Time taken: 3m 55s

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

Bugbot Autofix prepared fixes for both issues found in the latest run.

  • ✅ Fixed: Error wrapping discards original value in state resolver
    • Updated both non-Error fallbacks in resolveEnabledChainState to include String(error) in the wrapped message.
  • ✅ Fixed: Query fires before chain dependency is available
    • Added !!chain to the fee-check query enabled condition so it waits for the chain dependency before executing.

Create PR

Or push these changes by commenting:

@cursor push 7813e03f34
Preview (7813e03f34)
diff --git a/packages/interwovenkit-react/src/data/chains.ts b/packages/interwovenkit-react/src/data/chains.ts
--- a/packages/interwovenkit-react/src/data/chains.ts
+++ b/packages/interwovenkit-react/src/data/chains.ts
@@ -74,7 +74,8 @@
   if (error && !chains) {
     return {
       chain: undefined,
-      error: error instanceof Error ? error : new Error("Failed to load chains"),
+      error:
+        error instanceof Error ? error : new Error(`Failed to load chains: ${String(error)}`),
       isLoading: false,
     }
   }
@@ -86,7 +87,8 @@
   if (error) {
     return {
       chain: undefined,
-      error: error instanceof Error ? error : new Error("Failed to load chains"),
+      error:
+        error instanceof Error ? error : new Error(`Failed to load chains: ${String(error)}`),
       isLoading: false,
     }
   }

diff --git a/packages/interwovenkit-react/src/pages/bridge/FooterWithExactFeeCheck.tsx b/packages/interwovenkit-react/src/pages/bridge/FooterWithExactFeeCheck.tsx
--- a/packages/interwovenkit-react/src/pages/bridge/FooterWithExactFeeCheck.tsx
+++ b/packages/interwovenkit-react/src/pages/bridge/FooterWithExactFeeCheck.tsx
@@ -115,7 +115,7 @@
         throw await normalizeError(error)
       }
     },
-    enabled: requiresExactFeeCheck && balances !== undefined,
+    enabled: requiresExactFeeCheck && !!chain && balances !== undefined,
     retry: false,
   })

You can send follow-ups to the cloud agent here.

Reviewed by Cursor Bugbot for commit 51a8ec7. Configure here.

Comment thread packages/interwovenkit-react/src/data/chains.ts Outdated
})
}

if (isLoadingBalances || balances === undefined || isLoading) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Query fires before chain dependency is available

Low Severity

The enabled condition on the fee-check query is requiresExactFeeCheck && balances !== undefined but omits !!chain. When requiresExactFeeCheck is true and balances are loaded but chain is still loading from useChainEnabled, the query fires immediately and the queryFn guard throws "Invalid transaction data". This error gets cached in React Query under a throwaway key. It's not user-visible because isLoadingChain takes render priority, but it's a needless failed query execution that could confuse debugging and is fragile if the render order changes later.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 51a8ec7. Configure here.

coderabbitai bot and others added 2 commits April 7, 2026 11:16
Fixed 1 file(s) based on 1 unresolved review comment.

Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
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