diff --git a/CHANGELOG.md b/CHANGELOG.md index 85fac2c18d..41d8415c4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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)) diff --git a/source/renderer/app/actions/wallets-actions.js b/source/renderer/app/actions/wallets-actions.js index f31b5d9598..c50973ce8f 100644 --- a/source/renderer/app/actions/wallets-actions.js +++ b/source/renderer/app/actions/wallets-actions.js @@ -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, @@ -44,11 +45,7 @@ export default class WalletsActions { restoreWallet: Action = new Action(); importWalletFromFile: Action = new Action(); deleteWallet: Action<{ walletId: string, isLegacy: boolean }> = new Action(); - undelegateWallet: Action<{ - walletId: string, - stakePoolId: string, - passphrase: string, - }> = new Action(); + undelegateWallet: Action = new Action(); setUndelegateWalletSubmissionSuccess: Action<{ result: boolean, }> = new Action(); diff --git a/source/renderer/app/api/api.js b/source/renderer/app/api/api.js index 8eb19aa137..1e6e5fee93 100644 --- a/source/renderer/app/api/api.js +++ b/source/renderer/app/api/api.js @@ -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, @@ -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; @@ -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, @@ -2496,7 +2511,8 @@ const _createWalletFromServerData = action( isHardwareWallet, delegatedStakePoolId, delegationStakePoolStatus, - lastDelegationStakePoolId, + lastDelegatedStakePoolId, + lastDelegationStakePoolStatus, pendingDelegations: next, discovery, }); @@ -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 }; } ); diff --git a/source/renderer/app/api/staking/types.js b/source/renderer/app/api/staking/types.js index 380d1d1858..6eba284f7d 100644 --- a/source/renderer/app/api/staking/types.js +++ b/source/renderer/app/api/staking/types.js @@ -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 = { diff --git a/source/renderer/app/api/transactions/types.js b/source/renderer/app/api/transactions/types.js index d161ae0f8e..dd8ef8ae67 100644 --- a/source/renderer/app/api/transactions/types.js +++ b/source/renderer/app/api/transactions/types.js @@ -223,7 +223,8 @@ export type CoinSelectionsResponse = { inputs: Array, outputs: Array, certificates: CoinSelectionCertificates, - feeWithDeposits: BigNumber, + deposits: BigNumber, + depositsReclaimed: BigNumber, fee: BigNumber, }; diff --git a/source/renderer/app/components/staking/delegation-setup-wizard/DelegationStepsChooseStakePoolDialog.js b/source/renderer/app/components/staking/delegation-setup-wizard/DelegationStepsChooseStakePoolDialog.js index dc1682bccb..154ed3de91 100644 --- a/source/renderer/app/components/staking/delegation-setup-wizard/DelegationStepsChooseStakePoolDialog.js +++ b/source/renderer/app/components/staking/delegation-setup-wizard/DelegationStepsChooseStakePoolDialog.js @@ -190,7 +190,7 @@ export default class DelegationStepsChooseStakePoolDialog extends Component< ); const lastDelegatedStakePoolId = get( selectedWallet, - 'lastDelegationStakePoolId', + 'lastDelegatedStakePoolId', null ); const delegatedStakePoolId = get( diff --git a/source/renderer/app/components/staking/delegation-setup-wizard/DelegationStepsConfirmationDialog.js b/source/renderer/app/components/staking/delegation-setup-wizard/DelegationStepsConfirmationDialog.js index d5714b46d2..71b13baace 100644 --- a/source/renderer/app/components/staking/delegation-setup-wizard/DelegationStepsConfirmationDialog.js +++ b/source/renderer/app/components/staking/delegation-setup-wizard/DelegationStepsConfirmationDialog.js @@ -305,15 +305,16 @@ export default class DelegationStepsConfirmationDialog extends Component {formattedWalletAmount(transactionFee.fee, false)} -  {intl.formatMessage(globalMessages.unitAda)} + {` `} + {intl.formatMessage(globalMessages.unitAda)} )}

{transactionFee && - transactionFee.deposit.isZero && - !transactionFee.deposit.isZero() && ( + transactionFee.deposits.isZero && + !transactionFee.deposits.isZero() && ( <>

@@ -321,10 +322,11 @@ export default class DelegationStepsConfirmationDialog extends Component

- {formattedWalletAmount(transactionFee.deposit, false)} + {formattedWalletAmount(transactionFee.deposits, false)} -  {intl.formatMessage(globalMessages.unitAda)} + {` `} + {intl.formatMessage(globalMessages.unitAda)}

diff --git a/source/renderer/app/components/wallet/settings/DelegateWalletButton.js b/source/renderer/app/components/wallet/settings/DelegateWalletButton.js new file mode 100644 index 0000000000..8fd9fa3cb0 --- /dev/null +++ b/source/renderer/app/components/wallet/settings/DelegateWalletButton.js @@ -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 { + static contextTypes = { + intl: intlShape.isRequired, + }; + + render() { + const { disabled, onDelegate } = this.props; + const label = this.context.intl.formatMessage(messages.label); + return ( +