Встановлення
Додайте 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 engine |
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 | MPC-гаманці Para |
utila | MPC-кастодія Utila |
fordefi | Зберігання MPC від Fordefi |
ledger | Апаратний гаманець Ledger через USB-HID (лише Rust, за бажанням, не входить до all) |
all | Увімкнути всі бекенди, крім 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.
Базове використання
Усі підписувачі реалізують базовий
трейт SolanaSigner
(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 native auto | SendingSigner | Так |
| Fordefi native manual | ModifyingSigner | Так |
| Utila | TransactionSigner | Не підтримується |
| CDP | TransactionSigner | Лише дані в UTF-8 |
| Ledger | TransactionSigner | Так, через off-chain-конверт |
| Усі інші (зокрема Fordefi black box) | TransactionSigner | Так |
Конструктори Signer::from_* самі викликають init(). Якщо ви створюєте
типи підписувачів Privy, Fireblocks, Dfns, Crossmint, Para, Openfort або Utila
безпосередньо, викличте init().await перед використанням.
Налаштування бекенду
Підписувач в пам'яті
Для розробки та тестування з локальними keypair:
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 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 приймає лише дані в UTF-8.
Crossmint
Crossmint працює лише на відправлення: його API виконує кожну схвалену транзакцію
на стороні сервера, тому шляху лише з підписанням немає, а 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
Для підписання з гаманцем 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
Для підписання через бекенд-гаманець 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 змінює та підписує; ви транслюєте повернуту транзакцію |
Режим native manual замінює вашу транзакцію на ту, яку підписав 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,
розблокований пристрій із застосунком 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-конверт, що обгортає ваші дані, а не сирі
байти; для перевірки відтворіть його за допомогою 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-клієнта, тому
трансляцію надаєте ви; для бекенду з відправленням замикання ніколи не викликається:
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 або замикання sign_and_send, що завершилося помилкою)
означає, що транзакція, можливо, потрапила в блокчейн. Не повторюйте спробу навмання: спершу звірте
provider_tx_id або transaction_signature, або повторно надішліть лише
побайтово ідентичну транзакцію. Вичерпні match за SignerError мають містити цю гілку.
Про те, що гарантує кожна форма підписання, див.
модель безпеки.
Додавання власних підписувачів
Перегляньте посібник з додавання підписувачів для інтеграції додаткових сервісів керування ключами.
Is this page helpful?