Skip to content

Commit 57f45f6

Browse files
authored
Merge pull request #315 from forbole/dev
Dev
2 parents cf24906 + e4546b6 commit 57f45f6

File tree

16 files changed

+264
-25
lines changed

16 files changed

+264
-25
lines changed

components/AddressDetailCard/index.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Box, Card, Grid, useTheme, Button } from '@material-ui/core'
1+
import { Box, Card, Grid, Button } from '@material-ui/core'
22
import useTranslation from 'next-translate/useTranslation'
33
import React from 'react'
44
import get from 'lodash/get'
@@ -39,7 +39,6 @@ const AddressDetailCard: React.FC<AddressDetailCardProps> = ({ address, accountB
3939
const { lang, t } = useTranslation('common')
4040
const { currency } = useGeneralContext()
4141
const classes = useStyles()
42-
const theme = useTheme()
4342
const isMobile = useIsMobile()
4443

4544
const router = useRouter()
@@ -82,7 +81,6 @@ const AddressDetailCard: React.FC<AddressDetailCardProps> = ({ address, accountB
8281
>
8382
<AccountAvatar size="large" address={address} />
8483
<Box display="flex" mt={isMobile ? 2 : 0} ml={isMobile ? -2 : 0}>
85-
8684
<Button
8785
classes={{ root: classes.sendButton }}
8886
variant="contained"

components/Condition/index.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import React from 'react'
2+
import { useStyles } from './styles'
3+
4+
const Condition: React.FC<{
5+
className?: string
6+
}> = ({ className }) => {
7+
const classes = useStyles()
8+
9+
return <div className={`${className} ${classes.root}`} />
10+
}
11+
12+
export default Condition

components/Condition/styles.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { makeStyles, createStyles } from '@material-ui/core/styles'
2+
import { CustomTheme } from '../../misc/theme'
3+
4+
export const useStyles = makeStyles(
5+
(theme: CustomTheme) =>
6+
createStyles({
7+
root: {
8+
width: theme.spacing(1),
9+
height: theme.spacing(1),
10+
background: theme.palette.condition.zero,
11+
margin: '0',
12+
borderRadius: '50%',
13+
'&.green': {
14+
background: theme.palette.condition.one,
15+
},
16+
'&.yellow': {
17+
background: theme.palette.condition.two,
18+
},
19+
'&.red': {
20+
background: theme.palette.condition.three,
21+
},
22+
},
23+
}),
24+
{
25+
name: 'HookGlobalStyles',
26+
index: 2,
27+
}
28+
)

components/DelegationDialog/SelectValidators.tsx

Lines changed: 62 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ import {
1515
Card,
1616
} from '@material-ui/core'
1717
import { Autocomplete } from '@material-ui/lab'
18+
import { gql, useQuery } from '@apollo/client'
19+
import get from 'lodash/get'
1820
import useTranslation from 'next-translate/useTranslation'
1921
import React from 'react'
2022
import keyBy from 'lodash/keyBy'
@@ -23,14 +25,22 @@ import RemoveIcon from '../../assets/images/icons/icon_clear.svg'
2325
import DropDownIcon from '../../assets/images/icons/icon_arrow_down_input_box.svg'
2426
import useStyles from './styles'
2527
import useIconProps from '../../misc/useIconProps'
26-
import { formatCrypto, formatCurrency } from '../../misc/utils'
28+
import {
29+
formatCrypto,
30+
formatCurrency,
31+
getValidatorCondition,
32+
getValidatorConditionClass,
33+
} from '../../misc/utils'
2734
import { useGeneralContext } from '../../contexts/GeneralContext'
2835
import useIsMobile from '../../misc/useIsMobile'
2936
import ValidatorAvatar from '../ValidatorAvatar'
37+
import { getSlashingParams } from '../../graphql/queries/validators'
38+
import Condition from '../Condition'
3039

3140
interface SelectValidatorsProps {
3241
onConfirm(delegations: Array<{ amount: number; validator: Validator }>, memo: string): void
3342
delegations: Array<{ amount: number; validator: Validator }>
43+
price: number
3444
crypto: Cryptocurrency
3545
validators: Validator[]
3646
amount: number
@@ -42,6 +52,7 @@ const SelectValidators: React.FC<SelectValidatorsProps> = ({
4252
crypto,
4353
validators,
4454
delegations: defaultDelegations,
55+
price,
4556
amount,
4657
denom,
4758
onConfirm,
@@ -70,6 +81,15 @@ const SelectValidators: React.FC<SelectValidatorsProps> = ({
7081
const validatorsMap = keyBy(validators, 'address')
7182
const randomizedValidators = React.useMemo(() => shuffle(validators), [])
7283

84+
const { data: paramsData } = useQuery(
85+
gql`
86+
${getSlashingParams(get(crypto, 'name', ''))}
87+
`
88+
)
89+
const slashingParams = get(paramsData, ['slashing_params', 0, 'params'], {
90+
signed_blocks_window: 0,
91+
})
92+
const signedBlockWindow = slashingParams.signed_blocks_window
7393
React.useMemo(() => {
7494
setDelegations((d) =>
7595
d.map((a, j) =>
@@ -91,6 +111,11 @@ const SelectValidators: React.FC<SelectValidatorsProps> = ({
91111
)
92112
}, [delegations.length])
93113

114+
const totalAmount = React.useMemo(
115+
() => delegations.map((v) => Number(v.amount)).reduce((a, b) => a + b, 0),
116+
[delegations]
117+
)
118+
94119
return (
95120
<form
96121
noValidate
@@ -110,7 +135,7 @@ const SelectValidators: React.FC<SelectValidatorsProps> = ({
110135
<DialogContent className={classes.dialogContent}>
111136
<Box ml={4} minHeight={360} maxHeight={600}>
112137
<Typography className={classes.marginBottom}>
113-
{t('total delegation amount')}{' '}
138+
{t('target delegation amount')}{' '}
114139
<b className={classes.marginLeft}>{formatCrypto(amount, denom, lang)}</b>
115140
</Typography>
116141
<Grid container spacing={4}>
@@ -152,14 +177,38 @@ const SelectValidators: React.FC<SelectValidatorsProps> = ({
152177
)
153178
)
154179
}}
155-
renderOption={(address) => (
156-
<ValidatorAvatar
157-
crypto={crypto}
158-
validator={validatorsMap[address]}
159-
size="small"
160-
withoutLink
161-
/>
162-
)}
180+
renderOption={(address) => {
181+
const missedBlockCounter = get(
182+
validatorsMap,
183+
[address, 'missedBlockCounter'],
184+
0
185+
)
186+
const conditionClass = getValidatorCondition(
187+
signedBlockWindow,
188+
missedBlockCounter
189+
)
190+
const condition =
191+
validatorsMap[address].status === 'active'
192+
? getValidatorConditionClass(conditionClass)
193+
: undefined
194+
return (
195+
<Box
196+
display="flex"
197+
alignItems="center"
198+
flexDirection="row"
199+
justifyContent="space-between"
200+
width="100%"
201+
>
202+
<ValidatorAvatar
203+
crypto={crypto}
204+
validator={validatorsMap[address]}
205+
size="small"
206+
withoutLink
207+
/>
208+
<Condition className={condition} />
209+
</Box>
210+
)
211+
}}
163212
renderInput={({ InputProps, inputProps, ...params }) => (
164213
<TextField
165214
{...params}
@@ -352,8 +401,8 @@ const SelectValidators: React.FC<SelectValidatorsProps> = ({
352401
mx={2}
353402
>
354403
<Box>
355-
<Typography variant="h5">{formatCrypto(amount, denom, lang)}</Typography>
356-
<Typography>{formatCurrency(amount, currency, lang)}</Typography>
404+
<Typography variant="h5">{formatCrypto(totalAmount, denom, lang)}</Typography>
405+
<Typography>{formatCurrency(totalAmount * price, currency, lang)}</Typography>
357406
</Box>
358407
<Button
359408
variant="contained"
@@ -362,7 +411,7 @@ const SelectValidators: React.FC<SelectValidatorsProps> = ({
362411
disabled={
363412
loading ||
364413
!delegations.filter((v) => v.validator.name && Number(v.amount)).length ||
365-
delegations.map((v) => Number(v.amount)).reduce((a, b) => a + b, 0) > amount ||
414+
totalAmount > amount ||
366415
delegations.filter((v) => v.validator === '').length !== 0
367416
}
368417
type="submit"

components/DelegationDialog/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ const DelegationDialog: React.FC<DelegationDialogProps> = ({
5050
const classes = useStyles()
5151
const iconProps = useIconProps()
5252
const { password } = useWalletsContext()
53-
const { currency, theme } = useGeneralContext()
53+
const { theme } = useGeneralContext()
5454
const isMobile = useIsMobile()
5555
const [amount, setAmount] = React.useState(0)
5656
const [denom, setDenom] = React.useState('')
@@ -127,6 +127,7 @@ const DelegationDialog: React.FC<DelegationDialogProps> = ({
127127
delegations={delegations}
128128
validators={validators}
129129
amount={amount}
130+
price={availableAmount[denom]?.price}
130131
denom={denom}
131132
onConfirm={confirmDelegations}
132133
loading={loading}

components/ValidatorsTable/InfoPopover.tsx

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react'
2-
import { Popover, Paper } from '@material-ui/core'
2+
import { Popover, Paper, Typography } from '@material-ui/core'
33
import { HelpOutline } from '@material-ui/icons'
44
import { useInfoPopoverHook } from './hooks'
55
import { useGetStyles } from './styles'
@@ -15,6 +15,25 @@ const InfoPopover = (props: InfoPopoverProps) => {
1515
const { handlePopoverOpen, handlePopoverClose, anchorEl, open } = useInfoPopoverHook()
1616
const { classes } = useGetStyles()
1717

18+
const conditions = [
19+
{
20+
display: '90% - 100%',
21+
className: 'green',
22+
},
23+
{
24+
display: '70% - 90%',
25+
className: 'yellow',
26+
},
27+
{
28+
display: '1% - 70%',
29+
className: 'red',
30+
},
31+
{
32+
display: '0%',
33+
className: '',
34+
},
35+
]
36+
1837
return (
1938
<span
2039
aria-owns={open ? 'mouse-over-popover' : undefined}
@@ -42,6 +61,16 @@ const InfoPopover = (props: InfoPopoverProps) => {
4261
>
4362
<Paper className={classes.popoverContainer} elevation={0}>
4463
{detail}
64+
<div className={classes.itemWrapper}>
65+
{conditions.map((x) => {
66+
return (
67+
<div className={classes.item} key={x.display}>
68+
<Typography>{x.display}</Typography>
69+
<div className={`${classes.condition} ${x.className}`} />
70+
</div>
71+
)
72+
})}
73+
</div>
4574
</Paper>
4675
</Popover>
4776
</span>

components/ValidatorsTable/styles.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,30 @@ export const useGetStyles = (status?: string, alignRight?: boolean) => {
113113
textOverflow: 'ellipsis',
114114
whitespace: 'nowrap',
115115
},
116+
itemWrapper: {
117+
marginTop: theme.spacing(2),
118+
},
119+
item: {
120+
display: 'flex',
121+
alignItems: 'center',
122+
justifyContent: 'space-between',
123+
},
124+
condition: {
125+
width: theme.spacing(1),
126+
height: theme.spacing(1),
127+
background: theme.palette.condition.zero,
128+
marginLeft: theme.spacing(1),
129+
borderRadius: '50%',
130+
'&.green': {
131+
background: theme.palette.condition.one,
132+
},
133+
'&.yellow': {
134+
background: theme.palette.condition.two,
135+
},
136+
'&.red': {
137+
background: theme.palette.condition.three,
138+
},
139+
},
116140
}),
117141
{
118142
name: 'HookGlobalStyles',

custom.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ interface Validator {
118118
rewards?: TokenAmount
119119
delegated?: TokenAmount
120120
unbonding?: TokenAmount
121+
missedBlockCounter: number
121122
}
122123

123124
interface Unbonding {

graphql/queries/validators.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ subscription Validators {
2020
voting_power
2121
height
2222
}
23+
validator_signing_infos(order_by: {height: desc}, limit: 1) {
24+
missed_blocks_counter
25+
}
2326
status: validator_statuses(limit: 1, order_by: { height: desc }) {
2427
status
2528
jailed
@@ -56,3 +59,11 @@ subscription Validators($addresses: [String!]) {
5659
}
5760
}
5861
`
62+
63+
export const getSlashingParams = (crypto: string) => `
64+
query Validators {
65+
slashing_params(order_by: {height: desc}, limit: 1) {
66+
params
67+
}
68+
}
69+
`

locales/en/common.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@
178178
"voting power": "Voting Power",
179179
"self ratio": "Self%",
180180
"status": "Status",
181-
"status popover detail": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent urna libero, mattis nec ultrices sit amet, pharetra vitae lorem. Quisque pretium pulvinar eros",
181+
"status popover detail": "The overall health of a validator within the current signed block window",
182182
"24h": "24h",
183183
"insert address": "Insert address",
184184
"add address": "Add address",
@@ -379,5 +379,6 @@
379379
"proposal details": "Proposal Details",
380380
"deposit to": "Deposit to",
381381
"deposit time": "Deposit Time: {{from}} to {{to}}",
382-
"proposal with id": "# proposal {{id}}"
382+
"proposal with id": "# proposal {{id}}",
383+
"target delegation amount": "Target delegation amount"
383384
}

locales/en/faq.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
"contact us": "Can’t find answers to your questions? Please contact us at "
3-
}
2+
"contact us": "Can’t find answers to your questions? Please contact us at "
3+
}

locales/zh/common.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@
176176
"voting power": "[zh] Voting Power",
177177
"self ratio": "[zh] Self%",
178178
"status": "[zh] Status",
179-
"status popover detail": "[zh] Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent urna libero, mattis nec ultrices sit amet, pharetra vitae lorem. Quisque pretium pulvinar eros",
179+
"status popover detail": "[zh] The overall health of a validator within the current signed block window",
180180
"24h": "[zh] 24h",
181181
"insert address": "[zh] Insert address",
182182
"add address": "[zh] Add address",

locales/zh/faq.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
"contact us": "[zh] Can’t find answers to your questions? Please contact us at "
3-
}
2+
"contact us": "[zh] Can’t find answers to your questions? Please contact us at "
3+
}

0 commit comments

Comments
 (0)