Python

Versie 2.0 is de eerste stabiele release van het Python-pakket. De 2.0-migratiegids behandelt de ondertekeningsvormen die het deelt met Rust en TypeScript.

Installatie

Installeer het basispakket, plus één extra per backend die een provider- afhankelijkheid nodig heeft:

pip install solana-keychain # memory, vault and para
pip install 'solana-keychain[aws-kms]' # AWS KMS (boto3)
pip install 'solana-keychain[gcp-kms]' # GCP KMS (google-cloud-kms)
pip install 'solana-keychain[privy]' # Privy
pip install 'solana-keychain[turnkey]' # Turnkey
pip install 'solana-keychain[fireblocks]' # Fireblocks
pip install 'solana-keychain[cdp]' # Coinbase Developer Platform
pip install 'solana-keychain[crossmint]' # Crossmint
pip install 'solana-keychain[dfns]' # Dfns
pip install 'solana-keychain[openfort]' # Openfort
pip install 'solana-keychain[utila]' # Utila
pip install 'solana-keychain[fordefi]' # Fordefi
# Several at once
pip install 'solana-keychain[aws-kms,privy]'

Vereist Python 3.10 of nieuwer. Transacties zijn solders VersionedTransaction-objecten; legacy-, v0- en v1-berichten worden allemaal geaccepteerd, behalve door Fireblocks met use_program_call=True, dat alleen legacy en v0 accepteert.

Memory, Vault en Para kunnen worden geïmporteerd vanuit de pakketroot. Elke andere backend wordt geïmporteerd vanuit een eigen submodule (bijvoorbeeld solana_keychain.aws_kms), en het importeren van een backend zonder bijbehorende extra veroorzaakt een ImportError die de te installeren extra noemt. Ledger is alleen beschikbaar voor Rust.

Basisgebruik

Elke backend heeft een config-dataclass en een asynchrone create_<backend>_signer- factory die een kant-en-klare signer teruggeeft. Alle ondertekeningsmethoden zijn coroutines:

import asyncio
from solana_keychain import MemorySigner
from solders.transaction import VersionedTransaction
async 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 geeft een SignedTransaction terug met encoded_transaction, signature, is_complete en transaction. transaction is de gezaghebbende ondertekende transactie: ga daarmee verder, vooral bij een modifying signer, waarvan het resultaat een ander object is dan het object dat je hebt doorgegeven.

Uniforme factory

create_keychain_signer neemt een backendnaam en de config-dataclass van die backend, en importeert de backend lazy, zodat alleen de extras die je gebruikt hoeven te worden geïnstalleerd:

from solana_keychain import create_keychain_signer
from solana_keychain.privy import PrivySignerConfig
signer = await create_keychain_signer(
"privy",
PrivySignerConfig(
app_id="your-app-id",
app_secret="your-app-secret",
wallet_id="your-wallet-id",
),
)

De namen staan in SUPPORTED_BACKENDS: aws-kms, cdp, crossmint, dfns, fireblocks, fordefi, gcp-kms, memory, openfort, para, privy, turnkey, utila en vault. Een onbekende naam, of een config van de verkeerde klasse, veroorzaakt een SignerError met SignerErrorCode.CONFIG_ERROR. De factory is getypeerd als teruggevend de basis-SolanaSigner, dus beperk het type met isinstance voordat je ondertekent (zie Signer-mogelijkheden).

Externe HTTP-clients

Externe HTTP-backends accepteren een optionele http_client (een httpx.AsyncClient) voor aangepaste TLS of proxy's. Als deze niet is ingesteld, gebruikt elk verzoek een eenmalige client met een time-out van 60 seconden, afgedwongen HTTPS op de basis-URL, en worden redirects afgewezen.

Signer-mogelijkheden

Elke backend is een subklasse van de SolanaSigner-ABC (pubkey, sign_message, is_available) plus precies één capability-klasse:

  • TransactionSigner: sign_transaction(tx) ondertekent je transactie ter plekke en geeft een SignedTransaction terug. Jij verzendt de transactie.
  • ModifyingSigner: modify_and_sign_transaction(tx) laat de provider de transactie herschrijven en ondertekent die vervolgens zonder te verzenden. Je object blijft ongewijzigd; ga verder met de teruggegeven SignedTransaction.transaction.
  • SendingSigner: sign_and_send_transaction(tx) ondertekent en verzendt via de provider en geeft de Signature terug van de transactie die is verwerkt. Je transactie wordt nooit gewijzigd.
BackendCapability-klassesign_message
memory, vault, privy, turnkey, aws-kms, fireblocks, gcp-kms, dfns, para, openfortTransactionSignerJa
cdpTransactionSignerAlleen UTF-8-payloads, anders SERIALIZATION_ERROR
utilaTransactionSignerVeroorzaakt SIGNING_FAILED
fordefi black box (FordefiBlackBoxSigner)TransactionSignerJa
fordefi native manual (FordefiNativeManualSigner)ModifyingSignerJa
fordefi native auto (FordefiNativeAutoSigner)SendingSignerJa
crossmintSendingSignerVeroorzaakt SIGNING_FAILED

Beperk het type met isinstance. Alle capability-klassen worden geëxporteerd vanuit de pakketroot:

from solana_keychain import ModifyingSigner, SendingSigner, TransactionSigner
if 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)

Initialisatie

De create_*-factory's en create_keychain_signer doen alle vereiste setup voor jou. Als je de Privy-, Fireblocks-, Dfns-, Crossmint-, Para-, Openfort- of Utila-signerklasse rechtstreeks aanmaakt, voer dan await signer.init() uit vóór gebruik. Tot die tijd veroorzaken pubkey en elke ondertekenaanroep SignerErrorCode.NOT_INITIALIZED.

Backendconfiguratie

Memory

Bouw op basis van een Solana CLI-keypair-bestand, een base58- of "[1,2,...]"-string, ruwe bytes, of een solders Keypair:

from solana_keychain import MemorySigner, MemorySignerConfig, create_memory_signer
from solders.keypair import Keypair
signer = 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 bytes
signer = await create_memory_signer(MemorySignerConfig(keypair=Keypair()))

De sleutel staat in het procesgeheugen, en Python kan deze niet op nul zetten. Gebruik deze backend voor ontwikkeling en testen.

HashiCorp Vault

De sleutel moet een ed25519-sleutel in de transit-engine zijn. Gewone HTTP wordt alleen accepteerd voor een loopback-adres, voor vault server -dev:

from solana_keychain import VaultSignerConfig, create_vault_signer
signer = 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 is een sleutel-ID, ARN of alias voor een ECC_NIST_EDWARDS25519-sleutel. Geef een vooraf gebouwde boto3 KMS-client mee voor aangepaste inloggegevens of endpoints; region wordt dan genegeerd:

from solana_keychain.aws_kms import AwsKmsSignerConfig, create_aws_kms_signer
signer = 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

De sleutelversie moet een EC_SIGN_ED25519-sleutel zijn. client accepteert optioneel een vooraf gebouwde KeyManagementServiceAsyncClient:

from solana_keychain.gcp_kms import GcpKmsSignerConfig, create_gcp_kms_signer
signer = 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_signer
signer = await create_privy_signer(
PrivySignerConfig(
app_id="app_id",
app_secret="app_secret",
wallet_id="wallet_id",
)
)

Wallets die door een autorisatiesleutel worden beschermd, nemen een PrivyAuthorizationConfig als authorization_context.

Turnkey

from solana_keychain.turnkey import TurnkeySignerConfig, create_turnkey_signer
signer = await create_turnkey_signer(
TurnkeySignerConfig(
api_public_key="api_public_key", # hex P-256
api_private_key="api_private_key", # hex P-256
organization_id="org_id",
private_key_id="private_key_id",
public_key="base58_public_key",
)
)

Fireblocks

from solana_keychain.fireblocks import FireblocksSignerConfig, create_fireblocks_signer
signer = 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 ondertekent met de PROGRAM_CALL-operatie in plaats van RAW. De transactie wordt alleen ter ondertekening verzonden, dus Fireblocks herschrijft of verzendt de transactie niet, en jij verzendt zoals gebruikelijk. Het vereist een hot wallet en moet door Fireblocks voor je workspace worden ingeschakeld.

CDP (Coinbase Developer Platform)

from solana_keychain.cdp import CdpSignerConfig, create_cdp_signer
signer = 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_signer
signer = await create_crossmint_signer(
CrossmintSignerConfig(
api_key="api_key",
wallet_locator="wallet_locator",
)
)
signature = await signer.sign_and_send_transaction(transaction)

Crossmint is alleen verzendend. De API voert een goedgekeurde transactie altijd aan de serverzijde uit en sponsort gas, dus CrossmintSigner is een SendingSigner en sign_message veroorzaakt SIGNING_FAILED. De teruggegeven handtekening identificeert de transactie die Crossmint heeft verwerkt, en die kan afwijken van die van jou. Het instellen van signer_secret (een xmsk1_... delegated-signer-secret) keurt transacties automatisch goed, waarmee de keuze wat wordt goedgekeurd aan Crossmint wordt gedelegeerd.

Dfns

from solana_keychain.dfns import DfnsSignerConfig, create_dfns_signer
signer = 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_signer
signer = await create_openfort_signer(
OpenfortSignerConfig(
secret_key="sk_...",
account_id="acc_...",
wallet_secret="wallet_secret",
)
)

Para

from solana_keychain import ParaSignerConfig, create_para_signer
signer = await create_para_signer(
ParaSignerConfig(
api_key="sk_...",
wallet_id="wallet_uuid",
)
)

Utila

Utila ondertekent alleen transacties; sign_message veroorzaakt SIGNING_FAILED.

from solana_keychain.utila import UtilaSignerConfig, create_utila_signer
signer = 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 heeft drie ondertekeningsmodi, vastgelegd bij het aanmaken door chain en push_mode. create_fordefi_signer kiest de klasse, elke klasse weigert een config die voor een andere bedoeld is, en alle drie ondertekenen berichten:

ModusConfigKlasseMethode
Black boxchain niet ingesteldFordefiBlackBoxSignersign_transaction
Native autochain ingesteld, push_mode niet ingesteld of "auto"FordefiNativeAutoSignersign_and_send_transaction
Native manualchain ingesteld, push_mode="manual"FordefiNativeManualSignermodify_and_sign_transaction

API-verzoeken worden geauthenticeerd met een ECDSA P-256-verzoekhandtekening: lever de sleutel aan als private_key_pem, of bewaar deze in een KMS/HSM door een FordefiRequestSigner-subklasse mee te geven als request_signer.

Native auto-modus: stel chain in ("solana_devnet" of "solana_mainnet"), en Fordefi kan de blockhash en kosten vervangen, waarna het de transactie zelf ondertekent en verzendt. Het accepteert alleen een niet-ondertekende transactie waarvan de enige vereiste ondertekenaar de vault is. fee wordt ongewijzigd aan Fordefi doorgegeven:

import os
from solana_keychain.fordefi import FordefiSignerConfig, create_fordefi_signer
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"], # 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)

Native manual-modus: stel chain en push_mode="manual" in. Fordefi herschrijft het bericht (recente blockhash, Compute Budget-feeinstructies) en ondertekent het, maar verzendt niet. De teruggegeven transactie vervangt de transactie die je hebt ingediend, dus ga altijd verder met result.transaction. Fordefi moet de fee payer zijn en moet vóór elke andere vereiste ondertekenaar ondertekenen: een transactie die al handtekeningen bevat wordt geaccepteerd, maar de herschrijving maakt ze ongeldig. De herschrijving wordt niet vergeleken met het origineel, dus controleer het resultaat vóór het verzenden, en verzend snel, aangezien Fordefi de verloophoogte van de nieuwe blockhash niet teruggeeft.

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

Verzend de gecontroleerde transactie zoals bij Ondertekenen en verzenden, en stem af voordat je opnieuw probeert als het verzenden mislukt.

Black box-modus: laat chain weg. Fordefi ondertekent je exacte berichtbytes en verzendt niet. Gebruik dit met een Fordefi black box-vault.

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(),
)
)

Ondertekenen en verzenden

sign_and_send_transaction krijgt een transactie on-chain, ongeacht de vorm van de signer. Een SendingSigner verzendt via zijn provider en je verzendfunctie wordt nooit aangeroepen. Een TransactionSigner of ModifyingSigner ondertekent, en je verzend- functie verzendt het base64-gecodeerde resultaat (het pakket heeft geen RPC-client):

import httpx
from solana_keychain import sign_and_send_transaction
from solders.signature import Signature
async 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)

Een signer die alleen kan ondertekenen en geen verzendfunctie heeft, veroorzaakt CONFIG_ERROR, en een transactie waaraan na het ondertekenen nog handtekeningen ontbreken, veroorzaakt SIGNING_FAILED.

Foutafhandeling

Elke fout is een SignerError met een stabiele code uit SignerErrorCode: 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 en SIGNING_FAILED. Match op code, niet op het bericht: str() en repr() bevatten alleen een vast generiek bericht, nooit sleutelmateriaal of ruwe providerresponses. status_code en provider_error_code worden ingesteld wanneer de fout uit een providerrespons kwam.

SignerErrorCode.BROADCAST_UNCONFIRMED ("SIGNER_BROADCAST_UNCONFIRMED") betekent dat de transactie mogelijk is verwerkt:

  • Bij Crossmint en Fordefi native auto wordt provider_transaction_id ingesteld wanneer het aanmaken is geaccepteerd, en idempotency_key bevat de sleutel die is afgeleid van het bericht waaronder het aanmaken is verzonden. Het opnieuw verzenden van de byte-identieke transactie is veilig; een herbouwde transactie (bijvoorbeeld met een nieuwe blockhash) is een nieuwe overdracht.
  • Vanuit sign_and_send_transaction veroorzaakt een mislukkende verzendfunctie deze fout met transaction_signature ingesteld op de handtekening van de voltooide transactie.
  • Fireblocks veroorzaakt deze fout alleen als uit een poll blijkt dat Fireblocks een use_program_call-transactie heeft verzonden, ondanks dat deze alleen ter ondertekening was verzonden.
from solana_keychain import SignerError, SignerErrorCode
try:
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

Een geannuleerde aanroep werpt opnieuw asyncio.CancelledError, die geen velden bevat. Om een id te herstellen dat de provider vóór de annulering had geaccepteerd, geef je een PendingTransactionId() (uit solana_keychain.core) mee als pending_transaction_id van de Crossmint- of Fordefi native auto-config, en lees je .get() na de annulering. Stem af met de provider voordat je opnieuw probeert.

Keychain valideert de ondertekeningsstap, niet wat de transactie doet: een door de provider teruggegeven handtekening wordt met ed25519 geverifieerd tegen het lokaal berekende bericht voordat deze wordt toegevoegd. Python kan sleutelbuffers niet op nul zetten, dus behandel bij backends met lokale sleutels (Memory, en de API-sleutels en PEM's in de configs van externe backends) het volledige procesgeheugen als gevoelig. Zie het beveiligingsmodel voor wat elke ondertekeningsvorm garandeert.

Eigen signers toevoegen

Maak een subklasse van de ene capability-klasse die bij jouw backend past (TransactionSigner, ModifyingSigner of SendingSigner) uit solana_keychain.core. Raadpleeg de handleiding voor het toevoegen van signers om extra sleutelbeheerservices te integreren.

Bronnen

Is this page helpful?

© 2026 Solana Foundation. Alle rechten voorbehouden.