@orangecheck/sdk 1.3.0 → 1.4.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/attestation.js +33 -12
- package/dist/attestation.js.map +1 -1
- package/dist/attestation.mjs +33 -12
- package/dist/attestation.mjs.map +1 -1
- package/dist/identity.js +2 -1
- package/dist/identity.js.map +1 -1
- package/dist/identity.mjs +2 -1
- package/dist/identity.mjs.map +1 -1
- package/dist/index.js +33 -12
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +33 -12
- package/dist/index.mjs.map +1 -1
- package/dist/nostr.js +33 -12
- package/dist/nostr.js.map +1 -1
- package/dist/nostr.mjs +33 -12
- package/dist/nostr.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/canonical.ts","../src/utils/logger.ts","../src/nostr.ts","../src/nostr-crypto.ts","../src/attestation.ts","../src/scoring.ts","../src/verify.ts","../src/check.ts","../src/challenge.ts","../src/utils/rate-limiter.ts","../src/identity/dns.ts","../src/identity/github.ts","../src/identity/nostr.ts","../src/identity/twitter.ts","../src/identity/index.ts","../src/messages.ts"],"names":["log","days_unspent","verify","Buffer","Verifier","bitcoinMessage2"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Canonical message builder per SPEC.md §2\n *\n * - LF line endings, exactly one trailing LF\n * - 7 fixed core lines in strict order and wording\n * - Optional extensions appended as key: value with lexicographically sorted lowercase keys\n */\n\nimport type { AttestationEnvelope, IdentityBinding, Scheme } from './types';\n\n/**\n * Input for building a canonical message\n */\nexport interface CanonicalInput {\n /** Bitcoin address */\n address: string;\n /** Optional identity bindings */\n identities?: IdentityBinding[];\n}\n\n/**\n * Extension key-value pairs for canonical message\n */\nexport type Extensions = Record<string, string | undefined>;\n\n/**\n * Convert bytes to lowercase hex string\n * @param bytes - Byte array to convert\n * @returns Lowercase hex string\n */\nfunction toLowerHex(bytes: Uint8Array): string {\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n}\n\n/**\n * Generate a random 16-byte nonce as lowercase hex\n * Uses Web Crypto API when available, falls back to Math.random()\n * @returns 32-character lowercase hex string\n */\nexport function randomNonce16BHexLower(): string {\n const arr = new Uint8Array(16);\n\n try {\n if (typeof crypto !== 'undefined' && typeof crypto.getRandomValues === 'function') {\n crypto.getRandomValues(arr);\n return toLowerHex(arr);\n }\n } catch {\n // Fall through to non-cryptographic fallback\n }\n\n // No silent Math.random fallback: a nonce is a load-bearing security\n // primitive. A deployment without `crypto.getRandomValues` MUST fix its\n // environment rather than sign with weak randomness.\n throw new Error('crypto.getRandomValues unavailable — refusing to mint a weak nonce');\n}\n\n/**\n * Reject characters that would break the line-oriented canonical grammar\n * or the comma-separated identities list. If any of these slipped through,\n * an attacker could smuggle a forged `address:` or extension line into the\n * signed payload: `identities: alice\\naddress: bc1qEVIL…` would parse as a\n * second address line. Catch it at the boundary, not at verification time.\n *\n * Also rejects a colon in the identifier so a bad actor can't turn\n * `github:alice:extra` into a different protocol binding on parse.\n */\nconst IDENTITY_PROTOCOL_RE = /^[a-z][a-z0-9_-]*$/;\nconst IDENTITY_FORBIDDEN_CHARS = /[\\r\\n,]/;\n\nfunction assertSafeIdentity({ protocol, identifier }: IdentityBinding): void {\n if (!IDENTITY_PROTOCOL_RE.test(protocol)) {\n throw new Error(\n `invalid identity protocol: ${JSON.stringify(protocol)} — must match /^[a-z][a-z0-9_-]*$/`\n );\n }\n if (!identifier || IDENTITY_FORBIDDEN_CHARS.test(identifier)) {\n throw new Error(\n `invalid identity identifier: ${JSON.stringify(identifier)} — must be non-empty and contain no newlines or commas`\n );\n }\n}\n\n/**\n * Format identities as comma-separated protocol:identifier pairs, sorted lexicographically\n * @param identities - Array of identity bindings\n * @returns Comma-separated string of protocol:identifier pairs\n */\nexport function formatIdentities(identities: IdentityBinding[] = []): string {\n if (identities.length === 0) {\n return '';\n }\n for (const id of identities) assertSafeIdentity(id);\n\n // Format as protocol:identifier and sort lexicographically\n const formatted = identities\n .map(({ protocol, identifier }) => `${protocol}:${identifier}`)\n .sort();\n\n return formatted.join(',');\n}\n\n/**\n * Parse identities from comma-separated protocol:identifier format\n * @param identitiesStr - Comma-separated identity string\n * @returns Array of identity bindings\n * @throws {Error} If identity format is invalid\n */\nexport function parseIdentities(identitiesStr: string): IdentityBinding[] {\n if (!identitiesStr || identitiesStr.trim() === '') {\n return [];\n }\n // The identities field lives on one line of the canonical message. If it\n // contains a raw LF/CR, it's either corrupt or an attempt to smuggle a\n // fake core line into the parser. Refuse instead of trying to recover.\n if (IDENTITY_FORBIDDEN_CHARS.test(identitiesStr.replace(/,/g, ''))) {\n throw new Error('identities field contains forbidden characters (newline)');\n }\n\n const bindings = identitiesStr.split(',').map((binding) => {\n const colonIndex = binding.indexOf(':');\n if (colonIndex === -1) {\n throw new Error(`Invalid identity binding format: ${binding}`);\n }\n return {\n protocol: binding.substring(0, colonIndex).trim(),\n identifier: binding.substring(colonIndex + 1).trim(),\n };\n });\n\n for (const b of bindings) {\n if (!b.protocol || !b.identifier) {\n throw new Error(`Invalid identity binding: ${b.protocol}:${b.identifier}`);\n }\n assertSafeIdentity(b);\n }\n return bindings;\n}\n\n/**\n * Optional deterministic overrides for message building. Only intended for\n * tests / conformance vectors; production callers should let the builder\n * mint a fresh nonce + timestamp per message.\n */\nexport interface BuildOptions {\n /** 32-char lowercase hex. Default: freshly-generated cryptographic nonce. */\n nonce?: string;\n /** RFC-3339 UTC. Default: `new Date().toISOString()`. */\n issuedAt?: string;\n}\n\n/**\n * Build a canonical message following OrangeCheck Protocol v0 specification\n * @param input - Canonical input with address and identities\n * @param extensions - Optional extension key-value pairs\n * @param options - Optional deterministic overrides (testing only)\n * @returns Canonical message string with LF line endings\n */\nexport function buildCanonicalMessage(\n { address, identities }: CanonicalInput,\n extensions: Extensions = {},\n options: BuildOptions = {}\n): string {\n const nonce = options.nonce ?? randomNonce16BHexLower();\n if (!/^[0-9a-f]{32}$/.test(nonce)) {\n throw new Error(`invalid nonce: must be 32 lowercase hex chars`);\n }\n const issuedAt = options.issuedAt ?? new Date().toISOString();\n\n // Format identities\n const identitiesStr = formatIdentities(identities);\n\n // Core (strict wording + order per SPEC.md §2)\n const core = [\n 'orangecheck',\n `identities: ${identitiesStr}`,\n `address: ${address}`,\n 'purpose: portable reputation attestation (non-custodial)',\n `nonce: ${nonce}`,\n `issued_at: ${issuedAt}`,\n 'ack: I attest control of this address and bind it to my identities.',\n ];\n\n // Normalize and sort extensions\n const normExt: Record<string, string> = {};\n for (const [k, v] of Object.entries(extensions)) {\n if (v == null || v === '') {\n continue;\n }\n const key = k.toLowerCase();\n normExt[key] = String(v);\n }\n\n const extLines = Object.keys(normExt)\n .sort()\n .map((k) => `${k}: ${normExt[k]!}`);\n\n const all = [...core, ...extLines];\n\n // Join with LF and ensure exactly one trailing LF\n return all.join('\\n') + '\\n';\n}\n\n/**\n * Generate attestation ID from canonical message\n *\n * attestation_id = SHA-256(canonical_message)\n *\n * @param message - Canonical message string\n * @returns Lowercase hex SHA-256 hash\n */\nexport async function generateAttestationId(message: string): Promise<string> {\n // Convert message to UTF-8 bytes\n const encoder = new TextEncoder();\n const data = encoder.encode(message);\n\n // Compute SHA-256 hash\n const hashBuffer = await crypto.subtle.digest('SHA-256', data);\n\n // Convert to lowercase hex\n return toLowerHex(new Uint8Array(hashBuffer));\n}\n\n/**\n * Create an attestation envelope for publishing\n *\n * This wraps the canonical message with metadata for Nostr publishing\n *\n * @param message - Canonical message\n * @param signature - BIP-322 or legacy signature\n * @param scheme - Signature scheme used\n * @param address - Bitcoin address\n * @param identities - Identity bindings\n * @param extensions - Optional extensions\n * @returns Attestation envelope ready for publishing\n */\nexport async function createAttestationEnvelope(\n message: string,\n signature: string,\n scheme: Scheme,\n address: string,\n identities: IdentityBinding[],\n extensions: Extensions = {}\n): Promise<AttestationEnvelope> {\n const attestation_id = await generateAttestationId(message);\n\n // Extract issued_at from message\n const issuedAtMatch = message.match(/issued_at: ([^\\n]+)/);\n const issued_at = issuedAtMatch?.[1] ?? new Date().toISOString();\n\n // Extract expires from extensions if present\n const expires_at = extensions.expires;\n\n // Extract relay hints from extensions if present\n const relay_hints = extensions.relay_hints?.split(',').map((r) => r.trim());\n\n // Extract publish targets from extensions if present\n const publish_targets = extensions.publish?.split(',').map((t) => t.trim());\n\n // Base64url encode the message\n const encoder = new TextEncoder();\n const messageBytes = encoder.encode(message);\n const base64 = btoa(String.fromCharCode(...messageBytes));\n const message_b64url = base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\n\n // Construct verification URL\n const verification_url = `https://attest.ochk.io/attest/${attestation_id}`;\n\n return {\n attestation_id,\n scheme,\n address,\n identities,\n message,\n message_b64url,\n signature,\n issued_at,\n expires_at,\n verification_url,\n publish_targets,\n relay_hints,\n };\n}\n","/**\n * Simple logger for SDK\n * Can be disabled in production builds\n */\n\n/**\n * Log level type\n */\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'none';\n\n/**\n * Logger context type\n */\nexport type LogContext = Record<string, unknown>;\n\n/**\n * Logger interface\n */\nexport interface Logger {\n debug: (contextOrMessage: string | LogContext, message?: string) => void;\n info: (contextOrMessage: string | LogContext, message?: string) => void;\n warn: (contextOrMessage: string | LogContext, message?: string) => void;\n error: (contextOrMessage: string | LogContext, message?: string) => void;\n}\n\nlet logLevel: LogLevel = 'none';\n\n/**\n * Set the global log level\n * @param level - Log level to set\n */\nexport function setLogLevel(level: LogLevel): void {\n logLevel = level;\n}\n\n/**\n * Get the current log level\n * @returns Current log level\n */\nexport function getLogLevel(): LogLevel {\n return logLevel;\n}\n\n/**\n * Create a namespaced logger\n * @param namespace - Logger namespace\n * @returns Logger instance\n */\nexport function createLogger(namespace: string): Logger {\n const shouldLog = (level: Exclude<LogLevel, 'none'>): boolean => {\n if (logLevel === 'none') return false;\n\n const levels: Exclude<LogLevel, 'none'>[] = ['debug', 'info', 'warn', 'error'];\n const currentLevelIndex = levels.indexOf(logLevel as Exclude<LogLevel, 'none'>);\n const messageLevelIndex = levels.indexOf(level);\n\n return messageLevelIndex >= currentLevelIndex;\n };\n\n const formatMessage = (msg: string): string => `[${namespace}] ${msg}`;\n\n return {\n debug: (contextOrMessage: string | LogContext, message?: string): void => {\n if (shouldLog('debug')) {\n if (typeof contextOrMessage === 'string') {\n console.debug(formatMessage(contextOrMessage));\n } else {\n console.debug(formatMessage(message ?? 'Debug'), contextOrMessage);\n }\n }\n },\n info: (contextOrMessage: string | LogContext, message?: string): void => {\n if (shouldLog('info')) {\n if (typeof contextOrMessage === 'string') {\n console.info(formatMessage(contextOrMessage));\n } else {\n console.info(formatMessage(message ?? 'Info'), contextOrMessage);\n }\n }\n },\n warn: (contextOrMessage: string | LogContext, message?: string): void => {\n if (shouldLog('warn')) {\n if (typeof contextOrMessage === 'string') {\n console.warn(formatMessage(contextOrMessage));\n } else {\n console.warn(formatMessage(message ?? 'Warning'), contextOrMessage);\n }\n }\n },\n error: (contextOrMessage: string | LogContext, message?: string): void => {\n if (shouldLog('error')) {\n if (typeof contextOrMessage === 'string') {\n console.error(formatMessage(contextOrMessage));\n } else {\n console.error(formatMessage(message ?? 'Error'), contextOrMessage);\n }\n }\n },\n };\n}\n\n/**\n * Log verification error\n * @param protocol - Identity protocol\n * @param identifier - Identity identifier\n * @param error - Error object\n * @param context - Additional context\n */\nexport function logVerificationError(\n protocol: string,\n identifier: string,\n error: Error,\n context?: LogContext\n): void {\n const logger = createLogger('identity-verification');\n logger.error(\n {\n protocol,\n identifier,\n error: error.message,\n stack: error.stack,\n ...context,\n },\n 'Verification failed'\n );\n}\n","/**\n * Nostr Integration for OrangeCheck Protocol\n *\n * Implements NIP-78 (Application-specific data) for attestation publishing\n */\n\nimport type { AttestationEnvelope, IdentityBinding, NostrEvent } from './types';\n\nimport { createLogger } from './utils/logger';\n\nconst log = createLogger('ocp/nostr');\n\n/**\n * NIP-78 event kind for OrangeCheck attestations\n */\nexport const ATTESTATION_EVENT_KIND = 30078;\n\n/**\n * Default Nostr relays for OrangeCheck attestation publishing\n *\n * These are well-known, reliable relays with good uptime\n */\nexport const DEFAULT_RELAYS: string[] = [\n 'wss://relay.damus.io',\n 'wss://relay.nostr.band',\n 'wss://nos.lol',\n 'wss://relay.snort.social',\n];\n\n/**\n * Create a NIP-78 event for an OrangeCheck attestation\n *\n * Kind: 30078 (Parameterized Replaceable Event)\n * d-tag: attestation_id (makes it replaceable by attestation ID)\n *\n * @param envelope - Attestation envelope\n * @param pubkey - Nostr public key (hex format)\n * @returns Unsigned Nostr event\n */\nexport function createAttestationEvent(\n envelope: AttestationEnvelope,\n pubkey: string\n): Omit<NostrEvent, 'id' | 'sig'> {\n const tags: string[][] = [\n ['d', envelope.attestation_id], // Parameterized replaceable event identifier\n ['address', envelope.address], // Bitcoin address\n ['scheme', envelope.scheme], // Signature scheme (bip322 or legacy)\n ['issued_at', envelope.issued_at], // ISO timestamp\n ];\n\n // Add identity tags\n for (const identity of envelope.identities) {\n tags.push(['i', `${identity.protocol}:${identity.identifier}`]);\n }\n\n // Add expiration if present\n if (envelope.expires_at) {\n tags.push(['expires', envelope.expires_at]);\n }\n\n // Add relay hints if present\n if (envelope.relay_hints?.length) {\n for (const relay of envelope.relay_hints) {\n tags.push(['relay', relay]);\n }\n }\n\n // Content is the full attestation envelope as JSON\n const content = JSON.stringify(envelope, null, 2);\n\n return {\n kind: ATTESTATION_EVENT_KIND,\n tags,\n content,\n created_at: Math.floor(Date.parse(envelope.issued_at) / 1000),\n pubkey,\n };\n}\n\n/**\n * Parse identity bindings from Nostr event tags\n *\n * @param event - Nostr event\n * @returns Array of identity bindings\n */\nexport function parseIdentitiesFromEvent(event: NostrEvent): IdentityBinding[] {\n const identities: IdentityBinding[] = [];\n\n for (const tag of event.tags) {\n if (tag[0] === 'i' && tag[1]) {\n const colonIndex = tag[1].indexOf(':');\n if (colonIndex !== -1) {\n identities.push({\n protocol: tag[1].substring(0, colonIndex),\n identifier: tag[1].substring(colonIndex + 1),\n });\n }\n }\n }\n\n return identities;\n}\n\n/**\n * Extract attestation ID from Nostr event d-tag\n *\n * @param event - Nostr event\n * @returns Attestation ID or undefined if not found\n */\nexport function getAttestationIdFromEvent(event: NostrEvent): string | undefined {\n const dTag = event.tags.find((tag) => tag[0] === 'd');\n return dTag?.[1];\n}\n\n/**\n * Extract Bitcoin address from Nostr event tags\n *\n * @param event - Nostr event\n * @returns Bitcoin address or undefined if not found\n */\nexport function getAddressFromEvent(event: NostrEvent): string | undefined {\n const addressTag = event.tags.find((tag) => tag[0] === 'address');\n return addressTag?.[1];\n}\n\n/**\n * Publish a Nostr event to multiple relays\n * Returns array of relay URLs that successfully accepted the event\n */\nexport async function publishToRelays(\n event: NostrEvent,\n relays: string[] = DEFAULT_RELAYS\n): Promise<{ success: string[]; failed: string[] }> {\n const success: string[] = [];\n const failed: string[] = [];\n\n log.info({ eventId: event.id, relayCount: relays.length }, 'Publishing event to relays');\n\n const publishPromises = relays.map(async (relayUrl) => {\n let ws: WebSocket | null = null;\n\n try {\n // Connect to relay\n ws = new WebSocket(relayUrl);\n const wsRef = ws; // Capture for closures\n\n await new Promise<void>((resolve, reject) => {\n // One outer deadline covers connect + OK round-trip. The old\n // code cleared this on `onopen`, which meant a relay that\n // opened but never sent OK would hang the promise forever.\n const deadline = setTimeout(() => {\n wsRef.close();\n reject(new Error('Relay publish timeout'));\n }, 10_000);\n\n const cleanup = () => {\n clearTimeout(deadline);\n wsRef.close();\n };\n\n wsRef.onopen = () => {\n // Do NOT clear the deadline — we still need it in case\n // the relay never responds with OK.\n wsRef.send(JSON.stringify(['EVENT', event]));\n };\n\n wsRef.onmessage = (msg) => {\n try {\n const data = JSON.parse(msg.data);\n // Check for OK response\n if (data[0] === 'OK' && data[1] === event.id) {\n if (data[2] === true) {\n success.push(relayUrl);\n cleanup();\n resolve();\n } else {\n log.warn(\n { relay: relayUrl, reason: data[3] },\n 'Relay rejected event'\n );\n failed.push(relayUrl);\n cleanup();\n reject(new Error(data[3] || 'Relay rejected event'));\n }\n }\n } catch (err) {\n log.error(\n { relay: relayUrl, error: err },\n 'Failed to parse relay response'\n );\n failed.push(relayUrl);\n cleanup();\n reject(err);\n }\n };\n\n wsRef.onerror = (err) => {\n log.error({ relay: relayUrl, error: err }, 'WebSocket error');\n failed.push(relayUrl);\n cleanup();\n reject(err);\n };\n\n wsRef.onclose = () => {\n // Socket closed before we resolved/rejected — counts as\n // failure. clearTimeout here is safe (cleanup handles both).\n clearTimeout(deadline);\n };\n });\n } catch (err) {\n log.error({ relay: relayUrl, error: err }, 'Failed to publish to relay');\n if (!failed.includes(relayUrl)) {\n failed.push(relayUrl);\n }\n } finally {\n // Ensure WebSocket is closed\n if (ws && ws.readyState !== WebSocket.CLOSED) {\n ws.close();\n }\n }\n });\n\n await Promise.allSettled(publishPromises);\n\n log.info({ successCount: success.length, failedCount: failed.length }, 'Publishing complete');\n\n return { success, failed };\n}\n\n/**\n * Query relays for attestations by attestation ID\n */\nexport async function queryByAttestationId(\n attestationId: string,\n relays: string[] = DEFAULT_RELAYS\n): Promise<NostrEvent[]> {\n const events: NostrEvent[] = [];\n\n log.info({ attestationId, relayCount: relays.length }, 'Querying relays for attestation');\n\n const queryPromises = relays.map(async (relayUrl) => {\n let ws: WebSocket | null = null;\n\n try {\n ws = new WebSocket(relayUrl);\n const wsRef = ws; // Capture for closures\n\n await new Promise<void>((resolve, reject) => {\n const timeout = setTimeout(() => {\n wsRef.close();\n reject(new Error('Query timeout'));\n }, 10000);\n\n const cleanup = () => {\n clearTimeout(timeout);\n wsRef.close();\n };\n\n wsRef.onopen = () => {\n // Send REQ message for kind 30078 with d-tag = attestation_id\n const subscriptionId = `ochk_${Date.now()}`;\n wsRef.send(\n JSON.stringify([\n 'REQ',\n subscriptionId,\n {\n kinds: [30078],\n '#d': [attestationId],\n limit: 1,\n },\n ])\n );\n };\n\n wsRef.onmessage = (msg) => {\n try {\n const data = JSON.parse(msg.data);\n if (data[0] === 'EVENT') {\n events.push(data[2]);\n } else if (data[0] === 'EOSE') {\n cleanup();\n resolve();\n }\n } catch (err) {\n log.error({ relay: relayUrl, error: err }, 'Failed to parse event');\n }\n };\n\n wsRef.onerror = (err) => {\n log.error({ relay: relayUrl, error: err }, 'WebSocket error during query');\n cleanup();\n reject(err);\n };\n\n wsRef.onclose = () => {\n clearTimeout(timeout);\n };\n });\n } catch (err) {\n log.error({ relay: relayUrl, error: err }, 'Failed to query relay');\n } finally {\n // Ensure WebSocket is closed\n if (ws && ws.readyState !== WebSocket.CLOSED) {\n ws.close();\n }\n }\n });\n\n await Promise.allSettled(queryPromises);\n\n log.info({ eventCount: events.length }, 'Query complete');\n\n return events;\n}\n\n/**\n * Query relays for attestations by Bitcoin address\n */\nexport async function queryByAddress(\n address: string,\n relays: string[] = DEFAULT_RELAYS\n): Promise<NostrEvent[]> {\n const events: NostrEvent[] = [];\n\n log.info({ address, relayCount: relays.length }, 'Querying relays for address');\n\n const queryPromises = relays.map(async (relayUrl) => {\n try {\n const ws = new WebSocket(relayUrl);\n\n await new Promise<void>((resolve, reject) => {\n const timeout = setTimeout(() => {\n ws.close();\n reject(new Error('Query timeout'));\n }, 10000);\n\n ws.onopen = () => {\n const subscriptionId = `ochk_addr_${Date.now()}`;\n ws.send(\n JSON.stringify([\n 'REQ',\n subscriptionId,\n {\n kinds: [30078],\n '#address': [address],\n limit: 10,\n },\n ])\n );\n };\n\n ws.onmessage = (msg) => {\n try {\n const data = JSON.parse(msg.data);\n if (data[0] === 'EVENT') {\n events.push(data[2]);\n } else if (data[0] === 'EOSE') {\n clearTimeout(timeout);\n ws.close();\n resolve();\n }\n } catch (err) {\n log.error({ relay: relayUrl, error: err }, 'Failed to parse event');\n }\n };\n\n ws.onerror = (err) => {\n clearTimeout(timeout);\n log.error({ relay: relayUrl, error: err }, 'WebSocket error during query');\n reject(err);\n };\n });\n } catch (err) {\n log.error({ relay: relayUrl, error: err }, 'Failed to query relay');\n }\n });\n\n await Promise.allSettled(queryPromises);\n\n log.info({ eventCount: events.length }, 'Query complete');\n\n return events;\n}\n\n/**\n * Query relays for attestations by identity (any protocol)\n */\nexport async function queryByIdentity(\n protocol: string,\n identifier: string,\n relays: string[] = DEFAULT_RELAYS\n): Promise<NostrEvent[]> {\n const events: NostrEvent[] = [];\n const identityTag = `${protocol}:${identifier}`;\n\n log.info({ protocol, identifier, relayCount: relays.length }, 'Querying relays for identity');\n\n const queryPromises = relays.map(async (relayUrl) => {\n try {\n const ws = new WebSocket(relayUrl);\n\n await new Promise<void>((resolve, reject) => {\n const timeout = setTimeout(() => {\n ws.close();\n reject(new Error('Query timeout'));\n }, 10000);\n\n ws.onopen = () => {\n const subscriptionId = `ochk_identity_${Date.now()}`;\n ws.send(\n JSON.stringify([\n 'REQ',\n subscriptionId,\n {\n kinds: [30078],\n '#i': [identityTag],\n limit: 10,\n },\n ])\n );\n };\n\n ws.onmessage = (msg) => {\n try {\n const data = JSON.parse(msg.data);\n if (data[0] === 'EVENT') {\n events.push(data[2]);\n } else if (data[0] === 'EOSE') {\n clearTimeout(timeout);\n ws.close();\n resolve();\n }\n } catch (err) {\n log.error({ relay: relayUrl, error: err }, 'Failed to parse event');\n }\n };\n\n ws.onerror = (err) => {\n clearTimeout(timeout);\n log.error({ relay: relayUrl, error: err }, 'WebSocket error during query');\n reject(err);\n };\n });\n } catch (err) {\n log.error({ relay: relayUrl, error: err }, 'Failed to query relay');\n }\n });\n\n await Promise.allSettled(queryPromises);\n\n log.info({ eventCount: events.length }, 'Query complete');\n\n return events;\n}\n\n/**\n * Verify attestation envelope integrity\n * Checks that the attestation ID matches the message hash\n */\nexport async function verifyAttestationEnvelope(envelope: AttestationEnvelope): Promise<boolean> {\n try {\n // Re-compute attestation ID from message\n const encoder = new TextEncoder();\n const data = encoder.encode(envelope.message);\n const hashBuffer = await crypto.subtle.digest('SHA-256', data);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n const computedId = hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');\n\n return computedId === envelope.attestation_id;\n } catch (err) {\n log.error({ error: err }, 'Failed to verify attestation envelope');\n return false;\n }\n}\n\n/**\n * Parse attestation envelope from Nostr event content\n */\nexport function parseAttestationFromEvent(event: NostrEvent): AttestationEnvelope | null {\n try {\n const envelope = JSON.parse(event.content) as AttestationEnvelope;\n return envelope;\n } catch (err) {\n log.error({ eventId: event.id, error: err }, 'Failed to parse attestation from event');\n return null;\n }\n}\n","/**\n * Nostr Cryptographic Functions\n * Implements NIP-01 event ID computation and signature verification\n */\n\nimport type { NostrEvent } from './types';\n\nimport { createLogger } from './utils/logger';\n\ntype Nip07Window = {\n nostr?: {\n getPublicKey: () => Promise<string>;\n signEvent: (event: Omit<NostrEvent, 'id' | 'sig'>) => Promise<NostrEvent>;\n _metadata?: { name?: string; version?: string };\n };\n};\n\nconst log = createLogger('ocp/nostr-crypto');\n\n/**\n * Compute Nostr event ID according to NIP-01\n * Event ID is the SHA-256 hash of the serialized event\n * Serialization: [0, pubkey, created_at, kind, tags, content]\n */\nexport async function computeNostrEventId(event: Omit<NostrEvent, 'id' | 'sig'>): Promise<string> {\n // Serialize event according to NIP-01\n const serialized = JSON.stringify([\n 0, // Reserved for future use\n event.pubkey,\n event.created_at,\n event.kind,\n event.tags,\n event.content,\n ]);\n\n log.debug({ serialized }, 'Computing event ID');\n\n // Compute SHA-256 hash\n const encoder = new TextEncoder();\n const data = encoder.encode(serialized);\n const hashBuffer = await crypto.subtle.digest('SHA-256', data);\n\n // Convert to lowercase hex\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n const hashHex = hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');\n\n log.debug({ eventId: hashHex }, 'Computed event ID');\n\n return hashHex;\n}\n\n/**\n * Verify Nostr event ID\n * Recomputes the ID and checks if it matches\n */\nexport async function verifyNostrEventId(event: NostrEvent): Promise<boolean> {\n const computedId = await computeNostrEventId(event);\n return computedId === event.id;\n}\n\n/**\n * Check if NIP-07 extension is available\n * NIP-07 provides window.nostr for signing events\n */\nexport function isNip07Available(): boolean {\n if (typeof window === 'undefined') {\n return false;\n }\n\n return !!(window as unknown as { nostr?: Nip07Window['nostr'] }).nostr!;\n}\n\n/**\n * Get Nostr public key from NIP-07 extension\n * Returns null if extension not available or user denies\n */\nexport async function getNostrPublicKey(): Promise<string | null> {\n if (!isNip07Available()) {\n log.warn('NIP-07 extension not available');\n return null;\n }\n\n try {\n const nostr = (window as unknown as { nostr?: Nip07Window['nostr'] }).nostr!;\n const pubkey = await nostr.getPublicKey();\n log.info({ pubkey }, 'Got Nostr public key from NIP-07');\n return pubkey;\n } catch (err) {\n log.error({ error: err }, 'Failed to get Nostr public key');\n return null;\n }\n}\n\n/**\n * Sign Nostr event using NIP-07 extension\n * Returns signed event with id and sig fields\n */\nexport async function signNostrEvent(\n event: Omit<NostrEvent, 'id' | 'sig'>\n): Promise<NostrEvent | null> {\n if (!isNip07Available()) {\n log.warn('NIP-07 extension not available');\n return null;\n }\n\n try {\n const nostr = (window as unknown as { nostr?: Nip07Window['nostr'] }).nostr!;\n\n // NIP-07 signEvent expects the event without id and sig\n const signedEvent = await nostr.signEvent(event);\n\n log.info({ eventId: signedEvent.id }, 'Signed Nostr event with NIP-07');\n\n return signedEvent as NostrEvent;\n } catch (err) {\n log.error({ error: err }, 'Failed to sign Nostr event');\n return null;\n }\n}\n\n// Previously this file exported `generateEphemeralKeypair()` and\n// `signEventWithEphemeralKey()` for demo purposes. Both produced non-schnorr\n// values that Nostr relays would silently reject — creating the false\n// impression that publishing had succeeded. They have been removed. All Nostr\n// signing now flows through `signNostrEvent()` / `window.nostr` (NIP-07).\n\n/**\n * Validate Nostr event structure\n */\nexport function validateNostrEvent(event: unknown): event is NostrEvent {\n if (typeof event !== 'object' || event === null) return false;\n const e = event as Record<string, unknown>;\n\n if (typeof e.id !== 'string' || (e.id as string).length !== 64) return false;\n if (typeof e.pubkey !== 'string' || (e.pubkey as string).length !== 64) return false;\n if (typeof e.created_at !== 'number') return false;\n if (typeof e.kind !== 'number') return false;\n if (!Array.isArray(e.tags)) return false;\n if (typeof e.content !== 'string') return false;\n if (typeof e.sig !== 'string' || (e.sig as string).length !== 128) return false;\n\n return true;\n}\n\n/**\n * Get NIP-07 extension info\n */\nexport function getNip07Info(): {\n available: boolean;\n name?: string;\n version?: string;\n} {\n if (!isNip07Available()) {\n return { available: false };\n }\n\n const nostr = (window as unknown as { nostr?: Nip07Window['nostr'] }).nostr!;\n\n return {\n available: true,\n name: nostr._metadata?.name,\n version: nostr._metadata?.version,\n };\n}\n","/**\n * Attestation Manager\n *\n * High-level API for creating, publishing, and discovering OrangeCheck attestations\n */\n\nimport type { AttestationEnvelope, IdentityBinding, NostrEvent, Scheme } from './types';\n\nimport { createAttestationEnvelope } from './canonical';\nimport {\n createAttestationEvent,\n DEFAULT_RELAYS,\n parseAttestationFromEvent,\n publishToRelays,\n queryByAddress,\n queryByAttestationId,\n queryByIdentity,\n verifyAttestationEnvelope,\n} from './nostr';\nimport { isNip07Available, signNostrEvent } from './nostr-crypto';\nimport { createLogger } from './utils/logger';\n\nconst log = createLogger('ocp/attestation');\n\n/**\n * Options for creating an attestation\n */\nexport interface CreateAttestationOptions {\n /** Canonical message */\n message: string;\n /** BIP-322 or legacy signature */\n signature: string;\n /** Signature scheme used */\n scheme: Scheme;\n /** Bitcoin address */\n address: string;\n /** Optional identity bindings */\n identities?: IdentityBinding[];\n /** Optional extension key-value pairs */\n extensions?: Record<string, string | undefined>;\n}\n\n/**\n * Options for publishing an attestation to Nostr\n */\nexport interface PublishAttestationOptions {\n /** Attestation envelope to publish */\n envelope: AttestationEnvelope;\n /** Nostr public key (npub or hex) for signing the event */\n npub: string;\n /** Optional relay URLs (defaults to DEFAULT_RELAYS) */\n relays?: string[];\n}\n\n/**\n * Options for discovering attestations\n */\nexport interface DiscoverAttestationOptions {\n /** Search by attestation ID */\n attestationId?: string;\n /** Search by Bitcoin address */\n address?: string;\n /** Search by identity binding */\n identity?: { protocol: string; identifier: string };\n /** Optional relay URLs to query */\n relays?: string[];\n}\n\n/**\n * Result of publishing an attestation\n */\nexport interface PublishResult {\n /** Relays that successfully received the event */\n success: string[];\n /** Relays that failed to receive the event */\n failed: string[];\n}\n\n/**\n * Custom error for attestation operations\n */\nexport class AttestationError extends Error {\n constructor(\n message: string,\n public readonly code?: string\n ) {\n super(message);\n this.name = 'AttestationError';\n }\n}\n\n/**\n * Create an attestation envelope from a signed message\n *\n * @param options - Attestation creation options\n * @returns Attestation envelope ready for publishing\n * @throws {AttestationError} If envelope integrity check fails\n *\n * @example\n * ```typescript\n * const envelope = await createAttestation({\n * message: canonicalMessage,\n * signature: 'AkcwRAIg...',\n * scheme: 'bip322',\n * address: 'bc1q...',\n * identities: [{ protocol: 'nostr', identifier: 'npub1...' }],\n * });\n * ```\n */\nexport async function createAttestation(\n options: CreateAttestationOptions\n): Promise<AttestationEnvelope> {\n const { message, signature, scheme, address, identities = [], extensions = {} } = options;\n\n log.info({ address, identityCount: identities.length }, 'Creating attestation');\n\n const envelope = await createAttestationEnvelope(\n message,\n signature,\n scheme,\n address,\n identities,\n extensions\n );\n\n // Verify envelope integrity\n const isValid = await verifyAttestationEnvelope(envelope);\n if (!isValid) {\n throw new AttestationError(\n 'Attestation envelope integrity check failed',\n 'INTEGRITY_CHECK_FAILED'\n );\n }\n\n log.info({ attestationId: envelope.attestation_id }, 'Attestation created successfully');\n\n return envelope;\n}\n\n/**\n * Publish an attestation to Nostr relays\n *\n * Uses NIP-07 if available, falls back to ephemeral key for demo\n *\n * @param options - Publishing options\n * @returns Object with successful and failed relay URLs\n * @throws {AttestationError} If signing fails\n *\n * @example\n * ```typescript\n * const result = await publishAttestation({\n * envelope,\n * npub: 'npub1...',\n * relays: ['wss://relay.damus.io'],\n * });\n * console.log('Published to:', result.success);\n * ```\n */\nexport async function publishAttestation(\n options: PublishAttestationOptions\n): Promise<PublishResult> {\n const { envelope, npub, relays = DEFAULT_RELAYS } = options;\n\n log.info(\n { attestationId: envelope.attestation_id, relayCount: relays.length },\n 'Publishing attestation'\n );\n\n // Create unsigned event\n const unsignedEvent = createAttestationEvent(envelope, npub);\n\n // Nostr publishing requires a valid schnorr signature. Only NIP-07\n // (window.nostr) is supported. If no signer is present we refuse to\n // publish rather than emit an invalid-sig event that every relay will\n // silently reject — which would make the caller think it had succeeded.\n if (!isNip07Available()) {\n log.warn('NIP-07 unavailable — skipping Nostr publish');\n throw new Error(\n 'nostr_signer_unavailable: install a NIP-07 extension (e.g. nos2x, Alby) to publish'\n );\n }\n\n log.info('Using NIP-07 to sign event');\n const signedEvent = await signNostrEvent(unsignedEvent);\n if (!signedEvent) {\n throw new Error('nostr_signing_failed: NIP-07 extension rejected or errored');\n }\n\n const result = await publishToRelays(signedEvent, relays);\n\n log.info(\n {\n attestationId: envelope.attestation_id,\n successCount: result.success.length,\n failedCount: result.failed.length,\n },\n 'Publishing complete'\n );\n\n return result;\n}\n\n/**\n * Discover attestations from Nostr relays\n */\nexport async function discoverAttestations(\n options: DiscoverAttestationOptions\n): Promise<AttestationEnvelope[]> {\n const { attestationId, address, identity, relays = DEFAULT_RELAYS } = options;\n\n let events: NostrEvent[] = [];\n\n if (attestationId) {\n log.info({ attestationId }, 'Discovering by attestation ID');\n events = await queryByAttestationId(attestationId, relays);\n } else if (address) {\n log.info({ address }, 'Discovering by Bitcoin address');\n events = await queryByAddress(address, relays);\n } else if (identity) {\n log.info({ identity }, 'Discovering by identity');\n events = await queryByIdentity(identity.protocol, identity.identifier, relays);\n } else {\n throw new Error('Must provide attestationId, address, or identity');\n }\n\n // Parse and verify envelopes\n const envelopes: AttestationEnvelope[] = [];\n for (const event of events) {\n const envelope = parseAttestationFromEvent(event);\n if (envelope) {\n // Verify envelope integrity\n const isValid = await verifyAttestationEnvelope(envelope);\n if (isValid) {\n envelopes.push(envelope);\n } else {\n log.warn(\n { attestationId: envelope.attestation_id },\n 'Skipping invalid attestation envelope'\n );\n }\n }\n }\n\n log.info({ eventCount: events.length, validCount: envelopes.length }, 'Discovery complete');\n\n return envelopes;\n}\n\n/**\n * Verify an attestation by fetching it from Nostr and checking integrity\n */\nexport async function verifyAttestationById(\n attestationId: string,\n relays: string[] = DEFAULT_RELAYS\n): Promise<AttestationEnvelope | null> {\n log.info({ attestationId }, 'Verifying attestation by ID');\n\n const envelopes = await discoverAttestations({ attestationId, relays });\n\n if (envelopes.length === 0) {\n log.warn({ attestationId }, 'Attestation not found on any relay');\n return null;\n }\n\n if (envelopes.length > 1) {\n log.warn(\n { attestationId, count: envelopes.length },\n 'Multiple attestations found with same ID - using first'\n );\n }\n\n return envelopes[0] || null;\n}\n\n/**\n * Get all attestations for a Bitcoin address\n */\nexport async function getAttestationsForAddress(\n address: string,\n relays: string[] = DEFAULT_RELAYS\n): Promise<AttestationEnvelope[]> {\n log.info({ address }, 'Getting all attestations for address');\n return discoverAttestations({ address, relays });\n}\n\n/**\n * Get all attestations for an identity\n */\nexport async function getAttestationsForIdentity(\n protocol: string,\n identifier: string,\n relays: string[] = DEFAULT_RELAYS\n): Promise<AttestationEnvelope[]> {\n log.info({ protocol, identifier }, 'Getting all attestations for identity');\n return discoverAttestations({ identity: { protocol, identifier }, relays });\n}\n\n/**\n * Format identities for display as a comma-separated `protocol:identifier` list.\n * Same wire format the canonical message uses.\n */\nexport function formatIdentitiesForDisplay(identities: IdentityBinding[]): string {\n return identities.map((id) => `${id.protocol}:${id.identifier}`).join(', ');\n}\n\n/**\n * Build the canonical shareable URL for an attestation. Matches the live\n * `/attest/[id]` route on attest.ochk.io. Pass a different `baseUrl` for forks /\n * self-hosted verifiers.\n */\nexport function getVerificationUrl(\n attestationId: string,\n baseUrl = 'https://attest.ochk.io'\n): string {\n return `${baseUrl}/attest/${attestationId}`;\n}\n\n/**\n * Reverse of `getVerificationUrl` — pull an attestation id back out of a\n * `/attest/<id>` or legacy `/verify?id=<id>` URL. Returns `null` if the URL\n * shape doesn't match.\n */\nexport function extractAttestationIdFromUrl(url: string): string | null {\n try {\n const u = new URL(url);\n // New canonical form: /attest/<id>\n const m = u.pathname.match(/^\\/attest\\/([0-9a-f]{64})\\/?$/i);\n if (m) return m[1]!.toLowerCase();\n // Legacy form: /verify?id=<id>\n const q = u.searchParams.get('id');\n if (q && /^[0-9a-f]{64}$/i.test(q)) return q.toLowerCase();\n return null;\n } catch {\n return null;\n }\n}\n","/**\n * OrangeCheck Scoring\n *\n * The protocol registers exactly one scoring algorithm: `v0`. A `tier` helper\n * is also provided for UI convenience. RPs with specialized needs compute\n * their own score against raw metrics — the protocol does not ship an\n * algorithm zoo.\n *\n * See: docs/oc-protocol/registry/scoring.md\n */\n\nexport type ScoringAlgorithm = 'v0' | 'tier' | 'none';\nexport type Tier = 'platinum' | 'gold' | 'silver' | 'bronze' | 'none';\nexport type ScoreResult = number | Tier | null;\n\nexport interface ScoringConfig {\n algorithm: ScoringAlgorithm;\n}\n\nfunction scoreV0(sats: number, days: number): number {\n if (sats <= 0 || days <= 0) return 0;\n return Math.round(Math.log(1 + sats) * (1 + days / 30) * 100) / 100;\n}\n\nfunction scoreTier(sats: number, days: number): Tier {\n if (sats >= 10_000_000 && days >= 365) return 'platinum';\n if (sats >= 1_000_000 && days >= 180) return 'gold';\n if (sats >= 100_000 && days >= 90) return 'silver';\n if (sats >= 10_000 && days >= 30) return 'bronze';\n return 'none';\n}\n\nexport function computeScore(sats: number, days: number, config: ScoringConfig): ScoreResult {\n switch (config.algorithm) {\n case 'v0':\n return scoreV0(sats, days);\n case 'tier':\n return scoreTier(sats, days);\n case 'none':\n return null;\n }\n}\n\nexport function computeAllScores(sats: number, days: number) {\n return { v0: scoreV0(sats, days), tier: scoreTier(sats, days) };\n}\n\nexport function formatScore(score: ScoreResult, algorithm: ScoringAlgorithm): string {\n if (score === null || algorithm === 'none') return 'N/A';\n if (algorithm === 'v0') return (score as number).toFixed(1);\n const tier = score as Tier;\n const labels: Record<Tier, string> = {\n platinum: 'Platinum',\n gold: 'Gold',\n silver: 'Silver',\n bronze: 'Bronze',\n none: '—',\n };\n return labels[tier];\n}\n\nexport function getScoreColor(score: ScoreResult, algorithm: ScoringAlgorithm): string {\n if (algorithm === 'tier') {\n const colors: Record<Tier, string> = {\n platinum: '#a855f7',\n gold: '#eab308',\n silver: '#94a3b8',\n bronze: '#f97316',\n none: '#64748b',\n };\n return colors[(score as Tier) ?? 'none'] ?? '#64748b';\n }\n const n = (score as number) ?? 0;\n if (n >= 100) return '#22c55e';\n if (n >= 50) return '#3b82f6';\n if (n >= 20) return '#eab308';\n return '#f97316';\n}\n\nexport function getTierNumber(tier: Tier): number {\n const map: Record<Tier, number> = {\n platinum: 4,\n gold: 3,\n silver: 2,\n bronze: 1,\n none: 0,\n };\n return map[tier] ?? 0;\n}\n","/**\n * OrangeCheck Protocol Verification\n *\n * Core verification logic for BIP-322 and legacy signatures,\n * UTXO analysis, and reputation metrics computation\n */\n\nimport type { ScoringAlgorithm } from './scoring';\nimport type {\n IdentityBinding,\n Metrics,\n Network,\n Scheme,\n StatusCode,\n VerifyInput,\n VerifyOptions,\n VerifyOutcome,\n} from './types';\n\nimport { Buffer } from 'buffer';\n\nimport { Verifier } from 'bip322-js';\nimport * as bitcoinMessage from 'bitcoinjs-message';\n\nimport { generateAttestationId, parseIdentities } from './canonical';\nimport { computeAllScores, computeScore } from './scoring';\nimport { createLogger } from './utils/logger';\n\nconst log = createLogger('ocp/verify');\n\n/**\n * Scoring function per OCP v0 specification (SPEC.md §6)\n * Formula: score = round( ln(1 + sats_bonded) * (1 + days_unspent / 30), 2 )\n *\n * This produces an unbounded score that combines both sats and time.\n * Typical ranges:\n * - 10k sats, 30 days ≈ 18\n * - 100k sats, 90 days ≈ 46\n * - 1M sats, 365 days ≈ 182\n * - 100M sats, 365 days ≈ 243\n */\n/**\n * Export scoring functions for use in other modules\n */\nexport { computeScore, computeAllScores, type ScoringAlgorithm };\n\n/**\n * Input for signature verification\n */\ninterface SignatureVerifyInput {\n /** Bitcoin address */\n addr: string;\n /** Message to verify */\n msg: string;\n /** Signature (hex or base64) */\n sig: string;\n /** Optional signature scheme (auto-detected if not provided) */\n scheme?: Scheme;\n}\n\n/**\n * Check if a string looks like hexadecimal\n * @param s - String to check\n * @returns True if string is valid hex with even length\n */\nfunction looksLikeHex(s: string): boolean {\n return /^[0-9a-fA-F]+$/.test(s) && s.length % 2 === 0;\n}\n\n/**\n * Convert signature to base64 if it's in hex format\n * @param sig - Signature (hex or base64)\n * @returns Signature in base64 format\n */\nfunction toBase64Maybe(sig: string): string {\n if (looksLikeHex(sig)) {\n return Buffer.from(sig, 'hex').toString('base64');\n }\n return sig;\n}\n\n/**\n * Auto-detect signature scheme based on address type and signature format\n *\n * @param addr - Bitcoin address\n * @param sig - Signature\n * @returns Detected scheme ('bip322' or 'legacy')\n */\nfunction detectSignatureScheme(addr: string, sig: string): Scheme {\n // SegWit and Taproot addresses MUST use BIP-322\n const isSegWit = addr.startsWith('bc1') || addr.startsWith('tb1');\n if (isSegWit) {\n return 'bip322';\n }\n\n // For P2PKH addresses, check if signature looks like legacy format\n const sigBase64 = toBase64Maybe(sig);\n const looksLikeLegacy = sigBase64.length === 88 && /^[IHG]/.test(sigBase64);\n\n if (looksLikeLegacy) {\n return 'legacy';\n }\n\n // Default to BIP-322\n return 'bip322';\n}\n\nasync function verifySignature({\n addr,\n msg,\n sig,\n scheme,\n}: SignatureVerifyInput): Promise<StatusCode> {\n try {\n // Handle demo signatures - these should never reach here in demo mode,\n // but add defensive check in case demo mode flag isn't set properly\n if (sig === 'demo_signature') {\n log.warn('Demo signature detected in verifySignature - should be handled by demo mode');\n return 'sig_invalid';\n }\n\n // Auto-detect scheme if not explicitly provided\n const detectedScheme = scheme || detectSignatureScheme(addr, sig);\n\n log.debug(\n { addr, msgLength: msg.length, sigLength: sig.length, scheme: detectedScheme },\n 'Verifying signature'\n );\n\n if (detectedScheme === 'bip322') {\n const sigBase64 = toBase64Maybe(sig);\n log.debug(\n { sigBase64: sigBase64.substring(0, 50) + '...' },\n 'Signature converted to base64'\n );\n\n // Log the full message for debugging\n log.debug(\n {\n msgFull: msg,\n msgLines: msg.split('\\n').length,\n msgFirstLine: msg.split('\\n')[0],\n msgLastLine: msg.split('\\n')[msg.split('\\n').length - 1],\n },\n 'Message being verified'\n );\n\n const ok = Verifier.verifySignature(addr, msg, sigBase64);\n log.info({ addr, ok }, 'BIP-322 verification result');\n\n if (!ok) {\n // Check if this looks like an Electrum signature (88 chars, base64)\n const isSegWit = addr.startsWith('bc1') || addr.startsWith('tb1');\n if (isSegWit && sigBase64.length === 88) {\n log.warn(\n { addr, wallet: 'possibly Electrum', sigLength: sigBase64.length },\n 'BIP-322 verification failed - likely Electrum wallet (does not support BIP-322 for SegWit)'\n );\n } else {\n log.error(\n {\n addr,\n sigLength: sigBase64.length,\n msgLength: msg.length,\n msgPreview: msg.substring(0, 200),\n },\n 'BIP-322 verification failed - signature does not match message'\n );\n }\n }\n\n return ok ? 'sig_ok_bip322' : 'sig_invalid';\n }\n\n if (detectedScheme === 'legacy') {\n const sigBase64 = toBase64Maybe(sig);\n\n // Legacy policy: P2PKH only (address must start with '1' for mainnet or 'm'/'n' for testnet)\n if (!addr.startsWith('1') && !addr.startsWith('m') && !addr.startsWith('n')) {\n log.warn({ addr }, 'Legacy signature attempted on non-P2PKH address');\n return 'sig_unsupported_script';\n }\n\n log.debug(\n {\n addr,\n sigBase64: sigBase64.substring(0, 50) + '...',\n msgPreview: msg.substring(0, 100) + '...',\n msgLength: msg.length,\n },\n 'Verifying legacy signature'\n );\n const ok = bitcoinMessage.verify(msg, addr, sigBase64);\n log.info({ addr, ok, sigBase64Length: sigBase64.length }, 'Legacy verification result');\n if (!ok) {\n log.error(\n {\n addr,\n msgFirstLine: msg.split('\\n')[0],\n sigFormat: sigBase64.substring(0, 10),\n },\n 'Legacy signature verification failed - check message format and signature'\n );\n }\n return ok ? 'sig_ok_legacy' : 'sig_invalid';\n }\n\n return 'invalid_scheme';\n } catch (err) {\n log.error(\n { addr, error: err instanceof Error ? err.message : String(err) },\n 'Signature verification error'\n );\n return 'sig_invalid';\n }\n}\n\n// Canonical message parsing per SPEC + our builder (lowercase keys, extensions)\nfunction parseCanonicalMessage(msg: string) {\n const lines = msg.split('\\n').map((l) => l.trim());\n // `.split(':', 2)[1]` truncates values containing a colon (e.g. URLs in\n // extensions, or npubs in identities). Use the first colon as the\n // separator and keep everything after it — same approach as the\n // extensions loop below.\n const getVal = (prefix: string): string | undefined => {\n const needle = prefix + ':';\n const hit = lines.find((l) => l.toLowerCase().startsWith(needle));\n if (!hit) return undefined;\n const idx = hit.indexOf(':');\n return hit.slice(idx + 1).trim();\n };\n\n const address = getVal('address') || '';\n const identitiesStr = getVal('identities') || '';\n\n // Parse identities\n let identities: IdentityBinding[] = [];\n try {\n identities = parseIdentities(identitiesStr);\n } catch (err) {\n log.warn({ identitiesStr, error: err }, 'Failed to parse identities field');\n }\n\n // Extensions: collect all key: value pairs excluding core known keys\n const coreKeys = new Set([\n 'orangecheck',\n 'identities',\n 'address',\n 'purpose',\n 'nonce',\n 'issued_at',\n 'ack',\n ]);\n const extensions: Record<string, string> = {};\n for (const line of lines) {\n const idx = line.indexOf(':');\n if (idx === -1) continue;\n const key = line.slice(0, idx).trim().toLowerCase();\n const val = line.slice(idx + 1).trim();\n if (!coreKeys.has(key) && val) extensions[key] = val;\n }\n\n const network = (extensions['network'] || 'mainnet') as Network;\n\n // Parse bond extension if present (integer satoshis)\n const bondStr = extensions['bond'];\n const bond = bondStr ? parseInt(bondStr, 10) : undefined;\n\n return {\n core: { address, identities },\n network,\n extensions,\n bond: bond !== undefined && !isNaN(bond) && bond > 0 ? bond : undefined,\n };\n}\n\n/**\n * UTXO type from Esplora API\n */\ninterface EsploraUtxo {\n /** Transaction ID */\n txid: string;\n /** Output index */\n vout: number;\n /** Value in satoshis */\n value: number;\n /** Confirmation status */\n status: {\n /** Whether UTXO is confirmed */\n confirmed: boolean;\n /** Block height (if confirmed) */\n block_height?: number;\n /** Block timestamp (if confirmed) */\n block_time?: number;\n };\n}\n\n/**\n * Fetch UTXOs for an address from Esplora API\n *\n * Tries multiple endpoints in order with automatic fallback\n *\n * @param address - Bitcoin address\n * @param network - Bitcoin network\n * @param opts - Optional custom Esplora endpoints\n * @returns Array of UTXOs\n * @throws {Error} If all endpoints fail\n */\nasync function getAddressUtxos(\n address: string,\n network: Network,\n opts?: {\n esploraMainnetBase?: string;\n esploraSignetBase?: string;\n esploraTestnetBase?: string;\n }\n): Promise<EsploraUtxo[]> {\n // Define primary and fallback endpoints\n const endpoints =\n network === 'signet'\n ? [\n opts?.esploraSignetBase || 'https://mempool.space/signet/api',\n 'https://blockstream.info/signet/api',\n ]\n : network === 'testnet'\n ? [\n opts?.esploraTestnetBase || 'https://mempool.space/testnet/api',\n 'https://blockstream.info/testnet/api',\n ]\n : [\n opts?.esploraMainnetBase || 'https://mempool.space/api',\n 'https://blockstream.info/api',\n ];\n\n let lastError: Error | null = null;\n\n // Try each endpoint in order. Per-endpoint timeout kept tight (5s) so\n // a slow upstream doesn't stack against the next one; callers who want\n // a hard overall deadline should wrap this call with their own timeout.\n for (const base of endpoints) {\n try {\n const url = `${base}/address/${address}/utxo`;\n log.debug({ url, network }, 'Fetching UTXOs');\n\n const resp = await fetch(url, {\n method: 'GET',\n headers: { Accept: 'application/json' },\n signal: AbortSignal.timeout(5000),\n });\n\n if (!resp.ok) {\n throw new Error(`HTTP ${resp.status}`);\n }\n\n const data = await resp.json();\n\n // Validate response structure\n if (!Array.isArray(data)) {\n throw new Error('Invalid response: expected array');\n }\n\n // Validate each UTXO has required fields\n for (const utxo of data) {\n if (\n typeof utxo.value !== 'number' ||\n typeof utxo.status !== 'object' ||\n typeof utxo.status.confirmed !== 'boolean' ||\n typeof utxo.txid !== 'string' ||\n typeof utxo.vout !== 'number'\n ) {\n throw new Error('Invalid UTXO structure');\n }\n }\n\n log.info({ base, count: data.length, network }, 'UTXOs fetched successfully');\n return data as EsploraUtxo[];\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err));\n log.warn(\n { base, error: lastError.message, network },\n 'Esplora endpoint failed, trying next'\n );\n }\n }\n\n // All endpoints failed\n log.error({ endpoints, error: lastError?.message, network }, 'All Esplora endpoints failed');\n throw new Error(`esplora_all_failed: ${lastError?.message || 'unknown'}`);\n}\n\n/**\n * Enhanced metrics computation per SPEC.md §5.4 and §6.1\n *\n * Supports bond extension with oldest-first greedy UTXO selection\n *\n * @param utxos - Array of UTXOs from Esplora\n * @param bondAmount - Optional bond amount (enables greedy selection)\n * @returns Computed metrics (sats_bonded, days_unspent, confirmed_balance)\n */\nfunction computeMetrics(\n utxos: EsploraUtxo[],\n bondAmount?: number\n): {\n /** Bonded satoshis (confirmed balance or bond amount) */\n sats_bonded: number;\n /** Days since oldest/youngest UTXO */\n days_unspent: number;\n /** Total confirmed balance */\n confirmed_balance: number;\n} {\n // Filter out unconfirmed UTXOs\n const confirmedUtxos = utxos.filter((u) => u.status.confirmed);\n if (confirmedUtxos.length === 0) {\n return { sats_bonded: 0, days_unspent: 0, confirmed_balance: 0 };\n }\n\n // Compute total confirmed balance\n const confirmed_balance = confirmedUtxos.reduce((sum, u) => sum + u.value, 0);\n\n // If bond extension is present, use oldest-first greedy algorithm\n if (bondAmount !== undefined && bondAmount > 0) {\n // Sort UTXOs by (block_height ASC, txid ASC, vout ASC) - oldest first\n const sorted = [...confirmedUtxos].sort((a, b) => {\n const heightA = a.status.block_height ?? Infinity;\n const heightB = b.status.block_height ?? Infinity;\n if (heightA !== heightB) return heightA - heightB;\n if (a.txid !== b.txid) return a.txid.localeCompare(b.txid);\n return a.vout - b.vout;\n });\n\n // Greedily select UTXOs until sum >= bond\n let sum = 0;\n let youngestTime = 0;\n for (const utxo of sorted) {\n sum += utxo.value;\n youngestTime = Math.max(youngestTime, utxo.status.block_time || 0);\n if (sum >= bondAmount) break;\n }\n\n // Age is computed from the youngest UTXO in the bonded set\n const days_unspent = Math.max(\n 0,\n Math.floor((Date.now() / 1000 - youngestTime) / (24 * 60 * 60))\n );\n\n return {\n sats_bonded: bondAmount, // Use exactly bond amount (ignore surplus)\n days_unspent,\n confirmed_balance,\n };\n }\n\n // Default behavior (no bond extension): sum all confirmed UTXOs\n const sats_bonded = confirmed_balance;\n\n // Find the oldest confirmed UTXO for days_unspent\n const oldestTime = Math.min(\n ...confirmedUtxos.map((u) => u.status.block_time || Date.now() / 1000)\n );\n const days_unspent = Math.max(0, Math.floor((Date.now() / 1000 - oldestTime) / (24 * 60 * 60)));\n\n return { sats_bonded, days_unspent, confirmed_balance };\n}\n\n/**\n * Verify an OrangeCheck attestation\n *\n * This is the main verification function that:\n * 1. Validates the canonical message format\n * 2. Verifies the Bitcoin signature (BIP-322 or legacy)\n * 3. Fetches and analyzes UTXOs\n * 4. Computes reputation metrics\n *\n * @param input - Verification input (message, address, signature)\n * @param opts - Optional verification options (demo mode, test mode, etc.)\n * @returns Verification outcome with status codes and metrics\n *\n * @example\n * ```typescript\n * const result = await verify({\n * msg: canonicalMessage,\n * addr: 'bc1q...',\n * sig: 'AkcwRAIg...',\n * });\n *\n * if (result.ok) {\n * console.log('Score:', result.metrics?.score);\n * }\n * ```\n */\nexport async function verify(input: VerifyInput, opts: VerifyOptions = {}): Promise<VerifyOutcome> {\n const codes: StatusCode[] = [];\n let network: Network = 'mainnet';\n\n try {\n // Check if we have required fields\n if (!input.msg || !input.addr || !input.sig) {\n codes.push('bad_request');\n return { ok: false, codes, network };\n }\n\n // Parse canonical message with extensions\n const parsed = parseCanonicalMessage(input.msg);\n network = parsed.network || 'mainnet';\n\n // Compute attestation ID\n const attestation_id = await generateAttestationId(input.msg);\n\n // Validate address consistency\n if (parsed.core.address !== input.addr) {\n codes.push('bad_request');\n return { ok: false, codes, network, attestation_id };\n }\n\n // Demo mode short-circuit with demo data matching the App panel\n if (opts.demoMode) {\n // Keep demo values in sync with createDemoBadgeData()\n const sats_bonded = 1_000_000; // 0.01 BTC\n const days_unspent = 90;\n const metrics: Metrics = {\n sats_bonded,\n days_unspent,\n score: (computeScore(sats_bonded, days_unspent, { algorithm: 'v0' }) as number), // ≈ 55.26\n };\n codes.push('sig_ok_bip322');\n codes.push('bond_confirmed');\n return {\n ok: true,\n codes,\n network,\n attestation_id,\n identities: parsed.core.identities,\n metrics,\n };\n }\n\n // Testnet/Signet policy enforcement\n if ((network === 'testnet' || network === 'signet') && !opts.testMode) {\n codes.push('network_testmode');\n return { ok: false, codes, network, attestation_id };\n }\n\n // Optional policy checks for extensions.\n // `aud` binds the attestation to an origin. If the caller passed\n // `expectedAud`, the check must be load-bearing — a mismatch is a\n // phishing signal, not an advisory. Fail hard (spec-aligned).\n if (opts.expectedAud) {\n const aud = parsed.extensions['aud'];\n if (!aud || aud !== opts.expectedAud) {\n codes.push('aud_mismatch');\n return { ok: false, codes, network, attestation_id };\n }\n }\n\n // Check message expiration\n if (parsed.extensions['expires']) {\n const exp = Date.parse(parsed.extensions['expires']);\n if (!Number.isNaN(exp) && exp < Date.now()) {\n codes.push('expired');\n return { ok: false, codes, network, attestation_id };\n }\n }\n\n // Enhanced signature verification\n const sigCode = await verifySignature({\n addr: input.addr,\n msg: input.msg,\n sig: input.sig,\n ...(input.scheme && { scheme: input.scheme }),\n });\n codes.push(sigCode);\n\n const sigOk = sigCode === 'sig_ok_bip322' || sigCode === 'sig_ok_legacy';\n if (!sigOk) {\n return {\n ok: false,\n codes,\n network,\n attestation_id,\n identities: parsed.core.identities,\n };\n }\n\n // Enhanced UTXO analysis and metrics computation\n try {\n const utxos = await getAddressUtxos(input.addr, network, {\n esploraMainnetBase: opts.esploraMainnetBase,\n esploraSignetBase: opts.esploraSignetBase,\n });\n\n // Compute metrics with bond extension support (SPEC.md §5.4)\n const { sats_bonded, days_unspent, confirmed_balance } = computeMetrics(\n utxos,\n parsed.bond\n );\n\n // If bond extension is present, enforce minimum balance (SPEC.md §5.4.c)\n if (parsed.bond !== undefined && parsed.bond > 0) {\n if (confirmed_balance < parsed.bond) {\n codes.push('bond_insufficient');\n log.warn(\n {\n bond: parsed.bond,\n confirmed_balance,\n address: input.addr,\n },\n 'Bond extension: insufficient balance'\n );\n return {\n ok: false,\n codes,\n network,\n attestation_id,\n identities: parsed.core.identities,\n };\n }\n }\n\n // Analyze bond status\n if (sats_bonded <= 0) {\n codes.push('bond_zero');\n // Check for pending UTXOs\n if (utxos.some((u) => !u.status.confirmed)) {\n codes.push('bond_pending');\n }\n return {\n ok: false,\n codes,\n network,\n attestation_id,\n identities: parsed.core.identities,\n };\n } else {\n codes.push('bond_confirmed');\n }\n\n // Compute final metrics with enhanced scoring\n const metrics: Metrics = {\n sats_bonded,\n days_unspent,\n score: (computeScore(sats_bonded, days_unspent, { algorithm: 'v0' }) as number),\n };\n\n return {\n ok: true,\n codes,\n network,\n attestation_id,\n identities: parsed.core.identities,\n metrics,\n };\n } catch (utxoError) {\n log.error({ err: utxoError }, 'UTXO fetch failed');\n codes.push('bad_request');\n return { ok: false, codes, network, attestation_id };\n }\n } catch (e: unknown) {\n const msg = e instanceof Error ? e.message : String(e ?? 'decode_error');\n if (msg === 'decode_error') {\n codes.push('decode_error');\n } else {\n codes.push('bad_request');\n }\n return { ok: false, codes, network };\n }\n}\n","/**\n * check()\n *\n * The high-level sybil-gate primitive. One call, one answer.\n *\n * Under the hood: find the most recent attestation for the subject via Nostr,\n * verify the signature, recompute metrics from live chain state, then compare\n * against the caller's thresholds.\n *\n * Mirrors the response shape of GET /api/check.\n */\n\nimport type { AttestationEnvelope, IdentityBinding, Network, VerifyOptions } from './types';\n\nimport {\n discoverAttestations,\n getAttestationsForAddress,\n getAttestationsForIdentity,\n} from './attestation';\nimport { DEFAULT_RELAYS } from './nostr';\nimport { verify } from './verify';\n\nexport interface CheckParams {\n /** Bitcoin address to look up. */\n addr?: string;\n /** Content-addressed attestation ID (hex). */\n id?: string;\n /** Identity binding, e.g. `{ protocol: 'github', identifier: 'alice' }`. */\n identity?: { protocol: string; identifier: string };\n /** Minimum sats bonded to pass. Default 0. */\n minSats?: number;\n /** Minimum days unspent to pass. Default 0. */\n minDays?: number;\n /** Optional relay overrides for discovery. */\n relays?: string[];\n /** Optional verify-time options (esplora bases, test mode). */\n verifyOptions?: VerifyOptions;\n}\n\nexport interface CheckResult {\n /** True iff signature valid AND thresholds met. */\n ok: boolean;\n /** Sats bonded on-chain for the bonded UTXO set. */\n sats: number;\n /** Days since the youngest UTXO in the bonded set was confirmed. */\n days: number;\n /** Reference `score_v0` for this attestation. */\n score: number;\n /** Attestation ID (if one was found). */\n attestation_id?: string;\n /** Bitcoin address of the attestation. */\n address?: string;\n /** Self-asserted identity bindings. Verify independently. */\n identities?: IdentityBinding[];\n /** Network the address belongs to. */\n network?: Network;\n /** Present when `ok === false`. Codes explain why. */\n reasons?: string[];\n}\n\nexport async function check(params: CheckParams): Promise<CheckResult> {\n const {\n addr,\n id,\n identity,\n minSats = 0,\n minDays = 0,\n relays = DEFAULT_RELAYS,\n verifyOptions,\n } = params;\n\n if (!addr && !id && !identity) {\n return { ok: false, sats: 0, days: 0, score: 0, reasons: ['bad_request'] };\n }\n\n let envelopes: AttestationEnvelope[] = [];\n if (id) {\n envelopes = await discoverAttestations({ attestationId: id, relays });\n } else if (addr) {\n envelopes = await getAttestationsForAddress(addr, relays);\n } else if (identity) {\n envelopes = await getAttestationsForIdentity(\n identity.protocol,\n identity.identifier,\n relays\n );\n }\n\n if (envelopes.length === 0) {\n return { ok: false, sats: 0, days: 0, score: 0, reasons: ['not_found'] };\n }\n\n // Prefer most recent.\n envelopes.sort((a, b) => new Date(b.issued_at).getTime() - new Date(a.issued_at).getTime());\n const env = envelopes[0];\n if (!env) {\n return { ok: false, sats: 0, days: 0, score: 0, reasons: ['not_found'] };\n }\n\n const outcome = await verify(\n {\n addr: env.address,\n msg: env.message,\n sig: env.signature,\n scheme: env.scheme,\n },\n verifyOptions\n );\n\n const sats = outcome.metrics?.sats_bonded ?? 0;\n const days = outcome.metrics?.days_unspent ?? 0;\n const score = outcome.metrics?.score ?? 0;\n\n const reasons: string[] = [];\n if (!outcome.ok) reasons.push(...outcome.codes);\n if (sats < minSats) reasons.push('below_min_sats');\n if (days < minDays) reasons.push('below_min_days');\n\n const ok = outcome.ok && sats >= minSats && days >= minDays;\n\n return {\n ok,\n sats,\n days,\n score,\n attestation_id: env.attestation_id,\n address: env.address,\n identities: env.identities,\n network: outcome.network,\n ...(reasons.length ? { reasons } : {}),\n };\n}\n","/**\n * Signed-challenge auth\n *\n * When a gate can't trust the address source (public header, query string,\n * unsigned cookie), run a one-shot BIP-322 challenge first to cryptographically\n * prove the caller controls the address. Bind the proven address to a session\n * cookie or JWT, and the gate reads from there.\n *\n * This is a different wire format from the main OCP attestation — the header\n * literal is `orangecheck-auth`, not `orangecheck`, so a signed auth challenge\n * can never be confused with a reputation attestation.\n *\n * // Server, on the \"connect wallet\" flow:\n * const challenge = issueChallenge({ address, ttlSeconds: 300 });\n * // → send challenge.message to the client\n *\n * // Client signs challenge.message with BIP-322 via the user's wallet,\n * // then posts { message, signature } back.\n *\n * // Server, on callback:\n * const result = await verifyChallenge({ message, signature });\n * if (result.ok) {\n * // result.address is now cryptographically proven; attach to session.\n * }\n */\n\nimport type { Scheme } from './types';\n\nimport { Buffer } from 'buffer';\n\nimport { Verifier } from 'bip322-js';\nimport * as bitcoinMessage from 'bitcoinjs-message';\n\nconst AUTH_HEADER = 'orangecheck-auth';\nconst AUTH_ACK = 'I authorize this session under the OrangeCheck auth challenge.';\n\nfunction randomNonce(): string {\n // 16 bytes → 32 lowercase hex chars. Matches OCP core nonce format.\n const bytes = new Uint8Array(16);\n // Runtimes: Node 20+ (webcrypto), browsers.\n if (typeof globalThis.crypto?.getRandomValues === 'function') {\n globalThis.crypto.getRandomValues(bytes);\n } else {\n // Fallback: Math.random is *not* cryptographic — acceptable only for\n // environments without webcrypto (old Node). Flagged explicitly.\n for (let i = 0; i < bytes.length; i++) bytes[i] = Math.floor(Math.random() * 256);\n }\n return Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');\n}\n\nfunction iso(date: Date): string {\n return date.toISOString().replace(/\\.\\d{3}Z$/, 'Z');\n}\n\nexport interface IssueChallengeOptions {\n /** Bitcoin address the caller claims to control. */\n address: string;\n /** How long the challenge is valid for. Default 300 (5 minutes). */\n ttlSeconds?: number;\n /** Explicit nonce. Rare; prefer auto-generated. */\n nonce?: string;\n /** Origin-binding extension. If set, verify will require a match. */\n audience?: string;\n /** Human-readable label baked into the signed message. */\n purpose?: string;\n /** Freeze `now` for tests. */\n now?: Date;\n}\n\nexport interface Challenge {\n /** The canonical text the client MUST sign. */\n message: string;\n /** The generated nonce (kept for correlation / server-side storage). */\n nonce: string;\n /** Unix ms epoch the challenge expires at. */\n expiresAt: number;\n /** ISO string of the same. */\n expiresAtIso: string;\n}\n\n/**\n * Build a new signed-challenge message. The server MUST remember the nonce\n * it issued against the session (Redis, signed cookie, DB) so it can detect\n * replay or a different nonce coming back on verify.\n */\nexport function issueChallenge(opts: IssueChallengeOptions): Challenge {\n const now = opts.now ?? new Date();\n const ttl = opts.ttlSeconds ?? 300;\n const expiresAt = new Date(now.getTime() + ttl * 1000);\n const nonce = opts.nonce ?? randomNonce();\n\n if (!/^[0-9a-f]{32}$/.test(nonce)) {\n throw new Error('nonce must be 32 lowercase hex characters');\n }\n\n const coreLines = [\n AUTH_HEADER,\n `address: ${opts.address}`,\n `nonce: ${nonce}`,\n `issued_at: ${iso(now)}`,\n `expires_at: ${iso(expiresAt)}`,\n `ack: ${AUTH_ACK}`,\n ];\n\n const extensions: Array<[string, string]> = [];\n if (opts.audience) extensions.push(['audience', opts.audience]);\n if (opts.purpose) extensions.push(['purpose', opts.purpose]);\n // Lexicographic sort by key — matches OCP canonicalization rules.\n extensions.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));\n\n const extLines = extensions.map(([k, v]) => `${k}: ${v}`);\n const message = [...coreLines, ...extLines].join('\\n') + '\\n';\n\n return {\n message,\n nonce,\n expiresAt: expiresAt.getTime(),\n expiresAtIso: iso(expiresAt),\n };\n}\n\ninterface ParsedChallenge {\n address?: string;\n nonce?: string;\n issuedAt?: Date;\n expiresAt?: Date;\n ack?: string;\n audience?: string;\n purpose?: string;\n extensions: Array<[string, string]>;\n}\n\nfunction parseChallenge(message: string): ParsedChallenge {\n const lines = message.endsWith('\\n') ? message.slice(0, -1).split('\\n') : message.split('\\n');\n\n if (lines[0] !== AUTH_HEADER) {\n throw new Error('not an orangecheck-auth challenge');\n }\n\n const out: ParsedChallenge = { extensions: [] };\n const coreKeys = ['address', 'nonce', 'issued_at', 'expires_at', 'ack'] as const;\n const coreKeySet = new Set<string>(coreKeys);\n // Duplicate detection: a challenge with two `address:` lines would\n // previously let the second overwrite the first. A signer who saw both\n // lines would still sign the whole text — which means the verifier and\n // the signer disagree about what the message \"said\". Refuse instead.\n const seenCore = new Set<string>();\n\n for (let i = 1; i < lines.length; i++) {\n const line = lines[i] ?? '';\n const sep = line.indexOf(': ');\n if (sep === -1) continue;\n const key = line.slice(0, sep);\n const val = line.slice(sep + 2);\n\n if (coreKeySet.has(key)) {\n if (seenCore.has(key)) {\n throw new Error(`duplicate core key in challenge: ${key}`);\n }\n seenCore.add(key);\n if (key === 'address') out.address = val;\n else if (key === 'nonce') out.nonce = val;\n else if (key === 'issued_at') out.issuedAt = new Date(val);\n else if (key === 'expires_at') out.expiresAt = new Date(val);\n else if (key === 'ack') out.ack = val;\n } else {\n out.extensions.push([key, val]);\n if (key === 'audience') out.audience = val;\n if (key === 'purpose') out.purpose = val;\n }\n }\n\n if (seenCore.size !== coreKeys.length) {\n throw new Error(`challenge missing core lines (${seenCore.size}/${coreKeys.length})`);\n }\n return out;\n}\n\nexport interface VerifyChallengeOptions {\n /** The signed canonical challenge text, exactly as issued. */\n message: string;\n /** BIP-322 or legacy signature. */\n signature: string;\n /** Scheme override. Default 'bip322'. */\n scheme?: Scheme;\n\n /** If set, require the challenge's `audience:` extension to match. */\n expectedAudience?: string;\n /** If set, require the challenge's `purpose:` extension to match. */\n expectedPurpose?: string;\n /**\n * If set, require the challenge's `nonce:` to match. Use this to defeat\n * replay — pair with server-side nonce storage (Redis / signed cookie).\n */\n expectedNonce?: string;\n\n /** Tolerance on expiry check in ms. Default 0. */\n clockSkewMs?: number;\n /** Freeze `now` for tests. */\n now?: Date;\n}\n\nexport type VerifyChallengeReason =\n | 'ok'\n | 'malformed'\n | 'expired'\n | 'not_yet_valid'\n | 'sig_invalid'\n | 'sig_unsupported_scheme'\n | 'audience_mismatch'\n | 'purpose_mismatch'\n | 'nonce_mismatch';\n\nexport interface VerifyChallengeResult {\n ok: boolean;\n reason: VerifyChallengeReason;\n /** Present on success — the cryptographically proven Bitcoin address. */\n address?: string;\n /** Present on success — when the challenge expires (unix ms). */\n expiresAt?: number;\n /** Present on success — the nonce from the challenge. */\n nonce?: string;\n /** Present on success — the audience extension, if any. */\n audience?: string;\n /** Present on success — the purpose extension, if any. */\n purpose?: string;\n}\n\n/**\n * Verify a signed challenge. Returns the proven address on success.\n *\n * The caller is responsible for nonce replay prevention — pass `expectedNonce`\n * with the value you stashed at issue time.\n */\nexport async function verifyChallenge(\n opts: VerifyChallengeOptions\n): Promise<VerifyChallengeResult> {\n let parsed: ParsedChallenge;\n try {\n parsed = parseChallenge(opts.message);\n } catch {\n return { ok: false, reason: 'malformed' };\n }\n\n const { address, nonce, issuedAt, expiresAt, ack, audience, purpose } = parsed;\n if (!address || !nonce || !issuedAt || !expiresAt || !ack) {\n return { ok: false, reason: 'malformed' };\n }\n if (ack !== AUTH_ACK) {\n return { ok: false, reason: 'malformed' };\n }\n if (!/^[0-9a-f]{32}$/.test(nonce)) {\n return { ok: false, reason: 'malformed' };\n }\n\n const now = opts.now ?? new Date();\n const skew = opts.clockSkewMs ?? 0;\n\n if (now.getTime() - skew > expiresAt.getTime()) {\n return { ok: false, reason: 'expired' };\n }\n if (now.getTime() + skew < issuedAt.getTime()) {\n return { ok: false, reason: 'not_yet_valid' };\n }\n\n if (opts.expectedNonce && nonce !== opts.expectedNonce) {\n return { ok: false, reason: 'nonce_mismatch' };\n }\n if (opts.expectedAudience && audience !== opts.expectedAudience) {\n return { ok: false, reason: 'audience_mismatch' };\n }\n if (opts.expectedPurpose && purpose !== opts.expectedPurpose) {\n return { ok: false, reason: 'purpose_mismatch' };\n }\n\n const scheme: Scheme = opts.scheme ?? 'bip322';\n let sigValid = false;\n\n try {\n if (scheme === 'bip322') {\n const sigBase64 =\n /^[0-9a-fA-F]+$/.test(opts.signature) && opts.signature.length % 2 === 0\n ? Buffer.from(opts.signature, 'hex').toString('base64')\n : opts.signature;\n sigValid = Verifier.verifySignature(address, opts.message, sigBase64);\n } else if (scheme === 'legacy') {\n // Legacy signmessage only works for P2PKH addresses.\n if (!/^[1m][a-km-zA-HJ-NP-Z1-9]{25,34}$/.test(address)) {\n return { ok: false, reason: 'sig_unsupported_scheme' };\n }\n sigValid = bitcoinMessage.verify(opts.message, address, opts.signature);\n } else {\n return { ok: false, reason: 'sig_unsupported_scheme' };\n }\n } catch {\n sigValid = false;\n }\n\n if (!sigValid) return { ok: false, reason: 'sig_invalid' };\n\n return {\n ok: true,\n reason: 'ok',\n address,\n expiresAt: expiresAt.getTime(),\n nonce,\n ...(audience !== undefined ? { audience } : {}),\n ...(purpose !== undefined ? { purpose } : {}),\n };\n}\n","/**\n * Simple in-memory rate limiter\n */\n\n/**\n * Rate limiter configuration\n */\nexport interface RateLimiter {\n /** Maximum number of requests allowed in the time window */\n readonly maxRequests: number;\n /** Time window in milliseconds */\n readonly windowMs: number;\n /** Internal request tracking map */\n readonly requests: Map<string, number[]>;\n}\n\n/**\n * Rate limit error\n */\nexport class RateLimitError extends Error {\n constructor(message = 'Rate limit exceeded. Please try again later.') {\n super(message);\n this.name = 'RateLimitError';\n }\n}\n\n/**\n * Create a rate limiter\n * @param maxRequests - Maximum requests allowed in the time window\n * @param windowMs - Time window in milliseconds\n * @returns Rate limiter instance\n */\nexport function createRateLimiter(maxRequests: number, windowMs: number): RateLimiter {\n if (maxRequests <= 0) {\n throw new Error('maxRequests must be greater than 0');\n }\n if (windowMs <= 0) {\n throw new Error('windowMs must be greater than 0');\n }\n\n return {\n maxRequests,\n windowMs,\n requests: new Map<string, number[]>(),\n };\n}\n\n/**\n * Check if a request is within rate limits\n * @param limiter - Rate limiter instance\n * @param key - Unique key for the request (e.g., user ID, IP address)\n * @returns True if request is allowed, false if rate limit exceeded\n */\nexport function checkRateLimit(limiter: RateLimiter, key: string): boolean {\n const now = Date.now();\n const requests = limiter.requests.get(key) ?? [];\n\n // Remove old requests outside the window\n const validRequests = requests.filter((timestamp) => now - timestamp < limiter.windowMs);\n\n // Check if limit exceeded\n if (validRequests.length >= limiter.maxRequests) {\n return false;\n }\n\n // Add new request\n validRequests.push(now);\n limiter.requests.set(key, validRequests);\n\n return true;\n}\n\n/**\n * Enforce rate limit, throwing an error if exceeded\n * @param limiter - Rate limiter instance\n * @param key - Unique key for the request\n * @throws {RateLimitError} If rate limit is exceeded\n */\nexport function enforceRateLimit(limiter: RateLimiter, key: string): void {\n if (!checkRateLimit(limiter, key)) {\n throw new RateLimitError();\n }\n}\n\n/**\n * Get remaining requests for a key\n * @param limiter - Rate limiter instance\n * @param key - Unique key for the request\n * @returns Number of remaining requests in the current window\n */\nexport function getRemainingRequests(limiter: RateLimiter, key: string): number {\n const now = Date.now();\n const requests = limiter.requests.get(key) ?? [];\n const validRequests = requests.filter((timestamp) => now - timestamp < limiter.windowMs);\n return Math.max(0, limiter.maxRequests - validRequests.length);\n}\n\n/**\n * Reset rate limit for a key\n * @param limiter - Rate limiter instance\n * @param key - Unique key to reset\n */\nexport function resetRateLimit(limiter: RateLimiter, key: string): void {\n limiter.requests.delete(key);\n}\n\n/**\n * Default rate limiter for identity verification\n * 5 requests per minute\n */\nexport const identityVerificationLimiter = createRateLimiter(5, 60000);\n","/**\n * DNS Identity Verification\n * Verifies that a user controls a DNS domain\n */\n\nimport { createLogger } from '../utils/logger';\n\nconst log = createLogger('identity-verification/dns');\n\n/** Public-internet check. Blocks literal private/loopback/link-local hosts\n * from being reached via the well-known file verifier — otherwise a caller\n * running this server-side is an SSRF primitive (cloud metadata, internal\n * services, etc.). We don't do full DNS resolution here — TLD/label shape\n * checks + literal-IP rejection are the cheap layers. Production verifiers\n * running this untrusted should add DNS-pinning on top.\n */\nconst PRIVATE_HOST_RE =\n /^(?:localhost|.*\\.local|.*\\.internal|.*\\.localhost|.*\\.lan|.*\\.home|.*\\.arpa|\\[?::1\\]?|\\[?::\\]?)$/i;\nconst PRIVATE_IPV4_RE =\n /^(?:10\\.|127\\.|169\\.254\\.|192\\.168\\.|172\\.(?:1[6-9]|2\\d|3[01])\\.|0\\.|100\\.(?:6[4-9]|[7-9]\\d|1[01]\\d|12[0-7])\\.|22[4-9]\\.|23\\d\\.|24\\d\\.|25[0-5]\\.)/;\n\n/** Tight fetch deadline so a slow target can't stall the verifier. */\nconst WELL_KNOWN_TIMEOUT_MS = 5_000;\n\nfunction isSafePublicHost(host: string): boolean {\n const h = host.toLowerCase();\n if (PRIVATE_HOST_RE.test(h)) return false;\n if (PRIVATE_IPV4_RE.test(h)) return false;\n // IPv6 literal — we don't enumerate every private range; reject bracketed\n // literals entirely (no legitimate verification target is an IPv6 literal).\n if (h.startsWith('[') || /^[0-9a-f:]+$/.test(h)) return false;\n return true;\n}\n\n/**\n * Verification result for DNS identity\n */\nexport interface DnsVerificationResult {\n verified: boolean;\n method?: 'well-known' | 'dns-txt';\n url?: string;\n error?: string;\n}\n\n/**\n * Verify that a user controls a DNS domain\n *\n * Verification methods (in order of preference):\n * 1. Check .well-known/orangecheck.txt file\n * 2. Check DNS TXT record (requires server-side DNS lookup)\n *\n * @param attestationId - The attestation ID to look for\n * @param domain - The domain name (without protocol)\n * @returns Verification result\n */\nexport async function verifyDnsIdentity(\n attestationId: string,\n domain: string\n): Promise<DnsVerificationResult> {\n log.info({ attestationId, domain }, 'Verifying DNS identity');\n\n // Clean domain (remove protocol if present)\n const cleanDomain = domain.replace(/^https?:\\/\\//, '').replace(/\\/$/, '');\n\n // Shape + SSRF guards before we ever hand this to fetch().\n if (!isValidDomain(cleanDomain)) {\n return { verified: false, error: `invalid domain format: ${cleanDomain}` };\n }\n if (!isSafePublicHost(cleanDomain)) {\n return { verified: false, error: 'domain resolves to a disallowed private host' };\n }\n\n // Try .well-known file first\n const wellKnownResult = await checkWellKnownFile(attestationId, cleanDomain);\n if (wellKnownResult.verified) {\n return wellKnownResult;\n }\n\n // DNS TXT record check requires server-side implementation\n // For now, return instructions\n log.info({ domain: cleanDomain }, 'Well-known file not found, DNS TXT check not implemented');\n\n return {\n verified: false,\n error: 'Verification file not found. Please create .well-known/orangecheck.txt',\n };\n}\n\n/**\n * Check .well-known/orangecheck.txt file\n */\nasync function checkWellKnownFile(\n attestationId: string,\n domain: string\n): Promise<DnsVerificationResult> {\n // HTTPS only. The old HTTP fallback meant a MITM / hostile network could\n // forge a passing verification; dropping it costs us nothing — any real\n // domain worth attesting to has TLS in 2026.\n const url = `https://${domain}/.well-known/orangecheck.txt`;\n\n try {\n log.info({ url }, 'Checking well-known file');\n\n const response = await fetch(url, {\n method: 'GET',\n headers: { Accept: 'text/plain' },\n // Don't follow redirects to other domains\n redirect: 'manual',\n signal: AbortSignal.timeout(WELL_KNOWN_TIMEOUT_MS),\n });\n\n if (response.ok) {\n const content = await response.text();\n\n if (content.includes(attestationId)) {\n log.info({ domain, url }, 'Found attestation ID in well-known file');\n return {\n verified: true,\n method: 'well-known',\n url,\n };\n } else {\n log.info({ domain, url }, 'Well-known file exists but no attestation ID found');\n }\n }\n } catch (err) {\n log.warn({ error: err, url }, 'Failed to fetch well-known file');\n }\n\n return {\n verified: false,\n error: 'Well-known file not found or does not contain attestation ID',\n };\n}\n\n/**\n * Get verification instructions for DNS identity\n */\nexport function getDnsVerificationInstructions(attestationId: string, domain: string): string {\n const cleanDomain = domain.replace(/^https?:\\/\\//, '').replace(/\\/$/, '');\n\n return `To verify your DNS domain (${cleanDomain}):\n\n**Method 1: .well-known file (Recommended)**\n\n1. Create a file at: https://${cleanDomain}/.well-known/orangecheck.txt\n2. Add this content to the file:\n\n OrangeCheck Attestation Verification\n Domain: ${cleanDomain}\n Attestation ID: ${attestationId}\n Timestamp: ${new Date().toISOString()}\n\n3. Make sure the file is publicly accessible\n4. Return here and click \"Verify\"\n\n**Method 2: DNS TXT record (Advanced)**\n\n1. Add a TXT record to your DNS:\n Name: _orangecheck.${cleanDomain}\n Value: ${attestationId}\n\n2. Wait for DNS propagation (up to 24 hours)\n3. Return here and click \"Verify\"\n\nNote: Method 1 is faster and easier to set up.`;\n}\n\n/**\n * Generate well-known file content\n */\nexport function generateWellKnownContent(attestationId: string, domain: string): string {\n const cleanDomain = domain.replace(/^https?:\\/\\//, '').replace(/\\/$/, '');\n\n return `OrangeCheck Attestation Verification\n=====================================\n\nDomain: ${cleanDomain}\nAttestation ID: ${attestationId}\nTimestamp: ${new Date().toISOString()}\n\nThis file verifies that the owner of ${cleanDomain} controls the Bitcoin\naddress associated with attestation ${attestationId}.\n\nLearn more: https://ochk.io\n\n---\n\nVerification method: .well-known/orangecheck.txt\nProtocol: OrangeCheck Protocol (OCP)\n`;\n}\n\n/**\n * Get the expected well-known file URL\n */\nexport function getWellKnownUrl(domain: string): string {\n const cleanDomain = domain.replace(/^https?:\\/\\//, '').replace(/\\/$/, '');\n return `https://${cleanDomain}/.well-known/orangecheck.txt`;\n}\n\n/**\n * Validate domain format\n */\nexport function isValidDomain(domain: string): boolean {\n const cleanDomain = domain.replace(/^https?:\\/\\//, '').replace(/\\/$/, '');\n\n // Basic domain validation\n const domainPattern = /^[a-z0-9]+([\\-\\.]{1}[a-z0-9]+)*\\.[a-z]{2,}$/i;\n return domainPattern.test(cleanDomain);\n}\n\n/**\n * Check if a DNS identity is already verified\n * This is a quick check using cached data\n */\nexport function isDnsIdentityVerified(\n attestationId: string,\n _domain: string,\n cachedContent?: string\n): boolean {\n if (!cachedContent) {\n return false;\n }\n\n return cachedContent.includes(attestationId);\n}\n","/**\n * GitHub Identity Verification\n * Verifies that a user controls a GitHub identity by checking for gists\n */\n\nimport { createLogger } from '../utils/logger';\n\nconst log = createLogger('identity-verification/github');\n\n/**\n * Gist file bodies are fetched from `raw_url`. GitHub serves these from\n * `gist.githubusercontent.com`, but `raw_url` is *server-controlled* — a\n * malicious response could point it anywhere (internal IPs, 169.254.169.254,\n * file://, etc.) and our verifier would happily fetch it. Allow-list the\n * expected host to close the SSRF door.\n */\nconst GITHUB_GIST_RAW_HOST = 'gist.githubusercontent.com';\n\n/** Cap fan-out so a user with 1k gists × many files can't pin the verifier. */\nconst MAX_GISTS_SCANNED = 30;\nconst MAX_FILES_PER_GIST = 10;\n\n/** Tight per-request deadline. Github is usually under 300ms. */\nconst FETCH_TIMEOUT_MS = 5_000;\n\n/** Reject usernames that don't match GitHub's published allowed character set\n * before we interpolate them into a URL. */\nconst GITHUB_USERNAME_RE = /^[a-zA-Z0-9](?:[a-zA-Z0-9]|-(?=[a-zA-Z0-9])){0,38}$/;\n\nfunction isSafeGistRawUrl(raw: string): boolean {\n try {\n const u = new URL(raw);\n return u.protocol === 'https:' && u.hostname === GITHUB_GIST_RAW_HOST;\n } catch {\n return false;\n }\n}\n\n/**\n * Verification result for GitHub identity\n */\nexport interface GitHubVerificationResult {\n verified: boolean;\n gistUrl?: string;\n gistId?: string;\n error?: string;\n}\n\n/**\n * GitHub gist file structure\n */\ninterface GitHubGistFile {\n filename: string;\n type: string;\n language: string | null;\n raw_url: string;\n size: number;\n content?: string;\n}\n\n/**\n * GitHub gist structure\n */\ninterface GitHubGist {\n id: string;\n html_url: string;\n description: string;\n public: boolean;\n created_at: string;\n updated_at: string;\n files: Record<string, GitHubGistFile>;\n}\n\n/**\n * Verify that a user controls a GitHub identity\n *\n * Verification method:\n * 1. Query GitHub API for user's public gists\n * 2. Check if any gist file contains the attestation ID\n * 3. Return the gist URL as proof\n *\n * @param attestationId - The attestation ID to look for\n * @param username - The GitHub username\n * @returns Verification result with gist URL if verified\n */\nexport async function verifyGitHubIdentity(\n attestationId: string,\n username: string\n): Promise<GitHubVerificationResult> {\n log.info({ attestationId, username }, 'Verifying GitHub identity');\n\n if (!GITHUB_USERNAME_RE.test(username)) {\n return { verified: false, error: 'invalid GitHub username format' };\n }\n\n try {\n // Query GitHub API for user's gists\n const response = await fetch(\n `https://api.github.com/users/${encodeURIComponent(username)}/gists?per_page=${MAX_GISTS_SCANNED}`,\n {\n headers: { Accept: 'application/vnd.github.v3+json' },\n signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),\n }\n );\n\n if (!response.ok) {\n if (response.status === 404) {\n return {\n verified: false,\n error: `GitHub user '${username}' not found`,\n };\n }\n\n return {\n verified: false,\n error: `GitHub API error: ${response.status} ${response.statusText}`,\n };\n }\n\n const gists = (await response.json()) as GitHubGist[];\n\n log.info({ username, gistCount: gists.length }, 'Fetched GitHub gists');\n\n // Check each gist for attestation ID (capped fan-out)\n for (const gist of gists.slice(0, MAX_GISTS_SCANNED)) {\n // Check gist description\n if (gist.description?.includes(attestationId)) {\n log.info({ username, gistId: gist.id }, 'Found attestation ID in gist description');\n return {\n verified: true,\n gistUrl: gist.html_url,\n gistId: gist.id,\n };\n }\n\n // Check each file in the gist (capped)\n const files = Object.entries(gist.files).slice(0, MAX_FILES_PER_GIST);\n for (const [filename, file] of files) {\n // If content is available, check it\n if (file.content && file.content.includes(attestationId)) {\n log.info(\n { username, gistId: gist.id, filename },\n 'Found attestation ID in gist file'\n );\n return {\n verified: true,\n gistUrl: gist.html_url,\n gistId: gist.id,\n };\n }\n\n // If content not available, fetch it from raw_url — but only\n // if raw_url is a real GitHub-hosted URL. Without the allow-list\n // we're an SSRF primitive for anyone controlling the API\n // response (including via a compromised GitHub mirror / MITM).\n if (!isSafeGistRawUrl(file.raw_url)) {\n log.warn(\n { filename, rawUrl: file.raw_url },\n 'skipping gist file: raw_url failed allow-list'\n );\n continue;\n }\n\n try {\n const fileResponse = await fetch(file.raw_url, {\n signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),\n });\n if (fileResponse.ok) {\n const content = await fileResponse.text();\n if (content.includes(attestationId)) {\n log.info(\n { username, gistId: gist.id, filename },\n 'Found attestation ID in gist file (fetched)'\n );\n return {\n verified: true,\n gistUrl: gist.html_url,\n gistId: gist.id,\n };\n }\n }\n } catch (err) {\n log.warn({ error: err, filename }, 'Failed to fetch gist file content');\n }\n }\n }\n\n log.info({ username }, 'No verification gist found');\n return {\n verified: false,\n error: 'No gist found containing the attestation ID',\n };\n } catch (err) {\n log.error({ error: err, username }, 'Failed to verify GitHub identity');\n return {\n verified: false,\n error: err instanceof Error ? err.message : 'Unknown error',\n };\n }\n}\n\n/**\n * Get verification instructions for GitHub identity\n */\nexport function getGitHubVerificationInstructions(attestationId: string): string {\n return `To verify your GitHub identity:\n\n1. Go to https://gist.github.com\n2. Create a new public gist\n3. Add a file with any name (e.g., \"orangecheck.txt\")\n4. Paste this text into the file:\n\n OrangeCheck Attestation Verification\n Attestation ID: ${attestationId}\n\n5. Click \"Create public gist\"\n6. Return here and click \"Verify\" to check\n\nThe verification will search your public gists for this attestation ID.`;\n}\n\n/**\n * Generate a gist template for verification\n */\nexport function generateGistTemplate(attestationId: string, username: string): string {\n return `# OrangeCheck Attestation Verification\n\nI am verifying my GitHub identity (@${username}) for OrangeCheck.\n\n**Attestation ID:** \\`${attestationId}\\`\n\n**Timestamp:** ${new Date().toISOString()}\n\nThis gist proves that I control both:\n- GitHub account: @${username}\n- Bitcoin address associated with attestation ${attestationId}\n\n---\n\nLearn more about OrangeCheck: https://ochk.io\n`;\n}\n\n/**\n * Check if a GitHub identity is already verified\n * This is a quick check using cached gist data\n */\nexport function isGitHubIdentityVerified(\n attestationId: string,\n _username: string,\n cachedGists: GitHubGist[]\n): boolean {\n return cachedGists.some((gist) => {\n // Check description\n if (gist.description?.includes(attestationId)) {\n return true;\n }\n\n // Check files\n return Object.values(gist.files).some((file) => file.content?.includes(attestationId));\n });\n}\n\n/**\n * Get direct link to create a verification gist. The args are accepted for\n * API parity with other identity providers but unused — GitHub doesn't accept\n * pre-fill params on the gist creation page.\n */\nexport function getGistCreationUrl(): string {\n return 'https://gist.github.com/';\n}\n","/**\n * Nostr Identity Verification\n * Verifies that a user controls a Nostr identity by checking for proof events\n *\n * Two previous bugs in this file made verification a lie:\n * 1. `npubToHex` returned the bech32 string unchanged when given an npub\n * (only the already-hex branch worked). Downstream authors filters used\n * \"npub1…\" as a literal Nostr pubkey, which no relay indexes — so the\n * search *always* returned zero events and fell through to \"no proof\".\n * Benign false-negative, except combined with (2).\n * 2. `verifyNostrEventSignature` returned `true` for any event with a\n * 128-char-hex-looking `sig`. No actual schnorr check. An attacker\n * could publish a note from any pubkey, drop someone else's attestation\n * ID into its content, and the verifier would accept.\n *\n * Fixed by decoding npubs with @scure/base's bech32 and verifying the event\n * signature with @noble/curves' schnorr over sha256(id-preimage).\n */\n\nimport type { NostrEvent } from '../types';\n\nimport { schnorr } from '@noble/curves/secp256k1.js';\nimport { sha256 } from '@noble/hashes/sha2.js';\nimport { bech32 } from '@scure/base';\n\nimport { DEFAULT_RELAYS } from '../nostr';\nimport { createLogger } from '../utils/logger';\n\nconst log = createLogger('identity-verification/nostr');\n\nconst HEX_64_RE = /^[0-9a-f]{64}$/;\n\nfunction toHex(bytes: Uint8Array): string {\n let out = '';\n for (const b of bytes) out += b.toString(16).padStart(2, '0');\n return out;\n}\n\nfunction fromHex(hex: string): Uint8Array {\n if (hex.length % 2 !== 0) throw new Error('odd-length hex');\n const out = new Uint8Array(hex.length / 2);\n for (let i = 0; i < out.length; i++) {\n out[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);\n }\n return out;\n}\n\n/**\n * Verification result for Nostr identity\n */\nexport interface NostrVerificationResult {\n verified: boolean;\n event?: NostrEvent;\n error?: string;\n}\n\n/**\n * Decode a Nostr public key in `npub1…` bech32 form (or pass through if\n * already 64-char hex). Throws on invalid input — callers should treat a\n * throw as \"not a valid npub\" and fail closed.\n */\nfunction npubToHex(npub: string): string {\n const trimmed = npub.trim();\n if (HEX_64_RE.test(trimmed.toLowerCase())) {\n return trimmed.toLowerCase();\n }\n if (!trimmed.toLowerCase().startsWith('npub1')) {\n throw new Error(`not an npub: ${trimmed.slice(0, 12)}…`);\n }\n // `@scure/base` bech32 decoder; unlimited length is fine for NIP-19.\n const decoded = bech32.decode(trimmed.toLowerCase() as `${string}1${string}`, 1023);\n if (decoded.prefix !== 'npub') {\n throw new Error(`bech32 prefix mismatch: expected npub, got ${decoded.prefix}`);\n }\n const bytes = bech32.fromWords(decoded.words);\n if (bytes.length !== 32) {\n throw new Error(`invalid npub payload length: ${bytes.length}`);\n }\n return toHex(Uint8Array.from(bytes));\n}\n\n/**\n * Query Nostr relays for events from a specific author\n */\nasync function queryNostrEvents(options: {\n authors: string[];\n kinds: number[];\n search?: string;\n relays?: string[];\n limit?: number;\n}): Promise<NostrEvent[]> {\n const { authors, kinds, search, relays = DEFAULT_RELAYS, limit = 100 } = options;\n const events: NostrEvent[] = [];\n\n log.info({ authors, kinds, relayCount: relays.length }, 'Querying Nostr for events');\n\n const queryPromises = relays.map(async (relayUrl) => {\n let ws: WebSocket | null = null;\n\n try {\n ws = new WebSocket(relayUrl);\n const wsRef = ws;\n\n await new Promise<void>((resolve, reject) => {\n const timeout = setTimeout(() => {\n wsRef.close();\n reject(new Error('Query timeout'));\n }, 10000);\n\n const cleanup = () => {\n clearTimeout(timeout);\n wsRef.close();\n };\n\n wsRef.onopen = () => {\n const subscriptionId = `verify_${Date.now()}`;\n const filter: Record<string, unknown> = {\n authors,\n kinds,\n limit,\n };\n\n wsRef.send(JSON.stringify(['REQ', subscriptionId, filter]));\n };\n\n wsRef.onmessage = (msg) => {\n try {\n const data = JSON.parse(msg.data);\n if (data[0] === 'EVENT') {\n const event = data[2] as NostrEvent;\n\n // If search term provided, filter by content\n if (search) {\n if (event.content.includes(search)) {\n events.push(event);\n }\n } else {\n events.push(event);\n }\n } else if (data[0] === 'EOSE') {\n cleanup();\n resolve();\n }\n } catch (err) {\n log.error({ relay: relayUrl, error: err }, 'Failed to parse event');\n }\n };\n\n wsRef.onerror = (err) => {\n log.error({ relay: relayUrl, error: err }, 'WebSocket error during query');\n cleanup();\n reject(err);\n };\n\n wsRef.onclose = () => {\n clearTimeout(timeout);\n };\n });\n } catch (err) {\n log.error({ relay: relayUrl, error: err }, 'Failed to query relay');\n } finally {\n if (ws && ws.readyState !== WebSocket.CLOSED) {\n ws.close();\n }\n }\n });\n\n await Promise.allSettled(queryPromises);\n\n log.info({ eventCount: events.length }, 'Query complete');\n\n return events;\n}\n\n/**\n * Verify a Nostr event's schnorr signature per NIP-01:\n *\n * id = sha256(JSON.stringify([0, pubkey, created_at, kind, tags, content]))\n * sig = schnorr_sign(id, secret_key)\n * check = schnorr_verify(id, pubkey, sig)\n *\n * Fails closed on any shape problem, decoding error, or mismatch. A true\n * return from this function is the ONLY thing that should be treated as\n * proof the event really came from the claimed pubkey.\n */\nasync function verifyNostrEventSignature(event: NostrEvent): Promise<boolean> {\n try {\n if (\n !event.id ||\n !event.sig ||\n !event.pubkey ||\n typeof event.id !== 'string' ||\n typeof event.sig !== 'string' ||\n typeof event.pubkey !== 'string' ||\n event.sig.length !== 128 ||\n !HEX_64_RE.test(event.id) ||\n !HEX_64_RE.test(event.pubkey)\n ) {\n return false;\n }\n\n // Recompute the event id from the canonical NIP-01 preimage. If the\n // relay (or an attacker) altered any field since signing, id won't\n // match and we reject.\n const preimage = JSON.stringify([\n 0,\n event.pubkey,\n event.created_at,\n event.kind,\n event.tags ?? [],\n event.content ?? '',\n ]);\n const computedId = toHex(sha256(new TextEncoder().encode(preimage)));\n if (computedId !== event.id.toLowerCase()) {\n log.warn(\n { eventId: event.id, computedId },\n 'nostr event id does not match its content'\n );\n return false;\n }\n\n return schnorr.verify(fromHex(event.sig), fromHex(event.id), fromHex(event.pubkey));\n } catch (err) {\n log.warn({ err }, 'schnorr verify threw');\n return false;\n }\n}\n\n/**\n * Verify that a user controls a Nostr identity\n *\n * Verification method:\n * 1. Query Nostr relays for kind 1 (text note) events from the claimed npub\n * 2. Check if any event content contains the attestation ID\n * 3. Verify the event signature\n *\n * @param attestationId - The attestation ID to look for\n * @param npub - The Nostr public key (npub format or hex)\n * @param relays - Optional list of relays to query\n * @returns Verification result with proof event if verified\n */\nexport async function verifyNostrIdentity(\n attestationId: string,\n npub: string,\n relays?: string[]\n): Promise<NostrVerificationResult> {\n log.info({ attestationId, npub }, 'Verifying Nostr identity');\n\n try {\n // Convert npub to hex if needed\n const pubkeyHex = npubToHex(npub);\n\n // Query Nostr for kind 1 events from this pubkey containing attestation ID\n const events = await queryNostrEvents({\n authors: [pubkeyHex],\n kinds: [1], // Text notes\n search: attestationId,\n relays,\n });\n\n if (events.length === 0) {\n log.info({ npub }, 'No verification events found');\n return {\n verified: false,\n error: 'No verification event found. User must post a note containing the attestation ID.',\n };\n }\n\n // Check each event for attestation ID and verify signature\n for (const event of events) {\n if (event.content.includes(attestationId)) {\n // Verify event signature\n const isValid = await verifyNostrEventSignature(event);\n\n if (isValid) {\n log.info({ npub, eventId: event.id }, 'Nostr identity verified');\n return {\n verified: true,\n event,\n };\n } else {\n log.warn({ npub, eventId: event.id }, 'Invalid event signature');\n }\n }\n }\n\n return {\n verified: false,\n error: 'Found events but none had valid signatures',\n };\n } catch (err) {\n log.error({ error: err, npub }, 'Failed to verify Nostr identity');\n return {\n verified: false,\n error: err instanceof Error ? err.message : 'Unknown error',\n };\n }\n}\n\n/**\n * Get verification instructions for Nostr identity\n */\nexport function getNostrVerificationInstructions(attestationId: string): string {\n return `To verify your Nostr identity:\n\n1. Open your Nostr client (Damus, Amethyst, Primal, etc.)\n2. Post a note containing this text:\n\n Verifying my OrangeCheck attestation: ${attestationId}\n\n3. Wait a few seconds for the note to propagate to relays\n4. Return here and click \"Verify\" to check\n\nThe verification will search Nostr relays for your note and confirm you control this identity.`;\n}\n\n/**\n * Check if a Nostr identity is already verified\n * This is a quick check that doesn't re-query relays\n */\nexport function isNostrIdentityVerified(\n attestationId: string,\n npub: string,\n cachedEvents: NostrEvent[]\n): boolean {\n const pubkeyHex = npubToHex(npub);\n\n return cachedEvents.some(\n (event) =>\n event.pubkey === pubkeyHex && event.kind === 1 && event.content.includes(attestationId)\n );\n}\n","/**\n * Twitter Identity Verification\n * Verifies that a user controls a Twitter identity\n *\n * Note: Twitter API requires authentication and has rate limits.\n * This implementation uses manual verification where the user provides a tweet URL.\n */\n\nimport { createLogger } from '../utils/logger';\n\nconst log = createLogger('identity-verification/twitter');\n\n/**\n * Verification result for Twitter identity\n */\nexport interface TwitterVerificationResult {\n verified: boolean;\n tweetUrl?: string;\n tweetId?: string;\n error?: string;\n}\n\n/**\n * Verify Twitter identity via manual tweet URL\n *\n * @param attestationId - The attestation ID to look for\n * @param handle - The Twitter handle (with or without @)\n * @param tweetUrl - Optional tweet URL provided by user\n * @returns Verification result\n */\nexport async function verifyTwitterIdentity(\n attestationId: string,\n handle: string,\n tweetUrl?: string\n): Promise<TwitterVerificationResult> {\n log.info({ attestationId, handle, tweetUrl }, 'Verifying Twitter identity');\n\n if (!tweetUrl) {\n return {\n verified: false,\n error: 'Tweet URL required for verification',\n };\n }\n\n try {\n // Extract tweet ID from URL\n const tweetId = extractTweetId(tweetUrl);\n\n if (!tweetId) {\n return {\n verified: false,\n error: 'Invalid tweet URL format',\n };\n }\n\n // For now, we can't verify without Twitter API access\n // Return instructions for manual verification\n log.info({ handle, tweetId }, 'Manual verification required');\n\n return {\n verified: false,\n tweetUrl,\n tweetId,\n error: 'Automatic verification not available. Please verify manually by checking the tweet.',\n };\n } catch (err) {\n log.error({ error: err, handle }, 'Failed to verify Twitter identity');\n return {\n verified: false,\n error: err instanceof Error ? err.message : 'Unknown error',\n };\n }\n}\n\n/**\n * Extract tweet ID from various Twitter URL formats\n */\nfunction extractTweetId(url: string): string | null {\n // Support various Twitter URL formats:\n // https://twitter.com/username/status/1234567890\n // https://x.com/username/status/1234567890\n // https://mobile.twitter.com/username/status/1234567890\n\n const patterns = [\n /(?:twitter\\.com|x\\.com)\\/\\w+\\/status\\/(\\d+)/,\n /(?:mobile\\.twitter\\.com)\\/\\w+\\/status\\/(\\d+)/,\n ];\n\n for (const pattern of patterns) {\n const match = url.match(pattern);\n if (match && match[1]) {\n return match[1];\n }\n }\n\n return null;\n}\n\n/**\n * Get verification instructions for Twitter identity\n */\nexport function getTwitterVerificationInstructions(attestationId: string, handle: string): string {\n const cleanHandle = handle.startsWith('@') ? handle.slice(1) : handle;\n\n return `To verify your Twitter identity (@${cleanHandle}):\n\n1. Go to https://twitter.com/compose/tweet\n2. Post a tweet with this text:\n\n Verifying my OrangeCheck attestation: ${attestationId}\n\n3. After posting, copy the tweet URL\n4. Paste the URL below and click \"Verify\"\n\nExample tweet URL:\nhttps://twitter.com/${cleanHandle}/status/1234567890\n\nThe verification will check that the tweet exists and contains the attestation ID.`;\n}\n\n/**\n * Generate tweet text for verification\n */\nexport function generateTweetText(attestationId: string): string {\n return `Verifying my OrangeCheck attestation: ${attestationId}\n\nProving Bitcoin reputation with cryptographic signatures.\n\n#OrangeCheck #Bitcoin`;\n}\n\n/**\n * Get direct link to compose a verification tweet\n */\nexport function getTwitterComposeUrl(attestationId: string): string {\n const text = generateTweetText(attestationId);\n const encoded = encodeURIComponent(text);\n\n return `https://twitter.com/intent/tweet?text=${encoded}`;\n}\n\n/**\n * Validate tweet URL format\n */\nexport function isValidTweetUrl(url: string): boolean {\n return extractTweetId(url) !== null;\n}\n\n/**\n * Get tweet URL from handle and tweet ID\n */\nexport function getTweetUrl(handle: string, tweetId: string): string {\n const cleanHandle = handle.startsWith('@') ? handle.slice(1) : handle;\n return `https://twitter.com/${cleanHandle}/status/${tweetId}`;\n}\n\n/**\n * Manual verification helper\n * Returns instructions for verifier to manually check the tweet\n */\nexport function getManualVerificationInstructions(\n attestationId: string,\n handle: string,\n tweetUrl: string\n): string {\n return `Manual Verification Steps:\n\n1. Open this tweet: ${tweetUrl}\n2. Verify it's posted by @${handle}\n3. Check that the tweet contains: ${attestationId}\n4. Confirm the tweet is public and not deleted\n\nIf all checks pass, the identity is verified.`;\n}\n","import type { IdentityBinding } from '../types';\nimport type { DnsVerificationResult } from './dns';\nimport type { GitHubVerificationResult } from './github';\nimport type { NostrVerificationResult } from './nostr';\nimport type { TwitterVerificationResult } from './twitter';\n\nimport { logVerificationError } from '../utils/logger';\nimport { enforceRateLimit, identityVerificationLimiter } from '../utils/rate-limiter';\nimport { getDnsVerificationInstructions, verifyDnsIdentity } from './dns';\nimport { getGitHubVerificationInstructions, verifyGitHubIdentity } from './github';\nimport { getNostrVerificationInstructions, verifyNostrIdentity } from './nostr';\nimport { getTwitterVerificationInstructions, verifyTwitterIdentity } from './twitter';\n\n/**\n * Identity Verification\n *\n * Unified API for verifying identity bindings across multiple protocols\n */\n\nexport * from './nostr';\nexport * from './github';\nexport * from './twitter';\nexport * from './dns';\n\n/**\n * Unified verification result across all protocols\n */\nexport type VerificationResult =\n | NostrVerificationResult\n | GitHubVerificationResult\n | TwitterVerificationResult\n | DnsVerificationResult;\n\n/**\n * Options for identity verification\n */\nexport interface VerifyIdentityOptions {\n /** Tweet URL for Twitter verification */\n tweetUrl?: string;\n /** Relay URLs for Nostr verification */\n relays?: string[];\n}\n\n/**\n * Verify an identity binding\n *\n * @param attestationId - The attestation ID to verify against\n * @param identity - The identity binding to verify\n * @param options - Protocol-specific verification options\n * @returns Verification result with verified status and optional error\n *\n * @example\n * ```typescript\n * const result = await verifyIdentity(\n * 'abc123...',\n * { protocol: 'nostr', identifier: 'npub1...' },\n * { relays: ['wss://relay.damus.io'] }\n * );\n *\n * if (result.verified) {\n * console.log('Identity verified!');\n * }\n * ```\n */\nexport async function verifyIdentity(\n attestationId: string,\n identity: IdentityBinding,\n options?: VerifyIdentityOptions\n): Promise<VerificationResult> {\n const { protocol, identifier } = identity;\n\n // Rate limiting: 5 requests per minute per identity\n const rateLimitKey = `${protocol}:${identifier}`;\n try {\n enforceRateLimit(identityVerificationLimiter, rateLimitKey);\n } catch (err) {\n return {\n verified: false,\n error: err instanceof Error ? err.message : 'Rate limit exceeded',\n };\n }\n\n try {\n switch (protocol) {\n case 'nostr':\n return await verifyNostrIdentity(attestationId, identifier, options?.relays);\n\n case 'github':\n return await verifyGitHubIdentity(attestationId, identifier);\n\n case 'twitter':\n return await verifyTwitterIdentity(attestationId, identifier, options?.tweetUrl);\n\n case 'dns':\n return await verifyDnsIdentity(attestationId, identifier);\n\n case 'email':\n // Email verification not implemented yet\n return {\n verified: false,\n error: 'Email verification not implemented',\n };\n\n case 'web':\n // Web verification similar to DNS\n return await verifyDnsIdentity(attestationId, identifier);\n\n case 'did':\n // DID verification not implemented yet\n return {\n verified: false,\n error: 'DID verification not implemented',\n };\n\n default:\n return {\n verified: false,\n error: `Unknown protocol: ${protocol}`,\n };\n }\n } catch (error) {\n // Log error\n logVerificationError(\n protocol,\n identifier,\n error instanceof Error ? error : new Error(String(error)),\n {\n attestationId,\n }\n );\n\n return {\n verified: false,\n error: error instanceof Error ? error.message : 'Verification failed',\n };\n }\n}\n\n/**\n * Get verification instructions for an identity\n */\nexport function getVerificationInstructions(\n attestationId: string,\n identity: IdentityBinding\n): string {\n const { protocol, identifier } = identity;\n\n switch (protocol) {\n case 'nostr':\n return getNostrVerificationInstructions(attestationId);\n\n case 'github':\n return getGitHubVerificationInstructions(attestationId);\n\n case 'twitter':\n return getTwitterVerificationInstructions(attestationId, identifier);\n\n case 'dns':\n return getDnsVerificationInstructions(attestationId, identifier);\n\n case 'email':\n return `Email verification not implemented yet.`;\n\n case 'web':\n return getDnsVerificationInstructions(attestationId, identifier);\n\n case 'did':\n return `DID verification not implemented yet.`;\n\n default:\n return `Unknown protocol: ${protocol}`;\n }\n}\n\n/**\n * Check if a protocol supports automatic verification\n */\nexport function supportsAutomaticVerification(protocol: string): boolean {\n return ['nostr', 'github', 'dns', 'web'].includes(protocol);\n}\n\n/**\n * Check if a protocol requires manual verification\n */\nexport function requiresManualVerification(protocol: string): boolean {\n return ['twitter', 'email'].includes(protocol);\n}\n\n/**\n * Get verification status for multiple identities\n */\nexport async function verifyAllIdentities(\n attestationId: string,\n identities: IdentityBinding[],\n options?: {\n tweetUrls?: Record<string, string>; // Map of identifier -> tweet URL\n relays?: string[];\n }\n): Promise<Map<string, VerificationResult>> {\n const results = new Map<string, VerificationResult>();\n\n await Promise.all(\n identities.map(async (identity) => {\n const key = `${identity.protocol}:${identity.identifier}`;\n const tweetUrl = options?.tweetUrls?.[identity.identifier];\n\n const result = await verifyIdentity(attestationId, identity, {\n tweetUrl,\n relays: options?.relays,\n });\n\n results.set(key, result);\n })\n );\n\n return results;\n}\n\n/**\n * Get summary of verification results\n */\nexport function getVerificationSummary(results: Map<string, VerificationResult>): {\n total: number;\n verified: number;\n failed: number;\n pending: number;\n} {\n let verified = 0;\n let failed = 0;\n let pending = 0;\n\n for (const result of results.values()) {\n if (result.verified) {\n verified++;\n } else if (result.error?.includes('not implemented')) {\n pending++;\n } else {\n failed++;\n }\n }\n\n return {\n total: results.size,\n verified,\n failed,\n pending,\n };\n}\n","import type { StatusCode } from './types';\n\nexport type Severity = 'success' | 'info' | 'warn' | 'error';\n\nexport interface StatusMeta {\n label: string;\n detail?: string;\n severity: Severity;\n}\n\nexport const STATUS_META: Record<StatusCode, StatusMeta> = {\n sig_ok_bip322: {\n label: 'Signature verified',\n detail: 'Your BIP-322 signature is valid and proves ownership of this address.',\n severity: 'success',\n },\n sig_ok_legacy: {\n label: 'Signature verified (legacy)',\n detail: 'Your legacy signature is valid and proves ownership of this address.',\n severity: 'success',\n },\n sig_invalid: {\n label: 'Signature verification failed',\n detail: 'The signature does not match the message and address. Common issues: (1) Message not copied exactly from Step 2, (2) Wrong wallet/address used, (3) Wallet does not support BIP-322 (Electrum does NOT support BIP-322 for SegWit addresses - use Sparrow Wallet instead). For testnet, ensure your wallet is in testnet mode.',\n severity: 'error',\n },\n sig_unsupported_script: {\n label: 'Wallet does not support BIP-322',\n detail: 'Your wallet generated a legacy signature, but your SegWit address (bc1/tb1) requires BIP-322 message signing. Please use a wallet that supports BIP-322 (like Sparrow Wallet or Bitcoin Core), or switch to a P2PKH address (starting with \"1\" for mainnet or \"m\"/\"n\" for testnet) if your wallet only supports legacy signing.',\n severity: 'error',\n },\n bond_confirmed: {\n label: 'Bitcoin bond confirmed',\n detail: 'Found confirmed UTXOs on the blockchain for reputation scoring.',\n severity: 'success',\n },\n bond_zero: {\n label: 'No confirmed bitcoin found',\n detail: 'This address has no confirmed UTXOs. Send some bitcoin to this address and wait for confirmation to establish a reputation score.',\n severity: 'warn',\n },\n bond_pending: {\n label: 'Pending transactions detected',\n detail: 'This address has unconfirmed transactions. Wait for confirmations before they count toward your reputation score.',\n severity: 'info',\n },\n bond_insufficient: {\n label: 'Insufficient bond amount',\n 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.',\n severity: 'error',\n },\n aud_mismatch: {\n label: 'Audience mismatch',\n 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.',\n severity: 'warn',\n },\n expired: {\n label: 'Message expired',\n detail: 'This signature has passed its expiration date. Generate a new signature with a fresh message.',\n severity: 'error',\n },\n network_testmode: {\n label: 'Test network detected',\n detail: 'This signature uses testnet or signet. Test networks are for development only and cannot be verified in production mode.',\n severity: 'warn',\n },\n bad_request: {\n label: 'Verification error',\n detail: 'Unable to verify the signature due to invalid or inconsistent data. Please ensure the address in the message matches the address you entered, and try again.',\n severity: 'error',\n },\n decode_error: {\n label: 'Message format error',\n detail: 'The message could not be parsed. Ensure you copied the complete canonical message from Step 2 without modifications.',\n severity: 'error',\n },\n invalid_scheme: {\n label: 'Unsupported signing method',\n detail: 'The signing scheme is not supported. Please use BIP-322 or legacy Bitcoin message signing.',\n severity: 'error',\n },\n invalid_attestation_id: {\n label: 'Invalid attestation ID',\n detail: 'The attestation ID does not match the message hash. The attestation may have been tampered with.',\n severity: 'error',\n },\n};\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/canonical.ts","../src/utils/logger.ts","../src/nostr.ts","../src/nostr-crypto.ts","../src/attestation.ts","../src/scoring.ts","../src/verify.ts","../src/check.ts","../src/challenge.ts","../src/utils/rate-limiter.ts","../src/identity/dns.ts","../src/identity/github.ts","../src/identity/nostr.ts","../src/identity/twitter.ts","../src/identity/index.ts","../src/messages.ts"],"names":["log","days_unspent","verify","Buffer","Verifier","bitcoinMessage2"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Canonical message builder per SPEC.md §2\n *\n * - LF line endings, exactly one trailing LF\n * - 7 fixed core lines in strict order and wording\n * - Optional extensions appended as key: value with lexicographically sorted lowercase keys\n */\n\nimport type { AttestationEnvelope, IdentityBinding, Scheme } from './types';\n\n/**\n * Input for building a canonical message\n */\nexport interface CanonicalInput {\n /** Bitcoin address */\n address: string;\n /** Optional identity bindings */\n identities?: IdentityBinding[];\n}\n\n/**\n * Extension key-value pairs for canonical message\n */\nexport type Extensions = Record<string, string | undefined>;\n\n/**\n * Convert bytes to lowercase hex string\n * @param bytes - Byte array to convert\n * @returns Lowercase hex string\n */\nfunction toLowerHex(bytes: Uint8Array): string {\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n}\n\n/**\n * Generate a random 16-byte nonce as lowercase hex\n * Uses Web Crypto API when available, falls back to Math.random()\n * @returns 32-character lowercase hex string\n */\nexport function randomNonce16BHexLower(): string {\n const arr = new Uint8Array(16);\n\n try {\n if (typeof crypto !== 'undefined' && typeof crypto.getRandomValues === 'function') {\n crypto.getRandomValues(arr);\n return toLowerHex(arr);\n }\n } catch {\n // Fall through to non-cryptographic fallback\n }\n\n // No silent Math.random fallback: a nonce is a load-bearing security\n // primitive. A deployment without `crypto.getRandomValues` MUST fix its\n // environment rather than sign with weak randomness.\n throw new Error('crypto.getRandomValues unavailable — refusing to mint a weak nonce');\n}\n\n/**\n * Reject characters that would break the line-oriented canonical grammar\n * or the comma-separated identities list. If any of these slipped through,\n * an attacker could smuggle a forged `address:` or extension line into the\n * signed payload: `identities: alice\\naddress: bc1qEVIL…` would parse as a\n * second address line. Catch it at the boundary, not at verification time.\n *\n * Also rejects a colon in the identifier so a bad actor can't turn\n * `github:alice:extra` into a different protocol binding on parse.\n */\nconst IDENTITY_PROTOCOL_RE = /^[a-z][a-z0-9_-]*$/;\nconst IDENTITY_FORBIDDEN_CHARS = /[\\r\\n,]/;\n\nfunction assertSafeIdentity({ protocol, identifier }: IdentityBinding): void {\n if (!IDENTITY_PROTOCOL_RE.test(protocol)) {\n throw new Error(\n `invalid identity protocol: ${JSON.stringify(protocol)} — must match /^[a-z][a-z0-9_-]*$/`\n );\n }\n if (!identifier || IDENTITY_FORBIDDEN_CHARS.test(identifier)) {\n throw new Error(\n `invalid identity identifier: ${JSON.stringify(identifier)} — must be non-empty and contain no newlines or commas`\n );\n }\n}\n\n/**\n * Format identities as comma-separated protocol:identifier pairs, sorted lexicographically\n * @param identities - Array of identity bindings\n * @returns Comma-separated string of protocol:identifier pairs\n */\nexport function formatIdentities(identities: IdentityBinding[] = []): string {\n if (identities.length === 0) {\n return '';\n }\n for (const id of identities) assertSafeIdentity(id);\n\n // Format as protocol:identifier and sort lexicographically\n const formatted = identities\n .map(({ protocol, identifier }) => `${protocol}:${identifier}`)\n .sort();\n\n return formatted.join(',');\n}\n\n/**\n * Parse identities from comma-separated protocol:identifier format\n * @param identitiesStr - Comma-separated identity string\n * @returns Array of identity bindings\n * @throws {Error} If identity format is invalid\n */\nexport function parseIdentities(identitiesStr: string): IdentityBinding[] {\n if (!identitiesStr || identitiesStr.trim() === '') {\n return [];\n }\n // The identities field lives on one line of the canonical message. If it\n // contains a raw LF/CR, it's either corrupt or an attempt to smuggle a\n // fake core line into the parser. Refuse instead of trying to recover.\n if (IDENTITY_FORBIDDEN_CHARS.test(identitiesStr.replace(/,/g, ''))) {\n throw new Error('identities field contains forbidden characters (newline)');\n }\n\n const bindings = identitiesStr.split(',').map((binding) => {\n const colonIndex = binding.indexOf(':');\n if (colonIndex === -1) {\n throw new Error(`Invalid identity binding format: ${binding}`);\n }\n return {\n protocol: binding.substring(0, colonIndex).trim(),\n identifier: binding.substring(colonIndex + 1).trim(),\n };\n });\n\n for (const b of bindings) {\n if (!b.protocol || !b.identifier) {\n throw new Error(`Invalid identity binding: ${b.protocol}:${b.identifier}`);\n }\n assertSafeIdentity(b);\n }\n return bindings;\n}\n\n/**\n * Optional deterministic overrides for message building. Only intended for\n * tests / conformance vectors; production callers should let the builder\n * mint a fresh nonce + timestamp per message.\n */\nexport interface BuildOptions {\n /** 32-char lowercase hex. Default: freshly-generated cryptographic nonce. */\n nonce?: string;\n /** RFC-3339 UTC. Default: `new Date().toISOString()`. */\n issuedAt?: string;\n}\n\n/**\n * Build a canonical message following OrangeCheck Protocol v0 specification\n * @param input - Canonical input with address and identities\n * @param extensions - Optional extension key-value pairs\n * @param options - Optional deterministic overrides (testing only)\n * @returns Canonical message string with LF line endings\n */\nexport function buildCanonicalMessage(\n { address, identities }: CanonicalInput,\n extensions: Extensions = {},\n options: BuildOptions = {}\n): string {\n const nonce = options.nonce ?? randomNonce16BHexLower();\n if (!/^[0-9a-f]{32}$/.test(nonce)) {\n throw new Error(`invalid nonce: must be 32 lowercase hex chars`);\n }\n const issuedAt = options.issuedAt ?? new Date().toISOString();\n\n // Format identities\n const identitiesStr = formatIdentities(identities);\n\n // Core (strict wording + order per SPEC.md §2)\n const core = [\n 'orangecheck',\n `identities: ${identitiesStr}`,\n `address: ${address}`,\n 'purpose: portable reputation attestation (non-custodial)',\n `nonce: ${nonce}`,\n `issued_at: ${issuedAt}`,\n 'ack: I attest control of this address and bind it to my identities.',\n ];\n\n // Normalize and sort extensions\n const normExt: Record<string, string> = {};\n for (const [k, v] of Object.entries(extensions)) {\n if (v == null || v === '') {\n continue;\n }\n const key = k.toLowerCase();\n normExt[key] = String(v);\n }\n\n const extLines = Object.keys(normExt)\n .sort()\n .map((k) => `${k}: ${normExt[k]!}`);\n\n const all = [...core, ...extLines];\n\n // Join with LF and ensure exactly one trailing LF\n return all.join('\\n') + '\\n';\n}\n\n/**\n * Generate attestation ID from canonical message\n *\n * attestation_id = SHA-256(canonical_message)\n *\n * @param message - Canonical message string\n * @returns Lowercase hex SHA-256 hash\n */\nexport async function generateAttestationId(message: string): Promise<string> {\n // Convert message to UTF-8 bytes\n const encoder = new TextEncoder();\n const data = encoder.encode(message);\n\n // Compute SHA-256 hash\n const hashBuffer = await crypto.subtle.digest('SHA-256', data);\n\n // Convert to lowercase hex\n return toLowerHex(new Uint8Array(hashBuffer));\n}\n\n/**\n * Create an attestation envelope for publishing\n *\n * This wraps the canonical message with metadata for Nostr publishing\n *\n * @param message - Canonical message\n * @param signature - BIP-322 or legacy signature\n * @param scheme - Signature scheme used\n * @param address - Bitcoin address\n * @param identities - Identity bindings\n * @param extensions - Optional extensions\n * @returns Attestation envelope ready for publishing\n */\nexport async function createAttestationEnvelope(\n message: string,\n signature: string,\n scheme: Scheme,\n address: string,\n identities: IdentityBinding[],\n extensions: Extensions = {}\n): Promise<AttestationEnvelope> {\n const attestation_id = await generateAttestationId(message);\n\n // Extract issued_at from message\n const issuedAtMatch = message.match(/issued_at: ([^\\n]+)/);\n const issued_at = issuedAtMatch?.[1] ?? new Date().toISOString();\n\n // Extract expires from extensions if present\n const expires_at = extensions.expires;\n\n // Extract relay hints from extensions if present\n const relay_hints = extensions.relay_hints?.split(',').map((r) => r.trim());\n\n // Extract publish targets from extensions if present\n const publish_targets = extensions.publish?.split(',').map((t) => t.trim());\n\n // Base64url encode the message\n const encoder = new TextEncoder();\n const messageBytes = encoder.encode(message);\n const base64 = btoa(String.fromCharCode(...messageBytes));\n const message_b64url = base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\n\n // Construct verification URL\n const verification_url = `https://attest.ochk.io/attest/${attestation_id}`;\n\n return {\n attestation_id,\n scheme,\n address,\n identities,\n message,\n message_b64url,\n signature,\n issued_at,\n expires_at,\n verification_url,\n publish_targets,\n relay_hints,\n };\n}\n","/**\n * Simple logger for SDK\n * Can be disabled in production builds\n */\n\n/**\n * Log level type\n */\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'none';\n\n/**\n * Logger context type\n */\nexport type LogContext = Record<string, unknown>;\n\n/**\n * Logger interface\n */\nexport interface Logger {\n debug: (contextOrMessage: string | LogContext, message?: string) => void;\n info: (contextOrMessage: string | LogContext, message?: string) => void;\n warn: (contextOrMessage: string | LogContext, message?: string) => void;\n error: (contextOrMessage: string | LogContext, message?: string) => void;\n}\n\nlet logLevel: LogLevel = 'none';\n\n/**\n * Set the global log level\n * @param level - Log level to set\n */\nexport function setLogLevel(level: LogLevel): void {\n logLevel = level;\n}\n\n/**\n * Get the current log level\n * @returns Current log level\n */\nexport function getLogLevel(): LogLevel {\n return logLevel;\n}\n\n/**\n * Create a namespaced logger\n * @param namespace - Logger namespace\n * @returns Logger instance\n */\nexport function createLogger(namespace: string): Logger {\n const shouldLog = (level: Exclude<LogLevel, 'none'>): boolean => {\n if (logLevel === 'none') return false;\n\n const levels: Exclude<LogLevel, 'none'>[] = ['debug', 'info', 'warn', 'error'];\n const currentLevelIndex = levels.indexOf(logLevel as Exclude<LogLevel, 'none'>);\n const messageLevelIndex = levels.indexOf(level);\n\n return messageLevelIndex >= currentLevelIndex;\n };\n\n const formatMessage = (msg: string): string => `[${namespace}] ${msg}`;\n\n return {\n debug: (contextOrMessage: string | LogContext, message?: string): void => {\n if (shouldLog('debug')) {\n if (typeof contextOrMessage === 'string') {\n console.debug(formatMessage(contextOrMessage));\n } else {\n console.debug(formatMessage(message ?? 'Debug'), contextOrMessage);\n }\n }\n },\n info: (contextOrMessage: string | LogContext, message?: string): void => {\n if (shouldLog('info')) {\n if (typeof contextOrMessage === 'string') {\n console.info(formatMessage(contextOrMessage));\n } else {\n console.info(formatMessage(message ?? 'Info'), contextOrMessage);\n }\n }\n },\n warn: (contextOrMessage: string | LogContext, message?: string): void => {\n if (shouldLog('warn')) {\n if (typeof contextOrMessage === 'string') {\n console.warn(formatMessage(contextOrMessage));\n } else {\n console.warn(formatMessage(message ?? 'Warning'), contextOrMessage);\n }\n }\n },\n error: (contextOrMessage: string | LogContext, message?: string): void => {\n if (shouldLog('error')) {\n if (typeof contextOrMessage === 'string') {\n console.error(formatMessage(contextOrMessage));\n } else {\n console.error(formatMessage(message ?? 'Error'), contextOrMessage);\n }\n }\n },\n };\n}\n\n/**\n * Log verification error\n * @param protocol - Identity protocol\n * @param identifier - Identity identifier\n * @param error - Error object\n * @param context - Additional context\n */\nexport function logVerificationError(\n protocol: string,\n identifier: string,\n error: Error,\n context?: LogContext\n): void {\n const logger = createLogger('identity-verification');\n logger.error(\n {\n protocol,\n identifier,\n error: error.message,\n stack: error.stack,\n ...context,\n },\n 'Verification failed'\n );\n}\n","/**\n * Nostr Integration for OrangeCheck Protocol\n *\n * Implements NIP-78 (Application-specific data) for attestation publishing\n */\n\nimport type { AttestationEnvelope, IdentityBinding, NostrEvent } from './types';\n\nimport { createLogger } from './utils/logger';\n\nconst log = createLogger('ocp/nostr');\n\n/**\n * NIP-78 event kind for OrangeCheck attestations\n */\nexport const ATTESTATION_EVENT_KIND = 30078;\n\n/**\n * Default Nostr relays for OrangeCheck attestation publishing and lookup.\n *\n * Well-known relays with good uptime, plus the first-party family relay.\n * `relay.ochk.io` was missing here while attest.ochk.io's verifier has always\n * read from it, so the SDK and the reference implementation were looking in\n * different places — the SDK could miss a family attestation that the hosted\n * API found. It runs a kind allowlist (30078–30086) and canonical OC d-tag\n * prefixes, and is always co-published alongside the public relays, never the\n * only copy. See https://github.com/orangecheck/oc-relay-infra.\n *\n * Order matters only for readability; queries fan out to all of them and\n * merge. Pass your own `relays` to any query to override this entirely — the\n * protocol does not require trusting any particular relay.\n */\nexport const DEFAULT_RELAYS: string[] = [\n 'wss://relay.damus.io',\n 'wss://relay.nostr.band',\n 'wss://nos.lol',\n 'wss://relay.snort.social',\n 'wss://relay.ochk.io',\n];\n\n/**\n * Create a NIP-78 event for an OrangeCheck attestation\n *\n * Kind: 30078 (Parameterized Replaceable Event)\n * d-tag: attestation_id (makes it replaceable by attestation ID)\n *\n * @param envelope - Attestation envelope\n * @param pubkey - Nostr public key (hex format)\n * @returns Unsigned Nostr event\n */\nexport function createAttestationEvent(\n envelope: AttestationEnvelope,\n pubkey: string\n): Omit<NostrEvent, 'id' | 'sig'> {\n // NIP-12 relays index SINGLE-LETTER tags only. A multi-letter tag like\n // `address` is stored verbatim and stays readable in the event, but it is\n // never indexed, so no `#address` filter can ever retrieve it. Without the\n // `t` tags below an attestation published by this SDK is invisible to\n // every by-address query on every relay — including attest.ochk.io's own\n // verifier, which queries `#t`. Keep both: `t` is what makes it findable,\n // `address` is human-readable diagnostics and is not load-bearing.\n const tags: string[][] = [\n ['d', envelope.attestation_id], // Parameterized replaceable event identifier (indexed)\n ['t', envelope.address], // Indexed btc-address tag — query with `#t`\n ['t', 'oc-attest'], // Family marker — `#t=[\"oc-attest\"]` for cross-cut discovery\n ['address', envelope.address], // Diagnostic / legacy — relay won't index this\n ['scheme', envelope.scheme], // Signature scheme (bip322 or legacy)\n ['issued_at', envelope.issued_at], // ISO timestamp\n ];\n\n // Add identity tags\n for (const identity of envelope.identities) {\n tags.push(['i', `${identity.protocol}:${identity.identifier}`]);\n }\n\n // Add expiration if present\n if (envelope.expires_at) {\n tags.push(['expires', envelope.expires_at]);\n }\n\n // Add relay hints if present\n if (envelope.relay_hints?.length) {\n for (const relay of envelope.relay_hints) {\n tags.push(['relay', relay]);\n }\n }\n\n // Content is the full attestation envelope as JSON\n const content = JSON.stringify(envelope, null, 2);\n\n return {\n kind: ATTESTATION_EVENT_KIND,\n tags,\n content,\n created_at: Math.floor(Date.parse(envelope.issued_at) / 1000),\n pubkey,\n };\n}\n\n/**\n * Parse identity bindings from Nostr event tags\n *\n * @param event - Nostr event\n * @returns Array of identity bindings\n */\nexport function parseIdentitiesFromEvent(event: NostrEvent): IdentityBinding[] {\n const identities: IdentityBinding[] = [];\n\n for (const tag of event.tags) {\n if (tag[0] === 'i' && tag[1]) {\n const colonIndex = tag[1].indexOf(':');\n if (colonIndex !== -1) {\n identities.push({\n protocol: tag[1].substring(0, colonIndex),\n identifier: tag[1].substring(colonIndex + 1),\n });\n }\n }\n }\n\n return identities;\n}\n\n/**\n * Extract attestation ID from Nostr event d-tag\n *\n * @param event - Nostr event\n * @returns Attestation ID or undefined if not found\n */\nexport function getAttestationIdFromEvent(event: NostrEvent): string | undefined {\n const dTag = event.tags.find((tag) => tag[0] === 'd');\n return dTag?.[1];\n}\n\n/**\n * Extract Bitcoin address from Nostr event tags\n *\n * @param event - Nostr event\n * @returns Bitcoin address or undefined if not found\n */\nexport function getAddressFromEvent(event: NostrEvent): string | undefined {\n const addressTag = event.tags.find((tag) => tag[0] === 'address');\n return addressTag?.[1];\n}\n\n/**\n * Publish a Nostr event to multiple relays\n * Returns array of relay URLs that successfully accepted the event\n */\nexport async function publishToRelays(\n event: NostrEvent,\n relays: string[] = DEFAULT_RELAYS\n): Promise<{ success: string[]; failed: string[] }> {\n const success: string[] = [];\n const failed: string[] = [];\n\n log.info({ eventId: event.id, relayCount: relays.length }, 'Publishing event to relays');\n\n const publishPromises = relays.map(async (relayUrl) => {\n let ws: WebSocket | null = null;\n\n // One outcome per relay, first one wins. Without this a relay that\n // ACKs `OK true` and then emits an error or close event during\n // teardown lands in BOTH arrays, and the caller reports \"published\n // to 3 · rejected 3\" over the same three relays. The `failed.includes`\n // check this replaces only ever de-duplicated `failed` against\n // itself, so it could not catch a success/failure split.\n // attest.ochk.io's copy of this file has carried the guard for a\n // while; this is the back-port.\n let settled = false;\n const recordSuccess = (): void => {\n if (settled) return;\n settled = true;\n success.push(relayUrl);\n };\n const recordFailure = (): void => {\n if (settled) return;\n settled = true;\n failed.push(relayUrl);\n };\n\n try {\n // Connect to relay\n ws = new WebSocket(relayUrl);\n const wsRef = ws; // Capture for closures\n\n await new Promise<void>((resolve, reject) => {\n // One outer deadline covers connect + OK round-trip. The old\n // code cleared this on `onopen`, which meant a relay that\n // opened but never sent OK would hang the promise forever.\n const deadline = setTimeout(() => {\n wsRef.close();\n reject(new Error('Relay publish timeout'));\n }, 10_000);\n\n const cleanup = () => {\n clearTimeout(deadline);\n wsRef.close();\n };\n\n wsRef.onopen = () => {\n // Do NOT clear the deadline — we still need it in case\n // the relay never responds with OK.\n wsRef.send(JSON.stringify(['EVENT', event]));\n };\n\n wsRef.onmessage = (msg) => {\n try {\n const data = JSON.parse(msg.data);\n // Check for OK response\n if (data[0] === 'OK' && data[1] === event.id) {\n if (data[2] === true) {\n recordSuccess();\n cleanup();\n resolve();\n } else {\n log.warn(\n { relay: relayUrl, reason: data[3] },\n 'Relay rejected event'\n );\n recordFailure();\n cleanup();\n reject(new Error(data[3] || 'Relay rejected event'));\n }\n }\n } catch (err) {\n log.error(\n { relay: relayUrl, error: err },\n 'Failed to parse relay response'\n );\n recordFailure();\n cleanup();\n reject(err);\n }\n };\n\n wsRef.onerror = (err) => {\n log.error({ relay: relayUrl, error: err }, 'WebSocket error');\n recordFailure();\n cleanup();\n reject(err);\n };\n\n wsRef.onclose = () => {\n // Socket closed before we resolved/rejected — counts as\n // failure. clearTimeout here is safe (cleanup handles both).\n clearTimeout(deadline);\n };\n });\n } catch (err) {\n log.error({ relay: relayUrl, error: err }, 'Failed to publish to relay');\n recordFailure();\n } finally {\n // Ensure WebSocket is closed\n if (ws && ws.readyState !== WebSocket.CLOSED) {\n ws.close();\n }\n }\n });\n\n await Promise.allSettled(publishPromises);\n\n log.info({ successCount: success.length, failedCount: failed.length }, 'Publishing complete');\n\n return { success, failed };\n}\n\n/**\n * Query relays for attestations by attestation ID\n */\nexport async function queryByAttestationId(\n attestationId: string,\n relays: string[] = DEFAULT_RELAYS\n): Promise<NostrEvent[]> {\n const events: NostrEvent[] = [];\n\n log.info({ attestationId, relayCount: relays.length }, 'Querying relays for attestation');\n\n const queryPromises = relays.map(async (relayUrl) => {\n let ws: WebSocket | null = null;\n\n try {\n ws = new WebSocket(relayUrl);\n const wsRef = ws; // Capture for closures\n\n await new Promise<void>((resolve, reject) => {\n const timeout = setTimeout(() => {\n wsRef.close();\n reject(new Error('Query timeout'));\n }, 10000);\n\n const cleanup = () => {\n clearTimeout(timeout);\n wsRef.close();\n };\n\n wsRef.onopen = () => {\n // Send REQ message for kind 30078 with d-tag = attestation_id\n const subscriptionId = `ochk_${Date.now()}`;\n wsRef.send(\n JSON.stringify([\n 'REQ',\n subscriptionId,\n {\n kinds: [30078],\n '#d': [attestationId],\n limit: 1,\n },\n ])\n );\n };\n\n wsRef.onmessage = (msg) => {\n try {\n const data = JSON.parse(msg.data);\n if (data[0] === 'EVENT') {\n events.push(data[2]);\n } else if (data[0] === 'EOSE') {\n cleanup();\n resolve();\n }\n } catch (err) {\n log.error({ relay: relayUrl, error: err }, 'Failed to parse event');\n }\n };\n\n wsRef.onerror = (err) => {\n log.error({ relay: relayUrl, error: err }, 'WebSocket error during query');\n cleanup();\n reject(err);\n };\n\n wsRef.onclose = () => {\n clearTimeout(timeout);\n };\n });\n } catch (err) {\n log.error({ relay: relayUrl, error: err }, 'Failed to query relay');\n } finally {\n // Ensure WebSocket is closed\n if (ws && ws.readyState !== WebSocket.CLOSED) {\n ws.close();\n }\n }\n });\n\n await Promise.allSettled(queryPromises);\n\n log.info({ eventCount: events.length }, 'Query complete');\n\n return events;\n}\n\n/**\n * Query relays for attestations by Bitcoin address\n */\nexport async function queryByAddress(\n address: string,\n relays: string[] = DEFAULT_RELAYS\n): Promise<NostrEvent[]> {\n const events: NostrEvent[] = [];\n\n log.info({ address, relayCount: relays.length }, 'Querying relays for address');\n\n const queryPromises = relays.map(async (relayUrl) => {\n try {\n const ws = new WebSocket(relayUrl);\n\n await new Promise<void>((resolve, reject) => {\n const timeout = setTimeout(() => {\n ws.close();\n reject(new Error('Query timeout'));\n }, 10000);\n\n ws.onopen = () => {\n const subscriptionId = `ochk_addr_${Date.now()}`;\n ws.send(\n JSON.stringify([\n 'REQ',\n subscriptionId,\n {\n kinds: [30078],\n // `#t`, NOT `#address`: NIP-12 relays index\n // single-letter tags only, so `#address`\n // matched nothing on any relay and this\n // function returned empty for every real\n // attestation. attest.ochk.io's verifier has\n // queried `#t` since the same fix landed\n // there; this is the back-port.\n '#t': [address],\n limit: 50,\n },\n ])\n );\n };\n\n ws.onmessage = (msg) => {\n try {\n const data = JSON.parse(msg.data);\n if (data[0] === 'EVENT') {\n events.push(data[2]);\n } else if (data[0] === 'EOSE') {\n clearTimeout(timeout);\n ws.close();\n resolve();\n }\n } catch (err) {\n log.error({ relay: relayUrl, error: err }, 'Failed to parse event');\n }\n };\n\n ws.onerror = (err) => {\n clearTimeout(timeout);\n log.error({ relay: relayUrl, error: err }, 'WebSocket error during query');\n reject(err);\n };\n });\n } catch (err) {\n log.error({ relay: relayUrl, error: err }, 'Failed to query relay');\n }\n });\n\n await Promise.allSettled(queryPromises);\n\n log.info({ eventCount: events.length }, 'Query complete');\n\n return events;\n}\n\n/**\n * Query relays for attestations by identity (any protocol)\n */\nexport async function queryByIdentity(\n protocol: string,\n identifier: string,\n relays: string[] = DEFAULT_RELAYS\n): Promise<NostrEvent[]> {\n const events: NostrEvent[] = [];\n const identityTag = `${protocol}:${identifier}`;\n\n log.info({ protocol, identifier, relayCount: relays.length }, 'Querying relays for identity');\n\n const queryPromises = relays.map(async (relayUrl) => {\n try {\n const ws = new WebSocket(relayUrl);\n\n await new Promise<void>((resolve, reject) => {\n const timeout = setTimeout(() => {\n ws.close();\n reject(new Error('Query timeout'));\n }, 10000);\n\n ws.onopen = () => {\n const subscriptionId = `ochk_identity_${Date.now()}`;\n ws.send(\n JSON.stringify([\n 'REQ',\n subscriptionId,\n {\n kinds: [30078],\n '#i': [identityTag],\n limit: 10,\n },\n ])\n );\n };\n\n ws.onmessage = (msg) => {\n try {\n const data = JSON.parse(msg.data);\n if (data[0] === 'EVENT') {\n events.push(data[2]);\n } else if (data[0] === 'EOSE') {\n clearTimeout(timeout);\n ws.close();\n resolve();\n }\n } catch (err) {\n log.error({ relay: relayUrl, error: err }, 'Failed to parse event');\n }\n };\n\n ws.onerror = (err) => {\n clearTimeout(timeout);\n log.error({ relay: relayUrl, error: err }, 'WebSocket error during query');\n reject(err);\n };\n });\n } catch (err) {\n log.error({ relay: relayUrl, error: err }, 'Failed to query relay');\n }\n });\n\n await Promise.allSettled(queryPromises);\n\n log.info({ eventCount: events.length }, 'Query complete');\n\n return events;\n}\n\n/**\n * Verify attestation envelope integrity\n * Checks that the attestation ID matches the message hash\n */\nexport async function verifyAttestationEnvelope(envelope: AttestationEnvelope): Promise<boolean> {\n try {\n // Re-compute attestation ID from message\n const encoder = new TextEncoder();\n const data = encoder.encode(envelope.message);\n const hashBuffer = await crypto.subtle.digest('SHA-256', data);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n const computedId = hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');\n\n return computedId === envelope.attestation_id;\n } catch (err) {\n log.error({ error: err }, 'Failed to verify attestation envelope');\n return false;\n }\n}\n\n/**\n * Parse attestation envelope from Nostr event content\n */\nexport function parseAttestationFromEvent(event: NostrEvent): AttestationEnvelope | null {\n try {\n const envelope = JSON.parse(event.content) as AttestationEnvelope;\n return envelope;\n } catch (err) {\n log.error({ eventId: event.id, error: err }, 'Failed to parse attestation from event');\n return null;\n }\n}\n","/**\n * Nostr Cryptographic Functions\n * Implements NIP-01 event ID computation and signature verification\n */\n\nimport type { NostrEvent } from './types';\n\nimport { createLogger } from './utils/logger';\n\ntype Nip07Window = {\n nostr?: {\n getPublicKey: () => Promise<string>;\n signEvent: (event: Omit<NostrEvent, 'id' | 'sig'>) => Promise<NostrEvent>;\n _metadata?: { name?: string; version?: string };\n };\n};\n\nconst log = createLogger('ocp/nostr-crypto');\n\n/**\n * Compute Nostr event ID according to NIP-01\n * Event ID is the SHA-256 hash of the serialized event\n * Serialization: [0, pubkey, created_at, kind, tags, content]\n */\nexport async function computeNostrEventId(event: Omit<NostrEvent, 'id' | 'sig'>): Promise<string> {\n // Serialize event according to NIP-01\n const serialized = JSON.stringify([\n 0, // Reserved for future use\n event.pubkey,\n event.created_at,\n event.kind,\n event.tags,\n event.content,\n ]);\n\n log.debug({ serialized }, 'Computing event ID');\n\n // Compute SHA-256 hash\n const encoder = new TextEncoder();\n const data = encoder.encode(serialized);\n const hashBuffer = await crypto.subtle.digest('SHA-256', data);\n\n // Convert to lowercase hex\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n const hashHex = hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');\n\n log.debug({ eventId: hashHex }, 'Computed event ID');\n\n return hashHex;\n}\n\n/**\n * Verify Nostr event ID\n * Recomputes the ID and checks if it matches\n */\nexport async function verifyNostrEventId(event: NostrEvent): Promise<boolean> {\n const computedId = await computeNostrEventId(event);\n return computedId === event.id;\n}\n\n/**\n * Check if NIP-07 extension is available\n * NIP-07 provides window.nostr for signing events\n */\nexport function isNip07Available(): boolean {\n if (typeof window === 'undefined') {\n return false;\n }\n\n return !!(window as unknown as { nostr?: Nip07Window['nostr'] }).nostr!;\n}\n\n/**\n * Get Nostr public key from NIP-07 extension\n * Returns null if extension not available or user denies\n */\nexport async function getNostrPublicKey(): Promise<string | null> {\n if (!isNip07Available()) {\n log.warn('NIP-07 extension not available');\n return null;\n }\n\n try {\n const nostr = (window as unknown as { nostr?: Nip07Window['nostr'] }).nostr!;\n const pubkey = await nostr.getPublicKey();\n log.info({ pubkey }, 'Got Nostr public key from NIP-07');\n return pubkey;\n } catch (err) {\n log.error({ error: err }, 'Failed to get Nostr public key');\n return null;\n }\n}\n\n/**\n * Sign Nostr event using NIP-07 extension\n * Returns signed event with id and sig fields\n */\nexport async function signNostrEvent(\n event: Omit<NostrEvent, 'id' | 'sig'>\n): Promise<NostrEvent | null> {\n if (!isNip07Available()) {\n log.warn('NIP-07 extension not available');\n return null;\n }\n\n try {\n const nostr = (window as unknown as { nostr?: Nip07Window['nostr'] }).nostr!;\n\n // NIP-07 signEvent expects the event without id and sig\n const signedEvent = await nostr.signEvent(event);\n\n log.info({ eventId: signedEvent.id }, 'Signed Nostr event with NIP-07');\n\n return signedEvent as NostrEvent;\n } catch (err) {\n log.error({ error: err }, 'Failed to sign Nostr event');\n return null;\n }\n}\n\n// Previously this file exported `generateEphemeralKeypair()` and\n// `signEventWithEphemeralKey()` for demo purposes. Both produced non-schnorr\n// values that Nostr relays would silently reject — creating the false\n// impression that publishing had succeeded. They have been removed. All Nostr\n// signing now flows through `signNostrEvent()` / `window.nostr` (NIP-07).\n\n/**\n * Validate Nostr event structure\n */\nexport function validateNostrEvent(event: unknown): event is NostrEvent {\n if (typeof event !== 'object' || event === null) return false;\n const e = event as Record<string, unknown>;\n\n if (typeof e.id !== 'string' || (e.id as string).length !== 64) return false;\n if (typeof e.pubkey !== 'string' || (e.pubkey as string).length !== 64) return false;\n if (typeof e.created_at !== 'number') return false;\n if (typeof e.kind !== 'number') return false;\n if (!Array.isArray(e.tags)) return false;\n if (typeof e.content !== 'string') return false;\n if (typeof e.sig !== 'string' || (e.sig as string).length !== 128) return false;\n\n return true;\n}\n\n/**\n * Get NIP-07 extension info\n */\nexport function getNip07Info(): {\n available: boolean;\n name?: string;\n version?: string;\n} {\n if (!isNip07Available()) {\n return { available: false };\n }\n\n const nostr = (window as unknown as { nostr?: Nip07Window['nostr'] }).nostr!;\n\n return {\n available: true,\n name: nostr._metadata?.name,\n version: nostr._metadata?.version,\n };\n}\n","/**\n * Attestation Manager\n *\n * High-level API for creating, publishing, and discovering OrangeCheck attestations\n */\n\nimport type { AttestationEnvelope, IdentityBinding, NostrEvent, Scheme } from './types';\n\nimport { createAttestationEnvelope } from './canonical';\nimport {\n createAttestationEvent,\n DEFAULT_RELAYS,\n parseAttestationFromEvent,\n publishToRelays,\n queryByAddress,\n queryByAttestationId,\n queryByIdentity,\n verifyAttestationEnvelope,\n} from './nostr';\nimport { isNip07Available, signNostrEvent } from './nostr-crypto';\nimport { createLogger } from './utils/logger';\n\nconst log = createLogger('ocp/attestation');\n\n/**\n * Options for creating an attestation\n */\nexport interface CreateAttestationOptions {\n /** Canonical message */\n message: string;\n /** BIP-322 or legacy signature */\n signature: string;\n /** Signature scheme used */\n scheme: Scheme;\n /** Bitcoin address */\n address: string;\n /** Optional identity bindings */\n identities?: IdentityBinding[];\n /** Optional extension key-value pairs */\n extensions?: Record<string, string | undefined>;\n}\n\n/**\n * Options for publishing an attestation to Nostr\n */\nexport interface PublishAttestationOptions {\n /** Attestation envelope to publish */\n envelope: AttestationEnvelope;\n /** Nostr public key (npub or hex) for signing the event */\n npub: string;\n /** Optional relay URLs (defaults to DEFAULT_RELAYS) */\n relays?: string[];\n}\n\n/**\n * Options for discovering attestations\n */\nexport interface DiscoverAttestationOptions {\n /** Search by attestation ID */\n attestationId?: string;\n /** Search by Bitcoin address */\n address?: string;\n /** Search by identity binding */\n identity?: { protocol: string; identifier: string };\n /** Optional relay URLs to query */\n relays?: string[];\n}\n\n/**\n * Result of publishing an attestation\n */\nexport interface PublishResult {\n /** Relays that successfully received the event */\n success: string[];\n /** Relays that failed to receive the event */\n failed: string[];\n}\n\n/**\n * Custom error for attestation operations\n */\nexport class AttestationError extends Error {\n constructor(\n message: string,\n public readonly code?: string\n ) {\n super(message);\n this.name = 'AttestationError';\n }\n}\n\n/**\n * Create an attestation envelope from a signed message\n *\n * @param options - Attestation creation options\n * @returns Attestation envelope ready for publishing\n * @throws {AttestationError} If envelope integrity check fails\n *\n * @example\n * ```typescript\n * const envelope = await createAttestation({\n * message: canonicalMessage,\n * signature: 'AkcwRAIg...',\n * scheme: 'bip322',\n * address: 'bc1q...',\n * identities: [{ protocol: 'nostr', identifier: 'npub1...' }],\n * });\n * ```\n */\nexport async function createAttestation(\n options: CreateAttestationOptions\n): Promise<AttestationEnvelope> {\n const { message, signature, scheme, address, identities = [], extensions = {} } = options;\n\n log.info({ address, identityCount: identities.length }, 'Creating attestation');\n\n const envelope = await createAttestationEnvelope(\n message,\n signature,\n scheme,\n address,\n identities,\n extensions\n );\n\n // Verify envelope integrity\n const isValid = await verifyAttestationEnvelope(envelope);\n if (!isValid) {\n throw new AttestationError(\n 'Attestation envelope integrity check failed',\n 'INTEGRITY_CHECK_FAILED'\n );\n }\n\n log.info({ attestationId: envelope.attestation_id }, 'Attestation created successfully');\n\n return envelope;\n}\n\n/**\n * Publish an attestation to Nostr relays\n *\n * Uses NIP-07 if available, falls back to ephemeral key for demo\n *\n * @param options - Publishing options\n * @returns Object with successful and failed relay URLs\n * @throws {AttestationError} If signing fails\n *\n * @example\n * ```typescript\n * const result = await publishAttestation({\n * envelope,\n * npub: 'npub1...',\n * relays: ['wss://relay.damus.io'],\n * });\n * console.log('Published to:', result.success);\n * ```\n */\nexport async function publishAttestation(\n options: PublishAttestationOptions\n): Promise<PublishResult> {\n const { envelope, npub, relays = DEFAULT_RELAYS } = options;\n\n log.info(\n { attestationId: envelope.attestation_id, relayCount: relays.length },\n 'Publishing attestation'\n );\n\n // Create unsigned event\n const unsignedEvent = createAttestationEvent(envelope, npub);\n\n // Nostr publishing requires a valid schnorr signature. Only NIP-07\n // (window.nostr) is supported. If no signer is present we refuse to\n // publish rather than emit an invalid-sig event that every relay will\n // silently reject — which would make the caller think it had succeeded.\n if (!isNip07Available()) {\n log.warn('NIP-07 unavailable — skipping Nostr publish');\n throw new Error(\n 'nostr_signer_unavailable: install a NIP-07 extension (e.g. nos2x, Alby) to publish'\n );\n }\n\n log.info('Using NIP-07 to sign event');\n const signedEvent = await signNostrEvent(unsignedEvent);\n if (!signedEvent) {\n throw new Error('nostr_signing_failed: NIP-07 extension rejected or errored');\n }\n\n const result = await publishToRelays(signedEvent, relays);\n\n log.info(\n {\n attestationId: envelope.attestation_id,\n successCount: result.success.length,\n failedCount: result.failed.length,\n },\n 'Publishing complete'\n );\n\n return result;\n}\n\n/**\n * Discover attestations from Nostr relays\n */\nexport async function discoverAttestations(\n options: DiscoverAttestationOptions\n): Promise<AttestationEnvelope[]> {\n const { attestationId, address, identity, relays = DEFAULT_RELAYS } = options;\n\n let events: NostrEvent[] = [];\n\n if (attestationId) {\n log.info({ attestationId }, 'Discovering by attestation ID');\n events = await queryByAttestationId(attestationId, relays);\n } else if (address) {\n log.info({ address }, 'Discovering by Bitcoin address');\n events = await queryByAddress(address, relays);\n } else if (identity) {\n log.info({ identity }, 'Discovering by identity');\n events = await queryByIdentity(identity.protocol, identity.identifier, relays);\n } else {\n throw new Error('Must provide attestationId, address, or identity');\n }\n\n // Parse and verify envelopes\n const envelopes: AttestationEnvelope[] = [];\n for (const event of events) {\n const envelope = parseAttestationFromEvent(event);\n if (envelope) {\n // Verify envelope integrity\n const isValid = await verifyAttestationEnvelope(envelope);\n if (isValid) {\n envelopes.push(envelope);\n } else {\n log.warn(\n { attestationId: envelope.attestation_id },\n 'Skipping invalid attestation envelope'\n );\n }\n }\n }\n\n log.info({ eventCount: events.length, validCount: envelopes.length }, 'Discovery complete');\n\n return envelopes;\n}\n\n/**\n * Verify an attestation by fetching it from Nostr and checking integrity\n */\nexport async function verifyAttestationById(\n attestationId: string,\n relays: string[] = DEFAULT_RELAYS\n): Promise<AttestationEnvelope | null> {\n log.info({ attestationId }, 'Verifying attestation by ID');\n\n const envelopes = await discoverAttestations({ attestationId, relays });\n\n if (envelopes.length === 0) {\n log.warn({ attestationId }, 'Attestation not found on any relay');\n return null;\n }\n\n if (envelopes.length > 1) {\n log.warn(\n { attestationId, count: envelopes.length },\n 'Multiple attestations found with same ID - using first'\n );\n }\n\n return envelopes[0] || null;\n}\n\n/**\n * Get all attestations for a Bitcoin address\n */\nexport async function getAttestationsForAddress(\n address: string,\n relays: string[] = DEFAULT_RELAYS\n): Promise<AttestationEnvelope[]> {\n log.info({ address }, 'Getting all attestations for address');\n return discoverAttestations({ address, relays });\n}\n\n/**\n * Get all attestations for an identity\n */\nexport async function getAttestationsForIdentity(\n protocol: string,\n identifier: string,\n relays: string[] = DEFAULT_RELAYS\n): Promise<AttestationEnvelope[]> {\n log.info({ protocol, identifier }, 'Getting all attestations for identity');\n return discoverAttestations({ identity: { protocol, identifier }, relays });\n}\n\n/**\n * Format identities for display as a comma-separated `protocol:identifier` list.\n * Same wire format the canonical message uses.\n */\nexport function formatIdentitiesForDisplay(identities: IdentityBinding[]): string {\n return identities.map((id) => `${id.protocol}:${id.identifier}`).join(', ');\n}\n\n/**\n * Build the canonical shareable URL for an attestation. Matches the live\n * `/attest/[id]` route on attest.ochk.io. Pass a different `baseUrl` for forks /\n * self-hosted verifiers.\n */\nexport function getVerificationUrl(\n attestationId: string,\n baseUrl = 'https://attest.ochk.io'\n): string {\n return `${baseUrl}/attest/${attestationId}`;\n}\n\n/**\n * Reverse of `getVerificationUrl` — pull an attestation id back out of a\n * `/attest/<id>` or legacy `/verify?id=<id>` URL. Returns `null` if the URL\n * shape doesn't match.\n */\nexport function extractAttestationIdFromUrl(url: string): string | null {\n try {\n const u = new URL(url);\n // New canonical form: /attest/<id>\n const m = u.pathname.match(/^\\/attest\\/([0-9a-f]{64})\\/?$/i);\n if (m) return m[1]!.toLowerCase();\n // Legacy form: /verify?id=<id>\n const q = u.searchParams.get('id');\n if (q && /^[0-9a-f]{64}$/i.test(q)) return q.toLowerCase();\n return null;\n } catch {\n return null;\n }\n}\n","/**\n * OrangeCheck Scoring\n *\n * The protocol registers exactly one scoring algorithm: `v0`. A `tier` helper\n * is also provided for UI convenience. RPs with specialized needs compute\n * their own score against raw metrics — the protocol does not ship an\n * algorithm zoo.\n *\n * See: docs/oc-protocol/registry/scoring.md\n */\n\nexport type ScoringAlgorithm = 'v0' | 'tier' | 'none';\nexport type Tier = 'platinum' | 'gold' | 'silver' | 'bronze' | 'none';\nexport type ScoreResult = number | Tier | null;\n\nexport interface ScoringConfig {\n algorithm: ScoringAlgorithm;\n}\n\nfunction scoreV0(sats: number, days: number): number {\n if (sats <= 0 || days <= 0) return 0;\n return Math.round(Math.log(1 + sats) * (1 + days / 30) * 100) / 100;\n}\n\nfunction scoreTier(sats: number, days: number): Tier {\n if (sats >= 10_000_000 && days >= 365) return 'platinum';\n if (sats >= 1_000_000 && days >= 180) return 'gold';\n if (sats >= 100_000 && days >= 90) return 'silver';\n if (sats >= 10_000 && days >= 30) return 'bronze';\n return 'none';\n}\n\nexport function computeScore(sats: number, days: number, config: ScoringConfig): ScoreResult {\n switch (config.algorithm) {\n case 'v0':\n return scoreV0(sats, days);\n case 'tier':\n return scoreTier(sats, days);\n case 'none':\n return null;\n }\n}\n\nexport function computeAllScores(sats: number, days: number) {\n return { v0: scoreV0(sats, days), tier: scoreTier(sats, days) };\n}\n\nexport function formatScore(score: ScoreResult, algorithm: ScoringAlgorithm): string {\n if (score === null || algorithm === 'none') return 'N/A';\n if (algorithm === 'v0') return (score as number).toFixed(1);\n const tier = score as Tier;\n const labels: Record<Tier, string> = {\n platinum: 'Platinum',\n gold: 'Gold',\n silver: 'Silver',\n bronze: 'Bronze',\n none: '—',\n };\n return labels[tier];\n}\n\nexport function getScoreColor(score: ScoreResult, algorithm: ScoringAlgorithm): string {\n if (algorithm === 'tier') {\n const colors: Record<Tier, string> = {\n platinum: '#a855f7',\n gold: '#eab308',\n silver: '#94a3b8',\n bronze: '#f97316',\n none: '#64748b',\n };\n return colors[(score as Tier) ?? 'none'] ?? '#64748b';\n }\n const n = (score as number) ?? 0;\n if (n >= 100) return '#22c55e';\n if (n >= 50) return '#3b82f6';\n if (n >= 20) return '#eab308';\n return '#f97316';\n}\n\nexport function getTierNumber(tier: Tier): number {\n const map: Record<Tier, number> = {\n platinum: 4,\n gold: 3,\n silver: 2,\n bronze: 1,\n none: 0,\n };\n return map[tier] ?? 0;\n}\n","/**\n * OrangeCheck Protocol Verification\n *\n * Core verification logic for BIP-322 and legacy signatures,\n * UTXO analysis, and reputation metrics computation\n */\n\nimport type { ScoringAlgorithm } from './scoring';\nimport type {\n IdentityBinding,\n Metrics,\n Network,\n Scheme,\n StatusCode,\n VerifyInput,\n VerifyOptions,\n VerifyOutcome,\n} from './types';\n\nimport { Buffer } from 'buffer';\n\nimport { Verifier } from 'bip322-js';\nimport * as bitcoinMessage from 'bitcoinjs-message';\n\nimport { generateAttestationId, parseIdentities } from './canonical';\nimport { computeAllScores, computeScore } from './scoring';\nimport { createLogger } from './utils/logger';\n\nconst log = createLogger('ocp/verify');\n\n/**\n * Scoring function per OCP v0 specification (SPEC.md §6)\n * Formula: score = round( ln(1 + sats_bonded) * (1 + days_unspent / 30), 2 )\n *\n * This produces an unbounded score that combines both sats and time.\n * Typical ranges:\n * - 10k sats, 30 days ≈ 18\n * - 100k sats, 90 days ≈ 46\n * - 1M sats, 365 days ≈ 182\n * - 100M sats, 365 days ≈ 243\n */\n/**\n * Export scoring functions for use in other modules\n */\nexport { computeScore, computeAllScores, type ScoringAlgorithm };\n\n/**\n * Input for signature verification\n */\ninterface SignatureVerifyInput {\n /** Bitcoin address */\n addr: string;\n /** Message to verify */\n msg: string;\n /** Signature (hex or base64) */\n sig: string;\n /** Optional signature scheme (auto-detected if not provided) */\n scheme?: Scheme;\n}\n\n/**\n * Check if a string looks like hexadecimal\n * @param s - String to check\n * @returns True if string is valid hex with even length\n */\nfunction looksLikeHex(s: string): boolean {\n return /^[0-9a-fA-F]+$/.test(s) && s.length % 2 === 0;\n}\n\n/**\n * Convert signature to base64 if it's in hex format\n * @param sig - Signature (hex or base64)\n * @returns Signature in base64 format\n */\nfunction toBase64Maybe(sig: string): string {\n if (looksLikeHex(sig)) {\n return Buffer.from(sig, 'hex').toString('base64');\n }\n return sig;\n}\n\n/**\n * Auto-detect signature scheme based on address type and signature format\n *\n * @param addr - Bitcoin address\n * @param sig - Signature\n * @returns Detected scheme ('bip322' or 'legacy')\n */\nfunction detectSignatureScheme(addr: string, sig: string): Scheme {\n // SegWit and Taproot addresses MUST use BIP-322\n const isSegWit = addr.startsWith('bc1') || addr.startsWith('tb1');\n if (isSegWit) {\n return 'bip322';\n }\n\n // For P2PKH addresses, check if signature looks like legacy format\n const sigBase64 = toBase64Maybe(sig);\n const looksLikeLegacy = sigBase64.length === 88 && /^[IHG]/.test(sigBase64);\n\n if (looksLikeLegacy) {\n return 'legacy';\n }\n\n // Default to BIP-322\n return 'bip322';\n}\n\nasync function verifySignature({\n addr,\n msg,\n sig,\n scheme,\n}: SignatureVerifyInput): Promise<StatusCode> {\n try {\n // Handle demo signatures - these should never reach here in demo mode,\n // but add defensive check in case demo mode flag isn't set properly\n if (sig === 'demo_signature') {\n log.warn('Demo signature detected in verifySignature - should be handled by demo mode');\n return 'sig_invalid';\n }\n\n // Auto-detect scheme if not explicitly provided\n const detectedScheme = scheme || detectSignatureScheme(addr, sig);\n\n log.debug(\n { addr, msgLength: msg.length, sigLength: sig.length, scheme: detectedScheme },\n 'Verifying signature'\n );\n\n if (detectedScheme === 'bip322') {\n const sigBase64 = toBase64Maybe(sig);\n log.debug(\n { sigBase64: sigBase64.substring(0, 50) + '...' },\n 'Signature converted to base64'\n );\n\n // Log the full message for debugging\n log.debug(\n {\n msgFull: msg,\n msgLines: msg.split('\\n').length,\n msgFirstLine: msg.split('\\n')[0],\n msgLastLine: msg.split('\\n')[msg.split('\\n').length - 1],\n },\n 'Message being verified'\n );\n\n const ok = Verifier.verifySignature(addr, msg, sigBase64);\n log.info({ addr, ok }, 'BIP-322 verification result');\n\n if (!ok) {\n // Check if this looks like an Electrum signature (88 chars, base64)\n const isSegWit = addr.startsWith('bc1') || addr.startsWith('tb1');\n if (isSegWit && sigBase64.length === 88) {\n log.warn(\n { addr, wallet: 'possibly Electrum', sigLength: sigBase64.length },\n 'BIP-322 verification failed - likely Electrum wallet (does not support BIP-322 for SegWit)'\n );\n } else {\n log.error(\n {\n addr,\n sigLength: sigBase64.length,\n msgLength: msg.length,\n msgPreview: msg.substring(0, 200),\n },\n 'BIP-322 verification failed - signature does not match message'\n );\n }\n }\n\n return ok ? 'sig_ok_bip322' : 'sig_invalid';\n }\n\n if (detectedScheme === 'legacy') {\n const sigBase64 = toBase64Maybe(sig);\n\n // Legacy policy: P2PKH only (address must start with '1' for mainnet or 'm'/'n' for testnet)\n if (!addr.startsWith('1') && !addr.startsWith('m') && !addr.startsWith('n')) {\n log.warn({ addr }, 'Legacy signature attempted on non-P2PKH address');\n return 'sig_unsupported_script';\n }\n\n log.debug(\n {\n addr,\n sigBase64: sigBase64.substring(0, 50) + '...',\n msgPreview: msg.substring(0, 100) + '...',\n msgLength: msg.length,\n },\n 'Verifying legacy signature'\n );\n const ok = bitcoinMessage.verify(msg, addr, sigBase64);\n log.info({ addr, ok, sigBase64Length: sigBase64.length }, 'Legacy verification result');\n if (!ok) {\n log.error(\n {\n addr,\n msgFirstLine: msg.split('\\n')[0],\n sigFormat: sigBase64.substring(0, 10),\n },\n 'Legacy signature verification failed - check message format and signature'\n );\n }\n return ok ? 'sig_ok_legacy' : 'sig_invalid';\n }\n\n return 'invalid_scheme';\n } catch (err) {\n log.error(\n { addr, error: err instanceof Error ? err.message : String(err) },\n 'Signature verification error'\n );\n return 'sig_invalid';\n }\n}\n\n// Canonical message parsing per SPEC + our builder (lowercase keys, extensions)\nfunction parseCanonicalMessage(msg: string) {\n const lines = msg.split('\\n').map((l) => l.trim());\n // `.split(':', 2)[1]` truncates values containing a colon (e.g. URLs in\n // extensions, or npubs in identities). Use the first colon as the\n // separator and keep everything after it — same approach as the\n // extensions loop below.\n const getVal = (prefix: string): string | undefined => {\n const needle = prefix + ':';\n const hit = lines.find((l) => l.toLowerCase().startsWith(needle));\n if (!hit) return undefined;\n const idx = hit.indexOf(':');\n return hit.slice(idx + 1).trim();\n };\n\n const address = getVal('address') || '';\n const identitiesStr = getVal('identities') || '';\n\n // Parse identities\n let identities: IdentityBinding[] = [];\n try {\n identities = parseIdentities(identitiesStr);\n } catch (err) {\n log.warn({ identitiesStr, error: err }, 'Failed to parse identities field');\n }\n\n // Extensions: collect all key: value pairs excluding core known keys\n const coreKeys = new Set([\n 'orangecheck',\n 'identities',\n 'address',\n 'purpose',\n 'nonce',\n 'issued_at',\n 'ack',\n ]);\n const extensions: Record<string, string> = {};\n for (const line of lines) {\n const idx = line.indexOf(':');\n if (idx === -1) continue;\n const key = line.slice(0, idx).trim().toLowerCase();\n const val = line.slice(idx + 1).trim();\n if (!coreKeys.has(key) && val) extensions[key] = val;\n }\n\n const network = (extensions['network'] || 'mainnet') as Network;\n\n // Parse bond extension if present (integer satoshis)\n const bondStr = extensions['bond'];\n const bond = bondStr ? parseInt(bondStr, 10) : undefined;\n\n return {\n core: { address, identities },\n network,\n extensions,\n bond: bond !== undefined && !isNaN(bond) && bond > 0 ? bond : undefined,\n };\n}\n\n/**\n * UTXO type from Esplora API\n */\ninterface EsploraUtxo {\n /** Transaction ID */\n txid: string;\n /** Output index */\n vout: number;\n /** Value in satoshis */\n value: number;\n /** Confirmation status */\n status: {\n /** Whether UTXO is confirmed */\n confirmed: boolean;\n /** Block height (if confirmed) */\n block_height?: number;\n /** Block timestamp (if confirmed) */\n block_time?: number;\n };\n}\n\n/**\n * Fetch UTXOs for an address from Esplora API\n *\n * Tries multiple endpoints in order with automatic fallback\n *\n * @param address - Bitcoin address\n * @param network - Bitcoin network\n * @param opts - Optional custom Esplora endpoints\n * @returns Array of UTXOs\n * @throws {Error} If all endpoints fail\n */\nasync function getAddressUtxos(\n address: string,\n network: Network,\n opts?: {\n esploraMainnetBase?: string;\n esploraSignetBase?: string;\n esploraTestnetBase?: string;\n }\n): Promise<EsploraUtxo[]> {\n // Define primary and fallback endpoints\n const endpoints =\n network === 'signet'\n ? [\n opts?.esploraSignetBase || 'https://mempool.space/signet/api',\n 'https://blockstream.info/signet/api',\n ]\n : network === 'testnet'\n ? [\n opts?.esploraTestnetBase || 'https://mempool.space/testnet/api',\n 'https://blockstream.info/testnet/api',\n ]\n : [\n opts?.esploraMainnetBase || 'https://mempool.space/api',\n 'https://blockstream.info/api',\n ];\n\n let lastError: Error | null = null;\n\n // Try each endpoint in order. Per-endpoint timeout kept tight (5s) so\n // a slow upstream doesn't stack against the next one; callers who want\n // a hard overall deadline should wrap this call with their own timeout.\n for (const base of endpoints) {\n try {\n const url = `${base}/address/${address}/utxo`;\n log.debug({ url, network }, 'Fetching UTXOs');\n\n const resp = await fetch(url, {\n method: 'GET',\n headers: { Accept: 'application/json' },\n signal: AbortSignal.timeout(5000),\n });\n\n if (!resp.ok) {\n throw new Error(`HTTP ${resp.status}`);\n }\n\n const data = await resp.json();\n\n // Validate response structure\n if (!Array.isArray(data)) {\n throw new Error('Invalid response: expected array');\n }\n\n // Validate each UTXO has required fields\n for (const utxo of data) {\n if (\n typeof utxo.value !== 'number' ||\n typeof utxo.status !== 'object' ||\n typeof utxo.status.confirmed !== 'boolean' ||\n typeof utxo.txid !== 'string' ||\n typeof utxo.vout !== 'number'\n ) {\n throw new Error('Invalid UTXO structure');\n }\n }\n\n log.info({ base, count: data.length, network }, 'UTXOs fetched successfully');\n return data as EsploraUtxo[];\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err));\n log.warn(\n { base, error: lastError.message, network },\n 'Esplora endpoint failed, trying next'\n );\n }\n }\n\n // All endpoints failed\n log.error({ endpoints, error: lastError?.message, network }, 'All Esplora endpoints failed');\n throw new Error(`esplora_all_failed: ${lastError?.message || 'unknown'}`);\n}\n\n/**\n * Enhanced metrics computation per SPEC.md §5.4 and §6.1\n *\n * Supports bond extension with oldest-first greedy UTXO selection\n *\n * @param utxos - Array of UTXOs from Esplora\n * @param bondAmount - Optional bond amount (enables greedy selection)\n * @returns Computed metrics (sats_bonded, days_unspent, confirmed_balance)\n */\nfunction computeMetrics(\n utxos: EsploraUtxo[],\n bondAmount?: number\n): {\n /** Bonded satoshis (confirmed balance or bond amount) */\n sats_bonded: number;\n /** Days since oldest/youngest UTXO */\n days_unspent: number;\n /** Total confirmed balance */\n confirmed_balance: number;\n} {\n // Filter out unconfirmed UTXOs\n const confirmedUtxos = utxos.filter((u) => u.status.confirmed);\n if (confirmedUtxos.length === 0) {\n return { sats_bonded: 0, days_unspent: 0, confirmed_balance: 0 };\n }\n\n // Compute total confirmed balance\n const confirmed_balance = confirmedUtxos.reduce((sum, u) => sum + u.value, 0);\n\n // If bond extension is present, use oldest-first greedy algorithm\n if (bondAmount !== undefined && bondAmount > 0) {\n // Sort UTXOs by (block_height ASC, txid ASC, vout ASC) - oldest first\n const sorted = [...confirmedUtxos].sort((a, b) => {\n const heightA = a.status.block_height ?? Infinity;\n const heightB = b.status.block_height ?? Infinity;\n if (heightA !== heightB) return heightA - heightB;\n if (a.txid !== b.txid) return a.txid.localeCompare(b.txid);\n return a.vout - b.vout;\n });\n\n // Greedily select UTXOs until sum >= bond\n let sum = 0;\n let youngestTime = 0;\n for (const utxo of sorted) {\n sum += utxo.value;\n youngestTime = Math.max(youngestTime, utxo.status.block_time || 0);\n if (sum >= bondAmount) break;\n }\n\n // Age is computed from the youngest UTXO in the bonded set\n const days_unspent = Math.max(\n 0,\n Math.floor((Date.now() / 1000 - youngestTime) / (24 * 60 * 60))\n );\n\n return {\n sats_bonded: bondAmount, // Use exactly bond amount (ignore surplus)\n days_unspent,\n confirmed_balance,\n };\n }\n\n // Default behavior (no bond extension): sum all confirmed UTXOs\n const sats_bonded = confirmed_balance;\n\n // Find the oldest confirmed UTXO for days_unspent\n const oldestTime = Math.min(\n ...confirmedUtxos.map((u) => u.status.block_time || Date.now() / 1000)\n );\n const days_unspent = Math.max(0, Math.floor((Date.now() / 1000 - oldestTime) / (24 * 60 * 60)));\n\n return { sats_bonded, days_unspent, confirmed_balance };\n}\n\n/**\n * Verify an OrangeCheck attestation\n *\n * This is the main verification function that:\n * 1. Validates the canonical message format\n * 2. Verifies the Bitcoin signature (BIP-322 or legacy)\n * 3. Fetches and analyzes UTXOs\n * 4. Computes reputation metrics\n *\n * @param input - Verification input (message, address, signature)\n * @param opts - Optional verification options (demo mode, test mode, etc.)\n * @returns Verification outcome with status codes and metrics\n *\n * @example\n * ```typescript\n * const result = await verify({\n * msg: canonicalMessage,\n * addr: 'bc1q...',\n * sig: 'AkcwRAIg...',\n * });\n *\n * if (result.ok) {\n * console.log('Score:', result.metrics?.score);\n * }\n * ```\n */\nexport async function verify(input: VerifyInput, opts: VerifyOptions = {}): Promise<VerifyOutcome> {\n const codes: StatusCode[] = [];\n let network: Network = 'mainnet';\n\n try {\n // Check if we have required fields\n if (!input.msg || !input.addr || !input.sig) {\n codes.push('bad_request');\n return { ok: false, codes, network };\n }\n\n // Parse canonical message with extensions\n const parsed = parseCanonicalMessage(input.msg);\n network = parsed.network || 'mainnet';\n\n // Compute attestation ID\n const attestation_id = await generateAttestationId(input.msg);\n\n // Validate address consistency\n if (parsed.core.address !== input.addr) {\n codes.push('bad_request');\n return { ok: false, codes, network, attestation_id };\n }\n\n // Demo mode short-circuit with demo data matching the App panel\n if (opts.demoMode) {\n // Keep demo values in sync with createDemoBadgeData()\n const sats_bonded = 1_000_000; // 0.01 BTC\n const days_unspent = 90;\n const metrics: Metrics = {\n sats_bonded,\n days_unspent,\n score: (computeScore(sats_bonded, days_unspent, { algorithm: 'v0' }) as number), // ≈ 55.26\n };\n codes.push('sig_ok_bip322');\n codes.push('bond_confirmed');\n return {\n ok: true,\n codes,\n network,\n attestation_id,\n identities: parsed.core.identities,\n metrics,\n };\n }\n\n // Testnet/Signet policy enforcement\n if ((network === 'testnet' || network === 'signet') && !opts.testMode) {\n codes.push('network_testmode');\n return { ok: false, codes, network, attestation_id };\n }\n\n // Optional policy checks for extensions.\n // `aud` binds the attestation to an origin. If the caller passed\n // `expectedAud`, the check must be load-bearing — a mismatch is a\n // phishing signal, not an advisory. Fail hard (spec-aligned).\n if (opts.expectedAud) {\n const aud = parsed.extensions['aud'];\n if (!aud || aud !== opts.expectedAud) {\n codes.push('aud_mismatch');\n return { ok: false, codes, network, attestation_id };\n }\n }\n\n // Check message expiration\n if (parsed.extensions['expires']) {\n const exp = Date.parse(parsed.extensions['expires']);\n if (!Number.isNaN(exp) && exp < Date.now()) {\n codes.push('expired');\n return { ok: false, codes, network, attestation_id };\n }\n }\n\n // Enhanced signature verification\n const sigCode = await verifySignature({\n addr: input.addr,\n msg: input.msg,\n sig: input.sig,\n ...(input.scheme && { scheme: input.scheme }),\n });\n codes.push(sigCode);\n\n const sigOk = sigCode === 'sig_ok_bip322' || sigCode === 'sig_ok_legacy';\n if (!sigOk) {\n return {\n ok: false,\n codes,\n network,\n attestation_id,\n identities: parsed.core.identities,\n };\n }\n\n // Enhanced UTXO analysis and metrics computation\n try {\n const utxos = await getAddressUtxos(input.addr, network, {\n esploraMainnetBase: opts.esploraMainnetBase,\n esploraSignetBase: opts.esploraSignetBase,\n });\n\n // Compute metrics with bond extension support (SPEC.md §5.4)\n const { sats_bonded, days_unspent, confirmed_balance } = computeMetrics(\n utxos,\n parsed.bond\n );\n\n // If bond extension is present, enforce minimum balance (SPEC.md §5.4.c)\n if (parsed.bond !== undefined && parsed.bond > 0) {\n if (confirmed_balance < parsed.bond) {\n codes.push('bond_insufficient');\n log.warn(\n {\n bond: parsed.bond,\n confirmed_balance,\n address: input.addr,\n },\n 'Bond extension: insufficient balance'\n );\n return {\n ok: false,\n codes,\n network,\n attestation_id,\n identities: parsed.core.identities,\n };\n }\n }\n\n // Analyze bond status\n if (sats_bonded <= 0) {\n codes.push('bond_zero');\n // Check for pending UTXOs\n if (utxos.some((u) => !u.status.confirmed)) {\n codes.push('bond_pending');\n }\n return {\n ok: false,\n codes,\n network,\n attestation_id,\n identities: parsed.core.identities,\n };\n } else {\n codes.push('bond_confirmed');\n }\n\n // Compute final metrics with enhanced scoring\n const metrics: Metrics = {\n sats_bonded,\n days_unspent,\n score: (computeScore(sats_bonded, days_unspent, { algorithm: 'v0' }) as number),\n };\n\n return {\n ok: true,\n codes,\n network,\n attestation_id,\n identities: parsed.core.identities,\n metrics,\n };\n } catch (utxoError) {\n log.error({ err: utxoError }, 'UTXO fetch failed');\n codes.push('bad_request');\n return { ok: false, codes, network, attestation_id };\n }\n } catch (e: unknown) {\n const msg = e instanceof Error ? e.message : String(e ?? 'decode_error');\n if (msg === 'decode_error') {\n codes.push('decode_error');\n } else {\n codes.push('bad_request');\n }\n return { ok: false, codes, network };\n }\n}\n","/**\n * check()\n *\n * The high-level sybil-gate primitive. One call, one answer.\n *\n * Under the hood: find the most recent attestation for the subject via Nostr,\n * verify the signature, recompute metrics from live chain state, then compare\n * against the caller's thresholds.\n *\n * Mirrors the response shape of GET /api/check.\n */\n\nimport type { AttestationEnvelope, IdentityBinding, Network, VerifyOptions } from './types';\n\nimport {\n discoverAttestations,\n getAttestationsForAddress,\n getAttestationsForIdentity,\n} from './attestation';\nimport { DEFAULT_RELAYS } from './nostr';\nimport { verify } from './verify';\n\nexport interface CheckParams {\n /** Bitcoin address to look up. */\n addr?: string;\n /** Content-addressed attestation ID (hex). */\n id?: string;\n /** Identity binding, e.g. `{ protocol: 'github', identifier: 'alice' }`. */\n identity?: { protocol: string; identifier: string };\n /** Minimum sats bonded to pass. Default 0. */\n minSats?: number;\n /** Minimum days unspent to pass. Default 0. */\n minDays?: number;\n /** Optional relay overrides for discovery. */\n relays?: string[];\n /** Optional verify-time options (esplora bases, test mode). */\n verifyOptions?: VerifyOptions;\n}\n\nexport interface CheckResult {\n /** True iff signature valid AND thresholds met. */\n ok: boolean;\n /** Sats bonded on-chain for the bonded UTXO set. */\n sats: number;\n /** Days since the youngest UTXO in the bonded set was confirmed. */\n days: number;\n /** Reference `score_v0` for this attestation. */\n score: number;\n /** Attestation ID (if one was found). */\n attestation_id?: string;\n /** Bitcoin address of the attestation. */\n address?: string;\n /** Self-asserted identity bindings. Verify independently. */\n identities?: IdentityBinding[];\n /** Network the address belongs to. */\n network?: Network;\n /** Present when `ok === false`. Codes explain why. */\n reasons?: string[];\n}\n\nexport async function check(params: CheckParams): Promise<CheckResult> {\n const {\n addr,\n id,\n identity,\n minSats = 0,\n minDays = 0,\n relays = DEFAULT_RELAYS,\n verifyOptions,\n } = params;\n\n if (!addr && !id && !identity) {\n return { ok: false, sats: 0, days: 0, score: 0, reasons: ['bad_request'] };\n }\n\n let envelopes: AttestationEnvelope[] = [];\n if (id) {\n envelopes = await discoverAttestations({ attestationId: id, relays });\n } else if (addr) {\n envelopes = await getAttestationsForAddress(addr, relays);\n } else if (identity) {\n envelopes = await getAttestationsForIdentity(\n identity.protocol,\n identity.identifier,\n relays\n );\n }\n\n if (envelopes.length === 0) {\n return { ok: false, sats: 0, days: 0, score: 0, reasons: ['not_found'] };\n }\n\n // Prefer most recent.\n envelopes.sort((a, b) => new Date(b.issued_at).getTime() - new Date(a.issued_at).getTime());\n const env = envelopes[0];\n if (!env) {\n return { ok: false, sats: 0, days: 0, score: 0, reasons: ['not_found'] };\n }\n\n const outcome = await verify(\n {\n addr: env.address,\n msg: env.message,\n sig: env.signature,\n scheme: env.scheme,\n },\n verifyOptions\n );\n\n const sats = outcome.metrics?.sats_bonded ?? 0;\n const days = outcome.metrics?.days_unspent ?? 0;\n const score = outcome.metrics?.score ?? 0;\n\n const reasons: string[] = [];\n if (!outcome.ok) reasons.push(...outcome.codes);\n if (sats < minSats) reasons.push('below_min_sats');\n if (days < minDays) reasons.push('below_min_days');\n\n const ok = outcome.ok && sats >= minSats && days >= minDays;\n\n return {\n ok,\n sats,\n days,\n score,\n attestation_id: env.attestation_id,\n address: env.address,\n identities: env.identities,\n network: outcome.network,\n ...(reasons.length ? { reasons } : {}),\n };\n}\n","/**\n * Signed-challenge auth\n *\n * When a gate can't trust the address source (public header, query string,\n * unsigned cookie), run a one-shot BIP-322 challenge first to cryptographically\n * prove the caller controls the address. Bind the proven address to a session\n * cookie or JWT, and the gate reads from there.\n *\n * This is a different wire format from the main OCP attestation — the header\n * literal is `orangecheck-auth`, not `orangecheck`, so a signed auth challenge\n * can never be confused with a reputation attestation.\n *\n * // Server, on the \"connect wallet\" flow:\n * const challenge = issueChallenge({ address, ttlSeconds: 300 });\n * // → send challenge.message to the client\n *\n * // Client signs challenge.message with BIP-322 via the user's wallet,\n * // then posts { message, signature } back.\n *\n * // Server, on callback:\n * const result = await verifyChallenge({ message, signature });\n * if (result.ok) {\n * // result.address is now cryptographically proven; attach to session.\n * }\n */\n\nimport type { Scheme } from './types';\n\nimport { Buffer } from 'buffer';\n\nimport { Verifier } from 'bip322-js';\nimport * as bitcoinMessage from 'bitcoinjs-message';\n\nconst AUTH_HEADER = 'orangecheck-auth';\nconst AUTH_ACK = 'I authorize this session under the OrangeCheck auth challenge.';\n\nfunction randomNonce(): string {\n // 16 bytes → 32 lowercase hex chars. Matches OCP core nonce format.\n const bytes = new Uint8Array(16);\n // Runtimes: Node 20+ (webcrypto), browsers.\n if (typeof globalThis.crypto?.getRandomValues === 'function') {\n globalThis.crypto.getRandomValues(bytes);\n } else {\n // Fallback: Math.random is *not* cryptographic — acceptable only for\n // environments without webcrypto (old Node). Flagged explicitly.\n for (let i = 0; i < bytes.length; i++) bytes[i] = Math.floor(Math.random() * 256);\n }\n return Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');\n}\n\nfunction iso(date: Date): string {\n return date.toISOString().replace(/\\.\\d{3}Z$/, 'Z');\n}\n\nexport interface IssueChallengeOptions {\n /** Bitcoin address the caller claims to control. */\n address: string;\n /** How long the challenge is valid for. Default 300 (5 minutes). */\n ttlSeconds?: number;\n /** Explicit nonce. Rare; prefer auto-generated. */\n nonce?: string;\n /** Origin-binding extension. If set, verify will require a match. */\n audience?: string;\n /** Human-readable label baked into the signed message. */\n purpose?: string;\n /** Freeze `now` for tests. */\n now?: Date;\n}\n\nexport interface Challenge {\n /** The canonical text the client MUST sign. */\n message: string;\n /** The generated nonce (kept for correlation / server-side storage). */\n nonce: string;\n /** Unix ms epoch the challenge expires at. */\n expiresAt: number;\n /** ISO string of the same. */\n expiresAtIso: string;\n}\n\n/**\n * Build a new signed-challenge message. The server MUST remember the nonce\n * it issued against the session (Redis, signed cookie, DB) so it can detect\n * replay or a different nonce coming back on verify.\n */\nexport function issueChallenge(opts: IssueChallengeOptions): Challenge {\n const now = opts.now ?? new Date();\n const ttl = opts.ttlSeconds ?? 300;\n const expiresAt = new Date(now.getTime() + ttl * 1000);\n const nonce = opts.nonce ?? randomNonce();\n\n if (!/^[0-9a-f]{32}$/.test(nonce)) {\n throw new Error('nonce must be 32 lowercase hex characters');\n }\n\n const coreLines = [\n AUTH_HEADER,\n `address: ${opts.address}`,\n `nonce: ${nonce}`,\n `issued_at: ${iso(now)}`,\n `expires_at: ${iso(expiresAt)}`,\n `ack: ${AUTH_ACK}`,\n ];\n\n const extensions: Array<[string, string]> = [];\n if (opts.audience) extensions.push(['audience', opts.audience]);\n if (opts.purpose) extensions.push(['purpose', opts.purpose]);\n // Lexicographic sort by key — matches OCP canonicalization rules.\n extensions.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));\n\n const extLines = extensions.map(([k, v]) => `${k}: ${v}`);\n const message = [...coreLines, ...extLines].join('\\n') + '\\n';\n\n return {\n message,\n nonce,\n expiresAt: expiresAt.getTime(),\n expiresAtIso: iso(expiresAt),\n };\n}\n\ninterface ParsedChallenge {\n address?: string;\n nonce?: string;\n issuedAt?: Date;\n expiresAt?: Date;\n ack?: string;\n audience?: string;\n purpose?: string;\n extensions: Array<[string, string]>;\n}\n\nfunction parseChallenge(message: string): ParsedChallenge {\n const lines = message.endsWith('\\n') ? message.slice(0, -1).split('\\n') : message.split('\\n');\n\n if (lines[0] !== AUTH_HEADER) {\n throw new Error('not an orangecheck-auth challenge');\n }\n\n const out: ParsedChallenge = { extensions: [] };\n const coreKeys = ['address', 'nonce', 'issued_at', 'expires_at', 'ack'] as const;\n const coreKeySet = new Set<string>(coreKeys);\n // Duplicate detection: a challenge with two `address:` lines would\n // previously let the second overwrite the first. A signer who saw both\n // lines would still sign the whole text — which means the verifier and\n // the signer disagree about what the message \"said\". Refuse instead.\n const seenCore = new Set<string>();\n\n for (let i = 1; i < lines.length; i++) {\n const line = lines[i] ?? '';\n const sep = line.indexOf(': ');\n if (sep === -1) continue;\n const key = line.slice(0, sep);\n const val = line.slice(sep + 2);\n\n if (coreKeySet.has(key)) {\n if (seenCore.has(key)) {\n throw new Error(`duplicate core key in challenge: ${key}`);\n }\n seenCore.add(key);\n if (key === 'address') out.address = val;\n else if (key === 'nonce') out.nonce = val;\n else if (key === 'issued_at') out.issuedAt = new Date(val);\n else if (key === 'expires_at') out.expiresAt = new Date(val);\n else if (key === 'ack') out.ack = val;\n } else {\n out.extensions.push([key, val]);\n if (key === 'audience') out.audience = val;\n if (key === 'purpose') out.purpose = val;\n }\n }\n\n if (seenCore.size !== coreKeys.length) {\n throw new Error(`challenge missing core lines (${seenCore.size}/${coreKeys.length})`);\n }\n return out;\n}\n\nexport interface VerifyChallengeOptions {\n /** The signed canonical challenge text, exactly as issued. */\n message: string;\n /** BIP-322 or legacy signature. */\n signature: string;\n /** Scheme override. Default 'bip322'. */\n scheme?: Scheme;\n\n /** If set, require the challenge's `audience:` extension to match. */\n expectedAudience?: string;\n /** If set, require the challenge's `purpose:` extension to match. */\n expectedPurpose?: string;\n /**\n * If set, require the challenge's `nonce:` to match. Use this to defeat\n * replay — pair with server-side nonce storage (Redis / signed cookie).\n */\n expectedNonce?: string;\n\n /** Tolerance on expiry check in ms. Default 0. */\n clockSkewMs?: number;\n /** Freeze `now` for tests. */\n now?: Date;\n}\n\nexport type VerifyChallengeReason =\n | 'ok'\n | 'malformed'\n | 'expired'\n | 'not_yet_valid'\n | 'sig_invalid'\n | 'sig_unsupported_scheme'\n | 'audience_mismatch'\n | 'purpose_mismatch'\n | 'nonce_mismatch';\n\nexport interface VerifyChallengeResult {\n ok: boolean;\n reason: VerifyChallengeReason;\n /** Present on success — the cryptographically proven Bitcoin address. */\n address?: string;\n /** Present on success — when the challenge expires (unix ms). */\n expiresAt?: number;\n /** Present on success — the nonce from the challenge. */\n nonce?: string;\n /** Present on success — the audience extension, if any. */\n audience?: string;\n /** Present on success — the purpose extension, if any. */\n purpose?: string;\n}\n\n/**\n * Verify a signed challenge. Returns the proven address on success.\n *\n * The caller is responsible for nonce replay prevention — pass `expectedNonce`\n * with the value you stashed at issue time.\n */\nexport async function verifyChallenge(\n opts: VerifyChallengeOptions\n): Promise<VerifyChallengeResult> {\n let parsed: ParsedChallenge;\n try {\n parsed = parseChallenge(opts.message);\n } catch {\n return { ok: false, reason: 'malformed' };\n }\n\n const { address, nonce, issuedAt, expiresAt, ack, audience, purpose } = parsed;\n if (!address || !nonce || !issuedAt || !expiresAt || !ack) {\n return { ok: false, reason: 'malformed' };\n }\n if (ack !== AUTH_ACK) {\n return { ok: false, reason: 'malformed' };\n }\n if (!/^[0-9a-f]{32}$/.test(nonce)) {\n return { ok: false, reason: 'malformed' };\n }\n\n const now = opts.now ?? new Date();\n const skew = opts.clockSkewMs ?? 0;\n\n if (now.getTime() - skew > expiresAt.getTime()) {\n return { ok: false, reason: 'expired' };\n }\n if (now.getTime() + skew < issuedAt.getTime()) {\n return { ok: false, reason: 'not_yet_valid' };\n }\n\n if (opts.expectedNonce && nonce !== opts.expectedNonce) {\n return { ok: false, reason: 'nonce_mismatch' };\n }\n if (opts.expectedAudience && audience !== opts.expectedAudience) {\n return { ok: false, reason: 'audience_mismatch' };\n }\n if (opts.expectedPurpose && purpose !== opts.expectedPurpose) {\n return { ok: false, reason: 'purpose_mismatch' };\n }\n\n const scheme: Scheme = opts.scheme ?? 'bip322';\n let sigValid = false;\n\n try {\n if (scheme === 'bip322') {\n const sigBase64 =\n /^[0-9a-fA-F]+$/.test(opts.signature) && opts.signature.length % 2 === 0\n ? Buffer.from(opts.signature, 'hex').toString('base64')\n : opts.signature;\n sigValid = Verifier.verifySignature(address, opts.message, sigBase64);\n } else if (scheme === 'legacy') {\n // Legacy signmessage only works for P2PKH addresses.\n if (!/^[1m][a-km-zA-HJ-NP-Z1-9]{25,34}$/.test(address)) {\n return { ok: false, reason: 'sig_unsupported_scheme' };\n }\n sigValid = bitcoinMessage.verify(opts.message, address, opts.signature);\n } else {\n return { ok: false, reason: 'sig_unsupported_scheme' };\n }\n } catch {\n sigValid = false;\n }\n\n if (!sigValid) return { ok: false, reason: 'sig_invalid' };\n\n return {\n ok: true,\n reason: 'ok',\n address,\n expiresAt: expiresAt.getTime(),\n nonce,\n ...(audience !== undefined ? { audience } : {}),\n ...(purpose !== undefined ? { purpose } : {}),\n };\n}\n","/**\n * Simple in-memory rate limiter\n */\n\n/**\n * Rate limiter configuration\n */\nexport interface RateLimiter {\n /** Maximum number of requests allowed in the time window */\n readonly maxRequests: number;\n /** Time window in milliseconds */\n readonly windowMs: number;\n /** Internal request tracking map */\n readonly requests: Map<string, number[]>;\n}\n\n/**\n * Rate limit error\n */\nexport class RateLimitError extends Error {\n constructor(message = 'Rate limit exceeded. Please try again later.') {\n super(message);\n this.name = 'RateLimitError';\n }\n}\n\n/**\n * Create a rate limiter\n * @param maxRequests - Maximum requests allowed in the time window\n * @param windowMs - Time window in milliseconds\n * @returns Rate limiter instance\n */\nexport function createRateLimiter(maxRequests: number, windowMs: number): RateLimiter {\n if (maxRequests <= 0) {\n throw new Error('maxRequests must be greater than 0');\n }\n if (windowMs <= 0) {\n throw new Error('windowMs must be greater than 0');\n }\n\n return {\n maxRequests,\n windowMs,\n requests: new Map<string, number[]>(),\n };\n}\n\n/**\n * Check if a request is within rate limits\n * @param limiter - Rate limiter instance\n * @param key - Unique key for the request (e.g., user ID, IP address)\n * @returns True if request is allowed, false if rate limit exceeded\n */\nexport function checkRateLimit(limiter: RateLimiter, key: string): boolean {\n const now = Date.now();\n const requests = limiter.requests.get(key) ?? [];\n\n // Remove old requests outside the window\n const validRequests = requests.filter((timestamp) => now - timestamp < limiter.windowMs);\n\n // Check if limit exceeded\n if (validRequests.length >= limiter.maxRequests) {\n return false;\n }\n\n // Add new request\n validRequests.push(now);\n limiter.requests.set(key, validRequests);\n\n return true;\n}\n\n/**\n * Enforce rate limit, throwing an error if exceeded\n * @param limiter - Rate limiter instance\n * @param key - Unique key for the request\n * @throws {RateLimitError} If rate limit is exceeded\n */\nexport function enforceRateLimit(limiter: RateLimiter, key: string): void {\n if (!checkRateLimit(limiter, key)) {\n throw new RateLimitError();\n }\n}\n\n/**\n * Get remaining requests for a key\n * @param limiter - Rate limiter instance\n * @param key - Unique key for the request\n * @returns Number of remaining requests in the current window\n */\nexport function getRemainingRequests(limiter: RateLimiter, key: string): number {\n const now = Date.now();\n const requests = limiter.requests.get(key) ?? [];\n const validRequests = requests.filter((timestamp) => now - timestamp < limiter.windowMs);\n return Math.max(0, limiter.maxRequests - validRequests.length);\n}\n\n/**\n * Reset rate limit for a key\n * @param limiter - Rate limiter instance\n * @param key - Unique key to reset\n */\nexport function resetRateLimit(limiter: RateLimiter, key: string): void {\n limiter.requests.delete(key);\n}\n\n/**\n * Default rate limiter for identity verification\n * 5 requests per minute\n */\nexport const identityVerificationLimiter = createRateLimiter(5, 60000);\n","/**\n * DNS Identity Verification\n * Verifies that a user controls a DNS domain\n */\n\nimport { createLogger } from '../utils/logger';\n\nconst log = createLogger('identity-verification/dns');\n\n/** Public-internet check. Blocks literal private/loopback/link-local hosts\n * from being reached via the well-known file verifier — otherwise a caller\n * running this server-side is an SSRF primitive (cloud metadata, internal\n * services, etc.). We don't do full DNS resolution here — TLD/label shape\n * checks + literal-IP rejection are the cheap layers. Production verifiers\n * running this untrusted should add DNS-pinning on top.\n */\nconst PRIVATE_HOST_RE =\n /^(?:localhost|.*\\.local|.*\\.internal|.*\\.localhost|.*\\.lan|.*\\.home|.*\\.arpa|\\[?::1\\]?|\\[?::\\]?)$/i;\nconst PRIVATE_IPV4_RE =\n /^(?:10\\.|127\\.|169\\.254\\.|192\\.168\\.|172\\.(?:1[6-9]|2\\d|3[01])\\.|0\\.|100\\.(?:6[4-9]|[7-9]\\d|1[01]\\d|12[0-7])\\.|22[4-9]\\.|23\\d\\.|24\\d\\.|25[0-5]\\.)/;\n\n/** Tight fetch deadline so a slow target can't stall the verifier. */\nconst WELL_KNOWN_TIMEOUT_MS = 5_000;\n\nfunction isSafePublicHost(host: string): boolean {\n const h = host.toLowerCase();\n if (PRIVATE_HOST_RE.test(h)) return false;\n if (PRIVATE_IPV4_RE.test(h)) return false;\n // IPv6 literal — we don't enumerate every private range; reject bracketed\n // literals entirely (no legitimate verification target is an IPv6 literal).\n if (h.startsWith('[') || /^[0-9a-f:]+$/.test(h)) return false;\n return true;\n}\n\n/**\n * Verification result for DNS identity\n */\nexport interface DnsVerificationResult {\n verified: boolean;\n method?: 'well-known' | 'dns-txt';\n url?: string;\n error?: string;\n}\n\n/**\n * Verify that a user controls a DNS domain\n *\n * Verification methods (in order of preference):\n * 1. Check .well-known/orangecheck.txt file\n * 2. Check DNS TXT record (requires server-side DNS lookup)\n *\n * @param attestationId - The attestation ID to look for\n * @param domain - The domain name (without protocol)\n * @returns Verification result\n */\nexport async function verifyDnsIdentity(\n attestationId: string,\n domain: string\n): Promise<DnsVerificationResult> {\n log.info({ attestationId, domain }, 'Verifying DNS identity');\n\n // Clean domain (remove protocol if present)\n const cleanDomain = domain.replace(/^https?:\\/\\//, '').replace(/\\/$/, '');\n\n // Shape + SSRF guards before we ever hand this to fetch().\n if (!isValidDomain(cleanDomain)) {\n return { verified: false, error: `invalid domain format: ${cleanDomain}` };\n }\n if (!isSafePublicHost(cleanDomain)) {\n return { verified: false, error: 'domain resolves to a disallowed private host' };\n }\n\n // Try .well-known file first\n const wellKnownResult = await checkWellKnownFile(attestationId, cleanDomain);\n if (wellKnownResult.verified) {\n return wellKnownResult;\n }\n\n // DNS TXT record check requires server-side implementation\n // For now, return instructions\n log.info({ domain: cleanDomain }, 'Well-known file not found, DNS TXT check not implemented');\n\n return {\n verified: false,\n error: 'Verification file not found. Please create .well-known/orangecheck.txt',\n };\n}\n\n/**\n * Check .well-known/orangecheck.txt file\n */\nasync function checkWellKnownFile(\n attestationId: string,\n domain: string\n): Promise<DnsVerificationResult> {\n // HTTPS only. The old HTTP fallback meant a MITM / hostile network could\n // forge a passing verification; dropping it costs us nothing — any real\n // domain worth attesting to has TLS in 2026.\n const url = `https://${domain}/.well-known/orangecheck.txt`;\n\n try {\n log.info({ url }, 'Checking well-known file');\n\n const response = await fetch(url, {\n method: 'GET',\n headers: { Accept: 'text/plain' },\n // Don't follow redirects to other domains\n redirect: 'manual',\n signal: AbortSignal.timeout(WELL_KNOWN_TIMEOUT_MS),\n });\n\n if (response.ok) {\n const content = await response.text();\n\n if (content.includes(attestationId)) {\n log.info({ domain, url }, 'Found attestation ID in well-known file');\n return {\n verified: true,\n method: 'well-known',\n url,\n };\n } else {\n log.info({ domain, url }, 'Well-known file exists but no attestation ID found');\n }\n }\n } catch (err) {\n log.warn({ error: err, url }, 'Failed to fetch well-known file');\n }\n\n return {\n verified: false,\n error: 'Well-known file not found or does not contain attestation ID',\n };\n}\n\n/**\n * Get verification instructions for DNS identity\n */\nexport function getDnsVerificationInstructions(attestationId: string, domain: string): string {\n const cleanDomain = domain.replace(/^https?:\\/\\//, '').replace(/\\/$/, '');\n\n return `To verify your DNS domain (${cleanDomain}):\n\n**Method 1: .well-known file (Recommended)**\n\n1. Create a file at: https://${cleanDomain}/.well-known/orangecheck.txt\n2. Add this content to the file:\n\n OrangeCheck Attestation Verification\n Domain: ${cleanDomain}\n Attestation ID: ${attestationId}\n Timestamp: ${new Date().toISOString()}\n\n3. Make sure the file is publicly accessible\n4. Return here and click \"Verify\"\n\n**Method 2: DNS TXT record (Advanced)**\n\n1. Add a TXT record to your DNS:\n Name: _orangecheck.${cleanDomain}\n Value: ${attestationId}\n\n2. Wait for DNS propagation (up to 24 hours)\n3. Return here and click \"Verify\"\n\nNote: Method 1 is faster and easier to set up.`;\n}\n\n/**\n * Generate well-known file content\n */\nexport function generateWellKnownContent(attestationId: string, domain: string): string {\n const cleanDomain = domain.replace(/^https?:\\/\\//, '').replace(/\\/$/, '');\n\n return `OrangeCheck Attestation Verification\n=====================================\n\nDomain: ${cleanDomain}\nAttestation ID: ${attestationId}\nTimestamp: ${new Date().toISOString()}\n\nThis file verifies that the owner of ${cleanDomain} controls the Bitcoin\naddress associated with attestation ${attestationId}.\n\nLearn more: https://ochk.io\n\n---\n\nVerification method: .well-known/orangecheck.txt\nProtocol: OrangeCheck Protocol (OCP)\n`;\n}\n\n/**\n * Get the expected well-known file URL\n */\nexport function getWellKnownUrl(domain: string): string {\n const cleanDomain = domain.replace(/^https?:\\/\\//, '').replace(/\\/$/, '');\n return `https://${cleanDomain}/.well-known/orangecheck.txt`;\n}\n\n/**\n * Validate domain format\n */\nexport function isValidDomain(domain: string): boolean {\n const cleanDomain = domain.replace(/^https?:\\/\\//, '').replace(/\\/$/, '');\n\n // Basic domain validation\n const domainPattern = /^[a-z0-9]+([\\-\\.]{1}[a-z0-9]+)*\\.[a-z]{2,}$/i;\n return domainPattern.test(cleanDomain);\n}\n\n/**\n * Check if a DNS identity is already verified\n * This is a quick check using cached data\n */\nexport function isDnsIdentityVerified(\n attestationId: string,\n _domain: string,\n cachedContent?: string\n): boolean {\n if (!cachedContent) {\n return false;\n }\n\n return cachedContent.includes(attestationId);\n}\n","/**\n * GitHub Identity Verification\n * Verifies that a user controls a GitHub identity by checking for gists\n */\n\nimport { createLogger } from '../utils/logger';\n\nconst log = createLogger('identity-verification/github');\n\n/**\n * Gist file bodies are fetched from `raw_url`. GitHub serves these from\n * `gist.githubusercontent.com`, but `raw_url` is *server-controlled* — a\n * malicious response could point it anywhere (internal IPs, 169.254.169.254,\n * file://, etc.) and our verifier would happily fetch it. Allow-list the\n * expected host to close the SSRF door.\n */\nconst GITHUB_GIST_RAW_HOST = 'gist.githubusercontent.com';\n\n/** Cap fan-out so a user with 1k gists × many files can't pin the verifier. */\nconst MAX_GISTS_SCANNED = 30;\nconst MAX_FILES_PER_GIST = 10;\n\n/** Tight per-request deadline. Github is usually under 300ms. */\nconst FETCH_TIMEOUT_MS = 5_000;\n\n/** Reject usernames that don't match GitHub's published allowed character set\n * before we interpolate them into a URL. */\nconst GITHUB_USERNAME_RE = /^[a-zA-Z0-9](?:[a-zA-Z0-9]|-(?=[a-zA-Z0-9])){0,38}$/;\n\nfunction isSafeGistRawUrl(raw: string): boolean {\n try {\n const u = new URL(raw);\n return u.protocol === 'https:' && u.hostname === GITHUB_GIST_RAW_HOST;\n } catch {\n return false;\n }\n}\n\n/**\n * Verification result for GitHub identity\n */\nexport interface GitHubVerificationResult {\n verified: boolean;\n gistUrl?: string;\n gistId?: string;\n error?: string;\n}\n\n/**\n * GitHub gist file structure\n */\ninterface GitHubGistFile {\n filename: string;\n type: string;\n language: string | null;\n raw_url: string;\n size: number;\n content?: string;\n}\n\n/**\n * GitHub gist structure\n */\ninterface GitHubGist {\n id: string;\n html_url: string;\n description: string;\n public: boolean;\n created_at: string;\n updated_at: string;\n files: Record<string, GitHubGistFile>;\n}\n\n/**\n * Verify that a user controls a GitHub identity\n *\n * Verification method:\n * 1. Query GitHub API for user's public gists\n * 2. Check if any gist file contains the attestation ID\n * 3. Return the gist URL as proof\n *\n * @param attestationId - The attestation ID to look for\n * @param username - The GitHub username\n * @returns Verification result with gist URL if verified\n */\nexport async function verifyGitHubIdentity(\n attestationId: string,\n username: string\n): Promise<GitHubVerificationResult> {\n log.info({ attestationId, username }, 'Verifying GitHub identity');\n\n if (!GITHUB_USERNAME_RE.test(username)) {\n return { verified: false, error: 'invalid GitHub username format' };\n }\n\n try {\n // Query GitHub API for user's gists\n const response = await fetch(\n `https://api.github.com/users/${encodeURIComponent(username)}/gists?per_page=${MAX_GISTS_SCANNED}`,\n {\n headers: { Accept: 'application/vnd.github.v3+json' },\n signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),\n }\n );\n\n if (!response.ok) {\n if (response.status === 404) {\n return {\n verified: false,\n error: `GitHub user '${username}' not found`,\n };\n }\n\n return {\n verified: false,\n error: `GitHub API error: ${response.status} ${response.statusText}`,\n };\n }\n\n const gists = (await response.json()) as GitHubGist[];\n\n log.info({ username, gistCount: gists.length }, 'Fetched GitHub gists');\n\n // Check each gist for attestation ID (capped fan-out)\n for (const gist of gists.slice(0, MAX_GISTS_SCANNED)) {\n // Check gist description\n if (gist.description?.includes(attestationId)) {\n log.info({ username, gistId: gist.id }, 'Found attestation ID in gist description');\n return {\n verified: true,\n gistUrl: gist.html_url,\n gistId: gist.id,\n };\n }\n\n // Check each file in the gist (capped)\n const files = Object.entries(gist.files).slice(0, MAX_FILES_PER_GIST);\n for (const [filename, file] of files) {\n // If content is available, check it\n if (file.content && file.content.includes(attestationId)) {\n log.info(\n { username, gistId: gist.id, filename },\n 'Found attestation ID in gist file'\n );\n return {\n verified: true,\n gistUrl: gist.html_url,\n gistId: gist.id,\n };\n }\n\n // If content not available, fetch it from raw_url — but only\n // if raw_url is a real GitHub-hosted URL. Without the allow-list\n // we're an SSRF primitive for anyone controlling the API\n // response (including via a compromised GitHub mirror / MITM).\n if (!isSafeGistRawUrl(file.raw_url)) {\n log.warn(\n { filename, rawUrl: file.raw_url },\n 'skipping gist file: raw_url failed allow-list'\n );\n continue;\n }\n\n try {\n const fileResponse = await fetch(file.raw_url, {\n signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),\n });\n if (fileResponse.ok) {\n const content = await fileResponse.text();\n if (content.includes(attestationId)) {\n log.info(\n { username, gistId: gist.id, filename },\n 'Found attestation ID in gist file (fetched)'\n );\n return {\n verified: true,\n gistUrl: gist.html_url,\n gistId: gist.id,\n };\n }\n }\n } catch (err) {\n log.warn({ error: err, filename }, 'Failed to fetch gist file content');\n }\n }\n }\n\n log.info({ username }, 'No verification gist found');\n return {\n verified: false,\n error: 'No gist found containing the attestation ID',\n };\n } catch (err) {\n log.error({ error: err, username }, 'Failed to verify GitHub identity');\n return {\n verified: false,\n error: err instanceof Error ? err.message : 'Unknown error',\n };\n }\n}\n\n/**\n * Get verification instructions for GitHub identity\n */\nexport function getGitHubVerificationInstructions(attestationId: string): string {\n return `To verify your GitHub identity:\n\n1. Go to https://gist.github.com\n2. Create a new public gist\n3. Add a file with any name (e.g., \"orangecheck.txt\")\n4. Paste this text into the file:\n\n OrangeCheck Attestation Verification\n Attestation ID: ${attestationId}\n\n5. Click \"Create public gist\"\n6. Return here and click \"Verify\" to check\n\nThe verification will search your public gists for this attestation ID.`;\n}\n\n/**\n * Generate a gist template for verification\n */\nexport function generateGistTemplate(attestationId: string, username: string): string {\n return `# OrangeCheck Attestation Verification\n\nI am verifying my GitHub identity (@${username}) for OrangeCheck.\n\n**Attestation ID:** \\`${attestationId}\\`\n\n**Timestamp:** ${new Date().toISOString()}\n\nThis gist proves that I control both:\n- GitHub account: @${username}\n- Bitcoin address associated with attestation ${attestationId}\n\n---\n\nLearn more about OrangeCheck: https://ochk.io\n`;\n}\n\n/**\n * Check if a GitHub identity is already verified\n * This is a quick check using cached gist data\n */\nexport function isGitHubIdentityVerified(\n attestationId: string,\n _username: string,\n cachedGists: GitHubGist[]\n): boolean {\n return cachedGists.some((gist) => {\n // Check description\n if (gist.description?.includes(attestationId)) {\n return true;\n }\n\n // Check files\n return Object.values(gist.files).some((file) => file.content?.includes(attestationId));\n });\n}\n\n/**\n * Get direct link to create a verification gist. The args are accepted for\n * API parity with other identity providers but unused — GitHub doesn't accept\n * pre-fill params on the gist creation page.\n */\nexport function getGistCreationUrl(): string {\n return 'https://gist.github.com/';\n}\n","/**\n * Nostr Identity Verification\n * Verifies that a user controls a Nostr identity by checking for proof events\n *\n * Two previous bugs in this file made verification a lie:\n * 1. `npubToHex` returned the bech32 string unchanged when given an npub\n * (only the already-hex branch worked). Downstream authors filters used\n * \"npub1…\" as a literal Nostr pubkey, which no relay indexes — so the\n * search *always* returned zero events and fell through to \"no proof\".\n * Benign false-negative, except combined with (2).\n * 2. `verifyNostrEventSignature` returned `true` for any event with a\n * 128-char-hex-looking `sig`. No actual schnorr check. An attacker\n * could publish a note from any pubkey, drop someone else's attestation\n * ID into its content, and the verifier would accept.\n *\n * Fixed by decoding npubs with @scure/base's bech32 and verifying the event\n * signature with @noble/curves' schnorr over sha256(id-preimage).\n */\n\nimport type { NostrEvent } from '../types';\n\nimport { schnorr } from '@noble/curves/secp256k1.js';\nimport { sha256 } from '@noble/hashes/sha2.js';\nimport { bech32 } from '@scure/base';\n\nimport { DEFAULT_RELAYS } from '../nostr';\nimport { createLogger } from '../utils/logger';\n\nconst log = createLogger('identity-verification/nostr');\n\nconst HEX_64_RE = /^[0-9a-f]{64}$/;\n\nfunction toHex(bytes: Uint8Array): string {\n let out = '';\n for (const b of bytes) out += b.toString(16).padStart(2, '0');\n return out;\n}\n\nfunction fromHex(hex: string): Uint8Array {\n if (hex.length % 2 !== 0) throw new Error('odd-length hex');\n const out = new Uint8Array(hex.length / 2);\n for (let i = 0; i < out.length; i++) {\n out[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);\n }\n return out;\n}\n\n/**\n * Verification result for Nostr identity\n */\nexport interface NostrVerificationResult {\n verified: boolean;\n event?: NostrEvent;\n error?: string;\n}\n\n/**\n * Decode a Nostr public key in `npub1…` bech32 form (or pass through if\n * already 64-char hex). Throws on invalid input — callers should treat a\n * throw as \"not a valid npub\" and fail closed.\n */\nfunction npubToHex(npub: string): string {\n const trimmed = npub.trim();\n if (HEX_64_RE.test(trimmed.toLowerCase())) {\n return trimmed.toLowerCase();\n }\n if (!trimmed.toLowerCase().startsWith('npub1')) {\n throw new Error(`not an npub: ${trimmed.slice(0, 12)}…`);\n }\n // `@scure/base` bech32 decoder; unlimited length is fine for NIP-19.\n const decoded = bech32.decode(trimmed.toLowerCase() as `${string}1${string}`, 1023);\n if (decoded.prefix !== 'npub') {\n throw new Error(`bech32 prefix mismatch: expected npub, got ${decoded.prefix}`);\n }\n const bytes = bech32.fromWords(decoded.words);\n if (bytes.length !== 32) {\n throw new Error(`invalid npub payload length: ${bytes.length}`);\n }\n return toHex(Uint8Array.from(bytes));\n}\n\n/**\n * Query Nostr relays for events from a specific author\n */\nasync function queryNostrEvents(options: {\n authors: string[];\n kinds: number[];\n search?: string;\n relays?: string[];\n limit?: number;\n}): Promise<NostrEvent[]> {\n const { authors, kinds, search, relays = DEFAULT_RELAYS, limit = 100 } = options;\n const events: NostrEvent[] = [];\n\n log.info({ authors, kinds, relayCount: relays.length }, 'Querying Nostr for events');\n\n const queryPromises = relays.map(async (relayUrl) => {\n let ws: WebSocket | null = null;\n\n try {\n ws = new WebSocket(relayUrl);\n const wsRef = ws;\n\n await new Promise<void>((resolve, reject) => {\n const timeout = setTimeout(() => {\n wsRef.close();\n reject(new Error('Query timeout'));\n }, 10000);\n\n const cleanup = () => {\n clearTimeout(timeout);\n wsRef.close();\n };\n\n wsRef.onopen = () => {\n const subscriptionId = `verify_${Date.now()}`;\n const filter: Record<string, unknown> = {\n authors,\n kinds,\n limit,\n };\n\n wsRef.send(JSON.stringify(['REQ', subscriptionId, filter]));\n };\n\n wsRef.onmessage = (msg) => {\n try {\n const data = JSON.parse(msg.data);\n if (data[0] === 'EVENT') {\n const event = data[2] as NostrEvent;\n\n // If search term provided, filter by content\n if (search) {\n if (event.content.includes(search)) {\n events.push(event);\n }\n } else {\n events.push(event);\n }\n } else if (data[0] === 'EOSE') {\n cleanup();\n resolve();\n }\n } catch (err) {\n log.error({ relay: relayUrl, error: err }, 'Failed to parse event');\n }\n };\n\n wsRef.onerror = (err) => {\n log.error({ relay: relayUrl, error: err }, 'WebSocket error during query');\n cleanup();\n reject(err);\n };\n\n wsRef.onclose = () => {\n clearTimeout(timeout);\n };\n });\n } catch (err) {\n log.error({ relay: relayUrl, error: err }, 'Failed to query relay');\n } finally {\n if (ws && ws.readyState !== WebSocket.CLOSED) {\n ws.close();\n }\n }\n });\n\n await Promise.allSettled(queryPromises);\n\n log.info({ eventCount: events.length }, 'Query complete');\n\n return events;\n}\n\n/**\n * Verify a Nostr event's schnorr signature per NIP-01:\n *\n * id = sha256(JSON.stringify([0, pubkey, created_at, kind, tags, content]))\n * sig = schnorr_sign(id, secret_key)\n * check = schnorr_verify(id, pubkey, sig)\n *\n * Fails closed on any shape problem, decoding error, or mismatch. A true\n * return from this function is the ONLY thing that should be treated as\n * proof the event really came from the claimed pubkey.\n */\nasync function verifyNostrEventSignature(event: NostrEvent): Promise<boolean> {\n try {\n if (\n !event.id ||\n !event.sig ||\n !event.pubkey ||\n typeof event.id !== 'string' ||\n typeof event.sig !== 'string' ||\n typeof event.pubkey !== 'string' ||\n event.sig.length !== 128 ||\n !HEX_64_RE.test(event.id) ||\n !HEX_64_RE.test(event.pubkey)\n ) {\n return false;\n }\n\n // Recompute the event id from the canonical NIP-01 preimage. If the\n // relay (or an attacker) altered any field since signing, id won't\n // match and we reject.\n const preimage = JSON.stringify([\n 0,\n event.pubkey,\n event.created_at,\n event.kind,\n event.tags ?? [],\n event.content ?? '',\n ]);\n const computedId = toHex(sha256(new TextEncoder().encode(preimage)));\n if (computedId !== event.id.toLowerCase()) {\n log.warn(\n { eventId: event.id, computedId },\n 'nostr event id does not match its content'\n );\n return false;\n }\n\n return schnorr.verify(fromHex(event.sig), fromHex(event.id), fromHex(event.pubkey));\n } catch (err) {\n log.warn({ err }, 'schnorr verify threw');\n return false;\n }\n}\n\n/**\n * Verify that a user controls a Nostr identity\n *\n * Verification method:\n * 1. Query Nostr relays for kind 1 (text note) events from the claimed npub\n * 2. Check if any event content contains the attestation ID\n * 3. Verify the event signature\n *\n * @param attestationId - The attestation ID to look for\n * @param npub - The Nostr public key (npub format or hex)\n * @param relays - Optional list of relays to query\n * @returns Verification result with proof event if verified\n */\nexport async function verifyNostrIdentity(\n attestationId: string,\n npub: string,\n relays?: string[]\n): Promise<NostrVerificationResult> {\n log.info({ attestationId, npub }, 'Verifying Nostr identity');\n\n try {\n // Convert npub to hex if needed\n const pubkeyHex = npubToHex(npub);\n\n // Query Nostr for kind 1 events from this pubkey containing attestation ID\n const events = await queryNostrEvents({\n authors: [pubkeyHex],\n kinds: [1], // Text notes\n search: attestationId,\n relays,\n });\n\n if (events.length === 0) {\n log.info({ npub }, 'No verification events found');\n return {\n verified: false,\n error: 'No verification event found. User must post a note containing the attestation ID.',\n };\n }\n\n // Check each event for attestation ID and verify signature\n for (const event of events) {\n if (event.content.includes(attestationId)) {\n // Verify event signature\n const isValid = await verifyNostrEventSignature(event);\n\n if (isValid) {\n log.info({ npub, eventId: event.id }, 'Nostr identity verified');\n return {\n verified: true,\n event,\n };\n } else {\n log.warn({ npub, eventId: event.id }, 'Invalid event signature');\n }\n }\n }\n\n return {\n verified: false,\n error: 'Found events but none had valid signatures',\n };\n } catch (err) {\n log.error({ error: err, npub }, 'Failed to verify Nostr identity');\n return {\n verified: false,\n error: err instanceof Error ? err.message : 'Unknown error',\n };\n }\n}\n\n/**\n * Get verification instructions for Nostr identity\n */\nexport function getNostrVerificationInstructions(attestationId: string): string {\n return `To verify your Nostr identity:\n\n1. Open your Nostr client (Damus, Amethyst, Primal, etc.)\n2. Post a note containing this text:\n\n Verifying my OrangeCheck attestation: ${attestationId}\n\n3. Wait a few seconds for the note to propagate to relays\n4. Return here and click \"Verify\" to check\n\nThe verification will search Nostr relays for your note and confirm you control this identity.`;\n}\n\n/**\n * Check if a Nostr identity is already verified\n * This is a quick check that doesn't re-query relays\n */\nexport function isNostrIdentityVerified(\n attestationId: string,\n npub: string,\n cachedEvents: NostrEvent[]\n): boolean {\n const pubkeyHex = npubToHex(npub);\n\n return cachedEvents.some(\n (event) =>\n event.pubkey === pubkeyHex && event.kind === 1 && event.content.includes(attestationId)\n );\n}\n","/**\n * Twitter Identity Verification\n * Verifies that a user controls a Twitter identity\n *\n * Note: Twitter API requires authentication and has rate limits.\n * This implementation uses manual verification where the user provides a tweet URL.\n */\n\nimport { createLogger } from '../utils/logger';\n\nconst log = createLogger('identity-verification/twitter');\n\n/**\n * Verification result for Twitter identity\n */\nexport interface TwitterVerificationResult {\n verified: boolean;\n tweetUrl?: string;\n tweetId?: string;\n error?: string;\n}\n\n/**\n * Verify Twitter identity via manual tweet URL\n *\n * @param attestationId - The attestation ID to look for\n * @param handle - The Twitter handle (with or without @)\n * @param tweetUrl - Optional tweet URL provided by user\n * @returns Verification result\n */\nexport async function verifyTwitterIdentity(\n attestationId: string,\n handle: string,\n tweetUrl?: string\n): Promise<TwitterVerificationResult> {\n log.info({ attestationId, handle, tweetUrl }, 'Verifying Twitter identity');\n\n if (!tweetUrl) {\n return {\n verified: false,\n error: 'Tweet URL required for verification',\n };\n }\n\n try {\n // Extract tweet ID from URL\n const tweetId = extractTweetId(tweetUrl);\n\n if (!tweetId) {\n return {\n verified: false,\n error: 'Invalid tweet URL format',\n };\n }\n\n // For now, we can't verify without Twitter API access\n // Return instructions for manual verification\n log.info({ handle, tweetId }, 'Manual verification required');\n\n return {\n verified: false,\n tweetUrl,\n tweetId,\n error: 'Automatic verification not available. Please verify manually by checking the tweet.',\n };\n } catch (err) {\n log.error({ error: err, handle }, 'Failed to verify Twitter identity');\n return {\n verified: false,\n error: err instanceof Error ? err.message : 'Unknown error',\n };\n }\n}\n\n/**\n * Extract tweet ID from various Twitter URL formats\n */\nfunction extractTweetId(url: string): string | null {\n // Support various Twitter URL formats:\n // https://twitter.com/username/status/1234567890\n // https://x.com/username/status/1234567890\n // https://mobile.twitter.com/username/status/1234567890\n\n const patterns = [\n /(?:twitter\\.com|x\\.com)\\/\\w+\\/status\\/(\\d+)/,\n /(?:mobile\\.twitter\\.com)\\/\\w+\\/status\\/(\\d+)/,\n ];\n\n for (const pattern of patterns) {\n const match = url.match(pattern);\n if (match && match[1]) {\n return match[1];\n }\n }\n\n return null;\n}\n\n/**\n * Get verification instructions for Twitter identity\n */\nexport function getTwitterVerificationInstructions(attestationId: string, handle: string): string {\n const cleanHandle = handle.startsWith('@') ? handle.slice(1) : handle;\n\n return `To verify your Twitter identity (@${cleanHandle}):\n\n1. Go to https://twitter.com/compose/tweet\n2. Post a tweet with this text:\n\n Verifying my OrangeCheck attestation: ${attestationId}\n\n3. After posting, copy the tweet URL\n4. Paste the URL below and click \"Verify\"\n\nExample tweet URL:\nhttps://twitter.com/${cleanHandle}/status/1234567890\n\nThe verification will check that the tweet exists and contains the attestation ID.`;\n}\n\n/**\n * Generate tweet text for verification\n */\nexport function generateTweetText(attestationId: string): string {\n return `Verifying my OrangeCheck attestation: ${attestationId}\n\nProving Bitcoin reputation with cryptographic signatures.\n\n#OrangeCheck #Bitcoin`;\n}\n\n/**\n * Get direct link to compose a verification tweet\n */\nexport function getTwitterComposeUrl(attestationId: string): string {\n const text = generateTweetText(attestationId);\n const encoded = encodeURIComponent(text);\n\n return `https://twitter.com/intent/tweet?text=${encoded}`;\n}\n\n/**\n * Validate tweet URL format\n */\nexport function isValidTweetUrl(url: string): boolean {\n return extractTweetId(url) !== null;\n}\n\n/**\n * Get tweet URL from handle and tweet ID\n */\nexport function getTweetUrl(handle: string, tweetId: string): string {\n const cleanHandle = handle.startsWith('@') ? handle.slice(1) : handle;\n return `https://twitter.com/${cleanHandle}/status/${tweetId}`;\n}\n\n/**\n * Manual verification helper\n * Returns instructions for verifier to manually check the tweet\n */\nexport function getManualVerificationInstructions(\n attestationId: string,\n handle: string,\n tweetUrl: string\n): string {\n return `Manual Verification Steps:\n\n1. Open this tweet: ${tweetUrl}\n2. Verify it's posted by @${handle}\n3. Check that the tweet contains: ${attestationId}\n4. Confirm the tweet is public and not deleted\n\nIf all checks pass, the identity is verified.`;\n}\n","import type { IdentityBinding } from '../types';\nimport type { DnsVerificationResult } from './dns';\nimport type { GitHubVerificationResult } from './github';\nimport type { NostrVerificationResult } from './nostr';\nimport type { TwitterVerificationResult } from './twitter';\n\nimport { logVerificationError } from '../utils/logger';\nimport { enforceRateLimit, identityVerificationLimiter } from '../utils/rate-limiter';\nimport { getDnsVerificationInstructions, verifyDnsIdentity } from './dns';\nimport { getGitHubVerificationInstructions, verifyGitHubIdentity } from './github';\nimport { getNostrVerificationInstructions, verifyNostrIdentity } from './nostr';\nimport { getTwitterVerificationInstructions, verifyTwitterIdentity } from './twitter';\n\n/**\n * Identity Verification\n *\n * Unified API for verifying identity bindings across multiple protocols\n */\n\nexport * from './nostr';\nexport * from './github';\nexport * from './twitter';\nexport * from './dns';\n\n/**\n * Unified verification result across all protocols\n */\nexport type VerificationResult =\n | NostrVerificationResult\n | GitHubVerificationResult\n | TwitterVerificationResult\n | DnsVerificationResult;\n\n/**\n * Options for identity verification\n */\nexport interface VerifyIdentityOptions {\n /** Tweet URL for Twitter verification */\n tweetUrl?: string;\n /** Relay URLs for Nostr verification */\n relays?: string[];\n}\n\n/**\n * Verify an identity binding\n *\n * @param attestationId - The attestation ID to verify against\n * @param identity - The identity binding to verify\n * @param options - Protocol-specific verification options\n * @returns Verification result with verified status and optional error\n *\n * @example\n * ```typescript\n * const result = await verifyIdentity(\n * 'abc123...',\n * { protocol: 'nostr', identifier: 'npub1...' },\n * { relays: ['wss://relay.damus.io'] }\n * );\n *\n * if (result.verified) {\n * console.log('Identity verified!');\n * }\n * ```\n */\nexport async function verifyIdentity(\n attestationId: string,\n identity: IdentityBinding,\n options?: VerifyIdentityOptions\n): Promise<VerificationResult> {\n const { protocol, identifier } = identity;\n\n // Rate limiting: 5 requests per minute per identity\n const rateLimitKey = `${protocol}:${identifier}`;\n try {\n enforceRateLimit(identityVerificationLimiter, rateLimitKey);\n } catch (err) {\n return {\n verified: false,\n error: err instanceof Error ? err.message : 'Rate limit exceeded',\n };\n }\n\n try {\n switch (protocol) {\n case 'nostr':\n return await verifyNostrIdentity(attestationId, identifier, options?.relays);\n\n case 'github':\n return await verifyGitHubIdentity(attestationId, identifier);\n\n case 'twitter':\n return await verifyTwitterIdentity(attestationId, identifier, options?.tweetUrl);\n\n case 'dns':\n return await verifyDnsIdentity(attestationId, identifier);\n\n case 'email':\n // Email verification not implemented yet\n return {\n verified: false,\n error: 'Email verification not implemented',\n };\n\n case 'web':\n // Web verification similar to DNS\n return await verifyDnsIdentity(attestationId, identifier);\n\n case 'did':\n // DID verification not implemented yet\n return {\n verified: false,\n error: 'DID verification not implemented',\n };\n\n default:\n return {\n verified: false,\n error: `Unknown protocol: ${protocol}`,\n };\n }\n } catch (error) {\n // Log error\n logVerificationError(\n protocol,\n identifier,\n error instanceof Error ? error : new Error(String(error)),\n {\n attestationId,\n }\n );\n\n return {\n verified: false,\n error: error instanceof Error ? error.message : 'Verification failed',\n };\n }\n}\n\n/**\n * Get verification instructions for an identity\n */\nexport function getVerificationInstructions(\n attestationId: string,\n identity: IdentityBinding\n): string {\n const { protocol, identifier } = identity;\n\n switch (protocol) {\n case 'nostr':\n return getNostrVerificationInstructions(attestationId);\n\n case 'github':\n return getGitHubVerificationInstructions(attestationId);\n\n case 'twitter':\n return getTwitterVerificationInstructions(attestationId, identifier);\n\n case 'dns':\n return getDnsVerificationInstructions(attestationId, identifier);\n\n case 'email':\n return `Email verification not implemented yet.`;\n\n case 'web':\n return getDnsVerificationInstructions(attestationId, identifier);\n\n case 'did':\n return `DID verification not implemented yet.`;\n\n default:\n return `Unknown protocol: ${protocol}`;\n }\n}\n\n/**\n * Check if a protocol supports automatic verification\n */\nexport function supportsAutomaticVerification(protocol: string): boolean {\n return ['nostr', 'github', 'dns', 'web'].includes(protocol);\n}\n\n/**\n * Check if a protocol requires manual verification\n */\nexport function requiresManualVerification(protocol: string): boolean {\n return ['twitter', 'email'].includes(protocol);\n}\n\n/**\n * Get verification status for multiple identities\n */\nexport async function verifyAllIdentities(\n attestationId: string,\n identities: IdentityBinding[],\n options?: {\n tweetUrls?: Record<string, string>; // Map of identifier -> tweet URL\n relays?: string[];\n }\n): Promise<Map<string, VerificationResult>> {\n const results = new Map<string, VerificationResult>();\n\n await Promise.all(\n identities.map(async (identity) => {\n const key = `${identity.protocol}:${identity.identifier}`;\n const tweetUrl = options?.tweetUrls?.[identity.identifier];\n\n const result = await verifyIdentity(attestationId, identity, {\n tweetUrl,\n relays: options?.relays,\n });\n\n results.set(key, result);\n })\n );\n\n return results;\n}\n\n/**\n * Get summary of verification results\n */\nexport function getVerificationSummary(results: Map<string, VerificationResult>): {\n total: number;\n verified: number;\n failed: number;\n pending: number;\n} {\n let verified = 0;\n let failed = 0;\n let pending = 0;\n\n for (const result of results.values()) {\n if (result.verified) {\n verified++;\n } else if (result.error?.includes('not implemented')) {\n pending++;\n } else {\n failed++;\n }\n }\n\n return {\n total: results.size,\n verified,\n failed,\n pending,\n };\n}\n","import type { StatusCode } from './types';\n\nexport type Severity = 'success' | 'info' | 'warn' | 'error';\n\nexport interface StatusMeta {\n label: string;\n detail?: string;\n severity: Severity;\n}\n\nexport const STATUS_META: Record<StatusCode, StatusMeta> = {\n sig_ok_bip322: {\n label: 'Signature verified',\n detail: 'Your BIP-322 signature is valid and proves ownership of this address.',\n severity: 'success',\n },\n sig_ok_legacy: {\n label: 'Signature verified (legacy)',\n detail: 'Your legacy signature is valid and proves ownership of this address.',\n severity: 'success',\n },\n sig_invalid: {\n label: 'Signature verification failed',\n detail: 'The signature does not match the message and address. Common issues: (1) Message not copied exactly from Step 2, (2) Wrong wallet/address used, (3) Wallet does not support BIP-322 (Electrum does NOT support BIP-322 for SegWit addresses - use Sparrow Wallet instead). For testnet, ensure your wallet is in testnet mode.',\n severity: 'error',\n },\n sig_unsupported_script: {\n label: 'Wallet does not support BIP-322',\n detail: 'Your wallet generated a legacy signature, but your SegWit address (bc1/tb1) requires BIP-322 message signing. Please use a wallet that supports BIP-322 (like Sparrow Wallet or Bitcoin Core), or switch to a P2PKH address (starting with \"1\" for mainnet or \"m\"/\"n\" for testnet) if your wallet only supports legacy signing.',\n severity: 'error',\n },\n bond_confirmed: {\n label: 'Bitcoin bond confirmed',\n detail: 'Found confirmed UTXOs on the blockchain for reputation scoring.',\n severity: 'success',\n },\n bond_zero: {\n label: 'No confirmed bitcoin found',\n detail: 'This address has no confirmed UTXOs. Send some bitcoin to this address and wait for confirmation to establish a reputation score.',\n severity: 'warn',\n },\n bond_pending: {\n label: 'Pending transactions detected',\n detail: 'This address has unconfirmed transactions. Wait for confirmations before they count toward your reputation score.',\n severity: 'info',\n },\n bond_insufficient: {\n label: 'Insufficient bond amount',\n 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.',\n severity: 'error',\n },\n aud_mismatch: {\n label: 'Audience mismatch',\n 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.',\n severity: 'warn',\n },\n expired: {\n label: 'Message expired',\n detail: 'This signature has passed its expiration date. Generate a new signature with a fresh message.',\n severity: 'error',\n },\n network_testmode: {\n label: 'Test network detected',\n detail: 'This signature uses testnet or signet. Test networks are for development only and cannot be verified in production mode.',\n severity: 'warn',\n },\n bad_request: {\n label: 'Verification error',\n detail: 'Unable to verify the signature due to invalid or inconsistent data. Please ensure the address in the message matches the address you entered, and try again.',\n severity: 'error',\n },\n decode_error: {\n label: 'Message format error',\n detail: 'The message could not be parsed. Ensure you copied the complete canonical message from Step 2 without modifications.',\n severity: 'error',\n },\n invalid_scheme: {\n label: 'Unsupported signing method',\n detail: 'The signing scheme is not supported. Please use BIP-322 or legacy Bitcoin message signing.',\n severity: 'error',\n },\n invalid_attestation_id: {\n label: 'Invalid attestation ID',\n detail: 'The attestation ID does not match the message hash. The attestation may have been tampered with.',\n severity: 'error',\n },\n};\n"]}
|