Movement Labs LogoMovement Docs
Interact on Chain/Wallet Adapter/Use Wallet

Sign and Verify Message

Signing and verifying messages using an Movement wallet

Overview

This React component creates a user interface for signing and verifying messages using an Movement wallet. It's commonly used in blockchain applications to prove ownership of a wallet address by signing messages.

Key Features

  1. Message signing
  2. Message verification
  3. Wallet connection status
  4. Error handling

How It Works

1️⃣ Component Setup

const { signMessage, signMessageAndVerify, connected, account } = useWallet();
  • Uses the Aptos wallet adapter to get necessary functions and wallet status
  • connected: Tells if wallet is connected
  • account: Contains wallet information

2️⃣ State Management

const [message, setMessage] = useState<string>('');
const [nonce, setNonce] = useState<string>('');
const [signedMessage, setSignedMessage] = useState<any>(null);
const [verificationResult, setVerificationResult] = useState<boolean | null>(null);
const [error, setError] = useState<string | null>(null);

Manages five different states:

  • message: The text message to be signed
  • nonce: A random string to prevent replay attacks
  • signedMessage: Stores the signed message response
  • verificationResult: Stores whether the message verification was successful
  • error: Stores any error messages

3️⃣ Message Signing Function

const handleSignMessage = async () => {
    setError(null);
    try {
      const response = await signMessage({ message, nonce });
      setSignedMessage(response);
    } catch (err: any) {
      setError(`Failed to sign message: ${err.message}`);
    }
};
  • Clears any previous errors
  • Attempts to sign the message using the wallet
  • Stores the signed message or captures any errors

4️⃣ Message Verification Function

const handleVerifyMessage = async () => {
    setError(null);
    try {
      const result = await signMessageAndVerify({ message, nonce });
      setVerificationResult(result);
    } catch (err: any) {
      setError(`Failed to verify message: ${err.message}`);
    }
};
  • Clears any previous errors
  • Verifies the signed message
  • Stores the verification result or captures any errors

5️⃣ User Interface

The component renders different UI elements based on wallet connection status:

If wallet is not connected:

  • Shows a message asking user to connect wallet

If wallet is connected:

  1. Shows the connected wallet address
  2. Provides a text area for entering the message
  3. Provides an input field for the nonce
  4. Shows a "Sign Message" button
  5. If message is signed:
    • Displays the signed message
    • Shows a "Verify Message" button
  6. Shows verification result if available
  7. Displays any errors that occur

Use Cases

  1. Identity Verification: Prove ownership of a wallet address
  2. Authentication: Can be used as part of a login system
  3. Message Authentication: Ensure messages are authentic and haven't been tampered with

Error Handling

  • Handles signing errors
  • Handles verification errors
  • Displays user-friendly error messages

This component provides a complete solution for signing and verifying messages using an Aptos wallet, with a user-friendly interface and proper error handling.

Code Example

signAndVerify
import React, { useState } from 'react';
import { useWallet } from '@aptos-labs/wallet-adapter-react';

const SignMessageDemo = () => {
  const { signMessage, signMessageAndVerify, connected, account } = useWallet();
  const [message, setMessage] = useState<string>('');
  const [nonce, setNonce] = useState<string>('');
  const [signedMessage, setSignedMessage] = useState<any>(null);
  const [verificationResult, setVerificationResult] = useState<boolean | null>(null);
  const [error, setError] = useState<string | null>(null);

  const handleSignMessage = async () => {
    setError(null);
    try {
      const response = await signMessage({ message, nonce });
      setSignedMessage(response);
    } catch (err: any) {
      setError(`Failed to sign message: ${err.message}`);
    }
  };

  const handleVerifyMessage = async () => {
    setError(null);
    try {
      const result = await signMessageAndVerify({ message, nonce });
      setVerificationResult(result);
    } catch (err: any) {
      setError(`Failed to verify message: ${err.message}`);
    }
  };

  return (
    <div>
      <h1>Aptos Sign and Verify Message</h1>
      <div>
        {connected ? (
          <div>
            <p>Connected to: {account?.address}</p>
            <div className="flex flex-col gap-4">
              <textarea
                value={message}
                onChange={(e) => setMessage(e.target.value)}
                placeholder="Enter your message here"
                className="border rounded p-2"
              />
              <input
                type="text"
                value={nonce}
                onChange={(e) => setNonce(e.target.value)}
                placeholder="Enter nonce (random string) here"
                className="border rounded p-2 mt-2"
              />
              <button onClick={handleSignMessage} className="bg-blue-500 text-white rounded p-2 mt-2">
                Sign Message
              </button>
              {signedMessage && (
                <div>
                  <h4>Signed Message</h4>
                  <pre>{JSON.stringify(signedMessage, null, 2)}</pre>
                  <button onClick={handleVerifyMessage} className="bg-green-500 text-white rounded p-2 mt-2">
                    Verify Message
                  </button>
                </div>
              )}
              {verificationResult !== null && (
                <div>
                  <h4>Verification Result</h4>
                  <p>{verificationResult ? 'Message is verified!' : 'Failed to verify message.'}</p>
                </div>
              )}
              {error && (
                <div className="text-red-600">
                  <p>{error}</p>
                </div>
              )}
            </div>
          </div>
        ) : (
          <p>Please connect your wallet to sign and verify messages.</p>
        )}
      </div>
    </div>
  );
};

export default SignMessageDemo;

Sign & Submit BCS Transaction

How to sign and submit a BCS (Binary Canonical Serialization) transaction on the MoveVM blockchain. It specifically shows how to transfer tokens using the Move account module.

Function Breakdown

Transaction Submission Function

const onSignAndSubmitBCSTransaction = async () => {
    const response = await signAndSubmitTransaction({
        sender: account.address,
        data: {
            function: "0x1::aptos_account::transfer",
            functionArguments: [AccountAddress.from(account.address), new U64(1)],
        },
    });
    // ... transaction confirmation ...
};

Key Components:

  1. Sender: The address of the account initiating the transaction
  2. Function Path: 0x1::aptos_account::transfer
    • 0x1: Core framework address
    • aptos_account: Module name
    • transfer: Function name
  3. Function Arguments:
    • AccountAddress.from(account.address): Recipient address
    • new U64(1): Amount to transfer (1 unit)

Transaction Confirmation

try {
    await aptos.waitForTransaction({ transactionHash: response.hash });
} catch (error) {
    console.error(error);
}
  • Waits for transaction confirmation
  • Handles any errors during confirmation process

UI Element

<button onClick={onSignAndSubmitTransaction}>
    Sign and submit BCS transaction
</button>
  • Simple button to trigger the transaction

Important Notes

  1. BCS Format: Uses Binary Canonical Serialization for efficient transaction encoding
  2. Error Handling: Includes basic error handling for transaction confirmation
  3. Amount: Example shows transfer of 1 unit (adjust as needed)
  4. Gas Fees: Transaction will require gas fees (not shown in example)

Common Use Cases

  1. Token transfers
  2. Smart contract interactions
  3. Blockchain state modifications