noah-clarity 0.1.0
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 +49 -0
- package/dist/config.d.ts +38 -0
- package/dist/config.js +52 -0
- package/dist/contract.d.ts +40 -0
- package/dist/contract.js +152 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.js +74 -0
- package/dist/proof.d.ts +29 -0
- package/dist/proof.js +82 -0
- package/dist/types.d.ts +57 -0
- package/dist/types.js +5 -0
- package/dist/wallet.d.ts +21 -0
- package/dist/wallet.js +34 -0
- package/package.json +52 -0
package/README.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Noah-v2 SDK
|
|
2
|
+
|
|
3
|
+
TypeScript/JavaScript SDK for integrating Noah-v2 KYC system into Stacks protocols.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install noah-clarity
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
### Basic Setup
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { NoahSDK } from 'noah-clarity';
|
|
17
|
+
|
|
18
|
+
const sdk = new NoahSDK(
|
|
19
|
+
{
|
|
20
|
+
kycRegistryAddress: 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.kyc-registry',
|
|
21
|
+
attesterRegistryAddress: 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.attester-registry',
|
|
22
|
+
network: 'testnet',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
appName: 'Your Protocol',
|
|
26
|
+
}
|
|
27
|
+
);
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Check KYC Status
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
const hasKYC = await sdk.contract.hasKYC(userAddress);
|
|
34
|
+
if (hasKYC.hasKYC) {
|
|
35
|
+
// User has KYC
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Require KYC for Protocol Access
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
const isValid = await sdk.contract.isKYCValid(userAddress);
|
|
43
|
+
if (!isValid) {
|
|
44
|
+
throw new Error('KYC required');
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Examples and integration patterns will be available when the SDK is fully implemented.
|
|
49
|
+
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration loader for contract addresses
|
|
3
|
+
*/
|
|
4
|
+
export interface ContractAddresses {
|
|
5
|
+
network: string;
|
|
6
|
+
deployer: string;
|
|
7
|
+
contracts: {
|
|
8
|
+
'attester-registry': string;
|
|
9
|
+
'attester-registry-trait': string;
|
|
10
|
+
'kyc-registry': string;
|
|
11
|
+
'revocation': string;
|
|
12
|
+
};
|
|
13
|
+
deployment_date?: string;
|
|
14
|
+
description?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Default testnet contract addresses (deployed)
|
|
18
|
+
*/
|
|
19
|
+
export declare const TESTNET_CONTRACTS: ContractAddresses;
|
|
20
|
+
/**
|
|
21
|
+
* Load contract addresses from JSON file or use defaults
|
|
22
|
+
* In browser environments, this can load from a static JSON file
|
|
23
|
+
* In Node.js, can use fs to read the JSON file
|
|
24
|
+
*/
|
|
25
|
+
export declare function loadContractAddresses(network?: 'testnet' | 'mainnet' | 'devnet'): ContractAddresses;
|
|
26
|
+
/**
|
|
27
|
+
* Create SDK config from contract addresses
|
|
28
|
+
*/
|
|
29
|
+
export declare function createSDKConfig(addresses: ContractAddresses, options?: {
|
|
30
|
+
proverServiceUrl?: string;
|
|
31
|
+
attesterServiceUrl?: string;
|
|
32
|
+
}): {
|
|
33
|
+
kycRegistryAddress: string;
|
|
34
|
+
attesterRegistryAddress: string;
|
|
35
|
+
network: "testnet" | "mainnet" | "devnet";
|
|
36
|
+
proverServiceUrl: string;
|
|
37
|
+
attesterServiceUrl: string;
|
|
38
|
+
};
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Configuration loader for contract addresses
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.TESTNET_CONTRACTS = void 0;
|
|
7
|
+
exports.loadContractAddresses = loadContractAddresses;
|
|
8
|
+
exports.createSDKConfig = createSDKConfig;
|
|
9
|
+
/**
|
|
10
|
+
* Default testnet contract addresses (deployed)
|
|
11
|
+
*/
|
|
12
|
+
exports.TESTNET_CONTRACTS = {
|
|
13
|
+
network: 'testnet',
|
|
14
|
+
deployer: 'STVAH96MR73TP2FZG2W4X220MEB4NEMJHPMVYQNS',
|
|
15
|
+
contracts: {
|
|
16
|
+
'attester-registry': 'STVAH96MR73TP2FZG2W4X220MEB4NEMJHPMVYQNS.attester-registry',
|
|
17
|
+
'attester-registry-trait': 'STVAH96MR73TP2FZG2W4X220MEB4NEMJHPMVYQNS.attester-registry-trait',
|
|
18
|
+
'kyc-registry': 'STVAH96MR73TP2FZG2W4X220MEB4NEMJHPMVYQNS.kyc-registry',
|
|
19
|
+
'revocation': 'STVAH96MR73TP2FZG2W4X220MEB4NEMJHPMVYQNS.revocation',
|
|
20
|
+
},
|
|
21
|
+
deployment_date: '2025-01-17',
|
|
22
|
+
description: 'Deployed contract addresses for Noah-v2 KYC Registry system on Stacks Testnet',
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Load contract addresses from JSON file or use defaults
|
|
26
|
+
* In browser environments, this can load from a static JSON file
|
|
27
|
+
* In Node.js, can use fs to read the JSON file
|
|
28
|
+
*/
|
|
29
|
+
function loadContractAddresses(network = 'testnet') {
|
|
30
|
+
// For now, return hardcoded testnet addresses
|
|
31
|
+
// In production, you might want to:
|
|
32
|
+
// 1. Load from a JSON file
|
|
33
|
+
// 2. Fetch from a registry/API
|
|
34
|
+
// 3. Use environment variables
|
|
35
|
+
if (network === 'testnet') {
|
|
36
|
+
return exports.TESTNET_CONTRACTS;
|
|
37
|
+
}
|
|
38
|
+
// TODO: Add mainnet addresses when deployed
|
|
39
|
+
throw new Error(`Contract addresses for ${network} not yet configured`);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Create SDK config from contract addresses
|
|
43
|
+
*/
|
|
44
|
+
function createSDKConfig(addresses, options) {
|
|
45
|
+
return {
|
|
46
|
+
kycRegistryAddress: addresses.contracts['kyc-registry'],
|
|
47
|
+
attesterRegistryAddress: addresses.contracts['attester-registry'],
|
|
48
|
+
network: addresses.network,
|
|
49
|
+
proverServiceUrl: options?.proverServiceUrl || 'http://localhost:8080',
|
|
50
|
+
attesterServiceUrl: options?.attesterServiceUrl || 'http://localhost:8081',
|
|
51
|
+
};
|
|
52
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clarity contract interaction helpers
|
|
3
|
+
*/
|
|
4
|
+
import { SDKConfig, KYCStatus, RegisterKYCParams } from './types';
|
|
5
|
+
export declare class KYCContract {
|
|
6
|
+
private config;
|
|
7
|
+
private network;
|
|
8
|
+
constructor(config: SDKConfig);
|
|
9
|
+
private getNetwork;
|
|
10
|
+
/**
|
|
11
|
+
* Register KYC on-chain
|
|
12
|
+
* @param params Registration parameters
|
|
13
|
+
* @param privateKey Private key for signing transaction
|
|
14
|
+
* @returns Transaction ID
|
|
15
|
+
*/
|
|
16
|
+
registerKYC(params: RegisterKYCParams, privateKey: string): Promise<string>;
|
|
17
|
+
/**
|
|
18
|
+
* Check if a user has valid KYC
|
|
19
|
+
* @param userPrincipal User's Stacks principal
|
|
20
|
+
* @returns KYC status
|
|
21
|
+
*/
|
|
22
|
+
hasKYC(userPrincipal: string): Promise<KYCStatus>;
|
|
23
|
+
/**
|
|
24
|
+
* Check if KYC is valid
|
|
25
|
+
* Since KYC records don't expire, this is equivalent to hasKYC
|
|
26
|
+
* @param userPrincipal User's Stacks principal
|
|
27
|
+
* @returns true if KYC is valid
|
|
28
|
+
*/
|
|
29
|
+
isKYCValid(userPrincipal: string): Promise<boolean>;
|
|
30
|
+
/**
|
|
31
|
+
* Get KYC details for a user
|
|
32
|
+
* @param userPrincipal User's Stacks principal
|
|
33
|
+
* @returns KYC details or null
|
|
34
|
+
*/
|
|
35
|
+
getKYC(userPrincipal: string): Promise<KYCStatus | null>;
|
|
36
|
+
/**
|
|
37
|
+
* Parse contract address from contract identifier (e.g., "ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.kyc-registry")
|
|
38
|
+
*/
|
|
39
|
+
private parseContractAddress;
|
|
40
|
+
}
|
package/dist/contract.js
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Clarity contract interaction helpers
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.KYCContract = void 0;
|
|
7
|
+
const transactions_1 = require("@stacks/transactions");
|
|
8
|
+
const network_1 = require("@stacks/network");
|
|
9
|
+
class KYCContract {
|
|
10
|
+
constructor(config) {
|
|
11
|
+
this.config = config;
|
|
12
|
+
this.network = this.getNetwork();
|
|
13
|
+
}
|
|
14
|
+
getNetwork() {
|
|
15
|
+
switch (this.config.network) {
|
|
16
|
+
case 'mainnet':
|
|
17
|
+
return new network_1.StacksMainnet();
|
|
18
|
+
case 'testnet':
|
|
19
|
+
return new network_1.StacksTestnet();
|
|
20
|
+
default:
|
|
21
|
+
return new network_1.StacksTestnet();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Register KYC on-chain
|
|
26
|
+
* @param params Registration parameters
|
|
27
|
+
* @param privateKey Private key for signing transaction
|
|
28
|
+
* @returns Transaction ID
|
|
29
|
+
*/
|
|
30
|
+
async registerKYC(params, privateKey) {
|
|
31
|
+
const senderAddress = (0, transactions_1.getAddressFromPrivateKey)(privateKey, this.network.version);
|
|
32
|
+
const { address, name } = this.parseContractAddress(this.config.kycRegistryAddress);
|
|
33
|
+
const functionArgs = [
|
|
34
|
+
(0, transactions_1.bufferCV)(Buffer.from(params.commitment.replace('0x', ''), 'hex')),
|
|
35
|
+
(0, transactions_1.bufferCV)(Buffer.from(params.signature.replace('0x', ''), 'hex')),
|
|
36
|
+
(0, transactions_1.uintCV)(params.attesterId),
|
|
37
|
+
];
|
|
38
|
+
const txOptions = {
|
|
39
|
+
contractAddress: address,
|
|
40
|
+
contractName: name,
|
|
41
|
+
functionName: 'register-kyc',
|
|
42
|
+
functionArgs,
|
|
43
|
+
senderKey: privateKey,
|
|
44
|
+
fee: 1000,
|
|
45
|
+
network: this.network,
|
|
46
|
+
anchorMode: transactions_1.AnchorMode.Any,
|
|
47
|
+
postConditionMode: transactions_1.PostConditionMode.Allow,
|
|
48
|
+
};
|
|
49
|
+
try {
|
|
50
|
+
const transaction = await (0, transactions_1.makeContractCall)(txOptions);
|
|
51
|
+
const broadcastResponse = await (0, transactions_1.broadcastTransaction)(transaction, this.network);
|
|
52
|
+
return broadcastResponse.txid;
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
if (error instanceof Error) {
|
|
56
|
+
throw new Error(`Transaction failed: ${error.message}`);
|
|
57
|
+
}
|
|
58
|
+
throw new Error(`Transaction failed: ${String(error)}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Check if a user has valid KYC
|
|
63
|
+
* @param userPrincipal User's Stacks principal
|
|
64
|
+
* @returns KYC status
|
|
65
|
+
*/
|
|
66
|
+
async hasKYC(userPrincipal) {
|
|
67
|
+
const { address, name } = this.parseContractAddress(this.config.kycRegistryAddress);
|
|
68
|
+
try {
|
|
69
|
+
const result = await (0, transactions_1.callReadOnlyFunction)({
|
|
70
|
+
contractAddress: address,
|
|
71
|
+
contractName: name,
|
|
72
|
+
functionName: 'has-kyc?',
|
|
73
|
+
functionArgs: [(0, transactions_1.principalCV)(userPrincipal)],
|
|
74
|
+
network: this.network,
|
|
75
|
+
senderAddress: address, // Use contract address as sender for read-only calls
|
|
76
|
+
});
|
|
77
|
+
const jsonResult = (0, transactions_1.cvToJSON)(result);
|
|
78
|
+
// Result is (ok bool), so check if it's ok and the value is true
|
|
79
|
+
if (jsonResult.type === 'responseOk') {
|
|
80
|
+
const hasKYC = jsonResult.value.value === true;
|
|
81
|
+
return { hasKYC };
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
return { hasKYC: false };
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
console.error('Error checking KYC status:', error);
|
|
89
|
+
return { hasKYC: false };
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Check if KYC is valid
|
|
94
|
+
* Since KYC records don't expire, this is equivalent to hasKYC
|
|
95
|
+
* @param userPrincipal User's Stacks principal
|
|
96
|
+
* @returns true if KYC is valid
|
|
97
|
+
*/
|
|
98
|
+
async isKYCValid(userPrincipal) {
|
|
99
|
+
const status = await this.hasKYC(userPrincipal);
|
|
100
|
+
return status.hasKYC;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Get KYC details for a user
|
|
104
|
+
* @param userPrincipal User's Stacks principal
|
|
105
|
+
* @returns KYC details or null
|
|
106
|
+
*/
|
|
107
|
+
async getKYC(userPrincipal) {
|
|
108
|
+
const { address, name } = this.parseContractAddress(this.config.kycRegistryAddress);
|
|
109
|
+
try {
|
|
110
|
+
const result = await (0, transactions_1.callReadOnlyFunction)({
|
|
111
|
+
contractAddress: address,
|
|
112
|
+
contractName: name,
|
|
113
|
+
functionName: 'get-kyc',
|
|
114
|
+
functionArgs: [(0, transactions_1.principalCV)(userPrincipal)],
|
|
115
|
+
network: this.network,
|
|
116
|
+
senderAddress: address,
|
|
117
|
+
});
|
|
118
|
+
const jsonResult = (0, transactions_1.cvToJSON)(result);
|
|
119
|
+
// Result is (ok (some kyc-record)) or (ok none)
|
|
120
|
+
if (jsonResult.type === 'responseOk' && jsonResult.value.type === 'optionalSome') {
|
|
121
|
+
const record = jsonResult.value.value.value;
|
|
122
|
+
return {
|
|
123
|
+
hasKYC: true,
|
|
124
|
+
commitment: record.commitment?.value,
|
|
125
|
+
attesterId: record['attester-id']?.value,
|
|
126
|
+
registeredAt: record['registered-at']?.value,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
console.error('Error getting KYC details:', error);
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Parse contract address from contract identifier (e.g., "ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.kyc-registry")
|
|
140
|
+
*/
|
|
141
|
+
parseContractAddress(contractId) {
|
|
142
|
+
const parts = contractId.split('.');
|
|
143
|
+
if (parts.length !== 2) {
|
|
144
|
+
throw new Error(`Invalid contract address format: ${contractId}. Expected format: ADDRESS.contract-name`);
|
|
145
|
+
}
|
|
146
|
+
return {
|
|
147
|
+
address: parts[0],
|
|
148
|
+
name: parts[1],
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
exports.KYCContract = KYCContract;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Noah-v2 SDK
|
|
3
|
+
* Main entry point for protocol integration
|
|
4
|
+
*/
|
|
5
|
+
export { KYCContract } from './contract';
|
|
6
|
+
export { ProofService } from './proof';
|
|
7
|
+
export { WalletHelper } from './wallet';
|
|
8
|
+
export * from './types';
|
|
9
|
+
import { KYCContract } from './contract';
|
|
10
|
+
import { ProofService } from './proof';
|
|
11
|
+
import { WalletHelper } from './wallet';
|
|
12
|
+
import { SDKConfig, WalletConfig } from './types';
|
|
13
|
+
/**
|
|
14
|
+
* Main SDK class
|
|
15
|
+
*/
|
|
16
|
+
export declare class NoahSDK {
|
|
17
|
+
contract: KYCContract;
|
|
18
|
+
proof: ProofService;
|
|
19
|
+
wallet: WalletHelper;
|
|
20
|
+
constructor(config: SDKConfig, walletConfig: WalletConfig);
|
|
21
|
+
/**
|
|
22
|
+
* Complete KYC registration flow
|
|
23
|
+
* 1. Generate proof
|
|
24
|
+
* 2. Get attestation
|
|
25
|
+
* 3. Register on-chain
|
|
26
|
+
*/
|
|
27
|
+
registerKYC(proofRequest: any, privateKey: string): Promise<string>;
|
|
28
|
+
}
|
|
29
|
+
export default NoahSDK;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Noah-v2 SDK
|
|
4
|
+
* Main entry point for protocol integration
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
18
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
19
|
+
};
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.NoahSDK = exports.WalletHelper = exports.ProofService = exports.KYCContract = void 0;
|
|
22
|
+
var contract_1 = require("./contract");
|
|
23
|
+
Object.defineProperty(exports, "KYCContract", { enumerable: true, get: function () { return contract_1.KYCContract; } });
|
|
24
|
+
var proof_1 = require("./proof");
|
|
25
|
+
Object.defineProperty(exports, "ProofService", { enumerable: true, get: function () { return proof_1.ProofService; } });
|
|
26
|
+
var wallet_1 = require("./wallet");
|
|
27
|
+
Object.defineProperty(exports, "WalletHelper", { enumerable: true, get: function () { return wallet_1.WalletHelper; } });
|
|
28
|
+
__exportStar(require("./types"), exports);
|
|
29
|
+
const contract_2 = require("./contract");
|
|
30
|
+
const proof_2 = require("./proof");
|
|
31
|
+
const wallet_2 = require("./wallet");
|
|
32
|
+
/**
|
|
33
|
+
* Main SDK class
|
|
34
|
+
*/
|
|
35
|
+
class NoahSDK {
|
|
36
|
+
constructor(config, walletConfig) {
|
|
37
|
+
this.contract = new contract_2.KYCContract(config);
|
|
38
|
+
this.proof = new proof_2.ProofService(config);
|
|
39
|
+
this.wallet = new wallet_2.WalletHelper(walletConfig);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Complete KYC registration flow
|
|
43
|
+
* 1. Generate proof
|
|
44
|
+
* 2. Get attestation
|
|
45
|
+
* 3. Register on-chain
|
|
46
|
+
*/
|
|
47
|
+
async registerKYC(proofRequest, privateKey) {
|
|
48
|
+
// Step 1: Generate proof
|
|
49
|
+
const proofResponse = await this.proof.generateProof(proofRequest);
|
|
50
|
+
if (!proofResponse.success) {
|
|
51
|
+
throw new Error(`Proof generation failed: ${proofResponse.error}`);
|
|
52
|
+
}
|
|
53
|
+
// Step 2: Get attestation
|
|
54
|
+
const attestationResponse = await this.proof.requestAttestation({
|
|
55
|
+
commitment: proofResponse.commitment,
|
|
56
|
+
public_inputs: proofResponse.public_inputs,
|
|
57
|
+
proof: proofResponse.proof,
|
|
58
|
+
user_id: '', // Set from user session
|
|
59
|
+
});
|
|
60
|
+
if (!attestationResponse.success) {
|
|
61
|
+
throw new Error(`Attestation failed: ${attestationResponse.error}`);
|
|
62
|
+
}
|
|
63
|
+
// Step 3: Register on-chain
|
|
64
|
+
const txId = await this.contract.registerKYC({
|
|
65
|
+
commitment: attestationResponse.commitment,
|
|
66
|
+
signature: attestationResponse.signature,
|
|
67
|
+
attesterId: attestationResponse.attester_id,
|
|
68
|
+
}, privateKey);
|
|
69
|
+
return txId;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
exports.NoahSDK = NoahSDK;
|
|
73
|
+
// Default export
|
|
74
|
+
exports.default = NoahSDK;
|
package/dist/proof.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Proof generation and verification utilities
|
|
3
|
+
*/
|
|
4
|
+
import { ProofRequest, ProofResponse, AttestationRequest, AttestationResponse, SDKConfig } from './types';
|
|
5
|
+
export declare class ProofService {
|
|
6
|
+
private proverServiceUrl;
|
|
7
|
+
private attesterServiceUrl;
|
|
8
|
+
constructor(config: SDKConfig);
|
|
9
|
+
/**
|
|
10
|
+
* Generate a ZK proof
|
|
11
|
+
* @param request Proof generation request
|
|
12
|
+
* @returns Proof response
|
|
13
|
+
*/
|
|
14
|
+
generateProof(request: ProofRequest): Promise<ProofResponse>;
|
|
15
|
+
/**
|
|
16
|
+
* Request an attestation signature from the attester
|
|
17
|
+
* @param request Attestation request
|
|
18
|
+
* @returns Attestation response
|
|
19
|
+
*/
|
|
20
|
+
requestAttestation(request: AttestationRequest): Promise<AttestationResponse>;
|
|
21
|
+
/**
|
|
22
|
+
* Verify a proof (off-chain verification)
|
|
23
|
+
* Note: This is a placeholder - actual verification would use the verification key
|
|
24
|
+
* @param proof Serialized proof
|
|
25
|
+
* @param publicInputs Public inputs
|
|
26
|
+
* @returns true if proof is valid
|
|
27
|
+
*/
|
|
28
|
+
verifyProof(proof: string, publicInputs: string[]): Promise<boolean>;
|
|
29
|
+
}
|
package/dist/proof.js
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Proof generation and verification utilities
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ProofService = void 0;
|
|
7
|
+
class ProofService {
|
|
8
|
+
constructor(config) {
|
|
9
|
+
this.proverServiceUrl = config.proverServiceUrl || 'http://localhost:8080';
|
|
10
|
+
this.attesterServiceUrl = config.attesterServiceUrl || 'http://localhost:8081';
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Generate a ZK proof
|
|
14
|
+
* @param request Proof generation request
|
|
15
|
+
* @returns Proof response
|
|
16
|
+
*/
|
|
17
|
+
async generateProof(request) {
|
|
18
|
+
const response = await fetch(`${this.proverServiceUrl}/proof/generate`, {
|
|
19
|
+
method: 'POST',
|
|
20
|
+
headers: {
|
|
21
|
+
'Content-Type': 'application/json',
|
|
22
|
+
},
|
|
23
|
+
body: JSON.stringify(request),
|
|
24
|
+
});
|
|
25
|
+
if (!response.ok) {
|
|
26
|
+
let errorMessage = response.statusText;
|
|
27
|
+
try {
|
|
28
|
+
const errorData = await response.json();
|
|
29
|
+
errorMessage = errorData.error || errorMessage;
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
// If response is not JSON, use statusText
|
|
33
|
+
}
|
|
34
|
+
throw new Error(`Proof generation failed: ${errorMessage}`);
|
|
35
|
+
}
|
|
36
|
+
const data = await response.json();
|
|
37
|
+
return data;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Request an attestation signature from the attester
|
|
41
|
+
* @param request Attestation request
|
|
42
|
+
* @returns Attestation response
|
|
43
|
+
*/
|
|
44
|
+
async requestAttestation(request) {
|
|
45
|
+
const response = await fetch(`${this.attesterServiceUrl}/credential/attest`, {
|
|
46
|
+
method: 'POST',
|
|
47
|
+
headers: {
|
|
48
|
+
'Content-Type': 'application/json',
|
|
49
|
+
},
|
|
50
|
+
body: JSON.stringify(request),
|
|
51
|
+
});
|
|
52
|
+
if (!response.ok) {
|
|
53
|
+
let errorMessage = response.statusText;
|
|
54
|
+
try {
|
|
55
|
+
const errorData = await response.json();
|
|
56
|
+
errorMessage = errorData.error || errorMessage;
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
// If response is not JSON, use statusText
|
|
60
|
+
}
|
|
61
|
+
throw new Error(`Attestation failed: ${errorMessage}`);
|
|
62
|
+
}
|
|
63
|
+
const data = await response.json();
|
|
64
|
+
return data;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Verify a proof (off-chain verification)
|
|
68
|
+
* Note: This is a placeholder - actual verification would use the verification key
|
|
69
|
+
* @param proof Serialized proof
|
|
70
|
+
* @param publicInputs Public inputs
|
|
71
|
+
* @returns true if proof is valid
|
|
72
|
+
*/
|
|
73
|
+
async verifyProof(proof, publicInputs) {
|
|
74
|
+
// In production, this would:
|
|
75
|
+
// 1. Deserialize the proof
|
|
76
|
+
// 2. Load the verification key
|
|
77
|
+
// 3. Verify using gnark or similar library
|
|
78
|
+
// For now, return true as a placeholder
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
exports.ProofService = ProofService;
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for Noah-v2 SDK
|
|
3
|
+
*/
|
|
4
|
+
export interface KYCStatus {
|
|
5
|
+
hasKYC: boolean;
|
|
6
|
+
commitment?: string;
|
|
7
|
+
attesterId?: number;
|
|
8
|
+
registeredAt?: number;
|
|
9
|
+
}
|
|
10
|
+
export interface RegisterKYCParams {
|
|
11
|
+
commitment: string;
|
|
12
|
+
signature: string;
|
|
13
|
+
attesterId: number;
|
|
14
|
+
}
|
|
15
|
+
export interface ProofRequest {
|
|
16
|
+
age: string;
|
|
17
|
+
jurisdiction: string;
|
|
18
|
+
is_accredited: string;
|
|
19
|
+
identity_data: string;
|
|
20
|
+
nonce: string;
|
|
21
|
+
min_age: string;
|
|
22
|
+
allowed_jurisdictions: string[];
|
|
23
|
+
require_accreditation: string;
|
|
24
|
+
commitment: string;
|
|
25
|
+
}
|
|
26
|
+
export interface ProofResponse {
|
|
27
|
+
proof: string;
|
|
28
|
+
public_inputs: string[];
|
|
29
|
+
commitment: string;
|
|
30
|
+
success: boolean;
|
|
31
|
+
error?: string;
|
|
32
|
+
}
|
|
33
|
+
export interface AttestationRequest {
|
|
34
|
+
commitment: string;
|
|
35
|
+
public_inputs: string[];
|
|
36
|
+
proof: string;
|
|
37
|
+
user_id: string;
|
|
38
|
+
}
|
|
39
|
+
export interface AttestationResponse {
|
|
40
|
+
commitment: string;
|
|
41
|
+
signature: string;
|
|
42
|
+
attester_id: number;
|
|
43
|
+
success: boolean;
|
|
44
|
+
error?: string;
|
|
45
|
+
}
|
|
46
|
+
export interface SDKConfig {
|
|
47
|
+
kycRegistryAddress: string;
|
|
48
|
+
attesterRegistryAddress: string;
|
|
49
|
+
proverServiceUrl?: string;
|
|
50
|
+
attesterServiceUrl?: string;
|
|
51
|
+
network?: 'mainnet' | 'testnet' | 'devnet';
|
|
52
|
+
}
|
|
53
|
+
export interface WalletConfig {
|
|
54
|
+
appName: string;
|
|
55
|
+
appIcon?: string;
|
|
56
|
+
redirectPath?: string;
|
|
57
|
+
}
|
package/dist/types.js
ADDED
package/dist/wallet.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wallet integration helpers
|
|
3
|
+
*/
|
|
4
|
+
import { UserSession } from '@stacks/connect';
|
|
5
|
+
import { WalletConfig } from './types';
|
|
6
|
+
export declare class WalletHelper {
|
|
7
|
+
private config;
|
|
8
|
+
constructor(config: WalletConfig);
|
|
9
|
+
/**
|
|
10
|
+
* Get app name
|
|
11
|
+
*/
|
|
12
|
+
getAppName(): string;
|
|
13
|
+
/**
|
|
14
|
+
* Check if user is authenticated
|
|
15
|
+
*/
|
|
16
|
+
isAuthenticated(session: UserSession | null): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Get user's Stacks address from session
|
|
19
|
+
*/
|
|
20
|
+
getUserAddress(session: UserSession | null): string | null;
|
|
21
|
+
}
|
package/dist/wallet.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Wallet integration helpers
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.WalletHelper = void 0;
|
|
7
|
+
class WalletHelper {
|
|
8
|
+
constructor(config) {
|
|
9
|
+
this.config = config;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Get app name
|
|
13
|
+
*/
|
|
14
|
+
getAppName() {
|
|
15
|
+
return this.config.appName;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Check if user is authenticated
|
|
19
|
+
*/
|
|
20
|
+
isAuthenticated(session) {
|
|
21
|
+
return session !== null && session.isUserSignedIn();
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Get user's Stacks address from session
|
|
25
|
+
*/
|
|
26
|
+
getUserAddress(session) {
|
|
27
|
+
if (!this.isAuthenticated(session)) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
const userData = session.loadUserData();
|
|
31
|
+
return userData.profile.stxAddress.mainnet || userData.profile.stxAddress.testnet;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
exports.WalletHelper = WalletHelper;
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "noah-clarity",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "TypeScript SDK for Noah-v2 KYC system on Stacks",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist",
|
|
9
|
+
"README.md"
|
|
10
|
+
],
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsc",
|
|
13
|
+
"prepublishOnly": "npm run build",
|
|
14
|
+
"test": "jest",
|
|
15
|
+
"test:local": "ts-node test-local.ts",
|
|
16
|
+
"lint": "eslint src --ext .ts"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"stacks",
|
|
20
|
+
"kyc",
|
|
21
|
+
"zero-knowledge",
|
|
22
|
+
"zk-proof",
|
|
23
|
+
"clarity",
|
|
24
|
+
"blockchain",
|
|
25
|
+
"privacy",
|
|
26
|
+
"identity"
|
|
27
|
+
],
|
|
28
|
+
"author": "",
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "https://github.com/Samuel1-ona/Noah-Clarity.git",
|
|
33
|
+
"directory": "packages/noah-sdk"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@stacks/connect": "^6.0.0",
|
|
37
|
+
"@stacks/network": "^6.17.0",
|
|
38
|
+
"@stacks/transactions": "^6.0.0"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@types/bip39": "^2.4.2",
|
|
42
|
+
"@types/jest": "^29.0.0",
|
|
43
|
+
"@types/node": "^20.0.0",
|
|
44
|
+
"bip39": "^3.1.0",
|
|
45
|
+
"dotenv": "^17.2.3",
|
|
46
|
+
"ed25519-hd-key": "^1.3.0",
|
|
47
|
+
"jest": "^29.0.0",
|
|
48
|
+
"ts-jest": "^29.0.0",
|
|
49
|
+
"ts-node": "^10.9.2",
|
|
50
|
+
"typescript": "^5.0.0"
|
|
51
|
+
}
|
|
52
|
+
}
|