Sürüm 2.0, Python paketinin ilk kararlı sürümüdür. 2.0 geçiş kılavuzu, Rust ve TypeScript ile ortak olan imzalama yapılarını kapsar.
Kurulum
Temel paketi ve sağlayıcı bağımlılığı gerektiren her backend için bir ek paketi yükleyin:
pip install solana-keychain # memory, vault and parapip install 'solana-keychain[aws-kms]' # AWS KMS (boto3)pip install 'solana-keychain[gcp-kms]' # GCP KMS (google-cloud-kms)pip install 'solana-keychain[privy]' # Privypip install 'solana-keychain[turnkey]' # Turnkeypip install 'solana-keychain[fireblocks]' # Fireblockspip install 'solana-keychain[cdp]' # Coinbase Developer Platformpip install 'solana-keychain[crossmint]' # Crossmintpip install 'solana-keychain[dfns]' # Dfnspip install 'solana-keychain[openfort]' # Openfortpip install 'solana-keychain[utila]' # Utilapip install 'solana-keychain[fordefi]' # Fordefi# Several at oncepip install 'solana-keychain[aws-kms,privy]'
Python 3.10 veya üzeri gerekir. İşlemler,
solders VersionedTransaction nesneleridir;
legacy, v0 ve v1 mesajlarının tümü kabul edilir, ancak use_program_call=True
ile kullanılan Fireblocks yalnızca legacy ve v0 kabul eder.
Memory, Vault ve Para paket kökünden içe aktarılabilir. Diğer tüm backend'ler
kendi alt modülünden içe aktarılır (örneğin solana_keychain.aws_kms) ve ek
paketi olmadan içe aktarıldığında, yüklenmesi gereken ek paketin adını belirten
bir ImportError hatası verir. Ledger yalnızca Rust'ta bulunur.
Temel Kullanım
Her backend'in bir yapılandırma dataclass'ı ve kullanıma hazır bir signer döndüren
asenkron bir create_<backend>_signer factory'si vardır. Tüm imzalama
metotları coroutine'dir:
import asynciofrom solana_keychain import MemorySignerfrom solders.transaction import VersionedTransactionasync def sign(transaction: VersionedTransaction) -> str:signer = MemorySigner.from_private_key_file("/path/to/id.json")print("Signing with:", signer.pubkey)# Check availability (useful for remote signers)if not await signer.is_available():raise RuntimeError("Signer offline")result = await signer.sign_transaction(transaction)print("Signature:", result.signature)print("Fully signed:", result.is_complete)return result.encoded_transaction # base64 wire transaction
sign_transaction, encoded_transaction, signature, is_complete ve
transaction alanlarını içeren bir SignedTransaction döndürür. transaction,
yetkili imzalı işlemdir: özellikle sonucu sizin ilettiğinizden farklı bir nesne
olan değiştirici (modifying) bir signer kullanırken işleme bu nesneden devam edin.
Birleşik Factory
create_keychain_signer bir backend adı ve o backend'in yapılandırma
dataclass'ını alır, backend'i tembel (lazy) biçimde içe aktarır; bu sayede
yalnızca kullandığınız ek paketlerin yüklenmesi yeterlidir:
from solana_keychain import create_keychain_signerfrom solana_keychain.privy import PrivySignerConfigsigner = await create_keychain_signer("privy",PrivySignerConfig(app_id="your-app-id",app_secret="your-app-secret",wallet_id="your-wallet-id",),)
Adlar SUPPORTED_BACKENDS içinde listelenir: aws-kms, cdp, crossmint,
dfns, fireblocks, fordefi, gcp-kms, memory, openfort, para,
privy, turnkey, utila ve vault. Bilinmeyen bir ad veya yanlış sınıfa ait
bir yapılandırma, SignerErrorCode.CONFIG_ERROR ile SignerError hatası verir.
Factory'nin dönüş tipi temel SolanaSigner olarak belirtilmiştir; bu nedenle
imzalamadan önce isinstance ile daraltın (bkz. Signer Yetenekleri).
Uzak HTTP İstemcileri
Uzak HTTP backend'leri, özel TLS veya proxy kullanımı için isteğe bağlı bir
http_client (bir httpx.AsyncClient) kabul eder. Ayarlanmadığında her istek,
60 saniyelik zaman aşımına sahip, tek kullanımlık bir istemci kullanır; temel URL
için HTTPS zorunludur ve yönlendirmeler reddedilir.
Signer Yetenekleri
Her backend, SolanaSigner ABC'sinin (pubkey, sign_message,
is_available) alt sınıfıdır ve ayrıca tam olarak bir yetenek sınıfı içerir:
TransactionSigner:sign_transaction(tx)işleminizi yerinde imzalar ve birSignedTransactiondöndürür. Yayınlamayı siz yaparsınız.ModifyingSigner:modify_and_sign_transaction(tx)sağlayıcının işlemi yeniden yazmasına izin verir, ardından yayınlamadan imzalar. Nesneniz değiştirilmez; döndürülenSignedTransaction.transactionüzerinden devam edin.SendingSigner:sign_and_send_transaction(tx)sağlayıcı üzerinden imzalar ve yayınlar, zincire giren işleminSignaturedeğerini döndürür. İşleminiz hiçbir zaman değiştirilmez.
| Backend | Yetenek sınıfı | sign_message |
|---|---|---|
| memory, vault, privy, turnkey, aws-kms, fireblocks, gcp-kms, dfns, para, openfort | TransactionSigner | Evet |
| cdp | TransactionSigner | Yalnızca UTF-8 yükleri, aksi halde SERIALIZATION_ERROR |
| utila | TransactionSigner | SIGNING_FAILED hatası verir |
fordefi kara kutu (FordefiBlackBoxSigner) | TransactionSigner | Evet |
fordefi yerel manuel (FordefiNativeManualSigner) | ModifyingSigner | Evet |
fordefi yerel otomatik (FordefiNativeAutoSigner) | SendingSigner | Evet |
| crossmint | SendingSigner | SIGNING_FAILED hatası verir |
isinstance ile daraltın. Tüm yetenek sınıfları paket kökünden dışa aktarılır:
from solana_keychain import ModifyingSigner, SendingSigner, TransactionSignerif isinstance(signer, SendingSigner):signature = await signer.sign_and_send_transaction(transaction)elif isinstance(signer, ModifyingSigner):result = await signer.modify_and_sign_transaction(transaction)elif isinstance(signer, TransactionSigner):result = await signer.sign_transaction(transaction)
Başlatma
create_* factory'leri ve create_keychain_signer, gerekli kurulumu sizin için
yapar. Privy, Fireblocks, Dfns, Crossmint, Para, Openfort veya Utila signer
sınıfını doğrudan oluşturursanız, kullanmadan önce await signer.init() çağırın.
O zamana kadar pubkey ve tüm imzalama çağrıları SignerErrorCode.NOT_INITIALIZED
hatası verir.
Backend Yapılandırması
Memory
Bir Solana CLI keypair dosyasından, bir base58 veya "[1,2,...]" dizesinden, ham
baytlardan ya da bir solders Keypair nesnesinden oluşturun:
from solana_keychain import MemorySigner, MemorySignerConfig, create_memory_signerfrom solders.keypair import Keypairsigner = MemorySigner.from_private_key_file("/path/to/id.json")signer = MemorySigner.from_private_key_string("base58_private_key")signer = MemorySigner.from_bytes(secret_key_bytes) # 64 or 32 bytessigner = await create_memory_signer(MemorySignerConfig(keypair=Keypair()))
Anahtar işlem belleğinde durur ve Python bunu sıfırlayamaz. Bu backend'i geliştirme ve test için kullanın.
HashiCorp Vault
Anahtar, transit motorunda bir ed25519 anahtarı olmalıdır. Düz HTTP yalnızca
vault server -dev için kullanılan bir loopback adresinde kabul edilir:
from solana_keychain import VaultSignerConfig, create_vault_signersigner = await create_vault_signer(VaultSignerConfig(api_base_url="https://vault.example.com:8200",token="hvs.xxxxx",key_name="my-solana-key",public_key="base58_public_key",))
AWS KMS
key_id, bir ECC_NIST_EDWARDS25519 anahtarı için anahtar kimliği, ARN veya
takma addır. Özel kimlik bilgileri veya uç noktalar için önceden oluşturulmuş bir
boto3 KMS client iletin; bu durumda region yok sayılır:
from solana_keychain.aws_kms import AwsKmsSignerConfig, create_aws_kms_signersigner = await create_aws_kms_signer(AwsKmsSignerConfig(key_id="alias/my-solana-key",public_key="base58_public_key",region="us-east-1", # optional, defaults to the AWS config chain))
GCP KMS
Anahtar sürümü bir EC_SIGN_ED25519 anahtarı olmalıdır. client isteğe bağlı
olarak önceden oluşturulmuş bir KeyManagementServiceAsyncClient alır:
from solana_keychain.gcp_kms import GcpKmsSignerConfig, create_gcp_kms_signersigner = await create_gcp_kms_signer(GcpKmsSignerConfig(key_name="projects/my-project/locations/us-east1/keyRings/my-ring/cryptoKeys/my-key/cryptoKeyVersions/1",public_key="base58_public_key",))
Privy
from solana_keychain.privy import PrivySignerConfig, create_privy_signersigner = await create_privy_signer(PrivySignerConfig(app_id="app_id",app_secret="app_secret",wallet_id="wallet_id",))
Bir yetkilendirme anahtarıyla korunan cüzdanlar, authorization_context olarak bir
PrivyAuthorizationConfig alır.
Turnkey
from solana_keychain.turnkey import TurnkeySignerConfig, create_turnkey_signersigner = await create_turnkey_signer(TurnkeySignerConfig(api_public_key="api_public_key", # hex P-256api_private_key="api_private_key", # hex P-256organization_id="org_id",private_key_id="private_key_id",public_key="base58_public_key",))
Fireblocks
from solana_keychain.fireblocks import FireblocksSignerConfig, create_fireblocks_signersigner = await create_fireblocks_signer(FireblocksSignerConfig(api_key="api_key",private_key_pem="-----BEGIN RSA PRIVATE KEY-----\n...",vault_account_id="0",asset_id="SOL", # or "SOL_TEST" for devnet))
use_program_call=True, RAW yerine PROGRAM_CALL işlemiyle imzalar. Yalnızca
imzalama olarak gönderilir; dolayısıyla Fireblocks işlemi ne yeniden yazar ne de
yayınlar ve yayınlamayı her zamanki gibi siz yaparsınız. Bir hot wallet gerektirir
ve çalışma alanınız için Fireblocks tarafından etkinleştirilmiş olmalıdır.
CDP (Coinbase Developer Platform)
from solana_keychain.cdp import CdpSignerConfig, create_cdp_signersigner = await create_cdp_signer(CdpSignerConfig(api_key_id="api_key_id",api_key_secret="api_key_secret",wallet_secret="wallet_secret",address="base58_address",network="solana", # or "solana-devnet"; required for address lookup tables))
Crossmint
from solana_keychain.crossmint import CrossmintSignerConfig, create_crossmint_signersigner = await create_crossmint_signer(CrossmintSignerConfig(api_key="api_key",wallet_locator="wallet_locator",))signature = await signer.sign_and_send_transaction(transaction)
Crossmint yalnızca gönderim yapar. API'si onaylanmış bir işlemi her zaman
sunucu tarafında yürütür ve gas ücretini karşılar; bu nedenle CrossmintSigner
bir SendingSigner'dır ve sign_message SIGNING_FAILED hatası verir. Döndürülen
imza, Crossmint'in zincire işlediği işlemi tanımlar; bu işlem sizin işleminizden
farklı olabilir. signer_secret (bir xmsk1_... delege edilmiş signer gizli
anahtarı) ayarlandığında işlemler otomatik olarak onaylanır; bu da neyin
onaylanacağı kararını Crossmint'e devreder.
Dfns
from solana_keychain.dfns import DfnsSignerConfig, create_dfns_signersigner = await create_dfns_signer(DfnsSignerConfig(auth_token="auth_token",cred_id="cred_id",private_key_pem="-----BEGIN EC PRIVATE KEY-----\n...",wallet_id="wallet_id",))
Openfort
from solana_keychain.openfort import OpenfortSignerConfig, create_openfort_signersigner = await create_openfort_signer(OpenfortSignerConfig(secret_key="sk_...",account_id="acc_...",wallet_secret="wallet_secret",))
Para
from solana_keychain import ParaSignerConfig, create_para_signersigner = await create_para_signer(ParaSignerConfig(api_key="sk_...",wallet_id="wallet_uuid",))
Utila
Utila yalnızca işlemleri imzalar; sign_message SIGNING_FAILED hatası verir.
from solana_keychain.utila import UtilaSignerConfig, create_utila_signersigner = await create_utila_signer(UtilaSignerConfig(service_account_email="sa@example.com",service_account_private_key_pem="-----BEGIN PRIVATE KEY-----\n...",vault_id="vault_id",wallet_id="wallet_id",network="networks/solana-devnet",))
Fordefi
Fordefi'nin üç imzalama modu vardır; bunlar oluşturma sırasında chain ve
push_mode ile belirlenir. create_fordefi_signer sınıfı seçer, her sınıf başka
bir mod için hazırlanmış yapılandırmayı reddeder ve üçü de mesajları imzalar:
| Mod | Yapılandırma | Sınıf | Metot |
|---|---|---|---|
| Kara kutu | chain ayarlanmamış | FordefiBlackBoxSigner | sign_transaction |
| Yerel otomatik | chain ayarlı, push_mode ayarlanmamış veya "auto" | FordefiNativeAutoSigner | sign_and_send_transaction |
| Yerel manuel | chain ayarlı, push_mode="manual" | FordefiNativeManualSigner | modify_and_sign_transaction |
API istekleri bir ECDSA P-256 istek imzasıyla doğrulanır: anahtarı
private_key_pem olarak sağlayın ya da request_signer olarak bir
FordefiRequestSigner alt sınıfı ileterek anahtarı bir KMS/HSM içinde tutun.
Yerel otomatik mod: chain değerini ("solana_devnet" veya
"solana_mainnet") ayarlayın; Fordefi blockhash'i ve ücretleri değiştirebilir,
ardından işlemi kendisi imzalar ve yayınlar. Yalnızca gerekli tek imzalayanın
vault olduğu imzasız bir işlemi kabul eder. fee Fordefi'ye olduğu gibi iletilir:
import osfrom solana_keychain.fordefi import FordefiSignerConfig, create_fordefi_signersigner = await create_fordefi_signer(FordefiSignerConfig(access_token=os.environ["FORDEFI_ACCESS_TOKEN"],vault_id=os.environ["FORDEFI_VAULT_ID"],public_key=os.environ["FORDEFI_PUBLIC_KEY"], # vault address (base58)private_key_pem=open("./secret/private.pem").read(),chain="solana_devnet",fee={"type": "custom", "priority_fee": "1000"}, # optional))signature = await signer.sign_and_send_transaction(transaction)
Yerel manuel mod: chain değerini ayarlayın ve push_mode="manual" kullanın.
Fordefi mesajı yeniden yazar (güncel blockhash, Compute Budget ücret talimatları)
ve imzalar, ancak yayınlamaz. Döndürülen işlem, gönderdiğiniz işlemin yerini alır;
bu yüzden her zaman result.transaction üzerinden devam edin. Fordefi ücret
ödeyen olmalı ve gerekli diğer imzalayanlardan önce imzalamalıdır: zaten imza
taşıyan bir işlem kabul edilir, ancak yeniden yazma bu imzaları geçersiz kılar.
Yeniden yazmanın farkı (diff) çıkarılmaz; bu yüzden yayınlamadan önce sonucu
inceleyin ve gecikmeden yayınlayın, çünkü Fordefi yeni blockhash'in geçerlilik
sona erme yüksekliğini döndürmez.
signer = await create_fordefi_signer(FordefiSignerConfig(access_token=os.environ["FORDEFI_ACCESS_TOKEN"],vault_id=os.environ["FORDEFI_VAULT_ID"],public_key=os.environ["FORDEFI_PUBLIC_KEY"],private_key_pem=open("./secret/private.pem").read(),chain="solana_devnet",push_mode="manual",))result = await signer.modify_and_sign_transaction(transaction)... # inspect result.transaction, then add any remaining signatures
İncelenen işlemi İmzala ve Gönder bölümündeki gibi yayınlayın; gönderim başarısız olursa yeniden denemeden önce durumu mutabakata bağlayın.
Kara kutu modu: chain değerini atlayın. Fordefi mesajınızın tam bayt
dizisini imzalar ve yayınlamaz. Bunu bir Fordefi kara kutu vault ile kullanın.
signer = await create_fordefi_signer(FordefiSignerConfig(access_token=os.environ["FORDEFI_ACCESS_TOKEN"],vault_id=os.environ["FORDEFI_BB_VAULT_ID"],public_key=os.environ["FORDEFI_BB_PUBLIC_KEY"],private_key_pem=open("./secret/private.pem").read(),))
İmzala ve Gönder
sign_and_send_transaction, signer'ın yapısı ne olursa olsun bir işlemi zincire
ulaştırır. Bir SendingSigner sağlayıcısı üzerinden yayınlar ve gönderim
fonksiyonunuz hiçbir zaman çağrılmaz. Bir TransactionSigner veya
ModifyingSigner imzalar ve base64 kodlu sonucu gönderim fonksiyonunuz yayınlar
(paketin RPC istemcisi yoktur):
import httpxfrom solana_keychain import sign_and_send_transactionfrom solders.signature import Signatureasync def send(encoded: str) -> Signature:async with httpx.AsyncClient() as client:response = await client.post("https://api.devnet.solana.com",json={"jsonrpc": "2.0","id": 1,"method": "sendTransaction","params": [encoded, {"encoding": "base64"}],},)return Signature.from_string(response.json()["result"])signature = await sign_and_send_transaction(signer, transaction, send)
Gönderim fonksiyonu olmayan, yalnızca imzalama yapan bir signer CONFIG_ERROR
hatası verir; imzalamadan sonra hâlâ imzası eksik olan bir işlem ise
SIGNING_FAILED hatası verir.
Hata Yönetimi
Her hata, SignerErrorCode içinden sabit bir code değerine sahip bir
SignerError'dır: BROADCAST_UNCONFIRMED, CONFIG_ERROR,
EXPECTED_SOLANA_SIGNER, HTTP_ERROR, INVALID_PRIVATE_KEY,
INVALID_PUBLIC_KEY, IO_ERROR, NOT_AVAILABLE, NOT_INITIALIZED, OTHER,
PARSING_ERROR, REMOTE_API_ERROR, SERIALIZATION_ERROR ve SIGNING_FAILED.
Mesaja değil code değerine göre eşleştirin: str() ve repr() yalnızca sabit,
genel bir mesaj taşır; anahtar materyalini veya ham sağlayıcı yanıtlarını asla
içermez. status_code ve provider_error_code, hata bir sağlayıcı yanıtından
kaynaklandığında ayarlanır.
SignerErrorCode.BROADCAST_UNCONFIRMED ("SIGNER_BROADCAST_UNCONFIRMED"),
işlemin zincire girmiş olabileceği anlamına gelir:
- Crossmint ve Fordefi yerel otomatik modda, oluşturma isteği kabul edildiğinde
provider_transaction_idayarlanır veidempotency_key, oluşturma isteğinin gönderildiği mesajdan türetilen anahtarı taşır. Bayt düzeyinde aynı işlemi yeniden göndermek güvenlidir; yeniden oluşturulmuş bir işlem (örneğin yeni bir blockhash ile) yeni bir transferdir. sign_and_send_transactioniçinde, başarısız olan bir gönderim fonksiyonu bu hatayı,transaction_signaturedeğeri tamamlanan işlemin imzasına ayarlanmış şekilde verir.- Fireblocks, bunu yalnızca bir yoklama (poll), yalnızca imzalama olarak gönderilmiş
bir
use_program_callişleminin buna rağmen Fireblocks tarafından yayınlandığını gösterirse verir.
from solana_keychain import SignerError, SignerErrorCodetry:signature = await sign_and_send_transaction(signer, transaction, send)except SignerError as error:if error.code is SignerErrorCode.BROADCAST_UNCONFIRMED:reconcile(error.provider_transaction_id,error.idempotency_key,error.transaction_signature,)raise
İptal edilen bir çağrı, hiçbir alan taşımayan asyncio.CancelledError hatasını
yeniden verir. Sağlayıcının iptalden önce kabul ettiği bir kimliği kurtarmak için,
Crossmint veya Fordefi yerel otomatik yapılandırmasının pending_transaction_id
alanına bir PendingTransactionId() (solana_keychain.core içinden) iletin ve
iptalden sonra .get() ile okuyun. Yeniden denemeden önce sağlayıcıyla mutabakat
yapın.
Keychain, işlemin ne yaptığını değil imzalama adımını doğrular: sağlayıcının döndürdüğü imza, eklenmeden önce yerel olarak hesaplanan mesaja karşı ed25519 ile doğrulanır. Python anahtar arabelleklerini sıfırlayamaz; bu nedenle yerel anahtarlı backend'lerde (Memory ile uzak backend yapılandırmalarında tutulan API anahtarları ve PEM'ler) tüm işlem belleğini hassas kabul edin. Her imzalama yapısının neyi garanti ettiği için güvenlik modeline bakın.
Özel Signer Ekleme
Backend'inize uyan tek bir yetenek sınıfını (TransactionSigner,
ModifyingSigner veya SendingSigner) solana_keychain.core içinden alt sınıf olarak türetin. Ek anahtar yönetim hizmetlerini entegre etmek için
İmzalayıcı Ekleme kılavuzuna bakın.
Kaynaklar
Is this page helpful?