-
Notifications
You must be signed in to change notification settings - Fork 198
feat: big batch of yield improvements #11656
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: big batch of yield improvements #11656
Conversation
- Remove unnecessary filteredYields dependency in YieldAssetDetails useMemo hooks - Add validator breakdown utility functions - Enhance yield action modal with additional transaction handling - Refactor yield filters component for better code organization - Update yields list component layout - Improve yield filters hook logic - Add yield transaction flow hooks - Add missing translation key Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add APPROVAL type to TX_TYPE_TO_LABEL (button now shows "Approve" not "Approval") - Filter SKIPPED transactions in displaySteps preview - Use first CREATED transaction for button text - Harmonize button/row labels: SUPPLY/ENTER -> "Deposit", EXIT -> "Withdraw" - Fix useCallback missing dependencies in useYieldTransactionFlow - Add icon background color for yield detail hero - Add chainName to action transaction metadata Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Change invalidateQueries to refetchQueries with await - Ensures position data is fresh before modal closes - Fixes "My Positions" showing empty after deposit/withdraw Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Since dispatchNotification is called after waitForActionCompletion, the transaction is already confirmed. Dispatch with Complete status directly instead of relying on Unchained subscriber (which doesn't work for chains without Unchained support like Monad). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
After yield transaction completion, trigger portfolioApi.getAccount refetch for second class chains (Monad, Tron, etc.) that don't have Unchained support. This ensures wallet balances update immediately. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Extract sortedRows from table to use as dependency - TanStack Table's table object reference is stable, so useMemo was not re-running when filtered data changed - Using sortedRows as dependency triggers proper re-memoization Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add searchString prop to YieldItem - Pass current filter params when navigating to asset detail page - Filters persist across navigation (e.g., network=ethereum) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Set staleTime: Infinity to prevent refetching during modal lifecycle - Set gcTime: 0 to garbage collect cached quote when modal closes - Ensures fresh quote on re-entry, no stale data from previous tx Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove quote queries from cache when modal closes - Ensures fresh quote fetch on subsequent modal opens - Remove YIELD_POLISH.md Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create YieldEnterModal component with Trust Wallet-inspired design
- Big centered input with fiat/crypto toggle
- Asset icon, percent buttons (25%, 50%, 75%, Max)
- Debounced quote fetching (500ms) for pre-loading transactions
- Auto-select default validator (ShapeShift DAO for Cosmos)
- Stats section with APY, validator/provider info, and min deposit
- Modify YieldAssetSection to open modal instead of navigate
- Add translation key for "Stake {asset}"
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add TransactionStepsList component for shared step display - Extract useConfetti hook to eliminate duplication - Export poll/waitForActionCompletion from useYieldTransactionFlow - Update YieldOpportunityCard with horizontal layout - Use Card variant='dashboard' in YieldAssetSection - Add tx hash links in success view Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…ventions, style fixes Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- YieldFilters: Use MenuOptionGroup/MenuItemOption for proper theme styling (no more blue.500) - ValidatorBreakdown: Remove useColorModeValue, use direct color tokens - YieldEnterModal: Extract hover style constants outside component - YieldEnterExit: Extract style constants outside component, fix inline button handlers - YieldActionModal: Use STATUS_LABEL_KEYS map to avoid nested ternaries - useYieldTransactionFlow: Rename loadingMessage to statusLabel for consistency Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…a.50 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- YieldValidatorSelectModal: gray.300, gray.500 -> text.subtle - YieldActionModal: whiteAlpha.50 -> background.surface.raised.base Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add SHAPESHIFT_VALIDATOR constant with fallback APR data - normalizeCosmosValidators ensures ShapeShift is always first - Only ShapeShift is marked as preferred for Cosmos SDK - Add COSMOS_NETWORK_FALLBACK_APR (15%) for validators missing APR - Remove redundant sortValidators call in modal Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove redundant ASSET column from YieldActivePositions table - Remove "Your Balance" label (already obvious from context) - Move ensureValidatorApr to utils for reuse - Fix React key warning in ReactTable (destructure key from spread props) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…hide section without wallet - Extract TransactionStepStatus from anonymous IIFE in YieldActionModal - Reuse existing poll utility from lib/poll instead of custom implementation - Hide YieldAssetSection when wallet is not connected - Reorder TransactionStep type fields for cleaner grouping - Remove unnecessary curly braces in useYieldValidators Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…saction step - Reverted poll changes to use original inline implementation - Export waitForActionCompletion for YieldEnterModal usage - Fix enterButtonText to use getTransactionButtonText for proper labels (shows "Approve" instead of "Stake USDT" when approval is first step) - Add originalTitle and type to TransactionStep in YieldEnterModal - Ensure consistent use of loadingMessage property Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
… model - Replace for-loop auto-execution with click-per-step model matching useYieldTransactionFlow - Add activeStepIndex, rawTransactions, currentActionId state for multi-step tracking - Extract executeSingleTransaction callback for single transaction execution - Export filterExecutableTransactions from hook for code reuse - Fix button text and steps display between transaction steps [skip ci] Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…dals [skip ci] Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds waitForTransactionConfirmation helper to poll backend until the submitted transaction is confirmed, preventing nonce conflicts when users quickly transition between Approve and Deposit transactions. This resolves "replacement transaction underpriced" errors by ensuring the on-chain nonce counter has incremented before constructing the next transaction. [skip ci] Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this 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/components/MultiHopTrade/components/Earn/EarnConfirm.tsx`:
- Around line 282-285: The asset symbol and the "/yr" translation are rendered
back-to-back causing outputs like "1.5 ETH/yr"; update the JSX in EarnConfirm
(where GradientApy, estimatedYearlyEarnings, sellAsset?.symbol and
translate('yieldXYZ.perYear') are used) to include a space between the symbol
and the translation (e.g., ensure the symbol and translate('yieldXYZ.perYear')
are concatenated with a separating space or add a leading space to the
translation string) so the result renders as "1.5 ETH /yr" or "1.5 ETH / yr" per
project style.
♻️ Duplicate comments (1)
src/components/MultiHopTrade/components/Earn/EarnConfirm.tsx (1)
196-196: TheisLoadingprop is unused bySharedConfirm.This was identified in a previous review. The prop is passed on lines 196, 219, and 345 but
SharedConfirmdoes not destructure or use it.Also applies to: 219-219, 345-345
🧹 Nitpick comments (3)
src/pages/Yields/components/YieldActionModal.tsx (2)
208-208: Consider memoizingassetFlowDirectionfor consistency.This conditional value is used as a dependency in
animatedAvatarRowuseMemo. While functionally correct, memoizing it would align with the aggressive memoization pattern used throughout this component.Suggested change
- const assetFlowDirection = action === 'exit' ? 'exit' : 'enter' + const assetFlowDirection = useMemo( + () => (action === 'exit' ? 'exit' : 'enter'), + [action], + )
340-343: Unnecessary null check onvaultMetadata.
vaultMetadatais always defined due to the fallback on line 110 ({ name: 'Vault', logoURI: yieldItem.metadata.logoURI }), making the ternary check redundant.Suggested simplification
const successProviderInfo = useMemo( - () => (vaultMetadata ? { name: vaultMetadata.name, logoURI: vaultMetadata.logoURI } : null), + () => ({ name: vaultMetadata.name, logoURI: vaultMetadata.logoURI }), [vaultMetadata], )src/components/MultiHopTrade/components/Earn/EarnConfirm.tsx (1)
98-99: Consider explicit undefined handling for market data.The
|| {}fallback after destructuring could silently mask cases where market data is genuinely unavailable. Thepricewill beundefinedin both missing data and fallback scenarios, but the fallback pattern obscures the source.This is minor since the downstream code handles
undefinedcorrectly.
📜 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.
📒 Files selected for processing (2)
src/components/MultiHopTrade/components/Earn/EarnConfirm.tsxsrc/pages/Yields/components/YieldActionModal.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 runyarn lint --fixandyarn type-checkafter making changes
Avoidletvariable assignments - preferconstwith inline IIFE switch statements or extract to functions for conditional logic
Files:
src/components/MultiHopTrade/components/Earn/EarnConfirm.tsxsrc/pages/Yields/components/YieldActionModal.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 inuseMemoand callbacks inuseCallbackwhere 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 usinguseColorModeValuehook
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()fromreact-polyglot
UseuseFeatureFlag('FlagName')hook to access feature flag values in components
Prefertypeoverinterfacefor type definitions
Use strict typing - avoidany
UseNominaltypes for domain identifiers (e.g.,WalletId,AccountId)
Import types from@shapeshiftoss/caipfor chain/account/asset IDs
UseuseAppSelectorfor Redux state
UseuseAppDispatchfor Redux actions
Memoize expensive computations withuseMemo
Memoize callbacks withuseCallback
**/*.{ts,tsx}: UseResult<T, E>pattern for error handling in swappers and APIs; ALWAYS useOk()andErr()from@sniptt/monads; AVOID throwing within swapper API implementations
ALWAYS use custom error classes from@shapeshiftoss/errorswith meaningful error codes for internationalization and relevant details in error objects
ALWAYS wrap async op...
Files:
src/components/MultiHopTrade/components/Earn/EarnConfirm.tsxsrc/pages/Yields/components/YieldActionModal.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 useuseErrorToasthook for displaying errors with translated error messages and handle different error types appropriatelyUse PascalCase for React component names and match the component name to the file name
Files:
src/components/MultiHopTrade/components/Earn/EarnConfirm.tsxsrc/pages/Yields/components/YieldActionModal.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
Usehandleprefix for event handlers with descriptive names in camelCase
Use descriptive boolean variable names withis,has,can,shouldprefixes
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 likedata,item,obj, and single-letter variable names except in loops
Avoid abbreviations in names unless they are widely understood
Avoid generic function names likefn,func, orcallback
Files:
src/components/MultiHopTrade/components/Earn/EarnConfirm.tsxsrc/pages/Yields/components/YieldActionModal.tsx
**/*.{jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/react-best-practices.mdc)
**/*.{jsx,tsx}: ALWAYS useuseMemofor expensive computations, object/array creations, and filtered data
ALWAYS useuseMemofor derived values and computed properties
ALWAYS useuseMemofor conditional values and simple transformations
ALWAYS useuseCallbackfor event handlers and functions passed as props
ALWAYS useuseCallbackfor any function that could be passed as a prop or dependency
ALWAYS include all dependencies inuseEffect,useMemo,useCallbackdependency arrays
NEVER use// eslint-disable-next-line react-hooks/exhaustive-depsunless 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 withmemofor performance optimization
Files:
src/components/MultiHopTrade/components/Earn/EarnConfirm.tsxsrc/pages/Yields/components/YieldActionModal.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursor/rules/react-best-practices.mdc)
Ensure TypeScript types are explicit and proper; avoid use of
anytype
Files:
src/components/MultiHopTrade/components/Earn/EarnConfirm.tsxsrc/pages/Yields/components/YieldActionModal.tsx
🧠 Learnings (32)
📓 Common learnings
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: 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: 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: 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`
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-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/components/MultiHopTrade/components/Earn/EarnConfirm.tsxsrc/pages/Yields/components/YieldActionModal.tsx
📚 Learning: 2025-08-08T11:41:36.971Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10234
File: src/components/MultiHopTrade/hooks/useGetTradeQuotes/hooks/useTrackTradeQuotes.ts:88-109
Timestamp: 2025-08-08T11:41:36.971Z
Learning: In MultiHopTrade Confirm flow (src/components/MultiHopTrade/components/TradeConfirm/TradeConfirm.tsx), the Confirm route does not remount; navigating away goes to the swapper input page. Therefore, persistent deduplication across remounts for quote tracking is unnecessary; a ref-based single-mount dedupe is sufficient.
Applied to files:
src/components/MultiHopTrade/components/Earn/EarnConfirm.tsx
📚 Learning: 2025-08-08T11:40:55.734Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10234
File: src/components/MultiHopTrade/components/TradeConfirm/TradeConfirm.tsx:41-41
Timestamp: 2025-08-08T11:40:55.734Z
Learning: In MultiHopTrade confirm flow (src/components/MultiHopTrade/components/TradeConfirm/TradeConfirm.tsx and related hooks), there is only one active trade per flow. Because of this, persistent (module/Redux) dedupe for QuotesReceived in useTrackTradeQuotes is not necessary; the existing ref-based dedupe is acceptable.
Applied to files:
src/components/MultiHopTrade/components/Earn/EarnConfirm.tsx
📚 Learning: 2025-09-12T11:52:39.280Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/EIP155TransactionConfirmation.tsx:18-21
Timestamp: 2025-09-12T11:52:39.280Z
Learning: In WalletConnect dApps integration, gomesalexandre has implemented intentional routing logic where EIP155TransactionConfirmation is typed for EthSignTransactionCallRequest only, while a separate SendTransactionConfirmation component handles EthSendTransactionCallRequest. The WalletConnectModalManager contains conditional logic to route native send transactions to SendTransactionConfirmation and other transaction types to EIP155TransactionConfirmation, creating a clean separation of concerns between signing and sending flows.
Applied to files:
src/components/MultiHopTrade/components/Earn/EarnConfirm.tsx
📚 Learning: 2025-08-08T15:00:49.887Z
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.
Applied to files:
src/components/MultiHopTrade/components/Earn/EarnConfirm.tsxsrc/pages/Yields/components/YieldActionModal.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/components/MultiHopTrade/components/Earn/EarnConfirm.tsx
📚 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/components/MultiHopTrade/components/Earn/EarnConfirm.tsxsrc/pages/Yields/components/YieldActionModal.tsx
📚 Learning: 2025-09-12T12:00:33.924Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/SendTransactionConfirmation.tsx:42-50
Timestamp: 2025-09-12T12:00:33.924Z
Learning: gomesalexandre prefers maintaining consistency with existing code patterns across WalletConnect modal components, including side-effects-during-render for error handling (showErrorToast + handleReject calls before return null), rather than introducing isolated refactors that would create inconsistency in the codebase.
Applied to files:
src/components/MultiHopTrade/components/Earn/EarnConfirm.tsxsrc/pages/Yields/components/YieldActionModal.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/components/MultiHopTrade/components/Earn/EarnConfirm.tsxsrc/pages/Yields/components/YieldActionModal.tsx
📚 Learning: 2025-09-12T12:00:33.924Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/SendTransactionConfirmation.tsx:42-50
Timestamp: 2025-09-12T12:00:33.924Z
Learning: gomesalexandre prefers maintaining consistency with existing code patterns in WalletConnect modals, including side-effects-during-render for error handling (showErrorToast + handleReject), rather than introducing isolated refactors that would make the codebase inconsistent.
Applied to files:
src/pages/Yields/components/YieldActionModal.tsx
📚 Learning: 2025-08-22T12:59:01.210Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10323
File: src/components/Layout/Header/ActionCenter/components/RewardDistributionActionCard.tsx:26-29
Timestamp: 2025-08-22T12:59:01.210Z
Learning: In src/components/Layout/Header/ActionCenter/components/RewardDistributionActionCard.tsx, NeOMakinG declined wrapping the RewardDistributionActionCard component with React.memo, saying it was "too much", suggesting that like other action center components, memoization is not beneficial for this specific use case.
Applied to files:
src/pages/Yields/components/YieldActionModal.tsx
📚 Learning: 2025-10-17T07:51:58.374Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10783
File: src/context/WalletProvider/NewWalletViews/NewWalletViewsSwitch.tsx:344-349
Timestamp: 2025-10-17T07:51:58.374Z
Learning: In the shapeshift/web codebase, Chakra UI's ModalContent component supports the containerProps prop. When using the useModalRegistration hook from ModalStackProvider, spreading {...modalContentProps} directly onto ModalContent is correct and properly applies z-index and pointer-events through containerProps.sx. Do not suggest extracting sx from modalContentProps.containerProps.sx.
Applied to files:
src/pages/Yields/components/YieldActionModal.tsx
📚 Learning: 2025-08-25T12:59:43.842Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10323
File: src/pages/Fox/components/RFOXSection.tsx:234-248
Timestamp: 2025-08-25T12:59:43.842Z
Learning: NeOMakinG considers suggestions to refactor working modal state management from useState to useDisclosure as too nitpicky, preferring to keep such cosmetic code improvements out of feature PRs unless they address actual issues.
Applied to files:
src/pages/Yields/components/YieldActionModal.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/YieldActionModal.tsx
📚 Learning: 2025-08-08T14:59:40.422Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10231
File: src/pages/Explore/ExploreCategory.tsx:231-238
Timestamp: 2025-08-08T14:59:40.422Z
Learning: In src/pages/Explore/ExploreCategory.tsx, for the PageHeader filter trigger, NeOMakinG considers changing a clickable Chakra Icon to IconButton too nitpicky for this PR and prefers to keep the current Icon-based trigger; such minor a11y/UI nitpicks should be deferred to a follow-up if needed.
Applied to files:
src/pages/Yields/components/YieldActionModal.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} : Use Chakra UI components and conventions
Applied to files:
src/pages/Yields/components/YieldActionModal.tsx
📚 Learning: 2025-10-07T03:44:27.350Z
Learnt from: 0xApotheosis
Repo: shapeshift/web PR: 10760
File: src/components/ManageHiddenAssets/ManageHiddenAssetsList.tsx:78-84
Timestamp: 2025-10-07T03:44:27.350Z
Learning: In the ShapeShift web codebase, the following are stable references and do not need to be included in useCallback/useMemo dependency arrays:
- `navigate` from `useBrowserRouter()` hook
- Modal control objects (like `walletDrawer`) from `useModal()` hook (including their `isOpen`, `close`, and `open` methods)
- These are backed by stable context providers
Applied to files:
src/pages/Yields/components/YieldActionModal.tsx
📚 Learning: 2025-11-24T21:20:44.637Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-11-24T21:20:44.637Z
Learning: Applies to **/*.{jsx,tsx} : EXTRACT complex logic into custom hooks
Applied to files:
src/pages/Yields/components/YieldActionModal.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} : 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
Applied to files:
src/pages/Yields/components/YieldActionModal.tsx
📚 Learning: 2025-11-24T21:20:44.637Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-11-24T21:20:44.637Z
Learning: Applies to **/*.{jsx,tsx} : 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
Applied to files:
src/pages/Yields/components/YieldActionModal.tsx
📚 Learning: 2025-11-24T21:20:44.637Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-11-24T21:20:44.637Z
Learning: Applies to **/*.{jsx,tsx} : ALWAYS use `useMemo` for conditional values and simple transformations
Applied to files:
src/pages/Yields/components/YieldActionModal.tsx
📚 Learning: 2025-09-16T09:32:21.333Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10490
File: src/components/Layout/Header/NavBar/NavigationDropdown.tsx:96-103
Timestamp: 2025-09-16T09:32:21.333Z
Learning: In the shapeshift/web codebase, gomesalexandre confirms that using `item.icon && <Icon as={item.icon} boxSize={4} />` for Chakra UI MenuItem.icon prop is valid and acceptable - the boolean short-circuit pattern works fine with Chakra components and doesn't need to be changed to explicit undefined.
Applied to files:
src/pages/Yields/components/YieldActionModal.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} : Use `useAppSelector` for Redux state
Applied to files:
src/pages/Yields/components/YieldActionModal.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 src/state/slices/**/*.ts : Export selectors from slice using inline `selectors` property
Applied to files:
src/pages/Yields/components/YieldActionModal.tsx
📚 Learning: 2025-10-17T07:53:40.088Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10783
File: src/components/Modals/Snaps/Snaps.tsx:36-38
Timestamp: 2025-10-17T07:53:40.088Z
Learning: Chakra UI's ModalContent component supports the containerProps prop, which accepts an object with sx and other styling properties. When using the modal stack manager's useModalRegistration hook, spreading {...modalContentProps} into ModalContent is the correct approach, as modalContentProps contains { containerProps: { sx: { zIndex, pointerEvents } } }. Do not suggest extracting sx from modalContentProps.containerProps.
Applied to files:
src/pages/Yields/components/YieldActionModal.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} : Account for light/dark mode using `useColorModeValue` hook
Applied to files:
src/pages/Yields/components/YieldActionModal.tsx
📚 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:
src/pages/Yields/components/YieldActionModal.tsx
📚 Learning: 2025-08-06T09:47:29.865Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10191
File: src/pages/Explore/Explore.tsx:174-178
Timestamp: 2025-08-06T09:47:29.865Z
Learning: In src/pages/Explore/Explore.tsx, NeOMakinG prefers keeping complex height calculations inline rather than extracting them to useMemo, prioritizing perceived performance/execution speed over code readability, even when the calculation would only run when the dependency (isSearching) changes.
Applied to files:
src/pages/Yields/components/YieldActionModal.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/YieldActionModal.tsx
📚 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:
src/pages/Yields/components/YieldActionModal.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/YieldActionModal.tsx
🧬 Code graph analysis (2)
src/components/MultiHopTrade/components/Earn/EarnConfirm.tsx (11)
src/state/store.ts (1)
useAppSelector(145-145)src/state/slices/tradeEarnInputSlice/selectors.ts (1)
selectSelectedYieldId(33-36)src/lib/yieldxyz/constants.ts (1)
DEFAULT_NATIVE_VALIDATOR_BY_CHAIN_ID(91-93)src/pages/Yields/hooks/useYieldTransactionFlow.ts (1)
useYieldTransactionFlow(152-843)src/lib/yieldxyz/utils.ts (1)
getTransactionButtonText(54-75)src/components/MultiHopTrade/components/SharedConfirm/SharedConfirm.tsx (1)
SharedConfirm(23-58)src/pages/Yields/components/YieldSuccess.tsx (1)
YieldSuccess(28-139)src/pages/Yields/components/YieldAssetFlow.tsx (1)
YieldAssetFlow(13-76)src/components/Amount/Amount.tsx (1)
Amount(21-42)src/pages/Yields/components/GradientApy.tsx (1)
GradientApy(9-20)src/pages/Yields/components/TransactionStepsList.tsx (1)
TransactionStepsList(40-113)
src/pages/Yields/components/YieldActionModal.tsx (11)
src/lib/yieldxyz/utils.ts (1)
getTransactionButtonText(54-75)src/pages/Yields/components/YieldAssetFlow.tsx (1)
YieldAssetFlow(13-76)src/components/Text/Text.tsx (1)
Text(19-83)src/components/Amount/Amount.tsx (1)
Amount(21-42)src/pages/Yields/components/GradientApy.tsx (1)
GradientApy(9-20)src/pages/Yields/components/TransactionStepsList.tsx (1)
TransactionStepsList(40-113)src/pages/Yields/components/YieldSuccess.tsx (1)
YieldSuccess(28-139)src/components/Modal/components/Dialog.tsx (1)
Dialog(150-150)src/components/Modal/components/DialogHeader.tsx (1)
DialogHeader(15-48)src/components/Modal/components/DialogCloseButton.tsx (1)
DialogCloseButton(15-41)src/components/Modal/components/DialogFooter.tsx (1)
DialogFooter(9-15)
⏰ 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 (7)
src/pages/Yields/components/YieldActionModal.tsx (2)
371-390: Dialog structure and state management look solid.The Dialog structure properly handles:
- Preventing overlay close during submission
- Disabling close button while submitting
- Conditional rendering based on modal step
410-425: Duplicate close button in success state.The
YieldSuccesscomponent (rendered viasuccessContenton line 389) already includes a close button that callsonDone(which ishandleClose). ThisDialogFooterrenders a second close button, resulting in duplicate close buttons in the success UI.This contradicts PR objective
#11650: "Remove duplicate close buttons in success UI flows."Suggested fix: Remove the duplicate footer
{isInProgress && ( <DialogFooter borderTop='1px solid' borderColor='border.base' pt={4} pb={4}> <Button colorScheme='blue' size='lg' width='full' height='56px' fontSize='lg' fontWeight='semibold' borderRadius='xl' isDisabled={isButtonDisabled} isLoading={isButtonLoading} loadingText={loadingText} onClick={handleConfirm} > {buttonText} </Button> </DialogFooter> )} - {isSuccess && ( - <DialogFooter borderTop='1px solid' borderColor='border.base' pt={4} pb={4}> - <Button - colorScheme='blue' - size='lg' - width='full' - height='56px' - fontSize='lg' - fontWeight='semibold' - borderRadius='xl' - onClick={handleClose} - > - {translate('common.close')} - </Button> - </DialogFooter> - )} </Dialog>⛔ Skipped due to learnings
Learnt from: NeOMakinG Repo: shapeshift/web PR: 10323 File: src/components/Modal/components/DialogCloseButton.tsx:29-37 Timestamp: 2025-08-27T09:47:59.394Z Learning: In shapeshift/web, for DialogCloseButton.tsx, the onClick handler must remain on Drawer.Close (not moved to IconButton with asChild) because stopPropagation() needs to be called at the Drawer.Close level to properly handle drawer closing behavior; moving event handling to the child IconButton would break the event flow that Drawer.Close expects.Learnt from: premiumjibles Repo: shapeshift/web PR: 10361 File: src/pages/Markets/components/CardWithSparkline.tsx:83-92 Timestamp: 2025-08-25T23:32:13.876Z Learning: In shapeshift/web PR `#10361`, premiumjibles considered the nested button accessibility issue (ChartErrorFallback retry Button inside Card rendered as Button in CardWithSparkline.tsx) out of scope for the error boundaries feature PR, consistent with deferring minor a11y improvements to follow-up PRs.src/components/MultiHopTrade/components/Earn/EarnConfirm.tsx (5)
77-92: Well-structured validator selection with appropriate fallback chain.The logic correctly prioritizes: default validator by chain → preferred validator → first available validator. Dependencies are complete.
145-170: Loading states and button text logic are well-implemented.The alignment with
YieldEnterModalpatterns and the comprehensive fallback chain forconfirmButtonTextprovide consistent UX. ThestepsToShowpattern correctly switches betweendisplaySteps(pre-execution) andtransactionSteps(during execution).
326-338: Footer implementation follows established patterns.The button correctly combines:
isLoadingfor spinner during submission or quote fetchingisDisabledwhen submission isn't possible or data is loading- Dynamic
confirmButtonTextbased on current transaction step
65-69: The selector usage is correct. The patternselectAccountIdByAccountNumberAndChainId(state)[0]?.[yieldChainId]properly accesses account number 0's mapping by chain ID, matching the selector's return type ofPartialRecord<number, PartialRecord<ChainId, AccountId>>. This consistent usage across the codebase confirms the implementation is sound.
35-35: The type assertion{} as AugmentedYieldDtois safe in this context. WhenselectedYieldis undefined, the empty object is passed withisOpen: Boolean(selectedYield)set to false. The hook'suseQueryis gated withenabled: ... && isOpen(line 273 of useYieldTransactionFlow), which prevents any API calls or property access on the empty object when the guard is false. Refactoring to passundefinedand makingyieldItemoptional would require conditional logic that violates React's Rules of Hooks. This pattern is intentional and correct.Likely an incorrect or invalid review comment.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
- Fix YieldSelector modal to show ShapeShift DAO for Cosmos native staking - Add earningsPerYear interpolated translation for proper i18n support - Fix rewardsSchedule translation to include "every" (e.g., "every epoch") - Add ShapeShift DAO fallback to YieldActionModal for consistency - Remove redundant "Earn with" section from EarnFooter - Clean up unused imports and props Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…bbitai - YieldItem now fetches validators via react-query for staking yields - Shows default/preferred validator name in modal (e.g., Luganodes for Solana) - Validators are cached by react-query, so subsequent renders are instant Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…detail pages - Add "Native Staking" title for all native staking yields (ATOM, SOL, etc.) - Show ShapeShift DAO for Cosmos, Figment for Solana native staking - Use provider info (from yieldProviders) for non-native staking yields - Fix yield cards showing wrong provider name (e.g., "Stakekit" instead of "Morpho") - Add titleOverride prop to YieldHero and YieldItem for consistent naming - Add Figment validator constants for Solana @coderabbitai - Addressed your comments: polling completion now properly handles undefined tx (returns false instead of true), and display info now correctly uses yieldProviders for non-native-staking yields. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use selectHasUserEnteredAmount from base selectors instead of maintaining a duplicate wrapper selector that performs identical logic. @coderabbitai - Addressed your comment about duplicate selector. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this 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 `@src/pages/Yields/YieldDetail.tsx`:
- Line 25: The file defines a duplicate constant SHAPESHIFT_VALIDATOR_NAME;
remove the local const and import the existing exported
SHAPESHIFT_VALIDATOR_NAME from '@/lib/yieldxyz/constants.ts' instead (update
YieldDetail.tsx imports and remove the local declaration), ensuring all
references in YieldDetail.tsx use the imported symbol to maintain a single
source of truth.
♻️ Duplicate comments (2)
src/pages/Yields/YieldDetail.tsx (1)
122-131: Renameusdkey to reflect user currency denomination.The value at line 128 is calculated in user currency (
totalUsd.times(userCurrencyToUsdRate)), but the return keyusdis misleading. Rename it touserCurrencyto accurately reflect the denomination.🔧 Suggested fix
return { - usd: totalUsd.times(userCurrencyToUsdRate).toFixed(), + userCurrency: totalUsd.times(userCurrencyToUsdRate).toFixed(), crypto: totalCrypto.toFixed(), } - }, [balances, selectedValidatorAddress, userCurrencyToUsdRate]) + }, [balances, selectedValidatorAddress, userCurrencyToUsdRate])Then update the usage at line 185:
- userBalanceUsd={userBalances.usd} + userBalanceUsd={userBalances.userCurrency}src/components/MultiHopTrade/components/Earn/EarnConfirm.tsx (1)
186-200: Remove unusedisLoadingprop fromSharedConfirmcalls.The
isLoadingprop is passed toSharedConfirmin multiple places (lines 196, 219, 347) but was flagged in a previous review as unused in theSharedConfirmcomponent implementation.Also applies to: 219-219, 344-350
🧹 Nitpick comments (14)
src/pages/Yields/components/YieldActionModal.tsx (2)
60-89: Consider destructuringmanageActionTypeandaccountIddirectly.The rest spread
...propsonly containsmanageActionTypeandaccountId, which are then accessed viaprops.manageActionTypeandprops.accountId. Destructuring them directly would be cleaner and more explicit.♻️ Suggested refactor
validatorLogoURI, passthrough, - ...props -}: YieldActionModalProps) { + manageActionType, + accountId, +}: YieldActionModalProps) { const translate = useTranslate() const { ... } = useYieldTransactionFlow({ ... - manageActionType: props.manageActionType, - accountId: props.accountId, + manageActionType, + accountId, })
348-351: Redundant null check onvaultMetadata.The
vaultMetadatauseMemo (lines 107-119) always returns an object - it never returnsnullorundefined. The conditional check is unnecessary.♻️ Suggested simplification
const successProviderInfo = useMemo( - () => (vaultMetadata ? { name: vaultMetadata.name, logoURI: vaultMetadata.logoURI } : null), + () => ({ name: vaultMetadata.name, logoURI: vaultMetadata.logoURI }), [vaultMetadata], )src/pages/Yields/YieldAssetDetails.tsx (1)
447-456: The eslint-disable comment is justified but could be more specific.The comment explains that
sortedRowsis needed to trigger re-memoization when filtered data changes since the table ref is stable. This is a valid reason to include it in the dependency array despite eslint's warning.However, consider if
filteredYieldswould be a more direct dependency since that's what actually changes.Consider using filteredYields instead
const listViewElement = useMemo( () => ( <Box borderWidth='1px' borderRadius='xl' overflow='hidden'> <YieldTable table={table} isLoading={false} onRowClick={handleRowClick} /> </Box> ), - // sortedRows needed to trigger re-memoization when filtered data changes (table ref is stable) - // eslint-disable-next-line react-hooks/exhaustive-deps - [handleRowClick, sortedRows, table], + [handleRowClick, filteredYields, table], )src/pages/Yields/components/YieldsList.tsx (2)
156-189:getYieldDisplayInfohelper is duplicated from YieldAssetDetails.tsx.This helper function has identical logic to the one in
YieldAssetDetails.tsx. Consider extracting it to a shared utility to avoid duplication and ensure consistent behavior.Consider extracting to a shared utility
Create a shared utility in
src/pages/Yields/utils/getYieldDisplayInfo.ts:import type { AugmentedYieldDto } from '@/lib/yieldxyz/types' import { COSMOS_ATOM_NATIVE_STAKING_YIELD_ID, FIGMENT_VALIDATOR_LOGO, FIGMENT_VALIDATOR_NAME, SHAPESHIFT_VALIDATOR_LOGO, SHAPESHIFT_VALIDATOR_NAME, SOLANA_SOL_NATIVE_MULTIVALIDATOR_STAKING_YIELD_ID, } from '@/lib/yieldxyz/constants' export const getYieldDisplayInfo = ( yieldItem: AugmentedYieldDto, yieldProviders: Record<string, { name?: string; logoURI?: string }> | undefined, translate: (key: string) => string, ) => { // ... shared logic }Then import and use in both components.
670-755: Consider extracting repeated YieldItem rendering logic.The grid and list elements have very similar rendering patterns for both
isMyOpportunitiesand regular views. While not blocking, extracting common rendering logic could reduce code duplication.Based on learnings, this is a recommended refactor that can be deferred to a follow-up PR to keep the current scope focused.
Also applies to: 757-883
src/pages/Yields/components/YieldManager.tsx (3)
28-29: Unsafe type assertion foractionparameter.The cast
as 'enter' | 'exit' | 'claim' | undefineddoesn't validate the actual value. If the URL contains an unexpected value (e.g.,?action=invalid), it will pass through as-is and may cause unexpected behavior downstream inYieldForm.♻️ Suggested fix with validation
- const action = searchParams.get('action') as 'enter' | 'exit' | 'claim' | undefined + const actionParam = searchParams.get('action') + const action = useMemo(() => { + const validActions = ['enter', 'exit', 'claim'] as const + return validActions.includes(actionParam as typeof validActions[number]) + ? (actionParam as 'enter' | 'exit' | 'claim') + : undefined + }, [actionParam])
33-45: Fragile string pattern matching for Solana native staking detection.The condition
yieldId?.includes('solana') && yieldId?.includes('native')on line 38 is brittle and could match unintended yield IDs. Consider using a more explicit check or a dedicated constant/utility.♻️ Suggested improvement
+const SOLANA_NATIVE_YIELD_ID_PATTERN = /^solana-.*-native/ + const validatorAddress = useMemo(() => { // For native staking with hardcoded defaults, always use the default validator (ignore URL param) if ( yieldId === COSMOS_ATOM_NATIVE_STAKING_YIELD_ID || - yieldId === SOLANA_SOL_NATIVE_MULTIVALIDATOR_STAKING_YIELD_ID || - (yieldId?.includes('solana') && yieldId?.includes('native')) + (yieldId && SOLANA_NATIVE_YIELD_ID_PATTERN.test(yieldId)) ) { return yieldItem?.chainId ? DEFAULT_NATIVE_VALIDATOR_BY_CHAIN_ID[yieldItem.chainId] : undefined } return validatorParam }, [yieldId, yieldItem?.chainId, validatorParam])
73-96: Inline arrow functions create new references on every render.The
onCloseandonClickhandlers create new function instances on each render. While the Dialog component may not be performance-critical, memoizing these callbacks aligns with project guidelines and prevents unnecessary re-renders of child components.♻️ Suggested improvement
+ const handleClose = useCallback(() => navigate(-1), [navigate]) + return ( - <Dialog isOpen={true} onClose={() => navigate(-1)} isFullScreen> + <Dialog isOpen={true} onClose={handleClose} isFullScreen> <DialogHeader> <DialogHeader.Left>{null}</DialogHeader.Left> <DialogHeader.Middle> <DialogTitle>{title}</DialogTitle> </DialogHeader.Middle> <DialogHeader.Right> - <DialogCloseButton onClick={() => navigate(-1)} /> + <DialogCloseButton onClick={handleClose} /> </DialogHeader.Right> </DialogHeader> <DialogBody py={0} px={4} flex={1}> <YieldForm yieldItem={yieldItem} balances={balances} action={action ?? 'enter'} validatorAddress={validatorAddress} accountNumber={accountNumber} - onClose={() => navigate(-1)} - onDone={() => navigate(-1)} + onClose={handleClose} + onDone={handleClose} /> </DialogBody> </Dialog> )src/lib/yieldxyz/constants.ts (1)
64-66: Inconsistent APR constant types and values.
COSMOS_SHAPESHIFT_FALLBACK_APRis a string'0.1425'(14.25%), while the newCOSMOS_NETWORK_FALLBACK_APRis a number0.15(15%). The different types and values could cause confusion when choosing which constant to use. Consider documenting the intended use case for each or consolidating them.src/pages/Yields/components/YieldStats.tsx (1)
50-60: Duplicate validator selection logic across components.This native staking validator selection logic is duplicated in
YieldManager.tsx(lines 35-44) andYieldDetail.tsx(lines 45-55). Consider extracting this into a shared utility function or custom hook to ensure consistency and reduce maintenance burden.♻️ Suggested extraction to a shared utility
Create a utility in
src/lib/yieldxyz/utils.ts:export const getEffectiveValidatorAddress = ( yieldId: string | undefined, chainId: ChainId | undefined, validatorParam: string | null | undefined, defaultValidator: string | undefined, ): string | undefined => { if ( yieldId === COSMOS_ATOM_NATIVE_STAKING_YIELD_ID || yieldId === SOLANA_SOL_NATIVE_MULTIVALIDATOR_STAKING_YIELD_ID || (yieldId?.includes('solana') && yieldId?.includes('native')) ) { return chainId ? DEFAULT_NATIVE_VALIDATOR_BY_CHAIN_ID[chainId] : undefined } return validatorParam ?? defaultValidator }src/components/MultiHopTrade/components/Earn/components/YieldSelector.tsx (2)
49-50: Consolidate similar type-checking helpers.
isNativeStaking(line 49) andisStakingType(line 156) have overlapping logic but different definitions. This could lead to inconsistent behavior. Consider consolidating into a single helper or clearly documenting their different purposes.♻️ Suggested consolidation
-const isNativeStaking = (type: string | undefined): boolean => - ['native-staking', 'staking'].includes(type ?? '') - -const isStakingType = (type: string | undefined): boolean => - ['native-staking', 'pooled-staking', 'staking'].includes(type ?? '') +const NATIVE_STAKING_TYPES = ['native-staking', 'staking'] as const +const ALL_STAKING_TYPES = ['native-staking', 'pooled-staking', 'staking'] as const + +const isNativeStaking = (type: string | undefined): boolean => + NATIVE_STAKING_TYPES.includes(type as typeof NATIVE_STAKING_TYPES[number]) + +const isStakingType = (type: string | undefined): boolean => + ALL_STAKING_TYPES.includes(type as typeof ALL_STAKING_TYPES[number])Also applies to: 156-157
140-141: Extract hardcoded fallback image URLs to constants.The fallback image URL
'https://assets.coingecko.com/coins/images/279/small/ethereum.png'is duplicated on lines 140 and 273. Extract this to a constant for maintainability.♻️ Suggested fix
+const FALLBACK_TOKEN_IMAGE = 'https://assets.coingecko.com/coins/images/279/small/ethereum.png' + // In YieldItem component: <Image src={displayInfo.logoURI} alt={displayInfo.name} boxSize='40px' borderRadius='full' - fallbackSrc='https://assets.coingecko.com/coins/images/279/small/ethereum.png' + fallbackSrc={FALLBACK_TOKEN_IMAGE} /> // In YieldSelector component: <Image src={selectedDisplayInfo.logoURI} alt={selectedDisplayInfo.name} boxSize='32px' borderRadius='full' - fallbackSrc='https://assets.coingecko.com/coins/images/279/small/ethereum.png' + fallbackSrc={FALLBACK_TOKEN_IMAGE} />Also applies to: 273-274
src/components/MultiHopTrade/components/Earn/components/EarnFooter.tsx (1)
33-39: Type mismatch:statsBoxSxis typed asFlexPropsbut applied to aBoxcomponent.The
statsBoxSxconstant is typed asFlexPropsbut is spread onto aBoxcomponent (line 196). This should be typed asBoxPropsfor correctness.Suggested fix
-const statsBoxSx: FlexProps = { +const statsBoxSx = { bg: 'background.surface.raised.base', borderRadius: 'lg', p: 3, borderWidth: '1px', borderColor: 'border.base', }src/components/MultiHopTrade/components/Earn/EarnInput.tsx (1)
242-250: Consider logging JSON parse failures for debugging.The
catchblock silently swallows parse errors when extracting gas data. Adding aconsole.errorwould help debug issues with malformedgasEstimatedata.Suggested fix
try { const gasData = JSON.parse(tx.gasEstimate) return acc.plus(bnOrZero(gasData.amount)) } catch { + console.error('Failed to parse gasEstimate:', tx.gasEstimate) return acc }
- Remove unused isLoading prop from SharedConfirm component and call sites - Use relative path 'confirm' for EarnRoutePaths.Confirm (matches TradeRoutePaths pattern) - Import SHAPESHIFT_VALIDATOR_NAME from constants instead of duplicating - Rename userBalances.usd to userBalances.userCurrency for clarity @coderabbitai - Addressed remaining review comments. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace fragile string parsing on metadata.name with useYieldProviders() hook to properly map providerId to provider data. Also add Figment validator fallback for Solana native staking. @coderabbitai - Addressed comment about using providerId with provider mapping. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use availableBalanceUserCurrency instead of userBalanceUsd for recommended yields (user has no position yet, only wallet balance to stake) - Use input token symbol (ETH) instead of output token symbol (stETH) for title consistency across all yield cards Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…from" to "Enter from" - Convert YieldSelector from Chakra Modal to Dialog pattern for responsive behavior (drawer on mobile, modal on desktop) - Change sell asset dialog title from "Trade from" to "Enter from" in Earn tab - Add "earn.enterFrom" translation key Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
NeOMakinG
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review Summary
3 maybe blocking blocking, 8 suggestions, 4 nitpicks
Big PR consolidating yield improvements. Behind feature flags so safe to ship, but worth addressing these before enabling.
Blocking Issues
- Missing Error Boundary on EarnTab (TradeTab has TradingErrorBoundary)
- Unsafe type assertion
{} as AugmentedYieldDtoin EarnConfirm - Custom poll function without cancellation support (potential memory leak)
Key Suggestions
- Duplicate selector
selectEarnHasUserEnteredAmount- use existingselectHasUserEnteredAmount SHAPESHIFT_VALIDATOR_NAMEduplicated in 3 files - import from constants.ts- useEffect syncing state in useYieldFilters - could use useMemo instead
- Manual base unit conversion - use toBaseUnit from @/lib/math
- Several accessibility improvements needed on clickable elements
Nitpicks
- Magic numbers should be constants (debounce 500ms, etc.)
- Initial state inconsistency (
''vs'0'for sellAmountCryptoPrecision)
Runtime test:
https://jam.dev/c/2c3d22ee-4d13-44bf-95b3-a46208775f56
- Can't deposit SOL into kamino and another provider with "cannot get quote" error, one worked thought
- Withdrawing atom from a position but closing the modal is changing the action center element to "success" but the page isn't getting balances/status updates
- The position detail page is weird on desktop, all centered, it's not desktop friendly but looks more like a mobile layout
- Global "earn" view is not kept between navigations, this means if a user is staking some assets then coming page to this page he is going to be forced to click on "earn" again
- Provider selection on the swapper route earn tab should use a drawer instead of a modal (see mobile testing at 4:35) in the screen record)
- I've ended up in a state where the "deposit" button was under the menu bar, we need to add the menu height safe area at the bottom of this view because it's preventing me from depositing
Happy to stamp for the sake of progression, but we need to tackle those few bugs if its not done after this review already considering the current state 🙏
- Add TradingErrorBoundary to EarnTab for error handling
- Make useYieldTransactionFlow accept undefined yieldItem (removes unsafe {} as cast)
- Consolidate duplicate handleBack/handleClose in EarnConfirm
- Extract debounce magic number to SELL_AMOUNT_DEBOUNCE_MS constant
- Inline chainIdFilterPredicate in modal open call
- Restore isLoading optional prop in SharedConfirmProps for backwards compatibility
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
🤖 Fix all issues with AI agents
In `@src/components/MultiHopTrade/components/Earn/components/YieldSelector.tsx`:
- Around line 133-139: The Image components in YieldSelector (the JSX Image
element rendering displayInfo.logoURI with fallbackSrc set to a CoinGecko URL)
should use a first‑party/local fallback asset instead of the external CoinGecko
URL; import a local fallback icon (e.g., assets/images/token-fallback.png or
assets/icons/ethereum.png) at the top of the file and replace
fallbackSrc='https://assets.coingecko.com/coins/images/279/small/ethereum.png'
with fallbackSrc={tokenFallbackIcon}, and make the same change for the other
Image occurrence in this file so both fallback paths use the bundled asset.
In `@src/components/MultiHopTrade/components/Earn/EarnInput.tsx`:
- Around line 133-140: The path builder in the useEffect of EarnInput.tsx
currently encodes selectedYieldId but not sellAsset.assetId, so CAIP-19 assetIds
with “/” will break routing; update the navigate call in the useEffect (the code
that constructs `/earn/${sellAsset.assetId}/${encodedYieldId}/${baseUnit}`) to
encode the asset id as well (e.g. use encodeURIComponent on sellAsset.assetId)
so both path segments are URL-safe before calling navigate.
- Around line 431-438: The placeholder for SellAssetInput is hardcoded to
'$0.00' when isInputtingFiatSellAmount is true; change it to be currency-aware
or fall back to a neutral '0'. Update the placeholder prop on SellAssetInput
(the conditional using isInputtingFiatSellAmount) to use the user's fiat
currency formatter (e.g., formatCurrency(userCurrency, 0) or a locale-aware
Intl.NumberFormat call) or simply return '0' instead of the hardcoded USD string
so the UI reflects the correct currency.
- Around line 191-213: The txArguments memo can include validatorAddress:
undefined when the yield mechanics require it; update the useMemo for
txArguments so that when fieldNames.has('validatorAddress') you resolve const
validator = selectedValidatorAddress ??
DEFAULT_NATIVE_VALIDATOR_BY_CHAIN_ID[yieldChainId] and if validator is falsy
return null (or otherwise abort building args) instead of assigning undefined,
otherwise assign args.validatorAddress = validator; keep the rest of the
argument logic intact and ensure the dependency list still includes
selectedValidatorAddress and yieldChainId.
- Around line 121-129: In the useEffect inside EarnInput (the block that
computes amountCryptoPrecision using bnOrZero(...).div(...).toString()), replace
the final .toString() call with .toFixed() so the computed amountCryptoPrecision
string never uses exponential notation; update the expression in the effect that
assigns amountCryptoPrecision and keep the rest of the dispatch call to
tradeEarnInput.actions.setSellAmountCryptoPrecision unchanged.
🧹 Nitpick comments (4)
src/pages/Yields/components/YieldsList.tsx (1)
168-177: Broad string matching may catch unintended yields.The condition
yieldItem.id.includes('solana') && yieldItem.id.includes('native')could match future yields that contain both substrings but aren't the Figment multivalidator staking yield. Consider using a more specific check or adding this ID to the constants if it's a known pattern.src/pages/Yields/YieldDetail.tsx (2)
95-123: Consider combining reduce operations for cleaner code.The balance aggregation iterates over the same array twice (lines 107-112 and 114-117). For a 4-element array, the performance impact is negligible, but combining into a single reduce would be slightly cleaner:
♻️ Optional refactor
- const totalCrypto = [ - activeBalance, - enteringBalance, - exitingBalance, - withdrawableBalance, - ].reduce((sum, b) => sum.plus(bnOrZero(b?.aggregatedAmount)), bnOrZero(0)) - - const totalUsd = [activeBalance, enteringBalance, exitingBalance, withdrawableBalance].reduce( - (sum, b) => sum.plus(bnOrZero(b?.aggregatedAmountUsd)), - bnOrZero(0), - ) + const balanceArray = [activeBalance, enteringBalance, exitingBalance, withdrawableBalance] + const { totalCrypto, totalUsd } = balanceArray.reduce( + (acc, b) => ({ + totalCrypto: acc.totalCrypto.plus(bnOrZero(b?.aggregatedAmount)), + totalUsd: acc.totalUsd.plus(bnOrZero(b?.aggregatedAmountUsd)), + }), + { totalCrypto: bnOrZero(0), totalUsd: bnOrZero(0) }, + )
48-58: The pattern is intentional and used consistently for extensibility.The
yieldId?.includes('solana') && yieldId?.includes('native')check in line 53 is a secondary guard that appears in five other locations across the Yields feature (YieldAssetDetails, YieldManager, YieldStats, YieldsList), always paired with the explicitSOLANA_SOL_NATIVE_MULTIVALIDATOR_STAKING_YIELD_IDcheck. Currently, only one Solana native staking yield ID exists ('solana-sol-native-multivalidator-staking'), so the pattern serves as future-proofing for additional Solana native staking variants while remaining specific enough to avoid false matches.However, for maintainability, consider extracting this pattern into a helper function (e.g.,
isNativeSolanaStaking(yieldId)) to make the intent explicit and centralize the logic. This would also make future yield ID changes easier to track.src/components/MultiHopTrade/components/Earn/components/YieldSelector.tsx (1)
93-117: Potential query fan-out:useYieldValidators()per YieldItem.
If a page can list many validator-required yields, this can trigger many validator fetches at once. Consider gating with dialog open state (or only fetching validators for the selected yield) if this shows up in profiling.
src/components/MultiHopTrade/components/Earn/components/YieldSelector.tsx
Outdated
Show resolved
Hide resolved
- useYieldFilters: replace useState+useEffect with useMemo for sorting state
- useYieldTransactionFlow: use toBaseUnit from @/lib/math instead of manual conversion
- EarnInput: use fromBaseUnit from @/lib/math for base unit conversion
- tradeEarnInputSlice: fix initial state consistency ('' -> '0')
- YieldEnterModal/YieldForm: add accessibility attrs to fiat toggle (role, tabIndex, aria-label, keyboard support)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove duplicate constant definition from YieldForm and YieldEnterModal, import from @/lib/yieldxyz/constants instead. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this 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/YieldEnterModal.tsx`:
- Around line 72-77: The type declaration CryptoAmountInputProps uses
React.ChangeEvent<HTMLInputElement> but the React namespace isn't imported; fix
by importing the appropriate symbol from React (either add "import React from
'react'" or import the specific type like "import { ChangeEvent } from 'react'")
and update CryptoAmountInputProps to use the imported type (e.g., onChange?: (e:
ChangeEvent<HTMLInputElement>) => void) so TypeScript compiles correctly.
♻️ Duplicate comments (1)
src/components/MultiHopTrade/components/Earn/EarnInput.tsx (1)
203-206: Potential undefinedvalidatorAddresswhen field is required.When
fieldNames.has('validatorAddress')is true but neitherselectedValidatorAddressnorDEFAULT_NATIVE_VALIDATOR_BY_CHAIN_ID[yieldChainId]exists (for chains other than Cosmos/Solana),args.validatorAddresswill beundefined. This could cause API errors or unexpected behavior.Proposed fix
if (fieldNames.has('validatorAddress') && yieldChainId) { - args.validatorAddress = - selectedValidatorAddress || DEFAULT_NATIVE_VALIDATOR_BY_CHAIN_ID[yieldChainId] + const validatorAddress = + selectedValidatorAddress ?? DEFAULT_NATIVE_VALIDATOR_BY_CHAIN_ID[yieldChainId] + if (!validatorAddress) return null + args.validatorAddress = validatorAddress }
🧹 Nitpick comments (4)
src/pages/Yields/components/YieldForm.tsx (1)
294-300: Consider using string literals for BigNumber multiplication.Per project learnings, floating point literals should be passed as strings to BigNumber methods to maintain precision.
Suggested change
const fiatAmount = useMemo( - () => bnOrZero(cryptoAmount).times(marketData?.price ?? 0), + () => bnOrZero(cryptoAmount).times(marketData?.price ?? '0'), [cryptoAmount, marketData?.price], )Similar pattern applies to lines 303, 308.
src/pages/Yields/components/YieldEnterModal.tsx (2)
209-225: Consider using string literals for BigNumber operations.Per project learnings, floating point literals should be passed as strings to maintain precision.
Suggested change
const fiatAmount = useMemo( - () => bnOrZero(cryptoAmount).times(marketData?.price ?? 0), + () => bnOrZero(cryptoAmount).times(marketData?.price ?? '0'), [cryptoAmount, marketData?.price], ) // Similar for estimatedYearlyEarningsFiat
46-105: Significant code duplication with YieldForm.tsx.The
CryptoAmountInputProps,CryptoAmountInput,YieldEnterModalSkeleton,INPUT_LENGTH_BREAKPOINTS,getInputFontSize,PRESET_PERCENTAGES, andSHAPESHIFT_VALIDATOR_NAMEconstants are duplicated between this file andYieldForm.tsx. Consider extracting these to a shared module to reduce maintenance burden.This is a follow-up improvement that can be addressed separately from this PR to keep scope focused.
src/components/MultiHopTrade/components/Earn/EarnInput.tsx (1)
432-432: Minor: Hardcoded$0.00placeholder for fiat input.The
$0.00placeholder assumes USD. For non-USD user currencies, consider using a currency-aware formatter or a neutral'0'placeholder.
The yield.xyz API returns Solana transactions as base64-encoded strings (following Solana conventions), but the code was trying to decode them as hex, causing deserialization failures. Use isHex from viem to detect encoding format - if hex use hex decoding, otherwise use base64 (Solana convention). Fixes "cannot get quote" error when depositing SOL into Kamino and other Solana-based yield providers. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
013179d to
9e8f42c
Compare
- Add SOLANA_YIELD_COMPUTE_UNIT_MARGIN_MULTIPLIER (1.6) constant - Apply safety margin to estimated compute units (same as Jupiter swapper) - Remove broken STAKE_COMPUTE_UNIT_BUFFER static minimum approach Fixes "Computational budget exceeded" error when depositing SOL into Kamino and other Solana yield providers. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Display each exiting balance as separate row with completion date - Use dayjs relative time for "available in X days" countdown - Invalidate yield queries when transactions complete in background - Add yieldXYZ.unstaking and yieldXYZ.availableDate translations - Align unstaking/claimable sections consistently (badge top, action below) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
gm https://jam.dev/c/cc0b92e2-098e-49a3-87c7-1cceff01ded0
This one is expected since Cosmos SDK has a cooldown of sorts, balance will be the same, though unstaking should update, paranoia updated balances invalidation for claims here and confirmed worky. Also aligned visually with old DeFi opportunity:
https://jam.dev/c/a55f052b-6116-424d-8561-23c62a1fdc9b
Expected for now and will need some @reallybeard / @NeOMakinG goodness before - will let you guys know when in a good place to visually improve bits i.e v. v. soon
It's working if using back/forth browser nav which I believe is good enough for now! https://jam.dev/c/288a661f-baed-4407-80bb-e7b80a53981b
Ditto realm of neo-beard-y oil ⛽
Already tackled! Great minds ser
|
There was a problem hiding this 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 `@src/lib/yieldxyz/constants.ts`:
- Around line 58-61: Replace numeric JS floats used as exported constants with
string literals so downstream BigNumber math receives string inputs;
specifically change SOLANA_YIELD_COMPUTE_UNIT_MARGIN_MULTIPLIER and the other
APR/multiplier constants in this file (the constants around the 70-90 range)
from numeric values like 1.6 or 0.15 to string values like "1.6" or "0.15", and
ensure any usages that pass these into bnOrZero(...).times(...) or similar
BigNumber operations use the exported string constants directly.
In `@src/pages/Yields/components/YieldForm.tsx`:
- Around line 357-367: handleFormDone currently removes quote queries using the
wrong key variable (action) causing stale cache entries when
useYieldTransactionFlow maps actions to flowAction; update the removeQueries
call to use flowAction instead of action in the queryKey (['yieldxyz','quote',
flowAction, yieldItem.id]) and also add flowAction to the useCallback dependency
array so the closure invalidation is correct.
♻️ Duplicate comments (1)
src/pages/Yields/components/YieldEnterModal.tsx (1)
72-77: Fix TS type:React.ChangeEventis referenced without importingReact.
This will fail type-checking in builds that don’t have the React namespace types globally available.Proposed fix
-import { memo, useCallback, useMemo, useState } from 'react' +import type { ChangeEvent } from 'react' +import { memo, useCallback, useMemo, useState } from 'react' @@ type CryptoAmountInputProps = { value?: string - onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void + onChange?: (e: ChangeEvent<HTMLInputElement>) => void placeholder?: string [key: string]: unknown }
🧹 Nitpick comments (2)
src/pages/Yields/components/YieldForm.tsx (1)
403-408: Remove the no-opuseEffectblock.
It currently doesn’t do anything and adds noise.Proposed change
- useEffect(() => { - if (step === ModalStep.Success) { - // Here we could auto-close or let YieldSuccess handle it - } - }, [step]) + // (removed no-op effect)src/lib/yieldxyz/constants.ts (1)
58-60: (Optional) Drop the new inline comments if not strictly needed.
Repo guidelines prefer avoiding new comments where the code can be self-documenting.
📜 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.
📒 Files selected for processing (7)
src/assets/translations/en/main.jsonsrc/hooks/useActionCenterSubscribers/useGenericTransactionSubscriber.tsxsrc/lib/yieldxyz/constants.tssrc/lib/yieldxyz/executeTransaction.tssrc/pages/Yields/components/YieldEnterModal.tsxsrc/pages/Yields/components/YieldForm.tsxsrc/pages/Yields/components/YieldPositionCard.tsx
🧰 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 runyarn lint --fixandyarn type-checkafter making changes
Avoidletvariable assignments - preferconstwith inline IIFE switch statements or extract to functions for conditional logic
Files:
src/lib/yieldxyz/constants.tssrc/pages/Yields/components/YieldPositionCard.tsxsrc/pages/Yields/components/YieldEnterModal.tsxsrc/lib/yieldxyz/executeTransaction.tssrc/hooks/useActionCenterSubscribers/useGenericTransactionSubscriber.tsxsrc/pages/Yields/components/YieldForm.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 inuseMemoand callbacks inuseCallbackwhere 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 usinguseColorModeValuehook
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()fromreact-polyglot
UseuseFeatureFlag('FlagName')hook to access feature flag values in components
Prefertypeoverinterfacefor type definitions
Use strict typing - avoidany
UseNominaltypes for domain identifiers (e.g.,WalletId,AccountId)
Import types from@shapeshiftoss/caipfor chain/account/asset IDs
UseuseAppSelectorfor Redux state
UseuseAppDispatchfor Redux actions
Memoize expensive computations withuseMemo
Memoize callbacks withuseCallback
**/*.{ts,tsx}: UseResult<T, E>pattern for error handling in swappers and APIs; ALWAYS useOk()andErr()from@sniptt/monads; AVOID throwing within swapper API implementations
ALWAYS use custom error classes from@shapeshiftoss/errorswith meaningful error codes for internationalization and relevant details in error objects
ALWAYS wrap async op...
Files:
src/lib/yieldxyz/constants.tssrc/pages/Yields/components/YieldPositionCard.tsxsrc/pages/Yields/components/YieldEnterModal.tsxsrc/lib/yieldxyz/executeTransaction.tssrc/hooks/useActionCenterSubscribers/useGenericTransactionSubscriber.tsxsrc/pages/Yields/components/YieldForm.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
Usehandleprefix for event handlers with descriptive names in camelCase
Use descriptive boolean variable names withis,has,can,shouldprefixes
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 likedata,item,obj, and single-letter variable names except in loops
Avoid abbreviations in names unless they are widely understood
Avoid generic function names likefn,func, orcallback
Files:
src/lib/yieldxyz/constants.tssrc/pages/Yields/components/YieldPositionCard.tsxsrc/pages/Yields/components/YieldEnterModal.tsxsrc/lib/yieldxyz/executeTransaction.tssrc/hooks/useActionCenterSubscribers/useGenericTransactionSubscriber.tsxsrc/pages/Yields/components/YieldForm.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 useuseErrorToasthook for displaying errors with translated error messages and handle different error types appropriatelyUse PascalCase for React component names and match the component name to the file name
Files:
src/pages/Yields/components/YieldPositionCard.tsxsrc/pages/Yields/components/YieldEnterModal.tsxsrc/hooks/useActionCenterSubscribers/useGenericTransactionSubscriber.tsxsrc/pages/Yields/components/YieldForm.tsx
**/*.{jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/react-best-practices.mdc)
**/*.{jsx,tsx}: ALWAYS useuseMemofor expensive computations, object/array creations, and filtered data
ALWAYS useuseMemofor derived values and computed properties
ALWAYS useuseMemofor conditional values and simple transformations
ALWAYS useuseCallbackfor event handlers and functions passed as props
ALWAYS useuseCallbackfor any function that could be passed as a prop or dependency
ALWAYS include all dependencies inuseEffect,useMemo,useCallbackdependency arrays
NEVER use// eslint-disable-next-line react-hooks/exhaustive-depsunless 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 withmemofor performance optimization
Files:
src/pages/Yields/components/YieldPositionCard.tsxsrc/pages/Yields/components/YieldEnterModal.tsxsrc/hooks/useActionCenterSubscribers/useGenericTransactionSubscriber.tsxsrc/pages/Yields/components/YieldForm.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursor/rules/react-best-practices.mdc)
Ensure TypeScript types are explicit and proper; avoid use of
anytype
Files:
src/pages/Yields/components/YieldPositionCard.tsxsrc/pages/Yields/components/YieldEnterModal.tsxsrc/hooks/useActionCenterSubscribers/useGenericTransactionSubscriber.tsxsrc/pages/Yields/components/YieldForm.tsx
src/assets/translations/en/main.json
📄 CodeRabbit inference engine (CLAUDE.md)
Add English copy to
src/assets/translations/en/main.json(find appropriate section)
Files:
src/assets/translations/en/main.json
🧠 Learnings (63)
📓 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: 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: 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: 10418
File: src/plugins/walletConnectToDapps/components/header/WalletConnectToDappsHeaderButton.tsx:0-0
Timestamp: 2025-09-08T22:00:48.005Z
Learning: gomesalexandre dismissed an aria-label accessibility suggestion with "meh" in PR `#10418` for WalletConnectToDappsHeaderButton.tsx, consistent with the team's pattern of deferring minor a11y improvements to follow-up PRs rather than expanding feature PR scope.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10206
File: src/config.ts:127-128
Timestamp: 2025-08-07T11:20:44.614Z
Learning: gomesalexandre prefers required environment variables without default values in the config file (src/config.ts). They want explicit configuration and fail-fast behavior when environment variables are missing, rather than having fallback defaults.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/ContractInteractionBreakdown.tsx:0-0
Timestamp: 2025-09-13T16:45:18.813Z
Learning: gomesalexandre prefers aggressively deleting unused/obsolete code files ("ramboing") rather than fixing technical issues in code that won't be used, demonstrating his preference for keeping codebases clean and PR scope focused.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10458
File: src/plugins/walletConnectToDapps/types.ts:7-7
Timestamp: 2025-09-10T15:34:29.604Z
Learning: gomesalexandre is comfortable relying on transitive dependencies (like abitype through ethers/viem) rather than explicitly declaring them in package.json, preferring to avoid package.json bloat when the transitive dependency approach works reliably in practice.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10503
File: .env:56-56
Timestamp: 2025-09-16T13:17:02.938Z
Learning: gomesalexandre prefers to enable feature flags globally in the base .env file when the intent is to activate features everywhere, even when there are known issues like crashes, demonstrating his preference for intentional global feature rollouts over cautious per-environment enablement.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10249
File: src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx:447-503
Timestamp: 2025-08-13T17:07:10.763Z
Learning: gomesalexandre prefers relying on TypeScript's type system for validation rather than adding defensive runtime null checks when types are properly defined. They favor a TypeScript-first approach over defensive programming with runtime validations.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10276
File: src/hooks/useActionCenterSubscribers/useThorchainLpDepositActionSubscriber.tsx:61-66
Timestamp: 2025-08-14T17:51:47.556Z
Learning: gomesalexandre is not concerned about structured logging and prefers to keep console.error usage as-is rather than implementing structured logging patterns, even when project guidelines suggest otherwise.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10413
File: src/components/Modals/FiatRamps/fiatRampProviders/onramper/utils.ts:29-55
Timestamp: 2025-09-02T14:26:19.028Z
Learning: gomesalexandre prefers to keep preparatory/reference code simple until it's actively consumed, rather than implementing comprehensive error handling, validation, and robustness improvements upfront. They prefer to add these improvements when the code is actually being used in production.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10276
File: src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx:396-402
Timestamp: 2025-08-14T17:55:57.490Z
Learning: gomesalexandre is comfortable with functions/variables that return undefined or true (tri-state) when only the truthy case matters, preferring to rely on JavaScript's truthy/falsy behavior rather than explicitly returning boolean values.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10783
File: src/context/ModalStackProvider/useModalRegistration.ts:30-41
Timestamp: 2025-10-16T11:14:40.657Z
Learning: gomesalexandre prefers to add lint rules (like typescript-eslint/strict-boolean-expressions for truthiness checks on numbers) to catch common issues project-wide rather than relying on code review to catch them.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10206
File: src/lib/moralis.ts:47-85
Timestamp: 2025-08-07T11:22:16.983Z
Learning: gomesalexandre prefers console.error over structured logging for Moralis API integration debugging, as they find it more conventional and prefer to examine XHR requests directly rather than rely on structured logs for troubleshooting.
📚 Learning: 2025-11-24T21:20:57.909Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-11-24T21:20:57.909Z
Learning: Applies to packages/swapper/src/swappers/*/utils/constants.ts : Define supported chain IDs for each swapper in utils/constants.ts with both 'sell' and 'buy' properties following the pattern: SupportedChainIds type
Applied to files:
src/lib/yieldxyz/constants.tssrc/lib/yieldxyz/executeTransaction.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:
src/lib/yieldxyz/constants.tssrc/pages/Yields/components/YieldEnterModal.tsxsrc/pages/Yields/components/YieldForm.tsx
📚 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:
src/lib/yieldxyz/constants.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:
src/lib/yieldxyz/constants.tssrc/pages/Yields/components/YieldEnterModal.tsxsrc/pages/Yields/components/YieldForm.tsx
📚 Learning: 2026-01-08T23:17:05.494Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11578
File: src/pages/Yields/hooks/useYieldTransactionFlow.ts:183-185
Timestamp: 2026-01-08T23:17:05.494Z
Learning: In the Yield.xyz API integration (src/pages/Yields/hooks/useYieldTransactionFlow.ts), the cosmosPubKey argument field accepts the user's Cosmos address (userAddress), not the raw public key. This is the expected format for the Yield.xyz API endpoints (enterYield/exitYield/manageYield).
Applied to files:
src/lib/yieldxyz/constants.tssrc/pages/Yields/components/YieldEnterModal.tsxsrc/lib/yieldxyz/executeTransaction.tssrc/pages/Yields/components/YieldForm.tsx
📚 Learning: 2025-08-22T12:59:01.210Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10323
File: src/components/Layout/Header/ActionCenter/components/RewardDistributionActionCard.tsx:26-29
Timestamp: 2025-08-22T12:59:01.210Z
Learning: In src/components/Layout/Header/ActionCenter/components/RewardDistributionActionCard.tsx, NeOMakinG declined wrapping the RewardDistributionActionCard component with React.memo, saying it was "too much", suggesting that like other action center components, memoization is not beneficial for this specific use case.
Applied to files:
src/pages/Yields/components/YieldPositionCard.tsx
📚 Learning: 2025-10-13T11:55:57.439Z
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.
Applied to files:
src/pages/Yields/components/YieldPositionCard.tsxsrc/pages/Yields/components/YieldForm.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-25T23:32:13.876Z
Learnt from: premiumjibles
Repo: shapeshift/web PR: 10361
File: src/pages/Markets/components/CardWithSparkline.tsx:83-92
Timestamp: 2025-08-25T23:32:13.876Z
Learning: In shapeshift/web PR `#10361`, premiumjibles considered the nested button accessibility issue (ChartErrorFallback retry Button inside Card rendered as Button in CardWithSparkline.tsx) out of scope for the error boundaries feature PR, consistent with deferring minor a11y improvements to follow-up PRs.
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.tsxsrc/pages/Yields/components/YieldEnterModal.tsxsrc/pages/Yields/components/YieldForm.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.tsxsrc/pages/Yields/components/YieldEnterModal.tsxsrc/pages/Yields/components/YieldForm.tsx
📚 Learning: 2025-09-12T12:00:33.924Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/SendTransactionConfirmation.tsx:42-50
Timestamp: 2025-09-12T12:00:33.924Z
Learning: gomesalexandre prefers maintaining consistency with existing code patterns across WalletConnect modal components, including side-effects-during-render for error handling (showErrorToast + handleReject calls before return null), rather than introducing isolated refactors that would create inconsistency in the codebase.
Applied to files:
src/pages/Yields/components/YieldPositionCard.tsxsrc/pages/Yields/components/YieldEnterModal.tsxsrc/pages/Yields/components/YieldForm.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} : Use Chakra UI components and conventions
Applied to files:
src/pages/Yields/components/YieldPositionCard.tsxsrc/pages/Yields/components/YieldForm.tsx
📚 Learning: 2025-10-07T03:44:27.350Z
Learnt from: 0xApotheosis
Repo: shapeshift/web PR: 10760
File: src/components/ManageHiddenAssets/ManageHiddenAssetsList.tsx:78-84
Timestamp: 2025-10-07T03:44:27.350Z
Learning: In the ShapeShift web codebase, the following are stable references and do not need to be included in useCallback/useMemo dependency arrays:
- `navigate` from `useBrowserRouter()` hook
- Modal control objects (like `walletDrawer`) from `useModal()` hook (including their `isOpen`, `close`, and `open` methods)
- These are backed by stable context providers
Applied to files:
src/pages/Yields/components/YieldPositionCard.tsxsrc/pages/Yields/components/YieldEnterModal.tsx
📚 Learning: 2025-11-24T21:20:44.637Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-11-24T21:20:44.637Z
Learning: Applies to **/*.{jsx,tsx} : EXTRACT complex logic into custom hooks
Applied to files:
src/pages/Yields/components/YieldPositionCard.tsx
📚 Learning: 2025-11-24T21:20:44.637Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-11-24T21:20:44.637Z
Learning: Applies to **/*.{jsx,tsx} : 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
Applied to files:
src/pages/Yields/components/YieldPositionCard.tsx
📚 Learning: 2025-08-21T22:15:25.918Z
Learnt from: kaladinlight
Repo: shapeshift/web PR: 10326
File: src/hooks/useActionCenterSubscribers/useFetchBasePortfolio.ts:31-59
Timestamp: 2025-08-21T22:15:25.918Z
Learning: In the ShapeShift web codebase, the maintainer prefers inferred return types for React hooks over explicit return types, particularly for complex hooks that can have intricate return signatures.
Applied to files:
src/pages/Yields/components/YieldPositionCard.tsx
📚 Learning: 2025-07-29T10:27:23.424Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10128
File: .cursor/rules/react-best-practices.mdc:8-14
Timestamp: 2025-07-29T10:27:23.424Z
Learning: The ShapeShift team practices aggressive memoization in React components as documented in .cursor/rules/react-best-practices.mdc. They use useMemo for all transformations, derived values, and conditional values, and useCallback for all event handlers and functions that could be passed as props. This approach was adopted after experiencing performance issues ("had hard time") and is their current established practice, though they acknowledge it may evolve in the future.
Applied to files:
src/pages/Yields/components/YieldPositionCard.tsx
📚 Learning: 2025-10-17T07:51:58.374Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10783
File: src/context/WalletProvider/NewWalletViews/NewWalletViewsSwitch.tsx:344-349
Timestamp: 2025-10-17T07:51:58.374Z
Learning: In the shapeshift/web codebase, Chakra UI's ModalContent component supports the containerProps prop. When using the useModalRegistration hook from ModalStackProvider, spreading {...modalContentProps} directly onto ModalContent is correct and properly applies z-index and pointer-events through containerProps.sx. Do not suggest extracting sx from modalContentProps.containerProps.sx.
Applied to files:
src/pages/Yields/components/YieldPositionCard.tsx
📚 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:
src/pages/Yields/components/YieldPositionCard.tsx
📚 Learning: 2025-08-22T13:02:58.824Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10323
File: src/pages/RFOX/hooks/useRfoxRewardDistributionActionSubscriber.tsx:33-41
Timestamp: 2025-08-22T13:02:58.824Z
Learning: In src/pages/RFOX/hooks/useRfoxRewardDistributionActionSubscriber.tsx, NeOMakinG declined optimizing useMemo dependencies to depend on lifetimeRewardDistributionsQuery.data instead of the entire query object, indicating indifference toward this type of performance optimization.
Applied to files:
src/pages/Yields/components/YieldPositionCard.tsxsrc/hooks/useActionCenterSubscribers/useGenericTransactionSubscriber.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.tsxsrc/pages/Yields/components/YieldEnterModal.tsxsrc/hooks/useActionCenterSubscribers/useGenericTransactionSubscriber.tsxsrc/pages/Yields/components/YieldForm.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/YieldEnterModal.tsxsrc/pages/Yields/components/YieldForm.tsx
📚 Learning: 2025-09-12T12:00:33.924Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/SendTransactionConfirmation.tsx:42-50
Timestamp: 2025-09-12T12:00:33.924Z
Learning: gomesalexandre prefers maintaining consistency with existing code patterns in WalletConnect modals, including side-effects-during-render for error handling (showErrorToast + handleReject), rather than introducing isolated refactors that would make the codebase inconsistent.
Applied to files:
src/pages/Yields/components/YieldEnterModal.tsxsrc/pages/Yields/components/YieldForm.tsx
📚 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:
src/pages/Yields/components/YieldEnterModal.tsxsrc/pages/Yields/components/YieldForm.tsx
📚 Learning: 2025-09-04T17:26:19.447Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10380
File: src/components/PriceChangeTag/PriceChangeTag.tsx:25-36
Timestamp: 2025-09-04T17:26:19.447Z
Learning: In the shapeshift/web project, NeOMakinG prefers to hide 0% price changes in the PriceChangeTag component rather than displaying "0.00%", so the falsy check `if (!changePercent24Hr) return null` is intentional design behavior.
Applied to files:
src/pages/Yields/components/YieldEnterModal.tsxsrc/pages/Yields/components/YieldForm.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/YieldEnterModal.tsxsrc/pages/Yields/components/YieldForm.tsx
📚 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:
src/pages/Yields/components/YieldEnterModal.tsx
📚 Learning: 2025-11-03T05:46:24.190Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10985
File: packages/swapper/src/swappers/PortalsSwapper/getPortalsTradeRate/getPortalsTradeRate.tsx:130-141
Timestamp: 2025-11-03T05:46:24.190Z
Learning: In packages/swapper/src/swappers/PortalsSwapper/getPortalsTradeRate/getPortalsTradeRate.tsx, gomesalexandre prefers "let it crash" approach when Portals returns zero outputAmount or 100% buffer causing division by zero, rather than adding defensive guards to surface zero quotes. He wants to fail fast with exceptions that bubble up to the try/catch wrapper, surfacing upstream data issues rather than masking them with defensive programming.
Applied to files:
src/pages/Yields/components/YieldEnterModal.tsxsrc/pages/Yields/components/YieldForm.tsx
📚 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:
src/pages/Yields/components/YieldEnterModal.tsxsrc/lib/yieldxyz/executeTransaction.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:
src/pages/Yields/components/YieldEnterModal.tsxsrc/lib/yieldxyz/executeTransaction.ts
📚 Learning: 2025-08-13T15:51:43.290Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10272
File: src/components/RatingModal.tsx:98-0
Timestamp: 2025-08-13T15:51:43.290Z
Learning: In the ShapeShift web codebase, for user-facing feedback modals like RatingModal, the team prefers to avoid showing error messages to users when webhook submissions fail, instead opting to silently close the modal to prevent "spamming" users with additional notifications that could be boring or frustrating for them. The UX philosophy prioritizes keeping interactions minimal and smooth over technical transparency.
Applied to files:
src/pages/Yields/components/YieldEnterModal.tsx
📚 Learning: 2025-08-08T15:00:49.887Z
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.
Applied to files:
src/pages/Yields/components/YieldEnterModal.tsx
📚 Learning: 2025-08-25T12:59:43.842Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10323
File: src/pages/Fox/components/RFOXSection.tsx:234-248
Timestamp: 2025-08-25T12:59:43.842Z
Learning: NeOMakinG considers suggestions to refactor working modal state management from useState to useDisclosure as too nitpicky, preferring to keep such cosmetic code improvements out of feature PRs unless they address actual issues.
Applied to files:
src/pages/Yields/components/YieldEnterModal.tsx
📚 Learning: 2025-11-24T21:20:44.637Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-11-24T21:20:44.637Z
Learning: Applies to **/*.tsx : Ensure TypeScript types are explicit and proper; avoid use of `any` type
Applied to files:
src/pages/Yields/components/YieldEnterModal.tsxsrc/pages/Yields/components/YieldForm.tsx
📚 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/YieldEnterModal.tsx
📚 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 `use` prefix for custom React hooks with camelCase naming after the prefix
Applied to files:
src/pages/Yields/components/YieldEnterModal.tsxsrc/pages/Yields/components/YieldForm.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/YieldEnterModal.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} : Avoid 'any' types - use specific type annotations instead
Applied to files:
src/pages/Yields/components/YieldEnterModal.tsxsrc/pages/Yields/components/YieldForm.tsx
📚 Learning: 2025-08-08T14:59:40.422Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10231
File: src/pages/Explore/ExploreCategory.tsx:231-238
Timestamp: 2025-08-08T14:59:40.422Z
Learning: In src/pages/Explore/ExploreCategory.tsx, for the PageHeader filter trigger, NeOMakinG considers changing a clickable Chakra Icon to IconButton too nitpicky for this PR and prefers to keep the current Icon-based trigger; such minor a11y/UI nitpicks should be deferred to a follow-up if needed.
Applied to files:
src/pages/Yields/components/YieldEnterModal.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} : Use strict typing - avoid `any`
Applied to files:
src/pages/Yields/components/YieldEnterModal.tsx
📚 Learning: 2025-11-24T21:20:57.909Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-11-24T21:20:57.909Z
Learning: Applies to packages/swapper/src/swappers/*/*.ts : Reuse executeEvmTransaction utility for EVM-based swappers instead of implementing custom transaction execution
Applied to files:
src/lib/yieldxyz/executeTransaction.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:
src/lib/yieldxyz/executeTransaction.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:
src/lib/yieldxyz/executeTransaction.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:
src/lib/yieldxyz/executeTransaction.ts
📚 Learning: 2025-08-22T13:16:12.721Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10323
File: src/pages/RFOX/hooks/useRfoxRewardDistributionActionSubscriber.tsx:104-105
Timestamp: 2025-08-22T13:16:12.721Z
Learning: In src/pages/RFOX/hooks/useRfoxRewardDistributionActionSubscriber.tsx, the guard `if (!actions[actionId]) return` before upserting completed reward distributions is intentional product behavior. NeOMakinG confirmed that the system should only show completion notifications for reward distributions that were previously seen in a pending state, not for distributions the user missed during the pending phase.
Applied to files:
src/hooks/useActionCenterSubscribers/useGenericTransactionSubscriber.tsx
📚 Learning: 2025-08-22T14:59:04.889Z
Learnt from: kaladinlight
Repo: shapeshift/web PR: 10326
File: src/hooks/useActionCenterSubscribers/useGenericTransactionSubscriber.tsx:105-111
Timestamp: 2025-08-22T14:59:04.889Z
Learning: In the ShapeShift web Base chain handling, the await pattern inside forEach in useGenericTransactionSubscriber is intentional to delay the entire action completion flow (not just fetchBasePortfolio) for Base chain transactions. The user kaladinlight wants everything below the Base portfolio refresh - including dispatch, query invalidation, and toast notifications - to also be delayed by ~10 seconds to accommodate Base's degraded node state.
Applied to files:
src/hooks/useActionCenterSubscribers/useGenericTransactionSubscriber.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/hooks/useActionCenterSubscribers/useGenericTransactionSubscriber.tsx
📚 Learning: 2025-08-22T15:07:18.021Z
Learnt from: kaladinlight
Repo: shapeshift/web PR: 10326
File: src/hooks/useActionCenterSubscribers/useThorchainLpActionSubscriber.tsx:37-41
Timestamp: 2025-08-22T15:07:18.021Z
Learning: In src/hooks/useActionCenterSubscribers/useThorchainLpActionSubscriber.tsx, kaladinlight prefers not to await the upsertBasePortfolio call in the Base chain handling block, indicating intentional fire-and-forget behavior for Base portfolio upserts in the THORChain LP completion flow.
Applied to files:
src/hooks/useActionCenterSubscribers/useGenericTransactionSubscriber.tsx
📚 Learning: 2025-08-14T17:56:23.721Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10276
File: src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx:545-566
Timestamp: 2025-08-14T17:56:23.721Z
Learning: gomesalexandre prefers not to extract helper functions for toast rendering patterns in TransactionRow.tsx (src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx), considering it over-abstraction even when there's code duplication between deposit and withdraw flows.
Applied to files:
src/hooks/useActionCenterSubscribers/useGenericTransactionSubscriber.tsx
📚 Learning: 2025-11-24T21:20:44.637Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-11-24T21:20:44.637Z
Learning: Applies to **/*.{jsx,tsx} : ALWAYS use `useCallback` for event handlers and functions passed as props
Applied to files:
src/pages/Yields/components/YieldForm.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,js,jsx} : Validate all inputs, especially user inputs
Applied to files:
src/pages/Yields/components/YieldForm.tsx
📚 Learning: 2025-11-24T21:20:44.637Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-11-24T21:20:44.637Z
Learning: Applies to **/*.{jsx,tsx} : ALWAYS use `useCallback` for any function that could be passed as a prop or dependency
Applied to files:
src/pages/Yields/components/YieldForm.tsx
📚 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 **/*.{tsx,jsx} : ALWAYS wrap React components in error boundaries and provide user-friendly fallback components with error logging
Applied to files:
src/pages/Yields/components/YieldForm.tsx
📚 Learning: 2025-09-26T17:45:47.676Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10592
File: src/state/slices/tradeRampInputSlice/selectors.ts:53-63
Timestamp: 2025-09-26T17:45:47.676Z
Learning: gomesalexandre considers additional rate validation guards (like checking rate > 0) unnecessary when the mathematical operation already handles edge cases correctly (e.g., multiplying by 0 yields 0). He prefers to avoid defensive programming when domain knowledge indicates certain edge cases (like negative rates) are not valid concerns, consistent with his TypeScript-first approach over runtime validations.
Applied to files:
src/pages/Yields/components/YieldForm.tsx
📚 Learning: 2025-09-13T16:45:17.166Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/WalletConnectSigningModal/StructuredMessage/StructuredMessage.tsx:0-0
Timestamp: 2025-09-13T16:45:17.166Z
Learning: gomesalexandre appreciates safety-focused suggestions for UI rendering in WalletConnect components, specifically defensive programming approaches that prevent null/undefined values from displaying as literal "null"/"undefined" strings in the user interface.
Applied to files:
src/pages/Yields/components/YieldForm.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/YieldForm.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 src/assets/translations/en/main.json : Add English copy to `src/assets/translations/en/main.json` (find appropriate section)
Applied to files:
src/assets/translations/en/main.json
📚 Learning: 2025-10-21T23:21:22.304Z
Learnt from: premiumjibles
Repo: shapeshift/web PR: 10759
File: src/components/Modals/Send/hooks/useFormSend/useFormSend.tsx:41-50
Timestamp: 2025-10-21T23:21:22.304Z
Learning: In the shapeshift/web repository, the translation workflow follows an "English-first" approach: English translations in src/assets/translations/en/main.json are updated first in PRs, and translations for the other supported languages (de, es, fr, id, ja, ko, pt, ru, tr, uk, zh) are updated "after the fact" in follow-up work. Temporary mismatches between English and other language translation keys/formats during active development are expected and acceptable.
<!--
Applied to files:
src/assets/translations/en/main.json
📚 Learning: 2025-07-24T21:05:13.642Z
Learnt from: 0xApotheosis
Repo: shapeshift/web PR: 10073
File: src/components/Layout/Header/ActionCenter/components/Details/ClaimDetails.tsx:10-11
Timestamp: 2025-07-24T21:05:13.642Z
Learning: In the ShapeShift web repository, translation workflow follows a two-step process: 1) First PR adds only English translations to src/assets/translations/en/main.json, 2) Globalization team handles follow-up PRs to add keys to remaining language files (de, es, fr, id, ja, ko, pt, ru, tr, uk, zh). Don't suggest verifying all locale files simultaneously during initial feature PRs.
Applied to files:
src/assets/translations/en/main.json
📚 Learning: 2025-08-17T23:39:00.407Z
Learnt from: premiumjibles
Repo: shapeshift/web PR: 10291
File: src/assets/translations/en/main.json:216-218
Timestamp: 2025-08-17T23:39:00.407Z
Learning: In the shapeshift/web project, translations for non-English locales are handled as a separate follow-up process by language experts, not as part of the initial PR that adds English keys to src/assets/translations/en/main.json.
Applied to files:
src/assets/translations/en/main.json
📚 Learning: 2025-08-13T15:50:41.994Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10272
File: src/components/RatingModal.tsx:104-0
Timestamp: 2025-08-13T15:50:41.994Z
Learning: In the ShapeShift web codebase, internal strings like Discord webhook embed content (used for team notifications/feedback) don't need to be translated, only user-facing strings require translation keys. The team distinguishes between internal tooling strings and user-facing UI strings for internationalization purposes.
Applied to files:
src/assets/translations/en/main.json
🧬 Code graph analysis (4)
src/lib/yieldxyz/constants.ts (2)
src/lib/yieldxyz/types.ts (1)
ValidatorDto(285-297)packages/caip/src/constants.ts (2)
cosmosChainId(84-84)solanaChainId(89-89)
src/pages/Yields/components/YieldPositionCard.tsx (2)
src/components/Text/Text.tsx (1)
Text(19-83)src/components/Amount/Amount.tsx (1)
Amount(21-42)
src/pages/Yields/components/YieldEnterModal.tsx (5)
src/react-queries/queries/yieldxyz/useYieldValidators.ts (1)
useYieldValidators(26-42)src/lib/yieldxyz/constants.ts (4)
DEFAULT_NATIVE_VALIDATOR_BY_CHAIN_ID(101-104)SHAPESHIFT_COSMOS_VALIDATOR_ADDRESS(62-63)SHAPESHIFT_VALIDATOR_NAME(72-72)SHAPESHIFT_VALIDATOR_LOGO(65-66)src/state/slices/common-selectors.ts (1)
selectPortfolioCryptoPrecisionBalanceByFilter(148-163)src/pages/Yields/hooks/useYieldTransactionFlow.ts (1)
useYieldTransactionFlow(153-835)src/lib/yieldxyz/utils.ts (1)
getTransactionButtonText(54-75)
src/lib/yieldxyz/executeTransaction.ts (1)
src/lib/yieldxyz/constants.ts (1)
SOLANA_YIELD_COMPUTE_UNIT_MARGIN_MULTIPLIER(60-60)
⏰ 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
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
- Use locale-aware currency symbol for fiat placeholder - URL-encode sellAsset.assetId in earn route - Handle undefined validatorAddress properly - Fix React.ChangeEvent type import Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace Image component with Avatar to avoid external CoinGecko fallback URL. Avatar uses built-in fallback showing initials from name prop. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
@coderabbitai stop commenting you nit |
|
🧠 Learnings used✅ Actions performedReviews paused. |




Description
This PR consolidates the following PRs into a single review-friendly PR targeting
develop:All above PRs will be closed in favor of this consolidated PR.
What's included:
Fixes:
/yields/asset/GHO)passthroughandmanageActionTypefrom pendingActionsFeatures:
UX/UI Improvements:
Cleanup:
Issue (if applicable)
Risk
Low - all changes are scoped to the yield feature which is behind a feature flag. No changes to transaction logic beyond fixing the claim flow passthrough.
Yield.xyz integrations, yield enter/exit/claim actions on all supported yield protocols.
Testing
Engineering
/yieldsand apply network/provider/type filters - verify persistenceOperations
Screenshots (if applicable)
Yield detail page refactor:
https://jam.dev/c/2ff6b47e-d2dc-4147-a0d9-52c10a703069
Mobile improvements:




Type filter & recommendations:
https://jam.dev/c/8bae16b6-87fe-41a8-a480-f918a0b70679
Earn tab:
https://jam.dev/c/c9e81000-60cb-4430-95d0-89a51225629f
https://jam.dev/c/4fabf2af-06af-488f-8e5b-e93f513c278b
One-click enter flow - Mobile:
https://jam.dev/c/1ff8f48c-ca5e-4b79-992c-cc5bf9109ffb
One-click enter flow - Desktop:
https://jam.dev/c/1f93ce52-a66f-410c-a0ae-c92eb47d3ba9
USDT reset + approval flows:
https://jam.dev/c/2f4fe73b-095f-45f0-8e5d-7f11b654b9cf
https://jam.dev/c/c8a11f4e-aabb-4485-bab9-63a9276193c9
Initial fixes:
https://jam.dev/c/9f77b0f6-7185-4383-ac98-6dcd8f32517e
https://jam.dev/c/71010588-6804-4cf5-8974-b31cd602e5cd
Success step & duplicate close button fixes:
Summary by CodeRabbit
New Features
Improvements
Chores
✏️ Tip: You can customize this high-level summary in your review settings.