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.
- package/README.md +892 -0
- package/dist/core/APIClient.d.ts +71 -0
- package/dist/core/APIClient.d.ts.map +1 -0
- package/dist/core/APIClient.js +92 -0
- package/dist/core/APIClient.js.map +1 -0
- package/dist/core/ContractClient.d.ts +38 -0
- package/dist/core/ContractClient.d.ts.map +1 -0
- package/dist/core/ContractClient.js +209 -0
- package/dist/core/ContractClient.js.map +1 -0
- package/dist/core/NoahSDK.d.ts +43 -0
- package/dist/core/NoahSDK.d.ts.map +1 -0
- package/dist/core/NoahSDK.js +93 -0
- package/dist/core/NoahSDK.js.map +1 -0
- package/dist/core/WalletAdapter.d.ts +188 -0
- package/dist/core/WalletAdapter.d.ts.map +1 -0
- package/dist/core/WalletAdapter.js +425 -0
- package/dist/core/WalletAdapter.js.map +1 -0
- package/dist/hooks/index.d.ts +18 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +15 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/useCredentials.d.ts +136 -0
- package/dist/hooks/useCredentials.d.ts.map +1 -0
- package/dist/hooks/useCredentials.js +217 -0
- package/dist/hooks/useCredentials.js.map +1 -0
- package/dist/hooks/useProtocol.d.ts +117 -0
- package/dist/hooks/useProtocol.d.ts.map +1 -0
- package/dist/hooks/useProtocol.js +165 -0
- package/dist/hooks/useProtocol.js.map +1 -0
- package/dist/hooks/useUser.d.ts +159 -0
- package/dist/hooks/useUser.d.ts.map +1 -0
- package/dist/hooks/useUser.js +188 -0
- package/dist/hooks/useUser.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/issuer/IssuerClient.d.ts +98 -0
- package/dist/issuer/IssuerClient.d.ts.map +1 -0
- package/dist/issuer/IssuerClient.js +159 -0
- package/dist/issuer/IssuerClient.js.map +1 -0
- package/dist/protocol/ProtocolClient.d.ts +124 -0
- package/dist/protocol/ProtocolClient.d.ts.map +1 -0
- package/dist/protocol/ProtocolClient.js +265 -0
- package/dist/protocol/ProtocolClient.js.map +1 -0
- package/dist/protocol/RequirementsManager.d.ts +9 -0
- package/dist/protocol/RequirementsManager.d.ts.map +1 -0
- package/dist/protocol/RequirementsManager.js +9 -0
- package/dist/protocol/RequirementsManager.js.map +1 -0
- package/dist/user/ProofGenerator.d.ts +49 -0
- package/dist/user/ProofGenerator.d.ts.map +1 -0
- package/dist/user/ProofGenerator.js +80 -0
- package/dist/user/ProofGenerator.js.map +1 -0
- package/dist/user/UserClient.d.ts +191 -0
- package/dist/user/UserClient.d.ts.map +1 -0
- package/dist/user/UserClient.js +338 -0
- package/dist/user/UserClient.js.map +1 -0
- package/dist/utils/credentials.d.ts +47 -0
- package/dist/utils/credentials.d.ts.map +1 -0
- package/dist/utils/credentials.js +99 -0
- package/dist/utils/credentials.js.map +1 -0
- package/dist/utils/identity.d.ts +22 -0
- package/dist/utils/identity.d.ts.map +1 -0
- package/dist/utils/identity.js +35 -0
- package/dist/utils/identity.js.map +1 -0
- package/dist/utils/jurisdiction.d.ts +21 -0
- package/dist/utils/jurisdiction.d.ts.map +1 -0
- package/dist/utils/jurisdiction.js +64 -0
- package/dist/utils/jurisdiction.js.map +1 -0
- package/dist/utils/mrz.d.ts +16 -0
- package/dist/utils/mrz.d.ts.map +1 -0
- package/dist/utils/mrz.js +91 -0
- package/dist/utils/mrz.js.map +1 -0
- package/dist/utils/ocr.d.ts +31 -0
- package/dist/utils/ocr.d.ts.map +1 -0
- package/dist/utils/ocr.js +69 -0
- package/dist/utils/ocr.js.map +1 -0
- package/dist/utils/types.d.ts +122 -0
- package/dist/utils/types.d.ts.map +1 -0
- package/dist/utils/types.js +2 -0
- package/dist/utils/types.js.map +1 -0
- package/package.json +53 -0
- package/src/core/APIClient.ts +165 -0
- package/src/core/ContractClient.ts +266 -0
- package/src/core/NoahSDK.ts +123 -0
- package/src/core/WalletAdapter.ts +546 -0
- package/src/hooks/index.ts +31 -0
- package/src/hooks/types.d.ts +18 -0
- package/src/hooks/useCredentials.ts +359 -0
- package/src/hooks/useProtocol.ts +284 -0
- package/src/hooks/useUser.ts +331 -0
- package/src/index.ts +80 -0
- package/src/issuer/IssuerClient.ts +209 -0
- package/src/protocol/ProtocolClient.ts +330 -0
- package/src/protocol/RequirementsManager.ts +16 -0
- package/src/user/ProofGenerator.ts +113 -0
- package/src/user/UserClient.ts +440 -0
- package/src/utils/credentials.ts +122 -0
- package/src/utils/identity.ts +46 -0
- package/src/utils/jurisdiction.ts +83 -0
- package/src/utils/mrz.ts +113 -0
- package/src/utils/ocr.ts +84 -0
- package/src/utils/types.ts +144 -0
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
|
2
|
+
import { useMemo, useState, useEffect } from 'react';
|
|
3
|
+
import type { Signer } from 'ethers';
|
|
4
|
+
import { UserClient, type Credential as UserCredential } from '../user/UserClient';
|
|
5
|
+
import type { Requirements, TransactionResult, ZKProof } from '../utils/types';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Configuration options for useUser hook
|
|
9
|
+
*/
|
|
10
|
+
export interface UseUserOptions {
|
|
11
|
+
/** User's wallet address */
|
|
12
|
+
userAddress?: string;
|
|
13
|
+
/** Protocol address to check requirements/access for */
|
|
14
|
+
protocolAddress?: string;
|
|
15
|
+
/** Credential hash to check validity for */
|
|
16
|
+
credentialHash?: string;
|
|
17
|
+
/** Whether to enable automatic refetching */
|
|
18
|
+
enabled?: boolean;
|
|
19
|
+
/** React Query configuration options */
|
|
20
|
+
queryOptions?: {
|
|
21
|
+
refetchInterval?: number;
|
|
22
|
+
staleTime?: number;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Credential structure (re-exported from UserClient for convenience)
|
|
28
|
+
*/
|
|
29
|
+
export type Credential = UserCredential;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Return type for useUser hook
|
|
33
|
+
*/
|
|
34
|
+
export interface UseUserReturn {
|
|
35
|
+
// User client instance
|
|
36
|
+
user: UserClient | null;
|
|
37
|
+
|
|
38
|
+
// Read operations
|
|
39
|
+
protocolRequirements: Requirements | undefined;
|
|
40
|
+
isLoadingRequirements: boolean;
|
|
41
|
+
requirementsError: Error | null;
|
|
42
|
+
refetchRequirements: () => void;
|
|
43
|
+
|
|
44
|
+
// Credential validation
|
|
45
|
+
isCredentialValid: boolean | undefined;
|
|
46
|
+
isLoadingCredential: boolean;
|
|
47
|
+
credentialError: Error | null;
|
|
48
|
+
refetchCredential: () => void;
|
|
49
|
+
|
|
50
|
+
// Write operations (mutations)
|
|
51
|
+
checkCredentialValidity: {
|
|
52
|
+
mutate: (credentialHash: string) => void;
|
|
53
|
+
mutateAsync: (credentialHash: string) => Promise<boolean>;
|
|
54
|
+
isLoading: boolean;
|
|
55
|
+
error: Error | null;
|
|
56
|
+
reset: () => void;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
generateProof: {
|
|
60
|
+
mutate: (params: {
|
|
61
|
+
credential: Credential;
|
|
62
|
+
requirements: Requirements & { protocolAddress: string };
|
|
63
|
+
}) => void;
|
|
64
|
+
mutateAsync: (params: {
|
|
65
|
+
credential: Credential;
|
|
66
|
+
requirements: Requirements & { protocolAddress: string };
|
|
67
|
+
}) => Promise<{
|
|
68
|
+
proof: ZKProof;
|
|
69
|
+
publicSignals: string[];
|
|
70
|
+
nullifier: string;
|
|
71
|
+
packedFlags: number;
|
|
72
|
+
credentialHash: string;
|
|
73
|
+
success: boolean;
|
|
74
|
+
}>;
|
|
75
|
+
isLoading: boolean;
|
|
76
|
+
error: Error | null;
|
|
77
|
+
reset: () => void;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
verifyAndGrantAccess: {
|
|
81
|
+
mutate: (params: {
|
|
82
|
+
proof: ZKProof;
|
|
83
|
+
publicSignals: string[];
|
|
84
|
+
nullifier: string;
|
|
85
|
+
packedFlags: number;
|
|
86
|
+
credentialHash: string;
|
|
87
|
+
protocolAddress?: string;
|
|
88
|
+
userAddress?: string;
|
|
89
|
+
}) => void;
|
|
90
|
+
mutateAsync: (params: {
|
|
91
|
+
proof: ZKProof;
|
|
92
|
+
publicSignals: string[];
|
|
93
|
+
nullifier: string;
|
|
94
|
+
packedFlags: number;
|
|
95
|
+
credentialHash: string;
|
|
96
|
+
protocolAddress?: string;
|
|
97
|
+
userAddress?: string;
|
|
98
|
+
}) => Promise<TransactionResult>;
|
|
99
|
+
isLoading: boolean;
|
|
100
|
+
error: Error | null;
|
|
101
|
+
reset: () => void;
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* React hook for user operations
|
|
107
|
+
*
|
|
108
|
+
* Provides easy access to user-related functionality including:
|
|
109
|
+
* - Getting protocol requirements
|
|
110
|
+
* - Checking credential validity
|
|
111
|
+
* - Generating ZK proofs
|
|
112
|
+
* - Verifying proofs and granting access to protocols
|
|
113
|
+
*
|
|
114
|
+
* @param signer - Ethers signer instance (from wallet)
|
|
115
|
+
* @param options - Configuration options
|
|
116
|
+
* @returns Hook return object with user operations
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```tsx
|
|
120
|
+
* import { useUser } from '@noah-protocol/sdk/hooks';
|
|
121
|
+
* import { useSigner, useAccount } from 'wagmi';
|
|
122
|
+
*
|
|
123
|
+
* function UserDashboard() {
|
|
124
|
+
* const { data: signer } = useSigner();
|
|
125
|
+
* const { address } = useAccount();
|
|
126
|
+
* const {
|
|
127
|
+
* protocolRequirements,
|
|
128
|
+
* generateProof,
|
|
129
|
+
* verifyAndGrantAccess,
|
|
130
|
+
* hasAccess
|
|
131
|
+
* } = useUser(signer, {
|
|
132
|
+
* userAddress: address,
|
|
133
|
+
* protocolAddress: '0x...',
|
|
134
|
+
* apiBaseUrl: 'https://api.noah.xyz'
|
|
135
|
+
* });
|
|
136
|
+
*
|
|
137
|
+
* const handleGenerateProof = async () => {
|
|
138
|
+
* const result = await generateProof.mutateAsync({
|
|
139
|
+
* credential: {
|
|
140
|
+
* actualAge: 25,
|
|
141
|
+
* actualJurisdiction: 'US',
|
|
142
|
+
* actualAccredited: true,
|
|
143
|
+
* credentialHash: '0x...'
|
|
144
|
+
* },
|
|
145
|
+
* requirements: protocolRequirements!
|
|
146
|
+
* });
|
|
147
|
+
*
|
|
148
|
+
* await verifyAndGrantAccess.mutateAsync({
|
|
149
|
+
* ...result,
|
|
150
|
+
* credentialHash: '0x...',
|
|
151
|
+
* protocolAddress: '0x...'
|
|
152
|
+
* });
|
|
153
|
+
* };
|
|
154
|
+
*
|
|
155
|
+
* return (
|
|
156
|
+
* <div>
|
|
157
|
+
* {hasAccess ? (
|
|
158
|
+
* <p>You have access!</p>
|
|
159
|
+
* ) : (
|
|
160
|
+
* <button onClick={handleGenerateProof}>
|
|
161
|
+
* Request Access
|
|
162
|
+
* </button>
|
|
163
|
+
* )}
|
|
164
|
+
* </div>
|
|
165
|
+
* );
|
|
166
|
+
* }
|
|
167
|
+
* ```
|
|
168
|
+
*/
|
|
169
|
+
export function useUser(
|
|
170
|
+
signer: Signer | null | undefined,
|
|
171
|
+
options: UseUserOptions = {}
|
|
172
|
+
): UseUserReturn {
|
|
173
|
+
const {
|
|
174
|
+
userAddress,
|
|
175
|
+
protocolAddress,
|
|
176
|
+
credentialHash,
|
|
177
|
+
enabled = true,
|
|
178
|
+
queryOptions = {},
|
|
179
|
+
} = options;
|
|
180
|
+
|
|
181
|
+
const queryClient = useQueryClient();
|
|
182
|
+
|
|
183
|
+
// Create user client instance
|
|
184
|
+
const user = useMemo(() => {
|
|
185
|
+
if (!signer) return null;
|
|
186
|
+
try {
|
|
187
|
+
return new UserClient(signer);
|
|
188
|
+
} catch (error) {
|
|
189
|
+
console.warn('UserClient not available:', error);
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
}, [signer]);
|
|
193
|
+
|
|
194
|
+
// Note: userAddress is used directly in queries below
|
|
195
|
+
|
|
196
|
+
// Query: Get protocol requirements
|
|
197
|
+
const {
|
|
198
|
+
data: protocolRequirements,
|
|
199
|
+
isLoading: isLoadingRequirements,
|
|
200
|
+
error: requirementsError,
|
|
201
|
+
refetch: refetchRequirements,
|
|
202
|
+
} = useQuery({
|
|
203
|
+
queryKey: ['user', 'protocol-requirements', protocolAddress],
|
|
204
|
+
queryFn: async () => {
|
|
205
|
+
if (!user || !protocolAddress) {
|
|
206
|
+
throw new Error('User client or protocol address not available');
|
|
207
|
+
}
|
|
208
|
+
return user.getProtocolRequirements(protocolAddress);
|
|
209
|
+
},
|
|
210
|
+
enabled: enabled && !!user && !!protocolAddress,
|
|
211
|
+
...queryOptions,
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
// Note: To check user access, use the useProtocol hook instead
|
|
215
|
+
// This is because access checking is a protocol-level operation
|
|
216
|
+
|
|
217
|
+
// Query: Check credential validity
|
|
218
|
+
const {
|
|
219
|
+
data: isCredentialValid,
|
|
220
|
+
isLoading: isLoadingCredential,
|
|
221
|
+
error: credentialError,
|
|
222
|
+
refetch: refetchCredential,
|
|
223
|
+
} = useQuery({
|
|
224
|
+
queryKey: ['user', 'credential-validity', credentialHash],
|
|
225
|
+
queryFn: async () => {
|
|
226
|
+
if (!user || !credentialHash) {
|
|
227
|
+
throw new Error('User client or credential hash not available');
|
|
228
|
+
}
|
|
229
|
+
return user.checkCredentialValidity(credentialHash);
|
|
230
|
+
},
|
|
231
|
+
enabled: enabled && !!user && !!credentialHash,
|
|
232
|
+
...queryOptions,
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
// Mutation: Check credential validity
|
|
236
|
+
const checkCredentialValidityMutation = useMutation({
|
|
237
|
+
mutationFn: async (credentialHash: string) => {
|
|
238
|
+
if (!user) {
|
|
239
|
+
throw new Error('User client not available');
|
|
240
|
+
}
|
|
241
|
+
return user.checkCredentialValidity(credentialHash);
|
|
242
|
+
},
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
// Mutation: Generate proof
|
|
246
|
+
const generateProofMutation = useMutation({
|
|
247
|
+
mutationFn: async (params: {
|
|
248
|
+
credential: Credential;
|
|
249
|
+
requirements: Requirements & { protocolAddress: string };
|
|
250
|
+
}) => {
|
|
251
|
+
if (!user) {
|
|
252
|
+
throw new Error('User client not available');
|
|
253
|
+
}
|
|
254
|
+
return user.generateProof(params.credential, params.requirements);
|
|
255
|
+
},
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
// Mutation: Verify and grant access
|
|
259
|
+
const verifyAndGrantAccessMutation = useMutation({
|
|
260
|
+
mutationFn: async (params: {
|
|
261
|
+
proof: ZKProof;
|
|
262
|
+
publicSignals: string[];
|
|
263
|
+
nullifier: string;
|
|
264
|
+
packedFlags: number;
|
|
265
|
+
credentialHash: string;
|
|
266
|
+
protocolAddress?: string;
|
|
267
|
+
userAddress?: string;
|
|
268
|
+
}) => {
|
|
269
|
+
if (!user) {
|
|
270
|
+
throw new Error('User client not available');
|
|
271
|
+
}
|
|
272
|
+
// UserClient.verifyAndGrantAccess expects a ProofResult object
|
|
273
|
+
return user.verifyAndGrantAccess(
|
|
274
|
+
{
|
|
275
|
+
proof: params.proof,
|
|
276
|
+
publicSignals: params.publicSignals,
|
|
277
|
+
nullifier: params.nullifier,
|
|
278
|
+
packedFlags: params.packedFlags,
|
|
279
|
+
credentialHash: params.credentialHash,
|
|
280
|
+
success: true,
|
|
281
|
+
},
|
|
282
|
+
params.protocolAddress,
|
|
283
|
+
params.userAddress
|
|
284
|
+
);
|
|
285
|
+
},
|
|
286
|
+
onSuccess: () => {
|
|
287
|
+
// Invalidate and refetch access status
|
|
288
|
+
queryClient.invalidateQueries({
|
|
289
|
+
queryKey: ['user', 'access'],
|
|
290
|
+
});
|
|
291
|
+
},
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
return {
|
|
295
|
+
user,
|
|
296
|
+
protocolRequirements,
|
|
297
|
+
isLoadingRequirements,
|
|
298
|
+
requirementsError: requirementsError as Error | null,
|
|
299
|
+
refetchRequirements: () => {
|
|
300
|
+
refetchRequirements();
|
|
301
|
+
},
|
|
302
|
+
isCredentialValid,
|
|
303
|
+
isLoadingCredential,
|
|
304
|
+
credentialError: credentialError as Error | null,
|
|
305
|
+
refetchCredential: () => {
|
|
306
|
+
refetchCredential();
|
|
307
|
+
},
|
|
308
|
+
checkCredentialValidity: {
|
|
309
|
+
mutate: checkCredentialValidityMutation.mutate,
|
|
310
|
+
mutateAsync: checkCredentialValidityMutation.mutateAsync,
|
|
311
|
+
isLoading: checkCredentialValidityMutation.isPending,
|
|
312
|
+
error: checkCredentialValidityMutation.error as Error | null,
|
|
313
|
+
reset: checkCredentialValidityMutation.reset,
|
|
314
|
+
},
|
|
315
|
+
generateProof: {
|
|
316
|
+
mutate: generateProofMutation.mutate,
|
|
317
|
+
mutateAsync: generateProofMutation.mutateAsync,
|
|
318
|
+
isLoading: generateProofMutation.isPending,
|
|
319
|
+
error: generateProofMutation.error as Error | null,
|
|
320
|
+
reset: generateProofMutation.reset,
|
|
321
|
+
},
|
|
322
|
+
verifyAndGrantAccess: {
|
|
323
|
+
mutate: verifyAndGrantAccessMutation.mutate,
|
|
324
|
+
mutateAsync: verifyAndGrantAccessMutation.mutateAsync,
|
|
325
|
+
isLoading: verifyAndGrantAccessMutation.isPending,
|
|
326
|
+
error: verifyAndGrantAccessMutation.error as Error | null,
|
|
327
|
+
reset: verifyAndGrantAccessMutation.reset,
|
|
328
|
+
},
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NOAH Protocol SDK
|
|
3
|
+
*
|
|
4
|
+
* TypeScript/JavaScript SDK for integrating NOAH's privacy-preserving KYC functionality
|
|
5
|
+
* into DeFi protocols and applications.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Core exports
|
|
9
|
+
export { NoahSDK, NoahError, NoahValidationError, NoahProverError } from './core/NoahSDK.js';
|
|
10
|
+
export { ContractClient } from './core/ContractClient.js';
|
|
11
|
+
export { APIClient } from './core/APIClient.js';
|
|
12
|
+
export { WalletAdapter } from './core/WalletAdapter.js';
|
|
13
|
+
export type { WalletAdapterConfig, WalletState, WalletType } from './core/WalletAdapter.js';
|
|
14
|
+
|
|
15
|
+
// Protocol exports
|
|
16
|
+
export { ProtocolClient } from './protocol/ProtocolClient.js';
|
|
17
|
+
export { RequirementsManager } from './protocol/RequirementsManager.js';
|
|
18
|
+
|
|
19
|
+
// User exports
|
|
20
|
+
export { UserClient } from './user/UserClient.js';
|
|
21
|
+
export { ProofGenerator } from './user/ProofGenerator.js';
|
|
22
|
+
export type { Credential, ProofResult, UserClientConfig } from './user/UserClient.js';
|
|
23
|
+
|
|
24
|
+
// Issuer exports
|
|
25
|
+
export { IssuerClient } from './issuer/IssuerClient.js';
|
|
26
|
+
|
|
27
|
+
// Utilities
|
|
28
|
+
export {
|
|
29
|
+
jurisdictionStringToHash,
|
|
30
|
+
jurisdictionStringsToHashes,
|
|
31
|
+
parseJurisdictions,
|
|
32
|
+
} from './utils/jurisdiction.js';
|
|
33
|
+
|
|
34
|
+
export {
|
|
35
|
+
generateCredentialHash,
|
|
36
|
+
isValidCredentialHash,
|
|
37
|
+
isValidAddress,
|
|
38
|
+
toChecksumAddress,
|
|
39
|
+
} from './utils/credentials.js';
|
|
40
|
+
|
|
41
|
+
export {
|
|
42
|
+
parseTD3,
|
|
43
|
+
validateCheckDigit,
|
|
44
|
+
} from './utils/mrz.js';
|
|
45
|
+
export type { MRZData } from './utils/mrz.js';
|
|
46
|
+
|
|
47
|
+
export { OCRExtractor } from './utils/ocr.js';
|
|
48
|
+
export type { OCROutput } from './utils/ocr.js';
|
|
49
|
+
|
|
50
|
+
export { IdentityManager } from './utils/identity.js';
|
|
51
|
+
export type { IdentityProfile } from './utils/identity.js';
|
|
52
|
+
|
|
53
|
+
// Type exports
|
|
54
|
+
export type {
|
|
55
|
+
ContractAddresses,
|
|
56
|
+
Requirements,
|
|
57
|
+
IssuerInfo,
|
|
58
|
+
Proof,
|
|
59
|
+
ZKProof,
|
|
60
|
+
TransactionResult,
|
|
61
|
+
ContractClientConfig,
|
|
62
|
+
ProtocolClientConfig,
|
|
63
|
+
SetRequirementsParams,
|
|
64
|
+
VerifyUserAccessParams,
|
|
65
|
+
CredentialIssuedEvent,
|
|
66
|
+
AccessGrantedEvent,
|
|
67
|
+
EventCallback,
|
|
68
|
+
ContractEventPayload,
|
|
69
|
+
CredentialData,
|
|
70
|
+
CredentialHashResult,
|
|
71
|
+
} from './utils/types.js';
|
|
72
|
+
|
|
73
|
+
// API Client types
|
|
74
|
+
export type {
|
|
75
|
+
APIClientConfig,
|
|
76
|
+
ProofGenerationData,
|
|
77
|
+
ProofGenerationResult,
|
|
78
|
+
AccessStatus,
|
|
79
|
+
CredentialStatus,
|
|
80
|
+
} from './core/APIClient.js';
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import type { Signer } from 'ethers';
|
|
2
|
+
import type { TransactionResult, ContractAddresses } from '../utils/types';
|
|
3
|
+
import { ContractClient } from '../core/ContractClient';
|
|
4
|
+
import { APIClient } from '../core/APIClient';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* IssuerClient configuration options
|
|
8
|
+
*/
|
|
9
|
+
export interface IssuerClientConfig {
|
|
10
|
+
apiBaseUrl?: string;
|
|
11
|
+
contractAddresses?: Partial<ContractAddresses>;
|
|
12
|
+
rpcUrl?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Credential status information
|
|
17
|
+
*/
|
|
18
|
+
export interface CredentialStatus {
|
|
19
|
+
isValid: boolean;
|
|
20
|
+
credentialHash: string;
|
|
21
|
+
isRevoked: boolean;
|
|
22
|
+
issuer?: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* IssuerClient - High-level API for credential issuers
|
|
27
|
+
*
|
|
28
|
+
* Provides a simple interface for issuers to:
|
|
29
|
+
* - Register credentials on-chain
|
|
30
|
+
* - Revoke credentials
|
|
31
|
+
* - Check credential status
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```typescript
|
|
35
|
+
* import { IssuerClient } from '@noah-protocol/sdk';
|
|
36
|
+
* import { ethers } from 'ethers';
|
|
37
|
+
*
|
|
38
|
+
* const provider = new ethers.BrowserProvider(window.ethereum);
|
|
39
|
+
* const signer = await provider.getSigner();
|
|
40
|
+
* const issuer = new IssuerClient(signer, { apiBaseUrl: 'https://api.noah.xyz' });
|
|
41
|
+
*
|
|
42
|
+
* // Register credential
|
|
43
|
+
* await issuer.registerCredential(credentialHash, userAddress);
|
|
44
|
+
*
|
|
45
|
+
* // Revoke credential
|
|
46
|
+
* await issuer.revokeCredential(credentialHash);
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export class IssuerClient {
|
|
50
|
+
private signer: Signer;
|
|
51
|
+
private contractClient: ContractClient;
|
|
52
|
+
private apiClient: APIClient;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Create a new IssuerClient instance
|
|
56
|
+
* @param signer - Ethers.js signer from issuer's wallet
|
|
57
|
+
* @param config - Optional configuration
|
|
58
|
+
*/
|
|
59
|
+
constructor(signer: Signer, config: IssuerClientConfig = {}) {
|
|
60
|
+
if (!signer) {
|
|
61
|
+
throw new Error('Signer is required');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
this.signer = signer;
|
|
65
|
+
|
|
66
|
+
// Initialize ContractClient
|
|
67
|
+
this.contractClient = new ContractClient({
|
|
68
|
+
provider: signer.provider || undefined,
|
|
69
|
+
contractAddresses: config.contractAddresses as ContractAddresses | undefined,
|
|
70
|
+
rpcUrl: config.rpcUrl,
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// Initialize APIClient
|
|
74
|
+
this.apiClient = new APIClient({
|
|
75
|
+
baseURL: config.apiBaseUrl,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Register a credential on-chain
|
|
81
|
+
*
|
|
82
|
+
* @param credentialHash - The credential hash to register (bytes32)
|
|
83
|
+
* @param userAddress - The user's wallet address
|
|
84
|
+
* @param useAPI - If true, use backend API (gasless). If false, use direct contract call.
|
|
85
|
+
* @returns Promise resolving to transaction result
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```typescript
|
|
89
|
+
* const tx = await issuer.registerCredential('0x1234...', '0x5678...');
|
|
90
|
+
* console.log('Transaction hash:', tx.transactionHash);
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
async registerCredential(
|
|
94
|
+
credentialHash: string,
|
|
95
|
+
userAddress: string,
|
|
96
|
+
useAPI: boolean = false
|
|
97
|
+
): Promise<TransactionResult> {
|
|
98
|
+
if (!credentialHash) {
|
|
99
|
+
throw new Error('Credential hash is required');
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (!userAddress) {
|
|
103
|
+
throw new Error('User address is required');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
try {
|
|
107
|
+
if (useAPI) {
|
|
108
|
+
// Use backend API for gasless transactions
|
|
109
|
+
return await this.apiClient.registerCredential(credentialHash, userAddress);
|
|
110
|
+
} else {
|
|
111
|
+
// Use direct contract call
|
|
112
|
+
return await this.contractClient.registerCredential(
|
|
113
|
+
this.signer,
|
|
114
|
+
credentialHash,
|
|
115
|
+
userAddress
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
} catch (error: any) {
|
|
119
|
+
throw new Error(
|
|
120
|
+
`Failed to register credential: ${error.message || 'Unknown error'}`
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Revoke a credential
|
|
127
|
+
*
|
|
128
|
+
* @param credentialHash - The credential hash to revoke (bytes32)
|
|
129
|
+
* @param useAPI - If true, use backend API (gasless). If false, use direct contract call.
|
|
130
|
+
* @returns Promise resolving to transaction result
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* ```typescript
|
|
134
|
+
* const tx = await issuer.revokeCredential('0x1234...');
|
|
135
|
+
* console.log('Transaction hash:', tx.transactionHash);
|
|
136
|
+
* ```
|
|
137
|
+
*/
|
|
138
|
+
async revokeCredential(
|
|
139
|
+
credentialHash: string,
|
|
140
|
+
useAPI: boolean = false
|
|
141
|
+
): Promise<TransactionResult> {
|
|
142
|
+
if (!credentialHash) {
|
|
143
|
+
throw new Error('Credential hash is required');
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
try {
|
|
147
|
+
if (useAPI) {
|
|
148
|
+
// Use backend API for gasless transactions
|
|
149
|
+
return await this.apiClient.revokeCredential(credentialHash);
|
|
150
|
+
} else {
|
|
151
|
+
// Use direct contract call
|
|
152
|
+
return await this.contractClient.revokeCredential(
|
|
153
|
+
this.signer,
|
|
154
|
+
credentialHash
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
} catch (error: any) {
|
|
158
|
+
throw new Error(
|
|
159
|
+
`Failed to revoke credential: ${error.message || 'Unknown error'}`
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Check credential status
|
|
166
|
+
*
|
|
167
|
+
* @param credentialHash - The credential hash to check (bytes32)
|
|
168
|
+
* @returns Promise resolving to credential status information
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```typescript
|
|
172
|
+
* const status = await issuer.checkCredential('0x1234...');
|
|
173
|
+
* console.log('Is valid:', status.isValid);
|
|
174
|
+
* console.log('Is revoked:', status.isRevoked);
|
|
175
|
+
* ```
|
|
176
|
+
*/
|
|
177
|
+
async checkCredential(credentialHash: string): Promise<CredentialStatus> {
|
|
178
|
+
if (!credentialHash) {
|
|
179
|
+
throw new Error('Credential hash is required');
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
try {
|
|
183
|
+
// Check on-chain validity
|
|
184
|
+
const isValid = await this.contractClient.isCredentialValid(credentialHash);
|
|
185
|
+
|
|
186
|
+
// Get additional info from API if available
|
|
187
|
+
try {
|
|
188
|
+
const apiStatus = await this.apiClient.checkCredential(credentialHash);
|
|
189
|
+
return {
|
|
190
|
+
isValid: apiStatus.isValid && isValid,
|
|
191
|
+
credentialHash,
|
|
192
|
+
isRevoked: apiStatus.isRevoked,
|
|
193
|
+
issuer: apiStatus.issuer,
|
|
194
|
+
};
|
|
195
|
+
} catch {
|
|
196
|
+
// If API fails, return on-chain status
|
|
197
|
+
return {
|
|
198
|
+
isValid,
|
|
199
|
+
credentialHash,
|
|
200
|
+
isRevoked: !isValid,
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
} catch (error: any) {
|
|
204
|
+
throw new Error(
|
|
205
|
+
`Failed to check credential: ${error.message || 'Unknown error'}`
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|