diff --git a/web/src/pages/Cases/CaseDetails/Appeal/Classic/Fund.tsx b/web/src/pages/Cases/CaseDetails/Appeal/Classic/Fund.tsx index ad68c1a71..3888b2b25 100644 --- a/web/src/pages/Cases/CaseDetails/Appeal/Classic/Fund.tsx +++ b/web/src/pages/Cases/CaseDetails/Appeal/Classic/Fund.tsx @@ -1,7 +1,7 @@ import React, { useState } from "react"; import styled from "styled-components"; import { useParams } from "react-router-dom"; -import { useAccount, useBalance } from "wagmi"; +import { useAccount, useBalance, usePublicClient } from "wagmi"; import { useDebounce } from "react-use"; import { Field, Button } from "@kleros/ui-components-library"; import { wrapWithToast } from "utils/wrapWithToast"; @@ -49,6 +49,7 @@ const Fund: React.FC = () => { address, watch: true, }); + const publicClient = usePublicClient(); const [amount, setAmount] = useState(""); const [debouncedAmount, setDebouncedAmount] = useState(""); @@ -78,7 +79,7 @@ const Fund: React.FC = () => { onClick={() => { if (fundAppeal) { setIsSending(true); - wrapWithToast(fundAppeal()) + wrapWithToast(async () => await fundAppeal().then((response) => response.hash), publicClient) .then(() => { setAmount(""); close(); diff --git a/web/src/pages/Cases/CaseDetails/Evidence/SubmitEvidenceModal.tsx b/web/src/pages/Cases/CaseDetails/Evidence/SubmitEvidenceModal.tsx index abedd2980..9eab0e452 100644 --- a/web/src/pages/Cases/CaseDetails/Evidence/SubmitEvidenceModal.tsx +++ b/web/src/pages/Cases/CaseDetails/Evidence/SubmitEvidenceModal.tsx @@ -5,7 +5,7 @@ import Modal from "react-modal"; import { Textarea, Button } from "@kleros/ui-components-library"; import { wrapWithToast, OPTIONS as toastOptions } from "utils/wrapWithToast"; import { uploadFormDataToIPFS } from "utils/uploadFormDataToIPFS"; -import { useWalletClient } from "wagmi"; +import { useWalletClient, usePublicClient } from "wagmi"; import { EnsureChain } from "components/EnsureChain"; import { prepareWriteDisputeKitClassic } from "hooks/contracts/generated"; @@ -15,6 +15,7 @@ const SubmitEvidenceModal: React.FC<{ close: () => void; }> = ({ isOpen, evidenceGroup, close }) => { const { data: walletClient } = useWalletClient(); + const publicClient = usePublicClient(); const [isSending, setIsSending] = useState(false); const [message, setMessage] = useState(""); return ( @@ -41,10 +42,12 @@ const SubmitEvidenceModal: React.FC<{ functionName: "submitEvidence", args: [BigInt(evidenceGroup), cid], }); - await wrapWithToast(walletClient.writeContract(request)).then(() => { - setMessage(""); - close(); - }); + await wrapWithToast(async () => await walletClient.writeContract(request), publicClient).then( + () => { + setMessage(""); + close(); + } + ); } }) .catch() diff --git a/web/src/pages/Cases/CaseDetails/Voting/Binary.tsx b/web/src/pages/Cases/CaseDetails/Voting/Binary.tsx index 7e341ac4e..3930271ea 100644 --- a/web/src/pages/Cases/CaseDetails/Voting/Binary.tsx +++ b/web/src/pages/Cases/CaseDetails/Voting/Binary.tsx @@ -1,7 +1,7 @@ import React, { useMemo, useState } from "react"; import styled from "styled-components"; import { useParams } from "react-router-dom"; -import { useWalletClient } from "wagmi"; +import { useWalletClient, usePublicClient } from "wagmi"; import { Button, Textarea } from "@kleros/ui-components-library"; import { prepareWriteDisputeKitClassic } from "hooks/contracts/generated"; import { wrapWithToast } from "utils/wrapWithToast"; @@ -54,6 +54,7 @@ const Binary: React.FC<{ arbitrable: `0x${string}`; voteIDs: string[] }> = ({ ar const [isSending, setIsSending] = useState(false); const [justification, setJustification] = useState(""); const { data: walletClient } = useWalletClient(); + const publicClient = usePublicClient(); const handleVote = async (voteOption: number) => { setIsSending(true); @@ -69,7 +70,7 @@ const Binary: React.FC<{ arbitrable: `0x${string}`; voteIDs: string[] }> = ({ ar ], }); if (walletClient) { - wrapWithToast(walletClient.writeContract(request)).finally(() => { + wrapWithToast(async () => await walletClient.writeContract(request), publicClient).finally(() => { setChosenOption(-1); setIsSending(false); }); diff --git a/web/src/pages/Courts/CourtDetails/StakePanel/InputDisplay.tsx b/web/src/pages/Courts/CourtDetails/StakePanel/InputDisplay.tsx index 7ce8f0185..f969070ec 100644 --- a/web/src/pages/Courts/CourtDetails/StakePanel/InputDisplay.tsx +++ b/web/src/pages/Courts/CourtDetails/StakePanel/InputDisplay.tsx @@ -8,8 +8,9 @@ import { Field } from "@kleros/ui-components-library"; import { useParsedAmount } from "hooks/useParsedAmount"; import { usePNKBalance } from "queries/usePNKBalance"; -import { useJurorBalance } from "queries/useJurorBalance"; +import { useKlerosCoreGetJurorBalance } from "hooks/contracts/generated"; import StakeWithdrawButton, { ActionType } from "./StakeWithdrawButton"; +import { isUndefined } from "utils/index"; import { EnsureChain } from "components/EnsureChain"; const StyledField = styled(Field)` @@ -50,7 +51,11 @@ const InputDisplay: React.FC = ({ action, isSending, setIsSending const { address } = useAccount(); const { data: balance } = usePNKBalance(address); const parsedBalance = formatEther(balance ?? 0n); - const { data: jurorBalance } = useJurorBalance(address, id); + const { data: jurorBalance } = useKlerosCoreGetJurorBalance({ + enabled: !isUndefined(address), + args: [address, id], + watch: true, + }); const parsedStake = formatEther(jurorBalance?.[0] || 0n); const isStaking = action === ActionType.stake; diff --git a/web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsx b/web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsx index deb02174c..3c94541d8 100644 --- a/web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsx +++ b/web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsx @@ -1,6 +1,6 @@ import React, { useMemo } from "react"; import { useParams } from "react-router-dom"; -import { useAccount } from "wagmi"; +import { useAccount, usePublicClient } from "wagmi"; import { Button } from "@kleros/ui-components-library"; import { getKlerosCore, @@ -9,8 +9,8 @@ import { usePnkBalanceOf, usePnkIncreaseAllowance, usePreparePnkIncreaseAllowance, + useKlerosCoreGetJurorBalance, } from "hooks/contracts/generated"; -import { useJurorBalance } from "queries/useJurorBalance"; import { usePNKAllowance } from "queries/usePNKAllowance"; import { wrapWithToast } from "utils/wrapWithToast"; import { isUndefined } from "utils/index"; @@ -38,34 +38,44 @@ const StakeWithdrawButton: React.FC = ({ parsedAmount, action, se args: [address!], watch: true, }); - const { data: jurorBalance } = useJurorBalance(address, id); + const { data: jurorBalance } = useKlerosCoreGetJurorBalance({ + enabled: !isUndefined(address), + args: [address ?? "0x", BigInt(id ?? 0)], + watch: true, + }); const { data: allowance } = usePNKAllowance(address); + const publicClient = usePublicClient(); const isStaking = action === ActionType.stake; - const isAllowance = isStaking && allowance && allowance < parsedAmount; + const isAllowance = isStaking && !isUndefined(allowance) && allowance < parsedAmount; const targetStake = useMemo(() => { if (jurorBalance) { - if (action === ActionType.stake) { + if (isAllowance) { + return parsedAmount; + } else if (isStaking) { return jurorBalance[0] + parsedAmount; } else { return jurorBalance[0] - parsedAmount; } } - }, [action, jurorBalance, parsedAmount]); + return 0n; + }, [jurorBalance, parsedAmount, isAllowance, isStaking]); const klerosCore = getKlerosCore({}); const { config: increaseAllowanceConfig } = usePreparePnkIncreaseAllowance({ - enabled: !isUndefined([klerosCore, targetStake, allowance]), + enabled: isAllowance && !isUndefined(klerosCore) && !isUndefined(targetStake) && !isUndefined(allowance), args: [klerosCore?.address, BigInt(targetStake ?? 0) - BigInt(allowance ?? 0)], }); const { writeAsync: increaseAllowance } = usePnkIncreaseAllowance(increaseAllowanceConfig); const handleAllowance = () => { if (!isUndefined(increaseAllowance)) { setIsSending(true); - wrapWithToast(increaseAllowance!()).finally(() => { - setIsSending(false); - }); + wrapWithToast(async () => await increaseAllowance().then((response) => response.hash), publicClient).finally( + () => { + setIsSending(false); + } + ); } }; @@ -77,7 +87,7 @@ const StakeWithdrawButton: React.FC = ({ parsedAmount, action, se const handleStake = () => { if (typeof setStake !== "undefined") { setIsSending(true); - wrapWithToast(setStake()) + wrapWithToast(async () => await setStake().then((response) => response.hash), publicClient) .then(() => { setAmount(""); }) diff --git a/web/src/utils/wrapWithToast.ts b/web/src/utils/wrapWithToast.ts index d26e228b4..4ee577ed0 100644 --- a/web/src/utils/wrapWithToast.ts +++ b/web/src/utils/wrapWithToast.ts @@ -11,11 +11,12 @@ export const OPTIONS = { theme: "colored" as Theme, }; -export async function wrapWithToast(tx: Promise) { +export async function wrapWithToast(contractWrite: () => Promise<`0x${string}`>, publicClient: any) { toast.info("Transaction initiated", OPTIONS); - await tx - .then(async (tx) => { - await tx.wait(2); + const hash = await contractWrite(); + await publicClient + .waitForTransactionReceipt({ hash, confirmations: 2 }) + .then(() => { toast.success("Transaction mined!", OPTIONS); }) .catch((error) => {