@@ -4,7 +4,11 @@ import {
4
4
useQuery ,
5
5
} from "@tanstack/react-query" ;
6
6
import type { Abi , AbiFunction , ExtractAbiFunctionNames } from "abitype" ;
7
- import type { ThirdwebContract } from "../../../../contract/contract.js" ;
7
+ import type {
8
+ AbiOfLength ,
9
+ AsyncGetAbiFunctionFromContract ,
10
+ } from "../../../../contract/types.js" ;
11
+ import type { Extension } from "../../../../extensions/types.js" ;
8
12
import {
9
13
type ReadContractOptions ,
10
14
type ReadContractResult ,
@@ -17,17 +21,16 @@ import type {
17
21
import type { PreparedMethod } from "../../../../utils/abi/prepare-method.js" ;
18
22
import { getFunctionId } from "../../../../utils/function-id.js" ;
19
23
import { stringify } from "../../../../utils/json.js" ;
20
-
21
- type PickedQueryOptions = {
22
- enabled ?: boolean ;
23
- refetchInterval ?: number ;
24
- retry ?: number ;
25
- } ;
24
+ import type {
25
+ PickedOnceQueryOptions ,
26
+ WithPickedOnceQueryOptions ,
27
+ } from "../types.js" ;
26
28
27
29
/**
28
30
* A hook to read state from a contract that automatically updates when the contract changes.
29
31
*
30
- * You can use raw read calls or read [extensions](https://portal.thirdweb.com/react/v5/extensions) to read from a contract.
32
+ * You can use raw read calls or read [extensions](https://portal.thirdweb.com/react/v5/extensions) to read from a
33
+ * contract.
31
34
*
32
35
* @param options - The options for reading from a contract
33
36
* @returns a UseQueryResult object.
@@ -52,20 +55,19 @@ type PickedQueryOptions = {
52
55
* @contract
53
56
*/
54
57
export function useReadContract <
55
- const abi extends Abi ,
56
- const method extends abi extends { length : 0 }
58
+ const TAbi extends Abi ,
59
+ const TMethod extends TAbi extends AbiOfLength < 0 >
57
60
? AbiFunction | string
58
- : ExtractAbiFunctionNames < abi > ,
61
+ : ExtractAbiFunctionNames < TAbi > ,
59
62
> (
60
- options : ReadContractOptions < abi , method > & {
61
- queryOptions ?: PickedQueryOptions ;
62
- } ,
63
+ options : WithPickedOnceQueryOptions < ReadContractOptions < TAbi , TMethod > > ,
63
64
) : UseQueryResult <
64
- ReadContractResult < PreparedMethod < ParseMethod < abi , method > > [ 2 ] >
65
+ ReadContractResult < PreparedMethod < ParseMethod < TAbi , TMethod > > [ 2 ] >
65
66
> ;
66
67
/**
67
68
* A hook to read state from a contract that automatically updates when the contract changes.
68
- * You can use raw read calls or read [extensions](https://portal.thirdweb.com/react/v5/extensions) to read from a contract.
69
+ * You can use raw read calls or read [extensions](https://portal.thirdweb.com/react/v5/extensions) to read from a
70
+ * contract.
69
71
*
70
72
* @param extension - An extension to call.
71
73
* @param options - The read extension params.
@@ -82,38 +84,42 @@ export function useReadContract<
82
84
* ```
83
85
*/
84
86
export function useReadContract <
85
- const abi extends Abi ,
86
- const params extends object ,
87
- result ,
87
+ const TAbi extends Abi ,
88
+ const TParams extends object ,
89
+ TResult ,
88
90
> (
89
- extension : ( options : BaseTransactionOptions < params , abi > ) => Promise < result > ,
90
- options : BaseTransactionOptions < params , abi > & {
91
- queryOptions ?: PickedQueryOptions ;
92
- } ,
93
- ) : UseQueryResult < result > ;
91
+ extension : Extension < TAbi , TParams , TResult > ,
92
+ options : WithPickedOnceQueryOptions < BaseTransactionOptions < TParams , TAbi > > ,
93
+ ) : UseQueryResult < TResult > ;
94
94
95
95
export function useReadContract <
96
- const abi extends Abi ,
97
- const method extends abi extends {
98
- length : 0 ;
99
- }
100
- ?
101
- | AbiFunction
102
- | `function ${string } `
103
- | ( ( contract : ThirdwebContract < abi > ) => Promise < AbiFunction > )
104
- : ExtractAbiFunctionNames < abi > ,
105
- const params extends object ,
106
- result ,
96
+ const TAbi extends Abi ,
97
+ const TMethod extends TAbi extends AbiOfLength < 0 >
98
+ ? AbiFunction | `function ${string } ` | AsyncGetAbiFunctionFromContract < TAbi >
99
+ : ExtractAbiFunctionNames < TAbi > ,
100
+ const TParams extends object ,
101
+ TResult ,
107
102
> (
108
103
extensionOrOptions :
109
- | ( ( options : BaseTransactionOptions < params , abi > ) => Promise < result > )
110
- | ( ReadContractOptions < abi , method > & {
111
- queryOptions ?: PickedQueryOptions ;
112
- } ) ,
113
- options ?: BaseTransactionOptions < params , abi > & {
114
- queryOptions ?: PickedQueryOptions ;
115
- } ,
104
+ | Extension < TAbi , TParams , TResult >
105
+ | WithPickedOnceQueryOptions < ReadContractOptions < TAbi , TMethod > > ,
106
+ options ?: WithPickedOnceQueryOptions < BaseTransactionOptions < TParams , TAbi > > ,
116
107
) {
108
+ type QueryKey = readonly [
109
+ "readContract" ,
110
+ number | string ,
111
+ string ,
112
+ string | PreparedMethod < ParseMethod < TAbi , TMethod > > ,
113
+ string ,
114
+ ] ;
115
+ type QueryFn = ( ) => Promise <
116
+ TResult | ReadContractResult < PreparedMethod < ParseMethod < TAbi , TMethod > > [ 2 ] >
117
+ > ;
118
+
119
+ let queryKey : QueryKey | undefined ;
120
+ let queryFn : QueryFn | undefined ;
121
+ let queryOpts : PickedOnceQueryOptions | undefined ;
122
+
117
123
// extension case
118
124
if ( typeof extensionOrOptions === "function" ) {
119
125
if ( ! options ) {
@@ -122,46 +128,49 @@ export function useReadContract<
122
128
) as never ;
123
129
}
124
130
const { queryOptions, contract, ...params } = options ;
131
+ queryOpts = queryOptions ;
125
132
126
- const query = defineQuery ( {
127
- queryKey : [
128
- "readContract" ,
129
- contract . chain . id ,
130
- contract . address ,
131
- getFunctionId ( extensionOrOptions ) ,
132
- stringify ( params ) ,
133
- ] as const ,
134
- // @ts -expect-error - TODO: clean up the type issues here
135
- queryFn : ( ) => extensionOrOptions ( { ...params , contract } ) ,
136
- ...queryOptions ,
137
- } ) ;
133
+ queryKey = [
134
+ "readContract" ,
135
+ contract . chain . id ,
136
+ contract . address ,
137
+ getFunctionId ( extensionOrOptions ) ,
138
+ stringify ( params ) ,
139
+ ] as const ;
138
140
139
- // TODO - FIX LATER
140
- // biome-ignore lint/correctness/useHookAtTopLevel: <explanation>
141
- return useQuery ( query ) ;
141
+ queryFn = ( ) =>
142
+ extensionOrOptions ( {
143
+ ...( params as TParams ) ,
144
+ contract,
145
+ } ) ;
142
146
}
143
147
// raw tx case
144
148
if ( "method" in extensionOrOptions ) {
145
149
const { queryOptions, ...tx } = extensionOrOptions ;
150
+ queryOpts = queryOptions ;
146
151
147
- const query = defineQuery ( {
148
- queryKey : [
149
- "readContract" ,
150
- tx . contract . chain . id ,
151
- tx . contract . address ,
152
- tx . method ,
153
- stringify ( tx . params ) ,
154
- ] as const ,
155
- queryFn : ( ) => readContract ( extensionOrOptions ) ,
156
- ...queryOptions ,
157
- } ) ;
152
+ queryKey = [
153
+ "readContract" ,
154
+ tx . contract . chain . id ,
155
+ tx . contract . address ,
156
+ tx . method ,
157
+ stringify ( tx . params ) ,
158
+ ] as const ;
159
+
160
+ queryFn = ( ) => readContract ( extensionOrOptions ) ;
161
+ }
158
162
159
- // TODO - FIX LATER
160
- // biome-ignore lint/correctness/useHookAtTopLevel: <explanation>
161
- return useQuery ( query ) ;
163
+ if ( ! queryKey || ! queryFn ) {
164
+ throw new Error (
165
+ `Invalid "useReadContract" options. Expected either a read extension or a transaction object.` ,
166
+ ) as never ;
162
167
}
163
168
164
- throw new Error (
165
- `Invalid "useReadContract" options. Expected either a read extension or a transaction object.` ,
166
- ) as never ;
169
+ return useQuery (
170
+ defineQuery ( {
171
+ queryKey : queryKey as QueryKey ,
172
+ queryFn : queryFn as QueryFn ,
173
+ ...( queryOpts ?? { } ) ,
174
+ } ) ,
175
+ ) ;
167
176
}
0 commit comments