Skip to content

Commit

Permalink
Merge pull request #64 from secretkeylabs/imamahzafar/feat/stacking
Browse files Browse the repository at this point in the history
Add stacking screen
  • Loading branch information
Imamah-Zafar committed Nov 21, 2022
2 parents a051132 + eab617d commit a715a73
Show file tree
Hide file tree
Showing 11 changed files with 446 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/app/components/tabBar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ function BottomTabBar({ tab }:Props) {
};

const handleStackingButtonClick = () => {

if (tab !== 'stacking') { navigate('/stacking'); }
};

const handleSettingButtonClick = () => {
Expand Down
58 changes: 58 additions & 0 deletions src/app/hooks/useStackingData.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { useQueries } from '@tanstack/react-query';
import { useCallback } from 'react';
import {
fetchDelegationState, fetchPoolStackerInfo, fetchStackingPoolInfo, getStacksInfo, StackingData,
} from '@secretkeylabs/xverse-core';
import useWalletSelector from './useWalletSelector';

const useStackingData = () => {
const { stxAddress, network } = useWalletSelector();

const results = useQueries({
queries: [
{
queryKey: ['stacking-core-info', network],
queryFn: () => getStacksInfo(network.address),
},
{
queryKey: ['stacking-delegation-state', stxAddress, network],
queryFn: () => fetchDelegationState(stxAddress, network),
},
{
queryKey: ['stacking-pool-info'],
queryFn: () => fetchStackingPoolInfo(),
},
{
queryKey: ['pool-stacker-info', stxAddress],
queryFn: () => fetchPoolStackerInfo(stxAddress),
},
],
});

const coreInfoData = results[0].data;
const delegationStateData = results[1].data;
const poolInfoData = results[2].data;
const stackerInfoData = results[3].data;

const isStackingLoading = results.some((result) => result.isLoading);
const stackingError = results.find(({ error }) => error != null)?.error;
const refetchStackingData = useCallback(() => {
results.forEach((result) => result.refetch());
}, [results]);

const stackingData: StackingData = {
poolInfo: poolInfoData,
delegationInfo: delegationStateData!,
coreInfo: coreInfoData!,
stackerInfo: stackerInfoData,
};

return {
isStackingLoading,
stackingError,
stackingData,
refetchStackingData,
};
};

export default useStackingData;
5 changes: 5 additions & 0 deletions src/app/routes/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import Login from '@screens/login';
import RestoreWallet from '@screens/restoreWallet';
import ForgotPassword from '@screens/forgotPassword';
import BackupWalletSteps from '@screens/backupWalletSteps';
import Stacking from '@screens/stacking';
import NftDashboard from '@screens/nftDashboard';
import NftDetailScreen from '@screens/nftDetail';
import Setting from '@screens/settings';
Expand Down Expand Up @@ -119,6 +120,10 @@ const router = createHashRouter([
path: 'backupWalletSteps',
element: <BackupWalletSteps />,
},
{
path: 'stacking',
element: <Stacking />,
},
{
path: 'nft-dashboard',
element: <NftDashboard />,
Expand Down
63 changes: 63 additions & 0 deletions src/app/screens/stacking/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { useNavigate } from 'react-router-dom';
import { Ring } from 'react-spinners-css';
import { useEffect, useState } from 'react';
import styled from 'styled-components';
import useStackingData from '@hooks/useStackingData';
import useWalletSelector from '@hooks/useWalletSelector';
import AccountRow from '@components/accountRow';
import BottomBar from '@components/tabBar';
import StackingProgress from './stackingProgress';
import StartStacking from './startStacking';

const SelectedAccountContainer = styled.div((props) => ({
marginLeft: props.theme.spacing(8),
marginRight: props.theme.spacing(8),
}));

const LoaderContainer = styled.div((props) => ({
display: 'flex',
flex: 1,
justifyContent: 'center',
alignItems: 'center',
marginTop: props.theme.spacing(12),
}));

function Stacking() {
const { selectedAccount } = useWalletSelector();
const { isStackingLoading, stackingData } = useStackingData();
const navigate = useNavigate();
const [isStacking, setIsStacking] = useState<boolean>(false);
const handleAccountSelect = () => {
navigate('/account-list');
};

useEffect(() => {
if (stackingData) {
if (stackingData?.stackerInfo?.stacked || stackingData?.delegationInfo?.delegated) {
setIsStacking(true);
}
}
}, [stackingData]);

const showStatus = !isStackingLoading && (
isStacking ? <StackingProgress /> : <StartStacking />
);

return (
<>
<SelectedAccountContainer>
<AccountRow account={selectedAccount!} isSelected onAccountSelected={handleAccountSelect} />
</SelectedAccountContainer>
{isStackingLoading && (
<LoaderContainer>
<Ring color="white" size={30} />
</LoaderContainer>
) }
{showStatus}
<BottomBar tab="stacking" />
</>

);
}

export default Stacking;
36 changes: 36 additions & 0 deletions src/app/screens/stacking/stackingProgress/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { useTranslation } from 'react-i18next';
import styled from 'styled-components';
import StackingStatusTile from './stackingStatusTile';

const Container = styled.div((props) => ({
display: 'flex',
flex: 1,
flexDirection: 'column',
margin: props.theme.spacing(8),
borderTop: `1px solid ${props.theme.colors.background.elevation3}`,
}));

const TitleText = styled.h1((props) => ({
...props.theme.headline_s,
marginTop: props.theme.spacing(16),
}));

const StackingDescriptionText = styled.h1((props) => ({
...props.theme.body_m,
marginTop: props.theme.spacing(4),
marginBottom: props.theme.spacing(18),
color: props.theme.colors.white['200'],
}));
function StackingProgress() {
const { t } = useTranslation('translation', { keyPrefix: 'STACKING_SCREEN' });

return (
<Container>
<TitleText>{t('STACK_FOR_REWARD')}</TitleText>
<StackingDescriptionText>{t('XVERSE_POOL')}</StackingDescriptionText>
<StackingStatusTile />
</Container>
);
}

export default StackingProgress;
106 changes: 106 additions & 0 deletions src/app/screens/stacking/stackingProgress/stackingStatusTile.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import styled from 'styled-components';
import TokenTicker from '@assets/img/stacking/token_ticker.svg';
import { useTranslation } from 'react-i18next';
import useStackingData from '@hooks/useStackingData';
import { StackingState } from '@secretkeylabs/xverse-core/stacking';
import { useEffect, useState } from 'react';
import { XVERSE_WEB_POOL_URL } from '@utils/constants';

const Container = styled.button((props) => ({
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
background: props.theme.colors.background.elevation1,
borderRadius: props.theme.radius(2),
padding: props.theme.spacing(9),
}));

const TextContainer = styled.div({
display: 'flex',
flexDirection: 'row',
flex: 1,
});

const StatusContainer = styled.div((props) => ({
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
background: 'rgba(81, 214, 166, 0.15)',
borderRadius: props.theme.radius(7),
paddingLeft: props.theme.spacing(6),
paddingRight: props.theme.spacing(6),
paddingTop: props.theme.spacing(2),
paddingBottom: props.theme.spacing(2),
}));

const Dot = styled.div((props) => ({
width: 7,
height: 7,
borderRadius: props.theme.radius(9),
marginRight: props.theme.spacing(4),
background: props.theme.colors.feedback.success,
}));

const ColumnContainer = styled.div((props) => ({
display: 'flex',
flexDirection: 'column',
alignItems: 'flex-start',
marginLeft: props.theme.spacing(6),
}));

const BoldText = styled.h1((props) => ({
...props.theme.body_bold_m,
color: props.theme.colors.white['0'],
}));

const SubText = styled.h1((props) => ({
...props.theme.body_xs,
color: props.theme.colors.white['400'],
}));

const StatusText = styled.h1((props) => ({
...props.theme.body_xs,
fontWeight: 500,
color: props.theme.colors.white['0'],
}));

function StackingStatusTile() {
const { t } = useTranslation('translation', { keyPrefix: 'STACKING_SCREEN' });
const { stackingData } = useStackingData();
const [status, setStatus] = useState<StackingState>('Pending');

useEffect(() => {
if (stackingData) {
if (!stackingData?.stackerInfo?.stacked && stackingData?.delegationInfo?.delegated) {
setStatus('Delegated');
} else if (stackingData?.stackerInfo?.stacked) { setStatus('Stacking'); }
}
}, [stackingData]);

const handleOnClick = () => {
window.open(XVERSE_WEB_POOL_URL);
};

return (
<Container onClick={handleOnClick}>
<TextContainer>
<img src={TokenTicker} alt="Ticker" />
<ColumnContainer>
<BoldText>{t('STACK_STX')}</BoldText>
<SubText>{t('EARN_BTC')}</SubText>
</ColumnContainer>
</TextContainer>

<StatusContainer>
<Dot />
<StatusText>
{status === 'Stacking' ? t('IN_PROGRESS') : t('DELEGATED')}
</StatusText>
</StatusContainer>
</Container>
);
}

export default StackingStatusTile;
Loading

0 comments on commit a715a73

Please sign in to comment.