Make address human readable
This commit is contained in:
parent
eaac3b295a
commit
de77ea57c1
@ -8,9 +8,9 @@ import duration from 'dayjs/plugin/duration'
|
|||||||
import relativeTime from 'dayjs/plugin/relativeTime'
|
import relativeTime from 'dayjs/plugin/relativeTime'
|
||||||
import localeData from 'dayjs/plugin/localeData'
|
import localeData from 'dayjs/plugin/localeData'
|
||||||
|
|
||||||
|
dayjs.extend(localeData)
|
||||||
dayjs.extend(duration)
|
dayjs.extend(duration)
|
||||||
dayjs.extend(relativeTime)
|
dayjs.extend(relativeTime)
|
||||||
dayjs.extend(localeData)
|
|
||||||
|
|
||||||
export function toDuration(value) {
|
export function toDuration(value) {
|
||||||
return dayjs.duration(value).humanize()
|
return dayjs.duration(value).humanize()
|
||||||
@ -39,9 +39,16 @@ export function percent(num) {
|
|||||||
return parseFloat((num * 100).toFixed(2))
|
return parseFloat((num * 100).toFixed(2))
|
||||||
}
|
}
|
||||||
|
|
||||||
export function abbr(string, length = 6) {
|
export function abbr(string, length = 6, suffix = '...') {
|
||||||
if (string && string.length > length) {
|
if (string && string.length > length) {
|
||||||
return `${string.substring(0, length)}...`
|
return `${string.substring(0, length)}${suffix}`
|
||||||
|
}
|
||||||
|
return string
|
||||||
|
}
|
||||||
|
|
||||||
|
export function abbrRight(string, length = 6, suffix = '...') {
|
||||||
|
if (string && string.length > length) {
|
||||||
|
return `${string.substring(string.length - length)}${suffix}`
|
||||||
}
|
}
|
||||||
return string
|
return string
|
||||||
}
|
}
|
||||||
@ -105,6 +112,9 @@ export function tokenFormatter(tokens) {
|
|||||||
|
|
||||||
export function operatorAddressToAccount(operAddress) {
|
export function operatorAddressToAccount(operAddress) {
|
||||||
const { prefix, data } = Bech32.decode(operAddress)
|
const { prefix, data } = Bech32.decode(operAddress)
|
||||||
|
if (prefix === 'iva') { // handle special cases
|
||||||
|
return Bech32.encode('iaa', data)
|
||||||
|
}
|
||||||
return Bech32.encode(prefix.replace('valoper', ''), data)
|
return Bech32.encode(prefix.replace('valoper', ''), data)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,6 +129,38 @@ export function consensusPubkeyToHexAddress(consensusPubkey) {
|
|||||||
return address
|
return address
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getCachedValidators(chainName) {
|
||||||
|
const locals = localStorage.getItem(`validators-${chainName}`)
|
||||||
|
return locals
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isHexAddress(v) {
|
||||||
|
const re = /^[A-Z\d]{40}$/
|
||||||
|
return re.test(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getStakingValidatorByHex(chainName, hex) {
|
||||||
|
const locals = localStorage.getItem(`validators-${chainName}`)
|
||||||
|
if (locals) {
|
||||||
|
const val = JSON.parse(locals).find(x => consensusPubkeyToHexAddress(x.consensus_pubkey) === hex)
|
||||||
|
if (val) {
|
||||||
|
return val.description.moniker
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return abbr(hex)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getStakingValidatorByAccount(chainName, addr) {
|
||||||
|
const locals = localStorage.getItem(`validators-${chainName}`)
|
||||||
|
if (locals) {
|
||||||
|
const val = JSON.parse(locals).find(x => operatorAddressToAccount(x.operator_address) === addr)
|
||||||
|
if (val) {
|
||||||
|
return val.description.moniker
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return addr
|
||||||
|
}
|
||||||
|
|
||||||
export * from 'compare-versions'
|
export * from 'compare-versions'
|
||||||
|
|
||||||
export class Data {
|
export class Data {
|
||||||
|
@ -106,7 +106,11 @@ const chainAPI = class ChainFetch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getValidatorList() {
|
async getValidatorList() {
|
||||||
return this.get('/staking/validators').then(data => commonProcess(data).map(i => new Validator().init(i)))
|
return this.get('/staking/validators').then(data => {
|
||||||
|
const vals = commonProcess(data).map(i => new Validator().init(i))
|
||||||
|
localStorage.setItem(`validators-${this.config.chain_name}`, JSON.stringify(vals))
|
||||||
|
return vals
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async getStakingValidator(address) {
|
async getStakingValidator(address) {
|
||||||
|
@ -95,7 +95,7 @@ const router = new VueRouter({
|
|||||||
{
|
{
|
||||||
path: '/:chain/gov/:proposalid',
|
path: '/:chain/gov/:proposalid',
|
||||||
name: 'proposal',
|
name: 'proposal',
|
||||||
component: () => import('@/views/ProposalView.vue'),
|
component: () => import('@/views/GovernanceProposalView.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
pageTitle: 'Governance',
|
pageTitle: 'Governance',
|
||||||
breadcrumb: [
|
breadcrumb: [
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
>
|
>
|
||||||
<template #cell()="data">
|
<template #cell()="data">
|
||||||
<span v-if="isTokenField(data.value)">{{ formatTokens(data.value) }}</span>
|
<span v-if="isTokenField(data.value)">{{ formatTokens(data.value) }}</span>
|
||||||
|
<span v-else-if="isHex(data.value)">{{ formatHexAddress(data.value) }}</span>
|
||||||
<array-field-component
|
<array-field-component
|
||||||
v-else-if="isArrayText(data.value)"
|
v-else-if="isArrayText(data.value)"
|
||||||
:tablefield="eval_value(data.value)"
|
:tablefield="eval_value(data.value)"
|
||||||
@ -25,7 +26,7 @@ import { BTable } from 'bootstrap-vue'
|
|||||||
// import fetch from 'node-fetch'
|
// import fetch from 'node-fetch'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
abbr, isToken, toDay, tokenFormatter,
|
abbr, getStakingValidatorByHex, isHexAddress, isToken, toDay, tokenFormatter,
|
||||||
} from '@/libs/data/data'
|
} from '@/libs/data/data'
|
||||||
// import { Proposal, Proposer } from '@/libs/data'
|
// import { Proposal, Proposer } from '@/libs/data'
|
||||||
// import { formatToken } from '@/libs/data/data'
|
// import { formatToken } from '@/libs/data/data'
|
||||||
@ -65,6 +66,12 @@ export default {
|
|||||||
formatTokens(value) {
|
formatTokens(value) {
|
||||||
return tokenFormatter(value)
|
return tokenFormatter(value)
|
||||||
},
|
},
|
||||||
|
isHex(value) {
|
||||||
|
return isHexAddress(value)
|
||||||
|
},
|
||||||
|
formatHexAddress(v) {
|
||||||
|
return getStakingValidatorByHex(this.$http.config.chain_name, v)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
{{ formatTime(data.item.block.header.time) }}
|
{{ formatTime(data.item.block.header.time) }}
|
||||||
</template>
|
</template>
|
||||||
<template #cell(proposer)="data">
|
<template #cell(proposer)="data">
|
||||||
{{ data.item.block.header.proposer_address }}
|
{{ formatProposer(data.item.block.header.proposer_address) }}
|
||||||
</template>
|
</template>
|
||||||
<template #cell(txs)="data">
|
<template #cell(txs)="data">
|
||||||
{{ length(data.item.block.data.txs) }}
|
{{ length(data.item.block.data.txs) }}
|
||||||
@ -46,6 +46,8 @@ import {
|
|||||||
BTable, BCard, BCardHeader, BCardTitle, VBTooltip,
|
BTable, BCard, BCardHeader, BCardTitle, VBTooltip,
|
||||||
} from 'bootstrap-vue'
|
} from 'bootstrap-vue'
|
||||||
import {
|
import {
|
||||||
|
getCachedValidators,
|
||||||
|
getStakingValidatorByHex,
|
||||||
toDay,
|
toDay,
|
||||||
} from '@/libs/data'
|
} from '@/libs/data'
|
||||||
// import fetch from 'node-fetch'
|
// import fetch from 'node-fetch'
|
||||||
@ -101,6 +103,10 @@ export default {
|
|||||||
list.push(height - i)
|
list.push(height - i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!getCachedValidators()) {
|
||||||
|
this.$http.getValidatorList()
|
||||||
|
}
|
||||||
|
|
||||||
let promise = Promise.resolve()
|
let promise = Promise.resolve()
|
||||||
list.forEach(item => {
|
list.forEach(item => {
|
||||||
promise = promise.then(() => new Promise(resolve => {
|
promise = promise.then(() => new Promise(resolve => {
|
||||||
@ -120,6 +126,9 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
length: v => (Array.isArray(v) ? v.length : 0),
|
length: v => (Array.isArray(v) ? v.length : 0),
|
||||||
formatTime: v => toDay(v, 'time'),
|
formatTime: v => toDay(v, 'time'),
|
||||||
|
formatProposer(v) {
|
||||||
|
return getStakingValidatorByHex(this.$http.config.chain_name, v)
|
||||||
|
},
|
||||||
fetch() {
|
fetch() {
|
||||||
this.$http.getLatestBlock().then(b => {
|
this.$http.getLatestBlock().then(b => {
|
||||||
const has = this.blocks.findIndex(x => x.block.header.height === b.block.header.height)
|
const has = this.blocks.findIndex(x => x.block.header.height === b.block.header.height)
|
||||||
|
@ -48,7 +48,7 @@
|
|||||||
<b-tr>
|
<b-tr>
|
||||||
<b-td>
|
<b-td>
|
||||||
{{ $t('proposal_proposer') }}
|
{{ $t('proposal_proposer') }}
|
||||||
</b-td><b-td>{{ proposer.proposer }} </b-td>
|
</b-td><b-td>{{ formatAddress(proposer.proposer) }} </b-td>
|
||||||
</b-tr>
|
</b-tr>
|
||||||
<b-tr>
|
<b-tr>
|
||||||
<b-td>
|
<b-td>
|
||||||
@ -202,7 +202,7 @@ import {
|
|||||||
} from 'bootstrap-vue'
|
} from 'bootstrap-vue'
|
||||||
// import fetch from 'node-fetch'
|
// import fetch from 'node-fetch'
|
||||||
|
|
||||||
import { tokenFormatter } from '@/libs/data/data'
|
import { getCachedValidators, getStakingValidatorByAccount, tokenFormatter } from '@/libs/data/data'
|
||||||
import { Proposal, Proposer } from '@/libs/data'
|
import { Proposal, Proposer } from '@/libs/data'
|
||||||
import ObjectFieldComponent from './ObjectFieldComponent.vue'
|
import ObjectFieldComponent from './ObjectFieldComponent.vue'
|
||||||
// import { formatToken } from '@/libs/data/data'
|
// import { formatToken } from '@/libs/data/data'
|
||||||
@ -232,7 +232,11 @@ export default {
|
|||||||
deposits: [],
|
deposits: [],
|
||||||
votes: [],
|
votes: [],
|
||||||
votes_fields: [
|
votes_fields: [
|
||||||
{ key: 'voter', sortable: true },
|
{
|
||||||
|
key: 'voter',
|
||||||
|
sortable: true,
|
||||||
|
formatter: v => this.formatAddress(v),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'option',
|
key: 'option',
|
||||||
sortable: true,
|
sortable: true,
|
||||||
@ -253,7 +257,10 @@ export default {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
deposit_fields: [
|
deposit_fields: [
|
||||||
'depositor',
|
{
|
||||||
|
key: 'depositor',
|
||||||
|
formatter: v => this.formatAddress(v),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'amount',
|
key: 'amount',
|
||||||
sortable: true,
|
sortable: true,
|
||||||
@ -273,6 +280,10 @@ export default {
|
|||||||
this.proposal = p
|
this.proposal = p
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (!getCachedValidators()) {
|
||||||
|
this.$http.getValidatorList()
|
||||||
|
}
|
||||||
|
|
||||||
this.$http.getGovernanceProposer(pid).then(res => {
|
this.$http.getGovernanceProposer(pid).then(res => {
|
||||||
this.proposer = res
|
this.proposer = res
|
||||||
})
|
})
|
||||||
@ -283,46 +294,11 @@ export default {
|
|||||||
this.votes = res
|
this.votes = res
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
methods: {
|
||||||
// asyncComputed: {
|
formatAddress(v) {
|
||||||
// proposal: {
|
return getStakingValidatorByAccount(this.$http.config.chain_name, v)
|
||||||
// get() {
|
},
|
||||||
// const pid = this.$route.params.proposalid
|
},
|
||||||
// // const api = new ChainAPI(this.$route)
|
|
||||||
// return this.$http.getGovernance(pid).then(p => {
|
|
||||||
// if (p.status === 2) {
|
|
||||||
// this.$http.getGovernanceTally(pid, 0).then(t => p.updateTally(t)).catch(e => console.log('failed on update voting tally:', e))
|
|
||||||
// }
|
|
||||||
// return p
|
|
||||||
// })
|
|
||||||
// },
|
|
||||||
// default: new Proposal(),
|
|
||||||
// },
|
|
||||||
// proposer: {
|
|
||||||
// get() {
|
|
||||||
// const pid = this.$route.params.proposalid
|
|
||||||
// // const api = new ChainAPI(this.$route)
|
|
||||||
// return this.$http.getGovernanceProposer(pid)
|
|
||||||
// },
|
|
||||||
// default: new Proposer(),
|
|
||||||
// },
|
|
||||||
// deposits: {
|
|
||||||
// get() {
|
|
||||||
// const pid = this.$route.params.proposalid
|
|
||||||
// // const api = new ChainAPI(this.$route)
|
|
||||||
// return this.$http.getGovernanceDeposits(pid)
|
|
||||||
// },
|
|
||||||
// default: [],
|
|
||||||
// },
|
|
||||||
// votes: {
|
|
||||||
// get() {
|
|
||||||
// const pid = this.$route.params.proposalid
|
|
||||||
// // const api = new ChainAPI(this.$route)
|
|
||||||
// return this.$http.getGovernanceVotes(pid)
|
|
||||||
// },
|
|
||||||
// default: [],
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -21,6 +21,9 @@
|
|||||||
<b-td v-else-if="isArrayText(value)">
|
<b-td v-else-if="isArrayText(value)">
|
||||||
{{ value.join(', ') }}
|
{{ value.join(', ') }}
|
||||||
</b-td>
|
</b-td>
|
||||||
|
<b-td v-else-if="isHex(value)">
|
||||||
|
{{ formatHexAddress(value) }}
|
||||||
|
</b-td>
|
||||||
<b-td v-else-if="Array.isArray(value)">
|
<b-td v-else-if="Array.isArray(value)">
|
||||||
<array-field-component :tablefield="value" />
|
<array-field-component :tablefield="value" />
|
||||||
</b-td>
|
</b-td>
|
||||||
@ -60,7 +63,7 @@ import {
|
|||||||
BTableSimple, BTr, BTd, BTabs, BTab,
|
BTableSimple, BTr, BTd, BTabs, BTab,
|
||||||
} from 'bootstrap-vue'
|
} from 'bootstrap-vue'
|
||||||
import {
|
import {
|
||||||
abbr, isStringArray, isToken, tokenFormatter,
|
abbr, getStakingValidatorByHex, isHexAddress, isStringArray, isToken, tokenFormatter,
|
||||||
} from '@/libs/data'
|
} from '@/libs/data'
|
||||||
import ArrayFieldComponent from './ArrayFieldComponent.vue'
|
import ArrayFieldComponent from './ArrayFieldComponent.vue'
|
||||||
|
|
||||||
@ -100,6 +103,12 @@ export default {
|
|||||||
isTokenField(value) {
|
isTokenField(value) {
|
||||||
return isToken(value)
|
return isToken(value)
|
||||||
},
|
},
|
||||||
|
isHex(value) {
|
||||||
|
return isHexAddress(value)
|
||||||
|
},
|
||||||
|
formatHexAddress(v) {
|
||||||
|
return getStakingValidatorByHex(this.$http.config.chain_name, v)
|
||||||
|
},
|
||||||
isArrayText(value) {
|
isArrayText(value) {
|
||||||
return isStringArray(value)
|
return isStringArray(value)
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user