diff --git a/src/chains/mainnet/celestia.json b/src/chains/mainnet/celestia.json new file mode 100644 index 00000000..64e969bd --- /dev/null +++ b/src/chains/mainnet/celestia.json @@ -0,0 +1,17 @@ +{ + "chain_name": "celestia", + "coingecko": "", + "api": "https://celestia-api.skynetvalidators.com", + "sdk_version": "0.44.0", + "coin_type": "118", + "min_tx_fee": "800", + "addr_prefix": "celestia", + "logo": "https://explorer-images.s3.filebase.com/celestia-logo.png", + "assets": [{ + "base": "celes", + "symbol": "CELES", + "exponent": "0", + "coingecko_id": "", + "logo": "https://explorer-images.s3.filebase.com/celestia-logo.png" + }] +} diff --git a/src/chains/mainnet/cht.json b/src/chains/mainnet/cht.json new file mode 100644 index 00000000..324b896d --- /dev/null +++ b/src/chains/mainnet/cht.json @@ -0,0 +1,23 @@ +{ + "chain_name": "chronic-token", + "coingecko": "", + "api": "https://chtd-api.skynetvalidators.com", + "sdk_version": "0.44.5", + "coin_type": "118", + "min_tx_fee": "800", + "addr_prefix": "chronic", + "logo": "https://explorer-images.s3.filebase.com/cht-logo.jpg", + "assets": [{ + "base": "ucgas", + "symbol": "CGAS", + "exponent": "6", + "coingecko_id": "", + "logo": "https://explorer-images.s3.filebase.com/cht-logo.jpg" + },{ + "base": "ucht", + "symbol": "CHT", + "exponent": "6", + "coingecko_id": "ion", + "logo": "https://explorer-images.s3.filebase.com/cht-logo.jpg" + }] +} diff --git a/src/chains/mainnet/coho.json b/src/chains/mainnet/coho.json new file mode 100644 index 00000000..7143cf50 --- /dev/null +++ b/src/chains/mainnet/coho.json @@ -0,0 +1,16 @@ +{ + "chain_name": "cosmic-horizon", + "api": ["https://coho-api.skynetvalidators.com"], + "sdk_version": "0.44.5", + "coin_type": "118", + "min_tx_fee": "300", + "assets": [{ + "base": "ucoho", + "symbol": "COHO", + "exponent": "6", + "coingecko_id": "", + "logo": "https://coho-images.s3.filebase.com/red_logo.png" + }], + "addr_prefix": "coho", + "logo": "https://coho-images.s3.filebase.com/red_logo.png" +} diff --git a/src/chains/mainnet/dws.json b/src/chains/mainnet/dws.json new file mode 100644 index 00000000..ec8d817c --- /dev/null +++ b/src/chains/mainnet/dws.json @@ -0,0 +1,17 @@ +{ + "chain_name": "DWS", + "coingecko": "", + "api": "https://dws-api.skynetvalidators.com", + "sdk_version": "0.44.3", + "coin_type": "118", + "min_tx_fee": "200", + "addr_prefix": "deweb", + "logo": "https://dws-images.s3.filebase.com/logo.png", + "assets": [{ + "base": "udws", + "symbol": "DWS", + "exponent": "6", + "coingecko_id": "", + "logo": "https://dws-images.s3.filebase.com/logo.png" + }] +} diff --git a/src/chains/mainnet/omniflix.json b/src/chains/mainnet/omniflix.json new file mode 100644 index 00000000..f6ad4e59 --- /dev/null +++ b/src/chains/mainnet/omniflix.json @@ -0,0 +1,17 @@ +{ + "chain_name": "omniflix", + "coingecko": "", + "api": "https://omniflixhub-api.skynetvalidators.com", + "sdk_version": "0.45.1", + "coin_type": "118", + "min_tx_fee": "3000", + "addr_prefix": "omniflix", + "logo": "https://explorer-images.s3.filebase.com/omniflix-alpha-logo.png", + "assets": [{ + "base": "uflix", + "symbol": "FLIX", + "exponent": "6", + "coingecko_id": "", + "logo": "https://explorer-images.s3.filebase.com/omniflix-alpha-logo.png" + }] +} diff --git a/src/libs/fetch.js b/src/libs/fetch.js index 4bb1830d..bc17ec8f 100644 --- a/src/libs/fetch.js +++ b/src/libs/fetch.js @@ -71,8 +71,8 @@ export default class ChainFetch { return this.get(`/blocks/${height}`, config).then(data => Block.create(data)) } - async getSlashingSigningInfo() { - return this.get('/cosmos/slashing/v1beta1/signing_infos') + async getSlashingSigningInfo(config = null) { + return this.get('/cosmos/slashing/v1beta1/signing_infos?pagination.limit=500', config) } async getTxs(hash) { @@ -140,8 +140,8 @@ export default class ChainFetch { }) } - async getValidatorList() { - return this.get('/staking/validators').then(data => { + async getValidatorList(config = null) { + return this.get('/staking/validators', config).then(data => { const vals = commonProcess(data).map(i => new Validator().init(i)) localStorage.setItem(`validators-${this.config.chain_name}`, JSON.stringify(vals)) return vals @@ -157,15 +157,15 @@ export default class ChainFetch { } async getValidatorListByStatus(status) { - return this.get(`/cosmos/staking/v1beta1/validators?status=${status}`).then(data => { + return this.get(`/cosmos/staking/v1beta1/validators?status=${status}&pagination.limit=500`).then(data => { const result = commonProcess(data) const vals = result.validators ? result.validators : result return vals.map(i => new Validator().init(i)) }) } - async getValidatorListByHeight(height) { - return this.get(`/validatorsets/${height}`).then(data => commonProcess(data)) + async getValidatorListByHeight(height, offset) { + return this.get(`/cosmos/base/tendermint/v1beta1/validatorsets/${height}?pagination.limit=100&pagination.offset=${offset}`).then(data => commonProcess(data)) } async getStakingValidator(address) { diff --git a/src/views/Staking.vue b/src/views/Staking.vue index 58040931..a644a2b6 100644 --- a/src/views/Staking.vue +++ b/src/views/Staking.vue @@ -93,7 +93,7 @@ no-body > - + Validators {{ validators.length }}/{{ stakingParameters.max_validators }} - + { const xh = x - const change = this.changes[x.consensus_pubkey.value] + const change = this.changes[x.consensus_pubkey.key] if (change) { xh.changes = change.latest - change.previous } @@ -326,28 +327,7 @@ export default { }, }, created() { - this.$http.getValidatorListByHeight('latest').then(data => { - let height = Number(data.block_height) - if (height > 14400) { - height -= 14400 - } else { - height = 1 - } - const changes = [] - data.validators.forEach(x => { - changes[x.pub_key.value] = { latest: Number(x.voting_power), previous: 0 } - }) - this.$http.getValidatorListByHeight(height).then(previous => { - previous.validators.forEach(x => { - if (changes[x.pub_key.value]) { - changes[x.pub_key.value].previous = Number(x.voting_power) - } else { - changes[x.pub_key.value] = { latest: 0, previous: Number(x.voting_power) } - } - }) - this.$set(this, 'changes', changes) - }) - }) + this.getValidatorListByHeight() this.$http.getStakingParameters().then(res => { this.stakingParameters = res }) @@ -357,6 +337,30 @@ export default { this.islive = false }, methods: { + getValidatorListByHeight(offset = 0) { + this.$http.getValidatorListByHeight('latest', offset).then(data => { + let height = Number(data.block_height) + if (height > 14400) { + height -= 14400 + } else { + height = 1 + } + const { changes } = this + data.validators.forEach(x => { + changes[x.pub_key.key] = { latest: Number(x.voting_power), previous: 0 } + }) + this.$http.getValidatorListByHeight(height, offset).then(previous => { + previous.validators.forEach(x => { + if (changes[x.pub_key.key]) { + changes[x.pub_key.key].previous = Number(x.voting_power) + } else { + changes[x.pub_key.key] = { latest: 0, previous: Number(x.voting_power) } + } + }) + this.$set(this, 'changes', changes) + }) + }) + }, getValidatorListByStatus(statusList) { this.validators = [] statusList.forEach(status => { @@ -375,6 +379,9 @@ export default { } } this.stakingPool = total + if (total > 100) { + this.getValidatorListByHeight(100) + } this.validators.push(...temp) // fetch avatar from keybase diff --git a/src/views/Uptime.vue b/src/views/Uptime.vue index 288e7f37..188b4b9b 100644 --- a/src/views/Uptime.vue +++ b/src/views/Uptime.vue @@ -19,10 +19,20 @@ > Browse favorite only - + + + + + + - {{ index+1 }} {{ x.validator.moniker }} - +
+ {{ index+1 }} {{ x.validator.moniker }} + + + + {{ missing[x.address].missed_blocks_counter }} + + + 0 + + +
import { - BRow, BCol, VBTooltip, BFormInput, BCard, BAlert, BFormCheckbox, BButton, + BRow, BCol, VBTooltip, BFormInput, BCard, BAlert, BFormCheckbox, BButton, BBadge, BInputGroup, BInputGroupPrepend, } from 'bootstrap-vue' import { consensusPubkeyToHexAddress, getCachedValidators, timeIn, toDay, } from '@/libs/utils' +import { Bech32, toHex } from '@cosmjs/encoding' export default { components: { @@ -77,7 +111,10 @@ export default { BCard, BAlert, BButton, + BBadge, BFormCheckbox, + BInputGroup, + BInputGroupPrepend, }, directives: { 'b-tooltip': VBTooltip, @@ -86,6 +123,7 @@ export default { const { chain } = this.$route.params const pinned = localStorage.getItem('pinned') ? localStorage.getItem('pinned').split(',') : '' return { + missedFilter: false, pinned, chain, query: '', @@ -100,10 +138,14 @@ export default { uptime() { const vals = this.query ? this.validators.filter(x => String(x.description.moniker).indexOf(this.query) > -1) : this.validators vals.sort((a, b) => b.delegator_shares - a.delegator_shares) - return vals.map(x => ({ + const rets = vals.map(x => ({ validator: x.description, address: consensusPubkeyToHexAddress(x.consensus_pubkey), })) + if (this.missedFilter) { + return rets.filter(x => this.missing[x.address].missed_blocks_counter > 0) + } + return rets }, }, created() { @@ -115,6 +157,16 @@ export default { this.$http.getValidatorList().then(res => { this.validators = res }) + this.$http.getSlashingSigningInfo().then(res => { + if (res.info) { + res.info.forEach(x => { + if (x.address) { + const hex = toHex(Bech32.decode(x.address).data).toUpperCase() + this.missing[hex] = x + } + }) + } + }) this.initBlocks() }, beforeDestroy() { diff --git a/src/views/UptimeMyChainBlocks.vue b/src/views/UptimeMyChainBlocks.vue index 8d9ff33b..7abcb12d 100644 --- a/src/views/UptimeMyChainBlocks.vue +++ b/src/views/UptimeMyChainBlocks.vue @@ -23,14 +23,37 @@ sm="12" class="text-truncate" > - - {{ x.validator.moniker }} - +
+ + {{ x.validator.moniker }} + + + + {{ missing[x.address].missed_blocks_counter }} + + + 0 + + +
import { - BRow, BCol, VBTooltip, BCard, BAlert, BCardTitle, BFormCheckbox, + BRow, BCol, VBTooltip, BCard, BAlert, BCardTitle, BFormCheckbox, BBadge, } from 'bootstrap-vue' import { getLocalChains, timeIn, toDay, } from '@/libs/utils' +import { Bech32, toHex } from '@cosmjs/encoding' export default { name: 'Blocks', components: { + BBadge, BRow, BCol, BCard, @@ -105,6 +130,16 @@ export default { }, created() { this.initBlocks() + this.$http.getSlashingSigningInfo(this.config).then(res => { + if (res.info) { + res.info.forEach(x => { + if (x.address) { + const hex = toHex(Bech32.decode(x.address).data).toUpperCase() + this.missing[hex] = x + } + }) + } + }) }, beforeDestroy() { this.blocks = [] // clear running tasks if it is not finish diff --git a/src/views/UptimeMyValidators.vue b/src/views/UptimeMyValidators.vue index ddab0d7b..6fc98379 100644 --- a/src/views/UptimeMyValidators.vue +++ b/src/views/UptimeMyValidators.vue @@ -1,6 +1,6 @@