Rust

Instalasi

Tambahkan solana-keychain ke Cargo.toml Anda dengan hanya backend yang Anda butuhkan:

Cargo.toml
[dependencies]
# Memory signer only (default, Solana SDK 2.x)
solana-keychain = "2.0"
# Or specify backends explicitly (pick exactly one SDK feature)
solana-keychain = { version = "2.0", default-features = false, features = ["vault", "aws_kms", "sdk-v2"] }
# All remote backends on the Solana 4.x SDK line
solana-keychain = { version = "2.0", default-features = false, features = ["all", "sdk-v4"] }

Upgrade dari 1.x? Lihat panduan Migrasi ke 2.0.

Tanda Fitur

FiturDeskripsi
memoryPenandatanganan keypair lokal (default)
vaultMesin Transit HashiCorp Vault
aws_kmsAWS KMS dengan Ed25519
gcp_kmsGCP Cloud KMS dengan Ed25519
privyDompet tertanam Privy
turnkeyAPI Turnkey
fireblocksFireblocks MPC
cdpCoinbase Developer Platform
crossmintDompet terkelola Crossmint
dfnsInfrastruktur dompet Dfns
openfortDompet tertanam Openfort
paraDompet MPC Para
utilaKustodi MPC Utila
fordefiKustodi MPC Fordefi
ledgerDompet perangkat keras Ledger melalui USB-HID (hanya Rust, opt-in, tidak termasuk dalam all)
allAktifkan semua backend kecuali ledger
sdk-v2Solana SDK 2.x (default)
sdk-v3Solana SDK 3.x
sdk-v4Solana SDK 4.x (diperlukan untuk transaksi v1)
unsafe-debugMencatat log respons error lengkap dari provider; jangan pernah mengaktifkannya di production

Tepat satu dari sdk-v2, sdk-v3, dan sdk-v4 harus diaktifkan.

Penggunaan Dasar

Semua signer mengimplementasikan trait SolanaSigner dasar (pubkey, sign_message, is_available). Setiap backend juga mengimplementasikan tepat satu trait kapabilitas:

  • TransactionSigner: menandatangani transaksi Anda apa adanya.
  • ModifyingSigner: provider menulis ulang transaksi, lalu menandatanganinya.
  • SendingSigner: provider menandatangani dan menyiarkannya.
use solana_keychain::{SignerError, SolanaSigner, TransactionSigner};
use solana_sdk::transaction::VersionedTransaction;
async fn sign_transaction(
signer: &impl TransactionSigner,
tx: &mut VersionedTransaction,
) -> Result<(), SignerError> {
// Get the signer's public key
let pubkey = signer.pubkey();
println!("Signing with: {}", pubkey);
// Check availability (useful for remote signers)
if !signer.is_available().await {
return Err(SignerError::NotAvailable("Signer offline".into()));
}
// Sign the transaction: returns Complete or Partial
let result = signer.sign_transaction(tx).await?;
let (base64_tx, signature) = result.into_signed_transaction();
println!("Signature: {}", signature);
Ok(())
}

Konversikan Transaction legacy dengan .into(). Transaksi legacy dan v0 berfungsi di setiap fitur SDK; transaksi v1 memerlukan sdk-v4.

Kapabilitas Signer

BackendTrait kapabilitassign_message
CrossmintSendingSignerTidak didukung
Fordefi native autoSendingSignerYa
Fordefi native manualModifyingSignerYa
UtilaTransactionSignerTidak didukung
CDPTransactionSignerHanya payload UTF-8
LedgerTransactionSignerYa, melalui envelope off-chain
Semua lainnya (termasuk Fordefi black box)TransactionSignerYa

Konstruktor Signer::from_* menjalankan init() untuk Anda. Jika Anda membuat tipe signer Privy, Fireblocks, Dfns, Crossmint, Para, Openfort, atau Utila secara langsung, panggil init().await sebelum digunakan.

Konfigurasi Backend

Penandatangan Memori

Untuk pengembangan dan pengujian dengan keypair lokal:

use solana_keychain::Signer;
// From base58 private key
let signer = Signer::from_memory("base58_private_key")?;
// From JSON keypair file path
let signer = Signer::from_memory_file("/path/to/keypair.json")?;
// From byte array string
let signer = Signer::from_memory("[1,2,3,...]")?;

HashiCorp Vault

Untuk HSM yang dihosting sendiri dengan mesin Transit:

use solana_keychain::Signer;
let signer = Signer::from_vault(
"https://vault.example.com:8200".to_string(), // Vault address
"hvs.xxxxx".to_string(), // Vault token
"my-solana-key".to_string(), // Key name in Transit
"base58_public_key".to_string(), // Expected public key
None, // Default HTTP timeouts
)?;

AWS KMS

Untuk penandatanganan native-cloud dengan kunci Ed25519 AWS KMS:

use solana_keychain::Signer;
let signer = Signer::from_aws_kms(
"alias/my-solana-key".to_string(), // KMS key ID or alias
"base58_public_key".to_string(), // Expected public key
Some("us-east-1".to_string()), // Region (optional)
).await?;

Privy

Untuk penandatanganan dompet tertanam:

use solana_keychain::Signer;
let signer = Signer::from_privy(
"app_id".to_string(), // Privy app ID
"app_secret".to_string(), // Privy app secret
"wallet_id".to_string(), // Wallet ID
None, // Default HTTP timeouts
).await?;

Turnkey

Untuk penandatanganan non-kustodian:

use solana_keychain::Signer;
let signer = Signer::from_turnkey(
"api_public_key".to_string(), // Turnkey API public key
"api_private_key".to_string(), // Turnkey API private key
"org_id".to_string(), // Organization ID
"private_key_id".to_string(), // Private key ID in Turnkey
"base58_public_key".to_string(),// Expected public key
None, // Default HTTP timeouts
)?;

Fireblocks

Untuk penandatanganan MPC institusional:

use solana_keychain::{Signer, FireblocksSignerConfig};
let config = FireblocksSignerConfig {
api_key: "api_key".to_string(),
private_key_pem: "-----BEGIN RSA PRIVATE KEY-----\n...".to_string(),
vault_account_id: "0".to_string(),
asset_id: Some("SOL".to_string()), // None defaults to "SOL"; "SOL_TEST" for devnet
api_base_url: None,
poll_interval_ms: None,
max_poll_attempts: None,
use_program_call: None, // Some(true) signs via PROGRAM_CALL (sign-only, legacy/v0, hot wallet)
http_client_config: None,
};
let signer = Signer::from_fireblocks(config).await?;

GCP KMS

Untuk penandatanganan cloud-native dengan kunci Ed25519 GCP Cloud KMS:

use solana_keychain::Signer;
let signer = Signer::from_gcp_kms(
"projects/my-project/locations/us-east1/keyRings/my-ring/cryptoKeys/my-key/cryptoKeyVersions/1".to_string(),
"base58_public_key".to_string(),
).await?;

CDP (Coinbase Developer Platform)

Untuk penandatanganan dompet terkelola Coinbase:

use solana_keychain::{Signer, CdpSignerConfig, CDP_NETWORK_MAINNET};
let signer = Signer::from_cdp(CdpSignerConfig {
api_key_id: "api_key_id".to_string(), // CDP API key ID
api_key_secret: "api_key_secret".to_string(), // CDP API private key (base64 Ed25519)
wallet_secret: "wallet_secret".to_string(), // CDP wallet secret (base64 PKCS#8 DER)
address: "base58_address".to_string(), // Solana account address
network: Some(CDP_NETWORK_MAINNET.to_string()), // Required to sign transactions with address lookup tables
api_base_url: None,
http_client_config: None, // Default HTTP timeouts
})?;

sign_message CDP hanya menerima payload UTF-8.

Crossmint

Crossmint hanya mendukung pengiriman: API-nya mengeksekusi setiap transaksi yang disetujui di sisi server, sehingga tidak ada jalur khusus tanda tangan, dan sign_message gagal. Panggil sign_and_send_transaction, yang tidak mengubah transaksi Anda dan mengembalikan tanda tangan dari transaksi yang berhasil masuk. Transaksi tersebut bisa berbeda dari transaksi Anda jika Crossmint mensponsori gas.

use solana_keychain::{Signer, CrossmintSignerConfig};
let config = CrossmintSignerConfig {
api_key: "api_key".to_string(),
wallet_locator: "wallet_locator".to_string(),
signer_secret: None,
signer: None,
api_base_url: None,
poll_interval_ms: None,
max_poll_attempts: None,
};
let signer = Signer::from_crossmint(config).await?;
let signature = signer
.as_sending_signer()
.expect("Crossmint is a sending signer")
.sign_and_send_transaction(&tx)
.await?;

Dfns

Untuk penandatanganan infrastruktur dompet Dfns:

use solana_keychain::{Signer, DfnsSignerConfig};
let config = DfnsSignerConfig {
auth_token: "auth_token".to_string(),
cred_id: "cred_id".to_string(),
private_key_pem: "-----BEGIN EC PRIVATE KEY-----\n...".to_string(),
wallet_id: "wallet_id".to_string(),
api_base_url: None,
http_client_config: None,
};
let signer = Signer::from_dfns(config).await?;

Para

Untuk penandatanganan dompet MPC Para:

use solana_keychain::Signer;
let signer = Signer::from_para(
"api_key".to_string(), // Para API key
"wallet_id".to_string(), // Para wallet ID
None, // Default API base URL
).await?;

Openfort

Untuk penandatanganan dompet backend Openfort:

use solana_keychain::Signer;
let signer = Signer::from_openfort(
"sk_live_...".to_string(), // Openfort secret key
"acc_...".to_string(), // Account ID
"wallet_secret".to_string(), // Wallet secret (base64 PKCS#8 DER or PEM)
None, // Default HTTP timeouts
).await?;

Utila

Untuk penandatanganan kustodi MPC Utila. sign_message tidak didukung, dan Anda menyiarkan transaksi yang telah ditandatangani sendiri.

use solana_keychain::{Signer, UtilaSignerConfig};
let signer = Signer::from_utila(UtilaSignerConfig {
service_account_email: "sa@example.com".to_string(),
service_account_private_key_pem: "-----BEGIN PRIVATE KEY-----\n...".to_string(),
vault_id: "vault_id".to_string(),
wallet_id: "wallet_id".to_string(),
network: "networks/solana-devnet".to_string(),
api_base_url: None,
poll_interval_ms: None,
max_poll_attempts: None,
designated_signers: None,
http_client_config: None,
}).await?;

Fordefi

Untuk penandatanganan kustodi MPC Fordefi. Permintaan API diautentikasi dengan tanda tangan permintaan ECDSA P-256. Berikan tepat satu dari private_key_pem, atau request_signer (sebuah Arc<dyn FordefiRequestSigner>, digunakan untuk menyimpan kunci tersebut di KMS/HSM).

Fordefi hadir dalam tiga tipe signer, yang ditetapkan saat konstruksi melalui chain dan push_mode:

chainpush_modeTipeKapabilitasPerilaku
Noneapa sajaFordefiBlackBoxSignerTransactionSignerMenandatangani byte mentah; Anda yang menyiarkan
Some(..)None atau AutoFordefiNativeAutoSignerSendingSignerFordefi dapat menulis ulang blockhash dan biaya, lalu menandatangani dan menyiarkan
Some(..)ManualFordefiNativeManualSignerModifyingSignerFordefi menulis ulang dan menandatangani; Anda menyiarkan transaksi yang dikembalikan

Mode native manual mengganti transaksi Anda dengan transaksi yang ditandatangani Fordefi. Lanjutkan dari transaksi tersebut, jangan pernah dari transaksi yang Anda buat. Mode ini harus dijalankan sebelum signer wajib lainnya.

use solana_keychain::{
Signer, FordefiSignerConfig, FordefiPushMode, SolanaChainUniqueId, FordefiSolanaFee,
FordefiPriorityLevel,
};
let config = FordefiSignerConfig {
access_token: "api_token".to_string(),
vault_id: "vault_uuid".to_string(),
private_key_pem: Some(std::fs::read_to_string("./secret/private.pem")?),
request_signer: None, // Or Some(Arc::new(your_kms_signer))
public_key: "base58_public_key".to_string(), // Solana vault address
chain: Some(SolanaChainUniqueId::SolanaDevnet), // None for black box mode
fee: Some(FordefiSolanaFee::Priority {
priority_level: FordefiPriorityLevel::Medium,
}),
push_mode: Some(FordefiPushMode::Auto), // Manual: sign without broadcasting
api_base_url: None, // Default: https://api.fordefi.com
poll_interval_ms: None, // Default: 2000
max_poll_attempts: None, // Default: 50
http_client_config: None, // Default HTTP timeouts
};
let signer = Signer::from_fordefi(config).await?;

Ledger

Untuk penandatanganan dompet perangkat keras melalui USB-HID (hanya Rust). Memerlukan fitur ledger, perangkat yang tidak terkunci dengan aplikasi Solana berjalan, dan, di Linux, aturan udev Ledger. Ledger tidak tercakup dalam audit saat ini; lihat status audit.

use solana_keychain::{LedgerConfig, Signer};
let signer = Signer::from_ledger(LedgerConfig {
confirm_pubkey_on_device: true,
..LedgerConfig::default()
})
.await?;

sign_message menandatangani envelope off-chain yang membungkus payload Anda, bukan byte mentahnya; bangun ulang dengan solana_keychain::ledger::ledger_offchain_envelope untuk verifikasi. Setel auto_open_app: false untuk penggunaan tanpa pengawasan. Permintaan yang ditolak pada perangkat mengembalikan SignerError::UserRejected.

Enum Signer Terpadu

Gunakan enum Signer untuk memilih backend saat runtime:

use solana_keychain::{Signer, SolanaSigner, SignerError};
async fn get_signer(backend: &str) -> Result<Signer, SignerError> {
match backend {
"memory" => Signer::from_memory("base58_key"),
"vault" => Signer::from_vault(/* ... */),
"kms" => Signer::from_aws_kms(/* ... */).await,
_ => Err(SignerError::ConfigError("Unknown backend".into())),
}
}
// Use it generically
let signer = get_signer("kms").await?;
let pubkey = signer.pubkey();

Signer hanya mengimplementasikan SolanaSigner. Akses kapabilitas melalui as_transaction_signer(), as_modifying_signer(), atau as_sending_signer(), yang mengembalikan None jika backend tidak memiliki bentuk tersebut:

if let Some(transaction_signer) = signer.as_transaction_signer() {
let result = transaction_signer.sign_transaction(&mut tx).await?;
}

Atau biarkan sign_and_send mengarahkan berdasarkan backend. Crate ini tidak memiliki klien RPC, jadi Anda yang menyediakan penyiaran; untuk backend pengirim, closure tidak pernah dipanggil:

let signature = signer
.sign_and_send(&mut tx, |encoded| async move { broadcast(encoded).await })
.await?;

Penanganan Error

SignerError::BroadcastUnconfirmed { provider_tx_id, idempotency_key, transaction_signature, .. } (dari Crossmint, Fordefi native auto, atau closure sign_and_send yang gagal) berarti transaksi mungkin sudah masuk. Jangan mencoba ulang secara membabi buta: rekonsiliasi provider_tx_id atau transaction_signature terlebih dahulu, atau kirim ulang hanya transaksi yang identik byte demi byte. match yang menyeluruh pada SignerError memerlukan arm ini. Lihat model keamanan untuk mengetahui apa yang dijamin oleh setiap bentuk penandatanganan.

Menambahkan Signer Kustom

Lihat panduan Menambahkan Signer untuk mengintegrasikan layanan manajemen kunci tambahan.

Is this page helpful?

© 2026 Yayasan Solana. Semua hak dilindungi.