forked from cerc-io/cosmos-explorer
add power event
This commit is contained in:
parent
6cccb25964
commit
0e57913204
@ -14,6 +14,22 @@ export const percent = (num: number) => {
|
|||||||
return parseFloat((num * 100).toFixed(2));
|
return parseFloat((num * 100).toFixed(2));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function stringToUint8Array(str: string) {
|
||||||
|
const arr = [];
|
||||||
|
for (let i = 0, j = str.length; i < j; ++i) {
|
||||||
|
arr.push(str.charCodeAt(i));
|
||||||
|
}
|
||||||
|
return new Uint8Array(arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function uint8ArrayToString(arr: Uint8Array) {
|
||||||
|
let str = '';
|
||||||
|
for (let i = 0, j = arr.length; i < j; ++i) {
|
||||||
|
str += String.fromCharCode(arr[i]);
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
const COUNT_ABBRS = [
|
const COUNT_ABBRS = [
|
||||||
'',
|
'',
|
||||||
'K',
|
'K',
|
||||||
|
@ -17,6 +17,8 @@ import {
|
|||||||
} from '@/libs';
|
} from '@/libs';
|
||||||
import { PageRequest, type Coin, type Delegation, type PaginatedDelegations, type PaginatedTxs, type Validator } from '@/types';
|
import { PageRequest, type Coin, type Delegation, type PaginatedDelegations, type PaginatedTxs, type Validator } from '@/types';
|
||||||
import PaginationBar from '@/components/PaginationBar.vue';
|
import PaginationBar from '@/components/PaginationBar.vue';
|
||||||
|
import { fromBase64, toBase64 } from '@cosmjs/encoding';
|
||||||
|
import { stringToUint8Array, uint8ArrayToString } from '@/libs/utils';
|
||||||
|
|
||||||
const props = defineProps(['validator', 'chain']);
|
const props = defineProps(['validator', 'chain']);
|
||||||
|
|
||||||
@ -189,10 +191,56 @@ const tipMsg = computed(() => {
|
|||||||
|
|
||||||
function pageload(p: number) {
|
function pageload(p: number) {
|
||||||
page.setPage(p);
|
page.setPage(p);
|
||||||
|
page.limit = 10;
|
||||||
|
|
||||||
blockchain.rpc.getStakingValidatorsDelegations(validator, page).then(res => {
|
blockchain.rpc.getStakingValidatorsDelegations(validator, page).then(res => {
|
||||||
delegations.value = res
|
delegations.value = res
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const events = ref({} as PaginatedTxs)
|
||||||
|
|
||||||
|
enum EventType {
|
||||||
|
Delegate = 'delegate',
|
||||||
|
Unbond = 'unbond',
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectedEventType = ref(EventType.Unbond)
|
||||||
|
|
||||||
|
function loadPowerEvents(p: number, type: EventType) {
|
||||||
|
selectedEventType.value = type
|
||||||
|
page.setPage(p);
|
||||||
|
page.setPageSize(5);
|
||||||
|
blockchain.rpc.getTxs("?order_by=2&events={type}.validator='{validator}'", { type: selectedEventType.value, validator }, page).then(res => {
|
||||||
|
events.value = res
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function pagePowerEvents(page: number) {
|
||||||
|
loadPowerEvents(page, selectedEventType.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function mapEvents(events: {type: string, attributes: {key: string, value: string}[]}[]) {
|
||||||
|
const attributes = events.filter(x => x.type=== selectedEventType.value).filter(x => x.attributes.findIndex(attr => attr.value === toBase64(stringToUint8Array(validator))) > -1).map(x => {
|
||||||
|
// check if attributes need to decode
|
||||||
|
if(x.attributes.findIndex(a => a.value === `amount` || a.value === 'delegator_address') > -1) return x.attributes
|
||||||
|
const output = {} as {[key: string]: string }
|
||||||
|
x.attributes.forEach(attr => {
|
||||||
|
output[uint8ArrayToString(fromBase64(attr.key))] = uint8ArrayToString(fromBase64(attr.value))
|
||||||
|
})
|
||||||
|
return output
|
||||||
|
})
|
||||||
|
|
||||||
|
return attributes
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapDelegators(messages: any[]) {
|
||||||
|
if(!messages) return []
|
||||||
|
return Array.from(new Set(messages.map(x => x.delegator_address || x.grantee)))
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
@ -582,6 +630,72 @@ function pageload(p: number) {
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-5 bg-base-100 shadow rounded p-4">
|
||||||
|
<div class="text-lg mb-4 font-semibold">
|
||||||
|
<div class="tabs tabs-boxed bg-transparent">
|
||||||
|
|
||||||
|
<span class="mr-10">Power Events: </span>
|
||||||
|
<a
|
||||||
|
class="tab text-gray-400"
|
||||||
|
:class="{ 'tab-active': selectedEventType === EventType.Delegate }"
|
||||||
|
@click="loadPowerEvents(1, EventType.Delegate)"
|
||||||
|
>{{ $t('account.btn_delegate') }}</a
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
class="tab text-gray-400"
|
||||||
|
:class="{ 'tab-active': selectedEventType === EventType.Unbond }"
|
||||||
|
@click="loadPowerEvents(1, EventType.Unbond)"
|
||||||
|
>{{ $t('account.btn_unbond') }}</a
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="rounded overflow-auto">
|
||||||
|
<table class="table validatore-table w-full">
|
||||||
|
<thead>
|
||||||
|
<th class="text-left pl-4">{{ $t('account.delegator') }}</th>
|
||||||
|
<th class="text-left pl-4">{{ $t('account.amount') }}</th>
|
||||||
|
<th class="text-left pl-4">{{ $t('account.height') }} / {{ $t('account.time') }}</th>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="(item, i) in events.tx_responses">
|
||||||
|
<td class="pr-2 text-primary" style="max-width: 250px">
|
||||||
|
<RouterLink v-for="d in mapDelegators(item.tx?.body?.messages)" :to="`/${props.chain}/account/${d}`">
|
||||||
|
{{ d }}
|
||||||
|
</RouterLink>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="flex items-center" :class="{
|
||||||
|
'text-yes' : selectedEventType === EventType.Delegate,
|
||||||
|
'text-no' : selectedEventType === EventType.Unbond,
|
||||||
|
}">
|
||||||
|
<RouterLink :to="`/${props.chain}/tx/${item.txhash}`">
|
||||||
|
<span class="mr-2">
|
||||||
|
{{ (selectedEventType === EventType.Delegate ? '+' : '-')}} {{
|
||||||
|
mapEvents(item.events).map(x => x.amount).join(", ")
|
||||||
|
}}</span>
|
||||||
|
</RouterLink>
|
||||||
|
<Icon
|
||||||
|
v-if="item.code === 0"
|
||||||
|
icon="mdi-check"
|
||||||
|
class="text-yes"
|
||||||
|
/>
|
||||||
|
<Icon v-else icon="mdi-multiply" class="text-no" />
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td width="150">
|
||||||
|
<RouterLink class="text-primary mb-0" :to="`/${props.chain}/block/${item.height}`">{{
|
||||||
|
item.height
|
||||||
|
}}</RouterLink><br>
|
||||||
|
<span class="text-xs pt-0 mt-0">{{ format.toDay(item.timestamp, 'from') }}</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<PaginationBar :total="events.pagination?.total" :limit="page.limit" :callback="pagePowerEvents"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- end -->
|
||||||
<div class="toast" v-show="showCopyToast === 1">
|
<div class="toast" v-show="showCopyToast === 1">
|
||||||
<div class="alert alert-success">
|
<div class="alert alert-success">
|
||||||
<div class="text-xs md:!text-sm">
|
<div class="text-xs md:!text-sm">
|
||||||
|
@ -35,6 +35,9 @@ export class PageRequest {
|
|||||||
}
|
}
|
||||||
setPage(page: number) {
|
setPage(page: number) {
|
||||||
if(page >= 1) this.offset = (page - 1) * this.limit
|
if(page >= 1) this.offset = (page - 1) * this.limit
|
||||||
|
}
|
||||||
|
setPageSize(size: number) {
|
||||||
|
this.limit = size
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user