Skip to content

feat: add RPC fallback resilience for unchained outages#12017

Merged
kaladinlight merged 13 commits intodevelopfrom
feat/rpc-fallback-resilience
Mar 14, 2026
Merged

feat: add RPC fallback resilience for unchained outages#12017
kaladinlight merged 13 commits intodevelopfrom
feat/rpc-fallback-resilience

Conversation

@0xApotheosis
Copy link
Member

@0xApotheosis 0xApotheosis commented Feb 24, 2026

Description

When unchained's MoralisService returns 503 errors, all first-class EVM chains break because their VITE_*_NODE_URL env vars point to unchained's /api/v1/jsonrpc proxy. This PR adds public fallback RPCs at both the viem transport layer and the chain adapter layer so the app degrades gracefully instead of failing completely.

Three layers of change:

  1. viemClient.ts — Added FALLBACK_RPC_URLS constants and createFallbackTransport() helper. All 32 EVM chain viem clients now have public fallback RPCs (LlamaRPC, official chain RPCs). Previously only ETH, BSC, and Base had any.

  2. EvmBaseAdapter.ts — Added fallback paths for getAccount(), broadcastTransaction(), and getGasFeeData() that route through the viem client (which now has public fallback transports) when unchained fails. Token balances and tx history gracefully degrade to empty during outage.

  3. CSP connect-src — Created headers/csps/chains/fallbackRpcUrls.ts as a shared constants file. All 32 chain CSP configs now import and spread fallback RPC origins from this file.

Issue (if applicable)

Risk

Medium — Adds fallback network paths but does not modify any happy-path behavior. When unchained is healthy, no change in behavior. Fallbacks only activate on unchained failure.

Affects all first-class EVM chain adapters (ETH, AVAX, MATIC, ARB, OP, BSC, GNOSIS, BASE) and all second-class EVM chains. No new on-chain transactions or contract interactions introduced — fallback uses the same RPC calls that unchained proxies.

Testing

Engineering

  1. To simulate an unchained outage, temporarily set a first-class chain's node URL to a failing endpoint in .env:
    VITE_ETHEREUM_NODE_URL=https://httpstat.us/503
    
  2. yarn dev and connect a wallet with ETH
  3. Verify on this branch: Native ETH balance loads, console shows Unchained getAccount failed for eip155:1, falling back to direct RPC
  4. Verify on develop: Balance fails to load, no fallback
  5. Optionally test broadcast and fee estimation with the same broken URL
  6. Restore the env var and confirm normal behavior is unchanged

Operations

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

This is infrastructure resilience — no user-facing UI changes. When unchained is healthy, behavior is identical. When unchained is down, users will see native balances (but not token balances) and can still send transactions, vs a completely broken experience today.

Screenshots (if applicable)

N/A — no UI changes

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added unified fallback RPC endpoint support across all supported blockchains for automatic failover.
  • Improvements

    • More reliable transaction handling with additional fallback paths and error recovery.
    • Updated RPC configurations for improved connectivity and performance.
    • Security headers (CSP) expanded to include new trusted RPC sources for updated infrastructure.

When unchained's RPC proxy returns 503s, first-class EVM chains lose all
functionality. This adds public fallback RPCs so the app degrades
gracefully instead of breaking completely.

- Add FALLBACK_RPC_URLS constants and public fallback endpoints for all
  32 EVM chains in viemClient.ts (viem transport layer)
- Add EvmBaseAdapter fallback for getAccount, broadcastTransaction, and
  getGasFeeData that routes through the viem client when unchained fails
- Add CSP connect-src entries for all fallback RPC origins via a shared
  fallbackRpcUrls.ts constants file

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 24, 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

Centralizes fallback RPC URLs into a new FALLBACK_RPC_URLS export, updates viem client transports to use those fallbacks, extends CSP connect-src lists across ~35 chain files, and refactors EVM adapters/tests to use Viem PublicClient with direct-RPC fallbacks on HTTP failures.

Changes

Cohort / File(s) Summary
Fallback RPC constant & exports
packages/contracts/src/fallbackRpcUrls.ts, packages/contracts/src/index.ts
Adds exported FALLBACK_RPC_URLS mapping chains → fallback URL arrays and re-exports it from the contracts barrel.
Viem client transports
packages/contracts/src/viemClient.ts
Introduces createFallbackTransport and replaces inline transports with env + FALLBACK_RPC_URLS.* fallbacks for viem public clients.
CSP chain configs
headers/csps/chains/...
headers/csps/chains/arbitrum.ts, .../avalanche.ts, .../base.ts, .../berachain.ts, .../blast.ts, .../bnbsmartchain.ts, .../bob.ts, .../celo.ts, .../cronos.ts, .../ethereum.ts, .../flowEvm.ts, .../gnosis.ts, .../hemi.ts, .../hyperevm.ts, .../ink.ts, .../katana.ts, .../linea.ts, .../mantle.ts, .../megaeth.ts, .../mode.ts, .../monad.ts, .../optimism.ts, .../plasma.ts, .../plume.ts, .../polygon.ts, .../scroll.ts, .../soneium.ts, .../sonic.ts, .../story.ts, .../unichain.ts, .../worldchain.ts, .../zksyncera.ts
Each file imports FALLBACK_RPC_URLS and appends the relevant ...FALLBACK_RPC_URLS.<chain> entries into CSP connect-src arrays (some keep env node URLs plus fallbacks).
EVM adapter: EvmBaseAdapter
packages/chain-adapters/src/evm/EvmBaseAdapter.ts
Adds Viem client imports and private helpers (getAccountFallback, getGasFeeDataFallback); augments getAccount, getGasFeeData, getFeeData, and broadcast with Viem direct-RPC fallback paths and console.warn logs.
EVM adapter: SecondClassEvmAdapter
packages/chain-adapters/src/evm/SecondClassEvmAdapter.ts
Large refactor replacing ethers JsonRpcProvider + multicall/ERC20 interface with Viem PublicClient. Rewires transaction, balance, token, gas estimation, broadcast, multicall and block operations to Viem APIs; updates internal properties and error handling.
SecondClassEvmAdapter tests
packages/chain-adapters/src/evm/SecondClassEvmAdapter.test.ts
Tests updated to mock a Viem client (mockViemClient) and viem errors (e.g., TransactionReceiptNotFoundError); status mappings adjusted to Viem semantics.
Contracts constants removed
packages/contracts/src/constants.ts
Removes exported MULTICALL3_CONTRACT constant.
Config & env updates
.env, src/config.ts
Environment URLs updated (many moved to drpc.org variants); three BNBSMARTCHAIN fallback env validators removed from src/config.ts.
sequenceDiagram
    participant Client
    participant Adapter as EVM Adapter
    participant HTTP as HTTP Endpoint
    participant Viem as Viem PublicClient
    participant RPC as Direct RPC

    Client->>Adapter: request (getAccount / sendTx / estimate)
    Adapter->>HTTP: attempt HTTP request
    HTTP-->>Adapter: fails/error
    Adapter->>Viem: call Viem client (getBalance/nonce/sendRawTx/estimateGas)
    Viem->>RPC: direct RPC transport (envUrl + FALLBACK_RPC_URLS)
    RPC-->>Viem: response (balance/tx/hash/fees)
    Viem-->>Adapter: result
    Adapter-->>Client: return fallback result
    Note over Adapter: console.warn emitted when falling back
Loading

🎯 4 (Complex) | ⏱️ ~75 minutes

🐰 I sniffed the nets for extra links,
Added backups so nothing sinks.
From HTTP slips to Viem's grace,
Fallbacks hop to take their place.
Thirty-five chains now safer bound—hooray, backup hops abound! 🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: add RPC fallback resilience for unchained outages' accurately describes the primary change: adding fallback RPC routing to handle unchained service failures.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ 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/rpc-fallback-resilience
📝 Coding Plan
  • Generate coding plan for human review comments

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.

Copy link
Collaborator

@NeOMakinG NeOMakinG left a comment

Choose a reason for hiding this comment

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

LGTM — Important resilience improvement

Changes (35 files):

  1. fallbackRpcUrls.ts — Centralized fallback RPC URLs for all 32 EVM chains
  2. viemClient.tscreateFallbackTransport() helper wraps primary + fallback RPCs
  3. EvmBaseAdapter.ts — Fallback paths for getAccount(), broadcastTransaction(), etc.
  4. CSP headers — All fallback URLs added to chain CSP files

Why this matters:

  • When unchained's MoralisService returns 503, the app no longer breaks completely
  • Graceful degradation to public RPCs (LlamaRPC, official chain RPCs)
  • Every EVM chain now has at least one fallback

CI passes ✅


🤖 Reviewed by Claude Code

@NeOMakinG
Copy link
Collaborator

🤖 QABot Test Report

1/1 tests passed

Test Status
Code Review (RPC fallback) ✅ Passed

Verified: Fallback RPC URLs added for all 32 EVM chains, createFallbackTransport helper works.

📊 Full Report: https://qabot-kappa.vercel.app/runs/4d89df7b-ae3a-4cb0-b95f-622ef0024ded


🤖 Automated QA by Claude Code

@kaladinlight kaladinlight marked this pull request as ready for review March 13, 2026 17:38
@kaladinlight kaladinlight requested a review from a team as a code owner March 13, 2026 17:38
@kaladinlight kaladinlight enabled auto-merge (squash) March 13, 2026 17:38
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 (1)
packages/chain-adapters/src/evm/EvmBaseAdapter.ts (1)

646-648: Use structured logger instead of console.warn in fallback paths.

These warnings should go through the project logger with context fields (chainId, operation, primary error, fallback status) for observability consistency.

As per coding guidelines "ALWAYS log errors for debugging using structured logging with relevant context and error metadata".

Also applies to: 746-748, 991-993

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

In `@packages/chain-adapters/src/evm/EvmBaseAdapter.ts` around lines 646 - 648,
Replace the direct console.warn calls in EvmBaseAdapter.ts fallback paths with
the adapter's structured logger (e.g., this.logger.warn) and include contextual
fields: chainId (this.chainId), operation (e.g., "getAccount"), primaryError
(the caught error variable), and fallback="true"; specifically update the
warning before calling getAccountFallback(pubkey, viemClient) and the similar
calls at the other locations (around the code at the other fallback sites) so
the log message reads a concise descriptive string plus the structured context
and the original error metadata.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@headers/csps/chains/bnbsmartchain.ts`:
- Line 17: The CSP connect-src list is missing two BSC fallback endpoints used
by the BscChainAdapter broadcast fallback; update the connect-src directive to
include the same hosts as FALLBACK_RPC_URLS.bsc (add
https://bsc-dataseed.binance.org and https://bsc-dataseed1.ninicoin.io) or
replace the current entries with a consolidated set derived from
FALLBACK_RPC_URLS.bsc so the adapter's fallback calls are not blocked; ensure
the change aligns with the CSP declaration that references the BscChainAdapter
broadcast logic and FALLBACK_RPC_URLS.bsc.

---

Nitpick comments:
In `@packages/chain-adapters/src/evm/EvmBaseAdapter.ts`:
- Around line 646-648: Replace the direct console.warn calls in
EvmBaseAdapter.ts fallback paths with the adapter's structured logger (e.g.,
this.logger.warn) and include contextual fields: chainId (this.chainId),
operation (e.g., "getAccount"), primaryError (the caught error variable), and
fallback="true"; specifically update the warning before calling
getAccountFallback(pubkey, viemClient) and the similar calls at the other
locations (around the code at the other fallback sites) so the log message reads
a concise descriptive string plus the structured context and the original error
metadata.
🪄 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: 88b7a4e7-20d6-45da-b65e-70af86f3c151

📥 Commits

Reviewing files that changed from the base of the PR and between ff0aa68 and 35b8765.

📒 Files selected for processing (36)
  • headers/csps/chains/arbitrum.ts
  • headers/csps/chains/avalanche.ts
  • headers/csps/chains/base.ts
  • headers/csps/chains/berachain.ts
  • headers/csps/chains/blast.ts
  • headers/csps/chains/bnbsmartchain.ts
  • headers/csps/chains/bob.ts
  • headers/csps/chains/celo.ts
  • headers/csps/chains/cronos.ts
  • headers/csps/chains/ethereum.ts
  • headers/csps/chains/flowEvm.ts
  • headers/csps/chains/gnosis.ts
  • headers/csps/chains/hemi.ts
  • headers/csps/chains/hyperevm.ts
  • headers/csps/chains/ink.ts
  • headers/csps/chains/katana.ts
  • headers/csps/chains/linea.ts
  • headers/csps/chains/mantle.ts
  • headers/csps/chains/megaeth.ts
  • headers/csps/chains/mode.ts
  • headers/csps/chains/monad.ts
  • headers/csps/chains/optimism.ts
  • headers/csps/chains/plasma.ts
  • headers/csps/chains/plume.ts
  • headers/csps/chains/polygon.ts
  • headers/csps/chains/scroll.ts
  • headers/csps/chains/soneium.ts
  • headers/csps/chains/sonic.ts
  • headers/csps/chains/story.ts
  • headers/csps/chains/unichain.ts
  • headers/csps/chains/worldchain.ts
  • headers/csps/chains/zksyncera.ts
  • packages/chain-adapters/src/evm/EvmBaseAdapter.ts
  • packages/contracts/src/fallbackRpcUrls.ts
  • packages/contracts/src/index.ts
  • packages/contracts/src/viemClient.ts

@kaladinlight kaladinlight disabled auto-merge March 13, 2026 18:16
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 (2)
.env (1)

156-180: Static analysis: Environment variable ordering.

The static analysis tool flags these variables as not being in alphabetical order. While this is a low-priority cosmetic issue and doesn't affect functionality, maintaining alphabetical order can improve maintainability for large .env files.

Given the "Chill" review mode, this is optional to address now or defer to a future cleanup PR.

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

In @.env around lines 156 - 180, The .env entries are not alphabetically
ordered; to fix, reorder the VITE_* node URL variables into strict alphabetical
order (for example ensure BOB, BERACHAIN, BLAST, CELO, ETHEREAL, FLOWEVM, HEMI,
etc. appear in A–Z order) by sorting the keys like VITE_BERACHAIN_NODE_URL,
VITE_BLAST_NODE_URL, VITE_BOB_NODE_URL, VITE_CELO_NODE_URL,
VITE_ETHEREAL_NODE_URL, VITE_FLOWEVM_NODE_URL, VITE_HEMI_NODE_URL,
VITE_HYPEREVM_NODE_URL, VITE_INK_NODE_URL, VITE_KATANA_NODE_URL,
VITE_LINEA_NODE_URL, VITE_MEGAETH_NODE_URL, VITE_MODE_NODE_URL,
VITE_MONAD_NODE_URL, VITE_MANTLE_NODE_URL, VITE_PLASMA_NODE_URL,
VITE_PLUME_NODE_URL, VITE_SCROLL_NODE_URL, VITE_SONEIUM_NODE_URL,
VITE_SONIC_NODE_URL, VITE_STORY_NODE_URL, VITE_UNICHAIN_NODE_URL,
VITE_WORLDCHAIN_NODE_URL, VITE_ZKSYNC_ERA_NODE_URL so the file is consistently
ordered for maintainability.
packages/chain-adapters/src/evm/SecondClassEvmAdapter.ts (1)

122-122: Use a project error class instead of throwing a raw Error.

Prefer a custom error from @shapeshiftoss/errors with code/details so failures are consistently typed and localizable.
As per coding guidelines "ALWAYS use custom error classes from @shapeshiftoss/errors with meaningful error codes for internationalization and relevant details in error objects".

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

In `@packages/chain-adapters/src/evm/SecondClassEvmAdapter.ts` at line 122,
Replace the raw Error thrown when viemClient is missing with a custom error from
`@shapeshiftoss/errors`: locate the check in SecondClassEvmAdapter (the line that
reads if (!viemClient) throw new Error(...)) and throw an instance of the
project error class (e.g., new Problem or a similar exported custom error)
including a meaningful error code and a details object that contains the chainId
(args.chainId) and context ("No viem client found for chainId"). Ensure you
import the chosen error class from "@shapeshiftoss/errors" at the top of the
file and use it consistently so failures are typed and localizable.
🤖 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/chain-adapters/src/evm/SecondClassEvmAdapter.ts`:
- Around line 313-325: The current parallel call to
viemClient.estimateFeesPerGas causes Promise.all to fail on chains that only
support legacy or only EIP-1559 and also calls .toString() on possibly undefined
fields; update the logic in SecondClassEvmAdapter to attempt EIP-1559 first (via
this.requestQueue.add(() => this.viemClient.estimateFeesPerGas({ type:
'eip1559', ... }))) and if it throws, catch and fallback to a legacy estimate,
and vice-versa if you prefer trying legacy first for compatibility; ensure you
only call .toString() after checking the field is defined (e.g., gasPrice,
maxFeePerGas, maxPriorityFeePerGas) and map missing fields to null/undefined or
appropriate fallback values when constructing the GasFeeData object so the
adapter tolerates legacy-only and EIP-1559-only chains while using
this.requestQueue and this.viemClient identifiers from the diff.
- Around line 440-441: Replace the unsafe "as any" on the debug_traceTransaction
call in SecondClassEvmAdapter by casting the request result to unknown,
introduce a CallTraceResponse type describing { value?, from?, to?, calls? } and
a type guard isCallTraceResponse(val: unknown): val is CallTraceResponse that
checks it's a non-null object (and optionally checks keys/types), then call
this.viemClient.request(...) inside requestQueue.add, cast its result to
unknown, and only pass the value into your existing extraction logic (e.g.,
extractCalls or whatever processes the trace) after narrowing with
isCallTraceResponse to safely access value/from/to/calls. Ensure you update
references to the debug_traceTransaction params typing (the object passed to
viemClient.request) to a concrete shape rather than using any.

---

Nitpick comments:
In @.env:
- Around line 156-180: The .env entries are not alphabetically ordered; to fix,
reorder the VITE_* node URL variables into strict alphabetical order (for
example ensure BOB, BERACHAIN, BLAST, CELO, ETHEREAL, FLOWEVM, HEMI, etc. appear
in A–Z order) by sorting the keys like VITE_BERACHAIN_NODE_URL,
VITE_BLAST_NODE_URL, VITE_BOB_NODE_URL, VITE_CELO_NODE_URL,
VITE_ETHEREAL_NODE_URL, VITE_FLOWEVM_NODE_URL, VITE_HEMI_NODE_URL,
VITE_HYPEREVM_NODE_URL, VITE_INK_NODE_URL, VITE_KATANA_NODE_URL,
VITE_LINEA_NODE_URL, VITE_MEGAETH_NODE_URL, VITE_MODE_NODE_URL,
VITE_MONAD_NODE_URL, VITE_MANTLE_NODE_URL, VITE_PLASMA_NODE_URL,
VITE_PLUME_NODE_URL, VITE_SCROLL_NODE_URL, VITE_SONEIUM_NODE_URL,
VITE_SONIC_NODE_URL, VITE_STORY_NODE_URL, VITE_UNICHAIN_NODE_URL,
VITE_WORLDCHAIN_NODE_URL, VITE_ZKSYNC_ERA_NODE_URL so the file is consistently
ordered for maintainability.

In `@packages/chain-adapters/src/evm/SecondClassEvmAdapter.ts`:
- Line 122: Replace the raw Error thrown when viemClient is missing with a
custom error from `@shapeshiftoss/errors`: locate the check in
SecondClassEvmAdapter (the line that reads if (!viemClient) throw new
Error(...)) and throw an instance of the project error class (e.g., new Problem
or a similar exported custom error) including a meaningful error code and a
details object that contains the chainId (args.chainId) and context ("No viem
client found for chainId"). Ensure you import the chosen error class from
"@shapeshiftoss/errors" at the top of the file and use it consistently so
failures are typed and localizable.
🪄 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: 08340400-257f-49af-ac20-959f83fa1209

📥 Commits

Reviewing files that changed from the base of the PR and between f0c25fe and efaf1e6.

📒 Files selected for processing (5)
  • .env
  • .env.development
  • packages/chain-adapters/src/evm/SecondClassEvmAdapter.test.ts
  • packages/chain-adapters/src/evm/SecondClassEvmAdapter.ts
  • packages/contracts/src/constants.ts
💤 Files with no reviewable changes (1)
  • packages/contracts/src/constants.ts

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

🤖 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/chain-adapters/src/evm/EvmBaseAdapter.ts`:
- Around line 645-649: The getAccount path currently returns raw viem errors
when viemClient exists because getAccountFallback(pubkey, viemClient) is called
directly; wrap the fallback call in the adapter's ErrorHandler translation so
failures are normalized into the adapter's getAccount error shape. Specifically,
in the getAccount method replace the direct return of getAccountFallback with
invoking the same error-normalizing logic used elsewhere (e.g., call
ErrorHandler.translate or the adapter's existing error wrapper) around
getAccountFallback(pubkey, viemClient) so any thrown viem errors are caught and
rethrown/returned as the adapter's standardized getAccount error. Ensure you
reference getAccount, getAccountFallback, and ErrorHandler in the change.
- Around line 1032-1036: The fallback gas estimation calls
viemClient.estimateGas using value: BigInt(estimateGasBody.value) which throws
if estimateGasBody.value is undefined; update the call (and any similar usages
in EvmBaseAdapter.buildEstimateGasBody) to guard the conversion like in
SecondClassEvmAdapter (e.g., use estimateGasBody.value ?
BigInt(estimateGasBody.value) : undefined) so value is only converted when
present before passing to viemClient.estimateGas.
🪄 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: 9e253f6b-051a-403b-86f9-da6c6ebdd15a

📥 Commits

Reviewing files that changed from the base of the PR and between efaf1e6 and 578367d.

📒 Files selected for processing (2)
  • packages/chain-adapters/src/evm/EvmBaseAdapter.ts
  • packages/chain-adapters/src/evm/SecondClassEvmAdapter.ts

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/chain-adapters/src/evm/EvmBaseAdapter.ts (2)

977-977: Limit helper visibility to private to avoid API surface creep.

getGasFeeDataFallback appears internal-only; making it private keeps the class contract tighter and reduces accidental external use.

🔧 Suggested change
-  async getGasFeeDataFallback(viemClient: PublicClient): Promise<GasFeeDataEstimate> {
+  private async getGasFeeDataFallback(viemClient: PublicClient): Promise<GasFeeDataEstimate> {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/chain-adapters/src/evm/EvmBaseAdapter.ts` at line 977, The method
getGasFeeDataFallback on EvmBaseAdapter is intended for internal use but is
declared public; change its visibility to private to prevent API surface creep.
Locate the getGasFeeDataFallback(viemClient: PublicClient):
Promise<GasFeeDataEstimate> declaration in the EvmBaseAdapter class and update
the modifier to private, ensuring any internal callers within the class still
compile; if there are external references, refactor those call sites to use a
new public wrapper or move callers inside the class.

654-655: Use structured logging for fallback warnings (include error metadata).

These fallback logs are plain strings and drop error context. Prefer structured logger fields (e.g., chainId, operation, original error) so outage diagnostics are queryable.

As per coding guidelines "ALWAYS log errors for debugging using structured logging with relevant context and error metadata".

Also applies to: 754-756, 1012-1014, 1035-1037

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

In `@packages/chain-adapters/src/evm/EvmBaseAdapter.ts` around lines 654 - 655,
Replace the plain console.warn fallback messages in EvmBaseAdapter (the one
before calling getAccountFallback(pubkey, viemClient) and the other similar
fallback sites) with structured logger calls that include the chainId, operation
name (e.g., "getAccount"), the fallback action ("direct RPC"), and the original
error object/stack as metadata; specifically, swap the console.warn usage for
the adapter's logger (e.g., this.logger.warn or this.logger.error depending on
severity) and pass a message plus an object like { chainId: this.chainId,
operation: 'getAccount', fallback: 'getAccountFallback', error } so diagnostics
are queryable, and apply the same pattern to the other fallback instances in
this class.
🤖 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/chain-adapters/src/evm/EvmBaseAdapter.ts`:
- Around line 1039-1044: The fallback estimateGas call in EvmBaseAdapter passes
estimateGasBody.data which can be an empty string; change the call to supply a
valid hex or omit data when empty by normalizing data before calling
viemClient.estimateGas (e.g., set const normalizedData = estimateGasBody.data &&
estimateGasBody.data !== '' ? estimateGasBody.data : '0x' or remove the data
field) and use normalizedData in the estimateGas invocation so
viemClient.estimateGas always receives a valid 0x-prefixed hex value.

---

Nitpick comments:
In `@packages/chain-adapters/src/evm/EvmBaseAdapter.ts`:
- Line 977: The method getGasFeeDataFallback on EvmBaseAdapter is intended for
internal use but is declared public; change its visibility to private to prevent
API surface creep. Locate the getGasFeeDataFallback(viemClient: PublicClient):
Promise<GasFeeDataEstimate> declaration in the EvmBaseAdapter class and update
the modifier to private, ensuring any internal callers within the class still
compile; if there are external references, refactor those call sites to use a
new public wrapper or move callers inside the class.
- Around line 654-655: Replace the plain console.warn fallback messages in
EvmBaseAdapter (the one before calling getAccountFallback(pubkey, viemClient)
and the other similar fallback sites) with structured logger calls that include
the chainId, operation name (e.g., "getAccount"), the fallback action ("direct
RPC"), and the original error object/stack as metadata; specifically, swap the
console.warn usage for the adapter's logger (e.g., this.logger.warn or
this.logger.error depending on severity) and pass a message plus an object like
{ chainId: this.chainId, operation: 'getAccount', fallback:
'getAccountFallback', error } so diagnostics are queryable, and apply the same
pattern to the other fallback instances in this class.
🪄 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: b9562440-e0a6-4aa1-80f2-a0ee9a0639cb

📥 Commits

Reviewing files that changed from the base of the PR and between 578367d and b297809.

📒 Files selected for processing (1)
  • packages/chain-adapters/src/evm/EvmBaseAdapter.ts

@kaladinlight kaladinlight merged commit 25c5df9 into develop Mar 14, 2026
4 checks passed
@kaladinlight kaladinlight deleted the feat/rpc-fallback-resilience branch March 14, 2026 03:55
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.

3 participants