@sip-protocol/sdk 0.2.9 → 0.2.10
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/LICENSE +21 -0
- package/dist/browser.d.mts +100 -2
- package/dist/browser.d.ts +100 -2
- package/dist/browser.js +774 -114
- package/dist/browser.mjs +498 -16
- package/dist/{chunk-KXN6IWL5.mjs → chunk-AV37IZST.mjs} +284 -0
- package/dist/{chunk-VITVG25F.mjs → chunk-XLEPIR2P.mjs} +2 -100
- package/dist/index-BFOKTz2z.d.ts +6062 -0
- package/dist/index-CAhjA4kh.d.mts +6062 -0
- package/dist/index.d.mts +2 -5897
- package/dist/index.d.ts +2 -5897
- package/dist/index.mjs +1 -1
- package/dist/{noir-BHQtFvRk.d.mts → noir-BTyLXLlZ.d.mts} +1 -1
- package/dist/{noir-BHQtFvRk.d.ts → noir-BTyLXLlZ.d.ts} +1 -1
- package/dist/proofs/noir.d.mts +1 -1
- package/dist/proofs/noir.d.ts +1 -1
- package/dist/proofs/noir.js +11 -112
- package/dist/proofs/noir.mjs +10 -13
- package/package.json +16 -16
- package/src/browser.ts +23 -0
- package/src/proofs/browser-utils.ts +389 -0
- package/src/proofs/browser.ts +246 -19
- package/src/proofs/circuits/funding_proof.json +1 -1
- package/src/proofs/noir.ts +14 -14
- package/src/proofs/worker.ts +426 -0
- package/dist/chunk-4VJHI66K.mjs +0 -12120
- package/dist/chunk-5BAS4D44.mjs +0 -10283
- package/dist/chunk-6WOV2YNG.mjs +0 -10179
- package/dist/chunk-DU7LQDD2.mjs +0 -10148
- package/dist/chunk-MR7HRCRS.mjs +0 -10165
- package/dist/chunk-NDGUWOOZ.mjs +0 -10157
- package/dist/chunk-O4Y2ZUDL.mjs +0 -12721
- package/dist/chunk-UPTISVCY.mjs +0 -10304
- package/dist/chunk-VXSHK7US.mjs +0 -10158
package/dist/browser.mjs
CHANGED
|
@@ -55,6 +55,7 @@ import {
|
|
|
55
55
|
base58ToHex,
|
|
56
56
|
bytesToHex,
|
|
57
57
|
checkEd25519StealthAddress,
|
|
58
|
+
checkMobileWASMCompatibility,
|
|
58
59
|
checkStealthAddress,
|
|
59
60
|
commit,
|
|
60
61
|
commitZero,
|
|
@@ -93,6 +94,8 @@ import {
|
|
|
93
94
|
deserializeIntent,
|
|
94
95
|
deserializePayment,
|
|
95
96
|
detectEthereumWallets,
|
|
97
|
+
detectMobileBrowser,
|
|
98
|
+
detectMobilePlatform,
|
|
96
99
|
detectSolanaWallets,
|
|
97
100
|
ed25519PublicKeyToNearAddress,
|
|
98
101
|
ed25519PublicKeyToSolanaAddress,
|
|
@@ -113,6 +116,7 @@ import {
|
|
|
113
116
|
getActiveOracles,
|
|
114
117
|
getAvailableTransports,
|
|
115
118
|
getBrowserInfo,
|
|
119
|
+
getBrowserVersion,
|
|
116
120
|
getChainNumericId,
|
|
117
121
|
getChainsForStablecoin,
|
|
118
122
|
getCurveForChain,
|
|
@@ -121,6 +125,8 @@ import {
|
|
|
121
125
|
getEthereumProvider,
|
|
122
126
|
getGenerators,
|
|
123
127
|
getIntentSummary,
|
|
128
|
+
getMobileDeviceInfo,
|
|
129
|
+
getOSVersion,
|
|
124
130
|
getPaymentSummary,
|
|
125
131
|
getPaymentTimeRemaining,
|
|
126
132
|
getPrivacyConfig,
|
|
@@ -145,6 +151,7 @@ import {
|
|
|
145
151
|
isPrivateWalletAdapter,
|
|
146
152
|
isStablecoin,
|
|
147
153
|
isStablecoinOnChain,
|
|
154
|
+
isTablet,
|
|
148
155
|
isValidAmount,
|
|
149
156
|
isValidChainId,
|
|
150
157
|
isValidCompressedPublicKey,
|
|
@@ -176,7 +183,10 @@ import {
|
|
|
176
183
|
subtractBlindings,
|
|
177
184
|
subtractCommitments,
|
|
178
185
|
supportsSharedArrayBuffer,
|
|
186
|
+
supportsTouch,
|
|
179
187
|
supportsViewingKey,
|
|
188
|
+
supportsWASMBulkMemory,
|
|
189
|
+
supportsWASMSimd,
|
|
180
190
|
supportsWebBluetooth,
|
|
181
191
|
supportsWebHID,
|
|
182
192
|
supportsWebUSB,
|
|
@@ -199,12 +209,12 @@ import {
|
|
|
199
209
|
walletRegistry,
|
|
200
210
|
withSecureBuffer,
|
|
201
211
|
withSecureBufferSync
|
|
202
|
-
} from "./chunk-
|
|
212
|
+
} from "./chunk-AV37IZST.mjs";
|
|
203
213
|
import {
|
|
204
214
|
fulfillment_proof_default,
|
|
205
215
|
funding_proof_default,
|
|
206
216
|
validity_proof_default
|
|
207
|
-
} from "./chunk-
|
|
217
|
+
} from "./chunk-XLEPIR2P.mjs";
|
|
208
218
|
import {
|
|
209
219
|
CryptoError,
|
|
210
220
|
EncryptionNotImplementedError,
|
|
@@ -230,6 +240,9 @@ var BrowserNoirProvider = class _BrowserNoirProvider {
|
|
|
230
240
|
framework = "noir";
|
|
231
241
|
_isReady = false;
|
|
232
242
|
config;
|
|
243
|
+
// Mobile device info (cached)
|
|
244
|
+
deviceInfo = null;
|
|
245
|
+
wasmCompatibility = null;
|
|
233
246
|
// Circuit instances
|
|
234
247
|
fundingNoir = null;
|
|
235
248
|
fundingBackend = null;
|
|
@@ -241,17 +254,25 @@ var BrowserNoirProvider = class _BrowserNoirProvider {
|
|
|
241
254
|
worker = null;
|
|
242
255
|
workerPending = /* @__PURE__ */ new Map();
|
|
243
256
|
constructor(config = {}) {
|
|
257
|
+
this.deviceInfo = getMobileDeviceInfo();
|
|
258
|
+
const isMobile = this.deviceInfo.isMobile;
|
|
259
|
+
const defaultTimeout = isMobile ? 12e4 : 6e4;
|
|
244
260
|
this.config = {
|
|
245
261
|
useWorker: config.useWorker ?? true,
|
|
246
262
|
verbose: config.verbose ?? false,
|
|
247
263
|
oraclePublicKey: config.oraclePublicKey ?? void 0,
|
|
248
|
-
timeout: config.timeout ??
|
|
264
|
+
timeout: config.timeout ?? defaultTimeout,
|
|
265
|
+
mobileMode: config.mobileMode ?? isMobile,
|
|
266
|
+
forceInitialize: config.forceInitialize ?? false
|
|
249
267
|
};
|
|
250
268
|
if (!isBrowser()) {
|
|
251
269
|
console.warn(
|
|
252
270
|
"[BrowserNoirProvider] Not running in browser environment. Consider using NoirProofProvider for Node.js."
|
|
253
271
|
);
|
|
254
272
|
}
|
|
273
|
+
if (this.config.verbose && this.deviceInfo) {
|
|
274
|
+
console.log("[BrowserNoirProvider] Device info:", this.deviceInfo);
|
|
275
|
+
}
|
|
255
276
|
}
|
|
256
277
|
get isReady() {
|
|
257
278
|
return this._isReady;
|
|
@@ -281,6 +302,67 @@ var BrowserNoirProvider = class _BrowserNoirProvider {
|
|
|
281
302
|
missing
|
|
282
303
|
};
|
|
283
304
|
}
|
|
305
|
+
/**
|
|
306
|
+
* Get detailed mobile device information
|
|
307
|
+
*/
|
|
308
|
+
static getMobileInfo() {
|
|
309
|
+
return getMobileDeviceInfo();
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Check mobile WASM compatibility
|
|
313
|
+
*
|
|
314
|
+
* Returns detailed compatibility information including:
|
|
315
|
+
* - Feature support (WASM, SharedArrayBuffer, Workers, SIMD)
|
|
316
|
+
* - Compatibility score (0-100)
|
|
317
|
+
* - Issues and recommendations
|
|
318
|
+
*
|
|
319
|
+
* @example
|
|
320
|
+
* ```typescript
|
|
321
|
+
* const compat = BrowserNoirProvider.checkMobileCompatibility()
|
|
322
|
+
* if (compat.score < 70) {
|
|
323
|
+
* console.warn('Limited mobile support:', compat.issues)
|
|
324
|
+
* }
|
|
325
|
+
* ```
|
|
326
|
+
*/
|
|
327
|
+
static checkMobileCompatibility() {
|
|
328
|
+
return checkMobileWASMCompatibility();
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Check if the current device is mobile
|
|
332
|
+
*/
|
|
333
|
+
static isMobile() {
|
|
334
|
+
return getMobileDeviceInfo().isMobile;
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Get recommended configuration for the current device
|
|
338
|
+
*
|
|
339
|
+
* Automatically adjusts settings based on device capabilities:
|
|
340
|
+
* - Mobile devices get longer timeouts
|
|
341
|
+
* - Low-memory devices disable workers
|
|
342
|
+
* - Tablets get intermediate settings
|
|
343
|
+
*/
|
|
344
|
+
static getRecommendedConfig() {
|
|
345
|
+
const deviceInfo = getMobileDeviceInfo();
|
|
346
|
+
const compat = checkMobileWASMCompatibility();
|
|
347
|
+
const config = {};
|
|
348
|
+
if (deviceInfo.isMobile) {
|
|
349
|
+
config.timeout = 12e4;
|
|
350
|
+
config.mobileMode = true;
|
|
351
|
+
if (deviceInfo.deviceMemoryGB !== null && deviceInfo.deviceMemoryGB < 2) {
|
|
352
|
+
config.useWorker = false;
|
|
353
|
+
}
|
|
354
|
+
if (deviceInfo.platform === "ios" && deviceInfo.browser === "safari") {
|
|
355
|
+
config.useWorker = compat.sharedArrayBuffer;
|
|
356
|
+
}
|
|
357
|
+
} else if (deviceInfo.isTablet) {
|
|
358
|
+
config.timeout = 9e4;
|
|
359
|
+
config.mobileMode = true;
|
|
360
|
+
}
|
|
361
|
+
if (compat.score < 50) {
|
|
362
|
+
config.forceInitialize = false;
|
|
363
|
+
}
|
|
364
|
+
return config;
|
|
365
|
+
}
|
|
284
366
|
/**
|
|
285
367
|
* Derive secp256k1 public key coordinates from a private key
|
|
286
368
|
*/
|
|
@@ -290,6 +372,18 @@ var BrowserNoirProvider = class _BrowserNoirProvider {
|
|
|
290
372
|
const y = Array.from(uncompressedPubKey.slice(33, 65));
|
|
291
373
|
return { x, y };
|
|
292
374
|
}
|
|
375
|
+
/**
|
|
376
|
+
* Get the cached WASM compatibility info (available after construction)
|
|
377
|
+
*/
|
|
378
|
+
getWASMCompatibility() {
|
|
379
|
+
return this.wasmCompatibility;
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Get the cached device info (available after construction)
|
|
383
|
+
*/
|
|
384
|
+
getDeviceInfo() {
|
|
385
|
+
return this.deviceInfo;
|
|
386
|
+
}
|
|
293
387
|
/**
|
|
294
388
|
* Initialize the browser provider
|
|
295
389
|
*
|
|
@@ -302,8 +396,18 @@ var BrowserNoirProvider = class _BrowserNoirProvider {
|
|
|
302
396
|
if (this._isReady) {
|
|
303
397
|
return;
|
|
304
398
|
}
|
|
399
|
+
this.wasmCompatibility = checkMobileWASMCompatibility();
|
|
400
|
+
if (this.config.verbose) {
|
|
401
|
+
console.log("[BrowserNoirProvider] WASM compatibility:", this.wasmCompatibility);
|
|
402
|
+
}
|
|
403
|
+
if (this.wasmCompatibility.score < 50 && !this.config.forceInitialize) {
|
|
404
|
+
throw new ProofError(
|
|
405
|
+
`Device has poor WASM compatibility (score: ${this.wasmCompatibility.score}). Issues: ${this.wasmCompatibility.issues.join(", ")}. Set forceInitialize: true to override.`,
|
|
406
|
+
"SIP_4004" /* PROOF_PROVIDER_NOT_READY */
|
|
407
|
+
);
|
|
408
|
+
}
|
|
305
409
|
const { supported, missing } = _BrowserNoirProvider.checkBrowserSupport();
|
|
306
|
-
if (!supported) {
|
|
410
|
+
if (!supported && !this.config.forceInitialize) {
|
|
307
411
|
throw new ProofError(
|
|
308
412
|
`Browser missing required features: ${missing.join(", ")}`,
|
|
309
413
|
"SIP_4004" /* PROOF_PROVIDER_NOT_READY */
|
|
@@ -367,8 +471,69 @@ var BrowserNoirProvider = class _BrowserNoirProvider {
|
|
|
367
471
|
* Initialize Web Worker for off-main-thread proof generation
|
|
368
472
|
*/
|
|
369
473
|
async initializeWorker() {
|
|
370
|
-
if (
|
|
371
|
-
|
|
474
|
+
if (!supportsWebWorkers()) {
|
|
475
|
+
if (this.config.verbose) {
|
|
476
|
+
console.log("[BrowserNoirProvider] Web Workers not supported, using main thread");
|
|
477
|
+
}
|
|
478
|
+
return;
|
|
479
|
+
}
|
|
480
|
+
try {
|
|
481
|
+
const workerCode = this.getWorkerCode();
|
|
482
|
+
const blob = new Blob([workerCode], { type: "application/javascript" });
|
|
483
|
+
const workerURL = URL.createObjectURL(blob);
|
|
484
|
+
this.worker = new Worker(workerURL, { type: "module" });
|
|
485
|
+
this.worker.onmessage = (event) => {
|
|
486
|
+
this.handleWorkerMessage(event.data);
|
|
487
|
+
};
|
|
488
|
+
this.worker.onerror = (error) => {
|
|
489
|
+
console.error("[BrowserNoirProvider] Worker error:", error);
|
|
490
|
+
for (const [id, { reject }] of this.workerPending) {
|
|
491
|
+
reject(new Error(`Worker error: ${error.message}`));
|
|
492
|
+
this.workerPending.delete(id);
|
|
493
|
+
}
|
|
494
|
+
this.worker?.terminate();
|
|
495
|
+
this.worker = null;
|
|
496
|
+
};
|
|
497
|
+
URL.revokeObjectURL(workerURL);
|
|
498
|
+
if (this.config.verbose) {
|
|
499
|
+
console.log("[BrowserNoirProvider] Web Worker initialized successfully");
|
|
500
|
+
}
|
|
501
|
+
} catch (error) {
|
|
502
|
+
if (this.config.verbose) {
|
|
503
|
+
console.warn("[BrowserNoirProvider] Failed to initialize worker, using main thread:", error);
|
|
504
|
+
}
|
|
505
|
+
this.worker = null;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* Get inline worker code for bundler compatibility
|
|
510
|
+
*/
|
|
511
|
+
getWorkerCode() {
|
|
512
|
+
return `
|
|
513
|
+
self.onmessage = async function(event) {
|
|
514
|
+
const { id, type } = event.data;
|
|
515
|
+
// Signal that worker received message but proof gen happens on main thread
|
|
516
|
+
self.postMessage({ id, type: 'fallback', message: 'Worker initialized, using main thread for proofs' });
|
|
517
|
+
};
|
|
518
|
+
`;
|
|
519
|
+
}
|
|
520
|
+
/**
|
|
521
|
+
* Handle messages from worker
|
|
522
|
+
*/
|
|
523
|
+
handleWorkerMessage(data) {
|
|
524
|
+
const pending = this.workerPending.get(data.id);
|
|
525
|
+
if (!pending) return;
|
|
526
|
+
switch (data.type) {
|
|
527
|
+
case "success":
|
|
528
|
+
this.workerPending.delete(data.id);
|
|
529
|
+
pending.resolve(data.result);
|
|
530
|
+
break;
|
|
531
|
+
case "error":
|
|
532
|
+
this.workerPending.delete(data.id);
|
|
533
|
+
pending.reject(new Error(data.error));
|
|
534
|
+
break;
|
|
535
|
+
case "fallback":
|
|
536
|
+
break;
|
|
372
537
|
}
|
|
373
538
|
}
|
|
374
539
|
/**
|
|
@@ -390,15 +555,10 @@ var BrowserNoirProvider = class _BrowserNoirProvider {
|
|
|
390
555
|
percent: 10,
|
|
391
556
|
message: "Preparing witness inputs..."
|
|
392
557
|
});
|
|
393
|
-
const
|
|
394
|
-
params.balance,
|
|
395
|
-
params.blindingFactor,
|
|
396
|
-
params.assetId
|
|
397
|
-
);
|
|
558
|
+
const blindingField = this.bytesToField(params.blindingFactor);
|
|
398
559
|
const witnessInputs = {
|
|
399
|
-
commitment_hash: commitmentHash,
|
|
400
560
|
minimum_required: params.minimumRequired.toString(),
|
|
401
|
-
asset_id: this.assetIdToField(params.assetId)
|
|
561
|
+
asset_id: `0x${this.assetIdToField(params.assetId)}`,
|
|
402
562
|
balance: params.balance.toString(),
|
|
403
563
|
blinding: blindingField
|
|
404
564
|
};
|
|
@@ -407,7 +567,7 @@ var BrowserNoirProvider = class _BrowserNoirProvider {
|
|
|
407
567
|
percent: 30,
|
|
408
568
|
message: "Generating witness..."
|
|
409
569
|
});
|
|
410
|
-
const { witness } = await this.fundingNoir.execute(witnessInputs);
|
|
570
|
+
const { witness, returnValue } = await this.fundingNoir.execute(witnessInputs);
|
|
411
571
|
onProgress?.({
|
|
412
572
|
stage: "proving",
|
|
413
573
|
percent: 50,
|
|
@@ -419,10 +579,12 @@ var BrowserNoirProvider = class _BrowserNoirProvider {
|
|
|
419
579
|
percent: 100,
|
|
420
580
|
message: "Proof generated successfully"
|
|
421
581
|
});
|
|
582
|
+
const commitmentHashBytes = returnValue;
|
|
583
|
+
const commitmentHashHex = bytesToHex(new Uint8Array(commitmentHashBytes));
|
|
422
584
|
const publicInputs = [
|
|
423
|
-
`0x${commitmentHash}`,
|
|
424
585
|
`0x${params.minimumRequired.toString(16).padStart(16, "0")}`,
|
|
425
|
-
`0x${this.assetIdToField(params.assetId)}
|
|
586
|
+
`0x${this.assetIdToField(params.assetId)}`,
|
|
587
|
+
`0x${commitmentHashHex}`
|
|
426
588
|
];
|
|
427
589
|
const proof = {
|
|
428
590
|
type: "funding",
|
|
@@ -824,6 +986,314 @@ var BrowserNoirProvider = class _BrowserNoirProvider {
|
|
|
824
986
|
return { x, y };
|
|
825
987
|
}
|
|
826
988
|
};
|
|
989
|
+
|
|
990
|
+
// src/proofs/worker.ts
|
|
991
|
+
function createWorkerBlobURL() {
|
|
992
|
+
const workerCode = `
|
|
993
|
+
// Proof Generation Worker
|
|
994
|
+
// This code runs in a separate thread
|
|
995
|
+
|
|
996
|
+
let fundingNoir = null;
|
|
997
|
+
let fundingBackend = null;
|
|
998
|
+
let validityNoir = null;
|
|
999
|
+
let validityBackend = null;
|
|
1000
|
+
let fulfillmentNoir = null;
|
|
1001
|
+
let fulfillmentBackend = null;
|
|
1002
|
+
let isReady = false;
|
|
1003
|
+
let config = { verbose: false };
|
|
1004
|
+
|
|
1005
|
+
// Helper to send progress updates
|
|
1006
|
+
function sendProgress(id, stage, percent, message) {
|
|
1007
|
+
self.postMessage({
|
|
1008
|
+
id,
|
|
1009
|
+
type: 'progress',
|
|
1010
|
+
progress: { stage, percent, message }
|
|
1011
|
+
});
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
// Helper to send error
|
|
1015
|
+
function sendError(id, error) {
|
|
1016
|
+
self.postMessage({
|
|
1017
|
+
id,
|
|
1018
|
+
type: 'error',
|
|
1019
|
+
error: error.message || String(error)
|
|
1020
|
+
});
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
// Helper to send success
|
|
1024
|
+
function sendSuccess(id, result) {
|
|
1025
|
+
self.postMessage({
|
|
1026
|
+
id,
|
|
1027
|
+
type: 'success',
|
|
1028
|
+
result
|
|
1029
|
+
});
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
// Initialize circuits (called once)
|
|
1033
|
+
async function initialize(id, initConfig) {
|
|
1034
|
+
try {
|
|
1035
|
+
sendProgress(id, 'initializing', 10, 'Loading Noir JS...');
|
|
1036
|
+
|
|
1037
|
+
// Dynamic imports for Noir
|
|
1038
|
+
const { Noir } = await import('@noir-lang/noir_js');
|
|
1039
|
+
const { UltraHonkBackend } = await import('@aztec/bb.js');
|
|
1040
|
+
|
|
1041
|
+
sendProgress(id, 'initializing', 30, 'Loading circuit artifacts...');
|
|
1042
|
+
|
|
1043
|
+
// Load circuit artifacts
|
|
1044
|
+
const [fundingArtifact, validityArtifact, fulfillmentArtifact] = await Promise.all([
|
|
1045
|
+
fetch(new URL('./circuits/funding_proof.json', import.meta.url)).then(r => r.json()),
|
|
1046
|
+
fetch(new URL('./circuits/validity_proof.json', import.meta.url)).then(r => r.json()),
|
|
1047
|
+
fetch(new URL('./circuits/fulfillment_proof.json', import.meta.url)).then(r => r.json()),
|
|
1048
|
+
]);
|
|
1049
|
+
|
|
1050
|
+
sendProgress(id, 'initializing', 50, 'Initializing backends...');
|
|
1051
|
+
|
|
1052
|
+
// Initialize Noir instances
|
|
1053
|
+
fundingNoir = new Noir(fundingArtifact);
|
|
1054
|
+
fundingBackend = new UltraHonkBackend(fundingArtifact.bytecode);
|
|
1055
|
+
|
|
1056
|
+
sendProgress(id, 'initializing', 70, 'Initializing validity circuit...');
|
|
1057
|
+
validityNoir = new Noir(validityArtifact);
|
|
1058
|
+
validityBackend = new UltraHonkBackend(validityArtifact.bytecode);
|
|
1059
|
+
|
|
1060
|
+
sendProgress(id, 'initializing', 90, 'Initializing fulfillment circuit...');
|
|
1061
|
+
fulfillmentNoir = new Noir(fulfillmentArtifact);
|
|
1062
|
+
fulfillmentBackend = new UltraHonkBackend(fulfillmentArtifact.bytecode);
|
|
1063
|
+
|
|
1064
|
+
config = initConfig || { verbose: false };
|
|
1065
|
+
isReady = true;
|
|
1066
|
+
|
|
1067
|
+
sendProgress(id, 'complete', 100, 'Worker initialized');
|
|
1068
|
+
sendSuccess(id, { initialized: true });
|
|
1069
|
+
} catch (error) {
|
|
1070
|
+
sendError(id, error);
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
// Generate funding proof
|
|
1075
|
+
async function generateFundingProof(id, params) {
|
|
1076
|
+
if (!isReady) {
|
|
1077
|
+
sendError(id, new Error('Worker not initialized'));
|
|
1078
|
+
return;
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
try {
|
|
1082
|
+
sendProgress(id, 'witness', 20, 'Preparing witness...');
|
|
1083
|
+
|
|
1084
|
+
// Convert blinding factor to field
|
|
1085
|
+
const blindingField = bytesToField(params.blindingFactor);
|
|
1086
|
+
|
|
1087
|
+
const witnessInputs = {
|
|
1088
|
+
minimum_required: params.minimumRequired.toString(),
|
|
1089
|
+
asset_id: '0x' + assetIdToField(params.assetId),
|
|
1090
|
+
balance: params.balance.toString(),
|
|
1091
|
+
blinding: blindingField,
|
|
1092
|
+
};
|
|
1093
|
+
|
|
1094
|
+
sendProgress(id, 'witness', 40, 'Executing circuit...');
|
|
1095
|
+
const { witness, returnValue } = await fundingNoir.execute(witnessInputs);
|
|
1096
|
+
|
|
1097
|
+
sendProgress(id, 'proving', 60, 'Generating proof...');
|
|
1098
|
+
const proofData = await fundingBackend.generateProof(witness);
|
|
1099
|
+
|
|
1100
|
+
sendProgress(id, 'complete', 100, 'Proof generated');
|
|
1101
|
+
|
|
1102
|
+
// Extract commitment hash from return value
|
|
1103
|
+
const commitmentHashHex = bytesToHex(new Uint8Array(returnValue));
|
|
1104
|
+
|
|
1105
|
+
const publicInputs = [
|
|
1106
|
+
'0x' + params.minimumRequired.toString(16).padStart(16, '0'),
|
|
1107
|
+
'0x' + assetIdToField(params.assetId),
|
|
1108
|
+
'0x' + commitmentHashHex,
|
|
1109
|
+
];
|
|
1110
|
+
|
|
1111
|
+
const proof = {
|
|
1112
|
+
type: 'funding',
|
|
1113
|
+
proof: '0x' + bytesToHex(proofData.proof),
|
|
1114
|
+
publicInputs,
|
|
1115
|
+
};
|
|
1116
|
+
|
|
1117
|
+
sendSuccess(id, { proof, publicInputs });
|
|
1118
|
+
} catch (error) {
|
|
1119
|
+
sendError(id, error);
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
// Helper functions
|
|
1124
|
+
function bytesToField(bytes) {
|
|
1125
|
+
let result = 0n;
|
|
1126
|
+
const len = Math.min(bytes.length, 31);
|
|
1127
|
+
for (let i = 0; i < len; i++) {
|
|
1128
|
+
result = result * 256n + BigInt(bytes[i]);
|
|
1129
|
+
}
|
|
1130
|
+
return result.toString();
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1133
|
+
function assetIdToField(assetId) {
|
|
1134
|
+
if (assetId.startsWith('0x')) {
|
|
1135
|
+
return assetId.slice(2).padStart(64, '0');
|
|
1136
|
+
}
|
|
1137
|
+
const encoder = new TextEncoder();
|
|
1138
|
+
const bytes = encoder.encode(assetId);
|
|
1139
|
+
let result = 0n;
|
|
1140
|
+
for (let i = 0; i < bytes.length && i < 31; i++) {
|
|
1141
|
+
result = result * 256n + BigInt(bytes[i]);
|
|
1142
|
+
}
|
|
1143
|
+
return result.toString(16).padStart(64, '0');
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
function bytesToHex(bytes) {
|
|
1147
|
+
return Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('');
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
// Message handler
|
|
1151
|
+
self.onmessage = async function(event) {
|
|
1152
|
+
const { id, type, params, config: initConfig } = event.data;
|
|
1153
|
+
|
|
1154
|
+
switch (type) {
|
|
1155
|
+
case 'init':
|
|
1156
|
+
await initialize(id, initConfig);
|
|
1157
|
+
break;
|
|
1158
|
+
case 'generateFundingProof':
|
|
1159
|
+
await generateFundingProof(id, params);
|
|
1160
|
+
break;
|
|
1161
|
+
case 'generateValidityProof':
|
|
1162
|
+
// TODO: Implement
|
|
1163
|
+
sendError(id, new Error('Validity proof not yet implemented in worker'));
|
|
1164
|
+
break;
|
|
1165
|
+
case 'generateFulfillmentProof':
|
|
1166
|
+
// TODO: Implement
|
|
1167
|
+
sendError(id, new Error('Fulfillment proof not yet implemented in worker'));
|
|
1168
|
+
break;
|
|
1169
|
+
case 'destroy':
|
|
1170
|
+
// Cleanup
|
|
1171
|
+
fundingNoir = null;
|
|
1172
|
+
fundingBackend = null;
|
|
1173
|
+
validityNoir = null;
|
|
1174
|
+
validityBackend = null;
|
|
1175
|
+
fulfillmentNoir = null;
|
|
1176
|
+
fulfillmentBackend = null;
|
|
1177
|
+
isReady = false;
|
|
1178
|
+
sendSuccess(id, { destroyed: true });
|
|
1179
|
+
break;
|
|
1180
|
+
default:
|
|
1181
|
+
sendError(id, new Error('Unknown message type: ' + type));
|
|
1182
|
+
}
|
|
1183
|
+
};
|
|
1184
|
+
`;
|
|
1185
|
+
const blob = new Blob([workerCode], { type: "application/javascript" });
|
|
1186
|
+
return URL.createObjectURL(blob);
|
|
1187
|
+
}
|
|
1188
|
+
var ProofWorker = class _ProofWorker {
|
|
1189
|
+
worker = null;
|
|
1190
|
+
pendingRequests = /* @__PURE__ */ new Map();
|
|
1191
|
+
_isReady = false;
|
|
1192
|
+
requestCounter = 0;
|
|
1193
|
+
/**
|
|
1194
|
+
* Check if Web Workers are supported
|
|
1195
|
+
*/
|
|
1196
|
+
static isSupported() {
|
|
1197
|
+
return typeof Worker !== "undefined" && typeof Blob !== "undefined";
|
|
1198
|
+
}
|
|
1199
|
+
/**
|
|
1200
|
+
* Check if worker is initialized and ready
|
|
1201
|
+
*/
|
|
1202
|
+
get isReady() {
|
|
1203
|
+
return this._isReady;
|
|
1204
|
+
}
|
|
1205
|
+
/**
|
|
1206
|
+
* Initialize the worker
|
|
1207
|
+
*/
|
|
1208
|
+
async initialize(config) {
|
|
1209
|
+
if (this._isReady) {
|
|
1210
|
+
return;
|
|
1211
|
+
}
|
|
1212
|
+
if (!_ProofWorker.isSupported()) {
|
|
1213
|
+
throw new Error("Web Workers not supported in this environment");
|
|
1214
|
+
}
|
|
1215
|
+
const workerURL = createWorkerBlobURL();
|
|
1216
|
+
this.worker = new Worker(workerURL, { type: "module" });
|
|
1217
|
+
this.worker.onmessage = (event) => {
|
|
1218
|
+
this.handleWorkerMessage(event.data);
|
|
1219
|
+
};
|
|
1220
|
+
this.worker.onerror = (error) => {
|
|
1221
|
+
console.error("[ProofWorker] Worker error:", error);
|
|
1222
|
+
for (const [id, { reject }] of this.pendingRequests) {
|
|
1223
|
+
reject(new Error(`Worker error: ${error.message}`));
|
|
1224
|
+
this.pendingRequests.delete(id);
|
|
1225
|
+
}
|
|
1226
|
+
};
|
|
1227
|
+
await this.sendRequest("init", void 0, config);
|
|
1228
|
+
this._isReady = true;
|
|
1229
|
+
URL.revokeObjectURL(workerURL);
|
|
1230
|
+
}
|
|
1231
|
+
/**
|
|
1232
|
+
* Generate a proof using the worker
|
|
1233
|
+
*/
|
|
1234
|
+
async generateProof(type, params, onProgress) {
|
|
1235
|
+
if (!this._isReady || !this.worker) {
|
|
1236
|
+
throw new Error("Worker not initialized. Call initialize() first.");
|
|
1237
|
+
}
|
|
1238
|
+
const messageType = type === "funding" ? "generateFundingProof" : type === "validity" ? "generateValidityProof" : "generateFulfillmentProof";
|
|
1239
|
+
return this.sendRequest(messageType, params, void 0, onProgress);
|
|
1240
|
+
}
|
|
1241
|
+
/**
|
|
1242
|
+
* Destroy the worker and free resources
|
|
1243
|
+
*/
|
|
1244
|
+
async destroy() {
|
|
1245
|
+
if (this.worker) {
|
|
1246
|
+
try {
|
|
1247
|
+
await this.sendRequest("destroy");
|
|
1248
|
+
} catch {
|
|
1249
|
+
}
|
|
1250
|
+
this.worker.terminate();
|
|
1251
|
+
this.worker = null;
|
|
1252
|
+
}
|
|
1253
|
+
this._isReady = false;
|
|
1254
|
+
this.pendingRequests.clear();
|
|
1255
|
+
}
|
|
1256
|
+
/**
|
|
1257
|
+
* Send a request to the worker
|
|
1258
|
+
*/
|
|
1259
|
+
sendRequest(type, params, config, onProgress) {
|
|
1260
|
+
return new Promise((resolve, reject) => {
|
|
1261
|
+
if (!this.worker) {
|
|
1262
|
+
reject(new Error("Worker not available"));
|
|
1263
|
+
return;
|
|
1264
|
+
}
|
|
1265
|
+
const id = `req_${++this.requestCounter}_${Date.now()}`;
|
|
1266
|
+
this.pendingRequests.set(id, { resolve, reject, onProgress });
|
|
1267
|
+
const request = { id, type, params, config };
|
|
1268
|
+
this.worker.postMessage(request);
|
|
1269
|
+
});
|
|
1270
|
+
}
|
|
1271
|
+
/**
|
|
1272
|
+
* Handle messages from the worker
|
|
1273
|
+
*/
|
|
1274
|
+
handleWorkerMessage(response) {
|
|
1275
|
+
const pending = this.pendingRequests.get(response.id);
|
|
1276
|
+
if (!pending) {
|
|
1277
|
+
console.warn("[ProofWorker] Received response for unknown request:", response.id);
|
|
1278
|
+
return;
|
|
1279
|
+
}
|
|
1280
|
+
switch (response.type) {
|
|
1281
|
+
case "success":
|
|
1282
|
+
this.pendingRequests.delete(response.id);
|
|
1283
|
+
pending.resolve(response.result);
|
|
1284
|
+
break;
|
|
1285
|
+
case "error":
|
|
1286
|
+
this.pendingRequests.delete(response.id);
|
|
1287
|
+
pending.reject(new Error(response.error));
|
|
1288
|
+
break;
|
|
1289
|
+
case "progress":
|
|
1290
|
+
if (pending.onProgress && response.progress) {
|
|
1291
|
+
pending.onProgress(response.progress);
|
|
1292
|
+
}
|
|
1293
|
+
break;
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
};
|
|
827
1297
|
export {
|
|
828
1298
|
ATTESTATION_VERSION,
|
|
829
1299
|
BaseWalletAdapter,
|
|
@@ -866,6 +1336,7 @@ export {
|
|
|
866
1336
|
ProofError,
|
|
867
1337
|
ProofGenerationError,
|
|
868
1338
|
ProofNotImplementedError,
|
|
1339
|
+
ProofWorker,
|
|
869
1340
|
ProposalStatus,
|
|
870
1341
|
ReportStatus,
|
|
871
1342
|
SIP,
|
|
@@ -893,6 +1364,7 @@ export {
|
|
|
893
1364
|
bytesToHex as browserBytesToHex,
|
|
894
1365
|
hexToBytes as browserHexToBytes,
|
|
895
1366
|
checkEd25519StealthAddress,
|
|
1367
|
+
checkMobileWASMCompatibility,
|
|
896
1368
|
checkStealthAddress,
|
|
897
1369
|
commit,
|
|
898
1370
|
commitZero,
|
|
@@ -917,6 +1389,7 @@ export {
|
|
|
917
1389
|
createSolanaAdapter,
|
|
918
1390
|
createTrezorAdapter,
|
|
919
1391
|
createWalletFactory,
|
|
1392
|
+
createWorkerBlobURL,
|
|
920
1393
|
createZcashClient,
|
|
921
1394
|
createZcashShieldedService,
|
|
922
1395
|
createZcashSwapService,
|
|
@@ -931,6 +1404,8 @@ export {
|
|
|
931
1404
|
deserializeIntent,
|
|
932
1405
|
deserializePayment,
|
|
933
1406
|
detectEthereumWallets,
|
|
1407
|
+
detectMobileBrowser,
|
|
1408
|
+
detectMobilePlatform,
|
|
934
1409
|
detectSolanaWallets,
|
|
935
1410
|
ed25519PublicKeyToNearAddress,
|
|
936
1411
|
ed25519PublicKeyToSolanaAddress,
|
|
@@ -951,6 +1426,7 @@ export {
|
|
|
951
1426
|
getActiveOracles,
|
|
952
1427
|
getAvailableTransports,
|
|
953
1428
|
getBrowserInfo,
|
|
1429
|
+
getBrowserVersion,
|
|
954
1430
|
getChainNumericId,
|
|
955
1431
|
getChainsForStablecoin,
|
|
956
1432
|
getCurveForChain,
|
|
@@ -960,6 +1436,8 @@ export {
|
|
|
960
1436
|
getEthereumProvider,
|
|
961
1437
|
getGenerators,
|
|
962
1438
|
getIntentSummary,
|
|
1439
|
+
getMobileDeviceInfo,
|
|
1440
|
+
getOSVersion,
|
|
963
1441
|
getPaymentSummary,
|
|
964
1442
|
getPaymentTimeRemaining,
|
|
965
1443
|
getPrivacyConfig,
|
|
@@ -985,6 +1463,7 @@ export {
|
|
|
985
1463
|
isSIPError,
|
|
986
1464
|
isStablecoin,
|
|
987
1465
|
isStablecoinOnChain,
|
|
1466
|
+
isTablet,
|
|
988
1467
|
isValidAmount,
|
|
989
1468
|
isValidChainId,
|
|
990
1469
|
isValidCompressedPublicKey,
|
|
@@ -1016,7 +1495,10 @@ export {
|
|
|
1016
1495
|
subtractBlindings,
|
|
1017
1496
|
subtractCommitments,
|
|
1018
1497
|
supportsSharedArrayBuffer,
|
|
1498
|
+
supportsTouch,
|
|
1019
1499
|
supportsViewingKey,
|
|
1500
|
+
supportsWASMBulkMemory,
|
|
1501
|
+
supportsWASMSimd,
|
|
1020
1502
|
supportsWebBluetooth,
|
|
1021
1503
|
supportsWebHID,
|
|
1022
1504
|
supportsWebUSB,
|