Skip to content

feat: abstract chain + addchain scaffolder#12186

Open
gomesalexandre wants to merge 8 commits intoshapeshift:developfrom
gomesalexandre:worktree-swirling-doodling-pie
Open

feat: abstract chain + addchain scaffolder#12186
gomesalexandre wants to merge 8 commits intoshapeshift:developfrom
gomesalexandre:worktree-swirling-doodling-pie

Conversation

@gomesalexandre
Copy link
Contributor

@gomesalexandre gomesalexandre commented Mar 17, 2026

Description

Two things in one:

  1. Abstract chain — adds Abstract (EVM, chain ID 2741, Pudgy Penguins' L2 on ZK Stack) as a second-class EVM chain behind VITE_FEATURE_ABSTRACT. Native asset is ETH, swapper support via Relay (~1-2s bridge and on-chain swap times). Tested end-to-end: bridge in, on-chain DEX swap (ETH→USDT on Abstract), notification center, balance polling.

  2. scripts/addChain/ scaffolder — automates ~80% of the second-class EVM chain integration points documented in .claude/contracts/second-class-evm-chain.md. Uses the TypeScript compiler API (zero new deps — typescript already installed) to locate insertion points via AST, then string-splices. Abstract is the reference config (chains/abstract.json).

Usage: npx tsx scripts/addChain/index.ts chains/<chain>.json

Scaffolder covers ~50 insertion points:

  • caip constants, KnownChainIds enum, chain adapter types
  • hdwallet support flags across all wallet implementations
  • viem client, fallback RPCs, ethers provider switch case
  • feature flags, CSP headers, plugin registration
  • Relay swapper chain mapping + relayTokenToAssetId switch
  • asset generator, coingecko adapter, popular assets, markets row
  • WalletConnect config, account derivation, portfolio utils

Append-only ordering via appendLineAfterLastPattern so running the scaffolder for chain B always inserts after chain A — no merge conflicts. Idempotent: safe to run twice.

Issue (if applicable)

closes #11980

Risk

Low — new chain behind feature flag, scaffolder is scripts-only (no runtime impact).

No new on-chain transactions introduced. Scaffolder runs at dev-time only.

Testing

Engineering

  1. Enable VITE_FEATURE_ABSTRACT=true in .env.development
  2. Start dev server: pnpm run dev
  3. Trade page → chain filter → Abstract appears
  4. ETH on Abstract shows as popular asset when filtered
  5. Bridge ETH → Abstract via Relay, confirm in ~2s
  6. On-Abstract DEX swap (ETH → USDT) via Relay, confirm in ~1s
  7. Notification center shows "Confirmed" for both

Scaffolder test: npx tsx scripts/addChain/index.ts chains/abstract.json (idempotent — no-ops on already-applied entries)

Operations

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

Screenshots (if applicable)

QA run (all 21 steps passed): https://qabot-kappa.vercel.app/runs/52fafd4b-483d-426f-aaa5-841c48c690cb

Summary by CodeRabbit

  • New Features

    • Adds support for the Abstract (ABS) network: wallet support, asset discovery, portfolio/markets UI, trading (including Relay swap routes) and a new plugin.
    • Adds a feature flag and node URL configuration to enable/disable Abstract.
  • Chores

    • Migration updates and asset/data wiring to include Abstract.
    • Adds CLI tooling and templates to scaffold new chain integrations and generate asset data.
  • Tests

    • New end-to-end fixture and unit test updates covering Abstract scenarios.

- add Abstract (EVM chain ID 2741) as second-class EVM chain behind VITE_FEATURE_ABSTRACT flag
- add scripts/addChain/ scaffolder to automate ~80% of second-class EVM chain integration points
- Abstract integrates via Relay swapper with ~1-2s bridge/swap times
- native asset: ETH, explorer: abscan.org, rpc: api.mainnet.abs.xyz

scaffolder covers:
- AST-based engine (typescript compiler API, zero new deps) for enum/object/array/switch insertions
- chain config JSON schema (chains/abstract.json as reference)
- codemods registry for ~50 insertion points across the codebase
- append-only ordering (appendLineAfterLastPattern) to avoid merge conflicts
- idempotency: safe to run twice

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 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

Adds Abstract (ABS, eip155:2741) as a second-class EVM chain across the repo: env/config, CAIP constants, chain adapter & plugin, viem/ethers clients, asset data and generation, CSP, HDWallet capability flags, WalletConnectV2 wiring, swapper mappings, feature flags, tests, and a new add-chain scaffolder.

Changes

Cohort / File(s) Summary
Env & Config
/.env, /.env.development, src/config.ts, src/vite-env.d.ts, package.json
Add VITE_ABSTRACT_NODE_URL and VITE_FEATURE_ABSTRACT env entries, validators, and an add-chain script.
Chain Metadata & CSP
chains/abstract.json, headers/csps/chains/abstract.ts
New chain metadata JSON and CSP module wired to env node URL + fallback RPCs.
Clients & RPCs
packages/contracts/src/viemClient.ts, packages/contracts/src/ethersProviderSingleton.ts, packages/contracts/src/fallbackRpcUrls.ts
Create viem public client for Abstract, add ethers RPC case, and add Abstract fallback RPC URLs.
CAIP, Asset IDs & Coingecko
packages/caip/src/constants.ts, packages/caip/src/adapters/coingecko/*, packages/caip/src/adapters/coingecko/utils.ts
Add abstractChainId/abstractAssetId, Coingecko platform enum entry and mappings, and test updates.
Chain Adapter & Types
packages/chain-adapters/src/evm/..., packages/chain-adapters/src/types.ts
Add Abstract ChainAdapter, re-exports, EVM base adapter wiring, and type mappings for AbstractMainnet.
HDWallet Flags & Guards
packages/hdwallet-*/src/*, packages/hdwallet-core/src/{ethereum,wallet}.ts
Add _supportsAbstract flags across wallet implementations and supportsAbstract guard; update ETHWallet interface.
Swapper & Relay
packages/swapper/src/swappers/...
Map abstractChainId to Relay chain id and extend native-asset handling for Abstract.
Asset Data & Utilities
packages/utils/src/assetData/*, packages/utils/src/*, src/lib/...
Add abstract base asset, wire Abstract into utilities (fee asset, namespace, short name, getBaseAsset), asset-service and coingecko wiring, and feature-gated filtering.
Plugins & Runtime
src/plugins/abstract/index.tsx, src/plugins/activePlugins.ts, src/context/..., src/hooks/..., src/pages/...
New plugin registration and activation, WalletConnectV2 optional chain + RPC mapping, feature-flag gates, wallet-support checks, and UI guards.
Asset Generation, Tests & E2E
scripts/generateAssetData/..., e2e/fixtures/abstract-chain.yaml, src/lib/market-service/coingecko/coingecko.test.ts
Add asset generator and coingecko handling for Abstract, e2e fixture, and updated tests.
Chain Scaffolder Tooling
scripts/addChain/*
Add large new scaffolder: schema, engine (AST/string helpers), codemods orchestration, templates, report, and CLI entry.
State & Misc
src/state/*, src/test/mocks/store.ts, src/state/slices/*
Add migration keys, opportunities mapping entry, portfolio labeling and wallet-support checks, initialize Abstract feature flag in preferences and mock store, and small state updates.

Sequence Diagram(s)

sequenceDiagram
    participant UI as UI / User
    participant Plugin as AbstractPlugin
    participant AssetSvc as AssetService
    participant Adapter as AbstractChainAdapter
    participant Viem as ViemClient
    participant Relay as RelaySwapper

    UI->>Plugin: app boot -> register(VITE_ABSTRACT_NODE_URL)
    Plugin->>AssetSvc: getKnownTokens(abstractChainId)
    AssetSvc-->>Plugin: token list
    Plugin->>Adapter: new ChainAdapter(rpcUrl, getKnownTokens)
    Adapter->>Viem: createPublicClient(transport using VITE_ABSTRACT_NODE_URL + fallbacks)
    UI->>Adapter: buildTx / requestQuote
    Adapter->>Relay: request route (relayChainId 2741)
    Relay-->>UI: route / quote
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • NeOMakinG

Poem

"I hopped through code with twitchy nose and paw,
I planted RPCs and flags in neat little rows,
A plugin here, a CSP there — carrots for the night 🥕,
Abstract joins the ledger, shining bright,
Hooray — swaps now skip across with delight!"

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 32.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: abstract chain + addchain scaffolder' clearly summarizes the main changes: adding Abstract chain support and introducing the addchain scaffolding tool.
Linked Issues check ✅ Passed The PR fully implements the scaffolder tool and Abstract chain integration as specified in #11980, automating ~80% of EVM chain integration with marker-based generation, templates, and configuration schema.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the Abstract chain and the addchain scaffolder as defined in #11980; no out-of-scope modifications detected.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
📝 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.

@gomesalexandre
Copy link
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 17, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@gomesalexandre gomesalexandre marked this pull request as ready for review March 17, 2026 20:13
@gomesalexandre gomesalexandre requested a review from a team as a code owner March 17, 2026 20:13
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: 7

Caution

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

⚠️ Outside diff range comments (1)
src/context/WalletProvider/WalletConnectV2/config.ts (1)

55-69: ⚠️ Potential issue | 🟠 Major

Gate Abstract in WalletConnect config too.

This now advertises chain 2741 in every WalletConnect session, even when the Abstract plugin is disabled. That makes dapps believe Abstract is supported and can route users into missing-adapter/request-handling paths instead of cleanly hiding the network.

💡 Minimal gating change
 const {
   VITE_WALLET_CONNECT_WALLET_PROJECT_ID,
   VITE_AVALANCHE_NODE_URL,
   VITE_OPTIMISM_NODE_URL,
   VITE_BNBSMARTCHAIN_NODE_URL,
   VITE_POLYGON_NODE_URL,
   VITE_GNOSIS_NODE_URL,
   VITE_ETHEREUM_NODE_URL,
   VITE_ARBITRUM_NODE_URL,
   VITE_BASE_NODE_URL,
   VITE_INK_NODE_URL,
   VITE_FLOWEVM_NODE_URL,
+  VITE_FEATURE_ABSTRACT,
   VITE_ABSTRACT_NODE_URL,
 } = getConfig()
 
 export const walletConnectV2OptionalChains: AtLeastOneViemChain = (() => {
   const optionalViemChains: ViemChain[] = [
     optimism,
     bsc,
     gnosis,
     polygon,
     avalanche,
     arbitrum,
     base,
     ink,
     flowEvmChain,
     sei,
-    abstract,
+    ...(VITE_FEATURE_ABSTRACT ? [abstract] : []),
   ]
   if (optionalViemChains.length === 0) throw new Error('Array must contain at least one element.')
   return optionalViemChains as AtLeastOneViemChain
 })()
 
 export const walletConnectV2ProviderConfig: EthereumProviderOptions = {
   ...
   rpcMap: {
     [CHAIN_REFERENCE.AvalancheCChain]: VITE_AVALANCHE_NODE_URL,
     [CHAIN_REFERENCE.OptimismMainnet]: VITE_OPTIMISM_NODE_URL,
     [CHAIN_REFERENCE.BnbSmartChainMainnet]: VITE_BNBSMARTCHAIN_NODE_URL,
     [CHAIN_REFERENCE.PolygonMainnet]: VITE_POLYGON_NODE_URL,
     [CHAIN_REFERENCE.GnosisMainnet]: VITE_GNOSIS_NODE_URL,
     [CHAIN_REFERENCE.EthereumMainnet]: VITE_ETHEREUM_NODE_URL,
     [CHAIN_REFERENCE.ArbitrumMainnet]: VITE_ARBITRUM_NODE_URL,
     [CHAIN_REFERENCE.BaseMainnet]: VITE_BASE_NODE_URL,
     [CHAIN_REFERENCE.InkMainnet]: VITE_INK_NODE_URL,
     [CHAIN_REFERENCE.FlowEvmMainnet]: VITE_FLOWEVM_NODE_URL,
-    [CHAIN_REFERENCE.AbstractMainnet]: VITE_ABSTRACT_NODE_URL,
+    ...(VITE_FEATURE_ABSTRACT
+      ? { [CHAIN_REFERENCE.AbstractMainnet]: VITE_ABSTRACT_NODE_URL }
+      : {}),
   },
 }

Also applies to: 80-93, 114-126

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

In `@src/context/WalletProvider/WalletConnectV2/config.ts` around lines 55 - 69,
The arrays (notably walletConnectV2OptionalChains) currently always include the
'abstract' chain, causing WalletConnect sessions to advertise chain 2741 even
when the Abstract plugin is disabled; change these static arrays to only include
the 'abstract' ViemChain conditionally by checking a runtime feature flag/config
(e.g., an existing enableAbstract or isAbstractPluginEnabled boolean) and
pushing/concat-ing the abstract chain only when that flag is true; apply the
same conditional inclusion to the other WalletConnect V2 chain arrays referenced
in this diff so Abstract is advertised only when the plugin is enabled.
🧹 Nitpick comments (2)
packages/contracts/src/fallbackRpcUrls.ts (1)

34-34: Consider adding official or alternative RPC endpoints for better resilience.

The Abstract chain currently has only one fallback URL. Multiple public RPC endpoints are available: the official https://api.mainnet.abs.xyz and dRPC's https://abstract.drpc.org. Adding one or both would improve reliability if any single endpoint becomes unavailable.

💡 Suggested improvement
-  abstract: ['https://rpc.ankr.com/abstract'],
+  abstract: ['https://api.mainnet.abs.xyz', 'https://abstract.drpc.org'],
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/contracts/src/fallbackRpcUrls.ts` at line 34, The 'abstract' entry
in the fallback RPC URLs array only contains a single endpoint; update the
exported fallbackRpcUrls object so the 'abstract' key's array includes
additional resilient endpoints (e.g., add "https://api.mainnet.abs.xyz" and/or
"https://abstract.drpc.org") alongside the existing
"https://rpc.ankr.com/abstract" in the file that defines fallbackRpcUrls (look
for the 'abstract' property in fallbackRpcUrls.ts) so consumers will have
multiple RPC options if one endpoint is down.
package.json (1)

42-42: Use pnpm exec tsx for consistency with other scripts.

All other tsx-based scripts in this file use pnpm exec tsx (e.g., generate:chain, generate:asset-data, release). This script should follow the same pattern to ensure lockfile-pinned execution and consistency.

Suggested change
-    "add-chain": "npx tsx scripts/addChain/index.ts",
+    "add-chain": "pnpm exec tsx ./scripts/addChain/index.ts",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@package.json` at line 42, Update the add-chain package.json script to use the
same invocation style as other tsx scripts: replace the current "add-chain"
script that uses "npx tsx" with one that uses "pnpm exec tsx" so execution is
lockfile-pinned and consistent with scripts like "generate:chain" and "release".
🤖 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/types.ts`:
- Line 332: ChainSignTx is missing an entry for KnownChainIds.AbstractMainnet so
SignTx<KnownChainIds.AbstractMainnet> resolves to never; add a mapping for
KnownChainIds.AbstractMainnet to the appropriate signing type (e.g.,
evm.SignTxInput or whatever the repo uses for EVM-like chains) inside the
ChainSignTx union/map definition to mirror other chain-specific maps (like
ChainBuildTxInput and ChainSpecificAccount), updating the ChainSignTx type to
include [KnownChainIds.AbstractMainnet]: <appropriate sign type> so Abstract
chain signing works correctly.

In `@packages/hdwallet-walletconnectv2/src/walletconnectV2.ts`:
- Line 228: WalletConnectV2 advertises Abstract support via readonly
_supportsAbstract = true but WalletConnectV2WalletInfo.ethSupportsNetwork()
omits chainId 2741, causing ethSupportsNetwork (and
WalletConnectV2HDWallet.ethSupportsNetwork() which delegates to it) to reject
Abstract; fix by adding chainId 2741 to the supported chains/logic inside
WalletConnectV2WalletInfo.ethSupportsNetwork() so that it returns true for 2741
(and ensure WalletConnectV2HDWallet.ethSupportsNetwork() continues to delegate
to that updated method).

In `@scripts/addChain/codemods.ts`:
- Around line 24-30: wrap currently treats a false return from the codemod
function as 'skipped', which hides anchor-miss failures; change wrap (the
function wrap(file: string, operation: string, fn: () => boolean)) so that when
fn() returns true it still returns status 'inserted', but when fn() returns
false it returns status 'error' with a clear message like "anchor not found" (or
similar) instead of 'skipped'; preserve the existing catch branch for thrown
errors and keep the returned object shape { file, operation, status, message? }
so callers/consumers can detect and surface anchor-miss failures from wrap.

In `@scripts/addChain/engine.ts`:
- Around line 160-179: The idempotency check in addNamedImport is brittle
because it uses a raw file string/idempotencyKeyForImport(importName,
modulePath) and can false-skip or duplicate imports; update the logic to use the
TS AST: parseSource and locate the ImportDeclaration for modulePath
(targetImport), then inspect its importClause.namedBindings to determine if the
specific ImportSpecifier (importName) already exists (avoid relying on a global
string search). If no ImportDeclaration exists, generate a new import and use an
idempotency marker that uniquely ties modulePath+importName; if a targetImport
exists and lacks the specifier, mutate the ImportDeclaration to append a new
ImportSpecifier (use TS factory helpers or rebuild the namedBindings) instead of
string insertion so formatting/duplicates are handled correctly; remove or
narrow the current file-wide idempotency check and ensure
idempotencyKeyForImport is scoped to modulePath+importName.

In `@scripts/addChain/report.ts`:
- Around line 80-84: The report currently only logs errors but doesn't cause a
non-zero exit; after runAllCodemods returns results and you call
printReport(results, config) in the main() function (in
scripts/addChain/index.ts), check results for any entries with status ===
'error' (e.g., results.some(r => r.status === 'error')) and call process.exit(1)
when true so CI fails on codemod errors; update main() to perform this
post-report check and exit with code 1 on any error statuses.

In `@scripts/addChain/schema.ts`:
- Around line 93-99: Validate dependent fields and reject empty-string
addresses: when processing the chain config object (c) ensure that if
swappers.relay.supported === true then swappers.relay.relayChainId is present
and non-empty (throw a clear Error mentioning "swappers.relay.relayChainId" if
missing or falsy), and tighten wrappedNativeAddress validation to reject empty
strings (treat "" as invalid and only allow null or a non-empty string, throwing
an Error referencing "wrappedNativeAddress" otherwise). Apply the same stricter
checks in the other related block (lines analogous to 106-114) and use early
throws with descriptive messages so invalid configs fail fast.

In `@src/lib/account/evm.ts`:
- Line 186: Prefetching for chainIds[0] happens before the main loop and calls
adapter.getAddresses(), but for batch-capable wallets that don't support
Abstract this throws before the later check on abstractChainId can skip it;
modify the prefetch logic so it checks whether chainIds[0] === abstractChainId
and !supportsAbstract(wallet) (using the supportsAbstract helper and
abstractChainId symbol) and skip the prefetch in that case, or move that guard
earlier (before adapter.getAddresses is invoked) so account discovery quietly
skips Abstract chains instead of throwing.

---

Outside diff comments:
In `@src/context/WalletProvider/WalletConnectV2/config.ts`:
- Around line 55-69: The arrays (notably walletConnectV2OptionalChains)
currently always include the 'abstract' chain, causing WalletConnect sessions to
advertise chain 2741 even when the Abstract plugin is disabled; change these
static arrays to only include the 'abstract' ViemChain conditionally by checking
a runtime feature flag/config (e.g., an existing enableAbstract or
isAbstractPluginEnabled boolean) and pushing/concat-ing the abstract chain only
when that flag is true; apply the same conditional inclusion to the other
WalletConnect V2 chain arrays referenced in this diff so Abstract is advertised
only when the plugin is enabled.

---

Nitpick comments:
In `@package.json`:
- Line 42: Update the add-chain package.json script to use the same invocation
style as other tsx scripts: replace the current "add-chain" script that uses
"npx tsx" with one that uses "pnpm exec tsx" so execution is lockfile-pinned and
consistent with scripts like "generate:chain" and "release".

In `@packages/contracts/src/fallbackRpcUrls.ts`:
- Line 34: The 'abstract' entry in the fallback RPC URLs array only contains a
single endpoint; update the exported fallbackRpcUrls object so the 'abstract'
key's array includes additional resilient endpoints (e.g., add
"https://api.mainnet.abs.xyz" and/or "https://abstract.drpc.org") alongside the
existing "https://rpc.ankr.com/abstract" in the file that defines
fallbackRpcUrls (look for the 'abstract' property in fallbackRpcUrls.ts) so
consumers will have multiple RPC options if one endpoint is down.
🪄 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: 88a149ef-9a27-45cd-abbe-c3d239360f70

📥 Commits

Reviewing files that changed from the base of the PR and between 865d7d0 and 0036075.

⛔ Files ignored due to path filters (9)
  • public/generated/asset-manifest.json is excluded by !**/generated/**
  • public/generated/asset-manifest.json.br is excluded by !**/generated/**
  • public/generated/asset-manifest.json.gz is excluded by !**/*.gz, !**/generated/**
  • public/generated/generatedAssetData.json is excluded by !**/generated/**
  • public/generated/generatedAssetData.json.br is excluded by !**/generated/**
  • public/generated/generatedAssetData.json.gz is excluded by !**/*.gz, !**/generated/**
  • public/generated/relatedAssetIndex.json is excluded by !**/generated/**
  • public/generated/relatedAssetIndex.json.br is excluded by !**/generated/**
  • public/generated/relatedAssetIndex.json.gz is excluded by !**/*.gz, !**/generated/**
📒 Files selected for processing (73)
  • .env
  • .env.development
  • chains/abstract.json
  • e2e/fixtures/abstract-chain.yaml
  • headers/csps/chains/abstract.ts
  • headers/csps/index.ts
  • package.json
  • packages/caip/src/adapters/coingecko/index.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/abstract/AbstractChainAdapter.ts
  • packages/chain-adapters/src/evm/abstract/index.ts
  • packages/chain-adapters/src/evm/index.ts
  • packages/chain-adapters/src/types.ts
  • packages/contracts/src/ethersProviderSingleton.ts
  • packages/contracts/src/fallbackRpcUrls.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/native-multichain.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/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/addChain/codemods.ts
  • scripts/addChain/engine.ts
  • scripts/addChain/index.ts
  • scripts/addChain/report.ts
  • scripts/addChain/schema.ts
  • scripts/addChain/templates/assetGenerator.ts.tmpl
  • scripts/addChain/templates/chainAdapter.ts.tmpl
  • scripts/addChain/templates/chainAdapterIndex.ts.tmpl
  • scripts/addChain/templates/csp.ts.tmpl
  • scripts/addChain/templates/plugin.tsx.tmpl
  • scripts/generateAssetData/abstract/index.ts
  • scripts/generateAssetData/coingecko.ts
  • scripts/generateAssetData/generateAssetData.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/context/WalletProvider/WalletConnectV2/config.ts
  • 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/abstract/index.tsx
  • src/plugins/activePlugins.ts
  • src/state/migrations/index.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

Comment on lines +24 to +30
function wrap(file: string, operation: string, fn: () => boolean): CodemodResult {
try {
const changed = fn()
return { file, operation, status: changed ? 'inserted' : 'skipped' }
} catch (err) {
return { file, operation, status: 'error', message: String(err) }
}
Copy link
Contributor

@coderabbitai coderabbitai bot Mar 17, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

wrap() currently masks anchor-miss failures as “skipped”.

Because engine helpers use false for both “already present” and “pattern not found”, this wrapper records both as 'skipped'. That can hide broken codemods and produce incomplete scaffolds without surfacing an error state.

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

In `@scripts/addChain/codemods.ts` around lines 24 - 30, wrap currently treats a
false return from the codemod function as 'skipped', which hides anchor-miss
failures; change wrap (the function wrap(file: string, operation: string, fn: ()
=> boolean)) so that when fn() returns true it still returns status 'inserted',
but when fn() returns false it returns status 'error' with a clear message like
"anchor not found" (or similar) instead of 'skipped'; preserve the existing
catch branch for thrown errors and keep the returned object shape { file,
operation, status, message? } so callers/consumers can detect and surface
anchor-miss failures from wrap.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

post-MVP — wrap() propagates false/exception correctly; anchor-not-found vs already-present distinction is a UX improvement for the scaffold operator, not a correctness issue

Copy link
Contributor

Choose a reason for hiding this comment

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

@gomesalexandre, understood — the wrap() semantics are intentional: false maps to 'skipped' (covers both "already present" and "anchor not found"), and only thrown exceptions map to 'error'. Surfacing the finer-grained distinction is a post-MVP UX improvement and doesn't affect scaffold correctness.

This is already captured in my knowledge base so I won't flag it again in future reviews.


🧠 Learnings used
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T21:54:13.597Z
Learning: In scripts/addChain/codemods.ts, the `wrap()` helper intentionally uses `false` (from the engine) to mean "skipped/already present" and thrown exceptions to mean "error". The distinction between "anchor not found" vs "already present" in skip status is a known post-MVP UX improvement and does not affect scaffold correctness. Do not flag this as a masking issue.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T21:54:13.597Z
Learning: In scripts/addChain/engine.ts, the `addNamedImport()` idempotency key format is intentional for the current MVP scaffolder. Hardening the idempotency key approach is catalogued as a post-MVP improvement. Do not flag the current format as incorrect.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10458
File: src/plugins/walletConnectToDapps/components/modals/EIP155SignTypedDataConfirmation.tsx:55-55
Timestamp: 2025-09-10T15:35:46.223Z
Learning: gomesalexandre prefers fail-fast early returns over graceful degradation when critical data is missing in WalletConnect flows (like peer metadata in EIP155SignTypedDataConfirmation.tsx). He favors "safety first, always double-wrap" approach and believes missing peer metadata indicates bigger problems that should be surfaced explicitly rather than masked with partial UI rendering.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/SendTransactionConfirmation.tsx:42-50
Timestamp: 2025-09-12T12:00:33.924Z
Learning: gomesalexandre prefers maintaining consistency with existing code patterns in WalletConnect modals, including side-effects-during-render for error handling (showErrorToast + handleReject), rather than introducing isolated refactors that would make the codebase inconsistent.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11924
File: packages/chain-adapters/src/evm/mantle/MantleChainAdapter.ts:1-1
Timestamp: 2026-02-21T10:55:55.870Z
Learning: For second-class EVM chain adapters (those extending SecondClassEvmAdapter), the type guard function (e.g., isMantleChainAdapter, isKatanaChainAdapter, isUnichainChainAdapter) exists in BOTH locations: in the adapter file itself (packages/chain-adapters/src/evm/[chain]/[Chain]ChainAdapter.ts) AND in src/lib/utils/[chain].ts with defensive null/undefined checks. This pattern is consistent across at least 14 second-class adapters (base, berachain, cronos, hyperevm, ink, katana, linea, mantle, megaeth, monad, optimism, plasma, scroll, sonic, unichain) and should be maintained for consistency unless a comprehensive refactor across all adapters is undertaken.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11932
File: src/lib/utils/worldchain.ts:39-41
Timestamp: 2026-02-22T12:23:52.513Z
Learning: In src/lib/utils/[chain].ts files for second-class EVM chains (e.g., worldchain.ts, katana.ts, etc.), the per-chain utility functions like getWorldChainTransactionStatus() are effectively dead code after the migration to using the generic SecondClassEvmAdapter.getTransactionStatus() handler. Code quality concerns (like structured logging) for these files are not relevant since they're no longer actively used in hot paths.

Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-11-24T21:20:57.909Z
Learning: Applies to packages/swapper/**/*.ts : Use TypeScript with explicit types (e.g., SupportedChainIds) for all code in the Swapper system

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10206
File: src/config.ts:127-128
Timestamp: 2025-08-07T11:20:44.614Z
Learning: gomesalexandre prefers required environment variables without default values in the config file (src/config.ts). They want explicit configuration and fail-fast behavior when environment variables are missing, rather than having fallback defaults.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/ContractInteractionBreakdown.tsx:0-0
Timestamp: 2025-09-13T16:45:18.813Z
Learning: gomesalexandre prefers aggressively deleting unused/obsolete code files ("ramboing") rather than fixing technical issues in code that won't be used, demonstrating his preference for keeping codebases clean and PR scope focused.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10458
File: src/plugins/walletConnectToDapps/types.ts:7-7
Timestamp: 2025-09-10T15:34:29.604Z
Learning: gomesalexandre is comfortable relying on transitive dependencies (like abitype through ethers/viem) rather than explicitly declaring them in package.json, preferring to avoid package.json bloat when the transitive dependency approach works reliably in practice.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10503
File: .env:56-56
Timestamp: 2025-09-16T13:17:02.938Z
Learning: gomesalexandre prefers to enable feature flags globally in the base .env file when the intent is to activate features everywhere, even when there are known issues like crashes, demonstrating his preference for intentional global feature rollouts over cautious per-environment enablement.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10249
File: src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx:447-503
Timestamp: 2025-08-13T17:07:10.763Z
Learning: gomesalexandre prefers relying on TypeScript's type system for validation rather than adding defensive runtime null checks when types are properly defined. They favor a TypeScript-first approach over defensive programming with runtime validations.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10276
File: src/hooks/useActionCenterSubscribers/useThorchainLpDepositActionSubscriber.tsx:61-66
Timestamp: 2025-08-14T17:51:47.556Z
Learning: gomesalexandre is not concerned about structured logging and prefers to keep console.error usage as-is rather than implementing structured logging patterns, even when project guidelines suggest otherwise.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10413
File: src/components/Modals/FiatRamps/fiatRampProviders/onramper/utils.ts:29-55
Timestamp: 2025-09-02T14:26:19.028Z
Learning: gomesalexandre prefers to keep preparatory/reference code simple until it's actively consumed, rather than implementing comprehensive error handling, validation, and robustness improvements upfront. They prefer to add these improvements when the code is actually being used in production.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10276
File: src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx:396-402
Timestamp: 2025-08-14T17:55:57.490Z
Learning: gomesalexandre is comfortable with functions/variables that return undefined or true (tri-state) when only the truthy case matters, preferring to rely on JavaScript's truthy/falsy behavior rather than explicitly returning boolean values.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10783
File: src/context/ModalStackProvider/useModalRegistration.ts:30-41
Timestamp: 2025-10-16T11:14:40.657Z
Learning: gomesalexandre prefers to add lint rules (like typescript-eslint/strict-boolean-expressions for truthiness checks on numbers) to catch common issues project-wide rather than relying on code review to catch them.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10206
File: src/lib/moralis.ts:47-85
Timestamp: 2025-08-07T11:22:16.983Z
Learning: gomesalexandre prefers console.error over structured logging for Moralis API integration debugging, as they find it more conventional and prefer to examine XHR requests directly rather than rely on structured logs for troubleshooting.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T21:54:13.597Z
Learning: In shapeshift/web, the batch-prefetch in src/lib/account/evm.ts gates on `wallet.ethGetAddresses`, which is chain-agnostic and works for any EVM-capable wallet regardless of chain-specific support flags like `supportsAbstract`. The chain-specific `supports*` guard is enforced downstream in `deriveEvmAccountIdsAndMetadata`. This pattern is identical across all second-class EVM chains and should not be flagged as a missing pre-check.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T20:28:34.883Z
Learning: In shapeshift/web, chains added to `walletConnectV2OptionalChains` and `rpcMap` in `src/context/WalletProvider/WalletConnectV2/config.ts` are intentionally NOT gated by their feature flags. Feature-flagged chains (e.g., ink, flowEvmChain, sei, abstract) are unconditionally included in these WalletConnect V2 structures. This is the established convention and should not be flagged as a missing feature-flag guard.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/EIP712MessageDisplay.tsx:133-137
Timestamp: 2025-09-12T10:15:10.389Z
Learning: gomesalexandre has identified that EIP-712 domain chainId should be preferred over request context chainId for accuracy in WalletConnect dApps structured signing flows. The domain chainId from the parsed message is more specific and accurate than the general request context, especially for asset resolution and network-specific operations.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T01:29:21.619Z
Learning: In shapeshift/web PR `#12181`, the primary fix is replacing SHA-based comparison (`privateSha`) with a content diff approach (`privateContentMatchesMain` boolean) in `deriveReleaseState`/`deriveHotfixState` in `scripts/release.ts`. This unblocks new releases when `private` has been squash-synced with `main` (SHA differs even though content is identical). The secondary fix — `createPr` returning `null` on "No commits between" GitHub error — is a defensive improvement bundled in the same PR. The PR title only references the secondary change; the commit message body captures both.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11930
File: packages/chain-adapters/src/evm/soneium/SoneiumChainAdapter.ts:18-20
Timestamp: 2026-02-21T14:23:27.392Z
Learning: In packages/chain-adapters/src/evm/[chain]/[Chain]ChainAdapter.ts files for second-class EVM adapters, the type guard function (e.g., isSoneiumChainAdapter, isMantleChainAdapter) intentionally uses a simple pattern without defensive null/undefined checks: `(adapter as ChainAdapter).getType() === KnownChainIds.[Chain]Mainnet`. These simple type guards are exported for optional per-chain narrowing but are not actively used in hot paths. In practice, callers always check `getChainAdapterManager().get(chainId)` first, so null is never passed. The null-safe production code path uses `isSecondClassEvmAdapter` via `instanceof`. This pattern is consistent across 20+ second-class adapters (Berachain, HyperEvm, Base, Optimism, Linea, Monad, Scroll, Ink, Mode, Sonic, Bob, Plasma, Mantle, Katana, Cronos, MegaEth, Unichain, Soneium). Any defensive null-check additions should be done comprehensively across all adapters in a dedicated cleanup PR, not piecemeal.

Learnt from: gomes-bot
Repo: shapeshift/web PR: 11884
File: packages/chain-adapters/src/tron/TronChainAdapter.ts:732-735
Timestamp: 2026-02-16T15:00:09.111Z
Learning: In packages/chain-adapters/src/tron/TronChainAdapter.ts, inline comments explaining non-obvious domain-specific behavior (e.g., why TRC20 burns to zero address are allowed while mints from zero address are skipped) are acceptable when explicitly requested, especially when the rationale is easy to regress (e.g., sTRX unstaking burn behavior).

if (chainId === storyChainId && !supportsStory(wallet)) continue
if (chainId === zkSyncEraChainId && !supportsZkSyncEra(wallet)) continue
if (chainId === blastChainId && !supportsBlast(wallet)) continue
if (chainId === abstractChainId && !supportsAbstract(wallet)) continue
Copy link
Contributor

@coderabbitai coderabbitai bot Mar 17, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

The Abstract skip happens too late for batch-prefetch.

Lines 141-157 prefetch chainIds[0] before the main loop, and that path calls adapter.getAddresses(). If chainIds[0] is Abstract on a batch-capable wallet that doesn't support it, the adapter throws before Line 186 can continue, so account discovery fails instead of quietly skipping the chain.

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

In `@src/lib/account/evm.ts` at line 186, Prefetching for chainIds[0] happens
before the main loop and calls adapter.getAddresses(), but for batch-capable
wallets that don't support Abstract this throws before the later check on
abstractChainId can skip it; modify the prefetch logic so it checks whether
chainIds[0] === abstractChainId and !supportsAbstract(wallet) (using the
supportsAbstract helper and abstractChainId symbol) and skip the prefetch in
that case, or move that guard earlier (before adapter.getAddresses is invoked)
so account discovery quietly skips Abstract chains instead of throwing.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

dismissing — the prefetch gates on wallet.ethGetAddresses (any EVM wallet), not supportsAbstract. all other second-class EVM chains use the identical pattern without issue

Copy link
Contributor

Choose a reason for hiding this comment

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

Rate Limit Exceeded

@gomesalexandre have exceeded the limit for the number of chat messages per hour. Please wait 1 minutes and 32 seconds before sending another message.

@gomesalexandre
Copy link
Contributor Author

ser you're drunk @coderabbitai

abstract follows the same pattern as ink, flowEvmChain, and sei — all feature-flagged chains that are unconditionally included in walletConnectV2OptionalChains and rpcMap. None of them are gated by their feature flag in this file. Abstract is consistent with the existing convention.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 17, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check the WalletConnect V2 config file to verify the pattern for ink, flowEvmChain, sei, and abstract
cat src/context/WalletProvider/WalletConnectV2/config.ts

Length of output: 4114


@gomesalexandre You're absolutely right — I was wrong. The file confirms that ink, flowEvmChain, sei, and now abstract are all unconditionally included in both walletConnectV2OptionalChains and rpcMap with no feature flag gating, which is consistent with every other chain in the file. The pattern is clear and abstract follows it correctly. Apologies for the noise!


✏️ Learnings added
Learnt from: gomesalexandre
URL: https://github.com/shapeshift/web/pull/12186

Timestamp: 2026-03-17T20:28:34.883Z
Learning: In shapeshift/web, chains added to `walletConnectV2OptionalChains` and `rpcMap` in `src/context/WalletProvider/WalletConnectV2/config.ts` are intentionally NOT gated by their feature flags. Feature-flagged chains (e.g., ink, flowEvmChain, sei, abstract) are unconditionally included in these WalletConnect V2 structures. This is the established convention and should not be flagged as a missing feature-flag guard.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/utils/tenderly/index.ts:33-45
Timestamp: 2025-09-12T10:35:51.632Z
Learning: gomesalexandre consistently dismisses CodeRabbit suggestions about replacing console.error/console.warn with structured logging in API integration code, preferring simple console logging for debugging Tenderly transaction simulation APIs in WalletConnect flows.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/SendTransactionConfirmation.tsx:42-50
Timestamp: 2025-09-12T12:00:33.924Z
Learning: gomesalexandre prefers maintaining consistency with existing code patterns in WalletConnect modals, including side-effects-during-render for error handling (showErrorToast + handleReject), rather than introducing isolated refactors that would make the codebase inconsistent.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/SendTransactionConfirmation.tsx:42-50
Timestamp: 2025-09-12T12:00:33.924Z
Learning: gomesalexandre prefers maintaining consistency with existing code patterns across WalletConnect modal components, including side-effects-during-render for error handling (showErrorToast + handleReject calls before return null), rather than introducing isolated refactors that would create inconsistency in the codebase.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/WalletConnectSigningModal/StructuredMessage/StructuredMessage.tsx:0-0
Timestamp: 2025-09-13T16:45:17.166Z
Learning: gomesalexandre appreciates safety-focused suggestions for UI rendering in WalletConnect components, specifically defensive programming approaches that prevent null/undefined values from displaying as literal "null"/"undefined" strings in the user interface.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/EIP712MessageDisplay.tsx:21-24
Timestamp: 2025-09-12T13:16:27.004Z
Learning: gomesalexandre declined to add error boundaries to WalletConnect modals in PR `#10461`, stating "no error boundaries in this pr ser", consistent with his preference to keep PR scope focused and defer tangential improvements to separate efforts.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/hooks/useSimulateEvmTransaction.ts:0-0
Timestamp: 2025-09-12T13:44:17.019Z
Learning: gomesalexandre prefers letting chain adapter errors throw naturally in useSimulateEvmTransaction rather than adding explicit error handling for missing adapters, consistent with his fail-fast approach and dismissal of defensive validation as "stale" in WalletConnect transaction simulation flows.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10879
File: src/context/WalletProvider/WalletConnectV2/components/WalletConnectDirectRow.tsx:64-81
Timestamp: 2025-10-22T22:11:22.918Z
Learning: In early WalletConnect POC/features behind a flag, gomesalexandre prioritizes connection correctness/stability over UX polish; minimal safety guards (like preventing concurrent connects) are preferred, while visuals will be wired later by reallybeard.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/EIP712MessageDisplay.tsx:133-137
Timestamp: 2025-09-12T10:15:10.389Z
Learning: gomesalexandre has identified that EIP-712 domain chainId should be preferred over request context chainId for accuracy in WalletConnect dApps structured signing flows. The domain chainId from the parsed message is more specific and accurate than the general request context, especially for asset resolution and network-specific operations.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10458
File: src/plugins/walletConnectToDapps/types.ts:7-7
Timestamp: 2025-09-10T15:34:29.604Z
Learning: gomesalexandre is comfortable relying on transitive dependencies (like abitype through ethers/viem) rather than explicitly declaring them in package.json, preferring to avoid package.json bloat when the transitive dependency approach works reliably in practice.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10280
File: src/context/WalletProvider/MobileWallet/mobileMessageHandlers.ts:18-18
Timestamp: 2025-08-14T12:42:48.263Z
Learning: gomesalexandre prefers maintaining string literal patterns in the Message union type in src/context/WalletProvider/MobileWallet/mobileMessageHandlers.ts, even when there's some duplication between Command union and Message variants. They find properly typed string literals acceptable and prefer not to refactor for type hygiene in this context.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11924
File: packages/chain-adapters/src/evm/mantle/MantleChainAdapter.ts:1-1
Timestamp: 2026-02-21T10:55:55.870Z
Learning: For second-class EVM chain adapters (those extending SecondClassEvmAdapter), the type guard function (e.g., isMantleChainAdapter, isKatanaChainAdapter, isUnichainChainAdapter) exists in BOTH locations: in the adapter file itself (packages/chain-adapters/src/evm/[chain]/[Chain]ChainAdapter.ts) AND in src/lib/utils/[chain].ts with defensive null/undefined checks. This pattern is consistent across at least 14 second-class adapters (base, berachain, cronos, hyperevm, ink, katana, linea, mantle, megaeth, monad, optimism, plasma, scroll, sonic, unichain) and should be maintained for consistency unless a comprehensive refactor across all adapters is undertaken.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10857
File: src/plugins/walletConnectToDapps/eventsManager/useWalletConnectEventsHandler.ts:101-104
Timestamp: 2025-10-23T14:27:19.073Z
Learning: In WalletConnect wallet_switchEthereumChain and wallet_addEthereumChain requests, the chainId parameter is always present as per the protocol spec. Type guards checking for missing chainId in these handlers (like `if (!evmNetworkIdHex) return`) are solely for TypeScript compiler satisfaction, not real runtime edge cases.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10810
File: src/plugins/walletConnectToDapps/utils/tenderly/index.ts:212-0
Timestamp: 2025-10-15T15:57:39.956Z
Learning: gomesalexandre uses discriminated union patterns (e.g., `isEIP1559 ? { max_fee_per_gas, max_priority_fee_per_gas } : { gas_price }`) in WalletConnect flows without additional validation guards, trusting that the runtime data structure ensures mutual exclusivity between EIP-1559 and legacy gas pricing fields.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11930
File: packages/chain-adapters/src/evm/soneium/SoneiumChainAdapter.ts:18-20
Timestamp: 2026-02-21T14:23:27.392Z
Learning: In packages/chain-adapters/src/evm/[chain]/[Chain]ChainAdapter.ts files for second-class EVM adapters, the type guard function (e.g., isSoneiumChainAdapter, isMantleChainAdapter) intentionally uses a simple pattern without defensive null/undefined checks: `(adapter as ChainAdapter).getType() === KnownChainIds.[Chain]Mainnet`. These simple type guards are exported for optional per-chain narrowing but are not actively used in hot paths. In practice, callers always check `getChainAdapterManager().get(chainId)` first, so null is never passed. The null-safe production code path uses `isSecondClassEvmAdapter` via `instanceof`. This pattern is consistent across 20+ second-class adapters (Berachain, HyperEvm, Base, Optimism, Linea, Monad, Scroll, Ink, Mode, Sonic, Bob, Plasma, Mantle, Katana, Cronos, MegaEth, Unichain, Soneium). Any defensive null-check additions should be done comprehensively across all adapters in a dedicated cleanup PR, not piecemeal.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11932
File: src/lib/utils/worldchain.ts:39-41
Timestamp: 2026-02-22T12:23:52.513Z
Learning: In src/lib/utils/[chain].ts files for second-class EVM chains (e.g., worldchain.ts, katana.ts, etc.), the per-chain utility functions like getWorldChainTransactionStatus() are effectively dead code after the migration to using the generic SecondClassEvmAdapter.getTransactionStatus() handler. Code quality concerns (like structured logging) for these files are not relevant since they're no longer actively used in hot paths.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10206
File: src/config.ts:127-128
Timestamp: 2025-08-07T11:20:44.614Z
Learning: gomesalexandre prefers required environment variables without default values in the config file (src/config.ts). They want explicit configuration and fail-fast behavior when environment variables are missing, rather than having fallback defaults.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/ContractInteractionBreakdown.tsx:0-0
Timestamp: 2025-09-13T16:45:18.813Z
Learning: gomesalexandre prefers aggressively deleting unused/obsolete code files ("ramboing") rather than fixing technical issues in code that won't be used, demonstrating his preference for keeping codebases clean and PR scope focused.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10503
File: .env:56-56
Timestamp: 2025-09-16T13:17:02.938Z
Learning: gomesalexandre prefers to enable feature flags globally in the base .env file when the intent is to activate features everywhere, even when there are known issues like crashes, demonstrating his preference for intentional global feature rollouts over cautious per-environment enablement.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10249
File: src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx:447-503
Timestamp: 2025-08-13T17:07:10.763Z
Learning: gomesalexandre prefers relying on TypeScript's type system for validation rather than adding defensive runtime null checks when types are properly defined. They favor a TypeScript-first approach over defensive programming with runtime validations.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10276
File: src/hooks/useActionCenterSubscribers/useThorchainLpDepositActionSubscriber.tsx:61-66
Timestamp: 2025-08-14T17:51:47.556Z
Learning: gomesalexandre is not concerned about structured logging and prefers to keep console.error usage as-is rather than implementing structured logging patterns, even when project guidelines suggest otherwise.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10413
File: src/components/Modals/FiatRamps/fiatRampProviders/onramper/utils.ts:29-55
Timestamp: 2025-09-02T14:26:19.028Z
Learning: gomesalexandre prefers to keep preparatory/reference code simple until it's actively consumed, rather than implementing comprehensive error handling, validation, and robustness improvements upfront. They prefer to add these improvements when the code is actually being used in production.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10276
File: src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx:396-402
Timestamp: 2025-08-14T17:55:57.490Z
Learning: gomesalexandre is comfortable with functions/variables that return undefined or true (tri-state) when only the truthy case matters, preferring to rely on JavaScript's truthy/falsy behavior rather than explicitly returning boolean values.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10783
File: src/context/ModalStackProvider/useModalRegistration.ts:30-41
Timestamp: 2025-10-16T11:14:40.657Z
Learning: gomesalexandre prefers to add lint rules (like typescript-eslint/strict-boolean-expressions for truthiness checks on numbers) to catch common issues project-wide rather than relying on code review to catch them.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10206
File: src/lib/moralis.ts:47-85
Timestamp: 2025-08-07T11:22:16.983Z
Learning: gomesalexandre prefers console.error over structured logging for Moralis API integration debugging, as they find it more conventional and prefer to examine XHR requests directly rather than rely on structured logs for troubleshooting.

Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10136
File: src/lib/asset-service/service/encodedRelatedAssetIndex.json:1-1
Timestamp: 2025-07-29T10:22:27.037Z
Learning: PRs with titles starting with "feat: regenerate asset data" are routine daily asset updates that don't need detailed code analysis. Users prefer to skip automated reviews for these maintenance PRs using coderabbitai ignore.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T01:29:21.619Z
Learning: In shapeshift/web PR `#12181`, the primary fix is replacing SHA-based comparison (`privateSha`) with a content diff approach (`privateContentMatchesMain` boolean) in `deriveReleaseState`/`deriveHotfixState` in `scripts/release.ts`. This unblocks new releases when `private` has been squash-synced with `main` (SHA differs even though content is identical). The secondary fix — `createPr` returning `null` on "No commits between" GitHub error — is a defensive improvement bundled in the same PR. The PR title only references the secondary change; the commit message body captures both.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/EIP712MessageDisplay.tsx:0-0
Timestamp: 2025-09-12T10:21:26.693Z
Learning: gomesalexandre explained that in WalletConnect V2, the request context chainId comes from params?.chainId following CAIP2 standards, making both the request params chainId and EIP-712 domain chainId equally reliable sources. He considers both approaches trustworthy ("both gucci") for WalletConnect dApps integration.

- add AbstractMainnet to ChainSignTx (was missing, would resolve to never)
- add chainId 2741 to WalletConnectV2 ethSupportsNetwork()
- add process.exit(1) when scaffolder codemods have errors
- validate wrappedNativeAddress non-empty string + relay requires relayChainId
- use pnpm exec tsx instead of npx tsx for add-chain script
- add more fallback RPC endpoints for Abstract (mainnet + drpc)
- add eip155:2741 to coingecko utils parseData test (fixes failing CI)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@gomesalexandre
Copy link
Contributor Author

done @coderabbitai — addressed in the follow-up commit:

  • AbstractMainnet added to ChainSignTx ✓
  • chainId 2741 added to ethSupportsNetwork() ✓
  • process.exit(1) for scaffolder errors ✓
  • wrappedNativeAddress empty-string guard + relay relayChainId validation ✓
  • pnpm exec tsx for add-chain script ✓
  • more fallback RPCs for Abstract ✓
  • coingecko utils.test.ts parseData updated ✓ (was the failing CI check too)

dismissing the wrap()/engine idempotency/evm.ts prefetch comments — wrap() already logs via console.warn on misses (surfaced to the user), addNamedImport idempotency key format is intentional, and the evm.ts prefetch uses ethGetAddresses which works for all EVM chains regardless of supportsAbstract

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 17, 2026

Tip

For best results, initiate chat on the files or code changes.

@gomesalexandre Thanks for the detailed follow-up! All the addressed items look solid:

  • ChainSignTx + ethSupportsNetwork(2741) — correct, both needed for signing/network support parity.
  • process.exit(1) — good, scaffolder failures will now bubble up properly to CI/callers.
  • wrappedNativeAddress guard + relay relayChainId validation — the schema-level guards make the scaffolder more robust.
  • pnpm exec tsx — correct for monorepo consistency.
  • More fallback RPCs + coingecko test fix — both pragmatic and unblocks CI.

The dismissals also make sense:

  • wrap() surfacing misses via console.warn is sufficient for a dev-time tool.
  • addNamedImport idempotency key format being intentional is fine — the pattern is self-consistent within the engine.
  • ethGetAddresses being chain-agnostic for EVM is correct; supportsAbstract gating is enforced downstream in deriveEvmAccountIdsAndMetadata anyway.

🧠 Learnings used
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T20:28:34.883Z
Learning: In shapeshift/web, chains added to `walletConnectV2OptionalChains` and `rpcMap` in `src/context/WalletProvider/WalletConnectV2/config.ts` are intentionally NOT gated by their feature flags. Feature-flagged chains (e.g., ink, flowEvmChain, sei, abstract) are unconditionally included in these WalletConnect V2 structures. This is the established convention and should not be flagged as a missing feature-flag guard.

Learnt from: gomes-bot
Repo: shapeshift/web PR: 12024
File: src/lib/chainflip/rpc.ts:59-81
Timestamp: 2026-02-24T17:32:50.105Z
Learning: In src/lib/chainflip/rpc.ts, the chainflipRpc wrapper is intentionally kept thin without defensive null/undefined checks on result. Downstream consumers handle edge cases (e.g., cf_free_balances returns `{}` for non-existent accounts) with Array.isArray guards at the call site, rather than adding validation in the RPC layer.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11932
File: src/lib/utils/worldchain.ts:39-41
Timestamp: 2026-02-22T12:23:52.513Z
Learning: In src/lib/utils/[chain].ts files for second-class EVM chains (e.g., worldchain.ts, katana.ts, etc.), the per-chain utility functions like getWorldChainTransactionStatus() are effectively dead code after the migration to using the generic SecondClassEvmAdapter.getTransactionStatus() handler. Code quality concerns (like structured logging) for these files are not relevant since they're no longer actively used in hot paths.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/hooks/useSimulateEvmTransaction.ts:0-0
Timestamp: 2025-09-12T13:44:17.019Z
Learning: gomesalexandre prefers letting chain adapter errors throw naturally in useSimulateEvmTransaction rather than adding explicit error handling for missing adapters, consistent with his fail-fast approach and dismissal of defensive validation as "stale" in WalletConnect transaction simulation flows.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10857
File: src/plugins/walletConnectToDapps/eventsManager/useWalletConnectEventsHandler.ts:101-104
Timestamp: 2025-10-23T14:27:19.073Z
Learning: In WalletConnect wallet_switchEthereumChain and wallet_addEthereumChain requests, the chainId parameter is always present as per the protocol spec. Type guards checking for missing chainId in these handlers (like `if (!evmNetworkIdHex) return`) are solely for TypeScript compiler satisfaction, not real runtime edge cases.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11930
File: packages/chain-adapters/src/evm/soneium/SoneiumChainAdapter.ts:18-20
Timestamp: 2026-02-21T14:23:27.392Z
Learning: In packages/chain-adapters/src/evm/[chain]/[Chain]ChainAdapter.ts files for second-class EVM adapters, the type guard function (e.g., isSoneiumChainAdapter, isMantleChainAdapter) intentionally uses a simple pattern without defensive null/undefined checks: `(adapter as ChainAdapter).getType() === KnownChainIds.[Chain]Mainnet`. These simple type guards are exported for optional per-chain narrowing but are not actively used in hot paths. In practice, callers always check `getChainAdapterManager().get(chainId)` first, so null is never passed. The null-safe production code path uses `isSecondClassEvmAdapter` via `instanceof`. This pattern is consistent across 20+ second-class adapters (Berachain, HyperEvm, Base, Optimism, Linea, Monad, Scroll, Ink, Mode, Sonic, Bob, Plasma, Mantle, Katana, Cronos, MegaEth, Unichain, Soneium). Any defensive null-check additions should be done comprehensively across all adapters in a dedicated cleanup PR, not piecemeal.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10458
File: src/plugins/walletConnectToDapps/components/modals/EIP155SignTypedDataConfirmation.tsx:55-55
Timestamp: 2025-09-10T15:35:46.223Z
Learning: gomesalexandre prefers fail-fast early returns over graceful degradation when critical data is missing in WalletConnect flows (like peer metadata in EIP155SignTypedDataConfirmation.tsx). He favors "safety first, always double-wrap" approach and believes missing peer metadata indicates bigger problems that should be surfaced explicitly rather than masked with partial UI rendering.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/hooks/useSimulateEvmTransaction.ts:91-95
Timestamp: 2025-09-12T13:43:50.695Z
Learning: gomesalexandre dismissed gas calculation overflow validation in useSimulateEvmTransaction hook as "stale", preferring to trust Tenderly's simulation data without defensive validation checks, consistent with his established pattern of relying on external service quality over defensive programming in WalletConnect flows.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/EIP712MessageDisplay.tsx:133-137
Timestamp: 2025-09-12T10:15:10.389Z
Learning: gomesalexandre has identified that EIP-712 domain chainId should be preferred over request context chainId for accuracy in WalletConnect dApps structured signing flows. The domain chainId from the parsed message is more specific and accurate than the general request context, especially for asset resolution and network-specific operations.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10458
File: src/plugins/walletConnectToDapps/components/modals/EIP712MessageDisplay.tsx:46-59
Timestamp: 2025-09-10T15:34:54.593Z
Learning: After extensive testing by gomesalexandre in PR `#10458`, dApps do not send EIP-712 domain.chainId as hex or bigint values in practice. The simple String(domain.chainId) conversion is sufficient for real-world usage in WalletConnect dApps structured signing.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11078
File: src/setupVitest.ts:11-15
Timestamp: 2025-11-20T12:00:45.005Z
Learning: In shapeshift/web, src/setupVitest.ts must redirect 'ethers' to 'ethers5' for shapeshiftoss/hdwallet-trezor (and -trezor-connect), same as ledger and shapeshift-multichain. Removing 'trezor' from the regex causes CI/Vitest failures due to ethers v6 vs v5 API differences.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11924
File: packages/chain-adapters/src/evm/mantle/MantleChainAdapter.ts:1-1
Timestamp: 2026-02-21T10:55:55.870Z
Learning: For second-class EVM chain adapters (those extending SecondClassEvmAdapter), the type guard function (e.g., isMantleChainAdapter, isKatanaChainAdapter, isUnichainChainAdapter) exists in BOTH locations: in the adapter file itself (packages/chain-adapters/src/evm/[chain]/[Chain]ChainAdapter.ts) AND in src/lib/utils/[chain].ts with defensive null/undefined checks. This pattern is consistent across at least 14 second-class adapters (base, berachain, cronos, hyperevm, ink, katana, linea, mantle, megaeth, monad, optimism, plasma, scroll, sonic, unichain) and should be maintained for consistency unless a comprehensive refactor across all adapters is undertaken.

Learnt from: gomes-bot
Repo: shapeshift/web PR: 11884
File: packages/chain-adapters/src/tron/TronChainAdapter.ts:732-735
Timestamp: 2026-02-16T15:00:09.111Z
Learning: In packages/chain-adapters/src/tron/TronChainAdapter.ts, inline comments explaining non-obvious domain-specific behavior (e.g., why TRC20 burns to zero address are allowed while mints from zero address are skipped) are acceptable when explicitly requested, especially when the rationale is easy to regress (e.g., sTRX unstaking burn behavior).

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10206
File: src/config.ts:127-128
Timestamp: 2025-08-07T11:20:44.614Z
Learning: gomesalexandre prefers required environment variables without default values in the config file (src/config.ts). They want explicit configuration and fail-fast behavior when environment variables are missing, rather than having fallback defaults.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/ContractInteractionBreakdown.tsx:0-0
Timestamp: 2025-09-13T16:45:18.813Z
Learning: gomesalexandre prefers aggressively deleting unused/obsolete code files ("ramboing") rather than fixing technical issues in code that won't be used, demonstrating his preference for keeping codebases clean and PR scope focused.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10458
File: src/plugins/walletConnectToDapps/types.ts:7-7
Timestamp: 2025-09-10T15:34:29.604Z
Learning: gomesalexandre is comfortable relying on transitive dependencies (like abitype through ethers/viem) rather than explicitly declaring them in package.json, preferring to avoid package.json bloat when the transitive dependency approach works reliably in practice.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10503
File: .env:56-56
Timestamp: 2025-09-16T13:17:02.938Z
Learning: gomesalexandre prefers to enable feature flags globally in the base .env file when the intent is to activate features everywhere, even when there are known issues like crashes, demonstrating his preference for intentional global feature rollouts over cautious per-environment enablement.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10249
File: src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx:447-503
Timestamp: 2025-08-13T17:07:10.763Z
Learning: gomesalexandre prefers relying on TypeScript's type system for validation rather than adding defensive runtime null checks when types are properly defined. They favor a TypeScript-first approach over defensive programming with runtime validations.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10276
File: src/hooks/useActionCenterSubscribers/useThorchainLpDepositActionSubscriber.tsx:61-66
Timestamp: 2025-08-14T17:51:47.556Z
Learning: gomesalexandre is not concerned about structured logging and prefers to keep console.error usage as-is rather than implementing structured logging patterns, even when project guidelines suggest otherwise.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10413
File: src/components/Modals/FiatRamps/fiatRampProviders/onramper/utils.ts:29-55
Timestamp: 2025-09-02T14:26:19.028Z
Learning: gomesalexandre prefers to keep preparatory/reference code simple until it's actively consumed, rather than implementing comprehensive error handling, validation, and robustness improvements upfront. They prefer to add these improvements when the code is actually being used in production.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10276
File: src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx:396-402
Timestamp: 2025-08-14T17:55:57.490Z
Learning: gomesalexandre is comfortable with functions/variables that return undefined or true (tri-state) when only the truthy case matters, preferring to rely on JavaScript's truthy/falsy behavior rather than explicitly returning boolean values.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10783
File: src/context/ModalStackProvider/useModalRegistration.ts:30-41
Timestamp: 2025-10-16T11:14:40.657Z
Learning: gomesalexandre prefers to add lint rules (like typescript-eslint/strict-boolean-expressions for truthiness checks on numbers) to catch common issues project-wide rather than relying on code review to catch them.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10206
File: src/lib/moralis.ts:47-85
Timestamp: 2025-08-07T11:22:16.983Z
Learning: gomesalexandre prefers console.error over structured logging for Moralis API integration debugging, as they find it more conventional and prefer to examine XHR requests directly rather than rely on structured logs for troubleshooting.

Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10136
File: src/lib/asset-service/service/encodedRelatedAssetIndex.json:1-1
Timestamp: 2025-07-29T10:22:27.037Z
Learning: PRs with titles starting with "feat: regenerate asset data" are routine daily asset updates that don't need detailed code analysis. Users prefer to skip automated reviews for these maintenance PRs using coderabbitai ignore.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T01:29:21.619Z
Learning: In shapeshift/web PR `#12181`, the primary fix is replacing SHA-based comparison (`privateSha`) with a content diff approach (`privateContentMatchesMain` boolean) in `deriveReleaseState`/`deriveHotfixState` in `scripts/release.ts`. This unblocks new releases when `private` has been squash-synced with `main` (SHA differs even though content is identical). The secondary fix — `createPr` returning `null` on "No commits between" GitHub error — is a defensive improvement bundled in the same PR. The PR title only references the secondary change; the commit message body captures both.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/EIP712MessageDisplay.tsx:0-0
Timestamp: 2025-09-12T10:21:26.693Z
Learning: gomesalexandre explained that in WalletConnect V2, the request context chainId comes from params?.chainId following CAIP2 standards, making both the request params chainId and EIP-712 domain chainId equally reliable sources. He considers both approaches trustworthy ("both gucci") for WalletConnect dApps integration.

If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!

gomesalexandre and others added 2 commits March 17, 2026 21:40
- add ChainSignTx (ETHSignTx type map) codemod — was missing, manual fix needed for abstract
- add ethSupportsNetwork() chain ID codemod for walletconnectv2 — was missing, manual fix needed for abstract
- rename mislabeled types-ChainSignTx → types-ChainSpecificBuildTxInput
- add missing clearAssets migration 314

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@NeOMakinG
Copy link
Collaborator

🤖 QA Automation Report

QABot Run: #59223faa
Status: ⚠️ Partial Pass

✅ Build Verification

  • pnpm install && pnpm build:packages succeeded
  • Dev server starts on port 4471
  • VITE_FEATURE_ABSTRACT=true enabled in .env.development
  • No TypeScript errors after package build

⚠️ UI Testing (Partial)

  • Home page loads correctly
  • Trade UI renders with ETH/BTC default pair
  • Search modal opens and displays assets
  • Note: Browser automation encountered timing issues preventing full Abstract chain verification

📋 Recommendations

Manual verification needed for:

  1. Abstract chain appears in asset selector when feature flag enabled
  2. Bridge to Abstract chain works via Relay
  3. On-chain swap (ETH→USDT) on Abstract
  4. Balance polling and notification center

Automated QA by QABot

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: 4

♻️ Duplicate comments (1)
scripts/addChain/codemods.ts (1)

24-30: ⚠️ Potential issue | 🟠 Major

Don't collapse anchor misses into skipped.

wrap() still treats every false as an idempotent no-op. That is already wrong for Lines 1020-1023, where false means "couldn't find any clearAssets anchor". The report stays green and scripts/addChain/index.ts exits 0 even though the scaffold is incomplete.

🩹 Suggested shape
-function wrap(file: string, operation: string, fn: () => boolean): CodemodResult {
+function wrap(
+  file: string,
+  operation: string,
+  fn: () => 'inserted' | 'skipped',
+): CodemodResult {
   try {
-    const changed = fn()
-    return { file, operation, status: changed ? 'inserted' : 'skipped' }
+    return { file, operation, status: fn() }
   } catch (err) {
     return { file, operation, status: 'error', message: String(err) }
   }
 }

Then make anchor-miss paths throw instead of returning false.

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

In `@scripts/addChain/codemods.ts` around lines 24 - 30, wrap() currently treats
any falsy result from the codemod function as a benign 'skipped' and hides
anchor-misses (e.g., missing clearAssets anchor reported from the codemod run
around the clearAssets logic), so change the behavior so anchor-miss paths
surface as errors: update the codemod functions that return false on "anchor not
found" to throw a descriptive Error (e.g., "anchor clearAssets not found"), and
update wrap(fn) to stop converting false into 'skipped' — let thrown errors
propagate (or catch and return status: 'error' with the error message) so anchor
misses produce error status instead of a green 'skipped'.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@scripts/addChain/codemods.ts`:
- Around line 1529-1552: The scaffold currently decides to skip creation based
solely on adapterFile existence (variable adapterFile) which leaves index.ts
missing if a previous run failed; update the logic in codemods.ts to check both
the class file and the index file (the path used in the second writeFileSync
call) — if the directory doesn't exist create it, then individually ensure the
class file and the index.ts are created when absent (using the same
fill(tmpl(...), c) calls), and push appropriate results entries for each
artifact instead of a single skipped/inserted result so partial generation is
repaired on re-run.
- Around line 1101-1135: The current conditional branches that check
c.swappers.across.supported, c.swappers.portals.supported and
c.swappers.zerion.supported only add a named import (via addNamedImport) into
AcrossSwapper/constant.ts, PortalsSwapper/constants.ts and
packages/types/src/zerion.ts respectively, which leaves the swappers
functionally unsupported and produces unused imports; update each branch to also
scaffold the actual supported-chain constants and filters by adding the
SupportedChainIds structure (with sell and buy keys) into the swapper's
utils/constants.ts (or constants.ts) and update any supported-chain mappings or
network mappings used by the swappers so the import becomes used and the swapper
is truly enabled (ensure you follow the SupportedChainIds type pattern and
update sell/buy filters and any network mapping arrays referenced by the
swappers when adding ${c.camelName}ChainId).
- Around line 1017-1033: The code computes nextNum and the insertion anchor
using only clearAssets matches which can collide with later non-clearAssets
migrations; update the logic in the wrap callback (the function operating on
migrationsFile) to find the highest migration key by scanning all migration
entries (e.g. match /(\d+): \w+,/ or similar) to derive lastNum and nextNum,
then use that lastNum both to compute nextNum and as the regex anchor passed to
appendLineAfterPattern (instead of the last clearAssets match); keep the
existing use of appendLineAfterPattern and the surrounding wrap/migrationsFile
flow.

In `@scripts/addChain/index.ts`:
- Line 1: The first-line shebang is incorrect because env treats the rest as a
single program name; update the script's first-line shebang (the shebang on the
first line) to use argument-splitting (e.g., use env with -S) so the "npx tsx"
arguments are passed correctly, or remove the shebang altogether and
document/require running the script via `npx tsx scripts/addChain/index.ts`;
ensure the change replaces the existing shebang only.

---

Duplicate comments:
In `@scripts/addChain/codemods.ts`:
- Around line 24-30: wrap() currently treats any falsy result from the codemod
function as a benign 'skipped' and hides anchor-misses (e.g., missing
clearAssets anchor reported from the codemod run around the clearAssets logic),
so change the behavior so anchor-miss paths surface as errors: update the
codemod functions that return false on "anchor not found" to throw a descriptive
Error (e.g., "anchor clearAssets not found"), and update wrap(fn) to stop
converting false into 'skipped' — let thrown errors propagate (or catch and
return status: 'error' with the error message) so anchor misses produce error
status instead of a green 'skipped'.
🪄 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: ce2f8977-3842-47f6-8435-df25973624bf

📥 Commits

Reviewing files that changed from the base of the PR and between 0331873 and 918cc3f.

📒 Files selected for processing (5)
  • packages/contracts/src/fallbackRpcUrls.ts
  • scripts/addChain/codemods.ts
  • scripts/addChain/index.ts
  • scripts/addChain/schema.ts
  • src/state/migrations/index.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • scripts/addChain/schema.ts

Comment on lines +1017 to +1033
wrap(migrationsFile, 'migrations-clearAssets', () => {
const src = fs.readFileSync(migrationsFile, 'utf8')
const matches = [...src.matchAll(/(\d+): clearAssets,/g)]
if (!matches.length) {
console.warn('[codemods] Could not find any clearAssets migration entries')
return false
}
const lastNum = Math.max(...matches.map(m => parseInt(m[1], 10)))
const nextNum = lastNum + 1
if (src.includes(`${nextNum}: clearAssets`)) return false
return appendLineAfterPattern(
migrationsFile,
new RegExp(`${lastNum}: clearAssets,`),
` ${nextNum}: clearAssets,`,
`${nextNum}: clearAssets`,
)
}),
Copy link
Contributor

@coderabbitai coderabbitai bot Mar 17, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Allocate the next migration key from the highest existing migration.

This block derives nextNum from the last clearAssets entry, not the last migration entry. If the file already contains a later non-clearAssets migration, this can generate a duplicate object key and silently shadow one migration.

🔢 Suggested fix
-      const matches = [...src.matchAll(/(\d+): clearAssets,/g)]
-      if (!matches.length) {
-        console.warn('[codemods] Could not find any clearAssets migration entries')
-        return false
-      }
-      const lastNum = Math.max(...matches.map(m => parseInt(m[1], 10)))
-      const nextNum = lastNum + 1
+      const migrationNumbers = [...src.matchAll(/^\s*(\d+):\s*\w+,/gm)]
+      if (!migrationNumbers.length) {
+        throw new Error('Could not find any migration entries')
+      }
+      const nextNum = Math.max(...migrationNumbers.map(m => parseInt(m[1], 10))) + 1

Use the last migration entry as the insertion anchor as well, not the last clearAssets entry.

🧰 Tools
🪛 ast-grep (0.41.1)

[warning] 1028-1028: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(${lastNum}: clearAssets,)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)

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

In `@scripts/addChain/codemods.ts` around lines 1017 - 1033, The code computes
nextNum and the insertion anchor using only clearAssets matches which can
collide with later non-clearAssets migrations; update the logic in the wrap
callback (the function operating on migrationsFile) to find the highest
migration key by scanning all migration entries (e.g. match /(\d+): \w+,/ or
similar) to derive lastNum and nextNum, then use that lastNum both to compute
nextNum and as the regex anchor passed to appendLineAfterPattern (instead of the
last clearAssets match); keep the existing use of appendLineAfterPattern and the
surrounding wrap/migrationsFile flow.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

post-MVP improvement — noted

Copy link
Contributor

Choose a reason for hiding this comment

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

@gomesalexandre, understood — noted for post-MVP hardening. 👍


✏️ Learnings added
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 12186
File: scripts/addChain/codemods.ts:1017-1033
Timestamp: 2026-03-17T22:57:46.580Z
Learning: In scripts/addChain/codemods.ts (around the migrations-clearAssets wrap block), the `nextNum` computation derives the next migration key from the last `clearAssets` entry only (not the global highest migration key across all entry types). This can theoretically generate a duplicate object key if a later non-clearAssets migration already exists at a higher number, but this is intentionally deferred as a post-MVP improvement by gomesalexandre and should not be re-flagged in future reviews.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 12186
File: scripts/addChain/codemods.ts:1529-1552
Timestamp: 2026-03-17T22:57:18.383Z
Learning: In scripts/addChain/codemods.ts, the chain adapter scaffold checks only for the class file (e.g., AbstractChainAdapter.ts) to determine if creation should be skipped, not the index.ts. If a prior run stopped between writes, the missing index.ts is never repaired. This partial-generation idempotency gap is intentionally deferred as a post-MVP improvement by gomesalexandre.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11569
File: headers/csps/chains/katana.ts:8-10
Timestamp: 2026-01-07T15:36:13.236Z
Learning: In CSP chain files (headers/csps/chains/*.ts), explicitly filtering undefined environment variables with .filter(Boolean) is unnecessary because serializeCsp() in headers/util.ts filters all falsy values during serialization at line 51: `.map(([k, v]) => [k, v.filter(x => !!x)])`. The direct pattern [env.VITE_*_NODE_URL] is sufficient and preferred for consistency with second-class chain CSP files like plasma.ts and monad.ts.
<!-- </add_learning>

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11275
File: headers/csps/chains/plasma.ts:1-10
Timestamp: 2025-12-03T23:19:39.158Z
Learning: For CSP files in headers/csps/chains/, gomesalexandre prefers using Vite's loadEnv() pattern directly to load environment variables (e.g., VITE_PLASMA_NODE_URL, VITE_MONAD_NODE_URL) for consistency with existing second-class chain CSP files, rather than using getConfig() from src/config.ts, even though other parts of the codebase use validated config values.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11924
File: packages/chain-adapters/src/evm/mantle/MantleChainAdapter.ts:1-1
Timestamp: 2026-02-21T10:55:55.870Z
Learning: For second-class EVM chain adapters (those extending SecondClassEvmAdapter), the type guard function (e.g., isMantleChainAdapter, isKatanaChainAdapter, isUnichainChainAdapter) exists in BOTH locations: in the adapter file itself (packages/chain-adapters/src/evm/[chain]/[Chain]ChainAdapter.ts) AND in src/lib/utils/[chain].ts with defensive null/undefined checks. This pattern is consistent across at least 14 second-class adapters (base, berachain, cronos, hyperevm, ink, katana, linea, mantle, megaeth, monad, optimism, plasma, scroll, sonic, unichain) and should be maintained for consistency unless a comprehensive refactor across all adapters is undertaken.

Learnt from: kaladinlight
Repo: shapeshift/web PR: 11290
File: packages/chain-adapters/src/utxo/zcash/ZcashChainAdapter.ts:48-51
Timestamp: 2025-12-04T22:57:50.850Z
Learning: In packages/chain-adapters/src/**/*ChainAdapter.ts files, the getName() method uses the pattern `const enumIndex = Object.values(ChainAdapterDisplayName).indexOf(ChainAdapterDisplayName.XXX); return Object.keys(ChainAdapterDisplayName)[enumIndex]` to reverse-lookup the enum key from its value. This is the established pattern used consistently across almost all chain adapters (Bitcoin, Ethereum, Litecoin, Dogecoin, Polygon, Arbitrum, Cosmos, etc.) and should be preserved for consistency when adding new chain adapters.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T20:28:34.883Z
Learning: In shapeshift/web, chains added to `walletConnectV2OptionalChains` and `rpcMap` in `src/context/WalletProvider/WalletConnectV2/config.ts` are intentionally NOT gated by their feature flags. Feature-flagged chains (e.g., ink, flowEvmChain, sei, abstract) are unconditionally included in these WalletConnect V2 structures. This is the established convention and should not be flagged as a missing feature-flag guard.

Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-11-24T21:20:57.909Z
Learning: Applies to packages/swapper/src/swappers/*/utils/constants.ts : Define supported chain IDs for each swapper in utils/constants.ts with both 'sell' and 'buy' properties following the pattern: SupportedChainIds type

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11930
File: packages/chain-adapters/src/evm/soneium/SoneiumChainAdapter.ts:18-20
Timestamp: 2026-02-21T14:23:27.392Z
Learning: In packages/chain-adapters/src/evm/[chain]/[Chain]ChainAdapter.ts files for second-class EVM adapters, the type guard function (e.g., isSoneiumChainAdapter, isMantleChainAdapter) intentionally uses a simple pattern without defensive null/undefined checks: `(adapter as ChainAdapter).getType() === KnownChainIds.[Chain]Mainnet`. These simple type guards are exported for optional per-chain narrowing but are not actively used in hot paths. In practice, callers always check `getChainAdapterManager().get(chainId)` first, so null is never passed. The null-safe production code path uses `isSecondClassEvmAdapter` via `instanceof`. This pattern is consistent across 20+ second-class adapters (Berachain, HyperEvm, Base, Optimism, Linea, Monad, Scroll, Ink, Mode, Sonic, Bob, Plasma, Mantle, Katana, Cronos, MegaEth, Unichain, Soneium). Any defensive null-check additions should be done comprehensively across all adapters in a dedicated cleanup PR, not piecemeal.

Learnt from: 0xApotheosis
Repo: shapeshift/web PR: 10290
File: scripts/generateAssetData/color-map.json:41-47
Timestamp: 2025-08-17T21:53:03.806Z
Learning: In the ShapeShift web codebase, native assets (using CAIP-19 slip44 namespace like eip155:1/slip44:60, bip122:.../slip44:..., cosmos:.../slip44:...) are manually hardcoded and not generated via the automated asset generation script. Only ERC20/BEP20 tokens go through the asset generation process. The validation scripts should only validate generated assets, not manually added native assets.

Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-11-24T21:20:57.909Z
Learning: Applies to packages/swapper/src/swappers/*/*.ts : Implement filterAssetIdsBySellable method to filter assets by supported chain IDs in the sell property

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11932
File: src/lib/utils/worldchain.ts:39-41
Timestamp: 2026-02-22T12:23:52.513Z
Learning: In src/lib/utils/[chain].ts files for second-class EVM chains (e.g., worldchain.ts, katana.ts, etc.), the per-chain utility functions like getWorldChainTransactionStatus() are effectively dead code after the migration to using the generic SecondClassEvmAdapter.getTransactionStatus() handler. Code quality concerns (like structured logging) for these files are not relevant since they're no longer actively used in hot paths.

Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10375
File: src/state/migrations/index.ts:214-215
Timestamp: 2025-08-27T13:49:48.668Z
Learning: The clearAssetsMigrations system in the ShapeShift web app works independently of the root persistConfig version. Migration numbers (like 171) don't need to match the root persistConfig version field, and the system has been functioning correctly for months/years without manual version bumps.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T21:54:13.597Z
Learning: In scripts/addChain/codemods.ts, the `wrap()` helper intentionally uses `false` (from the engine) to mean "skipped/already present" and thrown exceptions to mean "error". The distinction between "anchor not found" vs "already present" in skip status is a known post-MVP UX improvement and does not affect scaffold correctness. Do not flag this as a masking issue.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T21:54:13.597Z
Learning: In scripts/addChain/engine.ts, the `addNamedImport()` idempotency key format is intentional for the current MVP scaffolder. Hardening the idempotency key approach is catalogued as a post-MVP improvement. Do not flag the current format as incorrect.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11078
File: src/setupVitest.ts:11-15
Timestamp: 2025-11-20T12:00:45.005Z
Learning: In shapeshift/web, src/setupVitest.ts must redirect 'ethers' to 'ethers5' for shapeshiftoss/hdwallet-trezor (and -trezor-connect), same as ledger and shapeshift-multichain. Removing 'trezor' from the regex causes CI/Vitest failures due to ethers v6 vs v5 API differences.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 12125
File: src/state/slices/portfolioSlice/portfolioSlice.ts:138-162
Timestamp: 2026-03-09T21:57:24.467Z
Learning: In `src/state/slices/portfolioSlice/portfolioSlice.ts`, the `clearNonEvmAccountsForWallet` reducer unconditionally deletes global accountMetadata/accountBalances/accounts records for non-EVM accountIds. This is safe because ShapeShift only connects one wallet at a time, so no other wallet can reference the same accountIds. The reducer is only called during explicit MetaMask native-multichain <> snap mode switches, so there is no cross-wallet collision risk in practice and no need to check other wallets before deleting global records.

Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10375
File: src/state/migrations/index.ts:214-215
Timestamp: 2025-08-27T13:49:48.668Z
Learning: The ShapeShift web app uses an automated versioning system for Redux Persist migrations. The version is calculated as `Math.max(...Object.keys(clearAssetsMigrations).map(Number))`, which automatically uses the highest migration number as the version. This eliminates the need to manually update persistConfig versions when adding new migrations - the system automatically bumps the version when new migration numbers are added to the migration objects.

Learnt from: gomes-bot
Repo: shapeshift/web PR: 12049
File: .npmrc:1-4
Timestamp: 2026-03-01T22:00:52.269Z
Learning: In shapeshift/web migration PRs (e.g., package manager migrations), intentionally match the previous tool's default behavior rather than introducing stricter enforcement or improvements. For example, during the yarn→pnpm migration, strict-peer-dependencies=false and auto-install-peers=true were intentionally set to mirror yarn's defaults. Hardening steps like enabling strict peer enforcement should be tracked as separate follow-up PRs after the migration lands and stabilizes, not included in the migration PR scope.

Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-11-24T21:20:57.909Z
Learning: Applies to packages/swapper/**/*.ts : Use TypeScript with explicit types (e.g., SupportedChainIds) for all code in the Swapper system

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10206
File: src/config.ts:127-128
Timestamp: 2025-08-07T11:20:44.614Z
Learning: gomesalexandre prefers required environment variables without default values in the config file (src/config.ts). They want explicit configuration and fail-fast behavior when environment variables are missing, rather than having fallback defaults.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/ContractInteractionBreakdown.tsx:0-0
Timestamp: 2025-09-13T16:45:18.813Z
Learning: gomesalexandre prefers aggressively deleting unused/obsolete code files ("ramboing") rather than fixing technical issues in code that won't be used, demonstrating his preference for keeping codebases clean and PR scope focused.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10458
File: src/plugins/walletConnectToDapps/types.ts:7-7
Timestamp: 2025-09-10T15:34:29.604Z
Learning: gomesalexandre is comfortable relying on transitive dependencies (like abitype through ethers/viem) rather than explicitly declaring them in package.json, preferring to avoid package.json bloat when the transitive dependency approach works reliably in practice.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10503
File: .env:56-56
Timestamp: 2025-09-16T13:17:02.938Z
Learning: gomesalexandre prefers to enable feature flags globally in the base .env file when the intent is to activate features everywhere, even when there are known issues like crashes, demonstrating his preference for intentional global feature rollouts over cautious per-environment enablement.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10249
File: src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx:447-503
Timestamp: 2025-08-13T17:07:10.763Z
Learning: gomesalexandre prefers relying on TypeScript's type system for validation rather than adding defensive runtime null checks when types are properly defined. They favor a TypeScript-first approach over defensive programming with runtime validations.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10276
File: src/hooks/useActionCenterSubscribers/useThorchainLpDepositActionSubscriber.tsx:61-66
Timestamp: 2025-08-14T17:51:47.556Z
Learning: gomesalexandre is not concerned about structured logging and prefers to keep console.error usage as-is rather than implementing structured logging patterns, even when project guidelines suggest otherwise.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10413
File: src/components/Modals/FiatRamps/fiatRampProviders/onramper/utils.ts:29-55
Timestamp: 2025-09-02T14:26:19.028Z
Learning: gomesalexandre prefers to keep preparatory/reference code simple until it's actively consumed, rather than implementing comprehensive error handling, validation, and robustness improvements upfront. They prefer to add these improvements when the code is actually being used in production.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10276
File: src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx:396-402
Timestamp: 2025-08-14T17:55:57.490Z
Learning: gomesalexandre is comfortable with functions/variables that return undefined or true (tri-state) when only the truthy case matters, preferring to rely on JavaScript's truthy/falsy behavior rather than explicitly returning boolean values.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10783
File: src/context/ModalStackProvider/useModalRegistration.ts:30-41
Timestamp: 2025-10-16T11:14:40.657Z
Learning: gomesalexandre prefers to add lint rules (like typescript-eslint/strict-boolean-expressions for truthiness checks on numbers) to catch common issues project-wide rather than relying on code review to catch them.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10206
File: src/lib/moralis.ts:47-85
Timestamp: 2025-08-07T11:22:16.983Z
Learning: gomesalexandre prefers console.error over structured logging for Moralis API integration debugging, as they find it more conventional and prefer to examine XHR requests directly rather than rely on structured logs for troubleshooting.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T21:54:13.597Z
Learning: In shapeshift/web, the batch-prefetch in src/lib/account/evm.ts gates on `wallet.ethGetAddresses`, which is chain-agnostic and works for any EVM-capable wallet regardless of chain-specific support flags like `supportsAbstract`. The chain-specific `supports*` guard is enforced downstream in `deriveEvmAccountIdsAndMetadata`. This pattern is identical across all second-class EVM chains and should not be flagged as a missing pre-check.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/EIP712MessageDisplay.tsx:133-137
Timestamp: 2025-09-12T10:15:10.389Z
Learning: gomesalexandre has identified that EIP-712 domain chainId should be preferred over request context chainId for accuracy in WalletConnect dApps structured signing flows. The domain chainId from the parsed message is more specific and accurate than the general request context, especially for asset resolution and network-specific operations.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T01:29:21.619Z
Learning: In shapeshift/web PR `#12181`, the primary fix is replacing SHA-based comparison (`privateSha`) with a content diff approach (`privateContentMatchesMain` boolean) in `deriveReleaseState`/`deriveHotfixState` in `scripts/release.ts`. This unblocks new releases when `private` has been squash-synced with `main` (SHA differs even though content is identical). The secondary fix — `createPr` returning `null` on "No commits between" GitHub error — is a defensive improvement bundled in the same PR. The PR title only references the secondary change; the commit message body captures both.

Comment on lines +1101 to +1135
// 40. Across swapper - conditional
if (c.swappers.across.supported) {
const acrossConstFile = r('packages/swapper/src/swappers/AcrossSwapper/constant.ts')
if (fs.existsSync(acrossConstFile)) {
results.push(
wrap(acrossConstFile, 'across-chain-support', () =>
addNamedImport(acrossConstFile, '@shapeshiftoss/caip', `${c.camelName}ChainId`),
),
)
}
}

// 41. Portals swapper - conditional
if (c.swappers.portals.supported) {
const portalsConstFile = r('packages/swapper/src/swappers/PortalsSwapper/constants.ts')
if (fs.existsSync(portalsConstFile)) {
results.push(
wrap(portalsConstFile, 'portals-chain-support', () =>
addNamedImport(portalsConstFile, '@shapeshiftoss/caip', `${c.camelName}ChainId`),
),
)
}
}

// 42. Zerion - conditional
if (c.swappers.zerion.supported) {
const zerionFile = r('packages/types/src/zerion.ts')
if (fs.existsSync(zerionFile)) {
results.push(
wrap(zerionFile, 'zerion-chain-support', () =>
addNamedImport(zerionFile, '@shapeshiftoss/caip', `${c.camelName}ChainId`),
),
)
}
}
Copy link
Contributor

@coderabbitai coderabbitai bot Mar 17, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

These supported swapper branches are effectively no-ops.

When supported is true, Across/Portals/Zerion only gain a ${c.camelName}ChainId import. Nothing here updates supported-chain constants, sell/buy filters, or network mappings, so the scaffolder can report success while the swapper remains unsupported and the inserted import is likely unused. Either scaffold the real support surfaces here or keep these integrations in the manual checklist.

Based on learnings: Applies to packages/swapper/src/swappers/*/utils/constants.ts : Define supported chain IDs for each swapper in utils/constants.ts with both sell and buy properties following the pattern: SupportedChainIds type.

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

In `@scripts/addChain/codemods.ts` around lines 1101 - 1135, The current
conditional branches that check c.swappers.across.supported,
c.swappers.portals.supported and c.swappers.zerion.supported only add a named
import (via addNamedImport) into AcrossSwapper/constant.ts,
PortalsSwapper/constants.ts and packages/types/src/zerion.ts respectively, which
leaves the swappers functionally unsupported and produces unused imports; update
each branch to also scaffold the actual supported-chain constants and filters by
adding the SupportedChainIds structure (with sell and buy keys) into the
swapper's utils/constants.ts (or constants.ts) and update any supported-chain
mappings or network mappings used by the swappers so the import becomes used and
the swapper is truly enabled (ensure you follow the SupportedChainIds type
pattern and update sell/buy filters and any network mapping arrays referenced by
the swappers when adding ${c.camelName}ChainId).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

acknowledged — full swapper integration varies per swapper; will tighten when those swappers get Abstract support

Copy link
Contributor

Choose a reason for hiding this comment

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

@gomesalexandre, understood — that makes sense given swapper integration varies per swapper and needs research beyond scaffolding. Would you like me to open a follow-up GitHub issue to track tightening the Across/Portals/Zerion scaffolding branches for Abstract (and future chains) when those swappers add support?


🧠 Learnings used
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11569
File: headers/csps/chains/katana.ts:8-10
Timestamp: 2026-01-07T15:36:13.236Z
Learning: In CSP chain files (headers/csps/chains/*.ts), explicitly filtering undefined environment variables with .filter(Boolean) is unnecessary because serializeCsp() in headers/util.ts filters all falsy values during serialization at line 51: `.map(([k, v]) => [k, v.filter(x => !!x)])`. The direct pattern [env.VITE_*_NODE_URL] is sufficient and preferred for consistency with second-class chain CSP files like plasma.ts and monad.ts.
<!-- </add_learning>

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11275
File: headers/csps/chains/plasma.ts:1-10
Timestamp: 2025-12-03T23:19:39.158Z
Learning: For CSP files in headers/csps/chains/, gomesalexandre prefers using Vite's loadEnv() pattern directly to load environment variables (e.g., VITE_PLASMA_NODE_URL, VITE_MONAD_NODE_URL) for consistency with existing second-class chain CSP files, rather than using getConfig() from src/config.ts, even though other parts of the codebase use validated config values.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11924
File: packages/chain-adapters/src/evm/mantle/MantleChainAdapter.ts:1-1
Timestamp: 2026-02-21T10:55:55.870Z
Learning: For second-class EVM chain adapters (those extending SecondClassEvmAdapter), the type guard function (e.g., isMantleChainAdapter, isKatanaChainAdapter, isUnichainChainAdapter) exists in BOTH locations: in the adapter file itself (packages/chain-adapters/src/evm/[chain]/[Chain]ChainAdapter.ts) AND in src/lib/utils/[chain].ts with defensive null/undefined checks. This pattern is consistent across at least 14 second-class adapters (base, berachain, cronos, hyperevm, ink, katana, linea, mantle, megaeth, monad, optimism, plasma, scroll, sonic, unichain) and should be maintained for consistency unless a comprehensive refactor across all adapters is undertaken.

Learnt from: kaladinlight
Repo: shapeshift/web PR: 11290
File: packages/chain-adapters/src/utxo/zcash/ZcashChainAdapter.ts:48-51
Timestamp: 2025-12-04T22:57:50.850Z
Learning: In packages/chain-adapters/src/**/*ChainAdapter.ts files, the getName() method uses the pattern `const enumIndex = Object.values(ChainAdapterDisplayName).indexOf(ChainAdapterDisplayName.XXX); return Object.keys(ChainAdapterDisplayName)[enumIndex]` to reverse-lookup the enum key from its value. This is the established pattern used consistently across almost all chain adapters (Bitcoin, Ethereum, Litecoin, Dogecoin, Polygon, Arbitrum, Cosmos, etc.) and should be preserved for consistency when adding new chain adapters.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T20:28:34.883Z
Learning: In shapeshift/web, chains added to `walletConnectV2OptionalChains` and `rpcMap` in `src/context/WalletProvider/WalletConnectV2/config.ts` are intentionally NOT gated by their feature flags. Feature-flagged chains (e.g., ink, flowEvmChain, sei, abstract) are unconditionally included in these WalletConnect V2 structures. This is the established convention and should not be flagged as a missing feature-flag guard.

Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-11-24T21:20:57.909Z
Learning: Applies to packages/swapper/src/swappers/*/utils/constants.ts : Define supported chain IDs for each swapper in utils/constants.ts with both 'sell' and 'buy' properties following the pattern: SupportedChainIds type

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11930
File: packages/chain-adapters/src/evm/soneium/SoneiumChainAdapter.ts:18-20
Timestamp: 2026-02-21T14:23:27.392Z
Learning: In packages/chain-adapters/src/evm/[chain]/[Chain]ChainAdapter.ts files for second-class EVM adapters, the type guard function (e.g., isSoneiumChainAdapter, isMantleChainAdapter) intentionally uses a simple pattern without defensive null/undefined checks: `(adapter as ChainAdapter).getType() === KnownChainIds.[Chain]Mainnet`. These simple type guards are exported for optional per-chain narrowing but are not actively used in hot paths. In practice, callers always check `getChainAdapterManager().get(chainId)` first, so null is never passed. The null-safe production code path uses `isSecondClassEvmAdapter` via `instanceof`. This pattern is consistent across 20+ second-class adapters (Berachain, HyperEvm, Base, Optimism, Linea, Monad, Scroll, Ink, Mode, Sonic, Bob, Plasma, Mantle, Katana, Cronos, MegaEth, Unichain, Soneium). Any defensive null-check additions should be done comprehensively across all adapters in a dedicated cleanup PR, not piecemeal.

Learnt from: 0xApotheosis
Repo: shapeshift/web PR: 10290
File: scripts/generateAssetData/color-map.json:41-47
Timestamp: 2025-08-17T21:53:03.806Z
Learning: In the ShapeShift web codebase, native assets (using CAIP-19 slip44 namespace like eip155:1/slip44:60, bip122:.../slip44:..., cosmos:.../slip44:...) are manually hardcoded and not generated via the automated asset generation script. Only ERC20/BEP20 tokens go through the asset generation process. The validation scripts should only validate generated assets, not manually added native assets.

Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-11-24T21:20:57.909Z
Learning: Applies to packages/swapper/src/swappers/*/*.ts : Implement filterAssetIdsBySellable method to filter assets by supported chain IDs in the sell property

Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-11-24T21:20:57.909Z
Learning: Applies to packages/swapper/src/swappers/*/*.ts : Implement filterBuyAssetsBySellAssetId method to filter assets by supported chain IDs in the buy property

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11941
File: packages/swapper/src/swappers/DebridgeSwapper/constant.ts:1-39
Timestamp: 2026-02-24T12:43:24.555Z
Learning: In shapeshift/web, swappers do not have a single enforced location for constants files. Many DEX-style swappers place them at packages/swapper/src/swappers/<SwapperName>/utils/constants.ts (e.g., ZrxSwapper, JupiterSwapper, CetusSwapper, AvnuSwapper, ButterSwap, StonfiSwapper, SunioSwapper, ArbitrumBridgeSwapper), while several bridge-oriented swappers (AcrossSwapper, RelaySwapper, PortalsSwapper, ChainflipSwapper) use a root-level constants file at packages/swapper/src/swappers/<SwapperName>/constant.ts. For consistency with bridge-style swappers, DebridgeSwapper should keep constant.ts at the swapper root.

Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-11-24T21:20:57.909Z
Learning: Applies to packages/swapper/**/*.ts : Use TypeScript with explicit types (e.g., SupportedChainIds) for all code in the Swapper system

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-16T21:35:02.159Z
Learning: In packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts (and related files like src/components/MultiHopTrade/components/TradeConfirm/hooks/useChainflipStreamingProgress.tsx), nullish checks (`== null` / `!= null`) MUST be used for `chainflipSwapId` instead of falsy checks, because `0` is a valid u64 swap ID that is falsy in JavaScript. Using `if (!chainflipSwapId)` would incorrectly discard a valid swap ID of `0`.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11335
File: packages/swapper/src/swappers/CetusSwapper/utils/helpers.ts:3-3
Timestamp: 2025-12-09T21:07:22.474Z
Learning: In packages/swapper/src/swappers/CetusSwapper, mysten/sui types (SuiClient, Transaction) must be imported from the nested path within cetusprotocol/aggregator-sdk (e.g., 'cetusprotocol/aggregator-sdk/node_modules/mysten/sui/client') because the aggregator SDK bundles its own version of mysten/sui. Direct imports from 'mysten/sui' break at runtime even when specified in package.json.

Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-11-24T21:20:57.909Z
Learning: Applies to packages/swapper/src/swappers/**/*.ts : Adhere to the Swapper directory structure: each swapper resides in packages/swapper/src/swappers/<SwapperName>/ with required files (SwapperName.ts, endpoints.ts, types.ts, utils/constants.ts, utils/helpers.ts)

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T21:54:13.597Z
Learning: In shapeshift/web, the batch-prefetch in src/lib/account/evm.ts gates on `wallet.ethGetAddresses`, which is chain-agnostic and works for any EVM-capable wallet regardless of chain-specific support flags like `supportsAbstract`. The chain-specific `supports*` guard is enforced downstream in `deriveEvmAccountIdsAndMetadata`. This pattern is identical across all second-class EVM chains and should not be flagged as a missing pre-check.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11281
File: packages/swapper/src/swappers/PortalsSwapper/utils/fetchSquidStatus.ts:98-106
Timestamp: 2025-12-04T11:05:01.146Z
Learning: In packages/swapper/src/swappers/PortalsSwapper/utils/fetchSquidStatus.ts, getSquidTrackingLink should return blockchain explorer links (using Asset.explorerTxLink) rather than API endpoints. For non-GMP Squid swaps: return source chain explorer link with sourceTxHash when pending/failed, and destination chain explorer link with destinationTxHash when confirmed.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 12178
File: packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts:238-239
Timestamp: 2026-03-16T18:38:42.205Z
Learning: In packages/swapper/src/swappers/ChainflipSwapper, `chainflipSwapId` intentionally uses a `number | string` union type. The Chainflip SDK (`swapResponse.id`) returns a `number`, while the status API (`status.swapId`) returns a `string` representing a u64. The `Number()` coercion must NOT be applied to the status API value because u64 can exceed JavaScript's `Number.MAX_SAFE_INTEGER` (2^53-1), causing precision loss. The string is kept as-is and flows directly into URL parameters and metadata.

Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-11-24T21:20:57.909Z
Learning: Applies to packages/swapper/src/swappers/*/*.ts : All swappers must implement the Swapper interface from packages/swapper/src/types.ts

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11016
File: packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts:93-93
Timestamp: 2025-11-12T12:48:02.977Z
Learning: In the swapper architecture, timeout handling is implemented at the abstraction layer in packages/swapper/src/swapper.ts using timeoutMonadic, which wraps all calls to individual swapper implementations. Individual swapper implementations (e.g., NearIntentsSwapper, PortalsSwapper, etc.) should NOT use timeoutMonadic directly—they simply return their results and the abstraction layer handles timeout concerns centrally.

Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-11-24T21:20:57.909Z
Learning: Applies to packages/swapper/src/constants.ts : Register new swappers in packages/swapper/src/constants.ts with an entry in the swappers registry mapping SwapperName enum to swapper implementation

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T21:54:13.597Z
Learning: In scripts/addChain/codemods.ts, the `wrap()` helper intentionally uses `false` (from the engine) to mean "skipped/already present" and thrown exceptions to mean "error". The distinction between "anchor not found" vs "already present" in skip status is a known post-MVP UX improvement and does not affect scaffold correctness. Do not flag this as a masking issue.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T21:54:13.597Z
Learning: In scripts/addChain/engine.ts, the `addNamedImport()` idempotency key format is intentional for the current MVP scaffolder. Hardening the idempotency key approach is catalogued as a post-MVP improvement. Do not flag the current format as incorrect.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11932
File: src/lib/utils/worldchain.ts:39-41
Timestamp: 2026-02-22T12:23:52.513Z
Learning: In src/lib/utils/[chain].ts files for second-class EVM chains (e.g., worldchain.ts, katana.ts, etc.), the per-chain utility functions like getWorldChainTransactionStatus() are effectively dead code after the migration to using the generic SecondClassEvmAdapter.getTransactionStatus() handler. Code quality concerns (like structured logging) for these files are not relevant since they're no longer actively used in hot paths.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10206
File: src/config.ts:127-128
Timestamp: 2025-08-07T11:20:44.614Z
Learning: gomesalexandre prefers required environment variables without default values in the config file (src/config.ts). They want explicit configuration and fail-fast behavior when environment variables are missing, rather than having fallback defaults.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/ContractInteractionBreakdown.tsx:0-0
Timestamp: 2025-09-13T16:45:18.813Z
Learning: gomesalexandre prefers aggressively deleting unused/obsolete code files ("ramboing") rather than fixing technical issues in code that won't be used, demonstrating his preference for keeping codebases clean and PR scope focused.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10458
File: src/plugins/walletConnectToDapps/types.ts:7-7
Timestamp: 2025-09-10T15:34:29.604Z
Learning: gomesalexandre is comfortable relying on transitive dependencies (like abitype through ethers/viem) rather than explicitly declaring them in package.json, preferring to avoid package.json bloat when the transitive dependency approach works reliably in practice.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10503
File: .env:56-56
Timestamp: 2025-09-16T13:17:02.938Z
Learning: gomesalexandre prefers to enable feature flags globally in the base .env file when the intent is to activate features everywhere, even when there are known issues like crashes, demonstrating his preference for intentional global feature rollouts over cautious per-environment enablement.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10249
File: src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx:447-503
Timestamp: 2025-08-13T17:07:10.763Z
Learning: gomesalexandre prefers relying on TypeScript's type system for validation rather than adding defensive runtime null checks when types are properly defined. They favor a TypeScript-first approach over defensive programming with runtime validations.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10276
File: src/hooks/useActionCenterSubscribers/useThorchainLpDepositActionSubscriber.tsx:61-66
Timestamp: 2025-08-14T17:51:47.556Z
Learning: gomesalexandre is not concerned about structured logging and prefers to keep console.error usage as-is rather than implementing structured logging patterns, even when project guidelines suggest otherwise.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10413
File: src/components/Modals/FiatRamps/fiatRampProviders/onramper/utils.ts:29-55
Timestamp: 2025-09-02T14:26:19.028Z
Learning: gomesalexandre prefers to keep preparatory/reference code simple until it's actively consumed, rather than implementing comprehensive error handling, validation, and robustness improvements upfront. They prefer to add these improvements when the code is actually being used in production.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10276
File: src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx:396-402
Timestamp: 2025-08-14T17:55:57.490Z
Learning: gomesalexandre is comfortable with functions/variables that return undefined or true (tri-state) when only the truthy case matters, preferring to rely on JavaScript's truthy/falsy behavior rather than explicitly returning boolean values.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10783
File: src/context/ModalStackProvider/useModalRegistration.ts:30-41
Timestamp: 2025-10-16T11:14:40.657Z
Learning: gomesalexandre prefers to add lint rules (like typescript-eslint/strict-boolean-expressions for truthiness checks on numbers) to catch common issues project-wide rather than relying on code review to catch them.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10206
File: src/lib/moralis.ts:47-85
Timestamp: 2025-08-07T11:22:16.983Z
Learning: gomesalexandre prefers console.error over structured logging for Moralis API integration debugging, as they find it more conventional and prefer to examine XHR requests directly rather than rely on structured logs for troubleshooting.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/EIP712MessageDisplay.tsx:133-137
Timestamp: 2025-09-12T10:15:10.389Z
Learning: gomesalexandre has identified that EIP-712 domain chainId should be preferred over request context chainId for accuracy in WalletConnect dApps structured signing flows. The domain chainId from the parsed message is more specific and accurate than the general request context, especially for asset resolution and network-specific operations.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T01:29:21.619Z
Learning: In shapeshift/web PR `#12181`, the primary fix is replacing SHA-based comparison (`privateSha`) with a content diff approach (`privateContentMatchesMain` boolean) in `deriveReleaseState`/`deriveHotfixState` in `scripts/release.ts`. This unblocks new releases when `private` has been squash-synced with `main` (SHA differs even though content is identical). The secondary fix — `createPr` returning `null` on "No commits between" GitHub error — is a defensive improvement bundled in the same PR. The PR title only references the secondary change; the commit message body captures both.

Learnt from: gomes-bot
Repo: shapeshift/web PR: 11884
File: packages/chain-adapters/src/tron/TronChainAdapter.ts:732-735
Timestamp: 2026-02-16T15:00:09.111Z
Learning: In packages/chain-adapters/src/tron/TronChainAdapter.ts, inline comments explaining non-obvious domain-specific behavior (e.g., why TRC20 burns to zero address are allowed while mints from zero address are skipped) are acceptable when explicitly requested, especially when the rationale is easy to regress (e.g., sTRX unstaking burn behavior).

Comment on lines +1529 to +1552
const adapterDir = r(`packages/chain-adapters/src/evm/${c.camelName}`)
const adapterFile = r(
`packages/chain-adapters/src/evm/${c.camelName}/${c.pascalName}ChainAdapter.ts`,
)
if (!fs.existsSync(adapterFile)) {
fs.mkdirSync(adapterDir, { recursive: true })
fs.writeFileSync(adapterFile, fill(tmpl('chainAdapter.ts.tmpl'), c))
fs.writeFileSync(
r(`packages/chain-adapters/src/evm/${c.camelName}/index.ts`),
fill(tmpl('chainAdapterIndex.ts.tmpl'), c),
)
results.push({
file: adapterFile,
operation: 'create-chain-adapter',
status: 'inserted',
})
} else {
results.push({
file: adapterFile,
operation: 'create-chain-adapter',
status: 'skipped',
message: 'already exists',
})
}
Copy link
Contributor

@coderabbitai coderabbitai bot Mar 17, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Handle partial adapter generation instead of keying only off the class file.

This block creates two artifacts—the chain adapter class and the folder index.ts—but reruns skip as soon as the class file exists. If a previous run stopped between those writes, the missing index.ts is never repaired, so the scaffolder is not actually idempotent.

🧩 Suggested fix
   const adapterDir = r(`packages/chain-adapters/src/evm/${c.camelName}`)
   const adapterFile = r(
     `packages/chain-adapters/src/evm/${c.camelName}/${c.pascalName}ChainAdapter.ts`,
   )
-  if (!fs.existsSync(adapterFile)) {
+  const adapterIndexFile = r(`packages/chain-adapters/src/evm/${c.camelName}/index.ts`)
+  if (!fs.existsSync(adapterFile) || !fs.existsSync(adapterIndexFile)) {
     fs.mkdirSync(adapterDir, { recursive: true })
-    fs.writeFileSync(adapterFile, fill(tmpl('chainAdapter.ts.tmpl'), c))
-    fs.writeFileSync(
-      r(`packages/chain-adapters/src/evm/${c.camelName}/index.ts`),
-      fill(tmpl('chainAdapterIndex.ts.tmpl'), c),
-    )
+    if (!fs.existsSync(adapterFile)) {
+      fs.writeFileSync(adapterFile, fill(tmpl('chainAdapter.ts.tmpl'), c))
+    }
+    if (!fs.existsSync(adapterIndexFile)) {
+      fs.writeFileSync(adapterIndexFile, fill(tmpl('chainAdapterIndex.ts.tmpl'), c))
+    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/addChain/codemods.ts` around lines 1529 - 1552, The scaffold
currently decides to skip creation based solely on adapterFile existence
(variable adapterFile) which leaves index.ts missing if a previous run failed;
update the logic in codemods.ts to check both the class file and the index file
(the path used in the second writeFileSync call) — if the directory doesn't
exist create it, then individually ensure the class file and the index.ts are
created when absent (using the same fill(tmpl(...), c) calls), and push
appropriate results entries for each artifact instead of a single
skipped/inserted result so partial generation is repaired on re-run.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

post-MVP — noted

Copy link
Contributor

Choose a reason for hiding this comment

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

@gomesalexandre, understood — acknowledged as a post-MVP improvement.


✏️ Learnings added
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 12186
File: scripts/addChain/codemods.ts:1529-1552
Timestamp: 2026-03-17T22:57:18.383Z
Learning: In scripts/addChain/codemods.ts, the chain adapter scaffold checks only for the class file (e.g., AbstractChainAdapter.ts) to determine if creation should be skipped, not the index.ts. If a prior run stopped between writes, the missing index.ts is never repaired. This partial-generation idempotency gap is intentionally deferred as a post-MVP improvement by gomesalexandre.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11569
File: headers/csps/chains/katana.ts:8-10
Timestamp: 2026-01-07T15:36:13.236Z
Learning: In CSP chain files (headers/csps/chains/*.ts), explicitly filtering undefined environment variables with .filter(Boolean) is unnecessary because serializeCsp() in headers/util.ts filters all falsy values during serialization at line 51: `.map(([k, v]) => [k, v.filter(x => !!x)])`. The direct pattern [env.VITE_*_NODE_URL] is sufficient and preferred for consistency with second-class chain CSP files like plasma.ts and monad.ts.
<!-- </add_learning>

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11275
File: headers/csps/chains/plasma.ts:1-10
Timestamp: 2025-12-03T23:19:39.158Z
Learning: For CSP files in headers/csps/chains/, gomesalexandre prefers using Vite's loadEnv() pattern directly to load environment variables (e.g., VITE_PLASMA_NODE_URL, VITE_MONAD_NODE_URL) for consistency with existing second-class chain CSP files, rather than using getConfig() from src/config.ts, even though other parts of the codebase use validated config values.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11924
File: packages/chain-adapters/src/evm/mantle/MantleChainAdapter.ts:1-1
Timestamp: 2026-02-21T10:55:55.870Z
Learning: For second-class EVM chain adapters (those extending SecondClassEvmAdapter), the type guard function (e.g., isMantleChainAdapter, isKatanaChainAdapter, isUnichainChainAdapter) exists in BOTH locations: in the adapter file itself (packages/chain-adapters/src/evm/[chain]/[Chain]ChainAdapter.ts) AND in src/lib/utils/[chain].ts with defensive null/undefined checks. This pattern is consistent across at least 14 second-class adapters (base, berachain, cronos, hyperevm, ink, katana, linea, mantle, megaeth, monad, optimism, plasma, scroll, sonic, unichain) and should be maintained for consistency unless a comprehensive refactor across all adapters is undertaken.

Learnt from: kaladinlight
Repo: shapeshift/web PR: 11290
File: packages/chain-adapters/src/utxo/zcash/ZcashChainAdapter.ts:48-51
Timestamp: 2025-12-04T22:57:50.850Z
Learning: In packages/chain-adapters/src/**/*ChainAdapter.ts files, the getName() method uses the pattern `const enumIndex = Object.values(ChainAdapterDisplayName).indexOf(ChainAdapterDisplayName.XXX); return Object.keys(ChainAdapterDisplayName)[enumIndex]` to reverse-lookup the enum key from its value. This is the established pattern used consistently across almost all chain adapters (Bitcoin, Ethereum, Litecoin, Dogecoin, Polygon, Arbitrum, Cosmos, etc.) and should be preserved for consistency when adding new chain adapters.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T20:28:34.883Z
Learning: In shapeshift/web, chains added to `walletConnectV2OptionalChains` and `rpcMap` in `src/context/WalletProvider/WalletConnectV2/config.ts` are intentionally NOT gated by their feature flags. Feature-flagged chains (e.g., ink, flowEvmChain, sei, abstract) are unconditionally included in these WalletConnect V2 structures. This is the established convention and should not be flagged as a missing feature-flag guard.

Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-11-24T21:20:57.909Z
Learning: Applies to packages/swapper/src/swappers/*/utils/constants.ts : Define supported chain IDs for each swapper in utils/constants.ts with both 'sell' and 'buy' properties following the pattern: SupportedChainIds type

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11930
File: packages/chain-adapters/src/evm/soneium/SoneiumChainAdapter.ts:18-20
Timestamp: 2026-02-21T14:23:27.392Z
Learning: In packages/chain-adapters/src/evm/[chain]/[Chain]ChainAdapter.ts files for second-class EVM adapters, the type guard function (e.g., isSoneiumChainAdapter, isMantleChainAdapter) intentionally uses a simple pattern without defensive null/undefined checks: `(adapter as ChainAdapter).getType() === KnownChainIds.[Chain]Mainnet`. These simple type guards are exported for optional per-chain narrowing but are not actively used in hot paths. In practice, callers always check `getChainAdapterManager().get(chainId)` first, so null is never passed. The null-safe production code path uses `isSecondClassEvmAdapter` via `instanceof`. This pattern is consistent across 20+ second-class adapters (Berachain, HyperEvm, Base, Optimism, Linea, Monad, Scroll, Ink, Mode, Sonic, Bob, Plasma, Mantle, Katana, Cronos, MegaEth, Unichain, Soneium). Any defensive null-check additions should be done comprehensively across all adapters in a dedicated cleanup PR, not piecemeal.

Learnt from: 0xApotheosis
Repo: shapeshift/web PR: 10290
File: scripts/generateAssetData/color-map.json:41-47
Timestamp: 2025-08-17T21:53:03.806Z
Learning: In the ShapeShift web codebase, native assets (using CAIP-19 slip44 namespace like eip155:1/slip44:60, bip122:.../slip44:..., cosmos:.../slip44:...) are manually hardcoded and not generated via the automated asset generation script. Only ERC20/BEP20 tokens go through the asset generation process. The validation scripts should only validate generated assets, not manually added native assets.

Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-11-24T21:20:57.909Z
Learning: Applies to packages/swapper/src/swappers/*/*.ts : Implement filterAssetIdsBySellable method to filter assets by supported chain IDs in the sell property

Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-11-24T21:20:57.909Z
Learning: Applies to packages/swapper/src/swappers/*/*.ts : Implement filterBuyAssetsBySellAssetId method to filter assets by supported chain IDs in the buy property

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T21:54:13.597Z
Learning: In shapeshift/web, the batch-prefetch in src/lib/account/evm.ts gates on `wallet.ethGetAddresses`, which is chain-agnostic and works for any EVM-capable wallet regardless of chain-specific support flags like `supportsAbstract`. The chain-specific `supports*` guard is enforced downstream in `deriveEvmAccountIdsAndMetadata`. This pattern is identical across all second-class EVM chains and should not be flagged as a missing pre-check.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10857
File: src/plugins/walletConnectToDapps/eventsManager/useWalletConnectEventsHandler.ts:101-104
Timestamp: 2025-10-23T14:27:19.073Z
Learning: In WalletConnect wallet_switchEthereumChain and wallet_addEthereumChain requests, the chainId parameter is always present as per the protocol spec. Type guards checking for missing chainId in these handlers (like `if (!evmNetworkIdHex) return`) are solely for TypeScript compiler satisfaction, not real runtime edge cases.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-16T21:35:02.159Z
Learning: In packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts (and related files like src/components/MultiHopTrade/components/TradeConfirm/hooks/useChainflipStreamingProgress.tsx), nullish checks (`== null` / `!= null`) MUST be used for `chainflipSwapId` instead of falsy checks, because `0` is a valid u64 swap ID that is falsy in JavaScript. Using `if (!chainflipSwapId)` would incorrectly discard a valid swap ID of `0`.

Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10380
File: src/components/TradeAssetSearch/hooks/useGetPopularAssetsQuery.tsx:28-33
Timestamp: 2025-09-04T17:29:59.479Z
Learning: In shapeshift/web, the useGetPopularAssetsQuery function in src/components/TradeAssetSearch/hooks/useGetPopularAssetsQuery.tsx intentionally uses primaryAssets[assetId] instead of falling back to assets[assetId]. The design distributes primary assets across chains by iterating through their related assets and adding the primary asset to each related asset's chain. This ensures primary assets appear in all chains where they have related assets, supporting the grouped asset system.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11569
File: packages/chain-adapters/src/evm/katana/KatanaChainAdapter.ts:44-46
Timestamp: 2026-01-05T23:24:54.841Z
Learning: In packages/chain-adapters/src/evm/**/[chain]ChainAdapter.ts files, second-class EVM chain adapters (those extending SecondClassEvmAdapter, such as Monad, Plasma, HyperEVM, and Katana) use hardcoded strings in their getName() method (e.g., `return 'Monad'`), NOT the enum reverse-lookup pattern. The enum reverse-lookup pattern (`Object.values(ChainAdapterDisplayName).indexOf(...)`) only applies to first-class chain adapters.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11932
File: src/lib/utils/worldchain.ts:39-41
Timestamp: 2026-02-22T12:23:52.513Z
Learning: In src/lib/utils/[chain].ts files for second-class EVM chains (e.g., worldchain.ts, katana.ts, etc.), the per-chain utility functions like getWorldChainTransactionStatus() are effectively dead code after the migration to using the generic SecondClassEvmAdapter.getTransactionStatus() handler. Code quality concerns (like structured logging) for these files are not relevant since they're no longer actively used in hot paths.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11078
File: src/setupVitest.ts:11-15
Timestamp: 2025-11-20T12:00:45.005Z
Learning: In shapeshift/web, src/setupVitest.ts must redirect 'ethers' to 'ethers5' for shapeshiftoss/hdwallet-trezor (and -trezor-connect), same as ledger and shapeshift-multichain. Removing 'trezor' from the regex causes CI/Vitest failures due to ethers v6 vs v5 API differences.

Learnt from: kaladinlight
Repo: shapeshift/web PR: 10369
File: packages/chain-adapters/src/cosmossdk/CosmosSdkBaseAdapter.ts:167-176
Timestamp: 2025-08-26T19:04:38.672Z
Learning: In packages/chain-adapters/src/cosmossdk/CosmosSdkBaseAdapter.ts, when processing assets from data.assets.reduce(), the team prefers using empty catch blocks to gracefully skip any assets that fail processing, rather than specific error type handling, to avoid useless noise and ensure robust asset filtering.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T21:54:13.597Z
Learning: In scripts/addChain/engine.ts, the `addNamedImport()` idempotency key format is intentional for the current MVP scaffolder. Hardening the idempotency key approach is catalogued as a post-MVP improvement. Do not flag the current format as incorrect.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T21:54:13.597Z
Learning: In scripts/addChain/codemods.ts, the `wrap()` helper intentionally uses `false` (from the engine) to mean "skipped/already present" and thrown exceptions to mean "error". The distinction between "anchor not found" vs "already present" in skip status is a known post-MVP UX improvement and does not affect scaffold correctness. Do not flag this as a masking issue.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/hooks/useSimulateEvmTransaction.ts:0-0
Timestamp: 2025-09-12T13:44:17.019Z
Learning: gomesalexandre prefers letting chain adapter errors throw naturally in useSimulateEvmTransaction rather than adding explicit error handling for missing adapters, consistent with his fail-fast approach and dismissal of defensive validation as "stale" in WalletConnect transaction simulation flows.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11012
File: src/context/WalletProvider/Vultisig/components/Connect.tsx:24-59
Timestamp: 2025-11-19T16:59:50.569Z
Learning: In src/context/WalletProvider/*/components/Connect.tsx files across the ShapeShift web codebase, the established pattern for handling null/undefined adapter from getAdapter() is to simply check `if (adapter) { ... }` without an else clause. All wallet Connect components (Coinbase, Keplr, Phantom, Ledger, MetaMask, WalletConnectV2, KeepKey, Vultisig) follow this pattern—they reset loading state after the if block but do not show error messages when adapter is null. This is an intentional design decision and should be maintained for consistency.

Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-11-24T21:20:57.909Z
Learning: Applies to packages/swapper/**/*.ts : Use TypeScript with explicit types (e.g., SupportedChainIds) for all code in the Swapper system

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10206
File: src/config.ts:127-128
Timestamp: 2025-08-07T11:20:44.614Z
Learning: gomesalexandre prefers required environment variables without default values in the config file (src/config.ts). They want explicit configuration and fail-fast behavior when environment variables are missing, rather than having fallback defaults.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/ContractInteractionBreakdown.tsx:0-0
Timestamp: 2025-09-13T16:45:18.813Z
Learning: gomesalexandre prefers aggressively deleting unused/obsolete code files ("ramboing") rather than fixing technical issues in code that won't be used, demonstrating his preference for keeping codebases clean and PR scope focused.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10458
File: src/plugins/walletConnectToDapps/types.ts:7-7
Timestamp: 2025-09-10T15:34:29.604Z
Learning: gomesalexandre is comfortable relying on transitive dependencies (like abitype through ethers/viem) rather than explicitly declaring them in package.json, preferring to avoid package.json bloat when the transitive dependency approach works reliably in practice.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10503
File: .env:56-56
Timestamp: 2025-09-16T13:17:02.938Z
Learning: gomesalexandre prefers to enable feature flags globally in the base .env file when the intent is to activate features everywhere, even when there are known issues like crashes, demonstrating his preference for intentional global feature rollouts over cautious per-environment enablement.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10249
File: src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx:447-503
Timestamp: 2025-08-13T17:07:10.763Z
Learning: gomesalexandre prefers relying on TypeScript's type system for validation rather than adding defensive runtime null checks when types are properly defined. They favor a TypeScript-first approach over defensive programming with runtime validations.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10276
File: src/hooks/useActionCenterSubscribers/useThorchainLpDepositActionSubscriber.tsx:61-66
Timestamp: 2025-08-14T17:51:47.556Z
Learning: gomesalexandre is not concerned about structured logging and prefers to keep console.error usage as-is rather than implementing structured logging patterns, even when project guidelines suggest otherwise.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10413
File: src/components/Modals/FiatRamps/fiatRampProviders/onramper/utils.ts:29-55
Timestamp: 2025-09-02T14:26:19.028Z
Learning: gomesalexandre prefers to keep preparatory/reference code simple until it's actively consumed, rather than implementing comprehensive error handling, validation, and robustness improvements upfront. They prefer to add these improvements when the code is actually being used in production.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10276
File: src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx:396-402
Timestamp: 2025-08-14T17:55:57.490Z
Learning: gomesalexandre is comfortable with functions/variables that return undefined or true (tri-state) when only the truthy case matters, preferring to rely on JavaScript's truthy/falsy behavior rather than explicitly returning boolean values.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10783
File: src/context/ModalStackProvider/useModalRegistration.ts:30-41
Timestamp: 2025-10-16T11:14:40.657Z
Learning: gomesalexandre prefers to add lint rules (like typescript-eslint/strict-boolean-expressions for truthiness checks on numbers) to catch common issues project-wide rather than relying on code review to catch them.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10206
File: src/lib/moralis.ts:47-85
Timestamp: 2025-08-07T11:22:16.983Z
Learning: gomesalexandre prefers console.error over structured logging for Moralis API integration debugging, as they find it more conventional and prefer to examine XHR requests directly rather than rely on structured logs for troubleshooting.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/EIP712MessageDisplay.tsx:133-137
Timestamp: 2025-09-12T10:15:10.389Z
Learning: gomesalexandre has identified that EIP-712 domain chainId should be preferred over request context chainId for accuracy in WalletConnect dApps structured signing flows. The domain chainId from the parsed message is more specific and accurate than the general request context, especially for asset resolution and network-specific operations.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T01:29:21.619Z
Learning: In shapeshift/web PR `#12181`, the primary fix is replacing SHA-based comparison (`privateSha`) with a content diff approach (`privateContentMatchesMain` boolean) in `deriveReleaseState`/`deriveHotfixState` in `scripts/release.ts`. This unblocks new releases when `private` has been squash-synced with `main` (SHA differs even though content is identical). The secondary fix — `createPr` returning `null` on "No commits between" GitHub error — is a defensive improvement bundled in the same PR. The PR title only references the secondary change; the commit message body captures both.

Learnt from: gomes-bot
Repo: shapeshift/web PR: 11884
File: packages/chain-adapters/src/tron/TronChainAdapter.ts:732-735
Timestamp: 2026-02-16T15:00:09.111Z
Learning: In packages/chain-adapters/src/tron/TronChainAdapter.ts, inline comments explaining non-obvious domain-specific behavior (e.g., why TRC20 burns to zero address are allowed while mints from zero address are skipped) are acceptable when explicitly requested, especially when the rationale is easy to regress (e.g., sTRX unstaking burn behavior).

gomesalexandre and others added 2 commits March 17, 2026 22:09
- run generate:caip-adapters to create eip155_2741 adapter
- add abstract to generated index.ts imports/exports
- add ethOnAbstract to index.test.ts coingeckoToAssetIds expectation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- add usdcOnCelo (0xceba9300f2b948710d2653dd7b07f33a8b32118c) to
  coingeckoToAssetIds 'usd-coin' test — celo adapter regenerated with
  native USDC entry when generate:caip-adapters ran
- fix shebang: #!/usr/bin/env npx tsx doesn't work on Linux (env
  treats 'npx tsx' as one arg); use -S to split args

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@gomesalexandre
Copy link
Contributor Author

addressing latest @coderabbitai comments:

ethSupportsNetwork (walletconnectV2.ts) — done in prior commit, 2741 is already at line 139

process.exit(1) (report.ts) — done in prior commit

schema.ts relay + wrappedNativeAddress guards — done in prior commit

shebang (index.ts) — fixed to `#!/usr/bin/env -S npx tsx` in latest commit

batch-prefetch ordering (evm.ts) — the prefetch gates on `wallet.ethGetAddresses` which works for any EVM-capable wallet regardless of `supportsAbstract`. All other second-class EVM chains use the identical pattern — dismissing.

wrap() masking anchor misses — post-MVP. `false` from engine = skip, exception = error. The "anchor not found" vs "already present" distinction is a UX improvement but doesn't affect scaffold correctness — dismissing.

addNamedImport() idempotency — post-MVP, catalogued for a follow-up hardening pass.

migration key from highest entry — valid, post-MVP improvement.

Across/Portals/Zerion supported branches — acknowledged, full integration per-swapper varies. Post-MVP when those swappers get Abstract support.

partial adapter generation idempotency — post-MVP.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 17, 2026

Tip

For best results, initiate chat on the files or code changes.

@gomesalexandre Thanks for the thorough rundown — all clear on every item:

  • ethSupportsNetwork / process.exit(1) / schema guards — confirmed done. ✓
  • Shebang#!/usr/bin/env -S npx tsx fix noted. ✓
  • evm.ts prefetch — makes sense; ethGetAddresses is chain-agnostic for all EVM wallets and the supportsAbstract gate is enforced downstream in deriveEvmAccountIdsAndMetadata. Consistent with every other second-class EVM chain. ✓
  • wrap() / addNamedImport idempotency / migration key / Across+Portals+Zerion / partial adapter idempotency — post-MVP catalogue noted, no correctness impact on the current scaffold. ✓

✏️ Learnings added
Learnt from: gomesalexandre
URL: https://github.com/shapeshift/web/pull/12186

Timestamp: 2026-03-17T21:54:13.597Z
Learning: In shapeshift/web, the batch-prefetch in src/lib/account/evm.ts gates on `wallet.ethGetAddresses`, which is chain-agnostic and works for any EVM-capable wallet regardless of chain-specific support flags like `supportsAbstract`. The chain-specific `supports*` guard is enforced downstream in `deriveEvmAccountIdsAndMetadata`. This pattern is identical across all second-class EVM chains and should not be flagged as a missing pre-check.

Learnt from: gomesalexandre
URL: https://github.com/shapeshift/web/pull/12186

Timestamp: 2026-03-17T21:54:13.597Z
Learning: In scripts/addChain/codemods.ts, the `wrap()` helper intentionally uses `false` (from the engine) to mean "skipped/already present" and thrown exceptions to mean "error". The distinction between "anchor not found" vs "already present" in skip status is a known post-MVP UX improvement and does not affect scaffold correctness. Do not flag this as a masking issue.

Learnt from: gomesalexandre
URL: https://github.com/shapeshift/web/pull/12186

Timestamp: 2026-03-17T21:54:13.597Z
Learning: In scripts/addChain/engine.ts, the `addNamedImport()` idempotency key format is intentional for the current MVP scaffolder. Hardening the idempotency key approach is catalogued as a post-MVP improvement. Do not flag the current format as incorrect.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11078
File: src/setupVitest.ts:11-15
Timestamp: 2025-11-20T12:00:45.005Z
Learning: In shapeshift/web, src/setupVitest.ts must redirect 'ethers' to 'ethers5' for shapeshiftoss/hdwallet-trezor (and -trezor-connect), same as ledger and shapeshift-multichain. Removing 'trezor' from the regex causes CI/Vitest failures due to ethers v6 vs v5 API differences.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T20:28:34.883Z
Learning: In shapeshift/web, chains added to `walletConnectV2OptionalChains` and `rpcMap` in `src/context/WalletProvider/WalletConnectV2/config.ts` are intentionally NOT gated by their feature flags. Feature-flagged chains (e.g., ink, flowEvmChain, sei, abstract) are unconditionally included in these WalletConnect V2 structures. This is the established convention and should not be flagged as a missing feature-flag guard.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10458
File: src/plugins/walletConnectToDapps/components/modals/EIP712MessageDisplay.tsx:46-59
Timestamp: 2025-09-10T15:34:54.593Z
Learning: After extensive testing by gomesalexandre in PR `#10458`, dApps do not send EIP-712 domain.chainId as hex or bigint values in practice. The simple String(domain.chainId) conversion is sufficient for real-world usage in WalletConnect dApps structured signing.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/hooks/useSimulateEvmTransaction.ts:91-95
Timestamp: 2025-09-12T13:43:50.695Z
Learning: gomesalexandre dismissed gas calculation overflow validation in useSimulateEvmTransaction hook as "stale", preferring to trust Tenderly's simulation data without defensive validation checks, consistent with his established pattern of relying on external service quality over defensive programming in WalletConnect flows.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/hooks/useSimulateEvmTransaction.ts:0-0
Timestamp: 2025-09-12T13:44:17.019Z
Learning: gomesalexandre prefers letting chain adapter errors throw naturally in useSimulateEvmTransaction rather than adding explicit error handling for missing adapters, consistent with his fail-fast approach and dismissal of defensive validation as "stale" in WalletConnect transaction simulation flows.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11569
File: headers/csps/chains/katana.ts:8-10
Timestamp: 2026-01-07T15:36:13.236Z
Learning: In CSP chain files (headers/csps/chains/*.ts), explicitly filtering undefined environment variables with .filter(Boolean) is unnecessary because serializeCsp() in headers/util.ts filters all falsy values during serialization at line 51: `.map(([k, v]) => [k, v.filter(x => !!x)])`. The direct pattern [env.VITE_*_NODE_URL] is sufficient and preferred for consistency with second-class chain CSP files like plasma.ts and monad.ts.
<!-- </add_learning>

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10857
File: src/plugins/walletConnectToDapps/eventsManager/useWalletConnectEventsHandler.ts:101-104
Timestamp: 2025-10-23T14:27:19.073Z
Learning: In WalletConnect wallet_switchEthereumChain and wallet_addEthereumChain requests, the chainId parameter is always present as per the protocol spec. Type guards checking for missing chainId in these handlers (like `if (!evmNetworkIdHex) return`) are solely for TypeScript compiler satisfaction, not real runtime edge cases.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11932
File: src/lib/utils/worldchain.ts:39-41
Timestamp: 2026-02-22T12:23:52.513Z
Learning: In src/lib/utils/[chain].ts files for second-class EVM chains (e.g., worldchain.ts, katana.ts, etc.), the per-chain utility functions like getWorldChainTransactionStatus() are effectively dead code after the migration to using the generic SecondClassEvmAdapter.getTransactionStatus() handler. Code quality concerns (like structured logging) for these files are not relevant since they're no longer actively used in hot paths.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10458
File: src/plugins/walletConnectToDapps/components/modals/EIP155SignTypedDataConfirmation.tsx:55-55
Timestamp: 2025-09-10T15:35:46.223Z
Learning: gomesalexandre prefers fail-fast early returns over graceful degradation when critical data is missing in WalletConnect flows (like peer metadata in EIP155SignTypedDataConfirmation.tsx). He favors "safety first, always double-wrap" approach and believes missing peer metadata indicates bigger problems that should be surfaced explicitly rather than masked with partial UI rendering.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11930
File: packages/chain-adapters/src/evm/soneium/SoneiumChainAdapter.ts:18-20
Timestamp: 2026-02-21T14:23:27.392Z
Learning: In packages/chain-adapters/src/evm/[chain]/[Chain]ChainAdapter.ts files for second-class EVM adapters, the type guard function (e.g., isSoneiumChainAdapter, isMantleChainAdapter) intentionally uses a simple pattern without defensive null/undefined checks: `(adapter as ChainAdapter).getType() === KnownChainIds.[Chain]Mainnet`. These simple type guards are exported for optional per-chain narrowing but are not actively used in hot paths. In practice, callers always check `getChainAdapterManager().get(chainId)` first, so null is never passed. The null-safe production code path uses `isSecondClassEvmAdapter` via `instanceof`. This pattern is consistent across 20+ second-class adapters (Berachain, HyperEvm, Base, Optimism, Linea, Monad, Scroll, Ink, Mode, Sonic, Bob, Plasma, Mantle, Katana, Cronos, MegaEth, Unichain, Soneium). Any defensive null-check additions should be done comprehensively across all adapters in a dedicated cleanup PR, not piecemeal.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11012
File: src/context/WalletProvider/Vultisig/components/Connect.tsx:24-59
Timestamp: 2025-11-19T16:59:50.569Z
Learning: In src/context/WalletProvider/*/components/Connect.tsx files across the ShapeShift web codebase, the established pattern for handling null/undefined adapter from getAdapter() is to simply check `if (adapter) { ... }` without an else clause. All wallet Connect components (Coinbase, Keplr, Phantom, Ledger, MetaMask, WalletConnectV2, KeepKey, Vultisig) follow this pattern—they reset loading state after the if block but do not show error messages when adapter is null. This is an intentional design decision and should be maintained for consistency.

Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10231
File: src/components/AssetSearch/components/AssetList.tsx:2-2
Timestamp: 2025-08-08T15:00:49.887Z
Learning: Project shapeshift/web: NeOMakinG prefers avoiding minor a11y/UI nitpicks (e.g., adding aria-hidden to decorative icons in empty states like src/components/AssetSearch/components/AssetList.tsx) within feature PRs; defer such suggestions to a follow-up instead of blocking the PR.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10879
File: src/context/WalletProvider/WalletConnectV2/components/WalletConnectDirectRow.tsx:64-81
Timestamp: 2025-10-22T22:11:22.918Z
Learning: In early WalletConnect POC/features behind a flag, gomesalexandre prioritizes connection correctness/stability over UX polish; minimal safety guards (like preventing concurrent connects) are preferred, while visuals will be wired later by reallybeard.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-16T21:35:02.159Z
Learning: In packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts (and related files like src/components/MultiHopTrade/components/TradeConfirm/hooks/useChainflipStreamingProgress.tsx), nullish checks (`== null` / `!= null`) MUST be used for `chainflipSwapId` instead of falsy checks, because `0` is a valid u64 swap ID that is falsy in JavaScript. Using `if (!chainflipSwapId)` would incorrectly discard a valid swap ID of `0`.

Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10323
File: src/components/ButtonWalletPredicate/ButtonWalletPredicate.tsx:7-7
Timestamp: 2025-08-27T09:47:06.275Z
Learning: In shapeshift/web project, NeOMakinG consistently prefers to defer UI/UX improvements and refactoring work (like the Drawer.Close hack fix in ButtonWalletPredicate.tsx) to follow-up PRs rather than expanding the scope of feature PRs, even when the improvements would enhance robustness.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11924
File: packages/chain-adapters/src/evm/mantle/MantleChainAdapter.ts:1-1
Timestamp: 2026-02-21T10:55:55.870Z
Learning: For second-class EVM chain adapters (those extending SecondClassEvmAdapter), the type guard function (e.g., isMantleChainAdapter, isKatanaChainAdapter, isUnichainChainAdapter) exists in BOTH locations: in the adapter file itself (packages/chain-adapters/src/evm/[chain]/[Chain]ChainAdapter.ts) AND in src/lib/utils/[chain].ts with defensive null/undefined checks. This pattern is consistent across at least 14 second-class adapters (base, berachain, cronos, hyperevm, ink, katana, linea, mantle, megaeth, monad, optimism, plasma, scroll, sonic, unichain) and should be maintained for consistency unless a comprehensive refactor across all adapters is undertaken.

Learnt from: gomes-bot
Repo: shapeshift/web PR: 11884
File: packages/chain-adapters/src/tron/TronChainAdapter.ts:732-735
Timestamp: 2026-02-16T15:00:09.111Z
Learning: In packages/chain-adapters/src/tron/TronChainAdapter.ts, inline comments explaining non-obvious domain-specific behavior (e.g., why TRC20 burns to zero address are allowed while mints from zero address are skipped) are acceptable when explicitly requested, especially when the rationale is easy to regress (e.g., sTRX unstaking burn behavior).

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 12061
File: package.json:387-392
Timestamp: 2026-03-04T20:31:05.875Z
Learning: In shapeshift/web package.json, the `pnpm.peerDependencyRules.allowedVersions` wildcards for `msw`, `ethers`, and `zod` are intentional:
- `msw: "*"` — vitest/mocker3.0.9 requires msw@^2.4.9 but the repo ships 0.27.2/0.36.8 for legacy test infra; cannot bump msw.
- `ethers: "*"` — cowprotocol/app-data wants ^5 and avnu/avnu-sdk wants ^6.15.0 (installed: 6.11.1); two cross-version conflicts handled by one wildcard.
- `zod: "*"` — ~6 packages (ai-sdk, abitype, zodios, etc.) declare different zod peer ranges; zod is not a direct dependency.
Do not flag these wildcards as imprecise; they are the correct suppression mechanism for known-unresolvable peer dep mismatches.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10418
File: src/plugins/walletConnectToDapps/components/header/WalletConnectToDappsHeaderButton.tsx:0-0
Timestamp: 2025-09-08T22:00:48.005Z
Learning: gomesalexandre dismissed an aria-label accessibility suggestion with "meh" in PR `#10418` for WalletConnectToDappsHeaderButton.tsx, consistent with the team's pattern of deferring minor a11y improvements to follow-up PRs rather than expanding feature PR scope.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10206
File: src/config.ts:127-128
Timestamp: 2025-08-07T11:20:44.614Z
Learning: gomesalexandre prefers required environment variables without default values in the config file (src/config.ts). They want explicit configuration and fail-fast behavior when environment variables are missing, rather than having fallback defaults.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/ContractInteractionBreakdown.tsx:0-0
Timestamp: 2025-09-13T16:45:18.813Z
Learning: gomesalexandre prefers aggressively deleting unused/obsolete code files ("ramboing") rather than fixing technical issues in code that won't be used, demonstrating his preference for keeping codebases clean and PR scope focused.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10458
File: src/plugins/walletConnectToDapps/types.ts:7-7
Timestamp: 2025-09-10T15:34:29.604Z
Learning: gomesalexandre is comfortable relying on transitive dependencies (like abitype through ethers/viem) rather than explicitly declaring them in package.json, preferring to avoid package.json bloat when the transitive dependency approach works reliably in practice.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10503
File: .env:56-56
Timestamp: 2025-09-16T13:17:02.938Z
Learning: gomesalexandre prefers to enable feature flags globally in the base .env file when the intent is to activate features everywhere, even when there are known issues like crashes, demonstrating his preference for intentional global feature rollouts over cautious per-environment enablement.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10249
File: src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx:447-503
Timestamp: 2025-08-13T17:07:10.763Z
Learning: gomesalexandre prefers relying on TypeScript's type system for validation rather than adding defensive runtime null checks when types are properly defined. They favor a TypeScript-first approach over defensive programming with runtime validations.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10276
File: src/hooks/useActionCenterSubscribers/useThorchainLpDepositActionSubscriber.tsx:61-66
Timestamp: 2025-08-14T17:51:47.556Z
Learning: gomesalexandre is not concerned about structured logging and prefers to keep console.error usage as-is rather than implementing structured logging patterns, even when project guidelines suggest otherwise.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10413
File: src/components/Modals/FiatRamps/fiatRampProviders/onramper/utils.ts:29-55
Timestamp: 2025-09-02T14:26:19.028Z
Learning: gomesalexandre prefers to keep preparatory/reference code simple until it's actively consumed, rather than implementing comprehensive error handling, validation, and robustness improvements upfront. They prefer to add these improvements when the code is actually being used in production.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10276
File: src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx:396-402
Timestamp: 2025-08-14T17:55:57.490Z
Learning: gomesalexandre is comfortable with functions/variables that return undefined or true (tri-state) when only the truthy case matters, preferring to rely on JavaScript's truthy/falsy behavior rather than explicitly returning boolean values.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10783
File: src/context/ModalStackProvider/useModalRegistration.ts:30-41
Timestamp: 2025-10-16T11:14:40.657Z
Learning: gomesalexandre prefers to add lint rules (like typescript-eslint/strict-boolean-expressions for truthiness checks on numbers) to catch common issues project-wide rather than relying on code review to catch them.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10206
File: src/lib/moralis.ts:47-85
Timestamp: 2025-08-07T11:22:16.983Z
Learning: gomesalexandre prefers console.error over structured logging for Moralis API integration debugging, as they find it more conventional and prefer to examine XHR requests directly rather than rely on structured logs for troubleshooting.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/EIP712MessageDisplay.tsx:133-137
Timestamp: 2025-09-12T10:15:10.389Z
Learning: gomesalexandre has identified that EIP-712 domain chainId should be preferred over request context chainId for accuracy in WalletConnect dApps structured signing flows. The domain chainId from the parsed message is more specific and accurate than the general request context, especially for asset resolution and network-specific operations.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T01:29:21.619Z
Learning: In shapeshift/web PR `#12181`, the primary fix is replacing SHA-based comparison (`privateSha`) with a content diff approach (`privateContentMatchesMain` boolean) in `deriveReleaseState`/`deriveHotfixState` in `scripts/release.ts`. This unblocks new releases when `private` has been squash-synced with `main` (SHA differs even though content is identical). The secondary fix — `createPr` returning `null` on "No commits between" GitHub error — is a defensive improvement bundled in the same PR. The PR title only references the secondary change; the commit message body captures both.

Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/EIP712MessageDisplay.tsx:0-0
Timestamp: 2025-09-12T10:21:26.693Z
Learning: gomesalexandre explained that in WalletConnect V2, the request context chainId comes from params?.chainId following CAIP2 standards, making both the request params chainId and EIP-712 domain chainId equally reliable sources. He considers both approaches trustworthy ("both gucci") for WalletConnect dApps integration.

gomesalexandre and others added 2 commits March 17, 2026 23:04
adapters are iterated in insertion order; celo adapter (eip155_42220)
was added by regenerate:caip-adapters before sei, so celo comes first

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
abstract is isNativeEth:true — adds one more entry to findAll() results

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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.

EVM chain scaffolder

2 participants