diff --git a/src/modules/[chain]/uptime/index.vue b/src/modules/[chain]/uptime/index.vue index 1dcd0fc0..30c05326 100644 --- a/src/modules/[chain]/uptime/index.vue +++ b/src/modules/[chain]/uptime/index.vue @@ -5,10 +5,10 @@ import { useStakingStore, useBaseStore, useBlockchain, -useFormatter, + useFormatter, } from '@/stores'; import UptimeBar from '@/components/UptimeBar.vue'; -import type { SlashingParam, SigningInfo } from '@/types'; +import type { SlashingParam, SigningInfo, Block } from '@/types'; import { consensusPubkeyToHexAddress, valconsToBase64 } from '@/libs'; const props = defineProps(['chain']); @@ -53,24 +53,24 @@ const validatorSet = computed(() => { }); }); -const blocks = ref({} as Record); +const blockColors = ref({} as Record); -const grid = computed(() => { +const grid = computed(() => { - const validators = keyword.value.length === 0 ? validatorSet.value : - validatorSet.value.filter((v) => v.moniker.toLowerCase().includes(keyword.value.toLowerCase())); + const validators = keyword.value.length === 0 ? validatorSet.value : + validatorSet.value.filter((v) => v.moniker.toLowerCase().includes(keyword.value.toLowerCase())); const window = Number(slashingParam.value.signed_blocks_window || 0); return validators.map((v) => { const signing = signingInfo.value[v.hex]; const uptime = signing && window > 0 - ? (window - Number(signing.missed_blocks_counter)) / window - : undefined + ? (window - Number(signing.missed_blocks_counter)) / window + : undefined return { moniker: v.moniker, hex: v.hex, base64: v.base64, - blocks: padding(blocks.value[v.base64] || []) , + blocks: padding(blockColors.value[v.base64] || []), uptime, missed_blocks_counter: signing?.missed_blocks_counter || 0, signing @@ -78,77 +78,29 @@ const grid = computed(() => { }) }); +const preload = ref(false); baseStore.$subscribe((_, state) => { const newHeight = Number(state.latest?.block?.header?.height || 0) if (newHeight > latest.value) { latest.value = newHeight; - if(Number(state.latest.block.header.height) % 7 === 0 ) updateTotalSigningInfo(); - validatorSet.value.forEach((v) => { - const sig = state.latest.block.last_commit?.signatures.find((s) => s.validator_address === v.base64) - const block = blocks.value[v.base64] || []; - if (sig){ - block.push({ - height: state.latest.block.header.height, - color: sig.block_id_flag === 'BLOCK_ID_FLAG_COMMIT' ? 'bg-green-500' : 'bg-yellow-500' - }); - } else { - block.push({ - height: state.latest.block.header.height, - color: 'bg-red-500' - }); - } - if (block.length > 50) block.shift(); - blocks.value[v.base64] = block; - }); + // initialize if it's the first time + if(!preload.value) { + preFill(); + preload.value = true; + } + + if (Number(state.latest.block.header.height) % 7 === 0) updateTotalSigningInfo(); + fillblock(state.latest); } }); onMounted(() => { live.value = true; - baseStore.fetchLatest().then((l) => { - let b = l; - if ( - baseStore.recents?.findIndex((x) => x.block_id.hash === l.block_id.hash) > - -1 - ) { - b = baseStore.recents?.at(0) || l; - } - latest.value = Number(b.block.header.height); - const height = Number(b.block.header?.height || 0); - if (height > 50) { - // constructs sequence for loading blocks - let promise = Promise.resolve(); - for (let i = height - 1; i > height - 50; i -= 1) { - promise = promise.then( - () => - new Promise((resolve) => { - if (live.value) { - // continue only if the page is living - baseStore.fetchBlock(i).then((x) => { - validatorSet.value.forEach((v) => { - const sig = x.block.last_commit?.signatures.find((s) => s.validator_address === v.base64) - const block = blocks.value[v.base64] || []; - if (sig){ - block.unshift({ - height: x.block.header.height, - color: sig.block_id_flag === 'BLOCK_ID_FLAG_COMMIT' ? 'bg-green-500' : 'bg-yellow-500' - }); - } else { - block.unshift({ - height: x.block.header.height, - color: 'bg-red-500' - }); - } - blocks.value[v.base64] = block; - }); - resolve(); - }); - } - }) - ); - } - } + + // fill the recent blocks + baseStore.recents?.forEach((b) => { + fillblock(b, 'start'); }); updateTotalSigningInfo(); @@ -158,6 +110,50 @@ onMounted(() => { }); }); +function preFill() { + + if(latest.value > 50 && baseStore.recents.length >= 49 ) return + // preload 50 blocks if recent blocks are not enough + let promise = Promise.resolve(); + for (let i = latest.value - baseStore.recents.length; i > latest.value - 50 && i > 1; i -= 1) { + promise = promise.then(() => + new Promise((resolve) => { + if (live.value) { + // continue only if the page is living + if (i > latest.value - 50) + baseStore.fetchBlock(i).then((x) => { + fillblock(x, 'start'); + resolve(); + }); + } + }) + ); + } +} +function fillblock(b: Block, direction: string = 'end') { + validatorSet.value.forEach((v) => { + const sig = b.block.last_commit?.signatures.find((s) => s.validator_address === v.base64) + const block = blockColors.value[v.base64] || []; + let color = { + height: b.block.header.height, + color: 'bg-red-500' + } + if (sig) { + color = { + height: b.block.header.height, + color: sig.block_id_flag === 'BLOCK_ID_FLAG_COMMIT' ? 'bg-green-500' : 'bg-yellow-500' + } + } + if (direction === 'end') { + block.push(color); + } else { + block.unshift(color); + } + if (block.length > 50) block.shift(); + blockColors.value[v.base64] = block; + }); +} + function updateTotalSigningInfo() { chainStore.rpc.getSlashingSigningInfos().then((x) => { x.info?.forEach((i) => { @@ -184,36 +180,24 @@ function fetchAllKeyRotation() {