@unicitylabs/nostr-js-sdk 0.1.1 → 0.2.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.
- package/README.md +115 -12
- package/dist/browser/index.js +1685 -80
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/index.min.js +7 -6
- package/dist/browser/index.min.js.map +1 -1
- package/dist/browser/index.umd.js +1694 -85
- package/dist/browser/index.umd.js.map +1 -1
- package/dist/browser/index.umd.min.js +7 -6
- package/dist/browser/index.umd.min.js.map +1 -1
- package/dist/cjs/NostrKeyManager.js +57 -0
- package/dist/cjs/NostrKeyManager.js.map +1 -1
- package/dist/cjs/client/NostrClient.js +46 -0
- package/dist/cjs/client/NostrClient.js.map +1 -1
- package/dist/cjs/crypto/index.js +4 -2
- package/dist/cjs/crypto/index.js.map +1 -1
- package/dist/cjs/crypto/nip04.js +14 -3
- package/dist/cjs/crypto/nip04.js.map +1 -1
- package/dist/cjs/crypto/nip44.js +297 -0
- package/dist/cjs/crypto/nip44.js.map +1 -0
- package/dist/cjs/index.js +27 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/messaging/index.js +24 -0
- package/dist/cjs/messaging/index.js.map +1 -0
- package/dist/cjs/messaging/nip17.js +267 -0
- package/dist/cjs/messaging/nip17.js.map +1 -0
- package/dist/cjs/messaging/types.js +20 -0
- package/dist/cjs/messaging/types.js.map +1 -0
- package/dist/cjs/nametag/NametagUtils.js +1 -1
- package/dist/cjs/nametag/NametagUtils.js.map +1 -1
- package/dist/cjs/payment/PaymentRequestProtocol.js +2 -0
- package/dist/cjs/payment/PaymentRequestProtocol.js.map +1 -1
- package/dist/cjs/protocol/EventKinds.js +13 -1
- package/dist/cjs/protocol/EventKinds.js.map +1 -1
- package/dist/cjs/token/TokenTransferProtocol.js +35 -5
- package/dist/cjs/token/TokenTransferProtocol.js.map +1 -1
- package/dist/esm/NostrKeyManager.js +57 -0
- package/dist/esm/NostrKeyManager.js.map +1 -1
- package/dist/esm/client/NostrClient.js +46 -0
- package/dist/esm/client/NostrClient.js.map +1 -1
- package/dist/esm/crypto/index.js +3 -1
- package/dist/esm/crypto/index.js.map +1 -1
- package/dist/esm/crypto/nip04.js +14 -3
- package/dist/esm/crypto/nip04.js.map +1 -1
- package/dist/esm/crypto/nip44.js +283 -0
- package/dist/esm/crypto/nip44.js.map +1 -0
- package/dist/esm/index.js +4 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/messaging/index.js +8 -0
- package/dist/esm/messaging/index.js.map +1 -0
- package/dist/esm/messaging/nip17.js +229 -0
- package/dist/esm/messaging/nip17.js.map +1 -0
- package/dist/esm/messaging/types.js +16 -0
- package/dist/esm/messaging/types.js.map +1 -0
- package/dist/esm/nametag/NametagUtils.js +1 -1
- package/dist/esm/nametag/NametagUtils.js.map +1 -1
- package/dist/esm/payment/PaymentRequestProtocol.js +2 -0
- package/dist/esm/payment/PaymentRequestProtocol.js.map +1 -1
- package/dist/esm/protocol/EventKinds.js +12 -0
- package/dist/esm/protocol/EventKinds.js.map +1 -1
- package/dist/esm/token/TokenTransferProtocol.js +34 -5
- package/dist/esm/token/TokenTransferProtocol.js.map +1 -1
- package/dist/types/NostrKeyManager.d.ts +36 -0
- package/dist/types/NostrKeyManager.d.ts.map +1 -1
- package/dist/types/client/NostrClient.d.ts +31 -0
- package/dist/types/client/NostrClient.d.ts.map +1 -1
- package/dist/types/crypto/index.d.ts +1 -1
- package/dist/types/crypto/index.d.ts.map +1 -1
- package/dist/types/crypto/nip04.d.ts.map +1 -1
- package/dist/types/crypto/nip44.d.ts +78 -0
- package/dist/types/crypto/nip44.d.ts.map +1 -0
- package/dist/types/index.d.ts +4 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/messaging/index.d.ts +8 -0
- package/dist/types/messaging/index.d.ts.map +1 -0
- package/dist/types/messaging/nip17.d.ts +42 -0
- package/dist/types/messaging/nip17.d.ts.map +1 -0
- package/dist/types/messaging/types.d.ts +59 -0
- package/dist/types/messaging/types.d.ts.map +1 -0
- package/dist/types/payment/PaymentRequestProtocol.d.ts.map +1 -1
- package/dist/types/protocol/EventKinds.d.ts +6 -0
- package/dist/types/protocol/EventKinds.d.ts.map +1 -1
- package/dist/types/token/TokenTransferProtocol.d.ts +22 -3
- package/dist/types/token/TokenTransferProtocol.d.ts.map +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -4,8 +4,10 @@ A TypeScript SDK for Nostr protocol with Unicity extensions. Works in both Node.
|
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
+
- **NIP-17 Private Messages** - Gift-wrapped private direct messages with sender anonymity
|
|
8
|
+
- **NIP-44 Encryption** - Modern ChaCha20-Poly1305 AEAD encryption with HKDF
|
|
7
9
|
- **BIP-340 Schnorr Signatures** - Full support for secp256k1 Schnorr signatures
|
|
8
|
-
- **NIP-04 Encryption** - AES-256-CBC encryption with ECDH key agreement
|
|
10
|
+
- **NIP-04 Encryption** - Legacy AES-256-CBC encryption with ECDH key agreement
|
|
9
11
|
- **GZIP Compression** - Automatic compression for large messages (>1KB)
|
|
10
12
|
- **Multi-Relay Support** - Connect to multiple relays with automatic reconnection
|
|
11
13
|
- **Token Transfers** - Encrypted Unicity token transfers over Nostr
|
|
@@ -73,7 +75,7 @@ const event = Event.create(keyManager, {
|
|
|
73
75
|
const eventId = await client.publishEvent(event);
|
|
74
76
|
```
|
|
75
77
|
|
|
76
|
-
### Encrypted Direct Messages
|
|
78
|
+
### Encrypted Direct Messages (NIP-04 Legacy)
|
|
77
79
|
|
|
78
80
|
```typescript
|
|
79
81
|
// Send encrypted DM
|
|
@@ -85,6 +87,67 @@ const encrypted = await keyManager.encryptHex('Hello!', recipientPubkey);
|
|
|
85
87
|
const decrypted = await keyManager.decryptHex(encrypted, senderPubkey);
|
|
86
88
|
```
|
|
87
89
|
|
|
90
|
+
### NIP-17 Private Messages (Recommended)
|
|
91
|
+
|
|
92
|
+
NIP-17 provides enhanced privacy using gift-wrapping with ephemeral keys:
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
// Send private message by nametag (auto-resolves to pubkey)
|
|
96
|
+
const eventId = await client.sendPrivateMessageToNametag(
|
|
97
|
+
'alice', // recipient nametag
|
|
98
|
+
'Hello, this is a private message!'
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
// Or send by pubkey directly
|
|
102
|
+
const recipientPubkey = '...';
|
|
103
|
+
const eventId = await client.sendPrivateMessage(
|
|
104
|
+
recipientPubkey,
|
|
105
|
+
'Hello, this is a private message!'
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
// Send reply to a previous message
|
|
109
|
+
const eventId = await client.sendPrivateMessage(
|
|
110
|
+
recipientPubkey,
|
|
111
|
+
'This is a reply!',
|
|
112
|
+
{ replyToEventId: originalEventId }
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
// Send read receipt
|
|
116
|
+
await client.sendReadReceipt(senderPubkey, messageEventId);
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Receive and unwrap private messages:
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
import { Filter, EventKinds } from '@unicitylabs/nostr-sdk';
|
|
123
|
+
|
|
124
|
+
// Subscribe to gift-wrapped messages
|
|
125
|
+
const filter = Filter.builder()
|
|
126
|
+
.kinds(EventKinds.GIFT_WRAP)
|
|
127
|
+
.pTags(keyManager.getPublicKeyHex())
|
|
128
|
+
.build();
|
|
129
|
+
|
|
130
|
+
client.subscribe(filter, {
|
|
131
|
+
onEvent: (event) => {
|
|
132
|
+
try {
|
|
133
|
+
const message = client.unwrapPrivateMessage(event);
|
|
134
|
+
|
|
135
|
+
if (message.kind === EventKinds.CHAT_MESSAGE) {
|
|
136
|
+
console.log('From:', message.senderPubkey);
|
|
137
|
+
console.log('Content:', message.content);
|
|
138
|
+
|
|
139
|
+
// Send read receipt
|
|
140
|
+
client.sendReadReceipt(message.senderPubkey, message.eventId);
|
|
141
|
+
} else if (message.kind === EventKinds.READ_RECEIPT) {
|
|
142
|
+
console.log('Read receipt for:', message.replyToEventId);
|
|
143
|
+
}
|
|
144
|
+
} catch (e) {
|
|
145
|
+
// Message not for us or decryption failed
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
```
|
|
150
|
+
|
|
88
151
|
### Subscriptions
|
|
89
152
|
|
|
90
153
|
```typescript
|
|
@@ -127,8 +190,28 @@ const event = await TokenTransferProtocol.createTokenTransferEvent(
|
|
|
127
190
|
|
|
128
191
|
await client.publishEvent(event);
|
|
129
192
|
|
|
193
|
+
// Create token transfer in response to a payment request
|
|
194
|
+
const paymentRequestEventId = '...'; // Event ID of the original payment request
|
|
195
|
+
const event = await TokenTransferProtocol.createTokenTransferEvent(
|
|
196
|
+
keyManager,
|
|
197
|
+
recipientPubkey,
|
|
198
|
+
tokenJson,
|
|
199
|
+
{
|
|
200
|
+
amount: 100n,
|
|
201
|
+
symbol: 'UNIT',
|
|
202
|
+
replyToEventId: paymentRequestEventId // Links transfer to the payment request
|
|
203
|
+
}
|
|
204
|
+
);
|
|
205
|
+
|
|
130
206
|
// Parse received token transfer
|
|
131
207
|
const tokenJson = await TokenTransferProtocol.parseTokenTransfer(event, keyManager);
|
|
208
|
+
|
|
209
|
+
// Get reply-to event ID (for payment request correlation)
|
|
210
|
+
const replyToId = TokenTransferProtocol.getReplyToEventId(event);
|
|
211
|
+
if (replyToId) {
|
|
212
|
+
// This transfer is in response to a payment request
|
|
213
|
+
const originalRequest = pendingRequests.get(replyToId);
|
|
214
|
+
}
|
|
132
215
|
```
|
|
133
216
|
|
|
134
217
|
### Payment Requests
|
|
@@ -223,6 +306,7 @@ Token transfers use Nostr event kind 31113 with NIP-04 encryption.
|
|
|
223
306
|
| `type` | Yes | Always `"token_transfer"` |
|
|
224
307
|
| `amount` | No | Transfer amount (metadata for filtering) |
|
|
225
308
|
| `symbol` | No | Token symbol (metadata for filtering) |
|
|
309
|
+
| `e` | No | Reply-to event ID (for payment request correlation) |
|
|
226
310
|
|
|
227
311
|
### Encrypted Content
|
|
228
312
|
|
|
@@ -247,10 +331,11 @@ gz:<base64_ciphertext>?iv=<base64_iv>
|
|
|
247
331
|
TokenTransferProtocol.isTokenTransfer(event); // boolean
|
|
248
332
|
|
|
249
333
|
// Get metadata from tags
|
|
250
|
-
TokenTransferProtocol.getAmount(event);
|
|
251
|
-
TokenTransferProtocol.getSymbol(event);
|
|
252
|
-
TokenTransferProtocol.getRecipient(event);
|
|
253
|
-
TokenTransferProtocol.getSender(event);
|
|
334
|
+
TokenTransferProtocol.getAmount(event); // bigint | undefined
|
|
335
|
+
TokenTransferProtocol.getSymbol(event); // string | undefined
|
|
336
|
+
TokenTransferProtocol.getRecipient(event); // string | undefined
|
|
337
|
+
TokenTransferProtocol.getSender(event); // string
|
|
338
|
+
TokenTransferProtocol.getReplyToEventId(event); // string | undefined (payment request correlation)
|
|
254
339
|
```
|
|
255
340
|
|
|
256
341
|
## Payment Request Format
|
|
@@ -350,7 +435,9 @@ const parsed = await PaymentRequestProtocol.parsePaymentRequest(event, keyManage
|
|
|
350
435
|
|
|
351
436
|
- **Bech32** - Bech32 encoding/decoding (npub, nsec)
|
|
352
437
|
- **SchnorrSigner** - BIP-340 Schnorr signatures
|
|
353
|
-
- **NIP04** - NIP-04 encryption/decryption
|
|
438
|
+
- **NIP04** - NIP-04 encryption/decryption (legacy)
|
|
439
|
+
- **NIP44** - NIP-44 encryption/decryption (ChaCha20-Poly1305)
|
|
440
|
+
- **NIP17** - NIP-17 private direct messages with gift-wrapping
|
|
354
441
|
- **EventKinds** - Event kind constants
|
|
355
442
|
- **NametagUtils** - Nametag normalization and hashing
|
|
356
443
|
- **NametagBinding** - Nametag binding event creation
|
|
@@ -363,7 +450,11 @@ const parsed = await PaymentRequestProtocol.parsePaymentRequest(event, keyManage
|
|
|
363
450
|
|------|------|-------------|
|
|
364
451
|
| 0 | PROFILE | User profile metadata |
|
|
365
452
|
| 1 | TEXT_NOTE | Short text note |
|
|
366
|
-
| 4 | ENCRYPTED_DM | Encrypted direct message |
|
|
453
|
+
| 4 | ENCRYPTED_DM | Encrypted direct message (NIP-04) |
|
|
454
|
+
| 13 | SEAL | Encrypted seal for gift-wrapping (NIP-17) |
|
|
455
|
+
| 14 | CHAT_MESSAGE | Private direct message rumor (NIP-17) |
|
|
456
|
+
| 15 | READ_RECEIPT | Read receipt rumor (NIP-17) |
|
|
457
|
+
| 1059 | GIFT_WRAP | Gift-wrapped message (NIP-17) |
|
|
367
458
|
| 30078 | APP_DATA | Application-specific data (nametag bindings) |
|
|
368
459
|
| 31111 | AGENT_PROFILE | Agent profile information |
|
|
369
460
|
| 31112 | AGENT_LOCATION | Agent GPS location |
|
|
@@ -392,22 +483,34 @@ npm run lint
|
|
|
392
483
|
|
|
393
484
|
## E2E Testing with Relay
|
|
394
485
|
|
|
486
|
+
### NIP-17 Private Messages
|
|
487
|
+
|
|
488
|
+
```bash
|
|
489
|
+
# Run NIP-17 E2E tests against real relay
|
|
490
|
+
npm test tests/integration/nip17-relay.test.ts
|
|
491
|
+
|
|
492
|
+
# Use a custom relay
|
|
493
|
+
NOSTR_TEST_RELAY=wss://your-relay.com npm test tests/integration/nip17-relay.test.ts
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
### Payment Requests (Manual)
|
|
497
|
+
|
|
395
498
|
To test payment requests against a real wallet:
|
|
396
499
|
|
|
397
500
|
```bash
|
|
398
501
|
# Send a single payment request
|
|
399
|
-
TARGET_NAMETAG=mp-
|
|
502
|
+
TARGET_NAMETAG=mp-9 npm test -- --testNamePattern="send single payment request"
|
|
400
503
|
|
|
401
504
|
# Send multiple payment requests (for UI testing)
|
|
402
|
-
TARGET_NAMETAG=mp-
|
|
505
|
+
TARGET_NAMETAG=mp-9 npm test -- --testNamePattern="send multiple payment requests"
|
|
403
506
|
|
|
404
507
|
# Full flow with token transfer verification (requires wallet interaction)
|
|
405
|
-
TARGET_NAMETAG=mp-
|
|
508
|
+
TARGET_NAMETAG=mp-9 npm test -- --testNamePattern="full payment request flow"
|
|
406
509
|
```
|
|
407
510
|
|
|
408
511
|
Environment variables:
|
|
409
512
|
- `TARGET_NAMETAG` - Nametag of the wallet to send requests to (required)
|
|
410
|
-
- `
|
|
513
|
+
- `NOSTR_TEST_RELAY` - Relay URL (default: `wss://nostr-relay.testnet.unicity.network`)
|
|
411
514
|
- `AMOUNT` - Amount in smallest units (default: `1000000`)
|
|
412
515
|
- `TIMEOUT` - Timeout in seconds for full flow test (default: `120`)
|
|
413
516
|
|