diff --git a/18_1_Accessing_Bitcoind_with_Go.md b/18_1_Accessing_Bitcoind_with_Go.md new file mode 100644 index 0000000..0ab73e1 --- /dev/null +++ b/18_1_Accessing_Bitcoind_with_Go.md @@ -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. \ No newline at end of file diff --git a/18_3_Accessing_Bitcoind_with_NodeJS.md b/18_3_Accessing_Bitcoind_with_NodeJS.md index 0926ce4..a133071 100644 --- a/18_3_Accessing_Bitcoind_with_NodeJS.md +++ b/18_3_Accessing_Bitcoind_with_NodeJS.md @@ -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) { diff --git a/README.md b/README.md index bd6f387..2b7f575 100644 --- a/README.md +++ b/README.md @@ -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.0: Talking to Lightningd with C * 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.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.5: Accessing Bitcoind with Rust] * [18.6: Accessing Bitcoind with Swift]