import { useMemo } from 'react' interface PunkAvatarProps { seed: string size?: number className?: string } // Hash function to generate consistent random values from seed function hashCode(str: string): number { let hash = 0 for (let i = 0; i < str.length; i++) { const char = str.charCodeAt(i) hash = ((hash << 5) - hash) + char hash = hash & hash } return Math.abs(hash) } // Get a value from hash at specific position function getHashValue(hash: number, position: number, max: number): number { return ((hash >> (position * 4)) & 0xF) % max } // Color palettes - Web3/Crypto aesthetic const BACKGROUNDS = [ '#1a1a2e', '#16213e', '#0f3460', '#1b1b2f', '#162447', '#1f1f3d', '#2d132c', '#1e1e3f', '#0d1b2a', '#1b263b', '#252538', '#2a2a4a', '#1e2a3a', '#0f172a', '#1a1f35', ] const SKIN_TONES = [ '#ffd5c8', '#f5c5b5', '#daa06d', '#c68642', '#8d5524', '#6b4423', '#4a3728', '#ffdbac', '#f1c27d', '#e0ac69', ] const HAIR_COLORS = [ '#090806', '#2c222b', '#3b3024', '#4a4035', '#504444', '#6a4e42', '#a55728', '#b55239', '#8d4a43', '#91553d', '#e6cea8', '#e5c8a8', '#debc99', '#977961', '#343434', '#9a3300', '#ff6b6b', '#4ecdc4', '#ffe66d', '#a855f7', ] const ACCESSORY_COLORS = [ '#F0B90B', '#0ECB81', '#F6465D', '#60a5fa', '#a855f7', '#ec4899', '#14b8a6', '#f97316', '#84cc16', '#06b6d4', ] export function PunkAvatar({ seed, size = 40, className = '' }: PunkAvatarProps) { const avatar = useMemo(() => { const hash = hashCode(seed) // Deterministic selections based on hash const bgColor = BACKGROUNDS[getHashValue(hash, 0, BACKGROUNDS.length)] const skinColor = SKIN_TONES[getHashValue(hash, 1, SKIN_TONES.length)] const hairColor = HAIR_COLORS[getHashValue(hash, 2, HAIR_COLORS.length)] const accColor = ACCESSORY_COLORS[getHashValue(hash, 3, ACCESSORY_COLORS.length)] const hairStyle = getHashValue(hash, 4, 8) const eyeStyle = getHashValue(hash, 5, 6) const mouthStyle = getHashValue(hash, 6, 5) const hasGlasses = getHashValue(hash, 7, 4) === 0 const hasEarring = getHashValue(hash, 8, 5) === 0 const hasMask = getHashValue(hash, 9, 8) === 0 const hasLaser = getHashValue(hash, 10, 12) === 0 return { bgColor, skinColor, hairColor, accColor, hairStyle, eyeStyle, mouthStyle, hasGlasses, hasEarring, hasMask, hasLaser, } }, [seed]) // Pixel size for 24x24 grid const px = size / 24 const renderHair = () => { const { hairColor, hairStyle } = avatar switch (hairStyle) { case 0: // Mohawk return ( <> ) case 1: // Messy return ( <> ) case 2: // Cap return ( <> ) case 3: // Long return ( <> ) case 4: // Bald with shine return ( ) case 5: // Spiky return ( <> ) case 6: // Hoodie return ( <> ) case 7: // Crown return ( <> ) default: return null } } const renderEyes = () => { const { eyeStyle, accColor } = avatar const eyeY = 10 * px switch (eyeStyle) { case 0: // Normal return ( <> ) case 1: // Angry return ( <> ) case 2: // Wink return ( <> ) case 3: // Sleepy return ( <> ) case 4: // Big eyes return ( <> ) case 5: // Robot return ( <> ) default: return null } } const renderMouth = () => { const { mouthStyle } = avatar const mouthY = 14 * px switch (mouthStyle) { case 0: // Smile return ( <> ) case 1: // Neutral return case 2: // Smirk return ( <> ) case 3: // Open return ( <> ) case 4: // Teeth return ( <> ) default: return null } } const renderAccessories = () => { const { hasGlasses, hasEarring, hasMask, hasLaser, accColor } = avatar const elements = [] if (hasGlasses) { elements.push( ) } if (hasEarring) { elements.push( ) } if (hasMask) { elements.push( ) } if (hasLaser) { elements.push( ) } return elements } return ( {/* Background */} {/* Head shape */} {/* Ears */} {/* Neck */} {/* Hair (rendered before accessories) */} {renderHair()} {/* Eyes */} {renderEyes()} {/* Nose */} {/* Mouth */} {renderMouth()} {/* Accessories (glasses, earrings, etc.) */} {renderAccessories()} ) } // Pre-defined punk collection for special traders export function getTraderAvatar(traderId: string, traderName: string): string { // Use a combination of ID and name for more unique results return `${traderId}-${traderName}` }