Node.jsでモナコインの送金がしたい。そのコード例と思しきものを読んでみた。さっぱり理解できなかった。

経緯

モナコインを送金する方法を調べたとき、コメントで以下を紹介してもらった。

今回はこれを調査する。Node.jsでモナコインの送金ができるようになるはず。それができればElectronでも同じことができるはず。ElectronでMpurseが使えなかった(Chrome拡張機能サポートを使用してもダメ)としても送金できるようになるはず、だと思いたい。

これまでの調査

これまでモナコインを送金するプログラムを調査してきた。

  • MasteringBitcoin PDFを読んで暗号通貨のトランザクション概念について学ぶ
  • Mpurse APIで送金する
  • mpchain APIで送金する
  • Node.jsで送金する

Mpurse APIならできるが、それ以外はまだわからない。Mpurseは内部でmpchain APIを呼び出しているようだが、その使い方がよくわからなかった。Node.jsでの方法は未調査だったため、今回はそれをやってみようと思う。

本当はフルノードをインストールして基礎となるコマンドから勉強するのがよさそう。でも取引データのサイズが膨大すぎてムリ。そこで軽量ノードであるelectrumのモナコイン版を入れようと思ったが、できなかった。

今回はのこる最後の手がかりNode.jsでの方法を探る。

調査

sample-sending-monacoin/app.js

記事をみるとフルノードいらずでモナコイン授受する方法としてsample-sending-monacoin/app.jsコードがあるという話らしい。

タイトルからして送金処理かと。私にはコードを見てもどこで何をしているのかよくわからなかった。まずは雰囲気で読んでみる。

使用パッケージ

コードでは以下のようなパッケージを利用していた。

const bitcoin = require('bitcoinjs-lib');
const coininfo = require('coininfo');
const coinselect = require('coinselect');
const ElectrumClient = require('electrum-client');

こいつらの役割分担すらわからない。

キーワードで読む

おそらくelectrum-clientを使って、指定サーバに送金処理を依頼している。そのために必要な細かい処理をbitcoinjs-lib, coininfo, coinselectでやっているのだと思われる。

bitcoin

const keyPair = bitcoin.ECPair.fromWIF(wif, network);
const fromAddress = keyPair.getAddress().toString();

coininfo

const network = coininfo('MONA').toBitcoinJS();

coinselect

  .then(utxos => coinselect(utxos, targets, feeRate))

electrum-client

const ElectrumClient = require('electrum-client');
const cli = new ElectrumClient(50001, 'electrumx.tamami-foundation.org', 'tcp');
cli.connect()
  .then(() =>
    cli.subscribe.on('blockchain.headers.subscribe', (v) => console.log(v)))
  .then(() => cli.server_version('2.7.11', '1.0'))
  .then(console.log)
  .then(() => cli.blockchainAddress_listunspent(fromAddress))
  .then(utxos => coinselect(utxos, targets, feeRate))
  .then(res => {
    // .inputs and .outputs will be undefined if no solution was found 
    if (!res.inputs) throw new Error('No input');
    if (!res.outputs) throw new Error('No output');

    let txb = new bitcoin.TransactionBuilder(network);
 
    res.inputs.forEach(input => txb.addInput(input.tx_hash, input.tx_pos));

    res.outputs.forEach(output => {
      // watch out, outputs may have been added that you need to provide 
      // an output address/script for 
      if (!output.address) {
        output.address = fromAddress;
      }
 
      txb.addOutput(output.address, output.value);
    });

    for (let i = 0; i < res.outputs.length; i++) {
      txb.sign(i, keyPair);
    }
    return txb.build().toHex();
  })
  .then(hex => cli.blockchainTransaction_broadcast(hex))
  .then(console.dir)
  .then(() => cli.close())
  .catch(console.error);

最後の長い処理が送金処理だと思われる。

  1. 入力するコインと出力するコインを設定する: input, output
  2. 署名する: sign
  3. 送金処理を依頼する: broadcast

キーワードからそう判断した。

所感

さっぱりわからないので、まずは各パッケージを個別に使ってみることからはじめたほうが良さそう。とくにelectrum-clientbitcoinjs-libがキモと思われる。