Table of Contents
- Introduction
- Prerequisites
- Setup
-
Creating a Command-Line Bitcoin Wallet - Initializing the Wallet - Generating a Bitcoin Address - Displaying Wallet Balance - Sending Bitcoin
- Conclusion
Introduction
In this tutorial, we will develop a command-line Bitcoin wallet using Go programming language. The purpose of this tutorial is to provide a hands-on experience in building a basic Bitcoin wallet with functionalities such as generating a Bitcoin address, checking wallet balance, and sending Bitcoin transactions.
By the end of this tutorial, you will be able to create your own command-line Bitcoin wallet and perform basic wallet operations using Go.
Prerequisites
To follow along with this tutorial, you should have basic knowledge of Go programming language, including variables, functions, loops, and error handling. Additionally, you should have Go installed on your machine.
Setup
Before we start building our command-line Bitcoin wallet, let’s ensure we have the necessary setup in place.
-
Install Go by following the official installation guide for your operating system: Go Installation Guide
-
Verify the Go installation by opening a terminal and running the following command:
go version
If the installation is successful, it should display the installed Go version.
Creating a Command-Line Bitcoin Wallet
Initializing the Wallet
Let’s begin by creating a new Go project for our Bitcoin wallet. Open a terminal and navigate to the desired directory where you want to create your project.
-
Create a new directory for the project:
mkdir bitcoin-wallet cd bitcoin-wallet
-
Initialize a new Go module for our project:
go mod init github.com/your-username/bitcoin-wallet
Make sure to replace
your-username
with your actual GitHub username or any other preferred username. -
Create a new Go file named
wallet.go
and open it in a text editor.touch wallet.go
Now we have our project setup ready to start building the Bitcoin wallet.
Generating a Bitcoin Address
To generate a Bitcoin address, we will use a Go package named btcd
. This package provides a set of functions for working with Bitcoin.
-
Import the required packages at the beginning of
wallet.go
file:package main import ( "fmt" "github.com/btcsuite/btcutil" )
-
Define a function named
generateAddress
that will generate a Bitcoin address:func generateAddress() { // Generate a new private key privateKey, err := btcutil.NewPrivateKey(btcutil.Secp256k1) if err != nil { fmt.Println("Error generating private key:", err) return } // Derive the corresponding public key publicKey := privateKey.PubKey() // Convert public key to Bitcoin address address, err := btcutil.NewAddressPubKey(publicKey.SerializeUncompressed(), &btcutil.MainNetParams) if err != nil { fmt.Println("Error generating Bitcoin address:", err) return } // Display the generated Bitcoin address fmt.Println("Generated Bitcoin Address:", address.EncodeAddress()) }
Here, we use the
btcutil.NewPrivateKey
function to generate a new private key,privateKey.PubKey()
to derive the public key, andbtcutil.NewAddressPubKey
to convert the public key to a Bitcoin address. -
Inside the
main
function, call thegenerateAddress
function:func main() { fmt.Println("Welcome to the Bitcoin Wallet!") generateAddress() }
-
Save and close the
wallet.go
file.Now, if you run
go run wallet.go
in the terminal, it will display the generated Bitcoin address.
Displaying Wallet Balance
To display the wallet balance, we will use a simple API provided by a public blockchain explorer.
-
Import the necessary packages:
package main import ( "fmt" "github.com/btcsuite/btcutil" "io/ioutil" "net/http" )
-
Define a function named
getBalance
that will fetch the wallet balance:func getBalance(address string) { url := fmt.Sprintf("https://blockchain.info/q/addressbalance/%s", address) response, err := http.Get(url) if err != nil { fmt.Println("Error fetching balance:", err) return } defer response.Body.Close() body, err := ioutil.ReadAll(response.Body) if err != nil { fmt.Println("Error reading response body:", err) return } fmt.Println("Wallet Balance:", string(body)) }
Here, we use the
http.Get
function to send a GET request to the blockchain explorer API. We read the response body and display the wallet balance. -
Modify the
main
function to call thegetBalance
function with a specific address:func main() { fmt.Println("Welcome to the Bitcoin Wallet!") address := "YOUR_BITCOIN_ADDRESS" generateAddress() getBalance(address) }
Make sure to replace
YOUR_BITCOIN_ADDRESS
with the actual Bitcoin address you generated. -
Save and close the
wallet.go
file.Now, when you run
go run wallet.go
, it will display both the generated Bitcoin address and the wallet balance.
Sending Bitcoin
To send Bitcoin from our wallet, we will use a public Bitcoin testnet provided by the go-bitcoin
package.
-
Import the required packages:
package main import ( "fmt" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil/hdkeychain" "log" )
-
Define a function named
sendBitcoin
that will send Bitcoin from the wallet:func sendBitcoin(seedPhrase []string, amount int64, toAddress string) { // Create a wallet from the seed phrase masterKey, err := hdkeychain.NewMaster(parseSeedPhrase(seedPhrase), &chaincfg.TestNet3Params) if err != nil { log.Fatal("Error creating wallet:", err) } // Derive the account key accountKey, err := masterKey.Child(hdkeychain.HardenedKeyStart + 0) if err != nil { log.Fatal("Error deriving account key:", err) } // Derive the external address key addressKey, err := accountKey.Child(0) if err != nil { log.Fatal("Error deriving address key:", err) } // Get the public key associated with the address publicKey, err := addressKey.ECPubKey() if err != nil { log.Fatal("Error getting public key:", err) } // Convert the public key to a Bitcoin address address, err := publicKey.Address(&chaincfg.TestNet3Params) if err != nil { log.Fatal("Error generating Bitcoin address:", err) } // Create a new transaction transaction := btcutil.NewTx(nil) // Set the recipient address to, err := btcutil.DecodeAddress(toAddress, &chaincfg.TestNet3Params) if err != nil { log.Fatal("Error decoding recipient address:", err) } pkScript, err := btcutil.PayToAddrScript(to) if err != nil { log.Fatal("Error creating pay-to-address script:", err) } outpoint := wire.NewOutPoint(&chainhash.Hash{}, math.MaxUint32) txOut := wire.NewTxOut(amount, pkScript) txIn := wire.NewTxIn(outpoint, nil, nil) tx := wire.NewMsgTx(wire.TxVersion) tx.AddTxIn(txIn) tx.AddTxOut(txOut) // Sign the transaction sigScript, err := addressKey.Sign(tx.SignatureHash(0, sigHashNone), txscript.SigHashAll, publicKey.Serialize()) if err != nil { log.Fatal("Error signing transaction:", err) } txIn.SignatureScript = sigScript // Send the transaction txHash, err := client.SendRawTransaction(tx, true) if err != nil { log.Fatal("Error sending transaction:", err) } fmt.Println("Successfully sent Bitcoin with transaction hash:", txHash) }
Here, we use the
hdkeychain.NewMaster
function to create a wallet from the seed phrase, derive the account key, derive the external address key, and get the public key associated with the address.We create a new transaction, set the recipient address, sign the transaction using our private key, and send the transaction using the Bitcoin testnet.
-
Modify the
main
function to call thesendBitcoin
function with appropriate parameters:func main() { fmt.Println("Welcome to the Bitcoin Wallet!") seedPhrase := []string{"word1", "word2", "word3"} // Replace with your actual seed phrase address := "YOUR_BITCOIN_ADDRESS" // Replace with your actual Bitcoin address toAddress := "RECIPIENT_BITCOIN_ADDRESS" // Replace with the Bitcoin address of the recipient amount := int64(1000000) // Specify the amount to send in satoshis (e.g., 0.01 BTC) generateAddress() getBalance(address) sendBitcoin(seedPhrase, amount, toAddress) }
Make sure to replace
YOUR_BITCOIN_ADDRESS
with your actual Bitcoin address andRECIPIENT_BITCOIN_ADDRESS
with the Bitcoin address of the recipient. -
Save and close the
wallet.go
file.Now, when you run
go run wallet.go
, it will generate a Bitcoin address, display the wallet balance, and send a Bitcoin transaction to the specified recipient.
Conclusion
Congratulations! You have successfully developed a command-line Bitcoin wallet in Go. In this tutorial, we covered the basics of generating a Bitcoin address, checking wallet balance, and sending Bitcoin transactions.
By understanding the concepts and code presented in this tutorial, you can further enhance the wallet functionality or explore more advanced features of Bitcoin programming in Go.