pubkey.ts raw
1 /**
2 * UI utilities for pubkey visualization.
3 *
4 * For pubkey validation, formatting, and conversion, use the domain Pubkey class:
5 * import { Pubkey } from '@/domain'
6 * - Pubkey.isValidHex(hex)
7 * - Pubkey.tryFromString(input)?.hex
8 * - Pubkey.tryFromString(input)?.npub
9 * - Pubkey.tryFromString(input)?.formatNpub(length)
10 */
11
12 import { LRUCache } from 'lru-cache'
13
14 const pubkeyImageCache = new LRUCache<string, string>({ max: 1000 })
15
16 /**
17 * Generate a unique SVG image based on a pubkey.
18 * Uses the pubkey bytes to deterministically create a colorful gradient pattern.
19 */
20 export function generateImageByPubkey(pubkey: string): string {
21 if (pubkeyImageCache.has(pubkey)) {
22 return pubkeyImageCache.get(pubkey)!
23 }
24
25 const paddedPubkey = pubkey.padEnd(2, '0')
26
27 // Split into 3 parts for colors and the rest for control points
28 const colors: string[] = []
29 const controlPoints: string[] = []
30 for (let i = 0; i < 11; i++) {
31 const part = paddedPubkey.slice(i * 6, (i + 1) * 6)
32 if (i < 3) {
33 colors.push(`#${part}`)
34 } else {
35 controlPoints.push(part)
36 }
37 }
38
39 // Generate SVG with multiple radial gradients
40 const gradients = controlPoints
41 .map((point, index) => {
42 const cx = parseInt(point.slice(0, 2), 16) % 100
43 const cy = parseInt(point.slice(2, 4), 16) % 100
44 const r = (parseInt(point.slice(4, 6), 16) % 35) + 30
45 const c = colors[index % (colors.length - 1)]
46
47 return `
48 <radialGradient id="grad${index}-${pubkey}" cx="${cx}%" cy="${cy}%" r="${r}%">
49 <stop offset="0%" style="stop-color:${c};stop-opacity:1" />
50 <stop offset="100%" style="stop-color:${c};stop-opacity:0" />
51 </radialGradient>
52 <rect width="100%" height="100%" fill="url(#grad${index}-${pubkey})" />
53 `
54 })
55 .join('')
56
57 const image = `
58 <svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
59 <rect width="100%" height="100%" fill="${colors[2]}" fill-opacity="0.3" />
60 ${gradients}
61 </svg>
62 `
63 const imageData = `data:image/svg+xml;base64,${btoa(image)}`
64
65 pubkeyImageCache.set(pubkey, imageData)
66
67 return imageData
68 }
69