@dvmkit/sdk 0.21.2 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/dist/card-charge-journal-SKMBEPRM.js +44 -0
  2. package/dist/{chunk-MA55LUNR.js → chunk-2WWVI32F.js} +55 -1
  3. package/dist/{chunk-3V6CSTWB.js → chunk-3DGIRHP2.js} +2 -2
  4. package/dist/{chunk-WWKFG6TM.js → chunk-5NMHZIIU.js} +1 -1
  5. package/dist/{chunk-FAT57DAP.js → chunk-5YJWAJ4N.js} +1 -1
  6. package/dist/{chunk-D2MGOQIS.js → chunk-CUWSJQGT.js} +1 -1
  7. package/dist/{chunk-6GZF7VDO.js → chunk-DLRPKEAM.js} +1 -1
  8. package/dist/{chunk-62JG4AF7.js → chunk-DY5QIHJA.js} +1 -1
  9. package/dist/{chunk-LWF4ABYF.js → chunk-EHBUAJ5M.js} +1 -1
  10. package/dist/{chunk-IUFVIIPF.js → chunk-EQIP6TFD.js} +1 -1
  11. package/dist/{chunk-ZBOCNF56.js → chunk-GDZXGB43.js} +3 -3
  12. package/dist/{chunk-2HSWWHXK.js → chunk-HEH7YUGE.js} +1 -1
  13. package/dist/{chunk-B27E7JIR.js → chunk-HVZIITWW.js} +27 -4
  14. package/dist/{chunk-VIAMJ6GS.js → chunk-JINZMDNK.js} +1224 -80
  15. package/dist/{chunk-NRE4NOCY.js → chunk-JMTLK2SZ.js} +1 -1
  16. package/dist/{chunk-LSANCGLP.js → chunk-L35WYOH2.js} +1 -1
  17. package/dist/{chunk-27QB2D3Z.js → chunk-LCNRFKP7.js} +2 -2
  18. package/dist/{chunk-2AGADOX3.js → chunk-QMKGYIBM.js} +1 -1
  19. package/dist/{chunk-JOSNSNS7.js → chunk-SEIMPHIP.js} +225 -11
  20. package/dist/{chunk-Y746QPX7.js → chunk-SQOVLAJ2.js} +1 -1
  21. package/dist/{chunk-XWG54M6T.js → chunk-UVRBD5GR.js} +1 -1
  22. package/dist/{chunk-5RGZN6WQ.js → chunk-XB644VN3.js} +1 -1
  23. package/dist/{chunk-2RZRYMCR.js → chunk-YNHFJE6U.js} +1 -1
  24. package/dist/{chunk-7KNFEDFW.js → chunk-ZH5CLGO6.js} +1 -1
  25. package/dist/{content-retention-efjireLM.d.ts → content-retention-DEvY5vjM.d.ts} +1 -1
  26. package/dist/{credit-ledger-M3EBVMOP.js → credit-ledger-S76KU53A.js} +11 -3
  27. package/dist/{credit-menu-UOOxuxVL.d.ts → credit-menu-BA2my6hE.d.ts} +229 -8
  28. package/dist/{fx-BtxHVj6w.d.ts → fx-J5oXbv9A.d.ts} +1 -1
  29. package/dist/index.d.ts +5 -5
  30. package/dist/index.js +4 -4
  31. package/dist/internal/caller.d.ts +10 -9
  32. package/dist/internal/caller.js +11 -11
  33. package/dist/internal/server.d.ts +7 -7
  34. package/dist/internal/server.js +21 -21
  35. package/dist/{job-store-DWVkleH3.d.ts → job-store-CjPnf0dd.d.ts} +1 -1
  36. package/dist/{lightning-backend-CTijN35u.d.ts → lightning-backend-D9Q2KDS-.d.ts} +1 -1
  37. package/dist/{memory-credit-ledger-WL2VKLE3.js → memory-credit-ledger-5KXHOWB2.js} +4 -4
  38. package/dist/{mpp-setup-DBYDXISN.js → mpp-setup-3YZMURZL.js} +3 -3
  39. package/dist/{payout-reporter-D5TCIBQA.js → payout-reporter-KTLBNJJ7.js} +2 -2
  40. package/dist/{postgres-consumed-credential-store-IPWPJ6V7.js → postgres-consumed-credential-store-Y336KNIB.js} +1 -1
  41. package/dist/{postgres-job-store-POZJNFJU.js → postgres-job-store-ESEAN7JL.js} +2 -2
  42. package/dist/{postgres-replay-store-JQYAKG47.js → postgres-replay-store-6SVCZ475.js} +2 -2
  43. package/dist/{pricing-FGPVRNTL.js → pricing-RP5CGW6I.js} +3 -3
  44. package/dist/{revenue-reporter-QKCBYFWT.js → revenue-reporter-FD3GDQZS.js} +2 -2
  45. package/dist/server/index.d.ts +20 -11
  46. package/dist/server/index.js +292 -28
  47. package/dist/{step-cache-Bx_ZybWF.d.ts → step-cache-DXFftnAc.d.ts} +154 -12
  48. package/dist/{tempo-charge-store-P7ZBR3GG.js → tempo-charge-store-SOIRMEFJ.js} +2 -2
  49. package/dist/{tempo-session-store-ZVRBAMLG.js → tempo-session-store-UBDFFHDG.js} +3 -3
  50. package/dist/testing/index.d.ts +3 -3
  51. package/dist/testing/index.js +6 -6
  52. package/dist/{usd-eOAMEO12.d.ts → usd-Bc_rva_K.d.ts} +1 -1
  53. package/dist/{x402-44JZJQ5F.js → x402-MFBRORHG.js} +5 -5
  54. package/package.json +1 -1
  55. package/dist/{chunk-NUDHO4HV.js → chunk-LABJSMSJ.js} +48 -48
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  PostgresReplayStore
3
- } from "../chunk-2HSWWHXK.js";
3
+ } from "../chunk-HEH7YUGE.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-D2MGOQIS.js";
21
+ } from "../chunk-CUWSJQGT.js";
22
22
  import {
23
23
  MemoryKVStore
24
24
  } from "../chunk-SDK6KDJN.js";
@@ -36,6 +36,7 @@ import {
36
36
  MemoryX402ExactSettlementStore,
37
37
  PostgresX402ExactSettlementStore,
38
38
  REQUEST_ID_FIELD,
39
+ STRIPE_CREDIT_MIN_MICRO,
39
40
  X402ExactIntentConflictError,
40
41
  X402ExactSettlementEvidenceMissingError,
41
42
  X402ExactSettlementNotReadyError,
@@ -53,11 +54,13 @@ import {
53
54
  clientUpgradeRequired,
54
55
  createDVMServer,
55
56
  createPlatformTempoObserverHealth,
57
+ createStripeRefundApi,
56
58
  createX402BatchSettlementServer,
57
59
  creditEnvelopeIgnoreFields,
58
60
  devModeSkipsPaymentVerification,
59
61
  drawSettlementRef,
60
62
  extractCreditEnvelope,
63
+ fiatMicroToMethodAmount,
61
64
  fundingCommitment,
62
65
  handleCreditRequest,
63
66
  hasInvalidRequestId,
@@ -83,30 +86,30 @@ import {
83
86
  toCreditView,
84
87
  unknownRouteNotFound,
85
88
  writeOffHostedTempoCloseReport
86
- } from "../chunk-VIAMJ6GS.js";
89
+ } from "../chunk-JINZMDNK.js";
87
90
  import {
88
91
  MemoryProcessedPaymentStore,
89
92
  PostgresProcessedPaymentStore,
90
93
  ProcessedPaymentReplayError
91
94
  } from "../chunk-XRLKGCAW.js";
92
- import "../chunk-62JG4AF7.js";
93
- import "../chunk-3V6CSTWB.js";
95
+ import "../chunk-DY5QIHJA.js";
96
+ import "../chunk-3DGIRHP2.js";
94
97
  import {
95
98
  MemoryCreditLedger
96
- } from "../chunk-B27E7JIR.js";
99
+ } from "../chunk-HVZIITWW.js";
97
100
  import {
98
101
  PostgresJobStore
99
- } from "../chunk-Y746QPX7.js";
102
+ } from "../chunk-SQOVLAJ2.js";
100
103
  import {
101
104
  SignedRequestError,
102
105
  carriesSignedEnvelope,
103
106
  createDefaultReplayStore,
104
107
  createSignedRequestVerifier,
105
108
  signedRequestInput
106
- } from "../chunk-6GZF7VDO.js";
109
+ } from "../chunk-DLRPKEAM.js";
107
110
  import {
108
111
  isStreamableJobStore
109
- } from "../chunk-WWKFG6TM.js";
112
+ } from "../chunk-5NMHZIIU.js";
110
113
  import {
111
114
  ContentHoldError,
112
115
  baselineContentExpiry,
@@ -117,23 +120,23 @@ import {
117
120
  IMPLICIT_CREDIT_TTL_MS,
118
121
  generateEphemeralReceiptKey,
119
122
  receiptPubkeyFromSecret
120
- } from "../chunk-IUFVIIPF.js";
123
+ } from "../chunk-EQIP6TFD.js";
121
124
  import {
122
125
  X402_DEFAULT_FACILITATOR,
123
126
  X402_DEFAULT_NETWORK,
124
127
  resolveRpcOverride,
125
128
  x402NetworkToCaip2
126
- } from "../chunk-NUDHO4HV.js";
129
+ } from "../chunk-LABJSMSJ.js";
127
130
  import {
128
131
  SIGNED_REQUEST_AUTH_ID,
129
132
  SIGNED_REQUEST_STATEMENT_VERSION,
130
133
  signedRequestStatementHeader
131
134
  } from "../chunk-SXL44PL5.js";
132
- import "../chunk-NRE4NOCY.js";
135
+ import "../chunk-JMTLK2SZ.js";
133
136
  import "../chunk-FUJ36YDV.js";
134
137
  import "../chunk-BQJIFRAZ.js";
135
- import "../chunk-LWF4ABYF.js";
136
- import "../chunk-XWG54M6T.js";
138
+ import "../chunk-EHBUAJ5M.js";
139
+ import "../chunk-UVRBD5GR.js";
137
140
  import {
138
141
  CreditLedger,
139
142
  CreditLedgerError,
@@ -141,7 +144,7 @@ import {
141
144
  PostgresX402ChannelStorage,
142
145
  X402RelaySubmissionLockError,
143
146
  allocateDrawValue
144
- } from "../chunk-JOSNSNS7.js";
147
+ } from "../chunk-SEIMPHIP.js";
145
148
  import "../chunk-YG7G4DPZ.js";
146
149
  import {
147
150
  SDK_INIT_ADVISORY_LOCK,
@@ -150,25 +153,26 @@ import {
150
153
  import "../chunk-5UC7TOQC.js";
151
154
  import {
152
155
  applyRetryToPool
153
- } from "../chunk-LSANCGLP.js";
156
+ } from "../chunk-L35WYOH2.js";
154
157
  import {
155
158
  assertSupportedX402Network
156
159
  } from "../chunk-BPYMEMQX.js";
157
160
  import "../chunk-H3GGFEE5.js";
158
161
  import {
162
+ MPPX_HMAC_MISMATCH_REASON,
159
163
  TEMPO_MODERATO_CHAIN_ID,
160
164
  TEMPO_MODERATO_RPC,
161
165
  TEMPO_SETTLEMENT_DEFAULT_LOW_BALANCE_MICRO,
162
166
  TempoSettlementReadiness,
163
167
  resolveTempoNetwork
164
- } from "../chunk-27QB2D3Z.js";
168
+ } from "../chunk-LCNRFKP7.js";
165
169
  import {
166
170
  initLoggers
167
- } from "../chunk-7KNFEDFW.js";
171
+ } from "../chunk-ZH5CLGO6.js";
168
172
  import "../chunk-66HGCPBU.js";
169
173
  import {
170
174
  diagnosticConsole
171
- } from "../chunk-MA55LUNR.js";
175
+ } from "../chunk-2WWVI32F.js";
172
176
 
173
177
  // src/sdk/server/cashu-env.ts
174
178
  async function resolveCashuOptsFromEnv(env, pool, cashuModeHint) {
@@ -286,6 +290,243 @@ function safeInteger(value) {
286
290
  return number;
287
291
  }
288
292
 
293
+ // src/sdk/server/stripe-credit.ts
294
+ import { randomBytes } from "crypto";
295
+ import { Credential, Errors as MppxErrors, PaymentRequest } from "mppx";
296
+ import { Mppx } from "mppx/server";
297
+ import { charge as stripeCharge } from "mppx/stripe/server";
298
+ function stripeCreditConfigFromEnv(env) {
299
+ const secretKey = env.DVMKIT_STRIPE_SECRET_KEY?.trim();
300
+ const networkId = env.DVMKIT_STRIPE_NETWORK_ID?.trim();
301
+ if (!secretKey && !networkId) return void 0;
302
+ if (!secretKey) {
303
+ throw new Error(
304
+ "DVMKIT_STRIPE_NETWORK_ID is set but DVMKIT_STRIPE_SECRET_KEY is not. Card credit needs both."
305
+ );
306
+ }
307
+ if (!networkId) {
308
+ throw new Error(
309
+ "DVMKIT_STRIPE_SECRET_KEY is set but DVMKIT_STRIPE_NETWORK_ID is not. Card credit needs both: the network id is your Stripe profile id (profile_\u2026)."
310
+ );
311
+ }
312
+ const hmacSecret = env.DVMKIT_TEMPO_SECRET_KEY;
313
+ if (!hmacSecret) {
314
+ throw new Error(
315
+ "Card credit requires DVMKIT_TEMPO_SECRET_KEY: it binds MPP challenges for both Tempo and card credit. Generate one with 'openssl rand -hex 32'."
316
+ );
317
+ }
318
+ return { secretKey, networkId, hmacSecret };
319
+ }
320
+ function createStripeCreditRail(opts) {
321
+ const apiBase = opts.apiBase ?? "https://api.stripe.com";
322
+ const fetchImpl = opts.fetch ?? fetch;
323
+ const build = (client, secretKey) => Mppx.create({
324
+ methods: [
325
+ stripeCharge({
326
+ client,
327
+ networkId: opts.networkId,
328
+ paymentMethodTypes: ["card"],
329
+ currency: "usd",
330
+ decimals: 2
331
+ })
332
+ ],
333
+ secretKey
334
+ });
335
+ const issuer = build(unusedClient, opts.hmacSecret);
336
+ return {
337
+ networkId: opts.networkId,
338
+ refunds: createStripeRefundApi({ secretKey: opts.secretKey, apiBase, fetch: fetchImpl }),
339
+ ...opts.chargeJournal && { chargeJournal: opts.chargeJournal },
340
+ async issueChallenge({ amountMicro, resourcePath, expires }) {
341
+ return issuer.challenge.stripe.charge({
342
+ amount: fiatMicroToMethodAmount(amountMicro, "stripe"),
343
+ expires,
344
+ meta: { path: resourcePath, nonce: randomBytes(16).toString("hex") }
345
+ });
346
+ },
347
+ async charge(serialized, { amountMicro, resourcePath }) {
348
+ let credential;
349
+ try {
350
+ credential = Credential.deserialize(serialized);
351
+ } catch {
352
+ return invalidCredential("the credential is not a well-formed MPP credential");
353
+ }
354
+ if (credential.challenge.method !== "stripe" || credential.challenge.intent !== "charge") {
355
+ return invalidCredential("the credential is not for a stripe charge challenge");
356
+ }
357
+ const attempt = {};
358
+ const journal = opts.chargeJournal;
359
+ const beforeCharge = journal ? async () => {
360
+ try {
361
+ await journal.record(credential.challenge.id);
362
+ } catch (err) {
363
+ attempt.journalFailed = true;
364
+ diagnosticConsole.warn({ event: "card_charge_journal_failed" });
365
+ throw err;
366
+ }
367
+ } : void 0;
368
+ const amount = fiatMicroToMethodAmount(amountMicro, "stripe");
369
+ const broadcast = (secretKey) => build(fetchClient({ apiBase, secretKey: opts.secretKey, fetchImpl, attempt, beforeCharge }), secretKey).broadcastCredential(serialized, {
370
+ request: { amount },
371
+ meta: { path: resourcePath, nonce: readNonce(credential.challenge) }
372
+ });
373
+ try {
374
+ let receipt;
375
+ try {
376
+ receipt = await broadcast(opts.hmacSecret);
377
+ } catch (err) {
378
+ const previous = !attempt.called && isHmacMismatch(err) ? await opts.previousHmacSecret?.() : void 0;
379
+ if (!previous) throw err;
380
+ receipt = await broadcast(previous);
381
+ }
382
+ if (!attempt.paymentIntentId || receipt.reference !== attempt.paymentIntentId) {
383
+ return {
384
+ ok: false,
385
+ reason: "indeterminate",
386
+ message: "the charge succeeded without a PaymentIntent this server observed"
387
+ };
388
+ }
389
+ if (attempt.amount !== amountMicro / 1e4 || attempt.currency !== "usd") {
390
+ return {
391
+ ok: false,
392
+ reason: "mismatch",
393
+ message: "the PaymentIntent's amount or currency is not this top-up's",
394
+ paymentIntentId: attempt.paymentIntentId
395
+ };
396
+ }
397
+ return { ok: true, paymentIntentId: attempt.paymentIntentId, replayed: attempt.replayed === true };
398
+ } catch (err) {
399
+ if (attempt.journalFailed) {
400
+ return {
401
+ ok: false,
402
+ reason: "unavailable",
403
+ message: "the charge attempt could not be recorded, so this request did not charge the card"
404
+ };
405
+ }
406
+ if (!attempt.called) return invalidCredential(credentialFailure(err));
407
+ const stripeError = attempt.failure?.codes;
408
+ const known = {
409
+ ...stripeError && { stripeError },
410
+ ...attempt.paymentIntentId && { paymentIntentId: attempt.paymentIntentId }
411
+ };
412
+ if (stripeError?.type === "card_error") {
413
+ return { ok: false, reason: "declined", message: "the card was declined", ...known };
414
+ }
415
+ if (attempt.failure?.status === 400 && stripeError?.type === "invalid_request_error") {
416
+ return {
417
+ ok: false,
418
+ reason: "token_unusable",
419
+ message: "Stripe refused the shared payment token; nothing was charged",
420
+ ...known
421
+ };
422
+ }
423
+ if (attempt.status === "requires_action") {
424
+ return {
425
+ ok: false,
426
+ reason: "requires_action",
427
+ message: "the card requires an authentication step",
428
+ ...known
429
+ };
430
+ }
431
+ return {
432
+ ok: false,
433
+ reason: "indeterminate",
434
+ message: attempt.failure ? `Stripe answered HTTP ${attempt.failure.status} without confirming the charge` : attempt.status ? `the PaymentIntent is ${attempt.status}, not succeeded` : "Stripe could not be reached or its answer was lost",
435
+ ...known
436
+ };
437
+ }
438
+ }
439
+ };
440
+ }
441
+ var unusedClient = {
442
+ paymentIntents: {
443
+ create() {
444
+ return Promise.reject(new Error("the challenge issuer never charges"));
445
+ }
446
+ }
447
+ };
448
+ function fetchClient(args) {
449
+ return {
450
+ paymentIntents: {
451
+ async create(params, options) {
452
+ await args.beforeCharge?.();
453
+ args.attempt.called = true;
454
+ const response = await args.fetchImpl(`${args.apiBase}/v1/payment_intents`, {
455
+ method: "POST",
456
+ headers: {
457
+ Authorization: `Basic ${Buffer.from(`${args.secretKey}:`).toString("base64")}`,
458
+ "Content-Type": "application/x-www-form-urlencoded",
459
+ ...options.idempotencyKey && { "Idempotency-Key": options.idempotencyKey },
460
+ ...options.apiVersion && { "Stripe-Version": options.apiVersion },
461
+ ...options.stripeAccount && { "Stripe-Account": options.stripeAccount }
462
+ },
463
+ body: formEncode(params)
464
+ });
465
+ const body = await response.json().catch(() => ({}));
466
+ if (!response.ok) {
467
+ const enumField = (value) => typeof value === "string" && /^[a-z0-9_]{1,64}$/.test(value) ? value : void 0;
468
+ const type = enumField(body.error?.type);
469
+ const code = enumField(body.error?.code);
470
+ const declineCode = enumField(body.error?.decline_code);
471
+ args.attempt.failure = {
472
+ status: response.status,
473
+ codes: { ...type && { type }, ...code && { code }, ...declineCode && { declineCode } }
474
+ };
475
+ const intent = body.error?.payment_intent?.id;
476
+ if (typeof intent === "string" && /^pi_[A-Za-z0-9]+$/.test(intent)) {
477
+ args.attempt.paymentIntentId = intent;
478
+ }
479
+ throw new Error(`Stripe answered HTTP ${response.status}`);
480
+ }
481
+ if (typeof body.id !== "string" || typeof body.status !== "string") {
482
+ throw new Error("Stripe returned a PaymentIntent without an id or status");
483
+ }
484
+ args.attempt.paymentIntentId = body.id;
485
+ args.attempt.status = body.status;
486
+ if (typeof body.amount === "number") args.attempt.amount = body.amount;
487
+ if (typeof body.currency === "string") args.attempt.currency = body.currency;
488
+ args.attempt.replayed = response.headers.get("idempotent-replayed") === "true";
489
+ return { id: body.id, status: body.status };
490
+ }
491
+ }
492
+ };
493
+ }
494
+ function formEncode(params) {
495
+ const out = new URLSearchParams();
496
+ const visit = (key, value) => {
497
+ if (value === void 0 || value === null) return;
498
+ if (Array.isArray(value)) {
499
+ value.forEach((item, index) => visit(`${key}[${index}]`, item));
500
+ } else if (typeof value === "object") {
501
+ for (const [child, nested] of Object.entries(value)) visit(`${key}[${child}]`, nested);
502
+ } else {
503
+ out.set(key, String(value));
504
+ }
505
+ };
506
+ for (const [key, value] of Object.entries(params)) visit(key, value);
507
+ return out;
508
+ }
509
+ function readNonce(challenge) {
510
+ let meta;
511
+ try {
512
+ meta = challenge.opaque ? PaymentRequest.deserialize(challenge.opaque) : challenge.meta;
513
+ } catch {
514
+ return "";
515
+ }
516
+ return typeof meta?.nonce === "string" ? meta.nonce : "";
517
+ }
518
+ function invalidCredential(message) {
519
+ return { ok: false, reason: "invalid_credential", message };
520
+ }
521
+ function credentialFailure(err) {
522
+ if (isHmacMismatch(err)) return "the challenge was not issued by this server";
523
+ if (err instanceof MppxErrors.PaymentExpiredError) return "the challenge has expired";
524
+ return "the credential does not match this top-up's challenge";
525
+ }
526
+ function isHmacMismatch(err) {
527
+ return err instanceof MppxErrors.InvalidChallengeError && err.message.includes(MPPX_HMAC_MISMATCH_REASON);
528
+ }
529
+
289
530
  // src/sdk/server/payment-mode.ts
290
531
  function resolvePaymentMode(opts) {
291
532
  const active = (rail, configured, ready) => ({
@@ -1195,7 +1436,7 @@ function createDVMHost(opts = {}) {
1195
1436
  });
1196
1437
  applyRetryToPool(pool, "dvm-host");
1197
1438
  pgPool = pool;
1198
- const { PostgresJobStore: PostgresJobStore2 } = await import("../postgres-job-store-POZJNFJU.js");
1439
+ const { PostgresJobStore: PostgresJobStore2 } = await import("../postgres-job-store-ESEAN7JL.js");
1199
1440
  const pgJobStore = new PostgresJobStore2(pool);
1200
1441
  pendingInits.push(pgJobStore.init(), pgJobStore.initStreaming());
1201
1442
  jobStore = pgJobStore;
@@ -1283,16 +1524,18 @@ ${config.facilitatorAuth?.keyId ?? ""}`;
1283
1524
  const tempoObserverHealth = createPlatformTempoObserverHealth(envMaybe);
1284
1525
  void tempoObserverHealth?.refresh();
1285
1526
  const receiptKey = envMaybe.DVMKIT_RECEIPT_KEY ?? (opts.devMode ? generateEphemeralReceiptKey().secret : void 0);
1527
+ let stripeCredit = opts.stripeCredit;
1528
+ const stripeCreditConfig = stripeCredit ? void 0 : stripeCreditConfigFromEnv(envMaybe);
1286
1529
  let mpp = opts.mpp;
1287
1530
  let mppSecretState = null;
1288
1531
  let tempoChargeBackend = "user-supplied";
1289
1532
  const mppTempoRecipient = envMaybe.DVMKIT_TEMPO_RECIPIENT;
1290
1533
  if (!mpp && mppTempoRecipient) {
1291
- const { createMppFromOpts, createDualKeyMppxFromOpts, parseMppMethodsAllowlist } = await import("../mpp-setup-DBYDXISN.js");
1534
+ const { createMppFromOpts, createDualKeyMppxFromOpts, parseMppMethodsAllowlist } = await import("../mpp-setup-3YZMURZL.js");
1292
1535
  tempoChargeBackend = pgPool ? "postgres" : "memory";
1293
1536
  let tempoCharge;
1294
1537
  if (pgPool) {
1295
- const { PostgresTempoChargeStore } = await import("../tempo-charge-store-P7ZBR3GG.js");
1538
+ const { PostgresTempoChargeStore } = await import("../tempo-charge-store-SOIRMEFJ.js");
1296
1539
  const chargeStore = new PostgresTempoChargeStore(pgPool);
1297
1540
  tempoChargeStore = chargeStore;
1298
1541
  pendingInits.push(chargeStore.init());
@@ -1312,7 +1555,7 @@ ${config.facilitatorAuth?.keyId ?? ""}`;
1312
1555
  { createPublicClient, createWalletClient, erc20Abi, http },
1313
1556
  { tempo: tempoMainnet, tempoModerato }
1314
1557
  ] = await Promise.all([
1315
- import("../tempo-session-store-ZVRBAMLG.js"),
1558
+ import("../tempo-session-store-UBDFFHDG.js"),
1316
1559
  import("viem/accounts"),
1317
1560
  import("viem"),
1318
1561
  import("viem/chains")
@@ -1464,8 +1707,22 @@ ${config.facilitatorAuth?.keyId ?? ""}`;
1464
1707
  mpp = createMppFromOpts(mppOpts, env);
1465
1708
  }
1466
1709
  }
1710
+ if (stripeCreditConfig) {
1711
+ let previousHmacSecret;
1712
+ if (pgPool) {
1713
+ const { initMppSecretStateTable, applyMppSecretRotation, loadMppSecretState, DEFAULT_ROTATION_WINDOW_MS } = await import("../mpp-secret-state-B5GCILVH.js");
1714
+ if (!mppSecretState) {
1715
+ await initMppSecretStateTable(pgPool);
1716
+ mppSecretState = (await applyMppSecretRotation(pgPool, stripeCreditConfig.hmacSecret, DEFAULT_ROTATION_WINDOW_MS)).state;
1717
+ }
1718
+ const localPool = pgPool;
1719
+ previousHmacSecret = async () => (await loadMppSecretState(localPool))?.previous?.secret;
1720
+ }
1721
+ const chargeJournal = pgPool ? await (await import("../card-charge-journal-SKMBEPRM.js")).createPostgresCardChargeJournal(pgPool) : void 0;
1722
+ stripeCredit = createStripeCreditRail({ ...stripeCreditConfig, previousHmacSecret, chargeJournal });
1723
+ }
1467
1724
  const fxSource = envMaybe.DVMKIT_FX_SOURCE;
1468
- const { createFxFetcher, resolveFxSourceFromEnv, warmFxSnapshot } = await import("../pricing-FGPVRNTL.js");
1725
+ const { createFxFetcher, resolveFxSourceFromEnv, warmFxSnapshot } = await import("../pricing-RP5CGW6I.js");
1469
1726
  const fxFetcher = opts.fx ?? createFxFetcher({ source: resolveFxSourceFromEnv(envMaybe) });
1470
1727
  const hostRailConfigured = (opts.paymentMethods?.length ?? 0) > 0 || (effectiveMints?.length ?? 0) > 0 || !!x402WithDualServe || !!mpp;
1471
1728
  if (mounts.some((entry) => mountNeedsFx(entry, hostRailConfigured))) warmFxSnapshot(fxFetcher);
@@ -1475,7 +1732,7 @@ ${config.facilitatorAuth?.keyId ?? ""}`;
1475
1732
  assertReceiptIdentity(envMaybe, opts.builder, receiptKey, cashuOpts.dvmId, opts.devMode);
1476
1733
  let sharedPgReplayStore;
1477
1734
  if (pgPool) {
1478
- const { PostgresReplayStore: PostgresReplayStore2 } = await import("../postgres-replay-store-JQYAKG47.js");
1735
+ const { PostgresReplayStore: PostgresReplayStore2 } = await import("../postgres-replay-store-6SVCZ475.js");
1479
1736
  const store2 = new PostgresReplayStore2(pgPool);
1480
1737
  pendingInits.push(store2.init());
1481
1738
  sharedPgReplayStore = store2;
@@ -1503,13 +1760,13 @@ ${config.facilitatorAuth?.keyId ?? ""}`;
1503
1760
  }
1504
1761
  let sharedPgConsumedStore;
1505
1762
  if (pgPool) {
1506
- const { PostgresConsumedCredentialStore } = await import("../postgres-consumed-credential-store-IPWPJ6V7.js");
1763
+ const { PostgresConsumedCredentialStore } = await import("../postgres-consumed-credential-store-Y336KNIB.js");
1507
1764
  const consumedStore = new PostgresConsumedCredentialStore(pgPool);
1508
1765
  pendingInits.push(consumedStore.init());
1509
1766
  sharedPgConsumedStore = consumedStore;
1510
1767
  }
1511
1768
  if (pgPool) {
1512
- const { CreditLedger: CreditLedger2 } = await import("../credit-ledger-M3EBVMOP.js");
1769
+ const { CreditLedger: CreditLedger2 } = await import("../credit-ledger-S76KU53A.js");
1513
1770
  const pgLedger = new CreditLedger2(pgPool, tempoSessionStore);
1514
1771
  pendingInits.push(pgLedger.init());
1515
1772
  creditLedger = pgLedger;
@@ -1518,7 +1775,7 @@ ${config.facilitatorAuth?.keyId ?? ""}`;
1518
1775
  pendingInits.push(pgProcessed.init());
1519
1776
  processedPayments = pgProcessed;
1520
1777
  } else {
1521
- const { MemoryCreditLedger: MemoryCreditLedger2 } = await import("../memory-credit-ledger-WL2VKLE3.js");
1778
+ const { MemoryCreditLedger: MemoryCreditLedger2 } = await import("../memory-credit-ledger-5KXHOWB2.js");
1522
1779
  creditLedger = disposableCashu?.ledger ?? new MemoryCreditLedger2();
1523
1780
  const { MemoryProcessedPaymentStore: MemoryProcessedPaymentStore2 } = await import("../processed-payment-store-GKMAWOM3.js");
1524
1781
  processedPayments = new MemoryProcessedPaymentStore2();
@@ -1633,6 +1890,7 @@ ${config.facilitatorAuth?.keyId ?? ""}`;
1633
1890
  x402: descX402WithDualServe,
1634
1891
  x402FacilitatorHealth: descX402Health,
1635
1892
  mpp: descMpp,
1893
+ stripeCredit,
1636
1894
  consumedCredentialStore: opts.consumedCredentialStore ?? sharedPgConsumedStore,
1637
1895
  adminCashuNonceStore: sharedPgConsumedStore,
1638
1896
  cashuMode: cashuOpts.cashuMode,
@@ -1706,6 +1964,7 @@ ${config.facilitatorAuth?.keyId ?? ""}`;
1706
1964
  x402: bootX402,
1707
1965
  x402Support: bootX402Support,
1708
1966
  lightningReceive,
1967
+ stripeCredit,
1709
1968
  fxSource,
1710
1969
  hasPlatformToken: !!platformToken,
1711
1970
  hasDvmId: !!cashuOpts.dvmId,
@@ -2030,6 +2289,9 @@ function logBootSummary(s) {
2030
2289
  diagnosticConsole.log(
2031
2290
  ` LN receive: ${s.lightningReceive ? `receive-only NWC (${s.lightningReceive.available() ? "reachable" : "unreachable \u2014 omitted from the funding menu"})` : "(unconfigured)"}`
2032
2291
  );
2292
+ diagnosticConsole.log(
2293
+ ` Card credit: ${s.stripeCredit ? `stripe (network ${s.stripeCredit.networkId})` : "(unconfigured)"}`
2294
+ );
2033
2295
  diagnosticConsole.log(
2034
2296
  ` Platform rep.: ${revenueReporterBannerState({
2035
2297
  platformUrl: s.platformUrl,
@@ -2181,6 +2443,7 @@ export {
2181
2443
  SIGNED_REQUEST_AUTH_ID,
2182
2444
  SIGNED_REQUEST_STATEMENT_VERSION,
2183
2445
  SSRFError,
2446
+ STRIPE_CREDIT_MIN_MICRO,
2184
2447
  SignedRequestError,
2185
2448
  X402ExactIntentConflictError,
2186
2449
  X402ExactSettlementEvidenceMissingError,
@@ -2203,6 +2466,7 @@ export {
2203
2466
  createDVMHost,
2204
2467
  createPinnedFetch,
2205
2468
  createSignedRequestVerifier,
2469
+ createStripeCreditRail,
2206
2470
  createX402BatchSettlementServer,
2207
2471
  creditEnvelopeIgnoreFields,
2208
2472
  drawSettlementRef,