Skip to content

Conversation

@gomesalexandre
Copy link
Contributor

@gomesalexandre gomesalexandre commented Jan 15, 2026

Description

Does what it says on the box i.e:

  • wires up multi-account across the board for yield
  • fetches account 0+ yield balances
  • aggregates yield balances in /yields, yield symbol pages
  • accommodates for multi-account in account/asset pages (show position across accounts/single accounts and enable the 0+ ones)
  • adds tests for yield utils

Issue (if applicable)

Risk

Low - behind YieldMultiAccount feature flag

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

None - UI only changes for yield display and account selection

Testing

Engineering

Note: test with flag on - assume this will ship with it

  • able to select account for multi-account chainId in yield page and see specific positions for each, interact from this specific account
  • able to see yield aggregate (available/aped) in yields page
  • able to see yield positions for all accounts in asset page
  • able to see yield positions for a given account in account page
  • account/asset page CTA routes to correct accountId selected in enter modal (if from account page), and to properly selected accountId for position
  • refreshing a given yield account page works

Operations

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

Screenshots (if applicable)

https://jam.dev/c/fbf0f785-b277-424e-8f07-20d4ce900339

Summary by CodeRabbit

  • New Features

    • Multi-account support across Yields: view balances and positions per account, switch accounts via an account selector (desktop & mobile), and see per-account totals.
    • Account selection synced to the URL for consistent navigation.
  • UI Improvements

    • Position and list views now show account labels and navigate including the selected account.
    • Active balance totals now sum all active/locked balances per position.
  • Translations

    • Added "Select Account" and "Balance by Account" strings.
  • Tests

    • Expanded unit test coverage for yield utilities and flows.

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

gomesalexandre and others added 8 commits January 15, 2026 14:51
- Replace useEffect with useMemo for default account selection in
  YieldAccountContext (per CLAUDE.md guidelines)
- Extract duplicate URL sync logic to useYieldAccountSync hook
- Fix aggregate calculation in YieldOpportunityStats to sum all
  active/locked balances across accounts (was using find instead of filter)
- Ensure feature flag properly gates single-account filtering
- Fix type inconsistency in useYieldAccount hook (return 0 not undefined)
- Remove duplicate account column in YieldActivePositions table
- Add comprehensive tests for yield utils

Co-Authored-By: Claude Opus 4.5 <[email protected]>
…selector

- YieldSuccess now accepts accountId and includes it in "View Position" navigation URL
- Updated all YieldSuccess callers (YieldForm, YieldEnterModal, YieldActionModal)
- Fixed YieldEnterModal to fallback to first available account when no accountId prop
- Show validator name/logo for staking positions in YieldActivePositions table
- Route to yield detail with accountId in query params when clicking positions

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

coderabbitai bot commented Jan 15, 2026

📝 Walkthrough

Walkthrough

Adds multi-account support for yield flows: feature flag, account context with URL sync, account-scoped balance queries, account selector UI, plumbing of optional accountId through forms/modals/transaction flows, per-account positions aggregation, tests, and translations.

Changes

Cohort / File(s) Summary
Environment & Translations
\.env.development, src/assets/translations/en/main.json
Added VITE_FEATURE_YIELD_MULTI_ACCOUNT=true and translation keys common.selectAccount, earn.balanceByAccount.
Yield account context & sync
src/pages/Yields/YieldAccountContext.tsx, src/pages/Yields/hooks/useYieldAccountSync.ts
Provider now tracks accountId + accountNumber with optional initialAccountId; new useYieldAccountSync synchronizes selected account with context and URL.
Account-aware hooks & queries
src/pages/Yields/hooks/useYieldTransactionFlow.ts, src/react-queries/queries/yieldxyz/useAllYieldBalances.ts
Account resolution now prioritizes explicit prop accountId, then context accountId, then mapped accountIds; useAllYieldBalances derives targetAccountIds with prioritized fallbacks.
Pages & details
src/pages/Yields/YieldAssetDetails.tsx, src/pages/Yields/YieldDetail.tsx
Feature-flag gating for multi-account, account filtering per asset, AccountSelector UI, useYieldAccountSync integration, and account-scoped balance fetching.
Active positions & lists
src/pages/Yields/components/YieldActivePositions.tsx, src/pages/Yields/components/YieldsList.tsx, src/pages/Yields/components/YieldAssetSection.tsx
Replace aggregated balances with per-yield per-account balancesByYieldId, aggregate per-account positions, pass accountId to modals, and use enabled wallet account IDs for queries.
Forms, modals & manager
src/pages/Yields/components/YieldForm.tsx, src/pages/Yields/components/YieldEnterModal.tsx, src/pages/Yields/components/YieldActionModal.tsx, src/pages/Yields/components/YieldManager.tsx
Added optional accountId prop to forms/modals/manager, derive accountNumber via selectAccountNumberByAccountId, and pass accountId into transaction flows and success UI.
Position card, stats & success
src/pages/Yields/components/YieldPositionCard.tsx, src/pages/Yields/components/YieldOpportunityStats.tsx, src/pages/Yields/components/YieldSuccess.tsx
Prefer context accountId in selectors, sum all active/locked balances per position, and include accountId in success navigation query param.
Utilities & tests
src/lib/yieldxyz/utils.ts, src/lib/yieldxyz/utils.test.ts
Removed exported toUserCurrency from utils; added comprehensive unit tests for yield utility functions.

Sequence Diagram

sequenceDiagram
    actor User
    participant UI as Yield UI (Page/Components)
    participant Hook as useYieldAccountSync
    participant Context as YieldAccountContext
    participant Query as useAllYieldBalances
    participant API as Yield API

    User->>UI: Select account in AccountSelector
    UI->>Hook: handleAccountChange(newAccountId)
    Hook->>Context: setAccountId(newAccountId)
    Hook->>UI: update URL ?accountId=newAccountId

    Context-->>UI: updated accountId
    UI->>Query: fetch balances(targetAccountIds=[newAccountId])
    Query->>API: GET /balances?accountIds=...
    API-->>Query: balances data
    Query-->>UI: balances response
    UI-->>User: render positions & stats for selected account
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • feat: yield.xyz POC #11578 — Touches the same yield.xyz utils surface and the feature flag; overlaps removal/addition around toUserCurrency and multi-account flag.

Suggested reviewers

  • NeOMakinG
  • premiumjibles

Poem

🐰 I hop between accounts with nimble feet,

Context whispers choices soft and sweet.
Selectors point where balances hide,
URL follows, side by side.
A rabbit cheers: multi-account treat!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: multi-account yield support' accurately and concisely describes the main objective of the PR, which is to add multi-account support for yield-related functionality.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat_yield_multi_account


📜 Recent 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 2da1247 and 5b69c61.

📒 Files selected for processing (1)
  • src/pages/Yields/components/YieldPositionCard.tsx
🧰 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:

  • src/pages/Yields/components/YieldPositionCard.tsx
**/*.{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:

  • src/pages/Yields/components/YieldPositionCard.tsx
**/*.{tsx,jsx}

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

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

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

Files:

  • src/pages/Yields/components/YieldPositionCard.tsx
**/*.{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:

  • src/pages/Yields/components/YieldPositionCard.tsx
**/*.{jsx,tsx}

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

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

Files:

  • src/pages/Yields/components/YieldPositionCard.tsx
**/*.tsx

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

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

Files:

  • src/pages/Yields/components/YieldPositionCard.tsx
🧠 Learnings (16)
📓 Common learnings
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10569
File: src/plugins/walletConnectToDapps/components/WalletConnectSigningModal/WalletConnectModalSigningFooter.tsx:121-129
Timestamp: 2025-09-17T22:40:30.149Z
Learning: gomesalexandre maintains strict scope discipline even for style/UI PRs in shapeshift/web, declining functionally correct UX improvements (like keeping Cancel button enabled during gas simulation loading) when they fall outside the PR's stated styling objectives, demonstrating his consistent pattern of deferring valid but tangential improvements to separate efforts.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10418
File: src/plugins/walletConnectToDapps/components/header/WalletConnectToDappsHeaderButton.tsx:0-0
Timestamp: 2025-09-08T22:00:48.005Z
Learning: gomesalexandre dismissed an aria-label accessibility suggestion with "meh" in PR `#10418` for WalletConnectToDappsHeaderButton.tsx, consistent with the team's pattern of deferring minor a11y improvements to follow-up PRs rather than expanding feature PR scope.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/EIP712MessageDisplay.tsx:21-24
Timestamp: 2025-09-12T13:16:27.004Z
Learning: gomesalexandre declined to add error boundaries to WalletConnect modals in PR `#10461`, stating "no error boundaries in this pr ser", consistent with his preference to keep PR scope focused and defer tangential improvements to separate efforts.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11170
File: patches/@shapeshiftoss+bitcoinjs-lib+7.0.0-shapeshift.0.patch:9-19
Timestamp: 2025-11-25T21:43:10.838Z
Learning: In shapeshift/web, gomesalexandre will not expand PR scope to fix latent bugs in unused API surface (like bitcoinjs-lib patch validation methods) when comprehensive testing proves the actual used code paths work correctly, preferring to avoid costly hdwallet/web verdaccio publish cycles and full regression testing for conceptual issues with zero runtime impact.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10879
File: src/context/WalletProvider/WalletConnectV2/components/WalletConnectDirectRow.tsx:64-81
Timestamp: 2025-10-22T22:11:22.918Z
Learning: In early WalletConnect POC/features behind a flag, gomesalexandre prioritizes connection correctness/stability over UX polish; minimal safety guards (like preventing concurrent connects) are preferred, while visuals will be wired later by reallybeard.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10206
File: src/config.ts:127-128
Timestamp: 2025-08-07T11:20:44.614Z
Learning: gomesalexandre prefers required environment variables without default values in the config file (src/config.ts). They want explicit configuration and fail-fast behavior when environment variables are missing, rather than having fallback defaults.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/ContractInteractionBreakdown.tsx:0-0
Timestamp: 2025-09-13T16:45:18.813Z
Learning: gomesalexandre prefers aggressively deleting unused/obsolete code files ("ramboing") rather than fixing technical issues in code that won't be used, demonstrating his preference for keeping codebases clean and PR scope focused.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10458
File: src/plugins/walletConnectToDapps/types.ts:7-7
Timestamp: 2025-09-10T15:34:29.604Z
Learning: gomesalexandre is comfortable relying on transitive dependencies (like abitype through ethers/viem) rather than explicitly declaring them in package.json, preferring to avoid package.json bloat when the transitive dependency approach works reliably in practice.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10503
File: .env:56-56
Timestamp: 2025-09-16T13:17:02.938Z
Learning: gomesalexandre prefers to enable feature flags globally in the base .env file when the intent is to activate features everywhere, even when there are known issues like crashes, demonstrating his preference for intentional global feature rollouts over cautious per-environment enablement.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10249
File: src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx:447-503
Timestamp: 2025-08-13T17:07:10.763Z
Learning: gomesalexandre prefers relying on TypeScript's type system for validation rather than adding defensive runtime null checks when types are properly defined. They favor a TypeScript-first approach over defensive programming with runtime validations.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10276
File: src/hooks/useActionCenterSubscribers/useThorchainLpDepositActionSubscriber.tsx:61-66
Timestamp: 2025-08-14T17:51:47.556Z
Learning: gomesalexandre is not concerned about structured logging and prefers to keep console.error usage as-is rather than implementing structured logging patterns, even when project guidelines suggest otherwise.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10413
File: src/components/Modals/FiatRamps/fiatRampProviders/onramper/utils.ts:29-55
Timestamp: 2025-09-02T14:26:19.028Z
Learning: gomesalexandre prefers to keep preparatory/reference code simple until it's actively consumed, rather than implementing comprehensive error handling, validation, and robustness improvements upfront. They prefer to add these improvements when the code is actually being used in production.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10276
File: src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx:396-402
Timestamp: 2025-08-14T17:55:57.490Z
Learning: gomesalexandre is comfortable with functions/variables that return undefined or true (tri-state) when only the truthy case matters, preferring to rely on JavaScript's truthy/falsy behavior rather than explicitly returning boolean values.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10783
File: src/context/ModalStackProvider/useModalRegistration.ts:30-41
Timestamp: 2025-10-16T11:14:40.657Z
Learning: gomesalexandre prefers to add lint rules (like typescript-eslint/strict-boolean-expressions for truthiness checks on numbers) to catch common issues project-wide rather than relying on code review to catch them.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10206
File: src/lib/moralis.ts:47-85
Timestamp: 2025-08-07T11:22:16.983Z
Learning: gomesalexandre prefers console.error over structured logging for Moralis API integration debugging, as they find it more conventional and prefer to examine XHR requests directly rather than rely on structured logs for troubleshooting.
📚 Learning: 2025-09-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:

  • src/pages/Yields/components/YieldPositionCard.tsx
📚 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:

  • src/pages/Yields/components/YieldPositionCard.tsx
📚 Learning: 2025-08-15T07:51:16.374Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10278
File: src/components/AssetHeader/hooks/useQuickBuy.ts:97-99
Timestamp: 2025-08-15T07:51:16.374Z
Learning: The selectPortfolioUserCurrencyBalanceByAssetId selector in src/state/slices/portfolioSlice/selectors.ts expects a filter object with an assetId property, not a raw AssetId string. The selector signature is (state: ReduxState, filter) where filter should have an assetId property. This pattern is consistent across portfolio selectors that use selectAssetIdParamFromFilter. Passing a filter object like { assetId: someAssetId } is the correct usage pattern.

Applied to files:

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

Applied to files:

  • src/pages/Yields/components/YieldPositionCard.tsx
📚 Learning: 2025-07-29T15:04:28.083Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10139
File: src/components/MultiHopTrade/components/TradeConfirm/components/ExpandableStepperSteps.tsx:109-115
Timestamp: 2025-07-29T15:04:28.083Z
Learning: In src/components/MultiHopTrade/components/TradeConfirm/components/ExpandableStepperSteps.tsx, the component is used under an umbrella that 100% of the time contains the quote, making the type assertion `activeTradeQuote?.steps[currentHopIndex] as TradeQuoteStep` safe. Adding conditional returns before hooks would violate React's Rules of Hooks.

Applied to files:

  • src/pages/Yields/components/YieldPositionCard.tsx
📚 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/pages/Yields/components/YieldPositionCard.tsx
📚 Learning: 2025-08-22T12:59:01.702Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10323
File: src/components/Layout/Header/ActionCenter/components/RewardDistributionActionCard.tsx:37-53
Timestamp: 2025-08-22T12:59:01.702Z
Learning: In RewardDistributionActionCard component (src/components/Layout/Header/ActionCenter/components/RewardDistributionActionCard.tsx), NeOMakinG confirmed that runeAsset is expected to always be defined when the component renders, so defensive guards against undefined runeAsset are not needed.

Applied to files:

  • src/pages/Yields/components/YieldPositionCard.tsx
📚 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:

  • src/pages/Yields/components/YieldPositionCard.tsx
📚 Learning: 2025-07-24T11:07:20.536Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10073
File: src/features/defi/providers/fox-farming/components/FoxFarmingManager/Claim/Claim.tsx:77-84
Timestamp: 2025-07-24T11:07:20.536Z
Learning: In fox farming components, the `opportunity?.rewardsCryptoBaseUnit?.amounts` property has a well-defined type signature that is always an array (never undefined), but can be empty: `readonly [] | readonly [string, string, string] | readonly [string, string] | readonly [string]`. Using optional chaining on the `amounts` property itself is unnecessary since it's always defined, though accessing `amounts[0]` on an empty array returns undefined which bnOrZero() handles safely.

Applied to files:

  • src/pages/Yields/components/YieldPositionCard.tsx
📚 Learning: 2025-08-22T12:58:36.070Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10323
File: src/components/Layout/Header/ActionCenter/components/Notifications/RewardDistributionNotification.tsx:33-55
Timestamp: 2025-08-22T12:58:36.070Z
Learning: In RewardDistributionNotification component (src/components/Layout/Header/ActionCenter/components/Notifications/RewardDistributionNotification.tsx), NeOMakinG confirmed that runeAsset is expected to always be defined when the component renders, so defensive guards against undefined runeAsset are not needed.

Applied to files:

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

Applied to files:

  • src/pages/Yields/components/YieldPositionCard.tsx
📚 Learning: 2025-08-13T15:52:25.116Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10272
File: src/context/WalletProvider/MobileWallet/mobileMessageHandlers.ts:61-0
Timestamp: 2025-08-13T15:52:25.116Z
Learning: In the ShapeShift web codebase, specifically in src/context/WalletProvider/MobileWallet/mobileMessageHandlers.ts, message variants in the Message union type do not include inline comments documenting their expected return types. The codebase follows a pattern of keeping these type definitions clean without such documentation comments.

Applied to files:

  • src/pages/Yields/components/YieldPositionCard.tsx
📚 Learning: 2025-08-10T21:09:25.643Z
Learnt from: premiumjibles
Repo: shapeshift/web PR: 10215
File: src/components/MultiHopTrade/hooks/useGetTradeRateInput.ts:65-67
Timestamp: 2025-08-10T21:09:25.643Z
Learning: In the MultiHopTrade components, `selectInputBuyAsset` and `selectInputSellAsset` selectors from `tradeInputSlice` always return defined values because they have default values in the initial state (BTC for buyAsset, ETH for sellAsset, with fallback to defaultAsset). Null checks for these assets are unnecessary when using these selectors.

Applied to files:

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

Applied to files:

  • src/pages/Yields/components/YieldPositionCard.tsx
📚 Learning: 2026-01-15T09:59:33.508Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11656
File: src/pages/Yields/components/YieldsList.tsx:1028-1046
Timestamp: 2026-01-15T09:59:33.508Z
Learning: In the Yields UI components (src/pages/Yields/components), do not render an in-app mobile filter UI due to limited screen space. Users on mobile should access filtered views via URL query parameters instead. This pattern applies to similar Yields UI components in the same directory; ensure the mobile UI remains navigable through URL parameters (e.g., ?filters=...), and document this behavior for consistency across the Yields-related components.

Applied to files:

  • src/pages/Yields/components/YieldPositionCard.tsx
🧬 Code graph analysis (1)
src/pages/Yields/components/YieldPositionCard.tsx (3)
src/pages/Yields/YieldAccountContext.tsx (1)
  • useYieldAccount (48-58)
src/lib/yieldxyz/constants.ts (1)
  • DEFAULT_NATIVE_VALIDATOR_BY_CHAIN_ID (101-104)
src/state/store.ts (1)
  • useAppSelector (145-145)
⏰ 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 (1)
src/pages/Yields/components/YieldPositionCard.tsx (1)

55-65: LGTM! Clean integration of context-provided accountId.

The logic correctly prioritizes contextAccountId from the yield account context, falling back to the derived accountId when unavailable. This aligns well with the multi-account yield support objective.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


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

❤️ Share

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

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

🤖 Fix all issues with AI agents
In `@src/pages/Yields/components/YieldPositionCard.tsx`:
- Line 63: The guard "if (accountNumber === undefined) return undefined" in
YieldPositionCard is unreachable because useYieldAccount always returns
accountNumber as a number (defaults to 0); remove this conditional and any early
return that depends on accountNumber being undefined to simplify the component
and rely on the numeric value from useYieldAccount instead.
🧹 Nitpick comments (3)
src/pages/Yields/components/YieldActionModal.tsx (1)

46-46: Use AccountId type instead of string for type consistency.

The accountId prop is typed as string, but YieldSuccess and other components in this PR use AccountId from @shapeshiftoss/caip. Using the nominal AccountId type ensures type safety across the yield flow.

Suggested fix

Add the import at the top of the file:

import type { AccountId } from '@shapeshiftoss/caip'

Then update the prop type:

 type YieldActionModalProps = {
   isOpen: boolean
   onClose: () => void
   yieldItem: AugmentedYieldDto
   action: 'enter' | 'exit' | 'manage'
   amount: string
   assetSymbol: string
   assetLogoURI?: string
   validatorAddress?: string
   validatorName?: string
   validatorLogoURI?: string
   passthrough?: string
   manageActionType?: string
-  accountId?: string
+  accountId?: AccountId
 }
src/pages/Yields/YieldAssetDetails.tsx (1)

115-118: Minor inconsistency with YieldDetail.tsx balance fetching logic.

In YieldDetail.tsx (line 68-71), when isYieldMultiAccountEnabled is false, balanceAccountIds returns undefined if availableAccounts is empty. Here, it returns accountIdsForAsset directly (potentially an empty array).

This difference may cause inconsistent behavior in useAllYieldBalances depending on how it handles empty arrays vs. undefined. Consider aligning the logic:

 const balanceAccountIds = useMemo(() => {
-  if (!isYieldMultiAccountEnabled) return accountIdsForAsset
+  if (!isYieldMultiAccountEnabled) return accountIdsForAsset.length > 0 ? accountIdsForAsset : undefined
   return selectedAccountId ? [selectedAccountId] : accountIdsForAsset
 }, [isYieldMultiAccountEnabled, selectedAccountId, accountIdsForAsset])
src/pages/Yields/components/YieldActivePositions.tsx (1)

87-141: Validator info may be lost when aggregating multiple validators.

When a user has positions with multiple validators in the same yield, only the first validator's info is preserved due to the existing.validatorAddress ?? validator?.address pattern. If the intent is to show separate positions per validator, consider grouping by (accountId, validatorAddress) instead of just accountId.

If showing one aggregate per account is intentional (with "first validator wins"), this is acceptable but worth documenting.

gomesalexandre and others added 3 commits January 15, 2026 18:10
- Remove toUserCurrency utility (use inline bnOrZero().times().toFixed() pattern)
- Remove trivial lookup table tests for getTransactionButtonText
- Keep meaningful tests for edge cases, fallbacks, and actual logic

Co-Authored-By: Claude Opus 4.5 <[email protected]>
accountNumber always returns a number (defaults to 0) from useYieldAccount,
so the undefined check is unreachable.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants