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

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 (70) hide show
  1. package/README.md +2 -0
  2. package/dist/{chunk-S3OY533W.js → chunk-26W6GPCD.js} +48 -6
  3. package/dist/{chunk-FWGWLPXF.js → chunk-2OM2QPBE.js} +2 -2
  4. package/dist/{chunk-CXCQLOOK.js → chunk-62FI3NJF.js} +42 -107
  5. package/dist/{chunk-VHNPVGSA.js → chunk-6STC5TCP.js} +3 -3
  6. package/dist/{chunk-N5RZ5HVB.js → chunk-72V5DTEC.js} +2 -2
  7. package/dist/chunk-A262WVYX.js +6 -0
  8. package/dist/{chunk-GY66THYI.js → chunk-A6CXKAQV.js} +183 -88
  9. package/dist/{chunk-QR2EF2NI.js → chunk-AQ7OX5NX.js} +2 -2
  10. package/dist/{chunk-BYCEKO65.js → chunk-CLIAFTUR.js} +102 -13
  11. package/dist/{chunk-GAOAYHZA.js → chunk-DNG4KGSC.js} +3 -3
  12. package/dist/{chunk-Z4ZT5LNT.js → chunk-GSLS4464.js} +3 -3
  13. package/dist/{chunk-RA2WIX7G.js → chunk-H5FVVEEN.js} +18 -7
  14. package/dist/{chunk-IXR5RFK7.js → chunk-HCE4MPZ5.js} +1 -1
  15. package/dist/{chunk-OML32F6I.js → chunk-I555L2WK.js} +1 -1
  16. package/dist/{chunk-EQLA4FFY.js → chunk-IIZQNDQU.js} +3 -3
  17. package/dist/{chunk-FUJ36YDV.js → chunk-KXWROQGK.js} +24 -1
  18. package/dist/{chunk-ETXDTUJO.js → chunk-LAKP6FUI.js} +55 -0
  19. package/dist/{chunk-X7EZ5CLI.js → chunk-MON76YBJ.js} +3 -3
  20. package/dist/chunk-OFSOLHRX.js +120 -0
  21. package/dist/{chunk-IV6Q7NRW.js → chunk-RAGX6VG7.js} +2 -2
  22. package/dist/{chunk-KA6VN5FK.js → chunk-RXPHMS4C.js} +3 -3
  23. package/dist/{chunk-6XF3RVVX.js → chunk-SPYEJXI7.js} +5 -5
  24. package/dist/{chunk-P6QON7ER.js → chunk-TRNMTTPX.js} +1 -1
  25. package/dist/{chunk-RCM3P2HE.js → chunk-UKD3R2KU.js} +55 -4
  26. package/dist/chunk-USL7ZEXN.js +17 -0
  27. package/dist/{chunk-KMED3H3A.js → chunk-VB5OLOZH.js} +395 -231
  28. package/dist/{content-retention-DHyLdA6b.d.ts → content-retention-CbnouEnh.d.ts} +1 -1
  29. package/dist/{credit-ledger-MCUXYKSJ.js → credit-ledger-7Z7LOCTN.js} +4 -4
  30. package/dist/{credit-menu-DjnkeEUU.d.ts → credit-menu-BO8yJppy.d.ts} +4 -4
  31. package/dist/{fx-zMWFzfrU.d.ts → fx-DSOZQ2z7.d.ts} +1 -1
  32. package/dist/index.d.ts +5 -5
  33. package/dist/index.js +236 -16
  34. package/dist/internal/caller.d.ts +4968 -8286
  35. package/dist/internal/caller.js +4291 -8084
  36. package/dist/internal/index.js +1 -1
  37. package/dist/internal/server.d.ts +7 -7
  38. package/dist/internal/server.js +27 -30
  39. package/dist/{job-store-DdLXBpol.d.ts → job-store-BJRlmq2Q.d.ts} +1 -1
  40. package/dist/{lightning-backend-Bw-qtAbt.d.ts → lightning-backend-f16-fsYK.d.ts} +2 -2
  41. package/dist/{memory-credit-ledger-SBSMGMDX.js → memory-credit-ledger-3WOS74UH.js} +5 -5
  42. package/dist/{mpp-setup-RF5FXGGV.js → mpp-setup-XB4KATMU.js} +2 -2
  43. package/dist/{payout-reporter-3Y2U55ZX.js → payout-reporter-WT7XYW42.js} +2 -2
  44. package/dist/{postgres-consumed-credential-store-BUVCAPLS.js → postgres-consumed-credential-store-W7UP33AH.js} +3 -3
  45. package/dist/{postgres-job-store-VHLQBJZC.js → postgres-job-store-3KGUGFRD.js} +2 -2
  46. package/dist/{postgres-replay-store-ARZSQ45X.js → postgres-replay-store-CVNJJOQG.js} +2 -2
  47. package/dist/{pricing-XT2IAPNE.js → pricing-QAVZUTZR.js} +12 -12
  48. package/dist/{revenue-reporter-MAERPYGK.js → revenue-reporter-7UR3W2SD.js} +2 -2
  49. package/dist/server/index.d.ts +10 -10
  50. package/dist/server/index.js +44 -48
  51. package/dist/{step-cache-2MkvenJn.d.ts → step-cache-CJFiZU3n.d.ts} +1 -1
  52. package/dist/{tempo-charge-store-Q3D7KYMH.js → tempo-charge-store-GA6CED6O.js} +2 -2
  53. package/dist/{tempo-session-store-ZRNCOX7P.js → tempo-session-store-WZWQRITB.js} +3 -3
  54. package/dist/testing/index.d.ts +3 -3
  55. package/dist/testing/index.js +6 -7
  56. package/dist/{usd-DI3d3gTK.d.ts → usd-DmHHg0_4.d.ts} +1 -1
  57. package/dist/{x402-FT4S4JS4.js → x402-ZU4GML7Z.js} +8 -27
  58. package/package.json +1 -1
  59. package/dist/chunk-66HGCPBU.js +0 -25
  60. package/dist/chunk-AT6V3SY7.js +0 -102
  61. package/dist/chunk-EZXAJ6EI.js +0 -1082
  62. package/dist/chunk-HCLVYZUZ.js +0 -244
  63. package/dist/chunk-JEVLNAO3.js +0 -1668
  64. package/dist/chunk-NFMOPYBA.js +0 -357
  65. package/dist/chunk-O2OTZ5GP.js +0 -1869
  66. package/dist/chunk-OFVV37XC.js +0 -57
  67. package/dist/chunk-SZVXOQ75.js +0 -211
  68. package/dist/chunk-WBOKPC37.js +0 -795
  69. package/dist/tempo-lifecycle-GJ77YKVY.js +0 -15
  70. package/dist/tempo-wallet-X2GGAZ6X.js +0 -40
@@ -1,357 +0,0 @@
1
- import {
2
- BTC_RATE_FILE,
3
- ensureConfigSubdir
4
- } from "./chunk-CXCQLOOK.js";
5
- import {
6
- canonicaliseForSigning
7
- } from "./chunk-OFVV37XC.js";
8
- import {
9
- formatFiat
10
- } from "./chunk-AT6V3SY7.js";
11
-
12
- // src/lib/credit-implicit.ts
13
- var IMPLICIT_CREDIT_TTL_MS = 30 * 24 * 60 * 60 * 1e3;
14
-
15
- // src/lib/payment-amounts.ts
16
- function msatsToUsd(msats, rate) {
17
- return msats / 1e11 * rate;
18
- }
19
- function usdToMsats(usd, rate) {
20
- return Math.round(usd / rate * 1e11);
21
- }
22
- function msatsToUsdCents(msats, btcPriceUsd) {
23
- const usd = msatsToUsd(msats, btcPriceUsd);
24
- return Math.round(usd * 100);
25
- }
26
- function msatsToUsdc(msats, btcUsdRate) {
27
- if (!Number.isSafeInteger(msats) || msats < 0) {
28
- throw new RangeError("msats must be a non-negative safe integer");
29
- }
30
- if (!Number.isFinite(btcUsdRate) || btcUsdRate <= 0) {
31
- throw new RangeError("BTC/USD rate must be finite and positive");
32
- }
33
- const [mantissa, exponent = "0"] = btcUsdRate.toString().split("e");
34
- const decimalPlaces = mantissa.split(".")[1]?.length ?? 0;
35
- const shift = Number(exponent) - decimalPlaces;
36
- let numerator = BigInt(msats) * BigInt(mantissa.replace(".", ""));
37
- let denominator = 100000n;
38
- if (shift > 0) numerator *= 10n ** BigInt(shift);
39
- else if (shift < 0) denominator *= 10n ** BigInt(-shift);
40
- const micro = (numerator + denominator - 1n) / denominator;
41
- if (micro > BigInt(Number.MAX_SAFE_INTEGER)) {
42
- throw new RangeError("USDC micro-unit amount exceeds the safe integer range");
43
- }
44
- return Number(micro);
45
- }
46
- function usdcToMsats(usdc, btcUsdRate) {
47
- return usdToMsats(usdc, btcUsdRate);
48
- }
49
- function msatsToMicro(msats, btcRate) {
50
- return Math.round(msatsToUsd(msats, btcRate) * 1e6);
51
- }
52
- function microToSats(micro, btcRate) {
53
- return Math.ceil(usdToMsats(micro / 1e6, btcRate) / 1e3);
54
- }
55
-
56
- // src/lib/fx-coingecko.ts
57
- var COINGECKO_SIMPLE_PRICE_URL = "https://api.coingecko.com/api/v3/simple/price?ids=bitcoin,usd-coin&vs_currencies=usd";
58
- var COINGECKO_BTC_USD_URL = "https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd";
59
- var DEFAULT_TIMEOUT_MS = 5e3;
60
- var DEFAULT_USER_AGENT = "dvmkit-platform/1.0 (+https://dvmkit.com)";
61
- async function fetchCoinGeckoSpot(opts) {
62
- const body = await fetchCoinGeckoBody(opts, COINGECKO_SIMPLE_PRICE_URL);
63
- const btc = body.bitcoin?.usd;
64
- const usdc = body["usd-coin"]?.usd;
65
- if (!isPositiveNumber(btc)) {
66
- throw new Error("coingecko response missing bitcoin.usd");
67
- }
68
- if (!isPositiveNumber(usdc)) {
69
- throw new Error("coingecko response missing usd-coin.usd");
70
- }
71
- return { btc_usd: btc, usdc_usd: usdc, as_of: (/* @__PURE__ */ new Date()).toISOString() };
72
- }
73
- async function fetchCoinGeckoBtcUsd(opts) {
74
- const body = await fetchCoinGeckoBody(opts, COINGECKO_BTC_USD_URL);
75
- const btc = body.bitcoin?.usd;
76
- if (!isPositiveNumber(btc)) {
77
- throw new Error("coingecko response missing bitcoin.usd");
78
- }
79
- return { btc_usd: btc, as_of: (/* @__PURE__ */ new Date()).toISOString() };
80
- }
81
- async function fetchCoinGeckoBody(opts, defaultUrl) {
82
- const url = opts?.url ?? defaultUrl;
83
- const fetchImpl = opts?.fetchImpl ?? fetch;
84
- const timeoutMs = opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
85
- const userAgent = opts?.userAgent ?? DEFAULT_USER_AGENT;
86
- const res = await fetchImpl(url, {
87
- headers: { "User-Agent": userAgent, Accept: "application/json" },
88
- signal: AbortSignal.timeout(timeoutMs)
89
- });
90
- if (!res.ok) {
91
- throw new Error(`coingecko returned HTTP ${res.status.toString()}`);
92
- }
93
- return await res.json();
94
- }
95
- function isPositiveNumber(v) {
96
- return typeof v === "number" && Number.isFinite(v) && v > 0;
97
- }
98
-
99
- // src/lib/currency.ts
100
- import { existsSync, readFileSync, writeFileSync } from "fs";
101
- import { dirname } from "path";
102
- function formatSats(msats) {
103
- if (msats === 0) return "0 sats";
104
- if (msats < 1e3) return `${msats.toLocaleString("en-US")} msats`;
105
- if (msats % 1e3 === 0) return `${(msats / 1e3).toLocaleString("en-US")} sats`;
106
- return `${Math.round(msats / 1e3 * 100) / 100} sats`;
107
- }
108
- function formatAmount(msats, rate, opts) {
109
- const usd = msatsToUsd(msats, rate);
110
- const base = `~$${formatUsd(usd)} (${formatSats(msats)})`;
111
- return opts?.anchor === false ? base : `${base} \u2014 ${costAnchor(usd)}`;
112
- }
113
- function formatPaymentAmount(msats, fiat, opts) {
114
- if (!fiat || fiat.amount <= 0) return formatAmountBestEffort(msats, opts);
115
- const base = `${formatFiat(fiat.amount, fiat.currency)} (${formatSats(msats)})`;
116
- return opts?.anchor === false ? base : `${base} \u2014 ${costAnchor(fiat.amount, fiat.currency)}`;
117
- }
118
- var COST_ANCHOR_BANDS = {
119
- usd: [0.01, 0.1, 1, 10],
120
- eur: [0.01, 0.1, 1, 10],
121
- gbp: [0.01, 0.1, 1, 10],
122
- jpy: [1, 10, 100, 1500]
123
- };
124
- function costAnchor(amount, currency = "usd") {
125
- const bands = COST_ANCHOR_BANDS[currency] ?? COST_ANCHOR_BANDS.usd;
126
- if (amount < bands[0]) return "fraction of a cent";
127
- if (amount <= bands[1]) return "comparable to an API call";
128
- if (amount <= bands[2]) return "comparable to a ChatGPT query";
129
- if (amount <= bands[3]) return "comparable to a coffee";
130
- return "significant purchase \u2014 review carefully";
131
- }
132
- function monetaryJson(msats, rate) {
133
- const usd = msatsToUsd(msats, rate);
134
- return {
135
- msats,
136
- usd: Math.round(usd * 100) / 100,
137
- anchor: costAnchor(usd),
138
- display: formatAmount(msats, rate)
139
- };
140
- }
141
- function formatUsd(usd) {
142
- if (usd === 0) return "0.00";
143
- if (usd >= 0.01) return usd.toFixed(2);
144
- const digits = Math.max(2, -Math.floor(Math.log10(usd)) + 1);
145
- return usd.toFixed(digits);
146
- }
147
- function formatUsdcMicrounits(microunits) {
148
- const value = typeof microunits === "bigint" ? microunits : BigInt(microunits);
149
- const whole = value / 1000000n;
150
- const fraction = (value % 1000000n).toString().padStart(6, "0").replace(/0+$/, "");
151
- return `${whole}.${fraction.padEnd(2, "0") || "00"}`;
152
- }
153
- function parseBudget(budget, rate) {
154
- const value = assertValidBudget(budget);
155
- return budget.startsWith("$") ? usdToMsats(value, rate) : value;
156
- }
157
- function assertValidBudget(budget) {
158
- const value = budget.startsWith("$") ? parseFloat(budget.slice(1)) : parseInt(budget, 10);
159
- if (isNaN(value)) throw new Error(`Invalid budget: ${budget}`);
160
- return value;
161
- }
162
- async function fetchBtcUsdRate() {
163
- if (memRate && Date.now() - memTime < CACHE_TTL) {
164
- return memRate;
165
- }
166
- const disk = readDiskCache();
167
- if (disk) {
168
- memRate = disk;
169
- memTime = Date.now();
170
- return disk;
171
- }
172
- const rate = await fetchFromApi();
173
- memRate = rate;
174
- memTime = Date.now();
175
- writeDiskCache(rate);
176
- return rate;
177
- }
178
- function getLastKnownBtcRate() {
179
- if (memRate && memTime > 0) return { rate: memRate, cachedAt: memTime };
180
- return readDiskCacheStale();
181
- }
182
- function formatStaleness(cachedAt, now = Date.now()) {
183
- const ageMs = Math.max(0, now - cachedAt);
184
- const seconds = Math.floor(ageMs / 1e3);
185
- if (seconds < 60) return `${seconds}s ago`;
186
- const minutes = Math.floor(seconds / 60);
187
- if (minutes < 60) return `${minutes} min ago`;
188
- const hours = Math.floor(minutes / 60);
189
- if (hours < 24) return `${hours} hour${hours === 1 ? "" : "s"} ago`;
190
- const days = Math.floor(hours / 24);
191
- return `${days} day${days === 1 ? "" : "s"} ago`;
192
- }
193
- function formatAmountBestEffort(msats, opts) {
194
- const m = msats ?? 0;
195
- const cached = getLastKnownBtcRate();
196
- if (cached === null) return `${Math.round(m / 1e3)} sats`;
197
- const base = formatAmount(m, cached.rate, opts);
198
- if (Date.now() - cached.cachedAt < CACHE_TTL) return base;
199
- return `${base} (rate cached ${formatStaleness(cached.cachedAt)})`;
200
- }
201
- var CACHE_TTL = 5 * 60 * 1e3;
202
- var CACHE_FILE = BTC_RATE_FILE;
203
- var memRate = null;
204
- var memTime = 0;
205
- function readDiskCache() {
206
- try {
207
- if (!existsSync(CACHE_FILE)) return null;
208
- const data = JSON.parse(readFileSync(CACHE_FILE, "utf-8"));
209
- if (Date.now() - data.timestamp >= CACHE_TTL) return null;
210
- if (!isPlausibleBtcUsdRate(data.rate)) return null;
211
- return data.rate;
212
- } catch {
213
- return null;
214
- }
215
- }
216
- function readDiskCacheStale() {
217
- try {
218
- if (!existsSync(CACHE_FILE)) return null;
219
- const data = JSON.parse(readFileSync(CACHE_FILE, "utf-8"));
220
- if (!isPlausibleBtcUsdRate(data.rate)) return null;
221
- return { rate: data.rate, cachedAt: data.timestamp };
222
- } catch {
223
- return null;
224
- }
225
- }
226
- function writeDiskCache(rate) {
227
- try {
228
- ensureConfigSubdir(dirname(CACHE_FILE));
229
- writeFileSync(CACHE_FILE, JSON.stringify({ rate, timestamp: Date.now() }));
230
- } catch {
231
- }
232
- }
233
- var MAX_PLAUSIBLE_BTC_USD = 1e7;
234
- function isPlausibleBtcUsdRate(rate) {
235
- return typeof rate === "number" && Number.isFinite(rate) && rate > 0 && rate < MAX_PLAUSIBLE_BTC_USD;
236
- }
237
- async function fetchFromApi() {
238
- const spot = await fetchCoinGeckoBtcUsd();
239
- const rate = spot.btc_usd;
240
- if (!isPlausibleBtcUsdRate(rate)) {
241
- throw new Error(`implausible BTC/USD rate from upstream: ${String(rate)}`);
242
- }
243
- return rate;
244
- }
245
-
246
- // src/lib/receipt.ts
247
- import { schnorr } from "@noble/curves/secp256k1.js";
248
- import { sha256 } from "@noble/hashes/sha2.js";
249
- import { bytesToHex, hexToBytes } from "@noble/hashes/utils.js";
250
- function computeResultHash(summary, artifactContents) {
251
- const artifactHashes = artifactContents.map(
252
- (content) => bytesToHex(sha256(canonicaliseForSigning(content)))
253
- );
254
- return bytesToHex(
255
- sha256(
256
- canonicaliseForSigning({
257
- summary: summary ?? null,
258
- artifact_hashes: artifactHashes
259
- })
260
- )
261
- );
262
- }
263
- function signReceipt(unsigned, secretHex) {
264
- const bytes = canonicaliseForSigning(unsigned);
265
- const signature = bytesToHex(schnorr.sign(bytes, hexToBytes(secretHex)));
266
- return { ...unsigned, signature };
267
- }
268
- function verifyReceipt(receipt) {
269
- try {
270
- const { signature, ...unsigned } = receipt;
271
- const bytes = canonicaliseForSigning(unsigned);
272
- return schnorr.verify(hexToBytes(signature), bytes, hexToBytes(receipt.receipt_pubkey));
273
- } catch {
274
- return false;
275
- }
276
- }
277
- function isSignedJobReceipt(value) {
278
- if (!value || typeof value !== "object" || Array.isArray(value)) return false;
279
- const r = value;
280
- const paid = r.paid;
281
- 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";
282
- }
283
- function signDrainReceipt(unsigned, secretHex) {
284
- const bytes = canonicaliseForSigning(unsigned);
285
- const signature = bytesToHex(schnorr.sign(bytes, hexToBytes(secretHex)));
286
- return { ...unsigned, signature };
287
- }
288
- function signFundingReceipt(unsigned, secretHex) {
289
- const bytes = canonicaliseForSigning(unsigned);
290
- const signature = bytesToHex(schnorr.sign(bytes, hexToBytes(secretHex)));
291
- return { ...unsigned, signature };
292
- }
293
- function isFundingReceipt(value) {
294
- if (!value || typeof value !== "object" || Array.isArray(value)) return false;
295
- const r = value;
296
- 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";
297
- }
298
- function verifyFundingReceipt(receipt) {
299
- try {
300
- const { signature, ...unsigned } = receipt;
301
- const bytes = canonicaliseForSigning(unsigned);
302
- return schnorr.verify(hexToBytes(signature), bytes, hexToBytes(receipt.receipt_pubkey));
303
- } catch {
304
- return false;
305
- }
306
- }
307
- function isDrainReceipt(value) {
308
- if (!value || typeof value !== "object" || Array.isArray(value)) return false;
309
- const r = value;
310
- 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";
311
- }
312
- function verifyDrainReceipt(receipt) {
313
- try {
314
- const { signature, ...unsigned } = receipt;
315
- const bytes = canonicaliseForSigning(unsigned);
316
- return schnorr.verify(hexToBytes(signature), bytes, hexToBytes(receipt.receipt_pubkey));
317
- } catch {
318
- return false;
319
- }
320
- }
321
-
322
- export {
323
- IMPLICIT_CREDIT_TTL_MS,
324
- msatsToUsd,
325
- usdToMsats,
326
- msatsToUsdCents,
327
- msatsToUsdc,
328
- usdcToMsats,
329
- msatsToMicro,
330
- microToSats,
331
- COINGECKO_SIMPLE_PRICE_URL,
332
- fetchCoinGeckoSpot,
333
- fetchCoinGeckoBtcUsd,
334
- formatSats,
335
- formatAmount,
336
- formatPaymentAmount,
337
- costAnchor,
338
- monetaryJson,
339
- formatUsd,
340
- formatUsdcMicrounits,
341
- parseBudget,
342
- assertValidBudget,
343
- fetchBtcUsdRate,
344
- getLastKnownBtcRate,
345
- formatStaleness,
346
- formatAmountBestEffort,
347
- computeResultHash,
348
- signReceipt,
349
- verifyReceipt,
350
- isSignedJobReceipt,
351
- signDrainReceipt,
352
- signFundingReceipt,
353
- isFundingReceipt,
354
- verifyFundingReceipt,
355
- isDrainReceipt,
356
- verifyDrainReceipt
357
- };