Skip to content

feat: add etherlink#487

Open
antoncoding wants to merge 2 commits intomasterfrom
feat/etherlink
Open

feat: add etherlink#487
antoncoding wants to merge 2 commits intomasterfrom
feat/etherlink

Conversation

@antoncoding
Copy link
Copy Markdown
Owner

@antoncoding antoncoding commented Apr 1, 2026

Summary by CodeRabbit

  • New Features

    • Full Etherlink support across the app: network, RPC config, clients, tokens, allocator and Morpho integrations
    • Added Etherlink token support: USDC, WETH, WBTC, WXTZ, xU3O8, mBASIS, mMEV, mTBILL
    • New .env example entry for an Etherlink public RPC
  • Improvements

    • Safer Morpho app-link handling (conditional external links)
    • Chart/UI color and volume display updated for Etherlink
    • Updated Morpho addresses and genesis date for Etherlink

@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Apr 1, 2026

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

Project Deployment Actions Updated (UTC)
monarch Ready Ready Preview, Comment Apr 2, 2026 11:12am

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 1, 2026

📝 Walkthrough

Walkthrough

Adds Etherlink (chain ID 42793) across the app: env var, network enum/config, RPC clients, Wagmi/AppKit adapters, token/address mappings, Morpho integrations, and UI conditional rendering for Morpho links.

Changes

Cohort / File(s) Summary
Environment & Network Config
\.env\.local\.example, src/utils/networks.ts
Added NEXT_PUBLIC_ETHERLINK_RPC, declared SupportedNetworks.Etherlink, included Etherlink in ALL_SUPPORTED_NETWORKS, and added a NetworkConfig entry (RPC, explorer, tokens, timing).
Client / Adapter Setup
src/config/appkit.ts, src/store/createWagmiConfig.ts, src/utils/rpc.ts
Imported etherlink, created customEtherlink for AppKit, added etherlink to wagmi chains and transports, and pre-initialized a public client for Etherlink.
Token & Address Maps
src/utils/tokens.ts, src/types/token.ts, src/constants/public-allocator.ts
Added Etherlink network addresses for USDC/WETH/WBTC, new Etherlink tokens (WXTZ, mBASIS, xU3O8, mMEV, mTBILL), WETH mapping, and allocator address.
Morpho & External URLs
src/utils/morpho.ts, src/utils/external.ts
Added Etherlink Morpho addresses, bundler, IRM mapping, genesis date; exported getMorphoNetworkSlug, added supportsMorphoAppLinks, and made market/vault URL helpers fall back to base app when slug is undefined.
UI Conditional Rendering
src/features/autovault/components/vault-identity.tsx, src/features/market-detail/components/market-header.tsx
Gate Morpho app links behind supportsMorphoAppLinks(chainId) so links/menu items are omitted for unsupported networks.
UI Styling / Charts
src/features/admin-v2/components/chain-volume-chart.tsx
Added color index mapping for chain ID 42793 (Etherlink) so charts and legends include Etherlink color.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~23 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.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 'feat: add etherlink' clearly and concisely describes the main change—adding support for the Etherlink chain across the codebase.

✏️ 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 feat/etherlink

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai bot added the feature request Specific feature ready to be implemented label Apr 1, 2026
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: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/features/autovault/components/vault-identity.tsx (1)

151-153: ⚠️ Potential issue | 🟡 Minor

Tooltip link not gated by canLinkToMorpho.

Main content correctly skips the link when Morpho app links aren't supported, but the tooltip's actionHref (line 152) still points to vaultHref unconditionally. For Etherlink, this would show a broken external link in the tooltip.

Proposed fix
           actionIcon={<ExternalLinkIcon className="h-4 w-4" />}
-          actionHref={vaultHref}
+          actionHref={canLinkToMorpho ? vaultHref : undefined}
           onActionClick={(e) => e.stopPropagation()}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/features/autovault/components/vault-identity.tsx` around lines 151 - 153,
The tooltip's actionHref is not gated by the canLinkToMorpho check and still
points to vaultHref, producing a broken external link for Etherlink; update the
tooltip props so actionHref is only set when canLinkToMorpho is true (e.g.,
actionHref={canLinkToMorpho ? vaultHref : undefined}) and ensure any click
handler like onActionClick remains consistent with that gating so the tooltip
shows no external link when linking to Morpho isn't supported.
🧹 Nitpick comments (1)
src/utils/tokens.ts (1)

289-294: WXTZ token missing image.

Consider adding an image for UI consistency, or document that img: undefined is intentional.

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

In `@src/utils/tokens.ts` around lines 289 - 294, The WXTZ token entry in
tokens.ts sets img: undefined which breaks UI consistency; update the token
object for symbol 'WXTZ' by either supplying a valid image path/URL (e.g., point
to the project's token asset or CDN) or explicitly set img to a named
placeholder constant (e.g., TOKEN_PLACEHOLDER) and ensure that constant is
imported/defined for the UI to use; alternatively, if undefined is intentional,
add a short inline comment on the WXTZ object explaining why img is undefined so
maintainers know it's deliberate.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/utils/external.ts`:
- Around line 27-31: Tooltip currently always passes vaultHref into
TooltipContent.actionHref causing an actionable link even when the chain doesn't
support Morpho; update the call site to pass actionHref only when
canLinkToMorpho is true (e.g., actionHref={canLinkToMorpho ? vaultHref :
undefined}) or alternatively remove actionIcon when canLinkToMorpho is false so
TooltipContent won't render the link; locate the TooltipContent usage that
supplies actionHref/actionIcon (where vaultHref is derived from getVaultURL) and
apply the conditional so unsupported chains do not show the link.

In `@src/utils/tokens.ts`:
- Around line 368-373: There are two duplicate token entries for symbol 'xU3O8'
with the same address; remove the incomplete entry (the one missing img and
protocol that appears in the block with symbol: 'xU3O8', img: undefined,
decimals: 18, networks: [...]) so only the complete entry (the one that includes
img and protocol: { name: 'Midas' }) remains; this ensures functions like
findToken()/useTokenPrices.ts (which use Array.find) and statsService.ts (which
reduces/iterates tokens) see the same consistent metadata for 'xU3O8'.

---

Outside diff comments:
In `@src/features/autovault/components/vault-identity.tsx`:
- Around line 151-153: The tooltip's actionHref is not gated by the
canLinkToMorpho check and still points to vaultHref, producing a broken external
link for Etherlink; update the tooltip props so actionHref is only set when
canLinkToMorpho is true (e.g., actionHref={canLinkToMorpho ? vaultHref :
undefined}) and ensure any click handler like onActionClick remains consistent
with that gating so the tooltip shows no external link when linking to Morpho
isn't supported.

---

Nitpick comments:
In `@src/utils/tokens.ts`:
- Around line 289-294: The WXTZ token entry in tokens.ts sets img: undefined
which breaks UI consistency; update the token object for symbol 'WXTZ' by either
supplying a valid image path/URL (e.g., point to the project's token asset or
CDN) or explicitly set img to a named placeholder constant (e.g.,
TOKEN_PLACEHOLDER) and ensure that constant is imported/defined for the UI to
use; alternatively, if undefined is intentional, add a short inline comment on
the WXTZ object explaining why img is undefined so maintainers know it's
deliberate.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 4d594dd1-9835-41d1-94eb-0c344b33af44

📥 Commits

Reviewing files that changed from the base of the PR and between b1360b4 and e417d0c.

⛔ Files ignored due to path filters (5)
  • src/imgs/chains/etherlink.svg is excluded by !**/*.svg
  • src/imgs/tokens/mbasis.png is excluded by !**/*.png
  • src/imgs/tokens/mmev.svg is excluded by !**/*.svg
  • src/imgs/tokens/mtbill.png is excluded by !**/*.png
  • src/imgs/tokens/xu3o8.png is excluded by !**/*.png
📒 Files selected for processing (13)
  • .env.local.example
  • src/config/appkit.ts
  • src/constants/public-allocator.ts
  • src/features/admin-v2/components/chain-volume-chart.tsx
  • src/features/autovault/components/vault-identity.tsx
  • src/features/market-detail/components/market-header.tsx
  • src/store/createWagmiConfig.ts
  • src/types/token.ts
  • src/utils/external.ts
  • src/utils/morpho.ts
  • src/utils/networks.ts
  • src/utils/rpc.ts
  • src/utils/tokens.ts

Comment on lines +368 to +373
{
symbol: 'xU3O8',
img: undefined,
decimals: 18,
networks: [{ chain: etherlink, address: '0x79052Ab3C166D4899a1e0DD033aC3b379AF0B1fD' }],
},
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Duplicate xU3O8 entries with conflicting metadata.

Two entries for xU3O8 at the same address (case-insensitive match):

  • Lines 368-373: no img, no protocol
  • Lines 421-429: has img and protocol: { name: 'Midas' }

This causes inconsistent behavior:

  • findToken() / useTokenPrices.ts uses find() → returns first entry (no image)
  • statsService.ts iterates all → last entry wins in map

Remove the first entry (lines 368-373) since the second is more complete.

🐛 Fix: Remove duplicate entry
-  {
-    symbol: 'xU3O8',
-    img: undefined,
-    decimals: 18,
-    networks: [{ chain: etherlink, address: '0x79052Ab3C166D4899a1e0DD033aC3b379AF0B1fD' }],
-  },

Also applies to: 421-429

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

In `@src/utils/tokens.ts` around lines 368 - 373, There are two duplicate token
entries for symbol 'xU3O8' with the same address; remove the incomplete entry
(the one missing img and protocol that appears in the block with symbol:
'xU3O8', img: undefined, decimals: 18, networks: [...]) so only the complete
entry (the one that includes img and protocol: { name: 'Midas' }) remains; this
ensures functions like findToken()/useTokenPrices.ts (which use Array.find) and
statsService.ts (which reduces/iterates tokens) see the same consistent metadata
for 'xU3O8'.

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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/utils/external.ts (1)

45-66: ⚠️ Potential issue | 🟡 Minor

Add Etherlink case to getChainNameForMerkl or create a guard for unsupported chains.

Etherlink is a supported network but falls through to the default 'ethereum' case, generating incorrect Merkl URLs. Either:

  1. Add Etherlink mapping if Merkl supports it (with correct slug)
  2. Add a guard like supportsMorphoAppLinks (already used at line 11 of this file) to prevent unsupported chains from reaching this function
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utils/external.ts` around lines 45 - 66, The getChainNameForMerkl
function returns incorrect defaults for Etherlink; either add a specific case
for SupportedNetworks.Etherlink with the correct Merkl slug inside
getChainNameForMerkl, or ensure callers check supportsMorphoAppLinks (the
existing guard used earlier in this file) before calling getChainNameForMerkl so
unsupported chains never hit the switch. Update the switch in
getChainNameForMerkl to include SupportedNetworks.Etherlink => '<correct-slug>'
if Merkl supports it, otherwise add/ensure a pre-check using
supportsMorphoAppLinks to short-circuit and avoid using this function for
unsupported chains.
♻️ Duplicate comments (1)
src/utils/external.ts (1)

21-31: ⚠️ Potential issue | 🟡 Minor

Fallback URL returns generic Morpho homepage.

When network is undefined, these functions return https://app.morpho.org which shows the homepage rather than anything useful. Consider returning an empty string or having callers use supportsMorphoAppLinks() to avoid calling these functions for unsupported chains.

The relevant code snippet shows vault-identity.tsx correctly guards the Link component with canLinkToMorpho, but still passes vaultHref to the tooltip's actionHref. This could render a useless link in the tooltip for Etherlink.

Suggested approach

Either:

  1. Return empty string from these functions when network is undefined, or
  2. Ensure all callers check supportsMorphoAppLinks() before using the URL (including tooltip props)

The second approach is cleaner - callers already have the guard function available.

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

In `@src/utils/external.ts` around lines 21 - 31, The getMarketURL and getVaultURL
functions currently return the generic Morpho homepage when
getMorphoNetworkSlug(chainId) is falsy; change behavior to avoid returning a
misleading homepage by either (A) returning an empty string from getMarketURL
and getVaultURL when network is undefined, or (B) (preferred) ensure all callers
use supportsMorphoAppLinks()/canLinkToMorpho before passing URLs — update
callers like vault-identity.tsx to guard the tooltip's actionHref (e.g.,
vaultHref) so actionHref is only set when supportsMorphoAppLinks() is true; pick
one approach and apply it consistently for both getMarketURL and getVaultURL and
all their call sites.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@src/utils/external.ts`:
- Around line 45-66: The getChainNameForMerkl function returns incorrect
defaults for Etherlink; either add a specific case for
SupportedNetworks.Etherlink with the correct Merkl slug inside
getChainNameForMerkl, or ensure callers check supportsMorphoAppLinks (the
existing guard used earlier in this file) before calling getChainNameForMerkl so
unsupported chains never hit the switch. Update the switch in
getChainNameForMerkl to include SupportedNetworks.Etherlink => '<correct-slug>'
if Merkl supports it, otherwise add/ensure a pre-check using
supportsMorphoAppLinks to short-circuit and avoid using this function for
unsupported chains.

---

Duplicate comments:
In `@src/utils/external.ts`:
- Around line 21-31: The getMarketURL and getVaultURL functions currently return
the generic Morpho homepage when getMorphoNetworkSlug(chainId) is falsy; change
behavior to avoid returning a misleading homepage by either (A) returning an
empty string from getMarketURL and getVaultURL when network is undefined, or (B)
(preferred) ensure all callers use supportsMorphoAppLinks()/canLinkToMorpho
before passing URLs — update callers like vault-identity.tsx to guard the
tooltip's actionHref (e.g., vaultHref) so actionHref is only set when
supportsMorphoAppLinks() is true; pick one approach and apply it consistently
for both getMarketURL and getVaultURL and all their call sites.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 9c5dcbd6-101f-46c9-8092-2242aafed0f2

📥 Commits

Reviewing files that changed from the base of the PR and between e417d0c and 4081260.

⛔ Files ignored due to path filters (5)
  • src/imgs/chains/etherlink.svg is excluded by !**/*.svg
  • src/imgs/tokens/mbasis.png is excluded by !**/*.png
  • src/imgs/tokens/mmev.svg is excluded by !**/*.svg
  • src/imgs/tokens/mtbill.png is excluded by !**/*.png
  • src/imgs/tokens/xu3o8.png is excluded by !**/*.png
📒 Files selected for processing (13)
  • .env.local.example
  • src/config/appkit.ts
  • src/constants/public-allocator.ts
  • src/features/admin-v2/components/chain-volume-chart.tsx
  • src/features/autovault/components/vault-identity.tsx
  • src/features/market-detail/components/market-header.tsx
  • src/store/createWagmiConfig.ts
  • src/types/token.ts
  • src/utils/external.ts
  • src/utils/morpho.ts
  • src/utils/networks.ts
  • src/utils/rpc.ts
  • src/utils/tokens.ts
✅ Files skipped from review due to trivial changes (5)
  • src/constants/public-allocator.ts
  • src/features/admin-v2/components/chain-volume-chart.tsx
  • src/types/token.ts
  • src/features/market-detail/components/market-header.tsx
  • src/utils/morpho.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/store/createWagmiConfig.ts
  • src/utils/rpc.ts
  • src/features/autovault/components/vault-identity.tsx
  • src/utils/tokens.ts

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/utils/external.ts (1)

45-66: ⚠️ Potential issue | 🟡 Minor

Add Etherlink to the Merkl chain mapping.

Merkl supports Etherlink and is actively used for the Apple Farm incentive program there. Add a case for Etherlink (likely SupportedNetworks.Etherlink returning 'etherlink') so requests don't incorrectly fall through to the 'ethereum' default.

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

In `@src/utils/external.ts` around lines 45 - 66, The getChainNameForMerkl
function is missing a branch for SupportedNetworks.Etherlink, causing Etherlink
requests to fall through to the default 'ethereum'; update getChainNameForMerkl
to add a case for SupportedNetworks.Etherlink that returns 'etherlink' so
Etherlink is mapped correctly (modify the switch in getChainNameForMerkl to
include case SupportedNetworks.Etherlink: return 'etherlink';).
♻️ Duplicate comments (1)
src/features/autovault/components/vault-identity.tsx (1)

151-153: ⚠️ Potential issue | 🟡 Minor

Tooltip link still shows for unsupported chains.

actionHref={vaultHref} is passed unconditionally to TooltipContent. For Etherlink, this results in a link to the generic https://app.morpho.org which isn't useful.

Fix: conditionally pass actionHref
           actionIcon={<ExternalLinkIcon className="h-4 w-4" />}
-          actionHref={vaultHref}
+          actionHref={canLinkToMorpho ? vaultHref : undefined}
           onActionClick={(e) => e.stopPropagation()}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/features/autovault/components/vault-identity.tsx` around lines 151 - 153,
The tooltip link is always shown because actionHref is passed unconditionally;
change the JSX so TooltipContent (or the component receiving actionHref in
vault-identity.tsx) only receives actionHref when the chain is supported—e.g.
replace actionHref={vaultHref} with a conditional prop (pass undefined or omit
the prop when the chain is unsupported), using the existing vaultHref and the
chain-support boolean you have in scope so onActionClick and actionIcon remain
unchanged.
🧹 Nitpick comments (1)
src/utils/tokens.ts (1)

289-294: Missing image for WXTZ.

WXTZ (wrapped native XTZ on Etherlink) has img: undefined. Consider adding an image for UI consistency with other wrapped native tokens.

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

In `@src/utils/tokens.ts` around lines 289 - 294, The token entry for symbol
'WXTZ' has img: undefined; update the WXTZ object in the tokens list to provide
an image reference consistent with other tokens (e.g., a relative asset path or
imported URL), so the UI shows the wrapped XTZ icon; locate the WXTZ object
(symbol: 'WXTZ', networks includes chain: etherlink, address:
'0xc9B53AB2679f573e480d01e0f49e2B5CFB7a3EAb') and replace img: undefined with
the appropriate image reference (or a fallback token image) following the same
pattern used by other token entries.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/utils/networks.ts`:
- Around line 176-187: The Etherlink network entry (SupportedNetworks.Etherlink)
calls getRpcUrl(process.env.NEXT_PUBLIC_ETHERLINK_RPC) without an
alchemySubdomain or public fallback, which yields an empty string when the env
var is unset and breaks http() transport in rpc.ts; update the Etherlink object
to call getRpcUrl(process.env.NEXT_PUBLIC_ETHERLINK_RPC, { alchemySubdomain:
'etherlink-mainnet' }) if Alchemy supports it, or pass a public fallback like {
fallback: 'https://node.mainnet.etherlink.com' } (or similar param your
getRpcUrl supports) so defaultRPC is never an empty string and http() always
receives a valid URL.

---

Outside diff comments:
In `@src/utils/external.ts`:
- Around line 45-66: The getChainNameForMerkl function is missing a branch for
SupportedNetworks.Etherlink, causing Etherlink requests to fall through to the
default 'ethereum'; update getChainNameForMerkl to add a case for
SupportedNetworks.Etherlink that returns 'etherlink' so Etherlink is mapped
correctly (modify the switch in getChainNameForMerkl to include case
SupportedNetworks.Etherlink: return 'etherlink';).

---

Duplicate comments:
In `@src/features/autovault/components/vault-identity.tsx`:
- Around line 151-153: The tooltip link is always shown because actionHref is
passed unconditionally; change the JSX so TooltipContent (or the component
receiving actionHref in vault-identity.tsx) only receives actionHref when the
chain is supported—e.g. replace actionHref={vaultHref} with a conditional prop
(pass undefined or omit the prop when the chain is unsupported), using the
existing vaultHref and the chain-support boolean you have in scope so
onActionClick and actionIcon remain unchanged.

---

Nitpick comments:
In `@src/utils/tokens.ts`:
- Around line 289-294: The token entry for symbol 'WXTZ' has img: undefined;
update the WXTZ object in the tokens list to provide an image reference
consistent with other tokens (e.g., a relative asset path or imported URL), so
the UI shows the wrapped XTZ icon; locate the WXTZ object (symbol: 'WXTZ',
networks includes chain: etherlink, address:
'0xc9B53AB2679f573e480d01e0f49e2B5CFB7a3EAb') and replace img: undefined with
the appropriate image reference (or a fallback token image) following the same
pattern used by other token entries.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: e1c07139-43c7-4a4b-9068-1066af37b8b7

📥 Commits

Reviewing files that changed from the base of the PR and between 4081260 and 24c820a.

⛔ Files ignored due to path filters (5)
  • src/imgs/chains/etherlink.svg is excluded by !**/*.svg
  • src/imgs/tokens/mbasis.png is excluded by !**/*.png
  • src/imgs/tokens/mmev.svg is excluded by !**/*.svg
  • src/imgs/tokens/mtbill.png is excluded by !**/*.png
  • src/imgs/tokens/xu3o8.png is excluded by !**/*.png
📒 Files selected for processing (13)
  • .env.local.example
  • src/config/appkit.ts
  • src/constants/public-allocator.ts
  • src/features/admin-v2/components/chain-volume-chart.tsx
  • src/features/autovault/components/vault-identity.tsx
  • src/features/market-detail/components/market-header.tsx
  • src/store/createWagmiConfig.ts
  • src/types/token.ts
  • src/utils/external.ts
  • src/utils/morpho.ts
  • src/utils/networks.ts
  • src/utils/rpc.ts
  • src/utils/tokens.ts
✅ Files skipped from review due to trivial changes (5)
  • src/features/admin-v2/components/chain-volume-chart.tsx
  • src/store/createWagmiConfig.ts
  • src/utils/rpc.ts
  • src/constants/public-allocator.ts
  • src/features/market-detail/components/market-header.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/config/appkit.ts
  • src/types/token.ts
  • src/utils/morpho.ts

Comment on lines +176 to +187
{
network: SupportedNetworks.Etherlink,
chain: etherlinkChain,
logo: require('../imgs/chains/etherlink.svg') as string,
name: 'Etherlink',
defaultRPC: getRpcUrl(process.env.NEXT_PUBLIC_ETHERLINK_RPC),
blocktime: 4.83,
maxBlockDelay: 10,
explorerUrl: 'https://explorer.etherlink.com',
nativeTokenSymbol: 'XTZ',
wrappedNativeToken: '0xc9B53AB2679f573e480d01e0f49e2B5CFB7a3EAb',
},
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify default Etherlink public RPC is functional
curl -s -X POST "https://node.mainnet.etherlink.com" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}' | jq .

Repository: antoncoding/monarch

Length of output: 118


🏁 Script executed:

# Check getRpcUrl implementation and alchemySubdomain handling
rg "function getRpcUrl|const getRpcUrl" -A 15 src/

Repository: antoncoding/monarch

Length of output: 1023


🏁 Script executed:

# Search for http() transport usage and how empty URLs are handled
rg "http\(" src/utils/rpc.ts -A 3 -B 3

Repository: antoncoding/monarch

Length of output: 1723


🏁 Script executed:

# Look for env var documentation and examples
find . -name ".env*" -o -name "README*" -o -name "docs" -type f | head -20

Repository: antoncoding/monarch

Length of output: 171


🏁 Script executed:

# Check if there are any error handlers or validation for missing RPC URLs
rg "NEXT_PUBLIC.*RPC|getRpcUrl" -B 2 -A 2 src/

Repository: antoncoding/monarch

Length of output: 4177


🏁 Script executed:

# Check .env.local.example for Etherlink RPC documentation
cat -n .env.local.example | grep -i etherlink

Repository: antoncoding/monarch

Length of output: 96


🏁 Script executed:

# Search for error handling or validation around http() or createPublicClient
rg "createPublicClient|http\(" src/utils/rpc.ts -B 3 -A 5 | head -50

Repository: antoncoding/monarch

Length of output: 2083


🏁 Script executed:

# Check if there's any error handling for empty or invalid RPC URLs
rg "RPC|rpcUrl" src/utils/rpc.ts -B 2 -A 2

Repository: antoncoding/monarch

Length of output: 2341


🏁 Script executed:

# Check if Alchemy supports Etherlink subdomain
rg "etherlink" -i src/utils/networks.ts | grep -i alchemy

Repository: antoncoding/monarch

Length of output: 45


🏁 Script executed:

# Verify viem's http() behavior with empty string - check if there's any validation or error handling in documentation or code comments
rg "http\(" -B 5 -A 5 src/ | grep -i "empty\|url\|validate\|error" | head -20

Repository: antoncoding/monarch

Length of output: 428


🏁 Script executed:

# Check getDefaultRPC function to see if it's the same as getRpcUrl
rg "function getDefaultRPC|const getDefaultRPC|export.*getDefaultRPC" -A 10 src/utils/networks.ts

Repository: antoncoding/monarch

Length of output: 436


🏁 Script executed:

# Check if there's initialization validation or error handling that would catch empty RPC URLs
rg "initializeDefaultClients|getClient" src/utils/rpc.ts -B 2 -A 10

Repository: antoncoding/monarch

Length of output: 940


🏁 Script executed:

# Look for any error boundaries or RPC validation in the app initialization
rg "try|catch|Error|throw" src/utils/rpc.ts | head -20

Repository: antoncoding/monarch

Length of output: 174


🏁 Script executed:

# Verify what happens with empty URL in http() - check if viem has inline validation
rg "http\(" -B 2 -A 2 src/utils/rpc.ts

Repository: antoncoding/monarch

Length of output: 1694


🏁 Script executed:

# Check if there's documentation in README about environment variables and Etherlink RPC requirement
grep -i "etherlink\|rpc\|environment" README.md | head -20

Repository: antoncoding/monarch

Length of output: 45


🏁 Script executed:

# Search for any error handling or runtime validation that might catch empty URLs
rg "defaultRPC|getDefaultRPC" src/ -B 3 -A 3 | grep -i "error\|throw\|valid\|empty" | head -20

Repository: antoncoding/monarch

Length of output: 145


🏁 Script executed:

# Check if there's a startup validation function that checks RPC URLs
rg "validate|check|init" src/utils/rpc.ts -i

Repository: antoncoding/monarch

Length of output: 163


🏁 Script executed:

# Check if there's any initialization code that validates RPC URLs on startup
rg "_app|initialization|startup" src/pages -i | head -10

Repository: antoncoding/monarch

Length of output: 112


🏁 Script executed:

# Verify if http() from viem throws on empty URL or just fails silently on request
rg "import.*http|from.*viem" src/utils/rpc.ts -A 2

Repository: antoncoding/monarch

Length of output: 320


🏁 Script executed:

# Check all network configs to compare Etherlink's RPC setup with others
rg "defaultRPC: getRpcUrl" src/utils/networks.ts

Repository: antoncoding/monarch

Length of output: 780


🏁 Script executed:

# Search for how the app uses these clients to see if there's error handling at usage time
rg "getClient|defaultClients" src/ | head -20

Repository: antoncoding/monarch

Length of output: 1614


🏁 Script executed:

# Check if the public Etherlink RPC is documented anywhere in the codebase or comments
rg "node.mainnet.etherlink|etherlink.com" src/

Repository: antoncoding/monarch

Length of output: 135


🏁 Script executed:

# Verify one more time that Etherlink is the only chain without alchemySubdomain
rg "getRpcUrl\(" src/utils/networks.ts | grep -v "alchemySubdomain"

Repository: antoncoding/monarch

Length of output: 780


Etherlink RPC lacks fallback—empty string if env var unset.

Unlike other chains, Etherlink's getRpcUrl() call omits the alchemySubdomain parameter, so when NEXT_PUBLIC_ETHERLINK_RPC is missing, it returns '' (empty string) instead of falling back to Alchemy. This empty string gets passed to http() transport in rpc.ts, causing request failures.

Other networks all have Alchemy subdomains: eth-mainnet, opt-mainnet, base-mainnet, polygon-mainnet, unichain-mainnet, arb-mainnet, hyperliquid-mainnet, monad-mainnet.

Options:

  1. Add alchemySubdomain: 'etherlink-mainnet' if Alchemy supports it, or document as required
  2. Provide public fallback: https://node.mainnet.etherlink.com (verified working, chainId 0xa729)
🧰 Tools
🪛 Betterleaks (1.1.1)

[high] 186-186: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

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

In `@src/utils/networks.ts` around lines 176 - 187, The Etherlink network entry
(SupportedNetworks.Etherlink) calls
getRpcUrl(process.env.NEXT_PUBLIC_ETHERLINK_RPC) without an alchemySubdomain or
public fallback, which yields an empty string when the env var is unset and
breaks http() transport in rpc.ts; update the Etherlink object to call
getRpcUrl(process.env.NEXT_PUBLIC_ETHERLINK_RPC, { alchemySubdomain:
'etherlink-mainnet' }) if Alchemy supports it, or pass a public fallback like {
fallback: 'https://node.mainnet.etherlink.com' } (or similar param your
getRpcUrl supports) so defaultRPC is never an empty string and http() always
receives a valid URL.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature request Specific feature ready to be implemented

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant