Skip to content

Commit

Permalink
Merge pull request #1775 from kleros/feat/new-stake-flow
Browse files Browse the repository at this point in the history
feat(web): new-stake-flow
  • Loading branch information
alcercu authored Dec 10, 2024
2 parents 9b945af + 40fa153 commit 8cde978
Show file tree
Hide file tree
Showing 21 changed files with 1,046 additions and 579 deletions.
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@
"web-devtools",
"eslint-config",
"prettier-config",
"tsconfig",
"kleros-app"
"tsconfig"
],
"packageManager": "[email protected]",
"volta": {
Expand Down
2 changes: 0 additions & 2 deletions web/netlify.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ NETLIFY_YARN_WORKSPACES = "true"
YARN_ENABLE_GLOBAL_CACHE = "true"
# YARN_CACHE_FOLDER = "$HOME/.yarn_cache"
# YARN_VERSION = "3.2.0"
[build]
command = "yarn workspace @kleros/kleros-v2-contracts install && yarn workspace @kleros/kleros-app install && yarn workspace @kleros/kleros-v2-web install && yarn workspace @kleros/kleros-v2-contracts build && yarn workspace @kleros/kleros-app build && yarn workspace @kleros/kleros-v2-web build-netlify"

[functions]
directory = "web/netlify/functions/"
10 changes: 5 additions & 5 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,15 @@
},
"dependencies": {
"@cyntler/react-doc-viewer": "^1.17.0",
"@kleros/kleros-app": "workspace:^",
"@kleros/kleros-app": "^2.0.1",
"@kleros/kleros-sdk": "workspace:^",
"@kleros/kleros-v2-contracts": "workspace:^",
"@kleros/ui-components-library": "^2.15.0",
"@kleros/ui-components-library": "^2.16.0",
"@lifi/wallet-management": "^3.4.5",
"@lifi/widget": "^3.12.2",
"@sentry/react": "^7.120.0",
"@sentry/tracing": "^7.120.0",
"@tanstack/react-query": "^5.61.0",
"@tanstack/react-query": "^5.56.2",
"@types/react-modal": "^3.16.3",
"@wagmi/connectors": "^5.5.0",
"@wagmi/core": "^2.15.0",
Expand Down Expand Up @@ -117,7 +117,7 @@
"react-toastify": "^9.1.3",
"react-use": "^17.5.1",
"styled-components": "^5.3.3",
"viem": "^2.21.48",
"wagmi": "^2.13.0"
"viem": "^2.21.54",
"wagmi": "^2.13.5"
}
}
2 changes: 1 addition & 1 deletion web/src/assets/svgs/icons/close-circle.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion web/src/components/ExternalLink.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Link } from "react-router-dom";
import styled from "styled-components";

import { Link } from "react-router-dom";

export const ExternalLink = styled(Link)`
:hover {
text-decoration: underline;
Expand Down
27 changes: 27 additions & 0 deletions web/src/components/Spinner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import styled, { keyframes } from "styled-components";

import SpinnerIcon from "svgs/icons/spinner.svg";

const rotating = keyframes`
0%{
transform: rotate(0deg);
}
50%{
transform: rotate(180deg);
}
100%{
transform: rotate(360deg);
}
`;

const Spinner = styled(SpinnerIcon)`
path {
fill: ${({ theme }) => theme.primaryBlue};
}
width: 16px;
height: 16px;
margin-right: 4px;
animation: ${rotating} 2s ease-in-out infinite normal;
`;

export default Spinner;
40 changes: 40 additions & 0 deletions web/src/components/TxnHash.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React, { useMemo } from "react";
import styled from "styled-components";

import NewTabIcon from "svgs/icons/new-tab.svg";

import { DEFAULT_CHAIN, getChain } from "consts/chains";

import { ExternalLink } from "./ExternalLink";

const TxnLabel = styled.label<{ variant: string }>`
display: flex;
gap: 4px;
color: ${({ theme, variant }) => (variant === "pending" ? theme.primaryBlue : theme[variant])};
cursor: pointer;
path {
fill: ${({ theme, variant }) => (variant === "pending" ? theme.primaryBlue : theme[variant])};
}
`;

interface ITxnHash {
hash: `0x${string}`;
variant: "success" | "error" | "pending";
}
const TxnHash: React.FC<ITxnHash> = ({ hash, variant }) => {
const transactionExplorerLink = useMemo(() => {
return `${getChain(DEFAULT_CHAIN)?.blockExplorers?.default.url}/tx/${hash}`;
}, [hash]);

return (
<ExternalLink to={transactionExplorerLink} rel="noopener noreferrer" target="_blank">
<TxnLabel {...{ variant }}>
{" "}
<span>{hash.substring(0, 6) + "..." + hash.substring(hash.length - 4)}</span>
<NewTabIcon />
</TxnLabel>
</ExternalLink>
);
};

export default TxnHash;
1 change: 1 addition & 0 deletions web/src/hooks/queries/useCourtDetails.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const courtDetailsQuery = graphql(`
paidPNK
timesPerPeriod
feeForJuror
name
}
}
`);
Expand Down
46 changes: 46 additions & 0 deletions web/src/hooks/usePNKData.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { useAccount } from "wagmi";

import { DEFAULT_CHAIN } from "consts/chains";

import { REFETCH_INTERVAL } from "src/consts";
import { isUndefined } from "src/utils";

import {
klerosCoreAddress,
useReadPnkAllowance,
useReadPnkBalanceOf,
useReadSortitionModuleGetJurorBalance,
} from "./contracts/generated";

interface UsePnkDataParams {
courtId?: string;
}

/**
* @description hook to provide user's pnk data. (pnk balance, pnk allowance, jurorBalance for provided courtId)
* @param param0 optional court Id to fetch juror balance for. Defaults to 0
*/
export const usePnkData = ({ courtId = "0" }: UsePnkDataParams) => {
const { address } = useAccount();
const queryConfig = {
enabled: !isUndefined(address),
refetchInterval: REFETCH_INTERVAL,
};

const { data: balance } = useReadPnkBalanceOf({
query: queryConfig,
args: [address!],
});

const { data: jurorBalance } = useReadSortitionModuleGetJurorBalance({
query: queryConfig,
args: [address ?? "0x", BigInt(courtId)],
});

const { data: allowance, refetch: refetchAllowance } = useReadPnkAllowance({
query: queryConfig,
args: [address ?? "0x", klerosCoreAddress[DEFAULT_CHAIN]],
});

return { balance, jurorBalance, allowance, refetchAllowance };
};
48 changes: 13 additions & 35 deletions web/src/pages/Courts/CourtDetails/StakePanel/InputDisplay.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
import React, { useState, useMemo, useEffect } from "react";
import styled, { css } from "styled-components";
import { landscapeStyle } from "styles/landscapeStyle";

import { useParams } from "react-router-dom";
import { useDebounce } from "react-use";
import { useAccount } from "wagmi";

import { REFETCH_INTERVAL } from "consts/index";

import { useReadSortitionModuleGetJurorBalance, useReadPnkBalanceOf } from "hooks/contracts/generated";
import { useParsedAmount } from "hooks/useParsedAmount";

import { usePnkData } from "hooks/usePNKData";
import { commify, uncommify } from "utils/commify";
import { formatPNK, roundNumberDown } from "utils/format";
import { isUndefined } from "utils/index";

import { landscapeStyle } from "styles/landscapeStyle";

import { NumberInputField } from "components/NumberInputField";

import StakeWithdrawButton, { ActionType } from "./StakeWithdrawButton";

const StyledField = styled(NumberInputField)`
height: fit-content;
input {
border-radius: 3px 0px 0px 3px;
}
`;

const LabelArea = styled.div`
Expand Down Expand Up @@ -62,48 +63,27 @@ const EnsureChainContainer = styled.div`
button {
height: 45px;
border: 1px solid ${({ theme }) => theme.stroke};
border-radius: 0px 3px 3px 0px;
}
`;

interface IInputDisplay {
action: ActionType;
isSending: boolean;
setIsSending: (arg0: boolean) => void;
setIsPopupOpen: (arg0: boolean) => void;
amount: string;
setAmount: (arg0: string) => void;
}

const InputDisplay: React.FC<IInputDisplay> = ({
action,
isSending,
setIsSending,
setIsPopupOpen,
amount,
setAmount,
}) => {
const InputDisplay: React.FC<IInputDisplay> = ({ action, amount, setAmount }) => {
const [debouncedAmount, setDebouncedAmount] = useState("");
const [errorMsg, setErrorMsg] = useState<string | undefined>();
useDebounce(() => setDebouncedAmount(amount), 500, [amount]);
const parsedAmount = useParsedAmount(uncommify(debouncedAmount) as `${number}`);

const { id } = useParams();
const { address } = useAccount();
const { data: balance } = useReadPnkBalanceOf({
query: {
enabled: !isUndefined(address),
refetchInterval: REFETCH_INTERVAL,
},
args: [address ?? "0x"],
});
const { balance, jurorBalance } = usePnkData({ courtId: id });

const parsedBalance = formatPNK(balance ?? 0n, 0, true);
const { data: jurorBalance } = useReadSortitionModuleGetJurorBalance({
query: {
enabled: !isUndefined(address),
refetchInterval: REFETCH_INTERVAL,
},
args: [address ?? "0x", BigInt(id ?? "0")],
});

const parsedStake = formatPNK(jurorBalance?.[2] ?? 0n, 0, true);
const isStaking = useMemo(() => action === ActionType.stake, [action]);

Expand Down Expand Up @@ -147,12 +127,10 @@ const InputDisplay: React.FC<IInputDisplay> = ({
<EnsureChainContainer>
<StakeWithdrawButton
{...{
amount,
parsedAmount,
action,
setAmount,
isSending,
setIsSending,
setIsPopupOpen,
setErrorMsg,
}}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from "react";
import styled from "styled-components";

import Skeleton from "react-loading-skeleton";

import { commify } from "utils/commify";
Expand All @@ -13,6 +14,7 @@ const Container = styled.div`
align-items: center;
flex-wrap: wrap;
gap: 0 8px;
justify-content: center;
`;

const TextWithTooltipContainer = styled.div`
Expand Down Expand Up @@ -48,13 +50,15 @@ interface IQuantityToSimulate {
jurorCurrentSpecificStake: number | undefined;
isStaking: boolean;
amountToStake: number;
className?: string;
}

const QuantityToSimulate: React.FC<IQuantityToSimulate> = ({
isStaking,
jurorCurrentEffectiveStake,
jurorCurrentSpecificStake,
amountToStake,
className,
}) => {
const effectiveStakeDisplay = !isUndefined(jurorCurrentEffectiveStake) ? (
`${commify(jurorCurrentEffectiveStake)} PNK`
Expand Down Expand Up @@ -85,7 +89,7 @@ const QuantityToSimulate: React.FC<IQuantityToSimulate> = ({
);

return (
<Container>
<Container {...{ className }}>
<Quantity>{effectiveStakeDisplay}</Quantity>
<TextWithTooltipContainer>
<WithHelpTooltip
Expand Down
Loading

0 comments on commit 8cde978

Please sign in to comment.