@otskit/client 0.3.0 → 0.5.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.
package/dist/index.js CHANGED
@@ -1,11 +1,7 @@
1
1
  // src/types.ts
2
+ import { DEFAULT_CALENDAR_URLS } from "@otskit/core";
2
3
  var isVerified = (r) => r.status === "verified";
3
- var DEFAULT_CALENDARS = [
4
- "https://alice.btc.calendar.opentimestamps.org",
5
- "https://bob.btc.calendar.opentimestamps.org",
6
- "https://finney.calendar.eternitywall.com",
7
- "https://btc.calendar.catallaxy.com"
8
- ];
4
+ var DEFAULT_CALENDARS = [...DEFAULT_CALENDAR_URLS];
9
5
  var DEFAULT_RESILIENCE = {
10
6
  totalTimeoutMs: 3e4,
11
7
  connectTimeoutMs: 5e3,
@@ -33,7 +29,7 @@ var OpenTimestampsClientError = class extends Error {
33
29
  constructor(message, options) {
34
30
  super(message);
35
31
  this.name = this.constructor.name;
36
- this.cause = options?.cause;
32
+ if (options?.cause !== void 0) this.cause = options.cause;
37
33
  Error.captureStackTrace?.(this, this.constructor);
38
34
  }
39
35
  };
@@ -51,11 +47,11 @@ var StampError = class extends OpenTimestampsClientError {
51
47
  var UpgradeError = class extends OpenTimestampsClientError {
52
48
  };
53
49
  var NetworkError = class extends OpenTimestampsClientError {
54
- /** HTTP status code, cuando el fallo viene de una respuesta HTTP. */
50
+ /** HTTP status code when the failure originates from an HTTP response. */
55
51
  status;
56
52
  constructor(message, options) {
57
53
  super(message, options);
58
- this.status = options?.status;
54
+ if (options?.status !== void 0) this.status = options.status;
59
55
  }
60
56
  };
61
57
  var CircuitBreakerError = class extends NetworkError {
@@ -78,7 +74,7 @@ var SizeLimitExceededError = class extends NetworkError {
78
74
  options
79
75
  );
80
76
  this.maxBytes = maxBytes;
81
- this.actualBytes = actualBytes;
77
+ if (actualBytes !== void 0) this.actualBytes = actualBytes;
82
78
  }
83
79
  };
84
80
 
@@ -130,7 +126,10 @@ var CircuitBreaker = class {
130
126
  this.onSuccess(key, circuit);
131
127
  return result;
132
128
  } catch (error) {
133
- this.onFailure(key, circuit);
129
+ const is4xx = error instanceof Error && error.retryable === false;
130
+ if (!is4xx) {
131
+ this.onFailure(key, circuit);
132
+ }
134
133
  throw error;
135
134
  }
136
135
  }
@@ -227,11 +226,15 @@ function sleep(ms, signal) {
227
226
  reject(new Error("Aborted"));
228
227
  return;
229
228
  }
230
- const timeout = setTimeout(resolve, ms);
231
- signal?.addEventListener("abort", () => {
229
+ const onAbort = () => {
232
230
  clearTimeout(timeout);
233
231
  reject(new Error("Aborted"));
234
- });
232
+ };
233
+ const timeout = setTimeout(() => {
234
+ signal?.removeEventListener("abort", onAbort);
235
+ resolve();
236
+ }, ms);
237
+ signal?.addEventListener("abort", onAbort, { once: true });
235
238
  });
236
239
  }
237
240
  async function withRetry(fn, options, logger, signal) {
@@ -314,8 +317,9 @@ async function executeRequest(request, maxBytes) {
314
317
  const response = await globalThis.fetch(request.url, {
315
318
  method: request.method,
316
319
  headers: { "Content-Type": "application/octet-stream", ...request.headers },
317
- body: request.body,
318
- signal: request.signal
320
+ ...request.body !== void 0 ? { body: request.body } : {},
321
+ ...request.signal !== void 0 ? { signal: request.signal } : {},
322
+ redirect: "error"
319
323
  });
320
324
  const data = await readResponseBody(response, maxBytes);
321
325
  return { ok: response.ok, status: response.status, statusText: response.statusText, data };
@@ -433,1453 +437,24 @@ var ResilientNetworkLayer = class {
433
437
  }
434
438
  };
435
439
 
436
- // ../otskit-core/dist/index.js
437
- var DeserializationError = class extends Error {
438
- constructor(message) {
439
- super(message);
440
- this.name = new.target.name;
441
- Object.setPrototypeOf(this, new.target.prototype);
442
- }
443
- };
444
- var BadMagicError = class extends DeserializationError {
445
- };
446
- var TruncatedStreamError = class extends DeserializationError {
447
- };
448
- var OversizedDataError = class extends DeserializationError {
449
- };
450
- var VaruintOverflowError = class extends DeserializationError {
451
- };
452
- var TrailingGarbageError = class extends DeserializationError {
453
- };
454
- var UnknownOperationError = class extends DeserializationError {
455
- };
456
- var OpExecutionError = class extends Error {
457
- constructor(message) {
458
- super(message);
459
- this.name = new.target.name;
460
- Object.setPrototypeOf(this, new.target.prototype);
461
- }
462
- };
463
- var MessageTooLongError = class extends OpExecutionError {
464
- };
465
- var ResultTooLongError = class extends OpExecutionError {
466
- };
467
- var InvalidUriError = class extends DeserializationError {
468
- };
469
- var VerificationError = class extends Error {
470
- constructor(message) {
471
- super(message);
472
- this.name = new.target.name;
473
- Object.setPrototypeOf(this, new.target.prototype);
474
- }
475
- };
476
- var EmptyTimestampError = class extends Error {
477
- constructor(message) {
478
- super(message);
479
- this.name = new.target.name;
480
- Object.setPrototypeOf(this, new.target.prototype);
481
- }
482
- };
483
- var MergeError = class extends Error {
484
- constructor(message) {
485
- super(message);
486
- this.name = new.target.name;
487
- Object.setPrototypeOf(this, new.target.prototype);
488
- }
489
- };
490
- var EmptyMerkleTreeError = class extends Error {
491
- constructor(message) {
492
- super(message);
493
- this.name = new.target.name;
494
- Object.setPrototypeOf(this, new.target.prototype);
495
- }
496
- };
497
- var UnsupportedVersionError = class extends DeserializationError {
498
- };
499
- var HEX_RE = /^[0-9a-fA-F]*$/;
500
- function hexToBytes(hex) {
501
- if (hex.length % 2 !== 0) {
502
- throw new Error(`hex string must have even length; got ${hex.length}`);
503
- }
504
- if (!HEX_RE.test(hex)) {
505
- throw new Error("hex string contains non-hex characters");
506
- }
507
- const out = new Uint8Array(hex.length / 2);
508
- for (let i = 0; i < out.length; i++) {
509
- out[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
510
- }
511
- return out;
512
- }
513
- var HEX_TABLE = Array.from({ length: 256 }, (_, b) => b.toString(16).padStart(2, "0"));
514
- function bytesToHex(bytes) {
515
- let s = "";
516
- for (let i = 0; i < bytes.length; i++) {
517
- s += HEX_TABLE[bytes[i]];
518
- }
519
- return s;
520
- }
521
- var encoder = new TextEncoder();
522
- var decoder = new TextDecoder("utf-8", { fatal: true });
523
- function textToBytes(text) {
524
- return encoder.encode(text);
525
- }
526
- function bytesEqual(a, b) {
527
- if (a.length !== b.length) return false;
528
- for (let i = 0; i < a.length; i++) {
529
- if (a[i] !== b[i]) return false;
530
- }
531
- return true;
532
- }
533
- function compareBytes(a, b) {
534
- const min = Math.min(a.length, b.length);
535
- for (let i = 0; i < min; i++) {
536
- const d = a[i] - b[i];
537
- if (d !== 0) return d;
538
- }
539
- return a.length - b.length;
540
- }
541
- var StreamDeserializationContext = class {
542
- #buffer;
543
- #counter = 0;
544
- constructor(stream) {
545
- if (!(stream instanceof Uint8Array)) {
546
- throw new TypeError("StreamDeserializationContext expects a Uint8Array");
547
- }
548
- this.#buffer = stream;
549
- }
550
- get counter() {
551
- return this.#counter;
552
- }
553
- /** Lee `length` bytes. Lanza si el stream no tiene suficientes. */
554
- read(length) {
555
- if (length < 0) throw new RangeError("read length must be >= 0");
556
- if (this.#counter + length > this.#buffer.length) {
557
- throw new TruncatedStreamError(
558
- `attempted to read ${length} bytes at offset ${this.#counter}, only ${this.#buffer.length - this.#counter} available`
559
- );
560
- }
561
- const slice = this.#buffer.subarray(this.#counter, this.#counter + length);
562
- this.#counter += length;
563
- return slice;
564
- }
565
- /** Lee un único byte. */
566
- readByte() {
567
- return this.read(1)[0];
568
- }
569
- /** Varuint LEB128: 7 bits por byte, bit 7 = continuación. */
570
- readVaruint() {
571
- let value = 0;
572
- let shift = 0;
573
- let byte;
574
- do {
575
- if (shift > 56) {
576
- throw new VaruintOverflowError("varuint exceeds Number.MAX_SAFE_INTEGER");
577
- }
578
- byte = this.readByte();
579
- value += (byte & 127) * 2 ** shift;
580
- if (!Number.isSafeInteger(value)) {
581
- throw new VaruintOverflowError("varuint exceeds Number.MAX_SAFE_INTEGER");
582
- }
583
- shift += 7;
584
- } while (byte & 128);
585
- return value;
586
- }
587
- /** Lee un bloque varbytes. `maxLen` es obligatorio (defensa DoS). */
588
- readVarbytes(maxLen, minLen = 0) {
589
- const length = this.readVaruint();
590
- if (length > maxLen) {
591
- throw new OversizedDataError(`varbytes length ${length} exceeds maxLen ${maxLen}`);
592
- }
593
- if (length < minLen) {
594
- throw new OversizedDataError(`varbytes length ${length} below minLen ${minLen}`);
595
- }
596
- return this.read(length);
597
- }
598
- /** Verifica el número mágico de cabecera. */
599
- assertMagic(expectedMagic) {
600
- const actual = this.read(expectedMagic.length);
601
- if (!bytesEqual(expectedMagic, actual)) {
602
- throw new BadMagicError("header magic mismatch");
603
- }
604
- }
605
- /** Exige que no queden bytes sin consumir. */
606
- assertEof() {
607
- if (this.#counter < this.#buffer.length) {
608
- throw new TrailingGarbageError("trailing garbage after end of deserialized data");
609
- }
610
- }
611
- };
612
- var StreamSerializationContext = class {
613
- #buffer = new Uint8Array(4096);
614
- #length = 0;
615
- get length() {
616
- return this.#length;
617
- }
618
- getOutput() {
619
- return this.#buffer.slice(0, this.#length);
620
- }
621
- writeByte(value) {
622
- if (!Number.isInteger(value) || value < 0 || value > 255) {
623
- throw new RangeError(`writeByte expects a byte 0..255; got ${value}`);
624
- }
625
- if (this.#length >= this.#buffer.length) {
626
- const grown = new Uint8Array(this.#buffer.length * 2);
627
- grown.set(this.#buffer, 0);
628
- this.#buffer = grown;
629
- }
630
- this.#buffer[this.#length] = value;
631
- this.#length += 1;
632
- }
633
- writeBytes(value) {
634
- for (let i = 0; i < value.length; i++) {
635
- this.writeByte(value[i]);
636
- }
637
- }
638
- /** Codifica un varuint LEB128. */
639
- writeVaruint(value) {
640
- if (!Number.isSafeInteger(value) || value < 0) {
641
- throw new RangeError(`writeVaruint expects a safe non-negative integer; got ${value}`);
642
- }
643
- do {
644
- let byte = value % 128;
645
- value = Math.floor(value / 128);
646
- if (value > 0) byte |= 128;
647
- this.writeByte(byte);
648
- } while (value > 0);
649
- }
650
- writeVarbytes(value) {
651
- this.writeVaruint(value.length);
652
- this.writeBytes(value);
653
- }
654
- };
655
- var rotl = (x, n) => x << n | x >>> 32 - n;
656
- function sha1(msg) {
657
- let h0 = 1732584193, h1 = 4023233417, h2 = 2562383102, h3 = 271733878, h4 = 3285377520;
658
- const bitLen = msg.length * 8;
659
- const withOne = msg.length + 1;
660
- const padded = new Uint8Array(Math.ceil((withOne + 8) / 64) * 64);
661
- padded.set(msg, 0);
662
- padded[msg.length] = 128;
663
- const dv = new DataView(padded.buffer);
664
- dv.setUint32(padded.length - 4, bitLen >>> 0, false);
665
- dv.setUint32(padded.length - 8, Math.floor(bitLen / 2 ** 32), false);
666
- const w = new Uint32Array(80);
667
- for (let off = 0; off < padded.length; off += 64) {
668
- for (let i = 0; i < 16; i++) w[i] = dv.getUint32(off + i * 4, false);
669
- for (let i = 16; i < 80; i++) w[i] = rotl(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1);
670
- let a = h0, b = h1, c = h2, d = h3, e = h4;
671
- for (let i = 0; i < 80; i++) {
672
- let f2, k;
673
- if (i < 20) {
674
- f2 = b & c | ~b & d;
675
- k = 1518500249;
676
- } else if (i < 40) {
677
- f2 = b ^ c ^ d;
678
- k = 1859775393;
679
- } else if (i < 60) {
680
- f2 = b & c | b & d | c & d;
681
- k = 2400959708;
682
- } else {
683
- f2 = b ^ c ^ d;
684
- k = 3395469782;
685
- }
686
- const t = rotl(a, 5) + f2 + e + k + w[i] | 0;
687
- e = d;
688
- d = c;
689
- c = rotl(b, 30);
690
- b = a;
691
- a = t;
692
- }
693
- h0 = h0 + a | 0;
694
- h1 = h1 + b | 0;
695
- h2 = h2 + c | 0;
696
- h3 = h3 + d | 0;
697
- h4 = h4 + e | 0;
698
- }
699
- const out = new Uint8Array(20);
700
- const odv = new DataView(out.buffer);
701
- odv.setUint32(0, h0, false);
702
- odv.setUint32(4, h1, false);
703
- odv.setUint32(8, h2, false);
704
- odv.setUint32(12, h3, false);
705
- odv.setUint32(16, h4, false);
706
- return out;
707
- }
708
- var K = new Uint32Array([
709
- 1116352408,
710
- 1899447441,
711
- 3049323471,
712
- 3921009573,
713
- 961987163,
714
- 1508970993,
715
- 2453635748,
716
- 2870763221,
717
- 3624381080,
718
- 310598401,
719
- 607225278,
720
- 1426881987,
721
- 1925078388,
722
- 2162078206,
723
- 2614888103,
724
- 3248222580,
725
- 3835390401,
726
- 4022224774,
727
- 264347078,
728
- 604807628,
729
- 770255983,
730
- 1249150122,
731
- 1555081692,
732
- 1996064986,
733
- 2554220882,
734
- 2821834349,
735
- 2952996808,
736
- 3210313671,
737
- 3336571891,
738
- 3584528711,
739
- 113926993,
740
- 338241895,
741
- 666307205,
742
- 773529912,
743
- 1294757372,
744
- 1396182291,
745
- 1695183700,
746
- 1986661051,
747
- 2177026350,
748
- 2456956037,
749
- 2730485921,
750
- 2820302411,
751
- 3259730800,
752
- 3345764771,
753
- 3516065817,
754
- 3600352804,
755
- 4094571909,
756
- 275423344,
757
- 430227734,
758
- 506948616,
759
- 659060556,
760
- 883997877,
761
- 958139571,
762
- 1322822218,
763
- 1537002063,
764
- 1747873779,
765
- 1955562222,
766
- 2024104815,
767
- 2227730452,
768
- 2361852424,
769
- 2428436474,
770
- 2756734187,
771
- 3204031479,
772
- 3329325298
773
- ]);
774
- var rotr = (x, n) => x >>> n | x << 32 - n;
775
- function sha256(msg) {
776
- const h = new Uint32Array([
777
- 1779033703,
778
- 3144134277,
779
- 1013904242,
780
- 2773480762,
781
- 1359893119,
782
- 2600822924,
783
- 528734635,
784
- 1541459225
785
- ]);
786
- const bitLen = msg.length * 8;
787
- const withOne = msg.length + 1;
788
- const padded = new Uint8Array(Math.ceil((withOne + 8) / 64) * 64);
789
- padded.set(msg, 0);
790
- padded[msg.length] = 128;
791
- const dv = new DataView(padded.buffer);
792
- dv.setUint32(padded.length - 4, bitLen >>> 0, false);
793
- dv.setUint32(padded.length - 8, Math.floor(bitLen / 2 ** 32), false);
794
- const w = new Uint32Array(64);
795
- for (let off = 0; off < padded.length; off += 64) {
796
- for (let i = 0; i < 16; i++) w[i] = dv.getUint32(off + i * 4, false);
797
- for (let i = 16; i < 64; i++) {
798
- const s0 = rotr(w[i - 15], 7) ^ rotr(w[i - 15], 18) ^ w[i - 15] >>> 3;
799
- const s1 = rotr(w[i - 2], 17) ^ rotr(w[i - 2], 19) ^ w[i - 2] >>> 10;
800
- w[i] = w[i - 16] + s0 + w[i - 7] + s1 | 0;
801
- }
802
- let [a, b, c, d, e, f2, g, hh] = h;
803
- for (let i = 0; i < 64; i++) {
804
- const S1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25);
805
- const ch = e & f2 ^ ~e & g;
806
- const t1 = hh + S1 + ch + K[i] + w[i] | 0;
807
- const S0 = rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22);
808
- const maj = a & b ^ a & c ^ b & c;
809
- const t2 = S0 + maj | 0;
810
- hh = g;
811
- g = f2;
812
- f2 = e;
813
- e = d + t1 | 0;
814
- d = c;
815
- c = b;
816
- b = a;
817
- a = t1 + t2 | 0;
818
- }
819
- h[0] = h[0] + a | 0;
820
- h[1] = h[1] + b | 0;
821
- h[2] = h[2] + c | 0;
822
- h[3] = h[3] + d | 0;
823
- h[4] = h[4] + e | 0;
824
- h[5] = h[5] + f2 | 0;
825
- h[6] = h[6] + g | 0;
826
- h[7] = h[7] + hh | 0;
827
- }
828
- const out = new Uint8Array(32);
829
- const odv = new DataView(out.buffer);
830
- for (let i = 0; i < 8; i++) odv.setUint32(i * 4, h[i], false);
831
- return out;
832
- }
833
- var rol = (x, n) => x << n | x >>> 32 - n;
834
- var ZL = [
835
- 0,
836
- 1,
837
- 2,
838
- 3,
839
- 4,
840
- 5,
841
- 6,
842
- 7,
843
- 8,
844
- 9,
845
- 10,
846
- 11,
847
- 12,
848
- 13,
849
- 14,
850
- 15,
851
- 7,
852
- 4,
853
- 13,
854
- 1,
855
- 10,
856
- 6,
857
- 15,
858
- 3,
859
- 12,
860
- 0,
861
- 9,
862
- 5,
863
- 2,
864
- 14,
865
- 11,
866
- 8,
867
- 3,
868
- 10,
869
- 14,
870
- 4,
871
- 9,
872
- 15,
873
- 8,
874
- 1,
875
- 2,
876
- 7,
877
- 0,
878
- 6,
879
- 13,
880
- 11,
881
- 5,
882
- 12,
883
- 1,
884
- 9,
885
- 11,
886
- 10,
887
- 0,
888
- 8,
889
- 12,
890
- 4,
891
- 13,
892
- 3,
893
- 7,
894
- 15,
895
- 14,
896
- 5,
897
- 6,
898
- 2,
899
- 4,
900
- 0,
901
- 5,
902
- 9,
903
- 7,
904
- 12,
905
- 2,
906
- 10,
907
- 14,
908
- 1,
909
- 3,
910
- 8,
911
- 11,
912
- 6,
913
- 15,
914
- 13
915
- ];
916
- var ZR = [
917
- 5,
918
- 14,
919
- 7,
920
- 0,
921
- 9,
922
- 2,
923
- 11,
924
- 4,
925
- 13,
926
- 6,
927
- 15,
928
- 8,
929
- 1,
930
- 10,
931
- 3,
932
- 12,
933
- 6,
934
- 11,
935
- 3,
936
- 7,
937
- 0,
938
- 13,
939
- 5,
940
- 10,
941
- 14,
942
- 15,
943
- 8,
944
- 12,
945
- 4,
946
- 9,
947
- 1,
948
- 2,
949
- 15,
950
- 5,
951
- 1,
952
- 3,
953
- 7,
954
- 14,
955
- 6,
956
- 9,
957
- 11,
958
- 8,
959
- 12,
960
- 2,
961
- 10,
962
- 0,
963
- 4,
964
- 13,
965
- 8,
966
- 6,
967
- 4,
968
- 1,
969
- 3,
970
- 11,
971
- 15,
972
- 0,
973
- 5,
974
- 12,
975
- 2,
976
- 13,
977
- 9,
978
- 7,
979
- 10,
980
- 14,
981
- 12,
982
- 15,
983
- 10,
984
- 4,
985
- 1,
986
- 5,
987
- 8,
988
- 7,
989
- 6,
990
- 2,
991
- 13,
992
- 14,
993
- 0,
994
- 3,
995
- 9,
996
- 11
997
- ];
998
- var SL = [
999
- 11,
1000
- 14,
1001
- 15,
1002
- 12,
1003
- 5,
1004
- 8,
1005
- 7,
1006
- 9,
1007
- 11,
1008
- 13,
1009
- 14,
1010
- 15,
1011
- 6,
1012
- 7,
1013
- 9,
1014
- 8,
1015
- 7,
1016
- 6,
1017
- 8,
1018
- 13,
1019
- 11,
1020
- 9,
1021
- 7,
1022
- 15,
1023
- 7,
1024
- 12,
1025
- 15,
1026
- 9,
1027
- 11,
1028
- 7,
1029
- 13,
1030
- 12,
1031
- 11,
1032
- 13,
1033
- 6,
1034
- 7,
1035
- 14,
1036
- 9,
1037
- 13,
1038
- 15,
1039
- 14,
1040
- 8,
1041
- 13,
1042
- 6,
1043
- 5,
1044
- 12,
1045
- 7,
1046
- 5,
1047
- 11,
1048
- 12,
1049
- 14,
1050
- 15,
1051
- 14,
1052
- 15,
1053
- 9,
1054
- 8,
1055
- 9,
1056
- 14,
1057
- 5,
1058
- 6,
1059
- 8,
1060
- 6,
1061
- 5,
1062
- 12,
1063
- 9,
1064
- 15,
1065
- 5,
1066
- 11,
1067
- 6,
1068
- 8,
1069
- 13,
1070
- 12,
1071
- 5,
1072
- 12,
1073
- 13,
1074
- 14,
1075
- 11,
1076
- 8,
1077
- 5,
1078
- 6
1079
- ];
1080
- var SR = [
1081
- 8,
1082
- 9,
1083
- 9,
1084
- 11,
1085
- 13,
1086
- 15,
1087
- 15,
1088
- 5,
1089
- 7,
1090
- 7,
1091
- 8,
1092
- 11,
1093
- 14,
1094
- 14,
1095
- 12,
1096
- 6,
1097
- 9,
1098
- 13,
1099
- 15,
1100
- 7,
1101
- 12,
1102
- 8,
1103
- 9,
1104
- 11,
1105
- 7,
1106
- 7,
1107
- 12,
1108
- 7,
1109
- 6,
1110
- 15,
1111
- 13,
1112
- 11,
1113
- 9,
1114
- 7,
1115
- 15,
1116
- 11,
1117
- 8,
1118
- 6,
1119
- 6,
1120
- 14,
1121
- 12,
1122
- 13,
1123
- 5,
1124
- 14,
1125
- 13,
1126
- 13,
1127
- 7,
1128
- 5,
1129
- 15,
1130
- 5,
1131
- 8,
1132
- 11,
1133
- 14,
1134
- 14,
1135
- 6,
1136
- 14,
1137
- 6,
1138
- 9,
1139
- 12,
1140
- 9,
1141
- 12,
1142
- 5,
1143
- 15,
1144
- 8,
1145
- 8,
1146
- 5,
1147
- 12,
1148
- 9,
1149
- 12,
1150
- 5,
1151
- 14,
1152
- 6,
1153
- 8,
1154
- 13,
1155
- 6,
1156
- 5,
1157
- 15,
1158
- 13,
1159
- 11,
1160
- 11
1161
- ];
1162
- var KL = [0, 1518500249, 1859775393, 2400959708, 2840853838];
1163
- var KR = [1352829926, 1548603684, 1836072691, 2053994217, 0];
1164
- var f = (j, x, y, z) => {
1165
- if (j < 16) return x ^ y ^ z;
1166
- if (j < 32) return x & y | ~x & z;
1167
- if (j < 48) return (x | ~y) ^ z;
1168
- if (j < 64) return x & z | y & ~z;
1169
- return x ^ (y | ~z);
1170
- };
1171
- function ripemd160(msg) {
1172
- let h0 = 1732584193, h1 = 4023233417, h2 = 2562383102, h3 = 271733878, h4 = 3285377520;
1173
- const bitLen = msg.length * 8;
1174
- const withOne = msg.length + 1;
1175
- const padded = new Uint8Array(Math.ceil((withOne + 8) / 64) * 64);
1176
- padded.set(msg, 0);
1177
- padded[msg.length] = 128;
1178
- const dv = new DataView(padded.buffer);
1179
- dv.setUint32(padded.length - 8, bitLen >>> 0, true);
1180
- dv.setUint32(padded.length - 4, Math.floor(bitLen / 2 ** 32), true);
1181
- const x = new Uint32Array(16);
1182
- for (let off = 0; off < padded.length; off += 64) {
1183
- for (let i = 0; i < 16; i++) x[i] = dv.getUint32(off + i * 4, true);
1184
- let al = h0, bl = h1, cl = h2, dl = h3, el = h4;
1185
- let ar = h0, br = h1, cr = h2, dr = h3, er = h4;
1186
- for (let j = 0; j < 80; j++) {
1187
- const round = Math.floor(j / 16);
1188
- let t2 = al + f(j, bl, cl, dl) + x[ZL[j]] + KL[round] | 0;
1189
- t2 = rol(t2, SL[j]) + el | 0;
1190
- al = el;
1191
- el = dl;
1192
- dl = rol(cl, 10);
1193
- cl = bl;
1194
- bl = t2;
1195
- t2 = ar + f(79 - j, br, cr, dr) + x[ZR[j]] + KR[round] | 0;
1196
- t2 = rol(t2, SR[j]) + er | 0;
1197
- ar = er;
1198
- er = dr;
1199
- dr = rol(cr, 10);
1200
- cr = br;
1201
- br = t2;
1202
- }
1203
- const t = h1 + cl + dr | 0;
1204
- h1 = h2 + dl + er | 0;
1205
- h2 = h3 + el + ar | 0;
1206
- h3 = h4 + al + br | 0;
1207
- h4 = h0 + bl + cr | 0;
1208
- h0 = t;
1209
- }
1210
- const out = new Uint8Array(20);
1211
- const odv = new DataView(out.buffer);
1212
- odv.setUint32(0, h0, true);
1213
- odv.setUint32(4, h1, true);
1214
- odv.setUint32(8, h2, true);
1215
- odv.setUint32(12, h3, true);
1216
- odv.setUint32(16, h4, true);
1217
- return out;
1218
- }
1219
- var MAX_RESULT_LENGTH = 4096;
1220
- var MAX_MSG_LENGTH = 4096;
1221
- function concatBytes(a, b) {
1222
- const out = new Uint8Array(a.length + b.length);
1223
- out.set(a, 0);
1224
- out.set(b, a.length);
1225
- return out;
1226
- }
1227
- var Op = class _Op {
1228
- static MAX_RESULT_LENGTH = MAX_RESULT_LENGTH;
1229
- static MAX_MSG_LENGTH = MAX_MSG_LENGTH;
1230
- /** Deserializa una operación leyendo su tag y despachando a la factoría correcta. */
1231
- static deserialize(ctx) {
1232
- return _Op.deserializeFromTag(ctx, ctx.readByte());
1233
- }
1234
- /** Igual que `deserialize`, pero con el tag ya leído del stream (lo usa el árbol Timestamp). */
1235
- static deserializeFromTag(ctx, tag) {
1236
- const factory = OP_BY_TAG.get(tag);
1237
- if (factory === void 0) {
1238
- throw new UnknownOperationError(`unknown operation tag 0x${tag.toString(16).padStart(2, "0")}`);
1239
- }
1240
- return factory(ctx);
1241
- }
1242
- get maxMsgLength() {
1243
- return MAX_MSG_LENGTH;
1244
- }
1245
- checkMsg(msg) {
1246
- if (msg.length > this.maxMsgLength) {
1247
- throw new MessageTooLongError(`message length ${msg.length} exceeds ${this.maxMsgLength}`);
1248
- }
1249
- }
1250
- checkResult(result) {
1251
- if (result.length > MAX_RESULT_LENGTH) {
1252
- throw new ResultTooLongError(`result length ${result.length} exceeds ${MAX_RESULT_LENGTH}`);
1253
- }
1254
- return result;
1255
- }
1256
- };
1257
- var OpBinary = class extends Op {
1258
- arg;
1259
- constructor(arg) {
1260
- super();
1261
- if (!(arg instanceof Uint8Array)) {
1262
- throw new TypeError("OpBinary arg must be a Uint8Array");
1263
- }
1264
- this.arg = arg.slice();
1265
- }
1266
- serialize(ctx) {
1267
- ctx.writeByte(this.tag);
1268
- ctx.writeVarbytes(this.arg);
1269
- }
1270
- };
1271
- var OpAppend = class _OpAppend extends OpBinary {
1272
- static TAG = 240;
1273
- tag = _OpAppend.TAG;
1274
- tagName = "append";
1275
- call(msg) {
1276
- this.checkMsg(msg);
1277
- return this.checkResult(concatBytes(msg, this.arg));
1278
- }
1279
- equals(other) {
1280
- return other instanceof _OpAppend && bytesEqual(this.arg, other.arg);
1281
- }
1282
- };
1283
- var OpPrepend = class _OpPrepend extends OpBinary {
1284
- static TAG = 241;
1285
- tag = _OpPrepend.TAG;
1286
- tagName = "prepend";
1287
- call(msg) {
1288
- this.checkMsg(msg);
1289
- return this.checkResult(concatBytes(this.arg, msg));
1290
- }
1291
- equals(other) {
1292
- return other instanceof _OpPrepend && bytesEqual(this.arg, other.arg);
1293
- }
1294
- };
1295
- var OpUnary = class extends Op {
1296
- serialize(ctx) {
1297
- ctx.writeByte(this.tag);
1298
- }
1299
- };
1300
- var OpReverse = class _OpReverse extends OpUnary {
1301
- static TAG = 242;
1302
- tag = _OpReverse.TAG;
1303
- tagName = "reverse";
1304
- call(msg) {
1305
- this.checkMsg(msg);
1306
- const r = new Uint8Array(msg.length);
1307
- for (let i = 0; i < msg.length; i++) r[i] = msg[msg.length - 1 - i];
1308
- return this.checkResult(r);
1309
- }
1310
- equals(other) {
1311
- return other instanceof _OpReverse;
1312
- }
1313
- };
1314
- var OpHexlify = class _OpHexlify extends OpUnary {
1315
- static TAG = 243;
1316
- tag = _OpHexlify.TAG;
1317
- tagName = "hexlify";
1318
- // El resultado mide el doble que el mensaje; el límite de mensaje es la mitad.
1319
- get maxMsgLength() {
1320
- return MAX_RESULT_LENGTH / 2;
1321
- }
1322
- call(msg) {
1323
- this.checkMsg(msg);
1324
- return this.checkResult(textToBytes(bytesToHex(msg)));
1325
- }
1326
- equals(other) {
1327
- return other instanceof _OpHexlify;
1328
- }
1329
- };
1330
- var CryptOp = class extends OpUnary {
1331
- call(msg) {
1332
- this.checkMsg(msg);
1333
- return this.hash(msg);
1334
- }
1335
- /**
1336
- * Hashea el contenido COMPLETO de un fichero (longitud arbitraria) con el algoritmo
1337
- * de esta operación. A diferencia de `call`, NO aplica el límite `MAX_MSG_LENGTH`:
1338
- * `call` transforma digests dentro del árbol de prueba (≤ 4096 bytes), mientras que
1339
- * `hashFile` recibe el contenido íntegro del fichero a sellar, que puede ser de
1340
- * cualquier tamaño. Lo usa `DetachedTimestampFile.fromBytes`.
1341
- */
1342
- hashFile(data) {
1343
- if (!(data instanceof Uint8Array)) {
1344
- throw new TypeError("hashFile expects a Uint8Array");
1345
- }
1346
- return this.hash(data);
1347
- }
1348
- };
1349
- var OpSHA1 = class _OpSHA1 extends CryptOp {
1350
- static TAG = 2;
1351
- tag = _OpSHA1.TAG;
1352
- tagName = "sha1";
1353
- digestLength = 20;
1354
- hash(msg) {
1355
- return sha1(msg);
1356
- }
1357
- equals(other) {
1358
- return other instanceof _OpSHA1;
1359
- }
1360
- };
1361
- var OpRIPEMD160 = class _OpRIPEMD160 extends CryptOp {
1362
- static TAG = 3;
1363
- tag = _OpRIPEMD160.TAG;
1364
- tagName = "ripemd160";
1365
- digestLength = 20;
1366
- hash(msg) {
1367
- return ripemd160(msg);
1368
- }
1369
- equals(other) {
1370
- return other instanceof _OpRIPEMD160;
1371
- }
1372
- };
1373
- var OpSHA256 = class _OpSHA256 extends CryptOp {
1374
- static TAG = 8;
1375
- tag = _OpSHA256.TAG;
1376
- tagName = "sha256";
1377
- digestLength = 32;
1378
- hash(msg) {
1379
- return sha256(msg);
1380
- }
1381
- equals(other) {
1382
- return other instanceof _OpSHA256;
1383
- }
1384
- };
1385
- var unary = (ctor) => () => new ctor();
1386
- var binary = (ctor) => (ctx) => new ctor(ctx.readVarbytes(MAX_RESULT_LENGTH, 1));
1387
- function buildTagTable(entries) {
1388
- const map = /* @__PURE__ */ new Map();
1389
- for (const [tag, factory] of entries) {
1390
- if (map.has(tag)) {
1391
- throw new Error(`duplicate operation tag 0x${tag.toString(16)}`);
1392
- }
1393
- map.set(tag, factory);
1394
- }
1395
- return map;
1396
- }
1397
- var OP_BY_TAG = buildTagTable([
1398
- [OpAppend.TAG, binary(OpAppend)],
1399
- [OpPrepend.TAG, binary(OpPrepend)],
1400
- [OpReverse.TAG, unary(OpReverse)],
1401
- [OpHexlify.TAG, unary(OpHexlify)],
1402
- [OpSHA1.TAG, unary(OpSHA1)],
1403
- [OpRIPEMD160.TAG, unary(OpRIPEMD160)],
1404
- [OpSHA256.TAG, unary(OpSHA256)]
1405
- ]);
1406
- var TAG_SIZE = 8;
1407
- var MAX_PAYLOAD_SIZE = 8192;
1408
- var MAX_URI_LENGTH = 1e3;
1409
- var ALLOWED_URI_CHARS = new Set(
1410
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._/:"
1411
- );
1412
- var PENDING_TAG = new Uint8Array([131, 223, 227, 13, 46, 249, 12, 142]);
1413
- var BITCOIN_TAG = new Uint8Array([5, 136, 150, 13, 115, 215, 25, 1]);
1414
- var LITECOIN_TAG = new Uint8Array([6, 134, 154, 13, 115, 215, 27, 69]);
1415
- function decodeAndValidateUri(bytes) {
1416
- if (bytes.length === 0) {
1417
- throw new InvalidUriError("pending attestation URI is empty");
1418
- }
1419
- if (bytes.length > MAX_URI_LENGTH) {
1420
- throw new InvalidUriError(`pending attestation URI exceeds ${MAX_URI_LENGTH} bytes`);
1421
- }
1422
- let uri = "";
1423
- for (let i = 0; i < bytes.length; i++) {
1424
- const byte = bytes[i];
1425
- const char = String.fromCharCode(byte);
1426
- if (!ALLOWED_URI_CHARS.has(char)) {
1427
- throw new InvalidUriError(
1428
- `pending attestation URI contains invalid byte 0x${byte.toString(16).padStart(2, "0")}`
1429
- );
1430
- }
1431
- uri += char;
1432
- }
1433
- return uri;
1434
- }
1435
- function deserializeAttestation(ctx) {
1436
- const tag = ctx.read(TAG_SIZE).slice();
1437
- const payload = ctx.readVarbytes(MAX_PAYLOAD_SIZE);
1438
- const payloadCtx = new StreamDeserializationContext(payload);
1439
- let attestation;
1440
- if (bytesEqual(tag, PENDING_TAG)) {
1441
- const uriBytes = payloadCtx.readVarbytes(MAX_URI_LENGTH).slice();
1442
- attestation = { kind: "pending", tag, uri: decodeAndValidateUri(uriBytes), uriBytes };
1443
- } else if (bytesEqual(tag, BITCOIN_TAG)) {
1444
- attestation = { kind: "bitcoin", tag, height: payloadCtx.readVaruint() };
1445
- } else if (bytesEqual(tag, LITECOIN_TAG)) {
1446
- attestation = { kind: "litecoin", tag, height: payloadCtx.readVaruint() };
1447
- } else {
1448
- return { kind: "unknown", tag, payload: payload.slice() };
1449
- }
1450
- payloadCtx.assertEof();
1451
- return attestation;
1452
- }
1453
- function serializePayload(ctx, att) {
1454
- switch (att.kind) {
1455
- case "pending":
1456
- ctx.writeVarbytes(att.uriBytes);
1457
- return;
1458
- case "bitcoin":
1459
- case "litecoin":
1460
- ctx.writeVaruint(att.height);
1461
- return;
1462
- case "unknown":
1463
- ctx.writeBytes(att.payload);
1464
- return;
1465
- }
1466
- }
1467
- function serializeAttestation(ctx, att) {
1468
- ctx.writeBytes(att.tag);
1469
- const payloadCtx = new StreamSerializationContext();
1470
- serializePayload(payloadCtx, att);
1471
- ctx.writeVarbytes(payloadCtx.getOutput());
1472
- }
1473
- function compareAttestations(a, b) {
1474
- const deltaTag = compareBytes(a.tag, b.tag);
1475
- if (deltaTag !== 0) {
1476
- return deltaTag;
1477
- }
1478
- switch (a.kind) {
1479
- case "pending":
1480
- return compareBytes(a.uriBytes, b.uriBytes);
1481
- case "bitcoin":
1482
- case "litecoin":
1483
- return a.height - b.height;
1484
- case "unknown":
1485
- return compareBytes(a.payload, b.payload);
1486
- }
1487
- }
1488
- function attestationsEqual(a, b) {
1489
- if (a.kind !== b.kind || !bytesEqual(a.tag, b.tag)) {
1490
- return false;
1491
- }
1492
- switch (a.kind) {
1493
- case "pending":
1494
- return bytesEqual(a.uriBytes, b.uriBytes);
1495
- case "bitcoin":
1496
- case "litecoin":
1497
- return a.height === b.height;
1498
- case "unknown":
1499
- return bytesEqual(a.payload, b.payload);
1500
- }
1501
- }
1502
- var MERKLEROOT_RE = /^[0-9a-fA-F]{64}$/;
1503
- function verifyAgainstBlockheader(digest, block) {
1504
- if (digest.length !== 32) {
1505
- throw new VerificationError(`expected digest of 32 bytes; got ${digest.length}`);
1506
- }
1507
- if (typeof block.merkleroot !== "string" || !MERKLEROOT_RE.test(block.merkleroot)) {
1508
- throw new VerificationError("block merkleroot is not a 64-char hex string");
1509
- }
1510
- if (!Number.isInteger(block.time) || block.time <= 0) {
1511
- throw new VerificationError("block time is not a positive integer");
1512
- }
1513
- if (!bytesEqual(digest, hexToBytes(block.merkleroot))) {
1514
- throw new VerificationError("digest does not match block merkleroot");
1515
- }
1516
- return block.time;
1517
- }
1518
- var MAX_TREE_DEPTH = 256;
1519
- function opToBytes(op) {
1520
- const ctx = new StreamSerializationContext();
1521
- op.serialize(ctx);
1522
- return ctx.getOutput();
1523
- }
1524
- function opKey(op) {
1525
- return bytesToHex(opToBytes(op));
1526
- }
1527
- var Timestamp = class _Timestamp {
1528
- /** Digest de este nodo (copia defensiva, no comparte memoria con la entrada). */
1529
- msg;
1530
- /** Sellos directos sobre `msg`. El cliente puede añadir con `.push()`. */
1531
- attestations = [];
1532
- /** Ramas indexadas por la serialización canónica (hex) de su op. */
1533
- #ops = /* @__PURE__ */ new Map();
1534
- constructor(msg) {
1535
- if (!(msg instanceof Uint8Array)) {
1536
- throw new TypeError("Timestamp msg must be a Uint8Array");
1537
- }
1538
- if (msg.length > Op.MAX_MSG_LENGTH) {
1539
- throw new TypeError(`Timestamp msg length ${msg.length} exceeds ${Op.MAX_MSG_LENGTH}`);
1540
- }
1541
- this.msg = msg.slice();
1542
- }
1543
- /** El digest de este nodo (copia: mutar el resultado no afecta al árbol). */
1544
- getDigest() {
1545
- return this.msg.slice();
1546
- }
1547
- /** Las ramas (op + sub-timestamp) de este nodo, como array de solo lectura. */
1548
- get branches() {
1549
- return [...this.#ops.values()];
1550
- }
1551
- /**
1552
- * Deserializa un Timestamp. El formato no incluye el mensaje sobre el que opera,
1553
- * así que hay que aportarlo (`initialMsg`) para recalcular los resultados de las ops.
1554
- * @param depth profundidad actual; protege contra árboles maliciosamente profundos.
1555
- */
1556
- static deserialize(ctx, initialMsg, depth = 0) {
1557
- if (depth > MAX_TREE_DEPTH) {
1558
- throw new OversizedDataError(`timestamp tree exceeds max depth ${MAX_TREE_DEPTH}`);
1559
- }
1560
- const self = new _Timestamp(initialMsg);
1561
- let tag = ctx.readByte();
1562
- while (tag === 255) {
1563
- self.#deserializeElement(ctx, ctx.readByte(), depth);
1564
- tag = ctx.readByte();
1565
- }
1566
- self.#deserializeElement(ctx, tag, depth);
1567
- return self;
1568
- }
1569
- #deserializeElement(ctx, tag, depth) {
1570
- if (tag === 0) {
1571
- this.attestations.push(deserializeAttestation(ctx));
1572
- return;
1573
- }
1574
- const op = Op.deserializeFromTag(ctx, tag);
1575
- let result;
1576
- try {
1577
- result = op.call(this.msg);
1578
- } catch (err) {
1579
- throw new DeserializationError(
1580
- `operation failed during deserialization: ${err.message}`
1581
- );
1582
- }
1583
- const stamp = _Timestamp.deserialize(ctx, result, depth + 1);
1584
- this.#ops.set(opKey(op), { op, stamp });
1585
- }
1586
- /** Serializa este nodo en orden canónico (determinista byte-a-byte). */
1587
- serialize(ctx) {
1588
- const attestations = [...this.attestations].sort(compareAttestations);
1589
- const branches = [...this.#ops.values()].sort(
1590
- (a, b) => compareBytes(opToBytes(a.op), opToBytes(b.op))
1591
- );
1592
- const total = attestations.length + branches.length;
1593
- if (total === 0) {
1594
- throw new EmptyTimestampError("an empty timestamp cannot be serialized");
1595
- }
1596
- let index = 0;
1597
- for (const attestation of attestations) {
1598
- if (index < total - 1) ctx.writeByte(255);
1599
- ctx.writeByte(0);
1600
- serializeAttestation(ctx, attestation);
1601
- index++;
1602
- }
1603
- for (const { op, stamp } of branches) {
1604
- if (index < total - 1) ctx.writeByte(255);
1605
- op.serialize(ctx);
1606
- stamp.serialize(ctx);
1607
- index++;
1608
- }
1609
- }
1610
- /**
1611
- * Añade una op a este nodo y devuelve el sub-timestamp de su resultado.
1612
- * Si la op (por contenido) ya existe, devuelve la rama existente.
1613
- */
1614
- add(op) {
1615
- const key = opKey(op);
1616
- const existing = this.#ops.get(key);
1617
- if (existing !== void 0) {
1618
- return existing.stamp;
1619
- }
1620
- const stamp = new _Timestamp(op.call(this.msg));
1621
- this.#ops.set(key, { op, stamp });
1622
- return stamp;
1623
- }
1624
- /**
1625
- * Vincula `op` a un sub-timestamp YA EXISTENTE, compartiendo el objeto (no crea uno nuevo).
1626
- * A diferencia de `add`, hace que esta rama apunte al mismo `Timestamp` que otra rama
1627
- * (de otro nodo) ya construyó, de modo que las attestations añadidas más arriba sean
1628
- * alcanzables desde ambos caminos. Lo usa el árbol Merkle para el cross-link izquierda/derecha.
1629
- * Falla (fail-closed) si `stamp` no es un Timestamp o si `op.call(this.msg)` no coincide con `stamp.msg`.
1630
- */
1631
- addExisting(op, stamp) {
1632
- if (!(stamp instanceof _Timestamp)) {
1633
- throw new TypeError("addExisting requires a Timestamp");
1634
- }
1635
- if (!bytesEqual(op.call(this.msg), stamp.msg)) {
1636
- throw new MergeError("operation result does not match the existing timestamp message");
1637
- }
1638
- this.#ops.set(opKey(op), { op, stamp });
1639
- return stamp;
1640
- }
1641
- /** Incorpora las attestations y ramas de `other` (mismo `msg`) en este timestamp. */
1642
- merge(other) {
1643
- if (!(other instanceof _Timestamp)) {
1644
- throw new MergeError("can only merge Timestamps together");
1645
- }
1646
- if (!bytesEqual(this.msg, other.msg)) {
1647
- throw new MergeError("cannot merge timestamps for different messages");
1648
- }
1649
- for (const attestation of other.attestations) {
1650
- if (!this.attestations.some((existing) => attestationsEqual(existing, attestation))) {
1651
- this.attestations.push(attestation);
1652
- }
1653
- }
1654
- for (const { op, stamp } of other.#ops.values()) {
1655
- const key = opKey(op);
1656
- let branch = this.#ops.get(key);
1657
- if (branch === void 0) {
1658
- branch = { op, stamp: new _Timestamp(op.call(this.msg)) };
1659
- this.#ops.set(key, branch);
1660
- }
1661
- branch.stamp.merge(stamp);
1662
- }
1663
- }
1664
- /** Todas las attestations del árbol con el msg de su nodo (sin pérdida de datos). */
1665
- allAttestations() {
1666
- const result = [];
1667
- for (const attestation of this.attestations) {
1668
- result.push({ msg: this.msg.slice(), attestation });
1669
- }
1670
- for (const { stamp } of this.#ops.values()) {
1671
- result.push(...stamp.allAttestations());
1672
- }
1673
- return result;
1674
- }
1675
- /** Todas las attestations del árbol (sin el msg asociado). */
1676
- getAttestations() {
1677
- return this.allAttestations().map((entry) => entry.attestation);
1678
- }
1679
- /** Verdadero si el árbol contiene una attestation verificable localmente (Bitcoin/Litecoin). */
1680
- isTimestampComplete() {
1681
- return this.allAttestations().some(
1682
- ({ attestation }) => attestation.kind === "bitcoin" || attestation.kind === "litecoin"
1683
- );
1684
- }
1685
- /** Sub-timestamps que tienen attestations directas. */
1686
- directlyVerified() {
1687
- if (this.attestations.length > 0) {
1688
- return [this];
1689
- }
1690
- const result = [];
1691
- for (const { stamp } of this.#ops.values()) {
1692
- result.push(...stamp.directlyVerified());
1693
- }
1694
- return result;
1695
- }
1696
- /** Los mensajes de las hojas del árbol (nodos sin ops). */
1697
- allTips() {
1698
- if (this.#ops.size === 0) {
1699
- return [this.msg.slice()];
1700
- }
1701
- const result = [];
1702
- for (const { stamp } of this.#ops.values()) {
1703
- result.push(...stamp.allTips());
1704
- }
1705
- return result;
1706
- }
1707
- /** Igualdad estructural recursiva con otro timestamp. */
1708
- equals(other) {
1709
- if (!(other instanceof _Timestamp)) {
1710
- return false;
1711
- }
1712
- if (!bytesEqual(this.msg, other.msg)) {
1713
- return false;
1714
- }
1715
- if (this.attestations.length !== other.attestations.length) {
1716
- return false;
1717
- }
1718
- const ours = [...this.attestations].sort(compareAttestations);
1719
- const theirs = [...other.attestations].sort(compareAttestations);
1720
- for (let i = 0; i < ours.length; i++) {
1721
- if (!attestationsEqual(ours[i], theirs[i])) {
1722
- return false;
1723
- }
1724
- }
1725
- if (this.#ops.size !== other.#ops.size) {
1726
- return false;
1727
- }
1728
- for (const [key, branch] of this.#ops) {
1729
- const otherBranch = other.#ops.get(key);
1730
- if (otherBranch === void 0) {
1731
- return false;
1732
- }
1733
- if (!branch.stamp.equals(otherBranch.stamp)) {
1734
- return false;
1735
- }
1736
- }
1737
- return true;
1738
- }
1739
- };
1740
- function catSha256(left, right) {
1741
- if (!(left instanceof Timestamp) || !(right instanceof Timestamp)) {
1742
- throw new TypeError("catSha256 requires two Timestamps");
1743
- }
1744
- const concat = right.add(new OpPrepend(left.msg));
1745
- left.addExisting(new OpAppend(right.msg), concat);
1746
- return concat.add(new OpSHA256());
1747
- }
1748
- function makeMerkleTree(timestamps) {
1749
- if (timestamps.length === 0) {
1750
- throw new EmptyMerkleTreeError("makeMerkleTree requires at least one timestamp");
1751
- }
1752
- for (const stamp of timestamps) {
1753
- if (!(stamp instanceof Timestamp)) {
1754
- throw new TypeError("makeMerkleTree requires an array of Timestamps");
1755
- }
1756
- }
1757
- let round = [...timestamps];
1758
- while (round.length > 1) {
1759
- const next = [];
1760
- for (let i = 0; i < round.length; i += 2) {
1761
- if (i + 1 < round.length) {
1762
- next.push(catSha256(round[i], round[i + 1]));
1763
- } else {
1764
- next.push(round[i]);
1765
- }
1766
- }
1767
- round = next;
1768
- }
1769
- return round[0];
1770
- }
1771
- var HEADER_MAGIC = new Uint8Array([
1772
- 0,
1773
- 79,
1774
- 112,
1775
- 101,
1776
- 110,
1777
- 84,
1778
- 105,
1779
- 109,
1780
- 101,
1781
- 115,
1782
- 116,
1783
- 97,
1784
- 109,
1785
- 112,
1786
- 115,
1787
- 0,
1788
- 0,
1789
- 80,
1790
- 114,
1791
- 111,
1792
- 111,
1793
- 102,
1794
- 0,
1795
- 191,
1796
- 137,
1797
- 226,
1798
- 232,
1799
- 132,
1800
- 232,
1801
- 146,
1802
- 148
1803
- ]);
1804
- var MAJOR_VERSION = 1;
1805
- var DetachedTimestampFile = class _DetachedTimestampFile {
1806
- fileHashOp;
1807
- timestamp;
1808
- constructor(fileHashOp, timestamp) {
1809
- if (!(fileHashOp instanceof CryptOp)) {
1810
- throw new TypeError("DetachedTimestampFile: fileHashOp must be a CryptOp");
1811
- }
1812
- if (!(timestamp instanceof Timestamp)) {
1813
- throw new TypeError("DetachedTimestampFile: timestamp must be a Timestamp");
1814
- }
1815
- if (timestamp.msg.length !== fileHashOp.digestLength) {
1816
- throw new TypeError(
1817
- `DetachedTimestampFile: timestamp message length ${timestamp.msg.length} does not match ${fileHashOp.tagName} digest length ${fileHashOp.digestLength}`
1818
- );
1819
- }
1820
- this.fileHashOp = fileHashOp;
1821
- this.timestamp = timestamp;
1822
- }
1823
- /** Digest del fichero sellado (copia defensiva: mutarla no afecta al objeto). */
1824
- fileDigest() {
1825
- return this.timestamp.getDigest();
1826
- }
1827
- /** Escribe el fichero `.ots` en el contexto: magic → versión → op → digest → árbol. */
1828
- serialize(ctx) {
1829
- ctx.writeBytes(HEADER_MAGIC);
1830
- ctx.writeVaruint(MAJOR_VERSION);
1831
- this.fileHashOp.serialize(ctx);
1832
- ctx.writeBytes(this.timestamp.msg);
1833
- this.timestamp.serialize(ctx);
1834
- }
1835
- /** Serializa el fichero `.ots` completo a bytes. */
1836
- serializeToBytes() {
1837
- const ctx = new StreamSerializationContext();
1838
- this.serialize(ctx);
1839
- return ctx.getOutput();
1840
- }
1841
- /**
1842
- * Lee un fichero `.ots` desde bytes. Único tipo de entrada: `Uint8Array` (fail-closed;
1843
- * elimina los 4 tipos del original y el bug `Array.from(ArrayBuffer) → []`).
1844
- */
1845
- static deserialize(input) {
1846
- if (!(input instanceof Uint8Array)) {
1847
- throw new TypeError("DetachedTimestampFile.deserialize expects a Uint8Array");
1848
- }
1849
- const ctx = new StreamDeserializationContext(input);
1850
- ctx.assertMagic(HEADER_MAGIC);
1851
- const major = ctx.readVaruint();
1852
- if (major !== MAJOR_VERSION) {
1853
- throw new UnsupportedVersionError(`unsupported .ots major version ${major}`);
1854
- }
1855
- const op = Op.deserialize(ctx);
1856
- if (!(op instanceof CryptOp)) {
1857
- throw new DeserializationError("file hash operation must be a cryptographic hash");
1858
- }
1859
- const fileHash = ctx.read(op.digestLength);
1860
- const timestamp = Timestamp.deserialize(ctx, fileHash);
1861
- ctx.assertEof();
1862
- return new _DetachedTimestampFile(op, timestamp);
1863
- }
1864
- /** Crea un `.ots` nuevo hasheando el contenido completo de un fichero. */
1865
- static fromBytes(fileHashOp, fileContent) {
1866
- if (!(fileHashOp instanceof CryptOp)) {
1867
- throw new TypeError("DetachedTimestampFile.fromBytes: fileHashOp must be a CryptOp");
1868
- }
1869
- const digest = fileHashOp.hashFile(fileContent);
1870
- return new _DetachedTimestampFile(fileHashOp, new Timestamp(digest));
1871
- }
1872
- /** Crea un `.ots` nuevo a partir de un digest ya calculado del fichero. */
1873
- static fromHash(fileHashOp, fileDigest) {
1874
- return new _DetachedTimestampFile(fileHashOp, new Timestamp(fileDigest));
1875
- }
1876
- /** Igualdad estructural con otro fichero `.ots`. */
1877
- equals(other) {
1878
- return other instanceof _DetachedTimestampFile && this.fileHashOp.equals(other.fileHashOp) && this.timestamp.equals(other.timestamp);
1879
- }
1880
- };
440
+ // src/core/orchestration.ts
441
+ import {
442
+ DetachedTimestampFile,
443
+ OpSHA256,
444
+ OpAppend,
445
+ OpSHA1,
446
+ OpRIPEMD160,
447
+ makeMerkleTree
448
+ } from "@otskit/core";
1881
449
 
1882
450
  // src/network/calendar.ts
451
+ import {
452
+ Timestamp,
453
+ StreamDeserializationContext,
454
+ bytesToHex,
455
+ TRUSTED_CALENDAR_WHITELIST_PATTERNS,
456
+ DEFAULT_AGGREGATOR_URLS
457
+ } from "@otskit/core";
1883
458
  var MAX_CALENDAR_RESPONSE_SIZE = 1e4;
1884
459
  function assertCommitment(bytes) {
1885
460
  if (!(bytes instanceof Uint8Array)) {
@@ -1905,7 +480,7 @@ var CalendarClient = class {
1905
480
  url;
1906
481
  networkLayer;
1907
482
  logger;
1908
- /** Envia un digest al calendario y devuelve el Timestamp que lo commit-ea. */
483
+ /** Submits a digest to the calendar and returns the Timestamp that commits to it. */
1909
484
  async submit(digest, signal) {
1910
485
  assertCommitment(digest);
1911
486
  this.logger?.debug(`Submitting digest to ${this.url}/digest`);
@@ -1916,7 +491,7 @@ var CalendarClient = class {
1916
491
  );
1917
492
  return this.#parseTimestamp(response.data, digest);
1918
493
  }
1919
- /** Pregunta al calendario si tiene un Timestamp mas completo para `commitment` (upgrade). */
494
+ /** Asks the calendar for a more complete Timestamp for `commitment` (upgrade). */
1920
495
  async getTimestamp(commitment, signal) {
1921
496
  assertCommitment(commitment);
1922
497
  const path = `/timestamp/${bytesToHex(commitment)}`;
@@ -1938,7 +513,7 @@ var CalendarClient = class {
1938
513
  }
1939
514
  return this.#parseTimestamp(response.data, commitment);
1940
515
  }
1941
- /** Deserializa la respuesta del calendario como un Timestamp commit-eado a `commitment`. */
516
+ /** Deserializes the calendar response as a Timestamp committed to `commitment`. */
1942
517
  #parseTimestamp(data, commitment) {
1943
518
  if (data.length > MAX_CALENDAR_RESPONSE_SIZE) {
1944
519
  throw new CalendarResponseTooLargeError(
@@ -1968,7 +543,7 @@ function parseWhitelistPattern(raw) {
1968
543
  hostname,
1969
544
  port: parsed.port,
1970
545
  pathname: parsed.pathname,
1971
- wildcardSuffix
546
+ ...wildcardSuffix !== void 0 ? { wildcardSuffix } : {}
1972
547
  };
1973
548
  }
1974
549
  function hostnameMatchesPattern(hostname, pattern) {
@@ -1984,20 +559,26 @@ var UrlWhitelist = class {
1984
559
  for (const u of urls) this.add(u);
1985
560
  }
1986
561
  }
1987
- /** Anade un patron; si no trae esquema, se anaden las variantes http y https. */
562
+ /**
563
+ * Adds a pattern. If the URL has no scheme, both http:// and https:// variants are added.
564
+ * Throws TypeError if the pattern is not a valid string or is structurally invalid.
565
+ */
1988
566
  add(url) {
1989
567
  if (typeof url !== "string") {
1990
568
  throw new TypeError("UrlWhitelist: URL must be a string");
1991
569
  }
1992
570
  if (url.startsWith("http://") || url.startsWith("https://")) {
1993
571
  const pattern = parseWhitelistPattern(url);
1994
- if (pattern !== void 0) this.#patterns.set(url, pattern);
572
+ if (pattern === void 0) {
573
+ throw new TypeError(`UrlWhitelist: invalid or unsupported pattern: "${url}"`);
574
+ }
575
+ this.#patterns.set(url, pattern);
1995
576
  } else {
1996
577
  this.add("http://" + url);
1997
578
  this.add("https://" + url);
1998
579
  }
1999
580
  }
2000
- /** Verdadero si `url` casa con algun patron de la whitelist. */
581
+ /** Returns true if `url` matches any pattern in the allowlist. */
2001
582
  contains(url) {
2002
583
  let parsed;
2003
584
  try {
@@ -2019,27 +600,21 @@ var UrlWhitelist = class {
2019
600
  return `UrlWhitelist([${[...this.#patterns.keys()].join(", ")}])`;
2020
601
  }
2021
602
  };
2022
- var DEFAULT_CALENDAR_WHITELIST = new UrlWhitelist([
2023
- "https://*.calendar.opentimestamps.org",
2024
- // Peter Todd
2025
- "https://*.btc.calendar.opentimestamps.org",
2026
- // Peter Todd Bitcoin calendars
2027
- "https://*.calendar.eternitywall.com",
2028
- // Eternity Wall
2029
- "https://*.calendar.catallaxy.com"
2030
- // Catallaxy
2031
- ]);
2032
- var DEFAULT_AGGREGATORS = [
2033
- "https://a.pool.opentimestamps.org",
2034
- "https://b.pool.opentimestamps.org",
2035
- "https://a.pool.eternitywall.com",
2036
- "https://ots.btc.catallaxy.com"
2037
- ];
603
+ var DEFAULT_CALENDAR_WHITELIST = new UrlWhitelist([...TRUSTED_CALENDAR_WHITELIST_PATTERNS]);
604
+ var DEFAULT_AGGREGATORS = [...DEFAULT_AGGREGATOR_URLS];
2038
605
 
2039
606
  // src/network/esplora.ts
607
+ import { createHash } from "crypto";
608
+ import { verifyAgainstRawHeader, VerificationError } from "@otskit/core";
2040
609
  var PUBLIC_ESPLORA_URL = "https://blockstream.info/api";
2041
610
  var MAX_ESPLORA_RESPONSE_SIZE = 1e5;
611
+ var RAW_HEADER_SIZE = 80;
2042
612
  var HEX64_RE = /^[0-9a-f]{64}$/i;
613
+ function sha256dDisplayHex(data) {
614
+ const first = createHash("sha256").update(data).digest();
615
+ const second = createHash("sha256").update(first).digest();
616
+ return Buffer.from(second).reverse().toString("hex");
617
+ }
2043
618
  var EsploraClient = class {
2044
619
  #url;
2045
620
  #networkLayer;
@@ -2059,7 +634,7 @@ var EsploraClient = class {
2059
634
  this.#url = raw.replace(/\/+$/, "");
2060
635
  this.#logger = options.logger;
2061
636
  }
2062
- /** Devuelve el hash (hex 64, minúsculas) del bloque a la altura dada. */
637
+ /** Returns the block hash (64-char hex, lowercase) at the given height. */
2063
638
  async blockHash(height, signal) {
2064
639
  if (!Number.isSafeInteger(height) || height < 0) {
2065
640
  throw new ValidationError(`block height must be a non-negative safe integer; got ${height}`);
@@ -2076,7 +651,7 @@ var EsploraClient = class {
2076
651
  }
2077
652
  return text.toLowerCase();
2078
653
  }
2079
- /** Devuelve la cabecera del bloque (merkleroot + time) dado su hash. */
654
+ /** Returns the block header (merkle root + timestamp) for the given hash. */
2080
655
  async block(hash, signal) {
2081
656
  if (typeof hash !== "string" || !HEX64_RE.test(hash)) {
2082
657
  throw new ValidationError("block hash must be a 64-char hex string");
@@ -2094,7 +669,7 @@ var EsploraClient = class {
2094
669
  } catch (err) {
2095
670
  throw new EsploraResponseError("esplora returned a non-JSON block response", {
2096
671
  /* v8 ignore next */
2097
- cause: err instanceof Error ? err : void 0
672
+ ...err instanceof Error ? { cause: err } : {}
2098
673
  });
2099
674
  }
2100
675
  if (typeof body !== "object" || body === null) {
@@ -2109,7 +684,36 @@ var EsploraClient = class {
2109
684
  }
2110
685
  return { merkleroot, time };
2111
686
  }
2112
- /** Decodifica el cuerpo a texto aplicando el límite de tamaño (fail-closed). */
687
+ /**
688
+ * Fetches the raw 80-byte block header for `hash` and self-authenticates it:
689
+ * sha256d(rawHeader) reversed must equal `hash`. This removes trust in the explorer's
690
+ * JSON layer — the raw header is cryptographically bound to the block hash we requested.
691
+ */
692
+ async rawBlockHeader(hash, signal) {
693
+ if (typeof hash !== "string" || !HEX64_RE.test(hash)) {
694
+ throw new ValidationError("block hash must be a 64-char hex string");
695
+ }
696
+ this.#logger?.debug(`Esplora raw header ${hash}`);
697
+ const response = await this.#networkLayer.request(
698
+ this.#url,
699
+ { url: `${this.#url}/block/${hash}/header`, method: "GET", headers: { Accept: "application/octet-stream" } },
700
+ signal
701
+ );
702
+ const data = response.data;
703
+ if (data.length !== RAW_HEADER_SIZE) {
704
+ throw new EsploraResponseError(
705
+ `raw block header must be ${RAW_HEADER_SIZE} bytes; got ${data.length}`
706
+ );
707
+ }
708
+ const actualHash = sha256dDisplayHex(data);
709
+ if (actualHash !== hash.toLowerCase()) {
710
+ throw new EsploraResponseError(
711
+ `raw block header hash mismatch: expected ${hash.toLowerCase()}, got ${actualHash}`
712
+ );
713
+ }
714
+ return data;
715
+ }
716
+ /** Decodes the response body as text, enforcing the size limit (fail-closed). */
2113
717
  #decode(data) {
2114
718
  if (data.length > MAX_ESPLORA_RESPONSE_SIZE) {
2115
719
  throw new EsploraResponseError(
@@ -2120,7 +724,7 @@ var EsploraClient = class {
2120
724
  return new TextDecoder("utf-8", { fatal: true }).decode(data);
2121
725
  } catch (cause) {
2122
726
  throw new EsploraResponseError("esplora response contains invalid UTF-8 bytes", {
2123
- cause: cause instanceof Error ? cause : void 0
727
+ ...cause instanceof Error ? { cause } : {}
2124
728
  });
2125
729
  }
2126
730
  }
@@ -2130,8 +734,8 @@ async function verifyTimestampAttestation(digest, attestation, explorer, signal)
2130
734
  throw new VerificationError(`cannot verify a '${attestation.kind}' attestation against the chain`);
2131
735
  }
2132
736
  const hash = await explorer.blockHash(attestation.height, signal);
2133
- const header = await explorer.block(hash, signal);
2134
- return verifyAgainstBlockheader(digest, header);
737
+ const rawHeader = await explorer.rawBlockHeader(hash, signal);
738
+ return verifyAgainstRawHeader(digest, rawHeader);
2135
739
  }
2136
740
 
2137
741
  // src/core/orchestration.ts
@@ -2315,7 +919,7 @@ async function orchestrateUpgrade(incompleteProof, _calendars, networkLayer, log
2315
919
  } catch (error) {
2316
920
  throw new ValidationError("Invalid .ots proof format", {
2317
921
  /* v8 ignore next */
2318
- cause: error instanceof Error ? error : void 0
922
+ ...error instanceof Error ? { cause: error } : {}
2319
923
  });
2320
924
  }
2321
925
  if (detached.timestamp.isTimestampComplete()) {
@@ -2352,15 +956,21 @@ async function orchestrateUpgrade(incompleteProof, _calendars, networkLayer, log
2352
956
  }
2353
957
  return Buffer.from(after);
2354
958
  }
2355
- async function orchestrateVerify(proof, networkLayer, originalDataHash, logger, signal) {
959
+ async function orchestrateVerify(proof, networkLayer, originalDataHash, logger, signal, esploraUrl) {
2356
960
  let detached;
2357
961
  try {
2358
962
  detached = DetachedTimestampFile.deserialize(new Uint8Array(proof));
2359
963
  } catch (cause) {
2360
964
  throw new ValidationError("Invalid .ots proof format", {
2361
- cause: cause instanceof Error ? cause : void 0
965
+ ...cause instanceof Error ? { cause } : {}
2362
966
  });
2363
967
  }
968
+ if (detached.fileHashOp instanceof OpSHA1 || detached.fileHashOp instanceof OpRIPEMD160) {
969
+ return {
970
+ status: "invalid",
971
+ reason: `This proof uses ${detached.fileHashOp.tagName} (a weak hash algorithm). Re-stamp the original file with SHA-256 to get a verifiable proof.`
972
+ };
973
+ }
2364
974
  if (originalDataHash !== void 0) {
2365
975
  let expected;
2366
976
  try {
@@ -2368,7 +978,7 @@ async function orchestrateVerify(proof, networkLayer, originalDataHash, logger,
2368
978
  } catch (err) {
2369
979
  throw new ValidationError(
2370
980
  err instanceof Error ? err.message : "Invalid hash format",
2371
- { cause: err instanceof Error ? err : void 0 }
981
+ { ...err instanceof Error ? { cause: err } : {} }
2372
982
  );
2373
983
  }
2374
984
  if (!timingSafeEq(expected, detached.fileDigest())) {
@@ -2399,7 +1009,10 @@ async function orchestrateVerify(proof, networkLayer, originalDataHash, logger,
2399
1009
  reason: hasLitecoin ? "Litecoin-only attestation is not supported by this client" : "No Bitcoin attestation found \u2014 timestamp not yet confirmed"
2400
1010
  };
2401
1011
  }
2402
- const explorer = new EsploraClient(networkLayer);
1012
+ const explorer = new EsploraClient(networkLayer, {
1013
+ ...esploraUrl !== void 0 ? { url: esploraUrl } : {},
1014
+ ...logger !== void 0 ? { logger } : {}
1015
+ });
2403
1016
  let lastNetworkError;
2404
1017
  let lastCryptoError;
2405
1018
  for (const { msg, attestation } of bitcoinAtts) {
@@ -2441,20 +1054,32 @@ var OpenTimestampsClient = class {
2441
1054
  globalSignal;
2442
1055
  minimumSuccessfulSubmissions;
2443
1056
  allowPrivateCalendars;
1057
+ esploraUrl;
2444
1058
  /**
2445
1059
  * Create a new OpenTimestamps client
2446
1060
  *
2447
1061
  * @param options Client configuration options
2448
1062
  */
2449
1063
  constructor(options = {}) {
1064
+ this.logger = options.logger;
2450
1065
  if (!options.calendars || options.calendars.length === 0) {
2451
1066
  this.calendars = DEFAULT_CALENDARS;
2452
1067
  this.logger?.info("No calendars provided, using defaults");
2453
1068
  } else {
2454
1069
  this.calendars = options.calendars;
2455
1070
  }
2456
- this.minimumSuccessfulSubmissions = options.minimumSuccessfulSubmissions ?? 2;
1071
+ const minSubs = options.minimumSuccessfulSubmissions ?? 2;
1072
+ if (!Number.isInteger(minSubs) || minSubs < 1) {
1073
+ throw new ValidationError("minimumSuccessfulSubmissions must be an integer >= 1");
1074
+ }
1075
+ if (minSubs > this.calendars.length) {
1076
+ throw new ValidationError(
1077
+ `minimumSuccessfulSubmissions (${minSubs}) cannot exceed the number of calendars (${this.calendars.length})`
1078
+ );
1079
+ }
1080
+ this.minimumSuccessfulSubmissions = minSubs;
2457
1081
  this.allowPrivateCalendars = options.allowPrivateCalendars ?? false;
1082
+ this.esploraUrl = options.esploraUrl;
2458
1083
  const resilienceConfig = {
2459
1084
  ...DEFAULT_RESILIENCE,
2460
1085
  ...options.resilience,
@@ -2471,8 +1096,7 @@ var OpenTimestampsClient = class {
2471
1096
  ...options.resilience?.circuitBreaker
2472
1097
  }
2473
1098
  };
2474
- this.logger = options.logger;
2475
- this.globalSignal = options.signal;
1099
+ if (options.signal !== void 0) this.globalSignal = options.signal;
2476
1100
  const internalOptions = options;
2477
1101
  this.networkLayer = internalOptions._networkLayer ?? new ResilientNetworkLayer(resilienceConfig, this.logger);
2478
1102
  this.logger?.info(`OpenTimestamps client initialized with ${this.calendars.length} calendars`);
@@ -2557,7 +1181,7 @@ var OpenTimestampsClient = class {
2557
1181
  * ```
2558
1182
  */
2559
1183
  async verify(proof, originalDataHash) {
2560
- return orchestrateVerify(proof, this.networkLayer, originalDataHash, this.logger, this.globalSignal);
1184
+ return orchestrateVerify(proof, this.networkLayer, originalDataHash, this.logger, this.globalSignal, this.esploraUrl);
2561
1185
  }
2562
1186
  /**
2563
1187
  * Get the current state of the circuit breaker for a calendar
@@ -2589,15 +1213,19 @@ var OpenTimestampsClient = class {
2589
1213
  }
2590
1214
  };
2591
1215
 
1216
+ // src/index.ts
1217
+ import { DetachedTimestampFile as DetachedTimestampFile2, Timestamp as Timestamp2 } from "@otskit/core";
1218
+ import { verifyAgainstBlockheader } from "@otskit/core";
1219
+
2592
1220
  // src/utils/hash.ts
2593
- import { createHash } from "crypto";
1221
+ import { createHash as createHash2 } from "crypto";
2594
1222
  import { createReadStream } from "fs";
2595
1223
  function hashBuffer(data) {
2596
- return createHash("sha256").update(data).digest();
1224
+ return createHash2("sha256").update(data).digest();
2597
1225
  }
2598
1226
  function hashFile(path) {
2599
1227
  return new Promise((resolve, reject) => {
2600
- const hash = createHash("sha256");
1228
+ const hash = createHash2("sha256");
2601
1229
  createReadStream(path).on("data", (chunk) => hash.update(chunk)).on("end", () => resolve(hash.digest())).on("error", reject);
2602
1230
  });
2603
1231
  }
@@ -2611,7 +1239,7 @@ export {
2611
1239
  DEFAULT_CALENDARS,
2612
1240
  DEFAULT_CALENDAR_WHITELIST,
2613
1241
  DEFAULT_RESILIENCE,
2614
- DetachedTimestampFile,
1242
+ DetachedTimestampFile2 as DetachedTimestampFile,
2615
1243
  EsploraClient,
2616
1244
  EsploraResponseError,
2617
1245
  MAX_CALENDAR_RESPONSE_SIZE,
@@ -2623,7 +1251,7 @@ export {
2623
1251
  ResilientNetworkLayer,
2624
1252
  SizeLimitExceededError,
2625
1253
  StampError,
2626
- Timestamp,
1254
+ Timestamp2 as Timestamp,
2627
1255
  UpgradeError,
2628
1256
  UrlWhitelist,
2629
1257
  ValidationError,