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