@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/README.md
CHANGED
|
@@ -288,6 +288,7 @@ Commands print human-readable success output by default. Errors are standardized
|
|
|
288
288
|
The CLI is the main entrypoint for most users. If you are integrating Veil programmatically, use the dedicated SDK guide:
|
|
289
289
|
|
|
290
290
|
- [SDK Quick Start and API Reference](./SDK.md)
|
|
291
|
+
- [Browser proof generation](./SDK.md#browser-proof-generation)
|
|
291
292
|
- [AI agent and signer integration notes](./SDK.md#for-ai-agents)
|
|
292
293
|
|
|
293
294
|
## Deposit Flow
|
package/SDK.md
CHANGED
|
@@ -182,6 +182,51 @@ const mergeResult = await mergeUtxos({
|
|
|
182
182
|
});
|
|
183
183
|
```
|
|
184
184
|
|
|
185
|
+
### Browser Proof Generation
|
|
186
|
+
|
|
187
|
+
`withdraw()`, `transfer()`, `mergeUtxos()`, `mergeSubaccount()`, `buildWithdrawProof()`,
|
|
188
|
+
`buildTransferProof()`, and `prepareTransaction()` can generate proofs in browser
|
|
189
|
+
runtimes.
|
|
190
|
+
|
|
191
|
+
In Node, the SDK uses the packaged `keys/` directory by default. In browsers,
|
|
192
|
+
the SDK defaults to same-origin hosted proving keys:
|
|
193
|
+
|
|
194
|
+
```text
|
|
195
|
+
/keys/transaction2.wasm
|
|
196
|
+
/keys/transaction2.zkey
|
|
197
|
+
/keys/transaction16.wasm
|
|
198
|
+
/keys/transaction16.zkey
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
For most web apps, copy the SDK `keys/` files into your app's public assets
|
|
202
|
+
directory. For example, in Next.js/Vite, serving them from `public/keys` makes
|
|
203
|
+
the default path work.
|
|
204
|
+
|
|
205
|
+
If you host keys elsewhere, pass `provingKeyPath`:
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
await withdraw({
|
|
209
|
+
amount: '0.05',
|
|
210
|
+
recipient: '0xRecipientAddress',
|
|
211
|
+
keypair,
|
|
212
|
+
provingKeyPath: 'https://cdn.example.com/veil-keys',
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
await transfer({
|
|
216
|
+
amount: '0.02',
|
|
217
|
+
recipientAddress: '0xRecipientAddress',
|
|
218
|
+
senderKeypair: keypair,
|
|
219
|
+
provingKeyPath: (circuitName) => `/static/zk/${circuitName}`,
|
|
220
|
+
});
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
`provingKeyPath` may be a directory/base URL (`/keys`) or a resolver returning
|
|
224
|
+
the circuit base path without the `.wasm` / `.zkey` extension.
|
|
225
|
+
|
|
226
|
+
This removes Node `fs` key lookup from the browser proof path. Some bundlers
|
|
227
|
+
may still require standard Node-core polyfills for existing legacy dependencies
|
|
228
|
+
such as `circomlib`, `eth-sig-util`, and `fixed-merkle-tree`.
|
|
229
|
+
|
|
185
230
|
### Balance Queries
|
|
186
231
|
|
|
187
232
|
Balance functions accept an optional `pool` parameter (`'eth'` | `'usdc'`), defaulting to `'eth'`.
|
package/dist/cli/index.cjs
CHANGED
|
@@ -8,35 +8,18 @@ var readline = require('readline');
|
|
|
8
8
|
var fs = require('fs');
|
|
9
9
|
var path = require('path');
|
|
10
10
|
var ethers = require('ethers');
|
|
11
|
-
var
|
|
11
|
+
var buffer = require('buffer');
|
|
12
|
+
var ethSigUtil = require('eth-sig-util');
|
|
13
|
+
var circomlib = require('circomlib');
|
|
12
14
|
var MerkleTree = require('fixed-merkle-tree-legacy');
|
|
13
15
|
var snarkjs = require('snarkjs');
|
|
14
|
-
var
|
|
16
|
+
var ffjavascript = require('ffjavascript');
|
|
15
17
|
|
|
16
18
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
17
19
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
var n = Object.create(null);
|
|
22
|
-
if (e) {
|
|
23
|
-
Object.keys(e).forEach(function (k) {
|
|
24
|
-
if (k !== 'default') {
|
|
25
|
-
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
26
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
27
|
-
enumerable: true,
|
|
28
|
-
get: function () { return e[k]; }
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
n.default = e;
|
|
34
|
-
return Object.freeze(n);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
var fs__namespace = /*#__PURE__*/_interopNamespace(fs);
|
|
38
|
-
var path__namespace = /*#__PURE__*/_interopNamespace(path);
|
|
39
|
-
var crypto__namespace = /*#__PURE__*/_interopNamespace(crypto);
|
|
21
|
+
var ethSigUtil__default = /*#__PURE__*/_interopDefault(ethSigUtil);
|
|
22
|
+
var circomlib__default = /*#__PURE__*/_interopDefault(circomlib);
|
|
40
23
|
var MerkleTree__default = /*#__PURE__*/_interopDefault(MerkleTree);
|
|
41
24
|
|
|
42
25
|
var __create = Object.create;
|
|
@@ -1234,8 +1217,8 @@ var require_command = __commonJS({
|
|
|
1234
1217
|
"node_modules/commander/lib/command.js"(exports$1) {
|
|
1235
1218
|
var EventEmitter = __require("events").EventEmitter;
|
|
1236
1219
|
var childProcess = __require("child_process");
|
|
1237
|
-
var
|
|
1238
|
-
var
|
|
1220
|
+
var path = __require("path");
|
|
1221
|
+
var fs = __require("fs");
|
|
1239
1222
|
var process2 = __require("process");
|
|
1240
1223
|
var { Argument: Argument2, humanReadableArgName } = require_argument();
|
|
1241
1224
|
var { CommanderError: CommanderError2 } = require_error();
|
|
@@ -2228,7 +2211,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2228
2211
|
* @param {string} subcommandName
|
|
2229
2212
|
*/
|
|
2230
2213
|
_checkForMissingExecutable(executableFile, executableDir, subcommandName) {
|
|
2231
|
-
if (
|
|
2214
|
+
if (fs.existsSync(executableFile)) return;
|
|
2232
2215
|
const executableDirMessage = executableDir ? `searched for local subcommand relative to directory '${executableDir}'` : "no directory for search for local subcommand, use .executableDir() to supply a custom directory";
|
|
2233
2216
|
const executableMissing = `'${executableFile}' does not exist
|
|
2234
2217
|
- if '${subcommandName}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead
|
|
@@ -2246,11 +2229,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2246
2229
|
let launchWithNode = false;
|
|
2247
2230
|
const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
2248
2231
|
function findFile(baseDir, baseName) {
|
|
2249
|
-
const localBin =
|
|
2250
|
-
if (
|
|
2251
|
-
if (sourceExt.includes(
|
|
2232
|
+
const localBin = path.resolve(baseDir, baseName);
|
|
2233
|
+
if (fs.existsSync(localBin)) return localBin;
|
|
2234
|
+
if (sourceExt.includes(path.extname(baseName))) return void 0;
|
|
2252
2235
|
const foundExt = sourceExt.find(
|
|
2253
|
-
(ext) =>
|
|
2236
|
+
(ext) => fs.existsSync(`${localBin}${ext}`)
|
|
2254
2237
|
);
|
|
2255
2238
|
if (foundExt) return `${localBin}${foundExt}`;
|
|
2256
2239
|
return void 0;
|
|
@@ -2262,21 +2245,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2262
2245
|
if (this._scriptPath) {
|
|
2263
2246
|
let resolvedScriptPath;
|
|
2264
2247
|
try {
|
|
2265
|
-
resolvedScriptPath =
|
|
2248
|
+
resolvedScriptPath = fs.realpathSync(this._scriptPath);
|
|
2266
2249
|
} catch {
|
|
2267
2250
|
resolvedScriptPath = this._scriptPath;
|
|
2268
2251
|
}
|
|
2269
|
-
executableDir =
|
|
2270
|
-
|
|
2252
|
+
executableDir = path.resolve(
|
|
2253
|
+
path.dirname(resolvedScriptPath),
|
|
2271
2254
|
executableDir
|
|
2272
2255
|
);
|
|
2273
2256
|
}
|
|
2274
2257
|
if (executableDir) {
|
|
2275
2258
|
let localFile = findFile(executableDir, executableFile);
|
|
2276
2259
|
if (!localFile && !subcommand._executableFile && this._scriptPath) {
|
|
2277
|
-
const legacyName =
|
|
2260
|
+
const legacyName = path.basename(
|
|
2278
2261
|
this._scriptPath,
|
|
2279
|
-
|
|
2262
|
+
path.extname(this._scriptPath)
|
|
2280
2263
|
);
|
|
2281
2264
|
if (legacyName !== this._name) {
|
|
2282
2265
|
localFile = findFile(
|
|
@@ -2287,7 +2270,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2287
2270
|
}
|
|
2288
2271
|
executableFile = localFile || executableFile;
|
|
2289
2272
|
}
|
|
2290
|
-
launchWithNode = sourceExt.includes(
|
|
2273
|
+
launchWithNode = sourceExt.includes(path.extname(executableFile));
|
|
2291
2274
|
let proc;
|
|
2292
2275
|
if (process2.platform !== "win32") {
|
|
2293
2276
|
if (launchWithNode) {
|
|
@@ -3202,7 +3185,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
3202
3185
|
* @return {Command}
|
|
3203
3186
|
*/
|
|
3204
3187
|
nameFromFilename(filename) {
|
|
3205
|
-
this._name =
|
|
3188
|
+
this._name = path.basename(filename, path.extname(filename));
|
|
3206
3189
|
return this;
|
|
3207
3190
|
}
|
|
3208
3191
|
/**
|
|
@@ -3216,9 +3199,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
3216
3199
|
* @param {string} [path]
|
|
3217
3200
|
* @return {(string|null|Command)}
|
|
3218
3201
|
*/
|
|
3219
|
-
executableDir(
|
|
3220
|
-
if (
|
|
3221
|
-
this._executableDir =
|
|
3202
|
+
executableDir(path2) {
|
|
3203
|
+
if (path2 === void 0) return this._executableDir;
|
|
3204
|
+
this._executableDir = path2;
|
|
3222
3205
|
return this;
|
|
3223
3206
|
}
|
|
3224
3207
|
/**
|
|
@@ -3567,10 +3550,10 @@ var require_package = __commonJS({
|
|
|
3567
3550
|
// node_modules/dotenv/lib/main.js
|
|
3568
3551
|
var require_main = __commonJS({
|
|
3569
3552
|
"node_modules/dotenv/lib/main.js"(exports$1, module) {
|
|
3570
|
-
var
|
|
3571
|
-
var
|
|
3553
|
+
var fs = __require("fs");
|
|
3554
|
+
var path = __require("path");
|
|
3572
3555
|
var os = __require("os");
|
|
3573
|
-
var
|
|
3556
|
+
var crypto = __require("crypto");
|
|
3574
3557
|
var packageJson = require_package();
|
|
3575
3558
|
var version = packageJson.version;
|
|
3576
3559
|
var TIPS = [
|
|
@@ -3709,7 +3692,7 @@ var require_main = __commonJS({
|
|
|
3709
3692
|
if (options && options.path && options.path.length > 0) {
|
|
3710
3693
|
if (Array.isArray(options.path)) {
|
|
3711
3694
|
for (const filepath of options.path) {
|
|
3712
|
-
if (
|
|
3695
|
+
if (fs.existsSync(filepath)) {
|
|
3713
3696
|
possibleVaultPath = filepath.endsWith(".vault") ? filepath : `${filepath}.vault`;
|
|
3714
3697
|
}
|
|
3715
3698
|
}
|
|
@@ -3717,15 +3700,15 @@ var require_main = __commonJS({
|
|
|
3717
3700
|
possibleVaultPath = options.path.endsWith(".vault") ? options.path : `${options.path}.vault`;
|
|
3718
3701
|
}
|
|
3719
3702
|
} else {
|
|
3720
|
-
possibleVaultPath =
|
|
3703
|
+
possibleVaultPath = path.resolve(process.cwd(), ".env.vault");
|
|
3721
3704
|
}
|
|
3722
|
-
if (
|
|
3705
|
+
if (fs.existsSync(possibleVaultPath)) {
|
|
3723
3706
|
return possibleVaultPath;
|
|
3724
3707
|
}
|
|
3725
3708
|
return null;
|
|
3726
3709
|
}
|
|
3727
3710
|
function _resolveHome(envPath) {
|
|
3728
|
-
return envPath[0] === "~" ?
|
|
3711
|
+
return envPath[0] === "~" ? path.join(os.homedir(), envPath.slice(1)) : envPath;
|
|
3729
3712
|
}
|
|
3730
3713
|
function _configVault(options) {
|
|
3731
3714
|
const debug = parseBoolean(process.env.DOTENV_CONFIG_DEBUG || options && options.debug);
|
|
@@ -3742,7 +3725,7 @@ var require_main = __commonJS({
|
|
|
3742
3725
|
return { parsed };
|
|
3743
3726
|
}
|
|
3744
3727
|
function configDotenv(options) {
|
|
3745
|
-
const dotenvPath =
|
|
3728
|
+
const dotenvPath = path.resolve(process.cwd(), ".env");
|
|
3746
3729
|
let encoding = "utf8";
|
|
3747
3730
|
let processEnv = process.env;
|
|
3748
3731
|
if (options && options.processEnv != null) {
|
|
@@ -3770,13 +3753,13 @@ var require_main = __commonJS({
|
|
|
3770
3753
|
}
|
|
3771
3754
|
let lastError;
|
|
3772
3755
|
const parsedAll = {};
|
|
3773
|
-
for (const
|
|
3756
|
+
for (const path2 of optionPaths) {
|
|
3774
3757
|
try {
|
|
3775
|
-
const parsed = DotenvModule.parse(
|
|
3758
|
+
const parsed = DotenvModule.parse(fs.readFileSync(path2, { encoding }));
|
|
3776
3759
|
DotenvModule.populate(parsedAll, parsed, options);
|
|
3777
3760
|
} catch (e) {
|
|
3778
3761
|
if (debug) {
|
|
3779
|
-
_debug(`Failed to load ${
|
|
3762
|
+
_debug(`Failed to load ${path2} ${e.message}`);
|
|
3780
3763
|
}
|
|
3781
3764
|
lastError = e;
|
|
3782
3765
|
}
|
|
@@ -3789,7 +3772,7 @@ var require_main = __commonJS({
|
|
|
3789
3772
|
const shortPaths = [];
|
|
3790
3773
|
for (const filePath of optionPaths) {
|
|
3791
3774
|
try {
|
|
3792
|
-
const relative =
|
|
3775
|
+
const relative = path.relative(process.cwd(), filePath);
|
|
3793
3776
|
shortPaths.push(relative);
|
|
3794
3777
|
} catch (e) {
|
|
3795
3778
|
if (debug) {
|
|
@@ -3824,7 +3807,7 @@ var require_main = __commonJS({
|
|
|
3824
3807
|
const authTag = ciphertext.subarray(-16);
|
|
3825
3808
|
ciphertext = ciphertext.subarray(12, -16);
|
|
3826
3809
|
try {
|
|
3827
|
-
const aesgcm =
|
|
3810
|
+
const aesgcm = crypto.createDecipheriv("aes-256-gcm", key, nonce);
|
|
3828
3811
|
aesgcm.setAuthTag(authTag);
|
|
3829
3812
|
return `${aesgcm.update(ciphertext)}${aesgcm.final()}`;
|
|
3830
3813
|
} catch (error) {
|
|
@@ -5107,15 +5090,18 @@ function loadEnv() {
|
|
|
5107
5090
|
} catch {
|
|
5108
5091
|
}
|
|
5109
5092
|
}
|
|
5110
|
-
var
|
|
5111
|
-
var poseidon = circomlib.poseidon;
|
|
5093
|
+
var poseidon = circomlib__default.default.poseidon;
|
|
5112
5094
|
var FIELD_SIZE = BigInt(
|
|
5113
5095
|
"21888242871839275222246405745257275088548364400416034343698204186575808495617"
|
|
5114
5096
|
);
|
|
5115
5097
|
var poseidonHash = (items) => BigInt(poseidon(items).toString());
|
|
5116
5098
|
var poseidonHash2 = (a, b) => poseidonHash([a, b]);
|
|
5117
5099
|
var randomBN = (nbytes = 31) => {
|
|
5118
|
-
const
|
|
5100
|
+
const cryptoApi = globalThis.crypto;
|
|
5101
|
+
if (!cryptoApi?.getRandomValues) {
|
|
5102
|
+
throw new Error("Secure random number generation is unavailable in this runtime");
|
|
5103
|
+
}
|
|
5104
|
+
const bytes = cryptoApi.getRandomValues(new Uint8Array(nbytes));
|
|
5119
5105
|
let hex = "0x";
|
|
5120
5106
|
for (let i = 0; i < bytes.length; i++) {
|
|
5121
5107
|
hex += bytes[i].toString(16).padStart(2, "0");
|
|
@@ -5124,7 +5110,7 @@ var randomBN = (nbytes = 31) => {
|
|
|
5124
5110
|
};
|
|
5125
5111
|
function toFixedHex(number, length = 32) {
|
|
5126
5112
|
let hexValue;
|
|
5127
|
-
if (number instanceof Buffer) {
|
|
5113
|
+
if (number instanceof buffer.Buffer) {
|
|
5128
5114
|
hexValue = number.toString("hex");
|
|
5129
5115
|
} else {
|
|
5130
5116
|
let bigIntValue = BigInt(number);
|
|
@@ -5139,11 +5125,10 @@ function toFixedHex(number, length = 32) {
|
|
|
5139
5125
|
var toBuffer = (value, length) => {
|
|
5140
5126
|
const bigIntValue = BigInt(value);
|
|
5141
5127
|
const hex = bigIntValue.toString(16).padStart(length * 2, "0");
|
|
5142
|
-
return Buffer.from(hex, "hex");
|
|
5128
|
+
return buffer.Buffer.from(hex, "hex");
|
|
5143
5129
|
};
|
|
5144
5130
|
function getExtDataHash(extData) {
|
|
5145
|
-
const
|
|
5146
|
-
const abi = ethers2.AbiCoder.defaultAbiCoder();
|
|
5131
|
+
const abi = ethers.ethers.AbiCoder.defaultAbiCoder();
|
|
5147
5132
|
const encodedData = abi.encode(
|
|
5148
5133
|
["tuple(address,int256,address,uint256,bytes,bytes)"],
|
|
5149
5134
|
[[
|
|
@@ -5155,7 +5140,7 @@ function getExtDataHash(extData) {
|
|
|
5155
5140
|
extData.encryptedOutput2
|
|
5156
5141
|
]]
|
|
5157
5142
|
);
|
|
5158
|
-
const hash =
|
|
5143
|
+
const hash = ethers.ethers.keccak256(encodedData);
|
|
5159
5144
|
return BigInt(hash) % FIELD_SIZE;
|
|
5160
5145
|
}
|
|
5161
5146
|
function shuffle(array) {
|
|
@@ -5171,15 +5156,14 @@ function shuffle(array) {
|
|
|
5171
5156
|
|
|
5172
5157
|
// src/keypair.ts
|
|
5173
5158
|
var VEIL_SIGNED_MESSAGE = "Sign this message to create your Veil Wallet private key. This will be used to decrypt your balances. Ensure you are signing this message on the Veil Cash website.";
|
|
5174
|
-
var ethSigUtil = __require("eth-sig-util");
|
|
5175
5159
|
function packEncryptedMessage(encryptedMessage) {
|
|
5176
|
-
const nonceBuf = Buffer.from(encryptedMessage.nonce, "base64");
|
|
5177
|
-
const ephemPublicKeyBuf = Buffer.from(encryptedMessage.ephemPublicKey, "base64");
|
|
5178
|
-
const ciphertextBuf = Buffer.from(encryptedMessage.ciphertext, "base64");
|
|
5179
|
-
const messageBuff = Buffer.concat([
|
|
5180
|
-
Buffer.alloc(24 - nonceBuf.length),
|
|
5160
|
+
const nonceBuf = buffer.Buffer.from(encryptedMessage.nonce, "base64");
|
|
5161
|
+
const ephemPublicKeyBuf = buffer.Buffer.from(encryptedMessage.ephemPublicKey, "base64");
|
|
5162
|
+
const ciphertextBuf = buffer.Buffer.from(encryptedMessage.ciphertext, "base64");
|
|
5163
|
+
const messageBuff = buffer.Buffer.concat([
|
|
5164
|
+
buffer.Buffer.alloc(24 - nonceBuf.length),
|
|
5181
5165
|
nonceBuf,
|
|
5182
|
-
Buffer.alloc(32 - ephemPublicKeyBuf.length),
|
|
5166
|
+
buffer.Buffer.alloc(32 - ephemPublicKeyBuf.length),
|
|
5183
5167
|
ephemPublicKeyBuf,
|
|
5184
5168
|
ciphertextBuf
|
|
5185
5169
|
]);
|
|
@@ -5189,7 +5173,7 @@ function unpackEncryptedMessage(encryptedMessage) {
|
|
|
5189
5173
|
if (encryptedMessage.slice(0, 2) === "0x") {
|
|
5190
5174
|
encryptedMessage = encryptedMessage.slice(2);
|
|
5191
5175
|
}
|
|
5192
|
-
const messageBuff = Buffer.from(encryptedMessage, "hex");
|
|
5176
|
+
const messageBuff = buffer.Buffer.from(encryptedMessage, "hex");
|
|
5193
5177
|
const nonceBuf = messageBuff.slice(0, 24);
|
|
5194
5178
|
const ephemPublicKeyBuf = messageBuff.slice(24, 56);
|
|
5195
5179
|
const ciphertextBuf = messageBuff.slice(56);
|
|
@@ -5214,7 +5198,7 @@ var Keypair = class _Keypair {
|
|
|
5214
5198
|
constructor(privkey = ethers.ethers.Wallet.createRandom().privateKey) {
|
|
5215
5199
|
this.privkey = privkey;
|
|
5216
5200
|
this.pubkey = poseidonHash([this.privkey]);
|
|
5217
|
-
this.encryptionKey =
|
|
5201
|
+
this.encryptionKey = ethSigUtil__default.default.getEncryptionPublicKey(privkey.slice(2));
|
|
5218
5202
|
}
|
|
5219
5203
|
/**
|
|
5220
5204
|
* Get the deposit key for this keypair
|
|
@@ -5222,7 +5206,7 @@ var Keypair = class _Keypair {
|
|
|
5222
5206
|
* @returns Deposit key as hex string (130 chars with 0x prefix)
|
|
5223
5207
|
*/
|
|
5224
5208
|
toString() {
|
|
5225
|
-
return toFixedHex(this.pubkey) + Buffer.from(this.encryptionKey, "base64").toString("hex");
|
|
5209
|
+
return toFixedHex(this.pubkey) + buffer.Buffer.from(this.encryptionKey, "base64").toString("hex");
|
|
5226
5210
|
}
|
|
5227
5211
|
/**
|
|
5228
5212
|
* Alias for toString() - returns the deposit key
|
|
@@ -5247,7 +5231,7 @@ var Keypair = class _Keypair {
|
|
|
5247
5231
|
return Object.assign(new _Keypair(), {
|
|
5248
5232
|
privkey: null,
|
|
5249
5233
|
pubkey: BigInt("0x" + str.slice(0, 64)),
|
|
5250
|
-
encryptionKey: Buffer.from(str.slice(64, 128), "hex").toString("base64")
|
|
5234
|
+
encryptionKey: buffer.Buffer.from(str.slice(64, 128), "hex").toString("base64")
|
|
5251
5235
|
});
|
|
5252
5236
|
}
|
|
5253
5237
|
/**
|
|
@@ -5332,7 +5316,7 @@ var Keypair = class _Keypair {
|
|
|
5332
5316
|
*/
|
|
5333
5317
|
encrypt(bytes) {
|
|
5334
5318
|
return packEncryptedMessage(
|
|
5335
|
-
|
|
5319
|
+
ethSigUtil__default.default.encrypt(
|
|
5336
5320
|
this.encryptionKey,
|
|
5337
5321
|
{ data: bytes.toString("base64") },
|
|
5338
5322
|
"x25519-xsalsa20-poly1305"
|
|
@@ -5348,8 +5332,8 @@ var Keypair = class _Keypair {
|
|
|
5348
5332
|
if (!this.privkey) {
|
|
5349
5333
|
throw new Error("Cannot decrypt without private key");
|
|
5350
5334
|
}
|
|
5351
|
-
return Buffer.from(
|
|
5352
|
-
|
|
5335
|
+
return buffer.Buffer.from(
|
|
5336
|
+
ethSigUtil__default.default.decrypt(unpackEncryptedMessage(data), this.privkey.slice(2)),
|
|
5353
5337
|
"base64"
|
|
5354
5338
|
);
|
|
5355
5339
|
}
|
|
@@ -5423,10 +5407,10 @@ async function confirm(question) {
|
|
|
5423
5407
|
input: process.stdin,
|
|
5424
5408
|
output: process.stdout
|
|
5425
5409
|
});
|
|
5426
|
-
return new Promise((
|
|
5410
|
+
return new Promise((resolve) => {
|
|
5427
5411
|
rl.question(`${question} (y/n): `, (answer) => {
|
|
5428
5412
|
rl.close();
|
|
5429
|
-
|
|
5413
|
+
resolve(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
|
|
5430
5414
|
});
|
|
5431
5415
|
});
|
|
5432
5416
|
}
|
|
@@ -5792,8 +5776,6 @@ function createRegisterCommand() {
|
|
|
5792
5776
|
});
|
|
5793
5777
|
return register;
|
|
5794
5778
|
}
|
|
5795
|
-
|
|
5796
|
-
// src/utxo.ts
|
|
5797
5779
|
var Utxo = class _Utxo {
|
|
5798
5780
|
amount;
|
|
5799
5781
|
blinding;
|
|
@@ -5844,7 +5826,7 @@ var Utxo = class _Utxo {
|
|
|
5844
5826
|
* @returns Encrypted data as 0x-prefixed hex string
|
|
5845
5827
|
*/
|
|
5846
5828
|
encrypt() {
|
|
5847
|
-
const bytes = Buffer.concat([
|
|
5829
|
+
const bytes = buffer.Buffer.concat([
|
|
5848
5830
|
toBuffer(this.amount, 31),
|
|
5849
5831
|
toBuffer(this.blinding, 31)
|
|
5850
5832
|
]);
|
|
@@ -6533,30 +6515,46 @@ async function buildMerkleTree(commitments) {
|
|
|
6533
6515
|
const tree = new MerkleTree__default.default(MERKLE_TREE_HEIGHT, leaves, { hashFunction });
|
|
6534
6516
|
return tree;
|
|
6535
6517
|
}
|
|
6536
|
-
var
|
|
6537
|
-
|
|
6538
|
-
|
|
6539
|
-
utils = ffjavascript.utils;
|
|
6540
|
-
} catch {
|
|
6541
|
-
console.warn("ffjavascript not found. Proof generation may not work.");
|
|
6518
|
+
var ffUtils = ffjavascript.utils;
|
|
6519
|
+
function isBrowserRuntime() {
|
|
6520
|
+
return !(typeof process !== "undefined" && !!process.versions?.node);
|
|
6542
6521
|
}
|
|
6543
|
-
function
|
|
6522
|
+
function stripTrailingSlash(value) {
|
|
6523
|
+
return value.endsWith("/") ? value.slice(0, -1) : value;
|
|
6524
|
+
}
|
|
6525
|
+
function normalizeCircuitBasePath(provingKeyPath, circuitName) {
|
|
6526
|
+
const resolvedPath = typeof provingKeyPath === "function" ? provingKeyPath(circuitName) : provingKeyPath;
|
|
6527
|
+
const withoutExtension = resolvedPath.replace(/\.(wasm|zkey)$/i, "");
|
|
6528
|
+
if (withoutExtension.endsWith(`/${circuitName}`) || withoutExtension.endsWith(`\\${circuitName}`)) {
|
|
6529
|
+
return withoutExtension;
|
|
6530
|
+
}
|
|
6531
|
+
return `${stripTrailingSlash(withoutExtension)}/${circuitName}`;
|
|
6532
|
+
}
|
|
6533
|
+
function importNodeModule(specifier) {
|
|
6534
|
+
const dynamicImport = new Function("specifier", "return import(specifier)");
|
|
6535
|
+
return dynamicImport(specifier);
|
|
6536
|
+
}
|
|
6537
|
+
async function findNodeKeysDirectory() {
|
|
6538
|
+
const [{ existsSync: existsSync2 }, pathModule, { fileURLToPath }] = await Promise.all([
|
|
6539
|
+
importNodeModule("node:fs"),
|
|
6540
|
+
importNodeModule("node:path"),
|
|
6541
|
+
importNodeModule("node:url")
|
|
6542
|
+
]);
|
|
6543
|
+
const path = pathModule;
|
|
6544
6544
|
const possiblePaths = [
|
|
6545
6545
|
// When running from package (installed via npm)
|
|
6546
|
-
|
|
6547
|
-
path__namespace.resolve(__dirname, "..", "..", "keys"),
|
|
6546
|
+
path.resolve(process.cwd(), "node_modules", "@veil-cash", "sdk", "keys"),
|
|
6548
6547
|
// When running from source
|
|
6549
|
-
|
|
6550
|
-
// ESM module path
|
|
6548
|
+
path.resolve(process.cwd(), "keys")
|
|
6551
6549
|
];
|
|
6552
6550
|
try {
|
|
6553
|
-
const currentFilePath =
|
|
6554
|
-
const currentDir =
|
|
6555
|
-
possiblePaths.unshift(
|
|
6551
|
+
const currentFilePath = fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)));
|
|
6552
|
+
const currentDir = path.dirname(currentFilePath);
|
|
6553
|
+
possiblePaths.unshift(path.resolve(currentDir, "..", "keys"));
|
|
6556
6554
|
} catch {
|
|
6557
6555
|
}
|
|
6558
6556
|
for (const p of possiblePaths) {
|
|
6559
|
-
if (
|
|
6557
|
+
if (existsSync2(p) && existsSync2(path.join(p, "transaction2.wasm"))) {
|
|
6560
6558
|
return p;
|
|
6561
6559
|
}
|
|
6562
6560
|
}
|
|
@@ -6564,26 +6562,48 @@ function findKeysDirectory() {
|
|
|
6564
6562
|
"Circuit keys not found. Expected to find keys/ directory with transaction2.wasm and transaction2.zkey files."
|
|
6565
6563
|
);
|
|
6566
6564
|
}
|
|
6567
|
-
async function
|
|
6568
|
-
if (
|
|
6569
|
-
|
|
6570
|
-
|
|
6571
|
-
|
|
6572
|
-
|
|
6573
|
-
|
|
6574
|
-
|
|
6565
|
+
async function resolveProvingKeyPaths(circuitName, provingKeyPath) {
|
|
6566
|
+
if (provingKeyPath) {
|
|
6567
|
+
const circuitBasePath = normalizeCircuitBasePath(provingKeyPath, circuitName);
|
|
6568
|
+
return {
|
|
6569
|
+
wasmPath: `${circuitBasePath}.wasm`,
|
|
6570
|
+
zkeyPath: `${circuitBasePath}.zkey`
|
|
6571
|
+
};
|
|
6572
|
+
}
|
|
6573
|
+
if (isBrowserRuntime()) {
|
|
6574
|
+
return {
|
|
6575
|
+
wasmPath: `/keys/${circuitName}.wasm`,
|
|
6576
|
+
zkeyPath: `/keys/${circuitName}.zkey`
|
|
6577
|
+
};
|
|
6578
|
+
}
|
|
6579
|
+
const keysDir = await findNodeKeysDirectory();
|
|
6580
|
+
return {
|
|
6581
|
+
wasmPath: `${keysDir}/${circuitName}.wasm`,
|
|
6582
|
+
zkeyPath: `${keysDir}/${circuitName}.zkey`
|
|
6583
|
+
};
|
|
6584
|
+
}
|
|
6585
|
+
async function assertNodeKeyFilesExist(wasmPath, zkeyPath) {
|
|
6586
|
+
if (isBrowserRuntime() || wasmPath.startsWith("http://") || wasmPath.startsWith("https://")) {
|
|
6587
|
+
return;
|
|
6588
|
+
}
|
|
6589
|
+
const { existsSync: existsSync2 } = await importNodeModule("node:fs");
|
|
6590
|
+
if (!existsSync2(wasmPath)) {
|
|
6575
6591
|
throw new Error(`Circuit WASM file not found: ${wasmPath}`);
|
|
6576
6592
|
}
|
|
6577
|
-
if (!
|
|
6593
|
+
if (!existsSync2(zkeyPath)) {
|
|
6578
6594
|
throw new Error(`Circuit zkey file not found: ${zkeyPath}`);
|
|
6579
6595
|
}
|
|
6596
|
+
}
|
|
6597
|
+
async function prove(input, circuitName, options = {}) {
|
|
6598
|
+
const { wasmPath, zkeyPath } = await resolveProvingKeyPaths(circuitName, options.provingKeyPath);
|
|
6599
|
+
await assertNodeKeyFilesExist(wasmPath, zkeyPath);
|
|
6580
6600
|
const result = await snarkjs.groth16.fullProve(
|
|
6581
|
-
|
|
6601
|
+
ffUtils.stringifyBigInts(input),
|
|
6582
6602
|
wasmPath,
|
|
6583
6603
|
zkeyPath,
|
|
6584
6604
|
void 0,
|
|
6585
6605
|
void 0,
|
|
6586
|
-
{ singleThread: true }
|
|
6606
|
+
{ singleThread: options.singleThread ?? true }
|
|
6587
6607
|
);
|
|
6588
6608
|
const proof = result.proof;
|
|
6589
6609
|
return "0x" + toFixedHex(proof.pi_a[0]).slice(2) + toFixedHex(proof.pi_a[1]).slice(2) + toFixedHex(proof.pi_b[0][1]).slice(2) + toFixedHex(proof.pi_b[0][0]).slice(2) + toFixedHex(proof.pi_b[1][1]).slice(2) + toFixedHex(proof.pi_b[1][0]).slice(2) + toFixedHex(proof.pi_c[0]).slice(2) + toFixedHex(proof.pi_c[1]).slice(2);
|
|
@@ -6607,7 +6627,8 @@ async function getProof({
|
|
|
6607
6627
|
fee,
|
|
6608
6628
|
recipient,
|
|
6609
6629
|
relayer,
|
|
6610
|
-
onProgress
|
|
6630
|
+
onProgress,
|
|
6631
|
+
provingKeyPath
|
|
6611
6632
|
}) {
|
|
6612
6633
|
inputs = shuffle([...inputs]);
|
|
6613
6634
|
outputs = shuffle([...outputs]);
|
|
@@ -6667,7 +6688,7 @@ async function getProof({
|
|
|
6667
6688
|
};
|
|
6668
6689
|
onProgress?.("Generating ZK proof...", `${inputs.length} inputs`);
|
|
6669
6690
|
const circuitName = selectCircuit(inputs.length);
|
|
6670
|
-
const proof = await prove(proofInput, circuitName);
|
|
6691
|
+
const proof = await prove(proofInput, circuitName, { provingKeyPath });
|
|
6671
6692
|
const args = {
|
|
6672
6693
|
proof,
|
|
6673
6694
|
root: toFixedHex(proofInput.root),
|
|
@@ -6689,7 +6710,8 @@ async function prepareTransaction({
|
|
|
6689
6710
|
fee = 0,
|
|
6690
6711
|
recipient = 0,
|
|
6691
6712
|
relayer = 0,
|
|
6692
|
-
onProgress
|
|
6713
|
+
onProgress,
|
|
6714
|
+
provingKeyPath
|
|
6693
6715
|
}) {
|
|
6694
6716
|
if (inputs.length > 16 || outputs.length > 2) {
|
|
6695
6717
|
throw new Error("Incorrect inputs/outputs count. Maximum: 16 inputs, 2 outputs.");
|
|
@@ -6711,7 +6733,8 @@ async function prepareTransaction({
|
|
|
6711
6733
|
fee: BigInt(fee),
|
|
6712
6734
|
recipient: String(recipient),
|
|
6713
6735
|
relayer: String(relayer),
|
|
6714
|
-
onProgress
|
|
6736
|
+
onProgress,
|
|
6737
|
+
provingKeyPath
|
|
6715
6738
|
});
|
|
6716
6739
|
return result;
|
|
6717
6740
|
}
|
|
@@ -6861,6 +6884,7 @@ async function buildWithdrawProof(options) {
|
|
|
6861
6884
|
keypair,
|
|
6862
6885
|
pool = "eth",
|
|
6863
6886
|
rpcUrl,
|
|
6887
|
+
provingKeyPath,
|
|
6864
6888
|
onProgress
|
|
6865
6889
|
} = options;
|
|
6866
6890
|
const poolConfig = POOL_CONFIG[pool];
|
|
@@ -6924,7 +6948,8 @@ async function buildWithdrawProof(options) {
|
|
|
6924
6948
|
fee: 0,
|
|
6925
6949
|
recipient,
|
|
6926
6950
|
relayer: "0x0000000000000000000000000000000000000000",
|
|
6927
|
-
onProgress
|
|
6951
|
+
onProgress,
|
|
6952
|
+
provingKeyPath
|
|
6928
6953
|
});
|
|
6929
6954
|
return {
|
|
6930
6955
|
proofArgs: {
|
|
@@ -7085,6 +7110,7 @@ async function buildTransferProof(options) {
|
|
|
7085
7110
|
senderKeypair,
|
|
7086
7111
|
pool = "eth",
|
|
7087
7112
|
rpcUrl,
|
|
7113
|
+
provingKeyPath,
|
|
7088
7114
|
onProgress
|
|
7089
7115
|
} = options;
|
|
7090
7116
|
const poolConfig = POOL_CONFIG[pool];
|
|
@@ -7163,7 +7189,8 @@ async function buildTransferProof(options) {
|
|
|
7163
7189
|
fee: 0,
|
|
7164
7190
|
recipient: "0x0000000000000000000000000000000000000000",
|
|
7165
7191
|
relayer: "0x0000000000000000000000000000000000000000",
|
|
7166
|
-
onProgress
|
|
7192
|
+
onProgress,
|
|
7193
|
+
provingKeyPath
|
|
7167
7194
|
});
|
|
7168
7195
|
return {
|
|
7169
7196
|
proofArgs: {
|
|
@@ -7205,7 +7232,7 @@ async function transfer(options) {
|
|
|
7205
7232
|
};
|
|
7206
7233
|
}
|
|
7207
7234
|
async function mergeUtxos(options) {
|
|
7208
|
-
const { amount, keypair, pool = "eth", rpcUrl, onProgress } = options;
|
|
7235
|
+
const { amount, keypair, pool = "eth", rpcUrl, provingKeyPath, onProgress } = options;
|
|
7209
7236
|
const poolConfig = POOL_CONFIG[pool];
|
|
7210
7237
|
const poolAddress = getPoolAddress(pool);
|
|
7211
7238
|
onProgress?.("Fetching your UTXOs...");
|
|
@@ -7273,7 +7300,8 @@ async function mergeUtxos(options) {
|
|
|
7273
7300
|
fee: 0,
|
|
7274
7301
|
recipient: "0x0000000000000000000000000000000000000000",
|
|
7275
7302
|
relayer: "0x0000000000000000000000000000000000000000",
|
|
7276
|
-
onProgress
|
|
7303
|
+
onProgress,
|
|
7304
|
+
provingKeyPath
|
|
7277
7305
|
});
|
|
7278
7306
|
onProgress?.("Submitting to relay...");
|
|
7279
7307
|
const relayResult = await submitRelay({
|
|
@@ -7964,6 +7992,7 @@ async function mergeSubaccount(options) {
|
|
|
7964
7992
|
pool = "eth",
|
|
7965
7993
|
rpcUrl,
|
|
7966
7994
|
relayUrl,
|
|
7995
|
+
provingKeyPath,
|
|
7967
7996
|
onProgress
|
|
7968
7997
|
} = options;
|
|
7969
7998
|
const normalizedSlot = normalizeSlot(slot);
|
|
@@ -8056,7 +8085,8 @@ async function mergeSubaccount(options) {
|
|
|
8056
8085
|
fee: 0,
|
|
8057
8086
|
recipient: "0x0000000000000000000000000000000000000000",
|
|
8058
8087
|
relayer: "0x0000000000000000000000000000000000000000",
|
|
8059
|
-
onProgress
|
|
8088
|
+
onProgress,
|
|
8089
|
+
provingKeyPath
|
|
8060
8090
|
});
|
|
8061
8091
|
onProgress?.("Submitting to relay...");
|
|
8062
8092
|
const relayResult = await submitRelay({
|