UNPKG

consequunturatque

Version:

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

203 lines (171 loc) 6.2 kB
'use strict'; /* ------------------------------------------------------------------------ */ const now = Date.now // TODO: figure out how to utilize performance.now () properly – it's not as easy as it does not return a unix timestamp... const microseconds = () => now () * 1000 // TODO: utilize performance.now for that purpose const milliseconds = now const seconds = () => Math.floor (now () / 1000) const uuidv1 = () => { const biasSeconds = 12219292800 // seconds from 15th Oct 1572 to Jan 1st 1970 const bias = biasSeconds * 10000000 // in hundreds of nanoseconds const time = microseconds () * 10 + bias const timeHex = time.toString (16) const arranged = timeHex.slice (7, 15) + timeHex.slice (3, 7) + '1' + timeHex.slice (0, 3) // these should be random, but we're not making more than 10 requests per microsecond so who cares const clockId = '9696' // a 14 bit number const macAddress = 'ff'.repeat (6) return arranged + clockId + macAddress } /* ------------------------------------------------------------------------ */ const setTimeout_original = setTimeout const setTimeout_safe = (done, ms, setTimeout = setTimeout_original /* overrideable for mocking purposes */, targetTime = now () + ms) => { /* The built-in setTimeout function can fire its callback earlier than specified, so we need to ensure that it does not happen: sleep recursively until `targetTime` is reached... */ let clearInnerTimeout = () => {} let active = true const id = setTimeout (() => { active = true const rest = targetTime - now () if (rest > 0) { clearInnerTimeout = setTimeout_safe (done, rest, setTimeout, targetTime) // try sleep more } else { done () } }, ms) return function clear () { if (active) { active = false // dunno if IDs are unique on various platforms, so it's better to rely on this flag to exclude the possible cancellation of the wrong timer (if called after completion) clearTimeout (id) } clearInnerTimeout () } } /* ------------------------------------------------------------------------ */ class TimedOut extends Error { constructor () { const message = 'timed out' super (message) this.constructor = TimedOut this.__proto__ = TimedOut.prototype this.message = message } } /* ------------------------------------------------------------------------ */ const iso8601 = (timestamp) => { let _timestampNumber = undefined; if (typeof timestamp === 'number') { _timestampNumber = Math.floor (timestamp); } else { _timestampNumber = parseInt (timestamp, 10); } // undefined, null and lots of nasty non-numeric values yield NaN if (Number.isNaN (_timestampNumber) || _timestampNumber < 0) { return undefined; } // last line of defence try { return new Date (_timestampNumber).toISOString (); } catch (e) { return undefined; } } const parse8601 = (x) => { if (typeof x !== 'string' || !x) { return undefined; } if (x.match (/^[0-9]+$/)) { // a valid number in a string, not a date. return undefined; } if (x.indexOf ('-') < 0 || x.indexOf (':') < 0) { // no date can be without a dash and a colon return undefined; } // last line of defence try { const candidate = Date.parse (((x.indexOf ('+') >= 0) || (x.slice (-1) === 'Z')) ? x : (x + 'Z').replace (/\s(\d\d):/, 'T$1:')); if (Number.isNaN (candidate)) { return undefined; } return candidate; } catch (e) { return undefined; } } const parseDate = (x) => { if (typeof x !== 'string' || !x) { return undefined; } if (x.indexOf ('GMT') >= 0) { try { return Date.parse (x); } catch (e) { return undefined; } } return parse8601 (x); } const rfc2616 = (timestamp = undefined) => { return new Date (timestamp).toUTCString (); } const mdy = (timestamp, infix = '-') => { infix = infix || '' const date = new Date (timestamp) const Y = date.getUTCFullYear ().toString () let m = date.getUTCMonth () + 1 let d = date.getUTCDate () m = m < 10 ? ('0' + m) : m.toString () d = d < 10 ? ('0' + d) : d.toString () return m + infix + d + infix + Y } const ymd = (timestamp, infix = '-') => { infix = infix || '' const date = new Date (timestamp) const Y = date.getUTCFullYear ().toString () let m = date.getUTCMonth () + 1 let d = date.getUTCDate () m = m < 10 ? ('0' + m) : m.toString () d = d < 10 ? ('0' + d) : d.toString () return Y + infix + m + infix + d } const ymdhms = (timestamp, infix = ' ') => { const date = new Date (timestamp) const Y = date.getUTCFullYear () let m = date.getUTCMonth () + 1 let d = date.getUTCDate () let H = date.getUTCHours () let M = date.getUTCMinutes () let S = date.getUTCSeconds () m = m < 10 ? ('0' + m) : m d = d < 10 ? ('0' + d) : d H = H < 10 ? ('0' + H) : H M = M < 10 ? ('0' + M) : M S = S < 10 ? ('0' + S) : S return Y + '-' + m + '-' + d + infix + H + ':' + M + ':' + S } module.exports = { now , microseconds , milliseconds , seconds , iso8601 , parse8601 , rfc2616 , uuidv1 , parseDate , mdy , ymd , ymdhms , setTimeout_safe , sleep: ms => new Promise (resolve => setTimeout_safe (resolve, ms)) , TimedOut , timeout: async (ms, promise) => { let clear = () => {} const expires = new Promise (resolve => (clear = setTimeout_safe (resolve, ms))) try { return await Promise.race ([promise, expires.then (() => { throw new TimedOut () })]) } finally { clear () // fixes https://github.com/ccxt/ccxt/issues/749 } } } /* ------------------------------------------------------------------------ */