nostr-mcp-server 2.0.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.
Files changed (36) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +498 -0
  3. package/build/__tests__/basic.test.js +87 -0
  4. package/build/__tests__/error-handling.test.js +145 -0
  5. package/build/__tests__/format-conversion.test.js +137 -0
  6. package/build/__tests__/integration.test.js +163 -0
  7. package/build/__tests__/mocks.js +109 -0
  8. package/build/__tests__/nip19-conversion.test.js +268 -0
  9. package/build/__tests__/nips-search.test.js +109 -0
  10. package/build/__tests__/note-creation.test.js +148 -0
  11. package/build/__tests__/note-tools-functions.test.js +173 -0
  12. package/build/__tests__/note-tools-unit.test.js +97 -0
  13. package/build/__tests__/profile-notes-simple.test.js +78 -0
  14. package/build/__tests__/profile-postnote.test.js +120 -0
  15. package/build/__tests__/profile-tools.test.js +90 -0
  16. package/build/__tests__/relay-specification.test.js +136 -0
  17. package/build/__tests__/search-nips-simple.test.js +96 -0
  18. package/build/__tests__/websocket-integration.test.js +257 -0
  19. package/build/__tests__/zap-tools-simple.test.js +72 -0
  20. package/build/__tests__/zap-tools-tests.test.js +197 -0
  21. package/build/index.js +1285 -0
  22. package/build/nips/nips-tools.js +567 -0
  23. package/build/nips-tools.js +421 -0
  24. package/build/note/note-tools.js +296 -0
  25. package/build/note-tools.js +53 -0
  26. package/build/profile/profile-tools.js +260 -0
  27. package/build/utils/constants.js +27 -0
  28. package/build/utils/conversion.js +332 -0
  29. package/build/utils/ephemeral-relay.js +438 -0
  30. package/build/utils/formatting.js +34 -0
  31. package/build/utils/index.js +6 -0
  32. package/build/utils/nip19-tools.js +117 -0
  33. package/build/utils/pool.js +55 -0
  34. package/build/zap/zap-tools.js +980 -0
  35. package/build/zap-tools.js +989 -0
  36. package/package.json +59 -0
@@ -0,0 +1,197 @@
1
+ import { generateKeypair } from 'snstr';
2
+ import { validateZapReceipt, formatZapReceipt, parseZapRequestData, determineZapDirection } from '../zap/zap-tools.js';
3
+ describe('Zap Processing Functions', () => {
4
+ let testKeys;
5
+ let zapperKeys;
6
+ beforeAll(async () => {
7
+ testKeys = await generateKeypair();
8
+ zapperKeys = await generateKeypair();
9
+ });
10
+ describe('validateZapReceipt', () => {
11
+ it('should validate a proper zap receipt', () => {
12
+ const zapReceipt = {
13
+ id: 'test-id',
14
+ pubkey: zapperKeys.publicKey,
15
+ created_at: Math.floor(Date.now() / 1000),
16
+ kind: 9735,
17
+ tags: [
18
+ ['p', testKeys.publicKey],
19
+ ['bolt11', 'lnbc1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpl2pkx2ctnv5sxxmmwwd5kgetjypeh2ursdae8g6twvus8g6rfwvs8qun0dfjkxaq8rkx3yf5tcsyz3d73gafnh3cax9rn449d9p5uxz9ezhhypd0elx87sjle52x86fux2ypatgddc6k63n7erqz25le42c4u4ecky03ylcqca784w'],
20
+ ['description', JSON.stringify({
21
+ kind: 9734,
22
+ content: 'Test zap',
23
+ tags: [['p', testKeys.publicKey]],
24
+ pubkey: 'sender-pubkey'
25
+ })]
26
+ ],
27
+ content: '',
28
+ sig: 'test-sig'
29
+ };
30
+ const result = validateZapReceipt(zapReceipt);
31
+ expect(result.valid).toBe(true);
32
+ expect(result.reason).toBeUndefined();
33
+ });
34
+ it('should reject invalid kind', () => {
35
+ const invalidReceipt = {
36
+ id: 'test-id',
37
+ pubkey: zapperKeys.publicKey,
38
+ created_at: Math.floor(Date.now() / 1000),
39
+ kind: 1, // Wrong kind
40
+ tags: [],
41
+ content: '',
42
+ sig: 'test-sig'
43
+ };
44
+ const result = validateZapReceipt(invalidReceipt);
45
+ expect(result.valid).toBe(false);
46
+ expect(result.reason).toContain('Not a zap receipt');
47
+ });
48
+ it('should reject missing bolt11 tag', () => {
49
+ const invalidReceipt = {
50
+ id: 'test-id',
51
+ pubkey: zapperKeys.publicKey,
52
+ created_at: Math.floor(Date.now() / 1000),
53
+ kind: 9735,
54
+ tags: [
55
+ ['p', testKeys.publicKey],
56
+ ['description', '{}'] // Missing bolt11
57
+ ],
58
+ content: '',
59
+ sig: 'test-sig'
60
+ };
61
+ const result = validateZapReceipt(invalidReceipt);
62
+ expect(result.valid).toBe(false);
63
+ expect(result.reason).toContain('Missing bolt11');
64
+ });
65
+ });
66
+ describe('parseZapRequestData', () => {
67
+ it('should parse zap request from description tag', () => {
68
+ const zapRequest = {
69
+ kind: 9734,
70
+ content: 'Great post!',
71
+ tags: [
72
+ ['p', testKeys.publicKey],
73
+ ['amount', '100000']
74
+ ],
75
+ pubkey: 'sender-pubkey',
76
+ created_at: Math.floor(Date.now() / 1000)
77
+ };
78
+ const zapReceipt = {
79
+ id: 'test-id',
80
+ pubkey: zapperKeys.publicKey,
81
+ created_at: Math.floor(Date.now() / 1000),
82
+ kind: 9735,
83
+ tags: [
84
+ ['p', testKeys.publicKey],
85
+ ['bolt11', 'lnbc1pvjluez'],
86
+ ['description', JSON.stringify(zapRequest)]
87
+ ],
88
+ content: '',
89
+ sig: 'test-sig'
90
+ };
91
+ const result = parseZapRequestData(zapReceipt);
92
+ expect(result).toBeDefined();
93
+ expect(result?.content).toBe('Great post!');
94
+ expect(result?.pubkey).toBe('sender-pubkey');
95
+ expect(result?.amount).toBe(100000);
96
+ });
97
+ it('should handle missing description tag', () => {
98
+ const zapReceipt = {
99
+ id: 'test-id',
100
+ pubkey: zapperKeys.publicKey,
101
+ created_at: Math.floor(Date.now() / 1000),
102
+ kind: 9735,
103
+ tags: [
104
+ ['p', testKeys.publicKey],
105
+ ['bolt11', 'lnbc10u1p...']
106
+ ],
107
+ content: '',
108
+ sig: 'test-sig'
109
+ };
110
+ const result = parseZapRequestData(zapReceipt);
111
+ expect(result).toBeUndefined();
112
+ });
113
+ });
114
+ describe('determineZapDirection', () => {
115
+ it('should identify received zaps', () => {
116
+ const zapReceipt = {
117
+ id: 'test-id',
118
+ pubkey: zapperKeys.publicKey,
119
+ created_at: Math.floor(Date.now() / 1000),
120
+ kind: 9735,
121
+ tags: [
122
+ ['p', testKeys.publicKey], // Recipient
123
+ ['P', 'sender-pubkey'] // Sender
124
+ ],
125
+ content: '',
126
+ sig: 'test-sig'
127
+ };
128
+ const direction = determineZapDirection(zapReceipt, testKeys.publicKey);
129
+ expect(direction).toBe('received');
130
+ });
131
+ it('should identify sent zaps', () => {
132
+ const zapReceipt = {
133
+ id: 'test-id',
134
+ pubkey: zapperKeys.publicKey,
135
+ created_at: Math.floor(Date.now() / 1000),
136
+ kind: 9735,
137
+ tags: [
138
+ ['p', 'recipient-pubkey'], // Recipient
139
+ ['P', testKeys.publicKey] // Sender
140
+ ],
141
+ content: '',
142
+ sig: 'test-sig'
143
+ };
144
+ const direction = determineZapDirection(zapReceipt, testKeys.publicKey);
145
+ expect(direction).toBe('sent');
146
+ });
147
+ it('should identify self zaps', () => {
148
+ const zapReceipt = {
149
+ id: 'test-id',
150
+ pubkey: zapperKeys.publicKey,
151
+ created_at: Math.floor(Date.now() / 1000),
152
+ kind: 9735,
153
+ tags: [
154
+ ['p', testKeys.publicKey], // Recipient
155
+ ['P', testKeys.publicKey] // Sender (same)
156
+ ],
157
+ content: '',
158
+ sig: 'test-sig'
159
+ };
160
+ const direction = determineZapDirection(zapReceipt, testKeys.publicKey);
161
+ expect(direction).toBe('self');
162
+ });
163
+ });
164
+ describe('formatZapReceipt', () => {
165
+ it('should format a zap receipt', () => {
166
+ const zapRequest = {
167
+ kind: 9734,
168
+ content: 'Great content!',
169
+ tags: [
170
+ ['p', testKeys.publicKey],
171
+ ['amount', '50000']
172
+ ],
173
+ pubkey: 'sender-pubkey',
174
+ created_at: Math.floor(Date.now() / 1000)
175
+ };
176
+ const zapReceipt = {
177
+ id: 'abcdef123456',
178
+ pubkey: zapperKeys.publicKey,
179
+ created_at: Math.floor(Date.now() / 1000) - 3600,
180
+ kind: 9735,
181
+ tags: [
182
+ ['p', testKeys.publicKey],
183
+ ['P', 'sender-pubkey'],
184
+ ['bolt11', 'lnbc1pvjluez'],
185
+ ['description', JSON.stringify(zapRequest)]
186
+ ],
187
+ content: '',
188
+ sig: 'test-sig'
189
+ };
190
+ const formatted = formatZapReceipt(zapReceipt, testKeys.publicKey);
191
+ // The format has changed, so we check for key elements
192
+ expect(formatted).toContain('RECEIVED');
193
+ expect(formatted).toContain('Great content!');
194
+ expect(formatted).toContain('From: sender-');
195
+ });
196
+ });
197
+ });