forked from cerc-io/cosmos-explorer
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.dispatch('chains/getQuotes')
|
||||
|
||||
return {
|
||||
skinClasses,
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
"regen": "Regen Network",
|
||||
"secret": "Secret Network",
|
||||
"desmos": "Desmos",
|
||||
"juno": "Juno Hera",
|
||||
"juno": "Juno",
|
||||
"certik": "Certik",
|
||||
"sentinel": "Sentinel",
|
||||
|
||||
@ -26,7 +26,8 @@
|
||||
"blockchains": "Blockchains",
|
||||
"uptime": "Uptime",
|
||||
|
||||
"gravity": "Gravity",
|
||||
"gravity": "Gravity(WIP)",
|
||||
"pools": "Pools(WIP)",
|
||||
|
||||
"proposal_id": "Proposal ID",
|
||||
"proposal_type": "Proposal Type",
|
||||
|
@ -13,6 +13,7 @@ import dayjs from 'dayjs'
|
||||
import duration from 'dayjs/plugin/duration'
|
||||
import relativeTime from 'dayjs/plugin/relativeTime'
|
||||
import localeData from 'dayjs/plugin/localeData'
|
||||
import { $themeColors } from '@themeConfig'
|
||||
|
||||
dayjs.extend(localeData)
|
||||
dayjs.extend(duration)
|
||||
@ -76,6 +77,41 @@ export function addressEnCode(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) {
|
||||
let raw = null
|
||||
if (typeof consensusPubkey === 'object') {
|
||||
@ -218,7 +254,7 @@ export function isToken(value) {
|
||||
|
||||
export function formatTokenDenom(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') {
|
||||
denom = denom.substring(1)
|
||||
} else if (denom === 'BASECRO') {
|
||||
|
@ -328,6 +328,7 @@ const chainAPI = class ChainFetch {
|
||||
return ChainFetch.fetchCoinMarketCap(`/quote/${symbol}`)
|
||||
}
|
||||
|
||||
// Tx Submit
|
||||
async broadcastTx(bodyBytes, config = null) {
|
||||
const txString = toBase64(TxRaw.encode(bodyBytes).finish())
|
||||
const txRaw = {
|
||||
@ -365,6 +366,15 @@ const chainAPI = class ChainFetch {
|
||||
// const response = axios.post((config ? config.api : this.config.api) + url, data)
|
||||
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
|
||||
|
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',
|
||||
route: 'uptime',
|
||||
},
|
||||
// {
|
||||
// scope: 'cosmos',
|
||||
// title: 'gravity',
|
||||
// route: 'gravity',
|
||||
// },
|
||||
{
|
||||
scope: 'cosmos',
|
||||
title: 'gravity',
|
||||
route: 'gravity',
|
||||
},
|
||||
{
|
||||
scope: 'osmosis',
|
||||
title: 'pools',
|
||||
route: 'osmosis-pool',
|
||||
},
|
||||
]
|
||||
|
||||
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',
|
||||
component: () => import('@/views/GravityPool.vue'),
|
||||
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',
|
||||
name: 'login',
|
||||
|
@ -48,6 +48,7 @@ export default {
|
||||
avatars: {},
|
||||
height: 0,
|
||||
ibcChannels: {},
|
||||
quotes: {},
|
||||
},
|
||||
getters: {
|
||||
getchains: state => state.chains,
|
||||
@ -69,6 +70,15 @@ export default {
|
||||
setChannels(state, { 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">
|
||||
Consensus Public Address
|
||||
</h6>
|
||||
<small @click="copy(consensusPubkey)">{{ consensusPubkey }}</small>
|
||||
<small @click="copy(JSON.stringify(consensusPubkey))">{{ consensusPubkey }}</small>
|
||||
</b-media-body>
|
||||
</b-media>
|
||||
<b-media
|
||||
|
@ -64,23 +64,24 @@
|
||||
<b-card-body class="pl-0 pr-0">
|
||||
<b-row>
|
||||
<b-col
|
||||
class="border-right"
|
||||
xm="12"
|
||||
md="4"
|
||||
>
|
||||
<chartjs-component-doughnut-chart
|
||||
<chart-component-doughnut
|
||||
v-if="chartData"
|
||||
:height="235"
|
||||
:width="235"
|
||||
:data="chartData"
|
||||
:chart-data="chartData"
|
||||
:options="doughnutChart.options"
|
||||
class="mb-3"
|
||||
/>
|
||||
</b-col>
|
||||
<b-col
|
||||
class="border-left d-none d-md-block"
|
||||
md="1"
|
||||
/>
|
||||
<b-col
|
||||
xm="12"
|
||||
md="8"
|
||||
md="7"
|
||||
>
|
||||
<!-- tokens -->
|
||||
<div
|
||||
@ -104,12 +105,12 @@
|
||||
</div>
|
||||
<div class="d-flex flex-column">
|
||||
<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>
|
||||
<!--/ tokens -->
|
||||
<div class="text-right border-top pt-1">
|
||||
<h2>Total: ${{ assetTable.currency }}</h2>
|
||||
<h2>Total: {{ currency }}{{ assetTable.currency }}</h2>
|
||||
</div>
|
||||
</b-col>
|
||||
</b-row>
|
||||
@ -363,17 +364,16 @@ import Ripple from 'vue-ripple-directive'
|
||||
import VueQr from 'vue-qr'
|
||||
import chainAPI from '@/libs/fetch'
|
||||
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'
|
||||
import { $themeColors } from '@themeConfig'
|
||||
import ObjectFieldComponent from './ObjectFieldComponent.vue'
|
||||
import ChartjsComponentDoughnutChart from './ChartjsComponentDoughnutChart.vue'
|
||||
import OperationTransferComponent from './OperationTransferComponent.vue'
|
||||
import OperationWithdrawComponent from './OperationWithdrawComponent.vue'
|
||||
import OperationUnbondComponent from './OperationUnbondComponent.vue'
|
||||
import OperationDelegateComponent from './OperationDelegateComponent.vue'
|
||||
import OperationRedelegateComponent from './OperationRedelegateComponent.vue'
|
||||
import OperationTransfer2Component from './OperationTransfer2Component.vue'
|
||||
import ChartComponentDoughnut from './ChartComponentDoughnut.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@ -398,13 +398,13 @@ export default {
|
||||
// eslint-disable-next-line vue/no-unused-components
|
||||
ToastificationContent,
|
||||
ObjectFieldComponent,
|
||||
ChartjsComponentDoughnutChart,
|
||||
OperationTransferComponent,
|
||||
OperationWithdrawComponent,
|
||||
OperationDelegateComponent,
|
||||
OperationRedelegateComponent,
|
||||
OperationUnbondComponent,
|
||||
OperationTransfer2Component,
|
||||
ChartComponentDoughnut,
|
||||
},
|
||||
directives: {
|
||||
'b-modal': VBModal,
|
||||
@ -414,6 +414,7 @@ export default {
|
||||
data() {
|
||||
const { address } = this.$route.params
|
||||
return {
|
||||
currency: getUserCurrencySign(),
|
||||
selectedValidator: '',
|
||||
totalCurrency: 0,
|
||||
address,
|
||||
@ -426,39 +427,6 @@ export default {
|
||||
unbonding: [],
|
||||
quotes: {},
|
||||
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: {
|
||||
@ -581,7 +549,7 @@ export default {
|
||||
{
|
||||
labels: Object.keys(data),
|
||||
data: Object.values(data),
|
||||
backgroundColor: [$themeColors.primary, $themeColors.success, $themeColors.warning, $themeColors.danger, $themeColors.info],
|
||||
backgroundColor: chartColors,
|
||||
borderWidth: 0,
|
||||
pointStyle: 'rectRounded',
|
||||
},
|
||||
@ -680,10 +648,10 @@ export default {
|
||||
formatCurrency(amount, denom) {
|
||||
const qty = this.formatAmount(amount)
|
||||
const d2 = this.formatDenom(denom)
|
||||
const userCurrency = 'USD'
|
||||
const quote = this.quotes[d2]
|
||||
if (quote && quote.quote) {
|
||||
const { price } = quote.quote[userCurrency]
|
||||
const userCurrency = getUserCurrency()
|
||||
const quote = this.$store.state.chains.quotes[d2]
|
||||
if (quote) {
|
||||
const price = quote[userCurrency]
|
||||
return parseFloat((qty * price).toFixed(2))
|
||||
}
|
||||
return 0
|
||||
|
@ -1,5 +1,57 @@
|
||||
<template>
|
||||
<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
|
||||
v-for="item,index in accounts"
|
||||
@ -81,7 +133,7 @@
|
||||
variant="light-primary"
|
||||
rounded
|
||||
/>
|
||||
<h3>${{ formatBalance(balances[acc.addr]) }}</h3>
|
||||
<h3>{{ currency }}{{ formatBalance(acc.addr) }}</h3>
|
||||
</div>
|
||||
<small
|
||||
class="pl-1 float-right text-muted text-overflow "
|
||||
@ -91,7 +143,7 @@
|
||||
</small>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row v-if="balances[acc.addr]">
|
||||
<b-row class="d-none">
|
||||
<b-col>
|
||||
<b-tabs
|
||||
active-nav-item-class="font-weight-bold text-second"
|
||||
@ -107,7 +159,7 @@
|
||||
</div>
|
||||
<div class="d-flex flex-column text-right">
|
||||
<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>
|
||||
</b-tab>
|
||||
@ -118,7 +170,6 @@
|
||||
</b-card>
|
||||
</b-col>
|
||||
</b-row>
|
||||
|
||||
</b-tab>
|
||||
</b-tabs>
|
||||
|
||||
@ -136,18 +187,20 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import chainAPI from '@/libs/fetch'
|
||||
import {
|
||||
BCard, BCardHeader, BCardTitle, BCardBody, VBModal, BRow, BCol, BTabs, BTab, BAvatar, BDropdown, BDropdownItem,
|
||||
} from 'bootstrap-vue'
|
||||
import Ripple from 'vue-ripple-directive'
|
||||
import FeatherIcon from '@/@core/components/feather-icon/FeatherIcon.vue'
|
||||
import {
|
||||
formatTokenAmount, formatTokenDenom, getLocalAccounts, getLocalChains,
|
||||
chartColors,
|
||||
formatTokenAmount, formatTokenDenom, getLocalAccounts, getLocalChains, getUserCurrency, getUserCurrencySign, setUserCurrency,
|
||||
} from '@/libs/data'
|
||||
import ToastificationContent from '@core/components/toastification/ToastificationContent.vue'
|
||||
import OperationTransferComponent from './OperationTransferComponent.vue'
|
||||
import OperationTransfer2Component from './OperationTransfer2Component.vue'
|
||||
import ChartComponentDoughnut from './ChartComponentDoughnut.vue'
|
||||
import ChartjsComponentBar from './ChartjsComponentBar.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@ -167,6 +220,8 @@ export default {
|
||||
// eslint-disable-next-line vue/no-unused-components
|
||||
ToastificationContent,
|
||||
OperationTransfer2Component,
|
||||
ChartComponentDoughnut,
|
||||
ChartjsComponentBar,
|
||||
},
|
||||
directives: {
|
||||
'b-modal': VBModal,
|
||||
@ -174,18 +229,128 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currency: getUserCurrencySign(),
|
||||
currency2: getUserCurrency(),
|
||||
selectedAddress: '',
|
||||
selectedName: '',
|
||||
transferWindow: false,
|
||||
accounts: [],
|
||||
balances: {},
|
||||
delegations: {},
|
||||
ibcDenom: {},
|
||||
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() {
|
||||
this.init()
|
||||
},
|
||||
mounted() {
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.accounts = getLocalAccounts()
|
||||
@ -193,33 +358,33 @@ export default {
|
||||
if (this.accounts) {
|
||||
Object.keys(this.accounts).forEach(acc => {
|
||||
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) {
|
||||
this.$set(this.balances, add.addr, res)
|
||||
res.forEach(token => {
|
||||
let symbol
|
||||
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)
|
||||
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) {
|
||||
this.selectedAddress = addr
|
||||
},
|
||||
@ -240,20 +405,26 @@ export default {
|
||||
formatCurrency(amount, denom) {
|
||||
const qty = this.formatAmount(amount)
|
||||
const d2 = this.formatDenom(denom)
|
||||
const userCurrency = 'USD'
|
||||
const quote = this.quotes[d2]
|
||||
if (quote && quote.quote) {
|
||||
const { price } = quote.quote[userCurrency]
|
||||
const quote = this.$store.state.chains.quotes[d2]
|
||||
if (quote) {
|
||||
const price = quote[this.currency2]
|
||||
return parseFloat((qty * price).toFixed(2))
|
||||
}
|
||||
return 0
|
||||
},
|
||||
formatBalance(v) {
|
||||
if (v) {
|
||||
const ret = v.map(x => this.formatCurrency(x.amount, x.denom)).reduce((t, c) => t + c)
|
||||
return parseFloat(ret.toFixed(2))
|
||||
let total = 0
|
||||
const balance = this.balances[v]
|
||||
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) {
|
||||
Object.keys(this.accounts).forEach(key => {
|
||||
|
Loading…
Reference in New Issue
Block a user