Private Key Account
Create an account from a private key for signing transactions and messages locally
A Private Key Account is an account that can sign transactions and messages with a given private key. In viem-go, signing uses go-ethereum/crypto (secp256k1).
Import
import "github.com/ChefBingbong/viem-go/accounts"Usage
Pass a 32-byte hex private key (with or without 0x prefix) to PrivateKeyToAccount:
import "github.com/ChefBingbong/viem-go/accounts"
account, err := accounts.PrivateKeyToAccount( "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80",)if err != nil { log.Fatal(err)}
fmt.Printf("Address: %s", account.GetAddress())// Address: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266fmt.Printf("Public Key: %s", account.GetPublicKey())The key in the example is valid for testing only. Do not use it for real funds.
Generating private keys
Generate a cryptographically secure random private key with GeneratePrivateKey. It returns a hex string (no error); it panics only on a broken RNG.
import "github.com/ChefBingbong/viem-go/accounts"
privateKey := accounts.GeneratePrivateKey()// "0x..." (64 hex characters)
account, err := accounts.PrivateKeyToAccount(privateKey)if err != nil { log.Fatal(err)}For deterministic tests, use GeneratePrivateKeyWithEntropy(entropy []byte) — it returns an error if the 32-byte entropy is not a valid secp256k1 private key.
Signing messages
Sign an EIP-191 personal message:
import "github.com/ChefBingbong/viem-go/utils/signature"
msg := signature.NewSignableMessage("Hello, Ethereum!")sig, err := account.SignMessage(msg)if err != nil { log.Fatal(err)}fmt.Printf("Signature: %s", sig)For raw bytes use signature.NewSignableMessageRaw(bytes) or signature.NewSignableMessageRawHex(hexString).
Signing transactions
Sign a transaction (legacy, EIP-2930, EIP-1559, etc.). The account returns the serialized signed transaction ready for broadcast.
import ( "github.com/ChefBingbong/viem-go/utils/transaction" "math/big")
tx := &transaction.Transaction{ To: "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", Value: big.NewInt(1e18), Gas: 21000, GasPrice: big.NewInt(20e9), Nonce: 0, ChainId: 1,}
signedTx, err := account.SignTransaction(tx)if err != nil { log.Fatal(err)}// signedTx is hex-encoded (e.g. 0x02...) ready for eth_sendRawTransactionSigning typed data (EIP-712)
import ( "github.com/ChefBingbong/viem-go/utils/signature" "math/big")
typedData := signature.TypedDataDefinition{ Domain: signature.TypedDataDomain{ Name: "Ether Mail", Version: "1", ChainId: big.NewInt(1), VerifyingContract: "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC", }, Types: map[string][]signature.TypedDataField{ "Person": {{Name: "name", Type: "string"}, {Name: "wallet", Type: "address"}}, "Mail": {{Name: "from", Type: "Person"}, {Name: "to", Type: "Person"}, {Name: "contents", Type: "string"}}, }, PrimaryType: "Mail", Message: map[string]any{ "from": map[string]any{"name": "Alice", "wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826"}, "to": map[string]any{"name": "Bob", "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB"}, "contents": "Hello, Bob!", },}
sig, err := account.SignTypedData(typedData)if err != nil { log.Fatal(err)}Signing authorizations (EIP-7702)
Private key accounts can sign EIP-7702 authorization requests via SignAuthorization:
signedAuth, err := account.SignAuthorization(accounts.AuthorizationRequest{
Address: account.GetAddress(),
ChainId: 1,
Nonce: 0,
})
Parameters
privateKey
- Type:
string - Format: 32-byte hex, with or without
0xprefix (64 hex characters after optional prefix).
The private key must be valid secp256k1 (e.g. not zero, in range).
account, err := accounts.PrivateKeyToAccount("0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80")// oraccount, err := accounts.PrivateKeyToAccount("ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80")opts (optional)
- Type:
...PrivateKeyToAccountOptions
In viem-go, PrivateKeyToAccountOptions is a struct that can be extended later (e.g. nonce manager). Currently you can omit it or pass an empty struct.
Return type
- Go:
PrivateKeyToAccount(privateKey string, opts ...PrivateKeyToAccountOptions) (*PrivateKeyAccount, error) - Must variant:
MustPrivateKeyToAccount(privateKey string, opts ...PrivateKeyToAccountOptions) *PrivateKeyAccount— panics on error.
Error handling
Possible errors: ErrInvalidPrivateKey (invalid format or not valid secp256k1). viem-go does not define a separate ErrPrivateKeyLength; invalid length is reported as ErrInvalidPrivateKey.
account, err := accounts.PrivateKeyToAccount(privateKey)if err != nil { if errors.Is(err, accounts.ErrInvalidPrivateKey) { log.Println("Invalid private key format or value") return } log.Fatal(err)}