forked from cerc-io/cosmos-explorer
Finish uptime
This commit is contained in:
parent
58d8cd034a
commit
be8ca28c56
32
src/components/UptimeBar.vue
Normal file
32
src/components/UptimeBar.vue
Normal file
@ -0,0 +1,32 @@
|
||||
<script lang=ts setup>
|
||||
import type { Commit } from "@/types";
|
||||
|
||||
const props = defineProps({
|
||||
blocks: { type: Array as PropType<Commit[]>},
|
||||
validator: { type: String },
|
||||
})
|
||||
|
||||
const bars = computed(() => {
|
||||
const uptime = Array(50).fill({height:0, color: 'bg-secondary'})
|
||||
props.blocks.forEach(element => {
|
||||
const has = element.signatures?.findIndex(sig => sig.validator_address === props.validator )
|
||||
// console.log(has, props.validato, element)
|
||||
uptime.push({
|
||||
height: element.height,
|
||||
color: has > -1 ? 'bg-success' : 'bg-error'
|
||||
})
|
||||
uptime.shift()
|
||||
});
|
||||
return uptime
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
<div class="d-flex justify-evenly">
|
||||
<span v-for="(b,i) in bars"
|
||||
:key="i"
|
||||
:class="b.color"
|
||||
style="width:1.5%">
|
||||
<v-tooltip v-if="Number(b.height) > 0" activator="parent" location="top">{{ b.height }}</v-tooltip>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
@ -50,6 +50,11 @@ export function consensusPubkeyToHexAddress(consensusPubkey?: {"@type": string,
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
export function valconsToBase64(address: string) {
|
||||
if(address) return toHex(fromBech32(address).data).toUpperCase()
|
||||
return ''
|
||||
}
|
||||
|
||||
export function toETHAddress(cosmosAddress: string) {
|
||||
return `0x${toHex(fromBech32(cosmosAddress).data)}`
|
||||
|
@ -63,7 +63,8 @@ export class CosmosRestClient {
|
||||
return this.request(this.registry.slashing_params, {})
|
||||
}
|
||||
async getSlashingSigningInfos() {
|
||||
return this.request(this.registry.slashing_signing_info, {})
|
||||
const query = "?pagination.limit=300"
|
||||
return this.request(this.registry.slashing_signing_info, {}, query)
|
||||
}
|
||||
// Gov
|
||||
async getGovParamsVoting() {
|
||||
|
@ -1,41 +1,72 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted } from 'vue';
|
||||
import {fromBase64, fromBech32, fromHex, toBase64, toBech32, toHex} from '@cosmjs/encoding'
|
||||
import { useFormatter, useStakingStore, useBaseStore, useBlockchain } from '@/stores';
|
||||
import UptimeBar from '@/components/UptimeBar.vue';
|
||||
import type { Commit } from '@/types'
|
||||
import { consensusPubkeyToHexAddress, valconsToBase64 } from "@/libs";
|
||||
|
||||
interface TabItem{
|
||||
tabName: string
|
||||
id: number
|
||||
value: string
|
||||
}
|
||||
const stakingStore = useStakingStore();
|
||||
const baseStore = useBaseStore();
|
||||
const chainStore = useBlockchain()
|
||||
const format = useFormatter();
|
||||
const latest = ref({})
|
||||
const commits = ref([] as Commit[]);
|
||||
const keyword = ref("")
|
||||
|
||||
const tab = ref('');
|
||||
const tabList: Array<TabItem> = [
|
||||
{ tabName: 'Group By Validator', id: 1, value: 'validator' },
|
||||
{ tabName: 'Group By Proposer', id: 2, value: 'proposer' },
|
||||
]
|
||||
const signingInfo = ref({})
|
||||
|
||||
const validators = computed(()=> {
|
||||
if(keyword) return stakingStore.validators.filter(x => x.description.moniker.indexOf(keyword.value) > -1)
|
||||
return stakingStore.validators
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
baseStore.fetchLatest().then(block => {
|
||||
latest.value = block
|
||||
commits.value.unshift(block.block.last_commit)
|
||||
const height = Number(block.block.header?.height|| 0)
|
||||
if(height > 0) {
|
||||
// constructs sequence for loading blocks
|
||||
let promise = Promise.resolve()
|
||||
for (let i = height - 1; i > height - 50; i -= 1) {
|
||||
if (i > height - 48 && i > 0) {
|
||||
promise = promise.then(() => new Promise(resolve => {
|
||||
baseStore.fetchBlock(i).then((x) => {
|
||||
commits.value.unshift(x.block.last_commit)
|
||||
resolve()
|
||||
})
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
chainStore.rpc.getSlashingSigningInfos().then((x)=> {
|
||||
x.info?.forEach(i => {
|
||||
signingInfo.value[valconsToBase64(i.address)] = i
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
function clickTab(item: TabItem) {
|
||||
// toggle tab and stop another tab fetch
|
||||
console.log(tab, 'tab')
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="">
|
||||
<VTabs v-model="tab" class="v-tabs-pill">
|
||||
<VTab
|
||||
v-for="(item, index) in tabList"
|
||||
:key="index"
|
||||
:value="item.value"
|
||||
@click="clickTab(item)"
|
||||
>{{ item.tabName }}</VTab>
|
||||
</VTabs>
|
||||
<VWindow v-model="tab" class="mt-5">
|
||||
<VWindowItem v-for="(item, index) in tabList" :key="index" :value="item.value">
|
||||
<!-- <ProposalListItem :proposals="store?.proposals['2']" /> -->
|
||||
|
||||
<VCard> {{item.tabName}}</VCard>
|
||||
</VWindowItem>
|
||||
</VWindow>
|
||||
<div>
|
||||
<VRow>
|
||||
<VCol cols="12" md="4">Current Height: {{latest.block?.header?.height}} </VCol>
|
||||
<VCol cols="12" md="8"><VTextField v-model="keyword" label="Keywords to filter validators" /></VCol>
|
||||
</VRow>
|
||||
<VRow>
|
||||
<VCol v-for="(v, i) in validators" cols="12" md="3" xl="2">
|
||||
<div class="d-flex justify-between">
|
||||
<span class="text-truncate">{{i + 1}}. {{v.description.moniker}}</span>
|
||||
<VChip v-if="Number(signingInfo[consensusPubkeyToHexAddress(v.consensus_pubkey)]?.missed_blocks_counter || 0) > 0" size="small" class="mb-1" label color="error">{{ signingInfo[consensusPubkeyToHexAddress(v.consensus_pubkey)]?.missed_blocks_counter }}</VChip>
|
||||
<VChip v-else size="small" class="mb-1" label color="success">{{ signingInfo[consensusPubkeyToHexAddress(v.consensus_pubkey)]?.missed_blocks_counter }}</VChip>
|
||||
</div>
|
||||
<UptimeBar :blocks="commits" :validator="toBase64(fromHex(consensusPubkeyToHexAddress(v.consensus_pubkey)))" />
|
||||
</VCol>
|
||||
</VRow>
|
||||
</div>
|
||||
</template>
|
||||
<route>
|
||||
|
@ -80,15 +80,17 @@ export interface Block {
|
||||
"evidence": {
|
||||
"evidence": any[]
|
||||
},
|
||||
"last_commit": {
|
||||
"height": string,
|
||||
"round": number,
|
||||
"block_id": BlockId,
|
||||
"signatures": Signature[]
|
||||
}
|
||||
"last_commit": Commit
|
||||
}
|
||||
}
|
||||
|
||||
export interface Commit {
|
||||
"height": string,
|
||||
"round": number,
|
||||
"block_id": BlockId,
|
||||
"signatures": Signature[]
|
||||
}
|
||||
|
||||
export interface TendermintValidator {
|
||||
"address": string,
|
||||
"pub_key": Key,
|
||||
|
@ -29,4 +29,10 @@ export class Response<T> {
|
||||
export interface Coin {
|
||||
amount: string;
|
||||
denom: string;
|
||||
}
|
||||
|
||||
export interface UptimeStatus {
|
||||
height: number;
|
||||
filled: boolean;
|
||||
signed: boolean;
|
||||
}
|
Loading…
Reference in New Issue
Block a user