bitmart-api
Version:
Complete & robust Node.js SDK for BitMart's REST APIs and WebSockets, with TypeScript declarations.
138 lines • 4.48 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.WsStore = void 0;
const logger_js_1 = require("../logger.js");
const WsStore_types_js_1 = require("./WsStore.types.js");
/**
* Simple comparison of two objects, only checks 1-level deep (nested objects won't match)
*/
function isDeepObjectMatch(object1, object2) {
if (typeof object1 === 'string' && typeof object2 === 'string') {
return object1 === object2;
}
if (typeof object1 !== 'object' || typeof object2 !== 'object') {
return false;
}
for (const key in object1) {
const value1 = object1[key];
const value2 = object2[key];
if (value1 !== value2) {
return false;
}
}
return true;
}
class WsStore {
wsState = {};
logger;
constructor(logger) {
this.logger = logger || logger_js_1.DefaultLogger;
}
get(key, createIfMissing) {
if (this.wsState[key]) {
return this.wsState[key];
}
if (createIfMissing) {
return this.create(key);
}
}
getKeys() {
return Object.keys(this.wsState);
}
create(key) {
if (this.hasExistingActiveConnection(key)) {
this.logger.info('WsStore setConnection() overwriting existing open connection: ', this.getWs(key));
}
this.wsState[key] = {
subscribedTopics: new Set(),
connectionState: WsStore_types_js_1.WsConnectionStateEnum.INITIAL,
};
return this.get(key);
}
delete(key) {
// TODO: should we allow this at all? Perhaps block this from happening...
if (this.hasExistingActiveConnection(key)) {
const ws = this.getWs(key);
this.logger.info('WsStore deleting state for connection still open: ', ws);
ws?.close();
}
delete this.wsState[key];
}
/* connection websocket */
hasExistingActiveConnection(key) {
return this.get(key) && this.isWsOpen(key);
}
getWs(key) {
return this.get(key)?.ws;
}
setWs(key, wsConnection) {
if (this.isWsOpen(key)) {
this.logger.info('WsStore setConnection() overwriting existing open connection: ', this.getWs(key));
}
this.get(key, true).ws = wsConnection;
return wsConnection;
}
/* connection state */
isWsOpen(key) {
const existingConnection = this.getWs(key);
return (!!existingConnection &&
existingConnection.readyState === existingConnection.OPEN);
}
getConnectionState(key) {
return this.get(key, true).connectionState;
}
setConnectionState(key, state) {
this.get(key, true).connectionState = state;
}
isConnectionState(key, state) {
return this.getConnectionState(key) === state;
}
/* subscribed topics */
getTopics(key) {
return this.get(key, true).subscribedTopics;
}
getTopicsByKey() {
const result = {};
for (const refKey in this.wsState) {
result[refKey] = this.getTopics(refKey);
}
return result;
}
// Since topics are objects we can't rely on the set to detect duplicates
getMatchingTopic(key, topic) {
// if (typeof topic === 'string') {
// return this.getMatchingTopic(key, { channel: topic });
// }
const allTopics = this.getTopics(key).values();
for (const storedTopic of allTopics) {
if (isDeepObjectMatch(topic, storedTopic)) {
return storedTopic;
}
}
}
addTopic(key, topic) {
// if (typeof topic === 'string') {
// return this.addTopic(key, {
// instType: 'sp',
// channel: topic,
// instId: 'default',
// };
// }
// Check for duplicate topic. If already tracked, don't store this one
const existingTopic = this.getMatchingTopic(key, topic);
if (existingTopic) {
return this.getTopics(key);
}
return this.getTopics(key).add(topic);
}
deleteTopic(key, topic) {
// Check if we're subscribed to a topic like this
const storedTopic = this.getMatchingTopic(key, topic);
if (storedTopic) {
this.getTopics(key).delete(storedTopic);
}
return this.getTopics(key);
}
}
exports.WsStore = WsStore;
//# sourceMappingURL=WsStore.js.map