Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.cloud.coinbase.com/llms.txt

Use this file to discover all available pages before exploring further.

CDP Wallets provide a sendTransaction feature that simplifies sending onchain transactions. For EVM, it handles gas estimation, nonce management, signing, and broadcasting automatically. For Solana, it handles signing and broadcasting, and sets the required priority fees for optimal transaction pricing.

EVM

sendTransaction is supported on Base, Ethereum, Avalanche, Polygon, Optimism, and Arbitrum. For other chains, use the sign transaction feature.
After the user logs in, use useSendEvmTransaction from cdp-hooks to send EVM transactions from the user’s wallet.
import { useSendEvmTransaction, useEvmAddress } from "@coinbase/cdp-hooks";

function SendTransaction() {
  const { sendEvmTransaction } = useSendEvmTransaction();
  const { evmAddress } = useEvmAddress();

  const handleSend = async () => {
    if (!evmAddress) return;
    const result = await sendEvmTransaction({
      transaction: {
        to: evmAddress,
        value: 1000000000000n,  // 0.000001 ETH in wei
        gas: 21000n,
        chainId: 84532,         // Base Sepolia
        type: "eip1559",
      },
      evmAccount: evmAddress,
      network: "base-sepolia",
    });
    console.log("Transaction hash:", result.transactionHash);
  };

  return <button onClick={handleSend}>Send Transaction</button>;
}

Network-scoped accounts

Use useNetwork() to scope an account to a specific network once, avoiding the need to pass network on every call. When scoped to Base or Base Sepolia, the SDK automatically uses CDP’s managed RPC endpoints.
Node (TypeScript)
// Without useNetwork — network required on every call
await cdp.evm.sendTransaction({ address, network: "base", transaction: { ... } });
await cdp.evm.sendTransaction({ address, network: "base", transaction: { ... } });

// With useNetwork — scope once, use everywhere
const baseAccount = await account.useNetwork("base");
await baseAccount.sendTransaction({ transaction: { to: "0x...", value: 0n } });
await baseAccount.waitForTransactionReceipt(result); // uses CDP Node RPC automatically
To use a custom RPC endpoint or a network not natively supported by CDP, pass the RPC URL directly:
Node (TypeScript)
const polygonAccount = await account.useNetwork(
  "https://polygon-mainnet.rpc-provider.com/YOUR_API_KEY"
);

const result = await polygonAccount.sendTransaction({
  transaction: { to: "0x...", value: 0n },
});
const receipt = await polygonAccount.waitForTransactionReceipt(result);

Solana

Solana transactions require building and serializing a transaction before sending. CDP injects the latest blockhash before broadcasting, so use the placeholder blockhash shown below.
Use useSendSolanaTransaction for programmatic control, or SendSolanaTransactionButton for a pre-built UI button with built-in loading and error states.
import { useSendSolanaTransaction, useSolanaAddress } from "@coinbase/cdp-hooks";
import {
  PublicKey,
  SystemProgram,
  Transaction,
  SYSVAR_RECENT_BLOCKHASHES_PUBKEY,
} from "@solana/web3.js";
import { Buffer } from "buffer";

function SendTransaction() {
  const { sendSolanaTransaction } = useSendSolanaTransaction();
  const { solanaAddress } = useSolanaAddress();

  const handleSend = async () => {
    if (!solanaAddress) return;

    const tx = new Transaction().add(
      SystemProgram.transfer({
        fromPubkey: new PublicKey(solanaAddress),
        toPubkey: new PublicKey("recipient-address"),
        lamports: 1000,
      })
    );
    tx.recentBlockhash = SYSVAR_RECENT_BLOCKHASHES_PUBKEY.toBase58();
    tx.feePayer = new PublicKey(solanaAddress);

    const serialized = Buffer.from(
      tx.serialize({ requireAllSignatures: false })
    ).toString("base64");

    const result = await sendSolanaTransaction({
      transaction: serialized,
      solanaAccount: solanaAddress,
      network: "solana-devnet",
    });
    console.log("Signature:", result.transactionSignature);
  };

  return <button onClick={handleSend}>Send</button>;
}

Bring your own node

Use signTransaction to sign with CDP and broadcast via a custom RPC node:
const { blockhash } = await connection.getLatestBlockhash();
tx.recentBlockhash = blockhash;

const signedTx = await cdp.solana.signTransaction({
  address: account.address,
  transaction: serialized,
});

const decoded = Buffer.from(signedTx.signature, "base64");
const signature = await connection.sendRawTransaction(decoded);
console.log("Signature:", signature);

Priority fees

The priority fee increases the likelihood of your transaction being included in the next block. Priority fee = Compute unit limit × Compute unit price
CDP automatically adds compute unit limit and price instructions if they are not already present in your transaction.
import { ComputeBudgetProgram, Transaction } from "@solana/web3.js";

const tx = new Transaction().add(
  ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 5000 }),
  ComputeBudgetProgram.setComputeUnitLimit({ units: 300000 }),
  // ...your other instructions
);

Fee sponsorship

CDP can pay the Solana network fee on behalf of your wallet. Pass useCdpSponsor: true when calling sendTransaction.
Fee sponsorship is in private preview and available to enterprise-scale integrations only. To opt in, apply for access.
import { useSendSolanaTransaction, useSolanaAddress } from "@coinbase/cdp-hooks";

function SendSponsoredTransaction() {
  const { sendSolanaTransaction } = useSendSolanaTransaction();
  const { solanaAddress } = useSolanaAddress();

  const handleSend = async () => {
    if (!solanaAddress) return;
    const result = await sendSolanaTransaction({
      solanaAccount: solanaAddress,
      network: "solana-mainnet",
      transaction: serializedTx,
      useCdpSponsor: true,
    });
    console.log("Signature:", result.transactionSignature);
  };

  return <button onClick={handleSend}>Send (sponsored)</button>;
}

Send USDC

USDC uses 6 decimal places, so 1000000 atomic units equals 1 USDC.
The useSendUsdc hook from @coinbase/cdp-hooks works across all account types (EOA, Smart Account, Solana) and handles contract addresses, decimal conversion, and Associated Token Account creation automatically.
import { useSendUsdc } from "@coinbase/cdp-hooks";

function SendUsdcComponent() {
  const { sendUsdc, data, error, status } = useSendUsdc();

  const handleSend = async () => {
    const result = await sendUsdc({
      to: "0x1234567890123456789012345678901234567890",
      amount: "25.50", // human-readable, not atomic units
      network: "base-sepolia",
    });

    if (result.type === "evm-eoa") {
      console.log("EOA Transaction:", result.transactionHash);
    } else if (result.type === "evm-smart") {
      console.log("Smart Account UserOp:", result.userOpHash);
    } else if (result.type === "solana") {
      console.log("Solana Transaction:", result.transactionSignature);
    }
  };

  return (
    <button onClick={handleSend} disabled={status === "pending"}>
      {status === "pending" ? "Sending..." : "Send 25.50 USDC"}
    </button>
  );
}
For Smart Accounts, pass useCdpPaymaster: true for gasless transactions. For Solana, pass createRecipientAta: true to create the recipient’s token account if it doesn’t exist.See the full parameter reference in the CDP Web SDK docs.

Webhooks

Subscribe to transaction lifecycle events using CDP Wallet Webhooks. The wallet.transaction.* events let you track each transaction from creation through confirmation or failure in real time.