Skip to content

feat: add Scroll chain support behind feature flag#11903

Merged
NeOMakinG merged 4 commits intodevelopfrom
feat/integrate-scroll-relay
Feb 19, 2026
Merged

feat: add Scroll chain support behind feature flag#11903
NeOMakinG merged 4 commits intodevelopfrom
feat/integrate-scroll-relay

Conversation

@NeOMakinG
Copy link
Collaborator

@NeOMakinG NeOMakinG commented Feb 17, 2026

Description

Add support for Scroll (EVM chain, chainId 534352) as a second-class citizen. Scroll is a zkEVM Layer 2 scaling solution for Ethereum, providing fast and low-cost transactions with EVM equivalence.

Implements: CAIP constants, chain adapter (SecondClassEvmAdapter), plugin, feature flag, Relay swapper mapping, HDWallet support flags, CSP headers, asset generation script, viem/ethers client configuration, and all required shared-file entries (chain gating, portfolio, markets, UI).

Issue (if applicable)

Part of #11902

Risk

Low - All changes are behind the Scroll feature flag (VITE_FEATURE_SCROLL), disabled by default in production.

No new on-chain transactions or contract interactions. Standard EVM chain support using existing SecondClassEvmAdapter pattern (identical to MegaETH integration).

No protocols, transaction types, wallets or contract interactions are affected until the feature flag is enabled.

Testing

Engineering

  1. Set VITE_FEATURE_SCROLL=true in .env.development
  2. Run yarn dev
  3. Verify Scroll appears in chain selector when feature flag is enabled
  4. Verify native ETH balance loads on Scroll
  5. Verify Relay swap routes include Scroll as source/destination chain
  6. Run yarn lint — passes with 0 errors
  7. Run yarn type-check — verify no new type errors

Operations

  • 🏁 My feature is behind a flag and doesn't require operations testing (yet)

Screenshots (if applicable)

https://jam.dev/c/c90e8747-915f-4180-8e99-7fd84bed77ed
N/A - Behind feature flag, no visual changes until enabled.

Summary by CodeRabbit

  • New Features

    • Added support for the Scroll blockchain network
    • Enabled Scroll token integration and wallet connectivity
    • Added Scroll chain support across portfolio, swapping, and market services
  • Configuration

    • Added environment variables for Scroll network configuration
    • Introduced feature flag to control Scroll availability

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 17, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR adds comprehensive support for the Scroll blockchain network. It introduces chain constants, creates a dedicated EVM chain adapter, adds wallet capability flags, integrates asset data generation, wires CSP headers, and enables feature flag-based gating for controlled rollout.

Changes

Cohort / File(s) Summary
Environment & Configuration
.env, .env.development, src/config.ts, src/vite-env.d.ts
Added VITE_SCROLL_NODE_URL and VITE_FEATURE_SCROLL environment variables with validators and TypeScript typings.
CSP Headers
headers/csps/chains/scroll.ts, headers/csps/index.ts
Created new Scroll CSP configuration module with connect-src directive and integrated into CSP exports.
Core Chain Types & Constants
packages/types/src/base.ts, packages/caip/src/constants.ts
Added ScrollMainnet to KnownChainIds enum, defined scrollChainId and scrollAssetId constants, extended CHAIN_REFERENCE, ASSET_REFERENCE, VALID_CHAIN_IDS, and FEE_ASSET_IDS.
Coingecko Adapter
packages/caip/src/adapters/coingecko/index.ts, packages/caip/src/adapters/coingecko/utils.ts, packages/caip/src/adapters/coingecko/...test.ts
Added Scroll platform to Coingecko asset platform enum, wired chainId mappings, and added token parsing logic with test expectations.
Chain Adapter - Scroll
packages/chain-adapters/src/evm/scroll/ScrollChainAdapter.ts, packages/chain-adapters/src/evm/scroll/index.ts, packages/chain-adapters/src/evm/index.ts
Implemented ScrollChainAdapter extending SecondClassEvmAdapter with static params, display name, and token resolution; exported via barrel.
Chain Adapter - Base & Types
packages/chain-adapters/src/evm/EvmBaseAdapter.ts, packages/chain-adapters/src/types.ts
Added Scroll mainnet to evmChainIds, implemented assertSupportsChain and assertSwitchChain handlers, and extended type mappings for Scroll across ChainSpecificAccount, ChainSpecificFeeData, ChainSignTx, ChainSpecificBuildTxData, and GetFeeDataInput.
Ethers & Viem Clients
packages/contracts/src/ethersProviderSingleton.ts, packages/contracts/src/viemClient.ts
Added Scroll case to RPC URL mapping and created viemScrollClient with scroll chain, HTTP provider, and integrated into client/network ID mappings.
Wallet Capability Flags
packages/hdwallet-core/src/ethereum.ts, packages/hdwallet-core/src/wallet.ts, packages/hdwallet-*/src/*.ts (Coinbase, GridPlus, KeepKey, Ledger, MetaMask, Native, Phantom, Trezor, Vultisig, WalletConnect)
Added _supportsScroll property to ETHWallet interface and supportsScroll type guard; implemented _supportsScroll flags across all wallet implementations (false for Coinbase, KeepKey, Phantom, Vultisig; true for GridPlus, Ledger, MetaMask, Native, Trezor, WalletConnect).
Asset Data
packages/utils/src/assetData/baseAssets.ts, packages/utils/src/assetData/getBaseAsset.ts
Defined scroll asset constant with full metadata (name, symbol, precision, colors, icons, explorer links) and added case to getBaseAsset switch.
Utility Functions
packages/utils/src/chainIdToFeeAssetId.ts, packages/utils/src/getAssetNamespaceFromChainId.ts, packages/utils/src/getChainShortName.ts, packages/utils/src/getNativeFeeAssetReference.ts
Added Scroll cases to chain-to-fee-asset, chain-to-namespace, chain-to-shortname, and chain-reference-to-asset-reference mappings.
Swapper Integration
packages/swapper/src/swappers/RelaySwapper/constant.ts, packages/swapper/src/swappers/RelaySwapper/utils/relayTokenToAssetId.ts
Added Scroll to chainIdToRelayChainId mapping and relayTokenToAssetId token routing logic.
Asset Generation Scripts
scripts/generateAssetData/coingecko.ts, scripts/generateAssetData/generateAssetData.ts, scripts/generateAssetData/scroll/index.ts, scripts/generateAssetData/generateRelatedAssetIndex/generateRelatedAssetIndex.ts
Created new Scroll asset generation module, integrated into asset data pipeline, included scrollAssetId in manual related asset index, and replaced environment-based Zerion API key with hardcoded constant.
Feature Flag Integration
src/config.ts, src/constants/chains.ts, src/state/slices/preferencesSlice/preferencesSlice.ts, src/test/mocks/store.ts, src/vite-env.d.ts
Added Scroll feature flag to preferences, initialized from config, added feature-flag gating in chain filtering, and updated mock store.
Plugin System
src/plugins/scroll/index.tsx, src/plugins/activePlugins.ts
Created Scroll plugin that registers chainAdapter provider, wires RPC URL and getKnownTokens function, and added to activePlugins array.
UI Feature Gating
src/context/PluginProvider/PluginProvider.tsx, src/hooks/useWalletSupportsChain/useWalletSupportsChain.ts, src/pages/Markets/components/MarketsRow.tsx
Added Scroll feature-flag checks and wallet capability checks across plugin provider, wallet support hook, and markets UI component.
Portfolio & Asset Service
src/lib/account/evm.ts, src/lib/asset-service/service/AssetService.ts, src/state/slices/portfolioSlice/utils/index.ts
Added Scroll chain filtering in EVM account derivation, asset service filtering, and portfolio utilities (accountIdToLabel and isAssetSupportedByWallet).
Popular Assets & Markets
src/components/TradeAssetSearch/hooks/useGetPopularAssetsQuery.tsx
Added scrollAssetId to popular assets query when Scroll feature flag is enabled.
State Migrations
src/state/migrations/index.ts, src/state/slices/opportunitiesSlice/mappings.ts
Added migration entries 289–292 for clearAssets and added ScrollMainnet to CHAIN_ID_TO_SUPPORTED_DEFI_OPPORTUNITIES mapping (empty array).
Testing
packages/caip/src/adapters/coingecko/index.test.ts, src/lib/market-service/coingecko/coingecko.test.ts
Updated test expectations to include scroll asset mappings in aggregated results.

Sequence Diagram

sequenceDiagram
    actor User
    participant UI as UI Component
    participant Plugin as Scroll Plugin
    participant Config as Configuration
    participant ChainAdapter as Chain Adapter
    participant Wallet as Wallet
    participant AssetService as Asset Service
    participant RPC as RPC Node

    User->>UI: Enable Scroll (Feature Flag)
    UI->>Plugin: Initialize Scroll support
    Plugin->>Config: Load VITE_SCROLL_NODE_URL
    Config-->>Plugin: RPC URL
    Plugin->>ChainAdapter: Create ScrollChainAdapter
    ChainAdapter->>Wallet: Check supportsScroll(wallet)
    Wallet-->>ChainAdapter: Wallet capability
    alt Wallet Supports Scroll
        ChainAdapter->>AssetService: getKnownTokens()
        AssetService->>AssetService: Filter Scroll ERC20 assets
        AssetService-->>ChainAdapter: Token list
        ChainAdapter->>RPC: Initialize client
        RPC-->>ChainAdapter: Connected
        ChainAdapter-->>UI: Ready for transactions
    else Wallet Does Not Support
        ChainAdapter-->>UI: Chain unavailable
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

high risk

Suggested reviewers

  • gomesalexandre

Poem

🐰 Scroll awaits in our bundle bright,
Chain adapters wired just right,
Wallets speak "yes, I support thee,"
Assets flow with harmony,
Feature flags guard the night!

🚥 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 PR title 'feat: add Scroll chain support behind feature flag' accurately describes the main change: adding support for the Scroll blockchain behind a feature flag toggle.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/integrate-scroll-relay

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.

@NeOMakinG NeOMakinG marked this pull request as ready for review February 17, 2026 15:14
@NeOMakinG NeOMakinG requested a review from a team as a code owner February 17, 2026 15:14
Copy link
Contributor

@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 (2)
packages/caip/src/adapters/coingecko/utils.ts (1)

294-304: Add explanatory comment to Scroll catch block for consistency.

The catch block at line 303 is empty (catch {}), while all other similar platform parsing blocks in this file include the comment // unable to create assetId, skip token. Update line 303 to match the established pattern for clarity and consistency.

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

In `@packages/caip/src/adapters/coingecko/utils.ts` around lines 294 - 304, The
empty catch block after attempting to build an assetId for
CoingeckoAssetPlatform.Scroll should include the same explanatory comment used
elsewhere; update the catch in the block that calls toAssetId (with
chainNamespace CHAIN_NAMESPACE.Evm, chainReference
CHAIN_REFERENCE.ScrollMainnet, assetNamespace 'erc20' and assetReference
platforms[CoingeckoAssetPlatform.Scroll]) to read catch { // unable to create
assetId, skip token } so it's consistent with other platform parsing blocks that
set prev[scrollChainId][assetId] = id.
src/plugins/scroll/index.tsx (1)

22-36: Double fromAssetId call per asset — minor inefficiency.

fromAssetId is invoked in both the filter (line 26) and map (line 31) callbacks for every matching asset. Since this runs once at startup and the PR description notes it's identical to the MegaETH pattern, this is a nit.

♻️ Optional: combine filter + map to avoid the extra parse
-                const getKnownTokens = () => {
-                  const assetService = getAssetService()
-                  return assetService.assets
-                    .filter(asset => {
-                      const { chainId, assetNamespace } = fromAssetId(asset.assetId)
-                      return chainId === scrollChainId && assetNamespace === 'erc20'
-                    })
-                    .map(asset => ({
-                      assetId: asset.assetId,
-                      contractAddress: fromAssetId(asset.assetId).assetReference,
-                      symbol: asset.symbol,
-                      name: asset.name,
-                      precision: asset.precision,
-                    }))
+                const getKnownTokens = () => {
+                  const assetService = getAssetService()
+                  return assetService.assets.reduce<
+                    {
+                      assetId: string
+                      contractAddress: string
+                      symbol: string
+                      name: string
+                      precision: number
+                    }[]
+                  >((acc, asset) => {
+                    const { chainId, assetNamespace, assetReference } = fromAssetId(asset.assetId)
+                    if (chainId === scrollChainId && assetNamespace === 'erc20') {
+                      acc.push({
+                        assetId: asset.assetId,
+                        contractAddress: assetReference,
+                        symbol: asset.symbol,
+                        name: asset.name,
+                        precision: asset.precision,
+                      })
+                    }
+                    return acc
+                  }, [])
                 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/plugins/scroll/index.tsx` around lines 22 - 36, getKnownTokens currently
calls fromAssetId twice per asset (once in the filter and again in the map),
causing unnecessary repeated parsing; refactor getKnownTokens to parse each
assetId once by calling fromAssetId(asset.assetId) in a single pass (e.g., use
map to extract parsed fields then filter by chainId === scrollChainId and
assetNamespace === 'erc20') and then build the returned object with
contractAddress, symbol, name, precision using the saved parsed result; update
references to fromAssetId, assetService.assets, and scrollChainId within
getKnownTokens accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.env.development:
- Line 66: Remove the trailing slash from the VITE_SCROLL_NODE_URL value so it
matches the other *_NODE_URL entries; locate the VITE_SCROLL_NODE_URL
environment variable and change its value from "https://rpc.scroll.io/" to
"https://rpc.scroll.io" (ensuring any code that concatenates paths remains
consistent without relying on a trailing slash).

---

Nitpick comments:
In `@packages/caip/src/adapters/coingecko/utils.ts`:
- Around line 294-304: The empty catch block after attempting to build an
assetId for CoingeckoAssetPlatform.Scroll should include the same explanatory
comment used elsewhere; update the catch in the block that calls toAssetId (with
chainNamespace CHAIN_NAMESPACE.Evm, chainReference
CHAIN_REFERENCE.ScrollMainnet, assetNamespace 'erc20' and assetReference
platforms[CoingeckoAssetPlatform.Scroll]) to read catch { // unable to create
assetId, skip token } so it's consistent with other platform parsing blocks that
set prev[scrollChainId][assetId] = id.

In `@src/plugins/scroll/index.tsx`:
- Around line 22-36: getKnownTokens currently calls fromAssetId twice per asset
(once in the filter and again in the map), causing unnecessary repeated parsing;
refactor getKnownTokens to parse each assetId once by calling
fromAssetId(asset.assetId) in a single pass (e.g., use map to extract parsed
fields then filter by chainId === scrollChainId and assetNamespace === 'erc20')
and then build the returned object with contractAddress, symbol, name, precision
using the saved parsed result; update references to fromAssetId,
assetService.assets, and scrollChainId within getKnownTokens accordingly.

Copy link
Contributor

@gomesalexandre gomesalexandre left a comment

Choose a reason for hiding this comment

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

what @gomes-bot said

Copy link
Contributor

@gomesalexandre gomesalexandre left a comment

Choose a reason for hiding this comment

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

found two more blockers - gomes-bot review coming in hot soon

@NeOMakinG NeOMakinG force-pushed the feat/integrate-scroll-relay branch from 787739c to 4bb2b26 Compare February 18, 2026 10:10
@NeOMakinG NeOMakinG self-assigned this Feb 18, 2026
@NeOMakinG NeOMakinG force-pushed the feat/integrate-scroll-relay branch from 7cf957a to 025c28e Compare February 19, 2026 09:31
Copy link
Contributor

@gomesalexandre gomesalexandre left a comment

Choose a reason for hiding this comment

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

Copy link
Contributor

@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

🧹 Nitpick comments (1)
.env.development (1)

99-99: VITE_FEATURE_SCROLL key is out of alphabetical order.

dotenv-linter reports that VITE_FEATURE_SCROLL should appear before VITE_FEATURE_WC_DIRECT_CONNECTION for consistent ordering.

Proposed fix
 VITE_FEATURE_WC_DIRECT_CONNECTION=true
 VITE_FEATURE_CETUS_SWAP=true
 VITE_FEATURE_MEGAETH=true
-VITE_FEATURE_SCROLL=true
 VITE_FEATURE_KATANA=true
+VITE_FEATURE_SCROLL=true
 VITE_FEATURE_ACROSS_SWAP=true
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.env.development at line 99, Move the VITE_FEATURE_SCROLL entry so the keys
are alphabetically ordered: locate the VITE_FEATURE_SCROLL line and place it
before the VITE_FEATURE_WC_DIRECT_CONNECTION entry (ensure there is a
newline/format preserved and no duplicate keys), so dotenv-linter no longer
reports an ordering violation.
🤖 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/caip/src/adapters/coingecko/utils.ts`:
- Around line 294-303: The empty catch block after attempting to build an
assetId for CoingeckoAssetPlatform.Scroll (the try using toAssetId and assigning
prev[scrollChainId][assetId] = id) should include the same standard comment used
in other catch blocks in this file; update the catch to include that comment
(e.g., the existing file-wide marker like "// ignore invalid asset id" or the
project's agreed-upon comment) so the empty catch is intentional and consistent
with other handlers.

In
`@scripts/generateAssetData/generateRelatedAssetIndex/generateRelatedAssetIndex.ts`:
- Around line 45-46: The hardcoded production key assigned to ZERION_API_KEY
must be removed and replaced with environment variable loading: change the
ZERION_API_KEY initialization to read from process.env.ZERION_API_KEY (or a
config loader) and restore the fail-fast guard by throwing an Error when that
environment variable is missing; update any usage sites that reference
ZERION_API_KEY to use the new variable as-is. Ensure no literal API key remains
in the file or diff and confirm the guard (if (!ZERION_API_KEY) throw new
Error(...)) is reachable again. Also record that the exposed key must be rotated
out-of-band immediately.

---

Duplicate comments:
In @.env.development:
- Line 66: The VITE_SCROLL_NODE_URL entry still contains a trailing slash;
update the environment variable value for VITE_SCROLL_NODE_URL to remove the
trailing slash (make it https://rpc.scroll.io) to match the format of other
*_NODE_URL entries and ensure any code that reads VITE_SCROLL_NODE_URL (e.g.,
config loaders or functions referencing VITE_SCROLL_NODE_URL) expects the URL
without a trailing slash.

---

Nitpick comments:
In @.env.development:
- Line 99: Move the VITE_FEATURE_SCROLL entry so the keys are alphabetically
ordered: locate the VITE_FEATURE_SCROLL line and place it before the
VITE_FEATURE_WC_DIRECT_CONNECTION entry (ensure there is a newline/format
preserved and no duplicate keys), so dotenv-linter no longer reports an ordering
violation.

@NeOMakinG NeOMakinG force-pushed the feat/integrate-scroll-relay branch from a7a2d61 to 793caa2 Compare February 19, 2026 10:09
@shapeshift shapeshift deleted a comment from coderabbitai bot Feb 19, 2026
@NeOMakinG NeOMakinG enabled auto-merge (squash) February 19, 2026 10:10
@NeOMakinG NeOMakinG dismissed a stale review February 19, 2026 10:40

bro

@NeOMakinG NeOMakinG merged commit 776d447 into develop Feb 19, 2026
5 checks passed
@NeOMakinG NeOMakinG deleted the feat/integrate-scroll-relay branch February 19, 2026 11:33
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.

2 participants