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

Basic Usage

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

import { SolanaSigner } from "@solana/keychain-core";
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();

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.