@zkproofport-ai/sdk 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.
Files changed (58) hide show
  1. package/README.md +437 -0
  2. package/dist/attestation.d.ts +60 -0
  3. package/dist/attestation.d.ts.map +1 -0
  4. package/dist/attestation.js +220 -0
  5. package/dist/attestation.js.map +1 -0
  6. package/dist/cdp.d.ts +44 -0
  7. package/dist/cdp.d.ts.map +1 -0
  8. package/dist/cdp.js +89 -0
  9. package/dist/cdp.js.map +1 -0
  10. package/dist/config.d.ts +19 -0
  11. package/dist/config.d.ts.map +1 -0
  12. package/dist/config.js +25 -0
  13. package/dist/config.js.map +1 -0
  14. package/dist/constants.d.ts +18 -0
  15. package/dist/constants.d.ts.map +1 -0
  16. package/dist/constants.js +29 -0
  17. package/dist/constants.js.map +1 -0
  18. package/dist/flow.d.ts +19 -0
  19. package/dist/flow.d.ts.map +1 -0
  20. package/dist/flow.js +82 -0
  21. package/dist/flow.js.map +1 -0
  22. package/dist/index.d.ts +17 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +22 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/inputs.d.ts +56 -0
  27. package/dist/inputs.d.ts.map +1 -0
  28. package/dist/inputs.js +204 -0
  29. package/dist/inputs.js.map +1 -0
  30. package/dist/merkle.d.ts +34 -0
  31. package/dist/merkle.d.ts.map +1 -0
  32. package/dist/merkle.js +95 -0
  33. package/dist/merkle.js.map +1 -0
  34. package/dist/payment.d.ts +15 -0
  35. package/dist/payment.d.ts.map +1 -0
  36. package/dist/payment.js +114 -0
  37. package/dist/payment.js.map +1 -0
  38. package/dist/prove.d.ts +12 -0
  39. package/dist/prove.d.ts.map +1 -0
  40. package/dist/prove.js +25 -0
  41. package/dist/prove.js.map +1 -0
  42. package/dist/session.d.ts +8 -0
  43. package/dist/session.d.ts.map +1 -0
  44. package/dist/session.js +20 -0
  45. package/dist/session.js.map +1 -0
  46. package/dist/signer.d.ts +69 -0
  47. package/dist/signer.d.ts.map +1 -0
  48. package/dist/signer.js +51 -0
  49. package/dist/signer.js.map +1 -0
  50. package/dist/types.d.ts +136 -0
  51. package/dist/types.d.ts.map +1 -0
  52. package/dist/types.js +12 -0
  53. package/dist/types.js.map +1 -0
  54. package/dist/verify.d.ts +29 -0
  55. package/dist/verify.d.ts.map +1 -0
  56. package/dist/verify.js +56 -0
  57. package/dist/verify.js.map +1 -0
  58. package/package.json +34 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE9D,YAAY;AACZ,OAAO,EACL,QAAQ,EACR,0BAA0B,EAC1B,kBAAkB,EAClB,cAAc,GACf,MAAM,gBAAgB,CAAC;AAExB,gBAAgB;AAChB,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,0BAA0B;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG1C,4CAA4C;AAC5C,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEzD,oBAAoB;AACpB,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,UAAU,EACV,wBAAwB,GACzB,MAAM,aAAa,CAAC;AAIrB,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEnF,2CAA2C;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3C,cAAc;AACd,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,mBAAmB,EACnB,qBAAqB,EACrB,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAE1B,SAAS;AACT,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,qBAAqB,GACtB,MAAM,aAAa,CAAC"}
@@ -0,0 +1,56 @@
1
+ import type { CircuitId, ProveInputs, ClientConfig } from './types.js';
2
+ /**
3
+ * Convert a hex string to an array of byte values (numbers 0-255).
4
+ */
5
+ export declare function hexToBytes(hex: string): number[];
6
+ /**
7
+ * Extract X and Y coordinates from an uncompressed public key.
8
+ * Input: "0x04..." (130 hex chars) or "04..." (128 hex chars)
9
+ * Output: { x: "0x...", y: "0x..." } each 64 hex chars (32 bytes)
10
+ */
11
+ export declare function extractPubkeyCoordinates(pubkey: string): {
12
+ x: string;
13
+ y: string;
14
+ };
15
+ /**
16
+ * Compute the deterministic signal hash.
17
+ * signalHash = keccak256(solidityPacked(address, scopeString, circuitName))
18
+ */
19
+ export declare function computeSignalHash(userAddress: string, scopeString: string, circuitName: string): Uint8Array;
20
+ /**
21
+ * Recover user's uncompressed public key from their signature over the signal hash.
22
+ * Returns "0x04..." (130 hex chars).
23
+ */
24
+ export declare function recoverUserPubkey(signalHash: Uint8Array, userSignature: string): string;
25
+ /**
26
+ * Compute scope bytes from a scope string.
27
+ * scope = keccak256(toUtf8Bytes(scopeString))
28
+ */
29
+ export declare function computeScope(scopeString: string): Uint8Array;
30
+ /**
31
+ * Compute nullifier = keccak256(keccak256(address + signalHash) + scope)
32
+ */
33
+ export declare function computeNullifier(userAddress: string, signalHash: Uint8Array, scopeBytes: Uint8Array): Uint8Array;
34
+ /**
35
+ * Prepare all inputs for POST /prove.
36
+ *
37
+ * Steps:
38
+ * 1. Compute signal hash
39
+ * 2. Recover user public key from signature
40
+ * 3. Fetch EAS attestation + raw transaction from Base chain
41
+ * 4. Recover Coinbase attester public key from tx signature
42
+ * 5. Build authorized signer Merkle tree + proof
43
+ * 6. Compute scope bytes and nullifier
44
+ * 7. Assemble the ProveInputs object
45
+ *
46
+ * All hex string fields use "0x..." format. The server converts to decimal internally.
47
+ */
48
+ export declare function prepareInputs(config: ClientConfig, params: {
49
+ circuitId: CircuitId;
50
+ userAddress: string;
51
+ userSignature: string;
52
+ scope: string;
53
+ countryList?: string[];
54
+ isIncluded?: boolean;
55
+ }): Promise<ProveInputs>;
56
+ //# sourceMappingURL=inputs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inputs.d.ts","sourceRoot":"","sources":["../src/inputs.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAQvE;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAOhD;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAKjF;AAID;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,GAClB,UAAU,CAMZ;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,UAAU,EACtB,aAAa,EAAE,MAAM,GACpB,MAAM,CAKR;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,UAAU,CAE5D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,UAAU,EACtB,UAAU,EAAE,UAAU,GACrB,UAAU,CAQZ;AA4ED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE;IAChE,SAAS,EAAE,SAAS,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,GAAG,OAAO,CAAC,WAAW,CAAC,CAuEvB"}
package/dist/inputs.js ADDED
@@ -0,0 +1,204 @@
1
+ import { ethers } from 'ethers';
2
+ import { CIRCUITS, MERKLE_PROOF_MAX_DEPTH, COUNTRY_LIST_MAX_LENGTH } from './constants.js';
3
+ import { fetchAttestation, recoverAttesterPubkey, getSignerAddress } from './attestation.js';
4
+ import { findSignerIndex, buildSignerMerkleTree } from './merkle.js';
5
+ // ─── Utility functions ──────────────────────────────────────────────────
6
+ /**
7
+ * Convert a hex string to an array of byte values (numbers 0-255).
8
+ */
9
+ export function hexToBytes(hex) {
10
+ const cleanHex = hex.startsWith('0x') ? hex.slice(2) : hex;
11
+ const bytes = [];
12
+ for (let i = 0; i < cleanHex.length; i += 2) {
13
+ bytes.push(parseInt(cleanHex.slice(i, i + 2), 16));
14
+ }
15
+ return bytes;
16
+ }
17
+ /**
18
+ * Extract X and Y coordinates from an uncompressed public key.
19
+ * Input: "0x04..." (130 hex chars) or "04..." (128 hex chars)
20
+ * Output: { x: "0x...", y: "0x..." } each 64 hex chars (32 bytes)
21
+ */
22
+ export function extractPubkeyCoordinates(pubkey) {
23
+ const pubkeyHex = pubkey.startsWith('0x04') ? pubkey.slice(4) : pubkey.slice(2);
24
+ const x = '0x' + pubkeyHex.slice(0, 64);
25
+ const y = '0x' + pubkeyHex.slice(64, 128);
26
+ return { x, y };
27
+ }
28
+ // ─── Core computation functions ─────────────────────────────────────────
29
+ /**
30
+ * Compute the deterministic signal hash.
31
+ * signalHash = keccak256(solidityPacked(address, scopeString, circuitName))
32
+ */
33
+ export function computeSignalHash(userAddress, scopeString, circuitName) {
34
+ const signalPreimage = ethers.solidityPacked(['address', 'string', 'string'], [userAddress, scopeString, circuitName]);
35
+ return ethers.getBytes(ethers.keccak256(signalPreimage));
36
+ }
37
+ /**
38
+ * Recover user's uncompressed public key from their signature over the signal hash.
39
+ * Returns "0x04..." (130 hex chars).
40
+ */
41
+ export function recoverUserPubkey(signalHash, userSignature) {
42
+ const messageHex = ethers.hexlify(signalHash);
43
+ const ethSignedHash = ethers.hashMessage(ethers.getBytes(messageHex));
44
+ const pubkey = ethers.SigningKey.recoverPublicKey(ethSignedHash, userSignature);
45
+ return pubkey;
46
+ }
47
+ /**
48
+ * Compute scope bytes from a scope string.
49
+ * scope = keccak256(toUtf8Bytes(scopeString))
50
+ */
51
+ export function computeScope(scopeString) {
52
+ return ethers.getBytes(ethers.keccak256(ethers.toUtf8Bytes(scopeString)));
53
+ }
54
+ /**
55
+ * Compute nullifier = keccak256(keccak256(address + signalHash) + scope)
56
+ */
57
+ export function computeNullifier(userAddress, signalHash, scopeBytes) {
58
+ const userAddressBytes = ethers.getBytes(userAddress);
59
+ const userSecret = ethers.getBytes(ethers.keccak256(ethers.concat([userAddressBytes, signalHash])));
60
+ return ethers.getBytes(ethers.keccak256(ethers.concat([userSecret, scopeBytes])));
61
+ }
62
+ // ─── Internal helpers for input assembly ────────────────────────────────
63
+ /**
64
+ * Pad a byte array to a target length with trailing zeros.
65
+ */
66
+ function padBytes(arr, targetLength) {
67
+ const result = [...arr];
68
+ while (result.length < targetLength) {
69
+ result.push(0);
70
+ }
71
+ return result;
72
+ }
73
+ /**
74
+ * Split a signature into r (32 bytes) + s (32 bytes) = 64 bytes.
75
+ * Drops the v component.
76
+ */
77
+ function splitSignatureToBytes(signature) {
78
+ const sig = ethers.Signature.from(signature);
79
+ const rBytes = hexToBytes(sig.r);
80
+ const sBytes = hexToBytes(sig.s);
81
+ return [...rBytes, ...sBytes];
82
+ }
83
+ /**
84
+ * Encode a country list into the [[u8; 2]; 10] format.
85
+ * Each country code is 2 ASCII bytes (e.g., "US" -> [85, 83]).
86
+ * Pads to 10 entries with zero pairs.
87
+ */
88
+ function encodeCountryList(countries) {
89
+ const result = [];
90
+ for (let i = 0; i < COUNTRY_LIST_MAX_LENGTH; i++) {
91
+ if (i < countries.length) {
92
+ result.push(countries[i].charCodeAt(0).toString());
93
+ result.push(countries[i].charCodeAt(1).toString());
94
+ }
95
+ else {
96
+ result.push('0');
97
+ result.push('0');
98
+ }
99
+ }
100
+ return result;
101
+ }
102
+ /**
103
+ * Convert byte values to decimal string entries.
104
+ */
105
+ function bytesToDecimalStrings(bytes) {
106
+ return bytes.map(b => b.toString());
107
+ }
108
+ /**
109
+ * Convert a Uint8Array to decimal string entries.
110
+ */
111
+ function uint8ArrayToDecimalStrings(arr) {
112
+ return Array.from(arr).map(b => b.toString());
113
+ }
114
+ /**
115
+ * Build a padded Merkle proof: 8 * 32 = 256 bytes as decimal strings.
116
+ */
117
+ function buildPaddedMerkleProof(proof) {
118
+ const result = [];
119
+ for (let i = 0; i < MERKLE_PROOF_MAX_DEPTH; i++) {
120
+ if (i < proof.length) {
121
+ result.push(...bytesToDecimalStrings(hexToBytes(proof[i])));
122
+ }
123
+ else {
124
+ result.push(...bytesToDecimalStrings(new Array(32).fill(0)));
125
+ }
126
+ }
127
+ return result;
128
+ }
129
+ // ─── Main function ──────────────────────────────────────────────────────
130
+ /**
131
+ * Prepare all inputs for POST /prove.
132
+ *
133
+ * Steps:
134
+ * 1. Compute signal hash
135
+ * 2. Recover user public key from signature
136
+ * 3. Fetch EAS attestation + raw transaction from Base chain
137
+ * 4. Recover Coinbase attester public key from tx signature
138
+ * 5. Build authorized signer Merkle tree + proof
139
+ * 6. Compute scope bytes and nullifier
140
+ * 7. Assemble the ProveInputs object
141
+ *
142
+ * All hex string fields use "0x..." format. The server converts to decimal internally.
143
+ */
144
+ export async function prepareInputs(config, params) {
145
+ const { circuitId, userAddress, userSignature, scope } = params;
146
+ // Validate circuit
147
+ if (!(circuitId in CIRCUITS)) {
148
+ throw new Error(`Unknown circuit: ${circuitId}`);
149
+ }
150
+ // Validate country fields for country circuit
151
+ if (circuitId === 'coinbase_country_attestation') {
152
+ if (!params.countryList || params.countryList.length === 0) {
153
+ throw new Error('countryList is required for coinbase_country_attestation');
154
+ }
155
+ if (params.isIncluded === undefined || params.isIncluded === null) {
156
+ throw new Error('isIncluded is required for coinbase_country_attestation');
157
+ }
158
+ }
159
+ // Step 1: Compute signal hash
160
+ const signalHash = computeSignalHash(userAddress, scope, circuitId);
161
+ // Step 2: Recover user public key
162
+ const userPubkey = recoverUserPubkey(signalHash, userSignature);
163
+ const { x: userPubkeyX, y: userPubkeyY } = extractPubkeyCoordinates(userPubkey);
164
+ // Step 3: Fetch attestation transaction from Base chain
165
+ const attestationData = await fetchAttestation(config, circuitId, userAddress);
166
+ // Step 4: Recover Coinbase attester public key
167
+ const attesterPubkey = recoverAttesterPubkey(attestationData.rawTransaction);
168
+ const attesterAddress = getSignerAddress(attesterPubkey);
169
+ const { x: attesterPubkeyX, y: attesterPubkeyY } = extractPubkeyCoordinates(attesterPubkey);
170
+ // Step 5: Build Merkle tree
171
+ const signerIndex = findSignerIndex(attesterAddress);
172
+ const merkleData = buildSignerMerkleTree(signerIndex);
173
+ // Step 6: Compute scope and nullifier
174
+ const scopeBytes = computeScope(scope);
175
+ const nullifierBytes = computeNullifier(userAddress, signalHash, scopeBytes);
176
+ // Step 7: Convert raw TX to byte array
177
+ const rawTxBytes = hexToBytes(attestationData.rawTransaction);
178
+ const txLength = rawTxBytes.length;
179
+ // Assemble ProveInputs -- all values as hex strings (0x...)
180
+ const inputs = {
181
+ signal_hash: ethers.hexlify(signalHash),
182
+ nullifier: ethers.hexlify(nullifierBytes),
183
+ scope_bytes: ethers.hexlify(scopeBytes),
184
+ merkle_root: merkleData.root,
185
+ user_address: userAddress,
186
+ signature: userSignature,
187
+ user_pubkey_x: userPubkeyX,
188
+ user_pubkey_y: userPubkeyY,
189
+ raw_transaction: attestationData.rawTransaction,
190
+ tx_length: txLength,
191
+ coinbase_attester_pubkey_x: attesterPubkeyX,
192
+ coinbase_attester_pubkey_y: attesterPubkeyY,
193
+ merkle_proof: merkleData.proof,
194
+ leaf_index: merkleData.leafIndex,
195
+ depth: merkleData.depth,
196
+ };
197
+ // Add country-specific fields
198
+ if (circuitId === 'coinbase_country_attestation') {
199
+ inputs.country_list = params.countryList;
200
+ inputs.is_included = params.isIncluded;
201
+ }
202
+ return inputs;
203
+ }
204
+ //# sourceMappingURL=inputs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inputs.js","sourceRoot":"","sources":["../src/inputs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Simple binary Merkle tree for signer verification.
3
+ *
4
+ * Leaf: keccak256(address_bytes)
5
+ * Odd number of leaves: duplicate last leaf
6
+ * Internal node: keccak256(left || right)
7
+ */
8
+ export declare class SimpleMerkleTree {
9
+ private leaves;
10
+ private layers;
11
+ constructor(addresses: string[]);
12
+ getRoot(): string;
13
+ getProof(index: number): {
14
+ proof: string[];
15
+ leafIndex: number;
16
+ depth: number;
17
+ };
18
+ getLeafHash(index: number): string;
19
+ }
20
+ /**
21
+ * Find the index of a signer address in the authorized signers list.
22
+ * Case-insensitive comparison.
23
+ */
24
+ export declare function findSignerIndex(signerAddress: string): number;
25
+ /**
26
+ * Build a Merkle tree from authorized signers and get proof for the given signer index.
27
+ */
28
+ export declare function buildSignerMerkleTree(signerIndex: number): {
29
+ root: string;
30
+ proof: string[];
31
+ leafIndex: number;
32
+ depth: number;
33
+ };
34
+ //# sourceMappingURL=merkle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merkle.d.ts","sourceRoot":"","sources":["../src/merkle.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAW;IACzB,OAAO,CAAC,MAAM,CAAa;gBAEf,SAAS,EAAE,MAAM,EAAE;IA+B/B,OAAO,IAAI,MAAM;IAIjB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE;IA8B9E,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;CAMnC;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAU7D;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG;IAC1D,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf,CAMA"}
package/dist/merkle.js ADDED
@@ -0,0 +1,95 @@
1
+ import { ethers } from 'ethers';
2
+ import { AUTHORIZED_SIGNERS } from './constants.js';
3
+ /**
4
+ * Simple binary Merkle tree for signer verification.
5
+ *
6
+ * Leaf: keccak256(address_bytes)
7
+ * Odd number of leaves: duplicate last leaf
8
+ * Internal node: keccak256(left || right)
9
+ */
10
+ export class SimpleMerkleTree {
11
+ leaves;
12
+ layers;
13
+ constructor(addresses) {
14
+ if (addresses.length === 0) {
15
+ throw new Error('SimpleMerkleTree requires at least one address');
16
+ }
17
+ // Create leaf hashes: keccak256(address_bytes)
18
+ this.leaves = addresses.map(addr => {
19
+ const addrBytes = ethers.getBytes(ethers.getAddress(addr));
20
+ return ethers.keccak256(addrBytes);
21
+ });
22
+ // Build layers bottom-up
23
+ this.layers = [this.leaves];
24
+ let currentLayer = this.leaves;
25
+ while (currentLayer.length > 1) {
26
+ const nextLayer = [];
27
+ for (let i = 0; i < currentLayer.length; i += 2) {
28
+ const left = currentLayer[i];
29
+ const right = currentLayer[i + 1] || left; // duplicate if odd
30
+ const combined = ethers.concat([
31
+ ethers.getBytes(left),
32
+ ethers.getBytes(right),
33
+ ]);
34
+ nextLayer.push(ethers.keccak256(combined));
35
+ }
36
+ this.layers.push(nextLayer);
37
+ currentLayer = nextLayer;
38
+ }
39
+ }
40
+ getRoot() {
41
+ return this.layers[this.layers.length - 1][0];
42
+ }
43
+ getProof(index) {
44
+ if (index < 0 || index >= this.leaves.length) {
45
+ throw new Error(`Leaf index ${index} out of bounds (0..${this.leaves.length - 1})`);
46
+ }
47
+ const proof = [];
48
+ let idx = index;
49
+ for (let i = 0; i < this.layers.length - 1; i++) {
50
+ const layer = this.layers[i];
51
+ const isRight = idx % 2 === 1;
52
+ const siblingIdx = isRight ? idx - 1 : idx + 1;
53
+ if (siblingIdx < layer.length) {
54
+ proof.push(layer[siblingIdx]);
55
+ }
56
+ else {
57
+ // No sibling -- use self (duplicate)
58
+ proof.push(layer[idx]);
59
+ }
60
+ idx = Math.floor(idx / 2);
61
+ }
62
+ return {
63
+ proof,
64
+ leafIndex: index,
65
+ depth: proof.length,
66
+ };
67
+ }
68
+ getLeafHash(index) {
69
+ if (index < 0 || index >= this.leaves.length) {
70
+ throw new Error(`Leaf index ${index} out of bounds (0..${this.leaves.length - 1})`);
71
+ }
72
+ return this.leaves[index];
73
+ }
74
+ }
75
+ /**
76
+ * Find the index of a signer address in the authorized signers list.
77
+ * Case-insensitive comparison.
78
+ */
79
+ export function findSignerIndex(signerAddress) {
80
+ const index = AUTHORIZED_SIGNERS.findIndex(addr => addr.toLowerCase() === signerAddress.toLowerCase());
81
+ if (index === -1) {
82
+ throw new Error(`Signer ${signerAddress} is not in the authorized signers list`);
83
+ }
84
+ return index;
85
+ }
86
+ /**
87
+ * Build a Merkle tree from authorized signers and get proof for the given signer index.
88
+ */
89
+ export function buildSignerMerkleTree(signerIndex) {
90
+ const tree = new SimpleMerkleTree(AUTHORIZED_SIGNERS);
91
+ const root = tree.getRoot();
92
+ const { proof, leafIndex, depth } = tree.getProof(signerIndex);
93
+ return { root, proof, leafIndex, depth };
94
+ }
95
+ //# sourceMappingURL=merkle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merkle.js","sourceRoot":"","sources":["../src/merkle.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { PaymentInfo } from './types.js';
2
+ import type { ProofportSigner } from './signer.js';
3
+ /**
4
+ * Make payment for a proof session via x402 protocol.
5
+ *
6
+ * Uses EIP-3009 TransferWithAuthorization signed by the client,
7
+ * settled via x402 facilitator (facilitator pays gas).
8
+ * Works on both Base Sepolia (testnet) and Base (mainnet).
9
+ *
10
+ * @param signer - ProofportSigner (ethers, CDP MPC, or any implementation)
11
+ * @param payment - PaymentInfo from session or 402 response
12
+ * @returns Transaction hash
13
+ */
14
+ export declare function makePayment(signer: ProofportSigner, payment: PaymentInfo): Promise<string>;
15
+ //# sourceMappingURL=payment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"payment.d.ts","sourceRoot":"","sources":["../src/payment.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAenD;;;;;;;;;;GAUG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,MAAM,CAAC,CAsGjB"}
@@ -0,0 +1,114 @@
1
+ import { ethers } from 'ethers';
2
+ const X402_FACILITATOR = 'https://www.x402.org/facilitator';
3
+ const CHAIN_IDS = {
4
+ 'base-sepolia': 84532,
5
+ 'base': 8453,
6
+ };
7
+ // EIP-712 domain names per USDC contract (queried via name() on-chain)
8
+ const USDC_DOMAIN_NAMES = {
9
+ 'base-sepolia': 'USDC',
10
+ 'base': 'USD Coin',
11
+ };
12
+ /**
13
+ * Make payment for a proof session via x402 protocol.
14
+ *
15
+ * Uses EIP-3009 TransferWithAuthorization signed by the client,
16
+ * settled via x402 facilitator (facilitator pays gas).
17
+ * Works on both Base Sepolia (testnet) and Base (mainnet).
18
+ *
19
+ * @param signer - ProofportSigner (ethers, CDP MPC, or any implementation)
20
+ * @param payment - PaymentInfo from session or 402 response
21
+ * @returns Transaction hash
22
+ */
23
+ export async function makePayment(signer, payment) {
24
+ const network = payment.network;
25
+ const chainId = CHAIN_IDS[network];
26
+ if (!chainId) {
27
+ throw new Error(`Unsupported network: ${network}`);
28
+ }
29
+ // Pad nonce to bytes32 (EIP-3009 requires bytes32 nonce)
30
+ const nonce = ethers.zeroPadValue(payment.nonce, 32);
31
+ // Validity window
32
+ const validAfter = 0;
33
+ const validBefore = Math.floor(Date.now() / 1000) + 3600; // 1 hour
34
+ // EIP-712 domain for USDC (domain name differs between testnet and mainnet)
35
+ const domain = {
36
+ name: USDC_DOMAIN_NAMES[network] || 'USD Coin',
37
+ version: '2',
38
+ chainId,
39
+ verifyingContract: payment.asset,
40
+ };
41
+ const types = {
42
+ TransferWithAuthorization: [
43
+ { name: 'from', type: 'address' },
44
+ { name: 'to', type: 'address' },
45
+ { name: 'value', type: 'uint256' },
46
+ { name: 'validAfter', type: 'uint256' },
47
+ { name: 'validBefore', type: 'uint256' },
48
+ { name: 'nonce', type: 'bytes32' },
49
+ ],
50
+ };
51
+ const from = await signer.getAddress();
52
+ const message = {
53
+ from,
54
+ to: payment.recipient,
55
+ value: payment.amount,
56
+ validAfter,
57
+ validBefore,
58
+ nonce,
59
+ };
60
+ // Sign EIP-712 TransferWithAuthorization
61
+ const signature = await signer.signTypedData(domain, types, message);
62
+ // Settle via x402 facilitator (facilitator pays gas)
63
+ const settlePayload = {
64
+ x402Version: 1,
65
+ scheme: 'exact',
66
+ network,
67
+ paymentPayload: {
68
+ x402Version: 1,
69
+ scheme: 'exact',
70
+ network,
71
+ payload: {
72
+ signature,
73
+ authorization: {
74
+ from,
75
+ to: payment.recipient,
76
+ value: String(payment.amount),
77
+ validAfter: String(validAfter),
78
+ validBefore: String(validBefore),
79
+ nonce,
80
+ },
81
+ },
82
+ },
83
+ paymentRequirements: {
84
+ scheme: 'exact',
85
+ network,
86
+ maxAmountRequired: String(payment.amount),
87
+ asset: payment.asset,
88
+ resource: `${payment.recipient}/proof`,
89
+ description: 'ZK proof generation payment',
90
+ mimeType: 'application/json',
91
+ payTo: payment.recipient,
92
+ extra: {
93
+ name: USDC_DOMAIN_NAMES[network] || 'USD Coin',
94
+ version: '2',
95
+ },
96
+ },
97
+ };
98
+ const settleResponse = await fetch(`${X402_FACILITATOR}/settle`, {
99
+ method: 'POST',
100
+ headers: { 'Content-Type': 'application/json' },
101
+ body: JSON.stringify(settlePayload),
102
+ });
103
+ if (!settleResponse.ok) {
104
+ const error = await settleResponse.text();
105
+ throw new Error(`x402 facilitator settle failed: ${error}`);
106
+ }
107
+ const settleResult = (await settleResponse.json());
108
+ const txHash = settleResult.txHash || settleResult.transaction?.hash || settleResult.transaction;
109
+ if (!txHash) {
110
+ throw new Error(`x402 settle failed: ${settleResult.errorReason || 'no transaction hash'}`);
111
+ }
112
+ return txHash;
113
+ }
114
+ //# sourceMappingURL=payment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"payment.js","sourceRoot":"","sources":["../src/payment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAIhC,MAAM,gBAAgB,GAAG,kCAAkC,CAAC;AAE5D,MAAM,SAAS,GAA2B;IACxC,cAAc,EAAE,KAAK;IACrB,MAAM,EAAE,IAAI;CACb,CAAC;AAEF,uEAAuE;AACvE,MAAM,iBAAiB,GAA2B;IAChD,cAAc,EAAE,MAAM;IACtB,MAAM,EAAE,UAAU;CACnB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAuB,EACvB,OAAoB;IAEpB,MAAM,OAAO,GAAG,OAAO,CAAC,OAAkC,CAAC;IAC3D,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IACnC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,wBAAwB,OAAO,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,yDAAyD;IACzD,MAAM,KAAK,GAAG,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAErD,kBAAkB;IAClB,MAAM,UAAU,GAAG,CAAC,CAAC;IACrB,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,SAAS;IAEnE,4EAA4E;IAC5E,MAAM,MAAM,GAAG;QACb,IAAI,EAAE,iBAAiB,CAAC,OAAO,CAAC,IAAI,UAAU;QAC9C,OAAO,EAAE,GAAG;QACZ,OAAO;QACP,iBAAiB,EAAE,OAAO,CAAC,KAAK;KACjC,CAAC;IAEF,MAAM,KAAK,GAAG;QACZ,yBAAyB,EAAE;YACzB,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE;YACjC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE;YAC/B,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE;YAClC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE;YACvC,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,SAAS,EAAE;YACxC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE;SACnC;KACF,CAAC;IAEF,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,UAAU,EAAE,CAAC;IAEvC,MAAM,OAAO,GAAG;QACd,IAAI;QACJ,EAAE,EAAE,OAAO,CAAC,SAAS;QACrB,KAAK,EAAE,OAAO,CAAC,MAAM;QACrB,UAAU;QACV,WAAW;QACX,KAAK;KACN,CAAC;IAEF,yCAAyC;IACzC,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IAErE,qDAAqD;IACrD,MAAM,aAAa,GAAG;QACpB,WAAW,EAAE,CAAC;QACd,MAAM,EAAE,OAAO;QACf,OAAO;QACP,cAAc,EAAE;YACd,WAAW,EAAE,CAAC;YACd,MAAM,EAAE,OAAO;YACf,OAAO;YACP,OAAO,EAAE;gBACP,SAAS;gBACT,aAAa,EAAE;oBACb,IAAI;oBACJ,EAAE,EAAE,OAAO,CAAC,SAAS;oBACrB,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;oBAC7B,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;oBAC9B,WAAW,EAAE,MAAM,CAAC,WAAW,CAAC;oBAChC,KAAK;iBACN;aACF;SACF;QACD,mBAAmB,EAAE;YACnB,MAAM,EAAE,OAAO;YACf,OAAO;YACP,iBAAiB,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;YACzC,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,QAAQ,EAAE,GAAG,OAAO,CAAC,SAAS,QAAQ;YACtC,WAAW,EAAE,6BAA6B;YAC1C,QAAQ,EAAE,kBAAkB;YAC5B,KAAK,EAAE,OAAO,CAAC,SAAS;YACxB,KAAK,EAAE;gBACL,IAAI,EAAE,iBAAiB,CAAC,OAAO,CAAC,IAAI,UAAU;gBAC9C,OAAO,EAAE,GAAG;aACb;SACF;KACF,CAAC;IAEF,MAAM,cAAc,GAAG,MAAM,KAAK,CAAC,GAAG,gBAAgB,SAAS,EAAE;QAC/D,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC;KACpC,CAAC,CAAC;IAEH,IAAI,CAAC,cAAc,CAAC,EAAE,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,MAAM,cAAc,CAAC,IAAI,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CAAC,mCAAmC,KAAK,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,MAAM,YAAY,GAAG,CAAC,MAAM,cAAc,CAAC,IAAI,EAAE,CAAQ,CAAC;IAC1D,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,IAAI,YAAY,CAAC,WAAW,EAAE,IAAI,IAAI,YAAY,CAAC,WAAW,CAAC;IACjG,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,uBAAuB,YAAY,CAAC,WAAW,IAAI,qBAAqB,EAAE,CAAC,CAAC;IAC9F,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { ClientConfig, CircuitName, ProveInputs, ProveResponse } from './types.js';
2
+ /**
3
+ * Submit proof generation with x402 payment headers.
4
+ * POST /api/v1/prove with X-Payment-TX and X-Payment-Nonce headers.
5
+ */
6
+ export declare function submitProof(config: ClientConfig, request: {
7
+ circuit: CircuitName;
8
+ inputs: ProveInputs;
9
+ paymentTxHash: string;
10
+ paymentNonce: string;
11
+ }): Promise<ProveResponse>;
12
+ //# sourceMappingURL=prove.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prove.d.ts","sourceRoot":"","sources":["../src/prove.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAExF;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE;IACP,OAAO,EAAE,WAAW,CAAC;IACrB,MAAM,EAAE,WAAW,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;CACtB,GACA,OAAO,CAAC,aAAa,CAAC,CAqBxB"}
package/dist/prove.js ADDED
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Submit proof generation with x402 payment headers.
3
+ * POST /api/v1/prove with X-Payment-TX and X-Payment-Nonce headers.
4
+ */
5
+ export async function submitProof(config, request) {
6
+ const url = `${config.baseUrl}/api/v1/prove`;
7
+ const response = await fetch(url, {
8
+ method: 'POST',
9
+ headers: {
10
+ 'Content-Type': 'application/json',
11
+ 'X-Payment-TX': request.paymentTxHash,
12
+ 'X-Payment-Nonce': request.paymentNonce,
13
+ },
14
+ body: JSON.stringify({
15
+ circuit: request.circuit,
16
+ inputs: request.inputs,
17
+ }),
18
+ });
19
+ if (!response.ok) {
20
+ const error = await response.json().catch(() => ({ message: `HTTP ${response.status}` }));
21
+ throw new Error(`Proof generation failed: ${JSON.stringify(error)}`);
22
+ }
23
+ return response.json();
24
+ }
25
+ //# sourceMappingURL=prove.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prove.js","sourceRoot":"","sources":["../src/prove.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAoB,EACpB,OAKC;IAED,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC,OAAO,eAAe,CAAC;IAC7C,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAChC,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,cAAc,EAAE,OAAO,CAAC,aAAa;YACrC,iBAAiB,EAAE,OAAO,CAAC,YAAY;SACxC;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACnB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC;KACH,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,QAAQ,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC;QAC1F,MAAM,IAAI,KAAK,CAAC,4BAA4B,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACvE,CAAC;IAED,OAAO,QAAQ,CAAC,IAAI,EAA4B,CAAC;AACnD,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { ClientConfig, CircuitName, ChallengeResponse, ProveInputs } from './types.js';
2
+ /**
3
+ * Request a 402 payment challenge from the server.
4
+ * POST /api/v1/prove without payment headers → 402 with nonce + payment info.
5
+ */
6
+ export declare function requestChallenge(config: ClientConfig, circuit: CircuitName, inputs: ProveInputs): Promise<ChallengeResponse>;
7
+ export { requestChallenge as createSession };
8
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE5F;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,iBAAiB,CAAC,CAc5B;AAGD,OAAO,EAAE,gBAAgB,IAAI,aAAa,EAAE,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Request a 402 payment challenge from the server.
3
+ * POST /api/v1/prove without payment headers → 402 with nonce + payment info.
4
+ */
5
+ export async function requestChallenge(config, circuit, inputs) {
6
+ const url = `${config.baseUrl}/api/v1/prove`;
7
+ const response = await fetch(url, {
8
+ method: 'POST',
9
+ headers: { 'Content-Type': 'application/json' },
10
+ body: JSON.stringify({ circuit, inputs }),
11
+ });
12
+ if (response.status !== 402) {
13
+ const error = await response.json().catch(() => ({ message: `HTTP ${response.status}` }));
14
+ throw new Error(`Expected 402 challenge, got ${response.status}: ${error.message || response.status}`);
15
+ }
16
+ return response.json();
17
+ }
18
+ // Backward-compatible alias (deprecated — use requestChallenge instead)
19
+ export { requestChallenge as createSession };
20
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,MAAoB,EACpB,OAAoB,EACpB,MAAmB;IAEnB,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC,OAAO,eAAe,CAAC;IAC7C,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAChC,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;KAC1C,CAAC,CAAC;IAEH,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QAC5B,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,QAAQ,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC;QAC1F,MAAM,IAAI,KAAK,CAAC,+BAA+B,QAAQ,CAAC,MAAM,KAAM,KAAa,CAAC,OAAO,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IAClH,CAAC;IAED,OAAO,QAAQ,CAAC,IAAI,EAAgC,CAAC;AACvD,CAAC;AAED,wEAAwE;AACxE,OAAO,EAAE,gBAAgB,IAAI,aAAa,EAAE,CAAC"}