2.0.0 is de eerste stabiele release van de Go-modules, dus er valt niets te migreren. De 2.0-migratiegids behandelt dezelfde opsplitsing in mogelijkheden voor Rust en TypeScript.
Installatie
Elke backend is een eigen Go-module, zodat je build en je modulegrafiek alleen de backends bevatten die je importeert:
go get github.com/solana-foundation/solana-keychain/go/core/v2 # Interfaces, errors, helpersgo get github.com/solana-foundation/solana-keychain/go/signers/memory/v2 # Local keypair signergo get github.com/solana-foundation/solana-keychain/go/signers/vault/v2 # HashiCorp Vaultgo get github.com/solana-foundation/solana-keychain/go/signers/awskms/v2 # AWS KMSgo get github.com/solana-foundation/solana-keychain/go/signers/gcpkms/v2 # GCP KMSgo get github.com/solana-foundation/solana-keychain/go/signers/privy/v2 # Privygo get github.com/solana-foundation/solana-keychain/go/signers/turnkey/v2 # Turnkeygo get github.com/solana-foundation/solana-keychain/go/signers/fireblocks/v2 # Fireblocksgo get github.com/solana-foundation/solana-keychain/go/signers/cdp/v2 # Coinbase Developer Platformgo get github.com/solana-foundation/solana-keychain/go/signers/crossmint/v2 # Crossmintgo get github.com/solana-foundation/solana-keychain/go/signers/dfns/v2 # Dfnsgo get github.com/solana-foundation/solana-keychain/go/signers/openfort/v2 # Openfortgo get github.com/solana-foundation/solana-keychain/go/signers/para/v2 # Parago get github.com/solana-foundation/solana-keychain/go/signers/utila/v2 # Utilago get github.com/solana-foundation/solana-keychain/go/signers/fordefi/v2 # Fordefi
Modules worden getagd als go/<module>/v2.0.0 (bijvoorbeeld
go/signers/memory/v2.0.0). Elke module vereist Go 1.25.0, behalve gcpkms,
die Go 1.25.8 vereist vanwege de ondergrens die door google.golang.org/api
wordt bepaald. Ledger is alleen beschikbaar voor Rust en heeft geen Go-module.
solana-go v2 en v1-transacties
De modules zijn gebouwd op
github.com/solana-foundation/solana-go/v2
v2.0.0 en accepteren de bijbehorende *solana.Transaction. Legacy-, v0- en
v1-transacties (solana.MessageVersionV1) worden ondersteund, behalve door
Fireblocks met UseProgramCall: true, dat alleen legacy en v0 accepteert.
Basisgebruik
Elke signer implementeert de basis-
core.SolanaSigner-interface
(Pubkey, SignMessage, IsAvailable). Methoden nemen een context.Context en
blokkeren. Daarnaast implementeert elke backend precies één interface voor een
mogelijkheid:
core.TransactionSigner:SignTransactionondertekent je transactie zoals aangeleverd.core.ModifyingSigner:ModifyAndSignTransactionlaat de provider de transactie herschrijven en ondertekent die vervolgens.core.SendingSigner:SignAndSendTransactionlaat de provider de transactie ondertekenen en uitzenden.
Elk backendpakket biedt een Config-struct en een New-constructor:
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 transactionreturn nil}
SignTransaction en ModifyAndSignTransaction geven een
core.SignedTransaction terug (EncodedTransaction, Signature,
Completeness). Externe HTTP-backends accepteren een optionele HTTPClient en
HTTPClientConfig (time-outs). De standaardclient dwingt HTTPS af; als je een
eigen client meegeeft, wordt dat omzeild en ben je zelf verantwoordelijk voor de
beveiliging ervan.
Mogelijkheden van signers
Een backend die geen transactie kan ondertekenen, heeft helemaal geen
SignTransaction-methode. Of een mogelijkheid beschikbaar is, staat dus bij
concrete typen al tijdens het compileren vast en wordt bij een
core.SolanaSigner bepaald via een type assertion:
| Backend | Mogelijkheid | SignMessage |
|---|---|---|
| memory, vault, privy, turnkey, awskms, gcpkms, fireblocks, dfns, para, openfort | TransactionSigner | Ja |
| cdp | TransactionSigner | Alleen UTF-8-payloads |
| utila | TransactionSigner | Mislukt met CodeSigningFailed |
fordefi black box (fordefi.BlackBoxSigner) | TransactionSigner | Ja |
fordefi native manual (fordefi.NativeManualSigner) | ModifyingSigner | Ja |
fordefi native auto (fordefi.NativeAutoSigner) | SendingSigner | Ja |
| crossmint | SendingSigner | Mislukt met CodeSigningFailed |
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)}
Initialisatie
Er is geen aparte Init-stap. Privy, Fireblocks, Dfns, Crossmint, Para,
Openfort en Utila bepalen het walletadres binnen New, en daarom nemen hun
constructors een context.Context. Bouw signers altijd via New: een
Crossmint-, Para- of Utila-signer met nulwaarde mislukt met
CodeNotInitialized in plaats van te ondertekenen voor het nuladres.
Ondertekenen en verzenden met elke signer
core.SignAndSendTransaction brengt een transactie on-chain, ongeacht het type
signer. Een SendingSigner zendt uit via zijn provider en negeert de
verzendfunctie; bij elk ander type ondertekent de signer en zendt jouw functie
het base64-resultaat uit. Bij een ModifyingSigner is dat de transactie die de
provider heeft herschreven. Core heeft geen RPC-afhankelijkheid:
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)})
Batchondertekening
Batchondertekening wordt aangeboden als losse helpers, gelijktijdig en met een optionele vertraging per verzoek voor API's met rate limits:
sigs, err := core.SignMessages(ctx, signer, [][]byte{msg1, msg2}, core.BatchOptions{MaxConcurrency: 4, // 0 = unboundedRequestDelay: 50 * time.Millisecond,})signed, err := core.SignTransactions(ctx, signer, txs, core.BatchOptions{})
core.SignTransactions neemt een core.TransactionSigner, dus de signers die
zelf uitzenden (Crossmint, Fordefi native auto) en Fordefi native manual kunnen
niet via deze functie in batches worden verwerkt; roep ze één transactie per
keer aan. Een signer waarvan de aanroepen werk aan de providerkant veroorzaken
(Fireblocks met UseProgramCall) meldt dat via core.BatchServerSideEffects,
waarna de batch sequentieel wordt uitgevoerd.
Backend-configuratie
Memory
Geef precies één van de volgende op: PrivateKey (ruwe bytes),
PrivateKeyString (base58 of een [1,2,...]-bytearray) of PrivateKeyPath
(Solana CLI-keypair-bestand):
import "github.com/solana-foundation/solana-keychain/go/signers/memory/v2"signer, err := memory.New(memory.Config{PrivateKeyPath: "/path/to/id.json",})
Go biedt geen betrouwbare manier om geheugen op nul te zetten: de garbage collector kan sleutelbytes kopiëren en bewaren tot de volgende opruiming (memory-keypairs en de sleutels die Crossmint en Openfort lokaal afleiden). Behandel het volledige procesgeheugen als gevoelig wanneer je backends met lokale sleutels gebruikt.
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 devnetUseProgramCall: 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 Ed25519WalletSecret: "wallet_secret", // base64 PKCS#8 DERAddress: "base58_address",Network: cdp.NetworkMainnet, // or cdp.NetworkDevnet; required for address lookup tables})
SignMessage van CDP accepteert alleen UTF-8-payloads.
Crossmint
Crossmint kan alleen uitzenden: de API voert elke goedgekeurde transactie aan
de serverkant uit, dus *crossmint.Signer heeft SignAndSendTransaction en
geen SignTransaction. Je transactie wordt nooit gewijzigd; de teruggegeven
handtekening identificeert de transactie die Crossmint heeft verwerkt, en die
kan afwijken van de jouwe als Crossmint de gas sponsort.
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 ondertekent alleen transacties; SignMessage mislukt, en je zendt de
ondertekende transactie zelf uit.
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 bestaat in drie signertypen, die bij de constructie worden bepaald door
Config.Chain en Config.PushMode. Alle drie ondertekenen berichten:
| Config | Type | Startpunt |
|---|---|---|
Chain niet ingesteld | *fordefi.BlackBoxSigner | SignTransaction |
Chain ingesteld, PushMode niet ingesteld of PushModeAuto | *fordefi.NativeAutoSigner | SignAndSendTransaction |
Chain ingesteld, PushMode: PushModeManual | *fordefi.NativeManualSigner | ModifyAndSignTransaction |
fordefi.New kiest op basis van de config en geeft een core.SolanaSigner
terug; fordefi.NewBlackBox, fordefi.NewNativeAuto en
fordefi.NewNativeManual geven het concrete type terug en weigeren de configs
van de andere modi. API-verzoeken worden geauthenticeerd met een ECDSA
P-256-verzoekhandtekening: geef precies één van de volgende op: PrivateKeyPEM,
of een RequestSigner om die sleutel in een KMS/HSM te houden.
Native auto-modus: Fordefi kan de blockhash en de fees vervangen, en ondertekent en zendt de transactie vervolgens uit. De modus accepteert alleen een niet-ondertekende transactie waarvan de enige vereiste ondertekenaar de vault is.
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.ChainSolanaMainnetFee: &fordefi.Fee{Type: fordefi.FeeTypePriority,PriorityLevel: fordefi.PriorityMedium,},})sig, err := signer.SignAndSendTransaction(ctx, tx)
Native manual-modus: stel PushMode: fordefi.PushModeManual in. Fordefi
herschrijft het bericht (recente blockhash, Compute Budget-feeinstructies) en
ondertekent het zonder uit te zenden. ModifyAndSignTransaction vervangt tx
door de transactie die Fordefi heeft ondertekend: ga altijd verder met die
transactie. Fordefi moet de fee payer zijn en moet vóór alle andere vereiste
ondertekenaars tekenen, omdat de herschrijving bestaande handtekeningen
ongeldig maakt. Het verschil met het origineel wordt niet bepaald, dus controleer
het resultaat voordat je uitzendt.
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)
Black box-modus: laat Chain niet ingesteld. Fordefi ondertekent exact de
bytes van je bericht en zendt niet uit. Gebruik dit met een Fordefi black
box-vault.
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),})
Waarom er geen overkoepelend pakket is
Rust heeft een Signer-enum en TypeScript heeft createKeychainSigner; Go
heeft bewust geen van beide. Go verwijdert geen dode code over een runtime
dispatch-switch heen, dus een overkoepelend pakket zou de vendor-SDK van elke
backend (AWS, GCP en de rest) in de build van elke consument dwingen. Het
importeren van het backendpakket dat je nodig hebt, is de selector. Wil je
runtime een backend kiezen, schrijf dan in je eigen code de switch over alleen
de backends die je ondersteunt, en bewaar het resultaat als een
core.SolanaSigner.
Foutafhandeling
Elke fout is een *core.SignerError met een stabiele Code (CodeConfigError,
CodeHTTPError, CodeRemoteAPIError, CodeSigningFailed,
CodeNotInitialized, CodeBroadcastUnconfirmed en andere). Error() geeft per
code alleen een vaste melding terug, nooit sleutelmateriaal of ruwe
providerresponses. Vergelijk met errors.As,
errors.Is(err, &core.SignerError{Code: ...}) of core.CodeOf(err).
Bij Crossmint en Fordefi native auto-modus betekent een fout niet dat er niets
is verwerkt. Als de provider de transactie mogelijk heeft geaccepteerd, is de
code core.CodeBroadcastUnconfirmed ("SIGNER_BROADCAST_UNCONFIRMED").
ProviderTxID wordt ingesteld wanneer het aanmaken is geaccepteerd, en
IdempotencyKey bevat de sleutel die van het bericht is afgeleid. Het opnieuw
verzenden van de byte-identieke transactie is veilig; een opnieuw opgebouwde
transactie (bijvoorbeeld met een nieuwe blockhash) is een nieuwe overdracht.
core.SignAndSendTransaction meldt deze code ook wanneer je verzendfunctie
faalt, met de handtekening van de fee payer in TransactionSignature.
Fireblocks PROGRAM_CALL ondertekent alleen en verstuurt geen sleutel; het meldt
deze code alleen wanneer een poll laat zien dat Fireblocks toch heeft
uitgezonden.
sig, err := core.SignAndSendTransaction(ctx, signer, tx, send)var se *core.SignerErrorif errors.As(err, &se) && se.Code == core.CodeBroadcastUnconfirmed {// Reconcile se.ProviderTxID, se.IdempotencyKey or se.TransactionSignature// with the provider before retrying.}
Zie het beveiligingsmodel voor wat elk type ondertekening garandeert, de Go README voor de volledige lijst met modules, en pkg.go.dev voor de API-referentie.
Eigen signers toevoegen
Implementeer core.SolanaSigner plus precies één interface voor een
mogelijkheid, en voeg geen methode toe die je backend niet kan waarmaken:
aanroepers stellen de mogelijkheden vast via een type assertion. Zie de
gids voor het toevoegen van signers om extra
sleutelbeheerdiensten te integreren.
Is this page helpful?