Python

バージョン2.0は、Pythonパッケージ初の安定版リリースです。2.0移行ガイドでは、RustおよびTypeScriptと共通の署名の形式について説明しています。

インストール

ベースパッケージをインストールし、プロバイダー依存関係が必要なバックエンドごとにextraを1つずつ追加でインストールします:

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]'

Python 3.10以降が必要です。トランザクションはsoldersのVersionedTransactionオブジェクトです。レガシー、v0、v1のメッセージはすべて受け付けられますが、use_program_call=Trueを指定したFireblocksのみ、レガシーとv0だけを受け付けます。

Memory、Vault、Paraはパッケージのルートからインポートできます。それ以外のバックエンドは、それぞれのサブモジュール(例: solana_keychain.aws_kms)からインポートします。extraを入れずにインポートすると、インストールすべきextraを示すImportErrorが発生します。LedgerはRust専用です。

基本的な使い方

各バックエンドには、設定用のdataclassと、すぐに使えるsignerを返す非同期のcreate_<backend>_signerファクトリがあります。すべての署名メソッドはコルーチンです:

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は、encoded_transaction、signature、is_complete、transactionを持つSignedTransactionを返します。transactionが正式な署名済みトランザクションです。特にmodifying signerでは、結果が渡したオブジェクトとは別のオブジェクトになるため、以降の処理はこのtransactionを使って続けてください。

統合ファクトリ

create_keychain_signerは、バックエンド名とそのバックエンドの設定dataclassを受け取り、バックエンドを遅延インポートします。そのため、使用するextraだけをインストールすれば済みます:

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

使用できる名前はSUPPORTED_BACKENDSに一覧されています: aws-kms、cdp、crossmint、dfns、fireblocks、fordefi、gcp-kms、memory、openfort、para、privy、turnkey、utila、vault。未知の名前や、クラスが正しくない設定を渡すと、SignerErrorCode.CONFIG_ERRORを伴うSignerErrorが発生します。ファクトリの戻り値の型はベースのSolanaSignerであるため、署名する前にisinstanceで絞り込んでください(Signerの機能を参照)。

リモートHTTPクライアント

リモートHTTPバックエンドは、カスタムTLSやプロキシを使用するための任意のhttp_client(httpx.AsyncClient)を受け付けます。未設定の場合、各リクエストはタイムアウト60秒の使い切りクライアントを使用し、ベースURLにはHTTPSが強制され、リダイレクトは拒否されます。

Signerの機能

すべてのバックエンドはSolanaSigner ABC(pubkey、sign_message、is_available)を継承し、さらに機能クラスをちょうど1つ継承します:

  • TransactionSigner: sign_transaction(tx)は、渡されたトランザクションにその場で署名し、SignedTransactionを返します。ブロードキャストは自分で行います。
  • ModifyingSigner: modify_and_sign_transaction(tx)は、プロバイダーによるトランザクションの書き換えを許可したうえで署名し、ブロードキャストは行いません。渡したオブジェクトは変更されないため、返されたSignedTransaction.transactionを使って処理を続けてください。
  • SendingSigner: sign_and_send_transaction(tx)は、プロバイダー経由で署名とブロードキャストを行い、チェーンに反映されたトランザクションのSignatureを返します。渡したトランザクションが変更されることはありません。
バックエンド機能クラスsign_message
memory、vault、privy、turnkey、aws-kms、fireblocks、gcp-kms、dfns、para、openfortTransactionSigner対応
cdpTransactionSignerUTF-8ペイロードのみ。それ以外はSERIALIZATION_ERROR
utilaTransactionSignerSIGNING_FAILEDが発生
fordefi black box(FordefiBlackBoxSigner)TransactionSigner対応
fordefi native manual(FordefiNativeManualSigner)ModifyingSigner対応
fordefi native auto(FordefiNativeAutoSigner)SendingSigner対応
crossmintSendingSignerSIGNING_FAILEDが発生

isinstanceで絞り込みます。すべての機能クラスはパッケージのルートからエクスポートされています:

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)

初期化

create_*ファクトリとcreate_keychain_signerが、必要なセットアップをすべて行います。Privy、Fireblocks、Dfns、Crossmint、Para、Openfort、Utilaのsignerクラスを直接生成する場合は、使用前にawait signer.init()を実行してください。それまでは、pubkeyおよびすべての署名呼び出しでSignerErrorCode.NOT_INITIALIZEDが発生します。

バックエンドの設定

Memory

Solana CLIのkeypairファイル、base58文字列または"[1,2,...]"形式の文字列、生のバイト列、あるいは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()))

キーはプロセスのメモリ上に保持され、Pythonではゼロ化できません。このバックエンドは開発とテストにのみ使用してください。

HashiCorp Vault

キーはtransitエンジン内のed25519キーである必要があります。プレーンHTTPは、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は、ECC_NIST_EDWARDS25519キーのキーID、ARN、またはエイリアスです。独自の認証情報やエンドポイントを使用する場合は、構築済みのboto3 KMS clientを渡してください。その場合、regionは無視されます:

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

キーバージョンはEC_SIGN_ED25519キーである必要があります。clientには、構築済みの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",
)
)

authorization keyで保護されたウォレットでは、PrivyAuthorizationConfigを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を指定すると、RAWの代わりにPROGRAM_CALLオペレーションで署名します。署名のみの形で送信されるため、Fireblocksがトランザクションを書き換えたりブロードキャストしたりすることはなく、これまでどおり自分でブロードキャストします。ホットウォレットが必要で、Fireblocks側でワークスペースに対して有効化されている必要があります。

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は送信専用です。そのAPIは承認されたトランザクションを常にサーバーサイドで実行し、ガス代をスポンサーするため、CrossmintSignerはSendingSignerであり、sign_messageはSIGNING_FAILEDを発生させます。返される署名は、Crossmintがチェーンに反映したトランザクションを識別するもので、送信したものと異なる場合があります。signer_secret(xmsk1_...形式のdelegated-signerシークレット)を設定すると、トランザクションが自動的に承認されます。これは、何を承認するかの判断をCrossmintに委ねることを意味します。

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はトランザクションの署名のみに対応しており、sign_messageは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には3つの署名モードがあり、chainとpush_modeによって構築時に決まります。create_fordefi_signerが適切なクラスを選択し、各クラスは他のモード向けの設定を拒否します。3つのモードはいずれもメッセージへの署名に対応しています:

モード設定クラスメソッド
Black boxchainを未設定FordefiBlackBoxSignersign_transaction
Native autochainを設定し、push_modeは未設定または"auto"FordefiNativeAutoSignersign_and_send_transaction
Native manualchainを設定し、push_mode="manual"FordefiNativeManualSignermodify_and_sign_transaction

APIリクエストは、ECDSA P-256のリクエスト署名で認証されます。キーをprivate_key_pemとして渡すか、FordefiRequestSignerのサブクラスをrequest_signerとして渡して、KMS/HSM内にキーを保持してください。

Native autoモード: chain("solana_devnet"または"solana_mainnet")を設定すると、Fordefiがブロックハッシュと手数料を置き換える場合があり、その後、トランザクションへの署名とブロードキャストをFordefi自身が行います。受け付けるのは、必須署名者がvaultのみである未署名のトランザクションに限られます。feeはそのままFordefiに渡されます:

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モード: chainを設定し、push_mode="manual"を指定します。Fordefiはメッセージ(最新のブロックハッシュ、Compute Budgetの手数料instructions)を書き換えて署名しますが、ブロードキャストは行いません。返されるトランザクションは、送信したものと置き換わるため、必ずresult.transactionを使って処理を続けてください。Fordefiは手数料支払者である必要があり、他のどの必須署名者よりも先に署名しなければなりません。すでに署名を含むトランザクションも受け付けられますが、書き換えによってそれらの署名は無効になります。書き換え内容の差分は提示されないため、ブロードキャストの前に結果を確認し、速やかにブロードキャストしてください。Fordefiは新しいブロックハッシュの有効期限の高さを返しません。

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

確認したトランザクションは署名と送信の手順でブロードキャストし、送信に失敗した場合は、再試行する前に状態を照合してください。

Black boxモード: chainを省略します。Fordefiは渡されたメッセージのバイト列そのものに署名し、ブロードキャストは行いません。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(),
)
)

署名と送信

sign_and_send_transactionは、signerの種類にかかわらず、トランザクションをチェーンに反映させます。SendingSignerはプロバイダー経由でブロードキャストするため、ユーザーの送信関数は呼び出されません。TransactionSignerまたはModifyingSignerは署名を行い、Base64エンコードされた結果を送信関数がブロードキャストします(このパッケージにはRPCクライアントはありません):

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)

署名のみのsignerで送信関数がない場合はCONFIG_ERRORが発生し、署名後も署名が不足しているトランザクションではSIGNING_FAILEDが発生します。

エラー処理

すべての失敗は、SignerErrorCodeの安定したcodeを持つSignerErrorとして発生します: 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、SIGNING_FAILED。判定にはメッセージではなくcodeを使用してください。str()とrepr()には固定の汎用メッセージのみが含まれ、キー素材やプロバイダーの生のレスポンスが含まれることはありません。status_codeとprovider_error_codeは、失敗の原因がプロバイダーのレスポンスにある場合に設定されます。

SignerErrorCode.BROADCAST_UNCONFIRMED("SIGNER_BROADCAST_UNCONFIRMED")は、トランザクションがチェーンに反映された可能性があることを意味します:

  • CrossmintおよびFordefi native autoでは、作成リクエストが受理された時点でprovider_transaction_idが設定され、idempotency_keyには、作成リクエストの送信に使われた、メッセージから導出されたキーが格納されます。バイト列が同一のトランザクションを再送しても安全ですが、再構築したトランザクション(たとえば新しいブロックハッシュを使ったもの)は、新たな送金として扱われます。
  • sign_and_send_transactionでは、送信関数が失敗すると、完成したトランザクションの署名がtransaction_signatureに設定された状態でこのエラーが発生します。
  • Fireblocksでは、署名のみで送信されたuse_program_callトランザクションを、Fireblocksがブロードキャストしたことがポーリングで判明した場合にのみ発生します。
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

キャンセルされた呼び出しではasyncio.CancelledErrorが再送出されますが、これにはフィールドがありません。キャンセル前にプロバイダーが受理したIDを回復するには、solana_keychain.coreのPendingTransactionId()を、CrossmintまたはFordefi native autoの設定のpending_transaction_idとして渡し、キャンセル後に.get()で読み取ってください。再試行する前に、プロバイダーと状態を照合してください。

Keychainが検証するのは署名の経路であり、トランザクションの内容ではありません。プロバイダーが返した署名は、アタッチされる前に、ローカルで計算したメッセージに対してed25519で検証されます。Pythonではキーのバッファをゼロ化できないため、ローカルキーのバックエンド(Memory、およびリモートバックエンドの設定内に保持されるAPIキーとPEM)では、プロセスのメモリ全体を機密として扱ってください。各署名の形式が何を保証するかについては、セキュリティモデルを参照してください。

カスタムsignerの追加

バックエンドに対応する機能クラスを1つ選び(TransactionSigner、 ModifyingSigner、または SendingSigner)、solana_keychain.core からサブクラス化してください。 追加のキー管理サービスを統合する方法については、 署名者の追加ガイドをご覧ください。

リソース

Is this page helpful?

© 2026 Solana Foundation. 無断転載を禁じます。