Signing Messages

Signing Messages

Your dApp can request the user to sign an arbitrary message. This is commonly used to verify ownership of an account without submitting a transaction.

Sign a Message

Use signMessage from the useWallet hook:

import { useWallet } from "@aptos-labs/wallet-adapter-react";
 
function SignMessageExample() {
  const { signMessage } = useWallet();
 
  const handleSign = async () => {
    try {
      const response = await signMessage({
        message: "Welcome to my dApp!",
        nonce: Date.now().toString(),
        address: true,    // include the account address in the signed message
        application: true, // include the dApp domain
        chainId: true,     // include the chain ID
      });
 
      console.log("Signature:", response.signature);
      console.log("Full message:", response.fullMessage);
    } catch (error) {
      // See "Error Codes" for possible errors
    }
  };
 
  return <button onClick={handleSign}>Sign Message</button>;
}

Types

interface SignMessagePayload {
  address?: boolean;     // Include the account address in the message
  application?: boolean; // Include the dApp domain
  chainId?: boolean;     // Include the current chain ID
  message: string;       // The message to sign
  nonce: string;         // A nonce your dApp generates
}
 
interface SignMessageResponse {
  address: string;
  application: string;
  chainId: number;
  fullMessage: string;   // The complete message that was signed
  message: string;       // The original message
  nonce: string;
  prefix: string;        // Always "APTOS"
  signature: string;     // The signature over fullMessage
}

Example Signed Output

Calling signMessage({ nonce: "1234034", message: "Welcome to dapp!" }) generates the following fullMessage:

APTOS
nonce: 1234034
message: Welcome to dapp!

Verifying a Signature

The simplest way to verify a signed message is signMessageAndVerify, which signs and verifies in a single call:

import { useWallet } from "@aptos-labs/wallet-adapter-react";
 
function VerifyOwnership() {
  const { signMessageAndVerify } = useWallet();
 
  const handleVerify = async () => {
    try {
      const isVerified = await signMessageAndVerify({
        message: "Prove account ownership",
        nonce: Date.now().toString(),
      });
 
      console.log("Verified:", isVerified); // true or false
    } catch (error) {
      console.error(error);
    }
  };
 
  return <button onClick={handleVerify}>Verify Ownership</button>;
}

This replaces the need for manual signature verification with libraries like tweetnacl.

For a more complete authentication flow, see Sign In with Aptos (SIWA) which provides a standardized sign-in protocol including email access for Keyless accounts.