Flutter/DartでBitfinexのレンディングアプリを作る(Part1 インストールと画面作成/画面遷移)

---
# :book: Flutterの記事を整理し本にしました :book:
https://zenn.dev/kazutxt/books/flutter_practice_introduction

* <font color="red"><b>本稿の記事を含む様々な記事を体系的に整理し本にまとめました</b></font>
* 今後はこちらを最新化するため、<font color="red"><b>最新情報はこちらをご確認くださ</b>い</font>
* 10万文字を超える超大作になっています(笑)

---

# はじめに
## モチベーション

* もともと、Bitfinex/Coinlend/Cryptolendのレンディング情報をスマホで可視化したいと思っていました。
    * [BitfinexとCoinlendでいくら儲かっているか可視化してみた](https://qiita.com/kazutxt/items/a23412625fa3e1f35443)
    * [ローコードプラットフォームのoutsystemsで3時間でスマホアプリが動くまで](https://qiita.com/kazutxt/items/9d139cb79c11b139a7ee)
    * [No Wark, More Money～残業している場合じゃない!!～](https://bfcl.kazutxt.com/index.html)
* 最初は順調だったoutsystemsなのですが、色々と壁にぶつかり挫折しました。
    * ドキュメント量が圧倒的に少ない
    * API呼び出しで失敗するが、切り分けする手段がない
    * JavaScriptでライブラリや外部モジュールが使えない
* ただ、気軽にスマホアプリが作成でき、クロスプラットフォームで開発ができるのは良かったです
    * なので、もう少し自由度が高く、かつ気軽にiOS/Android開発を同時にできるものがほしいとなりました。
    * 結果、見つかったのがFlutterです。


## Flutter
* 2018年にGoogleが正式に発表したクロスプラットフォームの開発環境
* Dartと呼ばれる言語(Javaに似ている)を用いて開発する
* VSCode/Androidstudi/XCodeなどと連携できる
* ドキュメントが豊富(日本語もたくさんあります)
    * [公式サイト](https://flutter.dev/)
    * [日本語ドキュメント](https://flutter.ctrnost.com/)

# 環境構築
* インストール方法についても詳しいドキュメントがあります。
* [インストール方法](https://flutter.ctrnost.com/install/)

## 本体/基本ツール
* まずは、下記が入っていることを確認し、不足していれば入れます
    * git
    * docker
    * bashと基本コマンド(unzip/curl/which)
* 続いて、本体(flutterSDK)を入れます 
    * [公式サイトのDLサイト](https://flutter.dev/docs/get-started/install)からzipをダウンロードします
    * パスを通します
        * インストーラーやapt-getなどではないので気をつけてください

### Android Studio / Android toolchain
* Android Studioをインストールします。
    * パッケージを落としてきてインストールしました。
* この時点で仮想デバイスを作って置きましたが、後からでも作れます
* 後述する確認方法で、Android toolchainでライセンスエラーが出たので、指定のコマンドを打って承認しました。

### XCode
* Macで環境を作ったのですが、XCodeのインストールがOSのバージョンや空き容量などで失敗したので、後回しにしています
    * ネットでたくさんインストール方法がありますので、こちらをご参照ください

## インストールの確認
* 確認方法
    * ` flutter doctor`で必要なものが入っているか確認できます
        * dockerじゃないですよ。自分はしばらく間違っていたので :sweat: 
* 対象
    * Flutter : 本体
    * Android toolchain : Android用のデバイスやライセンス
    * Xcode : iOS/MacOSのための開発環境
    * Android Studio : Androidアプリのための開発環境
    * IntelliJ IDEA : 開発環境
    * VSCode：開発環境
    * Connected Device : 動作確認をするためのマシン(仮想でも良い)
* 判定
    * ✓でOK。×でNGとなります。
    * すべてがOKである必要はありません。使わない部分はNGのままで構いません。

# HelloWorld
* Mac+VScodeでAndroidアプリを開発します
* AndroidStudioでシミュレータを作っているものとします

## 準備と実行
* VSCodeを起動し、プラグインのインストールでFlutterをインストールします
* コマンドパレットで`Flutter:New Project`を入力しプロジェクト名を入力します
* 右下のNoDeviceから作成したデバイスを選択して接続します
    * 初回のみかなり時間がかかります。(5分から10分)
* 最後に、実行から`デバッグの開始`を実行します。
* 正しく動作すると、+ボタンを押すとカウントされていくアプリが動作します
    * ソースコードは何もいじらなくても動きます!!


# 作りたいアプリに向けて

## 画面と画面遷移
* 基本的に↓を参考にさせていただきました
    * [Flutter でモバイルアプリを作ってみる 入門編① 〜ヘッダーとフッター〜](https://www.apps-gcp.com/introduction-of-flutter-about-header-and-footer/)
    * [Flutterでモバイルアプリを作ってみる入門編②~ボディ~](https://www.apps-gcp.com/flutter-body/)
    * [Flutter Guide JP/レイアウト概要](https://flutter.ctrnost.com/basic/layout/layout/)

* 2重記載しても仕方がないので、リンク元をご参照いただければと思いますが、以下のようなことが理解できます。
    * 画面構成(ヘッダ、ボディ、フッダ)
    * ボディの基本的なレイアウトパーツ(Scaffold,Row,Column)
    * 基本的なWidget(Text,Icon,List,ListTile)
    * リンクによる画面遷移


## BitfinexAPIでの情報取得
* [Bitfinexの認証API](https://docs.bitfinex.com/docs/rest-auth)に従って、必要な情報を投げる必要があります。
    * 色々やったのですが、APIKey invalidなどが出たりする場合もあり、下記に落ち着きました

* まず、httpsを使うためのrequestsパッケージを入れます
    * ライブラリ的にhttpっぽく見ていますが、接続先がhttpsなので、多分https通信ができています

``` pubspec.yaml
dependencies:
  requests: "^3.3.0"
```

続いて、必要な定数と、nonceやsignatureなどを作成し、リクエストを投げます

``` api.dart
//必要な定数を定義
String nonce = (DateTime.now().microsecondsSinceEpoch * 1000).toString();
String apiKey = '{APIKEY}';
String secret = '{APISECRET}';
String body = json.encode({});
String baseurl = "https://api.bitfinex.com/";
String path = "/v2/auth/r/funding/offers/";

//ActiveOffer用のパラメタを作る
String url = baseurl + path;
String signature = "/api" + path + nonce + body;
var hmacSha384 = new Hmac(sha384, utf8.encode(secret));
String sig = hmacSha384.convert(utf8.encode(signature)).toString();
Map<String, String> headers = {
  "bfx-nonce": nonce,
  "bfx-apikey": apiKey,
  "bfx-signature": sig,
  "content-type": 'application/json'
};

// リクエストを投げる
http.Response resp = await http.post(url, headers: headers, body: body);

// 結果の表示
var res = json.decode(resp.body);
print(res)
```
* あとは、結果を加工するだけ :smile: 


## アイコンの追加
* デフォルトのアイコンには、ドルや円マークがなかったので、font_awesomeを使いたくなりましたので、追加することにしました。

``` pubspec.yaml
dependencies:
  font_awesome_flutter: "^8.8.1"
```

``` soruce.dart
import 'package:font_awesome_flutter/font_awesome_flutter.dart'

Icon(FontAwesomeIcons.dollarSign, color: Colors.red) // ドルマークを赤で表示
```

## apkファイルの作成と実機での操作
* `flutter build apk`でapkファイルが作成されます。
* slackなどを通じて、スマホに渡します。
* 正規なルートではないので、警告が出ますがOKをすると、インストールできます。
* アプリのアイコンをタップすると作ったアプリが動作します
* ただし、外部との通信が確認できていません
    * 通信も許可しているはずなのですが、調査中です。。。

# 現時点の開発状況
* できたもの

![flutter.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/a2126f9b-696d-9af0-7ddf-e187fc66c4bf.png)

* Chart画面
    * 現時点のレートを表示する画面
    * BitfinexのpublicなAPIで直近のレートを表示しています
    * ColumnとRowで実現し、awesomeの円、ドル、ユーロのアイコンを使っています
* Funding画面
    * 貸し出し状態を表示する画面
        * 貸し出しオファーと貸出中の2種類をまとめて表示します
    * ListTileで作っています
        * leadingのアイコンは通貨を表すアイコン
        * tailingのアイコンはオファー中か確定済かを表すアイコン
        * titleにレートと金額。subtitleに開始日時と貸出期間を表示しています
* Interest画面
    * 貸し出し利益を表示する画面
    * ListTileで作っています
        * leadingのアイコンは、前日と比べて増えていれば :arrow_up: 減っていれば :arrow_down: 
を表示します
        * tailingは文字にしてあり、本日は「today」7日前までを「this week」と表示しています
            * this weekのニュアンスが少し違いますがｗ
* Setting画面
    * APIKeyを設定する画面
        * 今はハードコーディングしているのですが、入力できるようにしたいです
        * 今は、パーツだけで保存や読み出しはできません
* Info画面
    * アプリの情報を表示する画面
    * 今後もただ文字を表示するだけの画面になる予定

## 今後やりたいこと
* データ保持
    * APIKeyを保存したいので
* Stateful/Stateless
    * 今は、画面ロード時に処理が走るだけで、再描画ができていません
* フィルタリング/ソート
    * funding/interestを条件で表示を切り替えられるようになれば、使いやすそう