diff --git a/packages/browser-wallet/src/popup/popupX/pages/EarningRewards/Delegator/Stake/DelegatorStake.tsx b/packages/browser-wallet/src/popup/popupX/pages/EarningRewards/Delegator/Stake/DelegatorStake.tsx
index 1e1a5068..3c9649b5 100644
--- a/packages/browser-wallet/src/popup/popupX/pages/EarningRewards/Delegator/Stake/DelegatorStake.tsx
+++ b/packages/browser-wallet/src/popup/popupX/pages/EarningRewards/Delegator/Stake/DelegatorStake.tsx
@@ -26,7 +26,7 @@ import { useGetTransactionFee } from '@popup/shared/utils/transaction-helpers';
import FullscreenNotice, { FullscreenNoticeProps } from '@popup/popupX/shared/FullscreenNotice';
import { DelegationTypeForm, DelegatorForm, DelegatorStakeForm, configureDelegatorPayloadFromForm } from '../util';
-import {isAboveStakeWarningThreshold} from '../../util';
+import { STAKE_WARNING_THRESHOLD, isAboveStakeWarningThreshold } from '../../util';
type PoolInfoProps = {
/** The validator pool ID to show information for */
@@ -72,15 +72,16 @@ type HighStakeNoticeProps = FullscreenNoticeProps & {
onContinue(): void;
};
-function HighStakeNotice({ onContinue, ...props }: HighStakeNoticeProps) {
+function HighStakeWarning({ onContinue, ...props }: HighStakeNoticeProps) {
+ const { t } = useTranslation('x', { keyPrefix: 'earn.delegator.stake.overStakeThresholdWarning' });
return (
-
- Notice text...
+
+ {t('description', { threshold: STAKE_WARNING_THRESHOLD.toString() })}
-
-
+
+
@@ -171,7 +172,7 @@ export default function DelegatorStake({ title, target, initialValues, existingV
return (
<>
- setHighStakeWarning(false)} onContinue={submit} />
+ setHighStakeWarning(false)} onContinue={submit} />
diff --git a/packages/browser-wallet/src/popup/popupX/pages/EarningRewards/Delegator/TransactionFlow.tsx b/packages/browser-wallet/src/popup/popupX/pages/EarningRewards/Delegator/TransactionFlow.tsx
index 8d3fd938..ec03f74d 100644
--- a/packages/browser-wallet/src/popup/popupX/pages/EarningRewards/Delegator/TransactionFlow.tsx
+++ b/packages/browser-wallet/src/popup/popupX/pages/EarningRewards/Delegator/TransactionFlow.tsx
@@ -1,3 +1,4 @@
+/* eslint-disable react/destructuring-assignment */
import React, { useCallback, useState } from 'react';
import { Location, Navigate, useLocation, useNavigate } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
@@ -7,19 +8,38 @@ import { absoluteRoutes } from '@popup/popupX/constants/routes';
import MultiStepForm from '@popup/shared/MultiStepForm';
import { useSelectedAccountInfo } from '@popup/shared/AccountInfoListenerContext/AccountInfoListenerContext';
import { formatCcdAmount } from '@popup/popupX/shared/utils/helpers';
+import FullscreenNotice, { FullscreenNoticeProps } from '@popup/popupX/shared/FullscreenNotice';
+import Page from '@popup/popupX/shared/Page';
+import Button from '@popup/popupX/shared/Button';
import DelegatorStake from './Stake';
import DelegatorType from './Type';
import { configureDelegatorPayloadFromForm, type DelegatorForm } from './util';
import { DelegationResultLocationState } from './Result/DelegationResult';
+function NoChangesNotice(props: FullscreenNoticeProps) {
+ const { t } = useTranslation('x', { keyPrefix: 'earn.delegator.update.noChangesNotice' });
+ return (
+
+
+
+ {t('description')}
+
+
+
+
+
+ );
+}
+
type Props = {
+ title: string;
existingValues?: DelegatorForm | undefined;
};
-export default function DelegatorTransactionFlow({ existingValues }: Props) {
+function DelegatorTransactionFlow({ existingValues, title }: Props) {
const { state, pathname } = useLocation() as Location & { state: DelegatorForm | undefined };
- const { t } = useTranslation('x', { keyPrefix: 'earn.delegator.register' });
const nav = useNavigate();
+ const [noChangesNotice, setNoChangesNotice] = useState(false);
const initialValues = state ?? existingValues;
const store = useState>(initialValues ?? {});
@@ -28,45 +48,59 @@ export default function DelegatorTransactionFlow({ existingValues }: Props) {
(form: DelegatorForm) => {
const payload = configureDelegatorPayloadFromForm(form, existingValues);
+ if (Object.values(payload).every((v) => v === undefined)) {
+ setNoChangesNotice(true);
+ return;
+ }
+
nav(pathname, { replace: true, state: form }); // Override current router entry with stateful version
const submitDelegatorState: DelegationResultLocationState = { payload, type: 'register' };
nav(absoluteRoutes.settings.earn.delegator.submit.path, { state: submitDelegatorState });
},
- [pathname, existingValues]
+ [pathname, existingValues, setNoChangesNotice]
);
return (
- onDone={handleDone} valueStore={store}>
- {{
- target: {
- render: (initial, onNext) => (
-
- ),
- },
- stake: {
- render: (initial, onNext, form) => {
- if (form.target === undefined) {
- return ;
- }
-
- return (
-
- );
+ <>
+ setNoChangesNotice(false)} />
+ onDone={handleDone} valueStore={store}>
+ {{
+ target: {
+ render: (initial, onNext) => (
+
+ ),
},
- },
- }}
-
+ stake: {
+ render: (initial, onNext, form) => {
+ if (form.target === undefined) {
+ return ;
+ }
+
+ return (
+
+ );
+ },
+ },
+ }}
+
+ >
);
}
+export function RegisterDelegatorTransactionFlow() {
+ const { t } = useTranslation('x', { keyPrefix: 'earn.delegator.register' });
+ return ;
+}
+
export function UpdateDelegatorTransactionFlow() {
+ const { t } = useTranslation('x', { keyPrefix: 'earn.delegator.update' });
const accountInfo = useSelectedAccountInfo();
if (accountInfo === undefined || accountInfo.type !== AccountInfoType.Delegator) {
@@ -87,5 +121,5 @@ export function UpdateDelegatorTransactionFlow() {
: { type: DelegationTargetType.Baker, bakerId: delegationTarget.bakerId.toString() },
};
- return ;
+ return ;
}
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 e77c2d8e..c40b23b6 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
@@ -69,7 +69,14 @@ const t = {
backTitle: 'Earning rewards',
notice: 'This will lock your delegation amount. Amount is released after {{cooldown}} days from the time you remove or decrease your delegation.',
},
- update: { title: 'Update delegation' },
+ update: {
+ title: 'Update delegation',
+ noChangesNotice: {
+ title: 'No changes',
+ description: 'The proposed transaction contains no changes compared to the current delegation.',
+ buttonBack: 'Go back',
+ },
+ },
target: {
description: 'You can delegate to an open pool of your choice, or you can stake using passive delegation.',
radioValidatorLabel: 'Validator',
@@ -115,6 +122,13 @@ const t = {
description: 'I want to automatically add my delegation rewards to my delegation amount.',
},
buttonContinue: 'Continue',
+ overStakeThresholdWarning: {
+ title: 'Important',
+ description:
+ 'You are about to lock more than {{ threshold }}% of your total balance in a delegation stake.\n\nIf you don’t have enough unlocked CCD at your disposal, you might not be able to pay future transaction fees.',
+ buttonContinue: 'Continue',
+ buttonBack: 'Enter new stake',
+ },
},
submit: {
backTitle: 'Delegation settings',
diff --git a/packages/browser-wallet/src/popup/popupX/shell/Routes.tsx b/packages/browser-wallet/src/popup/popupX/shell/Routes.tsx
index b7dc309b..1db811f4 100644
--- a/packages/browser-wallet/src/popup/popupX/shell/Routes.tsx
+++ b/packages/browser-wallet/src/popup/popupX/shell/Routes.tsx
@@ -32,7 +32,10 @@ import { ManageTokenList, AddToken } from '@popup/popupX/pages/ManageTokens';
import { DelegationResult } from '../pages/EarningRewards/Delegator/Result';
import SubmittedTransaction from '../pages/SubmittedTransaction';
import { DelegatorIntro } from '../pages/EarningRewards/Delegator/Intro';
-import DelegatorTransactionFlow, { UpdateDelegatorTransactionFlow } from '../pages/EarningRewards/Delegator/TransactionFlow';
+import {
+ RegisterDelegatorTransactionFlow,
+ UpdateDelegatorTransactionFlow,
+} from '../pages/EarningRewards/Delegator/TransactionFlow';
import DelegatorStatus from '../pages/EarningRewards/Delegator/Status';
export default function Routes({ messagePromptHandlers }: { messagePromptHandlers: MessagePromptHandlersType }) {
@@ -123,7 +126,7 @@ export default function Routes({ messagePromptHandlers }: { messagePromptHandler
/>
}
+ element={}
/>