@veil-cash/sdk 0.6.3 → 0.6.4
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 +1 -0
- package/SDK.md +45 -0
- package/dist/cli/index.cjs +145 -115
- package/dist/index.cjs +113 -90
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +102 -64
- package/dist/index.d.ts +102 -64
- package/dist/index.js +90 -48
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
- package/src/ffjavascript.d.ts +28 -0
- package/src/index.ts +1 -1
- package/src/keypair.ts +2 -4
- package/src/prover.ts +108 -36
- package/src/subaccount.ts +2 -0
- package/src/transaction.ts +8 -2
- package/src/transfer.ts +5 -1
- package/src/types.ts +21 -0
- package/src/utils.ts +12 -5
- package/src/utxo.ts +1 -0
- package/src/withdraw.ts +2 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@veil-cash/sdk",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.4",
|
|
4
4
|
"description": "SDK and CLI for interacting with Veil Cash privacy pools - keypair generation, deposits, and status checking",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
"url": "https://github.com/veildotcash/veildotcash-sdk"
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
|
+
"buffer": "^6.0.3",
|
|
51
52
|
"circomlib": "github:tornadocash/circomlib#d20d53411d1bef61f38c99a8b36d5d0cc4836aa1",
|
|
52
53
|
"commander": "^14.0.2",
|
|
53
54
|
"dotenv": "^17.2.3",
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
declare module 'ffjavascript' {
|
|
2
|
+
export const utils: {
|
|
3
|
+
stringifyBigInts: (obj: unknown) => unknown;
|
|
4
|
+
unstringifyBigInts: (obj: unknown) => unknown;
|
|
5
|
+
};
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
declare module 'circomlib' {
|
|
9
|
+
const circomlib: {
|
|
10
|
+
poseidon: (items: Array<bigint | string | number>) => { toString: () => string };
|
|
11
|
+
};
|
|
12
|
+
export default circomlib;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
declare module 'eth-sig-util' {
|
|
16
|
+
import type { EncryptedMessage } from './types.js';
|
|
17
|
+
|
|
18
|
+
const ethSigUtil: {
|
|
19
|
+
getEncryptionPublicKey: (privateKey: string) => string;
|
|
20
|
+
encrypt: (
|
|
21
|
+
receiverPublicKey: string,
|
|
22
|
+
msgParams: { data: string },
|
|
23
|
+
version: 'x25519-xsalsa20-poly1305'
|
|
24
|
+
) => EncryptedMessage;
|
|
25
|
+
decrypt: (encryptedData: EncryptedMessage, receiverPrivateKey: string) => string;
|
|
26
|
+
};
|
|
27
|
+
export default ethSigUtil;
|
|
28
|
+
}
|
package/src/index.ts
CHANGED
package/src/keypair.ts
CHANGED
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { ethers } from 'ethers';
|
|
7
|
+
import { Buffer } from 'buffer';
|
|
7
8
|
import { privateKeyToAccount } from 'viem/accounts';
|
|
9
|
+
import ethSigUtil from 'eth-sig-util';
|
|
8
10
|
import { poseidonHash, toFixedHex } from './utils.js';
|
|
9
11
|
import type { EncryptedMessage } from './types.js';
|
|
10
12
|
|
|
@@ -20,10 +22,6 @@ export const VEIL_SIGNED_MESSAGE = "Sign this message to create your Veil Wallet
|
|
|
20
22
|
*/
|
|
21
23
|
export type MessageSigner = (message: string) => Promise<string>;
|
|
22
24
|
|
|
23
|
-
// eth-sig-util for x25519 encryption
|
|
24
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
25
|
-
const ethSigUtil = require('eth-sig-util');
|
|
26
|
-
|
|
27
25
|
/**
|
|
28
26
|
* Pack encrypted message into hex string
|
|
29
27
|
*/
|
package/src/prover.ts
CHANGED
|
@@ -4,10 +4,8 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { groth16 } from 'snarkjs';
|
|
7
|
+
import { utils } from 'ffjavascript';
|
|
7
8
|
import { toFixedHex } from './utils.js';
|
|
8
|
-
import * as path from 'path';
|
|
9
|
-
import * as fs from 'fs';
|
|
10
|
-
import { fileURLToPath } from 'url';
|
|
11
9
|
|
|
12
10
|
// Type definition for ffjavascript utils
|
|
13
11
|
interface FFJavascriptUtils {
|
|
@@ -15,15 +13,7 @@ interface FFJavascriptUtils {
|
|
|
15
13
|
unstringifyBigInts: (obj: unknown) => unknown;
|
|
16
14
|
}
|
|
17
15
|
|
|
18
|
-
|
|
19
|
-
let utils: FFJavascriptUtils | null = null;
|
|
20
|
-
try {
|
|
21
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
22
|
-
const ffjavascript = require('ffjavascript');
|
|
23
|
-
utils = ffjavascript.utils;
|
|
24
|
-
} catch {
|
|
25
|
-
console.warn('ffjavascript not found. Proof generation may not work.');
|
|
26
|
-
}
|
|
16
|
+
const ffUtils = utils as FFJavascriptUtils;
|
|
27
17
|
|
|
28
18
|
/**
|
|
29
19
|
* Input data for ZK proof generation
|
|
@@ -62,19 +52,70 @@ interface ProveResult {
|
|
|
62
52
|
publicSignals: string[];
|
|
63
53
|
}
|
|
64
54
|
|
|
55
|
+
/**
|
|
56
|
+
* Directory/base URL where proving keys are hosted, or a resolver that returns
|
|
57
|
+
* the circuit base path without the `.wasm` / `.zkey` extension.
|
|
58
|
+
*/
|
|
59
|
+
export type ProvingKeyPath = string | ((circuitName: string) => string);
|
|
60
|
+
|
|
61
|
+
export interface ProveOptions {
|
|
62
|
+
/**
|
|
63
|
+
* Proving key location.
|
|
64
|
+
*
|
|
65
|
+
* In Node this defaults to the package/source `keys` directory. In browsers
|
|
66
|
+
* this defaults to `/keys`, so apps can serve `/keys/transaction2.wasm` and
|
|
67
|
+
* `/keys/transaction2.zkey` from their own origin.
|
|
68
|
+
*/
|
|
69
|
+
provingKeyPath?: ProvingKeyPath;
|
|
70
|
+
/** Force snarkjs single-threaded proving. Defaults to true. */
|
|
71
|
+
singleThread?: boolean;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function isBrowserRuntime(): boolean {
|
|
75
|
+
return !(typeof process !== 'undefined' && !!process.versions?.node);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function stripTrailingSlash(value: string): string {
|
|
79
|
+
return value.endsWith('/') ? value.slice(0, -1) : value;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function normalizeCircuitBasePath(provingKeyPath: ProvingKeyPath, circuitName: string): string {
|
|
83
|
+
const resolvedPath =
|
|
84
|
+
typeof provingKeyPath === 'function' ? provingKeyPath(circuitName) : provingKeyPath;
|
|
85
|
+
|
|
86
|
+
const withoutExtension = resolvedPath.replace(/\.(wasm|zkey)$/i, '');
|
|
87
|
+
if (withoutExtension.endsWith(`/${circuitName}`) || withoutExtension.endsWith(`\\${circuitName}`)) {
|
|
88
|
+
return withoutExtension;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return `${stripTrailingSlash(withoutExtension)}/${circuitName}`;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function importNodeModule<T>(specifier: string): Promise<T> {
|
|
95
|
+
const dynamicImport = new Function('specifier', 'return import(specifier)') as (
|
|
96
|
+
specifier: string
|
|
97
|
+
) => Promise<T>;
|
|
98
|
+
return dynamicImport(specifier);
|
|
99
|
+
}
|
|
100
|
+
|
|
65
101
|
/**
|
|
66
102
|
* Find the keys directory containing circuit files
|
|
67
103
|
* Works in both development and installed package scenarios
|
|
68
104
|
*/
|
|
69
|
-
function
|
|
105
|
+
async function findNodeKeysDirectory(): Promise<string> {
|
|
106
|
+
const [{ existsSync }, pathModule, { fileURLToPath }] = await Promise.all([
|
|
107
|
+
importNodeModule<typeof import('node:fs')>('node:fs'),
|
|
108
|
+
importNodeModule<typeof import('node:path')>('node:path'),
|
|
109
|
+
importNodeModule<typeof import('node:url')>('node:url'),
|
|
110
|
+
]);
|
|
111
|
+
const path = pathModule;
|
|
112
|
+
|
|
70
113
|
// Try multiple possible locations
|
|
71
114
|
const possiblePaths = [
|
|
72
115
|
// When running from package (installed via npm)
|
|
73
|
-
path.resolve(
|
|
74
|
-
path.resolve(__dirname, '..', '..', 'keys'),
|
|
116
|
+
path.resolve(process.cwd(), 'node_modules', '@veil-cash', 'sdk', 'keys'),
|
|
75
117
|
// When running from source
|
|
76
118
|
path.resolve(process.cwd(), 'keys'),
|
|
77
|
-
// ESM module path
|
|
78
119
|
];
|
|
79
120
|
|
|
80
121
|
// Try to get module directory for ESM
|
|
@@ -83,11 +124,11 @@ function findKeysDirectory(): string {
|
|
|
83
124
|
const currentDir = path.dirname(currentFilePath);
|
|
84
125
|
possiblePaths.unshift(path.resolve(currentDir, '..', 'keys'));
|
|
85
126
|
} catch {
|
|
86
|
-
//
|
|
127
|
+
// Ignore non-file module URLs.
|
|
87
128
|
}
|
|
88
129
|
|
|
89
130
|
for (const p of possiblePaths) {
|
|
90
|
-
if (
|
|
131
|
+
if (existsSync(p) && existsSync(path.join(p, 'transaction2.wasm'))) {
|
|
91
132
|
return p;
|
|
92
133
|
}
|
|
93
134
|
}
|
|
@@ -97,6 +138,46 @@ function findKeysDirectory(): string {
|
|
|
97
138
|
);
|
|
98
139
|
}
|
|
99
140
|
|
|
141
|
+
async function resolveProvingKeyPaths(
|
|
142
|
+
circuitName: string,
|
|
143
|
+
provingKeyPath?: ProvingKeyPath,
|
|
144
|
+
): Promise<{ wasmPath: string; zkeyPath: string }> {
|
|
145
|
+
if (provingKeyPath) {
|
|
146
|
+
const circuitBasePath = normalizeCircuitBasePath(provingKeyPath, circuitName);
|
|
147
|
+
return {
|
|
148
|
+
wasmPath: `${circuitBasePath}.wasm`,
|
|
149
|
+
zkeyPath: `${circuitBasePath}.zkey`,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (isBrowserRuntime()) {
|
|
154
|
+
return {
|
|
155
|
+
wasmPath: `/keys/${circuitName}.wasm`,
|
|
156
|
+
zkeyPath: `/keys/${circuitName}.zkey`,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const keysDir = await findNodeKeysDirectory();
|
|
161
|
+
return {
|
|
162
|
+
wasmPath: `${keysDir}/${circuitName}.wasm`,
|
|
163
|
+
zkeyPath: `${keysDir}/${circuitName}.zkey`,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async function assertNodeKeyFilesExist(wasmPath: string, zkeyPath: string): Promise<void> {
|
|
168
|
+
if (isBrowserRuntime() || wasmPath.startsWith('http://') || wasmPath.startsWith('https://')) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const { existsSync } = await importNodeModule<typeof import('node:fs')>('node:fs');
|
|
173
|
+
if (!existsSync(wasmPath)) {
|
|
174
|
+
throw new Error(`Circuit WASM file not found: ${wasmPath}`);
|
|
175
|
+
}
|
|
176
|
+
if (!existsSync(zkeyPath)) {
|
|
177
|
+
throw new Error(`Circuit zkey file not found: ${zkeyPath}`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
100
181
|
/**
|
|
101
182
|
* Generate a ZK proof for a transaction
|
|
102
183
|
*
|
|
@@ -110,32 +191,23 @@ function findKeysDirectory(): string {
|
|
|
110
191
|
* // Returns: 0x1234...abcd (256 bytes hex)
|
|
111
192
|
* ```
|
|
112
193
|
*/
|
|
113
|
-
export async function prove(
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
const zkeyPath = path.join(keysDir, `${circuitName}.zkey`);
|
|
121
|
-
|
|
122
|
-
// Verify files exist
|
|
123
|
-
if (!fs.existsSync(wasmPath)) {
|
|
124
|
-
throw new Error(`Circuit WASM file not found: ${wasmPath}`);
|
|
125
|
-
}
|
|
126
|
-
if (!fs.existsSync(zkeyPath)) {
|
|
127
|
-
throw new Error(`Circuit zkey file not found: ${zkeyPath}`);
|
|
128
|
-
}
|
|
194
|
+
export async function prove(
|
|
195
|
+
input: ProofInput,
|
|
196
|
+
circuitName: string,
|
|
197
|
+
options: ProveOptions = {},
|
|
198
|
+
): Promise<string> {
|
|
199
|
+
const { wasmPath, zkeyPath } = await resolveProvingKeyPaths(circuitName, options.provingKeyPath);
|
|
200
|
+
await assertNodeKeyFilesExist(wasmPath, zkeyPath);
|
|
129
201
|
|
|
130
202
|
// Generate proof using snarkjs
|
|
131
203
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
132
204
|
const result = await groth16.fullProve(
|
|
133
|
-
|
|
205
|
+
ffUtils.stringifyBigInts(input) as any,
|
|
134
206
|
wasmPath,
|
|
135
207
|
zkeyPath,
|
|
136
208
|
undefined,
|
|
137
209
|
undefined,
|
|
138
|
-
{ singleThread: true },
|
|
210
|
+
{ singleThread: options.singleThread ?? true },
|
|
139
211
|
);
|
|
140
212
|
const proof = result.proof as unknown as SnarkProof;
|
|
141
213
|
|
package/src/subaccount.ts
CHANGED
|
@@ -563,6 +563,7 @@ export async function mergeSubaccount(
|
|
|
563
563
|
pool = 'eth',
|
|
564
564
|
rpcUrl,
|
|
565
565
|
relayUrl,
|
|
566
|
+
provingKeyPath,
|
|
566
567
|
onProgress,
|
|
567
568
|
} = options;
|
|
568
569
|
|
|
@@ -684,6 +685,7 @@ export async function mergeSubaccount(
|
|
|
684
685
|
recipient: '0x0000000000000000000000000000000000000000',
|
|
685
686
|
relayer: '0x0000000000000000000000000000000000000000',
|
|
686
687
|
onProgress,
|
|
688
|
+
provingKeyPath,
|
|
687
689
|
});
|
|
688
690
|
|
|
689
691
|
// Submit to relay
|
package/src/transaction.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { buildMerkleTree, MERKLE_TREE_HEIGHT } from './merkle.js';
|
|
7
|
-
import { prove, selectCircuit, type ProofInput } from './prover.js';
|
|
7
|
+
import { prove, selectCircuit, type ProofInput, type ProvingKeyPath } from './prover.js';
|
|
8
8
|
import { toFixedHex, getExtDataHash, shuffle, FIELD_SIZE } from './utils.js';
|
|
9
9
|
import { Utxo } from './utxo.js';
|
|
10
10
|
|
|
@@ -58,6 +58,8 @@ export interface PrepareTransactionParams {
|
|
|
58
58
|
relayer?: string | bigint | number;
|
|
59
59
|
/** Optional progress callback */
|
|
60
60
|
onProgress?: (stage: string, detail?: string) => void;
|
|
61
|
+
/** Optional proving key directory/base URL or circuit path resolver */
|
|
62
|
+
provingKeyPath?: ProvingKeyPath;
|
|
61
63
|
}
|
|
62
64
|
|
|
63
65
|
/**
|
|
@@ -72,6 +74,7 @@ interface GetProofParams {
|
|
|
72
74
|
recipient: string | bigint;
|
|
73
75
|
relayer: string | bigint;
|
|
74
76
|
onProgress?: (stage: string, detail?: string) => void;
|
|
77
|
+
provingKeyPath?: ProvingKeyPath;
|
|
75
78
|
}
|
|
76
79
|
|
|
77
80
|
async function getProof({
|
|
@@ -83,6 +86,7 @@ async function getProof({
|
|
|
83
86
|
recipient,
|
|
84
87
|
relayer,
|
|
85
88
|
onProgress,
|
|
89
|
+
provingKeyPath,
|
|
86
90
|
}: GetProofParams): Promise<TransactionResult> {
|
|
87
91
|
// Shuffle inputs and outputs for privacy
|
|
88
92
|
inputs = shuffle([...inputs]);
|
|
@@ -160,7 +164,7 @@ async function getProof({
|
|
|
160
164
|
|
|
161
165
|
// Select circuit based on input count and generate proof
|
|
162
166
|
const circuitName = selectCircuit(inputs.length);
|
|
163
|
-
const proof = await prove(proofInput, circuitName);
|
|
167
|
+
const proof = await prove(proofInput, circuitName, { provingKeyPath });
|
|
164
168
|
|
|
165
169
|
// Build proof arguments for on-chain verification
|
|
166
170
|
const args: ProofArgs = {
|
|
@@ -218,6 +222,7 @@ export async function prepareTransaction({
|
|
|
218
222
|
recipient = 0,
|
|
219
223
|
relayer = 0,
|
|
220
224
|
onProgress,
|
|
225
|
+
provingKeyPath,
|
|
221
226
|
}: PrepareTransactionParams): Promise<TransactionResult> {
|
|
222
227
|
// Validate input/output counts
|
|
223
228
|
if (inputs.length > 16 || outputs.length > 2) {
|
|
@@ -254,6 +259,7 @@ export async function prepareTransaction({
|
|
|
254
259
|
recipient: String(recipient),
|
|
255
260
|
relayer: String(relayer),
|
|
256
261
|
onProgress,
|
|
262
|
+
provingKeyPath,
|
|
257
263
|
});
|
|
258
264
|
|
|
259
265
|
return result;
|
package/src/transfer.ts
CHANGED
|
@@ -140,6 +140,7 @@ export async function buildTransferProof(
|
|
|
140
140
|
senderKeypair,
|
|
141
141
|
pool = 'eth',
|
|
142
142
|
rpcUrl,
|
|
143
|
+
provingKeyPath,
|
|
143
144
|
onProgress,
|
|
144
145
|
} = options;
|
|
145
146
|
|
|
@@ -246,6 +247,7 @@ export async function buildTransferProof(
|
|
|
246
247
|
recipient: '0x0000000000000000000000000000000000000000',
|
|
247
248
|
relayer: '0x0000000000000000000000000000000000000000',
|
|
248
249
|
onProgress,
|
|
250
|
+
provingKeyPath,
|
|
249
251
|
});
|
|
250
252
|
|
|
251
253
|
return {
|
|
@@ -338,9 +340,10 @@ export async function mergeUtxos(options: {
|
|
|
338
340
|
keypair: Keypair;
|
|
339
341
|
pool?: RelayPool;
|
|
340
342
|
rpcUrl?: string;
|
|
343
|
+
provingKeyPath?: import('./prover.js').ProvingKeyPath;
|
|
341
344
|
onProgress?: (stage: string, detail?: string) => void;
|
|
342
345
|
}): Promise<TransferResult> {
|
|
343
|
-
const { amount, keypair, pool = 'eth', rpcUrl, onProgress } = options;
|
|
346
|
+
const { amount, keypair, pool = 'eth', rpcUrl, provingKeyPath, onProgress } = options;
|
|
344
347
|
|
|
345
348
|
const poolConfig = POOL_CONFIG[pool];
|
|
346
349
|
const poolAddress = getPoolAddress(pool);
|
|
@@ -432,6 +435,7 @@ export async function mergeUtxos(options: {
|
|
|
432
435
|
recipient: '0x0000000000000000000000000000000000000000',
|
|
433
436
|
relayer: '0x0000000000000000000000000000000000000000',
|
|
434
437
|
onProgress,
|
|
438
|
+
provingKeyPath,
|
|
435
439
|
});
|
|
436
440
|
|
|
437
441
|
// 6. Submit to relay
|
package/src/types.ts
CHANGED
|
@@ -228,6 +228,13 @@ export interface BuildWithdrawProofOptions {
|
|
|
228
228
|
pool?: RelayPool;
|
|
229
229
|
/** Optional RPC URL */
|
|
230
230
|
rpcUrl?: string;
|
|
231
|
+
/**
|
|
232
|
+
* Optional proving key directory/base URL or resolver.
|
|
233
|
+
*
|
|
234
|
+
* Browsers default to `/keys`, expecting files like
|
|
235
|
+
* `/keys/transaction2.wasm` and `/keys/transaction2.zkey`.
|
|
236
|
+
*/
|
|
237
|
+
provingKeyPath?: import('./prover.js').ProvingKeyPath;
|
|
231
238
|
/** Progress callback */
|
|
232
239
|
onProgress?: (stage: string, detail?: string) => void;
|
|
233
240
|
}
|
|
@@ -246,6 +253,13 @@ export interface BuildTransferProofOptions {
|
|
|
246
253
|
pool?: RelayPool;
|
|
247
254
|
/** Optional RPC URL */
|
|
248
255
|
rpcUrl?: string;
|
|
256
|
+
/**
|
|
257
|
+
* Optional proving key directory/base URL or resolver.
|
|
258
|
+
*
|
|
259
|
+
* Browsers default to `/keys`, expecting files like
|
|
260
|
+
* `/keys/transaction2.wasm` and `/keys/transaction2.zkey`.
|
|
261
|
+
*/
|
|
262
|
+
provingKeyPath?: import('./prover.js').ProvingKeyPath;
|
|
249
263
|
/** Progress callback */
|
|
250
264
|
onProgress?: (stage: string, detail?: string) => void;
|
|
251
265
|
}
|
|
@@ -461,6 +475,13 @@ export interface SubaccountMergeOptions {
|
|
|
461
475
|
rpcUrl?: string;
|
|
462
476
|
/** Optional relay URL */
|
|
463
477
|
relayUrl?: string;
|
|
478
|
+
/**
|
|
479
|
+
* Optional proving key directory/base URL or resolver.
|
|
480
|
+
*
|
|
481
|
+
* Browsers default to `/keys`, expecting files like
|
|
482
|
+
* `/keys/transaction2.wasm` and `/keys/transaction2.zkey`.
|
|
483
|
+
*/
|
|
484
|
+
provingKeyPath?: import('./prover.js').ProvingKeyPath;
|
|
464
485
|
/** Progress callback */
|
|
465
486
|
onProgress?: (stage: string, detail?: string) => void;
|
|
466
487
|
}
|
package/src/utils.ts
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
* Poseidon hash, hex conversion, and random number generation
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import
|
|
6
|
+
import { ethers } from 'ethers';
|
|
7
|
+
import { Buffer } from 'buffer';
|
|
8
|
+
import circomlib from 'circomlib';
|
|
7
9
|
|
|
8
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
9
|
-
const circomlib = require('circomlib');
|
|
10
10
|
const poseidon = circomlib.poseidon;
|
|
11
11
|
|
|
12
12
|
/**
|
|
@@ -39,7 +39,15 @@ export const poseidonHash2 = (a: bigint | string | number, b: bigint | string |
|
|
|
39
39
|
* @returns Random bigint
|
|
40
40
|
*/
|
|
41
41
|
export const randomBN = (nbytes: number = 31): bigint => {
|
|
42
|
-
const
|
|
42
|
+
const cryptoApi = (globalThis as unknown as {
|
|
43
|
+
crypto?: { getRandomValues?: <T extends Uint8Array>(array: T) => T };
|
|
44
|
+
}).crypto;
|
|
45
|
+
|
|
46
|
+
if (!cryptoApi?.getRandomValues) {
|
|
47
|
+
throw new Error('Secure random number generation is unavailable in this runtime');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const bytes = cryptoApi.getRandomValues(new Uint8Array(nbytes));
|
|
43
51
|
let hex = '0x';
|
|
44
52
|
for (let i = 0; i < bytes.length; i++) {
|
|
45
53
|
hex += bytes[i].toString(16).padStart(2, '0');
|
|
@@ -106,7 +114,6 @@ export interface ExtDataInput {
|
|
|
106
114
|
*/
|
|
107
115
|
export function getExtDataHash(extData: ExtDataInput): bigint {
|
|
108
116
|
// Use ethers ABI encoder for Solidity-compatible encoding
|
|
109
|
-
const { ethers } = require('ethers');
|
|
110
117
|
const abi = ethers.AbiCoder.defaultAbiCoder();
|
|
111
118
|
|
|
112
119
|
// Encode the struct exactly as Solidity would
|
package/src/utxo.ts
CHANGED
package/src/withdraw.ts
CHANGED
|
@@ -145,6 +145,7 @@ export async function buildWithdrawProof(
|
|
|
145
145
|
keypair,
|
|
146
146
|
pool = 'eth',
|
|
147
147
|
rpcUrl,
|
|
148
|
+
provingKeyPath,
|
|
148
149
|
onProgress,
|
|
149
150
|
} = options;
|
|
150
151
|
|
|
@@ -231,6 +232,7 @@ export async function buildWithdrawProof(
|
|
|
231
232
|
recipient,
|
|
232
233
|
relayer: '0x0000000000000000000000000000000000000000',
|
|
233
234
|
onProgress,
|
|
235
|
+
provingKeyPath,
|
|
234
236
|
});
|
|
235
237
|
|
|
236
238
|
return {
|