Node.jsでモナコインを送金したかったが、できなかった。

ブツ

インストール&実行

NAME='Node.js.Electrum.Client.HelloWorld.20220920145313'
git clone https://github.com/ytyaru/$NAME
cd $NAME
npm install
node index.js

プロジェクト作成

NAME=hello-coininfo
mkdir $NAME
cd $NAME
npm init -y
npm i electrum-client
node index.js

ソースコード作成

前回のやつにnetworkの設定を追加した。coininfoMONAを指定すると返される。

vim index.js
'use strict;'

const ElectrumClient = require('electrum-client');
console.log('ElectrumClient:', ElectrumClient);
const cli = new ElectrumClient(50001, 'electrumx.tamami-foundation.org', 'tcp');
console.log('cli:', cli);
(async () => {
    const balance = await cli.getBalance('MEHCqJbgiNERCH3bRAtNSSD9uxPViEX1nu');
    console.log(balance);
})();

出力結果

ElectrumClient: [class ElectrumClient extends Client]
cli: ElectrumClient {
  id: 0,
  port: 50001,
  host: 'electrumx.tamami-foundation.org',
  callback_message_queue: {},
  subscribe: EventEmitter {
    _events: [Object: null prototype] {},
    _eventsCount: 0,
    _maxListeners: undefined,
    [Symbol(kCapture)]: false
  },
  conn: Socket {
    connecting: false,
    _hadError: false,
    _parent: null,
    _host: null,
    _readableState: ReadableState {
      objectMode: false,
      highWaterMark: 16384,
      buffer: BufferList { head: null, tail: null, length: 0 },
      length: 0,
      pipes: [],
      flowing: true,
      ended: false,
      endEmitted: false,
      reading: false,
      constructed: true,
      sync: true,
      needReadable: false,
      emittedReadable: false,
      readableListening: false,
      resumeScheduled: true,
      errorEmitted: false,
      emitClose: false,
      autoDestroy: true,
      destroyed: false,
      errored: null,
      closed: false,
      closeEmitted: false,
      defaultEncoding: 'utf8',
      awaitDrainWriters: null,
      multiAwaitDrain: false,
      readingMore: false,
      dataEmitted: false,
      decoder: [StringDecoder],
      encoding: 'utf8',
      [Symbol(kPaused)]: false
    },
    _events: [Object: null prototype] {
      end: [Array],
      connect: [Function (anonymous)],
      close: [Function (anonymous)],
      timeout: [Function (anonymous)],
      data: [Function (anonymous)],
      error: [Function (anonymous)]
    },
    _eventsCount: 6,
    _maxListeners: undefined,
    _writableState: WritableState {
      objectMode: false,
      highWaterMark: 16384,
      finalCalled: false,
      needDrain: false,
      ending: false,
      ended: false,
      finished: false,
      destroyed: false,
      decodeStrings: false,
      defaultEncoding: 'utf8',
      length: 0,
      writing: false,
      corked: 0,
      sync: true,
      bufferProcessing: false,
      onwrite: [Function: bound onwrite],
      writecb: null,
      writelen: 0,
      afterWriteTickInfo: null,
      buffered: [],
      bufferedIndex: 0,
      allBuffers: true,
      allNoop: true,
      pendingcb: 0,
      constructed: true,
      prefinished: false,
      errorEmitted: false,
      emitClose: false,
      autoDestroy: true,
      errored: null,
      closed: false,
      closeEmitted: false,
      [Symbol(kOnFinished)]: []
    },
    allowHalfOpen: false,
    _sockname: null,
    _pendingData: null,
    _pendingEncoding: '',
    server: null,
    _server: null,
    timeout: 10000,
    [Symbol(async_id_symbol)]: -1,
    [Symbol(kHandle)]: null,
    [Symbol(lastWriteQueueSize)]: 0,
    [Symbol(timeout)]: Timeout {
      _idleTimeout: 10000,
      _idlePrev: [TimersList],
      _idleNext: [TimersList],
      _idleStart: 337,
      _onTimeout: [Function: bound ],
      _timerArgs: undefined,
      _repeat: null,
      _destroyed: false,
      [Symbol(refed)]: false,
      [Symbol(kHasPrimitive)]: false,
      [Symbol(asyncId)]: 5,
      [Symbol(triggerId)]: 1
    },
    [Symbol(kBuffer)]: null,
    [Symbol(kBufferCb)]: null,
    [Symbol(kBufferGen)]: null,
    [Symbol(kCapture)]: false,
    [Symbol(kSetNoDelay)]: true,
    [Symbol(kSetKeepAlive)]: true,
    [Symbol(kSetKeepAliveInitialDelay)]: 0,
    [Symbol(kBytesRead)]: 0,
    [Symbol(kBytesWritten)]: 0
  },
  mp: MessageParser {
    buffer: '',
    callback: [Function (anonymous)],
    recursiveParser: [Function: recursiveParser]
  },
  status: 0
}
/tmp/work/Node.js.Electrum.Client.HelloWorld.20220920145313/index.js:8
    const balance = await cli.getBalance('MEHCqJbgiNERCH3bRAtNSSD9uxPViEX1nu');
                              ^

TypeError: cli.getBalance is not a function
    at /tmp/work/Node.js.Electrum.Client.HelloWorld.20220920145313/index.js:8:31
    at Object.<anonymous> (/tmp/work/Node.js.Electrum.Client.HelloWorld.20220920145313/index.js:10:3)
    at Module._compile (node:internal/modules/cjs/loader:1105:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1159:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12)
    at node:internal/main/run_main_module:17:47

あれ、getBalance()関数がないってさ。

ていうか、もしかしてパッケージが違うのかな?

試行2

とりあえずインストールしたパッケージを削除する。

npm uninstall electrum-client

electrum-clientのREADMEをみると以下のように書いてあった。

npm install @nimiq/electrum-client@https://github.com/nimiq/electrum-client#build

READMEと似たようなコードを書いてみる。

index.mjs

import { ElectrumApi } from '@nimiq/electrum-client'
const electrum = new ElectrumApi();
const balance = await electrum.getBalance('MEHCqJbgiNERCH3bRAtNSSD9uxPViEX1nu');
console.log(balance);

モジュールが見つからないと怒られる。公式のコードでもダメか……。

$ node index.mjs
node:internal/errors:465
    ErrorCaptureStackTrace(err);
    ^

Error [ERR_MODULE_NOT_FOUND]: Cannot find package '/tmp/work/Node.js.Electrum.Client.HelloWorld.20220920145313/node_modules/@nimiq/electrum-client/' imported from /tmp/work/Node.js.Electrum.Client.HelloWorld.20220920145313/index.mjs
    at new NodeError (node:internal/errors:372:5)
    at legacyMainResolve (node:internal/modules/esm/resolve:341:9)
    at packageResolve (node:internal/modules/esm/resolve:941:14)
    at moduleResolve (node:internal/modules/esm/resolve:1003:20)
    at defaultResolve (node:internal/modules/esm/resolve:1218:11)
    at ESMLoader.resolve (node:internal/modules/esm/loader:580:30)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:294:18)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:80:40)
    at link (node:internal/modules/esm/module_job:78:36) {
  code: 'ERR_MODULE_NOT_FOUND'
}

そもそもパッケージからしてこれでいいのかよくわからない。

そもそもelectrumもよくわからない。フルノードでない暗号通貨クライアントなのはわかるけど。SPV (Simplified Payment Verification) と呼ぶんだったかな?

それはわかるんだけど、electrum-clientを使ってそれをで実装する方法がわからない。指定されているURLやポート番号らしきものは今でも有効なのか? それを調べる必要があると思っていたのだが、それ以前のところでコケたようだ。

このelectrum-clientが送金処理をするっぽいので、使えないと送金できない。なんてこった……。またしても挫折。

原因はなんだろう。情報が古いのか。私が何か理解できてないのか。たぶん両方。

とりあえず使えたパッケージのecpairとcoininfoのほうをもう少し触ってみるか。

情報源