Merge remote-tracking branch 'upstream/master' into v3-single
This commit is contained in:
commit
5876ca7343
BIN
public/logos/ledger.jpeg
Normal file
BIN
public/logos/ledger.jpeg
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.6 KiB |
BIN
public/logos/ledger.webp
Normal file
BIN
public/logos/ledger.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 1002 B |
@ -85,6 +85,8 @@ function changeEndpoint(item: Endpoint) {
|
|||||||
Height: {{ baseStore.latest.block?.header.height }}
|
Height: {{ baseStore.latest.block?.header.height }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- bottom-->
|
||||||
|
<div class="px-4 py-2"> </div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -37,7 +37,7 @@ const tipMsg = computed(() => {
|
|||||||
<div class="dropdown dropdown-hover dropdown-end">
|
<div class="dropdown dropdown-hover dropdown-end">
|
||||||
<label
|
<label
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
class="btn btn-sm m-1 lowercase hidden truncate md:!inline-flex text-xs md:!text-sm"
|
class="btn btn-sm btn-primary m-1 lowercase hidden truncate md:!inline-flex text-xs md:!text-sm"
|
||||||
>
|
>
|
||||||
<Icon icon="mdi:wallet" />
|
<Icon icon="mdi:wallet" />
|
||||||
<span class="ml-1 hidden md:block">
|
<span class="ml-1 hidden md:block">
|
||||||
@ -51,7 +51,7 @@ const tipMsg = computed(() => {
|
|||||||
<label
|
<label
|
||||||
v-if="!walletStore?.currentAddress"
|
v-if="!walletStore?.currentAddress"
|
||||||
for="PingConnectWallet"
|
for="PingConnectWallet"
|
||||||
class="btn btn-sm"
|
class="btn btn-sm btn-primary"
|
||||||
><Icon icon="mdi:wallet" /><span class="ml-1 hidden md:block"
|
><Icon icon="mdi:wallet" /><span class="ml-1 hidden md:block"
|
||||||
>Connect Wallet</span
|
>Connect Wallet</span
|
||||||
></label
|
></label
|
||||||
|
@ -321,19 +321,21 @@ const color = computed(() => {
|
|||||||
</Teleport>
|
</Teleport>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="bg-base-100 rounded mt-4 shadow">
|
<div class="bg-base-100 rounded mt-4">
|
||||||
<div class="px-4 pt-4 pb-2 text-lg font-semibold text-main">
|
<div class="px-4 pt-4 pb-2 text-lg font-semibold text-main">
|
||||||
Application Versions
|
Application Versions
|
||||||
</div>
|
</div>
|
||||||
<!-- Application Version -->
|
<!-- Application Version -->
|
||||||
<ArrayObjectElement :value="paramStore.appVersion?.items" :thead="false" />
|
<ArrayObjectElement :value="paramStore.appVersion?.items" :thead="false" />
|
||||||
|
<div class="h-4"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="!store.coingeckoId" class="bg-base-100 rounded mt-4 shadow">
|
<div v-if="!store.coingeckoId" class="bg-base-100 rounded mt-4">
|
||||||
<div class="px-4 pt-4 pb-2 text-lg font-semibold text-main">
|
<div class="px-4 pt-4 pb-2 text-lg font-semibold text-main">
|
||||||
Node Information
|
Node Information
|
||||||
</div>
|
</div>
|
||||||
<ArrayObjectElement :value="paramStore.nodeVersion?.items" :thead="false" />
|
<ArrayObjectElement :value="paramStore.nodeVersion?.items" :thead="false" />
|
||||||
|
<div class="h-4"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -2,15 +2,17 @@
|
|||||||
import { CosmosRestClient } from '@/libs/client';
|
import { CosmosRestClient } from '@/libs/client';
|
||||||
import { useDashboard, useFormatter } from '@/stores';
|
import { useDashboard, useFormatter } from '@/stores';
|
||||||
import type { Coin, Delegation } from '@/types';
|
import type { Coin, Delegation } from '@/types';
|
||||||
import { fromBech32, toBase64, toBech32 } from '@cosmjs/encoding';
|
import { fromBech32, toBase64, toBech32, toHex } from '@cosmjs/encoding';
|
||||||
import { Icon } from '@iconify/vue';
|
import { Icon } from '@iconify/vue';
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { scanLocalKeys, type AccountEntry, scanCompatibleAccounts } from './utils';
|
import { scanLocalKeys, type AccountEntry, scanCompatibleAccounts, type LocalKey } from './utils';
|
||||||
|
|
||||||
const dashboard = useDashboard()
|
const dashboard = useDashboard()
|
||||||
const format = useFormatter()
|
const format = useFormatter()
|
||||||
const editable = ref(false) // to edit addresses
|
const editable = ref(false) // to edit addresses
|
||||||
|
const sourceAddress = ref('') //
|
||||||
|
const selectedSource = ref({} as LocalKey) //
|
||||||
function toggleEdit() {
|
function toggleEdit() {
|
||||||
editable.value = !editable.value
|
editable.value = !editable.value
|
||||||
}
|
}
|
||||||
@ -19,42 +21,21 @@ const conf = ref(JSON.parse(localStorage.getItem("imported-addresses") || "{}")
|
|||||||
const balances = ref({} as Record<string, Coin[]>)
|
const balances = ref({} as Record<string, Coin[]>)
|
||||||
const delegations = ref({} as Record<string, Delegation[]>)
|
const delegations = ref({} as Record<string, Delegation[]>)
|
||||||
|
|
||||||
scanLocalKeys().forEach(wallet => {
|
// load balances
|
||||||
const { data } = fromBech32(wallet.cosmosAddress)
|
Object.values(conf.value).forEach(imported => {
|
||||||
const walletKey = toBase64(data)
|
let promise = Promise.resolve()
|
||||||
let imported = conf.value[walletKey]
|
for(let i = 0;i < imported.length; i++) {
|
||||||
// save the default address to local storage
|
promise = promise.then(() => new Promise((resolve) => {
|
||||||
if (!imported) {
|
// continue only if the page is living
|
||||||
imported = []
|
if(imported[i].endpoint) {
|
||||||
dashboard.favorite.forEach(x => {
|
loadBalances(imported[i].endpoint || "", imported[i].address).finally(()=> resolve())
|
||||||
const chain = dashboard.chains[x]
|
} else {
|
||||||
if (chain && wallet.hdPath.indexOf(chain.coinType) === 6) {
|
resolve()
|
||||||
imported.push({
|
|
||||||
chainName: chain.chainName,
|
|
||||||
logo: chain.logo,
|
|
||||||
address: toBech32(chain.bech32Prefix, data),
|
|
||||||
coinType: chain.coinType,
|
|
||||||
endpoint: chain.endpoints.rest?.at(0)?.address
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
})
|
}))
|
||||||
conf.value[walletKey] = imported;
|
|
||||||
localStorage.setItem("imported-addresses", JSON.stringify(conf.value))
|
|
||||||
}
|
}
|
||||||
// load balance & delegations
|
|
||||||
imported.forEach(x => {
|
|
||||||
if (x.endpoint) {
|
|
||||||
const client = CosmosRestClient.newDefault(x.endpoint)
|
|
||||||
client.getBankBalances(x.address).then(res => {
|
|
||||||
balances.value[x.address] = res.balances.filter(x => x.denom.length < 10)
|
|
||||||
})
|
|
||||||
client.getStakingDelegations(x.address).then(res => {
|
|
||||||
delegations.value[x.address] = res.delegation_responses
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
const accounts = computed(() => {
|
const accounts = computed(() => {
|
||||||
let a = [] as AccountEntry[]
|
let a = [] as AccountEntry[]
|
||||||
@ -69,6 +50,8 @@ const accounts = computed(() => {
|
|||||||
denom = b.balance.denom
|
denom = b.balance.denom
|
||||||
})
|
})
|
||||||
entry.delegation = { amount: String(amount), denom }
|
entry.delegation = { amount: String(amount), denom }
|
||||||
|
}else{
|
||||||
|
entry.delegation = undefined
|
||||||
}
|
}
|
||||||
entry.balances = balances.value[entry.address]
|
entry.balances = balances.value[entry.address]
|
||||||
})
|
})
|
||||||
@ -81,43 +64,97 @@ const addresses = computed(() => {
|
|||||||
return accounts.value.map(x => (x.address))
|
return accounts.value.map(x => (x.address))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const sourceOptions = computed(() => {
|
||||||
|
// scan all connected wallet
|
||||||
|
const keys = scanLocalKeys()
|
||||||
|
// all existed keys
|
||||||
|
Object.values(conf.value).forEach(x => {
|
||||||
|
const [first] = x
|
||||||
|
if (first) {
|
||||||
|
const { data } = fromBech32(first.address)
|
||||||
|
const hex = toHex(data)
|
||||||
|
if (keys.findIndex(k => toHex(fromBech32(k.cosmosAddress).data) === hex) === -1) {
|
||||||
|
keys.push({
|
||||||
|
cosmosAddress: first.address,
|
||||||
|
hdPath: `m/44/${first.coinType}/0'/0/0`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// address
|
||||||
|
if (sourceAddress.value) {
|
||||||
|
const { prefix, data } = fromBech32(sourceAddress.value)
|
||||||
|
const chain = Object.values(dashboard.chains).find(x => x.bech32Prefix === prefix)
|
||||||
|
if (chain) {
|
||||||
|
keys.push({
|
||||||
|
cosmosAddress: sourceAddress.value,
|
||||||
|
hdPath: `m/44/${chain.coinType}/0'/0/0`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!selectedSource.value.cosmosAddress && keys.length > 0) {
|
||||||
|
selectedSource.value = keys[0]
|
||||||
|
}
|
||||||
|
return keys
|
||||||
|
})
|
||||||
|
|
||||||
const availableAccount = computed(() => {
|
const availableAccount = computed(() => {
|
||||||
return scanCompatibleAccounts().filter(x => !addresses.value.includes(x.address))
|
if (selectedSource.value.cosmosAddress) {
|
||||||
|
return scanCompatibleAccounts([selectedSource.value]).filter(x => !addresses.value.includes(x.address))
|
||||||
|
}
|
||||||
|
return []
|
||||||
})
|
})
|
||||||
|
|
||||||
function removeAddress(addr: string) {
|
function removeAddress(addr: string) {
|
||||||
const newConf = {} as Record<string, AccountEntry[]>
|
const newConf = {} as Record<string, AccountEntry[]>
|
||||||
Object.keys(conf.value).forEach(key => {
|
Object.keys(conf.value).forEach(key => {
|
||||||
newConf[key] = conf.value[key].filter(x => x.address !== addr)
|
const acc = conf.value[key].filter(x => x.address !== addr)
|
||||||
|
if (acc.length > 0) newConf[key] = acc
|
||||||
})
|
})
|
||||||
conf.value = newConf
|
conf.value = newConf
|
||||||
localStorage.setItem("imported-addresses", JSON.stringify(conf.value))
|
localStorage.setItem("imported-addresses", JSON.stringify(conf.value))
|
||||||
}
|
}
|
||||||
|
|
||||||
async function addAddress(acc: AccountEntry) {
|
async function addAddress(acc: AccountEntry) {
|
||||||
console.log('add', acc)
|
const { data } = fromBech32(acc.address)
|
||||||
const {data} = fromBech32(acc.address)
|
|
||||||
const key = toBase64(data)
|
const key = toBase64(data)
|
||||||
|
|
||||||
if(conf.value[key]) {
|
if (conf.value[key]) {
|
||||||
|
// existed
|
||||||
|
if (conf.value[key].findIndex(x => x.address === acc.address) > -1) {
|
||||||
|
return
|
||||||
|
}
|
||||||
conf.value[key].push(acc)
|
conf.value[key].push(acc)
|
||||||
} else {
|
} else {
|
||||||
conf.value[key] = [acc]
|
conf.value[key] = [acc]
|
||||||
}
|
}
|
||||||
|
|
||||||
if(acc.endpoint) {
|
// also add chain to favorite
|
||||||
const client = CosmosRestClient.newDefault(acc.endpoint)
|
if(!dashboard?.favoriteMap?.[acc.chainName]) {
|
||||||
client.getBankBalances(acc.address).then(res => {
|
dashboard.favoriteMap[acc.chainName] = true
|
||||||
balances.value[acc.address] = res.balances.filter(x => x.denom.length < 10)
|
window.localStorage.setItem(
|
||||||
})
|
'favoriteMap',
|
||||||
client.getStakingDelegations(acc.address).then(res => {
|
JSON.stringify(dashboard.favoriteMap)
|
||||||
delegations.value[acc.address] = res.delegation_responses
|
);
|
||||||
})
|
}
|
||||||
|
|
||||||
|
if (acc.endpoint) {
|
||||||
|
loadBalances(acc.endpoint, acc.address)
|
||||||
}
|
}
|
||||||
|
|
||||||
localStorage.setItem("imported-addresses", JSON.stringify(conf.value))
|
localStorage.setItem("imported-addresses", JSON.stringify(conf.value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function loadBalances(endpoint:string, address: string) {
|
||||||
|
const client = CosmosRestClient.newDefault(endpoint)
|
||||||
|
await client.getBankBalances(address).then(res => {
|
||||||
|
balances.value[address] = res.balances.filter(x => x.denom.length < 10)
|
||||||
|
})
|
||||||
|
await client.getStakingDelegations(address).then(res => {
|
||||||
|
delegations.value[address] = res.delegation_responses
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
@ -169,9 +206,10 @@ async function addAddress(acc: AccountEntry) {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<table class="table w-full">
|
|
||||||
|
<table class="table table-compact w-full">
|
||||||
<!-- head -->
|
<!-- head -->
|
||||||
<thead>
|
<thead class="rounded-none">
|
||||||
<tr>
|
<tr>
|
||||||
<th v-if="editable"></th>
|
<th v-if="editable"></th>
|
||||||
<th>Account</th>
|
<th>Account</th>
|
||||||
@ -186,11 +224,11 @@ async function addAddress(acc: AccountEntry) {
|
|||||||
<td v-if="editable">
|
<td v-if="editable">
|
||||||
<Icon icon="mdi:close-box" class="text-error" @click="removeAddress(acc.address)"></Icon>
|
<Icon icon="mdi:close-box" class="text-error" @click="removeAddress(acc.address)"></Icon>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td class="px-4">
|
||||||
<RouterLink :to="`/${acc.chainName}/account/${acc.address}`">
|
<RouterLink :to="`/${acc.chainName}/account/${acc.address}`">
|
||||||
<div class="flex items-center space-x-2">
|
<div class="flex items-center space-x-2">
|
||||||
<div class="avatar">
|
<div class="avatar">
|
||||||
<div class="mask mask-squircle w-12 h-12">
|
<div class="mask mask-squircle w-8 h-8">
|
||||||
<img :src="acc.logo" :alt="acc.address" />
|
<img :src="acc.logo" :alt="acc.address" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -232,45 +270,56 @@ async function addAddress(acc: AccountEntry) {
|
|||||||
<!-- Put this part before </body> tag -->
|
<!-- Put this part before </body> tag -->
|
||||||
<div class="modal" id="address-modal">
|
<div class="modal" id="address-modal">
|
||||||
<div class="modal-box">
|
<div class="modal-box">
|
||||||
<h3 class="font-bold text-lg">Import Accounts
|
<h3 class="font-bold text-lg mb-2">Derive Account From Address
|
||||||
<div class="dropdown dropdown-hover">
|
|
||||||
<label tabindex="0" class="text-info">
|
</h3>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="w-4 h-4 stroke-current"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>
|
|
||||||
|
<div>
|
||||||
|
<label class="input-group input-group-sm w-full">
|
||||||
|
<span>Connected</span>
|
||||||
|
<select v-model="selectedSource" class="select select-bordered select-sm w-3/4">
|
||||||
|
<option v-for="source in sourceOptions" :value="source">
|
||||||
|
<span class=" overflow-hidden">{{ source.cosmosAddress }}</span>
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
<label class="input-group input-group-sm my-2">
|
||||||
|
<span>Custom</span>
|
||||||
|
<input v-model="sourceAddress" class="input input-bordered w-full input-sm"
|
||||||
|
placeholder="Input an address" />
|
||||||
</label>
|
</label>
|
||||||
<div tabindex="0" class="card compact dropdown-content dark:bg-info-content bg-slate-300 shadow rounded-box w-64">
|
|
||||||
<div class="card-body">
|
|
||||||
<p>Only shows blockchains on your favorite list</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</h3>
|
<div class="py-4 max-h-72 overflow-y-auto">
|
||||||
<p class="py-4 max-h-60 overflow-y-auto">
|
<table class="table table-compact">
|
||||||
<table>
|
<tr v-for="acc in availableAccount">
|
||||||
<tr v-for="acc in availableAccount" >
|
<td>
|
||||||
<td>
|
<div class="flex items-center space-x-2">
|
||||||
<div class="flex items-center space-x-2">
|
|
||||||
<div class="avatar">
|
<div class="avatar">
|
||||||
<div class="mask mask-squircle w-8 h-8">
|
<div class="mask mask-squircle w-8 h-8">
|
||||||
<img :src="acc.logo" :alt="acc.address" />
|
<img :src="acc.logo" :alt="acc.address" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="font-bold capitalize">{{ acc.chainName }}</div>
|
<div class="tooltip" :class="acc.compatiable?'tooltip-success':'tooltip-error'" :data-tip="`Coin Type: ${acc.coinType}`">
|
||||||
|
<div class="font-bold capitalize" :class="acc.compatiable?'text-green-500':'text-red-500'">
|
||||||
|
{{ acc.chainName }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="text-xs opacity-50 hidden md:!block">{{ acc.address }}</div>
|
<div class="text-xs opacity-50 hidden md:!block">{{ acc.address }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="text-right">
|
<td class="text-right">
|
||||||
<span class="btn !bg-yes !border-yes btn-xs text-white" @click="addAddress(acc)">
|
<span class="btn !bg-yes !border-yes btn-xs text-white" @click="addAddress(acc)">
|
||||||
<Icon icon="mdi:plus"/>
|
<Icon icon="mdi:plus" />
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</p>
|
</div>
|
||||||
<div class="modal-action">
|
<div class="modal-action mt-2 mb-0">
|
||||||
<a href="#" class="btn">Close</a>
|
<a href="#" class="btn btn-primary btn-sm">Close</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div></template>
|
</div></template>
|
||||||
|
@ -10,39 +10,42 @@ export interface AccountEntry {
|
|||||||
endpoint?: string,
|
endpoint?: string,
|
||||||
delegation?: Coin,
|
delegation?: Coin,
|
||||||
balances?: Coin[],
|
balances?: Coin[],
|
||||||
|
compatiable?: boolean,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LocalKey {
|
||||||
|
cosmosAddress: string, hdPath: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export function scanLocalKeys() {
|
export function scanLocalKeys() {
|
||||||
const connected = [] as {cosmosAddress: string, hdPath: string}[]
|
const connected = [] as LocalKey[]
|
||||||
for (let i = 0; i < localStorage.length; i++) {
|
for (let i = 0; i < localStorage.length; i++) {
|
||||||
const key = localStorage.key(i)
|
const key = localStorage.key(i)
|
||||||
if (key?.startsWith("m/44")) {
|
if (key?.startsWith("m/44")) {
|
||||||
const wallet = JSON.parse(localStorage.getItem(key) || "")
|
const wallet = JSON.parse(localStorage.getItem(key) || "")
|
||||||
if (wallet) {
|
if (wallet) {
|
||||||
connected.push(wallet)
|
connected.push(wallet)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return connected
|
|
||||||
}
|
}
|
||||||
|
return connected
|
||||||
|
}
|
||||||
|
|
||||||
|
export function scanCompatibleAccounts(keys: LocalKey[]) {
|
||||||
export function scanCompatibleAccounts() {
|
const dashboard = useDashboard()
|
||||||
const dashboard = useDashboard()
|
const available = [] as AccountEntry[]
|
||||||
const available = [] as AccountEntry[]
|
keys.forEach(wallet => {
|
||||||
scanLocalKeys().forEach(wallet => {
|
Object.values(dashboard.chains).forEach(chain => {
|
||||||
Object.values(dashboard.chains).forEach(chain => {
|
const { data } = fromBech32(wallet.cosmosAddress)
|
||||||
if (wallet.hdPath.indexOf(chain.coinType) === 6) {
|
available.push({
|
||||||
const { data } = fromBech32(wallet.cosmosAddress)
|
chainName: chain.chainName,
|
||||||
available.push({
|
logo: chain.logo,
|
||||||
chainName: chain.chainName,
|
address: toBech32(chain.bech32Prefix, data),
|
||||||
logo: chain.logo,
|
coinType: chain.coinType,
|
||||||
address: toBech32(chain.bech32Prefix, data),
|
compatiable: wallet.hdPath.indexOf(chain.coinType) > 0,
|
||||||
coinType: chain.coinType,
|
endpoint: chain.endpoints.rest?.at(0)?.address
|
||||||
endpoint: chain.endpoints.rest?.at(0)?.address
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
return available
|
})
|
||||||
}
|
return available
|
||||||
|
}
|
@ -17,7 +17,7 @@ export const useWalletStore = defineStore('walletStore', {
|
|||||||
delegations: [] as Delegation[],
|
delegations: [] as Delegation[],
|
||||||
unbonding: [] as UnbondingResponses[],
|
unbonding: [] as UnbondingResponses[],
|
||||||
rewards: {} as DelegatorRewards,
|
rewards: {} as DelegatorRewards,
|
||||||
walletIsConnected: {} as WalletConnected | null
|
walletIsConnected: {} as WalletConnected
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
getters: {
|
getters: {
|
||||||
|
Loading…
Reference in New Issue
Block a user