mirror of
https://github.com/ChristopherA/Learning-Bitcoin-from-the-Command-Line.git
synced 2025-06-07 16:06:26 +00:00
Create 12_1_Accessing_Bitcoind_with_Curl.md
This commit is contained in:
parent
6d727a9de2
commit
efc5f83cda
@ -37,6 +37,12 @@ Examples:
|
||||
```
|
||||
And there's the `curl` command, at the end of the help screen! This somewhat lengthy command has four major parts: (1) a listing of your user name; (2) a `--data-binary` flag; (3) a JSON object that tells `bitcoind` what to do; and (4) an HTTP header that includes the URL to talk to. When you are working with `curl`, most of this will stay the same from command to command, other than the `method` and `params` entries in the JSON array. However, you need to know how to fill in your username and your URL address in order to make it work in the first place!
|
||||
|
||||
_Whenever you're unusure about how to directly access an RPC command via curl, just look at the bitcoin-cli help and go from there._
|
||||
|
||||
#### Know Your Parameters Format
|
||||
|
||||
[[BETTER EXPLAIN PARAMETERS FROM START]]
|
||||
|
||||
### Know Your User Name
|
||||
|
||||
In order to speak with the `bitcoind` port, you need a user name and password. These were created as part of your initial Bitcoin setup, and can be found in `~/.bitcoin/bitcoin.conf`.
|
||||
@ -81,30 +87,229 @@ However, with the right port number in hand, you should now be able to `curl` ou
|
||||
$ curl --user bitcoinrpc:d8340efbcd34e312044c8431c59c792c --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getmininginfo", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/
|
||||
{"result":{"blocks":1128599,"currentblocksize":0,"currentblockweight":0,"currentblocktx":0,"difficulty":1,"errors":"Warning: unknown new rules activated (versionbit 28)","networkhashps":8658807967387.751,"pooledtx":0,"chain":"test"},"error":null,"id":"curltest"}
|
||||
```
|
||||
You'll note that the result is another JSON array, which is kind of ugly to read if you're using `curl` by hand. That's why `bitcoin-cli` and `curl` libraries exist. But, for the moment, we'll struggle through the JSON inputs and outputs, to understand this as the low-level.
|
||||
We provided the method, `getmininginfo`, and the null set for parameters, and everything else was the standard JSON input.
|
||||
|
||||
You'll note that the result is another JSON array, which is kind of ugly to read if you're using `curl` by hand. That's why `bitcoin-cli` and `curl` libraries exist. Fortunately, you can clean it up very simply by piping it through `jq`:
|
||||
```
|
||||
$ curl --user bitcoinrpc:d8340efbcd34e312044c8431c59c792c --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getmininginfo", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.'
|
||||
|
||||
% Total % Received % Xferd Average Speed Time Time Time Current
|
||||
Dload Upload Total Spent Left Speed
|
||||
100 354 100 277 100 77 65546 18220 --:--:-- --:--:-- --:--:-- 92333
|
||||
|
||||
{
|
||||
"result": {
|
||||
"blocks": 1128609,
|
||||
"currentblocksize": 0,
|
||||
"currentblockweight": 0,
|
||||
"currentblocktx": 0,
|
||||
"difficulty": 2777757.750498331,
|
||||
"errors": "Warning: unknown new rules activated (versionbit 28)",
|
||||
"networkhashps": 8795436830406.6,
|
||||
"pooledtx": 0,
|
||||
"chain": "test"
|
||||
},
|
||||
"error": null,
|
||||
"id": "curltest"
|
||||
}
|
||||
```
|
||||
You'll see a bit of connectivity reporting as the data is downloaded, then when that data hits `jq`, everything will be output in a correctly indented form. (We'll be omiting the download information in future example.)
|
||||
|
||||
> **WARNING:** If you get a result like "Failed to connect to 127.0.0.1 port 8332: Connection refused", be sure that a line like `rpcallowip=127.0.0.1` is in your ~/.bitcoin/bitcoin.conf. If things still don't work, be sure that you're allowing access to port 18332 (or 8332) from localhost. Our standard setup from [Chapter Two: Creating a Bitcoin-Core VPS](02_0_Setting_Up_a_Bitcoin-Core_VPS.md) should do all of this.
|
||||
|
||||
## Understand the Limits of RPC
|
||||
|
||||
In each of these three chapters about accessing `bitcoind` via RPC, we're going to quickly run through lessons already learned, about wallet access and about sending raw transactions, as a guide to getting you started if you choose to use this message of access. Expect all of these access methods to be _harder_ than when you were working directly with `bitcoin-cli`.
|
||||
|
||||
There's a reason for this: `bitcoin-cli` actually provides two sorts of functionality. First, it gives you access to the RPC commands of `bitcoind`; and second, it proides you with basic wallet functionality while accessing those RPC commands. Now that you're accessing RPC commands directly, those wallet shortcuts are going to go away, leaving you on your own to deal with the wilds of Bitcoin. Mind you, this isn't necessarily a bad thing. When a programmer starts working with Bitcoin, often one of the first things he does is write a new set wallet functionality. Because he _needs_ it when working with Bitcoin more directly.
|
||||
|
||||
So, welcome to the club.
|
||||
|
||||
## Manipulate Your Wallet
|
||||
|
||||
### Lookup Addresses
|
||||
Though you're accessing `bitcoind` directly, you'll still get access to wallet functionality, because that's largely stored in `bitcoind` itself.
|
||||
|
||||
### Lookup Funds
|
||||
### Look Up Addresses
|
||||
|
||||
The `getaddressesbyaccount` RPC lists all of your current addresses:
|
||||
```
|
||||
$ curl --user bitcoinrpc:d8340efbcd34e312044c8431c59c792c --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getaddressesbyaccount", "params": [""] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.'
|
||||
|
||||
{
|
||||
"result": [
|
||||
"mg7YqyvK8HUFvpgZ5iYTfZ5vjfaJWnNTd9",
|
||||
"mkMkhbUzcSPdEHUoRQkBKHe8otP1SzWWeb",
|
||||
"moXjRArk4rWUYZvAiDHnMXQHmwyf3TtAb8",
|
||||
"mp3qqSTEYqhm3iuo9nM5GnzCGuoEvb9KrK",
|
||||
"msW5tzCMJRECSATENN11ATmxx3PLwjGEaW",
|
||||
"msZ5bMbZC4HQPRuJCoivDWYExAB7ssE5o8",
|
||||
"mx3wUEVp526gkqzMteK6NwsPffgtFB3CGX",
|
||||
"mxwLPpo2X1VXXAiLHNVb55H4JASeLMDm7A",
|
||||
"n2AfUVXq9MzsJohCjCKNXKj2SYHfdbrcqy",
|
||||
"n2fGxDXKozkZjpi9DqW93NZ65TnQDqd49V",
|
||||
"n4cqjJE6fqcmeWpftygwPoKMMDva6BpyHf",
|
||||
"2Mzw7WBvh9RAQ4ssKqxyNyP7L9NAojLqSW8",
|
||||
"2NAGfA4nW6nrZkD5je8tSiAcYB9xL2xYMCz",
|
||||
"2NDx9HTeLagiEqWrYvBuPkG3gwdhQ32Jz4B"
|
||||
],
|
||||
"error": null,
|
||||
"id": "curltest"
|
||||
}
|
||||
```
|
||||
This is our first example of a real parameter, `""`. This is the `account` parameter, but all of our addresses are in the default account, so nothing special was required here.
|
||||
|
||||
The result is a list of all the addresses that have been used by this wallet ... some of which presumably contain funds.
|
||||
|
||||
### Look Up Funds
|
||||
|
||||
The `listunspent` RPC lists out the funds that you have available:
|
||||
```
|
||||
$ curl --user bitcoinrpc:d8340efbcd34e312044c8431c59c792c --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "listunspent", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.'
|
||||
|
||||
{
|
||||
"result": [
|
||||
{
|
||||
"txid": "6a184a2f07fa30189f4831d6f041d52653a103b3883d2bec2f79187331fd7f0e",
|
||||
"vout": 0,
|
||||
"address": "mnsdQUxpGa6UsroUJhJGupPrPcuvQbPzmV",
|
||||
"scriptPubKey": "76a91450b1d90a130c4f3f1e5fbfa7320fd36b7265db0488ac",
|
||||
"amount": 1.2985,
|
||||
"confirmations": 1260,
|
||||
"spendable": true,
|
||||
"solvable": true
|
||||
},
|
||||
{
|
||||
"txid": "966099e0fd330007eac0394d97a36985980ff971d64b865c5d474f1931eeec3a",
|
||||
"vout": 0,
|
||||
"address": "2NAGfA4nW6nrZkD5je8tSiAcYB9xL2xYMCz",
|
||||
"account": "",
|
||||
"scriptPubKey": "a914babf9063cee8ab6e9334f95f6d4e9148d0e551c287",
|
||||
"amount": 1.2985,
|
||||
"confirmations": 3681,
|
||||
"spendable": false,
|
||||
"solvable": false
|
||||
},
|
||||
{
|
||||
"txid": "e31f747cb97a364a1a00b56a3d9d43a97c6e02938a47e599ad54d7cf710f056f",
|
||||
"vout": 0,
|
||||
"address": "2NDx9HTeLagiEqWrYvBuPkG3gwdhQ32Jz4B",
|
||||
"account": "",
|
||||
"redeemScript": "52210307fd375ed7cced0f50723e3e1a97bbe7ccff7318c815df4e99a59bc94dbcd81921029bf628adf0698a089137294975c8589cf0cc6be050f92d944faaa8c8a623430352ae",
|
||||
"scriptPubKey": "a914e31fa4be1f718e068ba5cbb2f12a59bba66a2da687",
|
||||
"amount": 1.3,
|
||||
"confirmations": 6515,
|
||||
"spendable": false,
|
||||
"solvable": true
|
||||
},
|
||||
{
|
||||
"txid": "88e5d5f3077517d76f5a61491fa52e6aaae078c52bc62d849f09507ef0cfada2",
|
||||
"vout": 0,
|
||||
"address": "n4cqjJE6fqcmeWpftygwPoKMMDva6BpyHf",
|
||||
"account": "",
|
||||
"scriptPubKey": "76a914fd67e8a7c7813e7a5c376eb71074f373d924d96888ac",
|
||||
"amount": 0.47,
|
||||
"confirmations": 38043,
|
||||
"spendable": true,
|
||||
"solvable": true
|
||||
},
|
||||
{
|
||||
"txid": "7e8abac5040a14f74fc8c44300c89cf93ce7f59f1e1c1d1711fdddd7012941c1",
|
||||
"vout": 0,
|
||||
"address": "moXjRArk4rWUYZvAiDHnMXQHmwyf3TtAb8",
|
||||
"account": "",
|
||||
"scriptPubKey": "76a91457e6ac3cfbc9c34c292ca59f105a2d7a819db7a488ac",
|
||||
"amount": 0.65,
|
||||
"confirmations": 6586,
|
||||
"spendable": true,
|
||||
"solvable": true
|
||||
}
|
||||
],
|
||||
"error": null,
|
||||
"id": "curltest"
|
||||
}
|
||||
```
|
||||
This is almost exactly the same output that you get when you type `bitcoin-cli listunspent`, showing how closely tied the two interfaces are. If no cleanup or extra help is needed, then `bitcoin-cli` just outputs the RPC. Easy!
|
||||
|
||||
### Create an Address
|
||||
|
||||
So you know where your funds are, as you're aware the next step in creating a transaction is to create a change address. By now you've probably got the hang of this, and you know that for simple RPC commands, all you need to do is adjust the `method` is the `curl` command:
|
||||
```
|
||||
$ curl --user bitcoinrpc:d8340efbcd34e312044c8431c59c792c --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getrawchangeaddress", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.'
|
||||
|
||||
{
|
||||
"result": "mznccEt2ozGFN6oVaYU5BGgTzcdH8Zj8wf",
|
||||
"error": null,
|
||||
"id": "curltest"
|
||||
}
|
||||
```
|
||||
At this point, we can even revert to our standard practice of saving results to variables:
|
||||
```
|
||||
$ changeaddress=$(curl --user bitcoinrpc:d8340efbcd34e312044c8431c59c792c --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getrawchangeaddress", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.result')
|
||||
|
||||
$ echo $changeaddress
|
||||
mmDWRH3CbeXwCqBwdHCj7E9d3oWTuuizxc
|
||||
```
|
||||
No need to worry about the downloading info. It'll go to `STDERR` and be displayed on your screen, while the results go to `STDOUT` and are saved in your variable.
|
||||
|
||||
## Create a Transaction
|
||||
|
||||
### Adjust the nVersion
|
||||
You're now ready to create a transaction with `curl`.
|
||||
|
||||
### Ready Your Variables
|
||||
|
||||
Just as with `bitcoin-cli`, in order to create a transaction using the RPC directly, you should first save your variables. The only change here is that you always need to pipe through the `.result` tag before you do anything else. This example sets up our variables for using the 1.2985 BTC in funds listed in the first unspent transaction above:
|
||||
```
|
||||
$ utxo_txid=$(curl --user bitcoinrpc:d8340efbcd34e312044c8431c59c792c --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "listunspent", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.result | .[0] | .txid')
|
||||
$ utxo_vout=$(curl --user bitcoinrpc:d8340efbcd34e312044c8431c59c792c --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "listunspent", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.result | .[0] | .vout')
|
||||
recipient=mwCwTceJvYV27KXBc3NJZys6CjsgsoeHmf
|
||||
$ changeaddress=$(curl --user bitcoinrpc:d8340efbcd34e312044c8431c59c792c --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getrawchangeaddress", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.result')
|
||||
|
||||
$ echo $utxo_txid
|
||||
6a184a2f07fa30189f4831d6f041d52653a103b3883d2bec2f79187331fd7f0e
|
||||
$ echo $utxo_vout
|
||||
0
|
||||
$ echo $recipient
|
||||
mwCwTceJvYV27KXBc3NJZys6CjsgsoeHmf
|
||||
$ echo $changeaddress
|
||||
mmDWRH3CbeXwCqBwdHCj7E9d3oWTuuizxc
|
||||
```
|
||||
|
||||
### Create the Transaction
|
||||
|
||||
The transaction created with `curl` is very similar to the transaction created with `bitcoin-cli`, but a few subtle differences:
|
||||
```
|
||||
$ curl --user bitcoinrpc:d8340efbcd34e312044c8431c59c792c --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "createrawtransaction", "params": [''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]'', ''{ "'$recipient'": 0.298, "'$changeaddress'": 1.0}'']}' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.'
|
||||
|
||||
{
|
||||
"result": "02000000010e7ffd317318792fec2b3d88b303a15326d541f0d631489f1830fa072f4a186a0000000000ffffffff0240b6c601000000001976a914ac19d3fd17710e6b9a331022fe92c693fdf6659588ac00e1f505000000001976a9143e84156731d67c80c3dff6c1cc3b4f58460e642388ac00000000",
|
||||
"error": null,
|
||||
"id": "curltest"
|
||||
}
|
||||
```
|
||||
The heart of the transaction is, of course, the `params` JSON array, which we're putting to full use for the first time.
|
||||
|
||||
Note that the entire params is lodged in `[]`s to mark an outermost array that you don't usually see.
|
||||
|
||||
We've also varied up the quoting, to lead and end each array and object within the `params` array with `''` instead of our traditional `'''`. That's because the entire set of JSON arguments already has a `'` around it. As usual, just take a look at the bizarre shell quoting an get used to it.
|
||||
|
||||
However, there's one last thing of note in this example, and it can be _maddening_ if you miss it. When we executed this command with `bitcoin-cli` the JSON array of inputs and the JSON object of outputs were separated by a space. Now, because they're part of that outermost JSON array, they're separated by a comma (`,`). Miss that and you'll get a continuous string of `parse errors` without much additional information.
|
||||
|
||||
> **WARNING:** Ever having troubles debugging your `curl`? Add the argument `--trace-ascii /tmp/foo`. Full information on what's being sent to the server will be saved in `/tmp/foo` (or whatever file name you provide).
|
||||
|
||||
Having verified that things work, you probably want to save this into a variable:
|
||||
```
|
||||
$ hexcode=$(curl --user bitcoinrpc:d8340efbcd34e312044c8431c59c792c --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "createrawtransaction", "params": [''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]'', ''{ "'$recipient'": 0.298, "'$changeaddress'": 1.0}'']}' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.result')
|
||||
```
|
||||
|
||||
### Sign and Send
|
||||
|
||||
Signing and sending is an easy use of the `signrawtransaction` and `sendrawtransaction` functions:
|
||||
|
||||
```
|
||||
$ signedhex=$(curl --user bitcoinrpc:d8340efbcd34e312044c8431c59c792c --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "signrawtransaction", "params": ["'$hexcode'"] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.result | .hex')
|
||||
|
||||
$ curl --user bitcoinrpc:d8340efbcd34e312044c8431c59c792c --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "sendrawtransaction", "params": ["'$signedhex'"] }' -H 'content-type: text/plain;' http://127.0.0.1:18332/ | jq -r '.'
|
||||
{
|
||||
"result": "000b4430a7a2ba60891b01b718747eaf9665cb93fbc0c619c99419b5b5cf3ad2",
|
||||
"error": null,
|
||||
"id": "curltest"
|
||||
}
|
||||
```
|
||||
## Summary: Accessing Bitcoind with Curl
|
||||
|
||||
Having finished this section, you may feel that accessing `bitcoind` via `curl` is very much like accessing it through `bitcoin-cli` ... but more cumbersome. And, you'd be right. `bitcoin-cli` has pretty complete RPC functionality, so anything that you do through `curl` you can probably do through `bitcoin-cli`.
|
||||
|
||||
_What is the power of curl?_ Most obviously, `curl` takes out one level of indirection. Instead of working with `bitcoin-cli` which sends RPC commands to `bitcoind`, you're sending those RPC commands directly. This allows for more robust programming, because you don't have to worry about what unexpected things `bitcoin-cli` might do or how it might change over time. However, you're also talking your first steps toward using a more comprehensive programming language than the poor options offered by a shell script. But for that, you'll need to use a `curl` library within a more familiar language like JavaScript or C. In other words, command-line `curl` was just the first step, the basis to better explain what you're doing as you move forward.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user