Skip to content

Commit

Permalink
[DDW-149] Undelegating a wallet (#2351)
Browse files Browse the repository at this point in the history
* [DDW-149] Implement undelegate wallet dialog on wallet settings screen

* [DDW-149] Update changelog

* [DDW-149] Update fees and deposit of undelegate wallet confirmation dialog

* [DDW-149] Show fees as absolute value on delegation/undelegation dialogs

* [DDW-149] Hide undelegate wallet panel for byron wallet

* [DDW-149] Add disability to undelegate wallet button

* [DDW-149] Disable undelegate button when wallet is not delegated yet or being restored

* [DDW-149] Fix flow test

* [DDW-149] Update undelegate wallet panel on wallet settings screen

* [DDW-149] Update undelegate wallet title translations

* [DDW-149] Update undelegate wallet translations

* [DDW-149] Enable hardware wallet undelegation

* [DDW-149] Fix delegation fee calculation handler

* [DDW-149] Remove unnecessary undelege wallet handlers

* [DDW-149] Add delegate and undelegate config

* [DDW-149] Update undeleate wallet variable naming

* [DDW-149] Remove unnecessary fee absolute value transformation

* [DDW-149] Update config variable names

* [DDW-149] Remove unnecessary variable of stake pool quit request payload

* [DDW-149] Adjust undelegate wallet box margin

* [DDW-149] Update undelegate wallet success dialog naming

* [DDW-149] Update undelegate wallet panel button click handler names

* [DDW-149] Update undelegate wallet panel styles

* [DDW-149] Update undelegate wallet panel styles

* [DDW-149] Add undelegate wallet config comment

* [DDW-149] Update props definition of undelegate wallet dialog container

* [DDW-149] Fix storybook error

* [DDW-149] Add hardware wallet story for undelegating

* [DDW-149] Change Wallet Settings Delegation to reflect Future Epoch

* [DDW-149] Fix issue with null status

* [DDW-149] Add Storybook groupId

* Updates CHANGELOG, Disables 'Voting Center' for Flight builds

* Re-enable Voting registration on Flight

* [DDW-149] Merges develop

* [DDW-149] Update hardware wallet fee calculation

* [DDW-149] Update delegation and undelegation fee calculation

* [DDW-149] Update wallet sync status checking on wallet settings screen

* [DDW-149] Show warning on wallet settings screen for non delegated wallet when syncing

* [DDW-149] Fix japanese translation

* [DDW-149] Bignumber isZero function exception handling

* [DDW-149] Fix CHANGELOG

* [DDW-149] Apply current delegation status also to the wallet delegation status

* [DDW-149] Fix variable naming

* [DDW-149] Fix undelegate wallet box style

* [DDW-149] Fix delegation check logic

* [DDW-149] Remove rewarded wallet invisibility on undelegation box

* [DDW-149] Disable wallet undelegation

Co-authored-by: Danilo Prates <daniloprates@gmail.com>
Co-authored-by: Nikola Glumac <niglumac@gmail.com>
  • Loading branch information
3 people committed Feb 19, 2021
1 parent 3be768b commit bdbb16e
Show file tree
Hide file tree
Showing 47 changed files with 1,306 additions and 572 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ Changelog

## vNext

### Features

- Implemented "Undelegate wallet" feature on "Wallet settings" screen ([PR 2351](https://github.com/input-output-hk/daedalus/pull/2351))

### Fixes

- Fixed calendar style issue on Filter dialog on transaction list screen ([PR 2387](https://github.com/input-output-hk/daedalus/pull/2387))
Expand Down
7 changes: 2 additions & 5 deletions source/renderer/app/actions/wallets-actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type {
HardwareWalletExtendedPublicKeyResponse,
} from '../../../common/types/hardware-wallets.types';
import type { CsvFileContent } from '../../../common/types/csv-request.types';
import type { QuitStakePoolRequest } from '../api/staking/types';

export type WalletImportFromFileParams = {
filePath: string,
Expand Down Expand Up @@ -44,11 +45,7 @@ export default class WalletsActions {
restoreWallet: Action<any> = new Action();
importWalletFromFile: Action<WalletImportFromFileParams> = new Action();
deleteWallet: Action<{ walletId: string, isLegacy: boolean }> = new Action();
undelegateWallet: Action<{
walletId: string,
stakePoolId: string,
passphrase: string,
}> = new Action();
undelegateWallet: Action<QuitStakePoolRequest> = new Action();
setUndelegateWalletSubmissionSuccess: Action<{
result: boolean,
}> = new Action();
Expand Down
38 changes: 28 additions & 10 deletions source/renderer/app/api/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ import {
SMASH_SERVERS_LIST,
MIN_REWARDS_REDEMPTION_RECEIVER_BALANCE,
REWARDS_REDEMPTION_FEE_CALCULATION_AMOUNT,
DELEGATION_DEPOSIT,
DELEGATION_ACTIONS,
} from '../config/stakingConfig';
import {
ADA_CERTIFICATE_MNEMONIC_LENGTH,
Expand Down Expand Up @@ -998,19 +1000,30 @@ export default class AdaApi {
});
}

const deposits = map(response.deposits, (deposit) => deposit.quantity);
const totalDeposits = deposits.length
? BigNumber.sum.apply(null, deposits)
const depositsArray = map(
response.deposits,
(deposit) => deposit.quantity
);
const deposits = depositsArray.length
? BigNumber.sum.apply(null, depositsArray)
: new BigNumber(0);
const feeWithDeposits = totalInputs.minus(totalOutputs);
const fee = feeWithDeposits.minus(totalDeposits);
// @TODO - Use api response when api is ready
const depositsReclaimed =
delegation && delegation.delegationAction === DELEGATION_ACTIONS.QUIT
? new BigNumber(DELEGATION_DEPOSIT).multipliedBy(LOVELACES_PER_ADA)
: new BigNumber(0);
const fee =
delegation && delegation.delegationAction === DELEGATION_ACTIONS.QUIT
? totalInputs.minus(totalOutputs).plus(depositsReclaimed)
: totalInputs.minus(totalOutputs).minus(deposits);

const extendedResponse = {
inputs: inputsData,
outputs: outputsData,
certificates: certificatesData,
feeWithDeposits: feeWithDeposits.dividedBy(LOVELACES_PER_ADA),
fee: fee.dividedBy(LOVELACES_PER_ADA),
deposits: deposits.dividedBy(LOVELACES_PER_ADA),
depositsReclaimed: depositsReclaimed.dividedBy(LOVELACES_PER_ADA),
};
logger.debug('AdaApi::selectCoins success', { extendedResponse });
return extendedResponse;
Expand Down Expand Up @@ -2479,7 +2492,9 @@ const _createWalletFromServerData = action(
const next = get(delegation, 'next', null);
const lastPendingStakePool = next ? last(next) : null;
const lastTarget = get(lastPendingStakePool, 'target', null);
const lastDelegationStakePoolId = isLegacy ? null : lastTarget;
const lastStatus = get(lastPendingStakePool, 'status', null);
const lastDelegatedStakePoolId = isLegacy ? null : lastTarget;
const lastDelegationStakePoolStatus = isLegacy ? null : lastStatus;

return new Wallet({
id,
Expand All @@ -2496,7 +2511,8 @@ const _createWalletFromServerData = action(
isHardwareWallet,
delegatedStakePoolId,
delegationStakePoolStatus,
lastDelegationStakePoolId,
lastDelegatedStakePoolId,
lastDelegationStakePoolStatus,
pendingDelegations: next,
discovery,
});
Expand Down Expand Up @@ -2605,10 +2621,12 @@ const _createDelegationFeeFromServerData = action(
const fee = new BigNumber(
get(data, ['estimated_max', 'quantity'], 0)
).dividedBy(LOVELACES_PER_ADA);
const deposit = new BigNumber(
const deposits = new BigNumber(
get(data, ['deposit', 'quantity'], 0)
).dividedBy(LOVELACES_PER_ADA);
return { fee, deposit };
// @TODO Use api response data when api is ready
const depositsReclaimed = new BigNumber(0);
return { fee, deposits, depositsReclaimed };
}
);

Expand Down
4 changes: 3 additions & 1 deletion source/renderer/app/api/staking/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,14 @@ export type GetDelegationFeeRequest = {

export type DelegationCalculateFeeResponse = {
fee: BigNumber,
deposit: BigNumber,
deposits: BigNumber,
depositsReclaimed: BigNumber,
};

export type QuitStakePoolRequest = {
walletId: string,
passphrase: string,
isHardwareWallet?: boolean,
};

export type GetRedeemItnRewardsFeeRequest = {
Expand Down
3 changes: 2 additions & 1 deletion source/renderer/app/api/transactions/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,8 @@ export type CoinSelectionsResponse = {
inputs: Array<CoinSelectionInput>,
outputs: Array<CoinSelectionOutput>,
certificates: CoinSelectionCertificates,
feeWithDeposits: BigNumber,
deposits: BigNumber,
depositsReclaimed: BigNumber,
fee: BigNumber,
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ export default class DelegationStepsChooseStakePoolDialog extends Component<
);
const lastDelegatedStakePoolId = get(
selectedWallet,
'lastDelegationStakePoolId',
'lastDelegatedStakePoolId',
null
);
const delegatedStakePoolId = get(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -305,26 +305,28 @@ export default class DelegationStepsConfirmationDialog extends Component<Props>
{formattedWalletAmount(transactionFee.fee, false)}
</span>
<span className={styles.feesAmountLabel}>
&nbsp;{intl.formatMessage(globalMessages.unitAda)}
{` `}
{intl.formatMessage(globalMessages.unitAda)}
</span>
</>
)}
</p>
</div>
{transactionFee &&
transactionFee.deposit.isZero &&
!transactionFee.deposit.isZero() && (
transactionFee.deposits.isZero &&
!transactionFee.deposits.isZero() && (
<>
<div className={styles.depositWrapper}>
<p className={styles.depositLabel}>
{intl.formatMessage(messages.depositLabel)}
</p>
<p className={styles.depositAmount}>
<span>
{formattedWalletAmount(transactionFee.deposit, false)}
{formattedWalletAmount(transactionFee.deposits, false)}
</span>
<span className={styles.depositAmountLabel}>
&nbsp;{intl.formatMessage(globalMessages.unitAda)}
{` `}
{intl.formatMessage(globalMessages.unitAda)}
</span>
</p>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// @flow
import React, { Component } from 'react';
import { defineMessages, intlShape } from 'react-intl';
import { Button } from 'react-polymorph/lib/components/Button';
import styles from './DelegateWalletButton.scss';

const messages = defineMessages({
label: {
id: 'wallet.settings.delegateWalletButtonLabel',
defaultMessage: '!!!Delegate',
description: 'Label for the delegate button on wallet settings',
},
});

type Props = {
disabled?: boolean,
onDelegate: Function,
};

export default class DelegateWalletButton extends Component<Props> {
static contextTypes = {
intl: intlShape.isRequired,
};

render() {
const { disabled, onDelegate } = this.props;
const label = this.context.intl.formatMessage(messages.label);
return (
<Button
label={label}
disabled={disabled}
onClick={onDelegate}
themeOverrides={styles}
/>
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.root {
font-weight: 500;
height: 36px;
line-height: 36px;
margin-left: 20px;
min-width: 160px;
width: 160px;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// @flow
import React, { Component } from 'react';
import { defineMessages, intlShape } from 'react-intl';
import { Button } from 'react-polymorph/lib/components/Button';
import styles from './UndelegateWalletButton.scss';

const messages = defineMessages({
label: {
id: 'wallet.settings.undelegateWalletButtonLabel',
defaultMessage: '!!!Undelegate',
description: 'Label for the undelegate button on wallet settings',
},
});

type Props = {
disabled?: boolean,
onUndelegate: Function,
};

export default class UndelegateWalletButton extends Component<Props> {
static contextTypes = {
intl: intlShape.isRequired,
};

render() {
const { disabled, onUndelegate } = this.props;
const label = this.context.intl.formatMessage(messages.label);
return (
<Button
className="flat"
label={label}
disabled={disabled}
onClick={onUndelegate}
themeOverrides={styles}
/>
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.root {
font-weight: 500;
height: 36px;
line-height: 36px;
margin-left: 20px;
min-width: 160px;
width: 160px;
}

0 comments on commit bdbb16e

Please sign in to comment.