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 16/12/24 #172

Merged
merged 15 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
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
9 changes: 9 additions & 0 deletions .changeset/silly-hounds-stare.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"create-eth": patch
---

- Follow root level naming convention (https://github.com/scaffold-eth/scaffold-eth-2/pull/1006)
- Fix useScaffoldEventHistory duplicated events (https://github.com/scaffold-eth/scaffold-eth-2/pull/1014)
- feat: disable vercel telemetry (https://github.com/scaffold-eth/scaffold-eth-2/pull/1012)
- Optional chainId config in Scaffold hooks (https://github.com/scaffold-eth/scaffold-eth-2/pull/931)
- Foundry improvements (https://github.com/scaffold-eth/scaffold-eth-2/pull/1011)
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type ContractUIProps = {
export const ContractUI = ({ contractName, className = "" }: ContractUIProps) => {
const [refreshDisplayVariables, triggerRefreshDisplayVariables] = useReducer(value => !value, false);
const { targetNetwork } = useTargetNetwork();
const { data: deployedContractData, isLoading: deployedContractLoading } = useDeployedContractInfo(contractName);
const { data: deployedContractData, isLoading: deployedContractLoading } = useDeployedContractInfo({ contractName });
const networkColor = useNetworkColor();

if (deployedContractLoading) {
Expand Down
1 change: 1 addition & 0 deletions templates/base/packages/nextjs/hooks/scaffold-eth/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ export * from "./useScaffoldWriteContract";
export * from "./useTargetNetwork";
export * from "./useTransactor";
export * from "./useWatchBalance";
export * from "./useSelectedNetwork";
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
import { useEffect, useState } from "react";
import { useTargetNetwork } from "./useTargetNetwork";
import { useIsMounted } from "usehooks-ts";
import { usePublicClient } from "wagmi";
import { Contract, ContractCodeStatus, ContractName, contracts } from "~~/utils/scaffold-eth/contract";
import { useSelectedNetwork } from "~~/hooks/scaffold-eth";
import {
Contract,
ContractCodeStatus,
ContractName,
UseDeployedContractConfig,
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,
chainId,
}: UseDeployedContractConfig<TContractName>) => {
const isMounted = useIsMounted();
const { targetNetwork } = useTargetNetwork();
const deployedContract = contracts?.[targetNetwork.id]?.[contractName as ContractName] as Contract<TContractName>;

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

useEffect(() => {
const checkContractDeployment = async () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useTargetNetwork } from "./useTargetNetwork";
import { useTheme } from "next-themes";
import { ChainWithAttributes } from "~~/utils/scaffold-eth";
import { useSelectedNetwork } from "~~/hooks/scaffold-eth";
import { AllowedChainIds, ChainWithAttributes } from "~~/utils/scaffold-eth";

export const DEFAULT_NETWORK_COLOR: [string, string] = ["#666666", "#bbbbbb"];

Expand All @@ -12,11 +13,11 @@ export function getNetworkColor(network: ChainWithAttributes, isDarkMode: boolea
/**
* Gets the color of the target network
*/
export const useNetworkColor = () => {
export const useNetworkColor = (chainId?: AllowedChainIds) => {
const { resolvedTheme } = useTheme();
const { targetNetwork } = useTargetNetwork();

const chain = useSelectedNetwork(chainId);
const isDarkMode = resolvedTheme === "dark";

return getNetworkColor(targetNetwork, isDarkMode);
return getNetworkColor(chain, isDarkMode);
};
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { useTargetNetwork } from "./useTargetNetwork";
import { Account, Address, Chain, Client, Transport, getContract } from "viem";
import { usePublicClient } from "wagmi";
import { GetWalletClientReturnType } from "wagmi/actions";
import { useSelectedNetwork } from "~~/hooks/scaffold-eth";
import { useDeployedContractInfo } from "~~/hooks/scaffold-eth";
import { AllowedChainIds } from "~~/utils/scaffold-eth";
import { Contract, ContractName } from "~~/utils/scaffold-eth/contract";

/**
Expand All @@ -11,20 +12,27 @@ import { Contract, ContractName } from "~~/utils/scaffold-eth/contract";
* @param config - The config settings for the hook
* @param config.contractName - deployed contract name
* @param config.walletClient - optional walletClient from wagmi useWalletClient hook can be passed for doing write transactions
* @param config.chainId - optional chainId that is configured with the scaffold project to make use for multi-chain interactions.
*/
export const useScaffoldContract = <
TContractName extends ContractName,
TWalletClient extends Exclude<GetWalletClientReturnType, null> | undefined,
>({
contractName,
walletClient,
chainId,
}: {
contractName: TContractName;
walletClient?: TWalletClient | null;
chainId?: AllowedChainIds;
}) => {
const { data: deployedContractData, isLoading: deployedContractLoading } = useDeployedContractInfo(contractName);
const { targetNetwork } = useTargetNetwork();
const publicClient = usePublicClient({ chainId: targetNetwork.id });
const selectedNetwork = useSelectedNetwork(chainId);
const { data: deployedContractData, isLoading: deployedContractLoading } = useDeployedContractInfo({
contractName,
chainId: selectedNetwork?.id as AllowedChainIds,
});

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

let contract = undefined;
if (deployedContractData && publicClient) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { useEffect, useState } from "react";
import { useTargetNetwork } from "./useTargetNetwork";
import { useInfiniteQuery } from "@tanstack/react-query";
import { Abi, AbiEvent, ExtractAbiEventNames } from "abitype";
import { BlockNumber, GetLogsParameters } from "viem";
import { Config, UsePublicClientReturnType, useBlockNumber, usePublicClient } from "wagmi";
import { useSelectedNetwork } from "~~/hooks/scaffold-eth";
import { useDeployedContractInfo } from "~~/hooks/scaffold-eth";
import { AllowedChainIds } from "~~/utils/scaffold-eth";
import { replacer } from "~~/utils/scaffold-eth/common";
import {
ContractAbi,
Expand Down Expand Up @@ -57,6 +58,7 @@ const getEvents = async (
* @param config.contractName - deployed contract name
* @param config.eventName - name of the event to listen for
* @param config.fromBlock - the block number to start reading events from
* @param config.chainId - optional chainId that is configured with the scaffold project to make use for multi-chain interactions.
* @param config.filters - filters to be applied to the event (parameterName: value)
* @param config.blockData - if set to true it will return the block data for each event (default: false)
* @param config.transactionData - if set to true it will return the transaction data for each event (default: false)
Expand All @@ -74,22 +76,27 @@ export const useScaffoldEventHistory = <
contractName,
eventName,
fromBlock,
chainId,
filters,
blockData,
transactionData,
receiptData,
watch,
enabled = true,
}: UseScaffoldEventHistoryConfig<TContractName, TEventName, TBlockData, TTransactionData, TReceiptData>) => {
const { targetNetwork } = useTargetNetwork();
const selectedNetwork = useSelectedNetwork(chainId);

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

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

const { data: deployedContractData } = useDeployedContractInfo(contractName);
const { data: deployedContractData } = useDeployedContractInfo({
contractName,
chainId: selectedNetwork.id as AllowedChainIds,
});

const event =
deployedContractData &&
Expand All @@ -105,7 +112,7 @@ export const useScaffoldEventHistory = <
address: deployedContractData?.address,
eventName,
fromBlock: fromBlock.toString(),
chainId: targetNetwork.id,
chainId: selectedNetwork.id,
filters: JSON.stringify(filters, replacer),
},
],
Expand All @@ -121,8 +128,18 @@ export const useScaffoldEventHistory = <
},
enabled: enabled && isContractAddressAndClientReady,
initialPageParam: fromBlock,
getNextPageParam: () => {
return blockNumber;
getNextPageParam: (lastPage, allPages, lastPageParam) => {
if (!blockNumber || fromBlock >= blockNumber) return undefined;

const lastPageHighestBlock = Math.max(
Number(fromBlock),
...(lastPage || []).map(event => Number(event.blockNumber || 0)),
);
const nextBlock = BigInt(Math.max(Number(lastPageParam), lastPageHighestBlock) + 1);

if (nextBlock > blockNumber) return undefined;

return nextBlock;
},
select: data => {
const events = data.pages.flat();
Expand All @@ -133,6 +150,7 @@ export const useScaffoldEventHistory = <
TTransactionData,
TReceiptData
>;

return {
pages: eventHistoryData?.reverse(),
pageParams: data.pageParams,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { useEffect } from "react";
import { useTargetNetwork } from "./useTargetNetwork";
import { QueryObserverResult, RefetchOptions, useQueryClient } from "@tanstack/react-query";
import type { ExtractAbiFunctionNames } from "abitype";
import { ReadContractErrorType } from "viem";
import { useBlockNumber, useReadContract } from "wagmi";
import { useSelectedNetwork } from "~~/hooks/scaffold-eth";
import { useDeployedContractInfo } from "~~/hooks/scaffold-eth";
import { AllowedChainIds } from "~~/utils/scaffold-eth";
import {
AbiFunctionReturnType,
ContractAbi,
Expand All @@ -19,6 +20,7 @@ import {
* @param config.contractName - deployed contract name
* @param config.functionName - name of the function to be called
* @param config.args - args to be passed to the function call
* @param config.chainId - optional chainId that is configured with the scaffold project to make use for multi-chain interactions.
*/
export const useScaffoldReadContract = <
TContractName extends ContractName,
Expand All @@ -27,16 +29,21 @@ export const useScaffoldReadContract = <
contractName,
functionName,
args,
chainId,
...readConfig
}: UseScaffoldReadConfig<TContractName, TFunctionName>) => {
const { data: deployedContract } = useDeployedContractInfo(contractName);
const { targetNetwork } = useTargetNetwork();
const selectedNetwork = useSelectedNetwork(chainId);
const { data: deployedContract } = useDeployedContractInfo({
contractName,
chainId: selectedNetwork.id as AllowedChainIds,
});

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

const readContractHookRes = useReadContract({
chainId: targetNetwork.id,
chainId: selectedNetwork.id,
functionName,
address: deployedContract?.address,
abi: deployedContract?.abi,
Expand All @@ -56,7 +63,7 @@ export const useScaffoldReadContract = <
const queryClient = useQueryClient();
const { data: blockNumber } = useBlockNumber({
watch: defaultWatch,
chainId: targetNetwork.id,
chainId: selectedNetwork.id,
query: {
enabled: defaultWatch,
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { useTargetNetwork } from "./useTargetNetwork";
import { Abi, ExtractAbiEventNames } from "abitype";
import { Log } from "viem";
import { useWatchContractEvent } from "wagmi";
import { useSelectedNetwork } from "~~/hooks/scaffold-eth";
import { addIndexedArgsToEvent, useDeployedContractInfo } from "~~/hooks/scaffold-eth";
import { AllowedChainIds } from "~~/utils/scaffold-eth";
import { ContractAbi, ContractName, UseScaffoldEventConfig } from "~~/utils/scaffold-eth/contract";

/**
Expand All @@ -11,6 +12,7 @@ import { ContractAbi, ContractName, UseScaffoldEventConfig } from "~~/utils/scaf
* @param config - The config settings
* @param config.contractName - deployed contract name
* @param config.eventName - name of the event to listen for
* @param config.chainId - optional chainId that is configured with the scaffold project to make use for multi-chain interactions.
* @param config.onLogs - the callback that receives events.
*/
export const useScaffoldWatchContractEvent = <
Expand All @@ -19,18 +21,22 @@ export const useScaffoldWatchContractEvent = <
>({
contractName,
eventName,
chainId,
onLogs,
}: UseScaffoldEventConfig<TContractName, TEventName>) => {
const { data: deployedContractData } = useDeployedContractInfo(contractName);
const { targetNetwork } = useTargetNetwork();
const selectedNetwork = useSelectedNetwork(chainId);
const { data: deployedContractData } = useDeployedContractInfo({
contractName,
chainId: selectedNetwork.id as AllowedChainIds,
});

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: selectedNetwork.id,
onLogs: listenerWithIndexedArgs,
eventName,
});
Expand Down
Loading
Loading