Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

backmerge 12 8 30 #107

Merged
merged 12 commits into from
Aug 30, 2024
11 changes: 11 additions & 0 deletions .changeset/tasty-ties-bow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"create-eth": patch
---

- revert #875 (https://github.com/scaffold-eth/scaffold-eth-2/pull/905)
- Fix typos (https://github.com/scaffold-eth/scaffold-eth-2/pull/906)
- Exclude external links from triggering progress bar ([#909](https://github.com/scaffold-eth/scaffold-eth-2/pull/909))
- Handle tx revert in `useTransactor` (https://github.com/scaffold-eth/scaffold-eth-2/pull/907)
- show blockexplorer link when transaction is reverted (https://github.com/scaffold-eth/scaffold-eth-2/pull/910)
- fix: useScaffoldEventHistory caching (https://github.com/scaffold-eth/scaffold-eth-2/pull/916)
- allow json module imports (https://github.com/scaffold-eth/scaffold-eth-2/pull/921)
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Dispatch, SetStateAction, useEffect, useState } from "react";
import { ContractInput } from "./ContractInput";
import { getFunctionInputKey, getInitalTupleFormState } from "./utilsContract";
import { getFunctionInputKey, getInitialTupleFormState } from "./utilsContract";
import { replacer } from "~~/utils/scaffold-eth/common";
import { AbiParameterTuple } from "~~/utils/scaffold-eth/contract";

Expand All @@ -12,7 +12,7 @@ type TupleProps = {
};

export const Tuple = ({ abiTupleParameter, setParentForm, parentStateObjectKey }: TupleProps) => {
const [form, setForm] = useState<Record<string, any>>(() => getInitalTupleFormState(abiTupleParameter));
const [form, setForm] = useState<Record<string, any>>(() => getInitialTupleFormState(abiTupleParameter));

useEffect(() => {
const values = Object.values(form);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Dispatch, SetStateAction, useEffect, useState } from "react";
import { ContractInput } from "./ContractInput";
import { getFunctionInputKey, getInitalTupleArrayFormState } from "./utilsContract";
import { getFunctionInputKey, getInitialTupleArrayFormState } from "./utilsContract";
import { replacer } from "~~/utils/scaffold-eth/common";
import { AbiParameterTuple } from "~~/utils/scaffold-eth/contract";

Expand All @@ -12,7 +12,7 @@ type TupleArrayProps = {
};

export const TupleArray = ({ abiTupleParameter, setParentForm, parentStateObjectKey }: TupleArrayProps) => {
const [form, setForm] = useState<Record<string, any>>(() => getInitalTupleArrayFormState(abiTupleParameter));
const [form, setForm] = useState<Record<string, any>>(() => getInitialTupleArrayFormState(abiTupleParameter));
const [additionalInputs, setAdditionalInputs] = useState<Array<typeof abiTupleParameter.components>>([
abiTupleParameter.components,
]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ const getInitialFormState = (abiFunction: AbiFunction) => {
return initialForm;
};

const getInitalTupleFormState = (abiTupleParameter: AbiParameterTuple) => {
const getInitialTupleFormState = (abiTupleParameter: AbiParameterTuple) => {
const initialForm: Record<string, any> = {};
if (abiTupleParameter.components.length === 0) return initialForm;

Expand All @@ -97,7 +97,7 @@ const getInitalTupleFormState = (abiTupleParameter: AbiParameterTuple) => {
return initialForm;
};

const getInitalTupleArrayFormState = (abiTupleParameter: AbiParameterTuple) => {
const getInitialTupleArrayFormState = (abiTupleParameter: AbiParameterTuple) => {
const initialForm: Record<string, any> = {};
if (abiTupleParameter.components.length === 0) return initialForm;
abiTupleParameter.components.forEach((component, componentIndex) => {
Expand Down Expand Up @@ -158,7 +158,7 @@ export {
getFunctionInputKey,
getInitialFormState,
getParsedContractFunctionArgs,
getInitalTupleFormState,
getInitalTupleArrayFormState,
getInitialTupleFormState,
getInitialTupleArrayFormState,
transformAbiFunction,
};
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export const AddressInput = ({ value, name, placeholder, onChange, disabled }: C
},
});

const { data: ensAvatar, isLoading: isEnsAvtarLoading } = useEnsAvatar({
const { data: ensAvatar, isLoading: isEnsAvatarLoading } = useEnsAvatar({
name: ensName ? normalize(ensName) : undefined,
chainId: 1,
query: {
Expand Down Expand Up @@ -94,7 +94,7 @@ export const AddressInput = ({ value, name, placeholder, onChange, disabled }: C
prefix={
ensName ? (
<div className="flex bg-base-300 rounded-l-full items-center">
{isEnsAvtarLoading && <div className="skeleton bg-base-200 w-[35px] h-[35px] rounded-full shrink-0"></div>}
{isEnsAvatarLoading && <div className="skeleton bg-base-200 w-[35px] h-[35px] rounded-full shrink-0"></div>}
{ensAvatar ? (
<span className="w-[35px]">
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,12 @@ export function ProgressBar() {
NProgress.configure({ showSpinner: false });

const handleAnchorClick = (event: MouseEvent) => {
const targetUrl = (event.currentTarget as HTMLAnchorElement).href;
const anchor = event.currentTarget as HTMLAnchorElement;
const targetUrl = anchor.href;
const currentUrl = location.href;
if (targetUrl !== currentUrl) {
NProgress.start();
}
const isTargetBlank = anchor?.target === "_blank";
if (targetUrl === currentUrl || isTargetBlank) return;
NProgress.start();
};

const handleMutation: MutationCallback = () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Abi, AbiEvent, ExtractAbiEventNames } from "abitype";
import { BlockNumber, GetLogsParameters } from "viem";
import { Config, UsePublicClientReturnType, useBlockNumber, usePublicClient } from "wagmi";
import { useDeployedContractInfo } from "~~/hooks/scaffold-eth";
import { replacer } from "~~/utils/scaffold-eth/common";
import {
ContractAbi,
ContractName,
Expand Down Expand Up @@ -105,6 +106,7 @@ export const useScaffoldEventHistory = <
eventName,
fromBlock: fromBlock.toString(),
chainId: targetNetwork.id,
filters: JSON.stringify(filters, replacer),
},
],
queryFn: async ({ pageParam }) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { getPublicClient } from "@wagmi/core";
import { Hash, SendTransactionParameters, WalletClient } from "viem";
import { Hash, SendTransactionParameters, TransactionReceipt, WalletClient } from "viem";
import { Config, useWalletClient } from "wagmi";
import { SendTransactionMutate } from "wagmi/query";
import { wagmiConfig } from "~~/services/web3/wagmiConfig";
Expand Down Expand Up @@ -48,6 +48,8 @@ export const useTransactor = (_walletClient?: WalletClient): TransactionFunc =>

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
Expand All @@ -65,18 +67,20 @@ export const useTransactor = (_walletClient?: WalletClient): TransactionFunc =>
}
notification.remove(notificationId);

const blockExplorerTxURL = network ? getBlockExplorerTxLink(network, transactionHash) : "";
blockExplorerTxURL = network ? getBlockExplorerTxLink(network, transactionHash) : "";

notificationId = notification.loading(
<TxnNotification message="Waiting for transaction to complete." blockExplorerLink={blockExplorerTxURL} />,
);

const transactionReceipt = await publicClient.waitForTransactionReceipt({
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} />,
{
Expand All @@ -91,6 +95,13 @@ export const useTransactor = (_walletClient?: WalletClient): TransactionFunc =>
}
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;
}
Expand Down
8 changes: 4 additions & 4 deletions templates/base/packages/nextjs/utils/scaffold-eth/contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,13 +131,13 @@ export type WriteAbiStateMutability = "nonpayable" | "payable";

export type FunctionNamesWithInputs<
TContractName extends ContractName,
TAbiStateMutibility extends AbiStateMutability = AbiStateMutability,
TAbiStateMutability extends AbiStateMutability = AbiStateMutability,
> = Exclude<
Extract<
ContractAbi<TContractName>[number],
{
type: "function";
stateMutability: TAbiStateMutibility;
stateMutability: TAbiStateMutability;
}
>,
{
Expand All @@ -149,14 +149,14 @@ type Expand<T> = T extends object ? (T extends infer O ? { [K in keyof O]: O[K]

type UnionToIntersection<U> = Expand<(U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never>;

type OptionalTupple<T> = T extends readonly [infer H, ...infer R] ? readonly [H | undefined, ...OptionalTupple<R>] : T;
type OptionalTuple<T> = T extends readonly [infer H, ...infer R] ? readonly [H | undefined, ...OptionalTuple<R>] : T;

type UseScaffoldArgsParam<
TContractName extends ContractName,
TFunctionName extends ExtractAbiFunctionNames<ContractAbi<TContractName>>,
> = TFunctionName extends FunctionNamesWithInputs<TContractName>
? {
args: OptionalTupple<UnionToIntersection<AbiFunctionArguments<ContractAbi<TContractName>, TFunctionName>>>;
args: OptionalTuple<UnionToIntersection<AbiFunctionArguments<ContractAbi<TContractName>, TFunctionName>>>;
value?: ExtractAbiFunction<ContractAbi<TContractName>, TFunctionName>["stateMutability"] extends "payable"
? bigint | undefined
: undefined;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"target": "es2020",
"module": "commonjs",
"esModuleInterop": true,
"resolveJsonModule": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
Expand Down
Loading