UNPKG

sfccxt

Version:

A JavaScript / Python / PHP cryptocurrency trading library with support for 130+ exchanges

215 lines (196 loc) 6.69 kB
/* eslint-disable max-classes-per-file */ 'use strict'; class BaseCache extends Array { constructor (maxSize = undefined) { super () Object.defineProperty (this, 'maxSize', { __proto__: null, // make it invisible value: maxSize, writable: true, }) } clear () { this.length = 0 } } class ArrayCache extends BaseCache { constructor (maxSize = undefined) { super (maxSize); Object.defineProperty (this, 'nestedNewUpdatesBySymbol', { __proto__: null, // make it invisible value: false, writable: true, }) Object.defineProperty (this, 'newUpdatesBySymbol', { __proto__: null, // make it invisible value: {}, writable: true, }) Object.defineProperty (this, 'clearUpdatesBySymbol', { __proto__: null, // make it invisible value: {}, writable: true, }) Object.defineProperty (this, 'allNewUpdates', { __proto__: null, // make it invisible value: 0, writable: true, }) Object.defineProperty (this, 'clearAllUpdates', { __proto__: null, // make it invisible value: false, writable: true, }) } getLimit (symbol, limit) { let newUpdatesValue = undefined if (symbol === undefined) { newUpdatesValue = this.allNewUpdates this.clearAllUpdates = true } else { newUpdatesValue = this.newUpdatesBySymbol[symbol]; if ((newUpdatesValue !== undefined) && this.nestedNewUpdatesBySymbol) { newUpdatesValue = newUpdatesValue.size } this.clearUpdatesBySymbol[symbol] = true } if (newUpdatesValue === undefined) { return limit } else if (limit !== undefined) { return Math.min (newUpdatesValue, limit) } else { return newUpdatesValue; } } append (item) { // maxSize may be 0 when initialized by a .filter() copy-construction if (this.maxSize && (this.length === this.maxSize)) { this.shift () } this.push (item) if (this.clearAllUpdates) { this.clearAllUpdates = false this.clearUpdatesBySymbol = {} this.allNewUpdates = 0 this.newUpdatesBySymbol = {} } if (this.clearUpdatesBySymbol[item.symbol]) { this.clearUpdatesBySymbol[item.symbol] = false this.newUpdatesBySymbol[item.symbol] = 0 } this.newUpdatesBySymbol[item.symbol] = (this.newUpdatesBySymbol[item.symbol] || 0) + 1 this.allNewUpdates = (this.allNewUpdates || 0) + 1 } } class ArrayCacheByTimestamp extends BaseCache { constructor (maxSize = undefined) { super (maxSize) Object.defineProperty (this, 'hashmap', { __proto__: null, // make it invisible value: {}, writable: true, }) Object.defineProperty (this, 'sizeTracker', { __proto__: null, // make it invisible value: new Set (), writable: true, }) Object.defineProperty (this, 'newUpdates', { __proto__: null, // make it invisible value: 0, writable: true, }) Object.defineProperty (this, 'clearUpdates', { __proto__: null, // make it invisible value: false, writable: true, }) } getLimit (symbol, limit) { this.clearUpdates = true if (limit === undefined) { return this.newUpdates } return Math.min (this.newUpdates, limit) } append (item) { if (item[0] in this.hashmap) { const reference = this.hashmap[item[0]] if (reference !== item) { for (const prop in item) { reference[prop] = item[prop] } } } else { this.hashmap[item[0]] = item if (this.maxSize && (this.length === this.maxSize)) { const deleteReference = this.shift () delete this.hashmap[deleteReference[0]] } this.push (item) } if (this.clearUpdates) { this.clearUpdates = false this.sizeTracker.clear () } this.sizeTracker.add (item[0]) this.newUpdates = this.sizeTracker.size } } class ArrayCacheBySymbolById extends ArrayCache { constructor (maxSize = undefined) { super (maxSize) this.nestedNewUpdatesBySymbol = true Object.defineProperty (this, 'hashmap', { __proto__: null, // make it invisible value: {}, writable: true, }) } append (item) { const byId = this.hashmap[item.symbol] = this.hashmap[item.symbol] || {} if (item.id in byId) { const reference = byId[item.id] if (reference !== item) { for (const prop in item) { reference[prop] = item[prop] } } item = reference const index = this.findIndex ((x) => x.id === item.id) // move the order to the end of the array this.splice (index, 1) } else { byId[item.id] = item } if (this.maxSize && (this.length === this.maxSize)) { const deleteReference = this.shift () delete this.hashmap[deleteReference.symbol][deleteReference.id] } this.push (item) if (this.clearAllUpdates) { this.clearAllUpdates = false this.clearUpdatesBySymbol = {} this.allNewUpdates = 0 this.newUpdatesBySymbol = {} } if (this.newUpdatesBySymbol[item.symbol] === undefined) { this.newUpdatesBySymbol[item.symbol] = new Set () } if (this.clearUpdatesBySymbol[item.symbol]) { this.clearUpdatesBySymbol[item.symbol] = false this.newUpdatesBySymbol[item.symbol].clear () } // in case an exchange updates the same order id twice const idSet = this.newUpdatesBySymbol[item.symbol] const beforeLength = idSet.size idSet.add (item.id) const afterLength = idSet.size this.allNewUpdates = (this.allNewUpdates || 0) + (afterLength - beforeLength) } } module.exports = { ArrayCache, ArrayCacheByTimestamp, ArrayCacheBySymbolById, }