Skip to content

feat: add plasma chain#11275

Merged
gomesalexandre merged 23 commits intodevelopfrom
feat_plasma
Dec 10, 2025
Merged

feat: add plasma chain#11275
gomesalexandre merged 23 commits intodevelopfrom
feat_plasma

Conversation

@gomesalexandre
Copy link
Contributor

@gomesalexandre gomesalexandre commented Dec 3, 2025

Description

Test me with hdwallet fren

Issue (if applicable)

closes N/A

Risk

High Risk PRs Require 2 approvals

Low, new chain, under flag

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

Testing

Test:

  • Sends
  • Receives
  • Relay swaps

Engineering

  • ☝🏽

Operations

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

Screenshots (if applicable)

https://jam.dev/c/e512e61b-d21f-4522-bd55-1eeea374e31c
https://jam.dev/c/abed37f6-2227-4826-9b59-02250c914d64

Summary by CodeRabbit

  • New Features

    • Added support for Plasma blockchain network with native asset (XPL).
    • Enabled wallet account management, token balances, and transaction broadcasting on Plasma.
    • Integrated Plasma with swap functionality through Relay and other swappers.
    • Added transaction status tracking for Plasma transactions.
  • Chores

    • Added environment configuration and feature flag for Plasma network.
    • Updated documentation with Plasma integration guidance and patterns.

✏️ Tip: You can customize this high-level summary in your review settings.

gomesalexandre and others added 6 commits December 3, 2025 14:15
- Add Plasma chain constants and types (chain ID: eip155:9745)
- Create Plasma chain adapter extending EvmBaseAdapter
- Add Plasma plugin with feature flag gating (VITE_FEATURE_PLASMA)
- Wire Plasma into account derivation and wallet support detection
- Add transaction status polling via public RPC
- Configure viem and ethers providers for Plasma
- Add Plasma to CoinGecko integration and asset generation
- Add CSP headers for Plasma RPC endpoint
- Generate Plasma assets from CoinGecko token list

Plasma uses SLIP44:60 (Ethereum derivation path) and is configured
to use public RPC at https://rpc.plasma.to

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
- Add PlasmaMainnet to evmChainIds array
- Add Plasma to ChainSpecificFeeData type mapping
- Add Plasma network metadata to EvmBaseAdapter targetNetwork

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Add documentation for:
- packages/chain-adapters/src/types.ts (ChainSpecificFeeData mapping)
- packages/chain-adapters/src/evm/EvmBaseAdapter.ts (evmChainIds array and targetNetwork)
- packages/chain-adapters/src/[type]/index.ts (export chain adapter)
- packages/contracts/src/viemClient.ts (viem client setup for EVM)
- packages/contracts/src/ethersProviderSingleton.ts (ethers provider for EVM)
- scripts/generateAssetData/coingecko.ts (asset generation helper)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

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

coderabbitai bot commented Dec 3, 2025

📝 Walkthrough

Walkthrough

This PR adds comprehensive Plasma EVM chain support to the ShapeShift application. It introduces Plasma chain constants, a specialized EVM chain adapter with multicall token batching, asset definitions, environment configuration, wallet integration, Relay swapper support, Ledger gating, and transaction status polling across the frontend and backend infrastructure.

Changes

Cohort / File(s) Change Summary
Plasma Chain Constants & Types
packages/types/src/base.ts, packages/caip/src/constants.ts
Added PlasmaMainnet chain ID (eip155:9745), asset reference, and extended EvmChainId union and VALID_CHAIN_IDS.
Chain Adapter Type Mappings
packages/chain-adapters/src/types.ts
Extended ChainSpecificAccount, ChainSpecificFeeData, ChainSignTx, ChainSpecificBuildTxData, GetFeeDataInput to map PlasmaMainnet to EVM types; added Plasma to ChainAdapterDisplayName enum.
EVM Base Adapter & Plasma Adapter
packages/chain-adapters/src/evm/EvmBaseAdapter.ts, packages/chain-adapters/src/evm/plasma/PlasmaChainAdapter.ts, packages/chain-adapters/src/evm/plasma/index.ts, packages/chain-adapters/src/evm/index.ts
Added PlasmaMainnet support to EVM base adapter; implemented new Plasma chain adapter with multicall token balance retrieval (BATCH_SIZE=500), fee data estimation, transaction broadcasting, and related utilities.
Environment Configuration
.env, .env.development, .env.production, src/config.ts
Added VITE_PLASMA_NODE_URL environment variable and VITE_FEATURE_PLASMA feature flag with url() validation.
CSP Headers
headers/csps/chains/plasma.ts, headers/csps/index.ts
Created Plasma-specific CSP configuration; added plasma to CSP index export.
Asset Data & Utilities
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
Added Plasma asset definition (XPL token with icon/explorer); mapped PlasmaMainnet to fee and asset namespace utilities.
Coingecko Integration
packages/caip/src/adapters/coingecko/index.ts, packages/caip/src/adapters/coingecko/utils.ts
Extended CoingeckoAssetPlatform enum with Plasma; added chainId↔Coingecko mappings and token parsing for Plasma assets.
Asset Generation Pipeline
scripts/generateAssetData/coingecko.ts, scripts/generateAssetData/generateAssetData.ts, scripts/generateAssetData/plasma/index.ts, scripts/generateAssetData/color-map.json
Integrated Plasma asset generation into coingecko script; added dedicated plasma module for asset fetching; updated token color map.
Provider Clients
packages/contracts/src/viemClient.ts, packages/contracts/src/ethersProviderSingleton.ts
Created viemPlasmaClient and added Plasma entries to viem client/network ID mappings; mapped PlasmaMainnet to RPC URL in ethers singleton.
Swapper Support
packages/swapper/src/swappers/RelaySwapper/constant.ts, packages/swapper/src/swappers/RelaySwapper/utils/relayTokenToAssetId.ts, packages/swapper/src/swappers/utils/helpers/helpers.ts
Extended Relay swapper constants with Plasma chain mapping; added PlasmaMainnet asset reference conversion; added Plasma to native EVM asset helper.
Ledger & Gating
packages/chain-adapters/src/utils/ledgerAppGate.ts, src/lib/utils/plasma.ts
Added PlasmaMainnet→Ethereum Ledger app mapping; implemented plasma utilities (isPlasmaChainAdapter, assertGetPlasmaChainAdapter, getPlasmaTransactionStatus with eth_getTransactionReceipt).
State Management & Hooks
src/state/slices/preferencesSlice/preferencesSlice.ts, src/state/slices/opportunitiesSlice/mappings.ts, src/state/slices/portfolioSlice/utils/index.ts, src/state/migrations/index.ts, src/test/mocks/store.ts
Added Plasma feature flag initialization; added empty DeFi opportunities mapping; added plasmaChainId label routing; added state migration entry; added mock feature flag.
Hooks & Account Handling
src/hooks/useWalletSupportsChain/useWalletSupportsChain.ts, src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx, src/lib/account/evm.ts
Added Plasma support in wallet capability detection; integrated getPlasmaTransactionStatus into transaction status polling; gated Plasma in EVM account derivation.
Portal & Plugin Integration
src/lib/portals/utils.ts, src/plugins/activePlugins.ts, src/plugins/plasma/index.tsx
Updated portals utilities to skip unsupported chains gracefully; registered Plasma plugin with chain adapter instantiation and known-tokens configuration.
Documentation
.claude/skills/chain-integration/SKILL.md, .claude/skills/swapper-integration/SKILL.md
Updated chain-integration skill with Plasma-specific guidance; added rate-limiting pattern documentation to swapper-integration skill.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Areas requiring extra attention:

  • PlasmaChainAdapter.ts — Multicall batching logic with fallback to individual calls; fee data estimation flow and transaction broadcasting with address validation
  • Asset generation pipeline — Integration of Plasma assets across coingecko, generateAssetData, and color-map updates
  • Transaction status polling — getPlasmaTransactionStatus implementation and eth_getTransactionReceipt handling in useSendActionSubscriber
  • Provider client initialization — viemPlasmaClient and ethersProviderSingleton configuration; ensure RPC URL validation and error handling

Possibly related PRs

  • feat: implement monad #11241 — Nearly identical EVM-style chain integration for Monad; modifies the same modules (EvmBaseAdapter, viem/ethers clients, chain adapters, constants, asset scripts, ledger/relay mappings).
  • feat: add chain integration skill #11260 — Introduces the Chain Integration Skill documentation that this PR builds upon and expands with Plasma-specific guidance.
  • feat: improve swapper skill #11259 — Updates swapper-integration skill documentation with rate-limiting patterns and gotchas referenced in this PR.

Suggested reviewers

  • NeOMakinG
  • 0xApotheosis
  • kaladinlight

Poem

🐰 Plasma flows bright with purple glow,
EVM chains now put on a show,
Token batches multicall with grace,
XPL finds its rightful place,
Fee data, ledgers, swappers aligned—
New chain integration, expertly designed!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: add plasma chain' directly and clearly summarizes the main objective of the changeset, which is to add support for a new Plasma blockchain.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat_plasma

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between cca876f and fc9dd23.

📒 Files selected for processing (2)
  • packages/caip/src/adapters/coingecko/utils.test.ts (1 hunks)
  • packages/swapper/src/swappers/utils/helpers/helpers.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,js,jsx}: Never assume a library is available - always check imports/package.json first
Prefer composition over inheritance
Write self-documenting code with clear variable and function names
Keep functions small and focused on a single responsibility
Avoid deep nesting - use early returns instead
Prefer procedural and easy to understand code
Never expose, log, or commit secrets, API keys, or credentials
Validate all inputs, especially user inputs
Handle errors gracefully with meaningful messages
Don't silently catch and ignore exceptions
Log errors appropriately for debugging
Provide fallback behavior when possible
Use appropriate data structures for the task
Never add code comments unless explicitly requested
When modifying code, do not add comments that reference previous implementations or explain what changed. Comments should only describe the current logic and functionality.
Use meaningful names for branches, variables, and functions
Always run yarn lint --fix and yarn type-check after making changes
Avoid let variable assignments - prefer const with inline IIFE switch statements or extract to functions for conditional logic

Files:

  • packages/caip/src/adapters/coingecko/utils.test.ts
  • packages/swapper/src/swappers/utils/helpers/helpers.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Avoid useEffect where practical - use it only when necessary and following best practices
Avoid 'any' types - use specific type annotations instead
For default values with user overrides, use computed values (useMemo) instead of useEffect - pattern: userSelected ?? smartDefault ?? fallback
When function parameters are unused due to interface requirements, refactor the interface or implementation to remove them rather than prefixing with underscore
Sanitize data before displaying to prevent XSS
Memoize aggressively - wrap component variables in useMemo and callbacks in useCallback where possible
For static JSX icon elements (e.g., <TbCopy />) that don't depend on state/props, define them as constants outside the component to avoid re-renders instead of using useMemo
Account for light/dark mode using useColorModeValue hook
Account for responsive mobile designs in all UI components
When applying styles, use the existing standards and conventions of the codebase
Use Chakra UI components and conventions
All copy/text must use translation keys - never hardcode strings
Use the translation hook: useTranslate() from react-polyglot
Use useFeatureFlag('FlagName') hook to access feature flag values in components
Prefer type over interface for type definitions
Use strict typing - avoid any
Use Nominal types for domain identifiers (e.g., WalletId, AccountId)
Import types from @shapeshiftoss/caip for chain/account/asset IDs
Use useAppSelector for Redux state
Use useAppDispatch for Redux actions
Memoize expensive computations with useMemo
Memoize callbacks with useCallback

**/*.{ts,tsx}: Use Result<T, E> pattern for error handling in swappers and APIs; ALWAYS use Ok() and Err() from @sniptt/monads; AVOID throwing within swapper API implementations
ALWAYS use custom error classes from @shapeshiftoss/errors with meaningful error codes for internationalization and relevant details in error objects
ALWAYS wrap async op...

Files:

  • packages/caip/src/adapters/coingecko/utils.test.ts
  • packages/swapper/src/swappers/utils/helpers/helpers.ts
**/*.test.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.test.{ts,tsx,js,jsx}: Write tests for critical business logic
Test edge cases and error conditions
Use descriptive test names that explain behavior
Keep tests isolated and independent
Mock external dependencies appropriately

Files:

  • packages/caip/src/adapters/coingecko/utils.test.ts
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/naming-conventions.mdc)

**/*.{js,jsx,ts,tsx}: Use camelCase for variables, functions, and methods with descriptive names that explain the purpose
Use verb prefixes for functions that perform actions (e.g., fetch, validate, execute, update, calculate)
Use UPPER_SNAKE_CASE for constants and configuration values with descriptive names
Use handle prefix for event handlers with descriptive names in camelCase
Use descriptive boolean variable names with is, has, can, should prefixes
Use named exports for components, functions, and utilities instead of default exports
Use descriptive import names and avoid renaming imports unless necessary
Avoid non-descriptive variable names like data, item, obj, and single-letter variable names except in loops
Avoid abbreviations in names unless they are widely understood
Avoid generic function names like fn, func, or callback

Files:

  • packages/caip/src/adapters/coingecko/utils.test.ts
  • packages/swapper/src/swappers/utils/helpers/helpers.ts
**/swapper{s,}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/error-handling.mdc)

ALWAYS use makeSwapErrorRight for swapper errors with TradeQuoteError enum for error codes and provide detailed error information

Files:

  • packages/swapper/src/swappers/utils/helpers/helpers.ts
packages/swapper/**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/swapper.mdc)

packages/swapper/**/*.ts: Use TypeScript with explicit types (e.g., SupportedChainIds) for all code in the Swapper system
Use camelCase for variable and function names in the Swapper system
Use PascalCase for types, interfaces, and enums in the Swapper system
Use kebab-case for filenames in the Swapper system

Files:

  • packages/swapper/src/swappers/utils/helpers/helpers.ts
packages/swapper/src/swappers/**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/swapper.mdc)

packages/swapper/src/swappers/**/*.ts: Adhere to the Swapper directory structure: each swapper resides in packages/swapper/src/swappers// with required files (SwapperName.ts, endpoints.ts, types.ts, utils/constants.ts, utils/helpers.ts)
Validate inputs and log errors for debugging in Swapper system implementations
Swapper files must be located in packages/swapper/src/swappers/ directory structure and not placed outside this location
Avoid side effects in swap logic; ensure swap methods are deterministic and stateless

Files:

  • packages/swapper/src/swappers/utils/helpers/helpers.ts
🧠 Learnings (19)
📓 Common learnings
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11170
File: patches/@shapeshiftoss+bitcoinjs-lib+7.0.0-shapeshift.0.patch:9-19
Timestamp: 2025-11-25T21:43:10.838Z
Learning: In shapeshift/web, gomesalexandre will not expand PR scope to fix latent bugs in unused API surface (like bitcoinjs-lib patch validation methods) when comprehensive testing proves the actual used code paths work correctly, preferring to avoid costly hdwallet/web verdaccio publish cycles and full regression testing for conceptual issues with zero runtime impact.
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: 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: kaladinlight
Repo: shapeshift/web PR: 10326
File: src/hooks/useActionCenterSubscribers/useGenericTransactionSubscriber.tsx:105-111
Timestamp: 2025-08-22T14:59:04.889Z
Learning: In the ShapeShift web Base chain handling, the await pattern inside forEach in useGenericTransactionSubscriber is intentional to delay the entire action completion flow (not just fetchBasePortfolio) for Base chain transactions. The user kaladinlight wants everything below the Base portfolio refresh - including dispatch, query invalidation, and toast notifications - to also be delayed by ~10 seconds to accommodate Base's degraded node state.
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.
📚 Learning: 2025-08-17T21:53:03.806Z
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.

Applied to files:

  • packages/caip/src/adapters/coingecko/utils.test.ts
  • packages/swapper/src/swappers/utils/helpers/helpers.ts
📚 Learning: 2025-11-20T12:00:45.005Z
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.

Applied to files:

  • packages/caip/src/adapters/coingecko/utils.test.ts
📚 Learning: 2025-11-24T21:20:57.909Z
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/**/*.test.ts : Write unit tests for swapper methods and API endpoints

Applied to files:

  • packages/caip/src/adapters/coingecko/utils.test.ts
📚 Learning: 2025-11-24T21:20:04.979Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T21:20:04.979Z
Learning: Applies to **/*.{ts,tsx} : Import types from `shapeshiftoss/caip` for chain/account/asset IDs

Applied to files:

  • packages/caip/src/adapters/coingecko/utils.test.ts
  • packages/swapper/src/swappers/utils/helpers/helpers.ts
📚 Learning: 2025-10-15T15:57:39.956Z
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.

Applied to files:

  • packages/caip/src/adapters/coingecko/utils.test.ts
📚 Learning: 2025-11-24T21:20:57.909Z
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

Applied to files:

  • packages/caip/src/adapters/coingecko/utils.test.ts
  • packages/swapper/src/swappers/utils/helpers/helpers.ts
📚 Learning: 2025-11-24T21:20:57.909Z
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

Applied to files:

  • packages/caip/src/adapters/coingecko/utils.test.ts
  • packages/swapper/src/swappers/utils/helpers/helpers.ts
📚 Learning: 2025-11-24T21:20:57.909Z
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

Applied to files:

  • packages/swapper/src/swappers/utils/helpers/helpers.ts
📚 Learning: 2025-11-24T21:20:57.909Z
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 : Reuse executeEvmTransaction utility for EVM-based swappers instead of implementing custom transaction execution

Applied to files:

  • packages/swapper/src/swappers/utils/helpers/helpers.ts
📚 Learning: 2025-11-24T21:20:57.909Z
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/*/endpoints.ts : Reuse checkEvmSwapStatus utility for checking EVM swap status instead of implementing custom status checks

Applied to files:

  • packages/swapper/src/swappers/utils/helpers/helpers.ts
📚 Learning: 2025-11-24T21:20:57.909Z
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 : Avoid side effects in swap logic; ensure swap methods are deterministic and stateless

Applied to files:

  • packages/swapper/src/swappers/utils/helpers/helpers.ts
📚 Learning: 2025-11-24T21:20:57.909Z
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

Applied to files:

  • packages/swapper/src/swappers/utils/helpers/helpers.ts
📚 Learning: 2025-11-24T21:20:57.909Z
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/index.ts : Export unique functions and types from packages/swapper/src/index.ts only if needed for external consumption

Applied to files:

  • packages/swapper/src/swappers/utils/helpers/helpers.ts
📚 Learning: 2025-08-05T23:36:13.214Z
Learnt from: premiumjibles
Repo: shapeshift/web PR: 10187
File: src/state/slices/preferencesSlice/selectors.ts:21-25
Timestamp: 2025-08-05T23:36:13.214Z
Learning: The AssetId type from 'shapeshiftoss/caip' package is a string type alias, so it can be used directly as a return type for cache key resolvers in re-reselect selectors without needing explicit string conversion.

Applied to files:

  • packages/swapper/src/swappers/utils/helpers/helpers.ts
📚 Learning: 2025-09-04T17:29:59.479Z
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.

Applied to files:

  • packages/swapper/src/swappers/utils/helpers/helpers.ts
📚 Learning: 2025-09-04T13:00:47.748Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10380
File: src/lib/utils/asset.ts:3-5
Timestamp: 2025-09-04T13:00:47.748Z
Learning: In shapeshift/web, primary assets are assets that represent a group of related assets across multiple chains. An asset with undefined relatedAssetKey doesn't participate in grouping and is not considered primary. Only assets with null relatedAssetKey or where relatedAssetKey === assetId are considered primary assets.

Applied to files:

  • packages/swapper/src/swappers/utils/helpers/helpers.ts
📚 Learning: 2025-09-04T17:35:57.584Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10380
File: src/state/slices/common-selectors.ts:164-178
Timestamp: 2025-09-04T17:35:57.584Z
Learning: In shapeshift/web, while the Asset type allows relatedAssetKey to be AssetId | null | undefined, the actual asset generation and processing system ensures relatedAssetKey is never undefined in practice. All asset creation utilities explicitly set it to either a specific AssetId (for grouped assets) or null (for primary/unique assets). The only exception is temporary undefined assignment during portal asset processing, which gets resolved later in the pipeline.

Applied to files:

  • packages/swapper/src/swappers/utils/helpers/helpers.ts
📚 Learning: 2025-09-04T17:35:57.584Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10380
File: src/state/slices/common-selectors.ts:164-178
Timestamp: 2025-09-04T17:35:57.584Z
Learning: In shapeshift/web, while the Asset type allows relatedAssetKey to be AssetId | null | undefined, the actual asset generation and processing system ensures relatedAssetKey is never undefined in practice. All asset creation utilities explicitly set it to either a specific AssetId (for grouped assets) or null (for primary/unique assets). The only undefined assignments occur during intermediate processing phases and get resolved during the final asset generation step.

Applied to files:

  • packages/swapper/src/swappers/utils/helpers/helpers.ts
🧬 Code graph analysis (1)
packages/swapper/src/swappers/utils/helpers/helpers.ts (1)
packages/caip/src/constants.ts (1)
  • plasmaAssetId (20-20)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Install and Cache
🔇 Additional comments (3)
packages/caip/src/adapters/coingecko/utils.test.ts (1)

178-180: Plasma CAIP-19 mapping looks consistent with existing EVM chains

The new eip155:9745 entry and its eip155:9745/slip44:60plasma mapping follow the same pattern as the other EVM native asset mappings (e.g., monad, base). Structure and naming look correct; no issues from the test perspective.

packages/swapper/src/swappers/utils/helpers/helpers.ts (2)

12-12: LGTM! Plasma native asset handling follows the established pattern.

The import and switch case addition correctly implement Plasma native asset recognition, consistent with all other EVM chains in the codebase.

Also applies to: 52-53


59-70: No action required—PlasmaMainnet treasury exclusion is intentional.

The getTreasuryAddressFromChainId function uses the isTreasuryChainId() type guard before accessing the mapping. PlasmaMainnet is deliberately excluded from the TreasuryChainId union type defined in @shapeshiftoss/utils, confirming that PlasmaMainnet does not participate in the DAO treasury system. The function correctly throws a meaningful error if called with an unsupported chain, so there is no runtime risk.

Likely an incorrect or invalid review comment.


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 and others added 7 commits December 3, 2025 14:53
Add comprehensive Plasma chain support across the entire codebase.

Fixes:
- Add PlasmaMainnet to ChainSpecificGetFeeDataInput type mapping
- Add ethers 6.11.1 dependency to chain-adapters
- Add Plasma to EvmBaseAdapter assertSupportsChain switch
- Add Plasma to Ledger app gate (getLedgerAppName & getCoin)
- Make Portals gracefully skip unsupported chains instead of throwing
- Add Plasma to Portals constants
- Update Plasma icon URLs to correct CoinGecko assets
- Add Plasma to Relay swapper support
- Add Plasma to accountIdToLabel for account selection in swapper
- Add Plasma to opportunities mapping

Documentation:
- Add Gotcha 12: Missing Ledger App Gate Entries
- Add Gotcha 13: Portals API Unsupported Chains
- Add Gotcha 14: Missing accountIdToLabel Case
- Add Step 5.4: Research & Add Swapper Support

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Add migration 233 to clear assets and update encoded asset data.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@gomesalexandre gomesalexandre marked this pull request as ready for review December 3, 2025 20:45
@gomesalexandre gomesalexandre requested a review from a team as a code owner December 3, 2025 20:45
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

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

⚠️ Outside diff range comments (2)
packages/chain-adapters/src/utils/ledgerAppGate.ts (1)

50-82: Remove or defer Plasma coin mapping until hdwallet adds Plasma support

The 'Plasma' coin identifier in the getCoin function references a chain that is not yet supported in hdwallet (v2.2.1 docs do not list Plasma as a supported cryptocurrency). Ledger users attempting to validate their app for Plasma will fail at runtime when wallet.validateCurrentApp('Plasma') is called. Either defer this mapping until hdwallet officially adds Plasma support, or verify that a newer hdwallet version with Plasma support is already available and being used by this project.

packages/caip/src/constants.ts (1)

209-230: Add plasmaAssetId to FEE_ASSET_IDS array.

The FEE_ASSET_IDS array is missing plasmaAssetId. All native chain assets (ETH, AVAX, POL, ARB, etc.) are included in this array for fee calculations, and Plasma's native asset should follow the same pattern.

Apply this diff to add the missing entry:

   arbitrumNovaAssetId,
   baseAssetId,
   monadAssetId,
+  plasmaAssetId,
   solAssetId,
   tronAssetId,
♻️ Duplicate comments (2)
packages/chain-adapters/package.json (1)

46-46: Confirm temporary ethers pin and associated past comment.

Line 46 adds an explicit [email protected] pin. The past comment ("remove me and ensure CI is happy, retest when hdwallet is published, local versioning shenanigans") indicates this is temporary.

Clarify whether this is:

  • A placeholder that should be removed/updated once hdwallet publishes, or
  • A permanent, intentional pin for the EVM adapter.
packages/swapper/package.json (1)

42-42: Address version mismatch: hdwallet-core differs from root package.json.

The hdwallet-core version here is 1.62.22-plasma.0, but root package.json specifies 1.62.23-plasma.1. This inconsistency needs clarification (intentional or oversight).

Also note the past comment: "update me to actual upstream when hdwallet is published"—confirm whether this should remain as a reminder or is stale.

🧹 Nitpick comments (12)
src/state/slices/portfolioSlice/utils/index.ts (1)

24-32: Plasma labeling looks consistent; verify wallet support handling for plasmaChainId.

  • Importing plasmaChainId from @shapeshiftoss/caip and routing it through the shared middleEllipsis(pubkey) branch in accountIdToLabel is consistent with how other EVM/Cosmos-style chains are labeled. No issues there and it matches the CAIP‑first approach used elsewhere.
  • However, isAssetSupportedByWallet still has a closed switch over chainId that doesn’t include plasmaChainId, so plasma assets will currently be treated as unsupported by all HDWallets wherever this helper is used. Given this PR adds a new chain and mentions tested Sends/Receives/Relay swaps, please double‑check whether plasma should:
    • remain intentionally unsupported here (e.g. only usable via flows that bypass this helper), or
    • get its own case mapping to the correct supports* predicate once hdwallet-core exposes it (or whatever pattern you intend for plasma wallet support).

If plasma is meant to be supported by the same app as another EVM network, you’ll likely want to mirror that case here; otherwise, this helper may silently gate plasma UX behind the default false branch.

Based on learnings, importing CAIP chain IDs and keeping support checks explicit in one place matches the project’s patterns.

Also applies to: 77-99, 361-403

.env.development (1)

65-65: Plasma env vars look correct; consider reordering to satisfy dotenv‑linter

VITE_PLASMA_NODE_URL and VITE_FEATURE_PLASMA values align with the rest of the Plasma wiring. To keep dotenv‑linter happy, you may want to reorder them to match the existing key ordering conventions (node URLs and feature flags are currently ordered, and these insertions trigger UnorderedKey warnings).

Also applies to: 95-95

.env.production (1)

61-61: Node URL addition looks good; consider fixing dotenv key ordering

VITE_PLASMA_NODE_URL is consistent with other node URLs. To satisfy dotenv-linter’s UnorderedKey warning, you can move it before VITE_POLYGON_NODE_URL to keep keys ordered.

 VITE_OPTIMISM_NODE_URL=https://api.optimism.shapeshift.com/api/v1/jsonrpc
 VITE_BNBSMARTCHAIN_NODE_URL=https://api.bnbsmartchain.shapeshift.com/api/v1/jsonrpc
+VITE_PLASMA_NODE_URL=https://rpc.plasma.to
 VITE_POLYGON_NODE_URL=https://api.polygon.shapeshift.com/api/v1/jsonrpc
 VITE_GNOSIS_NODE_URL=https://api.gnosis.shapeshift.com/api/v1/jsonrpc
 VITE_ARBITRUM_NODE_URL=https://api.arbitrum.shapeshift.com/api/v1/jsonrpc
 VITE_ARBITRUM_NOVA_NODE_URL=https://api.arbitrum-nova.shapeshift.com/api/v1/jsonrpc
 VITE_BASE_NODE_URL=https://api.base.shapeshift.com/api/v1/jsonrpc
 VITE_MONAD_NODE_URL=https://rpc.monad.xyz
-VITE_PLASMA_NODE_URL=https://rpc.plasma.to
src/lib/portals/utils.ts (1)

56-60: Graceful handling of unsupported Portals chains is a good change; small typing/refactor nit

The new behavior of:

  • filtering out unsupported networks for token listing, and
  • returning {} for unsupported chains in fetchPortalsAccount

avoids throwing on chains Portals doesn’t support and matches the “skip instead of fail” intent.

One small improvement for clarity/robustness:

  • Prefer Array.isArray(networks) instead of typeof networks === 'object' when deriving supportedNetworks:
-  const supportedNetworks = typeof networks === 'object' ? networks.filter(isSome) : undefined
+  const supportedNetworks = Array.isArray(networks) ? networks.filter(isSome) : undefined

Functionally equivalent today, but more explicit about the expected shape and future‑proof if networks ever stops being an array.

Also applies to: 283-289

src/plugins/plasma/index.tsx (1)

1-47: Plasma chain adapter plugin wiring looks correct; tiny optimization possible

The plugin correctly:

  • gates on the Plasma feature flag,
  • instantiates plasma.ChainAdapter with rpcUrl from getConfig().VITE_PLASMA_NODE_URL, and
  • builds knownTokens by restricting assets to plasmaChainId + erc20.

One small optional improvement: you call fromAssetId(asset.assetId) in both the filter and map steps. You could compute it once per asset and reuse it:

-                const knownTokens = assetService.assets
-                  .filter(asset => {
-                    const { chainId, assetNamespace } = fromAssetId(asset.assetId)
-                    return chainId === plasmaChainId && assetNamespace === 'erc20'
-                  })
-                  .map(asset => ({
-                    assetId: asset.assetId,
-                    contractAddress: fromAssetId(asset.assetId).assetReference,
-                    symbol: asset.symbol,
-                    name: asset.name,
-                    precision: asset.precision,
-                  }))
+                const knownTokens = assetService.assets
+                  .map(asset => {
+                    const { chainId, assetNamespace, assetReference } = fromAssetId(asset.assetId)
+                    if (chainId !== plasmaChainId || assetNamespace !== 'erc20') return undefined
+                    return {
+                      assetId: asset.assetId,
+                      contractAddress: assetReference,
+                      symbol: asset.symbol,
+                      name: asset.name,
+                      precision: asset.precision,
+                    }
+                  })
+                  .filter(
+                    (token): token is NonNullable<typeof token> => Boolean(token),
+                  )

Not required, but it avoids double CAIP parsing if you ever run this over a large asset set.

src/lib/utils/plasma.ts (2)

19-28: Consider improving error message for debugging.

The generic "invalid chain adapter" message doesn't provide context about what was expected or received.

Apply this diff to include more diagnostic information:

   if (!isPlasmaChainAdapter(adapter)) {
-    throw Error('invalid chain adapter')
+    throw Error(`Expected Plasma chain adapter for chainId ${chainId}, but got ${adapter?.getChainId?.() ?? 'unknown'}`)
   }

30-60: Consider including txHash in error logging.

The error log would benefit from including the transaction hash for debugging failed status lookups.

Apply this diff to improve error diagnostics:

   } catch (error) {
-    console.error('Error fetching Plasma transaction status:', error)
+    console.error(`Error fetching Plasma transaction status for ${txHash}:`, error)
     return TxStatus.Unknown
   }
packages/chain-adapters/src/evm/plasma/PlasmaChainAdapter.ts (5)

68-92: Avoid as any type assertions.

The constructor uses as any twice (lines 73 and 81), which violates the coding guideline to never use any type unless absolutely necessary.

Consider creating proper stub types for these cases:

+import type { TransactionParser } from '../types'
+
+type StubParser = Pick<TransactionParser<KnownChainIds.PlasmaMainnet>, 'parse'>
+
 constructor(args: ChainAdapterArgs) {
-  const dummyParser = {
+  const dummyParser: StubParser = {
     parse: () => {
       throw new Error('Transaction parsing is not supported for Plasma')
     },
-  } as any
+  }

   super({
     assetId: plasmaAssetId,
     chainId: DEFAULT_CHAIN_ID,
     rootBip44Params: ChainAdapter.rootBip44Params,
-    parser: dummyParser,
+    parser: dummyParser as TransactionParser<KnownChainIds.PlasmaMainnet>,
     supportedChainIds: SUPPORTED_CHAIN_IDS,
-    providers: {} as any,
+    providers: {} as Record<string, never>,
     rpcUrl: args.rpcUrl,
   })

142-144: Inconsistent error handling pattern.

getAccount throws a generic Error, while broadcastTransaction uses ErrorHandler. For consistency and proper error translation, consider using ErrorHandler here as well.

     } catch (err) {
-      throw new Error(`Failed to get account: ${err}`)
+      return ErrorHandler(err, {
+        translation: 'chainAdapters.errors.getAccount',
+      })
     }

147-149: Simplify async wrapper.

getKnownPlasmaTokens wraps a synchronous value in Promise.resolve. Since the caller uses await, this works, but if the intent is to keep this synchronous, consider returning the value directly and updating the call site.

-private getKnownPlasmaTokens(): Promise<TokenInfo[]> {
-  return Promise.resolve(this.knownTokens)
+private getKnownPlasmaTokens(): TokenInfo[] {
+  return this.knownTokens
 }

Then update line 117:

-const knownTokens = await this.getKnownPlasmaTokens()
+const knownTokens = this.getKnownPlasmaTokens()

283-286: Inconsistent error handling in fee methods.

Both getGasFeeData and getFeeData throw generic Error instead of using ErrorHandler. For consistency with broadcastTransaction, consider using ErrorHandler with appropriate translation keys.

     } catch (err) {
-      throw new Error(`Failed to get gas fee data: ${err}`)
+      return ErrorHandler(err, {
+        translation: 'chainAdapters.errors.getGasFeeData',
+      })
     }
     } catch (err) {
-      throw new Error(`Failed to get fee data: ${err}`)
+      return ErrorHandler(err, {
+        translation: 'chainAdapters.errors.getFeeData',
+      })
     }

Also applies to: 325-328


119-125: Consider extracting repeated type definition.

The token balance type is defined inline 4 times throughout the file. Consider extracting it to a type alias for better maintainability.

+type TokenBalance = {
+  assetId: AssetId
+  balance: string
+  symbol: string
+  name: string
+  precision: number
+}

Then use TokenBalance and TokenBalance[] in place of the inline definitions at lines 119-125, 154-161, 188-195, and 233-240.

Copy link
Collaborator

@NeOMakinG NeOMakinG left a comment

Choose a reason for hiding this comment

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

https://jam.dev/c/b5cd04a2-904d-41f5-9e18-2a089403c9e0

Better than hyperevm for this one, everything seems to work as expected minus getting rate limited and multicall not working!

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
.env.development (2)

66-66: Reorder VITE_PLASMA_NODE_URL to maintain alphabetical grouping within the nodes section.

VITE_PLASMA_NODE_URL should be positioned after VITE_OPTIMISM_NODE_URL and before VITE_POLYGON_NODE_URL to maintain alphabetical order.

  VITE_BASE_NODE_URL=https://dev-api.base.shapeshift.com/api/v1/jsonrpc
+ VITE_PLASMA_NODE_URL=https://rpc.plasma.to
  VITE_MONAD_NODE_URL=https://rpc.monad.xyz
- VITE_PLASMA_NODE_URL=https://rpc.plasma.to
  # Swap me back to 9R as-needed

95-95: Reorder VITE_FEATURE_PLASMA and verify base .env configuration.

VITE_FEATURE_PLASMA should come before VITE_FEATURE_SUNIO_SWAP to maintain alphabetical order in the feature flags section. Additionally, confirm that the base .env file explicitly sets VITE_FEATURE_PLASMA=false to ensure the feature is disabled by default and only enabled in development.

  VITE_FEATURE_MONAD=true
- VITE_FEATURE_PLASMA=true
  VITE_FEATURE_CETUS_SWAP=true
+ VITE_FEATURE_PLASMA=true
  VITE_FEATURE_SUNIO_SWAP=true

Please verify the base .env file contains VITE_FEATURE_PLASMA=false.

.env.production (1)

63-63: Reorder VITE_PLASMA_NODE_URL to maintain alphabetical grouping within the nodes section.

VITE_PLASMA_NODE_URL should be positioned after VITE_OPTIMISM_NODE_URL and before VITE_POLYGON_NODE_URL to maintain alphabetical order within the nodes section.

  VITE_BASE_NODE_URL=https://api.base.shapeshift.com/api/v1/jsonrpc
+ VITE_PLASMA_NODE_URL=https://rpc.plasma.to
  VITE_MONAD_NODE_URL=https://rpc.monad.xyz
- VITE_PLASMA_NODE_URL=https://rpc.plasma.to
  VITE_THORCHAIN_NODE_URL=https://api.thorchain.shapeshift.com/lcd
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 11b70cc and 340994e.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (27)
  • .env.development (2 hunks)
  • .env.production (1 hunks)
  • headers/csps/index.ts (2 hunks)
  • package.json (1 hunks)
  • packages/caip/src/adapters/coingecko/utils.ts (3 hunks)
  • packages/caip/src/constants.ts (5 hunks)
  • packages/chain-adapters/src/types.ts (6 hunks)
  • packages/chain-adapters/src/utils/ledgerAppGate.ts (2 hunks)
  • packages/types/src/base.ts (2 hunks)
  • packages/utils/src/assetData/baseAssets.ts (1 hunks)
  • packages/utils/src/assetData/getBaseAsset.ts (2 hunks)
  • packages/utils/src/chainIdToFeeAssetId.ts (2 hunks)
  • packages/utils/src/getAssetNamespaceFromChainId.ts (1 hunks)
  • packages/utils/src/getChainShortName.ts (1 hunks)
  • packages/utils/src/getNativeFeeAssetReference.ts (1 hunks)
  • scripts/generateAssetData/color-map.json (5 hunks)
  • scripts/generateAssetData/generateAssetData.ts (3 hunks)
  • src/config.ts (2 hunks)
  • src/constants/chains.ts (2 hunks)
  • src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx (2 hunks)
  • src/hooks/useWalletSupportsChain/useWalletSupportsChain.ts (3 hunks)
  • src/plugins/activePlugins.ts (2 hunks)
  • src/state/migrations/index.ts (1 hunks)
  • src/state/slices/opportunitiesSlice/mappings.ts (1 hunks)
  • src/state/slices/portfolioSlice/utils/index.ts (2 hunks)
  • src/state/slices/preferencesSlice/preferencesSlice.ts (2 hunks)
  • src/test/mocks/store.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (22)
  • src/state/slices/opportunitiesSlice/mappings.ts
  • packages/types/src/base.ts
  • src/state/slices/preferencesSlice/preferencesSlice.ts
  • src/test/mocks/store.ts
  • src/state/migrations/index.ts
  • src/hooks/useWalletSupportsChain/useWalletSupportsChain.ts
  • packages/utils/src/assetData/baseAssets.ts
  • packages/utils/src/chainIdToFeeAssetId.ts
  • packages/utils/src/assetData/getBaseAsset.ts
  • packages/chain-adapters/src/utils/ledgerAppGate.ts
  • packages/utils/src/getChainShortName.ts
  • packages/utils/src/getNativeFeeAssetReference.ts
  • src/state/slices/portfolioSlice/utils/index.ts
  • src/config.ts
  • src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx
  • package.json
  • packages/utils/src/getAssetNamespaceFromChainId.ts
  • packages/caip/src/constants.ts
  • headers/csps/index.ts
  • scripts/generateAssetData/generateAssetData.ts
  • src/constants/chains.ts
  • packages/chain-adapters/src/types.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,js,jsx}: Never assume a library is available - always check imports/package.json first
Prefer composition over inheritance
Write self-documenting code with clear variable and function names
Keep functions small and focused on a single responsibility
Avoid deep nesting - use early returns instead
Prefer procedural and easy to understand code
Never expose, log, or commit secrets, API keys, or credentials
Validate all inputs, especially user inputs
Handle errors gracefully with meaningful messages
Don't silently catch and ignore exceptions
Log errors appropriately for debugging
Provide fallback behavior when possible
Use appropriate data structures for the task
Never add code comments unless explicitly requested
When modifying code, do not add comments that reference previous implementations or explain what changed. Comments should only describe the current logic and functionality.
Use meaningful names for branches, variables, and functions
Always run yarn lint --fix and yarn type-check after making changes
Avoid let variable assignments - prefer const with inline IIFE switch statements or extract to functions for conditional logic

Files:

  • packages/caip/src/adapters/coingecko/utils.ts
  • src/plugins/activePlugins.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Avoid useEffect where practical - use it only when necessary and following best practices
Avoid 'any' types - use specific type annotations instead
For default values with user overrides, use computed values (useMemo) instead of useEffect - pattern: userSelected ?? smartDefault ?? fallback
When function parameters are unused due to interface requirements, refactor the interface or implementation to remove them rather than prefixing with underscore
Sanitize data before displaying to prevent XSS
Memoize aggressively - wrap component variables in useMemo and callbacks in useCallback where possible
For static JSX icon elements (e.g., <TbCopy />) that don't depend on state/props, define them as constants outside the component to avoid re-renders instead of using useMemo
Account for light/dark mode using useColorModeValue hook
Account for responsive mobile designs in all UI components
When applying styles, use the existing standards and conventions of the codebase
Use Chakra UI components and conventions
All copy/text must use translation keys - never hardcode strings
Use the translation hook: useTranslate() from react-polyglot
Use useFeatureFlag('FlagName') hook to access feature flag values in components
Prefer type over interface for type definitions
Use strict typing - avoid any
Use Nominal types for domain identifiers (e.g., WalletId, AccountId)
Import types from @shapeshiftoss/caip for chain/account/asset IDs
Use useAppSelector for Redux state
Use useAppDispatch for Redux actions
Memoize expensive computations with useMemo
Memoize callbacks with useCallback

**/*.{ts,tsx}: Use Result<T, E> pattern for error handling in swappers and APIs; ALWAYS use Ok() and Err() from @sniptt/monads; AVOID throwing within swapper API implementations
ALWAYS use custom error classes from @shapeshiftoss/errors with meaningful error codes for internationalization and relevant details in error objects
ALWAYS wrap async op...

Files:

  • packages/caip/src/adapters/coingecko/utils.ts
  • src/plugins/activePlugins.ts
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/naming-conventions.mdc)

**/*.{js,jsx,ts,tsx}: Use camelCase for variables, functions, and methods with descriptive names that explain the purpose
Use verb prefixes for functions that perform actions (e.g., fetch, validate, execute, update, calculate)
Use UPPER_SNAKE_CASE for constants and configuration values with descriptive names
Use handle prefix for event handlers with descriptive names in camelCase
Use descriptive boolean variable names with is, has, can, should prefixes
Use named exports for components, functions, and utilities instead of default exports
Use descriptive import names and avoid renaming imports unless necessary
Avoid non-descriptive variable names like data, item, obj, and single-letter variable names except in loops
Avoid abbreviations in names unless they are widely understood
Avoid generic function names like fn, func, or callback

Files:

  • packages/caip/src/adapters/coingecko/utils.ts
  • src/plugins/activePlugins.ts
{.env.development,.env.production}

📄 CodeRabbit inference engine (CLAUDE.md)

Use .env.development for dev-only features and .env.production for prod settings

Files:

  • .env.development
  • .env.production
🧠 Learnings (16)
📓 Common learnings
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.
📚 Learning: 2025-11-24T21:20:04.979Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T21:20:04.979Z
Learning: Applies to **/*.{ts,tsx} : Import types from `shapeshiftoss/caip` for chain/account/asset IDs

Applied to files:

  • packages/caip/src/adapters/coingecko/utils.ts
📚 Learning: 2025-11-24T21:20:57.909Z
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

Applied to files:

  • packages/caip/src/adapters/coingecko/utils.ts
📚 Learning: 2025-11-24T21:20:57.909Z
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

Applied to files:

  • packages/caip/src/adapters/coingecko/utils.ts
📚 Learning: 2025-08-17T21:53:03.806Z
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.

Applied to files:

  • packages/caip/src/adapters/coingecko/utils.ts
  • scripts/generateAssetData/color-map.json
📚 Learning: 2025-11-12T12:49:17.895Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11016
File: packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts:109-125
Timestamp: 2025-11-12T12:49:17.895Z
Learning: In packages/chain-adapters/src/evm/utils.ts, the getErc20Data function already includes a guard that returns an empty string when contractAddress is undefined (line 8: `if (!contractAddress) return ''`). This built-in handling means callers don't need to conditionally invoke getErc20Data—it safely handles both ERC20 tokens and native assets.

Applied to files:

  • packages/caip/src/adapters/coingecko/utils.ts
📚 Learning: 2025-09-08T15:53:09.362Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10442
File: src/components/TradeAssetSearch/components/GroupedAssetList/GroupedAssetList.tsx:34-35
Timestamp: 2025-09-08T15:53:09.362Z
Learning: In DefaultAssetList.tsx, the GroupedAssetList component already receives the activeChainId prop correctly on line ~58, contrary to automated analysis that may flag it as missing.

Applied to files:

  • packages/caip/src/adapters/coingecko/utils.ts
📚 Learning: 2025-11-24T21:20:57.909Z
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

Applied to files:

  • packages/caip/src/adapters/coingecko/utils.ts
📚 Learning: 2025-08-26T19:04:38.672Z
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.

Applied to files:

  • packages/caip/src/adapters/coingecko/utils.ts
📚 Learning: 2025-09-04T17:29:59.479Z
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.

Applied to files:

  • packages/caip/src/adapters/coingecko/utils.ts
📚 Learning: 2025-10-23T14:27:19.073Z
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.

Applied to files:

  • packages/caip/src/adapters/coingecko/utils.ts
📚 Learning: 2025-11-05T23:37:30.632Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10912
File: src/context/WalletProvider/NewWalletViews/NewWalletViewsSwitch.tsx:290-290
Timestamp: 2025-11-05T23:37:30.632Z
Learning: In the ShapeShift web codebase, `isMobile` imported from '@/lib/globals' is a module-level constant (defined as `export const isMobile = Boolean(window?.isShapeShiftMobile)`) that is evaluated once at module load time. It is a stable reference that does not need to be included in useCallback/useMemo/useEffect dependency arrays.

Applied to files:

  • src/plugins/activePlugins.ts
📚 Learning: 2025-11-24T21:20:04.979Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T21:20:04.979Z
Learning: Applies to src/config.ts : Default values always come from environment variables prefixed with `VITE_FEATURE_`

Applied to files:

  • .env.development
  • .env.production
📚 Learning: 2025-12-03T23:19:39.158Z
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.

Applied to files:

  • .env.development
  • .env.production
📚 Learning: 2025-09-09T06:01:24.130Z
Learnt from: 0xApotheosis
Repo: shapeshift/web PR: 10424
File: .env.production:3-3
Timestamp: 2025-09-09T06:01:24.130Z
Learning: In Vite, environment variables have a fallback mechanism where .env.production takes precedence over .env, but variables defined only in .env will still be available in the production environment if not overridden in .env.production.

Applied to files:

  • .env.development
  • .env.production
📚 Learning: 2025-11-24T21:20:04.979Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T21:20:04.979Z
Learning: Applies to {.env.development,.env.production} : Use `.env.development` for dev-only features and `.env.production` for prod settings

Applied to files:

  • .env.development
🧬 Code graph analysis (1)
packages/caip/src/adapters/coingecko/utils.ts (2)
packages/caip/src/assetId/assetId.ts (1)
  • toAssetId (59-127)
packages/caip/src/constants.ts (3)
  • CHAIN_NAMESPACE (87-94)
  • CHAIN_REFERENCE (100-124)
  • plasmaChainId (76-76)
🪛 dotenv-linter (4.0.0)
.env.development

[warning] 66-66: [UnorderedKey] The VITE_PLASMA_NODE_URL key should go before the VITE_POLYGON_NODE_URL key

(UnorderedKey)


[warning] 95-95: [UnorderedKey] The VITE_FEATURE_PLASMA key should go before the VITE_FEATURE_TRON key

(UnorderedKey)

.env.production

[warning] 63-63: [UnorderedKey] The VITE_PLASMA_NODE_URL key should go before the VITE_POLYGON_NODE_URL key

(UnorderedKey)

🔇 Additional comments (3)
scripts/generateAssetData/color-map.json (1)

4683-4683: Verify these token additions align with Plasma chain support.

This file shows color mappings for ERC20 tokens on Ethereum, Avalanche, BSC, and Base—but the PR objective states this is adding Plasma chain support. None of the changes include Plasma-specific token identifiers.

Clarify whether:

  1. These token additions support the Plasma ecosystem (e.g., tokens bridged to Plasma) but aren't Plasma-native assets
  2. Plasma chain color entries exist elsewhere in this PR
  3. These changes are unrelated to the Plasma feature and shouldn't be in this PR

Also applies to: 8702-8702, 12342-12342, 13753-13753, 14649-14649

src/plugins/activePlugins.ts (1)

17-17: LGTM! Plasma plugin correctly registered.

The import and array entry for the plasma plugin are correctly positioned alphabetically and follow the established pattern for adding new chain plugins.

Also applies to: 43-43

.env.production (1)

1-70: No action needed—the .env structure is correct.

The base .env file does not contain VITE_FEATURE_PLASMA and should not. The feature flag is properly configured with a code-level default of false in src/config.ts (line 97), which applies to production. Development overrides this with VITE_FEATURE_PLASMA=true in .env.development, enabling the feature for testing. This is the correct pattern.

Likely an incorrect or invalid review comment.

- Update PlasmaChainAdapter to use proper multicall implementation
- Import MULTICALL3_CONTRACT from @shapeshiftoss/contracts instead of hardcoding
- Import multicall3Abi from viem instead of inline definition
- Add PQueue throttling to prevent rate limiting issues
- Wrap all provider calls in requestQueue.add()
- Update chain-integration skill with multicall and throttling patterns
- Update swapper-integration skill with rate limiting guidance
- Note: CoinGecko does support 'plasma' as valid platform ID
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: 0

♻️ Duplicate comments (1)
packages/chain-adapters/src/evm/plasma/PlasmaChainAdapter.ts (1)

89-93: Adjust rate limiting to 25 req/s.

The current configuration allows ~20 req/s (1 request per 50ms), but based on previous feedback, Plasma requires throttling at 25 req/s to avoid rate limiting issues.

Apply this diff to fix the rate limit:

 this.requestQueue = new PQueue({
   intervalCap: 1,
-  interval: 50,
+  interval: 40,
   concurrency: 1,
 })

This changes the rate from 20 req/s (1000ms/50ms) to 25 req/s (1000ms/40ms).

🧹 Nitpick comments (3)
.claude/skills/chain-integration/SKILL.md (2)

1044-1044: Specify language for code fence.

The code block at line 1044 is missing a language identifier. Add a language specifier to the opening fence for proper syntax highlighting.

-\```
+\```

1060-1060: Wrap bare URLs in markdown links.

Lines 1060, 1065, 1066, and 1068 contain bare URLs. Wrap them in markdown link syntax for better readability and CSP compliance in the rendered documentation.

Example:

-Check if your chain's viem chain definition exists (e.g., `plasma` from 'viem/chains')
+Check if your chain's viem chain definition exists (e.g., `plasma` from [viem/chains](https://github.com/wevm/viem/tree/main/src/chains))

Also applies to: 1065-1068

.env (1)

236-236: Reorder for alphabetical consistency.

The feature flag should be placed before VITE_FEATURE_SUNIO_SWAP to maintain alphabetical ordering (MONAD → PLASMA → SUNIO_SWAP).

Apply this diff to fix the ordering:

 VITE_FEATURE_CETUS_SWAP=false
 VITE_FEATURE_SUNIO_SWAP=false
 VITE_FEATURE_MONAD=false
+VITE_FEATURE_PLASMA=false
-VITE_FEATURE_PLASMA=false

Based on learnings, ensure the feature flag is also added to src/state/slices/preferencesSlice/preferencesSlice.ts, src/config.ts, and src/test/mocks/store.ts per the standard feature flag pattern.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 340994e and cca876f.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (4)
  • .claude/skills/chain-integration/SKILL.md (6 hunks)
  • .claude/skills/swapper-integration/SKILL.md (1 hunks)
  • .env (1 hunks)
  • packages/chain-adapters/src/evm/plasma/PlasmaChainAdapter.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,js,jsx}: Never assume a library is available - always check imports/package.json first
Prefer composition over inheritance
Write self-documenting code with clear variable and function names
Keep functions small and focused on a single responsibility
Avoid deep nesting - use early returns instead
Prefer procedural and easy to understand code
Never expose, log, or commit secrets, API keys, or credentials
Validate all inputs, especially user inputs
Handle errors gracefully with meaningful messages
Don't silently catch and ignore exceptions
Log errors appropriately for debugging
Provide fallback behavior when possible
Use appropriate data structures for the task
Never add code comments unless explicitly requested
When modifying code, do not add comments that reference previous implementations or explain what changed. Comments should only describe the current logic and functionality.
Use meaningful names for branches, variables, and functions
Always run yarn lint --fix and yarn type-check after making changes
Avoid let variable assignments - prefer const with inline IIFE switch statements or extract to functions for conditional logic

Files:

  • packages/chain-adapters/src/evm/plasma/PlasmaChainAdapter.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Avoid useEffect where practical - use it only when necessary and following best practices
Avoid 'any' types - use specific type annotations instead
For default values with user overrides, use computed values (useMemo) instead of useEffect - pattern: userSelected ?? smartDefault ?? fallback
When function parameters are unused due to interface requirements, refactor the interface or implementation to remove them rather than prefixing with underscore
Sanitize data before displaying to prevent XSS
Memoize aggressively - wrap component variables in useMemo and callbacks in useCallback where possible
For static JSX icon elements (e.g., <TbCopy />) that don't depend on state/props, define them as constants outside the component to avoid re-renders instead of using useMemo
Account for light/dark mode using useColorModeValue hook
Account for responsive mobile designs in all UI components
When applying styles, use the existing standards and conventions of the codebase
Use Chakra UI components and conventions
All copy/text must use translation keys - never hardcode strings
Use the translation hook: useTranslate() from react-polyglot
Use useFeatureFlag('FlagName') hook to access feature flag values in components
Prefer type over interface for type definitions
Use strict typing - avoid any
Use Nominal types for domain identifiers (e.g., WalletId, AccountId)
Import types from @shapeshiftoss/caip for chain/account/asset IDs
Use useAppSelector for Redux state
Use useAppDispatch for Redux actions
Memoize expensive computations with useMemo
Memoize callbacks with useCallback

**/*.{ts,tsx}: Use Result<T, E> pattern for error handling in swappers and APIs; ALWAYS use Ok() and Err() from @sniptt/monads; AVOID throwing within swapper API implementations
ALWAYS use custom error classes from @shapeshiftoss/errors with meaningful error codes for internationalization and relevant details in error objects
ALWAYS wrap async op...

Files:

  • packages/chain-adapters/src/evm/plasma/PlasmaChainAdapter.ts
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/naming-conventions.mdc)

**/*.{js,jsx,ts,tsx}: Use camelCase for variables, functions, and methods with descriptive names that explain the purpose
Use verb prefixes for functions that perform actions (e.g., fetch, validate, execute, update, calculate)
Use UPPER_SNAKE_CASE for constants and configuration values with descriptive names
Use handle prefix for event handlers with descriptive names in camelCase
Use descriptive boolean variable names with is, has, can, should prefixes
Use named exports for components, functions, and utilities instead of default exports
Use descriptive import names and avoid renaming imports unless necessary
Avoid non-descriptive variable names like data, item, obj, and single-letter variable names except in loops
Avoid abbreviations in names unless they are widely understood
Avoid generic function names like fn, func, or callback

Files:

  • packages/chain-adapters/src/evm/plasma/PlasmaChainAdapter.ts
🧠 Learnings (36)
📓 Common learnings
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: 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.
📚 Learning: 2025-11-24T21:20:04.979Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T21:20:04.979Z
Learning: To add a new feature flag: (1) Add to `FeatureFlags` type in `src/state/slices/preferencesSlice/preferencesSlice.ts`, (2) Add environment variable validation in `src/config.ts`, (3) Add to initial state in `preferencesSlice.ts`, (4) Add to test mock in `src/test/mocks/store.ts`, (5) Set appropriate values in `.env`, `.env.development`, and `.env.production`

Applied to files:

  • .env
📚 Learning: 2025-11-24T21:20:04.979Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T21:20:04.979Z
Learning: Applies to src/config.ts : Default values always come from environment variables prefixed with `VITE_FEATURE_`

Applied to files:

  • .env
📚 Learning: 2025-12-03T23:19:39.158Z
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.

Applied to files:

  • .env
📚 Learning: 2025-11-12T12:48:02.977Z
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.

Applied to files:

  • .claude/skills/swapper-integration/SKILL.md
📚 Learning: 2025-11-24T21:20:17.804Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/error-handling.mdc:0-0
Timestamp: 2025-11-24T21:20:17.804Z
Learning: Applies to **/api/**/*.{ts,tsx} : ALWAYS use `timeoutMonadic` for API calls with appropriate timeout values and handle timeout errors gracefully

Applied to files:

  • .claude/skills/swapper-integration/SKILL.md
📚 Learning: 2025-11-03T22:31:30.786Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10985
File: packages/swapper/src/swappers/PortalsSwapper/getPortalsTradeQuote/getPortalsTradeQuote.ts:0-0
Timestamp: 2025-11-03T22:31:30.786Z
Learning: In packages/swapper/src/swappers/PortalsSwapper, the rate and quote files intentionally use different approaches for calculating buyAmountBeforeSlippageCryptoBaseUnit: getPortalsTradeRate.tsx uses minOutputAmount / (1 - buffer) for conservative estimates, while getPortalsTradeQuote.ts uses outputAmount / (1 - buffer) for final quote display. This difference is validated by on-chain simulation testing and is intentional.

Applied to files:

  • .claude/skills/swapper-integration/SKILL.md
📚 Learning: 2025-12-04T22:57:50.850Z
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.

Applied to files:

  • .claude/skills/chain-integration/SKILL.md
  • packages/chain-adapters/src/evm/plasma/PlasmaChainAdapter.ts
📚 Learning: 2025-11-24T21:20:57.909Z
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

Applied to files:

  • .claude/skills/chain-integration/SKILL.md
  • packages/chain-adapters/src/evm/plasma/PlasmaChainAdapter.ts
📚 Learning: 2025-08-17T21:53:03.806Z
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.

Applied to files:

  • .claude/skills/chain-integration/SKILL.md
📚 Learning: 2025-09-12T13:44:17.019Z
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.

Applied to files:

  • .claude/skills/chain-integration/SKILL.md
  • packages/chain-adapters/src/evm/plasma/PlasmaChainAdapter.ts
📚 Learning: 2025-11-19T16:59:50.569Z
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.

Applied to files:

  • .claude/skills/chain-integration/SKILL.md
  • packages/chain-adapters/src/evm/plasma/PlasmaChainAdapter.ts
📚 Learning: 2025-11-12T12:49:17.895Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11016
File: packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts:109-125
Timestamp: 2025-11-12T12:49:17.895Z
Learning: In packages/chain-adapters/src/evm/utils.ts, the getErc20Data function already includes a guard that returns an empty string when contractAddress is undefined (line 8: `if (!contractAddress) return ''`). This built-in handling means callers don't need to conditionally invoke getErc20Data—it safely handles both ERC20 tokens and native assets.

Applied to files:

  • .claude/skills/chain-integration/SKILL.md
  • packages/chain-adapters/src/evm/plasma/PlasmaChainAdapter.ts
📚 Learning: 2025-11-24T21:20:57.909Z
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

Applied to files:

  • .claude/skills/chain-integration/SKILL.md
  • packages/chain-adapters/src/evm/plasma/PlasmaChainAdapter.ts
📚 Learning: 2025-11-24T21:20:57.909Z
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 : Reuse executeEvmTransaction utility for EVM-based swappers instead of implementing custom transaction execution

Applied to files:

  • .claude/skills/chain-integration/SKILL.md
📚 Learning: 2025-10-23T14:27:19.073Z
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.

Applied to files:

  • .claude/skills/chain-integration/SKILL.md
  • packages/chain-adapters/src/evm/plasma/PlasmaChainAdapter.ts
📚 Learning: 2025-08-26T19:04:38.672Z
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.

Applied to files:

  • .claude/skills/chain-integration/SKILL.md
  • packages/chain-adapters/src/evm/plasma/PlasmaChainAdapter.ts
📚 Learning: 2025-11-20T12:00:45.005Z
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.

Applied to files:

  • .claude/skills/chain-integration/SKILL.md
📚 Learning: 2025-11-24T21:20:04.979Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T21:20:04.979Z
Learning: Applies to **/*.{ts,tsx} : Import types from `shapeshiftoss/caip` for chain/account/asset IDs

Applied to files:

  • .claude/skills/chain-integration/SKILL.md
  • packages/chain-adapters/src/evm/plasma/PlasmaChainAdapter.ts
📚 Learning: 2025-11-24T21:20:57.909Z
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

Applied to files:

  • .claude/skills/chain-integration/SKILL.md
  • packages/chain-adapters/src/evm/plasma/PlasmaChainAdapter.ts
📚 Learning: 2025-11-24T21:20:57.909Z
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

Applied to files:

  • .claude/skills/chain-integration/SKILL.md
📚 Learning: 2025-09-04T17:29:59.479Z
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.

Applied to files:

  • .claude/skills/chain-integration/SKILL.md
📚 Learning: 2025-10-01T07:42:40.195Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10596
File: src/components/Layout/Header/NavBar/WalletConnectedMenu.tsx:77-99
Timestamp: 2025-10-01T07:42:40.195Z
Learning: In WalletConnectedMenu.tsx's handleReconnectWallet handler, gomesalexandre prefers throwing an error for unsupported wallet types in the default case rather than gracefully handling with a fallback. His reasoning: "if we have a problem here, we have bigger problems" - only supported wallets (KeepKey, Ledger, MetaMask, Coinbase, Phantom) should reach the reconnect flow when disconnected/locked, so encountering an unsupported type indicates a larger architectural issue that should be surfaced explicitly rather than masked with graceful degradation.

Applied to files:

  • .claude/skills/chain-integration/SKILL.md
📚 Learning: 2025-09-16T08:47:31.440Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10528
File: src/plugins/walletConnectToDapps/utils/createApprovalNamespaces.ts:39-47
Timestamp: 2025-09-16T08:47:31.440Z
Learning: In WalletConnect dApps createApprovalNamespaces logic, required namespaces have different semantics than optional namespaces. Required namespaces are validated upfront in the UI - users cannot proceed without accounts for all required chains, and required chains are always selected and unselectable. Therefore, additional filtering by selectedChainIds is unnecessary for required namespaces since the validation flow guarantees they will be supported and selected.

Applied to files:

  • .claude/skills/chain-integration/SKILL.md
📚 Learning: 2025-11-24T21:20:04.979Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T21:20:04.979Z
Learning: Applies to src/state/slices/**/*.ts : Migrations are required when changing persisted state structure (see `src/state/migrations/`)

Applied to files:

  • .claude/skills/chain-integration/SKILL.md
📚 Learning: 2025-09-08T15:53:09.362Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10442
File: src/components/TradeAssetSearch/components/GroupedAssetList/GroupedAssetList.tsx:34-35
Timestamp: 2025-09-08T15:53:09.362Z
Learning: In DefaultAssetList.tsx, the GroupedAssetList component already receives the activeChainId prop correctly on line ~58, contrary to automated analysis that may flag it as missing.

Applied to files:

  • .claude/skills/chain-integration/SKILL.md
📚 Learning: 2025-11-24T21:21:12.774Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/typescript-best-practices.mdc:0-0
Timestamp: 2025-11-24T21:21:12.774Z
Learning: Applies to **/*.{ts,tsx} : ALWAYS use type guards for runtime type checking in TypeScript

Applied to files:

  • packages/chain-adapters/src/evm/plasma/PlasmaChainAdapter.ts
📚 Learning: 2025-11-24T21:21:12.774Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/typescript-best-practices.mdc:0-0
Timestamp: 2025-11-24T21:21:12.774Z
Learning: Applies to **/*.{ts,tsx} : ALWAYS use type guards instead of type assertions when possible in TypeScript

Applied to files:

  • packages/chain-adapters/src/evm/plasma/PlasmaChainAdapter.ts
📚 Learning: 2025-11-24T21:21:12.774Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/typescript-best-practices.mdc:0-0
Timestamp: 2025-11-24T21:21:12.774Z
Learning: Applies to **/*.{ts,tsx} : ALWAYS use `is` prefix for type guard functions in TypeScript

Applied to files:

  • packages/chain-adapters/src/evm/plasma/PlasmaChainAdapter.ts
📚 Learning: 2025-11-24T21:21:12.774Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/typescript-best-practices.mdc:0-0
Timestamp: 2025-11-24T21:21:12.774Z
Learning: Applies to **/*.{ts,tsx} : ALWAYS create custom type guards for complex types in TypeScript

Applied to files:

  • packages/chain-adapters/src/evm/plasma/PlasmaChainAdapter.ts
📚 Learning: 2025-09-10T15:35:46.223Z
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.

Applied to files:

  • packages/chain-adapters/src/evm/plasma/PlasmaChainAdapter.ts
📚 Learning: 2025-09-12T10:35:51.632Z
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.

Applied to files:

  • packages/chain-adapters/src/evm/plasma/PlasmaChainAdapter.ts
📚 Learning: 2025-08-11T09:45:51.174Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10219
File: src/components/MultiHopTrade/components/TradeInput/TradeInput.tsx:175-180
Timestamp: 2025-08-11T09:45:51.174Z
Learning: gomesalexandre prefers truthy checks over explicit boolean comparisons (e.g., `walletSupportsSellAssetChain` instead of `walletSupportsSellAssetChain === true`) when dealing with tri-state values (boolean | null) in TypeScript, as the falsy behavior for null/undefined is intentional and acceptable.

Applied to files:

  • packages/chain-adapters/src/evm/plasma/PlasmaChainAdapter.ts
📚 Learning: 2025-12-09T21:06:09.903Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11335
File: packages/swapper/src/swappers/CetusSwapper/endpoints.ts:66-68
Timestamp: 2025-12-09T21:06:09.903Z
Learning: In packages/swapper/src/swappers/CetusSwapper/endpoints.ts, gomesalexandre is comfortable with throwing errors directly in getUnsignedSuiTransaction and similar transaction preparation methods, rather than using the Result pattern. The Result pattern with makeSwapErrorRight/TradeQuoteError is primarily for the main swapper API methods (getTradeQuote, getTradeRate), while helper/preparation methods can use throws.

Applied to files:

  • packages/chain-adapters/src/evm/plasma/PlasmaChainAdapter.ts
📚 Learning: 2025-09-12T12:00:33.924Z
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.

Applied to files:

  • packages/chain-adapters/src/evm/plasma/PlasmaChainAdapter.ts
📚 Learning: 2025-10-16T11:14:40.657Z
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.

Applied to files:

  • packages/chain-adapters/src/evm/plasma/PlasmaChainAdapter.ts
🪛 dotenv-linter (4.0.0)
.env

[warning] 236-236: [UnorderedKey] The VITE_FEATURE_PLASMA key should go before the VITE_FEATURE_SUNIO_SWAP key

(UnorderedKey)

🪛 LanguageTool
.claude/skills/chain-integration/SKILL.md

[uncategorized] ~639-~639: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...ueue.add(() => ...)` - This prevents rate limiting issues with public RPCs 5. **Direct RPC...

(EN_COMPOUND_ADJECTIVE_INTERNAL)

🪛 markdownlint-cli2 (0.18.1)
.claude/skills/chain-integration/SKILL.md

1044-1044: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


1060-1060: Bare URL used

(MD034, no-bare-urls)


1065-1065: Bare URL used

(MD034, no-bare-urls)


1066-1066: Bare URL used

(MD034, no-bare-urls)


1068-1068: Bare URL used

(MD034, no-bare-urls)

🔇 Additional comments (11)
.claude/skills/swapper-integration/SKILL.md (1)

258-284: Well-documented rate limiting pattern.

The new "Key Pattern: Rate Limiting and Throttling" section clearly documents a practical pattern for implementing request queuing on chain adapters and swappers that directly interact with RPC/API endpoints. The examples properly show both swapper service and provider call patterns, and the use-case clarification (public endpoints) is helpful.

.claude/skills/chain-integration/SKILL.md (7)

1390-1409: Gotcha 11 excellently documents a subtle EVM chain requirement.

The documentation clearly explains why assertSupportsChain needs explicit cases for each chain in EvmBaseAdapter, even when hdwallet properly implements the support interfaces. This gotcha prevents a common integration mistake where developers assume the wallet's _supportsChainName flag is sufficient.


1411-1448: Gotcha 12 is critical and well-emphasizes the scope.

This gotcha correctly and emphatically documents that ledgerAppGate.ts changes are needed for ALL wallet types (not just Ledger), and that missing cases cause misleading "Unsupported chainId" errors even during native wallet derivation. The example error message and the bold "CRITICAL" label appropriately highlight this integration blocker.


1450-1494: Gotcha 13 documents an important portfolio state bug.

The documentation clearly explains how unsupported chains in Portals can cascade into account removal from Redux state, and provides the correct graceful-skip pattern. This prevents a confusing symptom where accounts briefly appear then vanish.


1496-1538: Gotcha 14 maps UI symptom (missing dropdown) to root cause (missing switch case).

The documentation connects observable symptoms in the swapper UI (no dropdown, account unselectable, balance shows in header but input shows 0) to the missing accountIdToLabel switch case. This symptom-to-cause mapping is invaluable for future integrators who might encounter the same issue.


1366-1388: Gotcha 10 documents essential rate-limiting pattern for EVM chains.

The PQueue throttling pattern (intervalCap: 1, interval: 50, concurrency: 1) is clearly explained with concrete implementation guidance. This prevents 429 errors and connection issues from public RPCs—a common gotcha for chains using public endpoints.


1036-1111: New swapper support section provides systematic research guidance.

The addition of Step 5.4 guides integrators through researching and implementing swapper support (Relay, 0x, CowSwap, etc.) with specific documentation links and implementation patterns. This fills a gap in the original guide and prevents incomplete integrations where a chain works but swaps don't.


1559-1570: Updated checklist correctly marks critical files.

The additions to the checklist appropriately flag ledgerAppGate.ts and portfolioSlice/utils/index.ts (accountIdToLabel) as CRITICAL, emphasizing they must not be overlooked. The annotations explaining why (with Gotcha references) make the checklist actionable.

packages/chain-adapters/src/evm/plasma/PlasmaChainAdapter.ts (3)

149-265: LGTM: Token balance retrieval implementation.

The multicall-based token balance retrieval with fallback to individual calls is well-designed. The batching strategy (500 tokens per batch), error handling, and requestQueue integration provide good resilience against RPC failures and rate limits.


267-332: LGTM: Gas fee estimation logic.

The fee estimation correctly calculates txFee = (maxFeePerGas ?? gasPrice) × gasLimit for each tier. Using identical fees for fast/average/slow is appropriate for chains without a mature fee market.


334-377: LGTM: Transaction broadcasting with proper safeguards.

The broadcast implementation correctly validates addresses against sanctions lists before submitting transactions. The stub implementations for subscriptions, history, and parsing are appropriate for an initial chain adapter implementation.

- Remove Plasma from Portals supported networks configuration
  - Prevents unwanted API calls to portals/v2/account?networks[]=plasma
  - Plasma is not supported by Portals, should gracefully skip instead
- Add Plasma to isNativeEvmAsset helper for proper native token detection
- Fix CoinGecko adapter test to include Plasma in expected results
- Note: Plasma does NOT need Tenderly gas overrides like Monad
- Note: Plasma is NOT supported by Near Intents swapper
@gomesalexandre gomesalexandre enabled auto-merge (squash) December 10, 2025 22:18
@gomesalexandre gomesalexandre merged commit 391f148 into develop Dec 10, 2025
4 checks passed
@gomesalexandre gomesalexandre deleted the feat_plasma branch December 10, 2025 22:19
@coderabbitai coderabbitai bot mentioned this pull request Dec 10, 2025
1 task
@coderabbitai coderabbitai bot mentioned this pull request Dec 27, 2025
15 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants