Skip to content
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

[DDW-435] Filtering stake pools through checkboxes - Private, Retiring and Pools without off-chain data #2461

Open
wants to merge 53 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
b245537
[DDW-435] Stake pool filter dialog draft
topseniors Mar 16, 2021
6172903
[DDW-435] Stake pool filter dialog view and handlers
topseniors Mar 17, 2021
b0b901f
Merge branch 'develop' into feature/ddw-435-filtering-stake-pools-thr…
nikolaglumac Mar 19, 2021
d578ad0
[DDW-435] Update stakingstore for filtering
topseniors Mar 22, 2021
033c011
Merge branch 'feature/ddw-435-filtering-stake-pools-through-checkboxe…
topseniors Mar 22, 2021
1078201
[DDW-435] Update theme variables for stake pool filter modal
topseniors Mar 23, 2021
9cfbe20
[DDW-435] Update theme variables for stake pool filter modal and tran…
topseniors Mar 23, 2021
eded65d
[DDW-435] Update stake pool filter modal markup and styles
topseniors Mar 23, 2021
30eefd0
[DDW-435] Update staking store
topseniors Mar 23, 2021
4a723c3
[DDW-435] Update stake pools filter logic
topseniors Mar 23, 2021
547736f
[DDW-435] Update stake pools filter logic
topseniors Mar 23, 2021
31bf016
[DDW-435] Update stake pool tooltip info for no metadata case
topseniors Mar 23, 2021
d2756e1
[DDW-435] Apply dynamic style to stake pool search input
topseniors Mar 23, 2021
c321bf7
[DDW-435] Fix flow errors and update translations
topseniors Mar 23, 2021
638cd0c
Merge branch 'develop' into feature/ddw-435-filtering-stake-pools-thr…
topseniors Mar 23, 2021
ac228d6
[DDW-435] Update changelog
topseniors Mar 23, 2021
17f7669
[DDW-435] Update stakepool filter props
topseniors Mar 26, 2021
3834f7c
Merge branch 'develop' into feature/ddw-435-filtering-stake-pools-thr…
topseniors Mar 26, 2021
e519c8b
[DDW-435] Update stakepool filter translations for private and retiri…
topseniors Mar 26, 2021
7ce66ca
[DDW-435] Update japanese translations
topseniors Mar 26, 2021
6c86261
[DDW-435] Fix delegation issue while device not selected at first
Mar 26, 2021
e038e1a
Merge branch 'feature/ddw-435-filtering-stake-pools-through-checkboxe…
Mar 26, 2021
00ea17d
[DDW-435] Show private, retiring and high profit margin pool warnings…
topseniors Mar 26, 2021
09899f5
[DDW-435] Remove unnecessary eslint disable marker
topseniors Mar 26, 2021
494b114
Merge branch 'develop' into feature/ddw-435-filtering-stake-pools-thr…
topseniors Mar 26, 2021
f997afb
[DDW-435] Update styles for stake pool filter popup
topseniors Mar 26, 2021
c7a7660
[DDW-435] Restore form values when hiding filter popup on stake pool
topseniors Mar 26, 2021
c60c08d
[DDW-435] Update styles of filter popup on stake pools
topseniors Mar 26, 2021
f057bc3
[DDW-435] Show ordered stake pools by default
topseniors Mar 26, 2021
66e73e9
Merge branch 'develop' into feature/ddw-435-filtering-stake-pools-thr…
topseniors Mar 26, 2021
343be03
[DDW-435] Fix ranked stake pools calculation logic when filtering
topseniors Mar 29, 2021
5d310b1
[DDW-435] Update stake pools ranking using index
topseniors Mar 30, 2021
6884d1e
[DDW-435] Update stake pools filter lables
topseniors Mar 30, 2021
8d41b74
Merge branch 'develop' into feature/ddw-435-filtering-stake-pools-thr…
topseniors Mar 30, 2021
95c6eca
Merge branch 'develop' into feature/ddw-435-filtering-stake-pools-thr…
topseniors Mar 30, 2021
c65f1e2
[DDW-435] Update missing props after merging develop
topseniors Mar 31, 2021
6306bc5
[DDW-435] Update stake pool ranking index handler
topseniors Mar 31, 2021
d849ace
[DDW-435] Fix stake pool tile style
topseniors Mar 31, 2021
2340db7
[DDW-435] Adjust stake pool filter popover style
topseniors Mar 31, 2021
7995c22
[DDW-435] Fix stake pool list view style
topseniors Mar 31, 2021
e8303bc
[DDW-435] Add empty filter warning
topseniors Mar 31, 2021
409f3af
[DDW-435] Fix missing props
topseniors Mar 31, 2021
8f77cd4
[DDW-435] Fix stake pools filter behavior
topseniors Mar 31, 2021
d38fbed
[DDW-435] Adjust stake pools filter popover style
topseniors Mar 31, 2021
a43856f
[DDW-435] Adjust stake pools filter popover style
topseniors Mar 31, 2021
e2e5581
[DDW-435] Run translations manager
topseniors Mar 31, 2021
fa0c282
[DDW-435] Fix modal overlay style
topseniors Apr 1, 2021
02ac0a6
Merge branch 'develop' into feature/ddw-435-filtering-stake-pools-thr…
topseniors Apr 1, 2021
691cdf2
[DDW-435] Merges develop
nikolaglumac Apr 19, 2021
23d25aa
[DDW-435] Merges develop
nikolaglumac Sep 13, 2021
1dff6e0
Merge branch 'develop' into feature/ddw-435-filtering-stake-pools-thr…
nikolaglumac Sep 14, 2021
0a2cafa
[DDW-435] Merges develop
nikolaglumac Oct 21, 2021
61523db
Merge branch 'develop' into feature/ddw-435-filtering-stake-pools-thr…
thedanheller Nov 8, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Features

- Implemented stake pools filter pop over ([PR 2461](https://github.com/input-output-hk/daedalus/pull/2461))
- Added Catalyst footer links ([PR 2721](https://github.com/input-output-hk/daedalus/pull/2721))
- Fixed the Delegation popover timeout ([PR 2722](https://github.com/input-output-hk/daedalus/pull/2722))
- Removed "Alonzo tada" icon and "Alonzo countdown" screen ([PR 2708](https://github.com/input-output-hk/daedalus/pull/2708))
Expand Down Expand Up @@ -201,7 +202,7 @@

- Added absolute slot number to Catalyst voting registration transaction metadata ([PR 2476](https://github.com/input-output-hk/daedalus/pull/2476))
- Improved the transactions and rewards CSV export contents ([PR 2451](https://github.com/input-output-hk/daedalus/pull/2451))
- Implement Trezor passphrase handling ([PR 2284](https://github.com/input-output-hk/daedalus/pull/2284))
- Implemented Trezor passphrase handling ([PR 2284](https://github.com/input-output-hk/daedalus/pull/2284))

### Fixes

Expand Down
2 changes: 2 additions & 0 deletions source/renderer/app/actions/staking-actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type {
QuitStakePoolRequest,
} from '../api/staking/types';
import type { CsvFileContent } from '../../../common/types/csv-request.types';
import type { StakePoolFilterOptionsType } from '../stores/StakingStore';
// ======= STAKING ACTIONS =======

export default class StakingActions {
Expand Down Expand Up @@ -33,5 +34,6 @@ export default class StakingActions {
onConfirmationContinue: Action<{ spendingPassword: string }> = new Action();
onResultContinue: Action<any> = new Action();
closeRedeemDialog: Action<any> = new Action();
filterStakePools: Action<StakePoolFilterOptionsType> = new Action();
setStakingInfoWasOpen: Action<any> = new Action();
}
12 changes: 5 additions & 7 deletions source/renderer/app/api/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -2227,16 +2227,10 @@ export default class AdaApi {
stake
);
const stakePools = response
.filter(({ metadata }: AdaApiStakePool) => metadata !== undefined)
.filter(({ flags }: AdaApiStakePool) => !flags.includes('delisted'))
.filter(
({ margin }: AdaApiStakePool) =>
margin !== undefined && margin.quantity < 100
)
.map(_createStakePoolFromServerData);
logger.debug('AdaApi::getStakePools success', {
stakePoolsTotal: response.length,
stakePoolsWithMetadata: stakePools.length,
unfilteredStakePools: response,
});
return stakePools;
Expand Down Expand Up @@ -2974,7 +2968,8 @@ const _createStakePoolFromServerData = action(
non_myopic_member_rewards: nonMyopicMemberRewards,
saturation,
} = metrics; // eslint-disable-line
const { name, description = '', ticker, homepage } = metadata;
const { name = '', description = '', ticker = '', homepage = '' } =
metadata || {};
const relativeStakePercentage = get(relativeStake, 'quantity', 0);
const producedBlocksCount = get(producedBlocks, 'quantity', 0);
const nonMyopicMemberRewardsQuantity = get(
Expand Down Expand Up @@ -3007,6 +3002,9 @@ const _createStakePoolFromServerData = action(
ranking: index + 1,
retiring: retiringAt ? new Date(retiringAt) : null,
saturation: saturation * 100,
isRetiring: !!retiringAt,
isPrivate: profitMarginPercentage === 100,
hasNoOffChainData: !metadata,
});
}
);
Expand Down
4 changes: 1 addition & 3 deletions source/renderer/app/components/layout/SidebarLayout.scss
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
overflow: hidden;
position: relative;
width: 100%;
// Show elements that overflow the main above the sidebar area
z-index: 20;
}

.sidebar {
Expand All @@ -25,7 +23,7 @@
box-shadow: 0 5px 20px 0 var(--theme-sidebar-layout-topbar-shadow-color);
flex-shrink: 0;
// Show elements that overflow the topbar above the content area
z-index: 20;
z-index: 10000;
}

.contentWrapper {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,7 @@ export default class WalletRow extends Component<Props, WalletRowState> {
onOpenExternalLink={onOpenExternalLink}
openWithDelay={false}
stakePool={futurePendingDelegatedStakePool}
ranking={futurePendingDelegatedStakePool.ranking}
containerClassName={containerClassName}
numberOfRankedStakePools={numberOfRankedStakePools}
showWithSelectButton={showWithSelectButton}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import DelegationStepsNotAvailableDialog from './DelegationStepsNotAvailableDial
import DelegationStepsChooseStakePoolDialog from './DelegationStepsChooseStakePoolDialog';
import LocalizableError from '../../../i18n/LocalizableError';
import StakePool from '../../../domains/StakePool';
import type { StakePoolFilterOptionsType } from '../../../stores/StakingStore';
import Wallet from '../../../domains/Wallet';

import type { DelegationCalculateFeeResponse } from '../../../api/staking/types';
import type { HwDeviceStatus } from '../../../domains/Wallet';

Expand Down Expand Up @@ -42,6 +42,9 @@ type Props = {
currentLocale: string,
getStakePoolById: Function,
hwDeviceStatus: HwDeviceStatus,
filterOptions: StakePoolFilterOptionsType,
onFilter: Function,
populatedFilterOptions: StakePoolFilterOptionsType,
isTrezor: boolean,
};

Expand Down Expand Up @@ -87,6 +90,9 @@ export default class DelegationSetupWizardDialog extends Component<Props> {
error,
getStakePoolById,
hwDeviceStatus,
filterOptions,
onFilter,
populatedFilterOptions,
isTrezor,
} = this.props;

Expand Down Expand Up @@ -132,6 +138,9 @@ export default class DelegationSetupWizardDialog extends Component<Props> {
onClose={onClose}
onBack={onBack}
onSelectPool={onSelectPool}
filterOptions={filterOptions}
onFilter={onFilter}
populatedFilterOptions={populatedFilterOptions}
/>
);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ import styles from './DelegationStepsChooseStakePoolDialog.scss';
import Wallet from '../../../domains/Wallet';
import ThumbSelectedPool from '../widgets/ThumbSelectedPool';
import { IS_RANKING_DATA_AVAILABLE } from '../../../config/stakingConfig';
import type { StakePoolFilterOptionsType } from '../../../stores/StakingStore';
import {
getNumberOfFilterDimensionsApplied,
hasStakePoolHighProfitMargin,
} from '../../../utils/staking';
import StakePool from '../../../domains/StakePool';

const messages = defineMessages({
Expand Down Expand Up @@ -115,10 +120,25 @@ const messages = defineMessages({
id:
'staking.delegationSetup.chooseStakePool.step.dialog.retiringPoolFooter',
defaultMessage:
'!!!The stake pool you have selected is about to be retired. If you continue the delegation process, you will need to delegate your stake to another pool at least one complete epoch before the current pool’s retirement date to avoid losing rewards.',
'!!!The stake pool you have selected is about to be retired. If you delegate to this pool, you will need to redelegate your wallet to a different pool at least one entire epoch before the current pool’s retirement date to avoid losing rewards.',
description:
'Retiring Pool Footer label on the delegation setup "choose wallet" step dialog.',
},
privatePoolFooter: {
id: 'staking.delegationSetup.chooseStakePool.step.dialog.privatePoolFooter',
defaultMessage:
'!!!The stake pool you have selected is private as its margin is 100%. If you delegate to this pool, all rewards will go to the stake pool, and you will not earn delegation rewards.',
description:
'Private Pool Footer label on the delegation setup "choose wallet" step dialog.',
},
highProfitMarginPoolFooter: {
id:
'staking.delegationSetup.chooseStakePool.step.dialog.highProfitMarginPoolFooter',
defaultMessage:
'!!!The stake pool you have selected has a high margin of {profitMarginPercentage}%. You could earn more rewards by delegating to a different pool. Delegating to pools with high margins is not a concern if they are charity pools or if you are supporting a pool for different reasons.',
description:
'High Profit Margin Pool Footer label on the delegation setup "choose wallet" step dialog.',
},
});

type Props = {
Expand All @@ -132,6 +152,9 @@ type Props = {
onClose: Function,
onBack: Function,
onSelectPool: Function,
filterOptions: StakePoolFilterOptionsType,
onFilter: Function,
populatedFilterOptions: StakePoolFilterOptionsType,
};

type State = {
Expand Down Expand Up @@ -177,6 +200,9 @@ export default class DelegationStepsChooseStakePoolDialog extends Component<
selectedWallet,
onClose,
onBack,
filterOptions,
onFilter,
populatedFilterOptions,
} = this.props;
const { searchValue, selectedPoolId } = this.state;
const selectedWalletName = get(selectedWallet, 'name');
Expand Down Expand Up @@ -217,12 +243,38 @@ export default class DelegationStepsChooseStakePoolDialog extends Component<
},
];

const footer =
selectedPool && selectedPool.retiring ? (
<div className={styles.retiringPoolFooter}>
const retiringFooter =
selectedPool && selectedPool.isRetiring ? (
<div className={styles.poolFooterContent}>
{intl.formatMessage(messages.retiringPoolFooter)}
</div>
) : null;
const privateFooter =
selectedPool && selectedPool.isPrivate ? (
<div className={styles.poolFooterContent}>
{intl.formatMessage(messages.privatePoolFooter)}
</div>
) : null;
const highProfitMarginFooter =
selectedPool &&
!selectedPool.isPrivate &&
hasStakePoolHighProfitMargin(selectedPool) ? (
<div className={styles.poolFooterContent}>
<FormattedHTMLMessage
{...messages.highProfitMarginPoolFooter}
values={{
profitMarginPercentage: selectedPool.profitMargin,
}}
/>
</div>
) : null;
const footer = (
<div className={styles.poolFooter}>
{retiringFooter}
{privateFooter}
{highProfitMarginFooter}
</div>
);

const dialogClassName = classNames([
commonStyles.delegationSteps,
Expand Down Expand Up @@ -299,11 +351,18 @@ export default class DelegationStepsChooseStakePoolDialog extends Component<
/>
);

const numberOfFilterDimensionsApplied = getNumberOfFilterDimensionsApplied(
filterOptions
);

const filteredStakePoolsList: Array<StakePool> = getFilteredStakePoolsList(
stakePoolsList,
searchValue
);

const isFilterDisabled =
!filteredStakePoolsList.length && !numberOfFilterDimensionsApplied;

const numberOfRankedStakePools: number = stakePoolsList.filter(
(stakePool) =>
IS_RANKING_DATA_AVAILABLE && stakePool.nonMyopicMemberRewards
Expand Down Expand Up @@ -345,6 +404,7 @@ export default class DelegationStepsChooseStakePoolDialog extends Component<
<div className={styles.selectStakePoolWrapper}>
<ThumbSelectedPool
stakePool={selectedPool}
ranking={selectedPool.ranking}
numberOfRankedStakePools={numberOfRankedStakePools}
alreadyDelegated={selectedPool && !canSubmit}
/>
Expand Down Expand Up @@ -386,6 +446,12 @@ export default class DelegationStepsChooseStakePoolDialog extends Component<
onClearSearch={this.handleClearSearch}
scrollableElementClassName="Dialog_content"
disabledStakePoolId={activeStakePoolId}
filterPopOverProps={{
populatedFilterOptions,
onFilter,
isFilterDisabled,
numberOfFilterDimensionsApplied,
}}
/>
</div>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,12 +161,20 @@
}
}

.retiringPoolFooter {
.poolFooter {
color: var(--theme-staking-stake-pool-retirement-background-color);
font-family: var(--font-medium);
font-size: 16px;
line-height: 1.38;
margin: 20px 0;
text-align: center;
text-align: left;

.poolFooterContent {
margin-bottom: 10px;

&:last-child {
margin-bottom: 0;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import Dialog from '../../widgets/Dialog';
import ReactToolboxMobxForm from '../../../utils/ReactToolboxMobxForm';
import { formattedWalletAmount } from '../../../utils/formatters';
import { submitOnEnter } from '../../../utils/form';
import { hasStakePoolHighProfitMargin } from '../../../utils/staking';
import globalMessages from '../../../i18n/global-messages';
import LocalizableError from '../../../i18n/LocalizableError';
import { FORM_VALIDATION_DEBOUNCE_WAIT } from '../../../config/timingConfig';
Expand Down Expand Up @@ -105,6 +106,29 @@ const messages = defineMessages({
defaultMessage: '!!!Calculating deposit',
description: '"Calculating deposit" message in the "confirmation" dialog.',
},
retiringPoolFooter: {
id:
'staking.delegationSetup.chooseStakePool.step.dialog.retiringPoolFooter',
defaultMessage:
'!!!The stake pool you have selected is about to be retired. If you delegate to this pool, you will need to redelegate your wallet to a different pool at least one entire epoch before the current pool’s retirement date to avoid losing rewards.',
description:
'Retiring Pool Footer label on the delegation setup "confirmation" step dialog.',
},
privatePoolFooter: {
id: 'staking.delegationSetup.chooseStakePool.step.dialog.privatePoolFooter',
defaultMessage:
'!!!The stake pool you have selected is private as its margin is 100%. If you delegate to this pool, all rewards will go to the stake pool, and you will not earn delegation rewards.',
description:
'Private Pool Footer label on the delegation setup "confirmation" step dialog.',
},
highProfitMarginPoolFooter: {
id:
'staking.delegationSetup.chooseStakePool.step.dialog.highProfitMarginPoolFooter',
defaultMessage:
'!!!The stake pool you have selected has a high margin of {profitMarginPercentage}%. You could earn more rewards by delegating to a different pool. Delegating to pools with high margins is not a concern if they are charity pools or if you are supporting a pool for different reasons.',
description:
'High Profit Margin Pool Footer label on the delegation setup "confirmation" step dialog.',
},
});

messages.fieldIsRequired = globalMessages.fieldIsRequired;
Expand Down Expand Up @@ -251,11 +275,45 @@ export default class DelegationStepsConfirmationDialog extends Component<Props>
/>
);

const retiringFooter =
selectedPool && selectedPool.isRetiring ? (
<div className={styles.poolFooterContent}>
{intl.formatMessage(messages.retiringPoolFooter)}
</div>
) : null;
const privateFooter =
selectedPool && selectedPool.isPrivate ? (
<div className={styles.poolFooterContent}>
{intl.formatMessage(messages.privatePoolFooter)}
</div>
) : null;
const highProfitMarginFooter =
selectedPool &&
!selectedPool.isPrivate &&
hasStakePoolHighProfitMargin(selectedPool) ? (
<div className={styles.poolFooterContent}>
<FormattedHTMLMessage
{...messages.highProfitMarginPoolFooter}
values={{
profitMarginPercentage: selectedPool.profitMargin,
}}
/>
</div>
) : null;
const footer = (
<div className={styles.poolFooter}>
{retiringFooter}
{privateFooter}
{highProfitMarginFooter}
</div>
);

return (
<Dialog
title={intl.formatMessage(messages.title)}
subtitle={stepsIndicatorLabel}
actions={actions}
footer={footer}
closeOnOverlayClick
onClose={!isSubmitting ? onClose : () => {}}
className={dialogClassName}
Expand Down
Loading