Node.jsを使ってピアノードから情報を取得する

Node.jsを使用するバージョンです。

https://qiita.com/ccHarvestasya/items/d38ee4a2ab5e343c2f20#%E3%83%AC%E3%82%B9%E3%83%9D%E3%83%B3%E3%82%B9%E3%82%92%E8%A7%A3%E8%AA%AD

```typescript
import fs from "fs";
import tls from "tls";

const HOST = "symbol02.harvestasya.com";
const PORT = 7900;
const NODE_DISCOVERY_PULL_PING = 0x111;

function getNodeInfo() {
  let connectionOptions: tls.ConnectionOptions = {
    host: HOST,
    port: PORT,
    cert: fs.readFileSync("cert/node.full.crt.pem"),
    key: fs.readFileSync("cert/node.key.pem"),
    rejectUnauthorized: false,
  };

  let socket = tls.connect(connectionOptions, function () {
    // Symbolヘッダー作成
    const symbolHeaderBuffer = new ArrayBuffer(8);
    const symbolHeaderView = new DataView(symbolHeaderBuffer);
    symbolHeaderView.setUint32(0, 8, true);
    symbolHeaderView.setUint32(4, NODE_DISCOVERY_PULL_PING, true);
    // ヘッダ送信
    socket.write(new Uint8Array(symbolHeaderBuffer));
  });

  socket.on("connect", () => {
    console.log("client connected");
  });

  socket.on("secureConnect", () => {
    const peerX509 = socket.getPeerX509Certificate();
    if (peerX509 === undefined) return;

    const validTo = peerX509.validTo;
    const validToDate = new Date(validTo);
    console.log("notAfter                  : " + validToDate);
    console.log(
      "nodePublicKey             : " +
        peerX509.publicKey
          .export({ format: "der", type: "spki" })
          .toString("hex", 12, 44)
          .toUpperCase()
    );
  });

  socket.once("data", (data) => {
    // レスポンスデータ（ヘッダ）取得
    const nodeBufferView = Buffer.from(new Uint8Array(data).buffer);
    // レスポンスサイズチェック
    let resSize = nodeBufferView.readUInt32LE(0);
    if (resSize === 0) {
      console.error(`${HOST}から受信したデータが空です。`);
      socket.end();
      return;
    }
    // レスポンスパケットタイプチェック
    let packetType = nodeBufferView.readUInt32LE(4);
    if (packetType !== NODE_DISCOVERY_PULL_PING) {
      console.error(
        `パケットタイプ${NODE_DISCOVERY_PULL_PING}を期待しましたが、${packetType}でした。`
      );
      socket.end();
      return;
    }

    // ヘッダが問題なければノード情報解析
    socket.on("data", (data) => {
      const nodeBufferView = Buffer.from(new Uint8Array(data).buffer);
      let resSize = nodeBufferView.readUInt32LE(0);
      let version = nodeBufferView.readUInt32LE(4);
      let publicKey = nodeBufferView.toString("hex", 8, 40).toUpperCase();
      let networkGenerationHashSeed = nodeBufferView
        .toString("hex", 40, 72)
        .toUpperCase();
      let roles = nodeBufferView.readUInt32LE(72);
      let port = nodeBufferView.readUInt16LE(76);
      let networkIdentifier = nodeBufferView.readUInt8(78);
      let hostLength = nodeBufferView.readUInt8(79);
      let friendlyNameLength = nodeBufferView.readUInt8(80);
      let host = nodeBufferView.toString("utf8", 81, 81 + hostLength);
      let friendlyName = nodeBufferView.toString(
        "utf8",
        81 + hostLength,
        81 + hostLength + friendlyNameLength
      );
      console.log(`version                   : ${version}`);
      console.log(`publicKey                 : ${publicKey}`);
      console.log(`networkGenerationHashSeed : ${networkGenerationHashSeed}`);
      console.log(`roles                     : ${roles}`);
      console.log(`port                      : ${port}`);
      console.log(`networkIdentifier         : ${networkIdentifier}`);
      console.log(`host                      : ${host}`);
      console.log(`friendlyName              : ${friendlyName}`);

      socket.end();
    });
  });

  socket.on("end", function () {
    console.log("Connection ended");
  });

  socket.on("close", function () {
    console.log("Connection closed");
  });

  socket.on("error", function (error) {
    console.error(error);
    socket.destroy();
  });
}

getNodeInfo();
```