# Sign messages

> Sign messages using your Smart Wallet

> For the complete documentation index, see [llms.txt](/docs/llms.txt).

This guide covers how to sign messages using your Smart Wallet. Message signing is a key feature that allows users to authenticate and prove ownership of their wallet without spending gas.

Signatures are generated in a format that can be validated using [ERC-1271](https://eips.ethereum.org/EIPS/eip-1271). If the smart wallet is undeployed (also known as a counterfactual address), then the signature is wrapped according to [ERC-6492](https://eips.ethereum.org/EIPS/eip-6492).

## Prerequisites

* API key from your [dashboard](https://dashboard.alchemy.com/apps)
* A Smart Wallet with an associated owner

<Note>
  When using [EIP-7702](/docs/wallets/transactions/using-eip-7702), your account must be delegated before signatures will be valid. Send at least one transaction to delegate your account first.
</Note>

## What is message signing?

Message signing allows users to:

* **Authenticate** without spending gas
* **Prove ownership** of their wallet
* **Sign arbitrary data** for offchain verification
* **Interact with dApps** that require signature-based authentication

EIP-191 message signing is supported, which is the standard for Ethereum message signing. You may also see EIP-191 referred to as the `personal_sign` message format.

## Text messages

<Tabs>
  <Tab title="JavaScript" language="typescript">
    <Info>`@alchemy/wallet-apis` (v5.x.x) is currently in beta but is the recommended replacement for `@account-kit/wallet-client` (v4.x.x). If you run into any issues, please [reach out](mailto:support@alchemy.com).</Info>

See the [`signMessage` SDK reference](/docs/wallets/reference/wallet-apis/functions/signMessage) for full parameter descriptions.

<CodeBlocks>

```ts title="signTextMessage.ts"
import { createPublicClient, http } from "viem";
import { arbitrumSepolia } from "viem/chains";
import { client } from "./client";

// Sign a simple text message
const message = "Hello, world!";
const signature = await client.signMessage({ message });

console.log("Signature:", signature);

// Verify the signature
const publicClient = createPublicClient({
  chain: arbitrumSepolia,
  transport: http(),
});

const isValid = await publicClient.verifyMessage({
  address: client.account.address,
  message,
  signature,
});

console.log("Valid:", isValid); // true
```

```ts title="client.ts"
import type { Hex } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { arbitrumSepolia } from "viem/chains";
import { createSmartWalletClient, alchemyWalletTransport } from "@alchemy/wallet-apis";

export const client = createSmartWalletClient({
  transport: alchemyWalletTransport({
    apiKey: "YOUR_API_KEY",
  }),
  chain: arbitrumSepolia,
  signer: privateKeyToAccount("0xYOUR_PRIVATE_KEY" as const),
});
```

</CodeBlocks>

  </Tab>
</Tabs>

## Raw hex messages

<Tabs>
  <Tab title="JavaScript" language="typescript">
    <Info>`@alchemy/wallet-apis` (v5.x.x) is currently in beta but is the recommended replacement for `@account-kit/wallet-client` (v4.x.x). If you run into any issues, please [reach out](mailto:support@alchemy.com).</Info>

See the [`signMessage` SDK reference](/docs/wallets/reference/wallet-apis/functions/signMessage) for full parameter descriptions.

<CodeBlocks>

```ts title="signRawMessage.ts"
import { createPublicClient, http } from "viem";
import { arbitrumSepolia } from "viem/chains";
import { client } from "./client";

// Sign a raw hex message
const message = {
  raw: "0x48656c6c6f2c20776f726c6421" as const, // "Hello, world!" in hex
};
const signature = await client.signMessage({ message });

console.log("Signature:", signature);

// Verify the signature
const publicClient = createPublicClient({
  chain: arbitrumSepolia,
  transport: http(),
});

const isValid = await publicClient.verifyMessage({
  address: client.account.address,
  message,
  signature,
});

console.log("Valid:", isValid); // true
```

```ts title="client.ts"
import type { Hex } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { arbitrumSepolia } from "viem/chains";
import { createSmartWalletClient, alchemyWalletTransport } from "@alchemy/wallet-apis";

export const client = createSmartWalletClient({
  transport: alchemyWalletTransport({
    apiKey: "YOUR_API_KEY",
  }),
  chain: arbitrumSepolia,
  signer: privateKeyToAccount("0xYOUR_PRIVATE_KEY" as const),
});
```

</CodeBlocks>

  </Tab>
</Tabs>

<Accordion title="Using @account-kit/wallet-client (v4.x.x)?">
The examples on this page use `@alchemy/wallet-apis` (v5.x.x). If you're using `@account-kit/wallet-client` (v4.x.x), the client setup looks like this:

```ts title="client.ts (v4.x.x)"
import { LocalAccountSigner } from "@aa-sdk/core";
import { createSmartWalletClient } from "@account-kit/wallet-client";
import { alchemy, sepolia } from "@account-kit/infra";

const signer = LocalAccountSigner.privateKeyToAccountSigner("0xYOUR_PRIVATE_KEY" as const);

export const client = createSmartWalletClient({
  transport: alchemy({ apiKey: "YOUR_API_KEY" }),
  chain: sepolia,
  signer,
  account: signer.address, // can also be passed per action as `from` or `account`
  // Optional: sponsor gas for your users (see "Sponsor gas" guide)
  policyId: "YOUR_POLICY_ID", 
});
```

Key v4.x.x differences:
* **Account address** must be specified on the client or per action (`from` or `account`). In v5.x.x, the client automatically uses the owner's address as the account address via [EIP-7702](/docs/wallets/transactions/using-eip-7702).
* **Chain imports** come directly from `@account-kit/infra` instead of `viem/chains`.
* **Numeric values** use hex strings: `value: "0x0"` instead of `value: BigInt(0)`.
* In v4.x.x, the **paymaster capability** on `prepareCalls` or `sendCalls` is called `paymasterService` instead of `paymaster`, or you can set the `policyId` directly on the client.
* **Owners** use `LocalAccountSigner` / `WalletClientSigner` from `@aa-sdk/core`. In v5.x.x, a viem `LocalAccount` or `WalletClient` is used directly.

See the [full migration guide](/docs/wallets/resources/migration-v5) for a complete cheat sheet.
</Accordion>


## Next steps

Build more:

* [Sign typed data](/docs/wallets/transactions/signing/sign-typed-data)
* [Send transactions](/docs/wallets/transactions/send-transactions)

Troubleshooting:

* [Common errors](/docs/wallets/resources/faqs#common-errors)