Overview

This guide covers the fundamentals of sending transactions on Solana using the CDP v2 Server Wallet. You will learn how to construct transactions and submit them to the Solana network. Solana transactions benefit from a single API that supports signing and broadcasting. With CDP, signing keys are securely managed in the platform’s infrastructure.
  1. Create transaction: Build a transaction with one or more instructions
  2. Send transaction: Use CDP to send the serialized transaction
  3. Confirm transaction: Wait for network confirmation

Prerequisites

It is assumed you have:
  • Completed the Quickstart guide
  • Basic understanding of Solana accounts
  • Installed dependencies:
    • For TypeScript: @solana/web3.js, @coinbase/cdp-sdk, and dotenv
    • For Python: solana, solders, cdp-sdk, and python-dotenv
The following steps break down the transaction flow into digestible pieces. If you prefer to see the full working code immediately, skip to the Complete example section below.

1. Create a Solana account

First, create or retrieve a Solana account using CDP. The below example uses solana-devnet and will source SOL from CDP faucet to transfer.
import { CdpClient } from "@coinbase/cdp-sdk";
import "dotenv/config";

const cdp = new CdpClient();

const account = await cdp.solana.createAccount({
  name: "test-sol-account",
});

let fromAddress: string;
fromAddress = account.address;
console.log("Successfully created new SOL account:", fromAddress);

// Request SOL from faucet
const faucetResp = await cdp.solana.requestFaucet({
  address: fromAddress,
  token: "sol",
});
console.log(
  "Successfully requested SOL from faucet:",
  faucetResp.signature
);

2. Build the transaction

Prepare a transaction with one or more instructions. The transaction may contain several instructions, each of which may require signatures from different account keys. Here is a simple SOL transfer.
We set the blockhash to a static value temporarily since the CDP v2 Server Wallet will update it before it is sent to the network.
import {
  PublicKey,
  SystemProgram,
  SYSVAR_RECENT_BLOCKHASHES_PUBKEY,
  Transaction,
} from "@solana/web3.js";

// Required: Destination address to send SOL to (replace with your recipient)
const destinationAddress = "3KzDtddx4i53FBkvCzuDmRbaMozTZoJBb1TToWhz3JfE";

// Amount of lamports to send (default: 1000 = 0.000001 SOL)
const lamportsToSend = 1000;

// Assumes fromAddress is defined from step 1
let fromAddress: string; // Your Solana account address

const transaction = new Transaction();
transaction.add(
  SystemProgram.transfer({
    fromPubkey: new PublicKey(fromAddress),
    toPubkey: new PublicKey(destinationAddress),
    lamports: lamportsToSend,
  })
);
transaction.recentBlockhash = SYSVAR_RECENT_BLOCKHASHES_PUBKEY.toBase58();
transaction.feePayer = new PublicKey(fromAddress);

3. Serialize transaction

Serialize the transaction for signing:
const serializedTx = Buffer.from(
  transaction.serialize({ requireAllSignatures: false })
).toString("base64");

console.log("Transaction serialized successfully");

4. Send the transaction

Use CDP to send the serialized transaction:
import { CdpClient } from "@coinbase/cdp-sdk";

// Assumes cdp client is initialized from step 1
const cdp = new CdpClient();

const txResult = await cdp.solana.sendTransaction({
    network: "solana-devnet",
    transaction: serializedTx,
});

const signature = txResult.signature;
console.log("Solana transaction hash:", signature);

5. Confirm

Wait for confirmation after you submitted the transaction to the network.
console.log("Waiting for transaction to be confirmed");
const latestBlockhash = await connection.getLatestBlockhash();
const confirmation = await connection.confirmTransaction({
  signature,
  blockhash: latestBlockhash.blockhash,
  lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
});

if (confirmation.value.err) {
  throw new Error(
    `Transaction failed: ${confirmation.value.err.toString()}`
  );
}

console.log(
  "Transaction confirmed:",
  confirmation.value.err ? "failed" : "success"
);
console.log(
  `Transaction explorer link: https://explorer.solana.com/tx/${signature}?cluster=devnet`
);

Complete example

More code samples are available in our TypeScript and Python SDK repositories.

Optimizing transaction sends

Priority Fee

When sending a transaction on Solana, you can set a priority fee, which is an optional fee that increases the likelihood of your transaction being included in the next block by validators. The priority fee is calculated based on the compute unit price and compute unit limit of the transaction. Priority Fee = Compute Unit Limit × Compute Unit Price Read more about Solana’s fee model.
CDP v2 Server Wallet will automatically add the appropriate instructions for the compute unit limit and compute unit price on a transaction if not already present.
To set your own compute unit limit and compute unit price for a transaction, take a look at the examples below.

Compute Unit Price

import { ComputeBudgetProgram, Transaction } from "@solana/web3.js";

// Assume you already have `otherInstruction`.
// Build a tx with compute unit price first, then your instruction(s).
const computeUnitPriceInstruction = ComputeBudgetProgram.setComputeUnitPrice({
  microLamports: 5000,
});

const tx = new Transaction().add(priorityFeeInstruction, otherInstruction);

// Send tx with your usual send flow.

Compute Unit Limit

import { ComputeBudgetProgram, Transaction } from "@solana/web3.js";

// Assume you already have `otherInstruction`.
// Build a tx with compute unit limit first, then your instruction(s).
const computeLimitInstruction = ComputeBudgetProgram.setComputeUnitLimit({
  units: 300000,
});

const tx = new Transaction().add(computeLimitInstruction, otherInstruction);

// Send tx with your usual send flow.

Bring your own node

Use a custom node provider to build and broadcast the transaction instead of relying on the CDP SDK. You will still call CDP to sign the transaction, but you can query the recent blockhash and broadcast the transaction using your own node.