التثبيت
أضف solana-keychain إلى 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 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 للمطورين |
crossmint | محافظ Crossmint المُدارة |
dfns | بنية تحتية لمحافظ Dfns |
openfort | محافظ Openfort المدمجة |
para | محافظ Para MPC |
utila | حضانة Utila MPC |
fordefi | حضانة Fordefi MPC |
ledger | محفظة Ledger الصلبة عبر USB-HID (لغة Rust فقط، اختياري، غير مشمول في all) |
all | تفعيل جميع الواجهات الخلفية باستثناء ledger |
sdk-v2 | حزمة تطوير سولانا SDK 2.x (الافتراضي) |
sdk-v3 | حزمة تطوير سولانا SDK 3.x |
sdk-v4 | حزمة تطوير سولانا SDK 4.x (مطلوبة لمعاملات الإصدار v1) |
unsafe-debug | يسجّل استجابات الأخطاء الكاملة من المزوّد؛ لا تفعّله أبدًا في بيئة الإنتاج |
يجب تفعيل واحد فقط من sdk-v2 وsdk-v3 وsdk-v4.
الاستخدام الأساسي
تنفّذ جميع أدوات التوقيع السمة الأساسية
SolanaSigner trait
(pubkey وsign_message وis_available). وتنفّذ كل واجهة خلفية أيضًا سمة قدرة واحدة
بالضبط:
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(())}
حوّل معاملة Transaction القديمة باستخدام .into(). تعمل المعاملات القديمة ومعاملات v0
مع كل ميزات SDK؛ أما معاملات v1 فتتطلب sdk-v4.
قدرات أداة التوقيع
| الواجهة الخلفية | سمة القدرة | sign_message |
|---|---|---|
| Crossmint | SendingSigner | غير مدعوم |
| Fordefi الأصلي التلقائي | SendingSigner | نعم |
| Fordefi الأصلي اليدوي | ModifyingSigner | نعم |
| Utila | TransactionSigner | غير مدعوم |
| CDP | TransactionSigner | حمولات UTF-8 فقط |
| Ledger | TransactionSigner | نعم، عبر غلاف خارج السلسلة |
| جميع الواجهات الأخرى (بما فيها Fordefi الصندوق الأسود) | TransactionSigner | نعم |
تقوم دوال الإنشاء Signer::from_* بتشغيل init() نيابةً عنك. إذا أنشأت أنواع أدوات التوقيع
Privy أو Fireblocks أو Dfns أو Crossmint أو Para أو Openfort أو Utila
مباشرةً، فاستدعِ init().await قبل الاستخدام.
تكوين الواجهة الخلفية
موقع الذاكرة
للتطوير والاختبار باستخدام أزواج المفاتيح المحلية:
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
للتوقيع السحابي الأصلي باستخدام مفاتيح 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
للتوقيع السحابي الأصلي باستخدام مفاتيح 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 للمطورين)
للتوقيع عبر المحفظة المُدارة من 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 حمولات UTF-8 فقط.
Crossmint
Crossmint للإرسال فقط: تنفّذ واجهته البرمجية كل معاملة معتمدة
على جانب الخادم، لذلك لا يوجد مسار للتوقيع فقط، وتفشل sign_message. استدعِ
sign_and_send_transaction، التي تترك معاملتك دون تعديل وتعيد
توقيع المعاملة التي تم تأكيدها فعليًا. وقد تختلف تلك المعاملة عن
معاملتك إذا كانت Crossmint ترعى رسوم الغاز.
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
للتوقيع عبر محفظة Para MPC:
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
للتوقيع عبر محفظة 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
للتوقيع عبر الحفظ المعتمد على MPC في Utila. إن 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
للتوقيع عبر الحفظ المعتمد على MPC في Fordefi. تتم مصادقة طلبات API باستخدام توقيع طلب ECDSA
P-256. قدّم واحدًا فقط من private_key_pem أو
request_signer (من النوع Arc<dyn FordefiRequestSigner>، ويُستخدم لإبقاء ذلك المفتاح في
KMS/HSM).
يأتي Fordefi في ثلاثة أنواع من أدوات التوقيع، تُحدَّد عند الإنشاء بواسطة chain و
push_mode:
chain | push_mode | النوع | القدرة | السلوك |
|---|---|---|---|---|
None | أي قيمة | FordefiBlackBoxSigner | TransactionSigner | يوقّع البايتات الخام؛ وتتولى أنت البث |
Some(..) | None أو Auto | FordefiNativeAutoSigner | SendingSigner | قد يعيد Fordefi كتابة blockhash والرسوم، ثم يوقّع ويبثّ |
Some(..) | Manual | FordefiNativeManualSigner | ModifyingSigner | يعيد Fordefi الكتابة ويوقّع؛ وتتولى أنت بث المعاملة المُعادة |
يستبدل الوضع اليدوي الأصلي معاملتك بالمعاملة التي وقّعها Fordefi. تابع العمل منها، وليس من المعاملة التي أنشأتها. ويجب أن يعمل قبل أي موقّع مطلوب آخر.
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،
وجهازًا مفتوح القفل يشغّل تطبيق سولانا، وعلى Linux قواعد udev الخاصة بـ Ledger.
لا يشمله التدقيق الحالي؛ راجع
حالة التدقيق.
use solana_keychain::{LedgerConfig, Signer};let signer = Signer::from_ledger(LedgerConfig {confirm_pubkey_on_device: true,..LedgerConfig::default()}).await?;
توقّع sign_message غلافًا خارج السلسلة يحيط بحمولتك، وليس البايتات الخام؛
أعد بناءه باستخدام solana_keychain::ledger::ledger_offchain_envelope للتحقق.
اضبط auto_open_app: false للاستخدام دون إشراف. وعند رفض الطلب على
الجهاز تُعيد الدالة SignerError::UserRejected.
تعداد الموقّع الموحد
استخدم تعداد Signer لاختيار الخلفيات في وقت التشغيل:
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 عندما لا تدعم الواجهة الخلفية ذلك النمط:
if let Some(transaction_signer) = signer.as_transaction_signer() {let result = transaction_signer.sign_transaction(&mut tx).await?;}
أو دع sign_and_send تختار المسار بحسب الواجهة الخلفية. لا تتضمن الحزمة عميل RPC، لذا
عليك توفير آلية البث؛ وفي الواجهة الخلفية المرسِلة لا يُستدعى الإغلاق (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 الأصلي التلقائي أو من إغلاق sign_and_send الفاشل)
تعني أن المعاملة ربما تم تأكيدها. لا تعد المحاولة بشكل أعمى: طابِق أولًا
provider_tx_id أو transaction_signature، أو أعد إرسال المعاملة المطابقة
بايتًا ببايت فقط. وتحتاج تعبيرات match الشاملة على SignerError إلى هذا الفرع.
راجع
نموذج الأمان
لمعرفة ما يضمنه كل نمط من أنماط التوقيع.
إضافة موقّعين مخصصين
راجع دليل إضافة الموقّعين لدمج خدمات إدارة المفاتيح الإضافية.
Is this page helpful?