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