spasm.js 0.1.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.md +21 -0
- package/lib.commonjs/README.md +20 -0
- package/lib.commonjs/identifyEvent.js +812 -0
- package/lib.commonjs/identifyEvent.js.map +1 -0
- package/lib.commonjs/index.js +7 -0
- package/lib.commonjs/index.js.map +1 -0
- package/lib.commonjs/interfaces.js +16 -0
- package/lib.commonjs/interfaces.js.map +1 -0
- package/lib.commonjs/package.json +4 -0
- package/lib.commonjs/utils.js +36 -0
- package/lib.commonjs/utils.js.map +1 -0
- package/lib.esm/README.md +20 -0
- package/lib.esm/identifyEvent.js +778 -0
- package/lib.esm/identifyEvent.js.map +1 -0
- package/lib.esm/index.js +3 -0
- package/lib.esm/index.js.map +1 -0
- package/lib.esm/interfaces.js +12 -0
- package/lib.esm/interfaces.js.map +1 -0
- package/lib.esm/package.json +4 -0
- package/lib.esm/utils.js +31 -0
- package/lib.esm/utils.js.map +1 -0
- package/package.json +49 -0
- package/src.ts/identifyEvent.ts +1103 -0
- package/src.ts/index.ts +3 -0
- package/src.ts/interfaces.ts +283 -0
- package/src.ts/utils.ts +33 -0
|
@@ -0,0 +1,812 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.convertToSpasm = exports.standartizePostWithNostrSpasmEventSignedOpened = exports.standartizePostWithDmpEventSignedClosed = exports.standartizeNostrSpasmEventSignedOpened = exports.standartizeDmpEventSignedClosed = exports.standartizePostOrEvent = exports.identifyEventInsidePost = exports.isPostWithNostrEvent = exports.isPostWithNostrSpasmEvent = exports.isPostWithNostrEventSignedOpened = exports.isPostWithNostrSpasmEventSignedOpened = exports.isPostWithDmpEventSignedClosed = exports.isPostWithDmpEventSignedOpened = exports.isPostWithDmpEvent = exports.isDmpEventSignedOpened = exports.isDmpEventSignedClosed = exports.isDmpEvent = exports.isNostrSpasmEventSignedOpened = exports.isNostrSpasmEvent = exports.isNostrEventSignedOpened = exports.isNostrEvent = exports.hasExtraSpasmFields = exports.identifyPrivateKey = exports.extractSealedEvent = exports.identifyLicenseInsideTags = exports.identifyLicense = exports.hasSignature = exports.identifyEvent = exports.isWeb3Post = exports.isWeb2Post = exports.identifyPostOrEvent = void 0;
|
|
4
|
+
const utils_1 = require("./utils");
|
|
5
|
+
// web2 post example
|
|
6
|
+
// webType: "web2",
|
|
7
|
+
// eventIsSealed: false,
|
|
8
|
+
// eventIsSealedUnderKeyName: false,
|
|
9
|
+
// eventInfo: false
|
|
10
|
+
// web3 post example
|
|
11
|
+
// webType: "web3",
|
|
12
|
+
// eventIsSealed: true,
|
|
13
|
+
// eventIsSealedUnderKeyName: "signed_message",
|
|
14
|
+
// eventInfo: {
|
|
15
|
+
// type: "DmpEventSignedClosed",
|
|
16
|
+
// hasSignature: true
|
|
17
|
+
// baseProtocol: "dmp",
|
|
18
|
+
// privateKey: "ethereum",
|
|
19
|
+
// isSpasmCompatible: true,
|
|
20
|
+
// hasExtraSpasmFields: false,
|
|
21
|
+
// }
|
|
22
|
+
// web3 event example
|
|
23
|
+
// webType: "web3",
|
|
24
|
+
// eventIsSealed: false,
|
|
25
|
+
// eventIsSealedUnderKeyName: false,
|
|
26
|
+
// eventInfo: {
|
|
27
|
+
// type: "NostrSpasmEventSignedOpened",
|
|
28
|
+
// hasSignature: true
|
|
29
|
+
// baseProtocol: "nostr",
|
|
30
|
+
// privateKey: "nostr",
|
|
31
|
+
// isSpasmCompatible: true,
|
|
32
|
+
// hasExtraSpasmFields: true,
|
|
33
|
+
// }
|
|
34
|
+
/**
|
|
35
|
+
There are usually 3 types of objects passed to this function:
|
|
36
|
+
- web3 post - an object is a post with a web3 event sealed inside
|
|
37
|
+
- web3 event - an object itself is a web3 event
|
|
38
|
+
- web2 post - an object is a post without a web3 event (e.g. RSS)
|
|
39
|
+
*/
|
|
40
|
+
const identifyPostOrEvent = (unknownPostOrEvent) => {
|
|
41
|
+
const info = {
|
|
42
|
+
webType: false,
|
|
43
|
+
eventIsSealed: false,
|
|
44
|
+
eventIsSealedUnderKeyName: false,
|
|
45
|
+
eventInfo: {
|
|
46
|
+
type: false,
|
|
47
|
+
hasSignature: false,
|
|
48
|
+
baseProtocol: false,
|
|
49
|
+
privateKey: false,
|
|
50
|
+
isSpasmCompatible: false,
|
|
51
|
+
hasExtraSpasmFields: false,
|
|
52
|
+
license: false
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
if (!(0, utils_1.isObjectWithValues)(unknownPostOrEvent))
|
|
56
|
+
return info;
|
|
57
|
+
let unknownEventOrWeb2Post;
|
|
58
|
+
// Option 1.
|
|
59
|
+
// If an object is a post with a sealed event (signed string),
|
|
60
|
+
// we need to extract the event by parsing the signed string.
|
|
61
|
+
// We then check if that extracted object is a valid web3 event.
|
|
62
|
+
if ((0, exports.isWeb3Post)(unknownPostOrEvent)) {
|
|
63
|
+
info.webType = "web3";
|
|
64
|
+
info.eventIsSealed = true;
|
|
65
|
+
if ('signed_message' in unknownPostOrEvent &&
|
|
66
|
+
typeof (unknownPostOrEvent.signed_message) === "string") {
|
|
67
|
+
const signedObject = JSON.parse(unknownPostOrEvent.signed_message);
|
|
68
|
+
info.eventIsSealedUnderKeyName = 'signed_message';
|
|
69
|
+
unknownEventOrWeb2Post = signedObject;
|
|
70
|
+
// Edge cases.
|
|
71
|
+
// Signed DMP event sealed in the Post under the key
|
|
72
|
+
// 'signed_message' doesn't have signature inside the signed
|
|
73
|
+
// string, so we cannot just parse the string to extract the
|
|
74
|
+
// object and then pass it into an identify function.
|
|
75
|
+
// Instead, we have to attach a signer and signature to the
|
|
76
|
+
// signed string, which is a type of DmpEventSignedClosed.
|
|
77
|
+
if ((0, exports.isDmpEvent)(unknownEventOrWeb2Post) &&
|
|
78
|
+
'signer' in unknownPostOrEvent &&
|
|
79
|
+
typeof (unknownPostOrEvent.signer) === "string" &&
|
|
80
|
+
'signature' in unknownPostOrEvent &&
|
|
81
|
+
typeof (unknownPostOrEvent.signature) === "string") {
|
|
82
|
+
// Recreating DmpEventSignedClosed
|
|
83
|
+
unknownEventOrWeb2Post = {
|
|
84
|
+
signer: unknownPostOrEvent.signer,
|
|
85
|
+
signedString: unknownPostOrEvent.signed_message,
|
|
86
|
+
signature: unknownPostOrEvent.signature
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// Option 2.
|
|
91
|
+
// If an object doesn't have a sealed event (signed string), then
|
|
92
|
+
// - either the object itself is a web3 event,
|
|
93
|
+
// - or the object is a web2 post (e.g., from an RSS feed).
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
info.webType = false;
|
|
97
|
+
info.eventIsSealed = false;
|
|
98
|
+
info.eventIsSealedUnderKeyName = false;
|
|
99
|
+
unknownEventOrWeb2Post = unknownPostOrEvent;
|
|
100
|
+
}
|
|
101
|
+
const eventInfo = (0, exports.identifyEvent)(unknownEventOrWeb2Post);
|
|
102
|
+
// An object has been identified as a web3 event.
|
|
103
|
+
if (eventInfo?.type && typeof (eventInfo.type) === "string") {
|
|
104
|
+
// web3 post and web3 event
|
|
105
|
+
info.webType = "web3";
|
|
106
|
+
info.eventInfo = eventInfo;
|
|
107
|
+
return info;
|
|
108
|
+
// An object has not been identified as a web3 event.
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
// web2 post
|
|
112
|
+
info.webType = "web2";
|
|
113
|
+
info.eventInfo = false;
|
|
114
|
+
return info;
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
exports.identifyPostOrEvent = identifyPostOrEvent;
|
|
118
|
+
const isWeb2Post = (unknownPostOrEvent) => {
|
|
119
|
+
if (!(0, utils_1.isObjectWithValues)(unknownPostOrEvent))
|
|
120
|
+
return false;
|
|
121
|
+
if (
|
|
122
|
+
// signatures
|
|
123
|
+
'sig' in unknownPostOrEvent ||
|
|
124
|
+
'signature' in unknownPostOrEvent ||
|
|
125
|
+
'signed_message' in unknownPostOrEvent ||
|
|
126
|
+
'signedObject' in unknownPostOrEvent ||
|
|
127
|
+
'signedString' in unknownPostOrEvent) {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
if ((0, exports.isNostrEvent)(unknownPostOrEvent))
|
|
131
|
+
return false;
|
|
132
|
+
if ((0, exports.isDmpEvent)(unknownPostOrEvent))
|
|
133
|
+
return false;
|
|
134
|
+
if ((0, exports.isDmpEventSignedClosed)(unknownPostOrEvent))
|
|
135
|
+
return false;
|
|
136
|
+
if ((0, exports.isDmpEventSignedOpened)(unknownPostOrEvent))
|
|
137
|
+
return false;
|
|
138
|
+
return false;
|
|
139
|
+
};
|
|
140
|
+
exports.isWeb2Post = isWeb2Post;
|
|
141
|
+
const isWeb3Post = (unknownPostOrEvent) => {
|
|
142
|
+
if (!(0, utils_1.isObjectWithValues)(unknownPostOrEvent))
|
|
143
|
+
return false;
|
|
144
|
+
if ('signed_message' in unknownPostOrEvent &&
|
|
145
|
+
typeof (unknownPostOrEvent.signed_message) === "string") {
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
return false;
|
|
149
|
+
};
|
|
150
|
+
exports.isWeb3Post = isWeb3Post;
|
|
151
|
+
const identifyEvent = (unknownPostOrEvent) => {
|
|
152
|
+
console.log("identifyEvent called");
|
|
153
|
+
const eventInfo = {
|
|
154
|
+
type: "unknown",
|
|
155
|
+
hasSignature: false,
|
|
156
|
+
baseProtocol: false,
|
|
157
|
+
privateKey: false,
|
|
158
|
+
isSpasmCompatible: false,
|
|
159
|
+
hasExtraSpasmFields: false,
|
|
160
|
+
license: false
|
|
161
|
+
};
|
|
162
|
+
if (!(0, utils_1.isObjectWithValues)(unknownPostOrEvent))
|
|
163
|
+
return eventInfo;
|
|
164
|
+
eventInfo.license = (0, exports.identifyLicense)(unknownPostOrEvent);
|
|
165
|
+
// TODO: refactor
|
|
166
|
+
// verifySignature()
|
|
167
|
+
// add key 'isSignatureValid' to EventInfo
|
|
168
|
+
// check privateKey after discovering eventInfo.type
|
|
169
|
+
if ((0, exports.hasSignature)(unknownPostOrEvent))
|
|
170
|
+
eventInfo.hasSignature = true;
|
|
171
|
+
// Another approach is to set a private key after identifying
|
|
172
|
+
// the event type (eventInfo.type).
|
|
173
|
+
if (eventInfo.hasSignature) {
|
|
174
|
+
eventInfo.privateKey = (0, exports.identifyPrivateKey)(unknownPostOrEvent);
|
|
175
|
+
}
|
|
176
|
+
if ((0, exports.hasExtraSpasmFields)(unknownPostOrEvent))
|
|
177
|
+
eventInfo.hasExtraSpasmFields = true;
|
|
178
|
+
// DMP
|
|
179
|
+
// Might be DMP or Nostr or web2 Post
|
|
180
|
+
if (!eventInfo.hasSignature && !eventInfo.hasExtraSpasmFields) {
|
|
181
|
+
if ((0, exports.isDmpEvent)(unknownPostOrEvent)) {
|
|
182
|
+
eventInfo.type = "DmpEvent";
|
|
183
|
+
eventInfo.baseProtocol = "dmp";
|
|
184
|
+
eventInfo.isSpasmCompatible = true;
|
|
185
|
+
return eventInfo;
|
|
186
|
+
}
|
|
187
|
+
// Might be DMP or Nostr with signature or Post with signature
|
|
188
|
+
}
|
|
189
|
+
else if (eventInfo.hasSignature && !eventInfo.hasExtraSpasmFields) {
|
|
190
|
+
if ((0, exports.isDmpEventSignedOpened)(unknownPostOrEvent)) {
|
|
191
|
+
eventInfo.type = "DmpEventSignedOpened";
|
|
192
|
+
eventInfo.baseProtocol = "dmp";
|
|
193
|
+
eventInfo.isSpasmCompatible = true;
|
|
194
|
+
return eventInfo;
|
|
195
|
+
}
|
|
196
|
+
else if ((0, exports.isDmpEventSignedClosed)(unknownPostOrEvent)) {
|
|
197
|
+
eventInfo.type = "DmpEventSignedClosed";
|
|
198
|
+
eventInfo.baseProtocol = "dmp";
|
|
199
|
+
eventInfo.isSpasmCompatible = true;
|
|
200
|
+
return eventInfo;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
// Nostr
|
|
204
|
+
if (eventInfo.hasSignature && eventInfo.hasExtraSpasmFields) {
|
|
205
|
+
// Looks like Nostr event with signature and SPASM fields
|
|
206
|
+
if ((0, exports.isNostrSpasmEventSignedOpened)(unknownPostOrEvent)) {
|
|
207
|
+
eventInfo.type = "NostrSpasmEventSignedOpened";
|
|
208
|
+
eventInfo.baseProtocol = "nostr";
|
|
209
|
+
eventInfo.isSpasmCompatible = true;
|
|
210
|
+
return eventInfo;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
else if (eventInfo.hasSignature && !eventInfo.hasExtraSpasmFields) {
|
|
214
|
+
// Looks like Nostr event with signature without SPASM fields
|
|
215
|
+
if ((0, exports.isNostrEventSignedOpened)(unknownPostOrEvent)) {
|
|
216
|
+
eventInfo.type = "NostrEventSignedOpened";
|
|
217
|
+
eventInfo.baseProtocol = "nostr";
|
|
218
|
+
eventInfo.isSpasmCompatible = false;
|
|
219
|
+
return eventInfo;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
else if (!eventInfo.hasSignature && eventInfo.hasExtraSpasmFields) {
|
|
223
|
+
// Looks like Nostr event without signature, but with SPASM fields
|
|
224
|
+
if ((0, exports.isNostrSpasmEvent)(unknownPostOrEvent)) {
|
|
225
|
+
eventInfo.type = "NostrSpasmEvent";
|
|
226
|
+
eventInfo.baseProtocol = "nostr";
|
|
227
|
+
eventInfo.isSpasmCompatible = true;
|
|
228
|
+
return eventInfo;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
else if (!eventInfo.hasSignature && !eventInfo.hasExtraSpasmFields) {
|
|
232
|
+
// Looks like Nostr event without signature and without SPASM fields
|
|
233
|
+
if ((0, exports.isNostrEvent)(unknownPostOrEvent)) {
|
|
234
|
+
eventInfo.type = "NostrEvent";
|
|
235
|
+
eventInfo.baseProtocol = "nostr";
|
|
236
|
+
eventInfo.isSpasmCompatible = false;
|
|
237
|
+
return eventInfo;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
exports.identifyEvent = identifyEvent;
|
|
242
|
+
const hasSignature = (unknownPostOrEvent, signatureKey, signatureLength = 40) => {
|
|
243
|
+
if (!(0, utils_1.isObjectWithValues)(unknownPostOrEvent))
|
|
244
|
+
return false;
|
|
245
|
+
let keys = signatureKey
|
|
246
|
+
? [signatureKey] // signature key is provided
|
|
247
|
+
: ['signature', 'sig']; // check all signature keys
|
|
248
|
+
for (let key of keys) {
|
|
249
|
+
if (key in unknownPostOrEvent &&
|
|
250
|
+
typeof (unknownPostOrEvent[key]) === 'string' &&
|
|
251
|
+
unknownPostOrEvent[key].length > signatureLength) {
|
|
252
|
+
return true;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
return false;
|
|
256
|
+
};
|
|
257
|
+
exports.hasSignature = hasSignature;
|
|
258
|
+
const identifyLicense = (unknownPostOrEvent) => {
|
|
259
|
+
if (!(0, utils_1.isObjectWithValues)(unknownPostOrEvent))
|
|
260
|
+
return false;
|
|
261
|
+
let license = false;
|
|
262
|
+
// Option 1.
|
|
263
|
+
// A license can be inside a 'license' key
|
|
264
|
+
// or inside tags (e.g. SPASM tags in Nostr events).
|
|
265
|
+
if ('license' in unknownPostOrEvent &&
|
|
266
|
+
typeof (unknownPostOrEvent['license']) === 'string' &&
|
|
267
|
+
unknownPostOrEvent['license'].length > 0) {
|
|
268
|
+
license = unknownPostOrEvent['license'];
|
|
269
|
+
if (license)
|
|
270
|
+
return license;
|
|
271
|
+
}
|
|
272
|
+
license = (0, exports.identifyLicenseInsideTags)(unknownPostOrEvent);
|
|
273
|
+
if (license)
|
|
274
|
+
return license;
|
|
275
|
+
// Option 2.
|
|
276
|
+
// If no license was found, then we should try to extract
|
|
277
|
+
// an object (event) from a signed string if such a string
|
|
278
|
+
// exists, and then check that object for a license.
|
|
279
|
+
const signedObject = (0, exports.extractSealedEvent)(unknownPostOrEvent);
|
|
280
|
+
if (!signedObject)
|
|
281
|
+
return false;
|
|
282
|
+
if (!(0, utils_1.isObjectWithValues)(signedObject))
|
|
283
|
+
return false;
|
|
284
|
+
if ('license' in signedObject &&
|
|
285
|
+
typeof (signedObject['license']) === 'string' &&
|
|
286
|
+
signedObject['license'].length > 0) {
|
|
287
|
+
license = signedObject['license'];
|
|
288
|
+
if (license)
|
|
289
|
+
return license;
|
|
290
|
+
}
|
|
291
|
+
license = (0, exports.identifyLicenseInsideTags)(signedObject);
|
|
292
|
+
if (license)
|
|
293
|
+
return license;
|
|
294
|
+
return false;
|
|
295
|
+
};
|
|
296
|
+
exports.identifyLicense = identifyLicense;
|
|
297
|
+
const identifyLicenseInsideTags = (unknownPostOrEvent) => {
|
|
298
|
+
if (!(0, utils_1.isObjectWithValues)(unknownPostOrEvent))
|
|
299
|
+
return false;
|
|
300
|
+
let license = false;
|
|
301
|
+
// A license can be placed inside SPASM tags
|
|
302
|
+
if ('tags' in unknownPostOrEvent &&
|
|
303
|
+
Array.isArray(unknownPostOrEvent.tags)) {
|
|
304
|
+
// Nostr events have tags of array type: NostrSpasmTag | AnyTag
|
|
305
|
+
// Post events have tags of string type: string
|
|
306
|
+
unknownPostOrEvent.tags.forEach(function (tag) {
|
|
307
|
+
if (Array.isArray(tag)) {
|
|
308
|
+
if (tag[0] === "license" &&
|
|
309
|
+
typeof (tag[1]) === "string") {
|
|
310
|
+
license = tag[1];
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
return license;
|
|
316
|
+
};
|
|
317
|
+
exports.identifyLicenseInsideTags = identifyLicenseInsideTags;
|
|
318
|
+
const extractSealedEvent = (unknownPostOrEvent) => {
|
|
319
|
+
if (!(0, utils_1.isObjectWithValues)(unknownPostOrEvent))
|
|
320
|
+
return false;
|
|
321
|
+
let signedObject = false;
|
|
322
|
+
if ('signed_message' in unknownPostOrEvent &&
|
|
323
|
+
typeof (unknownPostOrEvent['signed_message'] === "string")) {
|
|
324
|
+
signedObject = JSON.parse(unknownPostOrEvent['signed_message']);
|
|
325
|
+
}
|
|
326
|
+
else if ('signedString' in unknownPostOrEvent &&
|
|
327
|
+
typeof (unknownPostOrEvent['signedString'] === "string")) {
|
|
328
|
+
signedObject = JSON.parse(unknownPostOrEvent['signedString']);
|
|
329
|
+
}
|
|
330
|
+
return signedObject;
|
|
331
|
+
};
|
|
332
|
+
exports.extractSealedEvent = extractSealedEvent;
|
|
333
|
+
const identifyPrivateKey = (unknownPostOrEvent) => {
|
|
334
|
+
if (!(0, utils_1.isObjectWithValues)(unknownPostOrEvent))
|
|
335
|
+
return false;
|
|
336
|
+
/**
|
|
337
|
+
* If an object has 'sig' key, then it's most likely a Nostr event.
|
|
338
|
+
* Currently, all Nostr events can only be signed with a Nostr private
|
|
339
|
+
* key, so we can assume that a private key is "nostr".
|
|
340
|
+
* In the future there might be an option to sign Nostr events with
|
|
341
|
+
* different keys, so we will have to update the logic.
|
|
342
|
+
*/
|
|
343
|
+
if ('sig' in unknownPostOrEvent &&
|
|
344
|
+
typeof (unknownPostOrEvent['sig']) === 'string' &&
|
|
345
|
+
unknownPostOrEvent['sig'].length > 40) {
|
|
346
|
+
return 'nostr';
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* A post with a sealed event (hidden inside the signed string)
|
|
350
|
+
* under the key like 'signed_message' or 'signedObject' will
|
|
351
|
+
* usually have a signature inside a 'signature' key.
|
|
352
|
+
*
|
|
353
|
+
* So if an object has a 'signature' key, then it can be:
|
|
354
|
+
* - a DMP event signed with the Ethereum private key,
|
|
355
|
+
* - has 'signature'
|
|
356
|
+
* - a Post with a sealed DMP event signed with an Ethereum private key,
|
|
357
|
+
* - has 'signature'
|
|
358
|
+
* - a Post with a sealed Nostr event signed with a Nostr private key.
|
|
359
|
+
* - has 'signature'
|
|
360
|
+
* - and also has 'sig' inside 'signed_message'
|
|
361
|
+
*
|
|
362
|
+
* In other words, a Post with a sealed Nostr event will have
|
|
363
|
+
* the same signature recorded twice in different places:
|
|
364
|
+
* 1. Inside a 'signature' key in the Post (envelope).
|
|
365
|
+
* 2. Inside a 'sig' key in the object extracted from a signed string.
|
|
366
|
+
* While, a Post with a sealed DMP event will only have the signature
|
|
367
|
+
* specified once inside the 'signature' key.
|
|
368
|
+
*
|
|
369
|
+
* Thus, we have to convert the signed string into an object,
|
|
370
|
+
* then check whether it has a 'sig' key (Nostr event),
|
|
371
|
+
* otherwise assume that it was signed with an Ethereum private key.
|
|
372
|
+
*/
|
|
373
|
+
if ('signature' in unknownPostOrEvent &&
|
|
374
|
+
typeof (unknownPostOrEvent?.['signature']) === 'string' &&
|
|
375
|
+
unknownPostOrEvent?.['signature'].length > 40) {
|
|
376
|
+
if ('signed_message' in unknownPostOrEvent &&
|
|
377
|
+
typeof (unknownPostOrEvent?.['signed_message']) === 'string') {
|
|
378
|
+
const signedObject = JSON.parse(unknownPostOrEvent?.['signed_message']);
|
|
379
|
+
if (!(0, utils_1.isObjectWithValues)(signedObject))
|
|
380
|
+
return false;
|
|
381
|
+
if ('sig' in unknownPostOrEvent &&
|
|
382
|
+
typeof (unknownPostOrEvent['sig']) === 'string' &&
|
|
383
|
+
unknownPostOrEvent['sig'].length > 40) {
|
|
384
|
+
return 'nostr';
|
|
385
|
+
}
|
|
386
|
+
else {
|
|
387
|
+
return 'ethereum';
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
if ('signedString' in unknownPostOrEvent &&
|
|
391
|
+
typeof (unknownPostOrEvent?.['signedString']) === 'string') {
|
|
392
|
+
const signedObject = JSON.parse(unknownPostOrEvent?.['signedString']);
|
|
393
|
+
if (!(0, utils_1.isObjectWithValues)(signedObject))
|
|
394
|
+
return false;
|
|
395
|
+
if ((0, exports.isDmpEvent)(signedObject))
|
|
396
|
+
return 'ethereum';
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
};
|
|
400
|
+
exports.identifyPrivateKey = identifyPrivateKey;
|
|
401
|
+
const hasExtraSpasmFields = (unknownPostOrEvent) => {
|
|
402
|
+
if (!(0, utils_1.isObjectWithValues)(unknownPostOrEvent))
|
|
403
|
+
return false;
|
|
404
|
+
if ('tags' in unknownPostOrEvent &&
|
|
405
|
+
Array.isArray(unknownPostOrEvent.tags)) {
|
|
406
|
+
// spasm_version is optional
|
|
407
|
+
let hasSpasmVersion = false;
|
|
408
|
+
// spasm_target is optional (e.g. new posts have no target)
|
|
409
|
+
let hasSpasmTarget = false;
|
|
410
|
+
// spasm_action is optional for Nostr (can be taken from 'kind' key)
|
|
411
|
+
let hasSpasmAction = false;
|
|
412
|
+
// spasm_title is optional (e.g. comments/reactions have no title)
|
|
413
|
+
let hasSpasmTitle = false;
|
|
414
|
+
// Nostr events have tags of array type: NostrSpasmTag | AnyTag
|
|
415
|
+
// Post events have tags of string type: string
|
|
416
|
+
unknownPostOrEvent.tags.forEach(function (tag) {
|
|
417
|
+
if (Array.isArray(tag)) {
|
|
418
|
+
if (tag[0] === "spasm_version") {
|
|
419
|
+
hasSpasmVersion = true;
|
|
420
|
+
}
|
|
421
|
+
if (tag[0] === "spasm_target") {
|
|
422
|
+
hasSpasmTarget = true;
|
|
423
|
+
}
|
|
424
|
+
if (tag[0] === "spasm_action") {
|
|
425
|
+
hasSpasmAction = true;
|
|
426
|
+
}
|
|
427
|
+
if (tag[0] === "spasm_title") {
|
|
428
|
+
hasSpasmTitle = true;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
});
|
|
432
|
+
if (hasSpasmVersion || hasSpasmTarget || hasSpasmAction || hasSpasmTitle) {
|
|
433
|
+
return true;
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
return false;
|
|
437
|
+
};
|
|
438
|
+
exports.hasExtraSpasmFields = hasExtraSpasmFields;
|
|
439
|
+
const isNostrEvent = (unknownPostOrEvent) => {
|
|
440
|
+
if (!(0, utils_1.isObjectWithValues)(unknownPostOrEvent))
|
|
441
|
+
return false;
|
|
442
|
+
// Unsigned Nostr event can be without 'id'
|
|
443
|
+
// if (!('id' in unknownPostOrEvent)) return false
|
|
444
|
+
// content
|
|
445
|
+
if (!('content' in unknownPostOrEvent))
|
|
446
|
+
return false;
|
|
447
|
+
if (!unknownPostOrEvent.content)
|
|
448
|
+
return false;
|
|
449
|
+
if (typeof (unknownPostOrEvent.content) !== "string")
|
|
450
|
+
return false;
|
|
451
|
+
// created_at
|
|
452
|
+
if (!('created_at' in unknownPostOrEvent))
|
|
453
|
+
return false;
|
|
454
|
+
// 0 is a valid created_at
|
|
455
|
+
if (!unknownPostOrEvent.created_at &&
|
|
456
|
+
unknownPostOrEvent.created_at !== 0)
|
|
457
|
+
return false;
|
|
458
|
+
if (typeof (unknownPostOrEvent.created_at) !== "number")
|
|
459
|
+
return false;
|
|
460
|
+
// kind
|
|
461
|
+
if (!('kind' in unknownPostOrEvent))
|
|
462
|
+
return false;
|
|
463
|
+
// 0 is a valid kind
|
|
464
|
+
if (!unknownPostOrEvent.kind &&
|
|
465
|
+
unknownPostOrEvent.kind !== 0)
|
|
466
|
+
return false;
|
|
467
|
+
if (typeof (unknownPostOrEvent.kind) !== "number")
|
|
468
|
+
return false;
|
|
469
|
+
// pubkey
|
|
470
|
+
if (!('pubkey' in unknownPostOrEvent))
|
|
471
|
+
return false;
|
|
472
|
+
if (!unknownPostOrEvent.pubkey)
|
|
473
|
+
return false;
|
|
474
|
+
if (typeof (unknownPostOrEvent.pubkey) !== "string")
|
|
475
|
+
return false;
|
|
476
|
+
// tags
|
|
477
|
+
// TODO: check if tags is a mandatory field
|
|
478
|
+
// if (!('tags' in unknownPostOrEvent)) return false
|
|
479
|
+
// sig
|
|
480
|
+
// Unsigned Nostr event can be without 'sig'
|
|
481
|
+
// if (!('sig' in unknownPostOrEvent)) return false
|
|
482
|
+
return true;
|
|
483
|
+
};
|
|
484
|
+
exports.isNostrEvent = isNostrEvent;
|
|
485
|
+
const isNostrEventSignedOpened = (unknownPostOrEvent) => {
|
|
486
|
+
if (!(0, utils_1.isObjectWithValues)(unknownPostOrEvent))
|
|
487
|
+
return false;
|
|
488
|
+
if (!(0, exports.isNostrEvent)(unknownPostOrEvent))
|
|
489
|
+
return false;
|
|
490
|
+
// Signed Nostr event must have 'id'
|
|
491
|
+
if (!('id' in unknownPostOrEvent))
|
|
492
|
+
return false;
|
|
493
|
+
if (!(0, exports.hasSignature)(unknownPostOrEvent, 'sig'))
|
|
494
|
+
return false;
|
|
495
|
+
return true;
|
|
496
|
+
};
|
|
497
|
+
exports.isNostrEventSignedOpened = isNostrEventSignedOpened;
|
|
498
|
+
const isNostrSpasmEvent = (unknownPostOrEvent) => {
|
|
499
|
+
if (!(0, utils_1.isObjectWithValues)(unknownPostOrEvent))
|
|
500
|
+
return false;
|
|
501
|
+
if (!(0, exports.isNostrEvent)(unknownPostOrEvent))
|
|
502
|
+
return false;
|
|
503
|
+
if (!(0, exports.hasExtraSpasmFields)(unknownPostOrEvent))
|
|
504
|
+
return false;
|
|
505
|
+
return true;
|
|
506
|
+
};
|
|
507
|
+
exports.isNostrSpasmEvent = isNostrSpasmEvent;
|
|
508
|
+
const isNostrSpasmEventSignedOpened = (unknownPostOrEvent) => {
|
|
509
|
+
if (!(0, utils_1.isObjectWithValues)(unknownPostOrEvent))
|
|
510
|
+
return false;
|
|
511
|
+
if (!(0, exports.isNostrSpasmEvent)(unknownPostOrEvent))
|
|
512
|
+
return false;
|
|
513
|
+
if (!(0, exports.isNostrEventSignedOpened)(unknownPostOrEvent))
|
|
514
|
+
return false;
|
|
515
|
+
return true;
|
|
516
|
+
};
|
|
517
|
+
exports.isNostrSpasmEventSignedOpened = isNostrSpasmEventSignedOpened;
|
|
518
|
+
const isDmpEvent = (unknownPostOrEvent) => {
|
|
519
|
+
if (!(0, utils_1.isObjectWithValues)(unknownPostOrEvent))
|
|
520
|
+
return false;
|
|
521
|
+
// TODO: think what if unknownPostOrEvent is Post with version, action, license
|
|
522
|
+
if (!('version' in unknownPostOrEvent))
|
|
523
|
+
return false;
|
|
524
|
+
if (!('action' in unknownPostOrEvent))
|
|
525
|
+
return false;
|
|
526
|
+
if (!('license' in unknownPostOrEvent))
|
|
527
|
+
return false;
|
|
528
|
+
// time is optional
|
|
529
|
+
// if (!('time' in unknownPostOrEvent)) return false
|
|
530
|
+
// target is optional (e.g. a new post has no target)
|
|
531
|
+
// if (!('target' in unknownPostOrEvent)) return false
|
|
532
|
+
// title is optional (e.g. a comment has no title)
|
|
533
|
+
// if (!('title' in unknownPostOrEvent)) return false
|
|
534
|
+
// text is optional (e.g. an event has only title)
|
|
535
|
+
// if (!('text' in unknownPostOrEvent)) return false
|
|
536
|
+
if (!unknownPostOrEvent?.version?.startsWith("dmp"))
|
|
537
|
+
return false;
|
|
538
|
+
return true;
|
|
539
|
+
};
|
|
540
|
+
exports.isDmpEvent = isDmpEvent;
|
|
541
|
+
const isDmpEventSignedClosed = (unknownPostOrEvent) => {
|
|
542
|
+
if (!(0, utils_1.isObjectWithValues)(unknownPostOrEvent))
|
|
543
|
+
return false;
|
|
544
|
+
if (!('signedString' in unknownPostOrEvent))
|
|
545
|
+
return false;
|
|
546
|
+
if (!('signature' in unknownPostOrEvent))
|
|
547
|
+
return false;
|
|
548
|
+
// signer is optional
|
|
549
|
+
// if (!('signer' in unknownPostOrEvent)) return false
|
|
550
|
+
if (typeof (unknownPostOrEvent.signedString) !== "string")
|
|
551
|
+
return false;
|
|
552
|
+
const signedObject = JSON.parse(unknownPostOrEvent.signedString);
|
|
553
|
+
if (!(0, exports.isDmpEvent)(signedObject))
|
|
554
|
+
return false;
|
|
555
|
+
return true;
|
|
556
|
+
};
|
|
557
|
+
exports.isDmpEventSignedClosed = isDmpEventSignedClosed;
|
|
558
|
+
const isDmpEventSignedOpened = (unknownPostOrEvent) => {
|
|
559
|
+
if (!(0, utils_1.isObjectWithValues)(unknownPostOrEvent))
|
|
560
|
+
return false;
|
|
561
|
+
if (!exports.isDmpEventSignedClosed)
|
|
562
|
+
return false;
|
|
563
|
+
if ('signedObject' in unknownPostOrEvent) {
|
|
564
|
+
if ((0, exports.isDmpEvent)(unknownPostOrEvent.signedObject))
|
|
565
|
+
return true;
|
|
566
|
+
}
|
|
567
|
+
return false;
|
|
568
|
+
};
|
|
569
|
+
exports.isDmpEventSignedOpened = isDmpEventSignedOpened;
|
|
570
|
+
/**
|
|
571
|
+
* 1. Post can contain DPM event without signature as a string inside
|
|
572
|
+
* signed_message, so signature is attached with 'signature' key.
|
|
573
|
+
*
|
|
574
|
+
* isPostWithDmpEventSignedOpened()
|
|
575
|
+
* - contains isDmpEventSignedOpened()
|
|
576
|
+
* isPostWithDmpEventSignedClosed()
|
|
577
|
+
* - contains isDmpEventSignedClosed()
|
|
578
|
+
* isPostWithDmpEvent()
|
|
579
|
+
* - contains isDmpEvent()
|
|
580
|
+
*
|
|
581
|
+
* 2. Post can contain Nostr event with signature as a string inside
|
|
582
|
+
* signed_message, and signature is also attached with 'signature' key.
|
|
583
|
+
* In other words, signature will be passed twice:
|
|
584
|
+
* - inside 'sig' key of parsed 'signed_message'
|
|
585
|
+
* - inside 'signature' key of the post object.
|
|
586
|
+
*
|
|
587
|
+
* isPostWithNostrSpasmEventSignedOpened()
|
|
588
|
+
* - contains isNostrSpasmEventSignedOpened()
|
|
589
|
+
* isPostWithNostrEventSignedOpened()
|
|
590
|
+
* - contains isNostrEventSignedOpened()
|
|
591
|
+
* isPostWithNostrSpasmEvent()
|
|
592
|
+
* - contains isNostrSpasmEvent()
|
|
593
|
+
* isPostWithNostrEvent
|
|
594
|
+
* - contains isNostrEvent()
|
|
595
|
+
*/
|
|
596
|
+
const isPostWithDmpEvent = (unknownPostOrEvent) => {
|
|
597
|
+
return !!((0, exports.identifyEventInsidePost)(unknownPostOrEvent) === "DmpEvent");
|
|
598
|
+
};
|
|
599
|
+
exports.isPostWithDmpEvent = isPostWithDmpEvent;
|
|
600
|
+
const isPostWithDmpEventSignedOpened = (unknownPostOrEvent) => {
|
|
601
|
+
return !!((0, exports.identifyEventInsidePost)(unknownPostOrEvent) === "DmpEventSignedOpened");
|
|
602
|
+
};
|
|
603
|
+
exports.isPostWithDmpEventSignedOpened = isPostWithDmpEventSignedOpened;
|
|
604
|
+
const isPostWithDmpEventSignedClosed = (unknownPostOrEvent) => {
|
|
605
|
+
return !!((0, exports.identifyEventInsidePost)(unknownPostOrEvent) === "DmpEventSignedClosed");
|
|
606
|
+
};
|
|
607
|
+
exports.isPostWithDmpEventSignedClosed = isPostWithDmpEventSignedClosed;
|
|
608
|
+
const isPostWithNostrSpasmEventSignedOpened = (unknownPostOrEvent) => {
|
|
609
|
+
return !!((0, exports.identifyEventInsidePost)(unknownPostOrEvent) === "NostrSpasmEventSignedOpened");
|
|
610
|
+
};
|
|
611
|
+
exports.isPostWithNostrSpasmEventSignedOpened = isPostWithNostrSpasmEventSignedOpened;
|
|
612
|
+
const isPostWithNostrEventSignedOpened = (unknownPostOrEvent) => {
|
|
613
|
+
return !!((0, exports.identifyEventInsidePost)(unknownPostOrEvent) === "NostrEventSignedOpened");
|
|
614
|
+
};
|
|
615
|
+
exports.isPostWithNostrEventSignedOpened = isPostWithNostrEventSignedOpened;
|
|
616
|
+
const isPostWithNostrSpasmEvent = (unknownPostOrEvent) => {
|
|
617
|
+
return !!((0, exports.identifyEventInsidePost)(unknownPostOrEvent) === "NostrSpasmEvent");
|
|
618
|
+
};
|
|
619
|
+
exports.isPostWithNostrSpasmEvent = isPostWithNostrSpasmEvent;
|
|
620
|
+
const isPostWithNostrEvent = (unknownPostOrEvent) => {
|
|
621
|
+
return !!((0, exports.identifyEventInsidePost)(unknownPostOrEvent) === "NostrEvent");
|
|
622
|
+
};
|
|
623
|
+
exports.isPostWithNostrEvent = isPostWithNostrEvent;
|
|
624
|
+
const identifyEventInsidePost = (unknownPostOrEvent) => {
|
|
625
|
+
if (!(0, utils_1.isObjectWithValues)(unknownPostOrEvent))
|
|
626
|
+
return false;
|
|
627
|
+
if (!('signed_message' in unknownPostOrEvent))
|
|
628
|
+
return false;
|
|
629
|
+
if (typeof (unknownPostOrEvent.signed_message) !== "string")
|
|
630
|
+
return false;
|
|
631
|
+
const signedObject = JSON.parse(unknownPostOrEvent.signed_message);
|
|
632
|
+
// isNostrEvent() will return true for NostrSpasmEvent,
|
|
633
|
+
// so the order of calling the functions is important.
|
|
634
|
+
// Sorted by popularity/frequency.
|
|
635
|
+
// TODO: Ideally, refactor and call identifyEvent(), which has
|
|
636
|
+
// if statements and calls isSomething... functions in the right
|
|
637
|
+
// order, depending on whether event has signature, etc.
|
|
638
|
+
// DMP
|
|
639
|
+
if ((0, exports.isDmpEventSignedOpened)(signedObject))
|
|
640
|
+
return "DmpEventSignedOpened";
|
|
641
|
+
if ((0, exports.isDmpEventSignedClosed)(signedObject))
|
|
642
|
+
return "DmpEventSignedClosed";
|
|
643
|
+
if ((0, exports.isDmpEvent)(signedObject))
|
|
644
|
+
return "DmpEvent";
|
|
645
|
+
// Nostr
|
|
646
|
+
if ((0, exports.isNostrSpasmEventSignedOpened)(signedObject))
|
|
647
|
+
return "NostrSpasmEventSignedOpened";
|
|
648
|
+
if ((0, exports.isNostrSpasmEvent)(signedObject))
|
|
649
|
+
return "NostrSpasmEvent";
|
|
650
|
+
if ((0, exports.isNostrEventSignedOpened)(signedObject))
|
|
651
|
+
return "NostrEventSignedOpened";
|
|
652
|
+
if ((0, exports.isNostrEvent)(signedObject))
|
|
653
|
+
return "NostrEvent";
|
|
654
|
+
};
|
|
655
|
+
exports.identifyEventInsidePost = identifyEventInsidePost;
|
|
656
|
+
const standartizePostOrEvent = (unknownPostOrEvent, info) => {
|
|
657
|
+
if (!(0, utils_1.isObjectWithValues)(unknownPostOrEvent))
|
|
658
|
+
return false;
|
|
659
|
+
// Info about post/event might be provided.
|
|
660
|
+
// If not, then we should identify an event.
|
|
661
|
+
if (!info) {
|
|
662
|
+
info = (0, exports.identifyPostOrEvent)(unknownPostOrEvent);
|
|
663
|
+
}
|
|
664
|
+
if (!info || !info.webType)
|
|
665
|
+
return false;
|
|
666
|
+
let standartizedEvent = {};
|
|
667
|
+
// DMP event submitted via UI
|
|
668
|
+
if (info.eventInfo &&
|
|
669
|
+
info.eventInfo.type === "DmpEventSignedClosed" &&
|
|
670
|
+
info.eventIsSealed === false) {
|
|
671
|
+
standartizedEvent = (0, exports.standartizeDmpEventSignedClosed)(unknownPostOrEvent);
|
|
672
|
+
}
|
|
673
|
+
// Nostr SPASM event submitted via UI
|
|
674
|
+
if (info.eventInfo &&
|
|
675
|
+
info.eventInfo.type === "NostrSpasmEventSignedOpened" &&
|
|
676
|
+
info.eventIsSealed === false) {
|
|
677
|
+
standartizedEvent = (0, exports.standartizeNostrSpasmEventSignedOpened)(unknownPostOrEvent);
|
|
678
|
+
}
|
|
679
|
+
// Post with sealed DMP event (received e.g. via SPASM module)
|
|
680
|
+
if (info.eventInfo &&
|
|
681
|
+
info.eventInfo.type === "DmpEventSignedClosed" &&
|
|
682
|
+
info.eventIsSealed === true) {
|
|
683
|
+
standartizedEvent = (0, exports.standartizePostWithDmpEventSignedClosed)(unknownPostOrEvent);
|
|
684
|
+
}
|
|
685
|
+
// Post with sealed Nostr event (received e.g. via SPASM module)
|
|
686
|
+
if (info.eventInfo &&
|
|
687
|
+
info.eventInfo.type === "NostrSpasmEventSignedOpened" &&
|
|
688
|
+
info.eventIsSealed === true) {
|
|
689
|
+
standartizedEvent = (0, exports.standartizePostWithNostrSpasmEventSignedOpened)(unknownPostOrEvent);
|
|
690
|
+
}
|
|
691
|
+
return standartizedEvent;
|
|
692
|
+
};
|
|
693
|
+
exports.standartizePostOrEvent = standartizePostOrEvent;
|
|
694
|
+
// standardizeDmpEventSignedClosed
|
|
695
|
+
const standartizeDmpEventSignedClosed = (event) => {
|
|
696
|
+
if (!(0, utils_1.isObjectWithValues)(event))
|
|
697
|
+
return null;
|
|
698
|
+
if (!(0, exports.isDmpEventSignedClosed)(event))
|
|
699
|
+
return null;
|
|
700
|
+
const signedString = event.signedString;
|
|
701
|
+
const signedObject = JSON.parse(signedString);
|
|
702
|
+
const signature = event.signature;
|
|
703
|
+
const signer = event.signer;
|
|
704
|
+
const target = signedObject.target;
|
|
705
|
+
const action = signedObject.action;
|
|
706
|
+
const title = signedObject.title;
|
|
707
|
+
const text = signedObject.text;
|
|
708
|
+
const signedDate = signedObject.time;
|
|
709
|
+
return {
|
|
710
|
+
signedString,
|
|
711
|
+
signature,
|
|
712
|
+
signer,
|
|
713
|
+
target,
|
|
714
|
+
action,
|
|
715
|
+
title,
|
|
716
|
+
text,
|
|
717
|
+
signedDate
|
|
718
|
+
};
|
|
719
|
+
};
|
|
720
|
+
exports.standartizeDmpEventSignedClosed = standartizeDmpEventSignedClosed;
|
|
721
|
+
// standardizeNostrSpasmEventSignedOpened
|
|
722
|
+
const standartizeNostrSpasmEventSignedOpened = (event) => {
|
|
723
|
+
if (!(0, utils_1.isObjectWithValues)(event))
|
|
724
|
+
return null;
|
|
725
|
+
if (!(0, exports.isNostrSpasmEventSignedOpened)(event))
|
|
726
|
+
return null;
|
|
727
|
+
const signedString = JSON.stringify(event);
|
|
728
|
+
// const signedObject: DmpEvent = JSON.parse(signedString)
|
|
729
|
+
const signature = event.sig;
|
|
730
|
+
const signer = (0, utils_1.convertHexToBech32)(event.pubkey);
|
|
731
|
+
const text = event.content;
|
|
732
|
+
// Convert the Unix timestamp to a JavaScript Date object
|
|
733
|
+
const date = new Date(event.created_at * 1000);
|
|
734
|
+
// Format the date in ISO format
|
|
735
|
+
const timestamptz = date.toISOString();
|
|
736
|
+
const signedDate = timestamptz;
|
|
737
|
+
let target;
|
|
738
|
+
let action;
|
|
739
|
+
let title;
|
|
740
|
+
if (event.tags &&
|
|
741
|
+
Array.isArray(event.tags)) {
|
|
742
|
+
event.tags.forEach(function (tag) {
|
|
743
|
+
if (Array.isArray(tag) && tag[0] === "spasm_target") {
|
|
744
|
+
target = tag[1];
|
|
745
|
+
}
|
|
746
|
+
if (Array.isArray(tag) && tag[0] === "spasm_action") {
|
|
747
|
+
action = tag[1];
|
|
748
|
+
}
|
|
749
|
+
if (Array.isArray(tag) && tag[0] === "spasm_title") {
|
|
750
|
+
title = tag[1];
|
|
751
|
+
}
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
return {
|
|
755
|
+
signedString,
|
|
756
|
+
signature,
|
|
757
|
+
signer,
|
|
758
|
+
target,
|
|
759
|
+
action,
|
|
760
|
+
title,
|
|
761
|
+
text,
|
|
762
|
+
signedDate
|
|
763
|
+
};
|
|
764
|
+
};
|
|
765
|
+
exports.standartizeNostrSpasmEventSignedOpened = standartizeNostrSpasmEventSignedOpened;
|
|
766
|
+
// standartizePostWithDmpEventSignedClosed
|
|
767
|
+
const standartizePostWithDmpEventSignedClosed = (post) => {
|
|
768
|
+
if (!(0, utils_1.isObjectWithValues)(post))
|
|
769
|
+
return null;
|
|
770
|
+
if (!('signed_message' in post) ||
|
|
771
|
+
typeof (post.signed_message) !== "string") {
|
|
772
|
+
return null;
|
|
773
|
+
}
|
|
774
|
+
const signedString = post.signed_message;
|
|
775
|
+
const signedObject = JSON.parse(signedString);
|
|
776
|
+
const signature = post.signature;
|
|
777
|
+
const signer = post.signer;
|
|
778
|
+
const target = signedObject.target;
|
|
779
|
+
const action = signedObject.action;
|
|
780
|
+
const title = signedObject.title;
|
|
781
|
+
const text = signedObject.text;
|
|
782
|
+
const signedDate = signedObject.time;
|
|
783
|
+
return {
|
|
784
|
+
signedString,
|
|
785
|
+
signature,
|
|
786
|
+
signer,
|
|
787
|
+
target,
|
|
788
|
+
action,
|
|
789
|
+
title,
|
|
790
|
+
text,
|
|
791
|
+
signedDate
|
|
792
|
+
};
|
|
793
|
+
};
|
|
794
|
+
exports.standartizePostWithDmpEventSignedClosed = standartizePostWithDmpEventSignedClosed;
|
|
795
|
+
// standardizePostWithNostrSpasmEventSignedOpened
|
|
796
|
+
const standartizePostWithNostrSpasmEventSignedOpened = (post) => {
|
|
797
|
+
if (!(0, utils_1.isObjectWithValues)(post))
|
|
798
|
+
return null;
|
|
799
|
+
if (!('signed_message' in post) ||
|
|
800
|
+
typeof (post.signed_message) !== "string") {
|
|
801
|
+
return null;
|
|
802
|
+
}
|
|
803
|
+
// Extract the event
|
|
804
|
+
const event = (0, exports.extractSealedEvent)(post);
|
|
805
|
+
return (0, exports.standartizeNostrSpasmEventSignedOpened)(event);
|
|
806
|
+
};
|
|
807
|
+
exports.standartizePostWithNostrSpasmEventSignedOpened = standartizePostWithNostrSpasmEventSignedOpened;
|
|
808
|
+
const convertToSpasm = (unknownPostOrEvent) => {
|
|
809
|
+
return (0, exports.standartizePostOrEvent)(unknownPostOrEvent);
|
|
810
|
+
};
|
|
811
|
+
exports.convertToSpasm = convertToSpasm;
|
|
812
|
+
//# sourceMappingURL=identifyEvent.js.map
|