@unicitylabs/sphere-sdk 0.14.1-dev.1 → 0.14.1-dev.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/connect/index.cjs +20 -5
  2. package/dist/connect/index.cjs.map +1 -1
  3. package/dist/connect/index.d.cts +0 -1
  4. package/dist/connect/index.d.ts +0 -1
  5. package/dist/connect/index.js +20 -5
  6. package/dist/connect/index.js.map +1 -1
  7. package/dist/core/index.cjs +395 -213
  8. package/dist/core/index.cjs.map +1 -1
  9. package/dist/core/index.d.cts +10 -3
  10. package/dist/core/index.d.ts +10 -3
  11. package/dist/core/index.js +395 -213
  12. package/dist/core/index.js.map +1 -1
  13. package/dist/impl/browser/connect/index.cjs +10 -2
  14. package/dist/impl/browser/connect/index.cjs.map +1 -1
  15. package/dist/impl/browser/connect/index.d.cts +0 -1
  16. package/dist/impl/browser/connect/index.d.ts +0 -1
  17. package/dist/impl/browser/connect/index.js +10 -2
  18. package/dist/impl/browser/connect/index.js.map +1 -1
  19. package/dist/impl/nodejs/connect/index.cjs +9 -1
  20. package/dist/impl/nodejs/connect/index.cjs.map +1 -1
  21. package/dist/impl/nodejs/connect/index.d.cts +0 -1
  22. package/dist/impl/nodejs/connect/index.d.ts +0 -1
  23. package/dist/impl/nodejs/connect/index.js +9 -1
  24. package/dist/impl/nodejs/connect/index.js.map +1 -1
  25. package/dist/impl/nodejs/index.d.cts +8 -1
  26. package/dist/impl/nodejs/index.d.ts +8 -1
  27. package/dist/impl/shared/wallet-api/index.d.cts +8 -1
  28. package/dist/impl/shared/wallet-api/index.d.ts +8 -1
  29. package/dist/impl/wallet-api-v2/index.cjs +38 -5
  30. package/dist/impl/wallet-api-v2/index.cjs.map +1 -1
  31. package/dist/impl/wallet-api-v2/index.d.cts +23 -2
  32. package/dist/impl/wallet-api-v2/index.d.ts +23 -2
  33. package/dist/impl/wallet-api-v2/index.js +38 -5
  34. package/dist/impl/wallet-api-v2/index.js.map +1 -1
  35. package/dist/index.cjs +395 -213
  36. package/dist/index.cjs.map +1 -1
  37. package/dist/index.d.cts +10 -3
  38. package/dist/index.d.ts +10 -3
  39. package/dist/index.js +395 -213
  40. package/dist/index.js.map +1 -1
  41. package/dist/modules/payments-v2/index.cjs +340 -199
  42. package/dist/modules/payments-v2/index.cjs.map +1 -1
  43. package/dist/modules/payments-v2/index.d.cts +68 -19
  44. package/dist/modules/payments-v2/index.d.ts +68 -19
  45. package/dist/modules/payments-v2/index.js +339 -199
  46. package/dist/modules/payments-v2/index.js.map +1 -1
  47. package/package.json +1 -1
@@ -1058,6 +1058,14 @@ interface FacadeSession {
1058
1058
  start(): Promise<void>;
1059
1059
  stop(): Promise<void>;
1060
1060
  subscribeStream(stream: 'inventory' | 'mailbox' | 'payment_requests', handler: () => void): () => void;
1061
+ /** §5.1: the latched server syncEpoch ('' before first server contact). */
1062
+ currentEpoch(): string;
1063
+ /**
1064
+ * §5.1 restore hook — REQUIRED so an unwired restore protocol is a COMPILE
1065
+ * ERROR: handlers run and are AWAITED on a syncEpoch change BEFORE any
1066
+ * stream nudge resumes. The facade registers handleEpochChange here.
1067
+ */
1068
+ subscribeEpochChange(handler: (epoch: string) => Promise<void>): () => void;
1061
1069
  /**
1062
1070
  * Optional connection-status feed (same wiring pattern as the streams; the
1063
1071
  * emission point is the session's existing `connection:status` transition).
@@ -1346,7 +1354,6 @@ interface PaymentsV2TransportArgs {
1346
1354
  /** Per-(network, address) scoped KV — refresh token, cursors, seen-set live here. */
1347
1355
  kv: ScopedKV;
1348
1356
  emitStatus: (status: ConnectionStatus) => void;
1349
- onEpochChange: (epoch: string) => Promise<void>;
1350
1357
  }
1351
1358
  /**
1352
1359
  * The `Sphere.init({ walletApi })` transport config — built by
@@ -1058,6 +1058,14 @@ interface FacadeSession {
1058
1058
  start(): Promise<void>;
1059
1059
  stop(): Promise<void>;
1060
1060
  subscribeStream(stream: 'inventory' | 'mailbox' | 'payment_requests', handler: () => void): () => void;
1061
+ /** §5.1: the latched server syncEpoch ('' before first server contact). */
1062
+ currentEpoch(): string;
1063
+ /**
1064
+ * §5.1 restore hook — REQUIRED so an unwired restore protocol is a COMPILE
1065
+ * ERROR: handlers run and are AWAITED on a syncEpoch change BEFORE any
1066
+ * stream nudge resumes. The facade registers handleEpochChange here.
1067
+ */
1068
+ subscribeEpochChange(handler: (epoch: string) => Promise<void>): () => void;
1061
1069
  /**
1062
1070
  * Optional connection-status feed (same wiring pattern as the streams; the
1063
1071
  * emission point is the session's existing `connection:status` transition).
@@ -1346,7 +1354,6 @@ interface PaymentsV2TransportArgs {
1346
1354
  /** Per-(network, address) scoped KV — refresh token, cursors, seen-set live here. */
1347
1355
  kv: ScopedKV;
1348
1356
  emitStatus: (status: ConnectionStatus) => void;
1349
- onEpochChange: (epoch: string) => Promise<void>;
1350
1357
  }
1351
1358
  /**
1352
1359
  * The `Sphere.init({ walletApi })` transport config — built by
@@ -451,6 +451,14 @@ interface FacadeSession {
451
451
  start(): Promise<void>;
452
452
  stop(): Promise<void>;
453
453
  subscribeStream(stream: 'inventory' | 'mailbox' | 'payment_requests', handler: () => void): () => void;
454
+ /** §5.1: the latched server syncEpoch ('' before first server contact). */
455
+ currentEpoch(): string;
456
+ /**
457
+ * §5.1 restore hook — REQUIRED so an unwired restore protocol is a COMPILE
458
+ * ERROR: handlers run and are AWAITED on a syncEpoch change BEFORE any
459
+ * stream nudge resumes. The facade registers handleEpochChange here.
460
+ */
461
+ subscribeEpochChange(handler: (epoch: string) => Promise<void>): () => void;
454
462
  /**
455
463
  * Optional connection-status feed (same wiring pattern as the streams; the
456
464
  * emission point is the session's existing `connection:status` transition).
@@ -739,7 +747,6 @@ interface PaymentsV2TransportArgs {
739
747
  /** Per-(network, address) scoped KV — refresh token, cursors, seen-set live here. */
740
748
  kv: ScopedKV;
741
749
  emitStatus: (status: ConnectionStatus) => void;
742
- onEpochChange: (epoch: string) => Promise<void>;
743
750
  }
744
751
  /**
745
752
  * The `Sphere.init({ walletApi })` transport config — built by
@@ -451,6 +451,14 @@ interface FacadeSession {
451
451
  start(): Promise<void>;
452
452
  stop(): Promise<void>;
453
453
  subscribeStream(stream: 'inventory' | 'mailbox' | 'payment_requests', handler: () => void): () => void;
454
+ /** §5.1: the latched server syncEpoch ('' before first server contact). */
455
+ currentEpoch(): string;
456
+ /**
457
+ * §5.1 restore hook — REQUIRED so an unwired restore protocol is a COMPILE
458
+ * ERROR: handlers run and are AWAITED on a syncEpoch change BEFORE any
459
+ * stream nudge resumes. The facade registers handleEpochChange here.
460
+ */
461
+ subscribeEpochChange(handler: (epoch: string) => Promise<void>): () => void;
454
462
  /**
455
463
  * Optional connection-status feed (same wiring pattern as the streams; the
456
464
  * emission point is the session's existing `connection:status` transition).
@@ -739,7 +747,6 @@ interface PaymentsV2TransportArgs {
739
747
  /** Per-(network, address) scoped KV — refresh token, cursors, seen-set live here. */
740
748
  kv: ScopedKV;
741
749
  emitStatus: (status: ConnectionStatus) => void;
742
- onEpochChange: (epoch: string) => Promise<void>;
743
750
  }
744
751
  /**
745
752
  * The `Sphere.init({ walletApi })` transport config — built by
@@ -742,7 +742,10 @@ var STORE_KEYS = {
742
742
  shortfalls: "shortfalls",
743
743
  settlingLinks: "settling",
744
744
  streamCursor: (s) => `cursor:${s}`,
745
- epochLatch: "epoch-latch"
745
+ epochLatch: "epoch-latch",
746
+ // §5.2 InventoryView durable overlays (#625/#679).
747
+ suspectedSpent: "suspected-spent",
748
+ knownSpends: "known-spends"
746
749
  };
747
750
 
748
751
  // node_modules/@noble/curves/utils.js
@@ -2766,6 +2769,7 @@ var WalletApiSession = class {
2766
2769
  epochLatch = null;
2767
2770
  reseedChain = Promise.resolve();
2768
2771
  reseedsPending = 0;
2772
+ epochHandlers = /* @__PURE__ */ new Set();
2769
2773
  handlers = /* @__PURE__ */ new Map();
2770
2774
  statusHandlers = /* @__PURE__ */ new Set();
2771
2775
  socket = null;
@@ -2868,6 +2872,18 @@ var WalletApiSession = class {
2868
2872
  await this.deps.kv.set(this.refreshKey, tokens.refreshToken);
2869
2873
  }
2870
2874
  // ── epoch latch (F12) ─────────────────────────────────────────────────────
2875
+ /** §5.1: the latched server syncEpoch ('' before first server contact). */
2876
+ currentEpoch() {
2877
+ return this.epochLatch ?? "";
2878
+ }
2879
+ /**
2880
+ * §5.1 restore hook (FacadeSession contract): handlers are AWAITED inside
2881
+ * the reseed chain, BEFORE any stream nudge resumes.
2882
+ */
2883
+ subscribeEpochChange(handler) {
2884
+ this.epochHandlers.add(handler);
2885
+ return () => this.epochHandlers.delete(handler);
2886
+ }
2871
2887
  noteEpoch(epoch) {
2872
2888
  if (this.epochLatch === epoch) return;
2873
2889
  const previous = this.epochLatch;
@@ -2881,7 +2897,7 @@ var WalletApiSession = class {
2881
2897
  }
2882
2898
  async runReseed(epoch, previous) {
2883
2899
  try {
2884
- await this.deps.onEpochChange(epoch);
2900
+ for (const handler of [...this.epochHandlers]) await handler(epoch);
2885
2901
  await this.deps.kv.set(STORE_KEYS.epochLatch, epoch);
2886
2902
  } catch {
2887
2903
  if (this.epochLatch === epoch) this.epochLatch = previous;
@@ -4089,6 +4105,7 @@ var WalletApiDeliveryPort = class {
4089
4105
  wake;
4090
4106
  deriveFn;
4091
4107
  seenChain = new SerialChain();
4108
+ lastIncomingEpoch = null;
4092
4109
  constructor(config) {
4093
4110
  this.client = config.client;
4094
4111
  this.kv = config.kv;
@@ -4183,6 +4200,7 @@ var WalletApiDeliveryPort = class {
4183
4200
  const seen = await this.readSeen();
4184
4201
  let page = await this.client.listMailbox(sinceCursor === void 0 ? 0 : Number(sinceCursor));
4185
4202
  for (; ; ) {
4203
+ this.lastIncomingEpoch = String(page.syncEpoch);
4186
4204
  for (const entry of page.entries) {
4187
4205
  if (entry.status !== "unclaimed") continue;
4188
4206
  if (seen.has(entry.entryId)) continue;
@@ -4192,6 +4210,10 @@ var WalletApiDeliveryPort = class {
4192
4210
  page = await this.client.listMailbox(page.cursor);
4193
4211
  }
4194
4212
  }
4213
+ /** §5.7: the page-honest epoch — the restore-detection source Receive keys on. */
4214
+ incomingEpoch() {
4215
+ return this.lastIncomingEpoch;
4216
+ }
4195
4217
  toIncoming(entry) {
4196
4218
  const bundle = this.openEnvelope(entry);
4197
4219
  return {
@@ -4347,7 +4369,7 @@ var WalletApiSplitCheckpointStore = class {
4347
4369
  return utf8(`${transferId}:${String(opIndex)}`);
4348
4370
  }
4349
4371
  async put(transferId, opIndex, bytes) {
4350
- const { client, kv, fieldKey, signProgress } = this.config;
4372
+ const { kv, fieldKey } = this.config;
4351
4373
  const aad = this.aad(transferId, opIndex);
4352
4374
  const cacheKey = this.cacheKey(transferId, opIndex);
4353
4375
  let envelope = await kv.get(cacheKey);
@@ -4355,10 +4377,21 @@ var WalletApiSplitCheckpointStore = class {
4355
4377
  envelope = encryptFieldBytes(fieldKey, bytes, aad);
4356
4378
  await kv.set(cacheKey, envelope);
4357
4379
  }
4358
- const signature = await signProgress(progressSignMessage(transferId, opIndex, envelope));
4359
- const record = await client.postProgress(transferId, opIndex, envelope, signature);
4380
+ const record = await this.post(transferId, opIndex, envelope);
4360
4381
  return this.open(record.payload, aad);
4361
4382
  }
4383
+ /** §5.1 restore (CheckpointReseeder): re-POST the cached ciphertext byte-identical; false = none cached. */
4384
+ async reseedCheckpoint(transferId, opIndex) {
4385
+ const envelope = await this.config.kv.get(this.cacheKey(transferId, opIndex));
4386
+ if (envelope === null) return false;
4387
+ await this.post(transferId, opIndex, envelope);
4388
+ return true;
4389
+ }
4390
+ /** The ONE signed progress-append path put() and reseedCheckpoint() share. */
4391
+ async post(transferId, opIndex, envelope) {
4392
+ const signature = await this.config.signProgress(progressSignMessage(transferId, opIndex, envelope));
4393
+ return this.config.client.postProgress(transferId, opIndex, envelope, signature);
4394
+ }
4362
4395
  async get(transferId, opIndex) {
4363
4396
  const records = await this.config.client.getProgress(transferId);
4364
4397
  const record = records.find((r) => r.opIndex === opIndex);