@dvmkit/sdk 0.1.0-rc.2 → 0.1.0-rc.4

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 (42) hide show
  1. package/README.md +10 -2
  2. package/dist/{revenue-reporter-GB4WKLDC.js → chunk-2ABMGUDS.js} +1 -0
  3. package/dist/chunk-2K6UXDAN.js +1557 -0
  4. package/dist/chunk-4UVRXDNY.js +21745 -0
  5. package/dist/chunk-66HGCPBU.js +25 -0
  6. package/dist/{chunk-DCNT4PJS.js → chunk-AAJNGQMC.js} +6 -258
  7. package/dist/{chunk-KQAJVVZT.js → chunk-AZBXSXQT.js} +27 -287
  8. package/dist/{chunk-H25M54MI.js → chunk-C3MTFLC6.js} +16 -0
  9. package/dist/chunk-EDU6COY2.js +1057 -0
  10. package/dist/{chunk-OJ5WFIB2.js → chunk-EXHBXA4U.js} +1 -1
  11. package/dist/chunk-F2L6KIMD.js +380 -0
  12. package/dist/{chunk-KXWROQGK.js → chunk-FUJ36YDV.js} +1 -24
  13. package/dist/chunk-GJD7PVWY.js +1090 -0
  14. package/dist/{tempo-charge-store-6GJEMNUU.js → chunk-JZWELPFH.js} +1 -0
  15. package/dist/{chunk-365P52XQ.js → chunk-LWUR4CGG.js} +2 -1
  16. package/dist/{tempo-session-store-FTEEGZXA.js → chunk-RU7SXHLO.js} +2 -1
  17. package/dist/{chunk-7IH5SG2A.js → chunk-TKA6ZP4M.js} +62 -41
  18. package/dist/chunk-TVI4V7GF.js +283 -0
  19. package/dist/{payout-reporter-4TNWRS5F.js → chunk-X3IKFWJA.js} +3 -2
  20. package/dist/chunk-XYTSDAPH.js +232 -0
  21. package/dist/{credit-ledger-RO4FGSHG.js → credit-ledger-ED6JXKVD.js} +2 -2
  22. package/dist/credit-menu-ClA1JyYW.d.ts +5076 -0
  23. package/dist/{ssrf-DZi-xJyn.d.ts → fx-ptKVFOwq.d.ts} +37 -119
  24. package/dist/index.d.ts +8 -66
  25. package/dist/index.js +11 -219
  26. package/dist/internal/index.d.ts +5896 -0
  27. package/dist/internal/index.js +6407 -0
  28. package/dist/{job-store-6gR4pZRP.d.ts → job-store-DxFqDPYq.d.ts} +1498 -12
  29. package/dist/{memory-credit-ledger-I2G64DDK.js → memory-credit-ledger-XJ5VQEVP.js} +3 -3
  30. package/dist/payout-reporter-3UB5WRCV.js +13 -0
  31. package/dist/revenue-reporter-JIKUPXOK.js +7 -0
  32. package/dist/server/index.d.ts +14 -3590
  33. package/dist/server/index.js +155 -20850
  34. package/dist/ssrf-DbFkpDv0.d.ts +118 -0
  35. package/dist/tempo-charge-store-RIFTALZK.js +8 -0
  36. package/dist/tempo-session-store-DALMRIWN.js +11 -0
  37. package/dist/testing/index.d.ts +3 -2
  38. package/dist/testing/index.js +3 -2
  39. package/dist/usd-Cha_j80I.d.ts +97 -0
  40. package/dist/x402-XXFQQAAD.js +81 -0
  41. package/package.json +6 -2
  42. package/dist/x402-35VLYFKZ.js +0 -1272
@@ -1,10 +1,11 @@
1
1
  import { ProofLike } from '@cashu/cashu-ts';
2
- import { Challenge, Credential, Method, Receipt } from 'mppx';
3
- import { MiddlewareHandler, Context, Hono } from 'hono';
4
- import { FacilitatorClient } from '@x402/core/server';
2
+ import { Challenge, Credential, Store, Method, Receipt } from 'mppx';
3
+ import { FacilitatorClient, FacilitatorConfig } from '@x402/core/server';
5
4
  import { AuthorizerSigner, ChannelStorage, AutoSettlementConfig, Channel, ChannelUpdateResult } from '@x402/evm/batch-settlement/server';
5
+ import { MiddlewareHandler, Context, Hono } from 'hono';
6
+ import { Account, Client, Hex } from 'viem';
6
7
  import { Pool, PoolClient } from 'pg';
7
- import { PaymentPayload, PaymentRequirements, SettleResponse } from '@x402/core/types';
8
+ import { PaymentPayload as PaymentPayload$1, PaymentRequirements as PaymentRequirements$1, SettleResponse as SettleResponse$1 } from '@x402/core/types';
8
9
  import { z } from 'zod';
9
10
 
10
11
  /**
@@ -78,6 +79,8 @@ interface X402SelfRelayConfig {
78
79
  /** Advanced RPC-health hook; platform-hosted DVMs receive an automatic reporter. */
79
80
  onRpcHealth?: (observation: X402SelfRelayRpcHealthObservation) => void | Promise<void>;
80
81
  }
82
+ /** Caller-visible reasons an ambiguous x402 settlement could not be reconciled. */
83
+ type X402SettlementReconciliationReason = "settlement_not_on_chain" | "chain_unreachable" | "settlement_unbookmarked" | "facilitator_channel_state_unavailable";
81
84
  /** Builder-facing configuration for reusable x402 batch-settlement channels. */
82
85
  interface X402BatchSettlementConfig {
83
86
  /** Receiver-authorizer signer used when the facilitator advertises none. */
@@ -142,6 +145,13 @@ interface X402ExactVersionSupport {
142
145
  v1: boolean;
143
146
  v2: boolean;
144
147
  }
148
+ /** Client-side x402 wallet — EVM key pair for signing payments. */
149
+ interface X402Wallet {
150
+ privateKey: string;
151
+ address: string;
152
+ /** CAIP-2 chain id this wallet pays on. */
153
+ network: string;
154
+ }
145
155
  /** Server-side receipt from verifying an x402 payment. */
146
156
  interface X402Receipt {
147
157
  verified: boolean;
@@ -181,6 +191,50 @@ interface X402Receipt {
181
191
 
182
192
  /** Current x402 protocol version preferred by dvmkit clients and servers. */
183
193
  declare const X402_VERSION = 2;
194
+ /** Legacy x402 protocol version retained during the dual-serve window. */
195
+ declare const X402_V1_VERSION = 1;
196
+ /** x402 protocol versions supported by dvmkit's hand-rolled exact codec. */
197
+ type X402Version = typeof X402_V1_VERSION | typeof X402_VERSION;
198
+ /**
199
+ * Chain a caller's x402 wallet reads when it was connected without an explicit
200
+ * `--network`. Single source of truth for the default: the wallet loader, the
201
+ * connect output and the asset resolver all read it from here (internal-review).
202
+ */
203
+ declare const X402_DEFAULT_NETWORK = "eip155:8453";
204
+ /**
205
+ * Scheme name of the per-call rail — one signed authorization settling one
206
+ * resource. Shared with the credit funding menu's `x402.schemes` block, which
207
+ * has to name the same string the requirement carries (internal-review).
208
+ */
209
+ declare const X402_EXACT_SCHEME = "exact";
210
+ /**
211
+ * Scheme name of the reusable v2 channel rail. Single source of truth: the
212
+ * facilitator probe, the requirement the server builds, the header dispatch,
213
+ * the caller's requirement selection, and the credit menu's `x402.schemes`
214
+ * block all read it from here — the menu advertises exactly what the challenge
215
+ * will carry, so a rename cannot leave one of them advertising a flavour the
216
+ * others no longer speak (internal-review).
217
+ */
218
+ declare const X402_BATCH_SETTLEMENT_SCHEME = "batch-settlement";
219
+
220
+ /**
221
+ * x402-spec PaymentRequirements — the shape advertised on a 402 response's
222
+ * `accepts` array, mirrored from the facilitator's `PaymentRequirementsSchema`
223
+ * (see `x402/types/index.d.ts` in the published `x402` package).
224
+ */
225
+ interface PaymentRequirementsV1 {
226
+ scheme: string;
227
+ network: string;
228
+ maxAmountRequired: string;
229
+ resource: string;
230
+ description: string;
231
+ mimeType: string;
232
+ payTo: string;
233
+ asset: string;
234
+ maxTimeoutSeconds: number;
235
+ outputSchema?: Record<string, unknown>;
236
+ extra?: Record<string, unknown>;
237
+ }
184
238
  /** x402 v2 resource metadata echoed by a paying client. */
185
239
  interface ResourceInfo {
186
240
  url: string;
@@ -204,6 +258,73 @@ interface PaymentRequirementsV2 {
204
258
  */
205
259
  extra?: Record<string, unknown> | null;
206
260
  }
261
+ /** Legacy alias retained for server internals that carry the v1 body requirements. */
262
+ type PaymentRequirements = PaymentRequirementsV1;
263
+ /**
264
+ * EIP-3009 `TransferWithAuthorization` parameters that the client signs and
265
+ * the facilitator submits on settlement.
266
+ */
267
+ interface ExactEvmPayloadAuthorization {
268
+ from: string;
269
+ to: string;
270
+ value: string;
271
+ validAfter: string;
272
+ validBefore: string;
273
+ nonce: string;
274
+ }
275
+ /** Signed EIP-3009 transfer authorization (the `payload` of a PaymentPayload). */
276
+ interface ExactEvmPayload {
277
+ signature: string;
278
+ authorization: ExactEvmPayloadAuthorization;
279
+ }
280
+ /**
281
+ * x402-spec PaymentPayload — the JSON shape carried inside the `X-PAYMENT`
282
+ * header (base64-encoded). `payload` is scheme-specific; alpha only supports
283
+ * `scheme: "exact"` against an EVM network.
284
+ */
285
+ interface PaymentPayloadV1 {
286
+ x402Version: typeof X402_V1_VERSION;
287
+ scheme: "exact";
288
+ network: string;
289
+ payload: ExactEvmPayload;
290
+ }
291
+ /** x402 v2 payment payload carried in `PAYMENT-SIGNATURE`. */
292
+ interface PaymentPayloadV2 {
293
+ x402Version: typeof X402_VERSION;
294
+ resource?: ResourceInfo;
295
+ accepted: PaymentRequirementsV2;
296
+ payload: ExactEvmPayload;
297
+ extensions?: Record<string, unknown>;
298
+ }
299
+ /** Exact EVM payment payload accepted by the dual-version codec. */
300
+ type PaymentPayload = PaymentPayloadV1 | PaymentPayloadV2;
301
+ /** Facilitator `/verify` response. */
302
+ interface VerifyResponse {
303
+ isValid: boolean;
304
+ invalidReason?: string;
305
+ payer?: string;
306
+ }
307
+ /** Facilitator `/settle` response — what we base64 into `X-PAYMENT-RESPONSE`. */
308
+ interface SettleResponse {
309
+ success: boolean;
310
+ errorReason?: string;
311
+ payer?: string;
312
+ transaction?: string;
313
+ network?: string;
314
+ amount?: string;
315
+ extensions?: Record<string, unknown>;
316
+ }
317
+ /**
318
+ * Body envelope used to carry x402 PaymentRequirements on a 402 response.
319
+ * The x402 spec puts requirements in the JSON body under `accepts`; the
320
+ * `WWW-Authenticate: Payment` header carries the MPP method advertisements
321
+ * separately, so the two protocols don't fight for the same header slot.
322
+ */
323
+ interface X402ResponseBody {
324
+ x402Version: typeof X402_V1_VERSION;
325
+ accepts: PaymentRequirementsV1[];
326
+ error?: string;
327
+ }
207
328
  /** x402 v2 payment-required declaration encoded into `PAYMENT-REQUIRED`. */
208
329
  interface PaymentRequiredV2 {
209
330
  x402Version: typeof X402_VERSION;
@@ -212,6 +333,101 @@ interface PaymentRequiredV2 {
212
333
  accepts: PaymentRequirementsV2[];
213
334
  extensions?: Record<string, unknown>;
214
335
  }
336
+ /** Either challenge shape understood by dvmkit callers. */
337
+ type PaymentRequired = X402ResponseBody | PaymentRequiredV2;
338
+ /** Inputs for `buildPaymentRequirements`. */
339
+ interface BuildPaymentRequirementsOpts {
340
+ x402Config: X402Config;
341
+ requiredUsdcMicro: bigint;
342
+ resource: string;
343
+ description?: string;
344
+ mimeType?: string;
345
+ version?: X402Version;
346
+ }
347
+ /**
348
+ * Build a single x402 `PaymentRequirements` entry from the DVM's `X402Config`,
349
+ * the resolved per-call USDC amount, and the live request's resource URL.
350
+ * The resource string is bound into the EIP-3009 `extra` field on signing in
351
+ * the reference clients, so it must match exactly between the 402 response
352
+ * and the retry payload — pass the request URL the client will retry against.
353
+ */
354
+ declare function buildPaymentRequirements(opts: BuildPaymentRequirementsOpts & {
355
+ version: typeof X402_V1_VERSION;
356
+ }): PaymentRequirementsV1;
357
+ declare function buildPaymentRequirements(opts: (BuildPaymentRequirementsOpts & {
358
+ version: typeof X402_VERSION;
359
+ }) | (BuildPaymentRequirementsOpts & {
360
+ version?: undefined;
361
+ })): PaymentRequirementsV2;
362
+ /** Build the canonical x402 v2 declaration for a `PAYMENT-REQUIRED` header. */
363
+ declare function buildPaymentRequiredV2(opts: Omit<BuildPaymentRequirementsOpts, "version"> & {
364
+ error?: string;
365
+ }): PaymentRequiredV2;
366
+ /** Convert the server's legacy body requirements into the parallel v2 declaration. */
367
+ declare function paymentRequiredV2FromV1(requirements: PaymentRequirementsV1[], error?: string): PaymentRequiredV2;
368
+ /**
369
+ * Translate a CAIP-2 chain id (`eip155:8453`) to the x402-spec network slug
370
+ * (`base`). Operators configure DVMs in CAIP-2 because it's the lingua-franca
371
+ * across our other rails; the x402 facilitator API only accepts named slugs.
372
+ * Unknown CAIP-2 ids fall through to the original string so non-EVM rails
373
+ * (Solana mainnet, etc.) can also be plumbed once supported.
374
+ */
375
+ declare function caip2ToX402Network(network: string): string;
376
+ /** Translate a legacy x402 network slug back to its CAIP-2 chain id. */
377
+ declare function x402NetworkToCaip2(network: string): string;
378
+ /** EIP-712 chain id derived from a CAIP-2 chain id. */
379
+ declare function chainIdFromCaip2(network: string): number;
380
+ /** USDC contract address for a network slug (post-translation). */
381
+ declare function usdcContractFor(networkSlug: string): `0x${string}` | undefined;
382
+ /**
383
+ * USDC contract address for a CAIP-2 chain id (e.g. `eip155:8453`). Resolves
384
+ * via {@link caip2ToX402Network} so the one network table is the source of
385
+ * truth — keeps callers that hold the CAIP-2 form (CLI wallet) in lockstep
386
+ * with the SDK 402-builder which already speaks x402 slugs.
387
+ */
388
+ declare function usdcContractByCaip2(caip2: string): `0x${string}` | undefined;
389
+ /** USDC EIP-712 domain `name` for a network slug. */
390
+ declare function usdcDomainNameFor(networkSlug: string): string | undefined;
391
+ /** USDC EIP-712 domain `version` for a network slug. */
392
+ declare function usdcDomainVersionFor(networkSlug: string): string | undefined;
393
+ /**
394
+ * Decode a base64-encoded `X-PAYMENT` header into a structured `PaymentPayload`.
395
+ * Throws on malformed input rather than silently returning a partial — the
396
+ * server treats decode failures as `payment_invalid` per the spec.
397
+ */
398
+ declare function decodePayment(header: string): PaymentPayload;
399
+ /**
400
+ * Encode a `PaymentPayload` for transport in the `X-PAYMENT` header. JSON
401
+ * serialization uses string-typed integer fields (the spec encodes uint256
402
+ * values as decimal strings, so `bigint` must already be stringified by the
403
+ * caller).
404
+ */
405
+ declare function encodePayment(payload: PaymentPayload): string;
406
+ /** Encode a v2 `PaymentRequired` declaration for the HTTP response header. */
407
+ declare function encodePaymentRequiredHeader(required: PaymentRequiredV2): string;
408
+ /** Decode and structurally validate a v2 `PAYMENT-REQUIRED` header. */
409
+ declare function decodePaymentRequiredHeader(header: string): PaymentRequiredV2;
410
+ /** Read the exact EIP-3009 authorization carried by either protocol version. */
411
+ declare function exactEvmAuthorization(payload: PaymentPayload): ExactEvmPayloadAuthorization;
412
+ /**
413
+ * Encode a `SettleResponse` for the `X-PAYMENT-RESPONSE` header that the
414
+ * server emits on a 2xx after a successful settlement (internal-review, per the
415
+ * x402 spec).
416
+ */
417
+ declare function encodeSettleResponseHeader(response: SettleResponse): string;
418
+ /**
419
+ * POST a verify request to the facilitator. Returns the parsed `VerifyResponse`
420
+ * or a structured-failure shape when the facilitator rejects the call (network
421
+ * error, non-2xx, or `isValid: false`).
422
+ */
423
+ declare function verifyWithFacilitator(payload: PaymentPayload, requirements: PaymentRequirementsV1 | PaymentRequirementsV2, config?: Pick<X402Config, "facilitator" | "facilitatorAuth">, createAuthHeaders?: FacilitatorConfig["createAuthHeaders"] | undefined): Promise<VerifyResponse>;
424
+ /**
425
+ * POST a settle request to the facilitator. The facilitator broadcasts the
426
+ * EIP-3009 `transferWithAuthorization` and returns the on-chain tx hash on
427
+ * success; the dvmkit DVM mirrors that into `X-PAYMENT-RESPONSE` for the
428
+ * client and into `revenue_events.tx_hash` for the platform ledger.
429
+ */
430
+ declare function settleWithFacilitator(payload: PaymentPayload, requirements: PaymentRequirementsV1 | PaymentRequirementsV2, config?: Pick<X402Config, "facilitator" | "facilitatorAuth">, createAuthHeaders?: FacilitatorConfig["createAuthHeaders"] | undefined): Promise<SettleResponse>;
215
431
 
216
432
  /** Identifies which side of the conversation sent a message. */
217
433
  type MessageFrom = "requester" | "provider";
@@ -419,6 +635,21 @@ type Message = (MessageBase & {
419
635
  type: "progress";
420
636
  content: ProgressContent;
421
637
  });
638
+ /** Type guard: message is a prompt from the provider. */
639
+ declare function isPromptMessage(msg: Message): msg is MessageBase & {
640
+ type: "prompt";
641
+ content: PromptContent;
642
+ };
643
+ /** Type guard: message contains an artifact. */
644
+ declare function isArtifactMessage(msg: Message): msg is MessageBase & {
645
+ type: "artifact";
646
+ content: ArtifactContent;
647
+ };
648
+ /** Type guard: message is a payment request. */
649
+ declare function isPaymentRequestMessage(msg: Message): msg is MessageBase & {
650
+ type: "payment-request";
651
+ content: PaymentRequestContent;
652
+ };
422
653
 
423
654
  /** Auth identifier advertised by DVMs using audience-bound caller proofs. */
424
655
  declare const SIGNED_REQUEST_AUTH_ID: "secp256k1-schnorr-v2";
@@ -514,6 +745,42 @@ declare const requireClientCompatibility: ClientCompatibilityGate;
514
745
  /** Render the normal structured HTTP 426 compatibility error. */
515
746
  declare function clientUpgradeRequired(c: Context, compatibility: ClientCompatibility, requirement: ClientCompatibilityRequirement): Response;
516
747
 
748
+ /**
749
+ * Canonical JSON serialisation used for secp256k1+BIP-340 Schnorr request
750
+ * signing in cast (internal-review).
751
+ *
752
+ * Single source of truth for both the cast DVM's verifier (internal-review) and the
753
+ * client signing helper (internal-review). The same function on both sides guarantees
754
+ * that what the client signs is byte-identical to what the server hashes.
755
+ *
756
+ * Algorithm: recursively sort object keys lexicographically (UTF-16 code-unit
757
+ * order — JavaScript's default), then JSON.stringify with no whitespace.
758
+ * Arrays preserve order. Numbers, strings, booleans, null pass through as
759
+ * `JSON.stringify` formats them. Values of `undefined` or functions are
760
+ * forbidden (we throw rather than silently drop, since both sides must agree).
761
+ */
762
+ /** Any JSON-serialisable value accepted by `canonicalize`. */
763
+ type JsonValue = string | number | boolean | null | JsonValue[] | {
764
+ [key: string]: JsonValue;
765
+ };
766
+ /**
767
+ * Serialise `value` to its canonical JSON form (sorted keys, no whitespace).
768
+ *
769
+ * `undefined` properties on objects are silently omitted (mirroring
770
+ * `JSON.stringify`), so callers don't need to explicitly delete optional fields
771
+ * that weren't set. Throws `TypeError` for unsupported scalar types (functions,
772
+ * symbols, non-finite numbers). The caller is responsible for stripping fields
773
+ * that shouldn't appear in the signed payload (e.g. `signature` itself).
774
+ */
775
+ declare function canonicalize(value: JsonValue): string;
776
+ /**
777
+ * Canonicalise `value` and return the UTF-8 bytes the signer should produce a
778
+ * signature over. Both the cast client signer (`signAddEpisode`) and the
779
+ * server verifier (`verifyCanonicalSignedRequest`) call this — sharing the function
780
+ * guarantees byte-identical input on both sides.
781
+ */
782
+ declare function canonicaliseForSigning(value: JsonValue): Uint8Array;
783
+
517
784
  /** Terminal outcome a receipt attests. Mirrors the SDK's terminal job statuses. */
518
785
  type ReceiptOutcome = "completed" | "failed" | "cancelled";
519
786
  /** What the caller paid for the job, as persisted on the job record. */
@@ -611,6 +878,8 @@ interface JobReceipt {
611
878
  */
612
879
  credit?: ReceiptCredit;
613
880
  }
881
+ /** A receipt before signing — every field but the signature itself. */
882
+ type UnsignedJobReceipt = Omit<JobReceipt, "signature">;
614
883
  /** Reclaim lifecycle event a {@link DrainReceipt} attests (internal-review, spec §5). */
615
884
  type DrainReceiptEvent = "requested" | "parked" | "picked_up" | "sent" | "released";
616
885
  /**
@@ -665,6 +934,8 @@ interface DrainReceipt {
665
934
  /** BIP-340 Schnorr signature over the canonical receipt minus `signature`. */
666
935
  signature: string;
667
936
  }
937
+ /** A drain receipt before signing — every field but the signature itself. */
938
+ type UnsignedDrainReceipt = Omit<DrainReceipt, "signature">;
668
939
  /**
669
940
  * A DVM-signed proof that one payment funded a prepaid credit (internal-review).
670
941
  * The balance and sequence are the values fixed when the funding committed;
@@ -698,6 +969,94 @@ interface FundingReceipt {
698
969
  /** BIP-340 Schnorr signature over the canonical receipt minus `signature`. */
699
970
  signature: string;
700
971
  }
972
+ /** A funding receipt before signing. */
973
+ type UnsignedFundingReceipt = Omit<FundingReceipt, "signature">;
974
+ /**
975
+ * Hash the delivered result so a receipt binds to *what* was returned, not
976
+ * just that something was.
977
+ *
978
+ * `sha256(canonicalize({ summary, artifact_hashes }))`, where each artifact
979
+ * hash is `sha256(canonicalize(artifactContent))` in emission order (`[]`
980
+ * when the job emitted none). Hashing the artifact *content object* rather
981
+ * than trusting `content.sha256` — which is optional and which `ctx.artifact`
982
+ * never fills in — keeps the hash recomputable by any consumer from exactly
983
+ * the messages it received.
984
+ *
985
+ * **Pass `summary` only for a `completed` job.** On `failed`/`cancelled` the
986
+ * SDK's durable terminal writes the terminal *reason* into the job's summary
987
+ * column, so a verifier recomputing a non-completed receipt must pass
988
+ * `undefined` here and read the reason off `receipt.reason` instead. The
989
+ * issuer does the same (`resultHashFor` in `sdk/server/receipt-issuer.ts`).
990
+ */
991
+ declare function computeResultHash(summary: string | undefined, artifactContents: JsonValue[]): string;
992
+ /**
993
+ * Sign an unsigned receipt with the DVM's receipt secret, returning the
994
+ * complete receipt. Signs `canonicaliseForSigning(receipt)` — the same
995
+ * sorted-key canonical JSON the caller-auth envelope and the builder
996
+ * attestation use, so {@link verifyReceipt} is symmetric with
997
+ * `verifyCanonicalSignedRequest`. There is no second canonicalisation.
998
+ */
999
+ declare function signReceipt(unsigned: UnsignedJobReceipt, secretHex: string): JobReceipt;
1000
+ /**
1001
+ * Verify a receipt's self-consistency: the BIP-340 signature over the
1002
+ * canonical payload (minus `signature`) under the receipt's own
1003
+ * `receipt_pubkey`. Returns `false` rather than throwing on malformed input.
1004
+ *
1005
+ * This is only the inner link. A consumer that wants provenance must also
1006
+ * check `receipt_pubkey` against `/v1/info#builder`'s attested
1007
+ * `receipt_pubkey` and verify that attestation under the builder pubkey
1008
+ * (`verifyAttestation` in `builder-identity.ts`).
1009
+ */
1010
+ declare function verifyReceipt(receipt: JobReceipt): boolean;
1011
+ /**
1012
+ * Structural guard on a receipt that arrived from outside this process — off a
1013
+ * `/v1/job` response, or back out of the hand-editable `~/.dvm/receipts.jsonl`.
1014
+ *
1015
+ * Checks only that the load-bearing fields are the right *kind* of thing; it
1016
+ * deliberately does not judge the receipt. A well-formed receipt whose
1017
+ * signature doesn't hold is `invalid` and the caller must see it said so. A
1018
+ * body missing one of these fields is a different animal: consumers dereference
1019
+ * them unconditionally (`receiptDisplay`'s `paid.msats`, the attestation link's
1020
+ * `receipt_pubkey`), so an unguarded one throws `TypeError` and surfaces as an
1021
+ * `internal` exit — and it could never have verified anyway, since the
1022
+ * signature covers the whole canonical body. Refusing it costs no proof.
1023
+ *
1024
+ * One guard for both directions on purpose: what can't come in over the wire
1025
+ * must not be able to come back out of the file.
1026
+ *
1027
+ * Release coupling: adding or requiring a field here changes both the SDK's
1028
+ * emitted wire shape and the caller CLI's accepted shape. Name the first-party
1029
+ * fleet redeploy as a prerequisite in the release note before publishing the
1030
+ * stricter caller; see `public compatibility guide`.
1031
+ */
1032
+ declare function isSignedJobReceipt(value: unknown): value is JobReceipt;
1033
+ /** Sign an unsigned drain receipt — same canonicalisation as {@link signReceipt}. */
1034
+ declare function signDrainReceipt(unsigned: UnsignedDrainReceipt, secretHex: string): DrainReceipt;
1035
+ /** Sign an unsigned funding receipt using the common receipt canonicalisation. */
1036
+ declare function signFundingReceipt(unsigned: UnsignedFundingReceipt, secretHex: string): FundingReceipt;
1037
+ /** Structural guard for a funding receipt received over the wire or from disk. */
1038
+ declare function isFundingReceipt(value: unknown): value is FundingReceipt;
1039
+ /** Verify a funding receipt's inner BIP-340 signature. */
1040
+ declare function verifyFundingReceipt(receipt: FundingReceipt): boolean;
1041
+ /**
1042
+ * Structural guard on a drain receipt from outside this process — off a
1043
+ * `/v1/credit` drain response, or back out of `~/.dvm/credits.json`.
1044
+ *
1045
+ * Same contract and same reasoning as {@link isSignedJobReceipt}: both homes
1046
+ * type these `unknown[]` because neither the wire nor a hand-editable file is
1047
+ * evidence of shape, and the chain walk dereferences `receipt_pubkey`
1048
+ * unconditionally. A body missing one of these fields could never have carried
1049
+ * a valid signature anyway, so refusing it costs no proof.
1050
+ * Required-field changes follow the fleet-before-caller release note linked
1051
+ * from {@link isSignedJobReceipt}.
1052
+ */
1053
+ declare function isDrainReceipt(value: unknown): value is DrainReceipt;
1054
+ /**
1055
+ * Verify a drain receipt's self-consistency, mirroring {@link verifyReceipt}
1056
+ * — the same provenance caveat applies: check `receipt_pubkey` against the
1057
+ * DVM's attested `receipt_pubkey` for the outer link.
1058
+ */
1059
+ declare function verifyDrainReceipt(receipt: DrainReceipt): boolean;
701
1060
 
702
1061
  /**
703
1062
  * Funding lots: the in-kind basis of a non-channel Bitcoin credit (internal-review).
@@ -734,6 +1093,8 @@ interface FundingReceipt {
734
1093
  declare const NON_CHANNEL_BITCOIN_RAILS: readonly ["cashu", "lightning"];
735
1094
  /** A rail whose unused credit is a sats deposit the provider owes back. */
736
1095
  type NonChannelBitcoinRail = (typeof NON_CHANNEL_BITCOIN_RAILS)[number];
1096
+ /** True when `rail` funds a credit with sats the provider holds and owes back. */
1097
+ declare function isNonChannelBitcoinRail(rail: string | null | undefined): rail is NonChannelBitcoinRail;
737
1098
  /**
738
1099
  * One funding event's deposit: the sats that arrived and the credit micro they
739
1100
  * bought, with however much of that micro is still unspent.
@@ -760,6 +1121,71 @@ interface FundingLot {
760
1121
  fundingRef: string | null;
761
1122
  createdAt: number;
762
1123
  }
1124
+ /** One lot's share of a depletion, and what that share is worth in kind. */
1125
+ interface LotDebit {
1126
+ lotId: string;
1127
+ /** Credit micro taken out of this lot. */
1128
+ micro: number;
1129
+ /** Sats that micro is worth at this lot's own funding rate, floored. */
1130
+ sats: number;
1131
+ }
1132
+ /** What a FIFO depletion took, and what it could not cover. */
1133
+ interface LotDepletion {
1134
+ debits: LotDebit[];
1135
+ /** In-kind value of everything taken — the reclaim obligation. */
1136
+ satsOwed: number;
1137
+ /** Micro the lots could not cover. Non-zero means the credit's lots are short. */
1138
+ uncoveredMicro: number;
1139
+ /** Of the micro taken, how much came out of a lot carrying a real sats basis. */
1140
+ backedMicro: number;
1141
+ }
1142
+ /**
1143
+ * Take `amountMicro` out of `lots`, oldest first, and price what was taken at
1144
+ * each lot's own rate.
1145
+ *
1146
+ * FIFO rather than pro rata across the pool, so a top-up taken at a different
1147
+ * rate is reclaimed at *that* rate once the earlier deposit is spent. A
1148
+ * fraction of a satoshi cannot be handed back, so the conversion floors and
1149
+ * the dust stays with the provider rather than being rounded into a payout the
1150
+ * deposit does not cover.
1151
+ *
1152
+ * A slice is priced as the **decrement in the lot's own obligation** —
1153
+ * `lotSats(before) - lotSats(after)` — rather than by flooring the slice on
1154
+ * its own. The two agree whenever a lot is taken whole, which is every
1155
+ * ordinary reclaim; they diverge once a lot is drawn down in pieces, and there
1156
+ * the independent floor loses up to a satoshi *per piece*, permanently. That
1157
+ * matters since internal-review, where each settling draw is priced through here: the
1158
+ * slices have to telescope, or a lot spent over many jobs pays out less than
1159
+ * it took in and the residue is exactly the unattributable one this was meant
1160
+ * to remove. It also makes {@link lotOwedSats} exact rather than conservative
1161
+ * — the remaining obligation is precisely what future depletions will pay.
1162
+ *
1163
+ * `lots` must already be in FIFO order ({@link fifoOrder}).
1164
+ */
1165
+ declare function depleteLots(lots: FundingLot[], amountMicro: number): LotDepletion;
1166
+ /**
1167
+ * What a settling draw's fiat debit was worth in kind, in millisatoshis
1168
+ * (internal-review) — `null` where the lots cannot price it.
1169
+ *
1170
+ * This is the single sats authority for a non-channel Bitcoin credit. The
1171
+ * settle already depletes the lots the draw consumed, so the figure costs no
1172
+ * extra read: it is `depletion.satsOwed` in the ledger's own msat unit, and
1173
+ * stamping it on `credit_draws.draw_msats` is what makes
1174
+ * `Σ settled draw sats + reclaim sats == Σ sats funded` close per credit.
1175
+ *
1176
+ * `null` follows {@link isInKindDepletion} exactly, so a settle and a reclaim
1177
+ * fall back together: lots short of the balance, or covering lots with no sats
1178
+ * basis, keep the pooled pro-rata figure rather than blending a lot rate with
1179
+ * a blended one. Mixed coverage counts as unpriceable for the same reason it
1180
+ * does on the reclaim.
1181
+ */
1182
+ declare function inKindDrawMsats(depletion: LotDepletion, amountMicro: number): number | null;
1183
+ /**
1184
+ * What these lots owe in kind if every remaining micro were reclaimed now —
1185
+ * the deposit-liability figure, and the floor the hub must never be swept
1186
+ * below.
1187
+ */
1188
+ declare function lotOwedSats(lots: FundingLot[]): number;
763
1189
  /**
764
1190
  * Sats held back from every non-channel Bitcoin reclaim to pay for handing it
765
1191
  * over (internal-review).
@@ -782,7 +1208,502 @@ interface FundingLot {
782
1208
  * rule the per-lot flooring already follows.
783
1209
  */
784
1210
  declare const DRAIN_DELIVERY_RESERVE_SATS = 8;
1211
+ /**
1212
+ * The figure a reclaim publishes: its in-kind gross less
1213
+ * {@link DRAIN_DELIVERY_RESERVE_SATS}, floored at zero.
1214
+ *
1215
+ * Zero is a refusal rather than a payout — a balance worth no more than what
1216
+ * it costs to send is `drain_below_dust`, since parking a zero-value token
1217
+ * would hold the servicer's queue open forever.
1218
+ */
1219
+ declare function netOwedSats(grossSats: number): number;
1220
+ /**
1221
+ * The order lots deplete in: oldest first, `lotId` breaking a tie.
1222
+ *
1223
+ * A tiebreak is not decoration — lot ids are surrogates rather than a
1224
+ * per-credit sequence (`fund` takes no credit lock, so two concurrent
1225
+ * fundings cannot cooperate on a counter), and two fundings can land on the
1226
+ * same millisecond. Without it the FIFO order is whatever the planner
1227
+ * returned, and a reclaim's figure would depend on it.
1228
+ */
1229
+ declare function fifoOrder(left: FundingLot, right: FundingLot): number;
1230
+ /**
1231
+ * Whether a depletion may be settled in kind, or has to fall back to pricing
1232
+ * the fiat balance at a live rate.
1233
+ *
1234
+ * Both failure modes are real and neither is the caller's fault: a credit's
1235
+ * lots can be short (a coverage hole the boot backfill is meant to close), and
1236
+ * a credit funded before internal-review recorded a rail basis at all has lots whose
1237
+ * `satsFunded` is 0 — pricing *that* in kind would answer "we owe you nothing"
1238
+ * for a deposit we plainly hold. Mixed coverage is treated as unbacked too:
1239
+ * blending a lot rate with a live rate produces a figure neither basis
1240
+ * supports.
1241
+ */
1242
+ declare function isInKindDepletion(depletion: LotDepletion, amountMicro: number): boolean;
785
1243
 
1244
+ /** The rails a payout lands on. Lightning never pays out: credits fund straight into the receive wallet. */
1245
+ type PayoutRail = "cashu" | "x402" | "tempo";
1246
+ /**
1247
+ * What gathered the payments into one transfer: a cashu accumulator melt, an
1248
+ * x402 batch settle to `pay_to`, a Tempo channel's cooperative close, or a
1249
+ * Tempo channel's scheduled / manual settlement to the recipient.
1250
+ */
1251
+ type PayoutKind = "melt" | "batch" | "close" | "settle";
1252
+ /** Which repair verb completed a stuck movement. Only `tempo_close_reconciled` is produced here today. */
1253
+ type PayoutRepairKind = "x402_settlement_reconciled" | "lightning_invoice_reconciled" | "tempo_close_reconciled";
1254
+ /**
1255
+ * JSON wire shape POSTed to the platform's `/_internal/payout` endpoint —
1256
+ * one landed movement into the builder's custody. Idempotent platform-side
1257
+ * on `(dvmId, payoutId)`, so the durable retry loop can redeliver freely; a
1258
+ * `repaired` redelivery of an id that already landed upgrades that row rather
1259
+ * than adding a second.
1260
+ */
1261
+ interface PayoutReportPayload {
1262
+ /** Required. Platform DVM record ID (`dvms.id`); must match the bearer token's DVM. */
1263
+ dvmId: string;
1264
+ /** Required. The DVM's own id for the movement — `cashu:melt:<quote>`, `x402:batch:<uuid>`, `tempo:<tx>`. */
1265
+ payoutId: string;
1266
+ rail: PayoutRail;
1267
+ kind: PayoutKind;
1268
+ /** Required. Rail-native atomic units: sats, or USDC micro. Always > 0. */
1269
+ nativeAmount: number;
1270
+ /** Required. `sats` for cashu, `usdc` for the stablecoin rails. */
1271
+ nativeAsset: "sats" | "usdc";
1272
+ /** Where it landed; `null` for a melt, whose Lightning destination the platform never records. */
1273
+ recipient: string | null;
1274
+ /** Mechanism references — mint, melt quote, tx hash, batch id, voucher count, channel id. Description material, never arithmetic. */
1275
+ refs: Record<string, unknown>;
1276
+ /** Required. When the money landed (epoch ms). */
1277
+ landedAt: number;
1278
+ /** Set when a repair verb completed this movement. */
1279
+ repaired?: boolean;
1280
+ /** Required iff `repaired`. */
1281
+ repairKind?: PayoutRepairKind;
1282
+ }
1283
+ /** A stuck movement inside a pending snapshot. */
1284
+ interface PayoutWedge {
1285
+ id: string;
1286
+ /**
1287
+ * `settle`: an x402 batch whose transfer keeps failing (auto-retried).
1288
+ * `refund`: an x402 cooperative refund wedged between chain and ledger —
1289
+ * caller money, not in the pool. `close`: a Tempo close wedged the same way.
1290
+ * `melt`: cashu rows whose builder-side melt failed.
1291
+ */
1292
+ kind: "settle" | "refund" | "close" | "melt";
1293
+ /** Epoch ms the wedge was first observed. */
1294
+ since: number;
1295
+ /** Retry count where the retry is automatic, else null. */
1296
+ attempts: number | null;
1297
+ /** Epoch ms of the next automatic retry, else null. */
1298
+ nextRetry: number | null;
1299
+ lastError: string | null;
1300
+ /** Rail-native amount held up, when known. */
1301
+ native?: number;
1302
+ }
1303
+ /** One pool inside a rail's pending figure — a mint, a batch, a channel. */
1304
+ interface PayoutPool {
1305
+ id: string;
1306
+ native: number;
1307
+ label?: string;
1308
+ }
1309
+ /**
1310
+ * JSON wire shape POSTed to the platform's `/_internal/payout-pending`
1311
+ * endpoint — one rail's snapshot of money still moving toward the builder,
1312
+ * replaced on each report. Best-effort: a lost one is superseded by the next
1313
+ * tick, so it rides no durable queue.
1314
+ */
1315
+ interface PayoutPendingPayload {
1316
+ dvmId: string;
1317
+ rail: PayoutRail;
1318
+ /** Everything on this rail still moving toward the builder, in atomic units. */
1319
+ poolNative: number;
1320
+ nativeAsset: "sats" | "usdc";
1321
+ /** How many pools the figure is made of. */
1322
+ items: number;
1323
+ pools: PayoutPool[];
1324
+ wedged: PayoutWedge[];
1325
+ /** This DVM's clock when the snapshot was taken (epoch ms). */
1326
+ snapshotAt: number;
1327
+ }
1328
+ /** The delivery seam — implemented by `RevenueReporter`, stubbed in tests. */
1329
+ interface PayoutTransport {
1330
+ /**
1331
+ * Queue a payout through the caller's open transaction, so the row and the
1332
+ * fact it reports commit or roll back together; without `tx` it is queued on
1333
+ * its own. Durable once committed — the retry loop delivers it, or
1334
+ * {@link PayoutTransport.drainPending} when a caller wants it now.
1335
+ */
1336
+ enqueuePayout(payload: PayoutReportPayload, tx?: RevenueReporterQuerier): Promise<void>;
1337
+ /** Queue a payout on its own and try to deliver it at once. */
1338
+ reportPayout(payload: PayoutReportPayload): Promise<void>;
1339
+ /** Best-effort: one POST, replaced by the next snapshot. */
1340
+ reportPayoutPending(payload: PayoutPendingPayload): Promise<void>;
1341
+ /** Deliver what is queued now rather than on the next retry tick. */
1342
+ drainPending?(): Promise<void>;
1343
+ }
1344
+ /**
1345
+ * A money-path hook whose report must commit with the fact it describes.
1346
+ * `enqueue` runs inside the caller's transaction, and a throw rolls the fact
1347
+ * back with it — the drain report's own discipline (internal-review): a call the
1348
+ * caller has to repeat costs a round trip, where a landed movement with no
1349
+ * row understates paid-out forever. `committed` runs once that transaction
1350
+ * has committed, for the delivery and the snapshot that must not read
1351
+ * uncommitted state.
1352
+ */
1353
+ interface TransactionalPayoutHook<E> {
1354
+ enqueue(event: E, tx: RevenueReporterQuerier): Promise<void>;
1355
+ committed(): void;
1356
+ }
1357
+ /** What `/admin/cashu/mark-melted` knows once the rows are marked. */
1358
+ interface CashuMeltCompleted {
1359
+ rows: {
1360
+ id: string;
1361
+ mintUrl: string;
1362
+ proofAmount: number;
1363
+ }[];
1364
+ meltQuoteId: string;
1365
+ paymentPreimage: string;
1366
+ }
1367
+ /** What mppx reports after a Tempo channel settlement or close confirmed on chain. */
1368
+ interface TempoSessionSettled {
1369
+ txHash: string;
1370
+ channelId: string;
1371
+ trigger: "settle" | "close" | "scheduled";
1372
+ /** Cumulative amount settled to the payee on this channel, atomic units. */
1373
+ amount: bigint;
1374
+ /** Newly settled to the payee by this transaction, atomic units. */
1375
+ delta: bigint;
1376
+ }
1377
+ /** What `reconcile-tempo-drain` re-read from the close receipt it booked against. */
1378
+ interface TempoCloseReconciled {
1379
+ channelId: string;
1380
+ txHash: string;
1381
+ /** Captured by the payee — this DVM — per the receipt, atomic units as a decimal string. */
1382
+ settledToPayee: string;
1383
+ }
1384
+ /** The channel view the tracker sums claims over. */
1385
+ interface X402TrackedChannel {
1386
+ channelId: string;
1387
+ chargedCumulativeAmount: string;
1388
+ totalClaimed: string;
1389
+ }
1390
+ /** A refund settlement wedged between chain and ledger (internal-review), for the wedge list. */
1391
+ interface X402WedgedRefund {
1392
+ settlementId: string;
1393
+ /** Epoch ms the settlement was first prepared. */
1394
+ createdAt: number;
1395
+ native?: number;
1396
+ }
1397
+ /** What the batch-settlement server hands the tracker once it knows its scope. */
1398
+ interface X402PayoutContext {
1399
+ /** `${network}|${payTo}|${token}` — the scope the settle-pending marker is keyed on. */
1400
+ scope: string;
1401
+ payTo: string;
1402
+ network: string;
1403
+ storage: {
1404
+ list(): Promise<X402TrackedChannel[]>;
1405
+ };
1406
+ /** The scheduler's settle cadence — what a wedge's `nextRetry` is derived from. */
1407
+ settleIntervalMs: number;
1408
+ listWedgedRefunds?: () => Promise<X402WedgedRefund[]>;
1409
+ }
1410
+ /** The two manager verbs the tracker wraps. */
1411
+ interface X402TrackedManager {
1412
+ claim(...args: never[]): Promise<{
1413
+ vouchers: number;
1414
+ transaction: string;
1415
+ }[]>;
1416
+ settle(): Promise<{
1417
+ transaction: string;
1418
+ }>;
1419
+ }
1420
+ /**
1421
+ * The batch-settlement server's view of the reporter: attach once with the
1422
+ * scope, then route every claim and settle through the tracked manager so
1423
+ * the open batch is kept and the settle emits the payout.
1424
+ */
1425
+ interface X402PayoutObserver {
1426
+ attach(ctx: X402PayoutContext): void;
1427
+ trackManager<M extends X402TrackedManager>(manager: M): M;
1428
+ /** A settle that landed outside the tracked manager — the manual claim-and-settle's own retry loop. */
1429
+ recordSettle(transaction: string): Promise<void>;
1430
+ /** A settle attempt that failed outside the tracked manager. One call per attempt a builder would count as one. */
1431
+ recordSettleFailure(error: unknown): Promise<void>;
1432
+ }
1433
+ /** The Tempo readers the host attaches after mounting. */
1434
+ interface TempoPayoutReader {
1435
+ /** The recipient address every Tempo payout names. */
1436
+ recipient?: string;
1437
+ /** CAIP-2 network for the refs, when known. */
1438
+ network?: string;
1439
+ listActive?: (limit: number, cursor?: {
1440
+ updatedAt: number;
1441
+ key: string;
1442
+ }) => Promise<{
1443
+ key: string;
1444
+ state: Record<string, unknown>;
1445
+ updatedAt: number;
1446
+ }[]>;
1447
+ listChannelDrains?: (args: {
1448
+ limit: number;
1449
+ after?: ChannelDrainCursor;
1450
+ createdBeforeMs: number;
1451
+ rail: "tempo";
1452
+ }) => Promise<CreditDrainRecord[]>;
1453
+ }
1454
+ /**
1455
+ * The claims gathered since the last settle — the batch the next settle pays
1456
+ * out. Durable across machines because claims run under the fleet lock on
1457
+ * whichever machine won the tick, and the settle that finally moves the money
1458
+ * may run on another: an in-process figure would report a partial amount
1459
+ * after any restart in between.
1460
+ */
1461
+ interface X402OpenBatch {
1462
+ scope: string;
1463
+ batchId: string;
1464
+ claimedNative: bigint;
1465
+ voucherCount: number;
1466
+ claims: number;
1467
+ openedAt: number;
1468
+ attempts: number;
1469
+ firstFailedAt: number | null;
1470
+ lastError: string | null;
1471
+ nextRetryAt: number | null;
1472
+ }
1473
+ /** Where the open batch lives — Postgres beside the settlement rows, or memory in dev. */
1474
+ interface X402BatchStore {
1475
+ get(scope: string): Promise<X402OpenBatch | undefined>;
1476
+ put(batch: X402OpenBatch): Promise<void>;
1477
+ delete(scope: string): Promise<void>;
1478
+ /**
1479
+ * Close the open batch and run `enqueue` in the same transaction, so the
1480
+ * payout row is queued exactly when the batch is gone and never otherwise:
1481
+ * a settle can never lose its payout, because a failed enqueue leaves the
1482
+ * batch open for the next settle to report in full. `false` when the batch
1483
+ * under `scope` is no longer `batchId` — a sibling settled it first — in
1484
+ * which case nothing is queued.
1485
+ */
1486
+ settle(scope: string, batchId: string, enqueue: (tx?: RevenueReporterQuerier) => Promise<void>): Promise<boolean>;
1487
+ }
1488
+ /** Construction options for {@link PayoutReporter}. */
1489
+ interface PayoutReporterOpts {
1490
+ /** Platform DVM record ID, bound into every report. */
1491
+ dvmId: string;
1492
+ transport: PayoutTransport;
1493
+ /**
1494
+ * The SDK's Postgres. Reads the cashu accumulator for the pending pool and
1495
+ * holds the open x402 batch; without it the batch lives in memory (dev) and
1496
+ * no cashu snapshot is taken.
1497
+ */
1498
+ db?: Pool;
1499
+ /**
1500
+ * Whether this DVM runs the cashu accumulator. The cashu snapshot reads
1501
+ * `wallet_accumulator`, which only that mode creates — on any other DVM the
1502
+ * read would fail every tick and warn about a rail it does not carry.
1503
+ */
1504
+ cashu?: boolean;
1505
+ /** Override the batch store (tests); defaults to Postgres on `db`, memory without. */
1506
+ batchStore?: X402BatchStore;
1507
+ /** Snapshot cadence, ms. Default 5 minutes. */
1508
+ snapshotIntervalMs?: number;
1509
+ /** Override for the current time (tests). */
1510
+ now?: () => number;
1511
+ }
1512
+ /**
1513
+ * Builds the payout and pending reports from the SDK's money paths and hands
1514
+ * them to the transport.
1515
+ *
1516
+ * Two entry points are transactional: `cashuMelted` and `tempoCloseReconciled`
1517
+ * queue their row inside the caller's transaction and throw when they cannot,
1518
+ * so the melt or the reconciled close rolls back with its missing report rather
1519
+ * than landing without one. The x402 settle and the pending snapshots are
1520
+ * fail-safe instead: a report that cannot be built or queued there is logged and
1521
+ * picked up on the next tick, never thrown into the settle that produced it.
1522
+ */
1523
+ declare class PayoutReporter implements PayoutTransport {
1524
+ private readonly dvmId;
1525
+ private readonly transport;
1526
+ private readonly db?;
1527
+ private readonly cashu;
1528
+ private readonly batches;
1529
+ private readonly ownsBatchStore;
1530
+ private readonly intervalMs;
1531
+ private readonly now;
1532
+ private x402?;
1533
+ private tempo?;
1534
+ private timer;
1535
+ private warmup;
1536
+ constructor(opts: PayoutReporterOpts);
1537
+ /** Boot DDL for the durable batch store, when this reporter owns one. */
1538
+ init(): Promise<void>;
1539
+ /**
1540
+ * Start the snapshot loop. Unref'd, so it never keeps a scale-to-zero
1541
+ * machine awake; a first snapshot runs shortly after boot so a fresh process
1542
+ * reports without waiting a whole interval.
1543
+ */
1544
+ start(): void;
1545
+ stop(): void;
1546
+ enqueuePayout(payload: PayoutReportPayload, tx?: RevenueReporterQuerier): Promise<void>;
1547
+ reportPayout(payload: PayoutReportPayload): Promise<void>;
1548
+ reportPayoutPending(payload: PayoutPendingPayload): Promise<void>;
1549
+ /** Deliver what is queued now; a transport without the seam waits for its retry loop. */
1550
+ flush(): Promise<void>;
1551
+ /** The hook `mark-melted` runs inside its transaction: the mark and its payout commit together. */
1552
+ meltHook(): TransactionalPayoutHook<CashuMeltCompleted>;
1553
+ /**
1554
+ * A melt completed: the accumulator rows are SPENT at the mint and the
1555
+ * Lightning payment reached the builder's destination. One payout per mint
1556
+ * in the call — a `mark-melted` normally names one, since a melt quote
1557
+ * belongs to one mint. The amount is the face value melted; the mint's fee
1558
+ * and the Lightning amount received are builder-machine facts this DVM does
1559
+ * not see.
1560
+ *
1561
+ * Queued through `tx` when the caller is inside the transaction that marks
1562
+ * the rows, and a failure is thrown rather than swallowed so that mark rolls
1563
+ * back with it — see {@link TransactionalPayoutHook}. Without `tx` the rows
1564
+ * are queued on their own and delivered at once.
1565
+ */
1566
+ cashuMelted(event: CashuMeltCompleted, tx?: RevenueReporterQuerier): Promise<void>;
1567
+ /** The host attaches the session store and ledger readers once they exist. */
1568
+ attachTempo(reader: TempoPayoutReader): void;
1569
+ /**
1570
+ * A Tempo channel settled or closed on chain. `delta` is what this
1571
+ * transaction newly paid the recipient; a transaction that paid nothing new
1572
+ * (a close of a fully settled channel) is no payout.
1573
+ */
1574
+ tempoSettled(event: TempoSessionSettled): Promise<void>;
1575
+ /** The hook `reconcile-tempo-drain` runs inside its transaction: the booking and its payout commit together. */
1576
+ tempoRepairHook(): TransactionalPayoutHook<TempoCloseReconciled>;
1577
+ /**
1578
+ * The operator repaired a wedged cooperative close (internal-review). The close's
1579
+ * payee side landed on chain when the close did; if the live hook reported
1580
+ * it, this upgrades that row to `repair`, otherwise it is the row. The
1581
+ * figure is the receipt's payee total for the channel.
1582
+ *
1583
+ * Queued through `tx` when the caller is inside the transaction that books
1584
+ * the drain, and thrown rather than swallowed so that booking rolls back
1585
+ * with it — see {@link TransactionalPayoutHook}.
1586
+ */
1587
+ tempoCloseReconciled(event: TempoCloseReconciled, tx?: RevenueReporterQuerier): Promise<void>;
1588
+ /** The observer the batch-settlement server attaches to and routes its manager through. */
1589
+ x402Observer(): X402PayoutObserver;
1590
+ /**
1591
+ * Wrap the upstream channel manager so every claim grows the open batch and
1592
+ * every settle closes it. The claim delta is read off storage rather than
1593
+ * off upstream's result, which carries only a voucher count; under the
1594
+ * fleet lock the before/after read is consistent. A channel the claim
1595
+ * removed on its way through — a refund's claim-then-delete (internal-review) —
1596
+ * moved whatever it still owed before it went, and that value reaches
1597
+ * `pay_to` in this batch too, so it counts at its pre-claim figure.
1598
+ */
1599
+ private trackX402Manager;
1600
+ private recordX402Claim;
1601
+ private recordX402Settle;
1602
+ private recordX402SettleFailure;
1603
+ /** Every rail this reporter can read, each on its own failure boundary. */
1604
+ snapshot(): Promise<void>;
1605
+ /**
1606
+ * Cashu: every unmelted proof in the accumulator, per mint. Rows whose
1607
+ * builder-side melt failed are still in the pool (they are still at the
1608
+ * mint) and listed as wedged until `restart-failed` clears them.
1609
+ */
1610
+ snapshotCashu(): Promise<void>;
1611
+ /**
1612
+ * x402: the open batch (claimed, not yet transferred) plus every channel's
1613
+ * unclaimed voucher value; wedged when the settle keeps failing, and the
1614
+ * refund settlements stuck between chain and ledger beside it.
1615
+ */
1616
+ snapshotX402(): Promise<void>;
1617
+ /**
1618
+ * Tempo: each active channel's spent-but-unsettled balance — earned, not
1619
+ * yet paid to the recipient — and the cooperative closes wedged between
1620
+ * chain and ledger (internal-review), aged past the same floor the repair queue
1621
+ * uses so an in-flight close is not reported as stuck.
1622
+ */
1623
+ snapshotTempo(): Promise<void>;
1624
+ }
1625
+
1626
+ /**
1627
+ * JSON wire shape POSTed to the platform's `/_internal/job-revenue` endpoint
1628
+ * and stored in `pending_revenue_reports.payload` for durable retry.
1629
+ *
1630
+ * The platform-side consumer is `OnJobCompleted`, implemented by
1631
+ * `createRevenueCallback`. Keep the two shapes in sync: the SDK and platform
1632
+ * deploy in lockstep, and any
1633
+ * backwards-incompatible field change requires a coordinated release. No `version`
1634
+ * field is included pre-launch because there are no external container-runtime
1635
+ * consumers yet; add one once the first third-party builder ships a container-runtime
1636
+ * DVM (trigger condition: external builder onboarded via `dvmctl deploy --container`).
1637
+ */
1638
+ interface RevenueReportPayload {
1639
+ /** Required. Platform DVM record ID (`dvms.id`). Identifies which DVM earned the revenue. */
1640
+ dvmId: string;
1641
+ /** Required. Job identifier used by the platform to de-duplicate revenue rows and link to the job record. */
1642
+ jobId: string;
1643
+ /** Required. Total amount paid by the caller in millisatoshis, across all credits that satisfied the job. */
1644
+ paidMsats: number;
1645
+ /** Optional. Cashu mint URL from which the payment tokens were issued. Set only for the `cashu` rail; omitted for all other rails. */
1646
+ paymentMint?: string;
1647
+ /**
1648
+ * Required. Payment rail identifier (`"cashu"`, `"tempo"`, `"x402"`, `"stripe"`).
1649
+ * Mirrors `PaymentMethod` on the platform; carried as a plain string over the wire
1650
+ * so the SDK has no platform-type dependency.
1651
+ */
1652
+ rail: string;
1653
+ /**
1654
+ * Optional. Settlement reference for the credit: EVM tx hash for `x402`, credential
1655
+ * challenge ID for `tempo`, `X-Cashu-Request-Id` UUID for `cashu`. Required by the
1656
+ * platform revenue ledger for `tempo`/`x402` rails (recordJobRevenue throws without it);
1657
+ * nullable for `cashu`.
1658
+ */
1659
+ paymentTxHash?: string;
1660
+ /**
1661
+ * Optional. Rail-native payment amount in atomic units: satoshis for `tempo`, USDC
1662
+ * microunits for `x402`, USD cents for `stripe`. Omitted for `cashu` (platform derives
1663
+ * `paidMsats / 1000`). Must be set together with `nativeAsset`.
1664
+ */
1665
+ nativeAmount?: number;
1666
+ /**
1667
+ * Optional. Asset tag paired with `nativeAmount`: `"sats"`, `"usdc"`, `"usdc.e"`, or
1668
+ * `"usd-cents"`. Both fields must be present for the platform to write a non-cashu
1669
+ * revenue row.
1670
+ */
1671
+ nativeAsset?: string;
1672
+ /**
1673
+ * Optional. Cashu flow discriminator. Set to `"p2pk_accumulator"` when the cashu
1674
+ * accumulator path (internal-review) satisfied the job; omitted for legacy cashu. Written into
1675
+ * `revenue_events.metadata.cashu_flow` by the platform so ops can split per-call cashu
1676
+ * rows by source.
1677
+ */
1678
+ cashuFlow?: string;
1679
+ /**
1680
+ * Optional. Credit this job's payment drew against (internal-review). Present on
1681
+ * every job a ledger-backed payment satisfied; its presence is what tells
1682
+ * the platform the row is a **draw-keyed** revenue event rather than a
1683
+ * pre-credits per-call one.
1684
+ */
1685
+ creditId?: string;
1686
+ /** Optional. The draw this job settled — one draw, one revenue row. */
1687
+ drawId?: string;
1688
+ /** Optional. The draw's fiat amount, 1e-6 of `creditCurrency`. The exact liability offset. */
1689
+ drawAmountMicro?: number;
1690
+ /** Optional. Currency the credit is denominated in (lowercase ISO, e.g. `usd`). */
1691
+ creditCurrency?: string;
1692
+ /**
1693
+ * Optional. Settlement instant (epoch ms) — draws are revenue *when they
1694
+ * settle*, so this dates the row. Omitted for pre-credits rows, which the
1695
+ * platform dates at record time as before.
1696
+ */
1697
+ settledAt?: number;
1698
+ /** Optional. The funding's own rail reference, for reconciling a draw back to its deposit. */
1699
+ fundingRef?: string;
1700
+ /**
1701
+ * Optional. Revenue class when this row is not ordinary service revenue.
1702
+ * `short_pay_forfeit` marks money kept from an underpayment that bought no
1703
+ * job (internal-review operator ruling) so analytics can exclude it.
1704
+ */
1705
+ kind?: string;
1706
+ }
786
1707
  /**
787
1708
  * JSON wire shape POSTed to the platform's `/_internal/credit-deposit`
788
1709
  * endpoint (internal-review). A funding event is a **deposit** — a liability until
@@ -1015,6 +1936,36 @@ interface CreditExpiryReleasePayload {
1015
1936
  * between the two overstates or understates committed value forever.
1016
1937
  */
1017
1938
  type CreditExpiryReleaseEnqueue = (tx: RevenueReporterQuerier, payload: CreditExpiryReleasePayload) => Promise<void>;
1939
+ /**
1940
+ * JSON wire shape POSTed to the platform's `/_internal/paid-job-death` endpoint
1941
+ * (internal-review) when the stale-job reaper force-fails a *paid* job — its pending
1942
+ * credit draw is released rather than settled, so the caller's payment is back
1943
+ * on their credit balance and reclaimable by drain. The platform resolves fiat
1944
+ * + owner and sends an ambient notice via the shared alert sink. Unlike
1945
+ * {@link RevenueReportPayload} this carries no durable-retry semantics: the
1946
+ * reaper's `stale_job_failed` structured log is the durable backstop, so a lost
1947
+ * report degrades to log-only rather than blocking the sweep.
1948
+ */
1949
+ interface PaidJobDeathPayload {
1950
+ /** Required. Platform DVM record ID (`dvms.id`). Bound to the authenticating token. */
1951
+ dvmId: string;
1952
+ /** Required. Job identifier the reaper force-failed. */
1953
+ jobId: string;
1954
+ /** Required. Capability the job dispatched to (e.g. `"add-episode"`). */
1955
+ capability: string;
1956
+ /** Required. Amount of the released credit draw in millisatoshis. */
1957
+ paidMsats: number;
1958
+ /** Required. Payment rail of the credit draw (`"cashu"` / `"tempo"` / `"x402"`). */
1959
+ rail: string;
1960
+ /** Required. Terminal reason the reaper set: dead worker vs never-terminal idle. */
1961
+ reason: string;
1962
+ /** Optional. Rail-native released amount, paired with `nativeAsset`. */
1963
+ nativeAmount?: number;
1964
+ /** Optional. Asset tag for `nativeAmount` (`"sats"` / `"usdc"` / …). */
1965
+ nativeAsset?: string;
1966
+ /** Optional. Cashu mint URL the credit draw's tokens were issued from. */
1967
+ paymentMint?: string;
1968
+ }
1018
1969
  /** Distinct causes for a settled credit draw that could not book revenue. */
1019
1970
  type RevenueSkippedNoRailReason = "credit_rail_null" | "credit_rail_unrecognized" | "job_rail_missing" | "ledger_not_configured";
1020
1971
  /**
@@ -1044,6 +1995,210 @@ interface RevenueSkippedNoRailPayload {
1044
1995
  /** Required classification of why the revenue rail was unavailable. */
1045
1996
  reason: RevenueSkippedNoRailReason;
1046
1997
  }
1998
+ /** Gas-balance observation POSTed by a platform-hosted x402 self-relay. */
1999
+ interface X402SelfRelayGasBalancePayload {
2000
+ /** Platform DVM record ID, bound to the authenticating platform token. */
2001
+ dvmId: string;
2002
+ /** Dedicated relay EOA whose Base ETH balance was read. */
2003
+ address: `0x${string}`;
2004
+ /** CAIP-2 Base network identifier. */
2005
+ network: string;
2006
+ /** Current native balance as a decimal wei string. */
2007
+ balanceWei: string;
2008
+ /** Configured paging floor as a decimal wei string. */
2009
+ lowBalanceWei: string;
2010
+ /** Millisecond timestamp at which the DVM read the balance. */
2011
+ checkedAt: number;
2012
+ }
2013
+ /** RPC-health transition POSTed by a platform-hosted x402 self-relay. */
2014
+ type X402SelfRelayRpcHealthPayload = {
2015
+ /** Platform DVM record ID, bound to the authenticating platform token. */
2016
+ dvmId: string;
2017
+ /** Dedicated relay EOA identifying the affected self-relay. */
2018
+ address: `0x${string}`;
2019
+ /** CAIP-2 Base network identifier. */
2020
+ network: string;
2021
+ /** Healthy transition clears an open RPC page. */
2022
+ status: "healthy";
2023
+ /** Millisecond timestamp at which the DVM observed the transition. */
2024
+ checkedAt: number;
2025
+ } | {
2026
+ /** Platform DVM record ID, bound to the authenticating platform token. */
2027
+ dvmId: string;
2028
+ /** Dedicated relay EOA identifying the affected self-relay. */
2029
+ address: `0x${string}`;
2030
+ /** CAIP-2 Base network identifier. */
2031
+ network: string;
2032
+ /** Failed transition opens or refreshes an RPC page. */
2033
+ status: "failed";
2034
+ /** Redacted failure class; never the provider error or endpoint URL. */
2035
+ reason: X402SelfRelayRpcFailureReason;
2036
+ /** Millisecond timestamp at which the DVM observed the transition. */
2037
+ checkedAt: number;
2038
+ };
2039
+ /** Configured Tempo operator fee-token balance POSTed by a hosted DVM. */
2040
+ interface TempoSettlementBalancePayload {
2041
+ dvmId: string;
2042
+ address: `0x${string}`;
2043
+ network: string;
2044
+ token: `0x${string}`;
2045
+ balanceMicro: string;
2046
+ lowBalanceMicro: string;
2047
+ checkedAt: number;
2048
+ ready: boolean;
2049
+ }
2050
+ /** Redacted Tempo operator fee-funding rejection POSTed by a hosted DVM. */
2051
+ interface TempoSettlementFailurePayload {
2052
+ dvmId: string;
2053
+ address: `0x${string}`;
2054
+ network: string;
2055
+ token: `0x${string}`;
2056
+ operation: "settle" | "close";
2057
+ errorClass: "InsufficientFundsError";
2058
+ checkedAt: number;
2059
+ balanceMicro?: string;
2060
+ channelId?: string;
2061
+ creditId?: string;
2062
+ drainId?: string;
2063
+ }
2064
+ /**
2065
+ * Durable revenue reporter for container-runtime DVMs (internal-review).
2066
+ *
2067
+ * On job completion the SDK calls `report()`, which persists the payload to
2068
+ * a local Postgres table and attempts an immediate POST to the platform.
2069
+ * A background retry loop picks up un-acked rows with exponential backoff.
2070
+ */
2071
+ declare class RevenueReporter {
2072
+ private readonly db;
2073
+ private readonly platformUrl;
2074
+ private readonly platformToken;
2075
+ private retryTimer;
2076
+ private static readonly RETRY_INTERVAL_MS;
2077
+ private static readonly MAX_BACKOFF_MS;
2078
+ private static readonly ABANDON_AFTER_MS;
2079
+ constructor(db: Pool, platformUrl: string, platformToken: string);
2080
+ /** Create the pending-reports table (idempotent). */
2081
+ init(): Promise<void>;
2082
+ /** The boot DDL itself — always runs under {@link withSdkInitLock} (internal-review). */
2083
+ private createTables;
2084
+ /** Persist a revenue report and attempt immediate delivery. */
2085
+ report(payload: RevenueReportPayload): Promise<void>;
2086
+ /**
2087
+ * Join a credit deposit to the caller-owned rail transaction.
2088
+ *
2089
+ * This method performs no network I/O: it only writes the reporter-owned
2090
+ * durable queue row through `tx`. The retry drain delivers the row after the
2091
+ * rail transaction commits, including after a process restart.
2092
+ */
2093
+ enqueueDeposit(tx: RevenueReporterQuerier, payload: CreditDepositPayload): Promise<void>;
2094
+ /** Join a released draw to the transaction that made the hold terminal. */
2095
+ enqueueCreditDrawRelease(tx: RevenueReporterQuerier, payload: CreditDrawReleasePayload): Promise<void>;
2096
+ /**
2097
+ * Join a credit drain to the transaction that made it terminal (internal-review).
2098
+ *
2099
+ * Same discipline as {@link enqueueDeposit} and the same reason: no network
2100
+ * I/O here, only the durable queue row, written through `tx` so the report
2101
+ * and the status CAS commit or roll back together. A drain whose row was
2102
+ * lost between the two would overstate outstanding liability forever —
2103
+ * the mirror image of a lost deposit.
2104
+ *
2105
+ * Named for the payload rather than the verb because `drain` already means
2106
+ * "flush the queue" in this class (see {@link drainPending}).
2107
+ */
2108
+ enqueueCreditDrain(tx: RevenueReporterQuerier, payload: CreditDrainPayload): Promise<void>;
2109
+ /**
2110
+ * Join a payout to the transaction that commits the movement it reports
2111
+ * (internal-review) — the batch close, the accumulator mark, the drain booking.
2112
+ * No network I/O, only the durable queue row through `tx`, the discipline
2113
+ * {@link enqueueCreditDrain} set and for the same reason: the money has
2114
+ * already moved on a rail this ledger does not own, so the platform row is
2115
+ * the only record the builder's dashboard has of it, and a row lost between
2116
+ * the fact and the queue would understate "paid out" forever. Without `tx`
2117
+ * the row is queued on the pool, for callers with no fact of their own to
2118
+ * commit. Idempotent on `(dvmId, payoutId)` platform-side, so the retry
2119
+ * loop redelivers freely.
2120
+ */
2121
+ enqueuePayout(payload: PayoutReportPayload, tx?: RevenueReporterQuerier): Promise<void>;
2122
+ /**
2123
+ * Report one landed payout on its own and try to deliver it at once — the
2124
+ * live Tempo settlement, which has no dvmkit transaction to join. Durable
2125
+ * like {@link report}.
2126
+ */
2127
+ reportPayout(payload: PayoutReportPayload): Promise<void>;
2128
+ /**
2129
+ * Report one rail's pending-pool snapshot (internal-review). Best-effort and
2130
+ * fire-and-forget, deliberately unlike {@link reportPayout}: a snapshot is
2131
+ * replaced by the next tick, so queueing a stale one behind an outage would
2132
+ * only deliver figures the platform already has newer ones for.
2133
+ */
2134
+ reportPayoutPending(payload: PayoutPendingPayload): Promise<void>;
2135
+ /**
2136
+ * Join a credit-expiry release — or the revival that reverses one — to the
2137
+ * transaction that made it true (internal-review).
2138
+ *
2139
+ * Same discipline as {@link enqueueCreditDrain}: no network I/O, only the
2140
+ * durable queue row written through `tx`. A release whose row was lost after
2141
+ * the sweep committed would understate committed value forever; a lost
2142
+ * reversal would overstate it, which is the worse direction — the builder
2143
+ * would see money as theirs that a revived credit can still buy work with.
2144
+ */
2145
+ enqueueCreditExpiryRelease(tx: RevenueReporterQuerier, payload: CreditExpiryReleasePayload): Promise<void>;
2146
+ /**
2147
+ * Report a reaper-force-failed paid job to the platform (internal-review) so the
2148
+ * operator receives an ambient notice that a DVM died or wedged mid-job.
2149
+ * Best-effort and fire-and-forget: unlike {@link report} there is no local
2150
+ * durable queue — a non-2xx or transport failure is structured-logged
2151
+ * (`paid_job_death_report_failed`) and dropped, since the reaper's own
2152
+ * `stale_job_failed` log is the durable record and a failed *alert* must never
2153
+ * wedge the sweep.
2154
+ */
2155
+ reportPaidJobDeath(payload: PaidJobDeathPayload): Promise<void>;
2156
+ /**
2157
+ * Report a settled draw whose revenue event was skipped (internal-review).
2158
+ * Best-effort and fire-and-forget: the SDK's structured
2159
+ * `revenue_skipped_no_rail` log is the durable backstop, so a failed notice
2160
+ * must never wedge terminal handling or the orphan-draw reconciler.
2161
+ */
2162
+ reportRevenueSkippedNoRail(payload: RevenueSkippedNoRailPayload): Promise<void>;
2163
+ /** Report the self-relay's Base gas gauge for platform-side paging and recovery. */
2164
+ reportX402SelfRelayGasBalance(payload: X402SelfRelayGasBalancePayload): Promise<void>;
2165
+ /** Report redacted self-relay RPC health for platform-side paging and recovery. */
2166
+ reportX402SelfRelayRpcHealth(payload: X402SelfRelayRpcHealthPayload): Promise<void>;
2167
+ /** Report the Tempo operator's fee-token gauge for paging and recovery. */
2168
+ reportTempoSettlementBalance(payload: TempoSettlementBalancePayload): Promise<void>;
2169
+ /** Report a redacted operator fee rejection immediately. */
2170
+ reportTempoSettlementFailure(payload: TempoSettlementFailurePayload): Promise<void>;
2171
+ private postTempoSettlementReadiness;
2172
+ /** Start the background retry loop. */
2173
+ startRetryLoop(): void;
2174
+ /** Stop the background retry loop. */
2175
+ stop(): void;
2176
+ /**
2177
+ * Operator-facing queue snapshot: distinguishes the live retry queue from
2178
+ * terminal (stale) rows and breaks the latter down by classification reason
2179
+ * (`token_rotated`, `client_error:<status>`, `abandoned`). Lets monitoring tell
2180
+ * transient backlog apart from permanently-failed rows.
2181
+ */
2182
+ getQueueStats(): Promise<{
2183
+ liveRetry: number;
2184
+ stale: number;
2185
+ byReason: Record<string, number>;
2186
+ }>;
2187
+ /**
2188
+ * Deliver one bounded batch from the durable queue.
2189
+ *
2190
+ * Public so startup/recovery tests and operator tooling can drive the same
2191
+ * drain the background timer uses without reaching into private state.
2192
+ */
2193
+ drainPending(): Promise<void>;
2194
+ /** Durably queue one report of either kind, then try it once immediately. */
2195
+ private enqueue;
2196
+ /** Insert one pending report through either the pool or an open transaction. */
2197
+ private insertPending;
2198
+ private attemptDelivery;
2199
+ /** Mark a pending row terminal (stale) with a classification reason. */
2200
+ private markStale;
2201
+ }
1047
2202
 
1048
2203
  /** Query surface shared by the pool and an open Postgres transaction. */
1049
2204
  type X402ChannelQuerier = Pick<Pool, "query">;
@@ -1063,8 +2218,8 @@ interface X402SettlementIntent {
1063
2218
  operation: "fund" | "refund";
1064
2219
  effectId: string;
1065
2220
  paymentId: string;
1066
- payload: PaymentPayload;
1067
- requirements: PaymentRequirements;
2221
+ payload: PaymentPayload$1;
2222
+ requirements: PaymentRequirements$1;
1068
2223
  channelBefore: Channel;
1069
2224
  /**
1070
2225
  * The channel as it stood when the settlement was handed to the facilitator —
@@ -1083,7 +2238,7 @@ interface X402SettlementIntent {
1083
2238
  submissionBlock?: string;
1084
2239
  pendingId?: string;
1085
2240
  status: X402SettlementStatus;
1086
- response?: SettleResponse;
2241
+ response?: SettleResponse$1;
1087
2242
  /** Epoch ms the row was first prepared. */
1088
2243
  createdAt: number;
1089
2244
  /** Epoch ms of the last status write — what the repair queue ages against. */
@@ -1350,7 +2505,7 @@ declare class PostgresX402ChannelStorage implements ChannelStorage {
1350
2505
  * reversed. On the live path the columns are already `NULL` and this is a
1351
2506
  * no-op.
1352
2507
  */
1353
- recordSettlementResponse(settlementId: string, response: SettleResponse): Promise<void>;
2508
+ recordSettlementResponse(settlementId: string, response: SettleResponse$1): Promise<void>;
1354
2509
  /**
1355
2510
  * Mark the external settlement and ledger effect complete in the active transaction.
1356
2511
  *
@@ -1437,15 +2592,15 @@ declare class PostgresX402ChannelStorage implements ChannelStorage {
1437
2592
 
1438
2593
  /** Durable channel seam used to compose a settled draw with consumed Tempo value. */
1439
2594
  interface TempoSessionSettlementStore {
1440
- withDrawPlacement<value>(channelId: string, operation: (tx: CreditLedgerQuerier, lifecycle: TempoSessionLifecycle) => Promise<value>, tx?: CreditLedgerQuerier): Promise<value>;
1441
- withTerminalConsumption<value>(channelId: string, operation: (tx: CreditLedgerQuerier, lifecycle: TempoSessionLifecycle) => Promise<{
2595
+ withDrawPlacement<value>(channelId: string, operation: (tx: CreditLedgerQuerier, lifecycle: TempoSessionLifecycle$1) => Promise<value>, tx?: CreditLedgerQuerier): Promise<value>;
2596
+ withTerminalConsumption<value>(channelId: string, operation: (tx: CreditLedgerQuerier, lifecycle: TempoSessionLifecycle$1) => Promise<{
1442
2597
  value: value;
1443
2598
  amount: bigint;
1444
2599
  consume: boolean;
1445
2600
  }>): Promise<value>;
1446
2601
  }
1447
2602
  /** Tempo channel state read while holding its durable row lock. */
1448
- interface TempoSessionLifecycle {
2603
+ interface TempoSessionLifecycle$1 {
1449
2604
  finalized: boolean;
1450
2605
  closeRequestedAt: bigint;
1451
2606
  spent: bigint;
@@ -3504,6 +4659,17 @@ declare class CreditLedgerError extends Error {
3504
4659
  constructor(code: CreditLedgerErrorCode, message: string, details?: CreditLedgerErrorDetails, opts?: ErrorOptions);
3505
4660
  }
3506
4661
 
4662
+ /** One durable Tempo session-channel row exposed to reconciliation workers. */
4663
+ interface TempoSessionRow {
4664
+ key: string;
4665
+ state: Record<string, unknown>;
4666
+ updatedAt: number;
4667
+ }
4668
+ /** Cursor for stable pagination over active Tempo session channels. */
4669
+ interface TempoSessionCursor {
4670
+ updatedAt: number;
4671
+ key: string;
4672
+ }
3507
4673
  /** Durable state joining a credit drain to its cooperative channel close. */
3508
4674
  interface TempoSessionCloseRecord {
3509
4675
  channelId: string;
@@ -3521,7 +4687,212 @@ type TempoSessionCloseForecastResolution<value> = {
3521
4687
  } | {
3522
4688
  outcome: "missing";
3523
4689
  };
4690
+ /** The voucher increment observed while holding the channel row lock. */
4691
+ interface TempoVoucherDelta {
4692
+ key: string;
4693
+ cumulativeAmount: bigint;
4694
+ priorCumulativeAmount: bigint;
4695
+ delta: bigint;
4696
+ }
4697
+ /** Result of a ledger resolution composed with terminal channel consumption. */
4698
+ interface TempoSessionConsumption<value> {
4699
+ value: value;
4700
+ amount: bigint;
4701
+ consume: boolean;
4702
+ }
4703
+ /** Channel lifecycle fields exposed while its row lock is held. */
4704
+ interface TempoSessionLifecycle {
4705
+ finalized: boolean;
4706
+ closeRequestedAt: bigint;
4707
+ spent: bigint;
4708
+ settledOnChain: bigint;
4709
+ highestVoucherAmount: bigint;
4710
+ }
4711
+ /**
4712
+ * Postgres implementation of mppx's atomic channel store.
4713
+ *
4714
+ * Every mutation takes an advisory transaction lock keyed by the channel
4715
+ * before locking its row with `FOR UPDATE`, applies mppx's synchronous
4716
+ * transition exactly once, and commits before returning. The advisory lock
4717
+ * covers a channel's first write, when there is no row for `FOR UPDATE` to
4718
+ * lock. Together these are the cross-machine linearization point for voucher,
4719
+ * top-up, spend, and close state; mppx's process-local fallback is
4720
+ * intentionally never used in a durable SDK host.
4721
+ *
4722
+ * Lock order remains channel before credit: mutation paths take the advisory
4723
+ * lock and then the row lock, while terminal consumption requires an existing
4724
+ * row and starts there. Both own the channel lock before the ledger takes its
4725
+ * parent-credit lock through the same client.
4726
+ *
4727
+ * {@link withVoucherAcceptance} acquires its pooled client **lazily**, on the
4728
+ * first store mutation rather than up front (internal-review). Its `operation` is
4729
+ * mppx's credential verification, which does the chain work before it touches
4730
+ * the store: an `open` submits the escrow transaction and awaits its receipt,
4731
+ * a `voucher` reads channel state over public RPC. Holding a connection across
4732
+ * that starves everything else on the shared host pool — `/v1/job`, the job
4733
+ * store, KV, the credit ledger, the replay store — and exposes the open
4734
+ * transaction to `idle_in_transaction_session_timeout`. This is the same shape
4735
+ * internal-review removed from the x402 settlement path. Laziness costs nothing in
4736
+ * atomicity: the `FOR UPDATE` row lock was always taken at the first mutation,
4737
+ * never at `BEGIN`, so the critical section is unchanged — only the
4738
+ * connection-holding window shrinks to the database work it actually covers.
4739
+ */
4740
+ declare class PostgresTempoSessionStore implements Store.AtomicStore {
4741
+ private readonly pool;
4742
+ private readonly acceptance;
4743
+ constructor(pool: Pool);
4744
+ /** Create the channel table under the SDK-wide migration lock. */
4745
+ init(): Promise<void>;
4746
+ /** Read one channel snapshot. */
4747
+ get(key: string): Promise<unknown>;
4748
+ /** Replace one channel snapshot. Used by mppx only for non-RMW maintenance. */
4749
+ put(key: string, value: unknown): Promise<void>;
4750
+ /** Delete one channel snapshot. */
4751
+ delete(key: string): Promise<void>;
4752
+ /** Atomic read-modify-write using a row lock shared by every SDK replica. */
4753
+ update<result>(key: string, fn: (current: unknown) => Store.Change<unknown, result>): Promise<result>;
4754
+ /** Compose voucher acceptance and its ledger mutation under the channel-row lock. */
4755
+ withVoucherAcceptance<value, result>(voucher: {
4756
+ channelId: string;
4757
+ cumulativeAmount: bigint;
4758
+ }, commit: (tx: PoolClient, voucher: TempoVoucherDelta) => Promise<result>, operation: () => Promise<value>): Promise<{
4759
+ value: value;
4760
+ result: result | undefined;
4761
+ }>;
4762
+ /**
4763
+ * Check out the acceptance transaction's client, opening it on first demand.
4764
+ *
4765
+ * An operation that never mutates the store therefore never takes a
4766
+ * connection and never opens an empty transaction — the caller sees the same
4767
+ * `result: undefined` it saw before, because nothing committed either way.
4768
+ *
4769
+ * The in-flight checkout is memoized, not just its result: mppx awaits each
4770
+ * store call today, but two concurrent first mutations would otherwise open
4771
+ * two transactions and leak the one nobody keeps a handle to.
4772
+ */
4773
+ private acceptanceClient;
4774
+ /** Serialize a credit draw with the channel lifecycle that authorizes it. */
4775
+ withDrawPlacement<value>(channelId: string, operation: (tx: CreditLedgerQuerier, lifecycle: TempoSessionLifecycle) => Promise<value>, tx?: CreditLedgerQuerier): Promise<value>;
4776
+ private withLockedLifecycle;
4777
+ /**
4778
+ * Compose a terminal ledger resolution with the channel's consumed value.
4779
+ *
4780
+ * Voucher acceptance records spending authority; only a successful job
4781
+ * consumes it. Holding the channel row while the callback locks and settles
4782
+ * the credit keeps that distinction atomic across machines and preserves the
4783
+ * shared channel -> credit lock order.
4784
+ */
4785
+ withTerminalConsumption<value>(channelId: string, operation: (tx: PoolClient, lifecycle: TempoSessionLifecycle) => Promise<TempoSessionConsumption<value>>): Promise<value>;
4786
+ /** Retire lost backing while holding the channel row ahead of every credit lock. */
4787
+ withFinalizedCreditLoss<value>(channelId: string, operation: (tx: PoolClient, lifecycle: TempoSessionLifecycle) => Promise<value>): Promise<value>;
4788
+ /** Page active channel snapshots for the close/settlement watcher. */
4789
+ listActive(limit?: number, cursor?: TempoSessionCursor): Promise<TempoSessionRow[]>;
4790
+ /** Persist a drain's close intent before its credential is broadcast. */
4791
+ beginClose(channelId: string, drainId: string): Promise<TempoSessionCloseRecord>;
4792
+ /** Reserve a close intent and run its ledger debit in the same transaction. */
4793
+ withCloseIntent<value>(channelId: string, drainId: string, operation: (tx: PoolClient) => Promise<value>): Promise<value>;
4794
+ /**
4795
+ * Resolve a reserved close's forecast under the intent row lock.
4796
+ *
4797
+ * `proceed` opens the broadcast gate. `release` deletes the intent and runs
4798
+ * the ledger restore in the same transaction, but only while the gate is
4799
+ * still pending. A concurrent proceed wins by returning `proceed` to the
4800
+ * releaser, which must not restore value that may already be broadcasting.
4801
+ */
4802
+ resolveCloseForecast<value>(channelId: string, drainId: string, decision: TempoSessionCloseForecastDecision, operation?: (tx: PoolClient) => Promise<value>): Promise<TempoSessionCloseForecastResolution<value>>;
4803
+ /** Delete a matching close intent and release its ledger debit atomically. */
4804
+ releaseCloseIntent<value>(channelId: string, drainId: string, operation: (tx: PoolClient) => Promise<value>): Promise<value>;
4805
+ /** Read a persisted cooperative-close intent or confirmed result. */
4806
+ getClose(channelId: string): Promise<TempoSessionCloseRecord | null>;
4807
+ /** Persist proof that a cooperative close reached terminal chain state. */
4808
+ confirmClose(channelId: string, drainId: string, reference: string): Promise<TempoSessionCloseRecord>;
4809
+ private runCloseIntentTransaction;
4810
+ private transaction;
4811
+ private writeCloseIntent;
4812
+ private updateInTransaction;
4813
+ }
3524
4814
 
4815
+ /**
4816
+ * Options for assembling an Mppx server handle from explicit recipient strings
4817
+ * and the surrounding environment. The SDK boundary owns env reads so DVM
4818
+ * authors only think in terms of "set DVMKIT_TEMPO_RECIPIENT /
4819
+ * DVMKIT_TEMPO_SECRET_KEY in your DVM env" — same pattern as the existing
4820
+ * payment-rail inputs.
4821
+ */
4822
+ interface MppOpts {
4823
+ /**
4824
+ * Tempo recipient (0x-prefixed 40-char hex address). When set, registers
4825
+ * `tempo/charge`. Currency defaults to USDC on Tempo mainnet; override via
4826
+ * the `DVMKIT_TEMPO_CURRENCY` env var for testnet/devnet deployments.
4827
+ */
4828
+ tempoRecipient?: string;
4829
+ /**
4830
+ * Server realm for advertising on `/v1/info`. Default resolution lives in
4831
+ * mppx (env vars `MPP_REALM`, `FLY_APP_NAME`, `VERCEL_URL`, request URL,
4832
+ * `"MPP Payment"`).
4833
+ */
4834
+ realm?: string;
4835
+ /**
4836
+ * When set, only register MPP methods whose name appears in this list, even
4837
+ * if the per-rail env var (`DVMKIT_TEMPO_RECIPIENT`) is configured
4838
+ * (internal-review). Lets operators temporarily disable a rail without unsetting
4839
+ * other knobs. Empty/undefined falls back to "register everything that has
4840
+ * a configured recipient".
4841
+ */
4842
+ methodsAllowlist?: string[];
4843
+ /**
4844
+ * Durable replay protection for the one-shot `tempo/charge` method
4845
+ * (internal-review). Omit and mppx falls back to `Store.memory()`, whose consumed
4846
+ * transaction hashes are per-process — invisible to sibling machines and lost
4847
+ * on restart. Pass a cross-machine store (`PostgresTempoChargeStore`) on any
4848
+ * multi-instance deploy.
4849
+ *
4850
+ * The same store also backs mppx's fee-sponsor budget and, because mppx
4851
+ * enables proof-credential replay protection only when a store is supplied,
4852
+ * turns that guard on as a side effect.
4853
+ */
4854
+ tempoCharge?: {
4855
+ store: Store.AtomicStore;
4856
+ };
4857
+ /**
4858
+ * Durable TIP-1034 session support. Omit to keep the existing one-shot
4859
+ * `tempo/charge` method only. The account must be able to submit settlement
4860
+ * transactions as the channel payee/operator; an address-only client is not
4861
+ * sufficient.
4862
+ */
4863
+ tempoSession?: {
4864
+ store: Store.AtomicStore;
4865
+ account: Account;
4866
+ getClient?: (parameters: {
4867
+ chainId?: number;
4868
+ }) => Client | Promise<Client>;
4869
+ chainId?: number;
4870
+ settlementSchedule?: {
4871
+ units?: number;
4872
+ amount?: string | bigint;
4873
+ intervalMs?: number;
4874
+ /**
4875
+ * How long a settlement holds its in-flight lease (internal-review). Defaults to
4876
+ * {@link TEMPO_SETTLEMENT_LEASE_MS}, which documents the receipt-timeout
4877
+ * floor an override has to stay above.
4878
+ */
4879
+ leaseMs?: number;
4880
+ };
4881
+ beforeSessionSettlement?: () => string | undefined | Promise<string | undefined>;
4882
+ onSessionSettlement?: (context: {
4883
+ txHash: `0x${string}`;
4884
+ channelId: `0x${string}`;
4885
+ trigger: "settle" | "close" | "scheduled";
4886
+ amount: bigint;
4887
+ delta: bigint;
4888
+ recoveryVersion?: string;
4889
+ }) => void | Promise<void>;
4890
+ onInsufficientFunds?: (context: {
4891
+ operation: "settle";
4892
+ channelId: string;
4893
+ }) => void | Promise<void>;
4894
+ };
4895
+ }
3525
4896
  /**
3526
4897
  * Loose runtime view of an `Mppx.create(...)` handle. mppx's full generic
3527
4898
  * typing is precise but propagates badly through layers — the SDK boundary
@@ -3724,6 +5095,36 @@ interface TempoSessionDrainState {
3724
5095
  deposit: bigint;
3725
5096
  finalized: boolean;
3726
5097
  }
5098
+ /**
5099
+ * Attach the typed `issueChallenge` dispatcher to a freshly-created mppx
5100
+ * handle. Production builds via `createMppFromOpts`; tests build via
5101
+ * `Mppx.create(...)` directly and use `wrapMppx` to satisfy the SDK boundary.
5102
+ *
5103
+ * Accepts `unknown` because mppx's `Mppx<methods, transport>` generic doesn't
5104
+ * collapse cleanly through `ReturnType<typeof Mppx.create>` — the default
5105
+ * pins `methods: readonly []` and rejects any concrete method tuple. We cast
5106
+ * inside the wrapper instead of leaking the generic onto every caller.
5107
+ */
5108
+ declare function wrapMppx(mppx: unknown): MppxServer;
5109
+ interface TempoSessionChainOps {
5110
+ getChannelStatesBatch(client: Client, channelIds: readonly Hex[], escrowContract: `0x${string}`): Promise<{
5111
+ settled: bigint;
5112
+ deposit: bigint;
5113
+ closeRequestedAt: number;
5114
+ }[]>;
5115
+ settle(store: Store.AtomicStore, client: Client, channelId: Hex, options: {
5116
+ account: Account;
5117
+ escrowContract: `0x${string}`;
5118
+ feeToken: `0x${string}`;
5119
+ onSessionSettlement?: NonNullable<MppOpts["tempoSession"]>["onSessionSettlement"];
5120
+ }): Promise<Hex>;
5121
+ readChannelClose(client: Client, channelId: Hex, txHash: Hex): Promise<TempoChannelCloseAmounts>;
5122
+ }
5123
+ declare function attachTempoSessionRuntime(mppx: MppxServer, config: MppOpts["tempoSession"], chainOpOverrides?: Partial<TempoSessionChainOps>): MppxServer;
5124
+ /** Test-only seams for deterministic watcher coverage without a live Tempo RPC. */
5125
+ declare const _testing: {
5126
+ attachTempoSessionRuntime: typeof attachTempoSessionRuntime;
5127
+ };
3727
5128
 
3728
5129
  /** Envelope fields the verifier validates around the signed payload. */
3729
5130
  interface CanonicalEnvelope {
@@ -3835,6 +5236,28 @@ interface SignedRequestVerifier<T> {
3835
5236
  }
3836
5237
  /** Failure mode taxonomy returned from `verify()`. */
3837
5238
  type SignedRequestFailure = "schema_invalid" | "timestamp_drift" | "signature_invalid" | "replay_detected";
5239
+ /**
5240
+ * The four fields every signed-request envelope carries around the payload,
5241
+ * with the runtime type each must have once the schema has parsed.
5242
+ *
5243
+ * The single definition of "which part of a schema failure is the envelope's":
5244
+ * the post-parse shape check in `parse()` iterates it, and `authErrorBody`'s
5245
+ * internal-review classifier reads its keys to decide whether a `schema_invalid` throw
5246
+ * is the caller's *input* being wrong (disclosable: the schema is public on
5247
+ * `/v1/info`) or their *signing* being wrong (folded into `signature_invalid`,
5248
+ * one answer for every key and signature failure). `satisfies` pins it to
5249
+ * {@link CanonicalEnvelope}, so a fifth envelope field can't be added to the
5250
+ * type without both readers picking it up.
5251
+ */
5252
+ declare const SIGNED_ENVELOPE_TYPES: {
5253
+ readonly pubkey: "string";
5254
+ readonly signature: "string";
5255
+ readonly timestamp: "number";
5256
+ readonly nonce: "string";
5257
+ readonly auth_statement: "object";
5258
+ };
5259
+ /** The envelope field names — {@link SIGNED_ENVELOPE_TYPES}' keys. */
5260
+ declare const SIGNED_ENVELOPE_FIELDS: readonly (keyof CanonicalEnvelope)[];
3838
5261
  /** Structured error from `verify()` — `sub_reason` is the failure kind. */
3839
5262
  declare class SignedRequestError extends Error {
3840
5263
  readonly sub_reason: SignedRequestFailure;
@@ -3900,6 +5323,23 @@ declare function signedRequestInput(body: {
3900
5323
  input?: string;
3901
5324
  data?: unknown;
3902
5325
  }): unknown;
5326
+ /**
5327
+ * Build the bounded in-memory FIFO replay store used as the default when no
5328
+ * cross-machine `SignedRequestReplayStore` is supplied. 10-minute retention
5329
+ * window, 100k entry cap, per-process. Exported so `secp256k1Auth(...)` can
5330
+ * pre-build one and share it across every per-schema verifier plus its own
5331
+ * `recordReplay` path (internal-review).
5332
+ *
5333
+ * When the cap is hit after the time-expired sweep, fresh inserts are
5334
+ * **rejected** (return `true` — treated as replay at the wire) rather than
5335
+ * silently evicting an in-window entry. Silent eviction would flush a
5336
+ * still-valid nonce back to "unseen" and let an attacker who can drive cap
5337
+ * pressure replay it (internal-review). A rate-limited structured warning fires so
5338
+ * operators see saturation in `fly logs`; reaching cap means in-memory has
5339
+ * been pushed past where it's safe and the deploy should move to
5340
+ * `PostgresReplayStore`.
5341
+ */
5342
+ declare function createDefaultReplayStore(): SignedRequestReplayStore;
3903
5343
 
3904
5344
  /**
3905
5345
  * A DVM-level auth scheme, declared on `DVMDescriptor.auth`. Authentication
@@ -4383,6 +5823,35 @@ type PaymentMethod = "cashu" | "x402" | "tempo";
4383
5823
  * stops that dead rail from reappearing every time the funding menu grows.
4384
5824
  */
4385
5825
  type FundingMethod = PaymentMethod | "lightning";
5826
+ /**
5827
+ * Whether a failed job on a given rail can return the caller's funds (internal-review).
5828
+ *
5829
+ * **No rail refunds on `ctx.fail`, and no code behind the idea any more.** Under
5830
+ * the P2PK-accumulator Cashu path — the only Cashu path post-internal-review/internal-review —
5831
+ * `verifyAccumulatorReceipt` commits the caller's proofs straight into
5832
+ * `wallet_accumulator` and leaves `job.receivedProofs` empty; every producer in
5833
+ * `payment.ts` returns `[]`. The `ctx.fail(err, { refund: true })` branch that
5834
+ * used to send proofs back gated on those held proofs, so it had been an
5835
+ * unreachable no-op for as long as the accumulator has been the commit boundary,
5836
+ * and internal-review deleted it. This fail-closed posture was locked by internal-review
5837
+ * (Decision C) and pinned by internal-review. mpp (Tempo) and x402 credentials are
5838
+ * single-use, final-settlement — no SDK-managed reversal path either.
5839
+ *
5840
+ * **This is a rail-level question, and since internal-review it is no longer the whole
5841
+ * story.** A failed job never debits: the draw is a hold the terminal funnel
5842
+ * releases (`JobManager.resolveCreditDraw`), so the value stays on the caller's
5843
+ * credit. What this flag reports is narrower and still true — no rail hands
5844
+ * value backwards — and reclaiming a released balance runs through the
5845
+ * internal-review `drain` op, which exists only on a DVM that advertises credit.
5846
+ *
5847
+ * `{ refund: true }` survives as a **caller-fault annotation only** — first-party
5848
+ * handlers tag which errors were the caller's doing, and `sdk/testing`'s
5849
+ * `createTestContext` exposes it — and it is not a hook waiting to be re-wired.
5850
+ * internal-review, the accumulator-debit rewrite that would have flipped `cashu` back to
5851
+ * `true`, was cancelled as superseded: the ledger is where reclaim lives now.
5852
+ * x402 refund parity remains a deferred internal-review exploration.
5853
+ */
5854
+ declare const RAIL_REFUNDABLE: Record<PaymentMethod, boolean>;
4386
5855
  /**
4387
5856
  * Cashu receive mode for builder DVMs (internal-review).
4388
5857
  *
@@ -5346,5 +6815,22 @@ interface OutgoingMessage {
5346
6815
  * that calls the member it's missing.
5347
6816
  */
5348
6817
  declare function isStreamableJobStore(store: JobStore): store is StreamableJobStore;
6818
+ /**
6819
+ * The stale-job reaper surface (internal-review) — the two methods a sweeper needs to
6820
+ * find and atomically reap worker-stranded jobs. A strict subset of
6821
+ * `StreamableJobStore`: `MemoryJobStore` and `PostgresJobStore` satisfy it via
6822
+ * the full streamable interface, and the platform's `IsolateJobStore` (a plain
6823
+ * single-machine `JobStore`, not streamable) implements just these two so the
6824
+ * `IsolateJobManager` reaper can sweep the `isolate_jobs` table without taking
6825
+ * on the streaming/LISTEN machinery it doesn't need.
6826
+ */
6827
+ interface StaleJobReapable {
6828
+ /** See {@link StreamableJobStore.findStaleJobs}. */
6829
+ findStaleJobs(processingThresholdMs: number, awaitingThresholdMs: number, limit: number, capabilities: string[] | null): Promise<JobRecord[]>;
6830
+ /** See {@link StreamableJobStore.cancelStaleJob}. */
6831
+ cancelStaleJob(jobId: string, expectedActivityBefore: number, reason: string, terminalStatus: "failed" | "cancelled"): Promise<boolean>;
6832
+ }
6833
+ /** Runtime type guard for StaleJobReapable. */
6834
+ declare function isStaleJobReapable(store: JobStore): store is JobStore & StaleJobReapable;
5349
6835
 
5350
- export { type CreditSnapshot as $, type ApprovalContent as A, type SignedRequestDomain as B, type Currency as C, type DVMConfig as D, SignedRequestError as E, type SignedRequestFailure as F, type SignedRequestReplayStore as G, type SignedRequestSignOpts as H, type IncomingMessage as I, type JobRecord as J, type KVStore as K, type Logger as L, type SignedRequestStatementHeader as M, type SignedRequestVerifier as N, createSignedRequestVerifier as O, type PaymentContent as P, type QuoteConfig as Q, type ResolvedCreditConfig as R, type SDKJobContext as S, isZodSchema as T, UnsupportedCurrencyError as U, signedRequestStatementHeader as V, validateCurrency as W, type CashuMode as X, type FundingMethod as Y, type ZodLike as Z, type CreditLedgerLike as _, type DVMDescriptor as a, type OutgoingMessage as a$, type CreditInvoiceRecord as a0, type CreditDepositEnqueue as a1, type InvoiceSettlement as a2, type MppxServer as a3, type X402Config as a4, type ClientCompatibilityGate as a5, type Message as a6, type FundingReceipt as a7, type TopUpCapUnenforcedReason as a8, type JobReceipt as a9, type X402UnresolvedRefund as aA, type GrownDrawResult as aB, type DrawResolution as aC, type FundingRecord as aD, type BlockedInvoiceCursor as aE, type InvoiceReconciliation as aF, type InvoiceWriteOff as aG, type DrawRecord as aH, type StalePendingDrawCursor as aI, type TempoCreditLossEvidence as aJ, type TempoCreditLoss as aK, type X402CreditLossEvidence as aL, type X402CreditLoss as aM, type DrainMethod as aN, type DrainRequestResult as aO, type BitcoinDepositLiability as aP, type FundingLot as aQ, type CreditDrainRecord as aR, type ChannelDrainCursor as aS, type DrainWriteOff as aT, type DrainReleaseResult as aU, type DrainFulfilment as aV, type DrainTransitionResult as aW, type StreamableJobStore as aX, type ReceiptIssuingStore as aY, type RequestIdClaim as aZ, type RequestIdClaimResult as a_, type AppendOutgoingOptions as aa, StepCache as ab, type X402Receipt as ac, type X402ExactVersionSupport as ad, type X402SettlementIntent as ae, type X402FacilitatorAuth as af, type X402BatchSettlementConfig as ag, PostgresX402ChannelStorage as ah, type PaymentRequirementsV2 as ai, type CreditLedgerQuerier as aj, type X402SettlementCursor as ak, type X402SettlementStatus as al, type X402SettlementWriteOff as am, type X402RefundSettlementGate as an, type MppxCredential as ao, type ReceiptCredit as ap, type DrainReceiptEvent as aq, type DrainReceipt as ar, type CreditDrawReleaseEnqueue as as, type CreditDepositPayload as at, type RevenueSkippedNoRailPayload as au, type MessageType as av, type ClientCompatibility as aw, type CreditDrainEnqueue as ax, type DVMAuthScheme as ay, type DrawResult as az, type ArtifactContent as b, type PaymentCreditDelta as b0, type VerifyAndCreditResult as b1, type JobCounters as b2, CLIENT_COMPATIBILITY_HEADERS as b3, type ClientCompatibilityEnv as b4, type ClientCompatibilityRequirement as b5, type ClientSemVer as b6, type CreditFundingBasis as b7, type CreditInvoiceStatus as b8, CreditLedger as b9, requireClientCompatibility as bA, secp256k1Auth as bB, signedRequestInput as bC, CreditLedgerError as ba, type CreditLedgerErrorCode as bb, type CreditLedgerErrorDetails as bc, type CreditLedgerPool as bd, type CreditStatus as be, DRAIN_DELIVERY_RESERVE_SATS as bf, DVM_PROTOCOL_VERSION as bg, type DrainConflictReason as bh, type DrawRailValue as bi, type DrawStatus as bj, type ReplayStoreBackend as bk, type RevenueSkippedNoRailReason as bl, type Secp256k1AuthOpts as bm, type X402ChannelStorageOpts as bn, type X402RelayLockHolder as bo, type X402RelaySubmissionLock as bp, X402RelaySubmissionLockError as bq, allocateDrawValue as br, clientCompatibilityAttributes as bs, clientCompatibilityMiddleware as bt, clientUpgradeRequired as bu, isStreamableJobStore as bv, parseClientCapabilities as bw, parseClientCompatibility as bx, parseDvmClient as by, parseProtocolVersion as bz, type CancelContent as c, type CanonicalEnvelope as d, type CreateSignedRequestVerifierOpts as e, type CreditConfig as f, type CreditView as g, DEFAULT_CREDIT_MAX as h, DEFAULT_CREDIT_MIN as i, DEFAULT_CREDIT_TTL_SECONDS as j, type DVMRouteContext as k, type InputType as l, InvalidCurrencyError as m, type JobStatus as n, type JobStore as o, type PaymentMethod as p, type PriceValue as q, type ProgressContent as r, type PromptOpts as s, type QuoteContext as t, type QuoteResult as u, type ResponseContent as v, type SDKPaymentRequestOpts as w, SIGNED_REQUEST_AUTH_ID as x, SIGNED_REQUEST_STATEMENT_VERSION as y, type SignedRequestAudience as z };
6836
+ export { type PaymentRequired as $, type ApprovalContent as A, type SignedRequestDomain as B, type Currency as C, type DVMConfig as D, SignedRequestError as E, type SignedRequestFailure as F, type SignedRequestReplayStore as G, type SignedRequestSignOpts as H, type IncomingMessage as I, type JobRecord as J, type KVStore as K, type Logger as L, type SignedRequestStatementHeader as M, type SignedRequestVerifier as N, createSignedRequestVerifier as O, type PaymentContent as P, type QuoteConfig as Q, type ResolvedCreditConfig as R, type SDKJobContext as S, isZodSchema as T, UnsupportedCurrencyError as U, signedRequestStatementHeader as V, validateCurrency as W, type JsonValue as X, type FundingReceipt as Y, type ZodLike as Z, type JobReceipt as _, type DVMDescriptor as a, caip2ToX402Network as a$, type X402Version as a0, type MppxCredential as a1, type Message as a2, type MessageType as a3, type MppxChallenge as a4, X402_BATCH_SETTLEMENT_SCHEME as a5, X402_EXACT_SCHEME as a6, type X402Wallet as a7, type X402Config as a8, type X402ExactVersionSupport as a9, PayoutReporter as aA, PostgresTempoSessionStore as aB, RAIL_REFUNDABLE as aC, type ReceiptCredit as aD, type ReceiptOutcome as aE, type ReceiptPayment as aF, type ResourceInfo as aG, RevenueReporter as aH, SIGNED_ENVELOPE_FIELDS as aI, SIGNED_ENVELOPE_TYPES as aJ, type SettleResponse as aK, type StaleJobReapable as aL, StepCache as aM, type StepRecord as aN, type UnsignedDrainReceipt as aO, type UnsignedFundingReceipt as aP, type UnsignedJobReceipt as aQ, type VerifyResponse as aR, type X402ResponseBody as aS, type X402SelfRelayRpcFailureReason as aT, type X402TrackedChannel as aU, X402_DEFAULT_NETWORK as aV, X402_V1_VERSION as aW, X402_VERSION as aX, _testing as aY, buildPaymentRequiredV2 as aZ, buildPaymentRequirements as a_, type X402Receipt as aa, type TransactionalPayoutHook as ab, type CashuMeltCompleted as ac, type BuildPaymentRequirementsOpts as ad, type CapabilityDescriptor as ae, type CashuMode as af, type CreditDepositPayload as ag, type DrainReceipt as ah, type DrainReceiptEvent as ai, type ExactEvmPayload as aj, type ExactEvmPayloadAuthorization as ak, type FundingLot as al, type FundingMethod as am, type LotDebit as an, type LotDepletion as ao, type MppxServer as ap, NON_CHANNEL_BITCOIN_RAILS as aq, type NonChannelBitcoinRail as ar, type OutgoingMessage as as, type PaymentPayload as at, type PaymentPayloadV1 as au, type PaymentPayloadV2 as av, type PaymentRequiredV2 as aw, type PaymentRequirements as ax, type PaymentRequirementsV1 as ay, type PaymentRequirementsV2 as az, type ArtifactContent as b, type DrainMethod as b$, canonicaliseForSigning as b0, canonicalize as b1, chainIdFromCaip2 as b2, computeResultHash as b3, createDefaultReplayStore as b4, decodePayment as b5, decodePaymentRequiredHeader as b6, depleteLots as b7, encodePayment as b8, encodePaymentRequiredHeader as b9, verifyReceipt as bA, verifyWithFacilitator as bB, wrapMppx as bC, x402NetworkToCaip2 as bD, type CreditDrainEnqueue as bE, type DVMAuthScheme as bF, type CreditLedgerLike as bG, type X402RefundSettlementGate as bH, type CreditSnapshot as bI, type DrawResult as bJ, type X402SettlementStatus as bK, type X402UnresolvedRefund as bL, type GrownDrawResult as bM, type DrawResolution as bN, type FundingRecord as bO, type CreditInvoiceRecord as bP, type InvoiceSettlement as bQ, type BlockedInvoiceCursor as bR, type InvoiceReconciliation as bS, type InvoiceWriteOff as bT, type DrawRecord as bU, type StalePendingDrawCursor as bV, type TempoCreditLossEvidence as bW, type CreditLedgerQuerier as bX, type TempoCreditLoss as bY, type X402CreditLossEvidence as bZ, type X402CreditLoss as b_, encodeSettleResponseHeader as ba, exactEvmAuthorization as bb, fifoOrder as bc, inKindDrawMsats as bd, isArtifactMessage as be, isDrainReceipt as bf, isFundingReceipt as bg, isInKindDepletion as bh, isNonChannelBitcoinRail as bi, isPaymentRequestMessage as bj, isPromptMessage as bk, isSignedJobReceipt as bl, isStaleJobReapable as bm, lotOwedSats as bn, netOwedSats as bo, paymentRequiredV2FromV1 as bp, settleWithFacilitator as bq, signDrainReceipt as br, signFundingReceipt as bs, signReceipt as bt, usdcContractByCaip2 as bu, usdcContractFor as bv, usdcDomainNameFor as bw, usdcDomainVersionFor as bx, verifyDrainReceipt as by, verifyFundingReceipt as bz, type CancelContent as c, type X402PayoutObserver as c$, type DrainRequestResult as c0, type BitcoinDepositLiability as c1, type CreditDrainRecord as c2, type ChannelDrainCursor as c3, type DrainWriteOff as c4, type DrainReleaseResult as c5, type DrainFulfilment as c6, type DrainTransitionResult as c7, type StreamableJobStore as c8, type ReceiptIssuingStore as c9, type ReplayStoreBackend as cA, type RevenueSkippedNoRailPayload as cB, type RevenueSkippedNoRailReason as cC, type Secp256k1AuthOpts as cD, type X402ChannelStorageOpts as cE, type X402RelayLockHolder as cF, type X402RelaySubmissionLock as cG, X402RelaySubmissionLockError as cH, allocateDrawValue as cI, clientCompatibilityAttributes as cJ, clientCompatibilityMiddleware as cK, clientUpgradeRequired as cL, isStreamableJobStore as cM, parseClientCapabilities as cN, parseClientCompatibility as cO, parseDvmClient as cP, parseProtocolVersion as cQ, requireClientCompatibility as cR, secp256k1Auth as cS, signedRequestInput as cT, type CreditDepositEnqueue as cU, type TopUpCapUnenforcedReason as cV, type X402SettlementIntent as cW, type X402SettlementCursor as cX, type X402SettlementWriteOff as cY, type X402FacilitatorAuth as cZ, type X402BatchSettlementConfig as c_, type RequestIdClaim as ca, type RequestIdClaimResult as cb, type AppendOutgoingOptions as cc, type PaymentCreditDelta as cd, type VerifyAndCreditResult as ce, type JobCounters as cf, CLIENT_COMPATIBILITY_HEADERS as cg, type ClientCompatibility as ch, type ClientCompatibilityEnv as ci, type ClientCompatibilityGate as cj, type ClientCompatibilityRequirement as ck, type ClientSemVer as cl, type CreditFundingBasis as cm, type CreditInvoiceStatus as cn, CreditLedger as co, CreditLedgerError as cp, type CreditLedgerErrorCode as cq, type CreditLedgerErrorDetails as cr, type CreditLedgerPool as cs, type CreditStatus as ct, DRAIN_DELIVERY_RESERVE_SATS as cu, DVM_PROTOCOL_VERSION as cv, type DrainConflictReason as cw, type DrawRailValue as cx, type DrawStatus as cy, PostgresX402ChannelStorage as cz, type CanonicalEnvelope as d, type X402SettlementReconciliationReason as d0, type CreditDrawReleaseEnqueue as d1, type CreateSignedRequestVerifierOpts as e, type CreditConfig as f, type CreditView as g, DEFAULT_CREDIT_MAX as h, DEFAULT_CREDIT_MIN as i, DEFAULT_CREDIT_TTL_SECONDS as j, type DVMRouteContext as k, type InputType as l, InvalidCurrencyError as m, type JobStatus as n, type JobStore as o, type PaymentMethod as p, type PriceValue as q, type ProgressContent as r, type PromptOpts as s, type QuoteContext as t, type QuoteResult as u, type ResponseContent as v, type SDKPaymentRequestOpts as w, SIGNED_REQUEST_AUTH_ID as x, SIGNED_REQUEST_STATEMENT_VERSION as y, type SignedRequestAudience as z };