nostr-crypto-utils 0.4.12 → 0.4.13
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 +52 -2
- package/dist/browser/343.nostr-crypto-utils.min.js +1 -0
- package/dist/browser/419.nostr-crypto-utils.min.js +1 -0
- package/dist/browser/crypto.nostr-crypto-utils.min.js +1 -1
- package/dist/browser/main.nostr-crypto-utils.min.js +1 -0
- package/dist/browser/protocol.nostr-crypto-utils.min.js +1 -1
- package/dist/cjs/event/index.d.ts +7 -0
- package/dist/cjs/event/index.d.ts.map +1 -0
- package/dist/cjs/event/index.js +15 -0
- package/dist/cjs/event/index.js.map +1 -0
- package/dist/cjs/event/signing.d.ts +12 -0
- package/dist/cjs/event/signing.d.ts.map +1 -1
- package/dist/cjs/event/signing.js +29 -0
- package/dist/cjs/event/signing.js.map +1 -1
- package/dist/cjs/index.d.ts +11 -8
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +58 -56
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/nips/nip-04.d.ts +1 -1
- package/dist/cjs/nips/nip-04.d.ts.map +1 -1
- package/dist/cjs/nips/nip-04.js +1 -0
- package/dist/cjs/nips/nip-04.js.map +1 -1
- package/dist/cjs/protocol/index.d.ts +9 -9
- package/dist/cjs/protocol/index.d.ts.map +1 -1
- package/dist/cjs/protocol/index.js +8 -9
- package/dist/cjs/protocol/index.js.map +1 -1
- package/dist/cjs/types/base.d.ts +45 -121
- package/dist/cjs/types/base.d.ts.map +1 -1
- package/dist/cjs/types/base.js +10 -28
- package/dist/cjs/types/base.js.map +1 -1
- package/dist/cjs/utils/encoding.d.ts +12 -0
- package/dist/cjs/utils/encoding.d.ts.map +1 -1
- package/dist/cjs/utils/encoding.js +18 -0
- package/dist/cjs/utils/encoding.js.map +1 -1
- package/dist/cjs/utils/integration.d.ts +14 -15
- package/dist/cjs/utils/integration.d.ts.map +1 -1
- package/dist/cjs/utils/integration.js +145 -98
- package/dist/cjs/utils/integration.js.map +1 -1
- package/dist/cjs/utils/logger.d.ts +17 -2
- package/dist/cjs/utils/logger.d.ts.map +1 -1
- package/dist/cjs/utils/logger.js +40 -3
- package/dist/cjs/utils/logger.js.map +1 -1
- package/dist/cjs/utils/validation.d.ts +6 -0
- package/dist/cjs/utils/validation.d.ts.map +1 -1
- package/dist/cjs/utils/validation.js +37 -0
- package/dist/cjs/utils/validation.js.map +1 -1
- package/dist/cjs/validation/keys.d.ts +7 -0
- package/dist/cjs/validation/keys.d.ts.map +1 -0
- package/dist/cjs/validation/keys.js +23 -0
- package/dist/cjs/validation/keys.js.map +1 -0
- package/dist/esm/event/index.d.ts +7 -0
- package/dist/esm/event/index.d.ts.map +1 -0
- package/dist/esm/event/index.js +7 -0
- package/dist/esm/event/index.js.map +1 -0
- package/dist/esm/event/signing.d.ts +12 -0
- package/dist/esm/event/signing.d.ts.map +1 -1
- package/dist/esm/event/signing.js +27 -0
- package/dist/esm/event/signing.js.map +1 -1
- package/dist/esm/index.d.ts +11 -8
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +16 -14
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/nips/nip-04.d.ts +1 -1
- package/dist/esm/nips/nip-04.d.ts.map +1 -1
- package/dist/esm/nips/nip-04.js +1 -0
- package/dist/esm/nips/nip-04.js.map +1 -1
- package/dist/esm/protocol/index.d.ts +9 -9
- package/dist/esm/protocol/index.d.ts.map +1 -1
- package/dist/esm/protocol/index.js +8 -9
- package/dist/esm/protocol/index.js.map +1 -1
- package/dist/esm/types/base.d.ts +45 -121
- package/dist/esm/types/base.d.ts.map +1 -1
- package/dist/esm/types/base.js +10 -28
- package/dist/esm/types/base.js.map +1 -1
- package/dist/esm/utils/encoding.d.ts +12 -0
- package/dist/esm/utils/encoding.d.ts.map +1 -1
- package/dist/esm/utils/encoding.js +16 -0
- package/dist/esm/utils/encoding.js.map +1 -1
- package/dist/esm/utils/integration.d.ts +14 -15
- package/dist/esm/utils/integration.d.ts.map +1 -1
- package/dist/esm/utils/integration.js +136 -89
- package/dist/esm/utils/integration.js.map +1 -1
- package/dist/esm/utils/logger.d.ts +17 -2
- package/dist/esm/utils/logger.d.ts.map +1 -1
- package/dist/esm/utils/logger.js +38 -2
- package/dist/esm/utils/logger.js.map +1 -1
- package/dist/esm/utils/validation.d.ts +6 -0
- package/dist/esm/utils/validation.d.ts.map +1 -1
- package/dist/esm/utils/validation.js +36 -0
- package/dist/esm/utils/validation.js.map +1 -1
- package/dist/esm/validation/keys.d.ts +7 -0
- package/dist/esm/validation/keys.d.ts.map +1 -0
- package/dist/esm/validation/keys.js +20 -0
- package/dist/esm/validation/keys.js.map +1 -0
- package/package.json +1 -1
- package/src/__tests__/integration.test.ts +1 -1
- package/src/__tests__/types.test.ts +36 -242
- package/src/event/index.ts +7 -0
- package/src/event/signing.ts +29 -0
- package/src/index.ts +39 -47
- package/src/nips/nip-04.ts +2 -0
- package/src/protocol/index.ts +23 -14
- package/src/types/base.ts +58 -122
- package/src/utils/encoding.ts +18 -0
- package/src/utils/integration.ts +159 -107
- package/src/utils/logger.ts +46 -2
- package/src/utils/validation.ts +37 -0
- package/src/validation/keys.ts +19 -0
- package/dist/browser/551.nostr-crypto-utils.min.js +0 -1
- package/dist/browser/565.nostr-crypto-utils.min.js +0 -1
- package/dist/browser/69.nostr-crypto-utils.min.js +0 -1
- package/dist/browser/main-43dd7041.nostr-crypto-utils.min.js +0 -1
- package/dist/browser/main-7bd12dde.nostr-crypto-utils.min.js +0 -1
- package/dist/browser/main-d277ceb9.nostr-crypto-utils.min.js +0 -1
|
@@ -77,7 +77,7 @@ describe('Integration Utilities', () => {
|
|
|
77
77
|
});
|
|
78
78
|
|
|
79
79
|
it('should parse OK message', () => {
|
|
80
|
-
const message = ['OK', 'event1', true, 'success'];
|
|
80
|
+
const message = ['OK', 'event1', 'true', 'success'];
|
|
81
81
|
const parsed = parseNostrMessage(message);
|
|
82
82
|
expect(parsed).not.toBeNull();
|
|
83
83
|
if (parsed) {
|
|
@@ -1,150 +1,59 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
NostrEventKind,
|
|
3
|
+
SignedNostrEvent,
|
|
2
4
|
isNostrEvent,
|
|
3
5
|
isSignedNostrEvent,
|
|
4
6
|
isNostrFilter,
|
|
5
|
-
|
|
6
|
-
NostrEvent,
|
|
7
|
-
SignedNostrEvent,
|
|
8
|
-
NostrFilter,
|
|
9
|
-
NostrSubscription,
|
|
10
|
-
NostrEventKind
|
|
7
|
+
NostrFilter
|
|
11
8
|
} from '../types';
|
|
12
9
|
|
|
13
10
|
import { describe, it, expect } from 'vitest';
|
|
14
11
|
|
|
15
12
|
describe('Type Guards', () => {
|
|
16
|
-
describe('
|
|
17
|
-
it('should validate a
|
|
18
|
-
const
|
|
13
|
+
describe('Event Types', () => {
|
|
14
|
+
it('should validate a SignedNostrEvent', () => {
|
|
15
|
+
const signedEvent: SignedNostrEvent = {
|
|
19
16
|
kind: NostrEventKind.TEXT_NOTE,
|
|
20
17
|
created_at: Math.floor(Date.now() / 1000),
|
|
21
18
|
content: 'Hello, Nostr!',
|
|
22
19
|
tags: [['p', '1234'], ['t', 'test']],
|
|
23
|
-
pubkey: '0123456789abcdef'
|
|
20
|
+
pubkey: '0123456789abcdef',
|
|
21
|
+
id: '0123456789abcdef',
|
|
22
|
+
sig: '0123456789abcdef'
|
|
24
23
|
};
|
|
25
24
|
|
|
26
|
-
expect(
|
|
25
|
+
expect(isSignedNostrEvent(signedEvent)).toBe(true);
|
|
27
26
|
});
|
|
28
27
|
|
|
29
|
-
it('should
|
|
30
|
-
const
|
|
31
|
-
kind: NostrEventKind.
|
|
28
|
+
it('should handle NIP-42 authentication events', () => {
|
|
29
|
+
const authEvent: SignedNostrEvent = {
|
|
30
|
+
kind: NostrEventKind.AUTH_RESPONSE,
|
|
32
31
|
created_at: Math.floor(Date.now() / 1000),
|
|
33
|
-
content: '
|
|
34
|
-
tags: []
|
|
32
|
+
content: 'challenge-response',
|
|
33
|
+
tags: [['challenge', '1234']],
|
|
34
|
+
pubkey: '0123456789abcdef',
|
|
35
|
+
id: '0123456789abcdef',
|
|
36
|
+
sig: '0123456789abcdef'
|
|
35
37
|
};
|
|
36
38
|
|
|
37
|
-
expect(
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
it('should reject invalid NostrEvent objects', () => {
|
|
41
|
-
const invalidEvents = [
|
|
42
|
-
null,
|
|
43
|
-
undefined,
|
|
44
|
-
{},
|
|
45
|
-
{ kind: 'not a number' },
|
|
46
|
-
{ kind: 1, created_at: 'not a number' },
|
|
47
|
-
{ kind: 1, created_at: 123, content: 42 },
|
|
48
|
-
{ kind: 1, created_at: 123, content: 'valid', tags: 'not an array' },
|
|
49
|
-
{ kind: 1, created_at: 123, content: 'valid', tags: [['valid'], 42] },
|
|
50
|
-
{ kind: 1, created_at: 123, content: 'valid', tags: [], pubkey: 42 }
|
|
51
|
-
];
|
|
52
|
-
|
|
53
|
-
invalidEvents.forEach(event => {
|
|
54
|
-
expect(isNostrEvent(event)).toBe(false);
|
|
55
|
-
});
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
it('should handle edge cases for NostrEvent', () => {
|
|
59
|
-
const edgeCases: NostrEvent[] = [
|
|
60
|
-
// Large tag array
|
|
61
|
-
{
|
|
62
|
-
kind: NostrEventKind.TEXT_NOTE,
|
|
63
|
-
created_at: Math.floor(Date.now() / 1000),
|
|
64
|
-
content: 'Test',
|
|
65
|
-
tags: Array(1000).fill(['p', '1234']),
|
|
66
|
-
},
|
|
67
|
-
// Unicode content
|
|
68
|
-
{
|
|
69
|
-
kind: NostrEventKind.TEXT_NOTE,
|
|
70
|
-
created_at: Math.floor(Date.now() / 1000),
|
|
71
|
-
content: '🦄 Unicode test 漢字',
|
|
72
|
-
tags: [],
|
|
73
|
-
},
|
|
74
|
-
// Zero timestamp
|
|
75
|
-
{
|
|
76
|
-
kind: NostrEventKind.TEXT_NOTE,
|
|
77
|
-
created_at: 0,
|
|
78
|
-
content: 'Test',
|
|
79
|
-
tags: [],
|
|
80
|
-
},
|
|
81
|
-
// Reserved event kind
|
|
82
|
-
{
|
|
83
|
-
kind: 10000,
|
|
84
|
-
created_at: Math.floor(Date.now() / 1000),
|
|
85
|
-
content: 'Test',
|
|
86
|
-
tags: [],
|
|
87
|
-
},
|
|
88
|
-
// Empty content
|
|
89
|
-
{
|
|
90
|
-
kind: NostrEventKind.TEXT_NOTE,
|
|
91
|
-
created_at: Math.floor(Date.now() / 1000),
|
|
92
|
-
content: '',
|
|
93
|
-
tags: [],
|
|
94
|
-
}
|
|
95
|
-
];
|
|
96
|
-
|
|
97
|
-
edgeCases.forEach(event => {
|
|
98
|
-
expect(isNostrEvent(event)).toBe(true);
|
|
99
|
-
});
|
|
39
|
+
expect(isSignedNostrEvent(authEvent)).toBe(true);
|
|
40
|
+
expect(authEvent.kind).toBe(NostrEventKind.AUTH_RESPONSE);
|
|
100
41
|
});
|
|
101
42
|
});
|
|
102
43
|
|
|
103
|
-
describe('
|
|
104
|
-
it('should validate a valid
|
|
105
|
-
const
|
|
44
|
+
describe('isNostrEvent', () => {
|
|
45
|
+
it('should validate a valid NostrEvent', () => {
|
|
46
|
+
const event: SignedNostrEvent = {
|
|
106
47
|
kind: NostrEventKind.TEXT_NOTE,
|
|
107
|
-
created_at: Math.floor(Date.now() / 1000),
|
|
108
48
|
content: 'Hello, Nostr!',
|
|
109
|
-
|
|
49
|
+
created_at: Math.floor(Date.now() / 1000),
|
|
50
|
+
tags: [],
|
|
110
51
|
pubkey: '0123456789abcdef',
|
|
111
|
-
id: '
|
|
112
|
-
sig: '
|
|
52
|
+
id: '0123456789abcdef',
|
|
53
|
+
sig: '0123456789abcdef'
|
|
113
54
|
};
|
|
114
|
-
|
|
115
|
-
expect(isSignedNostrEvent(validEvent)).toBe(true);
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
it('should reject invalid SignedNostrEvent objects', () => {
|
|
119
|
-
const invalidEvents = [
|
|
120
|
-
null,
|
|
121
|
-
undefined,
|
|
122
|
-
{},
|
|
123
|
-
{ ...validNostrEvent }, // Missing id and sig
|
|
124
|
-
{ ...validNostrEvent, id: 42 }, // Wrong id type
|
|
125
|
-
{ ...validNostrEvent, id: 'valid', sig: 42 }, // Wrong sig type
|
|
126
|
-
{ ...validNostrEvent, id: 'valid', sig: 'valid', pubkey: undefined } // Missing required pubkey
|
|
127
|
-
];
|
|
128
55
|
|
|
129
|
-
|
|
130
|
-
expect(isSignedNostrEvent(event)).toBe(false);
|
|
131
|
-
});
|
|
132
|
-
});
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
describe('NostrFilter Type', () => {
|
|
136
|
-
it('should validate filter properties', () => {
|
|
137
|
-
const validFilter: NostrFilter = {
|
|
138
|
-
ids: ['abc123'],
|
|
139
|
-
authors: ['def456'],
|
|
140
|
-
kinds: [1, 2, 3],
|
|
141
|
-
'#e': ['ghi789'],
|
|
142
|
-
'#p': ['jkl012'],
|
|
143
|
-
since: 123456789,
|
|
144
|
-
until: 987654321,
|
|
145
|
-
limit: 100
|
|
146
|
-
};
|
|
147
|
-
expect(validFilter).toBeDefined();
|
|
56
|
+
expect(isNostrEvent(event)).toBe(true);
|
|
148
57
|
});
|
|
149
58
|
});
|
|
150
59
|
|
|
@@ -153,130 +62,15 @@ describe('Type Guards', () => {
|
|
|
153
62
|
const validFilter: NostrFilter = {
|
|
154
63
|
ids: ['1234', '5678'],
|
|
155
64
|
authors: ['abcd', 'efgh'],
|
|
156
|
-
kinds: [
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
65
|
+
kinds: [NostrEventKind.TEXT_NOTE, NostrEventKind.AUTH_RESPONSE],
|
|
66
|
+
since: 123,
|
|
67
|
+
until: 456,
|
|
68
|
+
limit: 10,
|
|
69
|
+
'#e': ['1234'],
|
|
70
|
+
'#p': ['5678']
|
|
162
71
|
};
|
|
163
|
-
|
|
164
|
-
expect(isNostrFilter(validFilter)).toBe(true);
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
it('should validate a NostrFilter with partial fields', () => {
|
|
168
|
-
const partialFilters: Partial<NostrFilter>[] = [
|
|
169
|
-
{ ids: ['1234'] },
|
|
170
|
-
{ authors: ['abcd'] },
|
|
171
|
-
{ kinds: [1] },
|
|
172
|
-
{ '#e': ['event1'] },
|
|
173
|
-
{ '#p': ['pubkey1'] },
|
|
174
|
-
{ since: 123456789 },
|
|
175
|
-
{ until: 987654321 },
|
|
176
|
-
{ limit: 100 }
|
|
177
|
-
];
|
|
178
|
-
|
|
179
|
-
partialFilters.forEach(filter => {
|
|
180
|
-
expect(isNostrFilter(filter)).toBe(true);
|
|
181
|
-
});
|
|
182
|
-
});
|
|
183
72
|
|
|
184
|
-
|
|
185
|
-
const invalidFilters = [
|
|
186
|
-
null,
|
|
187
|
-
undefined,
|
|
188
|
-
{ ids: [42] }, // Wrong type in array
|
|
189
|
-
{ authors: ['valid', 42] }, // Mixed types in array
|
|
190
|
-
{ kinds: ['1'] }, // Wrong array type
|
|
191
|
-
{ '#e': [42] }, // Wrong type in array
|
|
192
|
-
{ '#p': [true] }, // Wrong type in array
|
|
193
|
-
{ since: '123' }, // Wrong type
|
|
194
|
-
{ until: false }, // Wrong type
|
|
195
|
-
{ limit: '100' } // Wrong type
|
|
196
|
-
];
|
|
197
|
-
|
|
198
|
-
invalidFilters.forEach(filter => {
|
|
199
|
-
expect(isNostrFilter(filter)).toBe(false);
|
|
200
|
-
});
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
it('should handle edge cases for NostrFilter', () => {
|
|
204
|
-
const edgeCases: NostrFilter[] = [
|
|
205
|
-
// Multiple tag types
|
|
206
|
-
{
|
|
207
|
-
'#e': ['1234'],
|
|
208
|
-
'#p': ['5678'],
|
|
209
|
-
'#t': ['test'], // Custom tag
|
|
210
|
-
},
|
|
211
|
-
// Time range edge cases
|
|
212
|
-
{
|
|
213
|
-
since: 0,
|
|
214
|
-
until: Number.MAX_SAFE_INTEGER,
|
|
215
|
-
},
|
|
216
|
-
// Large limit
|
|
217
|
-
{
|
|
218
|
-
limit: Number.MAX_SAFE_INTEGER,
|
|
219
|
-
},
|
|
220
|
-
// Multiple array fields
|
|
221
|
-
{
|
|
222
|
-
ids: ['1', '2', '3'],
|
|
223
|
-
authors: ['a', 'b', 'c'],
|
|
224
|
-
kinds: [1, 2, 3, 10000],
|
|
225
|
-
}
|
|
226
|
-
];
|
|
227
|
-
|
|
228
|
-
edgeCases.forEach(filter => {
|
|
229
|
-
expect(isNostrFilter(filter)).toBe(true);
|
|
230
|
-
});
|
|
231
|
-
});
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
describe('isNostrSubscription', () => {
|
|
235
|
-
it('should validate a valid NostrSubscription', () => {
|
|
236
|
-
const validSubscription: NostrSubscription = {
|
|
237
|
-
id: 'sub_123',
|
|
238
|
-
filters: [
|
|
239
|
-
{ kinds: [1], limit: 10 },
|
|
240
|
-
{ authors: ['abcd'], since: 123456789 }
|
|
241
|
-
]
|
|
242
|
-
};
|
|
243
|
-
|
|
244
|
-
expect(isNostrSubscription(validSubscription)).toBe(true);
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
it('should validate a NostrSubscription with empty filters', () => {
|
|
248
|
-
const validSubscription: NostrSubscription = {
|
|
249
|
-
id: 'sub_123',
|
|
250
|
-
filters: []
|
|
251
|
-
};
|
|
252
|
-
|
|
253
|
-
expect(isNostrSubscription(validSubscription)).toBe(true);
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
it('should reject invalid NostrSubscription objects', () => {
|
|
257
|
-
const invalidSubscriptions = [
|
|
258
|
-
null,
|
|
259
|
-
undefined,
|
|
260
|
-
{},
|
|
261
|
-
{ id: 123, filters: [] }, // Wrong id type
|
|
262
|
-
{ id: 'valid' }, // Missing filters
|
|
263
|
-
{ id: 'valid', filters: 'not an array' }, // Wrong filters type
|
|
264
|
-
{ id: 'valid', filters: [null] }, // Invalid filter
|
|
265
|
-
{ id: 'valid', filters: [{ invalid: true }] } // Invalid filter object
|
|
266
|
-
];
|
|
267
|
-
|
|
268
|
-
invalidSubscriptions.forEach(sub => {
|
|
269
|
-
expect(isNostrSubscription(sub)).toBe(false);
|
|
270
|
-
});
|
|
73
|
+
expect(isNostrFilter(validFilter)).toBe(true);
|
|
271
74
|
});
|
|
272
75
|
});
|
|
273
76
|
});
|
|
274
|
-
|
|
275
|
-
// Helper for tests
|
|
276
|
-
const validNostrEvent: NostrEvent = {
|
|
277
|
-
kind: NostrEventKind.TEXT_NOTE,
|
|
278
|
-
created_at: Math.floor(Date.now() / 1000),
|
|
279
|
-
content: 'Hello, Nostr!',
|
|
280
|
-
tags: [['p', '1234'], ['t', 'test']],
|
|
281
|
-
pubkey: '0123456789abcdef'
|
|
282
|
-
};
|
package/src/event/signing.ts
CHANGED
|
@@ -51,3 +51,32 @@ export function verifySignature(event: SignedNostrEvent): boolean {
|
|
|
51
51
|
return false;
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Validates a Nostr event
|
|
57
|
+
* @param event - Event to validate
|
|
58
|
+
* @returns True if event is valid
|
|
59
|
+
*/
|
|
60
|
+
export function validateEvent(event: SignedNostrEvent): boolean {
|
|
61
|
+
try {
|
|
62
|
+
// Check required fields
|
|
63
|
+
if (!event.id || !event.pubkey || !event.sig) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Verify signature
|
|
68
|
+
return verifySignature(event);
|
|
69
|
+
} catch (error) {
|
|
70
|
+
logger.error('Error validating event:', error);
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Calculates the event ID for a Nostr event
|
|
77
|
+
* @param event - Event to calculate ID for
|
|
78
|
+
* @returns Event ID
|
|
79
|
+
*/
|
|
80
|
+
export function calculateEventId(event: NostrEvent): Promise<string> {
|
|
81
|
+
return getEventHash(event);
|
|
82
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,66 +1,58 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module nostr-crypto-utils
|
|
3
|
-
* @description
|
|
3
|
+
* @description Core cryptographic utilities for Nostr protocol
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
//
|
|
7
|
-
export
|
|
6
|
+
// Core types
|
|
7
|
+
export type {
|
|
8
|
+
NostrEvent,
|
|
9
|
+
UnsignedNostrEvent,
|
|
10
|
+
SignedNostrEvent,
|
|
11
|
+
NostrFilter,
|
|
12
|
+
NostrSubscription,
|
|
13
|
+
PublicKey,
|
|
14
|
+
KeyPair,
|
|
15
|
+
NostrMessageTuple,
|
|
16
|
+
} from './types';
|
|
8
17
|
|
|
9
|
-
//
|
|
18
|
+
// Event kinds and message types
|
|
19
|
+
export { NostrEventKind, NostrMessageType } from './types';
|
|
20
|
+
|
|
21
|
+
// Core crypto functions
|
|
10
22
|
export {
|
|
11
|
-
customCrypto,
|
|
12
|
-
signSchnorr,
|
|
13
|
-
verifySchnorrSignature,
|
|
14
23
|
generateKeyPair,
|
|
15
24
|
getPublicKey,
|
|
16
25
|
validateKeyPair,
|
|
17
|
-
getCompressedPublicKey,
|
|
18
|
-
getSchnorrPublicKey,
|
|
19
26
|
createEvent,
|
|
20
27
|
signEvent,
|
|
21
28
|
verifySignature,
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
} from './crypto
|
|
29
|
+
encrypt,
|
|
30
|
+
decrypt,
|
|
31
|
+
} from './crypto';
|
|
25
32
|
|
|
26
|
-
//
|
|
33
|
+
// Event functions
|
|
27
34
|
export {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
formatAuthForRelay,
|
|
32
|
-
parseMessage as parseEventFromRelay,
|
|
33
|
-
createMetadataEvent,
|
|
34
|
-
createTextNoteEvent,
|
|
35
|
-
createDirectMessageEvent,
|
|
36
|
-
createChannelMessageEvent,
|
|
37
|
-
extractReferencedEvents,
|
|
38
|
-
extractMentionedPubkeys,
|
|
39
|
-
createKindFilter,
|
|
40
|
-
createAuthorFilter,
|
|
41
|
-
createReplyFilter,
|
|
42
|
-
createFilter as validateEvent
|
|
43
|
-
} from './protocol/index';
|
|
35
|
+
validateEvent,
|
|
36
|
+
calculateEventId,
|
|
37
|
+
} from './event';
|
|
44
38
|
|
|
45
|
-
//
|
|
39
|
+
// NIP-04 encryption
|
|
46
40
|
export {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
41
|
+
computeSharedSecret,
|
|
42
|
+
encryptMessage,
|
|
43
|
+
decryptMessage,
|
|
44
|
+
} from './nips/nip-04';
|
|
50
45
|
|
|
51
|
-
// Re-export
|
|
52
|
-
export * from './
|
|
46
|
+
// Re-export NIPs
|
|
47
|
+
export * as nip01 from './nips/nip-01';
|
|
48
|
+
export * as nip04 from './nips/nip-04';
|
|
49
|
+
export * as nip19 from './nips/nip-19';
|
|
50
|
+
export * as nip26 from './nips/nip-26';
|
|
53
51
|
|
|
54
|
-
//
|
|
52
|
+
// Utils
|
|
55
53
|
export {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
naddrEncode,
|
|
62
|
-
nrelayEncode,
|
|
63
|
-
decode
|
|
64
|
-
} from './nips/nip-19';
|
|
65
|
-
|
|
66
|
-
export * from './nips/index';
|
|
54
|
+
hexToBytes,
|
|
55
|
+
bytesToHex,
|
|
56
|
+
utf8ToBytes,
|
|
57
|
+
bytesToUtf8,
|
|
58
|
+
} from './utils/encoding';
|
package/src/nips/nip-04.ts
CHANGED
package/src/protocol/index.ts
CHANGED
|
@@ -3,8 +3,17 @@
|
|
|
3
3
|
* @description Core Nostr protocol implementation
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
|
|
6
|
+
import {
|
|
7
|
+
NostrEvent,
|
|
8
|
+
NostrFilter,
|
|
9
|
+
NostrEventKind,
|
|
10
|
+
SignedNostrEvent,
|
|
11
|
+
NostrMessageType,
|
|
12
|
+
UnsignedEvent,
|
|
13
|
+
PublicKey,
|
|
14
|
+
NostrResponse,
|
|
15
|
+
NostrSubscription
|
|
16
|
+
} from '../types/base';
|
|
8
17
|
|
|
9
18
|
/**
|
|
10
19
|
* Formats an event for relay transmission according to NIP-01
|
|
@@ -109,9 +118,9 @@ export function parseMessage(message: string): NostrResponse {
|
|
|
109
118
|
* @category Event Creation
|
|
110
119
|
* @param {Record<string, string>} metadata - User metadata (name, about, picture, etc.)
|
|
111
120
|
* @param {string | PublicKey} pubkey - Public key of the user
|
|
112
|
-
* @returns {
|
|
121
|
+
* @returns {UnsignedEvent} Created metadata event
|
|
113
122
|
*/
|
|
114
|
-
export function createMetadataEvent(metadata: Record<string, string>, pubkey: string | PublicKey):
|
|
123
|
+
export function createMetadataEvent(metadata: Record<string, string>, pubkey: string | PublicKey): UnsignedEvent {
|
|
115
124
|
const pubkeyValue = typeof pubkey === 'string' ? pubkey : pubkey.hex;
|
|
116
125
|
return {
|
|
117
126
|
kind: NostrEventKind.SET_METADATA,
|
|
@@ -129,24 +138,24 @@ export function createMetadataEvent(metadata: Record<string, string>, pubkey: st
|
|
|
129
138
|
* @param {string | PublicKey} pubkey - Public key of the author
|
|
130
139
|
* @param {string} [replyTo] - Optional ID of event being replied to
|
|
131
140
|
* @param {string[]} [mentions] - Optional array of pubkeys to mention
|
|
132
|
-
* @returns {
|
|
141
|
+
* @returns {UnsignedEvent} Created text note event
|
|
133
142
|
*/
|
|
134
143
|
export function createTextNoteEvent(
|
|
135
144
|
content: string,
|
|
136
145
|
pubkey: string | PublicKey,
|
|
137
146
|
replyTo?: string,
|
|
138
147
|
mentions?: string[]
|
|
139
|
-
):
|
|
148
|
+
): UnsignedEvent {
|
|
140
149
|
const pubkeyValue = typeof pubkey === 'string' ? pubkey : pubkey.hex;
|
|
141
150
|
const tags: string[][] = [];
|
|
142
151
|
|
|
143
152
|
if (replyTo) {
|
|
144
|
-
tags.push([
|
|
153
|
+
tags.push(['e', replyTo]);
|
|
145
154
|
}
|
|
146
155
|
|
|
147
156
|
if (mentions) {
|
|
148
157
|
mentions.forEach(pubkey => {
|
|
149
|
-
tags.push([
|
|
158
|
+
tags.push(['p', pubkey]);
|
|
150
159
|
});
|
|
151
160
|
}
|
|
152
161
|
|
|
@@ -165,13 +174,13 @@ export function createTextNoteEvent(
|
|
|
165
174
|
* @param {string | PublicKey} recipientPubkey - Public key of message recipient
|
|
166
175
|
* @param {string} content - Message content (will be encrypted)
|
|
167
176
|
* @param {string | PublicKey} senderPubkey - Public key of the sender
|
|
168
|
-
* @returns {
|
|
177
|
+
* @returns {UnsignedEvent} Created direct message event
|
|
169
178
|
*/
|
|
170
179
|
export function createDirectMessageEvent(
|
|
171
180
|
recipientPubkey: string | PublicKey,
|
|
172
181
|
content: string,
|
|
173
182
|
senderPubkey: string | PublicKey
|
|
174
|
-
):
|
|
183
|
+
): UnsignedEvent {
|
|
175
184
|
const recipientKey = typeof recipientPubkey === 'string' ? recipientPubkey : recipientPubkey.hex;
|
|
176
185
|
const senderKey = typeof senderPubkey === 'string' ? senderPubkey : senderPubkey.hex;
|
|
177
186
|
|
|
@@ -191,14 +200,14 @@ export function createDirectMessageEvent(
|
|
|
191
200
|
* @param {string} content - Message content
|
|
192
201
|
* @param {string | PublicKey} authorPubkey - Public key of the message author
|
|
193
202
|
* @param {string} [replyTo] - Optional ID of message being replied to
|
|
194
|
-
* @returns {
|
|
203
|
+
* @returns {UnsignedEvent} Created channel message event
|
|
195
204
|
*/
|
|
196
205
|
export function createChannelMessageEvent(
|
|
197
206
|
channelId: string,
|
|
198
207
|
content: string,
|
|
199
208
|
authorPubkey: string | PublicKey,
|
|
200
209
|
replyTo?: string
|
|
201
|
-
):
|
|
210
|
+
): UnsignedEvent {
|
|
202
211
|
const pubkeyValue = typeof authorPubkey === 'string' ? authorPubkey : authorPubkey.hex;
|
|
203
212
|
const tags = [['e', channelId, '', 'root']];
|
|
204
213
|
if (replyTo) {
|
|
@@ -221,7 +230,7 @@ export function createChannelMessageEvent(
|
|
|
221
230
|
*/
|
|
222
231
|
export function extractReferencedEvents(event: NostrEvent): string[] {
|
|
223
232
|
return event.tags
|
|
224
|
-
.filter((tag: string[]) => tag[0] ===
|
|
233
|
+
.filter((tag: string[]) => tag[0] === 'e')
|
|
225
234
|
.map((tag: string[]) => tag[1]);
|
|
226
235
|
}
|
|
227
236
|
|
|
@@ -233,7 +242,7 @@ export function extractReferencedEvents(event: NostrEvent): string[] {
|
|
|
233
242
|
*/
|
|
234
243
|
export function extractMentionedPubkeys(event: NostrEvent): string[] {
|
|
235
244
|
return event.tags
|
|
236
|
-
.filter((tag: string[]) => tag[0] ===
|
|
245
|
+
.filter((tag: string[]) => tag[0] === 'p')
|
|
237
246
|
.map((tag: string[]) => tag[1]);
|
|
238
247
|
}
|
|
239
248
|
|