From c29cc511583943a63b58ea255aa00117b2c3b196 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8r=E2=88=82=C2=A1?= Date: Mon, 15 Jul 2024 11:47:31 +0200 Subject: [PATCH] Making useAbi work well with EOA's --- hooks/useAbi.ts | 42 +++++++++++++++++++++++++++++------------- utils/chains.ts | 6 ++++-- 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/hooks/useAbi.ts b/hooks/useAbi.ts index e9df089..01ae70c 100644 --- a/hooks/useAbi.ts +++ b/hooks/useAbi.ts @@ -42,16 +42,17 @@ export const useAbi = (contractAddress: Address) => { error, } = useQuery({ queryKey: ["abi", resolvedAddress || "", !!publicClient], - queryFn: () => { + queryFn: async () => { if (!resolvedAddress || !isAddress(resolvedAddress) || !publicClient) { - return Promise.resolve([]); + return []; + } else if (!(await isContract(resolvedAddress, publicClient))) { + return []; } - const abiLoader = getEtherscanAbiLoader(); return whatsabi .autoload(resolvedAddress, { provider: publicClient, - abiLoader, + abiLoader: getEtherscanAbiLoader(), followProxies: false, enableExperimentalMetadata: true, }) @@ -68,15 +69,7 @@ export const useAbi = (contractAddress: Address) => { type: item.type, }); } - functionItems.sort((a, b) => { - const a_RO = ["pure", "view"].includes(a.stateMutability); - const b_RO = ["pure", "view"].includes(b.stateMutability); - - if (a_RO === b_RO) return 0; - else if (a_RO) return 1; - else if (b_RO) return -1; - return 0; - }); + functionItems.sort(abiSortCallback); return functionItems; }) .catch((err) => { @@ -125,6 +118,11 @@ function getEtherscanAbiLoader() { apiKey: PUB_ETHERSCAN_API_KEY, baseURL: "https://api-sepolia.etherscan.io/api", }); + case "holesky": + return new whatsabi.loaders.EtherscanABILoader({ + apiKey: PUB_ETHERSCAN_API_KEY, + baseURL: "https://api-holesky.etherscan.io/api", + }); case "mumbai": return new whatsabi.loaders.EtherscanABILoader({ apiKey: PUB_ETHERSCAN_API_KEY, @@ -134,3 +132,21 @@ function getEtherscanAbiLoader() { throw new Error("Unknown chain"); } } + +function isContract(address: Address, publicClient: ReturnType) { + if (!publicClient) return Promise.reject(new Error("Invalid client")); + + return publicClient.getBytecode({ address }).then((bytecode) => { + return bytecode !== undefined && bytecode !== "0x"; + }); +} + +function abiSortCallback(a: AbiFunction, b: AbiFunction) { + const a_RO = ["pure", "view"].includes(a.stateMutability); + const b_RO = ["pure", "view"].includes(b.stateMutability); + + if (a_RO === b_RO) return 0; + else if (a_RO) return 1; + else if (b_RO) return -1; + return 0; +} diff --git a/utils/chains.ts b/utils/chains.ts index 40d78e1..61b6c71 100644 --- a/utils/chains.ts +++ b/utils/chains.ts @@ -1,6 +1,6 @@ -import { polygon, mainnet, sepolia, arbitrum, polygonMumbai, Chain } from "@wagmi/core/chains"; +import { polygon, mainnet, sepolia, holesky, arbitrum, polygonMumbai, Chain } from "@wagmi/core/chains"; -const chainNames = ["mainnet", "polygon", "sepolia", "mumbai", "arbitrum"] as const; +const chainNames = ["mainnet", "polygon", "sepolia", "holesky", "mumbai", "arbitrum"] as const; export type ChainName = (typeof chainNames)[number]; export function getChain(chainName: ChainName): Chain { @@ -13,6 +13,8 @@ export function getChain(chainName: ChainName): Chain { return arbitrum; case "sepolia": return sepolia; + case "holesky": + return holesky; case "mumbai": return polygonMumbai; default: