@otskit/client 0.6.1 → 0.7.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/browser.d.ts CHANGED
@@ -31,6 +31,12 @@ declare class OpenTimestampsBrowserClient {
31
31
  constructor(options?: BrowserClientOptions);
32
32
  /** hash: 32-byte Uint8Array or 64-char hex. Returns the pending .ots as Uint8Array. */
33
33
  stamp(hash: Uint8Array | string): Promise<Uint8Array>;
34
+ /**
35
+ * proof: a pending .ots as bytes. Queries the calendars it references (allowlisted) and returns
36
+ * the upgraded .ots. Throws UpgradeError if no calendar has confirmed the timestamp yet, which is
37
+ * the normal state until Bitcoin mines the commitment (typically an hour or more after stamping).
38
+ */
39
+ upgrade(proof: Uint8Array): Promise<Uint8Array>;
34
40
  }
35
41
 
36
42
  export { BROWSER_CALENDARS, type BrowserClientOptions, OpenTimestampsBrowserClient, bytesToHex, hashBlob, hashBytes };
package/dist/browser.js CHANGED
@@ -20,6 +20,8 @@ var StampError = class extends OpenTimestampsClientError {
20
20
  this.failedSubmissions = failed;
21
21
  }
22
22
  };
23
+ var UpgradeError = class extends OpenTimestampsClientError {
24
+ };
23
25
  var NetworkError = class extends OpenTimestampsClientError {
24
26
  /** HTTP status code when the failure originates from an HTTP response. */
25
27
  status;
@@ -653,6 +655,63 @@ async function orchestrateStamp(hash, calendars, networkLayer, validateCalendarU
653
655
  return detached.serializeToBytes();
654
656
  }
655
657
 
658
+ // src/core/upgrade-core.ts
659
+ import { DetachedTimestampFile as DetachedTimestampFile2 } from "@otskit/core";
660
+ function bytesEqual(a, b) {
661
+ if (a.length !== b.length) return false;
662
+ let diff = 0;
663
+ for (let i = 0; i < a.length; i++) {
664
+ diff |= a[i] ^ b[i];
665
+ }
666
+ return diff === 0;
667
+ }
668
+ async function upgradeProofBytes(incompleteProof, networkLayer, logger, signal) {
669
+ let detached;
670
+ try {
671
+ detached = DetachedTimestampFile2.deserialize(incompleteProof);
672
+ } catch (error) {
673
+ throw new ValidationError("Invalid .ots proof format", {
674
+ /* v8 ignore next */
675
+ ...error instanceof Error ? { cause: error } : {}
676
+ });
677
+ }
678
+ if (detached.timestamp.isTimestampComplete()) {
679
+ logger?.info("Proof already complete; nothing to upgrade");
680
+ return incompleteProof;
681
+ }
682
+ const before = detached.serializeToBytes();
683
+ for (const subStamp of detached.timestamp.directlyVerified()) {
684
+ if (subStamp.isTimestampComplete()) continue;
685
+ for (const att of subStamp.attestations) {
686
+ if (att.kind !== "pending") continue;
687
+ if (!DEFAULT_CALENDAR_WHITELIST.contains(att.uri)) {
688
+ logger?.warn(`Ignoring attestation from non-whitelisted calendar ${att.uri}`);
689
+ continue;
690
+ }
691
+ try {
692
+ const upgraded = await new CalendarClient(att.uri, networkLayer, logger).getTimestamp(
693
+ subStamp.getDigest(),
694
+ signal
695
+ );
696
+ subStamp.merge(upgraded);
697
+ } catch (err) {
698
+ if (err instanceof CommitmentNotFoundError) {
699
+ logger?.debug(`Calendar ${att.uri} has not confirmed yet`);
700
+ continue;
701
+ }
702
+ logger?.warn(
703
+ `Failed to query ${att.uri}: ${err instanceof Error ? err.message : String(err)}`
704
+ );
705
+ }
706
+ }
707
+ }
708
+ const after = detached.serializeToBytes();
709
+ if (bytesEqual(before, after)) {
710
+ throw new UpgradeError("No calendar has confirmed the timestamp yet (Bitcoin not yet mined)");
711
+ }
712
+ return after;
713
+ }
714
+
656
715
  // src/security/ssrf-web.ts
657
716
  async function assertSafeCalendarUrlStructural(url) {
658
717
  let parsed;
@@ -732,6 +791,14 @@ var OpenTimestampsBrowserClient = class {
732
791
  this.minSubs
733
792
  );
734
793
  }
794
+ /**
795
+ * proof: a pending .ots as bytes. Queries the calendars it references (allowlisted) and returns
796
+ * the upgraded .ots. Throws UpgradeError if no calendar has confirmed the timestamp yet, which is
797
+ * the normal state until Bitcoin mines the commitment (typically an hour or more after stamping).
798
+ */
799
+ upgrade(proof) {
800
+ return upgradeProofBytes(proof, this.layer, this.logger);
801
+ }
735
802
  };
736
803
  export {
737
804
  BROWSER_CALENDARS,
package/dist/index.cjs CHANGED
@@ -738,13 +738,20 @@ async function orchestrateStamp(hash, calendars, networkLayer, validateCalendarU
738
738
  return detached.serializeToBytes();
739
739
  }
740
740
 
741
- // src/core/upgrade.ts
741
+ // src/core/upgrade-core.ts
742
742
  var import_core4 = require("@otskit/core");
743
- var bytesEqFast = (a, b) => Buffer.compare(Buffer.from(a), Buffer.from(b)) === 0;
744
- async function orchestrateUpgrade(incompleteProof, _calendars, networkLayer, logger, signal) {
743
+ function bytesEqual(a, b) {
744
+ if (a.length !== b.length) return false;
745
+ let diff = 0;
746
+ for (let i = 0; i < a.length; i++) {
747
+ diff |= a[i] ^ b[i];
748
+ }
749
+ return diff === 0;
750
+ }
751
+ async function upgradeProofBytes(incompleteProof, networkLayer, logger, signal) {
745
752
  let detached;
746
753
  try {
747
- detached = import_core4.DetachedTimestampFile.deserialize(new Uint8Array(incompleteProof));
754
+ detached = import_core4.DetachedTimestampFile.deserialize(incompleteProof);
748
755
  } catch (error) {
749
756
  throw new ValidationError("Invalid .ots proof format", {
750
757
  /* v8 ignore next */
@@ -753,7 +760,7 @@ async function orchestrateUpgrade(incompleteProof, _calendars, networkLayer, log
753
760
  }
754
761
  if (detached.timestamp.isTimestampComplete()) {
755
762
  logger?.info("Proof already complete; nothing to upgrade");
756
- return Buffer.from(incompleteProof);
763
+ return incompleteProof;
757
764
  }
758
765
  const before = detached.serializeToBytes();
759
766
  for (const subStamp of detached.timestamp.directlyVerified()) {
@@ -782,10 +789,21 @@ async function orchestrateUpgrade(incompleteProof, _calendars, networkLayer, log
782
789
  }
783
790
  }
784
791
  const after = detached.serializeToBytes();
785
- if (bytesEqFast(before, after)) {
792
+ if (bytesEqual(before, after)) {
786
793
  throw new UpgradeError("No calendar has confirmed the timestamp yet (Bitcoin not yet mined)");
787
794
  }
788
- return Buffer.from(after);
795
+ return after;
796
+ }
797
+
798
+ // src/core/upgrade.ts
799
+ async function orchestrateUpgrade(incompleteProof, _calendars, networkLayer, logger, signal) {
800
+ const upgraded = await upgradeProofBytes(
801
+ new Uint8Array(incompleteProof),
802
+ networkLayer,
803
+ logger,
804
+ signal
805
+ );
806
+ return Buffer.from(upgraded);
789
807
  }
790
808
 
791
809
  // src/core/verify.ts
package/dist/index.js CHANGED
@@ -688,13 +688,20 @@ async function orchestrateStamp(hash, calendars, networkLayer, validateCalendarU
688
688
  return detached.serializeToBytes();
689
689
  }
690
690
 
691
- // src/core/upgrade.ts
691
+ // src/core/upgrade-core.ts
692
692
  import { DetachedTimestampFile as DetachedTimestampFile2 } from "@otskit/core";
693
- var bytesEqFast = (a, b) => Buffer.compare(Buffer.from(a), Buffer.from(b)) === 0;
694
- async function orchestrateUpgrade(incompleteProof, _calendars, networkLayer, logger, signal) {
693
+ function bytesEqual(a, b) {
694
+ if (a.length !== b.length) return false;
695
+ let diff = 0;
696
+ for (let i = 0; i < a.length; i++) {
697
+ diff |= a[i] ^ b[i];
698
+ }
699
+ return diff === 0;
700
+ }
701
+ async function upgradeProofBytes(incompleteProof, networkLayer, logger, signal) {
695
702
  let detached;
696
703
  try {
697
- detached = DetachedTimestampFile2.deserialize(new Uint8Array(incompleteProof));
704
+ detached = DetachedTimestampFile2.deserialize(incompleteProof);
698
705
  } catch (error) {
699
706
  throw new ValidationError("Invalid .ots proof format", {
700
707
  /* v8 ignore next */
@@ -703,7 +710,7 @@ async function orchestrateUpgrade(incompleteProof, _calendars, networkLayer, log
703
710
  }
704
711
  if (detached.timestamp.isTimestampComplete()) {
705
712
  logger?.info("Proof already complete; nothing to upgrade");
706
- return Buffer.from(incompleteProof);
713
+ return incompleteProof;
707
714
  }
708
715
  const before = detached.serializeToBytes();
709
716
  for (const subStamp of detached.timestamp.directlyVerified()) {
@@ -732,10 +739,21 @@ async function orchestrateUpgrade(incompleteProof, _calendars, networkLayer, log
732
739
  }
733
740
  }
734
741
  const after = detached.serializeToBytes();
735
- if (bytesEqFast(before, after)) {
742
+ if (bytesEqual(before, after)) {
736
743
  throw new UpgradeError("No calendar has confirmed the timestamp yet (Bitcoin not yet mined)");
737
744
  }
738
- return Buffer.from(after);
745
+ return after;
746
+ }
747
+
748
+ // src/core/upgrade.ts
749
+ async function orchestrateUpgrade(incompleteProof, _calendars, networkLayer, logger, signal) {
750
+ const upgraded = await upgradeProofBytes(
751
+ new Uint8Array(incompleteProof),
752
+ networkLayer,
753
+ logger,
754
+ signal
755
+ );
756
+ return Buffer.from(upgraded);
739
757
  }
740
758
 
741
759
  // src/core/verify.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@otskit/client",
3
- "version": "0.6.1",
3
+ "version": "0.7.0",
4
4
  "description": "Official client SDK for OpenTimestamps calendars with resilience patterns",
5
5
  "author": "alexalves87",
6
6
  "license": "MIT",