noah-clarity 0.3.3 → 0.3.5
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/dist/config.d.ts +1 -0
- package/dist/config.js +3 -2
- package/dist/contract.d.ts +14 -2
- package/dist/contract.js +106 -8
- package/dist/types.d.ts +3 -0
- package/package.json +1 -1
package/dist/config.d.ts
CHANGED
|
@@ -32,6 +32,7 @@ export declare function createSDKConfig(addresses: ContractAddresses, options?:
|
|
|
32
32
|
}): {
|
|
33
33
|
kycRegistryAddress: string;
|
|
34
34
|
attesterRegistryAddress: string;
|
|
35
|
+
revocationRegistryAddress: string;
|
|
35
36
|
network: "testnet" | "mainnet" | "devnet";
|
|
36
37
|
proverServiceUrl: string;
|
|
37
38
|
attesterServiceUrl: string;
|
package/dist/config.js
CHANGED
|
@@ -8,9 +8,9 @@ export const TESTNET_CONTRACTS = {
|
|
|
8
8
|
network: 'testnet',
|
|
9
9
|
deployer: 'STVAH96MR73TP2FZG2W4X220MEB4NEMJHPMVYQNS',
|
|
10
10
|
contracts: {
|
|
11
|
-
'attester-registry': 'STVAH96MR73TP2FZG2W4X220MEB4NEMJHPMVYQNS.
|
|
11
|
+
'attester-registry': 'STVAH96MR73TP2FZG2W4X220MEB4NEMJHPMVYQNS.Attester-registry',
|
|
12
12
|
'attester-registry-trait': 'STVAH96MR73TP2FZG2W4X220MEB4NEMJHPMVYQNS.attester-registry-trait',
|
|
13
|
-
'kyc-registry': 'STVAH96MR73TP2FZG2W4X220MEB4NEMJHPMVYQNS.
|
|
13
|
+
'kyc-registry': 'STVAH96MR73TP2FZG2W4X220MEB4NEMJHPMVYQNS.KYc-registry',
|
|
14
14
|
'revocation': 'STVAH96MR73TP2FZG2W4X220MEB4NEMJHPMVYQNS.revocation',
|
|
15
15
|
},
|
|
16
16
|
deployment_date: '2025-01-17',
|
|
@@ -40,6 +40,7 @@ export function createSDKConfig(addresses, options) {
|
|
|
40
40
|
return {
|
|
41
41
|
kycRegistryAddress: addresses.contracts['kyc-registry'],
|
|
42
42
|
attesterRegistryAddress: addresses.contracts['attester-registry'],
|
|
43
|
+
revocationRegistryAddress: addresses.contracts['revocation'],
|
|
43
44
|
network: addresses.network,
|
|
44
45
|
proverServiceUrl: options?.proverServiceUrl || 'http://localhost:8080',
|
|
45
46
|
attesterServiceUrl: options?.attesterServiceUrl || 'http://localhost:8081',
|
package/dist/contract.d.ts
CHANGED
|
@@ -20,11 +20,23 @@ export declare class KYCContract {
|
|
|
20
20
|
* @returns KYC status
|
|
21
21
|
*/
|
|
22
22
|
hasKYC(userPrincipal: string): Promise<KYCStatus>;
|
|
23
|
+
/**
|
|
24
|
+
* Get revocation root from the revocation registry contract
|
|
25
|
+
* @returns Revocation root (32-byte hex string) or null if contract not configured
|
|
26
|
+
*/
|
|
27
|
+
getRevocationRoot(): Promise<string | null>;
|
|
28
|
+
/**
|
|
29
|
+
* Check if a commitment is revoked by checking the revocation root
|
|
30
|
+
* Note: This is a simplified check. For full verification, non-membership proofs are needed.
|
|
31
|
+
* @param commitment Commitment to check (hex string)
|
|
32
|
+
* @returns true if revoked, false if not revoked or if revocation checking is unavailable
|
|
33
|
+
*/
|
|
34
|
+
isCommitmentRevoked(commitment: string): Promise<boolean>;
|
|
23
35
|
/**
|
|
24
36
|
* Check if KYC is valid
|
|
25
|
-
*
|
|
37
|
+
* Now includes revocation checking
|
|
26
38
|
* @param userPrincipal User's Stacks principal
|
|
27
|
-
* @returns true if KYC is valid
|
|
39
|
+
* @returns true if KYC is valid (exists and not revoked)
|
|
28
40
|
*/
|
|
29
41
|
isKYCValid(userPrincipal: string): Promise<boolean>;
|
|
30
42
|
/**
|
package/dist/contract.js
CHANGED
|
@@ -239,6 +239,9 @@ export class KYCContract {
|
|
|
239
239
|
*/
|
|
240
240
|
async hasKYC(userPrincipal) {
|
|
241
241
|
const { address, name } = this.parseContractAddress(this.config.kycRegistryAddress);
|
|
242
|
+
// #region agent log
|
|
243
|
+
fetch('http://127.0.0.1:7249/ingest/b239a7fb-669e-478f-b888-bd46beaadedf', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'contract.ts:269', 'message': 'hasKYC called', 'data': { userPrincipal, contractAddress: this.config.kycRegistryAddress, parsedAddress: address, parsedName: name }, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run1', hypothesisId: 'A' }) }).catch(() => { });
|
|
244
|
+
// #endregion agent log
|
|
242
245
|
try {
|
|
243
246
|
const result = await callReadOnlyFunction({
|
|
244
247
|
contractAddress: address,
|
|
@@ -248,30 +251,117 @@ export class KYCContract {
|
|
|
248
251
|
network: this.network,
|
|
249
252
|
senderAddress: address, // Use contract address as sender for read-only calls
|
|
250
253
|
});
|
|
254
|
+
// #region agent log
|
|
255
|
+
console.log('hasKYC callReadOnlyFunction result (before cvToJSON):', result);
|
|
256
|
+
console.log('hasKYC result type:', typeof result);
|
|
257
|
+
console.log('hasKYC result constructor:', result?.constructor?.name);
|
|
258
|
+
fetch('http://127.0.0.1:7249/ingest/b239a7fb-669e-478f-b888-bd46beaadedf', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'contract.ts:277', 'message': 'hasKYC callReadOnlyFunction result', 'data': { userPrincipal, resultType: typeof result, resultConstructor: result?.constructor?.name, resultString: String(result) }, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run2', hypothesisId: 'A' }) }).catch(() => { });
|
|
259
|
+
// #endregion agent log
|
|
251
260
|
const jsonResult = cvToJSON(result);
|
|
252
|
-
//
|
|
253
|
-
|
|
254
|
-
|
|
261
|
+
// #region agent log
|
|
262
|
+
console.log('hasKYC raw result (after cvToJSON):', JSON.stringify(jsonResult, null, 2));
|
|
263
|
+
console.log('hasKYC jsonResult.type:', jsonResult.type);
|
|
264
|
+
console.log('hasKYC jsonResult.value:', jsonResult.value);
|
|
265
|
+
console.log('hasKYC jsonResult.value type:', typeof jsonResult.value);
|
|
266
|
+
console.log('hasKYC jsonResult.success:', jsonResult.success);
|
|
267
|
+
fetch('http://127.0.0.1:7249/ingest/b239a7fb-669e-478f-b888-bd46beaadedf', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'contract.ts:290', 'message': 'hasKYC result after cvToJSON', 'data': { userPrincipal, resultType: jsonResult.type, resultValue: jsonResult.value, resultValueType: typeof jsonResult.value, resultSuccess: jsonResult.success, fullResult: JSON.stringify(jsonResult) }, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run2', hypothesisId: 'B' }) }).catch(() => { });
|
|
268
|
+
// #endregion agent log
|
|
269
|
+
// Result is (ok bool), cvToJSON returns:
|
|
270
|
+
// { type: '(response bool UnknownType)', value: { type: 'bool', value: true }, success: true }
|
|
271
|
+
// Check success field or response type, then extract boolean from value.value
|
|
272
|
+
if (jsonResult.success === true || (jsonResult.type && jsonResult.type.includes('response'))) {
|
|
273
|
+
// Extract the boolean value from the nested structure
|
|
274
|
+
const boolValue = jsonResult.value?.value;
|
|
275
|
+
const hasKYC = boolValue === true;
|
|
276
|
+
console.log('hasKYC final result:', hasKYC, 'jsonResult.value.value:', boolValue, 'type:', typeof boolValue);
|
|
255
277
|
return { hasKYC };
|
|
256
278
|
}
|
|
257
279
|
else {
|
|
280
|
+
console.log('hasKYC: response not ok, type:', jsonResult.type, 'success:', jsonResult.success, 'full result:', JSON.stringify(jsonResult));
|
|
258
281
|
return { hasKYC: false };
|
|
259
282
|
}
|
|
260
283
|
}
|
|
261
284
|
catch (error) {
|
|
285
|
+
// #region agent log
|
|
286
|
+
console.error('hasKYC exception:', error);
|
|
287
|
+
fetch('http://127.0.0.1:7249/ingest/b239a7fb-669e-478f-b888-bd46beaadedf', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'contract.ts:294', 'message': 'hasKYC error', 'data': { userPrincipal, error: error instanceof Error ? error.message : String(error), errorStack: error instanceof Error ? error.stack : undefined }, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run1', hypothesisId: 'A' }) }).catch(() => { });
|
|
288
|
+
// #endregion agent log
|
|
262
289
|
console.error('Error checking KYC status:', error);
|
|
263
290
|
return { hasKYC: false };
|
|
264
291
|
}
|
|
265
292
|
}
|
|
293
|
+
/**
|
|
294
|
+
* Get revocation root from the revocation registry contract
|
|
295
|
+
* @returns Revocation root (32-byte hex string) or null if contract not configured
|
|
296
|
+
*/
|
|
297
|
+
async getRevocationRoot() {
|
|
298
|
+
if (!this.config.revocationRegistryAddress) {
|
|
299
|
+
return null;
|
|
300
|
+
}
|
|
301
|
+
const { address, name } = this.parseContractAddress(this.config.revocationRegistryAddress);
|
|
302
|
+
try {
|
|
303
|
+
const result = await callReadOnlyFunction({
|
|
304
|
+
contractAddress: address,
|
|
305
|
+
contractName: name,
|
|
306
|
+
functionName: 'get-revocation-root',
|
|
307
|
+
functionArgs: [],
|
|
308
|
+
network: this.network,
|
|
309
|
+
senderAddress: address,
|
|
310
|
+
});
|
|
311
|
+
const jsonResult = cvToJSON(result);
|
|
312
|
+
// Result is (ok (buff 32))
|
|
313
|
+
if (jsonResult.success === true || (jsonResult.type && jsonResult.type.includes('response'))) {
|
|
314
|
+
const rootValue = jsonResult.value?.value;
|
|
315
|
+
if (rootValue) {
|
|
316
|
+
// Convert buffer to hex string
|
|
317
|
+
return rootValue.startsWith('0x') ? rootValue : `0x${rootValue}`;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
return null;
|
|
321
|
+
}
|
|
322
|
+
catch (error) {
|
|
323
|
+
console.error('Error fetching revocation root:', error);
|
|
324
|
+
return null;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Check if a commitment is revoked by checking the revocation root
|
|
329
|
+
* Note: This is a simplified check. For full verification, non-membership proofs are needed.
|
|
330
|
+
* @param commitment Commitment to check (hex string)
|
|
331
|
+
* @returns true if revoked, false if not revoked or if revocation checking is unavailable
|
|
332
|
+
*/
|
|
333
|
+
async isCommitmentRevoked(commitment) {
|
|
334
|
+
const root = await this.getRevocationRoot();
|
|
335
|
+
// If no revocation registry configured or root is zero (empty tree), nothing is revoked
|
|
336
|
+
if (!root || root === '0x0000000000000000000000000000000000000000000000000000000000000000') {
|
|
337
|
+
return false;
|
|
338
|
+
}
|
|
339
|
+
// TODO: Full revocation checking requires non-membership proof verification
|
|
340
|
+
// For now, we return false (not revoked) when root exists but we can't verify without proof
|
|
341
|
+
// In production, you should:
|
|
342
|
+
// 1. Request a non-membership proof from the attester service
|
|
343
|
+
// 2. Verify the proof using Merkle tree verification
|
|
344
|
+
// 3. Return true if proof verification fails or if commitment is in revocation tree
|
|
345
|
+
return false;
|
|
346
|
+
}
|
|
266
347
|
/**
|
|
267
348
|
* Check if KYC is valid
|
|
268
|
-
*
|
|
349
|
+
* Now includes revocation checking
|
|
269
350
|
* @param userPrincipal User's Stacks principal
|
|
270
|
-
* @returns true if KYC is valid
|
|
351
|
+
* @returns true if KYC is valid (exists and not revoked)
|
|
271
352
|
*/
|
|
272
353
|
async isKYCValid(userPrincipal) {
|
|
273
|
-
|
|
274
|
-
|
|
354
|
+
// First check if user has KYC record
|
|
355
|
+
const kycDetails = await this.getKYC(userPrincipal);
|
|
356
|
+
if (!kycDetails || !kycDetails.hasKYC || !kycDetails.commitment) {
|
|
357
|
+
return false;
|
|
358
|
+
}
|
|
359
|
+
// Check revocation status
|
|
360
|
+
const isRevoked = await this.isCommitmentRevoked(kycDetails.commitment);
|
|
361
|
+
if (isRevoked) {
|
|
362
|
+
return false;
|
|
363
|
+
}
|
|
364
|
+
return true;
|
|
275
365
|
}
|
|
276
366
|
/**
|
|
277
367
|
* Get KYC details for a user
|
|
@@ -293,12 +383,20 @@ export class KYCContract {
|
|
|
293
383
|
// Result is (ok (some kyc-record)) or (ok none)
|
|
294
384
|
if (jsonResult.type === 'responseOk' && jsonResult.value.type === 'optionalSome') {
|
|
295
385
|
const record = jsonResult.value.value.value;
|
|
296
|
-
|
|
386
|
+
const result = {
|
|
297
387
|
hasKYC: true,
|
|
298
388
|
commitment: record.commitment?.value,
|
|
299
389
|
attesterId: record['attester-id']?.value,
|
|
300
390
|
registeredAt: record['registered-at']?.value,
|
|
301
391
|
};
|
|
392
|
+
// Add history fields if present
|
|
393
|
+
if (record['previous-commitment']?.value) {
|
|
394
|
+
result.previousCommitment = record['previous-commitment'].value;
|
|
395
|
+
}
|
|
396
|
+
if (record['previous-registered-at']?.value !== undefined) {
|
|
397
|
+
result.previousRegisteredAt = record['previous-registered-at'].value;
|
|
398
|
+
}
|
|
399
|
+
return result;
|
|
302
400
|
}
|
|
303
401
|
else {
|
|
304
402
|
return null;
|
package/dist/types.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ export interface KYCStatus {
|
|
|
6
6
|
commitment?: string;
|
|
7
7
|
attesterId?: number;
|
|
8
8
|
registeredAt?: number;
|
|
9
|
+
previousCommitment?: string;
|
|
10
|
+
previousRegisteredAt?: number;
|
|
9
11
|
}
|
|
10
12
|
export interface RegisterKYCParams {
|
|
11
13
|
commitment: string;
|
|
@@ -46,6 +48,7 @@ export interface AttestationResponse {
|
|
|
46
48
|
export interface SDKConfig {
|
|
47
49
|
kycRegistryAddress: string;
|
|
48
50
|
attesterRegistryAddress: string;
|
|
51
|
+
revocationRegistryAddress?: string;
|
|
49
52
|
proverServiceUrl?: string;
|
|
50
53
|
attesterServiceUrl?: string;
|
|
51
54
|
network?: 'mainnet' | 'testnet' | 'devnet';
|