TypeScript

1.xからのアップグレードですか?2.0移行ガイドをご覧ください。

インストール

必要に応じて、統合パッケージまたは個別の署名者をインストールします:

# 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
pnpm add @solana/keychain-fordefi # Fordefi
# Kit client plugins (keychainSigner / keychainPayer / keychainIdentity)
pnpm add @solana/keychain-kit-plugin

@solana/kit 8.1以降が必要です。v1トランザクション(createTransactionMessage({ version: 1 }))はサポートされていますが、useProgramCall: trueを指定したFireblocksは例外で、レガシーとv0のみを受け付けます。

基本的な使い方

統合ファクトリ(複数の署名者をサポートしたいアプリに推奨)

createKeychainSignerを判別可能な設定と共に使用して、任意のバックエンドを作成します:

import { createKeychainSigner } from "@solana/keychain";
import { signTransactionWithSigners } from "@solana/signers"; // requires @solana/signers >= 8.1
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
);

または、依存関係のフットプリントを小さくするために、個別の署名者パッケージをインストールします:

import { createPrivySigner } from "@solana/keychain-privy";
const signer = await createPrivySigner({
appId: "your-app-id",
appSecret: "your-app-secret",
walletId: "your-wallet-id"
});

トランザクションメッセージでの使用

CrossmintとFordefiネイティブモードを除くすべてのバックエンドはSolanaTransactionSignerを返します。これはKitのTransactionPartialSignerであり、以下の@solana/signersのpartial-signerヘルパーで使用できます。マネージドブロードキャスト型のバックエンドについては、署名者の機能で説明しています。

import type { SolanaTransactionSigner } from "@solana/keychain-core";
import { signTransactionMessageWithSigners } from "@solana/signers";
import {
createTransactionMessage,
setTransactionMessageFeePayerSigner,
pipe
} from "@solana/kit";
async function signWithKeychain(signer: SolanaTransactionSigner) {
// 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)
// ... set a lifetime and add instructions
);
// Sign with the standard signers API
const signedTx = await signTransactionMessageWithSigners(transaction);
return signedTx;
}

任意の署名者で署名して送信する

@solana/keychain-coreのsignAndSendTransactionは、署名者の形態を問わずトランザクションをオンチェーンに送信します。送信型の署名者はプロバイダー経由でブロードキャストし、それ以外の形態では渡されたsendTransactionを使用します(coreはRPCに依存しません):

import { signAndSendTransaction } from "@solana/keychain-core";
const signature = await signAndSendTransaction(signer, transaction, {
sendTransaction: (tx) =>
sendAndConfirmTransaction(tx, { commitment: "confirmed" })
});

Kit クライアントでの使用方法(keychainSigner プラグイン)

@solana/keychain-kit-plugin は、キーチェーン署名者を Kit クライアントに直接インストールし、payer および identity として自動的に設定するため、上記の手動による pipe のセットアップを省略できます:

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; // SolanaTransactionSigner, also a Kit TransactionPartialSigner
client.identity; // same signer instance

プラグインはcreateKeychainSignerと同じバックエンドタグ付き設定を受け付けますが、CrossmintとFordefiネイティブモード(chainを設定した場合)は除きます。これらのバックエンドはサーバー側でトランザクションを書き換えるため、クライアントのpayerやidentityとして機能できず、プラグインはコンパイル時と実行時にこれらを拒否します。ディスパッチ先のバックエンドのみがバンドルされます(バックエンドパッケージは動的なimport()で読み込まれます)。

keychainPayer または keychainIdentity を使用して単一のロールのみを設定し、単一クライアント上で複数のバックエンドを混在させることができます:

import { createClient } from "@solana/kit";
import { keychainIdentity, keychainPayer } from "@solana/keychain-kit-plugin";
const client = await createClient()
.use(
keychainPayer({
backend: "memory",
privateKeyPath: `${process.env.HOME}/.config/solana/id.json`
})
)
.use(keychainIdentity({ backend: "turnkey", ...turnkeyConfig }));

すでにSolanaTransactionSignerをお持ちですか?これは有効なKitのTransactionPartialSignerなので、代わりに@solana/kit-plugin-signerでインストールできます(pnpm add @solana/kit-plugin-signer):

import { createClient } from "@solana/kit";
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));

キャンセルと未確認のブロードキャスト

signTransactions、modifyAndSignTransactions、signAndSendTransactions、signMessagesはいずれも、第2引数に{ abortSignal }を指定できます。中止すると待機は止まりますが、プロバイダーがすでに受け付けた処理が取り消されるわけではありません。

CrossmintおよびFordefiのネイティブ自動モードでは、失敗したからといって何も反映されていないとは限りません。プロバイダーがトランザクションを受け付けた可能性がある場合、エラーコードはSignerErrorCode.BROADCAST_UNCONFIRMED("SIGNER_BROADCAST_UNCONFIRMED")になります。作成リクエストが受理された場合はcontext.providerTransactionIdが設定され、context.idempotencyKeyにはメッセージから導出されたキーが格納されます。バイト単位で同一のトランザクションを再送しても安全ですが、再構築したもの(たとえば新しいブロックハッシュを使用したもの)は新しい送金になります。@solana/keychain-coreのproviderMayHaveAccepted(error)とproviderStatus(error)は、エラーの分類に役立ちます。再試行する前に、プロバイダー側の状態と照合してください。

バックエンド設定

メモリ

keyPair、privateKey、privateKeyString、privateKeyPathのうち、ちょうど1つを指定してください:

import { createMemorySigner } from "@solana/keychain-memory";
const signer = await createMemorySigner({
privateKeyPath: "/path/to/id.json"
});

HashiCorp Vault

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

import { createAwsKmsSigner } from "@solana/keychain-aws-kms";
const signer = createAwsKmsSigner({
keyId: "alias/my-solana-key",
publicKey: "base58_public_key",
region: "us-east-1" // optional
});

GCP KMS

import { createGcpKmsSigner } from "@solana/keychain-gcp-kms";
const signer = createGcpKmsSigner({
keyName:
"projects/my-project/locations/us-east1/keyRings/my-ring/cryptoKeys/my-key/cryptoKeyVersions/1",
publicKey: "base58_public_key"
});

Privy

import { createPrivySigner } from "@solana/keychain-privy";
const signer = await createPrivySigner({
appId: "app_id",
appSecret: "app_secret",
walletId: "wallet_id"
});

Turnkey

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

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)

import { createCdpSigner } from "@solana/keychain-cdp";
const signer = await createCdpSigner({
cdpApiKeyId: "api_key_id",
cdpApiKeySecret: "api_key_secret",
cdpWalletSecret: "wallet_secret",
address: "base58_address",
network: "solana" // or "solana-devnet"; required for address lookup tables
});

Crossmint

import { createCrossmintSigner } from "@solana/keychain-crossmint";
const signer = await createCrossmintSigner({
apiKey: "api_key",
walletLocator: "wallet_locator"
});

Crossmintは送信専用です。そのAPIは承認済みのトランザクションを常にサーバー側で実行し、ガス代をスポンサーするため、署名者が公開するのはsignAndSendTransactions()のみです。signTransactions()やsignMessages()はなく、@solana/keychain-kit-pluginでインストールすることもできません。返される署名は、Crossmintが反映したトランザクションを識別します。

const [signature] = await signer.signAndSendTransactions([transaction]);
// or: await signAndSendTransactionMessageWithSigners(transactionMessage);

Dfns

import { createDfnsSigner } from "@solana/keychain-dfns";
const signer = await createDfnsSigner({
authToken: "auth_token",
credId: "cred_id",
privateKeyPem: "-----BEGIN EC PRIVATE KEY-----\n...",
walletId: "wallet_id"
});

Openfort

import { createOpenfortSigner } from "@solana/keychain-openfort";
const signer = await createOpenfortSigner({
secretKey: "sk_...",
walletSecret: "wallet_secret",
accountId: "account_id"
});

パラメータ

import { createParaSigner } from "@solana/keychain-para";
const signer = await createParaSigner({
apiKey: "api_key",
walletId: "wallet_id"
});

Utila

Utilaはトランザクションの署名のみに対応しており、signMessages()はありません。

import { createUtilaSigner } from "@solana/keychain-utila";
const signer = await createUtilaSigner({
serviceAccountEmail: "sa@example.com",
serviceAccountPrivateKeyPem: "-----BEGIN PRIVATE KEY-----\n...",
vaultId: "vault_id",
walletId: "wallet_id",
network: "networks/solana-devnet"
});

Fordefi

Fordefiには3つの署名モードがあり、chainとpushModeによって構築時に固定されます。各モードが公開するトランザクションメソッドはちょうど1つで、3つのモードすべてがメッセージに署名できます:

モード設定型メソッド
ブラックボックスchain未設定FordefiBlackBoxSignersignTransactions()
ネイティブ自動chainを設定、pushModeは省略または"auto"FordefiNativeSignersignAndSendTransactions()
ネイティブ手動chainを設定、pushMode: "manual"FordefiNativeManualSignermodifyAndSignTransactions()

APIリクエストはECDSA P-256のリクエスト署名で認証されます。署名鍵をprivateKeyPemとして指定するか、requestSignerを渡してKMS/HSM内に保管したままにします。

ネイティブ自動モード(オンチェーンでの利用に推奨):chainを設定すると、Fordefi自身がトランザクションに署名してブロードキャストします。Fordefiは署名前にブロックハッシュや手数料を置き換える場合があるため、署名者はKitのTransactionSendingSignerとなります。上記のpartial-signerのフローではなく、signAndSendTransactionMessageWithSignersで使用してください。ネイティブ自動モードが受け付けるのは、唯一必要な署名者がボールトである未署名トランザクションのみで、@solana/keychain-kit-pluginと併用することはできません。

import { createFordefiSigner } from "@solana/keychain-fordefi";
import { signAndSendTransactionMessageWithSigners } from "@solana/signers";
import { readFileSync } from "node:fs";
const signer = await createFordefiSigner({
accessToken: process.env.FORDEFI_ACCESS_TOKEN!,
vaultId: process.env.FORDEFI_VAULT_ID!,
publicKey: process.env.FORDEFI_PUBLIC_KEY!, // Solana vault address (base58)
privateKeyPem: readFileSync("./secret/private.pem", "utf8"),
chain: "solana_devnet", // or "solana_mainnet"
fee: { type: "custom", priority_fee: "1000" } // optional
});
const signature =
await signAndSendTransactionMessageWithSigners(transactionMessage);

ネイティブ手動モード:chainとpushMode: "manual"を設定します。Fordefiはメッセージ(最新のブロックハッシュ、Compute Budgetのfee instructions)を書き換えて署名しますが、ブロードキャストは行いません。modifyAndSignTransactions()はFordefiが署名したトランザクションを返し、これは送信したものと置き換わります。必ず返されたトランザクションから処理を続けてください。Fordefiは手数料支払者である必要があり、他の必要な署名者より先に署名しなければなりません。書き換え内容の差分は提供されないため、ブロードキャストの前に結果を確認してください。

import { createFordefiSigner } from "@solana/keychain-fordefi";
import { readFileSync } from "node:fs";
const signer = await createFordefiSigner({
accessToken: process.env.FORDEFI_ACCESS_TOKEN!,
vaultId: process.env.FORDEFI_VAULT_ID!,
publicKey: process.env.FORDEFI_PUBLIC_KEY!,
privateKeyPem: readFileSync("./secret/private.pem", "utf8"),
chain: "solana_devnet",
pushMode: "manual"
});
const [signedTransaction] = await signer.modifyAndSignTransactions([
transaction
]);

ブラックボックスモード:chainを省略します。Fordefiは生のバイト列に署名しますが、ブロードキャストは行いません。トランザクションのアセンブルと送信はご自身で行ってください。このモードはFordefiのブラックボックスボールトと組み合わせて使用します。

import { createFordefiSigner } from "@solana/keychain-fordefi";
import { readFileSync } from "node:fs";
const signer = await createFordefiSigner({
accessToken: process.env.FORDEFI_ACCESS_TOKEN!,
vaultId: process.env.FORDEFI_BB_VAULT_ID!,
publicKey: process.env.FORDEFI_BB_PUBLIC_KEY!,
privateKeyPem: readFileSync("./secret/private.pem", "utf8")
});

署名者の機能

@solana/keychain-coreは、Kitの署名者の形態ごとに1つのインターフェースを定義しています。それぞれが、対応する@solana/signersのインターフェースにisAvailable(): Promise<boolean>を追加したものです:

  • SolanaTransactionSigner(KitのTransactionPartialSigner):ユーザーが所有するトランザクションに対する署名を返します。
  • SolanaModifyingSigner(KitのTransactionModifyingSigner):トランザクションを書き換えて署名し、ブロードキャストせずに新しいトランザクションを返します。
  • SolanaSendingSigner(KitのTransactionSendingSigner):プロバイダー経由で署名とブロードキャストを行います。
  • SolanaMessageSigner(KitのMessagePartialSigner):オフチェーンメッセージに署名します。トランザクションの形態とは別のものです。

SolanaSignerは3つのトランザクション形態のユニオン型です。各ファクトリーの戻り値の型は、そのバックエンドの正確な形態を示します。設定が実行時にしか分からない場合は、isSolanaTransactionSigner、isSolanaModifyingSigner、isSolanaSendingSigner、isSolanaMessageSignerで絞り込みます。signerCapabilities(signer)は4つすべてを一度に返します。

バックエンド形態
memory, vault, aws-kms, gcp-kms, privy, turnkey, fireblocks, cdp, dfns, para, openfort, fordefi(ブラックボックス)SolanaTransactionSigner & SolanaMessageSigner
utilaSolanaTransactionSigner(メッセージ署名なし)
fordefi(ネイティブ手動)SolanaModifyingSigner & SolanaMessageSigner
fordefi(ネイティブ自動)SolanaSendingSigner & SolanaMessageSigner
crossmintSolanaSendingSigner(メッセージ署名なし)
import {
isSolanaSendingSigner,
isSolanaTransactionSigner
} from "@solana/keychain-core";
if (isSolanaSendingSigner(signer)) {
await signer.signAndSendTransactions([transaction]);
} else if (isSolanaTransactionSigner(signer)) {
await signer.signTransactions([transaction]);
}

カスタム署名者の構築

バックエンドが対応する機能のインターフェースを実装します:

import type {
SolanaMessageSigner,
SolanaTransactionSigner
} from "@solana/keychain-core";
import type { Address } from "@solana/addresses";
import type {
MessagePartialSignerConfig,
SignableMessage,
TransactionPartialSignerConfig
} from "@solana/signers";
import type { Transaction } from "@solana/transactions";
class MyCustomSigner implements SolanaTransactionSigner, SolanaMessageSigner {
constructor(readonly address: Address) {}
async isAvailable(): Promise<boolean> {
return await myBackend.healthCheck();
}
async signMessages(
messages: readonly SignableMessage[],
config?: MessagePartialSignerConfig
) {
return await myBackend.signMessages(messages, config?.abortSignal);
}
async signTransactions(
transactions: readonly Transaction[],
config?: TransactionPartialSignerConfig
) {
return await myBackend.signTransactions(transactions, config?.abortSignal);
}
}

バックエンドが対応するものだけを実装してください。Kitはどのメソッドが存在するかで署名者を分類するため、例外を投げるだけのメソッドは追加しないでください。

追加の鍵管理サービスを統合するには、署名者の追加ガイドを参照してください。

Is this page helpful?

© 2026 Solana Foundation. 無断転載を禁じます。