@dvmkit/sdk 0.7.0-rc.9 → 0.8.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 (57) hide show
  1. package/NOTICE +1 -1
  2. package/README.md +57 -261
  3. package/dist/{chunk-5CSR33B5.js → chunk-2U6LAASN.js} +1 -1
  4. package/dist/chunk-66HGCPBU.js +25 -0
  5. package/dist/{chunk-QM2OS3NJ.js → chunk-7PM4R4GD.js} +1 -1
  6. package/dist/{chunk-YE53E4BT.js → chunk-AGE5XZKE.js} +1 -1
  7. package/dist/{chunk-RJFBBEWQ.js → chunk-ALWVJ2RB.js} +1 -1
  8. package/dist/{chunk-FYETJDBB.js → chunk-AVV5SYGO.js} +2 -2
  9. package/dist/{chunk-5PLQOC4B.js → chunk-BFGQG4WY.js} +9 -1
  10. package/dist/{chunk-IOKEKMIU.js → chunk-FM6QAGJC.js} +2 -2
  11. package/dist/{chunk-KXWROQGK.js → chunk-FUJ36YDV.js} +1 -24
  12. package/dist/{chunk-6JZDFYQL.js → chunk-G3MPHW5I.js} +1 -1
  13. package/dist/{chunk-2HAFZ5GC.js → chunk-IHQUBATH.js} +2 -2
  14. package/dist/{chunk-YS6PWVCZ.js → chunk-ILBSZMJL.js} +1 -1
  15. package/dist/{chunk-RGSWVNQG.js → chunk-IOQIXRGM.js} +2 -43
  16. package/dist/{chunk-YNHXOONR.js → chunk-J5J63WDC.js} +1 -1
  17. package/dist/{chunk-G7IXOVKV.js → chunk-JIZ4ZIXX.js} +331 -102
  18. package/dist/{chunk-ZLWPEIE2.js → chunk-NA2KOR6G.js} +1 -1
  19. package/dist/{chunk-2DE32RAW.js → chunk-NU5RWJ5B.js} +1 -1
  20. package/dist/chunk-OP7VCGQR.js +47 -0
  21. package/dist/{chunk-QN3CQOE2.js → chunk-QKE5NDPF.js} +368 -7
  22. package/dist/{chunk-7RZEJJTN.js → chunk-RSNC5T6C.js} +2 -2
  23. package/dist/{chunk-2GTLF74N.js → chunk-UDJNZ3UG.js} +1 -1
  24. package/dist/{chunk-WGK5KZ6S.js → chunk-UVS7MRJX.js} +3 -3
  25. package/dist/{chunk-HU6ZMQDN.js → chunk-UWGBI5WK.js} +58 -1
  26. package/dist/{chunk-OFSOLHRX.js → chunk-WMGXJQI3.js} +1 -1
  27. package/dist/{chunk-5TIFEMHJ.js → chunk-ZEPJF4JC.js} +2 -2
  28. package/dist/{content-retention-U7dJM7Ph.d.ts → content-retention-B7ddtJ2y.d.ts} +1 -1
  29. package/dist/{credit-ledger-F2LWQU6N.js → credit-ledger-KIQIE6I6.js} +3 -3
  30. package/dist/{credit-menu-CUJdCfpt.d.ts → credit-menu-BH3g9GQa.d.ts} +5 -5
  31. package/dist/{fx-BvG2Wnjk.d.ts → fx-DN26_J7o.d.ts} +1 -1
  32. package/dist/index.d.ts +5 -5
  33. package/dist/index.js +4 -4
  34. package/dist/internal/caller.d.ts +10 -8
  35. package/dist/internal/caller.js +12 -9
  36. package/dist/internal/server.d.ts +7 -7
  37. package/dist/internal/server.js +22 -20
  38. package/dist/{job-store-DjgN2AOk.d.ts → job-store-Cq21JT37.d.ts} +1 -1
  39. package/dist/{lightning-backend-DeasHNOP.d.ts → lightning-backend-S8F8nf8q.d.ts} +1 -1
  40. package/dist/{memory-credit-ledger-XOOWJTBZ.js → memory-credit-ledger-ATYFAYBG.js} +4 -4
  41. package/dist/{mpp-setup-KGX6PLAF.js → mpp-setup-ZTORW3VF.js} +4 -2
  42. package/dist/{payout-reporter-W3CCLYCN.js → payout-reporter-NN6K2IVQ.js} +2 -2
  43. package/dist/{postgres-consumed-credential-store-LUJ5CUJS.js → postgres-consumed-credential-store-XJTE5PCA.js} +1 -1
  44. package/dist/{postgres-job-store-IX7IUXF4.js → postgres-job-store-AR6ZJUQV.js} +2 -2
  45. package/dist/{postgres-replay-store-Q6MEQDWZ.js → postgres-replay-store-33K33QV7.js} +2 -2
  46. package/dist/{pricing-ZUEFO3CM.js → pricing-G5IN5YJE.js} +3 -3
  47. package/dist/{revenue-reporter-NRS2FANA.js → revenue-reporter-KDUZLD5F.js} +2 -2
  48. package/dist/server/index.d.ts +10 -10
  49. package/dist/server/index.js +30 -28
  50. package/dist/{step-cache-C9JRSFhM.d.ts → step-cache-CR12EZ1Q.d.ts} +136 -4
  51. package/dist/{tempo-charge-store-NZJTJCUO.js → tempo-charge-store-XEGJYM3G.js} +2 -2
  52. package/dist/{tempo-session-store-ENFDLDKC.js → tempo-session-store-3WTDOO7H.js} +3 -3
  53. package/dist/testing/index.d.ts +3 -3
  54. package/dist/testing/index.js +8 -6
  55. package/dist/{usd-DXDkHn_8.d.ts → usd-s_VZ_eS7.d.ts} +1 -1
  56. package/dist/{x402-T7WVKDD4.js → x402-HQ5GRQZU.js} +6 -5
  57. package/package.json +18 -3
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  PostgresReplayStore
3
- } from "../chunk-RJFBBEWQ.js";
3
+ } from "../chunk-ALWVJ2RB.js";
4
4
  import {
5
5
  PostgresKVStore
6
6
  } from "../chunk-V5ZRATJH.js";
@@ -18,7 +18,7 @@ import {
18
18
  parseNwcUri,
19
19
  validateX402Env,
20
20
  withNwcPool
21
- } from "../chunk-7RZEJJTN.js";
21
+ } from "../chunk-RSNC5T6C.js";
22
22
  import {
23
23
  MemoryKVStore
24
24
  } from "../chunk-SDK6KDJN.js";
@@ -80,32 +80,32 @@ import {
80
80
  stripProtocolEnvelope,
81
81
  toCreditView,
82
82
  unknownRouteNotFound
83
- } from "../chunk-G7IXOVKV.js";
83
+ } from "../chunk-JIZ4ZIXX.js";
84
84
  import {
85
85
  TEMPO_MODERATO_CHAIN_ID,
86
86
  TEMPO_MODERATO_RPC,
87
87
  TEMPO_SETTLEMENT_DEFAULT_LOW_BALANCE_MICRO,
88
88
  TempoSettlementReadiness,
89
89
  resolveTempoNetwork
90
- } from "../chunk-QN3CQOE2.js";
91
- import "../chunk-YNHXOONR.js";
92
- import "../chunk-FYETJDBB.js";
90
+ } from "../chunk-QKE5NDPF.js";
91
+ import "../chunk-J5J63WDC.js";
92
+ import "../chunk-AVV5SYGO.js";
93
93
  import {
94
94
  MemoryCreditLedger
95
- } from "../chunk-YE53E4BT.js";
95
+ } from "../chunk-AGE5XZKE.js";
96
96
  import {
97
97
  PostgresJobStore
98
- } from "../chunk-6JZDFYQL.js";
98
+ } from "../chunk-G3MPHW5I.js";
99
99
  import "../chunk-YG7G4DPZ.js";
100
100
  import {
101
101
  SignedRequestError,
102
102
  createDefaultReplayStore,
103
103
  createSignedRequestVerifier,
104
104
  signedRequestInput
105
- } from "../chunk-YS6PWVCZ.js";
105
+ } from "../chunk-ILBSZMJL.js";
106
106
  import {
107
107
  isStreamableJobStore
108
- } from "../chunk-2HAFZ5GC.js";
108
+ } from "../chunk-IHQUBATH.js";
109
109
  import {
110
110
  ContentHoldError,
111
111
  baselineContentExpiry,
@@ -116,7 +116,7 @@ import {
116
116
  IMPLICIT_CREDIT_TTL_MS,
117
117
  generateEphemeralReceiptKey,
118
118
  receiptPubkeyFromSecret
119
- } from "../chunk-5TIFEMHJ.js";
119
+ } from "../chunk-ZEPJF4JC.js";
120
120
  import {
121
121
  X402_DEFAULT_FACILITATOR,
122
122
  X402_DEFAULT_NETWORK,
@@ -128,13 +128,15 @@ import {
128
128
  SIGNED_REQUEST_STATEMENT_VERSION,
129
129
  signedRequestStatementHeader
130
130
  } from "../chunk-UKD3R2KU.js";
131
+ import "../chunk-OP7VCGQR.js";
131
132
  import {
132
133
  initLoggers
133
- } from "../chunk-RGSWVNQG.js";
134
- import "../chunk-KXWROQGK.js";
134
+ } from "../chunk-IOQIXRGM.js";
135
+ import "../chunk-FUJ36YDV.js";
136
+ import "../chunk-66HGCPBU.js";
135
137
  import "../chunk-BQJIFRAZ.js";
136
- import "../chunk-2GTLF74N.js";
137
- import "../chunk-5CSR33B5.js";
138
+ import "../chunk-UDJNZ3UG.js";
139
+ import "../chunk-2U6LAASN.js";
138
140
  import {
139
141
  CreditLedger,
140
142
  CreditLedgerError,
@@ -142,16 +144,16 @@ import {
142
144
  PostgresX402ChannelStorage,
143
145
  X402RelaySubmissionLockError,
144
146
  allocateDrawValue
145
- } from "../chunk-IOKEKMIU.js";
147
+ } from "../chunk-FM6QAGJC.js";
146
148
  import {
147
149
  applyRetryToPool
148
- } from "../chunk-QM2OS3NJ.js";
150
+ } from "../chunk-7PM4R4GD.js";
149
151
  import {
150
152
  assertSupportedX402Network
151
153
  } from "../chunk-BPYMEMQX.js";
152
154
  import {
153
155
  diagnosticConsole
154
- } from "../chunk-5PLQOC4B.js";
156
+ } from "../chunk-BFGQG4WY.js";
155
157
  import {
156
158
  MemoryProcessedPaymentStore,
157
159
  PostgresProcessedPaymentStore,
@@ -1147,7 +1149,7 @@ function createDVMHost(opts = {}) {
1147
1149
  });
1148
1150
  applyRetryToPool(pool, "dvm-host");
1149
1151
  pgPool = pool;
1150
- const { PostgresJobStore: PostgresJobStore2 } = await import("../postgres-job-store-IX7IUXF4.js");
1152
+ const { PostgresJobStore: PostgresJobStore2 } = await import("../postgres-job-store-AR6ZJUQV.js");
1151
1153
  const pgJobStore = new PostgresJobStore2(pool);
1152
1154
  pendingInits.push(pgJobStore.init(), pgJobStore.initStreaming());
1153
1155
  jobStore = pgJobStore;
@@ -1240,11 +1242,11 @@ ${config.facilitatorAuth?.keyId ?? ""}`;
1240
1242
  let tempoChargeBackend = "user-supplied";
1241
1243
  const mppTempoRecipient = envMaybe.DVMKIT_TEMPO_RECIPIENT;
1242
1244
  if (!mpp && mppTempoRecipient) {
1243
- const { createMppFromOpts, createDualKeyMppxFromOpts, parseMppMethodsAllowlist } = await import("../mpp-setup-KGX6PLAF.js");
1245
+ const { createMppFromOpts, createDualKeyMppxFromOpts, parseMppMethodsAllowlist } = await import("../mpp-setup-ZTORW3VF.js");
1244
1246
  tempoChargeBackend = pgPool ? "postgres" : "memory";
1245
1247
  let tempoCharge;
1246
1248
  if (pgPool) {
1247
- const { PostgresTempoChargeStore } = await import("../tempo-charge-store-NZJTJCUO.js");
1249
+ const { PostgresTempoChargeStore } = await import("../tempo-charge-store-XEGJYM3G.js");
1248
1250
  const chargeStore = new PostgresTempoChargeStore(pgPool);
1249
1251
  tempoChargeStore = chargeStore;
1250
1252
  pendingInits.push(chargeStore.init());
@@ -1264,7 +1266,7 @@ ${config.facilitatorAuth?.keyId ?? ""}`;
1264
1266
  { createPublicClient, createWalletClient, erc20Abi, http },
1265
1267
  { tempo: tempoMainnet, tempoModerato }
1266
1268
  ] = await Promise.all([
1267
- import("../tempo-session-store-ENFDLDKC.js"),
1269
+ import("../tempo-session-store-3WTDOO7H.js"),
1268
1270
  import("viem/accounts"),
1269
1271
  import("viem"),
1270
1272
  import("viem/chains")
@@ -1417,7 +1419,7 @@ ${config.facilitatorAuth?.keyId ?? ""}`;
1417
1419
  }
1418
1420
  }
1419
1421
  const fxSource = envMaybe.DVMKIT_FX_SOURCE;
1420
- const { createFxFetcher, resolveFxSourceFromEnv, warmFxSnapshot } = await import("../pricing-ZUEFO3CM.js");
1422
+ const { createFxFetcher, resolveFxSourceFromEnv, warmFxSnapshot } = await import("../pricing-G5IN5YJE.js");
1421
1423
  const fxFetcher = opts.fx ?? createFxFetcher({ source: resolveFxSourceFromEnv(envMaybe) });
1422
1424
  const hostRailConfigured = (opts.paymentMethods?.length ?? 0) > 0 || (effectiveMints?.length ?? 0) > 0 || !!x402WithDualServe || !!mpp;
1423
1425
  if (mounts.some((entry) => mountNeedsFx(entry, hostRailConfigured))) warmFxSnapshot(fxFetcher);
@@ -1427,7 +1429,7 @@ ${config.facilitatorAuth?.keyId ?? ""}`;
1427
1429
  assertReceiptIdentity(envMaybe, opts.builder, receiptKey, cashuOpts.dvmId, opts.devMode);
1428
1430
  let sharedPgReplayStore;
1429
1431
  if (pgPool) {
1430
- const { PostgresReplayStore: PostgresReplayStore2 } = await import("../postgres-replay-store-Q6MEQDWZ.js");
1432
+ const { PostgresReplayStore: PostgresReplayStore2 } = await import("../postgres-replay-store-33K33QV7.js");
1431
1433
  const store2 = new PostgresReplayStore2(pgPool);
1432
1434
  pendingInits.push(store2.init());
1433
1435
  sharedPgReplayStore = store2;
@@ -1455,13 +1457,13 @@ ${config.facilitatorAuth?.keyId ?? ""}`;
1455
1457
  }
1456
1458
  let sharedPgConsumedStore;
1457
1459
  if (pgPool) {
1458
- const { PostgresConsumedCredentialStore } = await import("../postgres-consumed-credential-store-LUJ5CUJS.js");
1460
+ const { PostgresConsumedCredentialStore } = await import("../postgres-consumed-credential-store-XJTE5PCA.js");
1459
1461
  const consumedStore = new PostgresConsumedCredentialStore(pgPool);
1460
1462
  pendingInits.push(consumedStore.init());
1461
1463
  sharedPgConsumedStore = consumedStore;
1462
1464
  }
1463
1465
  if (pgPool) {
1464
- const { CreditLedger: CreditLedger2 } = await import("../credit-ledger-F2LWQU6N.js");
1466
+ const { CreditLedger: CreditLedger2 } = await import("../credit-ledger-KIQIE6I6.js");
1465
1467
  const pgLedger = new CreditLedger2(pgPool, tempoSessionStore);
1466
1468
  pendingInits.push(pgLedger.init());
1467
1469
  creditLedger = pgLedger;
@@ -1470,7 +1472,7 @@ ${config.facilitatorAuth?.keyId ?? ""}`;
1470
1472
  pendingInits.push(pgProcessed.init());
1471
1473
  processedPayments = pgProcessed;
1472
1474
  } else {
1473
- const { MemoryCreditLedger: MemoryCreditLedger2 } = await import("../memory-credit-ledger-XOOWJTBZ.js");
1475
+ const { MemoryCreditLedger: MemoryCreditLedger2 } = await import("../memory-credit-ledger-ATYFAYBG.js");
1474
1476
  creditLedger = disposableCashu?.ledger ?? new MemoryCreditLedger2();
1475
1477
  const { MemoryProcessedPaymentStore: MemoryProcessedPaymentStore2 } = await import("../processed-payment-store-GKMAWOM3.js");
1476
1478
  processedPayments = new MemoryProcessedPaymentStore2();
@@ -1971,7 +1973,7 @@ function logBootSummary(s) {
1971
1973
  diagnosticConsole.log(` Database: ${s.databaseConnected ? "connected" : "(not configured)"}`);
1972
1974
  diagnosticConsole.log(` Mints: ${s.mints && s.mints.length > 0 ? s.mints.join(", ") : "(none)"}`);
1973
1975
  diagnosticConsole.log(` Cashu mode: ${s.cashuOpts.cashuMode ?? "(disabled)"}`);
1974
- diagnosticConsole.log(` Tempo: ${s.mpp ? `realm=${s.mpp.realm}` : "(unconfigured)"}`);
1976
+ diagnosticConsole.log(` Tempo: ${s.mpp ? `realm=${s.mpp.realm ?? "(unset)"}` : "(unconfigured)"}`);
1975
1977
  if (s.mpp) {
1976
1978
  const rotState = !s.mppSecretState ? "single-key (no DB-backed rotation)" : s.mppSecretState.previous ? `dual-key (previous expires ${new Date(s.mppSecretState.previous.expiresAtMs).toISOString()})` : "active-only";
1977
1979
  diagnosticConsole.log(` Tempo secret: ${rotState}`);
@@ -1227,7 +1227,51 @@ declare class HostedSettlementReportObligations {
1227
1227
  };
1228
1228
  }): Promise<HostedEffectReservation | null>;
1229
1229
  reserveTempo(channelId: string, operation: "settle" | "close", drainId?: string): Promise<HostedEffectReservation>;
1230
+ /**
1231
+ * Retire a close reservation that never recorded a transaction and reserve
1232
+ * the drain's next attempt, in one transaction, so the drain always keeps one
1233
+ * outstanding close obligation. A close from the retired attempt that lands
1234
+ * late is a close of the same channel: `recordSubmitted` on the retired row
1235
+ * writes it onto the successor, and recovery attaches it there if that
1236
+ * attempt never got to write, so it is reported once.
1237
+ *
1238
+ * The caller has just read the channel open on chain. The age bound only
1239
+ * spares a reservation young enough to be inside its first receipt wait; an
1240
+ * attempt slowed past it by a degraded RPC can still be running.
1241
+ */
1242
+ releaseStaleTempoClose(id: string, channelId: string, drainId: string, limits: {
1243
+ staleAfterMs: number;
1244
+ maxReleases: number;
1245
+ }): Promise<{
1246
+ outcome: "reserved";
1247
+ id: string;
1248
+ releases: number;
1249
+ } | {
1250
+ outcome: "in_flight";
1251
+ } | {
1252
+ outcome: "exhausted";
1253
+ releases: number;
1254
+ }>;
1255
+ /**
1256
+ * Resolve an unsubmitted close reservation whose channel the payer exited
1257
+ * on its own: no cooperative close of ours can land on a finalized channel.
1258
+ */
1259
+ resolveTempoCloseExit(id: string): Promise<boolean>;
1260
+ private reserveTempoIn;
1230
1261
  findPendingTempo(channelId: string, operation: "settle" | "close"): Promise<ObligationRow | undefined>;
1262
+ /** The original close obligation reserved for this drain, while its report is outstanding. */
1263
+ pendingTempoClose(channelId: string, drainId: string): Promise<{
1264
+ id: string;
1265
+ txHash: string | null;
1266
+ reservedAtMs: number;
1267
+ searchBefore: bigint | null;
1268
+ } | undefined>;
1269
+ /**
1270
+ * Where the next search for this close obligation's transaction resumes. It
1271
+ * lives on the obligation, not the drain's close intent, because releasing
1272
+ * the drain deletes the intent while the obligation still needs the search.
1273
+ */
1274
+ recordTempoCloseSearch(id: string, resumeAt: bigint): Promise<void>;
1231
1275
  submittedIds(rail: Rail, operation: Operation, txHash: string, batchId?: string): Promise<string[]>;
1232
1276
  refundClaimDelta(txHash: string, channelId: string): Promise<bigint>;
1233
1277
  assertReservedTempoClose(id: string, channelId: string): Promise<void>;
@@ -1236,6 +1280,26 @@ declare class HostedSettlementReportObligations {
1236
1280
  reserveOpenX402Settlement(): Promise<HostedEffectReservation>;
1237
1281
  private ensureOpenX402Batch;
1238
1282
  recordSubmitted(id: string, txHash: string): Promise<void>;
1283
+ /**
1284
+ * Close reservations that never recorded a transaction, oldest first. Each
1285
+ * one owes a payout report only if its close lands, so it stays unresolved
1286
+ * until a reconcile reads how its channel finalized.
1287
+ */
1288
+ unsubmittedTempoCloses(limit?: number): Promise<Array<{
1289
+ id: string;
1290
+ channelId: string;
1291
+ drainId: string;
1292
+ reservedAtMs: number;
1293
+ searchBefore: bigint | null;
1294
+ }>>;
1295
+ /**
1296
+ * A retired close reservation's attempt can still be running when its
1297
+ * successor is reserved, and its close can land. The close is the same
1298
+ * channel's, so it belongs to the drain's outstanding obligation; writing it
1299
+ * onto the retired row would leave that obligation without a transaction and
1300
+ * the payout unreported.
1301
+ */
1302
+ private successorOfRetiredClose;
1239
1303
  recoveryCandidates(): Promise<HostedRecoverableEffect[]>;
1240
1304
  recoverOriginalX402Refunds(): Promise<Array<{
1241
1305
  id: string;
@@ -4418,6 +4482,18 @@ declare class PostgresTempoSessionStore implements Store.AtomicStore {
4418
4482
  getClose(channelId: string): Promise<TempoSessionCloseRecord | null>;
4419
4483
  /** Persist proof that a cooperative close reached terminal chain state. */
4420
4484
  confirmClose(channelId: string, drainId: string, reference: string): Promise<TempoSessionCloseRecord>;
4485
+ /** Set a close's reference only if none is set, reporting whether this call set it. */
4486
+ claimCloseReference(channelId: string, drainId: string, reference: string): Promise<{
4487
+ reference: string | null;
4488
+ claimed: boolean;
4489
+ }>;
4490
+ getCloseRecovery(channelId: string): Promise<{
4491
+ updatedAtMs: number;
4492
+ searchBefore: bigint | null;
4493
+ settledBeforeClose: bigint | null;
4494
+ } | null>;
4495
+ /** Record where a paused close search resumes; the cursor only moves back. */
4496
+ recordCloseSearch(channelId: string, drainId: string, resumeAt: bigint): Promise<void>;
4421
4497
  private runCloseIntentTransaction;
4422
4498
  private transaction;
4423
4499
  private writeCloseIntent;
@@ -4519,7 +4595,8 @@ interface MppOpts {
4519
4595
  * of ours can reach the un-dual-keyed door — see `createDualKeyMppxFromOpts`.
4520
4596
  */
4521
4597
  interface MppxServer {
4522
- realm: string;
4598
+ /** Undefined when neither `Mppx.create` nor mppx's environment lookup names a realm. */
4599
+ realm?: string;
4523
4600
  methods: readonly Method.AnyServer[];
4524
4601
  /** Public, non-secret Tempo bindings resolved from the exact live method configuration. */
4525
4602
  tempoConfiguration?: {
@@ -4531,9 +4608,9 @@ interface MppxServer {
4531
4608
  };
4532
4609
  challenge: any;
4533
4610
  /**
4534
- * Re-validate and broadcast a credential, returning a receipt. mppx 0.8.x
4535
- * also exposes a non-mutating `validateCredential`; accepting payment is
4536
- * always the mutating path, so this is the only one the SDK binds.
4611
+ * Re-validate and broadcast a credential, returning a receipt. Accepting
4612
+ * payment is always this mutating path; `validateCredential` below is only
4613
+ * the hosted close's preflight.
4537
4614
  */
4538
4615
  broadcastCredential(credential: Credential.Credential | string, options?: any): Promise<Receipt.Receipt>;
4539
4616
  /** Non-mutating mppx HMAC, route, expiry and method preflight. */
@@ -4559,6 +4636,13 @@ interface MppxServer {
4559
4636
  settled: number;
4560
4637
  inFlight: number;
4561
4638
  }>;
4639
+ /**
4640
+ * Bring hosted close obligations whose channel has finalized to what the
4641
+ * chain shows, without settling anything. The sweep runs it too; the hosting
4642
+ * closure runs it alone before it decides, since those obligations block
4643
+ * the closure certificate.
4644
+ */
4645
+ reconcileTempoSessionCloses?: () => Promise<void>;
4562
4646
  /**
4563
4647
  * Reconcile and, if the channel is at risk, settle exactly one TIP-1034
4564
4648
  * channel. The forced-close protection path: a verified on-chain
@@ -4605,6 +4689,21 @@ interface MppxServer {
4605
4689
  getTempoSessionCloseIntent?: (channelId: string) => Promise<TempoSessionCloseRecord | null>;
4606
4690
  /** Read terminally consumed value for an exact cooperative-close challenge. */
4607
4691
  getTempoSessionSpent?: (channelId: string) => Promise<bigint>;
4692
+ /**
4693
+ * Refuse a cooperative close voucher that mppx's close would refuse before
4694
+ * submitting, using only the stored channel: no chain read and no write.
4695
+ * A hosted close runs it before reserving its settlement-report obligation,
4696
+ * so a voucher that could never broadcast does not leave a reservation behind.
4697
+ */
4698
+ assertTempoSessionCloseVoucher?: (voucher: {
4699
+ channelId: string;
4700
+ cumulativeAmount: bigint;
4701
+ signature: string;
4702
+ /** The credential's TIP-1034 channel descriptor, unchecked. */
4703
+ descriptor: unknown;
4704
+ /** The HMAC-verified challenge request the credential answers. */
4705
+ request: Record<string, unknown>;
4706
+ }) => Promise<void>;
4608
4707
  /**
4609
4708
  * Read the immutable chain binding of a stored channel, or `null`
4610
4709
  * when this DVM holds no such channel. What a close event must match before
@@ -4737,7 +4836,40 @@ interface TempoSessionChainOps {
4737
4836
  onSessionSettlement?: NonNullable<MppOpts["tempoSession"]>["onSessionSettlement"];
4738
4837
  }): Promise<Hex>;
4739
4838
  readChannelClose(client: Client, channelId: Hex, txHash: Hex): Promise<TempoChannelCloseAmounts>;
4839
+ /**
4840
+ * Search back for how this channel finalized: the newest `ChannelClosed`,
4841
+ * `CloseRequested` or `CloseRequestCancelled` log, from `startBlock` (the
4842
+ * chain head when omitted) down to blocks older than `notBeforeMs`. One call searches a bounded number of
4843
+ * windows; `paused` names the block the next call resumes from.
4844
+ */
4845
+ findChannelClose(client: Client, channelId: Hex, escrowContract: `0x${string}`, notBeforeMs: number, startBlock?: bigint): Promise<TempoChannelCloseSearch>;
4846
+ }
4847
+ type TempoChannelCloseSearch =
4848
+ /** A `ChannelClosed` log, with the address that sent its transaction. */
4849
+ {
4850
+ outcome: "closed";
4851
+ txHash: Hex;
4852
+ sender: `0x${string}`;
4853
+ }
4854
+ /**
4855
+ * The payer's `requestClose` is newer than any `ChannelClosed` and was not
4856
+ * cancelled: a timed exit.
4857
+ */
4858
+ | {
4859
+ outcome: "exit_requested";
4740
4860
  }
4861
+ /**
4862
+ * Nothing read shows what finalized the channel; a later search resumes at
4863
+ * `stoppedAt`, which never leads below the reservation's time bound. Without
4864
+ * it the range may still hold the answer, and a later search starts over.
4865
+ */
4866
+ | {
4867
+ outcome: "none";
4868
+ stoppedAt?: bigint;
4869
+ } | {
4870
+ outcome: "paused";
4871
+ resumeAt: bigint;
4872
+ };
4741
4873
  declare function attachTempoSessionRuntime(mppx: MppxServer, config: MppOpts["tempoSession"], chainOpOverrides?: Partial<TempoSessionChainOps>): MppxServer;
4742
4874
  /** Test-only seams for deterministic watcher coverage without a live Tempo RPC. */
4743
4875
  declare const _testing: {
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  PostgresTempoChargeStore
3
- } from "./chunk-ZLWPEIE2.js";
3
+ } from "./chunk-NA2KOR6G.js";
4
4
  import "./chunk-YG7G4DPZ.js";
5
- import "./chunk-5PLQOC4B.js";
5
+ import "./chunk-BFGQG4WY.js";
6
6
  import "./chunk-COYKJRMM.js";
7
7
  export {
8
8
  PostgresTempoChargeStore
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  PostgresTempoSessionStore,
3
3
  assertMonotonicTransition
4
- } from "./chunk-HU6ZMQDN.js";
4
+ } from "./chunk-UWGBI5WK.js";
5
5
  import "./chunk-YG7G4DPZ.js";
6
- import "./chunk-QM2OS3NJ.js";
7
- import "./chunk-5PLQOC4B.js";
6
+ import "./chunk-7PM4R4GD.js";
7
+ import "./chunk-BFGQG4WY.js";
8
8
  import "./chunk-COYKJRMM.js";
9
9
  export {
10
10
  PostgresTempoSessionStore,
@@ -1,6 +1,6 @@
1
- import { C as ContentHoldHistory, a as ContentHoldMutation } from '../content-retention-U7dJM7Ph.js';
2
- import { a0 as JobReceipt, a5 as Message, a1 as MessageType, K as KVStore, L as Logger, v as ResponseContent, P as PaymentContent, S as SDKJobContext } from '../step-cache-C9JRSFhM.js';
3
- import { c as StreamableJobStore, R as ReceiptIssuingStore, J as JobRecord, d as RequestIdClaim, e as RequestIdClaimResult, f as JobRetentionCursor, O as OutgoingMessage, A as AppendOutgoingOptions, P as PaymentCreditDelta, V as VerifyAndCreditResult, g as JobCounters } from '../job-store-DjgN2AOk.js';
1
+ import { C as ContentHoldHistory, a as ContentHoldMutation } from '../content-retention-B7ddtJ2y.js';
2
+ import { a0 as JobReceipt, a5 as Message, a1 as MessageType, K as KVStore, L as Logger, v as ResponseContent, P as PaymentContent, S as SDKJobContext } from '../step-cache-CR12EZ1Q.js';
3
+ import { c as StreamableJobStore, R as ReceiptIssuingStore, J as JobRecord, d as RequestIdClaim, e as RequestIdClaimResult, f as JobRetentionCursor, O as OutgoingMessage, A as AppendOutgoingOptions, P as PaymentCreditDelta, V as VerifyAndCreditResult, g as JobCounters } from '../job-store-Cq21JT37.js';
4
4
  import 'hono';
5
5
  import 'mppx';
6
6
  import '@x402/core/server';
@@ -4,20 +4,22 @@ import {
4
4
  import {
5
5
  MemoryJobStore,
6
6
  createInstrumentedFetch
7
- } from "../chunk-2HAFZ5GC.js";
7
+ } from "../chunk-IHQUBATH.js";
8
8
  import {
9
9
  JobCancelledError
10
10
  } from "../chunk-AFV77S4C.js";
11
11
  import {
12
12
  createNoopLogger
13
- } from "../chunk-RGSWVNQG.js";
14
- import "../chunk-KXWROQGK.js";
13
+ } from "../chunk-OP7VCGQR.js";
14
+ import "../chunk-IOQIXRGM.js";
15
+ import "../chunk-FUJ36YDV.js";
16
+ import "../chunk-66HGCPBU.js";
15
17
  import "../chunk-BQJIFRAZ.js";
16
- import "../chunk-2GTLF74N.js";
18
+ import "../chunk-UDJNZ3UG.js";
17
19
  import {
18
20
  validateCurrency
19
- } from "../chunk-5CSR33B5.js";
20
- import "../chunk-5PLQOC4B.js";
21
+ } from "../chunk-2U6LAASN.js";
22
+ import "../chunk-BFGQG4WY.js";
21
23
 
22
24
  // src/sdk/testing/test-context.ts
23
25
  function createTestContext(opts) {
@@ -1,4 +1,4 @@
1
- import { C as Currency } from './step-cache-C9JRSFhM.js';
1
+ import { C as Currency } from './step-cache-CR12EZ1Q.js';
2
2
 
3
3
  /**
4
4
  * Thrown by `fiatToSatsCeil` / `satsToFiat` when the supplied `ratePerBtc` is
@@ -3,11 +3,11 @@ import {
3
3
  generateX402PrivateKey,
4
4
  getX402Balance,
5
5
  resolveX402Asset
6
- } from "./chunk-OFSOLHRX.js";
6
+ } from "./chunk-WMGXJQI3.js";
7
7
  import {
8
8
  verifyX402Payment
9
- } from "./chunk-WGK5KZ6S.js";
10
- import "./chunk-FYETJDBB.js";
9
+ } from "./chunk-UVS7MRJX.js";
10
+ import "./chunk-AVV5SYGO.js";
11
11
  import {
12
12
  X402_DEFAULT_FACILITATOR,
13
13
  X402_DEFAULT_NETWORK,
@@ -27,7 +27,8 @@ import {
27
27
  usdcContractByCaip2,
28
28
  x402NetworkToCaip2
29
29
  } from "./chunk-62FI3NJF.js";
30
- import "./chunk-KXWROQGK.js";
30
+ import "./chunk-FUJ36YDV.js";
31
+ import "./chunk-66HGCPBU.js";
31
32
  import {
32
33
  X402_NETWORKS,
33
34
  assertSupportedX402Network,
@@ -36,7 +37,7 @@ import {
36
37
  x402NetworkListForCopy,
37
38
  x402SupportedNetworksHint
38
39
  } from "./chunk-BPYMEMQX.js";
39
- import "./chunk-5PLQOC4B.js";
40
+ import "./chunk-BFGQG4WY.js";
40
41
  export {
41
42
  X402_DEFAULT_FACILITATOR,
42
43
  X402_DEFAULT_NETWORK,
package/package.json CHANGED
@@ -1,7 +1,20 @@
1
1
  {
2
2
  "name": "@dvmkit/sdk",
3
- "version": "0.7.0-rc.9",
4
- "description": "SDK for building accountless, pay-per-use Digital Vending Machines",
3
+ "version": "0.8.1",
4
+ "description": "SDK for building Digital Vending Machines: pay-per-use HTTPS services AI agents can find, pay, and call with no account or API key",
5
+ "author": "DVM Technologies Ltd",
6
+ "keywords": [
7
+ "dvm",
8
+ "digital-vending-machine",
9
+ "ai-agents",
10
+ "agent-payments",
11
+ "pay-per-use",
12
+ "x402",
13
+ "cashu",
14
+ "lightning",
15
+ "mpp",
16
+ "hono"
17
+ ],
5
18
  "license": "Apache-2.0",
6
19
  "repository": {
7
20
  "type": "git",
@@ -44,6 +57,7 @@
44
57
  },
45
58
  "scripts": {
46
59
  "build": "NODE_OPTIONS=--max-old-space-size=6144 tsup --config tsup.config.ts && node scripts/write-internal-entry.mjs && node scripts/prune-sdk-dist.mjs",
60
+ "check:readme-quickstart": "node scripts/check-readme-quickstart.mjs",
47
61
  "check:api": "node scripts/check-api-surface.mjs && node scripts/generate-api-reference.mjs --check",
48
62
  "check:consumer": "node scripts/consumer-smoke.mjs",
49
63
  "install-published-release": "node scripts/install-published-release.mjs",
@@ -57,7 +71,8 @@
57
71
  "docs:api": "node scripts/generate-api-reference.mjs --write",
58
72
  "release:tag": "node scripts/release-tag.mjs",
59
73
  "test": "vitest run --config vitest.config.ts",
60
- "test:examples": "node --test examples/quickstart/handler.test.mjs examples/authenticated-route/handler.test.mjs examples/payments-and-lifecycle/handler.test.mjs",
74
+ "test:examples": "node --test examples/quickstart/handler.test.ts examples/authenticated-route/handler.test.ts examples/payments-and-lifecycle/handler.test.ts",
75
+ "test:server": "vitest run --config vitest.server.config.ts",
61
76
  "test:db": "vitest run --config vitest.db.config.ts",
62
77
  "typecheck": "tsc --noEmit",
63
78
  "typecheck:scripts": "tsc --noEmit --project tsconfig.scripts.json",