@orangecheck/sdk 1.14.1 → 1.16.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/README.md +2 -1
- package/dist/attestation.js +228 -64
- package/dist/attestation.js.map +1 -1
- package/dist/attestation.mjs +228 -64
- package/dist/attestation.mjs.map +1 -1
- package/dist/challenge.d.mts +1 -0
- package/dist/challenge.d.ts +1 -0
- package/dist/challenge.js +20 -14
- package/dist/challenge.js.map +1 -1
- package/dist/challenge.mjs +20 -14
- package/dist/challenge.mjs.map +1 -1
- package/dist/identity.js +19 -17
- package/dist/identity.js.map +1 -1
- package/dist/identity.mjs +19 -17
- package/dist/identity.mjs.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +555 -585
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +554 -586
- package/dist/index.mjs.map +1 -1
- package/dist/nostr.d.mts +3 -1
- package/dist/nostr.d.ts +3 -1
- package/dist/nostr.js +213 -38
- package/dist/nostr.js.map +1 -1
- package/dist/nostr.mjs +212 -39
- package/dist/nostr.mjs.map +1 -1
- package/dist/verify.d.mts +11 -2
- package/dist/verify.d.ts +11 -2
- package/dist/verify.js +39 -100
- package/dist/verify.js.map +1 -1
- package/dist/verify.mjs +39 -101
- package/dist/verify.mjs.map +1 -1
- package/package.json +2 -2
package/dist/nostr.mjs
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { bech32 } from '@scure/base';
|
|
2
|
+
import { verifySignature as verifySignature$1 } from '@orangecheck/bip322';
|
|
3
|
+
import { Buffer } from 'buffer';
|
|
2
4
|
|
|
3
5
|
// src/nostr-pubkey.ts
|
|
4
6
|
var HEX_64_RE = /^[0-9a-f]{64}$/;
|
|
@@ -71,8 +73,135 @@ function createLogger(namespace) {
|
|
|
71
73
|
};
|
|
72
74
|
}
|
|
73
75
|
|
|
76
|
+
// src/utils/time.ts
|
|
77
|
+
var RFC3339 = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/;
|
|
78
|
+
function rfc3339Ms(value) {
|
|
79
|
+
if (!value || !RFC3339.test(value)) return null;
|
|
80
|
+
const ms = Date.parse(value);
|
|
81
|
+
return Number.isNaN(ms) ? null : ms;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// src/canonical.ts
|
|
85
|
+
var IDENTITY_PROTOCOL_RE = /^[a-z][a-z0-9_-]*$/;
|
|
86
|
+
var IDENTITY_FORBIDDEN_CHARS = /[\r\n,]/;
|
|
87
|
+
function assertSafeIdentity({ protocol, identifier }) {
|
|
88
|
+
if (!IDENTITY_PROTOCOL_RE.test(protocol)) {
|
|
89
|
+
throw new Error(
|
|
90
|
+
`invalid identity protocol: ${JSON.stringify(protocol)} \u2014 must match /^[a-z][a-z0-9_-]*$/`
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
if (!identifier || IDENTITY_FORBIDDEN_CHARS.test(identifier)) {
|
|
94
|
+
throw new Error(
|
|
95
|
+
`invalid identity identifier: ${JSON.stringify(identifier)} \u2014 must be non-empty and contain no newlines or commas`
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function parseIdentities(identitiesStr) {
|
|
100
|
+
if (!identitiesStr || identitiesStr.trim() === "") {
|
|
101
|
+
return [];
|
|
102
|
+
}
|
|
103
|
+
if (IDENTITY_FORBIDDEN_CHARS.test(identitiesStr.replace(/,/g, ""))) {
|
|
104
|
+
throw new Error("identities field contains forbidden characters (newline)");
|
|
105
|
+
}
|
|
106
|
+
const bindings = identitiesStr.split(",").map((binding) => {
|
|
107
|
+
const colonIndex = binding.indexOf(":");
|
|
108
|
+
if (colonIndex === -1) {
|
|
109
|
+
throw new Error(`Invalid identity binding format: ${binding}`);
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
protocol: binding.substring(0, colonIndex).trim(),
|
|
113
|
+
identifier: binding.substring(colonIndex + 1).trim()
|
|
114
|
+
};
|
|
115
|
+
});
|
|
116
|
+
for (const b of bindings) {
|
|
117
|
+
if (!b.protocol || !b.identifier) {
|
|
118
|
+
throw new Error(`Invalid identity binding: ${b.protocol}:${b.identifier}`);
|
|
119
|
+
}
|
|
120
|
+
assertSafeIdentity(b);
|
|
121
|
+
}
|
|
122
|
+
return bindings;
|
|
123
|
+
}
|
|
124
|
+
function toBase64Maybe(sig) {
|
|
125
|
+
if (/^[0-9a-fA-F]+$/.test(sig) && sig.length % 2 === 0) {
|
|
126
|
+
return Buffer.from(sig, "hex").toString("base64");
|
|
127
|
+
}
|
|
128
|
+
return sig;
|
|
129
|
+
}
|
|
130
|
+
function signatureScheme(sigBase64) {
|
|
131
|
+
if (/^(ful|pof)/.test(sigBase64)) return null;
|
|
132
|
+
if (sigBase64.startsWith("smp")) return "bip322";
|
|
133
|
+
return Buffer.from(sigBase64, "base64").length === 65 ? "legacy" : "bip322";
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// src/verify.ts
|
|
137
|
+
var log = createLogger("ocp/verify");
|
|
138
|
+
async function verifySignature({ addr, msg, sig }) {
|
|
139
|
+
const sigBase64 = toBase64Maybe(sig);
|
|
140
|
+
const scheme = signatureScheme(sigBase64);
|
|
141
|
+
if (!scheme) return "sig_unsupported_script";
|
|
142
|
+
const ok = verifySignature$1(addr, msg, sigBase64);
|
|
143
|
+
log.info({ addr, ok, scheme, msgLength: msg.length }, "Signature verification result");
|
|
144
|
+
if (!ok) return "sig_invalid";
|
|
145
|
+
return scheme === "legacy" ? "sig_ok_legacy" : "sig_ok_bip322";
|
|
146
|
+
}
|
|
147
|
+
async function signatureIsValid(input) {
|
|
148
|
+
try {
|
|
149
|
+
const code = await verifySignature(input);
|
|
150
|
+
return code === "sig_ok_bip322" || code === "sig_ok_legacy";
|
|
151
|
+
} catch {
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
function parseCanonicalMessage(msg) {
|
|
156
|
+
const lines = msg.split("\n").map((l) => l.trim());
|
|
157
|
+
const getVal = (prefix) => {
|
|
158
|
+
const needle = prefix + ":";
|
|
159
|
+
const hit = lines.find((l) => l.toLowerCase().startsWith(needle));
|
|
160
|
+
if (!hit) return void 0;
|
|
161
|
+
const idx = hit.indexOf(":");
|
|
162
|
+
return hit.slice(idx + 1).trim();
|
|
163
|
+
};
|
|
164
|
+
const address = getVal("address") || "";
|
|
165
|
+
const identitiesStr = getVal("identities") || "";
|
|
166
|
+
const issued_at = getVal("issued_at") || "";
|
|
167
|
+
const expires = getVal("expires");
|
|
168
|
+
let identities = [];
|
|
169
|
+
try {
|
|
170
|
+
identities = parseIdentities(identitiesStr);
|
|
171
|
+
} catch (err) {
|
|
172
|
+
log.warn({ identitiesStr, error: err }, "Failed to parse identities field");
|
|
173
|
+
}
|
|
174
|
+
const coreKeys = /* @__PURE__ */ new Set([
|
|
175
|
+
"orangecheck",
|
|
176
|
+
"identities",
|
|
177
|
+
"address",
|
|
178
|
+
"purpose",
|
|
179
|
+
"nonce",
|
|
180
|
+
"issued_at",
|
|
181
|
+
"ack"
|
|
182
|
+
]);
|
|
183
|
+
const extensions = {};
|
|
184
|
+
for (const line of lines) {
|
|
185
|
+
const idx = line.indexOf(":");
|
|
186
|
+
if (idx === -1) continue;
|
|
187
|
+
const key = line.slice(0, idx).trim().toLowerCase();
|
|
188
|
+
const val = line.slice(idx + 1).trim();
|
|
189
|
+
if (!coreKeys.has(key) && val) extensions[key] = val;
|
|
190
|
+
}
|
|
191
|
+
const network = extensions["network"] || "mainnet";
|
|
192
|
+
const bondStr = extensions["bond"];
|
|
193
|
+
const bond = bondStr ? parseInt(bondStr, 10) : void 0;
|
|
194
|
+
return {
|
|
195
|
+
core: { address, identities, issued_at },
|
|
196
|
+
expires,
|
|
197
|
+
network,
|
|
198
|
+
extensions,
|
|
199
|
+
bond: bond !== void 0 && !isNaN(bond) && bond > 0 ? bond : void 0
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
|
|
74
203
|
// src/nostr.ts
|
|
75
|
-
var
|
|
204
|
+
var log2 = createLogger("ocp/nostr");
|
|
76
205
|
var ATTESTATION_EVENT_KIND = 30078;
|
|
77
206
|
var DEFAULT_RELAYS = [
|
|
78
207
|
"wss://relay.damus.io",
|
|
@@ -148,7 +277,7 @@ function getAddressFromEvent(event) {
|
|
|
148
277
|
async function publishToRelays(event, relays = DEFAULT_RELAYS) {
|
|
149
278
|
const success = [];
|
|
150
279
|
const failed = [];
|
|
151
|
-
|
|
280
|
+
log2.info({ eventId: event.id, relayCount: relays.length }, "Publishing event to relays");
|
|
152
281
|
const deadlineAt = Date.now() + FANOUT_DEADLINE_MS;
|
|
153
282
|
const publishPromises = relays.map(async (relayUrl) => {
|
|
154
283
|
let ws = null;
|
|
@@ -187,7 +316,7 @@ async function publishToRelays(event, relays = DEFAULT_RELAYS) {
|
|
|
187
316
|
cleanup();
|
|
188
317
|
resolve();
|
|
189
318
|
} else {
|
|
190
|
-
|
|
319
|
+
log2.warn(
|
|
191
320
|
{ relay: relayUrl, reason: data[3] },
|
|
192
321
|
"Relay rejected event"
|
|
193
322
|
);
|
|
@@ -197,7 +326,7 @@ async function publishToRelays(event, relays = DEFAULT_RELAYS) {
|
|
|
197
326
|
}
|
|
198
327
|
}
|
|
199
328
|
} catch (err) {
|
|
200
|
-
|
|
329
|
+
log2.error(
|
|
201
330
|
{ relay: relayUrl, error: err },
|
|
202
331
|
"Failed to parse relay response"
|
|
203
332
|
);
|
|
@@ -207,7 +336,7 @@ async function publishToRelays(event, relays = DEFAULT_RELAYS) {
|
|
|
207
336
|
}
|
|
208
337
|
};
|
|
209
338
|
wsRef.onerror = (err) => {
|
|
210
|
-
|
|
339
|
+
log2.error({ relay: relayUrl, error: err }, "WebSocket error");
|
|
211
340
|
recordFailure();
|
|
212
341
|
cleanup();
|
|
213
342
|
reject(err);
|
|
@@ -217,7 +346,7 @@ async function publishToRelays(event, relays = DEFAULT_RELAYS) {
|
|
|
217
346
|
};
|
|
218
347
|
});
|
|
219
348
|
} catch (err) {
|
|
220
|
-
|
|
349
|
+
log2.error({ relay: relayUrl, error: err }, "Failed to publish to relay");
|
|
221
350
|
recordFailure();
|
|
222
351
|
} finally {
|
|
223
352
|
if (ws && ws.readyState !== WebSocket.CLOSED) {
|
|
@@ -226,12 +355,12 @@ async function publishToRelays(event, relays = DEFAULT_RELAYS) {
|
|
|
226
355
|
}
|
|
227
356
|
});
|
|
228
357
|
await Promise.allSettled(publishPromises);
|
|
229
|
-
|
|
358
|
+
log2.info({ successCount: success.length, failedCount: failed.length }, "Publishing complete");
|
|
230
359
|
return { success, failed };
|
|
231
360
|
}
|
|
232
361
|
async function queryByAttestationId(attestationId, relays = DEFAULT_RELAYS) {
|
|
233
362
|
const events = [];
|
|
234
|
-
|
|
363
|
+
log2.info({ attestationId, relayCount: relays.length }, "Querying relays for attestation");
|
|
235
364
|
const deadlineAt = Date.now() + FANOUT_DEADLINE_MS;
|
|
236
365
|
const queryPromises = relays.map(async (relayUrl) => {
|
|
237
366
|
let ws = null;
|
|
@@ -271,11 +400,11 @@ async function queryByAttestationId(attestationId, relays = DEFAULT_RELAYS) {
|
|
|
271
400
|
resolve();
|
|
272
401
|
}
|
|
273
402
|
} catch (err) {
|
|
274
|
-
|
|
403
|
+
log2.error({ relay: relayUrl, error: err }, "Failed to parse event");
|
|
275
404
|
}
|
|
276
405
|
};
|
|
277
406
|
wsRef.onerror = (err) => {
|
|
278
|
-
|
|
407
|
+
log2.error({ relay: relayUrl, error: err }, "WebSocket error during query");
|
|
279
408
|
cleanup();
|
|
280
409
|
reject(err);
|
|
281
410
|
};
|
|
@@ -284,7 +413,7 @@ async function queryByAttestationId(attestationId, relays = DEFAULT_RELAYS) {
|
|
|
284
413
|
};
|
|
285
414
|
});
|
|
286
415
|
} catch (err) {
|
|
287
|
-
|
|
416
|
+
log2.error({ relay: relayUrl, error: err }, "Failed to query relay");
|
|
288
417
|
} finally {
|
|
289
418
|
if (ws && ws.readyState !== WebSocket.CLOSED) {
|
|
290
419
|
ws.close();
|
|
@@ -292,12 +421,12 @@ async function queryByAttestationId(attestationId, relays = DEFAULT_RELAYS) {
|
|
|
292
421
|
}
|
|
293
422
|
});
|
|
294
423
|
await Promise.allSettled(queryPromises);
|
|
295
|
-
|
|
424
|
+
log2.info({ eventCount: events.length }, "Query complete");
|
|
296
425
|
return events;
|
|
297
426
|
}
|
|
298
427
|
async function queryByAddress(address, relays = DEFAULT_RELAYS) {
|
|
299
428
|
const events = [];
|
|
300
|
-
|
|
429
|
+
log2.info({ address, relayCount: relays.length }, "Querying relays for address");
|
|
301
430
|
const deadlineAt = Date.now() + FANOUT_DEADLINE_MS;
|
|
302
431
|
const queryPromises = relays.map(async (relayUrl) => {
|
|
303
432
|
try {
|
|
@@ -339,28 +468,28 @@ async function queryByAddress(address, relays = DEFAULT_RELAYS) {
|
|
|
339
468
|
resolve();
|
|
340
469
|
}
|
|
341
470
|
} catch (err) {
|
|
342
|
-
|
|
471
|
+
log2.error({ relay: relayUrl, error: err }, "Failed to parse event");
|
|
343
472
|
}
|
|
344
473
|
};
|
|
345
474
|
ws.onerror = (err) => {
|
|
346
475
|
clearTimeout(timeout);
|
|
347
|
-
|
|
476
|
+
log2.error({ relay: relayUrl, error: err }, "WebSocket error during query");
|
|
348
477
|
reject(err);
|
|
349
478
|
};
|
|
350
479
|
});
|
|
351
480
|
} catch (err) {
|
|
352
|
-
|
|
481
|
+
log2.error({ relay: relayUrl, error: err }, "Failed to query relay");
|
|
353
482
|
}
|
|
354
483
|
});
|
|
355
484
|
await Promise.allSettled(queryPromises);
|
|
356
|
-
|
|
485
|
+
log2.info({ eventCount: events.length }, "Query complete");
|
|
357
486
|
return events;
|
|
358
487
|
}
|
|
359
488
|
async function queryByIdentity(protocol, identifier, relays = DEFAULT_RELAYS) {
|
|
360
489
|
const events = [];
|
|
361
490
|
const identityTag = `${protocol}:${identifier}`;
|
|
362
491
|
const identityTags = protocol === "nostr" ? nostrIdentifierForms(identifier).map((f) => `nostr:${f}`) : [identityTag];
|
|
363
|
-
|
|
492
|
+
log2.info({ protocol, identifier, relayCount: relays.length }, "Querying relays for identity");
|
|
364
493
|
const deadlineAt = Date.now() + FANOUT_DEADLINE_MS;
|
|
365
494
|
const queryPromises = relays.map(async (relayUrl) => {
|
|
366
495
|
try {
|
|
@@ -395,26 +524,26 @@ async function queryByIdentity(protocol, identifier, relays = DEFAULT_RELAYS) {
|
|
|
395
524
|
resolve();
|
|
396
525
|
}
|
|
397
526
|
} catch (err) {
|
|
398
|
-
|
|
527
|
+
log2.error({ relay: relayUrl, error: err }, "Failed to parse event");
|
|
399
528
|
}
|
|
400
529
|
};
|
|
401
530
|
ws.onerror = (err) => {
|
|
402
531
|
clearTimeout(timeout);
|
|
403
|
-
|
|
532
|
+
log2.error({ relay: relayUrl, error: err }, "WebSocket error during query");
|
|
404
533
|
reject(err);
|
|
405
534
|
};
|
|
406
535
|
});
|
|
407
536
|
} catch (err) {
|
|
408
|
-
|
|
537
|
+
log2.error({ relay: relayUrl, error: err }, "Failed to query relay");
|
|
409
538
|
}
|
|
410
539
|
});
|
|
411
540
|
await Promise.allSettled(queryPromises);
|
|
412
|
-
|
|
541
|
+
log2.info({ eventCount: events.length }, "Query complete");
|
|
413
542
|
return events;
|
|
414
543
|
}
|
|
415
544
|
async function queryRecent(relays = DEFAULT_RELAYS, limit = 200) {
|
|
416
545
|
const events = [];
|
|
417
|
-
|
|
546
|
+
log2.info({ relayCount: relays.length, limit }, "Querying relays for recent attestations");
|
|
418
547
|
const deadlineAt = Date.now() + FANOUT_DEADLINE_MS;
|
|
419
548
|
const queryPromises = relays.map(async (relayUrl) => {
|
|
420
549
|
try {
|
|
@@ -450,30 +579,22 @@ async function queryRecent(relays = DEFAULT_RELAYS, limit = 200) {
|
|
|
450
579
|
resolve();
|
|
451
580
|
}
|
|
452
581
|
} catch (err) {
|
|
453
|
-
|
|
582
|
+
log2.error({ relay: relayUrl, error: err }, "Failed to parse event");
|
|
454
583
|
}
|
|
455
584
|
};
|
|
456
585
|
ws.onerror = (err) => {
|
|
457
586
|
clearTimeout(timeout);
|
|
458
|
-
|
|
587
|
+
log2.error({ relay: relayUrl, error: err }, "WebSocket error during query");
|
|
459
588
|
reject(err);
|
|
460
589
|
};
|
|
461
590
|
});
|
|
462
591
|
} catch (err) {
|
|
463
|
-
|
|
592
|
+
log2.error({ relay: relayUrl, error: err }, "Failed to query relay");
|
|
464
593
|
}
|
|
465
594
|
});
|
|
466
595
|
await Promise.allSettled(queryPromises);
|
|
467
|
-
const
|
|
468
|
-
|
|
469
|
-
for (const ev of events) {
|
|
470
|
-
const envelope = parseAttestationFromEvent(ev);
|
|
471
|
-
if (!envelope || seen.has(envelope.attestation_id)) continue;
|
|
472
|
-
if (!await verifyAttestationEnvelope(envelope)) continue;
|
|
473
|
-
seen.add(envelope.attestation_id);
|
|
474
|
-
envelopes.push(envelope);
|
|
475
|
-
}
|
|
476
|
-
log.info({ eventCount: events.length, unique: envelopes.length }, "Recent query complete");
|
|
596
|
+
const envelopes = await collectSignedEnvelopes(events);
|
|
597
|
+
log2.info({ eventCount: events.length, unique: envelopes.length }, "Recent query complete");
|
|
477
598
|
return envelopes;
|
|
478
599
|
}
|
|
479
600
|
async function verifyAttestationEnvelope(envelope) {
|
|
@@ -485,20 +606,72 @@ async function verifyAttestationEnvelope(envelope) {
|
|
|
485
606
|
const computedId = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
486
607
|
return computedId === envelope.attestation_id;
|
|
487
608
|
} catch (err) {
|
|
488
|
-
|
|
609
|
+
log2.error({ error: err }, "Failed to verify attestation envelope");
|
|
489
610
|
return false;
|
|
490
611
|
}
|
|
491
612
|
}
|
|
613
|
+
function base64Url(text) {
|
|
614
|
+
const base64 = btoa(String.fromCharCode(...new TextEncoder().encode(text)));
|
|
615
|
+
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
616
|
+
}
|
|
617
|
+
function signedEnvelope(envelope) {
|
|
618
|
+
let parsed;
|
|
619
|
+
try {
|
|
620
|
+
parsed = parseCanonicalMessage(envelope.message);
|
|
621
|
+
} catch {
|
|
622
|
+
return null;
|
|
623
|
+
}
|
|
624
|
+
if (!parsed.core.address || rfc3339Ms(parsed.core.issued_at) === null) return null;
|
|
625
|
+
const { expires_at: _copy, ...rest } = envelope;
|
|
626
|
+
return {
|
|
627
|
+
...rest,
|
|
628
|
+
address: parsed.core.address,
|
|
629
|
+
identities: parsed.core.identities,
|
|
630
|
+
issued_at: parsed.core.issued_at,
|
|
631
|
+
...parsed.expires !== void 0 ? { expires_at: parsed.expires } : {},
|
|
632
|
+
message_b64url: base64Url(envelope.message)
|
|
633
|
+
};
|
|
634
|
+
}
|
|
635
|
+
async function collectSignedEnvelopes(events, accept = () => true) {
|
|
636
|
+
const copies = /* @__PURE__ */ new Map();
|
|
637
|
+
for (const event of events) {
|
|
638
|
+
const raw = parseAttestationFromEvent(event);
|
|
639
|
+
if (!raw || !await verifyAttestationEnvelope(raw)) continue;
|
|
640
|
+
const envelope = signedEnvelope(raw);
|
|
641
|
+
if (!envelope || !accept(event, envelope)) continue;
|
|
642
|
+
const same = copies.get(envelope.attestation_id) ?? [];
|
|
643
|
+
if (!same.some((e) => e.signature === envelope.signature && e.scheme === envelope.scheme)) {
|
|
644
|
+
same.push(envelope);
|
|
645
|
+
}
|
|
646
|
+
copies.set(envelope.attestation_id, same);
|
|
647
|
+
}
|
|
648
|
+
const kept = [];
|
|
649
|
+
for (const same of copies.values()) {
|
|
650
|
+
if (same.length === 1) {
|
|
651
|
+
kept.push(same[0]);
|
|
652
|
+
continue;
|
|
653
|
+
}
|
|
654
|
+
let valid;
|
|
655
|
+
for (const e of same) {
|
|
656
|
+
if (await signatureIsValid({ addr: e.address, msg: e.message, sig: e.signature, scheme: e.scheme })) {
|
|
657
|
+
valid = e;
|
|
658
|
+
break;
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
kept.push(valid ?? same[0]);
|
|
662
|
+
}
|
|
663
|
+
return kept;
|
|
664
|
+
}
|
|
492
665
|
function parseAttestationFromEvent(event) {
|
|
493
666
|
try {
|
|
494
667
|
const envelope = JSON.parse(event.content);
|
|
495
668
|
return envelope;
|
|
496
669
|
} catch (err) {
|
|
497
|
-
|
|
670
|
+
log2.error({ eventId: event.id, error: err }, "Failed to parse attestation from event");
|
|
498
671
|
return null;
|
|
499
672
|
}
|
|
500
673
|
}
|
|
501
674
|
|
|
502
|
-
export { ATTESTATION_EVENT_KIND, DEFAULT_RELAYS, FANOUT_DEADLINE_MS, createAttestationEvent, getAddressFromEvent, getAttestationIdFromEvent, parseAttestationFromEvent, parseIdentitiesFromEvent, publishToRelays, queryByAddress, queryByAttestationId, queryByIdentity, queryRecent, verifyAttestationEnvelope };
|
|
675
|
+
export { ATTESTATION_EVENT_KIND, DEFAULT_RELAYS, FANOUT_DEADLINE_MS, collectSignedEnvelopes, createAttestationEvent, getAddressFromEvent, getAttestationIdFromEvent, parseAttestationFromEvent, parseIdentitiesFromEvent, publishToRelays, queryByAddress, queryByAttestationId, queryByIdentity, queryRecent, signedEnvelope, verifyAttestationEnvelope };
|
|
503
676
|
//# sourceMappingURL=nostr.mjs.map
|
|
504
677
|
//# sourceMappingURL=nostr.mjs.map
|