Appearance
Signatures
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.
For embedded wallets on EVM networks, Privy's default signature confirmation modals are highly-customizable, allowing you to contextualize onchain actions within the broader experience of your product.
INFO
Customizing Privy's default confirmation modal for signatures is only available for embedded wallets on EVM networks, not Solana. We are actively building support for customizing the signature confirmation modal for Solana embedded wallets.
In kind, the guide below exclusively refers to embedded wallets on EVM networks.
Sign message
To request a signature from a user with a custom prompt, 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.
Parameter | Type | Description |
---|---|---|
message | string | Required. The message the user must sign as a string . |
uiConfig | SignMessageModalUIOptions | Optional. Options to customize the signature prompt shown to the user. Defaults to the values outlined below |
uiConfig.showWalletUIs | boolean | Optional. 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.title | string | Optional. The title text for the signature prompt. Defaults to 'Sign'. |
uiConfig.description | string | Optional. The description text for the signature prompt. Defaults to 'Sign to continue'. |
uiConfig.buttonText | string | Optional. 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.
Parameter | Type | Description |
---|---|---|
typedData | SignedTypedDataParams | Required. A JSON object that conforms to the EIP-712 TypedData JSON schema. |
uiConfig | SignMessageModalUIOptions | Optional. Options to customize the signature prompt shown to the user. Defaults to the values outlined below |
uiConfig.showWalletUIs | boolean | Optional. 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.title | string | Optional. The title text for the signature prompt. Defaults to 'Sign'. |
uiConfig.description | string | Optional. The description text for the signature prompt. Defaults to 'Sign to continue'. |
uiConfig.buttonText | string | Optional. 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>
);
}