@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.
- package/README.md +10 -2
- package/dist/{chunk-ANFX5HEG.js → chunk-2UUXIIOC.js} +43 -13
- package/dist/{chunk-C6JHBLMW.js → chunk-BIP6G74V.js} +1 -1
- package/dist/{chunk-EDDYHZ6W.js → chunk-CEOAHV2I.js} +0 -30
- package/dist/{chunk-TSWKITGR.js → chunk-CGKZDODG.js} +8 -1
- package/dist/{chunk-DBCLBYHP.js → chunk-KVEHHC7W.js} +11 -1
- package/dist/{chunk-VRQDX5P4.js → chunk-KXCKFIJI.js} +30 -0
- package/dist/{chunk-5GFED3GJ.js → chunk-M7LHFJ5K.js} +49 -6
- package/dist/{chunk-7AKBC4PW.js → chunk-TQWGQCNV.js} +1 -1
- package/dist/{chunk-QK3VJNCK.js → chunk-UB5FZ43T.js} +339 -212
- package/dist/{credit-menu-C1ezIFlJ.d.ts → credit-menu-s5HmGCqx.d.ts} +64 -21
- package/dist/{fx-C6dl2LVI.d.ts → fx-D860pZvP.d.ts} +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/internal/caller.d.ts +31 -11
- package/dist/internal/caller.js +23 -11
- package/dist/internal/index.js +1 -1
- package/dist/internal/server.d.ts +8 -8
- package/dist/internal/server.js +4 -4
- package/dist/{job-store-DHnW4Cg_.d.ts → job-store-BUGqvCfL.d.ts} +1 -1
- package/dist/{lightning-backend-Ci1nogk_.d.ts → lightning-backend-BozcevPZ.d.ts} +1 -1
- package/dist/{memory-credit-ledger-OP24Z2KO.js → memory-credit-ledger-MNUOTQO5.js} +1 -1
- package/dist/{mpp-setup-MOBWGTWJ.js → mpp-setup-4FJD6ZHV.js} +11 -1
- package/dist/server/index.d.ts +12 -13
- package/dist/server/index.js +215 -51
- package/dist/{step-cache-BLPZNizw.d.ts → step-cache-5dljDqrQ.d.ts} +4 -2
- package/dist/{tempo-lifecycle-SQL3KLEZ.js → tempo-lifecycle-DFIXQ54Q.js} +3 -3
- package/dist/{tempo-wallet-QOLEIPCV.js → tempo-wallet-4QKSV65O.js} +10 -2
- package/dist/testing/index.d.ts +2 -2
- package/dist/{usd-BgOfZlk6.d.ts → usd-DoRuAckA.d.ts} +1 -1
- package/dist/{x402-T2C5MX3T.js → x402-5H27DCBE.js} +2 -2
- 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-
|
|
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-
|
|
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-
|
|
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.
|
|
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-
|
|
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-
|
|
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-
|
|
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)
|
|
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)
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
16617
|
-
|
|
16618
|
-
|
|
16619
|
-
|
|
16620
|
-
|
|
16621
|
-
|
|
16622
|
-
|
|
16623
|
-
|
|
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
|
-
|
|
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
|
-
|
|
16632
|
-
|
|
16633
|
-
|
|
16634
|
-
|
|
16635
|
-
|
|
16636
|
-
|
|
16637
|
-
|
|
16638
|
-
|
|
16639
|
-
|
|
16640
|
-
|
|
16641
|
-
|
|
16642
|
-
|
|
16643
|
-
|
|
16644
|
-
|
|
16645
|
-
|
|
16646
|
-
|
|
16647
|
-
|
|
16648
|
-
|
|
16649
|
-
|
|
16650
|
-
|
|
16651
|
-
|
|
16652
|
-
|
|
16653
|
-
|
|
16654
|
-
|
|
16655
|
-
|
|
16656
|
-
|
|
16657
|
-
|
|
16658
|
-
|
|
16659
|
-
|
|
16660
|
-
|
|
16661
|
-
|
|
16662
|
-
|
|
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
|
-
|
|
16683
|
-
|
|
16684
|
-
|
|
16685
|
-
|
|
16686
|
-
|
|
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
|
-
|
|
16758
|
-
|
|
16759
|
-
|
|
16760
|
-
|
|
16761
|
-
|
|
16762
|
-
|
|
16763
|
-
|
|
16764
|
-
|
|
16765
|
-
|
|
16766
|
-
|
|
16767
|
-
|
|
16768
|
-
|
|
16769
|
-
|
|
16770
|
-
|
|
16771
|
-
|
|
16772
|
-
|
|
16773
|
-
|
|
16774
|
-
|
|
16775
|
-
|
|
16776
|
-
|
|
16777
|
-
|
|
16778
|
-
|
|
16779
|
-
|
|
16780
|
-
|
|
16781
|
-
|
|
16782
|
-
|
|
16783
|
-
|
|
16784
|
-
|
|
16785
|
-
|
|
16786
|
-
|
|
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
|
-
|
|
16790
|
-
|
|
16791
|
-
|
|
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
|
-
|
|
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.
|
|
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())
|
|
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,
|