Skip to content

Commit

Permalink
Merge pull request #43 from InvArch/yaki-coreEraStake
Browse files Browse the repository at this point in the history
Yaki-coreEraStake
  • Loading branch information
shibatales authored Jan 13, 2024
2 parents 4ee3716 + e86c08f commit c4411b2
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 77 deletions.
134 changes: 100 additions & 34 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, LockedType, StakingCore, TotalRewardsCoreClaimedQuery, TotalUserStakedData, UserStakedInfoType, getCoreInfo, getTotalUserStaked } from '../routes/staking';
import { BalanceType, ChainPropertiesType, CoreEraStakeInfoType, CoreIndexedRewardsType, LockedType, StakingCore, TotalRewardsCoreClaimedQuery, TotalUserStakedData, UserStakedInfoType, getCoreInfo, getTotalUserStaked } from '../routes/staking';
import { AnyJson, Codec } from '@polkadot/types/types';
import { StakedDaoType } from '../routes/overview';
import BigNumber from 'bignumber.js';
Expand Down Expand Up @@ -30,14 +30,15 @@ const DaoList = (props: DaoListProps) => {
const [availableBalance, setAvailableBalance] = useState<BigNumber>();
const [chainProperties, setChainProperties] = useState<ChainPropertiesType>();
const [coreEraStakeInfo, setCoreEraStakeInfo] = useState<CoreEraStakeInfoType[]>([]);
const [coreIndexedRewards, setCoreIndexedRewards] = useState<CoreIndexedRewardsType[]>([]);
const [totalUserStakedData, setTotalUserStakedData] = useState<TotalUserStakedData>({});
const [userStakedInfo, setUserStakedInfo] = useState<UserStakedInfoType[]
>([]);

const [rewardsCoreClaimedQuery, reexecuteQuery] = useQuery({
query: TotalRewardsCoreClaimedQuery,
variables: {},
pause: !selectedAccount || isLoading || !isDataLoaded,
pause: !selectedAccount,
});

const toggleViewMembers = (core: StakingCore, members: AnyJson[]) => {
Expand Down Expand Up @@ -78,14 +79,19 @@ const DaoList = (props: DaoListProps) => {
};

const loadCores = useCallback(async () => {
const cores = await loadProjectCores(api);
if (!selectedAccount) return;

const cores = await loadProjectCores(api);
if (cores) {
setStakingCores(cores);
}
}, [api]);
}, [selectedAccount, api]);

const loadTotalUserStaked = useCallback(() => {
if (!coreEraStakeInfo.length || !userStakedInfo.length) {
return;
}

const coreInfoResults: { [key: number]: Partial<CoreEraStakeInfoType> | undefined; } = {};
const totalUserStakedResults: TotalUserStakedData = {};

Expand Down Expand Up @@ -117,13 +123,48 @@ const DaoList = (props: DaoListProps) => {
setChainProperties({ maxStakersPerCore, inflationErasPerYear });
}, [api]);

const loadCoreEraStake = useCallback(async () => {
const coreEraStakeInfoMap: Map<number, CoreEraStakeInfoType> = new Map();
const currentEra = await api.query.ocifStaking.currentEra();

if (coreEraStakeInfo.length === 0) {
for (const stakingCore of stakingCores) {
await api.query.ocifStaking.coreEraStake(stakingCore.key, currentEra, (inf: Codec) => {

const info: {
total: string;
numberOfStakers: number;
rewardClaimed: boolean;
active: boolean;
} = inf.toPrimitive() as {
total: string;
numberOfStakers: number;
rewardClaimed: boolean;
active: boolean;
};

coreEraStakeInfoMap.set(stakingCore.key, {
totalStaked: info.total,
active: info.active,
rewardClaimed: info.rewardClaimed,
numberOfStakers: info.numberOfStakers,
coreId: stakingCore.key
});

const coreEraStake = Array.from(coreEraStakeInfoMap.values());
setCoreEraStakeInfo(coreEraStake);
});
}
}
}, [stakingCores, coreEraStakeInfo.length, api]);

const initializeData = useCallback(async (selectedAccount: InjectedAccountWithMeta | null) => {
try {
if (selectedAccount) {
await loadAccountInfo();
await loadCores();
await loadStakingConstants();
loadTotalUserStaked();
await loadCoreEraStake();
}

} catch (error) {
Expand All @@ -132,7 +173,7 @@ const DaoList = (props: DaoListProps) => {
setLoading(false);
setDataLoaded(true);
}
}, [loadAccountInfo, loadCores, loadStakingConstants, loadTotalUserStaked]);
}, [loadAccountInfo, loadCores, loadStakingConstants, loadCoreEraStake]);

const setupSubscriptions = useCallback(async () => {
if (!selectedAccount) {
Expand All @@ -146,8 +187,39 @@ const DaoList = (props: DaoListProps) => {
number, UserStakedInfoType
> = new Map();

if (coreEraStakeInfo && coreEraStakeInfo.length > 0) {
const currentEra = await api.query.ocifStaking.currentEra();

if (coreEraStakeInfo.length === 0) {
for (const stakingCore of stakingCores) {
await api.query.ocifStaking.coreEraStake(stakingCore.key, currentEra, (inf: Codec) => {

const info: {
total: string;
numberOfStakers: number;
rewardClaimed: boolean;
active: boolean;
} = inf.toPrimitive() as {
total: string;
numberOfStakers: number;
rewardClaimed: boolean;
active: boolean;
};

coreEraStakeInfoMap.set(stakingCore.key, {
totalStaked: info.total,
active: info.active,
rewardClaimed: info.rewardClaimed,
numberOfStakers: info.numberOfStakers,
coreId: stakingCore.key
});

const coreEraStake = Array.from(coreEraStakeInfoMap.values());
setCoreEraStakeInfo(coreEraStake);
});
}

for (const stakingCore of stakingCores) {

await api.query.ocifStaking.generalStakerInfo(
stakingCore.key,
selectedAccount.address,
Expand All @@ -168,28 +240,34 @@ const DaoList = (props: DaoListProps) => {
era: era,
staked: staked,
});
setUserStakedInfo(Array.from(userStakedInfoMap.values()));

const coreEraStake = coreEraStakeInfo.find(info => info.coreId === stakingCore.key);

if (coreEraStake) {
coreEraStakeInfoMap.set(stakingCore.key, {
...coreEraStake,
});

setCoreEraStakeInfo(Array.from(coreEraStakeInfoMap.values()));
}
const userStakedInfo = Array.from(userStakedInfoMap.values());
setUserStakedInfo(userStakedInfo);
}
);
}
}
}, [api, stakingCores, coreEraStakeInfo, selectedAccount]);

useEffect(() => {
const setup = async () => {
if (selectedAccount && typeof setupSubscriptions === 'function') {
await setupSubscriptions();
}
};
setup();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedAccount, stakingCores]);

useEffect(() => {
initializeData(selectedAccount);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedAccount]);

useEffect(() => {
loadTotalUserStaked();
}, [loadTotalUserStaked, coreEraStakeInfo, userStakedInfo, selectedAccount]);

useEffect(() => {
const loadDaos = async () => {
if (!selectedAccount) return;
Expand All @@ -202,10 +280,6 @@ const DaoList = (props: DaoListProps) => {
loadDaos();
}, [selectedAccount, stakingCores, api]);

useEffect(() => {
loadTotalUserStaked();
}, [stakingCores, loadTotalUserStaked]);

useEffect(() => {
if (selectedAccount) {
reexecuteQuery();
Expand All @@ -215,25 +289,15 @@ const DaoList = (props: DaoListProps) => {
useEffect(() => {
if (!rewardsCoreClaimedQuery.data?.cores?.length || !selectedAccount) return;

const coreEraStakeInfoMap: CoreEraStakeInfoType[] = rewardsCoreClaimedQuery.data.cores;
const coreIndexedRewardsMap: CoreIndexedRewardsType[] = rewardsCoreClaimedQuery.data.cores;

const uniqueCoreEraStakeInfo = coreEraStakeInfoMap.filter((core, index, self) =>
const uniqueCoreIndexedRewards = coreIndexedRewardsMap.filter((core, index, self) =>
index === self.findIndex((item) => item.coreId === core.coreId)
);

setCoreEraStakeInfo(uniqueCoreEraStakeInfo);
setCoreIndexedRewards(uniqueCoreIndexedRewards);
}, [selectedAccount, stakingCores, rewardsCoreClaimedQuery.data]);

useEffect(() => {
const setup = async () => {
if (selectedAccount && typeof setupSubscriptions === 'function') {
await setupSubscriptions();
}
};
setup();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedAccount, stakingCores]);

const stakedCoresCount = useMemo(() => {
return isOverview
? stakingCores.filter(core =>
Expand All @@ -256,6 +320,7 @@ const DaoList = (props: DaoListProps) => {
<div className="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
{stakingCores.map((core: StakingCore) => {
const coreInfo = coreEraStakeInfo.find((info) => info.coreId === core.key);
const coreRewards = coreIndexedRewards.find((info) => info.coreId === core.key);
const userStaked = totalUserStakedData[core.key] ? totalUserStakedData[core.key] : new BigNumber(0);

// If userStaked is zero, don't render the card
Expand All @@ -270,6 +335,7 @@ const DaoList = (props: DaoListProps) => {
core={core}
totalUserStaked={userStaked}
coreInfo={coreInfo}
coreRewards={coreRewards}
handleManageStaking={handleManageStaking}
handleViewDetails={(mini) => handleViewDetails(mini, projectCard(false))}
toggleExpanded={toggleReadMore}
Expand Down
16 changes: 9 additions & 7 deletions src/components/ProjectCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { RefObject, useCallback, useEffect, useState } from 'react';
import { BigNumber } from 'bignumber.js';
import { LockClosedIcon } from '@heroicons/react/24/outline';
import toast from 'react-hot-toast';
import { StakingCore, CoreEraStakeInfoType, ChainPropertiesType } from '../routes/staking';
import { StakingCore, CoreEraStakeInfoType, ChainPropertiesType, CoreIndexedRewardsType } from '../routes/staking';
import { InjectedAccountWithMeta } from '@polkadot/extension-inject/types';
import TotalStakersIcon from '../assets/total-stakers-icon.svg';
import TotalStakedIcon from '../assets/total-staked-icon.svg';
Expand All @@ -21,6 +21,7 @@ export interface ProjectCardProps {
core: StakingCore;
totalUserStaked: BigNumber | undefined;
coreInfo: Partial<CoreEraStakeInfoType> | undefined;
coreRewards: Partial<CoreIndexedRewardsType> | undefined;
chainProperties: ChainPropertiesType | undefined;
availableBalance: BigNumber | undefined;
handleManageStaking: (args: {
Expand All @@ -44,6 +45,7 @@ const ProjectCard = (props: ProjectCardProps) => {
core,
totalUserStaked: totalStaked,
coreInfo,
coreRewards,
chainProperties,
availableBalance,
handleManageStaking,
Expand Down Expand Up @@ -123,7 +125,7 @@ const ProjectCard = (props: ProjectCardProps) => {
useEffect(() => {
calcMinSupportMet();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
}, [minStakeReward, coreInfo?.totalStaked]);

useEffect(() => {
if (totalStaked !== undefined) {
Expand Down Expand Up @@ -234,8 +236,8 @@ const ProjectCard = (props: ProjectCardProps) => {
</div>
</div>
<div className="font-normal text-white text-[12px] text-right tracking-[0] leading-[normal] truncate">
{coreInfo?.totalRewards
? `${ formatNumberShorthand(parseFloat(coreInfo?.totalRewards.toString()) / Math.pow(10, 12)) } TNKR`
{coreRewards?.totalRewards
? `${ formatNumberShorthand(parseFloat(coreRewards?.totalRewards.toString()) / Math.pow(10, 12)) } TNKR`
: '--'}
</div>
</div> : null}
Expand All @@ -251,8 +253,8 @@ const ProjectCard = (props: ProjectCardProps) => {
</div>
</div>
<div className="font-normal text-white text-[12px] text-right tracking-[0] leading-[normal] truncate">
{coreInfo?.totalUnclaimed
? `${ formatNumberShorthand(parseFloat(coreInfo?.totalUnclaimed.toString()) / Math.pow(10, 12)) } TNKR`
{coreRewards?.totalUnclaimed
? `${ formatNumberShorthand(parseFloat(coreRewards?.totalUnclaimed.toString()) / Math.pow(10, 12)) } TNKR`
: '--'}
</div>
</div> : null}
Expand Down Expand Up @@ -304,4 +306,4 @@ const ProjectCard = (props: ProjectCardProps) => {
);
};

export default ProjectCard;
export default ProjectCard;
1 change: 1 addition & 0 deletions src/modals/ManageStaking.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,7 @@ const ManageStaking = (props: { isOpen: boolean; }) => {
<Button mini variant="primary" type="submit" disabled={!unstakeForm.formState.isValid}>
Unstake {watchedUnstakeAmount} TNKR
</Button>
<p className="text-xxs text-center text-tinkerYellow text-opacity-60">NOTE: Unstaking TNKR will have an unbonding period of 7 days.</p>
</form>
</Tab.Panel>
</Tab.Panels>
Expand Down
23 changes: 12 additions & 11 deletions src/routes/overview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -199,9 +199,20 @@ const Overview = () => {
}
}, [loadAccountInfo, loadCores, loadAggregateStaked, loadVestingBalance, loadCurrentEra]);

useEffect(() => {
const setup = async () => {
if (selectedAccount && typeof setupSubscriptions === 'function') {
await setupSubscriptions();
}
};
setup();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedAccount, stakingCores, coreEraStakeInfo]);

useEffect(() => {
initializeData(selectedAccount);
}, [initializeData, selectedAccount]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedAccount]);

useEffect(() => {
if (rewardsUserClaimedQuery.fetching || !selectedAccount?.address) return;
Expand Down Expand Up @@ -235,16 +246,6 @@ const Overview = () => {
setCoreEraStakeInfo(uniqueCoreEraStakeInfo);
}, [selectedAccount, stakingCores, rewardsCoreClaimedQuery.data, rewardsCoreClaimedQuery.fetching]);

useEffect(() => {
const setup = async () => {
if (selectedAccount && typeof setupSubscriptions === 'function') {
await setupSubscriptions();
}
};
setup();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedAccount, stakingCores, coreEraStakeInfo]);

return (
<div className="mx-auto w-full flex max-w-7xl flex-col justify-between p-4 sm:px-6 lg:px-8 mt-14 md:mt-0 gap-3">
<div className="flex flex-col md:flex-row justify-between items-start md:items-center">
Expand Down
Loading

1 comment on commit c4411b2

@vercel
Copy link

@vercel vercel bot commented on c4411b2 Jan 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.