Skip to content

Commit

Permalink
Merge pull request #55 from gnosischain/dev
Browse files Browse the repository at this point in the history
add tooltip and fix treshold issue
  • Loading branch information
Wagalidoom authored Sep 11, 2024
2 parents d4dc12b + 4e89325 commit 40da538
Show file tree
Hide file tree
Showing 11 changed files with 172 additions and 35 deletions.
2 changes: 1 addition & 1 deletion app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export default function Page() {
</div>
<p className="text-xl">BEACON CHAIN DEPOSIT</p>
<p className="text-xl my-8">Connect your wallet to get started:</p>
<Link href="/connect" className="bg-[#DD7143] px-8 py-4 rounded-full text-xl font-semibold outline outline-2 outline-transparent hover:outline-white/80 transition-all duration-300 ease-in-out">
<Link href="/connect" className="bg-accent px-8 py-4 rounded-full text-xl font-semibold outline outline-2 outline-transparent hover:outline-white/80 transition-all duration-300 ease-in-out">
Connect Wallet
</Link>
<Link target="_blank" className="w-full flex justify-center mt-20 text-sm lg:text-base items-center underline hover:text-slate-200" href={"https://docs.gnosischain.com/node/"}>
Expand Down
4 changes: 2 additions & 2 deletions components/dappnodeDeposit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ function Validation({
</p>
)}
<button
className="bg-[#DD7143] px-4 py-1 rounded-full text-white mt-4 text-lg font-semibold"
className="bg-accent px-4 py-1 rounded-full text-white mt-4 text-lg font-semibold"
onClick={onDeposit}
>
Claim
Expand All @@ -310,7 +310,7 @@ function SubmittedStatus({ tx }: { tx: `0x${string}` }) {
<Link
href={"https://gnosis.blockscout.com/tx/" + tx}
target="_blank"
className="text-[#DD7143] underline ml-1"
className="text-accent underline ml-1"
>
here.
</Link>
Expand Down
90 changes: 74 additions & 16 deletions components/deposit.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,32 @@
"use client";

import useDeposit from "@/hooks/use-deposit";
import { ArrowUturnLeftIcon, InformationCircleIcon, CheckIcon } from "@heroicons/react/20/solid";
import {
ArrowUturnLeftIcon,
CheckIcon,
} from "@heroicons/react/20/solid";
import Image from "next/image";
import { useCallback, useEffect, useState } from "react";
import { useDropzone } from "react-dropzone";
import { FileRejection } from "react-dropzone";
import Loader from "./loader";
import Link from "next/link";
import { ContractNetwork } from "@/utils/contracts";
import ToolTip from "./tooltip";

interface DepositProps {
contractConfig: ContractNetwork | undefined;
address: `0x${string}` | undefined;
chainId: number;
}

export default function Deposit({contractConfig, address, chainId}: DepositProps) {
const { setDepositData, depositData, deposit, depositSuccess, depositHash } = useDeposit(contractConfig, address, chainId);
export default function Deposit({
contractConfig,
address,
chainId,
}: DepositProps) {
const { setDepositData, depositData, deposit, depositSuccess, depositHash } =
useDeposit(contractConfig, address, chainId);
const [errorMessage, setErrorMessage] = useState("");
const [loading, setLoading] = useState(false);
const [tx, setTx] = useState<`0x${string}`>("0x0");
Expand Down Expand Up @@ -63,7 +72,11 @@ export default function Deposit({contractConfig, address, chainId}: DepositProps
};
}, []);

const { getRootProps, getInputProps } = useDropzone({ onDrop, accept: { "application/json": [] }, maxFiles: 1 });
const { getRootProps, getInputProps } = useDropzone({
onDrop,
accept: { "application/json": [] },
maxFiles: 1,
});

const onDeposit = useCallback(async () => {
setLoading(true);
Expand Down Expand Up @@ -91,15 +104,39 @@ export default function Deposit({contractConfig, address, chainId}: DepositProps
<p className="mt-2">Loading...</p>
</>
) : step === "deposit" ? (
<div className="w-full h-full flex flex-col items-center justify-center hover:cursor-pointer" {...getRootProps()}>
<div
className="w-full h-full flex flex-col items-center justify-center hover:cursor-pointer"
{...getRootProps()}
>
<input id="dropzone" {...getInputProps()} />
Upload deposit date file
<div className="flex font-bold items-center">
deposit_data.json <InformationCircleIcon className="ml-px h-5 w-5" />
<div className="flex font-bold items-center gap-x-1">
deposit_data.json{" "}
<ToolTip
text={
<p>
See{" "}
<a href="https://docs.gnosischain.com/node/manual/validator/generate-keys/" className="underline">
here
</a>{" "}
to learn how to generate the file.
</p>
}
/>
</div>
<Image src="/drop.svg" alt="Drop" width={80} height={24} className="my-8 rounded-full shadow-lg" />
<Image
src="/drop.svg"
alt="Drop"
width={80}
height={24}
className="my-8 rounded-full shadow-lg"
/>
<div>Drag file to upload or browse</div>
{errorMessage && <p className="text-red-400 text-sm" id="error">{errorMessage.substring(0, 150)}</p>}
{errorMessage && (
<p className="text-red-400 text-sm" id="error">
{errorMessage.substring(0, 150)}
</p>
)}
</div>
) : step === "validation" ? (
<div className="w-full flex flex-col items-center">
Expand All @@ -108,32 +145,53 @@ export default function Deposit({contractConfig, address, chainId}: DepositProps
<CheckIcon className="h-5 w-5" /> Accepted
</div>
<div className="flex items-center">
<CheckIcon className="h-5 w-5" /> Validator deposits: {depositData.deposits.length}
<CheckIcon className="h-5 w-5" /> Validator deposits:{" "}
{depositData.deposits.length}
</div>
<div className="flex items-center">
<CheckIcon className="h-5 w-5" /> Total amount required: {depositData.deposits.length} GNO
<CheckIcon className="h-5 w-5" /> Total amount required:{" "}
{depositData.deposits.length} GNO
</div>
{depositData.isBatch ? (
""
) : (
<p className="text-orange-400 text-xs text-center">
Your deposit file contains BLS credentials (starting with 0x00), you&apos;ll be asked to sign a transaction for each of them. Alternatively you can generate the keys again, make sure to specify an eth1 address for the withdrawal credentials.
Your deposit file contains BLS credentials (starting with 0x00),
you&apos;ll be asked to sign a transaction for each of them.
Alternatively you can generate the keys again, make sure to
specify an eth1 address for the withdrawal credentials.
</p>
)}
<button className="bg-[#DD7143] px-4 py-1 rounded-full text-white mt-4 text-lg font-semibold" onClick={onDeposit} id="depositButton">
<button
className="bg-accent px-4 py-1 rounded-full text-white mt-4 text-lg font-semibold"
onClick={onDeposit}
id="depositButton"
>
Deposit
</button>
</div>
) : step === "summary" ? (
<div className="w-full flex flex-col items-center">
<div className="flex items-center" id="confirmation">
<CheckIcon className="h-5 w-5" /> Your transaction is completed ! View it
<Link href={chainId === 100 ? "https://gnosis.blockscout.com/tx/" + tx : "https://gnosis-chiado.blockscout.com/tx/" + tx} target="_blank" className="text-[#DD7143] underline ml-1">
<CheckIcon className="h-5 w-5" /> Your transaction is completed !
View it
<Link
href={
chainId === 100
? "https://gnosis.blockscout.com/tx/" + tx
: "https://gnosis-chiado.blockscout.com/tx/" + tx
}
target="_blank"
className="text-accent underline ml-1"
>
here
</Link>
.
</div>
<button className="text-[#DD7143] flex items-center px-4 py-1 rounded-full mt-4 text-base font-semibold" onClick={() => setStep("deposit")}>
<button
className="text-accent flex items-center px-4 py-1 rounded-full mt-4 text-base font-semibold"
onClick={() => setStep("deposit")}
>
Back <ArrowUturnLeftIcon className="h-4 w-4 ml-2" />
</button>
</div>
Expand Down
2 changes: 1 addition & 1 deletion components/navigation-tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export default function NavigationTab({ value }: NavigationTabProps) {
};

return (
<div onClick={handleClick} className={`${searchParams.get("state") == value ? "border-[#DD7143]" : ""} w-full flex justify-center items-center text-center p-2 lg:p-3.5 font-bold border-b-2 hover:cursor-pointer`} id={value}>
<div onClick={handleClick} className={`${searchParams.get("state") == value ? "border-accent" : ""} w-full flex justify-center items-center text-center p-2 lg:p-3.5 font-bold border-b-2 hover:cursor-pointer`} id={value}>
{texts[value]}
</div>
);
Expand Down
62 changes: 62 additions & 0 deletions components/tooltip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
"use client";

import { Popover, PopoverButton, PopoverPanel } from "@headlessui/react";
import { InformationCircleIcon } from "@heroicons/react/20/solid";
import { useState, useRef, useEffect } from "react";

interface ToolTipProps {
text: React.ReactNode;
}

export default function ToolTip({ text }: ToolTipProps) {
const [isOpen, setIsOpen] = useState(false);
const popoverButtonRef = useRef<HTMLButtonElement>(null);

const handleMouseEnter = () => {
setIsOpen(true);
};

const handleMouseLeave = () => {
setIsOpen(false);
};

useEffect(() => {
const current = popoverButtonRef.current;
if (!current) {
return;
}

const observer = new MutationObserver((mutations) => {
const hovered = mutations.find(
({ attributeName }) => attributeName === "data-hover"
);
const active = current.hasAttribute("data-active");

if (hovered && !active) {
current.click();
}
});

observer.observe(current, { attributes: true });

return () => {
observer.disconnect();
};
}, [popoverButtonRef]);

return (
<Popover className="relative" onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave}>
<PopoverButton ref={popoverButtonRef} className="focus:outline-none">
<InformationCircleIcon className="h-5 w-5" />
</PopoverButton>
{isOpen && (
<PopoverPanel
anchor="top"
className="flex bg-accent/80 rounded-full py-1 px-2 text-sm mb-2 [--anchor-gap:4px]"
>
{text}
</PopoverPanel>
)}
</Popover>
);
}
26 changes: 18 additions & 8 deletions components/withdrawal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { Address, formatEther } from "viem";
import Link from "next/link";
import useBalance from "@/hooks/use-balance";
import { ContractNetwork } from "@/utils/contracts";
import { InformationCircleIcon } from "@heroicons/react/24/outline";
import ToolTip from "./tooltip";

interface WithdrawalProps {
contractConfig: ContractNetwork | undefined;
Expand Down Expand Up @@ -94,7 +96,15 @@ export default function Withdrawal({
) : step === "claim" ? (
<>
<div className="w-full text-sm flex justify-center">
Set up automated claim with your preferred frequency and threshold.
Set up automated claim with your preferred frequency and threshold.{" "}
<ToolTip
text={
<p>
Address will become eligable for claim if one of thresholds
reached.
</p>
}
/>
</div>
<div className="py-4 md:py-0 flex h-full flex-col justify-center gap-y-4">
<div className="flex flex-col">
Expand All @@ -113,7 +123,7 @@ export default function Withdrawal({
type="radio"
value={1}
name="inline-radio-group"
className="w-4 h-4 accent-[#DD7143]"
className="w-4 h-4 accent-accent"
/>
<label
htmlFor="day"
Expand All @@ -129,7 +139,7 @@ export default function Withdrawal({
type="radio"
value={7}
name="inline-radio-group"
className="w-4 h-4 accent-[#DD7143]"
className="w-4 h-4 accent-accent"
/>
<label
htmlFor="week"
Expand All @@ -145,7 +155,7 @@ export default function Withdrawal({
type="radio"
value={30}
name="inline-radio-group"
className="w-4 h-4 accent-[#DD7143]"
className="w-4 h-4 accent-accent"
/>
<label
htmlFor="month"
Expand All @@ -172,7 +182,7 @@ export default function Withdrawal({
/>
</div>
<button
className="bg-[#DD7143] py-1 rounded-full text-white text-lg font-semibold"
className="bg-accent py-1 rounded-full text-white text-lg font-semibold"
onClick={onAutoclaim}
id="autoclaim"
>
Expand All @@ -186,7 +196,7 @@ export default function Withdrawal({
{Number(formatEther(claimBalance || BigInt(0))).toFixed(3)} GNOS
</div>
<button
className="text-[#DD7143] underline hover:text-[#E07F55]"
className="text-accent underline hover:text-[#E07F55]"
onClick={onClaim}
>
Manual claim
Expand Down Expand Up @@ -216,14 +226,14 @@ export default function Withdrawal({
: "https://gnosis-chiado.blockscout.com/tx/" + tx
}
target="_blank"
className="text-[#DD7143] underline ml-1"
className="text-accent underline ml-1"
>
here
</Link>
.
</div>
<button
className="text-[#DD7143] flex items-center px-4 py-1 rounded-full mt-4 text-base font-semibold"
className="text-accent flex items-center px-4 py-1 rounded-full mt-4 text-base font-semibold"
onClick={() => setStep("claim")}
>
Back <ArrowUturnLeftIcon className="h-4 w-4 ml-2" />
Expand Down
5 changes: 3 additions & 2 deletions hooks/use-autoclaim.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { getPublicClient } from "wagmi/actions";
import { config } from "@/wagmi";
import { fetchRegister, fetchUnregister } from "@/utils/fetchEvents";
import { parseUnits } from "viem";
import { SECOND_IN_DAY } from "@/utils/constants";

function useAutoclaim(contractConfig: ContractNetwork | undefined, address: `0x${string}` | undefined, chainId: number) {
const [isRegister, setIsRegister] = useState(false);
Expand Down Expand Up @@ -44,7 +45,7 @@ function useAutoclaim(contractConfig: ContractNetwork | undefined, address: `0x$
const register = useCallback(
async (days: number, amount: number) => {
if (contractConfig) {
const timeStamp = BigInt(days * 86400000);
const timeStamp = BigInt(days * SECOND_IN_DAY);
writeContract({ address: contractConfig.addresses.claimRegistry, abi: claimRegistryABI, functionName: "register", args: [address || "0x0", timeStamp, parseUnits(amount.toString(), 18)] });
}
},
Expand All @@ -54,7 +55,7 @@ function useAutoclaim(contractConfig: ContractNetwork | undefined, address: `0x$
const updateConfig = useCallback(
async (days: number, amount: number) => {
if (contractConfig) {
const timeStamp = BigInt(days * 86400000);
const timeStamp = BigInt(days * SECOND_IN_DAY);
writeContract({ address: contractConfig.addresses.claimRegistry, abi: claimRegistryABI, functionName: "updateConfig", args: [address || "0x0", timeStamp, parseUnits(amount.toString(), 18)] });
}
},
Expand Down
5 changes: 3 additions & 2 deletions hooks/use-dappnode-deposit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { loadCachedDeposits } from "@/utils/deposit";
import { getPublicClient } from "wagmi/actions";
import { config } from "@/wagmi";
import { fetchDeposit } from "@/utils/fetchEvents";
import { DEPOSIT_TOKEN_AMOUNT_OLD, MAX_BATCH_DEPOSIT } from "@/utils/constants";

export type DepositDataJson = {
pubkey: string;
Expand Down Expand Up @@ -141,14 +142,14 @@ function useDappnodeDeposit(contractConfig: ContractNetwork | undefined, address
// check if withdrawal credential start with 0x00
_isBatch = !wc.startsWith("00");

if (_isBatch && newDeposits.length > 128) {
if (_isBatch && newDeposits.length > MAX_BATCH_DEPOSIT) {
throw Error(
"Number of validators exceeds the maximum batch size of 128. Please upload a file with 128 or fewer validators."
);
}

if (
!newDeposits.every((d) => BigInt(d.amount) === BigInt(32000000000))
!newDeposits.every((d) => BigInt(d.amount) === BigInt(DEPOSIT_TOKEN_AMOUNT_OLD))
) {
throw Error("Amount should be exactly 32 tokens for deposits.");
}
Expand Down
Loading

0 comments on commit 40da538

Please sign in to comment.