using type from cosmos-types
This commit is contained in:
parent
49fa44c6d6
commit
3bc6a3b660
@ -14,6 +14,7 @@
|
||||
"dependencies": {
|
||||
"@chenfengyuan/vue-countdown": "2",
|
||||
"@cosmjs/tendermint-rpc": "^0.32.2",
|
||||
"cosmjs-types": "^0.9.0",
|
||||
"@cosmjs/stargate": "^0.32.2",
|
||||
"@cosmjs/crypto": "^0.32.2",
|
||||
"@cosmjs/encoding": "^0.32.2",
|
||||
|
||||
@ -5,14 +5,16 @@ import { computed } from '@vue/reactivity';
|
||||
import { hashTx } from '@/libs';
|
||||
import { useBlockchain, useFormatter } from '@/stores';
|
||||
const props = defineProps({
|
||||
value: { type: Array<string> },
|
||||
value: { type: Array<Uint8Array> },
|
||||
});
|
||||
|
||||
const txs = computed(() => {
|
||||
return props.value?.map((x) => ({
|
||||
hash: hashTx(fromBase64(x)),
|
||||
tx: decodeTxRaw(fromBase64(x)),
|
||||
})) || []
|
||||
return (
|
||||
props.value?.map((x) => ({
|
||||
hash: hashTx(x),
|
||||
tx: decodeTxRaw(x),
|
||||
})) || []
|
||||
);
|
||||
});
|
||||
|
||||
const format = useFormatter();
|
||||
@ -23,7 +25,7 @@ const chain = useBlockchain();
|
||||
<table class="table w-full" density="compact" v-if="txs.length > 0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="position: relative; z-index: 2;">Hash</th>
|
||||
<th style="position: relative; z-index: 2">Hash</th>
|
||||
<th>Msgs</th>
|
||||
<th>Memo</th>
|
||||
</tr>
|
||||
@ -31,9 +33,11 @@ const chain = useBlockchain();
|
||||
<tbody class="text-sm">
|
||||
<tr v-for="item in txs">
|
||||
<td>
|
||||
<RouterLink :to="`/${chain.chainName}/tx/${item.hash}`" class="text-primary dark:invert">{{
|
||||
item.hash
|
||||
}}</RouterLink>
|
||||
<RouterLink
|
||||
:to="`/${chain.chainName}/tx/${item.hash}`"
|
||||
class="text-primary dark:invert"
|
||||
>{{ item.hash }}</RouterLink
|
||||
>
|
||||
</td>
|
||||
<td>
|
||||
{{
|
||||
|
||||
@ -7,6 +7,7 @@ import {
|
||||
toHex,
|
||||
} from '@cosmjs/encoding';
|
||||
import { Ripemd160, sha256 } from '@cosmjs/crypto';
|
||||
import type { Any } from 'cosmjs-types/google/protobuf/any';
|
||||
|
||||
export function decodeAddress(address: string) {
|
||||
return fromBech32(address);
|
||||
@ -33,30 +34,24 @@ export function operatorAddressToAccount(operAddress?: string) {
|
||||
return toBech32(prefix.replace('valoper', ''), data);
|
||||
}
|
||||
|
||||
export function consensusPubkeyToHexAddress(consensusPubkey?: {
|
||||
'@type': string;
|
||||
key: string;
|
||||
}) {
|
||||
export function consensusPubkeyToHexAddress(consensusPubkey?: Any) {
|
||||
if (!consensusPubkey) return '';
|
||||
let raw = '';
|
||||
if (consensusPubkey['@type'] === '/cosmos.crypto.ed25519.PubKey') {
|
||||
const pubkey = fromBase64(consensusPubkey.key);
|
||||
if (consensusPubkey.typeUrl === '/cosmos.crypto.ed25519.PubKey') {
|
||||
const pubkey = consensusPubkey.value;
|
||||
if (pubkey) return toHex(sha256(pubkey)).slice(0, 40).toUpperCase();
|
||||
}
|
||||
|
||||
if (consensusPubkey['@type'] === '/cosmos.crypto.secp256k1.PubKey') {
|
||||
const pubkey = fromBase64(consensusPubkey.key);
|
||||
if (consensusPubkey.typeUrl === '/cosmos.crypto.secp256k1.PubKey') {
|
||||
const pubkey = consensusPubkey.value;
|
||||
if (pubkey) return toHex(new Ripemd160().update(sha256(pubkey)).digest());
|
||||
}
|
||||
return raw;
|
||||
}
|
||||
|
||||
export function pubKeyToValcons(
|
||||
consensusPubkey: { '@type': string; key: string },
|
||||
prefix: string
|
||||
) {
|
||||
if (consensusPubkey && consensusPubkey.key) {
|
||||
const pubkey = fromBase64(consensusPubkey.key);
|
||||
export function pubKeyToValcons(consensusPubkey: Any, prefix: string) {
|
||||
if (consensusPubkey && consensusPubkey.value) {
|
||||
const pubkey = consensusPubkey.value;
|
||||
if (pubkey) {
|
||||
const addressData = sha256(pubkey).slice(0, 20);
|
||||
return toBech32(`${prefix}valcons`, addressData);
|
||||
|
||||
@ -462,9 +462,9 @@ export class CosmosRestClient extends BaseRestClient<RequestRegistry> {
|
||||
// this.registry.staking_validators_delegations_delegator,
|
||||
// { validator_addr, delegator_addr }
|
||||
// );
|
||||
const res = await this.queryClient.staking.delegatorValidator(
|
||||
validator_addr,
|
||||
delegator_addr
|
||||
const res = await this.queryClient.staking.delegation(
|
||||
delegator_addr,
|
||||
validator_addr
|
||||
);
|
||||
console.log(res);
|
||||
return res;
|
||||
@ -498,9 +498,9 @@ export class CosmosRestClient extends BaseRestClient<RequestRegistry> {
|
||||
return res;
|
||||
// return this.request(this.registry.base_tendermint_block_latest, {});
|
||||
}
|
||||
async getBaseBlockAt(height: string | number) {
|
||||
async getBaseBlockAt(height: string | number | undefined) {
|
||||
// return this.request(this.registry.base_tendermint_block_height, { height });
|
||||
const res = await this.tmClient.block(Number(height));
|
||||
const res = await this.tmClient.block(height ? Number(height) : undefined);
|
||||
console.log(res);
|
||||
return res;
|
||||
}
|
||||
@ -559,6 +559,8 @@ export class CosmosRestClient extends BaseRestClient<RequestRegistry> {
|
||||
}),
|
||||
order_by: page?.reverse ? 'desc' : 'asc',
|
||||
});
|
||||
console.log(res);
|
||||
return res;
|
||||
}
|
||||
// query ibc sending msgs
|
||||
// ?&pagination.reverse=true&events=send_packet.packet_src_channel='${channel}'&events=send_packet.packet_src_port='${port}'
|
||||
|
||||
@ -8,12 +8,13 @@ import { onBeforeRouteUpdate } from 'vue-router';
|
||||
import { useBaseStore, useFormatter } from '@/stores';
|
||||
import type { Block } from '@/types';
|
||||
import Countdown from '@/components/Countdown.vue';
|
||||
import type { BlockResponse } from '@cosmjs/tendermint-rpc';
|
||||
|
||||
const props = defineProps(['height', 'chain']);
|
||||
|
||||
const store = useBaseStore();
|
||||
const format = useFormatter()
|
||||
const current = ref({} as Block)
|
||||
const current = ref({} as BlockResponse)
|
||||
const target = ref(Number(props.height || 0))
|
||||
|
||||
const height = computed(() => {
|
||||
@ -24,7 +25,7 @@ const isFutureBlock = computed({
|
||||
get: () => {
|
||||
const latest = store.latest?.block?.header.height
|
||||
const isFuture = latest ? target.value > Number(latest) : true
|
||||
if (!isFuture && !current.value.block_id) store.fetchBlock(target.value).then(x => current.value = x)
|
||||
if (!isFuture && !current.value.blockId) store.fetchBlock(target.value).then(x => current.value = x)
|
||||
return isFuture
|
||||
},
|
||||
set: val => {
|
||||
@ -120,7 +121,7 @@ onBeforeRouteUpdate(async (to, from, next) => {
|
||||
</div>
|
||||
</h2>
|
||||
<div>
|
||||
<DynamicComponent :value="current.block_id" />
|
||||
<DynamicComponent :value="current.blockId" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -131,12 +132,12 @@ onBeforeRouteUpdate(async (to, from, next) => {
|
||||
|
||||
<div class="bg-base-100 px-4 pt-3 pb-4 rounded mb-4 shadow">
|
||||
<h2 class="card-title flex flex-row justify-between">{{ $t('account.transactions') }}</h2>
|
||||
<TxsElement :value="current.block?.data?.txs" />
|
||||
<TxsElement :value="current.block?.txs" />
|
||||
</div>
|
||||
|
||||
<div class="bg-base-100 px-4 pt-3 pb-4 rounded shadow">
|
||||
<h2 class="card-title flex flex-row justify-between">{{ $t('block.last_commit') }}</h2>
|
||||
<DynamicComponent :value="current.block?.last_commit" />
|
||||
<DynamicComponent :value="current.block?.lastCommit" />
|
||||
</div>
|
||||
</div>
|
||||
</div></template>
|
||||
|
||||
@ -10,6 +10,7 @@ import { useDistributionStore } from '@/stores/useDistributionStore';
|
||||
import { useMintStore } from '@/stores/useMintStore';
|
||||
import { useStakingStore } from '@/stores/useStakingStore';
|
||||
import type { Coin, Tally } from '@/types';
|
||||
import type { Pool } from 'cosmjs-types/cosmos/staking/v1beta1/staking';
|
||||
import numeral from 'numeral';
|
||||
import { defineStore } from 'pinia';
|
||||
|
||||
@ -148,8 +149,6 @@ export const useIndexModule = defineStore('module-index', {
|
||||
const mintStore = useMintStore();
|
||||
const formatter = useFormatter();
|
||||
|
||||
console.log('base', JSON.stringify(base, null, 2));
|
||||
|
||||
return [
|
||||
{
|
||||
title: 'Height',
|
||||
@ -163,7 +162,7 @@ export const useIndexModule = defineStore('module-index', {
|
||||
color: 'error',
|
||||
icon: 'mdi-human-queue',
|
||||
stats: String(
|
||||
base?.latest?.block?.last_commit?.signatures.length || 0
|
||||
base?.latest?.block?.lastCommit?.signatures.length || 0
|
||||
),
|
||||
change: 0,
|
||||
},
|
||||
@ -179,9 +178,8 @@ export const useIndexModule = defineStore('module-index', {
|
||||
color: 'warning',
|
||||
icon: 'mdi-lock',
|
||||
stats: formatter.formatTokenAmount({
|
||||
// @ts-ignore
|
||||
amount: this.pool.bonded_tokens,
|
||||
denom: staking.params.bond_denom,
|
||||
amount: this.pool.bondedTokens,
|
||||
denom: staking.params.bondDenom,
|
||||
}),
|
||||
change: 0,
|
||||
},
|
||||
@ -199,7 +197,7 @@ export const useIndexModule = defineStore('module-index', {
|
||||
stats: formatter.formatTokens(
|
||||
// @ts-ignore
|
||||
this.communityPool?.filter(
|
||||
(x: Coin) => x.denom === staking.params.bond_denom
|
||||
(x: Coin) => x.denom === staking.params.bondDenom
|
||||
)
|
||||
),
|
||||
change: 0,
|
||||
|
||||
@ -15,10 +15,19 @@ import {
|
||||
pubKeyToValcons,
|
||||
valoperToPrefix,
|
||||
} 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 { fromBase64, toBase64 } from '@cosmjs/encoding';
|
||||
import { stringToUint8Array, uint8ArrayToString } from '@/libs/utils';
|
||||
import type { TxSearchResponse } from '@cosmjs/tendermint-rpc';
|
||||
import type { DelegationResponse } from 'cosmjs-types/cosmos/staking/v1beta1/staking';
|
||||
|
||||
const props = defineProps(['validator', 'chain']);
|
||||
|
||||
@ -36,7 +45,7 @@ const avatars = ref(cache || {});
|
||||
const identity = ref('');
|
||||
const rewards = ref([] as Coin[] | undefined);
|
||||
const commission = ref([] as Coin[] | undefined);
|
||||
const delegations = ref({} as PaginatedDelegations)
|
||||
const delegations = ref({} as PaginatedDelegations);
|
||||
const addresses = ref(
|
||||
{} as {
|
||||
account: string;
|
||||
@ -45,7 +54,7 @@ const addresses = ref(
|
||||
valCons: string;
|
||||
}
|
||||
);
|
||||
const selfBonded = ref({} as Delegation);
|
||||
const selfBonded = ref({} as DelegationResponse);
|
||||
|
||||
addresses.value.account = operatorAddressToAccount(validator);
|
||||
// load self bond
|
||||
@ -53,11 +62,11 @@ staking
|
||||
.fetchValidatorDelegation(validator, addresses.value.account)
|
||||
.then((x) => {
|
||||
if (x) {
|
||||
selfBonded.value = x.delegation_response;
|
||||
selfBonded.value = x.delegationResponse!;
|
||||
}
|
||||
});
|
||||
|
||||
const txs = ref({} as PaginatedTxs);
|
||||
const txs = ref({} as TxSearchResponse);
|
||||
|
||||
blockchain.rpc.getTxsBySender(addresses.value.account).then((x) => {
|
||||
txs.value = x;
|
||||
@ -125,7 +134,8 @@ onMounted(() => {
|
||||
staking.fetchValidator(validator).then((res) => {
|
||||
v.value = res.validator;
|
||||
identity.value = res.validator?.description?.identity || '';
|
||||
if (identity.value && !avatars.value[identity.value]) loadAvatar(identity.value);
|
||||
if (identity.value && !avatars.value[identity.value])
|
||||
loadAvatar(identity.value);
|
||||
|
||||
const prefix = valoperToPrefix(v.value.operator_address) || '<Invalid>';
|
||||
addresses.value.hex = consensusPubkeyToHexAddress(
|
||||
@ -162,7 +172,6 @@ onMounted(() => {
|
||||
// Disable delegations due to its bad performance
|
||||
// Comment out the following code if you want to enable it
|
||||
// pageload(1)
|
||||
|
||||
}
|
||||
});
|
||||
let showCopyToast = ref(0);
|
||||
@ -193,62 +202,82 @@ function pageload(p: number) {
|
||||
page.setPage(p);
|
||||
page.limit = 10;
|
||||
|
||||
blockchain.rpc.getStakingValidatorsDelegations(validator, page).then(res => {
|
||||
delegations.value = res
|
||||
})
|
||||
blockchain.rpc
|
||||
.getStakingValidatorsDelegations(validator, page)
|
||||
.then((res) => {
|
||||
delegations.value = res;
|
||||
});
|
||||
}
|
||||
|
||||
const events = ref({} as PaginatedTxs)
|
||||
const events = ref({} as PaginatedTxs);
|
||||
|
||||
enum EventType {
|
||||
Delegate = 'delegate',
|
||||
Unbond = 'unbond',
|
||||
}
|
||||
|
||||
const selectedEventType = ref(EventType.Delegate)
|
||||
const selectedEventType = ref(EventType.Delegate);
|
||||
|
||||
function loadPowerEvents(p: number, type: EventType) {
|
||||
selectedEventType.value = type
|
||||
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
|
||||
})
|
||||
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)
|
||||
loadPowerEvents(page, selectedEventType.value);
|
||||
}
|
||||
|
||||
pagePowerEvents(1)
|
||||
pagePowerEvents(1);
|
||||
|
||||
function mapEvents(events: {type: string, attributes: {key: string, value: string}[]}[]) {
|
||||
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 === validator || attr.value === toBase64(stringToUint8Array(validator))) > -1)
|
||||
.map(x => {
|
||||
// check if attributes need to decode
|
||||
const output = {} as {[key: string]: string }
|
||||
.filter((x) => x.type === selectedEventType.value)
|
||||
.filter(
|
||||
(x) =>
|
||||
x.attributes.findIndex(
|
||||
(attr) =>
|
||||
attr.value === validator ||
|
||||
attr.value === toBase64(stringToUint8Array(validator))
|
||||
) > -1
|
||||
)
|
||||
.map((x) => {
|
||||
// check if attributes need to decode
|
||||
const output = {} as { [key: string]: string };
|
||||
|
||||
if(x.attributes.findIndex(a => a.key === `amount`) > -1) {
|
||||
x.attributes.forEach(attr => {
|
||||
output[attr.key] = attr.value
|
||||
})
|
||||
} else x.attributes.forEach(attr => {
|
||||
output[uint8ArrayToString(fromBase64(attr.key))] = uint8ArrayToString(fromBase64(attr.value))
|
||||
})
|
||||
return output
|
||||
})
|
||||
|
||||
return attributes
|
||||
if (x.attributes.findIndex((a) => a.key === `amount`) > -1) {
|
||||
x.attributes.forEach((attr) => {
|
||||
output[attr.key] = attr.value;
|
||||
});
|
||||
} else
|
||||
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)))
|
||||
if (!messages) return [];
|
||||
return Array.from(
|
||||
new Set(messages.map((x) => x.delegator_address || x.grantee))
|
||||
);
|
||||
}
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<div>
|
||||
@ -298,7 +327,9 @@ function mapDelegators(messages: any[]) {
|
||||
<div class="card-list">
|
||||
<div class="flex items-center mb-2">
|
||||
<Icon icon="mdi-web" class="text-xl mr-1" />
|
||||
<span class="font-bold mr-2">{{ $t('staking.website') }}: </span>
|
||||
<span class="font-bold mr-2"
|
||||
>{{ $t('staking.website') }}:
|
||||
</span>
|
||||
<a
|
||||
:href="v?.description?.website || '#'"
|
||||
:class="
|
||||
@ -312,17 +343,21 @@ function mapDelegators(messages: any[]) {
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<Icon icon="mdi-email-outline" class="text-xl mr-1" />
|
||||
<span class="font-bold mr-2">{{ $t('staking.contact') }}: </span>
|
||||
<span class="font-bold mr-2"
|
||||
>{{ $t('staking.contact') }}:
|
||||
</span>
|
||||
<a
|
||||
v-if="v.description?.security_contact"
|
||||
:href="'mailto:' + v.description.security_contact || '#' "
|
||||
:href="'mailto:' + v.description.security_contact || '#'"
|
||||
class="cursor-pointer"
|
||||
>
|
||||
{{ v.description?.security_contact || '-' }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-sm mt-4 mb-3 font-medium">{{ $t('staking.validator_status') }}</p>
|
||||
<p class="text-sm mt-4 mb-3 font-medium">
|
||||
{{ $t('staking.validator_status') }}
|
||||
</p>
|
||||
<div class="card-list">
|
||||
<div class="flex items-center mb-2">
|
||||
<Icon icon="mdi-shield-account-outline" class="text-xl mr-1" />
|
||||
@ -337,18 +372,42 @@ function mapDelegators(messages: any[]) {
|
||||
<span> {{ v.jailed || '-' }} </span>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-sm mt-4 mb-3 font-medium">{{ $t('staking.liquid_staking') }}</p>
|
||||
<p class="text-sm mt-4 mb-3 font-medium">
|
||||
{{ $t('staking.liquid_staking') }}
|
||||
</p>
|
||||
<div class="card-list">
|
||||
<div class="flex items-center mb-2">
|
||||
<Icon icon="mdi-lock" class="text-xl mr-1" />
|
||||
<span class="font-bold mr-2">{{ $t('staking.validator_bond_share') }}: </span>
|
||||
<span> {{ format.formatToken( {amount: v.validator_bond_shares, denom: staking.params.bond_denom }, false) }} </span>
|
||||
<span class="font-bold mr-2"
|
||||
>{{ $t('staking.validator_bond_share') }}:
|
||||
</span>
|
||||
<span>
|
||||
{{
|
||||
format.formatToken(
|
||||
{
|
||||
amount: v.validator_bond_shares,
|
||||
denom: staking.params.bondDenom,
|
||||
},
|
||||
false
|
||||
)
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<Icon icon="mdi-waves-arrow-right" class="text-xl mr-1" />
|
||||
<span class="font-bold mr-2">{{ $t('staking.liquid_staking_shares') }}: </span>
|
||||
<span class="font-bold mr-2"
|
||||
>{{ $t('staking.liquid_staking_shares') }}:
|
||||
</span>
|
||||
<span>
|
||||
{{ format.formatToken( {amount: v.liquid_shares, denom: staking.params.bond_denom }, false) }}
|
||||
{{
|
||||
format.formatToken(
|
||||
{
|
||||
amount: v.liquid_shares,
|
||||
denom: staking.params.bondDenom,
|
||||
},
|
||||
false
|
||||
)
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@ -368,7 +427,7 @@ function mapDelegators(messages: any[]) {
|
||||
{{
|
||||
format.formatToken2({
|
||||
amount: v.tokens,
|
||||
denom: staking.params.bond_denom,
|
||||
denom: staking.params.bondDenom,
|
||||
})
|
||||
}}
|
||||
</h4>
|
||||
@ -400,7 +459,7 @@ function mapDelegators(messages: any[]) {
|
||||
|
||||
<div class="ml-3 flex flex-col">
|
||||
<h4>
|
||||
{{ v.min_self_delegation }} {{ staking.params.bond_denom }}
|
||||
{{ v.min_self_delegation }} {{ staking.params.bondDenom }}
|
||||
</h4>
|
||||
<span class="text-sm">{{ $t('staking.min_self') }}</span>
|
||||
</div>
|
||||
@ -423,11 +482,16 @@ function mapDelegators(messages: any[]) {
|
||||
class="flex items-center justify-center rounded w-10 h-10"
|
||||
style="border: 1px solid #666"
|
||||
>
|
||||
<Icon icon="mdi:arrow-down-bold-circle-outline" class="text-3xl" />
|
||||
<Icon
|
||||
icon="mdi:arrow-down-bold-circle-outline"
|
||||
class="text-3xl"
|
||||
/>
|
||||
</div>
|
||||
<div class="ml-3 flex flex-col justify-center">
|
||||
<h4>{{ v.unbonding_height }}</h4>
|
||||
<span class="text-sm">{{ $t('staking.unbonding_height') }}</span>
|
||||
<span class="text-sm">{{
|
||||
$t('staking.unbonding_height')
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -439,7 +503,13 @@ function mapDelegators(messages: any[]) {
|
||||
<Icon icon="mdi-clock" class="text-3xl" />
|
||||
</div>
|
||||
<div class="ml-3 flex flex-col justify-center">
|
||||
<h4 v-if="v.unbonding_time && !v.unbonding_time.startsWith('1970')">{{ format.toDay(v.unbonding_time, 'from') }}</h4>
|
||||
<h4
|
||||
v-if="
|
||||
v.unbonding_time && !v.unbonding_time.startsWith('1970')
|
||||
"
|
||||
>
|
||||
{{ format.toDay(v.unbonding_time, 'from') }}
|
||||
</h4>
|
||||
<h4 v-else>-</h4>
|
||||
<span class="text-sm">{{ $t('staking.unbonding_time') }}</span>
|
||||
</div>
|
||||
@ -474,7 +544,9 @@ function mapDelegators(messages: any[]) {
|
||||
>
|
||||
{{ format.formatToken2(i) }}
|
||||
</div>
|
||||
<div class="text-sm mb-2 mt-2">{{ $t('staking.outstanding') }} {{ $t('account.rewards') }}</div>
|
||||
<div class="text-sm mb-2 mt-2">
|
||||
{{ $t('staking.outstanding') }} {{ $t('account.rewards') }}
|
||||
</div>
|
||||
<div
|
||||
v-for="(i, k) in rewards"
|
||||
:key="`reward-${k}`"
|
||||
@ -503,14 +575,15 @@ function mapDelegators(messages: any[]) {
|
||||
</div>
|
||||
<div class="px-4 pb-4">
|
||||
<div class="mb-3">
|
||||
<div class="text-sm flex">{{ $t('staking.account_addr') }}
|
||||
<div class="text-sm flex">
|
||||
{{ $t('staking.account_addr') }}
|
||||
<Icon
|
||||
icon="mdi:content-copy"
|
||||
class="ml-2 cursor-pointer"
|
||||
v-show="addresses.account"
|
||||
@click="copyWebsite(addresses.account || '')"
|
||||
/>
|
||||
</div>
|
||||
icon="mdi:content-copy"
|
||||
class="ml-2 cursor-pointer"
|
||||
v-show="addresses.account"
|
||||
@click="copyWebsite(addresses.account || '')"
|
||||
/>
|
||||
</div>
|
||||
<RouterLink
|
||||
class="text-xs text-primary"
|
||||
:to="`/${chain}/account/${addresses.account}`"
|
||||
@ -519,57 +592,69 @@ function mapDelegators(messages: any[]) {
|
||||
</RouterLink>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<div class="text-sm flex">{{ $t('staking.operator_addr') }}
|
||||
<div class="text-sm flex">
|
||||
{{ $t('staking.operator_addr') }}
|
||||
<Icon
|
||||
icon="mdi:content-copy"
|
||||
class="ml-2 cursor-pointer"
|
||||
v-show="v.operator_address"
|
||||
@click="copyWebsite(v.operator_address || '')"
|
||||
/></div>
|
||||
icon="mdi:content-copy"
|
||||
class="ml-2 cursor-pointer"
|
||||
v-show="v.operator_address"
|
||||
@click="copyWebsite(v.operator_address || '')"
|
||||
/>
|
||||
</div>
|
||||
<div class="text-xs">
|
||||
{{ v.operator_address }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<div class="text-sm flex">{{ $t('staking.hex_addr') }}
|
||||
<div class="text-sm flex">
|
||||
{{ $t('staking.hex_addr') }}
|
||||
<Icon
|
||||
icon="mdi:content-copy"
|
||||
class="ml-2 cursor-pointer"
|
||||
v-show="addresses.hex"
|
||||
@click="copyWebsite(addresses.hex || '')"
|
||||
/>
|
||||
</div>
|
||||
icon="mdi:content-copy"
|
||||
class="ml-2 cursor-pointer"
|
||||
v-show="addresses.hex"
|
||||
@click="copyWebsite(addresses.hex || '')"
|
||||
/>
|
||||
</div>
|
||||
<div class="text-xs">{{ addresses.hex }}</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<div class="text-sm flex">{{ $t('staking.signer_addr') }}
|
||||
<div class="text-sm flex">
|
||||
{{ $t('staking.signer_addr') }}
|
||||
<Icon
|
||||
icon="mdi:content-copy"
|
||||
class="ml-2 cursor-pointer"
|
||||
v-show="addresses.valCons"
|
||||
@click="copyWebsite(addresses.valCons || '')"
|
||||
/>
|
||||
</div>
|
||||
icon="mdi:content-copy"
|
||||
class="ml-2 cursor-pointer"
|
||||
v-show="addresses.valCons"
|
||||
@click="copyWebsite(addresses.valCons || '')"
|
||||
/>
|
||||
</div>
|
||||
<div class="text-xs">{{ addresses.valCons }}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-sm flex">{{ $t('staking.consensus_pub_key') }}
|
||||
<div class="text-sm flex">
|
||||
{{ $t('staking.consensus_pub_key') }}
|
||||
<Icon
|
||||
icon="mdi:content-copy"
|
||||
class="ml-2 cursor-pointer"
|
||||
v-show="v.consensus_pubkey"
|
||||
@click="copyWebsite(JSON.stringify(v.consensus_pubkey) || '')"
|
||||
/>
|
||||
</div>
|
||||
icon="mdi:content-copy"
|
||||
class="ml-2 cursor-pointer"
|
||||
v-show="v.consensus_pubkey"
|
||||
@click="copyWebsite(JSON.stringify(v.consensus_pubkey) || '')"
|
||||
/>
|
||||
</div>
|
||||
<div class="text-xs">{{ v.consensus_pubkey }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="delegations.delegation_responses" class="mt-5 bg-base-100 shadow rounded p-4 ">
|
||||
<div class="text-lg mb-4 font-semibold">{{ $t('account.delegations') }}
|
||||
<span class="float-right"> {{ delegations.delegation_responses?.length || 0 }} / {{ delegations.pagination?.total || 0 }} </span>
|
||||
<div
|
||||
v-if="delegations.delegation_responses"
|
||||
class="mt-5 bg-base-100 shadow rounded p-4"
|
||||
>
|
||||
<div class="text-lg mb-4 font-semibold">
|
||||
{{ $t('account.delegations') }}
|
||||
<span class="float-right">
|
||||
{{ delegations.delegation_responses?.length || 0 }} /
|
||||
{{ delegations.pagination?.total || 0 }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="rounded overflow-auto">
|
||||
<table class="table validatore-table w-full">
|
||||
@ -580,23 +665,33 @@ function mapDelegators(messages: any[]) {
|
||||
<th class="text-left pl-4">{{ $t('account.delegation') }}</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="{balance, delegation} in delegations.delegation_responses">
|
||||
<tr
|
||||
v-for="{
|
||||
balance,
|
||||
delegation,
|
||||
} in delegations.delegation_responses"
|
||||
>
|
||||
<td class="text-sm text-primary">
|
||||
{{ delegation.delegator_address }}
|
||||
</td>
|
||||
<td class="truncate text-primary">
|
||||
{{ format.formatToken(balance)}}
|
||||
{{ format.formatToken(balance) }}
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<PaginationBar :total="delegations.pagination?.total" :limit="page.limit" :callback="pageload"/>
|
||||
<PaginationBar
|
||||
:total="delegations.pagination?.total"
|
||||
:limit="page.limit"
|
||||
:callback="pageload"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-5 bg-base-100 shadow rounded p-4">
|
||||
<div class="text-lg mb-4 font-semibold">{{ $t('account.transactions') }}</div>
|
||||
<div class="text-lg mb-4 font-semibold">
|
||||
{{ $t('account.transactions') }}
|
||||
</div>
|
||||
<div class="rounded overflow-auto">
|
||||
<table class="table validatore-table w-full">
|
||||
<thead>
|
||||
@ -604,7 +699,9 @@ function mapDelegators(messages: any[]) {
|
||||
{{ $t('account.height') }}
|
||||
</th>
|
||||
<th class="text-left pl-4">{{ $t('account.hash') }}</th>
|
||||
<th class="text-left pl-4" width="40%">{{ $t('account.messages') }}</th>
|
||||
<th class="text-left pl-4" width="40%">
|
||||
{{ $t('account.messages') }}
|
||||
</th>
|
||||
<th class="text-left pl-4">{{ $t('account.time') }}</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -642,46 +739,57 @@ function mapDelegators(messages: any[]) {
|
||||
<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">Voting 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>
|
||||
<span class="mr-10">Voting 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>
|
||||
<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 truncate text-primary" style="max-width: 250px">
|
||||
<RouterLink v-for="d in mapDelegators(item.tx?.body?.messages)" :to="`/${props.chain}/account/${d}`">
|
||||
<RouterLink
|
||||
v-for="d in mapDelegators(item.tx?.body?.messages)"
|
||||
:to="`/${props.chain}/account/${d}`"
|
||||
>
|
||||
{{ d }}
|
||||
</RouterLink>
|
||||
</RouterLink>
|
||||
</td>
|
||||
<td>
|
||||
<div class="flex items-center" :class="{
|
||||
'text-yes' : selectedEventType === EventType.Delegate,
|
||||
'text-no' : selectedEventType === EventType.Unbond,
|
||||
}">
|
||||
<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: any) => x.amount).join(", ")
|
||||
}}</span>
|
||||
{{ selectedEventType === EventType.Delegate ? '+' : '-' }}
|
||||
{{
|
||||
mapEvents(item.events)
|
||||
.map((x: any) => x.amount)
|
||||
.join(', ')
|
||||
}}</span
|
||||
>
|
||||
</RouterLink>
|
||||
<Icon
|
||||
v-if="item.code === 0"
|
||||
@ -692,15 +800,23 @@ function mapDelegators(messages: any[]) {
|
||||
</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>
|
||||
<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"/>
|
||||
<PaginationBar
|
||||
:total="events.pagination?.total"
|
||||
:limit="page.limit"
|
||||
:callback="pagePowerEvents"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<!-- end -->
|
||||
|
||||
@ -6,120 +6,127 @@ import type { Block } from '@/types';
|
||||
import { hashTx } from '@/libs';
|
||||
import { fromBase64 } from '@cosmjs/encoding';
|
||||
import { useRouter } from 'vue-router';
|
||||
import type { BlockResponse } from '@cosmjs/tendermint-rpc';
|
||||
|
||||
export const useBaseStore = defineStore('baseStore', {
|
||||
state: () => {
|
||||
return {
|
||||
earlest: {} as Block,
|
||||
latest: {} as Block,
|
||||
recents: [] as Block[],
|
||||
theme: (window.localStorage.getItem('theme') || 'dark') as
|
||||
| 'light'
|
||||
| 'dark',
|
||||
connected: true,
|
||||
};
|
||||
state: () => {
|
||||
return {
|
||||
earlest: {} as BlockResponse,
|
||||
latest: {} as BlockResponse,
|
||||
recents: [] as BlockResponse[],
|
||||
theme: (window.localStorage.getItem('theme') || 'dark') as
|
||||
| 'light'
|
||||
| 'dark',
|
||||
connected: true,
|
||||
};
|
||||
},
|
||||
getters: {
|
||||
blocktime(): number {
|
||||
if (this.earlest && this.latest) {
|
||||
if (
|
||||
this.latest.block?.header?.height !==
|
||||
this.earlest.block?.header?.height
|
||||
) {
|
||||
const diff = dayjs(this.latest.block?.header?.time.toString()).diff(
|
||||
this.earlest.block?.header?.time.toString()
|
||||
);
|
||||
console.log(
|
||||
JSON.stringify(this.earlest),
|
||||
JSON.stringify(this.latest)
|
||||
);
|
||||
const blocks =
|
||||
Number(this.latest.block.header.height) -
|
||||
Number(this.earlest.block.header.height);
|
||||
return diff / blocks;
|
||||
}
|
||||
}
|
||||
return 6000;
|
||||
},
|
||||
getters: {
|
||||
blocktime(): number {
|
||||
if (this.earlest && this.latest) {
|
||||
if (
|
||||
this.latest.block?.header?.height !==
|
||||
this.earlest.block?.header?.height
|
||||
) {
|
||||
const diff = dayjs(this.latest.block?.header?.time).diff(
|
||||
this.earlest.block?.header?.time
|
||||
);
|
||||
const blocks = Number(this.latest.block.header.height) - Number(this.earlest.block.header.height)
|
||||
return diff / (blocks);
|
||||
}
|
||||
}
|
||||
return 6000;
|
||||
},
|
||||
blockchain() {
|
||||
return useBlockchain();
|
||||
},
|
||||
currentChainId(): string {
|
||||
return this.latest.block?.header.chain_id || '';
|
||||
},
|
||||
txsInRecents() {
|
||||
const txs = [] as {
|
||||
height: string;
|
||||
hash: string;
|
||||
tx: DecodedTxRaw;
|
||||
}[];
|
||||
this.recents.forEach((b) =>
|
||||
b.block?.data?.txs.forEach((tx: string) => {
|
||||
if (tx) {
|
||||
const raw = fromBase64(tx);
|
||||
try {
|
||||
txs.push({
|
||||
height: b.block.header.height,
|
||||
hash: hashTx(raw),
|
||||
tx: decodeTxRaw(raw),
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
return txs.sort((a, b) => {return Number(b.height) - Number(a.height)});
|
||||
},
|
||||
blockchain() {
|
||||
return useBlockchain();
|
||||
},
|
||||
actions: {
|
||||
async initial() {
|
||||
this.fetchLatest()
|
||||
},
|
||||
async clearRecentBlocks() {
|
||||
this.recents = [];
|
||||
},
|
||||
async fetchLatest() {
|
||||
try{
|
||||
this.latest = await this.blockchain.rpc?.getBaseBlockLatest();
|
||||
this.connected = true
|
||||
}catch(e) {
|
||||
this.connected = false
|
||||
currentChainId(): string {
|
||||
return this.latest.block?.header.chainId || '';
|
||||
},
|
||||
txsInRecents() {
|
||||
const txs = [] as {
|
||||
height: number;
|
||||
hash: string;
|
||||
tx: DecodedTxRaw;
|
||||
}[];
|
||||
this.recents.forEach((b) =>
|
||||
b.block?.txs.forEach((raw) => {
|
||||
if (raw) {
|
||||
try {
|
||||
txs.push({
|
||||
height: b.block.header.height,
|
||||
hash: hashTx(raw),
|
||||
tx: decodeTxRaw(raw),
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
if (
|
||||
!this.earlest ||
|
||||
this.earlest?.block?.header?.chain_id !=
|
||||
this.latest?.block?.header?.chain_id
|
||||
) {
|
||||
//reset earlest and recents
|
||||
this.earlest = this.latest;
|
||||
this.recents = [];
|
||||
}
|
||||
//check if the block exists in recents
|
||||
if (
|
||||
this.recents.findIndex(
|
||||
(x) => x?.block_id?.hash === this.latest?.block_id?.hash
|
||||
) === -1
|
||||
) {
|
||||
if (this.recents.length >= 50) {
|
||||
this.recents.shift();
|
||||
}
|
||||
this.recents.push(this.latest);
|
||||
}
|
||||
return this.latest;
|
||||
},
|
||||
}
|
||||
})
|
||||
);
|
||||
return txs.sort((a, b) => {
|
||||
return Number(b.height) - Number(a.height);
|
||||
});
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
async initial() {
|
||||
this.fetchLatest();
|
||||
},
|
||||
async clearRecentBlocks() {
|
||||
this.recents = [];
|
||||
},
|
||||
async fetchLatest() {
|
||||
try {
|
||||
this.latest = await this.blockchain.rpc?.getBaseBlockLatest();
|
||||
this.connected = true;
|
||||
} catch (e) {
|
||||
this.connected = false;
|
||||
}
|
||||
if (
|
||||
!this.earlest ||
|
||||
this.earlest?.block?.header?.chainId !=
|
||||
this.latest?.block?.header?.chainId
|
||||
) {
|
||||
//reset earlest and recents
|
||||
this.earlest = this.latest;
|
||||
this.recents = [];
|
||||
}
|
||||
//check if the block exists in recents
|
||||
if (
|
||||
this.recents.findIndex(
|
||||
(x) =>
|
||||
Buffer.from(x?.blockId?.hash).toString('base64') ===
|
||||
Buffer.from(this.latest?.blockId?.hash).toString('base64')
|
||||
) === -1
|
||||
) {
|
||||
if (this.recents.length >= 50) {
|
||||
this.recents.shift();
|
||||
}
|
||||
this.recents.push(this.latest);
|
||||
}
|
||||
return this.latest;
|
||||
},
|
||||
|
||||
async fetchValidatorByHeight(height?: number, offset = 0) {
|
||||
return this.blockchain.rpc.getBaseValidatorsetAt(
|
||||
String(height),
|
||||
offset
|
||||
);
|
||||
},
|
||||
async fetchLatestValidators(offset = 0) {
|
||||
return this.blockchain.rpc.getBaseValidatorsetLatest(offset);
|
||||
},
|
||||
async fetchBlock(height?: number | string) {
|
||||
return this.blockchain.rpc.getBaseBlockAt(String(height));
|
||||
},
|
||||
async fetchAbciInfo() {
|
||||
return this.blockchain.rpc.getBaseNodeInfo();
|
||||
},
|
||||
// async fetchNodeInfo() {
|
||||
// return this.blockchain.rpc.no()
|
||||
// }
|
||||
async fetchValidatorByHeight(height?: number, offset = 0) {
|
||||
return this.blockchain.rpc.getBaseValidatorsetAt(String(height), offset);
|
||||
},
|
||||
async fetchLatestValidators(offset = 0) {
|
||||
return this.blockchain.rpc.getBaseValidatorsetLatest(offset);
|
||||
},
|
||||
async fetchBlock(height?: number | string) {
|
||||
return this.blockchain.rpc.getBaseBlockAt(height);
|
||||
},
|
||||
async fetchAbciInfo() {
|
||||
return this.blockchain.rpc.getBaseNodeInfo();
|
||||
},
|
||||
// async fetchNodeInfo() {
|
||||
// return this.blockchain.rpc.no()
|
||||
// }
|
||||
},
|
||||
});
|
||||
|
||||
@ -2,7 +2,7 @@ import { defineStore } from 'pinia';
|
||||
import { useBlockchain } from './useBlockchain';
|
||||
|
||||
import { get } from '@/libs/http';
|
||||
import type { StakingParam, StakingPool, Validator } from '@/types';
|
||||
import type { StakingParam, StakingPool } from '@/types';
|
||||
import { CosmosRestClient } from '@/libs/client';
|
||||
import {
|
||||
consensusPubkeyToHexAddress,
|
||||
@ -18,31 +18,27 @@ import {
|
||||
} from '@cosmjs/encoding';
|
||||
import { useBaseStore } from './useBaseStore';
|
||||
import type { BondStatusString } from '@cosmjs/stargate/build/modules/staking/queries';
|
||||
import type { Duration } from 'cosmjs-types/google/protobuf/duration';
|
||||
import type {
|
||||
Pool,
|
||||
Validator,
|
||||
Params,
|
||||
} from 'cosmjs-types/cosmos/staking/v1beta1/staking';
|
||||
import type { Any } from 'cosmjs-types/google/protobuf/any';
|
||||
|
||||
export const useStakingStore = defineStore('stakingStore', {
|
||||
state: () => {
|
||||
return {
|
||||
validators: [] as Validator[],
|
||||
params: {} as {
|
||||
unbonding_time: string;
|
||||
max_validators: number;
|
||||
max_entries: number;
|
||||
historical_entries: number;
|
||||
bond_denom: string;
|
||||
min_commission_rate: string;
|
||||
min_self_delegation: string;
|
||||
},
|
||||
pool: {} as {
|
||||
bonded_tokens: string;
|
||||
not_bonded_tokens: string;
|
||||
},
|
||||
params: {} as Params,
|
||||
pool: {} as Pool,
|
||||
keyRotation: {} as Record<string, string>,
|
||||
};
|
||||
},
|
||||
getters: {
|
||||
totalPower(): number {
|
||||
const sum = (s: number, e: Validator) => {
|
||||
return s + parseInt(e.delegator_shares);
|
||||
return s + parseInt(e.delegatorShares);
|
||||
};
|
||||
return this.validators ? this.validators.reduce(sum, 0) : 0;
|
||||
},
|
||||
@ -104,12 +100,14 @@ export const useStakingStore = defineStore('stakingStore', {
|
||||
this.blockchain.current.providerChain.api.length > 0
|
||||
) {
|
||||
const signatures =
|
||||
useBaseStore().latest?.block?.last_commit.signatures;
|
||||
useBaseStore().latest?.block?.lastCommit?.signatures;
|
||||
if (signatures) {
|
||||
// console.log(signatures)
|
||||
const key = toBase64(fromHex(valconsToBase64(validatorAddr)));
|
||||
const exists = signatures.findIndex(
|
||||
(x) => x.validator_address === key
|
||||
(x) =>
|
||||
x.validatorAddress &&
|
||||
Buffer.from(x.validatorAddress).toString('base64') === key
|
||||
);
|
||||
if (exists < 0) {
|
||||
const client = CosmosRestClient.newDefault(
|
||||
@ -139,7 +137,7 @@ export const useStakingStore = defineStore('stakingStore', {
|
||||
this.keyRotation = keyRotation ? JSON.parse(keyRotation) : {};
|
||||
},
|
||||
|
||||
findRotatedHexAddress(key: { '@type': string; key: string }) {
|
||||
findRotatedHexAddress(key: Any) {
|
||||
const prefix = 'cosmos';
|
||||
const conskey = pubKeyToValcons(key, prefix);
|
||||
const rotated = this.keyRotation[conskey];
|
||||
@ -150,10 +148,10 @@ export const useStakingStore = defineStore('stakingStore', {
|
||||
},
|
||||
async fetchAllKeyRotation(chain_id: string) {
|
||||
for (const val of this.validators) {
|
||||
const { prefix } = fromBech32(val.operator_address);
|
||||
const { prefix } = fromBech32(val.operatorAddress);
|
||||
await this.fetchKeyRotation(
|
||||
chain_id,
|
||||
pubKeyToValcons(val.consensus_pubkey, prefix.replace('valoper', ''))
|
||||
pubKeyToValcons(val.consensusPubkey!, prefix.replace('valoper', ''))
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
Loading…
Reference in New Issue
Block a user