Skip to content

Commit

Permalink
Merge pull request #3870 from LiskHQ/3768-warn-users-voting-punished-…
Browse files Browse the repository at this point in the history
…delegate

Warn users when voting a punished delegate - Closes #3768
  • Loading branch information
ManuGowda authored Nov 1, 2021
2 parents f29d78d + 5c4d896 commit 5b51ac3
Show file tree
Hide file tree
Showing 14 changed files with 372 additions and 29 deletions.
5 changes: 5 additions & 0 deletions i18n/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@
"By voting you decide who is trusted to verify transactions and maintain the Lisk network, whilst collecting the rewards for doing so.": "By voting you decide who is trusted to verify transactions and maintain the Lisk network, whilst collecting the rewards for doing so.",
"Bytes counter": "Bytes counter",
"Cancel": "Cancel",
"Caution! This delegate was punished on {{punishmentStartDate}}. There is approximately {{daysLeft}} days remaining before the punishment ends.": "Caution! This delegate was punished on {{punishmentStartDate}}. There is approximately {{daysLeft}} days remaining before the punishment ends.",
"Caution! You are about to vote for the punished delegate, this will result in your LSK tokens being locked for a period of {{daysLeft}} days.": "Caution! You are about to vote for the punished delegate, this will result in your LSK tokens being locked for a period of {{daysLeft}} days.",
"Changed votes": "Changed votes",
"Check for Updates...": "Check for Updates...",
"Choose your avatar": "Choose your avatar",
Expand Down Expand Up @@ -502,6 +504,7 @@
"This account requires {{numberOfSignatures}} signatures to create a valid transaction.": "This account requires {{numberOfSignatures}} signatures to create a valid transaction.",
"This avatar will be linked to your new Lisk address.": "This avatar will be linked to your new Lisk address.",
"This delegate can not forge new blocks temporarily due to a protocol violation.": "This delegate can not forge new blocks temporarily due to a protocol violation.",
"This delegate has been permanently banned from {{punishmentStartDate}}": "This delegate has been permanently banned from {{punishmentStartDate}}",
"This delegate is among the first 101 delegates in delegate weight ranking.": "This delegate is among the first 101 delegates in delegate weight ranking.",
"This delegate is permanently banned from forging new blocks.": "This delegate is permanently banned from forging new blocks.",
"This delegate will be punished in upcoming rounds": "This delegate will be punished in upcoming rounds",
Expand Down Expand Up @@ -565,6 +568,7 @@
"Vote aborted on device": "Vote aborted on device",
"Vote amount": "Vote amount",
"Vote amount (LSK)": "Vote amount (LSK)",
"Vote for delegate": "Vote for delegate",
"Vote submission failed": "Vote submission failed",
"Voted delegates": "Voted delegates",
"Voter": "Voter",
Expand Down Expand Up @@ -605,6 +609,7 @@
"You can only vote in multiplies of 10 LSK.": "You can only vote in multiplies of 10 LSK.",
"You can share your Lisk ID with anyone you wish, but never reveal your passphrase to anyone as it would allow full access to your account.": "You can share your Lisk ID with anyone you wish, but never reveal your passphrase to anyone as it would allow full access to your account.",
"You can't vote for more than 10 delegates.": "You can't vote for more than 10 delegates.",
"You cannot vote for this delegate": "You cannot vote for this delegate",
"You don't have enough LSK in your account.": "You don't have enough LSK in your account.",
"You don’t have any bookmarks yet.": "You don’t have any bookmarks yet.",
"You have already registered as a delegate.": "You have already registered as a delegate.",
Expand Down
3 changes: 3 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ module.exports = {
'src/components/shared/searchBar/transactions.js',
'src/components/shared/navigationBars/topBar/networkName.js',
'src/components/shared/multisignatureMembers/index.js',
'src/components/shared/warnPunishedDelegate/warnPunishedDelegate.js',
'src/components/shared/warnPunishedDelegate/index.js',
'src/components/shared/warnPunishedDelegate/voteWarning.js',
'src/components/toolbox/tabsContainer/tabsContainer.js',
'src/components/toolbox/copyToClipboard/index.js',
'src/components/toolbox/dropdown/toolBoxDropdown.js',
Expand Down
4 changes: 4 additions & 0 deletions src/components/screens/editVote/editVote.css
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,7 @@
width: 100%;
}
}

.space {
margin: 10px;
}
15 changes: 14 additions & 1 deletion src/components/screens/editVote/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { useEffect, useState } from 'react';
import { withRouter } from 'react-router-dom';
import { withTranslation } from 'react-i18next';
import { useDispatch, useSelector } from 'react-redux';
import { compose } from 'redux';

import { selectSearchParamValue, removeSearchParamsFromUrl } from '@utils/searchParams';
import { tokenMap } from '@constants';
Expand All @@ -17,6 +18,7 @@ import BoxInfoText from '@toolbox/box/infoText';
import AmountField from '@shared/amountField';
import LiskAmount from '@shared/liskAmount';
import Converter from '@shared/converter';
import WarnPunishedDelegate from '@shared/warnPunishedDelegate';
import { PrimaryButton, WarningButton } from '@toolbox/buttons';
import useVoteAmountField from './useVoteAmountField';
import getMaxAmount from './getMaxAmount';
Expand All @@ -41,6 +43,8 @@ const AddVote = ({
const { account, network, voting } = useSelector(state => state);
const host = useSelector(state => state.account.info.LSK.summary.address);
const address = selectSearchParamValue(history.location.search, 'address');
const start = selectSearchParamValue(history.location.search, 'start');
const end = selectSearchParamValue(history.location.search, 'end');
const existingVote = useSelector(state => state.voting[address || host]);
const balance = useSelector(selectAccountBalance);
const [voteAmount, setVoteAmount] = useVoteAmountField(existingVote ? fromRawLsk(existingVote.unconfirmed) : '');
Expand Down Expand Up @@ -94,6 +98,12 @@ const AddVote = ({
/>
</div>
</BoxInfoText>
{start !== undefined && (
<>
<WarnPunishedDelegate pomHeight={{ start, end }} vote />
<span className={styles.space} />
</>
)}
<label className={styles.fieldGroup}>
<AmountField
amount={voteAmount}
Expand Down Expand Up @@ -125,4 +135,7 @@ const AddVote = ({
);
};

export default withRouter(withTranslation()(AddVote));
export default compose(
withRouter,
withTranslation(),
)(AddVote);
4 changes: 3 additions & 1 deletion src/components/screens/wallet/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { withTranslation } from 'react-i18next';
import { compose } from 'redux';

import { parseSearchParams, addSearchParamsToUrl } from '@utils/searchParams';
import { withRouter } from 'react-router';
import { transactionsRetrieved } from '@actions';
import {
selectAccount,
Expand Down Expand Up @@ -93,4 +95,4 @@ const Wallet = ({ t, history }) => {
);
};

export default withTranslation()(Wallet);
export default compose(withRouter, withTranslation())(Wallet);
34 changes: 26 additions & 8 deletions src/components/screens/wallet/overview/balanceInfo/actionBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ import { withTranslation } from 'react-i18next';
import { useSelector } from 'react-redux';
import { PrimaryButton, SecondaryButton, TertiaryButton } from '@toolbox/buttons';
import DialogLink from '@toolbox/dialog/link';
import Tooltip from '@toolbox/tooltip/tooltip';
import SignInTooltipWrapper from '@shared/signInTooltipWrapper';
import { selectAccountBalance, selectLSKAddress } from '@store/selectors';
import EmptyBalanceTooltipWrapper from './emptyBalanceTooltipWrapper';
import styles from './balanceInfo.css';

// eslint-disable-next-line complexity
const ActionBar = ({
username, address, t, isWalletRoute, activeToken,
username, address, t, isWalletRoute, activeToken, isBanned, pomStart,
}) => {
const hostBalance = useSelector(selectAccountBalance);
const disableButtons = hostBalance === 0;
Expand All @@ -31,14 +33,30 @@ const ActionBar = ({
<div className={styles.actionRow}>
{
username && (
<DialogLink component="editVote" className={`${styles.button} add-vote`}>
<SecondaryButton
className={`${styles.voteButton} open-add-vote-dialog`}
size="m"
disabled={disableButtons}
<DialogLink
component={!isBanned && 'editVote'}
data={pomStart}
className={`${styles.button} add-vote`}
>
<Tooltip
position="bottom"
size="maxContent"
content={(
<SecondaryButton
className={`${styles.voteButton} ${
isBanned && styles.disabled} ${!isBanned && 'open-add-vote-dialog'}`}
size="m"
>
{voteButtonTitle}
</SecondaryButton>
)}
>
{voteButtonTitle}
</SecondaryButton>
<p>
{isBanned
? t('You cannot vote for this delegate')
: t('Vote for delegate')}
</p>
</Tooltip>
</DialogLink>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,13 @@
}
}

.disabled {
cursor: not-allowed;
opacity: 0.5;
color: gray;
font-weight: 100;
}

.emptyBalanceTooltipWrapper {
display: inline-block;
}
Expand Down
5 changes: 4 additions & 1 deletion src/components/screens/wallet/overview/balanceInfo/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ import LockedBalanceLink from './unlocking';
import ActionBar from './actionBar';
import styles from './balanceInfo.css';

// eslint-disable-next-line complexity
const BalanceInfo = ({
t, activeToken, balance, isWalletRoute, address, username,
t, activeToken, balance, isWalletRoute, address, username, isBanned, pomStart,
}) => (
<Box className={`${styles.wrapper}`}>
<BoxContent className={styles.content}>
Expand All @@ -39,6 +40,8 @@ const BalanceInfo = ({
username={username}
isWalletRoute={isWalletRoute}
activeToken={activeToken}
isBanned={isBanned}
pomStart={pomStart}
/>
</BoxContent>
</Box>
Expand Down
102 changes: 85 additions & 17 deletions src/components/screens/wallet/overview/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable max-statements */
import React, { useEffect } from 'react';
import { useSelector } from 'react-redux';
import { compose } from 'redux';
Expand All @@ -6,31 +7,83 @@ import grid from 'flexboxgrid/dist/flexboxgrid.css';
import withData from '@utils/withData';
import { getTransactions } from '@api/transaction';
import { selectTransactions } from '@store/selectors';
import FlashMessageHolder from '@toolbox/flashMessage/holder';
import WarnPunishedDelegate from '@shared/warnPunishedDelegate';
import { withRouter } from 'react-router';
import BalanceChart from './balanceChart';
import AccountInfo from './accountInfo';
import BalanceInfo from './balanceInfo';
import styles from './overview.css';

const addWarningMessage = ({ isBanned, pomHeight, readMore }) => {
FlashMessageHolder.addMessage(
<WarnPunishedDelegate
isBanned={isBanned}
pomHeight={pomHeight}
readMore={readMore}
/>,
'WarnPunishedDelegate',
);
};

const removeWarningMessage = () => {
FlashMessageHolder.deleteMessage('WarnPunishedDelegate');
};

const Overview = ({
t, activeToken, transactions, hwInfo,
discreetMode, isWalletRoute, account,
t,
activeToken,
transactions,
hwInfo,
discreetMode,
isWalletRoute,
account,
history,
}) => {
const {
address, publicKey, balance = 0, isMultisignature,
address,
publicKey,
balance = 0,
isMultisignature,
} = account?.summary ?? {};
const { confirmed } = useSelector(selectTransactions);
const bookmark = useSelector(
state => state.bookmarks[activeToken].find(item => (item.address === address)),
);
const isBanned = account?.dpos?.delegate?.isBanned;
const pomHeights = account?.dpos?.delegate?.pomHeights;

const { confirmed } = useSelector(selectTransactions);
const bookmark = useSelector((state) =>
state.bookmarks[activeToken].find((item) => item.address === address));
const host = useSelector(
state => (
state.account
&& state.account.info
&& state.account.info[activeToken]
&& state.account.info[activeToken].summary?.address) || '',
(state) =>
(state.account
&& state.account.info
&& state.account.info[activeToken]
&& state.account.info[activeToken].summary?.address)
|| '',
);

const showWarning = () => {
if (!isWalletRoute && host && address && (isBanned || pomHeights?.length)) {
addWarningMessage({
isBanned,
pomHeight: pomHeights[pomHeights.length - 1],
readMore: () => {
// TODO define blog entry url - #3907
const url = '';
window.open(url, '_blank', 'rel="noopener noreferrer');
},
});
} else {
removeWarningMessage();
}
};

useEffect(() => {
const params = history?.location.search;
if (params === '') {
removeWarningMessage();
}
}, []);

useEffect(() => {
if (!isWalletRoute && address) {
transactions.loadData({ address });
Expand All @@ -39,7 +92,12 @@ const Overview = ({

return (
<section className={`${grid.row} ${styles.wrapper}`}>
<div className={`${grid['col-xs-6']} ${grid['col-md-3']} ${grid['col-lg-3']}`}>
{
showWarning()
}
<div
className={`${grid['col-xs-6']} ${grid['col-md-3']} ${grid['col-lg-3']}`}
>
<AccountInfo
t={t}
hwInfo={hwInfo}
Expand All @@ -53,7 +111,9 @@ const Overview = ({
isMultisignature={isMultisignature}
/>
</div>
<div className={`${grid['col-xs-6']} ${grid['col-md-3']} ${grid['col-lg-3']}`}>
<div
className={`${grid['col-xs-6']} ${grid['col-md-3']} ${grid['col-lg-3']}`}
>
<BalanceInfo
t={t}
activeToken={activeToken}
Expand All @@ -62,9 +122,15 @@ const Overview = ({
isWalletRoute={isWalletRoute}
username={account?.dpos?.delegate?.username}
address={address}
isBanned={isBanned}
pomStart={pomHeights?.length
? { ...pomHeights[pomHeights.length - 1] }
: {}}
/>
</div>
<div className={`${grid['col-xs-12']} ${grid['col-md-6']} ${grid['col-lg-6']} ${styles.balanceChart}`}>
<div
className={`${grid['col-xs-12']} ${grid['col-md-6']} ${grid['col-lg-6']} ${styles.balanceChart}`}
>
{address && (
<BalanceChart
t={t}
Expand All @@ -81,10 +147,12 @@ const Overview = ({
};

export default compose(
withRouter,
withData({
transactions: {
apiUtil: (network, { token, ...params }) => getTransactions({ network, params }, token),
getApiParams: state => ({
apiUtil: (network, { token, ...params }) =>
getTransactions({ network, params }, token),
getApiParams: (state) => ({
token: state.settings.token.active,
}),
defaultData: { data: [], meta: {} },
Expand Down
Loading

0 comments on commit 5b51ac3

Please sign in to comment.