Go

2.0.0 は Go モジュールの最初の安定版リリースであるため、移行作業はありません。Rust と TypeScript における同じ機能分割については、2.0 移行ガイドをご覧ください。

インストール

各バックエンドは独立した Go モジュールになっているため、ビルドとモジュールグラフにはインポートしたバックエンドのみが含まれます:

go get github.com/solana-foundation/solana-keychain/go/core/v2 # Interfaces, errors, helpers
go get github.com/solana-foundation/solana-keychain/go/signers/memory/v2 # Local keypair signer
go get github.com/solana-foundation/solana-keychain/go/signers/vault/v2 # HashiCorp Vault
go get github.com/solana-foundation/solana-keychain/go/signers/awskms/v2 # AWS KMS
go get github.com/solana-foundation/solana-keychain/go/signers/gcpkms/v2 # GCP KMS
go get github.com/solana-foundation/solana-keychain/go/signers/privy/v2 # Privy
go get github.com/solana-foundation/solana-keychain/go/signers/turnkey/v2 # Turnkey
go get github.com/solana-foundation/solana-keychain/go/signers/fireblocks/v2 # Fireblocks
go get github.com/solana-foundation/solana-keychain/go/signers/cdp/v2 # Coinbase Developer Platform
go get github.com/solana-foundation/solana-keychain/go/signers/crossmint/v2 # Crossmint
go get github.com/solana-foundation/solana-keychain/go/signers/dfns/v2 # Dfns
go get github.com/solana-foundation/solana-keychain/go/signers/openfort/v2 # Openfort
go get github.com/solana-foundation/solana-keychain/go/signers/para/v2 # Para
go get github.com/solana-foundation/solana-keychain/go/signers/utila/v2 # Utila
go get github.com/solana-foundation/solana-keychain/go/signers/fordefi/v2 # Fordefi

モジュールには go/<module>/v2.0.0 の形式でタグが付けられます(例: go/signers/memory/v2.0.0)。google.golang.org/api が定める下限のため gcpkms は Go 1.25.8 が必要ですが、それ以外のすべてのモジュールは Go 1.25.0 が必要です。Ledger は Rust 専用で、Go モジュールはありません。

solana-go v2 と v1 トランザクション

これらのモジュールは github.com/solana-foundation/solana-go/v2 v2.0.0 上に構築されており、その *solana.Transaction を受け取ります。レガシー、v0、v1(solana.MessageVersionV1)のトランザクションがサポートされますが、UseProgramCall: true を指定した Fireblocks はレガシーと v0 のみを受け付けます。

基本的な使い方

すべてのシグナーは基本の core.SolanaSigner インターフェース(Pubkey、SignMessage、IsAvailable)を実装しています。メソッドは context.Context を受け取り、ブロッキングで動作します。各バックエンドは、さらにケイパビリティインターフェースを 1 つだけ実装します:

  • core.TransactionSigner: SignTransaction は、渡されたトランザクションをそのまま署名します。
  • core.ModifyingSigner: ModifyAndSignTransaction は、プロバイダーがトランザクションを書き換えたうえで署名します。
  • core.SendingSigner: SignAndSendTransaction は、プロバイダーが署名とブロードキャストを行います。

各バックエンドパッケージは Config 構造体と New コンストラクターを公開しています:

import (
"context"
"fmt"
"github.com/solana-foundation/solana-go/v2"
"github.com/solana-foundation/solana-keychain/go/core/v2"
"github.com/solana-foundation/solana-keychain/go/signers/memory/v2"
)
func signWithKeychain(ctx context.Context, tx *solana.Transaction) error {
signer, err := memory.New(memory.Config{PrivateKeyPath: "/path/to/id.json"})
if err != nil {
return err
}
if !signer.IsAvailable(ctx) {
return core.NewSignerError(core.CodeNotAvailable, "signer offline")
}
result, err := signer.SignTransaction(ctx, tx)
if err != nil {
return err
}
fmt.Println("signature:", result.Signature)
fmt.Println("complete:", result.IsComplete())
// result.EncodedTransaction is the base64 wire transaction
return nil
}

SignTransaction と ModifyAndSignTransaction は core.SignedTransaction(EncodedTransaction、Signature、Completeness)を返します。リモート HTTP バックエンドは、オプションで HTTPClient と HTTPClientConfig(タイムアウト)を受け付けます。デフォルトのクライアントは HTTPS を強制します。独自のクライアントを指定するとその制約は回避されるため、セキュリティ体制はご自身の責任となります。

シグナーのケイパビリティ

トランザクションに署名できないバックエンドには SignTransaction メソッドがそもそも存在しません。そのため、ケイパビリティは具象型ではコンパイル時に確定し、core.SolanaSigner では型アサーションで判定されます:

バックエンドケイパビリティSignMessage
memory, vault, privy, turnkey, awskms, gcpkms, fireblocks, dfns, para, openfortTransactionSignerはい
cdpTransactionSignerUTF-8 ペイロードのみ
utilaTransactionSignerCodeSigningFailed で失敗
fordefi ブラックボックス(fordefi.BlackBoxSigner)TransactionSignerはい
fordefi ネイティブ手動(fordefi.NativeManualSigner)ModifyingSignerはい
fordefi ネイティブ自動(fordefi.NativeAutoSigner)SendingSignerはい
crossmintSendingSignerCodeSigningFailed で失敗
switch s := signer.(type) {
case core.SendingSigner:
sig, err := s.SignAndSendTransaction(ctx, tx)
case core.ModifyingSigner:
signed, err := s.ModifyAndSignTransaction(ctx, tx)
case core.TransactionSigner:
signed, err := s.SignTransaction(ctx, tx)
}

初期化

個別の Init ステップはありません。Privy、Fireblocks、Dfns、Crossmint、Para、Openfort、Utila は New の内部でウォレットアドレスを解決するため、これらのコンストラクターは context.Context を受け取ります。シグナーは必ず New で構築してください。ゼロ値の Crossmint、Para、Utila シグナーは、ゼロアドレスで署名するのではなく CodeNotInitialized で失敗します。

任意のシグナーで署名と送信を行う

core.SignAndSendTransaction は、シグナーの形態にかかわらずトランザクションをオンチェーンに送信します。SendingSigner はプロバイダー経由でブロードキャストし、send 関数は無視されます。それ以外の形態では署名のみが行われ、base64 の結果(ModifyingSigner の場合は、プロバイダーが書き換えたトランザクション)をユーザーの関数がブロードキャストします。Core は RPC に依存しません:

import "github.com/solana-foundation/solana-go/v2/rpc"
client := rpc.New("https://api.devnet.solana.com")
sig, err := core.SignAndSendTransaction(ctx, signer, tx,
func(ctx context.Context, encoded string) (solana.Signature, error) {
return client.SendEncodedTransaction(ctx, encoded)
})

バッチ署名

バッチ署名は独立したヘルパー関数として提供され、並行実行されます。レート制限のある API 向けに、リクエストごとの間隔(stagger)をオプションで指定できます:

sigs, err := core.SignMessages(ctx, signer, [][]byte{msg1, msg2}, core.BatchOptions{
MaxConcurrency: 4, // 0 = unbounded
RequestDelay: 50 * time.Millisecond,
})
signed, err := core.SignTransactions(ctx, signer, txs, core.BatchOptions{})

core.SignTransactions は core.TransactionSigner を受け取るため、ブロードキャスト管理型のシグナー(Crossmint、Fordefi ネイティブ自動)と Fordefi ネイティブ手動はこれを使ってバッチ処理できません。これらは 1 トランザクションずつ呼び出してください。呼び出しによってプロバイダー側で処理が発生するシグナー(UseProgramCall を指定した Fireblocks)は、core.BatchServerSideEffects を通じてそれを報告し、その場合バッチは順次実行されます。

バックエンド設定

Memory

PrivateKey(生バイト列)、PrivateKeyString(base58 または [1,2,...] 形式のバイト配列)、PrivateKeyPath(Solana CLI の keypair ファイル)のうち、ちょうど 1 つを指定してください:

import "github.com/solana-foundation/solana-keychain/go/signers/memory/v2"
signer, err := memory.New(memory.Config{
PrivateKeyPath: "/path/to/id.json",
})

Go にはメモリをゼロクリアする確実な方法がなく、ガベージコレクターが回収までの間に鍵のバイト列をコピーして保持する場合があります(memory keypair や、Crossmint と Openfort がローカルで導出する鍵が該当します)。ローカル鍵バックエンドを使用する際は、プロセスのメモリ全体を機密として扱ってください。

HashiCorp Vault

import "github.com/solana-foundation/solana-keychain/go/signers/vault/v2"
signer, err := vault.New(vault.Config{
VaultAddr: "https://vault.example.com:8200",
Token: "hvs.xxxxx",
KeyName: "my-solana-key",
Pubkey: "base58_public_key",
})

AWS KMS

import "github.com/solana-foundation/solana-keychain/go/signers/awskms/v2"
signer, err := awskms.New(ctx, awskms.Config{
KeyID: "alias/my-solana-key",
PublicKey: "base58_public_key",
Region: "us-east-1", // optional
})

GCP KMS

import "github.com/solana-foundation/solana-keychain/go/signers/gcpkms/v2"
signer, err := gcpkms.New(ctx, gcpkms.Config{
KeyName: "projects/my-project/locations/us-east1/keyRings/my-ring/cryptoKeys/my-key/cryptoKeyVersions/1",
PublicKey: "base58_public_key",
})
if err != nil {
return err
}
defer signer.Close()

Privy

import "github.com/solana-foundation/solana-keychain/go/signers/privy/v2"
signer, err := privy.New(ctx, privy.Config{
AppID: "app_id",
AppSecret: "app_secret",
WalletID: "wallet_id",
})

Turnkey

import "github.com/solana-foundation/solana-keychain/go/signers/turnkey/v2"
signer, err := turnkey.New(turnkey.Config{
APIPublicKey: "api_public_key",
APIPrivateKey: "api_private_key",
OrganizationID: "org_id",
PrivateKeyID: "private_key_id",
PublicKey: "base58_public_key",
})

Fireblocks

import "github.com/solana-foundation/solana-keychain/go/signers/fireblocks/v2"
signer, err := fireblocks.New(ctx, fireblocks.Config{
APIKey: "api_key",
PrivateKeyPEM: "-----BEGIN RSA PRIVATE KEY-----\n...",
VaultAccountID: "0",
AssetID: "SOL", // or "SOL_TEST" for devnet
UseProgramCall: false, // true signs via sign-only PROGRAM_CALL (legacy/v0, hot wallet)
})

CDP (Coinbase Developer Platform)

import "github.com/solana-foundation/solana-keychain/go/signers/cdp/v2"
signer, err := cdp.New(cdp.Config{
APIKeyID: "api_key_id",
APIKeySecret: "api_key_secret", // base64 Ed25519
WalletSecret: "wallet_secret", // base64 PKCS#8 DER
Address: "base58_address",
Network: cdp.NetworkMainnet, // or cdp.NetworkDevnet; required for address lookup tables
})

CDP の SignMessage は UTF-8 ペイロードのみを受け付けます。

Crossmint

Crossmint は送信専用です。その API は承認されたすべてのトランザクションをサーバー側で実行するため、*crossmint.Signer には SignAndSendTransaction があり、SignTransaction はありません。トランザクションが変更されることはありません。返される署名は Crossmint が実際にランディングさせたトランザクションを識別するもので、Crossmint がガス代をスポンサーする場合は、ユーザーのトランザクションと異なることがあります。

import "github.com/solana-foundation/solana-keychain/go/signers/crossmint/v2"
signer, err := crossmint.New(ctx, crossmint.Config{
APIKey: "api_key",
WalletLocator: "wallet_locator",
SignerSecret: "", // optional xmsk1_ secret: auto-approves what Crossmint presents
})
sig, err := signer.SignAndSendTransaction(ctx, tx)

Dfns

import "github.com/solana-foundation/solana-keychain/go/signers/dfns/v2"
signer, err := dfns.New(ctx, dfns.Config{
AuthToken: "auth_token",
CredID: "cred_id",
PrivateKeyPEM: "-----BEGIN EC PRIVATE KEY-----\n...",
WalletID: "wallet_id",
})

Openfort

import "github.com/solana-foundation/solana-keychain/go/signers/openfort/v2"
signer, err := openfort.New(ctx, openfort.Config{
SecretKey: "sk_live_...",
AccountID: "acc_...",
WalletSecret: "wallet_secret", // base64 PKCS#8 DER or PEM
})

Para

import "github.com/solana-foundation/solana-keychain/go/signers/para/v2"
signer, err := para.New(ctx, para.Config{
APIKey: "sk_...",
WalletID: "wallet_id",
})

Utila

Utila はトランザクションへの署名のみを行います。SignMessage は失敗するため、署名済みトランザクションはご自身でブロードキャストしてください。

import "github.com/solana-foundation/solana-keychain/go/signers/utila/v2"
signer, err := utila.New(ctx, utila.Config{
ServiceAccountEmail: "sa@example.com",
ServiceAccountPrivateKeyPEM: "-----BEGIN PRIVATE KEY-----\n...",
VaultID: "vault_id",
WalletID: "wallet_id",
Network: "networks/solana-devnet",
})

Fordefi

Fordefi には 3 種類のシグナータイプがあり、Config.Chain と Config.PushMode によって構築時に決まります。3 つとも、メッセージへの署名が可能です:

設定型エントリーポイント
Chain 未設定*fordefi.BlackBoxSignerSignTransaction
Chain 設定済み、PushMode 未設定または PushModeAuto*fordefi.NativeAutoSignerSignAndSendTransaction
Chain 設定済み、PushMode: PushModeManual*fordefi.NativeManualSignerModifyAndSignTransaction

fordefi.New は設定に応じて振り分け、core.SolanaSigner を返します。fordefi.NewBlackBox、fordefi.NewNativeAuto、fordefi.NewNativeManual は具象型を返し、他のモードの設定は拒否します。API リクエストは ECDSA P-256 のリクエスト署名で認証されます。PrivateKeyPEM か、鍵を KMS/HSM に保持するための RequestSigner のいずれか 1 つだけを指定してください。

ネイティブ自動モード: Fordefi がブロックハッシュと手数料を置き換える場合があり、その後に署名とブロードキャストを行います。必要な署名者がボールトのみである未署名トランザクションだけを受け付けます。

import "github.com/solana-foundation/solana-keychain/go/signers/fordefi/v2"
signer, err := fordefi.NewNativeAuto(ctx, fordefi.Config{
AccessToken: os.Getenv("FORDEFI_ACCESS_TOKEN"),
VaultID: os.Getenv("FORDEFI_VAULT_ID"),
PublicKey: os.Getenv("FORDEFI_PUBLIC_KEY"), // Solana vault address (base58)
PrivateKeyPEM: string(pemBytes),
Chain: fordefi.ChainSolanaDevnet, // or fordefi.ChainSolanaMainnet
Fee: &fordefi.Fee{
Type: fordefi.FeeTypePriority,
PriorityLevel: fordefi.PriorityMedium,
},
})
sig, err := signer.SignAndSendTransaction(ctx, tx)

ネイティブ手動モード: PushMode: fordefi.PushModeManual を設定します。Fordefi はメッセージ(最新のブロックハッシュ、Compute Budget の手数料 instructions)を書き換え、ブロードキャストせずに署名します。ModifyAndSignTransaction は tx を Fordefi が署名したトランザクションに置き換えるため、必ずそこから処理を続けてください。書き換えによって既存の署名は無効になるため、Fordefi が手数料支払者であり、他の必須署名者より先に署名する必要があります。書き換え内容の差分は取得されないため、ブロードキャスト前に結果を確認してください。

signer, err := fordefi.NewNativeManual(ctx, fordefi.Config{
AccessToken: os.Getenv("FORDEFI_ACCESS_TOKEN"),
VaultID: os.Getenv("FORDEFI_VAULT_ID"),
PublicKey: os.Getenv("FORDEFI_PUBLIC_KEY"),
PrivateKeyPEM: string(pemBytes),
Chain: fordefi.ChainSolanaDevnet,
PushMode: fordefi.PushModeManual,
})
signed, err := signer.ModifyAndSignTransaction(ctx, tx)

ブラックボックスモード: Chain を未設定のままにします。Fordefi はメッセージのバイト列をそのまま署名し、ブロードキャストは行いません。Fordefi のブラックボックスボールトで使用します。

signer, err := fordefi.NewBlackBox(ctx, fordefi.Config{
AccessToken: os.Getenv("FORDEFI_ACCESS_TOKEN"),
VaultID: os.Getenv("FORDEFI_BB_VAULT_ID"),
PublicKey: os.Getenv("FORDEFI_BB_PUBLIC_KEY"),
PrivateKeyPEM: string(pemBytes),
})

アンブレラパッケージが存在しない理由

Rust には Signer enum、TypeScript には createKeychainSigner がありますが、Go にはあえてどちらも用意していません。Go はランタイムのディスパッチ switch をまたいだデッドコード除去を行わないため、アンブレラパッケージを用意すると、すべてのバックエンドのベンダー SDK(AWS、GCP など)がすべての利用者のビルドに含まれてしまいます。必要なバックエンドのパッケージをインポートすること自体が選択手段です。実行時にバックエンドを選ぶには、サポートするバックエンドだけを対象とした switch を自分のコードに記述し、結果を core.SolanaSigner として保持してください。

エラー処理

すべてのエラーは、安定した Code(CodeConfigError、CodeHTTPError、CodeRemoteAPIError、CodeSigningFailed、CodeNotInitialized、CodeBroadcastUnconfirmed など)を持つ *core.SignerError です。Error() はコードごとの固定メッセージのみを返し、鍵素材やプロバイダーの生のレスポンスは含まれません。errors.As、errors.Is(err, &core.SignerError{Code: ...})、core.CodeOf(err) で照合できます。

Crossmint と Fordefi ネイティブ自動モードでは、失敗してもトランザクションが何も反映されていないとは限りません。プロバイダーがトランザクションを受理した可能性がある場合、コードは core.CodeBroadcastUnconfirmed("SIGNER_BROADCAST_UNCONFIRMED")になります。作成が受理された場合は ProviderTxID が設定され、IdempotencyKey にはメッセージから導出されたキーが格納されます。バイト列が同一のトランザクションを再送しても安全ですが、再構築したもの(たとえば新しいブロックハッシュを使ったもの)は新たな送金として扱われます。core.SignAndSendTransaction も、send 関数が失敗した場合にこのコードを報告し、手数料支払者の署名を TransactionSignature に格納します。Fireblocks の PROGRAM_CALL は署名専用でキーを送信しないため、ポーリングの結果 Fireblocks がそれでもブロードキャストしたと判明した場合にのみ、このコードを報告します。

sig, err := core.SignAndSendTransaction(ctx, signer, tx, send)
var se *core.SignerError
if errors.As(err, &se) && se.Code == core.CodeBroadcastUnconfirmed {
// Reconcile se.ProviderTxID, se.IdempotencyKey or se.TransactionSignature
// with the provider before retrying.
}

各署名形態が保証する内容についてはセキュリティモデル、完全なモジュール一覧についてはGo README、API リファレンスについてはpkg.go.devをご覧ください。

カスタムシグナーの追加

core.SolanaSigner と、ケイパビリティインターフェースをちょうど 1 つ実装してください。バックエンドが対応できないメソッドは追加しないでください。呼び出し側は型アサーションでケイパビリティを判定します。他のキー管理サービスを統合するには、シグナー追加ガイドをご覧ください。

Is this page helpful?

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