forked from LaconicNetwork/cosmos-explorer
use simple repo
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
export * from './useBankStore'
|
||||
export * from './useBlockchain'
|
||||
export * from './useCoinGecko'
|
||||
export * from './useDashboard'
|
||||
export * from './useBaseStore'
|
||||
export * from './useFormatter'
|
||||
export * from './useGovStore'
|
||||
export * from './useMintStore'
|
||||
export * from './useStakingStore'
|
||||
export * from './useDistributionStore'
|
||||
@@ -0,0 +1,13 @@
|
||||
import { defineStore } from "pinia";
|
||||
|
||||
export const useStoreName = defineStore('bankstore', {
|
||||
state: () => {
|
||||
return {
|
||||
}
|
||||
},
|
||||
getters: {
|
||||
|
||||
},
|
||||
actions: {
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,45 @@
|
||||
import { defineStore } from "pinia";
|
||||
|
||||
import { useBlockchain } from "./useBlockchain";
|
||||
import { useStakingStore } from "./useStakingStore";
|
||||
import type { Coin } from "@/types";
|
||||
|
||||
export const useBankStore = defineStore('bankstore', {
|
||||
state: () => {
|
||||
return {
|
||||
supply: {} as Coin[],
|
||||
balances: {} as Record<string, Coin[]>,
|
||||
totalSupply: {supply: []} ,
|
||||
}
|
||||
},
|
||||
getters: {
|
||||
blockchain() {
|
||||
return useBlockchain()
|
||||
},
|
||||
staking() {
|
||||
return useStakingStore()
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
initial() {
|
||||
this.$reset()
|
||||
this.supply = {} as Coin
|
||||
const denom = this.staking.params.bondDenom || this.blockchain.current?.assets[0].base
|
||||
if(denom) {
|
||||
this.blockchain.rpc.supplyOf(denom).then(res => {
|
||||
if(res.amount) this.supply = res.amount
|
||||
})
|
||||
}
|
||||
},
|
||||
// async fetchTotalSupply(param: QueryTotalSupplyRequest): Promise<QueryTotalSupplyResponse> {
|
||||
// const response = await this.blockchain.rpc.(param)
|
||||
// this.totalSupply.supply = [...this.totalSupply.supply, ...response.supply]
|
||||
// this.totalSupply.pagination = response.pagination
|
||||
// return response
|
||||
// },
|
||||
async fetchSupply(denom: string) {
|
||||
return this.blockchain.rpc.supplyOf( denom )
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
import { defineStore } from "pinia";
|
||||
import { useBlockchain } from "@/stores";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
import type { BlockResponse } from "@cosmjs/tendermint-rpc";
|
||||
|
||||
export const useBaseStore = defineStore('baseStore', {
|
||||
state: () => {
|
||||
return {
|
||||
earlest: {} as BlockResponse,
|
||||
latest: {} as BlockResponse,
|
||||
recents: [] as BlockResponse[]
|
||||
}
|
||||
},
|
||||
getters: {
|
||||
blocktime(): number {
|
||||
if(this.earlest && this.latest) {
|
||||
if(this.latest.block?.header?.height !== this.earlest.block?.header?.height) {
|
||||
const diff = dayjs(this.latest.block?.header?.time).diff(this.earlest.block?.header?.time)
|
||||
return diff
|
||||
}
|
||||
}
|
||||
return 6000
|
||||
},
|
||||
blockchain() {
|
||||
return useBlockchain()
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
async initial() {
|
||||
this.fetchLatest()
|
||||
},
|
||||
async clearRecentBlocks() {
|
||||
this.recents = []
|
||||
},
|
||||
async fetchLatest() {
|
||||
this.latest = await this.blockchain.rpc.block()
|
||||
if(!this.earlest || this.earlest.block?.header?.chainId != this.latest.block?.header?.chainId) {
|
||||
//reset earlest and recents
|
||||
this.earlest = this.latest
|
||||
this.recents = []
|
||||
}
|
||||
if(this.recents.length>= 50) {
|
||||
this.recents.pop()
|
||||
}
|
||||
this.recents.push(this.latest)
|
||||
return this.latest
|
||||
},
|
||||
|
||||
async fetchValidatorByHeight(height?: number, offset = 0) {
|
||||
return this.blockchain.rpc.validatorsAtHeight(height)
|
||||
},
|
||||
async fetchLatestValidators(offset = 0) {
|
||||
return this.blockchain.rpc.validatorsAtHeight()
|
||||
},
|
||||
async fetchBlock(height?: number) {
|
||||
return this.blockchain.rpc.block(height)
|
||||
},
|
||||
async fetchAbciInfo() {
|
||||
return this.blockchain.rpc.abciInfo()
|
||||
}
|
||||
// async fetchNodeInfo() {
|
||||
// return this.blockchain.rpc.no()
|
||||
// }
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,128 @@
|
||||
import { defineStore } from "pinia";
|
||||
import { useDashboard, type ChainConfig, type Endpoint, EndpointType } from "./useDashboard";
|
||||
import { LCDClient } from '@osmonauts/lcd'
|
||||
import type { VerticalNavItems } from '@/@layouts/types'
|
||||
import { useRouter } from "vue-router";
|
||||
import { useStakingStore } from "./useStakingStore";
|
||||
import { useBankStore } from "./useBankStore";
|
||||
import { useBaseStore } from "./useBaseStore";
|
||||
import { useGovStore } from "./useGovStore";
|
||||
import { ref } from "vue";
|
||||
import { useMintStore } from "./useMintStore";
|
||||
import { useBlockModule } from "@/modules/[chain]/block/block";
|
||||
|
||||
export const useBlockchain = defineStore("blockchain", {
|
||||
state: () => {
|
||||
return {
|
||||
status: {} as Record<string, string>,
|
||||
rest: '',
|
||||
chainName: "",
|
||||
endpoint: {} as {
|
||||
type?: EndpointType,
|
||||
address: string
|
||||
provider: string
|
||||
},
|
||||
connErr: ""
|
||||
}
|
||||
},
|
||||
getters: {
|
||||
current() : ChainConfig | undefined {
|
||||
return this.dashboard.chains[this.chainName]
|
||||
},
|
||||
logo(): string {
|
||||
return this.current?.logo || ''
|
||||
},
|
||||
dashboard() {
|
||||
return useDashboard()
|
||||
},
|
||||
computedChainMenu() {
|
||||
|
||||
let currNavItem: VerticalNavItems = []
|
||||
|
||||
const router = useRouter()
|
||||
const routes = router?.getRoutes()||[]
|
||||
console.log(routes)
|
||||
if(this.current && routes) {
|
||||
currNavItem = [{
|
||||
title: this.current?.prettyName || this.chainName || '',
|
||||
icon: {image: this.current.logo, size: '22'},
|
||||
i18n: false,
|
||||
children: routes
|
||||
.filter(x=>x.name && x.name.toString().startsWith('chain'))
|
||||
.map(x => ({
|
||||
title: `module.${x.name?.toString()}`,
|
||||
to: {path: x.path.replace(':chain',this.chainName)},
|
||||
icon: { icon: 'mdi-chevron-right', size: '22'},
|
||||
i18n: true
|
||||
}))
|
||||
.sort((a,b)=>a.to.path.length - b.to.path.length)
|
||||
}]
|
||||
}
|
||||
// compute favorite menu
|
||||
const favNavItems: VerticalNavItems = []
|
||||
this.dashboard.favorite.forEach(name => {
|
||||
const ch = this.dashboard.chains[name]
|
||||
if(ch) {
|
||||
favNavItems.push({
|
||||
title: ch.prettyName || ch.chainName || name,
|
||||
to: { path: `/${ch.chainName || name}`},
|
||||
icon: {image: ch.logo, size: '22'}
|
||||
} )
|
||||
}
|
||||
})
|
||||
|
||||
// combine all together
|
||||
return [...currNavItem,
|
||||
{ heading: 'Ecosystem' },
|
||||
{
|
||||
title: 'Favorite',
|
||||
children: favNavItems,
|
||||
badgeContent: favNavItems.length,
|
||||
badgeClass: 'bg-primary',
|
||||
i18n: true,
|
||||
icon: { icon: 'mdi-star', size: '22'}
|
||||
},
|
||||
{
|
||||
title: 'All Blockchains',
|
||||
to: { path : '/'},
|
||||
badgeContent: this.dashboard.length,
|
||||
badgeClass: 'bg-primary',
|
||||
i18n: true,
|
||||
icon: { icon: 'mdi-grid', size: '22'}
|
||||
}
|
||||
]
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
async initial() {
|
||||
await this.randomSetupEndpoint()
|
||||
await useStakingStore().init()
|
||||
useBankStore().initial()
|
||||
useBaseStore().initial()
|
||||
useGovStore().initial()
|
||||
useMintStore().initial()
|
||||
useBlockModule().initial()
|
||||
},
|
||||
|
||||
async randomSetupEndpoint() {
|
||||
const all = this.current?.endpoints?.rpc
|
||||
if(all) {
|
||||
const rn = Math.random()
|
||||
const endpoint = all[Math.floor(rn * all.length)]
|
||||
await this.setRestEndpoint(endpoint)
|
||||
}
|
||||
},
|
||||
|
||||
async setRestEndpoint(endpoint: Endpoint) {
|
||||
this.connErr = ''
|
||||
this.endpoint = endpoint
|
||||
// this.rpc = new RPCClient(endpoint.address)
|
||||
// console.log(this.rpc.endpoint)
|
||||
},
|
||||
setCurrent(name: string) {
|
||||
this.chainName = name
|
||||
console.log('set current', name)
|
||||
},
|
||||
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,51 @@
|
||||
import { defineStore } from "pinia";
|
||||
import { get } from '../libs/http'
|
||||
import type { LoadingStatus } from "./useDashboard";
|
||||
|
||||
export interface PriceMeta {
|
||||
usd?: string,
|
||||
usd_24h_change?: string,
|
||||
cny?: string,
|
||||
cny_24h_change? : string,
|
||||
eur?: string,
|
||||
eur_24h_change?: string,
|
||||
}
|
||||
|
||||
const LocalStoreKey = 'currency'
|
||||
|
||||
export const useCoingecko = defineStore('coingecko', {
|
||||
state: () => {
|
||||
const currency = localStorage.getItem(LocalStoreKey)
|
||||
return {
|
||||
currency, // secondary currency
|
||||
loadStatus: {} as Record<string, LoadingStatus | undefined>,
|
||||
prices: {} as Record<string, PriceMeta>,
|
||||
marketChart: {}
|
||||
}
|
||||
},
|
||||
getters: {
|
||||
|
||||
},
|
||||
|
||||
actions: {
|
||||
getMarketChart(days = 30, coinId = 'cosmos') {
|
||||
return get(`https://api.coingecko.com/api/v3/coins/${coinId}/market_chart?vs_currency=usd&days=${days}`)
|
||||
},
|
||||
|
||||
fetchCoinPrice(ids: string[]) {
|
||||
const url = `https://api.coingecko.com/api/v3/simple/price?include_24hr_change=true&vs_currencies=${['usd', this.currency].join(',')}&ids=${ids.join(',')}`
|
||||
get(url).then(data => {
|
||||
this.prices = {...this.prices, ...data}
|
||||
})
|
||||
},
|
||||
getCoinInfo(coinId: string) {
|
||||
return get(`https://api.coingecko.com/api/v3/coins/${coinId}`)
|
||||
},
|
||||
setSecondaryCurrency(currency: string) {
|
||||
if(currency !== 'usd') {
|
||||
localStorage.setItem(LocalStoreKey, currency)
|
||||
this.currency = currency
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,261 @@
|
||||
|
||||
import { defineStore } from "pinia";
|
||||
import { get } from '../libs/http'
|
||||
import type { Chain, Asset } from '@ping-pub/chain-registry-client/dist/types'
|
||||
import { useBlockchain } from "./useBlockchain";
|
||||
|
||||
export enum EndpointType {
|
||||
rpc,
|
||||
rest,
|
||||
grpc,
|
||||
// webgrpc
|
||||
}
|
||||
|
||||
export interface Endpoint {
|
||||
type?: EndpointType,
|
||||
address: string,
|
||||
provider: string
|
||||
}
|
||||
|
||||
// Chain config structure of cosmos.directory
|
||||
export interface DirectoryChain {
|
||||
assets: Asset[],
|
||||
bech32_prefix: string,
|
||||
best_apis: {
|
||||
rest: Endpoint[]
|
||||
rpc: Endpoint[]
|
||||
},
|
||||
chain_id: string,
|
||||
chain_name: string,
|
||||
pretty_name: string,
|
||||
coingecko_id: string,
|
||||
cosmwasm_enabled: boolean,
|
||||
decimals: number,
|
||||
denom: string,
|
||||
display: string,
|
||||
explorers: {
|
||||
name?: string | undefined;
|
||||
kind?: string | undefined;
|
||||
url?: string | undefined;
|
||||
tx_page?: string | undefined;
|
||||
account_page?: string | undefined;
|
||||
}[] | undefined,
|
||||
height: number,
|
||||
image: string,
|
||||
name: string,
|
||||
network_type: string,
|
||||
symbol: string,
|
||||
versions?: {
|
||||
application_version: string,
|
||||
cosmos_sdk_version: string,
|
||||
tendermint_version: string,
|
||||
}
|
||||
}
|
||||
|
||||
export interface ChainConfig {
|
||||
chainName: string,
|
||||
prettyName: string,
|
||||
bech32Prefix: string,
|
||||
chainId: string,
|
||||
assets: Asset[],
|
||||
themeColor?: string,
|
||||
endpoints: {
|
||||
rest?: Endpoint[]
|
||||
rpc?: Endpoint[]
|
||||
grpc?: Endpoint[]
|
||||
},
|
||||
logo: string,
|
||||
versions: {
|
||||
application?: string,
|
||||
cosmosSdk?: string,
|
||||
tendermint?: string,
|
||||
},
|
||||
}
|
||||
|
||||
export interface LocalConfig {
|
||||
addr_prefix: string,
|
||||
alias: string,
|
||||
api: string[] | Endpoint[],
|
||||
assets: {base: string, coingecko_id: string, exponent: string, logo: string, symbol: string}[]
|
||||
chain_name: string,
|
||||
coin_type: string
|
||||
logo: string,
|
||||
min_tx_fee: string,
|
||||
rpc: string[] | Endpoint[],
|
||||
sdk_version: string,
|
||||
}
|
||||
|
||||
function apiConverter(api: any[]){
|
||||
if(!api) return []
|
||||
const array = typeof api === 'string'? [api] : api
|
||||
return array.map(x => {
|
||||
if(typeof x === 'string') {
|
||||
const parts = String(x).split('.')
|
||||
return {
|
||||
address: x,
|
||||
provider: parts.length >=2 ? parts[parts.length-2] : x
|
||||
}
|
||||
}else{
|
||||
return x as Endpoint
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function fromLocal(lc: LocalConfig ): ChainConfig {
|
||||
const conf = {} as ChainConfig
|
||||
conf.assets = lc.assets.map(x => ({
|
||||
name: x.base,
|
||||
base: x.base,
|
||||
display: x.symbol,
|
||||
symbol: x.symbol,
|
||||
logo_URIs: { svg: x.logo },
|
||||
coingecko_id: x.coingecko_id,
|
||||
denom_units: [{denom: x.base, exponent: 0}, {denom: x.symbol.toLowerCase(), exponent: Number(x.exponent)}]
|
||||
}))
|
||||
conf.bech32Prefix = lc.addr_prefix
|
||||
conf.chainName = lc.chain_name
|
||||
conf.prettyName = lc.chain_name
|
||||
conf.endpoints = {
|
||||
rest: apiConverter(lc.api),
|
||||
rpc: apiConverter(lc.rpc),
|
||||
}
|
||||
conf.logo = lc.logo
|
||||
return conf
|
||||
}
|
||||
|
||||
|
||||
export function fromDirectory(source: DirectoryChain): ChainConfig {
|
||||
const conf = {} as ChainConfig
|
||||
conf.assets = source.assets,
|
||||
conf.bech32Prefix = source.bech32_prefix,
|
||||
conf.chainId = source.chain_id,
|
||||
conf.chainName = source.chain_name,
|
||||
conf.prettyName = source.pretty_name,
|
||||
conf.versions = {
|
||||
application: source.versions?.application_version || '',
|
||||
cosmosSdk: source.versions?.cosmos_sdk_version || '',
|
||||
tendermint: source.versions?.tendermint_version || '',
|
||||
},
|
||||
conf.logo = pathConvert(source.image)
|
||||
conf.endpoints = source.best_apis
|
||||
return conf
|
||||
}
|
||||
|
||||
function pathConvert(path: string | undefined) {
|
||||
if(path) {
|
||||
path = path.replace('https://raw.githubusercontent.com/cosmos/chain-registry/master', 'https://registry.ping.pub')
|
||||
}
|
||||
return path || ''
|
||||
}
|
||||
|
||||
export function getLogo(conf: {
|
||||
svg?: string,
|
||||
png?: string,
|
||||
jpeg?: string,
|
||||
} | undefined) {
|
||||
if(conf) {
|
||||
return pathConvert(conf.svg || conf.png || conf.jpeg)
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
function createChainFromDirectory(source: DirectoryChain) : Chain {
|
||||
const conf: Chain = {} as Chain;
|
||||
conf.apis = source.best_apis
|
||||
conf.bech32_prefix = source.bech32_prefix
|
||||
conf.chain_id = source.chain_id
|
||||
conf.chain_name = source.chain_name
|
||||
conf.explorers = source.explorers
|
||||
conf.pretty_name = source.pretty_name
|
||||
if(source.versions) {
|
||||
conf.codebase = {
|
||||
recommended_version: source.versions.application_version,
|
||||
cosmos_sdk_version: source.versions.cosmos_sdk_version,
|
||||
tendermint_version: source.versions.tendermint_version,
|
||||
}
|
||||
}
|
||||
if(source.image) {
|
||||
conf.logo_URIs = {
|
||||
svg: source.image
|
||||
}
|
||||
}
|
||||
return conf
|
||||
}
|
||||
|
||||
export enum LoadingStatus {
|
||||
Empty,
|
||||
Loading,
|
||||
Loaded,
|
||||
}
|
||||
export enum NetworkType {
|
||||
Mainnet,
|
||||
Testnet,
|
||||
}
|
||||
export enum ConfigSource {
|
||||
MainnetCosmosDirectory = "https://chains.cosmos.directory",
|
||||
TestnetCosmosDirectory = "https://chains.testcosmos.directory",
|
||||
Local = 'local',
|
||||
}
|
||||
|
||||
export const useDashboard = defineStore('dashboard', {
|
||||
state: () => {
|
||||
const fav = JSON.parse(localStorage.getItem('favorite') || '["cosmoshub", "osmosis"]')
|
||||
return {
|
||||
status: LoadingStatus.Empty,
|
||||
source: ConfigSource.MainnetCosmosDirectory,
|
||||
networkType: NetworkType.Mainnet,
|
||||
favorite: fav as string[],
|
||||
chains: {} as Record<string, ChainConfig>,
|
||||
}
|
||||
},
|
||||
getters: {
|
||||
length() : number {
|
||||
return Object.keys(this.chains).length
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
initial() {
|
||||
this.loadingFromLocal()
|
||||
// this.loadingFromRegistry()
|
||||
},
|
||||
async loadingFromRegistry() {
|
||||
if(this.status === LoadingStatus.Empty) {
|
||||
this.status = LoadingStatus.Loading
|
||||
get(this.source).then((res)=> {
|
||||
res.chains.forEach(( x: DirectoryChain ) => {
|
||||
this.chains[x.chain_name] = fromDirectory(x)
|
||||
});
|
||||
this.status = LoadingStatus.Loaded
|
||||
})
|
||||
}
|
||||
},
|
||||
async loadingFromLocal() {
|
||||
const source: Record<string, LocalConfig> = this.networkType === NetworkType.Mainnet
|
||||
? import.meta.glob('../../chains/mainnet/*.json', {eager: true})
|
||||
: import.meta.glob('../../chains/testnet/*.json', {eager: true})
|
||||
Object.values<LocalConfig>(source).forEach((x: LocalConfig) => {
|
||||
this.chains[x.chain_name] = fromLocal(x)
|
||||
})
|
||||
this.setupDefault()
|
||||
this.status = LoadingStatus.Loaded
|
||||
},
|
||||
setupDefault() {
|
||||
if(this.length > 0) {
|
||||
const blockchain = useBlockchain()
|
||||
for(let i=0; i < this.favorite.length; i++) {
|
||||
if(!blockchain.chainName && this.chains[this.favorite[i]]) {
|
||||
blockchain.setCurrent(this.favorite[i])
|
||||
}
|
||||
}
|
||||
if(!blockchain.chainName) {
|
||||
const [first] = Object.keys(this.chains)
|
||||
blockchain.setCurrent(first)
|
||||
}
|
||||
}
|
||||
},
|
||||
setConfigSource(newSource: ConfigSource) {
|
||||
this.source = newSource
|
||||
this.initial()
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,19 @@
|
||||
import { defineStore } from "pinia";
|
||||
import { useBlockchain } from "./useBlockchain";
|
||||
|
||||
export const useDistributionStore = defineStore('distributionStore', {
|
||||
state: () => {
|
||||
return {
|
||||
}
|
||||
},
|
||||
getters: {
|
||||
blockchain() {
|
||||
return useBlockchain()
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
async fetchCommunityPool() {
|
||||
return this.blockchain.rpc.communityPool()
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,160 @@
|
||||
import { defineStore } from "pinia";
|
||||
import { useBlockchain } from "./useBlockchain";
|
||||
import Long from "long";
|
||||
import numeral from "numeral";
|
||||
import dayjs from 'dayjs';
|
||||
import duration from 'dayjs/plugin/duration'
|
||||
import relativeTime from 'dayjs/plugin/relativeTime'
|
||||
import updateLocale from 'dayjs/plugin/updateLocale'
|
||||
import utc from 'dayjs/plugin/utc'
|
||||
import localeData from 'dayjs/plugin/localeData'
|
||||
import { useStakingStore } from "./useStakingStore";
|
||||
import { fromBech32, toBase64, toHex } from "@cosmjs/encoding";
|
||||
import { consensusPubkeyToHexAddress, operatorAddressToAccount } from "@/libs";
|
||||
|
||||
dayjs.extend(localeData)
|
||||
dayjs.extend(duration)
|
||||
dayjs.extend(relativeTime)
|
||||
dayjs.extend(updateLocale)
|
||||
dayjs.extend(utc)
|
||||
dayjs.updateLocale('en', {
|
||||
relativeTime: {
|
||||
future: 'in %s',
|
||||
past: '%s ago',
|
||||
s: '%ds',
|
||||
m: '1m',
|
||||
mm: '%dm',
|
||||
h: 'an hour',
|
||||
hh: '%d hours',
|
||||
d: 'a day',
|
||||
dd: '%d days',
|
||||
M: 'a month',
|
||||
MM: '%d months',
|
||||
y: 'a year',
|
||||
yy: '%d years',
|
||||
},
|
||||
})
|
||||
|
||||
export const useFormatter = defineStore('formatter', {
|
||||
state: () => {
|
||||
return {
|
||||
}
|
||||
},
|
||||
getters: {
|
||||
blockchain() {
|
||||
return useBlockchain()
|
||||
},
|
||||
staking() {
|
||||
return useStakingStore()
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
formatTokenAmount(token: {denom: string, amount: string;}) {
|
||||
return this.formatToken(token, false)
|
||||
},
|
||||
formatToken2(token: { denom: string, amount: string;}, withDenom = true) {
|
||||
return this.formatToken(token, true, '0,0.[00]')
|
||||
},
|
||||
formatToken(token: { denom: string, amount: string;}, withDenom = true, fmt='0.0a') : string {
|
||||
if(token && token.amount) {
|
||||
let amount = Number(token.amount)
|
||||
let denom = token.denom
|
||||
const conf = this.blockchain.current?.assets?.find(x => x.base === token.denom || x.base.denom === token.denom)
|
||||
if(conf) {
|
||||
let unit = {exponent: 6, denom: ''}
|
||||
// find the max exponent for display
|
||||
conf.denom_units.forEach(x => {
|
||||
if(x.exponent >= unit.exponent) {
|
||||
unit = x
|
||||
}
|
||||
})
|
||||
if(unit && unit.exponent > 0) {
|
||||
amount = amount / Math.pow(10, unit.exponent || 6)
|
||||
denom = unit.denom.toUpperCase()
|
||||
}
|
||||
}
|
||||
return `${numeral(amount).format(fmt)} ${withDenom ? denom: ''}`
|
||||
}
|
||||
return '-'
|
||||
},
|
||||
formatTokens(tokens?: { denom: string, amount: string;}[], withDenom = true, fmt='0.0a') : string {
|
||||
if(!tokens) return ''
|
||||
return tokens.map(x => this.formatToken(x, withDenom, fmt)).join(', ')
|
||||
},
|
||||
calculateBondedRatio(pool: {bonded_tokens: string, not_bonded_tokens: string}|undefined) {
|
||||
if(pool && pool.bonded_tokens) {
|
||||
const b = Number(pool.bonded_tokens)
|
||||
const nb = Number(pool.not_bonded_tokens)
|
||||
const p = b/(b+nb)
|
||||
console.log(b, nb, p, pool)
|
||||
return numeral(p).format('0.[00]%')
|
||||
}
|
||||
return '-'
|
||||
},
|
||||
validator(address: Uint8Array) {
|
||||
const txt = toHex(address).toUpperCase()
|
||||
const validator = this.staking.validators.find(x => consensusPubkeyToHexAddress(x.consensusPubkey) === txt)
|
||||
return validator?.description?.moniker
|
||||
},
|
||||
calculatePercent(input?: string, total?: string|number ) {
|
||||
if(!input || !total) return '0'
|
||||
const percent = Number(input)/Number(total)
|
||||
return numeral(percent).format("0.[00]%")
|
||||
},
|
||||
formatDecimalToPercent(decimal: string) {
|
||||
return numeral(decimal).format('0.[00]%')
|
||||
},
|
||||
formatCommissionRate(v?: string) {
|
||||
console.log(v)
|
||||
if(!v) return '-'
|
||||
const rate = Number(v) / Number("1000000000000000000")
|
||||
return this.percent(rate)
|
||||
},
|
||||
percent(decimal?: string|number) {
|
||||
return decimal ? numeral(decimal).format('0.[00]%') : '-'
|
||||
},
|
||||
numberAndSign(input: number, fmt="+0,0") {
|
||||
return numeral(input).format(fmt)
|
||||
},
|
||||
toDay(time?: string, format = 'long') {
|
||||
if(!time) return ''
|
||||
if (format === 'long') {
|
||||
return dayjs(time).format('YYYY-MM-DD HH:mm')
|
||||
}
|
||||
if (format === 'date') {
|
||||
return dayjs(time).format('YYYY-MM-DD')
|
||||
}
|
||||
if (format === 'time') {
|
||||
return dayjs(time).format('HH:mm:ss')
|
||||
}
|
||||
if (format === 'from') {
|
||||
return dayjs(time).fromNow()
|
||||
}
|
||||
if (format === 'to') {
|
||||
return dayjs(time).toNow()
|
||||
}
|
||||
return dayjs(time).format('YYYY-MM-DD HH:mm:ss')
|
||||
},
|
||||
messages(msgs: {typeUrl: string}[]) {
|
||||
if(msgs) {
|
||||
const sum: Record<string, number> = msgs.map(msg => {
|
||||
return msg.typeUrl.substring(msg.typeUrl.lastIndexOf('.') + 1).replace('Msg', '')
|
||||
}).reduce((s, c) => {
|
||||
const sh: Record<string, number> = s
|
||||
if (sh[c]) {
|
||||
sh[c] += 1
|
||||
} else {
|
||||
sh[c] = 1
|
||||
}
|
||||
return sh
|
||||
}, {})
|
||||
const output: string[] = []
|
||||
Object.keys(sum).forEach(k => {
|
||||
output.push(sum[k] > 1 ? `${k}×${sum[k]}` : k)
|
||||
})
|
||||
return output.join(', ')
|
||||
}
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
import { defineStore } from "pinia";
|
||||
import { useBlockchain } from "./useBlockchain";
|
||||
import { createGovRestClientForChain } from "@/libs/client";
|
||||
import { Tendermint34Client } from "@cosmjs/tendermint-rpc";
|
||||
import { QueryClient } from "@cosmjs/stargate";
|
||||
|
||||
export const useGovStore = defineStore('govStore', {
|
||||
state: () => {
|
||||
return {
|
||||
params: {
|
||||
deposit: {} as DepositParams,
|
||||
voting: {} as VotingParams,
|
||||
tally: {} as TallyParams,
|
||||
}
|
||||
}
|
||||
},
|
||||
getters: {
|
||||
blockchain() {
|
||||
return useBlockchain()
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
initial() {
|
||||
this.fetchParams()
|
||||
},
|
||||
async fetchProposals( proposalStatus: ProposalStatus, pagination?: PageRequest ) {
|
||||
const param = {
|
||||
proposalStatus,
|
||||
voter: '',
|
||||
depositor: '',
|
||||
pagination,
|
||||
}
|
||||
const proposals = await this.blockchain.rpc.proposals(proposalStatus, '', '')
|
||||
console.log(proposals)
|
||||
return proposals
|
||||
},
|
||||
async fetchParams() {
|
||||
// this.blockchain.rpc.govParam().then(x => {
|
||||
// this.params.deposit = x.deposit
|
||||
// })
|
||||
},
|
||||
async fetchTally(proposalId: number) {
|
||||
return this.blockchain.rpc.tally(proposalId)
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,27 @@
|
||||
import { defineStore } from "pinia";
|
||||
import { useBlockchain } from "./useBlockchain";
|
||||
|
||||
export const useMintStore = defineStore('mintStore', {
|
||||
state: () => {
|
||||
return {
|
||||
inflation: "0",
|
||||
}
|
||||
},
|
||||
getters: {
|
||||
blockchain() {
|
||||
return useBlockchain()
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
initial() {
|
||||
this.fetchInflation()
|
||||
},
|
||||
async fetchInflation() {
|
||||
this.blockchain.rpc.inflation().then(x => {
|
||||
this.inflation = x.inflation
|
||||
}).catch(() => {
|
||||
this.inflation = "0"
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,64 @@
|
||||
import { defineStore } from "pinia";
|
||||
import { useBlockchain } from "./useBlockchain";
|
||||
|
||||
import { get } from "@/libs/http";
|
||||
|
||||
export const useStakingStore = defineStore('stakingStore', {
|
||||
state: () => {
|
||||
return {
|
||||
validators: [] as Validator[],
|
||||
params: {} as QueryParamsResponse,
|
||||
pool: {} as Pool | undefined,
|
||||
}
|
||||
},
|
||||
getters: {
|
||||
totalPower(): number {
|
||||
const sum = (s:number, e: Validator) => { return s + parseInt(e.delegatorShares) }
|
||||
return this.validators ? this.validators.reduce(sum, 0): 0
|
||||
},
|
||||
blockchain() {
|
||||
return useBlockchain()
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
async init() {
|
||||
this.$reset()
|
||||
this.fetchPool()
|
||||
this.fetchAcitveValdiators()
|
||||
return await this.fetchParams()
|
||||
},
|
||||
async keybase(identity: string) {
|
||||
return get(`https://keybase.io/_/api/1.0/user/lookup.json?key_suffix=${identity}&fields=pictures`)
|
||||
},
|
||||
async fetchParams() {
|
||||
const response = await this.blockchain.rpc.stakingParams()
|
||||
if(response.params) this.params = response.params
|
||||
return this.params
|
||||
},
|
||||
async fetchPool() {
|
||||
const response = await this.blockchain.rpc.stakingPool()
|
||||
this.pool = response.pool
|
||||
},
|
||||
async fetchAcitveValdiators() {
|
||||
return this.fetchValidators('BOND_STATUS_BONDED')
|
||||
},
|
||||
async fetchInacitveValdiators() {
|
||||
return this.fetchValidators('BOND_STATUS_UNBONDED')
|
||||
},
|
||||
async fetchValidator(validatorAddr: string) {
|
||||
return this.blockchain.rpc.validator(validatorAddr)
|
||||
},
|
||||
async fetchValidatorDelegation(validatorAddr: string, delegatorAddr: string) {
|
||||
return (await this.blockchain.rpc.validatorDelegation(validatorAddr, delegatorAddr)).delegationResponse
|
||||
},
|
||||
async fetchValidators(status: string) {
|
||||
return this.blockchain.rpc.validators(status, undefined).then(res => {
|
||||
const vals = res.validators.sort((a, b) => (Number(b.delegatorShares) - Number(a.delegatorShares)))
|
||||
if(status==='BOND_STATUS_BONDED') {
|
||||
this.validators = vals
|
||||
}
|
||||
return vals
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user