LoginSignup
6
0

More than 3 years have passed since last update.

catapult-sdkを使って直接APIノードにトランザクションを送信する

Posted at

はじめに

カタパルトでは、APIノードとmongoDBとRESTゲートウェイを建てるのが一般的です。

そして、これに加えて、アプリケーションサーバーなどを建てることになると思います。

しかし、そんなリソースがない場合もあると思います。APIノードとアプリケーションだけでなんとかしたいと思うこともあるかと思います。

例えば、IoTのような。ミニPC内にノードを建てて定期的にトランザクションを送信するなど。

そんな場合に備えて、Node.jsを使ってAPIノードにトランザクションを送る方法を試してみようと思います。

やる

APIノード起動

https://github.com/tech-bureau/catapult-service-bootstrap/tree/v0.3.0 などでノードを起動します。その際、APIノードの7900番にアクセスできるようにしておきます。

catapult-restの仕様

まず、catapult-restの仕様を調べます。

APIノードへの接続は、Node.jsのNetを使っているようです。catapult-sdkを使って、ノード認証して、そのあとでデータを送信しているようです。

以下のソースを読みました。

  • index.js
  • connectionService.js
  • catapultConnection.js
  • routeUtils.js
  • transactionRoutes.js

あとはこれを真似して作ればいいだけです。

フォルダ構成

まずは、プロジェクトを作ります。npm init -yとかで。

次に、下記リポジトリからcatapult-sdkをフォルダをごとコピーしてきます。

そのあと、package.jsonにリンク情報を書きます。

package.json
  "dependencies": {
    "catapult-sdk": "link:catapult-sdk"
  }

yarn installします(npm iではだめです)。するとシンボリックリンクが作られます。

最後に、メインの処理を書くためのindex.jsとかを作ります。

するとフォルダ構成は以下のようになってると思います。

/
│  index.js
│  package.json
│  yarn.lock
├─catapult-sdk
│  │  .babelrc
│  │  .eslintignore
│  │  .eslintrc
│  │  package-lock.json
│  │  package.json
│  │  yarn.lock
│  ├─node_modules
│  ├─src
│  ├─test
│  ├─_build
│  └─_build_browser
└─node_modules

コード

index.js
const catapult = require('catapult-sdk');
const net = require('net');

const config = {
    clientPrivateKey: '0000000000000000000000000000000000000000000000000000000000000000'
};
const node = {
    host: '13.115.141.239',
    port: '7910',
    publicKey: '6244B76B2385C47872E0EA2B6C746408D8021349A13DCAE007D3F6A58E472D01'
};

const serverSocket = net.createConnection(node.port, node.host);
const apiNodePublicKey = catapult.utils.convert.hexToUint8(node.publicKey);

const clientKeyPair = catapult.crypto.createKeyPairFromPrivateKeyString(config.clientPrivateKey);

const params = {
    payload: 'A5000000894A829717A6627C108BD69D56A188659C403A4E2C0CEDBB35F856AFD57713E9ACA553C68803E56E39683A9D18CBAF258BFCE043724C56175C53E425727C050FAC1A6E1D8DE5B17D2C6B1293F1CAD3829EEACF38D09311BB3C8E5A880092DE26039054410000000000000000F475D6151700000090FA39EC47E05600AFA74308A7EA607D145E371B5F4F1447BC0100010044B262C46CEABB850000000000000000',
    hash: '',
    signer: '',
    type: 16724,
    networkType: 144
};

serverSocket
    .on('error', err => {
        console.error(`error raised by ${node.host}:${node.port} connection`, err);
    })
    .on('close', () => {
        console.log('close');
    });

catapult.auth.createAuthPromise(serverSocket, clientKeyPair, apiNodePublicKey, console.log).then(() => {

    const connection = serverSocket;
    const packetHeader = catapult.packet.header;

    const createPacketFromBuffer = (data, packetType) => {
        const length = packetHeader.size + data.length;
        const header = packetHeader.createBuffer(packetType, length);
        const buffers = [header, Buffer.from(data)];
        return Buffer.concat(buffers, length);
    };

    const parser = params => {
        return catapult.utils.convert.hexToUint8(params.payload)
    };

    const packetType = catapult.packet.PacketType.pushTransactions;

    const packetBuffer = createPacketFromBuffer(parser(params), packetType);
    const payload = packetBuffer;

    return new Promise((resolve, reject) => {
        connection.write(payload, resolve);
    })

}).then(() => {
    const packetType = catapult.packet.PacketType.pushTransactions;
    console.log(
        { message: `packet ${packetType} was pushed to the network via transaction` }
    );
    serverSocket.destroy();
});

以下の箇所で、APIノードの設定をします。

const config = {
    clientPrivateKey: '任意の秘密鍵'
};
const node = {
    host: 'ノードのIPかFQDN',
    port: 'ノードのポート番号',
    publicKey: 'ノードの公開鍵'
};

以下の箇所で、トランザクションを設定します。payloadだけでよいです。


const params = {
    payload: 'A5000000894A829717A6627C108BD69D56A188659C403A4E2C0CEDBB35F856AFD57713E9ACA553C68803E56E39683A9D18CBAF258BFCE043724C56175C53E425727C050FAC1A6E1D8DE5B17D2C6B1293F1CAD3829EEACF38D09311BB3C8E5A880092DE26039054410000000000000000F475D6151700000090FA39EC47E05600AFA74308A7EA607D145E371B5F4F1447BC0100010044B262C46CEABB850000000000000000',
    hash: '',
    signer: '',
    type: 16724,
    networkType: 144
};

実行

>node index.js
received data with size 8
received data with size 64
writing response of length: 169
received data with size 8
received data with size 64
client challenge verified? true
{ message: 'packet 9 was pushed to the network via transaction' }
close

createAuthPromiseの段階で、なにかをやりとりしているようです。

その次に、トランザクションを送っています。この送ったトランザクションが妥当だったかどうかはわかりません。

RESTゲートウェイに問い合わせるか、mongoDBから情報を取得する必要があります。unconfirmedにすらなっていない場合は、失敗していると思います。

送信データ

APIノードへ送信したデータはこんな感じでした。

AD00000009000000A5000000894A829717A6627C108BD69D56A188659C403A4E2C0CEDBB35F856AFD57713E9ACA553C68803E56E39683A9D18CBAF258BFCE043724C56175C53E425727C050FAC1A6E1D8DE5B17D2C6B1293F1CAD3829EEACF38D09311BB3C8E5A880092DE26039054410000000000000000F475D6151700000090FA39EC47E05600AFA74308A7EA607D145E371B5F4F1447BC0100010044B262C46CEABB850000000000000000

最初の4バイトでデータのサイズを指定します。0xADなので173バイトのデータです。

次の4バイトでパケットタイプを指定します。0x09なので、9です。

パケットタイプが何なのかは、ここに少し載っています。

そのあとに、トランザクションが続いています。

おわりに

おわり

6
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
0