Skip to content

Commit 75197a8

Browse files
authored
Merge pull request #261 from threshold-network/operator-mapping-card-success-state
Add success state to OperatorAddressMappingCard `OperatorAddressMappingCard` should be displayed in staking page also for the providers that already mapped an operator. We will keep this card with staking provider <> operator pair displayed. There are also a tooltip for each to help user know which address is which. **Note:** The OperatorAddressMappingCard with a success state should be displayed at the top on left column when staking provider doesnt own any stakes, and at the bottom of the left column if he owns some stakes. Link to Figma: https://www.figma.com/file/Tx1lZc7us4SqCeAgbt1hBV/Threshold-Dapp?node-id=6179%3A147494
2 parents 06009f9 + d818bfa commit 75197a8

File tree

2 files changed

+99
-20
lines changed

2 files changed

+99
-20
lines changed

src/pages/Staking/OperatorAddressMappingCard.tsx

Lines changed: 88 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,54 @@
1+
import { Icon } from "@chakra-ui/icons"
12
import {
23
Alert,
34
AlertIcon,
45
Badge,
6+
BodyMd,
57
BodyXs,
8+
Box,
9+
BoxLabel,
610
Button,
711
Card,
812
HStack,
913
LabelSm,
14+
LineDivider,
15+
Tooltip,
16+
useColorModeValue,
1017
} from "@threshold-network/components"
1118
import { FC } from "react"
1219
import { ModalType } from "../../enums"
1320
import { useAppSelector } from "../../hooks/store"
1421
import { useModal } from "../../hooks/useModal"
1522
import { selectMappedOperators } from "../../store/account/selectors"
23+
import shortenAddress from "../../utils/shortenAddress"
24+
import { isAddressZero } from "../../web3/utils"
25+
import { FcCheckmark, FiLink2 } from "react-icons/all"
26+
import { getSakingAppLabel } from "../../utils/getStakingAppLabel"
27+
import { StakingAppName } from "../../store/staking-applications"
1628

17-
const OperatorAddressMappingCard: FC = () => {
29+
const OperatorAddressMappingCard: FC<{ stakingProvider: string }> = ({
30+
stakingProvider,
31+
}) => {
1832
const { openModal } = useModal()
33+
const {
34+
mappedOperatorTbtc,
35+
mappedOperatorRandomBeacon,
36+
isOneOfTheAppsNotMapped,
37+
} = useAppSelector(selectMappedOperators)
1938

20-
const { isOneOfTheAppsNotMapped } = useAppSelector(selectMappedOperators)
39+
const shoudlDisplaySuccessState =
40+
!isAddressZero(mappedOperatorTbtc) &&
41+
!isAddressZero(mappedOperatorRandomBeacon)
2142

2243
const onStartMappingClick = () => {
2344
openModal(ModalType.MapOperatorToStakingProvider)
2445
}
2546

47+
const mappedOperators = {
48+
tbtc: mappedOperatorTbtc,
49+
randomBeacon: mappedOperatorRandomBeacon,
50+
}
51+
2652
return (
2753
<Card borderColor={isOneOfTheAppsNotMapped ? "red.500" : "gray.100"}>
2854
<HStack justifyContent={"space-between"}>
@@ -31,22 +57,66 @@ const OperatorAddressMappingCard: FC = () => {
3157
Node operators only
3258
</Badge>
3359
</HStack>
34-
<Alert
35-
status={isOneOfTheAppsNotMapped ? "error" : "warning"}
36-
alignItems={"center"}
37-
mt={5}
38-
p={"8px 10px"}
39-
>
40-
<AlertIcon h={"14px"} as={"div"} alignSelf="auto" />
41-
<BodyXs>
42-
{isOneOfTheAppsNotMapped
43-
? "One application from the tBTC + Random Beacon Rewards Bundle Suite requires the Operator Address mapped."
44-
: "This section is for Staking Providers and self-operating stakers only. Map your Operator Address to your Provider Address for a better support for your hardware wallet in the node setup."}
45-
</BodyXs>
46-
</Alert>
47-
<Button size="lg" w="100%" mt="5" onClick={onStartMappingClick}>
48-
Start Mapping
49-
</Button>
60+
{shoudlDisplaySuccessState ? (
61+
Object.entries(mappedOperators).map(([appName, operator]) => {
62+
return (
63+
<Box key={`mapped_operator_${appName}_${operator}`}>
64+
<HStack mt={5}>
65+
<BoxLabel status="secondary" size={"sm"}>
66+
{getSakingAppLabel(appName as StakingAppName)} App
67+
</BoxLabel>
68+
<Badge variant="subtle" size={"md"} bgColor={"green.50"} py={1}>
69+
<HStack>
70+
<Icon as={FcCheckmark} />{" "}
71+
<LabelSm color={"green.500"}>Operator Mapped</LabelSm>
72+
</HStack>
73+
</Badge>
74+
</HStack>
75+
<HStack justify="space-between" mt={5}>
76+
<BoxLabel status="primary" size={"sm"}>
77+
Provider
78+
</BoxLabel>
79+
<BodyMd color={useColorModeValue("brand.500", "brand.550")}>
80+
<Tooltip label={`Staking provider`}>
81+
{shortenAddress(stakingProvider)}
82+
</Tooltip>
83+
</BodyMd>
84+
<Icon color="gray.500" boxSize="16px" as={FiLink2} />
85+
<BoxLabel status="secondary" size={"sm"}>
86+
Operator
87+
</BoxLabel>
88+
<BodyMd color={useColorModeValue("gray.500", "gray.300")}>
89+
<Tooltip label={`Operator`}>
90+
{shortenAddress(operator)}
91+
</Tooltip>
92+
</BodyMd>
93+
</HStack>
94+
{Object.keys(mappedOperators)[
95+
Object.keys(mappedOperators).length - 1
96+
] !== appName && <LineDivider />}
97+
</Box>
98+
)
99+
})
100+
) : (
101+
<>
102+
<Alert
103+
status={isOneOfTheAppsNotMapped ? "error" : "warning"}
104+
alignItems={"center"}
105+
mt={5}
106+
p={"8px 10px"}
107+
>
108+
<AlertIcon h={"14px"} as={"div"} alignSelf="auto" />
109+
<BodyXs>
110+
{isOneOfTheAppsNotMapped
111+
? "One application from the tBTC + Random Beacon Rewards Bundle Suite requires the Operator Address mapped."
112+
: "This section is for Staking Providers and self-operating stakers only. Map your Operator Address to your Provider Address for a better support for your hardware wallet in the node setup."}
113+
</BodyXs>
114+
</Alert>
115+
<Button size="lg" w="100%" mt="5" onClick={onStartMappingClick}>
116+
Start Mapping
117+
</Button>
118+
</>
119+
)}
50120
</Card>
51121
)
52122
}

src/pages/Staking/index.tsx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ const StakingPage: PageComponent = (props) => {
5555
const hasStakes = stakes.length > 0
5656

5757
const {
58+
address,
5859
isStakingProvider,
5960
operatorMapping: {
6061
isInitialFetchDone: isOperatorMappingInitialFetchDone,
@@ -78,11 +79,12 @@ const StakingPage: PageComponent = (props) => {
7879
>
7980
Your Stake
8081
</H4>
81-
{isStakingProvider &&
82+
{address &&
83+
isStakingProvider &&
8284
isOperatorMappingInitialFetchDone &&
8385
(isAddressZero(mappedOperators.tbtc) ||
8486
isAddressZero(mappedOperators.randomBeacon)) && (
85-
<OperatorAddressMappingCard />
87+
<OperatorAddressMappingCard stakingProvider={address} />
8688
)}
8789
{hasStakes ? (
8890
stakes.map((stake) => (
@@ -91,6 +93,13 @@ const StakingPage: PageComponent = (props) => {
9193
) : (
9294
<NewStakeCard />
9395
)}
96+
{address &&
97+
isStakingProvider &&
98+
isOperatorMappingInitialFetchDone &&
99+
!isAddressZero(mappedOperators.tbtc) &&
100+
!isAddressZero(mappedOperators.randomBeacon) && (
101+
<OperatorAddressMappingCard stakingProvider={address} />
102+
)}
94103
</VStack>
95104

96105
<VStack w={"100%"} spacing={5}>

0 commit comments

Comments
 (0)