import { sha256 } from "@noble/hashes/sha256"; import { bytesToHex } from "@noble/hashes/utils"; export interface NostrPowEvent { id: string; pubkey: string; created_at: number; kind: number; tags: Array>; content: string; sig: string; } export function minePow(e: NostrPowEvent, target: number) { let ctr = 0; let nonceTagIdx = e.tags.findIndex(a => a[0] === "nonce"); if (nonceTagIdx === -1) { nonceTagIdx = e.tags.length; e.tags.push(["nonce", ctr.toString(), target.toString()]); } do { e.tags[nonceTagIdx][1] = (++ctr).toString(); e.id = createId(e); } while (countLeadingZeros(e.id) < target); return e; } function createId(e: NostrPowEvent) { const payload = [0, e.pubkey, e.created_at, e.kind, e.tags, e.content]; return bytesToHex(sha256(JSON.stringify(payload))); } export function countLeadingZeros(hex: string) { let count = 0; for (let i = 0; i < hex.length; i++) { const nibble = parseInt(hex[i], 16); if (nibble === 0) { count += 4; } else { count += Math.clz32(nibble) - 28; break; } } return count; }