This guide provides a step-by-step explanation of how to transfer ETH tokens and query balances on a locally hosted Ethereum private blockchain using Go and the go-ethereum
library.
Core Concepts
1. Private Blockchain Basics
- A private Ethereum blockchain allows controlled access and customization of network rules.
- Transactions are validated only by designated nodes, eliminating the need for gas fees in test environments.
2. Key Components
- Keystore Files: Encrypted wallet files storing private keys (e.g.,
UTC--2020-05-26T03-30-15.678995000Z--d8e670...
). - Web3 Providers: Local RPC endpoints (e.g.,
http://127.0.0.1:8545
) connect your application to the blockchain node. - Wei and ETH: The smallest denomination (1 ETH = 10¹⁸ wei).
👉 Learn how to set up a private Ethereum network
Step-by-Step Implementation
1. Initialize Account and Client
“`go
type accountBody struct {
File string
Passwd string
Address string
}
func newAccount(file string) *accountBody {
return &accountBody{
File: file,
Passwd: “111111”, // Default password for demo
}
}
func newClient(rawurl string) *clientManage {
rpcDial, err := rpc.Dial(rawurl)
if err != nil { panic(err) }
return &clientManage{
ethConn: ethclient.NewClient(rpcDial),
}
}
“`
2. Query ETH Balances
“`go
func (ec *clientManage) getBalance(address string) (string, error) {
account := common.HexToAddress(address)
balance, err := ec.ethConn.BalanceAt(context.Background(), account, nil)
if err != nil { return “”, err }
// Convert wei to ETH
fbalance := new(big.Float).SetInt(balance)
ethValue := new(big.Float).Quo(fbalance, big.NewFloat(math.Pow10(18)))
return ethValue.String(), nil
}
“`
3. Transfer ETH Between Accounts
“`go
func (ec clientManage) transferEth(pk, fromAddress, toAddress string, weiValue big.Int) (string, error) {
privateKey, err := crypto.HexToECDSA(pk)
if err != nil { log.Fatal(err) }
nonce, err := ec.ethConn.PendingNonceAt(context.Background(), common.HexToAddress(fromAddress))
if err != nil { log.Fatal(err) }
tx := types.NewTransaction(
nonce,
common.HexToAddress(toAddress),
weiValue,
21000, // Gas limit
big.NewInt(1), // Gas price (adjust for private chains)
nil,
)
signedTx, err := types.SignTx(tx, types.NewEIP155Signer(big.NewInt(150)), privateKey)
if err := ec.ethConn.SendTransaction(context.Background(), signedTx); err != nil {
log.Fatal(err)
}
return signedTx.Hash().Hex(), nil
}
“`
👉 Explore advanced blockchain development tools
Key Functions Explained
Function | Purpose |
---|---|
keyStoreToPrivateKey() |
Decrypts keystore files to extract private keys and addresses. |
EthToWei() |
Converts ETH values to wei for precise transactions. |
getBalance() |
Fetches the ETH balance of a given address from the blockchain state. |
FAQs
1. Why use a private blockchain for testing?
- Avoids real gas costs and provides deterministic environments for debugging.
2. How do I generate a keystore file?
- Use Geth or MetaMask to create wallets. Keystores are typically stored in
./wallets/
.
3. What’s the role of chainID
in signing?
- Prevents replay attacks. For private chains, this is arbitrary (e.g.,
150
in the example).
4. How to handle transaction failures?
- Check gas limits, nonce values, and network connectivity. Private chains often skip gas validation.
5. Can I use this for mainnet transactions?
- Yes, but replace test parameters (e.g., gas price, chainID) with mainnet-compatible values.
Best Practices
- Security: Never hardcode passwords or private keys in production code.
- Error Handling: Implement robust checks for RPC connectivity and transaction receipts.
- Testing: Use tools like Ganache for local blockchain simulations.
By following this guide, you’ll master ETH transactions and balance queries on private networks, a foundational skill for blockchain developers. 🚀