@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.
- package/dist/card-charge-journal-SKMBEPRM.js +44 -0
- package/dist/{chunk-MA55LUNR.js → chunk-2WWVI32F.js} +55 -1
- package/dist/{chunk-3V6CSTWB.js → chunk-3DGIRHP2.js} +2 -2
- package/dist/{chunk-WWKFG6TM.js → chunk-5NMHZIIU.js} +1 -1
- package/dist/{chunk-FAT57DAP.js → chunk-5YJWAJ4N.js} +1 -1
- package/dist/{chunk-D2MGOQIS.js → chunk-CUWSJQGT.js} +1 -1
- package/dist/{chunk-6GZF7VDO.js → chunk-DLRPKEAM.js} +1 -1
- package/dist/{chunk-62JG4AF7.js → chunk-DY5QIHJA.js} +1 -1
- package/dist/{chunk-LWF4ABYF.js → chunk-EHBUAJ5M.js} +1 -1
- package/dist/{chunk-IUFVIIPF.js → chunk-EQIP6TFD.js} +1 -1
- package/dist/{chunk-ZBOCNF56.js → chunk-GDZXGB43.js} +3 -3
- package/dist/{chunk-2HSWWHXK.js → chunk-HEH7YUGE.js} +1 -1
- package/dist/{chunk-B27E7JIR.js → chunk-HVZIITWW.js} +27 -4
- package/dist/{chunk-VIAMJ6GS.js → chunk-JINZMDNK.js} +1224 -80
- package/dist/{chunk-NRE4NOCY.js → chunk-JMTLK2SZ.js} +1 -1
- package/dist/{chunk-LSANCGLP.js → chunk-L35WYOH2.js} +1 -1
- package/dist/{chunk-27QB2D3Z.js → chunk-LCNRFKP7.js} +2 -2
- package/dist/{chunk-2AGADOX3.js → chunk-QMKGYIBM.js} +1 -1
- package/dist/{chunk-JOSNSNS7.js → chunk-SEIMPHIP.js} +225 -11
- package/dist/{chunk-Y746QPX7.js → chunk-SQOVLAJ2.js} +1 -1
- package/dist/{chunk-XWG54M6T.js → chunk-UVRBD5GR.js} +1 -1
- package/dist/{chunk-5RGZN6WQ.js → chunk-XB644VN3.js} +1 -1
- package/dist/{chunk-2RZRYMCR.js → chunk-YNHFJE6U.js} +1 -1
- package/dist/{chunk-7KNFEDFW.js → chunk-ZH5CLGO6.js} +1 -1
- package/dist/{content-retention-efjireLM.d.ts → content-retention-DEvY5vjM.d.ts} +1 -1
- package/dist/{credit-ledger-M3EBVMOP.js → credit-ledger-S76KU53A.js} +11 -3
- package/dist/{credit-menu-UOOxuxVL.d.ts → credit-menu-BA2my6hE.d.ts} +229 -8
- package/dist/{fx-BtxHVj6w.d.ts → fx-J5oXbv9A.d.ts} +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +4 -4
- package/dist/internal/caller.d.ts +10 -9
- package/dist/internal/caller.js +11 -11
- package/dist/internal/server.d.ts +7 -7
- package/dist/internal/server.js +21 -21
- package/dist/{job-store-DWVkleH3.d.ts → job-store-CjPnf0dd.d.ts} +1 -1
- package/dist/{lightning-backend-CTijN35u.d.ts → lightning-backend-D9Q2KDS-.d.ts} +1 -1
- package/dist/{memory-credit-ledger-WL2VKLE3.js → memory-credit-ledger-5KXHOWB2.js} +4 -4
- package/dist/{mpp-setup-DBYDXISN.js → mpp-setup-3YZMURZL.js} +3 -3
- package/dist/{payout-reporter-D5TCIBQA.js → payout-reporter-KTLBNJJ7.js} +2 -2
- package/dist/{postgres-consumed-credential-store-IPWPJ6V7.js → postgres-consumed-credential-store-Y336KNIB.js} +1 -1
- package/dist/{postgres-job-store-POZJNFJU.js → postgres-job-store-ESEAN7JL.js} +2 -2
- package/dist/{postgres-replay-store-JQYAKG47.js → postgres-replay-store-6SVCZ475.js} +2 -2
- package/dist/{pricing-FGPVRNTL.js → pricing-RP5CGW6I.js} +3 -3
- package/dist/{revenue-reporter-QKCBYFWT.js → revenue-reporter-FD3GDQZS.js} +2 -2
- package/dist/server/index.d.ts +20 -11
- package/dist/server/index.js +292 -28
- package/dist/{step-cache-Bx_ZybWF.d.ts → step-cache-DXFftnAc.d.ts} +154 -12
- package/dist/{tempo-charge-store-P7ZBR3GG.js → tempo-charge-store-SOIRMEFJ.js} +2 -2
- package/dist/{tempo-session-store-ZVRBAMLG.js → tempo-session-store-UBDFFHDG.js} +3 -3
- package/dist/testing/index.d.ts +3 -3
- package/dist/testing/index.js +6 -6
- package/dist/{usd-eOAMEO12.d.ts → usd-Bc_rva_K.d.ts} +1 -1
- package/dist/{x402-44JZJQ5F.js → x402-MFBRORHG.js} +5 -5
- package/package.json +1 -1
- package/dist/{chunk-NUDHO4HV.js → chunk-LABJSMSJ.js} +48 -48
package/dist/server/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
PostgresReplayStore
|
|
3
|
-
} from "../chunk-
|
|
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-
|
|
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-
|
|
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-
|
|
93
|
-
import "../chunk-
|
|
95
|
+
import "../chunk-DY5QIHJA.js";
|
|
96
|
+
import "../chunk-3DGIRHP2.js";
|
|
94
97
|
import {
|
|
95
98
|
MemoryCreditLedger
|
|
96
|
-
} from "../chunk-
|
|
99
|
+
} from "../chunk-HVZIITWW.js";
|
|
97
100
|
import {
|
|
98
101
|
PostgresJobStore
|
|
99
|
-
} from "../chunk-
|
|
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-
|
|
109
|
+
} from "../chunk-DLRPKEAM.js";
|
|
107
110
|
import {
|
|
108
111
|
isStreamableJobStore
|
|
109
|
-
} from "../chunk-
|
|
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-
|
|
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-
|
|
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-
|
|
135
|
+
import "../chunk-JMTLK2SZ.js";
|
|
133
136
|
import "../chunk-FUJ36YDV.js";
|
|
134
137
|
import "../chunk-BQJIFRAZ.js";
|
|
135
|
-
import "../chunk-
|
|
136
|
-
import "../chunk-
|
|
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-
|
|
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-
|
|
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-
|
|
168
|
+
} from "../chunk-LCNRFKP7.js";
|
|
165
169
|
import {
|
|
166
170
|
initLoggers
|
|
167
|
-
} from "../chunk-
|
|
171
|
+
} from "../chunk-ZH5CLGO6.js";
|
|
168
172
|
import "../chunk-66HGCPBU.js";
|
|
169
173
|
import {
|
|
170
174
|
diagnosticConsole
|
|
171
|
-
} from "../chunk-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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,
|