UNPKG

@crypto-dex-sdk/parachains-amplitude

Version:

Zenlink Parachains Impl for Amplitude

119 lines (101 loc) 3.84 kB
import type { ParachainId } from '@crypto-dex-sdk/chain' import type { Token, Type } from '@crypto-dex-sdk/currency' import type { QueryableStorageEntry } from '@polkadot/api/types' import type { OrmlTokensAccountData } from '@zenlink-types/bifrost/interfaces' import type { BalanceMap } from './types' import { Amount } from '@crypto-dex-sdk/currency' import { isZenlinkAddress } from '@crypto-dex-sdk/format' import { JSBI } from '@crypto-dex-sdk/math' import { useAccount, useApi, useCallMulti, useNativeBalancesAll } from '@crypto-dex-sdk/polkadot' import { useMemo } from 'react' import { addressToNodeCurrency, isNativeCurrency } from '../../libs' interface UseBalancesParams { account: string | undefined currencies: (Type | undefined)[] chainId?: ParachainId enabled?: boolean } type UseBalances = (params: UseBalancesParams) => { data: BalanceMap isLoading: boolean isError: boolean } export const useBalances: UseBalances = ({ chainId, account, currencies, enabled = true, }) => { const api = useApi(chainId) const { isAccount } = useAccount() const nativeBalancesAll = useNativeBalancesAll(chainId, account, enabled) const validatedTokens = useMemo( () => currencies.filter( (currency): currency is Token => { return !!chainId && !!currency && isZenlinkAddress(currency.wrapped.address) }, ), [chainId, currencies], ) const balances = useCallMulti<OrmlTokensAccountData[]>({ chainId, calls: (api && isAccount(account)) ? validatedTokens .map(currency => [api.query.tokens.accounts, [account, addressToNodeCurrency(currency.wrapped.address)]]) .filter((call): call is [QueryableStorageEntry<'promise'>, [string, any]] => Boolean(call[0])) : [], options: { enabled: enabled && Boolean(api && isAccount(account)) }, }) const balanceMap: BalanceMap = useMemo(() => { const result: BalanceMap = {} if (balances.length !== validatedTokens.length) return result for (let i = 0; i < validatedTokens.length; i++) { const value = balances[i]?.free.toString() const amount = value ? JSBI.BigInt(value.toString()) : undefined if (!result[validatedTokens[i].address]) result[validatedTokens[i].address] = Amount.fromRawAmount(validatedTokens[i], '0') if (amount) result[validatedTokens[i].address] = Amount.fromRawAmount(validatedTokens[i], amount) else result[validatedTokens[i].address] = Amount.fromRawAmount(validatedTokens[i], '0') if (isNativeCurrency(validatedTokens[i])) result[validatedTokens[i].wrapped.address] = Amount.fromRawAmount(validatedTokens[i], nativeBalancesAll?.availableBalance.toString() || '0') } return result }, [balances, nativeBalancesAll?.availableBalance, validatedTokens]) return useMemo(() => ({ data: balanceMap, isLoading: isAccount(account) && (!nativeBalancesAll || !balances.length), isError: !isAccount(account), }), [balanceMap, isAccount, account, nativeBalancesAll, balances.length]) } interface UseBalanceParams { account: string | undefined currency: Type | undefined chainId?: ParachainId enabled?: boolean } type UseBalance = (params: UseBalanceParams) => Pick<ReturnType<typeof useBalances>, 'isError' | 'isLoading'> & { data: Amount<Type> | undefined } export const useBalance: UseBalance = ({ chainId, account, currency, enabled, }) => { const currencies = useMemo(() => [currency], [currency]) const { data, isLoading, isError } = useBalances({ chainId, currencies, account, enabled }) return useMemo(() => { const balance = currency ? data?.[currency.wrapped.address] : undefined return { isError, isLoading, data: balance, } }, [isError, isLoading, currency, data]) }