@unicitylabs/sphere-sdk 0.14.11-dev.8 → 0.15.0-dev.1

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 (46) hide show
  1. package/README.md +55 -17
  2. package/dist/connect/index.cjs +10 -17
  3. package/dist/connect/index.cjs.map +1 -1
  4. package/dist/connect/index.js +10 -17
  5. package/dist/connect/index.js.map +1 -1
  6. package/dist/core/index.cjs +98 -99
  7. package/dist/core/index.cjs.map +1 -1
  8. package/dist/core/index.d.cts +5 -14
  9. package/dist/core/index.d.ts +5 -14
  10. package/dist/core/index.js +98 -99
  11. package/dist/core/index.js.map +1 -1
  12. package/dist/impl/browser/connect/index.cjs +3 -3
  13. package/dist/impl/browser/connect/index.cjs.map +1 -1
  14. package/dist/impl/browser/connect/index.js +3 -3
  15. package/dist/impl/browser/connect/index.js.map +1 -1
  16. package/dist/impl/browser/index.cjs.map +1 -1
  17. package/dist/impl/browser/index.js.map +1 -1
  18. package/dist/impl/nodejs/connect/index.cjs +2 -2
  19. package/dist/impl/nodejs/connect/index.cjs.map +1 -1
  20. package/dist/impl/nodejs/connect/index.js +2 -2
  21. package/dist/impl/nodejs/connect/index.js.map +1 -1
  22. package/dist/impl/nodejs/index.cjs.map +1 -1
  23. package/dist/impl/nodejs/index.js.map +1 -1
  24. package/dist/impl/wallet-api-v2/index.cjs +95 -1
  25. package/dist/impl/wallet-api-v2/index.cjs.map +1 -1
  26. package/dist/impl/wallet-api-v2/index.js +95 -1
  27. package/dist/impl/wallet-api-v2/index.js.map +1 -1
  28. package/dist/index.cjs +98 -99
  29. package/dist/index.cjs.map +1 -1
  30. package/dist/index.d.cts +6 -11
  31. package/dist/index.d.ts +6 -11
  32. package/dist/index.js +98 -99
  33. package/dist/index.js.map +1 -1
  34. package/dist/modules/payments-v2/index.cjs +149 -193
  35. package/dist/modules/payments-v2/index.cjs.map +1 -1
  36. package/dist/modules/payments-v2/index.d.cts +8 -5
  37. package/dist/modules/payments-v2/index.d.ts +8 -5
  38. package/dist/modules/payments-v2/index.js +146 -192
  39. package/dist/modules/payments-v2/index.js.map +1 -1
  40. package/dist/token-engine/index.cjs +43 -57
  41. package/dist/token-engine/index.cjs.map +1 -1
  42. package/dist/token-engine/index.d.cts +0 -4
  43. package/dist/token-engine/index.d.ts +0 -4
  44. package/dist/token-engine/index.js +43 -57
  45. package/dist/token-engine/index.js.map +1 -1
  46. package/package.json +2 -2
@@ -39,13 +39,123 @@ __export(payments_v2_exports, {
39
39
  PaymentsFacade: () => PaymentsFacade,
40
40
  STORE_KEYS: () => STORE_KEYS,
41
41
  createScopedKV: () => createScopedKV,
42
- supportsDeterministicMint: () => supportsDeterministicMint
42
+ isRetryableAckError: () => isRetryableAckError,
43
+ supportsDeterministicMint: () => supportsDeterministicMint,
44
+ sweepSupersededState: () => sweepSupersededState
43
45
  });
44
46
  module.exports = __toCommonJS(payments_v2_exports);
45
47
 
48
+ // modules/payments-v2/ports.ts
49
+ function isRetryableAckError(err) {
50
+ return err !== null && typeof err === "object" && err.retryable === true;
51
+ }
52
+
53
+ // core/logger.ts
54
+ var LOGGER_KEY = "__sphere_sdk_logger__";
55
+ function getState() {
56
+ const g = globalThis;
57
+ if (!g[LOGGER_KEY]) {
58
+ g[LOGGER_KEY] = { debug: false, tags: {}, handler: null };
59
+ }
60
+ return g[LOGGER_KEY];
61
+ }
62
+ function isEnabled(tag) {
63
+ const state = getState();
64
+ if (tag in state.tags) return state.tags[tag];
65
+ return state.debug;
66
+ }
67
+ var logger = {
68
+ /**
69
+ * Configure the logger. Can be called multiple times (last write wins).
70
+ * Typically called by createBrowserProviders(), createNodeProviders(), or Sphere.init().
71
+ */
72
+ configure(config) {
73
+ const state = getState();
74
+ if (config.debug !== void 0) state.debug = config.debug;
75
+ if (config.handler !== void 0) state.handler = config.handler;
76
+ },
77
+ /**
78
+ * Enable/disable debug logging for a specific tag.
79
+ * Per-tag setting overrides the global debug flag.
80
+ *
81
+ * @example
82
+ * ```ts
83
+ * logger.setTagDebug('Nostr', true); // enable only Nostr logs
84
+ * logger.setTagDebug('Nostr', false); // disable Nostr logs even if global debug=true
85
+ * ```
86
+ */
87
+ setTagDebug(tag, enabled) {
88
+ getState().tags[tag] = enabled;
89
+ },
90
+ /**
91
+ * Clear per-tag override, falling back to global debug flag.
92
+ */
93
+ clearTagDebug(tag) {
94
+ delete getState().tags[tag];
95
+ },
96
+ /** Returns true if debug mode is enabled for the given tag (or globally). */
97
+ isDebugEnabled(tag) {
98
+ if (tag) return isEnabled(tag);
99
+ return getState().debug;
100
+ },
101
+ /**
102
+ * Debug-level log. Only shown when debug is enabled (globally or for this tag).
103
+ * Use for detailed operational information.
104
+ */
105
+ debug(tag, message, ...args) {
106
+ if (!isEnabled(tag)) return;
107
+ const state = getState();
108
+ if (state.handler) {
109
+ state.handler("debug", tag, message, ...args);
110
+ } else {
111
+ console.log(`[${tag}]`, message, ...args);
112
+ }
113
+ },
114
+ /**
115
+ * Warning-level log. ALWAYS shown regardless of debug flag.
116
+ * Use for important but non-critical issues (timeouts, retries, degraded state).
117
+ */
118
+ warn(tag, message, ...args) {
119
+ const state = getState();
120
+ if (state.handler) {
121
+ state.handler("warn", tag, message, ...args);
122
+ } else {
123
+ console.warn(`[${tag}]`, message, ...args);
124
+ }
125
+ },
126
+ /**
127
+ * Error-level log. ALWAYS shown regardless of debug flag.
128
+ * Use for critical failures that should never be silenced.
129
+ */
130
+ error(tag, message, ...args) {
131
+ const state = getState();
132
+ if (state.handler) {
133
+ state.handler("error", tag, message, ...args);
134
+ } else {
135
+ console.error(`[${tag}]`, message, ...args);
136
+ }
137
+ },
138
+ /** Reset all logger state (debug flag, tags, handler). Primarily for tests. */
139
+ reset() {
140
+ const g = globalThis;
141
+ delete g[LOGGER_KEY];
142
+ }
143
+ };
144
+
46
145
  // modules/payments-v2/stores.ts
146
+ var KV_PREFIX = "pv2g2:";
147
+ var SUPERSEDED_KV_PREFIXES = ["pv2:"];
148
+ async function sweepSupersededState(storage) {
149
+ for (const prefix of SUPERSEDED_KV_PREFIXES) {
150
+ try {
151
+ await storage.clear(prefix);
152
+ } catch (err) {
153
+ logger.warn("PaymentsV2", `could not clear superseded state under "${prefix}": ${String(err)}`);
154
+ }
155
+ }
156
+ }
47
157
  function createScopedKV(storage, network, chainPubkey) {
48
- const prefix = `pv2:${network}:${chainPubkey}:`;
158
+ const prefix = `${KV_PREFIX}${network}:${chainPubkey}:`;
49
159
  return {
50
160
  async get(key) {
51
161
  const raw = await storage.get(prefix + key);
@@ -494,69 +604,6 @@ function randomUUID() {
494
604
  return `${h[0]}${h[1]}${h[2]}${h[3]}-${h[4]}${h[5]}-${h[6]}${h[7]}-${h[8]}${h[9]}-${h[10]}${h[11]}${h[12]}${h[13]}${h[14]}${h[15]}`;
495
605
  }
496
606
 
497
- // token-engine/sdk.ts
498
- var import_StateTransitionClient = require("@unicitylabs/state-transition-sdk/lib/StateTransitionClient.js");
499
- var import_AggregatorClient = require("@unicitylabs/state-transition-sdk/lib/api/AggregatorClient.js");
500
- var import_NetworkId = require("@unicitylabs/state-transition-sdk/lib/api/NetworkId.js");
501
- var import_CertificationData = require("@unicitylabs/state-transition-sdk/lib/api/CertificationData.js");
502
- var import_CertificationResponse = require("@unicitylabs/state-transition-sdk/lib/api/CertificationResponse.js");
503
- var import_StateId = require("@unicitylabs/state-transition-sdk/lib/api/StateId.js");
504
- var import_InclusionProof = require("@unicitylabs/state-transition-sdk/lib/api/InclusionProof.js");
505
- var import_InclusionProofResponse = require("@unicitylabs/state-transition-sdk/lib/api/InclusionProofResponse.js");
506
- var import_JsonRpcNetworkError = require("@unicitylabs/state-transition-sdk/lib/api/json-rpc/JsonRpcNetworkError.js");
507
- var import_RootTrustBase = require("@unicitylabs/state-transition-sdk/lib/api/bft/RootTrustBase.js");
508
- var import_InclusionProofUtils = require("@unicitylabs/state-transition-sdk/lib/util/InclusionProofUtils.js");
509
- var import_InclusionProofVerificationRule = require("@unicitylabs/state-transition-sdk/lib/transaction/verification/rule/InclusionProofVerificationRule.js");
510
- var import_Token = require("@unicitylabs/state-transition-sdk/lib/transaction/Token.js");
511
- var import_MintTransaction = require("@unicitylabs/state-transition-sdk/lib/transaction/MintTransaction.js");
512
- var import_TransferTransaction = require("@unicitylabs/state-transition-sdk/lib/transaction/TransferTransaction.js");
513
- var import_CertifiedMintTransaction = require("@unicitylabs/state-transition-sdk/lib/transaction/CertifiedMintTransaction.js");
514
- var import_CertifiedTransferTransaction = require("@unicitylabs/state-transition-sdk/lib/transaction/CertifiedTransferTransaction.js");
515
- var import_TokenId = require("@unicitylabs/state-transition-sdk/lib/transaction/TokenId.js");
516
- var import_TokenType = require("@unicitylabs/state-transition-sdk/lib/transaction/TokenType.js");
517
- var import_TokenSalt = require("@unicitylabs/state-transition-sdk/lib/transaction/TokenSalt.js");
518
- var import_StateMask = require("@unicitylabs/state-transition-sdk/lib/transaction/StateMask.js");
519
- var import_MintJustificationVerifierService = require("@unicitylabs/state-transition-sdk/lib/transaction/verification/MintJustificationVerifierService.js");
520
- var import_TokenIssuanceVerifierService = require("@unicitylabs/state-transition-sdk/lib/transaction/verification/TokenIssuanceVerifierService.js");
521
- var import_VerificationContext = require("@unicitylabs/state-transition-sdk/lib/transaction/verification/VerificationContext.js");
522
- var import_UnicityCertificateVerifier = require("@unicitylabs/state-transition-sdk/lib/api/bft/verification/UnicityCertificateVerifier.js");
523
- var import_UnicitySealQuorumSignaturesVerificationRule = require("@unicitylabs/state-transition-sdk/lib/api/bft/verification/rule/UnicitySealQuorumSignaturesVerificationRule.js");
524
- var import_VerifiedSealCache = require("@unicitylabs/state-transition-sdk/lib/api/bft/verification/VerifiedSealCache.js");
525
- var import_Secp256k1SignatureVerifier = require("@unicitylabs/state-transition-sdk/lib/crypto/secp256k1/Secp256k1SignatureVerifier.js");
526
- var import_WorkerTokenVerifier = require("@unicitylabs/state-transition-sdk/lib/transaction/verification/worker/WorkerTokenVerifier.js");
527
- var import_EncodedPredicate = require("@unicitylabs/state-transition-sdk/lib/predicate/EncodedPredicate.js");
528
- var import_SignaturePredicate = require("@unicitylabs/state-transition-sdk/lib/predicate/builtin/SignaturePredicate.js");
529
- var import_SignaturePredicateUnlockScript = require("@unicitylabs/state-transition-sdk/lib/predicate/builtin/SignaturePredicateUnlockScript.js");
530
- var import_BurnPredicate = require("@unicitylabs/state-transition-sdk/lib/predicate/builtin/BurnPredicate.js");
531
- var import_PredicateVerifierService = require("@unicitylabs/state-transition-sdk/lib/predicate/verification/PredicateVerifierService.js");
532
- var import_SigningService = require("@unicitylabs/state-transition-sdk/lib/crypto/secp256k1/SigningService.js");
533
- var import_Signature = require("@unicitylabs/state-transition-sdk/lib/crypto/secp256k1/Signature.js");
534
- var import_MintSigningService = require("@unicitylabs/state-transition-sdk/lib/crypto/MintSigningService.js");
535
- var import_HashAlgorithm = require("@unicitylabs/state-transition-sdk/lib/crypto/hash/HashAlgorithm.js");
536
- var import_DataHash = require("@unicitylabs/state-transition-sdk/lib/crypto/hash/DataHash.js");
537
- var import_DataHasher = require("@unicitylabs/state-transition-sdk/lib/crypto/hash/DataHasher.js");
538
- var import_DataHasherFactory = require("@unicitylabs/state-transition-sdk/lib/crypto/hash/DataHasherFactory.js");
539
- var import_CborSerializer = require("@unicitylabs/state-transition-sdk/lib/serialization/cbor/CborSerializer.js");
540
- var import_CborDeserializer = require("@unicitylabs/state-transition-sdk/lib/serialization/cbor/CborDeserializer.js");
541
- var import_CborError = require("@unicitylabs/state-transition-sdk/lib/serialization/cbor/CborError.js");
542
- var import_Asset = require("@unicitylabs/state-transition-sdk/lib/payment/asset/Asset.js");
543
- var import_AssetId = require("@unicitylabs/state-transition-sdk/lib/payment/asset/AssetId.js");
544
- var import_PaymentAssetCollection = require("@unicitylabs/state-transition-sdk/lib/payment/asset/PaymentAssetCollection.js");
545
- var import_TokenSplit = require("@unicitylabs/state-transition-sdk/lib/payment/TokenSplit.js");
546
- var import_SplitTokenRequest = require("@unicitylabs/state-transition-sdk/lib/payment/SplitTokenRequest.js");
547
- var import_SplitToken = require("@unicitylabs/state-transition-sdk/lib/payment/SplitToken.js");
548
- var import_SplitAllocationProof = require("@unicitylabs/state-transition-sdk/lib/payment/SplitAllocationProof.js");
549
- var import_SplitMintJustification = require("@unicitylabs/state-transition-sdk/lib/payment/SplitMintJustification.js");
550
- var import_SplitMintJustificationVerifier = require("@unicitylabs/state-transition-sdk/lib/payment/SplitMintJustificationVerifier.js");
551
- var import_VerificationStatus = require("@unicitylabs/state-transition-sdk/lib/verification/VerificationStatus.js");
552
- var import_VerificationResult = require("@unicitylabs/state-transition-sdk/lib/verification/VerificationResult.js");
553
- var import_HexConverter = require("@unicitylabs/state-transition-sdk/lib/util/HexConverter.js");
554
- var import_BigintConverter = require("@unicitylabs/state-transition-sdk/lib/util/BigintConverter.js");
555
- var import_BitString = require("@unicitylabs/state-transition-sdk/lib/util/BitString.js");
556
-
557
- // token-engine/token-blob.ts
558
- var TOKEN_BLOB_VERSION = 1;
559
-
560
607
  // modules/payments-v2/async.ts
561
608
  var SingleFlight = class {
562
609
  flight = null;
@@ -1201,12 +1248,7 @@ var TransferMachine = class {
1201
1248
  let total = 0n;
1202
1249
  for (const outcome of committed) {
1203
1250
  if (outcome.recipientBlob === void 0) continue;
1204
- const token = await engine.decodeToken({
1205
- v: TOKEN_BLOB_VERSION,
1206
- network: 0,
1207
- tokenId: "",
1208
- token: outcome.recipientBlob
1209
- });
1251
+ const token = await engine.decodeToken({ tokenId: "", token: outcome.recipientBlob });
1210
1252
  total += engine.balanceOf(token, coinId);
1211
1253
  }
1212
1254
  return total.toString();
@@ -1322,8 +1364,9 @@ async function fetchSources(deps, jobs) {
1322
1364
  const engine = deps.engine();
1323
1365
  for (const [tokenId, bytes] of blobs) {
1324
1366
  try {
1325
- decoded.set(tokenId, await engine.decodeToken({ v: TOKEN_BLOB_VERSION, network: 0, tokenId, token: bytes }));
1326
- } catch {
1367
+ decoded.set(tokenId, await engine.decodeToken({ tokenId, token: bytes }));
1368
+ } catch (err) {
1369
+ logger.warn("PaymentsV2", `resume: source ${tokenId} did not decode \u2014 ${String(err)}`);
1327
1370
  }
1328
1371
  }
1329
1372
  return decoded;
@@ -3147,103 +3190,6 @@ var InventoryView = class {
3147
3190
  }
3148
3191
  };
3149
3192
 
3150
- // core/logger.ts
3151
- var LOGGER_KEY = "__sphere_sdk_logger__";
3152
- function getState() {
3153
- const g = globalThis;
3154
- if (!g[LOGGER_KEY]) {
3155
- g[LOGGER_KEY] = { debug: false, tags: {}, handler: null };
3156
- }
3157
- return g[LOGGER_KEY];
3158
- }
3159
- function isEnabled(tag) {
3160
- const state = getState();
3161
- if (tag in state.tags) return state.tags[tag];
3162
- return state.debug;
3163
- }
3164
- var logger = {
3165
- /**
3166
- * Configure the logger. Can be called multiple times (last write wins).
3167
- * Typically called by createBrowserProviders(), createNodeProviders(), or Sphere.init().
3168
- */
3169
- configure(config) {
3170
- const state = getState();
3171
- if (config.debug !== void 0) state.debug = config.debug;
3172
- if (config.handler !== void 0) state.handler = config.handler;
3173
- },
3174
- /**
3175
- * Enable/disable debug logging for a specific tag.
3176
- * Per-tag setting overrides the global debug flag.
3177
- *
3178
- * @example
3179
- * ```ts
3180
- * logger.setTagDebug('Nostr', true); // enable only Nostr logs
3181
- * logger.setTagDebug('Nostr', false); // disable Nostr logs even if global debug=true
3182
- * ```
3183
- */
3184
- setTagDebug(tag, enabled) {
3185
- getState().tags[tag] = enabled;
3186
- },
3187
- /**
3188
- * Clear per-tag override, falling back to global debug flag.
3189
- */
3190
- clearTagDebug(tag) {
3191
- delete getState().tags[tag];
3192
- },
3193
- /** Returns true if debug mode is enabled for the given tag (or globally). */
3194
- isDebugEnabled(tag) {
3195
- if (tag) return isEnabled(tag);
3196
- return getState().debug;
3197
- },
3198
- /**
3199
- * Debug-level log. Only shown when debug is enabled (globally or for this tag).
3200
- * Use for detailed operational information.
3201
- */
3202
- debug(tag, message, ...args) {
3203
- if (!isEnabled(tag)) return;
3204
- const state = getState();
3205
- if (state.handler) {
3206
- state.handler("debug", tag, message, ...args);
3207
- } else {
3208
- console.log(`[${tag}]`, message, ...args);
3209
- }
3210
- },
3211
- /**
3212
- * Warning-level log. ALWAYS shown regardless of debug flag.
3213
- * Use for important but non-critical issues (timeouts, retries, degraded state).
3214
- */
3215
- warn(tag, message, ...args) {
3216
- const state = getState();
3217
- if (state.handler) {
3218
- state.handler("warn", tag, message, ...args);
3219
- } else {
3220
- console.warn(`[${tag}]`, message, ...args);
3221
- }
3222
- },
3223
- /**
3224
- * Error-level log. ALWAYS shown regardless of debug flag.
3225
- * Use for critical failures that should never be silenced.
3226
- */
3227
- error(tag, message, ...args) {
3228
- const state = getState();
3229
- if (state.handler) {
3230
- state.handler("error", tag, message, ...args);
3231
- } else {
3232
- console.error(`[${tag}]`, message, ...args);
3233
- }
3234
- },
3235
- /** Reset all logger state (debug flag, tags, handler). Primarily for tests. */
3236
- reset() {
3237
- const g = globalThis;
3238
- delete g[LOGGER_KEY];
3239
- }
3240
- };
3241
-
3242
- // modules/payments-v2/ports.ts
3243
- function isRetryableAckError(err) {
3244
- return err !== null && typeof err === "object" && err.retryable === true;
3245
- }
3246
-
3247
3193
  // modules/payments-v2/receive/Receive.ts
3248
3194
  var ACK_BATCH_SIZE = 200;
3249
3195
  var REFRESH_INTERVAL_MS = 2500;
@@ -3292,22 +3238,24 @@ var Receive = class {
3292
3238
  * the tokens just accepted, and the balance would still only move at the end.
3293
3239
  * Ordering is preserved: store() still precedes the ack (§5.7).
3294
3240
  */
3295
- async maybeRefresh(deps, pending, epochOf) {
3241
+ async maybeRefresh(ctx) {
3242
+ const { deps, pending, pageEpoch } = ctx;
3296
3243
  if (deps.refreshView === void 0) return;
3297
3244
  const now = deps.now?.() ?? Date.now();
3298
3245
  if (now - this.lastRefreshAt < REFRESH_INTERVAL_MS) return;
3299
3246
  this.lastRefreshAt = now;
3300
- await flushAcks(deps, pending, epochOf);
3301
- deps.refreshView();
3247
+ if ((await flushAcks(deps, pending, pageEpoch)).progressed) deps.refreshView();
3302
3248
  }
3303
3249
  /** One listing pass: process each entry, flushing and refreshing as it goes. */
3304
3250
  async drainPages(ctx, basis) {
3305
- const { deps, engine, pending, stored, pageEpoch } = ctx;
3251
+ const { deps, pending, pageEpoch, claimable } = ctx;
3306
3252
  for await (const entry of deps.delivery.incoming(basis === null ? void 0 : String(basis.cursor))) {
3307
- const storedBefore = stored.length;
3308
- await this.processEntry(deps, engine, entry, pending, stored);
3309
- if (pending.length >= ACK_BATCH_SIZE) await flushAcks(deps, pending, pageEpoch);
3310
- if (stored.length > storedBefore) await this.maybeRefresh(deps, pending, pageEpoch);
3253
+ const claimableBefore = claimable.n;
3254
+ await this.processEntry(ctx, entry);
3255
+ if (pending.length >= ACK_BATCH_SIZE) {
3256
+ if (!(await flushAcks(deps, pending, pageEpoch)).progressed) return;
3257
+ }
3258
+ if (claimable.n > claimableBefore) await this.maybeRefresh(ctx);
3311
3259
  }
3312
3260
  await flushAcks(deps, pending, pageEpoch);
3313
3261
  }
@@ -3318,11 +3266,16 @@ var Receive = class {
3318
3266
  const stored = [];
3319
3267
  const pending = [];
3320
3268
  const pageEpoch = () => deps.delivery.incomingEpoch() ?? deps.syncEpoch();
3269
+ const claimable = { n: 0 };
3270
+ const finish = () => {
3271
+ if (claimable.n > 0) deps.refreshView?.();
3272
+ return stored;
3273
+ };
3321
3274
  try {
3322
3275
  const record = await deps.kv.get(STORE_KEYS.streamCursor("mailbox"));
3323
3276
  let basis = record !== null && record.syncEpoch === deps.syncEpoch() ? record : null;
3324
3277
  for (let pass = 0; pass < 2; pass++) {
3325
- await this.drainPages({ deps, engine, pending, stored, pageEpoch }, basis);
3278
+ await this.drainPages({ deps, engine, pending, stored, pageEpoch, claimable }, basis);
3326
3279
  const served = deps.delivery.incomingEpoch();
3327
3280
  if (basis === null || served === null || served === basis.syncEpoch) break;
3328
3281
  await deps.kv.remove(STORE_KEYS.streamCursor("mailbox"));
@@ -3330,22 +3283,25 @@ var Receive = class {
3330
3283
  }
3331
3284
  } catch (err) {
3332
3285
  logger.warn("PaymentsV2", "receive drain interrupted \u2014 unacked entries retry next drain:", err);
3333
- if (isRetryableAckError(err)) return stored;
3286
+ if (isRetryableAckError(err)) return finish();
3334
3287
  await flushAcks(deps, pending, pageEpoch).catch((flushErr) => {
3335
3288
  logger.warn("PaymentsV2", "receive ack flush failed \u2014 cursor holds at the acked prefix:", flushErr);
3289
+ return { progressed: false };
3336
3290
  });
3337
3291
  }
3338
- if (stored.length > 0) deps.refreshView?.();
3339
- return stored;
3292
+ return finish();
3340
3293
  }
3341
- async processEntry(deps, engine, entry, pending, stored) {
3294
+ async processEntry(ctx, entry) {
3295
+ const { deps, engine, pending, stored, claimable } = ctx;
3342
3296
  const screened = await screen(deps, engine, entry);
3343
3297
  if (screened.kind === "ack") {
3344
3298
  pending.push(screened.ack);
3299
+ if (screened.ack.disposition === "claimed") claimable.n += 1;
3345
3300
  return;
3346
3301
  }
3347
3302
  await deps.view.store(screened.record);
3348
3303
  pending.push(claimAck(entry));
3304
+ claimable.n += 1;
3349
3305
  const transfer = await announce(deps, entry, screened.record);
3350
3306
  stored.push(transfer);
3351
3307
  deps.emit("transfer:incoming", transfer);
@@ -3355,13 +3311,9 @@ async function screen(deps, engine, entry) {
3355
3311
  const blobBytes = await entry.fetchBlob();
3356
3312
  let token;
3357
3313
  try {
3358
- token = await engine.decodeToken({
3359
- v: TOKEN_BLOB_VERSION,
3360
- network: 0,
3361
- tokenId: "",
3362
- token: blobBytes
3363
- });
3364
- } catch {
3314
+ token = await engine.decodeToken({ tokenId: "", token: blobBytes });
3315
+ } catch (err) {
3316
+ logger.warn("PaymentsV2", `receive: undecodable blob rejected \u2014 ${String(err)}`);
3365
3317
  return { kind: "ack", ack: rejectAck(entry, "invalid") };
3366
3318
  }
3367
3319
  const verdict = await engine.verify(token);
@@ -3406,7 +3358,8 @@ async function announce(deps, entry, record) {
3406
3358
  };
3407
3359
  }
3408
3360
  async function flushAcks(deps, pending, epochOf) {
3409
- if (pending.length === 0) return;
3361
+ if (pending.length === 0) return { progressed: true };
3362
+ const before = pending.length;
3410
3363
  let lastAcked = null;
3411
3364
  try {
3412
3365
  const settled = await settleAcks(deps, pending);
@@ -3424,6 +3377,7 @@ async function flushAcks(deps, pending, epochOf) {
3424
3377
  await deps.kv.set(STORE_KEYS.streamCursor("mailbox"), record);
3425
3378
  }
3426
3379
  }
3380
+ return { progressed: pending.length < before };
3427
3381
  }
3428
3382
  async function settleAcks(deps, pending) {
3429
3383
  const batch = deps.delivery.ackBatch?.bind(deps.delivery);
@@ -4762,7 +4716,7 @@ var PaymentsFacade = class {
4762
4716
  if (bytes === void 0) {
4763
4717
  throw new SphereError(`Selected source ${tokenId} has no blob in storage`, "STORAGE_ERROR");
4764
4718
  }
4765
- const token = await engine.decodeToken({ v: TOKEN_BLOB_VERSION, network: 0, tokenId, token: bytes });
4719
+ const token = await engine.decodeToken({ tokenId, token: bytes });
4766
4720
  const keys = await engine.deliveryKeys(bytes);
4767
4721
  spentStates[tokenId] = { local: keys.stateHash, protocol: keys.stateHash };
4768
4722
  sources.set(tokenId, token);
@@ -5027,7 +4981,9 @@ var PaymentsFacade = class {
5027
4981
  PaymentsFacade,
5028
4982
  STORE_KEYS,
5029
4983
  createScopedKV,
5030
- supportsDeterministicMint
4984
+ isRetryableAckError,
4985
+ supportsDeterministicMint,
4986
+ sweepSupersededState
5031
4987
  });
5032
4988
  /*! Bundled license information:
5033
4989