@dvmkit/sdk 0.1.5-rc.8 → 0.2.0-rc.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -0
- package/dist/{chunk-BIP6G74V.js → chunk-2ATUAUAO.js} +8 -8
- package/dist/{chunk-27V2ILSR.js → chunk-4A2RAKCW.js} +2 -2
- package/dist/{chunk-EVBK675R.js → chunk-6GRIKOFB.js} +28 -23
- package/dist/{chunk-CEOAHV2I.js → chunk-FDKRXOZO.js} +0 -5
- package/dist/{chunk-L4OYF4DQ.js → chunk-FT6HTUM4.js} +1 -1
- package/dist/{chunk-BTZY7VPH.js → chunk-GAIPXGM3.js} +1 -1
- package/dist/{chunk-U6M3ATSG.js → chunk-JDT5LCJC.js} +40 -6
- package/dist/{chunk-FROTD5XQ.js → chunk-JLXYOV4Y.js} +1 -2
- package/dist/{chunk-M7LHFJ5K.js → chunk-KMZXTBLA.js} +2 -2
- package/dist/{chunk-6BQM7TOW.js → chunk-L67WTZX2.js} +3 -7
- package/dist/{chunk-CGKZDODG.js → chunk-MG67KXU7.js} +0 -5
- package/dist/{chunk-JZWELPFH.js → chunk-MRAGS5VP.js} +1 -1
- package/dist/{chunk-2UUXIIOC.js → chunk-O2X2CCKH.js} +3 -3
- package/dist/{chunk-TQWGQCNV.js → chunk-OMIQMMME.js} +3 -3
- package/dist/{chunk-UB5FZ43T.js → chunk-PCUQZDZA.js} +475 -366
- package/dist/{chunk-KVEHHC7W.js → chunk-PHHAYRQV.js} +7 -9
- package/dist/{chunk-SSSZUVWM.js → chunk-QP53RWAD.js} +88 -38
- package/dist/{chunk-DMNLFNTW.js → chunk-QT4ONTST.js} +1 -1
- package/dist/{chunk-RW5LP57K.js → chunk-SDK6KDJN.js} +0 -1
- package/dist/{chunk-MLRCSJYX.js → chunk-V7EVFLAK.js} +87 -90
- package/dist/{chunk-E4EVGPDX.js → chunk-XQXJKJ3P.js} +0 -2
- package/dist/{credit-ledger-2DFQHNLB.js → credit-ledger-5ZEJRI46.js} +1 -1
- package/dist/{credit-menu-s5HmGCqx.d.ts → credit-menu-D4Gcdgc4.d.ts} +488 -644
- package/dist/{fx-D860pZvP.d.ts → fx-B0SLBe5x.d.ts} +38 -82
- package/dist/index.d.ts +11 -14
- package/dist/index.js +2 -2
- package/dist/internal/caller.d.ts +618 -1525
- package/dist/internal/caller.js +28 -60
- package/dist/internal/server.d.ts +36 -61
- package/dist/internal/server.js +11 -11
- package/dist/{job-store-BUGqvCfL.d.ts → job-store-B2uZvga4.d.ts} +70 -59
- package/dist/{lightning-backend-BozcevPZ.d.ts → lightning-backend-CQBnQgsT.d.ts} +19 -27
- package/dist/{memory-credit-ledger-MNUOTQO5.js → memory-credit-ledger-ZOH6C3N4.js} +2 -2
- package/dist/{mpp-setup-4FJD6ZHV.js → mpp-setup-IOJBF7DB.js} +1 -1
- package/dist/{payout-reporter-RG6XNGPI.js → payout-reporter-5PIRYFVQ.js} +1 -1
- package/dist/{postgres-consumed-credential-store-VHBT4KEA.js → postgres-consumed-credential-store-ISRHBMOU.js} +1 -1
- package/dist/{postgres-job-store-3RAXMNSY.js → postgres-job-store-OGQ6IT4U.js} +1 -1
- package/dist/{postgres-kv-store-JFBDP5IP.js → postgres-kv-store-D5E2EZ24.js} +1 -1
- package/dist/{postgres-replay-store-UJXRT6VO.js → postgres-replay-store-IZFLTTAC.js} +1 -1
- package/dist/{pricing-4CEB34RM.js → pricing-MU5GNUJZ.js} +1 -1
- package/dist/{processed-payment-store-HAA4SFNK.js → processed-payment-store-FIDI3RNH.js} +1 -1
- package/dist/{revenue-reporter-ASZ7SHHH.js → revenue-reporter-NNCNRY4C.js} +1 -1
- package/dist/server/index.d.ts +53 -59
- package/dist/server/index.js +38 -37
- package/dist/{ssrf-DbFkpDv0.d.ts → ssrf-dMooihtY.d.ts} +1 -2
- package/dist/{step-cache-5dljDqrQ.d.ts → step-cache-CXg7ziML.d.ts} +389 -551
- package/dist/{tempo-charge-store-RIFTALZK.js → tempo-charge-store-76TDAF34.js} +1 -1
- package/dist/{tempo-lifecycle-DFIXQ54Q.js → tempo-lifecycle-DXM7QXJQ.js} +3 -3
- package/dist/{tempo-wallet-4QKSV65O.js → tempo-wallet-O67H5M4N.js} +2 -2
- package/dist/testing/index.d.ts +5 -15
- package/dist/testing/index.js +4 -11
- package/dist/{usd-DoRuAckA.d.ts → usd-BNDg1715.d.ts} +14 -16
- package/dist/{wallet-CJC8lwxx.d.ts → wallet-Dwjs5n_M.d.ts} +1 -1
- package/dist/{x402-5H27DCBE.js → x402-7S2EFINY.js} +2 -2
- package/package.json +2 -1
|
@@ -25,11 +25,8 @@ declare class InvalidCurrencyError extends Error {
|
|
|
25
25
|
constructor(raw: unknown);
|
|
26
26
|
}
|
|
27
27
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* "usd" (the bundled fx fetcher is USD/BTC); EUR/GBP/JPY land when a
|
|
31
|
-
* multi-currency fx fetcher does. The message names the supported set so
|
|
32
|
-
* operators see exactly what's missing.
|
|
28
|
+
* A valid currency code that the configured FX snapshot cannot price.
|
|
29
|
+
* The error message names the supported set so the builder can correct it.
|
|
33
30
|
*/
|
|
34
31
|
declare class UnsupportedCurrencyError extends Error {
|
|
35
32
|
readonly raw: string;
|
|
@@ -128,7 +125,7 @@ interface X402Config {
|
|
|
128
125
|
* When true (default), the SDK includes x402 `PaymentRequirements` on the
|
|
129
126
|
* 402 response body alongside MPP's `WWW-Authenticate: Payment` header so
|
|
130
127
|
* x402-speaking agents (Coinbase reference client, thirdweb-ecosystem)
|
|
131
|
-
* can pay. Flip to `false` for MPP-only DVMs
|
|
128
|
+
* can pay. Flip to `false` for MPP-only DVMs.
|
|
132
129
|
*/
|
|
133
130
|
dualServe?: boolean;
|
|
134
131
|
/** Human-readable description carried on the `PaymentRequirements`. */
|
|
@@ -156,7 +153,7 @@ interface X402Receipt {
|
|
|
156
153
|
verified: boolean;
|
|
157
154
|
amountMsats: number;
|
|
158
155
|
/**
|
|
159
|
-
* Native USDC amount in 6-decimal microunits
|
|
156
|
+
* Native USDC amount in 6-decimal microunits. Captured from the
|
|
160
157
|
* payment payload's `value` field so the platform revenue ledger records
|
|
161
158
|
* the rail-native value without re-deriving it from `amountMsats` + a
|
|
162
159
|
* fresh BTC rate (lossy and racy across the boundary).
|
|
@@ -166,7 +163,7 @@ interface X402Receipt {
|
|
|
166
163
|
txHash?: string;
|
|
167
164
|
/**
|
|
168
165
|
* Base64-encoded `SettleResponse` for the `X-PAYMENT-RESPONSE` header the
|
|
169
|
-
* server attaches to the 2xx response per x402 spec
|
|
166
|
+
* server attaches to the 2xx response per x402 spec.
|
|
170
167
|
*/
|
|
171
168
|
settleResponseHeader?: string;
|
|
172
169
|
/** When `verified === false`, a short stable code surfacing the reason. */
|
|
@@ -197,13 +194,13 @@ type X402Version = typeof X402_V1_VERSION | typeof X402_VERSION;
|
|
|
197
194
|
/**
|
|
198
195
|
* Chain a caller's x402 wallet reads when it was connected without an explicit
|
|
199
196
|
* `--network`. Single source of truth for the default: the wallet loader, the
|
|
200
|
-
* connect output and the asset resolver all read it from here
|
|
197
|
+
* connect output and the asset resolver all read it from here.
|
|
201
198
|
*/
|
|
202
199
|
declare const X402_DEFAULT_NETWORK = "eip155:8453";
|
|
203
200
|
/**
|
|
204
201
|
* Scheme name of the per-call rail — one signed authorization settling one
|
|
205
202
|
* resource. Shared with the credit funding menu's `x402.schemes` block, which
|
|
206
|
-
* has to name the same string the requirement carries
|
|
203
|
+
* has to name the same string the requirement carries.
|
|
207
204
|
*/
|
|
208
205
|
declare const X402_EXACT_SCHEME = "exact";
|
|
209
206
|
/**
|
|
@@ -212,7 +209,7 @@ declare const X402_EXACT_SCHEME = "exact";
|
|
|
212
209
|
* the caller's requirement selection, and the credit menu's `x402.schemes`
|
|
213
210
|
* block all read it from here — the menu advertises exactly what the challenge
|
|
214
211
|
* will carry, so a rename cannot leave one of them advertising a flavour the
|
|
215
|
-
* others no longer speak
|
|
212
|
+
* others no longer speak.
|
|
216
213
|
*/
|
|
217
214
|
declare const X402_BATCH_SETTLEMENT_SCHEME = "batch-settlement";
|
|
218
215
|
|
|
@@ -410,29 +407,24 @@ declare function decodePaymentRequiredHeader(header: string): PaymentRequiredV2;
|
|
|
410
407
|
declare function exactEvmAuthorization(payload: PaymentPayload): ExactEvmPayloadAuthorization;
|
|
411
408
|
/**
|
|
412
409
|
* Encode a `SettleResponse` for the `X-PAYMENT-RESPONSE` header that the
|
|
413
|
-
* server emits on a 2xx after a successful settlement (
|
|
410
|
+
* server emits on a 2xx after a successful settlement (per the
|
|
414
411
|
* x402 spec).
|
|
415
412
|
*/
|
|
416
413
|
declare function encodeSettleResponseHeader(response: SettleResponse): string;
|
|
417
414
|
|
|
418
|
-
/** Identifies which side of the conversation sent a message. */
|
|
419
415
|
type MessageFrom = "requester" | "provider";
|
|
420
416
|
/** Single mppx-shaped MPP challenge carried in `payment-request` messages. */
|
|
421
417
|
type MppxChallenge = Challenge.Challenge;
|
|
422
418
|
/** Structured MPP credential (`{ challenge, payload, source? }`) carried in `payment` messages. */
|
|
423
419
|
type MppxCredential = Credential.Credential;
|
|
424
|
-
/** All supported message types in the conversation protocol. */
|
|
425
420
|
type MessageType = "text" | "prompt" | "response" | "artifact" | "payment-request" | "payment" | "approval" | "cancel" | "complete" | "working" | "progress";
|
|
426
|
-
/** Common fields shared by all message variants. */
|
|
427
421
|
interface MessageBase {
|
|
428
422
|
/** Monotonic sequence number, assigned by provider/server. */
|
|
429
423
|
seq: number;
|
|
430
|
-
/** Which side sent this message. */
|
|
431
424
|
from: MessageFrom;
|
|
432
425
|
/** Unix timestamp (seconds). */
|
|
433
426
|
timestamp: number;
|
|
434
427
|
}
|
|
435
|
-
/** Free-form text message content. */
|
|
436
428
|
interface TextContent {
|
|
437
429
|
text: string;
|
|
438
430
|
}
|
|
@@ -453,15 +445,12 @@ interface ResponseContent {
|
|
|
453
445
|
}
|
|
454
446
|
/** Job output — inline data or a URL reference. */
|
|
455
447
|
interface ArtifactContent {
|
|
456
|
-
/** Human-readable name for the artifact. */
|
|
457
448
|
name?: string;
|
|
458
|
-
/** MIME type of the artifact. */
|
|
459
449
|
mime_type?: string;
|
|
460
450
|
/** Inline data (string or base64 for binary). */
|
|
461
451
|
data?: string;
|
|
462
452
|
/** Encoding of inline data: "utf-8" for text, "base64" for binary. */
|
|
463
453
|
encoding?: "utf-8" | "base64";
|
|
464
|
-
/** URL to fetch the artifact from. */
|
|
465
454
|
url?: string;
|
|
466
455
|
/** Size in bytes (for URL-referenced artifacts). */
|
|
467
456
|
size_bytes?: number;
|
|
@@ -487,7 +476,7 @@ interface PaymentRequestContent {
|
|
|
487
476
|
mints?: string[];
|
|
488
477
|
min_locktime_seconds?: number;
|
|
489
478
|
/**
|
|
490
|
-
* NUT-11 P2PK lock pubkey the requester should lock cashu outputs to
|
|
479
|
+
* NUT-11 P2PK lock pubkey the requester should lock cashu outputs to.
|
|
491
480
|
* When absent, the requester falls back to `/v1/info`'s `cashu.lock_pubkeys[0]`.
|
|
492
481
|
*/
|
|
493
482
|
lock_pubkey?: string;
|
|
@@ -506,7 +495,7 @@ interface PaymentRequestContent {
|
|
|
506
495
|
* caller MUST use when signing `TransferWithAuthorization` for this
|
|
507
496
|
* payment-request. Binds the credential to this job so a payload signed
|
|
508
497
|
* for job A cannot satisfy job B within the pre-settlement window
|
|
509
|
-
*
|
|
498
|
+
* Optional on the wire for backwards-compat — pre-fix DVMs
|
|
510
499
|
* never set it; verify-side gate keys on `pendingX402Nonce !== undefined`.
|
|
511
500
|
*/
|
|
512
501
|
nonce?: string;
|
|
@@ -527,7 +516,7 @@ interface PaymentContent {
|
|
|
527
516
|
mint?: string;
|
|
528
517
|
amount_msats?: number;
|
|
529
518
|
/**
|
|
530
|
-
* UUIDv4 per-call identifier for the agent-wallet path
|
|
519
|
+
* UUIDv4 per-call identifier for the agent-wallet path.
|
|
531
520
|
* Mid-job equivalent of the upfront flow's `X-Cashu-Request-Id` header —
|
|
532
521
|
* threaded into the SDK accumulator's `(dvm_id, request_id)` replay key.
|
|
533
522
|
*/
|
|
@@ -545,7 +534,7 @@ interface PaymentContent {
|
|
|
545
534
|
*/
|
|
546
535
|
tempo_credential?: MppxCredential;
|
|
547
536
|
/**
|
|
548
|
-
* Dev-only: satisfy the ask with no proof at all
|
|
537
|
+
* Dev-only: satisfy the ask with no proof at all. The `/_dev`
|
|
549
538
|
* console has no wallet, so its auto-approve button sends this instead of a
|
|
550
539
|
* rail credential. Admitted only by a `devMode` server, and only on a
|
|
551
540
|
* message that carries none of the proofs above — money on the wire always
|
|
@@ -754,18 +743,9 @@ declare const requireClientCompatibility: ClientCompatibilityGate;
|
|
|
754
743
|
declare function clientUpgradeRequired(c: Context, compatibility: ClientCompatibility, requirement: ClientCompatibilityRequirement): Response;
|
|
755
744
|
|
|
756
745
|
/**
|
|
757
|
-
* Canonical JSON serialisation used for secp256k1+BIP-340 Schnorr request
|
|
758
|
-
* signing in cast (internal-review).
|
|
759
|
-
*
|
|
760
|
-
* Single source of truth for both the cast DVM's verifier (internal-review) and the
|
|
761
|
-
* client signing helper (internal-review). The same function on both sides guarantees
|
|
762
|
-
* that what the client signs is byte-identical to what the server hashes.
|
|
763
|
-
*
|
|
764
746
|
* Algorithm: recursively sort object keys lexicographically (UTF-16 code-unit
|
|
765
747
|
* order — JavaScript's default), then JSON.stringify with no whitespace.
|
|
766
|
-
* Arrays preserve order.
|
|
767
|
-
* `JSON.stringify` formats them. Values of `undefined` or functions are
|
|
768
|
-
* forbidden (we throw rather than silently drop, since both sides must agree).
|
|
748
|
+
* Arrays preserve order.
|
|
769
749
|
*/
|
|
770
750
|
/** Any JSON-serialisable value accepted by `canonicalize`. */
|
|
771
751
|
type JsonValue = string | number | boolean | null | JsonValue[] | {
|
|
@@ -789,21 +769,18 @@ declare function canonicalize(value: JsonValue): string;
|
|
|
789
769
|
*/
|
|
790
770
|
declare function canonicaliseForSigning(value: JsonValue): Uint8Array;
|
|
791
771
|
|
|
792
|
-
/** Terminal outcome a receipt attests. Mirrors the SDK's terminal job statuses. */
|
|
793
772
|
type ReceiptOutcome = "completed" | "failed" | "cancelled";
|
|
794
|
-
/** What the caller paid for the job, as persisted on the job record. */
|
|
795
773
|
interface ReceiptPayment {
|
|
796
774
|
/** Total credited millisats. `0` on free jobs — they still get receipts. */
|
|
797
775
|
msats: number;
|
|
798
776
|
/**
|
|
799
777
|
* Rail of the most recent successful credit; `null` when nothing was paid.
|
|
800
778
|
* `lightning` appears on a draw against a credit the caller funded by
|
|
801
|
-
* invoice
|
|
779
|
+
* invoice — it is a funding rail, never an attached-proof one.
|
|
802
780
|
*/
|
|
803
781
|
rail: "cashu" | "x402" | "tempo" | "lightning" | null;
|
|
804
782
|
/** Rail-native upfront amount (sats / USDC microunits), `null` when absent. */
|
|
805
783
|
native_amount: number | null;
|
|
806
|
-
/** Native asset tag paired with `native_amount`. */
|
|
807
784
|
native_asset: string | null;
|
|
808
785
|
/** Settlement reference: EVM tx hash (x402), mppx challenge id, or the Cashu request id. */
|
|
809
786
|
tx_hash: string | null;
|
|
@@ -811,8 +788,8 @@ interface ReceiptPayment {
|
|
|
811
788
|
mint: string | null;
|
|
812
789
|
}
|
|
813
790
|
/**
|
|
814
|
-
* Credit-draw countersignature block
|
|
815
|
-
*
|
|
791
|
+
* Credit-draw countersignature block. Present on every job whose payment funded
|
|
792
|
+
* or drew the credit
|
|
816
793
|
* ledger — including implicit N=1 per-job payments, which fund and draw a
|
|
817
794
|
* single-use credit in the same request. A caller holding a DVM-signed
|
|
818
795
|
* balance trajectory plus its own caller-signed draw intents can prove
|
|
@@ -820,23 +797,21 @@ interface ReceiptPayment {
|
|
|
820
797
|
* because the countersignature rides the receipt.
|
|
821
798
|
*
|
|
822
799
|
* Absence is signature-compatible: `canonicalize` omits absent keys, so a
|
|
823
|
-
* ledger-less (or free) job's receipt signs identically to a
|
|
800
|
+
* ledger-less (or free) job's receipt signs identically to a legacy
|
|
824
801
|
* receipt.
|
|
825
802
|
*/
|
|
826
803
|
interface ReceiptCredit {
|
|
827
|
-
/** Credit the draw was taken against. */
|
|
828
804
|
credit_id: string;
|
|
829
805
|
/** This draw's identifier — matches the caller-signed draw intent. */
|
|
830
806
|
draw_id: string;
|
|
831
807
|
/** Amount drawn, in the credit's denomination. */
|
|
832
808
|
amount: number;
|
|
833
|
-
/** Credit balance after this draw. */
|
|
834
809
|
balance_after: number;
|
|
835
810
|
/** Per-credit monotonic draw counter. */
|
|
836
811
|
ledger_seq: number;
|
|
837
812
|
}
|
|
838
813
|
/**
|
|
839
|
-
* A DVM-signed proof of what a job did and what it cost
|
|
814
|
+
* A DVM-signed proof of what a job did and what it cost.
|
|
840
815
|
*
|
|
841
816
|
* Signed once at the terminal transition by the per-DVM receipt key, whose
|
|
842
817
|
* authority chains to the builder identity key through the deploy-time
|
|
@@ -845,18 +820,22 @@ interface ReceiptCredit {
|
|
|
845
820
|
* and on every later re-read — the bytes are persisted, not recomputed.
|
|
846
821
|
*/
|
|
847
822
|
interface JobReceipt {
|
|
848
|
-
/** Receipt schema version. Currently always `1`. */
|
|
849
823
|
v: 1;
|
|
850
|
-
/** The job this receipt attests. */
|
|
851
824
|
job_id: string;
|
|
852
825
|
/** Immutable DVM identity bound into the builder attestation. */
|
|
853
826
|
dvm_id: string;
|
|
854
827
|
/** DVM slug, as bound in the builder attestation. */
|
|
855
828
|
dvm: string;
|
|
856
|
-
/** Capability the job dispatched to. */
|
|
857
829
|
capability: string;
|
|
858
|
-
/** Terminal outcome. */
|
|
859
830
|
outcome: ReceiptOutcome;
|
|
831
|
+
/** Signed Unix millisecond lifecycle times; absent on legacy receipts. */
|
|
832
|
+
timing?: {
|
|
833
|
+
accepted_at_ms: number;
|
|
834
|
+
terminal_at_ms: number;
|
|
835
|
+
caller_wait_ms: number;
|
|
836
|
+
};
|
|
837
|
+
/** SDK-derived attribution on failure/cancellation; absent on completion and legacy receipts. */
|
|
838
|
+
ended_by?: "caller" | "provider";
|
|
860
839
|
/** Terminal reason on `failed`/`cancelled` (e.g. `worker_died_mid_job`); `null` on success. */
|
|
861
840
|
reason: string | null;
|
|
862
841
|
/** Per-DVM monotonic terminal counter. Gaps expose receipt suppression. */
|
|
@@ -865,7 +844,6 @@ interface JobReceipt {
|
|
|
865
844
|
issued_at: number;
|
|
866
845
|
/** Caller's x-only pubkey when signed-request auth was used; `null` otherwise. */
|
|
867
846
|
requester_pubkey: string | null;
|
|
868
|
-
/** What the caller paid. */
|
|
869
847
|
paid: ReceiptPayment;
|
|
870
848
|
/**
|
|
871
849
|
* {@link computeResultHash} over the delivered result; `null` when nothing
|
|
@@ -878,7 +856,7 @@ interface JobReceipt {
|
|
|
878
856
|
/** BIP-340 Schnorr signature over the canonical receipt minus `signature` (128 hex chars). */
|
|
879
857
|
signature: string;
|
|
880
858
|
/**
|
|
881
|
-
* Credit-draw countersignature
|
|
859
|
+
* Credit-draw countersignature — present when the job's payment
|
|
882
860
|
* funded/drew the credit ledger. See {@link ReceiptCredit}. `balance_after`
|
|
883
861
|
* reflects the terminal resolution: the recorded draw trajectory on a
|
|
884
862
|
* settled (completed) job, the restored available balance on a released
|
|
@@ -886,12 +864,10 @@ interface JobReceipt {
|
|
|
886
864
|
*/
|
|
887
865
|
credit?: ReceiptCredit;
|
|
888
866
|
}
|
|
889
|
-
/** A receipt before signing — every field but the signature itself. */
|
|
890
867
|
type UnsignedJobReceipt = Omit<JobReceipt, "signature">;
|
|
891
|
-
/** Reclaim lifecycle event a {@link DrainReceipt} attests (internal-review, spec §5). */
|
|
892
868
|
type DrainReceiptEvent = "requested" | "parked" | "picked_up" | "sent" | "released";
|
|
893
869
|
/**
|
|
894
|
-
* A DVM-signed proof of one reclaim event
|
|
870
|
+
* A DVM-signed proof of one reclaim event. One receipt per
|
|
895
871
|
* lifecycle transition — `requested` (the balance debited into the drain
|
|
896
872
|
* liability), `parked` (Cashu notes locked to the caller's refund key,
|
|
897
873
|
* parked for pickup), `picked_up` (the caller collected them), `sent` (a
|
|
@@ -907,15 +883,12 @@ type DrainReceiptEvent = "requested" | "parked" | "picked_up" | "sent" | "releas
|
|
|
907
883
|
* same canonicalisation, so one attestation chain covers both.
|
|
908
884
|
*/
|
|
909
885
|
interface DrainReceipt {
|
|
910
|
-
/** Receipt schema version. Currently always `1`. */
|
|
911
886
|
v: 1;
|
|
912
887
|
/** Discriminator separating this from a `JobReceipt` in mixed stores. */
|
|
913
888
|
kind: "credit_drain";
|
|
914
|
-
/** Credit the drain was taken against. */
|
|
915
889
|
credit_id: string;
|
|
916
890
|
/** This drain's identifier — matches the caller-signed drain request. */
|
|
917
891
|
drain_id: string;
|
|
918
|
-
/** The lifecycle event this receipt attests. */
|
|
919
892
|
event: DrainReceiptEvent;
|
|
920
893
|
/** Payout rail: `cashu` | `x402` | `tempo`. */
|
|
921
894
|
method: string;
|
|
@@ -942,19 +915,16 @@ interface DrainReceipt {
|
|
|
942
915
|
/** BIP-340 Schnorr signature over the canonical receipt minus `signature`. */
|
|
943
916
|
signature: string;
|
|
944
917
|
}
|
|
945
|
-
/** A drain receipt before signing — every field but the signature itself. */
|
|
946
918
|
type UnsignedDrainReceipt = Omit<DrainReceipt, "signature">;
|
|
947
919
|
/**
|
|
948
|
-
* A DVM-signed proof that one payment funded a prepaid credit
|
|
920
|
+
* A DVM-signed proof that one payment funded a prepaid credit.
|
|
949
921
|
* The balance and sequence are the values fixed when the funding committed;
|
|
950
922
|
* retries return this original artifact even when the credit moved later.
|
|
951
923
|
*/
|
|
952
924
|
interface FundingReceipt {
|
|
953
|
-
/** Receipt schema version. Currently always `1`. */
|
|
954
925
|
v: 1;
|
|
955
926
|
/** Discriminator separating funding evidence from job and drain receipts. */
|
|
956
927
|
kind: "credit_funding";
|
|
957
|
-
/** Credit that received the value. */
|
|
958
928
|
credit_id: string;
|
|
959
929
|
/** Caller fund id, or the attached rail payment id for fund-and-draw. */
|
|
960
930
|
fund_id: string;
|
|
@@ -972,12 +942,10 @@ interface FundingReceipt {
|
|
|
972
942
|
dvm_id: string;
|
|
973
943
|
/** DVM slug, as bound in the builder attestation. */
|
|
974
944
|
dvm: string;
|
|
975
|
-
/** x-only secp256k1 pubkey that signed this receipt. */
|
|
976
945
|
receipt_pubkey: string;
|
|
977
946
|
/** BIP-340 Schnorr signature over the canonical receipt minus `signature`. */
|
|
978
947
|
signature: string;
|
|
979
948
|
}
|
|
980
|
-
/** A funding receipt before signing. */
|
|
981
949
|
type UnsignedFundingReceipt = Omit<FundingReceipt, "signature">;
|
|
982
950
|
/**
|
|
983
951
|
* Hash the delivered result so a receipt binds to *what* was returned, not
|
|
@@ -1042,9 +1010,7 @@ declare function isSignedJobReceipt(value: unknown): value is JobReceipt;
|
|
|
1042
1010
|
declare function signDrainReceipt(unsigned: UnsignedDrainReceipt, secretHex: string): DrainReceipt;
|
|
1043
1011
|
/** Sign an unsigned funding receipt using the common receipt canonicalisation. */
|
|
1044
1012
|
declare function signFundingReceipt(unsigned: UnsignedFundingReceipt, secretHex: string): FundingReceipt;
|
|
1045
|
-
/** Structural guard for a funding receipt received over the wire or from disk. */
|
|
1046
1013
|
declare function isFundingReceipt(value: unknown): value is FundingReceipt;
|
|
1047
|
-
/** Verify a funding receipt's inner BIP-340 signature. */
|
|
1048
1014
|
declare function verifyFundingReceipt(receipt: FundingReceipt): boolean;
|
|
1049
1015
|
/**
|
|
1050
1016
|
* Structural guard on a drain receipt from outside this process — off a
|
|
@@ -1061,33 +1027,16 @@ declare function verifyFundingReceipt(receipt: FundingReceipt): boolean;
|
|
|
1061
1027
|
declare function isDrainReceipt(value: unknown): value is DrainReceipt;
|
|
1062
1028
|
/**
|
|
1063
1029
|
* Verify a drain receipt's self-consistency, mirroring {@link verifyReceipt}
|
|
1064
|
-
*
|
|
1030
|
+
* the same provenance caveat applies: check `receipt_pubkey` against the
|
|
1065
1031
|
* DVM's attested `receipt_pubkey` for the outer link.
|
|
1066
1032
|
*/
|
|
1067
1033
|
declare function verifyDrainReceipt(receipt: DrainReceipt): boolean;
|
|
1068
1034
|
|
|
1069
1035
|
/**
|
|
1070
|
-
*
|
|
1071
|
-
*
|
|
1072
|
-
*
|
|
1073
|
-
*
|
|
1074
|
-
* reclaim time: fund 1,151 sats, draw 1.2% of the credit's value, reclaim
|
|
1075
|
-
* 98.8% of 1,151 sats. That obligation is only expressible if each funding
|
|
1076
|
-
* event's `{sats_funded, credited_micro}` pair survives — the ledger's pooled
|
|
1077
|
-
* `credits.msats_remaining` blends every funding into one ratio, which answers
|
|
1078
|
-
* a different question (what share of the credit's rail value does *this draw*
|
|
1079
|
-
* consume) and cannot say what a top-up taken at a different rate is worth.
|
|
1080
|
-
*
|
|
1081
|
-
* Everything here is pure integer arithmetic over that pair, shared by the
|
|
1082
|
-
* Postgres and in-memory ledgers so the two cannot drift — the arrangement
|
|
1083
|
-
* `allocateDrawValue` already holds for the pooled basis.
|
|
1084
|
-
*
|
|
1085
|
-
* Since internal-review these lots are also what a *settling* draw is priced at on
|
|
1086
|
-
* these rails, not only a reclaim: `inKindDrawMsats` turns the depletion a
|
|
1087
|
-
* settle already performs into the draw's booked rail value, so one credit has
|
|
1088
|
-
* one answer to "what were these sats" and the pooled remainder stops being a
|
|
1089
|
-
* second authority: settled draw sats plus reclaim sats must equal the sats
|
|
1090
|
-
* that credit's funding lots received.
|
|
1036
|
+
* Cashu and Lightning credits owe unused sats back at each deposit's funding
|
|
1037
|
+
* rate. Keep the sats/micro basis per funding lot: a pooled ratio loses the
|
|
1038
|
+
* basis of top-ups made at different rates. Settled draws and reclaims share
|
|
1039
|
+
* these lots so their total equals the sats funded.
|
|
1091
1040
|
*/
|
|
1092
1041
|
/**
|
|
1093
1042
|
* The rails whose credits carry a Bitcoin deposit this ledger owes back in
|
|
@@ -1100,9 +1049,7 @@ declare function verifyDrainReceipt(receipt: DrainReceipt): boolean;
|
|
|
1100
1049
|
* {@link FundingMethod} must be a decision here rather than a default.
|
|
1101
1050
|
*/
|
|
1102
1051
|
declare const NON_CHANNEL_BITCOIN_RAILS: readonly ["cashu", "lightning"];
|
|
1103
|
-
/** A rail whose unused credit is a sats deposit the provider owes back. */
|
|
1104
1052
|
type NonChannelBitcoinRail = (typeof NON_CHANNEL_BITCOIN_RAILS)[number];
|
|
1105
|
-
/** True when `rail` funds a credit with sats the provider holds and owes back. */
|
|
1106
1053
|
declare function isNonChannelBitcoinRail(rail: string | null | undefined): rail is NonChannelBitcoinRail;
|
|
1107
1054
|
/**
|
|
1108
1055
|
* One funding event's deposit: the sats that arrived and the credit micro they
|
|
@@ -1110,7 +1057,7 @@ declare function isNonChannelBitcoinRail(rail: string | null | undefined): rail
|
|
|
1110
1057
|
*
|
|
1111
1058
|
* `remainingMicro` is depleted FIFO by settled draws and by reclaims, so the
|
|
1112
1059
|
* sum of a credit's lots tracks `credits.balance_micro` exactly — with one
|
|
1113
|
-
* deliberate exception: an expiry release
|
|
1060
|
+
* deliberate exception: an expiry release zeroes the balance and
|
|
1114
1061
|
* leaves the lots standing, because a revival restores that balance and its
|
|
1115
1062
|
* in-kind basis has to still be there. A released credit is excluded from the
|
|
1116
1063
|
* sweep floor by `BITCOIN_CREDIT_PREDICATE`'s own `balance_micro > 0`, so the
|
|
@@ -1124,24 +1071,19 @@ interface FundingLot {
|
|
|
1124
1071
|
satsFunded: number;
|
|
1125
1072
|
/** Credit micro this funding bought — the lot's denominator, never depleted. */
|
|
1126
1073
|
creditedMicro: number;
|
|
1127
|
-
/** Credit micro of this lot not yet drawn or reclaimed. */
|
|
1128
1074
|
remainingMicro: number;
|
|
1129
1075
|
/** Rail settlement reference, provenance only. */
|
|
1130
1076
|
fundingRef: string | null;
|
|
1131
1077
|
createdAt: number;
|
|
1132
1078
|
}
|
|
1133
|
-
/** One lot's share of a depletion, and what that share is worth in kind. */
|
|
1134
1079
|
interface LotDebit {
|
|
1135
1080
|
lotId: string;
|
|
1136
|
-
/** Credit micro taken out of this lot. */
|
|
1137
1081
|
micro: number;
|
|
1138
|
-
/**
|
|
1082
|
+
/** Decrease in this lot's floored sats obligation after taking the micro debit. */
|
|
1139
1083
|
sats: number;
|
|
1140
1084
|
}
|
|
1141
|
-
/** What a FIFO depletion took, and what it could not cover. */
|
|
1142
1085
|
interface LotDepletion {
|
|
1143
1086
|
debits: LotDebit[];
|
|
1144
|
-
/** In-kind value of everything taken — the reclaim obligation. */
|
|
1145
1087
|
satsOwed: number;
|
|
1146
1088
|
/** Micro the lots could not cover. Non-zero means the credit's lots are short. */
|
|
1147
1089
|
uncoveredMicro: number;
|
|
@@ -1149,32 +1091,15 @@ interface LotDepletion {
|
|
|
1149
1091
|
backedMicro: number;
|
|
1150
1092
|
}
|
|
1151
1093
|
/**
|
|
1152
|
-
*
|
|
1153
|
-
*
|
|
1154
|
-
*
|
|
1155
|
-
*
|
|
1156
|
-
* rate is reclaimed at *that* rate once the earlier deposit is spent. A
|
|
1157
|
-
* fraction of a satoshi cannot be handed back, so the conversion floors and
|
|
1158
|
-
* the dust stays with the provider rather than being rounded into a payout the
|
|
1159
|
-
* deposit does not cover.
|
|
1160
|
-
*
|
|
1161
|
-
* A slice is priced as the **decrement in the lot's own obligation** —
|
|
1162
|
-
* `lotSats(before) - lotSats(after)` — rather than by flooring the slice on
|
|
1163
|
-
* its own. The two agree whenever a lot is taken whole, which is every
|
|
1164
|
-
* ordinary reclaim; they diverge once a lot is drawn down in pieces, and there
|
|
1165
|
-
* the independent floor loses up to a satoshi *per piece*, permanently. That
|
|
1166
|
-
* matters since internal-review, where each settling draw is priced through here: the
|
|
1167
|
-
* slices have to telescope, or a lot spent over many jobs pays out less than
|
|
1168
|
-
* it took in and the residue is exactly the unattributable one this was meant
|
|
1169
|
-
* to remove. It also makes {@link lotOwedSats} exact rather than conservative
|
|
1170
|
-
* — the remaining obligation is precisely what future depletions will pay.
|
|
1171
|
-
*
|
|
1172
|
-
* `lots` must already be in FIFO order ({@link fifoOrder}).
|
|
1094
|
+
* Deplete lots in FIFO order, supplied by fifoOrder. Price each debit as
|
|
1095
|
+
* lotSats(before) - lotSats(after), not the independently floored slice: small
|
|
1096
|
+
* draws then telescope to the full deposit instead of losing up to one sat
|
|
1097
|
+
* per draw. Fractional remaining sats stay with the provider.
|
|
1173
1098
|
*/
|
|
1174
1099
|
declare function depleteLots(lots: FundingLot[], amountMicro: number): LotDepletion;
|
|
1175
1100
|
/**
|
|
1176
1101
|
* What a settling draw's fiat debit was worth in kind, in millisatoshis
|
|
1177
|
-
*
|
|
1102
|
+
* `null` where the lots cannot price it.
|
|
1178
1103
|
*
|
|
1179
1104
|
* This is the single sats authority for a non-channel Bitcoin credit. The
|
|
1180
1105
|
* settle already depletes the lots the draw consumed, so the figure costs no
|
|
@@ -1196,25 +1121,9 @@ declare function inKindDrawMsats(depletion: LotDepletion, amountMicro: number):
|
|
|
1196
1121
|
*/
|
|
1197
1122
|
declare function lotOwedSats(lots: FundingLot[]): number;
|
|
1198
1123
|
/**
|
|
1199
|
-
*
|
|
1200
|
-
*
|
|
1201
|
-
*
|
|
1202
|
-
* Delivering a refund costs money whichever way it is fulfilled: an
|
|
1203
|
-
* accumulator swap pays the mint's per-input fee, and a just-in-time mint pays
|
|
1204
|
-
* the mint's quote plus whatever the Lightning hop routes for. internal-review puts
|
|
1205
|
-
* that cost on the caller — but charging *actual* fees would mean re-publishing
|
|
1206
|
-
* a smaller figure after the reclaim was already promised, and internal-review fixed
|
|
1207
|
-
* `owed_sats` at request time precisely so it cannot move between the promise
|
|
1208
|
-
* and the payout. A flat reserve keeps both: the caller is quoted one final
|
|
1209
|
-
* number, net, and the provider spends the reserve on delivery.
|
|
1210
|
-
*
|
|
1211
|
-
* It is deliberately a constant rather than a policy knob. The figure only has
|
|
1212
|
-
* to cover a small mint fee and one Lightning hop — the live hub's last hop
|
|
1213
|
-
* measured 1.1 sats on a 2,000-sat payment (internal-review) — so there is headroom
|
|
1214
|
-
* without a number anyone has to tune, and a knob nobody sets is a knob that
|
|
1215
|
-
* drifts. What the reserve does not cover on some future expensive route is
|
|
1216
|
-
* absorbed, and what it over-covers stays with the provider as dust, the same
|
|
1217
|
-
* rule the per-lot flooring already follows.
|
|
1124
|
+
* Refund delivery uses a fixed eight-sat reserve so owed_sats cannot shrink
|
|
1125
|
+
* after it is promised. Extra delivery cost is absorbed by the provider;
|
|
1126
|
+
* unused reserve stays with the provider, like fractional-sat dust.
|
|
1218
1127
|
*/
|
|
1219
1128
|
declare const DRAIN_DELIVERY_RESERVE_SATS = 8;
|
|
1220
1129
|
/**
|
|
@@ -1237,16 +1146,9 @@ declare function netOwedSats(grossSats: number): number;
|
|
|
1237
1146
|
*/
|
|
1238
1147
|
declare function fifoOrder(left: FundingLot, right: FundingLot): number;
|
|
1239
1148
|
/**
|
|
1240
|
-
*
|
|
1241
|
-
*
|
|
1242
|
-
*
|
|
1243
|
-
* Both failure modes are real and neither is the caller's fault: a credit's
|
|
1244
|
-
* lots can be short (a coverage hole the boot backfill is meant to close), and
|
|
1245
|
-
* a credit funded before internal-review recorded a rail basis at all has lots whose
|
|
1246
|
-
* `satsFunded` is 0 — pricing *that* in kind would answer "we owe you nothing"
|
|
1247
|
-
* for a deposit we plainly hold. Mixed coverage is treated as unbacked too:
|
|
1248
|
-
* blending a lot rate with a live rate produces a figure neither basis
|
|
1249
|
-
* supports.
|
|
1149
|
+
* Missing lot coverage or a zero legacy sats basis requires pooled pricing.
|
|
1150
|
+
* Mixed backed/unbacked lots also fall back: combining lot and live rates
|
|
1151
|
+
* would claim a value neither basis supports.
|
|
1250
1152
|
*/
|
|
1251
1153
|
declare function isInKindDepletion(depletion: LotDepletion, amountMicro: number): boolean;
|
|
1252
1154
|
|
|
@@ -1353,7 +1255,7 @@ interface PayoutTransport {
|
|
|
1353
1255
|
/**
|
|
1354
1256
|
* A money-path hook whose report must commit with the fact it describes.
|
|
1355
1257
|
* `enqueue` runs inside the caller's transaction, and a throw rolls the fact
|
|
1356
|
-
* back with it — the drain report's own discipline
|
|
1258
|
+
* back with it — the drain report's own discipline: a call the
|
|
1357
1259
|
* caller has to repeat costs a round trip, where a landed movement with no
|
|
1358
1260
|
* row understates paid-out forever. `committed` runs once that transaction
|
|
1359
1261
|
* has committed, for the delivery and the snapshot that must not read
|
|
@@ -1396,7 +1298,7 @@ interface X402TrackedChannel {
|
|
|
1396
1298
|
chargedCumulativeAmount: string;
|
|
1397
1299
|
totalClaimed: string;
|
|
1398
1300
|
}
|
|
1399
|
-
/** A refund settlement wedged between chain and ledger
|
|
1301
|
+
/** A refund settlement wedged between chain and ledger, for the wedge list. */
|
|
1400
1302
|
interface X402WedgedRefund {
|
|
1401
1303
|
settlementId: string;
|
|
1402
1304
|
/** Epoch ms the settlement was first prepared. */
|
|
@@ -1585,7 +1487,7 @@ declare class PayoutReporter implements PayoutTransport {
|
|
|
1585
1487
|
/** The hook `reconcile-tempo-drain` runs inside its transaction: the booking and its payout commit together. */
|
|
1586
1488
|
tempoRepairHook(): TransactionalPayoutHook<TempoCloseReconciled>;
|
|
1587
1489
|
/**
|
|
1588
|
-
* The operator repaired a wedged cooperative close
|
|
1490
|
+
* The operator repaired a wedged cooperative close. The close's
|
|
1589
1491
|
* payee side landed on chain when the close did; if the live hook reported
|
|
1590
1492
|
* it, this upgrades that row to `repair`, otherwise it is the row. The
|
|
1591
1493
|
* figure is the receipt's payee total for the channel.
|
|
@@ -1602,7 +1504,7 @@ declare class PayoutReporter implements PayoutTransport {
|
|
|
1602
1504
|
* every settle closes it. The claim delta is read off storage rather than
|
|
1603
1505
|
* off upstream's result, which carries only a voucher count; under the
|
|
1604
1506
|
* fleet lock the before/after read is consistent. A channel the claim
|
|
1605
|
-
* removed on its way through — a refund's claim-then-delete
|
|
1507
|
+
* removed on its way through — a refund's claim-then-delete —
|
|
1606
1508
|
* moved whatever it still owed before it went, and that value reaches
|
|
1607
1509
|
* `pay_to` in this batch too, so it counts at its pre-claim figure.
|
|
1608
1510
|
*/
|
|
@@ -1627,7 +1529,7 @@ declare class PayoutReporter implements PayoutTransport {
|
|
|
1627
1529
|
/**
|
|
1628
1530
|
* Tempo: each active channel's spent-but-unsettled balance — earned, not
|
|
1629
1531
|
* yet paid to the recipient — and the cooperative closes wedged between
|
|
1630
|
-
* chain and ledger
|
|
1532
|
+
* chain and ledger, aged past the same floor the repair queue
|
|
1631
1533
|
* uses so an in-flight close is not reported as stuck.
|
|
1632
1534
|
*/
|
|
1633
1535
|
snapshotTempo(): Promise<void>;
|
|
@@ -1636,14 +1538,6 @@ declare class PayoutReporter implements PayoutTransport {
|
|
|
1636
1538
|
/**
|
|
1637
1539
|
* JSON wire shape POSTed to the platform's `/_internal/job-revenue` endpoint
|
|
1638
1540
|
* and stored in `pending_dvm_reports.payload` for durable retry.
|
|
1639
|
-
*
|
|
1640
|
-
* The platform-side consumer is `OnJobCompleted`, implemented by
|
|
1641
|
-
* `createRevenueCallback`. Keep the two shapes in sync: the SDK and platform
|
|
1642
|
-
* deploy in lockstep, and any
|
|
1643
|
-
* backwards-incompatible field change requires a coordinated release. No `version`
|
|
1644
|
-
* field is included pre-launch because there are no external container-runtime
|
|
1645
|
-
* consumers yet; add one once the first third-party builder ships a container-runtime
|
|
1646
|
-
* DVM (trigger condition: external builder onboarded via `dvmctl deploy --container`).
|
|
1647
1541
|
*/
|
|
1648
1542
|
interface RevenueReportPayload {
|
|
1649
1543
|
/** Required. Platform DVM record ID (`dvms.id`). Identifies which DVM earned the revenue. */
|
|
@@ -1674,8 +1568,8 @@ interface RevenueReportPayload {
|
|
|
1674
1568
|
*/
|
|
1675
1569
|
paymentTxHash?: string;
|
|
1676
1570
|
/**
|
|
1677
|
-
*
|
|
1678
|
-
*
|
|
1571
|
+
* Rail-native payment amount in atomic units: USDC microunits for `tempo` and
|
|
1572
|
+
* `x402`, USD cents for `stripe`. Omitted for `cashu` (platform derives
|
|
1679
1573
|
* `paidMsats / 1000`). Must be set together with `nativeAsset`.
|
|
1680
1574
|
*/
|
|
1681
1575
|
nativeAmount?: number;
|
|
@@ -1687,14 +1581,14 @@ interface RevenueReportPayload {
|
|
|
1687
1581
|
nativeAsset?: string;
|
|
1688
1582
|
/**
|
|
1689
1583
|
* Optional. Cashu flow discriminator. Set to `"p2pk_accumulator"` when the cashu
|
|
1690
|
-
* accumulator path
|
|
1584
|
+
* accumulator path satisfied the job; omitted for legacy cashu. Written into
|
|
1691
1585
|
* `revenue_events.metadata.cashu_flow` by the platform so ops can split per-call cashu
|
|
1692
1586
|
* rows by source.
|
|
1693
1587
|
*/
|
|
1694
1588
|
cashuFlow?: string;
|
|
1695
1589
|
/**
|
|
1696
1590
|
* Optional. What the job cost the **builder** to serve, as declared by the
|
|
1697
|
-
* handler through `ctx.cost()`
|
|
1591
|
+
* handler through `ctx.cost()` — the other half of the
|
|
1698
1592
|
* margin the dashboard states. `amountMicro` is 1e-6 of `currency`, which
|
|
1699
1593
|
* is the currency the builder incurred the cost in and need not be the
|
|
1700
1594
|
* credit's.
|
|
@@ -1715,7 +1609,7 @@ interface RevenueReportPayload {
|
|
|
1715
1609
|
currency: string;
|
|
1716
1610
|
};
|
|
1717
1611
|
/**
|
|
1718
|
-
* Optional. Credit this job's payment drew against
|
|
1612
|
+
* Optional. Credit this job's payment drew against. Present on
|
|
1719
1613
|
* every job a ledger-backed payment satisfied; its presence is what tells
|
|
1720
1614
|
* the platform the row is a **draw-keyed** revenue event rather than a
|
|
1721
1615
|
* pre-credits per-call one.
|
|
@@ -1738,14 +1632,27 @@ interface RevenueReportPayload {
|
|
|
1738
1632
|
/**
|
|
1739
1633
|
* Optional. Revenue class when this row is not ordinary service revenue.
|
|
1740
1634
|
* `short_pay_forfeit` marks money kept from an underpayment that bought no
|
|
1741
|
-
* job
|
|
1635
|
+
* job so analytics can exclude it.
|
|
1742
1636
|
*/
|
|
1743
1637
|
kind?: string;
|
|
1744
1638
|
}
|
|
1639
|
+
/** Privacy-preserving terminal evidence; contains no caller or payment references. */
|
|
1640
|
+
interface JobTerminalReportPayload {
|
|
1641
|
+
dvmId: string;
|
|
1642
|
+
jobId: string;
|
|
1643
|
+
capability: string;
|
|
1644
|
+
outcome: "completed" | "failed" | "cancelled";
|
|
1645
|
+
endedBy: "caller" | "provider" | null;
|
|
1646
|
+
paid: boolean;
|
|
1647
|
+
acceptedAtMs: number;
|
|
1648
|
+
terminalAtMs: number;
|
|
1649
|
+
callerWaitMs: number;
|
|
1650
|
+
receiptSeq: number | null;
|
|
1651
|
+
}
|
|
1745
1652
|
/**
|
|
1746
1653
|
* JSON wire shape POSTed to the platform's `/_internal/job-cost` endpoint
|
|
1747
1654
|
* when a terminal job incurred a declared builder cost but produced no
|
|
1748
|
-
* revenue report
|
|
1655
|
+
* revenue report.
|
|
1749
1656
|
*
|
|
1750
1657
|
* Unlike {@link RevenueReportPayload}, this event has no payment rail or
|
|
1751
1658
|
* revenue amount: a failed, cancelled, or free job is not a sale. The
|
|
@@ -1781,8 +1688,8 @@ interface JobCostReportPayload {
|
|
|
1781
1688
|
}
|
|
1782
1689
|
/**
|
|
1783
1690
|
* JSON wire shape POSTed to the platform's `/_internal/credit-deposit`
|
|
1784
|
-
* endpoint
|
|
1785
|
-
* drawn — reported separately and never summed into revenue (
|
|
1691
|
+
* endpoint. A funding event is a **deposit** — a liability until
|
|
1692
|
+
* drawn — reported separately and never summed into revenue (the deposit-accounting rule).
|
|
1786
1693
|
*
|
|
1787
1694
|
* Idempotent on `(dvmId, creditId, fundingId)`, so the shared retry loop can
|
|
1788
1695
|
* redeliver freely.
|
|
@@ -1790,13 +1697,12 @@ interface JobCostReportPayload {
|
|
|
1790
1697
|
interface CreditDepositPayload {
|
|
1791
1698
|
/** Required. Platform DVM record ID (`dvms.id`); must match the bearer token's DVM. */
|
|
1792
1699
|
dvmId: string;
|
|
1793
|
-
/** Required. Credit the funding landed on. */
|
|
1794
1700
|
creditId: string;
|
|
1795
1701
|
/** Required. Canonical owner of the funded credit. */
|
|
1796
1702
|
callerPubkey: string;
|
|
1797
1703
|
/** Required. The rail's settlement reference — the deposit's idempotency key. */
|
|
1798
1704
|
fundingId: string;
|
|
1799
|
-
/**
|
|
1705
|
+
/** Payment rail (`"cashu"`, `"tempo"`, `"x402"`). */
|
|
1800
1706
|
rail: string;
|
|
1801
1707
|
/** Required. Rail value received, in millisatoshis. */
|
|
1802
1708
|
paidMsats: number;
|
|
@@ -1819,7 +1725,7 @@ interface CreditDepositPayload {
|
|
|
1819
1725
|
/** Required. Current credit expiry after this funding committed (epoch ms). */
|
|
1820
1726
|
expiryMs: number;
|
|
1821
1727
|
/**
|
|
1822
|
-
* Tempo session funding only
|
|
1728
|
+
* Tempo session funding only: the TIP-1034 channel this deposit
|
|
1823
1729
|
* arrived on, registered so the platform's close observer can route a
|
|
1824
1730
|
* `CloseRequested` event back to the DVM that owns the channel.
|
|
1825
1731
|
*
|
|
@@ -1841,14 +1747,14 @@ interface CreditDepositPayload {
|
|
|
1841
1747
|
payee?: string;
|
|
1842
1748
|
};
|
|
1843
1749
|
/**
|
|
1844
|
-
* Tempo session funding only
|
|
1750
|
+
* Tempo session funding only: which channel this deposit's voucher
|
|
1845
1751
|
* was accepted on, emitted **whenever the funding was session-based** —
|
|
1846
1752
|
* independently of whether {@link CreditDepositPayload.tempoChannel} could be
|
|
1847
1753
|
* read. That independence is the entire point: `rail: "tempo"` covers both
|
|
1848
1754
|
* `tempo/session` and the `tempo/charge` one-shot, and a charge legitimately
|
|
1849
1755
|
* carries no channel at all, so without this the platform cannot tell a
|
|
1850
1756
|
* routine charge deposit from a session whose chain binding was lost — the
|
|
1851
|
-
*
|
|
1757
|
+
* shape, where the close observer silently never watches the escrow.
|
|
1852
1758
|
*
|
|
1853
1759
|
* Carries only the channel id, not the chain binding: a DVM that could read
|
|
1854
1760
|
* the binding sends `tempoChannel` too, and one that could not still names
|
|
@@ -1859,7 +1765,7 @@ interface CreditDepositPayload {
|
|
|
1859
1765
|
channelId: string;
|
|
1860
1766
|
};
|
|
1861
1767
|
/**
|
|
1862
|
-
* Set by the blocked-invoice repair
|
|
1768
|
+
* Set by the blocked-invoice repair: this deposit is a paid
|
|
1863
1769
|
* Lightning invoice the builder's agent reconciled onto a credit. The money
|
|
1864
1770
|
* landed in the receive wallet at payment time and this deposit is the one
|
|
1865
1771
|
* row it gets, so the settlements table types it `repair` off this flag
|
|
@@ -1869,7 +1775,7 @@ interface CreditDepositPayload {
|
|
|
1869
1775
|
}
|
|
1870
1776
|
/**
|
|
1871
1777
|
* JSON wire shape POSTed to the platform's `/_internal/credit-draw-release`
|
|
1872
|
-
* endpoint
|
|
1778
|
+
* endpoint. A released hold leaves the credit balance intact, but
|
|
1873
1779
|
* marks that slice of the outstanding liability as failure churn rather than
|
|
1874
1780
|
* untouched prefunding.
|
|
1875
1781
|
*
|
|
@@ -1879,7 +1785,6 @@ interface CreditDepositPayload {
|
|
|
1879
1785
|
interface CreditDrawReleasePayload {
|
|
1880
1786
|
/** Required. Platform DVM record ID (`dvms.id`); must match the bearer token's DVM. */
|
|
1881
1787
|
dvmId: string;
|
|
1882
|
-
/** Required. Credit whose hold was released. */
|
|
1883
1788
|
creditId: string;
|
|
1884
1789
|
/** Required. Released draw; the platform idempotency key with DVM and credit. */
|
|
1885
1790
|
drawId: string;
|
|
@@ -1892,11 +1797,10 @@ interface CreditDrawReleasePayload {
|
|
|
1892
1797
|
/** Required. When the hold reached `released` (epoch ms). */
|
|
1893
1798
|
releasedAt: number;
|
|
1894
1799
|
}
|
|
1895
|
-
/** Repair verbs that can finish a caller-facing credit reclaim. */
|
|
1896
1800
|
type CreditDrainRepairKind = "x402_settlement_reconciled" | "tempo_close_reconciled";
|
|
1897
1801
|
/**
|
|
1898
1802
|
* JSON wire shape POSTed to the platform's `/_internal/credit-drain`
|
|
1899
|
-
* endpoint
|
|
1803
|
+
* endpoint. A drain is a **reclaim**: deposited money paid back to
|
|
1900
1804
|
* the caller, which extinguishes the liability the funding created. Reported
|
|
1901
1805
|
* so outstanding liability nets out to `deposited − drawn − drained`; never
|
|
1902
1806
|
* summed into revenue, and never a revenue row — no job was sold.
|
|
@@ -1916,19 +1820,18 @@ type CreditDrainRepairKind = "x402_settlement_reconciled" | "tempo_close_reconci
|
|
|
1916
1820
|
interface CreditDrainPayload {
|
|
1917
1821
|
/** Required. Platform DVM record ID (`dvms.id`); must match the bearer token's DVM. */
|
|
1918
1822
|
dvmId: string;
|
|
1919
|
-
/** Required. Credit the reclaim came off. */
|
|
1920
1823
|
creditId: string;
|
|
1921
1824
|
/** Required. Canonical owner of the reclaimed credit. */
|
|
1922
1825
|
callerPubkey: string;
|
|
1923
1826
|
/** Required. The drain's own idempotency key. */
|
|
1924
1827
|
drainId: string;
|
|
1925
|
-
/**
|
|
1828
|
+
/** Payout rail (`"cashu"`, `"x402"`, `"tempo"`). */
|
|
1926
1829
|
method: string;
|
|
1927
1830
|
/** Required. Fiat micro reclaimed — the liability this drain extinguishes. */
|
|
1928
1831
|
amountMicro: number;
|
|
1929
1832
|
/** Required. Currency `amountMicro` is 1e-6 of. */
|
|
1930
1833
|
creditCurrency: string;
|
|
1931
|
-
/**
|
|
1834
|
+
/** Terminal state: `"picked_up"` for cashu, `"sent"` for other rails. */
|
|
1932
1835
|
status: string;
|
|
1933
1836
|
/** Required. When the money left (epoch ms). */
|
|
1934
1837
|
drainedAt: number;
|
|
@@ -1957,7 +1860,7 @@ type CreditDepositEnqueue = (tx: RevenueReporterQuerier, payload: CreditDepositP
|
|
|
1957
1860
|
type CreditDrawReleaseEnqueue = (tx: RevenueReporterQuerier, payload: CreditDrawReleasePayload) => Promise<void>;
|
|
1958
1861
|
/**
|
|
1959
1862
|
* Transactional drain-outbox seam threaded through each terminal drain
|
|
1960
|
-
* transition
|
|
1863
|
+
* transition.
|
|
1961
1864
|
*
|
|
1962
1865
|
* Implemented by {@link RevenueReporter.enqueueCreditDrain}; callers must await
|
|
1963
1866
|
* it before committing the status CAS that moved the money.
|
|
@@ -1965,7 +1868,7 @@ type CreditDrawReleaseEnqueue = (tx: RevenueReporterQuerier, payload: CreditDraw
|
|
|
1965
1868
|
type CreditDrainEnqueue = (tx: RevenueReporterQuerier, payload: CreditDrainPayload) => Promise<void>;
|
|
1966
1869
|
/**
|
|
1967
1870
|
* JSON wire shape POSTed to the platform's `/_internal/credit-expiry-release`
|
|
1968
|
-
* endpoint
|
|
1871
|
+
* endpoint. A prepaid credit that reaches its TTL with an undrawn
|
|
1969
1872
|
* remainder RELEASES that remainder to the builder: on cashu, Lightning and
|
|
1970
1873
|
* x402 the funding value reached builder custody at funding time or on the
|
|
1971
1874
|
* settlement cycle, so expiry extinguishes the caller's remaining claim.
|
|
@@ -1981,10 +1884,10 @@ type CreditDrainEnqueue = (tx: RevenueReporterQuerier, payload: CreditDrainPaylo
|
|
|
1981
1884
|
*
|
|
1982
1885
|
* - **The release**, written by the expiry sweep with `reversedAt` absent.
|
|
1983
1886
|
* - **The reversal**, written when a later funding revives the credit
|
|
1984
|
-
*
|
|
1985
|
-
*
|
|
1986
|
-
*
|
|
1987
|
-
*
|
|
1887
|
+
* (`CreditLedger.fund` overwrites `expiry_ms`, so the recorded remainder is
|
|
1888
|
+
* no longer final). It repeats the whole payload rather than sending a
|
|
1889
|
+
* reference, because the retry loop can deliver the two out of order and the
|
|
1890
|
+
* platform's upsert must be able to land either one first.
|
|
1988
1891
|
*
|
|
1989
1892
|
* Idempotent on `(dvmId, creditId, releaseId)`, so the shared retry loop can
|
|
1990
1893
|
* redeliver freely.
|
|
@@ -1992,11 +1895,9 @@ type CreditDrainEnqueue = (tx: RevenueReporterQuerier, payload: CreditDrainPaylo
|
|
|
1992
1895
|
interface CreditExpiryReleasePayload {
|
|
1993
1896
|
/** Required. Platform DVM record ID (`dvms.id`); must match the bearer token's DVM. */
|
|
1994
1897
|
dvmId: string;
|
|
1995
|
-
/** Required. Credit whose remainder expired. */
|
|
1996
1898
|
creditId: string;
|
|
1997
1899
|
/** Required. Per-expiry-episode key; the platform idempotency key with DVM and credit. */
|
|
1998
1900
|
releaseId: string;
|
|
1999
|
-
/** Required. Caller whose claim on the remainder ended. */
|
|
2000
1901
|
callerPubkey: string;
|
|
2001
1902
|
/** Funding rail. `null` on a credit funded before the basis became mandatory. */
|
|
2002
1903
|
rail: string | null;
|
|
@@ -2013,7 +1914,7 @@ interface CreditExpiryReleasePayload {
|
|
|
2013
1914
|
}
|
|
2014
1915
|
/**
|
|
2015
1916
|
* Transactional expiry-release outbox seam, threaded through the sweep's insert
|
|
2016
|
-
* and through the funding that reverses a release
|
|
1917
|
+
* and through the funding that reverses a release.
|
|
2017
1918
|
*
|
|
2018
1919
|
* Implemented by {@link RevenueReporter.enqueueCreditExpiryRelease}; callers
|
|
2019
1920
|
* must await it before committing the write that made the release (or its
|
|
@@ -2023,7 +1924,7 @@ interface CreditExpiryReleasePayload {
|
|
|
2023
1924
|
type CreditExpiryReleaseEnqueue = (tx: RevenueReporterQuerier, payload: CreditExpiryReleasePayload) => Promise<void>;
|
|
2024
1925
|
/**
|
|
2025
1926
|
* JSON wire shape POSTed to the platform's `/_internal/paid-job-death` endpoint
|
|
2026
|
-
*
|
|
1927
|
+
* when the stale-job reaper force-fails a *paid* job — its pending
|
|
2027
1928
|
* credit draw is released rather than settled, so the caller's payment is back
|
|
2028
1929
|
* on their credit balance and reclaimable by drain. The platform resolves fiat
|
|
2029
1930
|
* + owner and sends an ambient notice via the shared alert sink. Unlike
|
|
@@ -2034,15 +1935,13 @@ type CreditExpiryReleaseEnqueue = (tx: RevenueReporterQuerier, payload: CreditEx
|
|
|
2034
1935
|
interface PaidJobDeathPayload {
|
|
2035
1936
|
/** Required. Platform DVM record ID (`dvms.id`). Bound to the authenticating token. */
|
|
2036
1937
|
dvmId: string;
|
|
2037
|
-
/** Required. Job identifier the reaper force-failed. */
|
|
2038
1938
|
jobId: string;
|
|
2039
|
-
/** Required. Capability the job dispatched to (e.g. `"add-episode"`). */
|
|
2040
1939
|
capability: string;
|
|
2041
1940
|
/** Required. Amount of the released credit draw in millisatoshis. */
|
|
2042
1941
|
paidMsats: number;
|
|
2043
|
-
/**
|
|
1942
|
+
/** Payment rail of the released draw (`"cashu"`, `"tempo"`, `"x402"`). */
|
|
2044
1943
|
rail: string;
|
|
2045
|
-
/**
|
|
1944
|
+
/** Reaper reason: dead worker or never-terminal idle job. */
|
|
2046
1945
|
reason: string;
|
|
2047
1946
|
/** Optional. Rail-native released amount, paired with `nativeAsset`. */
|
|
2048
1947
|
nativeAmount?: number;
|
|
@@ -2051,11 +1950,10 @@ interface PaidJobDeathPayload {
|
|
|
2051
1950
|
/** Optional. Cashu mint URL the credit draw's tokens were issued from. */
|
|
2052
1951
|
paymentMint?: string;
|
|
2053
1952
|
}
|
|
2054
|
-
/** Distinct causes for a settled credit draw that could not book revenue. */
|
|
2055
1953
|
type RevenueSkippedNoRailReason = "credit_rail_null" | "credit_rail_unrecognized" | "job_rail_missing" | "ledger_not_configured";
|
|
2056
1954
|
/**
|
|
2057
1955
|
* JSON wire shape POSTed to the platform's `/_internal/revenue-skipped-no-rail`
|
|
2058
|
-
* endpoint
|
|
1956
|
+
* endpoint when a settled credit draw has no usable payment rail
|
|
2059
1957
|
* for its revenue event. This is an operator notice rather than a durable
|
|
2060
1958
|
* accounting report: the SDK's structured log remains the durable backstop,
|
|
2061
1959
|
* and a failed alert must never block terminal handling or reconciliation.
|
|
@@ -2063,11 +1961,8 @@ type RevenueSkippedNoRailReason = "credit_rail_null" | "credit_rail_unrecognized
|
|
|
2063
1961
|
interface RevenueSkippedNoRailPayload {
|
|
2064
1962
|
/** Required. Platform DVM record ID (`dvms.id`). Bound to the authenticating token. */
|
|
2065
1963
|
dvmId: string;
|
|
2066
|
-
/** Required. Job whose settled draw could not be booked. */
|
|
2067
1964
|
jobId: string;
|
|
2068
|
-
/** Required. Credit carrying the settled draw. */
|
|
2069
1965
|
creditId: string;
|
|
2070
|
-
/** Required. Settled draw that has no revenue event. */
|
|
2071
1966
|
drawId: string;
|
|
2072
1967
|
/** Required. Caller payment captured for the job, in millisatoshis. */
|
|
2073
1968
|
paidMsats: number;
|
|
@@ -2077,7 +1972,6 @@ interface RevenueSkippedNoRailPayload {
|
|
|
2077
1972
|
creditCurrency?: string;
|
|
2078
1973
|
/** Credit funding rail as stored on the draw, or null for legacy rows. */
|
|
2079
1974
|
creditRail: string | null;
|
|
2080
|
-
/** Required classification of why the revenue rail was unavailable. */
|
|
2081
1975
|
reason: RevenueSkippedNoRailReason;
|
|
2082
1976
|
}
|
|
2083
1977
|
/** Gas-balance observation POSTed by a platform-hosted x402 self-relay. */
|
|
@@ -2147,11 +2041,13 @@ interface TempoSettlementFailurePayload {
|
|
|
2147
2041
|
drainId?: string;
|
|
2148
2042
|
}
|
|
2149
2043
|
/**
|
|
2150
|
-
* Durable revenue reporter for container-runtime DVMs
|
|
2044
|
+
* Durable revenue reporter for container-runtime DVMs.
|
|
2151
2045
|
*
|
|
2152
2046
|
* On job completion the SDK calls `report()`, which persists the payload to
|
|
2153
2047
|
* a local Postgres table and attempts an immediate POST to the platform.
|
|
2154
2048
|
* A background retry loop picks up un-acked rows with exponential backoff.
|
|
2049
|
+
* Gauge and health notifications are best-effort: failed delivery is logged
|
|
2050
|
+
* and dropped rather than queued for retry.
|
|
2155
2051
|
*/
|
|
2156
2052
|
declare class RevenueReporter {
|
|
2157
2053
|
private readonly db;
|
|
@@ -2164,16 +2060,17 @@ declare class RevenueReporter {
|
|
|
2164
2060
|
constructor(db: Pool, platformUrl: string, platformToken: string);
|
|
2165
2061
|
/** Create the pending-reports table and migrate the legacy SDK outbox (idempotent). */
|
|
2166
2062
|
init(): Promise<void>;
|
|
2167
|
-
/** The boot DDL itself — always runs under {@link withSdkInitLock} (internal-review). */
|
|
2168
2063
|
private createTables;
|
|
2169
|
-
/** Copy rows from the old SDK-owned table without touching the platform's table of that name. */
|
|
2170
2064
|
private migrateLegacySdkOutbox;
|
|
2171
|
-
/** Refuse a pre-existing relation whose columns cannot safely serve as the SDK outbox. */
|
|
2172
2065
|
private assertSdkTableShape;
|
|
2173
2066
|
private assertSdkColumns;
|
|
2174
2067
|
private tableColumns;
|
|
2175
2068
|
/** Persist a revenue report and attempt immediate delivery. */
|
|
2176
2069
|
report(payload: RevenueReportPayload): Promise<void>;
|
|
2070
|
+
/** The permanent deduplication claim and outbox insert commit together.
|
|
2071
|
+
* The claim survives successful delivery, including for custom job stores.
|
|
2072
|
+
*/
|
|
2073
|
+
reportTerminal(payload: JobTerminalReportPayload): Promise<void>;
|
|
2177
2074
|
/** Persist a zero-revenue job cost and attempt immediate delivery. */
|
|
2178
2075
|
reportCost(payload: JobCostReportPayload): Promise<void>;
|
|
2179
2076
|
/**
|
|
@@ -2187,21 +2084,18 @@ declare class RevenueReporter {
|
|
|
2187
2084
|
/** Join a released draw to the transaction that made the hold terminal. */
|
|
2188
2085
|
enqueueCreditDrawRelease(tx: RevenueReporterQuerier, payload: CreditDrawReleasePayload): Promise<void>;
|
|
2189
2086
|
/**
|
|
2190
|
-
* Join a credit drain to the transaction that made it terminal
|
|
2087
|
+
* Join a credit drain to the transaction that made it terminal.
|
|
2191
2088
|
*
|
|
2192
2089
|
* Same discipline as {@link enqueueDeposit} and the same reason: no network
|
|
2193
2090
|
* I/O here, only the durable queue row, written through `tx` so the report
|
|
2194
2091
|
* and the status CAS commit or roll back together. A drain whose row was
|
|
2195
2092
|
* lost between the two would overstate outstanding liability forever —
|
|
2196
2093
|
* the mirror image of a lost deposit.
|
|
2197
|
-
*
|
|
2198
|
-
* Named for the payload rather than the verb because `drain` already means
|
|
2199
|
-
* "flush the queue" in this class (see {@link drainPending}).
|
|
2200
2094
|
*/
|
|
2201
2095
|
enqueueCreditDrain(tx: RevenueReporterQuerier, payload: CreditDrainPayload): Promise<void>;
|
|
2202
2096
|
/**
|
|
2203
2097
|
* Join a payout to the transaction that commits the movement it reports
|
|
2204
|
-
*
|
|
2098
|
+
* the batch close, the accumulator mark, the drain booking.
|
|
2205
2099
|
* No network I/O, only the durable queue row through `tx`, the discipline
|
|
2206
2100
|
* {@link enqueueCreditDrain} set and for the same reason: the money has
|
|
2207
2101
|
* already moved on a rail this ledger does not own, so the platform row is
|
|
@@ -2219,7 +2113,7 @@ declare class RevenueReporter {
|
|
|
2219
2113
|
*/
|
|
2220
2114
|
reportPayout(payload: PayoutReportPayload): Promise<void>;
|
|
2221
2115
|
/**
|
|
2222
|
-
* Report one rail's pending-pool snapshot
|
|
2116
|
+
* Report one rail's pending-pool snapshot. Best-effort and
|
|
2223
2117
|
* fire-and-forget, deliberately unlike {@link reportPayout}: a snapshot is
|
|
2224
2118
|
* replaced by the next tick, so queueing a stale one behind an outage would
|
|
2225
2119
|
* only deliver figures the platform already has newer ones for.
|
|
@@ -2227,7 +2121,7 @@ declare class RevenueReporter {
|
|
|
2227
2121
|
reportPayoutPending(payload: PayoutPendingPayload): Promise<void>;
|
|
2228
2122
|
/**
|
|
2229
2123
|
* Join a credit-expiry release — or the revival that reverses one — to the
|
|
2230
|
-
* transaction that made it true
|
|
2124
|
+
* transaction that made it true.
|
|
2231
2125
|
*
|
|
2232
2126
|
* Same discipline as {@link enqueueCreditDrain}: no network I/O, only the
|
|
2233
2127
|
* durable queue row written through `tx`. A release whose row was lost after
|
|
@@ -2237,7 +2131,7 @@ declare class RevenueReporter {
|
|
|
2237
2131
|
*/
|
|
2238
2132
|
enqueueCreditExpiryRelease(tx: RevenueReporterQuerier, payload: CreditExpiryReleasePayload): Promise<void>;
|
|
2239
2133
|
/**
|
|
2240
|
-
* Report a reaper-force-failed paid job to the platform
|
|
2134
|
+
* Report a reaper-force-failed paid job to the platform so the
|
|
2241
2135
|
* operator receives an ambient notice that a DVM died or wedged mid-job.
|
|
2242
2136
|
* Best-effort and fire-and-forget: unlike {@link report} there is no local
|
|
2243
2137
|
* durable queue — a non-2xx or transport failure is structured-logged
|
|
@@ -2247,24 +2141,18 @@ declare class RevenueReporter {
|
|
|
2247
2141
|
*/
|
|
2248
2142
|
reportPaidJobDeath(payload: PaidJobDeathPayload): Promise<void>;
|
|
2249
2143
|
/**
|
|
2250
|
-
* Report a settled draw whose revenue event was skipped
|
|
2144
|
+
* Report a settled draw whose revenue event was skipped.
|
|
2251
2145
|
* Best-effort and fire-and-forget: the SDK's structured
|
|
2252
2146
|
* `revenue_skipped_no_rail` log is the durable backstop, so a failed notice
|
|
2253
2147
|
* must never wedge terminal handling or the orphan-draw reconciler.
|
|
2254
2148
|
*/
|
|
2255
2149
|
reportRevenueSkippedNoRail(payload: RevenueSkippedNoRailPayload): Promise<void>;
|
|
2256
|
-
/** Report the self-relay's Base gas gauge for platform-side paging and recovery. */
|
|
2257
2150
|
reportX402SelfRelayGasBalance(payload: X402SelfRelayGasBalancePayload): Promise<void>;
|
|
2258
|
-
/** Report redacted self-relay RPC health for platform-side paging and recovery. */
|
|
2259
2151
|
reportX402SelfRelayRpcHealth(payload: X402SelfRelayRpcHealthPayload): Promise<void>;
|
|
2260
|
-
/** Report the Tempo operator's fee-token gauge for paging and recovery. */
|
|
2261
2152
|
reportTempoSettlementBalance(payload: TempoSettlementBalancePayload): Promise<void>;
|
|
2262
|
-
/** Report a redacted operator fee rejection immediately. */
|
|
2263
2153
|
reportTempoSettlementFailure(payload: TempoSettlementFailurePayload): Promise<void>;
|
|
2264
2154
|
private postTempoSettlementReadiness;
|
|
2265
|
-
/** Start the background retry loop. */
|
|
2266
2155
|
startRetryLoop(): void;
|
|
2267
|
-
/** Stop the background retry loop. */
|
|
2268
2156
|
stop(): void;
|
|
2269
2157
|
/**
|
|
2270
2158
|
* Operator-facing queue snapshot: distinguishes the live retry queue from
|
|
@@ -2280,16 +2168,13 @@ declare class RevenueReporter {
|
|
|
2280
2168
|
/**
|
|
2281
2169
|
* Deliver one bounded batch from the durable queue.
|
|
2282
2170
|
*
|
|
2283
|
-
*
|
|
2284
|
-
*
|
|
2171
|
+
* Processes due, non-stale rows; failures back off up to five minutes and
|
|
2172
|
+
* become terminal after 24 hours. Successful deliveries remove their rows.
|
|
2285
2173
|
*/
|
|
2286
2174
|
drainPending(): Promise<void>;
|
|
2287
|
-
/** Durably queue one report of either kind, then try it once immediately. */
|
|
2288
2175
|
private enqueue;
|
|
2289
|
-
/** Insert one pending report through either the pool or an open transaction. */
|
|
2290
2176
|
private insertPending;
|
|
2291
2177
|
private attemptDelivery;
|
|
2292
|
-
/** Mark a pending row terminal (stale) with a classification reason. */
|
|
2293
2178
|
private markStale;
|
|
2294
2179
|
}
|
|
2295
2180
|
|
|
@@ -2298,7 +2183,7 @@ type X402ChannelQuerier = Pick<Pool, "query">;
|
|
|
2298
2183
|
/**
|
|
2299
2184
|
* Durable phase of an irreversible x402 facilitator settlement.
|
|
2300
2185
|
*
|
|
2301
|
-
* `written_off` is the operator's terminal
|
|
2186
|
+
* `written_off` is the operator's terminal: a settlement whose
|
|
2302
2187
|
* ledger leg cannot be completed, reviewed and closed so it leaves the repair
|
|
2303
2188
|
* queue without pretending it booked. It is deliberately reversible — a later
|
|
2304
2189
|
* reconcile still accepts it, because it moved nothing.
|
|
@@ -2317,7 +2202,7 @@ interface X402SettlementIntent {
|
|
|
2317
2202
|
/**
|
|
2318
2203
|
* The channel as it stood when the settlement was handed to the facilitator —
|
|
2319
2204
|
* after the refund's mandatory on-chain refresh, which {@link channelBefore}
|
|
2320
|
-
* precedes
|
|
2205
|
+
* precedes.
|
|
2321
2206
|
*
|
|
2322
2207
|
* The facilitator sizes a cooperative refund from *live* state
|
|
2323
2208
|
* (`balance − chargedCumulativeAmount`) and signs it against the *live*
|
|
@@ -2363,7 +2248,7 @@ interface X402SettlementPage {
|
|
|
2363
2248
|
nextAfter?: X402SettlementCursor;
|
|
2364
2249
|
}
|
|
2365
2250
|
/**
|
|
2366
|
-
* Fleet-wide serialisation of the self-relay's chain submissions
|
|
2251
|
+
* Fleet-wide serialisation of the self-relay's chain submissions.
|
|
2367
2252
|
*
|
|
2368
2253
|
* Narrow on purpose, and implemented by {@link PostgresX402ChannelStorage}: the
|
|
2369
2254
|
* relay asks for one thing — exclusive use of its gas EOA for the length of one
|
|
@@ -2411,7 +2296,7 @@ interface X402RelayLockHolder {
|
|
|
2411
2296
|
* fault in the payment: a fleet-mate whose RPC is retrying holds the lock, and
|
|
2412
2297
|
* the same request works once it lets go. It refuses rather than proceeding —
|
|
2413
2298
|
* two machines submitting from one EOA collide on the nonce — and it refuses
|
|
2414
|
-
* rather than blocking, which is the
|
|
2299
|
+
* rather than blocking, which is the defect: the old acquire had no
|
|
2415
2300
|
* `lock_timeout`, so a wedged holder pinned a host-pool client and a channel
|
|
2416
2301
|
* advisory lock for as long as it took.
|
|
2417
2302
|
*/
|
|
@@ -2428,7 +2313,7 @@ interface X402SettlementWriteOff {
|
|
|
2428
2313
|
intent: X402SettlementIntent;
|
|
2429
2314
|
written: boolean;
|
|
2430
2315
|
}
|
|
2431
|
-
/** The refund standing between a channel and the credit it backs
|
|
2316
|
+
/** The refund standing between a channel and the credit it backs. */
|
|
2432
2317
|
interface X402UnresolvedRefund {
|
|
2433
2318
|
settlementId: string;
|
|
2434
2319
|
/** `${creditId}:${drainId}` — the drain this settlement belongs to. */
|
|
@@ -2436,7 +2321,7 @@ interface X402UnresolvedRefund {
|
|
|
2436
2321
|
status: X402SettlementStatus;
|
|
2437
2322
|
}
|
|
2438
2323
|
/**
|
|
2439
|
-
* The credit ledger's read into durable x402 settlement state
|
|
2324
|
+
* The credit ledger's read into durable x402 settlement state.
|
|
2440
2325
|
*
|
|
2441
2326
|
* Narrow on purpose: the ledger asks one question — is this channel's refund
|
|
2442
2327
|
* still unresolved — and must not acquire the ability to move a settlement.
|
|
@@ -2454,7 +2339,7 @@ interface X402RefundSettlementGate {
|
|
|
2454
2339
|
* transaction to the credit ledger: the fixed lock order is channel first,
|
|
2455
2340
|
* credit second, and no credit-ledger path calls back into this store.
|
|
2456
2341
|
*
|
|
2457
|
-
* Two pools, and the split is load-bearing
|
|
2342
|
+
* Two pools, and the split is load-bearing. The settlement markers
|
|
2458
2343
|
* must write *outside* the ledger transaction, which means a second connection
|
|
2459
2344
|
* taken while the transaction's client is still checked out — on the shared
|
|
2460
2345
|
* host pool that is a self-deadlock the moment concurrent deposits reach its
|
|
@@ -2487,7 +2372,7 @@ declare class PostgresX402ChannelStorage implements ChannelStorage {
|
|
|
2487
2372
|
*
|
|
2488
2373
|
* Both accessors run on the settlement pool: every caller reads or writes the
|
|
2489
2374
|
* marker while {@link withFleetSettlementLock} holds a host-pool client, which
|
|
2490
|
-
* is the nesting the
|
|
2375
|
+
* is the nesting the split exists to keep off a non-terminal pool.
|
|
2491
2376
|
*/
|
|
2492
2377
|
isSettlePending(scope: string): Promise<boolean>;
|
|
2493
2378
|
/** Record whether a claim's funds still need a `settle(receiver, token)` transfer. */
|
|
@@ -2497,16 +2382,16 @@ declare class PostgresX402ChannelStorage implements ChannelStorage {
|
|
|
2497
2382
|
*
|
|
2498
2383
|
* On the dedicated settlement pool like every other marker, and for a sharper
|
|
2499
2384
|
* reason than they had: this and {@link prepareSettlement} now run *inside*
|
|
2500
|
-
* the channel transaction
|
|
2385
|
+
* the channel transaction, which holds a host-pool client for its
|
|
2501
2386
|
* whole duration. Taking a second client from that same pool is the
|
|
2502
|
-
* self-deadlock
|
|
2387
|
+
* self-deadlock fixed — at pool max every client is a holder and a
|
|
2503
2388
|
* waiter — and moving these calls under the transaction is exactly what would
|
|
2504
2389
|
* reintroduce it.
|
|
2505
2390
|
*/
|
|
2506
2391
|
getSettlement(operation: "fund" | "refund", effectId: string): Promise<X402SettlementIntent | undefined>;
|
|
2507
2392
|
/**
|
|
2508
2393
|
* The refund on this channel that is neither finished nor abandoned, if there
|
|
2509
|
-
* is one — the credit ledger's spend gate
|
|
2394
|
+
* is one — the credit ledger's spend gate.
|
|
2510
2395
|
*
|
|
2511
2396
|
* `statuses` is the caller's, because the two gates disagree by design: a
|
|
2512
2397
|
* draw is blocked by {@link X402_SPEND_BLOCKING_SETTLEMENT_STATUSES}, a fresh
|
|
@@ -2514,12 +2399,12 @@ declare class PostgresX402ChannelStorage implements ChannelStorage {
|
|
|
2514
2399
|
*
|
|
2515
2400
|
* On the dedicated settlement pool, and that is what makes the gate callable
|
|
2516
2401
|
* at all: a draw routinely runs inside an open channel transaction holding a
|
|
2517
|
-
* host-pool client, and taking a second one from that pool is the
|
|
2402
|
+
* host-pool client, and taking a second one from that pool is the
|
|
2518
2403
|
* self-deadlock. The oldest blocking row wins, so a channel that somehow
|
|
2519
2404
|
* accumulated two names the one an operator should reach for first.
|
|
2520
2405
|
*
|
|
2521
2406
|
* Projects three columns rather than decoding a whole {@link
|
|
2522
|
-
* X402SettlementIntent}: the decoder refuses a
|
|
2407
|
+
* X402SettlementIntent}: the decoder refuses a legacy row that carries
|
|
2523
2408
|
* no reconciliation snapshot, and a gate that throws on one would take every
|
|
2524
2409
|
* draw on that channel down with it — when the row is exactly the kind that
|
|
2525
2410
|
* ought to block them.
|
|
@@ -2527,7 +2412,7 @@ declare class PostgresX402ChannelStorage implements ChannelStorage {
|
|
|
2527
2412
|
pendingRefundSettlement(channelId: string, statuses: X402SettlementStatus[]): Promise<X402UnresolvedRefund | undefined>;
|
|
2528
2413
|
/**
|
|
2529
2414
|
* Read one settlement by its own identifier — the handle an operator holds
|
|
2530
|
-
*
|
|
2415
|
+
* Same dedicated pool as {@link getSettlement}, for the same
|
|
2531
2416
|
* reason: the repair reads this while a channel transaction may be open.
|
|
2532
2417
|
*/
|
|
2533
2418
|
getSettlementById(settlementId: string): Promise<X402SettlementIntent | undefined>;
|
|
@@ -2535,7 +2420,7 @@ declare class PostgresX402ChannelStorage implements ChannelStorage {
|
|
|
2535
2420
|
normalizeLegacyPaymentId(settlementId: string, operation: "fund" | "refund", legacyPaymentId: string, paymentId: string): Promise<X402SettlementIntent>;
|
|
2536
2421
|
/**
|
|
2537
2422
|
* The operator's repair queue: settlements stuck between "chain paid" and
|
|
2538
|
-
* "ledger booked", oldest write first
|
|
2423
|
+
* "ledger booked", oldest write first.
|
|
2539
2424
|
*
|
|
2540
2425
|
* Keyset-paginated on `(created_at, settlement_id)` for the reason the
|
|
2541
2426
|
* blocked-invoice queue is: a wedged row never self-clears, so a fixed first
|
|
@@ -2560,7 +2445,7 @@ declare class PostgresX402ChannelStorage implements ChannelStorage {
|
|
|
2560
2445
|
after?: X402SettlementCursor;
|
|
2561
2446
|
}): Promise<X402SettlementPage>;
|
|
2562
2447
|
/**
|
|
2563
|
-
* Close a wedged settlement without booking anything
|
|
2448
|
+
* Close a wedged settlement without booking anything.
|
|
2564
2449
|
*
|
|
2565
2450
|
* A single-statement CAS on the wedged statuses, on the settlement pool —
|
|
2566
2451
|
* there is no ledger effect to be atomic with, which is the whole point:
|
|
@@ -2580,7 +2465,7 @@ declare class PostgresX402ChannelStorage implements ChannelStorage {
|
|
|
2580
2465
|
* Mark that the next operation is the ambiguous external-call boundary.
|
|
2581
2466
|
*
|
|
2582
2467
|
* `channelAtSubmission` is the live channel the facilitator is about to size
|
|
2583
|
-
* and sign the settlement against
|
|
2468
|
+
* and sign the settlement against — bookmarked here, with the
|
|
2584
2469
|
* block height, because these two are the only description of that instant
|
|
2585
2470
|
* that survives the call.
|
|
2586
2471
|
*/
|
|
@@ -2602,7 +2487,7 @@ declare class PostgresX402ChannelStorage implements ChannelStorage {
|
|
|
2602
2487
|
/**
|
|
2603
2488
|
* Mark the external settlement and ledger effect complete in the active transaction.
|
|
2604
2489
|
*
|
|
2605
|
-
* `resolvedAtMs` is set only by the operator repair
|
|
2490
|
+
* `resolvedAtMs` is set only by the operator repair, so an audit
|
|
2606
2491
|
* read can tell a settlement that completed on its own from one a human had
|
|
2607
2492
|
* to finish.
|
|
2608
2493
|
*/
|
|
@@ -2629,7 +2514,7 @@ declare class PostgresX402ChannelStorage implements ChannelStorage {
|
|
|
2629
2514
|
* this is how the settlement layer says "this exact decrease is the one the
|
|
2630
2515
|
* payer's verified refund voucher authorises". Outside this scope a decrease
|
|
2631
2516
|
* of `chargedCumulativeAmount` is refused flat, which is what keeps the
|
|
2632
|
-
* arbitrary-decrease guard meaningful
|
|
2517
|
+
* arbitrary-decrease guard meaningful.
|
|
2633
2518
|
*/
|
|
2634
2519
|
withSanctionedRefundBase<T>(base: string, operation: () => Promise<T>): Promise<T>;
|
|
2635
2520
|
withChannelTransaction<T>(channelId: string, operation: (tx: PoolClient) => Promise<T>): Promise<T>;
|
|
@@ -2639,7 +2524,7 @@ declare class PostgresX402ChannelStorage implements ChannelStorage {
|
|
|
2639
2524
|
* The lock is session-scoped, so its client stays checked out for the whole
|
|
2640
2525
|
* operation — and `operation()` (upstream's claim/settle) re-enters the pool
|
|
2641
2526
|
* through {@link updateChannel}. Two bounds keep that from wedging the pool
|
|
2642
|
-
*
|
|
2527
|
+
* local callers are serialized in-process, so this holds at most
|
|
2643
2528
|
* one client per process no matter how many requests arrive, and a waiting
|
|
2644
2529
|
* acquire carries a `lock_timeout` so a wedged fleet-mate can't pin that
|
|
2645
2530
|
* client — and the caller's request — indefinitely. A timeout reports the
|
|
@@ -2652,7 +2537,7 @@ declare class PostgresX402ChannelStorage implements ChannelStorage {
|
|
|
2652
2537
|
*/
|
|
2653
2538
|
withFleetSettlementLock(operation: () => Promise<unknown>, wait?: boolean): Promise<boolean>;
|
|
2654
2539
|
/**
|
|
2655
|
-
* Hold the fleet-wide self-relay submission lock for one chain submission
|
|
2540
|
+
* Hold the fleet-wide self-relay submission lock for one chain submission.
|
|
2656
2541
|
*
|
|
2657
2542
|
* The session lock keeps one per-DVM gas EOA to one in-flight submission
|
|
2658
2543
|
* across the whole fleet — two machines submitting at once collide on the
|
|
@@ -2741,8 +2626,8 @@ interface X402CreditLoss {
|
|
|
2741
2626
|
observedAt: number;
|
|
2742
2627
|
}
|
|
2743
2628
|
/**
|
|
2744
|
-
* Money-safe credit ledger
|
|
2745
|
-
*
|
|
2629
|
+
* Money-safe credit ledger — the SDK-owned settlement primitive required for
|
|
2630
|
+
* prepaid balances in production DVMs.
|
|
2746
2631
|
* Two tables in the DVM's own Postgres (`credits`, `credit_draws`), two-phase
|
|
2747
2632
|
* draws (`pending` at job-accept → `settled` on success / `released` on
|
|
2748
2633
|
* failure), and a per-credit gap-free `ledger_seq` for the receipt evidence
|
|
@@ -2766,7 +2651,7 @@ declare class CreditLedger {
|
|
|
2766
2651
|
private readonly tempoSessionStore?;
|
|
2767
2652
|
/**
|
|
2768
2653
|
* Postgres-backed: balances survive a restart and are shared across the
|
|
2769
|
-
* fleet, so this DVM may advertise credit
|
|
2654
|
+
* fleet, so this DVM may advertise credit.
|
|
2770
2655
|
*/
|
|
2771
2656
|
readonly durable = true;
|
|
2772
2657
|
private x402Settlements?;
|
|
@@ -2774,7 +2659,6 @@ declare class CreditLedger {
|
|
|
2774
2659
|
constructor(pool: CreditLedgerPool, tempoSessionStore?: TempoSessionSettlementStore | undefined);
|
|
2775
2660
|
/**
|
|
2776
2661
|
* Bind the durable x402 settlement state this ledger gates spending on
|
|
2777
|
-
* (internal-review).
|
|
2778
2662
|
*
|
|
2779
2663
|
* Late, because the settlement store is built with the batch-settlement
|
|
2780
2664
|
* server, which is built *after* the ledger it reads earned draws from. An
|
|
@@ -2784,11 +2668,11 @@ declare class CreditLedger {
|
|
|
2784
2668
|
useX402SettlementGate(gate: X402RefundSettlementGate): void;
|
|
2785
2669
|
/**
|
|
2786
2670
|
* Bind the durable outbox that reports credit-expiry releases and their
|
|
2787
|
-
* revivals to the platform
|
|
2671
|
+
* revivals to the platform.
|
|
2788
2672
|
*
|
|
2789
2673
|
* Held on the ledger rather than threaded through {@link fund} for the same
|
|
2790
2674
|
* reason as the gate above: the revival half fires from *every* funding path
|
|
2791
|
-
*
|
|
2675
|
+
* Cashu commit, x402 exact and channel, Tempo, the Lightning invoice
|
|
2792
2676
|
* settle, the implicit N=1 per-call payment — and a seam each of those has to
|
|
2793
2677
|
* remember to pass is a seam one of them will eventually forget.
|
|
2794
2678
|
*
|
|
@@ -2800,10 +2684,10 @@ declare class CreditLedger {
|
|
|
2800
2684
|
useCreditExpiryReleaseOutbox(outbox: CreditExpiryReleaseOutbox): void;
|
|
2801
2685
|
/** Create the `credits` / `credit_draws` tables if absent. Call once at SDK boot. */
|
|
2802
2686
|
init(): Promise<void>;
|
|
2803
|
-
/** The boot DDL itself — always runs under {@link withSdkInitLock}
|
|
2687
|
+
/** The boot DDL itself — always runs under {@link withSdkInitLock}. */
|
|
2804
2688
|
private createTables;
|
|
2805
2689
|
/**
|
|
2806
|
-
* Give every open non-channel Bitcoin credit a funding lot
|
|
2690
|
+
* Give every open non-channel Bitcoin credit a funding lot.
|
|
2807
2691
|
*
|
|
2808
2692
|
* Runs inside the boot DDL, is guarded per credit by `NOT EXISTS`, and is
|
|
2809
2693
|
* therefore both the one-time migration and a standing self-heal for a
|
|
@@ -2814,12 +2698,12 @@ declare class CreditLedger {
|
|
|
2814
2698
|
* `{amount_micro, rail}` — no instrument amount at all — and is not written
|
|
2815
2699
|
* on every funding path, whereas `msats_remaining` **is** the credit's
|
|
2816
2700
|
* current unspent rail value, maintained pro rata on every draw since
|
|
2817
|
-
*
|
|
2701
|
+
* One synthetic lot pairing it with `balance_micro` therefore
|
|
2818
2702
|
* reproduces today's in-kind position exactly, and FIFO over a single lot is
|
|
2819
2703
|
* trivially correct. Historic per-funding rates are unrecoverable and would
|
|
2820
2704
|
* change nothing: only the remaining position is owed.
|
|
2821
2705
|
*
|
|
2822
|
-
* The semantics change is deliberately retroactive
|
|
2706
|
+
* The semantics change is deliberately retroactive — every
|
|
2823
2707
|
* current holder is first-party, so there is one regime and no legacy
|
|
2824
2708
|
* branch.
|
|
2825
2709
|
*/
|
|
@@ -2827,31 +2711,31 @@ declare class CreditLedger {
|
|
|
2827
2711
|
/**
|
|
2828
2712
|
* Create a credit, or top up an existing one (same `creditId`). Top-ups add
|
|
2829
2713
|
* to the balance and overwrite `expiry_ms` with the provided value — funding
|
|
2830
|
-
* an expired credit revives it (
|
|
2714
|
+
* an expired credit revives it (the caller-ownership contract carry-forward: the credit is a
|
|
2831
2715
|
* rolling buffer, not per-job escrow). The existing row's `caller_pubkey`
|
|
2832
2716
|
* and `currency` must match or the fund is refused with a typed error —
|
|
2833
2717
|
* without that check a top-up against someone else's `credit_id` would
|
|
2834
2718
|
* silently merge two callers' money.
|
|
2835
2719
|
*
|
|
2836
2720
|
* Pass `tx` (a client inside a caller-owned `BEGIN`) to commit the rail
|
|
2837
|
-
* receive and the ledger credit atomically (spec condition 3 — the
|
|
2721
|
+
* receive and the ledger credit atomically (spec condition 3 — the
|
|
2838
2722
|
* verifier does this). The ledger issues **no** transaction control on `tx`.
|
|
2839
2723
|
*
|
|
2840
2724
|
* Without `tx` it opens one of its own, because a funding is no longer a
|
|
2841
2725
|
* single statement: it upserts the credit, records its funding lot
|
|
2842
|
-
*
|
|
2726
|
+
* and reverses any standing expiry release — and that
|
|
2843
2727
|
* last leg restores balance and queues a report. A crash between the upsert
|
|
2844
2728
|
* and the reversal would leave a revived credit whose release still stands,
|
|
2845
2729
|
* which the sweep's own exclusion then makes permanent: `balance_micro > 0`
|
|
2846
2730
|
* but a standing release means it is neither drainable nor re-releasable.
|
|
2847
2731
|
*
|
|
2848
|
-
* `basis` records the rail value behind the fiat
|
|
2732
|
+
* `basis` records the rail value behind the fiat so each draw can
|
|
2849
2733
|
* be allocated its share of the rail-native amount actually received. A
|
|
2850
2734
|
* top-up on a different rail than the credit's is refused with
|
|
2851
2735
|
* `rail_mismatch`: sats and USDC microunits aren't summable, so a blended
|
|
2852
2736
|
* credit would have no coherent native basis to allocate from.
|
|
2853
2737
|
*
|
|
2854
|
-
* It is **required
|
|
2738
|
+
* It is **required**, in the type and again at runtime via
|
|
2855
2739
|
* {@link assertFundingBasis}. A basis-less fund wrote `rail = NULL`, and a
|
|
2856
2740
|
* draw against such a credit settles — a real debit — while
|
|
2857
2741
|
* `railAsFundingMethod` correctly declines to guess a rail, so `bookRevenue`
|
|
@@ -2862,7 +2746,7 @@ declare class CreditLedger {
|
|
|
2862
2746
|
* typed top-up via the `COALESCE` below.
|
|
2863
2747
|
*
|
|
2864
2748
|
* The rail-native **instrument** is pinned at first funding too, and both
|
|
2865
|
-
* channel guards are symmetric for the same reason
|
|
2749
|
+
* channel guards are symmetric for the same reason. A reusable
|
|
2866
2750
|
* channel — Tempo session or x402 batch-settlement — may only ever top up
|
|
2867
2751
|
* the credit it opened, and a credit opened by a one-shot (a Tempo charge, an
|
|
2868
2752
|
* x402 exact authorization) may never adopt one. The x402 half used to admit
|
|
@@ -2876,7 +2760,7 @@ declare class CreditLedger {
|
|
|
2876
2760
|
* one-credit-per-channel, not one-source-per-credit.
|
|
2877
2761
|
*
|
|
2878
2762
|
* An x402 channel deposit is additionally refused `settlement_pending` while
|
|
2879
|
-
* that channel carries an unresolved refund
|
|
2763
|
+
* that channel carries an unresolved refund — see the gate read
|
|
2880
2764
|
* below. This method is the authority on that rule, as it is on the binding
|
|
2881
2765
|
* rules above; every door preflights it where a refusal is still free.
|
|
2882
2766
|
*/
|
|
@@ -2889,12 +2773,12 @@ declare class CreditLedger {
|
|
|
2889
2773
|
private fundOn;
|
|
2890
2774
|
/**
|
|
2891
2775
|
* Undo any expiry release this credit still carries, because a funding just
|
|
2892
|
-
* landed on it (
|
|
2776
|
+
* landed on it (the revival rule), restoring the balance the
|
|
2893
2777
|
* release took.
|
|
2894
2778
|
*
|
|
2895
2779
|
* A release records the credit's **final** undrawn remainder and zeroes it
|
|
2896
2780
|
* (see {@link releaseExpiredCreditLocked}). Funding adds to the balance and
|
|
2897
|
-
* overwrites `expiry_ms` (
|
|
2781
|
+
* overwrites `expiry_ms` (the caller-ownership contract carry-forward: the credit is a rolling
|
|
2898
2782
|
* buffer), so the moment money arrives the recorded remainder is no longer
|
|
2899
2783
|
* final: the release stops counting and its micro come back.
|
|
2900
2784
|
*
|
|
@@ -2913,13 +2797,13 @@ declare class CreditLedger {
|
|
|
2913
2797
|
* re-derives it.
|
|
2914
2798
|
*
|
|
2915
2799
|
* @returns the credit row as the restore left it, or undefined when there was
|
|
2916
|
-
*
|
|
2917
|
-
*
|
|
2800
|
+
* nothing to reverse. The caller reads its snapshot off this rather than off
|
|
2801
|
+
* the funding upsert's `RETURNING`, which predates the restore.
|
|
2918
2802
|
*/
|
|
2919
2803
|
private reverseExpiryReleases;
|
|
2920
2804
|
/**
|
|
2921
2805
|
* Release the undrawn remainder of every credit whose TTL has run out
|
|
2922
|
-
*
|
|
2806
|
+
* Returns the releases this pass recorded.
|
|
2923
2807
|
*
|
|
2924
2808
|
* **What is released.** The credit's whole `balance_micro`. Expiry ends
|
|
2925
2809
|
* spending but never ownership of the record, so the balance stays readable;
|
|
@@ -2936,7 +2820,7 @@ declare class CreditLedger {
|
|
|
2936
2820
|
* runs above the expiry check, so a lost response is still recoverable), so
|
|
2937
2821
|
* the remainder is not final while a hold is outstanding. Skipping costs one
|
|
2938
2822
|
* sweep interval and keeps the released figure exactly "what nothing bought";
|
|
2939
|
-
* holds do resolve — the orphan-draw watchdog
|
|
2823
|
+
* holds do resolve — the orphan-draw watchdog is what guarantees
|
|
2940
2824
|
* a stranded one still reaches a terminal state.
|
|
2941
2825
|
*
|
|
2942
2826
|
* **Idempotent** two ways. `release_id` is derived from the expiry instant,
|
|
@@ -2985,7 +2869,7 @@ declare class CreditLedger {
|
|
|
2985
2869
|
*/
|
|
2986
2870
|
private releaseExpiredCreditLocked;
|
|
2987
2871
|
/**
|
|
2988
|
-
* Record this funding's in-kind basis as a lot
|
|
2872
|
+
* Record this funding's in-kind basis as a lot.
|
|
2989
2873
|
*
|
|
2990
2874
|
* Called from inside {@link fund}, on the same handle, so the lot shares
|
|
2991
2875
|
* whatever transaction the rail opened — `withCommitTx` for Cashu,
|
|
@@ -3028,11 +2912,11 @@ declare class CreditLedger {
|
|
|
3028
2912
|
* placed pre-expiry must stay recoverable after the credit expires, or the
|
|
3029
2913
|
* DVM holds a debit the caller can never reconcile. Fresh draws on an
|
|
3030
2914
|
* expired credit are refused with `credit_expired`; the balance stays
|
|
3031
|
-
* intact and readable (
|
|
2915
|
+
* intact and readable (the caller-ownership contract: expiry ends spending, never ownership).
|
|
3032
2916
|
*
|
|
3033
2917
|
* Pass `tx` (a client inside a caller-owned `BEGIN`) to place the hold in
|
|
3034
2918
|
* the same transaction as the rail commit and the `fund` upsert (spec
|
|
3035
|
-
* condition 3 — the
|
|
2919
|
+
* condition 3 — the implicit N=1 path). The ledger issues no
|
|
3036
2920
|
* transaction control on `tx`; the `SELECT … FOR UPDATE` row lock is still
|
|
3037
2921
|
* taken on the caller's transaction, so the locking invariant holds.
|
|
3038
2922
|
*/
|
|
@@ -3048,18 +2932,18 @@ declare class CreditLedger {
|
|
|
3048
2932
|
}): Promise<DrawResult>;
|
|
3049
2933
|
/**
|
|
3050
2934
|
* The unresolved refund on `channelId` that must stop this ledger effect, if
|
|
3051
|
-
* any
|
|
2935
|
+
* any.
|
|
3052
2936
|
*
|
|
3053
2937
|
* `undefined` whenever there is nothing to ask — an unbound credit, or a DVM
|
|
3054
2938
|
* with no durable settlement store, where a settlement row cannot exist.
|
|
3055
2939
|
*
|
|
3056
|
-
* Public since
|
|
2940
|
+
* Public since the behavior was introduced, so `/v1/credit`'s pre-payment preflight can ask the
|
|
3057
2941
|
* same question `fund` will ask from inside the rail transaction — one read,
|
|
3058
2942
|
* one answer, rather than a second copy of the rule in the routes.
|
|
3059
2943
|
*/
|
|
3060
2944
|
blockingX402Refund(channelId: string | null | undefined, statuses: X402SettlementStatus[]): Promise<X402UnresolvedRefund | undefined>;
|
|
3061
2945
|
/**
|
|
3062
|
-
* Grow a pending draw by `addAmountMicro`
|
|
2946
|
+
* Grow a pending draw by `addAmountMicro` — the ledger half of a
|
|
3063
2947
|
* mid-job `requestPayment` top-up. One job keeps **one** draw: the mid-job
|
|
3064
2948
|
* money funds the same credit and enlarges the hold the upfront leg placed,
|
|
3065
2949
|
* so the receipt's `ReceiptCredit` block countersigns the job's full cost
|
|
@@ -3078,7 +2962,7 @@ declare class CreditLedger {
|
|
|
3078
2962
|
* The increment's rail value comes from {@link growthRailValue}: earmarked
|
|
3079
2963
|
* to the funding that backs it when the caller names one (the mid-job case),
|
|
3080
2964
|
* pro-rata otherwise. Either way the draws of a credit keep summing to
|
|
3081
|
-
* precisely what the rails paid
|
|
2965
|
+
* precisely what the rails paid.
|
|
3082
2966
|
*
|
|
3083
2967
|
* **`ledger_seq` is not re-taken.** The per-credit sequence is gap-free
|
|
3084
2968
|
* (`credit_draws_seq_uidx`), so moving this draw forward would strand its
|
|
@@ -3096,8 +2980,8 @@ declare class CreditLedger {
|
|
|
3096
2980
|
* the whole transaction back on replay; x402/mpp collide on the
|
|
3097
2981
|
* `processed_payments` marker). Never call it outside a rail commit.
|
|
3098
2982
|
*
|
|
3099
|
-
* **`capMicro` bounds cumulative growth at what the job cumulatively asked
|
|
3100
|
-
*
|
|
2983
|
+
* **`capMicro` bounds cumulative growth at what the job cumulatively asked,**
|
|
2984
|
+
* and it is the only ceiling that can refuse a top-up: the
|
|
3101
2985
|
* available-balance check cannot, because the `fund` a moment earlier in
|
|
3102
2986
|
* this same transaction raised the balance by exactly the amount being
|
|
3103
2987
|
* drawn. Excess is **granted partially or not at all rather than thrown** —
|
|
@@ -3111,7 +2995,7 @@ declare class CreditLedger {
|
|
|
3111
2995
|
addAmountMicro: number;
|
|
3112
2996
|
/**
|
|
3113
2997
|
* Rail value that funded this growth, earmarked to the increment instead
|
|
3114
|
-
* of allocated pro-rata
|
|
2998
|
+
* of allocated pro-rata. Pass it whenever `addAmountMicro` is
|
|
3115
2999
|
* money that landed in this same transaction; omit it when the growth
|
|
3116
3000
|
* spends balance the credit already held.
|
|
3117
3001
|
*/
|
|
@@ -3121,7 +3005,7 @@ declare class CreditLedger {
|
|
|
3121
3005
|
};
|
|
3122
3006
|
/**
|
|
3123
3007
|
* Ceiling on this draw's **cumulative** growth, in fiat micro of the
|
|
3124
|
-
* credit's currency
|
|
3008
|
+
* credit's currency — the job's total mid-job ask. Growth is
|
|
3125
3009
|
* clipped to `capMicro - grown_micro`; a second payment for an ask the
|
|
3126
3010
|
* first already satisfied gets zero. Omit it only when the caller genuinely
|
|
3127
3011
|
* has no ask total to bound against; growth is then unbounded, as before.
|
|
@@ -3155,7 +3039,7 @@ declare class CreditLedger {
|
|
|
3155
3039
|
}): Promise<DrawResolution>;
|
|
3156
3040
|
/**
|
|
3157
3041
|
* Release a pending draw: the hold evaporates, the balance is untouched —
|
|
3158
|
-
* this is how "no debit on job failure" is mechanically real (
|
|
3042
|
+
* this is how "no debit on job failure" is mechanically real (the credit lifecycle contract).
|
|
3159
3043
|
* Idempotent: releasing a released draw returns the original tuple. A
|
|
3160
3044
|
* settled draw cannot be released (`invalid_draw_state`) — un-settling
|
|
3161
3045
|
* booked revenue is a reconciliation problem, not a ledger verb.
|
|
@@ -3167,14 +3051,14 @@ declare class CreditLedger {
|
|
|
3167
3051
|
nowMs?: number;
|
|
3168
3052
|
}): Promise<DrawResolution>;
|
|
3169
3053
|
/**
|
|
3170
|
-
* Record a fund-only top-up under its client-generated `fundId
|
|
3054
|
+
* Record a fund-only top-up under its client-generated `fundId`.
|
|
3171
3055
|
* The deposit half of the evidence chain, and the top-up path's idempotency
|
|
3172
3056
|
* key: `PRIMARY KEY (credit_id, fund_id)` means a concurrent duplicate
|
|
3173
3057
|
* loses with a typed `funding_replayed` rather than crediting twice.
|
|
3174
3058
|
*
|
|
3175
3059
|
* Call it inside the same `tx` as {@link fund} — the rail commit, the
|
|
3176
3060
|
* funding record, and the balance increment must land together or not at
|
|
3177
|
-
* all (
|
|
3061
|
+
* all (the funding-commitment rule). Like `fund`, this issues no transaction
|
|
3178
3062
|
* control on `tx`; it is a single statement.
|
|
3179
3063
|
*
|
|
3180
3064
|
* This does **not** move money on its own. `fund` still does the crediting;
|
|
@@ -3216,7 +3100,7 @@ declare class CreditLedger {
|
|
|
3216
3100
|
receipt: FundingReceipt;
|
|
3217
3101
|
}): Promise<FundingReceipt>;
|
|
3218
3102
|
/**
|
|
3219
|
-
* Record the bolt11 issued for a `(creditId, fundId)` top-up
|
|
3103
|
+
* Record the bolt11 issued for a `(creditId, fundId)` top-up, or
|
|
3220
3104
|
* return the one already issued for it.
|
|
3221
3105
|
*
|
|
3222
3106
|
* **Returning the existing row is the point.** A caller re-polling an unpaid
|
|
@@ -3254,7 +3138,7 @@ declare class CreditLedger {
|
|
|
3254
3138
|
}): Promise<CreditInvoiceRecord[]>;
|
|
3255
3139
|
/**
|
|
3256
3140
|
* Apply an observed Lightning settlement to the ledger — **the exactly-once
|
|
3257
|
-
* boundary** (
|
|
3141
|
+
* boundary** (the funding-commitment rule for a rail whose commit happens
|
|
3258
3142
|
* off-box).
|
|
3259
3143
|
*
|
|
3260
3144
|
* One transaction covers the funding record, the balance, and the invoice's
|
|
@@ -3275,13 +3159,13 @@ declare class CreditLedger {
|
|
|
3275
3159
|
fundId: string;
|
|
3276
3160
|
expiryMs: number;
|
|
3277
3161
|
/**
|
|
3278
|
-
* Rail-value basis, pinned when the invoice was issued
|
|
3279
|
-
* by
|
|
3162
|
+
* Rail-value basis, pinned when the invoice was issued. Required
|
|
3163
|
+
* by — it is what `fund` writes to `credits.rail`.
|
|
3280
3164
|
*/
|
|
3281
3165
|
basis: CreditFundingBasis;
|
|
3282
3166
|
/**
|
|
3283
3167
|
* Reporter-owned deposit outbox write. Runs on the invoice transaction
|
|
3284
|
-
* after the ledger/status writes and before COMMIT
|
|
3168
|
+
* after the ledger/status writes and before COMMIT.
|
|
3285
3169
|
*/
|
|
3286
3170
|
depositOutbox?: {
|
|
3287
3171
|
enqueue: CreditDepositEnqueue;
|
|
@@ -3300,7 +3184,7 @@ declare class CreditLedger {
|
|
|
3300
3184
|
fundId: string;
|
|
3301
3185
|
}): Promise<CreditInvoiceRecord | undefined>;
|
|
3302
3186
|
/**
|
|
3303
|
-
* Retire an invoice that **was paid** and can never be credited
|
|
3187
|
+
* Retire an invoice that **was paid** and can never be credited.
|
|
3304
3188
|
*
|
|
3305
3189
|
* Distinct from `expired` because the money is the opposite way round: an
|
|
3306
3190
|
* expired invoice was never paid and owes nobody anything, whereas a blocked
|
|
@@ -3322,15 +3206,15 @@ declare class CreditLedger {
|
|
|
3322
3206
|
/** Read one invoice by the wallet's own identifier for the payment (no lock). */
|
|
3323
3207
|
getInvoiceByPaymentHash(paymentHash: string): Promise<CreditInvoiceRecord | undefined>;
|
|
3324
3208
|
/**
|
|
3325
|
-
* The operator's queue: invoices the sweep gave up on
|
|
3209
|
+
* The operator's queue: invoices the sweep gave up on.
|
|
3326
3210
|
*
|
|
3327
3211
|
* **Keyset-paginated, not offset.** Blocked rows are terminal and never
|
|
3328
3212
|
* self-clear, so a row the operator declines to act on sits at the head of
|
|
3329
3213
|
* the age ordering forever; a fixed first page would starve everything
|
|
3330
|
-
* behind it on every run, which is the
|
|
3214
|
+
* behind it on every run, which is the shape one page up.
|
|
3331
3215
|
*
|
|
3332
3216
|
* `includeResolved` widens to the operator-resolved statuses so a run can be
|
|
3333
|
-
* audited after the fact
|
|
3217
|
+
* audited after the fact.
|
|
3334
3218
|
* Host-wide, like `listPendingDrains`: the ledger has no `dvm_id`, so on a
|
|
3335
3219
|
* multi-mount host one builder's admin credential reads every mount's rows.
|
|
3336
3220
|
*/
|
|
@@ -3341,7 +3225,7 @@ declare class CreditLedger {
|
|
|
3341
3225
|
}): Promise<CreditInvoiceRecord[]>;
|
|
3342
3226
|
/**
|
|
3343
3227
|
* Apply a blocked invoice's payment to a credit an operator named — the
|
|
3344
|
-
* repair for the one Lightning outcome the DVM cannot fix itself
|
|
3228
|
+
* repair for the one Lightning outcome the DVM cannot fix itself.
|
|
3345
3229
|
*
|
|
3346
3230
|
* Shaped statement-for-statement on {@link settleInvoice}, because it is the
|
|
3347
3231
|
* same money doing the same thing a different way: one transaction covering
|
|
@@ -3349,21 +3233,21 @@ declare class CreditLedger {
|
|
|
3349
3233
|
* outbox row, so the four can never disagree. Three deliberate differences:
|
|
3350
3234
|
*
|
|
3351
3235
|
* - **The lock is taken on `payment_hash`**, which is UNIQUE and is the
|
|
3352
|
-
*
|
|
3353
|
-
*
|
|
3354
|
-
*
|
|
3355
|
-
*
|
|
3356
|
-
*
|
|
3236
|
+
* identifier the operator actually holds (it is what the
|
|
3237
|
+
* `lightning_settlement_blocked` log carries and what names the payment in
|
|
3238
|
+
* their wallet). Invoice row first, credit row second via `fund`'s upsert —
|
|
3239
|
+
* the same order `settleInvoice` takes, which is what keeps a reconcile and
|
|
3240
|
+
* a concurrent settlement check from deadlocking against each other.
|
|
3357
3241
|
* - **The funding lands at `(targetCreditId, paymentHash)`, not the invoice's
|
|
3358
|
-
*
|
|
3359
|
-
*
|
|
3360
|
-
*
|
|
3361
|
-
*
|
|
3362
|
-
*
|
|
3363
|
-
*
|
|
3242
|
+
* own `(credit_id, fund_id)`.** That key is frequently the reason the row
|
|
3243
|
+
* is blocked at all — `funding_replayed_on_cashu` means something else
|
|
3244
|
+
* already holds it — and the operator's most natural target is that very
|
|
3245
|
+
* credit. The payment hash cannot collide with it, and it makes all three
|
|
3246
|
+
* references to this payment agree: `basis.fundingRef`, the deposit's
|
|
3247
|
+
* `funding_id`, and the funding row's `fund_id`.
|
|
3364
3248
|
* - **`written_off` is an accepted input status.** A write-off unwound
|
|
3365
|
-
*
|
|
3366
|
-
*
|
|
3249
|
+
* nothing, so an operator who closed a row by mistake must not need raw SQL
|
|
3250
|
+
* against a money table to reopen it.
|
|
3367
3251
|
*
|
|
3368
3252
|
* The invoice row's status — never the funding row — is the idempotency
|
|
3369
3253
|
* source of truth. `fund_id` is caller-chosen and the payment hash is
|
|
@@ -3377,7 +3261,7 @@ declare class CreditLedger {
|
|
|
3377
3261
|
/** Credit the money lands on. The caller identity comes off the invoice row. */
|
|
3378
3262
|
targetCreditId: string;
|
|
3379
3263
|
expiryMs: number;
|
|
3380
|
-
/** Rail-value basis, rebuilt from the invoice row by the caller
|
|
3264
|
+
/** Rail-value basis, rebuilt from the invoice row by the caller. */
|
|
3381
3265
|
basis: CreditFundingBasis;
|
|
3382
3266
|
/** The wallet's settlement instant, re-observed by the operator's verb. */
|
|
3383
3267
|
settledAtMs?: number;
|
|
@@ -3389,7 +3273,7 @@ declare class CreditLedger {
|
|
|
3389
3273
|
}): Promise<InvoiceReconciliation>;
|
|
3390
3274
|
/**
|
|
3391
3275
|
* Record that an operator reviewed a blocked invoice and chose not to credit
|
|
3392
|
-
* it
|
|
3276
|
+
* it — no ledger effect, purely a queue transition.
|
|
3393
3277
|
*
|
|
3394
3278
|
* A CAS on `blocked`, and idempotent: re-running returns the recorded row
|
|
3395
3279
|
* rather than overwriting the first note. It cannot capture a `reconciled`
|
|
@@ -3424,13 +3308,13 @@ declare class CreditLedger {
|
|
|
3424
3308
|
listDrawsByJobId(jobId: string): Promise<DrawRecord[]>;
|
|
3425
3309
|
/**
|
|
3426
3310
|
* All pending holds on a credit, in `ledger_seq` order (no lock). Read
|
|
3427
|
-
* surface for the
|
|
3311
|
+
* surface for the sweeper wiring — a worker that dies mid-job
|
|
3428
3312
|
* leaves its hold `pending` until something releases it.
|
|
3429
3313
|
*/
|
|
3430
3314
|
listPendingDraws(creditId: string): Promise<DrawRecord[]>;
|
|
3431
3315
|
/**
|
|
3432
3316
|
* One page of pending holds host-wide placed before `createdBeforeMs`,
|
|
3433
|
-
* oldest first (no lock). The orphan sweeper's read surface
|
|
3317
|
+
* oldest first (no lock). The orphan sweeper's read surface: a
|
|
3434
3318
|
* draw commits with its `job_id` before the job row is persisted, so a crash
|
|
3435
3319
|
* or a fail-closed refusal in that window strands a hold nothing can ever
|
|
3436
3320
|
* resolve — the only release path keys off the `credit_id`/`draw_id` written
|
|
@@ -3455,7 +3339,7 @@ declare class CreditLedger {
|
|
|
3455
3339
|
* Rail-native value the credit an x402 settlement channel funded has
|
|
3456
3340
|
* actually earned — the sum of its **settled** draws, in the credit's native
|
|
3457
3341
|
* atomic units (USDC micro on this rail). The batch-settlement claim job's
|
|
3458
|
-
* ceiling
|
|
3342
|
+
* ceiling: a channel is claimable up to what its credit's draws
|
|
3459
3343
|
* have earned, never up to the deposit that funded it.
|
|
3460
3344
|
*
|
|
3461
3345
|
* `undefined` when no credit is bound to the channel, which the claim job
|
|
@@ -3471,7 +3355,7 @@ declare class CreditLedger {
|
|
|
3471
3355
|
earnedNativeForX402Channel(channelId: string): Promise<number | undefined>;
|
|
3472
3356
|
/**
|
|
3473
3357
|
* The credit an x402 settlement channel funded, if one is bound to it — the
|
|
3474
|
-
* binding is UNIQUE, so at most one row can answer
|
|
3358
|
+
* binding is UNIQUE, so at most one row can answer.
|
|
3475
3359
|
*
|
|
3476
3360
|
* The operator repair's entry point: a wedged settlement row carries the
|
|
3477
3361
|
* channel and an `effect_id`, and this is what turns them back into the
|
|
@@ -3504,7 +3388,7 @@ declare class CreditLedger {
|
|
|
3504
3388
|
}): Promise<X402CreditLoss[]>;
|
|
3505
3389
|
/**
|
|
3506
3390
|
* Debit the caller's entire available balance into a drain liability
|
|
3507
|
-
* (
|
|
3391
|
+
* (the caller-ownership contract: expiry ends spending, never ownership — this is the
|
|
3508
3392
|
* builder-honored reclaim floor). Runs under the credit row lock: the
|
|
3509
3393
|
* amount is `balance − pending holds` read under `FOR UPDATE`, the balance
|
|
3510
3394
|
* is decremented in the same transaction, and the drain takes the next
|
|
@@ -3546,14 +3430,14 @@ declare class CreditLedger {
|
|
|
3546
3430
|
drainId: string;
|
|
3547
3431
|
}): Promise<CreditDrainRecord | undefined>;
|
|
3548
3432
|
/**
|
|
3549
|
-
* One credit's undepleted funding lots, oldest first
|
|
3433
|
+
* One credit's undepleted funding lots, oldest first — the
|
|
3550
3434
|
* public read behind the reclaim's own arithmetic, for anything that needs
|
|
3551
3435
|
* to show its work.
|
|
3552
3436
|
*/
|
|
3553
3437
|
listFundingLots(creditId: string): Promise<FundingLot[]>;
|
|
3554
3438
|
/**
|
|
3555
3439
|
* What this DVM owes back in satoshis if every open non-channel Bitcoin
|
|
3556
|
-
* credit reclaimed right now
|
|
3440
|
+
* credit reclaimed right now — the deposit half of the hub
|
|
3557
3441
|
* balance, and the floor a payout sweep must never go below.
|
|
3558
3442
|
*
|
|
3559
3443
|
* Read entirely off the funding lots, at their own funding rates, with no
|
|
@@ -3584,7 +3468,7 @@ declare class CreditLedger {
|
|
|
3584
3468
|
listPendingDrains(): Promise<CreditDrainRecord[]>;
|
|
3585
3469
|
/**
|
|
3586
3470
|
* One page of still-`pending` drains on a channel-backed credit, oldest
|
|
3587
|
-
* first (no lock) — the operator's repair queue
|
|
3471
|
+
* first (no lock) — the operator's repair queue.
|
|
3588
3472
|
*
|
|
3589
3473
|
* Keyset-paginated for the x402 settlement queue's reason: a wedged row
|
|
3590
3474
|
* never self-clears, so a caller that re-issues the same first page would
|
|
@@ -3600,10 +3484,10 @@ declare class CreditLedger {
|
|
|
3600
3484
|
* younger is in flight rather than stuck.
|
|
3601
3485
|
*
|
|
3602
3486
|
* The method filter is `'tempo'`, and it is the one line here worth a second
|
|
3603
|
-
* look: `init()` migrates the
|
|
3487
|
+
* look: `init()` migrates the legacy `'mpp'` spelling away and
|
|
3604
3488
|
* `DrainMethod` no longer carries it, so a query naming it matches nothing a
|
|
3605
|
-
* DVM has ever written. It named it anyway until
|
|
3606
|
-
*
|
|
3489
|
+
* DVM has ever written. It named it anyway until rename sweep and
|
|
3490
|
+
* live rung caught it independently — the whole operator queue
|
|
3607
3491
|
* read empty in production while every route test stayed green, because
|
|
3608
3492
|
* those run on `MemoryCreditLedger`, which filters on the typed value. The
|
|
3609
3493
|
* two implementations of this one predicate must be read together.
|
|
@@ -3622,7 +3506,7 @@ declare class CreditLedger {
|
|
|
3622
3506
|
}): Promise<CreditDrainRecord[]>;
|
|
3623
3507
|
/**
|
|
3624
3508
|
* Record that an operator reviewed a floor-refused channel drain and is not
|
|
3625
|
-
* booking it
|
|
3509
|
+
* booking it. Books nothing anywhere — no status change, no
|
|
3626
3510
|
* balance movement, no platform report.
|
|
3627
3511
|
*
|
|
3628
3512
|
* A single-statement CAS on `written_off_at IS NULL`, so the first note on
|
|
@@ -3680,7 +3564,7 @@ declare class CreditLedger {
|
|
|
3680
3564
|
creditId: string;
|
|
3681
3565
|
drainId: string;
|
|
3682
3566
|
token: string;
|
|
3683
|
-
/** Cost evidence for a just-in-time mint
|
|
3567
|
+
/** Cost evidence for a just-in-time mint; absent on an accumulator park. */
|
|
3684
3568
|
fulfilment?: DrainFulfilment;
|
|
3685
3569
|
tx?: CreditLedgerQuerier;
|
|
3686
3570
|
nowMs?: number;
|
|
@@ -3691,7 +3575,7 @@ declare class CreditLedger {
|
|
|
3691
3575
|
* loss, so the caller's re-poll keeps returning the same token either way.
|
|
3692
3576
|
*
|
|
3693
3577
|
* Returns `replayed` because this is a **terminal** transition and the money
|
|
3694
|
-
* has left at exactly one of these calls
|
|
3578
|
+
* has left at exactly one of these calls: the platform drain
|
|
3695
3579
|
* report must be emitted by that caller and no other. Pass `tx` to write the
|
|
3696
3580
|
* report through the same transaction as the CAS.
|
|
3697
3581
|
*/
|
|
@@ -3740,7 +3624,7 @@ declare class CreditLedger {
|
|
|
3740
3624
|
/** Shared refusal tail for the CAS transitions: idempotent replay or typed error. */
|
|
3741
3625
|
private refuseTransition;
|
|
3742
3626
|
/**
|
|
3743
|
-
* Price a reclaim in kind and say which lots it takes
|
|
3627
|
+
* Price a reclaim in kind and say which lots it takes.
|
|
3744
3628
|
*
|
|
3745
3629
|
* The debits are returned whether or not the reclaim can be priced, and the
|
|
3746
3630
|
* caller applies them either way: the money is leaving the credit, so the
|
|
@@ -3749,13 +3633,13 @@ declare class CreditLedger {
|
|
|
3749
3633
|
*
|
|
3750
3634
|
* `owedSats` is `null` where {@link isInKindDepletion} refuses — the lots
|
|
3751
3635
|
* are short of the balance, or the covering lots carry no sats basis (a
|
|
3752
|
-
* credit
|
|
3636
|
+
* legacy credit whose funding recorded no sats basis. That row is priced off a live rate by the
|
|
3753
3637
|
* admin surface instead, which is what *every* row did before this change,
|
|
3754
3638
|
* so the fallback is the old behaviour rather than a new failure mode.
|
|
3755
3639
|
*
|
|
3756
|
-
* What it publishes is **net of the delivery reserve
|
|
3640
|
+
* What it publishes is **net of the delivery reserve**: handing a
|
|
3757
3641
|
* refund over costs a mint fee and, when the notes have to be minted just in
|
|
3758
|
-
* time, a Lightning hop. The caller carries that cost per
|
|
3642
|
+
* time, a Lightning hop. The caller carries that cost per and a
|
|
3759
3643
|
* flat reserve is how they carry it without the figure moving — an
|
|
3760
3644
|
* actual-fee true-up could only be applied after the promise was made. The
|
|
3761
3645
|
* debits stay gross because they are denominated in micro and are what
|
|
@@ -3763,7 +3647,7 @@ declare class CreditLedger {
|
|
|
3763
3647
|
*/
|
|
3764
3648
|
private reclaimInKind;
|
|
3765
3649
|
/**
|
|
3766
|
-
* This credit's undepleted funding lots, oldest first
|
|
3650
|
+
* This credit's undepleted funding lots, oldest first.
|
|
3767
3651
|
*
|
|
3768
3652
|
* Ordered in SQL on the same `(created_at, lot_id)` key the partial index
|
|
3769
3653
|
* carries, so FIFO is the index's own order rather than something a reader
|
|
@@ -3794,7 +3678,7 @@ declare class CreditLedger {
|
|
|
3794
3678
|
/**
|
|
3795
3679
|
* Held-but-unresolved totals for a credit, in all three units at once — the
|
|
3796
3680
|
* fiat micro that defines available balance plus the rail-value remainders
|
|
3797
|
-
* a new draw allocates against
|
|
3681
|
+
* a new draw allocates against. One round-trip, since every
|
|
3798
3682
|
* caller needs the micro sum anyway.
|
|
3799
3683
|
*/
|
|
3800
3684
|
private pendingSums;
|
|
@@ -3803,7 +3687,7 @@ declare class CreditLedger {
|
|
|
3803
3687
|
private readX402CreditLosses;
|
|
3804
3688
|
}
|
|
3805
3689
|
/**
|
|
3806
|
-
* The ledger surface the SDK server codes against
|
|
3690
|
+
* The ledger surface the SDK server codes against. Implemented by
|
|
3807
3691
|
* the Postgres {@link CreditLedger} (production — spec condition 2 requires
|
|
3808
3692
|
* the DVM's own Postgres) and by `MemoryCreditLedger` (devMode / in-process
|
|
3809
3693
|
* tests / pool-less `createDVMServer` setups, mirroring the `MemoryJobStore`
|
|
@@ -3814,13 +3698,13 @@ declare class CreditLedger {
|
|
|
3814
3698
|
interface CreditLedgerLike {
|
|
3815
3699
|
/**
|
|
3816
3700
|
* True when balances survive a restart and are visible fleet-wide
|
|
3817
|
-
*
|
|
3701
|
+
* The funding menu is suppressed on a non-durable ledger
|
|
3818
3702
|
* outside devMode: a caller who funds on machine A and draws on machine B
|
|
3819
3703
|
* would get `credit_not_found`, so advertising credit there misadvertises.
|
|
3820
3704
|
*/
|
|
3821
3705
|
readonly durable: boolean;
|
|
3822
3706
|
/**
|
|
3823
|
-
* Bind the durable x402 settlement state spending is gated on
|
|
3707
|
+
* Bind the durable x402 settlement state spending is gated on.
|
|
3824
3708
|
*
|
|
3825
3709
|
* Optional because a host may wire a ledger implementation that has no such
|
|
3826
3710
|
* gate; the SDK's own two both do. See
|
|
@@ -3829,7 +3713,6 @@ interface CreditLedgerLike {
|
|
|
3829
3713
|
useX402SettlementGate?(gate: X402RefundSettlementGate): void;
|
|
3830
3714
|
/**
|
|
3831
3715
|
* Bind the outbox that reports credit-expiry releases and their revivals
|
|
3832
|
-
* (internal-review).
|
|
3833
3716
|
*
|
|
3834
3717
|
* Optional, and absent on `MemoryCreditLedger`: an expiry release is a
|
|
3835
3718
|
* durable liability fact, and a ledger whose balances do not survive a
|
|
@@ -3838,7 +3721,7 @@ interface CreditLedgerLike {
|
|
|
3838
3721
|
*/
|
|
3839
3722
|
useCreditExpiryReleaseOutbox?(outbox: CreditExpiryReleaseOutbox): void;
|
|
3840
3723
|
/**
|
|
3841
|
-
* Release the undrawn remainder of every credit past its TTL
|
|
3724
|
+
* Release the undrawn remainder of every credit past its TTL.
|
|
3842
3725
|
* Optional on the same terms as the binder above. See
|
|
3843
3726
|
* {@link CreditLedger.sweepExpiredCredits}.
|
|
3844
3727
|
*/
|
|
@@ -3850,7 +3733,7 @@ interface CreditLedgerLike {
|
|
|
3850
3733
|
}>;
|
|
3851
3734
|
/**
|
|
3852
3735
|
* Ask that gate directly, so a route can refuse a wedged channel **before**
|
|
3853
|
-
* the rail moves anything
|
|
3736
|
+
* the rail moves anything. Optional on the same terms as the
|
|
3854
3737
|
* binder above; an implementation without it simply gets no preflight, and
|
|
3855
3738
|
* the ledger effect stays the authority. See
|
|
3856
3739
|
* {@link CreditLedger.blockingX402Refund}.
|
|
@@ -4034,9 +3917,9 @@ interface CreditLedgerLike {
|
|
|
4034
3917
|
drainId: string;
|
|
4035
3918
|
}): Promise<CreditDrainRecord | undefined>;
|
|
4036
3919
|
listPendingDrains(): Promise<CreditDrainRecord[]>;
|
|
4037
|
-
/** See {@link CreditLedger.bitcoinDepositLiability} — the in-kind deposit floor
|
|
3920
|
+
/** See {@link CreditLedger.bitcoinDepositLiability} — the in-kind deposit floor. */
|
|
4038
3921
|
bitcoinDepositLiability(): Promise<BitcoinDepositLiability>;
|
|
4039
|
-
/** One credit's undepleted funding lots, oldest first
|
|
3922
|
+
/** One credit's undepleted funding lots, oldest first. */
|
|
4040
3923
|
listFundingLots(creditId: string): Promise<FundingLot[]>;
|
|
4041
3924
|
listChannelDrains(args: {
|
|
4042
3925
|
limit: number;
|
|
@@ -4098,14 +3981,14 @@ interface CreditLedgerLike {
|
|
|
4098
3981
|
interface CreditLedgerQuerier {
|
|
4099
3982
|
query: Pool["query"];
|
|
4100
3983
|
}
|
|
4101
|
-
/** Reporter outbox joined to a draw release's own transaction
|
|
3984
|
+
/** Reporter outbox joined to a draw release's own transaction. */
|
|
4102
3985
|
interface CreditDrawReleaseOutbox {
|
|
4103
3986
|
/** Platform DVM record ID bound into the report. */
|
|
4104
3987
|
dvmId: string;
|
|
4105
3988
|
/** Reporter-owned insert executed through the ledger transaction. */
|
|
4106
3989
|
enqueue: CreditDrawReleaseEnqueue;
|
|
4107
3990
|
}
|
|
4108
|
-
/** Reporter seam for credit-expiry releases and the revivals that reverse them
|
|
3991
|
+
/** Reporter seam for credit-expiry releases and the revivals that reverse them. */
|
|
4109
3992
|
interface CreditExpiryReleaseOutbox {
|
|
4110
3993
|
/** Platform DVM record ID bound into the report. */
|
|
4111
3994
|
dvmId: string;
|
|
@@ -4114,7 +3997,7 @@ interface CreditExpiryReleaseOutbox {
|
|
|
4114
3997
|
}
|
|
4115
3998
|
/**
|
|
4116
3999
|
* One recorded expiry episode: a credit's undrawn remainder passing to the
|
|
4117
|
-
* builder when its TTL ran out
|
|
4000
|
+
* builder when its TTL ran out.
|
|
4118
4001
|
*
|
|
4119
4002
|
* `reversedAt` is set when a later funding revived the credit, at which point
|
|
4120
4003
|
* the release stops counting against committed value — the row stays as the
|
|
@@ -4148,11 +4031,11 @@ type CreditStatus = "active" | "unbacked";
|
|
|
4148
4031
|
/** Draw lifecycle: two-phase hold → terminal settle/release. */
|
|
4149
4032
|
type DrawStatus = "pending" | "settled" | "released";
|
|
4150
4033
|
/**
|
|
4151
|
-
* Rails a drain can pay out on (
|
|
4034
|
+
* Rails a drain can pay out on (the reclaim contract).
|
|
4152
4035
|
*
|
|
4153
|
-
* Direct Lightning payout is deliberately absent
|
|
4036
|
+
* Direct Lightning payout is deliberately absent: a
|
|
4154
4037
|
* first-party deployment holds no send-capable Lightning credential by design
|
|
4155
|
-
* (the funding NWC is receive-only
|
|
4038
|
+
* (the funding NWC is receive-only), so P2PK-locked Cashu notes are
|
|
4156
4039
|
* the only non-channel Bitcoin reclaim path. Adding `lightning` back means
|
|
4157
4040
|
* re-deciding that, not just widening a union.
|
|
4158
4041
|
*/
|
|
@@ -4167,7 +4050,7 @@ type DrainMethod = "cashu" | "x402" | "tempo";
|
|
|
4167
4050
|
*/
|
|
4168
4051
|
type DrainStatus = "pending" | "parked" | "picked_up" | "sent" | "released";
|
|
4169
4052
|
/**
|
|
4170
|
-
* The sats a DVM owes back on undrawn non-channel Bitcoin credit
|
|
4053
|
+
* The sats a DVM owes back on undrawn non-channel Bitcoin credit —
|
|
4171
4054
|
* the deposit pot inside the hub's balance, which the operator's sweep may
|
|
4172
4055
|
* never bank below.
|
|
4173
4056
|
*/
|
|
@@ -4202,7 +4085,7 @@ interface BitcoinDepositLiability {
|
|
|
4202
4085
|
}
|
|
4203
4086
|
/**
|
|
4204
4087
|
* What it cost to put a just-in-time-minted refund in the caller's hands
|
|
4205
|
-
*
|
|
4088
|
+
* itemized on the drain row so the spend is auditable against the
|
|
4206
4089
|
* hub's own transaction history long after the worker's log has rotated.
|
|
4207
4090
|
*
|
|
4208
4091
|
* `faceSats` is what the caller receives and equals the drain's published
|
|
@@ -4242,10 +4125,10 @@ interface CreditDrainRecord {
|
|
|
4242
4125
|
* The method alone does not say who settles a reclaim: an `mpp` or `x402`
|
|
4243
4126
|
* drain on a channel-bound credit is closed by the channel itself, and a
|
|
4244
4127
|
* `pending` one is routinely mid-reconciliation rather than owed by anybody
|
|
4245
|
-
*
|
|
4128
|
+
* `completeTempoDrain` leaves every ambiguous close pending on purpose for
|
|
4246
4129
|
* `recoverTempoSessionClose` to finish on the caller's next poll. Carrying
|
|
4247
4130
|
* the binding on the record is what lets a reader tell that apart from a
|
|
4248
|
-
* one-payment reclaim only a person can settle
|
|
4131
|
+
* one-payment reclaim only a person can settle.
|
|
4249
4132
|
*/
|
|
4250
4133
|
channelId: string | null;
|
|
4251
4134
|
/** Method-specific payout target as signed by the caller. */
|
|
@@ -4257,12 +4140,11 @@ interface CreditDrainRecord {
|
|
|
4257
4140
|
* `null` on a rail that reports no native basis. This — not `amountMicro` —
|
|
4258
4141
|
* is what an on-chain payout must be sized against, because the fiat figure
|
|
4259
4142
|
* and the rail figure drift with the rate between funding and drain
|
|
4260
|
-
* (internal-review).
|
|
4261
4143
|
*/
|
|
4262
4144
|
drainedNative: number | null;
|
|
4263
4145
|
/**
|
|
4264
4146
|
* What this reclaim owes in satoshis, computed from the credit's funding
|
|
4265
|
-
* lots when it was requested and never re-priced
|
|
4147
|
+
* lots when it was requested and never re-priced: the deposited
|
|
4266
4148
|
* sats, pro rata to the share of the credit being reclaimed, floored per
|
|
4267
4149
|
* lot. `null` on a channel rail (in-kind structurally, through the escrow)
|
|
4268
4150
|
* and on a Bitcoin credit whose lots cannot price it — that one falls back
|
|
@@ -4283,7 +4165,7 @@ interface CreditDrainRecord {
|
|
|
4283
4165
|
/** Settlement evidence, present on `sent`. */
|
|
4284
4166
|
sentRef: Record<string, unknown> | null;
|
|
4285
4167
|
/**
|
|
4286
|
-
* How a parked refund was sourced and what delivering it cost
|
|
4168
|
+
* How a parked refund was sourced and what delivering it cost.
|
|
4287
4169
|
*
|
|
4288
4170
|
* `null` on an accumulator park — there the consumed rows *are* the record —
|
|
4289
4171
|
* and on every non-cashu rail. Set only where the notes were minted just in
|
|
@@ -4301,7 +4183,7 @@ interface CreditDrainRecord {
|
|
|
4301
4183
|
/** When an unfulfilled Tempo drain was restored to the credit balance. */
|
|
4302
4184
|
releasedAt: number | null;
|
|
4303
4185
|
/**
|
|
4304
|
-
* Why an operator closed this drain out without booking it
|
|
4186
|
+
* Why an operator closed this drain out without booking it, and
|
|
4305
4187
|
* when. Set only on a channel drain the payout floor refused: the chain paid
|
|
4306
4188
|
* the caller less than this ledger was extinguishing, the operator reviewed
|
|
4307
4189
|
* the two figures and is not booking the difference.
|
|
@@ -4336,7 +4218,6 @@ interface DrainWriteOff {
|
|
|
4336
4218
|
drain: CreditDrainRecord;
|
|
4337
4219
|
written: boolean;
|
|
4338
4220
|
}
|
|
4339
|
-
/** Result of restoring an unfulfilled Tempo drain to its credit. */
|
|
4340
4221
|
interface DrainReleaseResult {
|
|
4341
4222
|
drain: CreditDrainRecord;
|
|
4342
4223
|
credit: CreditSnapshot;
|
|
@@ -4344,7 +4225,7 @@ interface DrainReleaseResult {
|
|
|
4344
4225
|
}
|
|
4345
4226
|
/**
|
|
4346
4227
|
* Result of a terminal drain transition — {@link CreditLedger.markDrainPickedUp}
|
|
4347
|
-
* and {@link CreditLedger.markDrainSent}
|
|
4228
|
+
* and {@link CreditLedger.markDrainSent}.
|
|
4348
4229
|
*
|
|
4349
4230
|
* The record alone can't answer "did I move this money", because the CAS
|
|
4350
4231
|
* winner and an idempotent replay return the same row. Anything that must
|
|
@@ -4356,7 +4237,6 @@ interface DrainTransitionResult {
|
|
|
4356
4237
|
/** True when the drain was already terminal and this call changed nothing. */
|
|
4357
4238
|
replayed: boolean;
|
|
4358
4239
|
}
|
|
4359
|
-
/** Result of {@link CreditLedger.requestDrain}. */
|
|
4360
4240
|
interface DrainRequestResult {
|
|
4361
4241
|
drain: CreditDrainRecord;
|
|
4362
4242
|
/** The credit as of this call — balance already debited on a fresh drain. */
|
|
@@ -4381,7 +4261,6 @@ interface CreditSnapshot {
|
|
|
4381
4261
|
* `availableMicro` in the funding rail's own units — the ceiling any
|
|
4382
4262
|
* rail-denominated payout must respect. `null` marks a rail that reports no
|
|
4383
4263
|
* native basis, which is why a channel drain refuses rather than guessing
|
|
4384
|
-
* (internal-review).
|
|
4385
4264
|
*/
|
|
4386
4265
|
nativeAvailable: number | null;
|
|
4387
4266
|
expiryMs: number;
|
|
@@ -4391,7 +4270,7 @@ interface CreditSnapshot {
|
|
|
4391
4270
|
lastLedgerSeq: number;
|
|
4392
4271
|
createdAt: number;
|
|
4393
4272
|
/**
|
|
4394
|
-
* The rail this balance was funded on
|
|
4273
|
+
* The rail this balance was funded on; `null` on a credit opened
|
|
4395
4274
|
* before rail basis was recorded, which conflicts with nothing. Exposed so a
|
|
4396
4275
|
* route can refuse a cross-rail top-up **before** taking the payment `fund`
|
|
4397
4276
|
* would then refuse `rail_mismatch`.
|
|
@@ -4403,7 +4282,7 @@ interface CreditSnapshot {
|
|
|
4403
4282
|
x402ChannelId: string | null;
|
|
4404
4283
|
}
|
|
4405
4284
|
/**
|
|
4406
|
-
* Result of a draw — carries the receipt tuple the
|
|
4285
|
+
* Result of a draw — carries the receipt tuple the countersignature
|
|
4407
4286
|
* consumes (`ReceiptCredit`: `draw_id`, `amount`, `balance_after`,
|
|
4408
4287
|
* `ledger_seq`). `balanceAfterMicro` and `ledgerSeq` are the values recorded
|
|
4409
4288
|
* when the draw was first placed; a replay returns them unchanged.
|
|
@@ -4419,13 +4298,13 @@ interface DrawResult {
|
|
|
4419
4298
|
status: DrawStatus;
|
|
4420
4299
|
/** True when this call was an idempotent replay of an already-recorded state. */
|
|
4421
4300
|
replayed: boolean;
|
|
4422
|
-
/** Rail value allocated to this draw, plus the credit's rail identity
|
|
4301
|
+
/** Rail value allocated to this draw, plus the credit's rail identity. */
|
|
4423
4302
|
railValue: DrawRailValue;
|
|
4424
4303
|
/** When the draw reached its terminal state; `null` while pending. */
|
|
4425
4304
|
resolvedAt: number | null;
|
|
4426
4305
|
}
|
|
4427
4306
|
/**
|
|
4428
|
-
* The rail-native slice of a credit that one draw carries
|
|
4307
|
+
* The rail-native slice of a credit that one draw carries — what
|
|
4429
4308
|
* makes a settled draw bookable as a revenue event on the funding's rail.
|
|
4430
4309
|
*
|
|
4431
4310
|
* Allocated at draw time as `remaining × amountMicro / availableMicro`, where
|
|
@@ -4441,7 +4320,7 @@ interface DrawRailValue {
|
|
|
4441
4320
|
drawNative: number | null;
|
|
4442
4321
|
/**
|
|
4443
4322
|
* Rail that funded the credit — a {@link FundingMethod} on any row `fund`
|
|
4444
|
-
* wrote, `null` on one it opened before
|
|
4323
|
+
* wrote, `null` on one it opened before recorded the column. Stays
|
|
4445
4324
|
* `string` rather than the union: this is a database read, and a fleet
|
|
4446
4325
|
* mid-rollout can hold a rail a newer build wrote ({@link isFundingRail}).
|
|
4447
4326
|
*/
|
|
@@ -4456,7 +4335,7 @@ interface DrawRailValue {
|
|
|
4456
4335
|
creditCurrency: string | null;
|
|
4457
4336
|
}
|
|
4458
4337
|
/**
|
|
4459
|
-
* Result of `growDraw`
|
|
4338
|
+
* Result of `growDraw` — the draw's post-growth tuple, plus the
|
|
4460
4339
|
* slice this top-up added. The added slice is what the mid-job rail result
|
|
4461
4340
|
* reports as its `paidMsats` delta: the job's counters accumulate increments,
|
|
4462
4341
|
* not the running total the draw now holds.
|
|
@@ -4470,7 +4349,7 @@ interface GrownDrawResult extends DrawResult {
|
|
|
4470
4349
|
/** Fiat micro this growth added — `amountMicro` minus the pre-growth amount. */
|
|
4471
4350
|
addedAmountMicro: number;
|
|
4472
4351
|
/**
|
|
4473
|
-
* Fiat micro the
|
|
4352
|
+
* Fiat micro the cap refused, because growing by it would have
|
|
4474
4353
|
* pushed the draw past what the job cumulatively asked. Zero on every
|
|
4475
4354
|
* ordinary top-up. Non-zero means money landed on the credit that this job
|
|
4476
4355
|
* did not buy anything with — it stays the caller's available balance, and
|
|
@@ -4491,7 +4370,7 @@ interface DrawRecord extends Omit<DrawResult, "replayed"> {
|
|
|
4491
4370
|
createdAt: number;
|
|
4492
4371
|
/**
|
|
4493
4372
|
* What `allocateDrawValue` allocated this draw when the payment landed
|
|
4494
|
-
*
|
|
4373
|
+
* the pro-rata slice of the credit's pooled rail value that
|
|
4495
4374
|
* `withDrawBasis` mirrored onto the job's `paidMsats` counter.
|
|
4496
4375
|
*
|
|
4497
4376
|
* Equal to `railValue.drawMsats` on every draw the settle did not re-price,
|
|
@@ -4504,8 +4383,8 @@ interface DrawRecord extends Omit<DrawResult, "replayed"> {
|
|
|
4504
4383
|
allocatedMsats: number;
|
|
4505
4384
|
}
|
|
4506
4385
|
/**
|
|
4507
|
-
* Keyset cursor into {@link CreditLedgerLike.listStalePendingDraws}
|
|
4508
|
-
*
|
|
4386
|
+
* Keyset cursor into {@link CreditLedgerLike.listStalePendingDraws}, holding the
|
|
4387
|
+
* sort key of the last row a caller examined; offset paging would not
|
|
4509
4388
|
* do: the scan skips holds it can't resolve (their job row exists), so those
|
|
4510
4389
|
* rows stay `pending` and reappear at the head of every subsequent page. The
|
|
4511
4390
|
* tuple is `(createdAt, creditId, ledgerSeq)`, matching the read's `ORDER BY`;
|
|
@@ -4518,7 +4397,7 @@ interface StalePendingDrawCursor {
|
|
|
4518
4397
|
ledgerSeq: number;
|
|
4519
4398
|
}
|
|
4520
4399
|
/**
|
|
4521
|
-
* Rail value one funding contributes to a credit
|
|
4400
|
+
* Rail value one funding contributes to a credit. Recorded so a
|
|
4522
4401
|
* later draw can be allocated its share of what the rail actually paid, and so
|
|
4523
4402
|
* the platform can book the funding as a deposit.
|
|
4524
4403
|
*/
|
|
@@ -4527,11 +4406,11 @@ interface CreditFundingBasis {
|
|
|
4527
4406
|
* The rail whose value this funding carries. A top-up on another rail is
|
|
4528
4407
|
* refused (`rail_mismatch`).
|
|
4529
4408
|
*
|
|
4530
|
-
* Narrowed from `string` to {@link FundingMethod} by
|
|
4409
|
+
* Narrowed from `string` to {@link FundingMethod} by — the same type
|
|
4531
4410
|
* {@link FUNDING_RAILS} is keyed by — so a rail cannot enter `credits.rail`
|
|
4532
4411
|
* that the terminal has no way to book revenue under. That silently costs
|
|
4533
4412
|
* every draw the credit backs its booking, which is what happened when
|
|
4534
|
-
* `lightning` reached the ledger before the reader's allow-list
|
|
4413
|
+
* `lightning` reached the ledger before the reader's allow-list.
|
|
4535
4414
|
*/
|
|
4536
4415
|
rail: FundingMethod;
|
|
4537
4416
|
/** Rail payment value in millisatoshis. */
|
|
@@ -4565,14 +4444,14 @@ interface CreditFundArgs {
|
|
|
4565
4444
|
amountMicro: number;
|
|
4566
4445
|
/** Absolute expiry, ms since epoch. Overwrites the previous value on top-up. */
|
|
4567
4446
|
expiryMs: number;
|
|
4568
|
-
/** Rail-value basis this funding contributes (
|
|
4447
|
+
/** Rail-value basis this funding contributes (required by ). */
|
|
4569
4448
|
basis: CreditFundingBasis;
|
|
4570
4449
|
/** External transaction handle — caller owns BEGIN/COMMIT (spec condition 3). */
|
|
4571
4450
|
tx?: CreditLedgerQuerier;
|
|
4572
4451
|
nowMs?: number;
|
|
4573
4452
|
}
|
|
4574
4453
|
/**
|
|
4575
|
-
* Allocate a draw's share of a credit's unspent rail value
|
|
4454
|
+
* Allocate a draw's share of a credit's unspent rail value. Pure —
|
|
4576
4455
|
* shared by the Postgres and in-memory ledgers so the two can't drift.
|
|
4577
4456
|
*
|
|
4578
4457
|
* `availableMicro` and both remainders must be net of pending holds; the
|
|
@@ -4587,7 +4466,7 @@ declare function allocateDrawValue(args: {
|
|
|
4587
4466
|
drawMsats: number;
|
|
4588
4467
|
drawNative: number | null;
|
|
4589
4468
|
};
|
|
4590
|
-
/** Full persisted `credit_fundings` row, camel-cased
|
|
4469
|
+
/** Full persisted `credit_fundings` row, camel-cased. */
|
|
4591
4470
|
interface FundingRecord {
|
|
4592
4471
|
creditId: string;
|
|
4593
4472
|
fundId: string;
|
|
@@ -4603,7 +4482,7 @@ interface FundingRecord {
|
|
|
4603
4482
|
receipt: FundingReceipt | null;
|
|
4604
4483
|
}
|
|
4605
4484
|
/**
|
|
4606
|
-
* Lifecycle of a Lightning funding invoice
|
|
4485
|
+
* Lifecycle of a Lightning funding invoice.
|
|
4607
4486
|
*
|
|
4608
4487
|
* Only `pending` is live; everything else is terminal. The two that carry no
|
|
4609
4488
|
* balance carry opposite money: `expired` was never paid and owes nobody
|
|
@@ -4611,7 +4490,7 @@ interface FundingRecord {
|
|
|
4611
4490
|
* operator. Both exist so that a row the sweep can never advance stops being
|
|
4612
4491
|
* swept.
|
|
4613
4492
|
*
|
|
4614
|
-
* `reconciled` and `written_off`
|
|
4493
|
+
* `reconciled` and `written_off` are where a `blocked` row goes once
|
|
4615
4494
|
* that operator acts — respectively, the money was credited onto a credit they
|
|
4616
4495
|
* named, or they decided it would not be. Neither is `settled`: that one means
|
|
4617
4496
|
* the ledger applied the payment to the top-up the caller asked for, and
|
|
@@ -4619,7 +4498,7 @@ interface FundingRecord {
|
|
|
4619
4498
|
* human had to intervene.
|
|
4620
4499
|
*/
|
|
4621
4500
|
type CreditInvoiceStatus = "pending" | "settled" | "expired" | "blocked" | "reconciled" | "written_off";
|
|
4622
|
-
/** Full persisted `credit_invoices` row, camel-cased
|
|
4501
|
+
/** Full persisted `credit_invoices` row, camel-cased. */
|
|
4623
4502
|
interface CreditInvoiceRecord {
|
|
4624
4503
|
creditId: string;
|
|
4625
4504
|
fundId: string;
|
|
@@ -4638,7 +4517,7 @@ interface CreditInvoiceRecord {
|
|
|
4638
4517
|
* trail for why a human had to touch this row at all.
|
|
4639
4518
|
*/
|
|
4640
4519
|
blockedReason: string | null;
|
|
4641
|
-
/** Credit an operator sent a blocked invoice's money to
|
|
4520
|
+
/** Credit an operator sent a blocked invoice's money to. */
|
|
4642
4521
|
reconciledCreditId: string | null;
|
|
4643
4522
|
/** Funding key on that credit — the payment hash. See `reconcileBlockedInvoice`. */
|
|
4644
4523
|
reconciledFundId: string | null;
|
|
@@ -4652,18 +4531,18 @@ interface CreditInvoiceRecord {
|
|
|
4652
4531
|
/** When the payment landed at the wallet — never the instant an operator acted on it. */
|
|
4653
4532
|
settledAt: number | null;
|
|
4654
4533
|
}
|
|
4655
|
-
/** Outcome of applying an observed settlement to the ledger
|
|
4534
|
+
/** Outcome of applying an observed settlement to the ledger. */
|
|
4656
4535
|
interface InvoiceSettlement {
|
|
4657
4536
|
invoice: CreditInvoiceRecord;
|
|
4658
|
-
/** The `credit_fundings` row; absent only if a
|
|
4537
|
+
/** The `credit_fundings` row; absent only if a legacy row somehow lacks one. */
|
|
4659
4538
|
funding: FundingRecord | undefined;
|
|
4660
4539
|
credit: CreditSnapshot | undefined;
|
|
4661
4540
|
/** True when this settlement had already been applied — nothing moved. */
|
|
4662
4541
|
replayed: boolean;
|
|
4663
4542
|
}
|
|
4664
4543
|
/**
|
|
4665
|
-
* Outcome of an operator crediting a blocked invoice onto a credit they named
|
|
4666
|
-
*
|
|
4544
|
+
* Outcome of an operator crediting a blocked invoice onto a credit they named;
|
|
4545
|
+
* it has the same shape as {@link InvoiceSettlement}, but `funding` and
|
|
4667
4546
|
* `credit` describe the **target** credit, not the one the invoice was minted
|
|
4668
4547
|
* against.
|
|
4669
4548
|
*/
|
|
@@ -4689,7 +4568,7 @@ interface BlockedInvoiceCursor {
|
|
|
4689
4568
|
/** Typed failure codes for {@link CreditLedgerError}. */
|
|
4690
4569
|
type CreditLedgerErrorCode = "credit_not_found" | "credit_expired" | "credit_unbacked" | "tempo_channel_closing" | "tempo_settlement_pending" | "settlement_pending" | "insufficient_credit" | "draw_conflict" | "draw_not_found" | "invalid_draw_state" | "funding_replayed" | "currency_mismatch" | "caller_mismatch" | "rail_mismatch" | "invalid_amount" | "invalid_expiry" | "invalid_basis" | "nothing_to_drain" | "drain_below_dust" | "drain_not_found" | "drain_conflict" | "invalid_drain_state" | "invoice_not_found" | "invoice_conflict" | "invoice_not_blocked" | "below_rail_minimum";
|
|
4691
4570
|
/**
|
|
4692
|
-
* Which conflict a `drain_conflict` is, for the routes that answer one
|
|
4571
|
+
* Which conflict a `drain_conflict` is, for the routes that answer one.
|
|
4693
4572
|
*
|
|
4694
4573
|
* One code covers refusals whose only common property is that no drain was
|
|
4695
4574
|
* booked; the copy a caller relays to a human differs entirely between them.
|
|
@@ -4702,7 +4581,7 @@ type CreditLedgerErrorCode = "credit_not_found" | "credit_expired" | "credit_unb
|
|
|
4702
4581
|
* `balance_moved` roll back with nothing on any chain and clear on their own;
|
|
4703
4582
|
* `refund_floor` is the opposite — the cooperative refund reached the chain and
|
|
4704
4583
|
* paid short, so the caller's money moved and only the operator repair resolves
|
|
4705
|
-
* it
|
|
4584
|
+
* it. A route's `retryable` and `drain_registered` follow from which
|
|
4706
4585
|
* one it is, so the tag has to reach it.
|
|
4707
4586
|
*
|
|
4708
4587
|
* Absent means the duplicate-payout conflict `PAYMENT_ERROR_COPY.drain_conflict`
|
|
@@ -4740,13 +4619,13 @@ interface CreditLedgerErrorDetails {
|
|
|
4740
4619
|
settlementId?: string;
|
|
4741
4620
|
/** On `settlement_pending`: that settlement's status, so an operator sees which repair applies. */
|
|
4742
4621
|
settlementStatus?: string;
|
|
4743
|
-
/** On `settlement_pending`: the drain id that settlement is under — the one id this gate admits
|
|
4622
|
+
/** On `settlement_pending`: the drain id that settlement is under — the one id this gate admits. */
|
|
4744
4623
|
blockingDrainId?: string;
|
|
4745
4624
|
}
|
|
4746
4625
|
/**
|
|
4747
4626
|
* Thrown by every {@link CreditLedger} method on refusal. Carries a `code`
|
|
4748
4627
|
* discriminator (plus structured `details`) so callers branch on a field
|
|
4749
|
-
* instead of string-matching messages — the
|
|
4628
|
+
* instead of string-matching messages — the quote surface maps
|
|
4750
4629
|
* `insufficient_credit` + `details.availableMicro` onto the structured
|
|
4751
4630
|
* 402-class wire error.
|
|
4752
4631
|
*/
|
|
@@ -4822,14 +4701,14 @@ interface TempoSessionLifecycle {
|
|
|
4822
4701
|
* parent-credit lock through the same client.
|
|
4823
4702
|
*
|
|
4824
4703
|
* {@link withVoucherAcceptance} acquires its pooled client **lazily**, on the
|
|
4825
|
-
* first store mutation rather than up front
|
|
4704
|
+
* first store mutation rather than up front. Its `operation` is
|
|
4826
4705
|
* mppx's credential verification, which does the chain work before it touches
|
|
4827
4706
|
* the store: an `open` submits the escrow transaction and awaits its receipt,
|
|
4828
4707
|
* a `voucher` reads channel state over public RPC. Holding a connection across
|
|
4829
4708
|
* that starves everything else on the shared host pool — `/v1/job`, the job
|
|
4830
4709
|
* store, KV, the credit ledger, the replay store — and exposes the open
|
|
4831
4710
|
* transaction to `idle_in_transaction_session_timeout`. This is the same shape
|
|
4832
|
-
*
|
|
4711
|
+
* removed from the x402 settlement path. Laziness costs nothing in
|
|
4833
4712
|
* atomicity: the `FOR UPDATE` row lock was always taken at the first mutation,
|
|
4834
4713
|
* never at `BEGIN`, so the critical section is unchanged — only the
|
|
4835
4714
|
* connection-holding window shrinks to the database work it actually covers.
|
|
@@ -4933,14 +4812,14 @@ interface MppOpts {
|
|
|
4933
4812
|
/**
|
|
4934
4813
|
* When set, only register MPP methods whose name appears in this list, even
|
|
4935
4814
|
* if the per-rail env var (`DVMKIT_TEMPO_RECIPIENT`) is configured
|
|
4936
|
-
*
|
|
4815
|
+
* Lets operators temporarily disable a rail without unsetting
|
|
4937
4816
|
* other knobs. Empty/undefined falls back to "register everything that has
|
|
4938
4817
|
* a configured recipient".
|
|
4939
4818
|
*/
|
|
4940
4819
|
methodsAllowlist?: string[];
|
|
4941
4820
|
/**
|
|
4942
4821
|
* Durable replay protection for the one-shot `tempo/charge` method
|
|
4943
|
-
*
|
|
4822
|
+
* Omit and mppx falls back to `Store.memory()`, whose consumed
|
|
4944
4823
|
* transaction hashes are per-process — invisible to sibling machines and lost
|
|
4945
4824
|
* on restart. Pass a cross-machine store (`PostgresTempoChargeStore`) on any
|
|
4946
4825
|
* multi-instance deploy.
|
|
@@ -4970,7 +4849,7 @@ interface MppOpts {
|
|
|
4970
4849
|
amount?: string | bigint;
|
|
4971
4850
|
intervalMs?: number;
|
|
4972
4851
|
/**
|
|
4973
|
-
* How long a settlement holds its in-flight lease
|
|
4852
|
+
* How long a settlement holds its in-flight lease. Defaults to
|
|
4974
4853
|
* {@link TEMPO_SETTLEMENT_LEASE_MS}, which documents the receipt-timeout
|
|
4975
4854
|
* floor an override has to stay above.
|
|
4976
4855
|
*/
|
|
@@ -5031,7 +4910,7 @@ interface MppxServer {
|
|
|
5031
4910
|
* Reconcile active TIP-1034 channels; present only on a durable session
|
|
5032
4911
|
* handle. `inFlight` counts channels the sweep found due but declined to
|
|
5033
4912
|
* settle because another path already holds their settlement lease
|
|
5034
|
-
*
|
|
4913
|
+
* a deferral, not a failure.
|
|
5035
4914
|
*/
|
|
5036
4915
|
sweepTempoSessions?: () => Promise<{
|
|
5037
4916
|
scanned: number;
|
|
@@ -5041,7 +4920,7 @@ interface MppxServer {
|
|
|
5041
4920
|
}>;
|
|
5042
4921
|
/**
|
|
5043
4922
|
* Reconcile and, if the channel is at risk, settle exactly one TIP-1034
|
|
5044
|
-
* channel
|
|
4923
|
+
* channel. The forced-close protection path: a verified on-chain
|
|
5045
4924
|
* `CloseRequested` event authorises this and nothing else.
|
|
5046
4925
|
*
|
|
5047
4926
|
* Needs no `listActive`, unlike {@link sweepTempoSessions} — a store that
|
|
@@ -5074,7 +4953,7 @@ interface MppxServer {
|
|
|
5074
4953
|
/** Recover a close result after a process failure between chain and ledger commits. */
|
|
5075
4954
|
recoverTempoSessionClose?: (channelId: string, drainId: string) => Promise<string | null>;
|
|
5076
4955
|
/**
|
|
5077
|
-
* Read a channel's close intent without touching it
|
|
4956
|
+
* Read a channel's close intent without touching it.
|
|
5078
4957
|
*
|
|
5079
4958
|
* The operator repair needs the reference a confirmed close already carries,
|
|
5080
4959
|
* and it must not be `recoverTempoSessionClose`: that one *writes* — an
|
|
@@ -5086,14 +4965,14 @@ interface MppxServer {
|
|
|
5086
4965
|
/** Read terminally consumed value for an exact cooperative-close challenge. */
|
|
5087
4966
|
getTempoSessionSpent?: (channelId: string) => Promise<bigint>;
|
|
5088
4967
|
/**
|
|
5089
|
-
* Read the immutable chain binding of a stored channel
|
|
4968
|
+
* Read the immutable chain binding of a stored channel, or `null`
|
|
5090
4969
|
* when this DVM holds no such channel. What a close event must match before
|
|
5091
4970
|
* it may authorise anything.
|
|
5092
4971
|
*/
|
|
5093
4972
|
getTempoSessionBinding?: (channelId: string) => Promise<TempoChannelBinding | null>;
|
|
5094
4973
|
/**
|
|
5095
4974
|
* Fetch a transaction receipt from this DVM's **own** configured Tempo RPC
|
|
5096
|
-
*
|
|
4975
|
+
* the independent read that makes a close-event locator
|
|
5097
4976
|
* self-verifying rather than something the platform asserts.
|
|
5098
4977
|
*/
|
|
5099
4978
|
getTempoReceipt?: (args: {
|
|
@@ -5107,7 +4986,7 @@ interface MppxServer {
|
|
|
5107
4986
|
}[];
|
|
5108
4987
|
} | null>;
|
|
5109
4988
|
/**
|
|
5110
|
-
* Read what a landed cooperative close actually paid out
|
|
4989
|
+
* Read what a landed cooperative close actually paid out.
|
|
5111
4990
|
*
|
|
5112
4991
|
* mppx decodes `ChannelClosed` while verifying the close credential and then
|
|
5113
4992
|
* drops both amounts — its session receipt carries only the channel, the
|
|
@@ -5132,7 +5011,7 @@ interface TempoChannelCloseAmounts {
|
|
|
5132
5011
|
refundedToPayer: bigint;
|
|
5133
5012
|
}
|
|
5134
5013
|
/**
|
|
5135
|
-
* What a targeted single-channel settlement did
|
|
5014
|
+
* What a targeted single-channel settlement did.
|
|
5136
5015
|
*
|
|
5137
5016
|
* The platform's close observer acknowledges its durable event on a terminal
|
|
5138
5017
|
* outcome and retries otherwise, so the distinctions here are a delivery
|
|
@@ -5140,16 +5019,16 @@ interface TempoChannelCloseAmounts {
|
|
|
5140
5019
|
*
|
|
5141
5020
|
* - `settled` — a settlement transaction landed for this channel.
|
|
5142
5021
|
* - `already_safe` — the on-chain watermark already covers every accepted
|
|
5143
|
-
*
|
|
5022
|
+
* voucher, so there is nothing to protect. A replay lands here.
|
|
5144
5023
|
* - `unknown_channel` — not in this DVM's durable store. Terminal: a DVM must
|
|
5145
|
-
*
|
|
5024
|
+
* never settle a channel it does not own.
|
|
5146
5025
|
* - `finalized_before_protection` — the channel finalized while it still owed
|
|
5147
|
-
*
|
|
5148
|
-
*
|
|
5149
|
-
*
|
|
5026
|
+
* us value. A **money incident**, not a success: the grace period elapsed
|
|
5027
|
+
* without settlement and the deposit is gone. Preserved and paged, never
|
|
5028
|
+
* quietly acknowledged.
|
|
5150
5029
|
* - `retryable_failure` — a chain read or settlement attempt failed, or another
|
|
5151
|
-
*
|
|
5152
|
-
*
|
|
5030
|
+
* path is already broadcasting a settlement for this channel. The
|
|
5031
|
+
* event stays pending and is retried inside the grace period.
|
|
5153
5032
|
*/
|
|
5154
5033
|
type TempoChannelSettlementOutcome = {
|
|
5155
5034
|
outcome: "settled";
|
|
@@ -5174,7 +5053,6 @@ type TempoChannelSettlementOutcome = {
|
|
|
5174
5053
|
};
|
|
5175
5054
|
/**
|
|
5176
5055
|
* The immutable chain identity a TIP-1034 channel was opened against
|
|
5177
|
-
* (internal-review).
|
|
5178
5056
|
*
|
|
5179
5057
|
* Doubles as the close-event authorisation record and as what the DVM reports
|
|
5180
5058
|
* to the platform so a close can be routed back to it. `payee` is the DVM's
|
|
@@ -5233,7 +5111,6 @@ interface CanonicalEnvelope {
|
|
|
5233
5111
|
nonce: string;
|
|
5234
5112
|
auth_statement?: SignedRequestStatementHeader;
|
|
5235
5113
|
}
|
|
5236
|
-
/** Options for `createSignedRequestVerifier`. */
|
|
5237
5114
|
interface CreateSignedRequestVerifierOpts {
|
|
5238
5115
|
/** Fixed audience/operation for a custom signed route or standalone verifier. */
|
|
5239
5116
|
domain?: SignedRequestDomain;
|
|
@@ -5251,8 +5128,8 @@ interface CreateSignedRequestVerifierOpts {
|
|
|
5251
5128
|
/**
|
|
5252
5129
|
* Field names removed from the input before `schema` validates it — and
|
|
5253
5130
|
* **kept** in the canonical bytes the signature covers. For protocol-reserved
|
|
5254
|
-
* keys the caller signs but the schema never declares: the
|
|
5255
|
-
* envelope riding a capability schema
|
|
5131
|
+
* keys the caller signs but the schema never declares: the credit
|
|
5132
|
+
* envelope riding a capability schema. Defaults to none.
|
|
5256
5133
|
*
|
|
5257
5134
|
* This is the one place where "what is validated" and "what is signed"
|
|
5258
5135
|
* legitimately differ. Don't reach for it to paper over a schema mismatch —
|
|
@@ -5277,7 +5154,6 @@ interface SignedRequestReplayStore {
|
|
|
5277
5154
|
*/
|
|
5278
5155
|
checkAndRecord(pubkey: string, timestamp: number, nonce: string, now: number): Promise<boolean>;
|
|
5279
5156
|
}
|
|
5280
|
-
/** Options for the signer half. */
|
|
5281
5157
|
interface SignedRequestSignOpts {
|
|
5282
5158
|
/** Unix timestamp in seconds. Defaults to `now()`. */
|
|
5283
5159
|
timestamp?: number;
|
|
@@ -5285,17 +5161,16 @@ interface SignedRequestSignOpts {
|
|
|
5285
5161
|
nonce?: string;
|
|
5286
5162
|
}
|
|
5287
5163
|
/**
|
|
5288
|
-
* Round-trip verifier + signer for secp256k1+BIP-340 Schnorr-signed protocol
|
|
5289
|
-
* requests (internal-review, internal-review, internal-review).
|
|
5164
|
+
* Round-trip verifier + signer for secp256k1+BIP-340 Schnorr-signed protocol requests.
|
|
5290
5165
|
*
|
|
5291
5166
|
* Authentication is two-step so the replay nonce is committed iff a job is
|
|
5292
5167
|
* created, not on every request entry:
|
|
5293
5168
|
*
|
|
5294
5169
|
* 1. {@link checkAuth} runs schema → drift → signature at request entry on
|
|
5295
|
-
*
|
|
5170
|
+
* both `/v1/quote` and `/v1/job`. Sync; no replay-store touch.
|
|
5296
5171
|
* 2. {@link recordReplay} commits `(pubkey, timestamp, nonce)` to the replay
|
|
5297
|
-
*
|
|
5298
|
-
*
|
|
5172
|
+
* store. Called from `/v1/job` only, after upfront payment is verified
|
|
5173
|
+
* and immediately before `jobManager.createJob`.
|
|
5299
5174
|
*
|
|
5300
5175
|
* The unpaid `/v1/job` warmup probe (price discovery → 402) thus no longer
|
|
5301
5176
|
* burns the nonce — clients can re-submit the same envelope with a real
|
|
@@ -5310,7 +5185,7 @@ interface SignedRequestVerifier<T> {
|
|
|
5310
5185
|
checkAuth(input: unknown, domain?: SignedRequestDomain): T & CanonicalEnvelope;
|
|
5311
5186
|
/**
|
|
5312
5187
|
* Schema + signature check against `input`, without the drift window check
|
|
5313
|
-
* or replay-store touch
|
|
5188
|
+
* or replay-store touch. For the reactivation path where the
|
|
5314
5189
|
* persisted timestamp is from the original signing instant (could be hours
|
|
5315
5190
|
* or days ago) and the replay nonce was already committed at submission.
|
|
5316
5191
|
* Returns the verified envelope; throws {@link SignedRequestError} with
|
|
@@ -5341,7 +5216,7 @@ type SignedRequestFailure = "schema_invalid" | "timestamp_drift" | "signature_in
|
|
|
5341
5216
|
*
|
|
5342
5217
|
* The single definition of "which part of a schema failure is the envelope's":
|
|
5343
5218
|
* the post-parse shape check in `parse()` iterates it, and `authErrorBody`'s
|
|
5344
|
-
*
|
|
5219
|
+
* classifier reads its keys to decide whether a `schema_invalid` throw
|
|
5345
5220
|
* is the caller's *input* being wrong (disclosable: the schema is public on
|
|
5346
5221
|
* `/v1/info`) or their *signing* being wrong (folded into `signature_invalid`,
|
|
5347
5222
|
* one answer for every key and signature failure). `satisfies` pins it to
|
|
@@ -5362,7 +5237,7 @@ declare class SignedRequestError extends Error {
|
|
|
5362
5237
|
readonly sub_reason: SignedRequestFailure;
|
|
5363
5238
|
/**
|
|
5364
5239
|
* The Zod issues behind a `schema_invalid`, when the failure came from a
|
|
5365
|
-
* `safeParse` that produced any
|
|
5240
|
+
* `safeParse` that produced any. `authErrorBody` reads their
|
|
5366
5241
|
* paths to tell an input violation from an envelope one, and renders the
|
|
5367
5242
|
* input half into the caller-facing `display`. Absent on every other
|
|
5368
5243
|
* `sub_reason`, and on the `schema_invalid` throws that aren't a parse
|
|
@@ -5374,7 +5249,7 @@ declare class SignedRequestError extends Error {
|
|
|
5374
5249
|
constructor(message: string, sub_reason: SignedRequestFailure,
|
|
5375
5250
|
/**
|
|
5376
5251
|
* The Zod issues behind a `schema_invalid`, when the failure came from a
|
|
5377
|
-
* `safeParse` that produced any
|
|
5252
|
+
* `safeParse` that produced any. `authErrorBody` reads their
|
|
5378
5253
|
* paths to tell an input violation from an envelope one, and renders the
|
|
5379
5254
|
* input half into the caller-facing `display`. Absent on every other
|
|
5380
5255
|
* `sub_reason`, and on the `schema_invalid` throws that aren't a parse
|
|
@@ -5384,8 +5259,7 @@ declare class SignedRequestError extends Error {
|
|
|
5384
5259
|
issues?: readonly z.core.$ZodIssue[] | undefined);
|
|
5385
5260
|
}
|
|
5386
5261
|
/**
|
|
5387
|
-
* Build a secp256k1+BIP-340 Schnorr-over-canonical-JSON request verifier
|
|
5388
|
-
* (internal-review, internal-review, internal-review).
|
|
5262
|
+
* Build a secp256k1+BIP-340 Schnorr-over-canonical-JSON request verifier.
|
|
5389
5263
|
*
|
|
5390
5264
|
* Generalises cast's `canonicalSignedPayload` + `verifyCanonicalSignedRequest`
|
|
5391
5265
|
* into a reusable primitive — `(schema, opts) -> { verify, canonicalBytes, signRequest }`.
|
|
@@ -5394,10 +5268,10 @@ declare class SignedRequestError extends Error {
|
|
|
5394
5268
|
*/
|
|
5395
5269
|
declare function createSignedRequestVerifier<T = unknown>(schema: ZodLike<T>, opts?: CreateSignedRequestVerifierOpts): SignedRequestVerifier<T>;
|
|
5396
5270
|
/**
|
|
5397
|
-
* The wire object the caller signed, taken out of a request body
|
|
5271
|
+
* The wire object the caller signed, taken out of a request body.
|
|
5398
5272
|
*
|
|
5399
5273
|
* **The single definition of which bytes get verified, and every auth call site
|
|
5400
|
-
* reads it**: `/v1/quote`, the `/v1/job` submit, and the
|
|
5274
|
+
* reads it**: `/v1/quote`, the `/v1/job` submit, and the reactivation
|
|
5401
5275
|
* re-verify. They used to disagree — quote checked the raw `body.data`, submit
|
|
5402
5276
|
* checked `JobManager.parseInput`'s Zod output — so the two agreed only where
|
|
5403
5277
|
* the parse happened to be an identity on the caller's payload. A nested
|
|
@@ -5427,13 +5301,13 @@ declare function signedRequestInput(body: {
|
|
|
5427
5301
|
* cross-machine `SignedRequestReplayStore` is supplied. 10-minute retention
|
|
5428
5302
|
* window, 100k entry cap, per-process. Exported so `secp256k1Auth(...)` can
|
|
5429
5303
|
* pre-build one and share it across every per-schema verifier plus its own
|
|
5430
|
-
* `recordReplay` path
|
|
5304
|
+
* `recordReplay` path.
|
|
5431
5305
|
*
|
|
5432
5306
|
* When the cap is hit after the time-expired sweep, fresh inserts are
|
|
5433
5307
|
* **rejected** (return `true` — treated as replay at the wire) rather than
|
|
5434
5308
|
* silently evicting an in-window entry. Silent eviction would flush a
|
|
5435
5309
|
* still-valid nonce back to "unseen" and let an attacker who can drive cap
|
|
5436
|
-
* pressure replay it
|
|
5310
|
+
* pressure replay it. A rate-limited structured warning fires so
|
|
5437
5311
|
* operators see saturation in `fly logs`; reaching cap means in-memory has
|
|
5438
5312
|
* been pushed past where it's safe and the deploy should move to
|
|
5439
5313
|
* `PostgresReplayStore`.
|
|
@@ -5442,25 +5316,25 @@ declare function createDefaultReplayStore(): SignedRequestReplayStore;
|
|
|
5442
5316
|
|
|
5443
5317
|
/**
|
|
5444
5318
|
* A DVM-level auth scheme, declared on `DVMDescriptor.auth`. Authentication
|
|
5445
|
-
* is two-step
|
|
5319
|
+
* is two-step:
|
|
5446
5320
|
*
|
|
5447
5321
|
* 1. {@link checkAuth} fires at request entry on `/v1/quote` and `/v1/job`,
|
|
5448
|
-
*
|
|
5449
|
-
*
|
|
5450
|
-
*
|
|
5451
|
-
*
|
|
5322
|
+
* before payment verification. Schema / drift / signature checks only —
|
|
5323
|
+
* no replay-store touch. Unsigned / malformed / stale / wrong-sig
|
|
5324
|
+
* envelopes reject with HTTP 401 with no Cashu round-trip and no pending
|
|
5325
|
+
* revenue row.
|
|
5452
5326
|
* 2. {@link recordReplay} fires on `/v1/job` only, after upfront payment is
|
|
5453
|
-
*
|
|
5454
|
-
*
|
|
5455
|
-
*
|
|
5456
|
-
*
|
|
5327
|
+
* verified and immediately before `jobManager.createJob`. Commits the
|
|
5328
|
+
* `(pubkey, timestamp, nonce)` tuple to the replay store; throws 401
|
|
5329
|
+
* `replay_detected` on duplicate. The unpaid 402-discovery hop does not
|
|
5330
|
+
* burn the nonce, so clients can re-submit with payment.
|
|
5457
5331
|
*
|
|
5458
5332
|
* On `replay_detected` after payment was already accepted, the SDK responds
|
|
5459
5333
|
* 401 fail-closed uniformly across cashu / mppx / x402 — no rail-specific
|
|
5460
|
-
* refund or compensation logic
|
|
5334
|
+
* refund or compensation logic. The Cashu accept path
|
|
5461
5335
|
* commits proofs into the accumulator wallet inside `verifyUpfrontPayment`
|
|
5462
|
-
* before `recordReplay` runs
|
|
5463
|
-
*
|
|
5336
|
+
* before `recordReplay` runs. Unlocked Cashu is rejected upstream, so the
|
|
5337
|
+
* accumulator is the only production path and no proofs are held to
|
|
5464
5338
|
* refund; mppx / x402 credentials are single-use and already consumed by
|
|
5465
5339
|
* the facilitator.
|
|
5466
5340
|
*
|
|
@@ -5473,20 +5347,20 @@ declare function createDefaultReplayStore(): SignedRequestReplayStore;
|
|
|
5473
5347
|
* signature covers it. Those keys are the protocol's, not the capability's, so
|
|
5474
5348
|
* a scheme must not fail a schema that doesn't declare them — `secp256k1Auth`
|
|
5475
5349
|
* removes them for the schema check only, keeping the signing bytes verbatim
|
|
5476
|
-
*
|
|
5350
|
+
* A custom scheme owes callers the same tolerance, or every strict
|
|
5477
5351
|
* schema 401s on an explicit draw.
|
|
5478
5352
|
*/
|
|
5479
5353
|
/**
|
|
5480
|
-
* The replay-store backend resolved at host-boot time
|
|
5354
|
+
* The replay-store backend resolved at host-boot time. Surfaced in
|
|
5481
5355
|
* the boot summary so operators see which protection is active.
|
|
5482
5356
|
*
|
|
5483
5357
|
* - `postgres` — SDK auto-wired a `PostgresReplayStore` against the host's
|
|
5484
|
-
*
|
|
5358
|
+
* pool. Cross-machine safe.
|
|
5485
5359
|
* - `memory` — SDK fell back to the in-memory FIFO. Per-process; unsafe for
|
|
5486
|
-
*
|
|
5487
|
-
*
|
|
5360
|
+
* multi-machine deploys. `createDVMHost` emits a warning (or throws under
|
|
5361
|
+
* `DVMKIT_FAIL_FAST=true`) when this kicks in outside `devMode`.
|
|
5488
5362
|
* - `user-supplied` — user passed an explicit `replayStore` at factory time.
|
|
5489
|
-
*
|
|
5363
|
+
* SDK doesn't override.
|
|
5490
5364
|
* - `disabled` — user passed `replayStore: null`. No replay tracking.
|
|
5491
5365
|
*/
|
|
5492
5366
|
type ReplayStoreBackend = "postgres" | "memory" | "user-supplied" | "disabled";
|
|
@@ -5500,7 +5374,7 @@ interface DVMAuthScheme {
|
|
|
5500
5374
|
};
|
|
5501
5375
|
/**
|
|
5502
5376
|
* Re-verify the signature on a persisted envelope at reactivation time
|
|
5503
|
-
*
|
|
5377
|
+
* Schema + signature only — no drift check, no replay-store
|
|
5504
5378
|
* touch. Catches DB-layer tampering: persisted `record.input` would
|
|
5505
5379
|
* otherwise be trusted as authentic, and a compromised row could feed an
|
|
5506
5380
|
* attacker-supplied pubkey/envelope into the handler. Throws
|
|
@@ -5511,7 +5385,7 @@ interface DVMAuthScheme {
|
|
|
5511
5385
|
/** Commit the envelope's `(pubkey, timestamp, nonce)` to the replay store. Throws on duplicate. */
|
|
5512
5386
|
recordReplay(envelope: CanonicalEnvelope): Promise<void>;
|
|
5513
5387
|
/**
|
|
5514
|
-
* Called by `createDVMHost` after the Postgres pool is resolved
|
|
5388
|
+
* Called by `createDVMHost` after the Postgres pool is resolved.
|
|
5515
5389
|
* The SDK passes a Postgres store when one is available; the scheme adopts
|
|
5516
5390
|
* it iff the user did not supply `replayStore` explicitly at factory time.
|
|
5517
5391
|
* Returns the resolved backend for boot-summary logging. User code should
|
|
@@ -5521,7 +5395,6 @@ interface DVMAuthScheme {
|
|
|
5521
5395
|
postgresStore?: SignedRequestReplayStore;
|
|
5522
5396
|
}): ReplayStoreBackend;
|
|
5523
5397
|
}
|
|
5524
|
-
/** Options for `secp256k1Auth()`. */
|
|
5525
5398
|
interface Secp256k1AuthOpts {
|
|
5526
5399
|
/**
|
|
5527
5400
|
* Override the replay-window store. Most callers should omit this opt:
|
|
@@ -5529,7 +5402,7 @@ interface Secp256k1AuthOpts {
|
|
|
5529
5402
|
* pool is available, and falls back to a bounded in-memory FIFO (10-min
|
|
5530
5403
|
* window, 100k cap) only when no pool exists — emitting a warning (or
|
|
5531
5404
|
* throwing under `DVMKIT_FAIL_FAST=true`) outside `devMode` so multi-machine
|
|
5532
|
-
* deploys can't silently inherit the per-process default
|
|
5405
|
+
* deploys can't silently inherit the per-process default.
|
|
5533
5406
|
*
|
|
5534
5407
|
* Pass a custom `SignedRequestReplayStore` here only to override that
|
|
5535
5408
|
* default (e.g. a different cross-machine backend), or pass `null` to
|
|
@@ -5543,8 +5416,7 @@ interface Secp256k1AuthOpts {
|
|
|
5543
5416
|
now?: () => number;
|
|
5544
5417
|
}
|
|
5545
5418
|
/**
|
|
5546
|
-
* Build a descriptor-level secp256k1+BIP-340 Schnorr auth scheme
|
|
5547
|
-
* internal-review).
|
|
5419
|
+
* Build a descriptor-level secp256k1+BIP-340 Schnorr auth scheme.
|
|
5548
5420
|
*
|
|
5549
5421
|
* Declare on `configureDVM({ auth: secp256k1Auth({...}) })` to gate every
|
|
5550
5422
|
* capability's `/v1/job` and `/v1/quote` on a signed request envelope
|
|
@@ -5579,7 +5451,7 @@ interface ZodLike<T = unknown> {
|
|
|
5579
5451
|
/** Extract the output type from a ZodLike schema, or default to string. */
|
|
5580
5452
|
type InputType<T> = T extends ZodLike<infer O> ? O : string;
|
|
5581
5453
|
/**
|
|
5582
|
-
* Narrowed type for capability `example` payloads
|
|
5454
|
+
* Narrowed type for capability `example` payloads.
|
|
5583
5455
|
*
|
|
5584
5456
|
* Surfaces the Zod schema's output type so a drifted example produces a
|
|
5585
5457
|
* TypeScript error at the `configureDVM` call site. Falls back to
|
|
@@ -5612,19 +5484,16 @@ interface KVStore {
|
|
|
5612
5484
|
set(key: string, value: unknown, opts?: {
|
|
5613
5485
|
ttl?: number;
|
|
5614
5486
|
}): Promise<void>;
|
|
5615
|
-
/** Delete a key. */
|
|
5616
5487
|
delete(key: string): Promise<void>;
|
|
5617
5488
|
/** List keys, optionally filtered by prefix. */
|
|
5618
5489
|
list(prefix?: string): Promise<string[]>;
|
|
5619
5490
|
}
|
|
5620
|
-
/** Options for ctx.prompt(). */
|
|
5621
5491
|
interface PromptOpts {
|
|
5622
5492
|
/** Preset choices the client can select from. */
|
|
5623
5493
|
options?: string[];
|
|
5624
5494
|
/** JSON Schema describing the expected structured response. */
|
|
5625
5495
|
schema?: Record<string, unknown>;
|
|
5626
5496
|
}
|
|
5627
|
-
/** Options for ctx.requestPayment(). */
|
|
5628
5497
|
interface SDKPaymentRequestOpts {
|
|
5629
5498
|
/** Cashu mints accepted for this payment. */
|
|
5630
5499
|
mints?: string[];
|
|
@@ -5642,11 +5511,11 @@ interface SDKPaymentRequestOpts {
|
|
|
5642
5511
|
* pre-issued mppx challenge per accepted method/intent. Overrides the
|
|
5643
5512
|
* SDK's auto-issued challenges; if omitted, and the SDK is configured for
|
|
5644
5513
|
* MPP, challenges are issued automatically. Each challenge's `id` becomes
|
|
5645
|
-
* part of this job's per-job replay binding
|
|
5514
|
+
* part of this job's per-job replay binding.
|
|
5646
5515
|
*
|
|
5647
5516
|
* `session`-intent challenges are dropped from this list, whoever issued
|
|
5648
5517
|
* them: reusable channels fund credits on `POST /v1/credit` and are refused
|
|
5649
|
-
* everywhere on the job surface
|
|
5518
|
+
* everywhere on the job surface.
|
|
5650
5519
|
*/
|
|
5651
5520
|
mpp?: {
|
|
5652
5521
|
challenges: MppxChallenge[];
|
|
@@ -5687,14 +5556,13 @@ interface SDKJobContext<State = Record<string, unknown>, Input = string> {
|
|
|
5687
5556
|
readonly tags: string[];
|
|
5688
5557
|
/** Job input — raw string or parsed/validated object when an input schema is defined. */
|
|
5689
5558
|
readonly input: Input;
|
|
5690
|
-
/** Job parameters as key-value pairs. */
|
|
5691
5559
|
readonly params: Record<string, string>;
|
|
5692
5560
|
/** Opaque requester identifier (derived from auth token or "anonymous"). */
|
|
5693
5561
|
readonly requesterId: string;
|
|
5694
5562
|
/** Total msats paid so far for this job. */
|
|
5695
5563
|
readonly paidMsats: number;
|
|
5696
5564
|
/**
|
|
5697
|
-
* Verified caller identity from the descriptor's `auth` scheme
|
|
5565
|
+
* Verified caller identity from the descriptor's `auth` scheme.
|
|
5698
5566
|
* Present when the DVM declares `auth: secp256k1Auth(...)`; undefined for
|
|
5699
5567
|
* DVMs without descriptor-level auth. The envelope is the same `T &
|
|
5700
5568
|
* CanonicalEnvelope` the auth scheme produced — handlers can read
|
|
@@ -5717,10 +5585,10 @@ interface SDKJobContext<State = Record<string, unknown>, Input = string> {
|
|
|
5717
5585
|
*
|
|
5718
5586
|
* - `number` = msats raw (sats-native operators).
|
|
5719
5587
|
* - `{ amount, currency }` = fiat envelope; the SDK converts to sats at
|
|
5720
|
-
*
|
|
5721
|
-
*
|
|
5588
|
+
* send-time via its centralised fx fetcher. v1 supports `currency: "usd"`
|
|
5589
|
+
* only; other currencies throw `UnsupportedCurrencyError`.
|
|
5722
5590
|
*
|
|
5723
|
-
* The legacy `string` form (`"$0.05"`) was removed in
|
|
5591
|
+
* The legacy `string` form (`"$0.05"`) was removed in under the
|
|
5724
5592
|
* project's no-shims convention. Migrate callers to the fiat envelope.
|
|
5725
5593
|
*/
|
|
5726
5594
|
requestPayment(amount: number | {
|
|
@@ -5742,14 +5610,14 @@ interface SDKJobContext<State = Record<string, unknown>, Input = string> {
|
|
|
5742
5610
|
/**
|
|
5743
5611
|
* Fail the job with an error message. No debit happens either way — the
|
|
5744
5612
|
* terminal funnel releases the credit draw ({@link RAIL_REFUNDABLE}).
|
|
5745
|
-
* `{ refund: true }` annotates the failure as caller-fault
|
|
5613
|
+
* `{ refund: true }` annotates the failure as caller-fault; it
|
|
5746
5614
|
* moves no money on any rail and never has.
|
|
5747
5615
|
*/
|
|
5748
5616
|
fail(error: string, opts?: {
|
|
5749
5617
|
refund?: boolean;
|
|
5750
5618
|
}): void;
|
|
5751
5619
|
/**
|
|
5752
|
-
* Declare what this job cost **you**, the builder, to serve
|
|
5620
|
+
* Declare what this job cost **you**, the builder, to serve.
|
|
5753
5621
|
*
|
|
5754
5622
|
* The SDK reports it to the platform alongside the job's revenue, so the
|
|
5755
5623
|
* dashboard can state a margin. Without it the margin is unknowable, and the
|
|
@@ -5777,9 +5645,9 @@ interface SDKJobContext<State = Record<string, unknown>, Input = string> {
|
|
|
5777
5645
|
*
|
|
5778
5646
|
* ```ts
|
|
5779
5647
|
* const r = await ctx.step("transcribe", async () => {
|
|
5780
|
-
*
|
|
5781
|
-
*
|
|
5782
|
-
*
|
|
5648
|
+
* const result = await whisper(audio);
|
|
5649
|
+
* ctx.cost({ amount: result.seconds * 0.0001, currency: "usd" });
|
|
5650
|
+
* return result;
|
|
5783
5651
|
* });
|
|
5784
5652
|
* ```
|
|
5785
5653
|
*
|
|
@@ -5814,7 +5682,7 @@ interface SDKJobContext<State = Record<string, unknown>, Input = string> {
|
|
|
5814
5682
|
*/
|
|
5815
5683
|
fetch: typeof globalThis.fetch;
|
|
5816
5684
|
/**
|
|
5817
|
-
* Cancellation signal for this job
|
|
5685
|
+
* Cancellation signal for this job. Aborts when the caller
|
|
5818
5686
|
* cancels, the job idles out, or the handler is superseded. `ctx.fetch`
|
|
5819
5687
|
* already carries it; pass it into anything else that can be torn down —
|
|
5820
5688
|
* a provider SDK's `signal` option, a `spawn`, your own sleeps — so a
|
|
@@ -5824,7 +5692,6 @@ interface SDKJobContext<State = Record<string, unknown>, Input = string> {
|
|
|
5824
5692
|
readonly signal: AbortSignal;
|
|
5825
5693
|
/** Environment variables configured by the operator. */
|
|
5826
5694
|
env: Record<string, string>;
|
|
5827
|
-
/** Structured logging. */
|
|
5828
5695
|
log: Logger;
|
|
5829
5696
|
}
|
|
5830
5697
|
/** Context provided to the onQuote handler. */
|
|
@@ -5839,7 +5706,7 @@ interface QuoteContext<QuoteData = Record<string, unknown>> {
|
|
|
5839
5706
|
* Operator environment — same object threaded into `JobContext.env`.
|
|
5840
5707
|
* Quote handlers read it for pre-payment checks (API-key presence, feature
|
|
5841
5708
|
* flags, model overrides) so failures surface as a structured 400 rather
|
|
5842
|
-
* than after the upfront fee has been debited.
|
|
5709
|
+
* than after the upfront fee has been debited.
|
|
5843
5710
|
*/
|
|
5844
5711
|
env: Record<string, string>;
|
|
5845
5712
|
/**
|
|
@@ -5849,16 +5716,16 @@ interface QuoteContext<QuoteData = Record<string, unknown>> {
|
|
|
5849
5716
|
*/
|
|
5850
5717
|
fetch: typeof globalThis.fetch;
|
|
5851
5718
|
/**
|
|
5852
|
-
* Verified caller pubkey from the signed-request envelope
|
|
5853
|
-
*
|
|
5719
|
+
* Verified caller pubkey from the signed-request envelope. Present only when
|
|
5720
|
+
* the descriptor declares an auth scheme and the
|
|
5854
5721
|
* envelope verified — `/v1/quote` runs `checkAuth` before the handler, so by
|
|
5855
5722
|
* the time this is set the signature is good. Undefined on unauthenticated
|
|
5856
5723
|
* DVMs; quote handlers that price per-caller must handle that.
|
|
5857
5724
|
*/
|
|
5858
5725
|
callerPubkey?: string;
|
|
5859
5726
|
/**
|
|
5860
|
-
* The authenticated caller's standing prepaid credit at this DVM, if any
|
|
5861
|
-
*
|
|
5727
|
+
* The authenticated caller's standing prepaid credit at this DVM, if any,
|
|
5728
|
+
* so one round trip answers "cost + my remaining
|
|
5862
5729
|
* credit". Undefined when the DVM doesn't offer credit, the caller is
|
|
5863
5730
|
* unauthenticated, or they hold no live credit in this DVM's currency.
|
|
5864
5731
|
*
|
|
@@ -5869,8 +5736,8 @@ interface QuoteContext<QuoteData = Record<string, unknown>> {
|
|
|
5869
5736
|
credit?: CreditView;
|
|
5870
5737
|
}
|
|
5871
5738
|
/**
|
|
5872
|
-
* Read-only snapshot of a caller's credit, surfaced on {@link QuoteContext}
|
|
5873
|
-
*
|
|
5739
|
+
* Read-only snapshot of a caller's credit, surfaced on {@link QuoteContext};
|
|
5740
|
+
* it mirrors the ledger's `CreditSnapshot` minus the write surface
|
|
5874
5741
|
* and the fields a quote handler has no business branching on.
|
|
5875
5742
|
*/
|
|
5876
5743
|
interface CreditView {
|
|
@@ -5888,7 +5755,7 @@ interface CreditView {
|
|
|
5888
5755
|
expired: boolean;
|
|
5889
5756
|
}
|
|
5890
5757
|
/**
|
|
5891
|
-
* Result returned by the onQuote handler — the fiat-first envelope
|
|
5758
|
+
* Result returned by the onQuote handler — the fiat-first envelope.
|
|
5892
5759
|
*
|
|
5893
5760
|
* The protocol enforces exactly one hard invariant — `upfront` — and pushes
|
|
5894
5761
|
* every other pricing detail into prose. LLM-agent intermediaries read
|
|
@@ -5966,24 +5833,23 @@ interface QuoteConfig<QuoteData = Record<string, unknown>> {
|
|
|
5966
5833
|
interface IncomingMessage {
|
|
5967
5834
|
/** Message type (e.g. "response", "payment", "approval", "cancel"). */
|
|
5968
5835
|
type: MessageType;
|
|
5969
|
-
/** Raw message content. */
|
|
5970
5836
|
content: Record<string, unknown>;
|
|
5971
5837
|
}
|
|
5972
5838
|
/**
|
|
5973
5839
|
* A builder-declared price — a USD literal, always (`"$0.05"`).
|
|
5974
5840
|
*
|
|
5975
|
-
* Fiat is the only static price form
|
|
5841
|
+
* Fiat is the only static price form. The credit ledger is
|
|
5976
5842
|
* fiat-micro denominated, so a raw-msats price could only reach the ledger
|
|
5977
5843
|
* through a BTC/USD lookup that may be unavailable — which is how a
|
|
5978
5844
|
* numeric-priced DVM under a cold-start rate outage used to take money and
|
|
5979
|
-
* record no draw
|
|
5845
|
+
* record no draw. Rails are unaffected: callers still pay sats,
|
|
5980
5846
|
* the SDK converts at request time.
|
|
5981
5847
|
*/
|
|
5982
5848
|
type PriceValue = string;
|
|
5983
5849
|
/** Accepted payment rail identifier. */
|
|
5984
5850
|
type PaymentMethod = "cashu" | "x402" | "tempo";
|
|
5985
5851
|
/**
|
|
5986
|
-
* Rails a prepaid **credit
|
|
5852
|
+
* Rails that may fund a prepaid **credit**.
|
|
5987
5853
|
*
|
|
5988
5854
|
* A deliberate superset of {@link PaymentMethod}, not a widening of it.
|
|
5989
5855
|
* `lightning` funds a credit through the interactive invoice leg on
|
|
@@ -5991,59 +5857,40 @@ type PaymentMethod = "cashu" | "x402" | "tempo";
|
|
|
5991
5857
|
* connection and credits when settlement is observed — but it is **not** an
|
|
5992
5858
|
* attached-proof wire method: there is no header a caller can hang a bolt11
|
|
5993
5859
|
* on, nothing to verify inline, and no `lightning` entry in `/v1/info` or
|
|
5994
|
-
* `/v1/quote`'s `payment.methods
|
|
5995
|
-
* remnants of the per-call surface). Keeping the two types distinct is what
|
|
5860
|
+
* `/v1/quote`'s `payment.methods`. Keeping the two types distinct is what
|
|
5996
5861
|
* stops that dead rail from reappearing every time the funding menu grows.
|
|
5997
5862
|
*/
|
|
5998
5863
|
type FundingMethod = PaymentMethod | "lightning";
|
|
5999
5864
|
/**
|
|
6000
|
-
* Whether
|
|
6001
|
-
*
|
|
6002
|
-
*
|
|
6003
|
-
* the P2PK-accumulator Cashu path — the only Cashu path post-internal-review/internal-review —
|
|
6004
|
-
* `verifyAccumulatorReceipt` commits the caller's proofs straight into
|
|
6005
|
-
* `wallet_accumulator` and leaves `job.receivedProofs` empty; every producer in
|
|
6006
|
-
* `payment.ts` returns `[]`. The `ctx.fail(err, { refund: true })` branch that
|
|
6007
|
-
* used to send proofs back gated on those held proofs, so it had been an
|
|
6008
|
-
* unreachable no-op for as long as the accumulator has been the commit boundary,
|
|
6009
|
-
* and internal-review deleted it. This fail-closed posture was locked by internal-review
|
|
6010
|
-
* (Decision C) and pinned by internal-review. mpp (Tempo) and x402 credentials are
|
|
6011
|
-
* single-use, final-settlement — no SDK-managed reversal path either.
|
|
6012
|
-
*
|
|
6013
|
-
* **This is a rail-level question, and since internal-review it is no longer the whole
|
|
6014
|
-
* story.** A failed job never debits: the draw is a hold the terminal funnel
|
|
6015
|
-
* releases (`JobManager.resolveCreditDraw`), so the value stays on the caller's
|
|
6016
|
-
* credit. What this flag reports is narrower and still true — no rail hands
|
|
6017
|
-
* value backwards — and reclaiming a released balance runs through the
|
|
6018
|
-
* internal-review `drain` op, which exists only on a DVM that advertises credit.
|
|
5865
|
+
* Whether the payment rail returns value when a job fails. No rail reverses
|
|
5866
|
+
* `ctx.fail`: Cashu proofs are committed to the accumulator; Tempo and x402
|
|
5867
|
+
* credentials settle without an SDK reversal.
|
|
6019
5868
|
*
|
|
6020
|
-
*
|
|
6021
|
-
*
|
|
6022
|
-
*
|
|
6023
|
-
*
|
|
6024
|
-
* `true`, was cancelled as superseded: the ledger is where reclaim lives now.
|
|
6025
|
-
* x402 refund parity remains a deferred internal-review exploration.
|
|
5869
|
+
* Failed credit jobs release their draw hold back to the caller's balance.
|
|
5870
|
+
* Reclaiming that balance uses `drain`; this flag describes rail reversal,
|
|
5871
|
+
* independently of the credit ledger. `{ refund: true }` records caller fault
|
|
5872
|
+
* and does not move funds.
|
|
6026
5873
|
*/
|
|
6027
5874
|
declare const RAIL_REFUNDABLE: Record<PaymentMethod, boolean>;
|
|
6028
5875
|
/**
|
|
6029
|
-
* Cashu receive mode for builder DVMs
|
|
5876
|
+
* Cashu receive mode for builder DVMs.
|
|
6030
5877
|
*
|
|
6031
5878
|
* `"p2pk-accumulator"` — accept P2PK-locked proofs from agent wallets and persist
|
|
6032
5879
|
* them in `wallet_accumulator`. Melting runs builder-local via `dvmctl melt-pending`
|
|
6033
|
-
*
|
|
5880
|
+
* the SDK only monitors batches for `t_expire` proximity.
|
|
6034
5881
|
*/
|
|
6035
5882
|
type CashuMode = "p2pk-accumulator";
|
|
6036
5883
|
/**
|
|
6037
|
-
* Prepaid-credit sizing this DVM advertises
|
|
5884
|
+
* Prepaid-credit sizing this DVM advertises.
|
|
6038
5885
|
*
|
|
6039
5886
|
* Declaring the block is the opt-in: a DVM without `credit` never offers the
|
|
6040
5887
|
* funding menu on `/v1/quote` or the 402, and `/v1/credit` refuses with
|
|
6041
5888
|
* `credit_not_supported`. Every payment still funds and draws the ledger
|
|
6042
|
-
* internally (the implicit N=1 case
|
|
5889
|
+
* internally (the implicit N=1 case) — this block is only about
|
|
6043
5890
|
* whether callers may hold a balance across jobs.
|
|
6044
5891
|
*
|
|
6045
5892
|
* Isolate-runtime DVMs never advertise credit regardless of this config
|
|
6046
|
-
* (
|
|
5893
|
+
* (the isolate-runtime rule): they have no Postgres of their own, so the money-safety
|
|
6047
5894
|
* conditions the ledger relies on can't hold there.
|
|
6048
5895
|
*/
|
|
6049
5896
|
interface CreditConfig {
|
|
@@ -6058,14 +5905,14 @@ interface CreditConfig {
|
|
|
6058
5905
|
min?: PriceValue;
|
|
6059
5906
|
/**
|
|
6060
5907
|
* Largest **residual balance** a caller may hold, as a `PriceValue`.
|
|
6061
|
-
* Binds the balance, not the funding amount (
|
|
5908
|
+
* Binds the balance, not the funding amount (the balance-sizing contract): a job priced above
|
|
6062
5909
|
* `max` still clears as fund-and-immediately-draw. Bounds the DVM's
|
|
6063
5910
|
* prepaid-deposit liability. Default `"$5.00"`.
|
|
6064
5911
|
*/
|
|
6065
5912
|
max?: PriceValue;
|
|
6066
5913
|
/**
|
|
6067
5914
|
* Credit lifetime in **seconds**, from the most recent funding. Post-TTL
|
|
6068
|
-
* the credit refuses new draws; the balance stays the caller's (
|
|
5915
|
+
* the credit refuses new draws; the balance stays the caller's (the caller-ownership contract).
|
|
6069
5916
|
* Default 30 days.
|
|
6070
5917
|
*/
|
|
6071
5918
|
ttl?: number;
|
|
@@ -6099,17 +5946,17 @@ interface ResolvedCreditConfig {
|
|
|
6099
5946
|
declare const DEFAULT_CREDIT_MIN: PriceValue;
|
|
6100
5947
|
/**
|
|
6101
5948
|
* Platform default for {@link CreditConfig.max} — the largest residual balance
|
|
6102
|
-
* a caller may hold. Pocket-money sizing (
|
|
5949
|
+
* a caller may hold. Pocket-money sizing (the exposure limit: prepaid exposure is
|
|
6103
5950
|
* capped by policy at pocket-money size), set above the caller-side tier-1
|
|
6104
5951
|
* cap of $2 so an established caller can actually reach the builder ceiling.
|
|
6105
5952
|
*/
|
|
6106
5953
|
declare const DEFAULT_CREDIT_MAX: PriceValue;
|
|
6107
|
-
/** Platform default for {@link CreditConfig.ttl}
|
|
5954
|
+
/** Platform default for {@link CreditConfig.ttl}: 30 days. */
|
|
6108
5955
|
declare const DEFAULT_CREDIT_TTL_SECONDS: number;
|
|
6109
5956
|
/** Default lifetime of caller-controlled job content before it is redacted. */
|
|
6110
5957
|
declare const DEFAULT_JOB_RETENTION_DAYS = 90;
|
|
6111
5958
|
/**
|
|
6112
|
-
* Per-capability configuration for the multi-capability shape
|
|
5959
|
+
* Per-capability configuration for the multi-capability shape.
|
|
6113
5960
|
* Each capability is an independent unit a caller pays for: its own input
|
|
6114
5961
|
* schema, pricing, handler, and (optional) message handlers. DVM-level
|
|
6115
5962
|
* concerns (auth, payment rails, tags, builder) stay on the parent
|
|
@@ -6121,13 +5968,13 @@ interface CapabilityConfig<State = Record<string, unknown>, InputSchema extends
|
|
|
6121
5968
|
/** Zod schema for structured job input. When set, ctx.input is parsed and typed. */
|
|
6122
5969
|
input?: InputSchema;
|
|
6123
5970
|
/**
|
|
6124
|
-
* Example input payload surfaced on `/v1/info
|
|
5971
|
+
* Example input payload surfaced on `/v1/info`. Lets the CLI render
|
|
6125
5972
|
* a runnable `dvm quote --data '<payload>'` line when the JSON Schema alone
|
|
6126
5973
|
* is ambiguous — e.g. cross-field Zod refinements that don't survive
|
|
6127
5974
|
* serialization (narrate's `text` XOR `dialogue`). Must satisfy the schema
|
|
6128
5975
|
* including any `.refine()` checks.
|
|
6129
5976
|
*
|
|
6130
|
-
* Typed via `ExampleType<InputSchema
|
|
5977
|
+
* Typed via `ExampleType<InputSchema>`: narrows to the schema's
|
|
6131
5978
|
* output type when `input` is a Zod schema, falls back to
|
|
6132
5979
|
* `Record<string, unknown>` otherwise.
|
|
6133
5980
|
*/
|
|
@@ -6136,7 +5983,6 @@ interface CapabilityConfig<State = Record<string, unknown>, InputSchema extends
|
|
|
6136
5983
|
state?: State;
|
|
6137
5984
|
/** Static price — a USD literal ("$0.05"). Free capabilities omit this and `onQuote`. */
|
|
6138
5985
|
price?: PriceValue;
|
|
6139
|
-
/** Quote handler for dynamic pricing. */
|
|
6140
5986
|
onQuote?: QuoteConfig;
|
|
6141
5987
|
/** Handle a newly submitted job for this capability (required). */
|
|
6142
5988
|
onJob: (ctx: SDKJobContext<State, InputType<InputSchema>>) => void | Promise<void>;
|
|
@@ -6152,7 +5998,7 @@ interface CapabilityConfig<State = Record<string, unknown>, InputSchema extends
|
|
|
6152
5998
|
onMessage?: (ctx: SDKJobContext<State, InputType<InputSchema>>, msg: IncomingMessage) => void | Promise<void>;
|
|
6153
5999
|
}
|
|
6154
6000
|
/**
|
|
6155
|
-
* Desugared per-capability descriptor
|
|
6001
|
+
* Desugared per-capability descriptor. `configureDVM` produces one
|
|
6156
6002
|
* of these per capability — the SDK runtime always operates on this shape.
|
|
6157
6003
|
*/
|
|
6158
6004
|
interface CapabilityDescriptor<State = unknown, InputSchema extends ZodLike | undefined = undefined> {
|
|
@@ -6162,15 +6008,13 @@ interface CapabilityDescriptor<State = unknown, InputSchema extends ZodLike | un
|
|
|
6162
6008
|
readonly description: string;
|
|
6163
6009
|
/** Zod schema for structured job input. */
|
|
6164
6010
|
readonly input?: InputSchema;
|
|
6165
|
-
/** Example input payload surfaced on `/v1/info
|
|
6011
|
+
/** Example input payload surfaced on `/v1/info`. See `CapabilityConfig.example`. */
|
|
6166
6012
|
readonly example?: ExampleType<InputSchema>;
|
|
6167
6013
|
/** Default per-job state for jobs of this capability. */
|
|
6168
6014
|
readonly state: State;
|
|
6169
6015
|
/** Static price — a USD literal ("$0.05"). Undefined for dynamic-priced or free. */
|
|
6170
6016
|
readonly price?: PriceValue;
|
|
6171
|
-
/** Quote handler for dynamic pricing. */
|
|
6172
6017
|
readonly onQuote?: QuoteConfig;
|
|
6173
|
-
/** Handle a newly submitted job. */
|
|
6174
6018
|
readonly onJob: (ctx: SDKJobContext<State, InputType<InputSchema>>) => void | Promise<void>;
|
|
6175
6019
|
/** Handle a client response to a prompt. */
|
|
6176
6020
|
readonly onResponse?: (ctx: SDKJobContext<State, InputType<InputSchema>>, content: ResponseContent) => void | Promise<void>;
|
|
@@ -6186,30 +6030,28 @@ interface CapabilityDescriptor<State = unknown, InputSchema extends ZodLike | un
|
|
|
6186
6030
|
/**
|
|
6187
6031
|
* Configuration object passed to configureDVM().
|
|
6188
6032
|
*
|
|
6189
|
-
* Two equivalent shapes
|
|
6033
|
+
* Two equivalent shapes:
|
|
6190
6034
|
*
|
|
6191
6035
|
* - **Flat single-capability shape** — declare `capability: "<name>"` plus
|
|
6192
|
-
*
|
|
6193
|
-
*
|
|
6194
|
-
*
|
|
6195
|
-
*
|
|
6036
|
+
* the per-capability fields (`input`, `state`, `price`/`onQuote`, `onJob`,
|
|
6037
|
+
* `onResponse`, …) at the top level. Desugars internally to a one-entry
|
|
6038
|
+
* `capabilities` map. Ergonomic for the common case (narrate, scribe,
|
|
6039
|
+
* scrape).
|
|
6196
6040
|
*
|
|
6197
6041
|
* - **Explicit multi-capability shape** — declare `capabilities: { "<name>":
|
|
6198
|
-
*
|
|
6199
|
-
*
|
|
6200
|
-
*
|
|
6042
|
+
* { input, onJob, … } }`. Used by services that expose several operations
|
|
6043
|
+
* on a shared resource model (cast's add-episode / update-feed /
|
|
6044
|
+
* delete-episode / delete-feed).
|
|
6201
6045
|
*
|
|
6202
6046
|
* The two are mutually exclusive: providing both throws at `configureDVM`.
|
|
6203
6047
|
* DVM-level concerns (tags, payment rails, idle timeout, lifecycle,
|
|
6204
6048
|
* descriptor routes) live on `DVMConfig` regardless of shape.
|
|
6205
6049
|
*/
|
|
6206
6050
|
interface DVMConfig<State = Record<string, unknown>, InputSchema extends ZodLike | undefined = undefined> {
|
|
6207
|
-
/** Display name for the DVM. */
|
|
6208
6051
|
name: string;
|
|
6209
|
-
/** Human-readable description. */
|
|
6210
6052
|
description?: string;
|
|
6211
6053
|
/**
|
|
6212
|
-
* Single-capability name for the flat shape
|
|
6054
|
+
* Single-capability name for the flat shape. Mutually exclusive
|
|
6213
6055
|
* with `capabilities`. Single-capability DVMs declare it here and put the
|
|
6214
6056
|
* per-capability fields (`input`, `state`, `price`/`onQuote`, `onJob`,
|
|
6215
6057
|
* `onResponse`, …) at the top level; `configureDVM` desugars to a
|
|
@@ -6217,7 +6059,7 @@ interface DVMConfig<State = Record<string, unknown>, InputSchema extends ZodLike
|
|
|
6217
6059
|
*/
|
|
6218
6060
|
capability?: string;
|
|
6219
6061
|
/**
|
|
6220
|
-
* Explicit multi-capability block
|
|
6062
|
+
* Explicit multi-capability block. Mutually exclusive with the
|
|
6221
6063
|
* flat shape's `capability` + top-level handler fields. Each key is a
|
|
6222
6064
|
* capability name (tag-shape: lowercase letters/digits/hyphens, no
|
|
6223
6065
|
* slashes); each value carries its own `input`, `state`, `price`/`onQuote`,
|
|
@@ -6230,7 +6072,7 @@ interface DVMConfig<State = Record<string, unknown>, InputSchema extends ZodLike
|
|
|
6230
6072
|
tags?: string[];
|
|
6231
6073
|
/**
|
|
6232
6074
|
* The currency this DVM prices in — and therefore the one its credit ledger
|
|
6233
|
-
* is denominated in
|
|
6075
|
+
* is denominated in. ISO 4217 lowercase; default `"usd"`.
|
|
6234
6076
|
*
|
|
6235
6077
|
* The single authoritative answer to "what denomination does this DVM deal
|
|
6236
6078
|
* in", read by the funding menu, `POST /v1/credit`, and the quote balance
|
|
@@ -6241,11 +6083,11 @@ interface DVMConfig<State = Record<string, unknown>, InputSchema extends ZodLike
|
|
|
6241
6083
|
* Two consequences, both enforced rather than documented:
|
|
6242
6084
|
*
|
|
6243
6085
|
* - **`onQuote` must return it.** A quote denominated in anything else is a
|
|
6244
|
-
*
|
|
6245
|
-
*
|
|
6086
|
+
* builder config error, refused as `quote_currency_mismatch` — never
|
|
6087
|
+
* coerced, never converted.
|
|
6246
6088
|
* - **Static `price` literals are USD-only** (`"$0.05"` — that is the whole
|
|
6247
|
-
*
|
|
6248
|
-
*
|
|
6089
|
+
* grammar), so declaring a non-USD currency alongside one is a
|
|
6090
|
+
* `configureDVM` error. Price a non-USD DVM dynamically with `onQuote`.
|
|
6249
6091
|
*
|
|
6250
6092
|
* The rails are unaffected: callers still pay sats, and the SDK converts at
|
|
6251
6093
|
* request time through whichever rate the fx fetcher carries for this
|
|
@@ -6256,7 +6098,7 @@ interface DVMConfig<State = Record<string, unknown>, InputSchema extends ZodLike
|
|
|
6256
6098
|
price?: PriceValue;
|
|
6257
6099
|
/** Zod schema for structured job input. Flat shape only. */
|
|
6258
6100
|
input?: InputSchema;
|
|
6259
|
-
/** Example input payload surfaced on `/v1/info
|
|
6101
|
+
/** Example input payload surfaced on `/v1/info`. Flat shape only — see `CapabilityConfig.example`. */
|
|
6260
6102
|
example?: ExampleType<InputSchema>;
|
|
6261
6103
|
/** Per-job state shape and defaults. Flat shape only. */
|
|
6262
6104
|
state?: State;
|
|
@@ -6265,7 +6107,7 @@ interface DVMConfig<State = Record<string, unknown>, InputSchema extends ZodLike
|
|
|
6265
6107
|
/**
|
|
6266
6108
|
* Seconds a job may sit in `processing`/`working` with no SDK liveness
|
|
6267
6109
|
* heartbeat before the stale-job watchdog declares its worker dead and marks
|
|
6268
|
-
* it `failed
|
|
6110
|
+
* it `failed`. The SDK heartbeats locally-active jobs every ~30s,
|
|
6269
6111
|
* so this bounds *crashed/OOM-killed-worker* detection — not legitimate
|
|
6270
6112
|
* handler runtime, which the heartbeat keeps fresh regardless of how long it
|
|
6271
6113
|
* runs. Distinct from `idleTimeout`, which governs the `awaiting-input`
|
|
@@ -6281,7 +6123,7 @@ interface DVMConfig<State = Record<string, unknown>, InputSchema extends ZodLike
|
|
|
6281
6123
|
*/
|
|
6282
6124
|
jobRetentionDays?: number;
|
|
6283
6125
|
/**
|
|
6284
|
-
* Descriptor-level auth scheme
|
|
6126
|
+
* Descriptor-level auth scheme. Fires on `/v1/job` and
|
|
6285
6127
|
* `/v1/quote` before payment verification and handler dispatch — unsigned
|
|
6286
6128
|
* or malformed envelopes reject with HTTP 401, no payment is attempted.
|
|
6287
6129
|
*
|
|
@@ -6319,14 +6161,14 @@ interface DVMConfig<State = Record<string, unknown>, InputSchema extends ZodLike
|
|
|
6319
6161
|
/** MPP multi-rail payment handle (provider-side, built via `createMppFromOpts`). */
|
|
6320
6162
|
mpp?: MppxServer;
|
|
6321
6163
|
/**
|
|
6322
|
-
* Prepaid-credit sizing
|
|
6164
|
+
* Prepaid-credit sizing. Declaring the block opts this DVM into
|
|
6323
6165
|
* the funding menu on `/v1/quote` / the 402 and into `POST /v1/credit`;
|
|
6324
6166
|
* omitting it leaves callers on per-call payment. See {@link CreditConfig}.
|
|
6325
6167
|
*/
|
|
6326
6168
|
credit?: CreditConfig;
|
|
6327
6169
|
/**
|
|
6328
6170
|
* Register DVM-scoped non-protocol routes on the descriptor's Hono sub-app
|
|
6329
|
-
*
|
|
6171
|
+
* Invoked once per `host.mount(dvm)` against the sub-app that
|
|
6330
6172
|
* receives `/v1/info`, `/v1/job`, etc. — any prefix passed to `host.mount`
|
|
6331
6173
|
* applies automatically, so a route registered as `/feeds/:owner/:slug` on
|
|
6332
6174
|
* a DVM mounted under `/cast` becomes `/cast/feeds/:owner/:slug` externally.
|
|
@@ -6349,14 +6191,12 @@ interface DVMRouteContext {
|
|
|
6349
6191
|
}
|
|
6350
6192
|
/** Immutable descriptor returned by configureDVM(). */
|
|
6351
6193
|
interface DVMDescriptor<State = Record<string, unknown>, InputSchema extends ZodLike | undefined = undefined> {
|
|
6352
|
-
/** Display name for the DVM. */
|
|
6353
6194
|
readonly name: string;
|
|
6354
6195
|
/** Human-readable description (empty string if not provided). */
|
|
6355
6196
|
readonly description: string;
|
|
6356
|
-
/** Freeform tags this DVM handles. */
|
|
6357
6197
|
readonly tags: string[];
|
|
6358
6198
|
/**
|
|
6359
|
-
* Resolved pricing currency
|
|
6199
|
+
* Resolved pricing currency — `config.currency` after validation,
|
|
6360
6200
|
* or `"usd"` when the builder declared none. Always present, so no consumer
|
|
6361
6201
|
* re-derives the default, and always the exact code the ledger compares
|
|
6362
6202
|
* against (`"EUR"` is a `configureDVM` error, not a case to normalise: the
|
|
@@ -6385,14 +6225,14 @@ interface DVMDescriptor<State = Record<string, unknown>, InputSchema extends Zod
|
|
|
6385
6225
|
readonly state: State;
|
|
6386
6226
|
/** Seconds before an idle job is auto-cancelled. */
|
|
6387
6227
|
readonly idleTimeout: number;
|
|
6388
|
-
/** Seconds before a worker-stranded `processing`/`working` job is marked `failed
|
|
6228
|
+
/** Seconds before a worker-stranded `processing`/`working` job is marked `failed`. Undefined → SDK default (5 min). */
|
|
6389
6229
|
readonly processingWatchdog?: number;
|
|
6390
6230
|
/** Days terminal job content is retained; `0` disables automatic redaction. */
|
|
6391
6231
|
readonly jobRetentionDays: number;
|
|
6392
6232
|
/** Reference to the original DVMConfig (handler functions, quote config, etc.). */
|
|
6393
6233
|
readonly config: DVMConfig<State, InputSchema>;
|
|
6394
6234
|
/**
|
|
6395
|
-
* Desugared per-capability descriptors
|
|
6235
|
+
* Desugared per-capability descriptors. The SDK runtime always
|
|
6396
6236
|
* operates on this map: single-capability DVMs have one entry keyed by
|
|
6397
6237
|
* `config.capability`; multi-capability DVMs have N entries with the
|
|
6398
6238
|
* names declared in `config.capabilities`.
|
|
@@ -6410,13 +6250,13 @@ interface DVMDescriptor<State = Record<string, unknown>, InputSchema extends Zod
|
|
|
6410
6250
|
/** MPP multi-rail payment handle. */
|
|
6411
6251
|
readonly mpp?: MppxServer;
|
|
6412
6252
|
/**
|
|
6413
|
-
* Prepaid-credit sizing
|
|
6253
|
+
* Prepaid-credit sizing, with every optional field resolved to
|
|
6414
6254
|
* its platform default. Present iff `configureDVM` was called with a
|
|
6415
6255
|
* `credit` block — the presence check IS the opt-in gate.
|
|
6416
6256
|
*/
|
|
6417
6257
|
readonly credit?: ResolvedCreditConfig;
|
|
6418
6258
|
/**
|
|
6419
|
-
* Descriptor-level auth scheme
|
|
6259
|
+
* Descriptor-level auth scheme. Set when `configureDVM` was
|
|
6420
6260
|
* called with `auth: secp256k1Auth(...)` — the SDK fires this on
|
|
6421
6261
|
* `/v1/job` and `/v1/quote` before payment verification.
|
|
6422
6262
|
*/
|
|
@@ -6442,13 +6282,11 @@ interface StepRecord {
|
|
|
6442
6282
|
*/
|
|
6443
6283
|
declare class StepCache {
|
|
6444
6284
|
private cache;
|
|
6445
|
-
/** Check if a step result is cached. */
|
|
6446
6285
|
has(id: string): boolean;
|
|
6447
6286
|
/** Get a cached step result. Throws if not present. */
|
|
6448
6287
|
get(id: string): unknown;
|
|
6449
6288
|
/** Get a cached step record, including replay metadata. Throws if not present. */
|
|
6450
6289
|
getRecord(id: string): StepRecord;
|
|
6451
|
-
/** Cache a step result. */
|
|
6452
6290
|
set(id: string, value: unknown, costs?: readonly JobCost[]): void;
|
|
6453
6291
|
/** Export all cached steps for persistence. */
|
|
6454
6292
|
serialize(): StepRecord[];
|
|
@@ -6456,4 +6294,4 @@ declare class StepCache {
|
|
|
6456
6294
|
static deserialize(records: StepRecord[]): StepCache;
|
|
6457
6295
|
}
|
|
6458
6296
|
|
|
6459
|
-
export { type X402Version as $, type ApprovalContent as A, SignedRequestError as B, type Currency as C, type DVMConfig as D, type SignedRequestFailure as E, type SignedRequestReplayStore as F, type SignedRequestSignOpts as G, type SignedRequestStatementHeader as H, type IncomingMessage as I, type JobCost as J, type KVStore as K, type Logger as L, type SignedRequestVerifier as M, createSignedRequestVerifier as N, isZodSchema as O, type PaymentContent as P, type QuoteConfig as Q, type ResolvedCreditConfig as R, type SDKJobContext as S, signedRequestStatementHeader as T, UnsupportedCurrencyError as U, validateCurrency as V, type JsonValue as W, type FundingReceipt as X, type JobReceipt as Y, type ZodLike as Z, type PaymentRequired as _, type DVMDescriptor as a, isDrainReceipt as a$, type MppxCredential as a0, type Message as a1, type MessageType as a2, type MppxChallenge as a3, X402_BATCH_SETTLEMENT_SCHEME as a4, X402_EXACT_SCHEME as a5, type ReceiptCredit as a6, type X402Wallet as a7, type ResourceInfo as a8, type BuildPaymentRequirementsOpts as a9, type UnsignedFundingReceipt as aA, type UnsignedJobReceipt as aB, type VerifyResponse as aC, type WorkingContent as aD, type X402Config as aE, type X402ResponseBody as aF, type X402SelfRelayRpcFailureReason as aG, X402_DEFAULT_NETWORK as aH, X402_V1_VERSION as aI, X402_VERSION as aJ, buildPaymentRequiredV2 as aK, buildPaymentRequirements as aL, caip2ToX402Network as aM, canonicalRequestPath as aN, canonicaliseForSigning as aO, canonicalize as aP, chainIdFromCaip2 as aQ, computeResultHash as aR, decodePayment as aS, decodePaymentRequiredHeader as aT, encodePayment as aU, encodePaymentRequiredHeader as aV, encodeSettleResponseHeader as aW, exactEvmAuthorization as aX, isArtifactMessage as aY, isCancelMessage as aZ, isCompleteMessage as a_, type CapabilityDescriptor as aa, type CashuMode as ab, type CompleteContent as ac, type DrainReceipt as ad, type DrainReceiptEvent as ae, type ExactEvmPayload as af, type ExactEvmPayloadAuthorization as ag, type FundingMethod as ah, type MessageFrom as ai, type PaymentPayload as aj, type PaymentPayloadV1 as ak, type PaymentPayloadV2 as al, type PaymentRequestContent as am, type PaymentRequiredV2 as an, type PaymentRequirements as ao, type PaymentRequirementsV1 as ap, type PaymentRequirementsV2 as aq, type PromptContent as ar, RAIL_REFUNDABLE as as, type ReceiptOutcome as at, type ReceiptPayment as au, type SettleResponse as av, StepCache as aw, type StepRecord as ax, type TextContent as ay, type UnsignedDrainReceipt as az, type ArtifactContent as b, type StalePendingDrawCursor as b$, isFundingReceipt as b0, isPaymentRequestMessage as b1, isPromptMessage as b2, isSignedJobReceipt as b3, isTextMessage as b4, isWorkingMessage as b5, paymentRequiredV2FromV1 as b6, signDrainReceipt as b7, signFundingReceipt as b8, signReceipt as b9, _testing as bA, createDefaultReplayStore as bB, depleteLots as bC, fifoOrder as bD, inKindDrawMsats as bE, isInKindDepletion as bF, isNonChannelBitcoinRail as bG, lotOwedSats as bH, netOwedSats as bI, wrapMppx as bJ, type CreditDrainEnqueue as bK, type DVMAuthScheme as bL, type CreditLedgerLike as bM, type X402RefundSettlementGate as bN, type CreditSnapshot as bO, type DrawResult as bP, type X402SettlementStatus as bQ, type X402UnresolvedRefund as bR, type GrownDrawResult as bS, type DrawResolution as bT, type FundingRecord as bU, type CreditInvoiceRecord as bV, type InvoiceSettlement as bW, type BlockedInvoiceCursor as bX, type InvoiceReconciliation as bY, type InvoiceWriteOff as bZ, type DrawRecord as b_, usdcContractByCaip2 as ba, usdcContractFor as bb, usdcDomainNameFor as bc, usdcDomainVersionFor as bd, verifyDrainReceipt as be, verifyFundingReceipt as bf, verifyReceipt as bg, x402NetworkToCaip2 as bh, type X402ExactVersionSupport as bi, type X402Receipt as bj, type TransactionalPayoutHook as bk, type CashuMeltCompleted as bl, type CreditDepositPayload as bm, type CreditDrainPayload as bn, type FundingLot as bo, type LotDebit as bp, type LotDepletion as bq, type MppxServer as br, NON_CHANNEL_BITCOIN_RAILS as bs, type NonChannelBitcoinRail as bt, PayoutReporter as bu, PostgresTempoSessionStore as bv, RevenueReporter as bw, SIGNED_ENVELOPE_FIELDS as bx, SIGNED_ENVELOPE_TYPES as by, type X402TrackedChannel as bz, type CancelContent as c, type TempoCreditLossEvidence as c0, type CreditLedgerQuerier as c1, type TempoCreditLoss as c2, type X402CreditLossEvidence as c3, type X402CreditLoss as c4, type DrainMethod as c5, type DrainRequestResult as c6, type BitcoinDepositLiability as c7, type CreditDrainRecord as c8, type ChannelDrainCursor as c9, type
|
|
6297
|
+
export { type X402Version as $, type ApprovalContent as A, SignedRequestError as B, type Currency as C, type DVMConfig as D, type SignedRequestFailure as E, type SignedRequestReplayStore as F, type SignedRequestSignOpts as G, type SignedRequestStatementHeader as H, type IncomingMessage as I, type JobCost as J, type KVStore as K, type Logger as L, type SignedRequestVerifier as M, createSignedRequestVerifier as N, isZodSchema as O, type PaymentContent as P, type QuoteConfig as Q, type ResolvedCreditConfig as R, type SDKJobContext as S, signedRequestStatementHeader as T, UnsupportedCurrencyError as U, validateCurrency as V, type JsonValue as W, type FundingReceipt as X, type JobReceipt as Y, type ZodLike as Z, type PaymentRequired as _, type DVMDescriptor as a, isDrainReceipt as a$, type MppxCredential as a0, type Message as a1, type MessageType as a2, type MppxChallenge as a3, X402_BATCH_SETTLEMENT_SCHEME as a4, X402_EXACT_SCHEME as a5, type ReceiptCredit as a6, type X402Wallet as a7, type ResourceInfo as a8, type BuildPaymentRequirementsOpts as a9, type UnsignedFundingReceipt as aA, type UnsignedJobReceipt as aB, type VerifyResponse as aC, type WorkingContent as aD, type X402Config as aE, type X402ResponseBody as aF, type X402SelfRelayRpcFailureReason as aG, X402_DEFAULT_NETWORK as aH, X402_V1_VERSION as aI, X402_VERSION as aJ, buildPaymentRequiredV2 as aK, buildPaymentRequirements as aL, caip2ToX402Network as aM, canonicalRequestPath as aN, canonicaliseForSigning as aO, canonicalize as aP, chainIdFromCaip2 as aQ, computeResultHash as aR, decodePayment as aS, decodePaymentRequiredHeader as aT, encodePayment as aU, encodePaymentRequiredHeader as aV, encodeSettleResponseHeader as aW, exactEvmAuthorization as aX, isArtifactMessage as aY, isCancelMessage as aZ, isCompleteMessage as a_, type CapabilityDescriptor as aa, type CashuMode as ab, type CompleteContent as ac, type DrainReceipt as ad, type DrainReceiptEvent as ae, type ExactEvmPayload as af, type ExactEvmPayloadAuthorization as ag, type FundingMethod as ah, type MessageFrom as ai, type PaymentPayload as aj, type PaymentPayloadV1 as ak, type PaymentPayloadV2 as al, type PaymentRequestContent as am, type PaymentRequiredV2 as an, type PaymentRequirements as ao, type PaymentRequirementsV1 as ap, type PaymentRequirementsV2 as aq, type PromptContent as ar, RAIL_REFUNDABLE as as, type ReceiptOutcome as at, type ReceiptPayment as au, type SettleResponse as av, StepCache as aw, type StepRecord as ax, type TextContent as ay, type UnsignedDrainReceipt as az, type ArtifactContent as b, type StalePendingDrawCursor as b$, isFundingReceipt as b0, isPaymentRequestMessage as b1, isPromptMessage as b2, isSignedJobReceipt as b3, isTextMessage as b4, isWorkingMessage as b5, paymentRequiredV2FromV1 as b6, signDrainReceipt as b7, signFundingReceipt as b8, signReceipt as b9, _testing as bA, createDefaultReplayStore as bB, depleteLots as bC, fifoOrder as bD, inKindDrawMsats as bE, isInKindDepletion as bF, isNonChannelBitcoinRail as bG, lotOwedSats as bH, netOwedSats as bI, wrapMppx as bJ, type CreditDrainEnqueue as bK, type DVMAuthScheme as bL, type CreditLedgerLike as bM, type X402RefundSettlementGate as bN, type CreditSnapshot as bO, type DrawResult as bP, type X402SettlementStatus as bQ, type X402UnresolvedRefund as bR, type GrownDrawResult as bS, type DrawResolution as bT, type FundingRecord as bU, type CreditInvoiceRecord as bV, type InvoiceSettlement as bW, type BlockedInvoiceCursor as bX, type InvoiceReconciliation as bY, type InvoiceWriteOff as bZ, type DrawRecord as b_, usdcContractByCaip2 as ba, usdcContractFor as bb, usdcDomainNameFor as bc, usdcDomainVersionFor as bd, verifyDrainReceipt as be, verifyFundingReceipt as bf, verifyReceipt as bg, x402NetworkToCaip2 as bh, type X402ExactVersionSupport as bi, type X402Receipt as bj, type TransactionalPayoutHook as bk, type CashuMeltCompleted as bl, type CreditDepositPayload as bm, type CreditDrainPayload as bn, type FundingLot as bo, type LotDebit as bp, type LotDepletion as bq, type MppxServer as br, NON_CHANNEL_BITCOIN_RAILS as bs, type NonChannelBitcoinRail as bt, PayoutReporter as bu, PostgresTempoSessionStore as bv, RevenueReporter as bw, SIGNED_ENVELOPE_FIELDS as bx, SIGNED_ENVELOPE_TYPES as by, type X402TrackedChannel as bz, type CancelContent as c, type CreditDrawReleaseEnqueue as c$, type TempoCreditLossEvidence as c0, type CreditLedgerQuerier as c1, type TempoCreditLoss as c2, type X402CreditLossEvidence as c3, type X402CreditLoss as c4, type DrainMethod as c5, type DrainRequestResult as c6, type BitcoinDepositLiability as c7, type CreditDrainRecord as c8, type ChannelDrainCursor 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, parseClientCapabilities as cM, parseClientCompatibility as cN, parseDvmClient as cO, parseProtocolVersion as cP, requireClientCompatibility as cQ, secp256k1Auth as cR, signedRequestInput as cS, type X402SettlementIntent as cT, type X402SettlementCursor as cU, type X402SettlementWriteOff as cV, type X402FacilitatorAuth as cW, type X402BatchSettlementConfig as cX, type X402PayoutObserver as cY, type CreditDepositEnqueue as cZ, type X402SettlementReconciliationReason as c_, type DrainWriteOff as ca, type DrainReleaseResult as cb, type DrainFulfilment as cc, type DrainTransitionResult as cd, CLIENT_COMPATIBILITY_HEADERS as ce, type ClientCompatibility as cf, type ClientCompatibilityEnv as cg, type ClientCompatibilityGate as ch, type ClientCompatibilityRequirement as ci, type ClientSemVer as cj, type CreditFundingBasis as ck, type CreditInvoiceStatus as cl, CreditLedger as cm, CreditLedgerError as cn, type CreditLedgerErrorCode as co, type CreditLedgerErrorDetails as cp, type CreditLedgerPool as cq, type CreditStatus as cr, DRAIN_DELIVERY_RESERVE_SATS as cs, DVM_PROTOCOL_VERSION as ct, type DrainConflictReason as cu, type DrawRailValue as cv, type DrawStatus as cw, type JobCostReportPayload as cx, type JobTerminalReportPayload as cy, PostgresX402ChannelStorage as cz, 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, DEFAULT_JOB_RETENTION_DAYS as k, type DVMRouteContext as l, type InputType as m, InvalidCurrencyError as n, type PaymentMethod as o, type PriceValue as p, type ProgressContent as q, type PromptOpts as r, type QuoteContext as s, type QuoteResult as t, type ResponseContent as u, type SDKPaymentRequestOpts as v, SIGNED_REQUEST_AUTH_ID as w, SIGNED_REQUEST_STATEMENT_VERSION as x, type SignedRequestAudience as y, type SignedRequestDomain as z };
|