@dvmkit/sdk 0.10.0 → 0.11.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 (57) hide show
  1. package/dist/{chunk-3Q6FTZDB.js → chunk-3YFFZLW7.js} +2 -2
  2. package/dist/{chunk-YOSZIWC3.js → chunk-55DVLBCD.js} +135 -8
  3. package/dist/{chunk-VMHYGKWT.js → chunk-566CFXGU.js} +9 -1
  4. package/dist/chunk-5H7P3ORL.js +92 -0
  5. package/dist/{chunk-3R7NQA3Z.js → chunk-7KQLPVV7.js} +1 -1
  6. package/dist/{chunk-QNKK7SPY.js → chunk-AIQGF52I.js} +350 -71
  7. package/dist/{chunk-JNECYURT.js → chunk-D4FFS3IS.js} +1 -1
  8. package/dist/{chunk-VTHYQCDB.js → chunk-E7ZBCT5U.js} +1 -1
  9. package/dist/{chunk-MMGSYMIC.js → chunk-EP7OVWI5.js} +1 -1
  10. package/dist/{chunk-LDIPVPKI.js → chunk-FFRTAQUW.js} +1 -1
  11. package/dist/chunk-H3GGFEE5.js +57 -0
  12. package/dist/{chunk-M3T5JYDJ.js → chunk-HNXMWHLU.js} +1 -1
  13. package/dist/{chunk-Y6DO5WSO.js → chunk-HQPQ4PFI.js} +43 -21
  14. package/dist/{chunk-UKD3R2KU.js → chunk-HW2UCOOC.js} +4 -55
  15. package/dist/{chunk-FFXXGCVG.js → chunk-ITRSITFP.js} +1 -1
  16. package/dist/{chunk-MU3IE434.js → chunk-JLT2YIBS.js} +267 -52
  17. package/dist/{chunk-STJBBVNL.js → chunk-K2ZNIQZP.js} +458 -69
  18. package/dist/{chunk-KFCEXCZM.js → chunk-KJZVTWMX.js} +1 -1
  19. package/dist/{chunk-W3VGCNG6.js → chunk-LDKV4UHI.js} +1 -1
  20. package/dist/{chunk-AJ6UHXUA.js → chunk-M4NFYEEY.js} +1 -1
  21. package/dist/{chunk-MB6R4XPZ.js → chunk-NS2OMIU7.js} +15 -3
  22. package/dist/{chunk-VUGEEMLT.js → chunk-RPUFWIT4.js} +11 -89
  23. package/dist/{chunk-EWZFANHJ.js → chunk-VWIMQ5H5.js} +1 -1
  24. package/dist/{chunk-2XQLL6N6.js → chunk-WFCVS6QB.js} +2 -2
  25. package/dist/{chunk-QGNXYVBO.js → chunk-Z4FOPROB.js} +17 -0
  26. package/dist/{content-retention-CrILCNxk.d.ts → content-retention-ySTD1wwZ.d.ts} +1 -1
  27. package/dist/{credit-ledger-4PZNAMDT.js → credit-ledger-4CBYLSLY.js} +6 -3
  28. package/dist/{credit-menu-VwX_6KM7.d.ts → credit-menu-BYySnZBk.d.ts} +6 -4
  29. package/dist/{fx-BM5h4o5S.d.ts → fx-DVTNs9q1.d.ts} +1 -1
  30. package/dist/index.d.ts +5 -5
  31. package/dist/index.js +6 -5
  32. package/dist/internal/caller.d.ts +6 -6
  33. package/dist/internal/caller.js +26 -22
  34. package/dist/internal/server.d.ts +7 -7
  35. package/dist/internal/server.js +24 -22
  36. package/dist/{job-store-92v8e1LQ.d.ts → job-store-DRwXCJDI.d.ts} +1 -1
  37. package/dist/{lightning-backend-9oky_wJi.d.ts → lightning-backend-BX5YvjnM.d.ts} +1 -1
  38. package/dist/memory-credit-ledger-DKCN7FY2.js +14 -0
  39. package/dist/{mpp-setup-FURD45LI.js → mpp-setup-JU3MT7QX.js} +3 -3
  40. package/dist/{payout-reporter-HVJ6WUF3.js → payout-reporter-NXWQVKXW.js} +2 -2
  41. package/dist/{postgres-consumed-credential-store-WO6OCFXZ.js → postgres-consumed-credential-store-WXJLM6J7.js} +1 -1
  42. package/dist/{postgres-job-store-FSRUPYH2.js → postgres-job-store-WIIVRZPD.js} +2 -2
  43. package/dist/{postgres-replay-store-XXJSA457.js → postgres-replay-store-QJ4FG6AR.js} +2 -2
  44. package/dist/{pricing-X4XU5HXY.js → pricing-KCLENT2C.js} +3 -3
  45. package/dist/{revenue-reporter-EV3K5L6B.js → revenue-reporter-HD4GMXGD.js} +2 -2
  46. package/dist/server/index.d.ts +29 -12
  47. package/dist/server/index.js +31 -29
  48. package/dist/{step-cache--7yA5Ihr.d.ts → step-cache-d-VKen4K.d.ts} +147 -13
  49. package/dist/{tempo-charge-store-5JOIYUIH.js → tempo-charge-store-7LTUAQHQ.js} +2 -2
  50. package/dist/{tempo-session-store-S6QMLQUA.js → tempo-session-store-LYAIDR2B.js} +3 -3
  51. package/dist/testing/index.d.ts +3 -3
  52. package/dist/testing/index.js +6 -6
  53. package/dist/{usd-C7lvLvLk.d.ts → usd-DSroMJ--.d.ts} +1 -1
  54. package/dist/{x402-EN5LSOVM.js → x402-RUJ4LUKF.js} +3 -3
  55. package/package.json +1 -1
  56. package/recipes/postgres/financial-export-v1.sql +19 -5
  57. package/dist/memory-credit-ledger-RP7DT5IY.js +0 -11
@@ -2,7 +2,7 @@ import {
2
2
  createX402FacilitatorAuthHeaders,
3
3
  settleWithFacilitator,
4
4
  verifyWithFacilitator
5
- } from "./chunk-VTHYQCDB.js";
5
+ } from "./chunk-E7ZBCT5U.js";
6
6
  import {
7
7
  buildPaymentRequirements,
8
8
  decodePayment,
@@ -15,7 +15,7 @@ import {
15
15
  } from "./chunk-66HGCPBU.js";
16
16
  import {
17
17
  diagnosticConsole
18
- } from "./chunk-QGNXYVBO.js";
18
+ } from "./chunk-Z4FOPROB.js";
19
19
 
20
20
  // src/lib/x402/verify.ts
21
21
  async function verifyX402Payment(paymentHeader, config, requiredUsdcMicro, resource, btcUsdRate, exactVersions = { v1: true, v2: true }) {
@@ -10,12 +10,15 @@ import {
10
10
  fifoOrder,
11
11
  growthRailValue,
12
12
  inKindDrawMsats,
13
+ isFundingRail,
13
14
  isInKindDepletion,
14
15
  isNonChannelBitcoinRail,
15
16
  lotOwedSats,
16
17
  netOwedSats,
18
+ refundAssetDelta,
19
+ refundRequest,
17
20
  x402SettlementPending
18
- } from "./chunk-STJBBVNL.js";
21
+ } from "./chunk-K2ZNIQZP.js";
19
22
 
20
23
  // src/sdk/server/memory-credit-ledger.ts
21
24
  import { randomUUID } from "crypto";
@@ -26,7 +29,9 @@ var MemoryCreditLedger = class _MemoryCreditLedger {
26
29
  * machine and drawing on another would `credit_not_found`.
27
30
  */
28
31
  durable = false;
32
+ tempoCreditLossEvidenceVersion = 1;
29
33
  credits = /* @__PURE__ */ new Map();
34
+ refunds = /* @__PURE__ */ new Map();
30
35
  fundings = /* @__PURE__ */ new Map();
31
36
  invoices = /* @__PURE__ */ new Map();
32
37
  tempoLosses = /* @__PURE__ */ new Map();
@@ -35,7 +40,7 @@ var MemoryCreditLedger = class _MemoryCreditLedger {
35
40
  /** Internal disposable transaction snapshot. The caller must serialize every ledger access. */
36
41
  forkForTransaction() {
37
42
  const fork = new _MemoryCreditLedger();
38
- for (const name of ["credits", "fundings", "invoices", "tempoLosses", "x402Losses"]) {
43
+ for (const name of ["credits", "fundings", "invoices", "tempoLosses", "x402Losses", "refunds"]) {
39
44
  const target = fork[name];
40
45
  for (const [key, value] of this[name]) target.set(key, structuredClone(value));
41
46
  }
@@ -54,6 +59,90 @@ var MemoryCreditLedger = class _MemoryCreditLedger {
54
59
  if (wedged) throw x402SettlementPending(args.creditId ?? randomUUID(), wedged);
55
60
  return run(() => this.fundSync(args));
56
61
  }
62
+ /** Development accounting parity; this non-durable store cannot mount admin refunds. */
63
+ refundDraw(args) {
64
+ return run(() => {
65
+ const request = refundRequest(args);
66
+ const prior = this.refunds.get(args.refundId);
67
+ if (prior) {
68
+ if (prior.request !== request) throw new CreditLedgerError("refund_conflict", "This refundId was recorded with different arguments.");
69
+ return { ...prior.result, replayed: true };
70
+ }
71
+ const matches = [...this.credits.values()].flatMap((credit2) => [...credit2.draws.values()].filter((draw2) => args.jobId !== void 0 ? draw2.jobId === args.jobId : credit2.creditId === args.creditId && draw2.drawId === args.drawId).map((draw2) => ({ credit: credit2, draw: draw2 })));
72
+ if (matches.length !== 1 || !matches[0].draw.jobId) {
73
+ throw new CreditLedgerError("draw_not_found", "No unique job-bound draw matches this selector.");
74
+ }
75
+ const { credit, draw } = matches[0];
76
+ if (draw.status !== "settled") throw new CreditLedgerError("draw_not_completed", "Only a settled completed draw can be refunded.");
77
+ const nowMs = args.nowMs ?? Date.now();
78
+ const lastDrain = [...credit.drains.values()].filter((drain) => drain.status !== "released").sort((a, b) => b.ledgerSeq - a.ledgerSeq)[0];
79
+ const drained = lastDrain && lastDrain.balanceAfterMicro === 0 && (credit.lastFundingLedgerSeq === null || credit.lastFundingLedgerSeq < lastDrain.ledgerSeq) && ![...credit.draws.values()].some((later) => later.ledgerSeq > lastDrain.ledgerSeq && later.amountMicro > 0) && ![...this.fundings.values()].some((funding) => funding.creditId === credit.creditId && funding.ledgerSeq !== null && funding.ledgerSeq >= lastDrain.ledgerSeq && funding.amountMicro > 0);
80
+ if (credit.status !== "active" || credit.expiryMs <= nowMs) {
81
+ throw new CreditLedgerError("credit_not_open", "The original credit is no longer open for refunds.");
82
+ }
83
+ if (credit.tempoChannelId || credit.x402ChannelId) {
84
+ throw new CreditLedgerError("credit_refund_channel_unsupported", "Channel collateral cannot back a refund of settled spending.");
85
+ }
86
+ if (credit.balanceMicro === 0 && drained) {
87
+ if (credit.lastFundingLedgerSeq === null) {
88
+ throw new CreditLedgerError("credit_refund_state_unavailable", "The original credit's historical funding and drain order cannot be established.");
89
+ }
90
+ throw new CreditLedgerError("credit_not_open", "The original credit is no longer open for refunds.");
91
+ }
92
+ const before = [...this.refunds.values()].reduce((sum, refund) => sum + (refund.result.creditId === credit.creditId && refund.result.drawId === draw.drawId ? refund.result.amountMicro : 0), 0);
93
+ const amountMicro = args.amountMicro ?? draw.amountMicro - before;
94
+ if (amountMicro <= 0 || amountMicro > draw.amountMicro - before) {
95
+ throw new CreditLedgerError("refund_exceeds_draw", "The refund exceeds the draw's remaining unrefunded charge.");
96
+ }
97
+ if (!isFundingRail(credit.rail)) throw new CreditLedgerError("credit_refund_basis_unavailable", "The original funding rail is not recorded on this older credit.");
98
+ const bitcoin = isNonChannelBitcoinRail(credit.rail);
99
+ const originalSats = draw.settledSats ?? null;
100
+ if (bitcoin && originalSats === null) throw new CreditLedgerError("credit_refund_basis_unavailable", "The original Bitcoin value is not provable from this older draw.");
101
+ const after = before + amountMicro;
102
+ const restoredSats = bitcoin ? refundAssetDelta(originalSats, draw.amountMicro, before, after) : null;
103
+ const restoredMsats = restoredSats === null ? refundAssetDelta(draw.drawMsats, draw.amountMicro, before, after) : restoredSats * 1e3;
104
+ const restoredNative = draw.drawNative === null ? null : refundAssetDelta(draw.drawNative, draw.amountMicro, before, after);
105
+ const balanceAfterMicro = credit.balanceMicro + amountMicro;
106
+ const ledgerSeq = credit.lastLedgerSeq + 1;
107
+ if (![
108
+ balanceAfterMicro,
109
+ ledgerSeq,
110
+ credit.msatsRemaining + restoredMsats,
111
+ (credit.nativeRemaining ?? 0) + (restoredNative ?? 0)
112
+ ].every(Number.isSafeInteger)) {
113
+ throw new Error("credit ledger: refund exceeds safe integer range");
114
+ }
115
+ credit.balanceMicro = balanceAfterMicro;
116
+ credit.lastLedgerSeq = ledgerSeq;
117
+ credit.msatsRemaining += restoredMsats;
118
+ if (credit.nativeRemaining !== null) credit.nativeRemaining += restoredNative ?? 0;
119
+ if (bitcoin) credit.lots.push({
120
+ lotId: `lot:refund:${randomUUID()}`,
121
+ creditId: credit.creditId,
122
+ rail: credit.rail,
123
+ satsFunded: restoredSats,
124
+ satsBasisKnown: true,
125
+ creditedMicro: amountMicro,
126
+ remainingMicro: amountMicro,
127
+ fundingRef: args.refundId,
128
+ createdAt: nowMs
129
+ });
130
+ const result = {
131
+ refundId: args.refundId,
132
+ creditId: credit.creditId,
133
+ drawId: draw.drawId,
134
+ jobId: draw.jobId,
135
+ amountMicro,
136
+ currency: credit.currency,
137
+ ledgerSeq,
138
+ refundedAt: nowMs,
139
+ balanceAfterMicro,
140
+ replayed: false
141
+ };
142
+ this.refunds.set(args.refundId, { request, result });
143
+ return { ...result };
144
+ });
145
+ }
57
146
  async draw(args) {
58
147
  const blocking = await this.blockingRefundForCredit(
59
148
  args.creditId,
@@ -427,6 +516,7 @@ var MemoryCreditLedger = class _MemoryCreditLedger {
427
516
  }
428
517
  );
429
518
  }
519
+ existing.lastFundingLedgerSeq = existing.lastLedgerSeq;
430
520
  existing.balanceMicro += args.amountMicro;
431
521
  existing.expiryMs = args.expiryMs;
432
522
  applyBasis(existing, b);
@@ -457,6 +547,7 @@ var MemoryCreditLedger = class _MemoryCreditLedger {
457
547
  expiryMs: args.expiryMs,
458
548
  status: "active",
459
549
  lastLedgerSeq: 0,
550
+ lastFundingLedgerSeq: 0,
460
551
  createdAt: nowMs,
461
552
  draws: /* @__PURE__ */ new Map(),
462
553
  rail: null,
@@ -687,6 +778,15 @@ var MemoryCreditLedger = class _MemoryCreditLedger {
687
778
  return run(() => {
688
779
  const channelId = evidence.channelId.toLowerCase();
689
780
  const observedAt = evidence.observedAt ?? Date.now();
781
+ const refunded = evidence.refundedToPayerNative ?? 0n;
782
+ if (refunded < 0n) throw new Error("Tempo close refund must be nonnegative");
783
+ const payerExit = evidence.closeKind === "payer_exit";
784
+ if (payerExit && evidence.refundedToPayerNative !== void 0 || evidence.closeKind === "cooperative_close" && evidence.refundedToPayerNative === void 0) {
785
+ throw new Error("Tempo close kind requires matching exact cooperative refund evidence");
786
+ }
787
+ const lossNative = (payerExit ? evidence.consumedNative : evidence.highestVoucherNative) - evidence.settledOnChainNative - (payerExit ? 0n : refunded);
788
+ const lossBasis = payerExit ? "payer_exit" : evidence.refundedToPayerNative === void 0 ? "caller_asserted" : "cooperative_close";
789
+ if (lossNative <= 0n) return [...this.tempoLosses.values()].filter((loss) => loss.channelId === channelId);
690
790
  for (const credit of this.credits.values()) {
691
791
  if (credit.tempoChannelId !== channelId) continue;
692
792
  if (credit.status === "unbacked") continue;
@@ -701,6 +801,9 @@ var MemoryCreditLedger = class _MemoryCreditLedger {
701
801
  highestVoucherNative: evidence.highestVoucherNative,
702
802
  consumedServiceMicro,
703
803
  consumedNative: evidence.consumedNative,
804
+ refundedToPayerNative: evidence.refundedToPayerNative ?? null,
805
+ lossNative,
806
+ lossBasis,
704
807
  observedAt
705
808
  });
706
809
  credit.status = "unbacked";
@@ -708,9 +811,9 @@ var MemoryCreditLedger = class _MemoryCreditLedger {
708
811
  return [...this.tempoLosses.values()].filter((loss) => loss.channelId === channelId);
709
812
  });
710
813
  }
711
- listTempoCreditLosses(args) {
814
+ listTempoCreditLosses(args, _tx) {
712
815
  return Promise.resolve(
713
- [...this.tempoLosses.values()].sort((a, b) => b.observedAt - a.observedAt || a.creditId.localeCompare(b.creditId)).slice(0, args?.limit ?? 50)
816
+ [...this.tempoLosses.values()].filter((loss) => !args?.channelId || loss.channelId === args.channelId.toLowerCase()).sort((a, b) => b.observedAt - a.observedAt || a.creditId.localeCompare(b.creditId)).slice(0, args?.limit ?? 50)
714
817
  );
715
818
  }
716
819
  terminalizeX402Credit(evidence, _tx) {
@@ -841,7 +944,9 @@ var MemoryCreditLedger = class _MemoryCreditLedger {
841
944
  sentAt: null,
842
945
  releasedAt: null,
843
946
  writeOffNote: null,
844
- writtenOffAt: null
947
+ writtenOffAt: null,
948
+ provenRefundNative: null,
949
+ refundPaymentProven: false
845
950
  };
846
951
  applyLotDebits(credit, drain.lotDebits, -1);
847
952
  credit.drains.set(args.drainId, drain);
@@ -874,7 +979,7 @@ var MemoryCreditLedger = class _MemoryCreditLedger {
874
979
  const lots = openLots(credit);
875
980
  const covered = lots.reduce((sum, lot) => sum + lot.remainingMicro, 0);
876
981
  const basisless = lots.reduce(
877
- (sum, lot) => sum + (lot.satsFunded === 0 ? lot.remainingMicro : 0),
982
+ (sum, lot) => sum + (lot.satsFunded === 0 && !lot.satsBasisKnown ? lot.remainingMicro : 0),
878
983
  0
879
984
  );
880
985
  const inKind = covered >= credit.balanceMicro && basisless === 0;
@@ -947,7 +1052,7 @@ var MemoryCreditLedger = class _MemoryCreditLedger {
947
1052
  for (const drain of credit.drains.values()) {
948
1053
  if (drain.status !== "pending" && drain.status !== "exit_required" || drain.method !== "tempo") continue;
949
1054
  if (drain.createdAt > args.createdBeforeMs) continue;
950
- if (!args.includeResolved && drain.writtenOffAt !== null) continue;
1055
+ if (!args.includeResolved && !args.includeWrittenOff && drain.writtenOffAt !== null) continue;
951
1056
  out.push(drainRecord(drain, credit));
952
1057
  }
953
1058
  }
@@ -992,6 +1097,25 @@ var MemoryCreditLedger = class _MemoryCreditLedger {
992
1097
  return { drain: drainRecord(drain, credit), replayed: false };
993
1098
  });
994
1099
  }
1100
+ recordTempoDrainRefund(args) {
1101
+ const amount = String(args.refundedNative);
1102
+ if (!/^\d{1,78}$/.test(amount)) return Promise.reject(new CreditLedgerError("invalid_basis", "Tempo refund evidence must be a bounded non-negative integer."));
1103
+ return this.recordTempoDrainRefundEvidence(args, amount);
1104
+ }
1105
+ recordTempoDrainPayment(args) {
1106
+ return this.recordTempoDrainRefundEvidence(args, null);
1107
+ }
1108
+ recordTempoDrainRefundEvidence(args, amount) {
1109
+ return run(() => {
1110
+ const credit = this.credits.get(args.creditId);
1111
+ const drain = credit?.drains.get(args.drainId);
1112
+ if (!credit?.tempoChannelId || !drain || drain.method !== "tempo" || drain.status !== "pending" && drain.status !== "exit_required") return;
1113
+ if (amount !== null && (drain.provenRefundNative === null || BigInt(amount) > BigInt(drain.provenRefundNative))) {
1114
+ drain.provenRefundNative = amount;
1115
+ }
1116
+ drain.refundPaymentProven ||= amount === null || BigInt(amount) > 0n;
1117
+ });
1118
+ }
995
1119
  releaseDrain(args) {
996
1120
  return run(() => {
997
1121
  const { credit, drain } = this.requireDrain(args.creditId, args.drainId);
@@ -1115,6 +1239,7 @@ var MemoryCreditLedger = class _MemoryCreditLedger {
1115
1239
  if (isNonChannelBitcoinRail(credit.rail)) {
1116
1240
  const depletion = depleteLots(openLots(credit), draw.amountMicro);
1117
1241
  const settledMsats = inKindDrawMsats(depletion, draw.amountMicro);
1242
+ draw.settledSats = settledMsats === null ? null : settledMsats / 1e3;
1118
1243
  if (settledMsats !== null && settledMsats !== draw.drawMsats) {
1119
1244
  draw.allocatedMsats = draw.drawMsats;
1120
1245
  draw.drawMsats = settledMsats;
@@ -1295,7 +1420,9 @@ function drainRecord(drain, credit) {
1295
1420
  sentAt: drain.sentAt,
1296
1421
  releasedAt: drain.releasedAt,
1297
1422
  writeOffNote: drain.writeOffNote,
1298
- writtenOffAt: drain.writtenOffAt
1423
+ writtenOffAt: drain.writtenOffAt,
1424
+ provenRefundNative: drain.provenRefundNative,
1425
+ refundPaymentProven: drain.refundPaymentProven
1299
1426
  };
1300
1427
  }
1301
1428
  function assertAmount(amountMicro, opts) {
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-COYKJRMM.js";
4
4
  import {
5
5
  diagnosticConsole
6
- } from "./chunk-QGNXYVBO.js";
6
+ } from "./chunk-Z4FOPROB.js";
7
7
 
8
8
  // src/sdk/server/revenue-reporter.ts
9
9
  import { randomUUID } from "crypto";
@@ -13,6 +13,7 @@ var ENDPOINTS = {
13
13
  cost: "/_internal/job-cost",
14
14
  deposit: "/_internal/credit-deposit",
15
15
  release: "/_internal/credit-draw-release",
16
+ refund: "/_internal/credit-draw-refund",
16
17
  drain: "/_internal/credit-drain",
17
18
  payout: "/_internal/payout",
18
19
  expiry_release: "/_internal/credit-expiry-release"
@@ -166,6 +167,10 @@ var RevenueReporter = class _RevenueReporter {
166
167
  async enqueueDeposit(tx, payload) {
167
168
  await this.insertPending(tx, "deposit", payload);
168
169
  }
170
+ /** Persist without network delivery before the refund accounting transaction commits. */
171
+ async enqueueCreditDrawRefund(tx, payload) {
172
+ await this.insertPending(tx, "refund", payload);
173
+ }
169
174
  /** Join a released draw to the transaction that made the hold terminal. */
170
175
  async enqueueCreditDrawRelease(tx, payload) {
171
176
  await this.insertPending(tx, "release", payload);
@@ -620,6 +625,9 @@ var RevenueReporter = class _RevenueReporter {
620
625
  diagnosticConsole.log(`[revenue-reporter] reported ${kind} ${label}`);
621
626
  return;
622
627
  }
628
+ if (kind === "refund" && res.status === 409) {
629
+ throw new Error("Original draw revenue has not arrived yet");
630
+ }
623
631
  if (res.status === 401) {
624
632
  await this.markStale(id, "token_rotated");
625
633
  diagnosticConsole.warn(
@@ -0,0 +1,92 @@
1
+ import {
2
+ canonicaliseForSigning
3
+ } from "./chunk-H3GGFEE5.js";
4
+
5
+ // src/lib/receipt.ts
6
+ import { schnorr } from "@noble/curves/secp256k1.js";
7
+ import { sha256 } from "@noble/hashes/sha2.js";
8
+ import { bytesToHex, hexToBytes } from "@noble/hashes/utils.js";
9
+ function computeResultHash(summary, artifactContents) {
10
+ const artifactHashes = artifactContents.map(
11
+ (content) => bytesToHex(sha256(canonicaliseForSigning(content)))
12
+ );
13
+ return bytesToHex(
14
+ sha256(
15
+ canonicaliseForSigning({
16
+ summary: summary ?? null,
17
+ artifact_hashes: artifactHashes
18
+ })
19
+ )
20
+ );
21
+ }
22
+ function signReceipt(unsigned, secretHex) {
23
+ const bytes = canonicaliseForSigning(unsigned);
24
+ const signature = bytesToHex(schnorr.sign(bytes, hexToBytes(secretHex)));
25
+ return { ...unsigned, signature };
26
+ }
27
+ function verifyReceipt(receipt) {
28
+ try {
29
+ const { signature, ...unsigned } = receipt;
30
+ const bytes = canonicaliseForSigning(unsigned);
31
+ return schnorr.verify(hexToBytes(signature), bytes, hexToBytes(receipt.receipt_pubkey));
32
+ } catch {
33
+ return false;
34
+ }
35
+ }
36
+ function isSignedJobReceipt(value) {
37
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
38
+ const r = value;
39
+ const paid = r.paid;
40
+ return r.v === 1 && typeof r.job_id === "string" && typeof r.dvm_id === "string" && typeof r.dvm === "string" && typeof r.capability === "string" && (r.outcome === "completed" || r.outcome === "failed" || r.outcome === "cancelled") && typeof r.seq === "number" && typeof r.issued_at === "number" && typeof r.receipt_pubkey === "string" && typeof r.signature === "string" && !!paid && typeof paid === "object" && !Array.isArray(paid) && typeof paid.msats === "number";
41
+ }
42
+ function signDrainReceipt(unsigned, secretHex) {
43
+ const bytes = canonicaliseForSigning(unsigned);
44
+ const signature = bytesToHex(schnorr.sign(bytes, hexToBytes(secretHex)));
45
+ return { ...unsigned, signature };
46
+ }
47
+ function signFundingReceipt(unsigned, secretHex) {
48
+ const bytes = canonicaliseForSigning(unsigned);
49
+ const signature = bytesToHex(schnorr.sign(bytes, hexToBytes(secretHex)));
50
+ return { ...unsigned, signature };
51
+ }
52
+ function isFundingReceipt(value) {
53
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
54
+ const r = value;
55
+ return r.v === 1 && r.kind === "credit_funding" && typeof r.credit_id === "string" && typeof r.fund_id === "string" && typeof r.funded_micro === "number" && typeof r.balance_after_micro === "number" && typeof r.ledger_seq === "number" && typeof r.issued_at === "number" && typeof r.caller_pubkey === "string" && typeof r.dvm_id === "string" && typeof r.dvm === "string" && typeof r.receipt_pubkey === "string" && typeof r.signature === "string";
56
+ }
57
+ function verifyFundingReceipt(receipt) {
58
+ try {
59
+ const { signature, ...unsigned } = receipt;
60
+ const bytes = canonicaliseForSigning(unsigned);
61
+ return schnorr.verify(hexToBytes(signature), bytes, hexToBytes(receipt.receipt_pubkey));
62
+ } catch {
63
+ return false;
64
+ }
65
+ }
66
+ function isDrainReceipt(value) {
67
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
68
+ const r = value;
69
+ return r.v === 1 && r.kind === "credit_drain" && typeof r.credit_id === "string" && typeof r.drain_id === "string" && (r.event === "requested" || r.event === "parked" || r.event === "picked_up" || r.event === "sent" || r.event === "released") && typeof r.method === "string" && typeof r.amount_micro === "number" && typeof r.issued_at === "number" && typeof r.caller_pubkey === "string" && typeof r.dvm_id === "string" && typeof r.dvm === "string" && typeof r.receipt_pubkey === "string" && typeof r.signature === "string";
70
+ }
71
+ function verifyDrainReceipt(receipt) {
72
+ try {
73
+ const { signature, ...unsigned } = receipt;
74
+ const bytes = canonicaliseForSigning(unsigned);
75
+ return schnorr.verify(hexToBytes(signature), bytes, hexToBytes(receipt.receipt_pubkey));
76
+ } catch {
77
+ return false;
78
+ }
79
+ }
80
+
81
+ export {
82
+ computeResultHash,
83
+ signReceipt,
84
+ verifyReceipt,
85
+ isSignedJobReceipt,
86
+ signDrainReceipt,
87
+ signFundingReceipt,
88
+ isFundingReceipt,
89
+ verifyFundingReceipt,
90
+ isDrainReceipt,
91
+ verifyDrainReceipt
92
+ };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  emitDiagnostic,
3
3
  projectDiagnosticFields
4
- } from "./chunk-QGNXYVBO.js";
4
+ } from "./chunk-Z4FOPROB.js";
5
5
 
6
6
  // src/sdk/logger.ts
7
7
  function createConsoleLogger(_jobId) {