mirror of
				https://github.com/ChristopherA/Learning-Bitcoin-from-the-Command-Line.git
				synced 2025-10-31 10:27:29 +00:00 
			
		
		
		
	Go
This commit is contained in:
		
							parent
							
								
									1f7436fc13
								
							
						
					
					
						commit
						b49fc22895
					
				
							
								
								
									
										337
									
								
								18_1_Accessing_Bitcoind_with_Go.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										337
									
								
								18_1_Accessing_Bitcoind_with_Go.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,337 @@ | |||||||
|  | # 18.1: Accessing Bitcoind with NodeJS | ||||||
|  | 
 | ||||||
|  | ## Set up Go | ||||||
|  | 
 | ||||||
|  | First, install curl if you haven't already: | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | $ sudo apt install curl | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Then, look at the [Go downloads page](https://golang.org/dl/) and get the link for the latest download: | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | $ curl -O https://dl.google.com/go/go1.14.4.linux-amd64.tar.gz | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Once it finishes downloading, compare the hash of the download to the hash on the [Go downloads page](https://golang.org/dl/): | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | $ sha256sum go1.14.4.linux-amd64.tar.gz | ||||||
|  | aed845e4185a0b2a3c3d5e1d0a35491702c55889192bb9c30e67a3de6849c067  /home/user1/go1.14.4.linux-amd64.tar.gz | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | The hashes should match. Now we can extract the tarball and install Go on our system: | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | $ tar xvf go1.12.5.linux-amd64.tar.gz | ||||||
|  | $ sudo chown -R root:root ./go | ||||||
|  | $ sudo mv go /usr/local | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Now we need to create a Go path to specify our environment. Open the ```~/.profile``` file with an editor of your choice and add the following to the end of it: | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | export GOPATH=$HOME/work | ||||||
|  | export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Then, refresh your profile: | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | $ source ~/.profile | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Lastly, create the directory for your Go workspace: | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | $ mkdir $HOME/work | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | ## Setup btcd rpcclient | ||||||
|  | 
 | ||||||
|  | We will be using the rpcclient that comes with btcd, a Bitcoin implementation written in Go. We can use ```go get``` to download it: | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | $ go get github.com/btcsuite/btcd/rpcclient | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | To test that it works, navigate to the directory with the Bitcoin core examples: | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | $ cd $GOPATH/src/github.com/btcsuite/btcd/rpcclient/examples/bitcoincorehttp | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Modify the ```main.go``` file and enter the details associated with your Bitcoin core setup: | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | 		Host:         "localhost:18332", | ||||||
|  | 		User:         "bitcoinrpc", | ||||||
|  | 		Pass:         "d8340efbcd34e312044c8431c59c792c", | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Now run: | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | $ go run main.go | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | You should see the block count printed: | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | 2020/06/24 20:41:01 Block count: 1773552 | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | ### Print the latest block | ||||||
|  | 
 | ||||||
|  | Leave the btcd directory and create a new Go project: | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | $ mkdir -p ~/work/src/myproject/bitcoin | ||||||
|  | $ cd ~/work/src/myproject/bitcoin | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | In this directory, create a file called ```main.go``` and enter the following in it: | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | package main | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"log" | ||||||
|  | 	"fmt" | ||||||
|  | 	"github.com/btcsuite/btcd/rpcclient" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func main() { | ||||||
|  | 	connCfg := &rpcclient.ConnConfig{ | ||||||
|  | 		Host:         "localhost:18332", | ||||||
|  | 		User:         "bitcoinrpc", | ||||||
|  | 		Pass:         "431451790e3eee1913115b9dd2fbf0ac", | ||||||
|  | 		HTTPPostMode: true, | ||||||
|  | 		DisableTLS:   true, | ||||||
|  | 	} | ||||||
|  | 	client, err := rpcclient.New(connCfg, nil) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 	defer client.Shutdown() | ||||||
|  | 
 | ||||||
|  | 	blockCount, err := client.GetBlockCount() | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 	blockHash, err := client.GetBlockHash(blockCount) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	fmt.Printf("%d\n", blockCount) | ||||||
|  | 	fmt.Printf("%s\n", blockHash.String()) | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Make sure to change your username and password to those from your ```~/.bitcoin/bitcoin.conf``` file. When you run this: | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | $ go run main.go | ||||||
|  | 1773561 | ||||||
|  | 00000000000000346bab4126f418a5820692c9a7de7ef79717bebfccebacad61 | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | The latest block number along with its hash should be printed out. | ||||||
|  | 
 | ||||||
|  | ### Getting your wallet balance | ||||||
|  | 
 | ||||||
|  | Since the btcd rpcclient is quite limited, we can't make a use the ```getwalletinfo``` functino, however we can get the balance of our wallet: | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | package main | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"log" | ||||||
|  | 	"fmt" | ||||||
|  | 	"github.com/btcsuite/btcd/rpcclient" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func main() { | ||||||
|  | 	connCfg := &rpcclient.ConnConfig{ | ||||||
|  | 		Host:         "localhost:18332", | ||||||
|  | 		User:         "bitcoinrpc", | ||||||
|  | 		Pass:         "431451790e3eee1913115b9dd2fbf0ac", | ||||||
|  | 		HTTPPostMode: true, | ||||||
|  | 		DisableTLS:   true, | ||||||
|  | 	} | ||||||
|  | 	client, err := rpcclient.New(connCfg, nil) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 	defer client.Shutdown() | ||||||
|  | 
 | ||||||
|  | 	wallet, err := client.GetBalance("*") | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 	fmt.Println(wallet) | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | You should get an output similar to this: | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | 0.000689 BTC | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | ### Get amount received by an address | ||||||
|  | 
 | ||||||
|  | We can retrieve the amount of Bitcoin received by a specific address: | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | package main | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"log" | ||||||
|  | 	"fmt" | ||||||
|  | 	"github.com/btcsuite/btcd/rpcclient" | ||||||
|  | 	"github.com/btcsuite/btcutil" | ||||||
|  | 	"github.com/btcsuite/btcd/chaincfg" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func main() { | ||||||
|  | 	connCfg := &rpcclient.ConnConfig{ | ||||||
|  | 		Host:         "localhost:18332", | ||||||
|  | 		User:         "bitcoinrpc", | ||||||
|  | 		Pass:         "431451790e3eee1913115b9dd2fbf0ac", | ||||||
|  | 		HTTPPostMode: true, | ||||||
|  | 		DisableTLS:   true, | ||||||
|  | 	} | ||||||
|  | 	client, err := rpcclient.New(connCfg, nil) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 	defer client.Shutdown() | ||||||
|  | 
 | ||||||
|  | 	defaultNet := &chaincfg.TestNet3Params | ||||||
|  | 	addr, err := btcutil.DecodeAddress("mpGpCMX6SuUimDZKiVViuhd7EGyVxkNnha", defaultNet) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 	wallet, err := client.GetReceivedByAddress(addr) | ||||||
|  | 
 | ||||||
|  | 	fmt.Println(wallet) | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | The defaultNet variable is used to specify whether our Bitcoin node is on testnet or on mainnet. | ||||||
|  | 
 | ||||||
|  | ### Sending Bitcoin to an address | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | package main | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"log" | ||||||
|  | 	"fmt" | ||||||
|  | 	"github.com/btcsuite/btcd/rpcclient" | ||||||
|  | 	"github.com/btcsuite/btcutil" | ||||||
|  | 	"github.com/btcsuite/btcd/chaincfg" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func main() { | ||||||
|  | 	connCfg := &rpcclient.ConnConfig{ | ||||||
|  | 		Host:         "localhost:18332", | ||||||
|  | 		User:         "bitcoinrpc", | ||||||
|  | 		Pass:         "431451790e3eee1913115b9dd2fbf0ac", | ||||||
|  | 		HTTPPostMode: true, | ||||||
|  | 		DisableTLS:   true, | ||||||
|  | 	} | ||||||
|  | 	client, err := rpcclient.New(connCfg, nil) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 	defer client.Shutdown() | ||||||
|  | 
 | ||||||
|  | 	defaultNet := &chaincfg.TestNet3Params | ||||||
|  | 	addr, err := btcutil.DecodeAddress("n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi", defaultNet) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	sent, err := client.SendToAddress(addr, btcutil.Amount(1e4)) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 	fmt.Println(sent) | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | This outputs the txid of the transaction. | ||||||
|  | 
 | ||||||
|  | ### Lookup a transaction | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | package main | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"log" | ||||||
|  | 	"fmt" | ||||||
|  | 	"github.com/btcsuite/btcd/rpcclient" | ||||||
|  | 	"github.com/btcsuite/btcd/chaincfg/chainhash" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func main() { | ||||||
|  | 	connCfg := &rpcclient.ConnConfig{ | ||||||
|  | 		Host:         "localhost:18332", | ||||||
|  | 		User:         "bitcoinrpc", | ||||||
|  | 		Pass:         "431451790e3eee1913115b9dd2fbf0ac", | ||||||
|  | 		HTTPPostMode: true, | ||||||
|  | 		DisableTLS:   true, | ||||||
|  | 	} | ||||||
|  | 	client, err := rpcclient.New(connCfg, nil) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 	defer client.Shutdown() | ||||||
|  | 
 | ||||||
|  | 	chash, err := chainhash.NewHashFromStr("1661ce322c128e053b8ea8fcc22d17df680d2052983980e2281d692b9b4ab7df") | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 	transactions, err := client.GetTransaction(chash) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 	fmt.Println(transactions) | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | This prints out the details associated with a transaction, such as its amount and how many times it has been confirmed: | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | { | ||||||
|  |   "amount": 0.00100000, | ||||||
|  |   "confirmations": 4817, | ||||||
|  |   "blockhash": "000000006628870b0a8a66abea9cf0d4e815c491f079e3fa9e658a87b5dc863a", | ||||||
|  |   "blockindex": 117, | ||||||
|  |   "blocktime": 1591857418, | ||||||
|  |   "txid": "1661ce322c128e053b8ea8fcc22d17df680d2052983980e2281d692b9b4ab7df", | ||||||
|  |   "walletconflicts": [ | ||||||
|  |   ], | ||||||
|  |   "time": 1591857343, | ||||||
|  |   "timereceived": 1591857343, | ||||||
|  |   "bip125-replaceable": "no", | ||||||
|  |   "details": [ | ||||||
|  |     { | ||||||
|  |       "address": "mpGpCMX6SuUimDZKiVViuhd7EGyVxkNnha", | ||||||
|  |       "category": "receive", | ||||||
|  |       "amount": 0.00100000, | ||||||
|  |       "label": "", | ||||||
|  |       "vout": 0 | ||||||
|  |     } | ||||||
|  |   ], | ||||||
|  |   "hex": "02000000000101e9e8c3bd057d54e73baadc60c166860163b0e7aa60cab33a03e89fb44321f8d5010000001716001435c2aa3fc09ea53c3e23925c5b2e93b9119b2568feffffff02a0860100000000001976a914600c8c6a4abb0a502ea4de01681fe4fa1ca7800688ac65ec1c000000000017a91425b920efb2fde1a0277d3df11d0fd7249e17cf8587024730440220403a863d312946aae3f3ef0a57206197bc67f71536fb5f4b9ca71a7e226b6dc50220329646cf786cfef79d60de3ef54f702ab1073694022f0618731902d926918c3e012103e6feac9d7a8ad1ac6b36fb4c91c1c9f7fff1e7f63f0340e5253a0e4478b7b13f41fd1a00" | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | ## Summary: Accessing Bitcoind with Node | ||||||
|  | 
 | ||||||
|  | Although the btcd rpcclient is quite limited, we can still perform a lot of the main rpc commands in Go.  | ||||||
| @ -201,9 +201,9 @@ You should get an output similar to this: | |||||||
| } | } | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| ### Get address balance | ### Get Amount Received by an Address | ||||||
| 
 | 
 | ||||||
| A useful function when accepting Bitcoin is checking the balance of a specific address in your wallet. For example, if you were running an online store accepting Bitcoin, for each payment from a customer, you would generate a new address (as we did with ```getNewAddress``` function), show that address to the customer, then check the balance of the address after some time, to make sure the correct amount has been received: | A useful function when accepting Bitcoin is checking the received Bitcoin of a specific address in your wallet. For example, if you were running an online store accepting Bitcoin, for each payment from a customer, you would generate a new address (as we did with ```getNewAddress``` function), show that address to the customer, then check the balance of the address after some time, to make sure the correct amount has been received: | ||||||
| 
 | 
 | ||||||
| ``` | ``` | ||||||
| agent.getReceivedByAddress('mpGpCMX6SuUimDZKiVViuhd7EGyVxkNnha', function (err, addressInfo) { | agent.getReceivedByAddress('mpGpCMX6SuUimDZKiVViuhd7EGyVxkNnha', function (err, addressInfo) { | ||||||
|  | |||||||
| @ -104,9 +104,9 @@ _This section is currently a messy set of older writings which are being reorgan | |||||||
|    * 17.4: Integrating Libwally and Scripts |    * 17.4: Integrating Libwally and Scripts | ||||||
| * 17.0: Talking to Lightningd with C | * 17.0: Talking to Lightningd with C | ||||||
| * 18.0: Talking to Bitcoind with Other Languages | * 18.0: Talking to Bitcoind with Other Languages | ||||||
|   * [18.1: Accessing Bitcoind with Go] |   * [18.1: Accessing Bitcoind with Go](18_1_Accessing_Bitcoind_with_Go.md) | ||||||
|   * [18.2: Accessing Bitcoind with Java](18_2_Accessing_Bitcoind_with_Java.md) — Needs Rewrite + Editing |   * [18.2: Accessing Bitcoind with Java](18_2_Accessing_Bitcoind_with_Java.md) — Needs Rewrite + Editing | ||||||
|   * [18.3: Accessing Bitcoind with Node JS](18_3_Accessing_Bitcoind_with_NodeJS.md)  — Needs Rewrite + Editing |   * [18.3: Accessing Bitcoind with Node JS](18_3_Accessing_Bitcoind_with_NodeJS.md) | ||||||
|   * [18.4: Accessing Bitcoind with Python] |   * [18.4: Accessing Bitcoind with Python] | ||||||
|   * [18.5: Accessing Bitcoind with Rust] |   * [18.5: Accessing Bitcoind with Rust] | ||||||
|   * [18.6: Accessing Bitcoind with Swift] |   * [18.6: Accessing Bitcoind with Swift] | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user