Skip to content

Commit

Permalink
Add timer after stake 5s and allow claim always with redirect to HUB
Browse files Browse the repository at this point in the history
  • Loading branch information
martincik committed Sep 11, 2024
1 parent 5aaed9a commit 28e78e5
Show file tree
Hide file tree
Showing 3 changed files with 218 additions and 147 deletions.
58 changes: 34 additions & 24 deletions src/components/ProgressModal.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { Fragment, h } from 'preact';

import { RouteLink } from '../layout/Router';

import { useContext } from 'preact/hooks';
import { ConfigContext } from '../AppContext';
import { clsxp } from '../libs/utils';
import Loading from './Loading';
import { Fragment, h } from "preact";
import { RouteLink } from "../layout/Router";
import { useContext, useEffect, useState } from "preact/hooks";
import { ConfigContext } from "../AppContext";
import { clsxp } from "../libs/utils";
import Loading from "./Loading";

const ProgressModal = ({
working,
Expand All @@ -15,35 +13,47 @@ const ProgressModal = ({
doneStepName: string;
}) => {
const { classPrefix } = useContext(ConfigContext);
const [countdown, setCountdown] = useState(5);

useEffect(() => {
if (working === doneStepName && countdown > 0) {
const timer = setTimeout(() => setCountdown(countdown - 1), 1000);
return () => clearTimeout(timer);
}
return () => {};
}, [working, doneStepName, countdown]);

const isButtonDisabled = working !== doneStepName || countdown > 0;

return (
<Fragment>
<div className={clsxp(classPrefix, 'process_modal_title')}>
<div className={clsxp(classPrefix, "process_modal_title")}>
Sign a transaction
</div>
<div className={clsxp(classPrefix, 'process_modal_subtitle')}>
{ working === doneStepName ?
'Transaction sent successfully.' :
'We need you to sign a transaction to lock your funds.' }
<div className={clsxp(classPrefix, "process_modal_subtitle")}>
{working === doneStepName
? "Transaction sent successfully."
: "We need you to sign a transaction to lock your funds."}
</div>
<nav
className={clsxp(classPrefix, 'process_modal_steps')}
aria-label='Progress'
className={clsxp(classPrefix, "process_modal_steps")}
aria-label="Progress"
>
<div className={clsxp(classPrefix, 'process_modal_steps_load')}>
{ working !== doneStepName && <Loading />}
<div className={clsxp(classPrefix, "process_modal_steps_load")}>
{working !== doneStepName && <Loading />}
</div>
<RouteLink
disabled={working !== doneStepName}
href='/'
disabled={isButtonDisabled}
href="/"
className={clsxp(
classPrefix,
'process_modal_button',
working !== doneStepName
? 'process_modal_button_disabled'
: 'process_modal_button_selected'
"process_modal_button",
isButtonDisabled
? "process_modal_button_disabled"
: "process_modal_button_selected"
)}
>
Close
{isButtonDisabled && countdown > 0 ? `Close (${countdown})` : "Close"}
</RouteLink>
</nav>
</Fragment>
Expand Down
189 changes: 112 additions & 77 deletions src/routes/Actions.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,34 @@
import { h } from 'preact';
import { useCallback, useContext, useEffect, useMemo, useState, } from 'preact/hooks';
import { PublicKey } from '@solana/web3.js';
import BN from 'bn.js';
import { h } from "preact";
import {
useCallback,
useContext,
useEffect,
useMemo,
useState,
} from "preact/hooks";
import { PublicKey } from "@solana/web3.js";
import BN from "bn.js";

import { calculateRewardForStaker, getBondAccounts, getStakeAccounts, getUserACSBalance, } from '../libs/program';
import { ConfigContext } from '../AppContext';
import { BondAccount, BondV2Account, getBondV2Accounts, StakeAccount, StakePool } from '@accessprotocol/js';
import { clsxp, formatPenyACSCurrency } from '../libs/utils';
import { RouteLink } from '../layout/Router';
import { Header } from '../components/Header';
import { useWallet } from '../components/wallet-adapter/useWallet';
import { useConnection } from '../components/wallet-adapter/useConnection';
import env from '../libs/env';
import {
calculateRewardForStaker,
getBondAccounts,
getStakeAccounts,
getUserACSBalance,
} from "../libs/program";
import { ConfigContext } from "../AppContext";
import {
BondAccount,
BondV2Account,
getBondV2Accounts,
StakeAccount,
StakePool,
} from "@accessprotocol/js";
import { clsxp, formatPenyACSCurrency } from "../libs/utils";
import { RouteLink } from "../layout/Router";
import { Header } from "../components/Header";
import { useWallet } from "../components/wallet-adapter/useWallet";
import { useConnection } from "../components/wallet-adapter/useConnection";
import env from "../libs/env";

export const Actions = () => {
const { poolId, classPrefix } = useContext(ConfigContext);
Expand Down Expand Up @@ -83,8 +100,13 @@ export const Actions = () => {
env.PROGRAM_ID
);
setBondAccounts(
bAccounts.map((bAccount: any) => BondAccount.deserialize(bAccount.account.data))
.filter((bAccount: BondAccount) => bAccount.stakePool.toBase58() === poolId)
bAccounts
.map((bAccount: any) =>
BondAccount.deserialize(bAccount.account.data)
)
.filter(
(bAccount: BondAccount) => bAccount.stakePool.toBase58() === poolId
)
);
})();
}, [publicKey, connection, poolId]);
Expand All @@ -101,8 +123,13 @@ export const Actions = () => {
);

setBondV2Accounts(
bV2Accounts.map((bAccount: any) => BondV2Account.deserialize(bAccount.account.data))
.filter((bAccount: BondV2Account) => bAccount.pool.toBase58() === poolId)
bV2Accounts
.map((bAccount: any) =>
BondV2Account.deserialize(bAccount.account.data)
)
.filter(
(bAccount: BondV2Account) => bAccount.pool.toBase58() === poolId
)
);
})();
}, [publicKey, connection, poolId]);
Expand All @@ -123,36 +150,48 @@ export const Actions = () => {
return null;
}

return bondAccounts.reduce((acc, ba) =>
acc + calculateRewardForStaker(
stakePool.currentDayIdx - ba.lastClaimedOffset.toNumber(),
stakePool,
ba.totalStaked as BN
), 0);
return bondAccounts.reduce(
(acc, ba) =>
acc +
calculateRewardForStaker(
stakePool.currentDayIdx - ba.lastClaimedOffset.toNumber(),
stakePool,
ba.totalStaked as BN
),
0
);
}, [bondAccounts, stakePool]);

const claimableBondV2Amount = useMemo(() => {
if (bondV2Accounts.length === 0 || !stakePool) {
return null;
}

return bondV2Accounts.reduce((acc, ba) =>
acc + calculateRewardForStaker(
stakePool.currentDayIdx - ba.lastClaimedOffset.toNumber(),
stakePool,
ba.amount as BN
), 0);
return bondV2Accounts.reduce(
(acc, ba) =>
acc +
calculateRewardForStaker(
stakePool.currentDayIdx - ba.lastClaimedOffset.toNumber(),
stakePool,
ba.amount as BN
),
0
);
}, [bondV2Accounts, stakePool]);

const claimableAmount = useMemo(() => {
return (claimableBondAmount ?? 0) + (claimableStakeAmount ?? 0) + (claimableBondV2Amount ?? 0);
return (
(claimableBondAmount ?? 0) +
(claimableStakeAmount ?? 0) +
(claimableBondV2Amount ?? 0)
);
}, [claimableBondAmount, claimableStakeAmount, claimableBondV2Amount]);

const disconnectHandler = useCallback(async () => {
try {
await disconnect();
} catch (error) {
console.error('Failed to disconnect:', error);
console.error("Failed to disconnect:", error);
}
}, [disconnect]);

Expand All @@ -178,36 +217,36 @@ export const Actions = () => {
}, [stakePool, bondV2Accounts]);

return (
<div className={clsxp(classPrefix, 'actions_root')}>
<div className={clsxp(classPrefix, "actions_root")}>
{connected && disconnecting && (
<Header>
<div className={clsxp(classPrefix, 'actions_actions_disconnect')}>
<div className={clsxp(classPrefix, "actions_actions_disconnect")}>
Disconnecting...
</div>
</Header>
)}
{connected && !disconnecting && (
<Header>
<div
className={clsxp(classPrefix, 'actions_actions_disconnect')}
className={clsxp(classPrefix, "actions_actions_disconnect")}
onClick={disconnectHandler}
>
Disconnect
</div>
</Header>
)}

<div className={clsxp(classPrefix, 'actions_logo')}>
<div className={clsxp(classPrefix, "actions_logo")}>
<svg
width='48'
height='48'
viewBox='0 0 48 48'
fill='white'
xmlns='http://www.w3.org/2000/svg'
width="48"
height="48"
viewBox="0 0 48 48"
fill="white"
xmlns="http://www.w3.org/2000/svg"
>
<path
d='M22.8221 47.17C30.5621 47.17 37.1321 43.48 40.1021 36.28V46H47.9321V24.13C47.9321 9.91 38.2121 0.369997 24.2621 0.369997C10.1321 0.369997 0.23207 10.18 0.23207 24.13C0.23207 38.8 11.2121 47.17 22.8221 47.17ZM24.1721 39.25C14.9921 39.25 8.87207 32.77 8.87207 23.77C8.87207 14.77 14.9921 8.29 24.1721 8.29C33.3521 8.29 39.4721 14.77 39.4721 23.77C39.4721 32.77 33.3521 39.25 24.1721 39.25Z'
fill='#E7E5E4'
d="M22.8221 47.17C30.5621 47.17 37.1321 43.48 40.1021 36.28V46H47.9321V24.13C47.9321 9.91 38.2121 0.369997 24.2621 0.369997C10.1321 0.369997 0.23207 10.18 0.23207 24.13C0.23207 38.8 11.2121 47.17 22.8221 47.17ZM24.1721 39.25C14.9921 39.25 8.87207 32.77 8.87207 23.77C8.87207 14.77 14.9921 8.29 24.1721 8.29C33.3521 8.29 39.4721 14.77 39.4721 23.77C39.4721 32.77 33.3521 39.25 24.1721 39.25Z"
fill="#E7E5E4"
/>
</svg>
</div>
Expand All @@ -216,84 +255,80 @@ export const Actions = () => {
<div
className={clsxp(
classPrefix,
'actions_staked_amount',
"actions_staked_amount",
(stakedAccount === undefined || bondAccounts === undefined) &&
'actions_blink'
"actions_blink"
)}
>
<div>
{formatPenyACSCurrency(
(stakedAccount?.stakeAmount.toNumber() ?? 0) +
(bondAccounts?.reduce((acc, ba) => acc + ba.totalStaked.toNumber(), 0) ?? 0) +
(bondV2Accounts?.reduce((acc, ba) => acc + ba.amount.toNumber(), 0) ?? 0)
)}{' '}
(bondAccounts?.reduce(
(acc, ba) => acc + ba.totalStaked.toNumber(),
0
) ?? 0) +
(bondV2Accounts?.reduce(
(acc, ba) => acc + ba.amount.toNumber(),
0
) ?? 0)
)}{" "}
ACS locked
</div>
</div>
<div
className={clsxp(
classPrefix,
'actions_balance',
balance === undefined && 'actions_blink'
"actions_balance",
balance === undefined && "actions_blink"
)}
>
{formatPenyACSCurrency(balance?.toNumber() ?? 0)} ACS available
</div>
<div
className={clsxp(
classPrefix,
'actions_balance',
"actions_balance",
(stakedAccount === undefined || bondAccounts === undefined) &&
'actions_blink'
"actions_blink"
)}
>
{formatPenyACSCurrency(claimableAmount ?? 0)} ACS rewards
</div>
</div>

<div className={clsxp(classPrefix, 'actions_links_wrapper')}>
<div className={clsxp(classPrefix, "actions_links_wrapper")}>
<RouteLink
className={clsxp(classPrefix, 'actions_button')}
href='/stake'
className={clsxp(classPrefix, "actions_button")}
href="/stake"
>
Lock
</RouteLink>
{(stakedAccount && stakedAccount.stakeAmount.toNumber() > 0) || hasUnlockableBonds || hasUnlockableBondsV2 ? (
{(stakedAccount && stakedAccount.stakeAmount.toNumber() > 0) ||
hasUnlockableBonds ||
hasUnlockableBondsV2 ? (
<RouteLink
className={clsxp(classPrefix, 'actions_button')}
href='/unstake'
className={clsxp(classPrefix, "actions_button")}
href="/unstake"
>
Unlock ACS
</RouteLink>
) : (
<span
className={clsxp(
classPrefix,
'actions_button',
'actions_button_disabled'
"actions_button",
"actions_button_disabled"
)}
>
Unlock ACS
</span>
)}
{claimableAmount && claimableAmount > 0 ? (
<RouteLink
className={clsxp(classPrefix, 'actions_button')}
href='/claim'
>
Claim
</RouteLink>
) : (
<span
className={clsxp(
classPrefix,
'actions_button',
'actions_button_disabled'
)}
>
Claim rewards
</span>
)}
<RouteLink
className={clsxp(classPrefix, "actions_button")}
href="/claim"
>
Claim
</RouteLink>
</div>
</div>
);
Expand Down
Loading

0 comments on commit 28e78e5

Please sign in to comment.