---
title: TypeScript
description: Install and use @solana/keychain in TypeScript applications
---

## Installation

Install the umbrella package or individual signers as needed:

```shell
# 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-memory      # Local keypair signer
pnpm add @solana/keychain-vault       # HashiCorp Vault
pnpm add @solana/keychain-aws-kms     # AWS KMS
pnpm add @solana/keychain-gcp-kms     # GCP 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-openfort    # Openfort
pnpm add @solana/keychain-para        # Para
pnpm add @solana/keychain-utila       # Utila

# Kit client plugins (keychainSigner / keychainPayer / keychainIdentity)
pnpm add @solana/keychain-kit-plugin
```

## Basic Usage

### Unified Factory (Recommended for apps wanting to support multiple signers)

Use `createKeychainSigner` with a discriminated config to create any backend:

```typescript
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:

```typescript
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`:

```typescript
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;
}
```

### Using with a Kit Client (keychainSigner plugin)

`@solana/keychain-kit-plugin` installs a keychain signer directly on a
[Kit client](https://github.com/anza-xyz/kit), wiring it up as the `payer` and
`identity` so you skip the manual `pipe` setup shown above:

```typescript
import { createClient } from "@solana/kit";
import { keychainSigner } from "@solana/keychain-kit-plugin";

const client = await createClient().use(
  keychainSigner({
    backend: "privy",
    appId: process.env.PRIVY_APP_ID!,
    appSecret: process.env.PRIVY_APP_SECRET!,
    walletId: process.env.PRIVY_WALLET_ID!
  })
);

client.payer; // SolanaSigner — also a Kit TransactionSigner
client.identity; // same signer instance
```

The plugin accepts the same backend-tagged config as `createKeychainSigner`, and
only the backend it dispatches to is bundled (backend packages load via dynamic
`import()`).

Use `keychainPayer` or `keychainIdentity` to set just one role, and mix backends
on a single client:

```typescript
import { createClient } from "@solana/kit";
import { keychainIdentity, keychainPayer } from "@solana/keychain-kit-plugin";

const client = await createClient()
  .use(
    keychainPayer({
      backend: "memory",
      privateKeyPath: "~/.config/solana/id.json"
    })
  )
  .use(keychainIdentity({ backend: "turnkey", ...turnkeyConfig }));
```

Already have a `SolanaSigner`? Every keychain signer is a valid Kit
`TransactionSigner`, so you can install an existing one with
[`@solana/kit-plugin-signer`](https://github.com/anza-xyz/kit-plugins/tree/main/packages/kit-plugin-signer)
instead (`pnpm add @solana/kit-plugin-signer`):

```typescript
import { signer } from "@solana/kit-plugin-signer";
import { createKeychainSigner } from "@solana/keychain";

const mySigner = await createKeychainSigner({
  backend: "vault",
  ...vaultConfig
});
const client = createClient().use(signer(mySigner));
```

## Backend Configuration

### HashiCorp Vault

```typescript
import { createVaultSigner } from "@solana/keychain-vault";

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

### AWS KMS

```typescript
import { createAwsKmsSigner } from "@solana/keychain-aws-kms";

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

### Privy

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

const signer = await createPrivySigner({
  appId: "app_id",
  appSecret: "app_secret",
  walletId: "wallet_id"
});
```

### Turnkey

```typescript
import { createTurnkeySigner } from "@solana/keychain-turnkey";

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

### Fireblocks

```typescript
import { createFireblocksSigner } from "@solana/keychain-fireblocks";

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

### CDP (Coinbase Developer Platform)

```typescript
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

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

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

### Dfns

```typescript
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

```typescript
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:

```typescript
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:

```typescript
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](/docs/tools/keychain/adding-signers) to integrate
additional key management services.
