Merge branch 'master' into patch-1

This commit is contained in:
ping
2023-02-05 08:47:00 +08:00
committed by GitHub
70 changed files with 1433 additions and 565 deletions
@@ -31,7 +31,7 @@
{{ chainname }}
</b-breadcrumb-item>
<b-breadcrumb-item
v-for="item in $route.meta.breadcrumb"
v-for="item in breadcrumb"
:key="item.text"
:active="item.active"
:to="item.to"
@@ -75,6 +75,14 @@ export default {
chainname() {
return this.$store?.state?.chains?.selected?.chain_name
},
/**
* Invoke `route.meta.breadcrumb($route)` if breadcrumb is callable.
*/
breadcrumb() {
const { breadcrumb } = this.$route.meta
const breadcrumbIsCallable = typeof breadcrumb === 'function'
return breadcrumbIsCallable ? breadcrumb(this.$route) : breadcrumb
},
},
}
</script>
+10 -10
View File
@@ -1,53 +1,53 @@
export default () => ([
{
scope: 'normal',
title: 'dashboard',
title: 'dashboard.dashboard',
route: 'dashboard',
},
{
scope: 'normal',
title: 'blocks',
title: 'dashboard.blocks',
route: 'blocks',
},
{
scope: 'normal',
title: 'staking',
title: 'dashboard.staking',
route: 'staking',
},
{
scope: 'normal',
title: 'governance',
title: 'dashboard.governance',
route: 'governance',
exclude: 'emoney',
},
{
scope: 'normal',
title: 'uptime',
title: 'dashboard.uptime',
route: 'uptime',
},
{
scope: 'normal',
title: 'parameters',
title: 'dashboard.parameters',
route: 'parameters',
},
{
scope: 'normal',
title: 'statesync',
title: 'dashboard.statesync',
route: 'statesync',
},
{
scope: 'normal',
title: 'consensus',
title: 'dashboard.consensus',
route: 'consensus',
},
{
scope: 'cos-mos',
title: 'gravity',
title: 'dashboard.gravity',
route: 'gravity',
},
{
scope: 'osmosis',
title: 'trade',
title: 'dashboard.trade',
route: 'osmosis-trade',
},
])
@@ -22,3 +22,28 @@
.progress {
border-radius: 3px;
}
.scale {
width: 100%;
height: 3em;
position: relative;
/* margin: 30px; // */
}
.box {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
padding-top: 0.5em;
/* opacity: 0.7; /**/
background: transparent;
}
.overlay {
z-index: 9;
width: 2px;
border-right-color: green;
border-right-width: 2px;
border-right-style: dotted;
}
-1
View File
@@ -1,7 +1,6 @@
{
"chain_name": "agoric",
"api": [
"https://api.agoric.sgtstake.com",
"https://agoric-api.polkachu.com",
"https://api-agoric.nodes.guru",
"https://agoric.stakesystems.io",
+1 -1
View File
@@ -4,7 +4,7 @@
"api": ["https://rest.getbze.com"],
"rpc": ["https://rpc-1.getbze.com:443","https://rpc-2.getbze.com:443"],
"snapshot_provider": ["a9fac0534bd6853f5810fdc692564967bd01b1fe@rpc-1.getbze.com:26656"],
"sdk_version": "0.44.3",
"sdk_version": "0.45.9",
"coin_type": "370",
"min_tx_fee": "8000",
"addr_prefix": "bze",
+1 -1
View File
@@ -6,7 +6,7 @@
"snapshot_provider": "29edc55748bc341224f711a05cb0a9f6d73b4da3@bitcanna.rpc.ping.pub:26656",
"sdk_version": "0.45.10",
"coin_type": "118",
"min_tx_fee": "8000",
"min_tx_fee": "420",
"assets": [{
"base": "ubcna",
"symbol": "BCNA",
+16
View File
@@ -0,0 +1,16 @@
{
"chain_name": "chain4energy",
"api": ["https://lcd.c4e.io"],
"rpc": ["https://rpc.c4e.io:443", "https://rpc.c4e.io:443"],
"sdk_version": "0.45.5",
"coin_type": "4444",
"min_tx_fee": "3000",
"addr_prefix": "c4e",
"logo": "/logos/c4e.png",
"assets": [{
"base": "uc4e",
"symbol": "C4E",
"exponent": "6",
"logo": "/logos/c4e.png"
}]
}
+17
View File
@@ -0,0 +1,17 @@
{
"chain_name": "cronos",
"api": ["https://rest.cronos.org"],
"rpc": ["https://rpc.cronos.org:443"],
"snapshot_provider": "",
"sdk_version": "0.45.11",
"coin_type": "60",
"min_tx_fee": "5000000000000000",
"addr_prefix": "crc",
"logo": "/logos/cronos.png",
"assets": [{
"base": "basecro",
"symbol": "CRO",
"exponent": "18"
}]
}
+8 -2
View File
@@ -1,7 +1,7 @@
{
"chain_name": "injective",
"api": "https://lcd.injective.network",
"rpc": ["https://injective-rpc.api.chainlayer.network:443", "https://injective-rpc.api.chainlayer.network:443"],
"api": ["https://lcd.injective.network", "https://injective-api.polkachu.com"],
"rpc": ["https://tm.injective.network", "https://injective-rpc.polkachu.com"],
"snapshot_provider": "",
"sdk_version": "v0.45.5",
"coin_type": "60",
@@ -9,6 +9,12 @@
"addr_prefix": "inj",
"excludes": "",
"logo": "/logos/injective.jpg",
"keplr_features": ["ibc-transfer", "ibc-go", "eth-address-gen", "eth-key-sign"],
"keplr_price_step": {
"low": 100000000000,
"average": 200000000000,
"high": 30000000000000
},
"assets": [{
"base": "inj",
"symbol": "INJ",
+21 -11
View File
@@ -1,18 +1,28 @@
{
"chain_name": "jackal",
"coingecko": "",
"api": ["https://api.jackalprotocol.com", "https://jackal-api.polkachu.com","https://api.jackal.nodestake.top"],
"rpc": ["https://rpc.jackalprotocol.com", "https://jackal-rpc.polkachu.com","https://rpc.jackal.nodestake.top"],
"coingecko": "jackal-protocol",
"api": [
"https://api.jackalprotocol.com",
"https://jackal-api.polkachu.com",
"https://api.jackal.nodestake.top"
],
"rpc": [
"https://rpc.jackalprotocol.com",
"https://jackal-rpc.polkachu.com",
"https://rpc.jackal.nodestake.top"
],
"snapshot_provider": "",
"coin_type": "118",
"sdk_version": "0.45.9",
"sdk_version": "0.45.11",
"addr_prefix": "jkl",
"logo": "/logos/jackal.png",
"assets": [{
"base": "ujkl",
"symbol": "JKL",
"exponent": "6",
"coingecko_id": "jackal",
"logo": "/logos/jackal.png"
}]
"assets": [
{
"base": "ujkl",
"symbol": "JKL",
"exponent": "6",
"coingecko_id": "jackal",
"logo": "/logos/jackal.png"
}
]
}
+2 -2
View File
@@ -1,8 +1,8 @@
{
"chain_name": "lumenx",
"coingecko": "",
"api": "https://api.helios-1.lumenex.io",
"rpc": ["https://rpc.helios-1.lumenex.io:443","http://node4.lumenex.io:26657"],
"api": ["https://api.lumenx.chaintools.tech:443","https://api-lumenx.cryptonet.pl:443"],
"rpc": ["https://rpc.lumenx.chaintools.tech:443","https://rpc-lumenx.cryptonet.pl:443"],
"snapshot_provider": "",
"sdk_version": "0.45.5",
"coin_type": "118",
+29
View File
@@ -0,0 +1,29 @@
{
"chain_name": "mars",
"coingecko": "",
"api": [
"https://rest.marsprotocol.io",
"https://mars-api.polkachu.com",
"https://rest.cosmos.directory/mars"
],
"rpc": [
"https://rpc.marsprotocol.io",
"https://mars-rpc.polkachu.com",
"https://rpc.marsprotocol.io",
"https://rpc.cosmos.directory/mars"
],
"snapshot_provider": "",
"coin_type": "118",
"sdk_version": "0.46.8",
"addr_prefix": "mars",
"logo": "/logos/mars.png",
"assets": [
{
"base": "umars",
"symbol": "MARS",
"exponent": "6",
"coingecko_id": "",
"logo": "/logos/mars.png"
}
]
}
+19
View File
@@ -0,0 +1,19 @@
{
"chain_name": "planq",
"api": ["https://rest.planq.network"],
"rpc": ["https://rpc.planq.network"],
"snapshot_provider": "",
"sdk_version": "0.46.3",
"coin_type": "60",
"min_tx_fee": "5000000000000000",
"addr_prefix": "plq",
"logo": "/logos/planq.png",
"keplr_features": ["ibc-transfer", "ibc-go", "eth-address-gen", "eth-key-sign"],
"assets": [{
"base": "aplanq",
"symbol": "planq",
"exponent": "18",
"coingecko_id": "",
"logo": "/logos/planq.png"
}]
}
+20
View File
@@ -0,0 +1,20 @@
{
"chain_name": "quicksilver",
"coingecko": "",
"api": ["https://quicksilver-api.polkachu.com", "https://api-quicksilver.nodeist.net"],
"rpc": ["https://quicksilver-rpc.polkachu.com", "https://rpc-quicksilver.nodeist.net"],
"sdk_version": "0.46.7",
"coin_type": "118",
"min_tx_fee": "8000",
"addr_prefix": "quick",
"logo": "/logos/quicksilver.png",
"assets": [
{
"base": "uqck",
"symbol": "QCK",
"exponent": "6",
"coingecko_id": "",
"logo": "/logos/quicksilver.png"
}
]
}
+2 -2
View File
@@ -1,7 +1,7 @@
{
"chain_name": "rebus",
"api": ["https://api.mainnet.rebus.money:1317", "https://rebus.api.kjnodes.com"],
"rpc": ["https://api.mainnet.rebus.money:26657", "https://rebus.rpc.kjnodes.com:443"],
"api": ["https://api.mainnet.rebus.money:1317","https://api.rebus.nodestake.top"],
"rpc": ["https://api.mainnet.rebus.money:26657","https://rpc.rebus.nodestake.top"],
"snapshot_provider": "",
"sdk_version": "0.45.6",
"coin_type": "118",
+2 -2
View File
@@ -1,8 +1,8 @@
{
"chain_name": "secret",
"coingecko": "secret",
"api": ["https://api.roninventures.io","https://api.scrt.network"],
"rpc": ["http://beta-api.scrt.network:26657", "https://api.scrt.network:443"],
"api": ["https://lcd.spartanapi.dev", "https://secretnetwork-lcd.stakely.io"],
"rpc": ["https://rpc.spartanapi.dev", "https://secretnetwork-rpc.stakely.io"],
"snapshot_provider": "",
"sdk_version": "0.45.4",
"coin_type": "529",
+3 -3
View File
@@ -2,10 +2,10 @@
{
"chain_name": "shentu",
"coingecko": "certik",
"api": ["https://certik-api.polkachu.com/", "https://shentu-api.panthea.eu", "https://chainfull.noopsbycertik.com"],
"rpc": ["https://certik-rpc.polkachu.com:443", "https://shentu-rpc.panthea.eu:443"],
"api": ["https://certik-api.polkachu.com", "https://chainfull.noopsbycertik.com"],
"rpc": ["https://certik-rpc.polkachu.com:443"],
"snapshot_provider": "",
"sdk_version": "0.45.4",
"sdk_version": "0.45.9",
"coin_type": "118",
"min_tx_fee": "8000",
"addr_prefix": "certik",
+2 -2
View File
@@ -1,7 +1,7 @@
{
"chain_name": "teritori",
"api": ["https://rest.mainnet.teritori.com", "https://teritori.api.kjnodes.com"],
"rpc": ["https://rpc.mainnet.teritori.com", "https://teritori.rpc.kjnodes.com:443"],
"api": ["https://rest.mainnet.teritori.com","https://api.teritori.nodestake.top"],
"rpc": ["https://rpc.mainnet.teritori.com","https://rpc.teritori.nodestake.top"],
"snapshot_provider": "",
"sdk_version": "0.45.4",
"coin_type": "118",
+3 -3
View File
@@ -1,9 +1,9 @@
{
"chain_name": "vidulum",
"coingecko": "vidulum",
"api": ["https://mainnet-lcd.vidulum.app", "https://api-vidulum-ia.cosmosia.notional.ventures", "https://rest.rpc.erialos.me"],
"rpc": ["https://trpc.rpc.erialos.me:443","https://rpc-vidulum-ia.cosmosia.notional.ventures:443", "https://mainnet-rpc.vidulum.app:443"],
"snapshot_provider": "c32903505e9ab811ac46306d2913c98ccf4883ce@rpc.erialos.me:26656",
"api": ["https://mainnet-lcd.vidulum.app", "https://api-vidulum-ia.cosmosia.notional.ventures"],
"rpc": ["https://mainnet-rpc.vidulum.app:443", "https://rpc-vidulum-ia.cosmosia.notional.ventures:443"],
"snapshot_provider": "",
"sdk_version": "0.45.9",
"coin_type": "370",
"min_tx_fee": "8000",
+20
View File
@@ -0,0 +1,20 @@
{
"chain_name": "apollo",
"provider_chain": {
"api": "https://rest.provider-sentry-01.goc.earthball.xyz"
},
"api": ["https://apollo.api.ping.pub"],
"rpc": [],
"sdk_version": "0.45.7",
"coin_type": 118,
"min_tx_fee": "0",
"addr_prefix": "cosmos",
"logo": "/logos/game_of_chain.jpeg",
"assets": [{
"base": "upol",
"symbol": "POL",
"exponent": "6",
"coingecko_id": "",
"logo": "/logos/game_of_chain.jpeg"
}]
}
+19
View File
@@ -0,0 +1,19 @@
{
"chain_name": "canto",
"api": ["https://canto-testnet.ansybl.io/api"],
"rpc": ["https://canto-testnet.ansybl.io/rpc"],
"snapshot_provider": "",
"sdk_version": "0.45.6",
"coin_type": "60",
"min_tx_fee": "800",
"addr_prefix": "canto",
"logo": "/logos/canto.png",
"assets": [
{
"base": "acanto",
"symbol": "CANTO",
"exponent": "18"
}
]
}
+19
View File
@@ -0,0 +1,19 @@
{
"chain_name": "celestia",
"coingecko": "",
"api": ["https://celestia-testnet-api.polkachu.com"],
"rpc": ["https://celestia-testnet-rpc.polkachu.com"],
"snapshot_provider": "",
"sdk_version": "0.46.0",
"coin_type": "118",
"min_tx_fee": "800",
"addr_prefix": "celestia",
"logo": "/logos/celestia.png",
"assets": [{
"base": "utia",
"symbol": "TIA",
"exponent": "6",
"coingecko_id": "",
"logo": "/logos/celestia.png"
}]
}
+15 -5
View File
@@ -1,7 +1,17 @@
{
"chain_name": "cosmos-vega",
"api":"https://vega.api.ping.pub",
"sdk_version": "0.42.9",
"chain_name": "cosmos",
"api": ["https://vega.api.ping.pub", "https://rest.seed-01.theta-testnet.polypore.xyz", "https://rest.seed-02.theta-testnet.polypore.xyz"],
"rpc": ["https://rpc.seed-01.theta-testnet.polypore.xyz", "https://rpc.seed-02.theta-testnet.polypore.xyz"],
"sdk_version": "0.45.1",
"coin_type": "118",
"min_tx_fee": "800",
"addr_prefix": "cosmos",
"logo": "https://dl.airtable.com/.attachments/e54f814bba8c0f9af8a3056020210de0/2d1155fb/cosmos-hub.svg"
}
"logo": "/logos/cosmos.svg",
"assets": [{
"base": "uatom",
"symbol": "ATOM",
"exponent": "6",
"coingecko_id": "cosmos",
"logo": "/logos/cosmos.svg"
}]
}
+1
View File
@@ -9,6 +9,7 @@
"min_tx_fee": "3000000000000000",
"addr_prefix": "evmos",
"logo": "/logos/evmos.jpeg",
"keplr_features": ["ibc-transfer", "ibc-go", "eth-address-gen", "eth-key-sign"],
"assets": [{
"base": "atevmos",
"symbol": "TEVMOS",
+20
View File
@@ -0,0 +1,20 @@
{
"chain_name": "hero",
"provider_chain": {
"api": "https://rest.provider-sentry-01.goc.earthball.xyz"
},
"api": ["https://api-c.hero.nodestake.top"],
"rpc": ["https://rpc-c.hero.nodestake.top"],
"sdk_version": "0.45.7",
"coin_type": 118,
"min_tx_fee": "0",
"addr_prefix": "cosmos",
"logo": "/logos/game_of_chain.jpeg",
"assets": [{
"base": "uhero",
"symbol": "HERO",
"exponent": "6",
"coingecko_id": "",
"logo": "/logos/game_of_chain.jpeg"
}]
}
+19 -13
View File
@@ -1,17 +1,23 @@
{
"chain_name": "jackal",
"coingecko": "jackal",
"api": "https://testnet-api.jackalprotocol.com",
"rpc": "https://testnet-rpc.jackalprotocol.com",
"coingecko": "jackal_protocol",
"api": [
"https://testnet-api.jackalprotocol.com"
],
"rpc": [
"https://testnet-rpc.jackalprotocol.com"
],
"coin_type": "118",
"sdk_version": "0.45.9",
"addr_prefix": "jkl",
"sdk_version": "0.45.11",
"addr_prefix": "jkl",
"logo": "/logos/jackal.png",
"assets": [{
"base": "ujkl",
"symbol": "JKL",
"exponent": "6",
"coingecko_id": "jackal",
"logo": "/logos/jackal.png"
}]
}
"assets": [
{
"base": "ujkl",
"symbol": "JKL",
"exponent": "6",
"coingecko_id": "jackal-protocol",
"logo": "/logos/jackal.png"
}
]
}
+2 -2
View File
@@ -1,8 +1,8 @@
{
"chain_name": "osmosis",
"coingecko": "osmosis",
"api": ["https://testnet-rest.osmosis.zone", "https://lcd.osmo-test.ccvalidators.com", "https://osmosistest-lcd.quickapi.com"],
"rpc": ["https://testnet-rpc.osmosis.zone:443", "https://rpc.osmo-test.ccvalidators.com:443"," https://osmosistest-rpc.quickapi.com:443"],
"api": ["https://lcd-test.osmosis.zone", "https://lcd.osmo-test.ccvalidators.com", "https://osmosistest-lcd.quickapi.com"],
"rpc": ["https://rpc-test.osmosis.zone", "https://testnet-rpc.osmosis.zone:443", "https://rpc.osmo-test.ccvalidators.com:443"," https://osmosistest-rpc.quickapi.com:443"],
"snapshot_provider": "",
"sdk_version": "0.44.5",
"coin_type": "118",
+17
View File
@@ -0,0 +1,17 @@
{
"chain_name": "provider",
"api": ["https://rest.provider-sentry-01.goc.earthball.xyz","https://rest.provider-sentry-02.goc.earthball.xyz"],
"rpc": ["https://rpc.provider-sentry-01.goc.earthball.xyz"],
"sdk_version": "0.45.7",
"coin_type": 118,
"min_tx_fee": "0",
"addr_prefix": "cosmos",
"logo": "/logos/game_of_chain.jpeg",
"assets": [{
"base": "uprov",
"symbol": "PROV",
"exponent": "6",
"coingecko_id": "",
"logo": "/logos/game_of_chain.jpeg"
}]
}
+20
View File
@@ -0,0 +1,20 @@
{
"chain_name": "quasar",
"coingecko": "",
"api": ["https://quasar-testnet-api.polkachu.com", "https://lcd-office.cosmostation.io/quasar-testnet"],
"rpc": ["https://quasar-testnet-rpc.polkachu.com", "https://rpc-office.cosmostation.io/quasar-testnet", "https://questnet.quasar-finance.rhinostake.com"],
"sdk_version": "0.45.6",
"coin_type": 118,
"min_tx_fee": "8000",
"addr_prefix": "quasar",
"logo": "/logos/quasar.png",
"assets": [
{
"base": "uqsr",
"symbol": "QSR",
"exponent": 6,
"coingecko_id": "",
"logo": "/logos/quasar.png"
}
]
}
+2 -2
View File
@@ -1,8 +1,8 @@
{
"chain_name": "secret",
"coingecko": "secret",
"api": ["https://api.pulsar.scrttestnet.com","https://lcd.testnet.secretsaturn.net", "https://testnet-api.roninventures.io", "https://pulsar-2.api.trivium.network:1317"],
"rpc": ["https://rpc.pulsar.scrttestnet.com", "https://rpc.testnet.secretsaturn.net", "https://testnet-rpc.roninventures.io", "https://pulsar-2.api.trivium.network:26657"],
"api": ["https://api.pulsar.scrttestnet.com","https://lcd.testnet.secretsaturn.net", "https://pulsar-2.api.trivium.network:1317"],
"rpc": ["https://rpc.pulsar.scrttestnet.com", "https://rpc.testnet.secretsaturn.net", "https://pulsar-2.api.trivium.network:26657"],
"snapshot_provider": "",
"sdk_version": "0.45.4",
"coin_type": "529",
+20
View File
@@ -0,0 +1,20 @@
{
"chain_name": "sputnik",
"provider_chain": {
"api": "https://rest.provider-sentry-01.goc.earthball.xyz"
},
"api": ["https://sputnik.api.ping.pub"],
"rpc": [],
"sdk_version": "0.45.7",
"coin_type": 118,
"min_tx_fee": "0",
"addr_prefix": "cosmos",
"logo": "/logos/game_of_chain.jpeg",
"assets": [{
"base": "unik",
"symbol": "NIK",
"exponent": "6",
"coingecko_id": "",
"logo": "/logos/game_of_chain.jpeg"
}]
}
+143 -57
View File
@@ -2,64 +2,150 @@
"message": {
},
"cosmos": "Cosmos Hub",
"kava": "Kava",
"akash-network": "Akash Decloud",
"iris-network": "IRIS Hub",
"crypto-com-chain": "Crypto.org",
"osmosis": "Osmosis",
"okexchain": "OKEX Chain",
"band-protocol": "Band Protocol",
"terra-luna": "Terra",
"persistence": "Persistence",
"regen": "Regen Network",
"secret": "Secret Network",
"desmos": "Desmos",
"juno": "Juno",
"certik": "Certik",
"sentinel": "Sentinel",
"sifchain": "Sifchain",
"starname": "Starname",
"bitsong": "BitSong",
"e-money": "E-Money",
"omniflix": "OmniFlix",
"likecoin": "LikeCoin",
"stargaze": "Stargaze",
"injective": "Injective Protocal",
"vidulum": "Vidulum",
"kichain": "KI Chain",
"genesisL1": "Genesis L1",
"microtick": "Microtick",
"odin": "ODIN",
"chihuahua": "CHIHUAHUA",
"staking": "Staking",
"governance": "Governance",
"summary": "Summary",
"blocks": "Blocks / Transactions",
"blockchains": "Blockchains",
"uptime": "Uptime",
"statesync": "State Sync",
"trade": "Trade",
"gravity": "Gravity(WIP)",
"pools": "Pools(WIP)",
"chains": {
"cosmos": "Cosmos Hub",
"kava": "Kava",
"akash-network": "Akash Decloud",
"iris-network": "IRIS Hub",
"crypto-com-chain": "Crypto.org",
"osmosis": "Osmosis",
"okexchain": "OKEX Chain",
"band-protocol": "Band Protocol",
"terra-luna": "Terra",
"persistence": "Persistence",
"regen": "Regen Network",
"secret": "Secret Network",
"desmos": "Desmos",
"juno": "Juno",
"certik": "Certik",
"sentinel": "Sentinel",
"sifchain": "Sifchain",
"starname": "Starname",
"bitsong": "BitSong",
"e-money": "E-Money",
"omniflix": "OmniFlix",
"likecoin": "LikeCoin",
"stargaze": "Stargaze",
"injective": "Injective Protocal",
"vidulum": "Vidulum",
"kichain": "KI Chain",
"genesisL1": "Genesis L1",
"microtick": "Microtick",
"odin": "ODIN",
"chihuahua": "CHIHUAHUA",
"proposal_id": "Proposal ID",
"proposal_type": "Proposal Type",
"proposal_proposer": "Proposer",
"proposal_submit_time": "Submited Time",
"proposal_voting_start_time": "Voting Begin Time",
"proposal_voting_end_time": "Voting End Time",
"proposal_description": "Description",
"proposal_content": "Content",
"proposal_total_deposit": "Total Deposit",
"voting_time": "Voting Time",
"upgrade_time": "Estimated Upgrade Time:",
"gravity": "Gravity(WIP)",
"pools": "Pools(WIP)"
},
"btn_vote": "Vote",
"btn_deposit": "Deposit",
"btn_detail": "Detail",
"btn_back_list": "Back To List"
"dashboard": {
"dashboard": "Dashboard",
"staking": "Staking",
"governance": "Governance",
"summary": "Summary",
"blocks": "Blocks / Transactions",
"blockchains": "Blockchains",
"uptime": "Uptime",
"statesync": "State Sync",
"trade": "Trade",
"parameters": "Parameters",
"consensus": "consensus",
"no_new_blocks": "No new blocks have been produced since ",
"active_props": "Active Proposals",
"proposal_votes_yes": "voters voted Yes",
"proposal_votes_no": "voters voted No",
"proposal_votes_nwv": "voters voted No With Veto",
"proposal_votes_abstain": "voters voted Abstain",
"no_active_prop": "No active proposal!",
"browse": "Browse all",
"assets": "Assets",
"more": "More",
"not_conn": "Not Connected?",
"delegate": "Delegate",
"redelegate": "Redelegate",
"unbond": "Unbond",
"withdraw_reward": "Withdraw Rewards",
"unbonding_token": "Unbonding Tokens",
"send": "Send",
"receive": "Receive",
"connect_wal": "Connect Wallet"
},
"governanceProposal": {
"proposal_id": "Proposal ID",
"proposal_type": "Proposal Type",
"proposal_proposer": "Proposer",
"proposal_submit_time": "Submitted Time",
"proposal_voting_start_time": "Voting Begin Time",
"proposal_voting_end_time": "Voting End Time",
"proposal_description": "Description",
"proposal_content": "Content",
"proposal_total_deposit": "Total Deposit",
"proposal_deposits": "Deposits",
"voting_time": "Voting Time",
"upgrade_time": "Estimated Upgrade Time:",
"btn_vote": "Vote",
"btn_deposit": "Deposit",
"btn_detail": "Detail",
"btn_back_list": "Back To List",
"proposal_status": "Status",
"proposal_status_deposit": "Deposit",
"proposal_status_voting": "Voting",
"proposal_status_passed": "Passed",
"proposal_status_rejected": "Rejected",
"proposal_status_start_date": "Start Date",
"proposal_status_end_date": "End Date",
"proposal_votes": "Votes",
"proposal_votes_yes": "voted Yes",
"proposal_votes_no": "voted No",
"proposal_votes_nwv": "voted No With Veto",
"proposal_votes_abstain": "voted Abstain",
"proposal_votes_load": "Load More Votes"
},
"parameters" : {
"no_blocks_produced" : "No new blocks have been produced since ",
"app_ver": "Application Version",
"node_info": "Node Information"
},
"uptimeMyChainBlocks" : {
"height": "Height:",
"no_blocks_produced" : "No new blocks have been produced since ",
"not_active": "Your node is out of active validator set"
},
"walletAccountDetail": {
"address": "Address:",
"assets": "Assets",
"transfer": "Transfer",
"ibc_transfer": "IBC Transfer",
"total": "Total: ",
"unbonding": "Unbonding Tokens",
"from": "From: ",
"delegation": "Delegation",
"delegate": "Delegate",
"withdraw": " Withdraw Rewards",
"acct_type": "Account Type",
"acct_num": "Account Number",
"seq": "Sequence",
"pub_key": "Public Key",
"orig_vest": "Original Vesting",
"delegated_free": "Delegated Free",
"delegated_vest": "Delegated Vesting",
"vest_time": "Vesting Time",
"vest_period": "Vesting Periods",
"length": "Length",
"amount": "Amount",
"end_time": "End Time",
"acct_not_found": "Account not found",
"opps": "Oops!",
"back_home": "Back to home"
},
"uptimeMyValidators": {
"tips": "Tips",
"two_ways": "There are two ways to monitor your validators:",
"pin": "Pin a validator on Uptime pages.",
"link": "Specify parameters like following:"
}
}
+2 -2
View File
@@ -84,9 +84,9 @@
<!-- <dark-Toggler class="d-none d-lg-block" /> -->
<!-- Right Col -->
<b-navbar-nav class="nav align-items-center ml-auto">
<dark-Toggler class="d-none d-lg-block" />
<dark-Toggler />
<search-bar />
<locale />
<locale class="d-none" />
<b-dropdown
class="ml-1"
variant="link"
+5 -5
View File
@@ -9,16 +9,16 @@ export default class ProposalTally {
}
init(element, total) {
const subtotal = Number(element.yes) + Number(element.no) + Number(element.abstain) + Number(element.no_with_veto)
const subtotal = Number(element.yes || element.yes_count) + Number(element.no || element.no_count) + Number(element.abstain || element.abstain_count) + Number(element.no_with_veto || element.no_with_veto_count)
if (total < 1) {
this.total = subtotal + 1
} else {
this.total = total
}
this.yes = Number(element.yes) / this.total
this.no = Number(element.no) / this.total
this.veto = Number(element.no_with_veto) / this.total
this.abstain = Number(element.abstain) / this.total
this.yes = Number(element.yes || element.yes_count) / this.total
this.no = Number(element.no || element.no_count) / this.total
this.veto = Number(element.no_with_veto || element.no_with_veto_count) / this.total
this.abstain = Number(element.abstain || element.abstain_count) / this.total
this.turnout = subtotal / this.total
return this
}
+9 -1
View File
@@ -16,6 +16,7 @@ export default class Proposal {
this.voting_start_time = '0000-00-00'
this.total_deposit = '-'
this.contents = null
this.metadata = {}
}
init(element, total) {
@@ -29,7 +30,7 @@ export default class Proposal {
this.voting_start_time = element.voting_start_time
// eslint-disable-next-line prefer-destructuring
this.total_deposit = element.total_deposit[0]
this.contents = element.content.value || element.content
if (element.content) this.contents = element.content.value || element.content
if (this.contents) {
this.title = this.contents.title
this.description = this.contents.description
@@ -38,6 +39,7 @@ export default class Proposal {
this.type = element.content['@type']
}
}
this.metadata = element.metadata
return this
}
@@ -51,6 +53,12 @@ export default class Proposal {
versionFixed(ver) {
if (compareVersions(ver, '0.46') >= 0) {
if (this.element.messages) [this.contents] = this.element.messages
if (this.contents) this.type = this.contents['@type']
if (this.contents['@type'] === '/cosmos.gov.v1.MsgExecLegacyContent') {
this.title = this.contents.content.title
this.description = this.contents.content.description
}
if (this.element.metadata) {
this.title = this.element.metadata.title || this.element.metadata
this.description = this.element.metadata.description || this.element.metadata
+1
View File
@@ -46,6 +46,7 @@ export default class WrapStdTx {
self.tx = StdTx.create(element.tx, version)
self.raw_log = element.tx_response.raw_log
}
self.element = element
return self
}
}
+59 -35
View File
@@ -128,8 +128,8 @@ export default class ChainFetch {
// return ret
// })
return Promise.all([
this.get(`/cosmos/distribution/v1beta1/validators/${address}/commission`),
this.get(`/cosmos/distribution/v1beta1/validators/${address}/outstanding_rewards`),
this.get(`/cosmos/distribution/v1beta1/validators/${address}/commission`, null, true),
this.get(`/cosmos/distribution/v1beta1/validators/${address}/outstanding_rewards`, null, true),
]).then(data => {
const ret = ValidatorDistribution.create({
operator_address: address,
@@ -145,6 +145,9 @@ export default class ChainFetch {
}
async getBankTotal(denom) {
if (compareVersions(this.config.sdk_version, '0.46.2') > 0) {
return this.get(`/cosmos/bank/v1beta1/supply/by_denom?denom=${denom}`).then(data => commonProcess(data).amount)
}
if (compareVersions(this.config.sdk_version, '0.40') < 0) {
return this.get(`/supply/total/${denom}`).then(data => ({ amount: commonProcess(data), denom }))
}
@@ -159,7 +162,7 @@ export default class ChainFetch {
}
async getStakingPool() {
return this.get('/cosmos/staking/v1beta1/pool').then(data => new StakingPool().init(commonProcess(data.pool)))
return this.get('/cosmos/staking/v1beta1/pool', null, true).then(data => new StakingPool().init(commonProcess(data.pool)))
}
async getMintingInflation() {
@@ -176,14 +179,14 @@ export default class ChainFetch {
}
async getStakingParameters() {
return this.get('/cosmos/staking/v1beta1/params').then(data => {
return this.get('/cosmos/staking/v1beta1/params', null, true).then(data => {
this.getSelectedConfig()
return StakingParameters.create(commonProcess(data.params), this.config.chain_name)
})
}
async getValidatorList(config = null) {
return this.get('/cosmos/staking/v1beta1/validators?pagination.limit=200&status=BOND_STATUS_BONDED', config).then(data => {
return this.get('/cosmos/staking/v1beta1/validators?pagination.limit=200&status=BOND_STATUS_BONDED', config, true).then(data => {
const vals = commonProcess(data.validators).map(i => new Validator().init(i))
try {
localStorage.setItem(`validators-${this.config.chain_name}`, JSON.stringify(vals))
@@ -203,7 +206,7 @@ export default class ChainFetch {
}
async getValidatorUnbondedList() {
return this.get('/cosmos/staking/v1beta1/validators?pagination.limit=100&status=BOND_STATUS_UNBONDED').then(data => {
return this.get('/cosmos/staking/v1beta1/validators?pagination.limit=100&status=BOND_STATUS_UNBONDED', null, true).then(data => {
const result = commonProcess(data.validators)
const vals = result.validators ? result.validators : result
return vals.map(i => new Validator().init(i))
@@ -211,7 +214,7 @@ export default class ChainFetch {
}
async getValidatorListByStatus(status) {
return this.get(`/cosmos/staking/v1beta1/validators?status=${status}&pagination.limit=500`).then(data => {
return this.get(`/cosmos/staking/v1beta1/validators?status=${status}&pagination.limit=500`, null, true).then(data => {
const result = commonProcess(data)
const vals = result.validators ? result.validators : result
return vals.map(i => new Validator().init(i))
@@ -223,7 +226,7 @@ export default class ChainFetch {
}
async getStakingValidator(address) {
return this.get(`/cosmos/staking/v1beta1/validators/${address}`).then(data => new Validator().init(commonProcess(data).validator))
return this.get(`/cosmos/staking/v1beta1/validators/${address}`, null, true).then(data => new Validator().init(commonProcess(data).validator))
}
async getSlashingParameters() {
@@ -277,27 +280,39 @@ export default class ChainFetch {
}
async getDistributionParameters() {
return this.get('/cosmos/distribution/v1beta1/params').then(data => commonProcess(data.params))
return this.get('/cosmos/distribution/v1beta1/params', null, true).then(data => commonProcess(data.params))
}
async getGovernanceParameterDeposit() {
return this.get('/cosmos/gov/v1beta1/params/deposit').then(data => commonProcess(data.deposit_params))
const ver = compareVersions(this.config.sdk_version, '0.46.5') < 0 ? 'v1beta1' : 'v1'
return this.get(`/cosmos/gov/${ver}/params/deposit`).then(data => commonProcess(data.deposit_params))
}
async getGovernanceParameterTallying() {
return this.get('/cosmos/gov/v1beta1/params/tallying').then(data => commonProcess(data.tally_params))
const ver = compareVersions(this.config.sdk_version, '0.46.5') < 0 ? 'v1beta1' : 'v1'
return this.get(`/cosmos/gov/${ver}/params/tallying`).then(data => commonProcess(data.tally_params))
}
async getGovernanceParameterVoting() {
return this.get('/cosmos/gov/v1beta1/params/voting').then(data => commonProcess(data.voting_params))
const ver = compareVersions(this.config.sdk_version, '0.46.5') < 0 ? 'v1beta1' : 'v1'
return this.get(`/cosmos/gov/${ver}/params/voting`).then(data => commonProcess(data.voting_params))
}
async getGovernanceTally(pid, total, conf) {
return this.get(`/cosmos/gov/v1beta1/proposals/${pid}/tally`, conf).then(data => new ProposalTally().init(commonProcess(data).tally, total))
const ver = compareVersions(this.config.sdk_version, '0.46.5') < 0 ? 'v1beta1' : 'v1'
return this.get(`/cosmos/gov/${ver}/proposals/${pid}/tally`, conf).then(data => new ProposalTally().init(commonProcess(data).tally, total))
}
getGovernance(pid) {
return this.get(`/cosmos/gov/v1beta1/proposals/${pid}`).then(data => {
if (this.config.chain_name === 'shentu') {
return this.get(`/shentu/gov/v1alpha1/proposals/${pid}`).then(data => {
const p = new Proposal().init(commonProcess(data).proposal, 0)
return p
})
}
const ver = compareVersions(this.config.sdk_version, '0.46.5') < 0 ? 'v1beta1' : 'v1'
return this.get(`/cosmos/gov/${ver}/proposals/${pid}`).then(data => {
const p = new Proposal().init(commonProcess(data).proposal, 0)
p.versionFixed(this.config.sdk_version)
return p
@@ -305,20 +320,22 @@ export default class ChainFetch {
}
async getGovernanceProposer(pid) {
if (this.config.chain_name === 'certik') {
if (this.config.chain_name === 'shentu') {
return this.get(`/shentu/gov/v1alpha1/${pid}/proposer`).then(data => new Proposer().init(commonProcess(data)))
}
return this.get(`/gov/proposals/${pid}/proposer`).then(data => new Proposer().init(commonProcess(data)))
}
async getGovernanceDeposits(pid) {
if (this.config.chain_name === 'certik') {
if (this.config.chain_name === 'shentu') {
return this.get(`/shentu/gov/v1alpha1/proposals/${pid}/deposits`).then(data => {
const result = commonProcess(data)
return Array.isArray(result) ? result.reverse().map(d => new Deposit().init(d)) : result
})
}
return this.get(`/cosmos/gov/v1beta1/proposals/${pid}/deposits`).then(data => {
const ver = compareVersions(this.config.sdk_version, '0.46.5') < 0 ? 'v1beta1' : 'v1'
return this.get(`/cosmos/gov/${ver}/proposals/${pid}/deposits`).then(data => {
const result = commonProcess(data)
return Array.isArray(result) ? result.reverse().map(d => new Deposit().init(d)) : result
})
@@ -334,12 +351,15 @@ export default class ChainFetch {
if (this.config.chain_name === 'shentu') {
return this.get(`/shentu/gov/v1alpha1/proposals/${pid}/votes?pagination.key=${encodeURIComponent(next)}&pagination.limit=${limit}&pagination.reverse=true`)
}
return this.get(`/cosmos/gov/v1beta1/proposals/${pid}/votes?pagination.key=${encodeURIComponent(next)}&pagination.limit=${limit}&pagination.reverse=true`)
const ver = compareVersions(this.config.sdk_version, '0.46.5') < 0 ? 'v1beta1' : 'v1'
return this.get(`/cosmos/gov/${ver}/proposals/${pid}/votes?pagination.key=${encodeURIComponent(next)}&pagination.limit=${limit}&pagination.reverse=true`)
}
async getGovernanceListByStatus(status, chain = null) {
const conf = chain || this.config
const url = conf.chain_name === 'shentu' ? `/shentu/gov/v1alpha1/proposals?pagination.limit=100&proposal_status=${status}` : `/cosmos/gov/v1beta1/proposals?pagination.limit=100&proposal_status=${status}`
const ver = compareVersions(this.config.sdk_version, '0.46.5') < 0 ? 'v1beta1' : 'v1'
const url = conf.chain_name === 'shentu' ? `/shentu/gov/v1alpha1/proposals?pagination.limit=100&proposal_status=${status}` : `/cosmos/gov/${ver}/proposals?pagination.limit=100&proposal_status=${status}`
return this.get(url, conf).then(data => {
let proposals = commonProcess(data)
if (Array.isArray(proposals.proposals)) {
@@ -361,9 +381,10 @@ export default class ChainFetch {
}
async getGovernanceProposalVote(pid, voter, chain) {
const ver = compareVersions(this.config.sdk_version, '0.46.5') < 0 ? 'v1beta1' : 'v1'
const url = this.config.chain_name === 'shentu'
? `/shentu/gov/v1alpha1/proposals/${pid}/votes/${voter}`
: `/cosmos/gov/v1beta1/proposals/${pid}/votes/${voter}`
: `/cosmos/gov/${ver}/proposals/${pid}/votes/${voter}`
return this.get(url, chain).then(data => {
if (data.code === 3) {
throw new Error('not found')
@@ -379,9 +400,10 @@ export default class ChainFetch {
async getGovernanceList(next = '', chain = null) {
const key = next || ''
const ver = compareVersions(this.config.sdk_version, '0.46.5') < 0 ? 'v1beta1' : 'v1'
const url = this.config.chain_name === 'shentu'
? `/shentu/gov/v1alpha1/proposals?pagination.limit=20&pagination.reverse=true&pagination.key=${key}`
: `/cosmos/gov/v1beta1/proposals?pagination.limit=20&pagination.reverse=true&pagination.key=${key}`
: `/cosmos/gov/${ver}/proposals?pagination.limit=20&pagination.reverse=true&pagination.key=${key}`
return this.get(url, chain).then(data => {
let proposals = commonProcess(data)
if (Array.isArray(proposals.proposals)) {
@@ -415,22 +437,22 @@ export default class ChainFetch {
async getStakingReward(address, config = null) {
if (compareVersions(config ? config.sdk_version : this.config.sdk_version, '0.40') < 0) {
return this.get(`/distribution/delegators/${address}/rewards`, config).then(data => commonProcess(data))
return this.get(`/distribution/delegators/${address}/rewards`, config, true).then(data => commonProcess(data))
}
return this.get(`/cosmos/distribution/v1beta1/delegators/${address}/rewards`, config).then(data => commonProcess(data))
return this.get(`/cosmos/distribution/v1beta1/delegators/${address}/rewards`, config, true).then(data => commonProcess(data))
}
async getValidatorSlashs(address, config = null) {
return this.get(`/cosmos/distribution/v1beta1/validators//${address}/slashes`, config).then(data => commonProcess(data))
return this.get(`/cosmos/distribution/v1beta1/validators/${address}/slashes`, config, true).then(data => commonProcess(data))
}
async getStakingValidators(address) {
return this.get(`/cosmos/distribution/v1beta1/delegators/${address}/validators?pagination.size=200`).then(data => commonProcess(data.validators))
return this.get(`/cosmos/distribution/v1beta1/delegators/${address}/validators?pagination.size=200`, null, true).then(data => commonProcess(data.validators))
}
async getStakingDelegations(address, config = null) {
if (compareVersions(config ? config.sdk_version : this.config.sdk_version, '0.40') < 0) {
return this.get(`/staking/delegators/${address}/delegations`, config).then(data => commonProcess(data).map(x => {
return this.get(`/staking/delegators/${address}/delegations`, config, true).then(data => commonProcess(data).map(x => {
const xh = x
if (!xh.delegation) {
xh.delegation = {
@@ -441,21 +463,21 @@ export default class ChainFetch {
return xh
}))
}
return this.get(`/cosmos/staking/v1beta1/delegations/${address}`, config).then(data => commonProcess(data))
return this.get(`/cosmos/staking/v1beta1/delegations/${address}`, config, true).then(data => commonProcess(data))
}
async getStakingRedelegations(address, config = null) {
if (compareVersions(config ? config.sdk_version : this.config.sdk_version, '0.40') < 0) {
return this.get(`/staking/redelegations?delegator=${address}`, config).then(data => commonProcess(data))
return this.get(`/staking/redelegations?delegator=${address}`, config, true).then(data => commonProcess(data))
}
return this.get(`/cosmos/staking/v1beta1/delegators/${address}/redelegations`, config).then(data => commonProcess(data))
return this.get(`/cosmos/staking/v1beta1/delegators/${address}/redelegations`, config, true).then(data => commonProcess(data))
}
async getStakingUnbonding(address, config = null) {
if (compareVersions(config ? config.sdk_version : this.config.sdk_version, '0.40') < 0) {
return this.get(`/staking/delegators/${address}/unbonding_delegations`, config).then(data => commonProcess(data))
return this.get(`/staking/delegators/${address}/unbonding_delegations`, config, true).then(data => commonProcess(data))
}
return this.get(`/cosmos/staking/v1beta1/delegators/${address}/unbonding_delegations`, config).then(data => commonProcess(data))
return this.get(`/cosmos/staking/v1beta1/delegators/${address}/unbonding_delegations`, config, true).then(data => commonProcess(data))
}
async getBankBalances(address, config = null) {
@@ -463,7 +485,7 @@ export default class ChainFetch {
}
async getCommunityPool(config = null) {
return this.get('/cosmos/distribution/v1beta1/community_pool', config).then(data => commonProcess(data))
return this.get('/cosmos/distribution/v1beta1/community_pool', config, true).then(data => commonProcess(data))
}
async getAllIBCDenoms(config = null) {
@@ -589,15 +611,17 @@ export default class ChainFetch {
return response.json() // parses JSON response into native JavaScript objects
}
async get(url, config = null) {
async get(url, config = null, fetch_on_provider = false) {
if (!config) {
this.getSelectedConfig()
}
const conf = config || this.config
if (fetch_on_provider && conf.provider_chain) {
return fetch(`${conf.provider_chain.api}${url}`).then(response => response.json())
}
const finalurl = (Array.isArray(conf.api) ? conf.api[this.getApiIndex(config)] : conf.api) + url
// finalurl = finalurl.replaceAll('v1beta1', this.getEndpointVersion())
const ret = await fetch(finalurl).then(response => response.json())
return ret
return fetch(finalurl).then(response => response.json())
}
getApiIndex(config = null) {
+19 -13
View File
@@ -1,5 +1,5 @@
import {
Bech32, fromBase64, fromBech32, fromHex, toBase64, toBech32, toHex,
fromBase64, fromBech32, fromHex, toBase64, toBech32, toHex,
} from '@cosmjs/encoding'
import { sha256, stringToPath } from '@cosmjs/crypto'
// ledger
@@ -82,20 +82,26 @@ export async function connectLedger(transport = 'usb') {
return new CosmosApp(trans)
}
export function operatorAddressToAccount(operAddress) {
const { prefix, data } = Bech32.decode(operAddress)
if (prefix === 'iva') { // handle special cases
return Bech32.encode('iaa', data)
}
if (prefix === 'crocncl') { // handle special cases
return Bech32.encode('cro', data)
}
return Bech32.encode(prefix.replace('valoper', ''), data)
export function valoperToPrefix(valoper) {
const prefixIndex = valoper.indexOf('valoper')
if (prefixIndex === -1) return null
return valoper.slice(0, prefixIndex)
}
// TODO, not tested
export function pubkeyToAccountAddress(pubkey, prefix) {
return Bech32.encode(prefix, pubkey, 40)
export function operatorAddressToAccount(operAddress) {
const { prefix, data } = fromBech32(operAddress)
if (prefix === 'iva') { // handle special cases
return toBech32('iaa', data)
}
if (prefix === 'crocncl') { // handle special cases
return toBech32('cro', data)
}
return toBech32(prefix.replace('valoper', ''), data)
}
export function pubKeyToValcons(pubkey, prefix) {
const addressData = sha256(fromBase64(pubkey.key)).slice(0, 20)
return toBech32(`${prefix}valcons`, addressData)
}
export function toETHAddress(cosmosAddress) {
+6 -6
View File
@@ -249,16 +249,16 @@ const router = new VueRouter({
component: () => import('@/views/StakingValidator.vue'),
meta: {
pageTitle: 'Staking Validator',
breadcrumb: [
breadcrumb: route => ([
{
text: 'Staking',
active: true,
to: `/${route.params.chain}/staking`,
},
{
text: 'Validator',
active: true,
},
],
]),
},
},
{
@@ -317,16 +317,16 @@ const router = new VueRouter({
component: () => import('@/views/Block.vue'),
meta: {
pageTitle: 'Block',
breadcrumb: [
breadcrumb: route => ([
{
text: 'Blocks',
active: true,
to: `/${route.params.chain}/blocks`,
},
{
text: 'Block',
active: true,
},
],
]),
},
},
{
+2 -1
View File
@@ -273,8 +273,9 @@ export default {
return i
}
const txt = text.substring(text.indexOf(':') + 1, text.indexOf(' '))
const sig = text.split(' ')
const val = this.vals.find(x => x.hex.startsWith(txt))
return val?.description?.moniker || txt
return `${val?.description?.moniker || txt} - ${sig[2]}`
},
},
+279 -58
View File
@@ -5,7 +5,7 @@
:show="syncing"
>
<div class="alert-body">
<span>No new blocks have been produced since <strong>{{ latestTime }}</strong> </span>
<span>{{ $t('dashboard.no_new_blocks') }}<strong>{{ latestTime }}</strong> </span>
</div>
</b-alert>
@@ -90,40 +90,162 @@
</b-row>
<b-card no-body>
<b-card-header>
<b-card-title>Active Proposals</b-card-title>
<b-card-title>{{ $t('dashboard.active_props') }}</b-card-title>
</b-card-header>
<b-card-body>
<b-media
<b-row
v-for="prop in proprosals2"
:key="prop.id"
no-body
class="mb-1"
>
<b-media-aside
v-b-modal.operation-modal
@click="selectProposal('Vote',prop.id, prop.title)"
<b-col
md="6"
sm="12"
>
<b-avatar
rounded
size="42"
:variant="myVotes[prop.id] ? 'light-primary': 'primary'"
<b-media
no-body
class="mb-1"
>
{{ myVotes[prop.id] || 'Vote' }}
</b-avatar>
</b-media-aside>
<b-link :to="`./${chain}/gov/${prop.id}`">
<b-media-body class="d-flex flex-column justify-content-center">
<h6 class="transaction-title">
{{ prop.id }}. {{ prop.title }}
</h6>
<small>{{ formatType(prop.contents['@type']) }} {{ formatEnding(prop.voting_end_time) }}</small>
</b-media-body>
</b-link>
</b-media>
<b-media-aside
@click="showDetail(prop.id)"
>
<b-avatar
rounded
size="42"
variant="light-primary"
>
{{ prop.id }}
</b-avatar>
</b-media-aside>
<b-link :to="`./${chain}/gov/${prop.id}`">
<b-media-body class="d-flex flex-column justify-content-center">
<h6 class="transaction-title">
<b-badge
pill
variant="light-primary"
>
{{ formatType(prop.contents['@type']) }}
</b-badge>{{ prop.title }}
</h6>
<small>will {{ caculateTallyResult(prop.tally) }} {{ formatEnding(prop.voting_end_time) }}</small>
</b-media-body>
</b-link>
</b-media>
</b-col>
<b-col
md="6"
sm="12"
>
<b-row>
<b-col cols="8">
<div class="scale">
<div class="box">
<b-progress
:max="totalPower? 100 * (totalPower/prop.tally.total) :100"
height="2rem"
show-progress
class="font-small-1"
>
<b-progress-bar
:id="'vote-yes'+prop.id"
variant="success"
:value="percent(prop.tally.yes)"
show-progress
:label="`${percent(prop.tally.yes).toFixed()}%`"
/>
<b-progress-bar
:id="'vote-no'+prop.id"
variant="danger"
:value="percent(prop.tally.no)"
:label="`${percent(prop.tally.no).toFixed()}%`"
show-progress
/>
<b-progress-bar
:id="'vote-veto'+prop.id"
class="bg-danger bg-darken-4"
:value="percent(prop.tally.veto)"
:label="`${percent(prop.tally.veto).toFixed()}%`"
show-progress
/>
<b-progress-bar
:id="'vote-abstain'+prop.id"
variant="secondary"
:value="percent(prop.tally.abstain)"
:label="`${percent(prop.tally.abstain).toFixed()}%`"
show-progress
/>
</b-progress>
</div>
<div
v-b-tooltip.hover
title="Threshold"
class="box overlay"
:style="`left:${scaleWidth(prop)}%;`"
/>
<div
v-if="tallyParam"
v-b-tooltip.hover
title="Quorum"
class="box overlay"
:style="`left:${Number(tallyParam.quorum) * 100}%; border-color:black`"
/>
</div>
<b-tooltip
:target="'vote-yes'+prop.id"
>
{{ percent(prop.tally.yes) }}% {{ $t('dashboard.proposal_votes_yes') }}
</b-tooltip>
<b-tooltip
:target="'vote-no'+prop.id"
>
{{ percent(prop.tally.no) }}% {{ $t('dashboard.proposal_votes_no') }}
</b-tooltip>
<b-tooltip
:target="'vote-veto'+prop.id"
>
{{ percent(prop.tally.veto) }}% {{ $t('dashboard.proposal_votes_nwv') }}
</b-tooltip>
<b-tooltip
:target="'vote-abstain'+prop.id"
>
{{ percent(prop.tally.abstain) }}% {{ $t('dashboard.proposal_votes_abstain') }}
</b-tooltip>
</b-col>
<b-col
cols="4"
style="padding-top: 0.5em"
>
<b-button
v-b-modal.operation-modal
variant="primary"
size="sm"
class="mb-2"
@click="selectProposal('Vote',prop.id, prop.title)"
>
{{ myVotes[prop.id] ? `${myVotes[prop.id]}`: 'Vote' }}
</b-button>
</b-col>
</b-row>
</b-col>
<b-col
cols="12"
:class="detailId === prop.id? 'd-block': 'd-none'"
>
<b-card
border-variant="primary"
bg-variant="transparent"
class="shadow-none"
style="max-height:350px;overflow: auto;"
>
<VueMarkdown class="pb-1">
{{ addNewLine(prop.description) }}
</VueMarkdown>
</b-card>
</b-col>
</b-row>
<div v-if="proprosals2.length === 0">
No active proposal!
{{ $t('dashboard.no_active_prop') }}
<b-link :to="`./${chain}/gov`">
Browse all
{{ $t('dashboard.browse') }}
</b-link>
</div>
</b-card-body>
@@ -133,20 +255,20 @@
bg-variant="transparent"
class="shadow-none"
>
<b-card-title class="d-flex justify-content-between">
<span>{{ walletName }} Assets </span>
<b-card-title class="d-flex justify-content-between text-capitalize">
<span>{{ walletName }} {{ $t('dashboard.assets') }} </span>
<small>
<b-link
v-if="address"
:to="`./${chain}/account/${address}`"
>
More
{{ $t('dashboard.more') }}
</b-link>
<b-link
v-else
:to="`/wallet/accounts`"
>
Not connected?
{{ $t('dashboard.not_conn') }}
</b-link>
</small>
</b-card-title>
@@ -211,6 +333,7 @@
<!-- size -->
<b-button-group
size="sm"
class="d-none"
>
<b-button
v-b-modal.operation-modal
@@ -240,18 +363,41 @@
<feather-icon icon="LogOutIcon" />
</b-button>
</b-button-group>
<b-dropdown
v-b-modal.operation-modal
split
variant="outline-primary"
text="Delegate"
class="mr-1"
size="sm"
@click="selectDelegation(data,'Delegate')"
>
<template #button-content>
{{ $t('dashboard.delegate') }}
</template>
<b-dropdown-item
v-b-modal.operation-modal
@click="selectDelegation(data,'Redelegate')"
>
{{ $t('dashboard.redelegate') }}
</b-dropdown-item>
<b-dropdown-item
v-b-modal.operation-modal
@click="selectDelegation(data,'Unbond')"
>
{{ $t('dashboard.unbond') }}
</b-dropdown-item>
</b-dropdown>
<b-button
v-b-modal.operation-modal
variant="outline-primary"
size="sm"
@click="selectWithdraw()"
>
{{ $t('dashboard.withdraw_reward') }}
</b-button>
</template>
</b-table>
<b-card-footer class="text-right">
<b-button
v-b-modal.operation-modal
variant="outline-primary"
@click="selectWithdraw()"
>
<feather-icon icon="AwardIcon" />
Widthdraw Rewards
</b-button>
</b-card-footer>
</b-card>
</b-col>
</b-row>
@@ -260,7 +406,7 @@
<b-col>
<b-card>
<b-card-header class="pt-0 pl-0 pr-0">
<b-card-title>Unbonding Tokens</b-card-title>
<b-card-title>{{ $t('dashboard.unbonding_token') }}</b-card-title>
</b-card-header>
<b-card-body class="pl-0 pr-0">
<b-row
@@ -307,7 +453,7 @@
@click="selectSend()"
>
<feather-icon icon="SendIcon" />
Send
{{ $t('dashboard.send') }}
</b-button>
</b-col>
<b-col cols="6">
@@ -319,7 +465,7 @@
<feather-icon
icon="PlusCircleIcon"
/>
Receive
{{ $t('dashboard.receive') }}
</b-button>
</b-col>
</b-row>
@@ -327,7 +473,7 @@
<router-link to="/wallet/import">
<b-card class="addzone text-center">
<feather-icon icon="PlusIcon" />
Connect Wallet
{{ $t('dashboard.connect_wal') }}
</b-card>
</router-link>
<operation-modal
@@ -337,21 +483,24 @@
:proposal-id="selectedProposalId"
:proposal-title="selectedTitle"
/>
<div id="txevent" />
</div>
</template>
<script>
import {
BRow, BCol, BAlert, BCard, BTable, BFormCheckbox, BCardHeader, BCardTitle, BMedia, BMediaAside, BMediaBody, BAvatar,
BCardBody, BLink, BButtonGroup, BButton, BTooltip, VBModal, VBTooltip, BCardFooter,
BCardBody, BLink, BButtonGroup, BButton, BTooltip, VBModal, VBTooltip, BCardFooter, BProgress, BProgressBar, BBadge,
BDropdown, BDropdownItem,
} from 'bootstrap-vue'
import {
formatNumber, formatTokenAmount, isToken, percent, timeIn, toDay, toDuration, tokenFormatter, getLocalAccounts,
getStakingValidatorOperator,
getStakingValidatorOperator, formatToken,
} from '@/libs/utils'
import OperationModal from '@/views/components/OperationModal/index.vue'
import Ripple from 'vue-ripple-directive'
import dayjs from 'dayjs'
import VueMarkdown from 'vue-markdown'
import ParametersModuleComponent from './components/parameters/ParametersModuleComponent.vue'
import DashboardCardHorizontal from './components/dashboard/DashboardCardHorizontal.vue'
import DashboardCardVertical from './components/dashboard/DashboardCardVertical.vue'
@@ -364,6 +513,8 @@ export default {
BButtonGroup,
BTooltip,
BButton,
BDropdown,
BDropdownItem,
BRow,
BCol,
BAlert,
@@ -378,6 +529,10 @@ export default {
BCardBody,
BLink,
BCardFooter,
BProgress,
BProgressBar,
VueMarkdown,
BBadge,
OperationModal,
ParametersModuleComponent,
@@ -393,6 +548,7 @@ export default {
},
data() {
return {
detailId: 0,
fields: ['validator', 'delegation', 'rewards', 'action'],
delegations: [],
rewards: [],
@@ -414,6 +570,8 @@ export default {
selectedProposalId: 0,
selectedTitle: '',
operationModalType: '',
tallyParam: null,
totalPower: 0,
voteColors: {
YES: 'success',
NO: 'warning',
@@ -450,10 +608,12 @@ export default {
stakingList() {
return this.delegations.map(x => {
const rewards = this.rewards.find(r => r.validator_address === x.delegation.validator_address)
const conf = this.$http.getSelectedConfig()
const decimal = conf.assets[0].exponent || '6'
return {
valAddress: x.delegation.validator_address,
validator: getStakingValidatorOperator(this.$store.state.chains.selected.chain_name, x.delegation.validator_address),
delegation: this.formatToken([x.balance]),
delegation: formatToken(x.balance, {}, decimal),
rewards: rewards ? this.formatToken(rewards.reward) : '',
action: '',
}
@@ -461,9 +621,29 @@ export default {
},
},
created() {
this.$http.getGovernanceListByStatus(2).then(res => {
this.proposals = res.proposals
this.$http.getStakingParameters().then(res => {
Promise.all([this.$http.getStakingPool(), this.$http.getBankTotal(res.bond_denom)])
.then(pool => {
this.supply = `${formatNumber(formatTokenAmount(pool[1].amount, 2, res.bond_denom, false), true, 2)}`
this.bonded = `${formatNumber(formatTokenAmount(pool[0].bondedToken, 2, res.bond_denom, false), true, 2)}`
this.ratio = `${percent(pool[0].bondedToken / pool[1].amount)}%`
this.totalPower = pool[0].bondedToken
})
})
this.$http.getGovernanceListByStatus(2).then(gov => {
this.proposals = gov.proposals
this.proposals.forEach(p => {
this.$http.getGovernanceTally(p.id, 0).then(update => {
// const p2 = p
// p2.tally = update
// this.proposals.push(p2)
// this.proposals.sort((a, b) => a.id - b.id)
this.$set(p, 'tally', update)
})
})
})
this.$http.getLatestBlock().then(res => {
this.height = res.block.header.height
if (timeIn(res.block.header.time, 3, 'm')) {
@@ -475,19 +655,14 @@ export default {
this.validators = res.block.last_commit.signatures.length
})
this.$http.getStakingParameters().then(res => {
Promise.all([this.$http.getStakingPool(), this.$http.getBankTotal(res.bond_denom)])
.then(pool => {
this.supply = `${formatNumber(formatTokenAmount(pool[1].amount, 2, res.bond_denom, false), true, 2)}`
this.bonded = `${formatNumber(formatTokenAmount(pool[0].bondedToken, 2, res.bond_denom, false), true, 2)}`
this.ratio = `${percent(pool[0].bondedToken / pool[1].amount)}%`
})
})
this.$http.getCommunityPool().then(res => {
this.communityPool = this.formatToken(res.pool)
})
this.$http.getGovernanceParameterTallying().then(res => {
this.tallyParam = res
})
const conf = this.$http.getSelectedConfig()
if (conf.excludes && conf.excludes.indexOf('mint') > -1) {
this.inflation = '-'
@@ -499,7 +674,39 @@ export default {
})
}
},
mounted() {
const elem = document.getElementById('txevent')
elem.addEventListener('txcompleted', () => {
const key = this.$store?.state?.chains?.defaultWallet
if (key) {
const accounts = getLocalAccounts() || {}
const account = Object.entries(accounts)
.map(v => ({ wallet: v[0], address: v[1].address.find(x => x.chain === this.$store.state.chains.selected.chain_name) }))
.filter(v => v.address)
.find(x => x.wallet === key)
if (account) {
this.fetchAccount(account.address.addr)
}
}
})
},
methods: {
caculateTallyResult(tally) {
if (this.tallyParam && tally && this.totalPower > 0) {
if (tally.veto < Number(this.tallyParam.veto_threshold)
&& tally.yes > Number(this.tallyParam.threshold)
&& tally.total / this.totalPower > Number(this.tallyParam.quorum)) {
return 'pass'
}
}
return 'be rejected'
},
scaleWidth(p) {
if (this.tallyParam) {
return Number(this.tallyParam.quorum) * Number(this.tallyParam.threshold) * (1 - p.tally.abstain) * 100
}
return 50
},
selectProposal(modal, pid, title) {
this.operationModalType = modal
this.selectedProposalId = Number(pid)
@@ -609,6 +816,13 @@ export default {
return { title: this.convert(data[k]), subtitle: k }
})
},
addNewLine(value) {
return value ? value.replace(/(?:\\[rn])+/g, '\n') : '-'
},
percent: v => percent(v),
processBarLength(v) {
return percent(v)
},
formatDate: v => dayjs(v).format('YYYY-MM-DD HH:mm:ss'),
convert(v) {
if (typeof v === 'object') {
@@ -633,6 +847,13 @@ export default {
}
return v
},
showDetail(id) {
if (this.detailId !== id) {
this.detailId = id
} else {
this.detailId = 0
}
},
},
}
</script>
+12 -2
View File
@@ -7,7 +7,11 @@
lg="6"
md="12"
>
<proposal-summary-component :p="p" />
<proposal-summary-component
:p="p"
:total-power="totalPower"
:tally-param="tallyParam"
/>
</b-col>
</b-row>
<b-row v-if="next">
@@ -64,9 +68,14 @@ export default {
max: 1,
operationModalType: '',
next: '',
totalPower: 0,
tallyParam: null,
}
},
mounted() {
this.$http.getGovernanceParameterTallying().then(res => {
this.tallyParam = res
})
this.getList()
},
methods: {
@@ -81,9 +90,10 @@ export default {
},
updateTally(res) {
this.$http.getStakingPool().then(pool => {
this.totalPower = pool.bondedToken
const voting = res.filter(i => i.status === 2)
if (voting.length > 0) {
voting.forEach(p => this.$http.getGovernanceTally(p.id, pool.bondedToken).then(update => {
voting.forEach(p => this.$http.getGovernanceTally(p.id, 0).then(update => {
this.$set(p, 'tally', update)
}))
}
+155 -111
View File
@@ -12,7 +12,7 @@
variant="light-info"
class="text-right"
>
Deposit
{{$t('governanceProposal.proposal_status_deposit')}}
</b-badge>
<b-badge
v-if="proposal.status == 2"
@@ -20,7 +20,7 @@
variant="light-primary"
class="text-right"
>
Voting
{{$t('governanceProposal.proposal_status_voting')}}
</b-badge>
<b-badge
v-if="proposal.status == 3"
@@ -28,7 +28,7 @@
variant="light-success"
class="text-right"
>
Passed
{{$t('governanceProposal.proposal_status_passed')}}
</b-badge>
<b-badge
v-if="proposal.status == 4"
@@ -36,12 +36,17 @@
variant="light-danger"
class="text-right"
>
Rejected
{{$t('governanceProposal.proposal_status_rejected')}}
</b-badge>
{{ proposal.title }}
</b-card-title>
</b-card-header>
<b-card-body>
<div>
<object-field-component
:tablefield="proposal.contents"
:small="false"
/></div>
<b-table-simple
stacked="sm"
hover
@@ -50,38 +55,46 @@
<tbody>
<b-tr>
<b-td style="text-transform: capitalize; vertical-align: top; width:200px">
{{ $t('proposal_proposer') }}
</b-td><b-td><router-link :to="`../account/${proposer.proposer}`">
{{ formatAddress(proposer.proposer) }}
</router-link> </b-td>
</b-tr>
<b-tr>
<b-td>
{{ $t('proposal_total_deposit') }}
{{ $t('governanceProposal.proposal_total_deposit') }}
</b-td><b-td>{{ formatToken(proposal.total_deposit) }} </b-td>
</b-tr>
<b-tr>
<b-td>
{{ $t('proposal_submit_time') }}
{{ $t('governanceProposal.proposal_submit_time') }}
</b-td><b-td>{{ formatDate(proposal.submit_time) }}</b-td>
</b-tr>
<b-tr>
<b-td>
{{ $t('voting_time') }}
{{ $t('governanceProposal.voting_time') }}
</b-td><b-td>{{ formatDate(proposal.voting_start_time) }} - {{ formatDate(proposal.voting_end_time) }}</b-td>
</b-tr>
<b-tr v-if="proposal.metadata">
<b-td>
Metadata
</b-td><b-td>{{ proposal.metadata }}</b-td>
</b-tr>
</tbody>
</b-table-simple>
<div>
<object-field-component
:tablefield="proposal.contents"
:small="false"
/></div>
<b-table-simple v-if="proposal.type.indexOf('SoftwareUpgrade') > 0">
<b-tr>
<b-td class="text-center">
{{ $t('upgrade_time') }} {{ upgradeTime }}
{{ $t('governanceProposal.upgrade_time') }} {{ upgradeTime }}
<flip-countdown :deadline="upgradeTime" />
<b-input-group prepend="Estimated by block time: ">
<b-form-select v-model="blocktime">
<b-form-select-option value="7">
7s
</b-form-select-option>
<b-form-select-option value="6">
6s
</b-form-select-option>
<b-form-select-option value="2">
2s
</b-form-select-option>
<b-form-select-option value="1">
1s
</b-form-select-option>
</b-form-select></b-input-group>
</b-td>
</b-tr>
</b-table-simple>
@@ -91,7 +104,7 @@
<b-button
variant="outline-primary"
>
{{ $t('btn_back_list') }}
{{ $t('governanceProposal.btn_back_list') }}
</b-button>
</router-link>
<b-button
@@ -101,94 +114,106 @@
class="btn float-right mg-2"
@click="openModal('Vote')"
>
{{ $t('btn_vote') }}
{{ $t('governanceProposal.btn_vote') }}
</b-button>
</b-card-footer>
</b-card>
<b-card no-body>
<b-card-header>
<b-card-title>
Votes
{{ $t('governanceProposal.proposal_votes') }}
</b-card-title>
</b-card-header>
<b-card-body>
<b-progress
:max="100"
height="2rem"
class="mb-2"
show-progress
>
<b-progress-bar
:id="'vote-yes'+proposal.id"
variant="success"
:value="percent(proposal.tally.yes)"
:label="`${percent(proposal.tally.yes).toFixed()}%`"
show-progress
/>
<b-progress-bar
:id="'vote-no'+proposal.id"
variant="warning"
:value="percent(proposal.tally.no)"
:label="`${percent(proposal.tally.no).toFixed()}%`"
show-progress
/>
<b-progress-bar
:id="'vote-veto'+proposal.id"
variant="danger"
:value="percent(proposal.tally.veto)"
:label="`${percent(proposal.tally.veto).toFixed()}%`"
show-progress
/>
<b-progress-bar
:id="'vote-abstain'+proposal.id"
variant="secondary"
:value="percent(proposal.tally.abstain)"
:label="`${percent(proposal.tally.abstain).toFixed()}%`"
show-progress
/>
</b-progress>
<b-tooltip
:target="'vote-yes'+proposal.id"
>
{{ percent(proposal.tally.yes) }}% voted Yes
</b-tooltip>
<b-tooltip
:target="'vote-no'+proposal.id"
>
{{ percent(proposal.tally.no) }}% voted No
</b-tooltip>
<b-tooltip
:target="'vote-veto'+proposal.id"
>
{{ percent(proposal.tally.veto) }}% voted No With Veto
</b-tooltip>
<b-tooltip
:target="'vote-abstain'+proposal.id"
>
{{ percent(proposal.tally.abstain) }}% voted Abstain
</b-tooltip>
<b-table
v-if="votes.votes && votes.votes.length > 0"
stacked="sm"
:fields="votes_fields"
:items="votes.votes"
striped
>
<template #cell(voter)="data">
<router-link :to="`../account/${data.item.voter}`">
{{ formatAddress(data.item.voter) }}
</router-link>
</template>
</b-table>
<div
v-if="next"
class="addzone text-center pt-50 pb-50 bg-transparent text-primary"
@click="loadVotes()"
>
<feather-icon icon="PlusIcon" />
Load More Votes
</div>
</b-card-body>
<div>
<div class="scale">
<div class="box">
<b-progress
:max="totalPower && proposal.status ===2? 100 * (totalPower/proposal.tally.total) :100"
height="2rem"
class="mb-2"
show-progress
>
<b-progress-bar
:id="'vote-yes'+proposal.id"
variant="success"
:value="percent(proposal.tally.yes)"
:label="`${percent(proposal.tally.yes).toFixed()}%`"
show-progress
/>
<b-progress-bar
:id="'vote-no'+proposal.id"
variant="danger"
:value="percent(proposal.tally.no)"
:label="`${percent(proposal.tally.no).toFixed()}%`"
show-progress
/>
<b-progress-bar
:id="'vote-veto'+proposal.id"
class="bg-danger bg-darken-4"
:value="percent(proposal.tally.veto)"
:label="`${percent(proposal.tally.veto).toFixed()}%`"
show-progress
/>
<b-progress-bar
:id="'vote-abstain'+proposal.id"
variant="secondary"
:value="percent(proposal.tally.abstain)"
:label="`${percent(proposal.tally.abstain).toFixed()}%`"
show-progress
/>
</b-progress>
<b-tooltip
:target="'vote-yes'+proposal.id"
>
{{ percent(proposal.tally.yes) }}% {{ $t('governanceProposal.proposal_votes_yes') }}
</b-tooltip>
<b-tooltip
:target="'vote-no'+proposal.id"
>
{{ percent(proposal.tally.no) }}% {{ $t('governanceProposal.proposal_votes_no') }}
</b-tooltip>
<b-tooltip
:target="'vote-veto'+proposal.id"
>
{{ percent(proposal.tally.veto) }}% voted {{ $t('governanceProposal.proposal_votes_nwv') }}
</b-tooltip>
<b-tooltip
:target="'vote-abstain'+proposal.id"
>
{{ percent(proposal.tally.abstain) }}% {{ $t('governanceProposal.proposal_votes_abstain') }}
</b-tooltip>
<div
v-if="tallyParam"
title="Threshold"
class="box overlay"
:style="`left:${scaleWidth(proposal)}%;`"
/>
</div>
</div>
<b-table
v-if="votes.votes && votes.votes.length > 0"
stacked="sm"
:fields="votes_fields"
:items="votes.votes"
striped
>
<template #cell(voter)="data">
<router-link :to="`../account/${data.item.voter}`">
{{ formatAddress(data.item.voter) }}
</router-link>
</template>
</b-table>
<div
v-if="next"
class="addzone text-center pt-50 pb-50 bg-transparent text-primary"
@click="loadVotes()"
>
<feather-icon icon="PlusIcon" />
{{ $t('governanceProposal.proposal_votes_load') }}
</div>
</div></b-card-body>
</b-card>
<b-card
v-if="proposal.total_deposit"
@@ -196,7 +221,7 @@
>
<b-card-header>
<b-card-title>
Deposits ({{ formatToken(proposal.total_deposit) }})
{{ $t('governanceProposal.proposal_deposits') }} ({{ formatToken(proposal.total_deposit) }})
</b-card-title>
</b-card-header>
<b-card-body>
@@ -219,7 +244,7 @@
<b-button
variant="outline-primary"
>
{{ $t('btn_back_list') }}
{{ $t('governanceProposal.btn_back_list') }}
</b-button>
</router-link>
<b-button
@@ -229,7 +254,7 @@
class="btn float-right mg-2"
@click="openModal('GovDeposit')"
>
{{ $t('btn_deposit') }}
{{ $t('governanceProposal.btn_deposit') }}
</b-button>
<b-button
v-b-modal.operation-modal
@@ -238,7 +263,7 @@
class="btn float-right mg-2 mr-1"
@click="openModal('Vote')"
>
{{ $t('btn_vote') }}
{{ $t('governanceProposal.btn_vote') }}
</b-button>
</b-card-footer>
</b-card>
@@ -253,7 +278,7 @@
<script>
import {
BCard, BCardBody, BCardFooter, BButton, BTable, BTableSimple, BTr, BTd, BCardTitle, BCardHeader,
BProgressBar, BProgress, BTooltip, BBadge,
BProgressBar, BProgress, BTooltip, BBadge, BFormSelect, BFormSelectOption, BInputGroup, BInputGroupPrepend,
} from 'bootstrap-vue'
import FlipCountdown from 'vue2-flip-countdown'
// import fetch from 'node-fetch'
@@ -284,16 +309,23 @@ export default {
BProgress,
BTooltip,
BBadge,
BFormSelect,
BFormSelectOption,
BInputGroup,
BInputGroupPrepend,
ObjectFieldComponent,
FlipCountdown,
OperationModal,
},
data() {
return {
blocktime: 6,
tallyParam: null,
latest: {},
next: null,
proposal: new Proposal(),
proposer: new Proposer(),
totalPower: 0,
deposits: [],
votes: [],
operationModalType: '',
@@ -346,7 +378,7 @@ export default {
if (Number(this.proposal?.contents.plan.height || 0) > 0 && this.latest?.block) {
const blocks = Number(this.proposal.contents.plan.height) - Number(this.latest.block?.header?.height || 0)
if (blocks > 0) {
const endtime = dayjs().add(blocks * 6, 'second').format('YYYY-MM-DD HH:mm:ss')
const endtime = dayjs().add(blocks * this.blocktime, 'second').format('YYYY-MM-DD HH:mm:ss')
return endtime
}
}
@@ -356,6 +388,9 @@ export default {
},
},
created() {
this.$http.getGovernanceParameterTallying().then(res => {
this.tallyParam = res
})
const pid = this.$route.params.proposalid
if (this.$route.query.from) {
this.from = this.$route.query.from
@@ -368,7 +403,8 @@ export default {
this.$http.getGovernance(pid).then(p => {
if (p.status === 2) {
this.$http.getStakingPool().then(pool => {
this.$http.getGovernanceTally(pid, pool.bondedToken).then(t => p.updateTally(t))
this.totalPower = pool.bondedToken
this.$http.getGovernanceTally(pid, 0).then(t => p.updateTally(t))
})
}
this.proposal = p
@@ -377,10 +413,9 @@ export default {
if (!getCachedValidators()) {
this.$http.getValidatorList()
}
this.$http.getGovernanceProposer(pid).then(res => {
this.proposer = res
})
// this.$http.getGovernanceProposer(pid).then(res => {
// this.proposer = res
// })
this.$http.getGovernanceDeposits(pid).then(res => {
this.deposits = res
}).catch(() => {})
@@ -390,6 +425,15 @@ export default {
})
},
methods: {
scaleWidth(p) {
if (this.tallyParam) {
if (p.status === 2) {
return Number(this.tallyParam.quorum) * Number(this.tallyParam.threshold) * (1 - p.tally.abstain) * 100
}
return Number(this.tallyParam.threshold) * (1 - p.tally.abstain) * 100
}
return 50
},
percent: v => percent(v),
formatDate: v => dayjs(v).format('YYYY-MM-DD HH:mm'),
formatToken: v => tokenFormatter(v, {}),
+9 -5
View File
@@ -5,7 +5,7 @@
:show="syncing"
>
<div class="alert-body">
<span>No new blocks have been produced since <strong>{{ latestTime }}</strong> </span>
<span>{{$t('parameters.no_blocks_produced')}}<strong>{{ latestTime }}</strong> </span>
</div>
</b-alert>
<b-row>
@@ -38,11 +38,15 @@
<parameters-module-component :data="slashing" />
</b-col>
</b-row>
<b-card title="Application Version">
<object-field-component :tablefield="appVersion" />
<b-card>
<b-card-title class="card-title"><h4>{{$t('parameters.app_ver')}}</h4></b-card-title>
<b-card><object-field-component :tablefield="appVersion" /></b-card>
</b-card>
<b-card title="Node Information">
<object-field-component :tablefield="nodeVersion" />
<b-card>
<b-card-title class="card-title">
<h4>{{$t('parameters.node_info')}}</h4>
</b-card-title>
<b-card><object-field-component :tablefield="nodeVersion" /></b-card>
</b-card>
</div>
</template>
+2 -3
View File
@@ -468,11 +468,10 @@ export default {
if (this.selectedStatus === 'inactive') return 'primary'
const { index, item } = data
if (index === 0) {
window.sum = item.tokens
} else {
window.sum += item.tokens
window.sum = 0
}
const rank = window.sum / this.stakingPool
window.sum += item.tokens // sum up after the calculating.
if (rank < 0.333) {
return 'danger'
}
+5 -1
View File
@@ -224,6 +224,7 @@
:operator-address="validator.operator_address"
:consensus-pubkey="validator.consensus_pubkey"
:account-address="accountAddress"
:valcons-address="valconsAddress"
/>
</b-col>
</b-row>
@@ -273,7 +274,7 @@ import {
} from 'bootstrap-vue'
import {
percent, formatToken, StakingParameters, Validator, operatorAddressToAccount, consensusPubkeyToHexAddress, toDay, abbrMessage, abbrAddress,
percent, formatToken, StakingParameters, Validator, operatorAddressToAccount, consensusPubkeyToHexAddress, toDay, abbrMessage, abbrAddress, valoperToPrefix, pubKeyToValcons,
} from '@/libs/utils'
import { keybase } from '@/libs/fetch'
import OperationModal from '@/views/components/OperationModal/index.vue'
@@ -314,6 +315,7 @@ export default {
latestHeight: 0,
accountAddress: '-',
hexAddress: '-',
valconsAddress: '-',
stakingPool: {},
mintInflation: 0,
stakingParameter: new StakingParameters(),
@@ -384,8 +386,10 @@ export default {
return percent(value)
},
processAddress(operAddress, consensusPubkey) {
const prefix = valoperToPrefix(operAddress)
this.accountAddress = operatorAddressToAccount(operAddress)
this.hexAddress = consensusPubkeyToHexAddress(consensusPubkey)
this.valconsAddress = pubKeyToValcons(consensusPubkey, prefix)
this.$http.getStakingDelegatorDelegation(this.accountAddress, operAddress).then(d => {
this.selfDelegation = d
})
+15 -9
View File
@@ -13,7 +13,7 @@
</b-alert>
<b-card
v-if="error===null"
title="Basic"
title="Summary"
class="text-truncate"
>
<object-field-component
@@ -46,7 +46,8 @@
variant="light-danger"
>
Failed
</b-badge><b v-if="tx.code > 0"> {{ tx.raw_log }}</b> </b-td>
</b-badge>
</b-td>
</b-tr>
<b-tr>
<b-td>
@@ -85,26 +86,30 @@
</b-table-simple>
</b-card>
<b-card
v-if="tx.tx.messages"
:title="`Messages (total: ${tx.tx.messages.length})`"
no-body
>
<b-card v-if="tx.tx.messages">
<b-card-title>Messages (total: {{ tx.tx.messages.length }})</b-card-title>
<b-card-body
v-for="(item, i) in tx.tx.messages "
id="message"
:key="i"
class="message"
class="message px-0"
>
<object-field-component :tablefield="item" />
</b-card-body>
</b-card>
<b-card
v-if="tx.element"
title="Details"
>
<object-field-component :tablefield="tx.element.tx_response" />
</b-card>
</div>
</template>
<script>
import {
BCard, BTableSimple, BTr, BTd, BBadge, BCardBody, BAlert,
BCard, BTableSimple, BTr, BTd, BBadge, BCardBody, BAlert, BCardTitle,
} from 'bootstrap-vue'
import { toDay, tokenFormatter } from '@/libs/utils'
import ObjectFieldComponent from './components/ObjectFieldComponent.vue'
@@ -113,6 +118,7 @@ export default {
components: {
BAlert,
BCard,
BCardTitle,
BCardBody,
BTableSimple,
BTr,
+28 -16
View File
@@ -277,25 +277,20 @@ export default {
})
return Object.values(valCounter).sort((a, b) => b.counter - a.counter)
},
h() {
return this.height
},
},
created() {
const cached = JSON.parse(getCachedValidators(this.$route.params.chain))
if (cached) {
this.validators = cached
}
this.fetchMissingInfo()
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 = toBase64(fromBech32(x.address).data)
this.missing[hex] = x
}
})
}
})
this.initBlocks()
},
beforeDestroy() {
@@ -304,6 +299,18 @@ export default {
clearInterval(this.timer)
},
methods: {
fetchMissingInfo() {
this.$http.getSlashingSigningInfo().then(res => {
if (res.info) {
res.info.forEach(x => {
if (x.address) {
const hex = toBase64(fromBech32(x.address).data)
this.missing[hex] = x
}
})
}
})
},
pinValidator() {
localStorage.setItem('pinned', this.pinned)
},
@@ -319,13 +326,15 @@ export default {
const blocks = []
// update height
let promise = Promise.resolve()
for (let i = height - 1; i > height - 50; i -= 1) {
for (let i = height - 1; i > height - 48; i -= 1) {
blocks.unshift({ sigs: {}, height: i > 0 ? i : 0 })
if (i > height - 48 && i > 0) {
promise = promise.then(() => new Promise(resolve => {
promise = promise.then(() => new Promise(resolve => {
if (i > this.blocks[0].height && i > 0) { // filter useless loading
this.fetch_status(i, resolve)
}))
}
} else {
resolve()
}
}))
}
const sigs = this.initColor()
@@ -386,7 +395,10 @@ export default {
res.block.last_commit.signatures.forEach(x => {
if (x.validator_address) sigs[x.validator_address] = 'bg-success'
})
this.height = res.block.header.height
this.height = Number(res.block.header.height)
if (this.height % 100 === 0) { // update the missing number each 100
this.fetchMissingInfo()
}
const block = this.blocks.find(b => b.height === res.block.last_commit.height)
if (typeof block === 'undefined') { // mei
// this.$set(block, 0, typeof sigs !== 'undefined')
+3 -3
View File
@@ -2,21 +2,21 @@
<div class="px-0">
<b-card>
<b-card-title class="d-flex justify-content-between">
<span class="text-uppercase"> {{ chain }} </span><small class="text-right"> Height: {{ height }} </small>
<span class="text-uppercase"> {{ chain }} </span><small class="text-right"> {{$t('uptimeMyChainBlocks.height')}} {{ height }} </small>
</b-card-title>
<b-alert
variant="danger"
:show="syncing"
>
<div class="alert-body">
<span>No new blocks have been produced since <strong>{{ latestTime }}</strong> </span>
<span>{{$t('uptimeMyChainBlocks.no_blocks_produced')}}<strong>{{ latestTime }}</strong> </span>
</div>
</b-alert>
<b-row>
<span
v-if="uptime.length===0"
class="text-danger"
> Your node is out of active validator set</span>
> {{$t(uptimeMyChainBlocks.not_active)}}</span>
<b-col
v-for="(x,index) in uptime"
:key="index"
+4 -4
View File
@@ -21,12 +21,12 @@
show
>
<div class="alert-heading">
Tips
{{ $t('uptimeMyValidators.tips') }}
</div>
<div class="alert-body">
There are two ways to monitor your validators:
<li> Pin a validator on Uptime pages.</li>
<li> Specify parameters like following: <pre>https://ping.pub/cosmos/uptime/my?validators={"sifchain":["FBADE9A30473BB9ED6DFA16BFB3838E028F33650"],"chain_name":["hexAddress"]}</pre></li>
{{ $t('uptimeMyValidators.two_ways') }}
<li> {{ $t('uptimeMyValidators.pin') }}</li>
<li> {{ $t('uptimeMyValidators.link') }} <pre>https://ping.pub/cosmos/uptime/my?validators={"sifchain":["FBADE9A30473BB9ED6DFA16BFB3838E028F33650"],"chain_name":["hexAddress"]}</pre></li>
</div>
</b-alert>
</div>
+51 -37
View File
@@ -23,7 +23,7 @@
style="color: #fff"
class="mb-0"
>
Address: <feather-icon
{{ $t('walletAccountDetail.address') }} <feather-icon
icon="CopyIcon"
size="18"
@click="copy()"
@@ -38,7 +38,7 @@
class="d-flex flex-row"
>
<b-card-header class="pt-0 pl-0 pr-0">
<b-card-title>Assets</b-card-title>
<b-card-title>{{ $t('walletAccountDetail.assets') }}</b-card-title>
<div>
<b-button
v-b-modal.operation-modal
@@ -50,7 +50,7 @@
<feather-icon
icon="SendIcon"
class="d-md-none"
/><small class="d-none d-md-block">Transfer</small>
/><small class="d-none d-md-block">{{ $t('walletAccountDetail.transfer') }}</small>
</b-button>
<b-button
v-b-modal.operation-modal
@@ -61,7 +61,7 @@
icon="SendIcon"
class="d-md-none"
/>
<span class="d-none d-md-block">IBC Transfer</span>
<span class="d-none d-md-block">{{ $t('walletAccountDetail.ibc_transfer') }}</span>
</b-button>
</div>
</b-card-header>
@@ -117,7 +117,7 @@
</div>
<!--/ tokens -->
<div class="text-right border-top pt-1">
<h2>Total: {{ currency }}{{ formatNumber(assetTable.currency) }}</h2>
<h2>{{ $t('walletAccountDetail.total') }}{{ currency }}{{ formatNumber(assetTable.currency) }}</h2>
</div>
</b-col>
</b-row>
@@ -127,7 +127,7 @@
v-if="unbonding && unbonding.length > 0"
>
<b-card-header class="pt-0 pl-0 pr-0">
<b-card-title>Unbonding Tokens</b-card-title>
<b-card-title>{{ $t('walletAccountDetail.unbonding') }}</b-card-title>
</b-card-header>
<b-card-body class="pl-0 pr-0">
<b-row
@@ -135,7 +135,7 @@
:key="item.validator_address"
>
<b-col cols="12">
<span class="font-weight-bolder">From: <router-link :to="`../staking/${item.validator_address}`">{{ item.validator_address }}</router-link></span>
<span class="font-weight-bolder">{{ $t('walletAccountDetail.from') }}<router-link :to="`../staking/${item.validator_address}`">{{ item.validator_address }}</router-link></span>
</b-col>
<b-col cols="12">
<b-table
@@ -164,7 +164,7 @@
v-if="delegations"
>
<b-card-header class="pt-0 pl-0 pr-0">
<b-card-title>Delegation</b-card-title>
<b-card-title>{{ $t('walletAccountDetail.delegation') }}</b-card-title>
<div>
<b-button
v-b-modal.operation-modal
@@ -176,7 +176,7 @@
<feather-icon
icon="LogInIcon"
class="d-md-none"
/><small class="d-none d-md-block">Delegate</small>
/><small class="d-none d-md-block">{{ $t('walletAccountDetail.delegate') }}</small>
</b-button>
<b-button
v-if="delegations"
@@ -188,7 +188,7 @@
<feather-icon
icon="ShareIcon"
class="d-md-none"
/><small class="d-none d-md-block"> Withdraw Rewards</small>
/><small class="d-none d-md-block">{{ $t('walletAccountDetail.withdraw') }}</small>
</b-button>
</div>
</b-card-header>
@@ -197,6 +197,15 @@
:items="deleTable"
stacked="sm"
>
<template #cell(validator)="data">
<span>
<router-link
:to="`../staking/${data.value.address}`"
>
{{ data.value.moniker }}
</router-link>
</span>
</template>
<template #cell(action)="data">
<!-- size -->
<b-button-group
@@ -275,25 +284,25 @@
<b-tbody v-if="account.type === 'cosmos-sdk/BaseAccount'">
<b-tr>
<b-td>
Account Type
{{ $t('walletAccountDetail.acct_type') }}
</b-td><b-td> {{ account.type }} </b-td>
</b-tr>
<b-tr>
<b-td class="max-width:100px;">
Account Number
{{ $t('walletAccountDetail.acct_num') }}
</b-td><b-td> {{ account.value.account_number }} </b-td>
</b-tr>
<b-tr>
<b-td> Sequence </b-td><b-td> {{ account.value.sequence }} </b-td>
<b-td> {{ $t('walletAccountDetail.seq') }} </b-td><b-td> {{ account.value.sequence }} </b-td>
</b-tr>
<b-tr>
<b-td> Public Key </b-td><b-td> <object-field-component :tablefield="account.value.public_key" /> </b-td>
<b-td> {{ $t('walletAccountDetail.pub_key') }} </b-td><b-td> <object-field-component :tablefield="account.value.public_key" /> </b-td>
</b-tr>
</b-tbody>
<b-tbody v-else-if="account.type === 'cosmos-sdk/PeriodicVestingAccount' && account.value.base_vesting_account">
<b-tr>
<b-td>
Account Type
{{ $t('walletAccountDetail.acct_type') }}
</b-td>
<b-td>
{{ account.type }}
@@ -301,32 +310,32 @@
</b-tr>
<b-tr>
<b-td>
Account Number
{{ $t('walletAccountDetail.acct_num') }}
</b-td><b-td> {{ account.value.base_vesting_account.base_account.account_number }} </b-td>
</b-tr>
<b-tr>
<b-td> Sequence </b-td><b-td> {{ account.value.base_vesting_account.base_account.sequence }} </b-td>
<b-td> {{ $t('walletAccountDetail.seq') }} </b-td><b-td> {{ account.value.base_vesting_account.base_account.sequence }} </b-td>
</b-tr>
<b-tr>
<b-td> Public Key </b-td><b-td> <object-field-component :tablefield="account.value.base_vesting_account.base_account.public_key" /> </b-td>
<b-td> {{ $t('walletAccountDetail.pub_key') }} </b-td><b-td> <object-field-component :tablefield="account.value.base_vesting_account.base_account.public_key" /> </b-td>
</b-tr>
<b-tr>
<b-td> Original Vesting </b-td><b-td> {{ formatToken(account.value.base_vesting_account.original_vesting) }} </b-td>
<b-td> {{ $t('walletAccountDetail.orig_vest') }} </b-td><b-td> {{ formatToken(account.value.base_vesting_account.original_vesting) }} </b-td>
</b-tr>
<b-tr>
<b-td> Delegated Free </b-td><b-td> {{ formatToken(account.value.base_vesting_account.delegated_free) }} </b-td>
<b-td> {{ $t('walletAccountDetail.delegated_free') }} </b-td><b-td> {{ formatToken(account.value.base_vesting_account.delegated_free) }} </b-td>
</b-tr>
<b-tr>
<b-td> Delegated Vesting </b-td><b-td> {{ formatToken(account.value.base_vesting_account.delegated_vesting) }} </b-td>
<b-td> {{ $t('walletAccountDetail.delegated_vest') }} </b-td><b-td> {{ formatToken(account.value.base_vesting_account.delegated_vesting) }} </b-td>
</b-tr>
<b-tr>
<b-td> Vesting Time </b-td><b-td> {{ formatTime(account.value.start_time) }} - {{ formatTime(account.value.base_vesting_account.end_time) }}</b-td>
<b-td> {{ $t('walletAccountDetail.vest_time') }} </b-td><b-td> {{ formatTime(account.value.start_time) }} - {{ formatTime(account.value.base_vesting_account.end_time) }}</b-td>
</b-tr>
<b-tr>
<b-td> Vesting Periods </b-td>
<b-td> {{ $t('walletAccountDetail.vest_period') }} </b-td>
<b-td>
<b-table-simple>
<th>Length</th><th>Amount</th>
<th>{{ $t('walletAccountDetail.length') }}</th><th>{{ $t('walletAccountDetail.amount') }}</th>
<b-tr
v-for="p, index in account.value.vesting_periods"
:key="index"
@@ -340,31 +349,31 @@
<b-tbody v-else-if="account.type === 'cosmos-sdk/DelayedVestingAccount' && account.value.base_vesting_account">
<b-tr>
<b-td>
Account Type
{{ $t('walletAccountDetail.acct_type') }}
</b-td><b-td> {{ account.type }} </b-td>
</b-tr>
<b-tr>
<b-td style="max-width:100px;">
Account Number
{{ $t('walletAccountDetail.acct_num') }}
</b-td><b-td> {{ account.value.base_vesting_account.base_account.account_number }} </b-td>
</b-tr>
<b-tr>
<b-td> Sequence </b-td><b-td> {{ account.value.base_vesting_account.base_account.sequence }} </b-td>
<b-td> {{ $t('walletAccountDetail.seq') }} </b-td><b-td> {{ account.value.base_vesting_account.base_account.sequence }} </b-td>
</b-tr>
<b-tr>
<b-td> Public Key </b-td><b-td> <object-field-component :tablefield="account.value.base_vesting_account.base_account.public_key" /> </b-td>
<b-td> {{ $t('walletAccountDetail.pub_key') }} </b-td><b-td> <object-field-component :tablefield="account.value.base_vesting_account.base_account.public_key" /> </b-td>
</b-tr>
<b-tr>
<b-td> Original Vesting </b-td><b-td> {{ formatToken(account.value.base_vesting_account.original_vesting) }} </b-td>
<b-td> {{ $t('walletAccountDetail.orig_vest') }} </b-td><b-td> {{ formatToken(account.value.base_vesting_account.original_vesting) }} </b-td>
</b-tr>
<b-tr>
<b-td> Delegated Free </b-td><b-td> {{ formatToken(account.value.base_vesting_account.delegated_free) }} </b-td>
<b-td> {{ $t('walletAccountDetail.delegated_free') }} </b-td><b-td> {{ formatToken(account.value.base_vesting_account.delegated_free) }} </b-td>
</b-tr>
<b-tr>
<b-td> Delegated Vesting </b-td><b-td> {{ formatToken(account.value.base_vesting_account.delegated_vesting) }} </b-td>
<b-td> {{ $t('walletAccountDetail.delegated_vest') }} </b-td><b-td> {{ formatToken(account.value.base_vesting_account.delegated_vesting) }} </b-td>
</b-tr>
<b-tr>
<b-td> End Time </b-td><b-td> {{ formatTime(account.value.base_vesting_account.end_time) }}</b-td>
<b-td> {{ $t('walletAccountDetail.end_time') }} </b-td><b-td> {{ formatTime(account.value.base_vesting_account.end_time) }}</b-td>
</b-tr>
</b-tbody>
<object-field-component
@@ -394,10 +403,10 @@
<div class="misc-inner p-2 p-sm-3">
<div class="w-100 text-center">
<h2 class="mb-1">
Account not found 🕵🏻‍♀️
{{ $t('walletAccountDetail.acct_not_found') }} 🕵🏻‍♀️
</h2>
<p class="mb-2">
Oops! 😖 {{ error }}.
{{ $t('walletAccountDetail.opps') }} 😖 {{ error }}.
</p>
<b-button
@@ -405,7 +414,7 @@
class="mb-2 btn-sm-block"
:to="{path:'../'}"
>
Back to home
{{ $t('walletAccountDetail.back_home') }}
</b-button>
</div>
</div>
@@ -621,12 +630,17 @@ export default {
},
deleTable() {
const re = []
const conf = this.$http.getSelectedConfig()
const decimal = conf.assets[0].exponent || '6'
if (this.reward.rewards && this.delegations && this.delegations.length > 0) {
this.delegations.forEach(e => {
const reward = this.reward.rewards.find(r => r.validator_address === e.delegation.validator_address)
re.push({
validator: getStakingValidatorOperator(this.$http.config.chain_name, e.delegation.validator_address, 8),
token: formatToken(e.balance, {}, 2),
validator: {
moniker: getStakingValidatorOperator(this.$http.config.chain_name, e.delegation.validator_address, 8),
address: e.delegation.validator_address,
},
token: formatToken(e.balance, {}, decimal),
reward: tokenFormatter(reward.reward, this.denoms),
action: e.delegation.validator_address,
})
+12 -10
View File
@@ -464,15 +464,20 @@ export default {
}
},
initParamsForKeplr(chainid, chain) {
const gasPriceStep = chain.keplr_price_step || {
low: 0.01,
average: 0.025,
high: 0.03,
}
return JSON.stringify({
chainId: chainid,
chainName: chain.chain_name,
rpc: Array.isArray(chain.rpc) ? chain.rpc[0] : chain.rpc,
rest: Array.isArray(chain.api) ? chain.api[0] : chain.api,
bip44: {
coinType: chain.coin_type,
coinType: Number(chain.coin_type),
},
coinType: chain.coin_type,
coinType: Number(chain.coin_type),
bech32Config: {
bech32PrefixAccAddr: chain.addr_prefix,
bech32PrefixAccPub: `${chain.addr_prefix}pub`,
@@ -485,7 +490,7 @@ export default {
{
coinDenom: chain.assets[0].symbol,
coinMinimalDenom: chain.assets[0].base,
coinDecimals: chain.assets[0].exponent,
coinDecimals: Number(chain.assets[0].exponent),
coinGeckoId: chain.assets[0].coingecko_id || 'unknown',
},
],
@@ -493,21 +498,18 @@ export default {
{
coinDenom: chain.assets[0].symbol,
coinMinimalDenom: chain.assets[0].base,
coinDecimals: chain.assets[0].exponent,
coinDecimals: Number(chain.assets[0].exponent),
coinGeckoId: chain.assets[0].coingecko_id || 'unknown',
gasPriceStep,
},
],
gasPriceStep,
stakeCurrency: {
coinDenom: chain.assets[0].symbol,
coinMinimalDenom: chain.assets[0].base,
coinDecimals: chain.assets[0].exponent,
coinDecimals: Number(chain.assets[0].exponent),
coinGeckoId: chain.assets[0].coingecko_id || 'unknown',
},
gasPriceStep: {
low: 0.01,
average: 0.025,
high: 0.03,
},
features: chain.keplr_features || [],
}, null, '\t')
},
+6 -2
View File
@@ -119,6 +119,8 @@ export default {
},
computed: {
formatedDelegations() {
const conf = this.$http.getSelectedConfig()
const decimal = conf.assets[0].exponent || '6'
return this.delegations.map(x => ({
validator: {
logo: x.chain.logo,
@@ -128,13 +130,15 @@ export default {
},
delegator: x.keyname,
delegator_address: x.delegation.delegator_address,
delegation: formatToken(x.balance),
delegation: formatToken(x.balance, {}, decimal),
reward: this.findReward(x.delegation.delegator_address, x.delegation.validator_address),
// action: '',
}))
},
groupedDelegations() {
const group = {}
const conf = this.$http.getSelectedConfig()
const decimal = conf.assets[0].exponent || '6'
this.delegations.forEach(x => {
const d = {
validator: {
@@ -145,7 +149,7 @@ export default {
},
delegator: x.keyname,
delegator_address: x.delegation.delegator_address,
delegation: formatToken(x.balance),
delegation: formatToken(x.balance, {}, decimal),
reward: this.findReward(x.delegation.delegator_address, x.delegation.validator_address),
// action: '',
}
+11 -5
View File
@@ -69,7 +69,6 @@
</h6>
</div>
</div>
<b-progress
:max="100"
height="2rem"
@@ -85,21 +84,21 @@
/>
<b-progress-bar
:id="'vote-no'+p.id"
variant="warning"
variant="danger"
:value="percent(p.tally.no)"
:label="`${percent(p.tally.no).toFixed()}%`"
show-progress
/>
<b-progress-bar
:id="'vote-veto'+p.id"
variant="danger"
class="bg-danger bg-darken-4"
:value="percent(p.tally.veto)"
:label="`${percent(p.tally.veto).toFixed()}%`"
show-progress
/>
<b-progress-bar
:id="'vote-abstain'+p.id"
variant="info"
variant="secondary"
:value="percent(p.tally.abstain)"
:label="`${percent(p.tally.abstain).toFixed()}%`"
show-progress
@@ -129,7 +128,7 @@
<span
v-for="(v,k) in p.votes"
:key="k"
> <b-badge :variant="color(v.vote.option)">{{ v.keyname }} : {{ v.vote.option }}</b-badge></span>
> <b-badge :variant="color(v.vote.option)">{{ v.keyname }} : {{ formatOption(v.vote.option) }}</b-badge></span>
</b-card-footer>
</b-card>
</b-col>
@@ -237,6 +236,13 @@ export default {
percent: v => percent(v),
formatDate: v => dayjs(v).format('YYYY-MM-DD'),
formatToken: v => tokenFormatter(v, {}),
formatOption: v => {
const start = String(v).lastIndexOf('_')
if (start > 0) {
return String(v).substring(start + 1)
}
return v
},
init() {
this.accounts = getLocalAccounts()
if (this.accounts) {
@@ -63,7 +63,7 @@
/>
</b-progress>
<div class="status-text">
<span v-if="hash">SUBMITED</span>
<span v-if="hash">SUBMITTED</span>
<span v-if="succeed">COMPLETED</span>
<span v-if="error">FAILED</span>
</div>
@@ -235,7 +235,9 @@ export default {
return formatTokenDenom(this.token)
},
format(v) {
return formatToken(v, this.IBCDenom, 6)
const conf = this.$http.getSelectedConfig()
const decimal = conf.assets[0].exponent || '6'
return formatToken(v, this.IBCDenom, decimal)
},
},
}
@@ -179,8 +179,10 @@ export default {
return options
},
tokenOptions() {
const conf = this.$http.getSelectedConfig()
const decimal = conf.assets[0].exponent || '6'
if (!this.delegations) return []
return this.delegations.filter(x => x.delegation.validator_address === this.validatorAddress).map(x => ({ value: x.balance.denom, label: formatToken(x.balance) }))
return this.delegations.filter(x => x.delegation.validator_address === this.validatorAddress).map(x => ({ value: x.balance.denom, label: formatToken(x.balance, {}, decimal) }))
},
msg() {
return [{
@@ -5,29 +5,53 @@
<h4 class="mb-25 font-weight-bolder">
{{ statistic || '-' }}
</h4>
<span>{{ statisticTitle }}</span>
<span v-if="!statistic || statistic === '-'">{{ statisticTitle }}</span>
<span v-else-if="changes === 0">
{{ showPrice(statistic, statisticTitle) }}
</span>
<span
v-else-if="changes < 0"
v-b-tooltip.hover.v-danger
:title="`${changes.toFixed(1)}%`"
class="text-danger"
>
{{ showPrice(statistic, statisticTitle) }}
</span>
<span
v-else
v-b-tooltip.hover.v-success
:title="`+${changes.toFixed(1)}%`"
class="text-success"
>
{{ showPrice(statistic, statisticTitle) }}
</span>
</div>
<b-avatar
v-b-tooltip.hover
:variant="`light-${color}`"
size="45"
>
<feather-icon
size="21"
:icon="icon"
/>
</b-avatar>
:text="statisticTitle.substring(0,1)"
:title="statisticTitle"
/>
</b-card-body>
</b-card>
</template>
<script>
import { BCard, BCardBody, BAvatar } from 'bootstrap-vue'
import {
BCard, BCardBody, BAvatar, VBTooltip,
} from 'bootstrap-vue'
import { getUserCurrency, getUserCurrencySign } from '@/libs/utils'
export default {
components: {
BCard,
BCardBody,
BAvatar,
VBTooltip,
},
directives: {
'b-tooltip': VBTooltip,
},
props: {
icon: {
@@ -47,5 +71,24 @@ export default {
default: 'primary',
},
},
data() {
return {
changes: 0,
}
},
methods: {
showPrice(v, statisticTitle) {
const token = String(v).split(' ')
if (token.length >= 2) {
const quote = this.$store.state.chains.quotes[token[1]]
if (quote) {
const price = quote[getUserCurrency()]
this.changes = quote[`${getUserCurrency()}_24h_change`]
return `${getUserCurrencySign()}${(Number(token[0].replaceAll(',', '')) * price).toFixed(2)}`
}
}
return statisticTitle
},
},
}
</script>
@@ -20,27 +20,27 @@
<div class="gov-wrapper flex-wrap my-1">
<div class="gov">
<p class="card-text mb-25">
Status
{{$t('governanceProposal.proposal_status')}}
</p>
<h6 class="mb-0">
<span v-if="p.status == 1">
Deposit
{{$t('governanceProposal.proposal_status_deposit')}}
</span>
<span v-else-if="p.status == 2">
Voting
{{$t('governanceProposal.proposal_status_voting')}}
</span>
<span v-else-if="p.status == 3">
Passed
{{$t('governanceProposal.proposal_status_passed')}}
</span>
<span v-else-if="p.status == 4">
Rejected
{{$t('governanceProposal.proposal_status_rejected')}}
</span>
<span v-else>{{ p.status }}</span>
</h6>
</div>
<div class="gov">
<p class="card-text mb-25">
Start Date
{{$t('governanceProposal.proposal_status_start_date')}}
</p>
<h6 class="mb-0">
{{ formatDate(p.voting_start_time) }}
@@ -48,7 +48,7 @@
</div>
<div class="gov">
<p class="card-text mb-25">
End Date
{{$t('governanceProposal.proposal_status_end_date')}}
</p>
<h6 class="mb-0">
{{ formatDate(p.voting_end_time) }}
@@ -56,108 +56,126 @@
</div>
<div class="gov">
<p class="card-text mb-25">
Deposit
{{$t('governanceProposal.proposal_status_deposit')}}
</p>
<h6 class="mb-0">
{{ formatToken(p.total_deposit) || '-' }}
</h6>
</div>
</div>
<b-progress
:max="100"
height="2rem"
class="mb-2"
show-progress
>
<b-progress-bar
:id="'vote-yes'+p.id"
variant="success"
:value="percent(p.tally.yes)"
show-progress
:label="`${percent(p.tally.yes).toFixed()}%`"
/>
<b-progress-bar
:id="'vote-no'+p.id"
variant="warning"
:value="percent(p.tally.no)"
:label="`${percent(p.tally.no).toFixed()}%`"
show-progress
/>
<b-progress-bar
:id="'vote-veto'+p.id"
variant="danger"
:value="percent(p.tally.veto)"
:label="`${percent(p.tally.veto).toFixed()}%`"
show-progress
/>
<b-progress-bar
:id="'vote-abstain'+p.id"
variant="secondary"
:value="percent(p.tally.abstain)"
:label="`${percent(p.tally.abstain).toFixed()}%`"
show-progress
/>
</b-progress>
<b-tooltip
:target="'vote-yes'+p.id"
>
{{ percent(p.tally.yes) }}% voted Yes
</b-tooltip>
<b-tooltip
:target="'vote-no'+p.id"
>
{{ percent(p.tally.no) }}% voted No
</b-tooltip>
<b-tooltip
:target="'vote-veto'+p.id"
>
{{ percent(p.tally.veto) }}% voted No With Veto
</b-tooltip>
<b-tooltip
:target="'vote-abstain'+p.id"
>
{{ percent(p.tally.abstain) }}% voted Abstain
</b-tooltip>
<b-card-footer class="pb-0">
<router-link
v-ripple.400="'rgba(113, 102, 240, 0.15)'"
:to="`./gov/${p.id}`"
variant="outline-primary"
>
<b-button
<div>
<div class="scale">
<div class="box">
<b-progress
:max="totalPower && p.status === 2? 100 * (totalPower/p.tally.total) :100"
height="2rem"
class="mb-2"
show-progress
>
<b-progress-bar
:id="'vote-yes'+p.id"
variant="success"
:value="percent(p.tally.yes)"
show-progress
:label="`${percent(p.tally.yes).toFixed()}%`"
/>
<b-progress-bar
:id="'vote-no'+p.id"
variant="danger"
:value="percent(p.tally.no)"
:label="`${percent(p.tally.no).toFixed()}%`"
show-progress
/>
<b-progress-bar
:id="'vote-veto'+p.id"
class="bg-danger bg-darken-4"
:value="percent(p.tally.veto)"
:label="`${percent(p.tally.veto).toFixed()}%`"
show-progress
/>
<b-progress-bar
:id="'vote-abstain'+p.id"
variant="secondary"
:value="percent(p.tally.abstain)"
:label="`${percent(p.tally.abstain).toFixed()}%`"
show-progress
/>
</b-progress>
<div
v-if="tallyParam"
v-b-tooltip.hover
title="Threshold"
class="box overlay"
:style="`left:${scaleWidth(p)}%;`"
/>
<div
v-if="tallyParam && p.status === 2"
v-b-tooltip.hover
title="Quorum"
class="box overlay"
:style="`left:${Number(tallyParam.quorum) * 100}%; border-color:black`"
/>
</div>
<b-tooltip
:target="'vote-yes'+p.id"
>
{{ percent(p.tally.yes) }}% {{ $t('governanceProposal.proposal_votes_yes') }}
</b-tooltip>
<b-tooltip
:target="'vote-no'+p.id"
>
{{ percent(p.tally.no) }}% {{ $t('governanceProposal.proposal_votes_no') }}
</b-tooltip>
<b-tooltip
:target="'vote-veto'+p.id"
>
{{ percent(p.tally.veto) }}% {{ $t('governanceProposal.proposal_votes_nwv') }}
</b-tooltip>
<b-tooltip
:target="'vote-abstain'+p.id"
>
{{ percent(p.tally.abstain) }}% {{ $t('governanceProposal.proposal_votes_abstain') }}
</b-tooltip>
</div>
<b-card-footer class="pb-0">
<router-link
v-ripple.400="'rgba(113, 102, 240, 0.15)'"
:href="`./gov/${p.id}`"
:to="`./gov/${p.id}`"
variant="outline-primary"
>
{{ $t('btn_detail') }}
<b-button
v-ripple.400="'rgba(113, 102, 240, 0.15)'"
:href="`./gov/${p.id}`"
variant="outline-primary"
>
{{ $t('governanceProposal.btn_detail') }}
</b-button>
</router-link>
<b-button
v-if="p.status===1"
v-b-modal.operation-modal
variant="primary"
class="btn float-right mg-2"
@click="selectProposal('GovDeposit',p.id, p.title)"
>
{{ $t('governanceProposal.btn_deposit') }}
</b-button>
</router-link>
<b-button
v-if="p.status===1"
v-b-modal.operation-modal
variant="primary"
class="btn float-right mg-2"
@click="selectProposal('GovDeposit',p.id, p.title)"
>
{{ $t('btn_deposit') }}
</b-button>
<b-button
v-if="p.status===2"
v-b-modal.operation-modal
variant="primary"
class="btn float-right mg-2"
@click="selectProposal('Vote',p.id, p.title)"
>
{{ $t('btn_vote') }}
</b-button>
</b-card-footer>
</b-card>
<b-button
v-if="p.status===2"
v-b-modal.operation-modal
variant="primary"
class="btn float-right mg-2"
@click="selectProposal('Vote',p.id, p.title)"
>
{{ $t('governanceProposal.btn_vote') }}
</b-button>
</b-card-footer>
</div></b-card>
</template>
<script>
import {
BCard, BCardTitle, BCardFooter, BButton, BProgressBar, BProgress, BBadge, BTooltip, BRow, BCol, VBModal,
BCard, BCardTitle, BCardFooter, BButton, BProgressBar, BProgress, BBadge, BTooltip, BRow, BCol, VBModal, VBTooltip,
} from 'bootstrap-vue'
import Ripple from 'vue-ripple-directive'
import { percent, tokenFormatter } from '@/libs/utils'
@@ -180,6 +198,7 @@ export default {
},
directives: {
'b-modal': VBModal,
'b-tooltip': VBTooltip,
Ripple,
},
props: {
@@ -187,8 +206,25 @@ export default {
type: Object,
default: () => ({}),
},
totalPower: {
type: Number,
default: 0,
},
tallyParam: {
type: Object,
default: null,
},
},
methods: {
scaleWidth(p) {
if (this.tallyParam) {
if (p.status === 2) {
return Number(this.tallyParam.quorum) * Number(this.tallyParam.threshold) * (1 - p.tally.abstain) * 100
}
return Number(this.tallyParam.threshold) * (1 - p.tally.abstain) * 100
}
return 50
},
selectProposal(modal, pid, title) {
this.$parent.operationModalType = modal
this.$parent.selectedProposalId = Number(pid)
@@ -206,7 +242,7 @@ export default {
}
</script>
<style scoped>
<style scoped>
section {
display: flex;
/* flex-wrap: nowrap; */
@@ -98,6 +98,29 @@
<small @click="copy(hexAddress)">{{ hexAddress }}</small>
</b-media-body>
</b-media>
<b-media
class="mb-1"
no-body
>
<b-media-aside class="mr-1">
<b-avatar
rounded
variant="light-primary"
size="34"
>
<feather-icon
icon="HashIcon"
size="18"
/>
</b-avatar>
</b-media-aside>
<b-media-body class="text-truncate">
<h6 class="mb-0">
Signer Address
</h6>
<small @click="copy(valconsAddress)">{{ valconsAddress }}</small>
</b-media-body>
</b-media>
</b-card>
</template>
@@ -138,6 +161,10 @@ export default {
type: String,
default: '-',
},
valconsAddress: {
type: String,
default: '-',
},
},
methods: {
copy(v) {