Blockchain development using Golang Web3 library

Introduction

Blockchain, as a distributed ledger technology, has achieved tremendous development in recent years. Golang, as an efficient and highly concurrency programming language, is widely used in blockchain development. In Golang, we can use the Web3 library to interact with Ethereum or other blockchain networks.

The Web3 library is a library of tools for interacting with the blockchain. It provides a set of APIs for communicating with the blockchain network and can perform various operations, such as querying account balances, sending transactions, deploying smart contracts, etc. This article will introduce how to use the Web3 library in Golang for blockchain development and provide some practical cases.

Install Web3 library

First, we need to install the Web3 library in the Golang environment. It can be installed using the following command:

go get github.com/ethereum/go-ethereum

This command will install the Web3 library in your GOPATH. After the installation is complete, you can introduce the Web3 library into your project:

import (
    "github.com/ethereum/go-ethereum"
)

Connect to the blockchain network

The first step in interacting with a blockchain using the Web3 library is to connect to the target blockchain network. The Web3 library provides an easy way to connect to mainnet, testnet or local blockchain. Here is a sample code showing how to connect to the Ethereum mainnet:

client, err := ethclient.Dial("https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID")
if err != nil {<!-- -->
    log.Fatal(err)
}

In the above code, we use the public node provided by Infura to connect to the Ethereum mainnet. You need to replace YOUR_INFURA_PROJECT_ID with your own Infura project ID.

Check account balance

After connecting to the blockchain network, we can use the Web3 library to query the balance of the account. The following sample code shows how to query the Ethereum balance of a specified address:

address := common.HexToAddress("0x5FbDB2315678afecb367f032d93F642f64180aa3")
balance, err := client.BalanceAt(context.Background(), address, nil)
if err != nil {<!-- -->
    log.Fatal(err)
}
fmt.Println(balance)

In the above code, we first convert the address into a format recognized by Ethereum, and then use the client.BalanceAt function to query the account balance. This function accepts a context object, an account address, and a block number parameter. If the block number is set to nil, the latest block is queried.

Send transaction

Sending transactions on the blockchain is a common operation. The Web3 library provides a convenient API to build and send transactions. The following sample code demonstrates how to send an Ethereum transaction:

fromAddress := common.HexToAddress("0x5FbDB2315678afecb367f032d93F642f64180aa3")
toAddress := common.HexToAddress("0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2")
nonce, err := client.PendingNonceAt(context.Background(), fromAddress)
if err != nil {<!-- -->
    log.Fatal(err)
}
value := big.NewInt(1000000000000000000) // 1 ether
gasLimit := uint64(21000)
gasPrice, err := client.SuggestGasPrice(context.Background())
if err != nil {<!-- -->
    log.Fatal(err)
}
tx := types.NewTransaction(nonce, toAddress, value, gasLimit, gasPrice, nil)
signedTx, err := types.SignTx(tx, types.HomesteadSigner{<!-- -->}, privateKey)
if err != nil {<!-- -->
    log.Fatal(err)
}
err = client.SendTransaction(context.Background(), signedTx)
if err != nil {<!-- -->
    log.Fatal(err)
}

In the above code, we first obtain the current nonce value of the sending account to ensure the order of the transaction. We then set the receiving address, transfer amount, gas limit, and gas price for the transaction. Next, we sign the transaction using the private key of the sending account and finally send the transaction via the client.SendTransaction function.

Deploy smart contracts

In blockchain development, smart contracts are very important components. The Web3 library provides APIs to deploy and interact with smart contracts. The following example code shows how to deploy a simple smart contract:

contract, err := bind.DeployContract(
    context.Background(),
    auth,
    contractABI,
    client,
    contractBin,
    big.NewInt(0),
    nil,
)
if err != nil {<!-- -->
    log.Fatalf("Failed to deploy contract: %v", err)
}
fmt.Println("Contract address:", contract.Address().Hex())

In the above code, we first prepare an ABI (Application Binary Interface) and bytecode containing the smart contract code. Then, we use the bind.DeployContract function to deploy the contract. This function accepts a context object, an account object, a smart contract’s ABI, a blockchain client, the smart contract’s bytecode, the value of ether, and constructor parameters.

Case

Case 1: Query ERC20 token balance

On Ethereum, many tokens are based on the ERC20 standard. We can use the Web3 library to query the balance of ERC20 tokens. Below is a sample code that shows how to query the ERC20 token balance of a specified account:

// Import the ABI of the ERC20 token contract
tokenABI, err := abi.JSON(strings.NewReader(TokenABI))
if err != nil {<!-- -->
    log.Fatal(err)
}

// Token contract address
contractAddress := common.HexToAddress("0xContractAddress")

// Query account address
address := common.HexToAddress("0xAccountAddress")

//Construct call data for querying balance
data, err := tokenABI.Pack("balanceOf", address)
if err != nil {<!-- -->
    log.Fatal(err)
}

//Build calling message
msg := ethereum.CallMsg{<!-- -->
    To: &contractAddress,
    Data: data,
}

// Call the contract method to query the balance
result, err := client.CallContract(context.Background(), msg, nil)
if err != nil {<!-- -->
    log.Fatal(err)
}

// Parse query results
var balance big.Int
err = tokenABI.UnpackIntoInterface( & amp;balance, "balanceOf", result)
if err != nil {<!-- -->
    log.Fatal(err)
}

fmt.Println("Token balance:", balance)

In the above code, we first import the ABI of the ERC20 token contract and convert the contract address and account address into a format recognized by Ethereum. Then, we use the token contract’s ABI to build the call data for querying the balance, and execute the call by calling the client.CallContract method. Finally, we parse the returned results and get the token balance.

Case 2: Monitoring blockchain events

Events on the blockchain are very important for building decentralized applications. We can use the Web3 library to listen to events on the blockchain. Here is a sample code showing how to listen for new block events on the Ethereum blockchain:

//Create a new subscription and listen for new block events
sub, err := client.SubscribeNewHead(context.Background(), make(chan *types.Header))
if err != nil {<!-- -->
    log.Fatal(err)
}

// Handle subscription events
for {<!-- -->
    select {<!-- -->
    case header := <-sub.Err():
        log.Fatal(header.Err())
    case header := <-sub.Chan():
        fmt.Println("New block:", header.Number)
    }
}

In the above code, we first create a new subscription object using the client.SubscribeNewHead function. Then, we use the select statement to handle the subscription event. When a new block event is received, we can perform some actions, such as updating the application’s state or triggering other events.

Case 3: Calling smart contract methods

In addition to deploying smart contracts, we can also use the Web3 library to call smart contract methods. Here is a sample code that shows how to call a simple smart contract method:

// Import the ABI of the smart contract
contractABI, err := abi.JSON(strings.NewReader(ContractABI))
if err != nil {<!-- -->
    log.Fatal(err)
}

//Smart contract address
contractAddress := common.HexToAddress("0xContractAddress")

// Construct the data for calling the method
data, err := contractABI.Pack("methodName", arg1, arg2)
if err != nil {<!-- -->
    log.Fatal(err)
}

//Build calling message
msg := ethereum.CallMsg{<!-- -->
    To: &contractAddress,
    Data: data,
}

// Call contract method
result, err := client.CallContract(context.Background(), msg, nil)
if err != nil {<!-- -->
    log.Fatal(err)
}

// Parse the call result
var returnValue string
err = contractABI.UnpackIntoInterface( & amp;returnValue, "methodName", result)
if err != nil {<!-- -->
    log.Fatal(err)
}

fmt.Println("Return value:", returnValue)

In the above code, we first import the ABI of the smart contract and convert the contract address into a format recognized by Ethereum. We then use the smart contract’s ABI to build the data for the calling method and execute the call by calling the client.CallContract method. Finally, we parse the returned results and get the return value of the method call.

Conclusion

In this article, we introduced how to use the Web3 library in Golang for blockchain development. We show how to connect to a blockchain network, query account balances, send transactions, and deploy smart contracts. Using the Web3 library, developers can easily interact with the blockchain and build powerful decentralized applications.

The Web3 library is not limited to Ethereum, but can also be used to interact with other blockchain networks, such as EOS, TRON, etc. By learning more about the Web3 library’s features and APIs, you can gain a better understanding of blockchain development and build more complex applications.

Note: The sample code in this article is for demonstration purposes only. In actual development, please ensure that your code is safe and reliable, and consider various possible exceptions.

References

  • Ethereum Developer Tools
  • Ethereum Development with Go
  • Golang Web3 library documentation