finish block and transaction
This commit is contained in:
parent
f1e3e04e1f
commit
9e9f26af40
@ -15,6 +15,7 @@
|
||||
"@cosmjs/amino": "^0.25.6",
|
||||
"@cosmjs/crypto": "^0.25.6",
|
||||
"@cosmjs/encoding": "^0.25.6",
|
||||
"@cosmjs/proto-signing": "^0.25.6",
|
||||
"@fullcalendar/common": "5.x",
|
||||
"@fullcalendar/core": "5.x",
|
||||
"@fullcalendar/daygrid": "5.x",
|
||||
|
@ -12,6 +12,20 @@ export function percent(num) {
|
||||
return parseFloat((num * 100).toFixed(2))
|
||||
}
|
||||
|
||||
export function abbr(string, length = 6) {
|
||||
if (string && string.length > length) {
|
||||
return `${string.substring(0, length)}...`
|
||||
}
|
||||
return string
|
||||
}
|
||||
|
||||
export function abbrMessage(msg) {
|
||||
if (Array.isArray(msg)) {
|
||||
return msg.map(x => abbrMessage(x)).join()
|
||||
}
|
||||
return msg.typeUrl.substring(msg.typeUrl.lastIndexOf('.') + 1)
|
||||
}
|
||||
|
||||
export function isToken(value) {
|
||||
let is = false
|
||||
if (Array.isArray(value)) {
|
||||
@ -21,15 +35,18 @@ export function isToken(value) {
|
||||
}
|
||||
|
||||
export function formatToken(token) {
|
||||
let denom = token.denom.toUpperCase()
|
||||
if (denom.charAt(0) === 'U') {
|
||||
denom = denom.substring(1)
|
||||
if (token) {
|
||||
let denom = token.denom.toUpperCase()
|
||||
if (denom.charAt(0) === 'U') {
|
||||
denom = denom.substring(1)
|
||||
}
|
||||
const amount = token.amount / 1000000
|
||||
if (amount > 10) {
|
||||
return `${amount.toFixed()} ${denom}`
|
||||
}
|
||||
return `${amount} ${denom}`
|
||||
}
|
||||
const amount = token.amount / 1000000
|
||||
if (amount > 10) {
|
||||
return `${amount.toFixed()} ${denom}`
|
||||
}
|
||||
return `${amount} ${denom}`
|
||||
return ''
|
||||
}
|
||||
|
||||
const COUNT_ABBRS = ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y']
|
||||
|
@ -9,6 +9,7 @@ export { default as StakingParameters } from './staking-parameters'
|
||||
export { default as Block } from './block'
|
||||
export { default as ValidatorDistribution } from './validator-distribution'
|
||||
export { default as StakingDelegation } from './staking-delegation'
|
||||
export { default as WrapStdTx } from './wrapstdtx'
|
||||
export * from './data'
|
||||
|
||||
export default class Test {}
|
||||
|
36
src/libs/data/stdtx.js
Normal file
36
src/libs/data/stdtx.js
Normal file
@ -0,0 +1,36 @@
|
||||
import compareVersions from 'compare-versions'
|
||||
import Token from './token'
|
||||
|
||||
export default class StdTx {
|
||||
constructor() {
|
||||
this.type = ''
|
||||
this.fee = [new Token()]
|
||||
this.gas = 0
|
||||
this.memo = ''
|
||||
this.messages = []
|
||||
this.signatures = []
|
||||
this.timeout_height = 0
|
||||
}
|
||||
|
||||
static create(element, version = '0.40') {
|
||||
const self = new StdTx()
|
||||
if (compareVersions(version, '0.40') < 1) {
|
||||
self.type = element.type
|
||||
self.fee = element.value.fee.amount
|
||||
self.gas = element.value.fee.gas
|
||||
self.memo = element.value.memo
|
||||
self.messages = element.value.msg
|
||||
self.signatures = element.value.signatures
|
||||
self.timeout_height = 0
|
||||
} else {
|
||||
self.type = element['@type']
|
||||
self.fee = element.auth_info.fee.amount
|
||||
self.gas = element.auth_info.fee.gas_limit
|
||||
self.memo = element.body.memo
|
||||
self.messages = element.body.messages
|
||||
self.signatures = element.signatures
|
||||
self.timeout_height = element.body.timeout_height
|
||||
}
|
||||
return self
|
||||
}
|
||||
}
|
13
src/libs/data/token.js
Normal file
13
src/libs/data/token.js
Normal file
@ -0,0 +1,13 @@
|
||||
export default class Token {
|
||||
constructor() {
|
||||
this.amount = 0
|
||||
this.denom = ''
|
||||
}
|
||||
|
||||
static create(element) {
|
||||
const self = new Token()
|
||||
self.amount = Number(element.amount)
|
||||
self.denom = element.denom
|
||||
return self
|
||||
}
|
||||
}
|
27
src/libs/data/tx.js
Normal file
27
src/libs/data/tx.js
Normal file
@ -0,0 +1,27 @@
|
||||
import { sha256 } from '@cosmjs/crypto'
|
||||
import { fromBase64, toHex } from '@cosmjs/encoding'
|
||||
import Token from './token'
|
||||
|
||||
export default class Tx {
|
||||
constructor() {
|
||||
this.hash = ''
|
||||
this.fee = [new Token()]
|
||||
this.memo = ''
|
||||
this.messages = []
|
||||
this.signatures = []
|
||||
}
|
||||
|
||||
static create(element) {
|
||||
const self = new Tx()
|
||||
self.hash = ''
|
||||
self.fee = element.authInfo.fee.amount
|
||||
self.memo = element.body.memo
|
||||
self.messages = element.body.messages
|
||||
self.signatures = element.signatures
|
||||
return self
|
||||
}
|
||||
|
||||
setHash(raw) {
|
||||
this.hash = toHex(sha256(fromBase64(raw))).toUpperCase()
|
||||
}
|
||||
}
|
45
src/libs/data/wrapstdtx.js
Normal file
45
src/libs/data/wrapstdtx.js
Normal file
@ -0,0 +1,45 @@
|
||||
import compareVersions from 'compare-versions'
|
||||
import StdTx from './stdtx'
|
||||
|
||||
export default class WrapStdTx {
|
||||
constructor() {
|
||||
this.code = 0
|
||||
this.txhash = ''
|
||||
this.data = ''
|
||||
this.gas_used = ''
|
||||
this.gas_wanted = ''
|
||||
this.height = 0
|
||||
this.logs = []
|
||||
this.timestamp = ''
|
||||
this.tx = new StdTx()
|
||||
this.info = ''
|
||||
this.raw_log = ''
|
||||
}
|
||||
|
||||
static create(element, version = '0.40') {
|
||||
const self = new WrapStdTx()
|
||||
if (compareVersions(version, '0.40') < 1) {
|
||||
self.txhash = element.txhash
|
||||
self.data = element.data
|
||||
self.gas_used = element.gas_used
|
||||
self.gas_wanted = element.gas_wanted
|
||||
self.height = Number(element.height)
|
||||
self.logs = element.logs
|
||||
self.timestamp = element.timestamp
|
||||
self.tx = StdTx.create(element.tx)
|
||||
} else {
|
||||
self.code = element.tx_response.code
|
||||
self.txhash = element.tx_response.txhash
|
||||
self.data = element.tx_response.data
|
||||
self.gas_used = element.tx_response.gas_used
|
||||
self.gas_wanted = element.tx_response.gas_wanted
|
||||
self.height = Number(element.tx_response.height)
|
||||
self.info = element.tx_response.info
|
||||
self.logs = element.tx_response.logs
|
||||
self.timestamp = element.tx_response.timestamp
|
||||
self.tx = StdTx.create(element.tx, version)
|
||||
self.raw_log = element.tx_response.raw_log
|
||||
}
|
||||
return self
|
||||
}
|
||||
}
|
@ -3,7 +3,7 @@ import store from '@/store'
|
||||
import compareVersions from 'compare-versions'
|
||||
import {
|
||||
Proposal, ProposalTally, Proposer, StakingPool, Votes, Deposit,
|
||||
Validator, StakingParameters, Block, ValidatorDistribution, StakingDelegation,
|
||||
Validator, StakingParameters, Block, ValidatorDistribution, StakingDelegation, WrapStdTx,
|
||||
} from './data'
|
||||
|
||||
function commonProcess(res) {
|
||||
@ -11,14 +11,34 @@ function commonProcess(res) {
|
||||
}
|
||||
|
||||
// 头像
|
||||
export async function keybase(identity) {
|
||||
export function keybase(identity) {
|
||||
return fetch(`https://keybase.io/_/api/1.0/user/lookup.json?key_suffix=${identity}&fields=pictures`)
|
||||
.then(res => res.json())
|
||||
}
|
||||
|
||||
async function refetchVersion(chain) {
|
||||
await fetch(`${chain.api}/node_info`)
|
||||
.then(res => res.json())
|
||||
.then(json => {
|
||||
const sdk = json.application_version.build_deps.find(e => e.startsWith('github.com/cosmos/cosmos-sdk'))
|
||||
const re = /(\d+(\.\d+)*)/i
|
||||
const version = sdk.match(re)
|
||||
return version[0]
|
||||
})
|
||||
}
|
||||
|
||||
const chainAPI = class ChainFetch {
|
||||
getSelectedConfig() {
|
||||
this.config = store.state.chains.selected
|
||||
let chain = store.state.chains.selected
|
||||
const lschains = localStorage.getItem('chains')
|
||||
if (lschains) {
|
||||
chain = JSON.parse(lschains)[chain.chain_name]
|
||||
}
|
||||
if (!chain.sdk_version) {
|
||||
chain.sdk_version = refetchVersion(chain)
|
||||
}
|
||||
this.config = chain
|
||||
console.log(this.config)
|
||||
return this.config
|
||||
}
|
||||
|
||||
@ -30,6 +50,17 @@ const chainAPI = class ChainFetch {
|
||||
return this.get(`/blocks/${height}`).then(data => Block.create(data))
|
||||
}
|
||||
|
||||
async getTxs(hash) {
|
||||
const FIELD = 'sdk_version'
|
||||
const ver = this.getSelectedConfig() ? this.config.sdk_version : '0.41'
|
||||
console.log(ver, this.config[FIELD])
|
||||
// /cosmos/tx/v1beta1/txs/{hash}
|
||||
if (ver && compareVersions(ver, '0.40') < 1) {
|
||||
return this.get(`/txs/${hash}`).then(data => WrapStdTx.create(data, ver))
|
||||
}
|
||||
return this.get(`/cosmos/tx/v1beta1/txs/${hash}`).then(data => WrapStdTx.create(data, ver))
|
||||
}
|
||||
|
||||
async getValidatorDistribution(address) {
|
||||
return this.get(`/distribution/validators/${address}`).then(data => {
|
||||
const ret = ValidatorDistribution.create(commonProcess(data))
|
||||
|
@ -110,6 +110,34 @@ const router = new VueRouter({
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: '/:chain/block/:height',
|
||||
name: 'block',
|
||||
component: () => import('@/views/Block.vue'),
|
||||
meta: {
|
||||
pageTitle: 'Block',
|
||||
breadcrumb: [
|
||||
{
|
||||
text: 'Block',
|
||||
active: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: '/:chain/tx/:hash',
|
||||
name: 'transaction',
|
||||
component: () => import('@/views/Transaction.vue'),
|
||||
meta: {
|
||||
pageTitle: 'Transaction',
|
||||
breadcrumb: [
|
||||
{
|
||||
text: 'Transaction',
|
||||
active: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: '/login',
|
||||
name: 'login',
|
||||
@ -139,7 +167,7 @@ router.beforeEach((to, from, next) => {
|
||||
if (has > -1) {
|
||||
const chain = store.state.chains.config[c]
|
||||
store.commit('select', { chain_name: c })
|
||||
if (chain.sdk_version === undefined) {
|
||||
if (chain.sdk_version) {
|
||||
fetch(`${chain.api}/node_info`)
|
||||
.then(res => res.json())
|
||||
.then(json => {
|
||||
|
@ -1,9 +1,32 @@
|
||||
const chains = {}
|
||||
const configs = require.context('.', false, /\.json$/)
|
||||
let chains = {}
|
||||
|
||||
configs.keys().forEach(k => {
|
||||
const c = configs(k)
|
||||
chains[c.chain_name] = c
|
||||
const localChains = localStorage.getItem('chains')
|
||||
if (localChains) {
|
||||
chains = JSON.parse(localChains)
|
||||
} else {
|
||||
const configs = require.context('.', false, /\.json$/)
|
||||
|
||||
configs.keys().forEach(k => {
|
||||
const c = configs(k)
|
||||
chains[c.chain_name] = c
|
||||
})
|
||||
localStorage.setItem('chains', JSON.stringify(chains))
|
||||
}
|
||||
|
||||
Object.keys(chains).forEach(key => {
|
||||
const chain = chains[key]
|
||||
fetch(`${chain.api}/node_info`)
|
||||
.then(res => res.json())
|
||||
.then(json => {
|
||||
const sdk = json.application_version.build_deps.find(e => e.startsWith('github.com/cosmos/cosmos-sdk'))
|
||||
const re = /(\d+(\.\d+)*)/i
|
||||
const version = sdk.match(re)
|
||||
// eslint-disable-next-line prefer-destructuring
|
||||
chain.sdk_version = version[0]
|
||||
localStorage.setItem('chains', JSON.stringify(chains))
|
||||
console.log(`${chain.api}/node_info`, localStorage.getItem('chains'))
|
||||
})
|
||||
.catch(e => console.log(`Failed get api vesion of ${key}`, e))
|
||||
})
|
||||
|
||||
export default {
|
||||
|
@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<b-table
|
||||
v-if="Array.isArray(tablefield)"
|
||||
:items="tablefield"
|
||||
:sticky-header="true"
|
||||
:no-border-collapse="true"
|
||||
@ -11,7 +12,10 @@
|
||||
v-else-if="isArrayText(data.value)"
|
||||
:tablefield="eval_value(data.value)"
|
||||
/>
|
||||
<span v-else>{{ data.value }}</span>
|
||||
<span
|
||||
v-else
|
||||
:title="data.value"
|
||||
>{{ formatText(data.value) }}</span>
|
||||
</template>
|
||||
</b-table>
|
||||
</template>
|
||||
@ -20,7 +24,9 @@
|
||||
import { BTable } from 'bootstrap-vue'
|
||||
// import fetch from 'node-fetch'
|
||||
|
||||
import { isToken, tokenFormatter } from '@/libs/data/data'
|
||||
import {
|
||||
abbr, isToken, toDay, tokenFormatter,
|
||||
} from '@/libs/data/data'
|
||||
// import { Proposal, Proposer } from '@/libs/data'
|
||||
// import { formatToken } from '@/libs/data/data'
|
||||
|
||||
@ -31,7 +37,7 @@ export default {
|
||||
},
|
||||
props: {
|
||||
tablefield: {
|
||||
type: Array,
|
||||
type: [Array, Object],
|
||||
default: () => [],
|
||||
},
|
||||
},
|
||||
@ -46,9 +52,16 @@ export default {
|
||||
return isToken(value)
|
||||
},
|
||||
isArrayText(value) {
|
||||
const has = String(value).startsWith('[')
|
||||
const has = String(value).startsWith('[') && String(value).endsWith(']')
|
||||
return has
|
||||
},
|
||||
formatText(value) {
|
||||
const reg = /^\d{4}.\d{1,2}.\d{1,2}T\d{2}:\d{2}:.+Z$/
|
||||
if (reg.test(value)) {
|
||||
return toDay(value)
|
||||
}
|
||||
return abbr(value, 40)
|
||||
},
|
||||
formatTokens(value) {
|
||||
return tokenFormatter(value)
|
||||
},
|
||||
|
95
src/views/Block.vue
Normal file
95
src/views/Block.vue
Normal file
@ -0,0 +1,95 @@
|
||||
<template>
|
||||
<div>
|
||||
<b-card title="Block Id">
|
||||
<object-field-component :tablefield="block.block_id" />
|
||||
</b-card>
|
||||
|
||||
<b-card title="Block Header">
|
||||
<object-field-component :tablefield="block.block.header" />
|
||||
</b-card>
|
||||
|
||||
<b-card
|
||||
v-if="block.block.data.txs"
|
||||
title="Transaction"
|
||||
>
|
||||
<b-table
|
||||
:items="txs"
|
||||
:fields="fields"
|
||||
responsive="sm"
|
||||
>
|
||||
<template #cell(hash)="data">
|
||||
<router-link :to="`../tx/${data.value}`">
|
||||
{{ data.value }}
|
||||
</router-link>
|
||||
</template>
|
||||
</b-table>
|
||||
</b-card>
|
||||
|
||||
<b-card
|
||||
v-if="block.block.evidence.evidence"
|
||||
title="Evidence"
|
||||
>
|
||||
<array-field-component :tablefield="block.block.evidence.evidence" />
|
||||
</b-card>
|
||||
|
||||
<b-card title="Last Commit">
|
||||
<object-field-component :tablefield="block.block.last_commit" />
|
||||
</b-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { BCard, BTable } from 'bootstrap-vue'
|
||||
import { fromBase64 } from '@cosmjs/encoding'
|
||||
import { decodeTxRaw } from '@cosmjs/proto-signing'
|
||||
import Tx from '@/libs/data/tx'
|
||||
import { abbrMessage, tokenFormatter } from '@/libs/data'
|
||||
import ObjectFieldComponent from './ObjectFieldComponent.vue'
|
||||
import ArrayFieldComponent from './ArrayFieldComponent.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
BCard,
|
||||
BTable,
|
||||
ObjectFieldComponent,
|
||||
ArrayFieldComponent,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
block: { block: { header: {}, data: {}, evidence: {} } },
|
||||
txs: null,
|
||||
fields: [
|
||||
{ key: 'hash' },
|
||||
{ key: 'fee', formatter: v => tokenFormatter(v) },
|
||||
{ key: 'messages', formatter: v => abbrMessage(v) },
|
||||
{ key: 'memo' },
|
||||
],
|
||||
}
|
||||
},
|
||||
created() {
|
||||
const { height } = this.$route.params
|
||||
this.$http.getBlockByHeight(height).then(res => {
|
||||
this.block = res
|
||||
const { txs } = res.block.data
|
||||
const array = []
|
||||
for (let i = 0; i <= txs.length; i += 1) {
|
||||
try {
|
||||
const origin = decodeTxRaw(fromBase64(txs[i]))
|
||||
const tx = Tx.create(origin)
|
||||
tx.setHash(txs[i])
|
||||
array.push(tx)
|
||||
console.log('tx', origin, tx)
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
}
|
||||
if (array.length > 0) this.txs = array
|
||||
console.log(this.txs)
|
||||
})
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
@ -1,5 +1,11 @@
|
||||
<template>
|
||||
<b-table-simple>
|
||||
<b-table-simple
|
||||
v-if="typeof tablefield === 'object'"
|
||||
hover
|
||||
small
|
||||
striped
|
||||
responsive
|
||||
>
|
||||
<b-tr
|
||||
v-for="(value, name) in tablefield"
|
||||
:key="name"
|
||||
@ -7,7 +13,7 @@
|
||||
<b-td
|
||||
style="text-transform: capitalize; vertical-align: top; width:200px"
|
||||
>
|
||||
{{ name.replaceAll('_',' ') }}
|
||||
{{ name }}
|
||||
</b-td>
|
||||
<b-td v-if="isTokenField(value)">
|
||||
{{ formatTokens( value ) }}
|
||||
@ -15,8 +21,31 @@
|
||||
<b-td v-else-if="Array.isArray(value)">
|
||||
<array-field-component :tablefield="value" />
|
||||
</b-td>
|
||||
<b-td
|
||||
v-else-if="typeof (value) ==='object'"
|
||||
hover
|
||||
>
|
||||
<b-tabs>
|
||||
<b-tab
|
||||
v-for="key in Object.keys(value)"
|
||||
:key="key"
|
||||
:title="key"
|
||||
variant="danger"
|
||||
>
|
||||
<array-field-component
|
||||
v-if="Array.isArray(value[key])"
|
||||
:tablefield="value[key]"
|
||||
/>
|
||||
<object-field-component
|
||||
v-else-if="typeof value[key] === 'object'"
|
||||
:tablefield="value[key]"
|
||||
/>
|
||||
<span v-else>{{ formatText(value[key]) }} </span>
|
||||
</b-tab>
|
||||
</b-tabs>
|
||||
</b-td>
|
||||
<b-td v-else>
|
||||
{{ value }}
|
||||
{{ formatText(value) }}
|
||||
</b-td>
|
||||
</b-tr>
|
||||
</b-table-simple>
|
||||
@ -24,15 +53,10 @@
|
||||
|
||||
<script>
|
||||
import {
|
||||
BTableSimple, BTr, BTd,
|
||||
BTableSimple, BTr, BTd, BTabs, BTab,
|
||||
} from 'bootstrap-vue'
|
||||
import { isToken, tokenFormatter } from '@/libs/data'
|
||||
import { abbr, isToken, tokenFormatter } from '@/libs/data'
|
||||
import ArrayFieldComponent from './ArrayFieldComponent.vue'
|
||||
// import fetch from 'node-fetch'
|
||||
|
||||
// import { tokenFormatter } from '@/libs/data/data'
|
||||
// import { Proposal, Proposer } from '@/libs/data'
|
||||
// import { formatToken } from '@/libs/data/data'
|
||||
|
||||
export default {
|
||||
name: 'ObjectFieldComponent',
|
||||
@ -40,15 +64,26 @@ export default {
|
||||
BTableSimple,
|
||||
BTr,
|
||||
BTd,
|
||||
BTabs,
|
||||
BTab,
|
||||
ArrayFieldComponent,
|
||||
},
|
||||
props: {
|
||||
tablefield: {
|
||||
type: Object,
|
||||
type: [Array, Object],
|
||||
default: () => {},
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
formatObject(value) {
|
||||
// console.log(value, typeof (value) === 'object', Object.keys(value))
|
||||
// if (typeof (value) === 'object' && Object.keys(value).length === 1) {
|
||||
// console.log(value)
|
||||
// return value[Object.keys(value)[0]]
|
||||
// }
|
||||
return value
|
||||
},
|
||||
formatText: v => abbr(v, 60),
|
||||
eval_value(value) {
|
||||
return Array.from(value)
|
||||
},
|
||||
@ -61,3 +96,7 @@ export default {
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
|
@ -293,7 +293,7 @@ export default {
|
||||
inProgress: 64,
|
||||
},
|
||||
selfDelegation: {
|
||||
balance: {},
|
||||
balance: { amount: 0 },
|
||||
},
|
||||
latestHeight: 0,
|
||||
accountAddress: '-',
|
||||
|
130
src/views/Transaction.vue
Normal file
130
src/views/Transaction.vue
Normal file
@ -0,0 +1,130 @@
|
||||
<template>
|
||||
<div>
|
||||
<b-card title="Baisc">
|
||||
<b-table-simple>
|
||||
<b-tr>
|
||||
<b-td style="width:200px">
|
||||
{{ 'txhash' }}
|
||||
</b-td><b-td>{{ tx.txhash }}</b-td>
|
||||
</b-tr>
|
||||
<b-tr>
|
||||
<b-td>
|
||||
{{ 'status' }}
|
||||
</b-td><b-td> <b-badge
|
||||
v-if="tx.code===0"
|
||||
variant="light-success"
|
||||
>
|
||||
Success
|
||||
</b-badge><b-badge
|
||||
v-else
|
||||
variant="light-danger"
|
||||
>
|
||||
Failed
|
||||
</b-badge><b v-if="tx.code > 0"> {{ tx.raw_log }}</b> </b-td>
|
||||
</b-tr>
|
||||
<b-tr>
|
||||
<b-td>
|
||||
{{ 'height' }}
|
||||
</b-td><b-td>{{ tx.height }}</b-td>
|
||||
</b-tr>
|
||||
<b-tr>
|
||||
<b-td>
|
||||
{{ 'timestamp' }}
|
||||
</b-td><b-td>{{ formatTime(tx.timestamp) }}</b-td>
|
||||
</b-tr>
|
||||
<b-tr>
|
||||
<b-td>
|
||||
{{ 'gas_used' }}
|
||||
</b-td><b-td>{{ tx.gas_used }}</b-td>
|
||||
</b-tr>
|
||||
<b-tr>
|
||||
<b-td>
|
||||
{{ 'gas_wanted' }}
|
||||
</b-td><b-td>{{ tx.gas_wanted }}</b-td>
|
||||
</b-tr>
|
||||
<b-tr>
|
||||
<b-td>
|
||||
{{ 'gas' }}
|
||||
</b-td><b-td>{{ tx.tx.gas }}</b-td>
|
||||
</b-tr>
|
||||
<b-tr>
|
||||
<b-td>
|
||||
{{ 'fee' }}
|
||||
</b-td><b-td>{{ formattoken(tx.tx.fee) }}</b-td>
|
||||
</b-tr>
|
||||
<b-tr>
|
||||
<b-td>
|
||||
{{ 'memo' }}
|
||||
</b-td><b-td>{{ tx.tx.memo }}</b-td>
|
||||
</b-tr>
|
||||
<b-tr>
|
||||
<b-td>
|
||||
{{ 'timeout_height' }}
|
||||
</b-td><b-td>{{ tx.tx.timeout_height }}</b-td>
|
||||
</b-tr>
|
||||
</b-table-simple>
|
||||
</b-card>
|
||||
|
||||
<b-card
|
||||
v-if="tx.tx.messages"
|
||||
:title="`Messages (total: ${tx.tx.messages.length})`"
|
||||
>
|
||||
<b-card-body
|
||||
v-for="(item, i) in tx.tx.messages "
|
||||
id="message"
|
||||
:key="i"
|
||||
class="message"
|
||||
>
|
||||
<object-field-component :tablefield="item" />
|
||||
</b-card-body>
|
||||
</b-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
BCard, BTableSimple, BTr, BTd, BBadge, BCardBody,
|
||||
} from 'bootstrap-vue'
|
||||
import { toDay, tokenFormatter } from '@/libs/data'
|
||||
import ObjectFieldComponent from './ObjectFieldComponent.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
BCard,
|
||||
BCardBody,
|
||||
BTableSimple,
|
||||
BTr,
|
||||
BTd,
|
||||
BBadge,
|
||||
ObjectFieldComponent,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
tx: { tx: {} },
|
||||
}
|
||||
},
|
||||
created() {
|
||||
const { hash } = this.$route.params
|
||||
this.$http.getTxs(hash).then(res => {
|
||||
console.log(res)
|
||||
this.tx = res
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
formattoken: v => tokenFormatter(v),
|
||||
formatTime: v => toDay(v),
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
#message {
|
||||
border-top-width: 2px;
|
||||
border-top-style: double;
|
||||
}
|
||||
#message table.table-hover tr td:hover {
|
||||
border-width: 1px;
|
||||
border: double;
|
||||
border-radius: 0.5px;
|
||||
}
|
||||
</style>
|
96
yarn.lock
96
yarn.lock
@ -957,6 +957,15 @@
|
||||
dependencies:
|
||||
bn.js "^4.11.8"
|
||||
|
||||
"@cosmjs/proto-signing@^0.25.6":
|
||||
version "0.25.6"
|
||||
resolved "https://registry.yarnpkg.com/@cosmjs/proto-signing/-/proto-signing-0.25.6.tgz#d9fc57b8e0a46cda97e192bd0435157b24949ff8"
|
||||
integrity sha512-JpQ+Vnv9s6i3x8f3Jo0lJZ3VMnj3R5sMgX+8ti1LtB7qEYRR85qbDrEG9hDGIKqJJabvrAuCHnO6hYi0vJEJHA==
|
||||
dependencies:
|
||||
"@cosmjs/amino" "^0.25.6"
|
||||
long "^4.0.0"
|
||||
protobufjs "~6.10.2"
|
||||
|
||||
"@cosmjs/utils@^0.25.6":
|
||||
version "0.25.6"
|
||||
resolved "https://registry.yarnpkg.com/@cosmjs/utils/-/utils-0.25.6.tgz#934d9a967180baa66163847616a74358732227ca"
|
||||
@ -1187,6 +1196,59 @@
|
||||
consola "^2.15.0"
|
||||
node-fetch "^2.6.1"
|
||||
|
||||
"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf"
|
||||
integrity sha1-m4sMxmPWaafY9vXQiToU00jzD78=
|
||||
|
||||
"@protobufjs/base64@^1.1.2":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@protobufjs/base64/-/base64-1.1.2.tgz#4c85730e59b9a1f1f349047dbf24296034bb2735"
|
||||
integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==
|
||||
|
||||
"@protobufjs/codegen@^2.0.4":
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.4.tgz#7ef37f0d010fb028ad1ad59722e506d9262815cb"
|
||||
integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==
|
||||
|
||||
"@protobufjs/eventemitter@^1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70"
|
||||
integrity sha1-NVy8mLr61ZePntCV85diHx0Ga3A=
|
||||
|
||||
"@protobufjs/fetch@^1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45"
|
||||
integrity sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=
|
||||
dependencies:
|
||||
"@protobufjs/aspromise" "^1.1.1"
|
||||
"@protobufjs/inquire" "^1.1.0"
|
||||
|
||||
"@protobufjs/float@^1.0.2":
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1"
|
||||
integrity sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=
|
||||
|
||||
"@protobufjs/inquire@^1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089"
|
||||
integrity sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=
|
||||
|
||||
"@protobufjs/path@^1.1.2":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d"
|
||||
integrity sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=
|
||||
|
||||
"@protobufjs/pool@^1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54"
|
||||
integrity sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=
|
||||
|
||||
"@protobufjs/utf8@^1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570"
|
||||
integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=
|
||||
|
||||
"@sindresorhus/is@^0.14.0":
|
||||
version "0.14.0"
|
||||
resolved "https://registry.nlark.com/@sindresorhus/is/download/@sindresorhus/is-0.14.0.tgz"
|
||||
@ -1349,6 +1411,11 @@
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/long@^4.0.1":
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.1.tgz#459c65fa1867dafe6a8f322c4c51695663cc55e9"
|
||||
integrity sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==
|
||||
|
||||
"@types/mime@^1":
|
||||
version "1.3.2"
|
||||
resolved "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz"
|
||||
@ -1374,6 +1441,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-11.11.6.tgz#df929d1bb2eee5afdda598a41930fe50b43eaa6a"
|
||||
integrity sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==
|
||||
|
||||
"@types/node@^13.7.0":
|
||||
version "13.13.52"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.13.52.tgz#03c13be70b9031baaed79481c0c0cfb0045e53f7"
|
||||
integrity sha512-s3nugnZumCC//n4moGGe6tkNMyYEdaDBitVjwPxXmR5lnMG5dHePinH2EdxkG3Rh1ghFHHixAG4NJhpJW1rthQ==
|
||||
|
||||
"@types/normalize-package-data@^2.4.0":
|
||||
version "2.4.1"
|
||||
resolved "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz"
|
||||
@ -7130,6 +7202,11 @@ loglevel@^1.6.8:
|
||||
resolved "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz"
|
||||
integrity sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw==
|
||||
|
||||
long@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28"
|
||||
integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==
|
||||
|
||||
longest@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npm.taobao.org/longest/download/longest-1.0.1.tgz"
|
||||
@ -8901,6 +8978,25 @@ proto-list@~1.2.1:
|
||||
resolved "https://registry.npm.taobao.org/proto-list/download/proto-list-1.2.4.tgz"
|
||||
integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=
|
||||
|
||||
protobufjs@~6.10.2:
|
||||
version "6.10.2"
|
||||
resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.10.2.tgz#b9cb6bd8ec8f87514592ba3fdfd28e93f33a469b"
|
||||
integrity sha512-27yj+04uF6ya9l+qfpH187aqEzfCF4+Uit0I9ZBQVqK09hk/SQzKa2MUqUpXaVa7LOFRg1TSSr3lVxGOk6c0SQ==
|
||||
dependencies:
|
||||
"@protobufjs/aspromise" "^1.1.2"
|
||||
"@protobufjs/base64" "^1.1.2"
|
||||
"@protobufjs/codegen" "^2.0.4"
|
||||
"@protobufjs/eventemitter" "^1.1.0"
|
||||
"@protobufjs/fetch" "^1.1.0"
|
||||
"@protobufjs/float" "^1.0.2"
|
||||
"@protobufjs/inquire" "^1.1.0"
|
||||
"@protobufjs/path" "^1.1.2"
|
||||
"@protobufjs/pool" "^1.1.0"
|
||||
"@protobufjs/utf8" "^1.1.0"
|
||||
"@types/long" "^4.0.1"
|
||||
"@types/node" "^13.7.0"
|
||||
long "^4.0.0"
|
||||
|
||||
proxy-addr@~2.0.5:
|
||||
version "2.0.7"
|
||||
resolved "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz"
|
||||
|
Loading…
Reference in New Issue
Block a user