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

Optional chain parameter in Scaffold hooks #931

Merged
merged 18 commits into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions packages/nextjs/hooks/scaffold-eth/useDeployedContractInfo.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
import { useEffect, useState } from "react";
import { useTargetNetwork } from "./useTargetNetwork";
import { useIsMounted } from "usehooks-ts";
import { Chain } from "viem";
import { usePublicClient } from "wagmi";
import { Contract, ContractCodeStatus, ContractName, contracts } from "~~/utils/scaffold-eth/contract";

/**
* Gets the matching contract info for the provided contract name from the contracts present in deployedContracts.ts
* and externalContracts.ts corresponding to targetNetworks configured in scaffold.config.ts
*/
export const useDeployedContractInfo = <TContractName extends ContractName>(contractName: TContractName) => {
export const useDeployedContractInfo = <TContractName extends ContractName>(
contractName: TContractName,
chain?: Chain,
) => {
const isMounted = useIsMounted();
const { targetNetwork } = useTargetNetwork();
const deployedContract = contracts?.[targetNetwork.id]?.[contractName as ContractName] as Contract<TContractName>;
const selectedChain = chain ?? targetNetwork;

const deployedContract = contracts?.[selectedChain.id]?.[contractName as ContractName] as Contract<TContractName>;
const [status, setStatus] = useState<ContractCodeStatus>(ContractCodeStatus.LOADING);
const publicClient = usePublicClient({ chainId: targetNetwork.id });
const publicClient = usePublicClient({ chainId: selectedChain.id });

useEffect(() => {
const checkContractDeployment = async () => {
Expand Down
4 changes: 2 additions & 2 deletions packages/nextjs/hooks/scaffold-eth/useNetworkColor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ export function getNetworkColor(network: ChainWithAttributes, isDarkMode: boolea
/**
* Gets the color of the target network
*/
export const useNetworkColor = () => {
export const useNetworkColor = (chain?: ChainWithAttributes) => {
const { resolvedTheme } = useTheme();
const { targetNetwork } = useTargetNetwork();

const isDarkMode = resolvedTheme === "dark";

return getNetworkColor(targetNetwork, isDarkMode);
return getNetworkColor(chain ? chain : targetNetwork, isDarkMode);
rin-st marked this conversation as resolved.
Show resolved Hide resolved
};
12 changes: 10 additions & 2 deletions packages/nextjs/hooks/scaffold-eth/useScaffoldContract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,21 @@ export const useScaffoldContract = <
>({
contractName,
walletClient,
chain,
}: {
contractName: TContractName;
walletClient?: TWalletClient | null;
chain?: Chain;
}) => {
const { data: deployedContractData, isLoading: deployedContractLoading } = useDeployedContractInfo(contractName);
const { targetNetwork } = useTargetNetwork();
const publicClient = usePublicClient({ chainId: targetNetwork.id });
const selectedChain = chain ?? targetNetwork;

const { data: deployedContractData, isLoading: deployedContractLoading } = useDeployedContractInfo(
contractName,
selectedChain,
);

const publicClient = usePublicClient({ chainId: selectedChain?.id });

let contract = undefined;
if (deployedContractData && publicClient) {
Expand Down
11 changes: 7 additions & 4 deletions packages/nextjs/hooks/scaffold-eth/useScaffoldEventHistory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export const useScaffoldEventHistory = <
contractName,
eventName,
fromBlock,
chain,
filters,
blockData,
transactionData,
Expand All @@ -82,14 +83,16 @@ export const useScaffoldEventHistory = <
enabled = true,
}: UseScaffoldEventHistoryConfig<TContractName, TEventName, TBlockData, TTransactionData, TReceiptData>) => {
const { targetNetwork } = useTargetNetwork();
const selectedChain = chain ?? targetNetwork;

const publicClient = usePublicClient({
chainId: targetNetwork.id,
chainId: selectedChain.id,
});
const [isFirstRender, setIsFirstRender] = useState(true);

const { data: blockNumber } = useBlockNumber({ watch: watch, chainId: targetNetwork.id });
const { data: blockNumber } = useBlockNumber({ watch: watch, chainId: selectedChain.id });

const { data: deployedContractData } = useDeployedContractInfo(contractName);
const { data: deployedContractData } = useDeployedContractInfo(contractName, selectedChain);

const event =
deployedContractData &&
Expand All @@ -105,7 +108,7 @@ export const useScaffoldEventHistory = <
address: deployedContractData?.address,
eventName,
fromBlock: fromBlock.toString(),
chainId: targetNetwork.id,
chainId: selectedChain.id,
filters: JSON.stringify(filters, replacer),
},
],
Expand Down
9 changes: 6 additions & 3 deletions packages/nextjs/hooks/scaffold-eth/useScaffoldReadContract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,19 @@ export const useScaffoldReadContract = <
contractName,
functionName,
args,
chain,
...readConfig
}: UseScaffoldReadConfig<TContractName, TFunctionName>) => {
const { data: deployedContract } = useDeployedContractInfo(contractName);
const { targetNetwork } = useTargetNetwork();
const selectedChain = chain ?? targetNetwork;
const { data: deployedContract } = useDeployedContractInfo(contractName, selectedChain);

const { query: queryOptions, watch, ...readContractConfig } = readConfig;
// set watch to true by default
const defaultWatch = watch ?? true;

const readContractHookRes = useReadContract({
chainId: targetNetwork.id,
chainId: selectedChain.id,
functionName,
address: deployedContract?.address,
abi: deployedContract?.abi,
Expand All @@ -56,7 +59,7 @@ export const useScaffoldReadContract = <
const queryClient = useQueryClient();
const { data: blockNumber } = useBlockNumber({
watch: defaultWatch,
chainId: targetNetwork.id,
chainId: selectedChain.id,
query: {
enabled: defaultWatch,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,20 @@ export const useScaffoldWatchContractEvent = <
>({
contractName,
eventName,
chain,
onLogs,
}: UseScaffoldEventConfig<TContractName, TEventName>) => {
const { data: deployedContractData } = useDeployedContractInfo(contractName);
const { targetNetwork } = useTargetNetwork();
const selectedChain = chain ?? targetNetwork;
const { data: deployedContractData } = useDeployedContractInfo(contractName, selectedChain);

const addIndexedArgsToLogs = (logs: Log[]) => logs.map(addIndexedArgsToEvent);
const listenerWithIndexedArgs = (logs: Log[]) => onLogs(addIndexedArgsToLogs(logs) as Parameters<typeof onLogs>[0]);

return useWatchContractEvent({
address: deployedContractData?.address,
abi: deployedContractData?.abi as Abi,
chainId: targetNetwork.id,
chainId: selectedChain.id,
onLogs: listenerWithIndexedArgs,
eventName,
});
Expand Down
22 changes: 14 additions & 8 deletions packages/nextjs/hooks/scaffold-eth/useScaffoldWriteContract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useState } from "react";
import { useTargetNetwork } from "./useTargetNetwork";
import { MutateOptions } from "@tanstack/react-query";
import { Abi, ExtractAbiFunctionNames } from "abitype";
import { Chain } from "viem";
import { Config, UseWriteContractParameters, useAccount, useWriteContract } from "wagmi";
import { WriteContractErrorType, WriteContractReturnType } from "wagmi/actions";
import { WriteContractVariables } from "wagmi/query";
Expand All @@ -22,16 +23,19 @@ import {
*/
export const useScaffoldWriteContract = <TContractName extends ContractName>(
contractName: TContractName,
chain?: Chain,
rin-st marked this conversation as resolved.
Show resolved Hide resolved
writeContractParams?: UseWriteContractParameters,
) => {
const { chain } = useAccount();
const { chain: accountChain } = useAccount();
const writeTx = useTransactor();
const [isMining, setIsMining] = useState(false);
const { targetNetwork } = useTargetNetwork();

const wagmiContractWrite = useWriteContract(writeContractParams);

const { data: deployedContractData } = useDeployedContractInfo(contractName);
const selectedNetwork = chain ?? targetNetwork;

const { data: deployedContractData } = useDeployedContractInfo(contractName, selectedNetwork);

const sendContractWriteAsyncTx = async <
TFunctionName extends ExtractAbiFunctionNames<ContractAbi<TContractName>, "nonpayable" | "payable">,
Expand All @@ -44,12 +48,13 @@ export const useScaffoldWriteContract = <TContractName extends ContractName>(
return;
}

if (!chain?.id) {
if (!accountChain?.id) {
notification.error("Please connect your wallet");
return;
}
if (chain?.id !== targetNetwork.id) {
notification.error("You are on the wrong network");

if (accountChain?.id !== selectedNetwork.id) {
notification.error("Your wallet is connected to the wrong network");
return;
}

Expand Down Expand Up @@ -93,12 +98,13 @@ export const useScaffoldWriteContract = <TContractName extends ContractName>(
notification.error("Target Contract is not deployed, did you forget to run `yarn deploy`?");
return;
}
if (!chain?.id) {
if (!accountChain?.id) {
notification.error("Please connect your wallet");
return;
}
if (chain?.id !== targetNetwork.id) {
notification.error("You are on the wrong network");

if (accountChain?.id !== selectedNetwork.id) {
notification.error("Your wallet is connected to the wrong network");
return;
}

Expand Down
4 changes: 4 additions & 0 deletions packages/nextjs/utils/scaffold-eth/contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import type { MergeDeepRecord } from "type-fest/source/merge-deep";
import {
Address,
Block,
Chain,
GetEventArgs,
GetTransactionReceiptReturnType,
GetTransactionReturnType,
Expand Down Expand Up @@ -170,6 +171,7 @@ export type UseScaffoldReadConfig<
TFunctionName extends ExtractAbiFunctionNames<ContractAbi<TContractName>, ReadAbiStateMutability>,
> = {
contractName: TContractName;
chain?: Chain;
watch?: boolean;
} & IsContractDeclarationMissing<
Partial<UseReadContractParameters>,
Expand Down Expand Up @@ -215,6 +217,7 @@ export type UseScaffoldEventConfig<
> = {
contractName: TContractName;
eventName: TEventName;
chain?: Chain;
} & IsContractDeclarationMissing<
Omit<UseWatchContractEventParameters, "onLogs" | "address" | "abi" | "eventName"> & {
onLogs: (
Expand Down Expand Up @@ -274,6 +277,7 @@ export type UseScaffoldEventHistoryConfig<
contractName: TContractName;
eventName: IsContractDeclarationMissing<string, TEventName>;
fromBlock: bigint;
chain?: Chain;
filters?: EventFilters<TContractName, TEventName>;
blockData?: TBlockData;
transactionData?: TTransactionData;
Expand Down
Loading