BitBankの取引価格と残高を自動で取得

GoogleAppsScriptでバッチを定時実行して
Gmailで送信させることにより、
各取引所の取引価格や残高を自動取得させることが可能です。

ソースは一部省略しています。

GoFのデザインパターンで言うところの
Commandを参考にしました。

POSTメソッドを使えば自動取引も可能です。


```javascript:doGet.js
//-------Const-------
var EXCHANGE_CC = "CoinCheck";
var URL_CC = "https://coincheck.com";
var URL_CC_ACCOUNT = URL_CC + "/api/accounts/balance";
var URL_CC_TICKER  = URL_CC + "/api/ticker";
var URL_CC_RATE    = URL_CC + "/api/rate/btc_jpy";

var EXCHANGE_BB = "BitBank";
var URL_BB     = "https://public.bitbank.cc";
var URL_BB_PRV = "https://api.bitbank.cc";
var URL_BB_TICKER = URL_BB + "/btc_jpy/ticker";
var URL_BB_ASSETS = "/v1/user/assets";

var EXPORT_MAIL = "Mail";
var EXPORT_LOG  = "Log";

//-------JSON_Item-------
// Public
var mostLowPrice;  //24時間最安値
var mostHighPrice; //24時間最高値

var rateBtcJpy; //BTC/JPY価格

// private
var blncJpy; //JPY残高
var blncBtc; //BTC残高

/*******************************
 *  EntryPoint
 *******************************/ 
function doGet(){
  try{
    //JSONを取得
    getJson(EXCHANGE_BB);

    //メールで報告
    export(EXPORT_MAIL);
        
  }catch (e){
    var errMsg = "";
    if (e.fileName && e.lineNumber) {
            errMsg = "ファイル: " + e.fileName 
                   + ", 行: "    + e.lineNumber;
    }
    errMsg += ", " + e.message;
    export(EXPORT_MAIL, "エラーcatch: " + errMsg);
  }
  
  return;
}
```


```javascript:getJson.js
/*******************************
 *  JSONの取得
 *******************************/
function getJson(exchange){
  //Bitbank
  if (exchange === EXCHANGE_BB) { getBbJson(); }
  //CoinCheck
  if (exchange === EXCHANGE_CC) { getCcJson(); }
}

/*******************************
 *  JSONの取得(BitBank
 *******************************/
function getBbJson(){
  var methodGet = 'get';
  var nonce = Date.now().toString();
  
  //publicオプション
  var pubOption = {
    'method' : methodGet
    , 'muteHttpExceptions' : true
    , "contentType": "application/json"
  };
    
  //シグネチャ
  var sign = createSignature(EXCHANGE_BB, nonce);  
  
  //privateオプション
  var prvOption = {
    'method' : methodGet
    , 'muteHttpExceptions' : true
    ,  headers: {
        'ACCESS-KEY': BB_ACCESS_KEY
        , 'ACCESS-NONCE': nonce
        , 'ACCESS-SIGNATURE': sign
      }
    , "contentType": "application/json"
  };

  // fetch / responce
  var resTicker = UrlFetchApp.fetch(URL_BB_TICKER, pubOption);
  var resBalance = UrlFetchApp.fetch(URL_BB_PRV + URL_BB_ASSETS, prvOption);
  
  //取得の確認ログメール発行
  if (resTicker.getResponseCode() != 200) {export(EXPORT_MAIL, "ティッカーJSON取得失敗 " + resTicker.getContentText());}
  if (resBalance.getResponseCode() != 200) {export(EXPORT_MAIL, "残高JSON取得失敗 " + resBalance.getContentText());}
  
  // JSONファイル
  var jsonTicker  = JSON.parse(resTicker.getContentText());
  var jsonBalance = JSON.parse(resBalance.getContentText());
  
  //値の設定
  rateBtcJpy = jsonTicker["data"]["last"]; //BTC/JPY価格
  blncJpy = jsonBalance["data"]["assets"][IDX_JSON_BB_ASSET_JPY]["onhand_amount"];
  blncBtc = jsonBalance["data"]["assets"][IDX_JSON_BB_ASSET_BTC]["onhand_amount"];
}


//CoinCheck省略

```



```javascript:createSignature.js

/*******************************
 *  シグネチャ作成
 *******************************/
function createSignature(exchange, nonce, body){
  //BitBank
  if (exchange === EXCHANGE_BB) { 
    return createSignatureBb(URL_BB_ASSETS
                             , BB_SECRET_ACCSESS_KEY
                             , nonce
                             , body
                             ); 
  }
}

/*******************************
 *  シグネチャ作成(Bitbank
 *******************************/
function createSignatureBb(url, secretKey, nonce, body){
  var text =  (typeof body === "undefined") ? 
              nonce + url : nonce + url + body;
  
  var signature = Utilities.computeHmacSha256Signature(text, secretKey);
  
  var sign = signature.reduce(function(str,chr){
    chr = (chr < 0 ? chr + 256 : chr).toString(16);
    return str + (chr.length==1?'0':'') + chr;
  },'');
  
  return sign;
}
```

```javascript:mail.js
/*******************************
 *  出力
 *******************************/
function export(typeExport, msg){
  if (typeExport === EXPORT_MAIL) {
    reportMail(msg); 
    
    if (typeof　msg !== 'undefined'){logSheet(msg);}
  }
  
  if (typeExport === EXPORT_LOG) { logSheet(msg); }
}

/*******************************
 *  メールで報告
 *******************************/
function reportMail(msg){
  var date = Utilities.formatDate(new Date()
                                  , 'Asia/Tokyo'
                                  , 'yyyy年MM月dd日: HH時mm分ss秒'
                                 );
  
 GmailApp.sendEmail(
    TO_MAIL_ADDRESS
    , "自動売買の報告"
    ,""
    + "[BitBank]\n"
    + "残高JPY: " + delimit(blncJpy) + " 円\n"
    + "残高BTC: " + String(blncBtc)  + " BTC\n"
    + "\n\n"
    + "レート: " + delimit(rateBtcJpy)    + " 円\n" 
    + "\n"
    + date
  );
}

/******************************
 *  カンマ生成
 ******************************/
function delimit(val, floorble) { 
  var result = String(Math.floor(val)).replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,');
  
  return result;
}
```


参考
---

[ビットコおじさんの仮想通貨情報局 API入門（1）取引所のリアルタイムレートをゲット！](http://btcojisan.info/archives/4250350.html)
[Google Apps Scriptを使って定期実行するcronを作る](https://www.sakana.tech/entry/make-cron-use-googleappsscript)
[【保存版】Google Apps Scriptリファレンス～キーワード別インデックス ](https://tonari-it.com/google-apps-script-reference/)