Skip to content

Commit

Permalink
Merge pull request #57 from InvArch:yaki-tnkr-claim-fix-020124
Browse files Browse the repository at this point in the history
Yaki-tnkr-claim-fix-020124
  • Loading branch information
shibatales authored Feb 3, 2024
2 parents bccebc4 + caac493 commit 971bbc9
Show file tree
Hide file tree
Showing 11 changed files with 136 additions and 91 deletions.
2 changes: 1 addition & 1 deletion src/components/Avatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const Avatar = (props: AvatarProps) => {
const handleError = () => {
setHasError(true);
};
console.log('Avatar', src);

return (
<div className="flex flex-shrink-0">
{src === undefined || hasError ? (
Expand Down
18 changes: 4 additions & 14 deletions src/components/DaoList.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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; }

Expand All @@ -27,12 +28,12 @@ const DaoList = (props: DaoListProps) => {
const descriptionRef = useRef<HTMLDivElement | null>(null);
const projectCardRef = useRef<HTMLDivElement | null>(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<StakedDaoType[]>([]);
const [stakingCores, setStakingCores] = useState<StakingCore[]>([]);
const [availableBalance, setAvailableBalance] = useState<BigNumber>();
const [chainProperties, setChainProperties] = useState<ChainPropertiesType>();
const [coreEraStakeInfo, setCoreEraStakeInfo] = useState<CoreEraStakeInfoType[]>([]);
const [coreIndexedRewards, setCoreIndexedRewards] = useState<CoreIndexedRewardsType[]>([]);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -325,7 +316,6 @@ const DaoList = (props: DaoListProps) => {
try {
if (selectedAccount) {
clearFiltersFromLocalStorage();
await loadAccountInfo();
await loadCores();
await loadStakingConstants();
await loadCoreEraStake();
Expand All @@ -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) {
Expand Down
29 changes: 4 additions & 25 deletions src/components/LoginButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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<BigNumber>();
const { availableBalance } = 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) => ({
Expand All @@ -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);
Expand All @@ -63,10 +46,6 @@ const LoginButton = () => {
};
}, []);

useEffect(() => {
loadBalance();
}, [loadBalance]);

useEffect(() => {
const intervalId = setInterval(() => {
setShowFirstSpan(prev => !prev);
Expand All @@ -75,7 +54,7 @@ const LoginButton = () => {
return () => clearInterval(intervalId);
}, []);

const formattedBalance = balance ? formatBalanceToTwoDecimals(balance) : 0;
const formattedBalance = availableBalance ? formatBalanceToTwoDecimals(availableBalance) : 0;

return <Button
mini
Expand Down
2 changes: 1 addition & 1 deletion src/components/ProjectCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ const ProjectCard = (props: ProjectCardProps) => {
htmlElement.style.backgroundColor = '';
}
});
}, []);
}, [mini]);

useEffect(() => {
loadAggregateStaked();
Expand Down
34 changes: 18 additions & 16 deletions src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
} from "urql";
import { createClient as createWSClient } from "graphql-ws";
import Claim from "./routes/claim";
import Transfer from "./routes/xtransfer";
import Staking from "./routes/staking";
import NotFound from "./routes/not-found";
import "./index.css";
Expand All @@ -19,6 +18,7 @@ import ApiProvider from "./providers/api";
import Layout from "./components/Layout";
import Modals from "./modals";
import Overview from "./routes/overview";
import { BalanceProvider } from "./providers/balance";

const wsClient = createWSClient({
url: "wss://squid.subsquid.io/ocif-squid/v/v4/graphql",
Expand Down Expand Up @@ -51,28 +51,30 @@ ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
<Toaster position="bottom-right" />
<BrowserRouter>
<ApiProvider>
<URQLProvider value={client}>
<Modals />
<BalanceProvider>
<URQLProvider value={client}>
<Modals />

<Routes>
<Route index element={<Navigate to="overview" replace={true} />} />
<Routes>
<Route index element={<Navigate to="overview" replace={true} />} />

<Route path="/" element={<Layout />}>
<Route path="overview" element={<Overview />} />
<Route path="/" element={<Layout />}>
<Route path="overview" element={<Overview />} />

<Route path="claim" element={<Claim />} />
<Route path="claim" element={<Claim />} />

{/* Disabled temporarily */}
{/* <Route path="transfer" element={<Transfer />} /> */}
{/* Disabled temporarily */}
{/* <Route path="transfer" element={<Transfer />} /> */}

<Route path="staking" element={<Staking />} />
<Route path="staking" element={<Staking />} />

<Route path="404" element={<NotFound />} />
<Route path="404" element={<NotFound />} />

<Route path="*" element={<Navigate to="/404" replace={true} />} />
</Route>
</Routes>
</URQLProvider>
<Route path="*" element={<Navigate to="/404" replace={true} />} />
</Route>
</Routes>
</URQLProvider>
</BalanceProvider>
</ApiProvider>
</BrowserRouter>
</>
Expand Down
33 changes: 11 additions & 22 deletions src/modals/ManageStaking.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { Dialog, Tab } from "@headlessui/react";
import { XMarkIcon } from "@heroicons/react/24/outline";
import { zodResolver } from "@hookform/resolvers/zod";
import { web3Enable, web3FromAddress } from "@polkadot/extension-dapp";
import { formatBalance } from "@polkadot/util";
import BigNumber from "bignumber.js";
import { memo, useEffect, useMemo, useRef, useState } from "react";
import { useForm } from "react-hook-form";
Expand All @@ -19,6 +18,8 @@ import Button from "../components/Button";
import { StakingCore, TotalUserStakedData } from "../routes/staking";
import Dropdown from "../components/Dropdown";
import { BG_GRADIENT } from "../utils/consts";
import { formatBalanceSafely } from "../utils/formatBalanceSafely";
import { useBalance } from "../providers/balance";

export interface SelectedCoreInfo extends Metadata {
id: number;
Expand All @@ -42,6 +43,7 @@ const schema = z.object({

const ManageStaking = (props: { isOpen: boolean; }) => {
const { isOpen } = props;
const { reloadAccountInfo } = useBalance();
const [stakingCores, setStakingCores] = useState<StakingCore[]>([]);
const [selectedCore, setSelectedCore] = useState<StakingCore | null>(null);
const [totalUserStakedData, setTotalUserStakedData] = useState<TotalUserStakedData>({});
Expand Down Expand Up @@ -154,6 +156,7 @@ const ManageStaking = (props: { isOpen: boolean; }) => {
onSuccess: () => {
toast.dismiss();
toast.success("Staked successfully");
reloadAccountInfo();
},
onDropped: () => {
toast.dismiss();
Expand Down Expand Up @@ -250,6 +253,7 @@ const ManageStaking = (props: { isOpen: boolean; }) => {
onSuccess: () => {
toast.dismiss();
toast.success("Unstaked successfully");
reloadAccountInfo();
},
onDropped: () => {
toast.dismiss();
Expand Down Expand Up @@ -364,11 +368,7 @@ const ManageStaking = (props: { isOpen: boolean; }) => {
isAltBalance(true);

if (selectedCoreInfo?.userStaked) {
const stakedBalance = formatBalance(selectedCoreInfo?.userStaked?.toString(), {
decimals: 12,
withUnit: false,
forceUnit: "-",
}).slice(0, -2) || "0";
const stakedBalance = formatBalanceSafely(selectedCoreInfo?.userStaked?.toString());
setCoreStakedBalance(stakedBalance);
}
return;
Expand Down Expand Up @@ -428,17 +428,10 @@ const ManageStaking = (props: { isOpen: boolean; }) => {
<div className="flex flex-row justify-around gap-4 sm:flex-auto mb-4">
<div className="text-sm text-white text-center">
<div className="font-bold">
{formatBalance(
{formatBalanceSafely(
metadata?.availableBalance
? metadata.availableBalance.toString()
: "0",
{
decimals: 12,
withUnit: false,
forceUnit: "-",
}
).slice(0, -2) || "0"}{" "}
TNKR
: "0")}
</div>
<div className="text-xxs/none">Available Balance</div>
</div>
Expand All @@ -447,11 +440,7 @@ const ManageStaking = (props: { isOpen: boolean; }) => {
metadata?.totalUserStaked.toString() !== "0" ? (
<div className="text-sm text-white text-center">
<div className="font-bold">
{formatBalance(metadata?.totalUserStaked?.toString(), {
decimals: 12,
withUnit: false,
forceUnit: "-",
}).slice(0, -2) || "0"} TNKR
{formatBalanceSafely(metadata?.totalUserStaked?.toString())}
</div>
<div className="text-xxs/none">Currently Staked</div>
</div>
Expand Down Expand Up @@ -512,12 +501,12 @@ const ManageStaking = (props: { isOpen: boolean; }) => {
<div className="flex-grow">
<label
htmlFor="stakeAmount"
className="block text-xxs font-medium text-white mb-1"
className="block text-xxs font-medium text-white mb-1 truncate"
>
<span>Stake Amount</span>
{altBalance ?
<span className="float-right">
Balance: <span className="font-bold">{coreStakedBalance}</span> TNKR
Balance: <span className="font-bold">{coreStakedBalance}</span>
</span> : null}
</label>
<div className="relative flex flex-row items-center">
Expand Down
42 changes: 42 additions & 0 deletions src/providers/balance.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { createContext, useContext, useState, useEffect, useCallback, ReactNode } from 'react';
import BigNumber from 'bignumber.js';
import useApi from '../hooks/useApi';
import useAccount from '../stores/account';

interface BalanceContextType {
availableBalance: BigNumber;
reloadAccountInfo: () => void;
}

const BalanceContext = createContext<BalanceContextType>({
availableBalance: new BigNumber(0),
reloadAccountInfo: () => { },
});

export const BalanceProvider = ({ children }: { children: ReactNode; }) => {
const [availableBalance, setAvailableBalance] = useState(new BigNumber(0));
const api = useApi();
const { selectedAccount } = useAccount();

const loadAccountInfo = useCallback(async () => {
if (!selectedAccount || !api) return;
const account = await api.query.system.account(selectedAccount.address);
const balance = account.toPrimitive() as { data: { free: string; }; };
const locked = (await api.query.ocifStaking.ledger(selectedAccount.address)).toPrimitive() as { locked: string; };
const currentBalance = new BigNumber(balance.data.free).minus(new BigNumber(locked.locked));

setAvailableBalance(currentBalance);
}, [api, selectedAccount]);

useEffect(() => {
loadAccountInfo();
}, [selectedAccount, api, loadAccountInfo]);

return (
<BalanceContext.Provider value={{ availableBalance, reloadAccountInfo: loadAccountInfo }}>
{children}
</BalanceContext.Provider>
);
};

export const useBalance = () => useContext(BalanceContext);
10 changes: 5 additions & 5 deletions src/routes/staking.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -456,19 +456,19 @@ const Staking = () => {

setTotalUnclaimed(new BigNumber(0));
setUnclaimedEras({ cores: [], total: 0 });
setClaimAllSuccess(result);
setClaimAllSuccess(true);
refreshQuery();
};

const refreshQuery = () => {
const refreshQuery = useCallback(() => {
if (!claimAllSuccess) return;
reexecuteQuery({ requestPolicy: 'network-only' });
reexecuteCoreQuery({ requestPolicy: 'network-only' });
setClaimAllSuccess(false);
};
}, [claimAllSuccess, reexecuteQuery, reexecuteCoreQuery]);

const disableClaiming = useMemo(() => {
return isWaiting || unclaimedEras.total === 0 && totalUnclaimed.toNumber() > 0;
return isWaiting || unclaimedEras.total === 0 && totalUnclaimed.toNumber() === 0;
}, [isWaiting, unclaimedEras, totalUnclaimed]);

useEffect(() => {
Expand Down Expand Up @@ -525,7 +525,7 @@ const Staking = () => {
if (initialUnclaimed.current === null) {
initialUnclaimed.current = totalUnclaimed;
}
}, [selectedAccount, rewardsUserClaimedQuery.fetching, rewardsUserClaimedQuery.data, claimAllSuccess]);
}, [selectedAccount, rewardsUserClaimedQuery.fetching, rewardsUserClaimedQuery.data, claimAllSuccess, refreshQuery]);

useEffect(() => {
if (rewardsCoreClaimedQuery.fetching || !rewardsCoreClaimedQuery.data?.cores?.length || !selectedAccount) return;
Expand Down
Loading

0 comments on commit 971bbc9

Please sign in to comment.