viem-goviem-go

Local Accounts

Private key, mnemonic, and HD accounts for signing transactions and messages locally

A Local Account is an account whose signing keys are stored on the consuming application's machine. It performs signing of transactions and messages with a private key before broadcasting over JSON-RPC.

There are three types of Local Accounts in viem-go:

For address-only (JSON-RPC) or custom signing sources, see Custom & address-only accounts.

Import

import "github.com/ChefBingbong/viem-go/accounts"

Common imports when using accounts with a Wallet Client:

  • accounts: Account constructors (PrivateKeyToAccount, MnemonicToAccount, HDKeyToAccount, ToAccountFromAddress, ToAccount) and types (CustomSource, HDOptions).
  • client / transport / chain: When wiring the account into a Wallet Client.

Instantiation

1. Initialize a Wallet Client

Set up a Wallet Client with a Chain and Transport (e.g. transport.HTTP).

import (
"github.com/ChefBingbong/viem-go/client"
"github.com/ChefBingbong/viem-go/client/transport"
"github.com/ChefBingbong/viem-go/chain/definitions"
)
walletClient, err := client.CreateWalletClient(client.WalletClientConfig{
Chain: definitions.Mainnet,
Transport: transport.HTTP("https://eth.llamarpc.com"),
})
if err != nil {
log.Fatal(err)
}
defer walletClient.Close()

2. Set up your Local Account

Create a Private Key Account (or use Mnemonic / HD).

import "github.com/ChefBingbong/viem-go/accounts"
account, err := accounts.PrivateKeyToAccount("0x...")
if err != nil {
log.Fatal(err)
}
walletClient, err := client.CreateWalletClient(client.WalletClientConfig{
Account: account,
Chain: definitions.Mainnet,
Transport: transport.HTTP("https://eth.llamarpc.com"),
})

3. Consume Wallet Actions

Use the account in Wallet Actions that require a signature (e.g. SendTransaction, SignMessage, SignTypedData).

import (
"github.com/ChefBingbong/viem-go/actions/wallet"
"github.com/ChefBingbong/viem-go/chain/definitions"
)
hash, err := walletClient.SendTransaction(ctx, wallet.SendTransactionParameters{
Account: walletClient.Account(),
Chain: definitions.Mainnet,
To: "0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC",
Value: big.NewInt(1e15), // 0.001 ETH
})
if err != nil {
log.Fatal(err)
}

4. Optional: Hoist the Account

You can pass the account once when creating the Wallet Client so you don't pass it to every action. Use walletClient.Account() where an account is required.

account, _ := accounts.PrivateKeyToAccount("0x...")
walletClient, err := client.CreateWalletClient(client.WalletClientConfig{
Account: account,
Chain: definitions.Mainnet,
Transport: transport.HTTP("https://eth.llamarpc.com"),
})
if err != nil {
log.Fatal(err)
}
// Later: use walletClient.Account() in actions
hash, err := walletClient.SendTransaction(ctx, wallet.SendTransactionParameters{
Account: walletClient.Account(),
To: "0x...",
Value: big.NewInt(1e15),
})

5. Optional: Use with Public Client

When using a Local Account, you often need both read (e.g. balance, nonce) and write (send transaction). In viem-go you can use a Public Client for reads and the Wallet Client for writes, or extend your flow with public actions as needed.

With a local account, the client signs transactions locally and sends them via eth_sendRawTransaction — private keys are never sent to the RPC node.

Account types

TypeDescription
LocalPrivate key (or derived key) held in process; signs before sending (Private Key, Mnemonic, HD, Custom).
JSON-RPCAddress only; signing is delegated to the node/wallet over JSON-RPC. Use ToAccountFromAddress or client.NewAddressAccount for Wallet Client.

Local account capabilities

Local accounts can:

OperationMethod
Sign hashaccount.Sign(hash)
Sign message (EIP-191)account.SignMessage(message)
Sign transactionaccount.SignTransaction(tx)
Sign typed data (EIP-712)account.SignTypedData(data)
Sign authorization (EIP-7702)account.SignAuthorization(auth)

Account properties (Go)

// LocalAccount (and *PrivateKeyAccount, *HDAccount)
account.GetAddress()  // "0x..." — checksummed address
account.Addr          // same as GetAddress(), struct field
account.GetPublicKey() // "0x04..." — uncompressed public key (empty for custom without key)
account.GetSource()   // "privateKey", "hd", "mnemonic", "custom"
account.GetType()     // "local"

// HDAccount only
hdAccount.GetHdKey()  // underlying HDKey for derivation

Go notes

  • Errors: Account constructors return (account, error). Use Must* variants (e.g. MustPrivateKeyToAccount) to panic on error.
  • Context: Wallet actions take context.Context as the first argument for cancellation and timeouts.

Security

Never commit private keys or mnemonics to source control. Use environment variables or a secure key management system in production.

import "os"

privateKey := os.Getenv("PRIVATE_KEY")
if privateKey == "" {
    log.Fatal("PRIVATE_KEY not set")
}
account, err := accounts.PrivateKeyToAccount(privateKey)