インストール
必要なバックエンドのみを使用して、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 Developer Platform |
crossmint | Crossmintの管理ウォレット |
dfns | Dfnsウォレットインフラストラクチャ |
openfort | Openfortの組み込みウォレット |
para | Para MPCウォレット |
utila | Utila MPCカストディ |
fordefi | Fordefi MPCカストディ |
ledger | USB-HID経由のLedgerハードウェアウォレット(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のうち、必ずいずれか1つだけを有効にしてください。
基本的な使い方
すべてのシグナーは、基本の
SolanaSignerトレイト
(pubkey、sign_message、is_available)を実装しています。さらに、各バックエンドはケイパビリティトレイトをちょうど1つ実装しています。
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を呼び出してください。
バックエンド設定
メモリ署名者
ローカル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
Transitエンジンを使用したセルフホストHSM用:
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
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})?;
CDPのsign_messageは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
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
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内に保持するために使用)のいずれか1つだけを指定してください。
Fordefiには3種類のシグナー型があり、構築時にchainとpush_modeによって決まります。
chain | push_mode | 型 | ケイパビリティ | 動作 |
|---|---|---|---|---|
None | 任意 | FordefiBlackBoxSigner | TransactionSigner | 生のバイト列に署名します。ブロードキャストはご自身で行います |
Some(..) | NoneまたはAuto | FordefiNativeAutoSigner | SendingSigner | Fordefiがブロックハッシュと手数料を書き換える場合があり、署名してブロードキャストします |
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フィーチャー、Solanaアプリを実行中のロック解除済みデバイスが必要で、Linuxではさら LedgerのudevルールもPre必要です。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クライアントがないため、ブロードキャスト処理はご自身で用意する必要があります。送信型バックエンドの場合、クロージャは呼び出されません。
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を照合するか、バイト単位で同一のトランザクションのみを再送してください。SignerErrorに対する網羅的なmatchには、このアームが必要です。各署名形態が保証する内容については、
セキュリティモデル
をご覧ください。
カスタム署名者の追加
追加の鍵管理サービスを統合するには、署名者の追加ガイドを参照してください。
Is this page helpful?