Skip to content

Conversation

@NeOMakinG
Copy link
Collaborator

@NeOMakinG NeOMakinG commented Dec 30, 2025

Description

1000 birds one stone:

  • Add tokens balances to Starknet
  • Add market data and tokens balances
  • Add AVNU swapper (waiting for the affiliate addresse from the DAO)
  • Implement swaps
  • Allow sending tokens

Issue (if applicable)

Nothing to close

Risk

Low, under a flag

High Risk PRs Require 2 approvals

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

Testing

  • Try to swap anything to anything using avnu (STRK to USDC, USDC to USDT...)
  • Ensure balances are updated after the TX goes successful
  • Try to send STRK to another address
  • Try to send USDC or USDT to another address
  • Ensure TXs are successful in the action center
  • Market data for starknet tokens should be fine

Engineering

Operations

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

Screenshots (if applicable)

image image

Summary by CodeRabbit

  • New Features

    • Avnu swapper integration — users can get quotes/rates, build unsigned Starknet transactions, estimate fees, execute swaps, and check swap status.
    • Expanded Starknet support — runtime token discovery, Starknet asset mappings, and improved tiered fee estimates.
  • Chores

    • Feature flag and config added to enable Avnu swaps; new runtime dependency and UI icon included.
  • Tests

    • Updated tests and mocks to cover Starknet mappings and the Avnu feature flag.

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 30, 2025

📝 Walkthrough

Walkthrough

Adds AVNU Starknet swapper integration: new AvnuSwapper and API, AVNU SDK dependency, CSP and feature-flag wiring, Starknet token/treasury support and getKnownTokens, fee/nonce handling updates, UI icon and fee-call adjustments.

Changes

Cohort / File(s) Summary
Env & Feature Flags
\.env.development`, src/config.ts, src/state/slices/preferencesSlice/preferencesSlice.ts, src/state/helpers.ts, src/test/mocks/store.ts`
Add VITE_FEATURE_AVNU_SWAP env flag, validator, feature flag state init, enablement wiring and test mock.
CSPs / Headers
headers/csps/defi/swappers/Avnu.ts, headers/csps/index.ts
New CSP adding connect-src for https://starknet.api.avnu.fi and register it in exported csps.
Swapper package & exports
packages/swapper/package.json, packages/swapper/src/index.ts, packages/swapper/src/constants.ts, packages/swapper/src/types.ts
Add @avnu/avnu-sdk dependency; register SwapperName.Avnu, default slippage constant and swappers entry; re-export AvnuSwapper; extend TradeQuoteStep with avnuSpecific.
Avnu Swapper implementation
packages/swapper/src/swappers/AvnuSwapper/*
(AvnuSwapper.ts, endpoints.ts, getTradeQuote.ts, getTradeRate.ts, types.ts, utils/*, index.ts)
New AvnuSwapper and avnuApi: quote/rate fetching via AVNU SDK, unsigned Starknet tx construction, fee estimation integration, trade status checks, constants/helpers and exports.
Swapper utils / status
packages/swapper/src/utils.ts
Add checkStarknetSwapStatus to derive trade status from Starknet receipts.
Starknet Chain Adapter & plugin
packages/chain-adapters/src/starknet/StarknetChainAdapter.ts, packages/chain-adapters/src/starknet/types.ts, src/plugins/starknet/index.tsx
Add batched RPC provider and rate-limited queue, introduce TokenInfo and runtime getKnownTokens callback, extend Starknet tx details and parameterized fee input/nonce handling; plugin supplies getKnownTokens.
Fee call sites (Starknet) / UI
src/components/Modals/Send/utils.ts, src/components/Modals/Send/views/SendAmountDetails.tsx, src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx, packages/swapper/src/swappers/NearIntentsSwapper/*
Replace parameterless Starknet getFeeData() calls with parameterized GetFeeDataInput (to, value, chainSpecific.from, tokenContractAddress, sendMax) for accurate fee estimation.
Coingecko / asset support & tests
packages/caip/src/adapters/coingecko/utils.ts, packages/caip/src/adapters/coingecko/index.test.ts, packages/caip/src/adapters/coingecko/utils.test.ts, src/lib/coingecko/utils.ts
Add Starknet token mapping and include Starknet chain ID in supported lists; update tests to include Starknet mappings.
Utils exports & token namespace
packages/utils/src/index.ts
Reorganize exports and add recognition of ASSET_NAMESPACE.starknetToken in isToken.
Treasury & helpers
packages/swapper/src/swappers/utils/helpers/helpers.ts, packages/utils/src/treasury.ts
Add Starknet treasury support and export DAO_TREASURY_STARKNET.
State / enablement
src/state/helpers.ts
Include Avnu in swapper enablement logic and in cross-account-deny list.
UI icon
src/components/MultiHopTrade/components/TradeInput/components/SwapperIcon/SwapperIcon.tsx
Add Avnu icon handling.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant UI as Trade UI
  participant AvnuApi as AvnuSwapper / avnuApi
  participant AvnuSDK as AVNU SDK
  participant StarknetAdapter as Starknet ChainAdapter
  participant StarknetRPC as Starknet RPC

  User->>UI: Request AVNU quote
  UI->>AvnuApi: getTradeQuote(sell,buy,amount)
  AvnuApi->>AvnuSDK: fetchQuotes(...)
  AvnuSDK-->>AvnuApi: quotes
  AvnuApi->>StarknetAdapter: getFeeData({to,value,chainSpecific,sendMax})
  StarknetAdapter->>StarknetRPC: estimateFee / get_nonce
  StarknetRPC-->>StarknetAdapter: feeEstimate / nonce
  StarknetAdapter-->>AvnuApi: feeData
  AvnuApi-->>UI: TradeQuote (quoteId, routes, fees)

  User->>UI: Confirm
  UI->>AvnuApi: getUnsignedStarknetTransaction(quote,slippage)
  AvnuApi->>AvnuSDK: quoteToCalls(quote)
  AvnuSDK-->>AvnuApi: calldata/calls
  AvnuApi->>StarknetRPC: get_nonce(account)
  StarknetRPC-->>AvnuApi: nonce
  AvnuApi->>StarknetAdapter: getFeeData({from,to,value,tokenContractAddress})
  StarknetAdapter->>StarknetRPC: estimateFee(invoke)
  StarknetRPC-->>StarknetAdapter: resourceBounds
  StarknetAdapter-->>AvnuApi: fee/maxFee
  AvnuApi-->>UI: unsigned tx payload (txHash, addressNList, _txDetails)

  UI->>StarknetRPC: submit signed tx
  StarknetRPC-->>UI: txHash
  UI->>AvnuApi: checkTradeStatus(txHash)
  AvnuApi->>StarknetRPC: getTransactionReceipt(txHash)
  StarknetRPC-->>AvnuApi: receipt {execution_status}
  AvnuApi-->>UI: TradeStatus (Confirmed/Failed/Pending)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

high risk

Suggested reviewers

  • gomesalexandre
  • premiumjibles

Poem

🐰 I hopped through code with nimble paws,
I added AVNU, routes, and clause.
Nonces line up and fees now sing,
Starknet calls make transactions spring.
Hop on, swap safe — carrots for applause! 🥕

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: implement avnu for starknet tokens swaps' directly and accurately summarizes the primary change: introducing AVNU swapper integration for Starknet token swapping functionality, which is the main focus across the entire changeset.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ 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 ekubo-starknet

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@NeOMakinG NeOMakinG marked this pull request as ready for review December 31, 2025 11:30
@NeOMakinG NeOMakinG requested a review from a team as a code owner December 31, 2025 11:30
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 (5)
packages/swapper/src/swappers/AvnuSwapper/utils/constants.ts (1)

4-10: Consider adding SupportedChainIds type structure.

The coding guidelines specify: "Define supported chain IDs for each swapper in utils/constants.ts with both 'sell' and 'buy' properties following the pattern: SupportedChainIds type."

The current implementation uses a simple array, but the standard pattern includes separate sell/buy chain ID arrays:

type SupportedChainIds = {
  sell: ChainId[]
  buy: ChainId[]
}

export const AVNU_SUPPORTED_CHAIN_IDS: SupportedChainIds = {
  sell: [KnownChainIds.StarknetMainnet],
  buy: [KnownChainIds.StarknetMainnet],
} as const

However, if AVNU only supports same-chain swaps (Starknet → Starknet), the current simple array may be intentional.

Based on coding guidelines.

.env.development (1)

98-98: Consider alphabetical ordering for feature flags.

The static analyzer suggests placing VITE_FEATURE_AVNU_SWAP before VITE_FEATURE_CETUS_SWAP for consistency.

packages/swapper/src/types.ts (1)

408-411: Consider replacing any[] with a more specific type for routes.

The routes: any[] violates the coding guideline to avoid any types. Other swapper-specific metadata in this file uses explicit types (e.g., sunioTransactionMetadata.route, chainflipSpecific). If the AVNU SDK provides a type for routes, consider importing and using it here for better type safety and maintainability.

packages/swapper/src/utils.ts (1)

435-435: Consider adding type definition for Starknet receipt.

The any type for receipt works but loses type safety. Consider defining a minimal type interface for the receipt properties used (execution_status).

🔎 Suggested type definition
+type StarknetTransactionReceipt = {
+  execution_status?: 'SUCCEEDED' | 'REVERTED' | string
+}
+
 export const checkStarknetSwapStatus = async ({
   // ...
 }): Promise<TradeStatus> => {
   try {
     const adapter = assertGetStarknetChainAdapter(starknetChainId)
     const provider = adapter.getStarknetProvider()

-    const receipt: any = await provider.getTransactionReceipt(txHash)
+    const receipt = await provider.getTransactionReceipt(txHash) as StarknetTransactionReceipt
packages/swapper/src/swappers/AvnuSwapper/endpoints.ts (1)

38-41: Default slippage inconsistency.

The hardcoded fallback of 0.01 (1%) differs from DEFAULT_AVNU_SLIPPAGE_DECIMAL_PERCENTAGE (0.5%) defined in constants. Consider using the centralized constant for consistency.

🔎 Suggested fix
+import { getDefaultSlippageDecimalPercentageForSwapper } from '../../../constants'
+import { SwapperName } from '../../../types'
+
 // Convert slippage from decimal percentage string to number for AVNU format (e.g., "0.01" = 1%)
 const slippage: number = slippageTolerancePercentageDecimal
   ? parseFloat(slippageTolerancePercentageDecimal)
-  : 0.01
+  : parseFloat(getDefaultSlippageDecimalPercentageForSwapper(SwapperName.Avnu))

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/caip/src/adapters/coingecko/index.test.ts (1)

326-336: Consider adding test coverage for Starknet chain mapping.

Since this PR adds Starknet token support and includes USDC mappings, consider adding a test case to verify that chainIdToCoingeckoAssetPlatform correctly handles Starknet chain IDs, similar to the existing Ethereum test at line 328.

📝 Example test case for Starknet
it('can get CoinGecko asset platform from Starknet ChainId', () => {
  const chainId = starknetChainId
  expect(chainIdToCoingeckoAssetPlatform(chainId)).toEqual(CoingeckoAssetPlatform.Starknet)
})

Note: This assumes starknetChainId constant and CoingeckoAssetPlatform.Starknet are defined in the implementation.

📜 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 e58ae8f and bace3b1.

📒 Files selected for processing (2)
  • packages/caip/src/adapters/coingecko/index.test.ts
  • packages/caip/src/adapters/coingecko/utils.test.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.test.ts
  • packages/caip/src/adapters/coingecko/index.test.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/caip/src/adapters/coingecko/index.test.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
  • packages/caip/src/adapters/coingecko/index.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/caip/src/adapters/coingecko/index.test.ts
🧠 Learnings (9)
📓 Common learnings
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10231
File: src/components/AssetSearch/components/AssetList.tsx:2-2
Timestamp: 2025-08-08T15:00:49.887Z
Learning: Project shapeshift/web: NeOMakinG prefers avoiding minor a11y/UI nitpicks (e.g., adding aria-hidden to decorative icons in empty states like src/components/AssetSearch/components/AssetList.tsx) within feature PRs; defer such suggestions to a follow-up instead of blocking the PR.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11016
File: packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts:109-145
Timestamp: 2025-11-12T12:18:00.863Z
Learning: NEAR Intents swapper: The NEAR 1Click API does not provide gas limit estimation logic like other swappers (e.g., magic gasLimit fields). For ERC20 token swaps in getTradeQuote, accurate fee estimation requires token approval and sufficient balance; without these prerequisites, fees may display as 0 or use inaccurate native transfer estimates. This is a known limitation of the NEAR Intents integration.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10323
File: src/pages/RFOX/components/Stake/components/StakeSummary.tsx:112-114
Timestamp: 2025-08-22T13:00:44.879Z
Learning: NeOMakinG prefers to keep PR changes minimal and focused on the core objectives, avoiding cosmetic or defensive code improvements that aren't directly related to the PR scope, even when they would improve robustness.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10128
File: .cursor/rules/error-handling.mdc:266-274
Timestamp: 2025-07-29T10:35:22.059Z
Learning: NeOMakinG prefers less nitpicky suggestions on documentation and best practices files, finding overly detailed suggestions on minor implementation details (like console.error vs logger.error) too granular for cursor rules documentation.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10380
File: src/pages/Dashboard/components/AccountList/AccountTable.tsx:60-0
Timestamp: 2025-09-02T08:34:08.157Z
Learning: NeOMakinG prefers code review comments to focus only on actual PR changes, not pre-existing code issues, unless there are critical security or correctness concerns directly related to the new functionality.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10234
File: src/components/MultiHopTrade/hooks/useGetTradeQuotes/hooks/useTrackTradeQuotes.ts:42-86
Timestamp: 2025-08-08T11:41:22.794Z
Learning: NeOMakinG prefers not to include refactors in move-only PRs; such suggestions should be deferred to follow-up issues instead of being applied within the same PR.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10380
File: src/components/Table/Table.theme.ts:177-180
Timestamp: 2025-09-02T12:38:46.940Z
Learning: NeOMakinG prefers to defer technical debt and CSS correctness issues (like improper hover selectors) to follow-up PRs when the current PR is already large and focused on major feature implementation, even when the issues are valid from a usability/technical perspective.
📚 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/index.test.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/index.test.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/index.test.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:

  • packages/caip/src/adapters/coingecko/index.test.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:

  • packages/caip/src/adapters/coingecko/index.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/*/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/index.test.ts
📚 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:

  • packages/caip/src/adapters/coingecko/index.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/index.test.ts
⏰ 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 (2)
packages/caip/src/adapters/coingecko/utils.test.ts (1)

193-195: No issues found. The slip44 value 9004 is the correct SLIP-0044 registered coin type for StarkNet, and SN_MAIN is the standard chain reference for StarkNet mainnet per the CAIP-2 specification. Both values are correctly defined in packages/caip/src/constants.ts and accurately reflected in the test expectation.

packages/caip/src/adapters/coingecko/index.test.ts (1)

3-8: LGTM: Import reorganization improves clarity.

The explicit imports from the current module make dependencies clearer and follow TypeScript conventions.

Copy link
Contributor

@gomesalexandre gomesalexandre left a comment

Choose a reason for hiding this comment

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

Conceptually LGTM, happy to get this in for the sake of progression. A few functional issues to be fixed either in this PR or as direct follow-up:

  • Balance update doesn't seem to be consistently happy (see first STRK -> USDC failure, happy on refetch)
  • Tx links are sad e.g this guy
  • Was able to get into estimation failures on subsequent Txs i.e Fee estimation failed: {"code":41,"message":"Transaction execution error","data":{"execution_error":"Invalid transaction nonce of contract at address 0x02c7ea72c15d2f118256618c31d390bd6180f9c8716ec290383f59c3d1a38d6f. Account nonce: 0x0000000000000000000000000000000000000000000000000000000000000006; got: 0x0000000000000000000000000000000000000000000000000000000000000005.","transaction_index":0}} - looks like we should ensure fresh nonce is always fetched vs. cached ? (see 5 vs. 6)

https://jam.dev/c/5de23473-eace-49b8-9303-7e677fd7be99

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

Fix all issues with AI Agents 🤖
In @packages/swapper/src/utils.ts:
- Around line 452-457: The code reads receipt.execution_status directly when
computing the status (variable named status) which may be missing or have
unexpected values; update the logic in the function using receipt to first
validate that receipt is an object and receipt.execution_status is a known
string (e.g., 'SUCCEEDED' | 'REVERTED' | 'PENDING'), then map those known values
to TxStatus.Confirmed, TxStatus.Failed, or TxStatus.Pending; for any
missing/unknown value use a safe default (TxStatus.Pending) or handle explicitly
(throw or log) before mapping so accessing receipt.execution_status cannot cause
a runtime error.
- Line 450: Replace the use of the any type for the receipt returned by
provider.getTransactionReceipt(txHash) with a safe type: either declare an
explicit StarknetTransactionReceipt type alias that captures fields you use
(e.g., execution_status and other accessed properties) and annotate receipt with
that type, or annotate it as unknown and add a runtime type guard function
(e.g., isStarknetTransactionReceipt) that narrows unknown to the proper shape
before using receipt; update the variable declaration for receipt and all
subsequent accesses to use the narrowed type via the guard to restore TypeScript
safety.
- Around line 439-468: In checkStarknetSwapStatus, replace the receipt:any with
the proper StarknetReceipt type from the chain adapter (use
assertGetStarknetChainAdapter(...). types/exports) and update the status mapping
to treat receipt.execution_status === 'REJECTED' the same as 'REVERTED' (map
both to TxStatus.Failed); keep using assertGetStarknetChainAdapter,
starknetChainId, provider.getTransactionReceipt, TxStatus and
return/createDefaultStatusResponse unchanged. Optionally, if you want to
populate buy amount, parse receipt.events or receipt.messages_sent for the
swapper contract event signatures, but that’s separate from the required type
and status fixes.
♻️ Duplicate comments (1)
packages/caip/src/adapters/coingecko/index.test.ts (1)

197-202: Fix the Starknet USDC contract address to include the leading zero.

The assetReference is missing a leading zero. It should be 0x033068f6539f8e6e6b131e6b2b814e6c34a5224bc66947c47dab9dfee93b35fb (63 hex characters after 0x), not 0x33068f6539f8e6e6b131e6b2b814e6c34a5224bc66947c47dab9dfee93b35fb (62 hex characters). Starknet addresses require the full 251-bit felt representation for proper address resolution on the network.

🔎 Proposed fix
       const usdcOnStarknet = toAssetId({
         chainNamespace: CHAIN_NAMESPACE.Starknet,
         chainReference: CHAIN_REFERENCE.StarknetMainnet,
         assetNamespace: 'token',
-        assetReference: '0x33068f6539f8e6e6b131e6b2b814e6c34a5224bc66947c47dab9dfee93b35fb',
+        assetReference: '0x033068f6539f8e6e6b131e6b2b814e6c34a5224bc66947c47dab9dfee93b35fb',
       })
🧹 Nitpick comments (1)
.env.development (1)

95-95: Feature flag correctly enabled for development.

The AVNU swap feature is properly activated in the development environment.

Optional: Consider reordering for consistency.

The dotenv-linter suggests placing VITE_FEATURE_AVNU_SWAP before VITE_FEATURE_CETUS_SWAP to maintain alphabetical ordering.

🔎 Proposed reordering
 VITE_FEATURE_WC_DIRECT_CONNECTION=true
+VITE_FEATURE_AVNU_SWAP=true
 VITE_FEATURE_CETUS_SWAP=true
-VITE_FEATURE_AVNU_SWAP=true
 VITE_FEATURE_NEAR=true
📜 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 2853704 and e5c24bd.

⛔ Files ignored due to path filters (13)
  • packages/caip/src/adapters/coincap/generated/eip155_1/adapter.json is excluded by !**/generated/**
  • packages/caip/src/adapters/coincap/generated/eip155_10/adapter.json is excluded by !**/generated/**
  • packages/caip/src/adapters/coincap/generated/eip155_137/adapter.json is excluded by !**/generated/**
  • packages/caip/src/adapters/coincap/generated/eip155_42161/adapter.json is excluded by !**/generated/**
  • packages/caip/src/adapters/coincap/generated/eip155_43114/adapter.json is excluded by !**/generated/**
  • packages/caip/src/adapters/coincap/generated/eip155_56/adapter.json is excluded by !**/generated/**
  • packages/caip/src/adapters/coincap/generated/eip155_8453/adapter.json is excluded by !**/generated/**
  • packages/caip/src/adapters/coincap/generated/solana_5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/adapter.json is excluded by !**/generated/**
  • packages/caip/src/adapters/coingecko/generated/eip155_1/adapter.json is excluded by !**/generated/**
  • packages/caip/src/adapters/coingecko/generated/eip155_56/adapter.json is excluded by !**/generated/**
  • packages/caip/src/adapters/coingecko/generated/eip155_8453/adapter.json is excluded by !**/generated/**
  • packages/caip/src/adapters/coingecko/generated/solana_5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/adapter.json is excluded by !**/generated/**
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (15)
  • .env.development
  • headers/csps/index.ts
  • packages/caip/src/adapters/coingecko/index.test.ts
  • packages/caip/src/adapters/coingecko/utils.test.ts
  • packages/caip/src/adapters/coingecko/utils.ts
  • packages/swapper/package.json
  • packages/swapper/src/swappers/NearIntentsSwapper/endpoints.ts
  • packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts
  • packages/swapper/src/types.ts
  • packages/swapper/src/utils.ts
  • packages/utils/src/index.ts
  • src/components/Modals/Send/utils.ts
  • src/config.ts
  • src/state/slices/preferencesSlice/preferencesSlice.ts
  • src/test/mocks/store.ts
🚧 Files skipped from review as they are similar to previous changes (8)
  • packages/swapper/src/types.ts
  • packages/swapper/src/swappers/NearIntentsSwapper/endpoints.ts
  • packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts
  • headers/csps/index.ts
  • src/state/slices/preferencesSlice/preferencesSlice.ts
  • packages/swapper/package.json
  • packages/caip/src/adapters/coingecko/utils.ts
  • src/config.ts
🧰 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/utils/src/index.ts
  • src/components/Modals/Send/utils.ts
  • packages/swapper/src/utils.ts
  • packages/caip/src/adapters/coingecko/index.test.ts
  • src/test/mocks/store.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/utils/src/index.ts
  • src/components/Modals/Send/utils.ts
  • packages/swapper/src/utils.ts
  • packages/caip/src/adapters/coingecko/index.test.ts
  • src/test/mocks/store.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
  • packages/caip/src/adapters/coingecko/index.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/utils/src/index.ts
  • src/components/Modals/Send/utils.ts
  • packages/swapper/src/utils.ts
  • packages/caip/src/adapters/coingecko/index.test.ts
  • src/test/mocks/store.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/utils.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/utils.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
🧠 Learnings (44)
📓 Common learnings
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11016
File: packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts:109-145
Timestamp: 2025-11-12T12:18:00.863Z
Learning: NEAR Intents swapper: The NEAR 1Click API does not provide gas limit estimation logic like other swappers (e.g., magic gasLimit fields). For ERC20 token swaps in getTradeQuote, accurate fee estimation requires token approval and sufficient balance; without these prerequisites, fees may display as 0 or use inaccurate native transfer estimates. This is a known limitation of the NEAR Intents integration.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10323
File: src/pages/RFOX/components/Stake/components/StakeSummary.tsx:112-114
Timestamp: 2025-08-22T13:00:44.879Z
Learning: NeOMakinG prefers to keep PR changes minimal and focused on the core objectives, avoiding cosmetic or defensive code improvements that aren't directly related to the PR scope, even when they would improve robustness.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10128
File: .cursor/rules/error-handling.mdc:266-274
Timestamp: 2025-07-29T10:35:22.059Z
Learning: NeOMakinG prefers less nitpicky suggestions on documentation and best practices files, finding overly detailed suggestions on minor implementation details (like console.error vs logger.error) too granular for cursor rules documentation.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10380
File: src/pages/Dashboard/components/AccountList/AccountTable.tsx:60-0
Timestamp: 2025-09-02T08:34:08.157Z
Learning: NeOMakinG prefers code review comments to focus only on actual PR changes, not pre-existing code issues, unless there are critical security or correctness concerns directly related to the new functionality.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10234
File: src/components/MultiHopTrade/hooks/useGetTradeQuotes/hooks/useTrackTradeQuotes.ts:42-86
Timestamp: 2025-08-08T11:41:22.794Z
Learning: NeOMakinG prefers not to include refactors in move-only PRs; such suggestions should be deferred to follow-up issues instead of being applied within the same PR.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10380
File: src/components/Table/Table.theme.ts:177-180
Timestamp: 2025-09-02T12:38:46.940Z
Learning: NeOMakinG prefers to defer technical debt and CSS correctness issues (like improper hover selectors) to follow-up PRs when the current PR is already large and focused on major feature implementation, even when the issues are valid from a usability/technical perspective.
📚 Learning: 2026-01-03T15:12:53.276Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11537
File: packages/caip/src/adapters/coincap/generate.ts:7-7
Timestamp: 2026-01-03T15:12:53.276Z
Learning: In shapeshift/web, when running scripts in the packages/caip area via yarn workspace shapeshiftoss/caip generate, the working directory is packages/caip. Use ../../.env to reach the monorepo root .env file instead of .env. Also note that the -T flag only controls which node_modules are used (root's), not the current working directory. Apply these guidelines to all TypeScript files under packages/caip (i.e., packages/caip/**/*.ts) where environment loading or path resolution could be affected.

Applied to files:

  • packages/caip/src/adapters/coingecko/utils.test.ts
  • packages/caip/src/adapters/coingecko/index.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/index.ts : Export unique functions and types from packages/swapper/src/index.ts only if needed for external consumption

Applied to files:

  • packages/utils/src/index.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/utils/src/index.ts
  • packages/swapper/src/utils.ts
  • packages/caip/src/adapters/coingecko/index.test.ts
📚 Learning: 2025-11-24T21:20:30.085Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/naming-conventions.mdc:0-0
Timestamp: 2025-11-24T21:20:30.085Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use named exports for components, functions, and utilities instead of default exports

Applied to files:

  • packages/utils/src/index.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/utils/src/index.ts
  • packages/swapper/src/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/utils/src/index.ts
  • packages/caip/src/adapters/coingecko/index.test.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/utils/src/index.ts
  • packages/swapper/src/utils.ts
📚 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/utils/src/index.ts
📚 Learning: 2025-08-05T22:41:35.473Z
Learnt from: premiumjibles
Repo: shapeshift/web PR: 10187
File: src/pages/Assets/Asset.tsx:1-1
Timestamp: 2025-08-05T22:41:35.473Z
Learning: In the shapeshift/web codebase, component imports use direct file paths like '@/components/ComponentName/ComponentName' rather than barrel exports. The AssetAccountDetails component should be imported as '@/components/AssetAccountDetails/AssetAccountDetails', not from a directory index.

Applied to files:

  • packages/utils/src/index.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:

  • packages/utils/src/index.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/utils/src/index.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/utils/src/index.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/utils/src/index.ts
📚 Learning: 2025-10-21T17:11:18.087Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10871
File: src/components/Modals/Send/hooks/useSendDetails/useSendDetails.tsx:426-428
Timestamp: 2025-10-21T17:11:18.087Z
Learning: In src/components/Modals/Send/hooks/useSendDetails/useSendDetails.tsx, within the handleInputChange function, use .toFixed() without arguments (not .toString()) when converting BigNumber amounts for input field synchronization. This avoids exponential notation in the input while preserving precision for presentational components like <Amount.Crypto /> and <Amount.Fiat /> to format appropriately.

Applied to files:

  • src/components/Modals/Send/utils.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:

  • src/components/Modals/Send/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/*/endpoints.ts : Reuse checkEvmSwapStatus utility for checking EVM swap status instead of implementing custom status checks

Applied to files:

  • packages/swapper/src/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 : Reuse executeEvmTransaction utility for EVM-based swappers instead of implementing custom transaction execution

Applied to files:

  • packages/swapper/src/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 : Avoid side effects in swap logic; ensure swap methods are deterministic and stateless

Applied to files:

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

Applied to files:

  • packages/swapper/src/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 : Validate inputs and log errors for debugging in Swapper system implementations

Applied to files:

  • packages/swapper/src/utils.ts
📚 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 **/swapper{s,}/**/*.{ts,tsx} : ALWAYS use `makeSwapErrorRight` for swapper errors with `TradeQuoteError` enum for error codes and provide detailed error information

Applied to files:

  • packages/swapper/src/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/swapper/src/utils.ts
  • packages/caip/src/adapters/coingecko/index.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 filterAssetIdsBySellable method to filter assets by supported chain IDs in the sell property

Applied to files:

  • packages/swapper/src/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/swapper/src/utils.ts
  • packages/caip/src/adapters/coingecko/index.test.ts
📚 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/src/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/swapper/src/utils.ts
📚 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:

  • packages/swapper/src/utils.ts
📚 Learning: 2025-08-04T15:36:25.122Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10171
File: src/components/MultiHopTrade/components/TradeConfirm/components/ExpandedStepperSteps.tsx:458-458
Timestamp: 2025-08-04T15:36:25.122Z
Learning: In swap transaction handling, buy transaction hashes should always use the swapper's explorer (stepSource) because they are known by the swapper immediately upon swap execution. The conditional logic for using default explorers applies primarily to sell transactions which need to be detected/indexed by external systems like Thorchain or ViewBlock.

Applied to files:

  • packages/swapper/src/utils.ts
📚 Learning: 2025-08-14T17:54:32.563Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10276
File: src/pages/ThorChainLP/components/ReusableLpStatus/ReusableLpStatus.tsx:97-108
Timestamp: 2025-08-14T17:54:32.563Z
Learning: In ReusableLpStatus component (src/pages/ThorChainLP/components/ReusableLpStatus/ReusableLpStatus.tsx), the txAssets dependency is stable from first render because poolAsset, baseAsset, actionSide, and action are all defined first render, making the current txAssetsStatuses initialization pattern safe without needing useEffect synchronization.

Applied to files:

  • packages/swapper/src/utils.ts
📚 Learning: 2025-08-04T16:02:27.360Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10171
File: src/components/MultiHopTrade/components/TradeConfirm/components/ExpandedStepperSteps.tsx:458-458
Timestamp: 2025-08-04T16:02:27.360Z
Learning: In multi-hop swap transactions, last hop sell transactions might not be detected by the swapper (unlike buy transactions which are always known immediately). The conditional stepSource logic for last hop buy transactions (`isLastHopSellTxSeen ? stepSource : undefined`) serves as defensive programming for future multi-hop support with intermediate chains, even though multi-hop functionality is not currently supported in production.

Applied to files:

  • packages/swapper/src/utils.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/index.test.ts
📚 Learning: 2025-12-12T16:20:33.904Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11377
File: src/lib/referral/api.ts:30-57
Timestamp: 2025-12-12T16:20:33.904Z
Learning: In shapeshift/web referral feature, the backend expects an EVM address (0x… viem Address) as the owner identifier, not a CAIP AccountId. Update useReferral to derive the first connected EVM address via fromAccountId + getAddress, and do not URL-encode it in the API path.

Applied to files:

  • packages/caip/src/adapters/coingecko/index.test.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/index.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: 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:

  • src/test/mocks/store.ts
  • .env.development
📚 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 **/*.test.{ts,tsx,js,jsx} : Mock external dependencies appropriately

Applied to files:

  • src/test/mocks/store.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: Feature flags are stored in Redux state under `preferences.featureFlags`

Applied to files:

  • src/test/mocks/store.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:

  • src/test/mocks/store.ts
📚 Learning: 2025-11-12T12:18:00.863Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11016
File: packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts:109-145
Timestamp: 2025-11-12T12:18:00.863Z
Learning: NEAR Intents swapper: The NEAR 1Click API does not provide gas limit estimation logic like other swappers (e.g., magic gasLimit fields). For ERC20 token swaps in getTradeQuote, accurate fee estimation requires token approval and sufficient balance; without these prerequisites, fees may display as 0 or use inaccurate native transfer estimates. This is a known limitation of the NEAR Intents integration.

Applied to files:

  • src/test/mocks/store.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
📚 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-16T13:17:02.938Z
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.

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: 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
🧬 Code graph analysis (2)
src/components/Modals/Send/utils.ts (2)
packages/chain-adapters/src/types.ts (1)
  • GetFeeDataInput (353-360)
packages/chain-adapters/src/starknet/types.ts (1)
  • GetFeeDataInput (21-24)
packages/swapper/src/utils.ts (3)
packages/swapper/src/types.ts (1)
  • TradeStatus (701-708)
src/lib/utils/starknet.ts (1)
  • assertGetStarknetChainAdapter (16-27)
packages/caip/src/constants.ts (1)
  • starknetChainId (91-91)
🪛 dotenv-linter (4.0.0)
.env.development

[warning] 95-95: [UnorderedKey] The VITE_FEATURE_AVNU_SWAP key should go before the VITE_FEATURE_CETUS_SWAP 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: Install and Cache
🔇 Additional comments (6)
src/test/mocks/store.ts (1)

175-175: LGTM!

The AvnuSwap feature flag is correctly added to the mock store, following the established pattern and alphabetical ordering.

packages/caip/src/adapters/coingecko/utils.test.ts (1)

196-198: LGTM! Test coverage extended for Starknet native asset.

The Starknet mainnet mapping follows the same pattern as other chain native assets in the test suite.

src/components/Modals/Send/utils.ts (1)

175-184: LGTM! Proper fee estimation input for Starknet.

The implementation correctly constructs GetFeeDataInput for Starknet fee estimation, aligning with the pattern used for other chains (EVM, Solana, Near, etc.). All required fields (to, value, from) and optional fields (tokenContractAddress, sendMax) are properly mapped from function parameters.

packages/utils/src/index.ts (2)

36-36: LGTM! Starknet token namespace support added correctly.

The addition of ASSET_NAMESPACE.starknetToken to the isToken function is correct and follows the established pattern for recognizing token namespaces. This change directly supports the PR objective of enabling Starknet token swaps.


6-23: All new exports are actively used throughout the codebase and necessary for external consumption. The utilities include commonly-used helpers (bn, bnOrZero, makeAsset, isToken, etc.) that are imported across packages/swapper, scripts, state management, and UI components. No action required.

packages/swapper/src/utils.ts (1)

2-10: LGTM!

The import additions appropriately mirror the existing pattern for other chains (Sui, Solana) and provide the necessary types for Starknet swap status checking.

@NeOMakinG
Copy link
Collaborator Author

✅ Fixed - added leading zero to make it 0x033068f6539f8e6e6b131e6b2b814e6c34a5224bc66947c47dab9dfee93b35fb

See: packages/caip/src/adapters/coingecko/index.test.ts:201

- Fix Starknet USDC contract address with leading zero for proper felt representation
- Move TokenInfo type to ./types for better code organization
- Add getNonce() method with deployment status check to prevent nonce errors
- Add missing _txDetails fields required for v3 transaction hash computation
- Update AVNU swapper to use new getNonce method from chain adapter

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

Co-Authored-By: Claude <noreply@anthropic.com>
@NeOMakinG NeOMakinG enabled auto-merge (squash) January 5, 2026 20:06
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 @packages/chain-adapters/src/starknet/StarknetChainAdapter.ts:
- Around line 1059-1062: The nonce fetch currently ignores RPC errors by
defaulting to '0x0'; update the fetch logic in the StarknetChainAdapter where
provider.fetch('starknet_getNonce', ['pending', from]) is called so it mirrors
the fee estimate error handling: after awaiting nonceResponse.json(), check if
nonceResult.error and throw a descriptive Error (e.g., `Failed to fetch nonce:
${nonceResult.error.message}`) before deriving `const nonce = nonceResult.result
|| '0x0'`; apply the same pattern used in the fee estimate/
buildSignAndBroadcastTransaction code paths to ensure consistent RPC error
handling.
- Around line 1123-1146: The current hardcoded tier multipliers in
StarknetChainAdapter.ts (variables slowMaxFee / averageMaxFee / fastMaxFee)
should be replaced with Starknet's fee estimation flow: call the
starknet_estimateFee RPC (or SDK estimateFee helper) to obtain suggestedMaxFee
and resource_bounds, then apply configurable margins (e.g., feeMarginPercentage
and resourceBoundsOverhead) to that suggestedMaxFee to derive tiered fees
instead of using fixed 1.8x/4.5x/10x multipliers; for priority tiers adjust
resource_bounds (max_amount / max_price_per_unit) or a small adjustable fee
margin per tier rather than inflating both amount and price by arbitrary
factors, and remove the BigInt multiplier math in calculateTxFee (or wherever
slowMaxFee/averageMaxFee/fastMaxFee are computed) so the adapter uses the
SDK/RPC estimated fee plus configurable overhead.
📜 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 e5c24bd and a5538a1.

📒 Files selected for processing (4)
  • packages/caip/src/adapters/coingecko/index.test.ts
  • packages/chain-adapters/src/starknet/StarknetChainAdapter.ts
  • packages/chain-adapters/src/starknet/types.ts
  • packages/swapper/src/swappers/AvnuSwapper/endpoints.ts
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{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/starknet/StarknetChainAdapter.ts
  • packages/chain-adapters/src/starknet/types.ts
  • packages/swapper/src/swappers/AvnuSwapper/endpoints.ts
  • packages/caip/src/adapters/coingecko/index.test.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/starknet/StarknetChainAdapter.ts
  • packages/chain-adapters/src/starknet/types.ts
  • packages/swapper/src/swappers/AvnuSwapper/endpoints.ts
  • packages/caip/src/adapters/coingecko/index.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/chain-adapters/src/starknet/StarknetChainAdapter.ts
  • packages/chain-adapters/src/starknet/types.ts
  • packages/swapper/src/swappers/AvnuSwapper/endpoints.ts
  • packages/caip/src/adapters/coingecko/index.test.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/AvnuSwapper/endpoints.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/AvnuSwapper/endpoints.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/AvnuSwapper/endpoints.ts
packages/swapper/src/swappers/*/*.ts

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

packages/swapper/src/swappers/*/*.ts: All swappers must implement the Swapper interface from packages/swapper/src/types.ts
Implement filterAssetIdsBySellable method to filter assets by supported chain IDs in the sell property
Implement filterBuyAssetsBySellAssetId method to filter assets by supported chain IDs in the buy property
Reuse executeEvmTransaction utility for EVM-based swappers instead of implementing custom transaction execution

Files:

  • packages/swapper/src/swappers/AvnuSwapper/endpoints.ts
packages/swapper/src/swappers/*/endpoints.ts

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

packages/swapper/src/swappers/*/endpoints.ts: All swapper API implementations must implement the SwapperApi interface from packages/swapper/src/types.ts
Reuse checkEvmSwapStatus utility for checking EVM swap status instead of implementing custom status checks

Files:

  • packages/swapper/src/swappers/AvnuSwapper/endpoints.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/index.test.ts
🧠 Learnings (50)
📓 Common learnings
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: 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: 11016
File: packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts:109-145
Timestamp: 2025-11-12T12:18:00.863Z
Learning: NEAR Intents swapper: The NEAR 1Click API does not provide gas limit estimation logic like other swappers (e.g., magic gasLimit fields). For ERC20 token swaps in getTradeQuote, accurate fee estimation requires token approval and sufficient balance; without these prerequisites, fees may display as 0 or use inaccurate native transfer estimates. This is a known limitation of the NEAR Intents integration.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10323
File: src/pages/RFOX/components/Stake/components/StakeSummary.tsx:112-114
Timestamp: 2025-08-22T13:00:44.879Z
Learning: NeOMakinG prefers to keep PR changes minimal and focused on the core objectives, avoiding cosmetic or defensive code improvements that aren't directly related to the PR scope, even when they would improve robustness.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10128
File: .cursor/rules/error-handling.mdc:266-274
Timestamp: 2025-07-29T10:35:22.059Z
Learning: NeOMakinG prefers less nitpicky suggestions on documentation and best practices files, finding overly detailed suggestions on minor implementation details (like console.error vs logger.error) too granular for cursor rules documentation.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10380
File: src/pages/Dashboard/components/AccountList/AccountTable.tsx:60-0
Timestamp: 2025-09-02T08:34:08.157Z
Learning: NeOMakinG prefers code review comments to focus only on actual PR changes, not pre-existing code issues, unless there are critical security or correctness concerns directly related to the new functionality.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10234
File: src/components/MultiHopTrade/hooks/useGetTradeQuotes/hooks/useTrackTradeQuotes.ts:42-86
Timestamp: 2025-08-08T11:41:22.794Z
Learning: NeOMakinG prefers not to include refactors in move-only PRs; such suggestions should be deferred to follow-up issues instead of being applied within the same PR.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10380
File: src/components/Table/Table.theme.ts:177-180
Timestamp: 2025-09-02T12:38:46.940Z
Learning: NeOMakinG prefers to defer technical debt and CSS correctness issues (like improper hover selectors) to follow-up PRs when the current PR is already large and focused on major feature implementation, even when the issues are valid from a usability/technical perspective.
📚 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/chain-adapters/src/starknet/StarknetChainAdapter.ts
  • packages/chain-adapters/src/starknet/types.ts
  • packages/swapper/src/swappers/AvnuSwapper/endpoints.ts
📚 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:

  • packages/chain-adapters/src/starknet/StarknetChainAdapter.ts
  • packages/chain-adapters/src/starknet/types.ts
  • packages/swapper/src/swappers/AvnuSwapper/endpoints.ts
📚 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:

  • packages/chain-adapters/src/starknet/StarknetChainAdapter.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} : Prefer `type` over `interface` for type definitions

Applied to files:

  • packages/chain-adapters/src/starknet/StarknetChainAdapter.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 utility types for common transformations in TypeScript

Applied to files:

  • packages/chain-adapters/src/starknet/StarknetChainAdapter.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 descriptive property names in TypeScript type definitions

Applied to files:

  • packages/chain-adapters/src/starknet/StarknetChainAdapter.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 explicit types for object shapes using interfaces or type aliases in TypeScript

Applied to files:

  • packages/chain-adapters/src/starknet/StarknetChainAdapter.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 `as` instead of angle bracket syntax for type assertions in TypeScript

Applied to files:

  • packages/chain-adapters/src/starknet/StarknetChainAdapter.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,js,jsx} : Prefer procedural and easy to understand code

Applied to files:

  • packages/chain-adapters/src/starknet/StarknetChainAdapter.ts
📚 Learning: 2025-11-24T21:20:30.085Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/naming-conventions.mdc:0-0
Timestamp: 2025-11-24T21:20:30.085Z
Learning: Applies to **/*.{ts,tsx} : Use suffixes like `Props`, `State`, `Config`, `Type` for interfaces and types when appropriate

Applied to files:

  • packages/chain-adapters/src/starknet/StarknetChainAdapter.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} : Avoid 'any' types - use specific type annotations instead

Applied to files:

  • packages/chain-adapters/src/starknet/StarknetChainAdapter.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} : Use strict typing - avoid `any`

Applied to files:

  • packages/chain-adapters/src/starknet/StarknetChainAdapter.ts
📚 Learning: 2025-11-24T21:20:30.085Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/naming-conventions.mdc:0-0
Timestamp: 2025-11-24T21:20:30.085Z
Learning: Applies to **/*.{ts,tsx} : Use PascalCase for types, interfaces, and enums with descriptive names

Applied to files:

  • packages/chain-adapters/src/starknet/StarknetChainAdapter.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/chain-adapters/src/starknet/StarknetChainAdapter.ts
  • packages/chain-adapters/src/starknet/types.ts
  • packages/caip/src/adapters/coingecko/index.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/*/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/chain-adapters/src/starknet/StarknetChainAdapter.ts
  • packages/chain-adapters/src/starknet/types.ts
  • packages/caip/src/adapters/coingecko/index.test.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:

  • packages/chain-adapters/src/starknet/StarknetChainAdapter.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 : All swapper API implementations must implement the SwapperApi interface from packages/swapper/src/types.ts

Applied to files:

  • packages/swapper/src/swappers/AvnuSwapper/endpoints.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/AvnuSwapper/endpoints.ts
📚 Learning: 2025-12-09T21:06:15.748Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11335
File: packages/swapper/src/swappers/CetusSwapper/endpoints.ts:66-68
Timestamp: 2025-12-09T21:06:15.748Z
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/swapper/src/swappers/AvnuSwapper/endpoints.ts
📚 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 **/swapper{s,}/**/*.{ts,tsx} : ALWAYS use `makeSwapErrorRight` for swapper errors with `TradeQuoteError` enum for error codes and provide detailed error information

Applied to files:

  • packages/swapper/src/swappers/AvnuSwapper/endpoints.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/swapper/src/swappers/AvnuSwapper/endpoints.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/AvnuSwapper/endpoints.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/AvnuSwapper/endpoints.ts
📚 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:

  • packages/swapper/src/swappers/AvnuSwapper/endpoints.ts
📚 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/src/swappers/AvnuSwapper/endpoints.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/constants.ts : Register new swappers in packages/swapper/src/constants.ts with an entry in the swappers registry mapping SwapperName enum to swapper implementation

Applied to files:

  • packages/swapper/src/swappers/AvnuSwapper/endpoints.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:

  • packages/swapper/src/swappers/AvnuSwapper/endpoints.ts
📚 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:

  • packages/swapper/src/swappers/AvnuSwapper/endpoints.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/AvnuSwapper/endpoints.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 : Validate inputs and log errors for debugging in Swapper system implementations

Applied to files:

  • packages/swapper/src/swappers/AvnuSwapper/endpoints.ts
📚 Learning: 2025-08-22T12:58:26.590Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10323
File: src/components/Layout/Header/ActionCenter/components/GenericTransactionActionCard.tsx:108-111
Timestamp: 2025-08-22T12:58:26.590Z
Learning: In the RFOX GenericTransactionDisplayType flow in src/components/Layout/Header/ActionCenter/components/GenericTransactionActionCard.tsx, the txHash is always guaranteed to be present according to NeOMakinG, so defensive null checks for txLink are not needed in this context.

Applied to files:

  • packages/swapper/src/swappers/AvnuSwapper/endpoints.ts
📚 Learning: 2025-09-12T12:04:59.556Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/WalletConnectSigningModal/content/SendTransactionContent.tsx:0-0
Timestamp: 2025-09-12T12:04:59.556Z
Learning: The ShapeShift codebase's fromBaseUnit function correctly handles hex strings (like WalletConnect transaction.value) without manual conversion because bnOrZero -> bn -> new BigNumber() automatically detects and parses hex strings starting with "0x". gomesalexandre confirmed this with concrete evidence showing hex value 0x176d1c49189db correctly converts to 0.000412118294825435 ETH.

Applied to files:

  • packages/swapper/src/swappers/AvnuSwapper/endpoints.ts
  • packages/caip/src/adapters/coingecko/index.test.ts
📚 Learning: 2025-09-12T12:04:59.556Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/WalletConnectSigningModal/content/SendTransactionContent.tsx:0-0
Timestamp: 2025-09-12T12:04:59.556Z
Learning: gomesalexandre confirmed that fromBaseUnit in the ShapeShift codebase correctly handles hex strings (like transaction.value from WalletConnect) without requiring manual hex-to-decimal conversion, as bnOrZero handles this automatically via BigNumber.js.

Applied to files:

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

Applied to files:

  • packages/swapper/src/swappers/AvnuSwapper/endpoints.ts
📚 Learning: 2025-10-21T17:11:18.087Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10871
File: src/components/Modals/Send/hooks/useSendDetails/useSendDetails.tsx:426-428
Timestamp: 2025-10-21T17:11:18.087Z
Learning: In src/components/Modals/Send/hooks/useSendDetails/useSendDetails.tsx, within the handleInputChange function, use .toFixed() without arguments (not .toString()) when converting BigNumber amounts for input field synchronization. This avoids exponential notation in the input while preserving precision for presentational components like <Amount.Crypto /> and <Amount.Fiat /> to format appropriately.

Applied to files:

  • packages/swapper/src/swappers/AvnuSwapper/endpoints.ts
📚 Learning: 2025-08-05T16:39:58.598Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10191
File: src/pages/Explore/Explore.tsx:56-56
Timestamp: 2025-08-05T16:39:58.598Z
Learning: In the ShapeShift web codebase, the established pattern for handling floating point numbers is to use BigNumber operations (bnOrZero, bn) for calculations and convert to strings using .toString() before passing to UI components like Amount.Fiat, Amount.Crypto, and Amount.Percent. This prevents JavaScript floating point precision issues and maintains consistency across the application.

Applied to files:

  • packages/swapper/src/swappers/AvnuSwapper/endpoints.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/swapper/src/swappers/AvnuSwapper/endpoints.ts
📚 Learning: 2025-08-05T17:00:30.416Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10191
File: src/pages/Explore/components/AssetSearchRow.tsx:78-78
Timestamp: 2025-08-05T17:00:30.416Z
Learning: In BigNumber operations within the ShapeShift codebase, floating point literals like 0.01 should always be passed as strings like '0.01' to maintain precision. This applies to all BigNumber methods including .times(), .div(), .plus(), and .minus().

Applied to files:

  • packages/swapper/src/swappers/AvnuSwapper/endpoints.ts
📚 Learning: 2025-09-11T22:53:19.837Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/EIP155TransactionConfirmation.tsx:27-31
Timestamp: 2025-09-11T22:53:19.837Z
Learning: gomesalexandre trusts Tenderly's data quality and doesn't want defensive validation for gas values (transaction?.gasLimit ?? transaction?.gas) in WalletConnect flows, preferring to rely on the external service providing valid hex values.

Applied to files:

  • packages/swapper/src/swappers/AvnuSwapper/endpoints.ts
📚 Learning: 2025-09-12T13:43:19.770Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/utils/EIP155RequestHandlerUtil.ts:94-103
Timestamp: 2025-09-12T13:43:19.770Z
Learning: gomesalexandre has implemented a reliable gasLimit flow in WalletConnect dApps where Tenderly simulation provides gas estimates that get written to the form via setValue in GasSelectionMenu.tsx, making customTransactionData.gasLimit the primary reliable source. The sendTransaction.gasLimit fallback is kept as "paranoia" but may rarely be hit in practice due to this simulation-based architecture.

Applied to files:

  • packages/swapper/src/swappers/AvnuSwapper/endpoints.ts
📚 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 **/*.{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

Applied to files:

  • packages/swapper/src/swappers/AvnuSwapper/endpoints.ts
📚 Learning: 2025-11-18T09:52:51.368Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10334
File: src/lib/user/api.ts:46-105
Timestamp: 2025-11-18T09:52:51.368Z
Learning: In the shapeshift/web repository, monadic error-handling with Result types (Ok/Err from sniptt/monads) is specific to the swapper domain and is not used anywhere else in the codebase. API helpers outside the swapper domain (e.g., user API, notification services) should use traditional throw/catch error handling patterns instead of Result monads.

Applied to files:

  • packages/swapper/src/swappers/AvnuSwapper/endpoints.ts
📚 Learning: 2025-12-22T23:36:06.927Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11513
File: src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeQuotes.tsx:293-308
Timestamp: 2025-12-22T23:36:06.927Z
Learning: In the swapper types (TradeQuote/TradeRate), the `steps` property is defined as a tuple type that guarantees at least one element: `steps: [TradeQuoteStep] | [TradeQuoteStep, TradeQuoteStep] | [TradeRateStep] | [TradeRateStep, TradeRateStep]`. Therefore, runtime guards checking for empty arrays when accessing steps elements are unnecessary - TypeScript's type system already prevents this scenario.

Applied to files:

  • packages/swapper/src/swappers/AvnuSwapper/endpoints.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/index.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/index.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 filterAssetIdsBySellable method to filter assets by supported chain IDs in the sell property

Applied to files:

  • packages/caip/src/adapters/coingecko/index.test.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/index.test.ts
📚 Learning: 2025-12-12T16:20:33.904Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11377
File: src/lib/referral/api.ts:30-57
Timestamp: 2025-12-12T16:20:33.904Z
Learning: In shapeshift/web referral feature, the backend expects an EVM address (0x… viem Address) as the owner identifier, not a CAIP AccountId. Update useReferral to derive the first connected EVM address via fromAccountId + getAddress, and do not URL-encode it in the API path.

Applied to files:

  • packages/caip/src/adapters/coingecko/index.test.ts
📚 Learning: 2026-01-03T15:12:53.276Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11537
File: packages/caip/src/adapters/coincap/generate.ts:7-7
Timestamp: 2026-01-03T15:12:53.276Z
Learning: In shapeshift/web, when running scripts in the packages/caip area via yarn workspace shapeshiftoss/caip generate, the working directory is packages/caip. Use ../../.env to reach the monorepo root .env file instead of .env. Also note that the -T flag only controls which node_modules are used (root's), not the current working directory. Apply these guidelines to all TypeScript files under packages/caip (i.e., packages/caip/**/*.ts) where environment loading or path resolution could be affected.

Applied to files:

  • packages/caip/src/adapters/coingecko/index.test.ts
🧬 Code graph analysis (4)
packages/chain-adapters/src/starknet/StarknetChainAdapter.ts (2)
packages/chain-adapters/src/starknet/types.ts (4)
  • TokenInfo (16-22)
  • RpcJsonResponse (39-45)
  • StarknetNonceResult (47-47)
  • GetFeeDataInput (29-32)
packages/caip/src/assetId/assetId.ts (1)
  • AssetId (17-17)
packages/chain-adapters/src/starknet/types.ts (1)
packages/caip/src/assetId/assetId.ts (1)
  • AssetId (17-17)
packages/swapper/src/swappers/AvnuSwapper/endpoints.ts (4)
packages/swapper/src/types.ts (2)
  • SwapperApi (760-791)
  • TradeStatus (701-708)
packages/swapper/src/utils.ts (4)
  • isExecutableTradeQuote (331-332)
  • getExecutableTradeStep (337-347)
  • createDefaultStatusResponse (220-224)
  • checkStarknetSwapStatus (439-468)
src/lib/utils/starknet.ts (1)
  • assertGetStarknetChainAdapter (16-27)
packages/chain-adapters/src/utils/bip44.ts (1)
  • toAddressNList (42-44)
packages/caip/src/adapters/coingecko/index.test.ts (2)
packages/caip/src/assetId/assetId.ts (1)
  • toAssetId (59-127)
packages/caip/src/constants.ts (2)
  • CHAIN_NAMESPACE (93-102)
  • CHAIN_REFERENCE (108-135)
⏰ 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 (10)
packages/swapper/src/swappers/AvnuSwapper/endpoints.ts (3)

1-19: LGTM! Clean API structure and imports.

The avnuApi implementation correctly follows the SwapperApi interface pattern with proper imports from AVNU SDK, chain adapters, and internal swapper utilities.


21-205: Excellent implementation of Starknet transaction preparation!

The getUnsignedStarknetTransaction method is well-structured with:

  • Proper input validation and error handling
  • Correct AVNU SDK integration with slippage conversion
  • Complete Starknet v3 transaction format with all required fields
  • Appropriate fee estimation with 5x gas amount and 2x gas price buffers
  • All past review concerns addressed (adapter.getNonce() usage, complete _txDetails fields)

The resource bounds are correctly stored as BigInt for hash calculation and will be converted to hex during broadcast by the chain adapter.


207-227: LGTM! Fee and status methods follow established patterns.

Both getStarknetTransactionFees and checkTradeStatus are correctly implemented:

  • Fee extraction validates the quote and provides meaningful error messages
  • Status checking follows the standard pattern with appropriate fallback behavior
  • Proper delegation to shared utility functions
packages/caip/src/adapters/coingecko/index.test.ts (1)

197-202: LGTM!

The Starknet USDC asset integration is correct. The address now includes the proper leading zero (0x033...) as noted in the previous review, ensuring the full 63-hex-character felt representation required for Starknet mainnet.

Also applies to: 219-219

packages/chain-adapters/src/starknet/types.ts (2)

16-22: LGTM!

The TokenInfo type is well-structured with explicit types for all fields, using the AssetId nominal type from @shapeshiftoss/caip and descriptive property names as per coding guidelines.


77-81: LGTM!

The StarknetTxDetails extensions correctly implement Starknet v3 transaction fields. The literal union types (0 | 1) for data availability modes are appropriate (L1=0, L2=1), and all fields follow explicit typing conventions.

packages/chain-adapters/src/starknet/StarknetChainAdapter.ts (4)

8-8: LGTM!

The infrastructure setup for batched balance queries is well-designed. The dual RpcProvider approach (one for single calls, one for automatic batching) with clear explanatory comments, along with PQueue rate limiting (1 batch per 100ms), demonstrates thoughtful handling of RPC endpoint constraints. The getKnownTokens default fallback avoids race conditions with asset service initialization.

Also applies to: 40-40, 46-46, 67-89


157-266: LGTM!

The getAccount refactor with batched balance queries is well-implemented. The batch size of 50, queue-based rate limiting, and automatic RPC batching via batchedProvider (batch: 0) provide good balance between performance and reliability. Error handling returns zero balances for failed calls (defensive), and the final filter removes malformed tokens. The logic correctly separates native STRK balance from token balances.


305-319: LGTM!

The nonce handling and deployment checks in the transaction building flow are correct. The getNonce method safely returns '0x0' for undeployed accounts, and buildSendApiTransaction (line 542-549) properly validates account deployment before any fee estimation or nonce fetching, providing a clear error message for undeployed accounts.

Also applies to: 542-549, 601-604, 681-693


827-831: LGTM!

The extended transaction details fields (nonceDataAvailabilityMode, feeDataAvailabilityMode, tip, paymasterData, accountDeploymentData) correctly align with the StarknetTxDetails type extensions and Starknet v3 transaction specification. Values are set appropriately (L1 DA modes = 0, tip = '0x0', empty arrays for optional fields).

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 (2)
packages/swapper/src/swappers/AvnuSwapper/swapperApi/getTradeQuote.ts (2)

48-73: Consider removing redundant validation checks for required fields.

The validation checks for accountNumber (line 48) and receiveAddress (line 66) are redundant since these are required (non-optional) fields in CommonTradeQuoteInput. TypeScript's type system already guarantees these values are defined.

The sendAddress check (line 57) is valid since it's an optional field in the input type.

🔎 Proposed refactor to remove redundant checks
-  if (accountNumber === undefined) {
-    return Err(
-      makeSwapErrorRight({
-        message: `accountNumber is required`,
-        code: TradeQuoteError.UnknownError,
-      }),
-    )
-  }
-
   if (sendAddress === undefined) {
     return Err(
       makeSwapErrorRight({
         message: `sendAddress is required`,
         code: TradeQuoteError.UnknownError,
       }),
     )
   }
-
-  if (receiveAddress === undefined) {
-    return Err(
-      makeSwapErrorRight({
-        message: `receiveAddress is required`,
-        code: TradeQuoteError.UnknownError,
-      }),
-    )
-  }

100-107: Remove redundant bestQuote validation.

The check if (!bestQuote) at line 100 is redundant because if quotes.length > 0 (validated at line 89), then quotes[0] cannot be undefined.

🔎 Proposed refactor to remove redundant check
     if (!quotes || quotes.length === 0) {
       return Err(
         makeSwapErrorRight({
           message: 'No quotes available for this trade pair',
           code: TradeQuoteError.NoRouteFound,
         }),
       )
     }

     const bestQuote = quotes[0]
-
-    if (!bestQuote) {
-      return Err(
-        makeSwapErrorRight({
-          message: 'No valid quote returned from AVNU',
-          code: TradeQuoteError.QueryFailed,
-        }),
-      )
-    }
📜 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 a5538a1 and 1b8bfa1.

📒 Files selected for processing (5)
  • packages/caip/src/adapters/coingecko/index.test.ts
  • packages/swapper/src/swappers/AvnuSwapper/swapperApi/getTradeQuote.ts
  • packages/swapper/src/swappers/AvnuSwapper/swapperApi/getTradeRate.ts
  • packages/swapper/src/swappers/utils/helpers/helpers.ts
  • packages/utils/src/treasury.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/caip/src/adapters/coingecko/index.test.ts
  • packages/swapper/src/swappers/AvnuSwapper/swapperApi/getTradeRate.ts
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{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/swapper/src/swappers/utils/helpers/helpers.ts
  • packages/utils/src/treasury.ts
  • packages/swapper/src/swappers/AvnuSwapper/swapperApi/getTradeQuote.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/swapper/src/swappers/utils/helpers/helpers.ts
  • packages/utils/src/treasury.ts
  • packages/swapper/src/swappers/AvnuSwapper/swapperApi/getTradeQuote.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/src/swappers/AvnuSwapper/swapperApi/getTradeQuote.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/swapper/src/swappers/utils/helpers/helpers.ts
  • packages/utils/src/treasury.ts
  • packages/swapper/src/swappers/AvnuSwapper/swapperApi/getTradeQuote.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/AvnuSwapper/swapperApi/getTradeQuote.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
  • packages/swapper/src/swappers/AvnuSwapper/swapperApi/getTradeQuote.ts
🧠 Learnings (18)
📓 Common learnings
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: NeOMakinG
Repo: shapeshift/web PR: 10231
File: src/components/AssetSearch/components/AssetList.tsx:2-2
Timestamp: 2025-08-08T15:00:49.887Z
Learning: Project shapeshift/web: NeOMakinG prefers avoiding minor a11y/UI nitpicks (e.g., adding aria-hidden to decorative icons in empty states like src/components/AssetSearch/components/AssetList.tsx) within feature PRs; defer such suggestions to a follow-up instead of blocking the PR.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11016
File: packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts:109-145
Timestamp: 2025-11-12T12:18:00.863Z
Learning: NEAR Intents swapper: The NEAR 1Click API does not provide gas limit estimation logic like other swappers (e.g., magic gasLimit fields). For ERC20 token swaps in getTradeQuote, accurate fee estimation requires token approval and sufficient balance; without these prerequisites, fees may display as 0 or use inaccurate native transfer estimates. This is a known limitation of the NEAR Intents integration.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11335
File: packages/swapper/src/swappers/CetusSwapper/utils/helpers.ts:3-3
Timestamp: 2025-12-09T21:07:22.474Z
Learning: In packages/swapper/src/swappers/CetusSwapper, mysten/sui types (SuiClient, Transaction) must be imported from the nested path within cetusprotocol/aggregator-sdk (e.g., 'cetusprotocol/aggregator-sdk/node_modules/mysten/sui/client') because the aggregator SDK bundles its own version of mysten/sui. Direct imports from 'mysten/sui' break at runtime even when specified in package.json.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10323
File: src/pages/RFOX/components/Stake/components/StakeSummary.tsx:112-114
Timestamp: 2025-08-22T13:00:44.879Z
Learning: NeOMakinG prefers to keep PR changes minimal and focused on the core objectives, avoiding cosmetic or defensive code improvements that aren't directly related to the PR scope, even when they would improve robustness.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10128
File: .cursor/rules/error-handling.mdc:266-274
Timestamp: 2025-07-29T10:35:22.059Z
Learning: NeOMakinG prefers less nitpicky suggestions on documentation and best practices files, finding overly detailed suggestions on minor implementation details (like console.error vs logger.error) too granular for cursor rules documentation.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10380
File: src/pages/Dashboard/components/AccountList/AccountTable.tsx:60-0
Timestamp: 2025-09-02T08:34:08.157Z
Learning: NeOMakinG prefers code review comments to focus only on actual PR changes, not pre-existing code issues, unless there are critical security or correctness concerns directly related to the new functionality.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10234
File: src/components/MultiHopTrade/hooks/useGetTradeQuotes/hooks/useTrackTradeQuotes.ts:42-86
Timestamp: 2025-08-08T11:41:22.794Z
Learning: NeOMakinG prefers not to include refactors in move-only PRs; such suggestions should be deferred to follow-up issues instead of being applied within the same PR.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10380
File: src/components/Table/Table.theme.ts:177-180
Timestamp: 2025-09-02T12:38:46.940Z
Learning: NeOMakinG prefers to defer technical debt and CSS correctness issues (like improper hover selectors) to follow-up PRs when the current PR is already large and focused on major feature implementation, even when the issues are valid from a usability/technical perspective.
📚 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
  • packages/utils/src/treasury.ts
  • packages/swapper/src/swappers/AvnuSwapper/swapperApi/getTradeQuote.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/swapper/src/swappers/utils/helpers/helpers.ts
  • packages/swapper/src/swappers/AvnuSwapper/swapperApi/getTradeQuote.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/swapper/src/swappers/utils/helpers/helpers.ts
  • packages/utils/src/treasury.ts
  • packages/swapper/src/swappers/AvnuSwapper/swapperApi/getTradeQuote.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
  • packages/swapper/src/swappers/AvnuSwapper/swapperApi/getTradeQuote.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
  • packages/swapper/src/swappers/AvnuSwapper/swapperApi/getTradeQuote.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: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/swapper/src/swappers/utils/helpers/helpers.ts
  • packages/utils/src/treasury.ts
📚 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/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-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/constants.ts : Register new swappers in packages/swapper/src/constants.ts with an entry in the swappers registry mapping SwapperName enum to swapper implementation

Applied to files:

  • packages/swapper/src/swappers/utils/helpers/helpers.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/swapper/src/swappers/utils/helpers/helpers.ts
📚 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 **/swapper{s,}/**/*.{ts,tsx} : ALWAYS use `makeSwapErrorRight` for swapper errors with `TradeQuoteError` enum for error codes and provide detailed error information

Applied to files:

  • packages/swapper/src/swappers/AvnuSwapper/swapperApi/getTradeQuote.ts
📚 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:

  • packages/swapper/src/swappers/AvnuSwapper/swapperApi/getTradeQuote.ts
📚 Learning: 2025-12-09T21:06:15.748Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11335
File: packages/swapper/src/swappers/CetusSwapper/endpoints.ts:66-68
Timestamp: 2025-12-09T21:06:15.748Z
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/swapper/src/swappers/AvnuSwapper/swapperApi/getTradeQuote.ts
📚 Learning: 2025-11-12T12:18:00.863Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11016
File: packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts:109-145
Timestamp: 2025-11-12T12:18:00.863Z
Learning: NEAR Intents swapper: The NEAR 1Click API does not provide gas limit estimation logic like other swappers (e.g., magic gasLimit fields). For ERC20 token swaps in getTradeQuote, accurate fee estimation requires token approval and sufficient balance; without these prerequisites, fees may display as 0 or use inaccurate native transfer estimates. This is a known limitation of the NEAR Intents integration.

Applied to files:

  • packages/swapper/src/swappers/AvnuSwapper/swapperApi/getTradeQuote.ts
📚 Learning: 2025-11-12T13:01:06.086Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11016
File: packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeRate.ts:25-38
Timestamp: 2025-11-12T13:01:06.086Z
Learning: In the swapper architecture (packages/swapper), input validation for sell amounts (e.g., checking sellAmount > 0) is handled by the application layer before reaching individual swapper implementations. Swapper methods like getTradeRate and getTradeQuote can assume inputs have already been validated upstream, so defensive guards for basic input validation (amount > 0, valid addresses, etc.) are unnecessary at the swapper layer.

Applied to files:

  • packages/swapper/src/swappers/AvnuSwapper/swapperApi/getTradeQuote.ts
📚 Learning: 2025-08-11T09:46:41.060Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10219
File: src/components/MultiHopTrade/components/TradeInput/TradeInput.tsx:167-172
Timestamp: 2025-08-11T09:46:41.060Z
Learning: In the shapeshift/web repository, the display cache logic for trade quotes (using `selectUserAvailableTradeQuotes` and `selectUserUnavailableTradeQuotes`) is intentionally kept the same between `TradeInput.tsx` and `TradeQuotes.tsx` components. The `hasQuotes` computation in `TradeInput.tsx` uses these display cache selectors by design, matching the pattern used in `TradeQuotes.tsx`.

Applied to files:

  • packages/swapper/src/swappers/AvnuSwapper/swapperApi/getTradeQuote.ts
🧬 Code graph analysis (2)
packages/swapper/src/swappers/utils/helpers/helpers.ts (1)
packages/utils/src/treasury.ts (1)
  • DAO_TREASURY_STARKNET (39-40)
packages/swapper/src/swappers/AvnuSwapper/swapperApi/getTradeQuote.ts (6)
packages/swapper/src/types.ts (3)
  • CommonTradeQuoteInput (194-199)
  • TradeQuote (555-560)
  • SwapErrorRight (105-111)
packages/swapper/src/swappers/AvnuSwapper/utils/constants.ts (1)
  • AVNU_SUPPORTED_CHAIN_IDS (4-4)
packages/swapper/src/swappers/AvnuSwapper/index.ts (1)
  • AVNU_SUPPORTED_CHAIN_IDS (1-1)
packages/swapper/src/utils.ts (2)
  • makeSwapErrorRight (40-56)
  • getInputOutputRate (315-329)
packages/swapper/src/swappers/AvnuSwapper/utils/helpers.ts (1)
  • getTokenAddress (13-23)
packages/swapper/src/swappers/utils/helpers/helpers.ts (1)
  • getTreasuryAddressFromChainId (74-82)
🔇 Additional comments (8)
packages/swapper/src/swappers/utils/helpers/helpers.ts (2)

28-28: LGTM!

The import correctly adds the Starknet treasury constant following the existing pattern.


71-71: The Starknet treasury address mapping requires verification from the DAO before merging.

The address 0x05513953e22e358a332636048723402f5fc31e19ae2c59750048e2d38141029f is not documented in ShapeShift's official FOX token page or Starknet's official documentation. ShapeShift's public treasury documentation currently lists treasuries only on Ethereum, Arbitrum, Base, Gnosis, Optimism, and Polygon—Starknet is absent. Before adding this mapping, confirm this address is an authorized DAO treasury address and have it documented in official channels to prevent potential fund loss.

⛔ Skipped due to learnings
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10751
File: src/Routes/RoutesCommon.tsx:190-190
Timestamp: 2025-10-13T11:55:57.439Z
Learning: In the shapeshift/web codebase, there are multiple independent claim systems: Arbitrum bridge claims (removed in PR #10751), RFOX claims (in src/pages/RFOX/components/Claim/), and TCY claims (in src/pages/TCY/). Each has its own routes, components, and logic. When reviewing claim-related changes, distinguish which system is being modified and avoid suggesting changes to unrelated claim systems.
packages/utils/src/treasury.ts (2)

18-18: LGTM!

The addition of StarknetMainnet to the treasuryChainIds array is correct and properly expands the TreasuryChainId type.


39-40: LGTM!

The constant definition follows the correct naming convention and the address format appears valid for Starknet (properly padded with leading zeros).

packages/swapper/src/swappers/AvnuSwapper/swapperApi/getTradeQuote.ts (4)

1-13: LGTM!

Imports are appropriate and follow the swapper architecture patterns. The use of @sniptt/monads for Result types and proper helper imports align with established conventions.


178-186: LGTM!

Error handling properly follows the swapper architecture using the Result pattern with makeSwapErrorRight and includes the error cause for debugging. The implementation correctly wraps exceptions in SwapErrorRight with an appropriate error code.


111-121: LGTM!

Fee estimation correctly uses the Starknet adapter's getFeeData with appropriate parameters to simulate a token transfer for accurate fee calculation.


130-141: Verify the semantics of AVNU SDK's integratorFees parameter and buyAmount calculation.

The pattern in the codebase shows other swappers calculating different values for buyAmountBeforeFeesCryptoBaseUnit and buyAmountAfterFeesCryptoBaseUnit when protocol fees are involved (see ZrxSwapper, RelaySwapper, PortalsSwapper). However, AVNU sets both fields to the same value while also calculating protocolFees as a percentage of the post-fee amount.

Clarify:

  • Does passing integratorFees to AVNU's getQuotes cause the SDK to deduct these fees from the returned buyAmount, or is it just metadata?
  • If fees are deducted by the SDK, should buyAmountBeforeFeesCryptoBaseUnit be calculated to recover the pre-fee amount?

@NeOMakinG NeOMakinG merged commit b9f14bd into develop Jan 6, 2026
4 checks passed
@NeOMakinG NeOMakinG deleted the ekubo-starknet branch January 6, 2026 13:24
@coderabbitai coderabbitai bot mentioned this pull request Jan 8, 2026
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