nostr-tools 1.13.1 → 1.14.2
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 +1 -7
- package/lib/esm/nostr.mjs +225 -76
- package/lib/esm/nostr.mjs.map +4 -4
- package/lib/event.d.ts +7 -5
- package/lib/filter.d.ts +3 -3
- package/lib/index.d.ts +2 -0
- package/lib/nip28.d.ts +46 -0
- package/lib/nip28.test.d.ts +1 -0
- package/lib/nip44.d.ts +3 -0
- package/lib/nip44.test.d.ts +1 -0
- package/lib/nip98.d.ts +5 -8
- package/lib/nostr.bundle.js +5952 -6199
- package/lib/nostr.bundle.js.map +4 -4
- package/lib/nostr.cjs.js +228 -79
- package/lib/nostr.cjs.js.map +4 -4
- package/lib/pool.d.ts +7 -3
- package/lib/relay.d.ts +2 -6
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -108,13 +108,7 @@ let event = {
|
|
|
108
108
|
event.id = getEventHash(event)
|
|
109
109
|
event.sig = getSignature(event, sk)
|
|
110
110
|
|
|
111
|
-
|
|
112
|
-
pub.on('ok', () => {
|
|
113
|
-
console.log(`${relay.url} has accepted our event`)
|
|
114
|
-
})
|
|
115
|
-
pub.on('failed', reason => {
|
|
116
|
-
console.log(`failed to publish to ${relay.url}: ${reason}`)
|
|
117
|
-
})
|
|
111
|
+
await relay.publish(event)
|
|
118
112
|
|
|
119
113
|
let events = await relay.list([{kinds: [0, 1]}])
|
|
120
114
|
let event = await relay.get({
|
package/lib/esm/nostr.mjs
CHANGED
|
@@ -211,6 +211,7 @@ var Kind = /* @__PURE__ */ ((Kind3) => {
|
|
|
211
211
|
Kind3[Kind3["ProfileBadge"] = 30008] = "ProfileBadge";
|
|
212
212
|
Kind3[Kind3["BadgeDefinition"] = 30009] = "BadgeDefinition";
|
|
213
213
|
Kind3[Kind3["Article"] = 30023] = "Article";
|
|
214
|
+
Kind3[Kind3["FileMetadata"] = 1063] = "FileMetadata";
|
|
214
215
|
return Kind3;
|
|
215
216
|
})(Kind || {});
|
|
216
217
|
function getBlankEvent(kind = 255 /* Blank */) {
|
|
@@ -491,12 +492,11 @@ function relayInit(url, options = {}) {
|
|
|
491
492
|
let ok = data[2];
|
|
492
493
|
let reason = data[3] || "";
|
|
493
494
|
if (id2 in pubListeners) {
|
|
495
|
+
let { resolve: resolve2, reject: reject2 } = pubListeners[id2];
|
|
494
496
|
if (ok)
|
|
495
|
-
|
|
497
|
+
resolve2(null);
|
|
496
498
|
else
|
|
497
|
-
|
|
498
|
-
pubListeners[id2].ok = [];
|
|
499
|
-
pubListeners[id2].failed = [];
|
|
499
|
+
reject2(new Error(reason));
|
|
500
500
|
}
|
|
501
501
|
return;
|
|
502
502
|
}
|
|
@@ -581,27 +581,15 @@ function relayInit(url, options = {}) {
|
|
|
581
581
|
};
|
|
582
582
|
};
|
|
583
583
|
function _publishEvent(event, type) {
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
return {
|
|
589
|
-
on: (type2, cb) => {
|
|
590
|
-
pubListeners[id] = pubListeners[id] || {
|
|
591
|
-
ok: [],
|
|
592
|
-
failed: []
|
|
593
|
-
};
|
|
594
|
-
pubListeners[id][type2].push(cb);
|
|
595
|
-
},
|
|
596
|
-
off: (type2, cb) => {
|
|
597
|
-
let listeners2 = pubListeners[id];
|
|
598
|
-
if (!listeners2)
|
|
599
|
-
return;
|
|
600
|
-
let idx = listeners2[type2].indexOf(cb);
|
|
601
|
-
if (idx >= 0)
|
|
602
|
-
listeners2[type2].splice(idx, 1);
|
|
584
|
+
return new Promise((resolve, reject) => {
|
|
585
|
+
if (!event.id) {
|
|
586
|
+
reject(new Error(`event ${event} has no id`));
|
|
587
|
+
return;
|
|
603
588
|
}
|
|
604
|
-
|
|
589
|
+
let id = event.id;
|
|
590
|
+
trySend([type, event]);
|
|
591
|
+
pubListeners[id] = { resolve, reject };
|
|
592
|
+
});
|
|
605
593
|
}
|
|
606
594
|
return {
|
|
607
595
|
url,
|
|
@@ -658,19 +646,19 @@ function relayInit(url, options = {}) {
|
|
|
658
646
|
resolve(event);
|
|
659
647
|
});
|
|
660
648
|
}),
|
|
661
|
-
publish(event) {
|
|
662
|
-
|
|
649
|
+
async publish(event) {
|
|
650
|
+
await _publishEvent(event, "EVENT");
|
|
663
651
|
},
|
|
664
|
-
auth(event) {
|
|
665
|
-
|
|
652
|
+
async auth(event) {
|
|
653
|
+
await _publishEvent(event, "AUTH");
|
|
666
654
|
},
|
|
667
655
|
connect,
|
|
668
656
|
close() {
|
|
669
657
|
listeners = newListeners();
|
|
670
658
|
subListeners = {};
|
|
671
659
|
pubListeners = {};
|
|
672
|
-
if (ws
|
|
673
|
-
ws
|
|
660
|
+
if (ws?.readyState === WebSocket.OPEN) {
|
|
661
|
+
ws.close();
|
|
674
662
|
}
|
|
675
663
|
},
|
|
676
664
|
get status() {
|
|
@@ -683,14 +671,17 @@ function relayInit(url, options = {}) {
|
|
|
683
671
|
var SimplePool = class {
|
|
684
672
|
_conn;
|
|
685
673
|
_seenOn = {};
|
|
674
|
+
batchedByKey = {};
|
|
686
675
|
eoseSubTimeout;
|
|
687
676
|
getTimeout;
|
|
688
677
|
seenOnEnabled = true;
|
|
678
|
+
batchInterval = 100;
|
|
689
679
|
constructor(options = {}) {
|
|
690
680
|
this._conn = {};
|
|
691
681
|
this.eoseSubTimeout = options.eoseSubTimeout || 3400;
|
|
692
682
|
this.getTimeout = options.getTimeout || 3400;
|
|
693
683
|
this.seenOnEnabled = options.seenOnEnabled !== false;
|
|
684
|
+
this.batchInterval = options.batchInterval || 100;
|
|
694
685
|
}
|
|
695
686
|
close(relays) {
|
|
696
687
|
relays.forEach((url) => {
|
|
@@ -735,7 +726,7 @@ var SimplePool = class {
|
|
|
735
726
|
for (let cb of eoseListeners.values())
|
|
736
727
|
cb();
|
|
737
728
|
}, this.eoseSubTimeout);
|
|
738
|
-
relays.forEach(async (relay) => {
|
|
729
|
+
relays.filter((r, i, a) => a.indexOf(r) == i).forEach(async (relay) => {
|
|
739
730
|
let r;
|
|
740
731
|
try {
|
|
741
732
|
r = await this.ensureRelay(relay);
|
|
@@ -817,38 +808,54 @@ var SimplePool = class {
|
|
|
817
808
|
});
|
|
818
809
|
});
|
|
819
810
|
}
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
} };
|
|
830
|
-
}
|
|
831
|
-
});
|
|
832
|
-
const callbackMap = /* @__PURE__ */ new Map();
|
|
833
|
-
return {
|
|
834
|
-
on(type, cb) {
|
|
835
|
-
relays.forEach(async (relay, i) => {
|
|
836
|
-
let pub = await pubPromises[i];
|
|
837
|
-
let callback = () => cb(relay);
|
|
838
|
-
callbackMap.set(cb, callback);
|
|
839
|
-
pub.on(type, callback);
|
|
840
|
-
});
|
|
841
|
-
},
|
|
842
|
-
off(type, cb) {
|
|
843
|
-
relays.forEach(async (_, i) => {
|
|
844
|
-
let callback = callbackMap.get(cb);
|
|
845
|
-
if (callback) {
|
|
846
|
-
let pub = await pubPromises[i];
|
|
847
|
-
pub.off(type, callback);
|
|
811
|
+
batchedList(batchKey, relays, filters) {
|
|
812
|
+
return new Promise((resolve) => {
|
|
813
|
+
if (!this.batchedByKey[batchKey]) {
|
|
814
|
+
this.batchedByKey[batchKey] = [
|
|
815
|
+
{
|
|
816
|
+
filters,
|
|
817
|
+
relays,
|
|
818
|
+
resolve,
|
|
819
|
+
events: []
|
|
848
820
|
}
|
|
821
|
+
];
|
|
822
|
+
setTimeout(() => {
|
|
823
|
+
Object.keys(this.batchedByKey).forEach(async (batchKey2) => {
|
|
824
|
+
const batchedRequests = this.batchedByKey[batchKey2];
|
|
825
|
+
const filters2 = [];
|
|
826
|
+
const relays2 = [];
|
|
827
|
+
batchedRequests.forEach((br) => {
|
|
828
|
+
filters2.push(...br.filters);
|
|
829
|
+
relays2.push(...br.relays);
|
|
830
|
+
});
|
|
831
|
+
const sub = this.sub(relays2, filters2);
|
|
832
|
+
sub.on("event", (event) => {
|
|
833
|
+
batchedRequests.forEach(
|
|
834
|
+
(br) => matchFilters(br.filters, event) && br.events.push(event)
|
|
835
|
+
);
|
|
836
|
+
});
|
|
837
|
+
sub.on("eose", () => {
|
|
838
|
+
sub.unsub();
|
|
839
|
+
batchedRequests.forEach((br) => br.resolve(br.events));
|
|
840
|
+
});
|
|
841
|
+
delete this.batchedByKey[batchKey2];
|
|
842
|
+
});
|
|
843
|
+
}, this.batchInterval);
|
|
844
|
+
} else {
|
|
845
|
+
this.batchedByKey[batchKey].push({
|
|
846
|
+
filters,
|
|
847
|
+
relays,
|
|
848
|
+
resolve,
|
|
849
|
+
events: []
|
|
849
850
|
});
|
|
850
851
|
}
|
|
851
|
-
};
|
|
852
|
+
});
|
|
853
|
+
}
|
|
854
|
+
publish(relays, event) {
|
|
855
|
+
return relays.map(async (relay) => {
|
|
856
|
+
let r = await this.ensureRelay(relay);
|
|
857
|
+
return r.publish(event);
|
|
858
|
+
});
|
|
852
859
|
}
|
|
853
860
|
seenOn(id) {
|
|
854
861
|
return Array.from(this._seenOn[id]?.values?.() || []);
|
|
@@ -1578,6 +1585,107 @@ function replaceAll(content, replacer) {
|
|
|
1578
1585
|
});
|
|
1579
1586
|
}
|
|
1580
1587
|
|
|
1588
|
+
// nip28.ts
|
|
1589
|
+
var nip28_exports = {};
|
|
1590
|
+
__export(nip28_exports, {
|
|
1591
|
+
channelCreateEvent: () => channelCreateEvent,
|
|
1592
|
+
channelHideMessageEvent: () => channelHideMessageEvent,
|
|
1593
|
+
channelMessageEvent: () => channelMessageEvent,
|
|
1594
|
+
channelMetadataEvent: () => channelMetadataEvent,
|
|
1595
|
+
channelMuteUserEvent: () => channelMuteUserEvent
|
|
1596
|
+
});
|
|
1597
|
+
var channelCreateEvent = (t, privateKey) => {
|
|
1598
|
+
let content;
|
|
1599
|
+
if (typeof t.content === "object") {
|
|
1600
|
+
content = JSON.stringify(t.content);
|
|
1601
|
+
} else if (typeof t.content === "string") {
|
|
1602
|
+
content = t.content;
|
|
1603
|
+
} else {
|
|
1604
|
+
return void 0;
|
|
1605
|
+
}
|
|
1606
|
+
return finishEvent(
|
|
1607
|
+
{
|
|
1608
|
+
kind: 40 /* ChannelCreation */,
|
|
1609
|
+
tags: [...t.tags ?? []],
|
|
1610
|
+
content,
|
|
1611
|
+
created_at: t.created_at
|
|
1612
|
+
},
|
|
1613
|
+
privateKey
|
|
1614
|
+
);
|
|
1615
|
+
};
|
|
1616
|
+
var channelMetadataEvent = (t, privateKey) => {
|
|
1617
|
+
let content;
|
|
1618
|
+
if (typeof t.content === "object") {
|
|
1619
|
+
content = JSON.stringify(t.content);
|
|
1620
|
+
} else if (typeof t.content === "string") {
|
|
1621
|
+
content = t.content;
|
|
1622
|
+
} else {
|
|
1623
|
+
return void 0;
|
|
1624
|
+
}
|
|
1625
|
+
return finishEvent(
|
|
1626
|
+
{
|
|
1627
|
+
kind: 41 /* ChannelMetadata */,
|
|
1628
|
+
tags: [["e", t.channel_create_event_id], ...t.tags ?? []],
|
|
1629
|
+
content,
|
|
1630
|
+
created_at: t.created_at
|
|
1631
|
+
},
|
|
1632
|
+
privateKey
|
|
1633
|
+
);
|
|
1634
|
+
};
|
|
1635
|
+
var channelMessageEvent = (t, privateKey) => {
|
|
1636
|
+
const tags = [["e", t.channel_create_event_id, t.relay_url, "root"]];
|
|
1637
|
+
if (t.reply_to_channel_message_event_id) {
|
|
1638
|
+
tags.push(["e", t.reply_to_channel_message_event_id, t.relay_url, "reply"]);
|
|
1639
|
+
}
|
|
1640
|
+
return finishEvent(
|
|
1641
|
+
{
|
|
1642
|
+
kind: 42 /* ChannelMessage */,
|
|
1643
|
+
tags: [...tags, ...t.tags ?? []],
|
|
1644
|
+
content: t.content,
|
|
1645
|
+
created_at: t.created_at
|
|
1646
|
+
},
|
|
1647
|
+
privateKey
|
|
1648
|
+
);
|
|
1649
|
+
};
|
|
1650
|
+
var channelHideMessageEvent = (t, privateKey) => {
|
|
1651
|
+
let content;
|
|
1652
|
+
if (typeof t.content === "object") {
|
|
1653
|
+
content = JSON.stringify(t.content);
|
|
1654
|
+
} else if (typeof t.content === "string") {
|
|
1655
|
+
content = t.content;
|
|
1656
|
+
} else {
|
|
1657
|
+
return void 0;
|
|
1658
|
+
}
|
|
1659
|
+
return finishEvent(
|
|
1660
|
+
{
|
|
1661
|
+
kind: 43 /* ChannelHideMessage */,
|
|
1662
|
+
tags: [["e", t.channel_message_event_id], ...t.tags ?? []],
|
|
1663
|
+
content,
|
|
1664
|
+
created_at: t.created_at
|
|
1665
|
+
},
|
|
1666
|
+
privateKey
|
|
1667
|
+
);
|
|
1668
|
+
};
|
|
1669
|
+
var channelMuteUserEvent = (t, privateKey) => {
|
|
1670
|
+
let content;
|
|
1671
|
+
if (typeof t.content === "object") {
|
|
1672
|
+
content = JSON.stringify(t.content);
|
|
1673
|
+
} else if (typeof t.content === "string") {
|
|
1674
|
+
content = t.content;
|
|
1675
|
+
} else {
|
|
1676
|
+
return void 0;
|
|
1677
|
+
}
|
|
1678
|
+
return finishEvent(
|
|
1679
|
+
{
|
|
1680
|
+
kind: 44 /* ChannelMuteUser */,
|
|
1681
|
+
tags: [["p", t.pubkey_to_mute], ...t.tags ?? []],
|
|
1682
|
+
content,
|
|
1683
|
+
created_at: t.created_at
|
|
1684
|
+
},
|
|
1685
|
+
privateKey
|
|
1686
|
+
);
|
|
1687
|
+
};
|
|
1688
|
+
|
|
1581
1689
|
// nip39.ts
|
|
1582
1690
|
var nip39_exports = {};
|
|
1583
1691
|
__export(nip39_exports, {
|
|
@@ -1620,19 +1728,46 @@ var authenticate = async ({
|
|
|
1620
1728
|
],
|
|
1621
1729
|
content: ""
|
|
1622
1730
|
};
|
|
1623
|
-
|
|
1624
|
-
return new Promise((resolve, reject) => {
|
|
1625
|
-
pub.on("ok", function ok() {
|
|
1626
|
-
pub.off("ok", ok);
|
|
1627
|
-
resolve();
|
|
1628
|
-
});
|
|
1629
|
-
pub.on("failed", function fail(reason) {
|
|
1630
|
-
pub.off("failed", fail);
|
|
1631
|
-
reject(reason);
|
|
1632
|
-
});
|
|
1633
|
-
});
|
|
1731
|
+
return relay.auth(await sign(e));
|
|
1634
1732
|
};
|
|
1635
1733
|
|
|
1734
|
+
// nip44.ts
|
|
1735
|
+
var nip44_exports = {};
|
|
1736
|
+
__export(nip44_exports, {
|
|
1737
|
+
decrypt: () => decrypt2,
|
|
1738
|
+
encrypt: () => encrypt2,
|
|
1739
|
+
getSharedSecret: () => getSharedSecret
|
|
1740
|
+
});
|
|
1741
|
+
import { base64 as base642 } from "@scure/base";
|
|
1742
|
+
import { randomBytes as randomBytes2 } from "@noble/hashes/utils";
|
|
1743
|
+
import { secp256k1 as secp256k12 } from "@noble/curves/secp256k1";
|
|
1744
|
+
import { sha256 as sha2563 } from "@noble/hashes/sha256";
|
|
1745
|
+
import { xchacha20 } from "@noble/ciphers/chacha";
|
|
1746
|
+
var getSharedSecret = (privkey, pubkey) => sha2563(secp256k12.getSharedSecret(privkey, "02" + pubkey).subarray(1, 33));
|
|
1747
|
+
function encrypt2(key, text, v = 1) {
|
|
1748
|
+
if (v !== 1) {
|
|
1749
|
+
throw new Error("NIP44: unknown encryption version");
|
|
1750
|
+
}
|
|
1751
|
+
const nonce = randomBytes2(24);
|
|
1752
|
+
const plaintext = utf8Encoder.encode(text);
|
|
1753
|
+
const ciphertext = xchacha20(key, nonce, plaintext);
|
|
1754
|
+
const payload = new Uint8Array(25 + ciphertext.length);
|
|
1755
|
+
payload.set([v], 0);
|
|
1756
|
+
payload.set(nonce, 1);
|
|
1757
|
+
payload.set(ciphertext, 25);
|
|
1758
|
+
return base642.encode(payload);
|
|
1759
|
+
}
|
|
1760
|
+
function decrypt2(key, payload) {
|
|
1761
|
+
let data = base642.decode(payload);
|
|
1762
|
+
if (data[0] !== 1) {
|
|
1763
|
+
throw new Error(`NIP44: unknown encryption version: ${data[0]}`);
|
|
1764
|
+
}
|
|
1765
|
+
const nonce = data.slice(1, 25);
|
|
1766
|
+
const ciphertext = data.slice(25);
|
|
1767
|
+
const plaintext = xchacha20(key, nonce, ciphertext);
|
|
1768
|
+
return utf8Decoder.decode(plaintext);
|
|
1769
|
+
}
|
|
1770
|
+
|
|
1636
1771
|
// nip57.ts
|
|
1637
1772
|
var nip57_exports = {};
|
|
1638
1773
|
__export(nip57_exports, {
|
|
@@ -1754,15 +1889,15 @@ function makeZapReceipt({
|
|
|
1754
1889
|
var nip98_exports = {};
|
|
1755
1890
|
__export(nip98_exports, {
|
|
1756
1891
|
getToken: () => getToken,
|
|
1892
|
+
unpackEventFromToken: () => unpackEventFromToken,
|
|
1893
|
+
validateEvent: () => validateEvent2,
|
|
1757
1894
|
validateToken: () => validateToken
|
|
1758
1895
|
});
|
|
1759
|
-
import { base64 as
|
|
1896
|
+
import { base64 as base643 } from "@scure/base";
|
|
1760
1897
|
var _authorizationScheme = "Nostr ";
|
|
1761
1898
|
async function getToken(loginUrl, httpMethod, sign, includeAuthorizationScheme = false) {
|
|
1762
1899
|
if (!loginUrl || !httpMethod)
|
|
1763
1900
|
throw new Error("Missing loginUrl or httpMethod");
|
|
1764
|
-
if (httpMethod !== "get" /* Get */ && httpMethod !== "post" /* Post */)
|
|
1765
|
-
throw new Error("Unknown httpMethod");
|
|
1766
1901
|
const event = getBlankEvent(27235 /* HttpAuth */);
|
|
1767
1902
|
event.tags = [
|
|
1768
1903
|
["u", loginUrl],
|
|
@@ -1771,18 +1906,30 @@ async function getToken(loginUrl, httpMethod, sign, includeAuthorizationScheme =
|
|
|
1771
1906
|
event.created_at = Math.round(new Date().getTime() / 1e3);
|
|
1772
1907
|
const signedEvent = await sign(event);
|
|
1773
1908
|
const authorizationScheme = includeAuthorizationScheme ? _authorizationScheme : "";
|
|
1774
|
-
return authorizationScheme +
|
|
1909
|
+
return authorizationScheme + base643.encode(utf8Encoder.encode(JSON.stringify(signedEvent)));
|
|
1775
1910
|
}
|
|
1776
1911
|
async function validateToken(token, url, method) {
|
|
1912
|
+
const event = await unpackEventFromToken(token).catch((error) => {
|
|
1913
|
+
throw error;
|
|
1914
|
+
});
|
|
1915
|
+
const valid = await validateEvent2(event, url, method).catch((error) => {
|
|
1916
|
+
throw error;
|
|
1917
|
+
});
|
|
1918
|
+
return valid;
|
|
1919
|
+
}
|
|
1920
|
+
async function unpackEventFromToken(token) {
|
|
1777
1921
|
if (!token) {
|
|
1778
1922
|
throw new Error("Missing token");
|
|
1779
1923
|
}
|
|
1780
1924
|
token = token.replace(_authorizationScheme, "");
|
|
1781
|
-
const eventB64 = utf8Decoder.decode(
|
|
1925
|
+
const eventB64 = utf8Decoder.decode(base643.decode(token));
|
|
1782
1926
|
if (!eventB64 || eventB64.length === 0 || !eventB64.startsWith("{")) {
|
|
1783
1927
|
throw new Error("Invalid token");
|
|
1784
1928
|
}
|
|
1785
1929
|
const event = JSON.parse(eventB64);
|
|
1930
|
+
return event;
|
|
1931
|
+
}
|
|
1932
|
+
async function validateEvent2(event, url, method) {
|
|
1786
1933
|
if (!event) {
|
|
1787
1934
|
throw new Error("Invalid nostr event");
|
|
1788
1935
|
}
|
|
@@ -1832,8 +1979,10 @@ export {
|
|
|
1832
1979
|
nip25_exports as nip25,
|
|
1833
1980
|
nip26_exports as nip26,
|
|
1834
1981
|
nip27_exports as nip27,
|
|
1982
|
+
nip28_exports as nip28,
|
|
1835
1983
|
nip39_exports as nip39,
|
|
1836
1984
|
nip42_exports as nip42,
|
|
1985
|
+
nip44_exports as nip44,
|
|
1837
1986
|
nip57_exports as nip57,
|
|
1838
1987
|
nip98_exports as nip98,
|
|
1839
1988
|
parseReferences,
|