@melonproject/ea-bitfinex
Version:
Integration for the Bitfinex API.
65 lines (64 loc) • 3.16 kB
JavaScript
;
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const Rx = __importStar(require("rxjs"));
const R = __importStar(require("ramda"));
const webSocket_1 = require("rxjs/webSocket");
const isomorphic_ws_1 = __importDefault(require("isomorphic-ws"));
const operators_1 = require("rxjs/operators");
const debug_1 = require("../../../debug");
const isErrorMessage = R.propEq('event', 'error');
const isServerRestartMessage = R.allPass([R.propEq('event', 'info'), R.propEq('code', 20051)]);
const isMaintenanceStartMessage = R.allPass([R.propEq('event', 'info'), R.propEq('code', 20061)]);
const isMaintenanceEndMessage = R.allPass([R.propEq('event', 'info'), R.propEq('code', 20060)]);
const isServerStatusMessage = R.allPass([R.propEq('event', 'info'), R.has('version')]);
const isChannelMessage = (value => Array.isArray(value) && Array.isArray(value[1]));
class BitfinexWebSocketError extends Error {
constructor(message, code) {
super(message);
this.code = code;
}
}
exports.BitfinexWebSocketError = BitfinexWebSocketError;
exports.socket = (subscribe) => {
const open$ = new Rx.Subject();
const close$ = new Rx.Subject();
const socket$ = webSocket_1.webSocket({
url: 'wss://api-pub.bitfinex.com/ws/2',
WebSocketCtor: isomorphic_ws_1.default,
closeObserver: close$,
openObserver: open$,
});
open$.subscribe(() => {
socket$.next(subscribe());
debug_1.log('Opening connection.');
});
close$.subscribe(() => {
debug_1.log('Closing connection.');
});
// Take messages until a maintenance window ends or
// the server demands a reconnect.
const responses$ = socket$.pipe(operators_1.tap(value => {
if (isErrorMessage(value)) {
throw new BitfinexWebSocketError(value.msg, value.code);
}
if (isServerStatusMessage(value) && value.version !== 2) {
throw new BitfinexWebSocketError('Unsupported version.');
}
}), operators_1.takeWhile(value => !isServerRestartMessage(value)), operators_1.takeWhile(value => !isMaintenanceStartMessage(value)), operators_1.share());
// Take messages until a maintenance window starts.
const messages$ = responses$.pipe(operators_1.takeWhile(value => !isMaintenanceEndMessage(value)), operators_1.takeWhile(value => !(isServerStatusMessage(value) && value.platform.status === 0)));
// Keep the connection alive while we wait for a
// maintenance window to end.
const wait$ = responses$.pipe(operators_1.filter(() => false));
return Rx.merge(messages$, wait$).pipe(operators_1.filter(isChannelMessage), operators_1.map(value => value[1]), operators_1.repeat(), operators_1.share());
};