Update 04_4a_Interlude_Using_Curl.md

This commit is contained in:
Shannon Appelcline 2026-02-26 14:00:20 -10:00 committed by GitHub
parent f98fc83ee9
commit 553e570f95
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -18,23 +18,37 @@ $ bitcoin-cli help getmininginfo
getmininginfo getmininginfo
Returns a json object containing mining-related information. Returns a json object containing mining-related information.
Result: Result:
{ (json object) { (json object)
"blocks" : n, (numeric) The current block "blocks" : n, (numeric) The current block
"currentblockweight" : n, (numeric, optional) The block weight of the last assembled block (only present if a block was ever assembled) "currentblockweight" : n, (numeric, optional) The block weight (including reserved weight for block header, txs count and coinbase tx) of the last assembled block (only present if a block was ever assembled)
"currentblocktx" : n, (numeric, optional) The number of block transactions of the last assembled block (only present if a block was ever assembled) "currentblocktx" : n, (numeric, optional) The number of block transactions (excluding coinbase) of the last assembled block (only present if a block was ever assembled)
"difficulty" : n, (numeric) The current difficulty "bits" : "hex", (string) The current nBits, compact representation of the block difficulty target
"networkhashps" : n, (numeric) The network hashes per second "difficulty" : n, (numeric) The current difficulty
"pooledtx" : n, (numeric) The size of the mempool "target" : "hex", (string) The current target
"chain" : "str", (string) current network name (main, test, regtest) "networkhashps" : n, (numeric) The network hashes per second
"warnings" : "str" (string) any network and blockchain warnings "pooledtx" : n, (numeric) The size of the mempool
"blockmintxfee" : n, (numeric) Minimum feerate of packages selected for block inclusion in BTC/kvB
"chain" : "str", (string) current network name (main, test, testnet4, signet, regtest)
"signet_challenge" : "hex", (string, optional) The block challenge (aka. block script), in hexadecimal (only present if the current network is a signet)
"next" : { (json object) The next block
"height" : n, (numeric) The next height
"bits" : "hex", (string) The next target nBits
"difficulty" : n, (numeric) The next difficulty
"target" : "hex" (string) The next target
},
"warnings" : [ (json array) any network and blockchain warnings (run with `-deprecatedrpc=warnings` to return the latest warning as a single string)
"str", (string) warning
...
]
} }
Examples: Examples:
> bitcoin-cli getmininginfo > bitcoin-cli getmininginfo
> curl --user myusername --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "getmininginfo", "params": []}' -H 'content-type: text/plain;' http://127.0.0.1:8332/ > curl --user myusername --data-binary '{"jsonrpc": "2.0", "id": "curltest", "method": "getmininginfo", "params": []}' -H 'content-type: application/json' http://127.0.0.1:8332/
``` ```
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, including a JSON array of parameters; and (4) an HTTP header that includes the `bitcoind` URL. 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, including a JSON array of parameters; and (4) an HTTP header that includes the `bitcoind` URL.
When you are working with `curl`, most of these arguments to `curl` will stay the same from command to command; only the `method` and `params` entries in the JSON array will typically change. 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! When you are working with `curl`, most of these arguments to `curl` will stay the same from command to command; only the `method` and `params` entries in the JSON array will typically change. 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!
@ -53,16 +67,17 @@ par=1
maxuploadtarget=137 maxuploadtarget=137
maxconnections=16 maxconnections=16
rpcuser=StandUp rpcuser=StandUp
rpcpassword=8eaf562eaf45c33c3328bc66008f2dd1 rpcpassword=4b42b0447b08784cb41adedac54d7f26
rpcallowip=127.0.0.1 rpcallowip=127.0.0.1
debug=tor debug=tor
prune=550 prune=550
signet=1 signet=1
mintxfee=0.001 fallbackfee=0.0001
mintxfee=0.0001
txconfirmtarget=1 txconfirmtarget=1
[test] [test]
rpcbind=127.0.0.1 rpcbind=127.0.0.1
rpcport=38332 rpcport=18332
[main] [main]
rpcbind=127.0.0.1 rpcbind=127.0.0.1
rpcport=8332 rpcport=8332
@ -70,9 +85,9 @@ rpcport=8332
rpcbind=127.0.0.1 rpcbind=127.0.0.1
rpcport=18443 rpcport=18443
``` ```
Our user name is `StandUp` and our password is `8eaf562eaf45c33c3328bc66008f2dd1`. Our user name is `StandUp` and our password is `4b42b0447b08784cb41adedac54d7f26`.
> **WARNING:** Clearly, it's not very secure to have this information in a plain text file. As of Bitcoin Core 0.12, you can instead omit the `rpcpassword` from your `bitcoin.conf` file, and have `bitcoind` generate a new cookie whenever it starts up. The downside of this is that it makes use of RPC commands by other applications, such as the ones detailed in this chapter, more difficult. So, we're going to stick with the plain `rpcuser` and `rpcpassword` information for now, but for production software, consider moving to cookies. > **WARNING:** Clearly, it's not very secure to have this information in a plain text file. You can instead omit the `rpcpassword` from your `bitcoin.conf` file, and have `bitcoind` generate a new cookie whenever it starts up. The downside of this is that it makes use of RPC commands by other applications, such as the ones detailed in this chapter, more difficult. So, we're going to stick with the plain `rpcuser` and `rpcpassword` information for now, but for production software, consider moving to cookies.
The secure way to RPC with `bitcoind` is as follows: The secure way to RPC with `bitcoind` is as follows:
``` ```
@ -81,13 +96,13 @@ Enter host password for user 'bitcoinrpc':
``` ```
As noted, you will be prompted for your password. As noted, you will be prompted for your password.
> :link: **SIGNET vs MAINNET:** Testnet uses a URL with port 38332 and mainnet uses a URL with port 8332. Take a look in your `bitcoin.conf`, it's all laid out there. > 🔗 **SIGNET vs MAINNET:** Signet uses a URL with port 38332 and mainnet uses a URL with port 8332. Take a look in your `bitcoin.conf`, it's mostly laid out there.
The insecure way to do so is as follows: The insecure way to do so is as follows:
``` ```
$ curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getmininginfo", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ $ curl --user StandUp:4b42b0447b08784cb41adedac54d7f26 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getmininginfo", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/
``` ```
> **WARNING:** Entering your password on the command line may put your password into the process table and/or save it into a history. This is even less recommended than putting it in a file, except for testing on signet (or testnet). If you want to do it anywhere else, make sure you know what you're doing! > ⚠️ **WARNING: Password Not Secure!** Entering your password on the command line may put your password into the process table and/or save it into a history. This is even less recommended than putting it in a file, except for testing on signet (or testnet). If you want to do it anywhere else, make sure you know what you're doing!
### Know Your Command & Parameters ### Know Your Command & Parameters
@ -110,34 +125,41 @@ Here's what some parameter arrays will look like:
You can now send your first `curl` command by accessing the `getmininginfo` RPC: You can now send your first `curl` command by accessing the `getmininginfo` RPC:
``` ```
$ curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getmininginfo", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ $ curl --user StandUp:4b42b0447b08784cb41adedac54d7f26 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getmininginfo", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/
{"result":{"blocks":1772428,"difficulty":10178811.40698772,"networkhashps":91963587385939.06,"pooledtx":61,"chain":"test","warnings":"Warning: unknown new rules activated (versionbit 28)"},"error":null,"id":"curltest"} {"result":{"blocks":293320,"bits":"1d150eea","difficulty":0.0474865840527392,"target":"000000150eea0000000000000000000000000000000000000000000000000000","networkhashps":301893.0621307249,"pooledtx":80,"blockmintxfee":0.00000001,"chain":"signet","next":{"height":293321,"bits":"1d150eea","difficulty":0.0474865840527392,"target":"000000150eea0000000000000000000000000000000000000000000000000000"},"signet_challenge":"512103ad5e0edad18cb1f0fc0d28a3d4f1f3e445640337489abb10404f2d1e086be430210359ef5021964fe22d6f8e05b2463c9540ce96883fe3b278760f048f5189f2e6c452ae","warnings":[]},"error":null,"id":"curltest"}
``` ```
Note that we provided the method, `getmininginfo`, and the parameter, `[]`, but that everything else was the standard `curl` command line. Note that we provided the method, `getmininginfo`, and the parameter, `[]`, but that everything else was the standard `curl` command line.
> **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 38332 (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. > ⚠️ **WARNING: RPC May Not Allow.** 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 38332 (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.
The result is another JSON array, which is unfortunately ugly to read if you're using `curl` by hand. Fortunately, you can clean it up simply by piping it through `jq`: The result is another JSON array, which is unfortunately ugly to read if you're using `curl` by hand. Fortunately, you can clean it up simply by piping it through `jq`:
``` ```
$ curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getmininginfo", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ | jq -r '.' $ curl --user StandUp:4b42b0447b08784cb41adedac54d7f26 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getmininginfo", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ 2> /dev/null | jq -r '.'
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 295 100 218 100 77 72666 25666 --:--:-- --:--:-- --:--:-- 98333
{ {
"result": { "result": {
"blocks": 1772429, "blocks": 293320,
"difficulty": 10178811.40698772, "bits": "1d150eea",
"networkhashps": 90580030969896.44, "difficulty": 0.0474865840527392,
"pooledtx": 4, "target": "000000150eea0000000000000000000000000000000000000000000000000000",
"chain": "test", "networkhashps": 301893.0621307249,
"warnings": "Warning: unknown new rules activated (versionbit 28)" "pooledtx": 88,
"blockmintxfee": 1E-8,
"chain": "signet",
"next": {
"height": 293321,
"bits": "1d150eea",
"difficulty": 0.0474865840527392,
"target": "000000150eea0000000000000000000000000000000000000000000000000000"
},
"signet_challenge": "512103ad5e0edad18cb1f0fc0d28a3d4f1f3e445640337489abb10404f2d1e086be430210359ef5021964fe22d6f8e05b2463c9540ce96883fe3b278760f048f5189f2e6c452ae",
"warnings": []
}, },
"error": null, "error": null,
"id": "curltest" "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 omitting the download information in future examples.) The '2>' throws out the connectivity reporting that `curl` reports, and then we send the rest to `jq`, which ensures that everything will be output in a correctly indented form.
## Manipulate Your Wallet ## Manipulate Your Wallet
@ -147,25 +169,43 @@ Though you're accessing `bitcoind` directly, you'll still get access to wallet f
Use the `getaddressesbylabel` RPC to list all of your current addresses: Use the `getaddressesbylabel` RPC to list all of your current addresses:
``` ```
$ curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getaddressesbylabel", "params": [""] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ | jq -r '.' $ curl --user StandUp:4b42b0447b08784cb41adedac54d7f26 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getaddressesbylabel", "params": [""] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ 2> /dev/null | jq -r '.'
{ {
"result": { "result": {
"mi25UrzHnvn3bpEfFCNqJhPWJn5b77a5NE": { "tb1qxe0nn84xxw76jfc0s93g8kuefu2llglcvscy28": {
"purpose": "receive" "purpose": "receive"
}, },
"mjehC2KHzXcBDcwTd4LhZ2GzyzrZ3Kd3ff": { "tb1qxmx50fc06jt67nw6eqdcsm3rexgn6qvcet3rcm": {
"purpose": "receive" "purpose": "receive"
}, },
"moKVV6XEhfrBCE3QCYq6ppT7AaMF8KsZ1B": { "tb1q8lpqzydarurhsqttvw2qkf2qjxrwdv0kkej2ux": {
"purpose": "receive" "purpose": "receive"
}, },
"mwJL7cRiW2bUnY81r1thSu3D4jtMmwyU6d": { "tb1qdu69s5f9nw8x88lvsc8nt5d7gy9rgtnef0upfu": {
"purpose": "receive" "purpose": "receive"
}, },
"tb1q5gnwrh7ss5mmqt0qfan85jdagmumnatcscwpk6": { "tb1qsnm8mfafey9mlc3wj0qqspfmzdvhy0pnlmw9xm": {
"purpose": "receive" "purpose": "receive"
}, },
"tb1qmtucvjtga68kgrvkl7q05x4t9lylxhku7kqdpr": { "tb1qnu24edevunfh8lk2a4x74ctn9jhslr83e4nsxx": {
"purpose": "receive"
},
"tb1qkvcgm83wv9np7re8w4w5ayg9tm2kxxpxk99h9p": {
"purpose": "receive"
},
"tb1qmwzvuavdvc6x0kmlrqncau4txhm5qrs7exjnv4": {
"purpose": "receive"
},
"tb1qukwva953qreduzm3mgnjwh5ymxupa4jrrkj8ym": {
"purpose": "receive"
},
"tb1qactkrm2yj2g73s966ptw7m56634zdv4acnhjhx": {
"purpose": "receive"
},
"tb1q7xkh94r24zw4uc3wg2amkagxfm4an5gpwrgsnl": {
"purpose": "receive"
},
"tb1qlw280hk7cf7r97sm896s83wysat4vrqzpalm7e": {
"purpose": "receive" "purpose": "receive"
} }
}, },
@ -181,32 +221,54 @@ The result is a list of all the addresses that have been used by this wallet ...
Use the `listunspent` RPC to list the funds that you have available: Use the `listunspent` RPC to list the funds that you have available:
``` ```
$ curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "listunspent", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ | jq -r '.' $ curl --user StandUp:4b42b0447b08784cb41adedac54d7f26 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "listunspent", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ 2> /dev/null | jq -r '.'
{ {
"result": [ "result": [
{ {
"txid": "e7071092dee0b2ae584bf6c1ee3c22164304e3a17feea7a32c22db5603cd6a0d", "txid": "80619fca79ce08e6c5405a8a241bb479be6d3d18256df859afb7b92c5f472465",
"vout": 1, "vout": 1,
"address": "mk9ry5VVy8mrA8SygxSQQUDNSSXyGFot6h", "address": "tb1qjrs9jr572nfyg5un8f2rzjdngml0mvskxlyd09",
"scriptPubKey": "76a91432db726320e4ad170c9c1ee83cd4d8a243c3435988ac", "scriptPubKey": "001490e0590e9e54d24453933a543149b346fefdb216",
"amount": 0.0009, "amount": 0.00194000,
"confirmations": 4, "confirmations": 1,
"spendable": true, "spendable": true,
"solvable": true, "solvable": true,
"desc": "pkh([d6043800/0'/1'/2']02881697d252d8bf181d08c58de1f02aec088cd2d468fc5fd888c6e39909f7fabf)#p6k7dptk", "desc": "wpkh([b8309bae/84h/1h/0h/1/3]0347d61d5a0d09bf411b059a8ee97225e3430171b303a71ec40c5f414029cd84db)#gl740gxy",
"parent_descs": [
"wpkh([b8309bae/84h/1h/0h]tpubDDpSvPDUjstxFUEWzHkaL4qykf8vjNCspm8SZ26Z1wgPFbd63AdYrn4bDpEGPT1giJ6gcLW8Xou8fnhi35DJrUza9ikgu5dg2mDkd8jQpA6/1/*)#eeegkjmk"
],
"safe": true "safe": true
}, },
{ {
"txid": "91261eafae15ea53dedbea7c1db748c52bbc04a85859ffd0d839bda1421fda4c", "txid": "80619fca79ce08e6c5405a8a241bb479be6d3d18256df859afb7b92c5f472465",
"vout": 0, "vout": 0,
"address": "mjehC2KHzXcBDcwTd4LhZ2GzyzrZ3Kd3ff", "address": "tb1qdu69s5f9nw8x88lvsc8nt5d7gy9rgtnef0upfu",
"label": "", "label": "",
"scriptPubKey": "76a9142d573900aa357a38afd741fbf24b075d263ea6e088ac", "scriptPubKey": "00146f345851259b8e639fec860f35d1be410a342e79",
"amount": 0.00022, "amount": 0.02000000,
"confirmations": 19, "confirmations": 1,
"spendable": true, "spendable": true,
"solvable": true, "solvable": true,
"desc": "pkh([d6043800/0'/0'/3']0278608b54b8fb0d8379d3823d31f03a7c6ab0adffb07dd3811819fdfc34f8c132)#nhjc3f8y", "desc": "wpkh([b8309bae/84h/1h/0h/0/11]03d9cbd48a1238cc2c7371fd0c7169995106db6dec9fb287e4490c08cbd2b35cf1)#n3vc09ew",
"parent_descs": [
"wpkh([b8309bae/84h/1h/0h]tpubDDpSvPDUjstxFUEWzHkaL4qykf8vjNCspm8SZ26Z1wgPFbd63AdYrn4bDpEGPT1giJ6gcLW8Xou8fnhi35DJrUza9ikgu5dg2mDkd8jQpA6/0/*)#gduft8tw"
],
"safe": true
},
{
"txid": "8a0d9ab73d81a1ce043d1ede0e737136e6d3352d3e0bc9590f9e8bbd91036dc2",
"vout": 0,
"address": "tb1q7xkh94r24zw4uc3wg2amkagxfm4an5gpwrgsnl",
"label": "",
"scriptPubKey": "0014f1ad72d46aa89d5e622e42bbbb75064eebd9d101",
"amount": 0.00099000,
"confirmations": 9,
"spendable": true,
"solvable": true,
"desc": "wpkh([b8309bae/84h/1h/0h/0/5]027650c44c6f71d50a173f3f18858490cf26d2661a1d9929deba9aca57c76d1e5b)#7ss7jfnn",
"parent_descs": [
"wpkh([b8309bae/84h/1h/0h]tpubDDpSvPDUjstxFUEWzHkaL4qykf8vjNCspm8SZ26Z1wgPFbd63AdYrn4bDpEGPT1giJ6gcLW8Xou8fnhi35DJrUza9ikgu5dg2mDkd8jQpA6/0/*)#gduft8tw"
],
"safe": true "safe": true
} }
], ],
@ -218,25 +280,24 @@ This is almost exactly the same output that you receive when you type `bitcoin-c
### Create an Address ### Create an Address
After you know where your funds are, the next step in crafting a transaction is to get 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: After you know where your funds are, the next step in crafting a transaction is to get 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. This example demonstrates the creation of an older "legacy" address, mainly so that we can demonstrate how an actual parameter works in the RPC interface.
``` ```
$ curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getrawchangeaddress", "params": ["legacy"] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ | jq -r '.' $ curl --user StandUp:4b42b0447b08784cb41adedac54d7f26 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getrawchangeaddress", "params": ["legacy"] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ 2> /dev/null | jq -r '.'
{ {
"result": "mrSqN37TPs89GcidSZTvXmMzjxoJZ6RKoz", "result": "n2cv88ogXyYSiGsVvRuAswetLnf7D7GRM5",
"error": null, "error": null,
"id": "curltest" "id": "curltest"
} }
``` ```
> **WARNING:** The parameters order is important when you are sending RPC commands using curl. There's only one argument for `getrawchangeaddress`, but consider its close cousin `getnewaddress`. That takes two arguments: first label, then type. If we sent that same `"params": ["legacy"]` instead of `"params": ["", "legacy"]`, we would get a `bech32` address with a label of `"legacy"` instead of a `legacy` address, so pay attention to the order! > ⚠️ **WARNING: Parameter Order Matters!** The parameters order is important when you are sending RPC commands using curl. There's only one argument for `getrawchangeaddress`, but consider its close cousin `getnewaddress`. That takes two arguments: first label, then type. If we sent that same `"params": ["legacy"]` instead of `"params": ["", "legacy"]`, we would get a `bech32` address with a label of `"legacy"` instead of a `legacy` address, so pay attention to the order!
At this point, we can even revert to our standard practice of saving results to variables with additional help from `jq`: At this point, we can even revert to our standard practice of saving results to variables with additional help from `jq`:
``` ```
$ newaddress=$(curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getrawchangeaddress", "params": ["legacy"] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ | jq -r '.result') $ newaddress=$(curl --user StandUp:4b42b0447b08784cb41adedac54d7f26 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getrawchangeaddress", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ 2> /dev/null | jq -r '.result')
$ echo $newaddress $ echo $newaddress
mqdfnjgWr2r3sCCeuTDfe8fJ1CnycF2e6R tb1qmp3jd7s9s0vgnyxtjdf50qua90s825alqrpktv
``` ```
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 ## Create a Transaction
@ -246,30 +307,30 @@ You're now ready to create a transaction with `curl`.
Just as with `bitcoin-cli`, in order to create a transaction by curling RPC commands, you should first save your variables. The only change here is that `curl` creates a JSON object that includes a `result` key-value, so you always need to pipe through the `.result` tag before you do anything else. Just as with `bitcoin-cli`, in order to create a transaction by curling RPC commands, you should first save your variables. The only change here is that `curl` creates a JSON object that includes a `result` key-value, so 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: This example sets up our variables for using the 0.00194000 BTC in funds listed in the first unspent transaction above:
``` ```
$ utxo_txid=$(curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "listunspent", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ | jq -r '.result | .[0] | .txid') $ utxo_txid=$(curl --user StandUp:4b42b0447b08784cb41adedac54d7f26 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "listunspent", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ 2> /dev/null | jq -r '.result | .[0] | .txid')
$ utxo_vout=$(curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "listunspent", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ | jq -r '.result | .[0] | .vout') $ utxo_vout=$(curl --user StandUp:4b42b0447b08784cb41adedac54d7f26 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "listunspent", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ 2> /dev/null | jq -r '.result | .[0] | .vout')
$ recipient=mwCwTceJvYV27KXBc3NJZys6CjsgsoeHmf $ recipient=tb1qg3lau83hm9e9tdvzr5k7aqtw3uv0dwkfct4xdn
$ changeaddress=$(curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getrawchangeaddress", "params": ["legacy"] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ | jq -r '.result') $ changeaddress=$(curl --user StandUp:4b42b0447b08784cb41adedac54d7f26 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getrawchangeaddress", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ 2> /dev/null | jq -r '.result')
$ echo $utxo_txid $ echo $utxo_txid
e7071092dee0b2ae584bf6c1ee3c22164304e3a17feea7a32c22db5603cd6a0d 80619fca79ce08e6c5405a8a241bb479be6d3d18256df859afb7b92c5f472465
$ echo $utxo_vout $ echo $utxo_vout
1 1
$ echo $recipient $ echo $recipient
mwCwTceJvYV27KXBc3NJZys6CjsgsoeHmf tb1qg3lau83hm9e9tdvzr5k7aqtw3uv0dwkfct4xdn
$ echo $changeaddress $ echo $changeaddress
n2jf3MzeFpFGa7wq8rXKVnVuv5FoNSJZ1N tb1q79st28w04n57z6ht8zasfrdy9804qe9u5l4ahf
``` ```
### Create the Transaction ### Create the Transaction
The transaction created with `curl` is very similar to the transaction created with `bitcoin-cli`, but with a few subtle differences: The transaction created with `curl` is very similar to the transaction created with `bitcoin-cli`, but with a few subtle differences:
``` ```
$ curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "createrawtransaction", "params": [''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]'', ''{ "'$recipient'": 0.0003, "'$changeaddress'": 0.0005}'']}' -H 'content-type: text/plain;' http://127.0.0.1:38332/ | jq -r '.' $ curl --user StandUp:4b42b0447b08784cb41adedac54d7f26 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "createrawtransaction", "params": [''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]'', ''{ "'$recipient'": 0.001, "'$changeaddress'": 0.0009}'']}' -H 'content-type: text/plain;' http://127.0.0.1:38332/ 2> /dev/null | jq -r '.'
{ {
"result": "02000000010d6acd0356db222ca3a7ee7fa1e3044316223ceec1f64b58aeb2e0de921007e70100000000ffffffff0230750000000000001976a914ac19d3fd17710e6b9a331022fe92c693fdf6659588ac50c30000000000001976a9147021efec134057043386decfaa6a6aa4ee5f19eb88ac00000000", "result": "02000000016524475f2cb9b7af59f86d25183d6dbe79b41b248a5a40c5e608ce79ca9f61800100000000fdffffff02a086010000000000160014447fde1e37d97255b5821d2dee816e8f18f6bac9905f010000000000160014f160b51dcface9e16aeb38bb048da429df5064bc00000000",
"error": null, "error": null,
"id": "curltest" "id": "curltest"
} }
@ -282,11 +343,11 @@ We've also varied up the quoting from how things worked in `bitcoin-cli`, to sta
However, there's one last thing of note in this example, and it can be _maddening_ if you miss it. When you executed a `createrawtransaction` command with `bitcoin-cli` the JSON array of inputs and the JSON object of outputs were each distinct parameters, so they were separated by a space. Now, because they're part of that `params` JSON array, they're separated by a comma (`,`). Miss that and you'll get a `parse error` without much additional information. However, there's one last thing of note in this example, and it can be _maddening_ if you miss it. When you executed a `createrawtransaction` command with `bitcoin-cli` the JSON array of inputs and the JSON object of outputs were each distinct parameters, so they were separated by a space. Now, because they're part of that `params` JSON array, they're separated by a comma (`,`). Miss that and you'll get a `parse error` 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). > ⚠️ **WARNING: Loggin Ahead.** 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 the hex code into a variable: Having verified that things work, you probably want to save the hex code into a variable:
``` ```
$ hexcode=$(curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "createrawtransaction", "params": [''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]'', ''{ "'$recipient'": 0.0003, "'$changeaddress'": 0.0005}'']}' -H 'content-type: text/plain;' http://127.0.0.1:38332/ | jq -r '.result') $ hexcode=$(curl --user StandUp:4b42b0447b08784cb41adedac54d7f26 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "createrawtransaction", "params": [''[ { "txid": "'$utxo_txid'", "vout": '$utxo_vout' } ]'', ''{ "'$recipient'": 0.0003, "'$changeaddress'": 0.0005}'']}' -H 'content-type: text/plain;' http://127.0.0.1:38332/ 2> /dev/null | jq -r '.result')
``` ```
### Sign and Send ### Sign and Send
@ -294,22 +355,25 @@ $ hexcode=$(curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '
Signing and sending your transaction using `curl` is an easy use of the `signrawtransactionwithwallet` and `sendrawtransaction` RPC: Signing and sending your transaction using `curl` is an easy use of the `signrawtransactionwithwallet` and `sendrawtransaction` RPC:
``` ```
$ signedhex=$(curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "signrawtransactionwithwallet", "params": ["'$hexcode'"] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ | jq -r '.result | .hex') $ signedhex=$(curl --user StandUp:4b42b0447b08784cb41adedac54d7f26 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "signrawtransactionwithwallet", "params": ["'$hexcode'"] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ 2> /dev/null | jq -r '.result | .hex')
$ curl --user StandUp:8eaf562eaf45c33c3328bc66008f2dd1 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "sendrawtransaction", "params": ["'$signedhex'"] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ | jq -r '.' $ curl --user StandUp:4b42b0447b08784cb41adedac54d7f26 --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "sendrawtransaction", "params": ["'$signedhex'"] }' -H 'content-type: text/plain;' http://127.0.0.1:38332/ 2> /dev/null | jq -r '.'
{ {
"result": "eb84c5008038d760805d4d9644ace67849542864220cb2685a1ea2c64176b82d", "result": "d4ce7ab7db122373567addca4aa5a2866fc617b720db8147748b4108834144ff",
"error": null, "error": null,
"id": "curltest" "id": "curltest"
} }
``` ```
Whew! We're not going to do that again! (Using `bitcoin-cli` is complex enough!)
## Summary: Accessing Bitcoind with Curl ## 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`. Which is why we're going to continue concentrating on `bitcoin-cli` following this digression. 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`. Which is why we're going to continue concentrating on `bitcoin-cli` following this digression.
But there are still reasons you'd use `curl` instead of `bitcoin-cli`: But there are still reasons you'd use `curl` instead of `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 that `bitcoin-cli` might do or how it might change over time. However, you're also taking your first steps toward using a more comprehensive programming language than the poor options offered by a shell script. As you'll see in the last few chapters of this, you might actually see curl libraries are other functions to access the RPC commands in a variety of programming languages: but that's still a long ways away. > 🔥 **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 that `bitcoin-cli` might do or how it might change over time. However, you're also taking your first steps toward using a more comprehensive programming language than the poor options offered by a shell script. Ultimately, you might use libraries that provide access to curl functionality to access the RPC commands in a variety of programming languages—but that goes beyond the scope of the command line.
## What's Next? ## What's Next?