Εγκατάσταση
Προσθέστε το solana-keychain στο Cargo.toml σας με μόνο τα backends που
χρειάζεστε:
[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 linesolana-keychain = { version = "2.0", default-features = false, features = ["all", "sdk-v4"] }
Αναβαθμίζετε από την 1.x; Δείτε τον οδηγό μετάβασης στην 2.0.
Σημαίες Χαρακτηριστικών
| Χαρακτηριστικό | Περιγραφή |
|---|---|
memory | Τοπική υπογραφή keypair (προεπιλογή) |
vault | Μηχανή HashiCorp Vault Transit |
aws_kms | AWS KMS με Ed25519 |
gcp_kms | GCP Cloud KMS με Ed25519 |
privy | Ενσωματωμένα πορτοφόλια Privy |
turnkey | Turnkey API |
fireblocks | Fireblocks MPC |
cdp | Coinbase 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-v2 | Solana SDK 2.x (προεπιλογή) |
sdk-v3 | Solana SDK 3.x |
sdk-v4 | Solana 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 keylet 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 Partiallet 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
| Backend | Trait δυνατοτήτων | sign_message |
|---|---|---|
| Crossmint | SendingSigner | Δεν υποστηρίζεται |
| Fordefi native auto | SendingSigner | Ναι |
| Fordefi native manual | ModifyingSigner | Ναι |
| Utila | TransactionSigner | Δεν υποστηρίζεται |
| CDP | TransactionSigner | Μόνο payloads UTF-8 |
| Ledger | TransactionSigner | Ναι, μέσω 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 keylet signer = Signer::from_memory("base58_private_key")?;// From JSON keypair file pathlet signer = Signer::from_memory_file("/path/to/keypair.json")?;// From byte array stringlet 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 keyNone, // 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 keySome("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 IDNone, // 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 keyNone, // 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 devnetapi_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 IDapi_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 addressnetwork: Some(CDP_NETWORK_MAINNET.to_string()), // Required to sign transactions with address lookup tablesapi_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 IDNone, // 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:
chain | push_mode | Τύπος | Δυνατότητα | Συμπεριφορά |
|---|---|---|---|---|
None | οποιοδήποτε | FordefiBlackBoxSigner | TransactionSigner | Υπογράφει ακατέργαστα bytes· εσείς αναμεταδίδετε |
Some(..) | None ή Auto | FordefiNativeAutoSigner | SendingSigner | Το Fordefi μπορεί να τροποποιήσει το blockhash και τα τέλη, υπογράφει και αναμεταδίδει |
Some(..) | Manual | FordefiNativeManualSigner | ModifyingSigner | Το 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 addresschain: Some(SolanaChainUniqueId::SolanaDevnet), // None for black box modefee: Some(FordefiSolanaFee::Priority {priority_level: FordefiPriorityLevel::Medium,}),push_mode: Some(FordefiPushMode::Auto), // Manual: sign without broadcastingapi_base_url: None, // Default: https://api.fordefi.compoll_interval_ms: None, // Default: 2000max_poll_attempts: None, // Default: 50http_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 genericallylet 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?