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 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
- if (clean.length % 2 !== 0) throw new DX402Error("odd-length hex string");
1198
- const out = new Uint8Array(clean.length / 2);
1199
- for (let i = 0; i < out.length; i++) {
1200
- out[i] = parseInt(clean.slice(i * 2, i * 2 + 2), 16);
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 name = (network ?? "").includes(":") ? network.split(":")[1] ?? "" : network;
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 anchorDigest(paymentId2, contentHash2, "", payee, chainId);
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: btoa(String.fromCharCode(...blob)),
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
- payload.sellerSignature = await opts.sign(
1618
- sellerDigestFor(opts.paymentId, hash, opts.payee, opts.network)
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: JSON.stringify(payload)
1648
+ body: wire
1630
1649
  });
1631
- if (!res.ok) return { v: 1, skipped: "anchor_failed" };
1632
- return await res.json();
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
  }