> **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.

# personal\_sign

Signs an [EIP-191](https://eips.ethereum.org/EIPS/eip-191) personal message.

Applications use it to prove control of an address off-chain: sign-in flows, terms acceptance, or linking an address to an account on a backend. The message is prefixed with `\x19Ethereum Signed Message:\n<length>` before hashing, so a `personal_sign` signature can never be replayed as a transaction signature.

The Wallet renders the message on its `/sign/personal-sign` [route](https://www.openfort.io/docs/products/cross-app-wallet/setup/react/wallet-ui#wallet-routes) for the user to review before signing.

## Request

```ts
type Request = {
  method: 'personal_sign',
  params: [
    /** Message to sign. */
    message: string,
    /** Address of the signer. */
    address: `0x${string}`,
  ],
}
```

### Parameters

| Parameter | Type            | Required | Description                                                                                     |
| --------- | --------------- | -------- | ----------------------------------------------------------------------------------------------- |
| `message` | `string`        | Yes      | Message to sign, hex-encoded UTF-8. Pass it first — the parameter order is the reverse of `eth_sign`. |
| `address` | `0x${string}`   | Yes      | Address of the signer. Must be one of the accounts returned by [`eth_accounts`](https://www.openfort.io/docs/products/cross-app-wallet/rpc/eth_accounts). |

## Response

Signature.

```ts
type Response = `0x${string}`
```

```json
"0xa3f1...9c2b"
```

A cross-app wallet is a smart account, so the returned bytes are not always a 65-byte ECDSA signature and `ecrecover` may not return the account address. Verify with [ERC-1271](https://eips.ethereum.org/EIPS/eip-1271) `isValidSignature` instead — see [signature verification](https://www.openfort.io/docs/products/cross-app-wallet/usage/signatures).

## Example

:::warning
To make these instructions concrete, we have created a sample cross-app wallet called **Rapidfire ID**. To interact with it, you can find its SDK in the NPM package directory: [@rapidfire/id](https://www.npmjs.com/package/@rapidfire/id).

You can check out the GitHub [repository for Rapidfire Wallet](https://github.com/openfort-xyz/ecosystem-sample) to learn how to create your own wallet.
:::

An interactive demo, runnable on this page.

```ts
import RapidfireID from '@rapidfire/id'

const rapidfire = new RapidfireID()
const provider = rapidfire.getEthereumProvider()

const [account] = await provider.request({
  method: 'eth_accounts',
})

const hash = await provider.request({ // [!code focus]
  method: 'personal_sign', // [!code focus]
  params: [ // [!code focus]
    '0x68656c6c6f20776f726c64', // "hello world" in hex [!code focus]
    account, // [!code focus]
  ], // [!code focus]
})// [!code focus]
```

In React, wagmi's `useSignMessage` hook issues the same request and hex-encodes the message for you.

## Errors

| Code   | Meaning                   | When it happens                                                                 |
| ------ | ------------------------- | --------------------------------------------------------------------------------- |
| `4001` | User rejected the request | The user declines the signature or closes the Wallet window.                        |
| `4100` | Unauthorized              | The Application has not connected yet, or `address` is not one of its accounts.     |
| `-32602` | Invalid params          | `params` is neither an array nor an object, as required by the provider.            |

## Related

* [`eth_signTypedData_v4`](https://www.openfort.io/docs/products/cross-app-wallet/rpc/eth_signTypedData_v4) signs structured data the user can read field by field.
* [Signature verification](https://www.openfort.io/docs/products/cross-app-wallet/usage/signatures) covers ERC-1271 validation with wagmi.
* [`eth_requestAccounts`](https://www.openfort.io/docs/products/cross-app-wallet/rpc/eth_requestAccounts) connects the Application before any signing request.
