@orangecheck/sdk 0.1.2 → 0.1.4

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/index.js CHANGED
@@ -3,8 +3,8 @@
3
3
  var buffer = require('buffer');
4
4
  var bip322Js = require('bip322-js');
5
5
  var bitcoinMessage = require('bitcoinjs-message');
6
- var secp256k1 = require('@noble/curves/secp256k1');
7
- var sha2 = require('@noble/hashes/sha2');
6
+ var secp256k1_js = require('@noble/curves/secp256k1.js');
7
+ var sha2_js = require('@noble/hashes/sha2.js');
8
8
  var base = require('@scure/base');
9
9
 
10
10
  function _interopNamespace(e) {
@@ -89,9 +89,12 @@ function parseIdentities(identitiesStr) {
89
89
  }
90
90
  return bindings;
91
91
  }
92
- function buildCanonicalMessage({ address, identities }, extensions = {}) {
93
- const nonce = randomNonce16BHexLower();
94
- const issuedAt = (/* @__PURE__ */ new Date()).toISOString();
92
+ function buildCanonicalMessage({ address, identities }, extensions = {}, options = {}) {
93
+ const nonce = options.nonce ?? randomNonce16BHexLower();
94
+ if (!/^[0-9a-f]{32}$/.test(nonce)) {
95
+ throw new Error(`invalid nonce: must be 32 lowercase hex chars`);
96
+ }
97
+ const issuedAt = options.issuedAt ?? (/* @__PURE__ */ new Date()).toISOString();
95
98
  const identitiesStr = formatIdentities(identities);
96
99
  const core = [
97
100
  "orangecheck",
@@ -255,16 +258,15 @@ async function publishToRelays(event, relays = DEFAULT_RELAYS) {
255
258
  ws = new WebSocket(relayUrl);
256
259
  const wsRef = ws;
257
260
  await new Promise((resolve, reject) => {
258
- const timeout = setTimeout(() => {
261
+ const deadline = setTimeout(() => {
259
262
  wsRef.close();
260
- reject(new Error("Connection timeout"));
261
- }, 5e3);
263
+ reject(new Error("Relay publish timeout"));
264
+ }, 1e4);
262
265
  const cleanup = () => {
263
- clearTimeout(timeout);
266
+ clearTimeout(deadline);
264
267
  wsRef.close();
265
268
  };
266
269
  wsRef.onopen = () => {
267
- clearTimeout(timeout);
268
270
  wsRef.send(JSON.stringify(["EVENT", event]));
269
271
  };
270
272
  wsRef.onmessage = (msg) => {
@@ -302,7 +304,7 @@ async function publishToRelays(event, relays = DEFAULT_RELAYS) {
302
304
  reject(err);
303
305
  };
304
306
  wsRef.onclose = () => {
305
- clearTimeout(timeout);
307
+ clearTimeout(deadline);
306
308
  };
307
309
  });
308
310
  } catch (err) {
@@ -680,6 +682,24 @@ async function getAttestationsForIdentity(protocol, identifier, relays = DEFAULT
680
682
  log3.info({ protocol, identifier }, "Getting all attestations for identity");
681
683
  return discoverAttestations({ identity: { protocol, identifier }, relays });
682
684
  }
685
+ function formatIdentitiesForDisplay(identities) {
686
+ return identities.map((id) => `${id.protocol}:${id.identifier}`).join(", ");
687
+ }
688
+ function getVerificationUrl(attestationId, baseUrl = "https://ochk.io") {
689
+ return `${baseUrl}/attest/${attestationId}`;
690
+ }
691
+ function extractAttestationIdFromUrl(url) {
692
+ try {
693
+ const u = new URL(url);
694
+ const m = u.pathname.match(/^\/attest\/([0-9a-f]{64})\/?$/i);
695
+ if (m) return m[1].toLowerCase();
696
+ const q = u.searchParams.get("id");
697
+ if (q && /^[0-9a-f]{64}$/i.test(q)) return q.toLowerCase();
698
+ return null;
699
+ } catch {
700
+ return null;
701
+ }
702
+ }
683
703
 
684
704
  // src/scoring.ts
685
705
  function scoreV0(sats, days) {
@@ -703,12 +723,12 @@ function computeScore(sats, days, config) {
703
723
  return null;
704
724
  }
705
725
  }
726
+ function computeAllScores(sats, days) {
727
+ return { v0: scoreV0(sats, days), tier: scoreTier(sats, days) };
728
+ }
706
729
 
707
730
  // src/verify.ts
708
731
  var log4 = createLogger("ocp/verify");
709
- function scoreV02(sats, days) {
710
- return computeScore(sats, days, { algorithm: "v0" });
711
- }
712
732
  function looksLikeHex(s) {
713
733
  return /^[0-9a-fA-F]+$/.test(s) && s.length % 2 === 0;
714
734
  }
@@ -972,7 +992,7 @@ async function verify2(input, opts = {}) {
972
992
  const metrics = {
973
993
  sats_bonded,
974
994
  days_unspent,
975
- score: scoreV02(sats_bonded, days_unspent)
995
+ score: computeScore(sats_bonded, days_unspent, { algorithm: "v0" })
976
996
  // ≈ 55.26
977
997
  };
978
998
  codes.push("sig_ok_bip322");
@@ -1068,7 +1088,7 @@ async function verify2(input, opts = {}) {
1068
1088
  const metrics = {
1069
1089
  sats_bonded,
1070
1090
  days_unspent,
1071
- score: scoreV02(sats_bonded, days_unspent)
1091
+ score: computeScore(sats_bonded, days_unspent, { algorithm: "v0" })
1072
1092
  };
1073
1093
  return {
1074
1094
  ok: true,
@@ -1206,16 +1226,20 @@ function parseChallenge(message) {
1206
1226
  throw new Error("not an orangecheck-auth challenge");
1207
1227
  }
1208
1228
  const out = { extensions: [] };
1209
- const coreKeys = /* @__PURE__ */ new Set(["address", "nonce", "issued_at", "expires_at", "ack"]);
1210
- let seenCore = 0;
1229
+ const coreKeys = ["address", "nonce", "issued_at", "expires_at", "ack"];
1230
+ const coreKeySet = new Set(coreKeys);
1231
+ const seenCore = /* @__PURE__ */ new Set();
1211
1232
  for (let i = 1; i < lines.length; i++) {
1212
1233
  const line = lines[i] ?? "";
1213
1234
  const sep = line.indexOf(": ");
1214
1235
  if (sep === -1) continue;
1215
1236
  const key = line.slice(0, sep);
1216
1237
  const val = line.slice(sep + 2);
1217
- if (coreKeys.has(key)) {
1218
- seenCore++;
1238
+ if (coreKeySet.has(key)) {
1239
+ if (seenCore.has(key)) {
1240
+ throw new Error(`duplicate core key in challenge: ${key}`);
1241
+ }
1242
+ seenCore.add(key);
1219
1243
  if (key === "address") out.address = val;
1220
1244
  else if (key === "nonce") out.nonce = val;
1221
1245
  else if (key === "issued_at") out.issuedAt = new Date(val);
@@ -1227,8 +1251,8 @@ function parseChallenge(message) {
1227
1251
  if (key === "purpose") out.purpose = val;
1228
1252
  }
1229
1253
  }
1230
- if (seenCore !== 5) {
1231
- throw new Error(`challenge missing core lines (${seenCore}/5)`);
1254
+ if (seenCore.size !== coreKeys.length) {
1255
+ throw new Error(`challenge missing core lines (${seenCore.size}/${coreKeys.length})`);
1232
1256
  }
1233
1257
  return out;
1234
1258
  }
@@ -1720,7 +1744,7 @@ async function verifyNostrEventSignature(event) {
1720
1744
  event.tags ?? [],
1721
1745
  event.content ?? ""
1722
1746
  ]);
1723
- const computedId = toHex(sha2.sha256(new TextEncoder().encode(preimage)));
1747
+ const computedId = toHex(sha2_js.sha256(new TextEncoder().encode(preimage)));
1724
1748
  if (computedId !== event.id.toLowerCase()) {
1725
1749
  log7.warn(
1726
1750
  { eventId: event.id, computedId },
@@ -1728,7 +1752,7 @@ async function verifyNostrEventSignature(event) {
1728
1752
  );
1729
1753
  return false;
1730
1754
  }
1731
- return secp256k1.schnorr.verify(fromHex(event.sig), fromHex(event.id), fromHex(event.pubkey));
1755
+ return secp256k1_js.schnorr.verify(fromHex(event.sig), fromHex(event.id), fromHex(event.pubkey));
1732
1756
  } catch (err) {
1733
1757
  log7.warn({ err }, "schnorr verify threw");
1734
1758
  return false;
@@ -2092,12 +2116,15 @@ exports.DEFAULT_RELAYS = DEFAULT_RELAYS;
2092
2116
  exports.STATUS_META = STATUS_META;
2093
2117
  exports.buildCanonicalMessage = buildCanonicalMessage;
2094
2118
  exports.check = check;
2119
+ exports.computeAllScores = computeAllScores;
2095
2120
  exports.computeScore = computeScore;
2096
2121
  exports.createAttestation = createAttestation;
2097
2122
  exports.createAttestationEnvelope = createAttestationEnvelope;
2098
2123
  exports.createAttestationEvent = createAttestationEvent;
2099
2124
  exports.discoverAttestations = discoverAttestations;
2125
+ exports.extractAttestationIdFromUrl = extractAttestationIdFromUrl;
2100
2126
  exports.formatIdentities = formatIdentities;
2127
+ exports.formatIdentitiesForDisplay = formatIdentitiesForDisplay;
2101
2128
  exports.generateAttestationId = generateAttestationId;
2102
2129
  exports.generateGistTemplate = generateGistTemplate;
2103
2130
  exports.generateTweetText = generateTweetText;
@@ -2116,6 +2143,7 @@ exports.getTwitterComposeUrl = getTwitterComposeUrl;
2116
2143
  exports.getTwitterVerificationInstructions = getTwitterVerificationInstructions;
2117
2144
  exports.getVerificationInstructions = getVerificationInstructions;
2118
2145
  exports.getVerificationSummary = getVerificationSummary;
2146
+ exports.getVerificationUrl = getVerificationUrl;
2119
2147
  exports.getWellKnownUrl = getWellKnownUrl;
2120
2148
  exports.isDnsIdentityVerified = isDnsIdentityVerified;
2121
2149
  exports.isGitHubIdentityVerified = isGitHubIdentityVerified;