Skip to content

zscole/eth-signature-verifier

Repository files navigation

eth-signature-verifier

Bundle Size

Minimal Ethereum signature verifier for EIP-712, EIP-191, and eth_sign. No ethers.js, no web3.js. Zero dependencies.

Install

npm install eth-signature-verifier

Usage

import { verifyMessage, verifyTypedData } from 'eth-signature-verifier'

// EIP-191 or personal_sign
verifyMessage(
  '0x742d35Cc1C3c72AE4d5e4F0e3D1E3c7E5E8C1A2B',
  'Hello World',
  '0x...'
)

// EIP-712 typed data
verifyTypedData(
  '0x742d35Cc1C3c72AE4d5e4F0e3D1E3c7E5E8C1A2B',
  '0x...',
  { name: 'MyApp', version: '1', chainId: 1 },
  { Message: [{ name: 'content', type: 'string' }] },
  { content: 'Hello World' }
)

Using with ethers or viem

This library accepts types from popular Ethereum libraries without requiring them as dependencies:

import { verifyTypedData } from 'eth-signature-verifier'
import type { TypedDataDomain } from 'ethers'
import type { TypedData } from 'viem'

// With ethers types
const ethersDomain: TypedDataDomain = { /* ... */ }
const ethersTypes = { /* ... */ }
verifyTypedData(address, signature, ethersDomain, ethersTypes, value)

// With viem types  
const viemDomain = { /* ... */ }
const viemTypes: TypedData = { /* ... */ }
verifyTypedData(address, signature, viemDomain, viemTypes, value)

Note: Only TypeScript types are supported - no runtime dependencies are added to your bundle.

Why not ethers.js?

Most apps don't need 2MB+ of dependencies just to verify a signature. This library does one thing well:

  • No bundler bloat
  • Works in browser or server
  • Ideal for serverless, bots, RPC gateways, and minimal dapps

Examples

Express Middleware

import { verifyMessage } from 'eth-signature-verifier'

const auth = (req, res, next) => {
  const { address, message, signature } = req.headers
  if (!verifyMessage(address, message, signature)) {
    return res.status(401).json({ error: 'Invalid signature' })
  }
  req.user = { address }
  next()
}

MetaMask Verification

const message = 'Sign to authenticate'
const signature = await ethereum.request({
  method: 'personal_sign',
  params: [message, account]
})

const isValid = verifyMessage(account, message, signature)

EIP-712 Permit

const domain = {
  name: 'MyToken',
  version: '1',
  chainId: 1,
  verifyingContract: '0x...'
}

const types = {
  Permit: [
    { name: 'owner', type: 'address' },
    { name: 'spender', type: 'address' },
    { name: 'value', type: 'uint256' },
    { name: 'nonce', type: 'uint256' },
    { name: 'deadline', type: 'uint256' }
  ]
}

verifyTypedData(owner, signature, domain, types, permit)

API

verifyMessage(address, message, signature): boolean

Verifies a raw message signed via personal_sign or eth_sign.

verifyTypedData(address, signature, domain, types, value): boolean

Verifies EIP-712 structured data signatures. All parameters must match the original signed payload.

Returns false if the signature is invalid or mismatched.

Contributing

See CONTRIBUTING.md for setup and contribution flow.

License

MIT © Zak Cole

About

No description, website, or topics provided.

Resources

License

Contributing

Stars

Watchers

Forks

Packages

No packages published