From 2aad949299f2a7684bab5b14670a8cec008cace5 Mon Sep 17 00:00:00 2001 From: Yaki Date: Fri, 2 Feb 2024 17:50:19 -0800 Subject: [PATCH 1/5] Fix disableClaiming logic in Staking component --- src/routes/staking.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/staking.tsx b/src/routes/staking.tsx index 9f1d851..7670955 100644 --- a/src/routes/staking.tsx +++ b/src/routes/staking.tsx @@ -468,7 +468,7 @@ const Staking = () => { }; const disableClaiming = useMemo(() => { - return isWaiting || unclaimedEras.total === 0 && totalUnclaimed.toNumber() > 0; + return isWaiting || unclaimedEras.total === 0 && totalUnclaimed.toNumber() === 0; }, [isWaiting, unclaimedEras, totalUnclaimed]); useEffect(() => { From d746f802d5a3a5608554d0ac85065fe2e2e1b290 Mon Sep 17 00:00:00 2001 From: Yaki Date: Fri, 2 Feb 2024 18:33:10 -0800 Subject: [PATCH 2/5] Update Avatar component, set local host for RPC, add BalanceProvider, and format balance safely --- src/components/Avatar.tsx | 2 +- src/components/DaoList.tsx | 18 +++----------- src/components/LoginButton.tsx | 33 ++++++------------------- src/main.tsx | 34 ++++++++++++++------------ src/modals/ManageStaking.tsx | 33 +++++++++---------------- src/providers/balance.tsx | 42 ++++++++++++++++++++++++++++++++ src/stores/rpc.tsx | 4 +-- src/utils/formatBalanceSafely.ts | 37 ++++++++++++++++++++++++++++ src/utils/vestingServices.ts | 16 ++++++++---- 9 files changed, 134 insertions(+), 85 deletions(-) create mode 100644 src/providers/balance.tsx create mode 100644 src/utils/formatBalanceSafely.ts diff --git a/src/components/Avatar.tsx b/src/components/Avatar.tsx index b19f43b..d72fc85 100644 --- a/src/components/Avatar.tsx +++ b/src/components/Avatar.tsx @@ -13,7 +13,7 @@ const Avatar = (props: AvatarProps) => { const handleError = () => { setHasError(true); }; - console.log('Avatar', src); + return (
{src === undefined || hasError ? ( diff --git a/src/components/DaoList.tsx b/src/components/DaoList.tsx index 94a31b0..b0f2167 100644 --- a/src/components/DaoList.tsx +++ b/src/components/DaoList.tsx @@ -1,7 +1,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import ProjectCard from './ProjectCard'; import LoadingSpinner from './LoadingSpinner'; -import { BalanceType, ChainPropertiesType, CoreEraStakeInfoType, CoreIndexedRewardsType, LockedType, StakingCore, TotalRewardsCoreClaimedQuery, TotalUserStakedData, UserStakedInfoType, getTotalUserStaked } from '../routes/staking'; +import { ChainPropertiesType, CoreEraStakeInfoType, CoreIndexedRewardsType, StakingCore, TotalRewardsCoreClaimedQuery, TotalUserStakedData, UserStakedInfoType, getTotalUserStaked } from '../routes/staking'; import { AnyJson, Codec } from '@polkadot/types/types'; import { StakedDaoType } from '../routes/overview'; import BigNumber from 'bignumber.js'; @@ -17,6 +17,7 @@ import Input from './Input'; import FilterIcon from '../assets/filter-icon.svg'; import { CHOOSE_ONE, FilterStates, OrderByOption } from '../modals/DaoListFilters'; import { clearFiltersFromLocalStorage } from '../utils/filterStorage'; +import { useBalance } from '../providers/balance'; interface DaoListProps { mini: boolean; isOverview: boolean; } @@ -27,12 +28,12 @@ const DaoList = (props: DaoListProps) => { const descriptionRef = useRef(null); const projectCardRef = useRef(null); const setOpenModal = useModal((state) => state.setOpenModal); + const { availableBalance } = useBalance(); const selectedAccount = useAccount((state) => state.selectedAccount); const [isLoading, setLoading] = useState(true); const [isDataLoaded, setDataLoaded] = useState(false); const [stakedDaos, setStakedDaos] = useState([]); const [stakingCores, setStakingCores] = useState([]); - const [availableBalance, setAvailableBalance] = useState(); const [chainProperties, setChainProperties] = useState(); const [coreEraStakeInfo, setCoreEraStakeInfo] = useState([]); const [coreIndexedRewards, setCoreIndexedRewards] = useState([]); @@ -269,16 +270,6 @@ const DaoList = (props: DaoListProps) => { }); }, [stakingCores, coreEraStakeInfo, userStakedInfo]); - const loadAccountInfo = useCallback(async () => { - if (!selectedAccount) return; - const account = await api.query.system.account(selectedAccount.address); - const balance = account.toPrimitive() as BalanceType; - const locked = (await api.query.ocifStaking.ledger(selectedAccount.address)).toPrimitive() as LockedType; - const currentBalance = new BigNumber(balance.data.free).minus(new BigNumber(locked.locked)); - - setAvailableBalance(currentBalance); - }, [api, selectedAccount]); - const loadStakingConstants = useCallback(async () => { const maxStakersPerCore = api.consts.ocifStaking.maxStakersPerCore.toPrimitive() as number; const inflationErasPerYear = api.consts.checkedInflation.erasPerYear.toPrimitive() as number; @@ -325,7 +316,6 @@ const DaoList = (props: DaoListProps) => { try { if (selectedAccount) { clearFiltersFromLocalStorage(); - await loadAccountInfo(); await loadCores(); await loadStakingConstants(); await loadCoreEraStake(); @@ -338,7 +328,7 @@ const DaoList = (props: DaoListProps) => { setLoading(false); setDataLoaded(true); } - }, [loadAccountInfo, loadCores, loadStakingConstants, loadCoreEraStake, loadStakeRewardMinimum]); + }, [loadCores, loadStakingConstants, loadCoreEraStake, loadStakeRewardMinimum]); const setupSubscriptions = useCallback(async () => { if (!selectedAccount) { diff --git a/src/components/LoginButton.tsx b/src/components/LoginButton.tsx index 09d9f32..78988e3 100644 --- a/src/components/LoginButton.tsx +++ b/src/components/LoginButton.tsx @@ -2,21 +2,19 @@ import Button from "./Button"; import DisconnectIcon from "../assets/disconnect-icon.svg"; import TinkerYellowIcon from "../assets/tinker-yellow-icon.svg"; import TinkerBlackIcon from "../assets/tinker-black-icon.svg"; -import { useCallback, useEffect, useState } from "react"; -import BigNumber from "bignumber.js"; +import { useEffect, useState } from "react"; import { shallow } from "zustand/shallow"; -import useApi from "../hooks/useApi"; import useConnect from "../hooks/useConnect"; import useAccount from "../stores/account"; import useModal from "../stores/modals"; import { formatBalanceToTwoDecimals } from "../utils/formatNumber"; +import { useBalance } from "../providers/balance"; const LoginButton = () => { - const [balance, setBalance] = useState(); + const { availableBalance, reloadAccountInfo } = useBalance(); const [isHovered, setIsHovered] = useState(false); const [showFirstSpan, setShowFirstSpan] = useState(true); const { handleConnect } = useConnect(); - const api = useApi(); const closeCurrentModal = useModal((state) => state.closeCurrentModal); const { selectedAccount, setSelectedAccount } = useAccount( (state) => ({ @@ -31,21 +29,6 @@ const LoginButton = () => { closeCurrentModal(); }; - const loadBalance = useCallback(async () => { - if (!selectedAccount) return; - - await api.query.system.account(selectedAccount.address, ({ data }) => { - const balance = data.toPrimitive() as { - free: string; - reserved: string; - miscFrozen: string; - feeFrozen: string; - }; - - setBalance(new BigNumber(balance.free)); - }); - }, [selectedAccount, api]); - useEffect(() => { const handleResize = () => { setIsHovered(false); @@ -63,10 +46,6 @@ const LoginButton = () => { }; }, []); - useEffect(() => { - loadBalance(); - }, [loadBalance]); - useEffect(() => { const intervalId = setInterval(() => { setShowFirstSpan(prev => !prev); @@ -75,7 +54,11 @@ const LoginButton = () => { return () => clearInterval(intervalId); }, []); - const formattedBalance = balance ? formatBalanceToTwoDecimals(balance) : 0; + useEffect(() => { + reloadAccountInfo(); + }, [reloadAccountInfo]); + + const formattedBalance = availableBalance ? formatBalanceToTwoDecimals(availableBalance) : 0; return