4 - 3 使用 JQ
這邊要學會用 JQ 來處理 JSON 資料
用 key 取出在一個 JSON 的某個值
我們用 signrawtransaction
會產生一個 hex
值,我們試著用 JQ 將它取出
基本指令是 jq -r '.'
, -r
表示輸出原型資料,'.'
表示要輸出什麼
$ bitcoin-cli signrawtransaction $rawtxhex | jq -r '.hex'
0200000001735dfa1584b930a78ad2c1d6db72dd2a80ae5e5d552ad97e19f1d50d41fdd6d8000000006a47304402202210ce4b2a037da02622c380278cd79fec4e0e016e66f3eb894a2dcbb9ee998f02202cac167e6abdbbf08af139fb7c6b86e9d2e58e5516cd566ae2d54953ead9923b012102111bb978a3c93a00038ae344a1a017d7fee8a9be9d0558b5793ce6f440704a96ffffffff01b0e78604000000001976a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac00000000
這樣可以取出 hex 值,我們可以進一步將一堆指令變數化,以後方便取用
$ signedtx=$(bitcoin-cli signrawtransaction $rawtxhex | jq -r '.hex')
$ echo $signedtx
0200000001735dfa1584b930a78ad2c1d6db72dd2a80ae5e5d552ad97e19f1d50d41fdd6d8000000006a47304402202210ce4b2a037da02622c380278cd79fec4e0e016e66f3eb894a2dcbb9ee998f02202cac167e6abdbbf08af139fb7c6b86e9d2e58e5516cd566ae2d54953ead9923b012102111bb978a3c93a00038ae344a1a017d7fee8a9be9d0558b5793ce6f440704a96ffffffff01b0e78604000000001976a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac00000000
可以這樣用
$ bitcoin-cli sendrawtransaction $signedtx
3f9ccb6e16663e66dc119de1866610cc4f7a83079bfec2abf0598ed3adf10a78
Use JQ to Access singel JSON object value in array by key (超難翻譯所以不翻XD)
當我們想要從陣列裡挑出某個項目,例如 listunspent 裡挑出想要的 UTXO,可以這樣做
$ bitcoin-cli listunspent | jq -r '.[0]'
{
"txid": "03e99644fff32f9d7fc68e1b3253ed1ee9ddc1371c41a0a8e29b1f01ca06f4d9",
"vout": 0,
"address": "mrR54buSCnMnf9cBGSrg4zCrWdDnyiQkdM",
"account": "",
"scriptPubKey": "76a914778c899d7364cc5c33e5e07d622e31b3798d60f588ac",
"amount": 1.3,
"confirmations": 305,
"spendable": true,
"solvable": true,
"safe": true
}
從 UTXO 裡面挑出第一個,在 ' '
裡面可以繼續的 pipeline,傳遞更多想做的動作,
例如:從某一個 UTXO 裡面挑出 txid
$ bitcoin-cli listunspent | jq -r '.[0] | .txid'
03e99644fff32f9d7fc68e1b3253ed1ee9ddc1371c41a0a8e29b1f01ca06f4d9
如此我們可以創造出很多好用的變數
$ newtxid=$(bitcoin-cli listunspent | jq -r '.[0] | .txid')
$ newvout=$(bitcoin-cli listunspent | jq -r '.[0] | .vout')
Use JQ to access matching JSON object values in an array by key
不只可以列出某一個 UTXO 的某個值,還可以列出所有同個 key 的值,要用的是 '.[]'
$ bitcoin-cli listunsepnt | jq -r '.[] | .amount'
Use JQ for simple caculations by key
現在可以運用 JQ 和 awk 來做數學運算
$ bitcoin-cli listunspent | jq -r '.[] | .amount' | awk '{s+=$1} END {print s}'
//print the total amount output by JQ
也可以挑出 JSON 資料裡的多個值並輸出
$ bitcoin-cli listunspent | jq -r '.[] | .txid, .vout, .amount'
03e99644fff32f9d7fc68e1b3253ed1ee9ddc1371c41a0a8e29b1f01ca06f4d9
0
1.3
3850dd518b8402210eec76ac20230fab6ceb8522d068730ba97247b0b91763e8
0
0.84504001
54bfa8a2e05b087cd3b9c455c95817b87b7f1eb6b9fa7a0c6de29f2a8e36e5ef
0
0.83108164
JQ 也有功能可以美化這些輸出
$ bitcoin-cli listunspent | jq -r '.[] | {txid: .txid, vout: .vout, amount: .amount}'
{
"txid": "03e99644fff32f9d7fc68e1b3253ed1ee9ddc1371c41a0a8e29b1f01ca06f4d9",
"vout": 0,
"amount": 1.3
}
{
"txid": "3850dd518b8402210eec76ac20230fab6ceb8522d068730ba97247b0b91763e8",
"vout": 0,
"amount": 0.84504001
}
{
"txid": "54bfa8a2e05b087cd3b9c455c95817b87b7f1eb6b9fa7a0c6de29f2a8e36e5ef",
"vout": 0,
"amount": 0.83108164
}
現在我們要學會多層的取值,例如從 rawtransaction 裡取得 vin, vout 裡面的東西
其實也很簡單,假設一筆交易有兩個 vin, 兩個 vout,想要取vin值:
$ usedtxid1=$(bitcoin-cli decoderawtransaction $rawtxhex | jq -r '.vin | .[0] | .txid')
$ usedtxid2=$(bitcoin-cli decoderawtransaction $rawtxhex | jq -r '.vin | .[1] | .txid')
$ usedvout1=$(bitcoin-cli decoderawtransaction $rawtxhex | jq -r '.vin | .[1] | .vout')
$ usedvout2=$(bitcoin-cli decoderawtransaction $rawtxhex | jq -r '.vin | .[1] | .vout')
但好麻煩喔,每次都要打一大串,是不是可以類似像陣列一樣取值呢?可以的
$ usedtxid=($(bitcoin-cli decoderawtransaction $rawtxhex | jq -r '.vin | .[] | .txid'))
$ echo ${usedtxid[0]}
($(command))
意思是將東西存成陣列的意思, ${variable[n]}
是取出第幾個的意思,所以我們可以用陣列的方式取出
現在可以取出某個符合 txid
, vout
的 UTXO,運用 select, contains
$ bitcoin-cli listunspent | jq -r '.[] |
> select (.txid | contains("'${usedtxid[0]}'")) |
> select(.vout | contsins('${usedvout[0]}'))'
$ bitcoin-cli listunspent | jq -r '.[] |
> select (.txid | contains("'${usedtxid[1]}'")) |
> select(.vout | contsins('${usedvout[1]}'))'
上面的指令可以用 for-loop 合併
$ for ((i=0; i<${#usedtxid[*]}; i++);
> do txid=${usedtxid[i]};
> vout=${usedvout[i]};
> bitcoin-cli listunspent | jq -r '.[] | select(.txid | contains("'${txid}'")) | select(.vout | contains('${vout}'))'; done;
${#usedtxid[*]}
是取陣列大小
現在可以計算一筆交易的手續費
想法是把一筆交易的 vin 對應的交易的 BTC 數量總和,減掉這筆交易的 vout 的 BTC 數量總和,就是手續費
(一筆交易可以能有多個 vin 、多個 vout)
1. $ usedtxid=($(bitcoin-cli decoderawtransaction $rawtxhex | jq -r '.vin | .[] | .txid'))
2. $ usedvout=($(bitcoin-cli decoderawtransaction $rawtxhex | jq -r '.vin | .[] | .vout'))
3. $ btcin=$(for ((i=0; i<${#usedtxid[*]}; i++)); do txid=${usedtxid[i]}; vout=${usedvout[i]}; bitcoin-cli listunspent | jq -r '.[] | select (.txid | contains("'${txid}'")) | select(.vout | contains('$vout')) | .amount'; done | awk '{s+=$1} END {print s}')
4. $ btcout=$(bitcoin-cli decoderawtransaction $rawtxhex | jq -r '.vout [] | .value' | awk '{s+=$1} END {print s}')
5. $ echo "$btcin-$btcout"| /usr/bin/bc
.255
把 vin 的 txid 變數化
把 vin 的 vout 變數化
從 UTXO 裡面用 usedtxid, usedtxvout 把交易裡面的 vin 的 BTC 數量加起來
將交易裡面的 vout 的 BTC 數量加起來
相減獲得手續費,這邊是將算式導到 bin/bc 讓 linux 計算這個式子