@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.
- package/README.md +100 -0
- package/dist/{chunk-JH3SX3LY.js → chunk-6XF3RVVX.js} +1 -1
- package/dist/chunk-AFV77S4C.js +258 -0
- package/dist/{chunk-RLTSCKRI.js → chunk-BPYMEMQX.js} +50 -3
- package/dist/chunk-BQJIFRAZ.js +36 -0
- package/dist/{chunk-IWQHUSMO.js → chunk-CXCQLOOK.js} +143 -2
- package/dist/{chunk-PB4FYZET.js → chunk-EQLA4FFY.js} +54 -4
- package/dist/{chunk-LE74UEV7.js → chunk-EZXAJ6EI.js} +64 -53
- package/dist/{chunk-FI4CST2D.js → chunk-FWGWLPXF.js} +4 -6
- package/dist/{chunk-EYTHFFFU.js → chunk-GY66THYI.js} +179 -56
- package/dist/{chunk-TZ2WKCDD.js → chunk-HCLVYZUZ.js} +2 -2
- package/dist/{chunk-O5AT6S5T.js → chunk-IV6Q7NRW.js} +25 -195
- package/dist/{chunk-UOCZXO2Z.js → chunk-JEVLNAO3.js} +10 -5
- package/dist/{chunk-TUA7PYH7.js → chunk-KMED3H3A.js} +134 -130
- package/dist/{chunk-Z4KLECAC.js → chunk-N5RZ5HVB.js} +1 -1
- package/dist/{chunk-PAIM66YA.js → chunk-NFMOPYBA.js} +47 -37
- package/dist/{chunk-B2IROPQF.js → chunk-O2OTZ5GP.js} +40 -15
- package/dist/{chunk-FYRR2UEZ.js → chunk-OML32F6I.js} +1 -1
- package/dist/{chunk-6DOGTAHA.js → chunk-QR2EF2NI.js} +9 -43
- package/dist/{chunk-7ZUKL4IV.js → chunk-RA2WIX7G.js} +5 -5
- package/dist/{chunk-A4YFWZ7R.js → chunk-RCM3P2HE.js} +1 -1
- package/dist/{chunk-PLG4XER6.js → chunk-S3OY533W.js} +1 -1
- package/dist/{chunk-GFY5FRX3.js → chunk-SZVXOQ75.js} +5 -12
- package/dist/{chunk-MZRJR2CW.js → chunk-WBOKPC37.js} +22 -3
- package/dist/content-retention-DHyLdA6b.d.ts +78 -0
- package/dist/{credit-ledger-MI2H7NEC.js → credit-ledger-MCUXYKSJ.js} +2 -3
- package/dist/{credit-menu-CAfqe8IY.d.ts → credit-menu-DjnkeEUU.d.ts} +98 -5
- package/dist/{fx-D9nsN3n4.d.ts → fx-zMWFzfrU.d.ts} +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +3 -3
- package/dist/internal/caller.d.ts +1369 -860
- package/dist/internal/caller.js +1079 -991
- package/dist/internal/index.js +1 -1
- package/dist/internal/server.d.ts +8 -99
- package/dist/internal/server.js +19 -18
- package/dist/{job-store-Bx-VFRjg.d.ts → job-store-DdLXBpol.d.ts} +1 -1
- package/dist/{lightning-backend-BAx2Y8pP.d.ts → lightning-backend-Bw-qtAbt.d.ts} +4 -2
- package/dist/{memory-credit-ledger-W2BAUYJP.js → memory-credit-ledger-SBSMGMDX.js} +3 -4
- package/dist/{postgres-consumed-credential-store-CUQJKRSL.js → postgres-consumed-credential-store-BUVCAPLS.js} +13 -0
- package/dist/{postgres-job-store-VLXLWXUQ.js → postgres-job-store-VHLQBJZC.js} +3 -1
- package/dist/server/index.d.ts +28 -10
- package/dist/server/index.js +34 -24
- package/dist/{step-cache-QG_h5-3G.d.ts → step-cache-2MkvenJn.d.ts} +3 -3
- package/dist/tempo-lifecycle-GJ77YKVY.js +15 -0
- package/dist/{tempo-wallet-B5XXV3YH.js → tempo-wallet-X2GGAZ6X.js} +4 -4
- package/dist/testing/index.d.ts +9 -2
- package/dist/testing/index.js +6 -3
- package/dist/{usd-EwRqCPF-.d.ts → usd-DI3d3gTK.d.ts} +1 -1
- package/dist/{x402-R6HPBY5D.js → x402-FT4S4JS4.js} +8 -10
- package/package.json +5 -3
- package/recipes/postgres/financial-export-v1.sql +137 -0
- package/dist/chunk-CZULM42S.js +0 -143
- package/dist/chunk-LIRAHP7B.js +0 -53
- package/dist/tempo-lifecycle-ZBBLFBMH.js +0 -15
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
verifyDrainReceipt,
|
|
9
9
|
verifyFundingReceipt,
|
|
10
10
|
verifyReceipt
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-NFMOPYBA.js";
|
|
12
12
|
import {
|
|
13
13
|
AGENT_MNEMONIC_FILE,
|
|
14
14
|
BUILDER_CONFIG_DIR,
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
BUILDER_KEY_FILE,
|
|
17
17
|
WALLET_FILE,
|
|
18
18
|
ensureConfigDir
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-CXCQLOOK.js";
|
|
20
20
|
import {
|
|
21
21
|
canonicaliseForSigning
|
|
22
22
|
} from "./chunk-OFVV37XC.js";
|
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
} from "./chunk-66HGCPBU.js";
|
|
26
26
|
import {
|
|
27
27
|
DvmError
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-BPYMEMQX.js";
|
|
29
29
|
import {
|
|
30
30
|
diagnosticConsole
|
|
31
31
|
} from "./chunk-ETXDTUJO.js";
|
|
@@ -40,6 +40,9 @@ function isX402SettlementReconciliationReason(value) {
|
|
|
40
40
|
return value === "settlement_not_on_chain" || value === "chain_unreachable" || value === "settlement_unbookmarked" || value === "facilitator_channel_state_unavailable";
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
// src/lib/payment-rails/tempo-wire.ts
|
|
44
|
+
var TEMPO_SESSION_UPDATED_REASON = "Tempo session updated; attach the next voucher to fund this credit.";
|
|
45
|
+
|
|
43
46
|
// src/lib/mints.ts
|
|
44
47
|
var RECOMMENDED_MINTS = [
|
|
45
48
|
{
|
|
@@ -204,6 +207,9 @@ var DEFAULT_LOCK_RETRY_INTERVAL_MS = 1e3;
|
|
|
204
207
|
var WALLET_VERSION = 9;
|
|
205
208
|
var RECENT_SPENDS_CAP = 10;
|
|
206
209
|
var DEFAULT_AGENT_MINT_URL = "https://mint.coinos.io";
|
|
210
|
+
function loadWalletConfiguredMints() {
|
|
211
|
+
return loadAgentWallet()?.mints ?? [];
|
|
212
|
+
}
|
|
207
213
|
function loadAgentWallet() {
|
|
208
214
|
if (!existsSync3(WALLET_FILE)) return null;
|
|
209
215
|
const raw = readFileSync3(WALLET_FILE, "utf-8");
|
|
@@ -953,6 +959,112 @@ function generateEphemeralReceiptKey() {
|
|
|
953
959
|
return { secret: bytesToHex(secretKey), pubkey: bytesToHex(publicKey) };
|
|
954
960
|
}
|
|
955
961
|
|
|
962
|
+
// src/lib/wallet-agent/keypair.ts
|
|
963
|
+
import { secp256k1 as secp256k12 } from "@noble/curves/secp256k1.js";
|
|
964
|
+
var PRIVKEY_HEX_RE = /^[0-9a-f]{64}$/i;
|
|
965
|
+
function derivePubkeyFromPrivkey(privkey) {
|
|
966
|
+
if (!PRIVKEY_HEX_RE.test(privkey)) {
|
|
967
|
+
throw new DvmError(
|
|
968
|
+
"invalid_privkey",
|
|
969
|
+
"Privkey must be 64 hex characters (32 bytes).",
|
|
970
|
+
"Provide a valid secp256k1 private key as a 64-char hex string."
|
|
971
|
+
);
|
|
972
|
+
}
|
|
973
|
+
const bytes = hexToBytes2(privkey);
|
|
974
|
+
if (!secp256k12.utils.isValidSecretKey(bytes)) {
|
|
975
|
+
throw new DvmError(
|
|
976
|
+
"invalid_privkey",
|
|
977
|
+
"Privkey is not a valid secp256k1 scalar (zero or out of curve order).",
|
|
978
|
+
"Generate a fresh key with: dvm wallet init"
|
|
979
|
+
);
|
|
980
|
+
}
|
|
981
|
+
const pub = secp256k12.getPublicKey(bytes);
|
|
982
|
+
return bytesToHex2(pub);
|
|
983
|
+
}
|
|
984
|
+
function bytesToHex2(bytes) {
|
|
985
|
+
return Buffer.from(bytes).toString("hex");
|
|
986
|
+
}
|
|
987
|
+
function hexToBytes2(hex) {
|
|
988
|
+
return Uint8Array.from(Buffer.from(hex, "hex"));
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
// src/lib/wallet-agent/sign.ts
|
|
992
|
+
import { schnorr as schnorr2 } from "@noble/curves/secp256k1.js";
|
|
993
|
+
var PUBKEY_COMPRESSED_HEX_RE = /^0[23][0-9a-f]{64}$/i;
|
|
994
|
+
var PUBKEY_XONLY_HEX_RE = /^[0-9a-f]{64}$/i;
|
|
995
|
+
var SIG_HEX_RE = /^[0-9a-f]{128}$/i;
|
|
996
|
+
function signChallenge(privkeyHex, challenge) {
|
|
997
|
+
if (!PRIVKEY_HEX_RE.test(privkeyHex)) {
|
|
998
|
+
throw new DvmError(
|
|
999
|
+
"invalid_privkey",
|
|
1000
|
+
"Privkey must be 64 hex characters (32 bytes).",
|
|
1001
|
+
"Provide a valid secp256k1 private key as a 64-char hex string."
|
|
1002
|
+
);
|
|
1003
|
+
}
|
|
1004
|
+
if (challenge.length !== 32) {
|
|
1005
|
+
throw new DvmError(
|
|
1006
|
+
"invalid_challenge",
|
|
1007
|
+
`Challenge must be exactly 32 bytes; got ${challenge.length}.`,
|
|
1008
|
+
"Pass the SHA-256 digest output (32 bytes)."
|
|
1009
|
+
);
|
|
1010
|
+
}
|
|
1011
|
+
const sig = schnorr2.sign(challenge, hexToBytes3(privkeyHex));
|
|
1012
|
+
return bytesToHex3(sig);
|
|
1013
|
+
}
|
|
1014
|
+
function verifyChallenge(pubkeyHex, challenge, sigHex) {
|
|
1015
|
+
if (!SIG_HEX_RE.test(sigHex)) return false;
|
|
1016
|
+
if (challenge.length !== 32) return false;
|
|
1017
|
+
let xonly;
|
|
1018
|
+
if (PUBKEY_COMPRESSED_HEX_RE.test(pubkeyHex)) {
|
|
1019
|
+
xonly = hexToBytes3(pubkeyHex.slice(2));
|
|
1020
|
+
} else if (PUBKEY_XONLY_HEX_RE.test(pubkeyHex)) {
|
|
1021
|
+
xonly = hexToBytes3(pubkeyHex);
|
|
1022
|
+
} else {
|
|
1023
|
+
return false;
|
|
1024
|
+
}
|
|
1025
|
+
try {
|
|
1026
|
+
return schnorr2.verify(hexToBytes3(sigHex), challenge, xonly);
|
|
1027
|
+
} catch {
|
|
1028
|
+
return false;
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
function hexToBytes3(hex) {
|
|
1032
|
+
return Uint8Array.from(Buffer.from(hex, "hex"));
|
|
1033
|
+
}
|
|
1034
|
+
function bytesToHex3(bytes) {
|
|
1035
|
+
return Buffer.from(bytes).toString("hex");
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
// src/lib/cashu/admin-auth.ts
|
|
1039
|
+
import { randomBytes } from "crypto";
|
|
1040
|
+
import { sha256 as sha2562 } from "@noble/hashes/sha2.js";
|
|
1041
|
+
var ADMIN_AUTH_NONCE_TTL_SECONDS = 300;
|
|
1042
|
+
var ADMIN_AUTH_CLOCK_SKEW_SECONDS = 30;
|
|
1043
|
+
var ADMIN_STATE_UNAVAILABLE = "admin_state_unavailable";
|
|
1044
|
+
function buildAdminChallenge(args) {
|
|
1045
|
+
const msg = `dvmkit-admin:${args.method}:${args.path}:${args.dvmId}:${args.nonceHex}:${args.unixSeconds}`;
|
|
1046
|
+
return sha2562(new TextEncoder().encode(msg));
|
|
1047
|
+
}
|
|
1048
|
+
function buildAdminAuthHeader(args) {
|
|
1049
|
+
const nowMs = args.now ? args.now() : Date.now();
|
|
1050
|
+
const unixSeconds = Math.floor(nowMs / 1e3);
|
|
1051
|
+
const nonceBytes = args.randomNonce ? args.randomNonce() : Uint8Array.from(randomBytes(16));
|
|
1052
|
+
const nonceHex = Buffer.from(nonceBytes).toString("hex");
|
|
1053
|
+
const challenge = buildAdminChallenge({
|
|
1054
|
+
method: args.method,
|
|
1055
|
+
path: args.path,
|
|
1056
|
+
dvmId: args.dvmId,
|
|
1057
|
+
nonceHex,
|
|
1058
|
+
unixSeconds
|
|
1059
|
+
});
|
|
1060
|
+
const sigHex = signChallenge(args.privkeyHex, challenge);
|
|
1061
|
+
return {
|
|
1062
|
+
header: `P2PK ${nonceHex}.${unixSeconds}.${sigHex}`,
|
|
1063
|
+
nonceHex,
|
|
1064
|
+
unixSeconds
|
|
1065
|
+
};
|
|
1066
|
+
}
|
|
1067
|
+
|
|
956
1068
|
// src/lib/builder-identity.ts
|
|
957
1069
|
import {
|
|
958
1070
|
chmodSync as chmodSync3,
|
|
@@ -964,8 +1076,8 @@ import {
|
|
|
964
1076
|
unlinkSync as unlinkSync4,
|
|
965
1077
|
writeFileSync as writeFileSync5
|
|
966
1078
|
} from "fs";
|
|
967
|
-
import { schnorr as
|
|
968
|
-
import { sha256 as
|
|
1079
|
+
import { schnorr as schnorr3 } from "@noble/curves/secp256k1.js";
|
|
1080
|
+
import { sha256 as sha2563 } from "@noble/hashes/sha2.js";
|
|
969
1081
|
|
|
970
1082
|
// src/lib/builder-store.ts
|
|
971
1083
|
import {
|
|
@@ -1070,8 +1182,8 @@ function migrateV1Store(parsed) {
|
|
|
1070
1182
|
|
|
1071
1183
|
// src/lib/builder-identity.ts
|
|
1072
1184
|
function generateIdentity() {
|
|
1073
|
-
const { secretKey, publicKey } =
|
|
1074
|
-
return { pubkey:
|
|
1185
|
+
const { secretKey, publicKey } = schnorr3.keygen();
|
|
1186
|
+
return { pubkey: bytesToHex4(publicKey), secret: bytesToHex4(secretKey) };
|
|
1075
1187
|
}
|
|
1076
1188
|
function loadIdentitySecret() {
|
|
1077
1189
|
if (!existsSync5(BUILDER_KEY_FILE)) return null;
|
|
@@ -1114,7 +1226,7 @@ function writeIdentity(keypair, opts = {}) {
|
|
|
1114
1226
|
setIdentityPubkey(keypair.pubkey);
|
|
1115
1227
|
}
|
|
1116
1228
|
function hashCapabilities(capabilities) {
|
|
1117
|
-
return
|
|
1229
|
+
return bytesToHex4(sha2563(canonicaliseForSigning(capabilities)));
|
|
1118
1230
|
}
|
|
1119
1231
|
function buildAttestation(args) {
|
|
1120
1232
|
return {
|
|
@@ -1127,14 +1239,14 @@ function buildAttestation(args) {
|
|
|
1127
1239
|
};
|
|
1128
1240
|
}
|
|
1129
1241
|
function signAttestation(payload, secretHex) {
|
|
1130
|
-
const secretBytes =
|
|
1242
|
+
const secretBytes = hexToBytes4(secretHex);
|
|
1131
1243
|
const canonicalBytes = canonicaliseForSigning(payload);
|
|
1132
|
-
return
|
|
1244
|
+
return bytesToHex4(schnorr3.sign(canonicalBytes, secretBytes));
|
|
1133
1245
|
}
|
|
1134
1246
|
function verifyAttestation(payload, signatureHex, pubkeyHex) {
|
|
1135
1247
|
try {
|
|
1136
1248
|
const canonicalBytes = canonicaliseForSigning(payload);
|
|
1137
|
-
return
|
|
1249
|
+
return schnorr3.verify(hexToBytes4(signatureHex), canonicalBytes, hexToBytes4(pubkeyHex));
|
|
1138
1250
|
} catch {
|
|
1139
1251
|
return false;
|
|
1140
1252
|
}
|
|
@@ -1157,12 +1269,12 @@ function warnAndTightenLooseKeyMode() {
|
|
|
1157
1269
|
} catch {
|
|
1158
1270
|
}
|
|
1159
1271
|
}
|
|
1160
|
-
function
|
|
1272
|
+
function bytesToHex4(bytes) {
|
|
1161
1273
|
let s = "";
|
|
1162
1274
|
for (const b of bytes) s += b.toString(16).padStart(2, "0");
|
|
1163
1275
|
return s;
|
|
1164
1276
|
}
|
|
1165
|
-
function
|
|
1277
|
+
function hexToBytes4(hex) {
|
|
1166
1278
|
if (hex.length % 2 !== 0) {
|
|
1167
1279
|
throw new Error(`hex string has odd length: ${String(hex.length)}`);
|
|
1168
1280
|
}
|
|
@@ -1462,112 +1574,6 @@ function parseTraceparent(header) {
|
|
|
1462
1574
|
return { traceId, parentSpanId, flags: parseInt(flagsHex, 16) };
|
|
1463
1575
|
}
|
|
1464
1576
|
|
|
1465
|
-
// src/lib/wallet-agent/keypair.ts
|
|
1466
|
-
import { secp256k1 as secp256k12 } from "@noble/curves/secp256k1.js";
|
|
1467
|
-
var PRIVKEY_HEX_RE = /^[0-9a-f]{64}$/i;
|
|
1468
|
-
function derivePubkeyFromPrivkey(privkey) {
|
|
1469
|
-
if (!PRIVKEY_HEX_RE.test(privkey)) {
|
|
1470
|
-
throw new DvmError(
|
|
1471
|
-
"invalid_privkey",
|
|
1472
|
-
"Privkey must be 64 hex characters (32 bytes).",
|
|
1473
|
-
"Provide a valid secp256k1 private key as a 64-char hex string."
|
|
1474
|
-
);
|
|
1475
|
-
}
|
|
1476
|
-
const bytes = hexToBytes3(privkey);
|
|
1477
|
-
if (!secp256k12.utils.isValidSecretKey(bytes)) {
|
|
1478
|
-
throw new DvmError(
|
|
1479
|
-
"invalid_privkey",
|
|
1480
|
-
"Privkey is not a valid secp256k1 scalar (zero or out of curve order).",
|
|
1481
|
-
"Generate a fresh key with: dvm wallet init"
|
|
1482
|
-
);
|
|
1483
|
-
}
|
|
1484
|
-
const pub = secp256k12.getPublicKey(bytes);
|
|
1485
|
-
return bytesToHex3(pub);
|
|
1486
|
-
}
|
|
1487
|
-
function bytesToHex3(bytes) {
|
|
1488
|
-
return Buffer.from(bytes).toString("hex");
|
|
1489
|
-
}
|
|
1490
|
-
function hexToBytes3(hex) {
|
|
1491
|
-
return Uint8Array.from(Buffer.from(hex, "hex"));
|
|
1492
|
-
}
|
|
1493
|
-
|
|
1494
|
-
// src/lib/wallet-agent/sign.ts
|
|
1495
|
-
import { schnorr as schnorr3 } from "@noble/curves/secp256k1.js";
|
|
1496
|
-
var PUBKEY_COMPRESSED_HEX_RE = /^0[23][0-9a-f]{64}$/i;
|
|
1497
|
-
var PUBKEY_XONLY_HEX_RE = /^[0-9a-f]{64}$/i;
|
|
1498
|
-
var SIG_HEX_RE = /^[0-9a-f]{128}$/i;
|
|
1499
|
-
function signChallenge(privkeyHex, challenge) {
|
|
1500
|
-
if (!PRIVKEY_HEX_RE.test(privkeyHex)) {
|
|
1501
|
-
throw new DvmError(
|
|
1502
|
-
"invalid_privkey",
|
|
1503
|
-
"Privkey must be 64 hex characters (32 bytes).",
|
|
1504
|
-
"Provide a valid secp256k1 private key as a 64-char hex string."
|
|
1505
|
-
);
|
|
1506
|
-
}
|
|
1507
|
-
if (challenge.length !== 32) {
|
|
1508
|
-
throw new DvmError(
|
|
1509
|
-
"invalid_challenge",
|
|
1510
|
-
`Challenge must be exactly 32 bytes; got ${challenge.length}.`,
|
|
1511
|
-
"Pass the SHA-256 digest output (32 bytes)."
|
|
1512
|
-
);
|
|
1513
|
-
}
|
|
1514
|
-
const sig = schnorr3.sign(challenge, hexToBytes4(privkeyHex));
|
|
1515
|
-
return bytesToHex4(sig);
|
|
1516
|
-
}
|
|
1517
|
-
function verifyChallenge(pubkeyHex, challenge, sigHex) {
|
|
1518
|
-
if (!SIG_HEX_RE.test(sigHex)) return false;
|
|
1519
|
-
if (challenge.length !== 32) return false;
|
|
1520
|
-
let xonly;
|
|
1521
|
-
if (PUBKEY_COMPRESSED_HEX_RE.test(pubkeyHex)) {
|
|
1522
|
-
xonly = hexToBytes4(pubkeyHex.slice(2));
|
|
1523
|
-
} else if (PUBKEY_XONLY_HEX_RE.test(pubkeyHex)) {
|
|
1524
|
-
xonly = hexToBytes4(pubkeyHex);
|
|
1525
|
-
} else {
|
|
1526
|
-
return false;
|
|
1527
|
-
}
|
|
1528
|
-
try {
|
|
1529
|
-
return schnorr3.verify(hexToBytes4(sigHex), challenge, xonly);
|
|
1530
|
-
} catch {
|
|
1531
|
-
return false;
|
|
1532
|
-
}
|
|
1533
|
-
}
|
|
1534
|
-
function hexToBytes4(hex) {
|
|
1535
|
-
return Uint8Array.from(Buffer.from(hex, "hex"));
|
|
1536
|
-
}
|
|
1537
|
-
function bytesToHex4(bytes) {
|
|
1538
|
-
return Buffer.from(bytes).toString("hex");
|
|
1539
|
-
}
|
|
1540
|
-
|
|
1541
|
-
// src/lib/cashu/admin-auth.ts
|
|
1542
|
-
import { randomBytes } from "crypto";
|
|
1543
|
-
import { sha256 as sha2563 } from "@noble/hashes/sha2.js";
|
|
1544
|
-
var ADMIN_AUTH_NONCE_TTL_SECONDS = 300;
|
|
1545
|
-
var ADMIN_AUTH_CLOCK_SKEW_SECONDS = 30;
|
|
1546
|
-
var ADMIN_STATE_UNAVAILABLE = "admin_state_unavailable";
|
|
1547
|
-
function buildAdminChallenge(args) {
|
|
1548
|
-
const msg = `dvmkit-admin:${args.method}:${args.path}:${args.dvmId}:${args.nonceHex}:${args.unixSeconds}`;
|
|
1549
|
-
return sha2563(new TextEncoder().encode(msg));
|
|
1550
|
-
}
|
|
1551
|
-
function buildAdminAuthHeader(args) {
|
|
1552
|
-
const nowMs = args.now ? args.now() : Date.now();
|
|
1553
|
-
const unixSeconds = Math.floor(nowMs / 1e3);
|
|
1554
|
-
const nonceBytes = args.randomNonce ? args.randomNonce() : Uint8Array.from(randomBytes(16));
|
|
1555
|
-
const nonceHex = Buffer.from(nonceBytes).toString("hex");
|
|
1556
|
-
const challenge = buildAdminChallenge({
|
|
1557
|
-
method: args.method,
|
|
1558
|
-
path: args.path,
|
|
1559
|
-
dvmId: args.dvmId,
|
|
1560
|
-
nonceHex,
|
|
1561
|
-
unixSeconds
|
|
1562
|
-
});
|
|
1563
|
-
const sigHex = signChallenge(args.privkeyHex, challenge);
|
|
1564
|
-
return {
|
|
1565
|
-
header: `P2PK ${nonceHex}.${unixSeconds}.${sigHex}`,
|
|
1566
|
-
nonceHex,
|
|
1567
|
-
unixSeconds
|
|
1568
|
-
};
|
|
1569
|
-
}
|
|
1570
|
-
|
|
1571
1577
|
// src/lib/monotonic-clock.ts
|
|
1572
1578
|
function createMonotonicClock() {
|
|
1573
1579
|
let anchorWallMs = Date.now();
|
|
@@ -1620,9 +1626,6 @@ function normaliseMintUrl(url) {
|
|
|
1620
1626
|
}
|
|
1621
1627
|
}
|
|
1622
1628
|
|
|
1623
|
-
// src/lib/payment-rails/tempo-wire.ts
|
|
1624
|
-
var TEMPO_SESSION_UPDATED_REASON = "Tempo session updated; attach the next voucher to fund this credit.";
|
|
1625
|
-
|
|
1626
1629
|
export {
|
|
1627
1630
|
toLockPubkey,
|
|
1628
1631
|
isX402SettlementReconciliationReason,
|
|
@@ -1644,6 +1647,7 @@ export {
|
|
|
1644
1647
|
WALLET_VERSION,
|
|
1645
1648
|
RECENT_SPENDS_CAP,
|
|
1646
1649
|
DEFAULT_AGENT_MINT_URL,
|
|
1650
|
+
loadWalletConfiguredMints,
|
|
1647
1651
|
loadAgentWallet,
|
|
1648
1652
|
saveAgentWallet,
|
|
1649
1653
|
walletExists,
|
|
@@ -1662,6 +1666,14 @@ export {
|
|
|
1662
1666
|
receiptPubkeyFromSecret,
|
|
1663
1667
|
deriveReceiptKeypair,
|
|
1664
1668
|
generateEphemeralReceiptKey,
|
|
1669
|
+
PRIVKEY_HEX_RE,
|
|
1670
|
+
derivePubkeyFromPrivkey,
|
|
1671
|
+
verifyChallenge,
|
|
1672
|
+
ADMIN_AUTH_NONCE_TTL_SECONDS,
|
|
1673
|
+
ADMIN_AUTH_CLOCK_SKEW_SECONDS,
|
|
1674
|
+
ADMIN_STATE_UNAVAILABLE,
|
|
1675
|
+
buildAdminChallenge,
|
|
1676
|
+
buildAdminAuthHeader,
|
|
1665
1677
|
generateIdentity,
|
|
1666
1678
|
loadIdentitySecret,
|
|
1667
1679
|
writeIdentity,
|
|
@@ -1685,13 +1697,5 @@ export {
|
|
|
1685
1697
|
receiptFailureDetail,
|
|
1686
1698
|
isPublicRequestId,
|
|
1687
1699
|
parseTraceparent,
|
|
1688
|
-
PRIVKEY_HEX_RE,
|
|
1689
|
-
derivePubkeyFromPrivkey,
|
|
1690
|
-
verifyChallenge,
|
|
1691
|
-
ADMIN_AUTH_NONCE_TTL_SECONDS,
|
|
1692
|
-
ADMIN_AUTH_CLOCK_SKEW_SECONDS,
|
|
1693
|
-
ADMIN_STATE_UNAVAILABLE,
|
|
1694
|
-
buildAdminChallenge,
|
|
1695
|
-
buildAdminAuthHeader,
|
|
1696
1700
|
createMonotonicClock
|
|
1697
1701
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
BTC_RATE_FILE,
|
|
3
3
|
ensureConfigSubdir
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-CXCQLOOK.js";
|
|
5
5
|
import {
|
|
6
6
|
canonicaliseForSigning
|
|
7
7
|
} from "./chunk-OFVV37XC.js";
|
|
@@ -12,6 +12,47 @@ import {
|
|
|
12
12
|
// src/lib/credit-implicit.ts
|
|
13
13
|
var IMPLICIT_CREDIT_TTL_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
14
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
|
+
|
|
15
56
|
// src/lib/fx-coingecko.ts
|
|
16
57
|
var COINGECKO_SIMPLE_PRICE_URL = "https://api.coingecko.com/api/v3/simple/price?ids=bitcoin,usd-coin&vs_currencies=usd";
|
|
17
58
|
var COINGECKO_BTC_USD_URL = "https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd";
|
|
@@ -58,39 +99,6 @@ function isPositiveNumber(v) {
|
|
|
58
99
|
// src/lib/currency.ts
|
|
59
100
|
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
60
101
|
import { dirname } from "path";
|
|
61
|
-
function msatsToUsd(msats, rate) {
|
|
62
|
-
return msats / 1e11 * rate;
|
|
63
|
-
}
|
|
64
|
-
function usdToMsats(usd, rate) {
|
|
65
|
-
return Math.round(usd / rate * 1e11);
|
|
66
|
-
}
|
|
67
|
-
function msatsToUsdCents(msats, btcPriceUsd) {
|
|
68
|
-
const usd = msatsToUsd(msats, btcPriceUsd);
|
|
69
|
-
return Math.round(usd * 100);
|
|
70
|
-
}
|
|
71
|
-
function msatsToUsdc(msats, btcUsdRate) {
|
|
72
|
-
if (!Number.isSafeInteger(msats) || msats < 0) {
|
|
73
|
-
throw new RangeError("msats must be a non-negative safe integer");
|
|
74
|
-
}
|
|
75
|
-
if (!Number.isFinite(btcUsdRate) || btcUsdRate <= 0) {
|
|
76
|
-
throw new RangeError("BTC/USD rate must be finite and positive");
|
|
77
|
-
}
|
|
78
|
-
const [mantissa, exponent = "0"] = btcUsdRate.toString().split("e");
|
|
79
|
-
const decimalPlaces = mantissa.split(".")[1]?.length ?? 0;
|
|
80
|
-
const shift = Number(exponent) - decimalPlaces;
|
|
81
|
-
let numerator = BigInt(msats) * BigInt(mantissa.replace(".", ""));
|
|
82
|
-
let denominator = 100000n;
|
|
83
|
-
if (shift > 0) numerator *= 10n ** BigInt(shift);
|
|
84
|
-
else if (shift < 0) denominator *= 10n ** BigInt(-shift);
|
|
85
|
-
const micro = (numerator + denominator - 1n) / denominator;
|
|
86
|
-
if (micro > BigInt(Number.MAX_SAFE_INTEGER)) {
|
|
87
|
-
throw new RangeError("USDC micro-unit amount exceeds the safe integer range");
|
|
88
|
-
}
|
|
89
|
-
return Number(micro);
|
|
90
|
-
}
|
|
91
|
-
function usdcToMsats(usdc, btcUsdRate) {
|
|
92
|
-
return usdToMsats(usdc, btcUsdRate);
|
|
93
|
-
}
|
|
94
102
|
function formatSats(msats) {
|
|
95
103
|
if (msats === 0) return "0 sats";
|
|
96
104
|
if (msats < 1e3) return `${msats.toLocaleString("en-US")} msats`;
|
|
@@ -313,14 +321,16 @@ function verifyDrainReceipt(receipt) {
|
|
|
313
321
|
|
|
314
322
|
export {
|
|
315
323
|
IMPLICIT_CREDIT_TTL_MS,
|
|
316
|
-
COINGECKO_SIMPLE_PRICE_URL,
|
|
317
|
-
fetchCoinGeckoSpot,
|
|
318
|
-
fetchCoinGeckoBtcUsd,
|
|
319
324
|
msatsToUsd,
|
|
320
325
|
usdToMsats,
|
|
321
326
|
msatsToUsdCents,
|
|
322
327
|
msatsToUsdc,
|
|
323
328
|
usdcToMsats,
|
|
329
|
+
msatsToMicro,
|
|
330
|
+
microToSats,
|
|
331
|
+
COINGECKO_SIMPLE_PRICE_URL,
|
|
332
|
+
fetchCoinGeckoSpot,
|
|
333
|
+
fetchCoinGeckoBtcUsd,
|
|
324
334
|
formatSats,
|
|
325
335
|
formatAmount,
|
|
326
336
|
formatPaymentAmount,
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
IMPLICIT_CREDIT_TTL_MS,
|
|
3
3
|
isDrainReceipt
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-NFMOPYBA.js";
|
|
5
5
|
import {
|
|
6
6
|
CREDITS_FILE,
|
|
7
7
|
ensureConfigDir
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-CXCQLOOK.js";
|
|
9
9
|
import {
|
|
10
10
|
DvmError
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-BPYMEMQX.js";
|
|
12
12
|
|
|
13
13
|
// src/lib/payment-rails/types.ts
|
|
14
14
|
var RAIL_FLAGS = ["cashu", "tempo", "x402"];
|
|
@@ -1449,33 +1449,58 @@ function isObjectRecord(value) {
|
|
|
1449
1449
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1450
1450
|
}
|
|
1451
1451
|
function mergeDuplicateCredits(credits) {
|
|
1452
|
-
const
|
|
1452
|
+
const groups = [];
|
|
1453
1453
|
const byCredit = /* @__PURE__ */ new Map();
|
|
1454
1454
|
let changed = false;
|
|
1455
1455
|
for (const record of credits) {
|
|
1456
1456
|
if (typeof record.creditId !== "string" || typeof record.callerPubkey !== "string") {
|
|
1457
|
-
|
|
1457
|
+
groups.push([record]);
|
|
1458
1458
|
continue;
|
|
1459
1459
|
}
|
|
1460
1460
|
const key = `${record.callerPubkey}\0${record.creditId}`;
|
|
1461
|
-
|
|
1462
|
-
if (
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1461
|
+
let group = byCredit.get(key);
|
|
1462
|
+
if (group === void 0) {
|
|
1463
|
+
group = [];
|
|
1464
|
+
byCredit.set(key, group);
|
|
1465
|
+
groups.push(group);
|
|
1466
1466
|
}
|
|
1467
|
-
|
|
1468
|
-
|
|
1467
|
+
let combined = record;
|
|
1468
|
+
let index = group.findIndex((candidate) => compatibleCreditLocations(candidate, combined));
|
|
1469
|
+
while (index !== -1) {
|
|
1470
|
+
combined = mergeCreditRecords(group[index], combined);
|
|
1471
|
+
group.splice(index, 1);
|
|
1472
|
+
changed = true;
|
|
1473
|
+
index = group.findIndex((candidate) => compatibleCreditLocations(candidate, combined));
|
|
1474
|
+
}
|
|
1475
|
+
group.push(combined);
|
|
1469
1476
|
}
|
|
1470
|
-
return { credits:
|
|
1477
|
+
return { credits: groups.flat(), changed };
|
|
1478
|
+
}
|
|
1479
|
+
function compatibleCreditLocations(left, right) {
|
|
1480
|
+
const leftIdentity = dvmLocationIdentity(left);
|
|
1481
|
+
const rightIdentity = dvmLocationIdentity(right);
|
|
1482
|
+
if (leftIdentity && rightIdentity) {
|
|
1483
|
+
return matchesDvmIdentity(left, rightIdentity);
|
|
1484
|
+
}
|
|
1485
|
+
if (leftIdentity) {
|
|
1486
|
+
return dvmLocationOrigins(left).some((origin) => matchesDvmOrigin(right, origin, leftIdentity));
|
|
1487
|
+
}
|
|
1488
|
+
if (rightIdentity) {
|
|
1489
|
+
return dvmLocationOrigins(right).some((origin) => matchesDvmOrigin(left, origin, rightIdentity));
|
|
1490
|
+
}
|
|
1491
|
+
return dvmLocationOrigins(left).some((origin) => matchesDvmOrigin(right, origin, void 0));
|
|
1471
1492
|
}
|
|
1472
1493
|
function mergeCreditRecords(left, right) {
|
|
1473
1494
|
const leftUpdated = Number.isFinite(left.updatedAt) ? left.updatedAt : 0;
|
|
1474
1495
|
const rightUpdated = Number.isFinite(right.updatedAt) ? right.updatedAt : 0;
|
|
1475
1496
|
const [newer, older] = rightUpdated >= leftUpdated ? [right, left] : [left, right];
|
|
1476
1497
|
const record = { ...newer };
|
|
1477
|
-
|
|
1478
|
-
if (
|
|
1498
|
+
const identity = dvmLocationIdentity(newer) ?? dvmLocationIdentity(older);
|
|
1499
|
+
if (identity) {
|
|
1500
|
+
record.dvmId = identity.dvmId;
|
|
1501
|
+
record.attestedBuilderPubkey = identity.builderPubkey;
|
|
1502
|
+
} else if (record.dvmId === void 0 && record.attestedBuilderPubkey === void 0) {
|
|
1503
|
+
record.dvmId = older.dvmId;
|
|
1479
1504
|
record.attestedBuilderPubkey = older.attestedBuilderPubkey;
|
|
1480
1505
|
}
|
|
1481
1506
|
if (record.rail === void 0 && older.rail !== void 0) record.rail = older.rail;
|
|
@@ -10,39 +10,6 @@ import {
|
|
|
10
10
|
projectSpanRow
|
|
11
11
|
} from "./chunk-ETXDTUJO.js";
|
|
12
12
|
|
|
13
|
-
// src/sdk/step-cache.ts
|
|
14
|
-
var StepCache = class _StepCache {
|
|
15
|
-
cache = /* @__PURE__ */ new Map();
|
|
16
|
-
has(id) {
|
|
17
|
-
return this.cache.has(id);
|
|
18
|
-
}
|
|
19
|
-
get(id) {
|
|
20
|
-
return this.getRecord(id).value;
|
|
21
|
-
}
|
|
22
|
-
getRecord(id) {
|
|
23
|
-
const record = this.cache.get(id);
|
|
24
|
-
if (record === void 0) throw new Error(`StepCache: no cached result for step "${id}"`);
|
|
25
|
-
return record;
|
|
26
|
-
}
|
|
27
|
-
set(id, value, costs) {
|
|
28
|
-
this.cache.set(id, {
|
|
29
|
-
id,
|
|
30
|
-
value,
|
|
31
|
-
...costs !== void 0 && costs.length > 0 ? { costs: costs.map(({ amount, currency }) => ({ amount, currency })) } : {}
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
serialize() {
|
|
35
|
-
return [...this.cache.values()];
|
|
36
|
-
}
|
|
37
|
-
static deserialize(records) {
|
|
38
|
-
const cache = new _StepCache();
|
|
39
|
-
for (const { id, value, costs } of records) {
|
|
40
|
-
cache.set(id, value, costs);
|
|
41
|
-
}
|
|
42
|
-
return cache;
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
|
|
46
13
|
// src/sdk/logger.ts
|
|
47
14
|
function createConsoleLogger(_jobId) {
|
|
48
15
|
return {
|
|
@@ -373,15 +340,15 @@ async function withSpan(opts, fn) {
|
|
|
373
340
|
|
|
374
341
|
// src/observability/datasets.ts
|
|
375
342
|
var SPANS_DATASETS = [
|
|
376
|
-
{ name: "platform", retentionDays:
|
|
377
|
-
{ name: "cashu", retentionDays:
|
|
378
|
-
{ name: "lightning", retentionDays:
|
|
379
|
-
{ name: "stripe", retentionDays:
|
|
380
|
-
{ name: "x402", retentionDays:
|
|
381
|
-
{ name: "tempo", retentionDays:
|
|
382
|
-
{ name: "isolate", retentionDays:
|
|
383
|
-
{ name: "audit", retentionDays:
|
|
384
|
-
{ name: "cron", retentionDays:
|
|
343
|
+
{ name: "platform", retentionDays: 730 },
|
|
344
|
+
{ name: "cashu", retentionDays: 730 },
|
|
345
|
+
{ name: "lightning", retentionDays: 730 },
|
|
346
|
+
{ name: "stripe", retentionDays: 730 },
|
|
347
|
+
{ name: "x402", retentionDays: 730 },
|
|
348
|
+
{ name: "tempo", retentionDays: 730 },
|
|
349
|
+
{ name: "isolate", retentionDays: 730 },
|
|
350
|
+
{ name: "audit", retentionDays: 730 },
|
|
351
|
+
{ name: "cron", retentionDays: 730 }
|
|
385
352
|
];
|
|
386
353
|
var DATASET_NAMES = new Set(SPANS_DATASETS.map((d) => d.name));
|
|
387
354
|
|
|
@@ -485,7 +452,6 @@ function buildNoopLoggers() {
|
|
|
485
452
|
}
|
|
486
453
|
|
|
487
454
|
export {
|
|
488
|
-
StepCache,
|
|
489
455
|
createConsoleLogger,
|
|
490
456
|
createStdoutLogger,
|
|
491
457
|
createNoopLogger,
|