ccxt 4.4.88 → 4.4.90
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/README.md +61 -19
- package/dist/ccxt.browser.min.js +3 -3
- package/dist/cjs/ccxt.js +1 -1
- package/dist/cjs/src/base/Exchange.js +6 -3
- package/dist/cjs/src/base/functions/encode.js +1 -1
- package/dist/cjs/src/base/functions/generic.js +6 -0
- package/dist/cjs/src/base/functions.js +1 -0
- package/dist/cjs/src/binance.js +1 -1
- package/dist/cjs/src/bingx.js +60 -32
- package/dist/cjs/src/bitget.js +493 -154
- package/dist/cjs/src/bitrue.js +72 -66
- package/dist/cjs/src/bitvavo.js +34 -0
- package/dist/cjs/src/btcalpha.js +35 -0
- package/dist/cjs/src/btcbox.js +35 -0
- package/dist/cjs/src/btcmarkets.js +35 -0
- package/dist/cjs/src/btcturk.js +35 -0
- package/dist/cjs/src/bybit.js +9 -3
- package/dist/cjs/src/coinbase.js +1 -4
- package/dist/cjs/src/cryptocom.js +54 -0
- package/dist/cjs/src/delta.js +2 -2
- package/dist/cjs/src/digifinex.js +40 -109
- package/dist/cjs/src/gate.js +12 -5
- package/dist/cjs/src/hashkey.js +15 -28
- package/dist/cjs/src/hollaex.js +28 -24
- package/dist/cjs/src/kraken.js +30 -53
- package/dist/cjs/src/luno.js +92 -0
- package/dist/cjs/src/okx.js +2 -1
- package/dist/cjs/src/phemex.js +16 -8
- package/dist/cjs/src/pro/coinbase.js +2 -0
- package/dist/cjs/src/pro/cryptocom.js +27 -0
- package/dist/cjs/src/pro/kraken.js +3 -11
- package/dist/cjs/src/tradeogre.js +3 -3
- package/dist/cjs/src/xt.js +1 -1
- package/js/ccxt.d.ts +1 -1
- package/js/ccxt.js +1 -1
- package/js/src/abstract/bitget.d.ts +58 -0
- package/js/src/abstract/cryptocom.d.ts +2 -0
- package/js/src/abstract/luno.d.ts +1 -0
- package/js/src/base/Exchange.d.ts +4 -1
- package/js/src/base/Exchange.js +6 -3
- package/js/src/base/functions/encode.d.ts +1 -1
- package/js/src/base/functions/encode.js +1 -1
- package/js/src/base/functions/generic.d.ts +2 -1
- package/js/src/base/functions/generic.js +6 -1
- package/js/src/binance.js +1 -1
- package/js/src/bingx.d.ts +9 -5
- package/js/src/bingx.js +60 -32
- package/js/src/bitget.d.ts +4 -1
- package/js/src/bitget.js +493 -154
- package/js/src/bitrue.js +72 -66
- package/js/src/bitvavo.js +34 -0
- package/js/src/btcalpha.js +35 -0
- package/js/src/btcbox.js +35 -0
- package/js/src/btcmarkets.js +35 -0
- package/js/src/btcturk.js +35 -0
- package/js/src/bybit.js +9 -3
- package/js/src/coinbase.d.ts +1 -1
- package/js/src/coinbase.js +1 -4
- package/js/src/cryptocom.d.ts +17 -0
- package/js/src/cryptocom.js +54 -0
- package/js/src/delta.js +2 -2
- package/js/src/digifinex.js +40 -109
- package/js/src/gate.d.ts +1 -1
- package/js/src/gate.js +12 -5
- package/js/src/hashkey.d.ts +0 -1
- package/js/src/hashkey.js +15 -28
- package/js/src/hollaex.d.ts +1 -2
- package/js/src/hollaex.js +29 -25
- package/js/src/kraken.d.ts +0 -1
- package/js/src/kraken.js +30 -53
- package/js/src/luno.d.ts +9 -1
- package/js/src/luno.js +92 -0
- package/js/src/okx.js +2 -1
- package/js/src/phemex.d.ts +1 -0
- package/js/src/phemex.js +16 -8
- package/js/src/pro/coinbase.js +2 -0
- package/js/src/pro/cryptocom.d.ts +16 -0
- package/js/src/pro/cryptocom.js +27 -0
- package/js/src/pro/kraken.js +3 -11
- package/js/src/tradeogre.js +3 -3
- package/js/src/xt.js +1 -1
- package/package.json +4 -7
- package/examples/README.md +0 -316
- package/examples/js/README.md +0 -15
- package/examples/js/cli.js +0 -559
package/examples/js/cli.js
DELETED
|
@@ -1,559 +0,0 @@
|
|
|
1
|
-
#! /usr/bin/env node
|
|
2
|
-
import fs from 'fs'
|
|
3
|
-
import path from 'path'
|
|
4
|
-
import ansi from 'ansicolor'
|
|
5
|
-
import asTable from 'as-table'
|
|
6
|
-
import ololog from 'ololog'
|
|
7
|
-
import ccxt from '../../js/ccxt.js'
|
|
8
|
-
import { Agent } from 'https'
|
|
9
|
-
import { add_static_result } from '../../utils/update-static-tests-data.js'
|
|
10
|
-
const fsPromises = fs.promises;
|
|
11
|
-
ansi.nice
|
|
12
|
-
const log = ololog.configure ({ locate: false }).unlimited
|
|
13
|
-
const { ExchangeError , NetworkError} = ccxt
|
|
14
|
-
|
|
15
|
-
function jsonStringify (obj, indent = undefined) {
|
|
16
|
-
return JSON.stringify (obj, function(k, v) { return v === undefined ? null : v; }, indent);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
function countAllParams(fn) {
|
|
21
|
-
const fnStr = fn.toString()
|
|
22
|
-
.replace(/\/\/.*$/mg, '')
|
|
23
|
-
.replace(/\/\*[\s\S]*?\*\//mg, '')
|
|
24
|
-
.replace(/\s+/g, '');
|
|
25
|
-
|
|
26
|
-
const match = fnStr.match(/^[^(]*\(([^)]*)\)/);
|
|
27
|
-
if (!match) return 0;
|
|
28
|
-
|
|
29
|
-
const params = match[1].split(',').filter(p => p);
|
|
30
|
-
return params.length;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
//-----------------------------------------------------------------------------
|
|
34
|
-
|
|
35
|
-
let [processPath, , exchangeId, methodName, ... params] = process.argv.filter (x => !x.startsWith ('--'))
|
|
36
|
-
, verbose = process.argv.includes ('--verbose')
|
|
37
|
-
, debug = process.argv.includes ('--debug')
|
|
38
|
-
, poll = process.argv.includes ('--poll')
|
|
39
|
-
, no_send = process.argv.includes ('--no-send')
|
|
40
|
-
, no_load_markets = process.argv.includes ('--no-load-markets')
|
|
41
|
-
, details = process.argv.includes ('--details')
|
|
42
|
-
, no_table = process.argv.includes ('--no-table')
|
|
43
|
-
, table = process.argv.includes ('--table')
|
|
44
|
-
, iso8601 = process.argv.includes ('--iso8601')
|
|
45
|
-
, cors = process.argv.includes ('--cors')
|
|
46
|
-
, cache_markets = process.argv.includes ('--cache-markets')
|
|
47
|
-
, testnet =
|
|
48
|
-
process.argv.includes ('--test') ||
|
|
49
|
-
process.argv.includes ('--testnet') ||
|
|
50
|
-
process.argv.includes ('--sandbox')
|
|
51
|
-
, signIn = process.argv.includes ('--sign-in') || process.argv.includes ('--signIn')
|
|
52
|
-
, isSpot = process.argv.includes ('--spot')
|
|
53
|
-
, isSwap = process.argv.includes ('--swap')
|
|
54
|
-
, isFuture = process.argv.includes ('--future')
|
|
55
|
-
, isOption = process.argv.includes ('--option')
|
|
56
|
-
, shouldCreateRequestReport = process.argv.includes ('--report') || process.argv.includes ('--request')
|
|
57
|
-
, shouldCreateResponseReport = process.argv.includes ('--response')
|
|
58
|
-
, shouldCreateBoth = process.argv.includes ('--static')
|
|
59
|
-
, raw = process.argv.includes ('--raw')
|
|
60
|
-
, noKeys = process.argv.includes ('--no-keys')
|
|
61
|
-
|
|
62
|
-
let foundDescription = undefined;
|
|
63
|
-
const nameIndex = process.argv.indexOf ('--name')
|
|
64
|
-
if (nameIndex >= 0) {
|
|
65
|
-
foundDescription = process.argv[nameIndex + 1];
|
|
66
|
-
// search that string in `params` and remove it
|
|
67
|
-
const index = params.indexOf (foundDescription)
|
|
68
|
-
if (index >= 0) {
|
|
69
|
-
params.splice (index, 1);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
let lastParamObject
|
|
74
|
-
let symbol
|
|
75
|
-
for (let i = 0; i < process.argv.length; i++) {
|
|
76
|
-
if (process.argv[i] === '--param') {
|
|
77
|
-
const nextParam = process.argv[i + 1]
|
|
78
|
-
if (nextParam) {
|
|
79
|
-
const paramIndex = params.indexOf (nextParam)
|
|
80
|
-
if (paramIndex >= 0) {
|
|
81
|
-
if (nextParam.indexOf('=') >= 0) {
|
|
82
|
-
const parsed = nextParam.split('=')
|
|
83
|
-
if (parsed.length === 2) {
|
|
84
|
-
if (!lastParamObject) {
|
|
85
|
-
lastParamObject = {}
|
|
86
|
-
}
|
|
87
|
-
const key = parsed[0];
|
|
88
|
-
const value = parsed[1];
|
|
89
|
-
if (key === 'symbol') {
|
|
90
|
-
symbol = value
|
|
91
|
-
}
|
|
92
|
-
lastParamObject[key] = value
|
|
93
|
-
params.splice(paramIndex, 1)
|
|
94
|
-
} else {
|
|
95
|
-
throw new Error ('Invalid usage of --param. Please provide a key=value pair after --param.')
|
|
96
|
-
}
|
|
97
|
-
} else {
|
|
98
|
-
if (!lastParamObject) {
|
|
99
|
-
lastParamObject = {}
|
|
100
|
-
}
|
|
101
|
-
lastParamObject[nextParam] = true
|
|
102
|
-
}
|
|
103
|
-
} else {
|
|
104
|
-
throw new Error (`Unexpected error by parsing parameters: ${nextParam} is not found in params array.`)
|
|
105
|
-
}
|
|
106
|
-
} else {
|
|
107
|
-
throw new Error ('Invalid usage of --param. Please provide a value after --param.')
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
let lastParam = params[params.length - 1]
|
|
113
|
-
// exclude parasitic single quotes. Can happen on some shell processors
|
|
114
|
-
if (lastParam?.includes('{') && lastParam?.includes('}')) {
|
|
115
|
-
if (lastParam.startsWith('\'{') && lastParam.endsWith('}\'')) {
|
|
116
|
-
lastParam = params[params.length - 1] = lastParam.substring(1, lastParam.length - 1)
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
//-----------------------------------------------------------------------------
|
|
121
|
-
if (!raw) {
|
|
122
|
-
log ((new Date ()).toISOString())
|
|
123
|
-
log ('Node.js:', process.version)
|
|
124
|
-
log ('CCXT v' + ccxt.version)
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
//-----------------------------------------------------------------------------
|
|
128
|
-
|
|
129
|
-
process.on ('uncaughtException', e => { log.bright.red.error (e); log.red.error (e.message); process.exit (1) })
|
|
130
|
-
process.on ('unhandledRejection', e => { log.bright.red.error (e); log.red.error (e.message); process.exit (1) })
|
|
131
|
-
|
|
132
|
-
//-----------------------------------------------------------------------------
|
|
133
|
-
|
|
134
|
-
// set up keys and settings, if any
|
|
135
|
-
const keysGlobal = path.resolve ('keys.json')
|
|
136
|
-
const keysLocal = path.resolve ('keys.local.json')
|
|
137
|
-
|
|
138
|
-
const keysFile = fs.existsSync (keysLocal) ? keysLocal : keysGlobal
|
|
139
|
-
const settingsFile = fs.readFileSync(keysFile);
|
|
140
|
-
// eslint-disable-next-line import/no-dynamic-require, no-path-concat
|
|
141
|
-
let settings = JSON.parse(settingsFile)
|
|
142
|
-
settings = settings[exchangeId] || {}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
//-----------------------------------------------------------------------------
|
|
146
|
-
|
|
147
|
-
const timeout = 30000
|
|
148
|
-
let exchange = undefined
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
const httpsAgent = new Agent ({
|
|
153
|
-
ecdhCurve: 'auto',
|
|
154
|
-
keepAlive: true,
|
|
155
|
-
})
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
// check here if we have a arg like this: binance.fetchOrders()
|
|
159
|
-
const callRegex = /\s*(\w+)\s*\.\s*(\w+)\s*\(([^()]*)\)/
|
|
160
|
-
if (callRegex.test (exchangeId)) {
|
|
161
|
-
const res = callRegex.exec (exchangeId);
|
|
162
|
-
exchangeId = res[1];
|
|
163
|
-
methodName = res[2];
|
|
164
|
-
params = res[3].split(",").map(x => x.trim());
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
try {
|
|
168
|
-
if (ccxt.pro.exchanges.includes(exchangeId)) {
|
|
169
|
-
exchange = new (ccxt.pro)[exchangeId] ({ timeout, httpsAgent, ... settings })
|
|
170
|
-
} else {
|
|
171
|
-
exchange = new (ccxt)[exchangeId] ({ timeout, httpsAgent, ... settings })
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
if (exchange === undefined) {
|
|
175
|
-
process.exit ()
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
if (isSpot) {
|
|
179
|
-
exchange.options['defaultType'] = 'spot';
|
|
180
|
-
} else if (isSwap) {
|
|
181
|
-
exchange.options['defaultType'] = 'swap';
|
|
182
|
-
} else if (isFuture) {
|
|
183
|
-
exchange.options['defaultType'] = 'future';
|
|
184
|
-
} else if (isOption) {
|
|
185
|
-
exchange.options['defaultType'] = 'option';
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
if (!noKeys) {
|
|
189
|
-
// check auth keys in env var
|
|
190
|
-
const requiredCredentials = exchange.requiredCredentials;
|
|
191
|
-
for (const [credential, isRequired] of Object.entries (requiredCredentials)) {
|
|
192
|
-
if (isRequired && exchange[credential] === undefined) {
|
|
193
|
-
const credentialEnvName = (exchangeId + '_' + credential).toUpperCase () // example: KRAKEN_APIKEY
|
|
194
|
-
let credentialValue = process.env[credentialEnvName]
|
|
195
|
-
if (credentialValue) {
|
|
196
|
-
if (credentialValue.indexOf('---BEGIN') > -1) {
|
|
197
|
-
credentialValue = credentialValue.replaceAll('\\n', '\n');
|
|
198
|
-
}
|
|
199
|
-
exchange[credential] = credentialValue
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
if (testnet) {
|
|
206
|
-
exchange.setSandboxMode (true)
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
} catch (e) {
|
|
210
|
-
|
|
211
|
-
log.red (e)
|
|
212
|
-
printUsage ()
|
|
213
|
-
process.exit ()
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
//-----------------------------------------------------------------------------
|
|
217
|
-
|
|
218
|
-
function createRequestTemplate(exchange, methodName, args, result) {
|
|
219
|
-
const final = {
|
|
220
|
-
'description': 'Fill this with a description of the method call',
|
|
221
|
-
'method': methodName,
|
|
222
|
-
'url': exchange.last_request_url ?? '',
|
|
223
|
-
'input': args,
|
|
224
|
-
'output': exchange.last_request_body ?? undefined
|
|
225
|
-
}
|
|
226
|
-
log('Report: (paste inside static/request/' + exchange.id + '.json ->' + methodName + ')')
|
|
227
|
-
log.green('-------------------------------------------')
|
|
228
|
-
log (JSON.stringify (final, null, 2))
|
|
229
|
-
log.green('-------------------------------------------')
|
|
230
|
-
|
|
231
|
-
if (foundDescription !== undefined) {
|
|
232
|
-
final.description = foundDescription;
|
|
233
|
-
log.green('auto-saving static result');
|
|
234
|
-
add_static_result('request', exchange.id, methodName, final);
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
//-----------------------------------------------------------------------------
|
|
239
|
-
|
|
240
|
-
function createResponseTemplate(exchange, methodName, args, result) {
|
|
241
|
-
const final = {
|
|
242
|
-
'description': 'Fill this with a description of the method call',
|
|
243
|
-
'method': methodName,
|
|
244
|
-
'input': args,
|
|
245
|
-
'httpResponse': exchange.last_json_response ?? exchange.last_http_response,
|
|
246
|
-
'parsedResponse': result
|
|
247
|
-
}
|
|
248
|
-
log('Report: (paste inside static/response/' + exchange.id + '.json ->' + methodName + ')')
|
|
249
|
-
log.green('-------------------------------------------')
|
|
250
|
-
log (jsonStringify (final, 2))
|
|
251
|
-
log.green('-------------------------------------------')
|
|
252
|
-
|
|
253
|
-
if (foundDescription !== undefined) {
|
|
254
|
-
final.description = foundDescription;
|
|
255
|
-
log.green('auto-saving static result');
|
|
256
|
-
add_static_result('response', exchange.id, methodName, final);
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
//-----------------------------------------------------------------------------
|
|
261
|
-
|
|
262
|
-
function printSupportedExchanges () {
|
|
263
|
-
log ('Supported exchanges:', ccxt.exchanges.join (', ').green)
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
//-----------------------------------------------------------------------------
|
|
267
|
-
|
|
268
|
-
function printUsage () {
|
|
269
|
-
log ('This is an example of a basic command-line interface to all exchanges')
|
|
270
|
-
log ('Usage: node', process.argv[1], 'id'.green, 'method'.yellow, '"param1" param2 "param3" param4 ...'.blue)
|
|
271
|
-
log ('Examples:')
|
|
272
|
-
log ('node', process.argv[1], 'okcoin fetchOHLCV BTC/USD 15m')
|
|
273
|
-
log ('node', process.argv[1], 'bitfinex fetchBalance')
|
|
274
|
-
log ('node', process.argv[1], 'kraken fetchOrderBook ETH/BTC')
|
|
275
|
-
log ('node', process.argv[1], 'binanceusdm fetchTrades BTC/USDC undefined undefined --param until=1746988377067')
|
|
276
|
-
printSupportedExchanges ()
|
|
277
|
-
log ('Supported options:')
|
|
278
|
-
log ('--verbose Print verbose output')
|
|
279
|
-
log ('--debug Print debugging output')
|
|
280
|
-
log ('--poll Repeat continuously in rate-limited mode')
|
|
281
|
-
log ('--no-send Print the request but do not actually send it to the exchange (sets verbose and load-markets)')
|
|
282
|
-
log ('--no-load-markets Do not pre-load markets (for debugging)')
|
|
283
|
-
log ('--details Print detailed fetch responses')
|
|
284
|
-
log ('--no-table Do not print the fetch response as a table')
|
|
285
|
-
log ('--table Print the fetch response as a table')
|
|
286
|
-
log ('--iso8601 Print timestamps as ISO8601 datetimes')
|
|
287
|
-
log ('--param key=value Set a custom key=value pair for the last method\'s argument. Can be repeated multiple times')
|
|
288
|
-
log (' NOTE: don\'t forget to fill up missed arguments with "undefined" before last options parameter')
|
|
289
|
-
log ('--cors use CORS proxy for debugging')
|
|
290
|
-
log ('--sign-in Call signIn() if any')
|
|
291
|
-
log ('--sandbox Use the exchange sandbox if available, same as --testnet')
|
|
292
|
-
log ('--testnet Use the exchange testnet if available, same as --sandbox')
|
|
293
|
-
log ('--test Use the exchange testnet if available, same as --sandbox')
|
|
294
|
-
log ('--cache-markets Cache the loaded markets in the .cache folder in the current directory')
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
//-----------------------------------------------------------------------------
|
|
298
|
-
|
|
299
|
-
const printHumanReadable = (exchange, result) => {
|
|
300
|
-
if (raw) {
|
|
301
|
-
return log (jsonStringify (result))
|
|
302
|
-
}
|
|
303
|
-
if (!no_table && Array.isArray (result) || table) {
|
|
304
|
-
result = Object.values (result)
|
|
305
|
-
let arrayOfObjects = (typeof result[0] === 'object')
|
|
306
|
-
|
|
307
|
-
if (details)
|
|
308
|
-
result.forEach (object => {
|
|
309
|
-
if (arrayOfObjects)
|
|
310
|
-
log ('-------------------------------------------')
|
|
311
|
-
log (object)
|
|
312
|
-
})
|
|
313
|
-
|
|
314
|
-
if (arrayOfObjects || table && Array.isArray (result)) {
|
|
315
|
-
const configuredAsTable = asTable.configure ({
|
|
316
|
-
delimiter: ' | '.lightGray.dim,
|
|
317
|
-
right: true,
|
|
318
|
-
title: x => String (x).lightGray,
|
|
319
|
-
dash: '-'.lightGray.dim,
|
|
320
|
-
print: x => {
|
|
321
|
-
if (typeof x === 'object') {
|
|
322
|
-
const j = jsonStringify (x).trim ()
|
|
323
|
-
if (j.length < 100) return j
|
|
324
|
-
}
|
|
325
|
-
return String (x)
|
|
326
|
-
}
|
|
327
|
-
})
|
|
328
|
-
log (result.length > 0 ? configuredAsTable (result.map (rawElement => {
|
|
329
|
-
const element = Object.assign ({}, rawElement)
|
|
330
|
-
let keys = Object.keys (element)
|
|
331
|
-
delete element['info']
|
|
332
|
-
keys.forEach (key => {
|
|
333
|
-
if (!iso8601)
|
|
334
|
-
return element[key]
|
|
335
|
-
try {
|
|
336
|
-
const iso8601 = exchange.iso8601 (element[key])
|
|
337
|
-
if (iso8601.match (/^20[0-9]{2}[-]?/))
|
|
338
|
-
element[key] = iso8601
|
|
339
|
-
else
|
|
340
|
-
throw new Error ('wrong date')
|
|
341
|
-
} catch (e) {
|
|
342
|
-
return element[key]
|
|
343
|
-
}
|
|
344
|
-
})
|
|
345
|
-
return element
|
|
346
|
-
})) : result)
|
|
347
|
-
log (result.length, 'objects');
|
|
348
|
-
} else {
|
|
349
|
-
console.dir (result, { depth: null })
|
|
350
|
-
log (result.length, 'objects');
|
|
351
|
-
}
|
|
352
|
-
} else {
|
|
353
|
-
console.dir (result, { depth: null, maxArrayLength: null })
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
//-----------------------------------------------------------------------------
|
|
358
|
-
|
|
359
|
-
async function run () {
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
if (!exchangeId) {
|
|
364
|
-
|
|
365
|
-
printUsage ()
|
|
366
|
-
|
|
367
|
-
} else {
|
|
368
|
-
|
|
369
|
-
let args = params
|
|
370
|
-
.map (s => s.match (/^[0-9]{4}[-][0-9]{2}[-][0-9]{2}[T\s]?[0-9]{2}[:][0-9]{2}[:][0-9]{2}/g) ? exchange.parse8601 (s) : s)
|
|
371
|
-
.map (s => {
|
|
372
|
-
return (() => {
|
|
373
|
-
if (s.match(/^\d+$/g)) return s < Number.MAX_SAFE_INTEGER ? Number(s) : s
|
|
374
|
-
try {
|
|
375
|
-
return eval('(() => (' + s + ')) ()')
|
|
376
|
-
} catch (e) {
|
|
377
|
-
return s
|
|
378
|
-
}
|
|
379
|
-
})();
|
|
380
|
-
})
|
|
381
|
-
|
|
382
|
-
const www = Array.isArray (exchange.urls.www) ? exchange.urls.www[0] : exchange.urls.www
|
|
383
|
-
|
|
384
|
-
if (cors) {
|
|
385
|
-
exchange.proxy = 'https://cors-anywhere.herokuapp.com/';
|
|
386
|
-
exchange.origin = exchange.uuid ()
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
no_load_markets = no_send ? true : no_load_markets
|
|
390
|
-
|
|
391
|
-
if (debug) {
|
|
392
|
-
exchange.verbose = verbose
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
const path = '.cache/' + exchangeId + '-markets.json'
|
|
396
|
-
|
|
397
|
-
if (!no_load_markets) {
|
|
398
|
-
try {
|
|
399
|
-
await fsPromises.access (path, fs.constants.R_OK)
|
|
400
|
-
exchange.markets = JSON.parse (await fsPromises.readFile (path))
|
|
401
|
-
} catch {
|
|
402
|
-
await exchange.loadMarkets ()
|
|
403
|
-
if (cache_markets) {
|
|
404
|
-
await fsPromises.writeFile (path, jsonStringify (exchange.markets))
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
if (symbol && lastParamObject) {
|
|
409
|
-
let marketId
|
|
410
|
-
try {
|
|
411
|
-
marketId = exchange.marketId(symbol)
|
|
412
|
-
} catch (e) {
|
|
413
|
-
// noop possible loaded from cache
|
|
414
|
-
}
|
|
415
|
-
if (!marketId) {
|
|
416
|
-
try {
|
|
417
|
-
await exchange.loadMarkets();
|
|
418
|
-
marketId = exchange.marketId(symbol)
|
|
419
|
-
} catch (e) {
|
|
420
|
-
// noop
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
if (marketId) {
|
|
424
|
-
lastParamObject.symbol = marketId
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
if (typeof lastParamObject === 'object') {
|
|
429
|
-
const lastArgument = args[args.length - 1];
|
|
430
|
-
if (lastParam && typeof lastArgument === 'object') {
|
|
431
|
-
args[args.length - 1] = Object.assign (lastArgument, lastParamObject)
|
|
432
|
-
} else {
|
|
433
|
-
args.push (lastParamObject)
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
if (signIn && exchange.has.signIn) {
|
|
438
|
-
await exchange.signIn ()
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
exchange.verbose = verbose
|
|
442
|
-
|
|
443
|
-
if (no_send) {
|
|
444
|
-
|
|
445
|
-
exchange.verbose = no_send
|
|
446
|
-
exchange.fetch = function fetch (url, method = 'GET', headers = undefined, body = undefined) {
|
|
447
|
-
log.dim.noLocate ('-------------------------------------------')
|
|
448
|
-
log.dim.noLocate (exchange.iso8601 (exchange.milliseconds ()))
|
|
449
|
-
log.green.unlimited ({
|
|
450
|
-
url,
|
|
451
|
-
method,
|
|
452
|
-
headers,
|
|
453
|
-
body,
|
|
454
|
-
})
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
if (methodName) {
|
|
459
|
-
|
|
460
|
-
if (typeof exchange[methodName] === 'function') {
|
|
461
|
-
|
|
462
|
-
if (!raw || details) {
|
|
463
|
-
const methodArgsPrint = JSON.stringify(args);
|
|
464
|
-
log(exchange.id + '.' + methodName, '(' + methodArgsPrint.substring(1, methodArgsPrint.length - 1) + ')')
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
let start = exchange.milliseconds ()
|
|
468
|
-
let end = exchange.milliseconds ()
|
|
469
|
-
|
|
470
|
-
let i = 0;
|
|
471
|
-
|
|
472
|
-
let isWsMethod = false
|
|
473
|
-
if (methodName.startsWith("watch")) { // handle WS methods
|
|
474
|
-
isWsMethod = true;
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
while (true) {
|
|
478
|
-
try {
|
|
479
|
-
const fn = exchange[methodName]
|
|
480
|
-
const fnParams = countAllParams(fn)
|
|
481
|
-
const argsContainsParams = args.find( arg=> arg && typeof arg === 'object' && !Array.isArray(arg) && Object.keys(arg).length > 0)
|
|
482
|
-
if (argsContainsParams && fnParams !== args.length) {
|
|
483
|
-
// populate the missing params with undefined
|
|
484
|
-
const missingParams = fnParams - args.length
|
|
485
|
-
const paramsObj = args[args.length - 1]
|
|
486
|
-
args.pop()
|
|
487
|
-
const newArgsArray = args;
|
|
488
|
-
for (let i = 0; i < missingParams; i++) {
|
|
489
|
-
newArgsArray.push(undefined)
|
|
490
|
-
}
|
|
491
|
-
newArgsArray.push(paramsObj)
|
|
492
|
-
args = newArgsArray
|
|
493
|
-
}
|
|
494
|
-
const result = await exchange[methodName] (... args)
|
|
495
|
-
end = exchange.milliseconds ()
|
|
496
|
-
if (!isWsMethod && !raw) {
|
|
497
|
-
log (exchange.iso8601 (end), 'iteration', i++, 'passed in', end - start, 'ms\n')
|
|
498
|
-
}
|
|
499
|
-
printHumanReadable (exchange, result)
|
|
500
|
-
if (!isWsMethod && !raw) {
|
|
501
|
-
log (exchange.iso8601 (end), 'iteration', i, 'passed in', end - start, 'ms\n')
|
|
502
|
-
}
|
|
503
|
-
if (shouldCreateRequestReport || shouldCreateBoth) {
|
|
504
|
-
createRequestTemplate(exchange, methodName, args, result)
|
|
505
|
-
}
|
|
506
|
-
if (shouldCreateResponseReport || shouldCreateBoth) {
|
|
507
|
-
createResponseTemplate(exchange, methodName, args, result)
|
|
508
|
-
}
|
|
509
|
-
start = end
|
|
510
|
-
} catch (e) {
|
|
511
|
-
if (e instanceof ExchangeError) {
|
|
512
|
-
log.red (e.constructor.name, e.message)
|
|
513
|
-
} else if (e instanceof NetworkError) {
|
|
514
|
-
log.yellow (e.constructor.name, e.message)
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
log.dim ('---------------------------------------------------')
|
|
518
|
-
|
|
519
|
-
// rethrow for call-stack // other errors
|
|
520
|
-
throw e
|
|
521
|
-
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
if (debug) {
|
|
525
|
-
if (httpsAgent.freeSockets) {
|
|
526
|
-
const keys = Object.keys (httpsAgent.freeSockets)
|
|
527
|
-
if (keys.length) {
|
|
528
|
-
const firstKey = keys[0]
|
|
529
|
-
let httpAgent = httpsAgent.freeSockets[firstKey];
|
|
530
|
-
log (firstKey, httpAgent.length)
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
if (!poll && !isWsMethod){
|
|
536
|
-
break
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
exchange.close()
|
|
541
|
-
|
|
542
|
-
} else if (exchange[methodName] === undefined) {
|
|
543
|
-
log.red (exchange.id + '.' + methodName + ': no such property')
|
|
544
|
-
} else {
|
|
545
|
-
printHumanReadable (exchange, exchange[methodName])
|
|
546
|
-
}
|
|
547
|
-
} else {
|
|
548
|
-
log (exchange)
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
//-----------------------------------------------------------------------------
|
|
555
|
-
|
|
556
|
-
run ()
|
|
557
|
-
|
|
558
|
-
export {
|
|
559
|
-
}
|