Skip to content

Commit

Permalink
feat: display principal rep threshold on network section & representa…
Browse files Browse the repository at this point in the history
…tives page (closes #92)
  • Loading branch information
mistakia committed Jun 5, 2024
1 parent 9b7879b commit 9beecae
Show file tree
Hide file tree
Showing 6 changed files with 164 additions and 56 deletions.
7 changes: 6 additions & 1 deletion src/core/network/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,9 @@ export {
} from './actions'
export { networkReducer } from './reducer'
export { networkSagas } from './sagas'
export { getNetwork, getNetworkStats, getNetworkWattHour } from './selectors'
export {
getNetwork,
getNetworkStats,
getNetworkWattHour,
get_principal_representative_minimum_weight
} from './selectors'
9 changes: 9 additions & 0 deletions src/core/network/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ export function getNetworkWattHour(state) {
return sum
}

export function get_principal_representative_minimum_weight(state) {
const network = getNetwork(state)
const trended_weight = network.getIn(['weight', 'trendedWeight', 'median'])
if (!trended_weight) {
return null
}
return BigInt(trended_weight) / BigInt(1000)
}

export function getNetworkStats(state) {
const network = getNetwork(state)
const quorum_total = BigNumber(network.getIn(['weight', 'quorumTotal'], 0))
Expand Down
20 changes: 17 additions & 3 deletions src/views/components/network/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ import { connect } from 'react-redux'
import { createSelector } from 'reselect'
import BigNumber from 'bignumber.js'

import { getNetwork, getNetworkStats, getNetworkWattHour } from '@core/network'
import {
getNetwork,
getNetworkStats,
getNetworkWattHour,
get_principal_representative_minimum_weight
} from '@core/network'
import { getNetworkUnconfirmedBlockCount } from '@core/accounts'
import { nanodb_actions } from '@core/nanodb'

Expand All @@ -14,7 +19,15 @@ const mapStateToProps = createSelector(
getNetworkWattHour,
getNetworkUnconfirmedBlockCount,
(state) => state.get('nanodb'),
(network, stats, wattHour, unconfirmed_block_pool_count, nanodb) => {
get_principal_representative_minimum_weight,
(
network,
stats,
wattHour,
unconfirmed_block_pool_count,
nanodb,
principal_representative_minimum_weight
) => {
const send_volume_raw = network.getIn(
['stats', 'nanodb', 'send_volume_last_24_hours'],
0
Expand Down Expand Up @@ -51,7 +64,8 @@ const mapStateToProps = createSelector(
wattHour,
unconfirmed_block_pool_count,
send_volume_nano,
median_latency_of_median_bucket_by_confirmed_blocks_24h
median_latency_of_median_bucket_by_confirmed_blocks_24h,
principal_representative_minimum_weight
}
}
)
Expand Down
32 changes: 29 additions & 3 deletions src/views/components/network/network.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import React, { useEffect } from 'react'
import React, { useEffect, useMemo } from 'react'
import PropTypes from 'prop-types'
import HelpOutlineIcon from '@mui/icons-material/HelpOutline'
import Tooltip from '@mui/material/Tooltip'
import ImmutablePropTypes from 'react-immutable-proptypes'
import BigNumber from 'bignumber.js'

import './network.styl'

import { format_value } from '@core/utils'

// add commas to large number
const format_number = (x) => x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')

Expand All @@ -29,7 +32,8 @@ export default function Network({
unconfirmed_block_pool_count,
send_volume_nano,
get_blocks_confirmed_summary,
median_latency_of_median_bucket_by_confirmed_blocks_24h
median_latency_of_median_bucket_by_confirmed_blocks_24h,
principal_representative_minimum_weight
}) {
useEffect(() => {
// get confirmed blocks summary for 24h period for `Tx Speed (24h)`
Expand Down Expand Up @@ -59,6 +63,18 @@ export default function Network({
const energyText =
'Estimated live network CPU energy usage of Principle Representatives based on collected CPU model info. The estimate is based on CPU TDP, which is the average power, in watts, the processor dissipates when operating at base frequency with all cores active under manufacture-defined, high-complexity workload'

const pr_min_weight_text = `The minimum weight required to be a principal representative is the trended weight / 1000. Current threshold: \n${principal_representative_minimum_weight} Raw\n${BigNumber(principal_representative_minimum_weight).shiftedBy(-30).toNumber()} Nano`

const pr_min_weight = useMemo(() => {
return principal_representative_minimum_weight
? format_value({
value: BigNumber(principal_representative_minimum_weight)
.shiftedBy(-30)
.toNumber()
})
: '-'
}, [principal_representative_minimum_weight])

return (
<div className='network__container'>
<div className='network__title'>Network Stats</div>
Expand Down Expand Up @@ -211,6 +227,15 @@ export default function Network({
<div>Principal Reps</div>
<div>{stats.prCount || '-'}</div>
</div>
<div className='network__stat'>
<div>
Principal Rep Minimum Weight
<Tooltip title={pr_min_weight_text}>
<HelpOutlineIcon fontSize='inherit' />
</Tooltip>
</div>
<div>{pr_min_weight || '-'}</div>
</div>
<div className='network__stat'>
<div>Total Reps (24h)</div>
<div>{network.getIn(['totalReps'], '-')}</div>
Expand Down Expand Up @@ -266,5 +291,6 @@ Network.propTypes = {
unconfirmed_block_pool_count: PropTypes.number,
send_volume_nano: PropTypes.number,
get_blocks_confirmed_summary: PropTypes.func,
median_latency_of_median_bucket_by_confirmed_blocks_24h: PropTypes.number
median_latency_of_median_bucket_by_confirmed_blocks_24h: PropTypes.number,
principal_representative_minimum_weight: PropTypes.number
}
14 changes: 12 additions & 2 deletions src/views/components/representatives-weight/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
import { connect } from 'react-redux'
import { createSelector } from 'reselect'

import { getNetwork } from '@core/network'
import {
getNetwork,
get_principal_representative_minimum_weight
} from '@core/network'

import RepresentativesWeight from './representatives-weight'

const mapStateToProps = createSelector(getNetwork, (network) => ({ network }))
const mapStateToProps = createSelector(
getNetwork,
get_principal_representative_minimum_weight,
(network, principal_representative_minimum_weight) => ({
network,
principal_representative_minimum_weight
})
)

export default connect(mapStateToProps)(RepresentativesWeight)
138 changes: 91 additions & 47 deletions src/views/components/representatives-weight/representatives-weight.js
Original file line number Diff line number Diff line change
@@ -1,61 +1,105 @@
import React from 'react'
import React, { useMemo } from 'react'
import BigNumber from 'bignumber.js'
import ImmutablePropTypes from 'react-immutable-proptypes'

import './representatives-weight.styl'

export default class RepresentativesWeight extends React.Component {
render() {
const { network } = this.props
const onlineWeight = BigNumber(
network.getIn(['weight', 'onlineWeight', 'median'], 0)
)
const trendedWeight = BigNumber(
network.getIn(['weight', 'trendedWeight', 'median'], 0)
)
const quorumTotal = BigNumber.max(onlineWeight, trendedWeight)
const quorumWeightDelta = quorumTotal.multipliedBy(0.67)

const onlineSelected = onlineWeight.isGreaterThan(trendedWeight)

const onlineNano = onlineWeight.shiftedBy(-36)
const trendedNano = trendedWeight.shiftedBy(-36)
const quorumNano = quorumWeightDelta.shiftedBy(-36)
return (
<div className='representatives__weight-container'>
<div className='representatives__weight'>
<div
className={`representatives__weight-section ${
!onlineSelected && 'selected'
}`}>
<div className='representatives__weight-section-label'>Trended</div>
<div className='representatives__weight-section-value'>
{trendedNano.isNaN() ? '-' : `${trendedNano.toFormat(1)}M`}
</div>
import { format_value } from '@core/utils'

export default function RepresentativesWeight({
network,
principal_representative_minimum_weight
}) {
const pr_min_weight = useMemo(() => {
return principal_representative_minimum_weight
? format_value({
value: BigNumber(principal_representative_minimum_weight)
.shiftedBy(-30)
.toNumber()
})
: '-'
}, [principal_representative_minimum_weight])

const online_weight = useMemo(
() => BigNumber(network.getIn(['weight', 'onlineWeight', 'median'], 0)),
[network]
)

const trended_weight = useMemo(
() => BigNumber(network.getIn(['weight', 'trendedWeight', 'median'], 0)),
[network]
)

const quorum_total = useMemo(
() => BigNumber.max(online_weight, trended_weight),
[online_weight, trended_weight]
)
const quorum_weight_delta = useMemo(
() => quorum_total.multipliedBy(0.67),
[quorum_total]
)

const online_selected = useMemo(
() => online_weight.isGreaterThan(trended_weight),
[online_weight, trended_weight]
)

const online_nano = useMemo(
() => online_weight.shiftedBy(-36),
[online_weight]
)
const trended_nano = useMemo(
() => trended_weight.shiftedBy(-36),
[trended_weight]
)
const quorum_nano = useMemo(
() => quorum_weight_delta.shiftedBy(-36),
[quorum_weight_delta]
)

return (
<div className='representatives__weight-container'>
<div className='representatives__weight'>
<div
className={`representatives__weight-section ${
!online_selected && 'selected'
}`}>
<div className='representatives__weight-section-label'>Trended</div>
<div className='representatives__weight-section-value'>
{trended_nano.isNaN() ? '-' : `${trended_nano.toFormat(1)}M`}
</div>
<div
className={`representatives__weight-section ${
onlineSelected && 'selected'
}`}>
<div className='representatives__weight-section-label'>Online</div>
<div className='representatives__weight-section-value'>
{onlineNano.isNaN() ? '-' : `${onlineNano.toFormat(1)}M`}
</div>
</div>
<div
className={`representatives__weight-section ${
online_selected && 'selected'
}`}>
<div className='representatives__weight-section-label'>Online</div>
<div className='representatives__weight-section-value'>
{online_nano.isNaN() ? '-' : `${online_nano.toFormat(1)}M`}
</div>
</div>
<div className='representatives__weight-section'>
<div className='representatives__weight-section-label'>
Quorum Delta
</div>
<div className='representatives__weight-section-value'>
{quorum_nano.isNaN() ? '-' : `${quorum_nano.toFormat(1)}M`}
</div>
</div>
<div className='representatives__weight-section'>
<div className='representatives__weight-section-label'>
PR Threshold
</div>
<div className='representatives__weight-section'>
<div className='representatives__weight-section-label'>
Quorum Delta
</div>
<div className='representatives__weight-section-value'>
{quorumNano.isNaN() ? '-' : `${quorumNano.toFormat(1)}M`}
</div>
<div className='representatives__weight-section-value'>
{pr_min_weight}
</div>
</div>
</div>
)
}
</div>
)
}

RepresentativesWeight.propTypes = {
network: ImmutablePropTypes.map
network: ImmutablePropTypes.map,
principal_representative_minimum_weight: ImmutablePropTypes.number
}

0 comments on commit 9beecae

Please sign in to comment.