Symbolウォレットの残高を自動で取得・更新する


#### 目的
Googleスプレッドシートを利用して、Symbolウォレットの残高を自動で取得・更新する。

※あくまでも現時点での残高を取得するだけなので、詳細な履歴などを利用する場合などは
以下のサイトを利用することをオススメします。

- Symbol ブロックチェーンエクスプローラ  
http://explorer.symbolblockchain.io/
- XEMBook  
https://xembook.github.io/xembook/ 

#### 想定する利用者
複数ウォレットを保持している人

- 決済用、保管用でウォレットを分けている人
- マルチシグウォレットを作成している人
- ノード運用をしている人で、ハーベスト手数料の受益アカウントを専用に用意している人
- Symbol HD ウォレットを利用している人

#### 準備
##### スプレッドシートの作成
画像のようなスプレッドシートを作成しておきます。

![スプレッドシートの作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153148/bd26226c-c6de-0856-936f-1676eca3f07c.png)

##### Google App Script
メニューから「ツール > スクリプトエディタ」を選択してGoogle App Scriptを開きます。
![Google App Script.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153148/790282c1-fce7-e929-bf1b-00ffbb8e591c.png)

#### 実装

##### シートの情報を取得
スプレッドシートのシート名と、値を取得するセルの範囲を指定します。

``` js
  // 対象のスプレッドシート を設定.
  var sheet = SpreadsheetApp.getActiveSpreadsheet();
  var target_sheet = sheet.getSheetByName('Symbol');
  // セルからアドレスの情報を設定.
  var arr_raw_address = target_sheet.getRange('D7:D10').getValues();
```
色を変更している、D7:D10のセルに入力されている情報を取得します。
また、画像には写っていませんが、シートの名称をSymbolに変更しています。
![シートの情報.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153148/23677b23-e988-17bf-62a0-fe6a32424c00.png)

##### Symbolウォレットの情報を取得
SymbolのAPIサーバに対して、アカウント情報を要求するリクエストを投げます。
Symbolではxymがレスポンスのmosaicsの中にid - amountが紐づいた状態で格納されているため、
xymのidで取得する残高を指定します。

レスポンス内容など詳しくは、ドキュメントを参照してください。
- Catapult REST Endpoints (1.0.0)
https://docs.symbolplatform.com/symbol-openapi/v1.0.0/

``` js
  const id_symbol = '6BED913FA20223F8';
  // ウォレット残高の格納用.
  var arr_amount = []

  arr_raw_address.forEach(raw_address=>{
    // アドレスからハイフンを削除する.
    var address = String(raw_address).replace(/-/g, '');

    var url = 'http://'
            + 'ngl-dual-005.symbolblockchain.io'
            + ':3000'
            + '/accounts/'
            + address;

    // APIを呼び出して、アカウントの情報を取得.
    var response = UrlFetchApp.fetch(url);
    var json=JSON.parse(response.getContentText());

    // アカウントの情報から残高を取得.
    if(id_symbol == json.account.mosaics[0].id){
      raw_amount = json.account.mosaics[0].amount;

      // 数量を小数点に変換して格納.
      arr_amount.push(new Array(1)
        .fill(Number(raw_amount) / 1000000));
    }
  });
```
##### シートの情報を更新
取得した情報をシートに反映します。

``` js
  // 数量のセルを更新.
  target_sheet.getRange('F7:F10').setValues(arr_amount);

  // 更新日時を取得
  var time = Utilities.formatDate(
    new Date(),
    'Asia/Tokyo', 'yyyy/MM/dd HH:mm:ss'
    );

  // 日付のセルを更新.
  target_sheet.getRange('D3').setValue(time);
}

```
色を変更しているF7:F10とD3のセルの情報を更新します。
![シートの情報を更新.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153148/5326d67b-4846-4a65-2cb2-600256e8c8e0.png)

##### 全体ソース
``` js
function Update_Symbol_Amount() {
  const id_symbol = '6BED913FA20223F8';

  // 対象のスプレッドシート を設定.
  var sheet = SpreadsheetApp.getActiveSpreadsheet();
  var target_sheet = sheet.getSheetByName('Symbol');
  // セルからアドレスの情報を設定.
  var arr_raw_address = target_sheet.getRange('D7:D10').getValues();
  // ウォレット残高の格納用.
  var arr_amount = []

  arr_raw_address.forEach(raw_address=>{
    // アドレスからハイフンを削除する.
    var address = String(raw_address).replace(/-/g, '');

    var url = 'http://'
            + 'ngl-dual-005.symbolblockchain.io'
            + ':3000'
            + '/accounts/'
            + address;

    // APIを呼び出して、アカウントの情報を取得.
    var response = UrlFetchApp.fetch(url);
    var json=JSON.parse(response.getContentText());

    // アカウントの情報から残高を取得.
    if(id_symbol == json.account.mosaics[0].id){
      raw_amount = json.account.mosaics[0].amount;

      // 数量を小数点に変換して格納.
      arr_amount.push(new Array(1)
        .fill(Number(raw_amount) / 1000000));
    }
  });

  // 数量のセルを更新.
  target_sheet.getRange('F7:F10').setValues(arr_amount);

  // 更新日時を取得
  var time = Utilities.formatDate(
    new Date(),
    'Asia/Tokyo', 'yyyy/MM/dd HH:mm:ss'
    );

  // 日付のセルを更新.
  target_sheet.getRange('D3').setValue(time);
}

```

#### 自動実行設定
Google App Scriptの左のメニューから時計マークを選択して、実行するトリガーを設定します。
ここでは、日ごとにウォレットの残高を更新するように設定しています。

![自動実行.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153148/465294cc-f6f9-c087-805e-81aca45d9e6e.png)

#### まとめ
APIを実行するだけで、チェーンの情報にアクセスできるため、
結果的にSymbolの処理よりもスプレッドシートの操作が多くなりました。

また、サーバを用意しなくていいので、自前で管理するけど残高の更新が面倒ならこれで問題だと思います。
トリガーを日ごと、月ごとに設定しておいて履歴を残す形にしておけば確定申告時に必要なメモのし忘れもなくなりそうだなと思います。

#### 参照ドキュメント
- Symbol API 
https://docs.symbolplatform.com/ja/api.html#endpoints

- Catapult REST Endpoints (1.0.0)
https://docs.symbolplatform.com/symbol-openapi/v1.0.0/