| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- import useSWR from "swr";
- import {
- type AccountHistoryAction,
- type StakeDetails,
- AccountHistoryItemType,
- StakeType,
- loadAccountHistory,
- } from "../../api";
- import { useApiContext } from "../../use-api-context";
- import { LoadingSpinner } from "../LoadingSpinner";
- import { ModalButton } from "../ModalButton";
- import { Tokens } from "../Tokens";
- const ONE_SECOND_IN_MS = 1000;
- const ONE_MINUTE_IN_MS = 60 * ONE_SECOND_IN_MS;
- const REFRESH_INTERVAL = 1 * ONE_MINUTE_IN_MS;
- export const AccountHistoryButton = () => (
- <ModalButton
- title="Account history"
- description="A history of events that have affected your account balances"
- >
- <ModalBody />
- </ModalButton>
- );
- const ModalBody = () => {
- const history = useAccountHistoryData();
- switch (history.type) {
- case DataStateType.NotLoaded:
- case DataStateType.Loading: {
- return <LoadingSpinner />;
- }
- case DataStateType.Error: {
- return <p>Uh oh, an error occured!</p>;
- }
- case DataStateType.Loaded: {
- return (
- <table className="text-sm">
- <thead className="font-medium">
- <tr>
- <td className="pr-4">Timestamp</td>
- <td className="pr-4">Description</td>
- <td className="pr-4">Amount</td>
- <td className="pr-4">Account Total</td>
- <td className="pr-4">Available Rewards</td>
- <td className="pr-4">Available to Withdraw</td>
- <td>Locked</td>
- </tr>
- </thead>
- <tbody>
- {history.data.map(
- (
- {
- accountTotal,
- action,
- amount,
- availableRewards,
- availableToWithdraw,
- locked,
- timestamp,
- },
- i,
- ) => (
- <tr key={i}>
- <td className="pr-4">{timestamp.toLocaleString()}</td>
- <td className="pr-4">{mkDescription(action)}</td>
- <td className="pr-4">
- <Tokens>{amount}</Tokens>
- </td>
- <td className="pr-4">
- <Tokens>{accountTotal}</Tokens>
- </td>
- <td className="pr-4">
- <Tokens>{availableRewards}</Tokens>
- </td>
- <td className="pr-4">
- <Tokens>{availableToWithdraw}</Tokens>
- </td>
- <td>
- <Tokens>{locked}</Tokens>
- </td>
- </tr>
- ),
- )}
- </tbody>
- </table>
- );
- }
- }
- };
- const mkDescription = (action: AccountHistoryAction): string => {
- switch (action.type) {
- case AccountHistoryItemType.Claim: {
- return "Rewards claimed";
- }
- case AccountHistoryItemType.Deposit: {
- return "Tokens deposited";
- }
- case AccountHistoryItemType.LockedDeposit: {
- return `Locked tokens deposited, unlocking ${action.unlockDate.toLocaleString()}`;
- }
- case AccountHistoryItemType.RewardsCredited: {
- return "Rewards credited";
- }
- case AccountHistoryItemType.Slash: {
- return `Staked tokens slashed from ${action.publisherName}`;
- }
- case AccountHistoryItemType.StakeCreated: {
- return `Created stake position for ${getStakeDetails(action.details)}`;
- }
- case AccountHistoryItemType.StakeFinishedWarmup: {
- return `Warmup complete for position for ${getStakeDetails(action.details)}`;
- }
- case AccountHistoryItemType.Unlock: {
- return "Locked tokens unlocked";
- }
- case AccountHistoryItemType.UnstakeCreated: {
- return `Requested unstake for position for ${getStakeDetails(action.details)}`;
- }
- case AccountHistoryItemType.UnstakeExitedCooldown: {
- return `Cooldown completed for ${getStakeDetails(action.details)}`;
- }
- case AccountHistoryItemType.Withdrawal: {
- return "Tokens withdrawn to wallet";
- }
- }
- };
- const getStakeDetails = (details: StakeDetails): string => {
- switch (details.type) {
- case StakeType.Governance: {
- return "Governance Staking";
- }
- case StakeType.IntegrityStaking: {
- return `Integrity Staking, publisher: ${details.publisherName}`;
- }
- }
- };
- const useAccountHistoryData = () => {
- const apiContext = useApiContext();
- const { data, isLoading, ...rest } = useSWR(
- `${apiContext.stakeAccount.publicKey}/history`,
- () => loadAccountHistory(apiContext),
- {
- refreshInterval: REFRESH_INTERVAL,
- },
- );
- const error = rest.error as unknown;
- if (error) {
- return DataState.ErrorState(error);
- } else if (isLoading) {
- return DataState.Loading();
- } else if (data) {
- return DataState.Loaded(data);
- } else {
- return DataState.NotLoaded();
- }
- };
- enum DataStateType {
- NotLoaded,
- Loading,
- Loaded,
- Error,
- }
- const DataState = {
- NotLoaded: () => ({ type: DataStateType.NotLoaded as const }),
- Loading: () => ({ type: DataStateType.Loading as const }),
- Loaded: (data: Awaited<ReturnType<typeof loadAccountHistory>>) => ({
- type: DataStateType.Loaded as const,
- data,
- }),
- ErrorState: (error: unknown) => ({
- type: DataStateType.Error as const,
- error,
- }),
- };
- type DataState = ReturnType<(typeof DataState)[keyof typeof DataState]>;
|