> **Can't find what you're looking for?** Use `search_docs` on the docs MCP server at `https://www.openfort.io/api/mcp` to find what you need.
>
> **Have feedback?** Use `submit_feedback` on the same MCP server.

# Sign message

Use `useSignMessage` to open a confirmation screen and resolve either `{ signature }` or `{ error }`. Signing does not submit a transaction or consume gas.

## Personal message

```tsx
import { useState } from 'react'
import { useSignMessage } from '@openfort/react'

function SignMessage() {
  const { signMessage, isPending, error } = useSignMessage()
  const [signature, setSignature] = useState<string>()

  const handleSign = async () => {
    const result = await signMessage('Hello World')
    if ('error' in result) return
    setSignature(result.signature)
  }

  return (
    <div>
      <button onClick={() => void handleSign()} disabled={isPending}>
        {isPending ? 'Signing...' : 'Sign message'}
      </button>
      {signature && <p>Signature: {signature}</p>}
      {error && <p>Error: {error.shortMessage}</p>}
    </div>
  )
}
```

For Ethereum wallets, personal messages use the `personal_sign` RPC method. Smart and Delegated accounts use [EIP-1271](https://eips.ethereum.org/EIPS/eip-1271) verification.

## Typed data (EIP-712)

Typed-data signing is available for Ethereum wallets. Use the connected wallet's chain ID so the domain matches the active chain.

```tsx
import { useState } from 'react'
import { useSignMessage } from '@openfort/react'
import { useEthereumEmbeddedWallet } from '@openfort/react/ethereum'

function SignTypedData() {
  const { chainId } = useEthereumEmbeddedWallet()
  const { signTypedData, isPending, error } = useSignMessage()
  const [signature, setSignature] = useState<string>()

  const handleSign = async () => {
    if (!chainId) return

    const result = await signTypedData({
      domain: {
        chainId,
        name: 'Example DApp',
        verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC',
        version: '1',
      },
      types: {
        Mail: [
          { name: 'from', type: 'Person' },
          { name: 'to', type: 'Person' },
          { name: 'content', type: 'string' },
        ],
        Person: [
          { name: 'name', type: 'string' },
          { name: 'wallet', type: 'address' },
        ],
      },
      message: {
        from: { name: 'Alice', wallet: '0x2111111111111111111111111111111111111111' },
        to: { name: 'Bob', wallet: '0x3111111111111111111111111111111111111111' },
        content: 'Hello!',
      },
      primaryType: 'Mail',
    })

    if ('error' in result) return
    setSignature(result.signature)
  }

  return (
    <div>
      <button onClick={() => void handleSign()} disabled={isPending || !chainId}>
        {isPending ? 'Signing...' : 'Sign typed data'}
      </button>
      {signature && <p>Signature: {signature}</p>}
      {error && <p>Error: {error.shortMessage}</p>}
    </div>
  )
}
```

Try the modal on the [UI configuration](https://www.openfort.io/docs/products/embedded-wallet/react/ui/configuration#sign-message) page.
