@cardanowall/sdk-ts 0.1.0 → 0.3.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.
Files changed (38) hide show
  1. package/README.md +14 -14
  2. package/dist/client/index.cjs +1621 -1538
  3. package/dist/client/index.cjs.map +1 -1
  4. package/dist/client/index.d.cts +52 -52
  5. package/dist/client/index.d.ts +52 -52
  6. package/dist/client/index.js +1620 -1537
  7. package/dist/client/index.js.map +1 -1
  8. package/dist/conformance/cli.cjs +2367 -2106
  9. package/dist/conformance/cli.cjs.map +1 -1
  10. package/dist/conformance/cli.js +2367 -2106
  11. package/dist/conformance/cli.js.map +1 -1
  12. package/dist/identity/index.cjs +219 -104
  13. package/dist/identity/index.cjs.map +1 -1
  14. package/dist/identity/index.d.cts +1 -1
  15. package/dist/identity/index.d.ts +1 -1
  16. package/dist/identity/index.js +219 -104
  17. package/dist/identity/index.js.map +1 -1
  18. package/dist/ids/index.cjs.map +1 -1
  19. package/dist/ids/index.js.map +1 -1
  20. package/dist/index.cjs +2808 -2530
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.d.cts +3 -3
  23. package/dist/index.d.ts +3 -3
  24. package/dist/index.js +2805 -2527
  25. package/dist/index.js.map +1 -1
  26. package/dist/merkle/index.cjs +1 -1
  27. package/dist/merkle/index.cjs.map +1 -1
  28. package/dist/merkle/index.js +1 -1
  29. package/dist/merkle/index.js.map +1 -1
  30. package/dist/{types-BQMtbRCb.d.cts → types-DGsZTMuZ.d.cts} +6 -6
  31. package/dist/{types-BQMtbRCb.d.ts → types-DGsZTMuZ.d.ts} +6 -6
  32. package/dist/verifier/index.cjs +2368 -2107
  33. package/dist/verifier/index.cjs.map +1 -1
  34. package/dist/verifier/index.d.cts +3 -3
  35. package/dist/verifier/index.d.ts +3 -3
  36. package/dist/verifier/index.js +2369 -2108
  37. package/dist/verifier/index.js.map +1 -1
  38. package/package.json +8 -8
@@ -56,7 +56,7 @@ function buildSigStructure(args) {
56
56
  args.payload
57
57
  ]);
58
58
  }
59
- function buildCip309SigStructure(args) {
59
+ function buildLabel309SigStructure(args) {
60
60
  const toSign = new Uint8Array(
61
61
  CARDANO_POE_SIG_DOMAIN_PREFIX_BYTES.length + args.recordBodyCbor.length
62
62
  );
@@ -320,578 +320,752 @@ function sigEntryToCbor(entry) {
320
320
  }
321
321
  return out;
322
322
  }
323
-
324
- // ../poe-standard/src/chunked.ts
325
- var CHUNK_MAX_BYTES = 64;
326
- var UTF8_ENCODER2 = new TextEncoder();
327
- function chunkBytes(value) {
328
- if (value.length === 0) return [new Uint8Array(0)];
329
- const chunks = [];
330
- for (let i = 0; i < value.length; i += CHUNK_MAX_BYTES) {
331
- chunks.push(value.subarray(i, Math.min(i + CHUNK_MAX_BYTES, value.length)));
332
- }
333
- return chunks;
334
- }
335
- function chunkUri(uri) {
336
- const bytes = UTF8_ENCODER2.encode(uri);
337
- if (bytes.length === 0) return [""];
338
- if (bytes.length <= CHUNK_MAX_BYTES) return [uri];
339
- const decoder = new TextDecoder("utf-8", { fatal: true });
340
- const chunks = [];
341
- let cursor = 0;
342
- while (cursor < bytes.length) {
343
- let end = Math.min(cursor + CHUNK_MAX_BYTES, bytes.length);
344
- while (end < bytes.length && (bytes[end] & 192) === 128) end--;
345
- chunks.push(decoder.decode(bytes.subarray(cursor, end)));
346
- cursor = end;
347
- }
348
- return chunks;
349
- }
350
-
351
- // src/client/off-host-sign.ts
352
- var EMPTY_BYTES2 = new Uint8Array(0);
353
- var ED25519_PUBLIC_KEY_LENGTH = 32;
354
- var ED25519_SIGNATURE_LENGTH = 64;
355
- var OffHostSignError = class extends Error {
356
- code;
357
- constructor(code, message) {
358
- super(message);
359
- this.name = "OffHostSignError";
360
- this.code = code;
361
- }
362
- };
363
- function buildToSign(record) {
364
- const body = encodeRecordBodyForSigning(record);
365
- const out = new Uint8Array(CARDANO_POE_SIG_DOMAIN_PREFIX_BYTES.length + body.length);
366
- out.set(CARDANO_POE_SIG_DOMAIN_PREFIX_BYTES, 0);
367
- out.set(body, CARDANO_POE_SIG_DOMAIN_PREFIX_BYTES.length);
368
- return out;
323
+ var abytesDoc = abytes;
324
+ var randomBytes = randomBytes$2;
325
+ function equalBytes(a, b) {
326
+ if (a.length !== b.length)
327
+ return false;
328
+ let diff = 0;
329
+ for (let i = 0; i < a.length; i++)
330
+ diff |= a[i] ^ b[i];
331
+ return diff === 0;
369
332
  }
370
- function encodePath1ProtectedHeader(signerPubkey) {
371
- const protectedHeader = /* @__PURE__ */ new Map([
372
- [1, -8],
373
- [4, signerPubkey]
374
- ]);
375
- const protectedHeaderBytes = encodeCanonicalCbor(protectedHeader);
376
- return { protectedHeader, protectedHeaderBytes };
333
+ function copyBytes(bytes) {
334
+ return Uint8Array.from(abytes(bytes));
377
335
  }
378
- function prepareSigStructure(args) {
379
- if (args.signerPubkey.length !== ED25519_PUBLIC_KEY_LENGTH) {
380
- throw new OffHostSignError(
381
- "INVALID_PUBKEY_LENGTH",
382
- `signerPubkey must be 32 bytes (Ed25519 raw public key), got ${args.signerPubkey.length}`
383
- );
384
- }
385
- const { protectedHeaderBytes } = encodePath1ProtectedHeader(args.signerPubkey);
386
- const recordBodyCbor = encodeRecordBodyForSigning(args.record);
387
- const sigStructureBytes = buildCip309SigStructure({
388
- bodyProtectedBytes: protectedHeaderBytes,
389
- recordBodyCbor
390
- });
391
- return { sigStructureBytes, protectedHeaderBytes };
336
+ function splitCoder(label, ...lengths) {
337
+ const getLength = (c) => typeof c === "number" ? c : c.bytesLen;
338
+ const bytesLen = lengths.reduce((sum, a) => sum + getLength(a), 0);
339
+ return {
340
+ bytesLen,
341
+ encode: (bufs) => {
342
+ const res = new Uint8Array(bytesLen);
343
+ for (let i = 0, pos = 0; i < lengths.length; i++) {
344
+ const c = lengths[i];
345
+ const l = getLength(c);
346
+ const b = typeof c === "number" ? bufs[i] : c.encode(bufs[i]);
347
+ abytes(b, l, label);
348
+ res.set(b, pos);
349
+ if (typeof c !== "number")
350
+ b.fill(0);
351
+ pos += l;
352
+ }
353
+ return res;
354
+ },
355
+ decode: (buf) => {
356
+ abytes(buf, bytesLen, label);
357
+ const res = [];
358
+ for (const c of lengths) {
359
+ const l = getLength(c);
360
+ const b = buf.subarray(0, l);
361
+ res.push(typeof c === "number" ? b : c.decode(b));
362
+ buf = buf.subarray(l);
363
+ }
364
+ return res;
365
+ }
366
+ };
392
367
  }
393
- function assembleCoseSign1(args) {
394
- if (args.signerPubkey.length !== ED25519_PUBLIC_KEY_LENGTH) {
395
- throw new OffHostSignError(
396
- "INVALID_PUBKEY_LENGTH",
397
- `signerPubkey must be 32 bytes (Ed25519 raw public key), got ${args.signerPubkey.length}`
398
- );
399
- }
400
- if (args.signature.length !== ED25519_SIGNATURE_LENGTH) {
401
- throw new OffHostSignError(
402
- "INVALID_SIGNATURE_LENGTH",
403
- `signature must be 64 bytes (Ed25519 raw signature), got ${args.signature.length}`
404
- );
405
- }
406
- const { protectedHeader } = encodePath1ProtectedHeader(args.signerPubkey);
407
- const coseSign1Bytes = encodeCoseSign1({
408
- protectedHeader,
409
- unprotectedHeader: /* @__PURE__ */ new Map(),
410
- payload: null,
411
- signature: args.signature
412
- });
413
- const chunks = chunkBytes(coseSign1Bytes);
414
- const sigEntry = { cose_sign1: chunks };
415
- return { coseSign1Bytes, sigEntry };
368
+ function vecCoder(c, vecLen) {
369
+ const coder = c;
370
+ const bytesLen = vecLen * coder.bytesLen;
371
+ return {
372
+ bytesLen,
373
+ encode: (u) => {
374
+ if (u.length !== vecLen)
375
+ throw new RangeError(`vecCoder.encode: wrong length=${u.length}. Expected: ${vecLen}`);
376
+ const res = new Uint8Array(bytesLen);
377
+ for (let i = 0, pos = 0; i < u.length; i++) {
378
+ const b = coder.encode(u[i]);
379
+ res.set(b, pos);
380
+ b.fill(0);
381
+ pos += b.length;
382
+ }
383
+ return res;
384
+ },
385
+ decode: (a) => {
386
+ abytes(a, bytesLen);
387
+ const r = [];
388
+ for (let i = 0; i < a.length; i += coder.bytesLen)
389
+ r.push(coder.decode(a.subarray(i, i + coder.bytesLen)));
390
+ return r;
391
+ }
392
+ };
416
393
  }
417
- function prepareSigStructureHashed(args) {
418
- if (args.signerPubkey.length !== ED25519_PUBLIC_KEY_LENGTH) {
419
- throw new OffHostSignError(
420
- "INVALID_PUBKEY_LENGTH",
421
- `signerPubkey must be 32 bytes (Ed25519 raw public key), got ${args.signerPubkey.length}`
422
- );
394
+ function cleanBytes(...list) {
395
+ for (const t of list) {
396
+ if (Array.isArray(t))
397
+ for (const b of t)
398
+ b.fill(0);
399
+ else
400
+ t.fill(0);
423
401
  }
424
- const { protectedHeaderBytes } = encodePath1ProtectedHeader(args.signerPubkey);
425
- const toSign = buildToSign(args.record);
426
- const toSignHashBytes = blake2b224(toSign);
427
- const sigStructureBytes = buildSigStructure({
428
- context: "Signature1",
429
- bodyProtectedBytes: protectedHeaderBytes,
430
- externalAad: EMPTY_BYTES2,
431
- payload: toSignHashBytes
432
- });
433
- return { sigStructureBytes, protectedHeaderBytes, toSignHashBytes };
434
402
  }
435
- function assembleCoseSign1Hashed(args) {
436
- if (args.signerPubkey.length !== ED25519_PUBLIC_KEY_LENGTH) {
437
- throw new OffHostSignError(
438
- "INVALID_PUBKEY_LENGTH",
439
- `signerPubkey must be 32 bytes (Ed25519 raw public key), got ${args.signerPubkey.length}`
440
- );
441
- }
442
- if (args.signature.length !== ED25519_SIGNATURE_LENGTH) {
443
- throw new OffHostSignError(
444
- "INVALID_SIGNATURE_LENGTH",
445
- `signature must be 64 bytes (Ed25519 raw signature), got ${args.signature.length}`
446
- );
447
- }
448
- const { protectedHeader } = encodePath1ProtectedHeader(args.signerPubkey);
449
- const unprotectedHeader = /* @__PURE__ */ new Map([["hashed", true]]);
450
- const coseSign1Bytes = encodeCoseSign1({
451
- protectedHeader,
452
- unprotectedHeader,
453
- payload: null,
454
- signature: args.signature
455
- });
456
- const chunks = chunkBytes(coseSign1Bytes);
457
- const sigEntry = { cose_sign1: chunks };
458
- return { coseSign1Bytes, sigEntry };
403
+ function getMask(bits) {
404
+ if (!Number.isSafeInteger(bits) || bits < 0 || bits > 32)
405
+ throw new RangeError(`expected bits in [0..32], got ${bits}`);
406
+ return bits === 32 ? 4294967295 : ~(-1 << bits) >>> 0;
459
407
  }
460
408
 
461
- // src/client/http-error.ts
462
- var CANONICAL_PROBLEM_KEYS = /* @__PURE__ */ new Set([
463
- "type",
464
- "title",
465
- "status",
466
- "detail",
467
- "code",
468
- "trace_id",
469
- "errors",
470
- "instance"
471
- ]);
472
- function extractProblemExtensions(problem) {
473
- const out = {};
474
- for (const [key, value] of Object.entries(problem)) {
475
- if (!CANONICAL_PROBLEM_KEYS.has(key)) {
476
- out[key] = value;
409
+ // ../../node_modules/.pnpm/@noble+post-quantum@0.6.1/node_modules/@noble/post-quantum/_crystals.js
410
+ var genCrystals = (opts2) => {
411
+ const { newPoly, N: N2, Q: Q2, F: F2, ROOT_OF_UNITY: ROOT_OF_UNITY2, brvBits} = opts2;
412
+ const mod = (a, modulo = Q2) => {
413
+ const result = a % modulo | 0;
414
+ return (result >= 0 ? result | 0 : modulo + result | 0) | 0;
415
+ };
416
+ const smod = (a, modulo = Q2) => {
417
+ const r = mod(a, modulo) | 0;
418
+ return (r > modulo >> 1 ? r - modulo | 0 : r) | 0;
419
+ };
420
+ function getZettas() {
421
+ const out = newPoly(N2);
422
+ for (let i = 0; i < N2; i++) {
423
+ const b = reverseBits(i, brvBits);
424
+ const p = BigInt(ROOT_OF_UNITY2) ** BigInt(b) % BigInt(Q2);
425
+ out[i] = Number(p) | 0;
477
426
  }
427
+ return out;
478
428
  }
479
- return out;
480
- }
481
- var Cip309HttpError = class extends Error {
482
- problem;
483
- code;
484
- httpStatus;
485
- title;
486
- detail;
487
- type;
488
- traceId;
489
- instance;
490
- errors;
491
- extensions;
492
- requestId;
493
- retryAfterSeconds;
494
- constructor(init) {
495
- super(init.problem.detail || `${init.problem.title} (HTTP ${init.problem.status})`);
496
- this.name = "Cip309HttpError";
497
- this.problem = init.problem;
498
- this.code = init.problem.code;
499
- this.httpStatus = init.problem.status;
500
- this.title = init.problem.title;
501
- this.detail = init.problem.detail;
502
- this.type = init.problem.type;
503
- this.traceId = init.problem.trace_id;
504
- this.instance = init.problem.instance;
505
- this.errors = init.problem.errors;
506
- this.extensions = init.extensions ?? extractProblemExtensions(init.problem);
507
- this.requestId = init.requestId ?? init.problem.trace_id;
508
- this.retryAfterSeconds = init.retryAfterSeconds;
509
- }
510
- };
511
-
512
- // src/client/batch-empty-error.ts
513
- var BatchEmptyError = class extends Cip309HttpError {
514
- constructor(init) {
515
- super(init);
516
- this.name = "BatchEmptyError";
517
- }
518
- };
519
-
520
- // src/client/batch-too-large-error.ts
521
- function readInt(value) {
522
- return typeof value === "number" && Number.isFinite(value) ? value : void 0;
523
- }
524
- var BatchTooLargeError = class extends Cip309HttpError {
525
- max;
526
- got;
527
- constructor(init) {
528
- super(init);
529
- this.name = "BatchTooLargeError";
530
- this.max = readInt(this.extensions["max"]);
531
- this.got = readInt(this.extensions["got"]);
532
- }
429
+ const nttZetas = getZettas();
430
+ const field = {
431
+ add: (a, b) => mod((a | 0) + (b | 0)) | 0,
432
+ sub: (a, b) => mod((a | 0) - (b | 0)) | 0,
433
+ mul: (a, b) => mod((a | 0) * (b | 0)) | 0,
434
+ inv: (_a) => {
435
+ throw new Error("not implemented");
436
+ }
437
+ };
438
+ const nttOpts = {
439
+ N: N2,
440
+ roots: nttZetas,
441
+ invertButterflies: true,
442
+ skipStages: 1 ,
443
+ brp: false
444
+ };
445
+ const dif = FFTCore(field, { dit: false, ...nttOpts });
446
+ const dit = FFTCore(field, { dit: true, ...nttOpts });
447
+ const NTT = {
448
+ encode: (r) => {
449
+ return dif(r);
450
+ },
451
+ decode: (r) => {
452
+ dit(r);
453
+ for (let i = 0; i < r.length; i++)
454
+ r[i] = mod(F2 * r[i]);
455
+ return r;
456
+ }
457
+ };
458
+ const bitsCoder = (d, c) => {
459
+ const mask = getMask(d);
460
+ const bytesLen = d * (N2 / 8);
461
+ return {
462
+ bytesLen,
463
+ encode: (poly_) => {
464
+ const poly = poly_;
465
+ const r = new Uint8Array(bytesLen);
466
+ for (let i = 0, buf = 0, bufLen = 0, pos = 0; i < poly.length; i++) {
467
+ buf |= (c.encode(poly[i]) & mask) << bufLen;
468
+ bufLen += d;
469
+ for (; bufLen >= 8; bufLen -= 8, buf >>= 8)
470
+ r[pos++] = buf & getMask(bufLen);
471
+ }
472
+ return r;
473
+ },
474
+ decode: (bytes) => {
475
+ const r = newPoly(N2);
476
+ for (let i = 0, buf = 0, bufLen = 0, pos = 0; i < bytes.length; i++) {
477
+ buf |= bytes[i] << bufLen;
478
+ bufLen += 8;
479
+ for (; bufLen >= d; bufLen -= d, buf >>= d)
480
+ r[pos++] = c.decode(buf & mask);
481
+ }
482
+ return r;
483
+ }
484
+ };
485
+ };
486
+ return {
487
+ mod,
488
+ smod,
489
+ nttZetas,
490
+ NTT: {
491
+ encode: (r) => NTT.encode(r),
492
+ decode: (r) => NTT.decode(r)
493
+ },
494
+ bitsCoder
495
+ };
533
496
  };
534
-
535
- // src/client/forbidden-error.ts
536
- var ForbiddenError = class extends Cip309HttpError {
537
- constructor(init) {
538
- super(init);
539
- this.name = "ForbiddenError";
540
- }
497
+ var createXofShake = (shake) => (seed, blockLen) => {
498
+ if (!blockLen)
499
+ blockLen = shake.blockLen;
500
+ const _seed = new Uint8Array(seed.length + 2);
501
+ _seed.set(seed);
502
+ const seedLen = seed.length;
503
+ const buf = new Uint8Array(blockLen);
504
+ let h = shake.create({});
505
+ let calls = 0;
506
+ let xofs = 0;
507
+ return {
508
+ stats: () => ({ calls, xofs }),
509
+ get: (x, y) => {
510
+ _seed[seedLen + 0] = x;
511
+ _seed[seedLen + 1] = y;
512
+ h.destroy();
513
+ h = shake.create({}).update(_seed);
514
+ calls++;
515
+ return () => {
516
+ xofs++;
517
+ return h.xofInto(buf);
518
+ };
519
+ },
520
+ clean: () => {
521
+ h.destroy();
522
+ cleanBytes(buf, _seed);
523
+ }
524
+ };
541
525
  };
526
+ var XOF128 = /* @__PURE__ */ createXofShake(shake128);
542
527
 
543
- // src/client/idempotency-conflict-error.ts
544
- var IdempotencyConflictError = class extends Cip309HttpError {
545
- constructor(init) {
546
- super(init);
547
- this.name = "IdempotencyConflictError";
548
- }
528
+ // ../../node_modules/.pnpm/@noble+post-quantum@0.6.1/node_modules/@noble/post-quantum/ml-kem.js
529
+ var N = 256;
530
+ var Q = 3329;
531
+ var F = 3303;
532
+ var ROOT_OF_UNITY = 17;
533
+ var crystals = /* @__PURE__ */ genCrystals({
534
+ N,
535
+ Q,
536
+ F,
537
+ ROOT_OF_UNITY,
538
+ newPoly: (n) => new Uint16Array(n),
539
+ brvBits: 7});
540
+ var PARAMS = /* @__PURE__ */ (() => Object.freeze({
541
+ 512: Object.freeze({ N, Q, K: 2, ETA1: 3, ETA2: 2, du: 10, dv: 4, RBGstrength: 128 }),
542
+ 768: Object.freeze({ N, Q, K: 3, ETA1: 2, ETA2: 2, du: 10, dv: 4, RBGstrength: 192 }),
543
+ 1024: Object.freeze({ N, Q, K: 4, ETA1: 2, ETA2: 2, du: 11, dv: 5, RBGstrength: 256 })
544
+ }))();
545
+ var compress = (d) => {
546
+ if (d >= 12)
547
+ return { encode: (i) => i, decode: (i) => i >= Q ? i - Q : i };
548
+ const a = 2 ** (d - 1);
549
+ return {
550
+ // This only matches standalone Compress_d after bitsCoder masks the result into Z_(2^d).
551
+ encode: (i) => ((i << d) + Q / 2) / Q,
552
+ // const decompress = (i: number) => round((Q / 2 ** d) * i);
553
+ decode: (i) => i * Q + a >>> d
554
+ };
549
555
  };
550
-
551
- // src/client/insufficient-funds-error.ts
552
- function readBigIntString(value) {
553
- if (typeof value !== "string") return void 0;
554
- if (!/^-?[0-9]+$/.test(value)) return void 0;
555
- try {
556
- return BigInt(value);
557
- } catch {
558
- return void 0;
559
- }
556
+ var byteCoder = (d) => crystals.bitsCoder(d, { encode: (i) => i, decode: (i) => i >= Q ? i - Q : i } );
557
+ var polyCoder = (d) => d === 12 ? byteCoder(12) : crystals.bitsCoder(d, compress(d));
558
+ function polyAdd(a_, b_) {
559
+ const a = a_;
560
+ const b = b_;
561
+ for (let i = 0; i < N; i++)
562
+ a[i] = crystals.mod(a[i] + b[i]);
560
563
  }
561
- function readString(value) {
562
- return typeof value === "string" ? value : void 0;
564
+ function polySub(a_, b_) {
565
+ const a = a_;
566
+ const b = b_;
567
+ for (let i = 0; i < N; i++)
568
+ a[i] = crystals.mod(a[i] - b[i]);
563
569
  }
564
- var InsufficientFundsError = class extends Cip309HttpError {
565
- balanceUsdMicros;
566
- requiredUsdMicros;
567
- topUpUrl;
568
- constructor(init) {
569
- super(init);
570
- this.name = "InsufficientFundsError";
571
- this.balanceUsdMicros = readBigIntString(this.extensions["balance_usd_micros"]);
572
- this.requiredUsdMicros = readBigIntString(this.extensions["required_usd_micros"]);
573
- this.topUpUrl = readString(this.extensions["top_up_url"]);
574
- }
575
- };
576
-
577
- // src/client/insufficient-scope-error.ts
578
- function readScopeArray(value) {
579
- if (!Array.isArray(value)) return [];
580
- return value.filter((entry) => typeof entry === "string");
570
+ function BaseCaseMultiply(a0, a1, b0, b1, zeta) {
571
+ const c0 = crystals.mod(a1 * b1 * zeta + a0 * b0);
572
+ const c1 = crystals.mod(a0 * b1 + a1 * b0);
573
+ return { c0, c1 };
581
574
  }
582
- var InsufficientScopeError = class extends Cip309HttpError {
583
- requiredScopes;
584
- grantedScopes;
585
- constructor(init) {
586
- super(init);
587
- this.name = "InsufficientScopeError";
588
- this.requiredScopes = readScopeArray(this.extensions["required"]);
589
- this.grantedScopes = readScopeArray(this.extensions["granted"]);
590
- }
591
- /** Convenience for the single-scope case; first entry of `requiredScopes`. */
592
- get requiredScope() {
593
- return this.requiredScopes[0];
575
+ function MultiplyNTTs(f_, g_) {
576
+ const f = f_;
577
+ const g = g_;
578
+ for (let i = 0; i < N / 2; i++) {
579
+ let z3 = crystals.nttZetas[64 + (i >> 1)];
580
+ if (i & 1)
581
+ z3 = -z3;
582
+ const { c0, c1 } = BaseCaseMultiply(f[2 * i + 0], f[2 * i + 1], g[2 * i + 0], g[2 * i + 1], z3);
583
+ f[2 * i + 0] = c0;
584
+ f[2 * i + 1] = c1;
594
585
  }
595
- };
596
-
597
- // src/client/internal-server-error.ts
598
- var InternalServerError = class extends Cip309HttpError {
599
- constructor(init) {
600
- super(init);
601
- this.name = "InternalServerError";
586
+ return f;
587
+ }
588
+ function SampleNTT(xof_) {
589
+ const xof = xof_;
590
+ const r = new Uint16Array(N);
591
+ for (let j = 0; j < N; ) {
592
+ const b = xof();
593
+ if (b.length % 3)
594
+ throw new Error("SampleNTT: unaligned block");
595
+ for (let i = 0; j < N && i + 3 <= b.length; i += 3) {
596
+ const d1 = (b[i + 0] >> 0 | b[i + 1] << 8) & 4095;
597
+ const d2 = (b[i + 1] >> 4 | b[i + 2] << 4) & 4095;
598
+ if (d1 < Q)
599
+ r[j++] = d1;
600
+ if (j < N && d2 < Q)
601
+ r[j++] = d2;
602
+ }
602
603
  }
603
- };
604
-
605
- // src/client/invalid-body-error.ts
606
- var InvalidBodyError = class extends Cip309HttpError {
607
- constructor(init) {
608
- super(init);
609
- this.name = "InvalidBodyError";
610
- }
611
- };
612
-
613
- // src/client/malformed-cbor-error.ts
614
- var MalformedCborError = class extends Cip309HttpError {
615
- constructor(init) {
616
- super(init);
617
- this.name = "MalformedCborError";
618
- }
619
- };
620
-
621
- // src/client/not-found-error.ts
622
- var NotFoundError = class extends Cip309HttpError {
623
- constructor(init) {
624
- super(init);
625
- this.name = "NotFoundError";
626
- }
627
- };
628
-
629
- // src/client/quote-already-consumed-error.ts
630
- function readString2(value) {
631
- return typeof value === "string" ? value : void 0;
604
+ return r;
632
605
  }
633
- var QuoteAlreadyConsumedError = class extends Cip309HttpError {
634
- quoteId;
635
- constructor(init) {
636
- super(init);
637
- this.name = "QuoteAlreadyConsumedError";
638
- this.quoteId = readString2(this.extensions["quote_id"]);
606
+ var sampleCBDBytes = (buf, eta) => {
607
+ const r = new Uint16Array(N);
608
+ const b32 = u32(buf);
609
+ swap32IfBE(b32);
610
+ let len = 0;
611
+ for (let i = 0, p = 0, bb = 0, t0 = 0; i < b32.length; i++) {
612
+ let b = b32[i];
613
+ for (let j = 0; j < 32; j++) {
614
+ bb += b & 1;
615
+ b >>= 1;
616
+ len += 1;
617
+ if (len === eta) {
618
+ t0 = bb;
619
+ bb = 0;
620
+ } else if (len === 2 * eta) {
621
+ r[p++] = crystals.mod(t0 - bb);
622
+ bb = 0;
623
+ len = 0;
624
+ }
625
+ }
639
626
  }
627
+ swap32IfBE(b32);
628
+ if (len)
629
+ throw new Error(`sampleCBD: leftover bits: ${len}`);
630
+ return r;
640
631
  };
641
-
642
- // src/client/quote-expired-error.ts
643
- function readString3(value) {
644
- return typeof value === "string" ? value : void 0;
632
+ function sampleCBD(PRF_, seed, nonce, eta) {
633
+ const PRF = PRF_;
634
+ return sampleCBDBytes(PRF(eta * N / 4, seed, nonce), eta);
645
635
  }
646
- var QuoteExpiredError = class extends Cip309HttpError {
647
- quoteId;
648
- constructor(init) {
649
- super(init);
650
- this.name = "QuoteExpiredError";
651
- this.quoteId = readString3(this.extensions["quote_id"]);
652
- }
636
+ var genKPKE = (opts_) => {
637
+ const opts2 = opts_;
638
+ const { K, PRF, XOF, HASH512, ETA1, ETA2, du, dv } = opts2;
639
+ const poly1 = polyCoder(1);
640
+ const polyV = polyCoder(dv);
641
+ const polyU = polyCoder(du);
642
+ const publicCoder = splitCoder("publicKey", vecCoder(polyCoder(12), K), 32);
643
+ const secretCoder = vecCoder(polyCoder(12), K);
644
+ const cipherCoder = splitCoder("ciphertext", vecCoder(polyU, K), polyV);
645
+ const seedCoder = splitCoder("seed", 32, 32);
646
+ return {
647
+ secretCoder,
648
+ lengths: {
649
+ secretKey: secretCoder.bytesLen,
650
+ publicKey: publicCoder.bytesLen,
651
+ cipherText: cipherCoder.bytesLen
652
+ },
653
+ keygen: (seed) => {
654
+ abytesDoc(seed, 32, "seed");
655
+ const seedDst = new Uint8Array(33);
656
+ seedDst.set(seed);
657
+ seedDst[32] = K;
658
+ const seedHash = HASH512(seedDst);
659
+ const [rho, sigma] = seedCoder.decode(seedHash);
660
+ const sHat = [];
661
+ const tHat = [];
662
+ for (let i = 0; i < K; i++)
663
+ sHat.push(crystals.NTT.encode(sampleCBD(PRF, sigma, i, ETA1)));
664
+ const x = XOF(rho);
665
+ for (let i = 0; i < K; i++) {
666
+ const e = crystals.NTT.encode(sampleCBD(PRF, sigma, K + i, ETA1));
667
+ for (let j = 0; j < K; j++) {
668
+ const aji = SampleNTT(x.get(j, i));
669
+ polyAdd(e, MultiplyNTTs(aji, sHat[j]));
670
+ }
671
+ tHat.push(e);
672
+ }
673
+ x.clean();
674
+ const res = {
675
+ publicKey: publicCoder.encode([tHat, rho]),
676
+ secretKey: secretCoder.encode(sHat)
677
+ };
678
+ cleanBytes(rho, sigma, sHat, tHat, seedDst, seedHash);
679
+ return res;
680
+ },
681
+ encrypt: (publicKey, msg, seed) => {
682
+ const [tHat, rho] = publicCoder.decode(publicKey);
683
+ const rHat = [];
684
+ for (let i = 0; i < K; i++)
685
+ rHat.push(crystals.NTT.encode(sampleCBD(PRF, seed, i, ETA1)));
686
+ const x = XOF(rho);
687
+ const tmp2 = new Uint16Array(N);
688
+ const u = [];
689
+ for (let i = 0; i < K; i++) {
690
+ const e1 = sampleCBD(PRF, seed, K + i, ETA2);
691
+ const tmp = new Uint16Array(N);
692
+ for (let j = 0; j < K; j++) {
693
+ const aij = SampleNTT(x.get(i, j));
694
+ polyAdd(tmp, MultiplyNTTs(aij, rHat[j]));
695
+ }
696
+ polyAdd(e1, crystals.NTT.decode(tmp));
697
+ u.push(e1);
698
+ polyAdd(tmp2, MultiplyNTTs(tHat[i], rHat[i]));
699
+ cleanBytes(tmp);
700
+ }
701
+ x.clean();
702
+ const e2 = sampleCBD(PRF, seed, 2 * K, ETA2);
703
+ polyAdd(e2, crystals.NTT.decode(tmp2));
704
+ const v = poly1.decode(msg);
705
+ polyAdd(v, e2);
706
+ cleanBytes(tHat, rHat, tmp2, e2);
707
+ return cipherCoder.encode([u, v]);
708
+ },
709
+ decrypt: (cipherText, privateKey) => {
710
+ const [u, v] = cipherCoder.decode(cipherText);
711
+ const sk = secretCoder.decode(privateKey);
712
+ const tmp = new Uint16Array(N);
713
+ for (let i = 0; i < K; i++)
714
+ polyAdd(tmp, MultiplyNTTs(sk[i], crystals.NTT.encode(u[i])));
715
+ polySub(v, crystals.NTT.decode(tmp));
716
+ cleanBytes(tmp, sk, u);
717
+ return poly1.encode(v);
718
+ }
719
+ };
653
720
  };
654
-
655
- // src/client/quote-not-found-error.ts
656
- function readString4(value) {
657
- return typeof value === "string" ? value : void 0;
721
+ function createKyber(opts2) {
722
+ const rawOpts = opts2;
723
+ const KPKE = genKPKE(rawOpts);
724
+ const { HASH256, HASH512, KDF } = rawOpts;
725
+ const { secretCoder: KPKESecretCoder, lengths } = KPKE;
726
+ const secretCoder = splitCoder("secretKey", lengths.secretKey, lengths.publicKey, 32, 32);
727
+ const msgLen = 32;
728
+ const seedLen = 64;
729
+ const kemLengths = Object.freeze({
730
+ ...lengths,
731
+ seed: 64,
732
+ msg: msgLen,
733
+ msgRand: msgLen,
734
+ secretKey: secretCoder.bytesLen
735
+ });
736
+ return Object.freeze({
737
+ info: Object.freeze({ type: "ml-kem" }),
738
+ lengths: kemLengths,
739
+ keygen: (seed = randomBytes(seedLen)) => {
740
+ abytesDoc(seed, seedLen, "seed");
741
+ const { publicKey, secretKey: sk } = KPKE.keygen(seed.subarray(0, 32));
742
+ const publicKeyHash = HASH256(publicKey);
743
+ const secretKey = secretCoder.encode([sk, publicKey, publicKeyHash, seed.subarray(32)]);
744
+ cleanBytes(sk, publicKeyHash);
745
+ return {
746
+ publicKey,
747
+ secretKey
748
+ };
749
+ },
750
+ getPublicKey: (secretKey) => {
751
+ const [_sk, publicKey, _publicKeyHash, _z] = secretCoder.decode(secretKey);
752
+ return Uint8Array.from(publicKey);
753
+ },
754
+ encapsulate: (publicKey, msg = randomBytes(msgLen)) => {
755
+ abytesDoc(publicKey, lengths.publicKey, "publicKey");
756
+ abytesDoc(msg, msgLen, "message");
757
+ const eke = publicKey.subarray(0, 384 * opts2.K);
758
+ const ek = KPKESecretCoder.encode(KPKESecretCoder.decode(copyBytes(eke)));
759
+ if (!equalBytes(ek, eke)) {
760
+ cleanBytes(ek);
761
+ throw new Error("ML-KEM.encapsulate: wrong publicKey modulus");
762
+ }
763
+ cleanBytes(ek);
764
+ const kr = HASH512.create().update(msg).update(HASH256(publicKey)).digest();
765
+ const cipherText = KPKE.encrypt(publicKey, msg, kr.subarray(32, 64));
766
+ cleanBytes(kr.subarray(32));
767
+ return {
768
+ cipherText,
769
+ sharedSecret: kr.subarray(0, 32)
770
+ };
771
+ },
772
+ decapsulate: (cipherText, secretKey) => {
773
+ abytesDoc(secretKey, secretCoder.bytesLen, "secretKey");
774
+ abytesDoc(cipherText, lengths.cipherText, "cipherText");
775
+ const k768 = secretCoder.bytesLen - 96;
776
+ const start = k768 + 32;
777
+ const test = HASH256(secretKey.subarray(k768 / 2, start));
778
+ if (!equalBytes(test, secretKey.subarray(start, start + 32)))
779
+ throw new Error("invalid secretKey: hash check failed");
780
+ const [sk, publicKey, publicKeyHash, z3] = secretCoder.decode(secretKey);
781
+ const msg = KPKE.decrypt(cipherText, sk);
782
+ const kr = HASH512.create().update(msg).update(publicKeyHash).digest();
783
+ const Khat = kr.subarray(0, 32);
784
+ const cipherText2 = KPKE.encrypt(publicKey, msg, kr.subarray(32, 64));
785
+ const isValid = equalBytes(cipherText, cipherText2);
786
+ const Kbar = KDF.create({ dkLen: 32 }).update(z3).update(cipherText).digest();
787
+ cleanBytes(msg, cipherText2, !isValid ? Khat : Kbar);
788
+ return isValid ? Khat : Kbar;
789
+ }
790
+ });
658
791
  }
659
- var QuoteNotFoundError = class extends Cip309HttpError {
660
- quoteId;
661
- constructor(init) {
662
- super(init);
663
- this.name = "QuoteNotFoundError";
664
- this.quoteId = readString4(this.extensions["quote_id"]);
665
- }
666
- };
667
-
668
- // src/client/rate-limited-error.ts
669
- var RateLimitedError = class extends Cip309HttpError {
670
- constructor(init) {
671
- super(init);
672
- this.name = "RateLimitedError";
673
- }
674
- };
792
+ function shakePRF(dkLen, key, nonce) {
793
+ return shake256.create({ dkLen }).update(key).update(new Uint8Array([nonce])).digest();
794
+ }
795
+ var opts = /* @__PURE__ */ (() => ({
796
+ HASH256: sha3_256,
797
+ HASH512: sha3_512,
798
+ KDF: shake256,
799
+ XOF: XOF128,
800
+ PRF: shakePRF
801
+ }))();
802
+ var mk = (params) => createKyber({
803
+ ...opts,
804
+ ...params
805
+ });
806
+ var ml_kem768 = /* @__PURE__ */ (() => mk(PARAMS[768]))();
675
807
 
676
- // src/client/record-not-found-error.ts
677
- var RecordNotFoundError = class extends Cip309HttpError {
678
- constructor(init) {
679
- super(init);
680
- this.name = "RecordNotFoundError";
681
- }
682
- };
683
-
684
- // src/client/service-unavailable-error.ts
685
- var ServiceUnavailableError = class extends Cip309HttpError {
686
- constructor(init) {
687
- super(init);
688
- this.name = "ServiceUnavailableError";
689
- }
690
- };
691
-
692
- // src/client/unauthorized-error.ts
693
- var UnauthorizedError = class extends Cip309HttpError {
694
- constructor(init) {
695
- super(init);
696
- this.name = "UnauthorizedError";
697
- }
698
- };
699
-
700
- // src/client/validation-failed-error.ts
701
- var ValidationFailedError = class extends Cip309HttpError {
702
- constructor(init) {
703
- super(init);
704
- this.name = "ValidationFailedError";
705
- }
706
- };
707
-
708
- // src/client/parse-http-error.ts
709
- function asString(value) {
710
- return typeof value === "string" ? value : void 0;
711
- }
712
- function asNumber(value) {
713
- return typeof value === "number" && Number.isFinite(value) ? value : void 0;
714
- }
715
- function asProblemErrorEntries(value) {
716
- if (!Array.isArray(value)) return void 0;
717
- const out = [];
718
- for (const entry of value) {
719
- if (entry === null || typeof entry !== "object") continue;
720
- const e = entry;
721
- out.push({
722
- field: typeof e["field"] === "string" ? e["field"] : "",
723
- code: typeof e["code"] === "string" ? e["code"] : "",
724
- detail: typeof e["detail"] === "string" ? e["detail"] : ""
725
- });
808
+ // ../../node_modules/.pnpm/@noble+post-quantum@0.6.1/node_modules/@noble/post-quantum/hybrid.js
809
+ function ecKeygen(curve, allowZeroKey = false) {
810
+ const lengths = curve.lengths;
811
+ let keygen = curve.keygen;
812
+ if (allowZeroKey) {
813
+ if (!("getSharedSecret" in curve && "sign" in curve && "verify" in curve))
814
+ throw new Error("allowZeroKey requires a Weierstrass curve");
815
+ const wCurve = curve;
816
+ const Fn = wCurve.Point.Fn;
817
+ keygen = (seed = randomBytes(lengths.seed)) => {
818
+ abytes(seed, lengths.seed, "seed");
819
+ const seedScalar = Fn.isLE ? bytesToNumberLE(seed) : bytesToNumberBE(seed);
820
+ const secretKey = Fn.toBytes(Fn.create(seedScalar));
821
+ return {
822
+ secretKey,
823
+ publicKey: curve.getPublicKey(secretKey)
824
+ };
825
+ };
726
826
  }
727
- return out;
728
- }
729
- function synthesiseProblem(httpStatus, requestId) {
730
- const code = `http-${httpStatus}`;
731
827
  return {
732
- type: `about:blank`,
733
- title: `HTTP ${httpStatus}`,
734
- status: httpStatus,
735
- detail: `Server returned HTTP ${httpStatus} without a problem+json body.`,
736
- code,
737
- trace_id: requestId ?? ""
738
- };
739
- }
740
- function toProblemDetails(httpStatus, body, requestId) {
741
- if (body === null || typeof body !== "object") {
742
- return synthesiseProblem(httpStatus, requestId);
743
- }
744
- const b = body;
745
- const code = asString(b["code"]);
746
- const status = asNumber(b["status"]) ?? httpStatus;
747
- const title = asString(b["title"]);
748
- if (code === void 0 && title === void 0) {
749
- return synthesiseProblem(httpStatus, requestId);
750
- }
751
- const errors = asProblemErrorEntries(b["errors"]);
752
- const base = {
753
- ...b,
754
- // RFC 7807 §4.2: `about:blank` is the default when no type URI is supplied.
755
- // The client is gateway-agnostic, so it must not invent a vendor-specific
756
- // problem-type namespace; the machine-readable discriminator is `code`.
757
- type: asString(b["type"]) ?? "about:blank",
758
- title: title ?? `HTTP ${status}`,
759
- status,
760
- detail: asString(b["detail"]) ?? "",
761
- code: code ?? `http-${status}`,
762
- trace_id: asString(b["trace_id"]) ?? requestId ?? ""
828
+ lengths: { secretKey: lengths.secretKey, publicKey: lengths.publicKey, seed: lengths.seed },
829
+ keygen: (seed) => keygen(seed),
830
+ getPublicKey: (secretKey) => curve.getPublicKey(secretKey)
763
831
  };
764
- if (errors !== void 0) base["errors"] = errors;
765
- return base;
766
832
  }
767
- function parseHttpError(args) {
768
- const problem = toProblemDetails(args.httpStatus, args.body, args.requestId);
769
- const extensions = extractProblemExtensions(problem);
770
- const init = {
771
- problem,
772
- extensions,
773
- requestId: args.requestId,
774
- retryAfterSeconds: args.retryAfterSeconds
833
+ function ecdhKem(curve, allowZeroKey = false) {
834
+ const kg = ecKeygen(curve, allowZeroKey);
835
+ if (!curve.getSharedSecret)
836
+ throw new Error("wrong curve");
837
+ return {
838
+ lengths: { ...kg.lengths, msg: kg.lengths.seed, cipherText: kg.lengths.publicKey },
839
+ keygen: kg.keygen,
840
+ getPublicKey: kg.getPublicKey,
841
+ encapsulate(publicKey, rand = randomBytes(curve.lengths.seed)) {
842
+ const seed = copyBytes(rand);
843
+ let ek = void 0;
844
+ try {
845
+ ek = this.keygen(seed).secretKey;
846
+ const sharedSecret = this.decapsulate(publicKey, ek);
847
+ const cipherText = curve.getPublicKey(ek);
848
+ return { sharedSecret, cipherText };
849
+ } finally {
850
+ cleanBytes(seed);
851
+ if (ek)
852
+ cleanBytes(ek);
853
+ }
854
+ },
855
+ decapsulate(cipherText, secretKey) {
856
+ const res = curve.getSharedSecret(secretKey, cipherText);
857
+ return curve.lengths.publicKeyHasPrefix ? res.subarray(1) : res;
858
+ }
775
859
  };
776
- switch (problem.code) {
777
- case "unauthorized":
778
- return new UnauthorizedError(init);
779
- case "forbidden":
780
- case "csrf-invalid":
781
- return new ForbiddenError(init);
782
- case "insufficient-scope":
783
- return new InsufficientScopeError(init);
784
- case "insufficient-funds":
785
- return new InsufficientFundsError(init);
786
- case "quote-expired":
787
- return new QuoteExpiredError(init);
788
- case "quote-not-found":
789
- return new QuoteNotFoundError(init);
790
- case "quote-already-consumed":
791
- return new QuoteAlreadyConsumedError(init);
792
- case "not-found":
793
- return new NotFoundError(init);
794
- case "record-not-found":
795
- return new RecordNotFoundError(init);
796
- case "idempotency-key-conflict":
797
- return new IdempotencyConflictError(init);
798
- case "rate-limited":
799
- return new RateLimitedError(init);
800
- case "validation-failed":
801
- return new ValidationFailedError(init);
802
- case "invalid-body":
803
- return new InvalidBodyError(init);
804
- case "malformed-cbor":
805
- return new MalformedCborError(init);
806
- case "batch-too-large":
807
- return new BatchTooLargeError(init);
808
- case "batch-empty":
809
- return new BatchEmptyError(init);
810
- case "internal-error":
811
- return new InternalServerError(init);
812
- // A gateway that prices on a live FX oracle may surface a transient
813
- // `fx-stale` pricing outage; to a vendor-neutral client that is just a
814
- // temporary inability to serve, i.e. a service-unavailable condition.
815
- case "service-unavailable":
816
- case "fx-stale":
817
- return new ServiceUnavailableError(init);
818
- default:
819
- return new Cip309HttpError(init);
820
- }
821
- }
822
-
823
- // src/client/http-helpers.ts
824
- async function readJson(response) {
825
- const text = await response.text();
826
- if (text.length === 0) return null;
827
- try {
828
- return JSON.parse(text);
829
- } catch {
830
- return null;
831
- }
832
860
  }
833
- function parseRetryAfter(header) {
834
- if (header === null) return void 0;
835
- const parsed = Number(header);
836
- return Number.isFinite(parsed) ? parsed : void 0;
837
- }
838
- async function throwIfNotOk(response) {
839
- if (response.ok) return;
840
- const body = await readJson(response);
841
- const requestId = response.headers.get("x-request-id") ?? void 0;
842
- const retryAfterSeconds = parseRetryAfter(response.headers.get("retry-after"));
843
- throw parseHttpError({ httpStatus: response.status, body, requestId, retryAfterSeconds });
861
+ function splitLengths(lst, name) {
862
+ return splitCoder(name, ...lst.map((i) => {
863
+ if (typeof i.lengths[name] !== "number")
864
+ throw new Error("wrong length: " + name);
865
+ return i.lengths[name];
866
+ }));
844
867
  }
845
-
846
- // src/client/account.ts
847
- function buildHeaders(apiKey) {
848
- const headers = new Headers({
849
- "content-type": "application/json",
850
- accept: "application/json"
851
- });
852
- if (apiKey !== void 0) headers.set("authorization", `Bearer ${apiKey}`);
853
- return headers;
868
+ function expandSeedXof(xof) {
869
+ return ((seed, seedLen) => xof(seed, { dkLen: seedLen }));
854
870
  }
855
- var AccountNamespace = class {
856
- config;
857
- constructor(config) {
858
- this.config = config;
871
+ function combineKeys(realSeedLen, expandSeed_, ...ck_) {
872
+ const expandSeed = expandSeed_;
873
+ const ck = ck_;
874
+ const seedCoder = splitLengths(ck, "seed");
875
+ const pkCoder = splitLengths(ck, "publicKey");
876
+ anumber(realSeedLen);
877
+ function expandDecapsulationKey(seed) {
878
+ abytes(seed, realSeedLen);
879
+ const expandedRaw = expandSeed(seed, seedCoder.bytesLen);
880
+ const expandedSeed = expandedRaw.buffer === seed.buffer ? copyBytes(expandedRaw) : expandedRaw;
881
+ const expanded = [];
882
+ const keySecret = [];
883
+ const secretKey = [];
884
+ const publicKey = [];
885
+ let ok = false;
886
+ try {
887
+ for (const part of seedCoder.decode(expandedSeed))
888
+ expanded.push(copyBytes(part));
889
+ for (let i = 0; i < ck.length; i++) {
890
+ const keys = ck[i].keygen(expanded[i]);
891
+ keySecret.push(keys.secretKey);
892
+ secretKey.push(copyBytes(keys.secretKey));
893
+ publicKey.push(keys.publicKey);
894
+ }
895
+ ok = true;
896
+ return { secretKey, publicKey };
897
+ } finally {
898
+ cleanBytes(expandedSeed, expanded, keySecret);
899
+ if (!ok)
900
+ cleanBytes(secretKey);
901
+ }
859
902
  }
860
- /**
861
- * Fetch the caller's current prepaid USD balance.
862
- *
863
- * Returns `{ balanceUsdMicros }`, the gateway's `balance_usd_micros` field
864
- * (USD micro-cents as a decimal string). The string is preserved verbatim —
865
- * never parsed into a number — so no precision is lost. An account with no
866
- * ledger activity yet reads `"0"`.
867
- *
868
- * Requires authentication: 401 (UnauthorizedError) when anonymous, 403
869
- * (InsufficientScopeError) when the Bearer key lacks the `account:read`
870
- * scope.
871
- */
872
- async balance() {
873
- const response = await this.config.fetch(`${this.config.baseUrl}/api/v1/account/balance`, {
874
- method: "GET",
875
- headers: buildHeaders(this.config.apiKey)
876
- });
877
- await throwIfNotOk(response);
878
- const body = await readJson(response);
879
- return { balanceUsdMicros: body.balance_usd_micros };
903
+ return {
904
+ info: { lengths: { seed: realSeedLen, publicKey: pkCoder.bytesLen, secretKey: realSeedLen } },
905
+ getPublicKey(secretKey) {
906
+ return this.keygen(secretKey).publicKey;
907
+ },
908
+ keygen(seed = randomBytes(realSeedLen)) {
909
+ const { publicKey: pk, secretKey } = expandDecapsulationKey(seed);
910
+ try {
911
+ const publicKey = pkCoder.encode(pk);
912
+ return { secretKey: seed, publicKey };
913
+ } finally {
914
+ cleanBytes(pk);
915
+ cleanBytes(secretKey);
916
+ }
917
+ },
918
+ expandDecapsulationKey,
919
+ realSeedLen
920
+ };
921
+ }
922
+ function combineKEMS(realSeedLen, realMsgLen, expandSeed, combiner, ...kems) {
923
+ const rawCombiner = combiner;
924
+ const rawKems = kems;
925
+ const keys = combineKeys(realSeedLen, expandSeed, ...rawKems);
926
+ const ctCoder = splitLengths(rawKems, "cipherText");
927
+ const pkCoder = splitLengths(rawKems, "publicKey");
928
+ const msgCoder = splitLengths(rawKems, "msg");
929
+ anumber(realMsgLen);
930
+ const lengths = Object.freeze({
931
+ ...keys.info.lengths,
932
+ msg: realMsgLen,
933
+ msgRand: msgCoder.bytesLen,
934
+ cipherText: ctCoder.bytesLen
935
+ });
936
+ return Object.freeze({
937
+ lengths,
938
+ getPublicKey: keys.getPublicKey,
939
+ keygen: keys.keygen,
940
+ encapsulate(pk, randomness = randomBytes(msgCoder.bytesLen)) {
941
+ const pks = pkCoder.decode(pk);
942
+ const rand = msgCoder.decode(randomness);
943
+ const sharedSecret = [];
944
+ const cipherText = [];
945
+ try {
946
+ for (let i = 0; i < rawKems.length; i++) {
947
+ const enc = rawKems[i].encapsulate(pks[i], rand[i]);
948
+ sharedSecret.push(enc.sharedSecret);
949
+ cipherText.push(enc.cipherText);
950
+ }
951
+ return {
952
+ // Detach the combiner result before cleanup: a caller-provided combiner may alias one of
953
+ // the child sharedSecret buffers, and those child buffers are zeroized immediately below.
954
+ sharedSecret: copyBytes(rawCombiner(pks, cipherText, sharedSecret)),
955
+ cipherText: ctCoder.encode(cipherText)
956
+ };
957
+ } finally {
958
+ cleanBytes(sharedSecret, cipherText);
959
+ }
960
+ },
961
+ decapsulate(ct, seed) {
962
+ const cts = ctCoder.decode(ct);
963
+ const { publicKey, secretKey } = keys.expandDecapsulationKey(seed);
964
+ const sharedSecret = rawKems.map((i, j) => i.decapsulate(cts[j], secretKey[j]));
965
+ try {
966
+ return copyBytes(rawCombiner(publicKey, cts, sharedSecret));
967
+ } finally {
968
+ cleanBytes(secretKey, sharedSecret);
969
+ }
970
+ }
971
+ });
972
+ }
973
+ var x25519kem = /* @__PURE__ */ ecdhKem(x25519);
974
+ var ml_kem768_x25519 = /* @__PURE__ */ (() => combineKEMS(
975
+ 32,
976
+ 32,
977
+ expandSeedXof(shake256),
978
+ // Awesome label, so much escaping hell in a single line.
979
+ (pk, ct, ss) => sha3_256(concatBytes(ss[0], ss[1], ct[1], pk[1], asciiToBytes("\\.//^\\"))),
980
+ ml_kem768,
981
+ x25519kem
982
+ ))();
983
+ var XWing = /* @__PURE__ */ (() => ml_kem768_x25519)();
984
+ function chacha20Poly1305Encrypt(opts2) {
985
+ return chacha20poly1305(opts2.key, opts2.nonce, opts2.aad).encrypt(opts2.plaintext);
986
+ }
987
+ function xchacha20Poly1305Encrypt(opts2) {
988
+ return xchacha20poly1305(opts2.key, opts2.nonce, opts2.aad).encrypt(opts2.plaintext);
989
+ }
990
+ function hkdfSha256(opts2) {
991
+ return hkdf(sha256$1, opts2.ikm, opts2.salt, opts2.info, opts2.length);
992
+ }
993
+ var MLKEM768X25519_PUBLIC_KEY_LENGTH = 1216;
994
+ var MLKEM768X25519_ENC_LENGTH = 1120;
995
+ var MLKEM768X25519_ESEED_LENGTH = 64;
996
+ function mlkem768x25519Encapsulate(opts2) {
997
+ if (opts2.publicKey.length !== MLKEM768X25519_PUBLIC_KEY_LENGTH) {
998
+ throw new Error(
999
+ `mlkem768x25519 public key must be ${MLKEM768X25519_PUBLIC_KEY_LENGTH} bytes, got ${opts2.publicKey.length}`
1000
+ );
1001
+ }
1002
+ if (opts2.eseed !== void 0 && opts2.eseed.length !== MLKEM768X25519_ESEED_LENGTH) {
1003
+ throw new Error(
1004
+ `mlkem768x25519 eseed must be ${MLKEM768X25519_ESEED_LENGTH} bytes, got ${opts2.eseed.length}`
1005
+ );
1006
+ }
1007
+ const { cipherText, sharedSecret } = XWing.encapsulate(opts2.publicKey, opts2.eseed);
1008
+ return { enc: cipherText, ss: sharedSecret };
1009
+ }
1010
+ var X25519LowOrderPointError = class extends Error {
1011
+ code = "X25519_LOW_ORDER_POINT";
1012
+ constructor(options) {
1013
+ super("x25519 ECDH rejected: peer public key is a small-order point", options);
1014
+ this.name = "X25519LowOrderPointError";
880
1015
  }
881
1016
  };
882
-
883
- // src/client/invalid-client-config-error.ts
884
- var InvalidClientConfigError = class extends Error {
885
- code = "INVALID_CLIENT_CONFIG";
886
- constructor(message) {
887
- super(message);
888
- this.name = "InvalidClientConfigError";
1017
+ var NOBLE_LOW_ORDER_MESSAGE = "invalid private or public key received";
1018
+ function x25519PublicKey(opts2) {
1019
+ return x25519.getPublicKey(opts2.secretKey);
1020
+ }
1021
+ function x25519Ecdh(opts2) {
1022
+ try {
1023
+ return x25519.getSharedSecret(opts2.secretKey, opts2.theirPublicKey);
1024
+ } catch (e) {
1025
+ if (e instanceof Error && e.message === NOBLE_LOW_ORDER_MESSAGE) {
1026
+ throw new X25519LowOrderPointError({ cause: e });
1027
+ }
1028
+ throw e;
1029
+ }
1030
+ }
1031
+ var EciesSealedPoeError = class extends Error {
1032
+ code;
1033
+ constructor(code, message, options) {
1034
+ super(message, options);
1035
+ this.name = "EciesSealedPoeError";
1036
+ this.code = code;
889
1037
  }
890
1038
  };
891
-
892
- // src/hex.ts
893
- function bytesToHex(bytes) {
894
- return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
1039
+ var CHUNK_MAX_BYTES = 64;
1040
+ function chunkKemCt(value) {
1041
+ if (value.length === 0) {
1042
+ throw new Error("chunkKemCt: refusing to chunk an empty byte string");
1043
+ }
1044
+ const chunks = [];
1045
+ for (let i = 0; i < value.length; i += CHUNK_MAX_BYTES) {
1046
+ chunks.push(value.subarray(i, Math.min(i + CHUNK_MAX_BYTES, value.length)));
1047
+ }
1048
+ return chunks;
1049
+ }
1050
+ function joinKemCt(chunks) {
1051
+ let total = 0;
1052
+ for (const c of chunks) total += c.length;
1053
+ const out = new Uint8Array(total);
1054
+ let offset = 0;
1055
+ for (const c of chunks) {
1056
+ out.set(c, offset);
1057
+ offset += c.length;
1058
+ }
1059
+ return out;
1060
+ }
1061
+ function canonicalizeSlots(slots, kem) {
1062
+ if (kem === "x25519") {
1063
+ return slots.map((s) => ({ epk: s.epk, wrap: s.wrap }));
1064
+ }
1065
+ return slots.map((s) => ({
1066
+ kem_ct: chunkKemCt(joinKemCt(s.kem_ct)),
1067
+ wrap: s.wrap
1068
+ }));
895
1069
  }
896
1070
  function encodeCanonicalCbor3(value) {
897
1071
  return encode(value, {
@@ -901,1075 +1075,984 @@ function encodeCanonicalCbor3(value) {
901
1075
  sortKeys: sortCoreDeterministic
902
1076
  });
903
1077
  }
904
- var LEAVES_LIST_FORMAT_V1 = "cardano-poe-merkle-leaves-v1";
905
- var TREE_ALG_RFC9162 = "rfc9162-sha256";
906
- var DIGEST_LENGTH2 = 32;
907
- var MerkleLeavesListError = class extends Error {
908
- code;
909
- constructor(code, message) {
910
- super(message ? `${code}: ${message}` : code);
911
- this.code = code;
912
- this.name = "MerkleLeavesListError";
913
- }
914
- };
915
- function encodeLeavesList(args) {
916
- if (!(args.root instanceof Uint8Array) || args.root.length !== DIGEST_LENGTH2) {
917
- throw new MerkleLeavesListError(
918
- "SCHEMA_MERKLE_LEAVES_MALFORMED",
919
- `root must be a Uint8Array(${DIGEST_LENGTH2})`
920
- );
921
- }
922
- if (args.leaves.length < 1) {
923
- throw new MerkleLeavesListError(
924
- "SCHEMA_MERKLE_LEAVES_MALFORMED",
925
- "leaves array must be non-empty"
1078
+ var CARDANO_POE_SLOTS_TRANSCRIPT_PREFIX = new TextEncoder().encode(
1079
+ "cardano-poe-slots-transcript-v1"
1080
+ );
1081
+ var CARDANO_POE_HKDF_INFO_PAYLOAD = new TextEncoder().encode(
1082
+ "cardano-poe-payload-v1"
1083
+ );
1084
+ var CARDANO_POE_HKDF_INFO_PAYLOAD_PASSPHRASE = new TextEncoder().encode(
1085
+ "cardano-poe-payload-passphrase-v1"
1086
+ );
1087
+ var CARDANO_POE_XWING_KEK_SALT_PREFIX = new TextEncoder().encode(
1088
+ "cardano-poe-xwing-kek-salt-v1"
1089
+ );
1090
+ if (CARDANO_POE_SLOTS_TRANSCRIPT_PREFIX.length !== 31) {
1091
+ throw new Error(
1092
+ "CARDANO_POE_SLOTS_TRANSCRIPT_PREFIX byte-length invariant violated (expected 31)"
1093
+ );
1094
+ }
1095
+ if (CARDANO_POE_HKDF_INFO_PAYLOAD.length !== 22) {
1096
+ throw new Error("CARDANO_POE_HKDF_INFO_PAYLOAD byte-length invariant violated (expected 22)");
1097
+ }
1098
+ if (CARDANO_POE_HKDF_INFO_PAYLOAD_PASSPHRASE.length !== 33) {
1099
+ throw new Error(
1100
+ "CARDANO_POE_HKDF_INFO_PAYLOAD_PASSPHRASE byte-length invariant violated (expected 33)"
1101
+ );
1102
+ }
1103
+ if (CARDANO_POE_XWING_KEK_SALT_PREFIX.length !== 29) {
1104
+ throw new Error("CARDANO_POE_XWING_KEK_SALT_PREFIX byte-length invariant violated (expected 29)");
1105
+ }
1106
+ var MAX_SEALED_PLAINTEXT = 274877906880;
1107
+ function assertPlaintextWithinBound(plaintextLength) {
1108
+ if (plaintextLength >= MAX_SEALED_PLAINTEXT) {
1109
+ throw new SealedPayloadTooLargeError(
1110
+ `plaintext length ${plaintextLength} is at or above the maximum sealed payload size ${MAX_SEALED_PLAINTEXT}`
926
1111
  );
927
1112
  }
928
- const leavesCopy = [];
929
- for (let i = 0; i < args.leaves.length; i++) {
930
- const leaf = args.leaves[i];
931
- if (!(leaf instanceof Uint8Array) || leaf.length !== DIGEST_LENGTH2) {
932
- throw new MerkleLeavesListError(
933
- "SCHEMA_MERKLE_LEAVES_MALFORMED",
934
- `leaves[${i}] must be a Uint8Array(${DIGEST_LENGTH2})`
935
- );
936
- }
937
- leavesCopy.push(leaf);
938
- }
939
- if (args.leafAlg !== void 0 && typeof args.leafAlg !== "string") {
940
- throw new MerkleLeavesListError(
941
- "SCHEMA_MERKLE_LEAVES_MALFORMED",
942
- "leaf_alg must be a string when present"
943
- );
1113
+ }
1114
+ var SealedPayloadTooLargeError = class extends Error {
1115
+ constructor(message) {
1116
+ super(message);
1117
+ this.name = "SealedPayloadTooLargeError";
944
1118
  }
945
- const map = {
946
- format: LEAVES_LIST_FORMAT_V1,
947
- tree_alg: TREE_ALG_RFC9162,
948
- root: args.root,
949
- leaves: leavesCopy,
950
- leaf_count: leavesCopy.length
1119
+ };
1120
+ function computeSlotsHash(args) {
1121
+ const transcript = {
1122
+ scheme: 1,
1123
+ path: "slots",
1124
+ aead: "xchacha20-poly1305",
1125
+ kem: args.kem,
1126
+ nonce: args.nonce,
1127
+ slots: canonicalizeSlots(args.slots, args.kem)
951
1128
  };
952
- if (args.leafAlg !== void 0) {
953
- map["leaf_alg"] = args.leafAlg;
954
- }
955
- return encodeCanonicalCbor3(map);
1129
+ const encoded = encodeCanonicalCbor3(transcript);
1130
+ const message = new Uint8Array(CARDANO_POE_SLOTS_TRANSCRIPT_PREFIX.length + encoded.length);
1131
+ message.set(CARDANO_POE_SLOTS_TRANSCRIPT_PREFIX, 0);
1132
+ message.set(encoded, CARDANO_POE_SLOTS_TRANSCRIPT_PREFIX.length);
1133
+ return sha256$1(message);
1134
+ }
1135
+ function adContentSlots(args) {
1136
+ const ad = {
1137
+ scheme: 1,
1138
+ path: "slots",
1139
+ aead: "xchacha20-poly1305",
1140
+ kem: args.kem,
1141
+ nonce: args.nonce,
1142
+ slots_hash: args.slotsHash,
1143
+ slots_mac: args.slotsMac
1144
+ };
1145
+ return encodeCanonicalCbor3(ad);
956
1146
  }
957
- var abytesDoc = abytes;
958
- var randomBytes = randomBytes$2;
959
- function equalBytes(a, b) {
960
- if (a.length !== b.length)
961
- return false;
962
- let diff = 0;
963
- for (let i = 0; i < a.length; i++)
964
- diff |= a[i] ^ b[i];
965
- return diff === 0;
1147
+ function slotsPayloadKey(args) {
1148
+ return hkdfSha256({
1149
+ ikm: args.cek,
1150
+ salt: args.nonce,
1151
+ info: CARDANO_POE_HKDF_INFO_PAYLOAD,
1152
+ length: 32
1153
+ });
966
1154
  }
967
- function copyBytes(bytes) {
968
- return Uint8Array.from(abytes(bytes));
1155
+ function xwingKekSalt(args) {
1156
+ const message = new Uint8Array(
1157
+ CARDANO_POE_XWING_KEK_SALT_PREFIX.length + args.kemCt.length + args.pubR.length
1158
+ );
1159
+ let offset = 0;
1160
+ message.set(CARDANO_POE_XWING_KEK_SALT_PREFIX, offset);
1161
+ offset += CARDANO_POE_XWING_KEK_SALT_PREFIX.length;
1162
+ message.set(args.kemCt, offset);
1163
+ offset += args.kemCt.length;
1164
+ message.set(args.pubR, offset);
1165
+ return sha256$1(message);
969
1166
  }
970
- function splitCoder(label, ...lengths) {
971
- const getLength = (c) => typeof c === "number" ? c : c.bytesLen;
972
- const bytesLen = lengths.reduce((sum, a) => sum + getLength(a), 0);
973
- return {
974
- bytesLen,
975
- encode: (bufs) => {
976
- const res = new Uint8Array(bytesLen);
977
- for (let i = 0, pos = 0; i < lengths.length; i++) {
978
- const c = lengths[i];
979
- const l = getLength(c);
980
- const b = typeof c === "number" ? bufs[i] : c.encode(bufs[i]);
981
- abytes(b, l, label);
982
- res.set(b, pos);
983
- if (typeof c !== "number")
984
- b.fill(0);
985
- pos += l;
986
- }
987
- return res;
988
- },
989
- decode: (buf) => {
990
- abytes(buf, bytesLen, label);
991
- const res = [];
992
- for (const c of lengths) {
993
- const l = getLength(c);
994
- const b = buf.subarray(0, l);
995
- res.push(typeof c === "number" ? b : c.decode(b));
996
- buf = buf.subarray(l);
997
- }
998
- return res;
999
- }
1000
- };
1167
+ var CARDANO_POE_HKDF_INFO_KEK = new TextEncoder().encode("cardano-poe-kek-v1");
1168
+ var CARDANO_POE_HKDF_INFO_KEK_MLKEM768X25519 = new TextEncoder().encode(
1169
+ "cardano-poe-kek-mlkem768x25519-v1"
1170
+ );
1171
+ var CARDANO_POE_HKDF_INFO_SLOTS_MAC = new TextEncoder().encode(
1172
+ "cardano-poe-slots-mac-v1"
1173
+ );
1174
+ var ZERO_NONCE_12 = new Uint8Array(12);
1175
+ var EMPTY_SALT = new Uint8Array(0);
1176
+ var X25519_PUBLIC_KEY_LENGTH = 32;
1177
+ var X25519_SECRET_KEY_LENGTH = 32;
1178
+ var CEK_LENGTH = 32;
1179
+ var NONCE_LENGTH = 24;
1180
+ var WRAP_LENGTH = 48;
1181
+ var SLOTS_MAC_LENGTH = 32;
1182
+ if (CARDANO_POE_HKDF_INFO_KEK.length !== 18) {
1183
+ throw new Error("CARDANO_POE_HKDF_INFO_KEK byte-length invariant violated (expected 18)");
1001
1184
  }
1002
- function vecCoder(c, vecLen) {
1003
- const coder = c;
1004
- const bytesLen = vecLen * coder.bytesLen;
1005
- return {
1006
- bytesLen,
1007
- encode: (u) => {
1008
- if (u.length !== vecLen)
1009
- throw new RangeError(`vecCoder.encode: wrong length=${u.length}. Expected: ${vecLen}`);
1010
- const res = new Uint8Array(bytesLen);
1011
- for (let i = 0, pos = 0; i < u.length; i++) {
1012
- const b = coder.encode(u[i]);
1013
- res.set(b, pos);
1014
- b.fill(0);
1015
- pos += b.length;
1016
- }
1017
- return res;
1018
- },
1019
- decode: (a) => {
1020
- abytes(a, bytesLen);
1021
- const r = [];
1022
- for (let i = 0; i < a.length; i += coder.bytesLen)
1023
- r.push(coder.decode(a.subarray(i, i + coder.bytesLen)));
1024
- return r;
1025
- }
1026
- };
1185
+ if (CARDANO_POE_HKDF_INFO_KEK_MLKEM768X25519.length !== 33) {
1186
+ throw new Error(
1187
+ "CARDANO_POE_HKDF_INFO_KEK_MLKEM768X25519 byte-length invariant violated (expected 33)"
1188
+ );
1027
1189
  }
1028
- function cleanBytes(...list) {
1029
- for (const t of list) {
1030
- if (Array.isArray(t))
1031
- for (const b of t)
1032
- b.fill(0);
1033
- else
1034
- t.fill(0);
1190
+ if (CARDANO_POE_HKDF_INFO_SLOTS_MAC.length !== 24) {
1191
+ throw new Error("CARDANO_POE_HKDF_INFO_SLOTS_MAC byte-length invariant violated (expected 24)");
1192
+ }
1193
+ if (ZERO_NONCE_12.length !== 12) {
1194
+ throw new Error("ZERO_NONCE_12 byte-length invariant violated (expected 12)");
1195
+ }
1196
+ function concat(a, b) {
1197
+ const out = new Uint8Array(a.length + b.length);
1198
+ out.set(a, 0);
1199
+ out.set(b, a.length);
1200
+ return out;
1201
+ }
1202
+ function uniformIndexBelow(m) {
1203
+ const limit = 4294967296 - 4294967296 % m;
1204
+ const buf = new Uint32Array(1);
1205
+ let x;
1206
+ do {
1207
+ crypto.getRandomValues(buf);
1208
+ x = buf[0];
1209
+ } while (x >= limit);
1210
+ return x % m;
1211
+ }
1212
+ function csprngShuffle(arr) {
1213
+ for (let i = arr.length - 1; i > 0; i--) {
1214
+ const j = uniformIndexBelow(i + 1);
1215
+ const tmp = arr[i];
1216
+ arr[i] = arr[j];
1217
+ arr[j] = tmp;
1035
1218
  }
1036
1219
  }
1037
- function getMask(bits) {
1038
- if (!Number.isSafeInteger(bits) || bits < 0 || bits > 32)
1039
- throw new RangeError(`expected bits in [0..32], got ${bits}`);
1040
- return bits === 32 ? 4294967295 : ~(-1 << bits) >>> 0;
1220
+ function wrapSlotX25519(args) {
1221
+ const privEph = args.privEph ?? randomBytes$1(X25519_SECRET_KEY_LENGTH);
1222
+ if (privEph.length !== X25519_SECRET_KEY_LENGTH) {
1223
+ throw new EciesSealedPoeError(
1224
+ "INVALID_EPHEMERAL_SECRET_LENGTH",
1225
+ `ephemeralSecrets[${args.slotIdx}] MUST be exactly ${X25519_SECRET_KEY_LENGTH} bytes, got ${privEph.length}`
1226
+ );
1227
+ }
1228
+ const epk = x25519PublicKey({ secretKey: privEph });
1229
+ const shared = x25519Ecdh({ secretKey: privEph, theirPublicKey: args.pubR });
1230
+ const kek = hkdfSha256({
1231
+ ikm: shared,
1232
+ salt: concat(epk, args.pubR),
1233
+ info: CARDANO_POE_HKDF_INFO_KEK,
1234
+ length: 32
1235
+ });
1236
+ const wrap = chacha20Poly1305Encrypt({
1237
+ key: kek,
1238
+ nonce: ZERO_NONCE_12,
1239
+ aad: CARDANO_POE_HKDF_INFO_KEK,
1240
+ plaintext: args.cek
1241
+ });
1242
+ if (wrap.length !== WRAP_LENGTH) {
1243
+ throw new Error(`internal: wrap.length=${wrap.length}, expected ${WRAP_LENGTH}`);
1244
+ }
1245
+ return { epk, wrap };
1041
1246
  }
1042
-
1043
- // ../../node_modules/.pnpm/@noble+post-quantum@0.6.1/node_modules/@noble/post-quantum/_crystals.js
1044
- var genCrystals = (opts2) => {
1045
- const { newPoly, N: N2, Q: Q2, F: F2, ROOT_OF_UNITY: ROOT_OF_UNITY2, brvBits} = opts2;
1046
- const mod = (a, modulo = Q2) => {
1047
- const result = a % modulo | 0;
1048
- return (result >= 0 ? result | 0 : modulo + result | 0) | 0;
1049
- };
1050
- const smod = (a, modulo = Q2) => {
1051
- const r = mod(a, modulo) | 0;
1052
- return (r > modulo >> 1 ? r - modulo | 0 : r) | 0;
1053
- };
1054
- function getZettas() {
1055
- const out = newPoly(N2);
1056
- for (let i = 0; i < N2; i++) {
1057
- const b = reverseBits(i, brvBits);
1058
- const p = BigInt(ROOT_OF_UNITY2) ** BigInt(b) % BigInt(Q2);
1059
- out[i] = Number(p) | 0;
1247
+ function wrapSlotMlkem768X25519(args) {
1248
+ const { enc, ss } = mlkem768x25519Encapsulate({
1249
+ publicKey: args.pubR,
1250
+ ...args.eseed !== void 0 ? { eseed: args.eseed } : {}
1251
+ });
1252
+ if (enc.length !== MLKEM768X25519_ENC_LENGTH) {
1253
+ throw new Error(`internal: enc.length=${enc.length}, expected ${MLKEM768X25519_ENC_LENGTH}`);
1254
+ }
1255
+ const kek = hkdfSha256({
1256
+ ikm: ss,
1257
+ salt: xwingKekSalt({ kemCt: enc, pubR: args.pubR }),
1258
+ info: CARDANO_POE_HKDF_INFO_KEK_MLKEM768X25519,
1259
+ length: 32
1260
+ });
1261
+ const wrap = chacha20Poly1305Encrypt({
1262
+ key: kek,
1263
+ nonce: ZERO_NONCE_12,
1264
+ aad: CARDANO_POE_HKDF_INFO_KEK_MLKEM768X25519,
1265
+ plaintext: args.cek
1266
+ });
1267
+ if (wrap.length !== WRAP_LENGTH) {
1268
+ throw new Error(`internal: wrap.length=${wrap.length}, expected ${WRAP_LENGTH}`);
1269
+ }
1270
+ return { kem_ct: chunkKemCt(enc), wrap };
1271
+ }
1272
+ function eciesSealedPoeWrap(args) {
1273
+ const { plaintext, recipientPublicKeys } = args;
1274
+ const kem = args.kem ?? "x25519";
1275
+ const n = recipientPublicKeys.length;
1276
+ assertPlaintextWithinBound(plaintext.length);
1277
+ if (n < 1) {
1278
+ throw new EciesSealedPoeError(
1279
+ "ENC_SLOTS_EMPTY",
1280
+ `recipientPublicKeys.length=${n} must be >= 1`
1281
+ );
1282
+ }
1283
+ const expectedPubLen = kem === "x25519" ? X25519_PUBLIC_KEY_LENGTH : MLKEM768X25519_PUBLIC_KEY_LENGTH;
1284
+ for (let i = 0; i < n; i++) {
1285
+ const pub = recipientPublicKeys[i];
1286
+ if (pub === void 0 || pub.length !== expectedPubLen) {
1287
+ throw new EciesSealedPoeError(
1288
+ "KEM_EPK_LENGTH_MISMATCH",
1289
+ `recipientPublicKeys[${i}] MUST be exactly ${expectedPubLen} bytes for kem='${kem}'`
1290
+ );
1060
1291
  }
1061
- return out;
1062
1292
  }
1063
- const nttZetas = getZettas();
1064
- const field = {
1065
- add: (a, b) => mod((a | 0) + (b | 0)) | 0,
1066
- sub: (a, b) => mod((a | 0) - (b | 0)) | 0,
1067
- mul: (a, b) => mod((a | 0) * (b | 0)) | 0,
1068
- inv: (_a) => {
1069
- throw new Error("not implemented");
1293
+ if (kem === "x25519") {
1294
+ if (args.eseeds !== void 0) {
1295
+ throw new EciesSealedPoeError(
1296
+ "EPHEMERAL_SECRETS_COUNT_MISMATCH",
1297
+ "eseeds is an X-Wing (mlkem768x25519) override and MUST NOT be supplied for kem='x25519'"
1298
+ );
1070
1299
  }
1071
- };
1072
- const nttOpts = {
1073
- N: N2,
1074
- roots: nttZetas,
1075
- invertButterflies: true,
1076
- skipStages: 1 ,
1077
- brp: false
1078
- };
1079
- const dif = FFTCore(field, { dit: false, ...nttOpts });
1080
- const dit = FFTCore(field, { dit: true, ...nttOpts });
1081
- const NTT = {
1082
- encode: (r) => {
1083
- return dif(r);
1084
- },
1085
- decode: (r) => {
1086
- dit(r);
1087
- for (let i = 0; i < r.length; i++)
1088
- r[i] = mod(F2 * r[i]);
1089
- return r;
1300
+ if (args.ephemeralSecrets !== void 0 && args.ephemeralSecrets.length !== n) {
1301
+ throw new EciesSealedPoeError(
1302
+ "EPHEMERAL_SECRETS_COUNT_MISMATCH",
1303
+ `ephemeralSecrets.length=${args.ephemeralSecrets.length} must match recipientPublicKeys.length=${n}`
1304
+ );
1090
1305
  }
1091
- };
1092
- const bitsCoder = (d, c) => {
1093
- const mask = getMask(d);
1094
- const bytesLen = d * (N2 / 8);
1095
- return {
1096
- bytesLen,
1097
- encode: (poly_) => {
1098
- const poly = poly_;
1099
- const r = new Uint8Array(bytesLen);
1100
- for (let i = 0, buf = 0, bufLen = 0, pos = 0; i < poly.length; i++) {
1101
- buf |= (c.encode(poly[i]) & mask) << bufLen;
1102
- bufLen += d;
1103
- for (; bufLen >= 8; bufLen -= 8, buf >>= 8)
1104
- r[pos++] = buf & getMask(bufLen);
1105
- }
1106
- return r;
1107
- },
1108
- decode: (bytes) => {
1109
- const r = newPoly(N2);
1110
- for (let i = 0, buf = 0, bufLen = 0, pos = 0; i < bytes.length; i++) {
1111
- buf |= bytes[i] << bufLen;
1112
- bufLen += 8;
1113
- for (; bufLen >= d; bufLen -= d, buf >>= d)
1114
- r[pos++] = c.decode(buf & mask);
1306
+ } else {
1307
+ if (args.ephemeralSecrets !== void 0) {
1308
+ throw new EciesSealedPoeError(
1309
+ "EPHEMERAL_SECRETS_COUNT_MISMATCH",
1310
+ "ephemeralSecrets is an X25519 override and MUST NOT be supplied for kem='mlkem768x25519'"
1311
+ );
1312
+ }
1313
+ if (args.eseeds !== void 0) {
1314
+ if (args.eseeds.length !== n) {
1315
+ throw new EciesSealedPoeError(
1316
+ "EPHEMERAL_SECRETS_COUNT_MISMATCH",
1317
+ `eseeds.length=${args.eseeds.length} must match recipientPublicKeys.length=${n}`
1318
+ );
1319
+ }
1320
+ for (let i = 0; i < n; i++) {
1321
+ const eseed = args.eseeds[i];
1322
+ if (eseed.length !== MLKEM768X25519_ESEED_LENGTH) {
1323
+ throw new EciesSealedPoeError(
1324
+ "INVALID_EPHEMERAL_SECRET_LENGTH",
1325
+ `eseeds[${i}] MUST be exactly ${MLKEM768X25519_ESEED_LENGTH} bytes, got ${eseed.length}`
1326
+ );
1115
1327
  }
1116
- return r;
1117
1328
  }
1118
- };
1119
- };
1120
- return {
1121
- mod,
1122
- smod,
1123
- nttZetas,
1124
- NTT: {
1125
- encode: (r) => NTT.encode(r),
1126
- decode: (r) => NTT.decode(r)
1127
- },
1128
- bitsCoder
1129
- };
1130
- };
1131
- var createXofShake = (shake) => (seed, blockLen) => {
1132
- if (!blockLen)
1133
- blockLen = shake.blockLen;
1134
- const _seed = new Uint8Array(seed.length + 2);
1135
- _seed.set(seed);
1136
- const seedLen = seed.length;
1137
- const buf = new Uint8Array(blockLen);
1138
- let h = shake.create({});
1139
- let calls = 0;
1140
- let xofs = 0;
1141
- return {
1142
- stats: () => ({ calls, xofs }),
1143
- get: (x, y) => {
1144
- _seed[seedLen + 0] = x;
1145
- _seed[seedLen + 1] = y;
1146
- h.destroy();
1147
- h = shake.create({}).update(_seed);
1148
- calls++;
1149
- return () => {
1150
- xofs++;
1151
- return h.xofInto(buf);
1152
- };
1153
- },
1154
- clean: () => {
1155
- h.destroy();
1156
- cleanBytes(buf, _seed);
1157
1329
  }
1158
- };
1159
- };
1160
- var XOF128 = /* @__PURE__ */ createXofShake(shake128);
1161
-
1162
- // ../../node_modules/.pnpm/@noble+post-quantum@0.6.1/node_modules/@noble/post-quantum/ml-kem.js
1163
- var N = 256;
1164
- var Q = 3329;
1165
- var F = 3303;
1166
- var ROOT_OF_UNITY = 17;
1167
- var crystals = /* @__PURE__ */ genCrystals({
1168
- N,
1169
- Q,
1170
- F,
1171
- ROOT_OF_UNITY,
1172
- newPoly: (n) => new Uint16Array(n),
1173
- brvBits: 7});
1174
- var PARAMS = /* @__PURE__ */ (() => Object.freeze({
1175
- 512: Object.freeze({ N, Q, K: 2, ETA1: 3, ETA2: 2, du: 10, dv: 4, RBGstrength: 128 }),
1176
- 768: Object.freeze({ N, Q, K: 3, ETA1: 2, ETA2: 2, du: 10, dv: 4, RBGstrength: 192 }),
1177
- 1024: Object.freeze({ N, Q, K: 4, ETA1: 2, ETA2: 2, du: 11, dv: 5, RBGstrength: 256 })
1178
- }))();
1179
- var compress = (d) => {
1180
- if (d >= 12)
1181
- return { encode: (i) => i, decode: (i) => i >= Q ? i - Q : i };
1182
- const a = 2 ** (d - 1);
1183
- return {
1184
- // This only matches standalone Compress_d after bitsCoder masks the result into Z_(2^d).
1185
- encode: (i) => ((i << d) + Q / 2) / Q,
1186
- // const decompress = (i: number) => round((Q / 2 ** d) * i);
1187
- decode: (i) => i * Q + a >>> d
1188
- };
1189
- };
1190
- var byteCoder = (d) => crystals.bitsCoder(d, { encode: (i) => i, decode: (i) => i >= Q ? i - Q : i } );
1191
- var polyCoder = (d) => d === 12 ? byteCoder(12) : crystals.bitsCoder(d, compress(d));
1192
- function polyAdd(a_, b_) {
1193
- const a = a_;
1194
- const b = b_;
1195
- for (let i = 0; i < N; i++)
1196
- a[i] = crystals.mod(a[i] + b[i]);
1197
- }
1198
- function polySub(a_, b_) {
1199
- const a = a_;
1200
- const b = b_;
1201
- for (let i = 0; i < N; i++)
1202
- a[i] = crystals.mod(a[i] - b[i]);
1203
- }
1204
- function BaseCaseMultiply(a0, a1, b0, b1, zeta) {
1205
- const c0 = crystals.mod(a1 * b1 * zeta + a0 * b0);
1206
- const c1 = crystals.mod(a0 * b1 + a1 * b0);
1207
- return { c0, c1 };
1208
- }
1209
- function MultiplyNTTs(f_, g_) {
1210
- const f = f_;
1211
- const g = g_;
1212
- for (let i = 0; i < N / 2; i++) {
1213
- let z3 = crystals.nttZetas[64 + (i >> 1)];
1214
- if (i & 1)
1215
- z3 = -z3;
1216
- const { c0, c1 } = BaseCaseMultiply(f[2 * i + 0], f[2 * i + 1], g[2 * i + 0], g[2 * i + 1], z3);
1217
- f[2 * i + 0] = c0;
1218
- f[2 * i + 1] = c1;
1219
1330
  }
1220
- return f;
1221
- }
1222
- function SampleNTT(xof_) {
1223
- const xof = xof_;
1224
- const r = new Uint16Array(N);
1225
- for (let j = 0; j < N; ) {
1226
- const b = xof();
1227
- if (b.length % 3)
1228
- throw new Error("SampleNTT: unaligned block");
1229
- for (let i = 0; j < N && i + 3 <= b.length; i += 3) {
1230
- const d1 = (b[i + 0] >> 0 | b[i + 1] << 8) & 4095;
1231
- const d2 = (b[i + 1] >> 4 | b[i + 2] << 4) & 4095;
1232
- if (d1 < Q)
1233
- r[j++] = d1;
1234
- if (j < N && d2 < Q)
1235
- r[j++] = d2;
1236
- }
1331
+ const cek = args.cek ?? randomBytes$1(CEK_LENGTH);
1332
+ const nonce = args.nonce ?? randomBytes$1(NONCE_LENGTH);
1333
+ if (cek.length !== CEK_LENGTH) {
1334
+ throw new EciesSealedPoeError(
1335
+ "INVALID_CEK_LENGTH",
1336
+ `cek MUST be exactly ${CEK_LENGTH} bytes, got ${cek.length}`
1337
+ );
1237
1338
  }
1238
- return r;
1239
- }
1240
- var sampleCBDBytes = (buf, eta) => {
1241
- const r = new Uint16Array(N);
1242
- const b32 = u32(buf);
1243
- swap32IfBE(b32);
1244
- let len = 0;
1245
- for (let i = 0, p = 0, bb = 0, t0 = 0; i < b32.length; i++) {
1246
- let b = b32[i];
1247
- for (let j = 0; j < 32; j++) {
1248
- bb += b & 1;
1249
- b >>= 1;
1250
- len += 1;
1251
- if (len === eta) {
1252
- t0 = bb;
1253
- bb = 0;
1254
- } else if (len === 2 * eta) {
1255
- r[p++] = crystals.mod(t0 - bb);
1256
- bb = 0;
1257
- len = 0;
1258
- }
1259
- }
1339
+ if (nonce.length !== NONCE_LENGTH) {
1340
+ throw new EciesSealedPoeError(
1341
+ "NONCE_LENGTH_MISMATCH",
1342
+ `nonce MUST be exactly ${NONCE_LENGTH} bytes, got ${nonce.length}`
1343
+ );
1260
1344
  }
1261
- swap32IfBE(b32);
1262
- if (len)
1263
- throw new Error(`sampleCBD: leftover bits: ${len}`);
1264
- return r;
1265
- };
1266
- function sampleCBD(PRF_, seed, nonce, eta) {
1267
- const PRF = PRF_;
1268
- return sampleCBDBytes(PRF(eta * N / 4, seed, nonce), eta);
1269
- }
1270
- var genKPKE = (opts_) => {
1271
- const opts2 = opts_;
1272
- const { K, PRF, XOF, HASH512, ETA1, ETA2, du, dv } = opts2;
1273
- const poly1 = polyCoder(1);
1274
- const polyV = polyCoder(dv);
1275
- const polyU = polyCoder(du);
1276
- const publicCoder = splitCoder("publicKey", vecCoder(polyCoder(12), K), 32);
1277
- const secretCoder = vecCoder(polyCoder(12), K);
1278
- const cipherCoder = splitCoder("ciphertext", vecCoder(polyU, K), polyV);
1279
- const seedCoder = splitCoder("seed", 32, 32);
1280
- return {
1281
- secretCoder,
1282
- lengths: {
1283
- secretKey: secretCoder.bytesLen,
1284
- publicKey: publicCoder.bytesLen,
1285
- cipherText: cipherCoder.bytesLen
1286
- },
1287
- keygen: (seed) => {
1288
- abytesDoc(seed, 32, "seed");
1289
- const seedDst = new Uint8Array(33);
1290
- seedDst.set(seed);
1291
- seedDst[32] = K;
1292
- const seedHash = HASH512(seedDst);
1293
- const [rho, sigma] = seedCoder.decode(seedHash);
1294
- const sHat = [];
1295
- const tHat = [];
1296
- for (let i = 0; i < K; i++)
1297
- sHat.push(crystals.NTT.encode(sampleCBD(PRF, sigma, i, ETA1)));
1298
- const x = XOF(rho);
1299
- for (let i = 0; i < K; i++) {
1300
- const e = crystals.NTT.encode(sampleCBD(PRF, sigma, K + i, ETA1));
1301
- for (let j = 0; j < K; j++) {
1302
- const aji = SampleNTT(x.get(j, i));
1303
- polyAdd(e, MultiplyNTTs(aji, sHat[j]));
1304
- }
1305
- tHat.push(e);
1306
- }
1307
- x.clean();
1308
- const res = {
1309
- publicKey: publicCoder.encode([tHat, rho]),
1310
- secretKey: secretCoder.encode(sHat)
1311
- };
1312
- cleanBytes(rho, sigma, sHat, tHat, seedDst, seedHash);
1313
- return res;
1314
- },
1315
- encrypt: (publicKey, msg, seed) => {
1316
- const [tHat, rho] = publicCoder.decode(publicKey);
1317
- const rHat = [];
1318
- for (let i = 0; i < K; i++)
1319
- rHat.push(crystals.NTT.encode(sampleCBD(PRF, seed, i, ETA1)));
1320
- const x = XOF(rho);
1321
- const tmp2 = new Uint16Array(N);
1322
- const u = [];
1323
- for (let i = 0; i < K; i++) {
1324
- const e1 = sampleCBD(PRF, seed, K + i, ETA2);
1325
- const tmp = new Uint16Array(N);
1326
- for (let j = 0; j < K; j++) {
1327
- const aij = SampleNTT(x.get(i, j));
1328
- polyAdd(tmp, MultiplyNTTs(aij, rHat[j]));
1329
- }
1330
- polyAdd(e1, crystals.NTT.decode(tmp));
1331
- u.push(e1);
1332
- polyAdd(tmp2, MultiplyNTTs(tHat[i], rHat[i]));
1333
- cleanBytes(tmp);
1334
- }
1335
- x.clean();
1336
- const e2 = sampleCBD(PRF, seed, 2 * K, ETA2);
1337
- polyAdd(e2, crystals.NTT.decode(tmp2));
1338
- const v = poly1.decode(msg);
1339
- polyAdd(v, e2);
1340
- cleanBytes(tHat, rHat, tmp2, e2);
1341
- return cipherCoder.encode([u, v]);
1342
- },
1343
- decrypt: (cipherText, privateKey) => {
1344
- const [u, v] = cipherCoder.decode(cipherText);
1345
- const sk = secretCoder.decode(privateKey);
1346
- const tmp = new Uint16Array(N);
1347
- for (let i = 0; i < K; i++)
1348
- polyAdd(tmp, MultiplyNTTs(sk[i], crystals.NTT.encode(u[i])));
1349
- polySub(v, crystals.NTT.decode(tmp));
1350
- cleanBytes(tmp, sk, u);
1351
- return poly1.encode(v);
1345
+ let envelope;
1346
+ let slotsHash;
1347
+ if (kem === "x25519") {
1348
+ const slots = [];
1349
+ for (let i = 0; i < n; i++) {
1350
+ slots.push(
1351
+ wrapSlotX25519({
1352
+ pubR: recipientPublicKeys[i],
1353
+ privEph: args.ephemeralSecrets ? args.ephemeralSecrets[i] : void 0,
1354
+ cek,
1355
+ slotIdx: i
1356
+ })
1357
+ );
1352
1358
  }
1353
- };
1354
- };
1355
- function createKyber(opts2) {
1356
- const rawOpts = opts2;
1357
- const KPKE = genKPKE(rawOpts);
1358
- const { HASH256, HASH512, KDF } = rawOpts;
1359
- const { secretCoder: KPKESecretCoder, lengths } = KPKE;
1360
- const secretCoder = splitCoder("secretKey", lengths.secretKey, lengths.publicKey, 32, 32);
1361
- const msgLen = 32;
1362
- const seedLen = 64;
1363
- const kemLengths = Object.freeze({
1364
- ...lengths,
1365
- seed: 64,
1366
- msg: msgLen,
1367
- msgRand: msgLen,
1368
- secretKey: secretCoder.bytesLen
1369
- });
1370
- return Object.freeze({
1371
- info: Object.freeze({ type: "ml-kem" }),
1372
- lengths: kemLengths,
1373
- keygen: (seed = randomBytes(seedLen)) => {
1374
- abytesDoc(seed, seedLen, "seed");
1375
- const { publicKey, secretKey: sk } = KPKE.keygen(seed.subarray(0, 32));
1376
- const publicKeyHash = HASH256(publicKey);
1377
- const secretKey = secretCoder.encode([sk, publicKey, publicKeyHash, seed.subarray(32)]);
1378
- cleanBytes(sk, publicKeyHash);
1379
- return {
1380
- publicKey,
1381
- secretKey
1382
- };
1383
- },
1384
- getPublicKey: (secretKey) => {
1385
- const [_sk, publicKey, _publicKeyHash, _z] = secretCoder.decode(secretKey);
1386
- return Uint8Array.from(publicKey);
1387
- },
1388
- encapsulate: (publicKey, msg = randomBytes(msgLen)) => {
1389
- abytesDoc(publicKey, lengths.publicKey, "publicKey");
1390
- abytesDoc(msg, msgLen, "message");
1391
- const eke = publicKey.subarray(0, 384 * opts2.K);
1392
- const ek = KPKESecretCoder.encode(KPKESecretCoder.decode(copyBytes(eke)));
1393
- if (!equalBytes(ek, eke)) {
1394
- cleanBytes(ek);
1395
- throw new Error("ML-KEM.encapsulate: wrong publicKey modulus");
1396
- }
1397
- cleanBytes(ek);
1398
- const kr = HASH512.create().update(msg).update(HASH256(publicKey)).digest();
1399
- const cipherText = KPKE.encrypt(publicKey, msg, kr.subarray(32, 64));
1400
- cleanBytes(kr.subarray(32));
1401
- return {
1402
- cipherText,
1403
- sharedSecret: kr.subarray(0, 32)
1404
- };
1405
- },
1406
- decapsulate: (cipherText, secretKey) => {
1407
- abytesDoc(secretKey, secretCoder.bytesLen, "secretKey");
1408
- abytesDoc(cipherText, lengths.cipherText, "cipherText");
1409
- const k768 = secretCoder.bytesLen - 96;
1410
- const start = k768 + 32;
1411
- const test = HASH256(secretKey.subarray(k768 / 2, start));
1412
- if (!equalBytes(test, secretKey.subarray(start, start + 32)))
1413
- throw new Error("invalid secretKey: hash check failed");
1414
- const [sk, publicKey, publicKeyHash, z3] = secretCoder.decode(secretKey);
1415
- const msg = KPKE.decrypt(cipherText, sk);
1416
- const kr = HASH512.create().update(msg).update(publicKeyHash).digest();
1417
- const Khat = kr.subarray(0, 32);
1418
- const cipherText2 = KPKE.encrypt(publicKey, msg, kr.subarray(32, 64));
1419
- const isValid = equalBytes(cipherText, cipherText2);
1420
- const Kbar = KDF.create({ dkLen: 32 }).update(z3).update(cipherText).digest();
1421
- cleanBytes(msg, cipherText2, !isValid ? Khat : Kbar);
1422
- return isValid ? Khat : Kbar;
1359
+ if (args.skipShuffle !== true) {
1360
+ csprngShuffle(slots);
1423
1361
  }
1424
- });
1425
- }
1426
- function shakePRF(dkLen, key, nonce) {
1427
- return shake256.create({ dkLen }).update(key).update(new Uint8Array([nonce])).digest();
1428
- }
1429
- var opts = /* @__PURE__ */ (() => ({
1430
- HASH256: sha3_256,
1431
- HASH512: sha3_512,
1432
- KDF: shake256,
1433
- XOF: XOF128,
1434
- PRF: shakePRF
1435
- }))();
1436
- var mk = (params) => createKyber({
1437
- ...opts,
1438
- ...params
1439
- });
1440
- var ml_kem768 = /* @__PURE__ */ (() => mk(PARAMS[768]))();
1441
-
1442
- // ../../node_modules/.pnpm/@noble+post-quantum@0.6.1/node_modules/@noble/post-quantum/hybrid.js
1443
- function ecKeygen(curve, allowZeroKey = false) {
1444
- const lengths = curve.lengths;
1445
- let keygen = curve.keygen;
1446
- if (allowZeroKey) {
1447
- if (!("getSharedSecret" in curve && "sign" in curve && "verify" in curve))
1448
- throw new Error("allowZeroKey requires a Weierstrass curve");
1449
- const wCurve = curve;
1450
- const Fn = wCurve.Point.Fn;
1451
- keygen = (seed = randomBytes(lengths.seed)) => {
1452
- abytes(seed, lengths.seed, "seed");
1453
- const seedScalar = Fn.isLE ? bytesToNumberLE(seed) : bytesToNumberBE(seed);
1454
- const secretKey = Fn.toBytes(Fn.create(seedScalar));
1455
- return {
1456
- secretKey,
1457
- publicKey: curve.getPublicKey(secretKey)
1458
- };
1362
+ slotsHash = computeSlotsHash({ kem: "x25519", nonce, slots });
1363
+ envelope = {
1364
+ scheme: 1,
1365
+ aead: "xchacha20-poly1305",
1366
+ kem: "x25519",
1367
+ nonce,
1368
+ slots,
1369
+ slots_mac: computeSlotsMac(cek, slotsHash)
1370
+ };
1371
+ } else {
1372
+ const slots = [];
1373
+ for (let i = 0; i < n; i++) {
1374
+ slots.push(
1375
+ wrapSlotMlkem768X25519({
1376
+ pubR: recipientPublicKeys[i],
1377
+ eseed: args.eseeds ? args.eseeds[i] : void 0,
1378
+ cek
1379
+ })
1380
+ );
1381
+ }
1382
+ if (args.skipShuffle !== true) {
1383
+ csprngShuffle(slots);
1384
+ }
1385
+ slotsHash = computeSlotsHash({ kem: "mlkem768x25519", nonce, slots });
1386
+ envelope = {
1387
+ scheme: 1,
1388
+ aead: "xchacha20-poly1305",
1389
+ kem: "mlkem768x25519",
1390
+ nonce,
1391
+ slots,
1392
+ slots_mac: computeSlotsMac(cek, slotsHash)
1459
1393
  };
1460
1394
  }
1461
- return {
1462
- lengths: { secretKey: lengths.secretKey, publicKey: lengths.publicKey, seed: lengths.seed },
1463
- keygen: (seed) => keygen(seed),
1464
- getPublicKey: (secretKey) => curve.getPublicKey(secretKey)
1465
- };
1395
+ const payloadKey = slotsPayloadKey({ cek, nonce });
1396
+ const adContent = adContentSlots({
1397
+ kem: envelope.kem,
1398
+ nonce,
1399
+ slotsHash,
1400
+ slotsMac: envelope.slots_mac
1401
+ });
1402
+ const ciphertext = xchacha20Poly1305Encrypt({
1403
+ key: payloadKey,
1404
+ nonce,
1405
+ aad: adContent,
1406
+ plaintext
1407
+ });
1408
+ return { envelope, ciphertext };
1466
1409
  }
1467
- function ecdhKem(curve, allowZeroKey = false) {
1468
- const kg = ecKeygen(curve, allowZeroKey);
1469
- if (!curve.getSharedSecret)
1470
- throw new Error("wrong curve");
1471
- return {
1472
- lengths: { ...kg.lengths, msg: kg.lengths.seed, cipherText: kg.lengths.publicKey },
1473
- keygen: kg.keygen,
1474
- getPublicKey: kg.getPublicKey,
1475
- encapsulate(publicKey, rand = randomBytes(curve.lengths.seed)) {
1476
- const seed = copyBytes(rand);
1477
- let ek = void 0;
1478
- try {
1479
- ek = this.keygen(seed).secretKey;
1480
- const sharedSecret = this.decapsulate(publicKey, ek);
1481
- const cipherText = curve.getPublicKey(ek);
1482
- return { sharedSecret, cipherText };
1483
- } finally {
1484
- cleanBytes(seed);
1485
- if (ek)
1486
- cleanBytes(ek);
1487
- }
1488
- },
1489
- decapsulate(cipherText, secretKey) {
1490
- const res = curve.getSharedSecret(secretKey, cipherText);
1491
- return curve.lengths.publicKeyHasPrefix ? res.subarray(1) : res;
1492
- }
1493
- };
1410
+ function computeSlotsMac(cek, slotsHash) {
1411
+ const hmacKey = hkdfSha256({
1412
+ ikm: cek,
1413
+ salt: EMPTY_SALT,
1414
+ info: CARDANO_POE_HKDF_INFO_SLOTS_MAC,
1415
+ length: 32
1416
+ });
1417
+ const slotsMac = hmac(sha256$1, hmacKey, slotsHash);
1418
+ if (slotsMac.length !== SLOTS_MAC_LENGTH) {
1419
+ throw new Error(`internal: slots_mac.length=${slotsMac.length}, expected ${SLOTS_MAC_LENGTH}`);
1420
+ }
1421
+ return slotsMac;
1494
1422
  }
1495
- function splitLengths(lst, name) {
1496
- return splitCoder(name, ...lst.map((i) => {
1497
- if (typeof i.lengths[name] !== "number")
1498
- throw new Error("wrong length: " + name);
1499
- return i.lengths[name];
1500
- }));
1423
+
1424
+ // ../poe-standard/src/chunked.ts
1425
+ var CHUNK_MAX_BYTES2 = 64;
1426
+ var UTF8_ENCODER2 = new TextEncoder();
1427
+ function chunkBytes(value) {
1428
+ if (value.length === 0) return [new Uint8Array(0)];
1429
+ const chunks = [];
1430
+ for (let i = 0; i < value.length; i += CHUNK_MAX_BYTES2) {
1431
+ chunks.push(value.subarray(i, Math.min(i + CHUNK_MAX_BYTES2, value.length)));
1432
+ }
1433
+ return chunks;
1501
1434
  }
1502
- function expandSeedXof(xof) {
1503
- return ((seed, seedLen) => xof(seed, { dkLen: seedLen }));
1435
+ function chunkUri(uri) {
1436
+ const bytes = UTF8_ENCODER2.encode(uri);
1437
+ if (bytes.length === 0) return [""];
1438
+ if (bytes.length <= CHUNK_MAX_BYTES2) return [uri];
1439
+ const decoder = new TextDecoder("utf-8", { fatal: true });
1440
+ const chunks = [];
1441
+ let cursor = 0;
1442
+ while (cursor < bytes.length) {
1443
+ let end = Math.min(cursor + CHUNK_MAX_BYTES2, bytes.length);
1444
+ while (end < bytes.length && (bytes[end] & 192) === 128) end--;
1445
+ chunks.push(decoder.decode(bytes.subarray(cursor, end)));
1446
+ cursor = end;
1447
+ }
1448
+ return chunks;
1504
1449
  }
1505
- function combineKeys(realSeedLen, expandSeed_, ...ck_) {
1506
- const expandSeed = expandSeed_;
1507
- const ck = ck_;
1508
- const seedCoder = splitLengths(ck, "seed");
1509
- const pkCoder = splitLengths(ck, "publicKey");
1510
- anumber(realSeedLen);
1511
- function expandDecapsulationKey(seed) {
1512
- abytes(seed, realSeedLen);
1513
- const expandedRaw = expandSeed(seed, seedCoder.bytesLen);
1514
- const expandedSeed = expandedRaw.buffer === seed.buffer ? copyBytes(expandedRaw) : expandedRaw;
1515
- const expanded = [];
1516
- const keySecret = [];
1517
- const secretKey = [];
1518
- const publicKey = [];
1519
- let ok = false;
1520
- try {
1521
- for (const part of seedCoder.decode(expandedSeed))
1522
- expanded.push(copyBytes(part));
1523
- for (let i = 0; i < ck.length; i++) {
1524
- const keys = ck[i].keygen(expanded[i]);
1525
- keySecret.push(keys.secretKey);
1526
- secretKey.push(copyBytes(keys.secretKey));
1527
- publicKey.push(keys.publicKey);
1528
- }
1529
- ok = true;
1530
- return { secretKey, publicKey };
1531
- } finally {
1532
- cleanBytes(expandedSeed, expanded, keySecret);
1533
- if (!ok)
1534
- cleanBytes(secretKey);
1535
- }
1450
+
1451
+ // src/client/off-host-sign.ts
1452
+ var EMPTY_BYTES2 = new Uint8Array(0);
1453
+ var ED25519_PUBLIC_KEY_LENGTH = 32;
1454
+ var ED25519_SIGNATURE_LENGTH = 64;
1455
+ var OffHostSignError = class extends Error {
1456
+ code;
1457
+ constructor(code, message) {
1458
+ super(message);
1459
+ this.name = "OffHostSignError";
1460
+ this.code = code;
1536
1461
  }
1537
- return {
1538
- info: { lengths: { seed: realSeedLen, publicKey: pkCoder.bytesLen, secretKey: realSeedLen } },
1539
- getPublicKey(secretKey) {
1540
- return this.keygen(secretKey).publicKey;
1541
- },
1542
- keygen(seed = randomBytes(realSeedLen)) {
1543
- const { publicKey: pk, secretKey } = expandDecapsulationKey(seed);
1544
- try {
1545
- const publicKey = pkCoder.encode(pk);
1546
- return { secretKey: seed, publicKey };
1547
- } finally {
1548
- cleanBytes(pk);
1549
- cleanBytes(secretKey);
1550
- }
1551
- },
1552
- expandDecapsulationKey,
1553
- realSeedLen
1554
- };
1462
+ };
1463
+ function buildToSign(record) {
1464
+ const body = encodeRecordBodyForSigning(record);
1465
+ const out = new Uint8Array(CARDANO_POE_SIG_DOMAIN_PREFIX_BYTES.length + body.length);
1466
+ out.set(CARDANO_POE_SIG_DOMAIN_PREFIX_BYTES, 0);
1467
+ out.set(body, CARDANO_POE_SIG_DOMAIN_PREFIX_BYTES.length);
1468
+ return out;
1555
1469
  }
1556
- function combineKEMS(realSeedLen, realMsgLen, expandSeed, combiner, ...kems) {
1557
- const rawCombiner = combiner;
1558
- const rawKems = kems;
1559
- const keys = combineKeys(realSeedLen, expandSeed, ...rawKems);
1560
- const ctCoder = splitLengths(rawKems, "cipherText");
1561
- const pkCoder = splitLengths(rawKems, "publicKey");
1562
- const msgCoder = splitLengths(rawKems, "msg");
1563
- anumber(realMsgLen);
1564
- const lengths = Object.freeze({
1565
- ...keys.info.lengths,
1566
- msg: realMsgLen,
1567
- msgRand: msgCoder.bytesLen,
1568
- cipherText: ctCoder.bytesLen
1569
- });
1570
- return Object.freeze({
1571
- lengths,
1572
- getPublicKey: keys.getPublicKey,
1573
- keygen: keys.keygen,
1574
- encapsulate(pk, randomness = randomBytes(msgCoder.bytesLen)) {
1575
- const pks = pkCoder.decode(pk);
1576
- const rand = msgCoder.decode(randomness);
1577
- const sharedSecret = [];
1578
- const cipherText = [];
1579
- try {
1580
- for (let i = 0; i < rawKems.length; i++) {
1581
- const enc = rawKems[i].encapsulate(pks[i], rand[i]);
1582
- sharedSecret.push(enc.sharedSecret);
1583
- cipherText.push(enc.cipherText);
1584
- }
1585
- return {
1586
- // Detach the combiner result before cleanup: a caller-provided combiner may alias one of
1587
- // the child sharedSecret buffers, and those child buffers are zeroized immediately below.
1588
- sharedSecret: copyBytes(rawCombiner(pks, cipherText, sharedSecret)),
1589
- cipherText: ctCoder.encode(cipherText)
1590
- };
1591
- } finally {
1592
- cleanBytes(sharedSecret, cipherText);
1593
- }
1594
- },
1595
- decapsulate(ct, seed) {
1596
- const cts = ctCoder.decode(ct);
1597
- const { publicKey, secretKey } = keys.expandDecapsulationKey(seed);
1598
- const sharedSecret = rawKems.map((i, j) => i.decapsulate(cts[j], secretKey[j]));
1599
- try {
1600
- return copyBytes(rawCombiner(publicKey, cts, sharedSecret));
1601
- } finally {
1602
- cleanBytes(secretKey, sharedSecret);
1603
- }
1604
- }
1605
- });
1470
+ function encodePath1ProtectedHeader(signerPubkey) {
1471
+ const protectedHeader = /* @__PURE__ */ new Map([
1472
+ [1, -8],
1473
+ [4, signerPubkey]
1474
+ ]);
1475
+ const protectedHeaderBytes = encodeCanonicalCbor(protectedHeader);
1476
+ return { protectedHeader, protectedHeaderBytes };
1606
1477
  }
1607
- var x25519kem = /* @__PURE__ */ ecdhKem(x25519);
1608
- var ml_kem768_x25519 = /* @__PURE__ */ (() => combineKEMS(
1609
- 32,
1610
- 32,
1611
- expandSeedXof(shake256),
1612
- // Awesome label, so much escaping hell in a single line.
1613
- (pk, ct, ss) => sha3_256(concatBytes(ss[0], ss[1], ct[1], pk[1], asciiToBytes("\\.//^\\"))),
1614
- ml_kem768,
1615
- x25519kem
1616
- ))();
1617
- var XWing = /* @__PURE__ */ (() => ml_kem768_x25519)();
1618
- function chacha20Poly1305Encrypt(opts2) {
1619
- return chacha20poly1305(opts2.key, opts2.nonce, opts2.aad).encrypt(opts2.plaintext);
1478
+ function prepareSigStructure(args) {
1479
+ if (args.signerPubkey.length !== ED25519_PUBLIC_KEY_LENGTH) {
1480
+ throw new OffHostSignError(
1481
+ "INVALID_PUBKEY_LENGTH",
1482
+ `signerPubkey must be 32 bytes (Ed25519 raw public key), got ${args.signerPubkey.length}`
1483
+ );
1484
+ }
1485
+ const { protectedHeaderBytes } = encodePath1ProtectedHeader(args.signerPubkey);
1486
+ const recordBodyCbor = encodeRecordBodyForSigning(args.record);
1487
+ const sigStructureBytes = buildLabel309SigStructure({
1488
+ bodyProtectedBytes: protectedHeaderBytes,
1489
+ recordBodyCbor
1490
+ });
1491
+ return { sigStructureBytes, protectedHeaderBytes };
1620
1492
  }
1621
- function xchacha20Poly1305Encrypt(opts2) {
1622
- return xchacha20poly1305(opts2.key, opts2.nonce, opts2.aad).encrypt(opts2.plaintext);
1493
+ function assembleCoseSign1(args) {
1494
+ if (args.signerPubkey.length !== ED25519_PUBLIC_KEY_LENGTH) {
1495
+ throw new OffHostSignError(
1496
+ "INVALID_PUBKEY_LENGTH",
1497
+ `signerPubkey must be 32 bytes (Ed25519 raw public key), got ${args.signerPubkey.length}`
1498
+ );
1499
+ }
1500
+ if (args.signature.length !== ED25519_SIGNATURE_LENGTH) {
1501
+ throw new OffHostSignError(
1502
+ "INVALID_SIGNATURE_LENGTH",
1503
+ `signature must be 64 bytes (Ed25519 raw signature), got ${args.signature.length}`
1504
+ );
1505
+ }
1506
+ const { protectedHeader } = encodePath1ProtectedHeader(args.signerPubkey);
1507
+ const coseSign1Bytes = encodeCoseSign1({
1508
+ protectedHeader,
1509
+ unprotectedHeader: /* @__PURE__ */ new Map(),
1510
+ payload: null,
1511
+ signature: args.signature
1512
+ });
1513
+ const chunks = chunkBytes(coseSign1Bytes);
1514
+ const sigEntry = { cose_sign1: chunks };
1515
+ return { coseSign1Bytes, sigEntry };
1623
1516
  }
1624
- function hkdfSha256(opts2) {
1625
- return hkdf(sha256$1, opts2.ikm, opts2.salt, opts2.info, opts2.length);
1517
+ function prepareSigStructureHashed(args) {
1518
+ if (args.signerPubkey.length !== ED25519_PUBLIC_KEY_LENGTH) {
1519
+ throw new OffHostSignError(
1520
+ "INVALID_PUBKEY_LENGTH",
1521
+ `signerPubkey must be 32 bytes (Ed25519 raw public key), got ${args.signerPubkey.length}`
1522
+ );
1523
+ }
1524
+ const { protectedHeaderBytes } = encodePath1ProtectedHeader(args.signerPubkey);
1525
+ const toSign = buildToSign(args.record);
1526
+ const toSignHashBytes = blake2b224(toSign);
1527
+ const sigStructureBytes = buildSigStructure({
1528
+ context: "Signature1",
1529
+ bodyProtectedBytes: protectedHeaderBytes,
1530
+ externalAad: EMPTY_BYTES2,
1531
+ payload: toSignHashBytes
1532
+ });
1533
+ return { sigStructureBytes, protectedHeaderBytes, toSignHashBytes };
1626
1534
  }
1627
- var MLKEM768X25519_PUBLIC_KEY_LENGTH = 1216;
1628
- var MLKEM768X25519_ENC_LENGTH = 1120;
1629
- var MLKEM768X25519_ESEED_LENGTH = 64;
1630
- function mlkem768x25519Encapsulate(opts2) {
1631
- if (opts2.publicKey.length !== MLKEM768X25519_PUBLIC_KEY_LENGTH) {
1632
- throw new Error(
1633
- `mlkem768x25519 public key must be ${MLKEM768X25519_PUBLIC_KEY_LENGTH} bytes, got ${opts2.publicKey.length}`
1535
+ function assembleCoseSign1Hashed(args) {
1536
+ if (args.signerPubkey.length !== ED25519_PUBLIC_KEY_LENGTH) {
1537
+ throw new OffHostSignError(
1538
+ "INVALID_PUBKEY_LENGTH",
1539
+ `signerPubkey must be 32 bytes (Ed25519 raw public key), got ${args.signerPubkey.length}`
1634
1540
  );
1635
1541
  }
1636
- if (opts2.eseed !== void 0 && opts2.eseed.length !== MLKEM768X25519_ESEED_LENGTH) {
1637
- throw new Error(
1638
- `mlkem768x25519 eseed must be ${MLKEM768X25519_ESEED_LENGTH} bytes, got ${opts2.eseed.length}`
1542
+ if (args.signature.length !== ED25519_SIGNATURE_LENGTH) {
1543
+ throw new OffHostSignError(
1544
+ "INVALID_SIGNATURE_LENGTH",
1545
+ `signature must be 64 bytes (Ed25519 raw signature), got ${args.signature.length}`
1639
1546
  );
1640
1547
  }
1641
- const { cipherText, sharedSecret } = XWing.encapsulate(opts2.publicKey, opts2.eseed);
1642
- return { enc: cipherText, ss: sharedSecret };
1548
+ const { protectedHeader } = encodePath1ProtectedHeader(args.signerPubkey);
1549
+ const unprotectedHeader = /* @__PURE__ */ new Map([["hashed", true]]);
1550
+ const coseSign1Bytes = encodeCoseSign1({
1551
+ protectedHeader,
1552
+ unprotectedHeader,
1553
+ payload: null,
1554
+ signature: args.signature
1555
+ });
1556
+ const chunks = chunkBytes(coseSign1Bytes);
1557
+ const sigEntry = { cose_sign1: chunks };
1558
+ return { coseSign1Bytes, sigEntry };
1643
1559
  }
1644
- var X25519LowOrderPointError = class extends Error {
1645
- code = "X25519_LOW_ORDER_POINT";
1646
- constructor(options) {
1647
- super("x25519 ECDH rejected: peer public key is a small-order point", options);
1648
- this.name = "X25519LowOrderPointError";
1560
+
1561
+ // src/client/http-error.ts
1562
+ var CANONICAL_PROBLEM_KEYS = /* @__PURE__ */ new Set([
1563
+ "type",
1564
+ "title",
1565
+ "status",
1566
+ "detail",
1567
+ "code",
1568
+ "trace_id",
1569
+ "errors",
1570
+ "instance"
1571
+ ]);
1572
+ function extractProblemExtensions(problem) {
1573
+ const out = {};
1574
+ for (const [key, value] of Object.entries(problem)) {
1575
+ if (!CANONICAL_PROBLEM_KEYS.has(key)) {
1576
+ out[key] = value;
1577
+ }
1578
+ }
1579
+ return out;
1580
+ }
1581
+ var Label309HttpError = class extends Error {
1582
+ problem;
1583
+ code;
1584
+ httpStatus;
1585
+ title;
1586
+ detail;
1587
+ type;
1588
+ traceId;
1589
+ instance;
1590
+ errors;
1591
+ extensions;
1592
+ requestId;
1593
+ retryAfterSeconds;
1594
+ constructor(init) {
1595
+ super(init.problem.detail || `${init.problem.title} (HTTP ${init.problem.status})`);
1596
+ this.name = "Label309HttpError";
1597
+ this.problem = init.problem;
1598
+ this.code = init.problem.code;
1599
+ this.httpStatus = init.problem.status;
1600
+ this.title = init.problem.title;
1601
+ this.detail = init.problem.detail;
1602
+ this.type = init.problem.type;
1603
+ this.traceId = init.problem.trace_id;
1604
+ this.instance = init.problem.instance;
1605
+ this.errors = init.problem.errors;
1606
+ this.extensions = init.extensions ?? extractProblemExtensions(init.problem);
1607
+ this.requestId = init.requestId ?? init.problem.trace_id;
1608
+ this.retryAfterSeconds = init.retryAfterSeconds;
1649
1609
  }
1650
1610
  };
1651
- var NOBLE_LOW_ORDER_MESSAGE = "invalid private or public key received";
1652
- function x25519PublicKey(opts2) {
1653
- return x25519.getPublicKey(opts2.secretKey);
1611
+
1612
+ // src/client/batch-empty-error.ts
1613
+ var BatchEmptyError = class extends Label309HttpError {
1614
+ constructor(init) {
1615
+ super(init);
1616
+ this.name = "BatchEmptyError";
1617
+ }
1618
+ };
1619
+
1620
+ // src/client/batch-too-large-error.ts
1621
+ function readInt(value) {
1622
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
1654
1623
  }
1655
- function x25519Ecdh(opts2) {
1624
+ var BatchTooLargeError = class extends Label309HttpError {
1625
+ max;
1626
+ got;
1627
+ constructor(init) {
1628
+ super(init);
1629
+ this.name = "BatchTooLargeError";
1630
+ this.max = readInt(this.extensions["max"]);
1631
+ this.got = readInt(this.extensions["got"]);
1632
+ }
1633
+ };
1634
+
1635
+ // src/client/forbidden-error.ts
1636
+ var ForbiddenError = class extends Label309HttpError {
1637
+ constructor(init) {
1638
+ super(init);
1639
+ this.name = "ForbiddenError";
1640
+ }
1641
+ };
1642
+
1643
+ // src/client/idempotency-conflict-error.ts
1644
+ var IdempotencyConflictError = class extends Label309HttpError {
1645
+ constructor(init) {
1646
+ super(init);
1647
+ this.name = "IdempotencyConflictError";
1648
+ }
1649
+ };
1650
+
1651
+ // src/client/insufficient-funds-error.ts
1652
+ function readBigIntString(value) {
1653
+ if (typeof value !== "string") return void 0;
1654
+ if (!/^-?[0-9]+$/.test(value)) return void 0;
1656
1655
  try {
1657
- return x25519.getSharedSecret(opts2.secretKey, opts2.theirPublicKey);
1658
- } catch (e) {
1659
- if (e instanceof Error && e.message === NOBLE_LOW_ORDER_MESSAGE) {
1660
- throw new X25519LowOrderPointError({ cause: e });
1661
- }
1662
- throw e;
1656
+ return BigInt(value);
1657
+ } catch {
1658
+ return void 0;
1663
1659
  }
1664
1660
  }
1665
- var EciesSealedPoeError = class extends Error {
1666
- code;
1667
- constructor(code, message, options) {
1668
- super(message, options);
1669
- this.name = "EciesSealedPoeError";
1670
- this.code = code;
1661
+ function readString(value) {
1662
+ return typeof value === "string" ? value : void 0;
1663
+ }
1664
+ var InsufficientFundsError = class extends Label309HttpError {
1665
+ balanceUsdMicros;
1666
+ requiredUsdMicros;
1667
+ topUpUrl;
1668
+ constructor(init) {
1669
+ super(init);
1670
+ this.name = "InsufficientFundsError";
1671
+ this.balanceUsdMicros = readBigIntString(this.extensions["balance_usd_micros"]);
1672
+ this.requiredUsdMicros = readBigIntString(this.extensions["required_usd_micros"]);
1673
+ this.topUpUrl = readString(this.extensions["top_up_url"]);
1674
+ }
1675
+ };
1676
+
1677
+ // src/client/insufficient-scope-error.ts
1678
+ function readScopeArray(value) {
1679
+ if (!Array.isArray(value)) return [];
1680
+ return value.filter((entry) => typeof entry === "string");
1681
+ }
1682
+ var InsufficientScopeError = class extends Label309HttpError {
1683
+ requiredScopes;
1684
+ grantedScopes;
1685
+ constructor(init) {
1686
+ super(init);
1687
+ this.name = "InsufficientScopeError";
1688
+ this.requiredScopes = readScopeArray(this.extensions["required"]);
1689
+ this.grantedScopes = readScopeArray(this.extensions["granted"]);
1690
+ }
1691
+ /** Convenience for the single-scope case; first entry of `requiredScopes`. */
1692
+ get requiredScope() {
1693
+ return this.requiredScopes[0];
1694
+ }
1695
+ };
1696
+
1697
+ // src/client/internal-server-error.ts
1698
+ var InternalServerError = class extends Label309HttpError {
1699
+ constructor(init) {
1700
+ super(init);
1701
+ this.name = "InternalServerError";
1702
+ }
1703
+ };
1704
+
1705
+ // src/client/invalid-body-error.ts
1706
+ var InvalidBodyError = class extends Label309HttpError {
1707
+ constructor(init) {
1708
+ super(init);
1709
+ this.name = "InvalidBodyError";
1710
+ }
1711
+ };
1712
+
1713
+ // src/client/malformed-cbor-error.ts
1714
+ var MalformedCborError = class extends Label309HttpError {
1715
+ constructor(init) {
1716
+ super(init);
1717
+ this.name = "MalformedCborError";
1718
+ }
1719
+ };
1720
+
1721
+ // src/client/not-found-error.ts
1722
+ var NotFoundError = class extends Label309HttpError {
1723
+ constructor(init) {
1724
+ super(init);
1725
+ this.name = "NotFoundError";
1726
+ }
1727
+ };
1728
+
1729
+ // src/client/quote-already-consumed-error.ts
1730
+ function readString2(value) {
1731
+ return typeof value === "string" ? value : void 0;
1732
+ }
1733
+ var QuoteAlreadyConsumedError = class extends Label309HttpError {
1734
+ quoteId;
1735
+ constructor(init) {
1736
+ super(init);
1737
+ this.name = "QuoteAlreadyConsumedError";
1738
+ this.quoteId = readString2(this.extensions["quote_id"]);
1739
+ }
1740
+ };
1741
+
1742
+ // src/client/quote-expired-error.ts
1743
+ function readString3(value) {
1744
+ return typeof value === "string" ? value : void 0;
1745
+ }
1746
+ var QuoteExpiredError = class extends Label309HttpError {
1747
+ quoteId;
1748
+ constructor(init) {
1749
+ super(init);
1750
+ this.name = "QuoteExpiredError";
1751
+ this.quoteId = readString3(this.extensions["quote_id"]);
1671
1752
  }
1672
1753
  };
1673
- function encodeCanonicalCbor4(value) {
1674
- return encode(value, {
1675
- cde: true,
1676
- collapseBigInts: true,
1677
- rejectDuplicateKeys: true,
1678
- sortKeys: sortCoreDeterministic
1679
- });
1754
+
1755
+ // src/client/quote-not-found-error.ts
1756
+ function readString4(value) {
1757
+ return typeof value === "string" ? value : void 0;
1680
1758
  }
1681
- var CHUNK_MAX_BYTES2 = 64;
1682
- function chunkKemCt(value) {
1683
- if (value.length === 0) {
1684
- throw new Error("chunkKemCt: refusing to chunk an empty byte string");
1759
+ var QuoteNotFoundError = class extends Label309HttpError {
1760
+ quoteId;
1761
+ constructor(init) {
1762
+ super(init);
1763
+ this.name = "QuoteNotFoundError";
1764
+ this.quoteId = readString4(this.extensions["quote_id"]);
1685
1765
  }
1686
- const chunks = [];
1687
- for (let i = 0; i < value.length; i += CHUNK_MAX_BYTES2) {
1688
- chunks.push(value.subarray(i, Math.min(i + CHUNK_MAX_BYTES2, value.length)));
1766
+ };
1767
+
1768
+ // src/client/rate-limited-error.ts
1769
+ var RateLimitedError = class extends Label309HttpError {
1770
+ constructor(init) {
1771
+ super(init);
1772
+ this.name = "RateLimitedError";
1689
1773
  }
1690
- return chunks;
1691
- }
1692
- function joinKemCt(chunks) {
1693
- let total = 0;
1694
- for (const c of chunks) total += c.length;
1695
- const out = new Uint8Array(total);
1696
- let offset = 0;
1697
- for (const c of chunks) {
1698
- out.set(c, offset);
1699
- offset += c.length;
1774
+ };
1775
+
1776
+ // src/client/record-not-found-error.ts
1777
+ var RecordNotFoundError = class extends Label309HttpError {
1778
+ constructor(init) {
1779
+ super(init);
1780
+ this.name = "RecordNotFoundError";
1700
1781
  }
1701
- return out;
1702
- }
1703
- function slotsToMacCbor(slots, kem) {
1704
- let value;
1705
- if (kem === "x25519") {
1706
- value = slots.map((s) => ({ epk: s.epk, wrap: s.wrap }));
1707
- } else {
1708
- value = slots.map((s) => ({
1709
- // Canonicalize the chunk boundaries before the MAC commits to them:
1710
- // reassemble the logical ciphertext and re-split into canonical ≤ 64-byte
1711
- // chunks. The on-wire `kem_ct` array is a transport detail (the Cardano
1712
- // ledger's 64-byte metadatum cap), and a hostile or non-canonical chunking
1713
- // ([1, 63, …] instead of [64, …]) reassembles to the SAME bytes — so the
1714
- // MAC must be invariant to it. Committing to the verbatim wire chunks would
1715
- // let an attacker re-chunk an honest envelope and break the slots_mac match
1716
- // for an honest recipient. Honest (already-64B-chunked) records are
1717
- // unchanged; a real byte flip still changes the reassembled bytes and is
1718
- // still rejected.
1719
- kem_ct: chunkKemCt(joinKemCt(s.kem_ct)),
1720
- wrap: s.wrap
1721
- }));
1722
- }
1723
- return encodeCanonicalCbor4(value);
1724
- }
1725
- var CARDANO_POE_HKDF_INFO_KEK = new TextEncoder().encode("cardano-poe-kek-v1");
1726
- var CARDANO_POE_HKDF_INFO_KEK_MLKEM768X25519 = new TextEncoder().encode(
1727
- "cardano-poe-kek-mlkem768x25519-v1"
1728
- );
1729
- var CARDANO_POE_HKDF_INFO_SLOTS_MAC = new TextEncoder().encode(
1730
- "cardano-poe-slots-mac-v1"
1731
- );
1732
- var ZERO_NONCE_12 = new Uint8Array(12);
1733
- var EMPTY_SALT = new Uint8Array(0);
1734
- var X25519_PUBLIC_KEY_LENGTH = 32;
1735
- var X25519_SECRET_KEY_LENGTH = 32;
1736
- var CEK_LENGTH = 32;
1737
- var NONCE_LENGTH = 24;
1738
- var WRAP_LENGTH = 48;
1739
- var SLOTS_MAC_LENGTH = 32;
1740
- if (CARDANO_POE_HKDF_INFO_KEK.length !== 18) {
1741
- throw new Error("CARDANO_POE_HKDF_INFO_KEK byte-length invariant violated (expected 18)");
1742
- }
1743
- if (CARDANO_POE_HKDF_INFO_KEK_MLKEM768X25519.length !== 33) {
1744
- throw new Error(
1745
- "CARDANO_POE_HKDF_INFO_KEK_MLKEM768X25519 byte-length invariant violated (expected 33)"
1746
- );
1747
- }
1748
- if (CARDANO_POE_HKDF_INFO_SLOTS_MAC.length !== 24) {
1749
- throw new Error("CARDANO_POE_HKDF_INFO_SLOTS_MAC byte-length invariant violated (expected 24)");
1782
+ };
1783
+
1784
+ // src/client/service-unavailable-error.ts
1785
+ var ServiceUnavailableError = class extends Label309HttpError {
1786
+ constructor(init) {
1787
+ super(init);
1788
+ this.name = "ServiceUnavailableError";
1789
+ }
1790
+ };
1791
+
1792
+ // src/client/unauthorized-error.ts
1793
+ var UnauthorizedError = class extends Label309HttpError {
1794
+ constructor(init) {
1795
+ super(init);
1796
+ this.name = "UnauthorizedError";
1797
+ }
1798
+ };
1799
+
1800
+ // src/client/validation-failed-error.ts
1801
+ var ValidationFailedError = class extends Label309HttpError {
1802
+ constructor(init) {
1803
+ super(init);
1804
+ this.name = "ValidationFailedError";
1805
+ }
1806
+ };
1807
+
1808
+ // src/client/parse-http-error.ts
1809
+ function asString(value) {
1810
+ return typeof value === "string" ? value : void 0;
1750
1811
  }
1751
- if (ZERO_NONCE_12.length !== 12) {
1752
- throw new Error("ZERO_NONCE_12 byte-length invariant violated (expected 12)");
1812
+ function asNumber(value) {
1813
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
1753
1814
  }
1754
- function concat(a, b) {
1755
- const out = new Uint8Array(a.length + b.length);
1756
- out.set(a, 0);
1757
- out.set(b, a.length);
1815
+ function asProblemErrorEntries(value) {
1816
+ if (!Array.isArray(value)) return void 0;
1817
+ const out = [];
1818
+ for (const entry of value) {
1819
+ if (entry === null || typeof entry !== "object") continue;
1820
+ const e = entry;
1821
+ out.push({
1822
+ field: typeof e["field"] === "string" ? e["field"] : "",
1823
+ code: typeof e["code"] === "string" ? e["code"] : "",
1824
+ detail: typeof e["detail"] === "string" ? e["detail"] : ""
1825
+ });
1826
+ }
1758
1827
  return out;
1759
1828
  }
1760
- function uniformIndexBelow(m) {
1761
- const limit = 4294967296 - 4294967296 % m;
1762
- const buf = new Uint32Array(1);
1763
- let x;
1764
- do {
1765
- crypto.getRandomValues(buf);
1766
- x = buf[0];
1767
- } while (x >= limit);
1768
- return x % m;
1829
+ function synthesiseProblem(httpStatus, requestId) {
1830
+ const code = `http-${httpStatus}`;
1831
+ return {
1832
+ type: `about:blank`,
1833
+ title: `HTTP ${httpStatus}`,
1834
+ status: httpStatus,
1835
+ detail: `Server returned HTTP ${httpStatus} without a problem+json body.`,
1836
+ code,
1837
+ trace_id: requestId ?? ""
1838
+ };
1769
1839
  }
1770
- function csprngShuffle(arr) {
1771
- for (let i = arr.length - 1; i > 0; i--) {
1772
- const j = uniformIndexBelow(i + 1);
1773
- const tmp = arr[i];
1774
- arr[i] = arr[j];
1775
- arr[j] = tmp;
1840
+ function toProblemDetails(httpStatus, body, requestId) {
1841
+ if (body === null || typeof body !== "object") {
1842
+ return synthesiseProblem(httpStatus, requestId);
1843
+ }
1844
+ const b = body;
1845
+ const code = asString(b["code"]);
1846
+ const status = asNumber(b["status"]) ?? httpStatus;
1847
+ const title = asString(b["title"]);
1848
+ if (code === void 0 && title === void 0) {
1849
+ return synthesiseProblem(httpStatus, requestId);
1776
1850
  }
1851
+ const errors = asProblemErrorEntries(b["errors"]);
1852
+ const base = {
1853
+ ...b,
1854
+ // RFC 7807 §4.2: `about:blank` is the default when no type URI is supplied.
1855
+ // The client is gateway-agnostic, so it must not invent a vendor-specific
1856
+ // problem-type namespace; the machine-readable discriminator is `code`.
1857
+ type: asString(b["type"]) ?? "about:blank",
1858
+ title: title ?? `HTTP ${status}`,
1859
+ status,
1860
+ detail: asString(b["detail"]) ?? "",
1861
+ code: code ?? `http-${status}`,
1862
+ trace_id: asString(b["trace_id"]) ?? requestId ?? ""
1863
+ };
1864
+ if (errors !== void 0) base["errors"] = errors;
1865
+ return base;
1777
1866
  }
1778
- function wrapSlotX25519(args) {
1779
- const privEph = args.privEph ?? randomBytes$1(X25519_SECRET_KEY_LENGTH);
1780
- if (privEph.length !== X25519_SECRET_KEY_LENGTH) {
1781
- throw new EciesSealedPoeError(
1782
- "INVALID_EPHEMERAL_SECRET_LENGTH",
1783
- `ephemeralSecrets[${args.slotIdx}] MUST be exactly ${X25519_SECRET_KEY_LENGTH} bytes, got ${privEph.length}`
1784
- );
1867
+ function parseHttpError(args) {
1868
+ const problem = toProblemDetails(args.httpStatus, args.body, args.requestId);
1869
+ const extensions = extractProblemExtensions(problem);
1870
+ const init = {
1871
+ problem,
1872
+ extensions,
1873
+ requestId: args.requestId,
1874
+ retryAfterSeconds: args.retryAfterSeconds
1875
+ };
1876
+ switch (problem.code) {
1877
+ case "unauthorized":
1878
+ return new UnauthorizedError(init);
1879
+ case "forbidden":
1880
+ case "csrf-invalid":
1881
+ return new ForbiddenError(init);
1882
+ case "insufficient-scope":
1883
+ return new InsufficientScopeError(init);
1884
+ case "insufficient-funds":
1885
+ return new InsufficientFundsError(init);
1886
+ case "quote-expired":
1887
+ return new QuoteExpiredError(init);
1888
+ case "quote-not-found":
1889
+ return new QuoteNotFoundError(init);
1890
+ case "quote-already-consumed":
1891
+ return new QuoteAlreadyConsumedError(init);
1892
+ case "not-found":
1893
+ return new NotFoundError(init);
1894
+ case "record-not-found":
1895
+ return new RecordNotFoundError(init);
1896
+ case "idempotency-key-conflict":
1897
+ return new IdempotencyConflictError(init);
1898
+ case "rate-limited":
1899
+ return new RateLimitedError(init);
1900
+ case "validation-failed":
1901
+ return new ValidationFailedError(init);
1902
+ case "invalid-body":
1903
+ return new InvalidBodyError(init);
1904
+ case "malformed-cbor":
1905
+ return new MalformedCborError(init);
1906
+ case "batch-too-large":
1907
+ return new BatchTooLargeError(init);
1908
+ case "batch-empty":
1909
+ return new BatchEmptyError(init);
1910
+ case "internal-error":
1911
+ return new InternalServerError(init);
1912
+ // A gateway that prices on a live FX oracle may surface a transient
1913
+ // `fx-stale` pricing outage; to a vendor-neutral client that is just a
1914
+ // temporary inability to serve, i.e. a service-unavailable condition.
1915
+ case "service-unavailable":
1916
+ case "fx-stale":
1917
+ return new ServiceUnavailableError(init);
1918
+ default:
1919
+ return new Label309HttpError(init);
1785
1920
  }
1786
- const epk = x25519PublicKey({ secretKey: privEph });
1787
- const shared = x25519Ecdh({ secretKey: privEph, theirPublicKey: args.pubR });
1788
- const kek = hkdfSha256({
1789
- ikm: shared,
1790
- salt: concat(epk, args.pubR),
1791
- info: CARDANO_POE_HKDF_INFO_KEK,
1792
- length: 32
1793
- });
1794
- const wrap = chacha20Poly1305Encrypt({
1795
- key: kek,
1796
- nonce: ZERO_NONCE_12,
1797
- aad: CARDANO_POE_HKDF_INFO_KEK,
1798
- plaintext: args.cek
1799
- });
1800
- if (wrap.length !== WRAP_LENGTH) {
1801
- throw new Error(`internal: wrap.length=${wrap.length}, expected ${WRAP_LENGTH}`);
1921
+ }
1922
+
1923
+ // src/client/http-helpers.ts
1924
+ async function readJson(response) {
1925
+ const text = await response.text();
1926
+ if (text.length === 0) return null;
1927
+ try {
1928
+ return JSON.parse(text);
1929
+ } catch {
1930
+ return null;
1802
1931
  }
1803
- return { epk, wrap };
1804
1932
  }
1805
- function wrapSlotMlkem768X25519(args) {
1806
- const { enc, ss } = mlkem768x25519Encapsulate({
1807
- publicKey: args.pubR,
1808
- ...args.eseed !== void 0 ? { eseed: args.eseed } : {}
1809
- });
1810
- if (enc.length !== MLKEM768X25519_ENC_LENGTH) {
1811
- throw new Error(`internal: enc.length=${enc.length}, expected ${MLKEM768X25519_ENC_LENGTH}`);
1812
- }
1813
- const kek = hkdfSha256({
1814
- ikm: ss,
1815
- salt: EMPTY_SALT,
1816
- info: CARDANO_POE_HKDF_INFO_KEK_MLKEM768X25519,
1817
- length: 32
1818
- });
1819
- const wrap = chacha20Poly1305Encrypt({
1820
- key: kek,
1821
- nonce: ZERO_NONCE_12,
1822
- aad: CARDANO_POE_HKDF_INFO_KEK_MLKEM768X25519,
1823
- plaintext: args.cek
1933
+ function parseRetryAfter(header) {
1934
+ if (header === null) return void 0;
1935
+ const parsed = Number(header);
1936
+ return Number.isFinite(parsed) ? parsed : void 0;
1937
+ }
1938
+ async function throwIfNotOk(response) {
1939
+ if (response.ok) return;
1940
+ const body = await readJson(response);
1941
+ const requestId = response.headers.get("x-request-id") ?? void 0;
1942
+ const retryAfterSeconds = parseRetryAfter(response.headers.get("retry-after"));
1943
+ throw parseHttpError({ httpStatus: response.status, body, requestId, retryAfterSeconds });
1944
+ }
1945
+
1946
+ // src/client/account.ts
1947
+ function buildHeaders(apiKey) {
1948
+ const headers = new Headers({
1949
+ "content-type": "application/json",
1950
+ accept: "application/json"
1824
1951
  });
1825
- if (wrap.length !== WRAP_LENGTH) {
1826
- throw new Error(`internal: wrap.length=${wrap.length}, expected ${WRAP_LENGTH}`);
1827
- }
1828
- return { kem_ct: chunkKemCt(enc), wrap };
1952
+ if (apiKey !== void 0) headers.set("authorization", `Bearer ${apiKey}`);
1953
+ return headers;
1829
1954
  }
1830
- function eciesSealedPoeWrap(args) {
1831
- const { plaintext, recipientPublicKeys } = args;
1832
- const kem = args.kem ?? "x25519";
1833
- const n = recipientPublicKeys.length;
1834
- if (n < 1) {
1835
- throw new EciesSealedPoeError(
1836
- "ENC_SLOTS_EMPTY",
1837
- `recipientPublicKeys.length=${n} must be >= 1`
1838
- );
1955
+ var AccountNamespace = class {
1956
+ config;
1957
+ constructor(config) {
1958
+ this.config = config;
1839
1959
  }
1840
- const expectedPubLen = kem === "x25519" ? X25519_PUBLIC_KEY_LENGTH : MLKEM768X25519_PUBLIC_KEY_LENGTH;
1841
- for (let i = 0; i < n; i++) {
1842
- const pub = recipientPublicKeys[i];
1843
- if (pub === void 0 || pub.length !== expectedPubLen) {
1844
- throw new EciesSealedPoeError(
1845
- "KEM_EPK_LENGTH_MISMATCH",
1846
- `recipientPublicKeys[${i}] MUST be exactly ${expectedPubLen} bytes for kem='${kem}'`
1847
- );
1848
- }
1960
+ /**
1961
+ * Fetch the caller's current prepaid USD balance.
1962
+ *
1963
+ * Returns `{ balanceUsdMicros }`, the gateway's `balance_usd_micros` field
1964
+ * (USD micro-cents as a decimal string). The string is preserved verbatim —
1965
+ * never parsed into a number — so no precision is lost. An account with no
1966
+ * ledger activity yet reads `"0"`.
1967
+ *
1968
+ * Requires authentication: 401 (UnauthorizedError) when anonymous, 403
1969
+ * (InsufficientScopeError) when the Bearer key lacks the `account:read`
1970
+ * scope.
1971
+ */
1972
+ async balance() {
1973
+ const response = await this.config.fetch(`${this.config.baseUrl}/api/v1/account/balance`, {
1974
+ method: "GET",
1975
+ headers: buildHeaders(this.config.apiKey)
1976
+ });
1977
+ await throwIfNotOk(response);
1978
+ const body = await readJson(response);
1979
+ return { balanceUsdMicros: body.balance_usd_micros };
1849
1980
  }
1850
- if (kem === "x25519") {
1851
- if (args.eseeds !== void 0) {
1852
- throw new EciesSealedPoeError(
1853
- "EPHEMERAL_SECRETS_COUNT_MISMATCH",
1854
- "eseeds is an X-Wing (mlkem768x25519) override and MUST NOT be supplied for kem='x25519'"
1855
- );
1856
- }
1857
- if (args.ephemeralSecrets !== void 0 && args.ephemeralSecrets.length !== n) {
1858
- throw new EciesSealedPoeError(
1859
- "EPHEMERAL_SECRETS_COUNT_MISMATCH",
1860
- `ephemeralSecrets.length=${args.ephemeralSecrets.length} must match recipientPublicKeys.length=${n}`
1861
- );
1862
- }
1863
- } else {
1864
- if (args.ephemeralSecrets !== void 0) {
1865
- throw new EciesSealedPoeError(
1866
- "EPHEMERAL_SECRETS_COUNT_MISMATCH",
1867
- "ephemeralSecrets is an X25519 override and MUST NOT be supplied for kem='mlkem768x25519'"
1868
- );
1869
- }
1870
- if (args.eseeds !== void 0) {
1871
- if (args.eseeds.length !== n) {
1872
- throw new EciesSealedPoeError(
1873
- "EPHEMERAL_SECRETS_COUNT_MISMATCH",
1874
- `eseeds.length=${args.eseeds.length} must match recipientPublicKeys.length=${n}`
1875
- );
1876
- }
1877
- for (let i = 0; i < n; i++) {
1878
- const eseed = args.eseeds[i];
1879
- if (eseed.length !== MLKEM768X25519_ESEED_LENGTH) {
1880
- throw new EciesSealedPoeError(
1881
- "INVALID_EPHEMERAL_SECRET_LENGTH",
1882
- `eseeds[${i}] MUST be exactly ${MLKEM768X25519_ESEED_LENGTH} bytes, got ${eseed.length}`
1883
- );
1884
- }
1885
- }
1886
- }
1981
+ };
1982
+
1983
+ // src/client/invalid-client-config-error.ts
1984
+ var InvalidClientConfigError = class extends Error {
1985
+ code = "INVALID_CLIENT_CONFIG";
1986
+ constructor(message) {
1987
+ super(message);
1988
+ this.name = "InvalidClientConfigError";
1887
1989
  }
1888
- const cek = args.cek ?? randomBytes$1(CEK_LENGTH);
1889
- const nonce = args.nonce ?? randomBytes$1(NONCE_LENGTH);
1890
- if (cek.length !== CEK_LENGTH) {
1891
- throw new EciesSealedPoeError(
1892
- "INVALID_CEK_LENGTH",
1893
- `cek MUST be exactly ${CEK_LENGTH} bytes, got ${cek.length}`
1990
+ };
1991
+
1992
+ // src/hex.ts
1993
+ function bytesToHex(bytes) {
1994
+ return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
1995
+ }
1996
+ function encodeCanonicalCbor4(value) {
1997
+ return encode(value, {
1998
+ cde: true,
1999
+ collapseBigInts: true,
2000
+ rejectDuplicateKeys: true,
2001
+ sortKeys: sortCoreDeterministic
2002
+ });
2003
+ }
2004
+ var LEAVES_LIST_FORMAT_V1 = "cardano-poe-merkle-leaves-v1";
2005
+ var TREE_ALG_RFC9162 = "rfc9162-sha256";
2006
+ var DIGEST_LENGTH2 = 32;
2007
+ var MerkleLeavesListError = class extends Error {
2008
+ code;
2009
+ constructor(code, message) {
2010
+ super(message ? `${code}: ${message}` : code);
2011
+ this.code = code;
2012
+ this.name = "MerkleLeavesListError";
2013
+ }
2014
+ };
2015
+ function encodeLeavesList(args) {
2016
+ if (!(args.root instanceof Uint8Array) || args.root.length !== DIGEST_LENGTH2) {
2017
+ throw new MerkleLeavesListError(
2018
+ "SCHEMA_MERKLE_LEAVES_MALFORMED",
2019
+ `root must be a Uint8Array(${DIGEST_LENGTH2})`
1894
2020
  );
1895
2021
  }
1896
- if (nonce.length !== NONCE_LENGTH) {
1897
- throw new EciesSealedPoeError(
1898
- "NONCE_LENGTH_MISMATCH",
1899
- `nonce MUST be exactly ${NONCE_LENGTH} bytes, got ${nonce.length}`
2022
+ if (args.leaves.length < 1) {
2023
+ throw new MerkleLeavesListError(
2024
+ "SCHEMA_MERKLE_LEAVES_MALFORMED",
2025
+ "leaves array must be non-empty"
1900
2026
  );
1901
2027
  }
1902
- let envelope;
1903
- if (kem === "x25519") {
1904
- const slots = [];
1905
- for (let i = 0; i < n; i++) {
1906
- slots.push(
1907
- wrapSlotX25519({
1908
- pubR: recipientPublicKeys[i],
1909
- privEph: args.ephemeralSecrets ? args.ephemeralSecrets[i] : void 0,
1910
- cek,
1911
- slotIdx: i
1912
- })
1913
- );
1914
- }
1915
- if (args.skipShuffle !== true) {
1916
- csprngShuffle(slots);
1917
- }
1918
- const slotsMac = computeSlotsMac(cek, slots, "x25519");
1919
- envelope = {
1920
- scheme: 1,
1921
- aead: "xchacha20-poly1305",
1922
- kem: "x25519",
1923
- nonce,
1924
- slots,
1925
- slots_mac: slotsMac
1926
- };
1927
- } else {
1928
- const slots = [];
1929
- for (let i = 0; i < n; i++) {
1930
- slots.push(
1931
- wrapSlotMlkem768X25519({
1932
- pubR: recipientPublicKeys[i],
1933
- eseed: args.eseeds ? args.eseeds[i] : void 0,
1934
- cek
1935
- })
2028
+ const leavesCopy = [];
2029
+ for (let i = 0; i < args.leaves.length; i++) {
2030
+ const leaf = args.leaves[i];
2031
+ if (!(leaf instanceof Uint8Array) || leaf.length !== DIGEST_LENGTH2) {
2032
+ throw new MerkleLeavesListError(
2033
+ "SCHEMA_MERKLE_LEAVES_MALFORMED",
2034
+ `leaves[${i}] must be a Uint8Array(${DIGEST_LENGTH2})`
1936
2035
  );
1937
2036
  }
1938
- if (args.skipShuffle !== true) {
1939
- csprngShuffle(slots);
1940
- }
1941
- const slotsMac = computeSlotsMac(cek, slots, "mlkem768x25519");
1942
- envelope = {
1943
- scheme: 1,
1944
- aead: "xchacha20-poly1305",
1945
- kem: "mlkem768x25519",
1946
- nonce,
1947
- slots,
1948
- slots_mac: slotsMac
1949
- };
2037
+ leavesCopy.push(leaf);
1950
2038
  }
1951
- const adContent = concat(nonce, envelope.slots_mac);
1952
- const ciphertext = xchacha20Poly1305Encrypt({
1953
- key: cek,
1954
- nonce,
1955
- aad: adContent,
1956
- plaintext
1957
- });
1958
- return { envelope, ciphertext };
1959
- }
1960
- function computeSlotsMac(cek, slots, kem) {
1961
- const hmacKey = hkdfSha256({
1962
- ikm: cek,
1963
- salt: EMPTY_SALT,
1964
- info: CARDANO_POE_HKDF_INFO_SLOTS_MAC,
1965
- length: 32
1966
- });
1967
- const slotsCbor = slotsToMacCbor(slots, kem);
1968
- const slotsMac = hmac(sha256$1, hmacKey, slotsCbor);
1969
- if (slotsMac.length !== SLOTS_MAC_LENGTH) {
1970
- throw new Error(`internal: slots_mac.length=${slotsMac.length}, expected ${SLOTS_MAC_LENGTH}`);
2039
+ if (args.leafAlg !== void 0 && typeof args.leafAlg !== "string") {
2040
+ throw new MerkleLeavesListError(
2041
+ "SCHEMA_MERKLE_LEAVES_MALFORMED",
2042
+ "leaf_alg must be a string when present"
2043
+ );
1971
2044
  }
1972
- return slotsMac;
2045
+ const map = {
2046
+ format: LEAVES_LIST_FORMAT_V1,
2047
+ tree_alg: TREE_ALG_RFC9162,
2048
+ root: args.root,
2049
+ leaves: leavesCopy,
2050
+ leaf_count: leavesCopy.length
2051
+ };
2052
+ if (args.leafAlg !== void 0) {
2053
+ map["leaf_alg"] = args.leafAlg;
2054
+ }
2055
+ return encodeCanonicalCbor4(map);
1973
2056
  }
1974
2057
 
1975
2058
  // src/client/partial-upload-error.ts
@@ -2360,7 +2443,7 @@ var PoeNamespace = class {
2360
2443
  * publish time against the locked price snapshot.
2361
2444
  *
2362
2445
  * On HTTP-level failure (auth, rate limit, malformed request) this throws
2363
- * a typed `Cip309HttpError` subclass. Per-file failures inside a 200
2446
+ * a typed `Label309HttpError` subclass. Per-file failures inside a 200
2364
2447
  * response are NOT thrown by `uploads()` itself — the response body is
2365
2448
  * returned verbatim so the caller can decide how to react. The
2366
2449
  * higher-level helpers (`publishSealed`, `publishMerkle`) treat any failed
@@ -2445,7 +2528,7 @@ var PoeNamespace = class {
2445
2528
  }
2446
2529
  /**
2447
2530
  * High-level hash-only publish: hash the supplied content, build a
2448
- * single-item CIP-309 record, optionally sign it with the caller-supplied
2531
+ * single-item Label 309 record, optionally sign it with the caller-supplied
2449
2532
  * signer, and submit. No Arweave, no storage round-trip — anchors the
2450
2533
  * digest only.
2451
2534
  */
@@ -2463,7 +2546,7 @@ var PoeNamespace = class {
2463
2546
  /**
2464
2547
  * Sealed-PoE: encrypt the supplied content to the recipient X25519 public
2465
2548
  * keys (age-style sealed envelope), upload the ciphertext to Arweave via
2466
- * /uploads, build a CIP-309 record with the resulting `ar://` URI, sign
2549
+ * /uploads, build a Label 309 record with the resulting `ar://` URI, sign
2467
2550
  * it (optional), and submit via /publish.
2468
2551
  *
2469
2552
  * The sender SHOULD include their own X25519 public key in `recipients`
@@ -2561,7 +2644,7 @@ var RecordsNamespace = class {
2561
2644
  return await readJson(response);
2562
2645
  }
2563
2646
  /**
2564
- * Run the canonical CIP-309 verifier against the record at `txHash`.
2647
+ * Run the canonical Label 309 verifier against the record at `txHash`.
2565
2648
  * Returns the same `VerifyReport` shape the standalone verifier emits —
2566
2649
  * `VerifyReport` IS the wire body of this endpoint, with no transformer in
2567
2650
  * between.
@@ -2584,31 +2667,31 @@ var RecordsNamespace = class {
2584
2667
  }
2585
2668
  };
2586
2669
 
2587
- // src/client/cip309-client.ts
2670
+ // src/client/label-309-client.ts
2588
2671
  function resolveFetch(provided) {
2589
2672
  if (provided !== void 0) return provided;
2590
2673
  if (typeof globalThis.fetch === "function") {
2591
2674
  return globalThis.fetch.bind(globalThis);
2592
2675
  }
2593
2676
  throw new Error(
2594
- "Cip309Client: no fetch implementation available. Pass `fetch` in the config or run on a platform with globalThis.fetch."
2677
+ "Label309Client: no fetch implementation available. Pass `fetch` in the config or run on a platform with globalThis.fetch."
2595
2678
  );
2596
2679
  }
2597
2680
  function resolveBaseUrl(config) {
2598
2681
  const baseUrl = config.baseUrl?.trim();
2599
2682
  if (baseUrl === void 0 || baseUrl === "") {
2600
2683
  throw new InvalidClientConfigError(
2601
- "Cip309Client: baseUrl is required. Pass the base URL of the CIP-309 gateway you are targeting (e.g. https://gateway.example.com)."
2684
+ "Label309Client: baseUrl is required. Pass the base URL of the Label 309 gateway you are targeting (e.g. https://gateway.example.com)."
2602
2685
  );
2603
2686
  }
2604
2687
  return baseUrl.replace(/\/$/, "");
2605
2688
  }
2606
- var Cip309Client = class {
2689
+ var Label309Client = class {
2607
2690
  poe;
2608
2691
  records;
2609
2692
  account;
2610
2693
  /**
2611
- * Construct a client against a CIP-309 gateway.
2694
+ * Construct a client against a Label 309 gateway.
2612
2695
  *
2613
2696
  * `config.baseUrl` is required — there is no default deployment. The
2614
2697
  * `config.apiKey`, when supplied, is an opaque bearer token sent verbatim as
@@ -2636,6 +2719,6 @@ var Cip309Client = class {
2636
2719
  (*! noble-post-quantum - MIT License (c) 2024 Paul Miller (paulmillr.com) *)
2637
2720
  */
2638
2721
 
2639
- export { AccountNamespace, BatchEmptyError, BatchTooLargeError, Cip309Client, Cip309HttpError, ForbiddenError, IdempotencyConflictError, InsufficientFundsError, InsufficientScopeError, InternalServerError, InvalidBodyError, InvalidClientConfigError, MalformedCborError, NotFoundError, OffHostSignError, PartialUploadError, PoeNamespace, PublishError, QuoteAlreadyConsumedError, QuoteExpiredError, QuoteNotFoundError, RateLimitedError, RecordNotFoundError, RecordsNamespace, ServiceUnavailableError, UnauthorizedError, ValidationFailedError, assembleCoseSign1, assembleCoseSign1Hashed, buildToSign, parseHttpError, prepareSigStructure, prepareSigStructureHashed };
2722
+ export { AccountNamespace, BatchEmptyError, BatchTooLargeError, ForbiddenError, IdempotencyConflictError, InsufficientFundsError, InsufficientScopeError, InternalServerError, InvalidBodyError, InvalidClientConfigError, Label309Client, Label309HttpError, MalformedCborError, NotFoundError, OffHostSignError, PartialUploadError, PoeNamespace, PublishError, QuoteAlreadyConsumedError, QuoteExpiredError, QuoteNotFoundError, RateLimitedError, RecordNotFoundError, RecordsNamespace, ServiceUnavailableError, UnauthorizedError, ValidationFailedError, assembleCoseSign1, assembleCoseSign1Hashed, buildToSign, parseHttpError, prepareSigStructure, prepareSigStructureHashed };
2640
2723
  //# sourceMappingURL=index.js.map
2641
2724
  //# sourceMappingURL=index.js.map