Skip to main content

Overview

The SolanaWallet class extends the base Wallet with Solana-specific functionality for:
  • Sending versioned transactions
  • Handling serialized transactions
  • Managing additional signers
  • Executing Solana programs

Create a Solana Wallet Instance

Cast a base Wallet to SolanaWallet for Solana-specific operations:
import { SolanaWallet } from "@crossmint/wallets-sdk";

// Assuming you have a wallet instance
const solanaWallet = SolanaWallet.from(wallet);
The SolanaWallet.from() method will throw an error if the wallet is not on the Solana chain.

Send Custom Transactions

Execute custom Solana transactions.

Method Signature

solanaWallet.sendTransaction(params: SolanaTransactionInput): Promise<Transaction>

With Transaction Object

Send a Solana VersionedTransaction:
import { VersionedTransaction } from "@solana/web3.js";

// Build your transaction
const transaction: VersionedTransaction = /* ... */;

const tx = await solanaWallet.sendTransaction({
    transaction,
});

console.log(tx.hash);         // Transaction signature
console.log(tx.explorerLink); // Solana explorer link

With Serialized Transaction

Send a base58-encoded serialized transaction:
const serializedTx = "base58-encoded-transaction...";

const tx = await solanaWallet.sendTransaction({
    serializedTransaction: serializedTx,
});

console.log(tx.hash);
console.log(tx.explorerLink);

With Additional Signers

Include additional signers (e.g., for program-owned accounts):
import { Keypair, VersionedTransaction } from "@solana/web3.js";

// Create additional signer
const additionalSigner = Keypair.generate();

const transaction: VersionedTransaction = /* ... */;

const tx = await solanaWallet.sendTransaction({
    transaction,
    additionalSigners: [additionalSigner],
});

Prepare-Only Mode

Create a transaction without executing:
const preparedTx = await solanaWallet.sendTransaction({
    transaction,
    options: {
        experimental_prepareOnly: true,
    },
});

console.log(preparedTx.transactionId);

// Approve later
const completedTx = await wallet.approve({
    transactionId: preparedTx.transactionId,
});

With Custom Signer

const tx = await solanaWallet.sendTransaction({
    transaction,
    options: {
        experimental_signer: "external-wallet:SolanaAddress...",
    },
});

Parameters

transaction
VersionedTransaction
Solana versioned transaction object
serializedTransaction
string
Base58-encoded serialized transaction (alternative to transaction)
additionalSigners
Keypair[]
Additional keypairs that need to sign the transaction
options
TransactionInputOptions

Complete Example: Token Transfer

Transfer SPL tokens using the Solana wallet:
import { CrossmintWallets, createCrossmint, SolanaWallet } from "@crossmint/wallets-sdk";
import {
    Connection,
    PublicKey,
    Transaction,
    TransactionMessage,
    VersionedTransaction,
} from "@solana/web3.js";
import { createTransferInstruction, getAssociatedTokenAddress } from "@solana/spl-token";

// Initialize
const crossmint = createCrossmint({ apiKey: "..." });
const crossmintWallets = CrossmintWallets.from(crossmint);

// Get wallet
const wallet = await crossmintWallets.getOrCreateWallet({
    chain: "solana",
    signer: {
        type: "email",
        email: "[email protected]",
        onAuthRequired: async (...) => { /* ... */ },
    },
});

// Cast to Solana wallet
const solanaWallet = SolanaWallet.from(wallet);

// Setup connection
const connection = new Connection("https://api.mainnet-beta.solana.com");
const walletPubkey = new PublicKey(wallet.address);
const recipientPubkey = new PublicKey("RecipientAddress...");
const mintAddress = new PublicKey("TokenMintAddress...");

// Get token accounts
const sourceTokenAccount = await getAssociatedTokenAddress(
    mintAddress,
    walletPubkey
);
const destinationTokenAccount = await getAssociatedTokenAddress(
    mintAddress,
    recipientPubkey
);

// Create transfer instruction
const transferInstruction = createTransferInstruction(
    sourceTokenAccount,
    destinationTokenAccount,
    walletPubkey,
    1000000 // Amount (with decimals)
);

// Build transaction
const { blockhash } = await connection.getLatestBlockhash();
const messageV0 = new TransactionMessage({
    payerKey: walletPubkey,
    recentBlockhash: blockhash,
    instructions: [transferInstruction],
}).compileToV0Message();

const transaction = new VersionedTransaction(messageV0);

// Send transaction
const tx = await solanaWallet.sendTransaction({ transaction });

console.log(`Transfer complete! Transaction: ${tx.explorerLink}`);

Complete Example: NFT Minting

Mint a Metaplex NFT:
import { CrossmintWallets, createCrossmint, SolanaWallet } from "@crossmint/wallets-sdk";
import {
    Connection,
    PublicKey,
    TransactionMessage,
    VersionedTransaction,
} from "@solana/web3.js";
import { createMintToInstruction } from "@solana/spl-token";

// Initialize and get wallet
const crossmint = createCrossmint({ apiKey: "..." });
const crossmintWallets = CrossmintWallets.from(crossmint);
const wallet = await crossmintWallets.getOrCreateWallet({
    chain: "solana",
    signer: { type: "email", email: "[email protected]", onAuthRequired: async (...) => {...} },
});

const solanaWallet = SolanaWallet.from(wallet);

// Setup
const connection = new Connection("https://api.mainnet-beta.solana.com");
const walletPubkey = new PublicKey(wallet.address);

// Create mint instruction for Metaplex NFT
// (This is simplified - actual Metaplex minting requires more setup)
const mintInstruction = /* Create your Metaplex mint instruction */;

// Build transaction
const { blockhash } = await connection.getLatestBlockhash();
const messageV0 = new TransactionMessage({
    payerKey: walletPubkey,
    recentBlockhash: blockhash,
    instructions: [mintInstruction],
}).compileToV0Message();

const transaction = new VersionedTransaction(messageV0);

// Mint NFT
const tx = await solanaWallet.sendTransaction({ transaction });

console.log(`NFT minted! Transaction: ${tx.explorerLink}`);

Complete Example: Program Interaction

Interact with a Solana program:
import { CrossmintWallets, createCrossmint, SolanaWallet } from "@crossmint/wallets-sdk";
import {
    Connection,
    PublicKey,
    TransactionInstruction,
    TransactionMessage,
    VersionedTransaction,
} from "@solana/web3.js";

// Initialize
const crossmint = createCrossmint({ apiKey: "..." });
const crossmintWallets = CrossmintWallets.from(crossmint);
const wallet = await crossmintWallets.getOrCreateWallet({
    chain: "solana",
    signer: { type: "email", email: "[email protected]", onAuthRequired: async (...) => {...} },
});

const solanaWallet = SolanaWallet.from(wallet);

// Setup
const connection = new Connection("https://api.mainnet-beta.solana.com");
const walletPubkey = new PublicKey(wallet.address);
const programId = new PublicKey("YourProgramId...");

// Create program instruction
const instruction = new TransactionInstruction({
    keys: [
        { pubkey: walletPubkey, isSigner: true, isWritable: true },
        // Add other accounts as needed
    ],
    programId,
    data: Buffer.from([/* your instruction data */]),
});

// Build and send transaction
const { blockhash } = await connection.getLatestBlockhash();
const messageV0 = new TransactionMessage({
    payerKey: walletPubkey,
    recentBlockhash: blockhash,
    instructions: [instruction],
}).compileToV0Message();

const transaction = new VersionedTransaction(messageV0);
const tx = await solanaWallet.sendTransaction({ transaction });

console.log(`Program executed! Transaction: ${tx.explorerLink}`);

Working with External Wallets

Connect Phantom, Solflare, or other Solana wallets:
import { CrossmintWallets, createCrossmint } from "@crossmint/wallets-sdk";

// Assuming Phantom is installed
const provider = window.solana;

if (!provider?.isPhantom) {
    throw new Error("Phantom wallet not found");
}

// Connect to Phantom
const resp = await provider.connect();
const phantomAddress = resp.publicKey.toString();

// Create wallet with Phantom as signer
const crossmint = createCrossmint({ apiKey: "..." });
const crossmintWallets = CrossmintWallets.from(crossmint);

const wallet = await crossmintWallets.getOrCreateWallet({
    chain: "solana",
    signer: {
        type: "external-wallet",
        address: phantomAddress,
        onSignTransaction: async (transaction) => {
            const signedTx = await provider.signTransaction(transaction);
            return signedTx;
        },
        onSignMessage: async (message) => {
            const encodedMessage = new TextEncoder().encode(message);
            const { signature } = await provider.signMessage(encodedMessage);
            return { signature: Buffer.from(signature).toString("base64") };
        },
    },
});

Using Simple Token Transfers

For basic token transfers, use the base wallet’s send() method instead of building transactions manually:
// Simple USDC transfer
const tx = await wallet.send(
    "RecipientSolanaAddress...",
    "usdc",
    "100"
);

// Simple SOL transfer
const tx = await wallet.send(
    "RecipientSolanaAddress...",
    "sol",
    "1.5"
);
See Wallet Operations for more details.

Solana Network

The SDK works with:
  • Mainnet Beta: Production Solana network
  • Devnet: Testing network with free SOL from faucets

Next Steps

Wallet Operations

Learn about common wallet operations

Delegated Signers

Add multiple signers to a wallet

EVM Wallets

Learn about EVM-specific operations

Stellar Wallets

Learn about Stellar-specific operations

Build docs developers (and LLMs) love