-
-
Notifications
You must be signed in to change notification settings - Fork 326
feat(suite): cardano staking pool rebalancing logic #23402
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(suite): cardano staking pool rebalancing logic #23402
Conversation
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
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.
Pull request overview
This PR implements Cardano pool rebalancing functionality and updates APY calculations to reflect the actual pool a user is staked in, rather than a generic network APY.
Key Changes:
- Updated APY selectors to accept
Accountobjects instead of just network symbols, enabling pool-specific APY calculations - Implemented dynamic Cardano pool selection logic that chooses pools based on saturation levels
- Added new API integration for fetching Cardano pool statistics from Everstake
Reviewed changes
Copilot reviewed 27 out of 27 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| suite-common/wallet-utils/src/cardanoStakingUtils.ts | Added pool rebalancing logic with selectBestCardanoPool and helper functions for pool selection |
| suite-common/wallet-types/src/cardanoStaking.ts | Defined CardanoPoolInfo interface for pool data structure |
| suite-common/wallet-core/src/stake/stakeTypes.ts | Updated endpoint types and added Cardano-specific types for validator stats |
| suite-common/wallet-core/src/stake/stakeThunks.ts | Modified API endpoint configuration and response handling for Cardano pools |
| suite-common/wallet-core/src/stake/stakeSelectors.ts | Updated selectPoolStatsApyData to use account-specific pool data and added pool info selector |
| suite-common/wallet-constants/src/cardanoConstants.ts | Updated backup APY and added saturation threshold constant |
| packages/suite/src/hooks/wallet/useCardanoStaking.ts | Integrated pool selection into staking transaction creation |
| packages/suite/src/actions/wallet/stake/stakeFormCardanoActions.ts | Updated transaction preparation to use dynamic pool selection |
| Multiple UI components | Updated to pass Account objects instead of symbols to APY selectors |
Comments suppressed due to low confidence (1)
suite-common/wallet-utils/src/cardanoStakingUtils.ts:1
- The field is named 'apy' but is populated from 'pool.apr.value'. This naming inconsistency could cause confusion. Either rename the field to 'apr' in CardanoPoolInfo, or ensure the API actually returns APY values.
import { bech32 } from 'bech32';
WalkthroughThis pull request refactors Cardano staking to use dynamic pool selection instead of hardcoded pool constants. The changes replace symbol-based APY lookups with account object-based lookups across the codebase, introduce new types for pool information (CardanoPoolInfo), update the Everstake API endpoint and response structure, add pool saturation-based selection logic, and thread Cardano pool data through actions, selectors, and components. A new domain (stats.everstake.one) is whitelisted, the Cardano backup APY is adjusted from 4.5 to 2.16, and a pool saturation safe threshold is introduced at 80 percent. Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Tip 📝 Customizable high-level summaries are now available in beta!You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.
Example instruction:
Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 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.
Actionable comments posted: 4
🧹 Nitpick comments (1)
suite-common/wallet-utils/src/cardanoStakingUtils.ts (1)
4-8: Cardano pool utilities and rebalancing logic look soundThe new helpers:
isCardanoStakedWithEverstakecorrectly gates on Cardano accounts and matchesmisc.staking.poolIdagainst the providedCardanoPoolInfo[].selectBestCardanoPoolsafely filters byCARDANO_POOL_SATURATION_SAFE_THRESHOLDand picks the highest saturation among safe pools, or the lowest saturation overall as a fallback, without risking empty‑arrayreducecalls.poolBech32ToHexprovides the expected bech32→hex conversion used by the pool selector.To protect this selection logic from future regressions, it would be worth adding a few focused unit tests (e.g., all pools under threshold, all above threshold, empty list) exercising the returned
{ hex, bech32 }pair.Also applies to: 35-47, 49-85
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (27)
packages/suite-desktop-core/src/config.ts(1 hunks)packages/suite/src/actions/wallet/stake/stakeFormCardanoActions.ts(10 hunks)packages/suite/src/components/suite/StakingProcess/StakingInfo.tsx(1 hunks)packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeInANutshellModal/StakeInANutshellModal.tsx(1 hunks)packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakeInfoCards/EstimatedGains.tsx(1 hunks)packages/suite/src/components/wallet/WalletLayout/AccountBanners/StakingBanner.tsx(1 hunks)packages/suite/src/components/wallet/WalletLayout/AccountsMenu/AccountItem/AccountRow/AccountItemContent/AccountItemContent.tsx(2 hunks)packages/suite/src/hooks/wallet/useCardanoStaking.ts(5 hunks)packages/suite/src/views/dashboard/StakingDashboard/StakingDashboard.tsx(2 hunks)packages/suite/src/views/dashboard/StakingDashboard/StakingDashboardAccountRow.tsx(1 hunks)packages/suite/src/views/dashboard/StakingDashboard/StakingDashboardActivateRow.tsx(1 hunks)packages/suite/src/views/wallet/staking/components/CardanoNewProviderCard.tsx(2 hunks)packages/suite/src/views/wallet/staking/components/CardanoStakingDashboard/NewCardanoStakingDashboard.tsx(2 hunks)packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/EthStakingDashboard.tsx(1 hunks)packages/suite/src/views/wallet/staking/components/SolStakingDashboard/SolStakingDashboard.tsx(1 hunks)packages/suite/src/views/wallet/staking/components/StakingDashboard/components/EmptyStakingCard.tsx(1 hunks)packages/suite/src/views/wallet/staking/components/StakingDashboard/components/NewProviderCard.tsx(1 hunks)suite-common/wallet-constants/src/cardanoConstants.ts(2 hunks)suite-common/wallet-core/src/stake/stakeConstants.ts(1 hunks)suite-common/wallet-core/src/stake/stakeReducer.ts(2 hunks)suite-common/wallet-core/src/stake/stakeSelectors.ts(3 hunks)suite-common/wallet-core/src/stake/stakeThunks.ts(3 hunks)suite-common/wallet-core/src/stake/stakeTypes.ts(3 hunks)suite-common/wallet-types/src/cardanoStaking.ts(1 hunks)suite-common/wallet-utils/src/cardanoStakingUtils.ts(2 hunks)suite-native/staking/src/selectors.ts(1 hunks)suite-native/staking/src/solanaStakingSelectors.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{js,ts,tsx,jsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.{js,ts,tsx,jsx}: Use Conventional Commits format for commit messages (e.g.,feat(suite):,fix(components):,docs:)
Runyarn build:libsafter making dependency changes to rebuild libraries before development
Runyarn lintto lint JavaScript/TypeScript and styles before committing code
Runyarn type-checkfor TypeScript type checking on all code before submission
Runyarn formatto format code with Prettier before committing
Files:
packages/suite/src/views/wallet/staking/components/CardanoNewProviderCard.tsxsuite-common/wallet-core/src/stake/stakeReducer.tspackages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeInANutshellModal/StakeInANutshellModal.tsxsuite-common/wallet-constants/src/cardanoConstants.tspackages/suite/src/views/wallet/staking/components/StakingDashboard/components/NewProviderCard.tsxpackages/suite/src/views/dashboard/StakingDashboard/StakingDashboardAccountRow.tsxsuite-common/wallet-types/src/cardanoStaking.tspackages/suite/src/views/dashboard/StakingDashboard/StakingDashboardActivateRow.tsxpackages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/EthStakingDashboard.tsxpackages/suite/src/components/wallet/WalletLayout/AccountBanners/StakingBanner.tsxsuite-common/wallet-core/src/stake/stakeConstants.tssuite-common/wallet-utils/src/cardanoStakingUtils.tspackages/suite/src/views/wallet/staking/components/SolStakingDashboard/SolStakingDashboard.tsxsuite-common/wallet-core/src/stake/stakeSelectors.tspackages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakeInfoCards/EstimatedGains.tsxsuite-common/wallet-core/src/stake/stakeThunks.tspackages/suite/src/hooks/wallet/useCardanoStaking.tspackages/suite/src/components/suite/StakingProcess/StakingInfo.tsxpackages/suite/src/views/wallet/staking/components/StakingDashboard/components/EmptyStakingCard.tsxpackages/suite-desktop-core/src/config.tspackages/suite/src/components/wallet/WalletLayout/AccountsMenu/AccountItem/AccountRow/AccountItemContent/AccountItemContent.tsxsuite-native/staking/src/selectors.tssuite-common/wallet-core/src/stake/stakeTypes.tspackages/suite/src/views/wallet/staking/components/CardanoStakingDashboard/NewCardanoStakingDashboard.tsxsuite-native/staking/src/solanaStakingSelectors.tspackages/suite/src/actions/wallet/stake/stakeFormCardanoActions.tspackages/suite/src/views/dashboard/StakingDashboard/StakingDashboard.tsx
🧠 Learnings (5)
📚 Learning: 2025-11-10T09:22:18.490Z
Learnt from: tomasklim
Repo: trezor/trezor-suite PR: 22729
File: packages/suite/src/actions/wallet/selectedAccountActions.ts:184-190
Timestamp: 2025-11-10T09:22:18.490Z
Learning: In the trezor-suite repository, exchange (swap) routes should not use selectedAccount from Redux. Exchange components use the useTradingFormAccount hook to derive the account independently, and syncSelectedAccount is intentionally skipped for routes starting with 'wallet-trading-exchange' to prevent unnecessary Redux updates during the global swap flow.
Applied to files:
packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeInANutshellModal/StakeInANutshellModal.tsxpackages/suite/src/views/wallet/staking/components/StakingDashboard/components/NewProviderCard.tsxpackages/suite/src/views/dashboard/StakingDashboard/StakingDashboardAccountRow.tsxpackages/suite/src/views/dashboard/StakingDashboard/StakingDashboardActivateRow.tsxpackages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/EthStakingDashboard.tsxpackages/suite/src/components/wallet/WalletLayout/AccountBanners/StakingBanner.tsxpackages/suite/src/views/wallet/staking/components/SolStakingDashboard/SolStakingDashboard.tsxpackages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakeInfoCards/EstimatedGains.tsxpackages/suite/src/hooks/wallet/useCardanoStaking.tspackages/suite/src/components/wallet/WalletLayout/AccountsMenu/AccountItem/AccountRow/AccountItemContent/AccountItemContent.tsxsuite-native/staking/src/solanaStakingSelectors.tspackages/suite/src/views/dashboard/StakingDashboard/StakingDashboard.tsx
📚 Learning: 2025-03-25T08:57:21.694Z
Learnt from: vojtatranta
Repo: trezor/trezor-suite PR: 17644
File: packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/TxDetailModal/Detail/AdvancedTxDetails/IODetails/TransactionDetailsModal.tsx:87-112
Timestamp: 2025-03-25T08:57:21.694Z
Learning: Missing React keys in iterables in the `TransactionDetailsModal.tsx` file are accepted by the project maintainers, specifically in the token transfers mapping.
Applied to files:
packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeInANutshellModal/StakeInANutshellModal.tsxpackages/suite/src/views/wallet/staking/components/StakingDashboard/components/NewProviderCard.tsxpackages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/EthStakingDashboard.tsxpackages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakeInfoCards/EstimatedGains.tsx
📚 Learning: 2025-02-04T13:18:21.530Z
Learnt from: jbazant
Repo: trezor/trezor-suite PR: 16668
File: suite-native/module-trading/src/components/TradeableAssetsSheet/TradeableAssetsSheet.tsx:0-0
Timestamp: 2025-02-04T13:18:21.530Z
Learning: The mock data arrays in `suite-native/module-trading/src/components/TradeableAssetsSheet/TradeableAssetsSheet.tsx` are intentionally used as visual stubs and will be replaced with real data fetching in future commits.
Applied to files:
packages/suite/src/views/wallet/staking/components/StakingDashboard/components/NewProviderCard.tsxpackages/suite/src/views/dashboard/StakingDashboard/StakingDashboardAccountRow.tsxpackages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/EthStakingDashboard.tsxpackages/suite/src/components/suite/StakingProcess/StakingInfo.tsxpackages/suite/src/views/wallet/staking/components/StakingDashboard/components/EmptyStakingCard.tsx
📚 Learning: 2025-02-04T13:18:46.084Z
Learnt from: jbazant
Repo: trezor/trezor-suite PR: 16668
File: suite-native/module-trading/src/components/general/TradeableAssetsSheet/TradeableAssetsFilterTabs.tsx:17-28
Timestamp: 2025-02-04T13:18:46.084Z
Learning: The mock data in TradeableAssetsFilterTabs.tsx is part of a visual stub and will be replaced with dynamic data in future commits.
Applied to files:
packages/suite/src/views/dashboard/StakingDashboard/StakingDashboardAccountRow.tsxpackages/suite/src/views/wallet/staking/components/StakingDashboard/components/EmptyStakingCard.tsx
📚 Learning: 2025-10-08T21:10:41.455Z
Learnt from: vytick
Repo: trezor/trezor-suite PR: 22340
File: suite-native/module-settings/src/components/ConnectionSettings.tsx:37-40
Timestamp: 2025-10-08T21:10:41.455Z
Learning: In Trezor Suite Native, initialized devices (including view-only) always have at least one account because the app asks users to select at least one network during initialization and discovers at least one empty account. This means `selectIsDiscoveredDeviceAccountless` returns false for all initialized devices.
Applied to files:
suite-native/staking/src/solanaStakingSelectors.ts
🧬 Code graph analysis (23)
packages/suite/src/views/wallet/staking/components/CardanoNewProviderCard.tsx (2)
suite-common/wallet-core/src/stake/stakeSelectors.ts (1)
selectCardanoPoolsInfo(49-50)suite-common/wallet-utils/src/cardanoStakingUtils.ts (1)
isCardanoStakedWithEverstake(35-47)
suite-common/wallet-core/src/stake/stakeReducer.ts (1)
suite-common/wallet-core/src/stake/stakeTypes.ts (1)
EverstakeStakingInfo(131-134)
packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeInANutshellModal/StakeInANutshellModal.tsx (2)
suite-common/wallet-core/src/stake/stakeReducer.ts (1)
StakeRootState(62-62)suite-common/wallet-core/src/stake/stakeSelectors.ts (1)
selectPoolStatsApyData(23-47)
packages/suite/src/views/wallet/staking/components/StakingDashboard/components/NewProviderCard.tsx (1)
suite-common/wallet-core/src/stake/stakeSelectors.ts (1)
selectPoolStatsApyData(23-47)
packages/suite/src/views/dashboard/StakingDashboard/StakingDashboardAccountRow.tsx (1)
suite-common/wallet-core/src/stake/stakeSelectors.ts (1)
selectPoolStatsApyData(23-47)
packages/suite/src/views/dashboard/StakingDashboard/StakingDashboardActivateRow.tsx (1)
suite-common/wallet-core/src/stake/stakeSelectors.ts (1)
selectPoolStatsApyData(23-47)
packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/EthStakingDashboard.tsx (1)
suite-common/wallet-core/src/stake/stakeSelectors.ts (1)
selectPoolStatsApyData(23-47)
packages/suite/src/components/wallet/WalletLayout/AccountBanners/StakingBanner.tsx (1)
suite-common/wallet-core/src/stake/stakeSelectors.ts (1)
selectPoolStatsApyData(23-47)
suite-common/wallet-utils/src/cardanoStakingUtils.ts (2)
suite-common/wallet-types/src/cardanoStaking.ts (1)
CardanoPoolInfo(75-79)suite-common/wallet-constants/src/cardanoConstants.ts (1)
CARDANO_POOL_SATURATION_SAFE_THRESHOLD(27-27)
packages/suite/src/views/wallet/staking/components/SolStakingDashboard/SolStakingDashboard.tsx (2)
suite-common/wallet-core/src/stake/stakeReducer.ts (1)
StakeRootState(62-62)suite-common/wallet-core/src/stake/stakeSelectors.ts (1)
selectPoolStatsApyData(23-47)
suite-common/wallet-core/src/stake/stakeSelectors.ts (3)
suite-common/wallet-core/src/stake/stakeReducer.ts (1)
StakeRootState(62-62)suite-common/wallet-constants/src/cardanoConstants.ts (1)
BACKUP_CARDANO_APY(3-3)suite-common/wallet-constants/src/ethereumStakingConstants.ts (1)
BACKUP_ETH_APY(4-4)
packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakeInfoCards/EstimatedGains.tsx (2)
suite-common/wallet-core/src/stake/stakeReducer.ts (1)
StakeRootState(62-62)suite-common/wallet-core/src/stake/stakeSelectors.ts (1)
selectPoolStatsApyData(23-47)
suite-common/wallet-core/src/stake/stakeThunks.ts (3)
suite-common/wallet-core/src/stake/stakeTypes.ts (3)
EverstakeStakingInfo(131-134)EVERSTAKE_ASSET_ENDPOINT_TYPES(34-40)CardanoValidatorStats(136-151)suite-common/wallet-core/src/stake/stakeConstants.ts (2)
EVERSTAKE_ENDPOINT_PREFIX(7-16)EVERSTAKE_API_KEY(22-22)suite-common/wallet-utils/src/cardanoStakingUtils.ts (1)
isSupportedAdaStakingNetworkSymbol(17-21)
packages/suite/src/hooks/wallet/useCardanoStaking.ts (2)
suite-common/wallet-core/src/stake/stakeSelectors.ts (1)
selectCardanoPoolsInfo(49-50)suite-common/wallet-utils/src/cardanoStakingUtils.ts (1)
selectBestCardanoPool(56-85)
packages/suite/src/components/suite/StakingProcess/StakingInfo.tsx (2)
suite-common/wallet-core/src/stake/stakeReducer.ts (1)
StakeRootState(62-62)suite-common/wallet-core/src/stake/stakeSelectors.ts (1)
selectPoolStatsApyData(23-47)
packages/suite/src/views/wallet/staking/components/StakingDashboard/components/EmptyStakingCard.tsx (1)
suite-common/wallet-core/src/stake/stakeSelectors.ts (1)
selectPoolStatsApyData(23-47)
packages/suite/src/components/wallet/WalletLayout/AccountsMenu/AccountItem/AccountRow/AccountItemContent/AccountItemContent.tsx (2)
suite-common/wallet-core/src/stake/stakeSelectors.ts (1)
selectCardanoPoolsInfo(49-50)suite-common/wallet-utils/src/cardanoStakingUtils.ts (1)
isCardanoStakedWithEverstake(35-47)
suite-native/staking/src/selectors.ts (1)
suite-common/wallet-core/src/stake/stakeSelectors.ts (1)
selectPoolStatsApyData(23-47)
suite-common/wallet-core/src/stake/stakeTypes.ts (1)
suite-common/wallet-types/src/cardanoStaking.ts (1)
CardanoPoolInfo(75-79)
packages/suite/src/views/wallet/staking/components/CardanoStakingDashboard/NewCardanoStakingDashboard.tsx (2)
suite-common/wallet-core/src/stake/stakeSelectors.ts (2)
selectPoolStatsApyData(23-47)selectCardanoPoolsInfo(49-50)suite-common/wallet-utils/src/cardanoStakingUtils.ts (1)
isCardanoStakedWithEverstake(35-47)
suite-native/staking/src/solanaStakingSelectors.ts (2)
suite-common/wallet-core/src/accounts/accountsSelectors.ts (1)
selectAccountByKey(123-130)suite-common/wallet-core/src/stake/stakeSelectors.ts (1)
selectPoolStatsApyData(23-47)
packages/suite/src/actions/wallet/stake/stakeFormCardanoActions.ts (3)
suite-common/wallet-types/src/cardanoStaking.ts (1)
CardanoPoolInfo(75-79)suite-common/wallet-utils/src/cardanoStakingUtils.ts (1)
selectBestCardanoPool(56-85)suite-common/wallet-core/src/stake/stakeSelectors.ts (1)
selectCardanoPoolsInfo(49-50)
packages/suite/src/views/dashboard/StakingDashboard/StakingDashboard.tsx (3)
suite-common/wallet-config/src/types.ts (1)
NetworkSymbol(4-29)suite-native/trading-fixtures/src/__fixtures__/accounts.ts (1)
accounts(3-80)packages/suite/src/views/dashboard/StakingDashboard/StakingDashboardActivateRow.tsx (1)
StakingDashboardActivateRow(13-75)
🪛 Gitleaks (8.29.0)
suite-common/wallet-core/src/stake/stakeConstants.ts
[high] 22-22: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
⏰ 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). (2)
- GitHub Check: Agent
- GitHub Check: CodeQL analysis (javascript-typescript)
🔇 Additional comments (28)
suite-native/staking/src/solanaStakingSelectors.ts (1)
60-63: APY selector correctly migrated to account-based APIUsing
selectAccountByKeyand passing the resolvedaccountintoselectPoolStatsApyDataaligns with the new(state, account)signature and keeps the0fallback for missing accounts simple and safe for downstream callers (e.g.,.toString()inselectExpectedRewardsForEpoch). Looks good.packages/suite/src/views/wallet/staking/components/StakingDashboard/components/EmptyStakingCard.tsx (1)
54-78: Account-based APY selector usage looks correctPassing the full
accountintoselectPoolStatsApyDataaligns with the new selector signature and correctly drives Cardano pool–aware APY without changing the surrounding logic.packages/suite-desktop-core/src/config.ts (1)
18-44: Everstake Cardano stats domain whitelisting is consistentAdding
stats.everstake.onetoallowedDomainsmatches the pattern of existing Everstake endpoints and should safely enable the new Cardano stats calls.packages/suite/src/views/dashboard/StakingDashboard/StakingDashboardActivateRow.tsx (1)
13-21: Account-based activate row wiring is consistentSwitching
StakingDashboardActivateRowto acceptaccount?: Accountand derivingsymbolplus APY from that account is consistent with the new selectors; when no matching account existssymbolis falsy, so the row correctly renders nothing.packages/suite/src/views/dashboard/StakingDashboard/StakingDashboard.tsx (1)
71-73: Updated activate rows to pass accounts matches new APIUsing
getAccountBySymbolto feed anAccountintoStakingDashboardActivateRowmatches the component’s new props and keeps the activation CTA at the network level (first matching account per symbol).Also applies to: 213-221
packages/suite/src/views/dashboard/StakingDashboard/StakingDashboardAccountRow.tsx (1)
27-27: APY selector now correctly uses the full accountPassing the
accountintoselectPoolStatsApyDatais the right move for pool-aware APY (especially for Cardano) and keeps the rest of the reward calculations unchanged.packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeInANutshellModal/StakeInANutshellModal.tsx (1)
107-113: Stake-in-a-nutshell now uses account-aware APYUsing
selectPoolStatsApyData(state, account)makes the modal’s APY copy consistent with the actual staked pool (or backup APY when account/pool data is missing), without changing the surrounding flow.packages/suite/src/views/wallet/staking/components/SolStakingDashboard/SolStakingDashboard.tsx (1)
43-47: Sol staking APY wiring matches the new selector contractPassing the
accountintoselectPoolStatsApyDatacorrectly adapts the Sol staking dashboard to the account-based APY selector without affecting existing layout or control flow.packages/suite/src/views/wallet/staking/components/EthStakingDashboard/components/EthStakingDashboard.tsx (1)
51-51: LGTM! APY selector updated to use account object.The change from passing
account?.symboltoaccountaligns with the refactoredselectPoolStatsApyDatasignature. This enables Cardano APY lookups to access pool-specific data viaaccount.misc.staking.poolId.suite-native/staking/src/selectors.ts (1)
169-169: LGTM! Consistent with the account-based APY selector pattern.The update correctly passes the full account object to
selectPoolStatsApyData, enabling pool-specific APY calculation for Cardano staking.suite-common/wallet-types/src/cardanoStaking.ts (1)
75-79: LGTM! Well-structured type for Cardano pool information.The
CardanoPoolInfointerface appropriately captures the essential pool metrics (APY, saturation, ID) needed for dynamic pool selection and rebalancing logic.packages/suite/src/components/suite/StakingProcess/StakingInfo.tsx (1)
137-137: LGTM! APY selector updated consistently.The change to pass the full account object enables Cardano pool-specific APY calculation while maintaining type safety.
packages/suite/src/components/wallet/WalletLayout/AccountsMenu/AccountItem/AccountRow/AccountItemContent/AccountItemContent.tsx (1)
3-3: LGTM! Cardano pool integration for staking status.The changes correctly integrate Cardano pool information to determine Everstake staking status. The
isCardanoStakedWithEverstakeutility safely handles empty or undefined pool arrays, and the icon display logic properly reflects the staking state.Also applies to: 48-48, 53-53
suite-common/wallet-constants/src/cardanoConstants.ts (2)
27-27: LGTM! Reasonable saturation threshold for pool selection.The 80% saturation threshold provides a sensible safety margin for pool selection logic, helping users avoid oversaturated pools while maintaining flexibility.
3-3: Cardano APY value of 2.16% is reasonable and aligns with current market conditions.Based on current data, Cardano staking APY in 2025 ranges approximately 1.5%–4%, with platforms like StakingRewards reporting ~2.46% and Coinbase showing ~1.59%. The updated value of 2.16% falls comfortably within this range and is more accurate than the previous 4.5%, which exceeded current market rates. This change appropriately reflects lower staking rewards in the current Cardano environment and is suitable for a backup fallback value.
packages/suite/src/views/wallet/staking/components/StakingDashboard/components/NewProviderCard.tsx (1)
20-20: LGTM! APY selector updated consistently.The change correctly passes the full account object to enable pool-specific APY calculation for Cardano accounts.
packages/suite/src/components/wallet/WalletLayout/AccountBanners/StakingBanner.tsx (1)
47-47: LGTM! APY selector updated consistently.The change aligns with the repository-wide refactor to pass account objects for pool-aware APY calculation, particularly benefiting Cardano staking.
suite-common/wallet-core/src/stake/stakeReducer.ts (1)
12-17: Everstake stakingInfo type narrowing looks consistentSwitching
stakingInfo.datatoEverstakeStakingInfoand wiring the new type into imports aligns with the richer ADA pool data and existing thunk payloads. The pending/rejected branches still initializingdatato{}are safe given the optional fields, and selectors already guard against missing values.Also applies to: 47-47
packages/suite/src/views/wallet/staking/components/CardanoNewProviderCard.tsx (1)
5-6: Using Cardano pool list for Everstake check is appropriateSelecting
cardanoStakingPoolsviaselectCardanoPoolsInfoand passing it intoisCardanoStakedWithEverstake(account, cardanoStakingPools)matches the updated helper signature and ensures the banner logic tracks the actual Everstake-managed pools rather than a hardcoded pool id.Also applies to: 20-21
packages/suite/src/components/suite/modals/ReduxModal/UserContextModal/StakeModal/StakeInfoCards/EstimatedGains.tsx (1)
39-39: Account‑based APY selector usage is correctPassing the full
accountintoselectPoolStatsApyDatamatches the updated selector signature and allows Cardano APY to be resolved from the currently delegated pool rather than a symbol‑level default.packages/suite/src/views/wallet/staking/components/CardanoStakingDashboard/NewCardanoStakingDashboard.tsx (1)
7-10: Dashboard wiring to pool‑aware APY and Everstake pools is consistentUsing
selectPoolStatsApyData(state, account)and feedingcardanoStakingPoolsintoisCardanoStakedWithEverstake(account, cardanoStakingPools)cleanly aligns the Cardano dashboard with the new pool‑aware staking model. Gating<ApyCard>’sapyprop onisStakedWithEverstake || hasPendingTxpreserves the existing UX while leveraging the dynamic pool list.Also applies to: 45-46, 49-51
suite-common/wallet-core/src/stake/stakeTypes.ts (1)
6-7: New Everstake/Cardano staking types align with reducer and selector usageImporting
CardanoPoolInfo, expandingEVERSTAKE_ASSET_ENDPOINT_TYPES.StakingInfoto a per‑symbol map, and introducingEverstakeStakingInfo(withapyandpools?: CardanoPoolInfo[]) plusCardanoValidatorStatsline up with howstakingInfo.datais now typed and consumed in reducers/selectors. The shapes look consistent with the rest of the staking code.Also applies to: 35-40, 131-151
packages/suite/src/hooks/wallet/useCardanoStaking.ts (1)
4-8: Guard delegation against missing Cardano pool selection
selectBestCardanoPool(cardanoPools)can returnundefinedwhen pools have not loaded or the API returns an empty list, butprepareTxPlanstill calls:const pool = selectBestCardanoPool(cardanoPools); let certificates = action === 'delegate' ? getDelegationCertificates(stakingPath, pool?.hex, !isStakingActive) : [];This means a delegate action may attempt to build certificates with an undefined pool id, leading to opaque failures bubbling up as generic sign/compose errors.
Consider explicitly handling the “no pool” case for delegate actions, for example:
const pool = selectBestCardanoPool(cardanoPools); - let certificates = - action === 'delegate' - ? getDelegationCertificates(stakingPath, pool?.hex, !isStakingActive) - : []; + if (action === 'delegate' && !pool) { + // surface a clear reason; caught by existing try/catch and UI mapping + throw new Error('POOL_ID_FETCH_FAIL'); + } + + let certificates = + action === 'delegate' + ? getDelegationCertificates(stakingPath, pool.hex, !isStakingActive) + : [];This keeps delegation disabled (or fails with a specific, translatable reason) until Everstake pools are available, instead of silently relying on
pool?.hexbeing truthy.Also applies to: 22-23, 74-75, 135-140, 184-185
⛔ Skipped due to learnings
Learnt from: vojtatranta Repo: trezor/trezor-suite PR: 16760 File: packages/suite/src/views/wallet/transactions/TransactionList/TransactionList.tsx:105-107 Timestamp: 2025-02-11T09:53:11.461Z Learning: Error handling for transaction fetching operations in the Trezor Suite is managed at the thunk layer rather than in the component layer.suite-common/wallet-core/src/stake/stakeSelectors.ts (2)
23-29: LGTM - Breaking API change from symbol to account parameter.The refactored signature correctly derives
symbolandmiscfrom the account object. Callers across the codebase will need to pass account objects instead ofaccount.symbol.
35-44: ADA staking APY resolution logic looks correct.The implementation properly handles:
- Missing staking info in
misc→ falls back toBACKUP_CARDANO_APY- Pool not found by
poolId→ falls back toBACKUP_CARDANO_APY- Pool with non-positive APY → falls back to
BACKUP_CARDANO_APYMinor observation: Line 43 uses
currentPool?.apywith optional chaining, butcurrentPoolis guaranteed to be truthy at that point due to the check on line 41. This is harmless but redundant.suite-common/wallet-core/src/stake/stakeThunks.ts (3)
116-120: API key exposed in client-side code.The
EVERSTAKE_API_KEYis included in the request headers and will be visible in network requests from the browser/app. Ensure this is intentional and that the key is scoped appropriately (read-only, rate-limited, etc.) for public exposure.
86-95: LGTM - Endpoint parameters updated for new Cardano API.The change from
name=cardanotolimit=1000&offset=0&partner=Trezoraligns with the new stats.everstake.one endpoint format.
97-143: Return type correctly updated to EverstakeStakingInfo.The thunk now properly returns either
{ pools: [...] }for ADA or{ apy: number }for SOL, matching theEverstakeStakingInfointerface which has both fields as optional.
packages/suite/src/views/dashboard/StakingDashboard/StakingDashboard.tsx
Outdated
Show resolved
Hide resolved
...onents/suite/modals/ReduxModal/UserContextModal/StakeModal/StakeInfoCards/EstimatedGains.tsx
Outdated
Show resolved
Hide resolved
...nts/suite/modals/ReduxModal/UserContextModal/StakeInANutshellModal/StakeInANutshellModal.tsx
Outdated
Show resolved
Hide resolved
packages/suite/src/components/suite/StakingProcess/StakingInfo.tsx
Outdated
Show resolved
Hide resolved
...e/src/views/wallet/staking/components/CardanoStakingDashboard/NewCardanoStakingDashboard.tsx
Outdated
Show resolved
Hide resolved
| const hasPendingTx = useSelector(state => hasPendingStakeTypeTransaction(state, account.key)); | ||
| const isStakedWithEverstake = isCardanoStakedWithEverstake(account) || hasPendingTx; | ||
| const cardanoStakingPools = useSelector(selectCardanoPoolsInfo); | ||
| const isStakedWithEverstake = |
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.
This is confusing, why is hasPendingTx part of isStakedWithEverstake variable?
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.
If I remember it correctly, there is a case where after staking we show the Cardano dashboard, but isCardanoStakedWithEverstake is still false since tx is in the pending state. That's why hasPendingTx was added here. I renamed this to avoid confusion. 45eff80
packages/suite/src/views/wallet/staking/components/SolStakingDashboard/SolStakingDashboard.tsx
Outdated
Show resolved
Hide resolved
664a418 to
3d480fd
Compare
packages/suite/src/views/dashboard/StakingDashboard/StakingDashboardActivateRow.tsx
Outdated
Show resolved
Hide resolved
...e/src/views/wallet/staking/components/CardanoStakingDashboard/NewCardanoStakingDashboard.tsx
Outdated
Show resolved
Hide resolved
6aaf862 to
31ba307
Compare
|
Please squash and rebase |
31ba307 to
b50f3bc
Compare
tomasklim
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.
b50f3bc to
ae78896
Compare
Head branch was pushed to by a user without write access
ae78896 to
07b65d4
Compare



Description
Implemented Cardano pool rebalancing and updated APY calculation to reflect the APY of the pool the user is staked in.
Related Issue
Resolve #22794