@orbinum/sdk 1.1.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -342,14 +342,75 @@ var EncryptedMemo = {
342
342
  }
343
343
  };
344
344
 
345
- // src/foundation/crypto/stealth.ts
346
- import { sha256 as sha2562 } from "@noble/hashes/sha2.js";
345
+ // src/protocol/memo/OutgoingBlob.ts
346
+ import { chacha20poly1305 as chacha20poly13052 } from "@noble/ciphers/chacha.js";
347
+ import { randomBytes as randomBytes2 } from "@noble/ciphers/utils.js";
347
348
  import { hkdf } from "@noble/hashes/hkdf.js";
349
+ import { sha256 as sha2562 } from "@noble/hashes/sha2.js";
350
+ var OCK_DOMAIN = new TextEncoder().encode("orbinum-outgoing-cipher-v1");
351
+ var NONCE_PREFIX = new TextEncoder().encode("OVK1");
352
+ var NONCE_SUFFIX_SIZE = 8;
353
+ var SHARED_SECRET_SIZE = 32;
354
+ var MAC_SIZE = 16;
355
+ var OVK_BLOB_SIZE = NONCE_SUFFIX_SIZE + SHARED_SECRET_SIZE + MAC_SIZE;
356
+ function deriveOutgoingCipherKey(ovk, commitmentBytes, ephPkBytes) {
357
+ if (commitmentBytes.length !== 32) {
358
+ throw new Error(
359
+ `OutgoingBlob: commitmentBytes must be 32 bytes, got ${commitmentBytes.length}`
360
+ );
361
+ }
362
+ if (ephPkBytes.length !== 32) {
363
+ throw new Error(`OutgoingBlob: ephPkBytes must be 32 bytes, got ${ephPkBytes.length}`);
364
+ }
365
+ const salt = new Uint8Array(64);
366
+ salt.set(commitmentBytes, 0);
367
+ salt.set(ephPkBytes, 32);
368
+ return hkdf(sha2562, ovk, salt, OCK_DOMAIN, 32);
369
+ }
370
+ function buildNonce(suffix) {
371
+ const nonce = new Uint8Array(12);
372
+ nonce.set(NONCE_PREFIX, 0);
373
+ nonce.set(suffix, 4);
374
+ return nonce;
375
+ }
376
+ function sealOutgoingBlob(ovk, sharedSecret, commitmentBytes, ephPkBytes) {
377
+ if (sharedSecret.length !== SHARED_SECRET_SIZE) {
378
+ throw new Error(`OutgoingBlob: sharedSecret must be 32 bytes, got ${sharedSecret.length}`);
379
+ }
380
+ const ock = deriveOutgoingCipherKey(ovk, commitmentBytes, ephPkBytes);
381
+ const suffix = randomBytes2(NONCE_SUFFIX_SIZE);
382
+ const cipher = chacha20poly13052(ock, buildNonce(suffix));
383
+ const sealed = cipher.encrypt(sharedSecret);
384
+ const blob = new Uint8Array(OVK_BLOB_SIZE);
385
+ blob.set(suffix, 0);
386
+ blob.set(sealed, NONCE_SUFFIX_SIZE);
387
+ return blob;
388
+ }
389
+ function openOutgoingBlob(ovk, blob, commitmentBytes, ephPkBytes) {
390
+ if (blob.length !== OVK_BLOB_SIZE) return null;
391
+ if (commitmentBytes.length !== 32 || ephPkBytes.length !== 32) return null;
392
+ try {
393
+ const ock = deriveOutgoingCipherKey(ovk, commitmentBytes, ephPkBytes);
394
+ const suffix = blob.subarray(0, NONCE_SUFFIX_SIZE);
395
+ const sealed = blob.subarray(NONCE_SUFFIX_SIZE);
396
+ const cipher = chacha20poly13052(ock, buildNonce(suffix));
397
+ return cipher.decrypt(sealed);
398
+ } catch {
399
+ return null;
400
+ }
401
+ }
402
+ function randomOutgoingBlob() {
403
+ return randomBytes2(OVK_BLOB_SIZE);
404
+ }
405
+
406
+ // src/foundation/crypto/stealth.ts
407
+ import { sha256 as sha2563 } from "@noble/hashes/sha2.js";
408
+ import { hkdf as hkdf2 } from "@noble/hashes/hkdf.js";
348
409
  import { mulPointEscalar, Base8, addPoint } from "@zk-kit/baby-jubjub";
349
410
  var STEALTH_INFO = new TextEncoder().encode("orbinum-stealth-v1");
350
411
  function deriveStealthScalar(sharedSecret, ownerPkBigint) {
351
412
  const salt = bigintTo32Le(ownerPkBigint);
352
- const stealthBytes = hkdf(sha2562, sharedSecret, salt, STEALTH_INFO, 32);
413
+ const stealthBytes = hkdf2(sha2563, sharedSecret, salt, STEALTH_INFO, 32);
353
414
  return bytesToBigintLE(stealthBytes) % BABYJUB_SUBORDER || 1n;
354
415
  }
355
416
  function deriveStealthOwnerPk(sharedSecret, ownerPkBigint, ownerPkPoint) {
@@ -427,7 +488,7 @@ function recoverOwnerPkPoint(ax) {
427
488
 
428
489
  // src/protocol/note/NoteBuilder.ts
429
490
  import { mulPointEscalar as mulPointEscalar3, unpackPoint as unpackPoint2 } from "@zk-kit/baby-jubjub";
430
- import { randomBytes as randomBytes2 } from "@noble/ciphers/utils.js";
491
+ import { randomBytes as randomBytes3 } from "@noble/ciphers/utils.js";
431
492
  import { poseidon2, poseidon4 } from "poseidon-lite";
432
493
  var NoteBuilder = class {
433
494
  /**
@@ -456,7 +517,7 @@ var NoteBuilder = class {
456
517
  if (useStealth) {
457
518
  const recipientOwnerPk = input.recipientOwnerPk;
458
519
  const recipientIvkPacked = input.viewingPublicKey;
459
- const ephSk = randomBytes2(32);
520
+ const ephSk = randomBytes3(32);
460
521
  const ivkPackedBigint = bytesToBigintLE(recipientIvkPacked);
461
522
  const ivkPoint = unpackPoint2(ivkPackedBigint);
462
523
  if (!ivkPoint)
@@ -497,6 +558,21 @@ var NoteBuilder = class {
497
558
  throw new Error(
498
559
  `NoteBuilder.build: invariant violated \u2014 memo must be ${ENCRYPTED_MEMO_SIZE} bytes, got ${memo.length}`
499
560
  );
561
+ let ovkBlob;
562
+ if (input.outgoingViewingKey !== void 0) {
563
+ const ephPkBytes = Uint8Array.from(memo.slice(148, 180));
564
+ const sealed = sealOutgoingBlob(
565
+ input.outgoingViewingKey,
566
+ sharedSecret,
567
+ stealthCommitmentBytes,
568
+ ephPkBytes
569
+ );
570
+ if (sealed.length !== OVK_BLOB_SIZE)
571
+ throw new Error(
572
+ `NoteBuilder.build: invariant violated \u2014 ovkBlob must be ${OVK_BLOB_SIZE} bytes, got ${sealed.length}`
573
+ );
574
+ ovkBlob = Array.from(sealed);
575
+ }
500
576
  return {
501
577
  value,
502
578
  assetId,
@@ -511,7 +587,8 @@ var NoteBuilder = class {
511
587
  commitmentHex: toHex(commitmentBytes2),
512
588
  nullifierHex: toHex(nullifierBytes2),
513
589
  memo,
514
- counterpartyPk
590
+ counterpartyPk,
591
+ ...ovkBlob ? { ovkBlob } : {}
515
592
  };
516
593
  }
517
594
  const commitment = poseidon4([value, assetId, ownerPk, blinding]);
@@ -641,6 +718,18 @@ function buildDummyTransferInput(assetId) {
641
718
  }
642
719
 
643
720
  // src/protocol/note/NoteDecryptor.ts
721
+ function decryptAndVerifyPlaintext(memoBytes, commitmentBytes, sharedSecret, effectiveOwnerPk) {
722
+ const plaintext = EncryptedMemo.decryptWithSharedSecret(
723
+ memoBytes,
724
+ commitmentBytes,
725
+ sharedSecret
726
+ );
727
+ if (!plaintext) return null;
728
+ const ownerPk = effectiveOwnerPk ?? plaintext.ownerPk;
729
+ const recomputed = poseidon42([plaintext.value, plaintext.assetId, ownerPk, plaintext.blinding]);
730
+ if (recomputed !== bytesToBigintLE(commitmentBytes)) return null;
731
+ return plaintext;
732
+ }
644
733
  function computeNullifier(commitment, spendingKey) {
645
734
  return poseidon22([commitment, spendingKey]);
646
735
  }
@@ -723,6 +812,40 @@ function tryDecryptNoteVerbose(commitment, viewingSecretKey, spendingKey, ownOwn
723
812
  }
724
813
  };
725
814
  }
815
+ function tryRecoverOutgoing(hint, ovk, opts) {
816
+ if (!hint.ovkBlob || !hint.encryptedMemo) return null;
817
+ let commitmentBytes;
818
+ let memoBytes;
819
+ let blobBytes;
820
+ try {
821
+ commitmentBytes = fromHex(hint.commitmentHex);
822
+ memoBytes = fromHex(hint.encryptedMemo);
823
+ blobBytes = fromHex(hint.ovkBlob);
824
+ } catch {
825
+ return null;
826
+ }
827
+ if (memoBytes.length !== ENCRYPTED_MEMO_SIZE) return null;
828
+ if (blobBytes.length !== OVK_BLOB_SIZE) return null;
829
+ const ephPkBytes = memoBytes.subarray(148, 180);
830
+ const sharedSecret = openOutgoingBlob(ovk, blobBytes, commitmentBytes, ephPkBytes);
831
+ if (!sharedSecret) return null;
832
+ const activation = opts?.viewTagActivationLeaf;
833
+ if (activation !== void 0 && isValidLeafIndex(hint.leafIndex) && hint.leafIndex >= activation && !EncryptedMemo.checkViewTag(memoBytes, sharedSecret)) {
834
+ return null;
835
+ }
836
+ const plaintext = decryptAndVerifyPlaintext(memoBytes, commitmentBytes, sharedSecret, null);
837
+ if (!plaintext) return null;
838
+ return {
839
+ commitmentHex: hint.commitmentHex,
840
+ ...isValidLeafIndex(hint.leafIndex) ? { leafIndex: hint.leafIndex } : {},
841
+ value: plaintext.value,
842
+ assetId: plaintext.assetId,
843
+ recipientStealthPk: plaintext.ownerPk,
844
+ blinding: plaintext.blinding,
845
+ counterpartyPk: plaintext.counterpartyPk,
846
+ circuitVersion: plaintext.circuitVersion
847
+ };
848
+ }
726
849
 
727
850
  // src/protocol/note/NoteDisclosure.ts
728
851
  import { poseidon4 as poseidon43 } from "poseidon-lite";
@@ -809,11 +932,11 @@ function decodeNoteDisclosureKey(key) {
809
932
  }
810
933
 
811
934
  // src/protocol/eph/selfEph.ts
812
- import { sha256 as sha2563 } from "@noble/hashes/sha2.js";
935
+ import { sha256 as sha2564 } from "@noble/hashes/sha2.js";
813
936
  import { packPoint as packPoint2, unpackPoint as unpackPoint3 } from "@zk-kit/baby-jubjub";
814
937
  var SELF_EPH_DOMAIN = new TextEncoder().encode("orbinum-self-eph-v1");
815
938
  function deriveSelfEphSk(spendingKey, index) {
816
- const h = sha2563.create();
939
+ const h = sha2564.create();
817
940
  h.update(SELF_EPH_DOMAIN);
818
941
  h.update(bigintTo32Le(spendingKey));
819
942
  const idx = new Uint8Array(4);
@@ -839,7 +962,7 @@ function selfEphWindow(spendingKey, ivkPacked, from, count) {
839
962
  }
840
963
 
841
964
  // src/protocol/eph/pairwiseEph.ts
842
- import { sha256 as sha2564 } from "@noble/hashes/sha2.js";
965
+ import { sha256 as sha2565 } from "@noble/hashes/sha2.js";
843
966
  import { packPoint as packPoint3, unpackPoint as unpackPoint4 } from "@zk-kit/baby-jubjub";
844
967
  var PAIRWISE_EPH_DOMAIN = new TextEncoder().encode("orbinum-pairwise-eph-v1");
845
968
  function derivePairwiseSharedSecret(myViewingSk, theirIvkPacked) {
@@ -849,7 +972,7 @@ function derivePairwiseSharedSecret(myViewingSk, theirIvkPacked) {
849
972
  return bigintTo32Le(shared[0]);
850
973
  }
851
974
  function derivePairwiseEphSk(pairSecret, index) {
852
- const h = sha2564.create();
975
+ const h = sha2565.create();
853
976
  h.update(PAIRWISE_EPH_DOMAIN);
854
977
  h.update(pairSecret);
855
978
  const idx = new Uint8Array(4);
@@ -875,10 +998,11 @@ function pairwiseEphWindow(pairSecret, receiverIvkPacked, from, count) {
875
998
  }
876
999
 
877
1000
  // src/protocol/keys/PrivacyKeys.ts
878
- import { hkdf as hkdf2 } from "@noble/hashes/hkdf.js";
879
- import { sha256 as sha2565 } from "@noble/hashes/sha2.js";
1001
+ import { hkdf as hkdf3 } from "@noble/hashes/hkdf.js";
1002
+ import { sha256 as sha2566 } from "@noble/hashes/sha2.js";
880
1003
  import { packPoint as packPoint4 } from "@zk-kit/baby-jubjub";
881
1004
  var IVK_DOMAIN = new TextEncoder().encode("orbinum-ivk-v1");
1005
+ var OVK_DOMAIN = new TextEncoder().encode("orbinum-ovk-v1");
882
1006
  var KEY_VERSION = "v2";
883
1007
  function deriveSpendingKeyFromMaster(masterBytes) {
884
1008
  const skBigint = BigInt(toHex(masterBytes)) % BABYJUB_SUBORDER;
@@ -886,7 +1010,7 @@ function deriveSpendingKeyFromMaster(masterBytes) {
886
1010
  }
887
1011
  function deriveViewingSecretKey(spendingKey) {
888
1012
  const ikm = bigintTo32Le(spendingKey);
889
- return hkdf2(sha2565, ikm, void 0, IVK_DOMAIN, 32);
1013
+ return hkdf3(sha2566, ikm, void 0, IVK_DOMAIN, 32);
890
1014
  }
891
1015
  function deriveViewingPublicKey(ivsk) {
892
1016
  const ivskScalar = BigInt(toHex(ivsk)) % BABYJUB_SUBORDER || 1n;
@@ -902,6 +1026,9 @@ function deriveOwnerPk(spendingKey) {
902
1026
  return 0n;
903
1027
  }
904
1028
  }
1029
+ function deriveOutgoingViewingKey(masterBytes) {
1030
+ return hkdf3(sha2566, masterBytes, void 0, OVK_DOMAIN, 32);
1031
+ }
905
1032
 
906
1033
  // src/wallet/worker/kernel/types.ts
907
1034
  var SELF_EPH_WINDOW = 1024;
@@ -1201,6 +1328,11 @@ export {
1201
1328
  ENCRYPTED_MEMO_SIZE,
1202
1329
  bytesToBjjScalar,
1203
1330
  EncryptedMemo,
1331
+ OVK_BLOB_SIZE,
1332
+ deriveOutgoingCipherKey,
1333
+ sealOutgoingBlob,
1334
+ openOutgoingBlob,
1335
+ randomOutgoingBlob,
1204
1336
  deriveSelfEphSk,
1205
1337
  selfEphWindow,
1206
1338
  derivePairwiseSharedSecret,
@@ -1220,6 +1352,7 @@ export {
1220
1352
  computeNoteCommitment,
1221
1353
  tryDecryptNote,
1222
1354
  tryDecryptNoteVerbose,
1355
+ tryRecoverOutgoing,
1223
1356
  createNoteDisclosureKey,
1224
1357
  decodeNoteDisclosureKey,
1225
1358
  KEY_VERSION,
@@ -1227,6 +1360,7 @@ export {
1227
1360
  deriveViewingSecretKey,
1228
1361
  deriveViewingPublicKey,
1229
1362
  deriveOwnerPk,
1363
+ deriveOutgoingViewingKey,
1230
1364
  SELF_EPH_WINDOW,
1231
1365
  PAIRWISE_EPH_WINDOW,
1232
1366
  EMPTY_BATCH_RESULT,
@@ -76,6 +76,13 @@ type NoteInput = {
76
76
  * generates its own coordinated ephSk). Default: random.
77
77
  */
78
78
  ephSkOverride?: Uint8Array;
79
+ /**
80
+ * Sender's 32-byte outgoing viewing key (ovk). When present on the stealth
81
+ * path, `build()` seals the memo's shared secret into a 56-byte `ovkBlob` so
82
+ * the sender can recover this transfer after a cold restore. Absent → no blob
83
+ * (the app applies the ⊥ default at submit time, never the SDK).
84
+ */
85
+ outgoingViewingKey?: Uint8Array;
79
86
  };
80
87
  /**
81
88
  * Circuit version notes are created under today. A note carries its version
@@ -129,6 +136,39 @@ type ZkNote = {
129
136
  memo: number[];
130
137
  /** Counterparty BabyJubJub Ax coordinate. Zero for shield/unshield notes. */
131
138
  counterpartyPk: bigint;
139
+ /**
140
+ * 56-byte outgoing-viewing-key blob (per-note in the domain object; becomes a
141
+ * per-transaction field at submit, see the OVK plan §4.1). Present only on a
142
+ * stealth recipient note built with an `outgoingViewingKey`. It wraps the
143
+ * memo's shared secret under the sender's ovk so the sender can recover the
144
+ * transfer; the recipient never needs it. Not persisted in the vault.
145
+ */
146
+ ovkBlob?: number[];
147
+ };
148
+ /**
149
+ * A sender's record of a note they SENT, recovered via the OVK blob. Not a
150
+ * spendable note: it deliberately carries no `spendingKey`, no `nullifier`, no
151
+ * `spent` flag — the sender does not own the recipient's note, only the memory of
152
+ * having sent it. Used to rebuild the outgoing history after a cold restore.
153
+ */
154
+ type OutgoingNoteRecord = {
155
+ /** 0x-prefixed 32-byte LE commitment hex of the recipient output. */
156
+ commitmentHex: string;
157
+ /** Global Merkle leaf index, when the hint carried one. */
158
+ leafIndex?: number;
159
+ /** Amount sent, in planck. */
160
+ value: bigint;
161
+ /** Asset ID of the sent note. */
162
+ assetId: bigint;
163
+ /** The recipient's one-time stealth owner public key (BJJ Ax). */
164
+ recipientStealthPk: bigint;
165
+ /** Blinding scalar of the recipient output. With value/assetId/stealthPk it
166
+ * recomputes the commitment — needed to rebuild a payment slip for the note. */
167
+ blinding: bigint;
168
+ /** Counterparty BabyJubJub Ax coordinate stamped in the memo. */
169
+ counterpartyPk: bigint;
170
+ /** Circuit version the sent note was created under. */
171
+ circuitVersion: number;
132
172
  };
133
173
 
134
174
  /**
@@ -350,4 +390,4 @@ declare function createMainThreadPool(): DecryptPool;
350
390
 
351
391
  declare function createWorkerPool(factory: WorkerFactory, size: number): DecryptPool;
352
392
 
353
- export { CURRENT_CIRCUIT_VERSION as C, type DecryptedMemo as D, EMPTY_BATCH_RESULT as E, type KnownEphEntry as K, MAX_WORKERS as M, type NoteInput as N, PAIRWISE_EPH_WINDOW as P, type ScanCommitment as S, WORKER_CRASHED as W, type ZkNote as Z, type DecryptPool as a, type ScanKeys as b, DECRYPT_YIELD_EVERY as c, type DecryptBatchResult as d, type DecryptRequest as e, type KnownEphWindow as f, type MatchSource as g, type MerkleTreeInfo as h, SELF_EPH_WINDOW as i, type WorkerFactory as j, type WorkerLike as k, type WorkerMessage as l, clearKnownEphWindow as m, createDecryptPool as n, createMainThreadPool as o, createWorkerPool as p, decryptHintBatch as q, getKnownEphWindow as r };
393
+ export { CURRENT_CIRCUIT_VERSION as C, type DecryptedMemo as D, EMPTY_BATCH_RESULT as E, type KnownEphEntry as K, MAX_WORKERS as M, type NoteInput as N, type OutgoingNoteRecord as O, PAIRWISE_EPH_WINDOW as P, type ScanCommitment as S, WORKER_CRASHED as W, type ZkNote as Z, type DecryptPool as a, type ScanKeys as b, DECRYPT_YIELD_EVERY as c, type DecryptBatchResult as d, type DecryptRequest as e, type KnownEphWindow as f, type MatchSource as g, type MerkleTreeInfo as h, SELF_EPH_WINDOW as i, type WorkerFactory as j, type WorkerLike as k, type WorkerMessage as l, clearKnownEphWindow as m, createDecryptPool as n, createMainThreadPool as o, createWorkerPool as p, decryptHintBatch as q, getKnownEphWindow as r };
@@ -76,6 +76,13 @@ type NoteInput = {
76
76
  * generates its own coordinated ephSk). Default: random.
77
77
  */
78
78
  ephSkOverride?: Uint8Array;
79
+ /**
80
+ * Sender's 32-byte outgoing viewing key (ovk). When present on the stealth
81
+ * path, `build()` seals the memo's shared secret into a 56-byte `ovkBlob` so
82
+ * the sender can recover this transfer after a cold restore. Absent → no blob
83
+ * (the app applies the ⊥ default at submit time, never the SDK).
84
+ */
85
+ outgoingViewingKey?: Uint8Array;
79
86
  };
80
87
  /**
81
88
  * Circuit version notes are created under today. A note carries its version
@@ -129,6 +136,39 @@ type ZkNote = {
129
136
  memo: number[];
130
137
  /** Counterparty BabyJubJub Ax coordinate. Zero for shield/unshield notes. */
131
138
  counterpartyPk: bigint;
139
+ /**
140
+ * 56-byte outgoing-viewing-key blob (per-note in the domain object; becomes a
141
+ * per-transaction field at submit, see the OVK plan §4.1). Present only on a
142
+ * stealth recipient note built with an `outgoingViewingKey`. It wraps the
143
+ * memo's shared secret under the sender's ovk so the sender can recover the
144
+ * transfer; the recipient never needs it. Not persisted in the vault.
145
+ */
146
+ ovkBlob?: number[];
147
+ };
148
+ /**
149
+ * A sender's record of a note they SENT, recovered via the OVK blob. Not a
150
+ * spendable note: it deliberately carries no `spendingKey`, no `nullifier`, no
151
+ * `spent` flag — the sender does not own the recipient's note, only the memory of
152
+ * having sent it. Used to rebuild the outgoing history after a cold restore.
153
+ */
154
+ type OutgoingNoteRecord = {
155
+ /** 0x-prefixed 32-byte LE commitment hex of the recipient output. */
156
+ commitmentHex: string;
157
+ /** Global Merkle leaf index, when the hint carried one. */
158
+ leafIndex?: number;
159
+ /** Amount sent, in planck. */
160
+ value: bigint;
161
+ /** Asset ID of the sent note. */
162
+ assetId: bigint;
163
+ /** The recipient's one-time stealth owner public key (BJJ Ax). */
164
+ recipientStealthPk: bigint;
165
+ /** Blinding scalar of the recipient output. With value/assetId/stealthPk it
166
+ * recomputes the commitment — needed to rebuild a payment slip for the note. */
167
+ blinding: bigint;
168
+ /** Counterparty BabyJubJub Ax coordinate stamped in the memo. */
169
+ counterpartyPk: bigint;
170
+ /** Circuit version the sent note was created under. */
171
+ circuitVersion: number;
132
172
  };
133
173
 
134
174
  /**
@@ -350,4 +390,4 @@ declare function createMainThreadPool(): DecryptPool;
350
390
 
351
391
  declare function createWorkerPool(factory: WorkerFactory, size: number): DecryptPool;
352
392
 
353
- export { CURRENT_CIRCUIT_VERSION as C, type DecryptedMemo as D, EMPTY_BATCH_RESULT as E, type KnownEphEntry as K, MAX_WORKERS as M, type NoteInput as N, PAIRWISE_EPH_WINDOW as P, type ScanCommitment as S, WORKER_CRASHED as W, type ZkNote as Z, type DecryptPool as a, type ScanKeys as b, DECRYPT_YIELD_EVERY as c, type DecryptBatchResult as d, type DecryptRequest as e, type KnownEphWindow as f, type MatchSource as g, type MerkleTreeInfo as h, SELF_EPH_WINDOW as i, type WorkerFactory as j, type WorkerLike as k, type WorkerMessage as l, clearKnownEphWindow as m, createDecryptPool as n, createMainThreadPool as o, createWorkerPool as p, decryptHintBatch as q, getKnownEphWindow as r };
393
+ export { CURRENT_CIRCUIT_VERSION as C, type DecryptedMemo as D, EMPTY_BATCH_RESULT as E, type KnownEphEntry as K, MAX_WORKERS as M, type NoteInput as N, type OutgoingNoteRecord as O, PAIRWISE_EPH_WINDOW as P, type ScanCommitment as S, WORKER_CRASHED as W, type ZkNote as Z, type DecryptPool as a, type ScanKeys as b, DECRYPT_YIELD_EVERY as c, type DecryptBatchResult as d, type DecryptRequest as e, type KnownEphWindow as f, type MatchSource as g, type MerkleTreeInfo as h, SELF_EPH_WINDOW as i, type WorkerFactory as j, type WorkerLike as k, type WorkerMessage as l, clearKnownEphWindow as m, createDecryptPool as n, createMainThreadPool as o, createWorkerPool as p, decryptHintBatch as q, getKnownEphWindow as r };