@dvmkit/sdk 0.12.0 → 0.14.0

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 (27) hide show
  1. package/dist/{chunk-RPUFWIT4.js → chunk-5JSPTVIK.js} +52 -2
  2. package/dist/{chunk-5H7P3ORL.js → chunk-5UC7TOQC.js} +22 -0
  3. package/dist/{chunk-2VGMZ7VF.js → chunk-A2YESDQM.js} +47 -11
  4. package/dist/{chunk-WFCVS6QB.js → chunk-HULU2UVM.js} +1 -1
  5. package/dist/{chunk-S7PIFHE4.js → chunk-JFH34P3M.js} +258 -31
  6. package/dist/{chunk-HW2UCOOC.js → chunk-SXL44PL5.js} +1 -1
  7. package/dist/{chunk-POYUX2NN.js → chunk-TKJBUFYY.js} +11 -3
  8. package/dist/{content-retention-a1yRdmhI.d.ts → content-retention-BcHNpP2F.d.ts} +1 -1
  9. package/dist/{credit-ledger-MF23UKRJ.js → credit-ledger-D3UUR2GW.js} +2 -2
  10. package/dist/{credit-menu-B2T-O9oY.d.ts → credit-menu-C-kmf61K.d.ts} +57 -5
  11. package/dist/{fx-DLhscRUh.d.ts → fx-hFlF4Cn8.d.ts} +1 -1
  12. package/dist/index.d.ts +5 -5
  13. package/dist/index.js +2 -2
  14. package/dist/internal/caller.d.ts +160 -9
  15. package/dist/internal/caller.js +141 -10
  16. package/dist/internal/index.js +1 -1
  17. package/dist/internal/server.d.ts +7 -7
  18. package/dist/internal/server.js +7 -7
  19. package/dist/{job-store-B8Ijr5V6.d.ts → job-store-DVCATwhU.d.ts} +1 -1
  20. package/dist/{lightning-backend-DmwMSgaM.d.ts → lightning-backend-DXNVlVs9.d.ts} +1 -1
  21. package/dist/{memory-credit-ledger-ERD764PS.js → memory-credit-ledger-SCXQO4HZ.js} +3 -3
  22. package/dist/server/index.d.ts +17 -13
  23. package/dist/server/index.js +9 -9
  24. package/dist/{step-cache-DQqpwXa8.d.ts → step-cache-CoORQQ_Y.d.ts} +108 -11
  25. package/dist/testing/index.d.ts +3 -3
  26. package/dist/{usd-D5kk2nIT.d.ts → usd-CeXGiyTC.d.ts} +1 -1
  27. package/package.json +1 -1
@@ -1,11 +1,13 @@
1
1
  import {
2
2
  computeResultHash,
3
3
  isDrainReceipt,
4
+ isDrawFundingReceipt,
4
5
  isFundingReceipt,
5
6
  verifyDrainReceipt,
7
+ verifyDrawFundingReceipt,
6
8
  verifyFundingReceipt,
7
9
  verifyReceipt
8
- } from "./chunk-5H7P3ORL.js";
10
+ } from "./chunk-5UC7TOQC.js";
9
11
  import {
10
12
  DvmError
11
13
  } from "./chunk-BPYMEMQX.js";
@@ -30,7 +32,7 @@ function isX402SettlementReconciliationReason(value) {
30
32
  }
31
33
 
32
34
  // src/lib/credit-implicit.ts
33
- var IMPLICIT_CREDIT_TTL_MS = 30 * 24 * 60 * 60 * 1e3;
35
+ var IMPLICIT_CREDIT_TTL_MS = 90 * 24 * 60 * 60 * 1e3;
34
36
 
35
37
  // src/lib/payment-rails/tempo-wire.ts
36
38
  var TEMPO_SESSION_UPDATED_REASON = "Tempo session updated; attach the next voucher to fund this credit.";
@@ -1699,6 +1701,53 @@ function verifyFundingReceiptChain(args) {
1699
1701
  receipt: named
1700
1702
  };
1701
1703
  }
1704
+ function verifyDrawFundingReceiptChain(args) {
1705
+ const named = isDrawFundingReceipt(args.receipt) ? args.receipt : void 0;
1706
+ const check = (actual, expected) => expected === void 0 ? "unchecked" : actual === expected ? "ok" : "mismatch";
1707
+ const checks = {
1708
+ credit_id: check(named?.credit_id, args.expectedCreditId),
1709
+ job_id: check(named?.job_id, args.expectedJobId),
1710
+ draw_id: check(named?.draw_id, args.expectedDrawId),
1711
+ fund_id: check(named?.fund_id, args.expectedFundId),
1712
+ currency: check(named?.currency, args.expectedCurrency),
1713
+ funded_micro: check(named?.funded_micro, args.expectedFundedMicro),
1714
+ ledger_seq: check(named?.ledger_seq, args.expectedLedgerSeq),
1715
+ caller_pubkey: check(named?.caller_pubkey, args.expectedCallerPubkey),
1716
+ signature: named !== void 0 && verifyDrawFundingReceipt(named),
1717
+ attestation: "absent"
1718
+ };
1719
+ const mismatch = [
1720
+ ["credit_id", "credit_id_mismatch"],
1721
+ ["job_id", "job_id_mismatch"],
1722
+ ["draw_id", "draw_id_mismatch"],
1723
+ ["fund_id", "fund_id_mismatch"],
1724
+ ["currency", "funding_currency_mismatch"],
1725
+ ["funded_micro", "funding_amount_mismatch"],
1726
+ ["ledger_seq", "funding_ledger_seq_mismatch"],
1727
+ ["caller_pubkey", "caller_pubkey_mismatch"]
1728
+ ];
1729
+ for (const [field, reason] of mismatch) {
1730
+ if (checks[field] === "mismatch") return { status: "invalid", checks, reason, receipt: named };
1731
+ }
1732
+ if (!named || !checks.signature) {
1733
+ return { status: "invalid", checks, reason: "signature_invalid", receipt: named };
1734
+ }
1735
+ checks.attestation = checkReceiptAttestation(named, args.builder);
1736
+ if (checks.attestation === "invalid") {
1737
+ return { status: "invalid", checks, reason: "attestation_invalid", receipt: named };
1738
+ }
1739
+ if (checks.attestation === "identity_mismatch") {
1740
+ return { status: "invalid", checks, reason: "dvm_identity_mismatch", receipt: named };
1741
+ }
1742
+ if (checks.attestation === "key_mismatch") {
1743
+ return { status: "invalid", checks, reason: "receipt_key_mismatch", receipt: named };
1744
+ }
1745
+ return {
1746
+ status: checks.attestation === "ok" ? "verified" : "verified_unattested",
1747
+ checks,
1748
+ receipt: named
1749
+ };
1750
+ }
1702
1751
  function weakestReceiptVerdict(statuses) {
1703
1752
  if (statuses.length === 0) return "absent";
1704
1753
  if (statuses.includes("invalid")) return "invalid";
@@ -1862,6 +1911,7 @@ export {
1862
1911
  checkReceiptAttestation,
1863
1912
  verifyDrainReceiptChain,
1864
1913
  verifyFundingReceiptChain,
1914
+ verifyDrawFundingReceiptChain,
1865
1915
  weakestReceiptVerdict,
1866
1916
  isPublicRequestId,
1867
1917
  parseTraceparent,
@@ -63,6 +63,25 @@ function verifyFundingReceipt(receipt) {
63
63
  return false;
64
64
  }
65
65
  }
66
+ function signDrawFundingReceipt(unsigned, secretHex) {
67
+ const bytes = canonicaliseForSigning(unsigned);
68
+ const signature = bytesToHex(schnorr.sign(bytes, hexToBytes(secretHex)));
69
+ return { ...unsigned, signature };
70
+ }
71
+ function isDrawFundingReceipt(value) {
72
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
73
+ const r = value;
74
+ return r.v === 1 && r.kind === "credit_draw_funding" && typeof r.credit_id === "string" && typeof r.job_id === "string" && typeof r.draw_id === "string" && typeof r.fund_id === "string" && (r.payment_seq === void 0 || typeof r.payment_seq === "number") && typeof r.currency === "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";
75
+ }
76
+ function verifyDrawFundingReceipt(receipt) {
77
+ try {
78
+ const { signature, ...unsigned } = receipt;
79
+ const bytes = canonicaliseForSigning(unsigned);
80
+ return schnorr.verify(hexToBytes(signature), bytes, hexToBytes(receipt.receipt_pubkey));
81
+ } catch {
82
+ return false;
83
+ }
84
+ }
66
85
  function isDrainReceipt(value) {
67
86
  if (!value || typeof value !== "object" || Array.isArray(value)) return false;
68
87
  const r = value;
@@ -87,6 +106,9 @@ export {
87
106
  signFundingReceipt,
88
107
  isFundingReceipt,
89
108
  verifyFundingReceipt,
109
+ signDrawFundingReceipt,
110
+ isDrawFundingReceipt,
111
+ verifyDrawFundingReceipt,
90
112
  isDrainReceipt,
91
113
  verifyDrainReceipt
92
114
  };
@@ -7,7 +7,7 @@ import {
7
7
  import {
8
8
  isSignedJobReceipt,
9
9
  verifyReceipt
10
- } from "./chunk-5H7P3ORL.js";
10
+ } from "./chunk-5UC7TOQC.js";
11
11
  import {
12
12
  applyRetryToPool
13
13
  } from "./chunk-EP7OVWI5.js";
@@ -1345,7 +1345,11 @@ var CreditLedger = class {
1345
1345
  "caller_pubkey TEXT",
1346
1346
  "balance_after_micro BIGINT",
1347
1347
  "ledger_seq BIGINT",
1348
- "receipt JSONB"
1348
+ "receipt JSONB",
1349
+ // Mid-job draw funding bindings; null on opening and `/v1/credit` fundings.
1350
+ "job_id TEXT",
1351
+ "draw_id TEXT",
1352
+ "payment_seq BIGINT"
1349
1353
  ]) {
1350
1354
  await this.pool.query(`ALTER TABLE credit_fundings ADD COLUMN IF NOT EXISTS ${column}`);
1351
1355
  }
@@ -1546,8 +1550,8 @@ var CreditLedger = class {
1546
1550
  );
1547
1551
  }
1548
1552
  /**
1549
- * Funding adds balance and overwrites expiry, reviving an expired credit. It is additive,
1550
- * not idempotent: the caller’s rail marker or funding record must prevent replay. Owner and
1553
+ * Funding adds balance and extends expiry without shortening it, reviving an expired credit.
1554
+ * It is additive, not idempotent: the caller’s rail marker or funding record must prevent replay. Owner and
1551
1555
  * currency must match; rail and reusable-channel bindings cannot be mixed with other
1552
1556
  * instruments. A legacy NULL rail adopts its first typed top-up.
1553
1557
  *
@@ -1616,7 +1620,7 @@ var CreditLedger = class {
1616
1620
  ON CONFLICT (credit_id) DO UPDATE
1617
1621
  SET balance_micro = credits.balance_micro + EXCLUDED.balance_micro,
1618
1622
  last_funding_ledger_seq = credits.last_ledger_seq,
1619
- expiry_ms = EXCLUDED.expiry_ms,
1623
+ expiry_ms = GREATEST(credits.expiry_ms, EXCLUDED.expiry_ms),
1620
1624
  rail = COALESCE(credits.rail, EXCLUDED.rail),
1621
1625
  native_asset = COALESCE(EXCLUDED.native_asset, credits.native_asset),
1622
1626
  mint = COALESCE(EXCLUDED.mint, credits.mint),
@@ -2467,11 +2471,21 @@ var CreditLedger = class {
2467
2471
  });
2468
2472
  const nowMs = args.nowMs ?? Date.now();
2469
2473
  const { rows } = await q.query(
2470
- `INSERT INTO credit_fundings (credit_id, fund_id, amount_micro, rail, created_at)
2471
- VALUES ($1, $2, $3, $4, $5)
2474
+ `INSERT INTO credit_fundings
2475
+ (credit_id, fund_id, amount_micro, rail, created_at, job_id, draw_id, payment_seq)
2476
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
2472
2477
  ON CONFLICT (credit_id, fund_id) DO NOTHING
2473
2478
  RETURNING *`,
2474
- [args.creditId, args.fundId, args.amountMicro, args.rail ?? null, nowMs]
2479
+ [
2480
+ args.creditId,
2481
+ args.fundId,
2482
+ args.amountMicro,
2483
+ args.rail ?? null,
2484
+ nowMs,
2485
+ args.jobId ?? null,
2486
+ args.drawId ?? null,
2487
+ args.paymentSeq ?? null
2488
+ ]
2475
2489
  );
2476
2490
  if (rows.length === 0) {
2477
2491
  throw new CreditLedgerError(
@@ -2494,6 +2508,19 @@ var CreditLedger = class {
2494
2508
  );
2495
2509
  return rows.length > 0 ? fundingRecordFromRow(rows[0]) : void 0;
2496
2510
  }
2511
+ /**
2512
+ * Every funding accepted against one job's draw, oldest first. The order is
2513
+ * stable across reads so a job read lists the same evidence each time.
2514
+ */
2515
+ async listDrawFundings(args) {
2516
+ const { rows } = await this.pool.query(
2517
+ `SELECT * FROM credit_fundings
2518
+ WHERE credit_id = $1 AND draw_id = $2
2519
+ ORDER BY created_at ASC, fund_id ASC`,
2520
+ [args.creditId, args.drawId]
2521
+ );
2522
+ return rows.map(fundingRecordFromRow);
2523
+ }
2497
2524
  /** Fix the funding-time receipt tuple inside the rail's open transaction. */
2498
2525
  async completeFunding(args) {
2499
2526
  const q = args.tx ?? this.pool;
@@ -2693,7 +2720,10 @@ var CreditLedger = class {
2693
2720
  [args.creditId, args.fundId, settledAt]
2694
2721
  );
2695
2722
  if (args.depositOutbox) {
2696
- await args.depositOutbox.enqueue(client, args.depositOutbox.payload);
2723
+ await args.depositOutbox.enqueue(client, {
2724
+ ...args.depositOutbox.payload,
2725
+ expiryMs: credit.expiryMs
2726
+ });
2697
2727
  }
2698
2728
  await client.query("COMMIT");
2699
2729
  return {
@@ -2864,7 +2894,10 @@ var CreditLedger = class {
2864
2894
  ]
2865
2895
  );
2866
2896
  if (args.depositOutbox) {
2867
- await args.depositOutbox.enqueue(client, args.depositOutbox.payload);
2897
+ await args.depositOutbox.enqueue(client, {
2898
+ ...args.depositOutbox.payload,
2899
+ expiryMs: credit.expiryMs
2900
+ });
2868
2901
  }
2869
2902
  await client.query("COMMIT");
2870
2903
  return {
@@ -4330,7 +4363,10 @@ function fundingRecordFromRow(row) {
4330
4363
  callerPubkey: row.caller_pubkey,
4331
4364
  balanceAfterMicro: row.balance_after_micro === null ? null : toSafeInt(row.balance_after_micro),
4332
4365
  ledgerSeq: row.ledger_seq === null ? null : toSafeInt(row.ledger_seq),
4333
- receipt: row.receipt
4366
+ receipt: row.receipt,
4367
+ jobId: row.job_id ?? null,
4368
+ drawId: row.draw_id ?? null,
4369
+ paymentSeq: row.payment_seq === null || row.payment_seq === void 0 ? null : toSafeInt(row.payment_seq)
4334
4370
  };
4335
4371
  }
4336
4372
  function invoiceRecordFromRow(row) {
@@ -4,7 +4,7 @@ import {
4
4
  signedRequestHeaderMatchesDomain,
5
5
  signedRequestStatementHeader,
6
6
  testOnlySignedRequestDomain
7
- } from "./chunk-HW2UCOOC.js";
7
+ } from "./chunk-SXL44PL5.js";
8
8
  import {
9
9
  diagnosticConsole
10
10
  } from "./chunk-Z4FOPROB.js";