nostr-tools 2.0.1 → 2.0.3

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 CHANGED
@@ -21,7 +21,7 @@ If using TypeScript, this package requires TypeScript >= 5.0.
21
21
  ```js
22
22
  import { generateSecretKey, getPublicKey } from 'nostr-tools'
23
23
 
24
- let sk = generateSecretKey() // `sk` is a hex string
24
+ let sk = generateSecretKey() // `sk` is a Uint8Array
25
25
  let pk = getPublicKey(sk) // `pk` is a hex string
26
26
  ```
27
27
 
package/lib/cjs/index.js CHANGED
@@ -28,6 +28,7 @@ __export(nostr_tools_exports, {
28
28
  generateSecretKey: () => generateSecretKey,
29
29
  getEventHash: () => getEventHash,
30
30
  getPublicKey: () => getPublicKey,
31
+ kinds: () => kinds_exports,
31
32
  matchFilter: () => matchFilter,
32
33
  matchFilters: () => matchFilters,
33
34
  mergeFilters: () => mergeFilters,
@@ -45,6 +46,7 @@ __export(nostr_tools_exports, {
45
46
  nip30: () => nip30_exports,
46
47
  nip39: () => nip39_exports,
47
48
  nip42: () => nip42_exports,
49
+ nip44: () => nip44_exports,
48
50
  nip47: () => nip47_exports,
49
51
  nip57: () => nip57_exports,
50
52
  nip98: () => nip98_exports,
@@ -375,9 +377,9 @@ async function yieldThread() {
375
377
  }
376
378
 
377
379
  // relay.ts
378
- function relayConnect(url) {
380
+ async function relayConnect(url) {
379
381
  const relay = new Relay(url);
380
- relay.connect();
382
+ await relay.connect();
381
383
  return relay;
382
384
  }
383
385
  var Relay = class {
@@ -666,8 +668,8 @@ var SimplePool = class {
666
668
  if (this.trustedRelayURLs.has(relay.url))
667
669
  relay.trusted = true;
668
670
  this.relays.set(url, relay);
669
- await relay.connect();
670
671
  }
672
+ await relay.connect();
671
673
  return relay;
672
674
  }
673
675
  close(relays) {
@@ -1290,16 +1292,183 @@ __export(nip18_exports, {
1290
1292
  });
1291
1293
 
1292
1294
  // kinds.ts
1295
+ var kinds_exports = {};
1296
+ __export(kinds_exports, {
1297
+ Application: () => Application,
1298
+ BadgeAward: () => BadgeAward,
1299
+ BadgeDefinition: () => BadgeDefinition,
1300
+ BlockedRelaysList: () => BlockedRelaysList,
1301
+ BookmarkList: () => BookmarkList,
1302
+ Bookmarksets: () => Bookmarksets,
1303
+ Calendar: () => Calendar,
1304
+ CalendarEventRSVP: () => CalendarEventRSVP,
1305
+ ChannelCreation: () => ChannelCreation,
1306
+ ChannelHideMessage: () => ChannelHideMessage,
1307
+ ChannelMessage: () => ChannelMessage,
1308
+ ChannelMetadata: () => ChannelMetadata,
1309
+ ChannelMuteUser: () => ChannelMuteUser,
1310
+ ClassifiedListing: () => ClassifiedListing,
1311
+ ClientAuth: () => ClientAuth,
1312
+ CommunitiesList: () => CommunitiesList,
1313
+ CommunityDefinition: () => CommunityDefinition,
1314
+ CommunityPostApproval: () => CommunityPostApproval,
1315
+ Contacts: () => Contacts,
1316
+ CreateOrUpdateProduct: () => CreateOrUpdateProduct,
1317
+ CreateOrUpdateStall: () => CreateOrUpdateStall,
1318
+ Curationsets: () => Curationsets,
1319
+ Date: () => Date2,
1320
+ DraftClassifiedListing: () => DraftClassifiedListing,
1321
+ DraftLong: () => DraftLong,
1322
+ Emojisets: () => Emojisets,
1323
+ EncryptedDirectMessage: () => EncryptedDirectMessage,
1324
+ EncryptedDirectMessages: () => EncryptedDirectMessages,
1325
+ EventDeletion: () => EventDeletion,
1326
+ FileMetadata: () => FileMetadata,
1327
+ Followsets: () => Followsets,
1328
+ GenericRepost: () => GenericRepost,
1329
+ Genericlists: () => Genericlists,
1330
+ HTTPAuth: () => HTTPAuth,
1331
+ Handlerinformation: () => Handlerinformation,
1332
+ Handlerrecommendation: () => Handlerrecommendation,
1333
+ Highlights: () => Highlights,
1334
+ InterestsList: () => InterestsList,
1335
+ Interestsets: () => Interestsets,
1336
+ JobFeedback: () => JobFeedback,
1337
+ JobRequest: () => JobRequest,
1338
+ JobResult: () => JobResult,
1339
+ Label: () => Label,
1340
+ LightningPubRPC: () => LightningPubRPC,
1341
+ LiveChatMessage: () => LiveChatMessage,
1342
+ LiveEvent: () => LiveEvent,
1343
+ LongFormArticle: () => LongFormArticle,
1344
+ Metadata: () => Metadata,
1345
+ Mutelist: () => Mutelist,
1346
+ NWCWalletInfo: () => NWCWalletInfo,
1347
+ NWCWalletRequest: () => NWCWalletRequest,
1348
+ NWCWalletResponse: () => NWCWalletResponse,
1349
+ NostrConnect: () => NostrConnect,
1350
+ OpenTimestamps: () => OpenTimestamps,
1351
+ Pinlist: () => Pinlist,
1352
+ ProblemTracker: () => ProblemTracker,
1353
+ ProfileBadges: () => ProfileBadges,
1354
+ PublicChatsList: () => PublicChatsList,
1355
+ Reaction: () => Reaction,
1356
+ RecommendRelay: () => RecommendRelay,
1357
+ RelayList: () => RelayList,
1358
+ Relaysets: () => Relaysets,
1359
+ Report: () => Report,
1360
+ Reporting: () => Reporting,
1361
+ Repost: () => Repost,
1362
+ SearchRelaysList: () => SearchRelaysList,
1363
+ ShortTextNote: () => ShortTextNote,
1364
+ Time: () => Time,
1365
+ UserEmojiList: () => UserEmojiList,
1366
+ UserStatuses: () => UserStatuses,
1367
+ Zap: () => Zap,
1368
+ ZapGoal: () => ZapGoal,
1369
+ ZapRequest: () => ZapRequest,
1370
+ classifyKind: () => classifyKind,
1371
+ isEphemeralKind: () => isEphemeralKind,
1372
+ isParameterizedReplaceableKind: () => isParameterizedReplaceableKind,
1373
+ isRegularKind: () => isRegularKind,
1374
+ isReplaceableKind: () => isReplaceableKind
1375
+ });
1376
+ function isRegularKind(kind) {
1377
+ return 1e3 <= kind && kind < 1e4 || [1, 2, 4, 5, 6, 7, 8, 16, 40, 41, 42, 43, 44].includes(kind);
1378
+ }
1379
+ function isReplaceableKind(kind) {
1380
+ return [0, 3].includes(kind) || 1e4 <= kind && kind < 2e4;
1381
+ }
1382
+ function isEphemeralKind(kind) {
1383
+ return 2e4 <= kind && kind < 3e4;
1384
+ }
1385
+ function isParameterizedReplaceableKind(kind) {
1386
+ return 3e4 <= kind && kind < 4e4;
1387
+ }
1388
+ function classifyKind(kind) {
1389
+ if (isRegularKind(kind))
1390
+ return "regular";
1391
+ if (isReplaceableKind(kind))
1392
+ return "replaceable";
1393
+ if (isEphemeralKind(kind))
1394
+ return "ephemeral";
1395
+ if (isParameterizedReplaceableKind(kind))
1396
+ return "parameterized";
1397
+ return "unknown";
1398
+ }
1399
+ var Metadata = 0;
1400
+ var ShortTextNote = 1;
1401
+ var RecommendRelay = 2;
1402
+ var Contacts = 3;
1403
+ var EncryptedDirectMessage = 4;
1404
+ var EventDeletion = 5;
1293
1405
  var Repost = 6;
1294
1406
  var Reaction = 7;
1407
+ var BadgeAward = 8;
1295
1408
  var ChannelCreation = 40;
1296
1409
  var ChannelMetadata = 41;
1297
1410
  var ChannelMessage = 42;
1298
1411
  var ChannelHideMessage = 43;
1299
1412
  var ChannelMuteUser = 44;
1413
+ var Report = 1984;
1414
+ var ZapRequest = 9734;
1415
+ var Zap = 9735;
1416
+ var RelayList = 10002;
1300
1417
  var ClientAuth = 22242;
1418
+ var BadgeDefinition = 30009;
1419
+ var FileMetadata = 1063;
1420
+ var EncryptedDirectMessages = 4;
1421
+ var GenericRepost = 16;
1422
+ var OpenTimestamps = 1040;
1423
+ var LiveChatMessage = 1311;
1424
+ var ProblemTracker = 1971;
1425
+ var Reporting = 1984;
1426
+ var Label = 1985;
1427
+ var CommunityPostApproval = 4550;
1428
+ var JobRequest = 5999;
1429
+ var JobResult = 6999;
1430
+ var JobFeedback = 7e3;
1431
+ var ZapGoal = 9041;
1432
+ var Highlights = 9802;
1433
+ var Mutelist = 1e4;
1434
+ var Pinlist = 10001;
1435
+ var BookmarkList = 10003;
1436
+ var CommunitiesList = 10004;
1437
+ var PublicChatsList = 10005;
1438
+ var BlockedRelaysList = 10006;
1439
+ var SearchRelaysList = 10007;
1440
+ var InterestsList = 10015;
1441
+ var UserEmojiList = 10030;
1442
+ var NWCWalletInfo = 13194;
1443
+ var LightningPubRPC = 21e3;
1301
1444
  var NWCWalletRequest = 23194;
1445
+ var NWCWalletResponse = 23195;
1446
+ var NostrConnect = 24133;
1302
1447
  var HTTPAuth = 27235;
1448
+ var Followsets = 3e4;
1449
+ var Genericlists = 30001;
1450
+ var Relaysets = 30002;
1451
+ var Bookmarksets = 30003;
1452
+ var Curationsets = 30004;
1453
+ var ProfileBadges = 30008;
1454
+ var Interestsets = 30015;
1455
+ var CreateOrUpdateStall = 30017;
1456
+ var CreateOrUpdateProduct = 30018;
1457
+ var LongFormArticle = 30023;
1458
+ var DraftLong = 30024;
1459
+ var Emojisets = 30030;
1460
+ var Application = 30078;
1461
+ var LiveEvent = 30311;
1462
+ var UserStatuses = 30315;
1463
+ var ClassifiedListing = 30402;
1464
+ var DraftClassifiedListing = 30403;
1465
+ var Date2 = 31922;
1466
+ var Time = 31923;
1467
+ var Calendar = 31924;
1468
+ var CalendarEventRSVP = 31925;
1469
+ var Handlerrecommendation = 31989;
1470
+ var Handlerinformation = 31990;
1471
+ var CommunityDefinition = 34550;
1303
1472
 
1304
1473
  // nip18.ts
1305
1474
  function finishRepostEvent(t, reposted, relayUrl, privateKey) {
@@ -1633,6 +1802,128 @@ function makeAuthEvent(relayURL, challenge) {
1633
1802
  };
1634
1803
  }
1635
1804
 
1805
+ // nip44.ts
1806
+ var nip44_exports = {};
1807
+ __export(nip44_exports, {
1808
+ default: () => nip44_default,
1809
+ v2: () => v2
1810
+ });
1811
+ var import_chacha = require("@noble/ciphers/chacha");
1812
+ var import_utils9 = require("@noble/ciphers/utils");
1813
+ var import_secp256k13 = require("@noble/curves/secp256k1");
1814
+ var import_hkdf = require("@noble/hashes/hkdf");
1815
+ var import_hmac = require("@noble/hashes/hmac");
1816
+ var import_sha2562 = require("@noble/hashes/sha256");
1817
+ var import_utils10 = require("@noble/hashes/utils");
1818
+ var import_base3 = require("@scure/base");
1819
+ var decoder = new TextDecoder();
1820
+ var u = {
1821
+ minPlaintextSize: 1,
1822
+ maxPlaintextSize: 65535,
1823
+ utf8Encode: import_utils10.utf8ToBytes,
1824
+ utf8Decode(bytes) {
1825
+ return decoder.decode(bytes);
1826
+ },
1827
+ getConversationKey(privkeyA, pubkeyB) {
1828
+ const sharedX = import_secp256k13.secp256k1.getSharedSecret(privkeyA, "02" + pubkeyB).subarray(1, 33);
1829
+ return (0, import_hkdf.extract)(import_sha2562.sha256, sharedX, "nip44-v2");
1830
+ },
1831
+ getMessageKeys(conversationKey, nonce) {
1832
+ (0, import_utils9.ensureBytes)(conversationKey, 32);
1833
+ (0, import_utils9.ensureBytes)(nonce, 32);
1834
+ const keys = (0, import_hkdf.expand)(import_sha2562.sha256, conversationKey, nonce, 76);
1835
+ return {
1836
+ chacha_key: keys.subarray(0, 32),
1837
+ chacha_nonce: keys.subarray(32, 44),
1838
+ hmac_key: keys.subarray(44, 76)
1839
+ };
1840
+ },
1841
+ calcPaddedLen(len) {
1842
+ if (!Number.isSafeInteger(len) || len < 1)
1843
+ throw new Error("expected positive integer");
1844
+ if (len <= 32)
1845
+ return 32;
1846
+ const nextPower = 1 << Math.floor(Math.log2(len - 1)) + 1;
1847
+ const chunk = nextPower <= 256 ? 32 : nextPower / 8;
1848
+ return chunk * (Math.floor((len - 1) / chunk) + 1);
1849
+ },
1850
+ writeU16BE(num) {
1851
+ if (!Number.isSafeInteger(num) || num < u.minPlaintextSize || num > u.maxPlaintextSize)
1852
+ throw new Error("invalid plaintext size: must be between 1 and 65535 bytes");
1853
+ const arr = new Uint8Array(2);
1854
+ new DataView(arr.buffer).setUint16(0, num, false);
1855
+ return arr;
1856
+ },
1857
+ pad(plaintext) {
1858
+ const unpadded = u.utf8Encode(plaintext);
1859
+ const unpaddedLen = unpadded.length;
1860
+ const prefix = u.writeU16BE(unpaddedLen);
1861
+ const suffix = new Uint8Array(u.calcPaddedLen(unpaddedLen) - unpaddedLen);
1862
+ return (0, import_utils10.concatBytes)(prefix, unpadded, suffix);
1863
+ },
1864
+ unpad(padded) {
1865
+ const unpaddedLen = new DataView(padded.buffer).getUint16(0);
1866
+ const unpadded = padded.subarray(2, 2 + unpaddedLen);
1867
+ if (unpaddedLen < u.minPlaintextSize || unpaddedLen > u.maxPlaintextSize || unpadded.length !== unpaddedLen || padded.length !== 2 + u.calcPaddedLen(unpaddedLen))
1868
+ throw new Error("invalid padding");
1869
+ return u.utf8Decode(unpadded);
1870
+ },
1871
+ hmacAad(key, message, aad) {
1872
+ if (aad.length !== 32)
1873
+ throw new Error("AAD associated data must be 32 bytes");
1874
+ const combined = (0, import_utils10.concatBytes)(aad, message);
1875
+ return (0, import_hmac.hmac)(import_sha2562.sha256, key, combined);
1876
+ },
1877
+ decodePayload(payload) {
1878
+ if (typeof payload !== "string")
1879
+ throw new Error("payload must be a valid string");
1880
+ const plen = payload.length;
1881
+ if (plen < 132 || plen > 87472)
1882
+ throw new Error("invalid payload length: " + plen);
1883
+ if (payload[0] === "#")
1884
+ throw new Error("unknown encryption version");
1885
+ let data;
1886
+ try {
1887
+ data = import_base3.base64.decode(payload);
1888
+ } catch (error) {
1889
+ throw new Error("invalid base64: " + error.message);
1890
+ }
1891
+ const dlen = data.length;
1892
+ if (dlen < 99 || dlen > 65603)
1893
+ throw new Error("invalid data length: " + dlen);
1894
+ const vers = data[0];
1895
+ if (vers !== 2)
1896
+ throw new Error("unknown encryption version " + vers);
1897
+ return {
1898
+ nonce: data.subarray(1, 33),
1899
+ ciphertext: data.subarray(33, -32),
1900
+ mac: data.subarray(-32)
1901
+ };
1902
+ }
1903
+ };
1904
+ function encrypt2(plaintext, conversationKey, nonce = (0, import_utils10.randomBytes)(32)) {
1905
+ const { chacha_key, chacha_nonce, hmac_key } = u.getMessageKeys(conversationKey, nonce);
1906
+ const padded = u.pad(plaintext);
1907
+ const ciphertext = (0, import_chacha.chacha20)(chacha_key, chacha_nonce, padded);
1908
+ const mac = u.hmacAad(hmac_key, ciphertext, nonce);
1909
+ return import_base3.base64.encode((0, import_utils10.concatBytes)(new Uint8Array([2]), nonce, ciphertext, mac));
1910
+ }
1911
+ function decrypt2(payload, conversationKey) {
1912
+ const { nonce, ciphertext, mac } = u.decodePayload(payload);
1913
+ const { chacha_key, chacha_nonce, hmac_key } = u.getMessageKeys(conversationKey, nonce);
1914
+ const calculatedMac = u.hmacAad(hmac_key, ciphertext, nonce);
1915
+ if (!(0, import_utils9.equalBytes)(calculatedMac, mac))
1916
+ throw new Error("invalid MAC");
1917
+ const padded = (0, import_chacha.chacha20)(chacha_key, chacha_nonce, ciphertext);
1918
+ return u.unpad(padded);
1919
+ }
1920
+ var v2 = {
1921
+ utils: u,
1922
+ encrypt: encrypt2,
1923
+ decrypt: decrypt2
1924
+ };
1925
+ var nip44_default = { v2 };
1926
+
1636
1927
  // nip47.ts
1637
1928
  var nip47_exports = {};
1638
1929
  __export(nip47_exports, {
@@ -1675,7 +1966,7 @@ __export(nip57_exports, {
1675
1966
  useFetchImplementation: () => useFetchImplementation4,
1676
1967
  validateZapRequest: () => validateZapRequest
1677
1968
  });
1678
- var import_base3 = require("@scure/base");
1969
+ var import_base4 = require("@scure/base");
1679
1970
  var _fetch4;
1680
1971
  try {
1681
1972
  _fetch4 = fetch;
@@ -1689,8 +1980,8 @@ async function getZapEndpoint(metadata) {
1689
1980
  let lnurl = "";
1690
1981
  let { lud06, lud16 } = JSON.parse(metadata.content);
1691
1982
  if (lud06) {
1692
- let { words } = import_base3.bech32.decode(lud06, 1e3);
1693
- let data = import_base3.bech32.fromWords(words);
1983
+ let { words } = import_base4.bech32.decode(lud06, 1e3);
1984
+ let data = import_base4.bech32.fromWords(words);
1694
1985
  lnurl = utf8Decoder.decode(data);
1695
1986
  } else if (lud16) {
1696
1987
  let [name, domain] = lud16.split("@");
@@ -1786,13 +2077,13 @@ __export(nip98_exports, {
1786
2077
  validateEvent: () => validateEvent2,
1787
2078
  validateToken: () => validateToken
1788
2079
  });
1789
- var import_utils10 = require("@noble/hashes/utils");
1790
- var import_sha2562 = require("@noble/hashes/sha256");
1791
- var import_base4 = require("@scure/base");
2080
+ var import_utils12 = require("@noble/hashes/utils");
2081
+ var import_sha2563 = require("@noble/hashes/sha256");
2082
+ var import_base5 = require("@scure/base");
1792
2083
  var _authorizationScheme = "Nostr ";
1793
2084
  function hashPayload(payload) {
1794
- const hash = (0, import_sha2562.sha256)(utf8Encoder.encode(JSON.stringify(payload)));
1795
- return (0, import_utils10.bytesToHex)(hash);
2085
+ const hash = (0, import_sha2563.sha256)(utf8Encoder.encode(JSON.stringify(payload)));
2086
+ return (0, import_utils12.bytesToHex)(hash);
1796
2087
  }
1797
2088
  async function getToken(loginUrl, httpMethod, sign, includeAuthorizationScheme = false, payload) {
1798
2089
  const event = {
@@ -1805,11 +2096,11 @@ async function getToken(loginUrl, httpMethod, sign, includeAuthorizationScheme =
1805
2096
  content: ""
1806
2097
  };
1807
2098
  if (payload) {
1808
- event.tags.push(["payload", (0, import_utils10.bytesToHex)((0, import_sha2562.sha256)(utf8Encoder.encode(JSON.stringify(payload))))]);
2099
+ event.tags.push(["payload", (0, import_utils12.bytesToHex)((0, import_sha2563.sha256)(utf8Encoder.encode(JSON.stringify(payload))))]);
1809
2100
  }
1810
2101
  const signedEvent = await sign(event);
1811
2102
  const authorizationScheme = includeAuthorizationScheme ? _authorizationScheme : "";
1812
- return authorizationScheme + import_base4.base64.encode(utf8Encoder.encode(JSON.stringify(signedEvent)));
2103
+ return authorizationScheme + import_base5.base64.encode(utf8Encoder.encode(JSON.stringify(signedEvent)));
1813
2104
  }
1814
2105
  async function validateToken(token, url, method) {
1815
2106
  const event = await unpackEventFromToken(token).catch((error) => {
@@ -1825,7 +2116,7 @@ async function unpackEventFromToken(token) {
1825
2116
  throw new Error("Missing token");
1826
2117
  }
1827
2118
  token = token.replace(_authorizationScheme, "");
1828
- const eventB64 = utf8Decoder.decode(import_base4.base64.decode(token));
2119
+ const eventB64 = utf8Decoder.decode(import_base5.base64.decode(token));
1829
2120
  if (!eventB64 || eventB64.length === 0 || !eventB64.startsWith("{")) {
1830
2121
  throw new Error("Invalid token");
1831
2122
  }
@@ -1858,7 +2149,7 @@ async function validateEvent2(event, url, method, body) {
1858
2149
  }
1859
2150
  if (Boolean(body) && Object.keys(body).length > 0) {
1860
2151
  const payloadTag = event.tags.find((t) => t[0] === "payload");
1861
- const payloadHash = (0, import_utils10.bytesToHex)((0, import_sha2562.sha256)(utf8Encoder.encode(JSON.stringify(body))));
2152
+ const payloadHash = (0, import_utils12.bytesToHex)((0, import_sha2563.sha256)(utf8Encoder.encode(JSON.stringify(body))));
1862
2153
  if (payloadTag?.[1] !== payloadHash) {
1863
2154
  throw new Error("Invalid payload tag hash, does not match request body hash");
1864
2155
  }