import { LRUCache } from 'lru-cache' import { nip19 } from 'nostr-tools' export function formatPubkey(pubkey: string) { const npub = pubkeyToNpub(pubkey) if (npub) { return formatNpub(npub) } return pubkey.slice(0, 4) + '...' + pubkey.slice(-4) } export function formatNpub(npub: string, length = 12) { if (length < 12) { length = 12 } if (length >= 63) { return npub } const prefixLength = Math.floor((length - 5) / 2) + 5 const suffixLength = length - prefixLength return npub.slice(0, prefixLength) + '...' + npub.slice(-suffixLength) } export function formatUserId(userId: string) { if (userId.startsWith('npub1')) { return formatNpub(userId) } return formatPubkey(userId) } export function pubkeyToNpub(pubkey: string) { try { return nip19.npubEncode(pubkey) } catch { return null } } export function userIdToPubkey(userId: string, throwOnInvalid = false): string { if (userId.startsWith('npub1') || userId.startsWith('nprofile1')) { try { const { type, data } = nip19.decode(userId) if (type === 'npub') { return data } else if (type === 'nprofile') { return data.pubkey } } catch (error) { if (throwOnInvalid) { throw new Error('Invalid id') } console.error('Error decoding userId:', userId, 'error:', error) } } return userId } export function isValidPubkey(pubkey: string) { return /^[0-9a-f]{64}$/.test(pubkey) } const pubkeyImageCache = new LRUCache({ max: 1000 }) export function generateImageByPubkey(pubkey: string): string { if (pubkeyImageCache.has(pubkey)) { return pubkeyImageCache.get(pubkey)! } const paddedPubkey = pubkey.padEnd(2, '0') // Split into 3 parts for colors and the rest for control points const colors: string[] = [] const controlPoints: string[] = [] for (let i = 0; i < 11; i++) { const part = paddedPubkey.slice(i * 6, (i + 1) * 6) if (i < 3) { colors.push(`#${part}`) } else { controlPoints.push(part) } } // Generate SVG with multiple radial gradients const gradients = controlPoints .map((point, index) => { const cx = parseInt(point.slice(0, 2), 16) % 100 const cy = parseInt(point.slice(2, 4), 16) % 100 const r = (parseInt(point.slice(4, 6), 16) % 35) + 30 const c = colors[index % (colors.length - 1)] return ` ` }) .join('') const image = ` ${gradients} ` const imageData = `data:image/svg+xml;base64,${btoa(image)}` pubkeyImageCache.set(pubkey, imageData) return imageData }