Skip to content

Instantly share code, notes, and snippets.

@miguelmota
Created October 27, 2025 02:59
Show Gist options
  • Select an option

  • Save miguelmota/9d88a16127c3d25aff394999342d7d7b to your computer and use it in GitHub Desktop.

Select an option

Save miguelmota/9d88a16127c3d25aff394999342d7d7b to your computer and use it in GitHub Desktop.
MetaMask-style Identicon
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