forked from cerc-io/cosmos-explorer
merge
This commit is contained in:
commit
39f5cf5337
@ -2,6 +2,9 @@
|
||||
import { useWalletStore } from '@/stores';
|
||||
|
||||
const walletStore = useWalletStore();
|
||||
walletStore.$subscribe((m, s) => {
|
||||
console.log(m, s);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -10,7 +13,10 @@ const walletStore = useWalletStore();
|
||||
walletStore.currentAddress
|
||||
}}</span>
|
||||
|
||||
<label v-else for="PingConnectWallet" class="btn btn-sm ml-4 ping-connect-btn"
|
||||
<label
|
||||
v-else
|
||||
for="PingConnectWallet"
|
||||
class="btn btn-sm ml-4 ping-connect-btn"
|
||||
>Connect Wallet</label
|
||||
>
|
||||
</div>
|
||||
|
@ -193,13 +193,17 @@ export class CosmosRestClient extends BaseRestClient<RequestRegistry> {
|
||||
async getBaseNodeInfo() {
|
||||
return this.request(this.registry.base_tendermint_node_info, {});
|
||||
}
|
||||
async getBaseValidatorsetAt(height: string | number) {
|
||||
async getBaseValidatorsetAt(height: string | number, offset: number) {
|
||||
console.log("offset", offset)
|
||||
const query = `?pagination.limit=100&pagination.offset=${offset}`
|
||||
return this.request(this.registry.base_tendermint_validatorsets_height, {
|
||||
height,
|
||||
});
|
||||
}, query);
|
||||
}
|
||||
async getBaseValidatorsetLatest() {
|
||||
return this.request(this.registry.base_tendermint_validatorsets_latest, {});
|
||||
async getBaseValidatorsetLatest(offset: number) {
|
||||
console.log(offset)
|
||||
const query = `?pagination.limit=100&pagination.offset=${offset}`
|
||||
return this.request(this.registry.base_tendermint_validatorsets_latest, {}, query);
|
||||
}
|
||||
// tx
|
||||
async getTxsBySender(sender: string) {
|
||||
|
@ -73,7 +73,13 @@ export interface RequestRegistry extends AbstractRegistry {
|
||||
}>;
|
||||
distribution_validator_slashes: Request<PaginatedSlashes>;
|
||||
distribution_community_pool: Request<{ pool: Coin[] }>;
|
||||
distribution_delegator_rewards: Request<any>;
|
||||
distribution_delegator_rewards: Request<{
|
||||
rewards: {
|
||||
validator_address: string,
|
||||
reward: Coin[]
|
||||
}[],
|
||||
total: Coin[]
|
||||
}>;
|
||||
|
||||
mint_inflation: Request<{ inflation: string }>;
|
||||
mint_params: Request<{
|
||||
|
@ -97,7 +97,8 @@ const format = useFormatter();
|
||||
<route>
|
||||
{
|
||||
meta: {
|
||||
i18n: 'blocks'
|
||||
i18n: 'blocks',
|
||||
order: 5
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
@ -47,7 +47,8 @@ const changeTab = (val: '2' | '3' | '4') => {
|
||||
<route>
|
||||
{
|
||||
meta: {
|
||||
i18n: 'governance'
|
||||
i18n: 'governance',
|
||||
order: 2
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
@ -70,7 +70,8 @@ function color(v: string) {
|
||||
<route>
|
||||
{
|
||||
meta: {
|
||||
i18n: 'ibc'
|
||||
i18n: 'ibc',
|
||||
order: 8
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
@ -14,6 +14,7 @@ import ProposalListItem from '@/components/ProposalListItem.vue';
|
||||
const blockchain = useBlockchain();
|
||||
const store = useIndexModule();
|
||||
const walletStore = useWalletStore()
|
||||
const format = useFormatter()
|
||||
|
||||
const coinInfo = computed(() => {
|
||||
return store.coinInfo;
|
||||
@ -21,9 +22,9 @@ const coinInfo = computed(() => {
|
||||
|
||||
onMounted(() => {
|
||||
store.loadDashboard();
|
||||
walletStore.loadMyAsset()
|
||||
});
|
||||
|
||||
const format = useFormatter();
|
||||
const ticker = computed(() => store.coinInfo.tickers[store.tickerIndex]);
|
||||
|
||||
blockchain.$subscribe((m, s) => {
|
||||
@ -32,6 +33,7 @@ blockchain.$subscribe((m, s) => {
|
||||
['chainName', 'endpoint'].includes(m.events.key)
|
||||
) {
|
||||
store.loadDashboard();
|
||||
walletStore.loadMyAsset()
|
||||
}
|
||||
});
|
||||
function shortName(name: string, id: string) {
|
||||
@ -65,7 +67,20 @@ const comLinks = [
|
||||
];
|
||||
|
||||
// wallet box
|
||||
|
||||
const change = computed(() => {
|
||||
const token = walletStore.balanceOfStakingToken
|
||||
return token? format.priceChanges(token.denom) : 0
|
||||
})
|
||||
const color= computed(() => {
|
||||
switch(true) {
|
||||
case change.value > 0:
|
||||
return "text-green-600"
|
||||
case change.value === 0:
|
||||
return "text-grey-500"
|
||||
case change.value < 0:
|
||||
return "text-red-600"
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -226,10 +241,18 @@ const comLinks = [
|
||||
<span v-if="walletStore.currentAddress" class="float-right font-light text-sm">More</span>
|
||||
</div>
|
||||
<div class="grid grid-cols-1 md:grid-cols-4 auto-cols-auto gap-4 px-4 pb-8 py-4">
|
||||
<div class="bg-base-100">1</div>
|
||||
<div class="bg-base-100">2</div>
|
||||
<div class="bg-base-100">1</div>
|
||||
<div class="bg-base-100">2</div>
|
||||
<div class="bg-base-100">{{ format.formatToken(walletStore.balanceOfStakingToken) }}
|
||||
<br><span :class="color">{{ format.showChanges(change) }}<small>%</small></span>{{ format.tokenValue(walletStore.balanceOfStakingToken) }}</div>
|
||||
<div class="bg-base-100">{{ format.formatToken(walletStore.stakingAmount) }}
|
||||
<br> {{ format.tokenValue(walletStore.stakingAmount) }}</div>
|
||||
<div class="bg-base-100">{{ format.formatToken(walletStore.rewardAmount) }}</div>
|
||||
<div class="bg-base-100">{{ format.formatToken(walletStore.unbondingAmount) }}</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div v-for="v in walletStore.delegations">
|
||||
{{ v }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
@ -244,7 +267,8 @@ const comLinks = [
|
||||
<route>
|
||||
{
|
||||
meta: {
|
||||
i18n: 'dashboard'
|
||||
i18n: 'dashboard',
|
||||
order: 1,
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
@ -55,7 +55,8 @@ onMounted(() => {
|
||||
<route>
|
||||
{
|
||||
meta: {
|
||||
i18n: 'parameters'
|
||||
i18n: 'parameters',
|
||||
order: 10
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
@ -16,43 +16,68 @@ const tab = ref('active');
|
||||
const unbondList = ref([] as Validator[]);
|
||||
const base = useBaseStore();
|
||||
onMounted(() => {
|
||||
fetchChange(0);
|
||||
staking.fetchInacitveValdiators().then((x) => {
|
||||
unbondList.value = x;
|
||||
});
|
||||
});
|
||||
|
||||
function fetchChange(offset: number) {
|
||||
const base = useBaseStore();
|
||||
const diff = 86400000 / base.blocktime;
|
||||
// base.fetchAbciInfo().then(h => {
|
||||
// // console.log('block:', h)
|
||||
// base.fetchValidatorByHeight(h.lastBlockHeight, offset).then(x => {
|
||||
// x.validators.forEach(v => {
|
||||
// if(v.pubkey) latest.value[pubkeyToAddress(v.pubkey.algorithm, v.pubkey.data)] = Number(v.votingPower)
|
||||
// })
|
||||
// })
|
||||
// const height = Number(h.lastBlockHeight) - diff
|
||||
// base.fetchValidatorByHeight(height > 0 ? height : 1, offset).then(old => {
|
||||
// old.validators.forEach(v => {
|
||||
// if(v.pubkey) yesterday.value[pubkeyToAddress(v.pubkey.algorithm, v.pubkey.data)] = Number(v.votingPower)
|
||||
// })
|
||||
// // console.log(Object.keys(yesterday.value).map(x => x.toUpperCase()))
|
||||
// })
|
||||
// })
|
||||
async function fetchChange() {
|
||||
console.log('fetch changes')
|
||||
let page = 0
|
||||
|
||||
let height = Number(base.latest?.block?.header?.height || 0)
|
||||
if (height > 14400) {
|
||||
height -= 14400
|
||||
} else {
|
||||
height = 1
|
||||
}
|
||||
// voting power in 24h ago
|
||||
while(page < staking.validators.length && height > 0) {
|
||||
await base.fetchValidatorByHeight(height, page).then(x => {
|
||||
x.validators.forEach(v => {
|
||||
yesterday.value[v.pub_key.key] = Number(v.voting_power)
|
||||
})
|
||||
})
|
||||
page += 100
|
||||
}
|
||||
|
||||
page = 0
|
||||
// voting power for now
|
||||
while(page < staking.validators.length) {
|
||||
await base.fetchLatestValidators(page).then(x => {
|
||||
x.validators.forEach(v => {
|
||||
latest.value[v.pub_key.key] = Number(v.voting_power)
|
||||
})
|
||||
})
|
||||
page += 100
|
||||
}
|
||||
}
|
||||
|
||||
fetchChange();
|
||||
|
||||
const changes = computed(() => {
|
||||
const changes = {} as Record<string, number>
|
||||
Object.keys(latest.value).forEach(k => {
|
||||
const l = latest.value[k] || 0
|
||||
const y = yesterday.value[k] || 0
|
||||
changes[k] = l - y
|
||||
})
|
||||
return changes
|
||||
})
|
||||
|
||||
const change24 = (key: Key) => {
|
||||
const txt = key.key;
|
||||
const n: number = latest.value[txt];
|
||||
const o: number = yesterday.value[txt];
|
||||
return n > 0 && o > 0 ? n - o : 0;
|
||||
// const n: number = latest.value[txt];
|
||||
// const o: number = yesterday.value[txt];
|
||||
// // console.log( txt, n, o)
|
||||
// return n > 0 && o > 0 ? n - o : 0;
|
||||
return changes.value[txt]
|
||||
};
|
||||
|
||||
const change24Text = (key?: Key) => {
|
||||
if (!key) return '';
|
||||
const v = change24(key);
|
||||
return v !== 0 ? format.numberAndSign(v) : '';
|
||||
return v !== 0 ? format.showChanges(v) : '';
|
||||
};
|
||||
|
||||
const change24Color = (key?: Key) => {
|
||||
@ -308,7 +333,8 @@ const rank = function (position: number) {
|
||||
<route>
|
||||
{
|
||||
meta: {
|
||||
i18n: 'staking'
|
||||
i18n: 'staking',
|
||||
order: 3
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
@ -162,7 +162,8 @@ watchEffect(() => {
|
||||
<route>
|
||||
{
|
||||
meta: {
|
||||
i18n: 'uptime'
|
||||
i18n: 'uptime',
|
||||
order: 8
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
@ -12,6 +12,7 @@ const dashboard = useDashboard();
|
||||
|
||||
dashboard.$subscribe((mutation, state) => {
|
||||
localStorage.setItem('favorite', JSON.stringify(state.favorite));
|
||||
dashboard.loadingPrices()
|
||||
});
|
||||
const keywords = ref('');
|
||||
const chains = computed(() => {
|
||||
@ -23,7 +24,6 @@ const chains = computed(() => {
|
||||
return Object.values(dashboard.chains);
|
||||
}
|
||||
});
|
||||
const chain = useBlockchain();
|
||||
</script>
|
||||
<template>
|
||||
<div class="">
|
||||
|
@ -56,10 +56,10 @@ export const useBaseStore = defineStore('baseStore', {
|
||||
},
|
||||
|
||||
async fetchValidatorByHeight(height?: number, offset = 0) {
|
||||
return this.blockchain.rpc.getBaseValidatorsetAt(String(height));
|
||||
return this.blockchain.rpc.getBaseValidatorsetAt(String(height), offset);
|
||||
},
|
||||
async fetchLatestValidators(offset = 0) {
|
||||
return this.blockchain.rpc.getBaseValidatorsetLatest();
|
||||
return this.blockchain.rpc.getBaseValidatorsetLatest(offset);
|
||||
},
|
||||
async fetchBlock(height?: number) {
|
||||
return this.blockchain.rpc.getBaseBlockAt(String(height));
|
||||
|
@ -68,8 +68,9 @@ export const useBlockchain = defineStore('blockchain', {
|
||||
to: { path: x.path.replace(':chain', this.chainName) },
|
||||
icon: { icon: 'mdi-chevron-right', size: '22' },
|
||||
i18n: true,
|
||||
order: Number(x.meta.order || 100)
|
||||
}))
|
||||
.sort((a, b) => a.to.path.length - b.to.path.length),
|
||||
.sort((a, b) => a.order - b.order),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
@ -234,6 +234,8 @@ export const useDashboard = defineStore('dashboard', {
|
||||
favorite: fav as string[],
|
||||
favoriteMap: favMap as Record<string, boolean>,
|
||||
chains: {} as Record<string, ChainConfig>,
|
||||
prices: {},
|
||||
coingecko: {} as Record<string, {coinId: string, exponent: number, symbol: string}>,
|
||||
};
|
||||
},
|
||||
getters: {
|
||||
@ -246,6 +248,28 @@ export const useDashboard = defineStore('dashboard', {
|
||||
this.loadingFromLocal();
|
||||
// this.loadingFromRegistry()
|
||||
},
|
||||
loadingPrices() {
|
||||
const coinIds = [] as string[]
|
||||
Object.keys(this.favoriteMap).forEach(k => {
|
||||
if(this.chains[k]) this.chains[k].assets.forEach(a => {
|
||||
if(a.coingecko_id !== undefined) {
|
||||
coinIds.push(a.coingecko_id)
|
||||
a.denom_units.forEach(u => {
|
||||
this.coingecko[u.denom] = {
|
||||
coinId: a.coingecko_id || '',
|
||||
exponent: u.exponent,
|
||||
symbol: a.symbol
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
const currencies = ['usd, cny'] // usd,cny,eur,jpy,krw,sgd,hkd
|
||||
get(`https://api.coingecko.com/api/v3/simple/price?include_24hr_change=true&vs_currencies=${currencies.join(',')}&ids=${coinIds.join(",")}`).then(x => {
|
||||
this.prices = x
|
||||
})
|
||||
},
|
||||
async loadingFromRegistry() {
|
||||
if (this.status === LoadingStatus.Empty) {
|
||||
this.status = LoadingStatus.Loading;
|
||||
@ -274,12 +298,14 @@ export const useDashboard = defineStore('dashboard', {
|
||||
for (let i = 0; i < this.favorite.length; i++) {
|
||||
if (!blockchain.chainName && this.chains[this.favorite[i]]) {
|
||||
blockchain.setCurrent(this.favorite[i]);
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!blockchain.chainName) {
|
||||
const [first] = Object.keys(this.chains);
|
||||
blockchain.setCurrent(first);
|
||||
}
|
||||
this.loadingPrices()
|
||||
}
|
||||
},
|
||||
setConfigSource(newSource: ConfigSource) {
|
||||
|
@ -11,7 +11,8 @@ import { useStakingStore } from './useStakingStore';
|
||||
import { fromBase64, fromBech32, fromHex, toHex } from '@cosmjs/encoding';
|
||||
import { consensusPubkeyToHexAddress } from '@/libs';
|
||||
import { useBankStore } from './useBankStore';
|
||||
import type { DenomTrace } from '@/types';
|
||||
import type { Coin, DenomTrace } from '@/types';
|
||||
import { useDashboard } from './useDashboard';
|
||||
|
||||
dayjs.extend(localeData);
|
||||
dayjs.extend(duration);
|
||||
@ -52,6 +53,9 @@ export const useFormatter = defineStore('formatter', {
|
||||
useBank() {
|
||||
return useBankStore();
|
||||
},
|
||||
dashboard() {
|
||||
return useDashboard()
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
async fetchDenomTrace(denom: string) {
|
||||
@ -64,6 +68,33 @@ export const useFormatter = defineStore('formatter', {
|
||||
}
|
||||
return trace;
|
||||
},
|
||||
priceInfo(denom: string) {
|
||||
const id = this.dashboard.coingecko[denom]?.coinId
|
||||
const prices = this.dashboard.prices[id]
|
||||
return prices
|
||||
},
|
||||
price(denom: string, currency = "usd") {
|
||||
const info = this.priceInfo(denom);
|
||||
console.log("info", info, denom)
|
||||
return info? info[currency]||0 : 0
|
||||
},
|
||||
priceChanges(denom: string, currency="usd"): number {
|
||||
const info = this.priceInfo(denom);
|
||||
return info? info[`${currency}_24h_change`]||0 : 0
|
||||
},
|
||||
showChanges(v: number) {
|
||||
return numeral(v).format("+0,0.[00]")
|
||||
},
|
||||
tokenValue(token: Coin) {
|
||||
// find the symbol,
|
||||
const symbol = this.dashboard.coingecko[token.denom]?.symbol || ""
|
||||
// convert denomation to to symbol
|
||||
const exponent = this.dashboard.coingecko[symbol.toLowerCase()]?.exponent || 0
|
||||
// cacualte amount of symbol
|
||||
const amount = Number(token.amount) / (10 ** exponent)
|
||||
const value = amount * this.price(token.denom)
|
||||
return numeral(value).format('0,0.[00]')
|
||||
},
|
||||
formatTokenAmount(token: { denom: string; amount: string }) {
|
||||
return this.formatToken(token, false);
|
||||
},
|
||||
@ -136,6 +167,7 @@ export const useFormatter = defineStore('formatter', {
|
||||
);
|
||||
return validator?.description?.moniker;
|
||||
},
|
||||
// find validator by operator address
|
||||
validatorFromBech32(address: string) {
|
||||
if (!address) return address;
|
||||
const validator = this.staking.validators.find(
|
||||
|
@ -1,10 +1,22 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import { useBlockchain } from './useBlockchain';
|
||||
import { fromBech32, toBech32 } from '@cosmjs/encoding';
|
||||
import type {
|
||||
Delegation,
|
||||
Coin,
|
||||
UnbondingResponses,
|
||||
DelegatorRewards,
|
||||
} from '@/types';
|
||||
import { useStakingStore } from './useStakingStore';
|
||||
|
||||
export const useWalletStore = defineStore('walletStore', {
|
||||
state: () => {
|
||||
return {};
|
||||
return {
|
||||
balances: [] as Coin[],
|
||||
delegations: [] as Delegation[],
|
||||
unbonding: [] as UnbondingResponses[],
|
||||
rewards: {} as DelegatorRewards,
|
||||
};
|
||||
},
|
||||
getters: {
|
||||
blockchain() {
|
||||
@ -17,6 +29,42 @@ export const useWalletStore = defineStore('walletStore', {
|
||||
const connected = JSON.parse(localStorage.getItem(key) || '{}');
|
||||
return connected;
|
||||
},
|
||||
balanceOfStakingToken(): Coin {
|
||||
const stakingStore = useStakingStore();
|
||||
return (
|
||||
this.balances.find(
|
||||
(x) => x.denom === stakingStore.params.bond_denom
|
||||
) || { amount: '0', denom: stakingStore.params.bond_denom }
|
||||
);
|
||||
},
|
||||
stakingAmount() {
|
||||
let amt = 0;
|
||||
let denom = '';
|
||||
this.delegations.forEach((i) => {
|
||||
amt += Number(i.balance.amount);
|
||||
denom = i.balance.denom;
|
||||
});
|
||||
return { amount: String(amt), denom };
|
||||
},
|
||||
rewardAmount() {
|
||||
const stakingStore = useStakingStore();
|
||||
const reward = this.rewards.total?.find(
|
||||
(x) => x.denom === stakingStore.params.bond_denom
|
||||
);
|
||||
return reward || { amount: '0', denom: stakingStore.params.bond_denom };
|
||||
},
|
||||
unbondingAmount() {
|
||||
let amt = 0;
|
||||
let denom = '';
|
||||
this.unbonding.forEach((i) => {
|
||||
i.entries.forEach((e) => {
|
||||
amt += Number(e.balance);
|
||||
});
|
||||
});
|
||||
|
||||
const stakingStore = useStakingStore();
|
||||
return { amount: String(amt), denom: stakingStore.params.bond_denom };
|
||||
},
|
||||
currentAddress() {
|
||||
if (!this.connectedWallet?.cosmosAddress) return '';
|
||||
const { prefix, data } = fromBech32(this.connectedWallet.cosmosAddress);
|
||||
@ -25,6 +73,27 @@ export const useWalletStore = defineStore('walletStore', {
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
async loadMyAsset() {
|
||||
if (!this.currentAddress) return;
|
||||
this.blockchain.rpc.getBankBalances(this.currentAddress).then((x) => {
|
||||
this.balances = x.balances;
|
||||
});
|
||||
this.blockchain.rpc
|
||||
.getStakingDelegations(this.currentAddress)
|
||||
.then((x) => {
|
||||
this.delegations = x.delegation_responses;
|
||||
});
|
||||
this.blockchain.rpc
|
||||
.getStakingDelegatorUnbonding(this.currentAddress)
|
||||
.then((x) => {
|
||||
this.unbonding = x.unbonding_responses;
|
||||
});
|
||||
this.blockchain.rpc
|
||||
.getDistributionDelegatorRewards(this.currentAddress)
|
||||
.then((x) => {
|
||||
this.rewards = x;
|
||||
});
|
||||
},
|
||||
myBalance() {
|
||||
return this.blockchain.rpc.getBankBalances(this.currentAddress);
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user