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,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
+ }