Skip to content

Commit 3f9bd3e

Browse files
committed
fix(staking): localize numbers & dates the best English variant
1 parent 751757b commit 3f9bd3e

File tree

14 files changed

+476
-730
lines changed

14 files changed

+476
-730
lines changed

apps/staking/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
"@solana/wallet-adapter-react-ui": "^0.9.27",
3535
"@solana/wallet-adapter-wallets": "0.19.10",
3636
"@solana/web3.js": "^1.95.2",
37+
"bcp-47": "^2.1.0",
3738
"clsx": "^2.1.1",
3839
"dnum": "^2.13.1",
3940
"framer-motion": "^11.3.8",

apps/staking/src/api.ts

Lines changed: 0 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
// TODO remove these disables when moving off the mock APIs
2-
/* eslint-disable @typescript-eslint/no-unused-vars */
3-
41
import type { HermesClient, PublisherCaps } from "@pythnetwork/hermes-client";
52
import {
63
epochToDate,
@@ -86,68 +83,6 @@ export type StakeDetails = ReturnType<
8683
(typeof StakeDetails)[keyof typeof StakeDetails]
8784
>;
8885

89-
export enum AccountHistoryItemType {
90-
AddTokens,
91-
LockedDeposit,
92-
Withdrawal,
93-
RewardsCredited,
94-
Claim,
95-
Slash,
96-
Unlock,
97-
StakeCreated,
98-
StakeFinishedWarmup,
99-
UnstakeCreated,
100-
UnstakeExitedCooldown,
101-
}
102-
103-
const AccountHistoryAction = {
104-
AddTokens: () => ({ type: AccountHistoryItemType.AddTokens as const }),
105-
LockedDeposit: (unlockDate: Date) => ({
106-
type: AccountHistoryItemType.LockedDeposit as const,
107-
unlockDate,
108-
}),
109-
Withdrawal: () => ({ type: AccountHistoryItemType.Withdrawal as const }),
110-
RewardsCredited: () => ({
111-
type: AccountHistoryItemType.RewardsCredited as const,
112-
}),
113-
Claim: () => ({ type: AccountHistoryItemType.Claim as const }),
114-
Slash: (publisherName: string) => ({
115-
type: AccountHistoryItemType.Slash as const,
116-
publisherName,
117-
}),
118-
Unlock: () => ({ type: AccountHistoryItemType.Unlock as const }),
119-
StakeCreated: (details: StakeDetails) => ({
120-
type: AccountHistoryItemType.StakeCreated as const,
121-
details,
122-
}),
123-
StakeFinishedWarmup: (details: StakeDetails) => ({
124-
type: AccountHistoryItemType.StakeFinishedWarmup as const,
125-
details,
126-
}),
127-
UnstakeCreated: (details: StakeDetails) => ({
128-
type: AccountHistoryItemType.UnstakeCreated as const,
129-
details,
130-
}),
131-
UnstakeExitedCooldown: (details: StakeDetails) => ({
132-
type: AccountHistoryItemType.UnstakeExitedCooldown as const,
133-
details,
134-
}),
135-
};
136-
137-
export type AccountHistoryAction = ReturnType<
138-
(typeof AccountHistoryAction)[keyof typeof AccountHistoryAction]
139-
>;
140-
141-
export type AccountHistory = {
142-
timestamp: Date;
143-
action: AccountHistoryAction;
144-
amount: bigint;
145-
accountTotal: bigint;
146-
availableToWithdraw: bigint;
147-
availableRewards: bigint;
148-
locked: bigint;
149-
}[];
150-
15186
export const getAllStakeAccountAddresses = async (
15287
client: PythStakingClient,
15388
): Promise<PublicKey[]> => client.getAllStakeAccountPositions();
@@ -325,14 +260,6 @@ const getPublisherCap = (publisherCaps: PublisherCaps, publisher: PublicKey) =>
325260
)?.cap ?? 0,
326261
);
327262

328-
export const loadAccountHistory = async (
329-
_client: PythStakingClient,
330-
_stakeAccount: PublicKey,
331-
): Promise<AccountHistory> => {
332-
await new Promise((resolve) => setTimeout(resolve, MOCK_DELAY));
333-
return mkMockHistory();
334-
};
335-
336263
export const createStakeAccountAndDeposit = async (
337264
client: PythStakingClient,
338265
amount: bigint,
@@ -462,44 +389,3 @@ export const optPublisherOut = async (
462389
): Promise<void> => {
463390
await client.removePublisherStakeAccount(stakeAccount, publisherKey);
464391
};
465-
466-
const MOCK_DELAY = 500;
467-
468-
const mkMockHistory = (): AccountHistory => [
469-
{
470-
timestamp: new Date("2024-06-10T00:00:00Z"),
471-
action: AccountHistoryAction.AddTokens(),
472-
amount: 2_000_000n,
473-
accountTotal: 2_000_000n,
474-
availableRewards: 0n,
475-
availableToWithdraw: 2_000_000n,
476-
locked: 0n,
477-
},
478-
{
479-
timestamp: new Date("2024-06-14T02:00:00Z"),
480-
action: AccountHistoryAction.RewardsCredited(),
481-
amount: 200n,
482-
accountTotal: 2_000_000n,
483-
availableRewards: 200n,
484-
availableToWithdraw: 2_000_000n,
485-
locked: 0n,
486-
},
487-
{
488-
timestamp: new Date("2024-06-16T08:00:00Z"),
489-
action: AccountHistoryAction.Claim(),
490-
amount: 200n,
491-
accountTotal: 2_000_200n,
492-
availableRewards: 0n,
493-
availableToWithdraw: 2_000_200n,
494-
locked: 0n,
495-
},
496-
{
497-
timestamp: new Date("2024-06-16T08:00:00Z"),
498-
action: AccountHistoryAction.Slash("Cboe"),
499-
amount: 1000n,
500-
accountTotal: 1_999_200n,
501-
availableRewards: 0n,
502-
availableToWithdraw: 1_999_200n,
503-
locked: 0n,
504-
},
505-
];

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

Lines changed: 0 additions & 137 deletions
This file was deleted.

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

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import background from "./background.png";
1717
import { type States, StateType as ApiStateType } from "../../hooks/use-api";
1818
import { StateType, useAsync } from "../../hooks/use-async";
1919
import { Button } from "../Button";
20+
import { Date } from "../Date";
2021
import { ModalDialog } from "../ModalDialog";
2122
import { Tokens } from "../Tokens";
2223
import { TransferButton } from "../TransferButton";
@@ -82,7 +83,7 @@ export const AccountSummary = ({
8283
{lastSlash && (
8384
<p className="max-w-48 text-sm text-red-600">
8485
<Tokens>{lastSlash.amount}</Tokens> were slashed on{" "}
85-
{lastSlash.date.toLocaleString()}
86+
<Date options="time">{lastSlash.date}</Date>
8687
</p>
8788
)}
8889
</div>
@@ -112,7 +113,7 @@ export const AccountSummary = ({
112113
{unlockSchedule.map((unlock, i) => (
113114
<tr key={i}>
114115
<td className="pr-12 text-xs opacity-80 sm:text-sm">
115-
{unlock.date.toLocaleString()}
116+
<Date options="time">{unlock.date}</Date>
116117
</td>
117118
<td>
118119
<Tokens>{unlock.amount}</Tokens>
@@ -238,7 +239,7 @@ export const AccountSummary = ({
238239
<>
239240
Rewards expire one year from the epoch in which they were
240241
earned. You have rewards expiring on{" "}
241-
{expiringRewards.toLocaleDateString()}.
242+
<Date>{expiringRewards}</Date>.
242243
</>
243244
),
244245
})}
@@ -311,13 +312,13 @@ const OisUnstake = ({
311312
{cooldown > 0n && (
312313
<div className="mt-2 text-xs text-neutral-500">
313314
<Tokens>{cooldown}</Tokens> end{" "}
314-
{epochToDate(currentEpoch + 2n).toLocaleString()}
315+
<Date options="time">{epochToDate(currentEpoch + 2n)}</Date>
315316
</div>
316317
)}
317318
{cooldown2 > 0n && (
318319
<div className="mt-2 text-xs text-neutral-500">
319320
<Tokens>{cooldown2}</Tokens> end{" "}
320-
{epochToDate(currentEpoch + 1n).toLocaleString()}
321+
<Date options="time">{epochToDate(currentEpoch + 1n)}</Date>
321322
</div>
322323
)}
323324
</>
@@ -439,7 +440,7 @@ const ClaimDialog = ({
439440
<div className="text-sm">
440441
Rewards expire one year from the epoch in which they were
441442
earned. You have rewards expiring on{" "}
442-
{expiringRewards.toLocaleDateString()}.
443+
<Date>{expiringRewards}</Date>.
443444
</div>
444445
</div>
445446
)}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { useMemo, type HTMLProps } from "react";
2+
import { useDateFormatter, type DateFormatterOptions } from "react-aria";
3+
4+
type Props = Omit<HTMLProps<HTMLSpanElement>, "children"> & {
5+
children: Date;
6+
options?: DateFormatterOptions | undefined | "time";
7+
};
8+
9+
export const Date = ({ children, options, ...props }: Props) => {
10+
const formatter = useDateFormatter(
11+
options === "time"
12+
? {
13+
year: "numeric",
14+
month: "numeric",
15+
day: "numeric",
16+
hour: "numeric",
17+
minute: "numeric",
18+
second: "numeric",
19+
}
20+
: options,
21+
);
22+
const value = useMemo(
23+
() => formatter.format(children),
24+
[formatter, children],
25+
);
26+
27+
return <span {...props}>{value}</span>;
28+
};

0 commit comments

Comments
 (0)