diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 70917b8..c1880c8 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -13,12 +13,8 @@ import 'babel-polyfill'; import { useLoginByParams, useProgramState } from './hooks'; import { CONFIG, CURRENT_GAME, MSG_TO_GAME_ID, STRATEGY_IDS } from './atoms'; import { ProtectedRoute } from './features/Auth/components'; -import { useWalletSync } from './features/Wallet/hooks'; -import { - useAccountAvailableBalance, - useAccountAvailableBalanceSync, - useFTBalanceSync, -} from '@/features/ScoreBalance/hooks'; +import { useAccountAvailableBalance, useAccountAvailableBalanceSync, useWalletSync } from './features/Wallet/hooks'; +import { useFTBalanceSync } from '@/features/ScoreBalance/hooks'; import { LoginPage } from './pages/LoginPage'; import { NotAuthorizedPage } from './pages/NotAuthorizedPage'; import { ApiLoader } from './components/ApiLoader'; diff --git a/frontend/src/features/ScoreBalance/consts.ts b/frontend/src/features/ScoreBalance/consts.ts index a0454ed..a5a0709 100644 --- a/frontend/src/features/ScoreBalance/consts.ts +++ b/frontend/src/features/ScoreBalance/consts.ts @@ -1,9 +1,5 @@ import { HexString } from '@gear-js/api'; -import { atom } from 'jotai'; export const ADDRESS = { SFT: process.env.REACT_APP_FT_ADDRESS as HexString, }; - -export const IS_AVAILABLE_BALANCE_READY = atom(false); -export const AVAILABLE_BALANCE = atom(undefined); diff --git a/frontend/src/features/ScoreBalance/hooks.ts b/frontend/src/features/ScoreBalance/hooks.ts index c8d15ac..ff9ced4 100644 --- a/frontend/src/features/ScoreBalance/hooks.ts +++ b/frontend/src/features/ScoreBalance/hooks.ts @@ -1,12 +1,10 @@ import { useEffect } from 'react'; import { useAtomValue, useSetAtom } from 'jotai'; -import { CreateType } from '@gear-js/api'; -import { formatBalance } from '@polkadot/util'; -import { useAccount, useApi } from '@gear-js/react-hooks'; +import { useAccount } from '@gear-js/react-hooks'; import { useReadState } from '@/hooks'; import { FT_BALANCE, FT_BALANCE_READY } from './atoms'; -import { IFTMain, SystemAccount } from './types'; -import { ADDRESS, AVAILABLE_BALANCE, IS_AVAILABLE_BALANCE_READY } from './consts'; +import { IFTMain } from './types'; +import { ADDRESS } from './consts'; import meta from './assets/fungible_token.meta.txt'; export function useFTBalance() { @@ -47,49 +45,3 @@ export function useFTBalanceSync() { errorFT: error, }; } - -export function useAccountAvailableBalance() { - const isAvailableBalanceReady = useAtomValue(IS_AVAILABLE_BALANCE_READY); - const availableBalance = useAtomValue(AVAILABLE_BALANCE); - const setAvailableBalance = useSetAtom(AVAILABLE_BALANCE); - return { isAvailableBalanceReady, availableBalance, setAvailableBalance }; -} - -export function useAccountAvailableBalanceSync() { - const { isAccountReady, account } = useAccount(); - const { api, isApiReady } = useApi(); - - const isReady = useAtomValue(IS_AVAILABLE_BALANCE_READY); - const setIsReady = useSetAtom(IS_AVAILABLE_BALANCE_READY); - const setAvailableBalance = useSetAtom(AVAILABLE_BALANCE); - - useEffect(() => { - if (!api || !isApiReady || !isAccountReady) return; - - if (account?.decodedAddress) { - api.query.system.account(account.decodedAddress).then((res) => { - const systemAccount = res.toJSON() as SystemAccount; - const total = CreateType.create('u128', systemAccount.data.free).toString(); - const fee = CreateType.create('u128', systemAccount.data.feeFrozen).toString(); - - const getBalance = (b: string) => () => { - const [unit] = api.registry.chainTokens; - const [decimals] = api.registry.chainDecimals; - - const value = formatBalance(b.toString(), { - decimals, - forceUnit: unit, - withSiFull: false, - withSi: false, - withUnit: unit, - }); - - return { value, unit }; - }; - - setAvailableBalance(getBalance(`${+total - +fee}`)); - if (!isReady) setIsReady(true); - }); - } else setIsReady(true); - }, [account, api, isAccountReady, isApiReady, isReady, setAvailableBalance, setIsReady]); -} diff --git a/frontend/src/features/ScoreBalance/types.ts b/frontend/src/features/ScoreBalance/types.ts index c6115f7..9cd58fd 100644 --- a/frontend/src/features/ScoreBalance/types.ts +++ b/frontend/src/features/ScoreBalance/types.ts @@ -25,16 +25,3 @@ export type IFTStorage = { ftLogicId: HexString; transactionStatus: []; }; - -export type SystemAccount = { - consumers: number; // 0 - data: { - feeFrozen: number | HexString; // 0 - free: number | HexString; // '0x...' - miscFrozen: number | HexString; // 0 - reserved: number | HexString; // 8327965542000 - }; - nonce: number; // 94 - providers: number; // 1 - sufficients: number; // 0 -}; diff --git a/frontend/src/features/Wallet/components/WalletInfo/WalletInfo.tsx b/frontend/src/features/Wallet/components/WalletInfo/WalletInfo.tsx index 160d706..2b8b9d7 100644 --- a/frontend/src/features/Wallet/components/WalletInfo/WalletInfo.tsx +++ b/frontend/src/features/Wallet/components/WalletInfo/WalletInfo.tsx @@ -10,7 +10,7 @@ import { Button } from '@/ui'; import { WalletModal } from '../WalletModal'; import styles from './WalletInfo.module.scss'; import { ScorePPV } from '@/features/ScoreBalance/components'; -import { useAccountAvailableBalance } from '@/features/ScoreBalance/hooks'; +import { useAccountAvailableBalance } from '../../hooks'; function WalletInfo({ account }: WalletInfoProps) { const address = useAtom(CONTRACT_ADDRESS_ATOM); diff --git a/frontend/src/features/Wallet/consts.ts b/frontend/src/features/Wallet/consts.ts index 08e9c4c..7616cf0 100644 --- a/frontend/src/features/Wallet/consts.ts +++ b/frontend/src/features/Wallet/consts.ts @@ -1,3 +1,4 @@ +import { atom } from 'jotai'; import EnkryptSVG from '@/assets/icons/enkrypt-icon.svg'; import PolkadotSVG from '@/assets/icons/polkadot-js-icon.svg'; import SubWalletSVG from '@/assets/icons/sub-wallet-icon.svg'; @@ -11,3 +12,6 @@ export const WALLET = { 'subwallet-js': { name: 'SubWallet', SVG: SubWalletSVG }, talisman: { name: 'Talisman', SVG: TalismanSVG }, }; + +export const IS_AVAILABLE_BALANCE_READY = atom(false); +export const AVAILABLE_BALANCE = atom(undefined); diff --git a/frontend/src/features/Wallet/hooks.ts b/frontend/src/features/Wallet/hooks.ts index e4defaf..8f8495b 100644 --- a/frontend/src/features/Wallet/hooks.ts +++ b/frontend/src/features/Wallet/hooks.ts @@ -1,9 +1,12 @@ import { Buffer } from 'buffer'; import { useEffect, useState } from 'react'; -import { useAlert, useAccount } from '@gear-js/react-hooks'; +import { useAtomValue, useSetAtom } from 'jotai'; +import { CreateType } from '@gear-js/api'; +import { formatBalance } from '@polkadot/util'; +import { useAlert, useAccount, useApi } from '@gear-js/react-hooks'; import { LOCAL_STORAGE } from '@/consts'; -import { WALLET, WALLET_ID_LOCAL_STORAGE_KEY } from './consts'; -import { WalletId } from './types'; +import { AVAILABLE_BALANCE, IS_AVAILABLE_BALANCE_READY, WALLET, WALLET_ID_LOCAL_STORAGE_KEY } from './consts'; +import { SystemAccount, WalletId } from './types'; function useWasmMetadata(source: RequestInfo | URL) { const alert = useAlert(); @@ -53,4 +56,50 @@ function useWalletSync() { }, [isAccountReady, address, account]); } +export function useAccountAvailableBalance() { + const isAvailableBalanceReady = useAtomValue(IS_AVAILABLE_BALANCE_READY); + const availableBalance = useAtomValue(AVAILABLE_BALANCE); + const setAvailableBalance = useSetAtom(AVAILABLE_BALANCE); + return { isAvailableBalanceReady, availableBalance, setAvailableBalance }; +} + +export function useAccountAvailableBalanceSync() { + const { isAccountReady, account } = useAccount(); + const { api, isApiReady } = useApi(); + + const isReady = useAtomValue(IS_AVAILABLE_BALANCE_READY); + const setIsReady = useSetAtom(IS_AVAILABLE_BALANCE_READY); + const setAvailableBalance = useSetAtom(AVAILABLE_BALANCE); + + useEffect(() => { + if (!api || !isApiReady || !isAccountReady) return; + + if (account?.decodedAddress) { + api.query.system.account(account.decodedAddress).then((res) => { + const systemAccount = res.toJSON() as SystemAccount; + const total = CreateType.create('u128', systemAccount.data.free).toString(); + const fee = CreateType.create('u128', systemAccount.data.feeFrozen).toString(); + + const getBalance = (b: string) => () => { + const [unit] = api.registry.chainTokens; + const [decimals] = api.registry.chainDecimals; + + const value = formatBalance(b.toString(), { + decimals, + forceUnit: unit, + withSiFull: false, + withSi: false, + withUnit: unit, + }); + + return { value, unit }; + }; + + setAvailableBalance(getBalance(`${+total - +fee}`)); + if (!isReady) setIsReady(true); + }); + } else setIsReady(true); + }, [account, api, isAccountReady, isApiReady, isReady, setAvailableBalance, setIsReady]); +} + export { useWalletSync, useWallet, useWasmMetadata }; diff --git a/frontend/src/features/Wallet/types.ts b/frontend/src/features/Wallet/types.ts index d2e8d31..b04228b 100644 --- a/frontend/src/features/Wallet/types.ts +++ b/frontend/src/features/Wallet/types.ts @@ -1,3 +1,4 @@ +import { HexString } from '@gear-js/api'; import { WALLET } from './consts'; export type WalletId = keyof typeof WALLET; @@ -8,3 +9,16 @@ export type WalletValue = { }; export type WalletEntry = [WalletId, WalletValue]; + +export type SystemAccount = { + consumers: number; // 0 + data: { + feeFrozen: number | HexString; // 0 + free: number | HexString; // '0x...' + miscFrozen: number | HexString; // 0 + reserved: number | HexString; // 8327965542000 + }; + nonce: number; // 94 + providers: number; // 1 + sufficients: number; // 0 +};