@dvmkit/sdk 0.7.0-rc.1 → 0.7.0-rc.3

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 (70) hide show
  1. package/README.md +4 -0
  2. package/dist/{chunk-S3OY533W.js → chunk-26W6GPCD.js} +48 -6
  3. package/dist/{chunk-FWGWLPXF.js → chunk-2OM2QPBE.js} +2 -2
  4. package/dist/{chunk-GY66THYI.js → chunk-3UK3CDOT.js} +186 -90
  5. package/dist/{chunk-CXCQLOOK.js → chunk-62FI3NJF.js} +42 -107
  6. package/dist/{chunk-VHNPVGSA.js → chunk-6STC5TCP.js} +3 -3
  7. package/dist/{chunk-N5RZ5HVB.js → chunk-72V5DTEC.js} +2 -2
  8. package/dist/chunk-A262WVYX.js +6 -0
  9. package/dist/{chunk-QR2EF2NI.js → chunk-AQ7OX5NX.js} +2 -2
  10. package/dist/{chunk-BYCEKO65.js → chunk-CLIAFTUR.js} +102 -13
  11. package/dist/{chunk-GAOAYHZA.js → chunk-DNG4KGSC.js} +3 -3
  12. package/dist/{chunk-Z4ZT5LNT.js → chunk-GSLS4464.js} +3 -3
  13. package/dist/{chunk-RA2WIX7G.js → chunk-H5FVVEEN.js} +18 -7
  14. package/dist/{chunk-IXR5RFK7.js → chunk-HCE4MPZ5.js} +1 -1
  15. package/dist/{chunk-OML32F6I.js → chunk-I555L2WK.js} +1 -1
  16. package/dist/{chunk-EQLA4FFY.js → chunk-IIZQNDQU.js} +3 -3
  17. package/dist/{chunk-FUJ36YDV.js → chunk-KXWROQGK.js} +24 -1
  18. package/dist/{chunk-ETXDTUJO.js → chunk-LAKP6FUI.js} +55 -0
  19. package/dist/{chunk-X7EZ5CLI.js → chunk-MON76YBJ.js} +3 -3
  20. package/dist/chunk-OFSOLHRX.js +120 -0
  21. package/dist/{chunk-IV6Q7NRW.js → chunk-RAGX6VG7.js} +2 -2
  22. package/dist/{chunk-KA6VN5FK.js → chunk-RXPHMS4C.js} +3 -3
  23. package/dist/{chunk-6XF3RVVX.js → chunk-SPYEJXI7.js} +5 -5
  24. package/dist/{chunk-P6QON7ER.js → chunk-TRNMTTPX.js} +1 -1
  25. package/dist/{chunk-RCM3P2HE.js → chunk-UKD3R2KU.js} +55 -4
  26. package/dist/chunk-USL7ZEXN.js +17 -0
  27. package/dist/{chunk-KMED3H3A.js → chunk-VB5OLOZH.js} +395 -231
  28. package/dist/{content-retention-DHyLdA6b.d.ts → content-retention-ChFSSVO0.d.ts} +1 -1
  29. package/dist/{credit-ledger-MCUXYKSJ.js → credit-ledger-7Z7LOCTN.js} +4 -4
  30. package/dist/{credit-menu-DjnkeEUU.d.ts → credit-menu-fy0DDigm.d.ts} +6 -6
  31. package/dist/{fx-zMWFzfrU.d.ts → fx-DM0_NYiE.d.ts} +1 -1
  32. package/dist/index.d.ts +5 -5
  33. package/dist/index.js +236 -16
  34. package/dist/internal/caller.d.ts +4968 -8286
  35. package/dist/internal/caller.js +4291 -8084
  36. package/dist/internal/index.js +1 -1
  37. package/dist/internal/server.d.ts +7 -7
  38. package/dist/internal/server.js +27 -30
  39. package/dist/{job-store-DdLXBpol.d.ts → job-store-DkfNE9sv.d.ts} +1 -1
  40. package/dist/{lightning-backend-Bw-qtAbt.d.ts → lightning-backend-C3Gf1XpP.d.ts} +2 -2
  41. package/dist/{memory-credit-ledger-SBSMGMDX.js → memory-credit-ledger-3WOS74UH.js} +5 -5
  42. package/dist/{mpp-setup-RF5FXGGV.js → mpp-setup-XB4KATMU.js} +2 -2
  43. package/dist/{payout-reporter-3Y2U55ZX.js → payout-reporter-WT7XYW42.js} +2 -2
  44. package/dist/{postgres-consumed-credential-store-BUVCAPLS.js → postgres-consumed-credential-store-W7UP33AH.js} +3 -3
  45. package/dist/{postgres-job-store-VHLQBJZC.js → postgres-job-store-3KGUGFRD.js} +2 -2
  46. package/dist/{postgres-replay-store-ARZSQ45X.js → postgres-replay-store-CVNJJOQG.js} +2 -2
  47. package/dist/{pricing-XT2IAPNE.js → pricing-QAVZUTZR.js} +12 -12
  48. package/dist/{revenue-reporter-MAERPYGK.js → revenue-reporter-7UR3W2SD.js} +2 -2
  49. package/dist/server/index.d.ts +10 -10
  50. package/dist/server/index.js +44 -48
  51. package/dist/{step-cache-2MkvenJn.d.ts → step-cache-DDTwd4SK.d.ts} +6 -2
  52. package/dist/{tempo-charge-store-Q3D7KYMH.js → tempo-charge-store-GA6CED6O.js} +2 -2
  53. package/dist/{tempo-session-store-ZRNCOX7P.js → tempo-session-store-WZWQRITB.js} +3 -3
  54. package/dist/testing/index.d.ts +3 -3
  55. package/dist/testing/index.js +6 -7
  56. package/dist/{usd-DI3d3gTK.d.ts → usd-DkRy9nfU.d.ts} +1 -1
  57. package/dist/{x402-FT4S4JS4.js → x402-ZU4GML7Z.js} +8 -27
  58. package/package.json +1 -1
  59. package/dist/chunk-66HGCPBU.js +0 -25
  60. package/dist/chunk-AT6V3SY7.js +0 -102
  61. package/dist/chunk-EZXAJ6EI.js +0 -1082
  62. package/dist/chunk-HCLVYZUZ.js +0 -244
  63. package/dist/chunk-JEVLNAO3.js +0 -1668
  64. package/dist/chunk-NFMOPYBA.js +0 -357
  65. package/dist/chunk-O2OTZ5GP.js +0 -1869
  66. package/dist/chunk-OFVV37XC.js +0 -57
  67. package/dist/chunk-SZVXOQ75.js +0 -211
  68. package/dist/chunk-WBOKPC37.js +0 -795
  69. package/dist/tempo-lifecycle-GJ77YKVY.js +0 -15
  70. package/dist/tempo-wallet-X2GGAZ6X.js +0 -40
@@ -1,20 +1,28 @@
1
1
  import {
2
- MemoryProcessedPaymentStore,
3
- PostgresProcessedPaymentStore,
4
- ProcessedPaymentReplayError
5
- } from "./chunk-XRLKGCAW.js";
2
+ TEMPO_MODERATO_CHAIN_ID,
3
+ TEMPO_MODERATO_RPC,
4
+ advertisedMethods,
5
+ challengeMeta,
6
+ installHostedTempoChargeGuard,
7
+ installHostedTempoCloseGuard,
8
+ isTempoInsufficientFundsError,
9
+ resolveTempoNetwork
10
+ } from "./chunk-HCE4MPZ5.js";
6
11
  import {
7
12
  createX402FacilitatorAuthHeaders,
8
13
  createX402FacilitatorClient,
14
+ paymentFailureStage,
9
15
  settleWithFacilitator,
10
- verifyWithFacilitator
11
- } from "./chunk-S3OY533W.js";
16
+ verifyWithFacilitator,
17
+ withPaymentDiagnostics,
18
+ withPaymentStage
19
+ } from "./chunk-26W6GPCD.js";
12
20
  import {
13
21
  MemoryCreditLedger
14
- } from "./chunk-OML32F6I.js";
22
+ } from "./chunk-I555L2WK.js";
15
23
  import {
16
24
  PostgresJobStore
17
- } from "./chunk-EQLA4FFY.js";
25
+ } from "./chunk-IIZQNDQU.js";
18
26
  import {
19
27
  parseStoreValue
20
28
  } from "./chunk-YG7G4DPZ.js";
@@ -25,7 +33,7 @@ import {
25
33
  humanizeZodIssues,
26
34
  signedRequestInput,
27
35
  zodIssuesOf
28
- } from "./chunk-N5RZ5HVB.js";
36
+ } from "./chunk-72V5DTEC.js";
29
37
  import {
30
38
  MemoryJobStore,
31
39
  UNCAPPABLE_ASK_TOTAL,
@@ -34,7 +42,7 @@ import {
34
42
  isJobRetentionStore,
35
43
  isReceiptIssuingStore,
36
44
  isStreamableJobStore
37
- } from "./chunk-IV6Q7NRW.js";
45
+ } from "./chunk-RAGX6VG7.js";
38
46
  import {
39
47
  ContentHoldError,
40
48
  JobCancelledError,
@@ -53,34 +61,26 @@ import {
53
61
  ADMIN_AUTH_CLOCK_SKEW_SECONDS,
54
62
  ADMIN_AUTH_NONCE_TTL_SECONDS,
55
63
  ADMIN_STATE_UNAVAILABLE,
64
+ IMPLICIT_CREDIT_TTL_MS,
56
65
  TEMPO_SESSION_UPDATED_REASON,
57
66
  X402_BATCH_CHANNEL_ABI,
58
67
  attestedDvmIdentity,
59
68
  buildAdminChallenge,
60
69
  checkMintHealth,
70
+ computeResultHash,
61
71
  createMonotonicClock,
72
+ formatStaleness,
62
73
  getWallet,
63
74
  isPublicRequestId,
64
- isTestMintUrl,
65
75
  isX402SettlementReconciliationReason,
66
- normaliseMintUrl,
67
76
  parseTraceparent,
68
77
  receiptPubkeyFromSecret,
69
- toLockPubkey,
70
- verifyCashuToken,
71
- verifyChallenge
72
- } from "./chunk-KMED3H3A.js";
73
- import {
74
- IMPLICIT_CREDIT_TTL_MS,
75
- computeResultHash,
76
- formatStaleness,
77
- msatsToUsd,
78
- msatsToUsdc,
79
78
  signDrainReceipt,
80
79
  signFundingReceipt,
81
80
  signReceipt,
82
- usdcToMsats
83
- } from "./chunk-NFMOPYBA.js";
81
+ toLockPubkey,
82
+ verifyChallenge
83
+ } from "./chunk-VB5OLOZH.js";
84
84
  import {
85
85
  X402_BATCH_SETTLEMENT_SCHEME,
86
86
  X402_DEFAULT_FACILITATOR,
@@ -93,25 +93,26 @@ import {
93
93
  encodePaymentRequiredHeader,
94
94
  encodeSettleResponseHeader,
95
95
  exactEvmAuthorization,
96
+ msatsToUsd,
97
+ msatsToUsdc,
96
98
  paymentRequiredV2FromV1,
97
99
  resolveRpcOverride,
100
+ usdcToMsats,
98
101
  x402NetworkToCaip2
99
- } from "./chunk-CXCQLOOK.js";
102
+ } from "./chunk-62FI3NJF.js";
100
103
  import {
101
104
  RAIL_REFUNDABLE,
102
105
  canonicalRequestPath,
106
+ canonicalize,
103
107
  isZodSchema
104
- } from "./chunk-RCM3P2HE.js";
105
- import {
106
- canonicalize
107
- } from "./chunk-OFVV37XC.js";
108
+ } from "./chunk-UKD3R2KU.js";
108
109
  import {
109
110
  createConsoleLogger,
110
111
  loggers,
111
112
  pinDimension,
112
113
  withSpan,
113
114
  withTraceContext
114
- } from "./chunk-QR2EF2NI.js";
115
+ } from "./chunk-AQ7OX5NX.js";
115
116
  import {
116
117
  StepCache
117
118
  } from "./chunk-BQJIFRAZ.js";
@@ -120,16 +121,14 @@ import {
120
121
  InvalidCurrencyError,
121
122
  UnsupportedCurrencyError,
122
123
  createFxFetcher,
123
- fxRateFor,
124
- resolveFxSourceFromEnv,
125
- validateCurrency
126
- } from "./chunk-BYCEKO65.js";
127
- import {
128
124
  fiatToSatsCeil,
125
+ fxRateFor,
129
126
  parseUsdPrice,
127
+ resolveFxSourceFromEnv,
130
128
  roundUsd,
131
- satsToFiat
132
- } from "./chunk-AT6V3SY7.js";
129
+ satsToFiat,
130
+ validateCurrency
131
+ } from "./chunk-CLIAFTUR.js";
133
132
  import {
134
133
  CreditLedger,
135
134
  CreditLedgerError,
@@ -145,30 +144,26 @@ import {
145
144
  isNonChannelBitcoinRail,
146
145
  netOwedSats,
147
146
  x402SettlementPending
148
- } from "./chunk-6XF3RVVX.js";
149
- import {
150
- withSdkInitLock
151
- } from "./chunk-COYKJRMM.js";
147
+ } from "./chunk-SPYEJXI7.js";
152
148
  import {
153
149
  withPostgresRecoveryContext
154
- } from "./chunk-P6QON7ER.js";
150
+ } from "./chunk-TRNMTTPX.js";
155
151
  import {
152
+ DvmError,
156
153
  x402NetworkByCaip2
157
154
  } from "./chunk-BPYMEMQX.js";
158
- import {
159
- TEMPO_MODERATO_CHAIN_ID,
160
- TEMPO_MODERATO_RPC,
161
- advertisedMethods,
162
- challengeMeta,
163
- installHostedTempoChargeGuard,
164
- installHostedTempoCloseGuard,
165
- isTempoInsufficientFundsError,
166
- resolveTempoNetwork
167
- } from "./chunk-IXR5RFK7.js";
168
155
  import {
169
156
  createDiagnosticCapabilityAuthority,
170
157
  diagnosticConsole
171
- } from "./chunk-ETXDTUJO.js";
158
+ } from "./chunk-LAKP6FUI.js";
159
+ import {
160
+ MemoryProcessedPaymentStore,
161
+ PostgresProcessedPaymentStore,
162
+ ProcessedPaymentReplayError
163
+ } from "./chunk-XRLKGCAW.js";
164
+ import {
165
+ withSdkInitLock
166
+ } from "./chunk-COYKJRMM.js";
172
167
 
173
168
  // src/sdk/server/lock-pubkey-store.ts
174
169
  async function initLockPubkeyTable(db) {
@@ -1973,9 +1968,10 @@ async function createX402BatchSettlementServer(opts) {
1973
1968
  throw new Error("x402 batch-settlement payTo must be a 20-byte EVM address");
1974
1969
  }
1975
1970
  const withdrawDelay = opts.config.withdrawDelay ?? X402_BATCH_MIN_WITHDRAW_DELAY_SECONDS;
1976
- if (!Number.isInteger(withdrawDelay) || withdrawDelay < X402_BATCH_MIN_WITHDRAW_DELAY_SECONDS) {
1971
+ const minimumWithdrawDelay = opts.network === X402_BATCH_SETTLEMENT_NETWORK ? 900 : X402_BATCH_MIN_WITHDRAW_DELAY_SECONDS;
1972
+ if (!Number.isInteger(withdrawDelay) || withdrawDelay < minimumWithdrawDelay) {
1977
1973
  throw new Error(
1978
- `x402 batch-settlement withdrawDelay must be at least ${String(X402_BATCH_MIN_WITHDRAW_DELAY_SECONDS)} seconds`
1974
+ `x402 batch-settlement withdrawDelay must be at least ${String(minimumWithdrawDelay)} seconds`
1979
1975
  );
1980
1976
  }
1981
1977
  if (opts.config.autoSettlement !== false && opts.config.autoSettlement?.selectRefundChannels) {
@@ -3161,10 +3157,66 @@ function isRecord(value) {
3161
3157
  return !!value && typeof value === "object" && !Array.isArray(value);
3162
3158
  }
3163
3159
 
3160
+ // src/sdk/server/payment-diagnostics.ts
3161
+ import { Errors } from "mppx";
3162
+ function paymentFailureFields(error) {
3163
+ let category = "unknown";
3164
+ try {
3165
+ if (error instanceof ProcessedPaymentReplayError) category = "replay_detected";
3166
+ else if (error instanceof CreditLedgerError) category = "ledger_refused";
3167
+ else if (error instanceof Errors.InvalidChallengeError) category = "invalid_challenge";
3168
+ else if (error instanceof Errors.MalformedCredentialError || error instanceof Errors.InvalidPayloadError) category = "malformed_credential";
3169
+ else if (error instanceof Errors.PaymentExpiredError) category = "payment_expired";
3170
+ else if (error instanceof Errors.VerificationFailedError) category = "verification_failed";
3171
+ else if (error instanceof Errors.PaymentInsufficientError || error instanceof Errors.InsufficientBalanceError) category = "insufficient_funds";
3172
+ else if (error instanceof Errors.InvalidSignatureError) category = "invalid_signature";
3173
+ else if (error instanceof Errors.PaymentMethodUnsupportedError) category = "unsupported_method";
3174
+ } catch {
3175
+ }
3176
+ return { failure_category: category, failure_stage: paymentFailureStage(error) };
3177
+ }
3178
+
3164
3179
  // src/sdk/server/payment.ts
3165
3180
  import { randomBytes, randomUUID as randomUUID2 } from "crypto";
3166
3181
  import { Challenge } from "mppx";
3167
3182
 
3183
+ // src/lib/cashu/verify.ts
3184
+ import { getTokenMetadata } from "@cashu/cashu-ts";
3185
+ function verifyCashuToken(token, acceptedMints) {
3186
+ let mint, unit, totalMsats;
3187
+ try {
3188
+ const meta = getTokenMetadata(token);
3189
+ mint = meta.mint;
3190
+ unit = meta.unit;
3191
+ totalMsats = meta.amount.toNumber() * 1e3;
3192
+ } catch {
3193
+ throw new DvmError(
3194
+ "cashu_invalid_token",
3195
+ "The Cashu token could not be decoded.",
3196
+ "Ensure the token is a valid cashuA... or cashuB... string."
3197
+ );
3198
+ }
3199
+ const normalised = acceptedMints.map(normaliseMintUrl);
3200
+ if (!normalised.includes(normaliseMintUrl(mint))) {
3201
+ throw new DvmError(
3202
+ "cashu_mint_not_accepted",
3203
+ `Mint ${mint} is not accepted by this provider.`,
3204
+ `Accepted mints: ${acceptedMints.join(", ")}`
3205
+ );
3206
+ }
3207
+ return { mint, totalMsats, unit };
3208
+ }
3209
+ function normaliseMintUrl(url) {
3210
+ try {
3211
+ const u = new URL(url);
3212
+ u.hostname = u.hostname.toLowerCase();
3213
+ u.pathname = u.pathname.replace(/\/+/g, "/").replace(/\/+$/, "") || "/";
3214
+ return u.toString().replace(/\/$/, "");
3215
+ } catch {
3216
+ return url.toLowerCase().replace(/\/+$/, "");
3217
+ }
3218
+ }
3219
+
3168
3220
  // src/sdk/server/mpp-units.ts
3169
3221
  function decimalsFor(methodName) {
3170
3222
  switch (methodName) {
@@ -3219,6 +3271,22 @@ function methodNativeAmountToDecimal(amount, methodName) {
3219
3271
  return `${nativeAmount2 / scale}.${(nativeAmount2 % scale).toString().padStart(decimals, "0")}`;
3220
3272
  }
3221
3273
 
3274
+ // src/lib/mints.ts
3275
+ function isTestMintUrl(url) {
3276
+ let host;
3277
+ try {
3278
+ host = new URL(url).hostname.toLowerCase();
3279
+ } catch {
3280
+ return false;
3281
+ }
3282
+ if (host.startsWith("[") && host.endsWith("]")) host = host.slice(1, -1);
3283
+ if (LOOPBACK_HOSTS.has(host)) return true;
3284
+ if (host.endsWith(".localhost")) return true;
3285
+ return TEST_MINT_HOSTS.has(host);
3286
+ }
3287
+ var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "0.0.0.0", "::1"]);
3288
+ var TEST_MINT_HOSTS = /* @__PURE__ */ new Set(["testnut.cashu.space", "dvmkit-testmint.fly.dev"]);
3289
+
3222
3290
  // src/sdk/server/wallet-accumulator-receive.ts
3223
3291
  import {
3224
3292
  Amount as Amount2,
@@ -3468,6 +3536,9 @@ async function issueUpfrontChallenges(mpp, requiredMsats, resourcePath, btcUsdRa
3468
3536
  );
3469
3537
  }
3470
3538
  async function verifyUpfrontPayment(opts) {
3539
+ return withPaymentDiagnostics(() => verifyUpfrontPaymentInScope(opts));
3540
+ }
3541
+ async function verifyUpfrontPaymentInScope(opts) {
3471
3542
  const {
3472
3543
  cashuToken,
3473
3544
  requiredMsats,
@@ -3733,7 +3804,10 @@ async function verifyUpfrontPayment(opts) {
3733
3804
  );
3734
3805
  } catch (err) {
3735
3806
  const mapped = mapLedgerCommitError(err, x402Requirements);
3736
- if (mapped) return mapped;
3807
+ if (mapped) {
3808
+ logCredentialRejected("x402", "upfront", err);
3809
+ return mapped;
3810
+ }
3737
3811
  logCredentialRejected("x402", "upfront", err);
3738
3812
  return {
3739
3813
  paidMsats: 0,
@@ -3794,15 +3868,15 @@ async function verifyUpfrontPayment(opts) {
3794
3868
  x402Requirements
3795
3869
  });
3796
3870
  }
3797
- const { verifyX402Payment } = await import("./x402-FT4S4JS4.js");
3798
- const receipt = await verifyX402Payment(
3871
+ const { verifyX402Payment } = await import("./x402-ZU4GML7Z.js");
3872
+ const receipt = await withPaymentStage("verifier_broadcast", () => verifyX402Payment(
3799
3873
  x402Payment,
3800
3874
  x402Config,
3801
3875
  requiredUsdcMicro,
3802
3876
  x402Resource ?? "/v1/job",
3803
3877
  rate ?? 0,
3804
3878
  x402ExactVersions
3805
- );
3879
+ ));
3806
3880
  if (receipt.verified) {
3807
3881
  const settledUsdcMicro = receipt.amountUsdcMicro;
3808
3882
  const paidMsats = settledUsdcMicro === void 0 ? receipt.amountMsats : x402SettledShare(requiredMsats, Number(requiredUsdcMicro), settledUsdcMicro);
@@ -3846,7 +3920,10 @@ async function verifyUpfrontPayment(opts) {
3846
3920
  });
3847
3921
  } catch (err) {
3848
3922
  const mapped = mapLedgerCommitError(err, x402Requirements, true);
3849
- if (mapped) return mapped;
3923
+ if (mapped) {
3924
+ logCredentialRejected("x402", "upfront", err);
3925
+ return mapped;
3926
+ }
3850
3927
  throw err;
3851
3928
  }
3852
3929
  }
@@ -3963,7 +4040,7 @@ async function verifyUpfrontPayment(opts) {
3963
4040
  challenge_id: cred.challenge.id,
3964
4041
  amount: expectedAmount
3965
4042
  },
3966
- () => mpp.broadcastCredential(mppCredential, {
4043
+ () => withPaymentStage("verifier_broadcast", () => mpp.broadcastCredential(mppCredential, {
3967
4044
  request: { amount: expectedAmount },
3968
4045
  ...opts.hostingAdmissionId && {
3969
4046
  hostedPaymentIntent: {
@@ -3982,7 +4059,8 @@ async function verifyUpfrontPayment(opts) {
3982
4059
  path: resourcePath ?? "/v1/job",
3983
4060
  nonce: challengeMeta(cred.challenge)?.nonce ?? ""
3984
4061
  }
3985
- })
4062
+ })),
4063
+ { onError: paymentFailureFields }
3986
4064
  );
3987
4065
  tempoReceipt = receipt;
3988
4066
  return receipt;
@@ -4039,7 +4117,10 @@ async function verifyUpfrontPayment(opts) {
4039
4117
  credited = accepted.result;
4040
4118
  } catch (err) {
4041
4119
  const mapped = mapLedgerCommitError(err, x402Requirements, true);
4042
- if (mapped) return mapped;
4120
+ if (mapped) {
4121
+ logCredentialRejected("tempo", "upfront", err);
4122
+ return mapped;
4123
+ }
4043
4124
  throw err;
4044
4125
  }
4045
4126
  } else {
@@ -4070,7 +4151,7 @@ async function verifyUpfrontPayment(opts) {
4070
4151
  if (consumedCredentialStore) {
4071
4152
  const realm = mpp.realm;
4072
4153
  const id = cred.challenge.id;
4073
- if (await consumedCredentialStore.has(realm, id)) {
4154
+ if (await withPaymentStage("replay_store", () => consumedCredentialStore.has(realm, id))) {
4074
4155
  const mppChallenges = await issueUpfrontChallenges(
4075
4156
  mpp,
4076
4157
  requiredMsats,
@@ -4094,7 +4175,7 @@ async function verifyUpfrontPayment(opts) {
4094
4175
  };
4095
4176
  }
4096
4177
  if (!sessionBasis) {
4097
- await consumedCredentialStore.mark(realm, id, CONSUMED_CREDENTIAL_TTL_MS / 1e3);
4178
+ await withPaymentStage("replay_store", () => consumedCredentialStore.mark(realm, id, CONSUMED_CREDENTIAL_TTL_MS / 1e3));
4098
4179
  }
4099
4180
  }
4100
4181
  if (ledgerCtx) {
@@ -4109,16 +4190,19 @@ async function verifyUpfrontPayment(opts) {
4109
4190
  });
4110
4191
  } catch (err) {
4111
4192
  const mapped = mapLedgerCommitError(err, x402Requirements, true);
4112
- if (mapped) return mapped;
4193
+ if (mapped) {
4194
+ logCredentialRejected("tempo", "upfront", err);
4195
+ return mapped;
4196
+ }
4113
4197
  throw err;
4114
4198
  }
4115
4199
  }
4116
4200
  if (sessionBasis && consumedCredentialStore) {
4117
- await consumedCredentialStore.mark(
4201
+ await withPaymentStage("replay_store", () => consumedCredentialStore.mark(
4118
4202
  mpp.realm,
4119
4203
  cred.challenge.id,
4120
4204
  CONSUMED_CREDENTIAL_TTL_MS / 1e3
4121
- );
4205
+ ));
4122
4206
  }
4123
4207
  if (credited) {
4124
4208
  await mpp.completeHostedTempoCharge?.(cred.challenge.id).catch((error) => {
@@ -4687,6 +4771,9 @@ function buildPaymentErrorResponse(body, challenges, x402Requirements, status, x
4687
4771
  return new Response(JSON.stringify(mergedBody), { status: status ?? 402, headers });
4688
4772
  }
4689
4773
  async function verifyIncomingPayment(body, opts, snapshot) {
4774
+ return withPaymentDiagnostics(() => verifyIncomingPaymentInScope(body, opts, snapshot));
4775
+ }
4776
+ async function verifyIncomingPaymentInScope(body, opts, snapshot) {
4690
4777
  if (body.type !== "payment") return {};
4691
4778
  if (body.content.cashu_token) {
4692
4779
  if (opts.cashuMode === "p2pk-accumulator" && (opts.accumulatorDb || opts.disposableCashu) && opts.dvmId && opts.lockPubkeys && opts.lockPubkeys.length > 0) {
@@ -4769,15 +4856,15 @@ async function verifyIncomingPayment(body, opts, snapshot) {
4769
4856
  snapshot
4770
4857
  });
4771
4858
  }
4772
- const { verifyX402Payment } = await import("./x402-FT4S4JS4.js");
4773
- const receipt = await verifyX402Payment(
4859
+ const { verifyX402Payment } = await import("./x402-ZU4GML7Z.js");
4860
+ const receipt = await withPaymentStage("verifier_broadcast", () => verifyX402Payment(
4774
4861
  body.content.x402_payment,
4775
4862
  opts.x402Config,
4776
4863
  requiredUsdcMicro,
4777
4864
  opts.resourcePath ?? "/v1/job",
4778
4865
  rate,
4779
4866
  opts.x402ExactVersions
4780
- );
4867
+ ));
4781
4868
  if (!receipt.verified) {
4782
4869
  return {
4783
4870
  error: {
@@ -4826,6 +4913,7 @@ async function verifyIncomingPayment(body, opts, snapshot) {
4826
4913
  } catch (err) {
4827
4914
  const mapped = mapLedgerCommitError(err, void 0, true);
4828
4915
  if (mapped?.error) {
4916
+ logCredentialRejected("x402", "mid-job", err);
4829
4917
  return { error: { body: mapped.error.body, status: mapped.error.status } };
4830
4918
  }
4831
4919
  throw err;
@@ -4933,13 +5021,14 @@ async function verifyIncomingPayment(body, opts, snapshot) {
4933
5021
  challenge_id: credential.challenge.id,
4934
5022
  amount: expectedAmount
4935
5023
  },
4936
- () => mppServer.broadcastCredential(credential, {
5024
+ () => withPaymentStage("verifier_broadcast", () => mppServer.broadcastCredential(credential, {
4937
5025
  request: { amount: expectedAmount },
4938
5026
  ...opts.hostingPaymentSeq !== void 0 && {
4939
5027
  hostedPaymentIntent: { jobId: opts.jobId, paymentSeq: opts.hostingPaymentSeq }
4940
5028
  },
4941
5029
  ...expectedMeta && { meta: expectedMeta }
4942
- })
5030
+ })),
5031
+ { onError: paymentFailureFields }
4943
5032
  );
4944
5033
  let credited;
4945
5034
  if (ledgerCtx) {
@@ -4948,6 +5037,7 @@ async function verifyIncomingPayment(body, opts, snapshot) {
4948
5037
  } catch (err) {
4949
5038
  const mapped = mapLedgerCommitError(err, void 0, true);
4950
5039
  if (mapped?.error) {
5040
+ logCredentialRejected("tempo", "mid-job", err);
4951
5041
  return { error: { body: mapped.error.body, status: mapped.error.status } };
4952
5042
  }
4953
5043
  throw err;
@@ -5142,6 +5232,9 @@ function applyPaymentInfoToJob(job, info) {
5142
5232
  creditPendingPayment(job);
5143
5233
  }
5144
5234
  async function processIncomingPayment(job, body, opts) {
5235
+ return withPaymentDiagnostics(() => processIncomingPaymentInScope(job, body, opts));
5236
+ }
5237
+ async function processIncomingPaymentInScope(job, body, opts) {
5145
5238
  if (body.type !== "payment") return null;
5146
5239
  if (body.content.cashu_token) {
5147
5240
  if (opts.cashuMode === "p2pk-accumulator" && (opts.accumulatorDb || opts.disposableCashu) && opts.dvmId && opts.lockPubkeys && opts.lockPubkeys.length > 0) {
@@ -5194,15 +5287,15 @@ async function processIncomingPayment(job, body, opts) {
5194
5287
  try {
5195
5288
  const requiredMsats = job.pendingPaymentMsats ?? 0;
5196
5289
  const requiredUsdcMicro = job.pendingX402AmountUsdcMicro !== void 0 ? BigInt(job.pendingX402AmountUsdcMicro) : BigInt(msatsToUsdc(requiredMsats, rate));
5197
- const { verifyX402Payment } = await import("./x402-FT4S4JS4.js");
5198
- const receipt = await verifyX402Payment(
5290
+ const { verifyX402Payment } = await import("./x402-ZU4GML7Z.js");
5291
+ const receipt = await withPaymentStage("verifier_broadcast", () => verifyX402Payment(
5199
5292
  body.content.x402_payment,
5200
5293
  opts.x402Config,
5201
5294
  requiredUsdcMicro,
5202
5295
  opts.resourcePath ?? "/v1/job",
5203
5296
  rate,
5204
5297
  opts.x402ExactVersions
5205
- );
5298
+ ));
5206
5299
  if (receipt.verified) {
5207
5300
  if (job.pendingX402Nonce !== void 0) {
5208
5301
  const incomingNonce = decodePayment(body.content.x402_payment).payload.authorization.nonce;
@@ -5269,13 +5362,14 @@ async function processIncomingPayment(job, body, opts) {
5269
5362
  challenge_id: credential.challenge.id,
5270
5363
  amount: expectedAmount
5271
5364
  },
5272
- () => mppHandle.broadcastCredential(credential, {
5365
+ () => withPaymentStage("verifier_broadcast", () => mppHandle.broadcastCredential(credential, {
5273
5366
  request: { amount: expectedAmount },
5274
5367
  ...opts.hostingPaymentSeq !== void 0 && {
5275
5368
  hostedPaymentIntent: { jobId: opts.jobId, paymentSeq: opts.hostingPaymentSeq }
5276
5369
  },
5277
5370
  ...expectedMeta && { meta: expectedMeta }
5278
- })
5371
+ })),
5372
+ { onError: paymentFailureFields }
5279
5373
  );
5280
5374
  if (!job.pendingMppChallengeIds?.includes(credential.challenge.id)) {
5281
5375
  return {
@@ -5643,8 +5737,7 @@ async function resolveTopUpLedgerContext(opts, snapshot, binding) {
5643
5737
  if (!denomination.ok) {
5644
5738
  logSkip("denomination_unavailable", {
5645
5739
  currency,
5646
- cause: denomination.reason,
5647
- ...denomination.detail !== void 0 && { detail: denomination.detail }
5740
+ cause: denomination.reason
5648
5741
  });
5649
5742
  return void 0;
5650
5743
  }
@@ -5793,6 +5886,9 @@ function withDrawBasis(info, ctx, committed) {
5793
5886
  };
5794
5887
  }
5795
5888
  async function fundAndDraw(ctx, funding, tx) {
5889
+ return withPaymentStage("funding_ledger", () => fundAndDrawInScope(ctx, funding, tx));
5890
+ }
5891
+ async function fundAndDrawInScope(ctx, funding, tx) {
5796
5892
  const env = ctx.creditEnvelope;
5797
5893
  const fundedMicro = funding.fundedMicro ?? fundedMicroFor(ctx.priceFiat, funding.paidMsats, ctx.requiredMsats);
5798
5894
  const shortMidJob = ctx.midJob === true && funding.paidMsats < ctx.requiredMsats;
@@ -6219,7 +6315,7 @@ async function commitMarkedFunding(ctx, funding, outerTx) {
6219
6315
  const env = ctx.creditEnvelope;
6220
6316
  const creditId = ctx.fundOnly?.creditId ?? ctx.topUp?.creditId ?? env?.creditId ?? implicitCreditId(funding.rail, funding.paymentId);
6221
6317
  const drawId = ctx.fundOnly?.fundId ?? ctx.topUp?.drawId ?? env?.drawId ?? funding.paymentId;
6222
- await store.record({
6318
+ await withPaymentStage("replay_store", () => store.record({
6223
6319
  dvmId: ctx.dvmId,
6224
6320
  rail: funding.rail,
6225
6321
  paymentId: funding.paymentId,
@@ -6227,10 +6323,10 @@ async function commitMarkedFunding(ctx, funding, outerTx) {
6227
6323
  drawId,
6228
6324
  jobId: ctx.jobId,
6229
6325
  tx
6230
- });
6326
+ }));
6231
6327
  return fundAndDraw(ctx, funding, tx);
6232
6328
  };
6233
- return outerTx ? commit(outerTx) : store.withTx(commit);
6329
+ return outerTx ? commit(outerTx) : withPaymentStage("replay_store", () => store.withTx(commit));
6234
6330
  }
6235
6331
  async function commitMppFunding(ctx, credential, funding) {
6236
6332
  const session = mppSessionBasis(credential);
@@ -6592,15 +6688,14 @@ function x402NotOfferedResult(currency) {
6592
6688
  error: x402NotOfferedPaymentError(currency)
6593
6689
  };
6594
6690
  }
6595
- function logCredentialRejected(rail, phase, _err) {
6691
+ function logCredentialRejected(rail, phase, err) {
6596
6692
  diagnosticConsole.warn(
6597
6693
  {
6598
6694
  level: "warn",
6599
6695
  event: `${rail}_credential_rejected`,
6600
6696
  phase,
6601
6697
  rail,
6602
- error_name: void 0,
6603
- error_message: void 0
6698
+ ...paymentFailureFields(err)
6604
6699
  }
6605
6700
  );
6606
6701
  }
@@ -16524,7 +16619,7 @@ import {
16524
16619
  Amount as Amount3,
16525
16620
  CheckStateEnum as CheckStateEnum3,
16526
16621
  getP2PKExpectedWitnessPubkeys as getP2PKExpectedWitnessPubkeys2,
16527
- getTokenMetadata
16622
+ getTokenMetadata as getTokenMetadata2
16528
16623
  } from "@cashu/cashu-ts";
16529
16624
  function installAdminCreditRoutes(app, opts) {
16530
16625
  app.get("/admin/credit/pending-drains", (c) => handlePendingDrains(c, opts));
@@ -16885,7 +16980,7 @@ async function handleParkDrain(c, opts) {
16885
16980
  }
16886
16981
  let parsed;
16887
16982
  try {
16888
- const meta = getTokenMetadata(token);
16983
+ const meta = getTokenMetadata2(token);
16889
16984
  parsed = {
16890
16985
  mint: meta.mint,
16891
16986
  faceSats: Amount3.from(meta.amount).toNumber(),
@@ -19422,7 +19517,7 @@ async function createDVMServer(descriptor, opts) {
19422
19517
  }
19423
19518
  }
19424
19519
  if (!opts.onJobCompleted && platformToken && platformUrl && dvmId && opts.db) {
19425
- const { RevenueReporter } = await import("./revenue-reporter-MAERPYGK.js");
19520
+ const { RevenueReporter } = await import("./revenue-reporter-7UR3W2SD.js");
19426
19521
  const reporter = new RevenueReporter(
19427
19522
  opts.db,
19428
19523
  platformUrl,
@@ -19432,7 +19527,7 @@ async function createDVMServer(descriptor, opts) {
19432
19527
  revenueReporter = reporter;
19433
19528
  await reporter.init();
19434
19529
  reporter.startRetryLoop();
19435
- const { MemoryX402BatchStore, PayoutReporter } = await import("./payout-reporter-3Y2U55ZX.js");
19530
+ const { MemoryX402BatchStore, PayoutReporter } = await import("./payout-reporter-WT7XYW42.js");
19436
19531
  payoutReporter = new PayoutReporter({
19437
19532
  dvmId,
19438
19533
  db: opts.db,
@@ -22848,6 +22943,7 @@ export {
22848
22943
  derivedFundCreditId,
22849
22944
  drawSettlementRef,
22850
22945
  rateUnavailablePaymentError,
22946
+ isTestMintUrl,
22851
22947
  X402_BATCH_SETTLEMENT_NETWORK,
22852
22948
  X402_BATCH_SETTLEMENT_MAINNET_NETWORK,
22853
22949
  X402_BATCH_MIN_WITHDRAW_DELAY_SECONDS,