uvd-x402-sdk 2.59.0 → 2.61.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.
- package/dist/index.js +50 -22
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +46 -18
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/dx402.ts +94 -23
package/dist/index.js
CHANGED
|
@@ -4,9 +4,9 @@ var aes = require('@noble/ciphers/aes');
|
|
|
4
4
|
var ed25519 = require('@noble/curves/ed25519');
|
|
5
5
|
var secp256k1 = require('@noble/curves/secp256k1');
|
|
6
6
|
var hkdf = require('@noble/hashes/hkdf');
|
|
7
|
+
var utils = require('@noble/hashes/utils');
|
|
7
8
|
var sha3 = require('@noble/hashes/sha3');
|
|
8
9
|
var sha2 = require('@noble/hashes/sha2');
|
|
9
|
-
var utils = require('@noble/hashes/utils');
|
|
10
10
|
var ethers = require('ethers');
|
|
11
11
|
|
|
12
12
|
// src/dx402.ts
|
|
@@ -1194,24 +1194,20 @@ function b64urlDecode(value) {
|
|
|
1194
1194
|
}
|
|
1195
1195
|
function hexToBytes(hex) {
|
|
1196
1196
|
const clean = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1197
|
+
try {
|
|
1198
|
+
return utils.hexToBytes(clean);
|
|
1199
|
+
} catch (e) {
|
|
1200
|
+
throw new DX402Error(`invalid hex: ${e.message}`);
|
|
1201
1201
|
}
|
|
1202
|
-
return out;
|
|
1203
|
-
}
|
|
1204
|
-
function bytesToHex(bytes) {
|
|
1205
|
-
return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
1206
1202
|
}
|
|
1207
1203
|
function contentHash(body) {
|
|
1208
|
-
return "0x" + bytesToHex(sha3.keccak_256(body));
|
|
1204
|
+
return "0x" + utils.bytesToHex(sha3.keccak_256(body));
|
|
1209
1205
|
}
|
|
1210
1206
|
function paymentId(caip2Network, txHash) {
|
|
1211
1207
|
const enc = new TextEncoder();
|
|
1212
1208
|
const clean = txHash.startsWith("0x") ? txHash.slice(2) : txHash;
|
|
1213
1209
|
const preimage = new Uint8Array([...enc.encode(caip2Network), ...enc.encode(clean)]);
|
|
1214
|
-
return "0x" + bytesToHex(sha3.keccak_256(preimage));
|
|
1210
|
+
return "0x" + utils.bytesToHex(sha3.keccak_256(preimage));
|
|
1215
1211
|
}
|
|
1216
1212
|
function parseEvidenceHeader(value) {
|
|
1217
1213
|
let payload;
|
|
@@ -1494,12 +1490,12 @@ function signAnchorEd25519(privateKey, paymentId2, contentHash2, pointer = "") {
|
|
|
1494
1490
|
throw new DX402Error(`ed25519 seed must be 32 bytes, got ${privateKey.length}`);
|
|
1495
1491
|
}
|
|
1496
1492
|
const digest = anchorDigest(paymentId2, contentHash2, pointer, ZERO_ADDRESS, 0);
|
|
1497
|
-
return "0x" + bytesToHex(ed25519.ed25519.sign(digest, privateKey));
|
|
1493
|
+
return "0x" + utils.bytesToHex(ed25519.ed25519.sign(digest, privateKey));
|
|
1498
1494
|
}
|
|
1499
1495
|
function signAnchorEvm(privateKey, paymentId2, contentHash2, pointer, payee, chainId) {
|
|
1500
1496
|
const digest = anchorDigest(paymentId2, contentHash2, pointer, payee, chainId);
|
|
1501
1497
|
const sig = secp256k1.secp256k1.sign(digest, privateKey);
|
|
1502
|
-
return "0x" + bytesToHex(sig.toCompactRawBytes()) + (sig.recovery === 1 ? "01" : "00");
|
|
1498
|
+
return "0x" + utils.bytesToHex(sig.toCompactRawBytes()) + (sig.recovery === 1 ? "01" : "00");
|
|
1503
1499
|
}
|
|
1504
1500
|
function payerKeyFromSolanaAddress(address) {
|
|
1505
1501
|
if (!address || !address.trim()) throw new DX402Error("empty Solana address");
|
|
@@ -1578,7 +1574,12 @@ function isEvmAddress(value) {
|
|
|
1578
1574
|
return /^0x[0-9a-fA-F]{40}$/.test((value ?? "").trim());
|
|
1579
1575
|
}
|
|
1580
1576
|
function chainIdFor(network) {
|
|
1581
|
-
const
|
|
1577
|
+
const raw = network ?? "";
|
|
1578
|
+
if (raw.toLowerCase().startsWith("eip155:")) {
|
|
1579
|
+
const tail = raw.slice("eip155:".length);
|
|
1580
|
+
if (/^\d+$/.test(tail)) return Number(tail);
|
|
1581
|
+
}
|
|
1582
|
+
const name = raw.includes(":") ? raw.split(":")[1] ?? "" : raw;
|
|
1582
1583
|
const byId = Number(name);
|
|
1583
1584
|
if (Number.isFinite(byId) && byId > 0) return getChainById(byId)?.chainId;
|
|
1584
1585
|
return getChainByName(name)?.chainId;
|
|
@@ -1586,10 +1587,20 @@ function chainIdFor(network) {
|
|
|
1586
1587
|
function sellerDigestFor(paymentId2, contentHash2, payee, network) {
|
|
1587
1588
|
if (isEvmAddress(payee)) {
|
|
1588
1589
|
const chainId = chainIdFor(network);
|
|
1589
|
-
if (chainId) return
|
|
1590
|
+
if (!chainId) return void 0;
|
|
1591
|
+
return anchorDigest(paymentId2, contentHash2, "", payee, chainId);
|
|
1590
1592
|
}
|
|
1591
1593
|
return anchorDigest(paymentId2, contentHash2, "", ZERO_ADDRESS, 0);
|
|
1592
1594
|
}
|
|
1595
|
+
var ANCHOR_MAX_REQUEST_BYTES = 64 * 1024;
|
|
1596
|
+
function toBase64(bytes) {
|
|
1597
|
+
let out = "";
|
|
1598
|
+
const CHUNK = 32768;
|
|
1599
|
+
for (let i = 0; i < bytes.length; i += CHUNK) {
|
|
1600
|
+
out += String.fromCharCode(...bytes.subarray(i, i + CHUNK));
|
|
1601
|
+
}
|
|
1602
|
+
return btoa(out);
|
|
1603
|
+
}
|
|
1593
1604
|
async function anchorEvidence(body, opts) {
|
|
1594
1605
|
try {
|
|
1595
1606
|
const recipients = [
|
|
@@ -1606,17 +1617,25 @@ async function anchorEvidence(body, opts) {
|
|
|
1606
1617
|
txHash: opts.txHash,
|
|
1607
1618
|
payer: opts.payer,
|
|
1608
1619
|
payee: opts.payee,
|
|
1609
|
-
sealed:
|
|
1620
|
+
sealed: toBase64(blob),
|
|
1610
1621
|
backend: "s3",
|
|
1611
1622
|
contentHash: hash,
|
|
1612
1623
|
keyAlg: opts.payerKey.length === 32 ? "ECIES-X25519" : "ECIES-secp256k1",
|
|
1613
1624
|
mode: "direct",
|
|
1614
1625
|
retention: opts.retention ?? "90d"
|
|
1615
1626
|
};
|
|
1627
|
+
let unsigned;
|
|
1616
1628
|
if (opts.sign) {
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1629
|
+
const digest = sellerDigestFor(opts.paymentId, hash, opts.payee, opts.network);
|
|
1630
|
+
if (digest === void 0) {
|
|
1631
|
+
unsigned = "unknown_chain_id";
|
|
1632
|
+
} else {
|
|
1633
|
+
payload.sellerSignature = await opts.sign(digest);
|
|
1634
|
+
}
|
|
1635
|
+
}
|
|
1636
|
+
const wire = JSON.stringify(payload);
|
|
1637
|
+
if (new TextEncoder().encode(wire).length > ANCHOR_MAX_REQUEST_BYTES) {
|
|
1638
|
+
return { v: 1, skipped: "too_large" };
|
|
1620
1639
|
}
|
|
1621
1640
|
const base = (opts.facilitator ?? "https://facilitator.ultravioletadao.xyz").replace(
|
|
1622
1641
|
/\/+$/,
|
|
@@ -1626,10 +1645,19 @@ async function anchorEvidence(body, opts) {
|
|
|
1626
1645
|
const res = await doFetch(`${base}/dx402/anchor`, {
|
|
1627
1646
|
method: "POST",
|
|
1628
1647
|
headers: { "content-type": "application/json" },
|
|
1629
|
-
body:
|
|
1648
|
+
body: wire
|
|
1630
1649
|
});
|
|
1631
|
-
if (!res.ok)
|
|
1632
|
-
|
|
1650
|
+
if (!res.ok) {
|
|
1651
|
+
let error;
|
|
1652
|
+
try {
|
|
1653
|
+
error = (await res.json()).error;
|
|
1654
|
+
} catch {
|
|
1655
|
+
}
|
|
1656
|
+
return { v: 1, skipped: "anchor_failed", status: res.status, error };
|
|
1657
|
+
}
|
|
1658
|
+
const out = await res.json();
|
|
1659
|
+
if (unsigned) out.unsigned = unsigned;
|
|
1660
|
+
return out;
|
|
1633
1661
|
} catch {
|
|
1634
1662
|
return { v: 1, skipped: "anchor_failed" };
|
|
1635
1663
|
}
|