Initial commit with 🏗️ Scaffold-ETH 2 @ 1.0.2
This commit is contained in:
113
packages/nextjs/hooks/scaffold-eth/useTransactor.tsx
Normal file
113
packages/nextjs/hooks/scaffold-eth/useTransactor.tsx
Normal file
@@ -0,0 +1,113 @@
|
||||
import { Hash, SendTransactionParameters, TransactionReceipt, WalletClient } from "viem";
|
||||
import { Config, useWalletClient } from "wagmi";
|
||||
import { getPublicClient } from "wagmi/actions";
|
||||
import { SendTransactionMutate } from "wagmi/query";
|
||||
import { wagmiConfig } from "~~/services/web3/wagmiConfig";
|
||||
import { getBlockExplorerTxLink, getParsedError, notification } from "~~/utils/scaffold-eth";
|
||||
import { TransactorFuncOptions } from "~~/utils/scaffold-eth/contract";
|
||||
|
||||
type TransactionFunc = (
|
||||
tx: (() => Promise<Hash>) | Parameters<SendTransactionMutate<Config, undefined>>[0],
|
||||
options?: TransactorFuncOptions,
|
||||
) => Promise<Hash | undefined>;
|
||||
|
||||
/**
|
||||
* Custom notification content for TXs.
|
||||
*/
|
||||
const TxnNotification = ({ message, blockExplorerLink }: { message: string; blockExplorerLink?: string }) => {
|
||||
return (
|
||||
<div className={`flex flex-col ml-1 cursor-default`}>
|
||||
<p className="my-0">{message}</p>
|
||||
{blockExplorerLink && blockExplorerLink.length > 0 ? (
|
||||
<a href={blockExplorerLink} target="_blank" rel="noreferrer" className="block link">
|
||||
check out transaction
|
||||
</a>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Runs Transaction passed in to returned function showing UI feedback.
|
||||
* @param _walletClient - Optional wallet client to use. If not provided, will use the one from useWalletClient.
|
||||
* @returns function that takes in transaction function as callback, shows UI feedback for transaction and returns a promise of the transaction hash
|
||||
*/
|
||||
export const useTransactor = (_walletClient?: WalletClient): TransactionFunc => {
|
||||
let walletClient = _walletClient;
|
||||
const { data } = useWalletClient();
|
||||
if (walletClient === undefined && data) {
|
||||
walletClient = data;
|
||||
}
|
||||
|
||||
const result: TransactionFunc = async (tx, options) => {
|
||||
if (!walletClient) {
|
||||
notification.error("Cannot access account");
|
||||
console.error("⚡️ ~ file: useTransactor.tsx ~ error");
|
||||
return;
|
||||
}
|
||||
|
||||
let notificationId = null;
|
||||
let transactionHash: Hash | undefined = undefined;
|
||||
let transactionReceipt: TransactionReceipt | undefined;
|
||||
let blockExplorerTxURL = "";
|
||||
try {
|
||||
const network = await walletClient.getChainId();
|
||||
// Get full transaction from public client
|
||||
const publicClient = getPublicClient(wagmiConfig);
|
||||
|
||||
notificationId = notification.loading(<TxnNotification message="Awaiting for user confirmation" />);
|
||||
if (typeof tx === "function") {
|
||||
// Tx is already prepared by the caller
|
||||
const result = await tx();
|
||||
transactionHash = result;
|
||||
} else if (tx != null) {
|
||||
transactionHash = await walletClient.sendTransaction(tx as SendTransactionParameters);
|
||||
} else {
|
||||
throw new Error("Incorrect transaction passed to transactor");
|
||||
}
|
||||
notification.remove(notificationId);
|
||||
|
||||
blockExplorerTxURL = network ? getBlockExplorerTxLink(network, transactionHash) : "";
|
||||
|
||||
notificationId = notification.loading(
|
||||
<TxnNotification message="Waiting for transaction to complete." blockExplorerLink={blockExplorerTxURL} />,
|
||||
);
|
||||
|
||||
transactionReceipt = await publicClient.waitForTransactionReceipt({
|
||||
hash: transactionHash,
|
||||
confirmations: options?.blockConfirmations,
|
||||
});
|
||||
notification.remove(notificationId);
|
||||
|
||||
if (transactionReceipt.status === "reverted") throw new Error("Transaction reverted");
|
||||
|
||||
notification.success(
|
||||
<TxnNotification message="Transaction completed successfully!" blockExplorerLink={blockExplorerTxURL} />,
|
||||
{
|
||||
icon: "🎉",
|
||||
},
|
||||
);
|
||||
|
||||
if (options?.onBlockConfirmation) options.onBlockConfirmation(transactionReceipt);
|
||||
} catch (error: any) {
|
||||
if (notificationId) {
|
||||
notification.remove(notificationId);
|
||||
}
|
||||
console.error("⚡️ ~ file: useTransactor.ts ~ error", error);
|
||||
const message = getParsedError(error);
|
||||
|
||||
// if receipt was reverted, show notification with block explorer link and return error
|
||||
if (transactionReceipt?.status === "reverted") {
|
||||
notification.error(<TxnNotification message={message} blockExplorerLink={blockExplorerTxURL} />);
|
||||
throw error;
|
||||
}
|
||||
|
||||
notification.error(message);
|
||||
throw error;
|
||||
}
|
||||
|
||||
return transactionHash;
|
||||
};
|
||||
|
||||
return result;
|
||||
};
|
||||
Reference in New Issue
Block a user