Skip to content

Commit

Permalink
Merge pull request #6019 from kodadot/feat/multi-chain-balances
Browse files Browse the repository at this point in the history
  • Loading branch information
yangwao authored May 20, 2023
2 parents 30bfea1 + 32f443e commit d3746c1
Show file tree
Hide file tree
Showing 3 changed files with 196 additions and 16 deletions.
178 changes: 178 additions & 0 deletions components/balance/MultipleBalances.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
<template>
<div>
<div class="balance">
<div class="balance-row has-text-grey is-size-7">
<div>{{ $t('general.chain') }}</div>
<div class="has-text-right">{{ $t('general.balance') }}</div>
<div class="has-text-right">{{ $t('general.token') }}</div>
<div class="has-text-right">{{ $t('general.usd') }}</div>
</div>

<div v-for="(chain, key) in availableChains" :key="key" class="is-size-7">
<div v-for="token in chain" :key="token.token" class="balance-row">
<div>{{ key }}</div>
<div class="has-text-right">
{{ token.balance }}
</div>
<div class="has-text-right">{{ token.token }}</div>
<div class="has-text-right">${{ delimiter(token.usd) }}</div>
</div>
</div>

<NeoSkeleton v-if="status === 'loading'" animated />
</div>

<hr class="my-2" />
<p
class="is-flex is-justify-content-space-between is-align-items-center my-1">
<span class="is-size-7"> {{ $i18n.t('spotlight.total') }}: </span>
<span>${{ delimiter(sumUsd) }}</span>
</p>
</div>
</template>

<script setup lang="ts">
import { ApiPromise, WsProvider } from '@polkadot/api'
import { decodeAddress, encodeAddress } from '@polkadot/util-crypto'
import { CHAINS, ENDPOINT_MAP } from '@kodadot1/static'
import { NeoSkeleton } from '@kodadot1/brick'
import { balanceOf } from '@kodadot1/sub-api'
import format from '@/utils/format/balance'
import { useFiatStore } from '@/stores/fiat'
import { calculateExactUsdFromToken } from '@/utils/calculation'
import { getAssetIdByAccount, getKusamaAssetId } from '@/utils/api/bsx/query'
import type { PalletBalancesAccountData } from '@polkadot/types/lookup'
interface Token {
token: string
balance: string
usd: number
selected: boolean
}
interface Chain {
[key: string]: Token[]
}
const { accountId } = useAuth()
const status = ref('loading')
const availableChains = reactive<Chain>({
Kusama: [],
Statemine: [],
Basilisk: [],
})
const mapToPrefix = {
Kusama: 'ksm',
Basilisk: 'bsx',
Statemine: 'stmn',
}
function delimiter(amount: string | number) {
const formatAmount = typeof amount === 'number' ? amount.toString() : amount
const number = parseFloat(formatAmount.replace(/,/g, ''))
return number.toLocaleString('en-US', {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
})
}
const fiatStore = useFiatStore()
const totalUsd = ref([0])
const sumUsd = computed(() => totalUsd.value.reduce((a, b) => a + b, 0))
function calculateUsd(amount: string, token = 'KSM') {
if (!amount) {
return 0
}
const amountToNumber = Number(amount.replace(/\,/g, ''))
if (token === 'KSM') {
return calculateExactUsdFromToken(
amountToNumber,
Number(fiatStore.getCurrentKSMValue)
)
}
return calculateExactUsdFromToken(
amountToNumber,
Number(fiatStore.getCurrentBSXValue)
)
}
async function getBalance(chainName, token = 'KSM', tokenId = 0) {
const currentAddress = accountId.value
const prefix = mapToPrefix[chainName]
const chain = CHAINS[prefix]
const publicKey = decodeAddress(currentAddress)
const prefixAddress = encodeAddress(publicKey, chain.ss58Format)
const wsProvider = new WsProvider(ENDPOINT_MAP[prefix])
const api = await ApiPromise.create({
provider: wsProvider,
})
let currentBalance
if (tokenId) {
const balance = await api.query.tokens.accounts(prefixAddress, tokenId)
currentBalance = format(
(balance as PalletBalancesAccountData).free,
chain.tokenDecimals,
false
)
} else {
const balance = await balanceOf(api, prefixAddress)
currentBalance = format(balance, chain.tokenDecimals, false)
}
let selectedTokenId = String(tokenId)
if (chainName === 'Basilisk') {
selectedTokenId = await getAssetIdByAccount(api, prefixAddress)
}
const balance = delimiter(currentBalance)
const usd = calculateUsd(balance, token)
availableChains[chainName].push({
token,
balance,
usd,
selected: selectedTokenId === String(tokenId),
})
totalUsd.value.push(usd)
await wsProvider.disconnect()
}
onMounted(async () => {
await fiatStore.fetchFiatPrice()
Promise.all([
getBalance('Kusama'),
getBalance('Statemine'),
getBalance('Basilisk', 'BSX'),
getBalance('Basilisk', 'KSM', Number(getKusamaAssetId('bsx'))),
]).then(() => {
status.value = 'done'
})
})
</script>

<style scoped lang="scss">
.balance {
&-row {
display: flex;
justify-content: space-between;
& > * {
flex: 1;
}
}
}
</style>
31 changes: 15 additions & 16 deletions components/common/ConnectWallet/WalletAsset.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,18 @@
<hr class="my-2" />

<div>
<ProfileAssetsList v-if="isSnekOrBsx" @totalValueChange="setTotalValue" />
<AccountBalance v-else class="is-size-7" />
<ProfileAssetsList v-if="isSnek" @totalValueChange="setTotalValue" />
<MultipleBalances v-else />
</div>

<hr class="my-2" />

<div
v-if="totalValue"
class="is-flex is-justify-content-space-between is-align-items-center my-1">
<span class="is-size-7"> {{ $i18n.t('spotlight.total') }}: </span>
<span> ${{ totalValue.toFixed(2) }} </span>
<div v-if="isSnek">
<hr class="my-2" />
<div
v-if="totalValue"
class="is-flex is-justify-content-space-between is-align-items-center my-1">
<span class="is-size-7"> {{ $i18n.t('spotlight.total') }}: </span>
<span> ${{ totalValue.toFixed(2) }} </span>
</div>
</div>
<div
class="buttons is-justify-content-space-between is-flex-wrap-nowrap my-2">
Expand Down Expand Up @@ -52,8 +53,8 @@ import useIdentity from '@/components/identity/utils/useIdentity'
const Identity = defineAsyncComponent(
() => import('@/components/identity/module/IdentityLink.vue')
)
const AccountBalance = defineAsyncComponent(
() => import('@/components/shared/AccountBalance.vue')
const MultipleBalances = defineAsyncComponent(
() => import('@/components/balance/MultipleBalances.vue')
)
const ProfileAssetsList = defineAsyncComponent(
() => import('@/components/rmrk/Profile/ProfileAssetsList.vue')
Expand All @@ -69,9 +70,7 @@ const emit = defineEmits(['back'])
const account = computed(() => identityStore.getAuthAddress)
const walletName = computed(() => walletStore.getWalletName)
const isSnekOrBsx = computed(
() => urlPrefix.value === 'snek' || urlPrefix.value === 'bsx'
)
const isSnek = computed(() => urlPrefix.value === 'snek')
const { shortenedAddress } = useIdentity({
address: account,
Expand All @@ -91,10 +90,10 @@ const setTotalValue = (value: number) => {
totalValue.value = value
}
onMounted(() => {
onMounted(async () => {
if (identityStore.getAuthAddress) {
$consola.log('fetching balance...')
identityStore.fetchBalance({
await identityStore.fetchBalance({
address: identityStore.getAuthAddress,
})
}
Expand Down
3 changes: 3 additions & 0 deletions locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,9 @@
"asset": "Asset",
"using": "using",
"balance": "Balance",
"chain": "Chain",
"token": "Token",
"usd": "USD",
"connect": "Connect",
"connect_wallet": "Connect your wallet",
"change_account": "Change account",
Expand Down

0 comments on commit d3746c1

Please sign in to comment.