Sign Message

Sign Message

JoyID implements the EIP-191 ↗ (opens in a new tab) standard for signing messages. This allows for a more secure way of signing messages, as it prevents the user from signing a message that they did not intend to sign.

Sign text message

You can sign a message using the signMessage method. This method takes a string or bytes as a parameter and returns a hex-encoded signature.

import { Address } from 'viem'
import { signMessage } from '@joyid/evm';
interface Props {
  address: Address | null;
const SignMessage = ({ address }: Props) => {
  const [message, setMessage] = React.useState("Hello world");
  const [signature, setSignature] = React.useState<Address>("0x");
  const onSign = async () => {
    const sig = await signMessage(message, address!);
  return address ? (
    <div className="w-full">
      <h2 className="mb-4 text-lg text-center">Sign Message</h2>
      <label className="label">Message:</label>
        className="input input-bordered w-full mb-4"
        onChange={(e) => setMessage(}
      <label className="label">Signature:</label>
        className="textarea textarea-bordered w-full mb-4"
      <button className="btn btn-primary mb-4 mr-4" onClick={onSign}>
      <div className="divider"></div>
  ) : null;

Sign bytes message

Note that the signMessage method also accepts a bytes parameter. This allows you to sign any arbitrary data. If the message is a string, it is signed as UTF-8 encoded bytes. It is not interpretted as a BytesLike; so the string "0x1234" is signed as six characters, not two bytes.

To sign that example as two bytes, the Uint8Array should be used (i.e. new Uint8Array([ 0x12, 0x34 ])).

If your message is a hex string, you should convert it to a Uint8Array.

import { toBytes } from 'viem'
import { signMessage } from '@joyid/evm'
function signHexMessage(message: string, address: Address) {
  // message is a hex string, like "0x1234"
  const bytes = toBytes(message);
  return signMessage(bytes, address);
function signBytesMessage(message: Uint8Array, address: Address) {
  // message is a Uint8Array, just pass it through
  return signMessage(message, address);

Verify Message

Since the message is signed using the EIP-191 standard, it can be verified using any EIP-191 compliant library.

import { verifyMessage } from 'ethers/lib/utils'
function verify(message: string, address: string) {
  const signature = await signMessage(message, address);
  const res = verifyMessage(message, signature);

API Reference

Try it out