Rust

Cài đặt

Thêm solana-keychain vào Cargo.toml của bạn với chỉ những backend bạn cần:

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"] }

Nâng cấp từ 1.x? Xem hướng dẫn Chuyển sang 2.0.

Cờ Tính năng

Tính năngMô tả
memoryKý keypair cục bộ (mặc định)
vaultHashiCorp Vault Transit engine
aws_kmsAWS KMS với Ed25519
gcp_kmsGCP Cloud KMS với Ed25519
privyVí nhúng Privy
turnkeyTurnkey API
fireblocksFireblocks MPC
cdpCoinbase Developer Platform
crossmintVí được quản lý bởi Crossmint
dfnsCơ sở hạ tầng ví Dfns
openfortVí nhúng Openfort
paraVí MPC Para
utilaLưu ký MPC Utila
fordefiLưu ký MPC Fordefi
ledgerVí cứng Ledger qua USB-HID (chỉ Rust, tùy chọn bật, không nằm trong all)
allBật mọi backend ngoại trừ ledger
sdk-v2Solana SDK 2.x (mặc định)
sdk-v3Solana SDK 3.x
sdk-v4Solana SDK 4.x (bắt buộc đối với giao dịch v1)
unsafe-debugGhi log toàn bộ phản hồi lỗi từ nhà cung cấp; không bao giờ bật trong môi trường production

Phải bật đúng một trong các tính năng sdk-v2, sdk-v3 và sdk-v4.

Cách sử dụng Cơ bản

Tất cả signer đều triển khai trait SolanaSigner cơ sở (pubkey, sign_message, is_available). Mỗi backend cũng triển khai đúng một trait khả năng:

  • TransactionSigner: ký giao dịch của bạn đúng như được cung cấp.
  • ModifyingSigner: nhà cung cấp viết lại giao dịch, sau đó ký.
  • SendingSigner: nhà cung cấp ký và phát sóng giao dịch.
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(())
}

Chuyển đổi Transaction legacy bằng .into(). Giao dịch legacy và v0 hoạt động trên mọi tính năng SDK; giao dịch v1 yêu cầu sdk-v4.

Khả năng của Signer

BackendTrait khả năngsign_message
CrossmintSendingSignerKhông được hỗ trợ
Fordefi native autoSendingSignerCó
Fordefi native manualModifyingSignerCó
UtilaTransactionSignerKhông được hỗ trợ
CDPTransactionSignerChỉ payload UTF-8
LedgerTransactionSignerCó, thông qua một envelope off-chain
Tất cả các backend còn lại (bao gồm Fordefi black box)TransactionSignerCó

Các hàm khởi tạo Signer::from_* sẽ tự chạy init() cho bạn. Nếu bạn tạo trực tiếp các kiểu signer Privy, Fireblocks, Dfns, Crossmint, Para, Openfort hoặc Utila, hãy gọi init().await trước khi sử dụng.

Cấu hình Backend

Memory Signer

Dành cho phát triển và thử nghiệm với keypair cục bộ:

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

Dành cho HSM tự lưu trữ với Transit engine:

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

Dành cho ký cloud-native với khóa 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

Dành cho ký ví nhúng:

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

Dành cho ký phi tập trung:

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

Để ký MPC cấp tổ chức:

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

Để ký native trên đám mây với khóa Ed25519 của 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)

Để ký ví được quản lý bởi 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 của CDP chỉ chấp nhận payload UTF-8.

Crossmint

Crossmint chỉ hỗ trợ gửi: API của Crossmint thực thi mọi giao dịch đã được phê duyệt trên phía máy chủ, vì vậy không có luồng chỉ ký, và sign_message sẽ thất bại. Hãy gọi sign_and_send_transaction; hàm này giữ nguyên giao dịch của bạn và trả về chữ ký của giao dịch đã được ghi nhận. Giao dịch đó có thể khác với giao dịch của bạn nếu Crossmint tài trợ phí 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

Để ký cơ sở hạ tầng ví 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

Để ký ví MPC của 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

Dành cho việc ký bằng ví backend của 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

Dành cho việc ký với lưu ký MPC Utila. sign_message không được hỗ trợ, và bạn tự phát sóng giao dịch đã ký.

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

Dành cho việc ký với lưu ký MPC Fordefi. Các yêu cầu API được xác thực bằng chữ ký yêu cầu ECDSA P-256. Hãy cung cấp đúng một trong hai: private_key_pem, hoặc request_signer (một Arc<dyn FordefiRequestSigner>, dùng để giữ khóa đó trong KMS/HSM).

Fordefi có ba kiểu signer, được cố định khi khởi tạo bởi chain và push_mode:

chainpush_modeKiểuKhả năngHành vi
Nonebất kỳFordefiBlackBoxSignerTransactionSignerKý trên byte thô; bạn tự phát sóng
Some(..)None hoặc AutoFordefiNativeAutoSignerSendingSignerFordefi có thể viết lại blockhash và phí, rồi ký và phát sóng
Some(..)ManualFordefiNativeManualSignerModifyingSignerFordefi viết lại và ký; bạn tự phát sóng giao dịch được trả về

Chế độ native manual thay thế giao dịch của bạn bằng giao dịch mà Fordefi đã ký. Hãy tiếp tục từ giao dịch đó, không bao giờ từ giao dịch bạn đã dựng. Chế độ này phải chạy trước mọi signer bắt buộc khác.

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

Dành cho việc ký bằng ví cứng qua USB-HID (chỉ Rust). Yêu cầu tính năng ledger, một thiết bị đã mở khóa đang chạy ứng dụng Solana và, trên Linux, các quy tắc udev của Ledger. Ledger không nằm trong phạm vi cuộc kiểm toán hiện tại; xem trạng thái kiểm toán.

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

sign_message ký một envelope off-chain bao quanh payload của bạn, chứ không phải byte thô; hãy dựng lại bằng solana_keychain::ledger::ledger_offchain_envelope để xác minh. Đặt auto_open_app: false khi dùng không cần giám sát. Nếu từ chối lời nhắc trên thiết bị, hàm sẽ trả về SignerError::UserRejected.

Enum Signer Thống Nhất

Sử dụng enum Signer để chọn backend tại 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 chỉ triển khai SolanaSigner. Hãy truy cập một khả năng thông qua as_transaction_signer(), as_modifying_signer() hoặc as_sending_signer(), các hàm này trả về None khi backend không có dạng đó:

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

Hoặc để sign_and_send tự định tuyến theo backend. Crate này không có RPC client, vì vậy bạn tự cung cấp phần phát sóng; với backend dạng sending, closure sẽ không bao giờ được gọi:

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

Xử lý lỗi

SignerError::BroadcastUnconfirmed { provider_tx_id, idempotency_key, transaction_signature, .. } (từ Crossmint, Fordefi native auto, hoặc một closure sign_and_send bị lỗi) nghĩa là giao dịch có thể đã được ghi nhận. Đừng thử lại một cách mù quáng: hãy đối soát provider_tx_id hoặc transaction_signature trước, hoặc chỉ gửi lại giao dịch giống hệt từng byte. Các match đầy đủ trên SignerError cần có nhánh này. Xem mô hình bảo mật để biết mỗi dạng ký đảm bảo những gì.

Thêm Signer Tùy Chỉnh

Xem hướng dẫn Thêm Signer để tích hợp các dịch vụ quản lý khóa bổ sung.

Is this page helpful?