Ethereum Development with Golang
Last Updated :
01 Jun, 2023
Ethereum is a blockchain-based platform that enables developers to create decentralized applications (dApps) and smart contracts. Ethereum's native cryptocurrency is Ether (ETH), which is used to pay transaction fees and incentivize miners to secure the network.
Go, also known as Golang, is a programming language developed by Google. It is a compiled language that is designed to be efficient, concise, and easy to use. Go is often used for building web applications, network servers, and other types of software that require high performance.
Getting Started with Go-Ethereum
Ethereum Go, also known as Geth, is the official Go implementation of the Ethereum protocol. Geth provides a command-line interface (CLI) for interacting with the Ethereum network, as well as an API for building decentralized applications. The relationship between Ethereum and Go is that Geth is one of the software clients that can connect to the Ethereum network. Developers can use Geth to interact with the Ethereum network and build decentralized applications using the Go programming language.
Applications of Ethereum Go include building decentralized applications, interacting with smart contracts, and deploying and managing Ethereum nodes. The Ethereum network has a wide range of use cases, including decentralized finance (DeFi), non-fungible tokens (NFTs), and supply chain management.
Prerequisites
1. Go programming language: Install Go by following the official installation guide for your operating system.
2. Go-Ethereum (Geth): To use Ethereum Go, first install Geth on your computer. You can download Geth from the official Ethereum website.
3. Infura Account: Sign up for an account on Infura to obtain an API key. Infura allows us to connect to Ethereum nodes without setting up our own infrastructure.
Connecting to an Ethereum Node using Infura and Go
Step 1: After we have installed go-ethereum, create a new Go module for your project by running the following command:
go mod init <module-name>
Step 2: Import the required packages for interacting with Ethereum using Geth.
import (
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/ethclient"
)
Step 3: Go to the Infuara website and create an account and then head to your Ethereum dashboard.
Step 3: Click on create project button and add the name of the project. Copy the mainnet link of the Ethereum shown in the picture below. Proceed with the following code in the editor and use the link for a variable.
Step 4: Instantiate a new Ethereum client by providing the Infura endpoint and your Infura API key. Replace YOUR_INFURA_API_KEY with your actual Infura API key.
Go
endpoint := "https://mainnet.infura.io/v3/YOUR_INFURA_API_KEY"
client, err := ethclient.Dial(endpoint)
if err != nil {
log.Fatal(err)
}
Step 5: Once the connection is established, you can start interacting with the Ethereum node using the client object. For example, you can query the latest block number.
Go
blockNumber, err := client.BlockNumber(context.Background())
if err != nil {
log.Fatal(err)
}
fmt.Println("Latest Block Number:", blockNumber)
Code:
Go
package main
import (
"context"
"fmt"
"log"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/ethclient"
)
func main() {
// Initialize the Go module with the specified module name
err := goModInit("module-name")
if err != nil {
log.Fatal(err)
}
// Set the endpoint for the Ethereum client
endpoint := "https://mainnet.infura.io/v3/YOUR_INFURA_API_KEY"
// Connect to the Ethereum client
client, err := ethclient.Dial(endpoint)
if err != nil {
log.Fatal(err)
}
// Get the latest block number
blockNumber, err := client.BlockNumber(context.Background())
if err != nil {
log.Fatal(err)
}
// Print the latest block number
fmt.Println("Latest Block Number:", blockNumber)
}
// goModInit initializes the Go module with the specified module name
func goModInit(moduleName string) error {
// Command: go mod init <module-name>
cmd := exec.Command("go", "mod", "init", moduleName)
// Run the command and check for any errors
err := cmd.Run()
if err != nil {
return err
}
return nil
}
Note:
To run this code, you need to replace "YOUR_INFURA_API_KEY" with your actual Infura API key.
Output:
Once you have got the API key your output might look like this:
Querying Ethereum Wallet Balances with Geth
Step 1: Import the required packages:
import (
"context"
"fmt"
"log"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
)
Step 2: Copy your address from Infura as shown in the above picture and then in the code define the Ethereum address for which you want to query the balance:
address := common.HexToAddress("0xYOUR_ADDRESS")
Note:
Replace 0xYOUR_ADDRESS with the actual Ethereum address.
Step 3: You can now query the balance of your Ethereum address using the below code snippet function where we are setting up the Ethereum client connection and then returning the balance of your account.
Go
balance, err := client.BalanceAt(context.Background(), address, nil)
if err != nil {
log.Fatal(err)
}
fmt.Println("Wallet Balance:", balance)
Code:
Go
package main
import (
"context"
"fmt"
"log"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
)
func main() {
// Ethereum client connection setup
client, err := ethclient.Dial("https://mainnet.infura.io/v3/YOUR_INFURA_API")
if err != nil {
log.Fatal(err)
}
// Ethereum address to check balance
address := common.HexToAddress("0xYOUR_ADDRESS")
// Retrieve the wallet balance
balance, err := client.BalanceAt(context.Background(), address, nil)
if err != nil {
log.Fatal(err)
}
// Print the wallet balance
fmt.Println("Wallet Balance:", balance)
}
Output: Once you have entered your address and infura API in the above code your output might look like this:
Note:
The wallet balance is in wei the smallest unit of Ether.
Creating an Ethereum Wallet with Go-Ethereum
Step 1: We begin by importing all the important packages:
import (
"context"
"fmt"
"log"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
)
Step 2: Generate a new Ethereum account by creating a new private key and deriving the corresponding public key and address. In this code, we generate a new private key using crypto.GenerateKey() function. If there's an error, the program exits with a fatal error log message.
Go
privateKey, err := crypto.GenerateKey()
if err != nil {
log.Fatal(err)
}
publicKey := privateKey.Public()
publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
if !ok {
log.Fatal("Error casting public key to ECDSA")
}
address := crypto.PubkeyToAddress(*publicKeyECDSA)
Step 3: Print the newly created Ethereum address:
fmt.Println("New Wallet Address:", address.Hex())
Code:
Go
package main
import (
"context"
"crypto/ecdsa"
"fmt"
"log"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
)
func main() {
// Generate a new private key
privateKey, err := crypto.GenerateKey()
if err != nil {
log.Fatal(err)
}
// Obtain the public key from the generated private key
publicKey := privateKey.Public()
publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
if !ok {
log.Fatal("Error casting public key to ECDSA")
}
// Derive the Ethereum address from the public key
address := crypto.PubkeyToAddress(*publicKeyECDSA)
fmt.Println("New Wallet Address:", address.Hex())
// Other Ethereum-related operations can be performed here
// Example: Connect to an Ethereum client (such as Infura)
// Replace "<YOUR_INFURA_API_KEY>" with your actual Infura API key
infuraAPIKey := "<YOUR_INFURA_API_KEY>"
client, err := ethclient.Dial("https://mainnet.infura.io/v3/" + infuraAPIKey)
if err != nil {
log.Fatal(err)
}
// Other Ethereum operations using the client can be performed here
}
Output: Once you have entered your address and infura API in the above code your output might look like this:
Making Ethereum Transactions in Go using Go-Ethereum
Step 1: Import the following required packages to do this.
import (
"context"
"log"
"github.com/ethereum/go-ethereum/ethclient"
)
Step 2: We will create a new transaction by specifying the recipient address, value, gas price, gas limit, and nonce in the go code. Also, replace YOUR_PRIVATE_KEY with the private key of the account making the transaction and 0xRECIPIENT_ADDRESS with the recipient's Ethereum address.
Go
privateKey, err := crypto.HexToECDSA("YOUR_PRIVATE_KEY")
if err != nil {
log.Fatal(err)
}
publicKey := privateKey.Public()
publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
if !ok {
log.Fatal("Error casting public key to ECDSA")
}
fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA)
toAddress := common.HexToAddress("0xRECIPIENT_ADDRESS")
value := big.NewInt(1000000000000000000) // 1 ETH in Wei
gasLimit := uint64(21000)
gasPrice := big.NewInt(30000000000) // 30 Gwei
nonce, err := client.PendingNonceAt(context.Background(), fromAddress)
if err != nil {
log.Fatal(err)
}
tx := types.NewTransaction(nonce, toAddress, value, gasLimit, gasPrice, nil)
Step 3: Sign the transaction using the private key by replacing chainID with the appropriate chain ID and send it to the Ethereum network.
Go
//Sing the transaction
signedTx, err := types.SignTx(tx, types.NewEIP155Signer(chainID), privateKey)
if err != nil {
log.Fatal(err)
}
//Send it to the ethereum network
err = client.SendTransaction(context.Background(), signedTx)
if err != nil {
log.Fatal(err)
}
Code:
C++
package main
import (
"context"
"fmt"
"io/ioutil"
"log"
"math/big"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
)
var (
url = "https://kovan.infura.io/v3/0c7b3f204f37416388610fb274b0452c"
murl = "https://mainnet.infura.io/v3/0c7b3f204f37416388610fb274b0452c"
)
func main() {
// ks := keystore.NewKeyStore("./wallet", keystore.StandardScryptN, keystore.StandardScryptP)
// _, err := ks.NewAccount("password")
// if err != nil {
// log.Fatal(err)
// }
// _, err = ks.NewAccount("password")
// if err != nil {
// log.Fatal(err)
// }
// "1f7ecea2fa83cc4a7de969f11d16a40edf9023d7"
// "1e41ca1ccfc06597525c966a986b35a09e22358d"
client, err := ethclient.Dial(url)
if err != nil {
log.Fatal(err)
}
defer client.Close()
a1 := common.HexToAddress("c393967d7b4b7fd02e697d13085d645c9412af11")
a2 := common.HexToAddress("1e41ca1ccfc06597525c966a986b35a09e22358d")
b1, err := client.BalanceAt(context.Background(), a1, nil)
if err != nil {
log.Fatal(err)
}
b2, err := client.BalanceAt(context.Background(), a2, nil)
if err != nil {
log.Fatal(err)
}
fmt.Println("Balance 1:", b1)
fmt.Println("Balance 2:", b2)
nonce, err := client.PendingNonceAt(context.Background(), a1)
if err != nil {
log.Fatal(err)
}
// 1 ether = 1000000000000000000 wei
amount := big.NewInt(100000000000000000)
gasPrice, err := client.SuggestGasPrice(context.Background())
if err != nil {
log.Fatal(err)
}
tx := types.NewTransaction(nonce, a2, amount, 21000, gasPrice, nil)
chainID, err := client.NetworkID(context.Background())
if err != nil {
log.Fatal(err)
}
b, err := ioutil.ReadFile("wallet/UTC--2021-05-24T16-47-26.459903259Z--c393967d7b4b7fd02e697d13085d645c9412af11")
if err != nil {
log.Fatal(err)
}
key, err := keystore.DecryptKey(b, "password")
if err != nil {
log.Fatal(err)
}
tx, err = types.SignTx(tx, types.NewEIP155Signer(chainID), key.PrivateKey)
if err != nil {
log.Fatal(err)
}
err = client.SendTransaction(context.Background(), tx)
if err != nil {
log.Fatal(err)
}
fmt.Printf("tx sent: %s", tx.Hash().Hex())
}
Output: After you have added your Infura API key to the above code and the correct addresses of the sender and receiver.
Querying the Number of Transactions in a Block
Step 1: Import the following required packages to do this.
import (
"context"
"log"
"github.com/ethereum/go-ethereum/ethclient"
)
Step 2: Set up and create a client with the following GO code.
Go
package main
import (
"context"
"log"
"github.com/ethereum/go-ethereum/ethclient"
)
func main() {
client, err := ethclient.DialContext(context.Background(), )
}
Step 3: Proceed with the following code in the editor and use the link for a variable.
Go
package main
import (
"context"
"log"
"github.com/ethereum/go-ethereum/ethclient"
)
var infuraURL = "https://mainnet.infura.io/v3/INFURA_API_KEY"
func main() {
client, err := ethclient.DialContext(context.Background(), infuraURL)
if err != nil {
log.Fatalf("Error in creating an ether client: %v", err)
}
defer client.Close()
Step 4: After creating the client let's use it to get the Ethereum block number. Note that if you don't mention the block number you will automatically be given the last mined block's number.
Go
package main
import (
"context"
"log"
"github.com/ethereum/go-ethereum/ethclient"
)
var infuraURL = "https://mainnet.infura.io/v3/81888237d633446c976203dcf922d861"
func main() {
client, err := ethclient.DialContext(context.Background(), infuraURL)
if err != nil {
log.Fatalf("Error in creating an ether client: %v", err)
}
defer client.Close()
block,err:= client.BlockByNumber(context.Background(),nil)
if err != nil {
log.Fatalf("Error to get a block: %v", err)
}
fmt.Println(block.Number())
Step 5: Run the code on the terminal
Output:
In my and your case, it could differ depending on the current block being used in the network. Running the code at different intervals will generate different block numbers.
Querying Details of Transactions in a Block
Step 1: Import the following required packages to do this.
import (
"context"
"log"
"github.com/ethereum/go-ethereum/ethclient"
)
Step 2: Connect to the Ethereum node and specify the block number for which you want to query the transaction details.
blockNumber := uint64(1234567) // Replace with the desired block number
Step 3: Retrieve the block containing the transactions and iterate over the transactions in the block and print their details. We will look at the details like the transaction hash, from to addresses, gas price, nonce, etc.
Go
block, err := client.BlockByNumber(context.Background(), big.NewInt(int64(blockNumber)))
if err != nil {
log.Fatal(err)
}
for _, tx := range block.Transactions() {
fmt.Println("Transaction Hash:", tx.Hash().Hex())
fmt.Println("From:", tx.From().Hex())
fmt.Println("To:", tx.To().Hex())
fmt.Println("Value:", tx.Value().String())
fmt.Println("Gas Limit:", tx.Gas())
fmt.Println("Gas Price:", tx.GasPrice().String())
fmt.Println("Nonce:", tx.Nonce())
fmt.Println("Data:", tx.Data())
fmt.Println("-----------------------------------")
}
Code:
Go
package main
import (
"context"
"fmt"
"log"
"math/big"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
)
func main() {
// Ethereum node endpoint
nodeURL := "https://mainnet.infura.io/v3/your_infura_project_id"
// Create an Ethereum client instance
client, err := ethclient.Dial(nodeURL)
if err != nil {
log.Fatal(err)
}
// Specify the block number to retrieve
blockNumber := uint64(1234567)
// Retrieve the block using the block number
block, err := client.BlockByNumber(context.Background(), big.NewInt(int64(blockNumber)))
if err != nil {
log.Fatal(err)
}
// Iterate over the transactions in the block
for _, tx := range block.Transactions() {
fmt.Println("Transaction Hash:", tx.Hash().Hex())
fmt.Println("From:", tx.From().Hex())
fmt.Println("To:", tx.To().Hex())
fmt.Println("Value:", tx.Value().String())
fmt.Println("Gas Limit:", tx.Gas())
fmt.Println("Gas Price:", tx.GasPrice().String())
fmt.Println("Nonce:", tx.Nonce())
fmt.Println("Data:", tx.Data())
fmt.Println("-----------------------------------")
}
}
Output: After you have added the Infura API key in the code you will get a similar output.
Similar Reads
Go Tutorial Go or you say Golang is a procedural and statically typed programming language having the syntax similar to C programming language. It was developed in 2007 by Robert Griesemer, Rob Pike, and Ken Thompson at Google but launched in 2009 as an open-source programming language and mainly used in Google
2 min read
Overview
Go Programming Language (Introduction)Go is a procedural programming language. It was developed in 2007 by Robert Griesemer, Rob Pike, and Ken Thompson at Google but launched in 2009 as an open-source programming language. Programs are assembled by using packages, for efficient management of dependencies. This language also supports env
11 min read
How to Install Go on Windows?Prerequisite: Introduction to Go Programming Language Before, we start with the process of Installing Golang on our System. We must have first-hand knowledge of What the Go Language is and what it actually does? Go is an open-source and statically typed programming language developed in 2007 by Robe
3 min read
How to Install Golang on MacOS?Before, we start with the process of Installing Golang on our System. We must have first-hand knowledge of What the Go Language is and what it actually does? Go is an open-source and statically typed programming language developed in 2007 by Robert Griesemer, Rob Pike, and Ken Thompson at Google but
4 min read
Hello World in GolangHello, World! is the first basic program in any programming language. Letâs write the first program in the Go Language using the following steps:First of all open Go compiler. In Go language, the program is saved with .go extension and it is a UTF-8 text file.Now, first add the package main in your
3 min read
Fundamentals
Identifiers in Go LanguageIn programming languages, identifiers are used for identification purposes. In other words, identifiers are the user-defined names of the program components. In the Go language, an identifier can be a variable name, function name, constant, statement label, package name, or type. Example: package ma
3 min read
Go KeywordsKeywords or Reserved words are the words in a language that are used for some internal process or represent some predefined actions. These words are therefore not allowed to use as an identifier. Doing this will result in a compile-time error. Example: C // Go program to illustrate the // use of key
2 min read
Data Types in GoData types specify the type of data that a valid Go variable can hold. In Go language, the type is divided into four categories which are as follows: Basic type: Numbers, strings, and booleans come under this category.Aggregate type: Array and structs come under this category.Reference type: Pointer
7 min read
Go VariablesA typical program uses various values that may change during its execution. For Example, a program that performs some operations on the values entered by the user. The values entered by one user may differ from those entered by another user. Hence this makes it necessary to use variables as another
9 min read
Constants- Go LanguageAs the name CONSTANTS suggests, it means fixed. In programming languages also it is same i.e., once the value of constant is defined, it cannot be modified further. There can be any basic data type of constants like an integer constant, a floating constant, a character constant, or a string literal.
6 min read
Go OperatorsOperators are the foundation of any programming language. Thus the functionality of the Go language is incomplete without the use of operators. Operators allow us to perform different kinds of operations on operands. In the Go language, operators Can be categorized based on their different functiona
9 min read
Control Statements
Functions & Methods
Functions in Go LanguageIn Go, functions are blocks of code that perform specific tasks, which can be reused throughout the program to save memory, improve readability, and save time. Functions may or may not return a value to the caller.Example:Gopackage main import "fmt" // multiply() multiplies two integers and returns
3 min read
Variadic Functions in GoVariadic functions in Go allow you to pass a variable number of arguments to a function. This feature is useful when you donât know beforehand how many arguments you will pass. A variadic function accepts multiple arguments of the same type and can be called with any number of arguments, including n
3 min read
Anonymous function in Go LanguageAn anonymous function is a function that doesnât have a name. It is useful when you want to create an inline function. In Go, an anonymous function can also form a closure. An anonymous function is also known as a function literal.ExampleGopackage main import "fmt" func main() { // Anonymous functio
2 min read
main and init function in GolangThe Go language reserve two functions for special purpose and the functions are main() and init() function.main() functionIn Go language, the main package is a special package which is used with the programs that are executable and this package contains main() function. The main() function is a spec
2 min read
What is Blank Identifier(underscore) in Golang?_(underscore) in Golang is known as the Blank Identifier. Identifiers are the user-defined name of the program components used for the identification purpose. Golang has a special feature to define and use the unused variable using Blank Identifier. Unused variables are those variables that are defi
3 min read
Defer Keyword in GolangIn Go language, defer statements delay the execution of the function or method or an anonymous method until the nearby functions returns. In other words, defer function or method call arguments evaluate instantly, but they don't execute until the nearby functions returns. You can create a deferred m
3 min read
Methods in GolangGo methods are like functions but with a key difference: they have a receiver argument, which allows access to the receiver's properties. The receiver can be a struct or non-struct type, but both must be in the same package. Methods cannot be created for types defined in other packages, including bu
3 min read
Structure
Arrays
Slices
Slices in GolangSlices in Go are a flexible and efficient way to represent arrays, and they are often used in place of arrays because of their dynamic size and added features. A slice is a reference to a portion of an array. It's a data structure that describes a portion of an array by specifying the starting index
14 min read
Slice Composite Literal in GoThere are two terms i.e. Slice and Composite Literal. Slice is a composite data type similar to an array which is used to hold the elements of the same data type. The main difference between array and slice is that slice can vary in size dynamically but not an array. Composite literals are used to c
3 min read
How to sort a slice of ints in Golang?In Go, slices provide a flexible way to manage sequences of elements. To sort a slice of ints, the sort package offers a few straightforward functions. In this article we will learn How to Sort a Slice of Ints in Golang.ExampleGopackage main import ( "fmt" "sort" ) func main() { intSlice := []int{42
2 min read
How to trim a slice of bytes in Golang?In Go language slice is more powerful, flexible, convenient than an array, and is a lightweight data structure. The slice is a variable-length sequence which stores elements of a similar type, you are not allowed to store different type of elements in the same slice. In the Go slice of bytes, you ar
3 min read
How to split a slice of bytes in Golang?In Golang, you can split a slice of bytes into multiple parts using the bytes.Split function. This is useful when dealing with data like encoded strings, file contents, or byte streams that must be divided by a specific delimiter.Examplepackage mainimport ( "bytes" "fmt")func main() { // Initial byt
3 min read
Strings
Strings in GolangIn the Go language, strings are different from other languages like Java, C++, Python, etc. It is a sequence of variable-width characters where every character is represented by one or more bytes using UTF-8 Encoding. In other words, strings are the immutable chain of arbitrary bytes(including bytes
7 min read
How to Trim a String in Golang?In Go, strings are UTF-8 encoded sequences of variable-width characters, unlike some other languages like Java, python and C++. Go provides several functions within the strings package to trim characters from strings.In this article we will learn how to Trim a String in Golang.Examples := "@@Hello,
2 min read
How to Split a String in Golang?In Go language, strings differ from other languages like Java, C++, and Python. A string in Go is a sequence of variable-width characters, with each character represented by one or more bytes using UTF-8 encoding. In Go, you can split a string into a slice using several functions provided in the str
3 min read
Different ways to compare Strings in GolangIn Go, strings are immutable sequences of bytes encoded in UTF-8. You can compare them using comparison operators or the strings.Compare function. In this article,we will learn different ways to compare Strings in Golang.Examplepackage main import ( "fmt" "strings" ) func main() { s1 := "Hello" s2 :
2 min read
Pointers