Skip to content

Commit

Permalink
feat: integration of starting overview page
Browse files Browse the repository at this point in the history
  • Loading branch information
Teja2045 committed Nov 14, 2023
1 parent 7b0c4c8 commit 3244b2d
Show file tree
Hide file tree
Showing 20 changed files with 5,618 additions and 61 deletions.
3 changes: 2 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "staking",
"name": "resolute",
"version": "0.1.0",
"private": true,
"scripts": {
Expand Down Expand Up @@ -36,6 +36,7 @@
"react-dom": "^18.2.0",
"react-hook-form": "^7.47.0",
"react-redux": "^8.1.3",
"react-router-dom": "^6.18.0",
"tailwindcss": "3.3.3",
"typescript": "5.2.2"
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,292 @@
'use client';
import React, { useCallback, useEffect, useMemo } from 'react';
import { RootState } from '../../../..//store/store';
import { parseBalance } from '@/utils/denom';
import { getBalances } from '@/store/features/bank/bankSlice';
import { getIBCBalances } from '@/utils/ibc';
import chainDenoms from '@/utils/chainDenoms.json';
import { useAppDispatch, useAppSelector } from '@/hooks/StateHooks';
import {
getDelegations,
getAllValidators,
} from '@/store/features/staking/stakeSlice';

const chainDenomsData = chainDenoms as AssetData;

const OverviewPage = () => {
const dispatch = useAppDispatch();
const networks = useAppSelector((state: RootState) => state.wallet.networks);
const stakingChains = useAppSelector(
(state: RootState) => state.staking.chains
);
const balanceChains = useAppSelector(
(state: RootState) => state.bank.balances
);
const nameToChainIDs: Record<string, string> = useAppSelector(
(state: RootState) => state.wallet.nameToChainIDs
);
const chainIDs = Object.keys(nameToChainIDs).map(
(chainName) => nameToChainIDs[chainName]
);

const chainIdToNames = useMemo(() => {
const chainIdToNames: Record<string, string> = {};
for (const key in nameToChainIDs) {
chainIdToNames[nameToChainIDs[key]] = key;
}
return chainIdToNames;
}, [nameToChainIDs]);

const convertToDollars = (denom: string, amount: number) => {
// todo: after common slice
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
const tokensPriceInfo: any = {};
if (tokensPriceInfo?.[denom]) {
const price = +tokensPriceInfo?.[denom]?.info?.['usd'] || 0;
return amount * price;
}
return 0;
};

const calculateTotalStakedAmount = useCallback(() => {
let totalStakedAmount = 0;
chainIDs.forEach((chainID) => {
const staked = stakingChains?.[chainID]?.delegations?.totalStaked || 0;
if (staked > 0) {
const denom =
networks?.[chainID]?.network?.config?.currencies?.[0]
?.coinMinimalDenom;
const decimals =
networks?.[chainID]?.network?.config?.currencies?.[0]?.coinDecimals ||
0;
totalStakedAmount += convertToDollars(denom, staked / 10 ** decimals);
}
});
return totalStakedAmount;
}, [chainIDs, stakingChains, networks]);

// Todo: can be added after distribution slice is added
// const calculateTotalPendingAmount = useCallback(() => {
// let totalRewards = 0;
// chainIDs.forEach((chainID) => {
// const rewards =
// distributionChains?.[chainID]?.delegatorRewards?.totalRewards || 0;
// if (rewards > 0) {
// const denom =
// networks?.[chainID]?.network?.config?.currencies?.[0]
// ?.coinMinimalDenom;
// const decimals =
// networks?.[chainID]?.network?.config?.currencies?.[0]?.coinDecimals ||
// 0;
// totalRewards += convertToDollars(denom, rewards / 10 ** decimals);
// }
// });
// return totalRewards;
// }, [chainIDs, distributionChains, networks]);

const calculateTotalAvailableAmount = useCallback(() => {
let totalBalance = 0;
let totalIBCBalance = 0;
chainIDs.forEach((chainID) => {
const decimals =
networks?.[chainID]?.network?.config?.currencies?.[0]?.coinDecimals ||
0;
const denom =
networks?.[chainID]?.network?.config?.currencies?.[0]?.coinMinimalDenom;
const balance = parseBalance(
balanceChains?.[chainID]?.list || [],
decimals,
denom
);
const chainName =
networks?.[chainID]?.network?.config?.chainName.toLowerCase();
const ibcBalances = getIBCBalances(
balanceChains?.[chainID]?.list,
denom,
chainName
);
for (let i = 0; i < ibcBalances?.length; i++) {
totalIBCBalance += convertToDollars(
ibcBalances[i].balance.denom,
parseBalance(
[ibcBalances[i].balance],
ibcBalances?.[i]?.decimals,
ibcBalances?.[i]?.balance.denom
)
);
}
if (balanceChains?.[chainID]?.list?.length > 0) {
totalBalance += convertToDollars(denom, balance);
}
});
return { totalBalance: totalBalance, totalIBCBalance: totalIBCBalance };
}, [chainIDs, balanceChains, networks]);

const getSortedChainIds = useCallback(() => {
let sortedChains: { chainID: string; usdValue: number }[] = [];
chainIDs.forEach((chainID) => {
const decimals =
networks?.[chainID]?.network?.config?.currencies?.[0]?.coinDecimals ||
0;
const denom =
networks?.[chainID]?.network?.config?.currencies?.[0]?.coinMinimalDenom;
const balanceAmountInDenoms = parseBalance(
balanceChains?.[chainID]?.list || [],
decimals,
denom
);
// minimalDenom
const stakedAmountInDenoms: number =
stakingChains?.[chainID]?.delegations?.totalStaked || 0;
// minimalDenom
// Todo: after distribution slice is added
// const rewards =
// distributionChains?.[chainID]?.delegatorRewards?.totalRewards || 0;
const rewardsAmountInDenoms: number = 0;
const chain: { chainID: string; usdValue: number } = {
chainID,
usdValue: 0,
};
if (balanceChains?.[chainID]?.list?.length > 0) {
chain.usdValue =
convertToDollars(denom, balanceAmountInDenoms) +
convertToDollars(denom, stakedAmountInDenoms / 10 ** decimals) +
convertToDollars(denom, rewardsAmountInDenoms / 10 ** decimals);
}
sortedChains = [...sortedChains, chain];
});
sortedChains.sort((x, y) => y.usdValue - x.usdValue);
return sortedChains.map((chain) => chain.chainID);
}, [chainIDs, networks, balanceChains]);

const getIBCSortedChainIds = useCallback(() => {
let sortedIBCChains: {
usdValue: number;
usdPrice: number;
balanceAmount: number;
chainName: string;
denomInfo: (IBCAsset | NativeAsset)[];
}[] = [];

chainIDs.forEach((chainID) => {
const chainName = chainIdToNames[chainID];
const minimalDenom =
networks?.[chainID]?.network?.config?.currencies?.[0]?.coinMinimalDenom;
const chainBalances = balanceChains?.[chainID]?.list || [];
chainBalances.forEach((balance) => {
const denomInfo = chainDenomsData[chainName]?.filter((denomInfo) => {
return denomInfo.denom === balance.denom;
});
if (balance?.denom !== minimalDenom && denomInfo?.length) {
// const usdDenomPrice =
// tokensPriceInfo[denomInfo[0]?.origin_denom]?.info?.['usd'] || 0;
const usdDenomPrice = 0;
const balanceAmount = parseBalance(
[balance],
denomInfo[0].decimals,
balance.denom
);
const usdDenomValue = balanceAmount * usdDenomPrice;
sortedIBCChains = [
...sortedIBCChains,
{
usdValue: usdDenomValue,
usdPrice: usdDenomPrice,
balanceAmount: balanceAmount,
chainName: chainName,
denomInfo: denomInfo,
},
];
}
});
});

sortedIBCChains.sort((x, y) => y.usdValue - x.usdValue);
return sortedIBCChains;
}, [chainIDs, networks, balanceChains]);

useEffect(() => {
chainIDs.forEach((chainID) => {
const chainInfo = networks[chainID]?.network;
const address = networks[chainID]?.walletInfo?.bech32Address;
// const denom =
// networks?.[chainID]?.network?.config?.currencies?.[0]?.coinMinimalDenom;

dispatch(
getBalances({
baseURL: chainInfo.config.rest,
address: address,
chainID: chainID,
})
);

dispatch(
getDelegations({
baseURL: chainInfo.config.rest,
address: address,
chainID: chainID,
})
);

dispatch(
getAllValidators({
baseURL: chainInfo.config.rest,
chainID: chainID,
})
);

// Todo: after distribution slice
// dispatch(
// getDelegatorTotalRewards({
// baseURL: chainInfo.config.rest,
// address: address,
// chainID: chainID,
// denom: denom,
// })
// );
});
}, []);

const {
totalBalance: totalAvailableAmount,
totalIBCBalance: totalIBCAssetsAmount,
} = useMemo(
() => calculateTotalAvailableAmount(),
[calculateTotalAvailableAmount]
);
const totalStakedAmount = useMemo(
() => calculateTotalStakedAmount(),
[calculateTotalStakedAmount]
);
// const totalPendingAmount = useMemo(
// () => calculateTotalPendingAmount(),
// [calculateTotalPendingAmount]
// );

const sortedChainIds = useMemo(
() => getSortedChainIds(),
[getSortedChainIds]
);

const ibcSortedChains = useMemo(
() => getIBCSortedChainIds(),
[getIBCSortedChainIds]
);
return (
<div>
{JSON.stringify(sortedChainIds)}
<br />
<br />
{JSON.stringify(ibcSortedChains)}
<br />
<br />
{totalAvailableAmount +
' ' +
totalIBCAssetsAmount +
' ' +
totalStakedAmount}
</div>
);
};

export default OverviewPage;
9 changes: 9 additions & 0 deletions frontend/src/app/(routes)/(overview)/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React from 'react';
import OverviewPage from './overview-components/OverviewPage';

const Page = () => {
return <OverviewPage />;
//return <>Overview</>
};

export default Page;
2 changes: 1 addition & 1 deletion frontend/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { Metadata } from 'next';
import { Inter } from 'next/font/google';
import PermanentSideBar from '../components/PermanentSidebar';
import { ConnectWalletButton } from '../components/ConnectWalletButton';
import { StoreProvider } from 'staking/store/StoreProvider';
import { StoreProvider } from '@/store/StoreProvider';

const inter = Inter({ subsets: ['latin'] });

Expand Down
6 changes: 0 additions & 6 deletions frontend/src/app/page.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion frontend/src/components/popups/WalletPage.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import Image from 'next/image';
import { Dialog, DialogContent } from '@mui/material';
import { supportedWallets } from 'staking/utils/contants';
import { supportedWallets } from '@/utils/contants';

const Walletpage = ({
open,
Expand Down
7 changes: 7 additions & 0 deletions frontend/src/hooks/StateHooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
import type { RootState, AppDispatch } from '@/store/store';

// Use throughout your app instead of plain `useDispatch` and `useSelector`
type DispatchFunc = () => AppDispatch;
export const useAppDispatch: DispatchFunc = useDispatch;
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
2 changes: 1 addition & 1 deletion frontend/src/store/features/bank/bankService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const balanceURL = (address: string, denom: string) =>
const fetchBalances = (
baseURL: string,
address: string,
pagination: KeyLimitPagination
pagination?: KeyLimitPagination
): Promise<AxiosResponse> => {
let uri = `${cleanURL(baseURL)}${balancesURL}${address}`;
const parsed = convertPaginationToParams(pagination);
Expand Down
Loading

0 comments on commit 3244b2d

Please sign in to comment.