Skip to content

Commit

Permalink
refactor: query validators uptime on demand [wip] [PTD-1313]
Browse files Browse the repository at this point in the history
  • Loading branch information
dawidsowardx committed Oct 4, 2024
1 parent 959c313 commit 4da6db4
Show file tree
Hide file tree
Showing 18 changed files with 586 additions and 427 deletions.
28 changes: 28 additions & 0 deletions apps/dashboard/src/lib/validators/UptimeSelector.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<script lang="ts">
import {
uptimeUiOptions as options,
type UptimeValue
} from '@api/utils/entities/component/validator'
import SimplePicker from '@components/_base/picker/simple-picker/SimplePicker.svelte'
import { uptimeModule } from './uptime-module'
export let selected: UptimeValue
let selectedValue: (typeof options)[number]
$: selected = selectedValue?.value
$: {
console.log('selected value uptime', selected)
uptimeModule.maybeQueryUptime(selected)
}
</script>

<div class="picker">
<SimplePicker {options} bind:selected={selectedValue} />
</div>

<style lang="scss">
.picker {
width: var(--uptime-selector-width, 6rem);
min-width: 6rem;
}
</style>
88 changes: 88 additions & 0 deletions apps/dashboard/src/lib/validators/uptime-module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { BehaviorSubject } from 'rxjs'
import {
calculateApy,
getValidatorUptimeSinceDate,
uptimePeriodDefinition,
type UptimeValue
} from '@api/utils/entities/component/validator'
import type BigNumber from 'bignumber.js'
import type { ValidatorCollectionItem } from '@common/gateway-sdk'

type ValidatorAddress = string

export type UptimeData = Partial<
Record<
UptimeValue,
Record<
ValidatorAddress,
number | undefined
>
>
>

export const UptimeModule = () => {
const isLoading = new BehaviorSubject<boolean>(false)
let validators: Promise<{ address: string }[]> | undefined
let uptimeData: any = {}
return {
setValidators: (promise: typeof validators) => {
validators = promise
},
hasUptimeData: (uptime: UptimeValue) => {
return !!uptimeData[uptime]
},
getDataForUptime: (uptime: UptimeValue) => {
return uptimeData[uptime] || {}
},
getPercentage: (uptime: UptimeValue, address: ValidatorAddress) => {},
getApy: (
validator: ValidatorCollectionItem,
uptime: UptimeValue,
totalAmountStaked: BigNumber
) => {
const address = validator.address
// const fee = Number(validator.effective_fee_factor.current.fee_factor)
const fee = Number(validator.effective_fee_factor?.current?.fee_factor || (validator as any).fee()) // TODO: fix this
const uptimePercentage = uptimeData[uptime]?.[address]
return calculateApy(fee, uptimePercentage, totalAmountStaked)
},
maybeQueryUptime: async (uptime: UptimeValue | undefined) => {
if (!uptime) return
if (!validators) {
throw new Error('Validators not set')
}
if (uptimeData[uptime]) {
return uptimeData[uptime]
}

uptimeData[uptime] = {}

isLoading.next(true)

return validators
.then((v) =>
getValidatorUptimeSinceDate(v.map((v) => v.address))(
uptimePeriodDefinition[uptime].getStartingPoint()
)
)
.then((value) => {
isLoading.next(false)
if (value.isOk()) {
uptimeData[uptime] = value.value
return uptimeData[uptime]
}
})
.catch((e) => {
console.error(e)
uptimeData[uptime] = undefined
})
},
clean: () => {
validators = undefined
uptimeData = {}
},
isLoading$: isLoading.asObservable()
}
}

export const uptimeModule = UptimeModule()
90 changes: 20 additions & 70 deletions apps/dashboard/src/pages/navbar-pages/staking/Validators.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
</script>

<script lang="ts">
import ValidatorList from './validator-list/ValidatorList.svelte'
import Icon from '@components/_base/icon/IconNew.svelte'
import StakingCard from '../../../lib/staking-card/StakingCard.svelte'
Expand All @@ -43,12 +42,12 @@
import AvailableToStake from './available-to-stake/AvailableToStake.svelte'
import { track } from '../../../routes/+layout.svelte'
import type { ResultAsync } from 'neverthrow'
import ValidatorListWrapper from './validator-list/ValidatorListWrapper.svelte'
export let validators: Promise<ValidatorListItem<true, true, true>[]>
export let validators: Promise<ValidatorListItem<true, true>[]>
export let totalXrdBalance: ResultAsync<string, { code: string }>
export let filteredValidators:
| ValidatorListItem<true, true, true>[]
| undefined = undefined
export let filteredValidators: ValidatorListItem<true, true>[] | undefined =
undefined
const getTotal =
(type: 'staked' | 'unstaking' | 'readyToClaim') =>
Expand All @@ -75,10 +74,6 @@
$: totalReadyToClaim = $stakeInfo.then(getTotal('readyToClaim'))
const dispatch = createEventDispatcher<{
'show-claim-all': undefined
'show-claim-single': string
'show-stake-multiple': undefined
'show-stake-single': string
'show-filters': undefined
'reset-filters': undefined
}>()
Expand All @@ -102,11 +97,11 @@
(key) => $selectedValidators[key]
)

if (selected.length === 1) {
dispatch('show-stake-single', selected[0])
} else {
dispatch('show-stake-multiple')
}
goto(
selected.length === 1
? `/network-staking/${selected[0]}/stake`
: '/network-staking/stake-multiple'
)
}}
on:clear-all={() => {
$selectedValidators = {}
Expand Down Expand Up @@ -160,14 +155,14 @@
size="big"
on:click={() => {
track('click:claim-all')
dispatch('show-claim-all')
goto('/network-staking/claim-multiple')
}}>Claim All</ButtonNew
>
{/await}
</div>
</StakingCard>

<ValidatorList
<ValidatorListWrapper
validators={validators.then((v) =>
$stakeInfo.then((stakes) =>
v.filter(
Expand All @@ -178,34 +173,12 @@
)
)
)}
>
<svelte:fragment
slot="rows"
let:ValidatorRow
let:selectedUptime
let:validators
>
{#await validators}
{#each Array(3) as _}
<ValidatorRow input={'loading'} />
{/each}
{:then validators}
{#each validators as validator}
<ValidatorRow
input={{
validator,
selectedUptime
}}
showStakeInfo
on:click={() => goto(`/network-staking/${validator.address}`)}
on:claim-validator={(e) => {
dispatch('show-claim-single', e.detail)
}}
/>
{/each}
{/await}
</svelte:fragment>
</ValidatorList>
showStakeInfo
amountOfPlaceholders={3}
on:claim-validator={(e) => {
goto(`/network-staking/claim/${e.detail}`)
}}
/>
</div>
{/if}

Expand Down Expand Up @@ -237,36 +210,13 @@
</div>
</div>

<ValidatorList
<ValidatorListWrapper
validators={filteredValidators ?? validators}
amountOfPlaceholders={15}
on:click-validator={(e) => {
goto(`/network-staking/${e.detail}`)
}}
>
<svelte:fragment
slot="rows"
let:ValidatorRow
let:validators
let:selectedUptime
let:columnIds
>
{#await validators}
{#each Array(15) as _}
<ValidatorRow input={'loading'} />
{/each}
{:then validators}
{#each validators as validator}
<ValidatorRow
input={{
validator,
selectedUptime
}}
on:click={() => goto(`/network-staking/${validator.address}`)}
/>
{/each}
{/await}
</svelte:fragment>
</ValidatorList>
/>

<style lang="scss">
.title-header {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
totalXRDStakeFilter: [0, 100] as [number, number],
uptimeFilterPercentage: 0,
uptimeFilter: {
timeframe: '1month' as '1month',
timeframe: '1month' as UptimeValue,
percentage: 0
},
acceptsStakeFilter: false,
Expand All @@ -21,7 +21,7 @@
import SwitchFilterCard from './switch-filter-card/SwitchFilterCard.svelte'
import { createEventDispatcher } from 'svelte'
import SidePanelHeader from '@components/_base/side-panel/SidePanelHeader.svelte'
import type { Validator } from '@api/_deprecated/utils/entities/validator'
import { type UptimeValue } from '@api/utils/entities/component/validator'
export let open: boolean
export let feeValues: number[]
Expand All @@ -44,36 +44,10 @@
uptimeFilterPercentage
} = DEFAULT_VALIDATORS_FILTER
const recentUptimeOptions: {
label: string
value: keyof Validator<true, true, true>['uptimePercentages']
default?: boolean
}[] = [
{ label: '1 day', value: '1day' },
{ label: '1 week', value: '1week' },
{ label: '1 month', value: '1month', default: true },
{ label: '3 months', value: '3months' },
{ label: '6 months', value: '6months' },
{ label: '1 year', value: '1year' },
{ label: 'All time', value: 'alltime' }
]
const changeDefaultUptime = (
uptime: (typeof recentUptimeOptions)[number]['value']
) => {
recentUptimeOptions.forEach((option) => {
option.default = option.value === uptime
})
}
$: changeDefaultUptime(selectedUptime.value)
let selectedUptime =
recentUptimeOptions.find((option) => option.default) ||
recentUptimeOptions[0]
let selectedUptime: UptimeValue = '1month'
$: uptimeFilter = {
timeframe: selectedUptime.value,
timeframe: selectedUptime,
percentage: uptimeFilterPercentage
}
Expand Down Expand Up @@ -165,7 +139,6 @@

<div class="card">
<ManualFilterCard
options={recentUptimeOptions}
bind:selected={selectedUptime}
bind:percentage={uptimeFilterPercentage}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
<script lang="ts">
import type { UptimeValue } from '@api/utils/entities/component/validator'
import PercentageInput from '@components/_base/input/PercentageInput.svelte'
import SimplePicker from '@components/_base/picker/simple-picker/SimplePicker.svelte'
import UptimeSelector from '@dashboard/lib/validators/UptimeSelector.svelte'
type T = $$Generic
export let options: {
label: string
value: T
}[]
export let selected: (typeof options)[number]
export let selected: UptimeValue
export let percentage = 0
</script>

Expand All @@ -19,9 +16,7 @@
<PercentageInput bind:value={percentage} />
</div>
<span class="text"> OVER THE PAST </span>
<div class="picker">
<SimplePicker {options} bind:selected />
</div>
<UptimeSelector bind:selected --uptime-selector-width="7rem" />
</div>
</div>

Expand All @@ -43,9 +38,5 @@
font-size: var(--card-text-size);
color: var(--card-text-color);
}
.picker {
width: 7rem;
}
}
</style>
Loading

0 comments on commit 4da6db4

Please sign in to comment.