Skip to content

Signing messages ​

Privy allows your app to easily request signatures from users embedded wallet. By default, Privy will display a UI preview of the message to get approval from the user.

Sample sign message prompt
Sample sign message prompt UI

These UIs are highly-customizable via params, allowing you to contextualize onchain actions within the broader experience of your product. You can also fully disable Privy's UIs in favor of your own. Learn more about customizing wallet UIs here.

Sign message ​

To request a signature from a user use the signMessage method returned by the usePrivy hook:

tsx
const {signMessage} = usePrivy();

When invoked, signMessage will request an EIP-191 personal_sign signature from the embedded wallet, and returns a Promise for the user's signature as a string.

signMessage takes the following parameters. In particular, you can use the optional uiConfig to customize the prompt shown to the user to contextualize their signing action.

ParameterTypeDescription
messagestringRequired. The message the user must sign as a string.
uiConfigSignMessageModalUIOptionsOptional. Options to customize the signature prompt shown to the user. Defaults to the values outlined below
uiConfig.showWalletUIsbooleanOptional. Whether to overwrite the configured wallet UI for the signature prompt. Defaults to undefined, which will respect the server-side or SDK configured option.
uiConfig.titlestringOptional. The title text for the signature prompt. Defaults to 'Sign'.
uiConfig.descriptionstringOptional. The description text for the signature prompt. Defaults to 'Sign to continue'.
uiConfig.buttonTextstringOptional. The description text for the signature prompt. Defaults to 'Sign and Continue'.

Example ​

Below is an example of customizing the signature prompt:

tsx
import {usePrivy} from '@privy-io/react-auth';

function SignMessageButton() {
  const {signMessage} = usePrivy();
  const message = 'Hello world';
  const uiConfig = {
    title: 'Sample title text',
    description: 'Sample description text',
    buttonText: 'Sample button text',
  };

  return (
    <button
      onClick={async () => {
        // Use `signature` below however you'd like
        const signature = await signMessage(message, uiConfig);
      }}
    >
      Sign
    </button>
  );
}

Sign typed data ​

To have a user sign an EIP-712 typed data signature with a custom UI prompt, use the signTypedData method returned by the usePrivy hook:

tsx
const {signTypedData} = usePrivy();

When invoked, signTypedData will request an EIP-721 eth_signTypedData_v4 signature from the embedded wallet, and returns a Promise for the user's signature as a string.

signTypedData takes the following parameters. In particular, you can use the optional uiConfig to customize the prompt shown to the user to contextualize their signing action.

ParameterTypeDescription
typedDataSignedTypedDataParamsRequired. A JSON object that conforms to the EIP-712 TypedData JSON schema.
uiConfigSignMessageModalUIOptionsOptional. Options to customize the signature prompt shown to the user. Defaults to the values outlined below
uiConfig.showWalletUIsbooleanOptional. Whether to overwrite the configured wallet UI for the signature prompt. Defaults to undefined, which will respect the server-side or SDK configured option.
uiConfig.titlestringOptional. The title text for the signature prompt. Defaults to 'Sign'.
uiConfig.descriptionstringOptional. The description text for the signature prompt. Defaults to 'Sign to continue'.
uiConfig.buttonTextstringOptional. The description text for the signature prompt. Defaults to 'Sign and Continue'.

Example ​

Below is an example of customizing the typedData prompt:

tsx
import {usePrivy} from '@privy-io/react-auth';

function SignTypedDataButton() {
  const {signTypedData} = usePrivy();

  // Example from https://github.com/MetaMask/test-dapp/blob/285ef74eec90dbbb4994eff4ece8c81ba4fc77f9/src/index.js#L1585
  const domain = {
    name: 'Example Message',
    version: '1.0.0',
    chainId: 1,
    salt: '0',
    verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC' as `0x${string}`,
  };

  // The named list of all type definitions
  const types = {
    Person: [
      {name: 'name', type: 'string'},
      {name: 'wallet', type: 'address'},
    ],
    Mail: [
      {name: 'from', type: 'Person'},
      {name: 'to', type: 'Person'},
      {name: 'contents', type: 'string'},
    ],
    // Necessary to define salt param type
    EIP712Domain: [
      {
        name: 'name',
        type: 'string',
      },
      {
        name: 'version',
        type: 'string',
      },
      {
        name: 'chainId',
        type: 'uint256',
      },
      {
        name: 'salt',
        type: 'string',
      },
      {
        name: 'verifyingContract',
        type: 'string',
      },
    ],
  };

  // The data to sign
  const value = {
    from: {
      name: 'Cow',
      wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826',
    },
    to: {
      name: 'Bob',
      wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
    },
    contents: 'Hello, Bob!',
  };

  const typedData = {primaryType: 'Mail', domain: domain, types: types, message: value};
  const uiConfig = {
    title: 'Sample title text',
    description: 'Sample description text',
    buttonText: 'Sample button text',
  };

  return (
    <button
      onClick={async () => {
        // Use `signature` below however you'd like
        const signature = await signTypedData(typedData, uiConfig);
      }}
    >
      Sign Typed Data
    </button>
  );
}