Skip to content

Commit

Permalink
v0.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
yamorijp committed Oct 24, 2017
1 parent 80db01b commit ba2c296
Show file tree
Hide file tree
Showing 30 changed files with 3,450 additions and 0 deletions.
12 changes: 12 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.git
.gitignore
.node-version
*.iml
LICENSE
VERSION
README.md
Changelog.md
Makefile
docker-compose.yml
node_modules

12 changes: 12 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,6 @@ typings/
# dotenv environment variables file
.env

*.iml
.node-version
.credential.json
9 changes: 9 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FROM node:boron-slim

# install nc for sync-request
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && apt-get install -y --no-install-recommends \
netcat

ADD . /blac/
RUN cd /blac && npm install
107 changes: 107 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<p align="center">
<img alt="BLAC" src="https://raw.githubusercontent.com/yamorijp/blac/master/capture.jpg" width="600"/>
</p>


BLAC (Bitflyer Lightning API Console) は ビットコイン取引所 [bitFlyer](https://bitflyer.jp) が提供する
[bitFlyer Lightning API](https://bitflyer.jp/docs) を使用した非公式のCLIツールパッケージです。

Lightning APIクライアントを統合したjavascriptの対話型コンソールプログラム、
リアルタイム更新の板表示プログラムと約定履歴表示プログラムを含みます。

当プログラムは"experimental"です。
十分なテストが行われていません。オーダー発行を行う場合は最初に少額でお試しください。

※U.S.リージョンには対応していません


## 導入手順

当プログラムはNode.jsで動作するjsスクリプトです。
実行には[Node.js](https://nodejs.org) が必要です。バージョン6.10.0以上を導入してください。

また、サードパーティ製のnpmモジュールに依存しています。
[npm](https://www.npmjs.com/)[yarn](https://yarnpkg.com/) を使用してインストールを行ってください。

$ npm install



## プログラムの実行方法

nodeコマンドでスクリプトを実行します。

$ node console.js

いくつかコマンドラインオプションがあります。`-h`オプションで確認してください。

$ node console.js -h


## 対話型コンソール (console.js)

Lightning APIクライアントを統合したREPLコンソールプログラムです。
対話型シェルでjavascriptを使用した注文発注や取消等、Lightning APIの呼び出しが行えます。

残高の確認やオーダー発行などPrivate APIに属する機能の呼び出しにはAPI keyとAPI secretが必要になります。
[bitFlyer Lightning](https://lightning.bitflyer.jp)にログイン後、[開発者ページ](https://lightning.bitflyer.jp/developer)から取得してください。

PI keyとAPI secretは`.bc_set_key`コマンドで設定します。設定した認証情報はプログラム終了時まで有効です。

> .bf_set_key YOUR_API_KEY YOUR_API_SECRET

`.bf_store_key`コマンドで書き出しを行っておくと起動時に自動で読み込みます。(※平文で保存されます。セキュリティに注意)


APIの詳細は、bitFlyerによる[API Documentation](https://lightning.bitflyer.jp/docs)を参照してください。


オプション:

-n, --no-banner スタートアップバナーを表示しない

例:

$ node console.js -n



## 板表示プログラム (board.js)

リアルタイム更新の板表示プログラムです。
値段範囲で注文をまとめるグルーピング表示に対応しています。(`-g`オプション)


オプション:
-p, --product <code> プロダクトコード (BTC_JPY|ETH_BTC|BCH_BTC|FX_BTC_JPY)
-r, --row <n> 買いと売り注文の表示行数 (デフォルト: 24)
-g, --group <n> 指定範囲の注文をまとめて表示 (デフォルト: 無効)
例:
$ node board.js -p BTC_JPY -r 32 -g 1000

## 約定履歴表示プログラム (executions.js)

リアルタイム更新の約定履歴表示プログラムです。


オプション:

-p, --product <code> プロダクトコード (BTC_JPY|ETH_BTC|BCH_BTC|FX_BTC_JPY)
-r, --row <n> 履歴の表示行数 (デフォルト: 48)

例:

$ node executions.js -p ETH_BTC -r 20


## ライセンス

MIT


bitcoin: `1BpLZm4JEFiDqAnaexuYMhGJZKdRQJKixP`
monacoin: `MEaJSzymtvpB7AtrryVzn9LeZYhCrustpJ`
130 changes: 130 additions & 0 deletions board.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
#!/usr/bin/env node

"use strict";

require('./core/polyfill');

const throttle = require('lodash.throttle');

const term = require('./core/terminal');
const api = require('./lightning/api');
const model = require('./core/model');
const products = require('./core/product');

const render_wait = 200;

let product = products.BtcJpy;
let health = new model.Health();
let ticker = new model.Ticker();
let board = new model.Board();


const _render = () => {
let out = process.stdout;

out.write(term.clear);
out.write(term.nl);

out.write(" Product:".padEnd(20));
out.write(product.name.padStart(26));
out.write(term.nl);

out.write(" Last Price:".padEnd(20));
out.write(term.colorful(
ticker.price >= ticker.price_old ? term.green : term.red,
product.format_price(ticker.price).padStart(26)));
out.write(term.nl);

out.write(" Bid/Ask Ratio:".padEnd(20));
out.write(term.colorful(
ticker.ratio >= 1.0 ? term.green : term.red,
ticker.ratio.toFixed(2).padStart(26)));
out.write(term.nl);

out.write(" 24H Volume:".padEnd(20));
out.write(product.format_volume(ticker.volume).padStart(26));
out.write(term.nl);

out.write(term.separator + term.nl);

board.getAsks().forEach(row => {
out.write(product.format_volume(row[1]).padStart(16));
out.write(" " + term.colorful(term.red, product.format_price(row[0]).padStart(12)) + " ");
out.write("".padEnd(16));
out.write(term.nl);
});
board.getBids().forEach(row => {
out.write("".padEnd(16));
out.write(" " + term.colorful(term.green, product.format_price(row[0]).padStart(12)) + " ");
out.write(product.format_volume(row[1]).padStart(16));
out.write(term.nl);
});

out.write(term.separator + term.nl);

out.write(` Service) ${health.health} Market) ${health.state}`);
out.write(term.nl);
};
const render = throttle(_render, render_wait);


const main = (program) => {
product = products.get_product(program.product);
board.lock()
.setRowCount(program.row)
.setGroupingFactor(program.group);

let check_health = function () {
new api.PublicAPI().call('GET', '/v1/getboardstate', {product_code: product.code})
.then(data => {
health.update(data);
render();
});
};
check_health();
setInterval(check_health, 60000);

let board_channel = 'lightning_board_' + product.code;
let ticker_channel = 'lightning_ticker_' + product.code;
new api.RealtimeAPI()
.attach((channel, message) => {
switch (channel) {
case board_channel:
board.update(message);
break;
case ticker_channel:
ticker.update(message);
break;
}
render();
})
.subscribe([board_channel, ticker_channel]);

new api.PublicAPI()
.call('GET', '/v1/board', {product_code: product.code})
.then(data => {
board.setData(data);
board.unlock();
render();
});
};


const program = require('commander');
program
.version(require("./package.json").version)
.description("Display BitFlyer Lightning's order book")
.option("-p, --product <code>", "Product code (BTC_JPY|ETH_BTC|BCH_BTC|FX_BTC_JPY)", s => s.toUpperCase(), "BTC_JPY")
.option("-r, --row <n>", "Number of display rows (default: 24)", v => parseInt(v), 24)
.option("-g, --group <n>", "Order grouping unit (default: 0.0)", v => parseFloat(v), 0.0)
.on("--help", () => {
console.log("");
console.log(" Examples:");
console.log("");
console.log(" $ node board.js -p BTC_JPY -r 32 -g 1000");
console.log("");
})
.parse(process.argv);

main(program);

Binary file added capture.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
108 changes: 108 additions & 0 deletions console.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
#!/usr/bin/env node

"use strict";

require('./core/polyfill');

const repl = require('repl');

const term = require('./core/terminal');
const command = require('./core/command');

const api = require('./lightning/api');
const pub = require('./lightning/builder/pub');
const pri = require('./lightning/builder/pri');

const version = require('./package.json').version;

const banner = `${term.yellow}${term.bold}
_ _
| | | |
| |__ | | __ _ ___
| '_ \\| |/ _\` |/ __|
| |_) | | (_| | (__
|_.__/|_|\\__,_|\\___|
${term.reset}${term.yellow}
bitflyer - lightning - api - console
${term.reset}
コンテキスト変数:
api -> APIクライアント
pub -> パブリックAPI
pri -> プライベートAPIと認証
コマンド:
.help または .bf_* help を参照
> .bf_buy help
APIドキュメント:
bitFlyer Lightning API - https://lightning.bitflyer.jp/docs
例:
> pri.set_credential(YOUR_API_KEY, YOUR_API_SECRET)
> pri.getchildorders.create()
> _.product_code("BTC_JPY").child_order_state("ACTIVE")
> _.executeSync()
`;

const loadCredential = () => {
try {
const config = require('./.credential.json');
if (config.api_key && config.api_secret) {
pri.set_credential(config.api_key, config.api_secret);
console.log(term.colorful(term.green, " (.credential.json loaded)\n\n"));
}
} catch (e) {
// not found
}
};

const initContext = (context) => {
context.api = api;
context.pub = pub;
context.pri = pri;
};


const main = (program) => {

if (!program.nobanner) {
process.stdout.write(term.clear);
process.stdout.write(term.nl);
process.stdout.write(banner);
}

loadCredential();

let server = repl.start('> ');

initContext(server.context);
server.on('reset', initContext);

Object.values(command.commands)
.forEach(cmd => server.defineCommand(cmd.getName(), {
help: cmd.getHelp(),
action(arg) {
cmd.doAction(server, arg);
}
}));
};


const program = require('commander');
program
.version(require("./package.json").version)
.description("bitflyer - lightning - api - console")
.option("-n, --no-banner", "Don't show ugly startup banner", false)
.on("--help", () => {
console.log("");
console.log(" Examples:");
console.log("");
console.log(" $ node console.js -n");
console.log("");
})
.parse(process.argv);

main(program);
Loading

0 comments on commit ba2c296

Please sign in to comment.