@orangecheck/sdk 1.16.1 → 1.17.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 +1 -0
- package/dist/attestation.js +86 -170
- package/dist/attestation.js.map +1 -1
- package/dist/attestation.mjs +86 -170
- package/dist/attestation.mjs.map +1 -1
- package/dist/identity.js.map +1 -1
- package/dist/identity.mjs.map +1 -1
- package/dist/index.js +131 -172
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +131 -172
- package/dist/index.mjs.map +1 -1
- package/dist/nostr.js +86 -170
- package/dist/nostr.js.map +1 -1
- package/dist/nostr.mjs +86 -170
- package/dist/nostr.mjs.map +1 -1
- package/dist/verify.d.mts +1 -0
- package/dist/verify.d.ts +1 -0
- package/dist/verify.js +35 -0
- package/dist/verify.js.map +1 -1
- package/dist/verify.mjs +35 -0
- package/dist/verify.mjs.map +1 -1
- package/package.json +1 -1
package/dist/attestation.mjs
CHANGED
|
@@ -215,11 +215,15 @@ function parseCanonicalMessage(msg) {
|
|
|
215
215
|
"ack"
|
|
216
216
|
]);
|
|
217
217
|
const extensions = {};
|
|
218
|
+
const keys = /* @__PURE__ */ new Set();
|
|
219
|
+
const repeated = [];
|
|
218
220
|
for (const line of lines) {
|
|
219
221
|
const idx = line.indexOf(":");
|
|
220
222
|
if (idx === -1) continue;
|
|
221
223
|
const key = line.slice(0, idx).trim().toLowerCase();
|
|
222
224
|
const val = line.slice(idx + 1).trim();
|
|
225
|
+
if (keys.has(key)) repeated.push(key);
|
|
226
|
+
keys.add(key);
|
|
223
227
|
if (!coreKeys.has(key) && val) extensions[key] = val;
|
|
224
228
|
}
|
|
225
229
|
const network = extensions["network"] || "mainnet";
|
|
@@ -228,6 +232,7 @@ function parseCanonicalMessage(msg) {
|
|
|
228
232
|
return {
|
|
229
233
|
core: { address, identities, issued_at },
|
|
230
234
|
expires,
|
|
235
|
+
repeated,
|
|
231
236
|
network,
|
|
232
237
|
extensions,
|
|
233
238
|
bond: bond !== void 0 && !isNaN(bond) && bond > 0 ? bond : void 0
|
|
@@ -369,188 +374,98 @@ async function publishToRelays(event, relays = DEFAULT_RELAYS) {
|
|
|
369
374
|
log2.info({ successCount: success.length, failedCount: failed.length }, "Publishing complete");
|
|
370
375
|
return { success, failed };
|
|
371
376
|
}
|
|
372
|
-
|
|
377
|
+
var PAGE_LIMIT = 500;
|
|
378
|
+
var MAX_PAGES = 4;
|
|
379
|
+
async function querySubject(filter, relays, label) {
|
|
373
380
|
const events = [];
|
|
374
|
-
log2.info({ attestationId, relayCount: relays.length }, "Querying relays for attestation");
|
|
375
381
|
const deadlineAt = Date.now() + FANOUT_DEADLINE_MS;
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
382
|
+
await Promise.allSettled(
|
|
383
|
+
relays.map(async (relayUrl) => {
|
|
384
|
+
let ws = null;
|
|
385
|
+
try {
|
|
386
|
+
ws = new WebSocket(relayUrl);
|
|
387
|
+
const wsRef = ws;
|
|
388
|
+
await new Promise((resolve, reject) => {
|
|
389
|
+
const timeout = setTimeout(() => {
|
|
390
|
+
wsRef.close();
|
|
391
|
+
reject(new Error("Query timeout"));
|
|
392
|
+
}, budgetFor(deadlineAt));
|
|
393
|
+
const seen = /* @__PURE__ */ new Set();
|
|
394
|
+
let page = 0;
|
|
395
|
+
let inPage = 0;
|
|
396
|
+
let newInPage = 0;
|
|
397
|
+
let oldest = Infinity;
|
|
398
|
+
const ask = () => {
|
|
399
|
+
page++;
|
|
400
|
+
inPage = 0;
|
|
401
|
+
newInPage = 0;
|
|
402
|
+
const until = Number.isFinite(oldest) ? { until: oldest } : {};
|
|
403
|
+
wsRef.send(
|
|
404
|
+
JSON.stringify([
|
|
405
|
+
"REQ",
|
|
406
|
+
`ochk_${label}_${Date.now()}_${page}`,
|
|
407
|
+
{ ...filter, ...until, limit: PAGE_LIMIT }
|
|
408
|
+
])
|
|
409
|
+
);
|
|
410
|
+
};
|
|
411
|
+
wsRef.onopen = ask;
|
|
412
|
+
wsRef.onmessage = (msg) => {
|
|
413
|
+
try {
|
|
414
|
+
const data = JSON.parse(msg.data);
|
|
415
|
+
if (data[0] === "EVENT") {
|
|
416
|
+
const event = data[2];
|
|
417
|
+
const key = event.id ?? JSON.stringify(event);
|
|
418
|
+
inPage++;
|
|
419
|
+
if (!seen.has(key)) {
|
|
420
|
+
seen.add(key);
|
|
421
|
+
newInPage++;
|
|
422
|
+
events.push(event);
|
|
423
|
+
}
|
|
424
|
+
if (typeof event.created_at === "number") {
|
|
425
|
+
oldest = Math.min(oldest, event.created_at);
|
|
426
|
+
}
|
|
427
|
+
} else if (data[0] === "EOSE") {
|
|
428
|
+
wsRef.send(JSON.stringify(["CLOSE", data[1]]));
|
|
429
|
+
if (inPage >= PAGE_LIMIT && newInPage > 0 && page < MAX_PAGES) {
|
|
430
|
+
ask();
|
|
431
|
+
} else {
|
|
432
|
+
clearTimeout(timeout);
|
|
433
|
+
wsRef.close();
|
|
434
|
+
resolve();
|
|
435
|
+
}
|
|
400
436
|
}
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
};
|
|
404
|
-
wsRef.onmessage = (msg) => {
|
|
405
|
-
try {
|
|
406
|
-
const data = JSON.parse(msg.data);
|
|
407
|
-
if (data[0] === "EVENT") {
|
|
408
|
-
events.push(data[2]);
|
|
409
|
-
} else if (data[0] === "EOSE") {
|
|
410
|
-
cleanup();
|
|
411
|
-
resolve();
|
|
437
|
+
} catch (err) {
|
|
438
|
+
log2.error({ relay: relayUrl, error: err }, "Failed to parse event");
|
|
412
439
|
}
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
};
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
};
|
|
425
|
-
});
|
|
426
|
-
} catch (err) {
|
|
427
|
-
log2.error({ relay: relayUrl, error: err }, "Failed to query relay");
|
|
428
|
-
} finally {
|
|
429
|
-
if (ws && ws.readyState !== WebSocket.CLOSED) {
|
|
430
|
-
ws.close();
|
|
440
|
+
};
|
|
441
|
+
wsRef.onerror = (err) => {
|
|
442
|
+
clearTimeout(timeout);
|
|
443
|
+
log2.error({ relay: relayUrl, error: err }, "WebSocket error during query");
|
|
444
|
+
reject(err);
|
|
445
|
+
};
|
|
446
|
+
});
|
|
447
|
+
} catch (err) {
|
|
448
|
+
log2.error({ relay: relayUrl, error: err }, "Failed to query relay");
|
|
449
|
+
} finally {
|
|
450
|
+
if (ws && ws.readyState !== WebSocket.CLOSED) ws.close();
|
|
431
451
|
}
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
log2.info({ eventCount: events.length }, "Query complete");
|
|
452
|
+
})
|
|
453
|
+
);
|
|
454
|
+
log2.info({ label, eventCount: events.length }, "Query complete");
|
|
436
455
|
return events;
|
|
437
456
|
}
|
|
457
|
+
async function queryByAttestationId(attestationId, relays = DEFAULT_RELAYS) {
|
|
458
|
+
log2.info({ attestationId, relayCount: relays.length }, "Querying relays for attestation");
|
|
459
|
+
return querySubject({ kinds: [30078], "#d": [attestationId] }, relays, "id");
|
|
460
|
+
}
|
|
438
461
|
async function queryByAddress(address, relays = DEFAULT_RELAYS) {
|
|
439
|
-
const events = [];
|
|
440
462
|
log2.info({ address, relayCount: relays.length }, "Querying relays for address");
|
|
441
|
-
|
|
442
|
-
const queryPromises = relays.map(async (relayUrl) => {
|
|
443
|
-
try {
|
|
444
|
-
const ws = new WebSocket(relayUrl);
|
|
445
|
-
await new Promise((resolve, reject) => {
|
|
446
|
-
const timeout = setTimeout(() => {
|
|
447
|
-
ws.close();
|
|
448
|
-
reject(new Error("Query timeout"));
|
|
449
|
-
}, budgetFor(deadlineAt));
|
|
450
|
-
ws.onopen = () => {
|
|
451
|
-
const subscriptionId = `ochk_addr_${Date.now()}`;
|
|
452
|
-
ws.send(
|
|
453
|
-
JSON.stringify([
|
|
454
|
-
"REQ",
|
|
455
|
-
subscriptionId,
|
|
456
|
-
{
|
|
457
|
-
kinds: [30078],
|
|
458
|
-
// `#t`, NOT `#address`: NIP-12 relays index
|
|
459
|
-
// single-letter tags only, so `#address`
|
|
460
|
-
// matched nothing on any relay and this
|
|
461
|
-
// function returned empty for every real
|
|
462
|
-
// attestation. attest.ochk.io's verifier has
|
|
463
|
-
// queried `#t` since the same fix landed
|
|
464
|
-
// there; this is the back-port.
|
|
465
|
-
"#t": [address],
|
|
466
|
-
limit: 50
|
|
467
|
-
}
|
|
468
|
-
])
|
|
469
|
-
);
|
|
470
|
-
};
|
|
471
|
-
ws.onmessage = (msg) => {
|
|
472
|
-
try {
|
|
473
|
-
const data = JSON.parse(msg.data);
|
|
474
|
-
if (data[0] === "EVENT") {
|
|
475
|
-
events.push(data[2]);
|
|
476
|
-
} else if (data[0] === "EOSE") {
|
|
477
|
-
clearTimeout(timeout);
|
|
478
|
-
ws.close();
|
|
479
|
-
resolve();
|
|
480
|
-
}
|
|
481
|
-
} catch (err) {
|
|
482
|
-
log2.error({ relay: relayUrl, error: err }, "Failed to parse event");
|
|
483
|
-
}
|
|
484
|
-
};
|
|
485
|
-
ws.onerror = (err) => {
|
|
486
|
-
clearTimeout(timeout);
|
|
487
|
-
log2.error({ relay: relayUrl, error: err }, "WebSocket error during query");
|
|
488
|
-
reject(err);
|
|
489
|
-
};
|
|
490
|
-
});
|
|
491
|
-
} catch (err) {
|
|
492
|
-
log2.error({ relay: relayUrl, error: err }, "Failed to query relay");
|
|
493
|
-
}
|
|
494
|
-
});
|
|
495
|
-
await Promise.allSettled(queryPromises);
|
|
496
|
-
log2.info({ eventCount: events.length }, "Query complete");
|
|
497
|
-
return events;
|
|
463
|
+
return querySubject({ kinds: [30078], "#t": [address] }, relays, "addr");
|
|
498
464
|
}
|
|
499
465
|
async function queryByIdentity(protocol, identifier, relays = DEFAULT_RELAYS) {
|
|
500
|
-
const
|
|
501
|
-
const identityTag = `${protocol}:${identifier}`;
|
|
502
|
-
const identityTags = protocol === "nostr" ? nostrIdentifierForms(identifier).map((f) => `nostr:${f}`) : [identityTag];
|
|
466
|
+
const identityTags = protocol === "nostr" ? nostrIdentifierForms(identifier).map((f) => `nostr:${f}`) : [`${protocol}:${identifier}`];
|
|
503
467
|
log2.info({ protocol, identifier, relayCount: relays.length }, "Querying relays for identity");
|
|
504
|
-
|
|
505
|
-
const queryPromises = relays.map(async (relayUrl) => {
|
|
506
|
-
try {
|
|
507
|
-
const ws = new WebSocket(relayUrl);
|
|
508
|
-
await new Promise((resolve, reject) => {
|
|
509
|
-
const timeout = setTimeout(() => {
|
|
510
|
-
ws.close();
|
|
511
|
-
reject(new Error("Query timeout"));
|
|
512
|
-
}, budgetFor(deadlineAt));
|
|
513
|
-
ws.onopen = () => {
|
|
514
|
-
const subscriptionId = `ochk_identity_${Date.now()}`;
|
|
515
|
-
ws.send(
|
|
516
|
-
JSON.stringify([
|
|
517
|
-
"REQ",
|
|
518
|
-
subscriptionId,
|
|
519
|
-
{
|
|
520
|
-
kinds: [30078],
|
|
521
|
-
"#i": identityTags,
|
|
522
|
-
limit: 10
|
|
523
|
-
}
|
|
524
|
-
])
|
|
525
|
-
);
|
|
526
|
-
};
|
|
527
|
-
ws.onmessage = (msg) => {
|
|
528
|
-
try {
|
|
529
|
-
const data = JSON.parse(msg.data);
|
|
530
|
-
if (data[0] === "EVENT") {
|
|
531
|
-
events.push(data[2]);
|
|
532
|
-
} else if (data[0] === "EOSE") {
|
|
533
|
-
clearTimeout(timeout);
|
|
534
|
-
ws.close();
|
|
535
|
-
resolve();
|
|
536
|
-
}
|
|
537
|
-
} catch (err) {
|
|
538
|
-
log2.error({ relay: relayUrl, error: err }, "Failed to parse event");
|
|
539
|
-
}
|
|
540
|
-
};
|
|
541
|
-
ws.onerror = (err) => {
|
|
542
|
-
clearTimeout(timeout);
|
|
543
|
-
log2.error({ relay: relayUrl, error: err }, "WebSocket error during query");
|
|
544
|
-
reject(err);
|
|
545
|
-
};
|
|
546
|
-
});
|
|
547
|
-
} catch (err) {
|
|
548
|
-
log2.error({ relay: relayUrl, error: err }, "Failed to query relay");
|
|
549
|
-
}
|
|
550
|
-
});
|
|
551
|
-
await Promise.allSettled(queryPromises);
|
|
552
|
-
log2.info({ eventCount: events.length }, "Query complete");
|
|
553
|
-
return events;
|
|
468
|
+
return querySubject({ kinds: [30078], "#i": identityTags }, relays, "identity");
|
|
554
469
|
}
|
|
555
470
|
async function verifyAttestationEnvelope(envelope) {
|
|
556
471
|
try {
|
|
@@ -577,6 +492,7 @@ function signedEnvelope(envelope) {
|
|
|
577
492
|
return null;
|
|
578
493
|
}
|
|
579
494
|
if (!parsed.core.address || rfc3339Ms(parsed.core.issued_at) === null) return null;
|
|
495
|
+
if (parsed.repeated.length > 0) return null;
|
|
580
496
|
const { expires_at: _copy, ...rest } = envelope;
|
|
581
497
|
return {
|
|
582
498
|
...rest,
|