Rust

Εγκατάσταση

Προσθέστε το solana-keychain στο Cargo.toml σας με μόνο τα backends που χρειάζεστε:

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

Αναβαθμίζετε από την 1.x; Δείτε τον οδηγό μετάβασης στην 2.0.

Σημαίες Χαρακτηριστικών

ΧαρακτηριστικόΠεριγραφή
memoryΤοπική υπογραφή keypair (προεπιλογή)
vaultΜηχανή HashiCorp Vault Transit
aws_kmsAWS KMS με Ed25519
gcp_kmsGCP Cloud KMS με Ed25519
privyΕνσωματωμένα πορτοφόλια Privy
turnkeyTurnkey API
fireblocksFireblocks MPC
cdpCoinbase Developer Platform
crossmintΔιαχειριζόμενα πορτοφόλια Crossmint
dfnsΥποδομή πορτοφολιών Dfns
openfortΕνσωματωμένα πορτοφόλια Openfort
paraΠορτοφόλια Para MPC
utilaΦύλαξη Utila MPC
fordefiΘεματοφυλακή Fordefi MPC
ledgerΦορητό πορτοφόλι Ledger μέσω USB-HID (μόνο Rust, προαιρετικό, δεν περιλαμβάνεται στο all)
allΕνεργοποίηση όλων των backend εκτός από το ledger
sdk-v2Solana SDK 2.x (προεπιλογή)
sdk-v3Solana SDK 3.x
sdk-v4Solana SDK 4.x (απαιτείται για συναλλαγές v1)
unsafe-debugΚαταγράφει πλήρεις αποκρίσεις σφαλμάτων του παρόχου· μην το ενεργοποιείτε ποτέ στο περιβάλλον παραγωγής

Πρέπει να είναι ενεργοποιημένο ακριβώς ένα από τα sdk-v2, sdk-v3 και sdk-v4.

Βασική Χρήση

Όλοι οι signers υλοποιούν το βασικό trait SolanaSigner (pubkey, sign_message, is_available). Κάθε backend υλοποιεί επίσης ακριβώς ένα trait δυνατοτήτων:

  • TransactionSigner: υπογράφει τη συναλλαγή σας όπως έχει.
  • ModifyingSigner: ο πάροχος τροποποιεί τη συναλλαγή και στη συνέχεια την υπογράφει.
  • SendingSigner: ο πάροχος την υπογράφει και την αναμεταδίδει.
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(())
}

Μετατρέψτε μια legacy Transaction με .into(). Οι legacy και οι v0 συναλλαγές λειτουργούν με κάθε λειτουργία SDK· οι συναλλαγές v1 απαιτούν το sdk-v4.

Δυνατότητες Signer

BackendTrait δυνατοτήτωνsign_message
CrossmintSendingSignerΔεν υποστηρίζεται
Fordefi native autoSendingSignerΝαι
Fordefi native manualModifyingSignerΝαι
UtilaTransactionSignerΔεν υποστηρίζεται
CDPTransactionSignerΜόνο payloads UTF-8
LedgerTransactionSignerΝαι, μέσω off-chain envelope
Όλα τα υπόλοιπα (συμπ. Fordefi black box)TransactionSignerΝαι

Οι κατασκευαστές Signer::from_* εκτελούν αυτόματα το init(). Αν δημιουργήσετε απευθείας τους τύπους signer Privy, Fireblocks, Dfns, Crossmint, Para, Openfort ή Utila, καλέστε init().await πριν από τη χρήση.

Διαμόρφωση Backend

Memory Signer

Για ανάπτυξη και δοκιμή με τοπικά keypairs:

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

Για αυτο-φιλοξενούμενο HSM με μηχανή 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

Για υπογραφή βασισμένη σε cloud με κλειδιά AWS KMS Ed25519:

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

Για υπογραφή με ενσωματωμένο πορτοφόλι:

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

Για μη-κηδεμονική υπογραφή:

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

Για θεσμική υπογραφή MPC:

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

Για cloud-native υπογραφή με κλειδιά GCP Cloud KMS Ed25519:

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)

Για υπογραφή με διαχειριζόμενο πορτοφόλι 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 δέχεται μόνο payloads UTF-8.

Crossmint

Το Crossmint υποστηρίζει μόνο αποστολή: το API του εκτελεί κάθε εγκεκριμένη συναλλαγή στην πλευρά του διακομιστή, επομένως δεν υπάρχει διαδρομή μόνο υπογραφής και το sign_message αποτυγχάνει. Καλέστε το sign_and_send_transaction, το οποίο αφήνει τη συναλλαγή σας ανέγγιχτη και επιστρέφει την υπογραφή της συναλλαγής που καταχωρίστηκε. Η συναλλαγή αυτή μπορεί να διαφέρει από τη δική σας αν το Crossmint επιδοτεί το 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

Για υπογραφή με υποδομή πορτοφολιού 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

Για υπογραφή με πορτοφόλι 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

Για υπογραφή με 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

Για υπογραφή με φύλαξη Utila MPC. Το sign_message δεν υποστηρίζεται και εσείς αναμεταδίδετε την υπογεγραμμένη συναλλαγή.

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

Για υπογραφή με φύλαξη Fordefi MPC. Τα αιτήματα API ταυτοποιούνται με υπογραφή αιτήματος ECDSA P-256. Δώστε ακριβώς ένα από τα private_key_pem ή request_signer (ένα Arc<dyn FordefiRequestSigner>, που χρησιμοποιείται για να παραμένει το κλειδί αυτό σε KMS/HSM).

Το Fordefi διατίθεται σε τρεις τύπους signer, που καθορίζονται κατά την κατασκευή από τα chain και push_mode:

chainpush_modeΤύποςΔυνατότηταΣυμπεριφορά
NoneοποιοδήποτεFordefiBlackBoxSignerTransactionSignerΥπογράφει ακατέργαστα bytes· εσείς αναμεταδίδετε
Some(..)None ή AutoFordefiNativeAutoSignerSendingSignerΤο Fordefi μπορεί να τροποποιήσει το blockhash και τα τέλη, υπογράφει και αναμεταδίδει
Some(..)ManualFordefiNativeManualSignerModifyingSignerΤο Fordefi τροποποιεί και υπογράφει· εσείς αναμεταδίδετε την επιστρεφόμενη συναλλαγή

Η native manual λειτουργία αντικαθιστά τη συναλλαγή σας με αυτήν που υπέγραψε το Fordefi. Συνεχίστε από αυτήν, ποτέ από αυτήν που δημιουργήσατε εσείς. Πρέπει να εκτελεστεί πριν από οποιονδήποτε άλλον απαιτούμενο signer.

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

Για υπογραφή με φορητό πορτοφόλι μέσω USB-HID (μόνο Rust). Απαιτεί τη λειτουργία ledger, μια ξεκλείδωτη συσκευή με την εφαρμογή Solana και, σε Linux, τους κανόνες udev της Ledger. Η Ledger δεν καλύπτεται από τον τρέχοντα έλεγχο· δείτε την κατάσταση ελέγχου.

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

Το sign_message υπογράφει ένα off-chain envelope που περιβάλλει το payload σας, όχι τα ακατέργαστα bytes· ανακατασκευάστε το με το solana_keychain::ledger::ledger_offchain_envelope για επαλήθευση. Ορίστε auto_open_app: false για χρήση χωρίς επιτήρηση. Μια προτροπή που απορρίφθηκε στη συσκευή επιστρέφει SignerError::UserRejected.

Ενοποιημένο Enum Υπογραφέα

Χρησιμοποιήστε το enum Signer για να επιλέξετε backends κατά το 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 υλοποιεί μόνο το SolanaSigner. Αποκτήστε πρόσβαση σε μια δυνατότητα μέσω as_transaction_signer(), as_modifying_signer() ή as_sending_signer(), τα οποία επιστρέφουν None όταν το backend δεν διαθέτει αυτή τη μορφή:

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

Ή αφήστε το sign_and_send να δρομολογήσει ανάλογα με το backend. Το crate δεν διαθέτει RPC client, οπότε εσείς παρέχετε την αναμετάδοση· για backend αποστολής το closure δεν καλείται ποτέ:

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

Διαχείριση Σφαλμάτων

Το SignerError::BroadcastUnconfirmed { provider_tx_id, idempotency_key, transaction_signature, .. } (από το Crossmint, το Fordefi native auto ή ένα αποτυχημένο closure του sign_and_send) σημαίνει ότι η συναλλαγή μπορεί να έχει καταχωριστεί. Μην επαναλάβετε τυφλά την απόπειρα: συμφωνήστε πρώτα το provider_tx_id ή το transaction_signature, ή στείλτε ξανά μόνο την πανομοιότυπη, byte προς byte, συναλλαγή. Οι εξαντλητικές εκφράσεις match για το SignerError χρειάζονται αυτόν τον κλάδο. Δείτε το μοντέλο ασφάλειας για το τι εγγυάται κάθε μορφή υπογραφής.

Προσθήκη Προσαρμοσμένων Υπογραφέων

Δείτε τον οδηγό Προσθήκης Υπογραφέων για να ενσωματώσετε πρόσθετες υπηρεσίες διαχείρισης κλειδιών.

Is this page helpful?

© 2026 Ίδρυμα Solana. Με επιφύλαξη παντός δικαιώματος.