取引手数料を算出するために探した。たぶん発見したが、データをデコードできなかった。
前回まで
- モナコインの取引トランザクションを取得する方法を調べた
- Mastering Bitcoin 日本語訳PDFを読んでみる(UXTO)
- MasteringBitcoin日本語訳を読む(トランザクション手数料)
vin
にあるtxid
から入力用トランザクションを取得し、その残高を使って支払う。それは理解できた。
では、完了した取引データから手数料を算出・取得するには、どうしたらいいの? たぶんvin
のtxid
を引数にして、それに紐づくトランザクションデータを取得するAPIがあるのではないか?
今回
txid
からトランザクションデータを取得する方法を調べた。
たぶんAPIは発見したが、その結果にはデコードが必要っぽい。そのためのAPIらしきものを実行するも失敗するので、本当にトランザクションデータが取得できているかどうか確認できなかった。
まとめ
getrawtransaction
おそらくtxid
で指定されたトランザクション情報は以下で取得できる。
const txid = 'e1e94be2b6f541e6639d9bd1cce79ac9a668dd25b0c3bd5f48c411ade94f8003'
await window.mpurse.counterParty('get_tx_info', {tx_hex: await window.mpurse.counterParty('getrawtransaction', {tx_hash: txid})});
ただ、それで取得された値は以下のように謎の文字列である。
010000000119b25983f61ad0b58fbdcac01025be3b6f6d341cb11641b1e0d935e4f78a627b010000006b483045022100e7b36a5115a86326b91d0bf89407df78733850c63e041a51a913f3f09f6df13e022048896aaa5b71ababf66323b8bc8ed25e1b3a423ed643b5a7acf484dcf4f3afbf012103aedd2422519c7ea14e48116b571903c16d2b4657d4a3ffc0e35646cd7e53be3dffffffff02c0175302000000001976a9145bef72db1e9a105cf734ead06ef87a54f1d39a3588acffe3e30c000000001976a91413bd7f2032c935652371722ae6d987f2f8135aac88ac00000000
decoderawtransaction
ネットでググるとdecoderawtransaction
なるAPIがあるらしい。そいつでデコードするとJSONデータになるっぽい。
- https://qiita.com/Naomasa/items/36bdcf93bb3f085bd3da
- https://github.com/bitcoin/bitcoin/issues/15872
でも、そんなAPIは以下ドキュメントのどこにも書いていなかった。
一応試してみたが、やはりダメだった。
API | 結果 |
---|---|
CounterParty API | そんなメソッドねーよ |
CounterBlock API | このエンドポイントはcouterblock apiだけだよ(いやお前がcouterblock apiじゃないのかよ。どゆこと?) |
たぶんググった資料が古いとか、なんか知らない事情があるのだろう。ここで詰まった。これ以上は追えない。
CounterParty API
await window.mpurse.counterParty('decoderawtransaction', {tx_hash: '010000000119b25983f61ad0b58fbdcac01025be3b6f6d341cb11641b1e0d935e4f78a627b010000006b483045022100e7b36a5115a86326b91d0bf89407df78733850c63e041a51a913f3f09f6df13e022048896aaa5b71ababf66323b8bc8ed25e1b3a423ed643b5a7acf484dcf4f3afbf012103aedd2422519c7ea14e48116b571903c16d2b4657d4a3ffc0e35646cd7e53be3dffffffff02c0175302000000001976a9145bef72db1e9a105cf734ead06ef87a54f1d39a3588acffe3e30c000000001976a91413bd7f2032c935652371722ae6d987f2f8135aac88ac00000000'});
{
"code": -32000,
"data": {
"args": [
"{\"message\": \"Method not found\", \"code\": -32601}"
],
"message": "{\"message\": \"Method not found\", \"code\": -32601}",
"type": "Exception"
},
"message": "Server error"
}
decoderawtransaction
なんてメソッドはCounterParty APIには存在しませんよ、だってさ。
CounterBlock API
await window.mpurse.counterBlock('decoderawtransaction', {tx_hash: '010000000119b25983f61ad0b58fbdcac01025be3b6f6d341cb11641b1e0d935e4f78a627b010000006b483045022100e7b36a5115a86326b91d0bf89407df78733850c63e041a51a913f3f09f6df13e022048896aaa5b71ababf66323b8bc8ed25e1b3a423ed643b5a7acf484dcf4f3afbf012103aedd2422519c7ea14e48116b571903c16d2b4657d4a3ffc0e35646cd7e53be3dffffffff02c0175302000000001976a9145bef72db1e9a105cf734ead06ef87a54f1d39a3588acffe3e30c000000001976a91413bd7f2032c935652371722ae6d987f2f8135aac88ac00000000'});
Uncaught This endpoint is the couterblock api only.
このエンドポイントはcouterblock api
だけですよ、だってさ。君がそのcouterblock api
じゃないんかい。じゃあ君は何者? mpurse
の呼出メソッド名だってcounterBlock
じゃん。今までずっとそう思ってたんですけど?
お手上げです。
txid
からトランザクションデータの取得はたぶん成功している。あとはデコードができればいい。でも、デコードAPIがないからできない。一旦ここで諦める。
経緯
以下、結論に至るまでの経緯。
mpurse API
txid
はモナコインの取引トランザクションを取得する方法を調べたときのものを使う。e1e94be2b6f541e6639d9bd1cce79ac9a668dd25b0c3bd5f48c411ade94f8003
...
"vin": [
{
"scriptSig": {
"asm": "3045022100b18c83115da395e12791b717b32aff754865cac478bb4e72ddde0f0e6c28b28d0220716c20fcd5151e4aeb8c2f898b9735713a596ff8daac03d7169e207c2e4e6743[ALL] 03aedd2422519c7ea14e48116b571903c16d2b4657d4a3ffc0e35646cd7e53be3d",
"hex": "483045022100b18c83115da395e12791b717b32aff754865cac478bb4e72ddde0f0e6c28b28d0220716c20fcd5151e4aeb8c2f898b9735713a596ff8daac03d7169e207c2e4e6743012103aedd2422519c7ea14e48116b571903c16d2b4657d4a3ffc0e35646cd7e53be3d"
},
"sequence": 4294967295,
"txid": "e1e94be2b6f541e6639d9bd1cce79ac9a668dd25b0c3bd5f48c411ade94f8003",
"vout": 1
}
],
...
mpurseのREADMEからtransaction
で文字列検索する。ヒットしたAPIは以下2つ。
でも、名前や戻り値からして違うっぽい。となると、難しそうな以下APIを使うことになるのだろう。
mpurse#mpchain
mpurseのREADMEからリンクをたどるとmpchainにいく。ここにAPIが網羅されている。この中からtransaction関係のものは以下2つ。
- Send Transaction
- Transaction
目的は取得なのでSend Transaction
ではない。あとはTransaction
のみ。エンドポイントをみると以下。
/api/tx/{tx_index}
/api/tx/{tx_hash}
引数にしたい値はtxid
。なんか違わないか?
戻り値をみてみると、すごいたくさんある。Send
がそれっぽいかな? でも宛先のアドレスがないように見える。
...
Send: {
asset: string,
asset_group: string,
asset_longname: string,
block_index: number,
destination: string,
fungible: boolean,
memo: string,
memo_hex: string,
quantity: string,
source: string,
status: string,
timestamp: number,
tx_hash: string,
tx_index: number,
tx_type: string
}
...
まあいいや。とりあえず試してみよう。以下URLをブラウザで叩いてみる。
https://mpchain.info/api/tx/e1e94be2b6f541e6639d9bd1cce79ac9a668dd25b0c3bd5f48c411ade94f8003
するとエラーが返ってきた。あんれー? このAPIではないのかな?
{"error":"Transaction not found"}
mpurse#counterblock
引数をみるとアドレスになっている。txid
じゃない。
get_raw_transactions(address, start_ts=None, end_ts=None, limit=500):
こちらもts
とかいう謎の値。txid
じゃない。
get_transaction_stats(start_ts=None, end_ts=None)
検索するキーワードをtransaction
からtx
にしてみる。
名前からしてget
が目的のものだろう。create
やconvert
は違うはず。
あれ、引数がない。txid
を渡せない。
get_chain_txns_status
一応ほかの2つも見てみる。引数にtx
のキーワードはある。でもtxid
ではない。たぶん違う。
create_armory_utx(unsigned_tx_hex, public_key_hex)
convert_armory_signedtx_to_raw_hex(signed_tx_ascii)
mpurse#counterparty
transaction
をキーワードに文字列検索する。
party getrawtransaction
お、これかも?
getrawtransaction(tx_hash, verbose=false, skip_missing=false)
引数のtx_hash
は、txid
とは違うのかな?
tx_hash (string): The transaction hash identifier
Return:
If found, a raw transaction objects having the same format as the bitcoind getrawtransaction API call. If not found, null.
戻り値はトランザクション・オブジェクトだという。
さて、これをmpurse APIから叩くにはどうすればいいか。mpurse#counterpartyのコード例をみてみよう。
const cpParams = {address: 'MLinW5mA2Rnu7EjDQpnsrh6Z8APMBH6rAt'};
const unspentTxouts = await window.mpurse.counterParty('get_unspent_txouts', cpParams);
ん? このunspent
だのtx
だのout
だのっていうキーワードには見覚えがある。もしやこれ、vout
をゲットするAPIでは? ちがうか。名前から察するに、まだ消耗していないUXTO
データを取得しようとしているのか。ん? それってvin
にするためのトランザクションデータを取得するってことじゃないのか? もしかして支払いするときこのAPIでvin
になる取引データを取得するのかな?
なんにせよ、get_unspent_txouts
は今回ほしいものじゃない。私がほしいのはvin
のtxid
を引数にして、それを取得するやつ。
とりあえず話を戻そう。getrawtransaction
APIがそれかどうか確認する。以下コードでイケるんじゃないか?
const cpParams = {tx_hash: 'e1e94be2b6f541e6639d9bd1cce79ac9a668dd25b0c3bd5f48c411ade94f8003'};
const unspentTxouts = await window.mpurse.counterParty('getrawtransaction', cpParams);
これをHTTPSにアップロードしたページで開いたデベロッパツールのコンソールで実行してみる。ytyaruのプロフィールでいいだろう。ついでにワンライナーにしておく。変数に代入しないようにすれば、時間経過で表示されるはず。
await window.mpurse.counterParty('getrawtransaction', {tx_hash: 'e1e94be2b6f541e6639d9bd1cce79ac9a668dd25b0c3bd5f48c411ade94f8003'});
確かに何かが返ってきた。でも、JSONオブジェクトではなく、英数字の羅列だった。なにこれ。思ってたのと違う。次。
010000000119b25983f61ad0b58fbdcac01025be3b6f6d341cb11641b1e0d935e4f78a627b010000006b483045022100e7b36a5115a86326b91d0bf89407df78733850c63e041a51a913f3f09f6df13e022048896aaa5b71ababf66323b8bc8ed25e1b3a423ed643b5a7acf484dcf4f3afbf012103aedd2422519c7ea14e48116b571903c16d2b4657d4a3ffc0e35646cd7e53be3dffffffff02c0175302000000001976a9145bef72db1e9a105cf734ead06ef87a54f1d39a3588acffe3e30c000000001976a91413bd7f2032c935652371722ae6d987f2f8135aac88ac00000000
party getrawtransaction_batch
getrawtransaction_batch(txhash_list, verbose=false, skip_missing=false)
名前や引数txhash_list
からして複数形っぽい。違うな。
party search_raw_transactions
search_raw_transactions(address, unconfirmed=true)
これは違う。指定したアドレスの全トランザクションを取得するやつ。前に使ったから知ってる。
あんれー? どこにあるの?
tx
をキーワードに探してみる
party get_unspent_txouts
get_unspent_txouts(address, unconfirmed=false, unspent_tx_hash=null)
引数がアドレス。txid
じゃない。
戻り値は以下。
A list of objects, with each entry in the dict having the following properties:
- **amount**: The amount of the UTXO (e.g. 0.12345678)
- **value**: The value of the UTXO in satoshis (e.g. 12345678)
- **height**: The block height of the UTXO
- **confirmations**: Number of confirmations since the UTXO was created
- **txid**: The txid (hash) that the UTXO was included in
- **vout**: The vout number in the specified txid for the UTXO
UXTO
という覚えたての用語を発見。txid
もあった。でも戻り値じゃんか。あ、でもtxid (hash)
って書いてる。やはりtxid
はhash
で、tx_hash
のことだと思っていいのかな?
なんにせよ、このAPIではなさそう。
party get_tx_info
これかもしれん。
get_tx_info(tx_hex, block_index=null)
引数はtx_hex
。たぶんtxid
だろう。そして戻り値もなんかそれっぽい。fee
は手数料だし。btc_amount
はビットコイン量のことだろう。モナコインだとどうなるか知らないけど。とにかくそれっぽい雰囲気。
A list with the following items (in order as listed below):
- `source`
- `destination`
- `btc_amount`
- `fee`
- `data`: The embedded raw protocol data, in hexadecimal-serialized format
こいつをmpurse APIで叩いてみる。
await window.mpurse.counterParty('get_tx_info', {tx_hash: 'e1e94be2b6f541e6639d9bd1cce79ac9a668dd25b0c3bd5f48c411ade94f8003'});
エラーが返ってきた。
{
"code": -32000,
"data": {
"args": [
"get_tx_info() got an unexpected keyword argument 'tx_hash'"
],
"message": "get_tx_info() got an unexpected keyword argument 'tx_hash'",
"type": "Exception"
},
"message": "Server error"
}
tx_hash
が予期しないキーワード引数だと? どういうことだ。ならblock_index
にしてみるか。
await window.mpurse.counterParty('get_tx_info', {block_index: 'e1e94be2b6f541e6639d9bd1cce79ac9a668dd25b0c3bd5f48c411ade94f8003'});
{
"code": -32000,
"data": {
"args": [
"get_tx_info() missing 1 required positional argument: 'tx_hex'"
],
"message": "get_tx_info() missing 1 required positional argument: 'tx_hex'",
"type": "Exception"
},
"message": "Server error"
}
必須引数tx_hex
をよこせ、だってさ。なら以下でいいのか?
await window.mpurse.counterParty('get_tx_info', {tx_hex: 'e1e94be2b6f541e6639d9bd1cce79ac9a668dd25b0c3bd5f48c411ade94f8003'});
{
"code": -32000,
"data": {
"args": [
"Asked to read 32 bytes, but only got 27"
],
"message": "Asked to read 32 bytes, but only got 27",
"type": "Exception"
},
"message": "Server error"
}
32バイト必要なのに27バイトしかねーぞゴルァ! だそうです。知らんがな。この長ったらしいtxid
は65文字あるんですけどねぇ。32だの27だの、一体何の数字なの?
ていうか、引数名がそれぞれ何を指しているのかわからん。網羅してみよう。
txid
tx_hex
tx_hash
tx_index
block_index
ああ、最初のミスはtx_hex
をtx_hash
と勘違いしていたせいか。でも、名前を正してもダメだった。そもそもtx_hex
とやらはtxid
と同じって認識でいいの? 違うんだろうなぁ。じゃあ一体なんなんだ? どうしたらvin
にあったtxid
から金額をゲットできるの? そこから手数料を算出したかったのに。
見返してみたら、getrawtransaction
の戻り値って16進数じゃないか?
await window.mpurse.counterParty('getrawtransaction', {tx_hash: 'e1e94be2b6f541e6639d9bd1cce79ac9a668dd25b0c3bd5f48c411ade94f8003'});
010000000119b25983f61ad0b58fbdcac01025be3b6f6d341cb11641b1e0d935e4f78a627b010000006b483045022100e7b36a5115a86326b91d0bf89407df78733850c63e041a51a913f3f09f6df13e022048896aaa5b71ababf66323b8bc8ed25e1b3a423ed643b5a7acf484dcf4f3afbf012103aedd2422519c7ea14e48116b571903c16d2b4657d4a3ffc0e35646cd7e53be3dffffffff02c0175302000000001976a9145bef72db1e9a105cf734ead06ef87a54f1d39a3588acffe3e30c000000001976a91413bd7f2032c935652371722ae6d987f2f8135aac88ac00000000
もしやこれ、tx_hex
というやつでは? hex
って16進数のことだし。ということは、以下のようにしてみたらイケるかも?
await window.mpurse.counterParty('get_tx_info', {tx_hex: '010000000119b25983f61ad0b58fbdcac01025be3b6f6d341cb11641b1e0d935e4f78a627b010000006b483045022100e7b36a5115a86326b91d0bf89407df78733850c63e041a51a913f3f09f6df13e022048896aaa5b71ababf66323b8bc8ed25e1b3a423ed643b5a7acf484dcf4f3afbf012103aedd2422519c7ea14e48116b571903c16d2b4657d4a3ffc0e35646cd7e53be3dffffffff02c0175302000000001976a9145bef72db1e9a105cf734ead06ef87a54f1d39a3588acffe3e30c000000001976a91413bd7f2032c935652371722ae6d987f2f8135aac88ac00000000'});
え、525エラーだと。
Uncaught StatusCodeError: 525 - {"data":"Server is not caught up. Please try again later.","message":"Server error","code":-32000}
もう一回。
{
"code": -32602,
"data": {
"args": [
"argument of type 'NoneType' is not iterable"
],
"message": "argument of type 'NoneType' is not iterable",
"type": "TypeError"
},
"message": "Invalid params"
}
え、無効な引数? なんでNoneType
? nullになってるの? ちゃんと文字列渡したじゃん。
そういえば、32
バイト必要っていってたな。引数のtx_hex
は32バイトの16進数値ってこと? それってtxid
から取得できるの?
読み返すと、counterBlockのほうに以下のようなAPIがあった。
convert_armory_signedtx_to_raw_hex(signed_tx_ascii)
mpurse APIを介して実行するなら以下。引数signed_tx_ascii
がなんなのか知らないが、txid
を渡してみる。
await window.mpurse.counterBlock('convert_armory_signedtx_to_raw_hex', {signed_tx_ascii: 'e1e94be2b6f541e6639d9bd1cce79ac9a668dd25b0c3bd5f48c411ade94f8003'});
{
"code": -32000,
"data": {
"args": [
"Got call_jsonrpc_api request error: result is None -- is the 'http://armory-utxsvr:6590/' endpoint operational?"
],
"message": "Got call_jsonrpc_api request error: result is None -- is the 'http://armory-utxsvr:6590/' endpoint operational?",
"type": "Exception"
},
"message": "Server error"
}
call_jsonrpc_apiリクエストエラーが発生しました:結果はNoneです-「http:// armory-utxsvr:6590 /」エンドポイントは機能していますか?
お前は何を言っているんだ? まるでわからん。たぶんconvert_armory_signedtx_to_raw_hex
APIの中でcall_jsonrpc_api
というAPIを呼び出しているのだろう。で、そのホストサーバがhttp://armory-utxsvr:6590/
だけど機能してなくね? ってことかな?
armory
、武器庫って意味らしいが。これ暗号通貨の用語でいうと何を指す語なんだ? ウォレットのことではないのだろうし。トランザクション情報を保存する場所のことかな? わからん。
もしやビットコインとモナコインの保存サーバが違うから取り出せないとか?
だめだ。わからん。
最初にもどってみる
ここで私の取引データを取得する。以下APIで。
await window.mpurse.counterParty('search_raw_transactions', {address: 'MEHCqJbgiNERCH3bRAtNSSD9uxPViEX1nu'});
その結果、取引データのひとつの中にvin
があり、その要素にtxid
がある。これはらいうさんが私に送金したとき、その入力として使ったトランザクションデータ。らいうさんの所持金が入っていたはず。
...
"vin": [
{
"scriptSig": {
"asm": "3045022100b18c83115da395e12791b717b32aff754865cac478bb4e72ddde0f0e6c28b28d0220716c20fcd5151e4aeb8c2f898b9735713a596ff8daac03d7169e207c2e4e6743[ALL] 03aedd2422519c7ea14e48116b571903c16d2b4657d4a3ffc0e35646cd7e53be3d",
"hex": "483045022100b18c83115da395e12791b717b32aff754865cac478bb4e72ddde0f0e6c28b28d0220716c20fcd5151e4aeb8c2f898b9735713a596ff8daac03d7169e207c2e4e6743012103aedd2422519c7ea14e48116b571903c16d2b4657d4a3ffc0e35646cd7e53be3d"
},
"sequence": 4294967295,
"txid": "e1e94be2b6f541e6639d9bd1cce79ac9a668dd25b0c3bd5f48c411ade94f8003",
"vout": 1
}
],
...
もしや、らいうさんの全トランザクションデータの中から探せばいいのか?
たとえばさっきの取引データの中にあるvout
にはhex
がある。これとさっきのtxid
が一致するやつがあるのでは? でもこれscriptPubKey
って書いてあるし。なんだよscriptPubKey
って。
というか、過去のデータって、もうなくなっているのでは? vin
として使ったのだから、その取引により支払額と手数料が差し引かれたはずだし。この方法はダメな気がする。
"vout": [
{
"n": 0,
"scriptPubKey": {
"addresses": [
"MEHCqJbgiNERCH3bRAtNSSD9uxPViEX1nu"
],
"asm": "OP_DUP OP_HASH160 45fc13c9d3a0df34008291492c39e0efcdd220b8 OP_EQUALVERIFY OP_CHECKSIG",
"hex": "76a91445fc13c9d3a0df34008291492c39e0efcdd220b888ac",
"reqSigs": 1,
"type": "pubkeyhash"
},
"value": 1.14114
},
{
"n": 1,
"scriptPubKey": {
"addresses": [
"M9hY5XcC7MSD54DfqcEojiKm9QMgXeQhGK"
],
"asm": "OP_DUP OP_HASH160 13bd7f2032c935652371722ae6d987f2f8135aac OP_EQUALVERIFY OP_CHECKSIG",
"hex": "76a91413bd7f2032c935652371722ae6d987f2f8135aac88ac",
"reqSigs": 1,
"type": "pubkeyhash"
},
"value": 1.02124906
}
],
一応やってみる。らいうさんのアドレスを引数にして全トランザクションを取得する。
const transactions = await window.mpurse.counterParty('search_raw_transactions', {address: 'M9hY5XcC7MSD54DfqcEojiKm9QMgXeQhGK'});
transactions.length;
実行時点で292
件の取引があるようだ。その中からhex
がtxid
値e1e94be2b6f541e6639d9bd1cce79ac9a668dd25b0c3bd5f48c411ade94f8003
と同じものを探す。もしあれば1件だけ存在するはず。
const transactions = await window.mpurse.counterParty('search_raw_transactions', {address: 'M9hY5XcC7MSD54DfqcEojiKm9QMgXeQhGK'});
transactions.filter(t=>0<t.vout.filter(o=>o.scriptPubKey.hex=='e1e94be2b6f541e6639d9bd1cce79ac9a668dd25b0c3bd5f48c411ade94f8003').length);
空だった。ゼロ件。なし。
やっぱりないか。つまりscriptPubKey
のhex
とtxid
は別物なんだろう。
じゃあ、txid
というのをキーにして、どうやって取引データを取得すればいい? それがわからない。その取引の手数料がいくらだったかをどうやって取得・算出すればいいの?
ググる
ググってみた。するとgetrawtransaction
の結果をdecoderawtransaction
でデコードすればJSONになるらしい。
- https://qiita.com/Naomasa/items/36bdcf93bb3f085bd3da
- https://github.com/bitcoin/bitcoin/issues/15872
ただ、decoderawtransaction
というAPIはドキュメントに載ってなかったと思うのだが。
とりあえずgetrawtransaction
すると、なんかよくわからん文字列が返ってくる。
await window.mpurse.counterParty('getrawtransaction', {tx_hash: 'e1e94be2b6f541e6639d9bd1cce79ac9a668dd25b0c3bd5f48c411ade94f8003'});
010000000119b25983f61ad0b58fbdcac01025be3b6f6d341cb11641b1e0d935e4f78a627b010000006b483045022100e7b36a5115a86326b91d0bf89407df78733850c63e041a51a913f3f09f6df13e022048896aaa5b71ababf66323b8bc8ed25e1b3a423ed643b5a7acf484dcf4f3afbf012103aedd2422519c7ea14e48116b571903c16d2b4657d4a3ffc0e35646cd7e53be3dffffffff02c0175302000000001976a9145bef72db1e9a105cf734ead06ef87a54f1d39a3588acffe3e30c000000001976a91413bd7f2032c935652371722ae6d987f2f8135aac88ac00000000
こいつをdecoderawtransaction
に渡す。
await window.mpurse.counterParty('decoderawtransaction', {tx_hash: '010000000119b25983f61ad0b58fbdcac01025be3b6f6d341cb11641b1e0d935e4f78a627b010000006b483045022100e7b36a5115a86326b91d0bf89407df78733850c63e041a51a913f3f09f6df13e022048896aaa5b71ababf66323b8bc8ed25e1b3a423ed643b5a7acf484dcf4f3afbf012103aedd2422519c7ea14e48116b571903c16d2b4657d4a3ffc0e35646cd7e53be3dffffffff02c0175302000000001976a9145bef72db1e9a105cf734ead06ef87a54f1d39a3588acffe3e30c000000001976a91413bd7f2032c935652371722ae6d987f2f8135aac88ac00000000'});
{
"code": -32000,
"data": {
"args": [
"{\"message\": \"Method not found\", \"code\": -32601}"
],
"message": "{\"message\": \"Method not found\", \"code\": -32601}",
"type": "Exception"
},
"message": "Server error"
}
やっぱり「そんなメソッドねーよ」って怒られるじゃん。どうすりゃいいの。
一応、CounterBlock APIのほうでも実行してみたが。
await window.mpurse.counterBlock('decoderawtransaction', {tx_hash: '010000000119b25983f61ad0b58fbdcac01025be3b6f6d341cb11641b1e0d935e4f78a627b010000006b483045022100e7b36a5115a86326b91d0bf89407df78733850c63e041a51a913f3f09f6df13e022048896aaa5b71ababf66323b8bc8ed25e1b3a423ed643b5a7acf484dcf4f3afbf012103aedd2422519c7ea14e48116b571903c16d2b4657d4a3ffc0e35646cd7e53be3dffffffff02c0175302000000001976a9145bef72db1e9a105cf734ead06ef87a54f1d39a3588acffe3e30c000000001976a91413bd7f2032c935652371722ae6d987f2f8135aac88ac00000000'});
Uncaught This endpoint is the couterblock api only.
「このエンドポイントは couterblock api のみです」だと? え、君がそのCounterBlock APIではなかったの? わけわかめ。
CounterParty APIでdecoderawtransaction
を試す
mpchain APIで指定したアドレスの全トランザクションを取得する方法を調べたとき、mpurse APIでなく生のCounterParty APIを実行した。
curl -X POST -H "Content-Type: application/json" -d '{"id":0,"jsonrpc":"2.0","method":"proxy_to_counterpartyd","params":{"method":"search_raw_transactions", "params":{"address":"MEHCqJbgiNERCH3bRAtNSSD9uxPViEX1nu"}}}' https://mpchain.info/api/cb/
そのときのコマンドである上記を参考に、以下のようにしてみた。
curl -X POST -H "Content-Type: application/json" -d '{"id":0,"jsonrpc":"2.0","method":"proxy_to_counterpartyd","params":{"method":"decoderawtransaction", "params":{"tx_hash":"010000000119b25983f61ad0b58fbdcac01025be3b6f6d341cb11641b1e0d935e4f78a627b010000006b483045022100e7b36a5115a86326b91d0bf89407df78733850c63e041a51a913f3f09f6df13e022048896aaa5b71ababf66323b8bc8ed25e1b3a423ed643b5a7acf484dcf4f3afbf012103aedd2422519c7ea14e48116b571903c16d2b4657d4a3ffc0e35646cd7e53be3dffffffff02c0175302000000001976a9145bef72db1e9a105cf734ead06ef87a54f1d39a3588acffe3e30c000000001976a91413bd7f2032c935652371722ae6d987f2f8135aac88ac00000000"}}}' https://mpchain.info/api/cb/
{"error":{"code":-32000,"data":{"args":["{\"message\": \"Method not found\", \"code\": -32601}"],"message":"{\"message\": \"Method not found\", \"code\": -32601}","type":"Exception"},"message":"Server error"},"id":0,"jsonrpc":"2.0"}
やはりmpurse APIでCounterParty APIを実行したときと同じエラー。
CounterBlock APIでdecoderawtransaction
を試す
では、mpurseのソースコードutil.mpchain.ts#L209を参考にして、今度はCounterBlock APIをcurlで叩いてみよう。
curl -X POST -H "Content-Type: application/json" -d '{"id":0,"jsonrpc":"2.0","method":"decoderawtransaction","params":{"tx_hash":"010000000119b25983f61ad0b58fbdcac01025be3b6f6d341cb11641b1e0d935e4f78a627b010000006b483045022100e7b36a5115a86326b91d0bf89407df78733850c63e041a51a913f3f09f6df13e022048896aaa5b71ababf66323b8bc8ed25e1b3a423ed643b5a7acf484dcf4f3afbf012103aedd2422519c7ea14e48116b571903c16d2b4657d4a3ffc0e35646cd7e53be3dffffffff02c0175302000000001976a9145bef72db1e9a105cf734ead06ef87a54f1d39a3588acffe3e30c000000001976a91413bd7f2032c935652371722ae6d987f2f8135aac88ac00000000"}}' https://mpchain.info/api/cb/
{"error":"This endpoint is the couterblock api only."}
やはりCounterBlock APIをmpurse API経由で叩いたときと同じ結果になった。
引数調整
もう一度ググったときのURL先をみてみる。
curl --user yourAuth --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "decoderawtransaction", "params": ["0100000000010115a16270d3ee7ccc58a0757c1d8e1763790f223d4e4c3823948fb3dfdf9865180100000000ffffffff023f3256000000000017a9142915a7db6c6df171fd0436c7cec0042195dad01c8738ee4647000000001600140aad95e932ba045c2daf31a04c36683d39efe91002473044022002537539ac9586fdd8b5947fa0a47dc002ebe57502608433e103efe2740f93d4022023b1ade7bdf0f002a8fdc4ec6d534588d2132ab88850ac426ea413b4adb465260121031ef964af6923a2111e4916afcc87c73a8980322cc761dd3648714dfda99e72c400000000"] }' -H 'content-type: text/plain;' http://yourEndPoint
なんか引数が微妙に違う。上にあわせてみる。
curl -X POST -H "Content-Type: application/json" -d '{"id":"curltest","jsonrpc":"1.0","method":"decoderawtransaction","params":["010000000119b25983f61ad0b58fbdcac01025be3b6f6d341cb11641b1e0d935e4f78a627b010000006b483045022100e7b36a5115a86326b91d0bf89407df78733850c63e041a51a913f3f09f6df13e022048896aaa5b71ababf66323b8bc8ed25e1b3a423ed643b5a7acf484dcf4f3afbf012103aedd2422519c7ea14e48116b571903c16d2b4657d4a3ffc0e35646cd7e53be3dffffffff02c0175302000000001976a9145bef72db1e9a105cf734ead06ef87a54f1d39a3588acffe3e30c000000001976a91413bd7f2032c935652371722ae6d987f2f8135aac88ac00000000"]}' https://mpchain.info/api/cb/
{"error":"This endpoint is the couterblock api only."}
ダメだ。変わらない。これ以上は追えない。降参。お手上げ。まいりました。
まとめ
おそらくtxid
で指定されたトランザクション情報は以下で取得できる。
const txid = 'e1e94be2b6f541e6639d9bd1cce79ac9a668dd25b0c3bd5f48c411ade94f8003'
await window.mpurse.counterParty('get_tx_info', {tx_hex: await window.mpurse.counterParty('getrawtransaction', {tx_hash: txid})});
ただ、それで取得された値は以下のように謎の文字列である。
010000000119b25983f61ad0b58fbdcac01025be3b6f6d341cb11641b1e0d935e4f78a627b010000006b483045022100e7b36a5115a86326b91d0bf89407df78733850c63e041a51a913f3f09f6df13e022048896aaa5b71ababf66323b8bc8ed25e1b3a423ed643b5a7acf484dcf4f3afbf012103aedd2422519c7ea14e48116b571903c16d2b4657d4a3ffc0e35646cd7e53be3dffffffff02c0175302000000001976a9145bef72db1e9a105cf734ead06ef87a54f1d39a3588acffe3e30c000000001976a91413bd7f2032c935652371722ae6d987f2f8135aac88ac00000000
ネットでググるとdecoderawtransaction
なるAPIがあるらしい。そいつでデコードするとJSONデータになるっぽい。
- https://qiita.com/Naomasa/items/36bdcf93bb3f085bd3da
- https://github.com/bitcoin/bitcoin/issues/15872
でも、そんなAPIは以下ドキュメントのどこにも書いていなかった。
一応試してみたが、やはりダメだった。
API | 結果 |
---|---|
CounterParty API | そんなメソッドねーよ |
CounterBlock API | このエンドポイントはcouterblock apiだけだよ(いやお前がcouterblock apiじゃないのかよ。どゆこと?) |
await window.mpurse.counterParty('decoderawtransaction', {tx_hash: '010000000119b25983f61ad0b58fbdcac01025be3b6f6d341cb11641b1e0d935e4f78a627b010000006b483045022100e7b36a5115a86326b91d0bf89407df78733850c63e041a51a913f3f09f6df13e022048896aaa5b71ababf66323b8bc8ed25e1b3a423ed643b5a7acf484dcf4f3afbf012103aedd2422519c7ea14e48116b571903c16d2b4657d4a3ffc0e35646cd7e53be3dffffffff02c0175302000000001976a9145bef72db1e9a105cf734ead06ef87a54f1d39a3588acffe3e30c000000001976a91413bd7f2032c935652371722ae6d987f2f8135aac88ac00000000'});
{
"code": -32000,
"data": {
"args": [
"{\"message\": \"Method not found\", \"code\": -32601}"
],
"message": "{\"message\": \"Method not found\", \"code\": -32601}",
"type": "Exception"
},
"message": "Server error"
}
await window.mpurse.counterBlock('decoderawtransaction', {tx_hash: '010000000119b25983f61ad0b58fbdcac01025be3b6f6d341cb11641b1e0d935e4f78a627b010000006b483045022100e7b36a5115a86326b91d0bf89407df78733850c63e041a51a913f3f09f6df13e022048896aaa5b71ababf66323b8bc8ed25e1b3a423ed643b5a7acf484dcf4f3afbf012103aedd2422519c7ea14e48116b571903c16d2b4657d4a3ffc0e35646cd7e53be3dffffffff02c0175302000000001976a9145bef72db1e9a105cf734ead06ef87a54f1d39a3588acffe3e30c000000001976a91413bd7f2032c935652371722ae6d987f2f8135aac88ac00000000'});
Uncaught This endpoint is the couterblock api only.
データはたぶん取得できているから、あとはデコードができればいい。でも、デコードAPIがないからできない。
以上。
追記
コメント頂きました。ありがとうございます!
Counterparty や Counterblock は、セカンドレイヤ・チェーン (Counterparty やモナパーティ)のために存在します。 ファーストレイヤー (Bitcoin やモナコイン) の情報は一部しか提供しません。
そうだったのですね。私はそれすら知りませんでした。L1:MONA
, L2:XMP
という区切りがあるのは以前、別の記事のコメントで教えていただきましたが、今やっていることがその境界線上にあることだっとは。
仰る「手数料」がモナコインの採掘手数料を指すなら、
そうです。
モナコインを対象とするブロックチェーン・エクスプローラを利用する必要があります。たとえば https://blockbook.electrum-mona.org/ です。API の使い方は GitHub にあります。https://github.com/trezor/blockbook/blob/master/docs/api.md#get-transaction
ブロックチェーン・エクスプローラというのがあるのですね。これも知りませんでした。
リンク先を見て、リクエストURLを作り、試してみます。
https://blockbook.electrum-mona.org/api/v2/tx/e1e94be2b6f541e6639d9bd1cce79ac9a668dd25b0c3bd5f48c411ade94f8003
{"txid":"e1e94be2b6f541e6639d9bd1cce79ac9a668dd25b0c3bd5f48c411ade94f8003","version":1,"vin":[{"txid":"7b628af7e435d9e0b14116b11c346d6f3bbe2510c0cabd8fb5d01af68359b219","vout":1,"sequence":4294967295,"n":0,"addresses":["M9hY5XcC7MSD54DfqcEojiKm9QMgXeQhGK"],"isAddress":true,"value":"255284356","hex":"483045022100e7b36a5115a86326b91d0bf89407df78733850c63e041a51a913f3f09f6df13e022048896aaa5b71ababf66323b8bc8ed25e1b3a423ed643b5a7acf484dcf4f3afbf012103aedd2422519c7ea14e48116b571903c16d2b4657d4a3ffc0e35646cd7e53be3d"}],"vout":[{"value":"39000000","n":0,"hex":"76a9145bef72db1e9a105cf734ead06ef87a54f1d39a3588ac","addresses":["MGHGa55FH7CcaJdNqJZZb3YCPuZAn2iMUF"],"isAddress":true},{"value":"216261631","n":1,"spent":true,"hex":"76a91413bd7f2032c935652371722ae6d987f2f8135aac88ac","addresses":["M9hY5XcC7MSD54DfqcEojiKm9QMgXeQhGK"],"isAddress":true}],"blockHash":"f413585659148cdfc442975bb9bd9de8dddfafe2ccaad1fa3f394280988ae7b1","blockHeight":2633653,"confirmations":72901,"blockTime":1649863002,"value":"255261631","valueIn":"255284356","fees":"22725","hex":"010000000119b25983f61ad0b58fbdcac01025be3b6f6d341cb11641b1e0d935e4f78a627b010000006b483045022100e7b36a5115a86326b91d0bf89407df78733850c63e041a51a913f3f09f6df13e022048896aaa5b71ababf66323b8bc8ed25e1b3a423ed643b5a7acf484dcf4f3afbf012103aedd2422519c7ea14e48116b571903c16d2b4657d4a3ffc0e35646cd7e53be3dffffffff02c0175302000000001976a9145bef72db1e9a105cf734ead06ef87a54f1d39a3588acffe3e30c000000001976a91413bd7f2032c935652371722ae6d987f2f8135aac88ac00000000"}
キタ━━━━(゚∀゚)━━━━!!
ちゃんとJSONです。アドレスもそれっぽい。
けど、value
がおかしい。たぶん金額だと思うけど、少数でなく整数になっている。
らいうさんに教えていただいたURLの内容と見比べてみるで。こちらは小数点だし、単位がMONA
になっている。
アドレス | 金額 | 今回value |
---|---|---|
M9hY5XcC7MSD54DfqcEojiKm9QMgXeQhGK | 2.55284356 MONA | 255261631 , 255284356 |
MGHGa55FH7CcaJdNqJZZb3YCPuZAn2iMUF | 0.39 MONA | 39000000 |
M9hY5XcC7MSD54DfqcEojiKm9QMgXeQhGK | 2.16261631 MONA | 216261631 |
(Fee) | 0.00022725 MONA | 22725 |
vout
の配列のうち最後の要素にvin
のvalue
と同じ値のvalueIn
があるvalueIn - value = fees
fees
は手数料。すでに計算されてJSONのプロパティとして存在している
たしかモナコインの最小単位は小数点以下8桁。それを整数にした値がvalue
だと思われる。たぶん浮動小数点だと誤差が出るから整数にした、とかそんな理由だと予想する。あるいは、value
はMONA
とは別の単位なのかもしれない。サトシだかワタナベだが、そんな感じの単位があるってMasteringBitcoin日本語訳PDFに書いてあったような。それかな? でも8桁も違ったっけ?
とにかくfees
に0.000000001
を掛けた値がモナになると思われる。つまり以下の式。
fees * (0.1 ** 8) = ? MONA
話を最初に戻す。まとめてみよう。
モナコインの取引トランザクションを取得する方法を調べたの方法で、指定アドレスの全トランザクション情報を取得する。取引一件あたりvin
がある。それは支払に使うデータであり「支払額+手数料」以上の額が入った取引データである。実際のデータは入っておらず参照用IDのみ。それはtxid
で示されている。
このtxid
から実際の取引データを取得するには「ブロックチェーン・エクスプローラ」を使う。そのAPIによってtxid
に相当する取引データをJSONで取得できる。そこにはすでにトランザクション手数料をあらわすfees
プロパティが存在する。ただしその金額は謎の単位である。MONA
に変換するには0.1**8
倍する必要がある。
こんな感じかな。
- 今まで支払った手数料の全額は、全取引データの
vin
の中にあるtxid
から、今回の方法で取得したものを合算すればいい
でも、それをやったら取引件数だけリクエストすることになる。サーバへの負荷は大丈夫なのだろうか。
ところで、マイナーのアドレスは取得できないのかな? この手数料はどのアドレスに支払われたのだろう。それを取得できそうな値はJSON内に無さそう。
トランザクション情報の取得って思った以上に大変なんだなぁ。