TypeScript

Upgraden vanaf 1.x? Zie de 2.0-migratiegids.

Installatie

Installeer het overkoepelende pakket of individuele signers naar behoefte:

# 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

Vereist @solana/kit 8.1 of hoger. v1-transacties (createTransactionMessage({ version: 1 })) worden ondersteund, behalve door Fireblocks met useProgramCall: true, dat alleen legacy en v0 accepteert.

Basisgebruik

Uniforme Factory (Aanbevolen voor apps die meerdere signers willen ondersteunen)

Gebruik createKeychainSigner met een gediscrimineerde configuratie om elke backend te creëren:

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
);

Of installeer een individueel signer-pakket voor een kleinere afhankelijkheidsfootprint:

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

Gebruiken met Transaction Messages

Elke backend behalve Crossmint en de native modus van Fordefi retourneert een SolanaTransactionSigner, een Kit TransactionPartialSigner die werkt met de hieronder genoemde partial-signer-helpers van @solana/signers. Backends met beheerde broadcast worden behandeld in Signer Capabilities.

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

Ondertekenen en verzenden met elke signer

signAndSendTransaction uit @solana/keychain-core krijgt een transactie on-chain, ongeacht het type signer. Sending signers versturen via hun provider; elk ander type gebruikt de sendTransaction die je meegeeft (core heeft geen RPC-afhankelijkheid):

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

Gebruiken met een Kit Client (keychainSigner plugin)

@solana/keychain-kit-plugin installeert een keychain signer rechtstreeks op een Kit client, en koppelt deze als de payer en identity, zodat je de handmatige pipe-instelling zoals hierboven beschreven overslaat:

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

De plugin accepteert dezelfde backend-getagde configuratie als createKeychainSigner, behalve voor Crossmint en de native modus van Fordefi (chain ingesteld). Die backends herschrijven de transactie aan de serverkant, dus ze kunnen niet fungeren als client-payer of identity; de plugin weigert ze tijdens het compileren en tijdens runtime. Alleen de backend waarnaar wordt doorverwezen, wordt gebundeld (backendpakketten worden geladen via dynamische import()).

Gebruik keychainPayer of keychainIdentity om slechts één rol in te stellen en backends te combineren op een enkele client:

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 }));

Heb je al een SolanaTransactionSigner? Dit is een geldige Kit TransactionPartialSigner, dus je kunt hem in plaats daarvan installeren met @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));

Annulering en onbevestigde broadcasts

signTransactions, modifyAndSignTransactions, signAndSendTransactions en signMessages accepteren allemaal { abortSignal } als tweede argument. Afbreken stopt het wachten; het maakt werk dat een provider al heeft geaccepteerd niet ongedaan.

Bij de native automodus van Crossmint en Fordefi betekent een fout niet dat er niets is aangekomen. Als de provider de transactie mogelijk heeft geaccepteerd, is de foutcode SignerErrorCode.BROADCAST_UNCONFIRMED ("SIGNER_BROADCAST_UNCONFIRMED"). context.providerTransactionId wordt ingesteld wanneer het aanmaken is geaccepteerd, en context.idempotencyKey bevat de sleutel die van het bericht is afgeleid. Het opnieuw verzenden van de byte-identieke transactie is veilig; een opnieuw opgebouwde transactie (bijvoorbeeld met een nieuwe blockhash) is een nieuwe overdracht. providerMayHaveAccepted(error) en providerStatus(error) uit @solana/keychain-core helpen bij het classificeren van de fout. Stem af met de provider voordat je het opnieuw probeert.

Backendconfiguratie

Geheugen

Geef precies één van keyPair, privateKey, privateKeyString of privateKeyPath op:

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 kan alleen verzenden. De API voert een goedgekeurde transactie altijd serverzijdig uit en sponsort de gas, dus de signer biedt alleen signAndSendTransactions(): er is geen signTransactions() of signMessages(), en hij kan niet worden geïnstalleerd met @solana/keychain-kit-plugin. De geretourneerde handtekening identificeert de transactie die Crossmint heeft verwerkt.

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"
});

Para

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

Utila

Utila ondertekent alleen transacties; het heeft geen 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 heeft drie ondertekeningsmodi, vastgelegd bij de constructie via chain en pushMode. Elke modus biedt precies één transactiemethode, en alle drie ondertekenen berichten:

ModusConfiguratieTypeMethode
Black boxchain niet ingesteldFordefiBlackBoxSignersignTransactions()
Native autochain ingesteld, pushMode weggelaten of "auto"FordefiNativeSignersignAndSendTransactions()
Native handmatigchain ingesteld, pushMode: "manual"FordefiNativeManualSignermodifyAndSignTransactions()

API-verzoeken worden geauthenticeerd met een ECDSA P-256-verzoekhandtekening: geef de ondertekeningssleutel op als privateKeyPem, of bewaar deze in een KMS/HSM door een requestSigner mee te geven.

Native automodus (aanbevolen voor on-chain gebruik): stel chain in, en Fordefi ondertekent en verzendt de transactie zelf. Omdat Fordefi de blockhash of de kosten kan vervangen vóór het ondertekenen, is de signer een Kit TransactionSendingSigner: gebruik hem met signAndSendTransactionMessageWithSigners, niet met de hierboven getoonde partial-signer-flow. De native automodus accepteert alleen een niet-ondertekende transactie waarvan de enige vereiste ondertekenaar de vault is, en kan niet worden gebruikt met @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);

Native handmatige modus: stel chain en pushMode: "manual" in. Fordefi herschrijft het bericht (recente blockhash, Compute Budget-feeinstructies) en ondertekent het, maar verzendt het niet. modifyAndSignTransactions() retourneert de transactie die Fordefi heeft ondertekend en die de door jou ingediende vervangt: ga altijd verder met de teruggegeven transactie. Fordefi moet de fee payer zijn en moet vóór elke andere vereiste ondertekenaar ondertekenen. Het herschreven bericht wordt niet vergeleken, dus controleer het resultaat vóór het verzenden.

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
]);

Black box-modus: laat chain weg. Fordefi ondertekent ruwe bytes en verstuurt niet; je assembleert en verzendt de transactie zelf. Gebruik dit met een Fordefi black box-vault.

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")
});

Signer Capabilities

@solana/keychain-core definieert één interface per Kit-signertype. Elk voegt isAvailable(): Promise<boolean> toe aan de bijbehorende @solana/signers-interface:

  • SolanaTransactionSigner (Kit TransactionPartialSigner): retourneert handtekeningen voor een transactie die jij beheert.
  • SolanaModifyingSigner (Kit TransactionModifyingSigner): herschrijft de transactie, ondertekent deze en retourneert de nieuwe transactie zonder te verzenden.
  • SolanaSendingSigner (Kit TransactionSendingSigner): ondertekent en verzendt via zijn provider.
  • SolanaMessageSigner (Kit MessagePartialSigner): ondertekent off-chain berichten. Dit staat los van de transactietypen.

SolanaSigner is de unie van de drie transactietypen. Het retourtype van elke factory benoemt het exacte type van de betreffende backend. Wanneer de configuratie pas tijdens runtime bekend is, kun je vernauwen met isSolanaTransactionSigner, isSolanaModifyingSigner, isSolanaSendingSigner of isSolanaMessageSigner. signerCapabilities(signer) rapporteert alle vier tegelijk.

BackendType
memory, vault, aws-kms, gcp-kms, privy, turnkey, fireblocks, cdp, dfns, para, openfort, fordefi (black box)SolanaTransactionSigner & SolanaMessageSigner
utilaSolanaTransactionSigner (geen berichtondertekening)
fordefi (native handmatig)SolanaModifyingSigner & SolanaMessageSigner
fordefi (native auto)SolanaSendingSigner & SolanaMessageSigner
crossmintSolanaSendingSigner (geen berichtondertekening)
import {
isSolanaSendingSigner,
isSolanaTransactionSigner
} from "@solana/keychain-core";
if (isSolanaSendingSigner(signer)) {
await signer.signAndSendTransactions([transaction]);
} else if (isSolanaTransactionSigner(signer)) {
await signer.signTransactions([transaction]);
}

Aangepaste Signers Bouwen

Implementeer de capability-interfaces die jouw backend ondersteunt:

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);
}
}

Implementeer alleen wat jouw backend ondersteunt. Kit classificeert signers op basis van welke methoden bestaan, dus voeg nooit een methode toe die alleen een fout genereert.

Zie de gids voor het toevoegen van signers om aanvullende sleutelbeheerservices te integreren.

Is this page helpful?

© 2026 Solana Foundation. Alle rechten voorbehouden.