Catapult Rest開発のすゝめ

この記事はSymbolのREST改造する際のTipsです。

https://qiita.com/monakaJP/items/7614896d7aba6aee3e6c#%E3%83%93%E3%83%AB%E3%83%89

# 概要
SymbolのREST APIのプラグインを作成する際に、毎回Dockerイメージのビルドするの面倒くさいなぁ～と思ったのでそのまま`npm run start`で起動出来るようにしました（以下の修正を行わないと`npm run start`をしてもエラーで起動出来ません）

# 前提条件
- symbol-bootstrapが起動出来る
- mainnet or testnet を一度でも起動したことがある

# リポジトリのクローン

https://github.com/symbol/symbol

```bash
$ git clone git@github.com:symbol/symbol.git 
```

# 事前準備

- mainnet or testnetの設定ファイルをコピー

symbol-bootstrapの実行ディレクトリ内 `target/gateways/rest-gateway/api-node-config`をコピーします。

```bash
$ cp -fr target/gateways/rest-gateway/api-node-config symbol/client/rest/resources
```

- symbol-bootstrapで起動しているdbのIPAddressを調べる

```bash
$ docker ps # ←これで表示されるdbのコンテナIDを使用
$ docker inspect "コンテナID" | grep "IPAddress"
            "SecondaryIPAddresses": null,
            "IPAddress": "",
                    "IPAddress": "172.20.0.2", # ←コレ
```

# Rest 設定ファイルの修正


```symbol/client/resources/rest.json
{
  "network": {
    "name": "testnet",
    "description": "Symbol Custom Network"
  },
  "port": 3030, # bootstrapで起動してるrestとかぶらないポート番号を指定
  "protocol": "HTTP", # HTTPS →　HTTP
  "sslKeyPath": "",
  "sslCertificatePath": "",
  "crossDomain": {
    "allowedHosts": ["*"],
    "allowedMethods": ["GET", "POST", "PUT", "OPTIONS"]
  },
  "uncirculatingAccountPublicKeys": [
    "A4739036FD7EFED2750A51EE9D1D3113BA3F9849E0889213CED7F221B2AA1A20",
    "2BF1E1F3072E3BE0CD851E4741E101E33DB19C163895F69AA890E7CF177C878C",
    "E85D10BF47FFBCE2230F70CB43ED2DDE04FCF342524B383972F86EA1FF773C79",
    "FE454406EFC15EBBCF4C27491519B7EBE696AD2D734A53E02019FC5D02D1419C"
  ],
  "extensions": [
    "accountLink",
    "aggregate",
    "lockHash",
    "lockSecret",
    "mosaic",
    "metadata",
    "multisig",
    "namespace",
    "receipts",
    "restrictions",
    "transfer"
  ],
  "db": {
    "url": "mongodb://172.20.0.2:27017/",  # 調べたIPAddress
    "name": "catapult",
    "pageSizeMin": 10,
    "pageSizeMax": 100,
    "maxConnectionAttempts": 15,
    "baseRetryDelay": 750,
    "connectionPoolSize": 10
  },
  "apiNode": {
    "host": "127.0.0.1",
    "port": 7900,
    "timeout": 1000,

    # 以下コピーした設定ファイルのパスを記述
    "tlsClientCertificatePath": "/symbol/client/rest/resources/api-node-config/cert/node.crt.pem",
    "tlsClientKeyPath": "/symbol/client/rest/resources/api-node-config/cert/node.key.pem",
    "tlsCaCertificatePath": "/symbol/client/rest/resources/api-node-config/cert/ca.cert.pem",
    "networkPropertyFilePath": "/symbol/client/rest/resources/api-node-config/config-network.properties",
    "nodePropertyFilePath": "/symbol/client/rest/resources/api-node-config/config-node.properties",
    "inflationPropertyFilePath": "/symbol/client/rest/resources/api-node-config/config-inflation.properties"
  },

  "websocket": {
    "mq": {
      "host": "127.0.0.1",
      "port": 7902,
      "monitorInterval": 500,
      "connectTimeout": 10000,
      "monitorLoggingThrottle": 60000,
      "maxSubscriptions": 500
    },
    "allowOptionalAddress": true
  },

  "throttling": {
    "burst": 20,
    "rate": 5
  },

  "logging": {
    "console": {
      "formats": ["colorize", "simple"],

      "level": "verbose",
      "handleExceptions": true
    },
    "file": {
      "formats": ["prettyPrint"],

      "level": "verbose",
      "handleExceptions": true,

      "filename": "catapult-rest.log",
      "maxsize": 20971520,
      "maxFiles": 100
    }
  },

  "numBlocksTransactionFeeStats": 300,

  "deployment": {
    "deploymentTool": "",
    "deploymentToolVersion": "",
    "lastUpdatedDate": ""
  },

  "nodeMetadata": {
    "_info": "replace the body of this object with custom fields and objects to personalize your node"
  }
}
```

- 設定ファイルのパスの修正

`client/rest/src/index.js`を修正

```client/rest/src/index.js
const loadConfig = () => {
	let configFiles = process.argv.slice(2);
	if (0 === configFiles.length)
		// configFiles = ['../resources/rest.json'];
        // 相対パスだとエラーになるので絶対パスで指定
		configFiles = ['/symbol/client/rest/resources/rest.json'];

	let config;
	configFiles.forEach(configFile => {
		winston.info(`loading config from ${configFile}`);
		const partialConfig = JSON.parse(fs.readFileSync(configFile, 'utf8'));
		if (config) {
			// override config
			catapult.utils.objects.checkSchemaAgainstTemplate(config, partialConfig);
			catapult.utils.objects.deepAssign(config, partialConfig);
		} else {
			// primary config
			config = partialConfig;
		}
	});
```

以上で準備完了。

# Restサーバーの起動

```bash
$ cd symbol/client/rest
$ npm run start
```

うまくいけばログが出てRestサーバーが起動します。

`http://IPAddress:3030/chain/info`などにアクセスできればOKです。

これで毎回Dockerイメージをビルドする必要がなくなったので開発が捗りますね！

※symbol-bootstrapでノードを起動している必要があります。