@sip-protocol/sdk 0.2.0 → 0.2.1

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/dist/browser.js CHANGED
@@ -5097,609 +5097,6 @@ function getBrowserInfo() {
5097
5097
  };
5098
5098
  }
5099
5099
 
5100
- // src/proofs/browser.ts
5101
- var import_noir_js2 = require("@noir-lang/noir_js");
5102
- var import_bb2 = require("@aztec/bb.js");
5103
- var import_secp256k14 = require("@noble/curves/secp256k1");
5104
- var BrowserNoirProvider = class _BrowserNoirProvider {
5105
- framework = "noir";
5106
- _isReady = false;
5107
- config;
5108
- // Circuit instances
5109
- fundingNoir = null;
5110
- fundingBackend = null;
5111
- validityNoir = null;
5112
- validityBackend = null;
5113
- fulfillmentNoir = null;
5114
- fulfillmentBackend = null;
5115
- // Worker instance (optional)
5116
- worker = null;
5117
- workerPending = /* @__PURE__ */ new Map();
5118
- constructor(config = {}) {
5119
- this.config = {
5120
- useWorker: config.useWorker ?? true,
5121
- verbose: config.verbose ?? false,
5122
- oraclePublicKey: config.oraclePublicKey ?? void 0,
5123
- timeout: config.timeout ?? 6e4
5124
- };
5125
- if (!isBrowser()) {
5126
- console.warn(
5127
- "[BrowserNoirProvider] Not running in browser environment. Consider using NoirProofProvider for Node.js."
5128
- );
5129
- }
5130
- }
5131
- get isReady() {
5132
- return this._isReady;
5133
- }
5134
- /**
5135
- * Get browser environment info
5136
- */
5137
- static getBrowserInfo() {
5138
- return getBrowserInfo();
5139
- }
5140
- /**
5141
- * Check if browser supports all required features
5142
- */
5143
- static checkBrowserSupport() {
5144
- const missing = [];
5145
- if (!isBrowser()) {
5146
- missing.push("browser environment");
5147
- }
5148
- if (typeof WebAssembly === "undefined") {
5149
- missing.push("WebAssembly");
5150
- }
5151
- if (!supportsSharedArrayBuffer()) {
5152
- missing.push("SharedArrayBuffer (requires COOP/COEP headers)");
5153
- }
5154
- return {
5155
- supported: missing.length === 0,
5156
- missing
5157
- };
5158
- }
5159
- /**
5160
- * Derive secp256k1 public key coordinates from a private key
5161
- */
5162
- static derivePublicKey(privateKey) {
5163
- const uncompressedPubKey = import_secp256k14.secp256k1.getPublicKey(privateKey, false);
5164
- const x = Array.from(uncompressedPubKey.slice(1, 33));
5165
- const y = Array.from(uncompressedPubKey.slice(33, 65));
5166
- return { x, y };
5167
- }
5168
- /**
5169
- * Initialize the browser provider
5170
- *
5171
- * Loads WASM and circuit artifacts. This should be called before any
5172
- * proof generation. Consider showing a loading indicator during init.
5173
- *
5174
- * @param onProgress - Optional progress callback
5175
- */
5176
- async initialize(onProgress) {
5177
- if (this._isReady) {
5178
- return;
5179
- }
5180
- const { supported, missing } = _BrowserNoirProvider.checkBrowserSupport();
5181
- if (!supported) {
5182
- throw new ProofError(
5183
- `Browser missing required features: ${missing.join(", ")}`,
5184
- "SIP_4004" /* PROOF_PROVIDER_NOT_READY */
5185
- );
5186
- }
5187
- try {
5188
- onProgress?.({
5189
- stage: "initializing",
5190
- percent: 0,
5191
- message: "Loading WASM runtime..."
5192
- });
5193
- if (this.config.verbose) {
5194
- console.log("[BrowserNoirProvider] Initializing...");
5195
- console.log("[BrowserNoirProvider] Browser info:", getBrowserInfo());
5196
- }
5197
- const fundingCircuit = funding_proof_default;
5198
- const validityCircuit = validity_proof_default;
5199
- const fulfillmentCircuit = fulfillment_proof_default;
5200
- onProgress?.({
5201
- stage: "initializing",
5202
- percent: 20,
5203
- message: "Creating proof backends..."
5204
- });
5205
- this.fundingBackend = new import_bb2.UltraHonkBackend(fundingCircuit.bytecode);
5206
- this.validityBackend = new import_bb2.UltraHonkBackend(validityCircuit.bytecode);
5207
- this.fulfillmentBackend = new import_bb2.UltraHonkBackend(fulfillmentCircuit.bytecode);
5208
- onProgress?.({
5209
- stage: "initializing",
5210
- percent: 60,
5211
- message: "Initializing Noir circuits..."
5212
- });
5213
- this.fundingNoir = new import_noir_js2.Noir(fundingCircuit);
5214
- this.validityNoir = new import_noir_js2.Noir(validityCircuit);
5215
- this.fulfillmentNoir = new import_noir_js2.Noir(fulfillmentCircuit);
5216
- onProgress?.({
5217
- stage: "initializing",
5218
- percent: 90,
5219
- message: "Setting up worker..."
5220
- });
5221
- if (this.config.useWorker && supportsWebWorkers()) {
5222
- await this.initializeWorker();
5223
- }
5224
- this._isReady = true;
5225
- onProgress?.({
5226
- stage: "complete",
5227
- percent: 100,
5228
- message: "Ready for proof generation"
5229
- });
5230
- if (this.config.verbose) {
5231
- console.log("[BrowserNoirProvider] Initialization complete");
5232
- }
5233
- } catch (error) {
5234
- throw new ProofError(
5235
- `Failed to initialize BrowserNoirProvider: ${error instanceof Error ? error.message : String(error)}`,
5236
- "SIP_4003" /* PROOF_NOT_IMPLEMENTED */,
5237
- { context: { error } }
5238
- );
5239
- }
5240
- }
5241
- /**
5242
- * Initialize Web Worker for off-main-thread proof generation
5243
- */
5244
- async initializeWorker() {
5245
- if (this.config.verbose) {
5246
- console.log("[BrowserNoirProvider] Worker support: using async main-thread");
5247
- }
5248
- }
5249
- /**
5250
- * Generate a Funding Proof
5251
- *
5252
- * Proves: balance >= minimumRequired without revealing balance
5253
- *
5254
- * @param params - Funding proof parameters
5255
- * @param onProgress - Optional progress callback
5256
- */
5257
- async generateFundingProof(params, onProgress) {
5258
- this.ensureReady();
5259
- if (!this.fundingNoir || !this.fundingBackend) {
5260
- throw new ProofGenerationError("funding", "Funding circuit not initialized");
5261
- }
5262
- try {
5263
- onProgress?.({
5264
- stage: "witness",
5265
- percent: 10,
5266
- message: "Preparing witness inputs..."
5267
- });
5268
- const { commitmentHash, blindingField } = await this.computeCommitmentHash(
5269
- params.balance,
5270
- params.blindingFactor,
5271
- params.assetId
5272
- );
5273
- const witnessInputs = {
5274
- commitment_hash: commitmentHash,
5275
- minimum_required: params.minimumRequired.toString(),
5276
- asset_id: this.assetIdToField(params.assetId),
5277
- balance: params.balance.toString(),
5278
- blinding: blindingField
5279
- };
5280
- onProgress?.({
5281
- stage: "witness",
5282
- percent: 30,
5283
- message: "Generating witness..."
5284
- });
5285
- const { witness } = await this.fundingNoir.execute(witnessInputs);
5286
- onProgress?.({
5287
- stage: "proving",
5288
- percent: 50,
5289
- message: "Generating proof (this may take a moment)..."
5290
- });
5291
- const proofData = await this.fundingBackend.generateProof(witness);
5292
- onProgress?.({
5293
- stage: "complete",
5294
- percent: 100,
5295
- message: "Proof generated successfully"
5296
- });
5297
- const publicInputs = [
5298
- `0x${commitmentHash}`,
5299
- `0x${params.minimumRequired.toString(16).padStart(16, "0")}`,
5300
- `0x${this.assetIdToField(params.assetId)}`
5301
- ];
5302
- const proof = {
5303
- type: "funding",
5304
- proof: `0x${bytesToHex7(proofData.proof)}`,
5305
- publicInputs
5306
- };
5307
- return { proof, publicInputs };
5308
- } catch (error) {
5309
- const message = error instanceof Error ? error.message : String(error);
5310
- throw new ProofGenerationError(
5311
- "funding",
5312
- `Failed to generate funding proof: ${message}`,
5313
- error instanceof Error ? error : void 0
5314
- );
5315
- }
5316
- }
5317
- /**
5318
- * Generate a Validity Proof
5319
- *
5320
- * Proves: Intent is authorized by sender without revealing identity
5321
- */
5322
- async generateValidityProof(params, onProgress) {
5323
- this.ensureReady();
5324
- if (!this.validityNoir || !this.validityBackend) {
5325
- throw new ProofGenerationError("validity", "Validity circuit not initialized");
5326
- }
5327
- try {
5328
- onProgress?.({
5329
- stage: "witness",
5330
- percent: 10,
5331
- message: "Preparing validity witness..."
5332
- });
5333
- const intentHashField = this.hexToField(params.intentHash);
5334
- const senderAddressField = this.hexToField(params.senderAddress);
5335
- const senderBlindingField = this.bytesToField(params.senderBlinding);
5336
- const senderSecretField = this.bytesToField(params.senderSecret);
5337
- const nonceField = this.bytesToField(params.nonce);
5338
- const { commitmentX, commitmentY } = await this.computeSenderCommitment(
5339
- senderAddressField,
5340
- senderBlindingField
5341
- );
5342
- const nullifier = await this.computeNullifier(senderSecretField, intentHashField, nonceField);
5343
- const signature = Array.from(params.authorizationSignature);
5344
- const messageHash = this.fieldToBytes32(intentHashField);
5345
- let pubKeyX;
5346
- let pubKeyY;
5347
- if (params.senderPublicKey) {
5348
- pubKeyX = Array.from(params.senderPublicKey.x);
5349
- pubKeyY = Array.from(params.senderPublicKey.y);
5350
- } else {
5351
- const coords = this.getPublicKeyCoordinates(params.senderSecret);
5352
- pubKeyX = coords.x;
5353
- pubKeyY = coords.y;
5354
- }
5355
- const witnessInputs = {
5356
- intent_hash: intentHashField,
5357
- sender_commitment_x: commitmentX,
5358
- sender_commitment_y: commitmentY,
5359
- nullifier,
5360
- timestamp: params.timestamp.toString(),
5361
- expiry: params.expiry.toString(),
5362
- sender_address: senderAddressField,
5363
- sender_blinding: senderBlindingField,
5364
- sender_secret: senderSecretField,
5365
- pub_key_x: pubKeyX,
5366
- pub_key_y: pubKeyY,
5367
- signature,
5368
- message_hash: messageHash,
5369
- nonce: nonceField
5370
- };
5371
- onProgress?.({
5372
- stage: "witness",
5373
- percent: 30,
5374
- message: "Generating witness..."
5375
- });
5376
- const { witness } = await this.validityNoir.execute(witnessInputs);
5377
- onProgress?.({
5378
- stage: "proving",
5379
- percent: 50,
5380
- message: "Generating validity proof..."
5381
- });
5382
- const proofData = await this.validityBackend.generateProof(witness);
5383
- onProgress?.({
5384
- stage: "complete",
5385
- percent: 100,
5386
- message: "Validity proof generated"
5387
- });
5388
- const publicInputs = [
5389
- `0x${intentHashField}`,
5390
- `0x${commitmentX}`,
5391
- `0x${commitmentY}`,
5392
- `0x${nullifier}`,
5393
- `0x${params.timestamp.toString(16).padStart(16, "0")}`,
5394
- `0x${params.expiry.toString(16).padStart(16, "0")}`
5395
- ];
5396
- const proof = {
5397
- type: "validity",
5398
- proof: `0x${bytesToHex7(proofData.proof)}`,
5399
- publicInputs
5400
- };
5401
- return { proof, publicInputs };
5402
- } catch (error) {
5403
- const message = error instanceof Error ? error.message : String(error);
5404
- throw new ProofGenerationError(
5405
- "validity",
5406
- `Failed to generate validity proof: ${message}`,
5407
- error instanceof Error ? error : void 0
5408
- );
5409
- }
5410
- }
5411
- /**
5412
- * Generate a Fulfillment Proof
5413
- *
5414
- * Proves: Solver correctly executed the intent
5415
- */
5416
- async generateFulfillmentProof(params, onProgress) {
5417
- this.ensureReady();
5418
- if (!this.fulfillmentNoir || !this.fulfillmentBackend) {
5419
- throw new ProofGenerationError("fulfillment", "Fulfillment circuit not initialized");
5420
- }
5421
- try {
5422
- onProgress?.({
5423
- stage: "witness",
5424
- percent: 10,
5425
- message: "Preparing fulfillment witness..."
5426
- });
5427
- const intentHashField = this.hexToField(params.intentHash);
5428
- const recipientStealthField = this.hexToField(params.recipientStealth);
5429
- const { commitmentX, commitmentY } = await this.computeOutputCommitment(
5430
- params.outputAmount,
5431
- params.outputBlinding
5432
- );
5433
- const solverSecretField = this.bytesToField(params.solverSecret);
5434
- const solverId = await this.computeSolverId(solverSecretField);
5435
- const outputBlindingField = this.bytesToField(params.outputBlinding);
5436
- const attestation = params.oracleAttestation;
5437
- const attestationRecipientField = this.hexToField(attestation.recipient);
5438
- const attestationTxHashField = this.hexToField(attestation.txHash);
5439
- const oracleSignature = Array.from(attestation.signature);
5440
- const oracleMessageHash = await this.computeOracleMessageHash(
5441
- attestation.recipient,
5442
- attestation.amount,
5443
- attestation.txHash,
5444
- attestation.blockNumber
5445
- );
5446
- const oraclePubKeyX = this.config.oraclePublicKey?.x ?? new Array(32).fill(0);
5447
- const oraclePubKeyY = this.config.oraclePublicKey?.y ?? new Array(32).fill(0);
5448
- const witnessInputs = {
5449
- intent_hash: intentHashField,
5450
- output_commitment_x: commitmentX,
5451
- output_commitment_y: commitmentY,
5452
- recipient_stealth: recipientStealthField,
5453
- min_output_amount: params.minOutputAmount.toString(),
5454
- solver_id: solverId,
5455
- fulfillment_time: params.fulfillmentTime.toString(),
5456
- expiry: params.expiry.toString(),
5457
- output_amount: params.outputAmount.toString(),
5458
- output_blinding: outputBlindingField,
5459
- solver_secret: solverSecretField,
5460
- attestation_recipient: attestationRecipientField,
5461
- attestation_amount: attestation.amount.toString(),
5462
- attestation_tx_hash: attestationTxHashField,
5463
- attestation_block: attestation.blockNumber.toString(),
5464
- oracle_signature: oracleSignature,
5465
- oracle_message_hash: oracleMessageHash,
5466
- oracle_pub_key_x: oraclePubKeyX,
5467
- oracle_pub_key_y: oraclePubKeyY
5468
- };
5469
- onProgress?.({
5470
- stage: "witness",
5471
- percent: 30,
5472
- message: "Generating witness..."
5473
- });
5474
- const { witness } = await this.fulfillmentNoir.execute(witnessInputs);
5475
- onProgress?.({
5476
- stage: "proving",
5477
- percent: 50,
5478
- message: "Generating fulfillment proof..."
5479
- });
5480
- const proofData = await this.fulfillmentBackend.generateProof(witness);
5481
- onProgress?.({
5482
- stage: "complete",
5483
- percent: 100,
5484
- message: "Fulfillment proof generated"
5485
- });
5486
- const publicInputs = [
5487
- `0x${intentHashField}`,
5488
- `0x${commitmentX}`,
5489
- `0x${commitmentY}`,
5490
- `0x${recipientStealthField}`,
5491
- `0x${params.minOutputAmount.toString(16).padStart(16, "0")}`,
5492
- `0x${solverId}`,
5493
- `0x${params.fulfillmentTime.toString(16).padStart(16, "0")}`,
5494
- `0x${params.expiry.toString(16).padStart(16, "0")}`
5495
- ];
5496
- const proof = {
5497
- type: "fulfillment",
5498
- proof: `0x${bytesToHex7(proofData.proof)}`,
5499
- publicInputs
5500
- };
5501
- return { proof, publicInputs };
5502
- } catch (error) {
5503
- const message = error instanceof Error ? error.message : String(error);
5504
- throw new ProofGenerationError(
5505
- "fulfillment",
5506
- `Failed to generate fulfillment proof: ${message}`,
5507
- error instanceof Error ? error : void 0
5508
- );
5509
- }
5510
- }
5511
- /**
5512
- * Verify a proof
5513
- */
5514
- async verifyProof(proof) {
5515
- this.ensureReady();
5516
- let backend = null;
5517
- switch (proof.type) {
5518
- case "funding":
5519
- backend = this.fundingBackend;
5520
- break;
5521
- case "validity":
5522
- backend = this.validityBackend;
5523
- break;
5524
- case "fulfillment":
5525
- backend = this.fulfillmentBackend;
5526
- break;
5527
- default:
5528
- throw new ProofError(`Unknown proof type: ${proof.type}`, "SIP_4003" /* PROOF_NOT_IMPLEMENTED */);
5529
- }
5530
- if (!backend) {
5531
- throw new ProofError(
5532
- `${proof.type} backend not initialized`,
5533
- "SIP_4004" /* PROOF_PROVIDER_NOT_READY */
5534
- );
5535
- }
5536
- try {
5537
- const proofHex = proof.proof.startsWith("0x") ? proof.proof.slice(2) : proof.proof;
5538
- const proofBytes = hexToBytes5(proofHex);
5539
- const isValid = await backend.verifyProof({
5540
- proof: proofBytes,
5541
- publicInputs: proof.publicInputs.map(
5542
- (input) => input.startsWith("0x") ? input.slice(2) : input
5543
- )
5544
- });
5545
- return isValid;
5546
- } catch (error) {
5547
- if (this.config.verbose) {
5548
- console.error("[BrowserNoirProvider] Verification error:", error);
5549
- }
5550
- return false;
5551
- }
5552
- }
5553
- /**
5554
- * Destroy the provider and free resources
5555
- */
5556
- async destroy() {
5557
- if (this.fundingBackend) {
5558
- await this.fundingBackend.destroy();
5559
- this.fundingBackend = null;
5560
- }
5561
- if (this.validityBackend) {
5562
- await this.validityBackend.destroy();
5563
- this.validityBackend = null;
5564
- }
5565
- if (this.fulfillmentBackend) {
5566
- await this.fulfillmentBackend.destroy();
5567
- this.fulfillmentBackend = null;
5568
- }
5569
- if (this.worker) {
5570
- this.worker.terminate();
5571
- this.worker = null;
5572
- }
5573
- this.fundingNoir = null;
5574
- this.validityNoir = null;
5575
- this.fulfillmentNoir = null;
5576
- this._isReady = false;
5577
- }
5578
- // ─── Private Utility Methods ────────────────────────────────────────────────
5579
- ensureReady() {
5580
- if (!this._isReady) {
5581
- throw new ProofError(
5582
- "BrowserNoirProvider not initialized. Call initialize() first.",
5583
- "SIP_4004" /* PROOF_PROVIDER_NOT_READY */
5584
- );
5585
- }
5586
- }
5587
- async computeCommitmentHash(balance, blindingFactor, assetId) {
5588
- const blindingField = this.bytesToField(blindingFactor);
5589
- const { sha256: sha25611 } = await import("@noble/hashes/sha256");
5590
- const { bytesToHex: nobleToHex } = await import("@noble/hashes/utils");
5591
- const preimage = new Uint8Array([
5592
- ...this.bigintToBytes(balance, 8),
5593
- ...blindingFactor.slice(0, 32),
5594
- ...hexToBytes5(this.assetIdToField(assetId))
5595
- ]);
5596
- const hash2 = sha25611(preimage);
5597
- const commitmentHash = nobleToHex(hash2);
5598
- return { commitmentHash, blindingField };
5599
- }
5600
- assetIdToField(assetId) {
5601
- if (assetId.startsWith("0x")) {
5602
- return assetId.slice(2).padStart(64, "0");
5603
- }
5604
- const encoder = new TextEncoder();
5605
- const bytes = encoder.encode(assetId);
5606
- let result = 0n;
5607
- for (let i = 0; i < bytes.length && i < 31; i++) {
5608
- result = result * 256n + BigInt(bytes[i]);
5609
- }
5610
- return result.toString(16).padStart(64, "0");
5611
- }
5612
- bytesToField(bytes) {
5613
- let result = 0n;
5614
- const len = Math.min(bytes.length, 31);
5615
- for (let i = 0; i < len; i++) {
5616
- result = result * 256n + BigInt(bytes[i]);
5617
- }
5618
- return result.toString();
5619
- }
5620
- bigintToBytes(value, length) {
5621
- const bytes = new Uint8Array(length);
5622
- let v = value;
5623
- for (let i = length - 1; i >= 0; i--) {
5624
- bytes[i] = Number(v & 0xffn);
5625
- v = v >> 8n;
5626
- }
5627
- return bytes;
5628
- }
5629
- hexToField(hex) {
5630
- const h = hex.startsWith("0x") ? hex.slice(2) : hex;
5631
- return h.padStart(64, "0");
5632
- }
5633
- fieldToBytes32(field) {
5634
- const hex = field.padStart(64, "0");
5635
- const bytes = [];
5636
- for (let i = 0; i < 32; i++) {
5637
- bytes.push(parseInt(hex.slice(i * 2, i * 2 + 2), 16));
5638
- }
5639
- return bytes;
5640
- }
5641
- async computeSenderCommitment(senderAddressField, senderBlindingField) {
5642
- const { sha256: sha25611 } = await import("@noble/hashes/sha256");
5643
- const { bytesToHex: nobleToHex } = await import("@noble/hashes/utils");
5644
- const addressBytes = hexToBytes5(senderAddressField);
5645
- const blindingBytes = hexToBytes5(senderBlindingField.padStart(64, "0"));
5646
- const preimage = new Uint8Array([...addressBytes, ...blindingBytes]);
5647
- const hash2 = sha25611(preimage);
5648
- const commitmentX = nobleToHex(hash2.slice(0, 16)).padStart(64, "0");
5649
- const commitmentY = nobleToHex(hash2.slice(16, 32)).padStart(64, "0");
5650
- return { commitmentX, commitmentY };
5651
- }
5652
- async computeNullifier(senderSecretField, intentHashField, nonceField) {
5653
- const { sha256: sha25611 } = await import("@noble/hashes/sha256");
5654
- const { bytesToHex: nobleToHex } = await import("@noble/hashes/utils");
5655
- const secretBytes = hexToBytes5(senderSecretField.padStart(64, "0"));
5656
- const intentBytes = hexToBytes5(intentHashField);
5657
- const nonceBytes = hexToBytes5(nonceField.padStart(64, "0"));
5658
- const preimage = new Uint8Array([...secretBytes, ...intentBytes, ...nonceBytes]);
5659
- const hash2 = sha25611(preimage);
5660
- return nobleToHex(hash2);
5661
- }
5662
- async computeOutputCommitment(outputAmount, outputBlinding) {
5663
- const { sha256: sha25611 } = await import("@noble/hashes/sha256");
5664
- const { bytesToHex: nobleToHex } = await import("@noble/hashes/utils");
5665
- const amountBytes = this.bigintToBytes(outputAmount, 8);
5666
- const blindingBytes = outputBlinding.slice(0, 32);
5667
- const preimage = new Uint8Array([...amountBytes, ...blindingBytes]);
5668
- const hash2 = sha25611(preimage);
5669
- const commitmentX = nobleToHex(hash2.slice(0, 16)).padStart(64, "0");
5670
- const commitmentY = nobleToHex(hash2.slice(16, 32)).padStart(64, "0");
5671
- return { commitmentX, commitmentY };
5672
- }
5673
- async computeSolverId(solverSecretField) {
5674
- const { sha256: sha25611 } = await import("@noble/hashes/sha256");
5675
- const { bytesToHex: nobleToHex } = await import("@noble/hashes/utils");
5676
- const secretBytes = hexToBytes5(solverSecretField.padStart(64, "0"));
5677
- const hash2 = sha25611(secretBytes);
5678
- return nobleToHex(hash2);
5679
- }
5680
- async computeOracleMessageHash(recipient, amount, txHash, blockNumber) {
5681
- const { sha256: sha25611 } = await import("@noble/hashes/sha256");
5682
- const recipientBytes = hexToBytes5(this.hexToField(recipient));
5683
- const amountBytes = this.bigintToBytes(amount, 8);
5684
- const txHashBytes = hexToBytes5(this.hexToField(txHash));
5685
- const blockBytes = this.bigintToBytes(blockNumber, 8);
5686
- const preimage = new Uint8Array([
5687
- ...recipientBytes,
5688
- ...amountBytes,
5689
- ...txHashBytes,
5690
- ...blockBytes
5691
- ]);
5692
- const hash2 = sha25611(preimage);
5693
- return Array.from(hash2);
5694
- }
5695
- getPublicKeyCoordinates(privateKey) {
5696
- const uncompressedPubKey = import_secp256k14.secp256k1.getPublicKey(privateKey, false);
5697
- const x = Array.from(uncompressedPubKey.slice(1, 33));
5698
- const y = Array.from(uncompressedPubKey.slice(33, 65));
5699
- return { x, y };
5700
- }
5701
- };
5702
-
5703
5100
  // src/oracle/types.ts
5704
5101
  var ORACLE_DOMAIN = "SIP-ORACLE-ATTESTATION-V1";
5705
5102
  var ATTESTATION_VERSION = 1;
@@ -7653,7 +7050,7 @@ function getPaymentSummary(payment) {
7653
7050
 
7654
7051
  // src/treasury/treasury.ts
7655
7052
  var import_types12 = require("@sip-protocol/types");
7656
- var import_secp256k15 = require("@noble/curves/secp256k1");
7053
+ var import_secp256k14 = require("@noble/curves/secp256k1");
7657
7054
  var import_sha25610 = require("@noble/hashes/sha256");
7658
7055
  var import_utils12 = require("@noble/hashes/utils");
7659
7056
  var DEFAULT_PROPOSAL_TTL = 7 * 24 * 60 * 60;
@@ -8169,7 +7566,7 @@ function signMessage(messageHash, privateKey) {
8169
7566
  const keyHex = privateKey.startsWith("0x") ? privateKey.slice(2) : privateKey;
8170
7567
  const keyBytes = (0, import_utils12.hexToBytes)(keyHex);
8171
7568
  try {
8172
- const signature = import_secp256k15.secp256k1.sign(messageHash, keyBytes);
7569
+ const signature = import_secp256k14.secp256k1.sign(messageHash, keyBytes);
8173
7570
  return `0x${signature.toCompactHex()}`;
8174
7571
  } finally {
8175
7572
  secureWipe(keyBytes);
@@ -8181,7 +7578,7 @@ function verifySignature(messageHash, signature, publicKey) {
8181
7578
  try {
8182
7579
  const sigBytes = (0, import_utils12.hexToBytes)(sigHex);
8183
7580
  const pubKeyBytes = (0, import_utils12.hexToBytes)(pubKeyHex);
8184
- return import_secp256k15.secp256k1.verify(sigBytes, messageHash, pubKeyBytes);
7581
+ return import_secp256k14.secp256k1.verify(sigBytes, messageHash, pubKeyBytes);
8185
7582
  } catch {
8186
7583
  return false;
8187
7584
  }
@@ -12202,31 +11599,298 @@ var TrezorWalletAdapter = class extends BaseWalletAdapter {
12202
11599
  "trezor"
12203
11600
  );
12204
11601
  }
12205
- if (err.message?.includes("not found") || err.message?.includes("No device")) {
12206
- return new HardwareWalletError(
12207
- "Trezor device not found",
12208
- HardwareErrorCode.DEVICE_NOT_FOUND,
12209
- "trezor"
12210
- );
11602
+ if (err.message?.includes("not found") || err.message?.includes("No device")) {
11603
+ return new HardwareWalletError(
11604
+ "Trezor device not found",
11605
+ HardwareErrorCode.DEVICE_NOT_FOUND,
11606
+ "trezor"
11607
+ );
11608
+ }
11609
+ return new HardwareWalletError(
11610
+ err.message ?? "Unknown Trezor error",
11611
+ HardwareErrorCode.TRANSPORT_ERROR,
11612
+ "trezor",
11613
+ error
11614
+ );
11615
+ }
11616
+ };
11617
+ function createTrezorAdapter(config) {
11618
+ return new TrezorWalletAdapter(config);
11619
+ }
11620
+
11621
+ // src/wallet/hardware/mock.ts
11622
+ var import_types29 = require("@sip-protocol/types");
11623
+ var import_utils14 = require("@noble/hashes/utils");
11624
+ var MockLedgerAdapter = class extends BaseWalletAdapter {
11625
+ chain;
11626
+ name = "mock-ledger";
11627
+ config;
11628
+ _derivationPath;
11629
+ _deviceInfo = null;
11630
+ _account = null;
11631
+ mockAccounts = [];
11632
+ constructor(config) {
11633
+ super();
11634
+ this.chain = config.chain;
11635
+ this.config = {
11636
+ model: "nanoX",
11637
+ accountIndex: 0,
11638
+ isLocked: false,
11639
+ signingDelay: 100,
11640
+ shouldReject: false,
11641
+ shouldFailConnect: false,
11642
+ accountCount: 5,
11643
+ ...config
11644
+ };
11645
+ this._derivationPath = config.derivationPath ?? getDerivationPath(config.chain, config.accountIndex ?? 0);
11646
+ this.generateMockAccounts();
11647
+ }
11648
+ /**
11649
+ * Get device information
11650
+ */
11651
+ get deviceInfo() {
11652
+ return this._deviceInfo;
11653
+ }
11654
+ /**
11655
+ * Get current derivation path
11656
+ */
11657
+ get derivationPath() {
11658
+ return this._derivationPath;
11659
+ }
11660
+ /**
11661
+ * Get current account
11662
+ */
11663
+ get account() {
11664
+ return this._account;
11665
+ }
11666
+ /**
11667
+ * Connect to mock Ledger device
11668
+ */
11669
+ async connect() {
11670
+ this._connectionState = "connecting";
11671
+ await this.delay(200);
11672
+ if (this.config.shouldFailConnect) {
11673
+ this._connectionState = "error";
11674
+ throw new HardwareWalletError(
11675
+ "Mock connection failure",
11676
+ HardwareErrorCode.DEVICE_NOT_FOUND,
11677
+ "ledger"
11678
+ );
11679
+ }
11680
+ if (this.config.isLocked) {
11681
+ this._connectionState = "error";
11682
+ throw new HardwareWalletError(
11683
+ "Device is locked. Please enter PIN.",
11684
+ HardwareErrorCode.DEVICE_LOCKED,
11685
+ "ledger"
11686
+ );
11687
+ }
11688
+ this._account = this.mockAccounts[this.config.accountIndex ?? 0];
11689
+ this._deviceInfo = {
11690
+ manufacturer: "ledger",
11691
+ model: this.config.model ?? "Nano X",
11692
+ firmwareVersion: "2.1.0",
11693
+ isLocked: false,
11694
+ currentApp: this.getAppName(),
11695
+ label: "Mock Ledger",
11696
+ deviceId: "mock-ledger-001"
11697
+ };
11698
+ this.setConnected(this._account.address, this._account.publicKey);
11699
+ }
11700
+ /**
11701
+ * Disconnect from mock device
11702
+ */
11703
+ async disconnect() {
11704
+ this._account = null;
11705
+ this._deviceInfo = null;
11706
+ this.setDisconnected();
11707
+ }
11708
+ /**
11709
+ * Sign a message
11710
+ */
11711
+ async signMessage(message) {
11712
+ this.requireConnected();
11713
+ await this.delay(this.config.signingDelay ?? 100);
11714
+ if (this.config.shouldReject) {
11715
+ throw new HardwareWalletError(
11716
+ "User rejected on device",
11717
+ HardwareErrorCode.USER_REJECTED,
11718
+ "ledger"
11719
+ );
11720
+ }
11721
+ const sig = this.generateMockSignature(message);
11722
+ return {
11723
+ signature: sig,
11724
+ publicKey: this._account.publicKey
11725
+ };
11726
+ }
11727
+ /**
11728
+ * Sign a transaction
11729
+ */
11730
+ async signTransaction(tx) {
11731
+ this.requireConnected();
11732
+ await this.delay(this.config.signingDelay ?? 100);
11733
+ if (this.config.shouldReject) {
11734
+ throw new HardwareWalletError(
11735
+ "Transaction rejected on device",
11736
+ HardwareErrorCode.USER_REJECTED,
11737
+ "ledger"
11738
+ );
11739
+ }
11740
+ const sig = this.generateMockSignature(
11741
+ new TextEncoder().encode(JSON.stringify(tx.data))
11742
+ );
11743
+ return {
11744
+ unsigned: tx,
11745
+ signatures: [
11746
+ {
11747
+ signature: sig,
11748
+ publicKey: this._account.publicKey
11749
+ }
11750
+ ],
11751
+ serialized: sig
11752
+ };
11753
+ }
11754
+ /**
11755
+ * Sign and send transaction
11756
+ */
11757
+ async signAndSendTransaction(tx) {
11758
+ const signed = await this.signTransaction(tx);
11759
+ return {
11760
+ txHash: signed.serialized.slice(0, 66),
11761
+ status: "pending"
11762
+ };
11763
+ }
11764
+ /**
11765
+ * Get balance (not supported by hardware wallets)
11766
+ */
11767
+ async getBalance() {
11768
+ throw new WalletError(
11769
+ "Hardware wallets do not track balances",
11770
+ import_types29.WalletErrorCode.UNSUPPORTED_OPERATION
11771
+ );
11772
+ }
11773
+ /**
11774
+ * Get token balance (not supported by hardware wallets)
11775
+ */
11776
+ async getTokenBalance(_asset) {
11777
+ throw new WalletError(
11778
+ "Hardware wallets do not track balances",
11779
+ import_types29.WalletErrorCode.UNSUPPORTED_OPERATION
11780
+ );
11781
+ }
11782
+ /**
11783
+ * Get multiple accounts
11784
+ */
11785
+ async getAccounts(startIndex = 0, count = 5) {
11786
+ this.requireConnected();
11787
+ return this.mockAccounts.slice(startIndex, startIndex + count);
11788
+ }
11789
+ /**
11790
+ * Switch account
11791
+ */
11792
+ async switchAccount(accountIndex) {
11793
+ this.requireConnected();
11794
+ if (accountIndex >= this.mockAccounts.length) {
11795
+ throw new HardwareWalletError(
11796
+ "Account index out of range",
11797
+ HardwareErrorCode.INVALID_PATH,
11798
+ "ledger"
11799
+ );
11800
+ }
11801
+ const previousAddress = this._address;
11802
+ this._account = this.mockAccounts[accountIndex];
11803
+ this._derivationPath = this._account.derivationPath;
11804
+ this.setConnected(this._account.address, this._account.publicKey);
11805
+ if (previousAddress !== this._account.address) {
11806
+ this.emitAccountChanged(previousAddress, this._account.address);
11807
+ }
11808
+ return this._account;
11809
+ }
11810
+ // ─── Test Helpers ───────────────────────────────────────────────────────────
11811
+ /**
11812
+ * Set whether device should reject signing
11813
+ */
11814
+ setShouldReject(shouldReject) {
11815
+ this.config.shouldReject = shouldReject;
11816
+ }
11817
+ /**
11818
+ * Set signing delay
11819
+ */
11820
+ setSigningDelay(delay) {
11821
+ this.config.signingDelay = delay;
11822
+ }
11823
+ /**
11824
+ * Simulate device lock
11825
+ */
11826
+ simulateLock() {
11827
+ if (this._deviceInfo) {
11828
+ this._deviceInfo.isLocked = true;
11829
+ }
11830
+ this.config.isLocked = true;
11831
+ }
11832
+ /**
11833
+ * Simulate device unlock
11834
+ */
11835
+ simulateUnlock() {
11836
+ if (this._deviceInfo) {
11837
+ this._deviceInfo.isLocked = false;
11838
+ }
11839
+ this.config.isLocked = false;
11840
+ }
11841
+ // ─── Private Methods ────────────────────────────────────────────────────────
11842
+ getAppName() {
11843
+ switch (this.chain) {
11844
+ case "ethereum":
11845
+ return "Ethereum";
11846
+ case "solana":
11847
+ return "Solana";
11848
+ default:
11849
+ return "Unknown";
11850
+ }
11851
+ }
11852
+ generateMockAccounts() {
11853
+ const count = this.config.accountCount ?? 5;
11854
+ for (let i = 0; i < count; i++) {
11855
+ const path = getDerivationPath(this.chain, i);
11856
+ const address = this.config.mockAddress && i === 0 ? this.config.mockAddress : this.generateMockAddress(i);
11857
+ const publicKey = this.config.mockPublicKey && i === 0 ? this.config.mockPublicKey : this.generateMockPublicKey(i);
11858
+ this.mockAccounts.push({
11859
+ address,
11860
+ publicKey,
11861
+ derivationPath: path,
11862
+ index: i,
11863
+ chain: this.chain
11864
+ });
11865
+ }
11866
+ }
11867
+ generateMockAddress(index) {
11868
+ const bytes = (0, import_utils14.randomBytes)(20);
11869
+ bytes[0] = index;
11870
+ return `0x${(0, import_utils14.bytesToHex)(bytes)}`;
11871
+ }
11872
+ generateMockPublicKey(index) {
11873
+ const bytes = (0, import_utils14.randomBytes)(33);
11874
+ bytes[0] = 2;
11875
+ bytes[1] = index;
11876
+ return `0x${(0, import_utils14.bytesToHex)(bytes)}`;
11877
+ }
11878
+ generateMockSignature(data) {
11879
+ const sig = new Uint8Array(65);
11880
+ for (let i = 0; i < 32; i++) {
11881
+ sig[i] = (data[i % data.length] ?? 0) ^ i * 7;
11882
+ sig[32 + i] = (data[i % data.length] ?? 0) ^ i * 11;
12211
11883
  }
12212
- return new HardwareWalletError(
12213
- err.message ?? "Unknown Trezor error",
12214
- HardwareErrorCode.TRANSPORT_ERROR,
12215
- "trezor",
12216
- error
12217
- );
11884
+ sig[64] = 27;
11885
+ return `0x${(0, import_utils14.bytesToHex)(sig)}`;
11886
+ }
11887
+ delay(ms) {
11888
+ return new Promise((resolve) => setTimeout(resolve, ms));
12218
11889
  }
12219
11890
  };
12220
- function createTrezorAdapter(config) {
12221
- return new TrezorWalletAdapter(config);
12222
- }
12223
-
12224
- // src/wallet/hardware/mock.ts
12225
- var import_types29 = require("@sip-protocol/types");
12226
- var import_utils14 = require("@noble/hashes/utils");
12227
- var MockLedgerAdapter = class extends BaseWalletAdapter {
11891
+ var MockTrezorAdapter = class extends BaseWalletAdapter {
12228
11892
  chain;
12229
- name = "mock-ledger";
11893
+ name = "mock-trezor";
12230
11894
  config;
12231
11895
  _derivationPath;
12232
11896
  _deviceInfo = null;
@@ -12236,7 +11900,7 @@ var MockLedgerAdapter = class extends BaseWalletAdapter {
12236
11900
  super();
12237
11901
  this.chain = config.chain;
12238
11902
  this.config = {
12239
- model: "nanoX",
11903
+ model: "T",
12240
11904
  accountIndex: 0,
12241
11905
  isLocked: false,
12242
11906
  signingDelay: 100,
@@ -12248,27 +11912,15 @@ var MockLedgerAdapter = class extends BaseWalletAdapter {
12248
11912
  this._derivationPath = config.derivationPath ?? getDerivationPath(config.chain, config.accountIndex ?? 0);
12249
11913
  this.generateMockAccounts();
12250
11914
  }
12251
- /**
12252
- * Get device information
12253
- */
12254
11915
  get deviceInfo() {
12255
11916
  return this._deviceInfo;
12256
11917
  }
12257
- /**
12258
- * Get current derivation path
12259
- */
12260
11918
  get derivationPath() {
12261
11919
  return this._derivationPath;
12262
11920
  }
12263
- /**
12264
- * Get current account
12265
- */
12266
11921
  get account() {
12267
11922
  return this._account;
12268
11923
  }
12269
- /**
12270
- * Connect to mock Ledger device
12271
- */
12272
11924
  async connect() {
12273
11925
  this._connectionState = "connecting";
12274
11926
  await this.delay(200);
@@ -12277,40 +11929,33 @@ var MockLedgerAdapter = class extends BaseWalletAdapter {
12277
11929
  throw new HardwareWalletError(
12278
11930
  "Mock connection failure",
12279
11931
  HardwareErrorCode.DEVICE_NOT_FOUND,
12280
- "ledger"
11932
+ "trezor"
12281
11933
  );
12282
11934
  }
12283
11935
  if (this.config.isLocked) {
12284
11936
  this._connectionState = "error";
12285
11937
  throw new HardwareWalletError(
12286
- "Device is locked. Please enter PIN.",
11938
+ "Device requires PIN",
12287
11939
  HardwareErrorCode.DEVICE_LOCKED,
12288
- "ledger"
11940
+ "trezor"
12289
11941
  );
12290
11942
  }
12291
11943
  this._account = this.mockAccounts[this.config.accountIndex ?? 0];
12292
11944
  this._deviceInfo = {
12293
- manufacturer: "ledger",
12294
- model: this.config.model ?? "Nano X",
12295
- firmwareVersion: "2.1.0",
11945
+ manufacturer: "trezor",
11946
+ model: this.config.model ?? "Model T",
11947
+ firmwareVersion: "2.5.3",
12296
11948
  isLocked: false,
12297
- currentApp: this.getAppName(),
12298
- label: "Mock Ledger",
12299
- deviceId: "mock-ledger-001"
11949
+ label: "Mock Trezor",
11950
+ deviceId: "mock-trezor-001"
12300
11951
  };
12301
11952
  this.setConnected(this._account.address, this._account.publicKey);
12302
11953
  }
12303
- /**
12304
- * Disconnect from mock device
12305
- */
12306
11954
  async disconnect() {
12307
11955
  this._account = null;
12308
11956
  this._deviceInfo = null;
12309
11957
  this.setDisconnected();
12310
11958
  }
12311
- /**
12312
- * Sign a message
12313
- */
12314
11959
  async signMessage(message) {
12315
11960
  this.requireConnected();
12316
11961
  await this.delay(this.config.signingDelay ?? 100);
@@ -12318,7 +11963,7 @@ var MockLedgerAdapter = class extends BaseWalletAdapter {
12318
11963
  throw new HardwareWalletError(
12319
11964
  "User rejected on device",
12320
11965
  HardwareErrorCode.USER_REJECTED,
12321
- "ledger"
11966
+ "trezor"
12322
11967
  );
12323
11968
  }
12324
11969
  const sig = this.generateMockSignature(message);
@@ -12327,9 +11972,6 @@ var MockLedgerAdapter = class extends BaseWalletAdapter {
12327
11972
  publicKey: this._account.publicKey
12328
11973
  };
12329
11974
  }
12330
- /**
12331
- * Sign a transaction
12332
- */
12333
11975
  async signTransaction(tx) {
12334
11976
  this.requireConnected();
12335
11977
  await this.delay(this.config.signingDelay ?? 100);
@@ -12337,7 +11979,7 @@ var MockLedgerAdapter = class extends BaseWalletAdapter {
12337
11979
  throw new HardwareWalletError(
12338
11980
  "Transaction rejected on device",
12339
11981
  HardwareErrorCode.USER_REJECTED,
12340
- "ledger"
11982
+ "trezor"
12341
11983
  );
12342
11984
  }
12343
11985
  const sig = this.generateMockSignature(
@@ -12354,9 +11996,6 @@ var MockLedgerAdapter = class extends BaseWalletAdapter {
12354
11996
  serialized: sig
12355
11997
  };
12356
11998
  }
12357
- /**
12358
- * Sign and send transaction
12359
- */
12360
11999
  async signAndSendTransaction(tx) {
12361
12000
  const signed = await this.signTransaction(tx);
12362
12001
  return {
@@ -12364,348 +12003,709 @@ var MockLedgerAdapter = class extends BaseWalletAdapter {
12364
12003
  status: "pending"
12365
12004
  };
12366
12005
  }
12367
- /**
12368
- * Get balance (not supported by hardware wallets)
12369
- */
12370
12006
  async getBalance() {
12371
12007
  throw new WalletError(
12372
12008
  "Hardware wallets do not track balances",
12373
12009
  import_types29.WalletErrorCode.UNSUPPORTED_OPERATION
12374
12010
  );
12375
12011
  }
12376
- /**
12377
- * Get token balance (not supported by hardware wallets)
12378
- */
12379
12012
  async getTokenBalance(_asset) {
12380
12013
  throw new WalletError(
12381
12014
  "Hardware wallets do not track balances",
12382
12015
  import_types29.WalletErrorCode.UNSUPPORTED_OPERATION
12383
12016
  );
12384
12017
  }
12018
+ async getAccounts(startIndex = 0, count = 5) {
12019
+ this.requireConnected();
12020
+ return this.mockAccounts.slice(startIndex, startIndex + count);
12021
+ }
12022
+ async switchAccount(accountIndex) {
12023
+ this.requireConnected();
12024
+ if (accountIndex >= this.mockAccounts.length) {
12025
+ throw new HardwareWalletError(
12026
+ "Account index out of range",
12027
+ HardwareErrorCode.INVALID_PATH,
12028
+ "trezor"
12029
+ );
12030
+ }
12031
+ const previousAddress = this._address;
12032
+ this._account = this.mockAccounts[accountIndex];
12033
+ this._derivationPath = this._account.derivationPath;
12034
+ this.setConnected(this._account.address, this._account.publicKey);
12035
+ if (previousAddress !== this._account.address) {
12036
+ this.emitAccountChanged(previousAddress, this._account.address);
12037
+ }
12038
+ return this._account;
12039
+ }
12040
+ setShouldReject(shouldReject) {
12041
+ this.config.shouldReject = shouldReject;
12042
+ }
12043
+ setSigningDelay(delay) {
12044
+ this.config.signingDelay = delay;
12045
+ }
12046
+ simulateLock() {
12047
+ if (this._deviceInfo) {
12048
+ this._deviceInfo.isLocked = true;
12049
+ }
12050
+ this.config.isLocked = true;
12051
+ }
12052
+ simulateUnlock() {
12053
+ if (this._deviceInfo) {
12054
+ this._deviceInfo.isLocked = false;
12055
+ }
12056
+ this.config.isLocked = false;
12057
+ }
12058
+ generateMockAccounts() {
12059
+ const count = this.config.accountCount ?? 5;
12060
+ for (let i = 0; i < count; i++) {
12061
+ const path = getDerivationPath(this.chain, i);
12062
+ const address = this.config.mockAddress && i === 0 ? this.config.mockAddress : this.generateMockAddress(i);
12063
+ const publicKey = this.config.mockPublicKey && i === 0 ? this.config.mockPublicKey : this.generateMockPublicKey(i);
12064
+ this.mockAccounts.push({
12065
+ address,
12066
+ publicKey,
12067
+ derivationPath: path,
12068
+ index: i,
12069
+ chain: this.chain
12070
+ });
12071
+ }
12072
+ }
12073
+ generateMockAddress(index) {
12074
+ const bytes = (0, import_utils14.randomBytes)(20);
12075
+ bytes[0] = index + 100;
12076
+ return `0x${(0, import_utils14.bytesToHex)(bytes)}`;
12077
+ }
12078
+ generateMockPublicKey(index) {
12079
+ const bytes = (0, import_utils14.randomBytes)(33);
12080
+ bytes[0] = 3;
12081
+ bytes[1] = index + 100;
12082
+ return `0x${(0, import_utils14.bytesToHex)(bytes)}`;
12083
+ }
12084
+ generateMockSignature(data) {
12085
+ const sig = new Uint8Array(65);
12086
+ for (let i = 0; i < 32; i++) {
12087
+ sig[i] = (data[i % data.length] ?? 0) ^ i * 13;
12088
+ sig[32 + i] = (data[i % data.length] ?? 0) ^ i * 17;
12089
+ }
12090
+ sig[64] = 28;
12091
+ return `0x${(0, import_utils14.bytesToHex)(sig)}`;
12092
+ }
12093
+ delay(ms) {
12094
+ return new Promise((resolve) => setTimeout(resolve, ms));
12095
+ }
12096
+ };
12097
+ function createMockLedgerAdapter(config) {
12098
+ return new MockLedgerAdapter({ ...config, deviceType: "ledger" });
12099
+ }
12100
+ function createMockTrezorAdapter(config) {
12101
+ return new MockTrezorAdapter({ ...config, deviceType: "trezor" });
12102
+ }
12103
+
12104
+ // src/wallet/index.ts
12105
+ var import_types32 = require("@sip-protocol/types");
12106
+
12107
+ // src/proofs/browser.ts
12108
+ var import_noir_js2 = require("@noir-lang/noir_js");
12109
+ var import_bb2 = require("@aztec/bb.js");
12110
+ var import_secp256k15 = require("@noble/curves/secp256k1");
12111
+ var BrowserNoirProvider = class _BrowserNoirProvider {
12112
+ framework = "noir";
12113
+ _isReady = false;
12114
+ config;
12115
+ // Circuit instances
12116
+ fundingNoir = null;
12117
+ fundingBackend = null;
12118
+ validityNoir = null;
12119
+ validityBackend = null;
12120
+ fulfillmentNoir = null;
12121
+ fulfillmentBackend = null;
12122
+ // Worker instance (optional)
12123
+ worker = null;
12124
+ workerPending = /* @__PURE__ */ new Map();
12125
+ constructor(config = {}) {
12126
+ this.config = {
12127
+ useWorker: config.useWorker ?? true,
12128
+ verbose: config.verbose ?? false,
12129
+ oraclePublicKey: config.oraclePublicKey ?? void 0,
12130
+ timeout: config.timeout ?? 6e4
12131
+ };
12132
+ if (!isBrowser()) {
12133
+ console.warn(
12134
+ "[BrowserNoirProvider] Not running in browser environment. Consider using NoirProofProvider for Node.js."
12135
+ );
12136
+ }
12137
+ }
12138
+ get isReady() {
12139
+ return this._isReady;
12140
+ }
12141
+ /**
12142
+ * Get browser environment info
12143
+ */
12144
+ static getBrowserInfo() {
12145
+ return getBrowserInfo();
12146
+ }
12147
+ /**
12148
+ * Check if browser supports all required features
12149
+ */
12150
+ static checkBrowserSupport() {
12151
+ const missing = [];
12152
+ if (!isBrowser()) {
12153
+ missing.push("browser environment");
12154
+ }
12155
+ if (typeof WebAssembly === "undefined") {
12156
+ missing.push("WebAssembly");
12157
+ }
12158
+ if (!supportsSharedArrayBuffer()) {
12159
+ missing.push("SharedArrayBuffer (requires COOP/COEP headers)");
12160
+ }
12161
+ return {
12162
+ supported: missing.length === 0,
12163
+ missing
12164
+ };
12165
+ }
12385
12166
  /**
12386
- * Get multiple accounts
12167
+ * Derive secp256k1 public key coordinates from a private key
12387
12168
  */
12388
- async getAccounts(startIndex = 0, count = 5) {
12389
- this.requireConnected();
12390
- return this.mockAccounts.slice(startIndex, startIndex + count);
12169
+ static derivePublicKey(privateKey) {
12170
+ const uncompressedPubKey = import_secp256k15.secp256k1.getPublicKey(privateKey, false);
12171
+ const x = Array.from(uncompressedPubKey.slice(1, 33));
12172
+ const y = Array.from(uncompressedPubKey.slice(33, 65));
12173
+ return { x, y };
12391
12174
  }
12392
12175
  /**
12393
- * Switch account
12176
+ * Initialize the browser provider
12177
+ *
12178
+ * Loads WASM and circuit artifacts. This should be called before any
12179
+ * proof generation. Consider showing a loading indicator during init.
12180
+ *
12181
+ * @param onProgress - Optional progress callback
12394
12182
  */
12395
- async switchAccount(accountIndex) {
12396
- this.requireConnected();
12397
- if (accountIndex >= this.mockAccounts.length) {
12398
- throw new HardwareWalletError(
12399
- "Account index out of range",
12400
- HardwareErrorCode.INVALID_PATH,
12401
- "ledger"
12183
+ async initialize(onProgress) {
12184
+ if (this._isReady) {
12185
+ return;
12186
+ }
12187
+ const { supported, missing } = _BrowserNoirProvider.checkBrowserSupport();
12188
+ if (!supported) {
12189
+ throw new ProofError(
12190
+ `Browser missing required features: ${missing.join(", ")}`,
12191
+ "SIP_4004" /* PROOF_PROVIDER_NOT_READY */
12402
12192
  );
12403
12193
  }
12404
- const previousAddress = this._address;
12405
- this._account = this.mockAccounts[accountIndex];
12406
- this._derivationPath = this._account.derivationPath;
12407
- this.setConnected(this._account.address, this._account.publicKey);
12408
- if (previousAddress !== this._account.address) {
12409
- this.emitAccountChanged(previousAddress, this._account.address);
12194
+ try {
12195
+ onProgress?.({
12196
+ stage: "initializing",
12197
+ percent: 0,
12198
+ message: "Loading WASM runtime..."
12199
+ });
12200
+ if (this.config.verbose) {
12201
+ console.log("[BrowserNoirProvider] Initializing...");
12202
+ console.log("[BrowserNoirProvider] Browser info:", getBrowserInfo());
12203
+ }
12204
+ const fundingCircuit = funding_proof_default;
12205
+ const validityCircuit = validity_proof_default;
12206
+ const fulfillmentCircuit = fulfillment_proof_default;
12207
+ onProgress?.({
12208
+ stage: "initializing",
12209
+ percent: 20,
12210
+ message: "Creating proof backends..."
12211
+ });
12212
+ this.fundingBackend = new import_bb2.UltraHonkBackend(fundingCircuit.bytecode);
12213
+ this.validityBackend = new import_bb2.UltraHonkBackend(validityCircuit.bytecode);
12214
+ this.fulfillmentBackend = new import_bb2.UltraHonkBackend(fulfillmentCircuit.bytecode);
12215
+ onProgress?.({
12216
+ stage: "initializing",
12217
+ percent: 60,
12218
+ message: "Initializing Noir circuits..."
12219
+ });
12220
+ this.fundingNoir = new import_noir_js2.Noir(fundingCircuit);
12221
+ this.validityNoir = new import_noir_js2.Noir(validityCircuit);
12222
+ this.fulfillmentNoir = new import_noir_js2.Noir(fulfillmentCircuit);
12223
+ onProgress?.({
12224
+ stage: "initializing",
12225
+ percent: 90,
12226
+ message: "Setting up worker..."
12227
+ });
12228
+ if (this.config.useWorker && supportsWebWorkers()) {
12229
+ await this.initializeWorker();
12230
+ }
12231
+ this._isReady = true;
12232
+ onProgress?.({
12233
+ stage: "complete",
12234
+ percent: 100,
12235
+ message: "Ready for proof generation"
12236
+ });
12237
+ if (this.config.verbose) {
12238
+ console.log("[BrowserNoirProvider] Initialization complete");
12239
+ }
12240
+ } catch (error) {
12241
+ throw new ProofError(
12242
+ `Failed to initialize BrowserNoirProvider: ${error instanceof Error ? error.message : String(error)}`,
12243
+ "SIP_4003" /* PROOF_NOT_IMPLEMENTED */,
12244
+ { context: { error } }
12245
+ );
12410
12246
  }
12411
- return this._account;
12412
12247
  }
12413
- // ─── Test Helpers ───────────────────────────────────────────────────────────
12414
12248
  /**
12415
- * Set whether device should reject signing
12249
+ * Initialize Web Worker for off-main-thread proof generation
12416
12250
  */
12417
- setShouldReject(shouldReject) {
12418
- this.config.shouldReject = shouldReject;
12251
+ async initializeWorker() {
12252
+ if (this.config.verbose) {
12253
+ console.log("[BrowserNoirProvider] Worker support: using async main-thread");
12254
+ }
12419
12255
  }
12420
12256
  /**
12421
- * Set signing delay
12257
+ * Generate a Funding Proof
12258
+ *
12259
+ * Proves: balance >= minimumRequired without revealing balance
12260
+ *
12261
+ * @param params - Funding proof parameters
12262
+ * @param onProgress - Optional progress callback
12422
12263
  */
12423
- setSigningDelay(delay) {
12424
- this.config.signingDelay = delay;
12264
+ async generateFundingProof(params, onProgress) {
12265
+ this.ensureReady();
12266
+ if (!this.fundingNoir || !this.fundingBackend) {
12267
+ throw new ProofGenerationError("funding", "Funding circuit not initialized");
12268
+ }
12269
+ try {
12270
+ onProgress?.({
12271
+ stage: "witness",
12272
+ percent: 10,
12273
+ message: "Preparing witness inputs..."
12274
+ });
12275
+ const { commitmentHash, blindingField } = await this.computeCommitmentHash(
12276
+ params.balance,
12277
+ params.blindingFactor,
12278
+ params.assetId
12279
+ );
12280
+ const witnessInputs = {
12281
+ commitment_hash: commitmentHash,
12282
+ minimum_required: params.minimumRequired.toString(),
12283
+ asset_id: this.assetIdToField(params.assetId),
12284
+ balance: params.balance.toString(),
12285
+ blinding: blindingField
12286
+ };
12287
+ onProgress?.({
12288
+ stage: "witness",
12289
+ percent: 30,
12290
+ message: "Generating witness..."
12291
+ });
12292
+ const { witness } = await this.fundingNoir.execute(witnessInputs);
12293
+ onProgress?.({
12294
+ stage: "proving",
12295
+ percent: 50,
12296
+ message: "Generating proof (this may take a moment)..."
12297
+ });
12298
+ const proofData = await this.fundingBackend.generateProof(witness);
12299
+ onProgress?.({
12300
+ stage: "complete",
12301
+ percent: 100,
12302
+ message: "Proof generated successfully"
12303
+ });
12304
+ const publicInputs = [
12305
+ `0x${commitmentHash}`,
12306
+ `0x${params.minimumRequired.toString(16).padStart(16, "0")}`,
12307
+ `0x${this.assetIdToField(params.assetId)}`
12308
+ ];
12309
+ const proof = {
12310
+ type: "funding",
12311
+ proof: `0x${bytesToHex7(proofData.proof)}`,
12312
+ publicInputs
12313
+ };
12314
+ return { proof, publicInputs };
12315
+ } catch (error) {
12316
+ const message = error instanceof Error ? error.message : String(error);
12317
+ throw new ProofGenerationError(
12318
+ "funding",
12319
+ `Failed to generate funding proof: ${message}`,
12320
+ error instanceof Error ? error : void 0
12321
+ );
12322
+ }
12425
12323
  }
12426
12324
  /**
12427
- * Simulate device lock
12325
+ * Generate a Validity Proof
12326
+ *
12327
+ * Proves: Intent is authorized by sender without revealing identity
12428
12328
  */
12429
- simulateLock() {
12430
- if (this._deviceInfo) {
12431
- this._deviceInfo.isLocked = true;
12329
+ async generateValidityProof(params, onProgress) {
12330
+ this.ensureReady();
12331
+ if (!this.validityNoir || !this.validityBackend) {
12332
+ throw new ProofGenerationError("validity", "Validity circuit not initialized");
12333
+ }
12334
+ try {
12335
+ onProgress?.({
12336
+ stage: "witness",
12337
+ percent: 10,
12338
+ message: "Preparing validity witness..."
12339
+ });
12340
+ const intentHashField = this.hexToField(params.intentHash);
12341
+ const senderAddressField = this.hexToField(params.senderAddress);
12342
+ const senderBlindingField = this.bytesToField(params.senderBlinding);
12343
+ const senderSecretField = this.bytesToField(params.senderSecret);
12344
+ const nonceField = this.bytesToField(params.nonce);
12345
+ const { commitmentX, commitmentY } = await this.computeSenderCommitment(
12346
+ senderAddressField,
12347
+ senderBlindingField
12348
+ );
12349
+ const nullifier = await this.computeNullifier(senderSecretField, intentHashField, nonceField);
12350
+ const signature = Array.from(params.authorizationSignature);
12351
+ const messageHash = this.fieldToBytes32(intentHashField);
12352
+ let pubKeyX;
12353
+ let pubKeyY;
12354
+ if (params.senderPublicKey) {
12355
+ pubKeyX = Array.from(params.senderPublicKey.x);
12356
+ pubKeyY = Array.from(params.senderPublicKey.y);
12357
+ } else {
12358
+ const coords = this.getPublicKeyCoordinates(params.senderSecret);
12359
+ pubKeyX = coords.x;
12360
+ pubKeyY = coords.y;
12361
+ }
12362
+ const witnessInputs = {
12363
+ intent_hash: intentHashField,
12364
+ sender_commitment_x: commitmentX,
12365
+ sender_commitment_y: commitmentY,
12366
+ nullifier,
12367
+ timestamp: params.timestamp.toString(),
12368
+ expiry: params.expiry.toString(),
12369
+ sender_address: senderAddressField,
12370
+ sender_blinding: senderBlindingField,
12371
+ sender_secret: senderSecretField,
12372
+ pub_key_x: pubKeyX,
12373
+ pub_key_y: pubKeyY,
12374
+ signature,
12375
+ message_hash: messageHash,
12376
+ nonce: nonceField
12377
+ };
12378
+ onProgress?.({
12379
+ stage: "witness",
12380
+ percent: 30,
12381
+ message: "Generating witness..."
12382
+ });
12383
+ const { witness } = await this.validityNoir.execute(witnessInputs);
12384
+ onProgress?.({
12385
+ stage: "proving",
12386
+ percent: 50,
12387
+ message: "Generating validity proof..."
12388
+ });
12389
+ const proofData = await this.validityBackend.generateProof(witness);
12390
+ onProgress?.({
12391
+ stage: "complete",
12392
+ percent: 100,
12393
+ message: "Validity proof generated"
12394
+ });
12395
+ const publicInputs = [
12396
+ `0x${intentHashField}`,
12397
+ `0x${commitmentX}`,
12398
+ `0x${commitmentY}`,
12399
+ `0x${nullifier}`,
12400
+ `0x${params.timestamp.toString(16).padStart(16, "0")}`,
12401
+ `0x${params.expiry.toString(16).padStart(16, "0")}`
12402
+ ];
12403
+ const proof = {
12404
+ type: "validity",
12405
+ proof: `0x${bytesToHex7(proofData.proof)}`,
12406
+ publicInputs
12407
+ };
12408
+ return { proof, publicInputs };
12409
+ } catch (error) {
12410
+ const message = error instanceof Error ? error.message : String(error);
12411
+ throw new ProofGenerationError(
12412
+ "validity",
12413
+ `Failed to generate validity proof: ${message}`,
12414
+ error instanceof Error ? error : void 0
12415
+ );
12432
12416
  }
12433
- this.config.isLocked = true;
12434
12417
  }
12435
12418
  /**
12436
- * Simulate device unlock
12419
+ * Generate a Fulfillment Proof
12420
+ *
12421
+ * Proves: Solver correctly executed the intent
12437
12422
  */
12438
- simulateUnlock() {
12439
- if (this._deviceInfo) {
12440
- this._deviceInfo.isLocked = false;
12441
- }
12442
- this.config.isLocked = false;
12443
- }
12444
- // ─── Private Methods ────────────────────────────────────────────────────────
12445
- getAppName() {
12446
- switch (this.chain) {
12447
- case "ethereum":
12448
- return "Ethereum";
12449
- case "solana":
12450
- return "Solana";
12451
- default:
12452
- return "Unknown";
12423
+ async generateFulfillmentProof(params, onProgress) {
12424
+ this.ensureReady();
12425
+ if (!this.fulfillmentNoir || !this.fulfillmentBackend) {
12426
+ throw new ProofGenerationError("fulfillment", "Fulfillment circuit not initialized");
12453
12427
  }
12454
- }
12455
- generateMockAccounts() {
12456
- const count = this.config.accountCount ?? 5;
12457
- for (let i = 0; i < count; i++) {
12458
- const path = getDerivationPath(this.chain, i);
12459
- const address = this.config.mockAddress && i === 0 ? this.config.mockAddress : this.generateMockAddress(i);
12460
- const publicKey = this.config.mockPublicKey && i === 0 ? this.config.mockPublicKey : this.generateMockPublicKey(i);
12461
- this.mockAccounts.push({
12462
- address,
12463
- publicKey,
12464
- derivationPath: path,
12465
- index: i,
12466
- chain: this.chain
12428
+ try {
12429
+ onProgress?.({
12430
+ stage: "witness",
12431
+ percent: 10,
12432
+ message: "Preparing fulfillment witness..."
12467
12433
  });
12434
+ const intentHashField = this.hexToField(params.intentHash);
12435
+ const recipientStealthField = this.hexToField(params.recipientStealth);
12436
+ const { commitmentX, commitmentY } = await this.computeOutputCommitment(
12437
+ params.outputAmount,
12438
+ params.outputBlinding
12439
+ );
12440
+ const solverSecretField = this.bytesToField(params.solverSecret);
12441
+ const solverId = await this.computeSolverId(solverSecretField);
12442
+ const outputBlindingField = this.bytesToField(params.outputBlinding);
12443
+ const attestation = params.oracleAttestation;
12444
+ const attestationRecipientField = this.hexToField(attestation.recipient);
12445
+ const attestationTxHashField = this.hexToField(attestation.txHash);
12446
+ const oracleSignature = Array.from(attestation.signature);
12447
+ const oracleMessageHash = await this.computeOracleMessageHash(
12448
+ attestation.recipient,
12449
+ attestation.amount,
12450
+ attestation.txHash,
12451
+ attestation.blockNumber
12452
+ );
12453
+ const oraclePubKeyX = this.config.oraclePublicKey?.x ?? new Array(32).fill(0);
12454
+ const oraclePubKeyY = this.config.oraclePublicKey?.y ?? new Array(32).fill(0);
12455
+ const witnessInputs = {
12456
+ intent_hash: intentHashField,
12457
+ output_commitment_x: commitmentX,
12458
+ output_commitment_y: commitmentY,
12459
+ recipient_stealth: recipientStealthField,
12460
+ min_output_amount: params.minOutputAmount.toString(),
12461
+ solver_id: solverId,
12462
+ fulfillment_time: params.fulfillmentTime.toString(),
12463
+ expiry: params.expiry.toString(),
12464
+ output_amount: params.outputAmount.toString(),
12465
+ output_blinding: outputBlindingField,
12466
+ solver_secret: solverSecretField,
12467
+ attestation_recipient: attestationRecipientField,
12468
+ attestation_amount: attestation.amount.toString(),
12469
+ attestation_tx_hash: attestationTxHashField,
12470
+ attestation_block: attestation.blockNumber.toString(),
12471
+ oracle_signature: oracleSignature,
12472
+ oracle_message_hash: oracleMessageHash,
12473
+ oracle_pub_key_x: oraclePubKeyX,
12474
+ oracle_pub_key_y: oraclePubKeyY
12475
+ };
12476
+ onProgress?.({
12477
+ stage: "witness",
12478
+ percent: 30,
12479
+ message: "Generating witness..."
12480
+ });
12481
+ const { witness } = await this.fulfillmentNoir.execute(witnessInputs);
12482
+ onProgress?.({
12483
+ stage: "proving",
12484
+ percent: 50,
12485
+ message: "Generating fulfillment proof..."
12486
+ });
12487
+ const proofData = await this.fulfillmentBackend.generateProof(witness);
12488
+ onProgress?.({
12489
+ stage: "complete",
12490
+ percent: 100,
12491
+ message: "Fulfillment proof generated"
12492
+ });
12493
+ const publicInputs = [
12494
+ `0x${intentHashField}`,
12495
+ `0x${commitmentX}`,
12496
+ `0x${commitmentY}`,
12497
+ `0x${recipientStealthField}`,
12498
+ `0x${params.minOutputAmount.toString(16).padStart(16, "0")}`,
12499
+ `0x${solverId}`,
12500
+ `0x${params.fulfillmentTime.toString(16).padStart(16, "0")}`,
12501
+ `0x${params.expiry.toString(16).padStart(16, "0")}`
12502
+ ];
12503
+ const proof = {
12504
+ type: "fulfillment",
12505
+ proof: `0x${bytesToHex7(proofData.proof)}`,
12506
+ publicInputs
12507
+ };
12508
+ return { proof, publicInputs };
12509
+ } catch (error) {
12510
+ const message = error instanceof Error ? error.message : String(error);
12511
+ throw new ProofGenerationError(
12512
+ "fulfillment",
12513
+ `Failed to generate fulfillment proof: ${message}`,
12514
+ error instanceof Error ? error : void 0
12515
+ );
12468
12516
  }
12469
12517
  }
12470
- generateMockAddress(index) {
12471
- const bytes = (0, import_utils14.randomBytes)(20);
12472
- bytes[0] = index;
12473
- return `0x${(0, import_utils14.bytesToHex)(bytes)}`;
12474
- }
12475
- generateMockPublicKey(index) {
12476
- const bytes = (0, import_utils14.randomBytes)(33);
12477
- bytes[0] = 2;
12478
- bytes[1] = index;
12479
- return `0x${(0, import_utils14.bytesToHex)(bytes)}`;
12480
- }
12481
- generateMockSignature(data) {
12482
- const sig = new Uint8Array(65);
12483
- for (let i = 0; i < 32; i++) {
12484
- sig[i] = (data[i % data.length] ?? 0) ^ i * 7;
12485
- sig[32 + i] = (data[i % data.length] ?? 0) ^ i * 11;
12486
- }
12487
- sig[64] = 27;
12488
- return `0x${(0, import_utils14.bytesToHex)(sig)}`;
12489
- }
12490
- delay(ms) {
12491
- return new Promise((resolve) => setTimeout(resolve, ms));
12492
- }
12493
- };
12494
- var MockTrezorAdapter = class extends BaseWalletAdapter {
12495
- chain;
12496
- name = "mock-trezor";
12497
- config;
12498
- _derivationPath;
12499
- _deviceInfo = null;
12500
- _account = null;
12501
- mockAccounts = [];
12502
- constructor(config) {
12503
- super();
12504
- this.chain = config.chain;
12505
- this.config = {
12506
- model: "T",
12507
- accountIndex: 0,
12508
- isLocked: false,
12509
- signingDelay: 100,
12510
- shouldReject: false,
12511
- shouldFailConnect: false,
12512
- accountCount: 5,
12513
- ...config
12514
- };
12515
- this._derivationPath = config.derivationPath ?? getDerivationPath(config.chain, config.accountIndex ?? 0);
12516
- this.generateMockAccounts();
12517
- }
12518
- get deviceInfo() {
12519
- return this._deviceInfo;
12520
- }
12521
- get derivationPath() {
12522
- return this._derivationPath;
12523
- }
12524
- get account() {
12525
- return this._account;
12526
- }
12527
- async connect() {
12528
- this._connectionState = "connecting";
12529
- await this.delay(200);
12530
- if (this.config.shouldFailConnect) {
12531
- this._connectionState = "error";
12532
- throw new HardwareWalletError(
12533
- "Mock connection failure",
12534
- HardwareErrorCode.DEVICE_NOT_FOUND,
12535
- "trezor"
12536
- );
12518
+ /**
12519
+ * Verify a proof
12520
+ */
12521
+ async verifyProof(proof) {
12522
+ this.ensureReady();
12523
+ let backend = null;
12524
+ switch (proof.type) {
12525
+ case "funding":
12526
+ backend = this.fundingBackend;
12527
+ break;
12528
+ case "validity":
12529
+ backend = this.validityBackend;
12530
+ break;
12531
+ case "fulfillment":
12532
+ backend = this.fulfillmentBackend;
12533
+ break;
12534
+ default:
12535
+ throw new ProofError(`Unknown proof type: ${proof.type}`, "SIP_4003" /* PROOF_NOT_IMPLEMENTED */);
12537
12536
  }
12538
- if (this.config.isLocked) {
12539
- this._connectionState = "error";
12540
- throw new HardwareWalletError(
12541
- "Device requires PIN",
12542
- HardwareErrorCode.DEVICE_LOCKED,
12543
- "trezor"
12537
+ if (!backend) {
12538
+ throw new ProofError(
12539
+ `${proof.type} backend not initialized`,
12540
+ "SIP_4004" /* PROOF_PROVIDER_NOT_READY */
12544
12541
  );
12545
12542
  }
12546
- this._account = this.mockAccounts[this.config.accountIndex ?? 0];
12547
- this._deviceInfo = {
12548
- manufacturer: "trezor",
12549
- model: this.config.model ?? "Model T",
12550
- firmwareVersion: "2.5.3",
12551
- isLocked: false,
12552
- label: "Mock Trezor",
12553
- deviceId: "mock-trezor-001"
12554
- };
12555
- this.setConnected(this._account.address, this._account.publicKey);
12556
- }
12557
- async disconnect() {
12558
- this._account = null;
12559
- this._deviceInfo = null;
12560
- this.setDisconnected();
12543
+ try {
12544
+ const proofHex = proof.proof.startsWith("0x") ? proof.proof.slice(2) : proof.proof;
12545
+ const proofBytes = hexToBytes5(proofHex);
12546
+ const isValid = await backend.verifyProof({
12547
+ proof: proofBytes,
12548
+ publicInputs: proof.publicInputs.map(
12549
+ (input) => input.startsWith("0x") ? input.slice(2) : input
12550
+ )
12551
+ });
12552
+ return isValid;
12553
+ } catch (error) {
12554
+ if (this.config.verbose) {
12555
+ console.error("[BrowserNoirProvider] Verification error:", error);
12556
+ }
12557
+ return false;
12558
+ }
12561
12559
  }
12562
- async signMessage(message) {
12563
- this.requireConnected();
12564
- await this.delay(this.config.signingDelay ?? 100);
12565
- if (this.config.shouldReject) {
12566
- throw new HardwareWalletError(
12567
- "User rejected on device",
12568
- HardwareErrorCode.USER_REJECTED,
12569
- "trezor"
12570
- );
12560
+ /**
12561
+ * Destroy the provider and free resources
12562
+ */
12563
+ async destroy() {
12564
+ if (this.fundingBackend) {
12565
+ await this.fundingBackend.destroy();
12566
+ this.fundingBackend = null;
12571
12567
  }
12572
- const sig = this.generateMockSignature(message);
12573
- return {
12574
- signature: sig,
12575
- publicKey: this._account.publicKey
12576
- };
12568
+ if (this.validityBackend) {
12569
+ await this.validityBackend.destroy();
12570
+ this.validityBackend = null;
12571
+ }
12572
+ if (this.fulfillmentBackend) {
12573
+ await this.fulfillmentBackend.destroy();
12574
+ this.fulfillmentBackend = null;
12575
+ }
12576
+ if (this.worker) {
12577
+ this.worker.terminate();
12578
+ this.worker = null;
12579
+ }
12580
+ this.fundingNoir = null;
12581
+ this.validityNoir = null;
12582
+ this.fulfillmentNoir = null;
12583
+ this._isReady = false;
12577
12584
  }
12578
- async signTransaction(tx) {
12579
- this.requireConnected();
12580
- await this.delay(this.config.signingDelay ?? 100);
12581
- if (this.config.shouldReject) {
12582
- throw new HardwareWalletError(
12583
- "Transaction rejected on device",
12584
- HardwareErrorCode.USER_REJECTED,
12585
- "trezor"
12585
+ // ─── Private Utility Methods ────────────────────────────────────────────────
12586
+ ensureReady() {
12587
+ if (!this._isReady) {
12588
+ throw new ProofError(
12589
+ "BrowserNoirProvider not initialized. Call initialize() first.",
12590
+ "SIP_4004" /* PROOF_PROVIDER_NOT_READY */
12586
12591
  );
12587
12592
  }
12588
- const sig = this.generateMockSignature(
12589
- new TextEncoder().encode(JSON.stringify(tx.data))
12590
- );
12591
- return {
12592
- unsigned: tx,
12593
- signatures: [
12594
- {
12595
- signature: sig,
12596
- publicKey: this._account.publicKey
12597
- }
12598
- ],
12599
- serialized: sig
12600
- };
12601
- }
12602
- async signAndSendTransaction(tx) {
12603
- const signed = await this.signTransaction(tx);
12604
- return {
12605
- txHash: signed.serialized.slice(0, 66),
12606
- status: "pending"
12607
- };
12608
- }
12609
- async getBalance() {
12610
- throw new WalletError(
12611
- "Hardware wallets do not track balances",
12612
- import_types29.WalletErrorCode.UNSUPPORTED_OPERATION
12613
- );
12614
- }
12615
- async getTokenBalance(_asset) {
12616
- throw new WalletError(
12617
- "Hardware wallets do not track balances",
12618
- import_types29.WalletErrorCode.UNSUPPORTED_OPERATION
12619
- );
12620
12593
  }
12621
- async getAccounts(startIndex = 0, count = 5) {
12622
- this.requireConnected();
12623
- return this.mockAccounts.slice(startIndex, startIndex + count);
12594
+ async computeCommitmentHash(balance, blindingFactor, assetId) {
12595
+ const blindingField = this.bytesToField(blindingFactor);
12596
+ const { sha256: sha25611 } = await import("@noble/hashes/sha256");
12597
+ const { bytesToHex: nobleToHex } = await import("@noble/hashes/utils");
12598
+ const preimage = new Uint8Array([
12599
+ ...this.bigintToBytes(balance, 8),
12600
+ ...blindingFactor.slice(0, 32),
12601
+ ...hexToBytes5(this.assetIdToField(assetId))
12602
+ ]);
12603
+ const hash2 = sha25611(preimage);
12604
+ const commitmentHash = nobleToHex(hash2);
12605
+ return { commitmentHash, blindingField };
12624
12606
  }
12625
- async switchAccount(accountIndex) {
12626
- this.requireConnected();
12627
- if (accountIndex >= this.mockAccounts.length) {
12628
- throw new HardwareWalletError(
12629
- "Account index out of range",
12630
- HardwareErrorCode.INVALID_PATH,
12631
- "trezor"
12632
- );
12607
+ assetIdToField(assetId) {
12608
+ if (assetId.startsWith("0x")) {
12609
+ return assetId.slice(2).padStart(64, "0");
12633
12610
  }
12634
- const previousAddress = this._address;
12635
- this._account = this.mockAccounts[accountIndex];
12636
- this._derivationPath = this._account.derivationPath;
12637
- this.setConnected(this._account.address, this._account.publicKey);
12638
- if (previousAddress !== this._account.address) {
12639
- this.emitAccountChanged(previousAddress, this._account.address);
12611
+ const encoder = new TextEncoder();
12612
+ const bytes = encoder.encode(assetId);
12613
+ let result = 0n;
12614
+ for (let i = 0; i < bytes.length && i < 31; i++) {
12615
+ result = result * 256n + BigInt(bytes[i]);
12640
12616
  }
12641
- return this._account;
12642
- }
12643
- setShouldReject(shouldReject) {
12644
- this.config.shouldReject = shouldReject;
12645
- }
12646
- setSigningDelay(delay) {
12647
- this.config.signingDelay = delay;
12617
+ return result.toString(16).padStart(64, "0");
12648
12618
  }
12649
- simulateLock() {
12650
- if (this._deviceInfo) {
12651
- this._deviceInfo.isLocked = true;
12619
+ bytesToField(bytes) {
12620
+ let result = 0n;
12621
+ const len = Math.min(bytes.length, 31);
12622
+ for (let i = 0; i < len; i++) {
12623
+ result = result * 256n + BigInt(bytes[i]);
12652
12624
  }
12653
- this.config.isLocked = true;
12625
+ return result.toString();
12654
12626
  }
12655
- simulateUnlock() {
12656
- if (this._deviceInfo) {
12657
- this._deviceInfo.isLocked = false;
12627
+ bigintToBytes(value, length) {
12628
+ const bytes = new Uint8Array(length);
12629
+ let v = value;
12630
+ for (let i = length - 1; i >= 0; i--) {
12631
+ bytes[i] = Number(v & 0xffn);
12632
+ v = v >> 8n;
12658
12633
  }
12659
- this.config.isLocked = false;
12634
+ return bytes;
12660
12635
  }
12661
- generateMockAccounts() {
12662
- const count = this.config.accountCount ?? 5;
12663
- for (let i = 0; i < count; i++) {
12664
- const path = getDerivationPath(this.chain, i);
12665
- const address = this.config.mockAddress && i === 0 ? this.config.mockAddress : this.generateMockAddress(i);
12666
- const publicKey = this.config.mockPublicKey && i === 0 ? this.config.mockPublicKey : this.generateMockPublicKey(i);
12667
- this.mockAccounts.push({
12668
- address,
12669
- publicKey,
12670
- derivationPath: path,
12671
- index: i,
12672
- chain: this.chain
12673
- });
12636
+ hexToField(hex) {
12637
+ const h = hex.startsWith("0x") ? hex.slice(2) : hex;
12638
+ return h.padStart(64, "0");
12639
+ }
12640
+ fieldToBytes32(field) {
12641
+ const hex = field.padStart(64, "0");
12642
+ const bytes = [];
12643
+ for (let i = 0; i < 32; i++) {
12644
+ bytes.push(parseInt(hex.slice(i * 2, i * 2 + 2), 16));
12674
12645
  }
12646
+ return bytes;
12675
12647
  }
12676
- generateMockAddress(index) {
12677
- const bytes = (0, import_utils14.randomBytes)(20);
12678
- bytes[0] = index + 100;
12679
- return `0x${(0, import_utils14.bytesToHex)(bytes)}`;
12648
+ async computeSenderCommitment(senderAddressField, senderBlindingField) {
12649
+ const { sha256: sha25611 } = await import("@noble/hashes/sha256");
12650
+ const { bytesToHex: nobleToHex } = await import("@noble/hashes/utils");
12651
+ const addressBytes = hexToBytes5(senderAddressField);
12652
+ const blindingBytes = hexToBytes5(senderBlindingField.padStart(64, "0"));
12653
+ const preimage = new Uint8Array([...addressBytes, ...blindingBytes]);
12654
+ const hash2 = sha25611(preimage);
12655
+ const commitmentX = nobleToHex(hash2.slice(0, 16)).padStart(64, "0");
12656
+ const commitmentY = nobleToHex(hash2.slice(16, 32)).padStart(64, "0");
12657
+ return { commitmentX, commitmentY };
12680
12658
  }
12681
- generateMockPublicKey(index) {
12682
- const bytes = (0, import_utils14.randomBytes)(33);
12683
- bytes[0] = 3;
12684
- bytes[1] = index + 100;
12685
- return `0x${(0, import_utils14.bytesToHex)(bytes)}`;
12659
+ async computeNullifier(senderSecretField, intentHashField, nonceField) {
12660
+ const { sha256: sha25611 } = await import("@noble/hashes/sha256");
12661
+ const { bytesToHex: nobleToHex } = await import("@noble/hashes/utils");
12662
+ const secretBytes = hexToBytes5(senderSecretField.padStart(64, "0"));
12663
+ const intentBytes = hexToBytes5(intentHashField);
12664
+ const nonceBytes = hexToBytes5(nonceField.padStart(64, "0"));
12665
+ const preimage = new Uint8Array([...secretBytes, ...intentBytes, ...nonceBytes]);
12666
+ const hash2 = sha25611(preimage);
12667
+ return nobleToHex(hash2);
12686
12668
  }
12687
- generateMockSignature(data) {
12688
- const sig = new Uint8Array(65);
12689
- for (let i = 0; i < 32; i++) {
12690
- sig[i] = (data[i % data.length] ?? 0) ^ i * 13;
12691
- sig[32 + i] = (data[i % data.length] ?? 0) ^ i * 17;
12692
- }
12693
- sig[64] = 28;
12694
- return `0x${(0, import_utils14.bytesToHex)(sig)}`;
12669
+ async computeOutputCommitment(outputAmount, outputBlinding) {
12670
+ const { sha256: sha25611 } = await import("@noble/hashes/sha256");
12671
+ const { bytesToHex: nobleToHex } = await import("@noble/hashes/utils");
12672
+ const amountBytes = this.bigintToBytes(outputAmount, 8);
12673
+ const blindingBytes = outputBlinding.slice(0, 32);
12674
+ const preimage = new Uint8Array([...amountBytes, ...blindingBytes]);
12675
+ const hash2 = sha25611(preimage);
12676
+ const commitmentX = nobleToHex(hash2.slice(0, 16)).padStart(64, "0");
12677
+ const commitmentY = nobleToHex(hash2.slice(16, 32)).padStart(64, "0");
12678
+ return { commitmentX, commitmentY };
12695
12679
  }
12696
- delay(ms) {
12697
- return new Promise((resolve) => setTimeout(resolve, ms));
12680
+ async computeSolverId(solverSecretField) {
12681
+ const { sha256: sha25611 } = await import("@noble/hashes/sha256");
12682
+ const { bytesToHex: nobleToHex } = await import("@noble/hashes/utils");
12683
+ const secretBytes = hexToBytes5(solverSecretField.padStart(64, "0"));
12684
+ const hash2 = sha25611(secretBytes);
12685
+ return nobleToHex(hash2);
12686
+ }
12687
+ async computeOracleMessageHash(recipient, amount, txHash, blockNumber) {
12688
+ const { sha256: sha25611 } = await import("@noble/hashes/sha256");
12689
+ const recipientBytes = hexToBytes5(this.hexToField(recipient));
12690
+ const amountBytes = this.bigintToBytes(amount, 8);
12691
+ const txHashBytes = hexToBytes5(this.hexToField(txHash));
12692
+ const blockBytes = this.bigintToBytes(blockNumber, 8);
12693
+ const preimage = new Uint8Array([
12694
+ ...recipientBytes,
12695
+ ...amountBytes,
12696
+ ...txHashBytes,
12697
+ ...blockBytes
12698
+ ]);
12699
+ const hash2 = sha25611(preimage);
12700
+ return Array.from(hash2);
12701
+ }
12702
+ getPublicKeyCoordinates(privateKey) {
12703
+ const uncompressedPubKey = import_secp256k15.secp256k1.getPublicKey(privateKey, false);
12704
+ const x = Array.from(uncompressedPubKey.slice(1, 33));
12705
+ const y = Array.from(uncompressedPubKey.slice(33, 65));
12706
+ return { x, y };
12698
12707
  }
12699
12708
  };
12700
- function createMockLedgerAdapter(config) {
12701
- return new MockLedgerAdapter({ ...config, deviceType: "ledger" });
12702
- }
12703
- function createMockTrezorAdapter(config) {
12704
- return new MockTrezorAdapter({ ...config, deviceType: "trezor" });
12705
- }
12706
-
12707
- // src/wallet/index.ts
12708
- var import_types32 = require("@sip-protocol/types");
12709
12709
  // Annotate the CommonJS export names for ESM import in node:
12710
12710
  0 && (module.exports = {
12711
12711
  ATTESTATION_VERSION,