HerokuでTokenURI用JSONサーバーを構築（OpenSea）

[FLOCスマートコントラクト開発科](https://floc.jp/course/engsmart/)では、受講生の皆さんと一緒に、RinkebyにERC721トークンを発行し、OpenSeaで売却する、というワークショップをやっています。

ERC721には「TokenURI」という設定項目があり、設定したURL先にjsonファイルを置く事で、OpenSeaが自動的に Non Fungible Taken の情報を読み込んで画像や商品名、ステータスを表示してくれる、という機能があります。

「TokenURI」設定が、無いとき～。
![naitoki.png](https://qiita-image-store.s3.amazonaws.com/0/280104/d5086400-3086-3f7a-9542-e500b33b51da.png)
「TokenURI」設定が、あるとき～。
![arutoki.png](https://qiita-image-store.s3.amazonaws.com/0/280104/a8847591-2691-7cd0-5ce7-aef82526c8b6.png)

上の２枚の画像を比較してみても分かる様に、
OpenSeaで「いしおの」を高値で売りたいなら、TokenURIは絶対設定しておいた方がいいと思います。

ちなみに今回使用しているJSONデータはこんな感じです。
![json.png](https://qiita-image-store.s3.amazonaws.com/0/280104/ae281cee-f7e8-ff3e-74d1-201dd018de18.png)
でも、わざわざコレだけの為にサーバーを立てるのって、面倒ですよね？

# Herokuを使ってJSONサーバーを気軽に立てよう
というわけで今回は、Herokuの軽量コンテナ（Dyno）を使って、簡単に「JSONサーバー」を立ち上げてみます。

Herokuは、小規模利用ならずっと無料で使える便利なホスティング・サービスです。
暫くアクセスしないとスリープモードに入ってしまう欠点はありますが（無料ですし）アクセスすると20～30秒位で復旧するし（中にはHerokuでWordPress運用までしてしまう猛者も居る様です。）、今回の様なちょこっと利用にはうってつけです。

まず、Herokuに[登録](https://signup.heroku.com/)しアカウントを作成して下さい。

次に、[Getting Started on Heroku](https://devcenter.heroku.com/start)を開いて左上の「node.js」をクリックして下さい。
![nodejs_erabu.png](https://qiita-image-store.s3.amazonaws.com/0/280104/4957af78-772f-c8ce-20f2-d699fae95fae.png)

すると次の画面で「"ローカル環境にnode.jsの準備が出来ていると仮定します"」と英語で表示されます。
後で「npm install」を使いますので、もしインストールしていない人はサクっと入れて下さい。

準備が出来たら、「I'm ready to start」をクリックしましょう。
![Im_ready.png](https://qiita-image-store.s3.amazonaws.com/0/280104/1e6af257-6a0d-0e6f-c8d5-93b3afcb5572.png)

次の画面「Set up」では、ローカル環境にherokuコマンドの準備が出来ているかを問われます。
Windows、Mac、Ubuntu(Linxu)でのインストール方法が紹介されているので、うまくインストールして下さい。

　　※要するにherokuとタイプして実行できればOKです。
　　![command.png](https://qiita-image-store.s3.amazonaws.com/0/280104/3020e959-2c08-985c-b251-4789c6195ac9.png)

準備できたら、一番下までスクロールして、「I have install the Heroku CLI」をクリックして下さい。
![i_have_installed_the_heroku_cli.png](https://qiita-image-store.s3.amazonaws.com/0/280104/c1bf3f43-098a-80db-f6e3-6e7adf9afa2c.png)

# ここからが本題
さて、Herokuの準備が出来ている事が確認できたので、次のステップに進みます。
画面は以下の様に表示されていると思います。
![icloned_.png](https://qiita-image-store.s3.amazonaws.com/0/280104/196e9a68-ffc8-ae19-f0ce-e50188c1e074.png)

画像にマルで囲んでいるコマンドを使って、Heroku上でnode.jsを動かす為の各種ファイル群をダウンロード（clone）します。さっそく実行してみましょう。

```
git clone https://github.com/heroku/node-js-getting-started.git
```
　　node.js用ファイルを取得できます。
　　![git_git.png](https://qiita-image-store.s3.amazonaws.com/0/280104/e9b6dffe-a7d5-990e-9390-8fbd32d0f233.png)

gitクローンが終わり、フォルダ「node-js-getting-started」が生成されているので、パス移動しましょう。

```
cd node-js-getting-started
```

そして、「I cloned the app source code」をクリックして次のステップに進みます。
![i_clone_the_app_source_code.png](https://qiita-image-store.s3.amazonaws.com/0/280104/482e3141-240b-b619-3c8e-fde13829d17d.png)


# herokuに登録する
次の画面は、gitからローカルにダウンロード（clone）したファイル群を、herokuにアップロードする手順です。

```
heroku create
```
　　すると以下の様な画面になります。
　　![heroku_create.png](https://qiita-image-store.s3.amazonaws.com/0/280104/3da2270b-7b8d-8da2-4ec6-706fefab57d9.png)
　　今回は「sleepy-gorge-86016」という名前が割り振られました（毎回変わります）。

# json-serverをインストール

さて、今回の目的は、「TokenURI」の為の「JSONサーバー」を立てる事ですので、
Herokuの手順書を見ながら進めるのはここまでです。

今回は「JSONサーバー」として、パッケージ「[json-server](https://www.npmjs.com/package/json-server)」を使います。
以下のコマンドでインストールしましょう（「--save」は最近不要になったみたいです）。

```
npm install json-server
```
　　「+json-server@0.14.2」の様な表示になれば完了です。
　　![npm_install_json-server.png](https://qiita-image-store.s3.amazonaws.com/0/280104/99e507a8-2d61-5e81-0479-6ae98d2f2f3a.png)

さて、パッケージをインストールすると、「package.json」が自動的に書き換えられます。

```package.json
    :
  "dependencies": {
    "ejs": "^2.5.6",
    "express": "^4.15.2"
  },
    :
```
これが、　↓↓↓

```package.json
    :
  "dependencies": {
    "ejs": "^2.5.6",
    "express": "^4.15.2",
    "json-server": "^0.14.2"
  },
    :
```
この様に、「json-server」の行が追加されている事が分かります。

Herokuは、この「package.json」ファイルをgit経由でアップロードすると、この中に含まれるパッケージを自動的にHeroku内で追加インストールしてくれます。

最初はとっつきにくいかもしれませんが、馴れるととても便利です。

# index.jsを書き換える
Heroku上では、「package.json」の「main」設定に従い、自動的にnode.jsが実行され（てしまい）ます。

```package.json
    :
  "main": "index.js",
    :
```

今回はTokenURI用にHerokuを使う為に、「index.js」を改造して「json-server」を使いましょう。
「index.js」の中身を丸ごと削除し、以下に置き換えて下さい。

```javascript:index.js
const jsonServer = require('json-server');
const server = jsonServer.create();
const router = jsonServer.router('db.json');
const middlewares = jsonServer.defaults();
server.use(middlewares);
server.use(router);
server.listen(process.env.PORT || 5000, () => { console.log('JSON Server is running 5000'); });
```
３行目の「db.json」は、今回は以下の様な設定にしました。

```json:db.json
{
    "cbquest0" : {"name":"ishinoono","description":"CBQuest Asset #0","image":"https://ipfs.io/ipfs/QmScp12jmbqkDcXzZxBd5bWqFfd5xSsxPXu4nwVv2UYP9g"},
    "cbquest1" : {"name":"tetsunoken","description":"CBQuest Asset #1","image":"https://ipfs.io/ipfs/QmTZEY1WRiaP7B53ak8AzvHJ9d4d5YC4oXs8rHqA9w2Ya5"},
    "cbquest2" : {"name":"yari","description":"CBQuest Asset #2","image":"https://ipfs.io/ipfs/QmUuuosmkYd19eimrRwuBatt93RsLmpUUcKE6tcBLTBjCR"},
    "cbquest3" : {"name":"yuushanoken","description":"CBQuest Asset #3","image":"https://ipfs.io/ipfs/QmUzpyYzM5FKbdpgpuiamPMLuSpjHi1DQjUkjTdAPTg4ix"},
    "cbquest4" : {"name":"meriken","description":"CBQuest Asset #4","image":"https://ipfs.io/ipfs/QmRgW8L5Dmj4Ui9VPDY2r5CMAGqvd4yR7z7fRbXsC8KysN"}
}
```
今回の例では「sleepy-gorge-86016」という名前が割り振られたので、以下にアクセスすればJSONを返す筈です。
　いしのおの　　　https://sleepy-gorge-86016.herokuapp.com/cbquest0
　てつのけん　　　https://sleepy-gorge-86016.herokuapp.com/cbquest1
　やり　　　　　　https://sleepy-gorge-86016.herokuapp.com/cbquest2
　ゆうしゃのけん　https://sleepy-gorge-86016.herokuapp.com/cbquest3
　メリケンサック　https://sleepy-gorge-86016.herokuapp.com/cbquest4

このファイル「db.json」を、「index.js」と同じフォルダに置けば、ファイル準備は完了です。

# ローカルで修正した内容をHerokuにアップロードする
Herokuへのアップロードは全てgit経由で行う事になっています。

gitには手順があって、addコマンドでステージングする、commitコマンドでコミットする、そしてpushコマンドでHeroku側に変更を反映させる、という順に行います。

まずは「git add」です。「.」は、カレント・ディレクトリ以下のファイル変更を検知してステージングする、つまり変更があったファイルを全て反映させるという意味です。

```
git add .
```
　　すると、何事もなかった様に実行完了します。
　　![git_add.png](https://qiita-image-store.s3.amazonaws.com/0/280104/aed11961-3f3f-a551-3b7b-f2a84705bce4.png)
ちゃんとステージングできたかチェックしてみましょう。

```
git status
```
　　各ファイルがステージに上がった（緑色）事が分かります。
　　![git_status.png](https://qiita-image-store.s3.amazonaws.com/0/280104/fce33028-b3eb-ec5e-59b7-a076e6c0ea71.png)

ローカルgitに反映を確定させる為、コミットを行いましょう。「-m」は、コミットメッセージ（どんな変更を行ったのかコメントを残す）を指定するオプションです。

```
git commit -m "create json-server API"
```
　　これで反映されました。
　　![git_commit_.png](https://qiita-image-store.s3.amazonaws.com/0/280104/8f83b881-1e75-96cb-8e32-9606ab138bf7.png)

最後に、Heroku側に変更を反映させましょう。pushコマンドを使います。

```
git push heroku master
```
　　これで、Heroku上で、無料で使えるjson-serverが立ち上がりました。
　　![git_push_heroku_master.png](https://qiita-image-store.s3.amazonaws.com/0/280104/26268567-29f8-f8cc-86a0-10197d83e177.png)
　　暫くアクセスが無いとスリープモードに入りますが、その後アクセスすると、数十秒で自動回復します。

では、それぞれアクセスできるか、試してみましょう。
　いしのおの　　　https://sleepy-gorge-86016.herokuapp.com/cbquest0
　てつのけん　　　https://sleepy-gorge-86016.herokuapp.com/cbquest1
　やり　　　　　　https://sleepy-gorge-86016.herokuapp.com/cbquest2
　ゆうしゃのけん　https://sleepy-gorge-86016.herokuapp.com/cbquest3
　メリケンサック　https://sleepy-gorge-86016.herokuapp.com/cbquest4

　　こんな感じで表示されれば成功です！
　　![json_cbquest1.png](https://qiita-image-store.s3.amazonaws.com/0/280104/c7027c81-62b1-7713-7253-3cc24ae74b1c.png)


あとは、ERC721トークン生成時の「TokenURI」に、このアドレスを入れてやれば、
そのトークンをOpenSeaで売買する際、画像等が表示される様になります。

# OpenSea
[OpenSeaのドキュメント](https://docs.opensea.io/docs/2-adding-metadata)には、jsonの書き方が掲載されています。
![alt](https://files.readme.io/3df0848-attributes.png)

jsonファイルを工夫すれば、ERC721トークンに「プロパティ」を与えOpenSea上で表示させる事が出来ます。

また、OpenSeaは、プロパティのサンプルとして「[OpenSea Creature](https://rinkeby.opensea.io/category/openseacreature/)」を提供しています。
![opukuri.png](https://qiita-image-store.s3.amazonaws.com/0/280104/5d7eff58-e1f6-a106-a1c5-e7ebe33d89dd.png)

いろんなクリーチャーを見ながら、プロパティの作り方を勉強できて便利ですね。

# 最後に
今回は、FLOCブロックチェーン大学校の[授業](https://floc.jp/course/engsmart/)では説明しきれなかったHerokuについて触れました。
ブロックチェーン開発にはサーバー構築がつきものですが、Herokuの様なツールを使う事でサーバー周りの面倒ごとから解放され、よりERC721やOpenSeaの理解に集中出来ると思います。是非トライしてみて下さい。