Creating a Bitcoin Address in Golang with btcd
Tags: go, bitcoin, tutorial, wallet
Published: 2024-01-30 15:30:30

Imagine bitcoin as digital cash. To receive it, you need a unique identifier called a bitcoin address. You can share this address publicly to receive payments. 
But how do you access and manage your Bitcoin? That's where a Bitcoin wallet comes in.
It's like a secure digital container that holds your keys and allows you to send bitcoin, receive bitcoin, and track how many bitcoins were sent to your address.

**What is a bitcoin address?**
A Bitcoin address is a unique identifier used to receive or send bitcoin in the Bitcoin network. 
You can use it to receive or request payments. It is typically a string of letters and numbers, and it plays a role similar to an account number in traditional banking. 
Keep in mind that a Bitcoin address is just one part of a Bitcoin wallet, which also includes private keys, which is a cryptographically generated random number that allows you to spend the bitcoin sent to your bitcoin addresses.

**Different types**
- Legacy Addresses (P2PKH): These are traditional Bitcoin addresses that start with a '1'. They are derived from the public key and are widely used. For example, a legacy address might look like: `1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2`.

- Segregated Witness (SegWit) Addresses (bech32 encoding format): SegWit is an upgrade to the Bitcoin protocol that makes various changes to the protocol one of such is introducing a new bitcoin address format called segwit addresses.
SegWit addresses have 32 characters, which comprise lowercase letters a-z and numbers 0-9, it starts with '3' and are more space-efficient, resulting in lower transaction fees. For example, a SegWit address might look like: `3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy`

A private key is a secret, alphanumeric string that allows you to access and control the funds associated with a specific public address.

**NB**:
Keep your private keys safe, like your regular wallet's pin.
Never share your private keys with anyone!

Let's dive into it
**Requirements**
Ensure you have go installed

on MacOs
`brew install go
`
Verify the installation 
`go version
`
on Windows:
- Download the MSI installer from the [official Golang 
  website](https://go.dev/doc/install).
- Run the installer and follow the installation prompts.
- Open a new Command Prompt or PowerShell window, and verify 
  the installation by running 
`go version`

**Step 1: Set Up Your Go Module**
a. Open your terminal.
b. Create a new folder for your project: 
`mkdir btc-wallet- generator`
c. Change into the project directory: 
`cd btc-wallet-generator`
d. Create a new Go module: 
`go mod init btc-wallet-generator`
e. Run `go mod tidy` to clean up and update dependencies.

**Step 2: Install Dependencies**
Run the following command to install the btcd library, which is used for wallet generation:
`go get github.com/btcsuite/btcd@v0.22.1`

**Step 3: Create main.go File**
Create a main.go file in your project folder and add the following content below:

```
package main

import (
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"

	"github.com/btcsuite/btcd/chaincfg"
	"github.com/btcsuite/btcd/btcec"
	"github.com/btcsuite/btcutil"
)
```

**Step 4: Write the Main Function**
```
func main() {
	createP2PKHAddress()
}
```

**Step 5: Generate P2PKH Address Function**
Add the createP2PKHAddress function to your main.go file:
```
func createP2PKHAddress() {
	// Choose the Bitcoin network (testnet in this case)
	params := &chaincfg.TestNet3Params

	// Generate a new private key
	privKey, err := btcec.NewPrivateKey(btcec.S256())
	if err != nil {
		log.Fatal(err)
	}

	// Get the corresponding public key
	pubKey := privKey.PubKey()

	// Create a P2PKH address
	addr, err := btcutil.NewAddressPubKeyHash(btcutil.Hash160(pubKey.SerializeCompressed()), params)
	if err != nil {
		log.Fatal(err)
	}

	// Display the generated address and private key
	fmt.Printf("| Public Address | %s |\n", addr.EncodeAddress())
	fmt.Printf("| Private Key     | %s |\n", hex.EncodeToString(privKey.Serialize()))

	// Save the wallet information to a JSON file
	wallet := map[string]string{
		"address":    addr.EncodeAddress(),
		"privateKey": hex.EncodeToString(privKey.Serialize()),
	}

// Serialize wallet information to JSON format with indentation
walletJSON, err := json.MarshalIndent(wallet, "", "    ")
if err != nil {
    log.Fatal(err)
}

// Write the serialized JSON to a file named "wallet.json" //with read-write permissions (0644)
err = ioutil.WriteFile("wallet.json", walletJSON, 0644)
if err != nil {
    log.Fatal(err)
}

// Print a message indicating that the wallet has been created //and saved to "wallet.json"
fmt.Println("Address created and saved to wallet.json")
}
```

**Step 6: Run the Program**
Run the following command in your terminal to compile and execute the Go program:
`go run main.go`

**Step 7: Check Your Address on Mempool**
The program will generate a public address and private key, save them to wallet.json, and display a message. Copy the generated address and visit [coinfaucet](https://coinfaucet.eu/en/btc-testnet/) to get free bitcoin which in this case is just for testing purposes. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/29lrof8b0gazt539sqio.png)

After receiving some funds, check your UTXO and other information on [mempool-testnet](https://mempool.space/testnet/address/mkVQwZz9WXBz7nuhQQLdqfa8xuz1kKX6Ht).

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ybhjl02pg3gtyqancq4c.png)

In conclusion, this article aims to guide developers through the process of setting up a development environment, using btcd, writing Golang code, and testing a basic Bitcoin address.