Skip to content

Commit 1fa8884

Browse files
authored
Merge pull request #1873 from cprussin/staking-app-refinements
feat(staking): style refinements
2 parents e3d8bfe + b28b7a3 commit 1fa8884

File tree

35 files changed

+1084
-612
lines changed

35 files changed

+1084
-612
lines changed

apps/staking/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,12 @@
3434
"@solana/wallet-adapter-wallets": "0.19.10",
3535
"@solana/web3.js": "^1.95.2",
3636
"clsx": "^2.1.1",
37+
"dnum": "^2.13.1",
3738
"next": "^14.2.5",
3839
"pino": "^9.3.2",
3940
"react": "^18.3.1",
4041
"react-aria": "^3.34.3",
42+
"react-aria-components": "^1.3.3",
4143
"react-dom": "^18.3.1",
4244
"recharts": "^2.12.7",
4345
"swr": "^2.2.5",
@@ -61,6 +63,8 @@
6163
"postcss": "^8.4.40",
6264
"prettier": "^3.3.2",
6365
"tailwindcss": "^3.4.7",
66+
"tailwindcss-animate": "^1.0.7",
67+
"tailwindcss-react-aria-components": "^1.1.5",
6468
"typescript": "^5.5.4",
6569
"vercel": "^35.2.2"
6670
}

apps/staking/src/api.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ export type StakeDetails = ReturnType<
8383
>;
8484

8585
export enum AccountHistoryItemType {
86-
Deposit,
86+
AddTokens,
8787
LockedDeposit,
8888
Withdrawal,
8989
RewardsCredited,
@@ -97,7 +97,7 @@ export enum AccountHistoryItemType {
9797
}
9898

9999
const AccountHistoryAction = {
100-
Deposit: () => ({ type: AccountHistoryItemType.Deposit as const }),
100+
AddTokens: () => ({ type: AccountHistoryItemType.AddTokens as const }),
101101
LockedDeposit: (unlockDate: Date) => ({
102102
type: AccountHistoryItemType.LockedDeposit as const,
103103
unlockDate,
@@ -506,7 +506,7 @@ const MOCK_DATA: Record<string, Data> = {
506506
const mkMockHistory = (): AccountHistory => [
507507
{
508508
timestamp: new Date("2024-06-10T00:00:00Z"),
509-
action: AccountHistoryAction.Deposit(),
509+
action: AccountHistoryAction.AddTokens(),
510510
amount: 2_000_000n,
511511
accountTotal: 2_000_000n,
512512
availableRewards: 0n,
Lines changed: 21 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,26 @@
1-
import useSWR from "swr";
1+
import { ArrowPathIcon } from "@heroicons/react/24/outline";
22

33
import {
44
type AccountHistoryAction,
55
type StakeDetails,
66
AccountHistoryItemType,
77
StakeType,
8-
loadAccountHistory,
98
} from "../../api";
10-
import { useApiContext } from "../../hooks/use-api-context";
11-
import { LoadingSpinner } from "../LoadingSpinner";
9+
import { StateType, useAccountHistory } from "../../hooks/use-account-history";
1210
import { Tokens } from "../Tokens";
1311

14-
const ONE_SECOND_IN_MS = 1000;
15-
const ONE_MINUTE_IN_MS = 60 * ONE_SECOND_IN_MS;
16-
const REFRESH_INTERVAL = 1 * ONE_MINUTE_IN_MS;
17-
1812
export const AccountHistory = () => {
19-
const history = useAccountHistoryData();
13+
const history = useAccountHistory();
2014

2115
switch (history.type) {
22-
case DataStateType.NotLoaded:
23-
case DataStateType.Loading: {
24-
return <LoadingSpinner />;
16+
case StateType.NotLoaded:
17+
case StateType.Loading: {
18+
return <ArrowPathIcon className="size-6 animate-spin" />;
2519
}
26-
case DataStateType.Error: {
20+
case StateType.Error: {
2721
return <p>Uh oh, an error occured!</p>;
2822
}
29-
case DataStateType.Loaded: {
23+
case StateType.Loaded: {
3024
return (
3125
<table className="text-sm">
3226
<thead className="font-medium">
@@ -56,7 +50,9 @@ export const AccountHistory = () => {
5650
) => (
5751
<tr key={i}>
5852
<td className="pr-4">{timestamp.toLocaleString()}</td>
59-
<td className="pr-4">{mkDescription(action)}</td>
53+
<td className="pr-4">
54+
<Description>{action}</Description>
55+
</td>
6056
<td className="pr-4">
6157
<Tokens>{amount}</Tokens>
6258
</td>
@@ -82,37 +78,37 @@ export const AccountHistory = () => {
8278
}
8379
};
8480

85-
const mkDescription = (action: AccountHistoryAction): string => {
86-
switch (action.type) {
81+
const Description = ({ children }: { children: AccountHistoryAction }) => {
82+
switch (children.type) {
8783
case AccountHistoryItemType.Claim: {
8884
return "Rewards claimed";
8985
}
90-
case AccountHistoryItemType.Deposit: {
91-
return "Tokens deposited";
86+
case AccountHistoryItemType.AddTokens: {
87+
return "Tokens added";
9288
}
9389
case AccountHistoryItemType.LockedDeposit: {
94-
return `Locked tokens deposited, unlocking ${action.unlockDate.toLocaleString()}`;
90+
return `Locked tokens deposited, unlocking ${children.unlockDate.toLocaleString()}`;
9591
}
9692
case AccountHistoryItemType.RewardsCredited: {
9793
return "Rewards credited";
9894
}
9995
case AccountHistoryItemType.Slash: {
100-
return `Staked tokens slashed from ${action.publisherName}`;
96+
return `Staked tokens slashed from ${children.publisherName}`;
10197
}
10298
case AccountHistoryItemType.StakeCreated: {
103-
return `Created stake position for ${getStakeDetails(action.details)}`;
99+
return `Created stake position for ${getStakeDetails(children.details)}`;
104100
}
105101
case AccountHistoryItemType.StakeFinishedWarmup: {
106-
return `Warmup complete for position for ${getStakeDetails(action.details)}`;
102+
return `Warmup complete for position for ${getStakeDetails(children.details)}`;
107103
}
108104
case AccountHistoryItemType.Unlock: {
109105
return "Locked tokens unlocked";
110106
}
111107
case AccountHistoryItemType.UnstakeCreated: {
112-
return `Requested unstake for position for ${getStakeDetails(action.details)}`;
108+
return `Requested unstake for position for ${getStakeDetails(children.details)}`;
113109
}
114110
case AccountHistoryItemType.UnstakeExitedCooldown: {
115-
return `Cooldown completed for ${getStakeDetails(action.details)}`;
111+
return `Cooldown completed for ${getStakeDetails(children.details)}`;
116112
}
117113
case AccountHistoryItemType.Withdrawal: {
118114
return "Tokens withdrawn to wallet";
@@ -130,46 +126,3 @@ const getStakeDetails = (details: StakeDetails): string => {
130126
}
131127
}
132128
};
133-
134-
const useAccountHistoryData = () => {
135-
const apiContext = useApiContext();
136-
137-
const { data, isLoading, ...rest } = useSWR(
138-
`${apiContext.stakeAccount.address.toBase58()}/history`,
139-
() => loadAccountHistory(apiContext),
140-
{
141-
refreshInterval: REFRESH_INTERVAL,
142-
},
143-
);
144-
const error = rest.error as unknown;
145-
146-
if (error) {
147-
return DataState.ErrorState(error);
148-
} else if (isLoading) {
149-
return DataState.Loading();
150-
} else if (data) {
151-
return DataState.Loaded(data);
152-
} else {
153-
return DataState.NotLoaded();
154-
}
155-
};
156-
157-
enum DataStateType {
158-
NotLoaded,
159-
Loading,
160-
Loaded,
161-
Error,
162-
}
163-
const DataState = {
164-
NotLoaded: () => ({ type: DataStateType.NotLoaded as const }),
165-
Loading: () => ({ type: DataStateType.Loading as const }),
166-
Loaded: (data: Awaited<ReturnType<typeof loadAccountHistory>>) => ({
167-
type: DataStateType.Loaded as const,
168-
data,
169-
}),
170-
ErrorState: (error: unknown) => ({
171-
type: DataStateType.Error as const,
172-
error,
173-
}),
174-
};
175-
type DataState = ReturnType<(typeof DataState)[keyof typeof DataState]>;

apps/staking/src/components/AccountSummary/index.tsx

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,16 @@ export const AccountSummary = ({
4747
<Image
4848
src={background}
4949
alt=""
50-
className="absolute -right-40 h-full object-right [mask-image:linear-gradient(to_right,_transparent,_black_50%)]"
50+
className="absolute -right-40 hidden h-full object-cover object-right [mask-image:linear-gradient(to_right,_transparent,_black_50%)] md:block"
5151
/>
52-
<div className="relative flex flex-col items-start justify-between gap-16 px-12 py-20 md:flex-row md:items-center">
52+
<div className="relative flex flex-col items-start justify-between gap-8 px-6 py-10 sm:gap-16 sm:px-12 sm:py-20 lg:flex-row lg:items-center">
5353
<div>
54-
<div className="mb-4 inline-block border border-neutral-600/50 bg-neutral-900 px-4 py-1 text-xs text-neutral-400">
54+
<div className="mb-2 inline-block border border-neutral-600/50 bg-neutral-900 px-4 py-1 text-xs text-neutral-400 sm:mb-4">
5555
Total Balance
5656
</div>
5757
<div className="flex flex-row items-center gap-8">
5858
<span>
59-
<Tokens className="text-6xl font-light">{total}</Tokens>
59+
<Tokens className="text-4xl font-light sm:text-6xl">{total}</Tokens>
6060
</span>
6161
{lastSlash && (
6262
<p className="max-w-48 text-sm text-red-600">
@@ -65,19 +65,11 @@ export const AccountSummary = ({
6565
</p>
6666
)}
6767
</div>
68-
<div className="mt-8 flex flex-row items-center gap-4">
69-
<TransferButton
70-
actionDescription="Add funds to your balance"
71-
actionName="Deposit"
72-
max={walletAmount}
73-
transfer={deposit}
74-
/>
75-
</div>
7668
{locked > 0n && (
7769
<>
78-
<div className="mt-6 flex flex-row items-center gap-1 text-xl text-pythpurple-100/50">
70+
<div className="mt-3 flex flex-row items-center gap-1 text-pythpurple-100/50 sm:mt-6 sm:text-xl">
7971
<Tokens>{locked}</Tokens>
80-
<div>locked</div>
72+
<div>locked included</div>
8173
</div>
8274
<Modal>
8375
<ModalButton
@@ -90,7 +82,7 @@ export const AccountSummary = ({
9082
title="Unlock Schedule"
9183
description="Your tokens will become available for withdrawal and for participation in Integrity Staking according to this schedule"
9284
>
93-
<div className="border border-neutral-600/50 bg-pythpurple-100/10 px-8 py-6">
85+
<div className="border border-neutral-600/50 bg-pythpurple-100/10 p-4 sm:px-8 sm:py-6">
9486
<table>
9587
<thead className="font-medium">
9688
<tr>
@@ -101,7 +93,7 @@ export const AccountSummary = ({
10193
<tbody>
10294
{unlockSchedule.map((unlock, i) => (
10395
<tr key={i}>
104-
<td className="pr-12 text-sm opacity-80">
96+
<td className="pr-12 text-xs opacity-80 sm:text-sm">
10597
{unlock.date.toLocaleString()}
10698
</td>
10799
<td>
@@ -116,12 +108,20 @@ export const AccountSummary = ({
116108
</Modal>
117109
</>
118110
)}
111+
<div className="mt-3 flex flex-row items-center gap-4 sm:mt-8">
112+
<TransferButton
113+
actionDescription="Add funds to your balance"
114+
actionName="Add Tokens"
115+
max={walletAmount}
116+
transfer={deposit}
117+
/>
118+
</div>
119119
</div>
120-
<div className="flex flex-col items-stretch gap-4 xl:flex-row">
120+
<div className="flex w-full flex-col items-stretch gap-4 lg:w-auto xl:flex-row">
121121
<BalanceCategory
122-
name="Available for Withdrawal"
122+
name="Unlocked & Unstaked"
123123
amount={availableToWithdraw}
124-
description="The lesser of the amount you have available to stake in governance & integrity staking"
124+
description="The amount of unlocked tokens that are not staked in either program"
125125
action={
126126
<TransferButton
127127
small
@@ -137,7 +137,7 @@ export const AccountSummary = ({
137137
<BalanceCategory
138138
name="Available Rewards"
139139
amount={availableRewards}
140-
description="Rewards you have earned but not yet claimed from the Integrity Staking program"
140+
description="Rewards you have earned from OIS"
141141
action={<ClaimButton disabled={availableRewards === 0n} />}
142142
{...(expiringRewards !== undefined &&
143143
expiringRewards.amount > 0n && {
@@ -169,7 +169,7 @@ const BalanceCategory = ({
169169
action,
170170
warning,
171171
}: BalanceCategoryProps) => (
172-
<div className="flex flex-col justify-between border border-neutral-600/50 bg-pythpurple-800/60 p-6 backdrop-blur">
172+
<div className="flex w-full flex-col justify-between border border-neutral-600/50 bg-pythpurple-800/60 p-6 backdrop-blur lg:w-96">
173173
<div>
174174
<div className="mb-4 inline-block border border-neutral-600/50 bg-neutral-900 px-4 py-1 text-xs text-neutral-400">
175175
{name}

apps/staking/src/components/Amplitude/index.tsx

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,13 @@
11
"use client";
22

3-
import * as amplitude from "@amplitude/analytics-browser";
4-
import { autocapturePlugin } from "@amplitude/plugin-autocapture-browser";
5-
import { useEffect, useRef } from "react";
3+
import { useAmplitude } from "../../hooks/use-amplitude";
64

75
type Props = {
86
apiKey: string | undefined;
97
};
108

119
export const Amplitude = ({ apiKey }: Props) => {
12-
const amplitudeInitialized = useRef(false);
13-
14-
useEffect(() => {
15-
if (!amplitudeInitialized.current && apiKey) {
16-
amplitude.add(autocapturePlugin());
17-
amplitude.init(apiKey, {
18-
defaultTracking: true,
19-
});
20-
amplitudeInitialized.current = true;
21-
}
22-
}, [apiKey]);
10+
useAmplitude(apiKey);
2311

2412
// eslint-disable-next-line unicorn/no-null
2513
return null;

apps/staking/src/components/Button/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,5 @@ const ButtonBase = ({
2929

3030
export const Button = Styled(
3131
ButtonBase,
32-
"border border-pythpurple-600 bg-pythpurple-600/50 data-[small]:text-sm data-[small]:px-6 data-[small]:py-1 data-[secondary]:bg-pythpurple-600/20 px-8 py-2 data-[nopad]:px-0 data-[nopad]:py-0 disabled:cursor-not-allowed disabled:bg-neutral-50/10 disabled:border-neutral-50/10 disabled:text-white/60 disabled:data-[loading]:cursor-wait hover:bg-pythpurple-600/60 data-[secondary]:hover:bg-pythpurple-600/60 data-[secondary]:disabled:bg-neutral-50/10 focus-visible:ring-1 focus-visible:ring-pythpurple-400 focus:outline-none justify-center",
32+
"border border-pythpurple-600 bg-pythpurple-600/50 data-[small]:text-sm data-[small]:px-6 data-[small]:py-1 data-[secondary]:bg-pythpurple-600/20 px-2 sm:px-4 md:px-8 py-2 data-[nopad]:px-0 data-[nopad]:py-0 disabled:cursor-not-allowed disabled:bg-neutral-50/10 disabled:border-neutral-50/10 disabled:text-white/60 disabled:data-[loading]:cursor-wait hover:bg-pythpurple-600/60 data-[secondary]:hover:bg-pythpurple-600/60 data-[secondary]:disabled:bg-neutral-50/10 focus-visible:ring-1 focus-visible:ring-pythpurple-400 focus:outline-none",
3333
);

apps/staking/src/components/Dashboard/index.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,15 @@ export const Dashboard = ({
118118
expiringRewards={expiringRewards}
119119
/>
120120
<TabGroup as="section">
121-
<TabList className="flex w-full flex-row font-medium">
121+
<TabList className="flex w-full flex-row text-sm font-medium sm:text-base">
122122
<DashboardTab>Overview</DashboardTab>
123123
<DashboardTab>Governance</DashboardTab>
124-
<DashboardTab>Oracle Integrity Staking</DashboardTab>
124+
<DashboardTab>
125+
<span className="sm:hidden">Integrity Staking</span>
126+
<span className="hidden sm:inline">
127+
Oracle Integrity Staking (OIS)
128+
</span>
129+
</DashboardTab>
125130
</TabList>
126131
<TabPanels className="mt-8">
127132
<DashboardTabPanel>
@@ -159,7 +164,7 @@ export const Dashboard = ({
159164

160165
const DashboardTab = Styled(
161166
Tab,
162-
"grow border-b border-neutral-600/50 px-4 py-2 focus-visible:outline-none data-[selected]:cursor-default data-[selected]:border-pythpurple-400 data-[selected]:data-[hover]:bg-transparent data-[hover]:text-pythpurple-400 data-[selected]:text-pythpurple-400 data-[focus]:outline-none data-[focus]:ring-1 data-[focus]:ring-pythpurple-400",
167+
"grow basis-0 border-b border-neutral-600/50 px-4 py-2 focus-visible:outline-none data-[selected]:cursor-default data-[selected]:border-pythpurple-400 data-[selected]:data-[hover]:bg-transparent data-[hover]:text-pythpurple-400 data-[selected]:text-pythpurple-400 data-[focus]:outline-none data-[focus]:ring-1 data-[focus]:ring-pythpurple-400",
163168
);
164169

165170
const DashboardTabPanel = Styled(

0 commit comments

Comments
 (0)