@unicitylabs/sphere-sdk 0.5.8 → 0.6.0-dev.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.
@@ -1385,114 +1385,6 @@ var oidNist = (suffix) => ({
1385
1385
  oid: Uint8Array.from([6, 9, 96, 134, 72, 1, 101, 3, 4, 2, suffix])
1386
1386
  });
1387
1387
 
1388
- // node_modules/@noble/hashes/hmac.js
1389
- var _HMAC = class {
1390
- oHash;
1391
- iHash;
1392
- blockLen;
1393
- outputLen;
1394
- finished = false;
1395
- destroyed = false;
1396
- constructor(hash, key) {
1397
- ahash(hash);
1398
- abytes(key, void 0, "key");
1399
- this.iHash = hash.create();
1400
- if (typeof this.iHash.update !== "function")
1401
- throw new Error("Expected instance of class which extends utils.Hash");
1402
- this.blockLen = this.iHash.blockLen;
1403
- this.outputLen = this.iHash.outputLen;
1404
- const blockLen = this.blockLen;
1405
- const pad = new Uint8Array(blockLen);
1406
- pad.set(key.length > blockLen ? hash.create().update(key).digest() : key);
1407
- for (let i = 0; i < pad.length; i++)
1408
- pad[i] ^= 54;
1409
- this.iHash.update(pad);
1410
- this.oHash = hash.create();
1411
- for (let i = 0; i < pad.length; i++)
1412
- pad[i] ^= 54 ^ 92;
1413
- this.oHash.update(pad);
1414
- clean(pad);
1415
- }
1416
- update(buf) {
1417
- aexists(this);
1418
- this.iHash.update(buf);
1419
- return this;
1420
- }
1421
- digestInto(out) {
1422
- aexists(this);
1423
- abytes(out, this.outputLen, "output");
1424
- this.finished = true;
1425
- this.iHash.digestInto(out);
1426
- this.oHash.update(out);
1427
- this.oHash.digestInto(out);
1428
- this.destroy();
1429
- }
1430
- digest() {
1431
- const out = new Uint8Array(this.oHash.outputLen);
1432
- this.digestInto(out);
1433
- return out;
1434
- }
1435
- _cloneInto(to) {
1436
- to ||= Object.create(Object.getPrototypeOf(this), {});
1437
- const { oHash, iHash, finished, destroyed, blockLen, outputLen } = this;
1438
- to = to;
1439
- to.finished = finished;
1440
- to.destroyed = destroyed;
1441
- to.blockLen = blockLen;
1442
- to.outputLen = outputLen;
1443
- to.oHash = oHash._cloneInto(to.oHash);
1444
- to.iHash = iHash._cloneInto(to.iHash);
1445
- return to;
1446
- }
1447
- clone() {
1448
- return this._cloneInto();
1449
- }
1450
- destroy() {
1451
- this.destroyed = true;
1452
- this.oHash.destroy();
1453
- this.iHash.destroy();
1454
- }
1455
- };
1456
- var hmac = (hash, key, message) => new _HMAC(hash, key).update(message).digest();
1457
- hmac.create = (hash, key) => new _HMAC(hash, key);
1458
-
1459
- // node_modules/@noble/hashes/hkdf.js
1460
- function extract(hash, ikm, salt) {
1461
- ahash(hash);
1462
- if (salt === void 0)
1463
- salt = new Uint8Array(hash.outputLen);
1464
- return hmac(hash, salt, ikm);
1465
- }
1466
- var HKDF_COUNTER = /* @__PURE__ */ Uint8Array.of(0);
1467
- var EMPTY_BUFFER = /* @__PURE__ */ Uint8Array.of();
1468
- function expand(hash, prk, info, length = 32) {
1469
- ahash(hash);
1470
- anumber(length, "length");
1471
- const olen = hash.outputLen;
1472
- if (length > 255 * olen)
1473
- throw new Error("Length must be <= 255*HashLen");
1474
- const blocks = Math.ceil(length / olen);
1475
- if (info === void 0)
1476
- info = EMPTY_BUFFER;
1477
- else
1478
- abytes(info, void 0, "info");
1479
- const okm = new Uint8Array(blocks * olen);
1480
- const HMAC = hmac.create(hash, prk);
1481
- const HMACTmp = HMAC._cloneInto();
1482
- const T = new Uint8Array(HMAC.outputLen);
1483
- for (let counter = 0; counter < blocks; counter++) {
1484
- HKDF_COUNTER[0] = counter + 1;
1485
- HMACTmp.update(counter === 0 ? EMPTY_BUFFER : T).update(info).update(HKDF_COUNTER).digestInto(T);
1486
- okm.set(T, olen * counter);
1487
- HMAC._cloneInto(HMACTmp);
1488
- }
1489
- HMAC.destroy();
1490
- HMACTmp.destroy();
1491
- clean(T, HKDF_COUNTER);
1492
- return okm.slice(0, length);
1493
- }
1494
- var hkdf = (hash, ikm, salt, info, length) => expand(hash, extract(hash, ikm, salt), info, length);
1495
-
1496
1388
  // node_modules/@noble/hashes/_md.js
1497
1389
  function Chi(a, b, c) {
1498
1390
  return a & b ^ ~a & c;
@@ -1759,122 +1651,6 @@ var sha256 = /* @__PURE__ */ createHasher(
1759
1651
  // transport/NostrTransportProvider.ts
1760
1652
  var import_nostr_js_sdk = require("@unicitylabs/nostr-js-sdk");
1761
1653
 
1762
- // core/crypto.ts
1763
- var bip39 = __toESM(require("bip39"), 1);
1764
- var import_crypto_js = __toESM(require("crypto-js"), 1);
1765
- var import_elliptic = __toESM(require("elliptic"), 1);
1766
-
1767
- // core/bech32.ts
1768
- var CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
1769
- var GENERATOR = [996825010, 642813549, 513874426, 1027748829, 705979059];
1770
- function convertBits(data, fromBits, toBits, pad) {
1771
- let acc = 0;
1772
- let bits = 0;
1773
- const ret = [];
1774
- const maxv = (1 << toBits) - 1;
1775
- for (let i = 0; i < data.length; i++) {
1776
- const value = data[i];
1777
- if (value < 0 || value >> fromBits !== 0) return null;
1778
- acc = acc << fromBits | value;
1779
- bits += fromBits;
1780
- while (bits >= toBits) {
1781
- bits -= toBits;
1782
- ret.push(acc >> bits & maxv);
1783
- }
1784
- }
1785
- if (pad) {
1786
- if (bits > 0) {
1787
- ret.push(acc << toBits - bits & maxv);
1788
- }
1789
- } else if (bits >= fromBits || acc << toBits - bits & maxv) {
1790
- return null;
1791
- }
1792
- return ret;
1793
- }
1794
- function hrpExpand(hrp) {
1795
- const ret = [];
1796
- for (let i = 0; i < hrp.length; i++) ret.push(hrp.charCodeAt(i) >> 5);
1797
- ret.push(0);
1798
- for (let i = 0; i < hrp.length; i++) ret.push(hrp.charCodeAt(i) & 31);
1799
- return ret;
1800
- }
1801
- function bech32Polymod(values) {
1802
- let chk = 1;
1803
- for (let p = 0; p < values.length; p++) {
1804
- const top = chk >> 25;
1805
- chk = (chk & 33554431) << 5 ^ values[p];
1806
- for (let i = 0; i < 5; i++) {
1807
- if (top >> i & 1) chk ^= GENERATOR[i];
1808
- }
1809
- }
1810
- return chk;
1811
- }
1812
- function bech32Checksum(hrp, data) {
1813
- const values = hrpExpand(hrp).concat(data).concat([0, 0, 0, 0, 0, 0]);
1814
- const mod = bech32Polymod(values) ^ 1;
1815
- const ret = [];
1816
- for (let p = 0; p < 6; p++) {
1817
- ret.push(mod >> 5 * (5 - p) & 31);
1818
- }
1819
- return ret;
1820
- }
1821
- function encodeBech32(hrp, version, program) {
1822
- if (version < 0 || version > 16) {
1823
- throw new SphereError("Invalid witness version", "VALIDATION_ERROR");
1824
- }
1825
- const converted = convertBits(Array.from(program), 8, 5, true);
1826
- if (!converted) {
1827
- throw new SphereError("Failed to convert bits", "VALIDATION_ERROR");
1828
- }
1829
- const data = [version].concat(converted);
1830
- const checksum = bech32Checksum(hrp, data);
1831
- const combined = data.concat(checksum);
1832
- let out = hrp + "1";
1833
- for (let i = 0; i < combined.length; i++) {
1834
- out += CHARSET[combined[i]];
1835
- }
1836
- return out;
1837
- }
1838
-
1839
- // core/crypto.ts
1840
- var ec = new import_elliptic.default.ec("secp256k1");
1841
- var CURVE_ORDER = BigInt(
1842
- "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"
1843
- );
1844
- function getPublicKey(privateKey, compressed = true) {
1845
- const keyPair = ec.keyFromPrivate(privateKey, "hex");
1846
- return keyPair.getPublic(compressed, "hex");
1847
- }
1848
- function sha2562(data, inputEncoding = "hex") {
1849
- const parsed = inputEncoding === "hex" ? import_crypto_js.default.enc.Hex.parse(data) : import_crypto_js.default.enc.Utf8.parse(data);
1850
- return import_crypto_js.default.SHA256(parsed).toString();
1851
- }
1852
- function ripemd160(data, inputEncoding = "hex") {
1853
- const parsed = inputEncoding === "hex" ? import_crypto_js.default.enc.Hex.parse(data) : import_crypto_js.default.enc.Utf8.parse(data);
1854
- return import_crypto_js.default.RIPEMD160(parsed).toString();
1855
- }
1856
- function hash160(data) {
1857
- const sha = sha2562(data, "hex");
1858
- return ripemd160(sha, "hex");
1859
- }
1860
- function hash160ToBytes(hash160Hex) {
1861
- const matches = hash160Hex.match(/../g);
1862
- if (!matches) return new Uint8Array(0);
1863
- return Uint8Array.from(matches.map((x) => parseInt(x, 16)));
1864
- }
1865
- function publicKeyToAddress(publicKey, prefix = "alpha", witnessVersion = 0) {
1866
- const pubKeyHash = hash160(publicKey);
1867
- const programBytes = hash160ToBytes(pubKeyHash);
1868
- return encodeBech32(prefix, witnessVersion, programBytes);
1869
- }
1870
- function hexToBytes2(hex) {
1871
- const matches = hex.match(/../g);
1872
- if (!matches) {
1873
- return new Uint8Array(0);
1874
- }
1875
- return Uint8Array.from(matches.map((x) => parseInt(x, 16)));
1876
- }
1877
-
1878
1654
  // transport/websocket.ts
1879
1655
  var WebSocketReadyState = {
1880
1656
  CONNECTING: 0,
@@ -1897,63 +1673,6 @@ function defaultUUIDGenerator() {
1897
1673
  var COMPOSING_INDICATOR_KIND = 25050;
1898
1674
  var TIMESTAMP_RANDOMIZATION = 2 * 24 * 60 * 60;
1899
1675
  var EVENT_KINDS = NOSTR_EVENT_KINDS;
1900
- function hashAddressForTag(address) {
1901
- const bytes = new TextEncoder().encode("unicity:address:" + address);
1902
- return import_buffer.Buffer.from(sha256(bytes)).toString("hex");
1903
- }
1904
- function deriveNametagEncryptionKey(privateKeyHex) {
1905
- const privateKeyBytes = import_buffer.Buffer.from(privateKeyHex, "hex");
1906
- const saltInput = new TextEncoder().encode("sphere-nametag-salt");
1907
- const salt = sha256(saltInput);
1908
- const info = new TextEncoder().encode("nametag-encryption");
1909
- return hkdf(sha256, privateKeyBytes, salt, info, 32);
1910
- }
1911
- async function encryptNametag(nametag, privateKeyHex) {
1912
- const key = deriveNametagEncryptionKey(privateKeyHex);
1913
- const iv = crypto.getRandomValues(new Uint8Array(12));
1914
- const encoder = new TextEncoder();
1915
- const data = encoder.encode(nametag);
1916
- const cryptoKey = await crypto.subtle.importKey(
1917
- "raw",
1918
- new Uint8Array(key).buffer,
1919
- { name: "AES-GCM" },
1920
- false,
1921
- ["encrypt"]
1922
- );
1923
- const encrypted = await crypto.subtle.encrypt(
1924
- { name: "AES-GCM", iv: new Uint8Array(iv).buffer },
1925
- cryptoKey,
1926
- new Uint8Array(data).buffer
1927
- );
1928
- const combined = new Uint8Array(iv.length + encrypted.byteLength);
1929
- combined.set(iv, 0);
1930
- combined.set(new Uint8Array(encrypted), iv.length);
1931
- return import_buffer.Buffer.from(combined).toString("base64");
1932
- }
1933
- async function decryptNametag(encryptedBase64, privateKeyHex) {
1934
- try {
1935
- const key = deriveNametagEncryptionKey(privateKeyHex);
1936
- const combined = import_buffer.Buffer.from(encryptedBase64, "base64");
1937
- const iv = combined.slice(0, 12);
1938
- const ciphertext = combined.slice(12);
1939
- const cryptoKey = await crypto.subtle.importKey(
1940
- "raw",
1941
- new Uint8Array(key).buffer,
1942
- { name: "AES-GCM" },
1943
- false,
1944
- ["decrypt"]
1945
- );
1946
- const decrypted = await crypto.subtle.decrypt(
1947
- { name: "AES-GCM", iv: new Uint8Array(iv).buffer },
1948
- cryptoKey,
1949
- new Uint8Array(ciphertext).buffer
1950
- );
1951
- const decoder = new TextDecoder();
1952
- return decoder.decode(decrypted);
1953
- } catch {
1954
- return null;
1955
- }
1956
- }
1957
1676
  var NostrTransportProvider = class {
1958
1677
  id = "nostr";
1959
1678
  name = "Nostr Transport";
@@ -2422,138 +2141,51 @@ var NostrTransportProvider = class {
2422
2141
  }
2423
2142
  async resolveNametag(nametag) {
2424
2143
  this.ensureConnected();
2425
- const hashedNametag = (0, import_nostr_js_sdk.hashNametag)(nametag);
2426
- let events = await this.queryEvents({
2427
- kinds: [EVENT_KINDS.NAMETAG_BINDING],
2428
- "#t": [hashedNametag],
2429
- limit: 1
2430
- });
2431
- if (events.length === 0) {
2432
- events = await this.queryEvents({
2433
- kinds: [EVENT_KINDS.NAMETAG_BINDING],
2434
- "#d": [hashedNametag],
2435
- limit: 1
2436
- });
2437
- }
2438
- if (events.length === 0) return null;
2439
- const bindingEvent = events[0];
2440
- if (bindingEvent.pubkey) {
2441
- return bindingEvent.pubkey;
2442
- }
2443
- const pubkeyTag = bindingEvent.tags.find((t) => t[0] === "p");
2444
- if (pubkeyTag?.[1]) return pubkeyTag[1];
2445
- return null;
2144
+ return this.nostrClient.queryPubkeyByNametag(nametag);
2446
2145
  }
2447
2146
  async resolveNametagInfo(nametag) {
2448
2147
  this.ensureConnected();
2449
- const hashedNametag = (0, import_nostr_js_sdk.hashNametag)(nametag);
2450
- let events = await this.queryEvents({
2451
- kinds: [EVENT_KINDS.NAMETAG_BINDING],
2452
- "#t": [hashedNametag],
2453
- limit: 1
2454
- });
2455
- if (events.length === 0) {
2456
- events = await this.queryEvents({
2457
- kinds: [EVENT_KINDS.NAMETAG_BINDING],
2458
- "#d": [hashedNametag],
2459
- limit: 1
2460
- });
2461
- }
2462
- if (events.length === 0) {
2148
+ const binding = await this.nostrClient.queryBindingByNametag(nametag);
2149
+ if (!binding) {
2463
2150
  logger.debug("Nostr", `resolveNametagInfo: no binding events found for Unicity ID "${nametag}"`);
2464
2151
  return null;
2465
2152
  }
2466
- const bindingEvent = events[0];
2467
- try {
2468
- const content = JSON.parse(bindingEvent.content);
2469
- const { ProxyAddress } = await import("@unicitylabs/state-transition-sdk/lib/address/ProxyAddress");
2470
- const proxyAddr = await ProxyAddress.fromNameTag(nametag);
2471
- const proxyAddress = proxyAddr.toString();
2472
- if (content.public_key && content.l1_address) {
2473
- return {
2474
- nametag,
2475
- transportPubkey: bindingEvent.pubkey,
2476
- chainPubkey: content.public_key,
2477
- l1Address: content.l1_address,
2478
- directAddress: content.direct_address || "",
2479
- proxyAddress,
2480
- timestamp: bindingEvent.created_at * 1e3
2481
- };
2482
- }
2483
- logger.debug("Nostr", "Legacy nametag event without extended fields:", nametag);
2484
- const pubkeyTag = bindingEvent.tags.find((t) => t[0] === "pubkey");
2485
- const l1Tag = bindingEvent.tags.find((t) => t[0] === "l1");
2486
- if (pubkeyTag?.[1] && l1Tag?.[1]) {
2487
- return {
2488
- nametag,
2489
- transportPubkey: bindingEvent.pubkey,
2490
- chainPubkey: pubkeyTag[1],
2491
- l1Address: l1Tag[1],
2492
- directAddress: "",
2493
- proxyAddress,
2494
- timestamp: bindingEvent.created_at * 1e3
2495
- };
2496
- }
2497
- return {
2498
- nametag,
2499
- transportPubkey: bindingEvent.pubkey,
2500
- chainPubkey: "",
2501
- // Cannot derive from 32-byte Nostr pubkey
2502
- l1Address: "",
2503
- // Cannot derive without 33-byte pubkey
2504
- directAddress: "",
2505
- proxyAddress,
2506
- timestamp: bindingEvent.created_at * 1e3
2507
- };
2508
- } catch {
2509
- const { ProxyAddress } = await import("@unicitylabs/state-transition-sdk/lib/address/ProxyAddress");
2510
- const proxyAddr = await ProxyAddress.fromNameTag(nametag);
2511
- return {
2512
- nametag,
2513
- transportPubkey: bindingEvent.pubkey,
2514
- chainPubkey: "",
2515
- l1Address: "",
2516
- directAddress: "",
2517
- proxyAddress: proxyAddr.toString(),
2518
- timestamp: bindingEvent.created_at * 1e3
2519
- };
2520
- }
2153
+ return this.bindingInfoToPeerInfo(binding, nametag);
2521
2154
  }
2522
2155
  /**
2523
2156
  * Resolve a DIRECT://, PROXY://, or L1 address to full peer info.
2524
- * Performs reverse lookup: hash(address) query '#t' tag → parse binding event.
2525
- * Works with both new identity binding events and legacy nametag binding events.
2157
+ * Performs reverse lookup via nostr-js-sdk with first-seen-wins anti-hijacking.
2526
2158
  */
2527
2159
  async resolveAddressInfo(address) {
2528
2160
  this.ensureConnected();
2529
- const addressHash = hashAddressForTag(address);
2530
- const events = await this.queryEvents({
2531
- kinds: [EVENT_KINDS.NAMETAG_BINDING],
2532
- "#t": [addressHash],
2533
- limit: 1
2534
- });
2535
- if (events.length === 0) return null;
2536
- const bindingEvent = events[0];
2537
- try {
2538
- const content = JSON.parse(bindingEvent.content);
2539
- return {
2540
- nametag: content.nametag || void 0,
2541
- transportPubkey: bindingEvent.pubkey,
2542
- chainPubkey: content.public_key || "",
2543
- l1Address: content.l1_address || "",
2544
- directAddress: content.direct_address || "",
2545
- proxyAddress: content.proxy_address || void 0,
2546
- timestamp: bindingEvent.created_at * 1e3
2547
- };
2548
- } catch {
2549
- return {
2550
- transportPubkey: bindingEvent.pubkey,
2551
- chainPubkey: "",
2552
- l1Address: "",
2553
- directAddress: "",
2554
- timestamp: bindingEvent.created_at * 1e3
2555
- };
2161
+ const binding = await this.nostrClient.queryBindingByAddress(address);
2162
+ if (!binding) return null;
2163
+ return this.bindingInfoToPeerInfo(binding);
2164
+ }
2165
+ /**
2166
+ * Convert a BindingInfo (from nostr-js-sdk) to PeerInfo (sphere-sdk type).
2167
+ * Computes PROXY address from nametag if available.
2168
+ */
2169
+ async bindingInfoToPeerInfo(binding, nametag) {
2170
+ const nametagValue = nametag || binding.nametag;
2171
+ let proxyAddress = binding.proxyAddress;
2172
+ if (nametagValue && !proxyAddress) {
2173
+ try {
2174
+ const { ProxyAddress } = await import("@unicitylabs/state-transition-sdk/lib/address/ProxyAddress");
2175
+ const proxyAddr = await ProxyAddress.fromNameTag(nametagValue);
2176
+ proxyAddress = proxyAddr.toString();
2177
+ } catch {
2178
+ }
2556
2179
  }
2180
+ return {
2181
+ nametag: nametagValue,
2182
+ transportPubkey: binding.transportPubkey,
2183
+ chainPubkey: binding.publicKey || "",
2184
+ l1Address: binding.l1Address || "",
2185
+ directAddress: binding.directAddress || "",
2186
+ proxyAddress,
2187
+ timestamp: binding.timestamp
2188
+ };
2557
2189
  }
2558
2190
  /**
2559
2191
  * Resolve transport pubkey (Nostr pubkey) to full peer info.
@@ -2655,7 +2287,7 @@ var NostrTransportProvider = class {
2655
2287
  try {
2656
2288
  const content = JSON.parse(event.content);
2657
2289
  if (content.encrypted_nametag) {
2658
- const decrypted = await decryptNametag(
2290
+ const decrypted = await (0, import_nostr_js_sdk.decryptNametag)(
2659
2291
  content.encrypted_nametag,
2660
2292
  this.identity.privateKey
2661
2293
  );
@@ -2673,11 +2305,10 @@ var NostrTransportProvider = class {
2673
2305
  }
2674
2306
  /**
2675
2307
  * Publish identity binding event on Nostr.
2676
- * Without nametag: publishes base binding (chainPubkey, l1Address, directAddress).
2677
- * With nametag: also publishes nametag hash, proxy address, encrypted nametag for recovery.
2678
- *
2679
- * Uses kind 30078 parameterized replaceable event with d=SHA256('unicity:identity:' + nostrPubkey).
2680
- * Each HD address index has its own Nostr key → its own binding event.
2308
+ * Without nametag: publishes base binding (chainPubkey, l1Address, directAddress)
2309
+ * using a per-identity d-tag for address discovery.
2310
+ * With nametag: delegates to nostr-js-sdk's publishNametagBinding which handles
2311
+ * conflict detection (first-seen-wins), encryption, and indexed tags.
2681
2312
  *
2682
2313
  * @returns true if successful, false if nametag is taken by another pubkey
2683
2314
  */
@@ -2687,102 +2318,41 @@ var NostrTransportProvider = class {
2687
2318
  throw new SphereError("Identity not set", "NOT_INITIALIZED");
2688
2319
  }
2689
2320
  const nostrPubkey = this.getNostrPubkey();
2690
- const dTagBytes = new TextEncoder().encode("unicity:identity:" + nostrPubkey);
2691
- const dTag = import_buffer.Buffer.from(sha256(dTagBytes)).toString("hex");
2692
- const contentObj = {
2693
- public_key: chainPubkey,
2694
- l1_address: l1Address,
2695
- direct_address: directAddress
2696
- };
2697
- const tags = [
2698
- ["d", dTag],
2699
- ["t", hashAddressForTag(chainPubkey)],
2700
- ["t", hashAddressForTag(directAddress)],
2701
- ["t", hashAddressForTag(l1Address)]
2702
- ];
2703
2321
  if (nametag) {
2704
- const existing = await this.resolveNametag(nametag);
2705
- if (existing && existing !== nostrPubkey) {
2706
- logger.debug("Nostr", "Unicity ID already taken:", nametag, "- owner:", existing);
2707
- return false;
2708
- }
2709
2322
  const { ProxyAddress } = await import("@unicitylabs/state-transition-sdk/lib/address/ProxyAddress");
2710
2323
  const proxyAddr = await ProxyAddress.fromNameTag(nametag);
2711
- const proxyAddress = proxyAddr.toString();
2712
- const encryptedNametag = await encryptNametag(nametag, this.identity.privateKey);
2713
- const hashedNametag = (0, import_nostr_js_sdk.hashNametag)(nametag);
2714
- contentObj.nametag = nametag;
2715
- contentObj.encrypted_nametag = encryptedNametag;
2716
- contentObj.proxy_address = proxyAddress;
2717
- tags.push(["t", hashedNametag]);
2718
- tags.push(["t", hashAddressForTag(proxyAddress)]);
2719
- }
2720
- const content = JSON.stringify(contentObj);
2721
- const event = await this.createEvent(EVENT_KINDS.NAMETAG_BINDING, content, tags);
2722
- await this.publishEvent(event);
2723
- if (nametag) {
2724
- logger.debug("Nostr", "Published identity binding with Unicity ID:", nametag, "for pubkey:", nostrPubkey.slice(0, 16) + "...");
2725
- } else {
2726
- logger.debug("Nostr", "Published identity binding (no Unicity ID) for pubkey:", nostrPubkey.slice(0, 16) + "...");
2727
- }
2728
- return true;
2729
- }
2730
- /** @deprecated Use publishIdentityBinding instead */
2731
- async publishNametag(nametag, address) {
2732
- this.ensureReady();
2733
- const hashedNametag = (0, import_nostr_js_sdk.hashNametag)(nametag);
2734
- const event = await this.createEvent(EVENT_KINDS.NAMETAG_BINDING, address, [
2735
- ["d", hashedNametag],
2736
- ["a", address]
2737
- ]);
2738
- await this.publishEvent(event);
2739
- logger.debug("Nostr", "Published Unicity ID binding:", nametag);
2740
- }
2741
- async registerNametag(nametag, _publicKey, directAddress = "") {
2742
- this.ensureReady();
2743
- if (!this.identity) {
2744
- throw new SphereError("Identity not set", "NOT_INITIALIZED");
2745
- }
2746
- const nostrPubkey = this.getNostrPubkey();
2747
- const existing = await this.resolveNametag(nametag);
2748
- logger.debug("Nostr", "registerNametag:", nametag, "existing:", existing, "myPubkey:", nostrPubkey);
2749
- if (existing && existing !== nostrPubkey) {
2750
- logger.debug("Nostr", "Unicity ID already taken:", nametag, "- owner:", existing);
2751
- return false;
2324
+ try {
2325
+ const success2 = await this.nostrClient.publishNametagBinding(
2326
+ nametag,
2327
+ nostrPubkey,
2328
+ {
2329
+ publicKey: chainPubkey,
2330
+ l1Address,
2331
+ directAddress,
2332
+ proxyAddress: proxyAddr.toString()
2333
+ }
2334
+ );
2335
+ if (success2) {
2336
+ logger.debug("Nostr", "Published identity binding with Unicity ID:", nametag, "for pubkey:", nostrPubkey.slice(0, 16) + "...");
2337
+ }
2338
+ return success2;
2339
+ } catch (error) {
2340
+ if (error instanceof Error && error.message.includes("already claimed")) {
2341
+ logger.debug("Nostr", "Unicity ID already taken:", nametag);
2342
+ return false;
2343
+ }
2344
+ throw error;
2345
+ }
2752
2346
  }
2753
- const privateKeyHex = this.identity.privateKey;
2754
- const compressedPubkey = getPublicKey(privateKeyHex, true);
2755
- const l1Address = publicKeyToAddress(compressedPubkey, "alpha");
2756
- const encryptedNametag = await encryptNametag(nametag, privateKeyHex);
2757
- const { ProxyAddress } = await import("@unicitylabs/state-transition-sdk/lib/address/ProxyAddress");
2758
- const proxyAddr = await ProxyAddress.fromNameTag(nametag);
2759
- const proxyAddress = proxyAddr.toString();
2760
- const hashedNametag = (0, import_nostr_js_sdk.hashNametag)(nametag);
2761
- const content = JSON.stringify({
2762
- nametag_hash: hashedNametag,
2763
- address: nostrPubkey,
2764
- verified: Date.now(),
2765
- // Extended fields for nametag recovery and address lookup
2766
- encrypted_nametag: encryptedNametag,
2767
- public_key: compressedPubkey,
2768
- l1_address: l1Address,
2769
- direct_address: directAddress,
2770
- proxy_address: proxyAddress
2347
+ const success = await this.nostrClient.publishIdentityBinding({
2348
+ publicKey: chainPubkey,
2349
+ l1Address,
2350
+ directAddress
2771
2351
  });
2772
- const tags = [
2773
- ["d", hashedNametag],
2774
- ["nametag", hashedNametag],
2775
- ["t", hashedNametag],
2776
- ["t", hashAddressForTag(directAddress)],
2777
- ["t", hashAddressForTag(proxyAddress)],
2778
- ["address", nostrPubkey],
2779
- ["pubkey", compressedPubkey],
2780
- ["l1", l1Address]
2781
- ];
2782
- const event = await this.createEvent(EVENT_KINDS.NAMETAG_BINDING, content, tags);
2783
- await this.publishEvent(event);
2784
- logger.debug("Nostr", "Registered Unicity ID:", nametag, "for pubkey:", nostrPubkey.slice(0, 16) + "...", "l1:", l1Address.slice(0, 12) + "...");
2785
- return true;
2352
+ if (success) {
2353
+ logger.debug("Nostr", "Published identity binding (no Unicity ID) for pubkey:", nostrPubkey.slice(0, 16) + "...");
2354
+ }
2355
+ return success;
2786
2356
  }
2787
2357
  // Track broadcast subscriptions
2788
2358
  broadcastSubscriptions = /* @__PURE__ */ new Map();
@@ -4064,6 +3634,130 @@ var InMemoryIpfsStatePersistence = class {
4064
3634
  }
4065
3635
  };
4066
3636
 
3637
+ // node_modules/@noble/hashes/hmac.js
3638
+ var _HMAC = class {
3639
+ oHash;
3640
+ iHash;
3641
+ blockLen;
3642
+ outputLen;
3643
+ finished = false;
3644
+ destroyed = false;
3645
+ constructor(hash, key) {
3646
+ ahash(hash);
3647
+ abytes(key, void 0, "key");
3648
+ this.iHash = hash.create();
3649
+ if (typeof this.iHash.update !== "function")
3650
+ throw new Error("Expected instance of class which extends utils.Hash");
3651
+ this.blockLen = this.iHash.blockLen;
3652
+ this.outputLen = this.iHash.outputLen;
3653
+ const blockLen = this.blockLen;
3654
+ const pad = new Uint8Array(blockLen);
3655
+ pad.set(key.length > blockLen ? hash.create().update(key).digest() : key);
3656
+ for (let i = 0; i < pad.length; i++)
3657
+ pad[i] ^= 54;
3658
+ this.iHash.update(pad);
3659
+ this.oHash = hash.create();
3660
+ for (let i = 0; i < pad.length; i++)
3661
+ pad[i] ^= 54 ^ 92;
3662
+ this.oHash.update(pad);
3663
+ clean(pad);
3664
+ }
3665
+ update(buf) {
3666
+ aexists(this);
3667
+ this.iHash.update(buf);
3668
+ return this;
3669
+ }
3670
+ digestInto(out) {
3671
+ aexists(this);
3672
+ abytes(out, this.outputLen, "output");
3673
+ this.finished = true;
3674
+ this.iHash.digestInto(out);
3675
+ this.oHash.update(out);
3676
+ this.oHash.digestInto(out);
3677
+ this.destroy();
3678
+ }
3679
+ digest() {
3680
+ const out = new Uint8Array(this.oHash.outputLen);
3681
+ this.digestInto(out);
3682
+ return out;
3683
+ }
3684
+ _cloneInto(to) {
3685
+ to ||= Object.create(Object.getPrototypeOf(this), {});
3686
+ const { oHash, iHash, finished, destroyed, blockLen, outputLen } = this;
3687
+ to = to;
3688
+ to.finished = finished;
3689
+ to.destroyed = destroyed;
3690
+ to.blockLen = blockLen;
3691
+ to.outputLen = outputLen;
3692
+ to.oHash = oHash._cloneInto(to.oHash);
3693
+ to.iHash = iHash._cloneInto(to.iHash);
3694
+ return to;
3695
+ }
3696
+ clone() {
3697
+ return this._cloneInto();
3698
+ }
3699
+ destroy() {
3700
+ this.destroyed = true;
3701
+ this.oHash.destroy();
3702
+ this.iHash.destroy();
3703
+ }
3704
+ };
3705
+ var hmac = (hash, key, message) => new _HMAC(hash, key).update(message).digest();
3706
+ hmac.create = (hash, key) => new _HMAC(hash, key);
3707
+
3708
+ // node_modules/@noble/hashes/hkdf.js
3709
+ function extract(hash, ikm, salt) {
3710
+ ahash(hash);
3711
+ if (salt === void 0)
3712
+ salt = new Uint8Array(hash.outputLen);
3713
+ return hmac(hash, salt, ikm);
3714
+ }
3715
+ var HKDF_COUNTER = /* @__PURE__ */ Uint8Array.of(0);
3716
+ var EMPTY_BUFFER = /* @__PURE__ */ Uint8Array.of();
3717
+ function expand(hash, prk, info, length = 32) {
3718
+ ahash(hash);
3719
+ anumber(length, "length");
3720
+ const olen = hash.outputLen;
3721
+ if (length > 255 * olen)
3722
+ throw new Error("Length must be <= 255*HashLen");
3723
+ const blocks = Math.ceil(length / olen);
3724
+ if (info === void 0)
3725
+ info = EMPTY_BUFFER;
3726
+ else
3727
+ abytes(info, void 0, "info");
3728
+ const okm = new Uint8Array(blocks * olen);
3729
+ const HMAC = hmac.create(hash, prk);
3730
+ const HMACTmp = HMAC._cloneInto();
3731
+ const T = new Uint8Array(HMAC.outputLen);
3732
+ for (let counter = 0; counter < blocks; counter++) {
3733
+ HKDF_COUNTER[0] = counter + 1;
3734
+ HMACTmp.update(counter === 0 ? EMPTY_BUFFER : T).update(info).update(HKDF_COUNTER).digestInto(T);
3735
+ okm.set(T, olen * counter);
3736
+ HMAC._cloneInto(HMACTmp);
3737
+ }
3738
+ HMAC.destroy();
3739
+ HMACTmp.destroy();
3740
+ clean(T, HKDF_COUNTER);
3741
+ return okm.slice(0, length);
3742
+ }
3743
+ var hkdf = (hash, ikm, salt, info, length) => expand(hash, extract(hash, ikm, salt), info, length);
3744
+
3745
+ // core/crypto.ts
3746
+ var bip39 = __toESM(require("bip39"), 1);
3747
+ var import_crypto_js = __toESM(require("crypto-js"), 1);
3748
+ var import_elliptic = __toESM(require("elliptic"), 1);
3749
+ var ec = new import_elliptic.default.ec("secp256k1");
3750
+ var CURVE_ORDER = BigInt(
3751
+ "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"
3752
+ );
3753
+ function hexToBytes2(hex) {
3754
+ const matches = hex.match(/../g);
3755
+ if (!matches) {
3756
+ return new Uint8Array(0);
3757
+ }
3758
+ return Uint8Array.from(matches.map((x) => parseInt(x, 16)));
3759
+ }
3760
+
4067
3761
  // impl/shared/ipfs/ipns-key-derivation.ts
4068
3762
  var IPNS_HKDF_INFO = "ipfs-storage-ed25519-v1";
4069
3763
  var libp2pCryptoModule = null;