@dvmkit/sdk 0.5.0-rc.1 → 0.7.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +100 -0
  2. package/dist/{chunk-JH3SX3LY.js → chunk-6XF3RVVX.js} +1 -1
  3. package/dist/chunk-AFV77S4C.js +258 -0
  4. package/dist/{chunk-RLTSCKRI.js → chunk-BPYMEMQX.js} +50 -3
  5. package/dist/chunk-BQJIFRAZ.js +36 -0
  6. package/dist/{chunk-IWQHUSMO.js → chunk-CXCQLOOK.js} +143 -2
  7. package/dist/{chunk-PB4FYZET.js → chunk-EQLA4FFY.js} +54 -4
  8. package/dist/{chunk-LE74UEV7.js → chunk-EZXAJ6EI.js} +64 -53
  9. package/dist/{chunk-FI4CST2D.js → chunk-FWGWLPXF.js} +4 -6
  10. package/dist/{chunk-EYTHFFFU.js → chunk-GY66THYI.js} +179 -56
  11. package/dist/{chunk-TZ2WKCDD.js → chunk-HCLVYZUZ.js} +2 -2
  12. package/dist/{chunk-O5AT6S5T.js → chunk-IV6Q7NRW.js} +25 -195
  13. package/dist/{chunk-UOCZXO2Z.js → chunk-JEVLNAO3.js} +10 -5
  14. package/dist/{chunk-TUA7PYH7.js → chunk-KMED3H3A.js} +134 -130
  15. package/dist/{chunk-Z4KLECAC.js → chunk-N5RZ5HVB.js} +1 -1
  16. package/dist/{chunk-PAIM66YA.js → chunk-NFMOPYBA.js} +47 -37
  17. package/dist/{chunk-B2IROPQF.js → chunk-O2OTZ5GP.js} +40 -15
  18. package/dist/{chunk-FYRR2UEZ.js → chunk-OML32F6I.js} +1 -1
  19. package/dist/{chunk-6DOGTAHA.js → chunk-QR2EF2NI.js} +9 -43
  20. package/dist/{chunk-7ZUKL4IV.js → chunk-RA2WIX7G.js} +5 -5
  21. package/dist/{chunk-A4YFWZ7R.js → chunk-RCM3P2HE.js} +1 -1
  22. package/dist/{chunk-PLG4XER6.js → chunk-S3OY533W.js} +1 -1
  23. package/dist/{chunk-GFY5FRX3.js → chunk-SZVXOQ75.js} +5 -12
  24. package/dist/{chunk-MZRJR2CW.js → chunk-WBOKPC37.js} +22 -3
  25. package/dist/content-retention-DHyLdA6b.d.ts +78 -0
  26. package/dist/{credit-ledger-MI2H7NEC.js → credit-ledger-MCUXYKSJ.js} +2 -3
  27. package/dist/{credit-menu-CAfqe8IY.d.ts → credit-menu-DjnkeEUU.d.ts} +98 -5
  28. package/dist/{fx-D9nsN3n4.d.ts → fx-zMWFzfrU.d.ts} +1 -1
  29. package/dist/index.d.ts +5 -5
  30. package/dist/index.js +3 -3
  31. package/dist/internal/caller.d.ts +1369 -860
  32. package/dist/internal/caller.js +1079 -991
  33. package/dist/internal/index.js +1 -1
  34. package/dist/internal/server.d.ts +8 -99
  35. package/dist/internal/server.js +19 -18
  36. package/dist/{job-store-Bx-VFRjg.d.ts → job-store-DdLXBpol.d.ts} +1 -1
  37. package/dist/{lightning-backend-BAx2Y8pP.d.ts → lightning-backend-Bw-qtAbt.d.ts} +4 -2
  38. package/dist/{memory-credit-ledger-W2BAUYJP.js → memory-credit-ledger-SBSMGMDX.js} +3 -4
  39. package/dist/{postgres-consumed-credential-store-CUQJKRSL.js → postgres-consumed-credential-store-BUVCAPLS.js} +13 -0
  40. package/dist/{postgres-job-store-VLXLWXUQ.js → postgres-job-store-VHLQBJZC.js} +3 -1
  41. package/dist/server/index.d.ts +28 -10
  42. package/dist/server/index.js +34 -24
  43. package/dist/{step-cache-QG_h5-3G.d.ts → step-cache-2MkvenJn.d.ts} +3 -3
  44. package/dist/tempo-lifecycle-GJ77YKVY.js +15 -0
  45. package/dist/{tempo-wallet-B5XXV3YH.js → tempo-wallet-X2GGAZ6X.js} +4 -4
  46. package/dist/testing/index.d.ts +9 -2
  47. package/dist/testing/index.js +6 -3
  48. package/dist/{usd-EwRqCPF-.d.ts → usd-DI3d3gTK.d.ts} +1 -1
  49. package/dist/{x402-R6HPBY5D.js → x402-FT4S4JS4.js} +8 -10
  50. package/package.json +5 -3
  51. package/recipes/postgres/financial-export-v1.sql +137 -0
  52. package/dist/chunk-CZULM42S.js +0 -143
  53. package/dist/chunk-LIRAHP7B.js +0 -53
  54. package/dist/tempo-lifecycle-ZBBLFBMH.js +0 -15
@@ -1,16 +1,16 @@
1
- import { L as LightningTransactionListOptions, a as LightningTransactionSnapshot, b as LightningBackend, c as LightningPayment, d as LightningWalletInfo, C as CreatedInvoice, I as InvoiceStatus, M as MintAmountBounds, e as MintHealthCheckResult } from '../lightning-backend-BAx2Y8pP.js';
2
- export { A as AttestationPayload, B as BuilderIdentityKeypair, f as CheckMintHealthOptions, g as LockPubkey, h as amountBoundsVerdict, i as assertNutSupport, j as buildAttestation, k as canSwap, l as checkMintHealth, m as generateIdentity, n as hashCapabilities, o as loadIdentitySecret, s as signAttestation, t as toLockPubkey, v as verifyAttestation, w as writeIdentity } from '../lightning-backend-BAx2Y8pP.js';
3
- import { ProofLike, MeltQuoteBolt11Response, Proof, Wallet, SerializedDLEQ, MintQuoteBolt11Response, MintQuoteState, MintPreview, OutputDataLike, CounterSource, CounterRange } from '@cashu/cashu-ts';
1
+ import { L as LightningTransactionListOptions, a as LightningTransactionSnapshot, b as LightningBackend, c as LightningPayment, d as LightningWalletInfo, C as CreatedInvoice, I as InvoiceStatus, M as MintAmountBounds, e as MintHealthCheckResult } from '../lightning-backend-Bw-qtAbt.js';
2
+ export { A as AttestationPayload, B as BuilderIdentityKeypair, f as CheckMintHealthOptions, g as LockPubkey, h as amountBoundsVerdict, i as assertNutSupport, j as buildAttestation, k as canSwap, l as checkMintHealth, m as generateIdentity, n as hashCapabilities, o as loadIdentitySecret, p as meltAmountBounds, s as signAttestation, t as toLockPubkey, v as verifyAttestation, w as writeIdentity } from '../lightning-backend-Bw-qtAbt.js';
3
+ import { ProofLike, MeltQuoteBolt11Response, Proof, Wallet, SerializedDLEQ, MintQuoteBolt11Response, MintQuoteState, MintPreview, OutputData, OutputDataLike, CounterSource, CounterRange } from '@cashu/cashu-ts';
4
4
  export { g as getWallet } from '../wallet-Dwjs5n_M.js';
5
- import { W as JsonValue, z as SignedRequestDomain, H as SignedRequestStatementHeader, X as FundingReceipt, Y as JobReceipt$1, y as SignedRequestAudience, _ as PaymentRequired, $ as X402Version, a0 as MppxCredential, a1 as Message, a2 as MessageType, a3 as MppxChallenge, a4 as X402_BATCH_SETTLEMENT_SCHEME, a5 as X402_EXACT_SCHEME, a6 as DrainReceipt, a7 as ReceiptCredit, C as Currency, a8 as X402Wallet, L as Logger$1, K as KVStore, a9 as ResourceInfo } from '../step-cache-QG_h5-3G.js';
6
- export { aa as BuildPaymentRequirementsOpts, ab as CapabilityDescriptor, ac as CashuMode, ad as CompleteContent, ae as DrainReceiptEvent, af as ExactEvmPayload, ag as ExactEvmPayloadAuthorization, ah as FundingMethod, ai as MessageFrom, aj as PaymentPayload, ak as PaymentPayloadV1, al as PaymentPayloadV2, am as PaymentRequestContent, an as PaymentRequiredV2, ao as PaymentRequirements, ap as PaymentRequirementsV1, aq as PaymentRequirementsV2, ar as PromptContent, as as RAIL_REFUNDABLE, at as ReceiptOutcome, au as ReceiptPayment, av as SettleResponse, aw as StepCache, ax as StepRecord, ay as TextContent, az as UnsignedDrainReceipt, aA as UnsignedFundingReceipt, aB as UnsignedJobReceipt, aC as VerifyResponse, aD as WorkingContent, aE as X402Config, aF as X402ResponseBody, aG as X402SelfRelayRpcFailureReason, aH as X402_DEFAULT_NETWORK, aI as X402_V1_VERSION, aJ as X402_VERSION, aK as buildPaymentRequiredV2, aL as buildPaymentRequirements, aM as caip2ToX402Network, aN as canonicalRequestPath, aO as canonicaliseForSigning, aP as canonicalize, aQ as chainIdFromCaip2, aR as computeResultHash, aS as decodePayment, aT as decodePaymentRequiredHeader, aU as encodePayment, aV as encodePaymentRequiredHeader, aW as encodeSettleResponseHeader, aX as exactEvmAuthorization, aY as isArtifactMessage, aZ as isCancelMessage, a_ as isCompleteMessage, a$ as isDrainReceipt, b0 as isFundingReceipt, b1 as isPaymentRequestMessage, b2 as isPromptMessage, b3 as isSignedJobReceipt, b4 as isTextMessage, b5 as isWorkingMessage, b6 as paymentRequiredV2FromV1, b7 as signDrainReceipt, b8 as signFundingReceipt, b9 as signReceipt, ba as usdcContractByCaip2, bb as usdcContractFor, bc as usdcDomainNameFor, bd as usdcDomainVersionFor, be as verifyDrainReceipt, bf as verifyFundingReceipt, bg as verifyReceipt, bh as x402NetworkToCaip2 } from '../step-cache-QG_h5-3G.js';
5
+ import { W as JsonValue, z as SignedRequestDomain, H as SignedRequestStatementHeader, X as X402_BATCH_SETTLEMENT_SCHEME, Y as X402_EXACT_SCHEME, _ as FundingReceipt, $ as JobReceipt$1, y as SignedRequestAudience, a0 as PaymentRequired, a1 as X402Version, a2 as MppxCredential, a3 as Message, a4 as MessageType, a5 as MppxChallenge, a6 as DrainReceipt, a7 as ReceiptCredit, C as Currency, a8 as X402Wallet, L as Logger$1, K as KVStore, a9 as PaymentRequirementsV1, aa as PaymentRequirementsV2, ab as ResourceInfo } from '../step-cache-2MkvenJn.js';
6
+ export { ac as BuildPaymentRequirementsOpts, ad as CapabilityDescriptor, ae as CashuMode, af as CompleteContent, ag as DrainReceiptEvent, ah as ExactEvmPayload, ai as ExactEvmPayloadAuthorization, aj as FundingMethod, ak as MessageFrom, al as PaymentPayload, am as PaymentPayloadV1, an as PaymentPayloadV2, ao as PaymentRequestContent, ap as PaymentRequiredV2, aq as PaymentRequirements, ar as PromptContent, as as RAIL_REFUNDABLE, at as ReceiptOutcome, au as ReceiptPayment, av as SettleResponse, aw as StepCache, ax as StepRecord, ay as TextContent, az as UnsignedDrainReceipt, aA as UnsignedFundingReceipt, aB as UnsignedJobReceipt, aC as VerifyResponse, aD as WorkingContent, aE as X402Config, aF as X402ResponseBody, aG as X402SelfRelayRpcFailureReason, aH as X402_DEFAULT_NETWORK, aI as X402_V1_VERSION, aJ as X402_VERSION, aK as buildPaymentRequiredV2, aL as buildPaymentRequirements, aM as caip2ToX402Network, aN as canonicalRequestPath, aO as canonicaliseForSigning, aP as canonicalize, aQ as chainIdFromCaip2, aR as computeResultHash, aS as decodePayment, aT as decodePaymentRequiredHeader, aU as encodePayment, aV as encodePaymentRequiredHeader, aW as encodeSettleResponseHeader, aX as exactEvmAuthorization, aY as isArtifactMessage, aZ as isCancelMessage, a_ as isCompleteMessage, a$ as isDrainReceipt, b0 as isFundingReceipt, b1 as isPaymentRequestMessage, b2 as isPromptMessage, b3 as isSignedJobReceipt, b4 as isTextMessage, b5 as isWorkingMessage, b6 as paymentRequiredV2FromV1, b7 as signDrainReceipt, b8 as signFundingReceipt, b9 as signReceipt, ba as usdcContractByCaip2, bb as usdcContractFor, bc as usdcDomainNameFor, bd as usdcDomainVersionFor, be as verifyDrainReceipt, bf as verifyFundingReceipt, bg as verifyReceipt, bh as x402NetworkToCaip2 } from '../step-cache-2MkvenJn.js';
7
7
  import { SimplePool } from 'nostr-tools/pool';
8
8
  import { Session } from 'mppx/tempo';
9
9
  import { Pool } from 'pg';
10
10
  import { PaymentRequired as PaymentRequired$1 } from '@x402/core/types';
11
11
  import { ClientChannelStorage, BatchSettlementClientContext, BatchSettlementEvmScheme } from '@x402/evm/batch-settlement/client';
12
- export { e as FX_CACHE_TTL_MS, g as FX_RETRY_COUNT, w as warmFxSnapshot } from '../fx-D9nsN3n4.js';
13
- export { c as InvalidUsdPriceError, p as parseUsdPrice } from '../usd-EwRqCPF-.js';
12
+ export { e as FX_CACHE_TTL_MS, g as FX_RETRY_COUNT, w as warmFxSnapshot } from '../fx-zMWFzfrU.js';
13
+ export { c as InvalidUsdPriceError, p as parseUsdPrice } from '../usd-DI3d3gTK.js';
14
14
  import 'hono';
15
15
  import 'mppx';
16
16
  import '@x402/core/server';
@@ -103,15 +103,16 @@ interface BudgetSpendBreakdown {
103
103
  /** USD moved into DVM prepaid credits. */
104
104
  creditFundingsUsd: number;
105
105
  }
106
- /** Load the persisted ledger. Returns an empty ledger if the file is missing or corrupt. */
107
- declare function loadLedger(): BudgetLedger;
108
- /**
109
- * Persist the ledger using a temp-file-and-rename so a crash mid-write cannot
110
- * leave a partial JSON on disk (which would silently reset configured caps).
111
- * Confirmed spending is retained indefinitely; budget checks apply their own
112
- * window cutoffs. The optional clock is retained for existing callers.
113
- */
114
- declare function saveLedger(ledger: BudgetLedger, _now?: Date): void;
106
+ type BudgetCheckResult = {
107
+ ok: true;
108
+ } | {
109
+ ok: false;
110
+ window: BudgetWindow;
111
+ spentUsd: number;
112
+ limitUsd: number;
113
+ resetsAt: number;
114
+ breakdown: BudgetSpendBreakdown;
115
+ };
115
116
  interface RecordSpendOptions {
116
117
  msats: number;
117
118
  principalMsats?: number;
@@ -130,6 +131,28 @@ interface RecordSpendOptions {
130
131
  labelSource?: "provider";
131
132
  now?: Date;
132
133
  }
134
+ /**
135
+ * Check whether a planned spend would exceed any configured cap.
136
+ * Returns the first window violated; if multiple windows would be exceeded,
137
+ * the daily window is reported first, then weekly, then monthly.
138
+ */
139
+ declare function checkBudgetForLedger(ledger: BudgetLedger, opts: {
140
+ plannedMsats: number;
141
+ btcRate: number;
142
+ now?: Date;
143
+ }): BudgetCheckResult;
144
+ /** Normalise an entry's kind — legacy entries were all job spends. */
145
+ declare function entryKind(entry: BudgetLedgerEntry): BudgetSpendKind;
146
+ /** UTC-anchored start of the current window containing `now`. */
147
+ declare function windowStart(window: BudgetWindow, now: Date): Date;
148
+ /** UTC-anchored end (exclusive) of the current window containing `now`. */
149
+ declare function windowEnd(window: BudgetWindow, now: Date): Date;
150
+ declare function spendEntry(opts: RecordSpendOptions): BudgetLedgerEntry;
151
+ declare function capFor(caps: BudgetCaps, window: BudgetWindow): number | undefined;
152
+ declare function breakdownSince(entries: BudgetLedgerEntry[], sinceMs: number): BudgetSpendBreakdown;
153
+
154
+ declare function loadLedger(): BudgetLedger;
155
+ declare function saveLedger(ledger: BudgetLedger, _now?: Date): void;
133
156
  declare function recordSpend(opts: RecordSpendOptions): void;
134
157
  /**
135
158
  * Enforce the global budget caps before a planned spend.
@@ -160,10 +183,6 @@ declare function statusSnapshot(now?: Date): {
160
183
  breakdown: BudgetSpendBreakdown;
161
184
  }[];
162
185
  };
163
- /** Normalise an entry's kind — legacy entries were all job spends. */
164
- declare function entryKind(entry: BudgetLedgerEntry): BudgetSpendKind;
165
- /** UTC-anchored start of the current window containing `now`. */
166
- declare function windowStart(window: BudgetWindow, now: Date): Date;
167
186
 
168
187
  /** Stable response code for unavailable database-backed admin signer state. */
169
188
  declare const ADMIN_STATE_UNAVAILABLE = "admin_state_unavailable";
@@ -537,6 +556,108 @@ interface ConfigBackupInfo {
537
556
  */
538
557
  declare function describeConfigBackup(slot?: ConfigSnapshotSlot): ConfigBackupInfo | null;
539
558
 
559
+ /** Which x402 funding flavour a top-up at this DVM would take. */
560
+ type X402CreditFlavour = typeof X402_BATCH_SETTLEMENT_SCHEME | typeof X402_EXACT_SCHEME;
561
+ /**
562
+ * Rails accepted by caller funding selection and pin validation. Each rail's orchestration still
563
+ * owns its availability and payment protocol.
564
+ */
565
+ declare const CREDIT_FUND_RAILS: readonly ["cashu", "lightning", "x402", "tempo"];
566
+ type CreditFundRail = (typeof CREDIT_FUND_RAILS)[number];
567
+ /**
568
+ * Lightning invoices fund credit but do not provide a reclaim credential; reclaim uses the other
569
+ * supported payout rails.
570
+ */
571
+ declare const CREDIT_DRAIN_RAILS: readonly ["cashu", "x402", "tempo"];
572
+ type CreditDrainRail = (typeof CREDIT_DRAIN_RAILS)[number];
573
+ declare function isCreditFundRail(value: unknown): value is CreditFundRail;
574
+ /**
575
+ * The two rails that hold value in a stablecoin, and the only ones where the
576
+ * caller has an instrument to choose. Ecash and Lightning fund a
577
+ * credit by paying once; neither has a reusable form, so a funding mode narrows
578
+ * the eligible set to these two rather than reordering the whole list.
579
+ */
580
+ declare const STABLECOIN_FUND_RAILS: readonly ["x402", "tempo"];
581
+ declare function isStablecoinFundRail(rail: CreditFundRail): boolean;
582
+ /**
583
+ * How a stablecoin credit funding is paid for — the customer-level choice
584
+ * underneath a rail.
585
+ *
586
+ * Both modes fund **prepaid credit**; they are not "pay one job" versus "buy
587
+ * credit". What differs is the instrument: a `one-shot` funding is a single
588
+ * payment that settles and is done, while a `reusable` one puts up channel
589
+ * collateral that later top-ups draw against. The rail-native names —
590
+ * `charge` / `session` on Tempo, `exact` / `batch-settlement` on x402 — are the
591
+ * wire spelling of the same two choices and stay subordinate to them.
592
+ */
593
+ declare const CREDIT_FUNDING_MODES: readonly ["one-shot", "reusable"];
594
+ /** One-shot payment or reusable channel collateral, for a stablecoin funding. */
595
+ type CreditFundingMode = (typeof CREDIT_FUNDING_MODES)[number];
596
+ declare function isCreditFundingMode(value: unknown): value is CreditFundingMode;
597
+ declare function fundingModeForTempoIntent(intent: "charge" | "session"): CreditFundingMode;
598
+ declare function fundingModeForX402Flavour(flavour: X402CreditFlavour): CreditFundingMode;
599
+ /**
600
+ * The `fund.amount_micro` a fund-and-draw must sign for a token of
601
+ * `fundMsats`, mirroring the server's `fundedMicroFor` exactly:
602
+ * pro-rata at the quote-pinned ratio `priceMicroServer ↔ requiredMsats`,
603
+ * with the exact-payment case returning the fiat price with zero drift.
604
+ * Both inputs must be **server-authored**, and since the behavior was introduced both are exact
605
+ * integers on the same 402: `required_msats` and `price_micro`, resolved
606
+ * against one fx snapshot. A client-fx-derived figure — or one reconstructed by
607
+ * multiplying a rendered decimal price by a million — is refused with
608
+ * `funding_commitment_mismatch` after the spend has already committed. Taking
609
+ * the fiat half from a separate `/v1/quote` hop is the weaker fallback for
610
+ * providers that state no `price_micro`: that hop re-prices, so its figure and
611
+ * the 402's `required_msats` are two independent resolutions of one ratio.
612
+ *
613
+ * Cashu-shaped, which is all v1 funds on: x402 takes the same ratio against
614
+ * the 402's advertised `maxAmountRequired` in µUSDC rather than through
615
+ * millisatoshis, so a caller-side x402 fund needs its
616
+ * own derivation rather than this one.
617
+ */
618
+ declare function fundWireAmountMicro(priceMicroServer: number, fundMsats: number, requiredMsats: number): number;
619
+ /**
620
+ * What a `funding_commitment_mismatch` refusal says about the provider's own
621
+ * valuation of the artifact attached.
622
+ *
623
+ * The three cases are not interchangeable to a caller holding proofs that are
624
+ * already P2PK-locked to the provider: only `absent` means no re-sign can ever
625
+ * land, and only that case is safe to give up on.
626
+ */
627
+ type FundValuation =
628
+ /** A usable figure. A corrected re-sign carries exactly this. */
629
+ {
630
+ kind: "figure";
631
+ micro: number;
632
+ }
633
+ /** The provider stated a valuation, but not one that can be signed (zero, negative, fractional, out of range). */
634
+ | {
635
+ kind: "malformed";
636
+ }
637
+ /** No valuation stated at all: the commitment-hash branch, which re-signing can never fix. */
638
+ | {
639
+ kind: "absent";
640
+ };
641
+ /**
642
+ * Read the provider's valuation off a `funding_commitment_mismatch` body — the
643
+ * figure a corrected re-sign must carry. Prefers the structured
644
+ * `expected_micro` field; falls back to the figure the message states ("… at
645
+ * the quoted price (130769)") for providers that predate it, including when the
646
+ * structured field is present but unusable.
647
+ *
648
+ * A provider that stated *something* is on the amount branch even when what it
649
+ * stated is garbage, so that case returns `malformed` rather than `absent`. The
650
+ * two must not collapse: a caller that treats "the provider emitted a bad field"
651
+ * as "uncorrectable" drops the entry and burns proofs it could have held.
652
+ *
653
+ * Shared by both recovery legs: the in-flight retry in `request.ts` and the
654
+ * crash-resume sweep in `wallet-agent/recovery-submissions.ts`.
655
+ */
656
+ declare function readFundValuation(fields: {
657
+ expectedMicro?: unknown;
658
+ message?: string;
659
+ }): FundValuation;
660
+
540
661
  /**
541
662
  * Multi-rail abstraction for the agent wallet. Each `Rail` is a
542
663
  * concrete payment path the CLI knows how to execute end-to-end against a
@@ -559,6 +680,10 @@ type Rail = "cashu_p2pk" | "tempo" | "x402";
559
680
  */
560
681
  type RailFlag = "cashu" | "tempo" | "x402";
561
682
  declare const RAIL_FLAGS: readonly RailFlag[];
683
+ /** The largest advertised figure {@link withinAdvertisedTolerance} accepts against `localMicro`. */
684
+ declare function maxAdvertisedMicro(localMicro: bigint): bigint;
685
+ /** True when the DVM's advertised amount is close enough to the caller's own to sign. */
686
+ declare function withinAdvertisedTolerance(advertisedMicro: bigint, localMicro: bigint): boolean;
562
687
 
563
688
  interface Config {
564
689
  nwcUri?: string;
@@ -1247,6 +1372,35 @@ declare function floatBudgetJson(float: Pick<Float, "statedBudget">, walletRepor
1247
1372
  */
1248
1373
  declare function toFloatError(err: unknown): DvmError;
1249
1374
 
1375
+ /**
1376
+ * The trust anchor a receipt chains to — `/v1/info#builder`, verbatim.
1377
+ * Snapshotted alongside each stored receipt so verification stays offline and
1378
+ * an exported bundle is self-verifying by a third party.
1379
+ */
1380
+ interface ReceiptTrustAnchor {
1381
+ /** Builder identity x-only pubkey (64 hex). */
1382
+ pubkey: string;
1383
+ /** Deploy-time attestation payload, as served. */
1384
+ attestation: Record<string, unknown>;
1385
+ /** BIP-340 signature over the attestation, under {@link pubkey}. */
1386
+ signature: string;
1387
+ }
1388
+ /**
1389
+ * What one live `/v1/info` read learned about an endpoint's trust anchor.
1390
+ *
1391
+ * The two ways to come back without an anchor are different facts and must not
1392
+ * collapse into one: a DVM that answered and published no `builder` block has
1393
+ * told us it has none, while a DVM we could not reach has told us nothing. A
1394
+ * caller holding a previously pinned anchor needs them apart before it decides
1395
+ * whether to drop it.
1396
+ */
1397
+ interface TrustAnchorRead {
1398
+ /** `true` when `/v1/info` answered — so an absent {@link anchor} is the DVM's own word. */
1399
+ reachable: boolean;
1400
+ /** The anchor as served. Absent when the DVM publishes none, or when unreachable. */
1401
+ anchor?: ReceiptTrustAnchor;
1402
+ }
1403
+
1250
1404
  /**
1251
1405
  * Receipt provenance requires a valid signature, an immutable DVM ID matching
1252
1406
  * the builder attestation, a signing key named by that attestation, and a
@@ -1268,19 +1422,7 @@ declare function toFloatError(err: unknown): DvmError;
1268
1422
  */
1269
1423
  type ReceiptVerification = "verified" | "verified_unattested" | "invalid" | "absent";
1270
1424
  type ReceiptInvalidReason = "job_id_mismatch" | "drain_id_mismatch" | "credit_id_mismatch" | "fund_id_mismatch" | "funding_amount_mismatch" | "funding_balance_mismatch" | "funding_ledger_seq_mismatch" | "caller_pubkey_mismatch" | "signature_invalid" | "attestation_invalid" | "dvm_identity_mismatch" | "receipt_key_mismatch" | "result_hash_mismatch";
1271
- /**
1272
- * The trust anchor a receipt chains to — `/v1/info#builder`, verbatim.
1273
- * Snapshotted alongside each stored receipt so verification stays offline and
1274
- * an exported bundle is self-verifying by a third party.
1275
- */
1276
- interface ReceiptTrustAnchor {
1277
- /** Builder identity x-only pubkey (64 hex). */
1278
- pubkey: string;
1279
- /** Deploy-time attestation payload, as served. */
1280
- attestation: Record<string, unknown>;
1281
- /** BIP-340 signature over the attestation, under {@link pubkey}. */
1282
- signature: string;
1283
- }
1425
+
1284
1426
  /**
1285
1427
  * The pair two hostnames must present identically before caller state may be
1286
1428
  * pooled across them.
@@ -2295,6 +2437,7 @@ interface DescribeOptions {
2295
2437
 
2296
2438
  type ChannelStore = ReturnType<typeof Session.Client.createJsonChannelStore>;
2297
2439
  type ChannelEntry = NonNullable<Awaited<ReturnType<ChannelStore["get"]>>>;
2440
+ type TempoChannelDescriptor = ChannelEntry["descriptor"];
2298
2441
  /** A durable link from a local Tempo channel to one DVM prepaid credit. */
2299
2442
  interface TempoChannelAssociation {
2300
2443
  /** Normalised DVM origin. */
@@ -2320,6 +2463,12 @@ interface TempoChannelAssociation {
2320
2463
  /** Epoch ms of the latest channel-store update. */
2321
2464
  updatedAt: number;
2322
2465
  }
2466
+ interface TempoChannelStoreContext {
2467
+ callerPubkey: string;
2468
+ endpoint?: string;
2469
+ creditId?: string;
2470
+ operator?: string;
2471
+ }
2323
2472
  /**
2324
2473
  * A one-shot Tempo `charge` retained until its funding response is
2325
2474
  * acknowledged.
@@ -2385,6 +2534,14 @@ interface PendingTempoChargeFunding {
2385
2534
  */
2386
2535
  credentialValidBefore?: number;
2387
2536
  }
2537
+ /**
2538
+ * How long an unanswered charge holds its credit before the journal gives up on
2539
+ * it. A backstop rather than the usual exit: every definite answer from the DVM
2540
+ * funded, refused, bound elsewhere — clears the entry outright, so the only
2541
+ * way to reach this line is a DVM that stayed unreachable for a day, during
2542
+ * which no rail could have funded that credit anyway.
2543
+ */
2544
+ declare const TEMPO_CHARGE_PENDING_STALE_MS: number;
2388
2545
  /**
2389
2546
  * Serialize channel voucher and lifecycle transitions across CLI processes.
2390
2547
  * TIP-1034 credentials advance cumulative authority from durable state, so
@@ -2392,8 +2549,11 @@ interface PendingTempoChargeFunding {
2392
2549
  * around individual storage calls.
2393
2550
  */
2394
2551
  declare function withTempoChannelLock<T>(operation: () => Promise<T>): Promise<T>;
2552
+ /** Create mppx's JSON channel store over the caller's durable state file. */
2553
+ declare function createTempoChannelStore(context: TempoChannelStoreContext): ChannelStore;
2395
2554
  declare function listTempoChannelAssociations(): TempoChannelAssociation[];
2396
2555
  declare function loadTempoChannelAssociation(endpoint: string, callerPubkey: string, creditId: string): TempoChannelAssociation | undefined;
2556
+ declare function loadTempoChannelAssociationByKey(callerPubkey: string, operator: string, channelKey: string): TempoChannelAssociation | undefined;
2397
2557
  declare function loadTempoChannelEntry(association: TempoChannelAssociation): Promise<ChannelEntry | undefined>;
2398
2558
  /**
2399
2559
  * The wallets a recorded channel's descriptor authorizes over its collateral.
@@ -2417,17 +2577,55 @@ interface TempoChannelController {
2417
2577
  * what {@link tempoChannelControlledBy} calls a stranger's channel.
2418
2578
  */
2419
2579
  declare function loadTempoChannelController(association: TempoChannelAssociation): Promise<TempoChannelController | undefined>;
2580
+ /**
2581
+ * Who a channel descriptor names, in the form {@link tempoChannelControlledBy}
2582
+ * compares, or `undefined` when it names no payer at all.
2583
+ *
2584
+ * A descriptor without a payer is as unattributable as a missing one, and gets
2585
+ * the same answer: nothing is claimed about whose channel it is. The signer is
2586
+ * normalised the way `operator` is on the way in — an absent one is unset — and
2587
+ * the delegation itself is mppx's own rule, so a change to what "unset" means
2588
+ * cannot quietly widen what counts as a stranger's channel.
2589
+ */
2590
+ declare function tempoDescriptorController(descriptor: TempoChannelDescriptor): TempoChannelController | undefined;
2420
2591
  /**
2421
2592
  * Either payer or delegated signer controls the channel. Unknown ownership is
2422
2593
  * treated as controlled; with a known controller, an absent address does not match.
2423
2594
  */
2424
2595
  declare function tempoChannelControlledBy(controller: TempoChannelController | undefined, address: string | undefined): boolean;
2596
+ /** Forget a settled/closed channel and its credit association. */
2597
+ declare function retireTempoChannel(association: TempoChannelAssociation): Promise<void>;
2598
+ /** Forget a terminal channel, every credit associated with it, and its shared entry. */
2599
+ declare function retireTempoChannelScope(association: TempoChannelAssociation): Promise<void>;
2600
+ /**
2601
+ * Whether the journalled credential can still settle, which decides only
2602
+ * whether a resume re-presents it or signs a fresh one under the same fund id.
2603
+ * Never a safety gate: a stale credential presented anyway is refused by the
2604
+ * rail, and an entry whose deadline could not be read is treated as spent.
2605
+ */
2606
+ declare function tempoChargeCredentialSettleable(pending: PendingTempoChargeFunding, now?: number): boolean;
2607
+ /** Persist a verbatim charge credential before it is submitted, replacing this credit's last. */
2608
+ declare function recordPendingTempoChargeFunding(pending: PendingTempoChargeFunding): void;
2609
+ /** The charge funding this credit can still resume, if any. */
2610
+ declare function loadResumableTempoChargeFunding(args: {
2611
+ endpoint: string;
2612
+ callerPubkey: string;
2613
+ creditId: string;
2614
+ now?: number;
2615
+ }): PendingTempoChargeFunding | undefined;
2425
2616
  /** Every charge funding a sweep could still resume, optionally scoped to one DVM identity. */
2426
2617
  declare function listResumableTempoChargeFundings(filter?: {
2427
2618
  endpoint?: string;
2428
2619
  callerPubkey?: string;
2429
2620
  now?: number;
2430
2621
  }): PendingTempoChargeFunding[];
2622
+ /**
2623
+ * Forget one charge funding, because the DVM answered for it or it went stale.
2624
+ * Matched on the fund id as well as the credit key, so a sweep clearing a
2625
+ * lapsed entry cannot drop a fresher one a sibling process journalled in the
2626
+ * meantime.
2627
+ */
2628
+ declare function clearPendingTempoChargeFunding(pending: PendingTempoChargeFunding): void;
2431
2629
 
2432
2630
  /** Dependency-free display names for the token selected by a stablecoin rail. */
2433
2631
  interface RailAsset {
@@ -2610,10 +2808,169 @@ declare function generateTempoKey(opts?: {
2610
2808
  declare function getTempoUsdcBalance(account: TempoAccount): Promise<TempoBalance>;
2611
2809
  declare function deriveTempoAddress(privateKey: `0x${string}`): Promise<`0x${string}`>;
2612
2810
 
2811
+ declare function offersTempoCreditSession(menu: CreditMenu | undefined): boolean;
2812
+ declare function offersTempoCreditCharge(menu: CreditMenu | undefined): boolean;
2813
+ /**
2814
+ * True when a credit menu names `tempo/session` under `withheld` — the DVM is
2815
+ * configured for reusable sessions and is pausing them.
2816
+ *
2817
+ * Distinct from "absent", and the distinction is what a caller acts on. The
2818
+ * pause covers *new* channels only, so a caller already holding an open channel
2819
+ * on this credit may still top it up: the DVM issues that credit a session
2820
+ * challenge, and a one-shot charge is refused against a channel-bound credit
2821
+ * anyway. Absent means the DVM never offered sessions at all, where attempting
2822
+ * one buys nothing.
2823
+ */
2824
+ declare function withholdsTempoCreditSession(menu: CreditMenu | undefined): boolean;
2613
2825
  declare function offersTempoCreditFunding(menu: CreditMenu | undefined): boolean;
2614
2826
  type TempoSessionClientResolver = NonNullable<NonNullable<Parameters<typeof Session.Client.session>[0]>["getClient"]>;
2615
2827
  type TempoSessionMethod = ReturnType<typeof Session.Client.session>;
2616
2828
  type TempoSessionChallenge = Parameters<TempoSessionMethod["createCredential"]>[0]["challenge"];
2829
+ /** Fetch shape used by mppx's challenge-aware Tempo session wrapper. */
2830
+ type TempoSessionPaymentFetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
2831
+ /** Caller-side scope that keeps mppx's reusable key local to one DVM operator. */
2832
+ interface TempoSessionChannelScope {
2833
+ channelKey: string;
2834
+ operator: string;
2835
+ }
2836
+ declare function createTempoCreditSession(args: {
2837
+ account: TempoAccount;
2838
+ endpoint: string;
2839
+ callerPubkey: string;
2840
+ creditId: string;
2841
+ maxDepositMicro: number;
2842
+ topUpAmountMicro: number;
2843
+ operator?: string;
2844
+ getClient?: TempoSessionClientResolver;
2845
+ }): ReturnType<typeof Session.Client.session>;
2846
+ /** Wrap a credit POST bridge so mppx runs its automatic open/top-up hooks. */
2847
+ declare function createTempoSessionPaymentFetch(method: TempoSessionMethod, fetch: typeof globalThis.fetch): TempoSessionPaymentFetch;
2848
+ /** Resolve mppx's payment key together with the DVM operator that may reuse it. */
2849
+ declare function tempoSessionChallengeChannelScope(challenge: TempoSessionChallenge | undefined): TempoSessionChannelScope | undefined;
2850
+ /** Resolve the operator-local payment scope carried by a saved session credential. */
2851
+ declare function tempoSessionCredentialChannelScope(credential: string): TempoSessionChannelScope | undefined;
2852
+ /** Find the existing channel a Tempo session challenge or credential will actually reuse. */
2853
+ declare function tempoSessionAssociationByKey(args: {
2854
+ endpoint: string;
2855
+ callerPubkey: string;
2856
+ channelScope: TempoSessionChannelScope | undefined;
2857
+ creditId: string;
2858
+ }): TempoChannelAssociation | undefined;
2859
+ /**
2860
+ * What the reusable channel this funding will use has already authorized,
2861
+ * in USD micro-units — the cumulative every ceiling on this leg is rebased over.
2862
+ *
2863
+ * A provisional entry (`opened: false`, written before an open is broadcast)
2864
+ * reads as zero, because nothing on it has been authorized yet.
2865
+ */
2866
+ declare function tempoSessionPriorCumulativeMicro(args: {
2867
+ endpoint: string;
2868
+ callerPubkey: string;
2869
+ creditId: string;
2870
+ association?: TempoChannelAssociation;
2871
+ }): number;
2872
+ /** Rebase one funding allowance over a reusable channel's cumulative authorization. */
2873
+ declare function tempoSessionCumulativeCapMicro(args: {
2874
+ endpoint: string;
2875
+ callerPubkey: string;
2876
+ creditId: string;
2877
+ allowanceMicro: number;
2878
+ amountMicro: number;
2879
+ association?: TempoChannelAssociation;
2880
+ }): number;
2881
+ /**
2882
+ * Refuse to broadcast a session credential that would push the credit's
2883
+ * channel deposit above the cap the caller authorized.
2884
+ *
2885
+ * mppx applies that cap before it signs, on every automatic path — its open
2886
+ * clamps the DVM's `suggestedDeposit` to it and refuses a challenge amount
2887
+ * over it, and its top-up refills only the headroom left under it. This is the
2888
+ * belt: dvmkit has no hook between mppx's plan and its signature, so the check
2889
+ * lands on the figure the finished credential commits, which is also the only
2890
+ * figure that can be read rather than trusted. Pre-broadcast is still binding
2891
+ * for a deposit — this bridge is the sole conduit to the DVM and the chain, so
2892
+ * a signed transaction that is never sent locks nothing. The voucher
2893
+ * cumulative rides in a signature rather than a transaction, so it is guarded on
2894
+ * both sides of the signing instead: {@link assertTempoSessionChallengeWithinAsk}
2895
+ * before and {@link assertTempoSessionVoucherWithinAsk} after.
2896
+ */
2897
+ declare function assertTempoSessionDepositWithinCap(args: {
2898
+ credential: string;
2899
+ endpoint: string;
2900
+ callerPubkey: string;
2901
+ creditId: string;
2902
+ capMicro: number;
2903
+ channelScope?: TempoSessionChannelScope;
2904
+ }): void;
2905
+ /**
2906
+ * Refuse a session challenge that asks for materially more than the funding it
2907
+ * is paying for — before mppx signs anything.
2908
+ *
2909
+ * The deposit ceiling above bounds the collateral a channel locks; this bounds
2910
+ * the money the DVM can actually capture out of it. They are different numbers
2911
+ * on purpose: the caller's per-channel allowance is deliberately sized above one
2912
+ * funding so auto-top-up has headroom, and mppx spends that one figure as both
2913
+ * its deposit ceiling and its voucher ceiling — so a challenge naming several
2914
+ * times the ask signs cleanly under it.
2915
+ *
2916
+ * The basis is the funding ask, and the figure measured against it is the
2917
+ * challenge amount, because that amount is always the *delta*: on an open it
2918
+ * becomes the whole cumulative, on a reused channel mppx adds it to a cumulative
2919
+ * the caller already authorized. The tolerance is the shared stablecoin one —
2920
+ * both sides convert dollars from their own BTC/USD rate, so a small
2921
+ * disagreement is legitimate and a large one is a different price.
2922
+ *
2923
+ * Pre-signature is not pre-collateral: a session can re-challenge after mppx has
2924
+ * already opened a channel or had a management top-up accepted, so the refusal
2925
+ * copy claims only that no voucher was signed, and names the recovery path for
2926
+ * collateral this funding may already have locked.
2927
+ */
2928
+ declare function assertTempoSessionChallengeWithinAsk(args: {
2929
+ challenges: readonly MppxChallenge[];
2930
+ basisMicro: number;
2931
+ }): void;
2932
+ /**
2933
+ * The cumulative capture authority a session credential hands the DVM, in USD
2934
+ * micro-units. `undefined` when the credential authorizes none — a management
2935
+ * top-up moves collateral without naming a cumulative, and a replayed journal
2936
+ * entry or hand-rolled header is not an mppx credential at all.
2937
+ */
2938
+ declare function tempoSessionCredentialCumulativeMicro(credential: string): number | undefined;
2939
+ /**
2940
+ * Refuse to broadcast a signed voucher that authorizes materially more capture
2941
+ * than the funding it pays for.
2942
+ *
2943
+ * The belt behind {@link assertTempoSessionChallengeWithinAsk}: that one bounds
2944
+ * a single challenge, and mppx retries a 402 up to five times, so a DVM that
2945
+ * keeps re-challenging at the honest amount would otherwise walk the cumulative
2946
+ * up one ask at a time until it hit the whole per-channel allowance. This bounds
2947
+ * the total for the funding regardless of how many times mppx signs, and it
2948
+ * reads the figure off the credential rather than trusting the challenge that
2949
+ * produced it. Pre-broadcast is binding here for the same reason it is for the
2950
+ * deposit — this bridge is the sole conduit to the DVM, and a voucher that never
2951
+ * leaves the process authorizes nothing.
2952
+ *
2953
+ * `authorizedMicro` is the delta over the cumulative already authorized when
2954
+ * this funding began, so a reused channel is measured on what this funding adds
2955
+ * rather than on everything the channel has ever agreed to pay.
2956
+ *
2957
+ * Collateral is a separate question from capture authority: the open or the
2958
+ * management top-up earlier in this same funding may already have moved some,
2959
+ * so the copy claims only what it knows about the voucher and names the verb
2960
+ * that gets the collateral back.
2961
+ */
2962
+ declare function assertTempoSessionVoucherWithinAsk(args: {
2963
+ authorizedMicro: number;
2964
+ basisMicro: number;
2965
+ }): void;
2966
+ /** Persist an open credential before broadcast so a lost response remains recoverable. */
2967
+ declare function persistTempoOpenCredential(args: {
2968
+ credential: string;
2969
+ endpoint: string;
2970
+ callerPubkey: string;
2971
+ creditId: string;
2972
+ opened: boolean;
2973
+ }): Promise<boolean>;
2617
2974
  /** Read the first Tempo session challenge retained on a `/v1/credit` error. */
2618
2975
  declare function tempoSessionChallenge(err: unknown): TempoSessionChallenge | undefined;
2619
2976
  /**
@@ -2782,8 +3139,6 @@ declare function reconcileTempoChannelOnChain(args: {
2782
3139
  * loop asks without pulling the signing stack in behind it.
2783
3140
  */
2784
3141
 
2785
- /** Which x402 funding flavour a top-up at this DVM would take. */
2786
- type X402CreditFlavour = typeof X402_BATCH_SETTLEMENT_SCHEME | typeof X402_EXACT_SCHEME;
2787
3142
  /**
2788
3143
  * The same two flavours in the server's words.
2789
3144
  *
@@ -2808,6 +3163,31 @@ type X402CreditInstrument = "x402_exact" | "x402_channel";
2808
3163
  * planner's gate can stay scheme-level, the funding loop's is network-exact.
2809
3164
  */
2810
3165
  declare function offersX402CreditFunding(menu: CreditMenu | undefined, network?: string): boolean;
3166
+ /**
3167
+ * True when a menu offers a reusable x402 channel this caller could actually
3168
+ * open — the x402 twin of `offersTempoCreditSession`.
3169
+ *
3170
+ * Narrower than {@link offersX402CreditFunding} on purpose: an exact-only DVM
3171
+ * is fundable but opens nothing to amortize across top-ups, and only the
3172
+ * channel question can distinguish "reconnect on their chain" from "this DVM
3173
+ * opens no channel at all" in the forced-rail hint.
3174
+ */
3175
+ declare function offersX402CreditChannel(menu: CreditMenu | undefined, network?: string): boolean;
3176
+ /**
3177
+ * Which flavour to attempt on this wallet's chain, or `undefined` when neither
3178
+ * is offered there. The channel wins wherever both are advertised: a deposit
3179
+ * amortizes across every later top-up, where an exact authorization costs a
3180
+ * round trip and a signature each time.
3181
+ */
3182
+ declare function x402CreditFlavour(menu: CreditMenu | undefined, network: string): X402CreditFlavour | undefined;
3183
+ /**
3184
+ * True when a menu offers one *named* flavour on this wallet's chain — the
3185
+ * question a credit already bound to that flavour has to ask, where
3186
+ * {@link x402CreditFlavour}'s preference is beside the point.
3187
+ */
3188
+ declare function offersX402CreditFlavour(menu: CreditMenu | undefined, network: string, flavour: X402CreditFlavour): boolean;
3189
+ /** The binding a funding over this flavour leaves on the credit. */
3190
+ declare function x402InstrumentForFlavour(flavour: X402CreditFlavour): X402CreditInstrument;
2811
3191
  /**
2812
3192
  * The flavour a recorded binding pins, or `undefined` for anything that isn't
2813
3193
  * one of x402's two. A cross-rail refusal names its own instrument
@@ -2823,6 +3203,13 @@ declare function x402FlavourForInstrument(instrument: string | undefined): X402C
2823
3203
  declare function x402CreditChannelNetworks(menu: CreditMenu | undefined): string[];
2824
3204
  /** Chains this menu takes a per-call `exact` credit top-up on. */
2825
3205
  declare function x402CreditExactNetworks(menu: CreditMenu | undefined): string[];
3206
+ /**
3207
+ * Every chain this menu takes an x402 top-up on, either flavour, deduplicated.
3208
+ * The set a "your wallet is on the wrong chain" hint has to name — pinning to
3209
+ * the channel networks alone would tell an exact-only DVM's caller to reconnect
3210
+ * to nowhere.
3211
+ */
3212
+ declare function x402CreditFundingNetworks(menu: CreditMenu | undefined): string[];
2826
3213
 
2827
3214
  /**
2828
3215
  * Funds prepaid credit over Cashu, Lightning, x402 or Tempo. Before payment, an unavailable rail
@@ -2835,47 +3222,9 @@ declare function x402CreditExactNetworks(menu: CreditMenu | undefined): string[]
2835
3222
  */
2836
3223
 
2837
3224
  /**
2838
- * Rails accepted by caller funding selection and pin validation. Each rail's orchestration still
2839
- * owns its availability and payment protocol.
2840
- */
2841
- declare const CREDIT_FUND_RAILS: readonly ["cashu", "lightning", "x402", "tempo"];
2842
- type CreditFundRail = (typeof CREDIT_FUND_RAILS)[number];
2843
- /**
2844
- * Lightning invoices fund credit but do not provide a reclaim credential; reclaim uses the other
2845
- * supported payout rails.
2846
- */
2847
- declare const CREDIT_DRAIN_RAILS: readonly ["cashu", "x402", "tempo"];
2848
- type CreditDrainRail = (typeof CREDIT_DRAIN_RAILS)[number];
2849
- declare function isCreditFundRail(value: unknown): value is CreditFundRail;
2850
- /**
2851
- * The two rails that hold value in a stablecoin, and the only ones where the
2852
- * caller has an instrument to choose. Ecash and Lightning fund a
2853
- * credit by paying once; neither has a reusable form, so a funding mode narrows
2854
- * the eligible set to these two rather than reordering the whole list.
2855
- */
2856
- declare const STABLECOIN_FUND_RAILS: readonly ["x402", "tempo"];
2857
- declare function isStablecoinFundRail(rail: CreditFundRail): boolean;
2858
- /**
2859
- * How a stablecoin credit funding is paid for — the customer-level choice
2860
- * underneath a rail.
2861
- *
2862
- * Both modes fund **prepaid credit**; they are not "pay one job" versus "buy
2863
- * credit". What differs is the instrument: a `one-shot` funding is a single
2864
- * payment that settles and is done, while a `reusable` one puts up channel
2865
- * collateral that later top-ups draw against. The rail-native names —
2866
- * `charge` / `session` on Tempo, `exact` / `batch-settlement` on x402 — are the
2867
- * wire spelling of the same two choices and stay subordinate to them.
2868
- */
2869
- declare const CREDIT_FUNDING_MODES: readonly ["one-shot", "reusable"];
2870
- /** One-shot payment or reusable channel collateral, for a stablecoin funding. */
2871
- type CreditFundingMode = (typeof CREDIT_FUNDING_MODES)[number];
2872
- declare function isCreditFundingMode(value: unknown): value is CreditFundingMode;
2873
- declare function fundingModeForTempoIntent(intent: "charge" | "session"): CreditFundingMode;
2874
- declare function fundingModeForX402Flavour(flavour: X402CreditFlavour): CreditFundingMode;
2875
- /**
2876
- * Where a forced rail came from. Kept apart because they are not
2877
- * the same claim: the first three are the caller's preference, the fourth is
2878
- * the DVM's ledger refusing to blend two rails' native value.
3225
+ * Where a forced rail came from. Kept apart because they are not
3226
+ * the same claim: the first three are the caller's preference, the fourth is
3227
+ * the DVM's ledger refusing to blend two rails' native value.
2879
3228
  */
2880
3229
  type CreditRailSource =
2881
3230
  /** `--rail` on this invocation. */
@@ -3212,488 +3561,115 @@ interface CompletedCreditHistoryPage {
3212
3561
  }
3213
3562
 
3214
3563
  /**
3215
- * The terminal-outcome fields a job carries once it is over — the summary, the
3216
- * artifact metadata, and (on a failure) the provider's message. Read off a
3217
- * transport receipt / status response, persisted on the local job record
3218
- * and rendered into the JSON payload by `buildCompletionHintFields`.
3219
- */
3220
- interface JobCompletion {
3221
- /** Human-readable one-liner. Not the payload when artifacts are present. */
3222
- summary?: string;
3223
- /** Provider's status message (typically on a failed job). */
3224
- message?: string;
3225
- /** True when the provider emitted artifact messages. */
3226
- hasArtifacts?: boolean;
3227
- /** Count of artifact messages (present when `hasArtifacts` is true). */
3228
- artifactCount?: number;
3229
- /** Where the payload sits: the `summary` string, or in artifact messages. */
3230
- payloadIn?: "summary" | "messages";
3231
- }
3232
- /**
3233
- * Build the snake_case JSON fields (`has_artifacts`, `artifact_count`,
3234
- * `payload_in`, `next_step_hint`) from a transport receipt or status response.
3235
- * Returns an object meant to be spread into the parent JSON payload — agents
3236
- * relaying a completed-job response need these to know the summary string is
3237
- * a one-liner, not the payload, when the real output sits in artifact messages
3238
- */
3239
- declare function buildCompletionHintFields(jobId: string, input: JobCompletion): Record<string, unknown>;
3240
- /** `--no-stream` replays from seq 0: the stored cursor may already be past the artifacts. */
3241
- declare function nextStepHint(jobId: string, payloadIn: "summary" | "messages" | undefined, artifactCount: number | undefined): string | undefined;
3242
- /**
3243
- * Pick the terminal-outcome fields off a receipt or status response, dropping
3244
- * the ones the provider didn't send. What lands here is what `dvm status`
3245
- * replays from the local record on every later read, so it must be
3246
- * exactly the set the wire read would have rendered — no defaults, no guesses.
3247
- */
3248
- declare function completionSnapshot(src: JobCompletion): JobCompletion;
3249
- /**
3250
- * Derive the terminal snapshot from a streamed message log, for the paths that
3251
- * learn a job is over from the stream rather than a status response. Mirrors
3252
- * the SDK's own derivation (`statusCompletionFields`, `src/sdk/server/app.ts`):
3253
- * `payload_in` is `"messages"` iff any `artifact` message was emitted. Requires
3254
- * the full log (from seq 0) — a partial batch would undercount the artifacts.
3255
- */
3256
- declare function completionFromMessages(messages: Message[]): JobCompletion;
3257
-
3258
- /**
3259
- * Free text supplied by a provider. Agents should treat fields wrapped in this
3260
- * shape with appropriate skepticism — they are subject to prompt injection,
3261
- * social engineering, or simply contain unverified claims about the job.
3564
+ * Per-DVM prepaid-credit working record (`~/.dvm/credits.json`).
3262
3565
  *
3263
- * Wrapping is the structural marker; the JSON shape `{ _source: "provider", text: "..." }`
3264
- * lets an agent's framework distinguish provider-controlled content from CLI-owned
3265
- * instructions without inspecting field paths.
3566
+ * This file is the caller's *expectation*: what it believes each credit's
3567
+ * spendable balance to be, projected from the DVM-signed artifacts it has
3568
+ * already collected (fund responses, job receipts, drain records). It is
3569
+ * bookkeeping, not evidence — the signed balance trajectory lives in
3570
+ * `~/.dvm/receipts.jsonl`, and a mismatch between this file's projection and
3571
+ * a freshly countersigned `balance_after` is exactly what
3572
+ * {@link applyReceiptCredit} exists to surface.
3573
+ *
3574
+ * Mutable working set in the `budget.json` mold: one JSON object, temp-file +
3575
+ * rename writes, malformed *entries* tolerated on read. A malformed **file**
3576
+ * is not: damaged bytes are moved aside and named in the error rather than
3577
+ * replaced with an empty store, a file we merely failed to *open* is left
3578
+ * exactly where it is, and every cycle that touches the store runs under
3579
+ * {@link withCreditLock}.
3266
3580
  */
3267
- interface ProviderText {
3268
- _source: "provider";
3269
- text: string;
3270
- }
3271
- /** Wrap a string as provider-supplied text. */
3272
- declare function asProviderText(text: string): ProviderText;
3273
- /** Wrap a string only if defined; passes through undefined. */
3274
- declare function asProviderTextOpt(text: string | undefined): ProviderText | undefined;
3275
- /** Render a ProviderText (or string) back to plain text — used by --human output paths. */
3276
- declare function providerTextToString(value: string | ProviderText): string;
3277
3581
 
3278
- type NextAction = null | NextActionRespond | NextActionPay | NextActionApprove | NextActionPoll | NextActionRefund;
3279
- interface NextActionRespond {
3280
- type: "respond";
3281
- job_id: string;
3282
- prompt_id: string;
3283
- /** The provider's question. Treat with appropriate skepticism. */
3284
- prompt: ProviderText;
3285
- schema?: Record<string, unknown>;
3286
- /** CLI-owned guidance for the agent. */
3287
- hint: string;
3288
- }
3289
- interface NextActionPay {
3290
- type: "pay";
3291
- job_id: string;
3292
- amount_msats: number;
3582
+ type StoredCreditStatus = "active" | "expired" | "gone" | "drained" | "unbacked";
3583
+ /** A drain in flight — persisted so a re-invoked `dvm credit drain` polls the same id. */
3584
+ interface PendingDrain {
3585
+ /** Caller-minted drain id; doubles as the poll/pickup key server-side. */
3586
+ drainId: string;
3293
3587
  /**
3294
- * The provider's own fiat price for this charge, when it priced in fiat.
3295
- * Mirrors the wire's `fiat_amount` so a typed agent can do budget math
3296
- * against the figure the human is actually being asked to approve.
3588
+ * The server keys drains by (credit_id, drain_id). Only an exact pairing may be auto-reused.
3589
+ * Legacy unstamped entries remain visible but require an explicitly supplied pairing; they
3590
+ * cannot suppress later top-ups.
3297
3591
  */
3298
- fiat_amount?: {
3299
- amount: number;
3300
- currency: string;
3301
- };
3302
- display: string;
3303
- /** The provider's stated reason for the charge. Treat with appropriate skepticism. */
3304
- reason: ProviderText;
3305
- /** CLI-owned guidance for the agent. */
3306
- hint: string;
3307
- }
3308
- /** Provider delivered something and is waiting for sign-off. */
3309
- interface NextActionApprove {
3310
- type: "approve";
3311
- job_id: string;
3312
- artifact_seq: number;
3313
- hint: string;
3314
- }
3315
- /**
3316
- * Provider is working — nothing for the client to do right now.
3317
- * `hint` is a `ProviderText` when supplied by the provider; a plain `string` is the CLI fallback.
3318
- */
3319
- interface NextActionPoll {
3320
- type: "poll";
3321
- job_id: string;
3322
- estimate_seconds?: number;
3323
- hint: string | ProviderText;
3592
+ creditId?: string;
3593
+ method: string;
3594
+ /** Payout destination as signed into the drain request — immutable server-side. */
3595
+ payout: Record<string, string>;
3596
+ /** Epoch ms the drain was first requested. */
3597
+ requestedAt: number;
3598
+ /** Verbatim cooperative-close Authorization value, saved before transmission. */
3599
+ mppCredential?: string;
3324
3600
  }
3325
3601
  /**
3326
- * Provider sent an inbound Cashu payment (refund/change). The CLI auto-claims
3327
- * the proofs; this surfaces the outcome to the agent. `claimed: false` means the
3328
- * claim could not complete (e.g. mint down) and `cashu_token` carries the raw
3329
- * token for manual recovery.
3602
+ * A durable credit funding in flight.
3603
+ *
3604
+ * Kept outside {@link StoredCredit}: an opening funding must be durable before
3605
+ * its invoice request, when no server-confirmed credit exists yet.
3330
3606
  */
3331
- interface NextActionRefund {
3332
- type: "refund";
3333
- job_id: string;
3334
- amount_msats: number;
3335
- display: string;
3336
- reason: "refund" | "change";
3337
- /** Whether the proofs were auto-claimed into the local wallet. */
3338
- claimed: boolean;
3339
- /** Raw Cashu token — present only when the auto-claim failed, for manual recovery. */
3340
- cashu_token?: string;
3341
- /** CLI-owned guidance for the agent. */
3342
- hint: string;
3607
+ interface PendingFunding {
3608
+ /** Normalised endpoint origin the funding was requested from. */
3609
+ endpoint: string;
3610
+ /** x-only pubkey of the signing identity that owns the funding. */
3611
+ callerPubkey: string;
3612
+ /** Caller-minted credit id the invoice is bound to. */
3613
+ creditId: string;
3614
+ /** Caller-minted idempotency key the invoice is bound to. */
3615
+ fundId: string;
3616
+ /** Requested funding amount, in the credit currency's micro-units. */
3617
+ amountMicro: number;
3618
+ /** Funding rail whose money-moving credential must be replayed verbatim. */
3619
+ rail: "lightning" | "tempo";
3620
+ /** Refill target to retain when the funding becomes a stored credit. */
3621
+ targetMicro: number;
3622
+ /** Additional deposit authorization allowed for this durable MPP funding. */
3623
+ maxDepositMicro?: number;
3624
+ /** Funding-menu snapshot to retain when the funding becomes a stored credit. */
3625
+ menu?: CreditMenu;
3626
+ /** Epoch ms the funding intent was first persisted. */
3627
+ requestedAt: number;
3628
+ /** Bolt11 returned by the DVM, once one has been issued. */
3629
+ bolt11?: string;
3630
+ /** Payment hash returned alongside {@link PendingFunding.bolt11}. */
3631
+ paymentHash?: string;
3632
+ /** Invoice amount, in millisatoshis. */
3633
+ amountMsats?: number;
3634
+ /** Absolute invoice expiry, epoch ms. */
3635
+ expiresAtMs?: number;
3636
+ /** Paid invoice principal, in millisatoshis. Present only after money moved. */
3637
+ principalMsats?: number;
3638
+ /** Wallet-reported routing fee. Null means the wallet omitted it. */
3639
+ routingFeeMsats?: number | null;
3640
+ /** Total wallet fee from an exact debit. Null means the total is unprovable. */
3641
+ totalWalletFeeMsats?: number | null;
3642
+ /** Wallet fee not itemized as routing. Null means the split is unprovable. */
3643
+ unitemizedWalletFeeMsats?: number | null;
3644
+ /** Exact wallet debit. Null means wallet evidence could not prove it. */
3645
+ walletDebitMsats?: number | null;
3646
+ /** How the caller wallet reached settlement. */
3647
+ paymentOutcome?: "paid" | "reconciled" | "republished";
3648
+ /** Serialized MPP Authorization credential, persisted before its network send. */
3649
+ mppCredential?: string;
3650
+ /**
3651
+ * What this funding's Tempo session voucher actually authorizes the DVM to
3652
+ * capture, in micro-units — the cumulative it signed, net of whatever the
3653
+ * channel had already authorized when the funding began. Journalled beside
3654
+ * {@link PendingFunding.mppCredential} so a resume books the authorization
3655
+ * rather than the ask.
3656
+ */
3657
+ authorizedMicro?: number;
3658
+ /**
3659
+ * Budget-ledger valuation fixed before an MPP channel credential is created.
3660
+ * The debit itself is not journalled: it is this rate applied to
3661
+ * {@link PendingFunding.authorizedMicro}, so a resume books the figure the
3662
+ * credential authorized rather than one fixed before it existed.
3663
+ */
3664
+ budgetBtcRate?: number;
3343
3665
  }
3344
- /** A job status that means the job is over — nothing left for the caller to do. */
3345
- type TerminalJobStatus = "completed" | "failed" | "cancelled";
3346
3666
  /**
3347
- * True when a job status means the job is over and there is nothing left for
3348
- * the caller to do (`next_action: null`). Every other status — including one
3349
- * this CLI doesn't recognise — is non-terminal: mapping an unknown status to
3350
- * `null` would tell an agent a live job is done.
3351
- */
3352
- declare function isTerminalJobStatus(status: string): status is TerminalJobStatus;
3353
- /**
3354
- * CLI-owned fallback poll action, for job-status snapshots that carry no
3355
- * message log to derive a richer action from.
3356
- */
3357
- declare function pollNextAction(jobId: string, hint?: string): NextActionPoll;
3358
- /**
3359
- * Derive the next action from a batch of messages.
3360
- * Scans from the end for the last yield-type message and returns the
3361
- * appropriate action. Returns null if the job is done (complete/cancel)
3362
- * or no yield message is found.
3363
- */
3364
- declare function computeNextAction(jobId: string, messages: Message[]): NextAction;
3365
-
3366
- interface JobRecord {
3367
- id: string;
3368
- endpoint: string;
3369
- /** Canonical DVM name. Optional for older job records. */
3370
- dvmId?: string;
3371
- /** Router-issued claim authorizing DVM attribution for feedback on this job. */
3372
- feedbackClaim?: string;
3373
- /** Capability dispatched against this DVM. Optional for older job records. */
3374
- capability?: string;
3375
- /** Caller-generated public request id used to recover this exact job. */
3376
- requestId?: string;
3377
- status: "submitted" | "processing" | "completed" | "failed" | "timeout" | "cancelled" | "awaiting-input";
3378
- /** Unix timestamp (ms) when submitted */
3379
- submittedAt: number;
3380
- /** Unix timestamp (ms) when completed/failed */
3381
- completedAt?: number;
3382
- /**
3383
- * the terminal outcome (summary + artifact metadata + failure
3384
- * message), snapshotted the moment the CLI learns the job is over. `dvm status`
3385
- * replays it instead of re-reading the provider, so a finished job answers
3386
- * with the same field set on every call — and still answers with the provider
3387
- * down. Written by `markJobTerminal` in lockstep with a terminal `status`;
3388
- * absent only on records written before this landed.
3389
- */
3390
- completion?: JobCompletion;
3391
- /** Cost in millisatoshis */
3392
- costMsats?: number;
3393
- /** Rail the upfront spend settled on. `credit` — drawn from a prepaid credit. */
3394
- paymentMethod?: "cashu" | "x402" | "tempo" | "credit";
3395
- /** Validated Tempo settlement transaction associated with the request. */
3396
- transactionHash?: string;
3397
- /**
3398
- * Caller-pinned Cashu spend mint. When set, every spend leg for
3399
- * this job (upfront, mid-job `payment-request`, `dvm pay`) draws only from
3400
- * this mint — no fallback to another allowlisted mint.
3401
- */
3402
- pinnedMint?: string;
3403
- /** Request was submitted through the fail-closed direct-Cashu mode. */
3404
- strictPerCall?: true;
3405
- /** Job-wide Cashu swap-fee ceiling in sats, including later recovery swaps. */
3406
- maxCashuFeeSats?: number;
3407
- /** Whether Cashu change has been processed (prevents double-processing on repeated polls) */
3408
- changeProcessed?: boolean;
3409
- /**
3410
- * Sequence numbers of inbound `payment` messages (refund/change) whose Cashu
3411
- * proofs have already been claimed into the local wallet. Per-`seq` (unlike
3412
- * the coarse `changeProcessed`) because a job may carry several such messages,
3413
- * and prevents double-claim on replay/re-poll.
3414
- */
3415
- claimedPaymentSeqs?: number[];
3416
- /** Last seen message sequence number for cursor-based polling */
3417
- messageCursor?: number;
3418
- /** Running total of payments sent (millisatoshis) */
3419
- totalPaidMsats?: number;
3420
- /** Number of payments honoured for this job (auto + manual). */
3421
- paymentsHonoured?: number;
3422
- /** Index of received artifact deliverables. */
3423
- artifacts?: ArtifactRef[];
3424
- /** Spending policy for this job's conversation. */
3425
- policy?: {
3426
- maxTotalMsats: number;
3427
- autoPayBelowMsats: number;
3428
- maxIncrementMsats: number;
3429
- maxPayments: number;
3430
- };
3431
- /**
3432
- * opaque per-job token issued by the DVM at create-time when the
3433
- * caller resolved to anonymous (the default for free DVMs). Persisted on
3434
- * the local job record and sent as `X-Job-Token` on every subsequent
3435
- * `status`/`messages`/`message`/`pay`/`cancel` request. Absent for
3436
- * authenticated callers (bearer / signed-request).
3437
- */
3438
- jobToken?: string;
3439
- /**
3440
- * platform `trace_id` captured from the submit response's
3441
- * `traceparent` header. Persisted locally so `dvm feedback --job <id>` can
3442
- * derive it without re-querying the platform. Absent on legacy job records
3443
- * created before this field landed.
3444
- */
3445
- traceId?: string;
3446
- /**
3447
- * the DVM-signed receipt for this job, snapshotted the moment the
3448
- * CLI first saw it. Lets `dvm status` replay `receipt_verified` from the
3449
- * local record with the provider down, alongside `completion`. The durable
3450
- * copy lives in `~/.dvm/receipts.jsonl` — this one dies with the job record.
3451
- */
3452
- receipt?: JobReceipt$1;
3453
- /** Receipt value was offered but failed the transport's structural guard. */
3454
- receiptParseError?: ReceiptParseError;
3455
- /**
3456
- * whether `/v1/info` advertised `receipts` at submit time. Gates
3457
- * the one follow-up read the streamed arc spends to collect a receipt, so a
3458
- * DVM that doesn't issue them costs nothing.
3459
- */
3460
- receiptsSupported?: boolean;
3461
- /**
3462
- * `/v1/info#builder` as the endpoint served it at submit time —
3463
- * the anchor a receipt's attestation chain terminates at. Persisted so
3464
- * verification stays offline; `dvm receipts verify --endpoint` is the opt-in
3465
- * to re-fetch a possibly-rotated one.
3466
- */
3467
- builderAnchor?: ReceiptTrustAnchor;
3468
- }
3469
- interface ArtifactRef {
3470
- seq: number;
3471
- name?: string;
3472
- mimeType?: string;
3473
- }
3474
- declare function saveJob(job: JobRecord): void;
3475
- /** Merge a partial update into an existing job record. No-op if job not found. */
3476
- declare function updateJob(id: string, update: Partial<Omit<JobRecord, "id">>): void;
3477
- /** Persist status and completion together for offline replay. Empty completion is allowed.
3478
- * Repeated terminal updates preserve the original completedAt. Missing jobs are unchanged. */
3479
- declare function markJobTerminal(id: string, status: TerminalJobStatus, completion: JobCompletion, extra?: Partial<Omit<JobRecord, "id" | "status" | "completedAt" | "completion">>): void;
3480
- declare function loadJob(id: string): JobRecord | null;
3481
- /** Load all job records. Returns [] on missing/corrupt file. */
3482
- declare function loadAllJobs(): JobRecord[];
3483
- /** Add a payment to a job's running total and increment its honoured-payment count. No-op if job not found. */
3484
- declare function addPayment(jobId: string, amountMsats: number): void;
3485
- declare function refFromJob(job: JobRecord): ProviderRef;
3486
-
3487
- /**
3488
- * Receipt failures are warnings about evidence, not failures of the paid job.
3489
- * Persistence errors are logged without changing the job's outcome.
3490
- */
3491
-
3492
- /** Verify and persist a funding receipt; callers may anchor state only on a sound verdict. */
3493
- declare function captureFundingReceipt(args: {
3494
- receipt?: FundingReceipt;
3495
- parseError?: ReceiptParseError;
3496
- endpoint: string;
3497
- builder?: ReceiptTrustAnchor;
3498
- expectedCreditId: string;
3499
- expectedFundId: string;
3500
- expectedFundedMicro?: number;
3501
- expectedBalanceAfterMicro?: number;
3502
- expectedLedgerSeq?: number;
3503
- expectedCallerPubkey: string;
3504
- }): ReceiptVerification | "unparseable" | "absent";
3505
- type ReceiptCaptureStatus = ReceiptVerification | "unparseable";
3506
- interface ReceiptCapture {
3507
- /** The verdict. `"absent"` when none was offered; `"unparseable"` for an invalid shape. */
3508
- status: ReceiptCaptureStatus;
3509
- receipt?: JobReceipt$1;
3510
- /** Per-link detail, present whenever {@link receipt} is. */
3511
- checks?: ReceiptVerifyResult["checks"];
3512
- /** Machine slug for an `invalid` or `unparseable` verdict. */
3513
- reason?: ReceiptVerifyResult["reason"] | ReceiptParseError;
3514
- /** Pre-rendered line an intermediary agent can relay verbatim. */
3515
- display: string;
3516
- }
3517
- declare function captureTransportReceipt(jobId: string, response: Pick<JobStatus, "receipt" | "receiptParseError">): ReceiptCapture;
3518
- /**
3519
- * `receipt_verified` is always present. Non-absent captures include display
3520
- * text even when unparseable; raw receipt/checks require a parsed receipt.
3521
- * Emit only on terminal responses: absent during a running job means not yet
3522
- * issued, rather than unsupported receipts.
3523
- */
3524
- declare function receiptJsonFields(capture: ReceiptCapture): Record<string, unknown>;
3525
- declare function renderReceiptHuman(capture: ReceiptCapture): void;
3526
- /**
3527
- * Snapshot `/v1/info`'s receipt trust anchor onto a job record at `saveJob`
3528
- * time, so verification later stays offline and pins the anchor that was live
3529
- * when the job ran rather than whatever the DVM advertises by then.
3530
- */
3531
- declare function receiptTrustFields(provider: ProviderInfo): Pick<JobRecord, "receiptsSupported" | "builderAnchor">;
3532
- /**
3533
- * What one live `/v1/info` read learned about an endpoint's trust anchor.
3534
- *
3535
- * The two ways to come back without an anchor are different facts and must not
3536
- * collapse into one: a DVM that answered and published no `builder` block has
3537
- * told us it has none, while a DVM we could not reach has told us nothing. A
3538
- * caller holding a previously pinned anchor needs them apart before it decides
3539
- * whether to drop it.
3540
- */
3541
- interface TrustAnchorRead {
3542
- /** `true` when `/v1/info` answered — so an absent {@link anchor} is the DVM's own word. */
3543
- reachable: boolean;
3544
- /** The anchor as served. Absent when the DVM publishes none, or when unreachable. */
3545
- anchor?: ReceiptTrustAnchor;
3546
- }
3547
- /**
3548
- * Drain receipts lack a job's pinned anchor, so read it from the known endpoint.
3549
- * Unreachable reads return reachable=false; a successful read may still have no
3550
- * anchor. A present anchor is passed through for cryptographic verification,
3551
- * where a forged attestation is invalid rather than unattested.
3552
- */
3553
- declare function fetchTrustAnchor(transport: Transport, ref: ProviderRef): Promise<TrustAnchorRead>;
3554
- /**
3555
- * Collect a receipt missing from a locally-known job.
3556
- *
3557
- * The streamed request arc learns a job is over from the log, while
3558
- * `dvm status` can replay a terminal snapshot written by another command.
3559
- * Neither path has necessarily seen the receipt, which only rides on a job read.
3560
- *
3561
- * Costs one small GET, and only against a DVM that told us at submit time it
3562
- * issues receipts; everything else returns immediately. Best-effort throughout
3563
- * a failure here means no receipt this time, not a failed request.
3564
- */
3565
- declare function fetchMissingJobReceipt(jobId: string, transport: Transport, ref: ProviderRef): Promise<{
3566
- receipt?: JobReceipt$1;
3567
- receiptParseError?: ReceiptParseError;
3568
- }>;
3569
- /**
3570
- * Fill in a job record's missing trust anchor from a live `/v1/info` read.
3571
- *
3572
- * `dvm status` can be the first command to see a receipt — for a job submitted
3573
- * down a paid arc, or one that predates this feature — and a stored receipt
3574
- * with no anchor verifies as `verified_unattested` when the DVM may well have
3575
- * an attestation to offer. One describe call settles it. Best-effort: an
3576
- * unreachable provider leaves the record as it was.
3577
- */
3578
- declare function backfillTrustAnchor(jobId: string, transport: Transport, ref: ProviderRef): Promise<ReceiptTrustAnchor | undefined>;
3579
- /**
3580
- * Re-verify a receipt already on the job record — the `dvm status` local-replay
3581
- * path. Deliberately re-runs the chain instead of caching a verdict, so a
3582
- * tampered `jobs.json` answers `invalid` rather than replaying the verdict the
3583
- * untampered bytes once earned.
3584
- */
3585
- declare function replayStoredReceipt(job: JobRecord): ReceiptCapture;
3586
-
3587
- /**
3588
- * Per-DVM prepaid-credit working record (`~/.dvm/credits.json`).
3589
- *
3590
- * This file is the caller's *expectation*: what it believes each credit's
3591
- * spendable balance to be, projected from the DVM-signed artifacts it has
3592
- * already collected (fund responses, job receipts, drain records). It is
3593
- * bookkeeping, not evidence — the signed balance trajectory lives in
3594
- * `~/.dvm/receipts.jsonl`, and a mismatch between this file's projection and
3595
- * a freshly countersigned `balance_after` is exactly what
3596
- * {@link applyReceiptCredit} exists to surface.
3597
- *
3598
- * Mutable working set in the `budget.json` mold: one JSON object, temp-file +
3599
- * rename writes, malformed *entries* tolerated on read. A malformed **file**
3600
- * is not: damaged bytes are moved aside and named in the error rather than
3601
- * replaced with an empty store, a file we merely failed to *open* is left
3602
- * exactly where it is, and every cycle that touches the store runs under
3603
- * {@link withCreditLock}.
3604
- */
3605
-
3606
- type StoredCreditStatus = "active" | "expired" | "gone" | "drained" | "unbacked";
3607
- /** A drain in flight — persisted so a re-invoked `dvm credit drain` polls the same id. */
3608
- interface PendingDrain {
3609
- /** Caller-minted drain id; doubles as the poll/pickup key server-side. */
3610
- drainId: string;
3611
- /**
3612
- * The server keys drains by (credit_id, drain_id). Only an exact pairing may be auto-reused.
3613
- * Legacy unstamped entries remain visible but require an explicitly supplied pairing; they
3614
- * cannot suppress later top-ups.
3615
- */
3616
- creditId?: string;
3617
- method: string;
3618
- /** Payout destination as signed into the drain request — immutable server-side. */
3619
- payout: Record<string, string>;
3620
- /** Epoch ms the drain was first requested. */
3621
- requestedAt: number;
3622
- /** Verbatim cooperative-close Authorization value, saved before transmission. */
3623
- mppCredential?: string;
3624
- }
3625
- /**
3626
- * A durable credit funding in flight.
3627
- *
3628
- * Kept outside {@link StoredCredit}: an opening funding must be durable before
3629
- * its invoice request, when no server-confirmed credit exists yet.
3630
- */
3631
- interface PendingFunding {
3632
- /** Normalised endpoint origin the funding was requested from. */
3633
- endpoint: string;
3634
- /** x-only pubkey of the signing identity that owns the funding. */
3635
- callerPubkey: string;
3636
- /** Caller-minted credit id the invoice is bound to. */
3637
- creditId: string;
3638
- /** Caller-minted idempotency key the invoice is bound to. */
3639
- fundId: string;
3640
- /** Requested funding amount, in the credit currency's micro-units. */
3641
- amountMicro: number;
3642
- /** Funding rail whose money-moving credential must be replayed verbatim. */
3643
- rail: "lightning" | "tempo";
3644
- /** Refill target to retain when the funding becomes a stored credit. */
3645
- targetMicro: number;
3646
- /** Additional deposit authorization allowed for this durable MPP funding. */
3647
- maxDepositMicro?: number;
3648
- /** Funding-menu snapshot to retain when the funding becomes a stored credit. */
3649
- menu?: CreditMenu;
3650
- /** Epoch ms the funding intent was first persisted. */
3651
- requestedAt: number;
3652
- /** Bolt11 returned by the DVM, once one has been issued. */
3653
- bolt11?: string;
3654
- /** Payment hash returned alongside {@link PendingFunding.bolt11}. */
3655
- paymentHash?: string;
3656
- /** Invoice amount, in millisatoshis. */
3657
- amountMsats?: number;
3658
- /** Absolute invoice expiry, epoch ms. */
3659
- expiresAtMs?: number;
3660
- /** Paid invoice principal, in millisatoshis. Present only after money moved. */
3661
- principalMsats?: number;
3662
- /** Wallet-reported routing fee. Null means the wallet omitted it. */
3663
- routingFeeMsats?: number | null;
3664
- /** Total wallet fee from an exact debit. Null means the total is unprovable. */
3665
- totalWalletFeeMsats?: number | null;
3666
- /** Wallet fee not itemized as routing. Null means the split is unprovable. */
3667
- unitemizedWalletFeeMsats?: number | null;
3668
- /** Exact wallet debit. Null means wallet evidence could not prove it. */
3669
- walletDebitMsats?: number | null;
3670
- /** How the caller wallet reached settlement. */
3671
- paymentOutcome?: "paid" | "reconciled" | "republished";
3672
- /** Serialized MPP Authorization credential, persisted before its network send. */
3673
- mppCredential?: string;
3674
- /**
3675
- * What this funding's Tempo session voucher actually authorizes the DVM to
3676
- * capture, in micro-units — the cumulative it signed, net of whatever the
3677
- * channel had already authorized when the funding began. Journalled beside
3678
- * {@link PendingFunding.mppCredential} so a resume books the authorization
3679
- * rather than the ask.
3680
- */
3681
- authorizedMicro?: number;
3682
- /**
3683
- * Budget-ledger valuation fixed before an MPP channel credential is created.
3684
- * The debit itself is not journalled: it is this rate applied to
3685
- * {@link PendingFunding.authorizedMicro}, so a resume books the figure the
3686
- * credential authorized rather than one fixed before it existed.
3687
- */
3688
- budgetBtcRate?: number;
3689
- }
3690
- /**
3691
- * One drain's DVM-signed reclaim evidence, with the trust anchor it chains to.
3692
- *
3693
- * Held per drain rather than per credit: a credit can be re-funded and drained
3694
- * again, and each drain's receipts must be judged against the identity the DVM
3695
- * published at *that* reclaim — one anchor cannot honestly grade two drains
3696
- * that straddle a key rotation.
3667
+ * One drain's DVM-signed reclaim evidence, with the trust anchor it chains to.
3668
+ *
3669
+ * Held per drain rather than per credit: a credit can be re-funded and drained
3670
+ * again, and each drain's receipts must be judged against the identity the DVM
3671
+ * published at *that* reclaim — one anchor cannot honestly grade two drains
3672
+ * that straddle a key rotation.
3697
3673
  */
3698
3674
  interface StoredDrainEvidence {
3699
3675
  drainId: string;
@@ -4061,6 +4037,19 @@ declare function listPendingFundings(args?: {
4061
4037
  }): PendingFunding[];
4062
4038
  /** Load the oldest pending funding matching an endpoint, identity, and optional credit. */
4063
4039
  declare function loadPendingFunding(endpoint: string, callerPubkey: string, creditId?: string): PendingFunding | undefined;
4040
+ /**
4041
+ * Persist a funding intent or enrich the same intent with its issued invoice.
4042
+ *
4043
+ * The upsert key is `(callerPubkey, creditId, fundId)` — `fundId` is
4044
+ * caller-minted per intent — matched against any row reachable from this
4045
+ * endpoint. A row keeps the origin it was raised at even when the enrichment
4046
+ * arrives through a sibling hostname: the invoice belongs to the host process
4047
+ * that issued it, and rewriting that would point a resume at a host which
4048
+ * never saw the intent.
4049
+ */
4050
+ declare function recordPendingFunding(funding: PendingFunding): void;
4051
+ /** Clear one resolved or expired pending funding. */
4052
+ declare function clearPendingFunding(endpoint: string, callerPubkey: string, creditId: string, fundId: string): void;
4064
4053
  /**
4065
4054
  * Record the server's answer to a fund op (or the fund leg of a
4066
4055
  * fund-and-draw). Always the **server's** figures — `funded_micro` can differ
@@ -4194,6 +4183,29 @@ declare function markCredit(endpoint: string, callerPubkey: string, status: Stor
4194
4183
  ifCreditId?: string;
4195
4184
  identity?: AttestedDvmIdentity;
4196
4185
  }): void;
4186
+ /** What the caller last heard about a credit's place within the x402 rail. */
4187
+ interface StoredCreditX402Binding {
4188
+ /** The instrument every later top-up has to arrive on. */
4189
+ instrument?: X402CreditInstrument;
4190
+ /** The chain its settlement channel lives on, channel-bound only. */
4191
+ channelNetwork?: string;
4192
+ }
4193
+ /**
4194
+ * The x402 binding this DVM's tracked credit carries, when the record names
4195
+ * that same credit.
4196
+ *
4197
+ * Credit-scoped rather than record-scoped: the store holds one record per DVM
4198
+ * identity, so a `--credit-id` naming something else is a different credit with
4199
+ * its own binding and the pin does not carry across — the rule `pinnedRail`
4200
+ * applies to the rail, in the caller CLI, which lives in its own repository.
4201
+ * `gone` and `drained` records are excluded for the same reason they can't be
4202
+ * refilled at all.
4203
+ *
4204
+ * Both halves come back together because both answer one question — how to
4205
+ * route this credit's next top-up, and what to say when it can't be routed at
4206
+ * all — and reading them apart would take two loads of the same record.
4207
+ */
4208
+ declare function loadCreditX402Binding(endpoint: string, callerPubkey: string, creditId: string, identity?: AttestedDvmIdentity): StoredCreditX402Binding;
4197
4209
  /**
4198
4210
  * Adopt the x402 binding a refusal named onto the tracked credit.
4199
4211
  *
@@ -4305,6 +4317,17 @@ declare function settleDrainEvidence(args: {
4305
4317
  now?: number;
4306
4318
  }): void;
4307
4319
 
4320
+ declare function msatsToUsd(msats: number, rate: number): number;
4321
+ declare function usdToMsats(usd: number, rate: number): number;
4322
+ declare function msatsToUsdCents(msats: number, btcPriceUsd: number): number;
4323
+ /** Convert millisatoshis to USDC amount (6-decimal micro-units). USDC ≈ USD. */
4324
+ declare function msatsToUsdc(msats: number, btcUsdRate: number): number;
4325
+ /** Convert USDC amount (human-readable, e.g. 1.50) to millisatoshis. */
4326
+ declare function usdcToMsats(usdc: number, btcUsdRate: number): number;
4327
+ declare function msatsToMicro(msats: number, btcRate: number): number;
4328
+ /** Convert a micro-unit USD amount into whole sats (ceil) at the given rate. */
4329
+ declare function microToSats(micro: number, btcRate: number): number;
4330
+
4308
4331
  /**
4309
4332
  * Append-only receipt collection, separate from the rewrite-in-place job working
4310
4333
  * set. Each exported line carries its collection-time endpoint and trust anchor
@@ -4333,6 +4356,27 @@ interface StoredReceipt {
4333
4356
  /** Epoch ms at which this receipt was collected and first verified. */
4334
4357
  verified_at: number;
4335
4358
  }
4359
+ interface StoredFundingReceipt {
4360
+ receipt: FundingReceipt;
4361
+ endpoint: string;
4362
+ builder?: ReceiptTrustAnchor;
4363
+ verification: ReceiptVerification;
4364
+ verified_at: number;
4365
+ }
4366
+ /**
4367
+ * Append a receipt to the collection. No-op when a receipt for the same
4368
+ * `job_id` is already stored — a job's receipt is issued once and its bytes
4369
+ * are stable, so the second sighting (a `dvm status` re-read, a replayed
4370
+ * submit) carries nothing new.
4371
+ *
4372
+ * Deduped on `job_id`, never on the signature: BIP-340 mixes auxiliary
4373
+ * randomness, so signing the same payload twice yields different bytes. What
4374
+ * makes a receipt's bytes stable is the SDK persisting them write-once, not
4375
+ * the signer being deterministic.
4376
+ */
4377
+ declare function appendReceipt(entry: StoredReceipt): void;
4378
+ /** Append one funding artifact, deduped by its `(credit_id, fund_id)` identity. */
4379
+ declare function appendFundingReceipt(entry: StoredFundingReceipt): void;
4336
4380
  /** Load every stored receipt, oldest first. Returns [] when the file is absent. */
4337
4381
  declare function loadReceipts(): StoredReceipt[];
4338
4382
  declare function loadReceipt(jobId: string): StoredReceipt | null;
@@ -4706,78 +4750,7 @@ declare function pocketTargetMicro(config?: CreditConfig): number;
4706
4750
  * at the same healthy moments.
4707
4751
  */
4708
4752
  declare function needsPocketRefill(balanceMicro: number, targetMicro: number): boolean;
4709
- /**
4710
- * The `fund.amount_micro` a fund-and-draw must sign for a token of
4711
- * `fundMsats`, mirroring the server's `fundedMicroFor` exactly:
4712
- * pro-rata at the quote-pinned ratio `priceMicroServer ↔ requiredMsats`,
4713
- * with the exact-payment case returning the fiat price with zero drift.
4714
- * Both inputs must be **server-authored**, and since the behavior was introduced both are exact
4715
- * integers on the same 402: `required_msats` and `price_micro`, resolved
4716
- * against one fx snapshot. A client-fx-derived figure — or one reconstructed by
4717
- * multiplying a rendered decimal price by a million — is refused with
4718
- * `funding_commitment_mismatch` after the spend has already committed. Taking
4719
- * the fiat half from a separate `/v1/quote` hop is the weaker fallback for
4720
- * providers that state no `price_micro`: that hop re-prices, so its figure and
4721
- * the 402's `required_msats` are two independent resolutions of one ratio.
4722
- *
4723
- * Cashu-shaped, which is all v1 funds on: x402 takes the same ratio against
4724
- * the 402's advertised `maxAmountRequired` in µUSDC rather than through
4725
- * millisatoshis, so a caller-side x402 fund needs its
4726
- * own derivation rather than this one.
4727
- */
4728
- declare function fundWireAmountMicro(priceMicroServer: number, fundMsats: number, requiredMsats: number): number;
4729
- /**
4730
- * What a `funding_commitment_mismatch` refusal says about the provider's own
4731
- * valuation of the artifact attached.
4732
- *
4733
- * The three cases are not interchangeable to a caller holding proofs that are
4734
- * already P2PK-locked to the provider: only `absent` means no re-sign can ever
4735
- * land, and only that case is safe to give up on.
4736
- */
4737
- type FundValuation =
4738
- /** A usable figure. A corrected re-sign carries exactly this. */
4739
- {
4740
- kind: "figure";
4741
- micro: number;
4742
- }
4743
- /** The provider stated a valuation, but not one that can be signed (zero, negative, fractional, out of range). */
4744
- | {
4745
- kind: "malformed";
4746
- }
4747
- /** No valuation stated at all: the commitment-hash branch, which re-signing can never fix. */
4748
- | {
4749
- kind: "absent";
4750
- };
4751
- /**
4752
- * Read the provider's valuation off a `funding_commitment_mismatch` body — the
4753
- * figure a corrected re-sign must carry. Prefers the structured
4754
- * `expected_micro` field; falls back to the figure the message states ("… at
4755
- * the quoted price (130769)") for providers that predate it, including when the
4756
- * structured field is present but unusable.
4757
- *
4758
- * A provider that stated *something* is on the amount branch even when what it
4759
- * stated is garbage, so that case returns `malformed` rather than `absent`. The
4760
- * two must not collapse: a caller that treats "the provider emitted a bad field"
4761
- * as "uncorrectable" drops the entry and burns proofs it could have held.
4762
- *
4763
- * Shared by both recovery legs: the in-flight retry in `request.ts` and the
4764
- * crash-resume sweep in `wallet-agent/recovery-submissions.ts`.
4765
- */
4766
- declare function readFundValuation(fields: {
4767
- expectedMicro?: unknown;
4768
- message?: string;
4769
- }): FundValuation;
4770
- declare function msatsToMicro(msats: number, btcRate: number): number;
4771
- /** Convert a micro-unit USD amount into whole sats (ceil) at the given rate. */
4772
- declare function microToSats(micro: number, btcRate: number): number;
4773
4753
 
4774
- declare function msatsToUsd(msats: number, rate: number): number;
4775
- declare function usdToMsats(usd: number, rate: number): number;
4776
- declare function msatsToUsdCents(msats: number, btcPriceUsd: number): number;
4777
- /** Convert millisatoshis to USDC amount (6-decimal micro-units). USDC ≈ USD. */
4778
- declare function msatsToUsdc(msats: number, btcUsdRate: number): number;
4779
- /** Convert USDC amount (human-readable, e.g. 1.50) to millisatoshis. */
4780
- declare function usdcToMsats(usdc: number, btcUsdRate: number): number;
4781
4754
  /**
4782
4755
  * Whether an amount label carries its {@link costAnchor} clause. On by default:
4783
4756
  * an anchor is what lets an agent explain a price to a human who has never seen
@@ -5011,6 +4984,13 @@ declare function buildTempoCredential(args: BuildTempoCredentialArgs): Promise<M
5011
4984
  * booking the ask under-reports the spend by exactly that gap.
5012
4985
  */
5013
4986
  declare function tempoCredentialAmountMicro(credential: MppxCredential): bigint;
4987
+ /**
4988
+ * Unix seconds after which a Tempo charge credential can no longer settle,
4989
+ * reproducing mppx's own `min(signedAt + TTL, challenge.expires)`. `undefined`
4990
+ * when the challenge carries an unreadable `expires` — naming a deadline the
4991
+ * signature does not have is worse than naming none.
4992
+ */
4993
+ declare function tempoCredentialValidBefore(credential: MppxCredential, signedAtMs: number): number | undefined;
5014
4994
 
5015
4995
  /** Calls fn, retrying up to delays.length times on transport errors.
5016
4996
  * Logs a warning on each retry. Non-transport errors are rethrown immediately. */
@@ -5034,6 +5014,7 @@ interface JobPolicy {
5034
5014
  /** Maximum number of payments the CLI will honour for this job. Required — agents must declare expectations. */
5035
5015
  maxPayments: number;
5036
5016
  }
5017
+
5037
5018
  /**
5038
5019
  * Build a JobPolicy from CLI options and/or config values.
5039
5020
  * Budget strings can be msats ("5000") or USD ("$0.50").
@@ -5046,6 +5027,26 @@ declare function buildPolicy(opts: {
5046
5027
  maxPayments?: number;
5047
5028
  }, btcRate: number): JobPolicy;
5048
5029
 
5030
+ /**
5031
+ * Free text supplied by a provider. Agents should treat fields wrapped in this
5032
+ * shape with appropriate skepticism — they are subject to prompt injection,
5033
+ * social engineering, or simply contain unverified claims about the job.
5034
+ *
5035
+ * Wrapping is the structural marker; the JSON shape `{ _source: "provider", text: "..." }`
5036
+ * lets an agent's framework distinguish provider-controlled content from CLI-owned
5037
+ * instructions without inspecting field paths.
5038
+ */
5039
+ interface ProviderText {
5040
+ _source: "provider";
5041
+ text: string;
5042
+ }
5043
+ /** Wrap a string as provider-supplied text. */
5044
+ declare function asProviderText(text: string): ProviderText;
5045
+ /** Wrap a string only if defined; passes through undefined. */
5046
+ declare function asProviderTextOpt(text: string | undefined): ProviderText | undefined;
5047
+ /** Render a ProviderText (or string) back to plain text — used by --human output paths. */
5048
+ declare function providerTextToString(value: string | ProviderText): string;
5049
+
5049
5050
  interface ReceiptKeypair {
5050
5051
  /** secp256k1 BIP-340 x-only pubkey, 32 bytes hex (64 chars). */
5051
5052
  pubkey: string;
@@ -5618,6 +5619,8 @@ interface AgentWallet {
5618
5619
  /** ISO-8601 wallet creation timestamp. */
5619
5620
  created_at: string;
5620
5621
  }
5622
+ /** Reads configured mints without migrating legacy caller configuration or choosing a fallback. */
5623
+ declare function loadWalletConfiguredMints(): string[];
5621
5624
  /** Missing files return null; earlier supported schemas migrate in memory to v9.
5622
5625
  * Populated v1 legacy state is refused. Wallets without a bound mnemonic stay
5623
5626
  * NUT-13 inactive; old pending mints retain missing expiry for recovery fallback.
@@ -5844,6 +5847,13 @@ declare function buildDisplayMintInventory(wallet: Pick<AgentWallet, "mints" | "
5844
5847
  * blinded message, blinding factor, secret, and optional ephemeral E.
5845
5848
  */
5846
5849
  declare function serializeOutputData(data: OutputDataLike[]): PersistedOutputData[];
5850
+ /**
5851
+ * Rebuild concrete {@link OutputData} instances (with a working `toProof`
5852
+ * method) from previously persisted state. Throws on malformed input rather
5853
+ * than silently dropping outputs — partial recovery is worse than a clean
5854
+ * error the operator can act on.
5855
+ */
5856
+ declare function rehydrateOutputData(persisted: PersistedOutputData[]): OutputData[];
5847
5857
  /**
5848
5858
  * Replay persisted blinded outputs against the mint's NUT-09 `/v1/restore`
5849
5859
  * endpoint and unblind the signatures locally — the recovery half of the
@@ -5966,6 +5976,7 @@ interface CashuSubmissionBinding {
5966
5976
  }
5967
5977
  /** SHA-256 over canonical JSON for one exact strict Cashu submission binding. */
5968
5978
  declare function cashuSubmissionBindingFingerprint(binding: CashuSubmissionBinding): string;
5979
+ declare function cashuSubmissionBindingFromContext(context: PendingSubmissionContext): CashuSubmissionBinding | null;
5969
5980
 
5970
5981
  /**
5971
5982
  * The payer's two timed-exit calls, their exact-result events, and the three
@@ -6120,28 +6131,6 @@ declare const X402_BATCH_CHANNEL_ABI: readonly [{
6120
6131
  }];
6121
6132
  }];
6122
6133
 
6123
- /** Immutable channel configuration needed by the unilateral withdrawal verbs. */
6124
- interface StoredX402ChannelConfig {
6125
- payer: `0x${string}`;
6126
- payerAuthorizer: `0x${string}`;
6127
- receiver: `0x${string}`;
6128
- receiverAuthorizer: `0x${string}`;
6129
- token: `0x${string}`;
6130
- withdrawDelay: number;
6131
- salt: `0x${string}`;
6132
- }
6133
- /** Caller metadata that connects an upstream channel record to one DVM credit. */
6134
- interface StoredX402ChannelMetadata {
6135
- channelId: `0x${string}`;
6136
- endpoint: string;
6137
- callerPubkey: string;
6138
- creditId: string;
6139
- network: string;
6140
- config: StoredX402ChannelConfig;
6141
- updatedAt: number;
6142
- }
6143
- /** Provenance for an upstream balance write that did not read the contract. */
6144
- type X402UnobservedBalanceProvenance = "unreconciled" | "unchanged";
6145
6134
  /** Exact signed request retained until a funding response is acknowledged. */
6146
6135
  interface PendingX402Funding {
6147
6136
  endpoint: string;
@@ -6174,8 +6163,8 @@ interface PendingX402Funding {
6174
6163
  * ERC-3009 deposit authorization, dead at `authorizationValidBefore`, and the
6175
6164
  * cumulative claim voucher, which `claim()` accepts with no expiry field and
6176
6165
  * no dependency on the deposit having landed. So a refusal releases the
6177
- * deposit-shaped gates on that timestamp and raises the exit's guaranteed
6178
- * figure never — only `wallet x402-clear-pending --force` does that.
6166
+ * deposit-shaped gates on that timestamp, but never releases the claim
6167
+ * voucher reservation. Explicit journal deletion is a separate operation.
6179
6168
  */
6180
6169
  refusedAt?: number;
6181
6170
  /**
@@ -6185,6 +6174,81 @@ interface PendingX402Funding {
6185
6174
  */
6186
6175
  supersededAt?: number;
6187
6176
  }
6177
+ /**
6178
+ * Age at which an active unacknowledged voucher is reported as abandoned and
6179
+ * may be retired without force. Age alone does not revoke its signed authority.
6180
+ * Retired deposits have a separate authorization-expiry gate.
6181
+ */
6182
+ declare const X402_PENDING_STALE_MS: number;
6183
+ /** Whether an entry has gone long enough unacknowledged to read as abandoned. */
6184
+ declare function x402PendingStale(pending: PendingX402Funding, now?: number): boolean;
6185
+ /** Whether this funding has a final answer or a newer alias-split replacement. */
6186
+ declare function x402PendingRetired(pending: PendingX402Funding): boolean;
6187
+ /**
6188
+ * When a refused entry's deposit authorization stops being submittable, and
6189
+ * with it every gate that exists to stop a second deposit being minted.
6190
+ *
6191
+ * Entries with no readable `authorizationValidBefore` — written before the
6192
+ * field existed, or carrying a voucher-only payload — get the conservative
6193
+ * answer rather than an immediate release: the stale threshold, the same
6194
+ * "long enough to read as abandoned" line the CLI already draws.
6195
+ */
6196
+ declare function x402PendingBlockExpiresAt(pending: PendingX402Funding): number;
6197
+ /** Signed deposit deadline in epoch milliseconds; absent for unreadable/legacy authority. */
6198
+ declare function x402PendingDepositExpiresAt(pending: PendingX402Funding): number | undefined;
6199
+ /**
6200
+ * Whether an entry still carries the deposit-shaped hazard: a signed ERC-3009
6201
+ * authorization that could yet be submitted, which is what the rival-voucher
6202
+ * gate and the key-loss refusals exist to protect against. True for anything
6203
+ * still awaiting acknowledgement — nothing releases on age — and for
6204
+ * a refused entry only until its authorization dies.
6205
+ *
6206
+ * Never the predicate for the timed exit's guaranteed figure, which accounts
6207
+ * for the claim voucher and has no timestamp to release on.
6208
+ */
6209
+ declare function x402PendingUnsettled(pending: PendingX402Funding, now?: number): boolean;
6210
+ /** Refusal facts in epoch milliseconds, without caller recovery guidance. */
6211
+ interface X402VoucherPendingState {
6212
+ code: "x402_voucher_pending";
6213
+ creditId: string;
6214
+ fundId: string;
6215
+ channelId: string;
6216
+ endpoint: string;
6217
+ retired: boolean;
6218
+ blockedUntil: number;
6219
+ depositExpiresAt?: number;
6220
+ }
6221
+ declare function x402VoucherPendingState(blocking: PendingX402Funding): X402VoucherPendingState;
6222
+ /**
6223
+ * Reject a second independently spendable deposit across credit/endpoint scopes.
6224
+ * Same-credit live entries permit verbatim replay; retirement alone never revokes
6225
+ * an authorization. Supply the existing channel-scoped journal. The thrown
6226
+ * value is facts, for caller adapters to render.
6227
+ */
6228
+ declare function assertNoRivalX402Voucher(channelId: `0x${string}`, creditId: string, pending: PendingX402Funding[], now?: number): void;
6229
+
6230
+ /** Immutable channel configuration needed by the unilateral withdrawal verbs. */
6231
+ interface StoredX402ChannelConfig {
6232
+ payer: `0x${string}`;
6233
+ payerAuthorizer: `0x${string}`;
6234
+ receiver: `0x${string}`;
6235
+ receiverAuthorizer: `0x${string}`;
6236
+ token: `0x${string}`;
6237
+ withdrawDelay: number;
6238
+ salt: `0x${string}`;
6239
+ }
6240
+ /** Caller metadata that connects an upstream channel record to one DVM credit. */
6241
+ interface StoredX402ChannelMetadata {
6242
+ channelId: `0x${string}`;
6243
+ endpoint: string;
6244
+ callerPubkey: string;
6245
+ creditId: string;
6246
+ network: string;
6247
+ config: StoredX402ChannelConfig;
6248
+ updatedAt: number;
6249
+ }
6250
+ /** Provenance for an upstream balance write that did not read the contract. */
6251
+ type X402UnobservedBalanceProvenance = "unreconciled" | "unchanged";
6188
6252
  /**
6189
6253
  * An `exact`-scheme authorization retained until its funding response is
6190
6254
  * acknowledged.
@@ -6270,48 +6334,6 @@ declare function listResumableX402ExactFundings(filter?: {
6270
6334
  * a sibling process journalled in the meantime.
6271
6335
  */
6272
6336
  declare function clearPendingX402ExactFunding(pending: PendingX402ExactFunding): void;
6273
- /**
6274
- * Age at which an active unacknowledged voucher is reported as abandoned and
6275
- * may be retired without force. Age alone does not revoke its signed authority.
6276
- * Retired deposits have a separate authorization-expiry gate.
6277
- */
6278
- declare const X402_PENDING_STALE_MS: number;
6279
- /** Whether an entry has gone long enough unacknowledged to read as abandoned. */
6280
- declare function x402PendingStale(pending: PendingX402Funding, now?: number): boolean;
6281
- /** Whether this funding has a final answer or a newer alias-split replacement. */
6282
- declare function x402PendingRetired(pending: PendingX402Funding): boolean;
6283
- /**
6284
- * When a refused entry's deposit authorization stops being submittable, and
6285
- * with it every gate that exists to stop a second deposit being minted.
6286
- *
6287
- * Entries with no readable `authorizationValidBefore` — written before the
6288
- * field existed, or carrying a voucher-only payload — get the conservative
6289
- * answer rather than an immediate release: the stale threshold, the same
6290
- * "long enough to read as abandoned" line the CLI already draws.
6291
- */
6292
- declare function x402PendingBlockExpiresAt(pending: PendingX402Funding): number;
6293
- /**
6294
- * The deadline the caller actually signed, or `undefined` when this entry never
6295
- * carried one — a voucher-only payload authorizes no ERC-3009 transfer at all,
6296
- * and an entry written before journalled no expiry for the one it did.
6297
- *
6298
- * The block timestamp is the same either way, so this exists for the prose:
6299
- * telling an agent "the deposit you signed can be submitted until X" when X is
6300
- * a fallback this code invented is a claim about a signature that was never
6301
- * made, and the agent relays it to a human verbatim.
6302
- */
6303
- declare function x402PendingDepositExpiresAt(pending: PendingX402Funding): number | undefined;
6304
- /**
6305
- * Whether an entry still carries the deposit-shaped hazard: a signed ERC-3009
6306
- * authorization that could yet be submitted, which is what the rival-voucher
6307
- * gate and the key-loss refusals exist to protect against. True for anything
6308
- * still awaiting acknowledgement — nothing releases on age — and for
6309
- * a refused entry only until its authorization dies.
6310
- *
6311
- * Never the predicate for the timed exit's guaranteed figure, which accounts
6312
- * for the claim voucher and has no timestamp to release on.
6313
- */
6314
- declare function x402PendingUnsettled(pending: PendingX402Funding, now?: number): boolean;
6315
6337
  /**
6316
6338
  * One journal entry in the shape every CLI surface puts on the wire. Shared, so
6317
6339
  * an agent reading a drain, a timed exit and `x402-clear-pending` sees the same
@@ -6538,17 +6560,7 @@ declare function createX402BatchPayment(args: {
6538
6560
  /** Deposit policy in token micro-units, raised to upstream's required minimum. */
6539
6561
  depositMicro: number;
6540
6562
  }): Promise<X402BatchPayment>;
6541
- /**
6542
- * The one refusal that says "this channel already owes a signature". Shared by
6543
- * the authoritative gate below and by `credit-fund`'s cheap local pre-check, so
6544
- * an agent reading either gets the same two facts: which funding stands in the
6545
- * way, and what makes it go away.
6546
- *
6547
- * A funding the DVM refused outright is the second flavour, and it needs its
6548
- * own words: retrying it is impossible, so the way out is the clock. The hint
6549
- * names the moment its deposit authorization stops being submittable, which is
6550
- * when this block lifts on its own.
6551
- */
6563
+ /** Compatibility adapter retaining caller commands until consumer migration. */
6552
6564
  declare function x402VoucherPendingRefusal(blocking: PendingX402Funding, data?: Record<string, unknown>): DvmError;
6553
6565
  /** Advance durable cumulative state from a successful PAYMENT-RESPONSE. */
6554
6566
  declare function processX402BatchResponse(scheme: BatchSettlementEvmScheme, paymentResponse: string | undefined): Promise<void>;
@@ -6845,33 +6857,34 @@ interface X402Balance {
6845
6857
  */
6846
6858
  declare function getX402Balance(wallet: X402Wallet): Promise<X402Balance>;
6847
6859
 
6860
+ /** Descriptive diagnostic retention metadata; deletion and case controls belong to the platform. */
6848
6861
  declare const SPANS_DATASETS: readonly [{
6849
6862
  readonly name: "platform";
6850
- readonly retentionDays: 90;
6863
+ readonly retentionDays: 730;
6851
6864
  }, {
6852
6865
  readonly name: "cashu";
6853
- readonly retentionDays: 90;
6866
+ readonly retentionDays: 730;
6854
6867
  }, {
6855
6868
  readonly name: "lightning";
6856
- readonly retentionDays: 90;
6869
+ readonly retentionDays: 730;
6857
6870
  }, {
6858
6871
  readonly name: "stripe";
6859
- readonly retentionDays: 90;
6872
+ readonly retentionDays: 730;
6860
6873
  }, {
6861
6874
  readonly name: "x402";
6862
- readonly retentionDays: 90;
6875
+ readonly retentionDays: 730;
6863
6876
  }, {
6864
6877
  readonly name: "tempo";
6865
- readonly retentionDays: 90;
6878
+ readonly retentionDays: 730;
6866
6879
  }, {
6867
6880
  readonly name: "isolate";
6868
- readonly retentionDays: 90;
6881
+ readonly retentionDays: 730;
6869
6882
  }, {
6870
6883
  readonly name: "audit";
6871
- readonly retentionDays: 365;
6884
+ readonly retentionDays: 730;
6872
6885
  }, {
6873
6886
  readonly name: "cron";
6874
- readonly retentionDays: 30;
6887
+ readonly retentionDays: 730;
6875
6888
  }];
6876
6889
  type DatasetName = (typeof SPANS_DATASETS)[number]["name"];
6877
6890
 
@@ -7440,179 +7453,432 @@ interface StaleRateNotice {
7440
7453
  display: string;
7441
7454
  }
7442
7455
  /**
7443
- * Resolve BTC/USD, using the last cached rate when the provider is unreachable.
7444
- * A stale rate still permits cap enforcement; no rate blocks the spend with
7445
- * rate_unavailable rather than silently bypassing the cap. Stale fallback warns
7446
- * once per process on stderr. Display-only callers use tryResolveBtcUsdRate.
7456
+ * Resolve BTC/USD, using the last cached rate when the provider is unreachable.
7457
+ * A stale rate still permits cap enforcement; no rate blocks the spend with
7458
+ * rate_unavailable rather than silently bypassing the cap. Stale fallback warns
7459
+ * once per process on stderr. Display-only callers use tryResolveBtcUsdRate.
7460
+ */
7461
+ declare function resolveBtcUsdRate(purpose: BtcRatePurpose): Promise<ResolvedBtcRate>;
7462
+ /**
7463
+ * Best-effort rate for a figure that is *displayed* but never spent — a price
7464
+ * label, a wallet balance line. Returns null rather than throwing: a caller
7465
+ * should not lose a payment, or be blocked from connecting a wallet, because a
7466
+ * price API was down when we went to render a dollar sign.
7467
+ */
7468
+ declare function tryResolveBtcUsdRate(): Promise<ResolvedBtcRate | null>;
7469
+ /** Freshness notice for a resolved rate. Undefined when the rate came back live. */
7470
+ declare function staleRateNotice(resolved: ResolvedBtcRate | null): StaleRateNotice | undefined;
7471
+
7472
+ /** Get balance per mint as a Map of mintUrl → msats. */
7473
+ declare function getBalanceByMint(): Map<string, number>;
7474
+
7475
+ type SigningIdentitySource = {
7476
+ kind: "flag";
7477
+ name: string;
7478
+ } | {
7479
+ kind: "env";
7480
+ } | {
7481
+ kind: "default";
7482
+ name: string;
7483
+ } | {
7484
+ kind: "sole";
7485
+ name: string;
7486
+ }
7487
+ /** Matched by pubkey — the resume path re-signing as whoever paid. */
7488
+ | {
7489
+ kind: "pubkey";
7490
+ name: string;
7491
+ };
7492
+ interface ResolvedSigningIdentity {
7493
+ /** 32-byte secp256k1 secret, lowercase hex. */
7494
+ privkey: string;
7495
+ /** 32-byte BIP-340 x-only pubkey, lowercase hex. */
7496
+ pubkey: string;
7497
+ source: SigningIdentitySource;
7498
+ }
7499
+ interface ResolveSigningIdentityOpts {
7500
+ as?: string;
7501
+ config?: Config | null;
7502
+ }
7503
+ /**
7504
+ * Resolve which caller signing identity `dvm request` / `dvm quote` should
7505
+ * use to sign a descriptor-auth submission. Resolution chain (first match
7506
+ * wins):
7507
+ *
7508
+ * 1. `--as <name>` flag → look up named identity.
7509
+ * 2. `DVM_IDENTITY_KEY=<hex>` env → use as anonymous key (no name lookup).
7510
+ * 3. `config.defaultIdentity` → look up named identity.
7511
+ * 4. Identities file has exactly one entry → use it.
7512
+ * 5. Else → throw `auth_required` listing available identities.
7513
+ */
7514
+ declare function resolveSigningIdentity(opts: ResolveSigningIdentityOpts): ResolvedSigningIdentity;
7515
+ /**
7516
+ * Look an identity up by its pubkey rather than by name.
7517
+ *
7518
+ * The pending-submission resume has to re-sign the original call as the caller
7519
+ * who paid for it — signing as anyone else would file the job under the wrong
7520
+ * pubkey. It therefore can't go through {@link resolveSigningIdentity}, whose
7521
+ * answer depends on flags, env, and config that may have changed since. Returns
7522
+ * `null` when the key is no longer configured, which makes the submission
7523
+ * unresumable rather than mis-signed.
7524
+ */
7525
+ declare function findSigningIdentityByPubkey(pubkey: string): ResolvedSigningIdentity | null;
7526
+
7527
+ declare const IDENTITIES_VERSION: 1;
7528
+ /** One stored caller signing identity. The `name` is the file's record key. */
7529
+ interface CliIdentityEntry {
7530
+ /** 32-byte secp256k1 secret key, lowercase hex (64 chars). Never sent to any server. */
7531
+ privkey: string;
7532
+ /** 32-byte BIP-340 x-only public key, lowercase hex (64 chars). */
7533
+ pubkey: string;
7534
+ /** Epoch millis when the entry was generated or imported. */
7535
+ createdAt: number;
7536
+ }
7537
+ /**
7538
+ * Persistent on-disk shape of `~/.dvm/identities.json` (mode 0600). Stores the
7539
+ * caller signing identities `dvm request` / `dvm quote` use to auto-sign
7540
+ * descriptor-auth submissions.
7541
+ */
7542
+ interface IdentitiesFile {
7543
+ version: typeof IDENTITIES_VERSION;
7544
+ identities: Record<string, CliIdentityEntry>;
7545
+ }
7546
+ /** Whether `~/.dvm/identities.json` exists. Cheap presence check; does not parse. */
7547
+ declare function identitiesFileExists(): boolean;
7548
+ declare function loadIdentities(): IdentitiesFile | null;
7549
+ /**
7550
+ * Atomically write the identities file with mode 0600. POSIX guarantees rename atomicity within a filesystem,
7551
+ * so a crash mid-write leaves either the previous file or the new one.
7552
+ *
7553
+ * Callers performing a read-modify-write cycle must hold {@link withIdentitiesLock}
7554
+ * across the cycle so two concurrent `dvm identity …` invocations cannot
7555
+ * clobber each other's writes.
7556
+ */
7557
+ declare function saveIdentities(file: IdentitiesFile): void;
7558
+ /** Lock acquisition budget; retry and stale-lock values are in milliseconds. */
7559
+ interface WithIdentitiesLockOptions {
7560
+ /** Stale-lock threshold in ms. A lock whose mtime is older than this is reclaimed. Default 30_000. */
7561
+ stale?: number;
7562
+ /** Number of acquisition retries before failing. Default 30. */
7563
+ retries?: number;
7564
+ /** Milliseconds between retries. Default 1_000. */
7565
+ retryIntervalMs?: number;
7566
+ }
7567
+ /**
7568
+ * Run `fn` while holding an OS-level exclusive lock on the identities file,
7569
+ * so concurrent `dvm identity …` invocations serialise their
7570
+ * read-modify-write cycles instead of clobbering each other. The lock file
7571
+ * lives at `~/.dvm/identities.json.lock` and is reclaimed automatically if a
7572
+ * previous holder died without releasing.
7573
+ *
7574
+ * Throws `DvmError("identities_locked", …)` when the lock can't be acquired
7575
+ * within the retry budget (~30s by default).
7576
+ */
7577
+ declare function withIdentitiesLock<T>(fn: () => Promise<T> | T, opts?: WithIdentitiesLockOptions): Promise<T>;
7578
+ /**
7579
+ * Generate a fresh secp256k1 keypair as a {@link CliIdentityEntry}. The
7580
+ * private key is 32 cryptographically-random bytes; the public key is the
7581
+ * BIP-340 x-only form — same convention as the SDK's
7582
+ * `createSignedRequestVerifier.signRequest`.
7583
+ */
7584
+ declare function generateIdentity(now?: number): CliIdentityEntry;
7585
+ /**
7586
+ * Validate a 64-char lowercase hex private key and derive the matching
7587
+ * BIP-340 x-only pubkey. Throws `DvmError("invalid_privkey", ...)` on a
7588
+ * malformed input. Used by `dvm identity import` and the
7589
+ * `DVM_IDENTITY_KEY` env override resolver.
7590
+ */
7591
+ declare function deriveIdentityFromPrivkey(privkeyHex: string, now?: number): CliIdentityEntry;
7592
+
7593
+ /**
7594
+ * The terminal-outcome fields a job carries once it is over — the summary, the
7595
+ * artifact metadata, and (on a failure) the provider's message. Read off a
7596
+ * transport receipt / status response, persisted on the local job record
7597
+ * and rendered into the JSON payload by `buildCompletionHintFields`.
7598
+ */
7599
+ interface JobCompletion {
7600
+ /** Human-readable one-liner. Not the payload when artifacts are present. */
7601
+ summary?: string;
7602
+ /** Provider's status message (typically on a failed job). */
7603
+ message?: string;
7604
+ /** True when the provider emitted artifact messages. */
7605
+ hasArtifacts?: boolean;
7606
+ /** Count of artifact messages (present when `hasArtifacts` is true). */
7607
+ artifactCount?: number;
7608
+ /** Where the payload sits: the `summary` string, or in artifact messages. */
7609
+ payloadIn?: "summary" | "messages";
7610
+ }
7611
+ /**
7612
+ * Build the snake_case JSON fields (`has_artifacts`, `artifact_count`,
7613
+ * `payload_in`, `next_step_hint`) from a transport receipt or status response.
7614
+ * Returns an object meant to be spread into the parent JSON payload — agents
7615
+ * relaying a completed-job response need these to know the summary string is
7616
+ * a one-liner, not the payload, when the real output sits in artifact messages
7617
+ */
7618
+ declare function buildCompletionHintFields(jobId: string, input: JobCompletion): Record<string, unknown>;
7619
+ /** `--no-stream` replays from seq 0: the stored cursor may already be past the artifacts. */
7620
+ declare function nextStepHint(jobId: string, payloadIn: "summary" | "messages" | undefined, artifactCount: number | undefined): string | undefined;
7621
+ /**
7622
+ * Pick the terminal-outcome fields off a receipt or status response, dropping
7623
+ * the ones the provider didn't send. What lands here is what `dvm status`
7624
+ * replays from the local record on every later read, so it must be
7625
+ * exactly the set the wire read would have rendered — no defaults, no guesses.
7626
+ */
7627
+ declare function completionSnapshot(src: JobCompletion): JobCompletion;
7628
+ /**
7629
+ * Derive the terminal snapshot from a streamed message log, for the paths that
7630
+ * learn a job is over from the stream rather than a status response. Mirrors
7631
+ * the SDK's own derivation (`statusCompletionFields`, `src/sdk/server/app.ts`):
7632
+ * `payload_in` is `"messages"` iff any `artifact` message was emitted. Requires
7633
+ * the full log (from seq 0) — a partial batch would undercount the artifacts.
7634
+ */
7635
+ declare function completionFromMessages(messages: Message[]): JobCompletion;
7636
+
7637
+ /** Outcome of a {@link repairConfigDirMode} pass. Never throws; failures land in `error`. */
7638
+ interface ConfigDirModeResult {
7639
+ path: string;
7640
+ /** Whether the directory exists. False also when the stat itself failed (see `error`). */
7641
+ exists: boolean;
7642
+ /** Mode after the pass, e.g. `"0700"`. Null when absent, unreadable, or off-POSIX. */
7643
+ modeOctal: string | null;
7644
+ /** Mode found before the pass, when {@link repaired} is true. */
7645
+ previousModeOctal?: string;
7646
+ /** True when this call tightened a group/other-accessible directory to 0700. */
7647
+ repaired: boolean;
7648
+ /** True on Windows, where POSIX modes are meaningless and the pass is a no-op. */
7649
+ skippedNonPosix: boolean;
7650
+ /** Underlying message when the stat or chmod failed. */
7651
+ error?: string;
7652
+ }
7653
+ /** Create the caller-state directory owner-only; existing modes are unchanged. */
7654
+ declare function ensureConfigDir(): void;
7655
+ /**
7656
+ * Create a caller-state subdirectory owner-only. Recursive mkdir may also create
7657
+ * CONFIG_DIR, so every creation path must carry the same owner-only mode.
7447
7658
  */
7448
- declare function resolveBtcUsdRate(purpose: BtcRatePurpose): Promise<ResolvedBtcRate>;
7659
+ declare function ensureConfigSubdir(path: string): void;
7449
7660
  /**
7450
- * Best-effort rate for a figure that is *displayed* but never spent — a price
7451
- * label, a wallet balance line. Returns null rather than throwing: a caller
7452
- * should not lose a payment, or be blocked from connecting a wallet, because a
7453
- * price API was down when we went to render a dollar sign.
7661
+ * Tighten an existing `CONFIG_DIR` to 0700 when it is group- or
7662
+ * other-accessible. Does not create the directory — an absent one is reported,
7663
+ * not conjured, so read-mostly callers (`dvm doctor`) stay honest.
7664
+ *
7665
+ * Only *loosening* is corrected: a directory an operator deliberately set
7666
+ * stricter than 0700 (e.g. 0500) is left alone, so a shared-service setup is
7667
+ * not fought with on every run. No-op on Windows.
7454
7668
  */
7455
- declare function tryResolveBtcUsdRate(): Promise<ResolvedBtcRate | null>;
7456
- /** Freshness notice for a resolved rate. Undefined when the rate came back live. */
7457
- declare function staleRateNotice(resolved: ResolvedBtcRate | null): StaleRateNotice | undefined;
7669
+ declare function repairConfigDirMode(): ConfigDirModeResult;
7458
7670
 
7459
- /** Get balance per mint as a Map of mintUrl → msats. */
7460
- declare function getBalanceByMint(): Map<string, number>;
7671
+ /** Return whether a value is a 0x-prefixed 32-byte secp256k1 secret scalar. */
7672
+ declare function isValidEvmPrivateKey(value: string): value is `0x${string}`;
7461
7673
 
7462
- type SigningIdentitySource = {
7463
- kind: "flag";
7464
- name: string;
7465
- } | {
7466
- kind: "env";
7467
- } | {
7468
- kind: "default";
7469
- name: string;
7470
- } | {
7471
- kind: "sole";
7472
- name: string;
7674
+ type NextAction = null | NextActionRespond | NextActionPay | NextActionApprove | NextActionPoll | NextActionRefund;
7675
+ interface NextActionRespond {
7676
+ type: "respond";
7677
+ job_id: string;
7678
+ prompt_id: string;
7679
+ /** The provider's question. Treat with appropriate skepticism. */
7680
+ prompt: ProviderText;
7681
+ schema?: Record<string, unknown>;
7682
+ /** CLI-owned guidance for the agent. */
7683
+ hint: string;
7473
7684
  }
7474
- /** Matched by pubkey — the resume path re-signing as whoever paid. */
7475
- | {
7476
- kind: "pubkey";
7477
- name: string;
7478
- };
7479
- interface ResolvedSigningIdentity {
7480
- /** 32-byte secp256k1 secret, lowercase hex. */
7481
- privkey: string;
7482
- /** 32-byte BIP-340 x-only pubkey, lowercase hex. */
7483
- pubkey: string;
7484
- source: SigningIdentitySource;
7685
+ interface NextActionPay {
7686
+ type: "pay";
7687
+ job_id: string;
7688
+ amount_msats: number;
7689
+ /**
7690
+ * The provider's own fiat price for this charge, when it priced in fiat.
7691
+ * Mirrors the wire's `fiat_amount` so a typed agent can do budget math
7692
+ * against the figure the human is actually being asked to approve.
7693
+ */
7694
+ fiat_amount?: {
7695
+ amount: number;
7696
+ currency: string;
7697
+ };
7698
+ display: string;
7699
+ /** The provider's stated reason for the charge. Treat with appropriate skepticism. */
7700
+ reason: ProviderText;
7701
+ /** CLI-owned guidance for the agent. */
7702
+ hint: string;
7485
7703
  }
7486
- interface ResolveSigningIdentityOpts {
7487
- as?: string;
7488
- config?: Config | null;
7704
+ /** Provider delivered something and is waiting for sign-off. */
7705
+ interface NextActionApprove {
7706
+ type: "approve";
7707
+ job_id: string;
7708
+ artifact_seq: number;
7709
+ hint: string;
7489
7710
  }
7490
7711
  /**
7491
- * Resolve which caller signing identity `dvm request` / `dvm quote` should
7492
- * use to sign a descriptor-auth submission. Resolution chain (first match
7493
- * wins):
7494
- *
7495
- * 1. `--as <name>` flag → look up named identity.
7496
- * 2. `DVM_IDENTITY_KEY=<hex>` env → use as anonymous key (no name lookup).
7497
- * 3. `config.defaultIdentity` → look up named identity.
7498
- * 4. Identities file has exactly one entry → use it.
7499
- * 5. Else → throw `auth_required` listing available identities.
7712
+ * Provider is working — nothing for the client to do right now.
7713
+ * `hint` is a `ProviderText` when supplied by the provider; a plain `string` is the CLI fallback.
7500
7714
  */
7501
- declare function resolveSigningIdentity(opts: ResolveSigningIdentityOpts): ResolvedSigningIdentity;
7715
+ interface NextActionPoll {
7716
+ type: "poll";
7717
+ job_id: string;
7718
+ estimate_seconds?: number;
7719
+ hint: string | ProviderText;
7720
+ }
7502
7721
  /**
7503
- * Look an identity up by its pubkey rather than by name.
7504
- *
7505
- * The pending-submission resume has to re-sign the original call as the caller
7506
- * who paid for it — signing as anyone else would file the job under the wrong
7507
- * pubkey. It therefore can't go through {@link resolveSigningIdentity}, whose
7508
- * answer depends on flags, env, and config that may have changed since. Returns
7509
- * `null` when the key is no longer configured, which makes the submission
7510
- * unresumable rather than mis-signed.
7722
+ * Provider sent an inbound Cashu payment (refund/change). The CLI auto-claims
7723
+ * the proofs; this surfaces the outcome to the agent. `claimed: false` means the
7724
+ * claim could not complete (e.g. mint down) and `cashu_token` carries the raw
7725
+ * token for manual recovery.
7511
7726
  */
7512
- declare function findSigningIdentityByPubkey(pubkey: string): ResolvedSigningIdentity | null;
7513
-
7514
- declare const IDENTITIES_VERSION: 1;
7515
- /** One stored caller signing identity. The `name` is the file's record key. */
7516
- interface CliIdentityEntry {
7517
- /** 32-byte secp256k1 secret key, lowercase hex (64 chars). Never sent to any server. */
7518
- privkey: string;
7519
- /** 32-byte BIP-340 x-only public key, lowercase hex (64 chars). */
7520
- pubkey: string;
7521
- /** Epoch millis when the entry was generated or imported. */
7522
- createdAt: number;
7727
+ interface NextActionRefund {
7728
+ type: "refund";
7729
+ job_id: string;
7730
+ amount_msats: number;
7731
+ display: string;
7732
+ reason: "refund" | "change";
7733
+ /** Whether the proofs were auto-claimed into the local wallet. */
7734
+ claimed: boolean;
7735
+ /** Raw Cashu token — present only when the auto-claim failed, for manual recovery. */
7736
+ cashu_token?: string;
7737
+ /** CLI-owned guidance for the agent. */
7738
+ hint: string;
7523
7739
  }
7740
+ /** A job status that means the job is over — nothing left for the caller to do. */
7741
+ type TerminalJobStatus = "completed" | "failed" | "cancelled";
7524
7742
  /**
7525
- * Persistent on-disk shape of `~/.dvm/identities.json` (mode 0600). Stores the
7526
- * caller signing identities `dvm request` / `dvm quote` use to auto-sign
7527
- * descriptor-auth submissions.
7743
+ * True when a job status means the job is over and there is nothing left for
7744
+ * the caller to do (`next_action: null`). Every other status — including one
7745
+ * this CLI doesn't recognise — is non-terminal: mapping an unknown status to
7746
+ * `null` would tell an agent a live job is done.
7528
7747
  */
7529
- interface IdentitiesFile {
7530
- version: typeof IDENTITIES_VERSION;
7531
- identities: Record<string, CliIdentityEntry>;
7532
- }
7533
- /** Whether `~/.dvm/identities.json` exists. Cheap presence check; does not parse. */
7534
- declare function identitiesFileExists(): boolean;
7535
- declare function loadIdentities(): IdentitiesFile | null;
7748
+ declare function isTerminalJobStatus(status: string): status is TerminalJobStatus;
7536
7749
  /**
7537
- * Atomically write the identities file with mode 0600. POSIX guarantees rename atomicity within a filesystem,
7538
- * so a crash mid-write leaves either the previous file or the new one.
7539
- *
7540
- * Callers performing a read-modify-write cycle must hold {@link withIdentitiesLock}
7541
- * across the cycle so two concurrent `dvm identity …` invocations cannot
7542
- * clobber each other's writes.
7750
+ * CLI-owned fallback poll action, for job-status snapshots that carry no
7751
+ * message log to derive a richer action from.
7543
7752
  */
7544
- declare function saveIdentities(file: IdentitiesFile): void;
7545
- /** Lock acquisition budget; retry and stale-lock values are in milliseconds. */
7546
- interface WithIdentitiesLockOptions {
7547
- /** Stale-lock threshold in ms. A lock whose mtime is older than this is reclaimed. Default 30_000. */
7548
- stale?: number;
7549
- /** Number of acquisition retries before failing. Default 30. */
7550
- retries?: number;
7551
- /** Milliseconds between retries. Default 1_000. */
7552
- retryIntervalMs?: number;
7753
+ declare function pollNextAction(jobId: string, hint?: string): NextActionPoll;
7754
+ /**
7755
+ * Derive the next action from a batch of messages.
7756
+ * Scans from the end for the last yield-type message and returns the
7757
+ * appropriate action. Returns null if the job is done (complete/cancel)
7758
+ * or no yield message is found.
7759
+ */
7760
+ declare function computeNextAction(jobId: string, messages: Message[]): NextAction;
7761
+
7762
+ interface JobRecord {
7763
+ id: string;
7764
+ endpoint: string;
7765
+ /** Canonical DVM name. Optional for older job records. */
7766
+ dvmId?: string;
7767
+ /** Router-issued claim authorizing DVM attribution for feedback on this job. */
7768
+ feedbackClaim?: string;
7769
+ /** Capability dispatched against this DVM. Optional for older job records. */
7770
+ capability?: string;
7771
+ /** Caller-generated public request id used to recover this exact job. */
7772
+ requestId?: string;
7773
+ status: "submitted" | "processing" | "completed" | "failed" | "timeout" | "cancelled" | "awaiting-input";
7774
+ /** Unix timestamp (ms) when submitted */
7775
+ submittedAt: number;
7776
+ /** Unix timestamp (ms) when completed/failed */
7777
+ completedAt?: number;
7778
+ /**
7779
+ * the terminal outcome (summary + artifact metadata + failure
7780
+ * message), snapshotted the moment the CLI learns the job is over. `dvm status`
7781
+ * replays it instead of re-reading the provider, so a finished job answers
7782
+ * with the same field set on every call — and still answers with the provider
7783
+ * down. Written by `markJobTerminal` in lockstep with a terminal `status`;
7784
+ * absent only on records written before this landed.
7785
+ */
7786
+ completion?: JobCompletion;
7787
+ /** Cost in millisatoshis */
7788
+ costMsats?: number;
7789
+ /** Rail the upfront spend settled on. `credit` — drawn from a prepaid credit. */
7790
+ paymentMethod?: "cashu" | "x402" | "tempo" | "credit";
7791
+ /** Validated Tempo settlement transaction associated with the request. */
7792
+ transactionHash?: string;
7793
+ /**
7794
+ * Caller-pinned Cashu spend mint. When set, every spend leg for
7795
+ * this job (upfront, mid-job `payment-request`, `dvm pay`) draws only from
7796
+ * this mint — no fallback to another allowlisted mint.
7797
+ */
7798
+ pinnedMint?: string;
7799
+ /** Request was submitted through the fail-closed direct-Cashu mode. */
7800
+ strictPerCall?: true;
7801
+ /** Job-wide Cashu swap-fee ceiling in sats, including later recovery swaps. */
7802
+ maxCashuFeeSats?: number;
7803
+ /** Whether Cashu change has been processed (prevents double-processing on repeated polls) */
7804
+ changeProcessed?: boolean;
7805
+ /**
7806
+ * Sequence numbers of inbound `payment` messages (refund/change) whose Cashu
7807
+ * proofs have already been claimed into the local wallet. Per-`seq` (unlike
7808
+ * the coarse `changeProcessed`) because a job may carry several such messages,
7809
+ * and prevents double-claim on replay/re-poll.
7810
+ */
7811
+ claimedPaymentSeqs?: number[];
7812
+ /** Last seen message sequence number for cursor-based polling */
7813
+ messageCursor?: number;
7814
+ /** Running total of payments sent (millisatoshis) */
7815
+ totalPaidMsats?: number;
7816
+ /** Number of payments honoured for this job (auto + manual). */
7817
+ paymentsHonoured?: number;
7818
+ /** Index of received artifact deliverables. */
7819
+ artifacts?: ArtifactRef[];
7820
+ /** Spending policy for this job's conversation. */
7821
+ policy?: {
7822
+ maxTotalMsats: number;
7823
+ autoPayBelowMsats: number;
7824
+ maxIncrementMsats: number;
7825
+ maxPayments: number;
7826
+ };
7827
+ /**
7828
+ * opaque per-job token issued by the DVM at create-time when the
7829
+ * caller resolved to anonymous (the default for free DVMs). Persisted on
7830
+ * the local job record and sent as `X-Job-Token` on every subsequent
7831
+ * `status`/`messages`/`message`/`pay`/`cancel` request. Absent for
7832
+ * authenticated callers (bearer / signed-request).
7833
+ */
7834
+ jobToken?: string;
7835
+ /**
7836
+ * platform `trace_id` captured from the submit response's
7837
+ * `traceparent` header. Persisted locally so `dvm feedback --job <id>` can
7838
+ * derive it without re-querying the platform. Absent on legacy job records
7839
+ * created before this field landed.
7840
+ */
7841
+ traceId?: string;
7842
+ /**
7843
+ * the DVM-signed receipt for this job, snapshotted the moment the
7844
+ * CLI first saw it. Lets `dvm status` replay `receipt_verified` from the
7845
+ * local record with the provider down, alongside `completion`. The durable
7846
+ * copy lives in `~/.dvm/receipts.jsonl` — this one dies with the job record.
7847
+ */
7848
+ receipt?: JobReceipt$1;
7849
+ /** Receipt value was offered but failed the transport's structural guard. */
7850
+ receiptParseError?: ReceiptParseError;
7851
+ /**
7852
+ * whether `/v1/info` advertised `receipts` at submit time. Gates
7853
+ * the one follow-up read the streamed arc spends to collect a receipt, so a
7854
+ * DVM that doesn't issue them costs nothing.
7855
+ */
7856
+ receiptsSupported?: boolean;
7857
+ /**
7858
+ * `/v1/info#builder` as the endpoint served it at submit time —
7859
+ * the anchor a receipt's attestation chain terminates at. Persisted so
7860
+ * verification stays offline; `dvm receipts verify --endpoint` is the opt-in
7861
+ * to re-fetch a possibly-rotated one.
7862
+ */
7863
+ builderAnchor?: ReceiptTrustAnchor;
7553
7864
  }
7554
- /**
7555
- * Run `fn` while holding an OS-level exclusive lock on the identities file,
7556
- * so concurrent `dvm identity …` invocations serialise their
7557
- * read-modify-write cycles instead of clobbering each other. The lock file
7558
- * lives at `~/.dvm/identities.json.lock` and is reclaimed automatically if a
7559
- * previous holder died without releasing.
7560
- *
7561
- * Throws `DvmError("identities_locked", …)` when the lock can't be acquired
7562
- * within the retry budget (~30s by default).
7563
- */
7564
- declare function withIdentitiesLock<T>(fn: () => Promise<T> | T, opts?: WithIdentitiesLockOptions): Promise<T>;
7565
- /**
7566
- * Generate a fresh secp256k1 keypair as a {@link CliIdentityEntry}. The
7567
- * private key is 32 cryptographically-random bytes; the public key is the
7568
- * BIP-340 x-only form — same convention as the SDK's
7569
- * `createSignedRequestVerifier.signRequest`.
7570
- */
7571
- declare function generateIdentity(now?: number): CliIdentityEntry;
7572
- /**
7573
- * Validate a 64-char lowercase hex private key and derive the matching
7574
- * BIP-340 x-only pubkey. Throws `DvmError("invalid_privkey", ...)` on a
7575
- * malformed input. Used by `dvm identity import` and the
7576
- * `DVM_IDENTITY_KEY` env override resolver.
7577
- */
7578
- declare function deriveIdentityFromPrivkey(privkeyHex: string, now?: number): CliIdentityEntry;
7579
-
7580
- /** Outcome of a {@link repairConfigDirMode} pass. Never throws; failures land in `error`. */
7581
- interface ConfigDirModeResult {
7582
- path: string;
7583
- /** Whether the directory exists. False also when the stat itself failed (see `error`). */
7584
- exists: boolean;
7585
- /** Mode after the pass, e.g. `"0700"`. Null when absent, unreadable, or off-POSIX. */
7586
- modeOctal: string | null;
7587
- /** Mode found before the pass, when {@link repaired} is true. */
7588
- previousModeOctal?: string;
7589
- /** True when this call tightened a group/other-accessible directory to 0700. */
7590
- repaired: boolean;
7591
- /** True on Windows, where POSIX modes are meaningless and the pass is a no-op. */
7592
- skippedNonPosix: boolean;
7593
- /** Underlying message when the stat or chmod failed. */
7594
- error?: string;
7865
+ interface ArtifactRef {
7866
+ seq: number;
7867
+ name?: string;
7868
+ mimeType?: string;
7595
7869
  }
7596
- /** Create the caller-state directory owner-only; existing modes are unchanged. */
7597
- declare function ensureConfigDir(): void;
7598
- /**
7599
- * Create a caller-state subdirectory owner-only. Recursive mkdir may also create
7600
- * CONFIG_DIR, so every creation path must carry the same owner-only mode.
7601
- */
7602
- declare function ensureConfigSubdir(path: string): void;
7603
- /**
7604
- * Tighten an existing `CONFIG_DIR` to 0700 when it is group- or
7605
- * other-accessible. Does not create the directory — an absent one is reported,
7606
- * not conjured, so read-mostly callers (`dvm doctor`) stay honest.
7607
- *
7608
- * Only *loosening* is corrected: a directory an operator deliberately set
7609
- * stricter than 0700 (e.g. 0500) is left alone, so a shared-service setup is
7610
- * not fought with on every run. No-op on Windows.
7611
- */
7612
- declare function repairConfigDirMode(): ConfigDirModeResult;
7613
-
7614
- /** Return whether a value is a 0x-prefixed 32-byte secp256k1 secret scalar. */
7615
- declare function isValidEvmPrivateKey(value: string): value is `0x${string}`;
7870
+ declare function saveJob(job: JobRecord): void;
7871
+ /** Merge a partial update into an existing job record. No-op if job not found. */
7872
+ declare function updateJob(id: string, update: Partial<Omit<JobRecord, "id">>): void;
7873
+ /** Persist status and completion together for offline replay. Empty completion is allowed.
7874
+ * Repeated terminal updates preserve the original completedAt. Missing jobs are unchanged. */
7875
+ declare function markJobTerminal(id: string, status: TerminalJobStatus, completion: JobCompletion, extra?: Partial<Omit<JobRecord, "id" | "status" | "completedAt" | "completion">>): void;
7876
+ declare function loadJob(id: string): JobRecord | null;
7877
+ /** Load all job records. Returns [] on missing/corrupt file. */
7878
+ declare function loadAllJobs(): JobRecord[];
7879
+ /** Add a payment to a job's running total and increment its honoured-payment count. No-op if job not found. */
7880
+ declare function addPayment(jobId: string, amountMsats: number): void;
7881
+ declare function refFromJob(job: JobRecord): ProviderRef;
7616
7882
 
7617
7883
  interface MintRecommendation {
7618
7884
  name: string;
@@ -7646,6 +7912,14 @@ declare function info(msg: string): void;
7646
7912
  * so output stays vim-pasteable and shell-redirectable.
7647
7913
  */
7648
7914
  declare function raw(msg: string): void;
7915
+ /**
7916
+ * Write a structured progress event to stderr as one JSON line.
7917
+ *
7918
+ * Lets long-running JSON-mode commands (notably `dvmctl deploy`) stream
7919
+ * progress events to streaming callers — agents-as-intermediaries can tail
7920
+ * stderr while keeping stdout reserved for the final single-line result.
7921
+ */
7922
+ declare function progress(event: object): void;
7649
7923
 
7650
7924
  /**
7651
7925
  * The safety preflight that stands between the caller's Tempo key and the
@@ -7703,6 +7977,92 @@ type TempoWalletIntent = "replace" | "disconnect";
7703
7977
  */
7704
7978
  declare function assertTempoWalletIdle(intent: TempoWalletIntent): Promise<void>;
7705
7979
 
7980
+ /**
7981
+ * Receipt failures are warnings about evidence, not failures of the paid job.
7982
+ * Persistence errors are logged without changing the job's outcome.
7983
+ */
7984
+
7985
+ /** Verify and persist a funding receipt; callers may anchor state only on a sound verdict. */
7986
+ declare function captureFundingReceipt(args: {
7987
+ receipt?: FundingReceipt;
7988
+ parseError?: ReceiptParseError;
7989
+ endpoint: string;
7990
+ builder?: ReceiptTrustAnchor;
7991
+ expectedCreditId: string;
7992
+ expectedFundId: string;
7993
+ expectedFundedMicro?: number;
7994
+ expectedBalanceAfterMicro?: number;
7995
+ expectedLedgerSeq?: number;
7996
+ expectedCallerPubkey: string;
7997
+ }): ReceiptVerification | "unparseable" | "absent";
7998
+ type ReceiptCaptureStatus = ReceiptVerification | "unparseable";
7999
+ interface ReceiptCapture {
8000
+ /** The verdict. `"absent"` when none was offered; `"unparseable"` for an invalid shape. */
8001
+ status: ReceiptCaptureStatus;
8002
+ receipt?: JobReceipt$1;
8003
+ /** Per-link detail, present whenever {@link receipt} is. */
8004
+ checks?: ReceiptVerifyResult["checks"];
8005
+ /** Machine slug for an `invalid` or `unparseable` verdict. */
8006
+ reason?: ReceiptVerifyResult["reason"] | ReceiptParseError;
8007
+ /** Pre-rendered line an intermediary agent can relay verbatim. */
8008
+ display: string;
8009
+ }
8010
+ declare function captureTransportReceipt(jobId: string, response: Pick<JobStatus, "receipt" | "receiptParseError">): ReceiptCapture;
8011
+ /**
8012
+ * `receipt_verified` is always present. Non-absent captures include display
8013
+ * text even when unparseable; raw receipt/checks require a parsed receipt.
8014
+ * Emit only on terminal responses: absent during a running job means not yet
8015
+ * issued, rather than unsupported receipts.
8016
+ */
8017
+ declare function receiptJsonFields(capture: ReceiptCapture): Record<string, unknown>;
8018
+ declare function renderReceiptHuman(capture: ReceiptCapture): void;
8019
+ /**
8020
+ * Snapshot `/v1/info`'s receipt trust anchor onto a job record at `saveJob`
8021
+ * time, so verification later stays offline and pins the anchor that was live
8022
+ * when the job ran rather than whatever the DVM advertises by then.
8023
+ */
8024
+ declare function receiptTrustFields(provider: ProviderInfo): Pick<JobRecord, "receiptsSupported" | "builderAnchor">;
8025
+
8026
+ /**
8027
+ * Drain receipts lack a job's pinned anchor, so read it from the known endpoint.
8028
+ * Unreachable reads return reachable=false; a successful read may still have no
8029
+ * anchor. A present anchor is passed through for cryptographic verification,
8030
+ * where a forged attestation is invalid rather than unattested.
8031
+ */
8032
+ declare function fetchTrustAnchor(transport: Transport, ref: ProviderRef): Promise<TrustAnchorRead>;
8033
+ /**
8034
+ * Collect a receipt missing from a locally-known job.
8035
+ *
8036
+ * The streamed request arc learns a job is over from the log, while
8037
+ * `dvm status` can replay a terminal snapshot written by another command.
8038
+ * Neither path has necessarily seen the receipt, which only rides on a job read.
8039
+ *
8040
+ * Costs one small GET, and only against a DVM that told us at submit time it
8041
+ * issues receipts; everything else returns immediately. Best-effort throughout
8042
+ * a failure here means no receipt this time, not a failed request.
8043
+ */
8044
+ declare function fetchMissingJobReceipt(jobId: string, transport: Transport, ref: ProviderRef): Promise<{
8045
+ receipt?: JobReceipt$1;
8046
+ receiptParseError?: ReceiptParseError;
8047
+ }>;
8048
+ /**
8049
+ * Fill in a job record's missing trust anchor from a live `/v1/info` read.
8050
+ *
8051
+ * `dvm status` can be the first command to see a receipt — for a job submitted
8052
+ * down a paid arc, or one that predates this feature — and a stored receipt
8053
+ * with no anchor verifies as `verified_unattested` when the DVM may well have
8054
+ * an attestation to offer. One describe call settles it. Best-effort: an
8055
+ * unreachable provider leaves the record as it was.
8056
+ */
8057
+ declare function backfillTrustAnchor(jobId: string, transport: Transport, ref: ProviderRef): Promise<ReceiptTrustAnchor | undefined>;
8058
+ /**
8059
+ * Re-verify a receipt already on the job record — the `dvm status` local-replay
8060
+ * path. Deliberately re-runs the chain instead of caching a verdict, so a
8061
+ * tampered `jobs.json` answers `invalid` rather than replaying the verdict the
8062
+ * untampered bytes once earned.
8063
+ */
8064
+ declare function replayStoredReceipt(job: JobRecord): ReceiptCapture;
8065
+
7706
8066
  /** True when a value is a URL-safe caller-generated request identifier. */
7707
8067
  declare function isPublicRequestId(value: unknown): value is string;
7708
8068
 
@@ -7747,6 +8107,18 @@ interface WriteAgentMnemonicResult {
7747
8107
  */
7748
8108
  backupFile: string | null;
7749
8109
  }
8110
+ /**
8111
+ * Read the agent wallet's BIP-39 mnemonic from `~/.dvm/wallet.mnemonic`.
8112
+ *
8113
+ * Returns `null` when the file is absent — callers treat that as the
8114
+ * NUT-13-inactive "degraded mode" and skip `bip39seed` on the cashu-ts
8115
+ * `Wallet` constructor (see `getWallet` in `src/lib/cashu/wallet.ts`).
8116
+ *
8117
+ * The mnemonic is normalised on the way out (trimmed; words lower-cased
8118
+ * and joined by a single space) so any callsite gets the exact form
8119
+ * `mnemonicToSeedSync` expects.
8120
+ */
8121
+ declare function readAgentMnemonic(): string | null;
7750
8122
  /**
7751
8123
  * Throw `agent_mnemonic_exists` if `~/.dvm/wallet.mnemonic` is present and
7752
8124
  * `force` wasn't passed. {@link writeAgentMnemonic} calls this itself, so the
@@ -8137,6 +8509,8 @@ interface ToAgentProofTags {
8137
8509
  }
8138
8510
  /** Convert a cashu-ts proof into the lossless agent-wallet disk shape. */
8139
8511
  declare function toAgentProof(proof: Proof, mintUrl: string, lockedTo: string | null, tags?: ToAgentProofTags): AgentProof;
8512
+ /** Rehydrate persisted proofs for cashu-ts without dropping NUT-12 DLEQ. */
8513
+ declare function toCashuProofs(proofs: AgentProof[]): Proof[];
8140
8514
 
8141
8515
  interface ReceiveResult {
8142
8516
  mintUrl: string;
@@ -8947,6 +9321,13 @@ interface X402PaymentProof {
8947
9321
  * have a typed error. A cached rate can price the ceiling and budget ledger.
8948
9322
  */
8949
9323
  declare function tryX402Payment(request: X402PaymentRequest, wallet: X402Wallet): Promise<X402PaymentProof | null>;
9324
+ /**
9325
+ * Whether this build can sign the requirement — the predicate
9326
+ * {@link tryX402Payment} narrows a v2 challenge with, exported so a caller that
9327
+ * pre-narrows one (the credit rail chain-matches before signing) drops the same
9328
+ * entries the signer would rather than discarding a signable sibling.
9329
+ */
9330
+ declare function isSignableExactRequirement(requirement: PaymentRequirementsV1 | PaymentRequirementsV2): boolean;
8950
9331
 
8951
9332
  /**
8952
9333
  * Key replacement and disconnect require chain proof that every owned channel
@@ -9072,4 +9453,132 @@ declare function readX402ChannelOnChain(args: {
9072
9453
  */
9073
9454
  declare function x402ChannelControlledBy(channel: StoredX402ChannelMetadata, address: string | null | undefined): boolean;
9074
9455
 
9075
- export { ADMIN_STATE_UNAVAILABLE, AGENT_MNEMONIC_FILE, type AgentProof, type AgentWallet, type AmountLabelOptions, type AttestedDvmIdentity, BTC_RATE_FILE, BUDGET_FILE, type BudgetCaps, type BudgetSpendKind, type BudgetWindow, type BuilderLockKeypair, CAPABILITY_NAME_RE, COINGECKO_SIMPLE_PRICE_URL, CONFIG_AUDIT_FILE, CONFIG_BACKUP_FILE, CONFIG_DIR, CONFIG_FILE, CONFIG_PINNED_FILE, CREDITS_FILE, CREDIT_DRAIN_RAILS, CREDIT_FUNDING_MODES, CREDIT_FUND_RAILS, CREDIT_POSTURES, type CachedBtcRate, type CancelOptions, type CashOutMintOutcome, type CashOutQuote, type CliIdentityEntry, type CoinGeckoBtcSpot, type CoinGeckoSpot, type CompletedCreditHistoryPage, type CompletedCreditHistoryQuery, type CompletedCreditHistoryRecord, type CompletedRefundHistoryRecord, type Config, type ConfigBackupInfo, type ConfigDirModeResult, type ConfigField, type ConfigRollbackPreview, type ConfigSnapshotSlot, CreatedInvoice, type CreditConfig, type CreditDrainRail, type CreditFundOutcome, type CreditFundRail, type CreditFundStatus, type CreditFundingMode, type CreditMenu, type CreditOpResult, type CreditPlan, type CreditPosture, type CreditRailPick, type CreditRailReason, type CreditRailSource, type CreditTerms, type CreditWire, DEFAULT_AGENT_MINT_URL, DEFAULT_CREDIT_POSTURE, DEFAULT_RESERVE_LOCKTIME_SECONDS, DIAGNOSTIC_CATALOGUE_VERSION, DbTransport, type DeferredFunding, type DeliveredResult, type DescribeOptions, type DiagnosticCapabilityAuthority, type DiagnosticIdentityAuthority, DrainReceipt, type DrainReceiptChecks, type DrainReceiptVerifyResult, type DrainWire, type DrawCeilingSource, type DrawSkip, DvmError, DvmX402ChannelStorage, type EffectiveFundingRail, type ExpiredCreditLossHistoryRecord, FAVORITES_FILE, FEEDBACK_NUDGES_FILE, FEEDBACK_POSTURES, type FeedbackPosture, type Float, type FloatPayment, type FloatProbe, type FundCreditArgs, FundingReceipt, type FundingReceiptChecks, type FundingReceiptVerifyResult, type FundingSkip, IDENTITIES_FILE, IDENTITIES_VERSION, type IdentitiesFile, InvoiceStatus, JOBS_FILE, type JobCompletion, type JobEnvelope, type JobPolicy, JobReceipt$1 as JobReceipt, type JobRecord, type JobStatus, JsonValue, LightningBackend, type LightningFundingOffer, LightningPayment, LightningTransactionListOptions, LightningTransactionSnapshot, LightningWalletInfo, type LnAddressParts, MESSAGES_DIR, type MeltQuoteInfo, type MeltSweepResult, MemoryKVStore, Message, type MessagePollOptions, MessageType, MintAmountBounds, MintHealthCheckResult, type MintSource, type MnemonicValidationResult, MppxChallenge, MppxCredential, NWC_FUNDING_FLOAT_ROLE, type NextAction, type NextActionRefund, NwcBackend, type NwcConnection, NwcError, type NwcRequestOptions, type NwcTransaction, type OutboundMessage, PAIRINGS_DIR, PRIVKEY_HEX_RE, type PayInvoiceOutcome, type PayInvoiceReconcilingOptions, type PayInvoiceResult, type PayOutcome, type Payment, type PaymentRailKey, PaymentRequired, type PendingDrain, type PendingFunding, type PendingMint, type PendingSubmission, type PendingX402ExactFunding, type PendingX402Funding, type PersistedOutputData, PersistentCounterSource, type PreparedAgentSpend, type ProtectedTarget, type ProviderInfo, type ProviderRef, type ProviderText, type Quote, RAIL_FLAGS, RECEIPTS_FILE, RECENT_SPENDS_CAP, RECOMMENDED_MINTS, RECOVERY_MNEMONIC_FILE, REQUEST_INTENTS_DIR, RESUME_MAX_AGE_MS, RESUME_MAX_ATTEMPTS, ROUTER_FEEDBACK_CLAIM_HEADER, ROUTER_FEEDBACK_CLAIM_TTL_MS, type Rail, type RailFlag, type RailProbe, type ReceiptCapture, type ReceiptChecks, ReceiptCredit, type ReceiptInvalidReason, type ReceiptKeypair, type ReceiptParseError, type ReceiptTrustAnchor, type ReceiptVerification, type ReceiptVerifyResult, type ReleaseMintOutcome, type ResolvedBtcRate, ResourceInfo, SPANS_INSERTED_CHANNEL, STABLECOIN_FUND_RAILS, SUPPORTED_PROTOCOL_VERSION, type SelectError, type SendMessageOptions, type SpanProjectionResult, type SpanRow, type SpanTransport, SpanWriter, type StaleRateNotice, type StatusOptions, type StoredCredit, type StoredFundingMenuSnapshot, type StoredImplicitCredit, type StoredReceipt, type StoredSiblingCredit, type StoredX402ChannelConfig, type StoredX402ChannelMetadata, type StreamOptions, type StreamResult, type SubmissionSweepOutcome, type SubmitOptions, type SuppressedPurchase, type SweepResult, TEMPO_CHAIN_ID, TEMPO_CHANNELS_FILE, TEMPO_EXIT_KEY_MISSING_HINT, TEMPO_MODERATO_CHAIN_ID, TEMPO_MODERATO_RPC, TEMPO_PATH_USD_MODERATO, type TempoAccount, type TempoChannelAssociation, type TempoChannelExitResult, type TempoChannelReconcileResult, type TempoNetwork, type TerminalJobStatus, type Transport, type JobReceipt as TransportJobReceipt, type TrustAnchorRead, type TrustLadder, type V1InfoCapability, type V1InfoResponse, type VerifyJobReceiptArgs, WALLET_FILE, WALLET_VERSION, type WalletInfo, type X402Asset, type X402Balance, type X402BatchPayment, type X402ChannelChainReport, type X402ChannelClient, type X402ChannelReconciliation, type X402ConnectedWallet, type X402CreditFlavour, type X402CreditInstrument, X402EnvValidationError, type X402Network, type X402PaymentProof, type X402RefundArgs, type X402RefundOutcome, type X402RepinnedWallet, type X402UnobservedBalanceProvenance, X402Version, X402Wallet, X402_BATCH_CHANNEL_ABI, X402_BATCH_SETTLEMENT_KEY, X402_BATCH_SETTLEMENT_SCHEME, X402_CHANNELS_FILE, X402_DEFAULT_FACILITATOR, X402_EXACT_AUTHORIZATION_TTL_SECONDS, X402_EXACT_SCHEME, X402_NETWORKS, X402_PENDING_STALE_MS, X402_RECEIVER_AUTHORIZER_KEY, X402_REFUSAL_TRANSACTION_DISCOVERY_WINDOW_MS, X402_RPC_URL_KEY, X402_SELF_RELAY_KEY, abandonPendingSubmission, acknowledgeReplayedX402Payment, acknowledgeX402ChannelOwner, addPayment, advanceTempoChannelExit, applyImplicitReceiptCredit, applyReceiptCredit, applyRetryToPool, asProviderText, asProviderTextOpt, assertAgentMnemonicReplaceable, assertFloatBudget, assertSupportedX402Network, assertTempoWalletIdle, assertValidBudget, assertX402ChannelPayer, assertX402RequirementDescribesChannel, assertX402WalletIdle, attestedDvmIdentity, authenticatedBuilderPubkey, authorizeProtectedRemoval, automaticCreditBoundRail, availableRails, backfillTrustAnchor, backupSecretFile, bindDiagnosticCapabilityAuthority, bindDiagnosticIdentityAuthority, buildAdminAuthHeader, buildAdminChallenge, buildCompletionHintFields, buildDisplayMintInventory, buildPolicy, buildTempoCredential, builderLockPath, canReplaceExpiredX402Deposit, captureFundingReceipt, captureTransportReceipt, cashOutFromMint, cashuSubmissionBindingFingerprint, checkMeltQuoteState, checkReceiptAttestation, clearCreditSelection, clearPendingDrain, clearPendingX402ExactFunding, clearPendingX402Funding, clearRefillRailUnavailable, generateIdentity as cliIdentityStoreGenerateIdentity, commitAgentSpend, completionFromMessages, completionSnapshot, computeNextAction, computeSmartDenominations, configSnapshotPath, connectedTempoAccount, connectedX402Payer, correctPendingFundAmount, costAnchor, coveringMintsForSpend, createDiagnosticCapabilityAuthority, createMonotonicClock, createNoopLogger, createStdoutLogger, createTempoCloseCredential, createX402BatchPayment, currentContext, deleteAgentMnemonic, deriveAgentMasterKeypair, deriveBuilderLockKeypair, deriveBuilderLockPubkey, deriveIdentityFromPrivkey, derivePubkeyFromPrivkey, deriveReceiptKeypair, deriveReceiptSecret, deriveTempoAddress, describeConfigBackup, describeMintBounds, drainReceiptsDisplay, drainReceiptsHint, dvmLocationIdentity, effectiveCreditPosture, effectiveFundingMint, effectiveFundingRail, effectiveMints, emitFloatBudgetWarning, enforceGlobalBudget, ensureAddress, ensureConfig, ensureConfigDir, ensureConfigSubdir, ensureProvisionalCredit, entryKind, epochMsToIso, extendDiagnosticIdentityAuthority, extractBuilderHandle, fetchBtcUsdRate, fetchCoinGeckoBtcUsd, fetchCoinGeckoSpot, fetchLnurlPayInvoice, fetchMeltQuote, fetchMissingJobReceipt, fetchTrustAnchor, findSigningIdentityByPubkey, findX402Channel, floatBudgetJson, floatPaymentDisplay, floatPaymentJson, forgetCredit, formatAmount, formatAmountBestEffort, formatLocktime, formatPaymentAmount, formatSats, formatStaleness, formatUsd, formatUsdcMicrounits, fundAgentWallet, fundCredit, fundWireAmountMicro, fundingModeForTempoIntent, fundingModeForX402Flavour, fundingRailLabel, generateAgentMnemonic, generateEphemeralReceiptKey, generateTempoKey, generateX402PrivateKey, getBalance, getBalanceByMint, getFundingGuidance, getInfo, getInputFeesForProofs, getLastKnownBtcRate, getOutputTraceId, getTempoUsdcBalance, getX402Balance, hashedCanonicalDvmId, identitiesFileExists, info, initLoggers, insertSpanBatch, isAbortError, isCreditFundRail, isCreditFundingMode, isCreditPosture, isFeedbackPosture, isPaymentRailKey, isPublicRequestId, isResumable, isStablecoinFundRail, isTerminalJobStatus, isValidEvmPrivateKey, issueRouterFeedbackClaim, json, listCredits, listFundingMenuSnapshots, listImplicitCredits, listPendingFundings, listPendingX402Fundings, listPendingX402FundingsForChannel, listResumableTempoChargeFundings, listResumableX402ExactFundings, listResumableX402Fundings, listTempoChannelAssociations, listTransactions, listX402Channels, loadAgentWallet, loadAllJobs, loadConfig, loadConfiguredMints, loadCredit, loadFloat, loadIdentities, loadImplicitCredits, loadJob, loadLedger, loadPendingFunding, loadReceipt, loadReceipts, loadResumableX402ExactFunding, loadResumableX402Funding, loadTempoChannelAssociation, loadTempoChannelController, loadTempoChannelEntry, loadX402Wallet, loggers, looksLikeMnemonic, lookupInvoice, makeInvoice, markCredit, markImplicitCreditLost, markJobTerminal, markRefillDrainNoticed, markRefillRailUnavailable, maxKeysetDenomination, microToSats, missingDleqRecoveryDiagnostic, mnemonicFingerprint, monetaryJson, msatsToMicro, msatsToUsd, msatsToUsdCents, msatsToUsdc, needsPocketRefill, needsTopup, nextStepHint, normalizeCreditEndpoint, normalizeFeedbackEndpointHost, nwcDedupWindowMs, nwcRejectionDisplay, nwcTimeoutMs, offersTempoCreditFunding, offersX402CreditFunding, parseBudget, parseCreditMenu, parseCreditTerms, parseLnAddress, parseLocktime, parseNwcUri, parseStatedBudget, parseTraceparent, payInvoiceReconciling, payViaFloat, paymentRailLabel, pendingDrainById, pendingDrainFor, pickCreditFundRail, pinConfigSnapshot, pinDimension, planConfigReset, planCreditForQuote, planProbeDraw, pocketTargetMicro, pollNextAction, pollPendingCreditFundings, preferLightningFirst, prepareAgentSpend, prepareP2PKMint, previewConfigRollback, printFundingGuidance, probeFloat, probeRailLabel, probeWallets, processX402BatchCorrection, processX402BatchResponse, processX402BatchResponseForWallet, projectDiagnosticFields, projectEventName, projectSpanRow, providerProseSources, providerTextToString, railLabelAtSentenceStart, randomTraceId, raw, readCompletedCreditHistory, readFundValuation, readX402ChannelOnChain, receiptDisplay, receiptFailureDetail, receiptHint, receiptIssuedAtIso, receiptJsonFields, receiptPubkeyFromSecret, receiptTrustFields, receiveToAgentWallet, reclaimAtMs, reconcileRefusedX402Deposits, reconcileTempoChannelOnChain, recordBalanceResponse, recordCreditX402Instrument, recordDrainReceipts, recordFloatSpend, recordFundResponse, recordFundingMenuSnapshot, recordPendingDrain, recordPendingX402ExactFunding, recordPendingX402Funding, recordRefusedDrawBalance, recordSpend, recordX402ChannelMetadata, recoverPendingSubmission, redactUrl, redactUrlsInText, refFromJob, refundX402BatchChannel, releaseAgentReserve, removeX402Wallet, renderReceiptHuman, repairConfigDirMode, repinX402WalletNetwork, replayStoredReceipt, reserveAgentWallet, resolveBtcUsdRate, resolveFundMint, resolveLnurlPayMetadataUrl, resolveRpcHttpTransportOptions, resolveRpcOverride, resolveSigningIdentity, resolveTempoAsset, resolveTempoNetwork, resolveX402Asset, resolveX402ChannelRpc, restoreProofsFromOutputs, retireConfigBackup, retirePendingX402Funding, rollbackConfig, rpcEndpointLine, rpcEndpointSuffix, saveAgentWallet, saveIdentities, saveJob, saveLedger, saveX402Wallet, selectProofsForSpend, serializeOutputData, setEmitter, setOutputTraceId, settleDrainEvidence, shellQuoteArg, signDvmRequestData, signRequestData, signedRequestDomain, spendableAt, staleRateNotice, statusSnapshot, swapFeeForProofs, swapSendReserve, sweepPendingMelts, sweepPendingMints, sweepPendingSubmissions, sweepStaleInFlight, tempoBalanceCheckHint, tempoChannelControlledBy, tempoCredentialAmountMicro, tempoKeyImportRoutes, tempoSessionChallenge, tempoSessionChallengeMicro, tempoTokenReference, tempoWrongAssetHint, tierCapOverrides, toAgentProof, toFloatError, transportErrorCode, trustLadderFor, trustOverrideCapMicro, tryResolveBtcUsdRate, tryResolveTempoAsset, tryX402Payment, unreachableRailDisplay, unreachableRailHint, unrecordedFloatBudgetWarning, unsignRequestData, updateConfig, updateJob, usdToMsats, usdcToMsats, validateAgentMnemonic, validateLnAddress, validateX402Env, verifyCanonicalSignedRequest, verifyChallenge, verifyDrainReceiptChain, verifyFundingReceiptChain, verifyJobReceipt, verifyRouterFeedbackClaim, walletExists, weakestReceiptVerdict, windowStart, withIdentitiesLock, withInitRetry, withNwcPool, withTempoChannelLock, withTraceContext, withWalletLock, withX402ChannelLock, writeAgentMnemonic, x402ChannelBalanceUnreconciledAt, x402ChannelControlledBy, x402ChannelReservation, x402CreditChannelNetworks, x402CreditExactNetworks, x402ExactFundingDead, x402FlavourForInstrument, x402NetworkByCaip2, x402NetworkBySlug, x402NetworkLabel, x402NetworkListForCopy, x402PendingBlockExpiresAt, x402PendingDepositExpiresAt, x402PendingFundingJson, x402PendingRetired, x402PendingStale, x402PendingUnsettled, x402RequiredFromError, x402ReservationRelease, x402SupportedNetworksHint, x402VoucherPendingRefusal, x402WrongAssetHint };
9456
+ /** Credential projection only; config persistence and replacement policy belong to its owner. */
9457
+ interface WalletCredentialConfig {
9458
+ x402?: {
9459
+ privateKey: string;
9460
+ network?: string;
9461
+ };
9462
+ tempo?: {
9463
+ method: string;
9464
+ apiKey?: string;
9465
+ network?: "mainnet" | "moderato";
9466
+ };
9467
+ }
9468
+ interface TempoCredentialAccount {
9469
+ address: `0x${string}`;
9470
+ privateKey: `0x${string}`;
9471
+ network?: "mainnet" | "moderato";
9472
+ }
9473
+ declare function x402WalletFromConfig(config: WalletCredentialConfig | null): X402Wallet | null;
9474
+ declare function tempoAccountFromConfig(config: WalletCredentialConfig | null): Promise<TempoCredentialAccount | null>;
9475
+
9476
+ /** Load the persisted ledger. Returns an empty ledger if the file is missing or corrupt. */
9477
+ declare function loadBudgetLedger(file: string): BudgetLedger;
9478
+ /**
9479
+ * Persist the ledger using a temp-file-and-rename so a crash mid-write cannot
9480
+ * leave a partial JSON on disk (which would silently reset configured caps).
9481
+ * Confirmed spending is retained indefinitely; budget checks apply their own
9482
+ * window cutoffs.
9483
+ */
9484
+ declare function saveBudgetLedger(file: string, ledger: BudgetLedger): void;
9485
+ /**
9486
+ * Record one logical spend at most once across a crash/replay window.
9487
+ *
9488
+ * Callers must give the logical operation a stable `jobId`. Kind, job id and
9489
+ * provider form the idempotency tuple, so unrelated payments on one job can
9490
+ * still use the ordinary append-only path (`once = false`).
9491
+ * The caller holds its existing payment lock across check, payment, and append;
9492
+ * this writer does not create a separate lock domain.
9493
+ */
9494
+ declare function appendBudgetSpend(file: string, opts: RecordSpendOptions, once?: boolean): boolean;
9495
+
9496
+ /**
9497
+ * Derived per-DVM agent refund keypair. Both halves are hex; the privkey is
9498
+ * 32 bytes (64 chars), the pubkey is the 33-byte compressed secp256k1
9499
+ * encoding (66 chars starting with `02` or `03`).
9500
+ *
9501
+ * The privkey must never be persisted to disk — it is regenerated on demand
9502
+ * from the agent's mnemonic when `dvm wallet release` needs to sign refund
9503
+ * witnesses on unshipped pre-fund proofs.
9504
+ */
9505
+ interface AgentRefundKeypair {
9506
+ privkey: string;
9507
+ pubkey: string;
9508
+ }
9509
+ /**
9510
+ * Derive the agent's per-DVM refund keypair from a BIP-39 mnemonic.
9511
+ *
9512
+ * The pubkey is attached as the NUT-11 `refund` tag on pre-fund proofs minted
9513
+ * by `dvm wallet reserve --builder <handle>` **and**, since the behavior was introduced, on every
9514
+ * per-call swap output; the privkey signs refund witnesses on the matching
9515
+ * proofs after `t_expire` (`dvm wallet release`, and the auto-reclaim in
9516
+ * `sweepPendingSubmissions`).
9517
+ *
9518
+ * Per-DVM scoping means colluding builders cannot correlate the agent's
9519
+ * identity across DVMs from refund tags alone — each DVM sees a different
9520
+ * agent pubkey. What does trade away, deliberately, is *within*-DVM
9521
+ * unlinkability: one DVM now sees the same refund pubkey on every call from
9522
+ * this agent. The operator accepted that in exchange for eliminating
9523
+ * caller-side money loss. The mnemonic + `canonical_dvm_id` is the stable
9524
+ * derivation root; nothing else needs to be persisted to recover the keypair.
9525
+ */
9526
+ declare function deriveAgentRefundSubkey(mnemonic: string, canonicalDvmId: string): AgentRefundKeypair;
9527
+ declare function deriveAgentRefundSubkeyPubkey(mnemonic: string, canonicalDvmId: string): string;
9528
+
9529
+ declare function sha256hex(input: string): string;
9530
+
9531
+ /**
9532
+ * Wire strings the Tempo session handshake is keyed on, shared by the SDK that
9533
+ * writes them and the caller that reads them.
9534
+ *
9535
+ * Deliberately dependency-free and on the `src/lib/` side of the boundary:
9536
+ * `src/sdk/server/` imports from `src/lib/` freely, and nothing in `src/lib/`
9537
+ * may import back.
9538
+ */
9539
+ /**
9540
+ * The reason a DVM gives when it has accepted a Tempo session's on-chain
9541
+ * management top-up and now wants the cumulative voucher that funds against it.
9542
+ *
9543
+ * mppx's session hook posts the management credential and expects an empty
9544
+ * success before it will sign the voucher; dvmkit shares `/v1/credit` for both
9545
+ * phases, so the SDK answers that step with a 402 carrying this reason plus the
9546
+ * voucher challenge, and `credit-fund.ts`'s bridge translates exactly that
9547
+ * answer into the 204 mppx is waiting for.
9548
+ *
9549
+ * Written once here because the coupling is otherwise a substring match across
9550
+ * two modules with nothing linking them: a reword on the SDK side — the sort of
9551
+ * thing payment-language pass does routinely — would stop the
9552
+ * translation, mppx would never build the voucher, and every Tempo session
9553
+ * top-up would wedge, caught only by the non-per-PR Tempo money loop.
9554
+ * Same reasoning as `MPPX_HMAC_MISMATCH_REASON` in `sdk/server/mpp-setup.ts`.
9555
+ */
9556
+ declare const TEMPO_SESSION_UPDATED_REASON = "Tempo session updated; attach the next voucher to fund this credit.";
9557
+
9558
+ /** Backoff carried across repeated quote polls within one wait. */
9559
+ interface MintQuoteRetryState {
9560
+ backoffMs: number;
9561
+ lastRetryAt?: number;
9562
+ }
9563
+ /** Clock and deadline seams shared by fund/reserve waits and recovery sweeps. */
9564
+ interface MintQuoteRetryOptions {
9565
+ /** Absolute epoch/monotonic value, in the same time domain returned by `now`. */
9566
+ deadlineMs: number;
9567
+ /** Quote identifier included in a structured deadline error. */
9568
+ quoteId: string;
9569
+ /** Mutable state when backoff must survive more than one operation call. */
9570
+ state?: MintQuoteRetryState;
9571
+ now?: () => number;
9572
+ sleep?: (ms: number) => Promise<void>;
9573
+ }
9574
+ declare function createMintQuoteRetryState(): MintQuoteRetryState;
9575
+ /**
9576
+ * Retry one mint quote-status operation until it succeeds or its caller's
9577
+ * deadline arrives. Unknown/client failures are rethrown immediately.
9578
+ */
9579
+ declare function retryMintQuoteOperation<T>(operation: () => Promise<T>, opts: MintQuoteRetryOptions): Promise<T>;
9580
+
9581
+ /** Bind a token-dependent fund commitment into a serializable resume context. */
9582
+ declare function bindCashuTokenToSubmissionContext(context: PendingSubmissionContext | undefined, cashuToken: string): PendingSubmissionContext | undefined;
9583
+
9584
+ export { ADMIN_STATE_UNAVAILABLE, AGENT_MNEMONIC_FILE, type AgentProof, type AgentRecentSpend, type AgentWallet, type AmountLabelOptions, type AttestedDvmIdentity, BTC_RATE_FILE, BUDGET_FILE, type BudgetCaps, type BudgetCheckResult, type BudgetLedger, type BudgetLedgerEntry, type BudgetSpendBreakdown, type BudgetSpendKind, type BudgetWindow, type BuilderLockKeypair, CAPABILITY_NAME_RE, COINGECKO_SIMPLE_PRICE_URL, CONFIG_AUDIT_FILE, CONFIG_BACKUP_FILE, CONFIG_DIR, CONFIG_FILE, CONFIG_PINNED_FILE, CREDITS_FILE, CREDIT_DRAIN_RAILS, CREDIT_FUNDING_MODES, CREDIT_FUND_RAILS, CREDIT_POSTURES, type CachedBtcRate, type CancelOptions, type CashOutMintOutcome, type CashOutQuote, type CliIdentityEntry, type CoinGeckoBtcSpot, type CoinGeckoSpot, type CompletedCreditHistoryPage, type CompletedCreditHistoryQuery, type CompletedCreditHistoryRecord, type CompletedRefundHistoryRecord, type Config, type ConfigBackupInfo, type ConfigDirModeResult, type ConfigField, type ConfigRollbackPreview, type ConfigSnapshotSlot, CreatedInvoice, type CreditConfig, type CreditDrainRail, type CreditFundOutcome, type CreditFundRail, type CreditFundStatus, type CreditFundingMode, type CreditMenu, type CreditOpResult, type CreditPlan, type CreditPosture, type CreditRailPick, type CreditRailReason, type CreditRailSource, type CreditTerms, type CreditWire, DEFAULT_AGENT_MINT_URL, DEFAULT_CREDIT_POSTURE, DEFAULT_RESERVE_LOCKTIME_SECONDS, DIAGNOSTIC_CATALOGUE_VERSION, DbTransport, type DeferredFunding, type DeliveredResult, type DescribeOptions, type DiagnosticCapabilityAuthority, type DiagnosticIdentityAuthority, DrainReceipt, type DrainReceiptChecks, type DrainReceiptVerifyResult, type DrainWire, type DrawCeilingSource, type DrawSkip, DvmError, DvmX402ChannelStorage, type EffectiveFundingRail, type ExpiredCreditLossHistoryRecord, FAVORITES_FILE, FEEDBACK_NUDGES_FILE, FEEDBACK_POSTURES, type FeedbackPosture, type Float, type FloatPayment, type FloatProbe, type FundCreditArgs, type FundValuation, FundingReceipt, type FundingReceiptChecks, type FundingReceiptVerifyResult, type FundingSkip, IDENTITIES_FILE, IDENTITIES_VERSION, type IdentitiesFile, InvoiceStatus, JOBS_FILE, type JobCompletion, type JobEnvelope, type JobPolicy, JobReceipt$1 as JobReceipt, type JobRecord, type JobStatus, JsonValue, LightningBackend, type LightningFundingOffer, LightningPayment, LightningTransactionListOptions, LightningTransactionSnapshot, LightningWalletInfo, type LnAddressParts, MESSAGES_DIR, type MeltQuoteInfo, type MeltSweepResult, MemoryKVStore, Message, type MessagePollOptions, MessageType, MintAmountBounds, MintHealthCheckResult, type MintSource, type MnemonicValidationResult, MppxChallenge, MppxCredential, NWC_FUNDING_FLOAT_ROLE, type NextAction, type NextActionRefund, NwcBackend, type NwcConnection, NwcError, type NwcRequestOptions, type NwcTransaction, type OutboundMessage, PAIRINGS_DIR, PRIVKEY_HEX_RE, type PayInvoiceOutcome, type PayInvoiceReconcilingOptions, type PayInvoiceResult, type PayOutcome, type Payment, type PaymentRailKey, PaymentRequired, PaymentRequirementsV1, PaymentRequirementsV2, type PendingDrain, type PendingFunding, type PendingMelt, type PendingMint, type PendingMintMintingState, type PendingSubmission, type PendingSubmissionContext, type PendingTempoChargeFunding, type PendingX402ExactFunding, type PendingX402Funding, type PersistedOutputData, PersistentCounterSource, type PreparedAgentSpend, type ProtectedTarget, type ProviderInfo, type ProviderRef, type ProviderText, type Quote, RAIL_FLAGS, RECEIPTS_FILE, RECENT_SPENDS_CAP, RECOMMENDED_MINTS, RECOVERY_MNEMONIC_FILE, REQUEST_INTENTS_DIR, RESUME_MAX_AGE_MS, RESUME_MAX_ATTEMPTS, ROUTER_FEEDBACK_CLAIM_HEADER, ROUTER_FEEDBACK_CLAIM_TTL_MS, type Rail, type RailAsset, type RailFlag, type RailProbe, type ReceiptCapture, type ReceiptChecks, ReceiptCredit, type ReceiptInvalidReason, type ReceiptKeypair, type ReceiptParseError, type ReceiptTrustAnchor, type ReceiptVerification, type ReceiptVerifyResult, type RecordSpendOptions, type ReleaseMintOutcome, type ResolvedBtcRate, ResourceInfo, type RpcSource, SPANS_INSERTED_CHANNEL, STABLECOIN_FUND_RAILS, SUPPORTED_PROTOCOL_VERSION, type SelectError, type SendMessageOptions, type SpanProjectionResult, type SpanRow, type SpanTransport, SpanWriter, type StaleRateNotice, type StatusOptions, type StoredCredit, type StoredCreditX402Binding, type StoredFundingMenuSnapshot, type StoredImplicitCredit, type StoredReceipt, type StoredSiblingCredit, type StoredX402ChannelConfig, type StoredX402ChannelMetadata, type StreamOptions, type StreamResult, type SubmissionSweepOutcome, type SubmitOptions, type SuppressedPurchase, type SwapSendReserve, type SweepResult, TEMPO_CHAIN_ID, TEMPO_CHANNELS_FILE, TEMPO_CHARGE_PENDING_STALE_MS, TEMPO_EXIT_KEY_MISSING_HINT, TEMPO_MODERATO_CHAIN_ID, TEMPO_MODERATO_RPC, TEMPO_PATH_USD_MODERATO, TEMPO_SESSION_UPDATED_REASON, type TempoAccount, type TempoChannelAssociation, type TempoChannelController, type TempoChannelDescriptor, type TempoChannelExitResult, type TempoChannelReconcileResult, type TempoChannelStoreContext, type TempoCredentialAccount, type TempoNetwork, type TempoSessionClientResolver, type TerminalJobStatus, type Transport, type JobReceipt as TransportJobReceipt, type TrustAnchorRead, type TrustLadder, type V1InfoCapability, type V1InfoResponse, type VerifyJobReceiptArgs, WALLET_FILE, WALLET_VERSION, type WalletCredentialConfig, type WalletInfo, type X402Asset, type X402Balance, type X402BatchPayment, type X402ChannelChainReport, type X402ChannelClient, type X402ChannelReconciliation, type X402ConnectedWallet, type X402CreditFlavour, type X402CreditInstrument, X402EnvValidationError, type X402Network, type X402PaymentProof, type X402RefundArgs, type X402RefundOutcome, type X402RepinnedWallet, type X402UnobservedBalanceProvenance, X402Version, type X402VoucherPendingState, X402Wallet, X402_BATCH_CHANNEL_ABI, X402_BATCH_SETTLEMENT_KEY, X402_BATCH_SETTLEMENT_SCHEME, X402_CHANNELS_FILE, X402_DEFAULT_FACILITATOR, X402_EXACT_AUTHORIZATION_TTL_SECONDS, X402_EXACT_SCHEME, X402_NETWORKS, X402_PENDING_STALE_MS, X402_RECEIVER_AUTHORIZER_KEY, X402_REFUSAL_TRANSACTION_DISCOVERY_WINDOW_MS, X402_RPC_URL_KEY, X402_SELF_RELAY_KEY, abandonPendingSubmission, acknowledgeReplayedX402Payment, acknowledgeX402ChannelOwner, addPayment, advanceTempoChannelExit, appendBudgetSpend, appendFundingReceipt, appendReceipt, applyImplicitReceiptCredit, applyReceiptCredit, applyRetryToPool, asProviderText, asProviderTextOpt, assertAgentMnemonicReplaceable, assertFloatBudget, assertNoRivalX402Voucher, assertSupportedX402Network, assertTempoSessionChallengeWithinAsk, assertTempoSessionDepositWithinCap, assertTempoSessionVoucherWithinAsk, assertTempoWalletIdle, assertValidBudget, assertX402ChannelPayer, assertX402RequirementDescribesChannel, assertX402WalletIdle, attestedDvmIdentity, authenticatedBuilderPubkey, authorizeProtectedRemoval, automaticCreditBoundRail, availableRails, backfillTrustAnchor, backupSecretFile, bindCashuTokenToSubmissionContext, bindDiagnosticCapabilityAuthority, bindDiagnosticIdentityAuthority, breakdownSince, buildAdminAuthHeader, buildAdminChallenge, buildCompletionHintFields, buildDisplayMintInventory, buildPolicy, buildTempoCredential, builderLockPath, canReplaceExpiredX402Deposit, capFor, captureFundingReceipt, captureTransportReceipt, cashOutFromMint, cashuSubmissionBindingFingerprint, cashuSubmissionBindingFromContext, checkBudgetForLedger, checkMeltQuoteState, checkReceiptAttestation, clearCreditSelection, clearPendingDrain, clearPendingFunding, clearPendingTempoChargeFunding, clearPendingX402ExactFunding, clearPendingX402Funding, clearRefillRailUnavailable, generateIdentity as cliIdentityStoreGenerateIdentity, commitAgentSpend, completionFromMessages, completionSnapshot, computeNextAction, computeSmartDenominations, configSnapshotPath, connectedTempoAccount, connectedX402Payer, correctPendingFundAmount, costAnchor, coveringMintsForSpend, createDiagnosticCapabilityAuthority, createMintQuoteRetryState, createMonotonicClock, createNoopLogger, createStdoutLogger, createTempoChannelStore, createTempoCloseCredential, createTempoCreditSession, createTempoSessionPaymentFetch, createX402BatchPayment, currentContext, deleteAgentMnemonic, deriveAgentMasterKeypair, deriveAgentRefundSubkey, deriveAgentRefundSubkeyPubkey, deriveBuilderLockKeypair, deriveBuilderLockPubkey, deriveIdentityFromPrivkey, derivePubkeyFromPrivkey, deriveReceiptKeypair, deriveReceiptSecret, deriveTempoAddress, describeConfigBackup, describeMintBounds, drainReceiptsDisplay, drainReceiptsHint, dvmLocationIdentity, effectiveCreditPosture, effectiveFundingMint, effectiveFundingRail, effectiveMints, emitFloatBudgetWarning, enforceGlobalBudget, ensureAddress, ensureConfig, ensureConfigDir, ensureConfigSubdir, ensureProvisionalCredit, entryKind, epochMsToIso, extendDiagnosticIdentityAuthority, extractBuilderHandle, fetchBtcUsdRate, fetchCoinGeckoBtcUsd, fetchCoinGeckoSpot, fetchLnurlPayInvoice, fetchMeltQuote, fetchMissingJobReceipt, fetchTrustAnchor, findSigningIdentityByPubkey, findX402Channel, floatBudgetJson, floatPaymentDisplay, floatPaymentJson, forgetCredit, formatAmount, formatAmountBestEffort, formatLocktime, formatPaymentAmount, formatSats, formatStaleness, formatUsd, formatUsdcMicrounits, fundAgentWallet, fundCredit, fundWireAmountMicro, fundingModeForTempoIntent, fundingModeForX402Flavour, fundingRailLabel, generateAgentMnemonic, generateEphemeralReceiptKey, generateTempoKey, generateX402PrivateKey, getBalance, getBalanceByMint, getFundingGuidance, getInfo, getInputFeesForProofs, getLastKnownBtcRate, getOutputTraceId, getTempoUsdcBalance, getX402Balance, hashedCanonicalDvmId, identitiesFileExists, info, initLoggers, insertSpanBatch, isAbortError, isCreditFundRail, isCreditFundingMode, isCreditPosture, isFeedbackPosture, isPaymentRailKey, isPublicRequestId, isResumable, isSignableExactRequirement, isStablecoinFundRail, isTerminalJobStatus, isValidEvmPrivateKey, issueRouterFeedbackClaim, json, listCredits, listFundingMenuSnapshots, listImplicitCredits, listPendingFundings, listPendingX402Fundings, listPendingX402FundingsForChannel, listResumableTempoChargeFundings, listResumableX402ExactFundings, listResumableX402Fundings, listTempoChannelAssociations, listTransactions, listX402Channels, loadAgentWallet, loadAllJobs, loadBudgetLedger, loadConfig, loadConfiguredMints, loadCredit, loadCreditX402Binding, loadFloat, loadIdentities, loadImplicitCredits, loadJob, loadLedger, loadPendingFunding, loadReceipt, loadReceipts, loadResumableTempoChargeFunding, loadResumableX402ExactFunding, loadResumableX402Funding, loadTempoChannelAssociation, loadTempoChannelAssociationByKey, loadTempoChannelController, loadTempoChannelEntry, loadWalletConfiguredMints, loadX402Wallet, loggers, looksLikeMnemonic, lookupInvoice, makeInvoice, markCredit, markImplicitCreditLost, markJobTerminal, markRefillDrainNoticed, markRefillRailUnavailable, maxAdvertisedMicro, maxKeysetDenomination, microToSats, missingDleqRecoveryDiagnostic, mnemonicFingerprint, monetaryJson, msatsToMicro, msatsToUsd, msatsToUsdCents, msatsToUsdc, needsPocketRefill, needsTopup, nextStepHint, normalizeCreditEndpoint, normalizeFeedbackEndpointHost, nwcDedupWindowMs, nwcRejectionDisplay, nwcTimeoutMs, offersTempoCreditCharge, offersTempoCreditFunding, offersTempoCreditSession, offersX402CreditChannel, offersX402CreditFlavour, offersX402CreditFunding, parseBudget, parseCreditMenu, parseCreditTerms, parseLnAddress, parseLocktime, parseNwcUri, parseStatedBudget, parseTraceparent, payInvoiceReconciling, payViaFloat, paymentRailLabel, pendingDrainById, pendingDrainFor, persistTempoOpenCredential, pickCreditFundRail, pinConfigSnapshot, pinDimension, planConfigReset, planCreditForQuote, planProbeDraw, pocketTargetMicro, pollNextAction, pollPendingCreditFundings, preferLightningFirst, prepareAgentSpend, prepareP2PKMint, previewConfigRollback, printFundingGuidance, probeFloat, probeRailLabel, probeWallets, processX402BatchCorrection, processX402BatchResponse, processX402BatchResponseForWallet, progress, projectDiagnosticFields, projectEventName, projectSpanRow, providerProseSources, providerTextToString, railLabelAtSentenceStart, randomTraceId, raw, readAgentMnemonic, readCompletedCreditHistory, readFundValuation, readX402ChannelOnChain, receiptDisplay, receiptFailureDetail, receiptHint, receiptIssuedAtIso, receiptJsonFields, receiptPubkeyFromSecret, receiptTrustFields, receiveToAgentWallet, reclaimAtMs, reconcileRefusedX402Deposits, reconcileTempoChannelOnChain, recordBalanceResponse, recordCreditX402Instrument, recordDrainReceipts, recordFloatSpend, recordFundResponse, recordFundingMenuSnapshot, recordPendingDrain, recordPendingFunding, recordPendingTempoChargeFunding, recordPendingX402ExactFunding, recordPendingX402Funding, recordRefusedDrawBalance, recordSpend, recordX402ChannelMetadata, recoverPendingSubmission, redactUrl, redactUrlsInText, refFromJob, refundX402BatchChannel, rehydrateOutputData, releaseAgentReserve, removeX402Wallet, renderReceiptHuman, repairConfigDirMode, repinX402WalletNetwork, replayStoredReceipt, reserveAgentWallet, resolveBtcUsdRate, resolveFundMint, resolveLnurlPayMetadataUrl, resolveRpcHttpTransportOptions, resolveRpcOverride, resolveSigningIdentity, resolveTempoAsset, resolveTempoNetwork, resolveX402Asset, resolveX402ChannelRpc, restoreProofsFromOutputs, retireConfigBackup, retirePendingX402Funding, retireTempoChannel, retireTempoChannelScope, retryMintQuoteOperation, rollbackConfig, rpcEndpointLine, rpcEndpointSuffix, saveAgentWallet, saveBudgetLedger, saveIdentities, saveJob, saveLedger, saveX402Wallet, selectProofsForSpend, serializeOutputData, setEmitter, setOutputTraceId, settleDrainEvidence, sha256hex, shellQuoteArg, signDvmRequestData, signRequestData, signedRequestDomain, spendEntry, spendableAt, staleRateNotice, statusSnapshot, swapFeeForProofs, swapSendReserve, sweepPendingMelts, sweepPendingMints, sweepPendingSubmissions, sweepStaleInFlight, tempoAccountFromConfig, tempoBalanceCheckHint, tempoChannelControlledBy, tempoChargeCredentialSettleable, tempoCredentialAmountMicro, tempoCredentialValidBefore, tempoDescriptorController, tempoKeyImportRoutes, tempoSessionAssociationByKey, tempoSessionChallenge, tempoSessionChallengeChannelScope, tempoSessionChallengeMicro, tempoSessionCredentialChannelScope, tempoSessionCredentialCumulativeMicro, tempoSessionCumulativeCapMicro, tempoSessionPriorCumulativeMicro, tempoTokenReference, tempoWrongAssetHint, tierCapOverrides, toAgentProof, toCashuProofs, toFloatError, transportErrorCode, trustLadderFor, trustOverrideCapMicro, tryResolveBtcUsdRate, tryResolveTempoAsset, tryX402Payment, unreachableRailDisplay, unreachableRailHint, unrecordedFloatBudgetWarning, unsignRequestData, updateConfig, updateJob, usdToMsats, usdcToMsats, validateAgentMnemonic, validateLnAddress, validateX402Env, verifyCanonicalSignedRequest, verifyChallenge, verifyDrainReceiptChain, verifyFundingReceiptChain, verifyJobReceipt, verifyRouterFeedbackClaim, walletExists, weakestReceiptVerdict, windowEnd, windowStart, withIdentitiesLock, withInitRetry, withNwcPool, withTempoChannelLock, withTraceContext, withWalletLock, withX402ChannelLock, withholdsTempoCreditSession, withinAdvertisedTolerance, writeAgentMnemonic, x402ChannelBalanceUnreconciledAt, x402ChannelControlledBy, x402ChannelReservation, x402CreditChannelNetworks, x402CreditExactNetworks, x402CreditFlavour, x402CreditFundingNetworks, x402ExactFundingDead, x402FlavourForInstrument, x402InstrumentForFlavour, x402NetworkByCaip2, x402NetworkBySlug, x402NetworkLabel, x402NetworkListForCopy, x402PendingBlockExpiresAt, x402PendingDepositExpiresAt, x402PendingFundingJson, x402PendingRetired, x402PendingStale, x402PendingUnsettled, x402RequiredFromError, x402ReservationRelease, x402SupportedNetworksHint, x402VoucherPendingRefusal, x402VoucherPendingState, x402WalletFromConfig, x402WrongAssetHint };