forked from LaconicNetwork/cosmos-explorer
finish tx detail
This commit is contained in:
@@ -16,7 +16,7 @@ const height = computed(() => {
|
||||
|
||||
onBeforeRouteUpdate(async (to, from, next) => {
|
||||
if (from.path !== to.path) {
|
||||
store.fetchBlock(Number(to.params.height))
|
||||
store.fetchBlock(String(to.params.height))
|
||||
next()
|
||||
}
|
||||
})
|
||||
@@ -33,7 +33,7 @@ onBeforeRouteUpdate(async (to, from, next) => {
|
||||
</span>
|
||||
</VCardTitle>
|
||||
<VCardItem class="pt-0">
|
||||
<DynamicComponent :value="store.current.blockId"/>
|
||||
<DynamicComponent :value="store.current.block_id"/>
|
||||
</VCardItem>
|
||||
</VCard>
|
||||
|
||||
@@ -51,7 +51,7 @@ onBeforeRouteUpdate(async (to, from, next) => {
|
||||
|
||||
<VCard title="Last Commit" class="mt-5">
|
||||
<VCardItem class="pt-0">
|
||||
<DynamicComponent :value="store.current.block?.lastCommit"/>
|
||||
<DynamicComponent :value="store.current.block?.last_commit"/>
|
||||
</VCardItem>
|
||||
</VCard>
|
||||
</div>
|
||||
|
||||
@@ -22,7 +22,7 @@ export const useBlockModule = defineStore('blockModule', {
|
||||
},
|
||||
txsInRecents() {
|
||||
const txs = [] as {hash:string, tx: DecodedTxRaw}[]
|
||||
this.recents.forEach((x:GetLatestBlockResponse) => x.block?.data?.txs.forEach((tx:Uint8Array) => txs.push({
|
||||
this.recents.forEach((x) => x.block?.data?.txs.forEach((tx:Uint8Array) => txs.push({
|
||||
hash: hashTx(tx),
|
||||
tx :decodeTxRaw(tx)
|
||||
})))
|
||||
@@ -47,13 +47,13 @@ export const useBlockModule = defineStore('blockModule', {
|
||||
})
|
||||
},
|
||||
async fetchLatest() {
|
||||
this.latest = await this.blockchain.rpc.block()
|
||||
this.latest = await this.blockchain.rpc.getBaseBlockLatest()
|
||||
if(this.recents.length >= 50) this.recents.shift()
|
||||
this.recents.push(this.latest)
|
||||
return this.latest
|
||||
},
|
||||
async fetchBlock(height?: number) {
|
||||
this.current = await this.blockchain.rpc.block(height)
|
||||
async fetchBlock(height: string) {
|
||||
this.current = await this.blockchain.rpc.getBaseBlockAt(height)
|
||||
return this.current
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
<script lang="ts" setup>
|
||||
import TxsElement from '@/components/dynamic/TxsElement.vue';
|
||||
import { useBlockModule } from './block'
|
||||
import DynamicComponent from '@/components/dynamic/DynamicComponent.vue';
|
||||
import { computed } from '@vue/reactivity';
|
||||
import { toBase64, toHex } from '@cosmjs/encoding';
|
||||
import { computed, ref } from '@vue/reactivity';
|
||||
import { useFormatter } from '@/stores';
|
||||
const props = defineProps(["height", "chain"]);
|
||||
|
||||
const store = useBlockModule()
|
||||
store.fetchBlock(props.height)
|
||||
// store.fetchBlock(props.height)
|
||||
const tab = ref('blocks')
|
||||
|
||||
const format = useFormatter()
|
||||
@@ -33,8 +30,8 @@ const format = useFormatter()
|
||||
<tbody>
|
||||
<tr v-for="item in store.recents">
|
||||
<td><RouterLink :to="`/${props.chain}/block/${item.block?.header?.height}`">{{ item.block?.header?.height }}</RouterLink></td>
|
||||
<td>{{ toBase64(item.blockId?.hash) }}</td>
|
||||
<td>{{ format.validator(item.block?.header?.proposerAddress) }}</td>
|
||||
<td>{{ item.block_id?.hash }}</td>
|
||||
<td>{{ format.validator(item.block?.header?.proposer_address) }}</td>
|
||||
<td>{{ item.block?.data?.txs.length }}</td>
|
||||
<td>{{ format.toDay(item.block?.header?.time, 'from') }}</td>
|
||||
</tr>
|
||||
|
||||
@@ -146,11 +146,11 @@ function shortName(name: string, id: string) {
|
||||
<VExpansionPanels variant="accordion">
|
||||
<VExpansionPanel v-for="(x, i) in store.proposals">
|
||||
<VExpansionPanelTitle disable-icon-rotate>
|
||||
<VChip label color="primary" class="mr-2">{{x.proposalId}}</VChip>
|
||||
<VChip label color="primary" class="mr-2">{{x.proposal_id}}</VChip>
|
||||
<div class="w-100">{{ x.content?.title }}
|
||||
<div class="d-flex mt-1">
|
||||
<small class="text-secondary me-auto"> {{ format.toDay(x.votingEndTime, 'from') }}</small>
|
||||
<ProposalProcess style="width:300px;" :pool="store.pool" :tally="store.tally[Number(x.proposalId)]"></ProposalProcess>
|
||||
<small class="text-secondary me-auto"> {{ format.toDay(x.voting_end_time, 'from') }}</small>
|
||||
<ProposalProcess style="width:300px;" :pool="store.pool" :tally="store.tally[x.proposal_id]"></ProposalProcess>
|
||||
<span></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,6 +2,7 @@ import { useBlockchain, useCoingecko, useBaseStore, useBankStore, useFormatter,
|
||||
import { useDistributionStore } from "@/stores/useDistributionStore";
|
||||
import { useMintStore } from "@/stores/useMintStore";
|
||||
import { useStakingStore } from "@/stores/useStakingStore";
|
||||
import type { GovProposal, Tally } from "@/types";
|
||||
import numeral from "numeral";
|
||||
import { defineStore } from "pinia";
|
||||
|
||||
@@ -64,13 +65,8 @@ export const useIndexModule = defineStore('module-index', {
|
||||
total_volumes: [] as number[],
|
||||
},
|
||||
communityPool: [] as {amount: string, denom: string}[],
|
||||
proposals: [] as Proposal[],
|
||||
tally: {} as Record<number, {
|
||||
yes: string;
|
||||
abstain: string;
|
||||
no: string;
|
||||
noWithVeto: string;
|
||||
}>
|
||||
proposals: [] as GovProposal[],
|
||||
tally: {} as Record<string, Tally>
|
||||
}
|
||||
},
|
||||
getters: {
|
||||
@@ -144,7 +140,7 @@ export const useIndexModule = defineStore('module-index', {
|
||||
title: 'Validators',
|
||||
color: 'error',
|
||||
icon: 'mdi-human-queue',
|
||||
stats: String(base.latest.block?.lastCommit?.signatures.length || 0),
|
||||
stats: String(base.latest.block?.last_commit?.signatures.length || 0),
|
||||
change: 0,
|
||||
},
|
||||
{
|
||||
@@ -158,7 +154,7 @@ export const useIndexModule = defineStore('module-index', {
|
||||
title: 'Bonded Tokens',
|
||||
color: 'warning',
|
||||
icon: 'mdi-lock',
|
||||
stats: formatter.formatTokenAmount({amount: this.pool.bondedTokens, denom: staking.params.bondDenom }),
|
||||
stats: formatter.formatTokenAmount({amount: this.pool.bonded_tokens, denom: staking.params.bond_denom }),
|
||||
change: 0,
|
||||
},
|
||||
{
|
||||
@@ -185,18 +181,18 @@ export const useIndexModule = defineStore('module-index', {
|
||||
this.initCoingecko()
|
||||
useMintStore().fetchInflation()
|
||||
useDistributionStore().fetchCommunityPool().then(x => {
|
||||
this.communityPool = x.pool.filter(t=> t.denom.length < 10).map(t => ({
|
||||
this.communityPool = x.pool.filter(t => t.denom.length < 10).map(t => ({
|
||||
amount: String(parseInt(t.amount)),
|
||||
denom: t.denom
|
||||
}))
|
||||
})
|
||||
const gov = useGovStore()
|
||||
gov.fetchProposals(ProposalStatus.PROPOSAL_STATUS_VOTING_PERIOD).then(x => {
|
||||
gov.fetchProposals(2).then(x => {
|
||||
this.proposals = x.proposals
|
||||
x.proposals.forEach(x1 => {
|
||||
gov.fetchTally(Number(x1.proposalId)).then(t => {
|
||||
gov.fetchTally(x1.proposal_id).then(t => {
|
||||
console.log("log: ", t)
|
||||
if(t.tally) this.tally[Number(x1.proposalId)] = t.tally
|
||||
if(t.tally) this.tally[x1.proposal_id] = t.tally
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import { useBlockchain, useFormatter, useMintStore, useStakingStore } from '@/stores';
|
||||
import { onMounted } from 'vue';
|
||||
import { onMounted, computed, ref } from 'vue';
|
||||
import ValidatorCommissionRate from '@/components/ValidatorCommissionRate.vue'
|
||||
import { consensusPubkeyToHexAddress, operatorAddressToAccount, pubKeyToValcons, valoperToPrefix } from '@/libs';
|
||||
import { computed } from '@vue/reactivity';
|
||||
import type { Coin } from '@/types';
|
||||
import type { Txs } from '@/types/Txs';
|
||||
import type { Coin, Delegation, PaginatedTxs, Validator } from '@/types';
|
||||
|
||||
const props = defineProps(['validator', 'chain'])
|
||||
|
||||
@@ -15,45 +13,44 @@ const format = useFormatter()
|
||||
|
||||
const validator: string = props.validator
|
||||
|
||||
const v = ref({})
|
||||
const v = ref({} as Validator)
|
||||
const cache = JSON.parse(localStorage.getItem('avatars')||'{}')
|
||||
const avatars = ref( cache || {} )
|
||||
const identity = ref("")
|
||||
const rewards = ref([] as Coin[])
|
||||
const rewards = ref([] as Coin[]|undefined)
|
||||
const addresses = ref({} as {
|
||||
account: string
|
||||
operAddress: string
|
||||
hex: string
|
||||
valCons: string,
|
||||
})
|
||||
const selfBonded = ref({} as Coin)
|
||||
const selfBonded = ref({} as Delegation)
|
||||
|
||||
addresses.value.account = operatorAddressToAccount(validator)
|
||||
// load self bond
|
||||
staking.fetchValidatorDelegation(validator, addresses.value.account).then(x => {
|
||||
if(x) {
|
||||
selfBonded.value = x
|
||||
selfBonded.value = x.delegation_response
|
||||
}
|
||||
})
|
||||
|
||||
const txs = ref({} as Txs)
|
||||
const txs = ref({} as PaginatedTxs)
|
||||
|
||||
blockchain.rpc.txs([`message.sender='${addresses.value.account}'`]).then(x => {
|
||||
blockchain.rpc.getTxsBySender(addresses.value.account).then(x => {
|
||||
console.log("txs", x)
|
||||
txs.value = x
|
||||
})
|
||||
|
||||
const apr = computed(()=> {
|
||||
const rate = v.value.commission?.commissionRates.rate || 0
|
||||
const rate = v.value.commission?.commission_rates.rate || 0
|
||||
const inflation = useMintStore().inflation
|
||||
if(Number(inflation)) {
|
||||
return format.percent((1 - rate) * Number(inflation))
|
||||
return format.percent((1 - Number(rate)) * Number(inflation))
|
||||
}
|
||||
return "-"
|
||||
})
|
||||
|
||||
const selfRate = computed(()=> {
|
||||
console.log("self rate", selfBonded.value.balance?.amount, v.value.tokens)
|
||||
if(selfBonded.value.balance?.amount) {
|
||||
return format.calculatePercent(selfBonded.value.balance.amount, v.value.tokens)
|
||||
}
|
||||
@@ -62,9 +59,9 @@ const selfRate = computed(()=> {
|
||||
|
||||
onMounted(()=> {
|
||||
if(validator) {
|
||||
staking.fetchValidator(validator.toString()).then(res => {
|
||||
staking.fetchValidator(validator).then(res => {
|
||||
v.value = res.validator
|
||||
identity.value = res.validator?.description?.identity
|
||||
identity.value = res.validator?.description?.identity || ''
|
||||
if(identity.value && !avatars.value[identity.value]) {
|
||||
console.log(identity.value, avatars)
|
||||
staking.keybase(identity.value).then(d => {
|
||||
@@ -77,12 +74,11 @@ onMounted(()=> {
|
||||
}
|
||||
})
|
||||
}
|
||||
const prefix = valoperToPrefix(v.value.operatorAddress) || '<Invalid>'
|
||||
addresses.value.hex = consensusPubkeyToHexAddress(v.value.consensusPubkey)
|
||||
addresses.value.valCons = pubKeyToValcons(v.value.consensusPubkey, prefix)
|
||||
const prefix = valoperToPrefix(v.value.operator_address) || '<Invalid>'
|
||||
addresses.value.hex = consensusPubkeyToHexAddress(v.value.consensus_pubkey)
|
||||
addresses.value.valCons = pubKeyToValcons(v.value.consensus_pubkey, prefix)
|
||||
})
|
||||
blockchain.rpc.validatorOutstandingRewards(validator).then(res => {
|
||||
console.log(res)
|
||||
blockchain.rpc.getDistributionValidatorOutstandingRewards(validator).then(res => {
|
||||
rewards.value = res.rewards?.rewards
|
||||
})
|
||||
}
|
||||
@@ -114,7 +110,7 @@ onMounted(()=> {
|
||||
<span>Website: </span><span> {{ v.description?.website || '-' }}</span>
|
||||
</VListItem>
|
||||
<VListItem prepend-icon="mdi-phone">
|
||||
<span>Contact: </span><span> {{ v.description?.securityContact }}</span>
|
||||
<span>Contact: </span><span> {{ v.description?.security_contact }}</span>
|
||||
</VListItem>
|
||||
</VList>
|
||||
|
||||
@@ -137,7 +133,7 @@ onMounted(()=> {
|
||||
<div class="d-flex">
|
||||
<VAvatar color="secondary" rounded variant="outlined" icon="mdi-coin"></VAvatar>
|
||||
<div class="ml-3 d-flex flex-column justify-center">
|
||||
<h4>{{ format.formatToken2({amount: v.tokens, denom: staking.params.bondDenom}) }}</h4>
|
||||
<h4>{{ format.formatToken2({amount: v.tokens, denom: staking.params.bond_denom}) }}</h4>
|
||||
<span class="text-sm">Bonded Tokens</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -152,7 +148,7 @@ onMounted(()=> {
|
||||
<div class="d-flex">
|
||||
<VAvatar color="secondary" rounded variant="outlined" icon="mdi-flag"></VAvatar>
|
||||
<div class="ml-3 d-flex flex-column justify-center">
|
||||
<h4>{{ v.minSelfDelegation }} {{ staking.params.bondDenom }}</h4>
|
||||
<h4>{{ v.minSelfDelegation }} {{ staking.params.bond_denom }}</h4>
|
||||
<span class="text-sm">Min Self Delegation:</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -167,7 +163,7 @@ onMounted(()=> {
|
||||
<div class="d-flex">
|
||||
<VAvatar color="secondary" rounded variant="outlined" icon="mdi-pound"></VAvatar>
|
||||
<div class="ml-3 d-flex flex-column justify-center">
|
||||
<h4>{{ v.unbondingHeight }}</h4>
|
||||
<h4>{{ v.unbonding_height }}</h4>
|
||||
<span class="text-sm">Unbonding Height</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -175,7 +171,7 @@ onMounted(()=> {
|
||||
<div class="d-flex">
|
||||
<VAvatar color="secondary" rounded variant="outlined" icon="mdi-clock"></VAvatar>
|
||||
<div class="ml-3 d-flex flex-column justify-center">
|
||||
<h4>{{ format.toDay(v.unbondingTime, 'from') }}</h4>
|
||||
<h4>{{ format.toDay(v.unbonding_time, 'from') }}</h4>
|
||||
<span class="text-sm">Unbonding Time</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -209,7 +205,7 @@ onMounted(()=> {
|
||||
</VListItem>
|
||||
<VListItem>
|
||||
<VListItemTitle>Operator Address</VListItemTitle>
|
||||
<VListItemSubtitle class="text-caption">{{ v.operatorAddress }}</VListItemSubtitle>
|
||||
<VListItemSubtitle class="text-caption">{{ v.operator_address }}</VListItemSubtitle>
|
||||
</VListItem>
|
||||
<VListItem>
|
||||
<VListItemTitle>Hex Address</VListItemTitle>
|
||||
@@ -233,10 +229,10 @@ onMounted(()=> {
|
||||
<th class="text-left pl-4">Time</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(item, i) in txs.txResponses">
|
||||
<tr v-for="(item, i) in txs.tx_responses">
|
||||
<td>{{ item.height }}</td>
|
||||
<td class="text-truncate" style="max-width: 200px;">{{ item.txhash }}</td>
|
||||
<td>{{ format.messages(txs.txs[i]?.body.messages) }}</td>
|
||||
<td>{{ format.messages(item.tx.body.messages) }}</td>
|
||||
<td width="150">{{ format.toDay(item.timestamp,'from') }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<script lang=ts setup>
|
||||
import { useBaseStore, useFormatter, useStakingStore } from '@/stores';
|
||||
import { toBase64, toHex } from '@cosmjs/encoding';
|
||||
import { pubkeyToAddress } from '@cosmjs/tendermint-rpc';
|
||||
import { computed } from '@vue/reactivity';
|
||||
import { onMounted, ref, type DebuggerEvent } from 'vue';
|
||||
import { consensusPubkeyToHexAddress } from '@/libs'
|
||||
import type { Key, Validator } from '@/types';
|
||||
const staking = useStakingStore()
|
||||
const format = useFormatter()
|
||||
|
||||
@@ -13,7 +13,7 @@ const avatars = ref( cache || {} )
|
||||
const latest = ref({} as Record<string, number>)
|
||||
const yesterday = ref({} as Record<string, number>)
|
||||
const tab = ref('active')
|
||||
const unbondList = ref([])
|
||||
const unbondList = ref([] as Validator[])
|
||||
const base = useBaseStore()
|
||||
onMounted(()=> {
|
||||
fetchChange(0)
|
||||
@@ -25,39 +25,39 @@ onMounted(()=> {
|
||||
function fetchChange(offset: number) {
|
||||
const base = useBaseStore()
|
||||
const diff = 86400000 / base.blocktime
|
||||
base.fetchAbciInfo().then(h => {
|
||||
// console.log('block:', h)
|
||||
base.fetchValidatorByHeight(h.lastBlockHeight, offset).then(x => {
|
||||
x.validators.forEach(v => {
|
||||
if(v.pubkey) latest.value[pubkeyToAddress(v.pubkey.algorithm, v.pubkey.data)] = Number(v.votingPower)
|
||||
})
|
||||
})
|
||||
const height = Number(h.lastBlockHeight) - diff
|
||||
base.fetchValidatorByHeight(height > 0 ? height : 1, offset).then(old => {
|
||||
old.validators.forEach(v => {
|
||||
if(v.pubkey) yesterday.value[pubkeyToAddress(v.pubkey.algorithm, v.pubkey.data)] = Number(v.votingPower)
|
||||
})
|
||||
// console.log(Object.keys(yesterday.value).map(x => x.toUpperCase()))
|
||||
})
|
||||
})
|
||||
// base.fetchAbciInfo().then(h => {
|
||||
// // console.log('block:', h)
|
||||
// base.fetchValidatorByHeight(h.lastBlockHeight, offset).then(x => {
|
||||
// x.validators.forEach(v => {
|
||||
// if(v.pubkey) latest.value[pubkeyToAddress(v.pubkey.algorithm, v.pubkey.data)] = Number(v.votingPower)
|
||||
// })
|
||||
// })
|
||||
// const height = Number(h.lastBlockHeight) - diff
|
||||
// base.fetchValidatorByHeight(height > 0 ? height : 1, offset).then(old => {
|
||||
// old.validators.forEach(v => {
|
||||
// if(v.pubkey) yesterday.value[pubkeyToAddress(v.pubkey.algorithm, v.pubkey.data)] = Number(v.votingPower)
|
||||
// })
|
||||
// // console.log(Object.keys(yesterday.value).map(x => x.toUpperCase()))
|
||||
// })
|
||||
// })
|
||||
}
|
||||
|
||||
const change24 = (key: {typeUrl: string, value: Uint8Array}) => {
|
||||
const change24 = (key: Key) => {
|
||||
// console.log('hex key:', consensusPubkeyToHexAddress(key))
|
||||
const txt = toBase64(key.value)
|
||||
const txt = key.key
|
||||
const n : number = latest.value[txt];
|
||||
const o : number = yesterday.value[txt]
|
||||
// console.log( txt, n, o)
|
||||
return n >0 && o > 0 ? n - o : 0
|
||||
}
|
||||
|
||||
const change24Text = (key?: {typeUrl: string, value: Uint8Array}) => {
|
||||
const change24Text = (key?: Key) => {
|
||||
if(!key) return ''
|
||||
const v = change24(key)
|
||||
return v!==0 ? format.numberAndSign(v) : ''
|
||||
}
|
||||
|
||||
const change24Color = (key?: {typeUrl: string, value: Uint8Array}) => {
|
||||
const change24Color = (key?: Key) => {
|
||||
if(!key) return ''
|
||||
const v = change24(key)
|
||||
if(v > 0) return 'text-success'
|
||||
@@ -71,8 +71,8 @@ const update = (m: DebuggerEvent) => {
|
||||
}
|
||||
|
||||
const list = computed(() => {
|
||||
// return tab.value === 'active' ? staking.validators: unbondList.value
|
||||
return staking.validators
|
||||
return tab.value === 'active' ? staking.validators: unbondList.value
|
||||
// return staking.validators
|
||||
})
|
||||
|
||||
const loadAvatars = () => {
|
||||
@@ -116,7 +116,7 @@ const logo = (identity?: string) => {
|
||||
const rank = function(position: number) {
|
||||
let sum = 0
|
||||
for(let i = 0;i < position; i++) {
|
||||
sum += Number(staking.validators[i]?.delegatorShares)
|
||||
sum += Number(staking.validators[i]?.delegator_shares)
|
||||
}
|
||||
const percent = (sum / staking.totalPower)
|
||||
|
||||
@@ -135,7 +135,7 @@ const rank = function(position: number) {
|
||||
<VBtn value="active" variant="outlined" >Active</VBtn>
|
||||
<VBtn value="inactive" variant="outlined">Inactive</VBtn>
|
||||
</VBtnToggle>
|
||||
<span class="mt-2">{{ list.length }}/{{ staking.params.maxValidators }}</span>
|
||||
<span class="mt-2">{{ list.length }}/{{ staking.params.max_validators }}</span>
|
||||
</VCardTitle>
|
||||
<VTable class="text-no-wrap table-header-bg rounded-0">
|
||||
<thead>
|
||||
@@ -164,7 +164,7 @@ const rank = function(position: number) {
|
||||
<tbody>
|
||||
<tr
|
||||
v-for="(v, i) in list"
|
||||
:key="v.operatorAddress"
|
||||
:key="v.operator_address"
|
||||
>
|
||||
<!-- 👉 rank -->
|
||||
<td>
|
||||
@@ -186,7 +186,7 @@ const rank = function(position: number) {
|
||||
<div class="d-flex flex-column">
|
||||
<h6 class="text-sm">
|
||||
<RouterLink
|
||||
:to="{name: 'chain-staking-validator', params: {validator: v.operatorAddress}}"
|
||||
:to="{name: 'chain-staking-validator', params: {validator: v.operator_address}}"
|
||||
class="font-weight-medium user-list-name"
|
||||
>
|
||||
{{ v.description?.moniker }}
|
||||
@@ -202,18 +202,18 @@ const rank = function(position: number) {
|
||||
<td class="text-right">
|
||||
<div class="d-flex flex-column">
|
||||
<h6 class="text-sm font-weight-medium">
|
||||
{{ format.formatToken( {amount: parseInt(v.tokens).toString(), denom: staking.params.bondDenom }, true, "0,0") }}
|
||||
{{ format.formatToken( {amount: parseInt(v.tokens).toString(), denom: staking.params.bond_denom }, true, "0,0") }}
|
||||
</h6>
|
||||
<span class="text-xs">{{ format.calculatePercent(v.delegatorShares, staking.totalPower) }}</span>
|
||||
<span class="text-xs">{{ format.calculatePercent(v.delegator_shares, staking.totalPower) }}</span>
|
||||
</div>
|
||||
</td>
|
||||
<!-- 👉 24h Changes -->
|
||||
<td class="text-right text-xs" :class="change24Color(v.consensusPubkey)">
|
||||
{{ change24Text(v.consensusPubkey) }} <VChip label v-if="v.jailed" color="error">Jailed</VChip>
|
||||
<td class="text-right text-xs" :class="change24Color(v.consensus_pubkey)">
|
||||
{{ change24Text(v.consensus_pubkey) }} <VChip label v-if="v.jailed" color="error">Jailed</VChip>
|
||||
</td>
|
||||
<!-- 👉 commission -->
|
||||
<td class="text-right">
|
||||
{{ format.formatCommissionRate(v.commission?.commissionRates?.rate) }}
|
||||
{{ format.formatCommissionRate(v.commission?.commission_rates?.rate) }}
|
||||
</td>
|
||||
<!-- 👉 Action -->
|
||||
<td>
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
<script lang="ts" setup>
|
||||
import { useBlockchain, useFormatter } from '@/stores';
|
||||
import type { GetTxResponse } from 'cosmjs-types/cosmos/tx/v1beta1/service';
|
||||
import DynamicComponent from '@/components/dynamic/DynamicComponent.vue';
|
||||
import { computed } from '@vue/reactivity';
|
||||
import { fromBase64, toBase64 } from '@cosmjs/encoding';
|
||||
import { computed, ref } from '@vue/reactivity';
|
||||
import type { Tx, TxResponse } from '@/types';
|
||||
|
||||
const props = defineProps(['hash', 'chain'])
|
||||
|
||||
const blockchain = useBlockchain()
|
||||
const format = useFormatter()
|
||||
const tx = ref({} as GetTxResponse)
|
||||
const tx = ref({} as {
|
||||
tx: Tx;
|
||||
tx_response: TxResponse
|
||||
})
|
||||
if(props.hash) {
|
||||
blockchain.rpc.tx(props.hash).then(x => tx.value = x)
|
||||
blockchain.rpc.getTx(props.hash).then(x => tx.value = x)
|
||||
}
|
||||
const messages = computed(() => {
|
||||
return tx.value.tx?.body?.messages||[]
|
||||
@@ -19,19 +21,19 @@ const messages = computed(() => {
|
||||
</script>
|
||||
<template>
|
||||
<div>
|
||||
<VCard v-if="tx.txResponse" title="Summary">
|
||||
<VCard v-if="tx.tx_response" title="Summary">
|
||||
<VCardItem class="pt-0">
|
||||
<VTable>
|
||||
<tbody>
|
||||
<tr><td>Tx Hash</td><td>{{ tx.txResponse.txhash }}</td></tr>
|
||||
<tr><td>Height</td><td><RouterLink :to="`/${props.chain}/block/${tx.txResponse.height}`">{{ tx.txResponse.height }}</RouterLink></td></tr>
|
||||
<tr><td>Tx Hash</td><td>{{ tx.tx_response.txhash }}</td></tr>
|
||||
<tr><td>Height</td><td><RouterLink :to="`/${props.chain}/block/${tx.tx_response.height}`">{{ tx.tx_response.height }}</RouterLink></td></tr>
|
||||
<tr><td>Status</td><td>
|
||||
<VChip v-if="tx.txResponse.code === 0" color="success">Success</VChip>
|
||||
<VChip v-if="tx.tx_response.code === 0" color="success">Success</VChip>
|
||||
<span v-else><VChip color="error">Failded</VChip></span>
|
||||
</td></tr>
|
||||
<tr><td>Time</td><td>{{ tx.txResponse.timestamp }} ({{ format.toDay(tx.txResponse.timestamp, "from") }})</td></tr>
|
||||
<tr><td>Gas</td><td>{{ tx.txResponse.gasUsed }} / {{ tx.txResponse.gasWanted }}</td></tr>
|
||||
<tr><td>Fee</td><td>{{ format.formatTokens(tx.tx?.authInfo?.fee?.amount, true, '0,0.[00]') }}</td></tr>
|
||||
<tr><td>Time</td><td>{{ tx.tx_response.timestamp }} ({{ format.toDay(tx.tx_response.timestamp, "from") }})</td></tr>
|
||||
<tr><td>Gas</td><td>{{ tx.tx_response.gas_used }} / {{ tx.tx_response.gas_wanted }}</td></tr>
|
||||
<tr><td>Fee</td><td>{{ format.formatTokens(tx.tx?.auth_info?.fee?.amount, true, '0,0.[00]') }}</td></tr>
|
||||
<tr><td>Memo</td><td>{{ tx.tx.body.memo }}</td></tr>
|
||||
</tbody>
|
||||
</VTable>
|
||||
@@ -39,10 +41,9 @@ const messages = computed(() => {
|
||||
</VCard>
|
||||
|
||||
<VCard title="Messages" class="my-5">
|
||||
<VCardItem>
|
||||
<VCardItem style="border-top: 2px dotted gray;">
|
||||
<div v-for="(msg, i) in messages">
|
||||
<div><VChip label color="primary">#{{ i+1 }}</VChip>{{ msg.typeUrl }}</div>
|
||||
<div>{{ toBase64(msg.value) }}</div>
|
||||
<div><DynamicComponent :value="msg" /></div>
|
||||
</div>
|
||||
</VCardItem>
|
||||
</VCard>
|
||||
@@ -56,7 +57,7 @@ const messages = computed(() => {
|
||||
</VExpansionPanel>
|
||||
<VExpansionPanel title="Transaction Response">
|
||||
<v-expansion-panel-text>
|
||||
<DynamicComponent :value="tx.txResponse" />
|
||||
<DynamicComponent :value="tx.tx_response" />
|
||||
</v-expansion-panel-text>
|
||||
</VExpansionPanel>
|
||||
</VExpansionPanels>
|
||||
|
||||
@@ -5,7 +5,7 @@ async function tt() {
|
||||
const address = "echelon1uattqtrtv8944qkmh44ll97qjacj6tgrekqzm9"
|
||||
const validator = "echelonvaloper1uattqtrtv8944qkmh44ll97qjacj6tgr2cupk4"
|
||||
const client = new CosmosRestClient("https://api.ech.network")
|
||||
let response = await client.getSlashingSigningInfos();
|
||||
let response = await client.getBaseBlockLatest();
|
||||
console.log('response:', response)
|
||||
}
|
||||
tt()
|
||||
|
||||
Reference in New Issue
Block a user