1
- import { useEffect , useState } from "react" ;
1
+ import { useCallback , useEffect , useState } from "react" ;
2
2
import Image from "next/image" ;
3
3
import Link from "next/link" ;
4
4
import { useRouter } from "next/router" ;
@@ -12,9 +12,9 @@ import { MiniFooter } from "~~/components/MiniFooter";
12
12
import { NetworksDropdown } from "~~/components/NetworksDropdown/NetworksDropdown" ;
13
13
import { SwitchTheme } from "~~/components/SwitchTheme" ;
14
14
import { AddressInput } from "~~/components/scaffold-eth" ;
15
+ import useFetchContractAbi from "~~/hooks/useFetchContractAbi" ;
15
16
import { useAbiNinjaState } from "~~/services/store/store" ;
16
- import { fetchContractABIFromAnyABI , fetchContractABIFromEtherscan , parseAndCorrectJSON } from "~~/utils/abi" ;
17
- import { detectProxyTarget } from "~~/utils/abi-ninja/proxyContracts" ;
17
+ import { parseAndCorrectJSON } from "~~/utils/abi" ;
18
18
import { notification } from "~~/utils/scaffold-eth" ;
19
19
20
20
enum TabName {
@@ -30,7 +30,6 @@ const Home: NextPage = () => {
30
30
const [ verifiedContractAddress , setVerifiedContractAddress ] = useState ( "" ) ;
31
31
const [ localAbiContractAddress , setLocalAbiContractAddress ] = useState ( "" ) ;
32
32
const [ localContractAbi , setLocalContractAbi ] = useState ( "" ) ;
33
- const [ isFetchingAbi , setIsFetchingAbi ] = useState ( false ) ;
34
33
35
34
const publicClient = usePublicClient ( {
36
35
chainId : parseInt ( network ) ,
@@ -42,66 +41,64 @@ const Home: NextPage = () => {
42
41
setImplementationAddress : state . setImplementationAddress ,
43
42
} ) ) ;
44
43
45
- const [ isAbiAvailable , setIsAbiAvailable ] = useState ( false ) ;
46
-
47
44
const router = useRouter ( ) ;
48
45
49
- useEffect ( ( ) => {
50
- const fetchContractAbi = async ( ) => {
51
- setIsFetchingAbi ( true ) ;
52
- try {
53
- const implementationAddress = await detectProxyTarget ( verifiedContractAddress as Address , publicClient ) ;
54
-
55
- if ( implementationAddress ) {
56
- setImplementationAddress ( implementationAddress ) ;
57
- }
58
- const abi = await fetchContractABIFromAnyABI (
59
- implementationAddress || verifiedContractAddress ,
60
- parseInt ( network ) ,
61
- ) ;
62
- if ( ! abi ) throw new Error ( "Got empty or undefined ABI from AnyABI" ) ;
63
- setContractAbi ( abi ) ;
64
- setIsAbiAvailable ( true ) ;
65
- } catch ( error ) {
66
- console . error ( "Error fetching ABI from AnyABI: " , error ) ;
67
- console . log ( "Trying to fetch ABI from Etherscan..." ) ;
68
- try {
69
- const abiString = await fetchContractABIFromEtherscan ( verifiedContractAddress , parseInt ( network ) ) ;
70
- const abi = JSON . parse ( abiString ) ;
71
- setContractAbi ( abi ) ;
72
- setIsAbiAvailable ( true ) ;
73
- } catch ( etherscanError : any ) {
74
- setIsAbiAvailable ( false ) ;
75
- console . error ( "Error fetching ABI from Etherscan: " , etherscanError ) ;
46
+ const {
47
+ contractData,
48
+ error,
49
+ isLoading : isFetchingAbi ,
50
+ implementationAddress,
51
+ } = useFetchContractAbi ( { contractAddress : verifiedContractAddress , chainId : parseInt ( network ) , publicClient } ) ;
76
52
77
- const bytecode = await publicClient ?. getBytecode ( {
78
- address : verifiedContractAddress as Address ,
79
- } ) ;
80
- const isContract = Boolean ( bytecode ) && bytecode !== "0x" ;
53
+ const isAbiAvailable = contractData ?. abi && contractData . abi . length > 0 ;
81
54
82
- if ( isContract ) {
83
- setLocalAbiContractAddress ( verifiedContractAddress ) ;
84
- setActiveTab ( TabName . addressAbi ) ;
85
- } else {
86
- notification . error ( "Address is not a contract, are you sure you are on the correct chain?" ) ;
87
- }
88
- }
89
- } finally {
90
- setIsFetchingAbi ( false ) ;
91
- }
92
- } ;
55
+ const handleFetchError = useCallback ( async ( ) => {
56
+ try {
57
+ const bytecode = await publicClient ?. getBytecode ( {
58
+ address : verifiedContractAddress as Address ,
59
+ } ) ;
60
+ const isContract = Boolean ( bytecode ) && bytecode !== "0x" ;
93
61
94
- if ( isAddress ( verifiedContractAddress ) ) {
95
- if ( network === "31337" ) {
96
- setActiveTab ( TabName . addressAbi ) ;
62
+ if ( isContract ) {
97
63
setLocalAbiContractAddress ( verifiedContractAddress ) ;
98
- return ;
64
+ setActiveTab ( TabName . addressAbi ) ;
65
+ } else {
66
+ notification . error ( "Address is not a contract, are you sure you are on the correct chain?" ) ;
99
67
}
100
- fetchContractAbi ( ) ;
101
- } else {
102
- setIsAbiAvailable ( false ) ;
68
+ } catch ( error ) {
69
+ console . error ( "Error checking if address is a contract:" , error ) ;
70
+ notification . error ( "Error checking if address is a contract. Please try again." ) ;
71
+ }
72
+ } , [ publicClient , verifiedContractAddress , setLocalAbiContractAddress , setActiveTab ] ) ;
73
+
74
+ useEffect ( ( ) => {
75
+ if ( implementationAddress ) {
76
+ setImplementationAddress ( implementationAddress ) ;
77
+ }
78
+
79
+ if ( contractData ?. abi ) {
80
+ setContractAbi ( contractData . abi ) ;
81
+ }
82
+
83
+ if ( network === "31337" ) {
84
+ setActiveTab ( TabName . addressAbi ) ;
85
+ setLocalAbiContractAddress ( verifiedContractAddress ) ;
86
+ return ;
87
+ }
88
+
89
+ if ( error && isAddress ( verifiedContractAddress ) ) {
90
+ handleFetchError ( ) ;
103
91
}
104
- } , [ verifiedContractAddress , network , setContractAbi , publicClient , setImplementationAddress ] ) ;
92
+ } , [
93
+ contractData ,
94
+ error ,
95
+ implementationAddress ,
96
+ network ,
97
+ verifiedContractAddress ,
98
+ handleFetchError ,
99
+ setContractAbi ,
100
+ setImplementationAddress ,
101
+ ] ) ;
105
102
106
103
useEffect ( ( ) => {
107
104
if ( router . pathname === "/" ) {
@@ -132,7 +129,6 @@ const Home: NextPage = () => {
132
129
} ;
133
130
134
131
const fetchAbiFromHeimdall = async ( contractAddress : Address ) => {
135
- setIsFetchingAbi ( true ) ;
136
132
try {
137
133
const rpcUrlWithoutHttps = publicClient ?. chain . rpcUrls . default . http [ 0 ] . substring ( 8 ) ;
138
134
const response = await fetch (
@@ -141,19 +137,14 @@ const Home: NextPage = () => {
141
137
const abi = await response . json ( ) ;
142
138
if ( abi . length === 0 ) {
143
139
notification . error ( "Failed to fetch ABI from Heimdall. Please try again or enter ABI manually." ) ;
144
- setIsFetchingAbi ( false ) ;
145
140
return ;
146
141
}
147
142
setContractAbi ( abi ) ;
148
- setIsAbiAvailable ( true ) ;
149
143
setAbiContractAddress ( contractAddress ) ;
150
144
router . push ( `/${ contractAddress } /${ network } ` ) ;
151
145
} catch ( error ) {
152
146
console . error ( "Error fetching ABI from Heimdall: " , error ) ;
153
147
notification . error ( "Failed to fetch ABI from Heimdall. Please try again or enter ABI manually." ) ;
154
- setIsAbiAvailable ( false ) ;
155
- } finally {
156
- setIsFetchingAbi ( false ) ;
157
148
}
158
149
} ;
159
150
0 commit comments