@orangecheck/sdk 1.17.0 → 1.18.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/dist/index.mjs CHANGED
@@ -68,6 +68,11 @@ function parseIdentities(identitiesStr) {
68
68
  }
69
69
  return bindings;
70
70
  }
71
+ function readBondExtension(value) {
72
+ if (!/^[0-9]+$/.test(value)) return null;
73
+ const n = Number(value);
74
+ return Number.isSafeInteger(n) ? n : null;
75
+ }
71
76
  function buildCanonicalMessage({ address, identities }, extensions = {}, options = {}) {
72
77
  const nonce = options.nonce ?? randomNonce16BHexLower();
73
78
  if (!/^[0-9a-f]{32}$/.test(nonce)) {
@@ -90,6 +95,9 @@ function buildCanonicalMessage({ address, identities }, extensions = {}, options
90
95
  continue;
91
96
  }
92
97
  const key = k.toLowerCase();
98
+ if (key === "bond" && readBondExtension(String(v)) === null) {
99
+ throw new Error(`invalid bond: ${String(v)} is not a whole number of sats up to 2^53 - 1`);
100
+ }
93
101
  normExt[key] = String(v);
94
102
  }
95
103
  const extLines = Object.keys(normExt).sort().map((k) => `${k}: ${normExt[k]}`);
@@ -102,10 +110,15 @@ async function generateAttestationId(message) {
102
110
  const hashBuffer = await crypto.subtle.digest("SHA-256", data);
103
111
  return toLowerHex(new Uint8Array(hashBuffer));
104
112
  }
113
+ function readMessageValue(message, key) {
114
+ const needle = key + ":";
115
+ const hit = message.split("\n").map((l) => l.trim()).find((l) => l.toLowerCase().startsWith(needle));
116
+ if (!hit) return void 0;
117
+ return hit.slice(hit.indexOf(":") + 1).trim();
118
+ }
105
119
  async function createAttestationEnvelope(message, signature, scheme, address, identities, extensions = {}) {
106
120
  const attestation_id = await generateAttestationId(message);
107
- const issuedAtMatch = message.match(/issued_at: ([^\n]+)/);
108
- const issued_at = issuedAtMatch?.[1] ?? (/* @__PURE__ */ new Date()).toISOString();
121
+ const issued_at = readMessageValue(message, "issued_at") ?? (/* @__PURE__ */ new Date()).toISOString();
109
122
  const expires_at = extensions.expires;
110
123
  const relay_hints = extensions.relay_hints?.split(",").map((r) => r.trim());
111
124
  const publish_targets = extensions.publish?.split(",").map((t) => t.trim());
@@ -317,13 +330,7 @@ async function signatureIsValid(input) {
317
330
  }
318
331
  function parseCanonicalMessage(msg) {
319
332
  const lines = msg.split("\n").map((l) => l.trim());
320
- const getVal = (prefix) => {
321
- const needle = prefix + ":";
322
- const hit = lines.find((l) => l.toLowerCase().startsWith(needle));
323
- if (!hit) return void 0;
324
- const idx = hit.indexOf(":");
325
- return hit.slice(idx + 1).trim();
326
- };
333
+ const getVal = (key) => readMessageValue(msg, key);
327
334
  const address = getVal("address") || "";
328
335
  const identitiesStr = getVal("identities") || "";
329
336
  const issued_at = getVal("issued_at") || "";
@@ -357,14 +364,15 @@ function parseCanonicalMessage(msg) {
357
364
  }
358
365
  const network = extensions["network"] || "mainnet";
359
366
  const bondStr = extensions["bond"];
360
- const bond = bondStr ? parseInt(bondStr, 10) : void 0;
367
+ const bond = bondStr ? readBondExtension(bondStr) : void 0;
361
368
  return {
362
369
  core: { address, identities, issued_at },
363
370
  expires,
364
371
  repeated,
365
372
  network,
366
373
  extensions,
367
- bond: bond !== void 0 && !isNaN(bond) && bond > 0 ? bond : void 0
374
+ bond: bond !== void 0 && bond !== null && bond > 0 ? bond : void 0,
375
+ bondMalformed: bond === null
368
376
  };
369
377
  }
370
378
  async function getAddressUtxos(address, network, opts) {
@@ -533,6 +541,16 @@ async function verify(input, opts = {}) {
533
541
  identities: parsed.core.identities
534
542
  };
535
543
  }
544
+ if (parsed.bondMalformed) {
545
+ codes.push("bond_malformed");
546
+ return {
547
+ ok: false,
548
+ codes,
549
+ network,
550
+ attestation_id,
551
+ identities: parsed.core.identities
552
+ };
553
+ }
536
554
  try {
537
555
  const utxos = await getAddressUtxos(input.addr, network, {
538
556
  esploraMainnetBase: opts.esploraMainnetBase,
@@ -2317,6 +2335,11 @@ var STATUS_META = {
2317
2335
  detail: "The confirmed balance is less than the declared bond amount. The bond extension requires the address to hold at least the specified amount in confirmed UTXOs.",
2318
2336
  severity: "error"
2319
2337
  },
2338
+ bond_malformed: {
2339
+ label: "Bond amount not readable",
2340
+ detail: "The signed bond line is not a whole number of sats written in plain digits, so the attestation does not say how much it bonds.",
2341
+ severity: "error"
2342
+ },
2320
2343
  aud_mismatch: {
2321
2344
  label: "Audience mismatch",
2322
2345
  detail: "The message was signed for a different audience than expected. This may be intentional or indicate the signature is being used in the wrong context.",
@@ -2359,6 +2382,6 @@ var STATUS_META = {
2359
2382
  }
2360
2383
  };
2361
2384
 
2362
- export { BOND_DAYS_FLOORS, BOND_MAX_WINDOW_SECONDS, BOND_MIN_CONFIRMATIONS, BOND_SATS_FLOORS, DEFAULT_RELAYS, FANOUT_DEADLINE_MS, STATUS_META, bondFloors, bondId, bondNullifier, buildBondMessage, buildCanonicalMessage, check, checkBondCoin, computeAllScores, computeScore, createAttestation, createAttestationEnvelope, createAttestationEvent, discoverAttestations, esploraSource, extractAttestationIdFromUrl, formatIdentities, formatIdentitiesForDisplay, generateAttestationId, generateGistTemplate, generateTweetText, generateWellKnownContent, getAttestationsForAddress, getAttestationsForIdentity, getDnsVerificationInstructions, getGistCreationUrl, getGitHubVerificationInstructions, getManualVerificationInstructions, getNip07Info, getNostrPublicKey, getNostrVerificationInstructions, getTweetUrl, getTwitterComposeUrl, getTwitterVerificationInstructions, getVerificationInstructions, getVerificationSummary, getVerificationUrl, getWellKnownUrl, isDnsIdentityVerified, isGitHubIdentityVerified, isNip07Available, isNostrIdentityVerified, isValidDomain, isValidTweetUrl, issueBondMessage, issueChallenge, nostrIdentifierForms, nostrPubkeyToHex, parseAttestationFromEvent, parseBondMessage, parseIdentities, publishAttestation, publishToRelays, queryByAddress, queryByAttestationId, queryByIdentity, queryRecent, requiresManualVerification, signNostrEvent, signatureIsValid, signedEnvelope, supportsAutomaticVerification, verify, verifyAllIdentities, verifyAttestationById, verifyBond, verifyBondSignature, verifyChallenge, verifyDnsIdentity, verifyGitHubIdentity, verifyIdentity, verifyNostrIdentity, verifyTwitterIdentity };
2385
+ export { BOND_DAYS_FLOORS, BOND_MAX_WINDOW_SECONDS, BOND_MIN_CONFIRMATIONS, BOND_SATS_FLOORS, DEFAULT_RELAYS, FANOUT_DEADLINE_MS, STATUS_META, bondFloors, bondId, bondNullifier, buildBondMessage, buildCanonicalMessage, check, checkBondCoin, computeAllScores, computeScore, createAttestation, createAttestationEnvelope, createAttestationEvent, discoverAttestations, esploraSource, extractAttestationIdFromUrl, formatIdentities, formatIdentitiesForDisplay, generateAttestationId, generateGistTemplate, generateTweetText, generateWellKnownContent, getAttestationsForAddress, getAttestationsForIdentity, getDnsVerificationInstructions, getGistCreationUrl, getGitHubVerificationInstructions, getManualVerificationInstructions, getNip07Info, getNostrPublicKey, getNostrVerificationInstructions, getTweetUrl, getTwitterComposeUrl, getTwitterVerificationInstructions, getVerificationInstructions, getVerificationSummary, getVerificationUrl, getWellKnownUrl, isDnsIdentityVerified, isGitHubIdentityVerified, isNip07Available, isNostrIdentityVerified, isValidDomain, isValidTweetUrl, issueBondMessage, issueChallenge, nostrIdentifierForms, nostrPubkeyToHex, parseAttestationFromEvent, parseBondMessage, parseIdentities, publishAttestation, publishToRelays, queryByAddress, queryByAttestationId, queryByIdentity, queryRecent, readBondExtension, requiresManualVerification, signNostrEvent, signatureIsValid, signedEnvelope, supportsAutomaticVerification, verify, verifyAllIdentities, verifyAttestationById, verifyBond, verifyBondSignature, verifyChallenge, verifyDnsIdentity, verifyGitHubIdentity, verifyIdentity, verifyNostrIdentity, verifyTwitterIdentity };
2363
2386
  //# sourceMappingURL=index.mjs.map
2364
2387
  //# sourceMappingURL=index.mjs.map