@orangecheck/sdk 1.16.1 → 1.16.2

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