From b7f1c6011534c510f38d1a9cac4aeccd2d50531c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Bruus=20Zeppelin?= Date: Tue, 29 Oct 2024 13:49:32 +0100 Subject: [PATCH 1/2] Remove delegation --- .../src/popup/popupX/constants/routes.ts | 4 ---- .../Delegator/Result/DelegationResult.tsx | 17 ++++++++--------- .../pages/EarningRewards/Delegator/Status.tsx | 10 ++++++++-- .../popupX/pages/EarningRewards/i18n/en.ts | 6 ++++++ .../src/popup/popupX/shell/Routes.tsx | 1 - .../src/shared/utils/time-helpers.ts | 2 +- 6 files changed, 23 insertions(+), 17 deletions(-) diff --git a/packages/browser-wallet/src/popup/popupX/constants/routes.ts b/packages/browser-wallet/src/popup/popupX/constants/routes.ts index dab5219b..c299f8e3 100644 --- a/packages/browser-wallet/src/popup/popupX/constants/routes.ts +++ b/packages/browser-wallet/src/popup/popupX/constants/routes.ts @@ -200,10 +200,6 @@ export const relativeRoutes = { update: { path: 'update', }, - /** Remove existing delegator */ - stop: { - path: 'stop', - }, /** Submit configure delegator transaction */ submit: { path: 'submit', diff --git a/packages/browser-wallet/src/popup/popupX/pages/EarningRewards/Delegator/Result/DelegationResult.tsx b/packages/browser-wallet/src/popup/popupX/pages/EarningRewards/Delegator/Result/DelegationResult.tsx index 0855278b..2be84975 100644 --- a/packages/browser-wallet/src/popup/popupX/pages/EarningRewards/Delegator/Result/DelegationResult.tsx +++ b/packages/browser-wallet/src/popup/popupX/pages/EarningRewards/Delegator/Result/DelegationResult.tsx @@ -112,19 +112,18 @@ export default function DelegationResult() { return secondsToDaysRoundedDown(cooldownParam); }, [parametersV1]); - const title = useMemo(() => { + const [title, notice] = useMemo(() => { switch (state?.type) { case 'register': - return t('register.title'); + return [t('register.title'), t('register.notice', { cooldown })]; case 'change': - return t('update.title'); - // case 'remove': - // return t('remove.title'); + return [t('update.title'), t('update.lowerStakeNotice', { cooldown })]; + case 'remove': + return [t('remove.title'), t('remove.notice', { cooldown })]; default: - return undefined; + throw new Error("'type' must be defined on route state"); } - }, [state, t]); - const notice = t('register.notice', { cooldown }); // TODO: add more cases when supporting change/remove + }, [state, t, cooldown]); if (state === undefined) { return ; @@ -142,7 +141,7 @@ export default function DelegationResult() { return ( - {notice} + {notice !== undefined && {notice}} diff --git a/packages/browser-wallet/src/popup/popupX/pages/EarningRewards/Delegator/Status.tsx b/packages/browser-wallet/src/popup/popupX/pages/EarningRewards/Delegator/Status.tsx index 5180cf31..436075f5 100644 --- a/packages/browser-wallet/src/popup/popupX/pages/EarningRewards/Delegator/Status.tsx +++ b/packages/browser-wallet/src/popup/popupX/pages/EarningRewards/Delegator/Status.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { AccountInfoType, DelegationTargetType } from '@concordium/web-sdk'; +import { AccountInfoType, CcdAmount, DelegationTargetType } from '@concordium/web-sdk'; import { absoluteRoutes } from '@popup/popupX/constants/routes'; import Button from '@popup/popupX/shared/Button'; import Card from '@popup/popupX/shared/Card'; @@ -9,6 +9,12 @@ import { formatCcdAmount } from '@popup/popupX/shared/utils/helpers'; import { useSelectedAccountInfo } from '@popup/shared/AccountInfoListenerContext/AccountInfoListenerContext'; import { Navigate, useNavigate } from 'react-router-dom'; import AccountCooldowns from '../AccountCooldowns'; +import { DelegationResultLocationState } from './Result/DelegationResult'; + +const REMOVE_STATE: DelegationResultLocationState = { + type: 'remove', + payload: { stake: CcdAmount.zero() }, +}; export default function DelegatorStatus() { const { t } = useTranslation('x', { keyPrefix: 'earn.delegator' }); @@ -63,7 +69,7 @@ export default function DelegatorStatus() { /> nav(absoluteRoutes.settings.earn.delegator.stop.path)} + onClick={() => nav(absoluteRoutes.settings.earn.delegator.submit.path, { state: REMOVE_STATE })} /> diff --git a/packages/browser-wallet/src/popup/popupX/pages/EarningRewards/i18n/en.ts b/packages/browser-wallet/src/popup/popupX/pages/EarningRewards/i18n/en.ts index c40b23b6..f1d1cc97 100644 --- a/packages/browser-wallet/src/popup/popupX/pages/EarningRewards/i18n/en.ts +++ b/packages/browser-wallet/src/popup/popupX/pages/EarningRewards/i18n/en.ts @@ -76,6 +76,12 @@ const t = { description: 'The proposed transaction contains no changes compared to the current delegation.', buttonBack: 'Go back', }, + lowerStakeNotice: + 'Reducing your stake is subject to a cooldown period of {{cooldown}} days, in which the stake cannot be spent or transferred.', + }, + remove: { + title: 'Remove delegation', + notice: 'The delegated stake is released after {{cooldown}} days', }, target: { description: 'You can delegate to an open pool of your choice, or you can stake using passive delegation.', diff --git a/packages/browser-wallet/src/popup/popupX/shell/Routes.tsx b/packages/browser-wallet/src/popup/popupX/shell/Routes.tsx index 1db811f4..47f799e7 100644 --- a/packages/browser-wallet/src/popup/popupX/shell/Routes.tsx +++ b/packages/browser-wallet/src/popup/popupX/shell/Routes.tsx @@ -133,7 +133,6 @@ export default function Routes({ messagePromptHandlers }: { messagePromptHandler element={} path={`${relativeRoutes.settings.earn.delegator.update.path}/*`} /> - TODO} path={`${relativeRoutes.settings.earn.delegator.stop.path}`} /> } path={relativeRoutes.settings.earn.delegator.submit.path} diff --git a/packages/browser-wallet/src/shared/utils/time-helpers.ts b/packages/browser-wallet/src/shared/utils/time-helpers.ts index 4573a4df..a62b60b7 100644 --- a/packages/browser-wallet/src/shared/utils/time-helpers.ts +++ b/packages/browser-wallet/src/shared/utils/time-helpers.ts @@ -1,7 +1,7 @@ import { MILLISECONDS_PER_DAY, MILLISECONDS_PER_HOUR, MILLISECONDS_PER_MINUTE } from '@popup/constants/time'; export function secondsToDaysRoundedDown(seconds: bigint | undefined): bigint { - return seconds ? seconds / (60n * 60n * 24n) : 0n; + return seconds !== undefined ? seconds / (60n * 60n * 24n) : 0n; } type TimeAndUnit = { time: bigint; unit: string }; From 785a50952f0f53058a1df109217b37a5643937d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Bruus=20Zeppelin?= Date: Tue, 29 Oct 2024 14:02:52 +0100 Subject: [PATCH 2/2] Show notice when lowering stake --- .../Delegator/Result/DelegationResult.tsx | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/packages/browser-wallet/src/popup/popupX/pages/EarningRewards/Delegator/Result/DelegationResult.tsx b/packages/browser-wallet/src/popup/popupX/pages/EarningRewards/Delegator/Result/DelegationResult.tsx index 2be84975..4557a7b8 100644 --- a/packages/browser-wallet/src/popup/popupX/pages/EarningRewards/Delegator/Result/DelegationResult.tsx +++ b/packages/browser-wallet/src/popup/popupX/pages/EarningRewards/Delegator/Result/DelegationResult.tsx @@ -1,6 +1,7 @@ import React, { useCallback, useMemo } from 'react'; import { AccountAddress, + AccountInfoDelegator, AccountTransactionPayload, AccountTransactionType, CcdAmount, @@ -34,6 +35,7 @@ import { addPendingTransactionAtom } from '@popup/store/transactions'; import { cpStakingCooldown } from '@shared/utils/chain-parameters-helpers'; import { submittedTransactionRoute } from '@popup/popupX/constants/routes'; import Text from '@popup/popupX/shared/Text'; +import { useSelectedAccountInfo } from '@popup/shared/AccountInfoListenerContext/AccountInfoListenerContext'; enum TransactionSubmitErrorType { InsufficientFunds = 'InsufficientFunds', @@ -96,11 +98,11 @@ export default function DelegationResult() { const nav = useNavigate(); const { t } = useTranslation('x', { keyPrefix: 'earn.delegator' }); const getCost = useGetTransactionFee(AccountTransactionType.ConfigureDelegation); - const account = ensureDefined(useAtomValue(selectedAccountAtom), 'No account selected'); + const accountInfo = ensureDefined(useSelectedAccountInfo(), 'No account selected'); const parametersV1 = useBlockChainParametersAboveV0(); const submitTransaction = useTransactionSubmit( - AccountAddress.fromBase58(account), + accountInfo.accountAddress, AccountTransactionType.ConfigureDelegation ); @@ -117,6 +119,14 @@ export default function DelegationResult() { case 'register': return [t('register.title'), t('register.notice', { cooldown })]; case 'change': + if ( + state.payload.stake === undefined || + state.payload.stake.microCcdAmount >= + (accountInfo as AccountInfoDelegator).accountDelegation.stakedAmount.microCcdAmount + ) { + // Staked amount is not lowered + return [t('update.title')]; + } return [t('update.title'), t('update.lowerStakeNotice', { cooldown })]; case 'remove': return [t('remove.title'), t('remove.notice', { cooldown })]; @@ -144,7 +154,7 @@ export default function DelegationResult() { {notice !== undefined && {notice}} - + {state.payload.delegationTarget !== undefined && (