@unicitylabs/sphere-sdk 0.5.7 → 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.
@@ -1325,114 +1325,6 @@ var oidNist = (suffix) => ({
1325
1325
  oid: Uint8Array.from([6, 9, 96, 134, 72, 1, 101, 3, 4, 2, suffix])
1326
1326
  });
1327
1327
 
1328
- // node_modules/@noble/hashes/hmac.js
1329
- var _HMAC = class {
1330
- oHash;
1331
- iHash;
1332
- blockLen;
1333
- outputLen;
1334
- finished = false;
1335
- destroyed = false;
1336
- constructor(hash, key) {
1337
- ahash(hash);
1338
- abytes(key, void 0, "key");
1339
- this.iHash = hash.create();
1340
- if (typeof this.iHash.update !== "function")
1341
- throw new Error("Expected instance of class which extends utils.Hash");
1342
- this.blockLen = this.iHash.blockLen;
1343
- this.outputLen = this.iHash.outputLen;
1344
- const blockLen = this.blockLen;
1345
- const pad = new Uint8Array(blockLen);
1346
- pad.set(key.length > blockLen ? hash.create().update(key).digest() : key);
1347
- for (let i = 0; i < pad.length; i++)
1348
- pad[i] ^= 54;
1349
- this.iHash.update(pad);
1350
- this.oHash = hash.create();
1351
- for (let i = 0; i < pad.length; i++)
1352
- pad[i] ^= 54 ^ 92;
1353
- this.oHash.update(pad);
1354
- clean(pad);
1355
- }
1356
- update(buf) {
1357
- aexists(this);
1358
- this.iHash.update(buf);
1359
- return this;
1360
- }
1361
- digestInto(out) {
1362
- aexists(this);
1363
- abytes(out, this.outputLen, "output");
1364
- this.finished = true;
1365
- this.iHash.digestInto(out);
1366
- this.oHash.update(out);
1367
- this.oHash.digestInto(out);
1368
- this.destroy();
1369
- }
1370
- digest() {
1371
- const out = new Uint8Array(this.oHash.outputLen);
1372
- this.digestInto(out);
1373
- return out;
1374
- }
1375
- _cloneInto(to) {
1376
- to ||= Object.create(Object.getPrototypeOf(this), {});
1377
- const { oHash, iHash, finished, destroyed, blockLen, outputLen } = this;
1378
- to = to;
1379
- to.finished = finished;
1380
- to.destroyed = destroyed;
1381
- to.blockLen = blockLen;
1382
- to.outputLen = outputLen;
1383
- to.oHash = oHash._cloneInto(to.oHash);
1384
- to.iHash = iHash._cloneInto(to.iHash);
1385
- return to;
1386
- }
1387
- clone() {
1388
- return this._cloneInto();
1389
- }
1390
- destroy() {
1391
- this.destroyed = true;
1392
- this.oHash.destroy();
1393
- this.iHash.destroy();
1394
- }
1395
- };
1396
- var hmac = (hash, key, message) => new _HMAC(hash, key).update(message).digest();
1397
- hmac.create = (hash, key) => new _HMAC(hash, key);
1398
-
1399
- // node_modules/@noble/hashes/hkdf.js
1400
- function extract(hash, ikm, salt) {
1401
- ahash(hash);
1402
- if (salt === void 0)
1403
- salt = new Uint8Array(hash.outputLen);
1404
- return hmac(hash, salt, ikm);
1405
- }
1406
- var HKDF_COUNTER = /* @__PURE__ */ Uint8Array.of(0);
1407
- var EMPTY_BUFFER = /* @__PURE__ */ Uint8Array.of();
1408
- function expand(hash, prk, info, length = 32) {
1409
- ahash(hash);
1410
- anumber(length, "length");
1411
- const olen = hash.outputLen;
1412
- if (length > 255 * olen)
1413
- throw new Error("Length must be <= 255*HashLen");
1414
- const blocks = Math.ceil(length / olen);
1415
- if (info === void 0)
1416
- info = EMPTY_BUFFER;
1417
- else
1418
- abytes(info, void 0, "info");
1419
- const okm = new Uint8Array(blocks * olen);
1420
- const HMAC = hmac.create(hash, prk);
1421
- const HMACTmp = HMAC._cloneInto();
1422
- const T = new Uint8Array(HMAC.outputLen);
1423
- for (let counter = 0; counter < blocks; counter++) {
1424
- HKDF_COUNTER[0] = counter + 1;
1425
- HMACTmp.update(counter === 0 ? EMPTY_BUFFER : T).update(info).update(HKDF_COUNTER).digestInto(T);
1426
- okm.set(T, olen * counter);
1427
- HMAC._cloneInto(HMACTmp);
1428
- }
1429
- HMAC.destroy();
1430
- HMACTmp.destroy();
1431
- clean(T, HKDF_COUNTER);
1432
- return okm.slice(0, length);
1433
- }
1434
- var hkdf = (hash, ikm, salt, info, length) => expand(hash, extract(hash, ikm, salt), info, length);
1435
-
1436
1328
  // node_modules/@noble/hashes/_md.js
1437
1329
  function Chi(a, b, c) {
1438
1330
  return a & b ^ ~a & c;
@@ -1704,129 +1596,13 @@ import {
1704
1596
  NIP44,
1705
1597
  Event as NostrEventClass,
1706
1598
  EventKinds,
1707
- hashNametag,
1599
+ decryptNametag,
1708
1600
  NostrClient,
1709
1601
  Filter,
1710
1602
  isChatMessage,
1711
1603
  isReadReceipt
1712
1604
  } from "@unicitylabs/nostr-js-sdk";
1713
1605
 
1714
- // core/crypto.ts
1715
- import * as bip39 from "bip39";
1716
- import CryptoJS from "crypto-js";
1717
- import elliptic from "elliptic";
1718
-
1719
- // core/bech32.ts
1720
- var CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
1721
- var GENERATOR = [996825010, 642813549, 513874426, 1027748829, 705979059];
1722
- function convertBits(data, fromBits, toBits, pad) {
1723
- let acc = 0;
1724
- let bits = 0;
1725
- const ret = [];
1726
- const maxv = (1 << toBits) - 1;
1727
- for (let i = 0; i < data.length; i++) {
1728
- const value = data[i];
1729
- if (value < 0 || value >> fromBits !== 0) return null;
1730
- acc = acc << fromBits | value;
1731
- bits += fromBits;
1732
- while (bits >= toBits) {
1733
- bits -= toBits;
1734
- ret.push(acc >> bits & maxv);
1735
- }
1736
- }
1737
- if (pad) {
1738
- if (bits > 0) {
1739
- ret.push(acc << toBits - bits & maxv);
1740
- }
1741
- } else if (bits >= fromBits || acc << toBits - bits & maxv) {
1742
- return null;
1743
- }
1744
- return ret;
1745
- }
1746
- function hrpExpand(hrp) {
1747
- const ret = [];
1748
- for (let i = 0; i < hrp.length; i++) ret.push(hrp.charCodeAt(i) >> 5);
1749
- ret.push(0);
1750
- for (let i = 0; i < hrp.length; i++) ret.push(hrp.charCodeAt(i) & 31);
1751
- return ret;
1752
- }
1753
- function bech32Polymod(values) {
1754
- let chk = 1;
1755
- for (let p = 0; p < values.length; p++) {
1756
- const top = chk >> 25;
1757
- chk = (chk & 33554431) << 5 ^ values[p];
1758
- for (let i = 0; i < 5; i++) {
1759
- if (top >> i & 1) chk ^= GENERATOR[i];
1760
- }
1761
- }
1762
- return chk;
1763
- }
1764
- function bech32Checksum(hrp, data) {
1765
- const values = hrpExpand(hrp).concat(data).concat([0, 0, 0, 0, 0, 0]);
1766
- const mod = bech32Polymod(values) ^ 1;
1767
- const ret = [];
1768
- for (let p = 0; p < 6; p++) {
1769
- ret.push(mod >> 5 * (5 - p) & 31);
1770
- }
1771
- return ret;
1772
- }
1773
- function encodeBech32(hrp, version, program) {
1774
- if (version < 0 || version > 16) {
1775
- throw new SphereError("Invalid witness version", "VALIDATION_ERROR");
1776
- }
1777
- const converted = convertBits(Array.from(program), 8, 5, true);
1778
- if (!converted) {
1779
- throw new SphereError("Failed to convert bits", "VALIDATION_ERROR");
1780
- }
1781
- const data = [version].concat(converted);
1782
- const checksum = bech32Checksum(hrp, data);
1783
- const combined = data.concat(checksum);
1784
- let out = hrp + "1";
1785
- for (let i = 0; i < combined.length; i++) {
1786
- out += CHARSET[combined[i]];
1787
- }
1788
- return out;
1789
- }
1790
-
1791
- // core/crypto.ts
1792
- var ec = new elliptic.ec("secp256k1");
1793
- var CURVE_ORDER = BigInt(
1794
- "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"
1795
- );
1796
- function getPublicKey(privateKey, compressed = true) {
1797
- const keyPair = ec.keyFromPrivate(privateKey, "hex");
1798
- return keyPair.getPublic(compressed, "hex");
1799
- }
1800
- function sha2562(data, inputEncoding = "hex") {
1801
- const parsed = inputEncoding === "hex" ? CryptoJS.enc.Hex.parse(data) : CryptoJS.enc.Utf8.parse(data);
1802
- return CryptoJS.SHA256(parsed).toString();
1803
- }
1804
- function ripemd160(data, inputEncoding = "hex") {
1805
- const parsed = inputEncoding === "hex" ? CryptoJS.enc.Hex.parse(data) : CryptoJS.enc.Utf8.parse(data);
1806
- return CryptoJS.RIPEMD160(parsed).toString();
1807
- }
1808
- function hash160(data) {
1809
- const sha = sha2562(data, "hex");
1810
- return ripemd160(sha, "hex");
1811
- }
1812
- function hash160ToBytes(hash160Hex) {
1813
- const matches = hash160Hex.match(/../g);
1814
- if (!matches) return new Uint8Array(0);
1815
- return Uint8Array.from(matches.map((x) => parseInt(x, 16)));
1816
- }
1817
- function publicKeyToAddress(publicKey, prefix = "alpha", witnessVersion = 0) {
1818
- const pubKeyHash = hash160(publicKey);
1819
- const programBytes = hash160ToBytes(pubKeyHash);
1820
- return encodeBech32(prefix, witnessVersion, programBytes);
1821
- }
1822
- function hexToBytes2(hex) {
1823
- const matches = hex.match(/../g);
1824
- if (!matches) {
1825
- return new Uint8Array(0);
1826
- }
1827
- return Uint8Array.from(matches.map((x) => parseInt(x, 16)));
1828
- }
1829
-
1830
1606
  // transport/websocket.ts
1831
1607
  var WebSocketReadyState = {
1832
1608
  CONNECTING: 0,
@@ -1849,63 +1625,6 @@ function defaultUUIDGenerator() {
1849
1625
  var COMPOSING_INDICATOR_KIND = 25050;
1850
1626
  var TIMESTAMP_RANDOMIZATION = 2 * 24 * 60 * 60;
1851
1627
  var EVENT_KINDS = NOSTR_EVENT_KINDS;
1852
- function hashAddressForTag(address) {
1853
- const bytes = new TextEncoder().encode("unicity:address:" + address);
1854
- return Buffer2.from(sha256(bytes)).toString("hex");
1855
- }
1856
- function deriveNametagEncryptionKey(privateKeyHex) {
1857
- const privateKeyBytes = Buffer2.from(privateKeyHex, "hex");
1858
- const saltInput = new TextEncoder().encode("sphere-nametag-salt");
1859
- const salt = sha256(saltInput);
1860
- const info = new TextEncoder().encode("nametag-encryption");
1861
- return hkdf(sha256, privateKeyBytes, salt, info, 32);
1862
- }
1863
- async function encryptNametag(nametag, privateKeyHex) {
1864
- const key = deriveNametagEncryptionKey(privateKeyHex);
1865
- const iv = crypto.getRandomValues(new Uint8Array(12));
1866
- const encoder = new TextEncoder();
1867
- const data = encoder.encode(nametag);
1868
- const cryptoKey = await crypto.subtle.importKey(
1869
- "raw",
1870
- new Uint8Array(key).buffer,
1871
- { name: "AES-GCM" },
1872
- false,
1873
- ["encrypt"]
1874
- );
1875
- const encrypted = await crypto.subtle.encrypt(
1876
- { name: "AES-GCM", iv: new Uint8Array(iv).buffer },
1877
- cryptoKey,
1878
- new Uint8Array(data).buffer
1879
- );
1880
- const combined = new Uint8Array(iv.length + encrypted.byteLength);
1881
- combined.set(iv, 0);
1882
- combined.set(new Uint8Array(encrypted), iv.length);
1883
- return Buffer2.from(combined).toString("base64");
1884
- }
1885
- async function decryptNametag(encryptedBase64, privateKeyHex) {
1886
- try {
1887
- const key = deriveNametagEncryptionKey(privateKeyHex);
1888
- const combined = Buffer2.from(encryptedBase64, "base64");
1889
- const iv = combined.slice(0, 12);
1890
- const ciphertext = combined.slice(12);
1891
- const cryptoKey = await crypto.subtle.importKey(
1892
- "raw",
1893
- new Uint8Array(key).buffer,
1894
- { name: "AES-GCM" },
1895
- false,
1896
- ["decrypt"]
1897
- );
1898
- const decrypted = await crypto.subtle.decrypt(
1899
- { name: "AES-GCM", iv: new Uint8Array(iv).buffer },
1900
- cryptoKey,
1901
- new Uint8Array(ciphertext).buffer
1902
- );
1903
- const decoder = new TextDecoder();
1904
- return decoder.decode(decrypted);
1905
- } catch {
1906
- return null;
1907
- }
1908
- }
1909
1628
  var NostrTransportProvider = class {
1910
1629
  id = "nostr";
1911
1630
  name = "Nostr Transport";
@@ -2374,138 +2093,51 @@ var NostrTransportProvider = class {
2374
2093
  }
2375
2094
  async resolveNametag(nametag) {
2376
2095
  this.ensureConnected();
2377
- const hashedNametag = hashNametag(nametag);
2378
- let events = await this.queryEvents({
2379
- kinds: [EVENT_KINDS.NAMETAG_BINDING],
2380
- "#t": [hashedNametag],
2381
- limit: 1
2382
- });
2383
- if (events.length === 0) {
2384
- events = await this.queryEvents({
2385
- kinds: [EVENT_KINDS.NAMETAG_BINDING],
2386
- "#d": [hashedNametag],
2387
- limit: 1
2388
- });
2389
- }
2390
- if (events.length === 0) return null;
2391
- const bindingEvent = events[0];
2392
- if (bindingEvent.pubkey) {
2393
- return bindingEvent.pubkey;
2394
- }
2395
- const pubkeyTag = bindingEvent.tags.find((t) => t[0] === "p");
2396
- if (pubkeyTag?.[1]) return pubkeyTag[1];
2397
- return null;
2096
+ return this.nostrClient.queryPubkeyByNametag(nametag);
2398
2097
  }
2399
2098
  async resolveNametagInfo(nametag) {
2400
2099
  this.ensureConnected();
2401
- const hashedNametag = hashNametag(nametag);
2402
- let events = await this.queryEvents({
2403
- kinds: [EVENT_KINDS.NAMETAG_BINDING],
2404
- "#t": [hashedNametag],
2405
- limit: 1
2406
- });
2407
- if (events.length === 0) {
2408
- events = await this.queryEvents({
2409
- kinds: [EVENT_KINDS.NAMETAG_BINDING],
2410
- "#d": [hashedNametag],
2411
- limit: 1
2412
- });
2413
- }
2414
- if (events.length === 0) {
2100
+ const binding = await this.nostrClient.queryBindingByNametag(nametag);
2101
+ if (!binding) {
2415
2102
  logger.debug("Nostr", `resolveNametagInfo: no binding events found for Unicity ID "${nametag}"`);
2416
2103
  return null;
2417
2104
  }
2418
- const bindingEvent = events[0];
2419
- try {
2420
- const content = JSON.parse(bindingEvent.content);
2421
- const { ProxyAddress } = await import("@unicitylabs/state-transition-sdk/lib/address/ProxyAddress");
2422
- const proxyAddr = await ProxyAddress.fromNameTag(nametag);
2423
- const proxyAddress = proxyAddr.toString();
2424
- if (content.public_key && content.l1_address) {
2425
- return {
2426
- nametag,
2427
- transportPubkey: bindingEvent.pubkey,
2428
- chainPubkey: content.public_key,
2429
- l1Address: content.l1_address,
2430
- directAddress: content.direct_address || "",
2431
- proxyAddress,
2432
- timestamp: bindingEvent.created_at * 1e3
2433
- };
2434
- }
2435
- logger.debug("Nostr", "Legacy nametag event without extended fields:", nametag);
2436
- const pubkeyTag = bindingEvent.tags.find((t) => t[0] === "pubkey");
2437
- const l1Tag = bindingEvent.tags.find((t) => t[0] === "l1");
2438
- if (pubkeyTag?.[1] && l1Tag?.[1]) {
2439
- return {
2440
- nametag,
2441
- transportPubkey: bindingEvent.pubkey,
2442
- chainPubkey: pubkeyTag[1],
2443
- l1Address: l1Tag[1],
2444
- directAddress: "",
2445
- proxyAddress,
2446
- timestamp: bindingEvent.created_at * 1e3
2447
- };
2448
- }
2449
- return {
2450
- nametag,
2451
- transportPubkey: bindingEvent.pubkey,
2452
- chainPubkey: "",
2453
- // Cannot derive from 32-byte Nostr pubkey
2454
- l1Address: "",
2455
- // Cannot derive without 33-byte pubkey
2456
- directAddress: "",
2457
- proxyAddress,
2458
- timestamp: bindingEvent.created_at * 1e3
2459
- };
2460
- } catch {
2461
- const { ProxyAddress } = await import("@unicitylabs/state-transition-sdk/lib/address/ProxyAddress");
2462
- const proxyAddr = await ProxyAddress.fromNameTag(nametag);
2463
- return {
2464
- nametag,
2465
- transportPubkey: bindingEvent.pubkey,
2466
- chainPubkey: "",
2467
- l1Address: "",
2468
- directAddress: "",
2469
- proxyAddress: proxyAddr.toString(),
2470
- timestamp: bindingEvent.created_at * 1e3
2471
- };
2472
- }
2105
+ return this.bindingInfoToPeerInfo(binding, nametag);
2473
2106
  }
2474
2107
  /**
2475
2108
  * Resolve a DIRECT://, PROXY://, or L1 address to full peer info.
2476
- * Performs reverse lookup: hash(address) query '#t' tag → parse binding event.
2477
- * Works with both new identity binding events and legacy nametag binding events.
2109
+ * Performs reverse lookup via nostr-js-sdk with first-seen-wins anti-hijacking.
2478
2110
  */
2479
2111
  async resolveAddressInfo(address) {
2480
2112
  this.ensureConnected();
2481
- const addressHash = hashAddressForTag(address);
2482
- const events = await this.queryEvents({
2483
- kinds: [EVENT_KINDS.NAMETAG_BINDING],
2484
- "#t": [addressHash],
2485
- limit: 1
2486
- });
2487
- if (events.length === 0) return null;
2488
- const bindingEvent = events[0];
2489
- try {
2490
- const content = JSON.parse(bindingEvent.content);
2491
- return {
2492
- nametag: content.nametag || void 0,
2493
- transportPubkey: bindingEvent.pubkey,
2494
- chainPubkey: content.public_key || "",
2495
- l1Address: content.l1_address || "",
2496
- directAddress: content.direct_address || "",
2497
- proxyAddress: content.proxy_address || void 0,
2498
- timestamp: bindingEvent.created_at * 1e3
2499
- };
2500
- } catch {
2501
- return {
2502
- transportPubkey: bindingEvent.pubkey,
2503
- chainPubkey: "",
2504
- l1Address: "",
2505
- directAddress: "",
2506
- timestamp: bindingEvent.created_at * 1e3
2507
- };
2113
+ const binding = await this.nostrClient.queryBindingByAddress(address);
2114
+ if (!binding) return null;
2115
+ return this.bindingInfoToPeerInfo(binding);
2116
+ }
2117
+ /**
2118
+ * Convert a BindingInfo (from nostr-js-sdk) to PeerInfo (sphere-sdk type).
2119
+ * Computes PROXY address from nametag if available.
2120
+ */
2121
+ async bindingInfoToPeerInfo(binding, nametag) {
2122
+ const nametagValue = nametag || binding.nametag;
2123
+ let proxyAddress = binding.proxyAddress;
2124
+ if (nametagValue && !proxyAddress) {
2125
+ try {
2126
+ const { ProxyAddress } = await import("@unicitylabs/state-transition-sdk/lib/address/ProxyAddress");
2127
+ const proxyAddr = await ProxyAddress.fromNameTag(nametagValue);
2128
+ proxyAddress = proxyAddr.toString();
2129
+ } catch {
2130
+ }
2508
2131
  }
2132
+ return {
2133
+ nametag: nametagValue,
2134
+ transportPubkey: binding.transportPubkey,
2135
+ chainPubkey: binding.publicKey || "",
2136
+ l1Address: binding.l1Address || "",
2137
+ directAddress: binding.directAddress || "",
2138
+ proxyAddress,
2139
+ timestamp: binding.timestamp
2140
+ };
2509
2141
  }
2510
2142
  /**
2511
2143
  * Resolve transport pubkey (Nostr pubkey) to full peer info.
@@ -2625,11 +2257,10 @@ var NostrTransportProvider = class {
2625
2257
  }
2626
2258
  /**
2627
2259
  * Publish identity binding event on Nostr.
2628
- * Without nametag: publishes base binding (chainPubkey, l1Address, directAddress).
2629
- * With nametag: also publishes nametag hash, proxy address, encrypted nametag for recovery.
2630
- *
2631
- * Uses kind 30078 parameterized replaceable event with d=SHA256('unicity:identity:' + nostrPubkey).
2632
- * Each HD address index has its own Nostr key → its own binding event.
2260
+ * Without nametag: publishes base binding (chainPubkey, l1Address, directAddress)
2261
+ * using a per-identity d-tag for address discovery.
2262
+ * With nametag: delegates to nostr-js-sdk's publishNametagBinding which handles
2263
+ * conflict detection (first-seen-wins), encryption, and indexed tags.
2633
2264
  *
2634
2265
  * @returns true if successful, false if nametag is taken by another pubkey
2635
2266
  */
@@ -2639,102 +2270,41 @@ var NostrTransportProvider = class {
2639
2270
  throw new SphereError("Identity not set", "NOT_INITIALIZED");
2640
2271
  }
2641
2272
  const nostrPubkey = this.getNostrPubkey();
2642
- const dTagBytes = new TextEncoder().encode("unicity:identity:" + nostrPubkey);
2643
- const dTag = Buffer2.from(sha256(dTagBytes)).toString("hex");
2644
- const contentObj = {
2645
- public_key: chainPubkey,
2646
- l1_address: l1Address,
2647
- direct_address: directAddress
2648
- };
2649
- const tags = [
2650
- ["d", dTag],
2651
- ["t", hashAddressForTag(chainPubkey)],
2652
- ["t", hashAddressForTag(directAddress)],
2653
- ["t", hashAddressForTag(l1Address)]
2654
- ];
2655
2273
  if (nametag) {
2656
- const existing = await this.resolveNametag(nametag);
2657
- if (existing && existing !== nostrPubkey) {
2658
- logger.debug("Nostr", "Unicity ID already taken:", nametag, "- owner:", existing);
2659
- return false;
2660
- }
2661
2274
  const { ProxyAddress } = await import("@unicitylabs/state-transition-sdk/lib/address/ProxyAddress");
2662
2275
  const proxyAddr = await ProxyAddress.fromNameTag(nametag);
2663
- const proxyAddress = proxyAddr.toString();
2664
- const encryptedNametag = await encryptNametag(nametag, this.identity.privateKey);
2665
- const hashedNametag = hashNametag(nametag);
2666
- contentObj.nametag = nametag;
2667
- contentObj.encrypted_nametag = encryptedNametag;
2668
- contentObj.proxy_address = proxyAddress;
2669
- tags.push(["t", hashedNametag]);
2670
- tags.push(["t", hashAddressForTag(proxyAddress)]);
2671
- }
2672
- const content = JSON.stringify(contentObj);
2673
- const event = await this.createEvent(EVENT_KINDS.NAMETAG_BINDING, content, tags);
2674
- await this.publishEvent(event);
2675
- if (nametag) {
2676
- logger.debug("Nostr", "Published identity binding with Unicity ID:", nametag, "for pubkey:", nostrPubkey.slice(0, 16) + "...");
2677
- } else {
2678
- logger.debug("Nostr", "Published identity binding (no Unicity ID) for pubkey:", nostrPubkey.slice(0, 16) + "...");
2679
- }
2680
- return true;
2681
- }
2682
- /** @deprecated Use publishIdentityBinding instead */
2683
- async publishNametag(nametag, address) {
2684
- this.ensureReady();
2685
- const hashedNametag = hashNametag(nametag);
2686
- const event = await this.createEvent(EVENT_KINDS.NAMETAG_BINDING, address, [
2687
- ["d", hashedNametag],
2688
- ["a", address]
2689
- ]);
2690
- await this.publishEvent(event);
2691
- logger.debug("Nostr", "Published Unicity ID binding:", nametag);
2692
- }
2693
- async registerNametag(nametag, _publicKey, directAddress = "") {
2694
- this.ensureReady();
2695
- if (!this.identity) {
2696
- throw new SphereError("Identity not set", "NOT_INITIALIZED");
2697
- }
2698
- const nostrPubkey = this.getNostrPubkey();
2699
- const existing = await this.resolveNametag(nametag);
2700
- logger.debug("Nostr", "registerNametag:", nametag, "existing:", existing, "myPubkey:", nostrPubkey);
2701
- if (existing && existing !== nostrPubkey) {
2702
- logger.debug("Nostr", "Unicity ID already taken:", nametag, "- owner:", existing);
2703
- return false;
2276
+ try {
2277
+ const success2 = await this.nostrClient.publishNametagBinding(
2278
+ nametag,
2279
+ nostrPubkey,
2280
+ {
2281
+ publicKey: chainPubkey,
2282
+ l1Address,
2283
+ directAddress,
2284
+ proxyAddress: proxyAddr.toString()
2285
+ }
2286
+ );
2287
+ if (success2) {
2288
+ logger.debug("Nostr", "Published identity binding with Unicity ID:", nametag, "for pubkey:", nostrPubkey.slice(0, 16) + "...");
2289
+ }
2290
+ return success2;
2291
+ } catch (error) {
2292
+ if (error instanceof Error && error.message.includes("already claimed")) {
2293
+ logger.debug("Nostr", "Unicity ID already taken:", nametag);
2294
+ return false;
2295
+ }
2296
+ throw error;
2297
+ }
2704
2298
  }
2705
- const privateKeyHex = this.identity.privateKey;
2706
- const compressedPubkey = getPublicKey(privateKeyHex, true);
2707
- const l1Address = publicKeyToAddress(compressedPubkey, "alpha");
2708
- const encryptedNametag = await encryptNametag(nametag, privateKeyHex);
2709
- const { ProxyAddress } = await import("@unicitylabs/state-transition-sdk/lib/address/ProxyAddress");
2710
- const proxyAddr = await ProxyAddress.fromNameTag(nametag);
2711
- const proxyAddress = proxyAddr.toString();
2712
- const hashedNametag = hashNametag(nametag);
2713
- const content = JSON.stringify({
2714
- nametag_hash: hashedNametag,
2715
- address: nostrPubkey,
2716
- verified: Date.now(),
2717
- // Extended fields for nametag recovery and address lookup
2718
- encrypted_nametag: encryptedNametag,
2719
- public_key: compressedPubkey,
2720
- l1_address: l1Address,
2721
- direct_address: directAddress,
2722
- proxy_address: proxyAddress
2299
+ const success = await this.nostrClient.publishIdentityBinding({
2300
+ publicKey: chainPubkey,
2301
+ l1Address,
2302
+ directAddress
2723
2303
  });
2724
- const tags = [
2725
- ["d", hashedNametag],
2726
- ["nametag", hashedNametag],
2727
- ["t", hashedNametag],
2728
- ["t", hashAddressForTag(directAddress)],
2729
- ["t", hashAddressForTag(proxyAddress)],
2730
- ["address", nostrPubkey],
2731
- ["pubkey", compressedPubkey],
2732
- ["l1", l1Address]
2733
- ];
2734
- const event = await this.createEvent(EVENT_KINDS.NAMETAG_BINDING, content, tags);
2735
- await this.publishEvent(event);
2736
- logger.debug("Nostr", "Registered Unicity ID:", nametag, "for pubkey:", nostrPubkey.slice(0, 16) + "...", "l1:", l1Address.slice(0, 12) + "...");
2737
- return true;
2304
+ if (success) {
2305
+ logger.debug("Nostr", "Published identity binding (no Unicity ID) for pubkey:", nostrPubkey.slice(0, 16) + "...");
2306
+ }
2307
+ return success;
2738
2308
  }
2739
2309
  // Track broadcast subscriptions
2740
2310
  broadcastSubscriptions = /* @__PURE__ */ new Map();
@@ -4016,6 +3586,130 @@ var InMemoryIpfsStatePersistence = class {
4016
3586
  }
4017
3587
  };
4018
3588
 
3589
+ // node_modules/@noble/hashes/hmac.js
3590
+ var _HMAC = class {
3591
+ oHash;
3592
+ iHash;
3593
+ blockLen;
3594
+ outputLen;
3595
+ finished = false;
3596
+ destroyed = false;
3597
+ constructor(hash, key) {
3598
+ ahash(hash);
3599
+ abytes(key, void 0, "key");
3600
+ this.iHash = hash.create();
3601
+ if (typeof this.iHash.update !== "function")
3602
+ throw new Error("Expected instance of class which extends utils.Hash");
3603
+ this.blockLen = this.iHash.blockLen;
3604
+ this.outputLen = this.iHash.outputLen;
3605
+ const blockLen = this.blockLen;
3606
+ const pad = new Uint8Array(blockLen);
3607
+ pad.set(key.length > blockLen ? hash.create().update(key).digest() : key);
3608
+ for (let i = 0; i < pad.length; i++)
3609
+ pad[i] ^= 54;
3610
+ this.iHash.update(pad);
3611
+ this.oHash = hash.create();
3612
+ for (let i = 0; i < pad.length; i++)
3613
+ pad[i] ^= 54 ^ 92;
3614
+ this.oHash.update(pad);
3615
+ clean(pad);
3616
+ }
3617
+ update(buf) {
3618
+ aexists(this);
3619
+ this.iHash.update(buf);
3620
+ return this;
3621
+ }
3622
+ digestInto(out) {
3623
+ aexists(this);
3624
+ abytes(out, this.outputLen, "output");
3625
+ this.finished = true;
3626
+ this.iHash.digestInto(out);
3627
+ this.oHash.update(out);
3628
+ this.oHash.digestInto(out);
3629
+ this.destroy();
3630
+ }
3631
+ digest() {
3632
+ const out = new Uint8Array(this.oHash.outputLen);
3633
+ this.digestInto(out);
3634
+ return out;
3635
+ }
3636
+ _cloneInto(to) {
3637
+ to ||= Object.create(Object.getPrototypeOf(this), {});
3638
+ const { oHash, iHash, finished, destroyed, blockLen, outputLen } = this;
3639
+ to = to;
3640
+ to.finished = finished;
3641
+ to.destroyed = destroyed;
3642
+ to.blockLen = blockLen;
3643
+ to.outputLen = outputLen;
3644
+ to.oHash = oHash._cloneInto(to.oHash);
3645
+ to.iHash = iHash._cloneInto(to.iHash);
3646
+ return to;
3647
+ }
3648
+ clone() {
3649
+ return this._cloneInto();
3650
+ }
3651
+ destroy() {
3652
+ this.destroyed = true;
3653
+ this.oHash.destroy();
3654
+ this.iHash.destroy();
3655
+ }
3656
+ };
3657
+ var hmac = (hash, key, message) => new _HMAC(hash, key).update(message).digest();
3658
+ hmac.create = (hash, key) => new _HMAC(hash, key);
3659
+
3660
+ // node_modules/@noble/hashes/hkdf.js
3661
+ function extract(hash, ikm, salt) {
3662
+ ahash(hash);
3663
+ if (salt === void 0)
3664
+ salt = new Uint8Array(hash.outputLen);
3665
+ return hmac(hash, salt, ikm);
3666
+ }
3667
+ var HKDF_COUNTER = /* @__PURE__ */ Uint8Array.of(0);
3668
+ var EMPTY_BUFFER = /* @__PURE__ */ Uint8Array.of();
3669
+ function expand(hash, prk, info, length = 32) {
3670
+ ahash(hash);
3671
+ anumber(length, "length");
3672
+ const olen = hash.outputLen;
3673
+ if (length > 255 * olen)
3674
+ throw new Error("Length must be <= 255*HashLen");
3675
+ const blocks = Math.ceil(length / olen);
3676
+ if (info === void 0)
3677
+ info = EMPTY_BUFFER;
3678
+ else
3679
+ abytes(info, void 0, "info");
3680
+ const okm = new Uint8Array(blocks * olen);
3681
+ const HMAC = hmac.create(hash, prk);
3682
+ const HMACTmp = HMAC._cloneInto();
3683
+ const T = new Uint8Array(HMAC.outputLen);
3684
+ for (let counter = 0; counter < blocks; counter++) {
3685
+ HKDF_COUNTER[0] = counter + 1;
3686
+ HMACTmp.update(counter === 0 ? EMPTY_BUFFER : T).update(info).update(HKDF_COUNTER).digestInto(T);
3687
+ okm.set(T, olen * counter);
3688
+ HMAC._cloneInto(HMACTmp);
3689
+ }
3690
+ HMAC.destroy();
3691
+ HMACTmp.destroy();
3692
+ clean(T, HKDF_COUNTER);
3693
+ return okm.slice(0, length);
3694
+ }
3695
+ var hkdf = (hash, ikm, salt, info, length) => expand(hash, extract(hash, ikm, salt), info, length);
3696
+
3697
+ // core/crypto.ts
3698
+ import * as bip39 from "bip39";
3699
+ import CryptoJS from "crypto-js";
3700
+ import elliptic from "elliptic";
3701
+ var ec = new elliptic.ec("secp256k1");
3702
+ var CURVE_ORDER = BigInt(
3703
+ "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"
3704
+ );
3705
+ function hexToBytes2(hex) {
3706
+ const matches = hex.match(/../g);
3707
+ if (!matches) {
3708
+ return new Uint8Array(0);
3709
+ }
3710
+ return Uint8Array.from(matches.map((x) => parseInt(x, 16)));
3711
+ }
3712
+
4019
3713
  // impl/shared/ipfs/ipns-key-derivation.ts
4020
3714
  var IPNS_HKDF_INFO = "ipfs-storage-ed25519-v1";
4021
3715
  var libp2pCryptoModule = null;