ccxt 4.5.40 → 4.5.42
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 +6 -5
- package/dist/ccxt.browser.min.js +18 -18
- package/dist/cjs/ccxt.js +6 -1
- package/dist/cjs/src/abstract/lighter.js +11 -0
- package/dist/cjs/src/ascendex.js +73 -1
- package/dist/cjs/src/base/Exchange.js +149 -17
- package/dist/cjs/src/base/functions/generic.js +1 -0
- package/dist/cjs/src/base/functions/io.js +160 -0
- package/dist/cjs/src/base/functions.js +6 -0
- package/dist/cjs/src/base/ws/Client.js +1 -0
- package/dist/cjs/src/base/ws/WsClient.js +1 -0
- package/dist/cjs/src/binance.js +1 -0
- package/dist/cjs/src/bingx.js +13 -3
- package/dist/cjs/src/bitmex.js +20 -0
- package/dist/cjs/src/blofin.js +2 -2
- package/dist/cjs/src/bybit.js +1 -1
- package/dist/cjs/src/coinspot.js +7 -2
- package/dist/cjs/src/delta.js +1 -1
- package/dist/cjs/src/gate.js +11 -4
- package/dist/cjs/src/gemini.js +76 -1
- package/dist/cjs/src/htx.js +2 -2
- package/dist/cjs/src/hyperliquid.js +20 -7
- package/dist/cjs/src/independentreserve.js +7 -7
- package/dist/cjs/src/kraken.js +1 -1
- package/dist/cjs/src/krakenfutures.js +96 -5
- package/dist/cjs/src/kucoin.js +3 -3
- package/dist/cjs/src/kucoinfutures.js +1 -1
- package/dist/cjs/src/lighter.js +2931 -0
- package/dist/cjs/src/mexc.js +0 -1
- package/dist/cjs/src/phemex.js +1 -1
- package/dist/cjs/src/pro/binance.js +2 -2
- package/dist/cjs/src/pro/bingx.js +215 -2
- package/dist/cjs/src/pro/bitget.js +1 -0
- package/dist/cjs/src/pro/defx.js +1 -1
- package/dist/cjs/src/pro/kucoinfutures.js +1 -1
- package/dist/cjs/src/pro/lighter.js +787 -0
- package/dist/cjs/src/pro/mexc.js +1 -1
- package/dist/cjs/src/pro/paradex.js +1 -1
- package/dist/cjs/src/static_dependencies/ethers/abi-coder.js +1 -0
- package/dist/cjs/src/static_dependencies/ethers/address/address.js +1 -0
- package/dist/cjs/src/static_dependencies/ethers/coders/abstract-coder.js +1 -0
- package/dist/cjs/src/static_dependencies/ethers/coders/address.js +1 -0
- package/dist/cjs/src/static_dependencies/ethers/coders/array.js +1 -0
- package/dist/cjs/src/static_dependencies/ethers/coders/bytes.js +1 -0
- package/dist/cjs/src/static_dependencies/ethers/coders/fixed-bytes.js +1 -0
- package/dist/cjs/src/static_dependencies/ethers/coders/number.js +1 -0
- package/dist/cjs/src/static_dependencies/ethers/fragments.js +1 -0
- package/dist/cjs/src/static_dependencies/ethers/index.js +1 -0
- package/dist/cjs/src/static_dependencies/ethers/interface.js +1 -0
- package/dist/cjs/src/static_dependencies/ethers/typed.js +1 -0
- package/dist/cjs/src/static_dependencies/ethers/utils/index.js +1 -0
- package/dist/cjs/src/whitebit.js +118 -16
- package/dist/cjs/src/woo.js +1 -1
- package/js/ccxt.d.ts +8 -2
- package/js/ccxt.js +6 -2
- package/js/src/abstract/gemini.d.ts +27 -0
- package/js/src/abstract/lighter.d.ts +53 -0
- package/js/src/abstract/lighter.js +11 -0
- package/js/src/ascendex.d.ts +12 -1
- package/js/src/ascendex.js +73 -1
- package/js/src/base/Exchange.d.ts +18 -6
- package/js/src/base/Exchange.js +154 -21
- package/js/src/base/functions/generic.js +1 -0
- package/js/src/base/functions/io.d.ts +32 -0
- package/js/src/base/functions/io.js +137 -0
- package/js/src/base/functions.d.ts +1 -0
- package/js/src/base/functions.js +1 -0
- package/js/src/binance.d.ts +1 -0
- package/js/src/binance.js +1 -0
- package/js/src/bingx.js +13 -3
- package/js/src/bitmex.js +20 -0
- package/js/src/blofin.js +2 -2
- package/js/src/bybit.js +1 -1
- package/js/src/coinspot.js +7 -2
- package/js/src/delta.js +1 -1
- package/js/src/gate.d.ts +1 -0
- package/js/src/gate.js +11 -4
- package/js/src/gemini.d.ts +11 -0
- package/js/src/gemini.js +76 -1
- package/js/src/htx.js +2 -2
- package/js/src/hyperliquid.js +20 -7
- package/js/src/independentreserve.js +7 -7
- package/js/src/kraken.js +1 -1
- package/js/src/krakenfutures.d.ts +1 -1
- package/js/src/krakenfutures.js +96 -5
- package/js/src/kucoin.d.ts +3 -3
- package/js/src/kucoin.js +3 -3
- package/js/src/kucoinfutures.js +1 -1
- package/js/src/lighter.d.ts +424 -0
- package/js/src/lighter.js +2930 -0
- package/js/src/mexc.js +0 -1
- package/js/src/phemex.js +1 -1
- package/js/src/pro/binance.js +2 -2
- package/js/src/pro/bingx.d.ts +17 -1
- package/js/src/pro/bingx.js +216 -3
- package/js/src/pro/bitget.js +1 -0
- package/js/src/pro/defx.js +1 -1
- package/js/src/pro/kucoinfutures.js +1 -1
- package/js/src/pro/lighter.d.ts +161 -0
- package/js/src/pro/lighter.js +786 -0
- package/js/src/pro/mexc.js +1 -1
- package/js/src/pro/paradex.js +1 -1
- package/js/src/whitebit.d.ts +2 -1
- package/js/src/whitebit.js +118 -16
- package/js/src/woo.js +1 -1
- package/package.json +1 -1
package/js/src/ascendex.js
CHANGED
|
@@ -79,8 +79,9 @@ export default class ascendex extends Exchange {
|
|
|
79
79
|
'fetchMarkOHLCV': false,
|
|
80
80
|
'fetchMySettlementHistory': false,
|
|
81
81
|
'fetchOHLCV': true,
|
|
82
|
-
'fetchOpenInterest':
|
|
82
|
+
'fetchOpenInterest': 'emulated',
|
|
83
83
|
'fetchOpenInterestHistory': false,
|
|
84
|
+
'fetchOpenInterests': true,
|
|
84
85
|
'fetchOpenOrders': true,
|
|
85
86
|
'fetchOption': false,
|
|
86
87
|
'fetchOptionChain': false,
|
|
@@ -3602,6 +3603,77 @@ export default class ascendex extends Exchange {
|
|
|
3602
3603
|
const leverages = this.safeList(data, 'contracts', []);
|
|
3603
3604
|
return this.parseLeverages(leverages, symbols, 'symbol');
|
|
3604
3605
|
}
|
|
3606
|
+
/**
|
|
3607
|
+
* @method
|
|
3608
|
+
* @name ascendex#fetchOpenInterests
|
|
3609
|
+
* @description Retrieves the open interest for a list of symbols
|
|
3610
|
+
* @see https://ascendex.github.io/ascendex-futures-pro-api-v2/#futures-pricing-data
|
|
3611
|
+
* @param {string[]} [symbols] a list of unified CCXT market symbols
|
|
3612
|
+
* @param {object} [params] exchange specific parameters
|
|
3613
|
+
* @returns {object[]} a list of [open interest structures]{@link https://docs.ccxt.com/?id=open-interest-structure}
|
|
3614
|
+
*/
|
|
3615
|
+
async fetchOpenInterests(symbols = undefined, params = {}) {
|
|
3616
|
+
await this.loadMarkets();
|
|
3617
|
+
const request = {};
|
|
3618
|
+
let response = undefined;
|
|
3619
|
+
response = await this.v2PublicGetFuturesPricingData(this.extend(request, params));
|
|
3620
|
+
//
|
|
3621
|
+
// {
|
|
3622
|
+
// code: '0',
|
|
3623
|
+
// data: {
|
|
3624
|
+
// contracts: [
|
|
3625
|
+
// {
|
|
3626
|
+
// time: '1772138885616',
|
|
3627
|
+
// symbol: 'ZIL-PERP',
|
|
3628
|
+
// markPrice: '0.004167783',
|
|
3629
|
+
// indexPrice: '0.004168',
|
|
3630
|
+
// lastPrice: '0.00416',
|
|
3631
|
+
// openInterest: '7685003',
|
|
3632
|
+
// fundingRate: '0.0003',
|
|
3633
|
+
// nextFundingTime: '1772139600000'
|
|
3634
|
+
// },
|
|
3635
|
+
// ]
|
|
3636
|
+
// collaterals: [
|
|
3637
|
+
// { asset: 'TAO', referencePrice: '182.15' },
|
|
3638
|
+
// ...
|
|
3639
|
+
// ]
|
|
3640
|
+
// }
|
|
3641
|
+
// }
|
|
3642
|
+
//
|
|
3643
|
+
symbols = this.marketSymbols(symbols);
|
|
3644
|
+
const data = this.safeDict(response, 'data', {});
|
|
3645
|
+
const contracts = this.safeList(data, 'contracts', []);
|
|
3646
|
+
return this.parseOpenInterests(contracts, symbols);
|
|
3647
|
+
}
|
|
3648
|
+
parseOpenInterest(interest, market = undefined) {
|
|
3649
|
+
//
|
|
3650
|
+
// fetchOpenInterests
|
|
3651
|
+
//
|
|
3652
|
+
// {
|
|
3653
|
+
// time: '1772138885616',
|
|
3654
|
+
// symbol: 'ZIL-PERP',
|
|
3655
|
+
// markPrice: '0.004167783',
|
|
3656
|
+
// indexPrice: '0.004168',
|
|
3657
|
+
// lastPrice: '0.00416',
|
|
3658
|
+
// openInterest: '7685003',
|
|
3659
|
+
// fundingRate: '0.0003',
|
|
3660
|
+
// nextFundingTime: '1772139600000'
|
|
3661
|
+
// }
|
|
3662
|
+
//
|
|
3663
|
+
const marketId = this.safeString(interest, 'symbol');
|
|
3664
|
+
const timestamp = this.safeInteger(interest, 'time');
|
|
3665
|
+
const openInterest = this.safeNumber(interest, 'openInterest');
|
|
3666
|
+
return this.safeOpenInterest({
|
|
3667
|
+
'info': interest,
|
|
3668
|
+
'symbol': this.safeSymbol(marketId, market, undefined, 'swap'),
|
|
3669
|
+
'baseVolume': openInterest,
|
|
3670
|
+
'quoteVolume': undefined,
|
|
3671
|
+
'openInterestAmount': openInterest,
|
|
3672
|
+
'openInterestValue': undefined,
|
|
3673
|
+
'timestamp': timestamp,
|
|
3674
|
+
'datetime': this.iso8601(timestamp),
|
|
3675
|
+
}, market);
|
|
3676
|
+
}
|
|
3605
3677
|
parseLeverage(leverage, market = undefined) {
|
|
3606
3678
|
const marketId = this.safeString(leverage, 'symbol');
|
|
3607
3679
|
const leverageValue = this.safeInteger(leverage, 'leverage');
|
|
@@ -208,7 +208,6 @@ export default class Exchange {
|
|
|
208
208
|
isNode: boolean;
|
|
209
209
|
extend: (...args: any[]) => any;
|
|
210
210
|
clone: (x: any) => any;
|
|
211
|
-
flatten: (x: any[], out?: any[]) => any[];
|
|
212
211
|
unique: (x: any[]) => any[];
|
|
213
212
|
indexBy: (x: Dictionary<any>, k: IndexType, out?: Dictionary<any>) => Dictionary<any>;
|
|
214
213
|
indexBySafe: (x: Dictionary<any>, k: IndexType, out?: Dictionary<any>) => Dictionary<any>;
|
|
@@ -243,8 +242,6 @@ export default class Exchange {
|
|
|
243
242
|
implodeParams: (string: string, params: any[] | Dictionary<any>) => string;
|
|
244
243
|
extractParams: (string: string) => string[];
|
|
245
244
|
json: (data: any, params?: any) => string;
|
|
246
|
-
vwap: typeof functions.vwap;
|
|
247
|
-
merge: (target: Dictionary<any>, ...args: any) => Dictionary<any>;
|
|
248
245
|
binaryConcat: typeof import("../static_dependencies/noble-curves/abstract/utils.js").concatBytes;
|
|
249
246
|
hash: (request: import("../static_dependencies/noble-hashes/utils.js").Input, hash: {
|
|
250
247
|
(message: import("../static_dependencies/noble-hashes/utils.js").Input): Uint8Array;
|
|
@@ -270,8 +267,6 @@ export default class Exchange {
|
|
|
270
267
|
safeStringUpper: (o: any, k: IndexType, $default?: string) => string;
|
|
271
268
|
safeTimestamp: (o: any, k: IndexType, $default?: number) => number;
|
|
272
269
|
binaryConcatArray: (arr: any[]) => Uint8Array;
|
|
273
|
-
uuidv1: () => string;
|
|
274
|
-
numberToLE: (n: number, padding: number) => Uint8Array;
|
|
275
270
|
ymdhms: (timestamp: any, infix?: string) => string;
|
|
276
271
|
yymmdd: (timestamp: any, infix?: string) => string;
|
|
277
272
|
stringToBase64: (string: string) => string;
|
|
@@ -290,7 +285,6 @@ export default class Exchange {
|
|
|
290
285
|
safeStringLower2: (o: any, k1: IndexType, k2: IndexType, $default?: string) => string;
|
|
291
286
|
safeStringUpper2: (o: any, k1: IndexType, k2: IndexType, $default?: string) => string;
|
|
292
287
|
isEmpty: (object: any[] | Dictionary<any>) => boolean;
|
|
293
|
-
ordered: (x: any[] | Dictionary<any>) => any[] | Dictionary<any>;
|
|
294
288
|
filterBy: (x: Dictionary<any>, k: string, value?: any, out?: Dictionary<any>[]) => Dictionary<any>[];
|
|
295
289
|
uuid16: (a?: any) => string;
|
|
296
290
|
urlencodeWithArrayRepeat: (object: object) => string;
|
|
@@ -313,7 +307,12 @@ export default class Exchange {
|
|
|
313
307
|
crc32: typeof functions.crc32;
|
|
314
308
|
packb: typeof functions.packb;
|
|
315
309
|
urlencodeBase64: (payload: string | Uint8Array) => string;
|
|
310
|
+
readFile: typeof functions.readFile;
|
|
311
|
+
writeFile: typeof functions.writeFile;
|
|
312
|
+
existsFile: typeof functions.existsFile;
|
|
313
|
+
getTempDir: typeof functions.getTempDir;
|
|
316
314
|
constructor(userConfig?: ConstructorArgs);
|
|
315
|
+
loadExchangeSpecificFiles(): Promise<void>;
|
|
317
316
|
uuid5(namespace: string, name: string): string;
|
|
318
317
|
encodeURIComponent(...args: any[]): string;
|
|
319
318
|
checkRequiredVersion(requiredVersion: any, error?: boolean): boolean;
|
|
@@ -413,6 +412,19 @@ export default class Exchange {
|
|
|
413
412
|
binaryLength(binary: Uint8Array): number;
|
|
414
413
|
lockId(): any;
|
|
415
414
|
unlockId(): any;
|
|
415
|
+
loadLighterLibrary(libraryPath: any, chainId: any, privateKey: any, apiKeyIndex: any, accountIndex: any): Promise<{}>;
|
|
416
|
+
lighterSignCreateGroupedOrders(signer: any, request: any): any[];
|
|
417
|
+
lighterSignCreateOrder(signer: any, request: any): any[];
|
|
418
|
+
checkLighterSignedError(result: any): void;
|
|
419
|
+
lighterSignCancelOrder(signer: any, request: any): any[];
|
|
420
|
+
lighterSignWithdraw(signer: any, request: any): any[];
|
|
421
|
+
lighterSignCreateSubAccount(signer: any, request: any): any[];
|
|
422
|
+
lighterSignCancelAllOrders(signer: any, request: any): any[];
|
|
423
|
+
lighterSignModifyOrder(signer: any, request: any): any[];
|
|
424
|
+
lighterSignTransfer(signer: any, request: any): any[];
|
|
425
|
+
lighterSignUpdateLeverage(signer: any, request: any): any[];
|
|
426
|
+
lighterCreateAuthToken(signer: any, request: any): string;
|
|
427
|
+
lighterSignUpdateMargin(signer: any, request: any): any[];
|
|
416
428
|
describe(): any;
|
|
417
429
|
safeBoolN(dictionaryOrList: any, keys: IndexType[], defaultValue?: boolean): boolean | undefined;
|
|
418
430
|
safeBool2(dictionary: any, key1: IndexType, key2: IndexType, defaultValue?: boolean): boolean | undefined;
|
package/js/src/base/Exchange.js
CHANGED
|
@@ -6,11 +6,12 @@
|
|
|
6
6
|
|
|
7
7
|
// ----------------------------------------------------------------------------
|
|
8
8
|
import * as functions from './functions.js';
|
|
9
|
-
import {
|
|
10
|
-
// keys as keysFunc,
|
|
11
|
-
// values as valuesFunc,
|
|
12
|
-
// inArray as inArrayFunc,
|
|
13
|
-
vwap as vwapFunc,
|
|
9
|
+
// import {
|
|
10
|
+
// // keys as keysFunc,
|
|
11
|
+
// // values as valuesFunc,
|
|
12
|
+
// // inArray as inArrayFunc,
|
|
13
|
+
// // vwap as vwapFunc,
|
|
14
|
+
// } from './functions.js';
|
|
14
15
|
// import exceptions from "./errors.js"
|
|
15
16
|
import { // eslint-disable-line object-curly-newline
|
|
16
17
|
ExchangeError, BadSymbol, NullResponse, InvalidAddress, InvalidOrder, NotSupported, OperationFailed, BadResponse, AuthenticationError, DDoSProtection, RequestTimeout, NetworkError, InvalidProxySettings, ExchangeNotAvailable, ArgumentsRequired, RateLimitExceeded, BadRequest, UnsubscribeError, ExchangeClosedByUser, } from './errors.js';
|
|
@@ -35,9 +36,9 @@ import { sha256 } from '../static_dependencies/noble-hashes/sha256.js';
|
|
|
35
36
|
import { sha1 } from '../static_dependencies/noble-hashes/sha1.js';
|
|
36
37
|
import { exportMnemonicAndPrivateKey, deriveHDKeyFromMnemonic } from '../static_dependencies/dydx-v4-client/onboarding.js';
|
|
37
38
|
import { Long } from '../static_dependencies/dydx-v4-client/helpers.js';
|
|
38
|
-
const { isNode, selfIsDefined, deepExtend, extend, clone,
|
|
39
|
+
const { isNode, selfIsDefined, deepExtend, extend, clone, unique, indexBy, sortBy, sortBy2, safeFloat2, groupBy, aggregate, uuid, unCamelCase, precisionFromString, Throttler, capitalize, now, decimalToPrecision, safeValue, safeValue2, safeString, safeString2, seconds, milliseconds, binaryToBase16, numberToBE, base16ToBinary, iso8601, omit, isJsonEncodedObject, safeInteger, sum, omitZero, implodeParams, extractParams, json, binaryConcat, hash,
|
|
39
40
|
// ecdsa,
|
|
40
|
-
arrayConcat, encode, urlencode, hmac, numberToString, roundTimeframe, parseTimeframe, safeInteger2, safeStringLower, parse8601, yyyymmdd, safeStringUpper, safeTimestamp, binaryConcatArray,
|
|
41
|
+
arrayConcat, encode, urlencode, hmac, numberToString, roundTimeframe, parseTimeframe, safeInteger2, safeStringLower, parse8601, yyyymmdd, safeStringUpper, safeTimestamp, binaryConcatArray, ymdhms, stringToBase64, decode, uuid22, safeIntegerProduct2, safeIntegerProduct, safeStringLower2, yymmdd, base58ToBinary, binaryToBase58, safeTimestamp2, rawencode, keysort, sort, inArray, isEmpty, filterBy, uuid16, safeFloat, base64ToBinary, safeStringUpper2, urlencodeWithArrayRepeat, microseconds, binaryToBase64, strip, toArray, safeFloatN, safeIntegerN, safeIntegerProductN, safeTimestampN, safeValueN, safeStringN, safeStringLowerN, safeStringUpperN, urlencodeNested, urlencodeBase64, parseDate, ymd, base64ToString, crc32, packb, TRUNCATE, ROUND, DECIMAL_PLACES, NO_PADDING, TICK_SIZE, SIGNIFICANT_DIGITS, sleep, readFile, writeFile, existsFile, getTempDir, } = functions;
|
|
41
42
|
// ----------------------------------------------------------------------------
|
|
42
43
|
let protobufMexc = undefined;
|
|
43
44
|
let encodeAsAny = undefined;
|
|
@@ -47,14 +48,6 @@ let TxBody = undefined;
|
|
|
47
48
|
let TxRaw = undefined;
|
|
48
49
|
let SignDoc = undefined;
|
|
49
50
|
let SignMode = undefined;
|
|
50
|
-
(async () => {
|
|
51
|
-
try {
|
|
52
|
-
protobufMexc = await import('../protobuf/mexc/compiled.cjs');
|
|
53
|
-
}
|
|
54
|
-
catch (e) {
|
|
55
|
-
// TODO: handle error
|
|
56
|
-
}
|
|
57
|
-
})();
|
|
58
51
|
// -----------------------------------------------------------------------------
|
|
59
52
|
/**
|
|
60
53
|
* @class Exchange
|
|
@@ -172,7 +165,6 @@ export default class Exchange {
|
|
|
172
165
|
this.isNode = isNode;
|
|
173
166
|
this.extend = extend;
|
|
174
167
|
this.clone = clone;
|
|
175
|
-
this.flatten = flatten;
|
|
176
168
|
this.unique = unique;
|
|
177
169
|
this.indexBy = indexBy;
|
|
178
170
|
this.indexBySafe = indexBy;
|
|
@@ -207,8 +199,6 @@ export default class Exchange {
|
|
|
207
199
|
this.implodeParams = implodeParams;
|
|
208
200
|
this.extractParams = extractParams;
|
|
209
201
|
this.json = json;
|
|
210
|
-
this.vwap = vwapFunc;
|
|
211
|
-
this.merge = merge;
|
|
212
202
|
this.binaryConcat = binaryConcat;
|
|
213
203
|
this.hash = hash;
|
|
214
204
|
this.arrayConcat = arrayConcat;
|
|
@@ -224,8 +214,6 @@ export default class Exchange {
|
|
|
224
214
|
this.safeStringUpper = safeStringUpper;
|
|
225
215
|
this.safeTimestamp = safeTimestamp;
|
|
226
216
|
this.binaryConcatArray = binaryConcatArray;
|
|
227
|
-
this.uuidv1 = uuidv1;
|
|
228
|
-
this.numberToLE = numberToLE;
|
|
229
217
|
this.ymdhms = ymdhms;
|
|
230
218
|
this.yymmdd = yymmdd;
|
|
231
219
|
this.stringToBase64 = stringToBase64;
|
|
@@ -244,7 +232,6 @@ export default class Exchange {
|
|
|
244
232
|
this.safeStringLower2 = safeStringLower2;
|
|
245
233
|
this.safeStringUpper2 = safeStringUpper2;
|
|
246
234
|
this.isEmpty = isEmpty;
|
|
247
|
-
this.ordered = ordered;
|
|
248
235
|
this.filterBy = filterBy;
|
|
249
236
|
this.uuid16 = uuid16;
|
|
250
237
|
this.urlencodeWithArrayRepeat = urlencodeWithArrayRepeat;
|
|
@@ -267,6 +254,11 @@ export default class Exchange {
|
|
|
267
254
|
this.crc32 = crc32;
|
|
268
255
|
this.packb = packb;
|
|
269
256
|
this.urlencodeBase64 = urlencodeBase64;
|
|
257
|
+
// io
|
|
258
|
+
this.readFile = readFile;
|
|
259
|
+
this.writeFile = writeFile;
|
|
260
|
+
this.existsFile = existsFile;
|
|
261
|
+
this.getTempDir = getTempDir;
|
|
270
262
|
Object.assign(this, functions);
|
|
271
263
|
//
|
|
272
264
|
// if (isNode) {
|
|
@@ -382,6 +374,18 @@ export default class Exchange {
|
|
|
382
374
|
if (this.safeBool(userConfig, 'sandbox') || this.safeBool(userConfig, 'testnet')) {
|
|
383
375
|
this.setSandboxMode(true);
|
|
384
376
|
}
|
|
377
|
+
// exchange specific libs
|
|
378
|
+
this.loadExchangeSpecificFiles();
|
|
379
|
+
}
|
|
380
|
+
async loadExchangeSpecificFiles() {
|
|
381
|
+
if (this.id === 'mexc') {
|
|
382
|
+
try {
|
|
383
|
+
protobufMexc = await import('../protobuf/mexc/compiled.cjs');
|
|
384
|
+
}
|
|
385
|
+
catch (e) {
|
|
386
|
+
// TODO: handle error
|
|
387
|
+
}
|
|
388
|
+
}
|
|
385
389
|
}
|
|
386
390
|
uuid5(namespace, name) {
|
|
387
391
|
const nsBytes = namespace
|
|
@@ -681,6 +685,29 @@ export default class Exchange {
|
|
|
681
685
|
}
|
|
682
686
|
// set final headers
|
|
683
687
|
headers = this.setHeaders(headers);
|
|
688
|
+
// multipart/form-data
|
|
689
|
+
const headersKeys = Object.keys(headers);
|
|
690
|
+
for (let i = 0; i < headersKeys.length; i++) {
|
|
691
|
+
const key = headersKeys[i];
|
|
692
|
+
if (key.toLowerCase() === 'content-type') {
|
|
693
|
+
let value = headers[key];
|
|
694
|
+
if (value === 'multipart/form-data') {
|
|
695
|
+
const bodyKeys = Object.keys(body);
|
|
696
|
+
const boundary = '--------------------------' + this.randomBytes(12);
|
|
697
|
+
const eol = '\r\n';
|
|
698
|
+
let newBody = '';
|
|
699
|
+
for (let j = 0; j < bodyKeys.length; j++) {
|
|
700
|
+
const bodyKey = bodyKeys[j];
|
|
701
|
+
newBody += '--' + boundary + eol + 'Content-Disposition: form-data; name="' + bodyKey + '"' + eol + eol + body[bodyKey] + eol;
|
|
702
|
+
}
|
|
703
|
+
newBody += '--' + boundary + '--' + eol;
|
|
704
|
+
value += '; boundary=' + boundary;
|
|
705
|
+
headers[key] = value;
|
|
706
|
+
body = newBody;
|
|
707
|
+
break;
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
}
|
|
684
711
|
// log
|
|
685
712
|
if (this.verbose) {
|
|
686
713
|
this.log('fetch Request:\n', this.id, method, url, '\nRequestHeaders:\n', headers, '\nRequestBody:\n', body, '\n');
|
|
@@ -1565,6 +1592,112 @@ export default class Exchange {
|
|
|
1565
1592
|
unlockId() {
|
|
1566
1593
|
return undefined; // c# stub
|
|
1567
1594
|
}
|
|
1595
|
+
async loadLighterLibrary(libraryPath, chainId, privateKey, apiKeyIndex, accountIndex) {
|
|
1596
|
+
// wasmExecPathExample: '/opt/homebrew/opt/go/libexec/lib/wasm/wasm_exec.js';
|
|
1597
|
+
// libraryPath eg: '/Users/cjg/Git/lighter-go/lighter.wasm';
|
|
1598
|
+
if (libraryPath === undefined || libraryPath === '') {
|
|
1599
|
+
throw new Error('loadLighterLibrary() requires "libraryPath" that should point to "lighter.wasm".\nYou can build it from source using the official Ligher SDK or download it here https://github.com/ccxt/lighter-wasm.\nExample: exchanges.options["libraryPath"] = "/user/cjg/Git/lighter-wasm/lighter.wasm"');
|
|
1600
|
+
}
|
|
1601
|
+
if (!isNode) {
|
|
1602
|
+
throw new NotSupported(this.id + ' loadLighterLibrary() is only supported in node environment.');
|
|
1603
|
+
}
|
|
1604
|
+
await functions.initFileSystem();
|
|
1605
|
+
const wasmExecPath = this.safeString(this.options, 'wasmExecPath');
|
|
1606
|
+
if (wasmExecPath === undefined || wasmExecPath === '') {
|
|
1607
|
+
throw new Error('loadLighterLibrary() requires "wasmExecPath" that should point to `wasm_exec.js`. You can check the location of the file locally if you have GO installed or download it here https://github.com/ccxt/lighter-wasm.\nExample: exchanges.options["wasmExecPath"] = "/opt/homebrew/opt/go/libexec/lib/wasm/wasm_exec.js"');
|
|
1608
|
+
}
|
|
1609
|
+
await import(wasmExecPath);
|
|
1610
|
+
const go = new globalThis.Go();
|
|
1611
|
+
// read wasm from disks
|
|
1612
|
+
const bytes = new Uint8Array(readFile(libraryPath, null)); // it should point to lighter.wasm
|
|
1613
|
+
const { instance } = await WebAssembly.instantiate(bytes, go.importObject);
|
|
1614
|
+
go.run(instance);
|
|
1615
|
+
// createCLient
|
|
1616
|
+
const url = this.implodeHostname(this.urls['api']['public']);
|
|
1617
|
+
const res = globalThis.CreateClient(url, privateKey, chainId, apiKeyIndex, accountIndex);
|
|
1618
|
+
this.checkLighterSignedError(res);
|
|
1619
|
+
return {}; // empty object we will read it from globalThis
|
|
1620
|
+
}
|
|
1621
|
+
// eslint-disable-next-line no-unused-vars
|
|
1622
|
+
lighterSignCreateGroupedOrders(signer, request) {
|
|
1623
|
+
const orders = request['orders'];
|
|
1624
|
+
const ordersArr = [];
|
|
1625
|
+
for (let i = 0; i < orders.length; i++) {
|
|
1626
|
+
const order = orders[i];
|
|
1627
|
+
ordersArr.push({
|
|
1628
|
+
'MarketIndex': parseInt(order['market_index']),
|
|
1629
|
+
'ClientOrderIndex': order['client_order_index'],
|
|
1630
|
+
'BaseAmount': order['base_amount'],
|
|
1631
|
+
'Price': order['avg_execution_price'],
|
|
1632
|
+
'IsAsk': order['is_ask'],
|
|
1633
|
+
'Type': order['order_type'],
|
|
1634
|
+
'TimeInForce': order['time_in_force'],
|
|
1635
|
+
'ReduceOnly': order['reduce_only'],
|
|
1636
|
+
'TriggerPrice': order['trigger_price'],
|
|
1637
|
+
'OrderExpiry': order['order_expiry'],
|
|
1638
|
+
});
|
|
1639
|
+
}
|
|
1640
|
+
const res = globalThis.SignCreateGroupedOrders(request['grouping_type'], ordersArr, orders.length, request['nonce'], request['api_key_index'], request['account_index']);
|
|
1641
|
+
this.checkLighterSignedError(res);
|
|
1642
|
+
return [res.txType, res.txInfo];
|
|
1643
|
+
}
|
|
1644
|
+
// eslint-disable-next-line no-unused-vars
|
|
1645
|
+
lighterSignCreateOrder(signer, request) {
|
|
1646
|
+
const res = (globalThis.SignCreateOrder(parseInt(request['market_index']), request['client_order_index'], request['base_amount'], request['avg_execution_price'], request['is_ask'], request['order_type'], request['time_in_force'], request['reduce_only'], request['trigger_price'], request['order_expiry'], request['nonce'], request['api_key_index'], request['account_index']));
|
|
1647
|
+
this.checkLighterSignedError(res);
|
|
1648
|
+
return [res.txType, res.txInfo];
|
|
1649
|
+
}
|
|
1650
|
+
checkLighterSignedError(result) {
|
|
1651
|
+
if ('error' in result) {
|
|
1652
|
+
throw new Error('Lighter signing error: ' + result.error);
|
|
1653
|
+
}
|
|
1654
|
+
}
|
|
1655
|
+
lighterSignCancelOrder(signer, request) {
|
|
1656
|
+
const res = (globalThis.SignCancelOrder(request['market_index'], request['order_index'], request['nonce'], request['api_key_index'], request['account_index']));
|
|
1657
|
+
this.checkLighterSignedError(res);
|
|
1658
|
+
return [res.txType, res.txInfo];
|
|
1659
|
+
}
|
|
1660
|
+
lighterSignWithdraw(signer, request) {
|
|
1661
|
+
const res = (globalThis.SignWithdraw(request['asset_index'], request['route_type'], request['amount'], request['nonce'], request['api_key_index'], request['account_index']));
|
|
1662
|
+
this.checkLighterSignedError(res);
|
|
1663
|
+
return [res.txType, res.txInfo];
|
|
1664
|
+
}
|
|
1665
|
+
// eslint-disable-next-line no-unused-vars
|
|
1666
|
+
lighterSignCreateSubAccount(signer, request) {
|
|
1667
|
+
const res = (globalThis.SignCreateSubAccount(request['nonce'], request['api_key_index'], request['account_index']));
|
|
1668
|
+
this.checkLighterSignedError(res);
|
|
1669
|
+
return [res.txType, res.txInfo];
|
|
1670
|
+
}
|
|
1671
|
+
lighterSignCancelAllOrders(signer, request) {
|
|
1672
|
+
const res = (globalThis.SignCancelAllOrders(request['time_in_force'], request['time'], request['nonce'], request['api_key_index'], request['account_index']));
|
|
1673
|
+
this.checkLighterSignedError(res);
|
|
1674
|
+
return [res.txType, res.txInfo];
|
|
1675
|
+
}
|
|
1676
|
+
lighterSignModifyOrder(signer, request) {
|
|
1677
|
+
const res = (globalThis.SignModifyOrder(request['market_index'], request['index'], request['base_amount'], request['price'], request['trigger_price'], request['nonce'], request['api_key_index'], request['account_index']));
|
|
1678
|
+
this.checkLighterSignedError(res);
|
|
1679
|
+
return [res.txType, res.txInfo];
|
|
1680
|
+
}
|
|
1681
|
+
lighterSignTransfer(signer, request) {
|
|
1682
|
+
const res = globalThis.SignTransfer(request['to_account_index'], request['asset_index'], request['from_route_type'], request['to_route_type'], request['amount'], request['usdc_fee'], request['memo'], request['nonce'], request['api_key_index'], request['account_index']);
|
|
1683
|
+
this.checkLighterSignedError(res);
|
|
1684
|
+
return [res.txType, res.txInfo];
|
|
1685
|
+
}
|
|
1686
|
+
lighterSignUpdateLeverage(signer, request) {
|
|
1687
|
+
const res = (globalThis.SignUpdateLeverage(request['market_index'], request['initial_margin_fraction'], request['margin_mode'], request['nonce'], request['api_key_index'], request['account_index']));
|
|
1688
|
+
this.checkLighterSignedError(res);
|
|
1689
|
+
return [res.txType, res.txInfo];
|
|
1690
|
+
}
|
|
1691
|
+
lighterCreateAuthToken(signer, request) {
|
|
1692
|
+
const res = globalThis.CreateAuthToken(request['deadline'], request['api_key_index'], request['account_index']);
|
|
1693
|
+
this.checkLighterSignedError(res);
|
|
1694
|
+
return res.authToken;
|
|
1695
|
+
}
|
|
1696
|
+
lighterSignUpdateMargin(signer, request) {
|
|
1697
|
+
const res = globalThis.SignUpdateMargin(request['market_index'], request['usdc_amount'], request['direction'], request['nonce'], request['api_key_index'], request['account_index']);
|
|
1698
|
+
this.checkLighterSignedError(res);
|
|
1699
|
+
return [res.txType, res.txInfo];
|
|
1700
|
+
}
|
|
1568
1701
|
/* eslint-enable */
|
|
1569
1702
|
// ------------------------------------------------------------------------
|
|
1570
1703
|
// ########################################################################
|
|
@@ -176,6 +176,7 @@ const deepExtend = function (...args) {
|
|
|
176
176
|
}
|
|
177
177
|
return result;
|
|
178
178
|
};
|
|
179
|
+
// better "merge" func resides in static_dependencies/qs/utils.js
|
|
179
180
|
const merge = (target, ...args) => {
|
|
180
181
|
// doesn't overwrite defined keys with undefined
|
|
181
182
|
const overwrite = {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
/**
|
|
4
|
+
* Initialize synchronous file system module (Node.js only)
|
|
5
|
+
* Uses dynamic import to prevent bundling in browser builds
|
|
6
|
+
*/
|
|
7
|
+
export declare function initFileSystem(): Promise<void>;
|
|
8
|
+
/**
|
|
9
|
+
* Get system temporary directory (Node.js only)
|
|
10
|
+
* @returns Temporary directory path with trailing slash, or undefined
|
|
11
|
+
*/
|
|
12
|
+
export declare function getTempDir(): string | undefined;
|
|
13
|
+
/**
|
|
14
|
+
* Read file contents synchronously (Node.js only)
|
|
15
|
+
* @param path File path to read
|
|
16
|
+
* @param encoding File encoding (default: 'utf8')
|
|
17
|
+
* @returns File contents as string, or undefined in browser
|
|
18
|
+
*/
|
|
19
|
+
export declare function readFile(path: string, encoding?: BufferEncoding): string | undefined | Buffer;
|
|
20
|
+
/**
|
|
21
|
+
* Write file contents synchronously (Node.js only)
|
|
22
|
+
* @param path File path to write
|
|
23
|
+
* @param data Data to write
|
|
24
|
+
* @param encoding File encoding (default: 'utf8')
|
|
25
|
+
*/
|
|
26
|
+
export declare function writeFile(path: string, data: string, encoding?: BufferEncoding): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Check if file exists synchronously (Node.js only)
|
|
29
|
+
* @param path File path to check
|
|
30
|
+
* @returns true if file exists, false otherwise
|
|
31
|
+
*/
|
|
32
|
+
export declare function existsFile(path: string): boolean;
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
// ----------------------------------------------------------------------------
|
|
2
|
+
|
|
3
|
+
// PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
|
|
4
|
+
// https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
|
|
5
|
+
// EDIT THE CORRESPONDENT .ts FILE INSTEAD
|
|
6
|
+
|
|
7
|
+
/* ------------------------------------------------------------------------ */
|
|
8
|
+
import { isNode } from './platform.js';
|
|
9
|
+
/* ------------------------------------------------------------------------ */
|
|
10
|
+
let fsSyncModule = null;
|
|
11
|
+
let osSyncModule = null;
|
|
12
|
+
let pathSyncModule = null;
|
|
13
|
+
/* ------------------------------------------------------------------------ */
|
|
14
|
+
/**
|
|
15
|
+
* Initialize synchronous file system module (Node.js only)
|
|
16
|
+
* Uses dynamic import to prevent bundling in browser builds
|
|
17
|
+
*/
|
|
18
|
+
export async function initFileSystem() {
|
|
19
|
+
if (isNode) {
|
|
20
|
+
if (fsSyncModule === null) {
|
|
21
|
+
try {
|
|
22
|
+
// Dynamic import with webpackIgnore to prevent bundling
|
|
23
|
+
fsSyncModule = await import(/* webpackIgnore: true */ 'node:fs');
|
|
24
|
+
}
|
|
25
|
+
catch (e) { } // Silent fail in browser or if fs is unavailable
|
|
26
|
+
}
|
|
27
|
+
if (osSyncModule === null) {
|
|
28
|
+
try {
|
|
29
|
+
osSyncModule = await import(/* webpackIgnore: true */ 'node:os');
|
|
30
|
+
}
|
|
31
|
+
catch (e) { } // Silent fail in browser or if os is unavailable
|
|
32
|
+
}
|
|
33
|
+
if (pathSyncModule === null) {
|
|
34
|
+
try {
|
|
35
|
+
pathSyncModule = await import(/* webpackIgnore: true */ 'node:path');
|
|
36
|
+
}
|
|
37
|
+
catch (e) { } // Silent fail in browser or if path is unavailable
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (isNode) {
|
|
42
|
+
// Pre-initialize synchronous fs module for sync methods
|
|
43
|
+
initFileSystem();
|
|
44
|
+
}
|
|
45
|
+
/* ------------------------------------------------------------------------ */
|
|
46
|
+
/**
|
|
47
|
+
* Get system temporary directory (Node.js only)
|
|
48
|
+
* @returns Temporary directory path with trailing slash, or undefined
|
|
49
|
+
*/
|
|
50
|
+
export function getTempDir() {
|
|
51
|
+
if (!isNode || osSyncModule === null) {
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
const tmpDir = pathSyncModule.resolve(osSyncModule.tmpdir());
|
|
56
|
+
const sep = pathSyncModule ? pathSyncModule.sep : '/';
|
|
57
|
+
return tmpDir.endsWith(sep) ? tmpDir : tmpDir + sep;
|
|
58
|
+
}
|
|
59
|
+
catch (e) {
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Check if file path is ccxt-cache file, so users are ensured there is no access possible to other files
|
|
65
|
+
* @param path File path to check
|
|
66
|
+
*/
|
|
67
|
+
function ensureWhitelistedFile(filePath) {
|
|
68
|
+
if (pathSyncModule === null) {
|
|
69
|
+
throw new Error('path module is not available');
|
|
70
|
+
}
|
|
71
|
+
const sanitizedFilePath = pathSyncModule.resolve(filePath);
|
|
72
|
+
if ((sanitizedFilePath.startsWith(filePath) && sanitizedFilePath.endsWith('.ccxtfile')) || sanitizedFilePath.endsWith('.wasm')) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
throw new Error('invalid file path: ' + filePath);
|
|
76
|
+
}
|
|
77
|
+
/* ------------------------------------------------------------------------ */
|
|
78
|
+
/**
|
|
79
|
+
* Read file contents synchronously (Node.js only)
|
|
80
|
+
* @param path File path to read
|
|
81
|
+
* @param encoding File encoding (default: 'utf8')
|
|
82
|
+
* @returns File contents as string, or undefined in browser
|
|
83
|
+
*/
|
|
84
|
+
export function readFile(path, encoding = 'utf8') {
|
|
85
|
+
if (!isNode || fsSyncModule === null) {
|
|
86
|
+
// Sync module not initialized yet
|
|
87
|
+
return undefined;
|
|
88
|
+
}
|
|
89
|
+
ensureWhitelistedFile(path);
|
|
90
|
+
try {
|
|
91
|
+
return fsSyncModule.readFileSync(path, encoding);
|
|
92
|
+
}
|
|
93
|
+
catch (e) {
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/* ------------------------------------------------------------------------ */
|
|
98
|
+
/**
|
|
99
|
+
* Write file contents synchronously (Node.js only)
|
|
100
|
+
* @param path File path to write
|
|
101
|
+
* @param data Data to write
|
|
102
|
+
* @param encoding File encoding (default: 'utf8')
|
|
103
|
+
*/
|
|
104
|
+
export function writeFile(path, data, encoding = 'utf8') {
|
|
105
|
+
if (!isNode || fsSyncModule === null) {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
ensureWhitelistedFile(path);
|
|
109
|
+
try {
|
|
110
|
+
fsSyncModule.writeFileSync(path, data, encoding);
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
catch (e) {
|
|
114
|
+
// Silent fail
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/* ------------------------------------------------------------------------ */
|
|
119
|
+
/**
|
|
120
|
+
* Check if file exists synchronously (Node.js only)
|
|
121
|
+
* @param path File path to check
|
|
122
|
+
* @returns true if file exists, false otherwise
|
|
123
|
+
*/
|
|
124
|
+
export function existsFile(path) {
|
|
125
|
+
if (!isNode || fsSyncModule === null) {
|
|
126
|
+
// Sync module not initialized yet
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
ensureWhitelistedFile(path);
|
|
130
|
+
try {
|
|
131
|
+
fsSyncModule.accessSync(path);
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
catch (e) {
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
}
|
package/js/src/base/functions.js
CHANGED
|
@@ -15,4 +15,5 @@ export * from './functions/crypto.js';
|
|
|
15
15
|
export * from './functions/time.js';
|
|
16
16
|
export * from './functions/throttle.js';
|
|
17
17
|
export * from './functions/misc.js';
|
|
18
|
+
export * from './functions/io.js';
|
|
18
19
|
/* ------------------------------------------------------------------------ */
|
package/js/src/binance.d.ts
CHANGED
|
@@ -380,6 +380,7 @@ export default class binance extends Exchange {
|
|
|
380
380
|
* @param {string} [params.stopLossOrTakeProfit] 'stopLoss' or 'takeProfit', required for spot trailing orders
|
|
381
381
|
* @param {string} [params.positionSide] *swap and portfolio margin only* "BOTH" for one-way mode, "LONG" for buy side of hedged mode, "SHORT" for sell side of hedged mode
|
|
382
382
|
* @param {bool} [params.hedged] *swap and portfolio margin only* true for hedged mode, false for one way mode, default is false
|
|
383
|
+
* @param {string} [params.clientOrderId] the clientOrderId of the order
|
|
383
384
|
* @returns {object} an [order structure]{@link https://docs.ccxt.com/?id=order-structure}
|
|
384
385
|
*/
|
|
385
386
|
createOrder(symbol: string, type: OrderType, side: OrderSide, amount: number, price?: Num, params?: {}): Promise<Order>;
|
package/js/src/binance.js
CHANGED
|
@@ -6417,6 +6417,7 @@ export default class binance extends Exchange {
|
|
|
6417
6417
|
* @param {string} [params.stopLossOrTakeProfit] 'stopLoss' or 'takeProfit', required for spot trailing orders
|
|
6418
6418
|
* @param {string} [params.positionSide] *swap and portfolio margin only* "BOTH" for one-way mode, "LONG" for buy side of hedged mode, "SHORT" for sell side of hedged mode
|
|
6419
6419
|
* @param {bool} [params.hedged] *swap and portfolio margin only* true for hedged mode, false for one way mode, default is false
|
|
6420
|
+
* @param {string} [params.clientOrderId] the clientOrderId of the order
|
|
6420
6421
|
* @returns {object} an [order structure]{@link https://docs.ccxt.com/?id=order-structure}
|
|
6421
6422
|
*/
|
|
6422
6423
|
async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
|
package/js/src/bingx.js
CHANGED
|
@@ -141,7 +141,17 @@ export default class bingx extends Exchange {
|
|
|
141
141
|
'api': 'https://open-api.{hostname}/openApi',
|
|
142
142
|
},
|
|
143
143
|
'test': {
|
|
144
|
-
'
|
|
144
|
+
'fund': 'https://open-api-vst.{hostname}/openApi',
|
|
145
|
+
'spot': 'https://open-api-vst.{hostname}/openApi',
|
|
146
|
+
'swap': 'https://open-api-vst.{hostname}/openApi',
|
|
147
|
+
'contract': 'https://open-api-vst.{hostname}/openApi',
|
|
148
|
+
'wallets': 'https://open-api-vst.{hostname}/openApi',
|
|
149
|
+
'user': 'https://open-api-vst.{hostname}/openApi',
|
|
150
|
+
'subAccount': 'https://open-api-vst.{hostname}/openApi',
|
|
151
|
+
'account': 'https://open-api-vst.{hostname}/openApi',
|
|
152
|
+
'copyTrading': 'https://open-api-vst.{hostname}/openApi',
|
|
153
|
+
'cswap': 'https://open-api-vst.{hostname}/openApi',
|
|
154
|
+
'api': 'https://open-api-vst.{hostname}/openApi',
|
|
145
155
|
},
|
|
146
156
|
'www': 'https://bingx.com/',
|
|
147
157
|
'doc': 'https://bingx-api.github.io/docs/',
|
|
@@ -6841,10 +6851,10 @@ export default class bingx extends Exchange {
|
|
|
6841
6851
|
let version = section[1];
|
|
6842
6852
|
let access = section[2];
|
|
6843
6853
|
const isSandbox = this.safeBool(this.options, 'sandboxMode', false);
|
|
6844
|
-
|
|
6854
|
+
let url = this.implodeHostname(this.urls['api'][type]);
|
|
6855
|
+
if (isSandbox && url === undefined) {
|
|
6845
6856
|
throw new NotSupported(this.id + ' does not have a testnet/sandbox URL for ' + type + ' endpoints');
|
|
6846
6857
|
}
|
|
6847
|
-
let url = this.implodeHostname(this.urls['api'][type]);
|
|
6848
6858
|
path = this.implodeParams(path, params);
|
|
6849
6859
|
const versionIsTransfer = (version === 'transfer');
|
|
6850
6860
|
const versionIsAsset = (version === 'asset');
|