11import React from "react" ;
2- import { Card , CardContent , Typography , Chip , Button } from "@mui/material" ;
3- import { Minipool } from "../../types/MinipoolStatus" ;
4- import { toEtherString } from "../../utils/Utils" ;
52import OpenInNewIcon from "@mui/icons-material/OpenInNew" ;
6- import "./minipool.css" ;
3+ import { Button , Card , CardContent , Chip , Tooltip , Typography } from "@mui/material" ;
4+ import CopyToClipboardButton from "../Buttons/CopyToClipboardButton" ;
5+ import { Minipool } from "../../types/MinipoolStatus" ;
6+ import { ethBalanceGreaterThanMinStake , shortenAddress , toEtherString } from "../../utils/Utils" ;
77import ImportToSignerDialog from "./ImportToSignerDialog" ;
8+ import "./minipool.css" ;
9+
10+ enum MinipoolStatus {
11+ STAKING = "Staking" ,
12+ DISSOLVED = "Dissolved" ,
13+ PRELAUNCH = "Prelaunch" ,
14+ FINALISED = "Finalised"
15+ }
16+
17+ enum ValidatorStatus {
18+ EXITED = "Exited" ,
19+ ENQUEUED = "Enqueued" ,
20+ ACTIVE = "Active" ,
21+ READY_TO_CLOSE = "Ready to Close" ,
22+ INACTIVE = "Inactive"
23+ }
24+
25+ // Color theme constants
26+ const COLOR_THEME = {
27+ SUCCESS : "#81C784" , // Green
28+ WARNING : "#FFC107" , // Amber
29+ ERROR : "#E57373" , // Red
30+ INFO : "#FFB74D" // Orange
31+ } as const ;
32+
33+ // Status information interface
34+ interface StatusInfo {
35+ status : string ;
36+ color : string ;
37+ }
38+
39+ // Validator Status Service
40+ class ValidatorStatusService {
41+ /**
42+ * Determines the minipool status and returns status info
43+ */
44+ getMinipoolStatusInfo ( minipoolData : Minipool ) : StatusInfo {
45+ const status = this . determineMinipoolStatus ( minipoolData ) ;
46+ const color = this . getMinipoolStatusColor ( status ) ;
47+ return { status, color } ;
48+ }
49+
50+ /**
51+ * Determines the validator status and returns status info
52+ */
53+ getValidatorStatusInfo ( minipoolData : Minipool ) : StatusInfo {
54+ const status = this . determineValidatorStatus ( minipoolData ) ;
55+ const color = this . getValidatorStatusColor ( status , minipoolData ) ;
56+ return { status, color } ;
57+ }
58+
59+ /**
60+ * Determines the minipool status based on finalised state
61+ */
62+ private determineMinipoolStatus ( minipoolData : Minipool ) : string {
63+ return minipoolData . finalised ? MinipoolStatus . FINALISED : minipoolData . status . status ;
64+ }
65+
66+ /**
67+ * Determines the validator status with priority-based logic
68+ */
69+ private determineValidatorStatus ( minipoolData : Minipool ) : string {
70+ // Priority 1: Check if finalised
71+ if ( minipoolData . finalised ) {
72+ return ValidatorStatus . EXITED ;
73+ }
74+
75+ // Priority 2: Check if enqueued (staking but no validator index)
76+ if ( minipoolData . status . status === MinipoolStatus . STAKING && ! minipoolData . validator . index ) {
77+ return ValidatorStatus . ENQUEUED ;
78+ }
79+
80+ // Priority 3: Check if validator is active
81+ if ( minipoolData . validator . active ) {
82+ return ValidatorStatus . ACTIVE ;
83+ }
84+
85+ // Priority 4: Check if ready to close (staking with sufficient balance)
86+ if ( minipoolData . status . status === MinipoolStatus . STAKING &&
87+ ethBalanceGreaterThanMinStake ( minipoolData . balances . eth ) ) {
88+ return ValidatorStatus . READY_TO_CLOSE ;
89+ }
90+
91+ // Default: Inactive
92+ return ValidatorStatus . INACTIVE ;
93+ }
94+
95+ /**
96+ * Gets the color for minipool status
97+ */
98+ private getMinipoolStatusColor ( status : string ) : string {
99+ switch ( status ) {
100+ case MinipoolStatus . STAKING :
101+ return COLOR_THEME . SUCCESS ;
102+ case MinipoolStatus . DISSOLVED :
103+ return COLOR_THEME . ERROR ;
104+ case MinipoolStatus . FINALISED :
105+ return COLOR_THEME . WARNING ;
106+ default :
107+ return COLOR_THEME . INFO ;
108+ }
109+ }
110+
111+ /**
112+ * Gets the color for validator status
113+ */
114+ private getValidatorStatusColor ( validatorStatus : string , minipoolData : Minipool ) : string {
115+ // Success color for finalised or active validators
116+ if ( minipoolData . finalised || minipoolData . validator . active ) {
117+ return COLOR_THEME . SUCCESS ;
118+ }
119+
120+ // Warning color for prelaunch, enqueued, or ready to close
121+ if ( minipoolData . status . status === MinipoolStatus . PRELAUNCH ||
122+ [ ValidatorStatus . ENQUEUED , ValidatorStatus . READY_TO_CLOSE ] . includes ( validatorStatus as ValidatorStatus ) ) {
123+ return COLOR_THEME . WARNING ;
124+ }
125+
126+ // Error color for inactive
127+ return COLOR_THEME . ERROR ;
128+ }
129+ } ;
130+
131+ // Initialize status service
132+ const statusService = new ValidatorStatusService ( ) ;
8133
9134function MinipoolCard ( {
10135 data,
@@ -17,13 +142,11 @@ function MinipoolCard({
17142} ) : JSX . Element {
18143 const [ importToSignerDialogOpen , setImportToSignerDialogOpen ] =
19144 React . useState < boolean > ( false ) ;
20-
21- const backgroundColor =
22- data . status . status === "Staking"
23- ? "#81C784"
24- : data . status . status === "Dissolved"
25- ? "#E57373"
26- : "#FFB74D" ;
145+ const [ showAddress , setShowAddress ] = React . useState < boolean > ( false ) ;
146+
147+ // Get status information using the service
148+ const minipoolStatusInfo = statusService . getMinipoolStatusInfo ( data ) ;
149+ const validatorStatusInfo = statusService . getValidatorStatusInfo ( data ) ;
27150
28151 return (
29152 < Card
@@ -36,16 +159,28 @@ function MinipoolCard({
36159 >
37160 < CardContent >
38161 < div className = "chip-container" >
39- < Chip label = { `#${ data . validator . index } ` } />
162+ < div className = "chip-with-clipboard-container" >
163+ < Tooltip title = { showAddress ? "Minipool Address" : "Validator Index" } >
164+ < Chip
165+ label = { showAddress ? shortenAddress ( data . address ) : `#${ data . validator . index } ` }
166+ onClick = { ( ) => setShowAddress ( ! showAddress ) }
167+ sx = { { cursor : 'pointer' } }
168+ />
169+ </ Tooltip >
170+ < CopyToClipboardButton
171+ value = { showAddress ? data . address : data . validator . index . toString ( ) }
172+ fontSize = "small"
173+ />
174+ </ div >
40175 < Chip
41- label = { data . finalised ? "Finalised" : data . status . status }
42- sx = { { backgroundColor : data . finalised ? "#FFC107" : backgroundColor } }
176+ label = { minipoolStatusInfo . status }
177+ sx = { { backgroundColor : minipoolStatusInfo . color } }
43178 />
44179 </ div >
45180 < div className = "validator-status" >
46181 < Chip
47- label = { data . finalised ? "Exited" : ( data . validator . active ? "Active" : "Inactive" ) }
48- sx = { { backgroundColor : data . finalised || data . validator . active ? "#81C784" : "#E57373" } }
182+ label = { validatorStatusInfo . status }
183+ sx = { { backgroundColor : validatorStatusInfo . color } }
49184 />
50185 </ div >
51186
0 commit comments