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.
- package/LICENSE +21 -0
- package/README.md +498 -0
- package/build/__tests__/basic.test.js +87 -0
- package/build/__tests__/error-handling.test.js +145 -0
- package/build/__tests__/format-conversion.test.js +137 -0
- package/build/__tests__/integration.test.js +163 -0
- package/build/__tests__/mocks.js +109 -0
- package/build/__tests__/nip19-conversion.test.js +268 -0
- package/build/__tests__/nips-search.test.js +109 -0
- package/build/__tests__/note-creation.test.js +148 -0
- package/build/__tests__/note-tools-functions.test.js +173 -0
- package/build/__tests__/note-tools-unit.test.js +97 -0
- package/build/__tests__/profile-notes-simple.test.js +78 -0
- package/build/__tests__/profile-postnote.test.js +120 -0
- package/build/__tests__/profile-tools.test.js +90 -0
- package/build/__tests__/relay-specification.test.js +136 -0
- package/build/__tests__/search-nips-simple.test.js +96 -0
- package/build/__tests__/websocket-integration.test.js +257 -0
- package/build/__tests__/zap-tools-simple.test.js +72 -0
- package/build/__tests__/zap-tools-tests.test.js +197 -0
- package/build/index.js +1285 -0
- package/build/nips/nips-tools.js +567 -0
- package/build/nips-tools.js +421 -0
- package/build/note/note-tools.js +296 -0
- package/build/note-tools.js +53 -0
- package/build/profile/profile-tools.js +260 -0
- package/build/utils/constants.js +27 -0
- package/build/utils/conversion.js +332 -0
- package/build/utils/ephemeral-relay.js +438 -0
- package/build/utils/formatting.js +34 -0
- package/build/utils/index.js +6 -0
- package/build/utils/nip19-tools.js +117 -0
- package/build/utils/pool.js +55 -0
- package/build/zap/zap-tools.js +980 -0
- package/build/zap-tools.js +989 -0
- 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
|
+
});
|