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

Session Node Registration, Terms and Conditions, and UI Fixes #21

Merged
merged 37 commits into from
Jul 19, 2024
Merged
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
8e82dbb
feat: add hideCloseButton prop to dialog
Aerilym Jul 16, 2024
811cf68
feat: add checkbox shadcn component
Aerilym Jul 16, 2024
641f57b
feat: create session node registration contract hooks for approval an…
Aerilym Jul 16, 2024
c62164a
fix: eslint file path error in tests
Aerilym Jul 16, 2024
82c3262
feat: add radix checkbox package
Aerilym Jul 16, 2024
cf859dc
fix: add fee and amount types to sent backend js library
Aerilym Jul 16, 2024
f6895b5
fix: nextauth types
Aerilym Jul 16, 2024
27e86e8
feat: add modular primary and secondary buttons to the landing page
Aerilym Jul 16, 2024
b03d82b
feat: add terms and conditions logic for testnet involvement
Aerilym Jul 16, 2024
77f8877
feat: add TOS provider and handler
Aerilym Jul 16, 2024
caa8abb
feat: add node registration hooks and logic to form
Aerilym Jul 16, 2024
b333bd4
fix: update node staking logic
Aerilym Jul 16, 2024
ef5207d
fix: staked amount calculation on node cards
Aerilym Jul 16, 2024
7f8c20f
fix: styles and linting
Aerilym Jul 16, 2024
451c1a5
fix: pnpm lock refresh
Aerilym Jul 16, 2024
c523269
fix: add already registered state and filter out registered nodes
Aerilym Jul 17, 2024
8a56aa8
fix: balance module enable issue
Aerilym Jul 17, 2024
ecfe94e
fix: registration not found page
Aerilym Jul 17, 2024
b6ea262
fix: getPendingNodes now filters out already registered nodes
Aerilym Jul 17, 2024
4dc5901
fix: getPendingNodes now filters out already registered nodes
Aerilym Jul 17, 2024
4e620f8
fix: remove handeError from network dropdown child element
Aerilym Jul 17, 2024
6bb0df5
fix: add running node check to new node registration forms
Aerilym Jul 17, 2024
6394204
feat: add error reporting toasts to registration steps
Aerilym Jul 17, 2024
1f0a165
fix: remove staged linting
Aerilym Jul 17, 2024
5421c83
feat: add hover handling to tooltips
Aerilym Jul 17, 2024
320db93
feat: create pending status indicator
Aerilym Jul 17, 2024
30935a8
feat: add joining network logic to registration steps
Aerilym Jul 17, 2024
f825629
fix: add suffix to staked node uptime
Aerilym Jul 17, 2024
4277766
tests: add missing unit tests to date utils
Aerilym Jul 17, 2024
8c02a5e
feat: create areHexesEqual util function for determining equality of …
Aerilym Jul 17, 2024
8c81bfe
fix: use areHexesEqual util function for all address and pubkey equal…
Aerilym Jul 17, 2024
e85692f
fix: remove unused dropdown shadow
Aerilym Jul 17, 2024
c67f0f5
chore: simplify XIcon export
Aerilym Jul 18, 2024
62240a3
chore: minor style fixes
Aerilym Jul 18, 2024
531665b
chore: add to dep array
Aerilym Jul 19, 2024
73d9f37
chore: fix missing deps array items
Aerilym Jul 19, 2024
da4cd4a
chore: add nodeId to deps array
Aerilym Jul 19, 2024
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: 0 additions & 1 deletion .husky/pre-commit

This file was deleted.

1 change: 0 additions & 1 deletion .lintstagedrc.json

This file was deleted.

1 change: 1 addition & 0 deletions apps/staking/.env.local.template
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID=
NEXT_PUBLIC_SENT_STAKING_API_URL=
NEXT_PUBLIC_SENT_EXPLORER_API_URL=
FAUCET_WALLET_PRIVATE_KEY=
FAUCET_DB_SECRET_KEY=
FAUCET_HOURS_BETWEEN_USES=
Expand Down
1 change: 0 additions & 1 deletion apps/staking/.lintstagedrc.json

This file was deleted.

5 changes: 3 additions & 2 deletions apps/staking/app/api/auth/[...nextauth]/route.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { createAuthHandler } from '@session/auth/api';
import { DiscordProvider, handleDiscordSession } from '@session/auth/providers/discord';
import { TelegramProvider, handleTelegramSession } from '@session/auth/providers/telegram';
import { handleTelegramSession, TelegramProvider } from '@session/auth/providers/telegram';
import { NextAuthJWT, NextAuthSession } from '@session/auth/types';

const discordClientId = process.env.DISCORD_CLIENT_ID;
const discordClientSecret = process.env.DISCORD_CLIENT_SECRET;
Expand All @@ -23,7 +24,7 @@ export const { GET, POST } = createAuthHandler({
TelegramProvider({ botToken: telegramBotToken }),
],
callbacks: {
async session({ session, token }) {
async session({ session, token }: { session: NextAuthSession; token: NextAuthJWT }) {
handleDiscordSession({ session, token });
handleTelegramSession({ session, token });
return session;
Expand Down
18 changes: 10 additions & 8 deletions apps/staking/app/faucet/AuthModule.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ import {
FormMessage,
FormSubmitButton,
} from '@session/ui/ui/form';
import { Tooltip, TooltipContent, TooltipTrigger } from '@session/ui/ui/tooltip';
import { Tooltip } from '@session/ui/ui/tooltip';
import { collapseString } from '@session/util/string';
import { WALLET_STATUS, useWallet, useWalletChain } from '@session/wallet/hooks/wallet-hooks';
import { useWallet, useWalletChain, WALLET_STATUS } from '@session/wallet/hooks/wallet-hooks';
import { ReactNode, useEffect, useState } from 'react';
import { useForm } from 'react-hook-form';
import { Address, isAddress } from 'viem';
Expand All @@ -45,11 +45,8 @@ enum FORM_STATE {
}

const FaucetTextTooltip = ({ children, tooltip }: { children: ReactNode; tooltip: ReactNode }) => (
<Tooltip>
<TooltipTrigger asChild>
<span className="underline">{children}</span>
</TooltipTrigger>
<TooltipContent>{tooltip}</TooltipContent>
<Tooltip tooltipContent={tooltip}>
<span className="underline">{children}</span>
</Tooltip>
);

Expand Down Expand Up @@ -405,7 +402,12 @@ export const AuthModule = () => {
{transactionHistory.length > 0 ? (
<>
<p>{dictionary('watchSENTInfo')}</p>
<WalletAddTokenWithLocales rounded="md" size="md" variant="outline" tokenIcon={`${BASE_URL}/images/token_logo.svg`} />
<WalletAddTokenWithLocales
rounded="md"
size="md"
variant="outline"
tokenIcon={`${BASE_URL}/images/token_logo.svg`}
/>
</>
) : null}
</ActionModule>
Expand Down
2 changes: 2 additions & 0 deletions apps/staking/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { cookieToInitialState } from 'wagmi';
import ChainBanner from '@/components/ChainBanner';
import Header from '@/components/Header';
import { GlobalProvider } from '@/providers/global-provider';
import { TOSHandler } from '@/components/TOSHandler';

const wagmiConfig = createWagmiConfig({
projectId: NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID,
Expand Down Expand Up @@ -44,6 +45,7 @@ export default async function RootLayout({ children }: { children: React.ReactNo
<main>{children}</main>
<Toaster />
{!isProduction ? <DevSheet /> : null}
<TOSHandler />
</body>
</GlobalProvider>
</html>
Expand Down
2 changes: 1 addition & 1 deletion apps/staking/app/mystakes/modules/BalanceModule.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ function useTotalStakedAmount() {
{
address: address!,
},
Boolean(address)
{ enabled: Boolean(address) }
);
Aerilym marked this conversation as resolved.
Show resolved Hide resolved

const nodes = useMemo(() => {
Expand Down
2 changes: 1 addition & 1 deletion apps/staking/app/mystakes/modules/DailyNodeReward.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export default function DailyNodeReward() {
refetch,
}}
>
{data}
~{data}
yougotwill marked this conversation as resolved.
Show resolved Hide resolved
</ModuleDynamicContractReadText>
</Module>
);
Expand Down
7 changes: 4 additions & 3 deletions apps/staking/app/mystakes/modules/StakedNodesModule.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import Link from 'next/link';
import { useMemo } from 'react';
import { useStakingBackendQueryWithParams } from '@/lib/sent-staking-backend-client';
import { getStakedNodes } from '@/lib/queries/getStakedNodes';
import { getDateFromUnixTimestampSeconds } from '@session/util/date';

function StakedNodesWithAddress({ address }: { address: string }) {
const showMockNodes = useFeatureFlag(FEATURE_FLAG.MOCK_STAKED_NODES);
Expand Down Expand Up @@ -117,15 +118,15 @@ const msToBlockHeight = (height: number) => {
return Math.floor((currentBlockHeight + height) / blocksPerMs);
};

const parseSessionNodeData = (node: ServiceNode): GenericStakedNode => {
export const parseSessionNodeData = (node: ServiceNode): GenericStakedNode => {
return {
state: node.state,
contributors: node.contributors,
lastRewardHeight: 0,
lastUptime: new Date(Date.now() - msToBlockHeight(node.last_uptime_proof)),
lastUptime: getDateFromUnixTimestampSeconds(node.last_uptime_proof),
pubKey: node.service_node_pubkey,
balance: node.total_contributed,
operatorFee: node.portions_for_operator,
operatorFee: node.operator_fee,
operator_address: node.operator_address,
...(node.awaiting_liquidation ? { awaitingLiquidation: true } : {}),
...(node.decomm_blocks_remaining
Expand Down
75 changes: 40 additions & 35 deletions apps/staking/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,41 @@
import { Footer } from '@/components/Footer';
import { URL } from '@/lib/constants';
import { LANDING_BUTTON_URL } from '@/lib/constants';
import { ButtonDataTestId } from '@/testing/data-test-ids';
import { cn } from '@session/ui/lib/utils';
import { Button } from '@session/ui/ui/button';
import { useTranslations } from 'next-intl';
import Image from 'next/image';
import Link from 'next/link';

const PrimaryButton = ({ size, className }: { size: 'sm' | 'lg'; className?: string }) => {
yougotwill marked this conversation as resolved.
Show resolved Hide resolved
const dictionary = useTranslations('home');

return (
<Link href={LANDING_BUTTON_URL.PRIMARY} prefetch className={className}>
yougotwill marked this conversation as resolved.
Show resolved Hide resolved
<Button size={size} data-testid={ButtonDataTestId.Home_Primary} className="uppercase">
{dictionary('buttons.primary')}
</Button>
</Link>
);
};

const SecondaryButton = ({ size, className }: { size: 'sm' | 'lg'; className?: string }) => {
const dictionary = useTranslations('home');

return (
<Link href={LANDING_BUTTON_URL.SECONDARY} target="_blank" prefetch className={className}>
yougotwill marked this conversation as resolved.
Show resolved Hide resolved
<Button
size={size}
data-testid={ButtonDataTestId.Home_Secondary}
variant="outline"
className="uppercase"
>
{dictionary('buttons.secondary')}
</Button>
</Link>
);
};

export default function LandingPage() {
const dictionary = useTranslations('home');
return (
Expand All @@ -26,52 +55,28 @@ export default function LandingPage() {
'lg:mt-0'
)}
>
<div className={'flex flex-col items-center justify-start lg:items-start'}>
<h1 className="whitespace-nowrap text-center text-5xl font-medium md:text-7xl lg:text-start 2xl:text-8xl">
<div
className={'flex flex-col items-center justify-start backdrop-blur-sm lg:items-start'}
>
<h1 className="3xl:text-8xl whitespace-nowrap text-center text-5xl font-medium md:text-7xl lg:text-start">
{dictionary.rich('title')}
</h1>
<h2
className={cn(
'whitespace-nowrap text-center text-3xl font-medium md:text-4xl lg:text-start xl:text-7xl 2xl:text-8xl'
'3xl:text-8xl whitespace-nowrap text-center text-3xl font-medium md:text-4xl lg:text-start xl:text-7xl'
)}
>
{dictionary('titleDescription')}
</h2>
</div>
<div className="flex flex-row flex-wrap items-center justify-center gap-4 lg:flex-nowrap lg:justify-start">
<Link href="/stake" prefetch className="lg:hidden">
<Button size="sm" data-testid={ButtonDataTestId.Home_Primary} className="uppercase">
{dictionary('buttons.primary')}
</Button>
</Link>
<Link href={URL.SESSION_NODE_DOCS} target="_blank" className="lg:hidden">
<Button
size="sm"
variant="outline"
data-testid={ButtonDataTestId.Home_Secondary}
className="uppercase"
>
{dictionary('buttons.secondary')}
</Button>
</Link>
<Link href="/stake" prefetch className="hidden lg:inline">
<Button size="lg" data-testid={ButtonDataTestId.Home_Primary} className="uppercase">
{dictionary('buttons.primary')}
</Button>
</Link>
<Link href={URL.SESSION_NODE_DOCS} target="_blank" className="hidden lg:inline">
<Button
size="lg"
variant="outline"
data-testid={ButtonDataTestId.Home_Secondary}
className="uppercase"
>
{dictionary('buttons.secondary')}
</Button>
</Link>
<SecondaryButton size="sm" className="lg:hidden" />
<PrimaryButton size="sm" className="lg:hidden" />
<PrimaryButton size="lg" className="hidden lg:inline" />
<SecondaryButton size="lg" className="hidden lg:inline" />
</div>
</div>
<div className="flex max-w-[50vh] items-center justify-center overflow-hidden align-middle lg:max-w-full">
<div className="-z-10 flex max-w-[50vh] items-center justify-center overflow-hidden align-middle lg:max-w-full">
<Image
src="/images/cube.png"
alt={dictionary('heroImageAlt')}
Expand Down
17 changes: 8 additions & 9 deletions apps/staking/app/stake/ActionModule.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import {
} from '@session/ui/components/ModuleGrid';
import { QuestionIcon } from '@session/ui/icons/QuestionIcon';
import { cn } from '@session/ui/lib/utils';
import { Tooltip, TooltipContent, TooltipTrigger } from '@session/ui/ui/tooltip';
import { forwardRef, type HTMLAttributes, type ReactNode } from 'react';
import { Skeleton } from '@session/ui/ui/skeleton';
import { Tooltip } from '@session/ui/ui/tooltip';

type ActionModuleProps = {
title?: string;
Expand Down Expand Up @@ -44,7 +44,9 @@ export default function ActionModule({
</>
) : null}
</ModuleGridHeader>
<ModuleGridContent className={cn("overflow-y-auto p-8", contentClassName)}>{children}</ModuleGridContent>
<ModuleGridContent className={cn('overflow-y-auto p-8', contentClassName)}>
{children}
</ModuleGridContent>
</ModuleGrid>
);
}
Expand Down Expand Up @@ -75,13 +77,10 @@ export const actionModuleBackground = {

export const ActionModuleTooltip = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(
({ className, children, ...props }, ref) => (
<Tooltip>
<TooltipTrigger asChild>
<div ref={ref} className={cn('cursor-pointer', className)} {...props}>
<QuestionIcon className="fill-session-text h-4 w-4" />
</div>
</TooltipTrigger>
<TooltipContent>{children}</TooltipContent>
<Tooltip ref={ref} tooltipContent={children}>
<div className={cn('cursor-pointer', className)} {...props}>
<QuestionIcon className="fill-session-text h-4 w-4" />
</div>
</Tooltip>
)
);
Expand Down
12 changes: 11 additions & 1 deletion apps/staking/app/stake/PendingNodesModule.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import { PendingNodeCard } from '@/components/PendingNodeCard';
import { useTranslations } from 'next-intl';
import { cn } from '@session/ui/lib/utils';
import { generatePendingNodes } from '@session/sent-staking-js/test';
import { QUERY } from '@/lib/constants';
import { isProduction } from '@/lib/env';

export default function PendingNodesModule() {
const showOneMockNode = useFeatureFlag(FEATURE_FLAG.MOCK_PENDING_NODES_ONE);
Expand Down Expand Up @@ -45,7 +47,12 @@ export default function PendingNodesModule() {
const { data, isLoading } = useStakingBackendQueryWithParams(
getPendingNodes,
{ address: address! },
isConnected
{
enabled: isConnected,
staleTime: isProduction
? QUERY.STALE_TIME_REGISTRATIONS_LIST
: QUERY.STALE_TIME_REGISTRATIONS_LIST_DEV,
}
);

const nodes = useMemo(() => {
Expand Down Expand Up @@ -74,6 +81,9 @@ export default function PendingNodesModule() {
showManyMockNodes,
]);

/** NOTE: The parent div needs to be rendered while loading in case nodes are returned, this
yougotwill marked this conversation as resolved.
Show resolved Hide resolved
* allows the height transition to work.
* Once we know there are no nodes (loading is done and there are no nodes) it can be null */
return isLoading || nodes.length ? (
<div
className={cn(
Expand Down
3 changes: 2 additions & 1 deletion apps/staking/app/stake/[nodeId]/BlockExplorerLink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ import { useStakingBackendSuspenseQuery } from '@/lib/sent-staking-backend-clien
import { getOpenNodes } from '@/lib/queries/getOpenNodes';
import { useMemo } from 'react';
import { Loading } from '@session/ui/components/loading';
import { areHexesEqual } from '@session/util/string';

export const BlockExplorerLink = ({ nodeId }: { nodeId: string }) => {
const { data, isLoading } = useStakingBackendSuspenseQuery(getOpenNodes);

const node = useMemo(() => {
return data?.nodes?.find((node) => node.service_node_pubkey === nodeId);
return data?.nodes?.find((node) => areHexesEqual(node.service_node_pubkey, nodeId));
}, [data]);

yougotwill marked this conversation as resolved.
Show resolved Hide resolved
return isLoading ? (
Expand Down
14 changes: 8 additions & 6 deletions apps/staking/app/stake/[nodeId]/NodeStaking.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,27 @@ import { NodeContributorList } from '@/components/NodeCard';
import { PubKey } from '@/components/PubKey';
import { formatPercentage } from '@/lib/locale-client';
import { ButtonDataTestId } from '@/testing/data-test-ids';
import { SENT_SYMBOL } from '@session/contracts';
import { SENT_DECIMALS, SENT_SYMBOL } from '@session/contracts';
import type { GetOpenNodesResponse } from '@session/sent-staking-js/client';
import { Loading } from '@session/ui/components/loading';
import { Button, ButtonSkeleton } from '@session/ui/ui/button';
import { formatNumber } from '@session/util/maths';
import { bigIntToNumber, formatNumber } from '@session/util/maths';
import { useTranslations } from 'next-intl';
import { useMemo } from 'react';
import { ActionModuleDivider, ActionModuleRow, ActionModuleRowSkeleton } from '../ActionModule';
import { useStakingBackendSuspenseQuery } from '@/lib/sent-staking-backend-client';
import { getOpenNodes } from '@/lib/queries/getOpenNodes';
import { FEATURE_FLAG, useFeatureFlag } from '@/providers/feature-flag-provider';
import { generateOpenNodes } from '@session/sent-staking-js/test';
import { areHexesEqual } from '@session/util/string';

export default function NodeStaking({ nodeId }: { nodeId: string }) {
const showMockNodes = useFeatureFlag(FEATURE_FLAG.MOCK_OPEN_NODES);
const { data, isLoading } = useStakingBackendSuspenseQuery(getOpenNodes);

const node = useMemo(() => {
if (showMockNodes) return generateOpenNodes()[0];
return data?.nodes?.find((node) => node.service_node_pubkey === nodeId);
return data?.nodes?.find((node) => areHexesEqual(node.service_node_pubkey, nodeId));
}, [data, showMockNodes]);

return isLoading ? (
Expand All @@ -43,9 +44,10 @@ export function NodeStakingForm({ node }: { node: GetOpenNodesResponse['nodes'][

const formattedTotalStakedAmount = useMemo(() => {
if (!node.contributions || node.contributions.length === 0) return '0';
const totalStaked =
node.contributions.reduce((acc, contributor) => acc + contributor.amount, 0) /
Math.pow(10, 9);
const totalStaked = node.contributions.reduce(
(acc, contributor) => acc + bigIntToNumber(contributor.amount, SENT_DECIMALS),
0
);
return formatNumber(totalStaked);
}, [node.contributions]);

Expand Down
Loading