npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@solana/keychain

v2.0.0

Published

Unified Solana transaction signing across multiple backends

Readme

@solana/keychain

Unified Solana transaction signing for TypeScript applications. This umbrella package provides access to all keychain signers through a single import.

Installation

pnpm add @solana/keychain

This installs all signer implementations. For a smaller bundle, install individual packages instead:

  • @solana/keychain-aws-kms - AWS KMS signer
  • @solana/keychain-cdp - Coinbase Developer Platform (CDP) signer
  • @solana/keychain-crossmint - Crossmint signer
  • @solana/keychain-dfns - Dfns signer
  • @solana/keychain-fireblocks - Fireblocks signer
  • @solana/keychain-fordefi - Fordefi MPC signer
  • @solana/keychain-gcp-kms - GCP KMS signer
  • @solana/keychain-memory - In-memory keypair signer (local Ed25519 signing)
  • @solana/keychain-openfort - Openfort backend wallet signer
  • @solana/keychain-para - Para MPC signer
  • @solana/keychain-privy - Privy signer
  • @solana/keychain-turnkey - Turnkey signer
  • @solana/keychain-utila - Utila wallet signer
  • @solana/keychain-vault - HashiCorp Vault signer

Usage

Unified Factory (Recommended)

Use createKeychainSigner with a discriminated config to create any backend:

import { createKeychainSigner } from '@solana/keychain';

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

await signer.signTransactions([transaction]);

The backend field determines which signer is created. TypeScript narrows the config type automatically — you get full autocomplete for each backend's required fields, and the overloads return each backend's exact shape (see Signer Shapes).

Managed-broadcast backends (Crossmint always; Fordefi when chain is set and pushMode is omitted or 'auto') rewrite the transaction and/or broadcast it server-side, so they return a SolanaSendingSigner (Fordefi native auto mode's FordefiNativeSigner also signs messages) with signAndSendTransactions() instead of signTransactions():

const crossmint = await createKeychainSigner({
    backend: 'crossmint',
    apiKey: '...',
    walletLocator: '...',
});

// Returns the signature identifying the transaction Crossmint landed.
const [signature] = await crossmint.signAndSendTransactions([transaction]);

With Kit, use signAndSendTransactionMessageWithSigners() for these backends; the partial-signer helpers below apply to every other backend.

Resolve Address Without Signing

Use resolveAddress to get a signer's Solana address without initializing the full signing pipeline:

import { resolveAddress } from '@solana/keychain';

// Sync backends (AWS KMS, GCP KMS, Turnkey, Vault, CDP) return instantly
const address = await resolveAddress({
    backend: 'vault',
    vaultAddr: 'https://vault.example.com',
    vaultToken: 'hvs.xxx',
    keyName: 'my-key',
    publicKey: '4Nd1m...',
});

// Async backends (Privy, Para, Fireblocks, Fordefi, Crossmint, Dfns, Utila) fetch from the API
const address2 = await resolveAddress({
    backend: 'privy',
    appId: '...',
    appSecret: '...',
    walletId: '...',
});

Config Types

The KeychainSignerConfig discriminated union and individual config types are exported for building config management, CLIs, or dashboards:

import type { KeychainSignerConfig, BackendName, PrivySignerConfig } from '@solana/keychain';

// BackendName = 'aws-kms' | 'cdp' | 'crossmint' | 'dfns' | 'fireblocks' | 'fordefi' | 'gcp-kms' | 'memory' | 'openfort' | 'para' | 'privy' | 'turnkey' | 'utila' | 'vault'

function loadConfig(json: unknown): KeychainSignerConfig {
    // Parse and validate your config...
}

Signing a Compiled Transaction

If you already have a compiled transaction (e.g. from a dApp, backend service, or another system), use signTransactionWithSigners from @solana/signers (≥ 8.1) to sign it directly:

import { signTransactionWithSigners } from '@solana/signers';
import { createKeychainSigner } from '@solana/keychain';

const signer = await createKeychainSigner({
    backend: 'vault',
    vaultAddr: 'https://vault.example.com',
    vaultToken: 'hvs.xxx',
    keyName: 'my-key',
    publicKey: '4Nd1m...',
});

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

This complements the message-level helpers (signTransactionMessageWithSigners) which extract signers from account metas automatically. The transaction-level variant is useful when signers aren't embedded in the transaction message.

Direct Factory Imports

Each backend also exports its own factory function:

import { createPrivySigner } from '@solana/keychain';

const signer = await createPrivySigner({
    appId: '...',
    appSecret: '...',
    walletId: '...',
});

Namespaced Imports

Each signer package is available under its namespace for accessing types and utilities:

import { fireblocks, vault } from '@solana/keychain';

type VaultConfig = vault.VaultSignerConfig;
type FireblocksStatus = fireblocks.FireblocksTransactionStatus;

Core Utilities

Core types and utilities from @solana/keychain-core are re-exported:

import { SignerErrorCode, type SolanaSigner } from '@solana/keychain';

try {
    await signer.signMessages([message]);
} catch (error) {
    if (error.code === SignerErrorCode.REMOTE_API_ERROR) {
        // Handle API error
    }
}

Available Signers

| Backend | Package | Address Source | |---------|---------|---------------| | aws-kms | @solana/keychain-aws-kms | Config (publicKey) | | cdp | @solana/keychain-cdp | Config (address) | | crossmint | @solana/keychain-crossmint | API | | dfns | @solana/keychain-dfns | API | | fireblocks | @solana/keychain-fireblocks | API | | fordefi | @solana/keychain-fordefi | API | | gcp-kms | @solana/keychain-gcp-kms | Config (publicKey) | | memory | @solana/keychain-memory | Derived from local keypair | | openfort | @solana/keychain-openfort | API | | para | @solana/keychain-para | API | | privy | @solana/keychain-privy | API | | turnkey | @solana/keychain-turnkey | Config (publicKey) | | utila | @solana/keychain-utila | API | | vault | @solana/keychain-vault | Config (publicKey) |

Signer Shapes

@solana/keychain-core defines one capability interface per Kit signer shape, each adding isAvailable(): Promise<boolean>: SolanaTransactionSigner (Kit's TransactionPartialSigner), SolanaModifyingSigner (Kit's TransactionModifyingSigner), SolanaSendingSigner (Kit's TransactionSendingSigner), and the orthogonal SolanaMessageSigner (Kit's MessagePartialSigner). SolanaSigner is the union of the three transaction shapes — any keychain signer.

When the backend literal is known, createKeychainSigner's overloads return the exact shape: crossmint → SolanaSendingSigner, fordefi with chain set → FordefiNativeSigner, or FordefiNativeManualSigner (SolanaModifyingSigner & SolanaMessageSigner) with pushMode: 'manual', utila → SolanaTransactionSigner (no signMessages), and every other backend (including Fordefi black-box mode) → SolanaTransactionSigner & SolanaMessageSigner. With a widened KeychainSignerConfig — e.g. config loaded at runtime — the return type is the SolanaSigner union; narrow with isSolanaTransactionSigner() / isSolanaModifyingSigner() / isSolanaSendingSigner() from @solana/keychain-core before calling a signing method:

import { isSolanaModifyingSigner, isSolanaSendingSigner, isSolanaTransactionSigner } from '@solana/keychain-core';

const signer = await createKeychainSigner(loadConfig()); // SolanaSigner

if (isSolanaSendingSigner(signer)) {
    await signer.signAndSendTransactions([transaction]);
} else if (isSolanaModifyingSigner(signer)) {
    // Fordefi native manual mode: continue from the returned transaction, never the one you passed in
    const [signedTransaction] = await signer.modifyAndSignTransactions([transaction]);
} else if (isSolanaTransactionSigner(signer)) {
    await signer.signTransactions([transaction]);
}

Managed-broadcast signers (Crossmint, Fordefi native auto mode) and Fordefi native manual mode deliberately expose no signTransactions, because Kit classifies signers by method presence.

License

MIT