Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

nostr-tools

Package Overview
Dependencies
Maintainers
1
Versions
151
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

nostr-tools - npm Package Compare versions

Comparing version 1.7.5 to 1.8.0

lib/references.d.ts

1

lib/index.d.ts

@@ -6,2 +6,3 @@ export * from './keys';

export * from './pool';
export * from './references';
export * as nip04 from './nip04';

@@ -8,0 +9,0 @@ export * as nip05 from './nip05';

@@ -8,2 +8,3 @@ export type ProfilePointer = {

relays?: string[];
author?: string;
};

@@ -10,0 +11,0 @@ export type AddressPointer = {

402

lib/nostr.cjs.js

@@ -46,2 +46,3 @@ "use strict";

nip57: () => nip57_exports,
parseReferences: () => parseReferences,
relayInit: () => relayInit,

@@ -621,2 +622,3 @@ serializeEvent: () => serializeEvent,

this._seenOn[id] = set;
_knownIds.add(id);
return _knownIds.has(id);

@@ -646,3 +648,2 @@ };

s.on("event", (event) => {
_knownIds.add(event.id);
for (let cb of eventListeners.values())

@@ -742,131 +743,2 @@ cb(event);

// nip04.ts
var nip04_exports = {};
__export(nip04_exports, {
decrypt: () => decrypt,
encrypt: () => encrypt
});
var import_utils3 = require("@noble/hashes/utils");
var secp256k13 = __toESM(require("@noble/secp256k1"));
var import_base = require("@scure/base");
async function encrypt(privkey, pubkey, text) {
const key = secp256k13.getSharedSecret(privkey, "02" + pubkey);
const normalizedKey = getNormalizedX(key);
let iv = Uint8Array.from((0, import_utils3.randomBytes)(16));
let plaintext = utf8Encoder.encode(text);
let cryptoKey = await crypto.subtle.importKey(
"raw",
normalizedKey,
{ name: "AES-CBC" },
false,
["encrypt"]
);
let ciphertext = await crypto.subtle.encrypt(
{ name: "AES-CBC", iv },
cryptoKey,
plaintext
);
let ctb64 = import_base.base64.encode(new Uint8Array(ciphertext));
let ivb64 = import_base.base64.encode(new Uint8Array(iv.buffer));
return `${ctb64}?iv=${ivb64}`;
}
async function decrypt(privkey, pubkey, data) {
let [ctb64, ivb64] = data.split("?iv=");
let key = secp256k13.getSharedSecret(privkey, "02" + pubkey);
let normalizedKey = getNormalizedX(key);
let cryptoKey = await crypto.subtle.importKey(
"raw",
normalizedKey,
{ name: "AES-CBC" },
false,
["decrypt"]
);
let ciphertext = import_base.base64.decode(ctb64);
let iv = import_base.base64.decode(ivb64);
let plaintext = await crypto.subtle.decrypt(
{ name: "AES-CBC", iv },
cryptoKey,
ciphertext
);
let text = utf8Decoder.decode(plaintext);
return text;
}
function getNormalizedX(key) {
return key.slice(1, 33);
}
// nip05.ts
var nip05_exports = {};
__export(nip05_exports, {
queryProfile: () => queryProfile,
searchDomain: () => searchDomain,
useFetchImplementation: () => useFetchImplementation
});
var _fetch;
try {
_fetch = fetch;
} catch {
}
function useFetchImplementation(fetchImplementation) {
_fetch = fetchImplementation;
}
async function searchDomain(domain, query = "") {
try {
let res = await (await _fetch(`https://${domain}/.well-known/nostr.json?name=${query}`)).json();
return res.names;
} catch (_) {
return {};
}
}
async function queryProfile(fullname) {
let [name, domain] = fullname.split("@");
if (!domain) {
domain = name;
name = "_";
}
if (!name.match(/^[A-Za-z0-9-_]+$/))
return null;
if (!domain.includes("."))
return null;
let res;
try {
res = await (await _fetch(`https://${domain}/.well-known/nostr.json?name=${name}`)).json();
} catch (err) {
return null;
}
if (!res?.names?.[name])
return null;
let pubkey = res.names[name];
let relays = res.relays?.[pubkey] || [];
return {
pubkey,
relays
};
}
// nip06.ts
var nip06_exports = {};
__export(nip06_exports, {
generateSeedWords: () => generateSeedWords,
privateKeyFromSeedWords: () => privateKeyFromSeedWords,
validateWords: () => validateWords
});
var secp256k14 = __toESM(require("@noble/secp256k1"));
var import_english = require("@scure/bip39/wordlists/english.js");
var import_bip39 = require("@scure/bip39");
var import_bip32 = require("@scure/bip32");
function privateKeyFromSeedWords(mnemonic, passphrase) {
let root = import_bip32.HDKey.fromMasterSeed((0, import_bip39.mnemonicToSeedSync)(mnemonic, passphrase));
let privateKey = root.derive(`m/44'/1237'/0'/0/0`).privateKey;
if (!privateKey)
throw new Error("could not derive private key");
return secp256k14.utils.bytesToHex(privateKey);
}
function generateSeedWords() {
return (0, import_bip39.generateMnemonic)(import_english.wordlist);
}
function validateWords(words) {
return (0, import_bip39.validateMnemonic)(words, import_english.wordlist);
}
// nip19.ts

@@ -883,8 +755,8 @@ var nip19_exports = {};

});
var secp256k15 = __toESM(require("@noble/secp256k1"));
var import_base2 = require("@scure/base");
var secp256k13 = __toESM(require("@noble/secp256k1"));
var import_base = require("@scure/base");
var Bech32MaxSize = 5e3;
function decode(nip19) {
let { prefix, words } = import_base2.bech32.decode(nip19, Bech32MaxSize);
let data = new Uint8Array(import_base2.bech32.fromWords(words));
let { prefix, words } = import_base.bech32.decode(nip19, Bech32MaxSize);
let data = new Uint8Array(import_base.bech32.fromWords(words));
switch (prefix) {

@@ -900,3 +772,3 @@ case "nprofile": {

data: {
pubkey: secp256k15.utils.bytesToHex(tlv[0][0]),
pubkey: secp256k13.utils.bytesToHex(tlv[0][0]),
relays: tlv[1] ? tlv[1].map((d) => utf8Decoder.decode(d)) : []

@@ -912,7 +784,10 @@ }

throw new Error("TLV 0 should be 32 bytes");
if (tlv[2] && tlv[2][0].length !== 32)
throw new Error("TLV 2 should be 32 bytes");
return {
type: "nevent",
data: {
id: secp256k15.utils.bytesToHex(tlv[0][0]),
relays: tlv[1] ? tlv[1].map((d) => utf8Decoder.decode(d)) : []
id: secp256k13.utils.bytesToHex(tlv[0][0]),
relays: tlv[1] ? tlv[1].map((d) => utf8Decoder.decode(d)) : [],
author: tlv[2]?.[0] ? secp256k13.utils.bytesToHex(tlv[2][0]) : void 0
}

@@ -937,4 +812,4 @@ };

identifier: utf8Decoder.decode(tlv[0][0]),
pubkey: secp256k15.utils.bytesToHex(tlv[2][0]),
kind: parseInt(secp256k15.utils.bytesToHex(tlv[3][0]), 16),
pubkey: secp256k13.utils.bytesToHex(tlv[2][0]),
kind: parseInt(secp256k13.utils.bytesToHex(tlv[3][0]), 16),
relays: tlv[1] ? tlv[1].map((d) => utf8Decoder.decode(d)) : []

@@ -947,3 +822,3 @@ }

case "note":
return { type: prefix, data: secp256k15.utils.bytesToHex(data) };
return { type: prefix, data: secp256k13.utils.bytesToHex(data) };
default:

@@ -978,21 +853,22 @@ throw new Error(`unknown prefix ${prefix}`);

function encodeBytes(prefix, hex) {
let data = secp256k15.utils.hexToBytes(hex);
let words = import_base2.bech32.toWords(data);
return import_base2.bech32.encode(prefix, words, Bech32MaxSize);
let data = secp256k13.utils.hexToBytes(hex);
let words = import_base.bech32.toWords(data);
return import_base.bech32.encode(prefix, words, Bech32MaxSize);
}
function nprofileEncode(profile) {
let data = encodeTLV({
0: [secp256k15.utils.hexToBytes(profile.pubkey)],
0: [secp256k13.utils.hexToBytes(profile.pubkey)],
1: (profile.relays || []).map((url) => utf8Encoder.encode(url))
});
let words = import_base2.bech32.toWords(data);
return import_base2.bech32.encode("nprofile", words, Bech32MaxSize);
let words = import_base.bech32.toWords(data);
return import_base.bech32.encode("nprofile", words, Bech32MaxSize);
}
function neventEncode(event) {
let data = encodeTLV({
0: [secp256k15.utils.hexToBytes(event.id)],
1: (event.relays || []).map((url) => utf8Encoder.encode(url))
0: [secp256k13.utils.hexToBytes(event.id)],
1: (event.relays || []).map((url) => utf8Encoder.encode(url)),
2: event.author ? [secp256k13.utils.hexToBytes(event.author)] : []
});
let words = import_base2.bech32.toWords(data);
return import_base2.bech32.encode("nevent", words, Bech32MaxSize);
let words = import_base.bech32.toWords(data);
return import_base.bech32.encode("nevent", words, Bech32MaxSize);
}

@@ -1005,7 +881,7 @@ function naddrEncode(addr) {

1: (addr.relays || []).map((url) => utf8Encoder.encode(url)),
2: [secp256k15.utils.hexToBytes(addr.pubkey)],
2: [secp256k13.utils.hexToBytes(addr.pubkey)],
3: [new Uint8Array(kind)]
});
let words = import_base2.bech32.toWords(data);
return import_base2.bech32.encode("naddr", words, Bech32MaxSize);
let words = import_base.bech32.toWords(data);
return import_base.bech32.encode("naddr", words, Bech32MaxSize);
}

@@ -1023,5 +899,223 @@ function encodeTLV(tlv) {

});
return secp256k15.utils.concatBytes(...entries);
return secp256k13.utils.concatBytes(...entries);
}
// references.ts
var mentionRegex = /\bnostr:((note|npub|naddr|nevent|nprofile)1\w+)\b|#\[(\d+)\]/g;
function parseReferences(evt) {
let references = [];
for (let ref of evt.content.matchAll(mentionRegex)) {
if (ref[2]) {
try {
let { type, data } = decode(ref[1]);
switch (type) {
case "npub": {
references.push({
text: ref[0],
profile: { pubkey: data, relays: [] }
});
break;
}
case "nprofile": {
references.push({
text: ref[0],
profile: data
});
break;
}
case "note": {
references.push({
text: ref[0],
event: { id: data, relays: [] }
});
break;
}
case "nevent": {
references.push({
text: ref[0],
event: data
});
break;
}
case "naddr": {
references.push({
text: ref[0],
address: data
});
break;
}
}
} catch (err) {
}
} else if (ref[3]) {
let idx = parseInt(ref[3], 10);
let tag = evt.tags[idx];
if (!tag)
continue;
switch (tag[0]) {
case "p": {
references.push({
text: ref[0],
profile: { pubkey: tag[1], relays: tag[2] ? [tag[2]] : [] }
});
break;
}
case "e": {
references.push({
text: ref[0],
event: { id: tag[1], relays: tag[2] ? [tag[2]] : [] }
});
break;
}
case "a": {
try {
let [kind, pubkey, identifier] = ref[1].split(":");
references.push({
text: ref[0],
address: {
identifier,
pubkey,
kind: parseInt(kind, 10),
relays: tag[2] ? [tag[2]] : []
}
});
} catch (err) {
}
break;
}
}
}
}
return references;
}
// nip04.ts
var nip04_exports = {};
__export(nip04_exports, {
decrypt: () => decrypt,
encrypt: () => encrypt
});
var import_utils4 = require("@noble/hashes/utils");
var secp256k14 = __toESM(require("@noble/secp256k1"));
var import_base2 = require("@scure/base");
async function encrypt(privkey, pubkey, text) {
const key = secp256k14.getSharedSecret(privkey, "02" + pubkey);
const normalizedKey = getNormalizedX(key);
let iv = Uint8Array.from((0, import_utils4.randomBytes)(16));
let plaintext = utf8Encoder.encode(text);
let cryptoKey = await crypto.subtle.importKey(
"raw",
normalizedKey,
{ name: "AES-CBC" },
false,
["encrypt"]
);
let ciphertext = await crypto.subtle.encrypt(
{ name: "AES-CBC", iv },
cryptoKey,
plaintext
);
let ctb64 = import_base2.base64.encode(new Uint8Array(ciphertext));
let ivb64 = import_base2.base64.encode(new Uint8Array(iv.buffer));
return `${ctb64}?iv=${ivb64}`;
}
async function decrypt(privkey, pubkey, data) {
let [ctb64, ivb64] = data.split("?iv=");
let key = secp256k14.getSharedSecret(privkey, "02" + pubkey);
let normalizedKey = getNormalizedX(key);
let cryptoKey = await crypto.subtle.importKey(
"raw",
normalizedKey,
{ name: "AES-CBC" },
false,
["decrypt"]
);
let ciphertext = import_base2.base64.decode(ctb64);
let iv = import_base2.base64.decode(ivb64);
let plaintext = await crypto.subtle.decrypt(
{ name: "AES-CBC", iv },
cryptoKey,
ciphertext
);
let text = utf8Decoder.decode(plaintext);
return text;
}
function getNormalizedX(key) {
return key.slice(1, 33);
}
// nip05.ts
var nip05_exports = {};
__export(nip05_exports, {
queryProfile: () => queryProfile,
searchDomain: () => searchDomain,
useFetchImplementation: () => useFetchImplementation
});
var _fetch;
try {
_fetch = fetch;
} catch {
}
function useFetchImplementation(fetchImplementation) {
_fetch = fetchImplementation;
}
async function searchDomain(domain, query = "") {
try {
let res = await (await _fetch(`https://${domain}/.well-known/nostr.json?name=${query}`)).json();
return res.names;
} catch (_) {
return {};
}
}
async function queryProfile(fullname) {
let [name, domain] = fullname.split("@");
if (!domain) {
domain = name;
name = "_";
}
if (!name.match(/^[A-Za-z0-9-_]+$/))
return null;
if (!domain.includes("."))
return null;
let res;
try {
res = await (await _fetch(`https://${domain}/.well-known/nostr.json?name=${name}`)).json();
} catch (err) {
return null;
}
if (!res?.names?.[name])
return null;
let pubkey = res.names[name];
let relays = res.relays?.[pubkey] || [];
return {
pubkey,
relays
};
}
// nip06.ts
var nip06_exports = {};
__export(nip06_exports, {
generateSeedWords: () => generateSeedWords,
privateKeyFromSeedWords: () => privateKeyFromSeedWords,
validateWords: () => validateWords
});
var secp256k15 = __toESM(require("@noble/secp256k1"));
var import_english = require("@scure/bip39/wordlists/english.js");
var import_bip39 = require("@scure/bip39");
var import_bip32 = require("@scure/bip32");
function privateKeyFromSeedWords(mnemonic, passphrase) {
let root = import_bip32.HDKey.fromMasterSeed((0, import_bip39.mnemonicToSeedSync)(mnemonic, passphrase));
let privateKey = root.derive(`m/44'/1237'/0'/0/0`).privateKey;
if (!privateKey)
throw new Error("could not derive private key");
return secp256k15.utils.bytesToHex(privateKey);
}
function generateSeedWords() {
return (0, import_bip39.generateMnemonic)(import_english.wordlist);
}
function validateWords(words) {
return (0, import_bip39.validateMnemonic)(words, import_english.wordlist);
}
// nip26.ts

@@ -1028,0 +1122,0 @@ var nip26_exports = {};

{
"name": "nostr-tools",
"version": "1.7.5",
"version": "1.8.0",
"description": "Tools for making a Nostr client.",

@@ -5,0 +5,0 @@ "repository": {

@@ -173,2 +173,22 @@ # nostr-tools

### Parsing references (mentions) from a content using NIP-10 and NIP-27
```js
import {parseReferences} from 'nostr-tools'
let references = parseReferences(event)
let simpleAugmentedContent = event.content
for (let i = 0; i < references.length; i++) {
let {text, profile, event, address} = references[i]
let augmentedReference = profile
? `<strong>@${profilesCache[profile.pubkey].name}</strong>`
: event
? `<em>${eventsCache[event.id].content.slice(0, 5)}</em>`
: address
? `<a href="${text}">[link]</a>`
: text
simpleAugmentedContent.replaceAll(text, augmentedReference)
}
```
### Querying profile data from a NIP-05 address

@@ -175,0 +195,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc