@dvmkit/sdk 0.1.0-rc.1 → 0.1.0-rc.2
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/{chunk-RPXHKMYE.js → chunk-365P52XQ.js} +346 -33
- package/dist/{chunk-NTK5DJ6R.js → chunk-OJ5WFIB2.js} +11 -1
- package/dist/{credit-ledger-EDMEZSA2.js → credit-ledger-RO4FGSHG.js} +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/{job-store-C5n6bhap.d.ts → job-store-6gR4pZRP.d.ts} +279 -19
- package/dist/{memory-credit-ledger-7TTZDSRS.js → memory-credit-ledger-I2G64DDK.js} +2 -2
- package/dist/payout-reporter-4TNWRS5F.js +753 -0
- package/dist/{revenue-reporter-M35KP6V7.js → revenue-reporter-GB4WKLDC.js} +77 -2
- package/dist/server/index.d.ts +64 -4
- package/dist/server/index.js +203 -25
- package/dist/{ssrf-BdHsrrIb.d.ts → ssrf-DZi-xJyn.d.ts} +1 -1
- package/dist/testing/index.d.ts +1 -1
- package/package.json +1 -1
|
@@ -8,7 +8,9 @@ var ENDPOINTS = {
|
|
|
8
8
|
revenue: "/_internal/job-revenue",
|
|
9
9
|
deposit: "/_internal/credit-deposit",
|
|
10
10
|
release: "/_internal/credit-draw-release",
|
|
11
|
-
drain: "/_internal/credit-drain"
|
|
11
|
+
drain: "/_internal/credit-drain",
|
|
12
|
+
payout: "/_internal/payout",
|
|
13
|
+
expiry_release: "/_internal/credit-expiry-release"
|
|
12
14
|
};
|
|
13
15
|
var RevenueReporter = class _RevenueReporter {
|
|
14
16
|
// 24h of failed retries
|
|
@@ -83,6 +85,79 @@ var RevenueReporter = class _RevenueReporter {
|
|
|
83
85
|
async enqueueCreditDrain(tx, payload) {
|
|
84
86
|
await this.insertPending(tx, "drain", payload);
|
|
85
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* Join a payout to the transaction that commits the movement it reports
|
|
90
|
+
* (internal-review) — the batch close, the accumulator mark, the drain booking.
|
|
91
|
+
* No network I/O, only the durable queue row through `tx`, the discipline
|
|
92
|
+
* {@link enqueueCreditDrain} set and for the same reason: the money has
|
|
93
|
+
* already moved on a rail this ledger does not own, so the platform row is
|
|
94
|
+
* the only record the builder's dashboard has of it, and a row lost between
|
|
95
|
+
* the fact and the queue would understate "paid out" forever. Without `tx`
|
|
96
|
+
* the row is queued on the pool, for callers with no fact of their own to
|
|
97
|
+
* commit. Idempotent on `(dvmId, payoutId)` platform-side, so the retry
|
|
98
|
+
* loop redelivers freely.
|
|
99
|
+
*/
|
|
100
|
+
async enqueuePayout(payload, tx) {
|
|
101
|
+
await this.insertPending(tx ?? this.db, "payout", payload);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Report one landed payout on its own and try to deliver it at once — the
|
|
105
|
+
* live Tempo settlement, which has no dvmkit transaction to join. Durable
|
|
106
|
+
* like {@link report}.
|
|
107
|
+
*/
|
|
108
|
+
async reportPayout(payload) {
|
|
109
|
+
return this.enqueue("payout", payload, payload.payoutId);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Report one rail's pending-pool snapshot (internal-review). Best-effort and
|
|
113
|
+
* fire-and-forget, deliberately unlike {@link reportPayout}: a snapshot is
|
|
114
|
+
* replaced by the next tick, so queueing a stale one behind an outage would
|
|
115
|
+
* only deliver figures the platform already has newer ones for.
|
|
116
|
+
*/
|
|
117
|
+
async reportPayoutPending(payload) {
|
|
118
|
+
const url = `${this.platformUrl}/_internal/payout-pending`;
|
|
119
|
+
try {
|
|
120
|
+
const res = await fetch(url, {
|
|
121
|
+
method: "POST",
|
|
122
|
+
headers: {
|
|
123
|
+
"Content-Type": "application/json",
|
|
124
|
+
Authorization: `Bearer ${this.platformToken}`
|
|
125
|
+
},
|
|
126
|
+
body: JSON.stringify(payload),
|
|
127
|
+
signal: AbortSignal.timeout(1e4)
|
|
128
|
+
});
|
|
129
|
+
if (!res.ok) {
|
|
130
|
+
console.warn(
|
|
131
|
+
JSON.stringify({
|
|
132
|
+
level: "payout_pending_report_failed",
|
|
133
|
+
rail: payload.rail,
|
|
134
|
+
status: res.status
|
|
135
|
+
})
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
} catch (err) {
|
|
139
|
+
console.warn(
|
|
140
|
+
JSON.stringify({
|
|
141
|
+
level: "payout_pending_report_failed",
|
|
142
|
+
rail: payload.rail,
|
|
143
|
+
error: err instanceof Error ? err.message : String(err)
|
|
144
|
+
})
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Join a credit-expiry release — or the revival that reverses one — to the
|
|
150
|
+
* transaction that made it true (internal-review).
|
|
151
|
+
*
|
|
152
|
+
* Same discipline as {@link enqueueCreditDrain}: no network I/O, only the
|
|
153
|
+
* durable queue row written through `tx`. A release whose row was lost after
|
|
154
|
+
* the sweep committed would understate committed value forever; a lost
|
|
155
|
+
* reversal would overstate it, which is the worse direction — the builder
|
|
156
|
+
* would see money as theirs that a revived credit can still buy work with.
|
|
157
|
+
*/
|
|
158
|
+
async enqueueCreditExpiryRelease(tx, payload) {
|
|
159
|
+
await this.insertPending(tx, "expiry_release", payload);
|
|
160
|
+
}
|
|
86
161
|
/**
|
|
87
162
|
* Report a reaper-force-failed paid job to the platform (internal-review) so the
|
|
88
163
|
* operator receives an ambient notice that a DVM died or wedged mid-job.
|
|
@@ -325,7 +400,7 @@ var RevenueReporter = class _RevenueReporter {
|
|
|
325
400
|
[Date.now()]
|
|
326
401
|
);
|
|
327
402
|
for (const row of rows) {
|
|
328
|
-
const label = row.payload.jobId ?? row.payload.creditId ?? row.id;
|
|
403
|
+
const label = row.payload.jobId ?? row.payload.creditId ?? row.payload.payoutId ?? row.id;
|
|
329
404
|
try {
|
|
330
405
|
await this.attemptDelivery(row.id, row.payload, row.kind, label);
|
|
331
406
|
} catch {
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { X as CashuMode, R as ResolvedCreditConfig, Y as FundingMethod, _ as CreditLedgerLike, $ as CreditSnapshot, g as CreditView, a0 as CreditInvoiceRecord, a1 as CreditDepositEnqueue, a2 as InvoiceSettlement, Z as ZodLike, a as DVMDescriptor, K as KVStore, o as JobStore, a3 as MppxServer, a4 as X402Config, p as PaymentMethod, a5 as ClientCompatibilityGate, a6 as Message, a7 as FundingReceipt, a8 as TopUpCapUnenforcedReason, a9 as JobReceipt, aa as AppendOutgoingOptions, S as SDKJobContext, ab as StepCache, v as ResponseContent, P as PaymentContent, ac as X402Receipt, ad as X402ExactVersionSupport, ae as X402SettlementIntent, af as X402FacilitatorAuth, ag as X402BatchSettlementConfig, ah as PostgresX402ChannelStorage, ai as PaymentRequirementsV2, aj as CreditLedgerQuerier, ak as X402SettlementCursor, al as X402SettlementStatus, am as X402SettlementWriteOff, an as X402RefundSettlementGate, ao as MppxCredential, J as JobRecord, ap as ReceiptCredit, aq as DrainReceiptEvent, ar as DrainReceipt, z as SignedRequestAudience, as as CreditDrawReleaseEnqueue, at as CreditDepositPayload, au as RevenueSkippedNoRailPayload, av as MessageType, aw as ClientCompatibility, ax as CreditDrainEnqueue, ay as DVMAuthScheme, B as SignedRequestDomain, az as DrawResult, aA as X402UnresolvedRefund, aB as GrownDrawResult, aC as DrawResolution, aD as FundingRecord, aE as BlockedInvoiceCursor, aF as InvoiceReconciliation, aG as InvoiceWriteOff, aH as DrawRecord, aI as StalePendingDrawCursor, aJ as TempoCreditLossEvidence, aK as TempoCreditLoss, aL as X402CreditLossEvidence, aM as X402CreditLoss, aN as DrainMethod, aO as DrainRequestResult, aP as BitcoinDepositLiability, aQ as FundingLot, aR as CreditDrainRecord, aS as ChannelDrainCursor, aT as DrainWriteOff, aU as DrainReleaseResult, aV as DrainFulfilment, aW as DrainTransitionResult, aX as StreamableJobStore, aY as ReceiptIssuingStore, aZ as RequestIdClaim, a_ as RequestIdClaimResult, a$ as OutgoingMessage, b0 as PaymentCreditDelta, b1 as VerifyAndCreditResult, b2 as JobCounters, G as SignedRequestReplayStore } from '../job-store-
|
|
2
|
-
export { b3 as CLIENT_COMPATIBILITY_HEADERS, d as CanonicalEnvelope, b4 as ClientCompatibilityEnv, b5 as ClientCompatibilityRequirement, b6 as ClientSemVer, e as CreateSignedRequestVerifierOpts, b7 as CreditFundingBasis, b8 as CreditInvoiceStatus, b9 as CreditLedger, ba as CreditLedgerError, bb as CreditLedgerErrorCode, bc as CreditLedgerErrorDetails, bd as CreditLedgerPool, be as CreditStatus, bf as DRAIN_DELIVERY_RESERVE_SATS, bg as DVM_PROTOCOL_VERSION, bh as DrainConflictReason, bi as DrawRailValue, bj as DrawStatus, n as JobStatus, bk as ReplayStoreBackend, bl as RevenueSkippedNoRailReason, x as SIGNED_REQUEST_AUTH_ID, y as SIGNED_REQUEST_STATEMENT_VERSION, bm as Secp256k1AuthOpts, E as SignedRequestError, F as SignedRequestFailure, H as SignedRequestSignOpts, M as SignedRequestStatementHeader, N as SignedRequestVerifier, bn as X402ChannelStorageOpts, bo as X402RelayLockHolder, bp as X402RelaySubmissionLock, bq as X402RelaySubmissionLockError, br as allocateDrawValue, bs as clientCompatibilityAttributes, bt as clientCompatibilityMiddleware, bu as clientUpgradeRequired, O as createSignedRequestVerifier, bv as isStreamableJobStore, bw as parseClientCapabilities, bx as parseClientCompatibility, by as parseDvmClient, bz as parseProtocolVersion, bA as requireClientCompatibility, bB as secp256k1Auth, bC as signedRequestInput, V as signedRequestStatementHeader } from '../job-store-
|
|
1
|
+
import { X as CashuMode, R as ResolvedCreditConfig, Y as FundingMethod, _ as CreditLedgerLike, $ as CreditSnapshot, g as CreditView, a0 as CreditInvoiceRecord, a1 as CreditDepositEnqueue, a2 as InvoiceSettlement, Z as ZodLike, a as DVMDescriptor, K as KVStore, o as JobStore, a3 as MppxServer, a4 as X402Config, p as PaymentMethod, a5 as ClientCompatibilityGate, a6 as Message, a7 as FundingReceipt, a8 as TopUpCapUnenforcedReason, a9 as JobReceipt, aa as AppendOutgoingOptions, S as SDKJobContext, ab as StepCache, v as ResponseContent, P as PaymentContent, ac as X402Receipt, ad as X402ExactVersionSupport, ae as X402SettlementIntent, af as X402FacilitatorAuth, ag as X402BatchSettlementConfig, ah as PostgresX402ChannelStorage, ai as PaymentRequirementsV2, aj as CreditLedgerQuerier, ak as X402SettlementCursor, al as X402SettlementStatus, am as X402SettlementWriteOff, an as X402RefundSettlementGate, ao as MppxCredential, J as JobRecord, ap as ReceiptCredit, aq as DrainReceiptEvent, ar as DrainReceipt, z as SignedRequestAudience, as as CreditDrawReleaseEnqueue, at as CreditDepositPayload, au as RevenueSkippedNoRailPayload, av as MessageType, aw as ClientCompatibility, ax as CreditDrainEnqueue, ay as DVMAuthScheme, B as SignedRequestDomain, az as DrawResult, aA as X402UnresolvedRefund, aB as GrownDrawResult, aC as DrawResolution, aD as FundingRecord, aE as BlockedInvoiceCursor, aF as InvoiceReconciliation, aG as InvoiceWriteOff, aH as DrawRecord, aI as StalePendingDrawCursor, aJ as TempoCreditLossEvidence, aK as TempoCreditLoss, aL as X402CreditLossEvidence, aM as X402CreditLoss, aN as DrainMethod, aO as DrainRequestResult, aP as BitcoinDepositLiability, aQ as FundingLot, aR as CreditDrainRecord, aS as ChannelDrainCursor, aT as DrainWriteOff, aU as DrainReleaseResult, aV as DrainFulfilment, aW as DrainTransitionResult, aX as StreamableJobStore, aY as ReceiptIssuingStore, aZ as RequestIdClaim, a_ as RequestIdClaimResult, a$ as OutgoingMessage, b0 as PaymentCreditDelta, b1 as VerifyAndCreditResult, b2 as JobCounters, G as SignedRequestReplayStore } from '../job-store-6gR4pZRP.js';
|
|
2
|
+
export { b3 as CLIENT_COMPATIBILITY_HEADERS, d as CanonicalEnvelope, b4 as ClientCompatibilityEnv, b5 as ClientCompatibilityRequirement, b6 as ClientSemVer, e as CreateSignedRequestVerifierOpts, b7 as CreditFundingBasis, b8 as CreditInvoiceStatus, b9 as CreditLedger, ba as CreditLedgerError, bb as CreditLedgerErrorCode, bc as CreditLedgerErrorDetails, bd as CreditLedgerPool, be as CreditStatus, bf as DRAIN_DELIVERY_RESERVE_SATS, bg as DVM_PROTOCOL_VERSION, bh as DrainConflictReason, bi as DrawRailValue, bj as DrawStatus, n as JobStatus, bk as ReplayStoreBackend, bl as RevenueSkippedNoRailReason, x as SIGNED_REQUEST_AUTH_ID, y as SIGNED_REQUEST_STATEMENT_VERSION, bm as Secp256k1AuthOpts, E as SignedRequestError, F as SignedRequestFailure, H as SignedRequestSignOpts, M as SignedRequestStatementHeader, N as SignedRequestVerifier, bn as X402ChannelStorageOpts, bo as X402RelayLockHolder, bp as X402RelaySubmissionLock, bq as X402RelaySubmissionLockError, br as allocateDrawValue, bs as clientCompatibilityAttributes, bt as clientCompatibilityMiddleware, bu as clientUpgradeRequired, O as createSignedRequestVerifier, bv as isStreamableJobStore, bw as parseClientCapabilities, bx as parseClientCompatibility, by as parseDvmClient, bz as parseProtocolVersion, bA as requireClientCompatibility, bB as secp256k1Auth, bC as signedRequestInput, V as signedRequestStatementHeader } from '../job-store-6gR4pZRP.js';
|
|
3
3
|
import { Pool } from 'pg';
|
|
4
|
-
import { F as FxFetcher } from '../ssrf-
|
|
5
|
-
export { P as PinnedFetch, S as SSRFError, e as SSRFGuardOpts, f as SSRFReason, g as SSRFResolver, h as assertSafeUrl, j as createPinnedFetch } from '../ssrf-
|
|
4
|
+
import { F as FxFetcher } from '../ssrf-DZi-xJyn.js';
|
|
5
|
+
export { P as PinnedFetch, S as SSRFError, e as SSRFGuardOpts, f as SSRFReason, g as SSRFResolver, h as assertSafeUrl, j as createPinnedFetch } from '../ssrf-DZi-xJyn.js';
|
|
6
6
|
import { Hono, Context } from 'hono';
|
|
7
7
|
import { z } from 'zod';
|
|
8
8
|
import { ProofLike } from '@cashu/cashu-ts';
|
|
@@ -11,6 +11,56 @@ import { Channel, AutoSettlementConfig } from '@x402/evm/batch-settlement/server
|
|
|
11
11
|
import 'mppx';
|
|
12
12
|
import '@x402/core/server';
|
|
13
13
|
|
|
14
|
+
/** The channel view the tracker sums claims over. */
|
|
15
|
+
interface X402TrackedChannel {
|
|
16
|
+
channelId: string;
|
|
17
|
+
chargedCumulativeAmount: string;
|
|
18
|
+
totalClaimed: string;
|
|
19
|
+
}
|
|
20
|
+
/** A refund settlement wedged between chain and ledger (internal-review), for the wedge list. */
|
|
21
|
+
interface X402WedgedRefund {
|
|
22
|
+
settlementId: string;
|
|
23
|
+
/** Epoch ms the settlement was first prepared. */
|
|
24
|
+
createdAt: number;
|
|
25
|
+
native?: number;
|
|
26
|
+
}
|
|
27
|
+
/** What the batch-settlement server hands the tracker once it knows its scope. */
|
|
28
|
+
interface X402PayoutContext {
|
|
29
|
+
/** `${network}|${payTo}|${token}` — the scope the settle-pending marker is keyed on. */
|
|
30
|
+
scope: string;
|
|
31
|
+
payTo: string;
|
|
32
|
+
network: string;
|
|
33
|
+
storage: {
|
|
34
|
+
list(): Promise<X402TrackedChannel[]>;
|
|
35
|
+
};
|
|
36
|
+
/** The scheduler's settle cadence — what a wedge's `nextRetry` is derived from. */
|
|
37
|
+
settleIntervalMs: number;
|
|
38
|
+
listWedgedRefunds?: () => Promise<X402WedgedRefund[]>;
|
|
39
|
+
}
|
|
40
|
+
/** The two manager verbs the tracker wraps. */
|
|
41
|
+
interface X402TrackedManager {
|
|
42
|
+
claim(...args: never[]): Promise<{
|
|
43
|
+
vouchers: number;
|
|
44
|
+
transaction: string;
|
|
45
|
+
}[]>;
|
|
46
|
+
settle(): Promise<{
|
|
47
|
+
transaction: string;
|
|
48
|
+
}>;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* The batch-settlement server's view of the reporter: attach once with the
|
|
52
|
+
* scope, then route every claim and settle through the tracked manager so
|
|
53
|
+
* the open batch is kept and the settle emits the payout.
|
|
54
|
+
*/
|
|
55
|
+
interface X402PayoutObserver {
|
|
56
|
+
attach(ctx: X402PayoutContext): void;
|
|
57
|
+
trackManager<M extends X402TrackedManager>(manager: M): M;
|
|
58
|
+
/** A settle that landed outside the tracked manager — the manual claim-and-settle's own retry loop. */
|
|
59
|
+
recordSettle(transaction: string): Promise<void>;
|
|
60
|
+
/** A settle attempt that failed outside the tracked manager. One call per attempt a builder would count as one. */
|
|
61
|
+
recordSettleFailure(error: unknown): Promise<void>;
|
|
62
|
+
}
|
|
63
|
+
|
|
14
64
|
declare const lockPubkeyBrand: unique symbol;
|
|
15
65
|
/**
|
|
16
66
|
* NUT-11 P2PK lock pubkey, lowercase-by-construction. Hex-encoded compressed
|
|
@@ -1972,6 +2022,16 @@ interface CreateX402BatchSettlementServerOpts {
|
|
|
1972
2022
|
settlementEvidenceReader?: X402SettlementEvidenceReader;
|
|
1973
2023
|
/** Authoritative channel-view override for deterministic tests. */
|
|
1974
2024
|
channelStateReader?: (channelId: string) => Promise<X402BatchChannelObservation>;
|
|
2025
|
+
/**
|
|
2026
|
+
* The payout tracker (internal-review). Attached with this server's settle scope
|
|
2027
|
+
* and routed every claim and settle, so the batch that lands at `pay_to` is
|
|
2028
|
+
* reported with the value claimed into it, and the pending snapshot can say
|
|
2029
|
+
* what is still on the channels and whether the settle is wedged.
|
|
2030
|
+
*
|
|
2031
|
+
* @internal Wired by `createDVMServer` from the platform reporter; not a
|
|
2032
|
+
* builder surface, and not part of the extractable SDK contract (internal-review).
|
|
2033
|
+
*/
|
|
2034
|
+
payout?: X402PayoutObserver;
|
|
1975
2035
|
}
|
|
1976
2036
|
/**
|
|
1977
2037
|
* Initialize upstream's scheme and channel manager against dvmkit storage.
|
package/dist/server/index.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
PostgresReplayStore
|
|
3
|
+
} from "../chunk-L4OYF4DQ.js";
|
|
1
4
|
import {
|
|
2
5
|
MemoryCreditLedger
|
|
3
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-OJ5WFIB2.js";
|
|
4
7
|
import {
|
|
5
8
|
PostgresJobStore
|
|
6
9
|
} from "../chunk-6JZIX5WW.js";
|
|
7
10
|
import {
|
|
8
11
|
PostgresKVStore
|
|
9
12
|
} from "../chunk-FROTD5XQ.js";
|
|
10
|
-
import {
|
|
11
|
-
PostgresReplayStore
|
|
12
|
-
} from "../chunk-L4OYF4DQ.js";
|
|
13
13
|
import {
|
|
14
14
|
RAIL_REFUNDABLE,
|
|
15
15
|
SIGNED_ENVELOPE_FIELDS,
|
|
@@ -82,7 +82,7 @@ import {
|
|
|
82
82
|
isNonChannelBitcoinRail,
|
|
83
83
|
netOwedSats,
|
|
84
84
|
x402SettlementPending
|
|
85
|
-
} from "../chunk-
|
|
85
|
+
} from "../chunk-365P52XQ.js";
|
|
86
86
|
import {
|
|
87
87
|
applyRetryToPool,
|
|
88
88
|
withPostgresRecoveryContext
|
|
@@ -3176,11 +3176,20 @@ async function createX402BatchSettlementServer(opts) {
|
|
|
3176
3176
|
read: () => postgres.isSettlePending(settleScope),
|
|
3177
3177
|
write: (pending) => postgres.setSettlePending(settleScope, pending)
|
|
3178
3178
|
} : void 0;
|
|
3179
|
+
opts.payout?.attach({
|
|
3180
|
+
scope: settleScope,
|
|
3181
|
+
payTo: opts.payTo,
|
|
3182
|
+
network: opts.network,
|
|
3183
|
+
storage,
|
|
3184
|
+
settleIntervalMs: (settlementConfig.settleIntervalSecs ?? X402_BATCH_AUTO_SETTLEMENT.settleIntervalSecs ?? 300) * 1e3,
|
|
3185
|
+
...postgres ? { listWedgedRefunds: () => listWedgedRefunds(postgres) } : {}
|
|
3186
|
+
});
|
|
3187
|
+
const tracked = opts.payout ? opts.payout.trackManager(manager) : manager;
|
|
3179
3188
|
let scheduler;
|
|
3180
3189
|
if (opts.config.autoSettlement !== false) {
|
|
3181
3190
|
if (postgres && marker) {
|
|
3182
3191
|
scheduler = createX402FleetSettlementScheduler({
|
|
3183
|
-
manager,
|
|
3192
|
+
manager: tracked,
|
|
3184
3193
|
storage,
|
|
3185
3194
|
config: settlementConfig,
|
|
3186
3195
|
withLock: (operation) => postgres.withFleetSettlementLock(operation),
|
|
@@ -3521,7 +3530,7 @@ async function createX402BatchSettlementServer(opts) {
|
|
|
3521
3530
|
if ("withdrawalPending" in result) {
|
|
3522
3531
|
try {
|
|
3523
3532
|
const claim = async () => {
|
|
3524
|
-
const results = await
|
|
3533
|
+
const results = await tracked.claim({
|
|
3525
3534
|
maxClaimsPerBatch: 100,
|
|
3526
3535
|
selectClaimChannels: (channels, context) => claimCeiling(
|
|
3527
3536
|
channels.filter(
|
|
@@ -3567,13 +3576,19 @@ async function createX402BatchSettlementServer(opts) {
|
|
|
3567
3576
|
} : {},
|
|
3568
3577
|
async claimAndSettle() {
|
|
3569
3578
|
const operation = async () => {
|
|
3570
|
-
const claims = await
|
|
3579
|
+
const claims = await tracked.claim({
|
|
3571
3580
|
maxClaimsPerBatch: 100,
|
|
3572
3581
|
selectClaimChannels: claimCeiling
|
|
3573
3582
|
});
|
|
3574
3583
|
if (claims.length > 0) await marker?.write(true);
|
|
3575
3584
|
if (claims.length === 0 && !await marker?.read()) return;
|
|
3576
|
-
|
|
3585
|
+
try {
|
|
3586
|
+
const settled = await settleOutstandingClaims(manager);
|
|
3587
|
+
await opts.payout?.recordSettle(settled.transaction);
|
|
3588
|
+
} catch (error) {
|
|
3589
|
+
await opts.payout?.recordSettleFailure(error);
|
|
3590
|
+
throw error;
|
|
3591
|
+
}
|
|
3577
3592
|
await marker?.write(false);
|
|
3578
3593
|
};
|
|
3579
3594
|
if (postgres) await postgres.withFleetSettlementLock(operation, true);
|
|
@@ -3588,12 +3603,27 @@ async function createX402BatchSettlementServer(opts) {
|
|
|
3588
3603
|
}
|
|
3589
3604
|
};
|
|
3590
3605
|
}
|
|
3606
|
+
async function listWedgedRefunds(postgres) {
|
|
3607
|
+
const page = await postgres.listSettlements({
|
|
3608
|
+
statuses: X402_WEDGED_SETTLEMENT_STATUSES,
|
|
3609
|
+
updatedBeforeMs: Date.now() - WEDGED_REFUND_MIN_AGE_MS,
|
|
3610
|
+
limit: 50
|
|
3611
|
+
});
|
|
3612
|
+
return page.settlements.filter((intent) => intent.operation === "refund").map((intent) => {
|
|
3613
|
+
const amount = intent.response?.amount;
|
|
3614
|
+
return {
|
|
3615
|
+
settlementId: intent.settlementId,
|
|
3616
|
+
createdAt: intent.createdAt,
|
|
3617
|
+
...typeof amount === "string" && /^\d{1,15}$/.test(amount) ? { native: Number(amount) } : {}
|
|
3618
|
+
};
|
|
3619
|
+
});
|
|
3620
|
+
}
|
|
3621
|
+
var WEDGED_REFUND_MIN_AGE_MS = 5 * 6e4;
|
|
3591
3622
|
async function settleOutstandingClaims(manager) {
|
|
3592
3623
|
const retryDelaysMs = [250, 500, 1e3, 2e3];
|
|
3593
3624
|
for (let attempt = 0; ; attempt++) {
|
|
3594
3625
|
try {
|
|
3595
|
-
await manager.settle();
|
|
3596
|
-
return;
|
|
3626
|
+
return await manager.settle();
|
|
3597
3627
|
} catch (error) {
|
|
3598
3628
|
const message = error instanceof Error ? error.message : String(error);
|
|
3599
3629
|
if (!message.includes("invalid_batch_settlement_evm_nothing_to_settle") || attempt >= retryDelaysMs.length) {
|
|
@@ -9732,8 +9762,29 @@ async function handleMarkMelted(c, opts) {
|
|
|
9732
9762
|
);
|
|
9733
9763
|
}
|
|
9734
9764
|
}
|
|
9735
|
-
await
|
|
9736
|
-
|
|
9765
|
+
const client = await opts.db.connect();
|
|
9766
|
+
try {
|
|
9767
|
+
await client.query("BEGIN");
|
|
9768
|
+
await recordMeltAudit(client, rowIds, { meltQuoteId, paymentPreimage });
|
|
9769
|
+
await markRowsMelted(client, rowIds);
|
|
9770
|
+
if (opts.onMelted) {
|
|
9771
|
+
await opts.onMelted.enqueue(
|
|
9772
|
+
{
|
|
9773
|
+
rows: rows.map((r) => ({ id: r.id, mintUrl: r.mintUrl, proofAmount: r.proofAmount })),
|
|
9774
|
+
meltQuoteId,
|
|
9775
|
+
paymentPreimage
|
|
9776
|
+
},
|
|
9777
|
+
client
|
|
9778
|
+
);
|
|
9779
|
+
}
|
|
9780
|
+
await client.query("COMMIT");
|
|
9781
|
+
} catch (err) {
|
|
9782
|
+
await client.query("ROLLBACK").catch(() => void 0);
|
|
9783
|
+
throw err;
|
|
9784
|
+
} finally {
|
|
9785
|
+
client.release();
|
|
9786
|
+
}
|
|
9787
|
+
opts.onMelted?.committed();
|
|
9737
9788
|
return c.json({ melted: rowIds.length });
|
|
9738
9789
|
}
|
|
9739
9790
|
async function handleRestartFailed(c, opts) {
|
|
@@ -10877,7 +10928,11 @@ async function handleReconcileInvoice(c, opts) {
|
|
|
10877
10928
|
amountMicro: invoice.amountMicro,
|
|
10878
10929
|
creditCurrency: invoice.currency,
|
|
10879
10930
|
fundedAt: settledAtMs ?? invoice.settledAt ?? nowMs,
|
|
10880
|
-
expiryMs
|
|
10931
|
+
expiryMs,
|
|
10932
|
+
// The settlements table types this deposit `repair` off the
|
|
10933
|
+
// flag (internal-review): the sats landed at payment time and the
|
|
10934
|
+
// deposit is the one row they get.
|
|
10935
|
+
repaired: true
|
|
10881
10936
|
}
|
|
10882
10937
|
}
|
|
10883
10938
|
} : {},
|
|
@@ -11228,8 +11283,10 @@ async function handleReconcileTempo(c, opts) {
|
|
|
11228
11283
|
if (record.status === "sent") return tempoReconciledBody(c, record, channelId, true);
|
|
11229
11284
|
const evidence = await classifyTempoCloseEvidence(rail.rail, channelId);
|
|
11230
11285
|
if (evidence.chain !== "found") return tempoEvidenceRefusal(c, evidence);
|
|
11286
|
+
const client = await opts.db.connect();
|
|
11231
11287
|
let booked;
|
|
11232
11288
|
try {
|
|
11289
|
+
await client.query("BEGIN");
|
|
11233
11290
|
booked = await completeTempoChannelDrain({
|
|
11234
11291
|
deps: {
|
|
11235
11292
|
ledger: opts.ledger,
|
|
@@ -11245,14 +11302,30 @@ async function handleReconcileTempo(c, opts) {
|
|
|
11245
11302
|
refundedNative: evidence.refundedToPayer,
|
|
11246
11303
|
debitedNative: record.drainedNative,
|
|
11247
11304
|
reference: evidence.transaction,
|
|
11248
|
-
repaired: true
|
|
11305
|
+
repaired: true,
|
|
11306
|
+
tx: client
|
|
11249
11307
|
});
|
|
11308
|
+
if (opts.onTempoDrainReconciled && !booked.replayed) {
|
|
11309
|
+
await opts.onTempoDrainReconciled.enqueue(
|
|
11310
|
+
{
|
|
11311
|
+
channelId,
|
|
11312
|
+
txHash: evidence.transaction,
|
|
11313
|
+
settledToPayee: evidence.settledToPayee
|
|
11314
|
+
},
|
|
11315
|
+
client
|
|
11316
|
+
);
|
|
11317
|
+
}
|
|
11318
|
+
await client.query("COMMIT");
|
|
11250
11319
|
} catch (err) {
|
|
11320
|
+
await client.query("ROLLBACK").catch(() => void 0);
|
|
11251
11321
|
if (err instanceof CreditLedgerError) {
|
|
11252
11322
|
return c.json({ error: err.code, message: err.message }, ledgerRefusalStatus(err.code));
|
|
11253
11323
|
}
|
|
11254
11324
|
throw err;
|
|
11325
|
+
} finally {
|
|
11326
|
+
client.release();
|
|
11255
11327
|
}
|
|
11328
|
+
if (!booked.replayed) opts.onTempoDrainReconciled?.committed();
|
|
11256
11329
|
if (opts.receiptIssuer && !booked.replayed) {
|
|
11257
11330
|
const receipt = opts.receiptIssuer.issueDrain({
|
|
11258
11331
|
creditId: booked.drain.creditId,
|
|
@@ -11922,6 +11995,58 @@ function parseSerializedDleq(raw) {
|
|
|
11922
11995
|
return { e: dleq.e, s: dleq.s, ...dleq.r !== void 0 ? { r: dleq.r } : {} };
|
|
11923
11996
|
}
|
|
11924
11997
|
|
|
11998
|
+
// src/sdk/server/credit-expiry-sweep.ts
|
|
11999
|
+
function startCreditExpirySweep(ledger, opts = {}) {
|
|
12000
|
+
const sweepExpiredCredits = ledger.sweepExpiredCredits?.bind(ledger);
|
|
12001
|
+
if (!sweepExpiredCredits) return void 0;
|
|
12002
|
+
const intervalMs = opts.intervalMs ?? DEFAULT_SWEEP_INTERVAL_MS;
|
|
12003
|
+
const bootDelayMs = opts.bootDelayMs ?? DEFAULT_BOOT_DELAY_MS;
|
|
12004
|
+
let stopped = false;
|
|
12005
|
+
const runOnce = () => sweepExpiredCredits({ limit: opts.limit });
|
|
12006
|
+
const pass = () => {
|
|
12007
|
+
if (stopped) return;
|
|
12008
|
+
void runOnce().then(({ released }) => {
|
|
12009
|
+
if (released.length === 0) return;
|
|
12010
|
+
console.log(
|
|
12011
|
+
JSON.stringify({
|
|
12012
|
+
level: "credit_expiry_released",
|
|
12013
|
+
count: released.length,
|
|
12014
|
+
credits: released.map((r) => r.creditId)
|
|
12015
|
+
})
|
|
12016
|
+
);
|
|
12017
|
+
}).catch((err) => {
|
|
12018
|
+
console.error(
|
|
12019
|
+
JSON.stringify({
|
|
12020
|
+
level: "credit_expiry_sweep_failed",
|
|
12021
|
+
error: err instanceof Error ? err.message : String(err)
|
|
12022
|
+
})
|
|
12023
|
+
);
|
|
12024
|
+
});
|
|
12025
|
+
};
|
|
12026
|
+
let bootTimer;
|
|
12027
|
+
if (bootDelayMs > 0) {
|
|
12028
|
+
bootTimer = setTimeout(pass, bootDelayMs);
|
|
12029
|
+
bootTimer.unref();
|
|
12030
|
+
}
|
|
12031
|
+
let intervalTimer;
|
|
12032
|
+
if (intervalMs > 0) {
|
|
12033
|
+
intervalTimer = setInterval(pass, intervalMs);
|
|
12034
|
+
intervalTimer.unref();
|
|
12035
|
+
}
|
|
12036
|
+
return {
|
|
12037
|
+
stop() {
|
|
12038
|
+
stopped = true;
|
|
12039
|
+
if (bootTimer) clearTimeout(bootTimer);
|
|
12040
|
+
if (intervalTimer) clearInterval(intervalTimer);
|
|
12041
|
+
bootTimer = void 0;
|
|
12042
|
+
intervalTimer = void 0;
|
|
12043
|
+
},
|
|
12044
|
+
runOnce
|
|
12045
|
+
};
|
|
12046
|
+
}
|
|
12047
|
+
var DEFAULT_SWEEP_INTERVAL_MS = 60 * 60 * 1e3;
|
|
12048
|
+
var DEFAULT_BOOT_DELAY_MS = 3e4;
|
|
12049
|
+
|
|
11925
12050
|
// src/sdk/server/dev-page.ts
|
|
11926
12051
|
function devPageHtml(dvmName) {
|
|
11927
12052
|
const escaped = dvmName.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
@@ -12863,7 +12988,7 @@ function jobCredentialGate(opts) {
|
|
|
12863
12988
|
// a human verbatim, so the conditional advice lives in `hint`, which
|
|
12864
12989
|
// is what the agent acts on.
|
|
12865
12990
|
display: "Couldn't retrieve your result \u2014 the request was missing its job credential.",
|
|
12866
|
-
hint: `Send the job_token from the POST /v1/job response as the X-Job-Token header${alternative}. The token is minted once, at submit, and the DVM cannot reissue it \u2014 a job submitted from another machine, or by a caller that never stored it, can't be read here. If your caller never sends X-Job-Token at all, upgrade: npm i -g @dvmkit/cli@0.1.
|
|
12991
|
+
hint: `Send the job_token from the POST /v1/job response as the X-Job-Token header${alternative}. The token is minted once, at submit, and the DVM cannot reissue it \u2014 a job submitted from another machine, or by a caller that never stored it, can't be read here. If your caller never sends X-Job-Token at all, upgrade: npm i -g @dvmkit/dvm-cli@0.1.4.`
|
|
12867
12992
|
};
|
|
12868
12993
|
}
|
|
12869
12994
|
};
|
|
@@ -17116,12 +17241,24 @@ async function createDVMServer(descriptor, opts) {
|
|
|
17116
17241
|
const platformUrl = opts.platformUrl ?? envMaybe.DVMKIT_PLATFORM_URL;
|
|
17117
17242
|
const dvmId = opts.dvmId;
|
|
17118
17243
|
let revenueReporter;
|
|
17244
|
+
let payoutReporter;
|
|
17119
17245
|
if (!opts.onJobCompleted && platformToken && platformUrl && dvmId && opts.db) {
|
|
17120
|
-
const { RevenueReporter } = await import("../revenue-reporter-
|
|
17246
|
+
const { RevenueReporter } = await import("../revenue-reporter-GB4WKLDC.js");
|
|
17121
17247
|
const reporter = new RevenueReporter(opts.db, platformUrl, platformToken);
|
|
17122
17248
|
await reporter.init();
|
|
17123
17249
|
reporter.startRetryLoop();
|
|
17124
17250
|
revenueReporter = reporter;
|
|
17251
|
+
const { MemoryX402BatchStore, PayoutReporter } = await import("../payout-reporter-4TNWRS5F.js");
|
|
17252
|
+
payoutReporter = new PayoutReporter({
|
|
17253
|
+
dvmId,
|
|
17254
|
+
db: opts.db,
|
|
17255
|
+
transport: reporter,
|
|
17256
|
+
// The same condition the admin routes and the accumulator monitor mount on.
|
|
17257
|
+
cashu: opts.cashuMode === "p2pk-accumulator" && !!opts.lockPubkey,
|
|
17258
|
+
...typeof opts.db.connect === "function" ? {} : { batchStore: new MemoryX402BatchStore() }
|
|
17259
|
+
});
|
|
17260
|
+
await payoutReporter.init();
|
|
17261
|
+
payoutReporter.start();
|
|
17125
17262
|
}
|
|
17126
17263
|
assertRevenueReporterReady({
|
|
17127
17264
|
failFast: opts.failFast ?? false,
|
|
@@ -17164,6 +17301,13 @@ async function createDVMServer(descriptor, opts) {
|
|
|
17164
17301
|
});
|
|
17165
17302
|
opts.tempoSettlementReadiness?.start();
|
|
17166
17303
|
const creditLedger = opts.creditLedger ?? new MemoryCreditLedger();
|
|
17304
|
+
if (revenueReporter && dvmId) {
|
|
17305
|
+
creditLedger.useCreditExpiryReleaseOutbox?.({
|
|
17306
|
+
dvmId,
|
|
17307
|
+
enqueue: revenueReporter.enqueueCreditExpiryRelease.bind(revenueReporter)
|
|
17308
|
+
});
|
|
17309
|
+
}
|
|
17310
|
+
const creditExpirySweep = startCreditExpirySweep(creditLedger, opts.creditExpirySweep);
|
|
17167
17311
|
const processedPayments = opts.processedPayments ?? new MemoryProcessedPaymentStore();
|
|
17168
17312
|
const bootX402Support = opts.x402 ? opts.x402FacilitatorHealth?.support() ?? configuredX402FacilitatorSupport(opts.x402) : void 0;
|
|
17169
17313
|
const x402Config = opts.x402;
|
|
@@ -17214,7 +17358,8 @@ async function createDVMServer(descriptor, opts) {
|
|
|
17214
17358
|
db: opts.db,
|
|
17215
17359
|
allowInMemory: opts.devMode,
|
|
17216
17360
|
earnedNative: (channelId) => creditLedger.earnedNativeForX402Channel(channelId),
|
|
17217
|
-
supportedResponse: selfRelayEnabled ? void 0 : opts.x402FacilitatorHealth?.supportedResponse?.()
|
|
17361
|
+
supportedResponse: selfRelayEnabled ? void 0 : opts.x402FacilitatorHealth?.supportedResponse?.(),
|
|
17362
|
+
payout: payoutReporter?.x402Observer()
|
|
17218
17363
|
}) : void 0;
|
|
17219
17364
|
const x402BatchSettlement = x402BatchSettlementFactory && (bootX402Support?.batchSettlement || selfRelayEnabled) ? await x402BatchSettlementFactory() : void 0;
|
|
17220
17365
|
const x402ExactStore = x402Config && opts.db && typeof opts.db.connect === "function" ? new PostgresX402ExactSettlementStore(opts.db) : void 0;
|
|
@@ -17251,21 +17396,25 @@ async function createDVMServer(descriptor, opts) {
|
|
|
17251
17396
|
enqueueCreditDrawRelease,
|
|
17252
17397
|
x402BatchSettlement,
|
|
17253
17398
|
x402BatchSettlementFactory,
|
|
17254
|
-
x402ExactSettlement
|
|
17399
|
+
x402ExactSettlement,
|
|
17400
|
+
payoutReporter
|
|
17255
17401
|
});
|
|
17256
17402
|
return {
|
|
17257
17403
|
app: server.app,
|
|
17258
17404
|
authAudience: server.authAudience,
|
|
17259
17405
|
shutdown() {
|
|
17260
17406
|
const settlementStopped = server.shutdown();
|
|
17407
|
+
payoutReporter?.stop();
|
|
17261
17408
|
revenueReporter?.stop();
|
|
17409
|
+
creditExpirySweep?.stop();
|
|
17262
17410
|
unsubscribeTempoSettlementReadiness?.();
|
|
17263
17411
|
if (x402ChannelStorage) {
|
|
17264
17412
|
void settlementStopped.then(() => x402ChannelStorage.close()).catch(() => void 0);
|
|
17265
17413
|
}
|
|
17266
17414
|
},
|
|
17267
17415
|
jobManager: server.jobManager,
|
|
17268
|
-
revenueReporterActive: !!revenueReporter
|
|
17416
|
+
revenueReporterActive: !!revenueReporter,
|
|
17417
|
+
payoutReporter
|
|
17269
17418
|
};
|
|
17270
17419
|
}
|
|
17271
17420
|
function unknownRouteNotFound(c) {
|
|
@@ -17540,12 +17689,16 @@ var DVMServer = class {
|
|
|
17540
17689
|
if (this.opts.cashuMode === "p2pk-accumulator" && this.opts.db && this.opts.dvmId && this.opts.lockPubkey) {
|
|
17541
17690
|
const db = this.opts.db;
|
|
17542
17691
|
const dvmId = this.opts.dvmId;
|
|
17692
|
+
const payoutReporter = this.opts.payoutReporter;
|
|
17543
17693
|
installAdminCashuRoutes(this.app, {
|
|
17544
17694
|
db,
|
|
17545
17695
|
dvmId,
|
|
17546
17696
|
getLockPubkeyState: () => this.loadActiveLockPubkeyState(db, dvmId),
|
|
17547
17697
|
graceSeconds: this.graceSeconds(),
|
|
17548
|
-
nonceStore: this.adminCashuNonceStore
|
|
17698
|
+
nonceStore: this.adminCashuNonceStore,
|
|
17699
|
+
// internal-review: a completed melt is a landed payout, queued in the
|
|
17700
|
+
// transaction that marks it.
|
|
17701
|
+
...payoutReporter ? { onMelted: payoutReporter.meltHook() } : {}
|
|
17549
17702
|
});
|
|
17550
17703
|
installAdminCreditRoutes(this.app, {
|
|
17551
17704
|
db,
|
|
@@ -17575,7 +17728,10 @@ var DVMServer = class {
|
|
|
17575
17728
|
// Health-filtered, and read per request rather than captured: the
|
|
17576
17729
|
// servicer picking a mint to buy a refund at wants the list that
|
|
17577
17730
|
// excludes a mint currently failing its probe (internal-review).
|
|
17578
|
-
mints: () => this.advertisedMints()
|
|
17731
|
+
mints: () => this.advertisedMints(),
|
|
17732
|
+
// internal-review: a repaired Tempo close is a landed payout the agent
|
|
17733
|
+
// finished, queued in the transaction that books the drain.
|
|
17734
|
+
...payoutReporter ? { onTempoDrainReconciled: payoutReporter.tempoRepairHook() } : {}
|
|
17579
17735
|
});
|
|
17580
17736
|
}
|
|
17581
17737
|
}
|
|
@@ -21613,6 +21769,9 @@ function createDVMHost(opts = {}) {
|
|
|
21613
21769
|
let pgPool;
|
|
21614
21770
|
let creditLedger;
|
|
21615
21771
|
let tempoSessionStore;
|
|
21772
|
+
const tempoPayoutReader = {};
|
|
21773
|
+
const payoutSinks = {};
|
|
21774
|
+
let tempoPayoutOwner;
|
|
21616
21775
|
let tempoSettlementReadiness;
|
|
21617
21776
|
let processedPayments;
|
|
21618
21777
|
let pgStreamStore;
|
|
@@ -21764,6 +21923,7 @@ ${config.facilitatorAuth?.keyId ?? ""}`;
|
|
|
21764
21923
|
]);
|
|
21765
21924
|
const sessionStore = new PostgresTempoSessionStore(pgPool);
|
|
21766
21925
|
tempoSessionStore = sessionStore;
|
|
21926
|
+
tempoPayoutReader.listActive = (limit, cursor) => sessionStore.listActive(limit, cursor);
|
|
21767
21927
|
pendingInits.push(sessionStore.init());
|
|
21768
21928
|
const operator = privateKeyToAccount5(tempoOperatorKey);
|
|
21769
21929
|
const tempoCurrency = envMaybe.DVMKIT_TEMPO_CURRENCY ?? TEMPO_USDC_MAINNET;
|
|
@@ -21826,6 +21986,13 @@ ${config.facilitatorAuth?.keyId ?? ""}`;
|
|
|
21826
21986
|
delta: settlement.delta.toString()
|
|
21827
21987
|
})
|
|
21828
21988
|
);
|
|
21989
|
+
await payoutSinks.tempoSettled?.({
|
|
21990
|
+
txHash: settlement.txHash,
|
|
21991
|
+
channelId: settlement.channelId,
|
|
21992
|
+
trigger: settlement.trigger,
|
|
21993
|
+
amount: settlement.amount,
|
|
21994
|
+
delta: settlement.delta
|
|
21995
|
+
});
|
|
21829
21996
|
}
|
|
21830
21997
|
};
|
|
21831
21998
|
}
|
|
@@ -21916,7 +22083,7 @@ ${config.facilitatorAuth?.keyId ?? ""}`;
|
|
|
21916
22083
|
sharedPgConsumedStore = consumedStore;
|
|
21917
22084
|
}
|
|
21918
22085
|
if (pgPool) {
|
|
21919
|
-
const { CreditLedger: CreditLedger2 } = await import("../credit-ledger-
|
|
22086
|
+
const { CreditLedger: CreditLedger2 } = await import("../credit-ledger-RO4FGSHG.js");
|
|
21920
22087
|
const pgLedger = new CreditLedger2(pgPool, tempoSessionStore);
|
|
21921
22088
|
pendingInits.push(pgLedger.init());
|
|
21922
22089
|
creditLedger = pgLedger;
|
|
@@ -21925,7 +22092,7 @@ ${config.facilitatorAuth?.keyId ?? ""}`;
|
|
|
21925
22092
|
pendingInits.push(pgProcessed.init());
|
|
21926
22093
|
processedPayments = pgProcessed;
|
|
21927
22094
|
} else {
|
|
21928
|
-
const { MemoryCreditLedger: MemoryCreditLedger2 } = await import("../memory-credit-ledger-
|
|
22095
|
+
const { MemoryCreditLedger: MemoryCreditLedger2 } = await import("../memory-credit-ledger-I2G64DDK.js");
|
|
21929
22096
|
creditLedger = new MemoryCreditLedger2();
|
|
21930
22097
|
const { MemoryProcessedPaymentStore: MemoryProcessedPaymentStore2 } = await import("../processed-payment-store-HAA4SFNK.js");
|
|
21931
22098
|
processedPayments = new MemoryProcessedPaymentStore2();
|
|
@@ -21999,7 +22166,8 @@ ${config.facilitatorAuth?.keyId ?? ""}`;
|
|
|
21999
22166
|
const {
|
|
22000
22167
|
app: subApp,
|
|
22001
22168
|
shutdown,
|
|
22002
|
-
authAudience
|
|
22169
|
+
authAudience,
|
|
22170
|
+
payoutReporter
|
|
22003
22171
|
} = await createDVMServer(descriptor, {
|
|
22004
22172
|
env,
|
|
22005
22173
|
store,
|
|
@@ -22034,6 +22202,16 @@ ${config.facilitatorAuth?.keyId ?? ""}`;
|
|
|
22034
22202
|
tempoSettlementReadiness
|
|
22035
22203
|
});
|
|
22036
22204
|
entry.shutdown = shutdown;
|
|
22205
|
+
if (payoutReporter && !tempoPayoutOwner) {
|
|
22206
|
+
tempoPayoutOwner = payoutReporter;
|
|
22207
|
+
const ledger = creditLedger;
|
|
22208
|
+
payoutReporter.attachTempo({
|
|
22209
|
+
...tempoPayoutReader,
|
|
22210
|
+
...mppTempoRecipient ? { recipient: mppTempoRecipient } : {},
|
|
22211
|
+
listChannelDrains: (args) => ledger.listChannelDrains(args)
|
|
22212
|
+
});
|
|
22213
|
+
payoutSinks.tempoSettled = (event) => payoutReporter.tempoSettled(event);
|
|
22214
|
+
}
|
|
22037
22215
|
if (descriptor.config.routes) {
|
|
22038
22216
|
await descriptor.config.routes(subApp, {
|
|
22039
22217
|
authAudience,
|
package/dist/testing/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { aX as StreamableJobStore, aY as ReceiptIssuingStore, J as JobRecord, aZ as RequestIdClaim, a_ as RequestIdClaimResult, a9 as JobReceipt, a$ as OutgoingMessage, aa as AppendOutgoingOptions, b0 as PaymentCreditDelta, b1 as VerifyAndCreditResult, b2 as JobCounters, a6 as Message, av as MessageType, K as KVStore, L as Logger, v as ResponseContent, P as PaymentContent, S as SDKJobContext } from '../job-store-
|
|
1
|
+
import { aX as StreamableJobStore, aY as ReceiptIssuingStore, J as JobRecord, aZ as RequestIdClaim, a_ as RequestIdClaimResult, a9 as JobReceipt, a$ as OutgoingMessage, aa as AppendOutgoingOptions, b0 as PaymentCreditDelta, b1 as VerifyAndCreditResult, b2 as JobCounters, a6 as Message, av as MessageType, K as KVStore, L as Logger, v as ResponseContent, P as PaymentContent, S as SDKJobContext } from '../job-store-6gR4pZRP.js';
|
|
2
2
|
import '@cashu/cashu-ts';
|
|
3
3
|
import 'mppx';
|
|
4
4
|
import 'hono';
|