Skip to content

Commit

Permalink
Encapsulating all remaining transactions into useTransactionManager
Browse files Browse the repository at this point in the history
  • Loading branch information
brickpop committed Aug 29, 2024
1 parent 8fa14fb commit 99a7885
Show file tree
Hide file tree
Showing 13 changed files with 203 additions and 561 deletions.
53 changes: 13 additions & 40 deletions plugins/lockToVote/hooks/useCreateProposal.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import { useState } from "react";
import { ProposalMetadata, RawAction } from "@/utils/types";
import { useWaitForTransactionReceipt, useWriteContract } from "wagmi";
import { useAlerts } from "@/context/Alerts";
import { PUB_APP_NAME, PUB_CHAIN, PUB_LOCK_TO_VOTE_PLUGIN_ADDRESS, PUB_PROJECT_URL } from "@/constants";
import { uploadToPinata } from "@/utils/ipfs";
import { LockToVetoPluginAbi } from "../artifacts/LockToVetoPlugin.sol";
import { URL_PATTERN } from "@/utils/input-values";
import { toHex } from "viem";
import { useTransactionManager } from "@/hooks/useTransactionManager";

const UrlRegex = new RegExp(URL_PATTERN);

Expand All @@ -22,45 +22,18 @@ export function useCreateProposal() {
const [resources, setResources] = useState<{ name: string; url: string }[]>([
{ name: PUB_APP_NAME, url: PUB_PROJECT_URL },
]);
const { writeContract: createProposalWrite, data: createTxHash, error, status } = useWriteContract();
const { isLoading: isConfirming, isSuccess: isConfirmed } = useWaitForTransactionReceipt({ hash: createTxHash });

useEffect(() => {
if (status === "idle" || status === "pending") return;
else if (status === "error") {
if (error?.message?.startsWith("User rejected the request")) {
addAlert("The transaction signature was declined", {
description: "Nothing will be sent to the network",
timeout: 4 * 1000,
});
} else {
console.error(error);
addAlert("Could not create the proposal", { type: "error" });
}
setIsCreating(false);
return;
}

// success
if (!createTxHash) return;
else if (isConfirming) {
addAlert("Proposal submitted", {
description: "Waiting for the transaction to be validated",
txHash: createTxHash,
});
return;
} else if (!isConfirmed) return;

addAlert("Proposal created", {
description: "The transaction has been validated",
type: "success",
txHash: createTxHash,
});
setTimeout(() => {
push("#/");
window.scroll(0, 0);
}, 1000 * 2);
}, [status, createTxHash, isConfirming, isConfirmed]);
const { writeContract: createProposalWrite, isConfirming } = useTransactionManager({
onSuccessMessage: "Proposal created",
onSuccess() {
setTimeout(() => {
push("#/");
window.scroll(0, 0);
}, 1000 * 2);
},
onErrorMessage: "Could not create the proposal",
onError: () => setIsCreating(false),
});

const submitProposal = async () => {
// Check metadata
Expand Down
76 changes: 21 additions & 55 deletions plugins/lockToVote/hooks/useProposalClaimLock.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
import { useEffect } from "react";
import { useAccount, useReadContract, useWaitForTransactionReceipt, useWriteContract } from "wagmi";
import { AlertContextProps, useAlerts } from "@/context/Alerts";
import { useRouter } from "next/router";
import { PUB_CHAIN, PUB_LOCK_TO_VOTE_PLUGIN_ADDRESS } from "@/constants";
import { LockToVetoPluginAbi } from "../artifacts/LockToVetoPlugin.sol";
import { useTransactionManager } from "@/hooks/useTransactionManager";
import { useState } from "react";

export function useProposalClaimLock(proposalIdx: number) {
const { reload } = useRouter();
const account = useAccount();
const { addAlert } = useAlerts() as AlertContextProps;
const [isClaiming, setIsClaiming] = useState(false);

const {
data: hasClaimed,
isError: isCanVoteError,
isLoading: isCanVoteLoading,
} = useReadContract({
const { data: hasClaimed } = useReadContract({
address: PUB_LOCK_TO_VOTE_PLUGIN_ADDRESS,
abi: LockToVetoPluginAbi,
chainId: PUB_CHAIN.id,
Expand All @@ -24,19 +20,26 @@ export function useProposalClaimLock(proposalIdx: number) {
enabled: !!account.address,
},
});
const {
writeContract: claimLockWrite,
data: executeTxHash,
error: executingError,
status: claimingStatus,
} = useWriteContract();
const { isLoading: isConfirming, isSuccess: isConfirmed } = useWaitForTransactionReceipt({ hash: executeTxHash });

const { writeContract, isConfirming, isConfirmed } = useTransactionManager({
onSuccessMessage: "Claim executed",
onSuccess() {
reload();
setIsClaiming(false);
},
onErrorMessage: "Could not claim the locked tokens",
onErrorDescription: "Please get in touch with us",
onError() {
setIsClaiming(false);
},
});

const claimLockProposal = () => {
if (hasClaimed) return;

console.log(proposalIdx, account.address);
claimLockWrite({
setIsClaiming(true);

writeContract({
chainId: PUB_CHAIN.id,
abi: LockToVetoPluginAbi,
address: PUB_LOCK_TO_VOTE_PLUGIN_ADDRESS,
Expand All @@ -45,47 +48,10 @@ export function useProposalClaimLock(proposalIdx: number) {
});
};

useEffect(() => {
if (claimingStatus === "idle" || claimingStatus === "pending") return;
else if (claimingStatus === "error") {
if (executingError?.message?.startsWith("User rejected the request")) {
addAlert("Transaction rejected by the user", {
timeout: 4 * 1000,
});
} else {
console.error(executingError);
addAlert("Could not claim locked tokens", {
type: "error",
description: "The proposal may contain actions with invalid operations. Please get in contact with us.",
});
}
return;
}

// success
if (!executeTxHash) return;
else if (isConfirming) {
addAlert("Claim submitted", {
description: "Waiting for the transaction to be validated",
type: "info",
txHash: executeTxHash,
});
return;
} else if (!isConfirmed) return;

addAlert("Claim executed", {
description: "The transaction has been validated",
type: "success",
txHash: executeTxHash,
});

setTimeout(() => reload(), 1000 * 2);
}, [claimingStatus, executeTxHash, isConfirming, isConfirmed]);

return {
claimLockProposal,
hasClaimed: !!hasClaimed,
isConfirming,
isConfirming: isConfirming || isClaiming,
isConfirmed,
};
}
67 changes: 16 additions & 51 deletions plugins/lockToVote/hooks/useProposalExecute.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { useEffect, useState } from "react";
import { useReadContract, useWaitForTransactionReceipt, useWriteContract } from "wagmi";
import { AlertContextProps, useAlerts } from "@/context/Alerts";
import { useState } from "react";
import { useReadContract } from "wagmi";
import { useRouter } from "next/router";
import { PUB_CHAIN, PUB_LOCK_TO_VOTE_PLUGIN_ADDRESS } from "@/constants";
import { LockToVetoPluginAbi } from "../artifacts/LockToVetoPlugin.sol";
import { useTransactionManager } from "@/hooks/useTransactionManager";

export function useProposalExecute(proposalIdx: number) {
const { reload } = useRouter();
const { addAlert } = useAlerts() as AlertContextProps;
const [isExecuting, setIsExecuting] = useState(false);

const {
Expand All @@ -21,21 +20,26 @@ export function useProposalExecute(proposalIdx: number) {
functionName: "canExecute",
args: [BigInt(proposalIdx)],
});
const {
writeContract: executeWrite,
data: executeTxHash,
error: executingError,
status: executingStatus,
} = useWriteContract();
const { isLoading: isConfirming, isSuccess: isConfirmed } = useWaitForTransactionReceipt({ hash: executeTxHash });

const { writeContract, isConfirming, isConfirmed } = useTransactionManager({
onSuccessMessage: "Proposal executed",
onSuccess() {
setTimeout(() => reload(), 1000 * 2);
},
onErrorMessage: "Could not execute the proposal",
onErrorDescription: "The proposal may contain actions with invalid operations",
onError() {
setIsExecuting(false);
},
});

const executeProposal = () => {
if (!canExecute) return;
else if (typeof proposalIdx === "undefined") return;

setIsExecuting(true);

executeWrite({
writeContract({
chainId: PUB_CHAIN.id,
abi: LockToVetoPluginAbi,
address: PUB_LOCK_TO_VOTE_PLUGIN_ADDRESS,
Expand All @@ -44,45 +48,6 @@ export function useProposalExecute(proposalIdx: number) {
});
};

useEffect(() => {
if (executingStatus === "idle" || executingStatus === "pending") return;
else if (executingStatus === "error") {
if (executingError?.message?.startsWith("User rejected the request")) {
addAlert("The transaction signature was declined", {
description: "Nothing will be sent to the network",
timeout: 4 * 1000,
});
} else {
console.error(executingError);
addAlert("Could not execute the proposal", {
type: "error",
description: "The proposal may contain actions with invalid operations",
});
}
setIsExecuting(false);
return;
}

// success
if (!executeTxHash) return;
else if (isConfirming) {
addAlert("Transaction submitted", {
description: "Waiting for the transaction to be validated",
type: "info",
txHash: executeTxHash,
});
return;
} else if (!isConfirmed) return;

addAlert("Proposal executed", {
description: "The transaction has been validated",
type: "success",
txHash: executeTxHash,
});

setTimeout(() => reload(), 1000 * 2);
}, [executingStatus, executeTxHash, isConfirming, isConfirmed]);

return {
executeProposal,
canExecute: !isCanVoteError && !isCanVoteLoading && !isConfirmed && !!canExecute,
Expand Down
70 changes: 22 additions & 48 deletions plugins/lockToVote/hooks/useProposalVeto.ts
Original file line number Diff line number Diff line change
@@ -1,69 +1,43 @@
import { useEffect } from "react";
import { usePublicClient, useWaitForTransactionReceipt, useWriteContract, useReadContract, useAccount } from "wagmi";
import { useReadContract, useAccount } from "wagmi";
import { Address } from "viem";
import { ERC20PermitAbi } from "@/artifacts/ERC20Permit.sol";
import { useProposal } from "./useProposal";
import { useProposalVetoes } from "./useProposalVetoes";
import { useUserCanVeto } from "./useUserCanVeto";
import { LockToVetoPluginAbi } from "../artifacts/LockToVetoPlugin.sol";
import { usePermit } from "@/hooks/usePermit";
import { useAlerts, AlertContextProps } from "@/context/Alerts";
import { PUB_CHAIN, PUB_TOKEN_ADDRESS, PUB_LOCK_TO_VOTE_PLUGIN_ADDRESS } from "@/constants";
import { PUB_TOKEN_ADDRESS, PUB_LOCK_TO_VOTE_PLUGIN_ADDRESS } from "@/constants";
import { useTransactionManager } from "@/hooks/useTransactionManager";
import { ADDRESS_ZERO } from "@/utils/evm";

export function useProposalVeto(proposalId: number) {
const publicClient = usePublicClient({ chainId: PUB_CHAIN.id });

const { proposal, status: proposalFetchStatus, refetch: refetchProposal } = useProposal(proposalId, true);
const vetoes = useProposalVetoes(publicClient!, PUB_LOCK_TO_VOTE_PLUGIN_ADDRESS, proposalId, proposal);
const vetoes = useProposalVetoes(PUB_LOCK_TO_VOTE_PLUGIN_ADDRESS, proposalId, proposal);
const { signPermit, refetchPermitData } = usePermit();

const { addAlert } = useAlerts() as AlertContextProps;
const account_address = useAccount().address!;
const { address } = useAccount();

const { data: balanceData } = useReadContract({
address: PUB_TOKEN_ADDRESS,
abi: ERC20PermitAbi,
functionName: "balanceOf",
args: [account_address],
args: [address || ADDRESS_ZERO],
});

const { writeContract: vetoWrite, data: vetoTxHash, error: vetoingError, status: vetoingStatus } = useWriteContract();
const { isLoading: isConfirming, isSuccess: isConfirmed } = useWaitForTransactionReceipt({ hash: vetoTxHash });
const { canVeto, refetch: refetchCanVeto } = useUserCanVeto(proposalId);

useEffect(() => {
if (vetoingStatus === "idle" || vetoingStatus === "pending") return;
else if (vetoingStatus === "error") {
if (vetoingError?.message?.startsWith("User rejected the request")) {
addAlert("Transaction rejected by the user", {
timeout: 4 * 1000,
});
} else {
console.error(vetoingError);
addAlert("Could not create the veto", { type: "error" });
}
return;
}

// success
if (!vetoTxHash) return;
else if (isConfirming) {
addAlert("Veto submitted", {
description: "Waiting for the transaction to be validated",
txHash: vetoTxHash,
});
return;
} else if (!isConfirmed) return;

addAlert("Veto registered", {
description: "The transaction has been validated",
type: "success",
txHash: vetoTxHash,
});
refetchCanVeto();
refetchProposal();
refetchPermitData();
}, [vetoingStatus, vetoTxHash, isConfirming, isConfirmed]);
const {
writeContract,
status: vetoingStatus,
isConfirming,
isConfirmed,
} = useTransactionManager({
onSuccessMessage: "Veto registered",
onSuccess() {
refetchCanVeto();
refetchProposal();
refetchPermitData();
},
onErrorMessage: "Could not submit the veto",
});

const vetoProposal = () => {
const dest: Address = PUB_LOCK_TO_VOTE_PLUGIN_ADDRESS;
Expand All @@ -73,7 +47,7 @@ export function useProposalVeto(proposalId: number) {
signPermit(dest, value, deadline).then((sig) => {
if (!sig?.yParity) throw new Error("Invalid signature");

vetoWrite({
writeContract({
abi: LockToVetoPluginAbi,
address: dest,
functionName: "vetoPermit",
Expand Down
Loading

0 comments on commit 99a7885

Please sign in to comment.