Merge pull request #377 from alisaweb3/v3-single

UI refactor: Editor,Staking,Statesync, Connect wallet, Image lazy load
This commit is contained in:
ping 2023-05-11 07:37:31 +08:00 committed by GitHub
commit 009ae1c5e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 318 additions and 164 deletions

View File

@ -35,11 +35,12 @@
"cross-fetch": "^3.1.5", "cross-fetch": "^3.1.5",
"daisyui": "^2.51.6", "daisyui": "^2.51.6",
"dayjs": "^1.11.7", "dayjs": "^1.11.7",
"lazy-load-vue3": "^1.3.0",
"long": "^5.2.1", "long": "^5.2.1",
"md-editor-v3": "^2.8.1", "md-editor-v3": "^2.8.1",
"numeral": "^2.0.6", "numeral": "^2.0.6",
"osmojs": "^14.0.0-rc.0", "osmojs": "^14.0.0-rc.0",
"ping-widget": "^0.0.4", "ping-widget": "git+https://github.com/ping-pub/widget.git",
"pinia": "^2.0.28", "pinia": "^2.0.28",
"postcss": "^8.4.23", "postcss": "^8.4.23",
"prismjs": "^1.29.0", "prismjs": "^1.29.0",

View File

@ -19,6 +19,50 @@ function isMD() {
v-if="isMD()" v-if="isMD()"
:model-value="format.multiLine(value)" :model-value="format.multiLine(value)"
previewOnly previewOnly
class="md-editor-recover"
></MdEditor> ></MdEditor>
<span v-else>{{ value }}</span> <span v-else>{{ value }}</span>
</template> </template>
<style lang="scss">
.md-editor-recover {
.h1,h1 {
font-size: 2rem;
}
.h2,h2 {
font-size: 1.5rem;
}
.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 {
margin-top: 0;
margin-bottom: 0.5rem;
font-weight: 500;
line-height: 1.2;
}
ul {
display: block;
list-style-type: disc;
margin-block-start: 1em;
margin-block-end: 1em;
margin-inline-start: 0px;
margin-inline-end: 0px;
padding-inline-start: 40px;
}
dl, ol, ul {
margin-top: 0;
}
address, dl, ol, ul {
margin-bottom: 1rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
a {
color: #666cff !important;
}
.h1 > a, .h2> a, .h3> a, .h4> a, .h5> a, .h6> a, h1> a, h2> a, h3> a, h4> a, h5> a, h6> a {
color: inherit !important;
}
}
</style>

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" tag="i" class="v-icon notranslate v-theme--light v-icon--size-default iconify iconify--mdi" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M16.36 14c.08-.66.14-1.32.14-2c0-.68-.06-1.34-.14-2h3.38c.16.64.26 1.31.26 2s-.1 1.36-.26 2m-5.15 5.56c.6-1.11 1.06-2.31 1.38-3.56h2.95a8.03 8.03 0 0 1-4.33 3.56M14.34 14H9.66c-.1-.66-.16-1.32-.16-2c0-.68.06-1.35.16-2h4.68c.09.65.16 1.32.16 2c0 .68-.07 1.34-.16 2M12 19.96c-.83-1.2-1.5-2.53-1.91-3.96h3.82c-.41 1.43-1.08 2.76-1.91 3.96M8 8H5.08A7.923 7.923 0 0 1 9.4 4.44C8.8 5.55 8.35 6.75 8 8m-2.92 8H8c.35 1.25.8 2.45 1.4 3.56A8.008 8.008 0 0 1 5.08 16m-.82-2C4.1 13.36 4 12.69 4 12s.1-1.36.26-2h3.38c-.08.66-.14 1.32-.14 2c0 .68.06 1.34.14 2M12 4.03c.83 1.2 1.5 2.54 1.91 3.97h-3.82c.41-1.43 1.08-2.77 1.91-3.97M18.92 8h-2.95a15.65 15.65 0 0 0-1.38-3.56c1.84.63 3.37 1.9 4.33 3.56M12 2C6.47 2 2 6.5 2 12a10 10 0 0 0 10 10a10 10 0 0 0 10-10A10 10 0 0 0 12 2Z"></path></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -1,16 +1,23 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue'; import { useWalletStore } from '@/stores';
import { useBlockchain, useWalletStore } from '@/stores';
const walletStore = useWalletStore() const walletStore = useWalletStore();
walletStore.$subscribe((m, s) => { walletStore.$subscribe((m, s) => {
console.log(m, s) console.log(m, s);
}) });
</script> </script>
<template> <template>
<div> <div>
<span v-if="walletStore.currentAddress">{{ walletStore.currentAddress }}</span> <span v-if="walletStore.currentAddress">{{
<ping-connect-wallet class="mt-5" :chain-id="'juno-1'" :hd-path="`m/44'/118/0'/0/0`" /> walletStore.currentAddress
}}</span>
<label
v-else
for="PingConnectWallet"
class="btn btn-sm ml-4 ping-connect-btn"
>Connect Wallet</label
>
</div> </div>
</template> </template>

View File

@ -31,4 +31,13 @@
> >
</div> </div>
</footer> </footer>
<div class="footer-modal">
<ping-connect-wallet :chain-id="'juno-1'" :hd-path="`m/44'/118/0'/0/0`" />
</div>
</template> </template>
<style>
.footer-modal .ping-connect-btn {
display: none;
}
</style>

View File

@ -11,6 +11,7 @@ import '@/plugins/vuetify/styles/styles.scss';
import '@/style.css'; import '@/style.css';
import { createApp } from 'vue'; import { createApp } from 'vue';
import { createPinia } from 'pinia'; import { createPinia } from 'pinia';
import LazyLoad from 'lazy-load-vue3';
// import router from "@/plugins/vuetify/router"; // import router from "@/plugins/vuetify/router";
import router from './router'; import router from './router';
import { useBaseStore } from './stores/useBaseStore'; import { useBaseStore } from './stores/useBaseStore';
@ -25,7 +26,7 @@ app.use(vuetify);
app.use(createPinia()); app.use(createPinia());
app.use(layoutsPlugin); app.use(layoutsPlugin);
app.use(router); app.use(router);
app.use(LazyLoad, { component: true });
// Mount vue app // Mount vue app
app.mount('#app'); app.mount('#app');

View File

@ -136,7 +136,16 @@ function color(v: string) {
<td>{{ v.version }}</td> <td>{{ v.version }}</td>
<td>{{ v.ordering }}</td> <td>{{ v.ordering }}</td>
<td> <td>
<VChip :color="color(v.state)">{{ v.state }}</VChip> <div
class="text-xs truncate relative py-2 px-4 rounded-full w-fit"
:class="`text-${color(v.state)}`"
>
<span
class="inset-x-0 inset-y-0 opacity-10 absolute"
:class="`bg-${color(v.state)}`"
></span>
{{ v.state }}
</div>
</td> </td>
</tr> </tr>
</tbody> </tbody>

View File

@ -7,6 +7,7 @@ import {
useStakingStore, useStakingStore,
} from '@/stores'; } from '@/stores';
import { onMounted, computed, ref } from 'vue'; import { onMounted, computed, ref } from 'vue';
import { Icon } from '@iconify/vue';
import ValidatorCommissionRate from '@/components/ValidatorCommissionRate.vue'; import ValidatorCommissionRate from '@/components/ValidatorCommissionRate.vue';
import { import {
consensusPubkeyToHexAddress, consensusPubkeyToHexAddress,
@ -132,29 +133,47 @@ onMounted(() => {
</script> </script>
<template> <template>
<div> <div>
<VCard class="card-box"> <div style="border-width:1px" class="bg-base-100 px-4 pt-3 pb-4 rounded shadow border-indigo-500">
<VCardItem> <div class="flex flex-col lg:flex-row">
<VRow> <div class="flex-1">
<VCol cols="12" md="6"> <div class="flex">
<div class="d-flex pl-2"> <!-- avator -->
<VAvatar <!-- <VAvatar
icon="mdi-help-circle-outline" icon="mdi-help-circle-outline"
:image="avatars[identity]" :image="avatars[identity]"
size="90" size="90"
rounded rounded
variant="outlined" variant="outlined"
color="secondary" color="secondary"
/> -->
<div
class="avatar mr-4 relative w-24 rounded-lg overflow-hidden"
>
<div
class="w-24 rounded-lg absolute opacity-10"
></div>
<div class="w-24 rounded-lg">
<img
v-if="avatars[identity] !== 'undefined'"
:src="`https://s3.amazonaws.com/keybase_processed_uploads/${avatars[identity]}`"
class="object-contain"
/> />
<Icon
v-else
class="text-4xl"
:icon="`mdi-help-circle-outline`"
/>
</div>
</div>
<div class="mx-2"> <div class="mx-2">
<h4>{{ v.description?.moniker }}</h4> <h4>{{ v.description?.moniker }}</h4>
<div class="text-sm mb-2"> <div class="text-sm mb-2">
{{ v.description?.identity || '-' }} {{ v.description?.identity || '-' }}
</div> </div>
<VBtn>Delegate</VBtn> <button class="btn btn-primary btn-sm w-full">Delegate</button>
</div> </div>
</div> </div>
<VSpacer /> <div class="m-4 text-sm">
<VCardText>
<p class="text-md">About Us</p> <p class="text-md">About Us</p>
<VList class="card-list"> <VList class="card-list">
<VListItem prepend-icon="mdi-web"> <VListItem prepend-icon="mdi-web">
@ -166,7 +185,6 @@ onMounted(() => {
><span> {{ v.description?.security_contact }}</span> ><span> {{ v.description?.security_contact }}</span>
</VListItem> </VListItem>
</VList> </VList>
<p class="text-md mt-3">Validator Status</p> <p class="text-md mt-3">Validator Status</p>
<VList class="card-list"> <VList class="card-list">
<VListItem prepend-icon="mdi-shield-account-outline"> <VListItem prepend-icon="mdi-shield-account-outline">
@ -179,9 +197,9 @@ onMounted(() => {
<span>Jailed: </span><span> {{ v.jailed || '-' }} </span> <span>Jailed: </span><span> {{ v.jailed || '-' }} </span>
</VListItem> </VListItem>
</VList> </VList>
</VCardText> </div>
</VCol> </div>
<VCol cols="12" md="6"> <div class="flex-1">
<div class="d-flex flex-column py-3 justify-space-between"> <div class="d-flex flex-column py-3 justify-space-between">
<div class="d-flex"> <div class="d-flex">
<VAvatar <VAvatar
@ -272,12 +290,11 @@ onMounted(() => {
</div> </div>
</div> </div>
</div> </div>
</VCol> </div>
</VRow> </div>
<VDivider /> <div class="divider"></div>
<VCardText>{{ v.description?.details }}</VCardText> <div class="text-sm px-4">{{ v.description?.details }}</div>
</VCardItem> </div>
</VCard>
<VRow class="mt-3"> <VRow class="mt-3">
<VCol md="4" sm="12" class="h-100"> <VCol md="4" sm="12" class="h-100">

View File

@ -3,7 +3,7 @@ import { useBaseStore, useFormatter, useStakingStore } from '@/stores';
import { toBase64, toHex } from '@cosmjs/encoding'; import { toBase64, toHex } from '@cosmjs/encoding';
import { computed } from '@vue/reactivity'; import { computed } from '@vue/reactivity';
import { onMounted, ref, type DebuggerEvent } from 'vue'; import { onMounted, ref, type DebuggerEvent } from 'vue';
import { consensusPubkeyToHexAddress } from '@/libs'; import { Icon } from '@iconify/vue';
import type { Key, Validator } from '@/types'; import type { Key, Validator } from '@/types';
const staking = useStakingStore(); const staking = useStakingStore();
const format = useFormatter(); const format = useFormatter();
@ -22,57 +22,56 @@ onMounted(() => {
}); });
async function fetchChange() { async function fetchChange() {
console.log('fetch changes') console.log('fetch changes');
let page = 0 let page = 0;
let height = Number(base.latest?.block?.header?.height || 0) let height = Number(base.latest?.block?.header?.height || 0);
if (height > 14400) { if (height > 14400) {
height -= 14400 height -= 14400;
} else { } else {
height = 1 height = 1;
} }
// voting power in 24h ago // voting power in 24h ago
while (page < staking.validators.length && height > 0) { while (page < staking.validators.length && height > 0) {
await base.fetchValidatorByHeight(height, page).then(x => { await base.fetchValidatorByHeight(height, page).then((x) => {
x.validators.forEach(v => { x.validators.forEach((v) => {
yesterday.value[v.pub_key.key] = Number(v.voting_power) yesterday.value[v.pub_key.key] = Number(v.voting_power);
}) });
}) });
page += 100 page += 100;
} }
page = 0 page = 0;
// voting power for now // voting power for now
while (page < staking.validators.length) { while (page < staking.validators.length) {
await base.fetchLatestValidators(page).then(x => { await base.fetchLatestValidators(page).then((x) => {
x.validators.forEach(v => { x.validators.forEach((v) => {
latest.value[v.pub_key.key] = Number(v.voting_power) latest.value[v.pub_key.key] = Number(v.voting_power);
}) });
}) });
page += 100 page += 100;
} }
} }
fetchChange(); fetchChange();
const changes = computed(() => { const changes = computed(() => {
const changes = {} as Record<string, number> const changes = {} as Record<string, number>;
Object.keys(latest.value).forEach(k => { Object.keys(latest.value).forEach((k) => {
const l = latest.value[k] || 0 const l = latest.value[k] || 0;
const y = yesterday.value[k] || 0 const y = yesterday.value[k] || 0;
changes[k] = l - y changes[k] = l - y;
}) });
return changes return changes;
}) });
const change24 = (key: Key) => { const change24 = (key: Key) => {
// console.log('hex key:', consensusPubkeyToHexAddress(key))
const txt = key.key; const txt = key.key;
// const n: number = latest.value[txt]; // const n: number = latest.value[txt];
// const o: number = yesterday.value[txt]; // const o: number = yesterday.value[txt];
// // console.log( txt, n, o) // // console.log( txt, n, o)
// return n > 0 && o > 0 ? n - o : 0; // return n > 0 && o > 0 ? n - o : 0;
return changes.value[txt] return changes.value[txt];
}; };
const change24Text = (key?: Key) => { const change24Text = (key?: Key) => {
@ -187,12 +186,13 @@ const rank = function (position: number) {
{{ list.length }}/{{ staking.params.max_validators }} {{ list.length }}/{{ staking.params.max_validators }}
</div> </div>
</div> </div>
<div>
<VCard> <div class="bg-base-100 px-4 pt-3 pb-4 rounded shadow">
<VTable class="text-no-wrap table-header-bg rounded-0"> <div class="overflow-x-auto">
<table class="table w-full">
<thead> <thead>
<tr> <tr>
<th scope="col" style="width: 3rem">#</th> <th scope="col" style="width: 3rem; position: relative">#</th>
<th scope="col">VALIDATOR</th> <th scope="col">VALIDATOR</th>
<th scope="col" class="text-right">VOTING POWER</th> <th scope="col" class="text-right">VOTING POWER</th>
<th scope="col" class="text-right">24h CHANGES</th> <th scope="col" class="text-right">24h CHANGES</th>
@ -204,24 +204,43 @@ const rank = function (position: number) {
<tr v-for="(v, i) in list" :key="v.operator_address"> <tr v-for="(v, i) in list" :key="v.operator_address">
<!-- 👉 rank --> <!-- 👉 rank -->
<td> <td>
<VChip label :color="rank(i)"> <div
class="text-xs truncate relative py-2 px-4 rounded-full w-fit"
:class="`text-${rank(i)}`"
>
<span
class="inset-x-0 inset-y-0 opacity-10 absolute"
:class="`bg-${rank(i)}`"
></span>
{{ i + 1 }} {{ i + 1 }}
</VChip> </div>
</td> </td>
<!-- 👉 Validator --> <!-- 👉 Validator -->
<td> <td>
<div <div
class="d-flex align-center overflow-hidden" class="d-flex align-center overflow-hidden"
style="max-width: 400px" style="max-width: 400px"
> >
<VAvatar <div
variant="tonal" class="avatar mr-4 relative w-9 rounded-full overflow-hidden"
class="me-3" >
size="34" <div
icon="mdi-help-circle-outline" class="w-9 rounded-full bg-gray-400 absolute opacity-10"
:image="logo(v.description?.identity)" ></div>
<div class="w-9 rounded-full">
<img
v-if="logo(v.description?.identity) !== ''"
v-lazy="logo(v.description?.identity)"
class="object-contain"
/> />
<Icon
v-else
class="text-4xl"
:icon="`mdi-help-circle-outline`"
/>
</div>
</div>
<div class="d-flex flex-column"> <div class="d-flex flex-column">
<h6 class="text-sm text-primary"> <h6 class="text-sm text-primary">
<RouterLink <RouterLink
@ -270,7 +289,15 @@ const rank = function (position: number) {
:class="change24Color(v.consensus_pubkey)" :class="change24Color(v.consensus_pubkey)"
> >
{{ change24Text(v.consensus_pubkey) }} {{ change24Text(v.consensus_pubkey) }}
<VChip label v-if="v.jailed" color="error">Jailed</VChip> <div
v-if="v.jailed"
class="text-xs truncate relative py-2 px-4 rounded-full w-fit text-error"
>
<span
class="inset-x-0 inset-y-0 opacity-10 absolute bg-error"
></span>
Jailed
</div>
</td> </td>
<!-- 👉 commission --> <!-- 👉 commission -->
<td class="text-right"> <td class="text-right">
@ -286,13 +313,26 @@ const rank = function (position: number) {
</td> </td>
</tr> </tr>
</tbody> </tbody>
</VTable> </table>
<VDivider /> </div>
<VCardActions class="py-2">
<VChip label color="error">Top 33%</VChip> <div class="divider"></div>
<VChip label color="warning" class="mx-2">Top 67%</VChip> <div class="flex flex-row">
</VCardActions> <div
</VCard> class="text-xs truncate relative py-2 px-4 rounded-md w-fit text-error mr-2"
>
<span class="inset-x-0 inset-y-0 opacity-10 absolute bg-error"></span>
Top 33%
</div>
<div
class="text-xs truncate relative py-2 px-4 rounded-md w-fit text-warning"
>
<span
class="inset-x-0 inset-y-0 opacity-10 absolute bg-warning"
></span>
Top 67%
</div>
</div>
</div> </div>
</div> </div>
</template> </template>

View File

@ -38,9 +38,11 @@ onMounted(() => {
</script> </script>
<template> <template>
<div> <div>
<VCard> <div class="bg-base-100 px-4 pt-3 pb-4 rounded mb-4 shadow">
<VCardTitle>What's State Sync?</VCardTitle> <h2 class="card-title truncate mb-2">
<VCardText> What's State Sync?
</h2>
<div class="text-sm">
The Tendermint Core 0.34 release includes support for state sync, which The Tendermint Core 0.34 release includes support for state sync, which
allows a new node to join a network by fetching a snapshot of the allows a new node to join a network by fetching a snapshot of the
application state at a recent height instead of fetching and replaying application state at a recent height instead of fetching and replaying
@ -52,36 +54,39 @@ onMounted(() => {
>here</a >here</a
> >
for more infomation. for more infomation.
</VCardText> </div>
</VCard> </div>
<VCard class="my-5"> <div class="bg-base-100 px-4 pt-3 pb-4 rounded mb-4 shadow">
<VCardTitle>Starting New Node From State Sync</VCardTitle> <h2 class="card-title truncate mb-2">Starting New Node From State Sync</h2>
<VCardItem> <div class="text-sm">
1. Install Binary ({{ appName }} Version: 1. Install Binary ({{ appName }} Version:
{{ nodeInfo.application_version?.version || '' }}) {{ nodeInfo.application_version?.version || '' }})
<br /> <br />
We need to install the binary first and make sure that the version is We need to install the binary first and make sure that the version is
the one currently in use on mainnet. the one currently in use on mainnet.
<br /> <br /> <br />
2. Enable State Sync<br /> 2. Enable State Sync<br />
We can configure Tendermint to use state sync in We can configure Tendermint to use state sync in
$DAEMON_HOME/config/config.toml. $DAEMON_HOME/config/config.toml.
<br /><br />
<VTextarea auto-grow :model-value="state"></VTextarea> <VTextarea auto-grow :model-value="state"></VTextarea>
<br />
3. Start the daemon: <code>{{ appName }} start</code> 3. Start the daemon: <code>{{ appName }} start</code>
<br /> <br />
If you are resetting node, run If you are resetting node, run
<code>{{ appName }} unsafe-reset-all</code> or <code>{{ appName }} unsafe-reset-all</code> or
<code>{{ appName }} tendermint unsafe-reset-all --home ~/.HOME</code> <code>{{ appName }} tendermint unsafe-reset-all --home ~/.HOME</code>
before you start the daemon. before you start the daemon.
</VCardItem> </div>
</VCard> </div>
<VCard> <div class="bg-base-100 px-4 pt-3 pb-4 rounded shadow">
<VCardTitle>Enable Snapshot For State Sync</VCardTitle> <h2 class="card-title truncate mb-2">Enable Snapshot For State Sync</h2>
<VCardItem> <div class="text-sm">
To make state sync works, we can enable snapshot in To make state sync works, we can enable snapshot in
$DAEMON_HOME/config/app.toml $DAEMON_HOME/config/app.toml
<br/><br/>
<VTextarea <VTextarea
auto-grow auto-grow
model-value="[state-sync] model-value="[state-sync]
@ -93,8 +98,8 @@ snapshot-interval = 1000
snapshot-keep-recent = 2" snapshot-keep-recent = 2"
> >
</VTextarea> </VTextarea>
</VCardItem> </div>
</VCard> </div>
</div> </div>
</template> </template>

View File

@ -12,7 +12,8 @@ const dashboard = useDashboard();
dashboard.$subscribe((mutation, state) => { dashboard.$subscribe((mutation, state) => {
localStorage.setItem('favorite', JSON.stringify(state.favorite)); localStorage.setItem('favorite', JSON.stringify(state.favorite));
dashboard.loadingPrices() // TODO: cause endless loop
// dashboard.loadingPrices()
}); });
const keywords = ref(''); const keywords = ref('');
const chains = computed(() => { const chains = computed(() => {

View File

@ -1,7 +1,12 @@
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import { useBlockchain } from './useBlockchain'; import { useBlockchain } from './useBlockchain';
import { fromBech32, toBech32 } from '@cosmjs/encoding'; import { fromBech32, toBech32 } from '@cosmjs/encoding';
import type { Delegation, Coin, UnbondingResponses, DelegatorRewards } from '@/types'; import type {
Delegation,
Coin,
UnbondingResponses,
DelegatorRewards,
} from '@/types';
import { useStakingStore } from './useStakingStore'; import { useStakingStore } from './useStakingStore';
export const useWalletStore = defineStore('walletStore', { export const useWalletStore = defineStore('walletStore', {
@ -18,77 +23,87 @@ export const useWalletStore = defineStore('walletStore', {
return useBlockchain(); return useBlockchain();
}, },
connectedWallet() { connectedWallet() {
const chainStore = useBlockchain() const chainStore = useBlockchain();
const key = chainStore.defaultHDPath const key = chainStore.defaultHDPath;
const connected = JSON.parse(localStorage.getItem(key)||"{}") const connected = JSON.parse(localStorage.getItem(key) || '{}');
return connected return connected;
}, },
balanceOfStakingToken(): Coin { balanceOfStakingToken(): Coin {
const stakingStore = useStakingStore() const stakingStore = useStakingStore();
return this.balances.find( x => x.denom === stakingStore.params.bond_denom) || {amount: "0", denom: stakingStore.params.bond_denom} return (
this.balances.find(
(x) => x.denom === stakingStore.params.bond_denom
) || { amount: '0', denom: stakingStore.params.bond_denom }
);
}, },
stakingAmount() { stakingAmount() {
let amt = 0 let amt = 0;
let denom = '' let denom = '';
this.delegations.forEach((i) => { this.delegations.forEach((i) => {
amt += Number(i.balance.amount) amt += Number(i.balance.amount);
denom = i.balance.denom denom = i.balance.denom;
}) });
return {amount: String(amt), denom} return { amount: String(amt), denom };
}, },
rewardAmount() { rewardAmount() {
const stakingStore = useStakingStore();
const stakingStore = useStakingStore() const reward = this.rewards.total?.find(
const reward = this.rewards.total?.find(x => x.denom === stakingStore.params.bond_denom) (x) => x.denom === stakingStore.params.bond_denom
return reward || {amount: "0", denom: stakingStore.params.bond_denom} );
return reward || { amount: '0', denom: stakingStore.params.bond_denom };
}, },
unbondingAmount() { unbondingAmount() {
let amt = 0 let amt = 0;
let denom = '' let denom = '';
this.unbonding.forEach((i) => { this.unbonding.forEach((i) => {
i.entries.forEach(e => { i.entries.forEach((e) => {
amt += Number(e.balance) amt += Number(e.balance);
}) });
}) });
const stakingStore = useStakingStore() const stakingStore = useStakingStore();
return {amount: String(amt), denom: stakingStore.params.bond_denom} return { amount: String(amt), denom: stakingStore.params.bond_denom };
}, },
currentAddress() { currentAddress() {
if(this.connectedWallet.cosmosAddress) { if (!this.connectedWallet?.cosmosAddress) return '';
const { prefix, data } = fromBech32(this.connectedWallet.cosmosAddress); const { prefix, data } = fromBech32(this.connectedWallet.cosmosAddress);
const chainStore = useBlockchain() const chainStore = useBlockchain();
return toBech32(chainStore.current?.bech32Prefix || prefix, data) return toBech32(chainStore.current?.bech32Prefix || prefix, data);
} else { },
return ""
}
}
}, },
actions: { actions: {
async loadMyAsset() { async loadMyAsset() {
if(!this.currentAddress) return if (!this.currentAddress) return;
this.blockchain.rpc.getBankBalances(this.currentAddress).then(x => { this.blockchain.rpc.getBankBalances(this.currentAddress).then((x) => {
this.balances = x.balances this.balances = x.balances;
}) });
this.blockchain.rpc.getStakingDelegations(this.currentAddress).then(x => { this.blockchain.rpc
this.delegations = x.delegation_responses .getStakingDelegations(this.currentAddress)
}) .then((x) => {
this.blockchain.rpc.getStakingDelegatorUnbonding(this.currentAddress).then(x => { this.delegations = x.delegation_responses;
this.unbonding = x.unbonding_responses });
}) this.blockchain.rpc
this.blockchain.rpc.getDistributionDelegatorRewards(this.currentAddress).then(x => { .getStakingDelegatorUnbonding(this.currentAddress)
this.rewards = x .then((x) => {
}) this.unbonding = x.unbonding_responses;
});
this.blockchain.rpc
.getDistributionDelegatorRewards(this.currentAddress)
.then((x) => {
this.rewards = x;
});
}, },
myBalance() { myBalance() {
return this.blockchain.rpc.getBankBalances(this.currentAddress) return this.blockchain.rpc.getBankBalances(this.currentAddress);
}, },
myDelegations() { myDelegations() {
return this.blockchain.rpc.getStakingDelegations(this.currentAddress) return this.blockchain.rpc.getStakingDelegations(this.currentAddress);
}, },
myUnbonding() { myUnbonding() {
return this.blockchain.rpc.getStakingDelegatorUnbonding(this.currentAddress) return this.blockchain.rpc.getStakingDelegatorUnbonding(
} this.currentAddress
);
},
}, },
}); });

View File

@ -5977,6 +5977,11 @@ knitwork@^1.0.0:
resolved "https://registry.npmjs.org/knitwork/-/knitwork-1.0.0.tgz" resolved "https://registry.npmjs.org/knitwork/-/knitwork-1.0.0.tgz"
integrity sha512-dWl0Dbjm6Xm+kDxhPQJsCBTxrJzuGl0aP9rhr+TG8D3l+GL90N8O8lYUi7dTSAN2uuDqCtNgb6aEuQH5wsiV8Q== integrity sha512-dWl0Dbjm6Xm+kDxhPQJsCBTxrJzuGl0aP9rhr+TG8D3l+GL90N8O8lYUi7dTSAN2uuDqCtNgb6aEuQH5wsiV8Q==
lazy-load-vue3@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/lazy-load-vue3/-/lazy-load-vue3-1.3.0.tgz#6aaf573d1d09626ac11fec6b2de9fd07c0130ac0"
integrity sha512-IcyeMiDZrxzuIqqwkYkC+6RRQBdm0yTR0onIj6NITrWd6LaUlzzRmbvAmuzGB0g4H1HeVm/Oa0FokxD2lz9UAA==
ledger-cosmos-js@^2.1.8: ledger-cosmos-js@^2.1.8:
version "2.1.8" version "2.1.8"
resolved "https://registry.yarnpkg.com/ledger-cosmos-js/-/ledger-cosmos-js-2.1.8.tgz#b409ecd1e77f630e6fb212a9f602fe5c6e8f054b" resolved "https://registry.yarnpkg.com/ledger-cosmos-js/-/ledger-cosmos-js-2.1.8.tgz#b409ecd1e77f630e6fb212a9f602fe5c6e8f054b"
@ -6709,10 +6714,9 @@ pify@^3.0.0:
resolved "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz" resolved "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz"
integrity sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg== integrity sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==
ping-widget@^0.0.4: "ping-widget@git+https://github.com/ping-pub/widget.git":
version "0.0.4" version "0.0.5"
resolved "https://registry.yarnpkg.com/ping-widget/-/ping-widget-0.0.4.tgz#b42487cca64fe0be1a4e89c6f300630e3bcae987" resolved "git+https://github.com/ping-pub/widget.git#11de05f773e60430f332fb77b4a37e5ae8c681b2"
integrity sha512-FLzhgd/b+QZt2H7TucmLu8ZXiQh6Op07Usw78XlXBYVwXFtaI5PisKXzV6TftkEa5l8Q1YKMA5d8a8FwLe17HA==
dependencies: dependencies:
"@cosmjs/amino" "^0.30.1" "@cosmjs/amino" "^0.30.1"
"@cosmjs/ledger-amino" "^0.30.1" "@cosmjs/ledger-amino" "^0.30.1"