improve ui

This commit is contained in:
liangping 2023-05-18 21:20:19 +08:00
parent 0122fe89f6
commit be6cd1af7c
12 changed files with 66 additions and 39 deletions

View File

@ -41,7 +41,7 @@
"md-editor-v3": "^2.8.1", "md-editor-v3": "^2.8.1",
"numeral": "^2.0.6", "numeral": "^2.0.6",
"osmojs": "^14.0.0-rc.0", "osmojs": "^14.0.0-rc.0",
"ping-widget": "^0.0.13", "ping-widget": "^0.0.15",
"pinia": "^2.0.28", "pinia": "^2.0.28",
"postcss": "^8.4.23", "postcss": "^8.4.23",
"prismjs": "^1.29.0", "prismjs": "^1.29.0",

View File

@ -22,7 +22,7 @@ const header = computed(() => {
<VTable <VTable
v-if="header.length > 0" v-if="header.length > 0"
density="compact" density="compact"
height="300px" :height="value.length > 5? '300px': ''"
fixed-header fixed-header
hover hover
> >

View File

@ -5,10 +5,10 @@ const props = defineProps(['value']);
</script> </script>
<template> <template>
<div class="overflow-x-auto"> <div class="overflow-x-auto">
<table class="table w-full text-sm"> <table class="table table-compact w-full text-sm">
<tbody> <tbody>
<tr v-for="(v, k) of value"> <tr v-for="(v, k) of value">
<td class="text-capitalize" style="max-width: 100px">{{ String(k).replaceAll("_", " ") }}</td> <td class="text-capitalize whitespace-break-spaces w-1/5" style="min-width: 180px;">{{ String(k).replaceAll("_", " ") }}</td>
<td> <td>
<div <div
class="overflow-hidden w-auto whitespace-normal" class="overflow-hidden w-auto whitespace-normal"

View File

@ -30,7 +30,7 @@ import type {
PaginatedProposals, PaginatedProposals,
Tally, Tally,
} from '@/types/gov'; } from '@/types/gov';
import type { PaginatedSigningInfo } from '@/types/slashing'; import type { PaginatedSigningInfo, SlashingParam } from '@/types/slashing';
import type { import type {
Delegation, Delegation,
PaginatedDelegations, PaginatedDelegations,
@ -90,7 +90,7 @@ export interface RequestRegistry extends AbstractRegistry {
}>; }>;
mint_annual_provisions: Request<{ annual_provisions: string }>; mint_annual_provisions: Request<{ annual_provisions: string }>;
slashing_params: Request<any>; slashing_params: Request<{params: SlashingParam}>;
slashing_signing_info: Request<PaginatedSigningInfo>; slashing_signing_info: Request<PaginatedSigningInfo>;
gov_params_voting: Request<GovParams>; gov_params_voting: Request<GovParams>;

View File

@ -71,7 +71,7 @@ function color(v: string) {
{ {
meta: { meta: {
i18n: 'ibc', i18n: 'ibc',
order: 8 order: 9
} }
} }
</route> </route>

View File

@ -56,7 +56,7 @@ onMounted(() => {
{ {
meta: { meta: {
i18n: 'parameters', i18n: 'parameters',
order: 10 order: 50
} }
} }
</route> </route>

View File

@ -1,17 +1,16 @@
<script lang="ts" setup> <script lang="ts" setup>
import { ref, onMounted, computed, watchEffect } from 'vue'; import { ref, onMounted, computed, watchEffect } from 'vue';
import { fromHex, toBase64 } from '@cosmjs/encoding'; import { fromHex, toBase64 } from '@cosmjs/encoding';
import { Icon } from '@iconify/vue';
import { import {
useFormatter, useFormatter,
useStakingStore, useStakingStore,
useBaseStore, useBaseStore,
useBlockchain, useBlockchain,
useParamStore,
} from '@/stores'; } from '@/stores';
import UptimeBar from '@/components/UptimeBar.vue'; import UptimeBar from '@/components/UptimeBar.vue';
import type { Block, Commit } from '@/types'; import type { Commit, SlashingParam, SigningInfo } from '@/types';
import { consensusPubkeyToHexAddress, valconsToBase64 } from '@/libs'; import { consensusPubkeyToHexAddress, valconsToBase64 } from '@/libs';
import type { SigningInfo } from '@/types/slashing';
const props = defineProps(['chain']); const props = defineProps(['chain']);
@ -23,6 +22,7 @@ const latest = ref(0);
const commits = ref([] as Commit[]); const commits = ref([] as Commit[]);
const keyword = ref(''); const keyword = ref('');
const live = ref(true); const live = ref(true);
const slashingParam = ref({} as SlashingParam)
const signingInfo = ref({} as Record<string, SigningInfo>); const signingInfo = ref({} as Record<string, SigningInfo>);
@ -36,15 +36,20 @@ const validators = computed(() => {
}); });
const list = computed(() => { const list = computed(() => {
return validators.value.map(v => ({ const window = Number(slashingParam.value.signed_blocks_window|| 0)
v, return validators.value.map(v => {
signing: signingInfo.value[consensusPubkeyToHexAddress(v.consensus_pubkey)], const signing = signingInfo.value[consensusPubkeyToHexAddress(v.consensus_pubkey)]
hex: toBase64(fromHex(consensusPubkeyToHexAddress(v.consensus_pubkey))) return {
})) v,
signing,
hex: toBase64(fromHex(consensusPubkeyToHexAddress(v.consensus_pubkey))),
uptime: signing && window > 0 ? (window - Number(signing.missed_blocks_counter)) / window: undefined
}})
}) })
onMounted(() => { onMounted(() => {
live.value = true; live.value = true;
baseStore.fetchLatest().then(b => { baseStore.fetchLatest().then(b => {
latest.value = Number(b.block.header.height); latest.value = Number(b.block.header.height);
commits.value.unshift(b.block.last_commit); commits.value.unshift(b.block.last_commit);
@ -74,6 +79,10 @@ onMounted(() => {
signingInfo.value[valconsToBase64(i.address)] = i; signingInfo.value[valconsToBase64(i.address)] = i;
}); });
}); });
chainStore.rpc.getSlashingParams().then(x => {
slashingParam.value = x.params
})
}); });
const commits2 = computed(() => { const commits2 = computed(() => {
@ -140,23 +149,24 @@ function changeTab(v: string) {
<thead class=" capitalize"> <thead class=" capitalize">
<tr> <tr>
<td>Validator</td> <td>Validator</td>
<td>Start Height</td> <td class="text-right">Uptime</td>
<td>Signed Precommits</td> <td class="text-right">Signed Precommits</td>
<td>Missing blocks</td> <td class="text-right">Start Height</td>
<td>Last Jailed Time</td> <td>Last Jailed Time</td>
<td>Tombstoned</td> <td>Tombstoned</td>
</tr> </tr>
</thead> </thead>
<tr v-for="({v, signing}, i) in list"> <tr v-for="({v, signing, uptime}, i) in list" class="hover">
<td><div class="truncate max-w-sm">{{ i+1 }}. {{ v.description.moniker }}</div></td> <td><div class="truncate max-w-sm">{{ i+1 }}. {{ v.description.moniker }}</div></td>
<td>{{ signing?.start_height }}</td> <td class="text-right">
<td> <span v-if="signing" class="" :class="uptime > 0.95 ? 'text-green-500':'text-red-500'"><div class="tooltip" :data-tip="`${signing.missed_blocks_counter} missing blocks`"> {{ format.percent(uptime) }} </div> </span>
{{ signing?.index_offset }}
<span v-if="signing && signing.jailed_until.startsWith('1970')" class="badge badge-sm">{{ format.percent(Number(signing.index_offset)/(latest-Number(signing.start_height))) }}</span>
</td> </td>
<td> <td class="text-right text-xs">
<span v-if="signing" class="badge badge-sm text-white" :class="Number(signing?.missed_blocks_counter) < 10?'badge-success':'badge-error'">{{ signing?.missed_blocks_counter }}</span> {{ signing?.index_offset }}<br>
<span v-if="signing && signing.jailed_until.startsWith('1970')" class="text-xs">{{ format.percent(Number(signing.index_offset)/(latest-Number(signing.start_height))) }}</span>
</td> </td>
<td class="text-right">{{ signing?.start_height }}</td>
<td><span v-if="signing && !signing.jailed_until.startsWith('1970')"> <td><span v-if="signing && !signing.jailed_until.startsWith('1970')">
<div class="tooltip" :data-tip="format.toDay(signing?.jailed_until, 'long')"> <div class="tooltip" :data-tip="format.toDay(signing?.jailed_until, 'long')">
<span>{{ format.toDay(signing?.jailed_until, "from") }}</span> <span>{{ format.toDay(signing?.jailed_until, "from") }}</span>
@ -164,6 +174,12 @@ function changeTab(v: string) {
</span></td> </span></td>
<td class=" capitalize">{{ signing?.tombstoned }}</td> <td class=" capitalize">{{ signing?.tombstoned }}</td>
</tr> </tr>
<tfoot>
<tr>
<td colspan="2" class="text-right"> Minimum uptime per window: <span class="lowercase tooltip" :data-tip="`Window size: ${ slashingParam.signed_blocks_window }`"><span class="ml-2 btn btn-error btn-xs">{{ format.percent(slashingParam.min_signed_per_window) }}</span> </span></td>
<td colspan="8"></td>
</tr>
</tfoot>
</table> </table>
</div> </div>

View File

@ -1,7 +1,7 @@
{ {
"module": { "module": {
"dashboard": "Dashboard", "dashboard": "Dashboard",
"blocks": "Blocks&Transaction", "blocks": "Blocks",
"staking": "Staking", "staking": "Staking",
"governance": "Governance", "governance": "Governance",
"parameters": "Parameters", "parameters": "Parameters",

View File

@ -15,6 +15,7 @@ import {
useGovStore, useGovStore,
useMintStore, useMintStore,
useStakingStore, useStakingStore,
useWalletStore,
} from '.'; } from '.';
import { useBlockModule } from '@/modules/[chain]/block/block'; import { useBlockModule } from '@/modules/[chain]/block/block';
import { DEFAULT } from '@/libs'; import { DEFAULT } from '@/libs';
@ -67,7 +68,7 @@ export const useBlockchain = defineStore('blockchain', {
icon: { image: this.current.logo, size: '22' }, icon: { image: this.current.logo, size: '22' },
i18n: false, i18n: false,
badgeContent: this.isConsumerChain? 'Consumer': undefined, badgeContent: this.isConsumerChain? 'Consumer': undefined,
badgeClass: 'bg-secondary', badgeClass: 'bg-warning',
children: routes children: routes
.filter((x) => x.meta.i18n) // defined menu name .filter((x) => x.meta.i18n) // defined menu name
.filter((x) => !this.current?.features || this.current.features.includes(String(x.meta.i18n))) // filter none-custom module .filter((x) => !this.current?.features || this.current.features.includes(String(x.meta.i18n))) // filter none-custom module
@ -124,6 +125,7 @@ export const useBlockchain = defineStore('blockchain', {
// const { global } = useTheme(); // const { global } = useTheme();
// global.current // global.current
// } // }
useWalletStore().$reset()
await this.randomSetupEndpoint(); await this.randomSetupEndpoint();
await useStakingStore().init(); await useStakingStore().init();
useBankStore().initial(); useBankStore().initial();

View File

@ -7,4 +7,5 @@ export * from './distribution'
export * from './gov' export * from './gov'
export * from './staking' export * from './staking'
export * from './tx' export * from './tx'
export * from './ibc' export * from './ibc'
export * from './slashing'

View File

@ -1,14 +1,22 @@
import type { PaginatedResponse } from "./common"; import type { PaginatedResponse } from "./common";
export interface SigningInfo { export interface SigningInfo {
"address": string, address: string,
"start_height": string, start_height: string,
"index_offset": string, index_offset: string,
"jailed_until": string, jailed_until: string,
"tombstoned": boolean, tombstoned: boolean,
"missed_blocks_counter": string missed_blocks_counter: string
} }
export interface SlashingParam{
signed_blocks_window: string,
min_signed_per_window: string,
downtime_jail_duration: string,
slash_fraction_double_sign: string,
slash_fraction_downtime: string
}
export interface PaginatedSigningInfo extends PaginatedResponse { export interface PaginatedSigningInfo extends PaginatedResponse {
info: SigningInfo[] info: SigningInfo[]
} }

View File

@ -6808,10 +6808,10 @@ pify@^3.0.0:
resolved "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz" resolved "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz"
integrity sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg== integrity sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==
ping-widget@^0.0.13: ping-widget@^0.0.15:
version "0.0.13" version "0.0.15"
resolved "https://registry.yarnpkg.com/ping-widget/-/ping-widget-0.0.13.tgz#3738882da243871f7ed322cd75ef7b1bed8fd3bb" resolved "https://registry.yarnpkg.com/ping-widget/-/ping-widget-0.0.15.tgz#b15698ab7649fc8bd2318d7488366f3b30bcf5c6"
integrity sha512-BPpPcwDdffqHFO/6MeD3JleGWLFhOSSQLG2L0WaI1aiAe1em8gTC03refg86CjjwXtU4XtwJ0xnXgbJAVvZzjA== integrity sha512-aWUJwtwWbL7AXsAXpzQX8G5IQgGbhV5EM96wmcEez9Wp/UbwJ5BYOj8fdVDdW4yjzScnJ35R9KnHlpoOhzlF0g==
dependencies: dependencies:
"@cosmjs/amino" "^0.30.1" "@cosmjs/amino" "^0.30.1"
"@cosmjs/ledger-amino" "^0.30.1" "@cosmjs/ledger-amino" "^0.30.1"