Skip to content
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
1 change: 1 addition & 0 deletions apps/staking/src/app/restricted-mode/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { RestrictedMode as default } from "../../components/Home";
102 changes: 55 additions & 47 deletions apps/staking/src/components/AccountSummary/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ type Props = {
availableRewards: bigint;
expiringRewards: Date | undefined;
availableToWithdraw: bigint;
restrictedMode?: boolean | undefined;
};

export const AccountSummary = ({
Expand All @@ -54,6 +55,7 @@ export const AccountSummary = ({
availableToWithdraw,
availableRewards,
expiringRewards,
restrictedMode,
}: Props) => (
<section className="relative w-full overflow-hidden sm:border sm:border-neutral-600/50 sm:bg-pythpurple-800">
<Image
Expand Down Expand Up @@ -118,7 +120,9 @@ export const AccountSummary = ({
</>
)}
<div className="mt-3 flex flex-row items-center gap-4 sm:mt-8">
<AddTokensButton walletAmount={walletAmount} api={api} />
{!restrictedMode && (
<AddTokensButton walletAmount={walletAmount} api={api} />
)}
{availableToWithdraw === 0n ? (
<DialogTrigger>
<Button variant="secondary" className="xl:hidden">
Expand All @@ -145,23 +149,25 @@ export const AccountSummary = ({
className="xl:hidden"
/>
)}
<DialogTrigger>
<Button variant="secondary" className="xl:hidden">
Claim
</Button>
{availableRewards === 0n ||
api.type === ApiStateType.LoadedNoStakeAccount ? (
<ModalDialog title="No Rewards" closeButtonText="Ok">
<p>You have no rewards available to be claimed</p>
</ModalDialog>
) : (
<ClaimDialog
expiringRewards={expiringRewards}
availableRewards={availableRewards}
api={api}
/>
)}
</DialogTrigger>
{!restrictedMode && (
<DialogTrigger>
<Button variant="secondary" className="xl:hidden">
Claim
</Button>
{availableRewards === 0n ||
api.type === ApiStateType.LoadedNoStakeAccount ? (
<ModalDialog title="No Rewards" closeButtonText="Ok">
<p>You have no rewards available to be claimed</p>
</ModalDialog>
) : (
<ClaimDialog
expiringRewards={expiringRewards}
availableRewards={availableRewards}
api={api}
/>
)}
</DialogTrigger>
)}
</div>
</div>
<div className="hidden w-auto items-stretch gap-4 xl:flex">
Expand All @@ -173,35 +179,37 @@ export const AccountSummary = ({
<WithdrawButton api={api} max={availableToWithdraw} size="small" />
}
/>
<BalanceCategory
name="Available Rewards"
amount={availableRewards}
description="Rewards you have earned from OIS"
action={
api.type === ApiStateType.Loaded ? (
<ClaimButton
size="small"
variant="secondary"
isDisabled={availableRewards === 0n}
api={api}
/>
) : (
<Button size="small" variant="secondary" isDisabled={true}>
Claim
</Button>
)
}
{...(expiringRewards !== undefined &&
availableRewards > 0n && {
warning: (
<>
Rewards expire one year from the epoch in which they were
earned. You have rewards expiring on{" "}
{expiringRewards.toLocaleDateString()}.
</>
),
})}
/>
{!restrictedMode && (
<BalanceCategory
name="Available Rewards"
amount={availableRewards}
description="Rewards you have earned from OIS"
action={
api.type === ApiStateType.Loaded ? (
<ClaimButton
size="small"
variant="secondary"
isDisabled={availableRewards === 0n}
api={api}
/>
) : (
<Button size="small" variant="secondary" isDisabled={true}>
Claim
</Button>
)
}
{...(expiringRewards !== undefined &&
availableRewards > 0n && {
warning: (
<>
Rewards expire one year from the epoch in which they were
earned. You have rewards expiring on{" "}
{expiringRewards.toLocaleDateString()}.
</>
),
})}
/>
)}
</div>
</div>
</section>
Expand Down
140 changes: 80 additions & 60 deletions apps/staking/src/components/Dashboard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ type Props = {
integrityStakingPublishers: ComponentProps<
typeof OracleIntegrityStaking
>["publishers"];
restrictedMode?: boolean | undefined;
};

export const Dashboard = ({
Expand All @@ -57,6 +58,7 @@ export const Dashboard = ({
integrityStakingPublishers,
unlockSchedule,
yieldRate,
restrictedMode,
}: Props) => {
const [tab, setTab] = useState<TabId>(TabIds.Empty);

Expand Down Expand Up @@ -126,7 +128,11 @@ export const Dashboard = ({
}, [tab]);

return (
<main className="flex w-full flex-col gap-8 xl:px-4 xl:py-6">
<main
className={clsx("flex w-full flex-col gap-8 xl:px-4 xl:py-6", {
"sm:gap-0": restrictedMode,
})}
>
<AccountSummary
api={api}
locked={locked}
Expand All @@ -137,66 +143,80 @@ export const Dashboard = ({
availableToWithdraw={availableToWithdraw}
availableRewards={availableRewards}
expiringRewards={expiringRewards}
restrictedMode={restrictedMode}
/>
<Tabs
selectedKey={tab}
onSelectionChange={setTab}
className="group border-neutral-600/50 data-[empty]:my-[5dvh] data-[empty]:border data-[empty]:bg-white/10 data-[empty]:p-4 sm:p-4 data-[empty]:sm:my-0 data-[empty]:sm:border-0 data-[empty]:sm:bg-transparent data-[empty]:sm:p-0"
{...(tab === TabIds.Empty && { "data-empty": true })}
>
<h1 className="my-4 hidden text-center text-xl/tight font-light group-data-[empty]:mb-10 group-data-[empty]:block sm:mb-6 sm:text-3xl group-data-[empty]:sm:mb-6 lg:my-14 lg:text-5xl">
Choose Your Journey
</h1>
<TabList className="sticky top-header-height z-10 flex flex-row items-stretch justify-center group-data-[empty]:mx-auto group-data-[empty]:max-w-7xl group-data-[empty]:flex-col group-data-[empty]:gap-8 group-data-[empty]:sm:flex-row group-data-[empty]:sm:gap-2">
<Tab id={TabIds.Empty} className="hidden" />
<Journey
longText="Oracle Integrity Staking (OIS)"
shortText="OIS"
image={ois}
id={TabIds.IntegrityStaking}
>
<span>Secure the Oracle</span>
<br />
<span className="font-semibold">to Earn Rewards</span>
</Journey>
<Journey
longText="Pyth Governance"
shortText="Governance"
image={governanceImage}
id={TabIds.Governance}
>
<span>Gain Voting Power</span>
<br />
<span className="font-semibold">for Governance</span>
</Journey>
</TabList>
<TabPanel id={TabIds.Empty}></TabPanel>
<TabPanel id={TabIds.IntegrityStaking}>
<OracleIntegrityStaking
api={api}
currentEpoch={currentEpoch}
availableToStake={availableToStakeIntegrity}
locked={locked}
warmup={integrityStakingWarmup}
staked={integrityStakingStaked}
cooldown={integrityStakingCooldown}
cooldown2={integrityStakingCooldown2}
publishers={integrityStakingPublishers}
yieldRate={yieldRate}
/>
</TabPanel>
<TabPanel id={TabIds.Governance}>
<Governance
api={api}
currentEpoch={currentEpoch}
availableToStake={availableToStakeGovernance}
warmup={governance.warmup}
staked={governance.staked}
cooldown={governance.cooldown}
cooldown2={governance.cooldown2}
/>
</TabPanel>
</Tabs>
{restrictedMode ? (
<Governance
api={api}
currentEpoch={currentEpoch}
availableToStake={availableToStakeGovernance}
warmup={governance.warmup}
staked={governance.staked}
cooldown={governance.cooldown}
cooldown2={governance.cooldown2}
restrictedMode
/>
) : (
<Tabs
selectedKey={tab}
onSelectionChange={setTab}
className="group border-neutral-600/50 data-[empty]:my-[5dvh] data-[empty]:border data-[empty]:bg-white/10 data-[empty]:p-4 sm:p-4 data-[empty]:sm:my-0 data-[empty]:sm:border-0 data-[empty]:sm:bg-transparent data-[empty]:sm:p-0"
{...(tab === TabIds.Empty && { "data-empty": true })}
>
<h1 className="my-4 hidden text-center text-xl/tight font-light group-data-[empty]:mb-10 group-data-[empty]:block sm:mb-6 sm:text-3xl group-data-[empty]:sm:mb-6 lg:my-14 lg:text-5xl">
Choose Your Journey
</h1>
<TabList className="sticky top-header-height z-10 flex flex-row items-stretch justify-center group-data-[empty]:mx-auto group-data-[empty]:max-w-7xl group-data-[empty]:flex-col group-data-[empty]:gap-8 group-data-[empty]:sm:flex-row group-data-[empty]:sm:gap-2">
<Tab id={TabIds.Empty} className="hidden" />
<Journey
longText="Oracle Integrity Staking (OIS)"
shortText="OIS"
image={ois}
id={TabIds.IntegrityStaking}
>
<span>Secure the Oracle</span>
<br />
<span className="font-semibold">to Earn Rewards</span>
</Journey>
<Journey
longText="Pyth Governance"
shortText="Governance"
image={governanceImage}
id={TabIds.Governance}
>
<span>Gain Voting Power</span>
<br />
<span className="font-semibold">for Governance</span>
</Journey>
</TabList>
<TabPanel id={TabIds.Empty}></TabPanel>
<TabPanel id={TabIds.IntegrityStaking}>
<OracleIntegrityStaking
api={api}
currentEpoch={currentEpoch}
availableToStake={availableToStakeIntegrity}
locked={locked}
warmup={integrityStakingWarmup}
staked={integrityStakingStaked}
cooldown={integrityStakingCooldown}
cooldown2={integrityStakingCooldown2}
publishers={integrityStakingPublishers}
yieldRate={yieldRate}
/>
</TabPanel>
<TabPanel id={TabIds.Governance}>
<Governance
api={api}
currentEpoch={currentEpoch}
availableToStake={availableToStakeGovernance}
warmup={governance.warmup}
staked={governance.staked}
cooldown={governance.cooldown}
cooldown2={governance.cooldown2}
/>
</TabPanel>
</Tabs>
)}
</main>
);
};
Expand Down
12 changes: 10 additions & 2 deletions apps/staking/src/components/Governance/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import clsx from "clsx";

import { type States, StateType as ApiStateType } from "../../hooks/use-api";
import { GovernanceGuide } from "../GovernanceGuide";
import { ProgramSection } from "../ProgramSection";
Expand All @@ -10,6 +12,7 @@ type Props = {
staked: bigint;
cooldown: bigint;
cooldown2: bigint;
restrictedMode?: boolean | undefined;
};

export const Governance = ({
Expand All @@ -20,8 +23,10 @@ export const Governance = ({
staked,
cooldown,
cooldown2,
restrictedMode,
}: Props) => (
<ProgramSection
className={clsx({ "border-t sm:border-t-0": restrictedMode })}
name="Pyth Governance"
helpDialog={<GovernanceGuide />}
tagline="Vote and Influence the Network"
Expand All @@ -33,8 +38,6 @@ export const Governance = ({
staked,
cooldown,
cooldown2,
stake: api.type === ApiStateType.Loaded ? api.stakeGovernance : undefined,
stakeDescription: "Stake funds to participate in governance votes",
cancelWarmup:
api.type === ApiStateType.Loaded
? api.cancelWarmupGovernance
Expand All @@ -44,6 +47,11 @@ export const Governance = ({
unstake:
api.type === ApiStateType.Loaded ? api.unstakeGovernance : undefined,
unstakeDescription: "Unstake tokens from the Governance program",
...(!restrictedMode && {
stake:
api.type === ApiStateType.Loaded ? api.stakeGovernance : undefined,
stakeDescription: "Stake funds to participate in governance votes",
}),
}}
/>
);
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
"use client";

import clsx from "clsx";
import { useSelectedLayoutSegment } from "next/navigation";
import { type HTMLProps } from "react";

import { VPN_BLOCKED_SEGMENT } from "../../config/isomorphic";
import { StateType as ApiStateType, useApi } from "../../hooks/use-api";
import { CopyButton } from "../CopyButton";
import { TruncatedKey } from "../TruncatedKey";
Expand All @@ -11,9 +13,11 @@ export const CurrentStakeAccount = ({
className,
...props
}: HTMLProps<HTMLDivElement>) => {
const segment = useSelectedLayoutSegment();
const isBlocked = segment === VPN_BLOCKED_SEGMENT;
const api = useApi();

return api.type === ApiStateType.Loaded ? (
return api.type === ApiStateType.Loaded && !isBlocked ? (
<div
className={clsx(
"hidden flex-col items-end justify-center text-xs xs:flex md:flex-row md:items-center md:text-sm",
Expand Down
Loading
Loading