@dvmkit/sdk 0.1.1-rc.7 → 0.1.3-rc.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +14 -0
  2. package/dist/chunk-2K7E3N2D.js +1709 -0
  3. package/dist/{chunk-Y6W5ZZTW.js → chunk-3ZHMQCYP.js} +666 -3031
  4. package/dist/{chunk-TKA6ZP4M.js → chunk-4B56DEEV.js} +50 -426
  5. package/dist/{chunk-X3IKFWJA.js → chunk-6BQM7TOW.js} +4 -1
  6. package/dist/chunk-BIFLRKMO.js +87 -0
  7. package/dist/chunk-BQ2NMWKE.js +160 -0
  8. package/dist/{chunk-LDTWX7JW.js → chunk-BTZY7VPH.js} +13 -1
  9. package/dist/{chunk-FJDCFHW5.js → chunk-C6JHBLMW.js} +3 -81
  10. package/dist/{chunk-EXHBXA4U.js → chunk-DBCLBYHP.js} +13 -1
  11. package/dist/chunk-EPNDZ5DH.js +1010 -0
  12. package/dist/{chunk-P4RUVDU7.js → chunk-H2MEFVH6.js} +12 -141
  13. package/dist/chunk-KXZUCCEY.js +142 -0
  14. package/dist/{chunk-6JZIX5WW.js → chunk-LLXV32HA.js} +82 -5
  15. package/dist/{chunk-LWUR4CGG.js → chunk-MLRCSJYX.js} +11 -3
  16. package/dist/{chunk-2ABMGUDS.js → chunk-NFRM5QYP.js} +83 -10
  17. package/dist/chunk-RW5LP57K.js +44 -0
  18. package/dist/chunk-YDIYXGYL.js +384 -0
  19. package/dist/{chunk-JGGI65I3.js → chunk-Z4BNLUZF.js} +1 -150
  20. package/dist/{credit-ledger-ED6JXKVD.js → credit-ledger-2DFQHNLB.js} +2 -2
  21. package/dist/{credit-menu-BrTfAr7l.d.ts → credit-menu-C7zAJElJ.d.ts} +1632 -1946
  22. package/dist/{fx-H6K6qcH1.d.ts → fx-BF_SG2i0.d.ts} +1 -1
  23. package/dist/index.d.ts +7 -6
  24. package/dist/index.js +8 -4
  25. package/dist/internal/caller.d.ts +10429 -0
  26. package/dist/internal/caller.js +9957 -0
  27. package/dist/internal/index.d.ts +2 -10816
  28. package/dist/internal/index.js +2 -10130
  29. package/dist/internal/server.d.ts +404 -0
  30. package/dist/internal/server.js +202 -0
  31. package/dist/job-store-Bn23V3QU.d.ts +576 -0
  32. package/dist/lightning-backend-C04nH94l.d.ts +367 -0
  33. package/dist/{memory-credit-ledger-XJ5VQEVP.js → memory-credit-ledger-OP24Z2KO.js} +3 -3
  34. package/dist/{payout-reporter-3UB5WRCV.js → payout-reporter-RG6XNGPI.js} +1 -1
  35. package/dist/{postgres-job-store-J5F4GUWU.js → postgres-job-store-TAONYLIF.js} +1 -1
  36. package/dist/{revenue-reporter-JIKUPXOK.js → revenue-reporter-XXSU5KVB.js} +1 -1
  37. package/dist/server/index.d.ts +27 -11
  38. package/dist/server/index.js +93 -69
  39. package/dist/{job-store-DOSfYnLX.d.ts → step-cache-3cT4Shk0.d.ts} +38 -585
  40. package/dist/{tempo-session-store-DALMRIWN.js → tempo-session-store-2JNOKJGX.js} +2 -2
  41. package/dist/testing/index.d.ts +16 -4
  42. package/dist/testing/index.js +7 -3
  43. package/dist/{usd-Civ738b3.d.ts → usd-BnuXoFl5.d.ts} +1 -1
  44. package/dist/wallet-CJC8lwxx.d.ts +29 -0
  45. package/dist/{x402-FTG2GRAQ.js → x402-T2C5MX3T.js} +6 -3
  46. package/package.json +7 -2
  47. package/dist/{chunk-RU7SXHLO.js → chunk-UP2F5RRT.js} +3 -3
@@ -0,0 +1,404 @@
1
+ import { FacilitatorConfig } from '@x402/core/server';
2
+ import { ai as PaymentPayload, ao as PaymentRequirementsV1, ap as PaymentRequirementsV2, aD as X402Config, au as SettleResponse, aB as VerifyResponse, bh as X402ExactVersionSupport, bi as X402Receipt, bj as TransactionalPayoutHook, bk as CashuMeltCompleted } from '../step-cache-3cT4Shk0.js';
3
+ export { bl as CreditDepositPayload, bm as CreditDrainPayload, bn as FundingLot, bo as LotDebit, bp as LotDepletion, bq as MppxServer, br as NON_CHANNEL_BITCOIN_RAILS, bs as NonChannelBitcoinRail, bt as PayoutReporter, bu as PostgresTempoSessionStore, bv as RevenueReporter, bw as SIGNED_ENVELOPE_FIELDS, bx as SIGNED_ENVELOPE_TYPES, by as X402TrackedChannel, bz as _testing, bA as createDefaultReplayStore, bB as depleteLots, bC as fifoOrder, bD as inKindDrawMsats, bE as isInKindDepletion, bF as isNonChannelBitcoinRail, bG as lotOwedSats, bH as netOwedSats, bI as wrapMppx } from '../step-cache-3cT4Shk0.js';
4
+ import { Hono } from 'hono';
5
+ import { Env, BlankSchema } from 'hono/types';
6
+ import { Pool } from 'pg';
7
+ export { Pool } from 'pg';
8
+ import { g as getWallet } from '../wallet-CJC8lwxx.js';
9
+ import { A as AccumulatorPool, a as AccumulatorQuerier, C as ConsumedCredentialStore } from '../credit-menu-C7zAJElJ.js';
10
+ export { b as AppEnv, c as CreditFundingReport, F as FiatDenomination, d as FiatDenominationFailure, e as FundOnlyRequest, I as IncomingPaymentOpts, J as JobCancelledError, M as MintHealthTracker, P as PAYMENT_PROOF_KEYS, f as PaymentErrorCode, g as PaymentErrorDetail, h as PaymentInfo, R as ReporterBannerOpts, i as ResolvedFx, j as RevenueBootCheckOpts, S as SDKServerOpts, k as ServerJob, l as ShortPayForfeit, T as TempoChannelReport, m as TempoObserverHealth, n as TempoSessionChannelMismatchError, U as UpfrontPaymentOpts, V as VerifiedIncomingPayment, o as VerifyIncomingSnapshot, X as X402BatchChannelObservation, p as X402FacilitatorHealth, q as X402SettlementEvidenceOutcome, r as X402SettlementRepair, s as X402SettlementRepairRefusal, t as X402SettlementRepaired, u as X402WedgedSettlement, v as X402WedgedSettlementPage, w as X402_BATCH_SETTLEMENT_MAINNET_NETWORK, x as abortJob, y as applyPaymentInfoToJob, z as assertRevenueReporterReady, B as buildPaymentErrorResponse, D as clearAccumulatorForDvm, E as createDVMServer, G as creditDepositPayload, H as derivedFundCreditId, K as devModeSkipsPaymentVerification, L as fromJobRecord, N as fundedMicroFor, O as hasPaymentProof, Q as hashLockKey, W as implicitCreditId, Y as initWalletAccumulatorTable, Z as insertAccumulatorRows, _ as isDerivedCreditId, $ as isTerminal, a0 as isYieldMessage, a1 as issueUpfrontChallenges, a2 as msatsToFiatMicro, a3 as paymentErrorBody, a4 as pinAskFiat, a5 as priceFiatMicro, a6 as processIncomingPayment, a7 as providerMessage, a8 as repairX402ExactSettlementEffect, a9 as resolveFxSnapshot, aa as resolvePriceFiat, ab as revenueReporterBannerState, ac as toCreditTerms, ad as toJobRecord, ae as unknownRouteNotFound, af as verifyIncomingPayment, ag as verifyTempoSessionManagementCredential, ah as verifyUpfrontPayment, ai as x402RequiredUsdcMicro, aj as x402SettledShare } from '../credit-menu-C7zAJElJ.js';
11
+ import { g as LockPubkey } from '../lightning-backend-C04nH94l.js';
12
+ export { t as lockPubkeyStoreToLockPubkey } from '../lightning-backend-C04nH94l.js';
13
+ export { O as OutgoingMessage, S as StaleJobReapable, i as isStaleJobReapable } from '../job-store-Bn23V3QU.js';
14
+ import { Store } from 'mppx';
15
+ import { z } from 'zod';
16
+ import '@x402/evm/batch-settlement/server';
17
+ import 'viem';
18
+ import '@x402/core/types';
19
+ import '@cashu/cashu-ts';
20
+ import '../fx-BF_SG2i0.js';
21
+
22
+ /** POST a verify request to the configured facilitator. */
23
+ declare function verifyWithFacilitator(payload: PaymentPayload, requirements: PaymentRequirementsV1 | PaymentRequirementsV2, config?: Pick<X402Config, "facilitator" | "facilitatorAuth">, createAuthHeaders?: FacilitatorConfig["createAuthHeaders"] | undefined): Promise<VerifyResponse>;
24
+ /** POST a settlement request to the configured facilitator. */
25
+ declare function settleWithFacilitator(payload: PaymentPayload, requirements: PaymentRequirementsV1 | PaymentRequirementsV2, config?: Pick<X402Config, "facilitator" | "facilitatorAuth">, createAuthHeaders?: FacilitatorConfig["createAuthHeaders"] | undefined): Promise<SettleResponse>;
26
+
27
+ /**
28
+ * Verify an x402 `X-PAYMENT` header per the x402 spec (internal-review).
29
+ *
30
+ * Flow:
31
+ * 1. Decode the base64 `PaymentPayload`
32
+ * 2. Rebuild the `PaymentRequirements` the server advertised on the 402 — the
33
+ * facilitator deep-equals these against the payload's authorization, so a
34
+ * credential bought against any other set fails verification.
35
+ * 3. Call the facilitator's `/verify`
36
+ * 4. On valid, call the facilitator's `/settle` to broadcast the EIP-3009
37
+ * `transferWithAuthorization`. The on-chain tx hash flows through to the
38
+ * receipt and into `X-PAYMENT-RESPONSE` for the client.
39
+ *
40
+ * A positive `btcUsdRate` converts the settled USDC back to msats. Zero means
41
+ * the requirement was already stated exactly in USD and no rate was needed;
42
+ * in that case `amountMsats` degrades to zero while `amountUsdcMicro` remains
43
+ * authoritative. Upfront accounting values that native amount against the
44
+ * advertised requirement, so it never books the degraded field.
45
+ */
46
+ declare function verifyX402Payment(paymentHeader: string, config: X402Config, requiredUsdcMicro: bigint, resource: string, btcUsdRate: number, exactVersions?: X402ExactVersionSupport): Promise<X402Receipt>;
47
+
48
+ /**
49
+ * Snapshot of a DVM's published lock-pubkey state at a point in time. `current`
50
+ * is what the SDK advertises as `cashu.lock_pubkeys[0]`; `retired` are the
51
+ * pubkeys that have been rotated out but still fall inside the rotation grace
52
+ * window (`cashu.lock_pubkey_grace_seconds`). Both halves are needed by the
53
+ * receive path (accept proofs locked to any entry) and the admin auth verifier
54
+ * (accept signatures from any entry during grace).
55
+ */
56
+ interface LockPubkeyState {
57
+ current: LockPubkey;
58
+ retired: {
59
+ pubkey: LockPubkey;
60
+ retiredAtMs: number;
61
+ }[];
62
+ }
63
+ /**
64
+ * Lazy accessor for the DVM's lock-pubkey state. Threaded through the SDK
65
+ * server so call sites (info handler, accept flow, admin auth) read the fresh
66
+ * state on every invocation — rotation propagation has to be visible without
67
+ * a process restart.
68
+ */
69
+ type LockPubkeyStateLoader = () => Promise<LockPubkeyState>;
70
+ /**
71
+ * Subset of pg.Pool used by the lock-pubkey store. Sharing `AccumulatorPool`
72
+ * keeps the SDK's "pass me a Postgres pool" surface uniform across stores.
73
+ */
74
+ type LockPubkeyPool = AccumulatorPool;
75
+ /**
76
+ * Create the `dvm_lock_pubkeys` table if absent. Each row is one entry in a
77
+ * DVM's lock-pubkey lifecycle: `retired_at_ms IS NULL` is the current pubkey,
78
+ * any non-null value is a retired pubkey that the rotation walker can still
79
+ * derive privkeys for. One current row per `dvm_id` is enforced via a partial
80
+ * unique index — keeps `rotateLockPubkey` honest under concurrent calls.
81
+ */
82
+ declare function initLockPubkeyTable(db: LockPubkeyPool): Promise<void>;
83
+ /**
84
+ * Idempotent first-boot seed. Inserts `pubkey` as the current row for `dvmId`
85
+ * only when no current row exists. Reseeding with a different pubkey is a
86
+ * no-op — once the DB has state, `rotateLockPubkey` is the only sanctioned
87
+ * mutator, so a stale `DVMKIT_CASHU_LOCK_PUBKEY` env on a redeploy can't
88
+ * silently reset the DVM's view of "what's current".
89
+ *
90
+ * Also backfills any distinct `lock_pubkey` values found in
91
+ * `wallet_accumulator` for this DVM that aren't yet in `dvm_lock_pubkeys`,
92
+ * inserting them as retired rows with `retired_at_ms = 0` — the
93
+ * "long-retired-still-meltable" sentinel. This handles pre-internal-review batches
94
+ * that would otherwise trip the monitor's `orphan_lock_pubkey` alarm every
95
+ * tick. Sentinel-0 rows are exempt from grace-window filtering and
96
+ * `pruneRetired` so they stay visible until the operator melts the legacy
97
+ * batches and the receive path keeps accepting in-flight tokens locked to
98
+ * them.
99
+ *
100
+ * Two simultaneous cold boots can both pass the `WHERE NOT EXISTS` guard, and
101
+ * the loser then takes a 23505 on `dvm_lock_pubkeys_current_uidx` — the shape
102
+ * internal-review fixed for `mpp_secret_state`, reached here through the same
103
+ * first-boot window. Closed the same way, with `ON CONFLICT DO NOTHING` on
104
+ * that partial index: the boot lock (internal-review) serializes the cross-machine
105
+ * half, but two callers on one pool share its acquisition (a fire-and-forget
106
+ * hydrate overlapping boot's), so the guard has to hold without it.
107
+ */
108
+ declare function seedLockPubkeyState(db: LockPubkeyPool, dvmId: string, pubkey: string, now?: number): Promise<void>;
109
+ /**
110
+ * Read the active lock-pubkey state for a DVM. Retired rows older than the
111
+ * grace window are filtered out; aged-out rows linger physically until
112
+ * `pruneRetired` deletes them on a monitor tick. Sentinel-0 rows (the
113
+ * `retired_at_ms = 0` legacy backfill from `seedLockPubkeyState`) are always
114
+ * included regardless of grace. Throws when no current row exists — the SDK's
115
+ * accept/info/admin paths must not run before `seedLockPubkeyState` has been
116
+ * called.
117
+ */
118
+ declare function loadLockPubkeyState(db: AccumulatorQuerier, dvmId: string, graceMs: number, now?: number): Promise<LockPubkeyState>;
119
+ /**
120
+ * Atomically demote the current pubkey to retired (stamping `retired_at_ms`)
121
+ * and insert `newPubkey` as the new current row. Wrapped in a transaction so
122
+ * the partial unique index never has two current rows visible mid-rotation.
123
+ * Returns the post-rotation state filtered by the supplied grace window.
124
+ */
125
+ declare function rotateLockPubkey(db: LockPubkeyPool, dvmId: string, newPubkey: string, graceMs: number, now?: number): Promise<LockPubkeyState>;
126
+ /**
127
+ * Delete retired rows whose `retired_at_ms` is older than `now - graceMs`.
128
+ * Called from the monitor tick so aged-out entries don't accumulate.
129
+ * `wallet_accumulator` rows pointing at those pubkeys remain meltable (the
130
+ * builder can still derive the privkey from the mnemonic + rotation_index) —
131
+ * pruning only affects what the DVM advertises and accepts.
132
+ *
133
+ * Sentinel-0 rows (the legacy backfill from `seedLockPubkeyState`) are
134
+ * exempted from pruning — they exist precisely so the monitor keeps treating
135
+ * legacy `wallet_accumulator` batches as retired-still-meltable rather than
136
+ * orphan.
137
+ */
138
+ declare function pruneRetired(db: AccumulatorQuerier, dvmId: string, graceMs: number, now?: number): Promise<number>;
139
+ /**
140
+ * Default rotation grace window — 24h, per §4.5 of the cashu-integration
141
+ * design note. Operators tune via `BUILDER_LOCK_PUBKEY_GRACE_SECONDS`.
142
+ */
143
+ declare const DEFAULT_LOCK_PUBKEY_GRACE_SECONDS = 86400;
144
+ /**
145
+ * Lift a single pubkey + grace-filtered retired list into the flat array the
146
+ * accept path checks against. Convenience for call sites that don't care
147
+ * about the retired-row structure.
148
+ */
149
+ declare function activePubkeySet(state: LockPubkeyState): LockPubkey[];
150
+
151
+ /** Options for `installAdminCashuRoutes`. */
152
+ interface InstallAdminCashuRoutesOpts {
153
+ /** Pool against the SDK's accumulator DB. */
154
+ db: Pool;
155
+ /** Identifier of this DVM — bound into every signed admin challenge. */
156
+ dvmId: string;
157
+ /**
158
+ * Live lock-pubkey state loader. Auth accepts a signature from the current
159
+ * pubkey or any retired pubkey still within the rotation grace window
160
+ * (internal-review). The `/admin/cashu/rotate-lock-pubkey` route narrows that to
161
+ * current-only.
162
+ */
163
+ getLockPubkeyState: LockPubkeyStateLoader;
164
+ /** Rotation grace window in seconds — threaded into `rotateLockPubkey`. */
165
+ graceSeconds: number;
166
+ /** Replay-protection store keyed by nonce. */
167
+ nonceStore: ConsumedCredentialStore;
168
+ /**
169
+ * Runs inside the transaction that marks the rows melted (internal-review): the
170
+ * proofs are SPENT and the Lightning payment reached the builder, so the
171
+ * melt is a landed payout, and its report commits with the mark or not at
172
+ * all. `enqueue` throwing rolls the mark back and fails the call — the CLI's
173
+ * recovery re-posts `mark-melted` on its next run, where a melt marked with
174
+ * no row would understate paid-out forever. `committed` runs after.
175
+ */
176
+ onMelted?: TransactionalPayoutHook<CashuMeltCompleted>;
177
+ /** Override for cashu-ts wallet construction (tests). */
178
+ walletProvider?: typeof getWallet;
179
+ /** Override for the current time (tests). Returns ms since epoch. */
180
+ now?: () => number;
181
+ }
182
+ /**
183
+ * Register the four admin endpoints on the supplied Hono app. Idempotent at
184
+ * the call site — `app.ts` only invokes this when accumulator config is
185
+ * complete (`cashuMode === "p2pk-accumulator"`, `db`, `dvmId`, `lockPubkey`).
186
+ */
187
+ declare function installAdminCashuRoutes<E extends Env = Env, S extends BlankSchema = BlankSchema>(app: Hono<E, S>, opts: InstallAdminCashuRoutesOpts): void;
188
+ /**
189
+ * Convenience constructor for the in-memory nonce store — exported so callers
190
+ * outside `app.ts` (tests, custom wiring) can mint a store with the same caps
191
+ * the SDK uses by default.
192
+ */
193
+ declare function createAdminCashuNonceStore(): ConsumedCredentialStore;
194
+
195
+ /**
196
+ * The `fx_rate_unavailable` payment-error detail, shaped like every other flat
197
+ * payment error (internal-review): a flat machine `error` code plus `message` and the
198
+ * `display`/`hint`/`retryable` fields an agent relays verbatim and branches
199
+ * retries on — the shape the `paymentErrorBody` builder enforces for the sibling
200
+ * 503s (`mint_health_pending`, `cashu_mint_sick`) and the 402 family alike. This
201
+ * one is built by hand rather than through the builder because its copy already
202
+ * lives on `FxRateUnavailableError`, shared with the quote path's nested
203
+ * envelope. 503 rather than 402 — the caller's payment isn't the problem, our
204
+ * pricing is.
205
+ */
206
+ declare function rateUnavailablePaymentError(): {
207
+ body: Record<string, unknown>;
208
+ status: number;
209
+ };
210
+
211
+ /**
212
+ * Create a fetch wrapper that emits `dvm.fetch` spans via `loggers.isolate`.
213
+ *
214
+ * Attributes include the redacted URL, HTTP method, and (post-response)
215
+ * status code. When observability is disabled, `loggers.isolate` is the no-op
216
+ * logger — `span()` calls `fn()` directly with zero overhead.
217
+ *
218
+ * `signal` (internal-review) is the job's cancellation signal. When supplied, every
219
+ * request made through this fetch aborts on job cancel — that is what stops
220
+ * provider spend mid-job. It is *merged* with any caller-supplied
221
+ * `init.signal` rather than replacing it, so a per-request timeout (scrapfly,
222
+ * cast's ranged GET, …) keeps working and either signal can abort the call.
223
+ */
224
+ declare function createInstrumentedFetch(signal?: AbortSignal): typeof globalThis.fetch;
225
+
226
+ /**
227
+ * The subset of Hono's request object these helpers need. Structural rather
228
+ * than `HonoRequest` so both runtimes' `Context` generics pass without either
229
+ * side importing the other's env type.
230
+ */
231
+ interface JobCredentialRequest {
232
+ header(name: string): string | undefined;
233
+ }
234
+ /**
235
+ * internal-review: the credential gate on a runtime's `/v1/job/:id/*` routes — the
236
+ * "did this request present anything?" predicate and the 401 body that answers
237
+ * when it didn't, built together so the copy can never describe a credential
238
+ * the predicate doesn't accept.
239
+ */
240
+ interface JobCredentialGate {
241
+ /** Did this request present *any* credential this runtime accepts? */
242
+ presents(req: JobCredentialRequest): boolean;
243
+ /** The flat 401 body for a request that presented none. */
244
+ body(): Record<string, unknown>;
245
+ }
246
+ /**
247
+ * internal-review: build the credential gate for one runtime.
248
+ *
249
+ * `acceptsBearer` is what separates them. The isolate tier derives
250
+ * `requesterId` from `Authorization: Bearer`, so a Bearer token really is a
251
+ * job credential there. The SDK server does not — its auth middleware pins
252
+ * `requesterId` to `anonymous`/`dev-anonymous`, so every SDK job is gated on
253
+ * the internal-review `X-Job-Token` and a Bearer header proves nothing. Counting it
254
+ * anyway would send a stale client that happens to send one back to the
255
+ * opaque 404 this exists to eliminate.
256
+ *
257
+ * A request carrying no accepted credential can be refused before the job is
258
+ * ever looked up, which is what makes {@link JobCredentialGate.body} safe to
259
+ * be specific about — the 404-not-403 choice on a *failed* ownership check is
260
+ * deliberate (internal-review: a wrong credential must never confirm a job id exists),
261
+ * and that property is untouched here because this body is returned before any
262
+ * store lookup, identical whether or not the job exists.
263
+ *
264
+ * Shared by `src/sdk/server/app.ts` and the isolate routes so the two runtimes
265
+ * answer identically by construction rather than by comment.
266
+ */
267
+ declare function jobCredentialGate(opts: {
268
+ acceptsBearer: boolean;
269
+ }): JobCredentialGate;
270
+
271
+ /** Options for `PostgresTempoChargeStore`. */
272
+ interface PostgresTempoChargeStoreOpts {
273
+ /** Table name. Defaults to `"mpp_tempo_charge_replays"`. Must match `/^[a-zA-Z_][a-zA-Z0-9_]*$/`. */
274
+ tableName?: string;
275
+ /**
276
+ * How long a row survives its last write, in milliseconds. Defaults to one
277
+ * hour — see the class doc for why that is both generous and safe.
278
+ */
279
+ retentionMs?: number;
280
+ /**
281
+ * Probability (per write) of firing a fire-and-forget GC sweep that deletes
282
+ * expired rows. Defaults to 0.01 — every ~100 writes runs one DELETE. Set to
283
+ * 0 to disable GC entirely (rely on an external sweeper).
284
+ */
285
+ gcSampleRate?: number;
286
+ /** Clock source (ms). Defaults to `Date.now`. Test seam for deterministic TTL. */
287
+ now?: () => number;
288
+ }
289
+ /**
290
+ * Postgres implementation of the atomic store mppx's `tempo.charge` uses for
291
+ * replay protection (internal-review).
292
+ *
293
+ * mppx refuses a charge credential whose transaction hash it has already taken
294
+ * (`markHashUsed`), and refuses a zero-dollar proof credential whose challenge
295
+ * id it has already taken — but only against the store it is handed. Omitting
296
+ * one leaves it on `Store.memory()`: per-process, lost on restart, invisible to
297
+ * sibling machines. A replayed credential then reaches a broadcast the chain
298
+ * rejects instead of the cheap `Transaction hash has already been used`.
299
+ *
300
+ * {@link PostgresTempoSessionStore} cannot serve this keyspace — its `update`
301
+ * asserts a monotonic *channel-state object*, and a replay marker is the number
302
+ * `Date.now()`. Values here are deliberately opaque JSON: mppx writes a number
303
+ * for a replay marker and a `SponsorBudget.State` object for the fee-sponsor
304
+ * budget, which shares this store unprefixed so aggregate in-flight fee
305
+ * exposure is sponsor-wide rather than per-process.
306
+ *
307
+ * **Retention is ours — mppx has no TTL at any layer of `Store`.** Every row
308
+ * carries an `expires_at` refreshed on each write, swept by a sampled in-line
309
+ * DELETE. The window is uniform rather than per-keyspace because it is safe for
310
+ * both kinds of row: a replay marker guards a credential whose transaction is
311
+ * settleable for about twenty-five seconds and whose challenge expires in
312
+ * minutes, and a sponsor-budget reservation is bounded by that same expiring
313
+ * nonce (plus a thirty-second lease while it is `prepared`), so an hour-idle
314
+ * budget row holds only reservations `SponsorBudget.reconcile` would release on
315
+ * sight. Sweeping such a row is equivalent to reconciling it, and the next
316
+ * reservation recreates it. Keeping the rule uniform is what lets this store
317
+ * stay ignorant of mppx's key naming across version bumps.
318
+ *
319
+ * `expires_at` is a GC marker only: reads do not filter on it, so protection
320
+ * lapses when a row is swept and never before.
321
+ */
322
+ declare class PostgresTempoChargeStore implements Store.AtomicStore {
323
+ private readonly pool;
324
+ private readonly tableName;
325
+ private readonly retentionMs;
326
+ private readonly gcSampleRate;
327
+ private readonly now;
328
+ constructor(pool: Pool, opts?: PostgresTempoChargeStoreOpts);
329
+ /** Run the CREATE TABLE migration. Idempotent — safe to call repeatedly. */
330
+ init(): Promise<void>;
331
+ /** Read one stored value, or `null` when absent — mppx's miss sentinel. */
332
+ get(key: string): Promise<unknown>;
333
+ /** Replace one stored value. */
334
+ put(key: string, value: unknown): Promise<void>;
335
+ /** Delete one stored value — mppx's compensating release on a failed broadcast. */
336
+ delete(key: string): Promise<void>;
337
+ /**
338
+ * Atomic read-modify-write, linearized across every machine sharing the pool.
339
+ *
340
+ * The advisory lock is taken before the row lock because a key's *first*
341
+ * write is the one that matters here: `FOR UPDATE` locks nothing when no row
342
+ * exists, so two machines marking one hash for the first time would both read
343
+ * `null` and both believe they won.
344
+ *
345
+ * Replay keys are unique per credential, so they never contend. The contended
346
+ * key is the fee-sponsor budget — one per `(chain, sponsor)`, read-modified
347
+ * several times per sponsored charge — and serializing it across machines is
348
+ * the point of sharing the store at all. The critical section is a SELECT and
349
+ * an upsert, so a queue of waiters clears in tens of milliseconds; a pooled
350
+ * connection is held for exactly that long and never across a chain call.
351
+ */
352
+ update<result>(key: string, fn: (current: unknown) => Store.Change<unknown, result>): Promise<result>;
353
+ /** The boot DDL itself — always runs under {@link withSdkInitLock} (internal-review). */
354
+ private createTables;
355
+ private maybeSweep;
356
+ }
357
+
358
+ /**
359
+ * `topics[0]` of a `CloseRequested` log.
360
+ *
361
+ * Hard-coded rather than derived, because this module is imported by every
362
+ * DVM server while `viem` is an *optional* peer dependency — computing the
363
+ * selector at import time would make an EVM library mandatory for a DVM that
364
+ * takes no on-chain payments at all. `tempo-close-event.test.ts` pins the
365
+ * constant against viem's own `toEventSelector`, so it cannot drift.
366
+ */
367
+ declare const TEMPO_CLOSE_REQUESTED_TOPIC = "0xf5a36fc00a96cbb9cf1f8f59299165e1d8ffffe94396d82904b4da524d16bbce";
368
+ /**
369
+ * Maximum wall-clock budget for replacing stale Postgres sockets during one
370
+ * close delivery. The platform wake request allows 30 seconds; retaining a
371
+ * fifteen-second margin leaves receipt verification and the settlement submission
372
+ * room to finish instead of letting database recovery consume the whole wake.
373
+ */
374
+ declare const TEMPO_CLOSE_DB_RECOVERY_BUDGET_MS = 15000;
375
+
376
+ /** Humanised `{ message, hint }` derived from a ZodError for the `invalid_input`/`invalid_quote_data` envelope. */
377
+ interface HumanizedZodError {
378
+ message: string;
379
+ hint: string;
380
+ }
381
+ /**
382
+ * Render a `ZodError` into the structured `{ message, hint }` fields used by
383
+ * `/v1/job` and `/v1/quote` error envelopes.
384
+ *
385
+ * `message` is a single human-readable line (path: reason; …) that an agent
386
+ * can relay to its caller, capped at {@link MAX_REPORTED_CLAUSES} clauses with
387
+ * the remainder counted rather than printed. `hint` is the most actionable fix
388
+ * derived from the issues — oversized string → chunking guidance, empty
389
+ * required string → "provide non-empty text", everything else → a pointer at
390
+ * `/v1/info`. The hint is picked over **every** issue, not just the clauses
391
+ * that fit: a chunking hint is the one output that tells a caller what to
392
+ * actually do, and losing it because the oversized field sorted fourth is the
393
+ * same class of unhelpful answer this whole path exists to avoid.
394
+ *
395
+ * The `ZodError.message` field is itself a JSON-stringified array of issues
396
+ * (per Zod's default Error contract). Using it raw — as the SDK previously
397
+ * did — leaks the unstructured array into the agent-facing response, which
398
+ * is what internal-review fixes.
399
+ */
400
+ declare function humanizeZodError(err: z.ZodError, opts: {
401
+ schemaUrl: string;
402
+ }): HumanizedZodError;
403
+
404
+ export { AccumulatorPool, DEFAULT_LOCK_PUBKEY_GRACE_SECONDS, type LockPubkeyPool, type LockPubkeyState, type LockPubkeyStateLoader, LockPubkey as LockPubkeyStoreLockPubkey, PostgresTempoChargeStore, TEMPO_CLOSE_DB_RECOVERY_BUDGET_MS, TEMPO_CLOSE_REQUESTED_TOPIC, activePubkeySet, createAdminCashuNonceStore, createInstrumentedFetch, humanizeZodError, initLockPubkeyTable, installAdminCashuRoutes, jobCredentialGate, loadLockPubkeyState, pruneRetired, rateUnavailablePaymentError, rotateLockPubkey, seedLockPubkeyState, settleWithFacilitator, verifyWithFacilitator, verifyX402Payment };
@@ -0,0 +1,202 @@
1
+ import {
2
+ PostgresTempoSessionStore
3
+ } from "../chunk-UP2F5RRT.js";
4
+ import {
5
+ verifyX402Payment
6
+ } from "../chunk-BIFLRKMO.js";
7
+ import {
8
+ RevenueReporter
9
+ } from "../chunk-NFRM5QYP.js";
10
+ import {
11
+ PayoutReporter
12
+ } from "../chunk-6BQM7TOW.js";
13
+ import {
14
+ PostgresTempoChargeStore
15
+ } from "../chunk-JZWELPFH.js";
16
+ import "../chunk-YG7G4DPZ.js";
17
+ import {
18
+ DEFAULT_LOCK_PUBKEY_GRACE_SECONDS,
19
+ MintHealthTracker,
20
+ PAYMENT_PROOF_KEYS,
21
+ TEMPO_CLOSE_DB_RECOVERY_BUDGET_MS,
22
+ TEMPO_CLOSE_REQUESTED_TOPIC,
23
+ TempoSessionChannelMismatchError,
24
+ X402FacilitatorHealth,
25
+ X402_BATCH_SETTLEMENT_MAINNET_NETWORK,
26
+ activePubkeySet,
27
+ applyPaymentInfoToJob,
28
+ assertRevenueReporterReady,
29
+ buildPaymentErrorResponse,
30
+ clearAccumulatorForDvm,
31
+ createAdminCashuNonceStore,
32
+ createDVMServer,
33
+ creditDepositPayload,
34
+ derivedFundCreditId,
35
+ devModeSkipsPaymentVerification,
36
+ fundedMicroFor,
37
+ hasPaymentProof,
38
+ hashLockKey,
39
+ implicitCreditId,
40
+ initLockPubkeyTable,
41
+ initWalletAccumulatorTable,
42
+ insertAccumulatorRows,
43
+ installAdminCashuRoutes,
44
+ isDerivedCreditId,
45
+ issueUpfrontChallenges,
46
+ jobCredentialGate,
47
+ loadLockPubkeyState,
48
+ msatsToFiatMicro,
49
+ paymentErrorBody,
50
+ pinAskFiat,
51
+ priceFiatMicro,
52
+ processIncomingPayment,
53
+ pruneRetired,
54
+ rateUnavailablePaymentError,
55
+ repairX402ExactSettlementEffect,
56
+ resolveFxSnapshot,
57
+ resolvePriceFiat,
58
+ revenueReporterBannerState,
59
+ rotateLockPubkey,
60
+ seedLockPubkeyState,
61
+ toCreditTerms,
62
+ unknownRouteNotFound,
63
+ verifyIncomingPayment,
64
+ verifyTempoSessionManagementCredential,
65
+ verifyUpfrontPayment,
66
+ x402RequiredUsdcMicro,
67
+ x402SettledShare
68
+ } from "../chunk-3ZHMQCYP.js";
69
+ import "../chunk-DMNLFNTW.js";
70
+ import {
71
+ settleWithFacilitator,
72
+ verifyWithFacilitator
73
+ } from "../chunk-BQ2NMWKE.js";
74
+ import "../chunk-DBCLBYHP.js";
75
+ import {
76
+ SIGNED_ENVELOPE_FIELDS,
77
+ SIGNED_ENVELOPE_TYPES,
78
+ createDefaultReplayStore,
79
+ humanizeZodError
80
+ } from "../chunk-H2MEFVH6.js";
81
+ import {
82
+ JobCancelledError,
83
+ abortJob,
84
+ createInstrumentedFetch,
85
+ fromJobRecord,
86
+ isStaleJobReapable,
87
+ isTerminal,
88
+ isYieldMessage,
89
+ providerMessage,
90
+ toJobRecord
91
+ } from "../chunk-4B56DEEV.js";
92
+ import {
93
+ toLockPubkey
94
+ } from "../chunk-2K7E3N2D.js";
95
+ import "../chunk-Z4BNLUZF.js";
96
+ import "../chunk-5URG56JJ.js";
97
+ import "../chunk-MKI6OVW4.js";
98
+ import "../chunk-KXZUCCEY.js";
99
+ import "../chunk-YDIYXGYL.js";
100
+ import "../chunk-66HGCPBU.js";
101
+ import "../chunk-FUJ36YDV.js";
102
+ import "../chunk-27V2ILSR.js";
103
+ import "../chunk-AT6V3SY7.js";
104
+ import {
105
+ NON_CHANNEL_BITCOIN_RAILS,
106
+ depleteLots,
107
+ fifoOrder,
108
+ inKindDrawMsats,
109
+ isInKindDepletion,
110
+ isNonChannelBitcoinRail,
111
+ lotOwedSats,
112
+ netOwedSats
113
+ } from "../chunk-MLRCSJYX.js";
114
+ import "../chunk-S3XAHZQY.js";
115
+ import "../chunk-C3MTFLC6.js";
116
+ import {
117
+ _testing,
118
+ wrapMppx
119
+ } from "../chunk-5GFED3GJ.js";
120
+ export {
121
+ DEFAULT_LOCK_PUBKEY_GRACE_SECONDS,
122
+ JobCancelledError,
123
+ MintHealthTracker,
124
+ NON_CHANNEL_BITCOIN_RAILS,
125
+ PAYMENT_PROOF_KEYS,
126
+ PayoutReporter,
127
+ PostgresTempoChargeStore,
128
+ PostgresTempoSessionStore,
129
+ RevenueReporter,
130
+ SIGNED_ENVELOPE_FIELDS,
131
+ SIGNED_ENVELOPE_TYPES,
132
+ TEMPO_CLOSE_DB_RECOVERY_BUDGET_MS,
133
+ TEMPO_CLOSE_REQUESTED_TOPIC,
134
+ TempoSessionChannelMismatchError,
135
+ X402FacilitatorHealth,
136
+ X402_BATCH_SETTLEMENT_MAINNET_NETWORK,
137
+ _testing,
138
+ abortJob,
139
+ activePubkeySet,
140
+ applyPaymentInfoToJob,
141
+ assertRevenueReporterReady,
142
+ buildPaymentErrorResponse,
143
+ clearAccumulatorForDvm,
144
+ createAdminCashuNonceStore,
145
+ createDVMServer,
146
+ createDefaultReplayStore,
147
+ createInstrumentedFetch,
148
+ creditDepositPayload,
149
+ depleteLots,
150
+ derivedFundCreditId,
151
+ devModeSkipsPaymentVerification,
152
+ fifoOrder,
153
+ fromJobRecord,
154
+ fundedMicroFor,
155
+ hasPaymentProof,
156
+ hashLockKey,
157
+ humanizeZodError,
158
+ implicitCreditId,
159
+ inKindDrawMsats,
160
+ initLockPubkeyTable,
161
+ initWalletAccumulatorTable,
162
+ insertAccumulatorRows,
163
+ installAdminCashuRoutes,
164
+ isDerivedCreditId,
165
+ isInKindDepletion,
166
+ isNonChannelBitcoinRail,
167
+ isStaleJobReapable,
168
+ isTerminal,
169
+ isYieldMessage,
170
+ issueUpfrontChallenges,
171
+ jobCredentialGate,
172
+ loadLockPubkeyState,
173
+ toLockPubkey as lockPubkeyStoreToLockPubkey,
174
+ lotOwedSats,
175
+ msatsToFiatMicro,
176
+ netOwedSats,
177
+ paymentErrorBody,
178
+ pinAskFiat,
179
+ priceFiatMicro,
180
+ processIncomingPayment,
181
+ providerMessage,
182
+ pruneRetired,
183
+ rateUnavailablePaymentError,
184
+ repairX402ExactSettlementEffect,
185
+ resolveFxSnapshot,
186
+ resolvePriceFiat,
187
+ revenueReporterBannerState,
188
+ rotateLockPubkey,
189
+ seedLockPubkeyState,
190
+ settleWithFacilitator,
191
+ toCreditTerms,
192
+ toJobRecord,
193
+ unknownRouteNotFound,
194
+ verifyIncomingPayment,
195
+ verifyTempoSessionManagementCredential,
196
+ verifyUpfrontPayment,
197
+ verifyWithFacilitator,
198
+ verifyX402Payment,
199
+ wrapMppx,
200
+ x402RequiredUsdcMicro,
201
+ x402SettledShare
202
+ };