Skip to content

Conversation

@gomesalexandre
Copy link
Contributor

@gomesalexandre gomesalexandre commented Jan 5, 2026

Description

New chain who dis

Issue (if applicable)

closes N/A

Risk

Low, new chain, under flag

Testing

  • Sends
  • Receives
  • Relay swaps
  • Make sure balances get updated
  • Ensure Tx history (actual Tx history, not action center) looks somehow sane

Engineering

Test with shapeshift/hdwallet#779

Operations

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

Screenshots

https://jam.dev/c/27146c48-4262-47e9-aaf1-d161cbe368b9

Summary by CodeRabbit

  • New Features

    • Added Katana blockchain support: network, asset discovery, trading, and explorer integration.
    • Katana assets now appear in searches, popular assets, and portfolio views when enabled.
    • Katana RPC endpoint and a feature flag were added (feature off by default; enabled in development).
  • Chores

    • Bumped wallet-related dependencies to 1.62.38.

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

- Add katana to activePlugins
- Add Katana feature flag check in PluginProvider
- Add katanaChainId and supportsKatana to evm account derivation
- Add supportsKatana and Katana case to EvmBaseAdapter.assertSupportsChain
- Fix networkIcon URL in baseAssets
- Add katana plugin and feature flag
- Add katanaChainId to evm account derivation
- Add supportsKatana to EvmBaseAdapter.assertSupportsChain
- Add Katana coingecko platform mapping
- Bump hdwallet dependencies to 1.62.37
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 5, 2026

📝 Walkthrough

Walkthrough

Adds Katana (a new EVM chain) across the app: environment variables, feature flag, CSP, chain constants/types, adapters and plugin, RPC/viem clients, asset mappings and generation, wallet/fee support, swapper mappings, and migration entries.

Changes

Cohort / File(s) Summary
Environment Configuration
\.env, \.env.development, src/config.ts
Added VITE_KATANA_NODE_URL and VITE_FEATURE_KATANA validators; .env defaults feature to false, .env.development sets it true.
CSP Headers
headers/csps/chains/katana.ts, headers/csps/index.ts
New Katana CSP module exporting connect-src from VITE_KATANA_NODE_URL; added to exported csps array.
Types & CAIP Constants
packages/types/src/base.ts, packages/caip/src/constants.ts, packages/caip/src/adapters/coingecko/index.ts
Added KnownChainIds.KatanaMainnet, katanaChainId, katanaAssetId, CAIP refs (747474, 60), and Coingecko platform mappings for Katana.
Chain Adapters & Types
packages/chain-adapters/src/evm/* (EvmBaseAdapter.ts, index.ts, katana/*, types.ts)
New KatanaChainAdapter, exported katana namespace, included Katana in evmChainIds and chain-specific type mappings; added runtime support hooks.
RPC / Viem Clients
packages/contracts/src/ethersProviderSingleton.ts, packages/contracts/src/viemClient.ts
Added Katana RPC branch using VITE_KATANA_NODE_URL; created viemKatanaClient and mapped Katana chain/network IDs to the client.
Asset Declarations & Lookups
packages/utils/src/assetData/*, packages/utils/src/getBaseAsset.ts, packages/utils/src/chainIdToFeeAssetId.ts, getAssetNamespaceFromChainId.ts, getChainShortName.ts, getNativeFeeAssetReference.ts
Added exported katana base asset and mappings; map KatanaMainnet to ERC20/fee/short name KAT and include asset in fee/namespace/resolution utilities.
Asset Generation Scripts
scripts/generateAssetData/* (coingecko.ts, generateAssetData.ts, katana/index.ts, generateRelatedAssetIndex.ts)
New katana asset generator module; fetches Katana assets from Coingecko and integrates them into generated asset data and related-asset indices.
Plugin Registration
src/plugins/katana/index.tsx, src/plugins/activePlugins.ts
New Katana plugin registering a KatanaChainAdapter using VITE_KATANA_NODE_URL; added to active plugins list.
Feature Flags & Config
src/state/slices/preferencesSlice/preferencesSlice.ts, src/test/mocks/store.ts, src/config.ts
Added Katana feature flag, initialized from config; updated test mock store flag.
Wallet / Account Support
src/hooks/useWalletSupportsChain/useWalletSupportsChain.ts, src/lib/account/evm.ts, src/state/slices/portfolioSlice/utils/index.ts
Added Katana wallet-support checks, supportsKatana gating for account derivation and asset support.
Asset Service & State
src/lib/asset-service/service/AssetService.ts, src/state/slices/opportunitiesSlice/mappings.ts, src/state/migrations/index.ts
Asset service filters Katana assets when feature disabled; added empty DeFi opportunities entry for Katana; added migrations 261 and 262 to clear assets.
UI Integrations
src/components/TradeAssetSearch/hooks/useGetPopularAssetsQuery.tsx, src/context/PluginProvider/PluginProvider.tsx, src/constants/chains.ts
Included katanaAssetId in popular assets (feature-gated); PluginProvider and knownChainIds logic gate Katana on feature flag.
Swapper / Relay
packages/swapper/src/swappers/RelaySwapper/constant.ts, .../relayTokenToAssetId.ts
Added mapping from katanaChainId to Relay network id and asset resolution support for Katana.
Utilities
src/lib/utils/katana.ts
New helpers: isKatanaChainAdapter type guard and getKatanaTransactionStatus (fetches receipt, maps to TxStatus).
Dependency Updates
package.json, packages/chain-adapters/package.json, packages/swapper/package.json
Bumped @shapeshiftoss/hdwallet-* dependencies to 1.62.38.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Plugin as PluginRegister
  participant AssetSvc as AssetService
  participant Adapter as KatanaChainAdapter
  participant Viem as ViemKatanaClient
  participant RPC as KatanaRPC (VITE_KATANA_NODE_URL)

  Note over Plugin,Adapter: Plugin registration flow (feature-gated)
  Plugin->>AssetSvc: request getKnownTokens()
  AssetSvc-->>Plugin: return ERC20 tokens for katanaChainId
  Plugin->>Adapter: instantiate with rpcUrl & getKnownTokens
  Adapter->>Viem: uses viemKatanaClient (chain=katana)
  Viem->>RPC: HTTP requests to VITE_KATANA_NODE_URL
  RPC-->>Viem: responses (txs, receipts)
  Note over Viem,RPC: used for RPC calls & tx status checks
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 A hop, a click, a Katana spring—
New chain, new nodes, the rabbit sings.
Flags flipped false till tests are done,
Tokens fetched beneath the sun.
Hooray for hops and code that runs!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ 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%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: katana chain' is clear, specific, and directly summarizes the main change: adding Katana chain integration support.

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

✨ 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_katana

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 gomesalexandre marked this pull request as ready for review January 5, 2026 16:50
@gomesalexandre gomesalexandre requested a review from a team as a code owner January 5, 2026 16:50
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

Fix all issues with AI Agents 🤖
In @headers/csps/chains/katana.ts:
- Around line 8-10: The csp object currently puts env.VITE_KATANA_NODE_URL
directly into the 'connect-src' array which can include undefined; update the
csp definition (the exported csp constant and its 'connect-src' entry) to
explicitly filter out falsy values by applying .filter(Boolean) to the array
containing env.VITE_KATANA_NODE_URL so it matches the established pattern (like
near.ts) and prevents undefined values from being included.

In @packages/chain-adapters/src/evm/katana/KatanaChainAdapter.ts:
- Around line 44-46: Replace the hardcoded return in getName() with the
established enum reverse-lookup pattern: use ChainAdapterDisplayName with the
appropriate SupportedChainId key (e.g., SupportedChainId.Katana) so getName()
returns ChainAdapterDisplayName[SupportedChainId.Katana]; update imports if
needed to include ChainAdapterDisplayName and SupportedChainId to match other
adapters.

Caution

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

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

240-264: Missing Katana fee asset ID in FEE_ASSET_IDS array.

The FEE_ASSET_IDS array includes other recently added EVM chains (hyperEvm at line 258, plasma implied from context) but does not include katanaAssetId. Since Katana is an EVM chain that requires ETH for gas fees, it should be added to this array.

🔎 Proposed fix
   arbitrumNovaAssetId,
   baseAssetId,
   monadAssetId,
+  katanaAssetId,
   solAssetId,
   tronAssetId,
🧹 Nitpick comments (5)
.env (1)

159-159: Consider reordering environment variables for consistency.

The static analysis tool flagged ordering inconsistencies:

  • VITE_KATANA_NODE_URL (line 159) should appear before VITE_MONAD_NODE_URL to maintain alphabetical ordering in the nodes section.
  • VITE_FEATURE_KATANA (line 308) should appear before VITE_FEATURE_MONAD to maintain consistent ordering in the feature flags section.

While this doesn't affect functionality, maintaining consistent ordering improves maintainability and makes the file easier to scan.

🔎 Proposed reordering

For the nodes section around line 159:

 VITE_HYPEREVM_NODE_URL=https://rpc.hyperliquid.xyz/evm
+VITE_KATANA_NODE_URL=https://rpc.katana.network
 VITE_MONAD_NODE_URL=https://rpc.monad.xyz
 VITE_PLASMA_NODE_URL=https://rpc.plasma.to
-VITE_KATANA_NODE_URL=https://rpc.katana.network

For the feature flags section around line 308:

 VITE_FEATURE_HYPEREVM=true
+VITE_FEATURE_KATANA=false
 VITE_FEATURE_MONAD=true
 VITE_FEATURE_PLASMA=true
-VITE_FEATURE_KATANA=false

Also applies to: 308-308

.env.development (2)

66-66: Reorder VITE_KATANA_NODE_URL alphabetically.

The variable should be placed before VITE_MONAD_NODE_URL to maintain alphabetical ordering in the nodes section.

🔎 Proposed fix

Move line 66 to appear between lines 63 and 64:

 VITE_BASE_NODE_URL=https://dev-api.base.shapeshift.com/api/v1/jsonrpc
+VITE_KATANA_NODE_URL=https://rpc.katana.network
 VITE_MONAD_NODE_URL=https://rpc.monad.xyz
 VITE_PLASMA_NODE_URL=https://rpc.plasma.to
-VITE_KATANA_NODE_URL=https://rpc.katana.network

97-97: Reorder VITE_FEATURE_KATANA alphabetically.

The variable should be placed before VITE_FEATURE_NEAR to maintain alphabetical ordering in the feature flags section.

🔎 Proposed fix

Move line 97 to appear between lines 94 and 96:

 VITE_FEATURE_WC_DIRECT_CONNECTION=true
 VITE_FEATURE_CETUS_SWAP=true
+VITE_FEATURE_KATANA=true
 VITE_FEATURE_NEAR=true
-VITE_FEATURE_KATANA=true
src/plugins/katana/index.tsx (1)

22-36: Consider optimizing fromAssetId parsing.

The fromAssetId function is called twice for each asset—once in the filter predicate (line 26) and again in the map function (line 31). This could be optimized by parsing once and reusing the result.

🔎 Proposed optimization to parse fromAssetId once per asset
                const getKnownTokens = () => {
                  const assetService = getAssetService()
-                 return assetService.assets
-                   .filter(asset => {
-                     const { chainId, assetNamespace } = fromAssetId(asset.assetId)
-                     return chainId === katanaChainId && assetNamespace === 'erc20'
-                   })
-                   .map(asset => ({
-                     assetId: asset.assetId,
-                     contractAddress: fromAssetId(asset.assetId).assetReference,
-                     symbol: asset.symbol,
-                     name: asset.name,
-                     precision: asset.precision,
-                   }))
+                 return assetService.assets
+                   .map(asset => ({ asset, parsed: fromAssetId(asset.assetId) }))
+                   .filter(({ parsed }) => 
+                     parsed.chainId === katanaChainId && parsed.assetNamespace === 'erc20'
+                   )
+                   .map(({ asset, parsed }) => ({
+                     assetId: asset.assetId,
+                     contractAddress: parsed.assetReference,
+                     symbol: asset.symbol,
+                     name: asset.name,
+                     precision: asset.precision,
+                   }))
                }
packages/chain-adapters/src/evm/katana/KatanaChainAdapter.ts (1)

18-20: Consider adding defensive checks in the type guard.

The type guard uses a type assertion before validating that adapter is a safe object with a getType method. If adapter is null or undefined, calling .getType() will throw at runtime.

🔎 Proposed defensive type guard
 export const isKatanaChainAdapter = (adapter: unknown): adapter is ChainAdapter => {
-  return (adapter as ChainAdapter).getType() === KnownChainIds.KatanaMainnet
+  return (
+    adapter != null &&
+    typeof adapter === 'object' &&
+    'getType' in adapter &&
+    typeof (adapter as ChainAdapter).getType === 'function' &&
+    (adapter as ChainAdapter).getType() === KnownChainIds.KatanaMainnet
+  )
 }

@gomesalexandre gomesalexandre marked this pull request as draft January 6, 2026 01:04
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/6e4e1851-774d-4520-b3a9-b89a15e03487

Looks good overall, spotted a few things but fixed them already:

  • Send status were never resolved (missing in useSendActionSubscriber)
  • ETH for katana wasn't in the related asset array

We will need to rerun asset generation to fix the related asset keys (my connection isn't good enough for that...)

@gomesalexandre gomesalexandre marked this pull request as ready for review January 7, 2026 16:19
@gomesalexandre
Copy link
Contributor Author

Looks good overall, spotted a few things but fixed them already:

  • Send status were never resolved (missing in useSendActionSubscriber)
  • ETH for katana wasn't in the related asset array

tyvm @NeOMakinG !

Retested in https://jam.dev/c/35bea64e-478a-4822-a879-12980f72e7a5 - apart from a bit of gas flakiness and one v. low value Tx which failed, not noticing anything odd here!

@gomesalexandre gomesalexandre enabled auto-merge (squash) January 7, 2026 16:20
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

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

66-66: Consider reordering for alphabetical consistency.

The Katana environment variables are functionally correct. However, for consistency with alphabetical ordering conventions:

  • VITE_KATANA_NODE_URL should be placed before VITE_MONAD_NODE_URL (around line 64)
  • VITE_FEATURE_KATANA should be placed before VITE_FEATURE_NEAR (around line 97)
📝 Proposed reordering

For the node URLs section (around lines 64-66):

 VITE_BASE_NODE_URL=https://dev-api.base.shapeshift.com/api/v1/jsonrpc
+VITE_KATANA_NODE_URL=https://rpc.katana.network
 VITE_MONAD_NODE_URL=https://rpc.monad.xyz
 VITE_PLASMA_NODE_URL=https://rpc.plasma.to
-VITE_KATANA_NODE_URL=https://rpc.katana.network
 VITE_HYPEREVM_NODE_URL=https://rpc.hyperliquid.xyz/evm

For the feature flags section (around lines 97-98):

 VITE_FEATURE_AVNU_SWAP=true
+VITE_FEATURE_KATANA=true
 VITE_FEATURE_NEAR=true
-VITE_FEATURE_KATANA=true

Also applies to: 98-98

📜 Review details

Configuration used: Organization 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 444721b and a4e6e6c.

⛔ Files ignored due to path filters (10)
  • public/generated/asset-manifest.json is excluded by !**/generated/**
  • public/generated/asset-manifest.json.br is excluded by !**/generated/**
  • public/generated/asset-manifest.json.gz is excluded by !**/*.gz, !**/generated/**
  • public/generated/generatedAssetData.json is excluded by !**/generated/**
  • public/generated/generatedAssetData.json.br is excluded by !**/generated/**
  • public/generated/generatedAssetData.json.gz is excluded by !**/*.gz, !**/generated/**
  • public/generated/relatedAssetIndex.json is excluded by !**/generated/**
  • public/generated/relatedAssetIndex.json.br is excluded by !**/generated/**
  • public/generated/relatedAssetIndex.json.gz is excluded by !**/*.gz, !**/generated/**
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (12)
  • .env.development
  • headers/csps/index.ts
  • package.json
  • packages/chain-adapters/package.json
  • packages/swapper/package.json
  • scripts/generateAssetData/generateRelatedAssetIndex/generateRelatedAssetIndex.ts
  • src/config.ts
  • src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx
  • src/lib/utils/katana.ts
  • src/state/migrations/index.ts
  • src/state/slices/preferencesSlice/preferencesSlice.ts
  • src/test/mocks/store.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/state/migrations/index.ts
  • package.json
  • src/test/mocks/store.ts
  • src/state/slices/preferencesSlice/preferencesSlice.ts
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{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:

  • scripts/generateAssetData/generateRelatedAssetIndex/generateRelatedAssetIndex.ts
  • headers/csps/index.ts
  • src/lib/utils/katana.ts
  • src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx
  • src/config.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:

  • scripts/generateAssetData/generateRelatedAssetIndex/generateRelatedAssetIndex.ts
  • headers/csps/index.ts
  • src/lib/utils/katana.ts
  • src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx
  • src/config.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:

  • scripts/generateAssetData/generateRelatedAssetIndex/generateRelatedAssetIndex.ts
  • headers/csps/index.ts
  • src/lib/utils/katana.ts
  • src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx
  • src/config.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
**/*.{tsx,jsx}

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

**/*.{tsx,jsx}: ALWAYS wrap React components in error boundaries and provide user-friendly fallback components with error logging
ALWAYS use useErrorToast hook for displaying errors with translated error messages and handle different error types appropriately

Use PascalCase for React component names and match the component name to the file name

Files:

  • src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx
**/*.{jsx,tsx}

📄 CodeRabbit inference engine (.cursor/rules/react-best-practices.mdc)

**/*.{jsx,tsx}: ALWAYS use useMemo for expensive computations, object/array creations, and filtered data
ALWAYS use useMemo for derived values and computed properties
ALWAYS use useMemo for conditional values and simple transformations
ALWAYS use useCallback for event handlers and functions passed as props
ALWAYS use useCallback for any function that could be passed as a prop or dependency
ALWAYS include all dependencies in useEffect, useMemo, useCallback dependency arrays
NEVER use // eslint-disable-next-line react-hooks/exhaustive-deps unless absolutely necessary, and ALWAYS explain why dependencies are excluded if using eslint disable
ALWAYS use named exports for components; NEVER use default exports for components
KEEP component files under 200 lines when possible; BREAK DOWN large components into smaller, reusable pieces
EXTRACT complex logic into custom hooks
ALWAYS wrap components in error boundaries for production
ALWAYS handle async errors properly in async operations
ALWAYS provide user-friendly error messages in error handling
ALWAYS use virtualization for lists with 100+ items
ALWAYS implement proper key props for list items
ALWAYS lazy load heavy components using React.lazy for code splitting
ALWAYS use Suspense wrapper for lazy loaded components
USE local state for component-level state; LIFT state up when needed across multiple components; USE Context for avoiding prop drilling; USE Redux only for global state shared across multiple places
Wrap components receiving props with memo for performance optimization

Files:

  • src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursor/rules/react-best-practices.mdc)

Ensure TypeScript types are explicit and proper; avoid use of any type

Files:

  • src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx
src/config.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Default values always come from environment variables prefixed with VITE_FEATURE_

Files:

  • src/config.ts
🧠 Learnings (44)
📓 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: 10231
File: src/components/AssetSearch/components/AssetList.tsx:2-2
Timestamp: 2025-08-08T15:00:49.887Z
Learning: Project shapeshift/web: NeOMakinG prefers avoiding minor a11y/UI nitpicks (e.g., adding aria-hidden to decorative icons in empty states like src/components/AssetSearch/components/AssetList.tsx) within feature PRs; defer such suggestions to a follow-up instead of blocking the PR.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10231
File: src/components/MultiHopTrade/components/TradeInput/components/HighlightedTokens.tsx:14-14
Timestamp: 2025-08-08T15:00:22.321Z
Learning: In shapeshift/web reviews for NeOMakinG, avoid nitpicks to change deep-relative imports to '@/…' alias paths within feature/non-refactor PRs; defer such style-only changes to a dedicated follow-up refactor unless they fix an issue.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11569
File: packages/chain-adapters/src/evm/katana/KatanaChainAdapter.ts:44-46
Timestamp: 2026-01-05T23:24:46.120Z
Learning: In packages/chain-adapters/src/evm/**/[chain]ChainAdapter.ts files, second-class EVM chain adapters (those extending SecondClassEvmAdapter, such as Monad, Plasma, HyperEVM, and Katana) use hardcoded strings in their getName() method (e.g., `return 'Monad'`), NOT the enum reverse-lookup pattern. The enum reverse-lookup pattern (`Object.values(ChainAdapterDisplayName).indexOf(...)`) only applies to first-class chain adapters.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 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-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:

  • scripts/generateAssetData/generateRelatedAssetIndex/generateRelatedAssetIndex.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:

  • scripts/generateAssetData/generateRelatedAssetIndex/generateRelatedAssetIndex.ts
📚 Learning: 2025-09-04T13:22:35.399Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10380
File: src/state/slices/assetsSlice/selectors.ts:45-51
Timestamp: 2025-09-04T13:22:35.399Z
Learning: In shapeshift/web, the isPrimaryAsset function in src/lib/utils/asset.ts is intentionally designed to only treat null relatedAssetKey as primary (not undefined). The asset generation process specifically sets relatedAssetKey to null for primary assets, while undefined means the asset doesn't participate in grouping and should not be considered primary. Only assets with null relatedAssetKey or where relatedAssetKey === assetId are primary assets.

Applied to files:

  • scripts/generateAssetData/generateRelatedAssetIndex/generateRelatedAssetIndex.ts
📚 Learning: 2025-12-26T15:45:47.558Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11515
File: scripts/generateAssetData/generateRelatedAssetIndex/generateRelatedAssetIndex.ts:100-122
Timestamp: 2025-12-26T15:45:47.558Z
Learning: In scripts/generateAssetData/generateRelatedAssetIndex/generateRelatedAssetIndex.ts, gomesalexandre is comfortable with the fetchBridgedCategoryMappings function lacking try-catch error handling for CoinGecko API calls. He prefers letting the script crash on API failures rather than adding defensive error handling, consistent with his fail-fast approach for asset generation scripts.

Applied to files:

  • scripts/generateAssetData/generateRelatedAssetIndex/generateRelatedAssetIndex.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:

  • scripts/generateAssetData/generateRelatedAssetIndex/generateRelatedAssetIndex.ts
  • headers/csps/index.ts
  • packages/swapper/package.json
  • packages/chain-adapters/package.json
📚 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:

  • scripts/generateAssetData/generateRelatedAssetIndex/generateRelatedAssetIndex.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:

  • scripts/generateAssetData/generateRelatedAssetIndex/generateRelatedAssetIndex.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:

  • scripts/generateAssetData/generateRelatedAssetIndex/generateRelatedAssetIndex.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:

  • scripts/generateAssetData/generateRelatedAssetIndex/generateRelatedAssetIndex.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:

  • scripts/generateAssetData/generateRelatedAssetIndex/generateRelatedAssetIndex.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:

  • scripts/generateAssetData/generateRelatedAssetIndex/generateRelatedAssetIndex.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:

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

Applied to files:

  • headers/csps/index.ts
  • src/config.ts
📚 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:

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

Applied to files:

  • headers/csps/index.ts
  • src/lib/utils/katana.ts
  • packages/chain-adapters/package.json
  • src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx
📚 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/package.json
📚 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/package.json
📚 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 camelCase for variable and function names in the Swapper system

Applied to files:

  • packages/swapper/package.json
📚 Learning: 2025-11-19T22:20:25.661Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10767
File: package.json:324-324
Timestamp: 2025-11-19T22:20:25.661Z
Learning: In shapeshift/web package.json, the resolution "gridplus-sdk/bs58check": "2.1.2" is intentional and must not be removed. It forces gridplus-sdk's transitive bs58check dependency from 4.0.0 down to 2.1.2 because bs58check 4.0.0 breaks legacy address validation (due to bs58 v6.0.0 and noble/hash vs 2.1.2's bs58 v4.0.0 and create-hash).

Applied to files:

  • packages/swapper/package.json
  • packages/chain-adapters/package.json
📚 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 PascalCase for types, interfaces, and enums in the Swapper system

Applied to files:

  • packages/swapper/package.json
📚 Learning: 2025-08-08T20:16:12.898Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10222
File: package.json:202-202
Timestamp: 2025-08-08T20:16:12.898Z
Learning: In shapeshift/web, the semver package must be included in dependencies (not devDependencies) because hdwallet packages have transient dependencies that require semver but don't ship it themselves. This ensures semver is available at runtime for hdwallet functionality.

Applied to files:

  • packages/swapper/package.json
  • packages/chain-adapters/package.json
📚 Learning: 2025-08-08T20:27:02.203Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10222
File: package.json:202-202
Timestamp: 2025-08-08T20:27:02.203Z
Learning: In shapeshift/web, while gomesalexandre generally prefers pinned dependencies for security, semver with a caret range (^7.7.2) is acceptable as an exception since it's already a transient dependency of many packages and is being made explicit for hdwallet support.

Applied to files:

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

Applied to files:

  • packages/swapper/package.json
  • packages/chain-adapters/package.json
📚 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/swapper/package.json
📚 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/package.json
📚 Learning: 2025-08-29T18:09:45.982Z
Learnt from: kaladinlight
Repo: shapeshift/web PR: 10376
File: vite.config.mts:136-137
Timestamp: 2025-08-29T18:09:45.982Z
Learning: In the ShapeShift web repository vite.config.mts, the commonjsOptions.exclude configuration using bare package name strings like ['shapeshiftoss/caip', 'shapeshiftoss/types'] works correctly for excluding specific packages from CommonJS transformation, despite theoretical concerns about module ID matching patterns.

Applied to files:

  • packages/swapper/package.json
  • packages/chain-adapters/package.json
📚 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/swapper/package.json
  • packages/chain-adapters/package.json
📚 Learning: 2025-12-17T14:50:01.629Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11449
File: packages/chain-adapters/src/tron/TronChainAdapter.ts:570-596
Timestamp: 2025-12-17T14:50:01.629Z
Learning: In packages/chain-adapters/src/tron/TronChainAdapter.ts, the parseTx method uses `unknown` type for the txHashOrTx parameter intentionally. TRON is a "second-class chain" that works differently from other chains - it accepts either a string hash (to fetch TronTx via unchained client) or a TronTx object directly. The base chain-adapter interface is strongly typed and doesn't accommodate this flexible signature, so `unknown` is used as an appropriate escape hatch rather than a type safety issue.

Applied to files:

  • src/lib/utils/katana.ts
  • src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx
📚 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:

  • src/lib/utils/katana.ts
  • packages/chain-adapters/package.json
  • src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx
📚 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:

  • src/lib/utils/katana.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:

  • src/lib/utils/katana.ts
  • packages/chain-adapters/package.json
📚 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:

  • src/lib/utils/katana.ts
  • packages/chain-adapters/package.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:

  • src/lib/utils/katana.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
  • src/config.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: 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.development
  • src/config.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 {.env.development,.env.production} : Use `.env.development` for dev-only features and `.env.production` for prod settings

Applied to files:

  • .env.development
📚 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
📚 Learning: 2026-01-03T15:12:57.968Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11537
File: packages/caip/src/adapters/coincap/generate.ts:7-7
Timestamp: 2026-01-03T15:12:57.968Z
Learning: In shapeshift/web, when scripts in packages/caip run via `yarn workspace shapeshiftoss/caip generate`, the working directory is `packages/caip`, so dotenv paths should use `../../.env` to reach the monorepo root .env file, not `.env`. The `-T` flag only affects which node_modules is used (root's), not the working directory.

Applied to files:

  • packages/chain-adapters/package.json
📚 Learning: 2025-08-22T15:07:18.021Z
Learnt from: kaladinlight
Repo: shapeshift/web PR: 10326
File: src/hooks/useActionCenterSubscribers/useThorchainLpActionSubscriber.tsx:37-41
Timestamp: 2025-08-22T15:07:18.021Z
Learning: In src/hooks/useActionCenterSubscribers/useThorchainLpActionSubscriber.tsx, kaladinlight prefers not to await the upsertBasePortfolio call in the Base chain handling block, indicating intentional fire-and-forget behavior for Base portfolio upserts in the THORChain LP completion flow.

Applied to files:

  • src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx
📚 Learning: 2025-08-22T13:16:12.721Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10323
File: src/pages/RFOX/hooks/useRfoxRewardDistributionActionSubscriber.tsx:104-105
Timestamp: 2025-08-22T13:16:12.721Z
Learning: In src/pages/RFOX/hooks/useRfoxRewardDistributionActionSubscriber.tsx, the guard `if (!actions[actionId]) return` before upserting completed reward distributions is intentional product behavior. NeOMakinG confirmed that the system should only show completion notifications for reward distributions that were previously seen in a pending state, not for distributions the user missed during the pending phase.

Applied to files:

  • src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx
📚 Learning: 2025-08-22T14:59:04.889Z
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.

Applied to files:

  • src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx
📚 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:

  • src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx
📚 Learning: 2025-12-27T16:02:52.792Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11536
File: src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx:252-265
Timestamp: 2025-12-27T16:02:52.792Z
Learning: When reviewing bug fixes, especially in shapeshift/web, prefer minimal changes that fix correctness over introducing broader refactors or quality-of-life improvements (e.g., extracting duplicated logic) unless such improvements are essential to the fix. Apply this guideline broadly to TSX files and related components, not just the specific location, to keep changes focused and maintainable.

Applied to files:

  • src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx
🧬 Code graph analysis (4)
scripts/generateAssetData/generateRelatedAssetIndex/generateRelatedAssetIndex.ts (1)
packages/caip/src/constants.ts (6)
  • ethAssetId (10-10)
  • optimismAssetId (12-12)
  • arbitrumAssetId (16-16)
  • arbitrumNovaAssetId (17-17)
  • baseAssetId (18-18)
  • katanaAssetId (22-22)
headers/csps/index.ts (1)
packages/utils/src/assetData/baseAssets.ts (1)
  • katana (375-390)
src/lib/utils/katana.ts (1)
packages/caip/src/constants.ts (1)
  • katanaChainId (82-82)
src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx (2)
src/config.ts (1)
  • getConfig (249-251)
src/lib/utils/katana.ts (1)
  • getKatanaTransactionStatus (15-43)
🪛 dotenv-linter (4.0.0)
.env.development

[warning] 66-66: [UnorderedKey] The VITE_KATANA_NODE_URL key should go before the VITE_MONAD_NODE_URL key

(UnorderedKey)


[warning] 98-98: [UnorderedKey] The VITE_FEATURE_KATANA key should go before the VITE_FEATURE_NEAR key

(UnorderedKey)

⏰ 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: Call / Static
🔇 Additional comments (11)
scripts/generateAssetData/generateRelatedAssetIndex/generateRelatedAssetIndex.ts (2)

12-12: LGTM!

The import follows the established pattern for EVM chain asset IDs and is used on line 49.


49-49: LGTM!

Adding katanaAssetId to the ETH related assets array is correct for this new EVM chain integration. The grouping ensures Katana ETH (slip44:60) is properly linked to ETH across other chains, consistent with how Optimism, Arbitrum, Base, and other EVM chains are handled.

packages/chain-adapters/package.json (1)

38-39: Dependency versions verified.

Both @shapeshiftoss/hdwallet-core@1.62.38 and @shapeshiftoss/hdwallet-ledger@1.62.38 exist on npm and are consistent with the Katana chain integration (hdwallet PR #779). The pinned versions follow the project's security-focused dependency management practices.

src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx (2)

15-15: LGTM!

The import of getKatanaTransactionStatus is correctly placed and follows the pattern of other second-class chain utility imports.


204-210: LGTM!

The Katana transaction status handling follows the exact pattern used for HyperEVM and other second-class chains. The implementation correctly:

  • Retrieves the Katana node URL from config
  • Calls getKatanaTransactionStatus with the transaction hash and node URL
  • Treats both Confirmed and Failed statuses as completion states
src/config.ts (1)

68-68: LGTM!

The environment variable validators for Katana are correctly implemented:

  • VITE_KATANA_NODE_URL uses url() validator (required, no default)
  • VITE_FEATURE_KATANA uses bool({ default: false }) (secure default for new chain)

Both entries follow the established pattern and are placed in the appropriate alphabetical positions.

Also applies to: 108-108

headers/csps/index.ts (1)

17-17: LGTM!

The Katana CSP import and registration follow the established pattern for chain CSP integration. The import is correctly placed and the katana entry is appropriately added to the csps array.

Also applies to: 110-110

packages/swapper/package.json (1)

43-43: @shapeshiftoss/hdwallet-core@1.62.38 is valid and has no security advisories. The version exists on npm as the latest release and has no known vulnerabilities.

src/lib/utils/katana.ts (3)

1-4: LGTM!

All imports are necessary and properly declared. The type-only import for EvmChainAdapter follows TypeScript best practices.


6-13: LGTM!

The type guard correctly validates the adapter structure before invoking methods, ensuring type safety. The pattern of checking for the function's existence and then comparing the chain ID is sound.


15-43: No action required—code follows established patterns and is compatible with ethers v6.11.1.

The staticNetwork option is supported by the project's ethers version (6.11.1) and is an established pattern used consistently across the codebase in five locations, including the nearly identical hyperevm.ts utility. The transaction receipt status handling (1 for confirmed, 0 for failed, null/undefined for unknown) correctly implements ethers v6 behavior and properly handles all cases including pre-Byzantium transactions.

@gomesalexandre gomesalexandre merged commit 34831da into develop Jan 7, 2026
4 checks passed
@gomesalexandre gomesalexandre deleted the feat_katana branch January 7, 2026 16:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants