Optimize quotes loading
This commit is contained in:
parent
ffa366ee25
commit
e34a82402f
@ -94,6 +94,8 @@ export default {
|
|||||||
store.commit('app/UPDATE_WINDOW_WIDTH', val)
|
store.commit('app/UPDATE_WINDOW_WIDTH', val)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
store.dispatch('chains/getQuotes')
|
||||||
|
|
||||||
return {
|
return {
|
||||||
skinClasses,
|
skinClasses,
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
"regen": "Regen Network",
|
"regen": "Regen Network",
|
||||||
"secret": "Secret Network",
|
"secret": "Secret Network",
|
||||||
"desmos": "Desmos",
|
"desmos": "Desmos",
|
||||||
"juno": "Juno Hera",
|
"juno": "Juno",
|
||||||
"certik": "Certik",
|
"certik": "Certik",
|
||||||
"sentinel": "Sentinel",
|
"sentinel": "Sentinel",
|
||||||
|
|
||||||
@ -26,7 +26,8 @@
|
|||||||
"blockchains": "Blockchains",
|
"blockchains": "Blockchains",
|
||||||
"uptime": "Uptime",
|
"uptime": "Uptime",
|
||||||
|
|
||||||
"gravity": "Gravity",
|
"gravity": "Gravity(WIP)",
|
||||||
|
"pools": "Pools(WIP)",
|
||||||
|
|
||||||
"proposal_id": "Proposal ID",
|
"proposal_id": "Proposal ID",
|
||||||
"proposal_type": "Proposal Type",
|
"proposal_type": "Proposal Type",
|
||||||
|
@ -13,6 +13,7 @@ import dayjs from 'dayjs'
|
|||||||
import duration from 'dayjs/plugin/duration'
|
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'
|
||||||
|
import { $themeColors } from '@themeConfig'
|
||||||
|
|
||||||
dayjs.extend(localeData)
|
dayjs.extend(localeData)
|
||||||
dayjs.extend(duration)
|
dayjs.extend(duration)
|
||||||
@ -76,6 +77,41 @@ export function addressEnCode(prefix, pubkey) {
|
|||||||
return Bech32.encode(prefix, pubkey)
|
return Bech32.encode(prefix, pubkey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getUserCurrency() {
|
||||||
|
const currency = localStorage.getItem('currency')
|
||||||
|
return currency || 'usd'
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setUserCurrency(currency) {
|
||||||
|
localStorage.setItem('currency', currency)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function chartColors() {
|
||||||
|
const colors = ['#6610f2', '#20c997', '#000000', '#FF0000',
|
||||||
|
'#800000', '#FFFF00', '#808000', '#00FF00', '#008000', '#00FFFF',
|
||||||
|
'#008080', '#0000FF', '#000080', '#FF00FF', '#800080']
|
||||||
|
return Object.values($themeColors).concat(colors)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getUserCurrencySign() {
|
||||||
|
let s = ''
|
||||||
|
switch (getUserCurrency()) {
|
||||||
|
case 'cny':
|
||||||
|
case 'jpy':
|
||||||
|
s = '¥'
|
||||||
|
break
|
||||||
|
case 'krw':
|
||||||
|
s = '₩'
|
||||||
|
break
|
||||||
|
case 'eur':
|
||||||
|
s = '€'
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
s = '$'
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
export function consensusPubkeyToHexAddress(consensusPubkey) {
|
export function consensusPubkeyToHexAddress(consensusPubkey) {
|
||||||
let raw = null
|
let raw = null
|
||||||
if (typeof consensusPubkey === 'object') {
|
if (typeof consensusPubkey === 'object') {
|
||||||
@ -218,7 +254,7 @@ export function isToken(value) {
|
|||||||
|
|
||||||
export function formatTokenDenom(tokenDenom) {
|
export function formatTokenDenom(tokenDenom) {
|
||||||
if (tokenDenom) {
|
if (tokenDenom) {
|
||||||
let denom = tokenDenom.toUpperCase()
|
let denom = tokenDenom.denom_trace ? tokenDenom.denom_trace.base_denom.toUpperCase() : tokenDenom.toUpperCase()
|
||||||
if (denom.charAt(0) === 'U') {
|
if (denom.charAt(0) === 'U') {
|
||||||
denom = denom.substring(1)
|
denom = denom.substring(1)
|
||||||
} else if (denom === 'BASECRO') {
|
} else if (denom === 'BASECRO') {
|
||||||
|
@ -328,6 +328,7 @@ const chainAPI = class ChainFetch {
|
|||||||
return ChainFetch.fetchCoinMarketCap(`/quote/${symbol}`)
|
return ChainFetch.fetchCoinMarketCap(`/quote/${symbol}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tx Submit
|
||||||
async broadcastTx(bodyBytes, config = null) {
|
async broadcastTx(bodyBytes, config = null) {
|
||||||
const txString = toBase64(TxRaw.encode(bodyBytes).finish())
|
const txString = toBase64(TxRaw.encode(bodyBytes).finish())
|
||||||
const txRaw = {
|
const txRaw = {
|
||||||
@ -365,6 +366,15 @@ const chainAPI = class ChainFetch {
|
|||||||
// const response = axios.post((config ? config.api : this.config.api) + url, data)
|
// const response = axios.post((config ? config.api : this.config.api) + url, data)
|
||||||
return response.json() // parses JSON response into native JavaScript objects
|
return response.json() // parses JSON response into native JavaScript objects
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Custom Module
|
||||||
|
async getOsmosisPools() {
|
||||||
|
return this.get('/osmosis/gamm/v1beta1/pools')
|
||||||
|
}
|
||||||
|
|
||||||
|
async getOsmosisIncentivesPools() {
|
||||||
|
return this.get('/osmosis/pool-incentives/v1beta1/incentivized_pools')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default chainAPI
|
export default chainAPI
|
||||||
|
11
src/libs/osmos.js
Normal file
11
src/libs/osmos.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import fetch from 'node-fetch'
|
||||||
|
|
||||||
|
export default class OsmosAPI {
|
||||||
|
static async get(url) {
|
||||||
|
return fetch(url)
|
||||||
|
}
|
||||||
|
|
||||||
|
static async getPools() {
|
||||||
|
return OsmosAPI.get('/osmosis/gamm/v1beta1/pools')
|
||||||
|
}
|
||||||
|
}
|
@ -26,11 +26,16 @@ const modules = [
|
|||||||
title: 'uptime',
|
title: 'uptime',
|
||||||
route: 'uptime',
|
route: 'uptime',
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// scope: 'cosmos',
|
scope: 'cosmos',
|
||||||
// title: 'gravity',
|
title: 'gravity',
|
||||||
// route: 'gravity',
|
route: 'gravity',
|
||||||
// },
|
},
|
||||||
|
{
|
||||||
|
scope: 'osmosis',
|
||||||
|
title: 'pools',
|
||||||
|
route: 'osmosis-pool',
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
function processMenu() {
|
function processMenu() {
|
||||||
|
@ -258,8 +258,10 @@ const router = new VueRouter({
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
// custom modules for specified chains
|
||||||
|
// 1. cosmos
|
||||||
{
|
{
|
||||||
path: '/cosmos/gravity',
|
path: '/:chain/cosmos/pools',
|
||||||
name: 'gravity',
|
name: 'gravity',
|
||||||
component: () => import('@/views/GravityPool.vue'),
|
component: () => import('@/views/GravityPool.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
@ -272,6 +274,22 @@ const router = new VueRouter({
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
// 2. OSMOSIS
|
||||||
|
{
|
||||||
|
path: '/:chain/osmosis/pools',
|
||||||
|
name: 'osmosis-pool',
|
||||||
|
component: () => import('@/views/OsmosisPools.vue'),
|
||||||
|
meta: {
|
||||||
|
pageTitle: 'Pools',
|
||||||
|
breadcrumb: [
|
||||||
|
{
|
||||||
|
text: 'Pools',
|
||||||
|
active: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// common modules
|
||||||
{
|
{
|
||||||
path: '/user/login',
|
path: '/user/login',
|
||||||
name: 'login',
|
name: 'login',
|
||||||
|
@ -48,6 +48,7 @@ export default {
|
|||||||
avatars: {},
|
avatars: {},
|
||||||
height: 0,
|
height: 0,
|
||||||
ibcChannels: {},
|
ibcChannels: {},
|
||||||
|
quotes: {},
|
||||||
},
|
},
|
||||||
getters: {
|
getters: {
|
||||||
getchains: state => state.chains,
|
getchains: state => state.chains,
|
||||||
@ -69,6 +70,15 @@ export default {
|
|||||||
setChannels(state, { chain, channels }) {
|
setChannels(state, { chain, channels }) {
|
||||||
state.chains.ibcChannels[chain] = channels
|
state.chains.ibcChannels[chain] = channels
|
||||||
},
|
},
|
||||||
|
setQuotes(state, quotes) {
|
||||||
|
state.quotes = quotes
|
||||||
|
},
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
async getQuotes(context) {
|
||||||
|
fetch('https://price.ping.pub/quotes').then(data => data.json()).then(data => {
|
||||||
|
context.commit('setQuotes', data)
|
||||||
|
})
|
||||||
|
},
|
||||||
},
|
},
|
||||||
actions: {},
|
|
||||||
}
|
}
|
||||||
|
73
src/views/ChartComponentDoughnut.vue
Normal file
73
src/views/ChartComponentDoughnut.vue
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
<template>
|
||||||
|
<chartjs-component-doughnut-chart
|
||||||
|
:height="height"
|
||||||
|
:width="width"
|
||||||
|
:data="data"
|
||||||
|
:chart-data="data"
|
||||||
|
:options="options"
|
||||||
|
class="mb-3"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { percent } from '@/libs/data'
|
||||||
|
import { $themeColors } from '@themeConfig'
|
||||||
|
|
||||||
|
import ChartjsComponentDoughnutChart from './ChartjsComponentDoughnutChart.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'ChartDoughnut',
|
||||||
|
components: {
|
||||||
|
ChartjsComponentDoughnutChart,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
height: {
|
||||||
|
type: Number,
|
||||||
|
default: 235,
|
||||||
|
},
|
||||||
|
width: {
|
||||||
|
type: Number,
|
||||||
|
default: 235,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
options: {
|
||||||
|
responsive: true,
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
responsiveAnimationDuration: 500,
|
||||||
|
cutoutPercentage: 60,
|
||||||
|
legend: {
|
||||||
|
display: true,
|
||||||
|
title: {
|
||||||
|
display: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
tooltips: {
|
||||||
|
callbacks: {
|
||||||
|
label(tooltipItem, data) {
|
||||||
|
const label = data.datasets[0].labels[tooltipItem.index] || ''
|
||||||
|
const value = data.datasets[0].data[tooltipItem.index]
|
||||||
|
const total = data.datasets[0].data.reduce((t, c) => t + c)
|
||||||
|
const output = ` ${label} : ${percent(value / total)} %`
|
||||||
|
return output
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Updated default tooltip UI
|
||||||
|
shadowOffsetX: 1,
|
||||||
|
shadowOffsetY: 1,
|
||||||
|
shadowBlur: 8,
|
||||||
|
// shadowColor: chartColors.tooltipShadow,
|
||||||
|
backgroundColor: $themeColors.light,
|
||||||
|
titleFontColor: $themeColors.dark,
|
||||||
|
bodyFontColor: $themeColors.dark,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
31
src/views/ChartjsComponentBar.vue
Normal file
31
src/views/ChartjsComponentBar.vue
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<script>
|
||||||
|
import { Bar, mixins } from 'vue-chartjs'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
extends: Bar,
|
||||||
|
mixins: [mixins.reactiveProp],
|
||||||
|
props: {
|
||||||
|
// options: {
|
||||||
|
// type: Object,
|
||||||
|
// default: null,
|
||||||
|
// },
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
options: {
|
||||||
|
plugins: {
|
||||||
|
legend: {
|
||||||
|
display: false,
|
||||||
|
labels: {
|
||||||
|
color: 'rgb(255, 99, 132)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.renderChart(this.chartData, this.options)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
110
src/views/OsmosisPools.vue
Normal file
110
src/views/OsmosisPools.vue
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
<template>
|
||||||
|
<div class="container-md">
|
||||||
|
-------
|
||||||
|
<b-row class="match-height">
|
||||||
|
<b-col
|
||||||
|
v-for="(data,index) in pools.pools"
|
||||||
|
:key="index"
|
||||||
|
md="4"
|
||||||
|
sm="6"
|
||||||
|
>
|
||||||
|
<router-link :to="data.id">
|
||||||
|
<b-card
|
||||||
|
v-if="data"
|
||||||
|
class="earnings-card text-left"
|
||||||
|
>
|
||||||
|
<b-row>
|
||||||
|
<b-col cols="8">
|
||||||
|
<b-card-title class="mb-1 text-uppercase">
|
||||||
|
#{{ data.id }} {{ formatDenom(data.reserve_coin_denoms[0]) }} - {{ formatDenom(data.reserve_coin_denoms[1]) }}<small class="font-small-2"> xx</small>
|
||||||
|
</b-card-title>
|
||||||
|
<div class="font-small-2">
|
||||||
|
Height
|
||||||
|
</div>
|
||||||
|
<h5 class="mb-1">
|
||||||
|
{{ data.height || '0' }}
|
||||||
|
</h5>
|
||||||
|
<b-card-text class="text-muted font-small-2">
|
||||||
|
<span class="font-weight-bolder">{{ data.pool_coin_denom || '...' }}</span>
|
||||||
|
</b-card-text>
|
||||||
|
</b-col>
|
||||||
|
<b-col
|
||||||
|
cols="4"
|
||||||
|
>
|
||||||
|
<b-avatar
|
||||||
|
:src="data.logo"
|
||||||
|
class="mt-1 badge-minimal"
|
||||||
|
variant="light-primary"
|
||||||
|
rounded
|
||||||
|
size="82"
|
||||||
|
badge
|
||||||
|
:badge-variant="data.variant"
|
||||||
|
/></b-col>
|
||||||
|
</b-row>
|
||||||
|
</b-card>
|
||||||
|
</router-link>
|
||||||
|
</b-col>
|
||||||
|
</b-row>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
BCard, BCardTitle, VBTooltip, BRow, BCol,
|
||||||
|
} from 'bootstrap-vue'
|
||||||
|
import { formatTokenDenom } from '@/libs/data'
|
||||||
|
// import fetch from 'node-fetch'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
BRow,
|
||||||
|
BCol,
|
||||||
|
BCard,
|
||||||
|
BCardTitle,
|
||||||
|
},
|
||||||
|
directives: {
|
||||||
|
'b-tooltip': VBTooltip,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
pools: [],
|
||||||
|
ibcDenom: {},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
// const api = new OsmosAPI()
|
||||||
|
this.$http.getOsmosisIncentivesPools().then(res => {
|
||||||
|
console.log(res)
|
||||||
|
})
|
||||||
|
// this.$http.getGravityPools().then(res => {
|
||||||
|
// this.pools = res
|
||||||
|
// res.pools.forEach(x => {
|
||||||
|
// const denom1 = x.reserve_coin_denoms[0]
|
||||||
|
// const denom2 = x.reserve_coin_denoms[1]
|
||||||
|
// if (denom1.startsWith('ibc')) {
|
||||||
|
// this.$http.getIBCDenomTrace(denom1).then(denom => {
|
||||||
|
// this.$set(this.ibcDenom, denom1, denom)
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// if (denom2.startsWith('ibc')) {
|
||||||
|
// this.$http.getIBCDenomTrace(denom2).then(denom => {
|
||||||
|
// this.$set(this.ibcDenom, denom2, denom)
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
this.islive = false
|
||||||
|
clearInterval(this.timer)
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
formatDenom(v) {
|
||||||
|
// console.log(v, this.ibcDenom[v])
|
||||||
|
const denom = (v.startsWith('ibc') ? this.ibcDenom[v].denom_trace.base_denom : v)
|
||||||
|
return formatTokenDenom(denom)
|
||||||
|
},
|
||||||
|
length: v => (Array.isArray(v) ? v.length : 0),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
@ -72,7 +72,7 @@
|
|||||||
<h6 class="mb-0">
|
<h6 class="mb-0">
|
||||||
Consensus Public Address
|
Consensus Public Address
|
||||||
</h6>
|
</h6>
|
||||||
<small @click="copy(consensusPubkey)">{{ consensusPubkey }}</small>
|
<small @click="copy(JSON.stringify(consensusPubkey))">{{ consensusPubkey }}</small>
|
||||||
</b-media-body>
|
</b-media-body>
|
||||||
</b-media>
|
</b-media>
|
||||||
<b-media
|
<b-media
|
||||||
|
@ -64,23 +64,24 @@
|
|||||||
<b-card-body class="pl-0 pr-0">
|
<b-card-body class="pl-0 pr-0">
|
||||||
<b-row>
|
<b-row>
|
||||||
<b-col
|
<b-col
|
||||||
class="border-right"
|
|
||||||
xm="12"
|
xm="12"
|
||||||
md="4"
|
md="4"
|
||||||
>
|
>
|
||||||
<chartjs-component-doughnut-chart
|
<chart-component-doughnut
|
||||||
v-if="chartData"
|
v-if="chartData"
|
||||||
:height="235"
|
:height="235"
|
||||||
:width="235"
|
:width="235"
|
||||||
:data="chartData"
|
:data="chartData"
|
||||||
:chart-data="chartData"
|
|
||||||
:options="doughnutChart.options"
|
|
||||||
class="mb-3"
|
class="mb-3"
|
||||||
/>
|
/>
|
||||||
</b-col>
|
</b-col>
|
||||||
|
<b-col
|
||||||
|
class="border-left d-none d-md-block"
|
||||||
|
md="1"
|
||||||
|
/>
|
||||||
<b-col
|
<b-col
|
||||||
xm="12"
|
xm="12"
|
||||||
md="8"
|
md="7"
|
||||||
>
|
>
|
||||||
<!-- tokens -->
|
<!-- tokens -->
|
||||||
<div
|
<div
|
||||||
@ -104,12 +105,12 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="d-flex flex-column">
|
<div class="d-flex flex-column">
|
||||||
<span class="text-right">{{ formatAmount(token.amount) }} {{ formatDenom(token.denom) }}</span>
|
<span class="text-right">{{ formatAmount(token.amount) }} {{ formatDenom(token.denom) }}</span>
|
||||||
<small class="text-right">${{ token.currency }}</small>
|
<small class="text-right">{{ currency }}{{ token.currency }}</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!--/ tokens -->
|
<!--/ tokens -->
|
||||||
<div class="text-right border-top pt-1">
|
<div class="text-right border-top pt-1">
|
||||||
<h2>Total: ${{ assetTable.currency }}</h2>
|
<h2>Total: {{ currency }}{{ assetTable.currency }}</h2>
|
||||||
</div>
|
</div>
|
||||||
</b-col>
|
</b-col>
|
||||||
</b-row>
|
</b-row>
|
||||||
@ -363,17 +364,16 @@ import Ripple from 'vue-ripple-directive'
|
|||||||
import VueQr from 'vue-qr'
|
import VueQr from 'vue-qr'
|
||||||
import chainAPI from '@/libs/fetch'
|
import chainAPI from '@/libs/fetch'
|
||||||
import {
|
import {
|
||||||
formatToken, formatTokenAmount, formatTokenDenom, getStakingValidatorOperator, percent, tokenFormatter, toDay, toDuration, abbrMessage, abbrAddress,
|
formatToken, formatTokenAmount, formatTokenDenom, getStakingValidatorOperator, percent, tokenFormatter, toDay, toDuration, abbrMessage, abbrAddress, getUserCurrency, getUserCurrencySign, chartColors,
|
||||||
} from '@/libs/data'
|
} from '@/libs/data'
|
||||||
import { $themeColors } from '@themeConfig'
|
|
||||||
import ObjectFieldComponent from './ObjectFieldComponent.vue'
|
import ObjectFieldComponent from './ObjectFieldComponent.vue'
|
||||||
import ChartjsComponentDoughnutChart from './ChartjsComponentDoughnutChart.vue'
|
|
||||||
import OperationTransferComponent from './OperationTransferComponent.vue'
|
import OperationTransferComponent from './OperationTransferComponent.vue'
|
||||||
import OperationWithdrawComponent from './OperationWithdrawComponent.vue'
|
import OperationWithdrawComponent from './OperationWithdrawComponent.vue'
|
||||||
import OperationUnbondComponent from './OperationUnbondComponent.vue'
|
import OperationUnbondComponent from './OperationUnbondComponent.vue'
|
||||||
import OperationDelegateComponent from './OperationDelegateComponent.vue'
|
import OperationDelegateComponent from './OperationDelegateComponent.vue'
|
||||||
import OperationRedelegateComponent from './OperationRedelegateComponent.vue'
|
import OperationRedelegateComponent from './OperationRedelegateComponent.vue'
|
||||||
import OperationTransfer2Component from './OperationTransfer2Component.vue'
|
import OperationTransfer2Component from './OperationTransfer2Component.vue'
|
||||||
|
import ChartComponentDoughnut from './ChartComponentDoughnut.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@ -398,13 +398,13 @@ export default {
|
|||||||
// eslint-disable-next-line vue/no-unused-components
|
// eslint-disable-next-line vue/no-unused-components
|
||||||
ToastificationContent,
|
ToastificationContent,
|
||||||
ObjectFieldComponent,
|
ObjectFieldComponent,
|
||||||
ChartjsComponentDoughnutChart,
|
|
||||||
OperationTransferComponent,
|
OperationTransferComponent,
|
||||||
OperationWithdrawComponent,
|
OperationWithdrawComponent,
|
||||||
OperationDelegateComponent,
|
OperationDelegateComponent,
|
||||||
OperationRedelegateComponent,
|
OperationRedelegateComponent,
|
||||||
OperationUnbondComponent,
|
OperationUnbondComponent,
|
||||||
OperationTransfer2Component,
|
OperationTransfer2Component,
|
||||||
|
ChartComponentDoughnut,
|
||||||
},
|
},
|
||||||
directives: {
|
directives: {
|
||||||
'b-modal': VBModal,
|
'b-modal': VBModal,
|
||||||
@ -414,6 +414,7 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
const { address } = this.$route.params
|
const { address } = this.$route.params
|
||||||
return {
|
return {
|
||||||
|
currency: getUserCurrencySign(),
|
||||||
selectedValidator: '',
|
selectedValidator: '',
|
||||||
totalCurrency: 0,
|
totalCurrency: 0,
|
||||||
address,
|
address,
|
||||||
@ -426,39 +427,6 @@ export default {
|
|||||||
unbonding: [],
|
unbonding: [],
|
||||||
quotes: {},
|
quotes: {},
|
||||||
transactions: [],
|
transactions: [],
|
||||||
doughnutChart: {
|
|
||||||
options: {
|
|
||||||
responsive: true,
|
|
||||||
maintainAspectRatio: false,
|
|
||||||
responsiveAnimationDuration: 500,
|
|
||||||
cutoutPercentage: 60,
|
|
||||||
legend: {
|
|
||||||
display: true,
|
|
||||||
title: {
|
|
||||||
display: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
tooltips: {
|
|
||||||
callbacks: {
|
|
||||||
label(tooltipItem, data) {
|
|
||||||
const label = data.datasets[0].labels[tooltipItem.index] || ''
|
|
||||||
const value = data.datasets[0].data[tooltipItem.index]
|
|
||||||
const total = data.datasets[0].data.reduce((t, c) => t + c)
|
|
||||||
const output = ` ${label} : ${percent(value / total)} %`
|
|
||||||
return output
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// Updated default tooltip UI
|
|
||||||
shadowOffsetX: 1,
|
|
||||||
shadowOffsetY: 1,
|
|
||||||
shadowBlur: 8,
|
|
||||||
// shadowColor: chartColors.tooltipShadow,
|
|
||||||
// backgroundColor: $themeColors.light,
|
|
||||||
// titleFontColor: $themeColors.dark,
|
|
||||||
// bodyFontColor: $themeColors.dark,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -581,7 +549,7 @@ export default {
|
|||||||
{
|
{
|
||||||
labels: Object.keys(data),
|
labels: Object.keys(data),
|
||||||
data: Object.values(data),
|
data: Object.values(data),
|
||||||
backgroundColor: [$themeColors.primary, $themeColors.success, $themeColors.warning, $themeColors.danger, $themeColors.info],
|
backgroundColor: chartColors,
|
||||||
borderWidth: 0,
|
borderWidth: 0,
|
||||||
pointStyle: 'rectRounded',
|
pointStyle: 'rectRounded',
|
||||||
},
|
},
|
||||||
@ -680,10 +648,10 @@ export default {
|
|||||||
formatCurrency(amount, denom) {
|
formatCurrency(amount, denom) {
|
||||||
const qty = this.formatAmount(amount)
|
const qty = this.formatAmount(amount)
|
||||||
const d2 = this.formatDenom(denom)
|
const d2 = this.formatDenom(denom)
|
||||||
const userCurrency = 'USD'
|
const userCurrency = getUserCurrency()
|
||||||
const quote = this.quotes[d2]
|
const quote = this.$store.state.chains.quotes[d2]
|
||||||
if (quote && quote.quote) {
|
if (quote) {
|
||||||
const { price } = quote.quote[userCurrency]
|
const price = quote[userCurrency]
|
||||||
return parseFloat((qty * price).toFixed(2))
|
return parseFloat((qty * price).toFixed(2))
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
|
@ -1,5 +1,57 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
|
<b-card border-variant="primary">
|
||||||
|
<b-row class="mx-0">
|
||||||
|
<b-col
|
||||||
|
md="4"
|
||||||
|
>
|
||||||
|
<b-dropdown
|
||||||
|
:text="`Currency: ${currency2.toUpperCase()}`"
|
||||||
|
size="sm"
|
||||||
|
class="text-uppercase"
|
||||||
|
variant="primary"
|
||||||
|
>
|
||||||
|
<b-dropdown-item @click="setCurrency('usd')">
|
||||||
|
USD
|
||||||
|
</b-dropdown-item>
|
||||||
|
<b-dropdown-item @click="setCurrency('cny')">
|
||||||
|
CNY (人民币)
|
||||||
|
</b-dropdown-item>
|
||||||
|
<b-dropdown-item @click="setCurrency('eur')">
|
||||||
|
EUR (Euro)
|
||||||
|
</b-dropdown-item>
|
||||||
|
<b-dropdown-item @click="setCurrency('jpy')">
|
||||||
|
JPY (日本円)
|
||||||
|
</b-dropdown-item>
|
||||||
|
<b-dropdown-item @click="setCurrency('hkd')">
|
||||||
|
HKD (港幣)
|
||||||
|
</b-dropdown-item>
|
||||||
|
<b-dropdown-item @click="setCurrency('sgd')">
|
||||||
|
SGD
|
||||||
|
</b-dropdown-item>
|
||||||
|
<b-dropdown-item @click="setCurrency('krw')">
|
||||||
|
KRW (대한민국원)
|
||||||
|
</b-dropdown-item>
|
||||||
|
</b-dropdown>
|
||||||
|
<h2 class="my-1">
|
||||||
|
{{ currency }}{{ calculateTotal }}
|
||||||
|
</h2>
|
||||||
|
<!-- chart -->
|
||||||
|
<chart-component-doughnut
|
||||||
|
:height="235"
|
||||||
|
:width="235"
|
||||||
|
:data="calculateChartDoughnut"
|
||||||
|
class="mb-3"
|
||||||
|
/>
|
||||||
|
</b-col>
|
||||||
|
<b-col md="8">
|
||||||
|
<chartjs-component-bar
|
||||||
|
:height="135.0"
|
||||||
|
:chart-data="calculateChartBar"
|
||||||
|
/>
|
||||||
|
</b-col>
|
||||||
|
</b-row>
|
||||||
|
</b-card>
|
||||||
|
|
||||||
<b-tabs
|
<b-tabs
|
||||||
v-for="item,index in accounts"
|
v-for="item,index in accounts"
|
||||||
@ -81,7 +133,7 @@
|
|||||||
variant="light-primary"
|
variant="light-primary"
|
||||||
rounded
|
rounded
|
||||||
/>
|
/>
|
||||||
<h3>${{ formatBalance(balances[acc.addr]) }}</h3>
|
<h3>{{ currency }}{{ formatBalance(acc.addr) }}</h3>
|
||||||
</div>
|
</div>
|
||||||
<small
|
<small
|
||||||
class="pl-1 float-right text-muted text-overflow "
|
class="pl-1 float-right text-muted text-overflow "
|
||||||
@ -91,7 +143,7 @@
|
|||||||
</small>
|
</small>
|
||||||
</b-col>
|
</b-col>
|
||||||
</b-row>
|
</b-row>
|
||||||
<b-row v-if="balances[acc.addr]">
|
<b-row class="d-none">
|
||||||
<b-col>
|
<b-col>
|
||||||
<b-tabs
|
<b-tabs
|
||||||
active-nav-item-class="font-weight-bold text-second"
|
active-nav-item-class="font-weight-bold text-second"
|
||||||
@ -107,7 +159,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="d-flex flex-column text-right">
|
<div class="d-flex flex-column text-right">
|
||||||
<span class="font-weight-bold mb-0">{{ formatAmount(b.amount) }}</span>
|
<span class="font-weight-bold mb-0">{{ formatAmount(b.amount) }}</span>
|
||||||
<span class="font-small-2 text-muted text-nowrap">${{ formatCurrency(b.amount, b.denom) }}</span>
|
<span class="font-small-2 text-muted text-nowrap">{{ currency }}{{ formatCurrency(b.amount, b.denom) }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</b-tab>
|
</b-tab>
|
||||||
@ -118,7 +170,6 @@
|
|||||||
</b-card>
|
</b-card>
|
||||||
</b-col>
|
</b-col>
|
||||||
</b-row>
|
</b-row>
|
||||||
|
|
||||||
</b-tab>
|
</b-tab>
|
||||||
</b-tabs>
|
</b-tabs>
|
||||||
|
|
||||||
@ -136,18 +187,20 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import chainAPI from '@/libs/fetch'
|
|
||||||
import {
|
import {
|
||||||
BCard, BCardHeader, BCardTitle, BCardBody, VBModal, BRow, BCol, BTabs, BTab, BAvatar, BDropdown, BDropdownItem,
|
BCard, BCardHeader, BCardTitle, BCardBody, VBModal, BRow, BCol, BTabs, BTab, BAvatar, BDropdown, BDropdownItem,
|
||||||
} from 'bootstrap-vue'
|
} from 'bootstrap-vue'
|
||||||
import Ripple from 'vue-ripple-directive'
|
import Ripple from 'vue-ripple-directive'
|
||||||
import FeatherIcon from '@/@core/components/feather-icon/FeatherIcon.vue'
|
import FeatherIcon from '@/@core/components/feather-icon/FeatherIcon.vue'
|
||||||
import {
|
import {
|
||||||
formatTokenAmount, formatTokenDenom, getLocalAccounts, getLocalChains,
|
chartColors,
|
||||||
|
formatTokenAmount, formatTokenDenom, getLocalAccounts, getLocalChains, getUserCurrency, getUserCurrencySign, setUserCurrency,
|
||||||
} from '@/libs/data'
|
} from '@/libs/data'
|
||||||
import ToastificationContent from '@core/components/toastification/ToastificationContent.vue'
|
import ToastificationContent from '@core/components/toastification/ToastificationContent.vue'
|
||||||
import OperationTransferComponent from './OperationTransferComponent.vue'
|
import OperationTransferComponent from './OperationTransferComponent.vue'
|
||||||
import OperationTransfer2Component from './OperationTransfer2Component.vue'
|
import OperationTransfer2Component from './OperationTransfer2Component.vue'
|
||||||
|
import ChartComponentDoughnut from './ChartComponentDoughnut.vue'
|
||||||
|
import ChartjsComponentBar from './ChartjsComponentBar.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@ -167,6 +220,8 @@ export default {
|
|||||||
// eslint-disable-next-line vue/no-unused-components
|
// eslint-disable-next-line vue/no-unused-components
|
||||||
ToastificationContent,
|
ToastificationContent,
|
||||||
OperationTransfer2Component,
|
OperationTransfer2Component,
|
||||||
|
ChartComponentDoughnut,
|
||||||
|
ChartjsComponentBar,
|
||||||
},
|
},
|
||||||
directives: {
|
directives: {
|
||||||
'b-modal': VBModal,
|
'b-modal': VBModal,
|
||||||
@ -174,18 +229,128 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
currency: getUserCurrencySign(),
|
||||||
|
currency2: getUserCurrency(),
|
||||||
selectedAddress: '',
|
selectedAddress: '',
|
||||||
selectedName: '',
|
selectedName: '',
|
||||||
transferWindow: false,
|
transferWindow: false,
|
||||||
accounts: [],
|
accounts: [],
|
||||||
balances: {},
|
balances: {},
|
||||||
|
delegations: {},
|
||||||
ibcDenom: {},
|
ibcDenom: {},
|
||||||
quotes: {},
|
quotes: {},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
calculateTotal() {
|
||||||
|
const v = Object.values(this.balances)
|
||||||
|
let total = 0
|
||||||
|
if (v) {
|
||||||
|
v.forEach(tokens => {
|
||||||
|
const subtotal = tokens.map(x => this.formatCurrency(x.amount, x.denom)).reduce((t, c) => t + c)
|
||||||
|
total += subtotal
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const d = Object.values(this.delegations)
|
||||||
|
if (d) {
|
||||||
|
d.forEach(tokens => {
|
||||||
|
const subtotal = tokens.map(x => this.formatCurrency(x.amount, x.denom)).reduce((t, c) => t + c, 0)
|
||||||
|
total += subtotal
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return parseFloat(total.toFixed(2))
|
||||||
|
},
|
||||||
|
calculateChartDoughnut() {
|
||||||
|
const v = Object.values(this.balances)
|
||||||
|
const total = {}
|
||||||
|
if (v) {
|
||||||
|
v.forEach(tokens => {
|
||||||
|
const subtotal = tokens.map(x => ({ denom: x.denom, sub: this.formatCurrency(x.amount, x.denom) }))
|
||||||
|
subtotal.forEach(x => {
|
||||||
|
const denom = this.formatDenom(x.denom)
|
||||||
|
if (total[denom]) {
|
||||||
|
total[denom] += x.sub
|
||||||
|
} else {
|
||||||
|
total[denom] = x.sub
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const d = Object.values(this.delegations)
|
||||||
|
if (d) {
|
||||||
|
d.forEach(tokens => {
|
||||||
|
const subtotal = tokens.map(x => ({ denom: x.denom, sub: this.formatCurrency(x.amount, x.denom) }))
|
||||||
|
subtotal.forEach(x => {
|
||||||
|
const denom = this.formatDenom(x.denom)
|
||||||
|
if (total[denom]) {
|
||||||
|
total[denom] += x.sub
|
||||||
|
} else {
|
||||||
|
total[denom] = x.sub
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
labels: Object.keys(total),
|
||||||
|
data: Object.values(total),
|
||||||
|
backgroundColor: chartColors(),
|
||||||
|
borderWidth: 0,
|
||||||
|
pointStyle: 'rectRounded',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
calculateChartBar() {
|
||||||
|
const v = Object.values(this.balances)
|
||||||
|
const total = {}
|
||||||
|
if (v) {
|
||||||
|
v.forEach(tokens => {
|
||||||
|
const subtotal = tokens.map(x => ({ denom: x.denom, sub: this.formatCurrency(x.amount, x.denom) }))
|
||||||
|
subtotal.forEach(x => {
|
||||||
|
const denom = this.formatDenom(x.denom)
|
||||||
|
if (total[denom]) {
|
||||||
|
total[denom] += x.sub
|
||||||
|
} else {
|
||||||
|
total[denom] = x.sub
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const d = Object.values(this.delegations)
|
||||||
|
if (d) {
|
||||||
|
d.forEach(tokens => {
|
||||||
|
const subtotal = tokens.map(x => ({ denom: x.denom, sub: this.formatCurrency(x.amount, x.denom) }))
|
||||||
|
subtotal.forEach(x => {
|
||||||
|
const denom = this.formatDenom(x.denom)
|
||||||
|
if (total[denom]) {
|
||||||
|
total[denom] += x.sub
|
||||||
|
} else {
|
||||||
|
total[denom] = x.sub
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
labels: Object.keys(total),
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
data: Object.values(total),
|
||||||
|
backgroundColor: chartColors(),
|
||||||
|
borderWidth: 0,
|
||||||
|
pointStyle: 'rectRounded',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
created() {
|
created() {
|
||||||
this.init()
|
this.init()
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
init() {
|
init() {
|
||||||
this.accounts = getLocalAccounts()
|
this.accounts = getLocalAccounts()
|
||||||
@ -193,33 +358,33 @@ export default {
|
|||||||
if (this.accounts) {
|
if (this.accounts) {
|
||||||
Object.keys(this.accounts).forEach(acc => {
|
Object.keys(this.accounts).forEach(acc => {
|
||||||
this.accounts[acc].address.forEach(add => {
|
this.accounts[acc].address.forEach(add => {
|
||||||
chainAPI.getBankBalance(chains[add.chain].api, add.addr).then(res => {
|
this.$http.getBankBalances(add.addr, chains[add.chain]).then(res => {
|
||||||
if (res && res.length > 0) {
|
if (res && res.length > 0) {
|
||||||
this.$set(this.balances, add.addr, res)
|
this.$set(this.balances, add.addr, res)
|
||||||
res.forEach(token => {
|
res.forEach(token => {
|
||||||
let symbol
|
|
||||||
if (token.denom.startsWith('ibc')) {
|
if (token.denom.startsWith('ibc')) {
|
||||||
chainAPI.getIBCDenomTraceText(chains[add.chain].api, token.denom).then(denom => {
|
this.$http.getIBCDenomTrace(token.denom, chains[add.chain]).then(denom => {
|
||||||
this.$set(this.ibcDenom, token.denom, denom)
|
this.$set(this.ibcDenom, token.denom, denom)
|
||||||
symbol = formatTokenDenom(denom)
|
|
||||||
})
|
})
|
||||||
} else {
|
|
||||||
symbol = formatTokenDenom(token.denom)
|
|
||||||
}
|
|
||||||
if (symbol) {
|
|
||||||
if (!this.quotes[symbol]) {
|
|
||||||
chainAPI.fetchTokenQuote(symbol).then(quote => {
|
|
||||||
this.$set(this.quotes, symbol, quote)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
this.$http.getStakingDelegations(add.addr, chains[add.chain]).then(res => {
|
||||||
|
if (res.delegation_responses) {
|
||||||
|
const delegation = res.delegation_responses.map(x => x.balance)
|
||||||
|
this.$set(this.delegations, add.addr, delegation)
|
||||||
|
}
|
||||||
|
}).catch(() => {})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
setCurrency(c) {
|
||||||
|
setUserCurrency(c)
|
||||||
|
this.currency2 = c
|
||||||
|
this.currency = getUserCurrencySign()
|
||||||
|
},
|
||||||
transfer(addr) {
|
transfer(addr) {
|
||||||
this.selectedAddress = addr
|
this.selectedAddress = addr
|
||||||
},
|
},
|
||||||
@ -240,20 +405,26 @@ export default {
|
|||||||
formatCurrency(amount, denom) {
|
formatCurrency(amount, denom) {
|
||||||
const qty = this.formatAmount(amount)
|
const qty = this.formatAmount(amount)
|
||||||
const d2 = this.formatDenom(denom)
|
const d2 = this.formatDenom(denom)
|
||||||
const userCurrency = 'USD'
|
const quote = this.$store.state.chains.quotes[d2]
|
||||||
const quote = this.quotes[d2]
|
if (quote) {
|
||||||
if (quote && quote.quote) {
|
const price = quote[this.currency2]
|
||||||
const { price } = quote.quote[userCurrency]
|
|
||||||
return parseFloat((qty * price).toFixed(2))
|
return parseFloat((qty * price).toFixed(2))
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
},
|
},
|
||||||
formatBalance(v) {
|
formatBalance(v) {
|
||||||
if (v) {
|
let total = 0
|
||||||
const ret = v.map(x => this.formatCurrency(x.amount, x.denom)).reduce((t, c) => t + c)
|
const balance = this.balances[v]
|
||||||
return parseFloat(ret.toFixed(2))
|
if (balance) {
|
||||||
|
const ret = balance.map(x => this.formatCurrency(x.amount, x.denom)).reduce((t, c) => t + c)
|
||||||
|
total += ret
|
||||||
}
|
}
|
||||||
return 0
|
const delegations = this.delegations[v]
|
||||||
|
if (delegations) {
|
||||||
|
const ret = delegations.map(x => this.formatCurrency(x.amount, x.denom)).reduce((t, c) => t + c, 0)
|
||||||
|
total += ret
|
||||||
|
}
|
||||||
|
return parseFloat(total.toFixed(2))
|
||||||
},
|
},
|
||||||
removeAddress(v) {
|
removeAddress(v) {
|
||||||
Object.keys(this.accounts).forEach(key => {
|
Object.keys(this.accounts).forEach(key => {
|
||||||
|
Loading…
Reference in New Issue
Block a user