TypeScript

Install and use @solana/keychain in TypeScript applications

Installation

Install the umbrella package or individual signers as needed:

# Umbrella package (includes all signers)
pnpm add @solana/keychain

# Or install individual packages
pnpm add @solana/keychain-core        # Core interfaces (required for custom signers)
pnpm add @solana/keychain-vault       # HashiCorp Vault
pnpm add @solana/keychain-aws-kms     # AWS KMS
pnpm add @solana/keychain-privy       # Privy
pnpm add @solana/keychain-turnkey     # Turnkey
pnpm add @solana/keychain-fireblocks  # Fireblocks
pnpm add @solana/keychain-cdp         # Coinbase Developer Platform
pnpm add @solana/keychain-crossmint   # Crossmint
pnpm add @solana/keychain-dfns        # Dfns
pnpm add @solana/keychain-para        # Para

Basic Usage

Use createKeychainSigner with a discriminated config to create any backend:

import { createKeychainSigner } from "@solana/keychain";
import { signTransactionWithSigners } from "@solana/signers"; // requires @solana/signers ≥ 6.5

const signer = await createKeychainSigner({
  backend: "privy",
  appId: "your-app-id",
  appSecret: "your-app-secret",
  walletId: "your-wallet-id",
});

// Sign an already-compiled transaction
const signedTx = await signTransactionWithSigners(
  [signer],
  compiledTransaction,
);

Or install an individual signer package for a smaller dependency footprint:

import { createPrivySigner } from "@solana/keychain-privy";

const signer = await createPrivySigner({
  appId: "your-app-id",
  appSecret: "your-app-secret",
  walletId: "your-wallet-id",
});

Using with Transaction Messages

All signers implement the SolanaSigner interface, which is compatible with @solana/kit and @solana/signers:

import { signTransactionMessageWithSigners } from "@solana/signers";
import {
  createTransactionMessage,
  setTransactionMessageFeePayerSigner,
  pipe,
} from "@solana/kit";

async function signWithKeychain(signer: SolanaSigner) {
  // Check availability (useful for remote signers)
  if (!(await signer.isAvailable())) {
    throw new Error("Signer offline");
  }

  // Use with @solana/kit transaction builder
  const transaction = pipe(
    createTransactionMessage({ version: 0 }),
    tx => setTransactionMessageFeePayerSigner(signer, tx)
    // ... add instructions
  );

  // Sign with the standard signers API
  const signedTx = await signTransactionMessageWithSigners(transaction);
  return signedTx;
}

Backend Configuration

HashiCorp Vault

import { VaultSigner } from "@solana/keychain-vault";

const signer = new VaultSigner({
  vaultAddr: "https://vault.example.com:8200",
  vaultToken: "hvs.xxxxx",
  keyName: "my-solana-key",
  publicKey: "base58_public_key",
});

AWS KMS

import { AwsKmsSigner } from "@solana/keychain-aws-kms";

const signer = new AwsKmsSigner({
  keyId: "alias/my-solana-key",
  publicKey: "base58_public_key",
  region: "us-east-1", // optional
});

Privy

import { PrivySigner } from "@solana/keychain-privy";

const signer = await PrivySigner.create({
  appId: "app_id",
  appSecret: "app_secret",
  walletId: "wallet_id",
});

Turnkey

import { TurnkeySigner } from "@solana/keychain-turnkey";

const signer = new TurnkeySigner({
  apiPublicKey: "api_public_key",
  apiPrivateKey: "api_private_key",
  organizationId: "org_id",
  privateKeyId: "private_key_id",
  publicKey: "base58_public_key",
});

Fireblocks

import { FireblocksSigner } from "@solana/keychain-fireblocks";

const signer = new FireblocksSigner({
  apiKey: "api_key",
  privateKeyPem: "-----BEGIN RSA PRIVATE KEY-----\n...",
  vaultAccountId: "0",
  assetId: "SOL", // or "SOL_TEST" for devnet
});
await signer.init();

CDP (Coinbase Developer Platform)

import { createCdpSigner } from "@solana/keychain-cdp";

const signer = await createCdpSigner({
  apiKeyId: "api_key_id",
  apiKeySecret: "api_key_secret",
  walletSecret: "wallet_secret",
  address: "base58_address",
});

Crossmint

import { createCrossmintSigner } from "@solana/keychain-crossmint";

const signer = await createCrossmintSigner({
  apiKey: "api_key",
  walletLocator: "wallet_locator",
});

Dfns

import { createDfnsSigner } from "@solana/keychain-dfns";

const signer = await createDfnsSigner({
  authToken: "auth_token",
  credId: "cred_id",
  privateKeyPem: "-----BEGIN EC PRIVATE KEY-----\n...",
  appId: "app_id",
  walletId: "wallet_id",
});

Para

import { createParaSigner } from "@solana/keychain-para";

const signer = await createParaSigner({
  apiKey: "api_key",
  walletId: "wallet_id",
});

SolanaSigner Interface

The SolanaSigner interface extends @solana/signers types for full compatibility:

interface SolanaSigner<TAddress extends string = string>
  extends TransactionPartialSigner<TAddress>,
    MessagePartialSigner<TAddress> {
  // Public key address
  readonly address: Address<TAddress>;

  // Health check for remote signers
  isAvailable(): Promise<boolean>;

  // Sign messages (@solana/kit compatible)
  signMessages(
    messages: readonly SignableMessage[]
  ): Promise<readonly SignatureDictionary[]>;

  // Sign transactions (@solana/kit compatible)
  signTransactions(
    transactions: readonly Transaction[]
  ): Promise<readonly SignatureDictionary[]>;
}

Building Custom Signers

Implement the SolanaSigner interface to create custom signers:

import { SolanaSigner } from "@solana/keychain-core";
import type { Address } from "@solana/addresses";

class MyCustomSigner implements SolanaSigner {
  readonly address: Address;

  constructor(address: Address) {
    this.address = address;
  }

  async isAvailable(): Promise<boolean> {
    return await myBackend.healthCheck();
  }

  async signMessages(messages) {
    return await myBackend.signMessages(messages);
  }

  async signTransactions(transactions) {
    return await myBackend.signTransactions(transactions);
  }
}

See the Adding Signers guide to integrate additional key management services.