@dvmkit/sdk 0.1.4-rc.7 → 0.1.5-rc.8

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 (31) hide show
  1. package/README.md +10 -2
  2. package/dist/{chunk-ANFX5HEG.js → chunk-2UUXIIOC.js} +43 -13
  3. package/dist/{chunk-C6JHBLMW.js → chunk-BIP6G74V.js} +1 -1
  4. package/dist/{chunk-EDDYHZ6W.js → chunk-CEOAHV2I.js} +0 -30
  5. package/dist/{chunk-TSWKITGR.js → chunk-CGKZDODG.js} +8 -1
  6. package/dist/{chunk-DBCLBYHP.js → chunk-KVEHHC7W.js} +11 -1
  7. package/dist/{chunk-VRQDX5P4.js → chunk-KXCKFIJI.js} +30 -0
  8. package/dist/{chunk-5GFED3GJ.js → chunk-M7LHFJ5K.js} +49 -6
  9. package/dist/{chunk-7AKBC4PW.js → chunk-TQWGQCNV.js} +1 -1
  10. package/dist/{chunk-QK3VJNCK.js → chunk-UB5FZ43T.js} +339 -212
  11. package/dist/{credit-menu-C1ezIFlJ.d.ts → credit-menu-s5HmGCqx.d.ts} +64 -21
  12. package/dist/{fx-C6dl2LVI.d.ts → fx-D860pZvP.d.ts} +1 -1
  13. package/dist/index.d.ts +5 -5
  14. package/dist/internal/caller.d.ts +31 -11
  15. package/dist/internal/caller.js +23 -11
  16. package/dist/internal/index.js +1 -1
  17. package/dist/internal/server.d.ts +8 -8
  18. package/dist/internal/server.js +4 -4
  19. package/dist/{job-store-DHnW4Cg_.d.ts → job-store-BUGqvCfL.d.ts} +1 -1
  20. package/dist/{lightning-backend-Ci1nogk_.d.ts → lightning-backend-BozcevPZ.d.ts} +1 -1
  21. package/dist/{memory-credit-ledger-OP24Z2KO.js → memory-credit-ledger-MNUOTQO5.js} +1 -1
  22. package/dist/{mpp-setup-MOBWGTWJ.js → mpp-setup-4FJD6ZHV.js} +11 -1
  23. package/dist/server/index.d.ts +12 -13
  24. package/dist/server/index.js +215 -51
  25. package/dist/{step-cache-BLPZNizw.d.ts → step-cache-5dljDqrQ.d.ts} +4 -2
  26. package/dist/{tempo-lifecycle-SQL3KLEZ.js → tempo-lifecycle-DFIXQ54Q.js} +3 -3
  27. package/dist/{tempo-wallet-QOLEIPCV.js → tempo-wallet-4QKSV65O.js} +10 -2
  28. package/dist/testing/index.d.ts +2 -2
  29. package/dist/{usd-BgOfZlk6.d.ts → usd-DoRuAckA.d.ts} +1 -1
  30. package/dist/{x402-T2C5MX3T.js → x402-5H27DCBE.js} +2 -2
  31. package/package.json +1 -1
@@ -10,7 +10,7 @@ import {
10
10
  } from "./chunk-BQ2NMWKE.js";
11
11
  import {
12
12
  MemoryCreditLedger
13
- } from "./chunk-DBCLBYHP.js";
13
+ } from "./chunk-KVEHHC7W.js";
14
14
  import {
15
15
  SIGNED_ENVELOPE_FIELDS,
16
16
  SignedRequestError,
@@ -49,6 +49,7 @@ import {
49
49
  createMonotonicClock,
50
50
  getWallet,
51
51
  isPublicRequestId,
52
+ isTestMintUrl,
52
53
  isX402SettlementReconciliationReason,
53
54
  normaliseMintUrl,
54
55
  parseTraceparent,
@@ -59,7 +60,7 @@ import {
59
60
  toLockPubkey,
60
61
  verifyCashuToken,
61
62
  verifyChallenge
62
- } from "./chunk-VRQDX5P4.js";
63
+ } from "./chunk-KXCKFIJI.js";
63
64
  import {
64
65
  X402_BATCH_SETTLEMENT_SCHEME,
65
66
  X402_DEFAULT_FACILITATOR,
@@ -140,7 +141,7 @@ import {
140
141
  advertisedMethods,
141
142
  challengeMeta,
142
143
  isTempoInsufficientFundsError
143
- } from "./chunk-5GFED3GJ.js";
144
+ } from "./chunk-M7LHFJ5K.js";
144
145
 
145
146
  // src/sdk/server/lock-pubkey-store.ts
146
147
  async function initLockPubkeyTable(db) {
@@ -3074,7 +3075,8 @@ import {
3074
3075
  Amount as Amount2,
3075
3076
  CheckStateEnum,
3076
3077
  getP2PKExpectedWitnessPubkeys,
3077
- getTagInt
3078
+ getTagInt,
3079
+ verifyDleqIfPresent
3078
3080
  } from "@cashu/cashu-ts";
3079
3081
  function valueCashuFunding(wallet, proofs) {
3080
3082
  let grossSats = Amount2.zero();
@@ -3091,6 +3093,9 @@ function valueCashuFunding(wallet, proofs) {
3091
3093
  };
3092
3094
  }
3093
3095
  async function acceptAccumulatorPayment(opts) {
3096
+ if (opts.disposable && !opts.mints.every(isTestMintUrl)) {
3097
+ throw new Error("Disposable Cashu accepts only known test or loopback mints.");
3098
+ }
3094
3099
  if (!opts.requestId) {
3095
3100
  return {
3096
3101
  kind: "rejected",
@@ -3115,6 +3120,16 @@ async function acceptAccumulatorPayment(opts) {
3115
3120
  const walletProvider = opts.walletProvider ?? getWallet;
3116
3121
  const wallet = await walletProvider(mintUrl);
3117
3122
  proofs = wallet.decodeToken(opts.cashuToken).proofs;
3123
+ if (meta.unit !== "sat" || proofs.length === 0) {
3124
+ throw new Error("Cashu payment requires nonempty sat proofs.");
3125
+ }
3126
+ for (const proof of proofs) {
3127
+ if (!proof.dleq || !verifyDleqIfPresent(proof, wallet.getKeyset(proof.id))) {
3128
+ throw new Error(
3129
+ "Cashu payment requires valid mint-provided NUT-12 DLEQ evidence for every proof. Request a fresh token from a compatible mint."
3130
+ );
3131
+ }
3132
+ }
3118
3133
  valuation = valueCashuFunding(wallet, proofs);
3119
3134
  } catch (err) {
3120
3135
  return {
@@ -3149,6 +3164,9 @@ async function acceptAccumulatorPayment(opts) {
3149
3164
  };
3150
3165
  }
3151
3166
  const allowedNormalised = allowed.map(toLockPubkey);
3167
+ if (opts.disposable && (allowedNormalised.length !== 1 || (getTagInt(p.secret, "n_sigs") ?? 1) !== 1)) {
3168
+ return { kind: "rejected", code: "not_p2pk_locked", message: "Disposable Cashu requires an exclusive single-signature P2PK lock." };
3169
+ }
3152
3170
  const match = accepted.find((pk) => allowedNormalised.includes(pk));
3153
3171
  if (!match) {
3154
3172
  return {
@@ -3185,6 +3203,9 @@ async function acceptAccumulatorPayment(opts) {
3185
3203
  message: "One or more proofs are pending at the mint \u2014 retry shortly."
3186
3204
  };
3187
3205
  }
3206
+ if (states.some((state) => state.state !== CheckStateEnum.UNSPENT)) {
3207
+ return { kind: "rejected", code: "mint_unreachable", message: "Mint returned an unknown proof state." };
3208
+ }
3188
3209
  } catch (err) {
3189
3210
  return {
3190
3211
  kind: "rejected",
@@ -3202,7 +3223,13 @@ async function acceptAccumulatorPayment(opts) {
3202
3223
  tExpireMsByIndex
3203
3224
  };
3204
3225
  try {
3205
- if (opts.withCommitTx) {
3226
+ if (opts.disposable) {
3227
+ const account = opts.withDisposableLedger;
3228
+ if (!account) throw new Error("Disposable Cashu requires atomic credit accounting.");
3229
+ await opts.disposable.commit(opts.requestId, proofs, (ledger) => account(ledger, acceptedValue));
3230
+ } else if (!opts.db) {
3231
+ throw new Error("Cashu accumulator requires a storage backend.");
3232
+ } else if (opts.withCommitTx) {
3206
3233
  const withCommitTx = opts.withCommitTx;
3207
3234
  const client = await opts.db.connect();
3208
3235
  try {
@@ -3254,7 +3281,7 @@ function parseNut11LocktimeMs(secret) {
3254
3281
  var UPFRONT_CHALLENGE_TTL_MS = 5 * 60 * 1e3;
3255
3282
  var CONSUMED_CREDENTIAL_TTL_MS = 2 * UPFRONT_CHALLENGE_TTL_MS;
3256
3283
  function devModeSkipsPaymentVerification(opts) {
3257
- return Boolean(opts.devMode) && !opts.mints;
3284
+ return Boolean(opts.devMode) && !opts.mints && !opts.x402 && !opts.mpp && !opts.paymentMethods?.some((method) => method === "cashu" || method === "x402" || method === "tempo");
3258
3285
  }
3259
3286
  var PAYMENT_PROOF_KEYS = ["cashu_token", "x402_payment", "tempo_credential"];
3260
3287
  function hasPaymentProof(content) {
@@ -3457,7 +3484,7 @@ async function verifyUpfrontPayment(opts) {
3457
3484
  }
3458
3485
  };
3459
3486
  }
3460
- if (opts.cashuMode === "p2pk-accumulator" && opts.accumulatorDb && opts.dvmId && opts.lockPubkeys && opts.lockPubkeys.length > 0) {
3487
+ if (opts.cashuMode === "p2pk-accumulator" && (opts.accumulatorDb || opts.disposableCashu) && opts.dvmId && opts.lockPubkeys && opts.lockPubkeys.length > 0) {
3461
3488
  return verifyAccumulatorReceipt(opts, mints, requiredMsats, ledgerCtx);
3462
3489
  }
3463
3490
  return {
@@ -3605,7 +3632,7 @@ async function verifyUpfrontPayment(opts) {
3605
3632
  x402Requirements
3606
3633
  });
3607
3634
  }
3608
- const { verifyX402Payment } = await import("./x402-T2C5MX3T.js");
3635
+ const { verifyX402Payment } = await import("./x402-5H27DCBE.js");
3609
3636
  const receipt = await verifyX402Payment(
3610
3637
  x402Payment,
3611
3638
  x402Config,
@@ -4454,7 +4481,7 @@ function buildPaymentErrorResponse(body, challenges, x402Requirements, status, x
4454
4481
  async function verifyIncomingPayment(body, opts, snapshot) {
4455
4482
  if (body.type !== "payment") return {};
4456
4483
  if (body.content.cashu_token) {
4457
- if (opts.cashuMode === "p2pk-accumulator" && opts.accumulatorDb && opts.dvmId && opts.lockPubkeys && opts.lockPubkeys.length > 0) {
4484
+ if (opts.cashuMode === "p2pk-accumulator" && (opts.accumulatorDb || opts.disposableCashu) && opts.dvmId && opts.lockPubkeys && opts.lockPubkeys.length > 0) {
4458
4485
  const mints = opts.mints ?? [];
4459
4486
  if (mints.length === 0) {
4460
4487
  return {
@@ -4472,6 +4499,7 @@ async function verifyIncomingPayment(body, opts, snapshot) {
4472
4499
  {
4473
4500
  cashuToken: body.content.cashu_token,
4474
4501
  accumulatorDb: opts.accumulatorDb,
4502
+ disposableCashu: opts.disposableCashu,
4475
4503
  dvmId: opts.dvmId,
4476
4504
  lockPubkeys: opts.lockPubkeys,
4477
4505
  requestId,
@@ -4533,7 +4561,7 @@ async function verifyIncomingPayment(body, opts, snapshot) {
4533
4561
  snapshot
4534
4562
  });
4535
4563
  }
4536
- const { verifyX402Payment } = await import("./x402-T2C5MX3T.js");
4564
+ const { verifyX402Payment } = await import("./x402-5H27DCBE.js");
4537
4565
  const receipt = await verifyX402Payment(
4538
4566
  body.content.x402_payment,
4539
4567
  opts.x402Config,
@@ -4897,7 +4925,7 @@ function applyPaymentInfoToJob(job, info) {
4897
4925
  async function processIncomingPayment(job, body, opts) {
4898
4926
  if (body.type !== "payment") return null;
4899
4927
  if (body.content.cashu_token) {
4900
- if (opts.cashuMode === "p2pk-accumulator" && opts.accumulatorDb && opts.dvmId && opts.lockPubkeys && opts.lockPubkeys.length > 0) {
4928
+ if (opts.cashuMode === "p2pk-accumulator" && (opts.accumulatorDb || opts.disposableCashu) && opts.dvmId && opts.lockPubkeys && opts.lockPubkeys.length > 0) {
4901
4929
  const mints = opts.mints ?? [];
4902
4930
  if (mints.length === 0) {
4903
4931
  return {
@@ -4912,6 +4940,7 @@ async function processIncomingPayment(job, body, opts) {
4912
4940
  {
4913
4941
  cashuToken: body.content.cashu_token,
4914
4942
  accumulatorDb: opts.accumulatorDb,
4943
+ disposableCashu: opts.disposableCashu,
4915
4944
  dvmId: opts.dvmId,
4916
4945
  lockPubkeys: opts.lockPubkeys,
4917
4946
  requestId,
@@ -4946,7 +4975,7 @@ async function processIncomingPayment(job, body, opts) {
4946
4975
  try {
4947
4976
  const requiredMsats = job.pendingPaymentMsats ?? 0;
4948
4977
  const requiredUsdcMicro = job.pendingX402AmountUsdcMicro !== void 0 ? BigInt(job.pendingX402AmountUsdcMicro) : BigInt(msatsToUsdc(requiredMsats, rate));
4949
- const { verifyX402Payment } = await import("./x402-T2C5MX3T.js");
4978
+ const { verifyX402Payment } = await import("./x402-5H27DCBE.js");
4950
4979
  const receipt = await verifyX402Payment(
4951
4980
  body.content.x402_payment,
4952
4981
  opts.x402Config,
@@ -5066,7 +5095,7 @@ function creditPendingPayment(job) {
5066
5095
  }
5067
5096
  async function verifyAccumulatorReceipt(opts, mints, requiredMsats, ledgerCtx) {
5068
5097
  const { cashuToken, accumulatorDb, dvmId, lockPubkeys, mintHealthTracker } = opts;
5069
- if (!cashuToken || !accumulatorDb || !dvmId || !lockPubkeys || lockPubkeys.length === 0) {
5098
+ if (!cashuToken || !accumulatorDb && !opts.disposableCashu || !dvmId || !lockPubkeys || lockPubkeys.length === 0) {
5070
5099
  return {
5071
5100
  paidMsats: 0,
5072
5101
  receivedProofs: [],
@@ -5145,6 +5174,17 @@ async function verifyAccumulatorReceipt(opts, mints, requiredMsats, ledgerCtx) {
5145
5174
  requestId: opts.requestId,
5146
5175
  mints,
5147
5176
  db: accumulatorDb,
5177
+ disposable: opts.disposableCashu,
5178
+ withDisposableLedger: ledgerCtx && requestId ? async (ledger, accepted) => {
5179
+ credited = await fundAndDraw({ ...ledgerCtx, ledger }, {
5180
+ rail: "cashu",
5181
+ paymentId: requestId,
5182
+ paidMsats: accepted.paidMsats,
5183
+ grossPaidMsats: accepted.grossMsats,
5184
+ cashuInputFeeMsats: accepted.inputFeeMsats,
5185
+ mint: tokenMint
5186
+ });
5187
+ } : void 0,
5148
5188
  dvmId,
5149
5189
  lockPubkeys,
5150
5190
  beforeCommit,
@@ -11696,6 +11736,7 @@ var JobManager = class {
11696
11736
  resourcePath: `/v1/job/${job.id}/messages`,
11697
11737
  cashuMode: this.opts.cashuMode,
11698
11738
  accumulatorDb: this.opts.cashuMode === "p2pk-accumulator" ? this.opts.db : void 0,
11739
+ disposableCashu: this.opts.disposableCashu,
11699
11740
  dvmId: this.opts.dvmId,
11700
11741
  lockPubkeys: extra?.lockPubkeys,
11701
11742
  mintHealthTracker: extra?.mintHealthTracker,
@@ -12134,8 +12175,25 @@ var JobManager = class {
12134
12175
  * `context.ts`). The gap is visible to callers — the `seq` series skips a
12135
12176
  * number — which is precisely the completeness signal receipts exist for.
12136
12177
  */
12178
+ async observePaidCompletion(record) {
12179
+ const callback = this.opts.onPaidJobCompleted;
12180
+ if (!callback || record.status !== "completed" || !record.paymentRail || !record.creditId || !record.drawId || !this.opts.creditLedger) return;
12181
+ const draw = await this.opts.creditLedger.getDraw({ creditId: record.creditId, drawId: record.drawId }).catch(() => void 0);
12182
+ const rail = draw?.railValue.rail;
12183
+ const currency = draw?.railValue.creditCurrency;
12184
+ if (draw?.status !== "settled" || draw.amountMicro <= 0 || !currency || !rail || !isFundingRail(rail)) return;
12185
+ const testFunds = rail === "lightning" ? null : this.opts.paymentMode?.rails[rail].testFunds ?? null;
12186
+ try {
12187
+ await callback({ jobId: record.id, rail, amountMicro: draw.amountMicro, currency, testFunds });
12188
+ } catch (error) {
12189
+ console.error(`[${record.id}] Paid completion observer failed:`, error);
12190
+ }
12191
+ }
12137
12192
  async issueReceipt(record) {
12138
- if (record.receipt) return record.receipt;
12193
+ if (record.receipt) {
12194
+ await this.observePaidCompletion(record);
12195
+ return record.receipt;
12196
+ }
12139
12197
  if (!isReceiptableStatus(record.status)) return void 0;
12140
12198
  let credit;
12141
12199
  try {
@@ -12155,13 +12213,18 @@ var JobManager = class {
12155
12213
  return void 0;
12156
12214
  }
12157
12215
  const issuer = this.opts.receiptIssuer;
12158
- if (!issuer) return void 0;
12216
+ if (!issuer) {
12217
+ await this.observePaidCompletion(record);
12218
+ return void 0;
12219
+ }
12159
12220
  if (!isReceiptIssuingStore(this.jobStore)) return void 0;
12160
12221
  const store = this.jobStore;
12161
12222
  try {
12162
12223
  const seq = await store.claimReceiptSeq(record.id);
12163
12224
  const receipt = issuer.issue(record, seq, void 0, credit);
12164
- return await store.saveReceipt(record.id, receipt) ?? receipt;
12225
+ const saved = await store.saveReceipt(record.id, receipt) ?? receipt;
12226
+ await this.observePaidCompletion(record);
12227
+ return saved;
12165
12228
  } catch (err) {
12166
12229
  console.error(
12167
12230
  JSON.stringify({
@@ -13654,7 +13717,7 @@ var X402FacilitatorHealth = class {
13654
13717
  facilitator: support.facilitator,
13655
13718
  network: support.network,
13656
13719
  reason: support.reason,
13657
- message: "x402 omitted because the configured facilitator advertises no supported exact generation on this network. Other rails are unaffected."
13720
+ message: "Exact x402 is unavailable because the configured facilitator advertises no supported exact generation on this network. Configured batch settlement is evaluated separately; other rails are unaffected."
13658
13721
  })
13659
13722
  );
13660
13723
  } else if (!support.exact.v1 || !support.exact.v2 || this.config.batchSettlement && !support.batchSettlement) {
@@ -16599,197 +16662,236 @@ function revenueReporterBannerState(s) {
16599
16662
  return s.devMode ? "(dev \u2014 not reporting)" : "misconfigured";
16600
16663
  }
16601
16664
  async function createDVMServer(descriptor, opts) {
16602
- if (process.env.DVMKIT_CASHU_MINTS && opts.cashuMode === void 0) {
16603
- console.warn(
16604
- JSON.stringify({
16605
- level: "cashu_opts_env_ignored",
16606
- message: "DVMKIT_CASHU_MINTS is set in env but cashuMode opt is undefined \u2014 cashu is NOT active. Pass cashuMode, lockPubkey, and db via createDVMHost to enable it."
16607
- })
16608
- );
16609
- }
16610
- const envMaybe = opts.env;
16611
- const platformToken = opts.platformToken ?? envMaybe.DVMKIT_PLATFORM_TOKEN;
16612
- const platformUrl = opts.platformUrl ?? envMaybe.DVMKIT_PLATFORM_URL;
16613
- const dvmId = opts.dvmId;
16614
16665
  let revenueReporter;
16615
16666
  let payoutReporter;
16616
- if (!opts.onJobCompleted && platformToken && platformUrl && dvmId && opts.db) {
16617
- const { RevenueReporter } = await import("./revenue-reporter-ASZ7SHHH.js");
16618
- const reporter = new RevenueReporter(opts.db, platformUrl, platformToken);
16619
- await reporter.init();
16620
- reporter.startRetryLoop();
16621
- revenueReporter = reporter;
16622
- const { MemoryX402BatchStore, PayoutReporter } = await import("./payout-reporter-RG6XNGPI.js");
16623
- payoutReporter = new PayoutReporter({
16667
+ let unsubscribeTempoSettlementReadiness;
16668
+ let creditExpirySweep;
16669
+ let x402ChannelStorage;
16670
+ let x402BatchSettlement;
16671
+ let server;
16672
+ let shutdownPromise;
16673
+ const shutdown = () => shutdownPromise ??= (async () => {
16674
+ const errors = [];
16675
+ const capture = async (operation) => {
16676
+ try {
16677
+ await operation();
16678
+ } catch (error) {
16679
+ errors.push(error);
16680
+ }
16681
+ };
16682
+ let settlementStopped;
16683
+ if (server) {
16684
+ try {
16685
+ settlementStopped = server.shutdown();
16686
+ } catch (error) {
16687
+ errors.push(error);
16688
+ }
16689
+ } else if (x402BatchSettlement) {
16690
+ try {
16691
+ settlementStopped = x402BatchSettlement.stop();
16692
+ } catch (error) {
16693
+ errors.push(error);
16694
+ }
16695
+ }
16696
+ await capture(() => payoutReporter?.stop());
16697
+ await capture(() => revenueReporter?.stop());
16698
+ await capture(() => creditExpirySweep?.stop());
16699
+ await capture(() => unsubscribeTempoSettlementReadiness?.());
16700
+ if (settlementStopped) await capture(() => settlementStopped);
16701
+ if (x402ChannelStorage) {
16702
+ await capture(() => x402ChannelStorage?.close());
16703
+ }
16704
+ if (errors.length === 1) throw errors[0];
16705
+ if (errors.length > 1) {
16706
+ throw new AggregateError(errors, `${String(errors.length)} DVM shutdown operations failed`);
16707
+ }
16708
+ })();
16709
+ try {
16710
+ if (process.env.DVMKIT_CASHU_MINTS && opts.cashuMode === void 0) {
16711
+ console.warn(
16712
+ JSON.stringify({
16713
+ level: "cashu_opts_env_ignored",
16714
+ message: "DVMKIT_CASHU_MINTS is set in env but cashuMode opt is undefined \u2014 cashu is NOT active. Pass cashuMode, lockPubkey, and db via createDVMHost to enable it."
16715
+ })
16716
+ );
16717
+ }
16718
+ const envMaybe = opts.env;
16719
+ const platformToken = opts.platformToken ?? envMaybe.DVMKIT_PLATFORM_TOKEN;
16720
+ const platformUrl = opts.platformUrl ?? envMaybe.DVMKIT_PLATFORM_URL;
16721
+ const dvmId = opts.dvmId;
16722
+ if (!opts.onJobCompleted && platformToken && platformUrl && dvmId && opts.db) {
16723
+ const { RevenueReporter } = await import("./revenue-reporter-ASZ7SHHH.js");
16724
+ const reporter = new RevenueReporter(opts.db, platformUrl, platformToken);
16725
+ revenueReporter = reporter;
16726
+ await reporter.init();
16727
+ reporter.startRetryLoop();
16728
+ const { MemoryX402BatchStore, PayoutReporter } = await import("./payout-reporter-RG6XNGPI.js");
16729
+ payoutReporter = new PayoutReporter({
16730
+ dvmId,
16731
+ db: opts.db,
16732
+ transport: reporter,
16733
+ // The same condition the admin routes and the accumulator monitor mount on.
16734
+ cashu: opts.cashuMode === "p2pk-accumulator" && !!opts.lockPubkey,
16735
+ ...typeof opts.db.connect === "function" ? {} : { batchStore: new MemoryX402BatchStore() }
16736
+ });
16737
+ await payoutReporter.init();
16738
+ payoutReporter.start();
16739
+ }
16740
+ assertRevenueReporterReady({
16741
+ failFast: opts.failFast ?? false,
16742
+ devMode: opts.devMode,
16743
+ platformToken,
16744
+ platformUrl,
16624
16745
  dvmId,
16625
- db: opts.db,
16626
- transport: reporter,
16627
- // The same condition the admin routes and the accumulator monitor mount on.
16628
- cashu: opts.cashuMode === "p2pk-accumulator" && !!opts.lockPubkey,
16629
- ...typeof opts.db.connect === "function" ? {} : { batchStore: new MemoryX402BatchStore() }
16746
+ hasPgPool: !!opts.db
16630
16747
  });
16631
- await payoutReporter.init();
16632
- payoutReporter.start();
16633
- }
16634
- assertRevenueReporterReady({
16635
- failFast: opts.failFast ?? false,
16636
- devMode: opts.devMode,
16637
- platformToken,
16638
- platformUrl,
16639
- dvmId,
16640
- hasPgPool: !!opts.db
16641
- });
16642
- const effectiveOnJobCompleted = opts.onJobCompleted ?? (revenueReporter ? (info) => revenueReporter.report(info) : void 0);
16643
- const effectiveOnJobCost = opts.onJobCost ?? (revenueReporter ? (info) => revenueReporter.reportCost(info) : void 0);
16644
- const effectiveOnPaidJobDeath = opts.onPaidJobDeath ?? (revenueReporter ? (info) => revenueReporter.reportPaidJobDeath(info) : void 0);
16645
- const effectiveOnRevenueSkippedNoRail = opts.onRevenueSkippedNoRail ?? (revenueReporter ? (info) => revenueReporter.reportRevenueSkippedNoRail(info) : void 0);
16646
- const enqueueCreditDeposit = !opts.onCreditFunded && revenueReporter ? revenueReporter.enqueueDeposit.bind(revenueReporter) : void 0;
16647
- const enqueueCreditDrain = revenueReporter ? revenueReporter.enqueueCreditDrain.bind(revenueReporter) : void 0;
16648
- const enqueueCreditDrawRelease = revenueReporter ? revenueReporter.enqueueCreditDrawRelease.bind(revenueReporter) : void 0;
16649
- const unsubscribeTempoSettlementReadiness = opts.tempoSettlementReadiness?.subscribe({
16650
- onBalance: (observation) => revenueReporter && dvmId ? revenueReporter.reportTempoSettlementBalance({
16651
- dvmId,
16652
- address: observation.address,
16653
- network: observation.network,
16654
- token: observation.token,
16655
- balanceMicro: observation.balanceMicro.toString(),
16656
- lowBalanceMicro: observation.lowBalanceMicro.toString(),
16657
- checkedAt: observation.checkedAt,
16658
- ready: observation.ready
16659
- }) : void 0,
16660
- onFailure: (observation) => revenueReporter && dvmId ? revenueReporter.reportTempoSettlementFailure({
16661
- dvmId,
16662
- address: observation.address,
16663
- network: observation.network,
16664
- token: observation.token,
16665
- operation: observation.operation,
16666
- errorClass: observation.errorClass,
16667
- checkedAt: observation.checkedAt,
16668
- ...observation.balanceMicro !== void 0 ? { balanceMicro: observation.balanceMicro.toString() } : {},
16669
- ...observation.channelId ? { channelId: observation.channelId } : {},
16670
- ...observation.creditId ? { creditId: observation.creditId } : {},
16671
- ...observation.drainId ? { drainId: observation.drainId } : {}
16672
- }) : void 0
16673
- });
16674
- opts.tempoSettlementReadiness?.start();
16675
- const creditLedger = opts.creditLedger ?? new MemoryCreditLedger();
16676
- if (revenueReporter && dvmId) {
16677
- creditLedger.useCreditExpiryReleaseOutbox?.({
16678
- dvmId,
16679
- enqueue: revenueReporter.enqueueCreditExpiryRelease.bind(revenueReporter)
16748
+ const activeRevenueReporter = revenueReporter;
16749
+ const effectiveOnJobCompleted = opts.onJobCompleted ?? (activeRevenueReporter ? (info) => activeRevenueReporter.report(info) : void 0);
16750
+ const effectiveOnJobCost = opts.onJobCost ?? (activeRevenueReporter ? (info) => activeRevenueReporter.reportCost(info) : void 0);
16751
+ const effectiveOnPaidJobDeath = opts.onPaidJobDeath ?? (activeRevenueReporter ? (info) => activeRevenueReporter.reportPaidJobDeath(info) : void 0);
16752
+ const effectiveOnRevenueSkippedNoRail = opts.onRevenueSkippedNoRail ?? (activeRevenueReporter ? (info) => activeRevenueReporter.reportRevenueSkippedNoRail(info) : void 0);
16753
+ const enqueueCreditDeposit = !opts.onCreditFunded && activeRevenueReporter ? activeRevenueReporter.enqueueDeposit.bind(activeRevenueReporter) : void 0;
16754
+ const enqueueCreditDrain = activeRevenueReporter ? activeRevenueReporter.enqueueCreditDrain.bind(activeRevenueReporter) : void 0;
16755
+ const enqueueCreditDrawRelease = activeRevenueReporter ? activeRevenueReporter.enqueueCreditDrawRelease.bind(activeRevenueReporter) : void 0;
16756
+ unsubscribeTempoSettlementReadiness = opts.tempoSettlementReadiness?.subscribe({
16757
+ onBalance: (observation) => activeRevenueReporter && dvmId ? activeRevenueReporter.reportTempoSettlementBalance({
16758
+ dvmId,
16759
+ address: observation.address,
16760
+ network: observation.network,
16761
+ token: observation.token,
16762
+ balanceMicro: observation.balanceMicro.toString(),
16763
+ lowBalanceMicro: observation.lowBalanceMicro.toString(),
16764
+ checkedAt: observation.checkedAt,
16765
+ ready: observation.ready
16766
+ }) : void 0,
16767
+ onFailure: (observation) => activeRevenueReporter && dvmId ? activeRevenueReporter.reportTempoSettlementFailure({
16768
+ dvmId,
16769
+ address: observation.address,
16770
+ network: observation.network,
16771
+ token: observation.token,
16772
+ operation: observation.operation,
16773
+ errorClass: observation.errorClass,
16774
+ checkedAt: observation.checkedAt,
16775
+ ...observation.balanceMicro !== void 0 ? { balanceMicro: observation.balanceMicro.toString() } : {},
16776
+ ...observation.channelId ? { channelId: observation.channelId } : {},
16777
+ ...observation.creditId ? { creditId: observation.creditId } : {},
16778
+ ...observation.drainId ? { drainId: observation.drainId } : {}
16779
+ }) : void 0
16680
16780
  });
16681
- }
16682
- const creditExpirySweep = startCreditExpirySweep(creditLedger, opts.creditExpirySweep);
16683
- const processedPayments = opts.processedPayments ?? new MemoryProcessedPaymentStore();
16684
- const bootX402Support = opts.x402 ? opts.x402FacilitatorHealth?.support() ?? configuredX402FacilitatorSupport(opts.x402) : void 0;
16685
- const x402Config = opts.x402;
16686
- const x402BatchConfig = x402Config?.batchSettlement;
16687
- const selfRelayEnabled = !!x402BatchConfig?.selfRelay;
16688
- const effectiveX402BatchConfig = x402BatchConfig?.selfRelay ? {
16689
- ...x402BatchConfig,
16690
- selfRelay: {
16691
- ...x402BatchConfig.selfRelay,
16692
- onBalance: async (observation) => {
16693
- if (revenueReporter && dvmId) {
16694
- await revenueReporter.reportX402SelfRelayGasBalance({
16695
- dvmId,
16696
- address: observation.address,
16697
- network: observation.network,
16698
- balanceWei: observation.balanceWei.toString(),
16699
- lowBalanceWei: observation.lowBalanceWei.toString(),
16700
- checkedAt: observation.checkedAt
16701
- });
16702
- }
16703
- await x402BatchConfig.selfRelay?.onBalance?.(observation);
16704
- },
16705
- onRpcHealth: async (observation) => {
16706
- if (revenueReporter && dvmId) {
16707
- await revenueReporter.reportX402SelfRelayRpcHealth({
16708
- dvmId,
16709
- ...observation
16710
- });
16711
- }
16712
- await x402BatchConfig.selfRelay?.onRpcHealth?.(observation);
16713
- }
16714
- }
16715
- } : x402BatchConfig;
16716
- const x402ChannelStorage = opts.db && x402Config && effectiveX402BatchConfig && !effectiveX402BatchConfig.storage ? new PostgresX402ChannelStorage(opts.db, {
16717
- terminalizeUnbackedCredit: (evidence, tx) => creditLedger.terminalizeX402Credit(evidence, tx)
16718
- }) : void 0;
16719
- if (x402ChannelStorage) {
16720
- await x402ChannelStorage.init();
16721
- creditLedger.useX402SettlementGate?.(x402ChannelStorage);
16722
- }
16723
- const x402BatchSettlementFactory = x402Config && effectiveX402BatchConfig ? () => createX402BatchSettlementServer({
16724
- channelStorage: x402ChannelStorage,
16725
- network: x402Config.network,
16726
- payTo: x402Config.payTo,
16727
- facilitator: x402Config.facilitator,
16728
- ...x402Config.facilitatorAuth ? { facilitatorAuth: x402Config.facilitatorAuth } : {},
16729
- config: effectiveX402BatchConfig,
16730
- db: opts.db,
16731
- allowInMemory: opts.devMode,
16732
- earnedNative: (channelId) => creditLedger.earnedNativeForX402Channel(channelId),
16733
- supportedResponse: selfRelayEnabled ? void 0 : opts.x402FacilitatorHealth?.supportedResponse?.(),
16734
- payout: payoutReporter?.x402Observer()
16735
- }) : void 0;
16736
- const x402BatchSettlement = x402BatchSettlementFactory && (bootX402Support?.batchSettlement || selfRelayEnabled) ? await x402BatchSettlementFactory() : void 0;
16737
- const x402ExactStore = x402Config && opts.db && typeof opts.db.connect === "function" ? new PostgresX402ExactSettlementStore(opts.db) : void 0;
16738
- await x402ExactStore?.init();
16739
- const x402ExactEvidence = x402Config && x402ExactStore ? await createX402SettlementEvidenceReader({
16740
- network: x402Config.network,
16741
- ...x402BatchConfig?.rpcUrl ? { rpcUrl: x402BatchConfig.rpcUrl } : {}
16742
- }) : void 0;
16743
- const x402ExactSettlement = x402Config && x402ExactStore ? new X402ExactSettlementServer({
16744
- store: x402ExactStore,
16745
- evidence: x402ExactEvidence,
16746
- repair: async (effect, receipt, tx) => {
16747
- if (!receipt.txHash) throw new Error("settled exact x402 intent has no transaction");
16748
- await repairX402ExactSettlementEffect({
16749
- effect,
16750
- paymentId: receipt.txHash,
16751
- ledger: creditLedger,
16752
- processedPayments,
16753
- enqueueCreditDeposit,
16754
- tx
16781
+ opts.tempoSettlementReadiness?.start();
16782
+ const creditLedger = opts.creditLedger ?? new MemoryCreditLedger();
16783
+ if (activeRevenueReporter && dvmId) {
16784
+ creditLedger.useCreditExpiryReleaseOutbox?.({
16785
+ dvmId,
16786
+ enqueue: activeRevenueReporter.enqueueCreditExpiryRelease.bind(activeRevenueReporter)
16755
16787
  });
16756
16788
  }
16757
- }) : void 0;
16758
- const server = new DVMServer(descriptor, {
16759
- ...opts,
16760
- creditLedger,
16761
- processedPayments,
16762
- onJobCompleted: effectiveOnJobCompleted,
16763
- onJobCost: effectiveOnJobCost,
16764
- onPaidJobDeath: effectiveOnPaidJobDeath,
16765
- onRevenueSkippedNoRail: effectiveOnRevenueSkippedNoRail,
16766
- onCreditFunded: opts.onCreditFunded,
16767
- enqueueCreditDeposit,
16768
- enqueueCreditDrain,
16769
- enqueueCreditDrawRelease,
16770
- x402BatchSettlement,
16771
- x402BatchSettlementFactory,
16772
- x402ExactSettlement,
16773
- payoutReporter
16774
- });
16775
- await server.jobManager.recoverTerminalCosts();
16776
- return {
16777
- app: server.app,
16778
- authAudience: server.authAudience,
16779
- shutdown() {
16780
- const settlementStopped = server.shutdown();
16781
- payoutReporter?.stop();
16782
- revenueReporter?.stop();
16783
- creditExpirySweep?.stop();
16784
- unsubscribeTempoSettlementReadiness?.();
16785
- if (x402ChannelStorage) {
16786
- void settlementStopped.then(() => x402ChannelStorage.close()).catch(() => void 0);
16789
+ creditExpirySweep = startCreditExpirySweep(creditLedger, opts.creditExpirySweep);
16790
+ const processedPayments = opts.processedPayments ?? new MemoryProcessedPaymentStore();
16791
+ const bootX402Support = opts.x402 ? opts.x402FacilitatorHealth?.support() ?? configuredX402FacilitatorSupport(opts.x402) : void 0;
16792
+ const x402Config = opts.x402;
16793
+ const x402BatchConfig = x402Config?.batchSettlement;
16794
+ const selfRelayEnabled = !!x402BatchConfig?.selfRelay;
16795
+ const effectiveX402BatchConfig = x402BatchConfig?.selfRelay ? {
16796
+ ...x402BatchConfig,
16797
+ selfRelay: {
16798
+ ...x402BatchConfig.selfRelay,
16799
+ onBalance: async (observation) => {
16800
+ if (activeRevenueReporter && dvmId) {
16801
+ await activeRevenueReporter.reportX402SelfRelayGasBalance({
16802
+ dvmId,
16803
+ address: observation.address,
16804
+ network: observation.network,
16805
+ balanceWei: observation.balanceWei.toString(),
16806
+ lowBalanceWei: observation.lowBalanceWei.toString(),
16807
+ checkedAt: observation.checkedAt
16808
+ });
16809
+ }
16810
+ await x402BatchConfig.selfRelay?.onBalance?.(observation);
16811
+ },
16812
+ onRpcHealth: async (observation) => {
16813
+ if (activeRevenueReporter && dvmId) {
16814
+ await activeRevenueReporter.reportX402SelfRelayRpcHealth({
16815
+ dvmId,
16816
+ ...observation
16817
+ });
16818
+ }
16819
+ await x402BatchConfig.selfRelay?.onRpcHealth?.(observation);
16820
+ }
16787
16821
  }
16788
- },
16789
- jobManager: server.jobManager,
16790
- revenueReporterActive: !!revenueReporter,
16791
- payoutReporter
16792
- };
16822
+ } : x402BatchConfig;
16823
+ x402ChannelStorage = opts.db && x402Config && effectiveX402BatchConfig && !effectiveX402BatchConfig.storage ? new PostgresX402ChannelStorage(opts.db, {
16824
+ terminalizeUnbackedCredit: (evidence, tx) => creditLedger.terminalizeX402Credit(evidence, tx)
16825
+ }) : void 0;
16826
+ if (x402ChannelStorage) {
16827
+ await x402ChannelStorage.init();
16828
+ creditLedger.useX402SettlementGate?.(x402ChannelStorage);
16829
+ }
16830
+ const x402BatchSettlementFactory = x402Config && effectiveX402BatchConfig ? () => createX402BatchSettlementServer({
16831
+ channelStorage: x402ChannelStorage,
16832
+ network: x402Config.network,
16833
+ payTo: x402Config.payTo,
16834
+ facilitator: x402Config.facilitator,
16835
+ ...x402Config.facilitatorAuth ? { facilitatorAuth: x402Config.facilitatorAuth } : {},
16836
+ config: effectiveX402BatchConfig,
16837
+ db: opts.db,
16838
+ allowInMemory: opts.devMode,
16839
+ earnedNative: (channelId) => creditLedger.earnedNativeForX402Channel(channelId),
16840
+ supportedResponse: selfRelayEnabled ? void 0 : opts.x402FacilitatorHealth?.supportedResponse?.(),
16841
+ payout: payoutReporter?.x402Observer()
16842
+ }) : void 0;
16843
+ x402BatchSettlement = x402BatchSettlementFactory && (bootX402Support?.batchSettlement || selfRelayEnabled) ? await x402BatchSettlementFactory() : void 0;
16844
+ const x402ExactStore = x402Config && opts.db && typeof opts.db.connect === "function" ? new PostgresX402ExactSettlementStore(opts.db) : void 0;
16845
+ await x402ExactStore?.init();
16846
+ const x402ExactEvidence = x402Config && x402ExactStore ? await createX402SettlementEvidenceReader({
16847
+ network: x402Config.network,
16848
+ ...x402BatchConfig?.rpcUrl ? { rpcUrl: x402BatchConfig.rpcUrl } : {}
16849
+ }) : void 0;
16850
+ const x402ExactSettlement = x402Config && x402ExactStore ? new X402ExactSettlementServer({
16851
+ store: x402ExactStore,
16852
+ evidence: x402ExactEvidence,
16853
+ repair: async (effect, receipt, tx) => {
16854
+ if (!receipt.txHash) throw new Error("settled exact x402 intent has no transaction");
16855
+ await repairX402ExactSettlementEffect({
16856
+ effect,
16857
+ paymentId: receipt.txHash,
16858
+ ledger: creditLedger,
16859
+ processedPayments,
16860
+ enqueueCreditDeposit,
16861
+ tx
16862
+ });
16863
+ }
16864
+ }) : void 0;
16865
+ server = new DVMServer(descriptor, {
16866
+ ...opts,
16867
+ creditLedger,
16868
+ processedPayments,
16869
+ onJobCompleted: effectiveOnJobCompleted,
16870
+ onJobCost: effectiveOnJobCost,
16871
+ onPaidJobDeath: effectiveOnPaidJobDeath,
16872
+ onRevenueSkippedNoRail: effectiveOnRevenueSkippedNoRail,
16873
+ onCreditFunded: opts.onCreditFunded,
16874
+ enqueueCreditDeposit,
16875
+ enqueueCreditDrain,
16876
+ enqueueCreditDrawRelease,
16877
+ x402BatchSettlement,
16878
+ x402BatchSettlementFactory,
16879
+ x402ExactSettlement,
16880
+ payoutReporter
16881
+ });
16882
+ await server.jobManager.recoverTerminalCosts();
16883
+ return {
16884
+ app: server.app,
16885
+ authAudience: server.authAudience,
16886
+ shutdown,
16887
+ jobManager: server.jobManager,
16888
+ revenueReporterActive: !!activeRevenueReporter,
16889
+ payoutReporter
16890
+ };
16891
+ } catch (initializationError) {
16892
+ await shutdown().catch(() => void 0);
16893
+ throw initializationError;
16894
+ }
16793
16895
  }
16794
16896
  function unknownRouteNotFound(c) {
16795
16897
  c.set("unknownRoute", true);
@@ -16865,7 +16967,6 @@ var DVMServer = class {
16865
16967
  this.ownsMintHealthTracker = false;
16866
16968
  } else if (opts.mints && opts.mints.length > 0) {
16867
16969
  this.mintHealthTracker = new MintHealthTracker({ mints: opts.mints });
16868
- this.mintHealthTracker.start();
16869
16970
  this.ownsMintHealthTracker = true;
16870
16971
  } else {
16871
16972
  this.ownsMintHealthTracker = false;
@@ -16878,12 +16979,6 @@ var DVMServer = class {
16878
16979
  this.creditLedger = opts.creditLedger ?? new MemoryCreditLedger();
16879
16980
  this.opts.mpp?.useTempoCreditLedger?.(this.creditLedger);
16880
16981
  this.processedPayments = opts.processedPayments ?? new MemoryProcessedPaymentStore();
16881
- if (this.opts.tempoObserverHealth?.declareSessionCapability) {
16882
- this.undeclareSessionCapability = this.opts.tempoObserverHealth.declareSessionCapability(
16883
- () => this.tempoSessionCapability()
16884
- );
16885
- void this.opts.tempoObserverHealth.refresh?.();
16886
- }
16887
16982
  this.jobManager = new JobManager(descriptor, {
16888
16983
  receiptIssuer: this.receiptIssuer,
16889
16984
  creditLedger: this.creditLedger,
@@ -16912,6 +17007,7 @@ var DVMServer = class {
16912
17007
  mpp: opts.mpp,
16913
17008
  cashuMode: opts.cashuMode,
16914
17009
  lockPubkey: opts.lockPubkey,
17010
+ disposableCashu: opts.disposableCashu,
16915
17011
  db: opts.db,
16916
17012
  dvmId: opts.dvmId,
16917
17013
  authAudience: this.authAudience,
@@ -16928,6 +17024,8 @@ var DVMServer = class {
16928
17024
  pricingCurrency: this.pricingCurrency,
16929
17025
  onCreditFunded: opts.onCreditFunded,
16930
17026
  onJobCompleted: opts.onJobCompleted,
17027
+ onPaidJobCompleted: opts.onPaidJobCompleted,
17028
+ paymentMode: opts.paymentMode,
16931
17029
  onJobCost: opts.onJobCost,
16932
17030
  onPaidJobDeath: opts.onPaidJobDeath,
16933
17031
  onRevenueSkippedNoRail: opts.onRevenueSkippedNoRail,
@@ -16936,19 +17034,44 @@ var DVMServer = class {
16936
17034
  reactivationClaimGraceMs: opts.reactivationClaimGraceMs
16937
17035
  });
16938
17036
  this.app = new Hono();
16939
- this.registerRoutes();
17037
+ try {
17038
+ this.registerRoutes();
17039
+ if (this.ownsMintHealthTracker) this.mintHealthTracker?.start();
17040
+ if (this.opts.tempoObserverHealth?.declareSessionCapability) {
17041
+ this.undeclareSessionCapability = this.opts.tempoObserverHealth.declareSessionCapability(
17042
+ () => this.tempoSessionCapability()
17043
+ );
17044
+ void this.opts.tempoObserverHealth.refresh?.();
17045
+ }
17046
+ } catch (error) {
17047
+ try {
17048
+ this.jobManager.shutdown();
17049
+ } catch {
17050
+ }
17051
+ try {
17052
+ if (this.ownsMintHealthTracker) this.mintHealthTracker?.stop();
17053
+ } catch {
17054
+ }
17055
+ try {
17056
+ this.undeclareSessionCapability?.();
17057
+ } catch {
17058
+ }
17059
+ this.undeclareSessionCapability = void 0;
17060
+ throw error;
17061
+ }
16940
17062
  }
16941
17063
  /**
16942
17064
  * Tear down this mount. Every leg is synchronous except the batch-settlement
16943
17065
  * server's own `stop()`; the returned promise settles once that has finished,
16944
17066
  * so a caller holding a resource behind it — the settlement pool the spend
16945
17067
  * gate's store owns (internal-review) — can sequence its close instead of pulling it
16946
- * out from under an in-flight stop. It never rejects, so ignoring it is safe.
17068
+ * out from under an in-flight stop. A rejection remains observable so the app
17069
+ * and host teardown layers can finish later cleanup before surfacing it.
16947
17070
  */
16948
17071
  shutdown() {
16949
17072
  this.jobManager.shutdown();
16950
17073
  const settlement = this.x402BatchSettlementInit ?? Promise.resolve(this.x402BatchSettlement);
16951
- const stopped = settlement.then((s) => s?.stop()).catch(() => void 0);
17074
+ const stopped = settlement.then((s) => s?.stop());
16952
17075
  if (this.ownsMintHealthTracker) this.mintHealthTracker?.stop();
16953
17076
  this.undeclareSessionCapability?.();
16954
17077
  this.undeclareSessionCapability = void 0;
@@ -17145,6 +17268,7 @@ var DVMServer = class {
17145
17268
  * `cashu_not_p2pk_locked`).
17146
17269
  */
17147
17270
  async resolveLockPubkeysForReceive() {
17271
+ if (this.opts.disposableCashu && this.opts.lockPubkey) return [toLockPubkey(this.opts.lockPubkey)];
17148
17272
  if (this.opts.cashuMode !== "p2pk-accumulator" || !this.opts.db || !this.opts.dvmId || !this.opts.lockPubkey) {
17149
17273
  return void 0;
17150
17274
  }
@@ -17463,7 +17587,7 @@ var DVMServer = class {
17463
17587
  defaultPaymentMethods() {
17464
17588
  const methods = [];
17465
17589
  if (this.opts.mints?.length) {
17466
- const accumulatorReady = this.opts.cashuMode === "p2pk-accumulator" && !!this.opts.lockPubkey && !!this.opts.db;
17590
+ const accumulatorReady = this.opts.cashuMode === "p2pk-accumulator" && !!this.opts.lockPubkey && (!!this.opts.db || !!this.opts.disposableCashu);
17467
17591
  if (accumulatorReady) methods.push("cashu");
17468
17592
  }
17469
17593
  if (this.opts.x402 && this.x402CurrencySupported()) methods.push("x402");
@@ -17648,7 +17772,7 @@ var DVMServer = class {
17648
17772
  const authHeader = c.req.header("Authorization");
17649
17773
  const { Credential } = await import("mppx");
17650
17774
  const mppCredential = authHeader ? Credential.extractPaymentScheme(authHeader) ?? void 0 : void 0;
17651
- let lockPubkeys;
17775
+ let lockPubkeys = this.opts.disposableCashu && this.opts.lockPubkey ? [toLockPubkey(this.opts.lockPubkey)] : void 0;
17652
17776
  if (this.opts.cashuMode === "p2pk-accumulator" && this.opts.db && this.opts.dvmId && this.opts.lockPubkey) {
17653
17777
  const active = await this.lockPubkeyStateForRead(this.opts.db, this.opts.dvmId);
17654
17778
  lockPubkeys = activePubkeySet(active);
@@ -17682,6 +17806,7 @@ var DVMServer = class {
17682
17806
  consumedCredentialStore: this.consumedCredentialStore,
17683
17807
  cashuMode: this.opts.cashuMode,
17684
17808
  accumulatorDb: this.opts.cashuMode === "p2pk-accumulator" ? this.opts.db : void 0,
17809
+ disposableCashu: this.opts.disposableCashu,
17685
17810
  dvmId: this.opts.dvmId,
17686
17811
  lockPubkeys,
17687
17812
  requestId: c.req.header("X-Cashu-Request-Id"),
@@ -17868,6 +17993,7 @@ var DVMServer = class {
17868
17993
  ...this.opts.mpp.tempoConfiguration && {
17869
17994
  recipient: this.opts.mpp.tempoConfiguration.recipient,
17870
17995
  payment_token: this.opts.mpp.tempoConfiguration.paymentToken,
17996
+ chain_id: this.opts.mpp.tempoConfiguration.chainId,
17871
17997
  ...this.opts.mpp.tempoConfiguration.operator && {
17872
17998
  operator: this.opts.mpp.tempoConfiguration.operator
17873
17999
  },
@@ -19846,6 +19972,7 @@ export {
19846
19972
  pruneRetired,
19847
19973
  DEFAULT_LOCK_PUBKEY_GRACE_SECONDS,
19848
19974
  activePubkeySet,
19975
+ AccumulatorReplayError,
19849
19976
  initWalletAccumulatorTable,
19850
19977
  insertAccumulatorRows,
19851
19978
  clearAccumulatorForDvm,