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