Skip to main content
Sign messages and transactions to prove account ownership or authorize actions without broadcasting to the blockchain.

EVM

Sign messages (EIP-191)

EIP-191 signs a plain text message with a standard prefix, proving account ownership without sending a transaction. Common uses: authentication, off-chain agreements, Sign in with Ethereum.
import { useSignEvmMessage, useEvmAddress } from "@coinbase/cdp-hooks";

function SignMessage() {
  const { signEvmMessage } = useSignEvmMessage();
  const { evmAddress } = useEvmAddress();

  const handleSign = async () => {
    if (!evmAddress) return;
    const result = await signEvmMessage({
      evmAccount: evmAddress,
      message: "Hello World",
    });
    console.log("Signature:", result.signature);
  };

  return <button onClick={handleSign}>Sign Message</button>;
}

Sign typed data (EIP-712)

EIP-712 signs structured data in a human-readable format. Used for permit signatures, order books, and any protocol that requires structured off-chain signing.
import { useSignEvmTypedData, useEvmAddress } from "@coinbase/cdp-hooks";

function SignTypedData() {
  const { signEvmTypedData } = useSignEvmTypedData();
  const { evmAddress } = useEvmAddress();

  const handleSign = async () => {
    if (!evmAddress) return;
    const result = await signEvmTypedData({
      evmAccount: evmAddress,
      typedData: {
        domain: {
          name: "Example DApp",
          version: "1",
          chainId: 84532,
        },
        types: {
          Person: [
            { name: "name", type: "string" },
            { name: "wallet", type: "address" },
          ],
        },
        primaryType: "Person",
        message: { name: "Bob", wallet: evmAddress },
      },
    });
    console.log("Signature:", result.signature);
  };

  return <button onClick={handleSign}>Sign Typed Data</button>;
}

Sign transactions

For networks other than those supported by the Send Transaction API, you can sign a transaction with the wallet and broadcast it yourself. This example uses the public client from viem / web3 to broadcast the transaction. Common use cases include Tempo (a stablecoin payments blockchain) and other EVM-compatible chains not listed above.
import { useSignEvmTransaction, useEvmAddress } from "@coinbase/cdp-hooks";
import { createPublicClient, http } from "viem";
import { tron } from "viem/chains";

function SignAndBroadcast() {
  const { signEvmTransaction } = useSignEvmTransaction();
  const { evmAddress } = useEvmAddress();

  const handleSign = async () => {
    if (!evmAddress) return;

    const { signedTransaction } = await signEvmTransaction({
      evmAccount: evmAddress,
      transaction: {
        to: evmAddress,
        value: 1000000000000n,
        gas: 21000n,
        chainId: 728126428, // Tron
        type: "eip1559",
      },
    });

    const client = createPublicClient({ chain: tron, transport: http() });
    const hash = await client.sendRawTransaction({
      serializedTransaction: signedTransaction,
    });
    console.log("Transaction hash:", hash);
  };

  return <button onClick={handleSign}>Sign and Broadcast</button>;
}

Sign a hash

Sign a raw 32-byte hash directly. Useful for custom signing schemes, off-chain commitments, or protocols that require signing pre-hashed data.
import { useSignEvmHash, useEvmAddress } from "@coinbase/cdp-hooks";

function SignHash() {
  const { signEvmHash } = useSignEvmHash();
  const { evmAddress } = useEvmAddress();

  const handleSign = async () => {
    if (!evmAddress) return;

    const result = await signEvmHash({
      evmAccount: evmAddress,
      hash: "0x1234567890123456789012345678901234567890123456789012345678901234",
    });

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

  return <button onClick={handleSign}>Sign Hash</button>;
}

Solana

Sign messages

Sign arbitrary data to prove account ownership without sending anything to the blockchain. The hook takes a base64-encoded message and returns an Ed25519 signature.
import { useSignSolanaMessage, useSolanaAddress } from "@coinbase/cdp-hooks";

function SignMessage() {
  const { signSolanaMessage } = useSignSolanaMessage();
  const { solanaAddress } = useSolanaAddress();

  const handleSign = async () => {
    if (!solanaAddress) return;
    const result = await signSolanaMessage({
      solanaAccount: solanaAddress,
      message: "base64-encoded-message",
    });
    console.log("Signature:", result.signature);
  };

  return <button onClick={handleSign}>Sign Message</button>;
}

Sign transactions (without broadcasting)

Sign a transaction locally and broadcast it yourself via a custom RPC endpoint.
import { useSignSolanaTransaction, useSolanaAddress } from "@coinbase/cdp-hooks";

function SignTransaction() {
  const { signSolanaTransaction } = useSignSolanaTransaction();
  const { solanaAddress } = useSolanaAddress();

  const handleSign = async () => {
    if (!solanaAddress) return;
    const result = await signSolanaTransaction({
      solanaAccount: solanaAddress,
      transaction: "base64-encoded-transaction",
    });
    console.log("Signed transaction:", result.signedTransaction);
    // Broadcast result.signedTransaction via your own RPC
  };

  return <button onClick={handleSign}>Sign Transaction</button>;
}