@dvmkit/sdk 0.1.5-rc.9 → 0.2.0-rc.9
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 +12 -0
- package/dist/{chunk-BIP6G74V.js → chunk-2ATUAUAO.js} +8 -8
- package/dist/{chunk-27V2ILSR.js → chunk-4A2RAKCW.js} +2 -2
- package/dist/{chunk-EVBK675R.js → chunk-6GRIKOFB.js} +28 -23
- package/dist/{chunk-CEOAHV2I.js → chunk-FDKRXOZO.js} +0 -5
- package/dist/{chunk-L4OYF4DQ.js → chunk-FT6HTUM4.js} +1 -1
- package/dist/{chunk-BTZY7VPH.js → chunk-GAIPXGM3.js} +1 -1
- package/dist/{chunk-U6M3ATSG.js → chunk-JDT5LCJC.js} +40 -6
- package/dist/{chunk-FROTD5XQ.js → chunk-JLXYOV4Y.js} +1 -2
- package/dist/{chunk-M7LHFJ5K.js → chunk-KMZXTBLA.js} +2 -2
- package/dist/{chunk-6BQM7TOW.js → chunk-L67WTZX2.js} +3 -7
- package/dist/{chunk-CGKZDODG.js → chunk-MG67KXU7.js} +0 -5
- package/dist/{chunk-JZWELPFH.js → chunk-MRAGS5VP.js} +1 -1
- package/dist/{chunk-2UUXIIOC.js → chunk-O2X2CCKH.js} +3 -3
- package/dist/{chunk-TQWGQCNV.js → chunk-OMIQMMME.js} +3 -3
- package/dist/{chunk-5PBOA25N.js → chunk-PCUQZDZA.js} +436 -355
- package/dist/{chunk-KVEHHC7W.js → chunk-PHHAYRQV.js} +7 -9
- package/dist/{chunk-SSSZUVWM.js → chunk-QP53RWAD.js} +88 -38
- package/dist/{chunk-DMNLFNTW.js → chunk-QT4ONTST.js} +1 -1
- package/dist/{chunk-RW5LP57K.js → chunk-SDK6KDJN.js} +0 -1
- package/dist/{chunk-MLRCSJYX.js → chunk-V7EVFLAK.js} +87 -90
- package/dist/{chunk-E4EVGPDX.js → chunk-XQXJKJ3P.js} +0 -2
- package/dist/{credit-ledger-2DFQHNLB.js → credit-ledger-5ZEJRI46.js} +1 -1
- package/dist/{credit-menu-enwMbn55.d.ts → credit-menu-D4Gcdgc4.d.ts} +487 -643
- package/dist/{fx-D860pZvP.d.ts → fx-B0SLBe5x.d.ts} +38 -82
- package/dist/index.d.ts +11 -14
- package/dist/index.js +2 -2
- package/dist/internal/caller.d.ts +618 -1525
- package/dist/internal/caller.js +28 -60
- package/dist/internal/server.d.ts +36 -61
- package/dist/internal/server.js +11 -11
- package/dist/{job-store-BUGqvCfL.d.ts → job-store-B2uZvga4.d.ts} +70 -59
- package/dist/{lightning-backend-BozcevPZ.d.ts → lightning-backend-CQBnQgsT.d.ts} +19 -27
- package/dist/{memory-credit-ledger-MNUOTQO5.js → memory-credit-ledger-ZOH6C3N4.js} +2 -2
- package/dist/{mpp-setup-4FJD6ZHV.js → mpp-setup-IOJBF7DB.js} +1 -1
- package/dist/{payout-reporter-RG6XNGPI.js → payout-reporter-5PIRYFVQ.js} +1 -1
- package/dist/{postgres-consumed-credential-store-VHBT4KEA.js → postgres-consumed-credential-store-ISRHBMOU.js} +1 -1
- package/dist/{postgres-job-store-3RAXMNSY.js → postgres-job-store-OGQ6IT4U.js} +1 -1
- package/dist/{postgres-kv-store-JFBDP5IP.js → postgres-kv-store-D5E2EZ24.js} +1 -1
- package/dist/{postgres-replay-store-UJXRT6VO.js → postgres-replay-store-IZFLTTAC.js} +1 -1
- package/dist/{pricing-4CEB34RM.js → pricing-MU5GNUJZ.js} +1 -1
- package/dist/{processed-payment-store-HAA4SFNK.js → processed-payment-store-FIDI3RNH.js} +1 -1
- package/dist/{revenue-reporter-ASZ7SHHH.js → revenue-reporter-NNCNRY4C.js} +1 -1
- package/dist/server/index.d.ts +53 -59
- package/dist/server/index.js +38 -37
- package/dist/{ssrf-DbFkpDv0.d.ts → ssrf-dMooihtY.d.ts} +1 -2
- package/dist/{step-cache-5dljDqrQ.d.ts → step-cache-CXg7ziML.d.ts} +389 -551
- package/dist/{tempo-charge-store-RIFTALZK.js → tempo-charge-store-76TDAF34.js} +1 -1
- package/dist/{tempo-lifecycle-DFIXQ54Q.js → tempo-lifecycle-DXM7QXJQ.js} +3 -3
- package/dist/{tempo-wallet-4QKSV65O.js → tempo-wallet-O67H5M4N.js} +2 -2
- package/dist/testing/index.d.ts +5 -15
- package/dist/testing/index.js +4 -11
- package/dist/{usd-DoRuAckA.d.ts → usd-BNDg1715.d.ts} +14 -16
- package/dist/{wallet-CJC8lwxx.d.ts → wallet-Dwjs5n_M.d.ts} +1 -1
- package/dist/{x402-5H27DCBE.js → x402-7S2EFINY.js} +2 -2
- package/package.json +2 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ProofLike } from '@cashu/cashu-ts';
|
|
2
|
-
import { a1 as Message, ah as FundingMethod, X as FundingReceipt, bO as CreditSnapshot, Y as JobReceipt, ax as StepRecord, a2 as MessageType } from './step-cache-
|
|
2
|
+
import { a1 as Message, ah as FundingMethod, X as FundingReceipt, bO as CreditSnapshot, Y as JobReceipt, ax as StepRecord, a2 as MessageType } from './step-cache-CXg7ziML.js';
|
|
3
3
|
|
|
4
4
|
/** Job status values that can be persisted. */
|
|
5
5
|
type JobStatus = "processing" | "completed" | "failed" | "awaiting-input" | "cancelled" | "working";
|
|
@@ -8,7 +8,7 @@ interface JobRecord {
|
|
|
8
8
|
id: string;
|
|
9
9
|
tags: string[];
|
|
10
10
|
/**
|
|
11
|
-
* Capability name this job dispatches to
|
|
11
|
+
* Capability name this job dispatches to. Populated from the
|
|
12
12
|
* `POST /v1/job` body's `capability` field at submission time; persisted
|
|
13
13
|
* so reactivation on another machine routes to the same handler.
|
|
14
14
|
*/
|
|
@@ -18,7 +18,7 @@ interface JobRecord {
|
|
|
18
18
|
requesterId: string;
|
|
19
19
|
/**
|
|
20
20
|
* SHA-256 hex of the per-job opaque token issued at creation time for
|
|
21
|
-
* anonymous requesters
|
|
21
|
+
* anonymous requesters. When set, all `/v1/job/:id/*` reads/writes
|
|
22
22
|
* gate on the caller presenting the matching `X-Job-Token` header — this is
|
|
23
23
|
* the mechanism that prevents cross-caller transcript leaks for free DVMs
|
|
24
24
|
* where every caller otherwise resolves to `requesterId === "anonymous"`.
|
|
@@ -27,7 +27,7 @@ interface JobRecord {
|
|
|
27
27
|
*/
|
|
28
28
|
requesterTokenHash?: string;
|
|
29
29
|
/**
|
|
30
|
-
* The `job_token` itself, in the clear
|
|
30
|
+
* The `job_token` itself, in the clear. Kept so a caller whose
|
|
31
31
|
* paid submit timed out can replay it and be handed back the very token the
|
|
32
32
|
* lost response carried — the alternative (minting a fresh one) would be
|
|
33
33
|
* rejected by whichever machine is still running the job, since its
|
|
@@ -41,14 +41,14 @@ interface JobRecord {
|
|
|
41
41
|
*/
|
|
42
42
|
requesterToken?: string;
|
|
43
43
|
/**
|
|
44
|
-
* Fingerprint of the submission that created this job
|
|
44
|
+
* Fingerprint of the submission that created this job — see
|
|
45
45
|
* `requestFingerprint`. The replay gate: a retried paid submit is handed the
|
|
46
46
|
* original job only when it reproduces this.
|
|
47
47
|
*/
|
|
48
48
|
requestFingerprint?: string;
|
|
49
49
|
/**
|
|
50
50
|
* secp256k1 x-only pubkey of the caller that signed the submission, on
|
|
51
|
-
* DVMs with descriptor-level auth
|
|
51
|
+
* DVMs with descriptor-level auth. Second half of the replay
|
|
52
52
|
* gate — the signature envelope is re-minted on every resume attempt, so
|
|
53
53
|
* the identity behind it is pinned here instead.
|
|
54
54
|
*/
|
|
@@ -58,6 +58,16 @@ interface JobRecord {
|
|
|
58
58
|
/** HTTP path whose live auth gate accepted the persisted caller proof. */
|
|
59
59
|
authRequestPath?: string;
|
|
60
60
|
status: JobStatus;
|
|
61
|
+
/** False on jobs accepted before complete lifecycle timing was available. */
|
|
62
|
+
timingKnown?: boolean;
|
|
63
|
+
/** SDK terminal attribution; never accepted from a handler. */
|
|
64
|
+
endedBy?: "caller" | "provider";
|
|
65
|
+
/** Unix ms when the terminal status committed; immutable afterwards. */
|
|
66
|
+
terminalAtMs?: number;
|
|
67
|
+
/** Accumulated awaiting-input time, excluding the currently open stretch. */
|
|
68
|
+
callerWaitMs?: number;
|
|
69
|
+
/** Unix ms at which the current awaiting-input stretch began. */
|
|
70
|
+
awaitingInputAtMs?: number;
|
|
61
71
|
summary?: string;
|
|
62
72
|
messages: Message[];
|
|
63
73
|
seq: number;
|
|
@@ -68,22 +78,22 @@ interface JobRecord {
|
|
|
68
78
|
/**
|
|
69
79
|
* Settlement reference threaded into the platform revenue ledger
|
|
70
80
|
* (`revenue_events.tx_hash`). EVM tx hash for x402, mppx `challenge.id`
|
|
71
|
-
* for mpp
|
|
72
|
-
* `X-Cashu-Request-Id` UUID
|
|
81
|
+
* for mpp; cashu accumulator path sets this to the
|
|
82
|
+
* `X-Cashu-Request-Id` UUID. Persisted so it survives durable
|
|
73
83
|
* replay.
|
|
74
84
|
*/
|
|
75
85
|
paymentTxHash?: string;
|
|
76
86
|
/** Chain transaction returned to callers recovering x402 or Tempo acceptance. */
|
|
77
87
|
paymentTransactionHash?: string;
|
|
78
|
-
/** Rail-native upfront amount (sats
|
|
88
|
+
/** Rail-native upfront amount (sats or USDC microunits). */
|
|
79
89
|
nativeAmount?: number;
|
|
80
|
-
/** Native asset tag
|
|
90
|
+
/** Native asset tag paired with `nativeAmount`. */
|
|
81
91
|
nativeAsset?: "sats" | "usdc" | "usdc.e" | "usd-cents";
|
|
82
|
-
/** Cashu flow discriminator written into `revenue_events.metadata.cashu_flow
|
|
92
|
+
/** Cashu flow discriminator written into `revenue_events.metadata.cashu_flow`. */
|
|
83
93
|
cashuFlow?: "p2pk_accumulator";
|
|
84
94
|
/**
|
|
85
95
|
* What this job cost the **builder** to serve, in 1e-6 of
|
|
86
|
-
* {@link JobRecord.costCurrency}
|
|
96
|
+
* {@link JobRecord.costCurrency}. Mirror of
|
|
87
97
|
* `ServerJob.costAmountMicro`; see that field. Absent means unreported,
|
|
88
98
|
* which the platform treats differently from a declared zero.
|
|
89
99
|
*/
|
|
@@ -97,12 +107,12 @@ interface JobRecord {
|
|
|
97
107
|
*/
|
|
98
108
|
costRevision?: number;
|
|
99
109
|
/**
|
|
100
|
-
* Credit the upfront payment funded/drew
|
|
110
|
+
* Credit the upfront payment funded/drew. The terminal funnel
|
|
101
111
|
* settles the draw on success and releases it on failure/cancel, and the
|
|
102
112
|
* receipt countersigns the `ReceiptCredit` block from it.
|
|
103
113
|
*/
|
|
104
114
|
creditId?: string;
|
|
105
|
-
/** The draw placed for this job on `creditId
|
|
115
|
+
/** The draw placed for this job on `creditId`. */
|
|
106
116
|
drawId?: string;
|
|
107
117
|
/** Funding-time evidence returned on explicit fund-and-draw submissions. */
|
|
108
118
|
fundingReceipt?: FundingReceipt;
|
|
@@ -110,11 +120,11 @@ interface JobRecord {
|
|
|
110
120
|
receivedProofs: ProofLike[];
|
|
111
121
|
pendingPaymentMsats?: number;
|
|
112
122
|
/**
|
|
113
|
-
* Per-job MPP credential binding
|
|
123
|
+
* Per-job MPP credential binding. Challenge ids issued in the
|
|
114
124
|
* most-recent `requestPayment` yield; the SDK rejects mid-job credentials
|
|
115
125
|
* whose `challenge.id` isn't in this set.
|
|
116
126
|
*
|
|
117
|
-
* Keeps its `mpp` spelling past
|
|
127
|
+
* Keeps its `mpp` spelling past rail rename. The ids
|
|
118
128
|
* are mppx challenge ids — objects of the MPP envelope the Tempo rail rides,
|
|
119
129
|
* which is not itself a rail — and this is server-internal anti-replay state
|
|
120
130
|
* that is never serialised to a caller. It persists as
|
|
@@ -122,7 +132,7 @@ interface JobRecord {
|
|
|
122
132
|
*/
|
|
123
133
|
pendingMppChallengeIds?: string[];
|
|
124
134
|
/**
|
|
125
|
-
* Per-job x402 credential binding
|
|
135
|
+
* Per-job x402 credential binding. 0x-prefixed 32-byte hex nonce
|
|
126
136
|
* issued in the most-recent `requestPayment` yield; the SDK rejects mid-job
|
|
127
137
|
* x402 payments whose decoded `authorization.nonce` differs from this value.
|
|
128
138
|
*/
|
|
@@ -135,7 +145,7 @@ interface JobRecord {
|
|
|
135
145
|
pendingX402AmountUsdcMicro?: string;
|
|
136
146
|
/**
|
|
137
147
|
* The outstanding `requestPayment` ask denominated in fiat micro-units, pinned
|
|
138
|
-
* when the payment-request was emitted
|
|
148
|
+
* when the payment-request was emitted — the mid-job analogue of
|
|
139
149
|
* `resolvePriceFiat` pinning the quote. The ledger is fiat-denominated, so the
|
|
140
150
|
* top-up's `fund` + `growDraw` need a figure that doesn't move with the BTC/USD
|
|
141
151
|
* rate between the ask and the payment. Absent when the ask couldn't be priced
|
|
@@ -146,7 +156,7 @@ interface JobRecord {
|
|
|
146
156
|
pendingPaymentFiatCurrency?: string;
|
|
147
157
|
/**
|
|
148
158
|
* What this job has **cumulatively** asked for mid-job, in fiat micro-units
|
|
149
|
-
* of {@link askedTopUpCurrency}
|
|
159
|
+
* of {@link askedTopUpCurrency} — the ceiling `growDraw` caps the
|
|
150
160
|
* job's draw growth at. Monotonic: written by the same Tx A that emits each
|
|
151
161
|
* payment-request, and never decremented, which is exactly what
|
|
152
162
|
* `pendingPaymentFiatMicro` is not (Tx C drains it as payments land). A cap
|
|
@@ -154,7 +164,7 @@ interface JobRecord {
|
|
|
154
164
|
* in the window before Tx C see a full ask that the winner had already
|
|
155
165
|
* bought.
|
|
156
166
|
*
|
|
157
|
-
* `-1` is a sticky "not expressible" sentinel — after
|
|
167
|
+
* `-1` is a sticky "not expressible" sentinel — after the one door
|
|
158
168
|
* left to it is an ask the rate provider was down for. Undefined means no
|
|
159
169
|
* mid-job ask has been recorded (including a row written before this
|
|
160
170
|
* existed). Either way the cap is skipped and growth is unbounded, as it was
|
|
@@ -163,13 +173,13 @@ interface JobRecord {
|
|
|
163
173
|
askedTopUpMicro?: number;
|
|
164
174
|
/**
|
|
165
175
|
* Currency of {@link askedTopUpMicro} (lowercase ISO-4217) — and, from
|
|
166
|
-
*
|
|
176
|
+
* the job's own ask denomination: first-write-wins, and read back
|
|
167
177
|
* by `ctx.requestPayment` so every later ask pins in it too. That is what
|
|
168
178
|
* makes a mid-job currency switch unexpressible rather than merely unlikely.
|
|
169
179
|
*/
|
|
170
180
|
askedTopUpCurrency?: string;
|
|
171
181
|
/**
|
|
172
|
-
* Why this job's draw growth is **not** capped, when it isn't
|
|
182
|
+
* Why this job's draw growth is **not** capped, when it isn't —
|
|
173
183
|
* the durable half of the `-1` sentinel, so an operator can list the affected
|
|
174
184
|
* jobs after the fact rather than reconstruct them from log lines. Sticky
|
|
175
185
|
* first-writer-wins, like the sentinel itself. Null on every job whose ceiling
|
|
@@ -179,7 +189,7 @@ interface JobRecord {
|
|
|
179
189
|
/** Price the job was charged at (msats). Used to detect overpayment for change/melt gating. */
|
|
180
190
|
requiredMsats?: number;
|
|
181
191
|
/**
|
|
182
|
-
* The DVM-signed proof of this job's outcome
|
|
192
|
+
* The DVM-signed proof of this job's outcome. Written once at the
|
|
183
193
|
* terminal transition via `saveReceipt` and never rewritten — `save` leaves
|
|
184
194
|
* the column alone so a stale in-memory snapshot can't clear it. Absent on
|
|
185
195
|
* non-terminal jobs, and on every job when the DVM has no receipt key wired.
|
|
@@ -194,8 +204,8 @@ interface JobRecord {
|
|
|
194
204
|
}
|
|
195
205
|
/**
|
|
196
206
|
* Counter snapshot used by the NOTIFY-driven resolver and the
|
|
197
|
-
* `verifyAndCredit` flow
|
|
198
|
-
* needed to decide whether a pending payment yield can resolve, plus
|
|
207
|
+
* `verifyAndCredit` flow. Carries just the handler-visible state
|
|
208
|
+
* needed to decide whether a pending payment yield can resolve, plus
|
|
199
209
|
* the terminal reason so a machine adopting another machine's cancel can hand
|
|
200
210
|
* the caller's own words to `ctx.signal.reason` and the `onCancel` hook.
|
|
201
211
|
*/
|
|
@@ -211,7 +221,7 @@ interface JobCounters {
|
|
|
211
221
|
summary?: string;
|
|
212
222
|
}
|
|
213
223
|
/**
|
|
214
|
-
* Credit delta written inside the Tx C transaction
|
|
224
|
+
* Credit delta written inside the Tx C transaction when an
|
|
215
225
|
* inbound payment verifies. Fields mirror what the rails produce in
|
|
216
226
|
* `payment.ts`; `paidMsatsDelta` is the only required key.
|
|
217
227
|
*/
|
|
@@ -230,7 +240,7 @@ interface PaymentCreditDelta {
|
|
|
230
240
|
/** Clear the pending nonce + advertised amount after an x402 credit succeeds. */
|
|
231
241
|
clearPendingX402Binding?: boolean;
|
|
232
242
|
/**
|
|
233
|
-
* Credit this payment funded
|
|
243
|
+
* Credit this payment funded. Only ever set when the mid-job
|
|
234
244
|
* top-up minted a *fresh* implicit credit — a free-then-paid job whose
|
|
235
245
|
* upfront leg placed no draw. Written set-if-null: a job already bound to a
|
|
236
246
|
* credit keeps that binding, because the top-up grew its existing draw
|
|
@@ -242,12 +252,14 @@ interface PaymentCreditDelta {
|
|
|
242
252
|
}
|
|
243
253
|
/** Atomic side effects applied with an outgoing provider message. */
|
|
244
254
|
interface AppendOutgoingOptions {
|
|
255
|
+
/** A suspending SDK prompt/payment yield; event-driven messages leave status unchanged. */
|
|
256
|
+
awaitingInput?: boolean;
|
|
245
257
|
pendingPaymentDelta?: number;
|
|
246
258
|
pendingMppChallengeIds?: string[];
|
|
247
259
|
pendingX402Nonce?: string;
|
|
248
260
|
pendingX402AmountUsdcMicro?: string;
|
|
249
261
|
/**
|
|
250
|
-
* Fiat envelope pinned for this ask
|
|
262
|
+
* Fiat envelope pinned for this ask. Accumulates alongside
|
|
251
263
|
* `pendingPaymentDelta` when the currency matches what's already recorded,
|
|
252
264
|
* and replaces it when it doesn't — the same shape `pending_payment_msats`
|
|
253
265
|
* uses, so stacked asks stay summable.
|
|
@@ -256,16 +268,16 @@ interface AppendOutgoingOptions {
|
|
|
256
268
|
pendingPaymentFiatCurrency?: string;
|
|
257
269
|
}
|
|
258
270
|
/**
|
|
259
|
-
* Why a job's cumulative ask total can't bound its draw growth
|
|
271
|
+
* Why a job's cumulative ask total can't bound its draw growth.
|
|
260
272
|
*
|
|
261
273
|
* - `ask_unpriceable` — an ask the rate provider was down for, or one whose
|
|
262
|
-
*
|
|
263
|
-
*
|
|
264
|
-
*
|
|
274
|
+
* fiat figure isn't a safe integer. The only door left after and
|
|
275
|
+
* deliberately still open: failing the charge to protect a ledger comparison
|
|
276
|
+
* would break a payment that doesn't need the rate to be quoted or collected.
|
|
265
277
|
* - `ask_currency_switch` — two asks on one job in different denominations.
|
|
266
|
-
*
|
|
267
|
-
*
|
|
268
|
-
*
|
|
278
|
+
* Unreachable through `ctx.requestPayment`, which pins every ask in the job's
|
|
279
|
+
* own sticky denomination; kept as the backstop for a record written by an
|
|
280
|
+
* older build, and because the accumulator must not silently sum two units.
|
|
269
281
|
*/
|
|
270
282
|
type TopUpCapUnenforcedReason = "ask_unpriceable" | "ask_currency_switch";
|
|
271
283
|
/**
|
|
@@ -278,7 +290,7 @@ interface VerifyAndCreditResult {
|
|
|
278
290
|
alreadyVerified: boolean;
|
|
279
291
|
/**
|
|
280
292
|
* The credit the job row holds **after** this call — the authoritative
|
|
281
|
-
* answer, read back rather than assumed
|
|
293
|
+
* answer, read back rather than assumed.
|
|
282
294
|
*
|
|
283
295
|
* {@link PaymentCreditDelta.creditId} is written set-if-null, so a caller
|
|
284
296
|
* that passes one cannot know whether it won the bind: on a free-then-paid
|
|
@@ -318,7 +330,7 @@ interface JobStore {
|
|
|
318
330
|
/** Retrieve a job record by ID. Returns undefined if not found. */
|
|
319
331
|
get(id: string): Promise<JobRecord | undefined>;
|
|
320
332
|
/**
|
|
321
|
-
* Retrieve the job a settlement reference paid for
|
|
333
|
+
* Retrieve the job a settlement reference paid for. On the cashu
|
|
322
334
|
* accumulator path `paymentTxHash` is the caller's `X-Cashu-Request-Id`, so
|
|
323
335
|
* this is what makes a retried paid submit idempotent: the replay finds the
|
|
324
336
|
* job its (already-spent) payment created instead of a bare 409.
|
|
@@ -347,7 +359,6 @@ interface JobStore {
|
|
|
347
359
|
releaseRequestIdClaim?(claim: RequestIdClaim): Promise<void>;
|
|
348
360
|
/** Upsert a job record. */
|
|
349
361
|
save(record: JobRecord): Promise<void>;
|
|
350
|
-
/** Delete a job record. */
|
|
351
362
|
delete(id: string): Promise<void>;
|
|
352
363
|
}
|
|
353
364
|
/** Total-order cursor for terminal job retention scans. */
|
|
@@ -356,7 +367,7 @@ interface JobRetentionCursor {
|
|
|
356
367
|
id: string;
|
|
357
368
|
}
|
|
358
369
|
/**
|
|
359
|
-
* JobStore extension for signed job receipts
|
|
370
|
+
* JobStore extension for signed job receipts. Implemented by both
|
|
360
371
|
* container-tier stores (`MemoryJobStore`, `PostgresJobStore`); the isolate
|
|
361
372
|
* tier's `IsolateJobStore` deliberately doesn't, which is what keeps the
|
|
362
373
|
* out-of-scope isolate gap a compile-time fact rather than a runtime surprise.
|
|
@@ -385,24 +396,24 @@ interface ReceiptIssuingStore {
|
|
|
385
396
|
saveReceipt(jobId: string, receipt: JobReceipt): Promise<JobReceipt | undefined>;
|
|
386
397
|
}
|
|
387
398
|
/**
|
|
388
|
-
* JobStore extension for cross-machine message streaming + the
|
|
399
|
+
* JobStore extension for cross-machine message streaming + the
|
|
389
400
|
* transactional model (Tx A / Tx B / Tx C).
|
|
390
401
|
*
|
|
391
402
|
* Tx A — outgoing message + immediate counter consequence (`appendOutgoing`).
|
|
392
|
-
*
|
|
393
|
-
*
|
|
394
|
-
*
|
|
403
|
+
* Single tx: server-allocate seq, append `job_messages` row with
|
|
404
|
+
* `status='verified'`, bump `pending_payment_msats` for payment-request
|
|
405
|
+
* messages, and `pg_notify`.
|
|
395
406
|
*
|
|
396
407
|
* Tx B — incoming message marked `pending-verification` (`recordInbound`).
|
|
397
|
-
*
|
|
398
|
-
*
|
|
399
|
-
*
|
|
408
|
+
* Single tx: server-allocate seq, append `job_messages` row with
|
|
409
|
+
* `status='pending-verification'`, and `pg_notify`. External verification
|
|
410
|
+
* (Cashu mint, x402 facilitator, MPP server) runs OUTSIDE the tx.
|
|
400
411
|
*
|
|
401
412
|
* Tx C — verification outcome + credit (`verifyAndCredit`). Single tx:
|
|
402
|
-
*
|
|
403
|
-
*
|
|
404
|
-
*
|
|
405
|
-
*
|
|
413
|
+
* flip the `job_messages.status` to `'verified'`, bump `paid_msats` /
|
|
414
|
+
* clear `pending_payment_msats` per the credit delta, and `pg_notify`.
|
|
415
|
+
* Idempotent — a repeat call returns `alreadyVerified: true` without
|
|
416
|
+
* re-crediting.
|
|
406
417
|
*/
|
|
407
418
|
interface StreamableJobStore extends JobStore {
|
|
408
419
|
/**
|
|
@@ -430,7 +441,7 @@ interface StreamableJobStore extends JobStore {
|
|
|
430
441
|
verifyAndCredit(jobId: string, seq: number, credit: PaymentCreditDelta | null): Promise<VerifyAndCreditResult>;
|
|
431
442
|
/**
|
|
432
443
|
* Read back what Tx C committed for an inbound message, without opening a
|
|
433
|
-
* transaction of its own
|
|
444
|
+
* transaction of its own.
|
|
434
445
|
*
|
|
435
446
|
* A `verifyAndCredit` that throws is ambiguous: the error may have been
|
|
436
447
|
* raised at or after its COMMIT, in which case the write is durable and the
|
|
@@ -454,7 +465,7 @@ interface StreamableJobStore extends JobStore {
|
|
|
454
465
|
/** Read the counters used by the resolver (status / paid / pending). */
|
|
455
466
|
getCounters(jobId: string): Promise<JobCounters | undefined>;
|
|
456
467
|
/**
|
|
457
|
-
* Single-execution claim
|
|
468
|
+
* Single-execution claim. Atomically flip a job from
|
|
458
469
|
* `awaiting-input` to `processing`, returning `true` only for the caller
|
|
459
470
|
* that won the transition. After a mid-job payment lands cross-machine, the
|
|
460
471
|
* live original handler (woken via NOTIFY) and a reactivation replay on the
|
|
@@ -490,13 +501,13 @@ interface StreamableJobStore extends JobStore {
|
|
|
490
501
|
/**
|
|
491
502
|
* Subscribe to raw NOTIFY events for a job. Fires once per `pg_notify`
|
|
492
503
|
* delivery; no message decoding. Used by `Context.requestPayment` to
|
|
493
|
-
* re-read counters when cross-machine credit lands
|
|
504
|
+
* re-read counters when cross-machine credit lands.
|
|
494
505
|
*/
|
|
495
506
|
subscribeNotifications(jobId: string, onNotify: () => void): Promise<() => void>;
|
|
496
507
|
/** Read messages from the `job_messages` table for a job. */
|
|
497
508
|
getMessages(jobId: string, afterSeq: number): Promise<Message[]>;
|
|
498
509
|
/**
|
|
499
|
-
* Find stale non-terminal jobs
|
|
510
|
+
* Find stale non-terminal jobs. Two status-aware
|
|
500
511
|
* cutoffs (both Unix ms): `processing`/`working` rows older than
|
|
501
512
|
* `processingThresholdMs` (worker-liveness watchdog — the SDK heartbeats
|
|
502
513
|
* live workers, so a frozen `last_activity_at` here means the worker died),
|
|
@@ -515,7 +526,7 @@ interface StreamableJobStore extends JobStore {
|
|
|
515
526
|
/**
|
|
516
527
|
* Atomically transition a stale job to `terminalStatus` (`failed` for a
|
|
517
528
|
* dead worker, `cancelled` for an idle caller-wait) and append a final
|
|
518
|
-
* `cancel` message in the same transaction
|
|
529
|
+
* `cancel` message in the same transaction. The
|
|
519
530
|
* `expectedActivityBefore` clause is an optimistic CAS — the flip only
|
|
520
531
|
* lands when the job is still non-terminal AND `last_activity_at <=
|
|
521
532
|
* expectedActivityBefore`. Returns true when this caller claimed the
|
|
@@ -525,8 +536,8 @@ interface StreamableJobStore extends JobStore {
|
|
|
525
536
|
*/
|
|
526
537
|
cancelStaleJob(jobId: string, expectedActivityBefore: number, reason: string, terminalStatus: "failed" | "cancelled"): Promise<boolean>;
|
|
527
538
|
/**
|
|
528
|
-
* Atomically cancel a job from a machine that isn't running its handler
|
|
529
|
-
*
|
|
539
|
+
* Atomically cancel a job from a machine that isn't running its handler.
|
|
540
|
+
* Same transaction shape as {@link cancelStaleJob} minus the
|
|
530
541
|
* activity cutoff — the CAS guards only on the job still being non-terminal,
|
|
531
542
|
* so this replaces the read-then-`save` the DELETE route used to do (a TOCTOU
|
|
532
543
|
* against a concurrent terminal write).
|
|
@@ -541,7 +552,7 @@ interface StreamableJobStore extends JobStore {
|
|
|
541
552
|
cancelJob(jobId: string, reason: string): Promise<boolean>;
|
|
542
553
|
/**
|
|
543
554
|
* Bump `last_activity_at` to `now` (Unix ms) for the given jobs that are
|
|
544
|
-
* still in `processing`/`working
|
|
555
|
+
* still in `processing`/`working`. Called on a
|
|
545
556
|
* tick by the `JobManager` for its locally-active jobs so a live worker's
|
|
546
557
|
* row stays fresh and the processing watchdog only fires when the process
|
|
547
558
|
* has actually died. A no-op for rows that have since gone terminal or
|
|
@@ -571,7 +582,7 @@ interface OutgoingMessage {
|
|
|
571
582
|
*/
|
|
572
583
|
declare function isStreamableJobStore(store: JobStore): store is StreamableJobStore;
|
|
573
584
|
/**
|
|
574
|
-
* The stale-job reaper surface
|
|
585
|
+
* The stale-job reaper surface — the two methods a sweeper needs to
|
|
575
586
|
* find and atomically reap worker-stranded jobs. A strict subset of
|
|
576
587
|
* `StreamableJobStore`: `MemoryJobStore` and `PostgresJobStore` satisfy it via
|
|
577
588
|
* the full streamable interface, and the platform's `IsolateJobStore` (a plain
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { W as JsonValue } from './step-cache-
|
|
1
|
+
import { W as JsonValue } from './step-cache-CXg7ziML.js';
|
|
2
2
|
|
|
3
3
|
declare const lockPubkeyBrand: unique symbol;
|
|
4
4
|
/**
|
|
@@ -23,11 +23,9 @@ type LockPubkey = string & {
|
|
|
23
23
|
declare function toLockPubkey(raw: string): LockPubkey;
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
|
-
* Canonical deploy-time attestation payload
|
|
26
|
+
* Canonical deploy-time attestation payload. One signature serves
|
|
27
27
|
* both auth-on-deploy and the `/v1/info#builder` attestation — the bytes the
|
|
28
|
-
* builder signs are the canonical JSON of this object.
|
|
29
|
-
* also requires the coordinated fleet-before-caller release note in
|
|
30
|
-
* `public compatibility guide`.
|
|
28
|
+
* builder signs are the canonical JSON of this object.
|
|
31
29
|
*/
|
|
32
30
|
interface AttestationPayload {
|
|
33
31
|
/** Immutable platform or self-hosted DVM identifier this attestation applies to. */
|
|
@@ -35,12 +33,12 @@ interface AttestationPayload {
|
|
|
35
33
|
/** DVM slug the attestation applies to (must match the deploy request's slug). */
|
|
36
34
|
slug: string;
|
|
37
35
|
/** sha256(`canonicaliseForSigning(capabilities)`) hex. Binds the attestation
|
|
38
|
-
*
|
|
36
|
+
* to the capability shape declared at deploy time. */
|
|
39
37
|
capabilities_hash: string;
|
|
40
38
|
/** Builder identity x-only secp256k1 pubkey, hex (32 bytes / 64 chars). */
|
|
41
39
|
builder_pubkey: string;
|
|
42
40
|
/**
|
|
43
|
-
* Per-DVM receipt-signing x-only pubkey, hex
|
|
41
|
+
* Per-DVM receipt-signing x-only pubkey, hex. Binds the key the
|
|
44
42
|
* deployed DVM signs job receipts with to the cold builder identity: the
|
|
45
43
|
* builder signs this payload, so a receipt verifying under
|
|
46
44
|
* `receipt_pubkey` inherits the builder's authority.
|
|
@@ -54,14 +52,12 @@ interface AttestationPayload {
|
|
|
54
52
|
/** Unix seconds at which the attestation was signed. */
|
|
55
53
|
deployed_at: number;
|
|
56
54
|
}
|
|
57
|
-
/** Result of {@link generateIdentity}: hex pubkey + hex secret. */
|
|
58
55
|
interface BuilderIdentityKeypair {
|
|
59
56
|
/** secp256k1 BIP-340 x-only pubkey, 32 bytes hex (64 chars). */
|
|
60
57
|
pubkey: string;
|
|
61
58
|
/** secp256k1 secret, 32 bytes hex (64 chars). */
|
|
62
59
|
secret: string;
|
|
63
60
|
}
|
|
64
|
-
/** Generate a fresh BIP-340 Schnorr keypair for builder identity. */
|
|
65
61
|
declare function generateIdentity(): BuilderIdentityKeypair;
|
|
66
62
|
/**
|
|
67
63
|
* Read the builder identity secret from `~/.dvmkit/builder.key`. Returns
|
|
@@ -96,7 +92,7 @@ declare function writeIdentity(keypair: BuilderIdentityKeypair, opts?: {
|
|
|
96
92
|
*/
|
|
97
93
|
declare function hashCapabilities(capabilities: JsonValue): string;
|
|
98
94
|
/**
|
|
99
|
-
* Assemble the deploy-time attestation payload
|
|
95
|
+
* Assemble the deploy-time attestation payload. `deployedAt`
|
|
100
96
|
* defaults to the current Unix second; tests can pin it for reproducibility.
|
|
101
97
|
*/
|
|
102
98
|
declare function buildAttestation(args: {
|
|
@@ -104,8 +100,8 @@ declare function buildAttestation(args: {
|
|
|
104
100
|
slug: string;
|
|
105
101
|
capabilities: JsonValue;
|
|
106
102
|
builderPubkey: string;
|
|
107
|
-
/** Receipt-signing pubkey to attest
|
|
108
|
-
*
|
|
103
|
+
/** Receipt-signing pubkey to attest. Omitted when the deploy path
|
|
104
|
+
* can't provision the matching `DVMKIT_RECEIPT_KEY`. */
|
|
109
105
|
receiptPubkey?: string;
|
|
110
106
|
deployedAt?: number;
|
|
111
107
|
}): AttestationPayload;
|
|
@@ -126,7 +122,7 @@ declare function verifyAttestation(payload: AttestationPayload, signatureHex: st
|
|
|
126
122
|
|
|
127
123
|
/**
|
|
128
124
|
* Per-method amount limits a mint advertises on its NUT-4 / NUT-5 bolt11/sat
|
|
129
|
-
* entry
|
|
125
|
+
* entry. Both values are in the method's own unit — `sat` here,
|
|
130
126
|
* never msats.
|
|
131
127
|
*
|
|
132
128
|
* `null` means the mint advertised nothing in that direction, which reads as
|
|
@@ -167,7 +163,7 @@ interface MintHealthCheckResult {
|
|
|
167
163
|
* is not switched off (`disabled: true`). Distinct from
|
|
168
164
|
* {@link bolt11SatMintSupported}, which only asks whether the method exists:
|
|
169
165
|
* a mint in melt-only recovery keeps advertising the method and turns the
|
|
170
|
-
* flag on. Consulted when picking a funding default
|
|
166
|
+
* flag on. Consulted when picking a funding default.
|
|
171
167
|
*/
|
|
172
168
|
mintingEnabled?: boolean;
|
|
173
169
|
/** Same question for NUT-05 (melt) — whether the mint can currently pay out. */
|
|
@@ -176,12 +172,11 @@ interface MintHealthCheckResult {
|
|
|
176
172
|
* True when the mint can currently serve `/v1/swap` — see {@link canSwap} for
|
|
177
173
|
* why an unadvertised NUT-3 reads as `true`. This is what a per-call spend
|
|
178
174
|
* needs, so a `false` here is the reason a spend routes around this mint
|
|
179
|
-
* (internal-review).
|
|
180
175
|
*/
|
|
181
176
|
swapEnabled?: boolean;
|
|
182
177
|
/**
|
|
183
178
|
* Amount limits the mint advertises for issuing (NUT-04 bolt11/sat), in sats
|
|
184
|
-
*
|
|
179
|
+
* Consulted when picking a funding default and when refusing an
|
|
185
180
|
* amount locally, so a fund outside the range never opens a Lightning quote.
|
|
186
181
|
*/
|
|
187
182
|
mintAmountBounds?: MintAmountBounds;
|
|
@@ -191,7 +186,7 @@ interface MintHealthCheckResult {
|
|
|
191
186
|
* True when the mint passes the full {@link assertNutSupport} gate — every
|
|
192
187
|
* required NUT present (not `supported: false`) and bolt11/sat on NUT-4 +
|
|
193
188
|
* NUT-5. The runtime `MintHealthTracker` treats a mint as healthy only when
|
|
194
|
-
* this is true, reproducing the boot-time NUT gate post-`listen
|
|
189
|
+
* this is true, reproducing the boot-time NUT gate post-`listen`.
|
|
195
190
|
*/
|
|
196
191
|
nutCompliant?: boolean;
|
|
197
192
|
/** Raw `nuts` object from the `/v1/info` response. Used by `assertNutSupport`. */
|
|
@@ -202,7 +197,6 @@ interface MintHealthCheckResult {
|
|
|
202
197
|
message: string;
|
|
203
198
|
};
|
|
204
199
|
}
|
|
205
|
-
/** Tunables for `checkMintHealth`. */
|
|
206
200
|
interface CheckMintHealthOptions {
|
|
207
201
|
/** Per-attempt timeout in ms. Default: 5000. */
|
|
208
202
|
timeoutMs?: number;
|
|
@@ -221,11 +215,10 @@ interface CheckMintHealthOptions {
|
|
|
221
215
|
declare function checkMintHealth(mintUrl: string, opts?: CheckMintHealthOptions): Promise<MintHealthCheckResult>;
|
|
222
216
|
/**
|
|
223
217
|
* Whether the mint can currently serve `/v1/swap` — the operation every
|
|
224
|
-
* per-call Cashu payment depends on
|
|
218
|
+
* per-call Cashu payment depends on.
|
|
225
219
|
*
|
|
226
220
|
* **An absent NUT-3 means yes.** Swap is a baseline mint operation and healthy
|
|
227
|
-
* mints do not enumerate it — neither coinos nor lnvoltz advertises a `"3"` key
|
|
228
|
-
* (see `public design rationale`).
|
|
221
|
+
* mints do not enumerate it — neither coinos nor lnvoltz advertises a `"3"` key.
|
|
229
222
|
* Reading silence as "incapable" would rule out every working mint.
|
|
230
223
|
*
|
|
231
224
|
* A mint that has *switched swaps off* does say so: a mint in melt-only
|
|
@@ -250,11 +243,11 @@ declare function amountBoundsVerdict(sats: number, bounds?: MintAmountBounds): A
|
|
|
250
243
|
/**
|
|
251
244
|
* Assert that a mint's NUT-06 `nuts` object advertises all required capabilities.
|
|
252
245
|
* Two-phase check:
|
|
253
|
-
*
|
|
254
|
-
*
|
|
255
|
-
*
|
|
256
|
-
*
|
|
257
|
-
*
|
|
246
|
+
* 1. Dict-level — each NUT in `requiredNuts` must be present and not have
|
|
247
|
+
* `supported: false`. Throws naming the missing NUT numbers and mint URL.
|
|
248
|
+
* 2. Method-level — NUT-4 and NUT-5 must each advertise a `bolt11`/`sat`
|
|
249
|
+
* entry in their `methods` array (covers NUT-23). Throws naming the
|
|
250
|
+
* missing method.
|
|
258
251
|
*/
|
|
259
252
|
declare function assertNutSupport(mintUrl: string, nuts: Record<string, unknown>, requiredNuts?: readonly number[]): void;
|
|
260
253
|
|
|
@@ -269,7 +262,6 @@ interface CreatedInvoice {
|
|
|
269
262
|
/** Unix milliseconds when the invoice expires. */
|
|
270
263
|
expiresAt: number;
|
|
271
264
|
}
|
|
272
|
-
/** Result of looking up an invoice's settlement status. */
|
|
273
265
|
interface InvoiceStatus {
|
|
274
266
|
/** True once the invoice has been paid and preimage is known. */
|
|
275
267
|
settled: boolean;
|
|
@@ -27,7 +27,7 @@ var PostgresConsumedCredentialStore = class {
|
|
|
27
27
|
async init() {
|
|
28
28
|
await withSdkInitLock(this.pool, () => this.createTables());
|
|
29
29
|
}
|
|
30
|
-
/** The boot DDL itself — always runs under {@link withSdkInitLock}
|
|
30
|
+
/** The boot DDL itself — always runs under {@link withSdkInitLock}. */
|
|
31
31
|
async createTables() {
|
|
32
32
|
await this.pool.query(`
|
|
33
33
|
CREATE TABLE IF NOT EXISTS ${this.tableName} (
|