Skip to content

feat: integrate Mode (eip155:34443) as second-class citizen#11926

Merged
gomesalexandre merged 61 commits intodevelopfrom
feat/integrate-mode-relay
Feb 21, 2026
Merged

feat: integrate Mode (eip155:34443) as second-class citizen#11926
gomesalexandre merged 61 commits intodevelopfrom
feat/integrate-mode-relay

Conversation

@NeOMakinG
Copy link
Collaborator

@NeOMakinG NeOMakinG commented Feb 17, 2026

Description

Integrates Mode (eip155:34443) as a second-class citizen chain in ShapeShift Web via Relay.link.

This is PR 6 of 17 in a sequential chain integration series. These PRs must be reviewed and merged in order, as each builds on the previous one (stacked branches).

PR merge order:

  1. Mantle (feat: integrate Mantle (chainId 5000) as second-class EVM chain #11905)
  2. Cronos (feat: integrate Cronos (chainId 25) as second-class EVM chain #11910)
  3. Sonic (feat: integrate Sonic (eip155:146) as second-class EVM chain #11923)
  4. Unichain (feat: integrate Unichain (eip155:130) as second-class citizen via Relay #11924)
  5. BOB (feat: integrate BOB (eip155:60808) as second-class citizen #11925)
  6. Mode (feat: integrate Mode (eip155:34443) as second-class citizen #11926) ← this PR
  7. Soneium (feat: integrate Soneium (chainId: 1868) via Relay #11930)
  8. Hemi (feat: integrate Hemi (chainId: 43111) via Relay #11931)
  9. World Chain (feat: integrate World Chain (480) as second-class Relay chain #11932)
  10. Blast (feat: integrate Blast (81457) as second-class Relay chain #11933)
  11. zkSync Era (feat: integrate zkSync Era (324) as second-class Relay chain #11934)
  12. Story (feat: integrate Story (1514) as second-class Relay chain #11936)
  13. Plume (feat: integrate Plume (98866) as second-class Relay chain #11937)
  14. Flow EVM (feat: integrate Flow EVM (747) as second-class Relay chain #11938)
  15. Celo (feat: integrate Celo (42220) as second-class Relay chain #11939)
  16. Ethereal (feat: integrate Ethereal (5064014) as second-class Relay chain #11940)

Note: Linea (#11922) is already in develop.

Mode is an EVM L2 with ETH as its native gas token. This integration adds full support including:

  • Chain constants, types, and HDWallet support (all wallet types)
  • EVM chain adapter with Mode-specific configuration
  • Relay swapper chain mapping
  • Across swapper chain mapping (Mode is supported by Across)
  • CoinGecko price adapter (platform: mode, maps to ethereum)
  • Zerion chain mapping
  • Feature flag (VITE_FEATURE_MODE) gated behind second-class citizen config
  • CSP headers for RPC and explorer endpoints
  • Asset generation scripts
  • Related asset index entry (ETH-native)
  • CoinGecko supported chain IDs integration

Issue (if applicable)

Part of #11902

Risk

Low risk - feature-flagged second-class chain integration following established patterns (identical to Scroll, Ink, Mantle, Cronos, Berachain, Linea, Sonic, Unichain, BOB integrations).

What protocols, transaction types, wallets or contract interactions might be affected by this PR?

No existing protocols affected. New chain only accessible when feature flag is enabled.

Testing

Engineering

  1. Enable feature flag: Set VITE_FEATURE_MODE=true in .env.development
  2. Verify Mode chain appears in chain selector
  3. Verify Mode ETH balance loads for connected wallet
  4. Verify Relay swaps work for Mode assets
  5. Verify Across bridge works for Mode
  6. Run yarn type-check - passes
  7. Run yarn lint - passes

Operations

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

Screenshots (if applicable)

N/A - chain integration following established patterns

Summary by CodeRabbit

Release Notes

  • New Features
    • Added support for the Mode chain, a layer-2 network built on Ethereum.
    • Integrated Mode with multiple wallet providers (Ledger, MetaMask, Trezor, and others).
    • Enabled Mode assets (ETH on Mode) for trading, portfolio tracking, and swapping.
    • Mode network is currently disabled by default and can be toggled via feature flags.

…Relay bridge support

Add support for Mantle (MNT native gas) including CAIP constants, chain adapter,
plugin, feature flag, Relay swapper mapping, HDWallet support flags, CSP headers,
asset generation script, and all required shared-file entries.

Part of #11902
…lay bridge support

Add support for Cronos (CRO native gas) including CAIP constants, chain adapter,
plugin, feature flag, Relay swapper mapping, HDWallet support flags, CSP headers,
asset generation script, and all required shared-file entries.

Part of #11902
Add src/lib/utils/mantle.ts with getMantleTransactionStatus using
eth_getTransactionReceipt via the Mantle RPC.

Add KnownChainIds.MantleMainnet case to useSendActionSubscriber.tsx
so Mantle transactions resolve in the action center.
Add src/lib/utils/cronos.ts with getCronosTransactionStatus using
eth_getTransactionReceipt via the Cronos RPC.

Add KnownChainIds.CronosMainnet case to useSendActionSubscriber.tsx
so Cronos transactions resolve in the action center.

Add CHAIN_REFERENCE.CronosMainnet case to relayTokenToAssetId.ts
to prevent runtime crash on Relay swaps involving Cronos.
Address PR review feedback:
- Add mantleChainId to getCoingeckoSupportedChainIds (feature-flagged)
- Add mantle to ZERION_CHAINS array and ZERION_CHAINS_MAP
- Across does not support Mantle, skipped
Address PR review feedback:
- Add cronosChainId to getCoingeckoSupportedChainIds (feature-flagged)
- Add cronos to ZERION_CHAINS array and ZERION_CHAINS_MAP
- Across does not support Cronos, skipped
Adds full Unichain support including:
- CAIP constants, types, and chain adapter
- HDWallet support flags across all wallet implementations
- Relay and Across swapper mappings
- CoinGecko adapter with unichain platform
- Zerion chain mapping
- Feature flag, plugin, CSP headers
- Portfolio, account, asset service, and market integrations
- Asset generation scripts and related asset index (ETH-native)

Part of #11902
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 17, 2026

📝 Walkthrough

Walkthrough

Comprehensive integration of Mode blockchain network across the codebase, including environment configuration, CAIP constants, EVM chain adapters, wallet support capabilities, asset data generation pipelines, viem/ethers clients, swapper integrations, plugin registration, and state management—all gated behind a feature flag for conditional enablement.

Changes

Cohort / File(s) Summary
Environment & Configuration
.env, .env.development, src/config.ts, src/vite-env.d.ts
Added VITE_MODE_NODE_URL environment variable and VITE_FEATURE_MODE feature flag across environment files and TypeScript type definitions.
Chain Type System
packages/types/src/base.ts, packages/caip/src/constants.ts
Added KnownChainIds.ModeMainnet ('eip155:34443') enum entry, modeChainId and modeAssetId constants, and updated EvmChainId union to include Mode.
EVM Chain Adapter Infrastructure
packages/chain-adapters/src/evm/EvmBaseAdapter.ts, packages/chain-adapters/src/evm/SecondClassEvmAdapter.ts, packages/chain-adapters/src/evm/mode/*, packages/chain-adapters/src/types.ts
Implemented Mode-specific SecondClassEvmAdapter with rootBip44Params, display names, and type definitions; extended ChainSpecificAccount, ChainSpecificFeeData, ChainSignTx, and ChainSpecificBuildTxData types to include ModeMainnet mappings.
Wallet Support Capabilities
packages/hdwallet-core/src/ethereum.ts, packages/hdwallet-core/src/wallet.ts, packages/hdwallet-*/src/*.ts (Coinbase, GridPlus, KeepKey, Ledger, MetaMask-Multichain, Native, Phantom, Trezor, Vultisig, WalletConnectV2)
Added readonly \_supportsMode capability flag (true/false per wallet type) to all HDWallet implementations and created supportsMode(wallet) type guard function.
Coingecko Integration
packages/caip/src/adapters/coingecko/index.ts, packages/caip/src/adapters/coingecko/index.test.ts, packages/caip/src/adapters/coingecko/utils.ts, packages/caip/src/adapters/coingecko/utils.test.ts
Added Mode platform mappings in CoingeckoAssetPlatform enum, chainId-to-platform conversions, EIP-155 chain parsing, and test expectations for Mode asset handling.
Viem & Ethers Clients
packages/contracts/src/viemClient.ts, packages/contracts/src/ethersProviderSingleton.ts, headers/csps/chains/mode.ts, headers/csps/index.ts
Created viemModeClient and CSP connect-src directives for Mode network; added RPC URL resolution in rpcUrlByChainId and viem client mappings (viemClientByChainId, viemNetworkIdByChainId, viemClientByNetworkId).
Swapper Integrations
packages/swapper/src/swappers/AcrossSwapper/constant.ts, packages/swapper/src/swappers/RelaySwapper/constant.ts, packages/swapper/src/swappers/RelaySwapper/utils/relayTokenToAssetId.ts
Extended chainIdToAcrossChainId and chainIdToRelayChainId mappings to include Mode; added Mode asset reference mapping in relayTokenToAssetId switch case.
Asset Data Generation
packages/utils/src/assetData/baseAssets.ts, packages/utils/src/assetData/getBaseAsset.ts, scripts/generateAssetData/coingecko.ts, scripts/generateAssetData/generateAssetData.ts, scripts/generateAssetData/mode/index.ts
Added modeChain asset definition, getAssets() function for Mode chain asset fetching, and integration into the main asset-generation pipeline.
Related Asset Indexing
scripts/generateAssetData/generateRelatedAssetIndex/generateChainRelatedAssetIndex.ts, scripts/generateAssetData/generateRelatedAssetIndex/generateRelatedAssetIndex.ts
Included modeAssetId in ETH-related asset associations within the manual related-asset index mappings.
Utility Functions
packages/utils/src/chainIdToFeeAssetId.ts, packages/utils/src/getAssetNamespaceFromChainId.ts, packages/utils/src/getChainShortName.ts, packages/utils/src/getNativeFeeAssetReference.ts, src/lib/utils/mode.ts
Added Mode case handling in fee asset ID, asset namespace, and chain short name switches; created isModeChainAdapter type guard and getModeTransactionStatus async function for tx status polling.
State Management & Feature Flagging
src/state/slices/preferencesSlice/preferencesSlice.ts, src/test/mocks/store.ts, src/constants/chains.ts, src/state/slices/opportunitiesSlice/mappings.ts, src/state/migrations/index.ts
Added Mode feature flag to FeatureFlags type and initial state; added ModeMainnet to SECOND_CLASS_CHAINS with conditional filtering based on feature flag; added migration entry 299 and empty defi opportunities mapping.
Plugin Registration & UI Integration
src/plugins/mode/index.tsx, src/plugins/activePlugins.ts
Created Mode plugin register() function that instantiates ModeChainAdapter with RPC URL and getKnownTokens callback; registered mode plugin in activePlugins array.
Wallet & Chain Support Checks
src/hooks/useWalletSupportsChain/useWalletSupportsChain.ts, src/lib/account/evm.ts, src/context/PluginProvider/PluginProvider.tsx, src/state/slices/portfolioSlice/utils/index.ts
Added modeChainId and supportsMode checks in wallet capability gates and account derivation; implemented conditional filtering based on wallet capability and feature flag.
Asset & Coingecko Support
src/lib/asset-service/service/AssetService.ts, src/lib/coingecko/utils.ts, packages/types/src/zerion.ts
Extended asset filtering to exclude modeChainId when feature flag disabled; added modeChainId to supported chains list; added Mode entry to ZERION_CHAINS and ZERION_CHAINS_MAP.
UI Components & Queries
src/components/TradeAssetSearch/hooks/useGetPopularAssetsQuery.tsx, src/pages/Markets/components/MarketsRow.tsx, src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx, src/lib/market-service/coingecko/coingecko.test.ts
Conditionally added modeAssetId to popular assets when feature enabled; added Mode transaction status polling via getModeTransactionStatus; updated test expectations for flattened Coingecko responses.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~45 minutes

Possibly related PRs

  • #11241: Implements nearly identical second-class EVM chain integration (Monad vs Mode), modifying the same modules and functions across constants, adapters, clients, plugins, and asset generation.
  • #11569: Implements chain-specific integration following the same pattern (Katana vs Mode), with analogous changes to env config, CAIP constants, chain adapters, hdwallet support guards, and asset generation.
  • #11457: Modifies the same transaction-status polling logic in useSendActionSubscriber to add a new second-class EVM chain case (HyperEVM vs Mode).

Suggested labels

high risk, chain-integration, feature-flag


🐰 Hop, hop to Mode we go,
A new chain joins our rainbow flow!
With constants, adapters, wallets all,
Mode mainnet answers the call! ✨
Feature flags keep things in check,
One integration—no wreck! 🎉

🚥 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 clearly identifies the primary change: integrating Mode (eip155:34443) as a second-class citizen chain, which aligns with the comprehensive changeset across chain constants, adapters, swappers, and feature flags.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/integrate-mode-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 and others added 13 commits February 17, 2026 23:15
Mode (eip155:34443) sorts before MegaEth (eip155:4326) in coingeckoToAssetIds.
Add missing Mode entry to market-service test destructuring and expected array.
The BOB adapter.json (eip155_60808) was created but not imported/exported
from the generated index.ts, causing coingeckoToAssetIds to not return BOB.
Also fix ethereum assetId ordering and add BOB to market-service test.
The Unichain adapter.json (eip155_130) was created but not imported/exported
from the generated index.ts, causing coingeckoToAssetIds to not return Unichain.
The Sonic adapter.json (eip155_146) was created but not imported/exported
from the generated index.ts, preventing CoinGecko mapping for Sonic tokens.
…tle-relay

# Conflicts:
#	.env
#	.env.development
#	packages/caip/src/adapters/coingecko/generated/index.ts
#	packages/caip/src/adapters/coingecko/index.ts
#	packages/caip/src/adapters/coingecko/utils.test.ts
#	packages/caip/src/adapters/coingecko/utils.ts
#	packages/caip/src/constants.ts
#	packages/chain-adapters/src/evm/EvmBaseAdapter.ts
#	packages/chain-adapters/src/types.ts
#	packages/contracts/src/ethersProviderSingleton.ts
#	packages/contracts/src/viemClient.ts
#	packages/hdwallet-coinbase/src/coinbase.ts
#	packages/hdwallet-core/src/ethereum.ts
#	packages/hdwallet-core/src/wallet.ts
#	packages/hdwallet-gridplus/src/gridplus.ts
#	packages/hdwallet-keepkey/src/keepkey.ts
#	packages/hdwallet-ledger/src/ledger.ts
#	packages/hdwallet-metamask-multichain/src/shapeshift-multichain.ts
#	packages/hdwallet-native/src/ethereum.ts
#	packages/hdwallet-phantom/src/phantom.ts
#	packages/hdwallet-trezor/src/trezor.ts
#	packages/hdwallet-vultisig/src/vultisig.ts
#	packages/hdwallet-walletconnectv2/src/walletconnectV2.ts
#	packages/swapper/src/swappers/RelaySwapper/constant.ts
#	packages/swapper/src/swappers/RelaySwapper/utils/relayTokenToAssetId.ts
#	packages/types/src/base.ts
#	packages/types/src/zerion.ts
#	packages/utils/src/assetData/baseAssets.ts
#	packages/utils/src/assetData/getBaseAsset.ts
#	packages/utils/src/chainIdToFeeAssetId.ts
#	packages/utils/src/getAssetNamespaceFromChainId.ts
#	packages/utils/src/getChainShortName.ts
#	packages/utils/src/getNativeFeeAssetReference.ts
#	scripts/generateAssetData/coingecko.ts
#	scripts/generateAssetData/generateAssetData.ts
#	src/components/TradeAssetSearch/hooks/useGetPopularAssetsQuery.tsx
#	src/config.ts
#	src/constants/chains.ts
#	src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx
#	src/hooks/useWalletSupportsChain/useWalletSupportsChain.ts
#	src/lib/account/evm.ts
#	src/lib/asset-service/service/AssetService.ts
#	src/lib/coingecko/utils.ts
#	src/pages/Markets/components/MarketsRow.tsx
#	src/state/slices/portfolioSlice/utils/index.ts
#	src/state/slices/preferencesSlice/preferencesSlice.ts
#	src/test/mocks/store.ts
#	src/vite-env.d.ts
Missing closing braces in 7 files where auto-resolve stripped
them at mantle/next-entry boundaries.

Also made generateChainRelatedAssetIndex self-contained (no
import from generateRelatedAssetIndex to avoid module-scope
ZERION_API_KEY check).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
77 Mantle assets added with relatedAssetKey cross-chain linking.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
gomesalexandre and others added 2 commits February 21, 2026 12:57
…e-relay

# Conflicts:
#	.beads/pr-context.jsonl
#	.beads/ss-dx5.8.json
#	.beads/ss-dx5.9.json
#	.claude/contracts/second-class-evm-chain.md
#	.env
#	.env.development
#	headers/csps/index.ts
#	packages/caip/src/adapters/coingecko/generated/index.ts
#	packages/caip/src/adapters/coingecko/index.test.ts
#	packages/caip/src/adapters/coingecko/index.ts
#	packages/caip/src/adapters/coingecko/utils.test.ts
#	packages/caip/src/adapters/coingecko/utils.ts
#	packages/caip/src/constants.ts
#	packages/chain-adapters/src/evm/EvmBaseAdapter.ts
#	packages/chain-adapters/src/evm/SecondClassEvmAdapter.ts
#	packages/chain-adapters/src/evm/index.ts
#	packages/chain-adapters/src/types.ts
#	packages/contracts/src/ethersProviderSingleton.ts
#	packages/contracts/src/viemClient.ts
#	packages/hdwallet-coinbase/src/coinbase.ts
#	packages/hdwallet-core/src/ethereum.ts
#	packages/hdwallet-core/src/wallet.ts
#	packages/hdwallet-gridplus/src/gridplus.ts
#	packages/hdwallet-keepkey/src/keepkey.ts
#	packages/hdwallet-ledger/src/ledger.ts
#	packages/hdwallet-metamask-multichain/src/shapeshift-multichain.ts
#	packages/hdwallet-native/src/ethereum.ts
#	packages/hdwallet-phantom/src/phantom.ts
#	packages/hdwallet-trezor/src/trezor.ts
#	packages/hdwallet-vultisig/src/vultisig.ts
#	packages/hdwallet-walletconnectv2/src/walletconnectV2.ts
#	packages/swapper/src/swappers/RelaySwapper/constant.ts
#	packages/swapper/src/swappers/RelaySwapper/utils/relayTokenToAssetId.ts
#	packages/types/src/base.ts
#	packages/types/src/zerion.ts
#	packages/utils/src/assetData/baseAssets.ts
#	packages/utils/src/assetData/getBaseAsset.ts
#	packages/utils/src/chainIdToFeeAssetId.ts
#	packages/utils/src/getAssetNamespaceFromChainId.ts
#	packages/utils/src/getChainShortName.ts
#	packages/utils/src/getNativeFeeAssetReference.ts
#	public/generated/asset-manifest.json
#	public/generated/asset-manifest.json.br
#	public/generated/asset-manifest.json.gz
#	public/generated/generatedAssetData.json
#	public/generated/generatedAssetData.json.br
#	public/generated/generatedAssetData.json.gz
#	public/generated/relatedAssetIndex.json
#	public/generated/relatedAssetIndex.json.br
#	public/generated/relatedAssetIndex.json.gz
#	scripts/generateAssetData/coingecko.ts
#	scripts/generateAssetData/generateRelatedAssetIndex/generateChainRelatedAssetIndex.ts
#	scripts/generateAssetData/generateRelatedAssetIndex/generateRelatedAssetIndex.ts
#	src/components/TradeAssetSearch/hooks/useGetPopularAssetsQuery.tsx
#	src/config.ts
#	src/constants/chains.ts
#	src/context/PluginProvider/PluginProvider.tsx
#	src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx
#	src/hooks/useWalletSupportsChain/useWalletSupportsChain.ts
#	src/lib/account/evm.ts
#	src/lib/asset-service/service/AssetService.ts
#	src/lib/coingecko/utils.ts
#	src/lib/market-service/coingecko/coingecko.test.ts
#	src/pages/Markets/components/MarketsRow.tsx
#	src/plugins/activePlugins.ts
#	src/state/slices/opportunitiesSlice/mappings.ts
#	src/state/slices/portfolioSlice/utils/index.ts
#	src/state/slices/preferencesSlice/preferencesSlice.ts
#	src/test/mocks/store.ts
#	src/vite-env.d.ts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gomesalexandre gomesalexandre marked this pull request as ready for review February 21, 2026 12:01
@gomesalexandre gomesalexandre requested a review from a team as a code owner February 21, 2026 12:01
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

Caution

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

⚠️ Outside diff range comments (1)
packages/caip/src/constants.ts (1)

298-331: ⚠️ Potential issue | 🟡 Minor

modeAssetId is missing from FEE_ASSET_IDS.

modeAssetId is introduced in this PR but not appended to FEE_ASSET_IDS. Most other second-class EVM chains added in this series (monadAssetId, mantleAssetId, inkAssetId, megaethAssetId, lineaAssetId, berachainAssetId, scrollAssetId, sonicAssetId, unichainAssetId) are included. Any consumer that checks FEE_ASSET_IDS for Mode ETH (fee asset detection, trade/quote fee checks, portfolio display) will silently miss it.

🐛 Proposed fix
   unichainAssetId,
+  modeAssetId,
   solAssetId,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/caip/src/constants.ts` around lines 298 - 331, FEE_ASSET_IDS is
missing modeAssetId so Mode ETH won't be recognized for fee detection; update
the array FEE_ASSET_IDS to include modeAssetId alongside the other asset ids
(e.g., add modeAssetId near the other EVM-like entries such as monadAssetId,
mantleAssetId, inkAssetId) so consumers checking FEE_ASSET_IDS will correctly
detect Mode as a fee asset.
🧹 Nitpick comments (6)
.env (2)

168-168: Minor: VITE_MODE_NODE_URL key ordering flagged by dotenv-linter.

MODE sorts before MONAD alphabetically; VITE_MODE_NODE_URL should be placed before VITE_MONAD_NODE_URL (currently at line 156).

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

In @.env at line 168, Reorder the environment keys to satisfy dotenv-linter:
move the VITE_MODE_NODE_URL entry so it appears alphabetically before
VITE_MONAD_NODE_URL (i.e., place VITE_MODE_NODE_URL above VITE_MONAD_NODE_URL)
to correct the ordering issue flagged by dotenv-linter.

326-326: Minor: VITE_FEATURE_MODE key ordering flagged by dotenv-linter.

VITE_FEATURE_MODE should precede VITE_FEATURE_MONAD (currently at line 309).

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

In @.env at line 326, Move the environment variable line so that
VITE_FEATURE_MODE appears before VITE_FEATURE_MONAD in the .env file; update the
ordering by relocating the VITE_FEATURE_MODE entry (currently
"VITE_FEATURE_MODE=false") to a position above the existing VITE_FEATURE_MONAD
key to satisfy dotenv-linter ordering rules.
.env.development (2)

67-67: Optional: VITE_MODE_NODE_URL ordering

The linter flags this key as unordered — alphabetically MODE precedes MONAD. A quick reorder keeps the file consistent.

♻️ Proposed fix
+VITE_MODE_NODE_URL=https://mainnet.mode.network
 VITE_MONAD_NODE_URL=https://rpc.monad.xyz
 VITE_PLASMA_NODE_URL=https://rpc.plasma.to
 ...
 VITE_BOB_NODE_URL=https://rpc.gobob.xyz
-VITE_MODE_NODE_URL=https://mainnet.mode.network
 VITE_HYPEREVM_NODE_URL=https://rpc.hyperliquid.xyz/evm
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.env.development at line 67, The .env.development file has an unordered
environment key: VITE_MODE_NODE_URL is out of alphabetical order relative to
other keys (e.g., keys containing MONAD), causing the linter warning; reorder
the environment variables so that VITE_MODE_NODE_URL appears in its correct
alphabetical position among the VITE_* keys (i.e., place VITE_MODE_NODE_URL
before any VITE_MONAD_* entries) to satisfy the linter and keep the file
consistent.

118-118: Optional: VITE_FEATURE_MODE ordering

Same linter finding — MODE (M) should precede SCROLL (S).

♻️ Proposed fix
+VITE_FEATURE_MODE=true
 VITE_FEATURE_KATANA=true
 VITE_FEATURE_SONIC=true
 VITE_FEATURE_UNICHAIN=true
 VITE_FEATURE_BOB=true
-VITE_FEATURE_MODE=true
 VITE_FEATURE_TON=true
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.env.development at line 118, The env variable VITE_FEATURE_MODE is out of
alphabetical order (M should come before S); reorder the .env.development
entries so the line defining VITE_FEATURE_MODE appears before any variables
starting with "VITE_FEATURE_SCROLL" (or other "S" keys) to satisfy the linter
and maintain consistent alphabetical ordering.
src/lib/utils/mode.ts (1)

15-43: getModeTransactionStatus creates a new JsonRpcProvider on every poll invocation.

This function is called in a polling loop (useSendActionSubscriber.tsx). Constructing a fresh JsonRpcProvider per call allocates a new HTTP connection pool each time, even with staticNetwork: true. Other parts of the project use provider singletons (see packages/contracts/src/ethersProviderSingleton.ts). Consider a module-level singleton keyed on nodeUrl:

♻️ Suggested refactor
+const modeProviders = new Map<string, JsonRpcProvider>()
+
+const getModeProvider = (nodeUrl: string): JsonRpcProvider => {
+  const existing = modeProviders.get(nodeUrl)
+  if (existing) return existing
+  const provider = new JsonRpcProvider(nodeUrl, undefined, { staticNetwork: true })
+  modeProviders.set(nodeUrl, provider)
+  return provider
+}
+
 export const getModeTransactionStatus = async (
   txHash: string,
   nodeUrl: string,
 ): Promise<TxStatus> => {
   try {
-    const provider = new JsonRpcProvider(nodeUrl, undefined, {
-      staticNetwork: true,
-    })
-
+    const provider = getModeProvider(nodeUrl)
     const receipt = await provider.getTransactionReceipt(txHash)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/utils/mode.ts` around lines 15 - 43, getModeTransactionStatus
currently constructs a new JsonRpcProvider on every call which creates repeated
connection pools; change it to reuse a module-level provider cache keyed by
nodeUrl (e.g., add a getProvider(nodeUrl) that returns an existing
JsonRpcProvider or constructs-and-caches one with staticNetwork: true) and
update getModeTransactionStatus to call getProvider(nodeUrl) instead of new
JsonRpcProvider(...). Ensure the cached provider is shared across calls and
retain existing behavior for receipt handling and error fallback to
TxStatus.Unknown; you can reference existing patterns like
ethersProviderSingleton for implementation guidance.
src/plugins/mode/index.tsx (1)

22-36: Minor: fromAssetId called twice per asset in getKnownTokens.

The filter step calls fromAssetId(asset.assetId) and the map step calls it again. A combined reduce (or destructuring the result inside filter into a variable) would avoid the double parse.

♻️ Proposed refactor
-                const getKnownTokens = () => {
-                  const assetService = getAssetService()
-                  return assetService.assets
-                    .filter(asset => {
-                      const { chainId, assetNamespace } = fromAssetId(asset.assetId)
-                      return chainId === modeChainId && 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<ReturnType<typeof getKnownTokens>>((acc, asset) => {
+                    const { chainId, assetNamespace, assetReference } = fromAssetId(asset.assetId)
+                    if (chainId === modeChainId && 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/mode/index.tsx` around lines 22 - 36, getKnownTokens currently
calls fromAssetId(asset.assetId) twice per asset (once in the filter and again
in the map); change the implementation so fromAssetId is invoked only once per
asset by extracting its result into a variable and reusing it (e.g., use a
single reduce or map that checks chainId === modeChainId and assetNamespace ===
'erc20' while building the returned object), updating getKnownTokens to
reference the parsed result rather than calling fromAssetId again; keep
references to assetService.assets and modeChainId intact.
🤖 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/swapper/src/swappers/RelaySwapper/constant.ts`:
- Line 46: The import of mode from viem/chains will fail against the pinned viem
2.43.5; either update the viem dependency to >=2.46.0 so mode is exported, or
stop importing mode and instead define a local chain object using defineChain
(mirroring the hardcoded approach used for megaethChainId) and replace uses of
mode with that new chain symbol; update the import list in constant.ts (remove
mode) and add the locally defined chain constant before it is referenced.

---

Outside diff comments:
In `@packages/caip/src/constants.ts`:
- Around line 298-331: FEE_ASSET_IDS is missing modeAssetId so Mode ETH won't be
recognized for fee detection; update the array FEE_ASSET_IDS to include
modeAssetId alongside the other asset ids (e.g., add modeAssetId near the other
EVM-like entries such as monadAssetId, mantleAssetId, inkAssetId) so consumers
checking FEE_ASSET_IDS will correctly detect Mode as a fee asset.

---

Nitpick comments:
In @.env:
- Line 168: Reorder the environment keys to satisfy dotenv-linter: move the
VITE_MODE_NODE_URL entry so it appears alphabetically before VITE_MONAD_NODE_URL
(i.e., place VITE_MODE_NODE_URL above VITE_MONAD_NODE_URL) to correct the
ordering issue flagged by dotenv-linter.
- Line 326: Move the environment variable line so that VITE_FEATURE_MODE appears
before VITE_FEATURE_MONAD in the .env file; update the ordering by relocating
the VITE_FEATURE_MODE entry (currently "VITE_FEATURE_MODE=false") to a position
above the existing VITE_FEATURE_MONAD key to satisfy dotenv-linter ordering
rules.

In @.env.development:
- Line 67: The .env.development file has an unordered environment key:
VITE_MODE_NODE_URL is out of alphabetical order relative to other keys (e.g.,
keys containing MONAD), causing the linter warning; reorder the environment
variables so that VITE_MODE_NODE_URL appears in its correct alphabetical
position among the VITE_* keys (i.e., place VITE_MODE_NODE_URL before any
VITE_MONAD_* entries) to satisfy the linter and keep the file consistent.
- Line 118: The env variable VITE_FEATURE_MODE is out of alphabetical order (M
should come before S); reorder the .env.development entries so the line defining
VITE_FEATURE_MODE appears before any variables starting with
"VITE_FEATURE_SCROLL" (or other "S" keys) to satisfy the linter and maintain
consistent alphabetical ordering.

In `@src/lib/utils/mode.ts`:
- Around line 15-43: getModeTransactionStatus currently constructs a new
JsonRpcProvider on every call which creates repeated connection pools; change it
to reuse a module-level provider cache keyed by nodeUrl (e.g., add a
getProvider(nodeUrl) that returns an existing JsonRpcProvider or
constructs-and-caches one with staticNetwork: true) and update
getModeTransactionStatus to call getProvider(nodeUrl) instead of new
JsonRpcProvider(...). Ensure the cached provider is shared across calls and
retain existing behavior for receipt handling and error fallback to
TxStatus.Unknown; you can reference existing patterns like
ethersProviderSingleton for implementation guidance.

In `@src/plugins/mode/index.tsx`:
- Around line 22-36: getKnownTokens currently calls fromAssetId(asset.assetId)
twice per asset (once in the filter and again in the map); change the
implementation so fromAssetId is invoked only once per asset by extracting its
result into a variable and reusing it (e.g., use a single reduce or map that
checks chainId === modeChainId and assetNamespace === 'erc20' while building the
returned object), updating getKnownTokens to reference the parsed result rather
than calling fromAssetId again; keep references to assetService.assets and
modeChainId intact.

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.

lgtm - all CI green, contract review done.

prior testing confirmed on Mode (native ETH balance, relay bridge quotes, chain selector). will re-verify on Soneium as final chain in the pipeline.

merge conflicts with develop (cronos+sonic+unichain+bob) resolved cleanly - migration 299 added, related asset index updated with modeAssetId in ethAssetId group, market service test counts bumped (flatten=12, rate limited=11).

re: coderabbit viem concern - mode export confirmed in viem/chains (id: 34443, name: Mode Mainnet).

@gomesalexandre gomesalexandre merged commit 46ac090 into develop Feb 21, 2026
6 checks passed
@gomesalexandre gomesalexandre deleted the feat/integrate-mode-relay branch February 21, 2026 12:13
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