@jaw.id/wagmi 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +147 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/lib/Actions.d.ts +2 -0
- package/dist/lib/Actions.d.ts.map +1 -0
- package/dist/lib/Actions.js +1 -0
- package/dist/lib/Connector.d.ts +30 -0
- package/dist/lib/Connector.d.ts.map +1 -0
- package/dist/lib/Connector.js +254 -0
- package/dist/lib/Connector.test.d.ts +2 -0
- package/dist/lib/Connector.test.d.ts.map +1 -0
- package/dist/lib/Connector.test.js +18 -0
- package/dist/lib/Hooks.d.ts +2 -0
- package/dist/lib/Hooks.d.ts.map +1 -0
- package/dist/lib/Hooks.js +1 -0
- package/dist/lib/Query.d.ts +2 -0
- package/dist/lib/Query.d.ts.map +1 -0
- package/dist/lib/Query.js +1 -0
- package/dist/lib/internal/core.d.ts +264 -0
- package/dist/lib/internal/core.d.ts.map +1 -0
- package/dist/lib/internal/core.js +248 -0
- package/dist/lib/internal/query.d.ts +98 -0
- package/dist/lib/internal/query.d.ts.map +1 -0
- package/dist/lib/internal/query.js +67 -0
- package/dist/lib/internal/react.d.ts +247 -0
- package/dist/lib/internal/react.d.ts.map +1 -0
- package/dist/lib/internal/react.js +517 -0
- package/package.json +43 -0
|
@@ -0,0 +1,517 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useEffect, useMemo, useRef } from 'react';
|
|
3
|
+
import { useAccount, useChainId, useConfig, useConnectors, } from 'wagmi';
|
|
4
|
+
import { useMutation, useQuery, useQueryClient, skipToken, } from '@tanstack/react-query';
|
|
5
|
+
import { connect, disconnect, grantPermissions, getPermissions, revokePermissions, getAssets, getCapabilities, sign, getCallsHistory, } from './core.js';
|
|
6
|
+
import { getPermissionsQueryKey, getAssetsQueryKey, getCapabilitiesQueryKey, getCallsHistoryQueryKey } from './query.js';
|
|
7
|
+
/**
|
|
8
|
+
* Hook to connect to the wallet with optional capabilities.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* const { mutate, data, isPending } = useConnect();
|
|
13
|
+
*
|
|
14
|
+
* // Basic connect
|
|
15
|
+
* mutate({ connector: jawWallet({ apiKey: 'xxx' }) });
|
|
16
|
+
*
|
|
17
|
+
* // Connect with capabilities (subname issuance)
|
|
18
|
+
* mutate({
|
|
19
|
+
* connector: jawWallet({ apiKey: 'xxx' }),
|
|
20
|
+
* capabilities: {
|
|
21
|
+
* subnameTextRecords: [
|
|
22
|
+
* { key: 'avatar', value: 'https://example.com/avatar.png' },
|
|
23
|
+
* ],
|
|
24
|
+
* },
|
|
25
|
+
* });
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export function useConnect(parameters = {}) {
|
|
29
|
+
const { mutation } = parameters;
|
|
30
|
+
const config = useConfig(parameters);
|
|
31
|
+
return useMutation({
|
|
32
|
+
...mutation,
|
|
33
|
+
mutationFn: async (variables) => {
|
|
34
|
+
return connect(config, variables);
|
|
35
|
+
},
|
|
36
|
+
mutationKey: ['connect'],
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Hook to grant permissions to a spender address.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```tsx
|
|
44
|
+
* const { mutate, data, isPending } = useGrantPermissions();
|
|
45
|
+
*
|
|
46
|
+
* mutate({
|
|
47
|
+
* expiry: Math.floor(Date.now() / 1000) + 3600, // 1 hour
|
|
48
|
+
* spender: '0x...',
|
|
49
|
+
* permissions: {
|
|
50
|
+
* calls: [{ target: '0x...', functionSignature: 'transfer(address,uint256)' }],
|
|
51
|
+
* spends: [{ token: '0x...', allowance: '1000000000000000000', unit: 'hour', multiplier: 1 }],
|
|
52
|
+
* },
|
|
53
|
+
* });
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export function useGrantPermissions(parameters = {}) {
|
|
57
|
+
const { mutation } = parameters;
|
|
58
|
+
const config = useConfig(parameters);
|
|
59
|
+
return useMutation({
|
|
60
|
+
...mutation,
|
|
61
|
+
mutationFn: async (variables) => {
|
|
62
|
+
return grantPermissions(config, variables);
|
|
63
|
+
},
|
|
64
|
+
mutationKey: ['grantPermissions'],
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Hook to revoke a permission by its ID.
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ```tsx
|
|
72
|
+
* const { mutate, isPending } = useRevokePermissions();
|
|
73
|
+
*
|
|
74
|
+
* mutate({
|
|
75
|
+
* id: '0x...', // permission hash
|
|
76
|
+
* });
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export function useRevokePermissions(parameters = {}) {
|
|
80
|
+
const { mutation } = parameters;
|
|
81
|
+
const config = useConfig(parameters);
|
|
82
|
+
return useMutation({
|
|
83
|
+
...mutation,
|
|
84
|
+
mutationFn: async (variables) => {
|
|
85
|
+
return revokePermissions(config, variables);
|
|
86
|
+
},
|
|
87
|
+
mutationKey: ['revokePermissions'],
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Hook to get the current permissions for an account.
|
|
92
|
+
* Automatically updates when permissions change.
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```tsx
|
|
96
|
+
* const { data: permissions, isLoading } = usePermissions();
|
|
97
|
+
*
|
|
98
|
+
* // With specific address (works even when not connected)
|
|
99
|
+
* const { data } = usePermissions({ address: '0x...' });
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
export function usePermissions(parameters = {}) {
|
|
103
|
+
const { query = {}, ...rest } = parameters;
|
|
104
|
+
const config = useConfig(rest);
|
|
105
|
+
const queryClient = useQueryClient();
|
|
106
|
+
const chainId = useChainId({ config });
|
|
107
|
+
const { address: connectedAddress, connector, status } = useAccount({ config });
|
|
108
|
+
const connectors = useConnectors({ config });
|
|
109
|
+
// Use account connector if connected, otherwise find JAW connector from available connectors
|
|
110
|
+
const jawConnector = connectors.find((c) => c.id === 'jaw');
|
|
111
|
+
const activeConnector = parameters.connector ?? connector ?? jawConnector;
|
|
112
|
+
// Use explicit address if provided, otherwise fall back to connected address
|
|
113
|
+
const targetAddress = parameters.address ?? connectedAddress;
|
|
114
|
+
// Enable query if:
|
|
115
|
+
// 1. Connected (existing behavior), OR
|
|
116
|
+
// 2. Explicit address provided AND connector available (disconnected query)
|
|
117
|
+
const isConnected = status === 'connected' || (status === 'reconnecting' && activeConnector?.getProvider);
|
|
118
|
+
const canQueryDisconnected = Boolean(targetAddress && activeConnector?.getProvider);
|
|
119
|
+
const enabled = Boolean((isConnected || canQueryDisconnected) && (query.enabled ?? true));
|
|
120
|
+
const queryKey = useMemo(() => getPermissionsQueryKey({
|
|
121
|
+
address: targetAddress,
|
|
122
|
+
chainId: parameters.chainId ?? chainId,
|
|
123
|
+
connector: activeConnector,
|
|
124
|
+
}), [targetAddress, chainId, parameters.chainId, activeConnector]);
|
|
125
|
+
// Set up event listener for permission changes
|
|
126
|
+
const providerRef = useRef(undefined);
|
|
127
|
+
const handlerRef = useRef(undefined);
|
|
128
|
+
useEffect(() => {
|
|
129
|
+
if (!activeConnector)
|
|
130
|
+
return;
|
|
131
|
+
let mounted = true;
|
|
132
|
+
void (async () => {
|
|
133
|
+
const provider = (await activeConnector.getProvider?.());
|
|
134
|
+
if (!mounted || !provider)
|
|
135
|
+
return;
|
|
136
|
+
providerRef.current = provider;
|
|
137
|
+
const handleMessage = (event) => {
|
|
138
|
+
if (event.type !== 'permissionsChanged')
|
|
139
|
+
return;
|
|
140
|
+
queryClient.invalidateQueries({ queryKey });
|
|
141
|
+
};
|
|
142
|
+
handlerRef.current = handleMessage;
|
|
143
|
+
provider.on('message', handleMessage);
|
|
144
|
+
})();
|
|
145
|
+
return () => {
|
|
146
|
+
mounted = false;
|
|
147
|
+
if (providerRef.current && handlerRef.current) {
|
|
148
|
+
providerRef.current.removeListener?.('message', handlerRef.current);
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
}, [activeConnector, queryClient, queryKey]);
|
|
152
|
+
return useQuery({
|
|
153
|
+
...query,
|
|
154
|
+
enabled,
|
|
155
|
+
gcTime: 0,
|
|
156
|
+
queryFn: activeConnector
|
|
157
|
+
? async () => {
|
|
158
|
+
// When connected, use the standard flow
|
|
159
|
+
if (isConnected) {
|
|
160
|
+
return getPermissions(config, {
|
|
161
|
+
...rest,
|
|
162
|
+
connector: activeConnector,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
// When disconnected but have address, make direct provider call
|
|
166
|
+
const provider = (await activeConnector.getProvider?.());
|
|
167
|
+
if (!provider)
|
|
168
|
+
throw new Error('Provider not available');
|
|
169
|
+
if (!targetAddress)
|
|
170
|
+
throw new Error('Address is required when not connected');
|
|
171
|
+
return provider.request({
|
|
172
|
+
method: 'wallet_getPermissions',
|
|
173
|
+
params: [{ address: targetAddress }],
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
: skipToken,
|
|
177
|
+
queryKey,
|
|
178
|
+
staleTime: Number.POSITIVE_INFINITY,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Hook to disconnect from the wallet.
|
|
183
|
+
*
|
|
184
|
+
* @example
|
|
185
|
+
* ```tsx
|
|
186
|
+
* const { mutate: disconnectWallet, isPending } = useDisconnect();
|
|
187
|
+
*
|
|
188
|
+
* // Disconnect active connector
|
|
189
|
+
* disconnectWallet({});
|
|
190
|
+
*
|
|
191
|
+
* // Disconnect specific connector
|
|
192
|
+
* disconnectWallet({ connector: jawWallet({ apiKey: 'xxx' }) });
|
|
193
|
+
* ```
|
|
194
|
+
*/
|
|
195
|
+
export function useDisconnect(parameters = {}) {
|
|
196
|
+
const { mutation } = parameters;
|
|
197
|
+
const config = useConfig(parameters);
|
|
198
|
+
return useMutation({
|
|
199
|
+
...mutation,
|
|
200
|
+
mutationFn: async (variables) => {
|
|
201
|
+
return disconnect(config, variables);
|
|
202
|
+
},
|
|
203
|
+
mutationKey: ['disconnect'],
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Hook to get the assets for an account.
|
|
208
|
+
* Automatically updates when assets change.
|
|
209
|
+
*
|
|
210
|
+
* @example
|
|
211
|
+
* ```tsx
|
|
212
|
+
* const { data: assets, isLoading } = useGetAssets();
|
|
213
|
+
*
|
|
214
|
+
* // With specific address (works even when not connected)
|
|
215
|
+
* const { data } = useGetAssets({ address: '0x...' });
|
|
216
|
+
*
|
|
217
|
+
* // With chain filter
|
|
218
|
+
* const { data } = useGetAssets({ chainFilter: ['0x1', '0xa'] });
|
|
219
|
+
*
|
|
220
|
+
* // With asset type filter
|
|
221
|
+
* const { data } = useGetAssets({ assetTypeFilter: ['erc20'] });
|
|
222
|
+
* ```
|
|
223
|
+
*/
|
|
224
|
+
export function useGetAssets(parameters = {}) {
|
|
225
|
+
const { query = {}, ...rest } = parameters;
|
|
226
|
+
const config = useConfig(rest);
|
|
227
|
+
const queryClient = useQueryClient();
|
|
228
|
+
const chainId = useChainId({ config });
|
|
229
|
+
const { address: connectedAddress, connector, status } = useAccount({ config });
|
|
230
|
+
const connectors = useConnectors({ config });
|
|
231
|
+
// Use account connector if connected, otherwise find JAW connector from available connectors
|
|
232
|
+
const jawConnector = connectors.find((c) => c.id === 'jaw');
|
|
233
|
+
const activeConnector = parameters.connector ?? connector ?? jawConnector;
|
|
234
|
+
// Use explicit address if provided, otherwise fall back to connected address
|
|
235
|
+
const targetAddress = parameters.address ?? connectedAddress;
|
|
236
|
+
// Enable query if:
|
|
237
|
+
// 1. Connected (existing behavior), OR
|
|
238
|
+
// 2. Explicit address provided AND connector available (disconnected query)
|
|
239
|
+
const isConnected = status === 'connected' || (status === 'reconnecting' && activeConnector?.getProvider);
|
|
240
|
+
const canQueryDisconnected = Boolean(targetAddress && activeConnector?.getProvider);
|
|
241
|
+
const enabled = Boolean((isConnected || canQueryDisconnected) && (query.enabled ?? true));
|
|
242
|
+
const queryKey = useMemo(() => getAssetsQueryKey({
|
|
243
|
+
address: targetAddress,
|
|
244
|
+
chainId: parameters.chainId ?? chainId,
|
|
245
|
+
connector: activeConnector,
|
|
246
|
+
chainFilter: parameters.chainFilter,
|
|
247
|
+
assetTypeFilter: parameters.assetTypeFilter,
|
|
248
|
+
assetFilter: parameters.assetFilter,
|
|
249
|
+
}), [
|
|
250
|
+
targetAddress,
|
|
251
|
+
chainId,
|
|
252
|
+
parameters.chainId,
|
|
253
|
+
activeConnector,
|
|
254
|
+
parameters.chainFilter,
|
|
255
|
+
parameters.assetTypeFilter,
|
|
256
|
+
parameters.assetFilter,
|
|
257
|
+
]);
|
|
258
|
+
// Set up event listener for asset changes (e.g., after transactions)
|
|
259
|
+
const providerRef = useRef(undefined);
|
|
260
|
+
const handlerRef = useRef(undefined);
|
|
261
|
+
useEffect(() => {
|
|
262
|
+
if (!activeConnector)
|
|
263
|
+
return;
|
|
264
|
+
let mounted = true;
|
|
265
|
+
void (async () => {
|
|
266
|
+
const provider = (await activeConnector.getProvider?.());
|
|
267
|
+
if (!mounted || !provider)
|
|
268
|
+
return;
|
|
269
|
+
providerRef.current = provider;
|
|
270
|
+
const handleMessage = (event) => {
|
|
271
|
+
if (event.type !== 'assetsChanged')
|
|
272
|
+
return;
|
|
273
|
+
queryClient.invalidateQueries({ queryKey });
|
|
274
|
+
};
|
|
275
|
+
handlerRef.current = handleMessage;
|
|
276
|
+
provider.on('message', handleMessage);
|
|
277
|
+
})();
|
|
278
|
+
return () => {
|
|
279
|
+
mounted = false;
|
|
280
|
+
if (providerRef.current && handlerRef.current) {
|
|
281
|
+
providerRef.current.removeListener?.('message', handlerRef.current);
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
}, [activeConnector, queryClient, queryKey]);
|
|
285
|
+
return useQuery({
|
|
286
|
+
...query,
|
|
287
|
+
enabled,
|
|
288
|
+
gcTime: 0,
|
|
289
|
+
queryFn: activeConnector
|
|
290
|
+
? async () => {
|
|
291
|
+
// When connected, use the standard flow
|
|
292
|
+
if (isConnected) {
|
|
293
|
+
return getAssets(config, {
|
|
294
|
+
...rest,
|
|
295
|
+
address: targetAddress,
|
|
296
|
+
connector: activeConnector,
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
// When disconnected but have address, make direct provider call
|
|
300
|
+
const provider = (await activeConnector.getProvider?.());
|
|
301
|
+
if (!provider)
|
|
302
|
+
throw new Error('Provider not available');
|
|
303
|
+
if (!targetAddress)
|
|
304
|
+
throw new Error('Address is required when not connected');
|
|
305
|
+
return provider.request({
|
|
306
|
+
method: 'wallet_getAssets',
|
|
307
|
+
params: [{
|
|
308
|
+
account: targetAddress,
|
|
309
|
+
chainFilter: parameters.chainFilter,
|
|
310
|
+
assetTypeFilter: parameters.assetTypeFilter,
|
|
311
|
+
assetFilter: parameters.assetFilter,
|
|
312
|
+
}],
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
: skipToken,
|
|
316
|
+
queryKey,
|
|
317
|
+
staleTime: 30_000, // Cache for 30 seconds since assets change less frequently
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Hook to get the wallet capabilities (EIP-5792).
|
|
322
|
+
* Can be called without a connected account.
|
|
323
|
+
*
|
|
324
|
+
* @example
|
|
325
|
+
* ```tsx
|
|
326
|
+
* // Get capabilities (uses connected account if available)
|
|
327
|
+
* const { data: capabilities, isLoading } = useCapabilities();
|
|
328
|
+
*
|
|
329
|
+
* // With specific address (works even when not connected)
|
|
330
|
+
* const { data } = useCapabilities({ address: '0x...' });
|
|
331
|
+
*
|
|
332
|
+
* // With chain filter
|
|
333
|
+
* const { data } = useCapabilities({ chainFilter: ['0x1', '0xa'] });
|
|
334
|
+
* ```
|
|
335
|
+
*/
|
|
336
|
+
export function useCapabilities(parameters = {}) {
|
|
337
|
+
const { query = {}, ...rest } = parameters;
|
|
338
|
+
const config = useConfig(rest);
|
|
339
|
+
const chainId = useChainId({ config });
|
|
340
|
+
const { address: connectedAddress, connector, status } = useAccount({ config });
|
|
341
|
+
const connectors = useConnectors({ config });
|
|
342
|
+
// Use account connector if connected, otherwise find JAW connector from available connectors
|
|
343
|
+
const jawConnector = connectors.find((c) => c.id === 'jaw');
|
|
344
|
+
const activeConnector = parameters.connector ?? connector ?? jawConnector;
|
|
345
|
+
// Use explicit address if provided, otherwise fall back to connected address
|
|
346
|
+
const targetAddress = parameters.address ?? connectedAddress;
|
|
347
|
+
// Enable query if:
|
|
348
|
+
// 1. Connected (existing behavior), OR
|
|
349
|
+
// 2. Connector available (can query capabilities without connection)
|
|
350
|
+
const isConnected = status === 'connected' || (status === 'reconnecting' && activeConnector?.getProvider);
|
|
351
|
+
const canQueryDisconnected = Boolean(activeConnector?.getProvider);
|
|
352
|
+
const enabled = Boolean((isConnected || canQueryDisconnected) && (query.enabled ?? true));
|
|
353
|
+
const queryKey = useMemo(() => getCapabilitiesQueryKey({
|
|
354
|
+
address: targetAddress,
|
|
355
|
+
chainId: parameters.chainId ?? chainId,
|
|
356
|
+
connector: activeConnector,
|
|
357
|
+
chainFilter: parameters.chainFilter,
|
|
358
|
+
}), [targetAddress, chainId, parameters.chainId, activeConnector, parameters.chainFilter]);
|
|
359
|
+
return useQuery({
|
|
360
|
+
...query,
|
|
361
|
+
enabled,
|
|
362
|
+
gcTime: 0,
|
|
363
|
+
queryFn: activeConnector
|
|
364
|
+
? async () => {
|
|
365
|
+
// When connected, use the standard flow
|
|
366
|
+
if (isConnected) {
|
|
367
|
+
return getCapabilities(config, {
|
|
368
|
+
...rest,
|
|
369
|
+
address: targetAddress,
|
|
370
|
+
connector: activeConnector,
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
// When disconnected, make direct provider call
|
|
374
|
+
const provider = (await activeConnector.getProvider?.());
|
|
375
|
+
if (!provider)
|
|
376
|
+
throw new Error('Provider not available');
|
|
377
|
+
return provider.request({
|
|
378
|
+
method: 'wallet_getCapabilities',
|
|
379
|
+
params: [targetAddress, parameters.chainFilter],
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
: skipToken,
|
|
383
|
+
queryKey,
|
|
384
|
+
staleTime: 60_000, // Cache for 60 seconds since capabilities don't change often
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Hook to sign messages using the unified wallet_sign method (ERC-7871).
|
|
389
|
+
* This combines the functionality of useSignMessage and useSignTypedData.
|
|
390
|
+
*
|
|
391
|
+
* @example
|
|
392
|
+
* ```tsx
|
|
393
|
+
* const { mutate: signMessage, data: signature, isPending } = useSign();
|
|
394
|
+
*
|
|
395
|
+
* // Personal sign (EIP-191)
|
|
396
|
+
* signMessage({
|
|
397
|
+
* request: {
|
|
398
|
+
* type: '0x45',
|
|
399
|
+
* data: { message: 'Hello World' },
|
|
400
|
+
* },
|
|
401
|
+
* });
|
|
402
|
+
*
|
|
403
|
+
* // Typed data sign (EIP-712)
|
|
404
|
+
* signMessage({
|
|
405
|
+
* request: {
|
|
406
|
+
* type: '0x01',
|
|
407
|
+
* data: {
|
|
408
|
+
* types: { ... },
|
|
409
|
+
* primaryType: 'Mail',
|
|
410
|
+
* domain: { ... },
|
|
411
|
+
* message: { ... },
|
|
412
|
+
* },
|
|
413
|
+
* },
|
|
414
|
+
* });
|
|
415
|
+
*
|
|
416
|
+
* // Sign on a specific chain (useful for smart accounts)
|
|
417
|
+
* signMessage({
|
|
418
|
+
* chainId: 8453, // Base
|
|
419
|
+
* request: {
|
|
420
|
+
* type: '0x45',
|
|
421
|
+
* data: { message: 'Hello from Base' },
|
|
422
|
+
* },
|
|
423
|
+
* });
|
|
424
|
+
* ```
|
|
425
|
+
*/
|
|
426
|
+
export function useSign(parameters = {}) {
|
|
427
|
+
const { mutation } = parameters;
|
|
428
|
+
const config = useConfig(parameters);
|
|
429
|
+
return useMutation({
|
|
430
|
+
...mutation,
|
|
431
|
+
mutationFn: async (variables) => {
|
|
432
|
+
return sign(config, variables);
|
|
433
|
+
},
|
|
434
|
+
mutationKey: ['sign'],
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Hook to get the calls history for an account.
|
|
439
|
+
* Can be called without a connected account if address is provided.
|
|
440
|
+
*
|
|
441
|
+
* @example
|
|
442
|
+
* ```tsx
|
|
443
|
+
* // Get calls history for connected account
|
|
444
|
+
* const { data: history, isLoading } = useGetCallsHistory();
|
|
445
|
+
*
|
|
446
|
+
* // With specific address (works even when not connected)
|
|
447
|
+
* const { data } = useGetCallsHistory({ address: '0x...' });
|
|
448
|
+
*
|
|
449
|
+
* // With pagination
|
|
450
|
+
* const { data } = useGetCallsHistory({
|
|
451
|
+
* address: '0x...',
|
|
452
|
+
* limit: 10,
|
|
453
|
+
* sort: 'desc',
|
|
454
|
+
* });
|
|
455
|
+
* ```
|
|
456
|
+
*/
|
|
457
|
+
export function useGetCallsHistory(parameters = {}) {
|
|
458
|
+
const { query = {}, ...rest } = parameters;
|
|
459
|
+
const config = useConfig(rest);
|
|
460
|
+
const chainId = useChainId({ config });
|
|
461
|
+
const { address: connectedAddress, connector, status } = useAccount({ config });
|
|
462
|
+
const connectors = useConnectors({ config });
|
|
463
|
+
// Use account connector if connected, otherwise find JAW connector from available connectors
|
|
464
|
+
const jawConnector = connectors.find((c) => c.id === 'jaw');
|
|
465
|
+
const activeConnector = parameters.connector ?? connector ?? jawConnector;
|
|
466
|
+
// Use explicit address if provided, otherwise fall back to connected address
|
|
467
|
+
const targetAddress = parameters.address ?? connectedAddress;
|
|
468
|
+
// Enable query if:
|
|
469
|
+
// 1. Connected (existing behavior), OR
|
|
470
|
+
// 2. Explicit address provided AND connector available (disconnected query)
|
|
471
|
+
const isConnected = status === 'connected' || (status === 'reconnecting' && activeConnector?.getProvider);
|
|
472
|
+
const canQueryDisconnected = Boolean(targetAddress && activeConnector?.getProvider);
|
|
473
|
+
const enabled = Boolean((isConnected || canQueryDisconnected) && (query.enabled ?? true));
|
|
474
|
+
const queryKey = useMemo(() => getCallsHistoryQueryKey({
|
|
475
|
+
address: targetAddress,
|
|
476
|
+
chainId: parameters.chainId ?? chainId,
|
|
477
|
+
connector: activeConnector,
|
|
478
|
+
index: parameters.index,
|
|
479
|
+
limit: parameters.limit,
|
|
480
|
+
sort: parameters.sort,
|
|
481
|
+
}), [targetAddress, chainId, parameters.chainId, activeConnector, parameters.index, parameters.limit, parameters.sort]);
|
|
482
|
+
return useQuery({
|
|
483
|
+
...query,
|
|
484
|
+
enabled,
|
|
485
|
+
gcTime: 0,
|
|
486
|
+
queryFn: activeConnector
|
|
487
|
+
? async () => {
|
|
488
|
+
// When connected, use the standard flow
|
|
489
|
+
if (isConnected) {
|
|
490
|
+
return getCallsHistory(config, {
|
|
491
|
+
...rest,
|
|
492
|
+
address: targetAddress,
|
|
493
|
+
connector: activeConnector,
|
|
494
|
+
});
|
|
495
|
+
}
|
|
496
|
+
// When disconnected but have address, make direct provider call
|
|
497
|
+
const provider = (await activeConnector.getProvider?.());
|
|
498
|
+
if (!provider)
|
|
499
|
+
throw new Error('Provider not available');
|
|
500
|
+
if (!targetAddress)
|
|
501
|
+
throw new Error('Address is required when not connected');
|
|
502
|
+
return provider.request({
|
|
503
|
+
method: 'wallet_getCallsHistory',
|
|
504
|
+
params: [{
|
|
505
|
+
address: targetAddress,
|
|
506
|
+
chainId: parameters.chainId,
|
|
507
|
+
index: parameters.index,
|
|
508
|
+
limit: parameters.limit,
|
|
509
|
+
sort: parameters.sort,
|
|
510
|
+
}],
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
: skipToken,
|
|
514
|
+
queryKey,
|
|
515
|
+
staleTime: 30_000, // Cache for 30 seconds
|
|
516
|
+
});
|
|
517
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@jaw.id/wagmi",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
"./package.json": "./package.json",
|
|
10
|
+
".": {
|
|
11
|
+
"@jaw-mono/source": "./src/index.ts",
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js",
|
|
14
|
+
"default": "./dist/index.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/JustaName-id/jaw-mono.git",
|
|
20
|
+
"directory": "packages/wagmi"
|
|
21
|
+
},
|
|
22
|
+
"publishConfig": {
|
|
23
|
+
"access": "public"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"dist",
|
|
27
|
+
"!**/*.tsbuildinfo"
|
|
28
|
+
],
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@jaw.id/core": "0.0.1",
|
|
31
|
+
"@wagmi/core": "^3.0.0",
|
|
32
|
+
"tslib": "^2.3.0",
|
|
33
|
+
"viem": "^2.38.2"
|
|
34
|
+
},
|
|
35
|
+
"peerDependencies": {
|
|
36
|
+
"@tanstack/react-query": ">=5.0.0",
|
|
37
|
+
"react": ">=18.0.0",
|
|
38
|
+
"wagmi": ">=3.0.0"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@types/react": "^19.0.0"
|
|
42
|
+
}
|
|
43
|
+
}
|