noah-avalanche-sdk 0.1.2

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.
Files changed (103) hide show
  1. package/README.md +892 -0
  2. package/dist/core/APIClient.d.ts +71 -0
  3. package/dist/core/APIClient.d.ts.map +1 -0
  4. package/dist/core/APIClient.js +92 -0
  5. package/dist/core/APIClient.js.map +1 -0
  6. package/dist/core/ContractClient.d.ts +38 -0
  7. package/dist/core/ContractClient.d.ts.map +1 -0
  8. package/dist/core/ContractClient.js +209 -0
  9. package/dist/core/ContractClient.js.map +1 -0
  10. package/dist/core/NoahSDK.d.ts +43 -0
  11. package/dist/core/NoahSDK.d.ts.map +1 -0
  12. package/dist/core/NoahSDK.js +93 -0
  13. package/dist/core/NoahSDK.js.map +1 -0
  14. package/dist/core/WalletAdapter.d.ts +188 -0
  15. package/dist/core/WalletAdapter.d.ts.map +1 -0
  16. package/dist/core/WalletAdapter.js +425 -0
  17. package/dist/core/WalletAdapter.js.map +1 -0
  18. package/dist/hooks/index.d.ts +18 -0
  19. package/dist/hooks/index.d.ts.map +1 -0
  20. package/dist/hooks/index.js +15 -0
  21. package/dist/hooks/index.js.map +1 -0
  22. package/dist/hooks/useCredentials.d.ts +136 -0
  23. package/dist/hooks/useCredentials.d.ts.map +1 -0
  24. package/dist/hooks/useCredentials.js +217 -0
  25. package/dist/hooks/useCredentials.js.map +1 -0
  26. package/dist/hooks/useProtocol.d.ts +117 -0
  27. package/dist/hooks/useProtocol.d.ts.map +1 -0
  28. package/dist/hooks/useProtocol.js +165 -0
  29. package/dist/hooks/useProtocol.js.map +1 -0
  30. package/dist/hooks/useUser.d.ts +159 -0
  31. package/dist/hooks/useUser.d.ts.map +1 -0
  32. package/dist/hooks/useUser.js +188 -0
  33. package/dist/hooks/useUser.js.map +1 -0
  34. package/dist/index.d.ts +28 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +26 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/issuer/IssuerClient.d.ts +98 -0
  39. package/dist/issuer/IssuerClient.d.ts.map +1 -0
  40. package/dist/issuer/IssuerClient.js +159 -0
  41. package/dist/issuer/IssuerClient.js.map +1 -0
  42. package/dist/protocol/ProtocolClient.d.ts +124 -0
  43. package/dist/protocol/ProtocolClient.d.ts.map +1 -0
  44. package/dist/protocol/ProtocolClient.js +265 -0
  45. package/dist/protocol/ProtocolClient.js.map +1 -0
  46. package/dist/protocol/RequirementsManager.d.ts +9 -0
  47. package/dist/protocol/RequirementsManager.d.ts.map +1 -0
  48. package/dist/protocol/RequirementsManager.js +9 -0
  49. package/dist/protocol/RequirementsManager.js.map +1 -0
  50. package/dist/user/ProofGenerator.d.ts +49 -0
  51. package/dist/user/ProofGenerator.d.ts.map +1 -0
  52. package/dist/user/ProofGenerator.js +80 -0
  53. package/dist/user/ProofGenerator.js.map +1 -0
  54. package/dist/user/UserClient.d.ts +191 -0
  55. package/dist/user/UserClient.d.ts.map +1 -0
  56. package/dist/user/UserClient.js +338 -0
  57. package/dist/user/UserClient.js.map +1 -0
  58. package/dist/utils/credentials.d.ts +47 -0
  59. package/dist/utils/credentials.d.ts.map +1 -0
  60. package/dist/utils/credentials.js +99 -0
  61. package/dist/utils/credentials.js.map +1 -0
  62. package/dist/utils/identity.d.ts +22 -0
  63. package/dist/utils/identity.d.ts.map +1 -0
  64. package/dist/utils/identity.js +35 -0
  65. package/dist/utils/identity.js.map +1 -0
  66. package/dist/utils/jurisdiction.d.ts +21 -0
  67. package/dist/utils/jurisdiction.d.ts.map +1 -0
  68. package/dist/utils/jurisdiction.js +64 -0
  69. package/dist/utils/jurisdiction.js.map +1 -0
  70. package/dist/utils/mrz.d.ts +16 -0
  71. package/dist/utils/mrz.d.ts.map +1 -0
  72. package/dist/utils/mrz.js +91 -0
  73. package/dist/utils/mrz.js.map +1 -0
  74. package/dist/utils/ocr.d.ts +31 -0
  75. package/dist/utils/ocr.d.ts.map +1 -0
  76. package/dist/utils/ocr.js +69 -0
  77. package/dist/utils/ocr.js.map +1 -0
  78. package/dist/utils/types.d.ts +122 -0
  79. package/dist/utils/types.d.ts.map +1 -0
  80. package/dist/utils/types.js +2 -0
  81. package/dist/utils/types.js.map +1 -0
  82. package/package.json +53 -0
  83. package/src/core/APIClient.ts +165 -0
  84. package/src/core/ContractClient.ts +266 -0
  85. package/src/core/NoahSDK.ts +123 -0
  86. package/src/core/WalletAdapter.ts +546 -0
  87. package/src/hooks/index.ts +31 -0
  88. package/src/hooks/types.d.ts +18 -0
  89. package/src/hooks/useCredentials.ts +359 -0
  90. package/src/hooks/useProtocol.ts +284 -0
  91. package/src/hooks/useUser.ts +331 -0
  92. package/src/index.ts +80 -0
  93. package/src/issuer/IssuerClient.ts +209 -0
  94. package/src/protocol/ProtocolClient.ts +330 -0
  95. package/src/protocol/RequirementsManager.ts +16 -0
  96. package/src/user/ProofGenerator.ts +113 -0
  97. package/src/user/UserClient.ts +440 -0
  98. package/src/utils/credentials.ts +122 -0
  99. package/src/utils/identity.ts +46 -0
  100. package/src/utils/jurisdiction.ts +83 -0
  101. package/src/utils/mrz.ts +113 -0
  102. package/src/utils/ocr.ts +84 -0
  103. package/src/utils/types.ts +144 -0
@@ -0,0 +1,359 @@
1
+ import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
2
+ import { useMemo } from 'react';
3
+ import type { Signer } from 'ethers';
4
+ import type { TransactionResult } from '../utils/types';
5
+
6
+ /**
7
+ * Configuration options for useCredentials hook
8
+ */
9
+ export interface UseCredentialsOptions {
10
+ /** User address to get credentials for */
11
+ userAddress?: string;
12
+ /** Issuer address to get credentials from */
13
+ issuerAddress?: string;
14
+ /** Credential hash to check */
15
+ credentialHash?: string;
16
+ /** Whether to enable automatic refetching */
17
+ enabled?: boolean;
18
+ /** React Query configuration options */
19
+ queryOptions?: {
20
+ refetchInterval?: number;
21
+ staleTime?: number;
22
+ };
23
+ }
24
+
25
+ /**
26
+ * Credential information structure
27
+ */
28
+ export interface CredentialInfo {
29
+ credentialHash: string;
30
+ userAddress: string;
31
+ issuerAddress: string;
32
+ isValid: boolean;
33
+ isRevoked: boolean;
34
+ timestamp?: bigint;
35
+ }
36
+
37
+ /**
38
+ * Issuer information structure
39
+ */
40
+ export interface IssuerInfo {
41
+ isTrusted: boolean;
42
+ name: string;
43
+ }
44
+
45
+ /**
46
+ * Return type for useCredentials hook
47
+ */
48
+ export interface UseCredentialsReturn {
49
+ // Read operations
50
+ credentialInfo: CredentialInfo | undefined;
51
+ isLoadingCredential: boolean;
52
+ credentialError: Error | null;
53
+ refetchCredential: () => void;
54
+
55
+ issuerInfo: IssuerInfo | undefined;
56
+ isLoadingIssuer: boolean;
57
+ issuerError: Error | null;
58
+ refetchIssuer: () => void;
59
+
60
+ userCredentials: CredentialInfo[] | undefined;
61
+ isLoadingUserCredentials: boolean;
62
+ userCredentialsError: Error | null;
63
+ refetchUserCredentials: () => void;
64
+
65
+ issuerCredentials: CredentialInfo[] | undefined;
66
+ isLoadingIssuerCredentials: boolean;
67
+ issuerCredentialsError: Error | null;
68
+ refetchIssuerCredentials: () => void;
69
+
70
+ // Write operations (mutations) - requires issuer signer
71
+ registerCredential: {
72
+ mutate: (params: {
73
+ credentialHash: string;
74
+ userAddress: string;
75
+ }) => void;
76
+ mutateAsync: (params: {
77
+ credentialHash: string;
78
+ userAddress: string;
79
+ }) => Promise<TransactionResult>;
80
+ isLoading: boolean;
81
+ error: Error | null;
82
+ reset: () => void;
83
+ };
84
+
85
+ revokeCredential: {
86
+ mutate: (params: {
87
+ credentialHash: string;
88
+ }) => void;
89
+ mutateAsync: (params: {
90
+ credentialHash: string;
91
+ }) => Promise<TransactionResult>;
92
+ isLoading: boolean;
93
+ error: Error | null;
94
+ reset: () => void;
95
+ };
96
+ }
97
+
98
+ /**
99
+ * React hook for credential management operations
100
+ *
101
+ * Provides easy access to credential-related functionality including:
102
+ * - Checking credential validity
103
+ * - Getting issuer information
104
+ * - Listing user and issuer credentials
105
+ * - Registering and revoking credentials (for issuers)
106
+ *
107
+ * @param signer - Ethers signer instance (from wallet, required for write operations)
108
+ * @param options - Configuration options
109
+ * @returns Hook return object with credential operations
110
+ *
111
+ * @example
112
+ * ```tsx
113
+ * import { useCredentials } from '@noah-protocol/sdk/hooks';
114
+ * import { useSigner, useAccount } from 'wagmi';
115
+ *
116
+ * function CredentialManager() {
117
+ * const { data: signer } = useSigner();
118
+ * const { address } = useAccount();
119
+ * const {
120
+ * credentialInfo,
121
+ * registerCredential,
122
+ * revokeCredential
123
+ * } = useCredentials(signer, {
124
+ * credentialHash: '0x...',
125
+ * userAddress: address
126
+ * });
127
+ *
128
+ * const handleRegister = async () => {
129
+ * await registerCredential.mutateAsync({
130
+ * credentialHash: '0x...',
131
+ * userAddress: '0x...'
132
+ * });
133
+ * };
134
+ *
135
+ * return (
136
+ * <div>
137
+ * {credentialInfo?.isValid ? (
138
+ * <p>Credential is valid</p>
139
+ * ) : (
140
+ * <button onClick={handleRegister}>
141
+ * Register Credential
142
+ * </button>
143
+ * )}
144
+ * </div>
145
+ * );
146
+ * }
147
+ * ```
148
+ */
149
+ export function useCredentials(
150
+ signer: Signer | null | undefined,
151
+ options: UseCredentialsOptions = {}
152
+ ): UseCredentialsReturn {
153
+ const {
154
+ userAddress,
155
+ issuerAddress,
156
+ credentialHash,
157
+ enabled = true,
158
+ queryOptions = {},
159
+ } = options;
160
+
161
+ const queryClient = useQueryClient();
162
+
163
+ // Get ContractClient instance (assuming it's available)
164
+ const contractClient = useMemo(() => {
165
+ try {
166
+ const { ContractClient } = require('../core/ContractClient');
167
+ return new ContractClient();
168
+ } catch (error) {
169
+ console.warn('ContractClient not available:', error);
170
+ return null;
171
+ }
172
+ }, []);
173
+
174
+ // Initialize contract client with provider if signer is available
175
+ useMemo(() => {
176
+ if (contractClient && signer) {
177
+ const provider = signer.provider;
178
+ if (provider) {
179
+ contractClient.initialize(provider);
180
+ }
181
+ }
182
+ }, [contractClient, signer]);
183
+
184
+ // Query: Get credential info
185
+ const {
186
+ data: credentialInfo,
187
+ isLoading: isLoadingCredential,
188
+ error: credentialError,
189
+ refetch: refetchCredential,
190
+ } = useQuery({
191
+ queryKey: ['credentials', 'info', credentialHash],
192
+ queryFn: async () => {
193
+ if (!contractClient || !credentialHash) {
194
+ throw new Error('Contract client or credential hash not available');
195
+ }
196
+ const isValid = await contractClient.isCredentialValid(credentialHash);
197
+
198
+ // Get issuer info if available
199
+ let issuerAddress = '';
200
+ try {
201
+ // This would require additional contract methods
202
+ // For now, we'll return basic info
203
+ issuerAddress = '';
204
+ } catch (error) {
205
+ // Ignore if not available
206
+ }
207
+
208
+ return {
209
+ credentialHash,
210
+ userAddress: userAddress || '',
211
+ issuerAddress,
212
+ isValid,
213
+ isRevoked: !isValid,
214
+ } as CredentialInfo;
215
+ },
216
+ enabled: enabled && !!contractClient && !!credentialHash,
217
+ ...queryOptions,
218
+ });
219
+
220
+ // Query: Get issuer info
221
+ const {
222
+ data: issuerInfo,
223
+ isLoading: isLoadingIssuer,
224
+ error: issuerError,
225
+ refetch: refetchIssuer,
226
+ } = useQuery({
227
+ queryKey: ['credentials', 'issuer', issuerAddress],
228
+ queryFn: async () => {
229
+ if (!contractClient || !issuerAddress) {
230
+ throw new Error('Contract client or issuer address not available');
231
+ }
232
+ return contractClient.getIssuerInfo(issuerAddress);
233
+ },
234
+ enabled: enabled && !!contractClient && !!issuerAddress,
235
+ ...queryOptions,
236
+ });
237
+
238
+ // Query: Get user credentials (would need API endpoint or contract method)
239
+ const {
240
+ data: userCredentials,
241
+ isLoading: isLoadingUserCredentials,
242
+ error: userCredentialsError,
243
+ refetch: refetchUserCredentials,
244
+ } = useQuery({
245
+ queryKey: ['credentials', 'user', userAddress],
246
+ queryFn: async () => {
247
+ if (!userAddress) {
248
+ throw new Error('User address not available');
249
+ }
250
+ // This would typically call an API endpoint or contract method
251
+ // For now, return empty array
252
+ return [] as CredentialInfo[];
253
+ },
254
+ enabled: enabled && !!userAddress,
255
+ ...queryOptions,
256
+ });
257
+
258
+ // Query: Get issuer credentials (would need API endpoint or contract method)
259
+ const {
260
+ data: issuerCredentials,
261
+ isLoading: isLoadingIssuerCredentials,
262
+ error: issuerCredentialsError,
263
+ refetch: refetchIssuerCredentials,
264
+ } = useQuery({
265
+ queryKey: ['credentials', 'issuer-list', issuerAddress],
266
+ queryFn: async () => {
267
+ if (!issuerAddress) {
268
+ throw new Error('Issuer address not available');
269
+ }
270
+ // This would typically call an API endpoint
271
+ // For now, return empty array
272
+ return [] as CredentialInfo[];
273
+ },
274
+ enabled: enabled && !!issuerAddress,
275
+ ...queryOptions,
276
+ });
277
+
278
+ // Mutation: Register credential (requires issuer signer)
279
+ const registerCredentialMutation = useMutation({
280
+ mutationFn: async (params: {
281
+ credentialHash: string;
282
+ userAddress: string;
283
+ }) => {
284
+ if (!contractClient || !signer) {
285
+ throw new Error('Contract client or signer not available');
286
+ }
287
+ return contractClient.registerCredential(
288
+ signer,
289
+ params.credentialHash,
290
+ params.userAddress
291
+ );
292
+ },
293
+ onSuccess: () => {
294
+ // Invalidate credential queries
295
+ queryClient.invalidateQueries({
296
+ queryKey: ['credentials'],
297
+ });
298
+ },
299
+ });
300
+
301
+ // Mutation: Revoke credential (requires issuer signer)
302
+ const revokeCredentialMutation = useMutation({
303
+ mutationFn: async (params: {
304
+ credentialHash: string;
305
+ }) => {
306
+ if (!contractClient || !signer) {
307
+ throw new Error('Contract client or signer not available');
308
+ }
309
+ return contractClient.revokeCredential(signer, params.credentialHash);
310
+ },
311
+ onSuccess: () => {
312
+ // Invalidate credential queries
313
+ queryClient.invalidateQueries({
314
+ queryKey: ['credentials'],
315
+ });
316
+ },
317
+ });
318
+
319
+ return {
320
+ credentialInfo,
321
+ isLoadingCredential,
322
+ credentialError: credentialError as Error | null,
323
+ refetchCredential: () => {
324
+ refetchCredential();
325
+ },
326
+ issuerInfo,
327
+ isLoadingIssuer,
328
+ issuerError: issuerError as Error | null,
329
+ refetchIssuer: () => {
330
+ refetchIssuer();
331
+ },
332
+ userCredentials,
333
+ isLoadingUserCredentials,
334
+ userCredentialsError: userCredentialsError as Error | null,
335
+ refetchUserCredentials: () => {
336
+ refetchUserCredentials();
337
+ },
338
+ issuerCredentials,
339
+ isLoadingIssuerCredentials,
340
+ issuerCredentialsError: issuerCredentialsError as Error | null,
341
+ refetchIssuerCredentials: () => {
342
+ refetchIssuerCredentials();
343
+ },
344
+ registerCredential: {
345
+ mutate: registerCredentialMutation.mutate,
346
+ mutateAsync: registerCredentialMutation.mutateAsync,
347
+ isLoading: registerCredentialMutation.isPending,
348
+ error: registerCredentialMutation.error as Error | null,
349
+ reset: registerCredentialMutation.reset,
350
+ },
351
+ revokeCredential: {
352
+ mutate: revokeCredentialMutation.mutate,
353
+ mutateAsync: revokeCredentialMutation.mutateAsync,
354
+ isLoading: revokeCredentialMutation.isPending,
355
+ error: revokeCredentialMutation.error as Error | null,
356
+ reset: revokeCredentialMutation.reset,
357
+ },
358
+ };
359
+ }
@@ -0,0 +1,284 @@
1
+ import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
2
+ import { useMemo, useState, useEffect } from 'react';
3
+ import type { Signer } from 'ethers';
4
+ import { ProtocolClient } from '../protocol/ProtocolClient';
5
+ import type { Requirements, TransactionResult } from '../utils/types';
6
+
7
+ /**
8
+ * Configuration options for useProtocol hook
9
+ */
10
+ export interface UseProtocolOptions {
11
+ /** Protocol contract address (optional, defaults to signer address) */
12
+ protocolAddress?: string;
13
+ /** User address to check access for */
14
+ userAddress?: string;
15
+ /** Whether to enable automatic refetching */
16
+ enabled?: boolean;
17
+ /** React Query configuration options */
18
+ queryOptions?: {
19
+ refetchInterval?: number;
20
+ staleTime?: number;
21
+ };
22
+ }
23
+
24
+ /**
25
+ * Return type for useProtocol hook
26
+ */
27
+ export interface UseProtocolReturn {
28
+ // Protocol client instance
29
+ protocol: ProtocolClient | null;
30
+
31
+ // Read operations
32
+ requirements: Requirements | undefined;
33
+ isLoadingRequirements: boolean;
34
+ requirementsError: Error | null;
35
+ refetchRequirements: () => void;
36
+
37
+ // Access checking
38
+ hasAccess: boolean | undefined;
39
+ isLoadingAccess: boolean;
40
+ accessError: Error | null;
41
+ refetchAccess: () => void;
42
+
43
+ // Write operations (mutations)
44
+ setRequirements: {
45
+ mutate: (params: {
46
+ minAge: number;
47
+ jurisdictions: string[];
48
+ requireAccredited: boolean;
49
+ }) => void;
50
+ mutateAsync: (params: {
51
+ minAge: number;
52
+ jurisdictions: string[];
53
+ requireAccredited: boolean;
54
+ }) => Promise<TransactionResult>;
55
+ isLoading: boolean;
56
+ error: Error | null;
57
+ reset: () => void;
58
+ };
59
+
60
+ verifyAndGrantAccess: {
61
+ mutate: (params: {
62
+ proof: {
63
+ a: [string, string];
64
+ b: [[string, string], [string, string]];
65
+ c: [string, string];
66
+ };
67
+ publicSignals: string[];
68
+ credentialHash: string;
69
+ userAddress: string;
70
+ }) => void;
71
+ mutateAsync: (params: {
72
+ proof: {
73
+ a: [string, string];
74
+ b: [[string, string], [string, string]];
75
+ c: [string, string];
76
+ };
77
+ publicSignals: string[];
78
+ credentialHash: string;
79
+ userAddress: string;
80
+ }) => Promise<TransactionResult>;
81
+ isLoading: boolean;
82
+ error: Error | null;
83
+ reset: () => void;
84
+ };
85
+ }
86
+
87
+ /**
88
+ * React hook for protocol operations
89
+ *
90
+ * Provides easy access to protocol-related functionality including:
91
+ * - Getting and setting protocol requirements
92
+ * - Checking user access
93
+ * - Verifying proofs and granting access
94
+ *
95
+ * @param signer - Ethers signer instance (from wallet)
96
+ * @param options - Configuration options
97
+ * @returns Hook return object with protocol operations
98
+ *
99
+ * @example
100
+ * ```tsx
101
+ * import { useProtocol } from '@noah-protocol/sdk/hooks';
102
+ * import { useSigner } from 'wagmi';
103
+ *
104
+ * function ProtocolDashboard() {
105
+ * const { data: signer } = useSigner();
106
+ * const {
107
+ * requirements,
108
+ * setRequirements,
109
+ * hasAccess
110
+ * } = useProtocol(signer, {
111
+ * protocolAddress: '0x...',
112
+ * userAddress: '0x...'
113
+ * });
114
+ *
115
+ * return (
116
+ * <div>
117
+ * <button onClick={() => setRequirements.mutate({
118
+ * minAge: 21,
119
+ * jurisdictions: ['US', 'UK'],
120
+ * requireAccredited: true
121
+ * })}>
122
+ * Set Requirements
123
+ * </button>
124
+ * </div>
125
+ * );
126
+ * }
127
+ * ```
128
+ */
129
+ export function useProtocol(
130
+ signer: Signer | null | undefined,
131
+ options: UseProtocolOptions = {}
132
+ ): UseProtocolReturn {
133
+ const {
134
+ protocolAddress,
135
+ userAddress,
136
+ enabled = true,
137
+ queryOptions = {},
138
+ } = options;
139
+
140
+ const queryClient = useQueryClient();
141
+
142
+ // Create protocol client instance
143
+ const protocol = useMemo(() => {
144
+ if (!signer) return null;
145
+ try {
146
+ return new ProtocolClient(signer);
147
+ } catch (error) {
148
+ console.warn('ProtocolClient not available:', error);
149
+ return null;
150
+ }
151
+ }, [signer]);
152
+
153
+ // Get current protocol address (use signer address if not provided)
154
+ const [currentProtocolAddress, setCurrentProtocolAddress] = useState<string | undefined>(protocolAddress);
155
+
156
+ useEffect(() => {
157
+ if (protocolAddress) {
158
+ setCurrentProtocolAddress(protocolAddress);
159
+ } else if (signer) {
160
+ signer.getAddress()
161
+ .then(address => setCurrentProtocolAddress(address))
162
+ .catch(() => setCurrentProtocolAddress(undefined));
163
+ } else {
164
+ setCurrentProtocolAddress(undefined);
165
+ }
166
+ }, [protocolAddress, signer]);
167
+
168
+ // Query: Get protocol requirements
169
+ const {
170
+ data: requirements,
171
+ isLoading: isLoadingRequirements,
172
+ error: requirementsError,
173
+ refetch: refetchRequirements,
174
+ } = useQuery({
175
+ queryKey: ['protocol', 'requirements', currentProtocolAddress],
176
+ queryFn: async () => {
177
+ if (!protocol || !currentProtocolAddress) {
178
+ throw new Error('Protocol client or address not available');
179
+ }
180
+ return protocol.getRequirements(currentProtocolAddress);
181
+ },
182
+ enabled: enabled && !!protocol && !!currentProtocolAddress,
183
+ ...queryOptions,
184
+ });
185
+
186
+ // Query: Check user access
187
+ const {
188
+ data: hasAccess,
189
+ isLoading: isLoadingAccess,
190
+ error: accessError,
191
+ refetch: refetchAccess,
192
+ } = useQuery({
193
+ queryKey: ['protocol', 'access', currentProtocolAddress, userAddress],
194
+ queryFn: async () => {
195
+ if (!protocol || !currentProtocolAddress || !userAddress) {
196
+ throw new Error('Protocol client, address, or user address not available');
197
+ }
198
+ return protocol.checkUserAccess(currentProtocolAddress, userAddress);
199
+ },
200
+ enabled: enabled && !!protocol && !!currentProtocolAddress && !!userAddress,
201
+ ...queryOptions,
202
+ });
203
+
204
+ // Mutation: Set requirements
205
+ const setRequirementsMutation = useMutation({
206
+ mutationFn: async (params: {
207
+ minAge: number;
208
+ jurisdictions: string[];
209
+ requireAccredited: boolean;
210
+ }) => {
211
+ if (!protocol) {
212
+ throw new Error('Protocol client not available');
213
+ }
214
+ return protocol.setRequirements(params);
215
+ },
216
+ onSuccess: () => {
217
+ // Invalidate and refetch requirements
218
+ queryClient.invalidateQueries({
219
+ queryKey: ['protocol', 'requirements'],
220
+ });
221
+ },
222
+ });
223
+
224
+ // Mutation: Verify and grant access
225
+ const verifyAndGrantAccessMutation = useMutation({
226
+ mutationFn: async (params: {
227
+ proof: {
228
+ a: [string, string];
229
+ b: [[string, string], [string, string]];
230
+ c: [string, string];
231
+ };
232
+ publicSignals: string[];
233
+ credentialHash: string;
234
+ userAddress: string;
235
+ }) => {
236
+ if (!protocol || !currentProtocolAddress) {
237
+ throw new Error('Protocol client or address not available');
238
+ }
239
+ return protocol.verifyUserAccess({
240
+ userAddress: params.userAddress,
241
+ proof: params.proof,
242
+ publicSignals: params.publicSignals,
243
+ credentialHash: params.credentialHash,
244
+ });
245
+ },
246
+ onSuccess: () => {
247
+ // Invalidate and refetch access status
248
+ queryClient.invalidateQueries({
249
+ queryKey: ['protocol', 'access'],
250
+ });
251
+ },
252
+ });
253
+
254
+ return {
255
+ protocol,
256
+ requirements,
257
+ isLoadingRequirements,
258
+ requirementsError: requirementsError as Error | null,
259
+ refetchRequirements: () => {
260
+ refetchRequirements();
261
+ },
262
+ hasAccess,
263
+ isLoadingAccess,
264
+ accessError: accessError as Error | null,
265
+ refetchAccess: () => {
266
+ refetchAccess();
267
+ },
268
+ setRequirements: {
269
+ mutate: setRequirementsMutation.mutate,
270
+ mutateAsync: setRequirementsMutation.mutateAsync,
271
+ isLoading: setRequirementsMutation.isPending,
272
+ error: setRequirementsMutation.error as Error | null,
273
+ reset: setRequirementsMutation.reset,
274
+ },
275
+ verifyAndGrantAccess: {
276
+ mutate: verifyAndGrantAccessMutation.mutate,
277
+ mutateAsync: verifyAndGrantAccessMutation.mutateAsync,
278
+ isLoading: verifyAndGrantAccessMutation.isPending,
279
+ error: verifyAndGrantAccessMutation.error as Error | null,
280
+ reset: verifyAndGrantAccessMutation.reset,
281
+ },
282
+ };
283
+ }
284
+