nostr-tools 1.14.2 → 1.16.0
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 +49 -61
- package/lib/esm/nostr.mjs +177 -127
- package/lib/esm/nostr.mjs.map +4 -4
- package/lib/event.d.ts +15 -8
- package/lib/index.d.ts +1 -0
- package/lib/kinds.d.ts +13 -0
- package/lib/kinds.test.d.ts +1 -0
- package/lib/nip13.d.ts +9 -1
- package/lib/nip19.d.ts +1 -0
- package/lib/nip42.d.ts +1 -1
- package/lib/nip47.d.ts +11 -0
- package/lib/nip47.test.d.ts +1 -0
- package/lib/nip57.d.ts +2 -2
- package/lib/nostr.bundle.js +350 -1045
- package/lib/nostr.bundle.js.map +4 -4
- package/lib/nostr.cjs.js +179 -125
- package/lib/nostr.cjs.js.map +4 -4
- package/lib/relay.d.ts +4 -1
- package/package.json +16 -7
package/README.md
CHANGED
|
@@ -12,12 +12,14 @@ This package is only providing lower-level functionality. If you want an easy-to
|
|
|
12
12
|
npm install nostr-tools # or yarn add nostr-tools
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
+
If using TypeScript, this package requires TypeScript >= 5.0.
|
|
16
|
+
|
|
15
17
|
## Usage
|
|
16
18
|
|
|
17
19
|
### Generating a private key and a public key
|
|
18
20
|
|
|
19
21
|
```js
|
|
20
|
-
import {generatePrivateKey, getPublicKey} from 'nostr-tools'
|
|
22
|
+
import { generatePrivateKey, getPublicKey } from 'nostr-tools'
|
|
21
23
|
|
|
22
24
|
let sk = generatePrivateKey() // `sk` is a hex string
|
|
23
25
|
let pk = getPublicKey(sk) // `pk` is a hex string
|
|
@@ -26,20 +28,14 @@ let pk = getPublicKey(sk) // `pk` is a hex string
|
|
|
26
28
|
### Creating, signing and verifying events
|
|
27
29
|
|
|
28
30
|
```js
|
|
29
|
-
import {
|
|
30
|
-
validateEvent,
|
|
31
|
-
verifySignature,
|
|
32
|
-
getSignature,
|
|
33
|
-
getEventHash,
|
|
34
|
-
getPublicKey
|
|
35
|
-
} from 'nostr-tools'
|
|
31
|
+
import { validateEvent, verifySignature, getSignature, getEventHash, getPublicKey } from 'nostr-tools'
|
|
36
32
|
|
|
37
33
|
let event = {
|
|
38
34
|
kind: 1,
|
|
39
35
|
created_at: Math.floor(Date.now() / 1000),
|
|
40
36
|
tags: [],
|
|
41
37
|
content: 'hello',
|
|
42
|
-
pubkey: getPublicKey(privateKey)
|
|
38
|
+
pubkey: getPublicKey(privateKey),
|
|
43
39
|
}
|
|
44
40
|
|
|
45
41
|
event.id = getEventHash(event)
|
|
@@ -52,13 +48,7 @@ let veryOk = verifySignature(event)
|
|
|
52
48
|
### Interacting with a relay
|
|
53
49
|
|
|
54
50
|
```js
|
|
55
|
-
import {
|
|
56
|
-
relayInit,
|
|
57
|
-
generatePrivateKey,
|
|
58
|
-
getPublicKey,
|
|
59
|
-
getEventHash,
|
|
60
|
-
getSignature
|
|
61
|
-
} from 'nostr-tools'
|
|
51
|
+
import { relayInit, finishEvent, generatePrivateKey, getPublicKey } from 'nostr-tools'
|
|
62
52
|
|
|
63
53
|
const relay = relayInit('wss://relay.example.com')
|
|
64
54
|
relay.on('connect', () => {
|
|
@@ -73,8 +63,8 @@ await relay.connect()
|
|
|
73
63
|
// let's query for an event that exists
|
|
74
64
|
let sub = relay.sub([
|
|
75
65
|
{
|
|
76
|
-
ids: ['d7dd5eb3ab747e16f8d0212d53032ea2a7cadef53837e5a6c66d42849fcb9027']
|
|
77
|
-
}
|
|
66
|
+
ids: ['d7dd5eb3ab747e16f8d0212d53032ea2a7cadef53837e5a6c66d42849fcb9027'],
|
|
67
|
+
},
|
|
78
68
|
])
|
|
79
69
|
sub.on('event', event => {
|
|
80
70
|
console.log('we got the event we wanted:', event)
|
|
@@ -90,8 +80,8 @@ let pk = getPublicKey(sk)
|
|
|
90
80
|
let sub = relay.sub([
|
|
91
81
|
{
|
|
92
82
|
kinds: [1],
|
|
93
|
-
authors: [pk]
|
|
94
|
-
}
|
|
83
|
+
authors: [pk],
|
|
84
|
+
},
|
|
95
85
|
])
|
|
96
86
|
|
|
97
87
|
sub.on('event', event => {
|
|
@@ -100,19 +90,18 @@ sub.on('event', event => {
|
|
|
100
90
|
|
|
101
91
|
let event = {
|
|
102
92
|
kind: 1,
|
|
103
|
-
pubkey: pk,
|
|
104
93
|
created_at: Math.floor(Date.now() / 1000),
|
|
105
94
|
tags: [],
|
|
106
|
-
content: 'hello world'
|
|
95
|
+
content: 'hello world',
|
|
107
96
|
}
|
|
108
|
-
event.id = getEventHash(event)
|
|
109
|
-
event.sig = getSignature(event, sk)
|
|
110
97
|
|
|
111
|
-
|
|
98
|
+
// this assigns the pubkey, calculates the event id and signs the event in a single step
|
|
99
|
+
const signedEvent = finishEvent(event, sk)
|
|
100
|
+
await relay.publish(signedEvent)
|
|
112
101
|
|
|
113
|
-
let events = await relay.list([{kinds: [0, 1]}])
|
|
102
|
+
let events = await relay.list([{ kinds: [0, 1] }])
|
|
114
103
|
let event = await relay.get({
|
|
115
|
-
ids: ['44e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245']
|
|
104
|
+
ids: ['44e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245'],
|
|
116
105
|
})
|
|
117
106
|
|
|
118
107
|
relay.close()
|
|
@@ -127,7 +116,7 @@ import 'websocket-polyfill'
|
|
|
127
116
|
### Interacting with multiple relays
|
|
128
117
|
|
|
129
118
|
```js
|
|
130
|
-
import {SimplePool} from 'nostr-tools'
|
|
119
|
+
import { SimplePool } from 'nostr-tools'
|
|
131
120
|
|
|
132
121
|
const pool = new SimplePool()
|
|
133
122
|
|
|
@@ -137,11 +126,9 @@ let sub = pool.sub(
|
|
|
137
126
|
[...relays, 'wss://relay.example3.com'],
|
|
138
127
|
[
|
|
139
128
|
{
|
|
140
|
-
authors: [
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
}
|
|
144
|
-
]
|
|
129
|
+
authors: ['32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245'],
|
|
130
|
+
},
|
|
131
|
+
],
|
|
145
132
|
)
|
|
146
133
|
|
|
147
134
|
sub.on('event', event => {
|
|
@@ -150,31 +137,35 @@ sub.on('event', event => {
|
|
|
150
137
|
})
|
|
151
138
|
|
|
152
139
|
let pubs = pool.publish(relays, newEvent)
|
|
153
|
-
|
|
154
|
-
// this may be called multiple times, once for every relay that accepts the event
|
|
155
|
-
// ...
|
|
156
|
-
})
|
|
140
|
+
await Promise.all(pubs)
|
|
157
141
|
|
|
158
|
-
let events = await pool.list(relays, [{kinds: [0, 1]}])
|
|
142
|
+
let events = await pool.list(relays, [{ kinds: [0, 1] }])
|
|
159
143
|
let event = await pool.get(relays, {
|
|
160
|
-
ids: ['44e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245']
|
|
144
|
+
ids: ['44e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245'],
|
|
161
145
|
})
|
|
162
146
|
|
|
163
|
-
let
|
|
164
|
-
|
|
165
|
-
)
|
|
147
|
+
let batchedEvents = await pool.batchedList('notes', relays, [{ kinds: [1] }])
|
|
148
|
+
// `batchedList` will wait for other function calls with the same `batchKey`
|
|
149
|
+
// (e.g. 'notes', 'authors', etc) within a fixed amount of time (default: `100ms`) before sending
|
|
150
|
+
// next ws request, and batch all requests with similar `batchKey`s together in a single request.
|
|
151
|
+
|
|
152
|
+
let relaysForEvent = pool.seenOn('44e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245')
|
|
166
153
|
// relaysForEvent will be an array of URLs from relays a given event was seen on
|
|
154
|
+
|
|
155
|
+
pool.close()
|
|
167
156
|
```
|
|
168
157
|
|
|
158
|
+
read more details about `batchedList` on this pr: [https://github.com/nbd-wtf/nostr-tools/pull/279](https://github.com/nbd-wtf/nostr-tools/pull/279#issue-1859315757)
|
|
159
|
+
|
|
169
160
|
### Parsing references (mentions) from a content using NIP-10 and NIP-27
|
|
170
161
|
|
|
171
162
|
```js
|
|
172
|
-
import {parseReferences} from 'nostr-tools'
|
|
163
|
+
import { parseReferences } from 'nostr-tools'
|
|
173
164
|
|
|
174
165
|
let references = parseReferences(event)
|
|
175
166
|
let simpleAugmentedContent = event.content
|
|
176
167
|
for (let i = 0; i < references.length; i++) {
|
|
177
|
-
let {text, profile, event, address} = references[i]
|
|
168
|
+
let { text, profile, event, address } = references[i]
|
|
178
169
|
let augmentedReference = profile
|
|
179
170
|
? `<strong>@${profilesCache[profile.pubkey].name}</strong>`
|
|
180
171
|
: event
|
|
@@ -189,7 +180,7 @@ for (let i = 0; i < references.length; i++) {
|
|
|
189
180
|
### Querying profile data from a NIP-05 address
|
|
190
181
|
|
|
191
182
|
```js
|
|
192
|
-
import {nip05} from 'nostr-tools'
|
|
183
|
+
import { nip05 } from 'nostr-tools'
|
|
193
184
|
|
|
194
185
|
let profile = await nip05.queryProfile('jb55.com')
|
|
195
186
|
console.log(profile.pubkey)
|
|
@@ -198,7 +189,7 @@ console.log(profile.relays)
|
|
|
198
189
|
// prints: [wss://relay.damus.io]
|
|
199
190
|
```
|
|
200
191
|
|
|
201
|
-
To use this on Node.js you first must install `node-fetch@2` and call something like this:
|
|
192
|
+
To use this on Node.js < v18, you first must install `node-fetch@2` and call something like this:
|
|
202
193
|
|
|
203
194
|
```js
|
|
204
195
|
nip05.useFetchImplementation(require('node-fetch'))
|
|
@@ -207,27 +198,24 @@ nip05.useFetchImplementation(require('node-fetch'))
|
|
|
207
198
|
### Encoding and decoding NIP-19 codes
|
|
208
199
|
|
|
209
200
|
```js
|
|
210
|
-
import {nip19, generatePrivateKey, getPublicKey} from 'nostr-tools'
|
|
201
|
+
import { nip19, generatePrivateKey, getPublicKey } from 'nostr-tools'
|
|
211
202
|
|
|
212
203
|
let sk = generatePrivateKey()
|
|
213
204
|
let nsec = nip19.nsecEncode(sk)
|
|
214
|
-
let {type, data} = nip19.decode(nsec)
|
|
205
|
+
let { type, data } = nip19.decode(nsec)
|
|
215
206
|
assert(type === 'nsec')
|
|
216
207
|
assert(data === sk)
|
|
217
208
|
|
|
218
209
|
let pk = getPublicKey(generatePrivateKey())
|
|
219
210
|
let npub = nip19.npubEncode(pk)
|
|
220
|
-
let {type, data} = nip19.decode(npub)
|
|
211
|
+
let { type, data } = nip19.decode(npub)
|
|
221
212
|
assert(type === 'npub')
|
|
222
213
|
assert(data === pk)
|
|
223
214
|
|
|
224
215
|
let pk = getPublicKey(generatePrivateKey())
|
|
225
|
-
let relays = [
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
]
|
|
229
|
-
let nprofile = nip19.nprofileEncode({pubkey: pk, relays})
|
|
230
|
-
let {type, data} = nip19.decode(nprofile)
|
|
216
|
+
let relays = ['wss://relay.nostr.example.mydomain.example.com', 'wss://nostr.banana.com']
|
|
217
|
+
let nprofile = nip19.nprofileEncode({ pubkey: pk, relays })
|
|
218
|
+
let { type, data } = nip19.decode(nprofile)
|
|
231
219
|
assert(type === 'nprofile')
|
|
232
220
|
assert(data.pubkey === pk)
|
|
233
221
|
assert(data.relays.length === 2)
|
|
@@ -236,7 +224,7 @@ assert(data.relays.length === 2)
|
|
|
236
224
|
### Encrypting and decrypting direct messages
|
|
237
225
|
|
|
238
226
|
```js
|
|
239
|
-
import {nip04, getPublicKey, generatePrivateKey} from 'nostr-tools'
|
|
227
|
+
import { nip04, getPublicKey, generatePrivateKey } from 'nostr-tools'
|
|
240
228
|
|
|
241
229
|
// sender
|
|
242
230
|
let sk1 = generatePrivateKey()
|
|
@@ -255,13 +243,13 @@ let event = {
|
|
|
255
243
|
pubkey: pk1,
|
|
256
244
|
tags: [['p', pk2]],
|
|
257
245
|
content: ciphertext,
|
|
258
|
-
...otherProperties
|
|
246
|
+
...otherProperties,
|
|
259
247
|
}
|
|
260
248
|
|
|
261
249
|
sendEvent(event)
|
|
262
250
|
|
|
263
251
|
// on the receiver side
|
|
264
|
-
sub.on('event', event => {
|
|
252
|
+
sub.on('event', async event => {
|
|
265
253
|
let sender = event.pubkey
|
|
266
254
|
pk1 === sender
|
|
267
255
|
let plaintext = await nip04.decrypt(sk2, pk1, event.content)
|
|
@@ -271,7 +259,7 @@ sub.on('event', event => {
|
|
|
271
259
|
### Performing and checking for delegation
|
|
272
260
|
|
|
273
261
|
```js
|
|
274
|
-
import {nip26, getPublicKey, generatePrivateKey} from 'nostr-tools'
|
|
262
|
+
import { nip26, getPublicKey, generatePrivateKey } from 'nostr-tools'
|
|
275
263
|
|
|
276
264
|
// delegator
|
|
277
265
|
let sk1 = generatePrivateKey()
|
|
@@ -286,7 +274,7 @@ let delegation = nip26.createDelegation(sk1, {
|
|
|
286
274
|
pubkey: pk2,
|
|
287
275
|
kind: 1,
|
|
288
276
|
since: Math.round(Date.now() / 1000),
|
|
289
|
-
until: Math.round(Date.now() / 1000) + 60 * 60 * 24 * 30 /* 30 days
|
|
277
|
+
until: Math.round(Date.now() / 1000) + 60 * 60 * 24 * 30 /* 30 days */,
|
|
290
278
|
})
|
|
291
279
|
|
|
292
280
|
// the delegatee uses the delegation when building an event
|
|
@@ -295,7 +283,7 @@ let event = {
|
|
|
295
283
|
kind: 1,
|
|
296
284
|
created_at: Math.round(Date.now() / 1000),
|
|
297
285
|
content: 'hello from a delegated key',
|
|
298
|
-
tags: [['delegation', delegation.from, delegation.cond, delegation.sig]]
|
|
286
|
+
tags: [['delegation', delegation.from, delegation.cond, delegation.sig]],
|
|
299
287
|
}
|
|
300
288
|
|
|
301
289
|
// finally any receiver of this event can check for the presence of a valid delegation tag
|