ccxt-look 1.81.50
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cache/eslintcache +1 -0
- package/.dockerignore +6 -0
- package/.eslintignore +1 -0
- package/.gitattributes +5 -0
- package/.readthedocs.yaml +16 -0
- package/CONTRIBUTING.md +1049 -0
- package/LICENSE.txt +21 -0
- package/README.md +537 -0
- package/SECURITY.md +5 -0
- package/build/cleanup-old-tags.js +94 -0
- package/build/countries.js +256 -0
- package/build/export-exchanges.js +520 -0
- package/build/fs.js +51 -0
- package/build/transpile.js +1772 -0
- package/build/vss.js +78 -0
- package/ccxt.browser.js +7 -0
- package/ccxt.d.ts +692 -0
- package/ccxt.js +171 -0
- package/cleanup.sh +2 -0
- package/composer-install.sh +20 -0
- package/dist/ccxt.browser.js +208383 -0
- package/gource.sh +3 -0
- package/index.html +7 -0
- package/js/.eslintrc +87 -0
- package/js/aax.js +2686 -0
- package/js/ascendex.js +2584 -0
- package/js/base/.eslintrc.js +43 -0
- package/js/base/Exchange.js +2371 -0
- package/js/base/Precise.js +283 -0
- package/js/base/errorHierarchy.js +47 -0
- package/js/base/errors.js +55 -0
- package/js/base/functions/crypto.js +158 -0
- package/js/base/functions/encode.js +118 -0
- package/js/base/functions/generic.js +270 -0
- package/js/base/functions/misc.js +138 -0
- package/js/base/functions/number.js +329 -0
- package/js/base/functions/platform.js +38 -0
- package/js/base/functions/string.js +21 -0
- package/js/base/functions/throttle.js +79 -0
- package/js/base/functions/time.js +210 -0
- package/js/base/functions/type.js +66 -0
- package/js/base/functions.js +28 -0
- package/js/bequant.js +32 -0
- package/js/bibox.js +1407 -0
- package/js/bigone.js +1366 -0
- package/js/binance.js +5652 -0
- package/js/binancecoinm.js +46 -0
- package/js/binanceus.js +46 -0
- package/js/binanceusdm.js +49 -0
- package/js/bit2c.js +535 -0
- package/js/bitbank.js +842 -0
- package/js/bitbay.js +16 -0
- package/js/bitbns.js +1073 -0
- package/js/bitcoincom.js +15 -0
- package/js/bitfinex.js +1433 -0
- package/js/bitfinex2.js +2025 -0
- package/js/bitflyer.js +840 -0
- package/js/bitforex.js +614 -0
- package/js/bitget.js +2397 -0
- package/js/bithumb.js +980 -0
- package/js/bitmart.js +2516 -0
- package/js/bitmex.js +1809 -0
- package/js/bitopro.js +1443 -0
- package/js/bitpanda.js +1782 -0
- package/js/bitrue.js +1747 -0
- package/js/bitso.js +1062 -0
- package/js/bitstamp.js +1757 -0
- package/js/bitstamp1.js +343 -0
- package/js/bittrex.js +1876 -0
- package/js/bitvavo.js +1579 -0
- package/js/bkex.js +1233 -0
- package/js/bl3p.js +346 -0
- package/js/blockchaincom.js +969 -0
- package/js/btcalpha.js +680 -0
- package/js/btcbox.js +477 -0
- package/js/btcmarkets.js +1022 -0
- package/js/btctradeua.js +466 -0
- package/js/btcturk.js +734 -0
- package/js/buda.js +946 -0
- package/js/bw.js +1265 -0
- package/js/bybit.js +3372 -0
- package/js/bytetrade.js +1336 -0
- package/js/cdax.js +1646 -0
- package/js/cex.js +1410 -0
- package/js/coinbase.js +1342 -0
- package/js/coinbaseprime.js +31 -0
- package/js/coinbasepro.js +1466 -0
- package/js/coincheck.js +755 -0
- package/js/coinex.js +3400 -0
- package/js/coinfalcon.js +880 -0
- package/js/coinmate.js +794 -0
- package/js/coinone.js +816 -0
- package/js/coinspot.js +345 -0
- package/js/crex24.js +1636 -0
- package/js/cryptocom.js +1832 -0
- package/js/currencycom.js +1748 -0
- package/js/delta.js +1547 -0
- package/js/deribit.js +2148 -0
- package/js/digifinex.js +1585 -0
- package/js/eqonex.js +1660 -0
- package/js/exmo.js +1670 -0
- package/js/fairdesk.js +1231 -0
- package/js/flowbtc.js +35 -0
- package/js/fmfwio.js +34 -0
- package/js/ftx.js +2751 -0
- package/js/ftxus.js +38 -0
- package/js/gateio.js +4174 -0
- package/js/gemini.js +1397 -0
- package/js/hitbtc.js +1343 -0
- package/js/hitbtc3.js +2329 -0
- package/js/hollaex.js +1486 -0
- package/js/huobi.js +5706 -0
- package/js/huobijp.js +1710 -0
- package/js/huobipro.js +18 -0
- package/js/idex.js +1439 -0
- package/js/independentreserve.js +649 -0
- package/js/indodax.js +742 -0
- package/js/itbit.js +722 -0
- package/js/kraken.js +2179 -0
- package/js/kucoin.js +2571 -0
- package/js/kucoinfutures.js +1771 -0
- package/js/kuna.js +809 -0
- package/js/latoken.js +1445 -0
- package/js/lbank.js +760 -0
- package/js/liquid.js +1432 -0
- package/js/luno.js +873 -0
- package/js/lykke.js +1147 -0
- package/js/mercado.js +771 -0
- package/js/mexc.js +3151 -0
- package/js/ndax.js +2233 -0
- package/js/novadax.js +1318 -0
- package/js/oceanex.js +816 -0
- package/js/okcoin.js +3841 -0
- package/js/okex.js +16 -0
- package/js/okex5.js +16 -0
- package/js/okx.js +4795 -0
- package/js/paymium.js +498 -0
- package/js/phemex.js +2957 -0
- package/js/poloniex.js +1674 -0
- package/js/probit.js +1346 -0
- package/js/qtrade.js +1588 -0
- package/js/ripio.js +1061 -0
- package/js/static_dependencies/BN/bn.js +3526 -0
- package/js/static_dependencies/README.md +1 -0
- package/js/static_dependencies/crypto-js/crypto-js.js +5988 -0
- package/js/static_dependencies/elliptic/lib/elliptic/curve/base.js +375 -0
- package/js/static_dependencies/elliptic/lib/elliptic/curve/edwards.js +433 -0
- package/js/static_dependencies/elliptic/lib/elliptic/curve/index.js +8 -0
- package/js/static_dependencies/elliptic/lib/elliptic/curve/mont.js +180 -0
- package/js/static_dependencies/elliptic/lib/elliptic/curve/short.js +938 -0
- package/js/static_dependencies/elliptic/lib/elliptic/curves.js +204 -0
- package/js/static_dependencies/elliptic/lib/elliptic/ec/index.js +240 -0
- package/js/static_dependencies/elliptic/lib/elliptic/ec/key.js +119 -0
- package/js/static_dependencies/elliptic/lib/elliptic/ec/signature.js +24 -0
- package/js/static_dependencies/elliptic/lib/elliptic/eddsa/index.js +145 -0
- package/js/static_dependencies/elliptic/lib/elliptic/eddsa/key.js +100 -0
- package/js/static_dependencies/elliptic/lib/elliptic/eddsa/signature.js +65 -0
- package/js/static_dependencies/elliptic/lib/elliptic/precomputed/secp256k1.js +780 -0
- package/js/static_dependencies/elliptic/lib/elliptic/utils.js +214 -0
- package/js/static_dependencies/elliptic/lib/elliptic.js +22 -0
- package/js/static_dependencies/elliptic/lib/hmac-drbg/hmac-drbg.js +114 -0
- package/js/static_dependencies/fetch-ponyfill/fetch-node.js +39 -0
- package/js/static_dependencies/node-fetch/index.js +1564 -0
- package/js/static_dependencies/node-rsa/NodeRSA.js +223 -0
- package/js/static_dependencies/node-rsa/asn1/ber/errors.js +13 -0
- package/js/static_dependencies/node-rsa/asn1/ber/index.js +21 -0
- package/js/static_dependencies/node-rsa/asn1/ber/reader.js +262 -0
- package/js/static_dependencies/node-rsa/asn1/ber/types.js +36 -0
- package/js/static_dependencies/node-rsa/asn1/index.js +17 -0
- package/js/static_dependencies/node-rsa/encryptEngines/js.js +34 -0
- package/js/static_dependencies/node-rsa/formats/components.js +71 -0
- package/js/static_dependencies/node-rsa/formats/formats.js +31 -0
- package/js/static_dependencies/node-rsa/formats/pkcs1.js +148 -0
- package/js/static_dependencies/node-rsa/formats/pkcs8.js +187 -0
- package/js/static_dependencies/node-rsa/libs/jsbn.js +1252 -0
- package/js/static_dependencies/node-rsa/libs/rsa.js +147 -0
- package/js/static_dependencies/node-rsa/schemes/pkcs1.js +176 -0
- package/js/static_dependencies/node-rsa/schemes/schemes.js +21 -0
- package/js/static_dependencies/node-rsa/utils.js +98 -0
- package/js/static_dependencies/qs/formats.js +18 -0
- package/js/static_dependencies/qs/index.js +11 -0
- package/js/static_dependencies/qs/parse.js +242 -0
- package/js/static_dependencies/qs/stringify.js +269 -0
- package/js/static_dependencies/qs/utils.js +230 -0
- package/js/stex.js +1925 -0
- package/js/test/.eslintrc.js +42 -0
- package/js/test/Exchange/test.balance.js +61 -0
- package/js/test/Exchange/test.borrowRate.js +32 -0
- package/js/test/Exchange/test.currency.js +52 -0
- package/js/test/Exchange/test.fetchBalance.js +23 -0
- package/js/test/Exchange/test.fetchBorrowInterest.js +59 -0
- package/js/test/Exchange/test.fetchBorrowRate.js +32 -0
- package/js/test/Exchange/test.fetchBorrowRates.js +28 -0
- package/js/test/Exchange/test.fetchClosedOrders.js +32 -0
- package/js/test/Exchange/test.fetchCurrencies.js +35 -0
- package/js/test/Exchange/test.fetchDeposits.js +31 -0
- package/js/test/Exchange/test.fetchFundingFees.js +19 -0
- package/js/test/Exchange/test.fetchFundingRateHistory.js +40 -0
- package/js/test/Exchange/test.fetchL2OrderBook.js +23 -0
- package/js/test/Exchange/test.fetchLedger.js +42 -0
- package/js/test/Exchange/test.fetchLeverageTiers.js +33 -0
- package/js/test/Exchange/test.fetchMarketLeverageTiers.js +22 -0
- package/js/test/Exchange/test.fetchMarkets.js +33 -0
- package/js/test/Exchange/test.fetchMyTrades.js +42 -0
- package/js/test/Exchange/test.fetchOHLCV.js +46 -0
- package/js/test/Exchange/test.fetchOpenOrders.js +36 -0
- package/js/test/Exchange/test.fetchOrderBook.js +25 -0
- package/js/test/Exchange/test.fetchOrderBooks.js +35 -0
- package/js/test/Exchange/test.fetchOrders.js +41 -0
- package/js/test/Exchange/test.fetchPositions.js +47 -0
- package/js/test/Exchange/test.fetchStatus.js +35 -0
- package/js/test/Exchange/test.fetchTicker.js +38 -0
- package/js/test/Exchange/test.fetchTickers.js +49 -0
- package/js/test/Exchange/test.fetchTrades.js +39 -0
- package/js/test/Exchange/test.fetchTradingFee.js +18 -0
- package/js/test/Exchange/test.fetchTradingFees.js +22 -0
- package/js/test/Exchange/test.fetchTransactions.js +31 -0
- package/js/test/Exchange/test.fetchWithdrawals.js +31 -0
- package/js/test/Exchange/test.ledgerItem.js +46 -0
- package/js/test/Exchange/test.leverageTier.js +33 -0
- package/js/test/Exchange/test.loadMarkets.js +35 -0
- package/js/test/Exchange/test.market.js +129 -0
- package/js/test/Exchange/test.ohlcv.js +33 -0
- package/js/test/Exchange/test.order.js +62 -0
- package/js/test/Exchange/test.orderbook.js +61 -0
- package/js/test/Exchange/test.position.js +21 -0
- package/js/test/Exchange/test.throttle.js +94 -0
- package/js/test/Exchange/test.ticker.js +95 -0
- package/js/test/Exchange/test.trade.js +68 -0
- package/js/test/Exchange/test.tradingFee.js +34 -0
- package/js/test/Exchange/test.transaction.js +35 -0
- package/js/test/base/.eslintrc +38 -0
- package/js/test/base/functions/test.crypto.js +110 -0
- package/js/test/base/functions/test.datetime.js +62 -0
- package/js/test/base/functions/test.generic.js +152 -0
- package/js/test/base/functions/test.number.js +362 -0
- package/js/test/base/functions/test.time.js +56 -0
- package/js/test/base/functions/test.type.js +53 -0
- package/js/test/base/test.base.js +193 -0
- package/js/test/errors/test.InsufficientFunds.js +86 -0
- package/js/test/errors/test.InvalidNonce.js +64 -0
- package/js/test/errors/test.InvalidOrder.js +35 -0
- package/js/test/errors/test.OrderNotFound.js +39 -0
- package/js/test/test.js +426 -0
- package/js/test/test.timeout_hang.js +12 -0
- package/js/therock.js +1431 -0
- package/js/tidebit.js +632 -0
- package/js/tidex.js +939 -0
- package/js/timex.js +1283 -0
- package/js/upbit.js +1622 -0
- package/js/vcc.js +1353 -0
- package/js/wavesexchange.js +2185 -0
- package/js/wazirx.js +732 -0
- package/js/whitebit.js +1352 -0
- package/js/woo.js +1577 -0
- package/js/xena.js +1948 -0
- package/js/yobit.js +1129 -0
- package/js/zaif.js +647 -0
- package/js/zb.js +4088 -0
- package/js/zipmex.js +40 -0
- package/js/zonda.js +1497 -0
- package/multilang.sh +159 -0
- package/package.json +591 -0
- package/postinstall.js +103 -0
@@ -0,0 +1,329 @@
|
|
1
|
+
'use strict'
|
2
|
+
|
3
|
+
/* ------------------------------------------------------------------------
|
4
|
+
|
5
|
+
NB: initially, I used objects for options passing:
|
6
|
+
|
7
|
+
decimalToPrecision ('123.456', { digits: 2, round: true, afterPoint: true })
|
8
|
+
|
9
|
+
...but it turns out it's hard to port that across different languages and it is also
|
10
|
+
probably has a performance penalty -- while it's a performance critical code! So
|
11
|
+
I switched to using named constants instead, as it is actually more readable and
|
12
|
+
succinct, and surely doesn't come with any inherent performance downside:
|
13
|
+
|
14
|
+
decimalToPrecision ('123.456', ROUND, 2, DECIMAL_PLACES) */
|
15
|
+
|
16
|
+
const ROUND = 0 // rounding mode
|
17
|
+
, TRUNCATE = 1
|
18
|
+
, ROUND_UP = 2
|
19
|
+
, ROUND_DOWN = 3
|
20
|
+
|
21
|
+
const DECIMAL_PLACES = 0 // digits counting mode
|
22
|
+
, SIGNIFICANT_DIGITS = 1
|
23
|
+
, TICK_SIZE = 2
|
24
|
+
|
25
|
+
const NO_PADDING = 0 // zero-padding mode
|
26
|
+
, PAD_WITH_ZERO = 1
|
27
|
+
|
28
|
+
const precisionConstants = {
|
29
|
+
ROUND,
|
30
|
+
TRUNCATE,
|
31
|
+
ROUND_UP,
|
32
|
+
ROUND_DOWN,
|
33
|
+
DECIMAL_PLACES,
|
34
|
+
SIGNIFICANT_DIGITS,
|
35
|
+
TICK_SIZE,
|
36
|
+
NO_PADDING,
|
37
|
+
PAD_WITH_ZERO,
|
38
|
+
}
|
39
|
+
|
40
|
+
/* ------------------------------------------------------------------------ */
|
41
|
+
|
42
|
+
// See https://stackoverflow.com/questions/1685680/how-to-avoid-scientific-notation-for-large-numbers-in-javascript for discussion
|
43
|
+
|
44
|
+
function numberToString (x) { // avoids scientific notation for too large and too small numbers
|
45
|
+
if (x === undefined) return undefined
|
46
|
+
|
47
|
+
if (typeof x !== 'number') return x.toString ()
|
48
|
+
|
49
|
+
const s = x.toString ()
|
50
|
+
if (Math.abs (x) < 1.0) {
|
51
|
+
const n_e = s.split ('e-')
|
52
|
+
const n = n_e[0].replace ('.', '')
|
53
|
+
const e = parseInt (n_e[1])
|
54
|
+
const neg = (s[0] === '-')
|
55
|
+
if (e) {
|
56
|
+
x = (neg ? '-' : '') + '0.' + (new Array (e)).join ('0') + n.substring (neg)
|
57
|
+
return x
|
58
|
+
}
|
59
|
+
} else {
|
60
|
+
const parts = s.split ('e')
|
61
|
+
if (parts[1]) {
|
62
|
+
let e = parseInt (parts[1])
|
63
|
+
const m = parts[0].split ('.')
|
64
|
+
let part = ''
|
65
|
+
if (m[1]) {
|
66
|
+
e -= m[1].length
|
67
|
+
part = m[1]
|
68
|
+
}
|
69
|
+
return m[0] + part + (new Array (e + 1)).join ('0')
|
70
|
+
}
|
71
|
+
}
|
72
|
+
return s
|
73
|
+
}
|
74
|
+
|
75
|
+
//-----------------------------------------------------------------------------
|
76
|
+
// expects non-scientific notation
|
77
|
+
|
78
|
+
const truncate_regExpCache = []
|
79
|
+
, truncate_to_string = (num, precision = 0) => {
|
80
|
+
num = numberToString (num)
|
81
|
+
if (precision > 0) {
|
82
|
+
const re = truncate_regExpCache[precision] || (truncate_regExpCache[precision] = new RegExp ("([-]*\\d+\\.\\d{" + precision + "})(\\d)"))
|
83
|
+
const [ , result] = num.toString ().match (re) || [null, num]
|
84
|
+
return result.toString ()
|
85
|
+
}
|
86
|
+
return parseInt (num).toString ()
|
87
|
+
}
|
88
|
+
, truncate = (num, precision = 0) => parseFloat (truncate_to_string (num, precision))
|
89
|
+
|
90
|
+
function precisionFromString (string) {
|
91
|
+
const split = string.replace (/0+$/g, '').split ('.')
|
92
|
+
return (split.length > 1) ? (split[1].length) : 0
|
93
|
+
}
|
94
|
+
|
95
|
+
/* ------------------------------------------------------------------------ */
|
96
|
+
|
97
|
+
const decimalToPrecision = (x, roundingMode
|
98
|
+
, numPrecisionDigits
|
99
|
+
, countingMode = DECIMAL_PLACES
|
100
|
+
, paddingMode = NO_PADDING) => {
|
101
|
+
|
102
|
+
if (countingMode === TICK_SIZE) {
|
103
|
+
if (numPrecisionDigits <= 0) {
|
104
|
+
throw new Error ('TICK_SIZE cant be used with negative or zero numPrecisionDigits')
|
105
|
+
}
|
106
|
+
}
|
107
|
+
|
108
|
+
if (numPrecisionDigits < 0) {
|
109
|
+
const toNearest = Math.pow (10, -numPrecisionDigits)
|
110
|
+
if (roundingMode === ROUND) {
|
111
|
+
return (toNearest * decimalToPrecision (x / toNearest, roundingMode, 0, countingMode, paddingMode)).toString ()
|
112
|
+
}
|
113
|
+
if (roundingMode === TRUNCATE) {
|
114
|
+
return (x - (x % toNearest)).toString ()
|
115
|
+
}
|
116
|
+
}
|
117
|
+
|
118
|
+
/* handle tick size */
|
119
|
+
if (countingMode === TICK_SIZE) {
|
120
|
+
const precisionDigitsString = decimalToPrecision (numPrecisionDigits, ROUND, 22, DECIMAL_PLACES, NO_PADDING)
|
121
|
+
const newNumPrecisionDigits = precisionFromString (precisionDigitsString)
|
122
|
+
let missing = x % numPrecisionDigits
|
123
|
+
// See: https://github.com/ccxt/ccxt/pull/6486
|
124
|
+
missing = Number (decimalToPrecision (missing, ROUND, 8, DECIMAL_PLACES, NO_PADDING));
|
125
|
+
const fpError = decimalToPrecision (missing / numPrecisionDigits, ROUND, Math.max (newNumPrecisionDigits, 8), DECIMAL_PLACES, NO_PADDING)
|
126
|
+
if (precisionFromString (fpError) !== 0) {
|
127
|
+
if (roundingMode === ROUND) {
|
128
|
+
if (x > 0) {
|
129
|
+
if (missing >= numPrecisionDigits / 2) {
|
130
|
+
x = x - missing + numPrecisionDigits
|
131
|
+
} else {
|
132
|
+
x = x - missing
|
133
|
+
}
|
134
|
+
} else {
|
135
|
+
if (missing >= numPrecisionDigits / 2) {
|
136
|
+
x = Number (x) - missing
|
137
|
+
} else {
|
138
|
+
x = Number (x) - missing - numPrecisionDigits
|
139
|
+
}
|
140
|
+
}
|
141
|
+
} else if (roundingMode === TRUNCATE) {
|
142
|
+
x = x - missing
|
143
|
+
}
|
144
|
+
}
|
145
|
+
return decimalToPrecision (x, ROUND, newNumPrecisionDigits, DECIMAL_PLACES, paddingMode);
|
146
|
+
}
|
147
|
+
|
148
|
+
/* Convert to a string (if needed), skip leading minus sign (if any) */
|
149
|
+
|
150
|
+
const str = numberToString (x)
|
151
|
+
, isNegative = str[0] === '-'
|
152
|
+
, strStart = isNegative ? 1 : 0
|
153
|
+
, strEnd = str.length
|
154
|
+
|
155
|
+
/* Find the dot position in the source buffer */
|
156
|
+
|
157
|
+
for (var strDot = 0; strDot < strEnd; strDot++)
|
158
|
+
if (str[strDot] === '.')
|
159
|
+
break
|
160
|
+
|
161
|
+
const hasDot = strDot < str.length
|
162
|
+
|
163
|
+
/* Char code constants */
|
164
|
+
|
165
|
+
const MINUS = 45
|
166
|
+
, DOT = 46
|
167
|
+
, ZERO = 48
|
168
|
+
, ONE = (ZERO + 1)
|
169
|
+
, FIVE = (ZERO + 5)
|
170
|
+
, NINE = (ZERO + 9)
|
171
|
+
|
172
|
+
/* For -123.4567 the `chars` array will hold 01234567 (leading zero is reserved for rounding cases when 099 → 100) */
|
173
|
+
|
174
|
+
const chars = new Uint8Array ((strEnd - strStart) + (hasDot ? 0 : 1))
|
175
|
+
chars[0] = ZERO
|
176
|
+
|
177
|
+
/* Validate & copy digits, determine certain locations in the resulting buffer */
|
178
|
+
|
179
|
+
let afterDot = chars.length
|
180
|
+
, digitsStart = -1 // significant digits
|
181
|
+
, digitsEnd = -1
|
182
|
+
|
183
|
+
for (var i = 1, j = strStart; j < strEnd; j++, i++) {
|
184
|
+
|
185
|
+
const c = str.charCodeAt (j)
|
186
|
+
|
187
|
+
if (c === DOT) {
|
188
|
+
afterDot = i--
|
189
|
+
|
190
|
+
} else if ((c < ZERO) || (c > NINE)) {
|
191
|
+
throw new Error (`${str}: invalid number (contains an illegal character '${str[i - 1]}')`)
|
192
|
+
|
193
|
+
} else {
|
194
|
+
chars[i] = c
|
195
|
+
if ((c !== ZERO) && (digitsStart < 0)) digitsStart = i
|
196
|
+
}
|
197
|
+
}
|
198
|
+
|
199
|
+
if (digitsStart < 0) digitsStart = 1
|
200
|
+
|
201
|
+
/* Determine the range to cut */
|
202
|
+
|
203
|
+
let precisionStart = (countingMode === DECIMAL_PLACES) ? afterDot // 0.(0)001234567
|
204
|
+
: digitsStart // 0.00(1)234567
|
205
|
+
, precisionEnd = precisionStart +
|
206
|
+
numPrecisionDigits
|
207
|
+
|
208
|
+
/* Reset the last significant digit index, as it will change during the rounding/truncation. */
|
209
|
+
|
210
|
+
digitsEnd = -1
|
211
|
+
|
212
|
+
/* Perform rounding/truncation per digit, from digitsEnd to digitsStart, by using the following
|
213
|
+
algorithm (rounding 999 → 1000, as an example):
|
214
|
+
|
215
|
+
step = i=3 i=2 i=1 i=0
|
216
|
+
|
217
|
+
chars = 0999 0999 0900 1000
|
218
|
+
memo = ---0 --1- -1-- 0--- */
|
219
|
+
|
220
|
+
let allZeros = true;
|
221
|
+
let signNeeded = isNegative;
|
222
|
+
|
223
|
+
for (let i = chars.length - 1, memo = 0; i >= 0; i--) {
|
224
|
+
|
225
|
+
let c = chars[i]
|
226
|
+
|
227
|
+
if (i !== 0) {
|
228
|
+
c += memo
|
229
|
+
|
230
|
+
if (i >= (precisionStart + numPrecisionDigits)) {
|
231
|
+
|
232
|
+
const ceil = (roundingMode === ROUND) &&
|
233
|
+
(c >= FIVE) &&
|
234
|
+
!((c === FIVE) && memo) // prevents rounding of 1.45 to 2
|
235
|
+
|
236
|
+
c = ceil ? (NINE + 1) : ZERO
|
237
|
+
}
|
238
|
+
if (c > NINE) { c = ZERO; memo = 1; }
|
239
|
+
else memo = 0
|
240
|
+
|
241
|
+
} else if (memo) c = ONE // leading extra digit (0900 → 1000)
|
242
|
+
|
243
|
+
chars[i] = c
|
244
|
+
|
245
|
+
if (c !== ZERO) {
|
246
|
+
allZeros = false
|
247
|
+
digitsStart = i
|
248
|
+
digitsEnd = (digitsEnd < 0) ? (i + 1) : digitsEnd
|
249
|
+
}
|
250
|
+
}
|
251
|
+
|
252
|
+
/* Update the precision range, as `digitsStart` may have changed... & the need for a negative sign if it is only 0 */
|
253
|
+
|
254
|
+
if (countingMode === SIGNIFICANT_DIGITS) {
|
255
|
+
precisionStart = digitsStart
|
256
|
+
precisionEnd = precisionStart + numPrecisionDigits
|
257
|
+
}
|
258
|
+
|
259
|
+
if (allZeros) {
|
260
|
+
signNeeded = false
|
261
|
+
}
|
262
|
+
|
263
|
+
/* Determine the input character range */
|
264
|
+
|
265
|
+
const readStart = ((digitsStart >= afterDot) || allZeros) ? (afterDot - 1) : digitsStart // 0.000(1)234 ----> (0).0001234
|
266
|
+
, readEnd = (digitsEnd < afterDot) ? (afterDot ) : digitsEnd // 12(3)000 ----> 123000( )
|
267
|
+
|
268
|
+
/* Compute various sub-ranges */
|
269
|
+
|
270
|
+
const nSign = (signNeeded ? 1 : 0) // (-)123.456
|
271
|
+
, nBeforeDot = (nSign + (afterDot - readStart)) // (-123).456
|
272
|
+
, nAfterDot = Math.max (readEnd - afterDot, 0) // -123.(456)
|
273
|
+
, actualLength = (readEnd - readStart) // -(123.456)
|
274
|
+
, desiredLength = (paddingMode === NO_PADDING)
|
275
|
+
? (actualLength) // -(123.456)
|
276
|
+
: (precisionEnd - readStart) // -(123.456 )
|
277
|
+
|
278
|
+
, pad = Math.max (desiredLength - actualLength, 0) // -123.456( )
|
279
|
+
, padStart = (nBeforeDot + 1 + nAfterDot) // -123.456( )
|
280
|
+
, padEnd = (padStart + pad) // -123.456 ( )
|
281
|
+
, isInteger = (nAfterDot + pad) === 0 // -123
|
282
|
+
|
283
|
+
/* Fill the output buffer with characters */
|
284
|
+
|
285
|
+
const out = new Uint8Array (nBeforeDot + (isInteger ? 0 : 1) + nAfterDot + pad)
|
286
|
+
// ------------------------------------------------------------------------------------------ // ---------------------
|
287
|
+
if (signNeeded) out[0] = MINUS // - minus sign
|
288
|
+
for (i = nSign, j = readStart; i < nBeforeDot; i++, j++) out[i] = chars[j] // 123 before dot
|
289
|
+
if (!isInteger) out[nBeforeDot] = DOT // . dot
|
290
|
+
for (i = nBeforeDot + 1, j = afterDot; i < padStart; i++, j++) out[i] = chars[j] // 456 after dot
|
291
|
+
for (i = padStart; i < padEnd; i++) out[i] = ZERO // 000 padding
|
292
|
+
|
293
|
+
/* Build a string from the output buffer */
|
294
|
+
|
295
|
+
return String.fromCharCode (...out)
|
296
|
+
}
|
297
|
+
|
298
|
+
function omitZero (stringNumber) {
|
299
|
+
if (stringNumber === undefined || stringNumber === '') {
|
300
|
+
return undefined
|
301
|
+
}
|
302
|
+
if (parseFloat (stringNumber) === 0) {
|
303
|
+
return undefined
|
304
|
+
}
|
305
|
+
return stringNumber
|
306
|
+
}
|
307
|
+
|
308
|
+
/* ------------------------------------------------------------------------ */
|
309
|
+
|
310
|
+
module.exports = {
|
311
|
+
numberToString,
|
312
|
+
precisionFromString,
|
313
|
+
decimalToPrecision,
|
314
|
+
truncate_to_string,
|
315
|
+
truncate,
|
316
|
+
omitZero,
|
317
|
+
precisionConstants,
|
318
|
+
ROUND,
|
319
|
+
TRUNCATE,
|
320
|
+
ROUND_UP,
|
321
|
+
ROUND_DOWN,
|
322
|
+
DECIMAL_PLACES,
|
323
|
+
SIGNIFICANT_DIGITS,
|
324
|
+
TICK_SIZE,
|
325
|
+
NO_PADDING,
|
326
|
+
PAD_WITH_ZERO,
|
327
|
+
}
|
328
|
+
|
329
|
+
/* ------------------------------------------------------------------------ */
|
@@ -0,0 +1,38 @@
|
|
1
|
+
"use strict";
|
2
|
+
|
3
|
+
// ----------------------------------------------------------------------------
|
4
|
+
// There's been a lot of messing with this code...
|
5
|
+
// The problem is to satisfy the following requirements:
|
6
|
+
// - properly detect isNode == true on server side and isNode == false in the browser (on client side)
|
7
|
+
// - make sure create-react-app, react-starter-kit and other react frameworks work
|
8
|
+
// - make sure it does not break the browserified version (when linked into a html from a cdn)
|
9
|
+
// - make sure it does not break the webpacking and babel-transpiled scripts
|
10
|
+
// - make sure it works in Electron
|
11
|
+
// - make sure it works with Angular.js
|
12
|
+
// - make sure it does not break other possible usage scenarios
|
13
|
+
|
14
|
+
const isBrowser = typeof window !== 'undefined'
|
15
|
+
|
16
|
+
const isElectron = typeof process !== 'undefined' &&
|
17
|
+
typeof process.versions !== 'undefined' &&
|
18
|
+
typeof process.versions.electron !== 'undefined'
|
19
|
+
|
20
|
+
const isWebWorker = typeof WorkerGlobalScope !== 'undefined' && (self instanceof WorkerGlobalScope)
|
21
|
+
|
22
|
+
const isWindows = typeof process !== 'undefined' && process.platform === "win32"
|
23
|
+
|
24
|
+
const isNode = !(isBrowser || isWebWorker)
|
25
|
+
|
26
|
+
const defaultFetch = typeof (fetch) === "undefined" ? require ('../../static_dependencies/fetch-ponyfill/fetch-node') ().fetch : fetch
|
27
|
+
|
28
|
+
// ----------------------------------------------------------------------------
|
29
|
+
|
30
|
+
module.exports = {
|
31
|
+
|
32
|
+
isBrowser,
|
33
|
+
isElectron,
|
34
|
+
isWebWorker,
|
35
|
+
isNode,
|
36
|
+
isWindows,
|
37
|
+
defaultFetch,
|
38
|
+
}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
"use strict";
|
2
|
+
|
3
|
+
// ----------------------------------------------------------------------------
|
4
|
+
|
5
|
+
const uuid = a => a ? (a ^ Math.random () * 16 >> a / 4).toString (16) : ([1e7]+-1e3+-4e3+-8e3+-1e11).replace (/[018]/g, uuid)
|
6
|
+
const uuid16 = a => a ? (a ^ Math.random () * 16 >> a / 4).toString (16) : ([1e5]+1e2+4e2+8e3).replace (/[018]/g, uuid16)
|
7
|
+
const uuid22 = a => a ? (a ^ Math.random () * 16 >> a / 4).toString (16) : ([1e7]+1e3+4e3+8e5).replace (/[018]/g, uuid22)
|
8
|
+
|
9
|
+
|
10
|
+
// ----------------------------------------------------------------------------
|
11
|
+
|
12
|
+
module.exports = {
|
13
|
+
|
14
|
+
uuid
|
15
|
+
, uuid16
|
16
|
+
, uuid22
|
17
|
+
// hasFetchOHLCV → has_fetch_ohlcv; parseHTTPResponse → parse_http_response
|
18
|
+
, unCamelCase: s => s.match (/^[A-Z0-9_]+$/) ? s : (s.replace (/[a-z0-9][A-Z]/g, x => x[0] + '_' + x[1]).replace(/[A-Z0-9][A-Z0-9][a-z]/g, x => x[0] + '_' + x[1] + x[2]).toLowerCase ())
|
19
|
+
, capitalize: s => s.length ? (s.charAt (0).toUpperCase () + s.slice (1)) : s
|
20
|
+
, strip: s => s.replace(/^\s+|\s+$/g, '')
|
21
|
+
}
|
@@ -0,0 +1,79 @@
|
|
1
|
+
"use strict";
|
2
|
+
|
3
|
+
/* ------------------------------------------------------------------------ */
|
4
|
+
|
5
|
+
const { now, sleep } = require ('./time')
|
6
|
+
|
7
|
+
/* ------------------------------------------------------------------------ */
|
8
|
+
|
9
|
+
class Throttle {
|
10
|
+
constructor (config) {
|
11
|
+
this.config = {
|
12
|
+
refillRate: 1.0,
|
13
|
+
delay: 0.001,
|
14
|
+
capacity: 1.0,
|
15
|
+
maxCapacity: 2000,
|
16
|
+
tokens: 0,
|
17
|
+
cost: 1.0,
|
18
|
+
}
|
19
|
+
Object.assign (this.config, config)
|
20
|
+
this.queue = []
|
21
|
+
this.running = false
|
22
|
+
}
|
23
|
+
|
24
|
+
async loop () {
|
25
|
+
let lastTimestamp = now ()
|
26
|
+
while (this.running) {
|
27
|
+
const { resolver, cost } = this.queue[0]
|
28
|
+
if (this.config['tokens'] >= 0) {
|
29
|
+
this.config['tokens'] -= cost
|
30
|
+
resolver ()
|
31
|
+
this.queue.shift ()
|
32
|
+
// contextswitch
|
33
|
+
await Promise.resolve ()
|
34
|
+
if (this.queue.length === 0) {
|
35
|
+
this.running = false
|
36
|
+
}
|
37
|
+
} else {
|
38
|
+
await sleep (this.config['delay'] * 1000);
|
39
|
+
const current = now ()
|
40
|
+
const elapsed = current - lastTimestamp
|
41
|
+
lastTimestamp = current
|
42
|
+
this.config['tokens'] = Math.min (this.config['tokens'] + (this.config['refillRate'] * elapsed), this.config['capacity'])
|
43
|
+
}
|
44
|
+
}
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
function throttle (config) {
|
49
|
+
function inner (cost = undefined) {
|
50
|
+
let resolver
|
51
|
+
const promise = new Promise ((resolve, reject) => {
|
52
|
+
resolver = resolve
|
53
|
+
})
|
54
|
+
if (this.queue.length > this.config['maxCapacity']) {
|
55
|
+
throw new Error ('throttle queue is over maxCapacity')
|
56
|
+
}
|
57
|
+
cost = (cost === undefined) ? this.config['cost'] : cost
|
58
|
+
this.queue.push ({
|
59
|
+
resolver,
|
60
|
+
cost,
|
61
|
+
})
|
62
|
+
if (!this.running) {
|
63
|
+
this.running = true
|
64
|
+
this.loop ()
|
65
|
+
}
|
66
|
+
return promise
|
67
|
+
}
|
68
|
+
const instance = new Throttle (config)
|
69
|
+
const bound = inner.bind (instance)
|
70
|
+
// useful for inspecting the tokenBucket
|
71
|
+
bound.config = instance.config
|
72
|
+
return bound
|
73
|
+
}
|
74
|
+
|
75
|
+
module.exports = {
|
76
|
+
throttle,
|
77
|
+
}
|
78
|
+
|
79
|
+
// ----------------------------------------
|
@@ -0,0 +1,210 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
/* ------------------------------------------------------------------------ */
|
4
|
+
|
5
|
+
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...
|
6
|
+
const microseconds = () => now () * 1000 // TODO: utilize performance.now for that purpose
|
7
|
+
const milliseconds = now
|
8
|
+
const seconds = () => Math.floor (now () / 1000)
|
9
|
+
const uuidv1 = () => {
|
10
|
+
const biasSeconds = 12219292800 // seconds from 15th Oct 1572 to Jan 1st 1970
|
11
|
+
const bias = biasSeconds * 10000000 // in hundreds of nanoseconds
|
12
|
+
const time = microseconds () * 10 + bias
|
13
|
+
const timeHex = time.toString (16)
|
14
|
+
const arranged = timeHex.slice (7, 15) + timeHex.slice (3, 7) + '1' + timeHex.slice (0, 3)
|
15
|
+
// these should be random, but we're not making more than 10 requests per microsecond so who cares
|
16
|
+
const clockId = '9696' // a 14 bit number
|
17
|
+
const macAddress = 'ff'.repeat (6)
|
18
|
+
return arranged + clockId + macAddress
|
19
|
+
}
|
20
|
+
|
21
|
+
/* ------------------------------------------------------------------------ */
|
22
|
+
|
23
|
+
const setTimeout_original = setTimeout
|
24
|
+
const setTimeout_safe = (done, ms, setTimeout = setTimeout_original /* overrideable for mocking purposes */, targetTime = now () + ms) => {
|
25
|
+
|
26
|
+
// avoid MAX_INT issue https://stackoverflow.com/questions/60474110
|
27
|
+
if (ms >= 2147483647) {
|
28
|
+
throw new Exception('setTimeout() function was called with unrealistic value of ' + ms.toString ())
|
29
|
+
}
|
30
|
+
|
31
|
+
// The built-in setTimeout function can fire its callback earlier than specified, so we
|
32
|
+
// need to ensure that it does not happen: sleep recursively until `targetTime` is reached...
|
33
|
+
|
34
|
+
let clearInnerTimeout = () => {}
|
35
|
+
let active = true
|
36
|
+
|
37
|
+
const id = setTimeout (() => {
|
38
|
+
active = true
|
39
|
+
const rest = targetTime - now ()
|
40
|
+
if (rest > 0) {
|
41
|
+
clearInnerTimeout = setTimeout_safe (done, rest, setTimeout, targetTime) // try sleep more
|
42
|
+
} else {
|
43
|
+
done ()
|
44
|
+
}
|
45
|
+
}, ms)
|
46
|
+
|
47
|
+
return function clear () {
|
48
|
+
if (active) {
|
49
|
+
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)
|
50
|
+
clearTimeout (id)
|
51
|
+
}
|
52
|
+
clearInnerTimeout ()
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
/* ------------------------------------------------------------------------ */
|
57
|
+
|
58
|
+
class TimedOut extends Error {
|
59
|
+
|
60
|
+
constructor () {
|
61
|
+
const message = 'timed out'
|
62
|
+
super (message)
|
63
|
+
this.constructor = TimedOut
|
64
|
+
this.__proto__ = TimedOut.prototype
|
65
|
+
this.message = message
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
/* ------------------------------------------------------------------------ */
|
70
|
+
|
71
|
+
const iso8601 = (timestamp) => {
|
72
|
+
let _timestampNumber = undefined;
|
73
|
+
if (typeof timestamp === 'number') {
|
74
|
+
_timestampNumber = Math.floor (timestamp);
|
75
|
+
} else {
|
76
|
+
_timestampNumber = parseInt (timestamp, 10);
|
77
|
+
}
|
78
|
+
|
79
|
+
// undefined, null and lots of nasty non-numeric values yield NaN
|
80
|
+
if (Number.isNaN (_timestampNumber) || _timestampNumber < 0) {
|
81
|
+
return undefined;
|
82
|
+
}
|
83
|
+
|
84
|
+
// last line of defence
|
85
|
+
try {
|
86
|
+
return new Date (_timestampNumber).toISOString ();
|
87
|
+
} catch (e) {
|
88
|
+
return undefined;
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
92
|
+
const parse8601 = (x) => {
|
93
|
+
if (typeof x !== 'string' || !x) {
|
94
|
+
return undefined;
|
95
|
+
}
|
96
|
+
|
97
|
+
if (x.match (/^[0-9]+$/)) {
|
98
|
+
// a valid number in a string, not a date.
|
99
|
+
return undefined;
|
100
|
+
}
|
101
|
+
|
102
|
+
if (x.indexOf ('-') < 0 || x.indexOf (':') < 0) { // no date can be without a dash and a colon
|
103
|
+
return undefined;
|
104
|
+
}
|
105
|
+
|
106
|
+
// last line of defence
|
107
|
+
try {
|
108
|
+
const candidate = Date.parse (((x.indexOf ('+') >= 0) || (x.slice (-1) === 'Z')) ? x : (x + 'Z').replace (/\s(\d\d):/, 'T$1:'));
|
109
|
+
if (Number.isNaN (candidate)) {
|
110
|
+
return undefined;
|
111
|
+
}
|
112
|
+
return candidate;
|
113
|
+
} catch (e) {
|
114
|
+
return undefined;
|
115
|
+
}
|
116
|
+
}
|
117
|
+
|
118
|
+
const parseDate = (x) => {
|
119
|
+
if (typeof x !== 'string' || !x) {
|
120
|
+
return undefined;
|
121
|
+
}
|
122
|
+
|
123
|
+
if (x.indexOf ('GMT') >= 0) {
|
124
|
+
try {
|
125
|
+
return Date.parse (x);
|
126
|
+
} catch (e) {
|
127
|
+
return undefined;
|
128
|
+
}
|
129
|
+
}
|
130
|
+
|
131
|
+
return parse8601 (x);
|
132
|
+
}
|
133
|
+
|
134
|
+
const rfc2616 = (timestamp = undefined) => new Date (timestamp).toUTCString ();
|
135
|
+
|
136
|
+
const mdy = (timestamp, infix = '-') => {
|
137
|
+
infix = infix || ''
|
138
|
+
const date = new Date (timestamp)
|
139
|
+
const Y = date.getUTCFullYear ().toString ()
|
140
|
+
let m = date.getUTCMonth () + 1
|
141
|
+
let d = date.getUTCDate ()
|
142
|
+
m = m < 10 ? ('0' + m) : m.toString ()
|
143
|
+
d = d < 10 ? ('0' + d) : d.toString ()
|
144
|
+
return m + infix + d + infix + Y
|
145
|
+
}
|
146
|
+
|
147
|
+
const ymd = (timestamp, infix, fullYear = true) => {
|
148
|
+
infix = infix || ''
|
149
|
+
const date = new Date (timestamp)
|
150
|
+
const intYear = date.getUTCFullYear ()
|
151
|
+
const year = fullYear ? intYear : (intYear - 2000)
|
152
|
+
const Y = year.toString ()
|
153
|
+
let m = date.getUTCMonth () + 1
|
154
|
+
let d = date.getUTCDate ()
|
155
|
+
m = m < 10 ? ('0' + m) : m.toString ()
|
156
|
+
d = d < 10 ? ('0' + d) : d.toString ()
|
157
|
+
return Y + infix + m + infix + d
|
158
|
+
}
|
159
|
+
|
160
|
+
const yymmdd = (timestamp, infix = '') => ymd (timestamp, infix, false)
|
161
|
+
const yyyymmdd = (timestamp, infix = '-') => ymd (timestamp, infix, true)
|
162
|
+
|
163
|
+
const ymdhms = (timestamp, infix = ' ') => {
|
164
|
+
const date = new Date (timestamp)
|
165
|
+
const Y = date.getUTCFullYear ()
|
166
|
+
let m = date.getUTCMonth () + 1
|
167
|
+
let d = date.getUTCDate ()
|
168
|
+
let H = date.getUTCHours ()
|
169
|
+
let M = date.getUTCMinutes ()
|
170
|
+
let S = date.getUTCSeconds ()
|
171
|
+
m = m < 10 ? ('0' + m) : m
|
172
|
+
d = d < 10 ? ('0' + d) : d
|
173
|
+
H = H < 10 ? ('0' + H) : H
|
174
|
+
M = M < 10 ? ('0' + M) : M
|
175
|
+
S = S < 10 ? ('0' + S) : S
|
176
|
+
return Y + '-' + m + '-' + d + infix + H + ':' + M + ':' + S
|
177
|
+
}
|
178
|
+
|
179
|
+
module.exports = {
|
180
|
+
now
|
181
|
+
, microseconds
|
182
|
+
, milliseconds
|
183
|
+
, seconds
|
184
|
+
, iso8601
|
185
|
+
, parse8601
|
186
|
+
, rfc2616
|
187
|
+
, uuidv1
|
188
|
+
, parseDate
|
189
|
+
, mdy
|
190
|
+
, ymd
|
191
|
+
, yymmdd
|
192
|
+
, yyyymmdd
|
193
|
+
, ymdhms
|
194
|
+
, setTimeout_safe
|
195
|
+
, sleep: (ms) => new Promise ((resolve) => setTimeout_safe (resolve, ms))
|
196
|
+
, TimedOut
|
197
|
+
, timeout: async (ms, promise) => {
|
198
|
+
|
199
|
+
let clear = () => {}
|
200
|
+
const expires = new Promise ((resolve) => (clear = setTimeout_safe (resolve, ms)))
|
201
|
+
|
202
|
+
try {
|
203
|
+
return await Promise.race ([promise, expires.then (() => { throw new TimedOut () })])
|
204
|
+
} finally {
|
205
|
+
clear () // fixes https://github.com/ccxt/ccxt/issues/749
|
206
|
+
}
|
207
|
+
}
|
208
|
+
}
|
209
|
+
|
210
|
+
/* ------------------------------------------------------------------------ */
|