ccxt 4.3.44 → 4.3.45

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.
@@ -0,0 +1,2901 @@
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 Exchange from './abstract/oxfun.js';
9
+ import { Precise } from './base/Precise.js';
10
+ import { AccountNotEnabled, ArgumentsRequired, AuthenticationError, BadRequest, BadSymbol, ExchangeError, InvalidOrder, InsufficientFunds, OrderNotFound, MarketClosed, NetworkError, NotSupported, OperationFailed, RateLimitExceeded, RequestTimeout } from './base/errors.js';
11
+ import { TICK_SIZE } from './base/functions/number.js';
12
+ import { sha256 } from './static_dependencies/noble-hashes/sha256.js';
13
+ // ---------------------------------------------------------------------------
14
+ /**
15
+ * @class oxfun
16
+ * @augments Exchange
17
+ */
18
+ export default class oxfun extends Exchange {
19
+ describe() {
20
+ return this.deepExtend(super.describe(), {
21
+ 'id': 'oxfun',
22
+ 'name': 'Oxfun',
23
+ 'countries': ['PA'],
24
+ 'version': 'v3',
25
+ 'rateLimit': 120,
26
+ 'pro': true,
27
+ 'has': {
28
+ 'CORS': undefined,
29
+ 'spot': true,
30
+ 'margin': false,
31
+ 'swap': true,
32
+ 'future': false,
33
+ 'option': false,
34
+ 'addMargin': false,
35
+ 'cancelAllOrders': true,
36
+ 'cancelOrder': true,
37
+ 'cancelOrders': true,
38
+ 'closeAllPositions': false,
39
+ 'closePosition': false,
40
+ 'createDepositAddress': false,
41
+ 'createMarketBuyOrderWithCost': true,
42
+ 'createMarketOrderWithCost': false,
43
+ 'createMarketSellOrderWithCost': false,
44
+ 'createOrder': true,
45
+ 'createOrders': true,
46
+ 'createPostOnlyOrder': true,
47
+ 'createReduceOnlyOrder': false,
48
+ 'createStopLimitOrder': true,
49
+ 'createStopMarketOrder': true,
50
+ 'createStopOrder': true,
51
+ 'deposit': false,
52
+ 'editOrder': false,
53
+ 'fetchAccounts': true,
54
+ 'fetchBalance': true,
55
+ 'fetchBidsAsks': false,
56
+ 'fetchBorrowInterest': false,
57
+ 'fetchBorrowRateHistories': false,
58
+ 'fetchBorrowRateHistory': false,
59
+ 'fetchCanceledOrders': false,
60
+ 'fetchClosedOrder': false,
61
+ 'fetchClosedOrders': false,
62
+ 'fetchCrossBorrowRate': false,
63
+ 'fetchCrossBorrowRates': false,
64
+ 'fetchCurrencies': true,
65
+ 'fetchDeposit': false,
66
+ 'fetchDepositAddress': false,
67
+ 'fetchDepositAddresses': false,
68
+ 'fetchDepositAddressesByNetwork': false,
69
+ 'fetchDeposits': true,
70
+ 'fetchDepositWithdrawFee': false,
71
+ 'fetchDepositWithdrawFees': false,
72
+ 'fetchFundingHistory': true,
73
+ 'fetchFundingRate': false,
74
+ 'fetchFundingRateHistory': true,
75
+ 'fetchFundingRates': true,
76
+ 'fetchIndexOHLCV': false,
77
+ 'fetchIsolatedBorrowRate': false,
78
+ 'fetchIsolatedBorrowRates': false,
79
+ 'fetchL3OrderBook': false,
80
+ 'fetchLedger': false,
81
+ 'fetchLeverage': false,
82
+ 'fetchLeverageTiers': true,
83
+ 'fetchMarketLeverageTiers': false,
84
+ 'fetchMarkets': true,
85
+ 'fetchMarkOHLCV': false,
86
+ 'fetchMyTrades': true,
87
+ 'fetchOHLCV': true,
88
+ 'fetchOpenInterestHistory': false,
89
+ 'fetchOpenOrder': false,
90
+ 'fetchOpenOrders': true,
91
+ 'fetchOrder': true,
92
+ 'fetchOrderBook': true,
93
+ 'fetchOrderBooks': false,
94
+ 'fetchOrders': false,
95
+ 'fetchOrderTrades': false,
96
+ 'fetchPosition': false,
97
+ 'fetchPositionHistory': false,
98
+ 'fetchPositionMode': false,
99
+ 'fetchPositions': true,
100
+ 'fetchPositionsForSymbol': false,
101
+ 'fetchPositionsHistory': false,
102
+ 'fetchPositionsRisk': false,
103
+ 'fetchPremiumIndexOHLCV': false,
104
+ 'fetchStatus': false,
105
+ 'fetchTicker': true,
106
+ 'fetchTickers': true,
107
+ 'fetchTime': false,
108
+ 'fetchTrades': true,
109
+ 'fetchTradingFee': false,
110
+ 'fetchTradingFees': false,
111
+ 'fetchTradingLimits': false,
112
+ 'fetchTransactionFee': false,
113
+ 'fetchTransactionFees': false,
114
+ 'fetchTransactions': false,
115
+ 'fetchTransfers': true,
116
+ 'fetchWithdrawal': false,
117
+ 'fetchWithdrawals': true,
118
+ 'fetchWithdrawalWhitelist': false,
119
+ 'reduceMargin': false,
120
+ 'repayCrossMargin': false,
121
+ 'repayIsolatedMargin': false,
122
+ 'setLeverage': false,
123
+ 'setMargin': false,
124
+ 'setMarginMode': false,
125
+ 'setPositionMode': false,
126
+ 'signIn': false,
127
+ 'transfer': true,
128
+ 'withdraw': true,
129
+ 'ws': true,
130
+ },
131
+ 'timeframes': {
132
+ '1m': '60s',
133
+ '5m': '300s',
134
+ '15m': '900s',
135
+ '30m': '1800s',
136
+ '1h': '3600s',
137
+ '2h': '7200s',
138
+ '4h': '14400s',
139
+ '1d': '86400s',
140
+ },
141
+ 'urls': {
142
+ 'logo': 'https://github.com/ccxt/ccxt/assets/43336371/9c7114b3-ec32-4cf7-a716-f807d7d071cd',
143
+ 'referral': 'https://ox.fun/register?shareAccountId=5ZUD4a7G',
144
+ 'api': {
145
+ 'public': 'https://api.ox.fun',
146
+ 'private': 'https://api.ox.fun',
147
+ },
148
+ 'test': {
149
+ 'public': 'https://stgapi.ox.fun',
150
+ 'private': 'https://stgapi.ox.fun',
151
+ },
152
+ 'www': 'https://ox.fun/',
153
+ 'doc': 'https://docs.ox.fun/',
154
+ 'fees': 'https://support.ox.fun/en/articles/8819866-trading-fees',
155
+ },
156
+ 'api': {
157
+ 'public': {
158
+ 'get': {
159
+ 'v3/markets': 1,
160
+ 'v3/assets': 1,
161
+ 'v3/tickers': 1,
162
+ 'v3/funding/estimates': 1,
163
+ 'v3/candles': 1,
164
+ 'v3/depth': 1,
165
+ 'v3/markets/operational': 1,
166
+ 'v3/exchange-trades': 1,
167
+ 'v3/funding/rates': 1,
168
+ 'v3/leverage/tiers': 1,
169
+ },
170
+ },
171
+ 'private': {
172
+ 'get': {
173
+ 'v3/account': 1,
174
+ 'v3/account/names': 1,
175
+ 'v3/wallet': 1,
176
+ 'v3/transfer': 1,
177
+ 'v3/balances': 1,
178
+ 'v3/positions': 1,
179
+ 'v3/funding': 1,
180
+ 'v3/deposit-addresses': 1,
181
+ 'v3/deposit': 1,
182
+ 'v3/withdrawal-addresses': 1,
183
+ 'v3/withdrawal': 1,
184
+ 'v3/withdrawal-fees': 1,
185
+ 'v3/orders/status': 1,
186
+ 'v3/orders/working': 1,
187
+ 'v3/trades': 1,
188
+ },
189
+ 'post': {
190
+ 'v3/transfer': 1,
191
+ 'v3/withdrawal': 1,
192
+ 'v3/orders/place': 1,
193
+ },
194
+ 'delete': {
195
+ 'v3/orders/cancel': 1,
196
+ 'v3/orders/cancel-all': 1,
197
+ },
198
+ },
199
+ },
200
+ 'fees': {
201
+ 'trading': {
202
+ 'tierBased': true,
203
+ 'percentage': true,
204
+ 'maker': this.parseNumber('0.00020'),
205
+ 'taker': this.parseNumber('0.00070'),
206
+ 'tiers': {
207
+ 'maker': [
208
+ [this.parseNumber('0'), this.parseNumber('0.00020')],
209
+ [this.parseNumber('2500000'), this.parseNumber('0.00010')],
210
+ [this.parseNumber('25000000'), this.parseNumber('0')],
211
+ ],
212
+ 'taker': [
213
+ [this.parseNumber('0'), this.parseNumber('0.00070')],
214
+ [this.parseNumber('2500000'), this.parseNumber('0.00050')],
215
+ [this.parseNumber('25000000'), this.parseNumber('0.00040')],
216
+ ],
217
+ },
218
+ },
219
+ },
220
+ 'precisionMode': TICK_SIZE,
221
+ // exchange-specific options
222
+ 'options': {
223
+ 'sandboxMode': false,
224
+ 'networks': {
225
+ 'BTC': 'Bitcoin',
226
+ 'ERC20': 'Ethereum',
227
+ 'AVAX': 'Avalanche',
228
+ 'SOL': 'Solana',
229
+ 'ARB': 'Arbitrum',
230
+ 'MATIC': 'Polygon',
231
+ 'FTM': 'Fantom',
232
+ 'BNB': 'BNBSmartChain',
233
+ 'OPTIMISM': 'Optimism',
234
+ },
235
+ 'networksById': {
236
+ 'Bitcoin': 'BTC',
237
+ 'Ethereum': 'ERC20',
238
+ 'Avalanche': 'AVAX',
239
+ 'Solana': 'SOL',
240
+ 'Arbitrum': 'ARB',
241
+ 'Polygon': 'MATIC',
242
+ 'Fantom': 'FTM',
243
+ 'Base': 'BASE',
244
+ 'BNBSmartChain': 'BNB',
245
+ 'Optimism': 'OPTIMISM',
246
+ },
247
+ },
248
+ 'exceptions': {
249
+ 'exact': {
250
+ '-0010': OperationFailed,
251
+ '-429': RateLimitExceeded,
252
+ '-05001': AuthenticationError,
253
+ '-10001': ExchangeError,
254
+ '-20000': BadRequest,
255
+ '-20001': BadRequest,
256
+ '-20002': BadRequest,
257
+ '-20003': NotSupported,
258
+ '-20005': AuthenticationError,
259
+ '-20006': BadRequest,
260
+ '-20007': AuthenticationError,
261
+ '-20008': BadRequest,
262
+ '-20009': BadRequest,
263
+ '-20010': ArgumentsRequired,
264
+ '-20011': ArgumentsRequired,
265
+ '-20012': ArgumentsRequired,
266
+ '-20013': ArgumentsRequired,
267
+ '-20014': BadRequest,
268
+ '-20015': BadSymbol,
269
+ '-20016': BadRequest,
270
+ '-20017': BadRequest,
271
+ '-20018': BadRequest,
272
+ '-20019': BadRequest,
273
+ '-20020': BadRequest,
274
+ '-20021': BadRequest,
275
+ '-20022': ArgumentsRequired,
276
+ '-20023': ArgumentsRequired,
277
+ '-20024': ExchangeError,
278
+ '-20025': AuthenticationError,
279
+ '-20026': BadRequest,
280
+ '-20027': BadRequest,
281
+ '-20028': BadRequest,
282
+ '-20029': BadRequest,
283
+ '-20030': BadRequest,
284
+ '-20031': MarketClosed,
285
+ '-20032': NetworkError,
286
+ '-20033': BadRequest,
287
+ '-20034': BadRequest,
288
+ '-20050': ExchangeError,
289
+ '-30001': BadRequest,
290
+ '-35034': AuthenticationError,
291
+ '-35046': AuthenticationError,
292
+ '-40001': ExchangeError,
293
+ '-50001': ExchangeError,
294
+ '-300001': AccountNotEnabled,
295
+ '-300011': InvalidOrder,
296
+ '-300012': InvalidOrder,
297
+ '-100005': OrderNotFound,
298
+ '-100006': InvalidOrder,
299
+ '-100008': BadRequest,
300
+ '-100015': NetworkError,
301
+ '-710001': ExchangeError,
302
+ '-710002': BadRequest,
303
+ '-710003': BadRequest,
304
+ '-710004': BadRequest,
305
+ '-710005': InsufficientFunds,
306
+ '-710006': InsufficientFunds,
307
+ '-710007': InsufficientFunds,
308
+ '-000101': NetworkError,
309
+ '-000201': NetworkError, // Trade service is busy, try again later
310
+ },
311
+ 'broad': {
312
+ '-20001': OperationFailed,
313
+ '-200050': RequestTimeout, // The market is not active
314
+ },
315
+ },
316
+ });
317
+ }
318
+ async fetchMarkets(params = {}) {
319
+ /**
320
+ * @method
321
+ * @name oxfun#fetchMarkets
322
+ * @description retrieves data on all markets for bitmex
323
+ * @see https://docs.ox.fun/?json#get-v3-markets
324
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
325
+ * @returns {object[]} an array of objects representing market data
326
+ */
327
+ const [responseFromMarkets, responseFromTickers] = await Promise.all([this.publicGetV3Markets(params), this.publicGetV3Tickers(params)]);
328
+ const marketsFromMarkets = this.safeList(responseFromMarkets, 'data', []);
329
+ //
330
+ // {
331
+ // success: true,
332
+ // data: [
333
+ // {
334
+ // marketCode: 'OX-USD-SWAP-LIN',
335
+ // name: 'OX/USD Perp',
336
+ // referencePair: 'OX/USDT',
337
+ // base: 'OX',
338
+ // counter: 'USD',
339
+ // type: 'FUTURE',
340
+ // tickSize: '0.00001',
341
+ // minSize: '1',
342
+ // listedAt: '1704766320000',
343
+ // upperPriceBound: '0.02122',
344
+ // lowerPriceBound: '0.01142',
345
+ // markPrice: '0.01632',
346
+ // indexPrice: '0.01564',
347
+ // lastUpdatedAt: '1714762235569'
348
+ // },
349
+ // {
350
+ // marketCode: 'BTC-USD-SWAP-LIN',
351
+ // name: 'BTC/USD Perp',
352
+ // referencePair: 'BTC/USDT',
353
+ // base: 'BTC',
354
+ // counter: 'USD',
355
+ // type: 'FUTURE',
356
+ // tickSize: '1',
357
+ // minSize: '0.0001',
358
+ // listedAt: '1704686640000',
359
+ // upperPriceBound: '67983',
360
+ // lowerPriceBound: '55621',
361
+ // markPrice: '61802',
362
+ // indexPrice: '61813',
363
+ // lastUpdatedAt: '1714762234765'
364
+ // },
365
+ // {
366
+ // "marketCode": "MILK-OX",
367
+ // "name": "MILK/OX",
368
+ // "referencePair": "MILK/OX",
369
+ // "base": "MILK",
370
+ // "counter": "OX",
371
+ // "type": "SPOT",
372
+ // "tickSize": "0.0001",
373
+ // "minSize": "1",
374
+ // "listedAt": "1706608500000",
375
+ // "upperPriceBound": "1.0000",
376
+ // "lowerPriceBound": "-1.0000",
377
+ // "markPrice": "0.0269",
378
+ // "indexPrice": "0.0269",
379
+ // "lastUpdatedAt": "1714757402185"
380
+ // },
381
+ // ...
382
+ // ]
383
+ // }
384
+ //
385
+ const marketsFromTickers = this.safeList(responseFromTickers, 'data', []);
386
+ //
387
+ // {
388
+ // "success": true,
389
+ // "data": [
390
+ // {
391
+ // "marketCode": "DYM-USD-SWAP-LIN",
392
+ // "markPrice": "3.321",
393
+ // "open24h": "3.315",
394
+ // "high24h": "3.356",
395
+ // "low24h": "3.255",
396
+ // "volume24h": "0",
397
+ // "currencyVolume24h": "0",
398
+ // "openInterest": "1768.1",
399
+ // "lastTradedPrice": "3.543",
400
+ // "lastTradedQuantity": "1.0",
401
+ // "lastUpdatedAt": "1714853388102"
402
+ // },
403
+ // ...
404
+ // ]
405
+ // }
406
+ //
407
+ const markets = this.arrayConcat(marketsFromMarkets, marketsFromTickers);
408
+ return this.parseMarkets(markets);
409
+ }
410
+ parseMarkets(markets) {
411
+ const marketIds = [];
412
+ const result = [];
413
+ for (let i = 0; i < markets.length; i++) {
414
+ const market = markets[i];
415
+ const marketId = this.safeString(market, 'marketCode');
416
+ if (!(this.inArray(marketId, marketIds))) {
417
+ marketIds.push(marketId);
418
+ result.push(this.parseMarket(market));
419
+ }
420
+ }
421
+ return result;
422
+ }
423
+ parseMarket(market) {
424
+ const id = this.safeString(market, 'marketCode', '');
425
+ const parts = id.split('-');
426
+ const baseId = this.safeString(parts, 0);
427
+ const quoteId = this.safeString(parts, 1);
428
+ const base = this.safeCurrencyCode(baseId);
429
+ const quote = this.safeCurrencyCode(quoteId);
430
+ let symbol = base + '/' + quote;
431
+ let type = this.safeStringLower(market, 'type', 'spot'); // markets from v3/tickers are spot and have no type
432
+ let settleId = undefined;
433
+ let settle = undefined;
434
+ const isFuture = (type === 'future'); // the exchange has only perpetual futures
435
+ if (isFuture) {
436
+ type = 'swap';
437
+ settleId = 'OX';
438
+ settle = this.safeCurrencyCode('OX');
439
+ symbol = symbol + ':' + settle;
440
+ }
441
+ const isSpot = type === 'spot';
442
+ return this.safeMarketStructure({
443
+ 'id': id,
444
+ 'numericId': undefined,
445
+ 'symbol': symbol,
446
+ 'base': base,
447
+ 'quote': quote,
448
+ 'settle': settle,
449
+ 'baseId': baseId,
450
+ 'quoteId': quoteId,
451
+ 'settleId': settleId,
452
+ 'type': type,
453
+ 'spot': isSpot,
454
+ 'margin': false,
455
+ 'swap': isFuture,
456
+ 'future': false,
457
+ 'option': false,
458
+ 'active': true,
459
+ 'contract': isFuture,
460
+ 'linear': isFuture ? true : undefined,
461
+ 'inverse': isFuture ? false : undefined,
462
+ 'taker': this.fees['trading']['taker'],
463
+ 'maker': this.fees['trading']['maker'],
464
+ 'contractSize': isFuture ? 1 : undefined,
465
+ 'expiry': undefined,
466
+ 'expiryDatetime': undefined,
467
+ 'strike': undefined,
468
+ 'optionType': undefined,
469
+ 'precision': {
470
+ 'amount': undefined,
471
+ 'price': this.safeNumber(market, 'tickSize'),
472
+ },
473
+ 'limits': {
474
+ 'leverage': {
475
+ 'min': undefined,
476
+ 'max': undefined,
477
+ },
478
+ 'amount': {
479
+ 'min': this.safeNumber(market, 'minSize'),
480
+ 'max': undefined,
481
+ },
482
+ 'price': {
483
+ 'min': undefined,
484
+ 'max': undefined,
485
+ },
486
+ 'cost': {
487
+ 'min': undefined,
488
+ 'max': undefined,
489
+ },
490
+ },
491
+ 'created': this.safeInteger(market, 'listedAt'),
492
+ 'index': undefined,
493
+ 'info': market,
494
+ });
495
+ }
496
+ async fetchCurrencies(params = {}) {
497
+ /**
498
+ * @method
499
+ * @name oxfun#fetchCurrencies
500
+ * @description fetches all available currencies on an exchange
501
+ * @see https://docs.ox.fun/?json#get-v3-assets
502
+ * @param {dict} [params] extra parameters specific to the exchange API endpoint
503
+ * @returns {dict} an associative dictionary of currencies
504
+ */
505
+ const response = await this.publicGetV3Assets(params);
506
+ //
507
+ // {
508
+ // "success": true,
509
+ // "data": [
510
+ // {
511
+ // "asset": "OX",
512
+ // "isCollateral": true,
513
+ // "loanToValue": "1.000000000",
514
+ // "loanToValueFactor": "0.000000000",
515
+ // "networkList": [
516
+ // {
517
+ // "network": "BNBSmartChain",
518
+ // "tokenId": "0x78a0A62Fba6Fb21A83FE8a3433d44C73a4017A6f",
519
+ // "transactionPrecision": "18",
520
+ // "isWithdrawalFeeChargedToUser": true,
521
+ // "canDeposit": true,
522
+ // "canWithdraw": false,
523
+ // "minDeposit": "0.00010",
524
+ // "minWithdrawal": "0.00010"
525
+ // },
526
+ // {
527
+ // "network": "Polygon",
528
+ // "tokenId": "0x78a0A62Fba6Fb21A83FE8a3433d44C73a4017A6f",
529
+ // "transactionPrecision": "18",
530
+ // "isWithdrawalFeeChargedToUser": true,
531
+ // "canDeposit": true,
532
+ // "canWithdraw": false,
533
+ // "minDeposit": "0.00010",
534
+ // "minWithdrawal": "0.00010"
535
+ // },
536
+ // {
537
+ // "network": "Arbitrum",
538
+ // "tokenId": "0xba0Dda8762C24dA9487f5FA026a9B64b695A07Ea",
539
+ // "transactionPrecision": "18",
540
+ // "isWithdrawalFeeChargedToUser": true,
541
+ // "canDeposit": true,
542
+ // "canWithdraw": true,
543
+ // "minDeposit": "0.00010",
544
+ // "minWithdrawal": "0.00010"
545
+ // },
546
+ // {
547
+ // "network": "Ethereum",
548
+ // "tokenId": "0xba0Dda8762C24dA9487f5FA026a9B64b695A07Ea",
549
+ // "transactionPrecision": "18",
550
+ // "isWithdrawalFeeChargedToUser": true,
551
+ // "canDeposit": true,
552
+ // "canWithdraw": true,
553
+ // "minDeposit": "0.00010",
554
+ // "minWithdrawal": "0.00010"
555
+ // },
556
+ // {
557
+ // "network": "Arbitrum",
558
+ // "tokenId": "0x78a0A62Fba6Fb21A83FE8a3433d44C73a4017A6f",
559
+ // "transactionPrecision": "18",
560
+ // "isWithdrawalFeeChargedToUser": true,
561
+ // "canDeposit": true,
562
+ // "canWithdraw": false,
563
+ // "minDeposit": "0.00010",
564
+ // "minWithdrawal": "0.00010"
565
+ // },
566
+ // {
567
+ // "network": "Avalanche",
568
+ // "tokenId": "0x78a0A62Fba6Fb21A83FE8a3433d44C73a4017A6f",
569
+ // "transactionPrecision": "18",
570
+ // "isWithdrawalFeeChargedToUser": true,
571
+ // "canDeposit": true,
572
+ // "canWithdraw": false,
573
+ // "minDeposit": "0.00010",
574
+ // "minWithdrawal": "0.00010"
575
+ // },
576
+ // {
577
+ // "network": "Solana",
578
+ // "tokenId": "DV3845GEAVXfwpyVGGgWbqBVCtzHdCXNCGfcdboSEuZz",
579
+ // "transactionPrecision": "8",
580
+ // "isWithdrawalFeeChargedToUser": true,
581
+ // "canDeposit": true,
582
+ // "canWithdraw": true,
583
+ // "minDeposit": "0.00010",
584
+ // "minWithdrawal": "0.00010"
585
+ // },
586
+ // {
587
+ // "network": "Ethereum",
588
+ // "tokenId": "0x78a0A62Fba6Fb21A83FE8a3433d44C73a4017A6f",
589
+ // "transactionPrecision": "18",
590
+ // "isWithdrawalFeeChargedToUser": true,
591
+ // "canDeposit": true,
592
+ // "canWithdraw": false,
593
+ // "minDeposit": "0.00010",
594
+ // "minWithdrawal": "0.00010"
595
+ // }
596
+ // ]
597
+ // },
598
+ // {
599
+ // "asset": "BTC",
600
+ // "isCollateral": true,
601
+ // "loanToValue": "0.950000000",
602
+ // "loanToValueFactor": "0.000000000",
603
+ // "networkList": [
604
+ // {
605
+ // "network": "Bitcoin",
606
+ // "transactionPrecision": "8",
607
+ // "isWithdrawalFeeChargedToUser": true,
608
+ // "canDeposit": true,
609
+ // "canWithdraw": true,
610
+ // "minDeposit": "0.00010",
611
+ // "minWithdrawal": "0.00010"
612
+ // }
613
+ // ]
614
+ // },
615
+ // {
616
+ // "asset": "USDT.ARB",
617
+ // "isCollateral": true,
618
+ // "loanToValue": "0.950000000",
619
+ // "loanToValueFactor": "0.000000000",
620
+ // "networkList": [
621
+ // {
622
+ // "network": "Arbitrum",
623
+ // "tokenId": "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9",
624
+ // "transactionPrecision": "18",
625
+ // "isWithdrawalFeeChargedToUser": true,
626
+ // "canDeposit": true,
627
+ // "canWithdraw": true,
628
+ // "minDeposit": "0.00010",
629
+ // "minWithdrawal": "0.00010"
630
+ // }
631
+ // ]
632
+ // },
633
+ // ...
634
+ // ]
635
+ // }
636
+ //
637
+ const data = this.safeList(response, 'data', []);
638
+ const result = {};
639
+ for (let i = 0; i < data.length; i++) {
640
+ const currency = data[i];
641
+ const fullId = this.safeString(currency, 'asset', '');
642
+ const parts = fullId.split('.');
643
+ const id = parts[0];
644
+ const code = this.safeCurrencyCode(id);
645
+ let networks = {};
646
+ const chains = this.safeList(currency, 'networkList', []);
647
+ let currencyMaxPrecision = undefined;
648
+ let currencyDepositEnabled = undefined;
649
+ let currencyWithdrawEnabled = undefined;
650
+ for (let j = 0; j < chains.length; j++) {
651
+ const chain = chains[j];
652
+ const networkId = this.safeString(chain, 'network');
653
+ const networkCode = this.networkIdToCode(networkId);
654
+ const deposit = this.safeBool(chain, 'canDeposit');
655
+ const withdraw = this.safeBool(chain, 'canWithdraw');
656
+ const active = (deposit && withdraw);
657
+ const minDeposit = this.safeString(chain, 'minDeposit');
658
+ const minWithdrawal = this.safeString(chain, 'minWithdrawal');
659
+ const precision = this.parsePrecision(this.safeString(chain, 'transactionPrecision'));
660
+ networks[networkCode] = {
661
+ 'id': networkId,
662
+ 'network': networkCode,
663
+ 'margin': undefined,
664
+ 'deposit': deposit,
665
+ 'withdraw': withdraw,
666
+ 'active': active,
667
+ 'fee': undefined,
668
+ 'precision': this.parseNumber(precision),
669
+ 'limits': {
670
+ 'deposit': {
671
+ 'min': minDeposit,
672
+ 'max': undefined,
673
+ },
674
+ 'withdraw': {
675
+ 'min': minWithdrawal,
676
+ 'max': undefined,
677
+ },
678
+ },
679
+ 'info': chain,
680
+ };
681
+ if ((currencyDepositEnabled === undefined) || deposit) {
682
+ currencyDepositEnabled = deposit;
683
+ }
684
+ if ((currencyWithdrawEnabled === undefined) || withdraw) {
685
+ currencyWithdrawEnabled = withdraw;
686
+ }
687
+ if ((currencyMaxPrecision === undefined) || Precise.stringGt(currencyMaxPrecision, precision)) {
688
+ currencyMaxPrecision = precision;
689
+ }
690
+ }
691
+ if (code in result) {
692
+ // checking for specific ids as USDC.ARB
693
+ networks = this.extend(result[code]['networks'], networks);
694
+ }
695
+ result[code] = {
696
+ 'id': id,
697
+ 'code': code,
698
+ 'name': undefined,
699
+ 'type': undefined,
700
+ 'active': undefined,
701
+ 'deposit': currencyDepositEnabled,
702
+ 'withdraw': currencyWithdrawEnabled,
703
+ 'fee': undefined,
704
+ 'precision': this.parseNumber(currencyMaxPrecision),
705
+ 'limits': {
706
+ 'amount': {
707
+ 'min': undefined,
708
+ 'max': undefined,
709
+ },
710
+ 'withdraw': {
711
+ 'min': undefined,
712
+ 'max': undefined,
713
+ },
714
+ },
715
+ 'networks': networks,
716
+ 'info': currency,
717
+ };
718
+ }
719
+ return result;
720
+ }
721
+ async fetchTickers(symbols = undefined, params = {}) {
722
+ /**
723
+ * @method
724
+ * @name oxfun#fetchTickers
725
+ * @description fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
726
+ * @see https://docs.ox.fun/?json#get-v3-tickers
727
+ * @param {string[]|undefined} symbols unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
728
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
729
+ * @returns {object} a dictionary of [ticker structures]{@link https://docs.ccxt.com/#/?id=ticker-structure}
730
+ */
731
+ await this.loadMarkets();
732
+ symbols = this.marketSymbols(symbols);
733
+ const response = await this.publicGetV3Tickers(params);
734
+ //
735
+ // {
736
+ // "success": true,
737
+ // "data": [
738
+ // {
739
+ // "marketCode": "NII-USDT",
740
+ // "markPrice": "0",
741
+ // "open24h": "0",
742
+ // "high24h": "0",
743
+ // "low24h": "0",
744
+ // "volume24h": "0",
745
+ // "currencyVolume24h": "0",
746
+ // "openInterest": "0",
747
+ // "lastTradedPrice": "0",
748
+ // "lastTradedQuantity": "0",
749
+ // "lastUpdatedAt": "1714853388621"
750
+ // },
751
+ // {
752
+ // "marketCode": "GEC-USDT",
753
+ // "markPrice": "0",
754
+ // "open24h": "0",
755
+ // "high24h": "0",
756
+ // "low24h": "0",
757
+ // "volume24h": "0",
758
+ // "currencyVolume24h": "0",
759
+ // "openInterest": "0",
760
+ // "lastTradedPrice": "0",
761
+ // "lastTradedQuantity": "0",
762
+ // "lastUpdatedAt": "1714853388621"
763
+ // },
764
+ // {
765
+ // "marketCode": "DYM-USD-SWAP-LIN",
766
+ // "markPrice": "3.321",
767
+ // "open24h": "3.315",
768
+ // "high24h": "3.356",
769
+ // "low24h": "3.255",
770
+ // "volume24h": "0",
771
+ // "currencyVolume24h": "0",
772
+ // "openInterest": "1768.1",
773
+ // "lastTradedPrice": "3.543",
774
+ // "lastTradedQuantity": "1.0",
775
+ // "lastUpdatedAt": "1714853388102"
776
+ // },
777
+ // ...
778
+ // ]
779
+ // }
780
+ //
781
+ const tickers = this.safeList(response, 'data', []);
782
+ return this.parseTickers(tickers, symbols);
783
+ }
784
+ async fetchTicker(symbol, params = {}) {
785
+ /**
786
+ * @method
787
+ * @name oxfun#fetchTicker
788
+ * @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
789
+ * @see https://docs.ox.fun/?json#get-v3-tickers
790
+ * @param {string} symbol unified symbol of the market to fetch the ticker for
791
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
792
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
793
+ */
794
+ await this.loadMarkets();
795
+ const market = this.market(symbol);
796
+ const request = {
797
+ 'marketCode': market['id'],
798
+ };
799
+ const response = await this.publicGetV3Tickers(this.extend(request, params));
800
+ //
801
+ // {
802
+ // "success": true,
803
+ // "data": [
804
+ // {
805
+ // "marketCode": "BTC-USD-SWAP-LIN",
806
+ // "markPrice": "64276",
807
+ // "open24h": "63674",
808
+ // "high24h": "64607",
809
+ // "low24h": "62933",
810
+ // "volume24h": "306317655.80000",
811
+ // "currencyVolume24h": "48.06810",
812
+ // "openInterest": "72.39250",
813
+ // "lastTradedPrice": "64300.0",
814
+ // "lastTradedQuantity": "1.0",
815
+ // "lastUpdatedAt": "1714925196034"
816
+ // }
817
+ // ]
818
+ // }
819
+ //
820
+ const data = this.safeList(response, 'data', []);
821
+ const ticker = this.safeDict(data, 0, {});
822
+ return this.parseTicker(ticker, market);
823
+ }
824
+ parseTicker(ticker, market = undefined) {
825
+ //
826
+ // {
827
+ // "marketCode": "BTC-USD-SWAP-LIN",
828
+ // "markPrice": "64276",
829
+ // "open24h": "63674",
830
+ // "high24h": "64607",
831
+ // "low24h": "62933",
832
+ // "volume24h": "306317655.80000",
833
+ // "currencyVolume24h": "48.06810",
834
+ // "openInterest": "72.39250",
835
+ // "lastTradedPrice": "64300.0",
836
+ // "lastTradedQuantity": "1.0",
837
+ // "lastUpdatedAt": "1714925196034"
838
+ // }
839
+ //
840
+ const timestamp = this.safeInteger(ticker, 'lastUpdatedAt');
841
+ const marketId = this.safeString(ticker, 'marketCode');
842
+ market = this.safeMarket(marketId, market);
843
+ const symbol = market['symbol'];
844
+ const last = this.safeString(ticker, 'lastTradedPrice');
845
+ return this.safeTicker({
846
+ 'symbol': symbol,
847
+ 'timestamp': timestamp,
848
+ 'datetime': this.iso8601(timestamp),
849
+ 'high': this.safeString(ticker, 'high24h'),
850
+ 'low': this.safeString(ticker, 'low24h'),
851
+ 'bid': undefined,
852
+ 'bidVolume': undefined,
853
+ 'ask': undefined,
854
+ 'askVolume': undefined,
855
+ 'vwap': undefined,
856
+ 'open': this.safeString(ticker, 'open24h'),
857
+ 'close': last,
858
+ 'last': last,
859
+ 'previousClose': undefined,
860
+ 'change': undefined,
861
+ 'percentage': undefined,
862
+ 'average': undefined,
863
+ 'baseVolume': this.safeString(ticker, 'currencyVolume24h'),
864
+ 'quoteVolume': undefined,
865
+ 'info': ticker,
866
+ }, market);
867
+ }
868
+ async fetchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
869
+ /**
870
+ * @method
871
+ * @name oxfun#fetchOHLCV
872
+ * @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
873
+ * @see https://docs.ox.fun/?json#get-v3-candles
874
+ * @param {string} symbol unified symbol of the market to fetch OHLCV data for
875
+ * @param {string} timeframe the length of time each candle represents
876
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch (default 24 hours ago)
877
+ * @param {int} [limit] the maximum amount of candles to fetch (default 200, max 500)
878
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
879
+ * @param {int} [params.until] timestamp in ms of the latest candle to fetch (default now)
880
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
881
+ */
882
+ await this.loadMarkets();
883
+ const market = this.market(symbol);
884
+ timeframe = this.safeString(this.timeframes, timeframe, timeframe);
885
+ const request = {
886
+ 'marketCode': market['id'],
887
+ 'timeframe': timeframe,
888
+ };
889
+ if (since !== undefined) {
890
+ request['startTime'] = since; // startTime and endTime must be within 7 days of each other
891
+ }
892
+ if (limit !== undefined) {
893
+ request['limit'] = limit;
894
+ }
895
+ const until = this.safeInteger(params, 'until');
896
+ if (until !== undefined) {
897
+ request['endTime'] = until;
898
+ params = this.omit(params, 'until');
899
+ }
900
+ else if (since !== undefined) {
901
+ request['endTime'] = this.sum(since, 7 * 24 * 60 * 60 * 1000); // for the exchange not to throw an exception if since is younger than 7 days
902
+ }
903
+ const response = await this.publicGetV3Candles(this.extend(request, params));
904
+ //
905
+ // {
906
+ // "success": true,
907
+ // "timeframe": "3600s",
908
+ // "data": [
909
+ // {
910
+ // "open": "0.03240000",
911
+ // "high": "0.03240000",
912
+ // "low": "0.03240000",
913
+ // "close": "0.03240000",
914
+ // "volume": "0",
915
+ // "currencyVolume": "0",
916
+ // "openedAt": "1714906800000"
917
+ // },
918
+ // {
919
+ // "open": "0.03240000",
920
+ // "high": "0.03240000",
921
+ // "low": "0.03240000",
922
+ // "close": "0.03240000",
923
+ // "volume": "0",
924
+ // "currencyVolume": "0",
925
+ // "openedAt": "1714903200000"
926
+ // },
927
+ // ...
928
+ // ]
929
+ // }
930
+ //
931
+ const result = this.safeList(response, 'data', []);
932
+ return this.parseOHLCVs(result, market, timeframe, since, limit);
933
+ }
934
+ parseOHLCV(ohlcv, market = undefined) {
935
+ //
936
+ // {
937
+ // "open": "0.03240000",
938
+ // "high": "0.03240000",
939
+ // "low": "0.03240000",
940
+ // "close": "0.03240000",
941
+ // "volume": "0",
942
+ // "currencyVolume": "0",
943
+ // "openedAt": "1714906800000"
944
+ // }
945
+ //
946
+ return [
947
+ this.safeInteger(ohlcv, 'openedAt'),
948
+ this.safeNumber(ohlcv, 'open'),
949
+ this.safeNumber(ohlcv, 'high'),
950
+ this.safeNumber(ohlcv, 'low'),
951
+ this.safeNumber(ohlcv, 'close'),
952
+ this.safeNumber(ohlcv, 'currencyVolume'),
953
+ ];
954
+ }
955
+ async fetchOrderBook(symbol, limit = undefined, params = {}) {
956
+ /**
957
+ * @method
958
+ * @name oxfun#fetchOrderBook
959
+ * @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
960
+ * @see https://docs.ox.fun/?json#get-v3-depth
961
+ * @param {string} symbol unified symbol of the market to fetch the order book for
962
+ * @param {int} [limit] the maximum amount of order book entries to return (default 5, max 100)
963
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
964
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
965
+ */
966
+ await this.loadMarkets();
967
+ const market = this.market(symbol);
968
+ const request = {
969
+ 'marketCode': market['id'],
970
+ };
971
+ if (limit !== undefined) {
972
+ request['level'] = limit;
973
+ }
974
+ const response = await this.publicGetV3Depth(this.extend(request, params));
975
+ //
976
+ // {
977
+ // "success": true,
978
+ // "level": "5",
979
+ // "data": {
980
+ // "marketCode": "BTC-USD-SWAP-LIN",
981
+ // "lastUpdatedAt": "1714933499266",
982
+ // "asks": [
983
+ // [ 64073.0, 8.4622 ],
984
+ // [ 64092.0, 8.1912 ],
985
+ // [ 64111.0, 8.0669 ],
986
+ // [ 64130.0, 11.7195 ],
987
+ // [ 64151.0, 10.1798 ]
988
+ // ],
989
+ // "bids": [
990
+ // [ 64022.0, 10.1292 ],
991
+ // [ 64003.0, 8.1619 ],
992
+ // [ 64000.0, 1.0 ],
993
+ // [ 63984.0, 12.7724 ],
994
+ // [ 63963.0, 11.0073 ]
995
+ // ]
996
+ // }
997
+ // }
998
+ //
999
+ const data = this.safeDict(response, 'data', {});
1000
+ const timestamp = this.safeInteger(data, 'lastUpdatedAt');
1001
+ return this.parseOrderBook(data, market['symbol'], timestamp);
1002
+ }
1003
+ async fetchFundingRates(symbols = undefined, params = {}) {
1004
+ /**
1005
+ * @method
1006
+ * @name oxfun#fetchFundingRates
1007
+ * @see https://docs.ox.fun/?json#get-v3-funding-estimates
1008
+ * @description fetch the current funding rates
1009
+ * @param {string[]} symbols unified market symbols
1010
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1011
+ * @returns {Order[]} an array of [funding rate structures]{@link https://docs.ccxt.com/#/?id=funding-rate-structure}
1012
+ */
1013
+ await this.loadMarkets();
1014
+ symbols = this.marketSymbols(symbols);
1015
+ const response = await this.publicGetV3FundingEstimates(params);
1016
+ //
1017
+ // {
1018
+ // "success": true,
1019
+ // "data": [
1020
+ // {
1021
+ // "marketCode": "OX-USD-SWAP-LIN",
1022
+ // "fundingAt": "1715515200000",
1023
+ // "estFundingRate": "0.000200000"
1024
+ // },
1025
+ // {
1026
+ // "marketCode": "BTC-USD-SWAP-LIN",
1027
+ // "fundingAt": "1715515200000",
1028
+ // "estFundingRate": "0.000003"
1029
+ // },
1030
+ // ...
1031
+ // ]
1032
+ // }
1033
+ //
1034
+ const data = this.safeList(response, 'data', []);
1035
+ const result = this.parseFundingRates(data);
1036
+ return this.filterByArray(result, 'symbol', symbols);
1037
+ }
1038
+ parseFundingRate(fundingRate, market = undefined) {
1039
+ //
1040
+ // {
1041
+ // "marketCode": "OX-USD-SWAP-LIN",
1042
+ // "fundingAt": "1715515200000",
1043
+ // "estFundingRate": "0.000200000"
1044
+ // },
1045
+ //
1046
+ //
1047
+ const symbol = this.safeString(fundingRate, 'marketCode');
1048
+ market = this.market(symbol);
1049
+ const estFundingRateTimestamp = this.safeInteger(fundingRate, 'fundingAt');
1050
+ return {
1051
+ 'info': fundingRate,
1052
+ 'symbol': market['symbol'],
1053
+ 'markPrice': undefined,
1054
+ 'indexPrice': undefined,
1055
+ 'interestRate': this.parseNumber('0'),
1056
+ 'estimatedSettlePrice': undefined,
1057
+ 'timestamp': estFundingRateTimestamp,
1058
+ 'datetime': this.iso8601(estFundingRateTimestamp),
1059
+ 'fundingRate': this.safeNumber(fundingRate, 'estFundingRate'),
1060
+ 'fundingTimestamp': undefined,
1061
+ 'fundingDatetime': undefined,
1062
+ 'nextFundingRate': undefined,
1063
+ 'nextFundingTimestamp': undefined,
1064
+ 'nextFundingDatetime': undefined,
1065
+ 'previousFundingRate': undefined,
1066
+ 'previousFundingTimestamp': undefined,
1067
+ 'previousFundingDatetime': undefined,
1068
+ };
1069
+ }
1070
+ async fetchFundingRateHistory(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1071
+ /**
1072
+ * @method
1073
+ * @name oxfun#fetchFundingRateHistory
1074
+ * @description Fetches the history of funding rates
1075
+ * @see https://docs.ox.fun/?json#get-v3-funding-rates
1076
+ * @param {string} symbol unified symbol of the market to fetch trades for
1077
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch (default 24 hours ago)
1078
+ * @param {int} [limit] the maximum amount of trades to fetch (default 200, max 500)
1079
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1080
+ * @param {int} [params.until] timestamp in ms of the latest trade to fetch (default now)
1081
+ * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
1082
+ */
1083
+ await this.loadMarkets();
1084
+ const market = this.market(symbol);
1085
+ const request = {
1086
+ 'marketCode': market['id'],
1087
+ };
1088
+ if (since !== undefined) {
1089
+ request['startTime'] = since; // startTime and endTime must be within 7 days of each other
1090
+ }
1091
+ if (limit !== undefined) {
1092
+ request['limit'] = limit;
1093
+ }
1094
+ const until = this.safeInteger(params, 'until');
1095
+ if (until !== undefined) {
1096
+ request['endTime'] = until;
1097
+ params = this.omit(params, 'until');
1098
+ }
1099
+ const response = await this.publicGetV3FundingRates(this.extend(request, params));
1100
+ //
1101
+ // {
1102
+ // success: true,
1103
+ // data: [
1104
+ // {
1105
+ // marketCode: 'NEAR-USD-SWAP-LIN',
1106
+ // fundingRate: '-0.000010000',
1107
+ // createdAt: '1715428870755'
1108
+ // },
1109
+ // {
1110
+ // marketCode: 'ENA-USD-SWAP-LIN',
1111
+ // fundingRate: '0.000150000',
1112
+ // createdAt: '1715428868616'
1113
+ // },
1114
+ // ...
1115
+ // }
1116
+ //
1117
+ const data = this.safeList(response, 'data', []);
1118
+ return this.parseFundingRateHistories(data, market, since, limit);
1119
+ }
1120
+ parseFundingRateHistory(info, market = undefined) {
1121
+ //
1122
+ // {
1123
+ // success: true,
1124
+ // data: [
1125
+ // {
1126
+ // marketCode: 'NEAR-USD-SWAP-LIN',
1127
+ // fundingRate: '-0.000010000',
1128
+ // createdAt: '1715428870755'
1129
+ // },
1130
+ // {
1131
+ // marketCode: 'ENA-USD-SWAP-LIN',
1132
+ // fundingRate: '0.000150000',
1133
+ // createdAt: '1715428868616'
1134
+ // },
1135
+ // ...
1136
+ // }
1137
+ //
1138
+ const marketId = this.safeString(info, 'marketCode');
1139
+ market = this.safeMarket(marketId, market);
1140
+ const symbol = market['symbol'];
1141
+ const timestamp = this.safeInteger(info, 'createdAt');
1142
+ return {
1143
+ 'info': info,
1144
+ 'symbol': symbol,
1145
+ 'fundingRate': this.safeNumber(info, 'fundingRate'),
1146
+ 'timestamp': timestamp,
1147
+ 'datetime': this.iso8601(timestamp),
1148
+ };
1149
+ }
1150
+ async fetchFundingHistory(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1151
+ /**
1152
+ * @method
1153
+ * @name oxfun#fetchFundingHistory
1154
+ * @description fetches the history of funding payments
1155
+ * @see https://docs.ox.fun/?json#get-v3-funding
1156
+ * @param {string} symbol unified symbol of the market to fetch trades for
1157
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch (default 24 hours ago)
1158
+ * @param {int} [limit] the maximum amount of trades to fetch (default 200, max 500)
1159
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1160
+ * @param {int} [params.until] timestamp in ms of the latest trade to fetch (default now)
1161
+ * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
1162
+ */
1163
+ await this.loadMarkets();
1164
+ const market = this.market(symbol);
1165
+ const request = {
1166
+ 'marketCode': market['id'],
1167
+ };
1168
+ if (since !== undefined) {
1169
+ request['startTime'] = since; // startTime and endTime must be within 7 days of each other
1170
+ }
1171
+ if (limit !== undefined) {
1172
+ request['limit'] = limit;
1173
+ }
1174
+ const until = this.safeInteger(params, 'until');
1175
+ if (until !== undefined) {
1176
+ request['endTime'] = until;
1177
+ params = this.omit(params, 'until');
1178
+ }
1179
+ const response = await this.privateGetV3Funding(this.extend(request, params));
1180
+ //
1181
+ // {
1182
+ // success: true,
1183
+ // data: [
1184
+ // {
1185
+ // id: '966709913041305605',
1186
+ // marketCode: 'ETH-USD-SWAP-LIN',
1187
+ // payment: '-0.00430822',
1188
+ // fundingRate: '0.000014',
1189
+ // position: '0.001',
1190
+ // indexPrice: '3077.3',
1191
+ // createdAt: '1715086852890'
1192
+ // },
1193
+ // {
1194
+ // id: '966698111997509637',
1195
+ // marketCode: 'ETH-USD-SWAP-LIN',
1196
+ // payment: '-0.0067419',
1197
+ // fundingRate: '0.000022',
1198
+ // position: '0.001',
1199
+ // indexPrice: '3064.5',
1200
+ // createdAt: '1715083251516'
1201
+ // },
1202
+ // ...
1203
+ // ]
1204
+ // }
1205
+ //
1206
+ const result = this.safeList(response, 'data', []);
1207
+ return this.parseIncomes(result, market, since, limit);
1208
+ }
1209
+ parseIncome(income, market = undefined) {
1210
+ //
1211
+ // {
1212
+ // id: '966709913041305605',
1213
+ // marketCode: 'ETH-USD-SWAP-LIN',
1214
+ // payment: '-0.00430822',
1215
+ // fundingRate: '0.000014',
1216
+ // position: '0.001',
1217
+ // indexPrice: '3077.3',
1218
+ // createdAt: '1715086852890'
1219
+ // },
1220
+ //
1221
+ const marketId = this.safeString(income, 'marketCode');
1222
+ const symbol = this.safeSymbol(marketId, market);
1223
+ const amount = this.safeNumber(income, 'payment');
1224
+ const code = this.safeCurrencyCode('OX');
1225
+ const id = this.safeString(income, 'id');
1226
+ const timestamp = this.safeTimestamp(income, 'createdAt');
1227
+ const rate = this.safeNumber(income, 'fundingRate');
1228
+ return {
1229
+ 'info': income,
1230
+ 'symbol': symbol,
1231
+ 'code': code,
1232
+ 'timestamp': timestamp,
1233
+ 'datetime': this.iso8601(timestamp),
1234
+ 'id': id,
1235
+ 'amount': amount,
1236
+ 'rate': rate,
1237
+ };
1238
+ }
1239
+ async fetchLeverageTiers(symbols = undefined, params = {}) {
1240
+ /**
1241
+ * @method
1242
+ * @name oxfun#fetchLeverageTiers
1243
+ * @description retrieve information on the maximum leverage, and maintenance margin for trades of varying trade sizes, if a market has a leverage tier of 0, then the leverage tiers cannot be obtained for this market
1244
+ * @see https://docs.ox.fun/?json#get-v3-leverage-tiers
1245
+ * @param {string[]} [symbols] list of unified market symbols
1246
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1247
+ * @returns {object} a dictionary of [leverage tiers structures]{@link https://docs.ccxt.com/#/?id=leverage-tiers-structure}, indexed by market symbols
1248
+ */
1249
+ await this.loadMarkets();
1250
+ const response = await this.publicGetV3LeverageTiers(params);
1251
+ //
1252
+ // {
1253
+ // success: true,
1254
+ // data: [
1255
+ // {
1256
+ // marketCode: 'SOL-USD-SWAP-LIN',
1257
+ // tiers: [
1258
+ // {
1259
+ // tier: '1',
1260
+ // leverage: '10',
1261
+ // positionFloor: '0',
1262
+ // positionCap: '200000000',
1263
+ // initialMargin: '0.1',
1264
+ // maintenanceMargin: '0.05',
1265
+ // maintenanceAmount: '0'
1266
+ // },
1267
+ // {
1268
+ // tier: '2',
1269
+ // leverage: '5',
1270
+ // positionFloor: '200000000',
1271
+ // positionCap: '280000000',
1272
+ // initialMargin: '0.2',
1273
+ // maintenanceMargin: '0.1',
1274
+ // maintenanceAmount: '7000000'
1275
+ // },
1276
+ // {
1277
+ // tier: '3',
1278
+ // leverage: '4',
1279
+ // positionFloor: '280000000',
1280
+ // positionCap: '460000000',
1281
+ // initialMargin: '0.25',
1282
+ // maintenanceMargin: '0.125',
1283
+ // maintenanceAmount: '14000000'
1284
+ // },
1285
+ // ...
1286
+ // ]
1287
+ // },
1288
+ // ...
1289
+ // ]
1290
+ // }
1291
+ //
1292
+ const data = this.safeList(response, 'data', []);
1293
+ return this.parseLeverageTiers(data, symbols, 'marketCode');
1294
+ }
1295
+ parseMarketLeverageTiers(info, market = undefined) {
1296
+ //
1297
+ // {
1298
+ // marketCode: 'SOL-USD-SWAP-LIN',
1299
+ // tiers: [
1300
+ // {
1301
+ // tier: '1',
1302
+ // leverage: '10',
1303
+ // positionFloor: '0',
1304
+ // positionCap: '200000000',
1305
+ // initialMargin: '0.1',
1306
+ // maintenanceMargin: '0.05',
1307
+ // maintenanceAmount: '0'
1308
+ // ...
1309
+ // ]
1310
+ // },
1311
+ //
1312
+ const marketId = this.safeString(info, 'marketCode');
1313
+ market = this.safeMarket(marketId, market);
1314
+ const listOfTiers = this.safeList(info, 'tiers', []);
1315
+ const tiers = [];
1316
+ for (let j = 0; j < listOfTiers.length; j++) {
1317
+ const tier = listOfTiers[j];
1318
+ tiers.push({
1319
+ 'tier': this.safeNumber(tier, 'tier'),
1320
+ 'currency': market['settle'],
1321
+ 'minNotional': this.safeNumber(tier, 'positionFloor'),
1322
+ 'maxNotional': this.safeNumber(tier, 'positionCap'),
1323
+ 'maintenanceMarginRate': this.safeNumber(tier, 'maintenanceMargin'),
1324
+ 'maxLeverage': this.safeNumber(tier, 'leverage'),
1325
+ 'info': tier,
1326
+ });
1327
+ }
1328
+ return tiers;
1329
+ }
1330
+ async fetchTrades(symbol, since = undefined, limit = undefined, params = {}) {
1331
+ /**
1332
+ * @method
1333
+ * @name oxfun#fetchTrades
1334
+ * @description get the list of most recent trades for a particular symbol
1335
+ * @see https://docs.ox.fun/?json#get-v3-exchange-trades
1336
+ * @param {string} symbol unified symbol of the market to fetch trades for
1337
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch (default 24 hours ago)
1338
+ * @param {int} [limit] the maximum amount of trades to fetch (default 200, max 500)
1339
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1340
+ * @param {int} [params.until] timestamp in ms of the latest trade to fetch (default now)
1341
+ * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
1342
+ */
1343
+ await this.loadMarkets();
1344
+ const market = this.market(symbol);
1345
+ const request = {
1346
+ 'marketCode': market['id'],
1347
+ };
1348
+ if (since !== undefined) {
1349
+ request['startTime'] = since; // startTime and endTime must be within 7 days of each other
1350
+ }
1351
+ if (limit !== undefined) {
1352
+ request['limit'] = limit;
1353
+ }
1354
+ const until = this.safeInteger(params, 'until');
1355
+ if (until !== undefined) {
1356
+ request['endTime'] = until;
1357
+ params = this.omit(params, 'until');
1358
+ }
1359
+ else if (since !== undefined) {
1360
+ request['endTime'] = this.sum(since, 7 * 24 * 60 * 60 * 1000); // for the exchange not to throw an exception if since is younger than 7 days
1361
+ }
1362
+ const response = await this.publicGetV3ExchangeTrades(this.extend(request, params));
1363
+ //
1364
+ // {
1365
+ // "success": true,
1366
+ // "data": [
1367
+ // {
1368
+ // "marketCode": "BTC-USD-SWAP-LIN",
1369
+ // "matchPrice": "63900",
1370
+ // "matchQuantity": "1",
1371
+ // "side": "SELL",
1372
+ // "matchType": "TAKER",
1373
+ // "matchedAt": "1714934112352"
1374
+ // },
1375
+ // ...
1376
+ // ]
1377
+ // }
1378
+ //
1379
+ const data = this.safeList(response, 'data', []);
1380
+ return this.parseTrades(data, market, since, limit);
1381
+ }
1382
+ async fetchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1383
+ /**
1384
+ * @method
1385
+ * @name oxfun#fetchMyTrades
1386
+ * @description fetch all trades made by the user
1387
+ * @see https://docs.ox.fun/?json#get-v3-trades
1388
+ * @param {string} symbol unified market symbol
1389
+ * @param {int} [since] the earliest time in ms to fetch trades for
1390
+ * @param {int} [limit] the maximum amount of trades to fetch (default 200, max 500)
1391
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1392
+ * @param {int} [params.until] timestamp in ms of the latest trade to fetch (default now)
1393
+ * @returns {Trade[]} a list of [trade structures]{@link https://github.com/ccxt/ccxt/wiki/Manual#trade-structure}
1394
+ */
1395
+ await this.loadMarkets();
1396
+ const request = {};
1397
+ let market = undefined;
1398
+ if (symbol !== undefined) {
1399
+ market = this.market(symbol);
1400
+ request['marketCode'] = market['id'];
1401
+ }
1402
+ if (since !== undefined) { // startTime and endTime must be within 7 days of each other
1403
+ request['startTime'] = since;
1404
+ }
1405
+ if (limit !== undefined) {
1406
+ request['limit'] = limit;
1407
+ }
1408
+ const until = this.safeInteger(params, 'until');
1409
+ if (until !== undefined) {
1410
+ request['endTime'] = until;
1411
+ params = this.omit(params, 'until');
1412
+ }
1413
+ else if (since !== undefined) {
1414
+ request['endTime'] = this.sum(since, 7 * 24 * 60 * 60 * 1000); // for the exchange not to throw an exception if since is younger than 7 days
1415
+ }
1416
+ const response = await this.privateGetV3Trades(this.extend(request, params));
1417
+ //
1418
+ // {
1419
+ // "success": true,
1420
+ // "data": [
1421
+ // {
1422
+ // "orderId": "1000104903698",
1423
+ // "clientOrderId": "1715000260094",
1424
+ // "matchId": "400017129522773178",
1425
+ // "marketCode": "ETH-USD-SWAP-LIN",
1426
+ // "side": "BUY",
1427
+ // "matchedQuantity": "0.001",
1428
+ // "matchPrice": "3100.2",
1429
+ // "total": "310.02",
1430
+ // "orderMatchType": "MAKER",
1431
+ // "feeAsset": "OX",
1432
+ // "fee": "0.062004",
1433
+ // "source": "0",
1434
+ // "matchedAt": "1715000267420"
1435
+ // }
1436
+ // ]
1437
+ // }
1438
+ //
1439
+ const result = this.safeList(response, 'data', []);
1440
+ return this.parseTrades(result, market, since, limit);
1441
+ }
1442
+ parseTrade(trade, market = undefined) {
1443
+ //
1444
+ // public fetchTrades
1445
+ //
1446
+ // {
1447
+ // "marketCode": "BTC-USD-SWAP-LIN",
1448
+ // "matchPrice": "63900",
1449
+ // "matchQuantity": "1",
1450
+ // "side": "SELL",
1451
+ // "matchType": "TAKER",
1452
+ // "matchedAt": "1714934112352"
1453
+ // }
1454
+ //
1455
+ //
1456
+ // private fetchMyTrades
1457
+ //
1458
+ // {
1459
+ // "orderId": "1000104903698",
1460
+ // "clientOrderId": "1715000260094",
1461
+ // "matchId": "400017129522773178",
1462
+ // "marketCode": "ETH-USD-SWAP-LIN",
1463
+ // "side": "BUY",
1464
+ // "matchedQuantity": "0.001",
1465
+ // "matchPrice": "3100.2",
1466
+ // "total": "310.02",
1467
+ // "orderMatchType": "MAKER",
1468
+ // "feeAsset": "OX",
1469
+ // "fee": "0.062004",
1470
+ // "source": "0",
1471
+ // "matchedAt": "1715000267420"
1472
+ // }
1473
+ //
1474
+ const marketId = this.safeString(trade, 'marketCode');
1475
+ market = this.safeMarket(marketId, market);
1476
+ const symbol = market['symbol'];
1477
+ const timestamp = this.safeInteger(trade, 'matchedAt');
1478
+ const fee = {
1479
+ 'cost': this.safeString(trade, 'fee'),
1480
+ 'currency': this.safeCurrencyCode(this.safeString(trade, 'feeAsset')),
1481
+ };
1482
+ return this.safeTrade({
1483
+ 'id': this.safeString(trade, 'matchId'),
1484
+ 'timestamp': timestamp,
1485
+ 'datetime': this.iso8601(timestamp),
1486
+ 'symbol': symbol,
1487
+ 'type': undefined,
1488
+ 'order': this.safeString(trade, 'orderId'),
1489
+ 'side': this.safeStringLower(trade, 'side'),
1490
+ 'takerOrMaker': this.safeStringLower2(trade, 'matchType', 'orderMatchType'),
1491
+ 'price': this.safeString(trade, 'matchPrice'),
1492
+ 'amount': this.safeString2(trade, 'matchQuantity', 'matchedQuantity'),
1493
+ 'cost': undefined,
1494
+ 'fee': fee,
1495
+ 'info': trade,
1496
+ }, market);
1497
+ }
1498
+ async fetchBalance(params = {}) {
1499
+ /**
1500
+ * @method
1501
+ * @name oxfun#fetchBalance
1502
+ * @description query for balance and get the amount of funds available for trading or funds locked in orders
1503
+ * @see https://docs.ox.fun/?json#get-v3-balances
1504
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1505
+ * @param {string} [params.asset] currency id, if empty the exchange returns info about all currencies
1506
+ * @param {string} [params.subAcc] Name of sub account. If no subAcc is given, then the response contains only the account linked to the API-Key.
1507
+ * @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
1508
+ */
1509
+ await this.loadMarkets();
1510
+ const response = await this.privateGetV3Balances(params);
1511
+ //
1512
+ // {
1513
+ // "success": true,
1514
+ // "data": [
1515
+ // {
1516
+ // "accountId": "106490",
1517
+ // "name": "main",
1518
+ // "balances": [
1519
+ // {
1520
+ // "asset": "OX",
1521
+ // "total": "-7.55145065000",
1522
+ // "available": "-71.16445065000",
1523
+ // "reserved": "0",
1524
+ // "lastUpdatedAt": "1715000448946"
1525
+ // },
1526
+ // {
1527
+ // "asset": "ETH",
1528
+ // "total": "0.01",
1529
+ // "available": "0.01",
1530
+ // "reserved": "0",
1531
+ // "lastUpdatedAt": "1714914512750"
1532
+ // },
1533
+ // ...
1534
+ // ]
1535
+ // },
1536
+ // ...
1537
+ // ]
1538
+ // }
1539
+ //
1540
+ const data = this.safeList(response, 'data', []);
1541
+ let balance = data[0];
1542
+ const subAcc = this.safeString(params, 'subAcc');
1543
+ if (subAcc !== undefined) {
1544
+ for (let i = 0; i < data.length; i++) {
1545
+ const b = data[i];
1546
+ const name = this.safeString(b, 'name');
1547
+ if (name === subAcc) {
1548
+ balance = b;
1549
+ break;
1550
+ }
1551
+ }
1552
+ }
1553
+ return this.parseBalance(balance);
1554
+ }
1555
+ parseBalance(balance) {
1556
+ //
1557
+ // {
1558
+ // "accountId": "106490",
1559
+ // "name": "main",
1560
+ // "balances": [
1561
+ // {
1562
+ // "asset": "OX",
1563
+ // "total": "-7.55145065000",
1564
+ // "available": "-71.16445065000",
1565
+ // "reserved": "0",
1566
+ // "lastUpdatedAt": "1715000448946"
1567
+ // },
1568
+ // {
1569
+ // "asset": "ETH",
1570
+ // "total": "0.01",
1571
+ // "available": "0.01",
1572
+ // "reserved": "0",
1573
+ // "lastUpdatedAt": "1714914512750"
1574
+ // },
1575
+ // ...
1576
+ // ]
1577
+ // }
1578
+ //
1579
+ const result = {
1580
+ 'info': balance,
1581
+ };
1582
+ const balances = this.safeList(balance, 'balances', []);
1583
+ for (let i = 0; i < balances.length; i++) {
1584
+ const balanceEntry = balances[i];
1585
+ const currencyId = this.safeString(balanceEntry, 'asset');
1586
+ const code = this.safeCurrencyCode(currencyId);
1587
+ const account = this.account();
1588
+ account['total'] = this.safeString(balanceEntry, 'total');
1589
+ account['free'] = this.safeString(balanceEntry, 'available');
1590
+ account['used'] = this.safeString(balanceEntry, 'reserved');
1591
+ result[code] = account;
1592
+ }
1593
+ return this.safeBalance(result);
1594
+ }
1595
+ async fetchAccounts(params = {}) {
1596
+ /**
1597
+ * @method
1598
+ * @name oxfun#fetchAccounts
1599
+ * @description fetch subaccounts associated with a profile
1600
+ * @see https://docs.ox.fun/?json#get-v3-account-names
1601
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1602
+ * @returns {object} a dictionary of [account structures]{@link https://docs.ccxt.com/#/?id=account-structure} indexed by the account type
1603
+ */
1604
+ await this.loadMarkets();
1605
+ // this endpoint can only be called using API keys paired with the parent account! Returns all active subaccounts.
1606
+ const response = await this.privateGetV3AccountNames(params);
1607
+ //
1608
+ // {
1609
+ // "success": true,
1610
+ // "data": [
1611
+ // {
1612
+ // "accountId": "106526",
1613
+ // "name": "testSubAccount"
1614
+ // },
1615
+ // ...
1616
+ // ]
1617
+ // }
1618
+ //
1619
+ const data = this.safeList(response, 'data', []);
1620
+ return this.parseAccounts(data, params);
1621
+ }
1622
+ parseAccount(account) {
1623
+ //
1624
+ // {
1625
+ // "accountId": "106526",
1626
+ // "name": "testSubAccount"
1627
+ // },
1628
+ //
1629
+ return {
1630
+ 'id': this.safeString(account, 'accountId'),
1631
+ 'type': undefined,
1632
+ 'code': undefined,
1633
+ 'info': account,
1634
+ };
1635
+ }
1636
+ async transfer(code, amount, fromAccount, toAccount, params = {}) {
1637
+ /**
1638
+ * @method
1639
+ * @name oxfun#transfer
1640
+ * @description transfer currency internally between wallets on the same account
1641
+ * @see https://docs.ox.fun/?json#post-v3-transfer
1642
+ * @param {string} code unified currency code
1643
+ * @param {float} amount amount to transfer
1644
+ * @param {string} fromAccount account id to transfer from
1645
+ * @param {string} toAccount account id to transfer to
1646
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1647
+ * @returns {object} a [transfer structure]{@link https://docs.ccxt.com/#/?id=transfer-structure}
1648
+ */
1649
+ // transferring funds between sub-accounts is restricted to API keys linked to the parent account.
1650
+ await this.loadMarkets();
1651
+ const currency = this.currency(code);
1652
+ const request = {
1653
+ 'asset': currency['id'],
1654
+ 'quantity': this.currencyToPrecision(code, amount),
1655
+ 'fromAccount': fromAccount,
1656
+ 'toAccount': toAccount,
1657
+ };
1658
+ const response = await this.privatePostV3Transfer(this.extend(request, params));
1659
+ //
1660
+ // {
1661
+ // timestamp: 1715430036267,
1662
+ // datetime: '2024-05-11T12:20:36.267Z',
1663
+ // currency: 'OX',
1664
+ // amount: 10,
1665
+ // fromAccount: '106464',
1666
+ // toAccount: '106570',
1667
+ // info: {
1668
+ // asset: 'OX',
1669
+ // quantity: '10',
1670
+ // fromAccount: '106464',
1671
+ // toAccount: '106570',
1672
+ // transferredAt: '1715430036267'
1673
+ // }
1674
+ // }
1675
+ //
1676
+ const data = this.safeDict(response, 'data', {});
1677
+ return this.parseTransfer(data, currency);
1678
+ }
1679
+ async fetchTransfers(code = undefined, since = undefined, limit = undefined, params = {}) {
1680
+ /**
1681
+ * @method
1682
+ * @name oxfun#fetchTransfers
1683
+ * @description fetch a history of internal transfers made on an account
1684
+ * @see https://docs.ox.fun/?json#get-v3-transfer
1685
+ * @param {string} code unified currency code of the currency transferred
1686
+ * @param {int} [since] the earliest time in ms to fetch transfers for (default 24 hours ago)
1687
+ * @param {int} [limit] the maximum number of transfer structures to retrieve (default 50, max 200)
1688
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1689
+ * @param {int} [params.until] the latest time in ms to fetch transfers for (default time now)
1690
+ * @returns {object[]} a list of [transfer structures]{@link https://docs.ccxt.com/#/?id=transfer-structure}
1691
+ */
1692
+ // API keys linked to the parent account can get all account transfers, while API keys linked to a sub-account can only see transfers where the sub-account is either the "fromAccount" or "toAccount"
1693
+ await this.loadMarkets();
1694
+ const request = {};
1695
+ let currency = undefined;
1696
+ if (code !== undefined) {
1697
+ currency = this.currency(code);
1698
+ request['asset'] = currency['id'];
1699
+ }
1700
+ if (since !== undefined) {
1701
+ request['startTime'] = since; // startTime and endTime must be within 7 days of each other
1702
+ }
1703
+ if (limit !== undefined) {
1704
+ request['limit'] = limit;
1705
+ }
1706
+ const until = this.safeInteger(params, 'until');
1707
+ if (until !== undefined) {
1708
+ request['endTime'] = until;
1709
+ params = this.omit(params, 'until');
1710
+ }
1711
+ else if (since !== undefined) {
1712
+ request['endTime'] = this.sum(since, 7 * 24 * 60 * 60 * 1000); // for the exchange not to throw an exception if since is younger than 7 days
1713
+ }
1714
+ const response = await this.privateGetV3Transfer(this.extend(request, params));
1715
+ //
1716
+ // {
1717
+ // "success": true,
1718
+ // "data": [
1719
+ // {
1720
+ // "asset": "USDT",
1721
+ // "quantity": "5",
1722
+ // "fromAccount": "106490",
1723
+ // "toAccount": "106526",
1724
+ // "id": "966706320886267905",
1725
+ // "status": "COMPLETED",
1726
+ // "transferredAt": "1715085756708"
1727
+ // },
1728
+ // ...
1729
+ // ]
1730
+ // }
1731
+ //
1732
+ const data = this.safeList(response, 'data', []);
1733
+ return this.parseTransfers(data, currency, since, limit);
1734
+ }
1735
+ parseTransfer(transfer, currency = undefined) {
1736
+ //
1737
+ // fetchTransfers
1738
+ //
1739
+ // {
1740
+ // "asset": "USDT",
1741
+ // "quantity": "5",
1742
+ // "fromAccount": "106490",
1743
+ // "toAccount": "106526",
1744
+ // "id": "966706320886267905",
1745
+ // "status": "COMPLETED",
1746
+ // "transferredAt": "1715085756708"
1747
+ // }
1748
+ //
1749
+ const timestamp = this.safeInteger(transfer, 'transferredAt');
1750
+ const currencyId = this.safeString(transfer, 'asset');
1751
+ return {
1752
+ 'id': this.safeString(transfer, 'id'),
1753
+ 'timestamp': timestamp,
1754
+ 'datetime': this.iso8601(timestamp),
1755
+ 'currency': this.safeCurrencyCode(currencyId, currency),
1756
+ 'amount': this.safeNumber(transfer, 'quantity'),
1757
+ 'fromAccount': this.safeString(transfer, 'fromAccount'),
1758
+ 'toAccount': this.safeString(transfer, 'toAccount'),
1759
+ 'status': this.parseTransferStatus(this.safeString(transfer, 'status')),
1760
+ 'info': transfer,
1761
+ };
1762
+ }
1763
+ parseTransferStatus(status) {
1764
+ const statuses = {
1765
+ 'COMPLETED': 'ok',
1766
+ };
1767
+ return this.safeString(statuses, status, status);
1768
+ }
1769
+ async fetchDepositAddress(code, params = {}) {
1770
+ /**
1771
+ * @method
1772
+ * @name oxfun#fetchDepositAddress
1773
+ * @description fetch the deposit address for a currency associated with this account
1774
+ * @see https://docs.ox.fun/?json#get-v3-deposit-addresses
1775
+ * @param {string} code unified currency code
1776
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1777
+ * @param {string} [params.network] network for fetch deposit address
1778
+ * @returns {object} an [address structure]{@link https://docs.ccxt.com/#/?id=address-structure}
1779
+ */
1780
+ const networkCode = this.safeString(params, 'network');
1781
+ const networkId = this.networkCodeToId(networkCode, code);
1782
+ if (networkId === undefined) {
1783
+ throw new BadRequest(this.id + ' fetchDepositAddress() require network parameter');
1784
+ }
1785
+ await this.loadMarkets();
1786
+ const currency = this.currency(code);
1787
+ const request = {
1788
+ 'asset': currency['id'],
1789
+ 'network': networkId,
1790
+ };
1791
+ params = this.omit(params, 'network');
1792
+ const response = await this.privateGetV3DepositAddresses(this.extend(request, params));
1793
+ //
1794
+ // {"success":true,"data":{"address":"0x998dEc76151FB723963Bd8AFD517687b38D33dE8"}}
1795
+ //
1796
+ const data = this.safeDict(response, 'data', {});
1797
+ return this.parseDepositAddress(data, currency);
1798
+ }
1799
+ parseDepositAddress(depositAddress, currency = undefined) {
1800
+ //
1801
+ // {"address":"0x998dEc76151FB723963Bd8AFD517687b38D33dE8"}
1802
+ //
1803
+ const address = this.safeString(depositAddress, 'address');
1804
+ this.checkAddress(address);
1805
+ return {
1806
+ 'currency': currency['code'],
1807
+ 'address': address,
1808
+ 'tag': undefined,
1809
+ 'network': undefined,
1810
+ 'info': depositAddress,
1811
+ };
1812
+ }
1813
+ async fetchDeposits(code = undefined, since = undefined, limit = undefined, params = {}) {
1814
+ /**
1815
+ * @method
1816
+ * @name oxfun#fetchDeposits
1817
+ * @description fetch all deposits made to an account
1818
+ * @see https://docs.ox.fun/?json#get-v3-deposit
1819
+ * @param {string} code unified currency code of the currency transferred
1820
+ * @param {int} [since] the earliest time in ms to fetch transfers for (default 24 hours ago)
1821
+ * @param {int} [limit] the maximum number of transfer structures to retrieve (default 50, max 200)
1822
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1823
+ * @param {int} [params.until] the latest time in ms to fetch transfers for (default time now)
1824
+ * @returns {object[]} a list of [transfer structures]{@link https://docs.ccxt.com/#/?id=transfer-structure}
1825
+ */
1826
+ await this.loadMarkets();
1827
+ const request = {};
1828
+ let currency = undefined;
1829
+ if (code !== undefined) {
1830
+ currency = this.currency(code);
1831
+ request['asset'] = currency['id'];
1832
+ }
1833
+ if (since !== undefined) {
1834
+ request['startTime'] = since; // startTime and endTime must be within 7 days of each other
1835
+ }
1836
+ if (limit !== undefined) {
1837
+ request['limit'] = limit;
1838
+ }
1839
+ const until = this.safeInteger(params, 'until');
1840
+ if (until !== undefined) {
1841
+ request['endTime'] = until;
1842
+ params = this.omit(params, 'until');
1843
+ }
1844
+ const response = await this.privateGetV3Deposit(this.extend(request, params));
1845
+ //
1846
+ // {
1847
+ // "success": true,
1848
+ // "data": [
1849
+ // {
1850
+ // "asset":"USDC",
1851
+ // "network":"Ethereum",
1852
+ // "address": "0x998dEc76151FB723963Bd8AFD517687b38D33dE8",
1853
+ // "quantity":"50",
1854
+ // "id":"5914",
1855
+ // "status": "COMPLETED",
1856
+ // "txId":"0xf5e79663830a0c6f94d46638dcfbc134566c12facf1832396f81ecb55d3c75dc",
1857
+ // "creditedAt":"1714821645154"
1858
+ // }
1859
+ // ]
1860
+ // }
1861
+ //
1862
+ const data = this.safeList(response, 'data', []);
1863
+ for (let i = 0; i < data.length; i++) {
1864
+ data[i]['type'] = 'deposit';
1865
+ }
1866
+ return this.parseTransactions(data, currency, since, limit);
1867
+ }
1868
+ async fetchWithdrawals(code = undefined, since = undefined, limit = undefined, params = {}) {
1869
+ /**
1870
+ * @method
1871
+ * @name oxfun#fetchWithdrawals
1872
+ * @description fetch all withdrawals made from an account
1873
+ * @see https://docs.ox.fun/?json#get-v3-withdrawal
1874
+ * @param {string} code unified currency code of the currency transferred
1875
+ * @param {int} [since] the earliest time in ms to fetch transfers for (default 24 hours ago)
1876
+ * @param {int} [limit] the maximum number of transfer structures to retrieve (default 50, max 200)
1877
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1878
+ * @param {int} [params.until] the latest time in ms to fetch transfers for (default time now)
1879
+ * @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure}
1880
+ */
1881
+ await this.loadMarkets();
1882
+ const request = {};
1883
+ let currency = undefined;
1884
+ if (code !== undefined) {
1885
+ currency = this.currency(code);
1886
+ request['asset'] = currency['id'];
1887
+ }
1888
+ if (since !== undefined) {
1889
+ request['startTime'] = since; // startTime and endTime must be within 7 days of each other
1890
+ }
1891
+ if (limit !== undefined) {
1892
+ request['limit'] = limit;
1893
+ }
1894
+ const until = this.safeInteger(params, 'until');
1895
+ if (until !== undefined) {
1896
+ request['endTime'] = until;
1897
+ params = this.omit(params, 'until');
1898
+ }
1899
+ const response = await this.privateGetV3Withdrawal(this.extend(request, params));
1900
+ //
1901
+ // {
1902
+ // success: true,
1903
+ // data: [
1904
+ // {
1905
+ // id: '968163212989431811',
1906
+ // asset: 'OX',
1907
+ // network: 'Arbitrum',
1908
+ // address: '0x90fc1fB49a4ED8f485dd02A2a1Cf576897f6Bfc9',
1909
+ // quantity: '11.7444',
1910
+ // fee: '1.744400000',
1911
+ // status: 'COMPLETED',
1912
+ // txId: '0xe96b2d128b737fdbca927edf355cff42202e65b0fb960e64ffb9bd68c121f69f',
1913
+ // requestedAt: '1715530365450',
1914
+ // completedAt: '1715530527000'
1915
+ // }
1916
+ // ]
1917
+ // }
1918
+ //
1919
+ const data = this.safeList(response, 'data', []);
1920
+ for (let i = 0; i < data.length; i++) {
1921
+ data[i]['type'] = 'withdrawal';
1922
+ }
1923
+ return this.parseTransactions(data, currency, since, limit);
1924
+ }
1925
+ parseTransactions(transactions, currency = undefined, since = undefined, limit = undefined, params = {}) {
1926
+ let result = [];
1927
+ for (let i = 0; i < transactions.length; i++) {
1928
+ transactions[i] = this.extend(transactions[i], params);
1929
+ const transaction = this.parseTransaction(transactions[i], currency);
1930
+ result.push(transaction);
1931
+ }
1932
+ result = this.sortBy(result, 'timestamp');
1933
+ const code = (currency !== undefined) ? currency['code'] : undefined;
1934
+ return this.filterByCurrencySinceLimit(result, code, since, limit);
1935
+ }
1936
+ parseTransaction(transaction, currency = undefined) {
1937
+ //
1938
+ // fetchDeposits
1939
+ // {
1940
+ // "asset":"USDC",
1941
+ // "network":"Ethereum",
1942
+ // "address": "0x998dEc76151FB723963Bd8AFD517687b38D33dE8",
1943
+ // "quantity":"50",
1944
+ // "id":"5914",
1945
+ // "status": "COMPLETED",
1946
+ // "txId":"0xf5e79663830a0c6f94d46638dcfbc134566c12facf1832396f81ecb55d3c75dc",
1947
+ // "creditedAt":"1714821645154"
1948
+ // }
1949
+ //
1950
+ // fetchWithdrawals
1951
+ // {
1952
+ // id: '968163212989431811',
1953
+ // asset: 'OX',
1954
+ // network: 'Arbitrum',
1955
+ // address: '0x90fc1fB49a4ED8f485dd02A2a1Cf576897f6Bfc9',
1956
+ // quantity: '11.7444',
1957
+ // fee: '1.744400000',
1958
+ // status: 'COMPLETED',
1959
+ // txId: '0xe96b2d128b737fdbca927edf355cff42202e65b0fb960e64ffb9bd68c121f69f',
1960
+ // requestedAt: '1715530365450',
1961
+ // completedAt: '1715530527000'
1962
+ // }
1963
+ //
1964
+ // withdraw
1965
+ // {
1966
+ // "id": "968364664449302529",
1967
+ // "asset": "OX",
1968
+ // "network": "Arbitrum",
1969
+ // "address": "0x90fc1fB49a4ED8f485dd02A2a1Cf576897f6Bfc9",
1970
+ // "quantity": "10",
1971
+ // "externalFee": false,
1972
+ // "fee": "1.6728",
1973
+ // "status": "PENDING",
1974
+ // "requestedAt": "1715591843616"
1975
+ // }
1976
+ //
1977
+ const id = this.safeString(transaction, 'id');
1978
+ const type = this.safeString(transaction, 'type');
1979
+ transaction = this.omit(transaction, 'type');
1980
+ let address = undefined;
1981
+ let addressTo = undefined;
1982
+ let status = undefined;
1983
+ if (type === 'deposit') {
1984
+ address = this.safeString(transaction, 'address');
1985
+ status = this.parseDepositStatus(this.safeString(transaction, 'status'));
1986
+ }
1987
+ else if (type === 'withdrawal') {
1988
+ addressTo = this.safeString(transaction, 'address');
1989
+ status = this.parseWithdrawalStatus(this.safeString(transaction, 'status'));
1990
+ }
1991
+ const txid = this.safeString(transaction, 'txId');
1992
+ const currencyId = this.safeString(transaction, 'asset');
1993
+ const code = this.safeCurrencyCode(currencyId, currency);
1994
+ const network = this.safeString(transaction, 'network');
1995
+ const networkCode = this.networkIdToCode(network);
1996
+ const timestamp = this.safeInteger2(transaction, 'creditedAt', 'requestedAt');
1997
+ const amount = this.safeNumber(transaction, 'quantity');
1998
+ const feeCost = this.safeNumber(transaction, 'fee');
1999
+ let fee = undefined;
2000
+ if (feeCost !== undefined) {
2001
+ fee = {
2002
+ 'cost': feeCost,
2003
+ 'currency': code,
2004
+ };
2005
+ }
2006
+ return {
2007
+ 'info': transaction,
2008
+ 'id': id,
2009
+ 'txid': txid,
2010
+ 'timestamp': timestamp,
2011
+ 'datetime': this.iso8601(timestamp),
2012
+ 'network': networkCode,
2013
+ 'address': address,
2014
+ 'addressTo': addressTo,
2015
+ 'addressFrom': undefined,
2016
+ 'tag': undefined,
2017
+ 'tagTo': undefined,
2018
+ 'tagFrom': undefined,
2019
+ 'type': type,
2020
+ 'amount': amount,
2021
+ 'currency': code,
2022
+ 'status': status,
2023
+ 'updated': undefined,
2024
+ 'internal': undefined,
2025
+ 'comment': undefined,
2026
+ 'fee': fee,
2027
+ };
2028
+ }
2029
+ parseDepositStatus(status) {
2030
+ const statuses = {
2031
+ 'COMPLETED': 'ok',
2032
+ };
2033
+ return this.safeString(statuses, status, status);
2034
+ }
2035
+ parseWithdrawalStatus(status) {
2036
+ const statuses = {
2037
+ 'COMPLETED': 'ok',
2038
+ 'PROCESSING': 'pending',
2039
+ 'IN SWEEPING': 'pending',
2040
+ 'PENDING': 'pending',
2041
+ 'ON HOLD': 'pending',
2042
+ 'CANCELED': 'canceled',
2043
+ 'FAILED': 'failed',
2044
+ };
2045
+ return this.safeString(statuses, status, status);
2046
+ }
2047
+ async withdraw(code, amount, address, tag = undefined, params = {}) {
2048
+ /**
2049
+ * @method
2050
+ * @name bitflex#withdraw
2051
+ * @description make a withdrawal
2052
+ * @see https://docs.bitflex.com/spot#withdraw
2053
+ * @param {string} code unified currency code
2054
+ * @param {float} amount the amount to withdraw
2055
+ * @param {string} address the address to withdraw to
2056
+ * @param {string} tag
2057
+ * @param {string} [params.network] network for withdraw
2058
+ * @param {bool} [params.externalFee] if false, then the fee is taken from the quantity, also with the burn fee for asset SOLO
2059
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2060
+ *
2061
+ * EXCHANGE SPECIFIC PARAMETERS
2062
+ * @param {string} [params.tfaType] GOOGLE, or AUTHY_SECRET, or YUBIKEY, for 2FA
2063
+ * @param {string} [params.code] 2FA code
2064
+ * @returns {object} a [transaction structure]{@link https://docs.ccxt.com/#/?id=transaction-structure}
2065
+ */
2066
+ [tag, params] = this.handleWithdrawTagAndParams(tag, params);
2067
+ await this.loadMarkets();
2068
+ const currency = this.currency(code);
2069
+ const stringAmount = this.currencyToPrecision(code, amount);
2070
+ const request = {
2071
+ 'asset': currency['id'],
2072
+ 'address': address,
2073
+ 'quantity': stringAmount,
2074
+ };
2075
+ if (tag !== undefined) {
2076
+ request['memo'] = tag;
2077
+ }
2078
+ let networkCode = undefined;
2079
+ [networkCode, params] = this.handleNetworkCodeAndParams(params);
2080
+ if (networkCode !== undefined) {
2081
+ request['network'] = this.networkCodeToId(networkCode);
2082
+ }
2083
+ request['externalFee'] = false;
2084
+ const response = await this.privatePostV3Withdrawal(this.extend(request, params));
2085
+ //
2086
+ // {
2087
+ // "success": true,
2088
+ // "data": {
2089
+ // "id": "968364664449302529",
2090
+ // "asset": "OX",
2091
+ // "network": "Arbitrum",
2092
+ // "address": "0x90fc1fB49a4ED8f485dd02A2a1Cf576897f6Bfc9",
2093
+ // "quantity": "10",
2094
+ // "externalFee": false,
2095
+ // "fee": "1.6728",
2096
+ // "status": "PENDING",
2097
+ // "requestedAt": "1715591843616"
2098
+ // }
2099
+ // }
2100
+ //
2101
+ const data = this.safeDict(response, 'data', {});
2102
+ data['type'] = 'withdrawal';
2103
+ return this.parseTransaction(data, currency);
2104
+ }
2105
+ async fetchPositions(symbols = undefined, params = {}) {
2106
+ /**
2107
+ * @method
2108
+ * @name oxfun#fetchPositions
2109
+ * @description fetch all open positions
2110
+ * @see https://docs.ox.fun/?json#get-v3-positions
2111
+ * @param {string[]|undefined} symbols list of unified market symbols
2112
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2113
+ * @param {boolean} [params.subAcc]
2114
+ * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/#/?id=position-structure}
2115
+ */
2116
+ // Calling this endpoint using an API key pair linked to the parent account with the parameter "subAcc"
2117
+ // allows the caller to include positions of additional sub-accounts in the response.
2118
+ // This feature does not work when using API key pairs linked to a sub-account
2119
+ await this.loadMarkets();
2120
+ symbols = this.marketSymbols(symbols);
2121
+ const response = await this.privateGetV3Positions(params);
2122
+ //
2123
+ // {
2124
+ // "success": true,
2125
+ // "data": [
2126
+ // {
2127
+ // "accountId": "106490",
2128
+ // "name": "main",
2129
+ // "positions": [
2130
+ // {
2131
+ // "marketCode": "BTC-USD-SWAP-LIN",
2132
+ // "baseAsset": "BTC",
2133
+ // "counterAsset": "USD",
2134
+ // "position": "0.00010",
2135
+ // "entryPrice": "64300.0",
2136
+ // "markPrice": "63278",
2137
+ // "positionPnl": "-10.1900",
2138
+ // "estLiquidationPrice": "0",
2139
+ // "lastUpdatedAt": "1714915841448"
2140
+ // },
2141
+ // ...
2142
+ // ]
2143
+ // },
2144
+ // {
2145
+ // "accountId": "106526",
2146
+ // "name": "testSubAccount",
2147
+ // "positions": [
2148
+ // {
2149
+ // "marketCode": "ETH-USD-SWAP-LIN",
2150
+ // "baseAsset": "ETH",
2151
+ // "counterAsset": "USD",
2152
+ // "position": "0.001",
2153
+ // "entryPrice": "3080.5",
2154
+ // "markPrice": "3062.0",
2155
+ // "positionPnl": "-1.8500",
2156
+ // "estLiquidationPrice": "0",
2157
+ // "lastUpdatedAt": "1715089678013"
2158
+ // },
2159
+ // ...
2160
+ // ]
2161
+ // }
2162
+ // ]
2163
+ // }
2164
+ //
2165
+ const data = this.safeList(response, 'data', []);
2166
+ let allPositions = [];
2167
+ for (let i = 0; i < data.length; i++) {
2168
+ const account = data[i];
2169
+ const positions = this.safeList(account, 'positions', []);
2170
+ allPositions = this.arrayConcat(allPositions, positions);
2171
+ }
2172
+ return this.parsePositions(allPositions, symbols);
2173
+ }
2174
+ parsePosition(position, market = undefined) {
2175
+ //
2176
+ // {
2177
+ // "marketCode": "ETH-USD-SWAP-LIN",
2178
+ // "baseAsset": "ETH",
2179
+ // "counterAsset": "USD",
2180
+ // "position": "0.001",
2181
+ // "entryPrice": "3080.5",
2182
+ // "markPrice": "3062.0",
2183
+ // "positionPnl": "-1.8500",
2184
+ // "estLiquidationPrice": "0",
2185
+ // "lastUpdatedAt": "1715089678013"
2186
+ // }
2187
+ //
2188
+ const marketId = this.safeString(position, 'marketCode');
2189
+ market = this.safeMarket(marketId, market);
2190
+ return this.safePosition({
2191
+ 'info': position,
2192
+ 'id': undefined,
2193
+ 'symbol': market['symbol'],
2194
+ 'notional': undefined,
2195
+ 'marginMode': 'cross',
2196
+ 'liquidationPrice': this.safeNumber(position, 'estLiquidationPrice'),
2197
+ 'entryPrice': this.safeNumber(position, 'entryPrice'),
2198
+ 'unrealizedPnl': this.safeNumber(position, 'positionPnl'),
2199
+ 'realizedPnl': undefined,
2200
+ 'percentage': undefined,
2201
+ 'contracts': this.safeNumber(position, 'position'),
2202
+ 'contractSize': undefined,
2203
+ 'markPrice': this.safeNumber(position, 'markPrice'),
2204
+ 'lastPrice': undefined,
2205
+ 'side': undefined,
2206
+ 'hedged': undefined,
2207
+ 'timestamp': undefined,
2208
+ 'datetime': undefined,
2209
+ 'lastUpdateTimestamp': this.safeInteger(position, 'lastUpdatedAt'),
2210
+ 'maintenanceMargin': undefined,
2211
+ 'maintenanceMarginPercentage': undefined,
2212
+ 'collateral': undefined,
2213
+ 'initialMargin': undefined,
2214
+ 'initialMarginPercentage': undefined,
2215
+ 'leverage': undefined,
2216
+ 'marginRatio': undefined,
2217
+ 'stopLossPrice': undefined,
2218
+ 'takeProfitPrice': undefined,
2219
+ });
2220
+ }
2221
+ async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
2222
+ /**
2223
+ * @method
2224
+ * @name oxfun#createOrder
2225
+ * @description create a trade order
2226
+ * @see https://docs.ox.fun/?json#post-v3-orders-place
2227
+ * @param {string} symbol unified symbol of the market to create an order in
2228
+ * @param {string} type 'market', 'limit', 'STOP_LIMIT' or 'STOP_MARKET'
2229
+ * @param {string} side 'buy' or 'sell'
2230
+ * @param {float} amount how much of currency you want to trade in units of base currency
2231
+ * @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
2232
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2233
+ * @param {int} [params.clientOrderId] a unique id for the order
2234
+ * @param {int} [params.timestamp] in milliseconds. If an order reaches the matching engine and the current timestamp exceeds timestamp + recvWindow, then the order will be rejected.
2235
+ * @param {int} [params.recvWindow] in milliseconds. If an order reaches the matching engine and the current timestamp exceeds timestamp + recvWindow, then the order will be rejected. If timestamp is provided without recvWindow, then a default recvWindow of 1000ms is used.
2236
+ * @param {string} [params.responseType] FULL or ACK
2237
+ * @param {float} [params.cost] the quote quantity that can be used as an alternative for the amount for market buy orders
2238
+ * @param {float} [params.triggerPrice] The price at which a trigger order is triggered at
2239
+ * @param {float} [params.limitPrice] Limit price for the STOP_LIMIT order
2240
+ * @param {bool} [params.postOnly] if true, the order will only be posted if it will be a maker order
2241
+ * @param {string} [params.timeInForce] GTC (default), IOC, FOK, PO, MAKER_ONLY or MAKER_ONLY_REPRICE (reprices order to the best maker only price if the specified price were to lead to a taker trade)
2242
+ * @param {string} [params.selfTradePreventionMode] NONE, EXPIRE_MAKER, EXPIRE_TAKER or EXPIRE_BOTH for more info check here {@link https://docs.ox.fun/?json#self-trade-prevention-modes}
2243
+ * @param {string} [params.displayQuantity] for an iceberg order, pass both quantity and displayQuantity fields in the order request
2244
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
2245
+ */
2246
+ await this.loadMarkets();
2247
+ const request = {
2248
+ 'responseType': this.safeString(params, 'responseType', 'FULL'),
2249
+ 'timestamp': this.safeInteger(params, 'timestamp', this.milliseconds()),
2250
+ };
2251
+ params = this.omit(params, ['responseType', 'timestamp']);
2252
+ const recvWindow = this.safeInteger(params, 'recvWindow');
2253
+ if (recvWindow !== undefined) {
2254
+ request['recvWindow'] = recvWindow;
2255
+ params = this.omit(params, 'recvWindow');
2256
+ }
2257
+ const orderRequest = this.createOrderRequest(symbol, type, side, amount, price, params);
2258
+ request['orders'] = [orderRequest];
2259
+ const response = await this.privatePostV3OrdersPlace(request);
2260
+ //
2261
+ // accepted market order responseType FULL
2262
+ // {
2263
+ // "success": true,
2264
+ // "data": [
2265
+ // {
2266
+ // "notice": "OrderMatched",
2267
+ // "accountId": "106490",
2268
+ // "orderId": "1000109901865",
2269
+ // "submitted": true,
2270
+ // "clientOrderId": "0",
2271
+ // "marketCode": "OX-USDT",
2272
+ // "status": "FILLED",
2273
+ // "side": "SELL",
2274
+ // "isTriggered": false,
2275
+ // "quantity": "150.0",
2276
+ // "amount": "0.0",
2277
+ // "remainQuantity": "0.0",
2278
+ // "matchId": "100017047880451399",
2279
+ // "matchPrice": "0.01465",
2280
+ // "matchQuantity": "150.0",
2281
+ // "feeInstrumentId": "USDT",
2282
+ // "fees": "0.0015382500",
2283
+ // "orderType": "MARKET",
2284
+ // "createdAt": "1715592472236",
2285
+ // "lastMatchedAt": "1715592472200",
2286
+ // "displayQuantity": "150.0"
2287
+ // }
2288
+ // ]
2289
+ // }
2290
+ //
2291
+ // accepted limit order responseType FULL
2292
+ // {
2293
+ // "success": true,
2294
+ // "data": [
2295
+ // {
2296
+ // "notice": "OrderOpened",
2297
+ // "accountId": "106490",
2298
+ // "orderId": "1000111482406",
2299
+ // "submitted": true,
2300
+ // "clientOrderId": "0",
2301
+ // "marketCode": "ETH-USD-SWAP-LIN",
2302
+ // "status": "OPEN",
2303
+ // "side": "SELL",
2304
+ // "price": "4000.0",
2305
+ // "isTriggered": false,
2306
+ // "quantity": "0.01",
2307
+ // "amount": "0.0",
2308
+ // "orderType": "LIMIT",
2309
+ // "timeInForce": "GTC",
2310
+ // "createdAt": "1715763507682",
2311
+ // "displayQuantity": "0.01"
2312
+ // }
2313
+ // ]
2314
+ // }
2315
+ //
2316
+ // accepted order responseType ACK
2317
+ // {
2318
+ // "success": true,
2319
+ // "data": [
2320
+ // {
2321
+ // "accountId": "106490",
2322
+ // "orderId": "1000109892193",
2323
+ // "submitted": true,
2324
+ // "marketCode": "OX-USDT",
2325
+ // "side": "BUY",
2326
+ // "price": "0.01961",
2327
+ // "isTriggered": false,
2328
+ // "quantity": "100",
2329
+ // "orderType": "MARKET",
2330
+ // "timeInForce": "IOC",
2331
+ // "createdAt": "1715591529057",
2332
+ // "selfTradePreventionMode": "NONE"
2333
+ // }
2334
+ // ]
2335
+ // }
2336
+ //
2337
+ // rejected order (balance insufficient)
2338
+ // {
2339
+ // "success": true,
2340
+ // "data": [
2341
+ // {
2342
+ // "code": "710001",
2343
+ // "message": "System failure, exception thrown -> null",
2344
+ // "submitted": false,
2345
+ // "marketCode": "OX-USDT",
2346
+ // "side": "BUY",
2347
+ // "price": "0.01961",
2348
+ // "amount": "100",
2349
+ // "orderType": "MARKET",
2350
+ // "timeInForce": "IOC",
2351
+ // "createdAt": "1715591678835",
2352
+ // "source": 11,
2353
+ // "selfTradePreventionMode": "NONE"
2354
+ // }
2355
+ // ]
2356
+ // }
2357
+ //
2358
+ // rejected order (bad request)
2359
+ // {
2360
+ // "success": true,
2361
+ // "data": [
2362
+ // {
2363
+ // "code": "20044",
2364
+ // "message": "Amount is not supported for this order type",
2365
+ // "submitted": false,
2366
+ // "marketCode": "OX-USDT",
2367
+ // "side": "SELL",
2368
+ // "amount": "200",
2369
+ // "orderType": "MARKET",
2370
+ // "createdAt": "1715592079986",
2371
+ // "source": 11
2372
+ // }
2373
+ // ]
2374
+ // }
2375
+ //
2376
+ const data = this.safeList(response, 'data', []);
2377
+ const order = this.safeDict(data, 0, {});
2378
+ return this.parseOrder(order);
2379
+ }
2380
+ async createOrders(orders, params = {}) {
2381
+ /**
2382
+ * @method
2383
+ * @name oxfun#createOrders
2384
+ * @description create a list of trade orders
2385
+ * @see https://docs.ox.fun/?json#post-v3-orders-place
2386
+ * @param {Array} orders list of orders to create, each object should contain the parameters required by createOrder, namely symbol, type, side, amount, price and params
2387
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2388
+ * @param {int} [params.timestamp] *for all orders* in milliseconds. If orders reach the matching engine and the current timestamp exceeds timestamp + recvWindow, then all orders will be rejected.
2389
+ * @param {int} [params.recvWindow] *for all orders* in milliseconds. If orders reach the matching engine and the current timestamp exceeds timestamp + recvWindow, then all orders will be rejected. If timestamp is provided without recvWindow, then a default recvWindow of 1000ms is used.
2390
+ * @param {string} [params.responseType] *for all orders* FULL or ACK
2391
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
2392
+ */
2393
+ await this.loadMarkets();
2394
+ const ordersRequests = [];
2395
+ for (let i = 0; i < orders.length; i++) {
2396
+ const rawOrder = orders[i];
2397
+ const symbol = this.safeString(rawOrder, 'symbol');
2398
+ const type = this.safeString(rawOrder, 'type');
2399
+ const side = this.safeString(rawOrder, 'side');
2400
+ const amount = this.safeNumber(rawOrder, 'amount');
2401
+ const price = this.safeNumber(rawOrder, 'price');
2402
+ const orderParams = this.safeDict(rawOrder, 'params', {});
2403
+ const orderRequest = this.createOrderRequest(symbol, type, side, amount, price, orderParams);
2404
+ ordersRequests.push(orderRequest);
2405
+ }
2406
+ const request = {
2407
+ 'responseType': 'FULL',
2408
+ 'timestamp': this.milliseconds(),
2409
+ 'orders': ordersRequests,
2410
+ };
2411
+ const response = await this.privatePostV3OrdersPlace(this.extend(request, params));
2412
+ const data = this.safeList(response, 'data', []);
2413
+ return this.parseOrders(data);
2414
+ }
2415
+ createOrderRequest(symbol, type, side, amount, price = undefined, params = {}) {
2416
+ /**
2417
+ * @param {string} symbol unified symbol of the market to create an order in
2418
+ * @param {string} type 'market', 'limit', 'STOP_LIMIT' or 'STOP_MARKET'
2419
+ * @param {string} side 'buy' or 'sell'
2420
+ * @param {float} amount how much of currency you want to trade in units of base currency
2421
+ * @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
2422
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2423
+ * @param {int} [params.clientOrderId] a unique id for the order
2424
+ * @param {float} [params.cost] the quote quantity that can be used as an alternative for the amount for market buy orders
2425
+ * @param {float} [params.triggerPrice] The price at which a trigger order is triggered at
2426
+ * @param {float} [params.limitPrice] Limit price for the STOP_LIMIT order
2427
+ * @param {bool} [params.postOnly] if true, the order will only be posted if it will be a maker order
2428
+ * @param {string} [params.timeInForce] GTC (default), IOC, FOK, PO, MAKER_ONLY or MAKER_ONLY_REPRICE (reprices order to the best maker only price if the specified price were to lead to a taker trade)
2429
+ * @param {string} [params.selfTradePreventionMode] NONE, EXPIRE_MAKER, EXPIRE_TAKER or EXPIRE_BOTH for more info check here {@link https://docs.ox.fun/?json#self-trade-prevention-modes}
2430
+ * @param {string} [params.displayQuantity] for an iceberg order, pass both quantity and displayQuantity fields in the order request
2431
+ */
2432
+ const market = this.market(symbol);
2433
+ const request = {
2434
+ 'marketCode': market['id'],
2435
+ 'side': side.toUpperCase(),
2436
+ 'source': 1000,
2437
+ };
2438
+ const cost = this.safeString2(params, 'cost', 'amount');
2439
+ if (cost !== undefined) {
2440
+ request['amount'] = cost; // todo costToPrecision
2441
+ params = this.omit(params, ['cost', 'amount']);
2442
+ }
2443
+ else {
2444
+ request['quantity'] = amount; // todo amountToPrecision
2445
+ }
2446
+ const triggerPrice = this.safeString2(params, 'triggerPrice', 'stopPrice');
2447
+ let orderType = type.toUpperCase();
2448
+ if (triggerPrice !== undefined) {
2449
+ if (orderType === 'MARKET') {
2450
+ orderType = 'STOP_MARKET';
2451
+ }
2452
+ else if (orderType === 'LIMIT') {
2453
+ orderType = 'STOP_LIMIT';
2454
+ }
2455
+ request['stopPrice'] = triggerPrice; // todo priceToPrecision
2456
+ params = this.omit(params, ['triggerPrice', 'stopPrice']);
2457
+ }
2458
+ request['orderType'] = orderType;
2459
+ if (orderType === 'STOP_LIMIT') {
2460
+ request['limitPrice'] = price; // todo priceToPrecision
2461
+ }
2462
+ else if (price !== undefined) {
2463
+ request['price'] = price; // todo priceToPrecision
2464
+ }
2465
+ let postOnly = undefined;
2466
+ const isMarketOrder = (orderType === 'MARKET') || (orderType === 'STOP_MARKET');
2467
+ [postOnly, params] = this.handlePostOnly(isMarketOrder, false, params);
2468
+ const timeInForce = this.safeStringUpper(params, 'timeInForce');
2469
+ if (postOnly && (timeInForce !== 'MAKER_ONLY_REPRICE')) {
2470
+ request['timeInForce'] = 'MAKER_ONLY';
2471
+ }
2472
+ return this.extend(request, params);
2473
+ }
2474
+ async createMarketBuyOrderWithCost(symbol, cost, params = {}) {
2475
+ /**
2476
+ * @method
2477
+ * @name oxfun#createMarketBuyOrderWithCost
2478
+ * @description create a market buy order by providing the symbol and cost
2479
+ * @see https://open.big.one/docs/spot_orders.html#create-order
2480
+ * @param {string} symbol unified symbol of the market to create an order in
2481
+ * @param {float} cost how much you want to trade in units of the quote currency
2482
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2483
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
2484
+ */
2485
+ await this.loadMarkets();
2486
+ const market = this.market(symbol);
2487
+ if (!market['spot']) {
2488
+ throw new NotSupported(this.id + ' createMarketBuyOrderWithCost() supports spot orders only');
2489
+ }
2490
+ const request = {
2491
+ 'cost': cost,
2492
+ };
2493
+ return await this.createOrder(symbol, 'market', 'buy', undefined, undefined, this.extend(request, params));
2494
+ }
2495
+ async fetchOrder(id, symbol = undefined, params = {}) {
2496
+ /**
2497
+ * @method
2498
+ * @name oxfun#fetchOrder
2499
+ * @see https://docs.ox.fun/?json#get-v3-orders-status
2500
+ * @description fetches information on an order made by the user
2501
+ * @param {string} id a unique id for the order
2502
+ * @param {string} [symbol] not used by oxfun fetchOrder
2503
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2504
+ * @param {int} [params.clientOrderId] the client order id of the order
2505
+ * @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
2506
+ */
2507
+ await this.loadMarkets();
2508
+ const request = {
2509
+ 'orderId': id,
2510
+ };
2511
+ const response = await this.privateGetV3OrdersStatus(this.extend(request, params));
2512
+ //
2513
+ // {
2514
+ // "success": true,
2515
+ // "data": {
2516
+ // "orderId": "1000111762980",
2517
+ // "clientOrderId": "0",
2518
+ // "marketCode": "ETH-USD-SWAP-LIN",
2519
+ // "status": "OPEN",
2520
+ // "side": "BUY",
2521
+ // "price": "2700.0",
2522
+ // "isTriggered": false,
2523
+ // "remainQuantity": "0.01",
2524
+ // "totalQuantity": "0.01",
2525
+ // "amount": "0",
2526
+ // "displayQuantity": "0.01",
2527
+ // "cumulativeMatchedQuantity": "0",
2528
+ // "orderType": "STOP_LIMIT",
2529
+ // "timeInForce": "GTC",
2530
+ // "source": "11",
2531
+ // "createdAt": "1715794191277"
2532
+ // }
2533
+ // }
2534
+ //
2535
+ const data = this.safeDict(response, 'data', {});
2536
+ return this.parseOrder(data);
2537
+ }
2538
+ async fetchOpenOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
2539
+ /**
2540
+ * @method
2541
+ * @name oxfun#fetchOpenOrders
2542
+ * @description fetch all unfilled currently open orders
2543
+ * @see https://docs.ox.fun/?json#get-v3-orders-working
2544
+ * @param {string} symbol unified market symbol
2545
+ * @param {int} [since] the earliest time in ms to fetch open orders for
2546
+ * @param {int} [limit] the maximum number of open orders structures to retrieve
2547
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2548
+ * @param {int} [params.orderId] a unique id for the order
2549
+ * @param {int} [params.clientOrderId] the client order id of the order
2550
+ * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
2551
+ */
2552
+ await this.loadMarkets();
2553
+ const request = {};
2554
+ let market = undefined;
2555
+ if (symbol !== undefined) {
2556
+ market = this.market(symbol);
2557
+ }
2558
+ const response = await this.privateGetV3OrdersWorking(this.extend(request, params));
2559
+ const data = this.safeList(response, 'data', []);
2560
+ return this.parseOrders(data, market, since, limit);
2561
+ }
2562
+ async cancelOrder(id, symbol = undefined, params = {}) {
2563
+ /**
2564
+ * @method
2565
+ * @name oxfun#cancelOrder
2566
+ * @description cancels an open order
2567
+ * @see https://docs.ox.fun/?json#delete-v3-orders-cancel
2568
+ * @param {string} id order id
2569
+ * @param {string} symbol unified symbol of the market the order was made in
2570
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2571
+ * @param {int} [params.clientOrderId] a unique id for the order
2572
+ * @param {int} [params.timestamp] in milliseconds
2573
+ * @param {int} [params.recvWindow] in milliseconds
2574
+ * @param {string} [params.responseType] 'FULL' or 'ACK'
2575
+ * @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
2576
+ */
2577
+ if (symbol === undefined) {
2578
+ throw new ArgumentsRequired(this.id + ' cancelOrder() requires a symbol argument');
2579
+ }
2580
+ const market = this.market(symbol);
2581
+ const marketId = market['id'];
2582
+ const request = {
2583
+ 'timestamp': this.milliseconds(),
2584
+ 'responseType': 'FULL',
2585
+ };
2586
+ const orderRequest = {
2587
+ 'marketCode': marketId,
2588
+ 'orderId': id,
2589
+ };
2590
+ const clientOrderId = this.safeInteger(params, 'clientOrderId');
2591
+ if (clientOrderId !== undefined) {
2592
+ orderRequest['clientOrderId'] = clientOrderId;
2593
+ }
2594
+ request['orders'] = [orderRequest];
2595
+ const response = await this.privateDeleteV3OrdersCancel(this.extend(request, params));
2596
+ const data = this.safeList(response, 'data', []);
2597
+ const order = this.safeDict(data, 0, {});
2598
+ return this.parseOrder(order);
2599
+ }
2600
+ async cancelAllOrders(symbol = undefined, params = {}) {
2601
+ /**
2602
+ * @method
2603
+ * @name oxfun#cancelAllOrders
2604
+ * @description cancel all open orders
2605
+ * @see https://docs.ox.fun/?json#delete-v3-orders-cancel-all
2606
+ * @param {string} symbol unified market symbol, only orders in the market of this symbol are cancelled when symbol is not undefined
2607
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2608
+ * @returns {object} response from exchange
2609
+ */
2610
+ const request = {};
2611
+ if (symbol !== undefined) {
2612
+ const market = this.market(symbol);
2613
+ request['marketCode'] = market['id'];
2614
+ }
2615
+ //
2616
+ // {
2617
+ // "success": true,
2618
+ // "data": { "notice": "Orders queued for cancelation" }
2619
+ // }
2620
+ //
2621
+ // {
2622
+ // "success": true,
2623
+ // "data": { "notice": "No working orders found" }
2624
+ // }
2625
+ //
2626
+ return await this.privateDeleteV3OrdersCancelAll(this.extend(request, params));
2627
+ }
2628
+ async cancelOrders(ids, symbol = undefined, params = {}) {
2629
+ /**
2630
+ * @method
2631
+ * @name oxfun#cancelOrders
2632
+ * @description cancel multiple orders
2633
+ * @see https://docs.ox.fun/?json#delete-v3-orders-cancel
2634
+ * @param {string[]} ids order ids
2635
+ * @param {string} [symbol] unified market symbol
2636
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2637
+ * @param {int} [params.timestamp] in milliseconds
2638
+ * @param {int} [params.recvWindow] in milliseconds
2639
+ * @param {string} [params.responseType] 'FULL' or 'ACK'
2640
+ * @returns {object} an list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
2641
+ */
2642
+ if (symbol === undefined) {
2643
+ throw new ArgumentsRequired(this.id + ' cancelOrders() requires a symbol argument');
2644
+ }
2645
+ await this.loadMarkets();
2646
+ const market = this.market(symbol);
2647
+ const marketId = market['id'];
2648
+ const request = {
2649
+ 'timestamp': this.milliseconds(),
2650
+ 'responseType': 'FULL',
2651
+ };
2652
+ const orders = [];
2653
+ for (let i = 0; i < ids.length; i++) {
2654
+ const order = {
2655
+ 'marketCode': marketId,
2656
+ 'orderId': ids[i],
2657
+ };
2658
+ orders.push(order);
2659
+ }
2660
+ request['orders'] = orders;
2661
+ const response = await this.privateDeleteV3OrdersCancel(this.extend(request, params));
2662
+ const data = this.safeList(response, 'data', []);
2663
+ return this.parseOrders(data, market);
2664
+ }
2665
+ parseOrder(order, market = undefined) {
2666
+ //
2667
+ // accepted market order responseType FULL
2668
+ // {
2669
+ // "notice": "OrderMatched",
2670
+ // "accountId": "106490",
2671
+ // "orderId": "1000109901865",
2672
+ // "submitted": true,
2673
+ // "clientOrderId": "0",
2674
+ // "marketCode": "OX-USDT",
2675
+ // "status": "FILLED",
2676
+ // "side": "SELL",
2677
+ // "isTriggered": false,
2678
+ // "quantity": "150.0",
2679
+ // "amount": "0.0",
2680
+ // "remainQuantity": "0.0",
2681
+ // "matchId": "100017047880451399",
2682
+ // "matchPrice": "0.01465",
2683
+ // "matchQuantity": "150.0",
2684
+ // "feeInstrumentId": "USDT",
2685
+ // "fees": "0.0015382500",
2686
+ // "orderType": "MARKET",
2687
+ // "createdAt": "1715592472236",
2688
+ // "lastMatchedAt": "1715592472200",
2689
+ // "displayQuantity": "150.0"
2690
+ // }
2691
+ //
2692
+ // accepted limit order responseType FULL
2693
+ // {
2694
+ // "notice": "OrderOpened",
2695
+ // "accountId": "106490",
2696
+ // "orderId": "1000111482406",
2697
+ // "submitted": true,
2698
+ // "clientOrderId": "0",
2699
+ // "marketCode": "ETH-USD-SWAP-LIN",
2700
+ // "status": "OPEN",
2701
+ // "side": "SELL",
2702
+ // "price": "4000.0",
2703
+ // "isTriggered": false,
2704
+ // "quantity": "0.01",
2705
+ // "amount": "0.0",
2706
+ // "orderType": "LIMIT",
2707
+ // "timeInForce": "GTC",
2708
+ // "createdAt": "1715763507682",
2709
+ // "displayQuantity": "0.01"
2710
+ // }
2711
+ //
2712
+ // accepted order responseType ACK
2713
+ // {
2714
+ // "accountId": "106490",
2715
+ // "orderId": "1000109892193",
2716
+ // "submitted": true,
2717
+ // "marketCode": "OX-USDT",
2718
+ // "side": "BUY",
2719
+ // "price": "0.01961",
2720
+ // "isTriggered": false,
2721
+ // "quantity": "100",
2722
+ // "orderType": "MARKET",
2723
+ // "timeInForce": "IOC",
2724
+ // "createdAt": "1715591529057",
2725
+ // "selfTradePreventionMode": "NONE"
2726
+ // }
2727
+ //
2728
+ // rejected order (balance insufficient)
2729
+ // {
2730
+ // "code": "710001",
2731
+ // "message": "System failure, exception thrown -> null",
2732
+ // "submitted": false,
2733
+ // "marketCode": "OX-USDT",
2734
+ // "side": "BUY",
2735
+ // "price": "0.01961",
2736
+ // "amount": "100",
2737
+ // "orderType": "MARKET",
2738
+ // "timeInForce": "IOC",
2739
+ // "createdAt": "1715591678835",
2740
+ // "source": 11,
2741
+ // "selfTradePreventionMode": "NONE"
2742
+ // }
2743
+ //
2744
+ // rejected order (bad request)
2745
+ // {
2746
+ // "code": "20044",
2747
+ // "message": "Amount is not supported for this order type",
2748
+ // "submitted": false,
2749
+ // "marketCode": "OX-USDT",
2750
+ // "side": "SELL",
2751
+ // "amount": "200",
2752
+ // "orderType": "MARKET",
2753
+ // "createdAt": "1715592079986",
2754
+ // "source": 11
2755
+ // }
2756
+ //
2757
+ // fetchOrder
2758
+ // {
2759
+ // "orderId": "1000111762980",
2760
+ // "clientOrderId": "0",
2761
+ // "marketCode": "ETH-USD-SWAP-LIN",
2762
+ // "status": "OPEN",
2763
+ // "side": "BUY",
2764
+ // "price": "2700.0",
2765
+ // "isTriggered": false,
2766
+ // "remainQuantity": "0.01",
2767
+ // "totalQuantity": "0.01",
2768
+ // "amount": "0",
2769
+ // "displayQuantity": "0.01",
2770
+ // "cumulativeMatchedQuantity": "0",
2771
+ // "orderType": "STOP_LIMIT",
2772
+ // "timeInForce": "GTC",
2773
+ // "source": "11",
2774
+ // "createdAt": "1715794191277"
2775
+ // }
2776
+ //
2777
+ const marketId = this.safeString(order, 'marketCode');
2778
+ market = this.safeMarket(marketId, market);
2779
+ const timestamp = this.safeInteger(order, 'createdAt');
2780
+ let fee = undefined;
2781
+ const feeCurrency = this.safeString(order, 'feeInstrumentId');
2782
+ if (feeCurrency !== undefined) {
2783
+ fee = {
2784
+ 'currency': this.safeCurrencyCode(feeCurrency),
2785
+ 'cost': this.safeNumber(order, 'fees'),
2786
+ };
2787
+ }
2788
+ let status = this.safeString(order, 'status');
2789
+ const code = this.safeInteger(order, 'code'); // rejected orders have code of the error
2790
+ if (code !== undefined) {
2791
+ status = 'rejected';
2792
+ }
2793
+ const triggerPrice = this.safeString(order, 'stopPrice');
2794
+ return this.safeOrder({
2795
+ 'id': this.safeString(order, 'orderId'),
2796
+ 'clientOrderId': this.safeString(order, 'clientOrderId'),
2797
+ 'timestamp': timestamp,
2798
+ 'datetime': this.iso8601(timestamp),
2799
+ 'lastTradeTimestamp': this.safeInteger(order, 'lastMatchedAt'),
2800
+ 'lastUpdateTimestamp': this.safeInteger(order, 'lastModifiedAt'),
2801
+ 'status': this.parseOrderStatus(status),
2802
+ 'symbol': market['symbol'],
2803
+ 'type': this.parseOrderType(this.safeString(order, 'orderType')),
2804
+ 'timeInForce': this.parseOrderTimeInForce(this.safeString(order, 'timeInForce')),
2805
+ 'side': this.safeStringLower(order, 'side'),
2806
+ 'price': this.safeStringN(order, ['price', 'matchPrice', 'limitPrice']),
2807
+ 'average': undefined,
2808
+ 'amount': this.safeString2(order, 'totalQuantity', 'quantity'),
2809
+ 'filled': this.safeString2(order, 'cumulativeMatchedQuantity', 'matchQuantity'),
2810
+ 'remaining': this.safeString(order, 'remainQuantity'),
2811
+ 'triggerPrice': triggerPrice,
2812
+ 'stopLossPrice': triggerPrice,
2813
+ 'cost': this.omitZero(this.safeString(order, 'amount')),
2814
+ 'trades': undefined,
2815
+ 'fee': fee,
2816
+ 'info': order,
2817
+ }, market);
2818
+ }
2819
+ parseOrderStatus(status) {
2820
+ const statuses = {
2821
+ 'OPEN': 'open',
2822
+ 'PARTIALLY_FILLED': 'open',
2823
+ 'PARTIAL_FILL': 'open',
2824
+ 'FILLED': 'closed',
2825
+ 'CANCELED': 'canceled',
2826
+ 'CANCELED_BY_USER': 'canceled',
2827
+ 'CANCELED_BY_MAKER_ONLY': 'rejected',
2828
+ 'CANCELED_BY_FOK': 'rejected',
2829
+ 'CANCELED_ALL_BY_IOC': 'rejected',
2830
+ 'CANCELED_PARTIAL_BY_IOC': 'canceled',
2831
+ 'CANCELED_BY_SELF_TRADE_PROTECTION': 'rejected',
2832
+ };
2833
+ return this.safeString(statuses, status, status);
2834
+ }
2835
+ parseOrderType(type) {
2836
+ const types = {
2837
+ 'LIMIT': 'limit',
2838
+ 'STOP_LIMIT': 'limit',
2839
+ 'MARKET': 'market',
2840
+ 'STOP_MARKET': 'market',
2841
+ };
2842
+ return this.safeString(types, type, type);
2843
+ }
2844
+ parseOrderTimeInForce(type) {
2845
+ const types = {
2846
+ 'GTC': 'GTC',
2847
+ 'IOC': 'IOC',
2848
+ 'FOK': 'FOK',
2849
+ 'MAKER_ONLY': 'PO',
2850
+ 'MAKER_ONLY_REPRICE': 'PO',
2851
+ };
2852
+ return this.safeString(types, type, type);
2853
+ }
2854
+ sign(path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
2855
+ const baseUrl = this.urls['api'][api];
2856
+ let url = baseUrl + '/' + path;
2857
+ let queryString = '';
2858
+ if (method === 'GET') {
2859
+ queryString = this.urlencode(params);
2860
+ if (queryString.length !== 0) {
2861
+ url += '?' + queryString;
2862
+ }
2863
+ }
2864
+ if (api === 'private') {
2865
+ this.checkRequiredCredentials();
2866
+ const timestamp = this.milliseconds();
2867
+ const isoDatetime = this.iso8601(timestamp);
2868
+ const datetimeParts = isoDatetime.split('.');
2869
+ const datetime = datetimeParts[0];
2870
+ const nonce = this.nonce();
2871
+ const urlParts = baseUrl.split('//');
2872
+ if ((method === 'POST') || (method === 'DELETE')) {
2873
+ body = this.json(params);
2874
+ queryString = body;
2875
+ }
2876
+ const msgString = datetime + '\n' + nonce.toString() + '\n' + method + '\n' + urlParts[1] + '\n/' + path + '\n' + queryString;
2877
+ const signature = this.hmac(this.encode(msgString), this.encode(this.secret), sha256, 'base64');
2878
+ headers = {
2879
+ 'Content-Type': 'application/json',
2880
+ 'AccessKey': this.apiKey,
2881
+ 'Timestamp': datetime,
2882
+ 'Signature': signature,
2883
+ 'Nonce': nonce,
2884
+ };
2885
+ }
2886
+ return { 'url': url, 'method': method, 'body': body, 'headers': headers };
2887
+ }
2888
+ handleErrors(code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
2889
+ if (response === undefined) {
2890
+ return undefined;
2891
+ }
2892
+ if (code !== 200) {
2893
+ const responseCode = this.safeString(response, 'code', undefined);
2894
+ const feedback = this.id + ' ' + body;
2895
+ this.throwBroadlyMatchedException(this.exceptions['broad'], body, feedback);
2896
+ this.throwExactlyMatchedException(this.exceptions['exact'], responseCode, feedback);
2897
+ throw new ExchangeError(feedback);
2898
+ }
2899
+ return undefined;
2900
+ }
2901
+ }