Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(staking): add changelog #2019

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
198 changes: 198 additions & 0 deletions apps/staking/src/components/Changelog/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
"use client";

import type { ReactNode } from "react";
import { useDateFormatter } from "react-aria";

import { useChangelog } from "../../hooks/use-changelog";
import { Link } from "../Link";
import { ModalDialog } from "../ModalDialog";

export const Changelog = () => {
const { isOpen, toggleOpen } = useChangelog();

return (
<ModalDialog title="Changelog" isOpen={isOpen} onOpenChange={toggleOpen}>
<ul className="flex max-w-prose flex-col divide-y divide-neutral-600/50">
{messages.map(({ id, message }) => (
<li key={id}>{message}</li>
))}
</ul>
</ModalDialog>
);
};

type ChangelogMessageProps = {
date: Date;
children: ReactNode | ReactNode[];
};

export const ChangelogMessage = ({ date, children }: ChangelogMessageProps) => {
const dateFormatter = useDateFormatter({
year: "numeric",
month: "short",
day: "numeric",
});

return (
<section className="py-8">
<h2 className="text-sm uppercase text-pythpurple-400">
{dateFormatter.format(date)}
</h2>
{children}
</section>
);
};

type ChangelogSectionProps = {
title: ReactNode;
children: ReactNode | ReactNode[];
};

export const ChangelogSection = ({
title,
children,
}: ChangelogSectionProps) => (
<section className="mt-4">
<h3 className="text-lg font-semibold text-white">{title}</h3>
<div className="flex flex-col gap-2 pl-2 text-sm opacity-70">
{children}
</div>
</section>
);

export const messages = [
{
id: 1,
message: (
<ChangelogMessage date={new Date("2024-10-10")}>
<ChangelogSection title="Milestones">
<div>
<p>
We are pleased to announce the following Oracle Integrity Staking
milestones:
</p>
<ul className="list-disc pl-8">
<li>143M PYTH staked and securing DeFi.</li>
<li>9.6K unique stakers participating.</li>
<li>237K in PYTH programmatically distributed.</li>
</ul>
</div>
<p>We’re thrilled to see so many community participants.</p>
</ChangelogSection>
<ChangelogSection title="New Features to the Staking Frontend">
<ul className="list-disc pl-4">
<li>
New sort filter for publishers list. Publishers with self-stake
are displayed first by default. You can sort by publisher details,
pool composition, and more.
</li>
<li>
Publishers interested in de-anonymizing themselves can have their
names displayed in the publisher list.
</li>
<li>New OIS live stats added to navigation bar.</li>
<li>
New dialogue added under “Help” where you can view current program
parameters.
</li>
<li>
Option to remove PYTH from the smart contract program for parties
with restricted access to the staking frontend.
</li>
<li>
Full access to Pyth Governance for certain restricted
jurisdictions.
</li>
<li>APYs are now shown as net of delegation fees.</li>
<li>
Updates to educational materials (all Guides and FAQs) for clarity
and readability.
</li>
<li>
New Oracle Integrity Staking{" "}
<Link
href="https://forum.pyth.network/c/oracle-integrity-staking-ois-discussion/8"
className="underline"
target="_blank"
>
discussion catalogue
</Link>{" "}
opened in Pyth DAO forum. Let the community know your thoughts and
feedback!
</li>
</ul>
</ChangelogSection>
<ChangelogSection title="Security">
<p>
The Pyth contributors take security extremely seriously. The
contract code is{" "}
<Link
href="https://github.com/pyth-network/governance/tree/main/staking/programs/staking"
className="underline"
target="_blank"
>
open source
</Link>{" "}
and the upgrade authority is governed by the Pyth DAO. The official{" "}
<Link
href="https://github.com/pyth-network/audit-reports/blob/main/2024_09_11/pyth_cip_final_report.pdf"
className="underline"
target="_blank"
>
audit report
</Link>{" "}
is publicly accessible. All on-chain contract codes are verified
using{" "}
<Link
href="https://github.com/Ellipsis-Labs/solana-verifiable-build/"
className="underline"
target="_blank"
>
Solana verifiable build
</Link>{" "}
and the Pyth DAO governs the upgrade authority.
</p>
</ChangelogSection>
<ChangelogSection title="Best Practices">
<p>
Please remember that publishers have priority for programmatic
rewards distributions. By protocol design, if a pool’s stake cap is
exceeded, the programmatic reward rate for other stakers
participating in that pool will be lower than the Pyth DAO-set
maximum reward rate.
</p>
</ChangelogSection>
<ChangelogSection title="Acknowledgements">
<p>
The Pyth contributors are glad to see so many network participants
getting involved with Oracle Integrity Staking to help secure the
oracle and protect the wider DeFi industry. OIS wouldn’t be possible
without you!
</p>
</ChangelogSection>
<ChangelogSection title="Feedback">
<p>
Please reach out in the official{" "}
<Link
href="https://discord.com/invite/PythNetwork"
className="underline"
target="_blank"
>
Pyth Discord
</Link>{" "}
or the{" "}
<Link
href="https://forum.pyth.network"
className="underline"
target="_blank"
>
Pyth DAO Forum
</Link>{" "}
to share your questions, ideas, or feedback. We want to hear what
you think.
</p>
</ChangelogSection>
</ChangelogMessage>
),
},
];
23 changes: 12 additions & 11 deletions apps/staking/src/components/Header/help-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { MenuTrigger, Button } from "react-aria-components";

import { ProgramParameters } from "./program-parameters";
import { StateType, useApi } from "../../hooks/use-api";
import { useChangelog } from "../../hooks/use-changelog";
import { GeneralFaq } from "../GeneralFaq";
import { GovernanceGuide } from "../GovernanceGuide";
import { Menu, MenuItem, Section, Separator } from "../Menu";
Expand Down Expand Up @@ -41,6 +42,7 @@ export const HelpMenu = () => {
const openParameters = useCallback(() => {
setParametersOpen(true);
}, [setParametersOpen]);
const { open: openChangelog } = useChangelog();

return (
<>
Expand Down Expand Up @@ -73,17 +75,16 @@ export const HelpMenu = () => {
Data Publisher Guide
</MenuItem>
</Section>
{(api.type === StateType.Loaded ||
api.type === StateType.LoadedNoStakeAccount) && (
<>
<Separator />
<Section>
<MenuItem onAction={openParameters}>
Current Program Parameters
</MenuItem>
</Section>
</>
)}
<Separator />
<Section>
{(api.type === StateType.Loaded ||
api.type === StateType.LoadedNoStakeAccount) && (
<MenuItem onAction={openParameters}>
Current Program Parameters
</MenuItem>
)}
<MenuItem onAction={openChangelog}>Changelog</MenuItem>
</Section>
</Menu>
</MenuTrigger>
<GeneralFaq isOpen={faqOpen} onOpenChange={setFaqOpen} />
Expand Down
2 changes: 2 additions & 0 deletions apps/staking/src/components/ModalDialog/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"use client";

import { XMarkIcon } from "@heroicons/react/24/outline";
import clsx from "clsx";
import type { ComponentProps, ReactNode } from "react";
Expand Down
2 changes: 2 additions & 0 deletions apps/staking/src/components/Root/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { LoggerProvider } from "../../hooks/use-logger";
import { NetworkProvider } from "../../hooks/use-network";
import { ToastProvider } from "../../hooks/use-toast";
import { Amplitude } from "../Amplitude";
import { Changelog } from "../Changelog";
import { Footer } from "../Footer";
import { Header } from "../Header";
import { MaxWidth } from "../MaxWidth";
Expand Down Expand Up @@ -64,6 +65,7 @@ export const Root = ({ children }: Props) => (
</MaxWidth>
<Footer className="z-10" />
<ToastRegion />
<Changelog />
</body>
{GOOGLE_ANALYTICS_ID && <GoogleAnalytics gaId={GOOGLE_ANALYTICS_ID} />}
{AMPLITUDE_API_KEY && <Amplitude apiKey={AMPLITUDE_API_KEY} />}
Expand Down
41 changes: 41 additions & 0 deletions apps/staking/src/hooks/use-changelog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { useLocalStorageValue } from "@react-hookz/web";
import { useCallback, useMemo } from "react";

import { messages } from "../components/Changelog";

export const useChangelog = () => {
const lastMessageSeen = useLocalStorageValue<number>(
"last-changelog-message-seen",
{
parse: (value) =>
// eslint-disable-next-line unicorn/no-null
value === null || value === "" ? null : Number.parseInt(value, 10),
stringify: (value) => value.toString(),
},
);

const isOpen = useMemo(() => {
const lastClosed = lastMessageSeen.value;
return (
lastClosed === undefined ||
messages.some((message) => message.id > lastClosed)
);
}, [lastMessageSeen.value]);

const toggleOpen = useCallback(
(isOpen: boolean) => {
if (isOpen) {
lastMessageSeen.remove();
} else {
lastMessageSeen.set(Math.max(...messages.map(({ id }) => id)));
}
},
[lastMessageSeen],
);

const open = useCallback(() => {
toggleOpen(true);
}, [toggleOpen]);

return { isOpen, toggleOpen, open };
};
Loading