Created
October 27, 2025 02:59
-
-
Save miguelmota/9d88a16127c3d25aff394999342d7d7b to your computer and use it in GitHub Desktop.
MetaMask-style Identicon
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import type React from "react" | |
| // MetaMask-style hash function | |
| const 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) | |
| } | |
| // Generate MetaMask-style colors (bright and vibrant) | |
| const generateMetaMaskColors = (seed: number) => { | |
| const colors = [ | |
| "#FF6B6B", | |
| "#4ECDC4", | |
| "#45B7D1", | |
| "#96CEB4", | |
| "#FECA57", | |
| "#FF9FF3", | |
| "#54A0FF", | |
| "#5F27CD", | |
| "#00D2D3", | |
| "#FF9F43", | |
| "#10AC84", | |
| "#EE5A24", | |
| "#0ABDE3", | |
| "#C44569", | |
| "#F8B500", | |
| "#6C5CE7", | |
| "#A3CB38", | |
| "#FD79A8", | |
| "#636E72", | |
| "#00B894", | |
| ] | |
| const bg = colors[seed % colors.length] | |
| const spot = colors[(seed + 7) % colors.length] | |
| return { backgroundColor: bg, spotColor: spot } | |
| } | |
| // Generate MetaMask-style pattern | |
| const generateMetaMaskPattern = (address: string) => { | |
| const cleanAddress = address.replace(/^0x/i, "").toLowerCase() | |
| // Use address to generate deterministic values | |
| const seed = hashCode(cleanAddress) | |
| const { backgroundColor, spotColor } = generateMetaMaskColors(seed) | |
| // Generate a 8x8 grid pattern like MetaMask | |
| const size = 8 | |
| const pattern: boolean[][] = [] | |
| // Generate pattern with symmetry (like MetaMask) | |
| for (let y = 0; y < size; y++) { | |
| const row: boolean[] = [] | |
| for (let x = 0; x < size; x++) { | |
| // Create horizontal symmetry | |
| const actualX = x < 4 ? x : 7 - x | |
| // Use different parts of address for different rows/columns | |
| const addressIndex = (y * 4 + actualX) % cleanAddress.length | |
| const char = cleanAddress.charCodeAt(addressIndex) | |
| // Determine if this cell should be filled | |
| const shouldFill = (char + seed) % 3 === 0 | |
| row.push(shouldFill) | |
| } | |
| pattern.push(row) | |
| } | |
| return { | |
| backgroundColor, | |
| spotColor, | |
| pattern, | |
| } | |
| } | |
| interface IdenticonProps { | |
| value?: string | |
| size?: number | |
| className?: string | |
| } | |
| export const Identicon: React.FC<IdenticonProps> = ({ | |
| value = "0x0000000000000000000000000000000000000000", | |
| size = 64, | |
| className = "", | |
| }) => { | |
| if (!value || typeof value !== "string") { | |
| return ( | |
| <div | |
| className={`inline-block ${className}`} | |
| style={{ | |
| width: size, | |
| height: size, | |
| backgroundColor: "#cccccc", | |
| borderRadius: "50%", | |
| }} | |
| /> | |
| ) | |
| } | |
| const { backgroundColor, spotColor, pattern } = generateMetaMaskPattern(value) | |
| const gridSize = 8 | |
| const cellSize = size / gridSize | |
| return ( | |
| <div | |
| className={`inline-block ${className}`} | |
| style={{ | |
| width: size, | |
| height: size, | |
| borderRadius: "50%", | |
| overflow: "hidden", | |
| backgroundColor: backgroundColor, | |
| }} | |
| > | |
| <svg | |
| width={size} | |
| height={size} | |
| style={{ display: "block" }} | |
| aria-label={`Identicon for ${value}`} | |
| > | |
| <title>Identicon for {value}</title> | |
| {/* Background circle */} | |
| <circle | |
| cx={size / 2} | |
| cy={size / 2} | |
| r={size / 2} | |
| fill={backgroundColor} | |
| /> | |
| {/* Pattern cells */} | |
| {pattern.map((row, y) => | |
| row.map((shouldFill, x) => | |
| shouldFill ? ( | |
| <rect | |
| key={`cell-${y}-${x}-${value.slice(-8)}`} | |
| x={x * cellSize} | |
| y={y * cellSize} | |
| width={cellSize} | |
| height={cellSize} | |
| fill={spotColor} | |
| /> | |
| ) : null, | |
| ), | |
| )} | |
| </svg> | |
| </div> | |
| ) | |
| } | |
| export default Identicon |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment