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,129 @@
|
|
1
|
+
'use strict'
|
2
|
+
|
3
|
+
const assert = require ('assert')
|
4
|
+
|
5
|
+
function testMarket (exchange, market, method) {
|
6
|
+
const format = {
|
7
|
+
'id': 'btcusd', // string literal for referencing within an exchange
|
8
|
+
'symbol': 'BTC/USD', // uppercase string literal of a pair of currencies
|
9
|
+
'base': 'BTC', // unified uppercase string, base currency, 3 or more letters
|
10
|
+
'quote': 'USD', // unified uppercase string, quote currency, 3 or more letters
|
11
|
+
'taker': 0.0011, // taker fee, for example, 0.0011 = 0.11%
|
12
|
+
'maker': 0.0009, // maker fee, for example, 0.0009 = 0.09%
|
13
|
+
'baseId': 'btc', // exchange-specific base currency id
|
14
|
+
'quoteId': 'usd', // exchange-specific quote currency id
|
15
|
+
'active': true, // boolean, market status
|
16
|
+
'type': 'spot',
|
17
|
+
'linear': undefined,
|
18
|
+
'inverse': undefined,
|
19
|
+
'spot': true,
|
20
|
+
'swap': false,
|
21
|
+
'future': false,
|
22
|
+
'option': false,
|
23
|
+
'margin': false,
|
24
|
+
'contract': false,
|
25
|
+
'contractSize': 0.001,
|
26
|
+
'expiry': 1656057600000,
|
27
|
+
'expiryDatetime': '2022-06-24T08:00:00.000Z',
|
28
|
+
'optionType': 'put',
|
29
|
+
'strike': 56000,
|
30
|
+
'settle': undefined,
|
31
|
+
'settleId': undefined,
|
32
|
+
'precision': {
|
33
|
+
'price': 8, // integer or fraction
|
34
|
+
'amount': 8, // integer or fraction
|
35
|
+
'cost': 8, // integer or fraction
|
36
|
+
},
|
37
|
+
// value limits when placing orders on this market
|
38
|
+
'limits': {
|
39
|
+
'amount': {
|
40
|
+
'min': 0.01, // order amount should be > min
|
41
|
+
'max': 1000, // order amount should be < max
|
42
|
+
},
|
43
|
+
'price': {
|
44
|
+
'min': 0.01, // order price should be > min
|
45
|
+
'max': 1000, // order price should be < max
|
46
|
+
},
|
47
|
+
// order cost = price * amount
|
48
|
+
'cost': {
|
49
|
+
'min': 0.01, // order cost should be > min
|
50
|
+
'max': 1000, // order cost should be < max
|
51
|
+
},
|
52
|
+
},
|
53
|
+
'info': {}, // the original unparsed market info from the exchange
|
54
|
+
};
|
55
|
+
let keys = Object.keys (format);
|
56
|
+
for (let i = 0; i < keys.length; i++) {
|
57
|
+
const key = keys[i];
|
58
|
+
const keyPresent = (key in market);
|
59
|
+
assert (keyPresent, key + ' missing ' + exchange.json (market));
|
60
|
+
}
|
61
|
+
keys = [
|
62
|
+
'id',
|
63
|
+
'symbol',
|
64
|
+
'baseId',
|
65
|
+
'quoteId',
|
66
|
+
'base',
|
67
|
+
'quote',
|
68
|
+
'precision',
|
69
|
+
'limits',
|
70
|
+
];
|
71
|
+
for (let i = 0; i < keys.length; i++) {
|
72
|
+
const key = keys[i];
|
73
|
+
assert (market[key] !== undefined, key + ' undefined ' + exchange.json (market));
|
74
|
+
}
|
75
|
+
assert ((market['taker'] === undefined) || (typeof market['taker'] === 'number'));
|
76
|
+
assert ((market['maker'] === undefined) || (typeof market['maker'] === 'number'));
|
77
|
+
if (market['contract']) {
|
78
|
+
assert (market['linear'] !== market['inverse']);
|
79
|
+
} else {
|
80
|
+
assert ((market['linear'] === undefined) && (market['inverse'] === undefined));
|
81
|
+
}
|
82
|
+
if (market['option']) {
|
83
|
+
assert (market['strike'] !== undefined);
|
84
|
+
assert (market['optionType'] !== undefined);
|
85
|
+
}
|
86
|
+
const validTypes = {
|
87
|
+
'spot': true,
|
88
|
+
'margin': true,
|
89
|
+
'swap': true,
|
90
|
+
'future': true,
|
91
|
+
'option': true,
|
92
|
+
};
|
93
|
+
const type = market['type'];
|
94
|
+
//
|
95
|
+
// binance has type = 'delivery'
|
96
|
+
// https://github.com/ccxt/ccxt/issues/11121
|
97
|
+
//
|
98
|
+
// assert (type in validTypes);
|
99
|
+
//
|
100
|
+
const types = Object.keys (validTypes);
|
101
|
+
for (let i = 0; i < types.length; i++) {
|
102
|
+
const entry = types[i];
|
103
|
+
if (entry in market) {
|
104
|
+
const value = market[entry];
|
105
|
+
assert ((value === undefined) || value || !value);
|
106
|
+
}
|
107
|
+
}
|
108
|
+
//
|
109
|
+
// todo fix binance
|
110
|
+
//
|
111
|
+
// if (market['future']) {
|
112
|
+
// assert ((market['swap'] === false) && (market['option'] === false));
|
113
|
+
// } else if (market['swap']) {
|
114
|
+
// assert ((market['future'] === false) && (market['option'] === false));
|
115
|
+
// } else if (market['option']) {
|
116
|
+
// assert ((market['future'] === false) && (market['swap'] === false));
|
117
|
+
// }
|
118
|
+
// if (market['linear']) {
|
119
|
+
// assert (market['inverse'] === false);
|
120
|
+
// } else if (market['inverse']) {
|
121
|
+
// assert (market['linear'] === false);
|
122
|
+
// }
|
123
|
+
// if (market['future']) {
|
124
|
+
// assert (market['expiry'] !== undefined);
|
125
|
+
// assert (market['expiryDatetime'] !== undefined);
|
126
|
+
// }
|
127
|
+
}
|
128
|
+
|
129
|
+
module.exports = testMarket;
|
@@ -0,0 +1,33 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
const assert = require ('assert');
|
4
|
+
|
5
|
+
function testOHLCV (exchange, ohlcv, symbol, now) {
|
6
|
+
|
7
|
+
const json = exchange.json (ohlcv);
|
8
|
+
assert (ohlcv);
|
9
|
+
assert (Array.isArray (ohlcv), json);
|
10
|
+
const length = ohlcv.length;
|
11
|
+
assert (length >= 6);
|
12
|
+
for (let i = 0; i < ohlcv.length; i++) {
|
13
|
+
assert ((ohlcv[i] === undefined) || (typeof ohlcv[i] === 'number'), json);
|
14
|
+
}
|
15
|
+
|
16
|
+
assert (ohlcv[0] > 1230940800000, json); // 03 Jan 2009 - first block
|
17
|
+
assert (ohlcv[0] < 2147483648000, json); // 19 Jan 2038 - int32 overflows
|
18
|
+
|
19
|
+
const skippedExchanges = [
|
20
|
+
'bitmex', // BitMEX API docs: also note the open price is equal to the close price of the previous timeframe bucket.
|
21
|
+
'vcc', // same as BitMEX, the open price is equal to the close price of the previous timeframe bucket.
|
22
|
+
'delta',
|
23
|
+
'cryptocom',
|
24
|
+
];
|
25
|
+
|
26
|
+
if (!exchange.inArray (exchange.id, skippedExchanges)) {
|
27
|
+
assert ((ohlcv[1] === undefined) || (ohlcv[2] === undefined) || (ohlcv[1] <= ohlcv[2]), 'open > high, ' + exchange.safeString (ohlcv, 1, 'undefined') + ' > ' + exchange.safeString (ohlcv, 2, 'undefined')); // open <= high
|
28
|
+
assert ((ohlcv[3] === undefined) || (ohlcv[2] === undefined) || (ohlcv[3] <= ohlcv[2]), 'low > high, ' + exchange.safeString (ohlcv, 2, 'undefined') + ' > ' + exchange.safeString (ohlcv, 3, 'undefined')); // low <= high
|
29
|
+
assert ((ohlcv[3] === undefined) || (ohlcv[4] === undefined) || (ohlcv[3] <= ohlcv[4]), 'low > close, ' + exchange.safeString (ohlcv, 3, 'undefined') + ' > ' + exchange.safeString (ohlcv, 4, 'undefined')); // low <= close
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
module.exports = testOHLCV;
|
@@ -0,0 +1,62 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
const assert = require ('assert');
|
4
|
+
|
5
|
+
function testOrder (exchange, order, symbol, now) {
|
6
|
+
assert (order);
|
7
|
+
assert ('id' in order);
|
8
|
+
assert (typeof order['id'] === 'string');
|
9
|
+
assert ('clientOrderId' in order);
|
10
|
+
assert ((order['clientOrderId'] === undefined) || (typeof order['clientOrderId'] === 'string'));
|
11
|
+
assert ('timestamp' in order);
|
12
|
+
assert (typeof order['timestamp'] === 'number');
|
13
|
+
assert (order['timestamp'] > 1230940800000); // 03 Jan 2009 - first block
|
14
|
+
assert (order['timestamp'] < now);
|
15
|
+
assert ('lastTradeTimestamp' in order);
|
16
|
+
assert ('datetime' in order);
|
17
|
+
assert (order['datetime'] === exchange.iso8601 (order['timestamp']));
|
18
|
+
assert ('status' in order);
|
19
|
+
assert ((order['status'] === 'open') || (order['status'] === 'closed') || (order['status'] === 'canceled'));
|
20
|
+
assert ('symbol' in order);
|
21
|
+
assert (order['symbol'] === symbol);
|
22
|
+
assert ('type' in order);
|
23
|
+
assert ((order['type'] === undefined) || (typeof order['type'] === 'string'));
|
24
|
+
assert ('timeInForce' in order);
|
25
|
+
assert ((order['timeInForce'] === undefined) || (typeof order['timeInForce'] === 'string'));
|
26
|
+
assert ('side' in order);
|
27
|
+
assert ((order['side'] === 'buy') || (order['side'] === 'sell'));
|
28
|
+
assert ('price' in order);
|
29
|
+
assert ((order['price'] === undefined) || (typeof order['price'] === 'number'));
|
30
|
+
if (order['price'] !== undefined) {
|
31
|
+
assert (order['price'] > 0);
|
32
|
+
}
|
33
|
+
assert ('amount' in order);
|
34
|
+
assert (typeof order['amount'] === 'number');
|
35
|
+
assert (order['amount'] >= 0);
|
36
|
+
assert ('filled' in order);
|
37
|
+
if (order['filled'] !== undefined) {
|
38
|
+
assert (typeof order['filled'] === 'number');
|
39
|
+
assert ((order['filled'] >= 0) && (order['filled'] <= order['amount']));
|
40
|
+
}
|
41
|
+
assert ('remaining' in order);
|
42
|
+
if (order['remaining'] !== undefined) {
|
43
|
+
assert (typeof order['remaining'] === 'number');
|
44
|
+
assert ((order['remaining'] >= 0) && (order['remaining'] <= order['amount']));
|
45
|
+
}
|
46
|
+
assert ('trades' in order);
|
47
|
+
if (order['trades']) {
|
48
|
+
assert (Array.isArray (order['trades']));
|
49
|
+
}
|
50
|
+
assert ('fee' in order);
|
51
|
+
const fee = order['fee'];
|
52
|
+
if (fee) {
|
53
|
+
assert (typeof fee['cost'] === 'number');
|
54
|
+
if (fee['cost'] !== 0) {
|
55
|
+
assert (typeof fee['currency'] === 'string');
|
56
|
+
}
|
57
|
+
}
|
58
|
+
assert ('info' in order);
|
59
|
+
assert (order['info']);
|
60
|
+
}
|
61
|
+
|
62
|
+
module.exports = testOrder;
|
@@ -0,0 +1,61 @@
|
|
1
|
+
'use strict'
|
2
|
+
|
3
|
+
// ----------------------------------------------------------------------------
|
4
|
+
|
5
|
+
const assert = require ('assert')
|
6
|
+
|
7
|
+
// ----------------------------------------------------------------------------
|
8
|
+
|
9
|
+
module.exports = (exchange, orderbook, method, symbol) => {
|
10
|
+
|
11
|
+
const format = {
|
12
|
+
// 'symbol': 'ETH/BTC', // reserved
|
13
|
+
'bids': [],
|
14
|
+
'asks': [],
|
15
|
+
'timestamp': 1234567890,
|
16
|
+
'datetime': '2017-09-01T00:00:00',
|
17
|
+
'nonce': 134234234,
|
18
|
+
// 'info': {},
|
19
|
+
}
|
20
|
+
|
21
|
+
const keys = Object.keys (format)
|
22
|
+
for (let i = 0; i < keys.length; i++) {
|
23
|
+
assert (keys[i] in orderbook)
|
24
|
+
}
|
25
|
+
|
26
|
+
const bids = orderbook['bids']
|
27
|
+
const asks = orderbook['asks']
|
28
|
+
|
29
|
+
for (let i = 0; i < bids.length; i++) {
|
30
|
+
if (bids.length > (i + 1)) {
|
31
|
+
assert (bids[i][0] >= bids[i + 1][0])
|
32
|
+
}
|
33
|
+
assert (typeof bids[i][0] === 'number')
|
34
|
+
assert (typeof bids[i][1] === 'number')
|
35
|
+
}
|
36
|
+
|
37
|
+
for (let i = 0; i < asks.length; i++) {
|
38
|
+
if (asks.length > (i + 1)) {
|
39
|
+
assert (asks[i][0] <= asks[i + 1][0])
|
40
|
+
}
|
41
|
+
assert (typeof asks[i][0] === 'number')
|
42
|
+
assert (typeof asks[i][1] === 'number')
|
43
|
+
}
|
44
|
+
|
45
|
+
if (![
|
46
|
+
|
47
|
+
'bitrue',
|
48
|
+
'ftxus',
|
49
|
+
'mexc',
|
50
|
+
'xbtce',
|
51
|
+
'upbit', // an orderbook might have a 0-price ask occasionally
|
52
|
+
|
53
|
+
].includes (exchange.id)) {
|
54
|
+
|
55
|
+
if (bids.length && asks.length) {
|
56
|
+
assert (bids[0][0] <= asks[0][0], 'bids[0][0]:', bids[0][0], 'of', bids.length, 'asks[0][0]:', asks[0][0], 'of', asks.length)
|
57
|
+
}
|
58
|
+
}
|
59
|
+
|
60
|
+
console.log (symbol, method, orderbook['nonce'] || orderbook['datetime'], bids.length, 'bids:', bids[0], asks.length, 'asks:', asks[0])
|
61
|
+
}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
const assert = require ('assert');
|
4
|
+
|
5
|
+
function testPosition (exchange, position, symbol, now) {
|
6
|
+
assert (position);
|
7
|
+
assert ('id' in position);
|
8
|
+
assert (position['id'] === undefined || typeof position['id'] === 'string');
|
9
|
+
assert ('timestamp' in position);
|
10
|
+
assert (position['timestamp'] === undefined || typeof position['timestamp'] === 'number');
|
11
|
+
assert (position['timestamp'] === undefined || position['timestamp'] > 1230940800000); // 03 Jan 2009 - first cryptocurrency block creation time
|
12
|
+
assert (position['timestamp'] === undefined || position['timestamp'] < now);
|
13
|
+
assert ('datetime' in position);
|
14
|
+
assert (position['datetime'] === exchange.iso8601 (position['timestamp']));
|
15
|
+
assert ('symbol' in position);
|
16
|
+
assert (symbol === undefined || position['symbol'] === symbol);
|
17
|
+
assert ('info' in position);
|
18
|
+
assert (position['info']);
|
19
|
+
}
|
20
|
+
|
21
|
+
module.exports = testPosition;
|
@@ -0,0 +1,94 @@
|
|
1
|
+
const { throttle } = require ('../../base/functions/throttle')
|
2
|
+
|
3
|
+
const delta = 10
|
4
|
+
const testCases = [
|
5
|
+
{
|
6
|
+
'tokens': 0,
|
7
|
+
'refillRate': 1 / 50,
|
8
|
+
'cost': 1,
|
9
|
+
'runs': 100,
|
10
|
+
},
|
11
|
+
{
|
12
|
+
'tokens': 20,
|
13
|
+
'refillRate': 1 / 50,
|
14
|
+
'cost': 1,
|
15
|
+
'runs': 100,
|
16
|
+
},
|
17
|
+
{
|
18
|
+
'tokens': 40,
|
19
|
+
'refillRate': 1 / 50,
|
20
|
+
'cost': 1,
|
21
|
+
'runs': 100,
|
22
|
+
},
|
23
|
+
{
|
24
|
+
'tokens': 0,
|
25
|
+
'refillRate': 1 / 20,
|
26
|
+
'cost': 1,
|
27
|
+
'runs': 100,
|
28
|
+
},
|
29
|
+
{
|
30
|
+
'tokens': 100,
|
31
|
+
'refillRate': 1 / 20,
|
32
|
+
'cost': 5,
|
33
|
+
'runs': 50,
|
34
|
+
},
|
35
|
+
{
|
36
|
+
'tokens': 0,
|
37
|
+
'refillRate': 1 / 40,
|
38
|
+
'cost': 2,
|
39
|
+
'runs': 50,
|
40
|
+
},
|
41
|
+
{
|
42
|
+
'tokens': 1,
|
43
|
+
'refillRate': 1 / 100,
|
44
|
+
'cost': 1,
|
45
|
+
'runs': 10,
|
46
|
+
},
|
47
|
+
{
|
48
|
+
'tokens': 5,
|
49
|
+
'refillRate': 1 / 100,
|
50
|
+
'cost': 1,
|
51
|
+
'runs': 10,
|
52
|
+
},
|
53
|
+
{
|
54
|
+
'tokens': 0,
|
55
|
+
'refillRate': 1 / 500,
|
56
|
+
'cost': 1,
|
57
|
+
'runs': 10,
|
58
|
+
},
|
59
|
+
{
|
60
|
+
'tokens': 0,
|
61
|
+
'refillRate': 1 / 10,
|
62
|
+
'cost': 1,
|
63
|
+
'runs': 500,
|
64
|
+
},
|
65
|
+
]
|
66
|
+
|
67
|
+
|
68
|
+
let number = 0
|
69
|
+
for (const test of testCases) {
|
70
|
+
test['number'] = number++
|
71
|
+
const instantlyComplete = test['tokens'] / test['cost']
|
72
|
+
// after that each run will take cost and the total time will be runs * cost / refillRate
|
73
|
+
const remaining = test['runs'] - instantlyComplete - 1
|
74
|
+
test['expected'] = remaining * test['cost'] / test['refillRate']
|
75
|
+
}
|
76
|
+
|
77
|
+
async function runner (test) {
|
78
|
+
const throttler = throttle ({
|
79
|
+
'refillRate': test['refillRate'],
|
80
|
+
'tokens': test['tokens'],
|
81
|
+
})
|
82
|
+
const start = performance.now ()
|
83
|
+
for (let i = 0; i < test['runs']; i++) {
|
84
|
+
await throttler (test['cost'])
|
85
|
+
}
|
86
|
+
const end = performance.now ()
|
87
|
+
const elapsed = end - start
|
88
|
+
const result = Math.abs (elapsed - test['expected']) < delta
|
89
|
+
console.log (`case ${test['number']} ${result ? 'suceeded' : 'failed'} in ${elapsed}ms expected ${test['expected']}ms`)
|
90
|
+
}
|
91
|
+
|
92
|
+
for (const test of testCases) {
|
93
|
+
runner (test)
|
94
|
+
}
|
@@ -0,0 +1,95 @@
|
|
1
|
+
'use strict'
|
2
|
+
|
3
|
+
// ----------------------------------------------------------------------------
|
4
|
+
|
5
|
+
const assert = require ('assert')
|
6
|
+
|
7
|
+
// ----------------------------------------------------------------------------
|
8
|
+
|
9
|
+
module.exports = (exchange, ticker, method, symbol) => {
|
10
|
+
|
11
|
+
const format = {
|
12
|
+
'symbol': 'ETH/BTC',
|
13
|
+
'info': {},
|
14
|
+
'timestamp': 1234567890,
|
15
|
+
'datetime': '2017-09-01T00:00:00',
|
16
|
+
'high': 1.234, // highest price
|
17
|
+
'low': 1.234, // lowest price
|
18
|
+
'bid': 1.234, // current best bid (buy) price
|
19
|
+
'bidVolume': 1.234, // current best bid (buy) amount (may be missing or undefined)
|
20
|
+
'ask': 1.234, // current best ask (sell) price
|
21
|
+
'askVolume': 1.234, // current best ask (sell) amount (may be missing or undefined)
|
22
|
+
'vwap': 1.234, // volume weighed average price
|
23
|
+
'open': 1.234, // opening price
|
24
|
+
'close': 1.234, // price of last trade (closing price for current period)
|
25
|
+
'last': 1.234, // same as `close`, duplicated for convenience
|
26
|
+
'previousClose': 1.234, // closing price for the previous period
|
27
|
+
'change': 1.234, // absolute change, `last - open`
|
28
|
+
'percentage': 1.234, // relative change, `(change/open) * 100`
|
29
|
+
'average': 1.234, // average price, `(last + open) / 2`
|
30
|
+
'baseVolume': 1.234, // volume of base currency
|
31
|
+
'quoteVolume': 1.234, // volume of quote currency
|
32
|
+
}
|
33
|
+
|
34
|
+
const keys = Object.keys (format)
|
35
|
+
for (let i = 0; i < keys.length; i++) {
|
36
|
+
const key = keys[i]
|
37
|
+
assert (key in ticker)
|
38
|
+
}
|
39
|
+
|
40
|
+
assert (!('first' in ticker), '`first` field leftover in ' + exchange.id)
|
41
|
+
assert (ticker['last'] === ticker['close'], '`last` != `close` in ' + exchange.id)
|
42
|
+
|
43
|
+
if (method !== undefined) {
|
44
|
+
console.log (ticker['datetime'], exchange.id, method, ticker['symbol'], ticker['last'])
|
45
|
+
}
|
46
|
+
|
47
|
+
// const { high, low, vwap, baseVolume, quoteVolume } = ticker
|
48
|
+
// this assert breaks QuadrigaCX sometimes... still investigating
|
49
|
+
// if (vwap) {
|
50
|
+
// assert (vwap >= low && vwap <= high)
|
51
|
+
// }
|
52
|
+
// if (baseVolume && quoteVolume && high && low) {
|
53
|
+
// assert (quoteVolume >= baseVolume * low) // this assertion breaks therock
|
54
|
+
// assert (quoteVolume <= baseVolume * high)
|
55
|
+
// }
|
56
|
+
// if (baseVolume && vwap) {
|
57
|
+
// assert (quoteVolume)
|
58
|
+
// }
|
59
|
+
// if (quoteVolume && vwap) {
|
60
|
+
// assert (baseVolume)
|
61
|
+
// }
|
62
|
+
|
63
|
+
if (![
|
64
|
+
|
65
|
+
'bigone',
|
66
|
+
'bitmart',
|
67
|
+
'bitrue',
|
68
|
+
'btcturk',
|
69
|
+
'bybit',
|
70
|
+
'coss',
|
71
|
+
'ftx',
|
72
|
+
'ftxus',
|
73
|
+
'gateio', // some ticker bids are greaters than asks
|
74
|
+
'idex',
|
75
|
+
'mercado',
|
76
|
+
'mexc',
|
77
|
+
'okex',
|
78
|
+
'poloniex',
|
79
|
+
'qtrade',
|
80
|
+
'southxchange', // https://user-images.githubusercontent.com/1294454/59953532-314bea80-9489-11e9-85b3-2a711ca49aa7.png
|
81
|
+
'timex',
|
82
|
+
'xbtce',
|
83
|
+
|
84
|
+
].includes (exchange.id)) {
|
85
|
+
|
86
|
+
if (ticker['baseVolume'] || ticker['quoteVolume']) {
|
87
|
+
if (ticker['bid'] && ticker['ask']) {
|
88
|
+
assert (ticker['bid'] <= ticker['ask'], (ticker['symbol'] ? (ticker['symbol'] + ' ') : '') + 'ticker bid is greater than ticker ask!')
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
92
|
+
}
|
93
|
+
|
94
|
+
return ticker
|
95
|
+
}
|
@@ -0,0 +1,68 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
const assert = require ('assert');
|
4
|
+
|
5
|
+
function testTrade (exchange, trade, symbol, now) {
|
6
|
+
assert (trade);
|
7
|
+
const sampleTrade = {
|
8
|
+
'info': { 'a': 1, 'b': 2, 'c': 3 }, // the original decoded JSON as is
|
9
|
+
'id': '12345-67890:09876/54321', // string trade id
|
10
|
+
'timestamp': 1502962946216, // Unix timestamp in milliseconds
|
11
|
+
'datetime': '2017-08-17 12:42:48.000', // ISO8601 datetime with milliseconds
|
12
|
+
'symbol': 'ETH/BTC', // symbol
|
13
|
+
'order': '12345-67890:09876/54321', // string order id or undefined/None/null
|
14
|
+
'type': 'limit', // order type, 'market', 'limit' or undefined/None/null
|
15
|
+
'side': 'buy', // direction of the trade, 'buy' or 'sell'
|
16
|
+
'takerOrMaker': 'taker', // string, 'taker' or 'maker'
|
17
|
+
'price': 0.06917684, // float price in quote currency
|
18
|
+
'amount': 1.5, // amount of base currency
|
19
|
+
'cost': 0.10376526, // total cost (including fees), `price * amount`
|
20
|
+
};
|
21
|
+
const keys = Object.keys (sampleTrade);
|
22
|
+
for (let i = 0; i < keys.length; i++) {
|
23
|
+
const key = keys[i];
|
24
|
+
assert (key in trade);
|
25
|
+
}
|
26
|
+
const fee = ('fee' in trade) ? trade['fee'] : undefined;
|
27
|
+
const fees = ('fees' in trade) ? trade['fees'] : undefined;
|
28
|
+
// logical XOR
|
29
|
+
// doesn't work when both fee is defined and fees is defined
|
30
|
+
// if (fee || fees) {
|
31
|
+
// assert (!(fee && fees));
|
32
|
+
// }
|
33
|
+
if (fee) {
|
34
|
+
assert (('cost' in fee) && ('currency' in fee));
|
35
|
+
}
|
36
|
+
if (fees) {
|
37
|
+
assert (Array.isArray (fees));
|
38
|
+
for (let i = 0; i < fees.length; i++) {
|
39
|
+
const fee = fees[i];
|
40
|
+
assert (('cost' in fee) && ('currency' in fee));
|
41
|
+
}
|
42
|
+
}
|
43
|
+
const id = trade['id'];
|
44
|
+
assert ((id === undefined) || (typeof id === 'string'));
|
45
|
+
const timestamp = trade['timestamp'];
|
46
|
+
assert (typeof timestamp === 'number' || timestamp === undefined);
|
47
|
+
if (timestamp) {
|
48
|
+
assert (timestamp > 1230940800000); // 03 Jan 2009 - first block
|
49
|
+
assert (timestamp < 2147483648000); // 19 Jan 2038 - int32 overflows
|
50
|
+
const adjustedNow = now + 60000;
|
51
|
+
assert (timestamp < adjustedNow, 'trade.timestamp is greater than or equal to current time: trade: ' + exchange.iso8601 (timestamp) + ' now: ' + exchange.iso8601 (now));
|
52
|
+
}
|
53
|
+
assert (trade['datetime'] === exchange.iso8601 (timestamp));
|
54
|
+
assert (trade['symbol'] === symbol, 'trade symbol is not equal to requested symbol: trade: ' + trade['symbol'] + ' requested: ' + symbol);
|
55
|
+
assert (trade['type'] === undefined || typeof trade['type'] === 'string');
|
56
|
+
assert (trade['side'] === undefined || trade['side'] === 'buy' || trade['side'] === 'sell', 'unexpected trade side ' + trade['side']);
|
57
|
+
assert (trade['order'] === undefined || typeof trade['order'] === 'string');
|
58
|
+
assert (typeof trade['price'] === 'number', 'trade.price is not a number');
|
59
|
+
assert (trade['price'] > 0);
|
60
|
+
assert (typeof trade['amount'] === 'number', 'trade.amount is not a number');
|
61
|
+
assert (trade['amount'] >= 0);
|
62
|
+
assert (trade['cost'] === undefined || typeof trade['cost'] === 'number', 'trade.cost is not a number');
|
63
|
+
assert (trade['cost'] === undefined || trade['cost'] >= 0);
|
64
|
+
const takerOrMaker = trade['takerOrMaker'];
|
65
|
+
assert (takerOrMaker === undefined || takerOrMaker === 'taker' || takerOrMaker === 'maker');
|
66
|
+
}
|
67
|
+
|
68
|
+
module.exports = testTrade;
|
@@ -0,0 +1,34 @@
|
|
1
|
+
'use strict'
|
2
|
+
|
3
|
+
// ----------------------------------------------------------------------------
|
4
|
+
|
5
|
+
const assert = require ('assert')
|
6
|
+
|
7
|
+
// ---------------------------------------------------------------------------
|
8
|
+
|
9
|
+
function testTradingFee (exchange = undefined, symbol, fee) {
|
10
|
+
assert (fee, 'fee is undefined')
|
11
|
+
const sampleFee = {
|
12
|
+
'info': { 'a': 1, 'b': 2, 'c': 3 },
|
13
|
+
'symbol': 'ETH/BTC',
|
14
|
+
'maker': 0.002,
|
15
|
+
'taker': 0.003,
|
16
|
+
}
|
17
|
+
const keys = Object.keys (sampleFee)
|
18
|
+
for (let i = 0; i < keys.length; i++) {
|
19
|
+
const key = keys[i]
|
20
|
+
assert (key in fee, 'fee key ' + key + ' not found')
|
21
|
+
}
|
22
|
+
assert (fee['symbol'] === symbol, 'trade symbol is not equal to requested symbol: trade: ' + fee['symbol'] + ' requested: ' + symbol)
|
23
|
+
assert (typeof fee['maker'] === 'number', 'maker fee is not a number')
|
24
|
+
assert (typeof fee['taker'] === 'number', 'taker fee is not a number')
|
25
|
+
if ('percentage' in fee) {
|
26
|
+
assert (typeof fee['percentage'] === 'boolean', 'percentage is not a boolean')
|
27
|
+
}
|
28
|
+
if ('tierBased' in fee) {
|
29
|
+
assert (typeof fee['tierBased'] === 'boolean', 'percentage is not a boolean')
|
30
|
+
}
|
31
|
+
return fee
|
32
|
+
}
|
33
|
+
|
34
|
+
module.exports = testTradingFee
|
@@ -0,0 +1,35 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
// ----------------------------------------------------------------------------
|
4
|
+
|
5
|
+
const assert = require ('assert');
|
6
|
+
|
7
|
+
// ---------------------------------------------------------------------------
|
8
|
+
|
9
|
+
function testTransaction (exchange, transaction, code, now) {
|
10
|
+
assert (transaction);
|
11
|
+
assert ((transaction['id'] === undefined) || (typeof transaction['id'] === 'string'));
|
12
|
+
assert (typeof transaction['timestamp'] === 'number');
|
13
|
+
assert (transaction['timestamp'] > 1230940800000); // 03 Jan 2009 - first block
|
14
|
+
assert (transaction['timestamp'] < now);
|
15
|
+
assert ('updated' in transaction);
|
16
|
+
assert ('address' in transaction);
|
17
|
+
assert ('tag' in transaction);
|
18
|
+
assert ('txid' in transaction);
|
19
|
+
assert (transaction['datetime'] === exchange.iso8601 (transaction['timestamp']));
|
20
|
+
assert ((transaction['status'] === 'ok') || (transaction['status'] === 'pending') || (transaction['status'] === 'canceled'));
|
21
|
+
assert (transaction['currency'] === code);
|
22
|
+
assert (typeof transaction['type'] === 'string');
|
23
|
+
assert (transaction['type'] === 'deposit' || transaction['type'] === 'withdrawal');
|
24
|
+
assert (typeof transaction['amount'] === 'number');
|
25
|
+
assert (transaction['amount'] >= 0);
|
26
|
+
if (transaction['fee']) {
|
27
|
+
assert (typeof transaction['fee']['cost'] === 'number');
|
28
|
+
if (transaction['fee']['cost'] !== 0) {
|
29
|
+
assert (typeof transaction['fee']['currency'] === 'string');
|
30
|
+
}
|
31
|
+
}
|
32
|
+
assert (transaction.info);
|
33
|
+
}
|
34
|
+
|
35
|
+
module.exports = testTransaction;
|