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,330 @@
|
|
|
1
|
+
import { Contract } from 'ethers';
|
|
2
|
+
import type { Signer, Provider, ContractTransactionReceipt } from 'ethers';
|
|
3
|
+
import {
|
|
4
|
+
Requirements,
|
|
5
|
+
TransactionResult,
|
|
6
|
+
ProtocolClientConfig,
|
|
7
|
+
SetRequirementsParams,
|
|
8
|
+
VerifyUserAccessParams,
|
|
9
|
+
} from '../utils/types';
|
|
10
|
+
import { jurisdictionStringsToHashes } from '../utils/jurisdiction';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Protocol Access Control ABI (minimal for required operations)
|
|
14
|
+
*/
|
|
15
|
+
const PROTOCOL_ACCESS_CONTROL_ABI = [
|
|
16
|
+
'function hasAccess(address protocol, address user) view returns (bool)',
|
|
17
|
+
'function protocolRequirements(address) view returns (uint256 minAge, bool requireAccredited, bool isSet)',
|
|
18
|
+
'function setRequirements(uint256 minAge, uint256[] memory allowedJurisdictions, bool requireAccredited)',
|
|
19
|
+
'function verifyAndGrantAccess(uint[2] a, uint[2][2] b, uint[2] c, uint[13] publicSignals, bytes32 credentialHash, address user)',
|
|
20
|
+
'event AccessGranted(address indexed user, address indexed protocol, bytes32 credentialHash, uint256 timestamp)',
|
|
21
|
+
'event RequirementsSet(address indexed protocol, uint256 minAge, uint256[] allowedJurisdictions, bool requireAccredited)',
|
|
22
|
+
] as const;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Default Protocol Access Control contract address (Mantle Sepolia)
|
|
26
|
+
* Can be overridden via config
|
|
27
|
+
*/
|
|
28
|
+
const DEFAULT_PROTOCOL_ACCESS_CONTROL_ADDRESS = '0xF599F186aC6fD2a9bECd9eDEE91fd58D3Dc3dB0A';
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* ProtocolClient - High-level API for DeFi protocol integration
|
|
32
|
+
*
|
|
33
|
+
* Provides a simple interface for protocols to:
|
|
34
|
+
* - Set KYC requirements (minAge, jurisdictions, accredited status)
|
|
35
|
+
* - Check if users have access
|
|
36
|
+
* - Verify ZK proofs and grant access to users
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```typescript
|
|
40
|
+
* import { ProtocolClient } from '@noah-protocol/sdk';
|
|
41
|
+
* import { ethers } from 'ethers';
|
|
42
|
+
*
|
|
43
|
+
* const provider = new ethers.BrowserProvider(window.ethereum);
|
|
44
|
+
* const signer = await provider.getSigner();
|
|
45
|
+
* const protocol = new ProtocolClient(signer);
|
|
46
|
+
*
|
|
47
|
+
* // Set requirements
|
|
48
|
+
* await protocol.setRequirements({
|
|
49
|
+
* minAge: 21,
|
|
50
|
+
* jurisdictions: ['US', 'UK', 'CA'],
|
|
51
|
+
* requireAccredited: true
|
|
52
|
+
* });
|
|
53
|
+
*
|
|
54
|
+
* // Check user access
|
|
55
|
+
* const hasAccess = await protocol.checkUserAccess(protocolAddress, userAddress);
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export class ProtocolClient {
|
|
59
|
+
private signer: Signer;
|
|
60
|
+
private provider: Provider;
|
|
61
|
+
private protocolAccessControlAddress: string;
|
|
62
|
+
private contract: Contract | null = null;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Create a new ProtocolClient instance
|
|
66
|
+
*
|
|
67
|
+
* @param signer - Ethers signer (from wallet connection)
|
|
68
|
+
* @param config - Optional configuration (contract address, provider)
|
|
69
|
+
*/
|
|
70
|
+
constructor(signer: Signer, config?: ProtocolClientConfig) {
|
|
71
|
+
if (!signer) {
|
|
72
|
+
throw new Error('Signer is required');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
this.signer = signer;
|
|
76
|
+
this.provider = config?.provider || signer.provider!;
|
|
77
|
+
|
|
78
|
+
if (!this.provider) {
|
|
79
|
+
throw new Error('Provider is required. Pass it via config or ensure signer has a provider.');
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
this.protocolAccessControlAddress =
|
|
83
|
+
config?.protocolAccessControlAddress ||
|
|
84
|
+
DEFAULT_PROTOCOL_ACCESS_CONTROL_ADDRESS;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Get or create the ProtocolAccessControl contract instance
|
|
89
|
+
* Uses signer for write operations, provider for read operations
|
|
90
|
+
*/
|
|
91
|
+
private getContract(): Contract {
|
|
92
|
+
if (!this.contract) {
|
|
93
|
+
this.contract = new Contract(
|
|
94
|
+
this.protocolAccessControlAddress,
|
|
95
|
+
PROTOCOL_ACCESS_CONTROL_ABI,
|
|
96
|
+
this.signer
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
return this.contract;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Get read-only contract instance (for queries)
|
|
104
|
+
*/
|
|
105
|
+
private getReadOnlyContract(): Contract {
|
|
106
|
+
return new Contract(
|
|
107
|
+
this.protocolAccessControlAddress,
|
|
108
|
+
PROTOCOL_ACCESS_CONTROL_ABI,
|
|
109
|
+
this.provider
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Set protocol requirements for KYC verification
|
|
115
|
+
*
|
|
116
|
+
* @param params - Requirements parameters
|
|
117
|
+
* @param params.minAge - Minimum age required (must be positive integer)
|
|
118
|
+
* @param params.jurisdictions - Array of allowed jurisdiction hashes (strings or numbers)
|
|
119
|
+
* @param params.requireAccredited - Whether accredited investor status is required
|
|
120
|
+
* @returns Promise resolving to transaction result
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* ```typescript
|
|
124
|
+
* const tx = await protocol.setRequirements({
|
|
125
|
+
* minAge: 21,
|
|
126
|
+
* jurisdictions: ['1234567890', '1111111111'],
|
|
127
|
+
* requireAccredited: true
|
|
128
|
+
* });
|
|
129
|
+
* console.log('Transaction hash:', tx.transactionHash);
|
|
130
|
+
* ```
|
|
131
|
+
*/
|
|
132
|
+
async setRequirements(params: SetRequirementsParams): Promise<TransactionResult> {
|
|
133
|
+
const { minAge, jurisdictions, requireAccredited } = params;
|
|
134
|
+
|
|
135
|
+
if (minAge < 0 || !Number.isInteger(minAge)) {
|
|
136
|
+
throw new Error('minAge must be a non-negative integer');
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (!Array.isArray(jurisdictions)) {
|
|
140
|
+
throw new Error('jurisdictions must be an array');
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (jurisdictions.length > 10) {
|
|
144
|
+
throw new Error('Maximum 10 jurisdictions allowed');
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Convert jurisdictions to BigInt array
|
|
148
|
+
// First, check if they're jurisdiction strings (like "US", "UK") or already hashes
|
|
149
|
+
let jurisdictionsToProcess: (string | number)[];
|
|
150
|
+
|
|
151
|
+
// Check if any jurisdiction is a string that's not numeric (like "US", "UK")
|
|
152
|
+
const hasStringJurisdictions = jurisdictions.some(j =>
|
|
153
|
+
typeof j === 'string' && !j.startsWith('0x') && !/^\d+$/.test(j)
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
if (hasStringJurisdictions) {
|
|
157
|
+
// Convert jurisdiction strings to hashes
|
|
158
|
+
const jurisdictionStrings = jurisdictions.map(j => String(j));
|
|
159
|
+
const hashes = jurisdictionStringsToHashes(jurisdictionStrings);
|
|
160
|
+
jurisdictionsToProcess = hashes;
|
|
161
|
+
} else {
|
|
162
|
+
jurisdictionsToProcess = jurisdictions;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Convert to BigInt array
|
|
166
|
+
const jurisdictionsArray = jurisdictionsToProcess.map(j => {
|
|
167
|
+
if (typeof j === 'string') {
|
|
168
|
+
if (j.startsWith('0x')) {
|
|
169
|
+
return BigInt(j);
|
|
170
|
+
}
|
|
171
|
+
return BigInt(j);
|
|
172
|
+
}
|
|
173
|
+
return BigInt(j);
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
try {
|
|
177
|
+
const contract = this.getContract();
|
|
178
|
+
const tx = await contract.setRequirements(
|
|
179
|
+
BigInt(minAge),
|
|
180
|
+
jurisdictionsArray,
|
|
181
|
+
requireAccredited
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
const receipt = await tx.wait();
|
|
185
|
+
|
|
186
|
+
return {
|
|
187
|
+
transactionHash: tx.hash,
|
|
188
|
+
receipt: receipt as ContractTransactionReceipt,
|
|
189
|
+
};
|
|
190
|
+
} catch (error) {
|
|
191
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
192
|
+
throw new Error(`Failed to set requirements: ${errorMessage}`);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Get protocol requirements
|
|
198
|
+
*
|
|
199
|
+
* @param protocolAddress - The protocol contract address (defaults to signer's address)
|
|
200
|
+
* @returns Promise resolving to requirements object
|
|
201
|
+
*
|
|
202
|
+
* @example
|
|
203
|
+
* ```typescript
|
|
204
|
+
* const requirements = await protocol.getRequirements(protocolAddress);
|
|
205
|
+
* console.log('Min age:', requirements.minAge);
|
|
206
|
+
* console.log('Jurisdictions:', requirements.allowedJurisdictions);
|
|
207
|
+
* ```
|
|
208
|
+
*/
|
|
209
|
+
async getRequirements(protocolAddress?: string): Promise<Requirements> {
|
|
210
|
+
const address = protocolAddress || (await this.signer.getAddress());
|
|
211
|
+
|
|
212
|
+
try {
|
|
213
|
+
const contract = this.getReadOnlyContract();
|
|
214
|
+
const [minAge, requireAccredited, isSet] =
|
|
215
|
+
await contract.protocolRequirements(address);
|
|
216
|
+
|
|
217
|
+
return {
|
|
218
|
+
minAge: Number(minAge),
|
|
219
|
+
allowedJurisdictions: [], // Public mapping getter does not return arrays
|
|
220
|
+
requireAccredited,
|
|
221
|
+
isSet,
|
|
222
|
+
};
|
|
223
|
+
} catch (error) {
|
|
224
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
225
|
+
throw new Error(`Failed to get requirements: ${errorMessage}`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Verify ZK proof and grant access to a user
|
|
231
|
+
*
|
|
232
|
+
* @param params - Verification parameters
|
|
233
|
+
* @param params.userAddress - The user's wallet address
|
|
234
|
+
* @param params.proof - ZK proof object (Groth16 format)
|
|
235
|
+
* @param params.publicSignals - Public signals array (13 elements)
|
|
236
|
+
* @param params.credentialHash - The credential hash (bytes32)
|
|
237
|
+
* @returns Promise resolving to transaction result
|
|
238
|
+
*
|
|
239
|
+
* @example
|
|
240
|
+
* ```typescript
|
|
241
|
+
* const tx = await protocol.verifyUserAccess({
|
|
242
|
+
* userAddress: '0x...',
|
|
243
|
+
* proof: { a: [...], b: [...], c: [...] },
|
|
244
|
+
* publicSignals: ['21', '1234567890', ...],
|
|
245
|
+
* credentialHash: '0x...'
|
|
246
|
+
* });
|
|
247
|
+
* ```
|
|
248
|
+
*/
|
|
249
|
+
async verifyUserAccess(params: VerifyUserAccessParams): Promise<TransactionResult> {
|
|
250
|
+
const { userAddress, proof, publicSignals, credentialHash } = params;
|
|
251
|
+
|
|
252
|
+
if (!proof.a || !Array.isArray(proof.a) || proof.a.length !== 2) {
|
|
253
|
+
throw new Error('Proof.a must be an array of 2 elements');
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
if (!proof.b || !Array.isArray(proof.b) || proof.b.length !== 2) {
|
|
257
|
+
throw new Error('Proof.b must be an array of 2 arrays');
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if (!proof.c || !Array.isArray(proof.c) || proof.c.length !== 2) {
|
|
261
|
+
throw new Error('Proof.c must be an array of 2 elements');
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
if (!Array.isArray(publicSignals) || publicSignals.length < 13) {
|
|
265
|
+
throw new Error('publicSignals must be an array of at least 13 elements');
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Convert proof arrays to BigInt arrays
|
|
269
|
+
const a: [bigint, bigint] = [BigInt(proof.a[0]), BigInt(proof.a[1])];
|
|
270
|
+
const b: [[bigint, bigint], [bigint, bigint]] = [
|
|
271
|
+
[BigInt(proof.b[0][0]), BigInt(proof.b[0][1])],
|
|
272
|
+
[BigInt(proof.b[1][0]), BigInt(proof.b[1][1])],
|
|
273
|
+
];
|
|
274
|
+
const c: [bigint, bigint] = [BigInt(proof.c[0]), BigInt(proof.c[1])];
|
|
275
|
+
|
|
276
|
+
// Convert public signals to BigInt array (13 elements)
|
|
277
|
+
const publicSignalsArray = publicSignals.slice(0, 13).map(s => BigInt(s));
|
|
278
|
+
|
|
279
|
+
try {
|
|
280
|
+
const contract = this.getContract();
|
|
281
|
+
const tx = await contract.verifyAndGrantAccess(
|
|
282
|
+
a,
|
|
283
|
+
b,
|
|
284
|
+
c,
|
|
285
|
+
publicSignalsArray,
|
|
286
|
+
credentialHash,
|
|
287
|
+
userAddress
|
|
288
|
+
);
|
|
289
|
+
|
|
290
|
+
const receipt = await tx.wait();
|
|
291
|
+
|
|
292
|
+
return {
|
|
293
|
+
transactionHash: tx.hash,
|
|
294
|
+
receipt: receipt as ContractTransactionReceipt,
|
|
295
|
+
};
|
|
296
|
+
} catch (error) {
|
|
297
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
298
|
+
throw new Error(`Failed to verify and grant access: ${errorMessage}`);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Check if a user has access to a protocol
|
|
304
|
+
*
|
|
305
|
+
* @param protocolAddress - The protocol contract address (defaults to signer's address)
|
|
306
|
+
* @param userAddress - The user's wallet address
|
|
307
|
+
* @returns Promise resolving to boolean indicating access status
|
|
308
|
+
*
|
|
309
|
+
* @example
|
|
310
|
+
* ```typescript
|
|
311
|
+
* const hasAccess = await protocol.checkUserAccess(protocolAddress, userAddress);
|
|
312
|
+
* if (hasAccess) {
|
|
313
|
+
* console.log('User has access');
|
|
314
|
+
* }
|
|
315
|
+
* ```
|
|
316
|
+
*/
|
|
317
|
+
async checkUserAccess(
|
|
318
|
+
protocolAddress: string,
|
|
319
|
+
userAddress: string
|
|
320
|
+
): Promise<boolean> {
|
|
321
|
+
try {
|
|
322
|
+
const contract = this.getReadOnlyContract();
|
|
323
|
+
return await contract.hasAccess(protocolAddress, userAddress);
|
|
324
|
+
} catch (error) {
|
|
325
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
326
|
+
throw new Error(`Failed to check user access: ${errorMessage}`);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RequirementsManager
|
|
3
|
+
*
|
|
4
|
+
* Helper utilities for managing protocol requirements.
|
|
5
|
+
* This is a placeholder - implementation will be added in Phase 3.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export class RequirementsManager {
|
|
9
|
+
// Implementation coming in Phase 3
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ProofGenerator - Browser-side ZK Proof Generation
|
|
3
|
+
*
|
|
4
|
+
* This class manages the lifecycle of the ZK prover:
|
|
5
|
+
* 1. Loading the WASM module
|
|
6
|
+
* 2. Caching artifacts in IndexedDB
|
|
7
|
+
* 3. Executing proofs in a Web Worker (optional but recommended)
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { ZKProof } from '../utils/types';
|
|
11
|
+
|
|
12
|
+
export interface ProverInput {
|
|
13
|
+
actualAge: number;
|
|
14
|
+
actualJurisdiction: number;
|
|
15
|
+
actualAccredited: number;
|
|
16
|
+
credentialHash: string;
|
|
17
|
+
passportNumber: string;
|
|
18
|
+
expiryDate: number;
|
|
19
|
+
minAge: number;
|
|
20
|
+
recipientAddress: string;
|
|
21
|
+
currentDate: number;
|
|
22
|
+
allowedJurisdictions: number[];
|
|
23
|
+
sanctionedCountries: number[];
|
|
24
|
+
requireAccredited: number;
|
|
25
|
+
credentialHashPublic: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface ProofGenerationResult {
|
|
29
|
+
proof: ZKProof;
|
|
30
|
+
publicSignals: string[];
|
|
31
|
+
success: boolean;
|
|
32
|
+
nullifier: string;
|
|
33
|
+
packedFlags: number;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export class ProofGenerator {
|
|
37
|
+
private wasmLoaded: boolean = false;
|
|
38
|
+
private wasmBinary: ArrayBuffer | null = null;
|
|
39
|
+
|
|
40
|
+
constructor() { }
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Load the ZK prover artifacts
|
|
44
|
+
* @param wasmUrl - URL to the noah_prover.wasm file
|
|
45
|
+
*/
|
|
46
|
+
async loadProver(wasmUrl: string = '/noah_prover.wasm'): Promise<void> {
|
|
47
|
+
if (this.wasmLoaded) return;
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
// 1. Try to load from IndexedDB cache
|
|
51
|
+
const cached = await this.getCachedWasm();
|
|
52
|
+
if (cached) {
|
|
53
|
+
this.wasmBinary = cached;
|
|
54
|
+
} else {
|
|
55
|
+
// 2. Download from URL
|
|
56
|
+
const response = await fetch(wasmUrl);
|
|
57
|
+
if (!response.ok) throw new Error(`Failed to fetch WASM from ${wasmUrl}`);
|
|
58
|
+
this.wasmBinary = await response.arrayBuffer();
|
|
59
|
+
|
|
60
|
+
// 3. Cache for next time
|
|
61
|
+
await this.cacheWasm(this.wasmBinary);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
this.wasmLoaded = true;
|
|
65
|
+
} catch (error: any) {
|
|
66
|
+
throw new Error(`Failed to load prover: ${error.message}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Generate a ZK proof locally
|
|
72
|
+
* @param input - Circuit assignment data
|
|
73
|
+
*/
|
|
74
|
+
async generateProof(input: ProverInput): Promise<ProofGenerationResult> {
|
|
75
|
+
if (!this.wasmLoaded) {
|
|
76
|
+
await this.loadProver();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// This is a simulation/placeholder for the Go-WASM bridge call
|
|
80
|
+
// In a real implementation, you would use:
|
|
81
|
+
// const go = new Go();
|
|
82
|
+
// const result = await WebAssembly.instantiate(this.wasmBinary, go.importObject);
|
|
83
|
+
// go.run(result.instance);
|
|
84
|
+
// const proofResult = globalThis.generateNoahProof(JSON.stringify(input));
|
|
85
|
+
|
|
86
|
+
console.log('Generating proof locally with input:', input);
|
|
87
|
+
|
|
88
|
+
// Simulate some work
|
|
89
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
proof: {
|
|
93
|
+
a: ["0", "0"],
|
|
94
|
+
b: [["0", "0"], ["0", "0"]],
|
|
95
|
+
c: ["0", "0"]
|
|
96
|
+
} as ZKProof,
|
|
97
|
+
publicSignals: [], // This would be populated by the WASM
|
|
98
|
+
nullifier: "0x" + Math.random().toString(16).substring(2, 66),
|
|
99
|
+
packedFlags: 15, // All checks pass
|
|
100
|
+
success: true
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
private async getCachedWasm(): Promise<ArrayBuffer | null> {
|
|
105
|
+
// Basic IndexedDB retrieval placeholder
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
private async cacheWasm(binary: ArrayBuffer): Promise<void> {
|
|
110
|
+
// Basic IndexedDB storage placeholder
|
|
111
|
+
console.log('Caching WASM binary, size:', binary.byteLength);
|
|
112
|
+
}
|
|
113
|
+
}
|