Skip to content
This repository was archived by the owner on Sep 8, 2025. It is now read-only.

Commit eac74bf

Browse files
authored
feat: expansion verification unhappy local storage (#1446)
1 parent f20dcdf commit eac74bf

File tree

9 files changed

+758
-113
lines changed

9 files changed

+758
-113
lines changed
Lines changed: 3 additions & 0 deletions
Loading

src/ui/common/components/Activity/components/StakeExpansionSection.tsx

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ import { AiOutlineMinus, AiOutlinePlus } from "react-icons/ai";
99
import iconBSNFp from "@/ui/common/assets/expansion-bsn-fp.svg";
1010
import iconHistory from "@/ui/common/assets/expansion-history.svg";
1111
import iconRenew from "@/ui/common/assets/expansion-renew.svg";
12+
import iconVerified from "@/ui/common/assets/expansion-verified.svg";
1213
import { useExpansionHistoryService } from "@/ui/common/hooks/services/useExpansionHistoryService";
14+
import { useVerifiedStakingExpansionService } from "@/ui/common/hooks/services/useVerifiedStakingExpansionService";
1315
import { useDelegationV2State } from "@/ui/common/state/DelegationV2State";
1416
import { useStakingExpansionState } from "@/ui/common/state/StakingExpansionState";
1517
import { StakingExpansionStep } from "@/ui/common/state/StakingExpansionTypes";
@@ -34,6 +36,10 @@ export function StakeExpansionSection({
3436
} = useStakingExpansionState();
3537
const { delegations } = useDelegationV2State();
3638
const { getHistoryCount } = useExpansionHistoryService();
39+
const {
40+
openVerifiedExpansionModalForDelegation,
41+
getVerifiedExpansionInfoForDelegation,
42+
} = useVerifiedStakingExpansionService();
3743

3844
const currentBsnCount = delegation.finalityProviderBtcPksHex.length;
3945
const canExpandDelegation = canExpand(delegation);
@@ -97,12 +103,24 @@ export function StakeExpansionSection({
97103
}
98104
};
99105

106+
/**
107+
* Handle verified expansion button click.
108+
*/
109+
const handleVerifiedExpansion = () => {
110+
openVerifiedExpansionModalForDelegation(delegation);
111+
};
112+
100113
// Calculate actual expansion history count
101114
const expansionHistoryCount = getHistoryCount(
102115
delegations,
103116
delegation.stakingTxHashHex,
104117
);
105118

119+
// Get verified expansion info for this specific delegation
120+
const delegationVerifiedExpansionInfo = getVerifiedExpansionInfoForDelegation(
121+
delegation.stakingTxHashHex,
122+
);
123+
106124
return (
107125
<div className="w-full">
108126
<Accordion className="border border-secondary-strokeLight rounded bg-surface">
@@ -147,6 +165,18 @@ export function StakeExpansionSection({
147165
onClick={handleExpansionHistory}
148166
disabled={expansionHistoryCount === 0 || processing}
149167
/>
168+
{delegationVerifiedExpansionInfo.hasVerifiedExpansions && (
169+
<ExpansionButton
170+
Icon={iconVerified}
171+
text="Verified Stake Expansion"
172+
counter={`${delegationVerifiedExpansionInfo.count}`}
173+
onClick={handleVerifiedExpansion}
174+
disabled={
175+
!delegationVerifiedExpansionInfo.hasVerifiedExpansions ||
176+
processing
177+
}
178+
/>
179+
)}
150180
</div>
151181
</AccordionDetails>
152182
</Accordion>

src/ui/common/components/StakingExpansion/StakingExpansionModalSystem.tsx

Lines changed: 86 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { VerificationModal } from "@/ui/common/components/Modals/VerificationMod
1010
import { FinalityProviderLogo } from "@/ui/common/components/Staking/FinalityProviders/FinalityProviderLogo";
1111
import { getNetworkConfigBBN } from "@/ui/common/config/network/bbn";
1212
import { getNetworkConfigBTC } from "@/ui/common/config/network/btc";
13-
import { chainLogos } from "@/ui/common/constants";
13+
import { BaseStakingStep, chainLogos, EOIStep } from "@/ui/common/constants";
1414
import { useNetworkInfo } from "@/ui/common/hooks/client/api/useNetworkInfo";
1515
import { usePrice } from "@/ui/common/hooks/client/api/usePrices";
1616
import { useStakingExpansionService } from "@/ui/common/hooks/services/useStakingExpansionService";
@@ -33,17 +33,18 @@ import { SignDetailsModal } from "../Modals/SignDetailsModal";
3333

3434
import { RenewTimelockModal } from "./RenewTimelockModal";
3535
import { StakingExpansionModal } from "./StakingExpansionModal";
36+
import { VerifiedStakeExpansionModal } from "./VerifiedStakeExpansionModal";
3637

37-
const EOI_INDEXES: Record<string, number> = {
38-
"eoi-staking-slashing": 1,
39-
"eoi-unbonding-slashing": 2,
40-
"eoi-proof-of-possession": 3,
41-
"eoi-sign-bbn": 4,
38+
const EOI_STEP_INDEXES: Record<string, number> = {
39+
[EOIStep.EOI_STAKING_SLASHING]: 1,
40+
[EOIStep.EOI_UNBONDING_SLASHING]: 2,
41+
[EOIStep.EOI_PROOF_OF_POSSESSION]: 3,
42+
[EOIStep.EOI_SIGN_BBN]: 4,
4243
};
4344

44-
const VERIFICATION_STEPS: Record<string, 1 | 2> = {
45-
"eoi-send-bbn": 1,
46-
verifying: 2,
45+
const VERIFICATION_STEP_INDEXES: Record<string, 1 | 2> = {
46+
[EOIStep.EOI_SEND_BBN]: 1,
47+
[BaseStakingStep.VERIFYING]: 2,
4748
};
4849

4950
const { chainId: BBN_CHAIN_ID } = getNetworkConfigBBN();
@@ -57,6 +58,8 @@ function StakingExpansionModalSystemInner() {
5758
verifiedDelegation,
5859
reset: resetState,
5960
expansionStepOptions,
61+
verifiedExpansionModalOpen,
62+
setVerifiedExpansionModalOpen,
6063
} = useStakingExpansionState();
6164

6265
const { getRegisteredFinalityProvider } = useFinalityProviderState();
@@ -232,76 +235,88 @@ function StakingExpansionModalSystemInner() {
232235
btcInUsd,
233236
]);
234237

235-
if (!step) {
236-
return null;
237-
}
238-
239238
const handleClose = () => {
240239
resetState();
241240
setDelegationV2StepOptions?.(undefined);
242241
};
243242

243+
const handleCloseVerifiedModal = () => {
244+
setVerifiedExpansionModalOpen(false);
245+
};
246+
244247
return (
245248
<>
246-
{step === StakingExpansionStep.BSN_FP_SELECTION && (
247-
<StakingExpansionModal open onClose={handleClose} />
248-
)}
249-
{step === StakingExpansionStep.RENEWAL_TIMELOCK && (
250-
<RenewTimelockModal open onClose={handleClose} />
251-
)}
252-
{step === StakingExpansionStep.PREVIEW && formData && details && (
253-
<PreviewMultistakingModal
254-
open
255-
processing={processing}
256-
bsns={bsnInfos}
257-
finalityProviders={finalityProviderInfos}
258-
details={details}
259-
isExpansion={true}
260-
onClose={handleClose}
261-
onProceed={async () => {
262-
await createExpansionEOI(formData);
263-
resetForm();
264-
revalidateForm();
265-
}}
266-
/>
267-
)}
268-
{Boolean(EOI_INDEXES[step]) && (
269-
<SignModal
270-
open
271-
processing={processing}
272-
step={EOI_INDEXES[step]}
273-
title="Staking Expansion"
274-
options={expansionStepOptions}
275-
/>
276-
)}
277-
{Boolean(VERIFICATION_STEPS[step]) && (
278-
<VerificationModal
279-
open
280-
processing={processing}
281-
step={VERIFICATION_STEPS[step]}
282-
/>
283-
)}
284-
{verifiedDelegation && (
285-
<StakeModal
286-
open={step === StakingExpansionStep.VERIFIED}
287-
processing={processing}
288-
onSubmit={() => stakeDelegationExpansion(verifiedDelegation)}
289-
onClose={handleClose}
290-
/>
249+
{/* Step-based modals - only render when there's an active step */}
250+
{step && (
251+
<>
252+
{step === StakingExpansionStep.BSN_FP_SELECTION && (
253+
<StakingExpansionModal open onClose={handleClose} />
254+
)}
255+
{step === StakingExpansionStep.RENEWAL_TIMELOCK && (
256+
<RenewTimelockModal open onClose={handleClose} />
257+
)}
258+
{step === StakingExpansionStep.PREVIEW && formData && details && (
259+
<PreviewMultistakingModal
260+
open
261+
processing={processing}
262+
bsns={bsnInfos}
263+
finalityProviders={finalityProviderInfos}
264+
details={details}
265+
isExpansion={true}
266+
onClose={handleClose}
267+
onProceed={async () => {
268+
await createExpansionEOI(formData);
269+
resetForm();
270+
revalidateForm();
271+
}}
272+
/>
273+
)}
274+
{Boolean(EOI_STEP_INDEXES[step]) && (
275+
<SignModal
276+
open
277+
processing={processing}
278+
step={EOI_STEP_INDEXES[step]}
279+
title="Staking Expansion"
280+
options={expansionStepOptions}
281+
/>
282+
)}
283+
{Boolean(VERIFICATION_STEP_INDEXES[step]) && (
284+
<VerificationModal
285+
open
286+
processing={processing}
287+
step={VERIFICATION_STEP_INDEXES[step]}
288+
/>
289+
)}
290+
{verifiedDelegation && (
291+
<StakeModal
292+
open={step === StakingExpansionStep.VERIFIED}
293+
processing={processing}
294+
onSubmit={() => stakeDelegationExpansion(verifiedDelegation)}
295+
onClose={handleClose}
296+
/>
297+
)}
298+
<SuccessFeedbackModal
299+
open={step === StakingExpansionStep.FEEDBACK_SUCCESS}
300+
onClose={handleClose}
301+
/>
302+
<CancelFeedbackModal
303+
open={step === StakingExpansionStep.FEEDBACK_CANCEL}
304+
onClose={handleClose}
305+
/>
306+
<SignDetailsModal
307+
open={Boolean(delegationV2StepOptions) && processing}
308+
onClose={() => setDelegationV2StepOptions?.(undefined)}
309+
details={delegationV2StepOptions}
310+
title={detailsModalTitle}
311+
/>
312+
</>
291313
)}
292-
<SuccessFeedbackModal
293-
open={step === StakingExpansionStep.FEEDBACK_SUCCESS}
294-
onClose={handleClose}
295-
/>
296-
<CancelFeedbackModal
297-
open={step === StakingExpansionStep.FEEDBACK_CANCEL}
298-
onClose={handleClose}
299-
/>
300-
<SignDetailsModal
301-
open={Boolean(delegationV2StepOptions) && processing}
302-
onClose={() => setDelegationV2StepOptions?.(undefined)}
303-
details={delegationV2StepOptions}
304-
title={detailsModalTitle}
314+
315+
{/* Independent modals - render regardless of step */}
316+
<VerifiedStakeExpansionModal
317+
open={verifiedExpansionModalOpen}
318+
onClose={handleCloseVerifiedModal}
319+
processing={processing}
305320
/>
306321
</>
307322
);

0 commit comments

Comments
 (0)