ccxt 4.4.77 → 4.4.80

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 (154) hide show
  1. package/README.md +8 -10
  2. package/dist/ccxt.browser.min.js +7 -7
  3. package/dist/cjs/ccxt.js +8 -4
  4. package/dist/cjs/src/abstract/ace.js +1 -1
  5. package/dist/cjs/src/abstract/apex.js +9 -0
  6. package/dist/cjs/src/ace.js +1 -1
  7. package/dist/cjs/src/apex.js +1949 -0
  8. package/dist/cjs/src/ascendex.js +25 -4
  9. package/dist/cjs/src/base/Exchange.js +42 -2
  10. package/dist/cjs/src/binance.js +9 -1
  11. package/dist/cjs/src/bingx.js +3 -3
  12. package/dist/cjs/src/bitfinex.js +64 -36
  13. package/dist/cjs/src/bitget.js +191 -138
  14. package/dist/cjs/src/bitmart.js +7 -2
  15. package/dist/cjs/src/bitmex.js +16 -8
  16. package/dist/cjs/src/bitopro.js +5 -1
  17. package/dist/cjs/src/bitrue.js +2 -1
  18. package/dist/cjs/src/bitso.js +1 -1
  19. package/dist/cjs/src/bitteam.js +2 -0
  20. package/dist/cjs/src/bitvavo.js +28 -10
  21. package/dist/cjs/src/btcalpha.js +1 -1
  22. package/dist/cjs/src/btcmarkets.js +1 -1
  23. package/dist/cjs/src/btcturk.js +1 -1
  24. package/dist/cjs/src/bybit.js +32 -16
  25. package/dist/cjs/src/cex.js +1 -1
  26. package/dist/cjs/src/coinbase.js +18 -2
  27. package/dist/cjs/src/coincatch.js +68 -0
  28. package/dist/cjs/src/coinex.js +1 -0
  29. package/dist/cjs/src/coinlist.js +1 -0
  30. package/dist/cjs/src/coinone.js +1 -0
  31. package/dist/cjs/src/delta.js +4 -0
  32. package/dist/cjs/src/deribit.js +1 -0
  33. package/dist/cjs/src/hitbtc.js +3 -0
  34. package/dist/cjs/src/hollaex.js +1 -0
  35. package/dist/cjs/src/htx.js +7 -3
  36. package/dist/cjs/src/huobijp.js +1 -0
  37. package/dist/cjs/src/hyperliquid.js +14 -4
  38. package/dist/cjs/src/kraken.js +2 -0
  39. package/dist/cjs/src/mexc.js +50 -57
  40. package/dist/cjs/src/okx.js +1 -1
  41. package/dist/cjs/src/phemex.js +2 -1
  42. package/dist/cjs/src/poloniex.js +2 -1
  43. package/dist/cjs/src/pro/apex.js +1043 -0
  44. package/dist/cjs/src/pro/binance.js +3 -3
  45. package/dist/cjs/src/pro/coinbase.js +45 -68
  46. package/dist/cjs/src/pro/gate.js +27 -2
  47. package/dist/cjs/src/pro/hollaex.js +2 -2
  48. package/dist/cjs/src/pro/p2b.js +2 -2
  49. package/dist/cjs/src/pro/tradeogre.js +283 -0
  50. package/dist/cjs/src/pro/upbit.js +43 -0
  51. package/dist/cjs/src/probit.js +1 -0
  52. package/dist/cjs/src/static_dependencies/zklink/zklink-sdk-web.js +2639 -0
  53. package/dist/cjs/src/timex.js +2 -2
  54. package/dist/cjs/src/tradeogre.js +2 -1
  55. package/dist/cjs/src/upbit.js +277 -67
  56. package/dist/cjs/src/whitebit.js +66 -12
  57. package/dist/cjs/src/woo.js +3 -1
  58. package/dist/cjs/src/xt.js +9 -0
  59. package/js/ccxt.d.ts +11 -5
  60. package/js/ccxt.js +8 -4
  61. package/js/src/abstract/apex.d.ts +34 -0
  62. package/js/src/abstract/bitmart.d.ts +1 -0
  63. package/js/src/apex.d.ts +333 -0
  64. package/js/src/apex.js +1945 -0
  65. package/js/src/ascendex.d.ts +3 -3
  66. package/js/src/ascendex.js +25 -4
  67. package/js/src/base/Exchange.d.ts +2 -0
  68. package/js/src/base/Exchange.js +42 -1
  69. package/js/src/binance.d.ts +7 -7
  70. package/js/src/binance.js +9 -1
  71. package/js/src/bingx.js +3 -3
  72. package/js/src/bitfinex.d.ts +3 -3
  73. package/js/src/bitfinex.js +64 -36
  74. package/js/src/bitflyer.d.ts +2 -2
  75. package/js/src/bitget.d.ts +2 -0
  76. package/js/src/bitget.js +191 -138
  77. package/js/src/bitmart.d.ts +5 -4
  78. package/js/src/bitmart.js +7 -2
  79. package/js/src/bitmex.d.ts +3 -3
  80. package/js/src/bitmex.js +16 -8
  81. package/js/src/bitopro.js +5 -1
  82. package/js/src/bitrue.js +2 -1
  83. package/js/src/bitso.js +1 -1
  84. package/js/src/bitteam.js +2 -0
  85. package/js/src/bitvavo.js +28 -10
  86. package/js/src/btcalpha.js +1 -1
  87. package/js/src/btcmarkets.js +1 -1
  88. package/js/src/btcturk.js +1 -1
  89. package/js/src/bybit.js +32 -16
  90. package/js/src/cex.js +1 -1
  91. package/js/src/coinbase.d.ts +4 -4
  92. package/js/src/coinbase.js +18 -2
  93. package/js/src/coinbaseexchange.d.ts +1 -1
  94. package/js/src/coincatch.d.ts +11 -0
  95. package/js/src/coincatch.js +68 -0
  96. package/js/src/coinex.js +1 -0
  97. package/js/src/coinlist.js +1 -0
  98. package/js/src/coinone.js +1 -0
  99. package/js/src/cryptocom.d.ts +4 -4
  100. package/js/src/delta.js +4 -0
  101. package/js/src/deribit.d.ts +4 -4
  102. package/js/src/deribit.js +1 -0
  103. package/js/src/derive.d.ts +3 -3
  104. package/js/src/digifinex.d.ts +4 -4
  105. package/js/src/hitbtc.js +3 -0
  106. package/js/src/hollaex.js +1 -0
  107. package/js/src/htx.d.ts +4 -4
  108. package/js/src/htx.js +7 -3
  109. package/js/src/huobijp.js +1 -0
  110. package/js/src/hyperliquid.d.ts +1 -0
  111. package/js/src/hyperliquid.js +14 -4
  112. package/js/src/kraken.d.ts +3 -3
  113. package/js/src/kraken.js +2 -0
  114. package/js/src/krakenfutures.d.ts +2 -2
  115. package/js/src/kucoinfutures.d.ts +5 -5
  116. package/js/src/mexc.d.ts +1 -0
  117. package/js/src/mexc.js +50 -57
  118. package/js/src/okx.js +1 -1
  119. package/js/src/oxfun.d.ts +3 -3
  120. package/js/src/phemex.d.ts +3 -3
  121. package/js/src/phemex.js +2 -1
  122. package/js/src/poloniex.d.ts +3 -3
  123. package/js/src/poloniex.js +2 -1
  124. package/js/src/pro/apex.d.ts +160 -0
  125. package/js/src/pro/apex.js +1038 -0
  126. package/js/src/pro/binance.js +3 -3
  127. package/js/src/pro/coinbase.d.ts +4 -3
  128. package/js/src/pro/coinbase.js +45 -66
  129. package/js/src/pro/gate.js +27 -2
  130. package/js/src/pro/hollaex.js +2 -2
  131. package/js/src/pro/p2b.js +2 -2
  132. package/js/src/pro/tradeogre.d.ts +49 -0
  133. package/js/src/pro/tradeogre.js +278 -0
  134. package/js/src/pro/upbit.d.ts +16 -1
  135. package/js/src/pro/upbit.js +43 -0
  136. package/js/src/probit.js +1 -0
  137. package/js/src/static_dependencies/zklink/zklink-sdk-web.d.ts +1279 -0
  138. package/js/src/static_dependencies/zklink/zklink-sdk-web.js +4276 -0
  139. package/js/src/timex.js +2 -2
  140. package/js/src/tradeogre.js +2 -1
  141. package/js/src/upbit.d.ts +75 -23
  142. package/js/src/upbit.js +277 -67
  143. package/js/src/vertex.d.ts +3 -3
  144. package/js/src/whitebit.js +66 -12
  145. package/js/src/woo.d.ts +4 -4
  146. package/js/src/woo.js +3 -1
  147. package/js/src/woofipro.d.ts +4 -4
  148. package/js/src/xt.d.ts +4 -4
  149. package/js/src/xt.js +9 -0
  150. package/package.json +2 -2
  151. package/js/src/abstract/ace.d.ts +0 -18
  152. package/js/src/ace.d.ts +0 -158
  153. package/js/src/ace.js +0 -1175
  154. /package/js/src/abstract/{ace.js → apex.js} +0 -0
package/js/src/apex.js ADDED
@@ -0,0 +1,1945 @@
1
+ // ---------------------------------------------------------------------------
2
+ import { Precise } from './base/Precise.js';
3
+ import Exchange from './abstract/apex.js';
4
+ import { TICK_SIZE, TRUNCATE } from './base/functions/number.js';
5
+ import { sha256 } from './static_dependencies/noble-hashes/sha256.js';
6
+ import { ArgumentsRequired, BadRequest, ExchangeError, InvalidOrder, RateLimitExceeded } from './base/errors.js';
7
+ // ---------------------------------------------------------------------------
8
+ /**
9
+ * @class apex
10
+ * @augments Exchange
11
+ */
12
+ export default class apex extends Exchange {
13
+ describe() {
14
+ return this.deepExtend(super.describe(), {
15
+ 'id': 'apex',
16
+ 'name': 'Apex',
17
+ 'countries': [],
18
+ 'version': 'v3',
19
+ 'rateLimit': 20,
20
+ 'certified': false,
21
+ 'pro': true,
22
+ 'dex': true,
23
+ 'has': {
24
+ 'CORS': undefined,
25
+ 'spot': false,
26
+ 'margin': false,
27
+ 'swap': true,
28
+ 'future': false,
29
+ 'option': false,
30
+ 'addMargin': false,
31
+ 'borrowCrossMargin': false,
32
+ 'borrowIsolatedMargin': false,
33
+ 'cancelAllOrders': true,
34
+ 'cancelAllOrdersAfter': false,
35
+ 'cancelOrder': true,
36
+ 'cancelOrders': false,
37
+ 'cancelOrdersForSymbols': false,
38
+ 'closeAllPositions': false,
39
+ 'closePosition': false,
40
+ 'createMarketBuyOrderWithCost': false,
41
+ 'createMarketOrderWithCost': false,
42
+ 'createMarketSellOrderWithCost': false,
43
+ 'createOrder': true,
44
+ 'createOrders': false,
45
+ 'createPostOnlyOrder': true,
46
+ 'createReduceOnlyOrder': true,
47
+ 'createStopOrder': true,
48
+ 'createTriggerOrder': true,
49
+ 'editOrder': false,
50
+ 'fetchAccounts': true,
51
+ 'fetchBalance': true,
52
+ 'fetchBorrowInterest': false,
53
+ 'fetchBorrowRateHistories': false,
54
+ 'fetchBorrowRateHistory': false,
55
+ 'fetchCanceledAndClosedOrders': false,
56
+ 'fetchCanceledOrders': false,
57
+ 'fetchClosedOrders': false,
58
+ 'fetchCrossBorrowRate': false,
59
+ 'fetchCrossBorrowRates': false,
60
+ 'fetchCurrencies': true,
61
+ 'fetchDepositAddress': false,
62
+ 'fetchDepositAddresses': false,
63
+ 'fetchDeposits': false,
64
+ 'fetchDepositWithdrawFee': false,
65
+ 'fetchDepositWithdrawFees': false,
66
+ 'fetchFundingHistory': true,
67
+ 'fetchFundingRate': false,
68
+ 'fetchFundingRateHistory': true,
69
+ 'fetchFundingRates': false,
70
+ 'fetchIndexOHLCV': false,
71
+ 'fetchIsolatedBorrowRate': false,
72
+ 'fetchIsolatedBorrowRates': false,
73
+ 'fetchLedger': false,
74
+ 'fetchLeverage': false,
75
+ 'fetchLeverageTiers': false,
76
+ 'fetchLiquidations': false,
77
+ 'fetchMarginMode': false,
78
+ 'fetchMarketLeverageTiers': false,
79
+ 'fetchMarkets': true,
80
+ 'fetchMarkOHLCV': false,
81
+ 'fetchMyLiquidations': false,
82
+ 'fetchMyTrades': true,
83
+ 'fetchOHLCV': true,
84
+ 'fetchOpenInterest': true,
85
+ 'fetchOpenInterestHistory': false,
86
+ 'fetchOpenInterests': false,
87
+ 'fetchOpenOrders': true,
88
+ 'fetchOrder': true,
89
+ 'fetchOrderBook': true,
90
+ 'fetchOrders': true,
91
+ 'fetchOrderTrades': true,
92
+ 'fetchPosition': false,
93
+ 'fetchPositionMode': false,
94
+ 'fetchPositions': true,
95
+ 'fetchPositionsRisk': false,
96
+ 'fetchPremiumIndexOHLCV': false,
97
+ 'fetchTicker': true,
98
+ 'fetchTickers': true,
99
+ 'fetchTime': true,
100
+ 'fetchTrades': true,
101
+ 'fetchTradingFee': false,
102
+ 'fetchTradingFees': false,
103
+ 'fetchTransfer': true,
104
+ 'fetchTransfers': true,
105
+ 'fetchWithdrawal': false,
106
+ 'fetchWithdrawals': false,
107
+ 'reduceMargin': false,
108
+ 'repayCrossMargin': false,
109
+ 'repayIsolatedMargin': false,
110
+ 'sandbox': true,
111
+ 'setLeverage': true,
112
+ 'setMarginMode': false,
113
+ 'setPositionMode': false,
114
+ 'transfer': false,
115
+ 'withdraw': false,
116
+ },
117
+ 'timeframes': {
118
+ '1m': '1',
119
+ '5m': '5',
120
+ '15m': '15',
121
+ '30m': '30',
122
+ '1h': '60',
123
+ '2h': '120',
124
+ '4h': '240',
125
+ '6h': '360',
126
+ '12h': '720',
127
+ '1d': 'D',
128
+ '1w': 'W',
129
+ '1M': 'M',
130
+ },
131
+ 'hostname': 'omni.apex.exchange',
132
+ 'urls': {
133
+ 'logo': 'https://github.com/user-attachments/assets/fef8f2f7-4265-46aa-965e-33a91881cb00',
134
+ 'api': {
135
+ 'public': 'https://{hostname}/api',
136
+ 'private': 'https://{hostname}/api',
137
+ },
138
+ 'test': {
139
+ 'public': 'https://testnet.omni.apex.exchange/api',
140
+ 'private': 'https://testnet.omni.apex.exchange/api',
141
+ },
142
+ 'www': 'https://apex.exchange/',
143
+ 'doc': 'https://api-docs.pro.apex.exchange',
144
+ 'fees': 'https://apex-pro.gitbook.io/apex-pro/apex-omni-live-now/trading-perpetual-contracts/trading-fees',
145
+ 'referral': 'https://omni.apex.exchange/trade',
146
+ },
147
+ 'api': {
148
+ 'public': {
149
+ 'get': {
150
+ 'v3/symbols': 1,
151
+ 'v3/history-funding': 1,
152
+ 'v3/ticker': 1,
153
+ 'v3/klines': 1,
154
+ 'v3/trades': 1,
155
+ 'v3/depth': 1,
156
+ 'v3/time': 1,
157
+ 'v3/data/all-ticker-info': 1,
158
+ },
159
+ },
160
+ 'private': {
161
+ 'get': {
162
+ 'v3/account': 1,
163
+ 'v3/account-balance': 1,
164
+ 'v3/fills': 1,
165
+ 'v3/order-fills': 1,
166
+ 'v3/order': 1,
167
+ 'v3/history-orders': 1,
168
+ 'v3/order-by-client-order-id': 1,
169
+ 'v3/funding': 1,
170
+ 'v3/historical-pnl': 1,
171
+ 'v3/open-orders': 1,
172
+ 'v3/transfers': 1,
173
+ 'v3/transfer': 1,
174
+ },
175
+ 'post': {
176
+ 'v3/delete-open-orders': 1,
177
+ 'v3/delete-client-order-id': 1,
178
+ 'v3/delete-order': 1,
179
+ 'v3/order': 1,
180
+ 'v3/set-initial-margin-rate': 1,
181
+ 'v3/transfer-out': 1,
182
+ 'v3/contract-transfer-out': 1,
183
+ },
184
+ },
185
+ },
186
+ 'httpExceptions': {
187
+ '403': RateLimitExceeded, // Forbidden -- You request too many times
188
+ },
189
+ 'exceptions': {
190
+ // Uncodumented explanation of error strings:
191
+ // - oc_diff: order cost needed to place this order
192
+ // - new_oc: total order cost of open orders including the order you are trying to open
193
+ // - ob: order balance - the total cost of current open orders
194
+ // - ab: available balance
195
+ 'exact': {
196
+ '20006': 'apikey sign error',
197
+ '20016': 'request para error',
198
+ '10001': BadRequest,
199
+ },
200
+ 'broad': {
201
+ 'ORDER_PRICE_MUST_GREETER_ZERO': InvalidOrder,
202
+ 'ORDER_POSSIBLE_LEAD_TO_ACCOUNT_LIQUIDATED': InvalidOrder,
203
+ 'ORDER_WITH_THIS_PRICE_CANNOT_REDUCE_POSITION_ONLY': InvalidOrder,
204
+ },
205
+ },
206
+ 'fees': {
207
+ 'swap': {
208
+ 'taker': this.parseNumber('0.0005'),
209
+ 'maker': this.parseNumber('0.0002'),
210
+ },
211
+ },
212
+ 'requiredCredentials': {
213
+ 'apiKey': true,
214
+ 'secret': true,
215
+ 'walletAddress': false,
216
+ 'privateKey': false,
217
+ 'password': true,
218
+ },
219
+ 'precisionMode': TICK_SIZE,
220
+ 'commonCurrencies': {},
221
+ 'options': {
222
+ 'defaultType': 'swap',
223
+ 'defaultSlippage': 0.05,
224
+ 'brokerId': '6956',
225
+ },
226
+ 'features': {
227
+ 'default': {
228
+ 'sandbox': true,
229
+ 'createOrder': {
230
+ 'marginMode': false,
231
+ 'triggerPrice': true,
232
+ 'triggerPriceType': undefined,
233
+ 'triggerDirection': false,
234
+ 'stopLossPrice': false,
235
+ 'takeProfitPrice': false,
236
+ 'attachedStopLossTakeProfit': undefined,
237
+ 'timeInForce': {
238
+ 'IOC': true,
239
+ 'FOK': true,
240
+ 'PO': true,
241
+ 'GTD': true,
242
+ },
243
+ 'hedged': false,
244
+ 'selfTradePrevention': false,
245
+ 'trailing': true,
246
+ 'leverage': false,
247
+ 'marketBuyByCost': false,
248
+ 'marketBuyRequiresPrice': false,
249
+ 'iceberg': false,
250
+ },
251
+ 'createOrders': undefined,
252
+ 'fetchMyTrades': {
253
+ 'marginMode': false,
254
+ 'limit': 500,
255
+ 'daysBack': 100000,
256
+ 'untilDays': 100000,
257
+ 'symbolRequired': false,
258
+ },
259
+ 'fetchOrder': {
260
+ 'marginMode': false,
261
+ 'trigger': false,
262
+ 'trailing': false,
263
+ 'symbolRequired': false,
264
+ },
265
+ 'fetchOpenOrders': {
266
+ 'marginMode': false,
267
+ 'limit': undefined,
268
+ 'trigger': false,
269
+ 'trailing': false,
270
+ 'symbolRequired': false,
271
+ },
272
+ 'fetchOrders': {
273
+ 'marginMode': false,
274
+ 'limit': 100,
275
+ 'daysBack': 100000,
276
+ 'untilDays': 100000,
277
+ 'trigger': false,
278
+ 'trailing': false,
279
+ 'symbolRequired': false,
280
+ },
281
+ 'fetchClosedOrders': undefined,
282
+ 'fetchOHLCV': {
283
+ 'limit': 200,
284
+ },
285
+ },
286
+ 'swap': {
287
+ 'linear': {
288
+ 'extends': 'default',
289
+ },
290
+ 'inverse': undefined,
291
+ },
292
+ },
293
+ });
294
+ }
295
+ /**
296
+ * @method
297
+ * @name apex#fetchTime
298
+ * @description fetches the current integer timestamp in milliseconds from the exchange server
299
+ * @see https://api-docs.pro.apex.exchange/#publicapi-v3-for-omni-get-system-time-v3
300
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
301
+ * @returns {int} the current integer timestamp in milliseconds from the exchange server
302
+ */
303
+ async fetchTime(params = {}) {
304
+ const response = await this.publicGetV3Time(params);
305
+ const data = this.safeDict(response, 'data', {});
306
+ //
307
+ // {
308
+ // "data": {
309
+ // "time": 1738837534454
310
+ // }
311
+ // }
312
+ return this.safeInteger(data, 'time');
313
+ }
314
+ parseBalance(response) {
315
+ //
316
+ // {
317
+ // "totalEquityValue": "100.000000",
318
+ // "availableBalance": "100.000000",
319
+ // "initialMargin": "100.000000",
320
+ // "maintenanceMargin": "100.000000",
321
+ // "symbolToOraclePrice": {
322
+ // "BTC-USDC": {
323
+ // "oraclePrice": "20000",
324
+ // "createdTime": 124566
325
+ // }
326
+ // }
327
+ // }
328
+ //
329
+ const timestamp = this.milliseconds();
330
+ const result = {
331
+ 'info': response,
332
+ 'timestamp': timestamp,
333
+ 'datetime': this.iso8601(timestamp),
334
+ };
335
+ const code = 'USDT';
336
+ const account = this.account();
337
+ account['free'] = this.safeString(response, 'availableBalance');
338
+ account['total'] = this.safeString(response, 'totalEquityValue');
339
+ result[code] = account;
340
+ return this.safeBalance(result);
341
+ }
342
+ /**
343
+ * @method
344
+ * @name apex#fetchBalance
345
+ * @description query for account info
346
+ * @see https://api-docs.pro.apex.exchange/#privateapi-v3-for-omni-get-retrieve-user-account-balance
347
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
348
+ * @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
349
+ */
350
+ async fetchBalance(params = {}) {
351
+ await this.loadMarkets();
352
+ const response = await this.privateGetV3AccountBalance(params);
353
+ const data = this.safeDict(response, 'data', {});
354
+ return this.parseBalance(data);
355
+ }
356
+ parseAccount(account) {
357
+ const accountId = this.safeString(account, 'id', '0');
358
+ return {
359
+ 'id': accountId,
360
+ 'type': undefined,
361
+ 'code': undefined,
362
+ 'info': account,
363
+ };
364
+ }
365
+ /**
366
+ * @method
367
+ * @name apex#fetchAccount
368
+ * @description query for balance and get the amount of funds available for trading or funds locked in orders
369
+ * @see https://api-docs.pro.apex.exchange/#privateapi-v3-for-omni-get-retrieve-user-account-data
370
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
371
+ * @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
372
+ */
373
+ async fetchAccount(params = {}) {
374
+ await this.loadMarkets();
375
+ const response = await this.privateGetV3Account(params);
376
+ const data = this.safeDict(response, 'data', {});
377
+ return this.parseAccount(data);
378
+ }
379
+ /**
380
+ * @method
381
+ * @name apex#fetchCurrencies
382
+ * @description fetches all available currencies on an exchange
383
+ * @see https://api-docs.pro.apex.exchange/#publicapi-v3-for-omni-get-all-config-data-v3
384
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
385
+ * @returns {object} an associative dictionary of currencies
386
+ */
387
+ async fetchCurrencies(params = {}) {
388
+ const response = await this.publicGetV3Symbols(params);
389
+ const data = this.safeDict(response, 'data', {});
390
+ const spotConfig = this.safeDict(data, 'spotConfig', {});
391
+ const multiChain = this.safeDict(spotConfig, 'multiChain', {});
392
+ // "spotConfig": {
393
+ // "assets": [
394
+ // {
395
+ // "tokenId": "141",
396
+ // "token": "USDT",
397
+ // "displayName": "Tether USD Coin",
398
+ // "decimals": 18,
399
+ // "showStep": "0.01",
400
+ // "iconUrl": "https://static-pro.apex.exchange/chains/chain_tokens/Ethereum/Ethereum_USDT.svg",
401
+ // "l2WithdrawFee": "0",
402
+ // "enableCollateral": true,
403
+ // "enableCrossCollateral": false,
404
+ // "crossCollateralDiscountRate": null,
405
+ // "isGray": false
406
+ // }
407
+ // ],
408
+ // "multiChain": {
409
+ // "chains": [
410
+ // {
411
+ // "chain": "Arbitrum One",
412
+ // "chainId": "9",
413
+ // "chainType": "0",
414
+ // "l1ChainId": "42161",
415
+ // "chainIconUrl": "https://static-pro.apex.exchange/chains/chain_logos/Arbitrum.svg",
416
+ // "contractAddress": "0x3169844a120c0f517b4eb4a750c08d8518c8466a",
417
+ // "swapContractAddress": "0x9e07b6Aef1bbD9E513fc2Eb8873e311E80B4f855",
418
+ // "stopDeposit": false,
419
+ // "feeLess": false,
420
+ // "gasLess": false,
421
+ // "gasToken": "ETH",
422
+ // "dynamicFee": true,
423
+ // "gasTokenDecimals": 18,
424
+ // "feeGasLimit": 300000,
425
+ // "blockTimeSeconds": 2,
426
+ // "rpcUrl": "https://arb.pro.apex.exchange",
427
+ // "minSwapUsdtAmount": "",
428
+ // "maxSwapUsdtAmount": "",
429
+ // "webRpcUrl": "https://arb.pro.apex.exchange",
430
+ // "webTxUrl": "https://arbiscan.io/tx/",
431
+ // "backupRpcUrl": "https://arb-mainnet.g.alchemy.com/v2/rGlYUbRHtUav5mfeThCPtsV9GLPt2Xq5",
432
+ // "txConfirm": 20,
433
+ // "withdrawGasFeeLess": false,
434
+ // "tokens": [
435
+ // {
436
+ // "decimals": 6,
437
+ // "iconUrl": "https://static-pro.apex.exchange/chains/chain_tokens/Arbitrum/Arbitrum_USDT.svg",
438
+ // "token": "USDT",
439
+ // "tokenAddress": "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9",
440
+ // "pullOff": false,
441
+ // "withdrawEnable": true,
442
+ // "slippage": "",
443
+ // "isDefaultToken": false,
444
+ // "displayToken": "USDT",
445
+ // "needResetApproval": true,
446
+ // "minFee": "2",
447
+ // "maxFee": "40",
448
+ // "feeRate": "0.0001",
449
+ // "maxWithdraw": "",
450
+ // "minDeposit": "",
451
+ // "minWithdraw": "",
452
+ // "maxFastWithdrawAmount": "40000",
453
+ // "minFastWithdrawAmount": "1",
454
+ // "isGray": false
455
+ // },
456
+ // {
457
+ // "decimals": 6,
458
+ // "iconUrl": "https://static-pro.apex.exchange/chains/chain_tokens/Arbitrum/Arbitrum_USDC.svg",
459
+ // "token": "USDC",
460
+ // "tokenAddress": "0xaf88d065e77c8cc2239327c5edb3a432268e5831",
461
+ // "pullOff": false,
462
+ // "withdrawEnable": true,
463
+ // "slippage": "",
464
+ // "isDefaultToken": false,
465
+ // "displayToken": "USDC",
466
+ // "needResetApproval": true,
467
+ // "minFee": "2",
468
+ // "maxFee": "20",
469
+ // "feeRate": "0.0001",
470
+ // "maxWithdraw": "",
471
+ // "minDeposit": "",
472
+ // "minWithdraw": "",
473
+ // "maxFastWithdrawAmount": "1",
474
+ // "minFastWithdrawAmount": "1",
475
+ // "isGray": false
476
+ // }
477
+ // ]
478
+ // }
479
+ // ]
480
+ // }
481
+ const rows = this.safeList(spotConfig, 'assets', []);
482
+ const chains = this.safeList(multiChain, 'chains', []);
483
+ const result = {};
484
+ for (let i = 0; i < rows.length; i++) {
485
+ const currency = rows[i];
486
+ const currencyId = this.safeString(currency, 'token');
487
+ const code = this.safeCurrencyCode(currencyId);
488
+ const name = this.safeString(currency, 'displayName');
489
+ const networks = {};
490
+ let minPrecision = undefined;
491
+ let minWithdrawFeeString = undefined;
492
+ let minWithdrawString = undefined;
493
+ let deposit = false;
494
+ let withdraw = false;
495
+ for (let j = 0; j < chains.length; j++) {
496
+ const chain = chains[j];
497
+ const tokens = this.safeList(chain, 'tokens', []);
498
+ for (let f = 0; f < tokens.length; f++) {
499
+ const token = tokens[f];
500
+ const tokenName = this.safeString(token, 'token');
501
+ if (tokenName === currencyId) {
502
+ const networkId = this.safeString(chain, 'chainId');
503
+ const networkCode = this.networkIdToCode(networkId);
504
+ const precision = this.parseNumber(this.parsePrecision(this.safeString(currency, 'decimals')));
505
+ minPrecision = (minPrecision === undefined) ? precision : Math.min(minPrecision, precision);
506
+ const depositAllowed = !this.safeBool(chain, 'stopDeposit');
507
+ deposit = (depositAllowed) ? depositAllowed : deposit;
508
+ const withdrawAllowed = this.safeBool(token, 'withdrawEnable');
509
+ withdraw = (withdrawAllowed) ? withdrawAllowed : withdraw;
510
+ minWithdrawFeeString = this.safeString(token, 'minFee');
511
+ minWithdrawString = this.safeString(token, 'minWithdraw');
512
+ const minNetworkDepositString = this.safeString(chain, 'depositMin');
513
+ networks[networkCode] = {
514
+ 'info': chain,
515
+ 'id': networkId,
516
+ 'network': networkCode,
517
+ 'active': depositAllowed && withdrawAllowed,
518
+ 'deposit': depositAllowed,
519
+ 'withdraw': withdrawAllowed,
520
+ 'fee': this.parseNumber(minWithdrawFeeString),
521
+ 'precision': precision,
522
+ 'limits': {
523
+ 'withdraw': {
524
+ 'min': this.parseNumber(minWithdrawString),
525
+ 'max': undefined,
526
+ },
527
+ 'deposit': {
528
+ 'min': this.parseNumber(minNetworkDepositString),
529
+ 'max': undefined,
530
+ },
531
+ },
532
+ };
533
+ }
534
+ }
535
+ }
536
+ result[code] = {
537
+ 'info': currency,
538
+ 'code': code,
539
+ 'id': currencyId,
540
+ 'type': 'crypto',
541
+ 'name': name,
542
+ 'active': deposit && withdraw,
543
+ 'deposit': deposit,
544
+ 'withdraw': withdraw,
545
+ 'fee': this.parseNumber(minWithdrawFeeString),
546
+ 'precision': minPrecision,
547
+ 'limits': {
548
+ 'amount': {
549
+ 'min': undefined,
550
+ 'max': undefined,
551
+ },
552
+ 'withdraw': {
553
+ 'min': this.parseNumber(minWithdrawString),
554
+ 'max': undefined,
555
+ },
556
+ 'deposit': {
557
+ 'min': undefined,
558
+ 'max': undefined,
559
+ },
560
+ },
561
+ 'networks': networks,
562
+ };
563
+ }
564
+ return result;
565
+ }
566
+ /**
567
+ * @method
568
+ * @name apex#fetchMarkets
569
+ * @description retrieves data on all markets for apex
570
+ * @see https://api-docs.pro.apex.exchange/#publicapi-v3-for-omni-get-all-config-data-v3
571
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
572
+ * @returns {object[]} an array of objects representing market data
573
+ */
574
+ async fetchMarkets(params = {}) {
575
+ const response = await this.publicGetV3Symbols(params);
576
+ const data = this.safeDict(response, 'data', {});
577
+ const contractConfig = this.safeDict(data, 'contractConfig', {});
578
+ const perpetualContract = this.safeList(contractConfig, 'perpetualContract', []);
579
+ // {
580
+ // "perpetualContract":[
581
+ // {
582
+ // "baselinePositionValue": "50000.0000",
583
+ // "crossId": 30002,
584
+ // "crossSymbolId": 10,
585
+ // "crossSymbolName": "BTCUSDT",
586
+ // "digitMerge": "0.1,0.2,0.4,1,2",
587
+ // "displayMaxLeverage": "100",
588
+ // "displayMinLeverage": "1",
589
+ // "enableDisplay": true,
590
+ // "enableOpenPosition": true,
591
+ // "enableTrade": true,
592
+ // "fundingImpactMarginNotional": "6",
593
+ // "fundingInterestRate": "0.0003",
594
+ // "incrementalInitialMarginRate": "0.00250",
595
+ // "incrementalMaintenanceMarginRate": "0.00100",
596
+ // "incrementalPositionValue": "50000.0000",
597
+ // "initialMarginRate": "0.01",
598
+ // "maintenanceMarginRate": "0.005",
599
+ // "maxOrderSize": "50",
600
+ // "maxPositionSize": "100",
601
+ // "minOrderSize": "0.0010",
602
+ // "maxMarketPriceRange": "0.025",
603
+ // "settleAssetId": "USDT",
604
+ // "baseTokenId": "BTC",
605
+ // "stepSize": "0.001",
606
+ // "symbol": "BTC-USDT",
607
+ // "symbolDisplayName": "BTCUSDT",
608
+ // "tickSize": "0.1",
609
+ // "maxMaintenanceMarginRate": "0.5000",
610
+ // "maxPositionValue": "5000000.0000",
611
+ // "tagIconUrl": "https://static-pro.apex.exchange/icon/LABLE_HOT.svg",
612
+ // "tag": "HOT",
613
+ // "riskTip": false,
614
+ // "defaultInitialMarginRate": "0.05",
615
+ // "klineStartTime": 0,
616
+ // "maxMarketSizeBuffer": "0.98",
617
+ // "enableFundingSettlement": true,
618
+ // "indexPriceDecimals": 2,
619
+ // "indexPriceVarRate": "0.001",
620
+ // "openPositionOiLimitRate": "0.05",
621
+ // "fundingMaxRate": "0.000234",
622
+ // "fundingMinRate": "-0.000234",
623
+ // "fundingMaxValue": "",
624
+ // "enableFundingMxValue": true,
625
+ // "l2PairId": "50001",
626
+ // "settleTimeStamp": 0,
627
+ // "isPrelaunch": false,
628
+ // "riskLimitConfig": {},
629
+ // "category": "L1"
630
+ // }
631
+ // ]
632
+ // }
633
+ return this.parseMarkets(perpetualContract);
634
+ }
635
+ parseMarket(market) {
636
+ const id = this.safeString(market, 'symbol');
637
+ const id2 = this.safeString(market, 'crossSymbolName');
638
+ const quoteId = this.safeString(market, 'l2PairId');
639
+ const baseId = this.safeString(market, 'baseTokenId');
640
+ const quote = this.safeString(market, 'settleAssetId');
641
+ const base = this.safeCurrencyCode(baseId);
642
+ const settleId = this.safeString(market, 'settleAssetId');
643
+ const settle = this.safeCurrencyCode(settleId);
644
+ const symbol = baseId + '/' + quote + ':' + settle;
645
+ const expiry = 0;
646
+ const takerFee = this.parseNumber('0.0002');
647
+ const makerFee = this.parseNumber('0.0005');
648
+ return this.safeMarketStructure({
649
+ 'id': id,
650
+ 'id2': id2,
651
+ 'symbol': symbol,
652
+ 'base': base,
653
+ 'quote': quote,
654
+ 'settle': settle,
655
+ 'baseId': baseId,
656
+ 'quoteId': quoteId,
657
+ 'settleId': settleId,
658
+ 'type': 'swap',
659
+ 'spot': false,
660
+ 'margin': undefined,
661
+ 'swap': true,
662
+ 'future': false,
663
+ 'option': false,
664
+ 'active': this.safeBool(market, 'enableTrade'),
665
+ 'contract': true,
666
+ 'linear': true,
667
+ 'inverse': false,
668
+ 'taker': takerFee,
669
+ 'maker': makerFee,
670
+ 'contractSize': this.safeNumber(market, 'minOrderSize'),
671
+ 'expiry': (expiry === 0) ? undefined : expiry,
672
+ 'expiryDatetime': (expiry === 0) ? undefined : this.iso8601(expiry),
673
+ 'strike': undefined,
674
+ 'optionType': undefined,
675
+ 'precision': {
676
+ 'amount': this.safeNumber(market, 'stepSize'),
677
+ 'price': this.safeNumber(market, 'tickSize'),
678
+ },
679
+ 'limits': {
680
+ 'leverage': {
681
+ 'min': this.safeNumber(market, 'displayMinLeverage'),
682
+ 'max': this.safeNumber(market, 'displayMaxLeverage'),
683
+ },
684
+ 'amount': {
685
+ 'min': this.safeNumber(market, 'minOrderSize'),
686
+ 'max': this.safeNumber(market, 'maxOrderSize'),
687
+ },
688
+ 'price': {
689
+ 'min': undefined,
690
+ 'max': undefined,
691
+ },
692
+ 'cost': {
693
+ 'min': undefined,
694
+ 'max': undefined,
695
+ },
696
+ },
697
+ 'created': undefined,
698
+ 'info': market,
699
+ });
700
+ }
701
+ parseTicker(ticker, market = undefined) {
702
+ //
703
+ // {
704
+ // "symbol": "BTCUSDT",
705
+ // "price24hPcnt": "0.450141",
706
+ // "lastPrice": "43511.50",
707
+ // "highPrice24h": "43513.50",
708
+ // "lowPrice24h": "29996.00",
709
+ // "markPrice": "43513.50",
710
+ // "indexPrice": "40828.94",
711
+ // "openInterest": "2036854775808",
712
+ // "turnover24h": "5626085.23749999",
713
+ // "volume24h": "169.317",
714
+ // "fundingRate": "0",
715
+ // "predictedFundingRate": "0",
716
+ // "nextFundingTime": "10:00:00",
717
+ // "tradeCount": 100
718
+ // }
719
+ //
720
+ const timestamp = this.milliseconds();
721
+ const marketId = this.safeString(ticker, 'symbol');
722
+ market = this.safeMarket(marketId, market);
723
+ const symbol = this.safeSymbol(marketId, market);
724
+ const last = this.safeString(ticker, 'lastPrice');
725
+ const percentage = this.safeString(ticker, 'price24hPcnt');
726
+ const quoteVolume = this.safeString(ticker, 'turnover24h');
727
+ const baseVolume = this.safeString(ticker, 'volume24h');
728
+ const high = this.safeString(ticker, 'highPrice24h');
729
+ const low = this.safeString(ticker, 'lowPrice24h');
730
+ return this.safeTicker({
731
+ 'symbol': symbol,
732
+ 'timestamp': timestamp,
733
+ 'datetime': this.iso8601(timestamp),
734
+ 'high': high,
735
+ 'low': low,
736
+ 'bid': undefined,
737
+ 'bidVolume': undefined,
738
+ 'ask': undefined,
739
+ 'askVolume': undefined,
740
+ 'vwap': undefined,
741
+ 'open': undefined,
742
+ 'close': last,
743
+ 'last': last,
744
+ 'previousClose': undefined,
745
+ 'change': undefined,
746
+ 'percentage': percentage,
747
+ 'average': undefined,
748
+ 'baseVolume': baseVolume,
749
+ 'quoteVolume': quoteVolume,
750
+ 'markPrice': this.safeString(ticker, 'markPrice'),
751
+ 'indexPrice': this.safeString(ticker, 'indexPrice'),
752
+ 'info': ticker,
753
+ }, market);
754
+ }
755
+ /**
756
+ * @method
757
+ * @name apex#fetchTicker
758
+ * @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
759
+ * @see https://api-docs.pro.apex.exchange/#publicapi-v3-for-omni-get-ticker-data-v3
760
+ * @param {string} symbol unified symbol of the market to fetch the ticker for
761
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
762
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
763
+ */
764
+ async fetchTicker(symbol, params = {}) {
765
+ await this.loadMarkets();
766
+ const market = this.market(symbol);
767
+ const request = {
768
+ 'symbol': market['id2'],
769
+ };
770
+ const response = await this.publicGetV3Ticker(this.extend(request, params));
771
+ const tickers = this.safeList(response, 'data', []);
772
+ const rawTicker = this.safeDict(tickers, 0, {});
773
+ return this.parseTicker(rawTicker, market);
774
+ }
775
+ /**
776
+ * @method
777
+ * @name apex#fetchTickers
778
+ * @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
779
+ * @see https://api-docs.pro.apex.exchange/#publicapi-v3-for-omni-get-ticker-data-v3
780
+ * @param {string} symbols unified symbol of the market to fetch the ticker for
781
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
782
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
783
+ */
784
+ async fetchTickers(symbols = undefined, params = {}) {
785
+ await this.loadMarkets();
786
+ const response = await this.publicGetV3DataAllTickerInfo(params);
787
+ const tickers = this.safeList(response, 'data', []);
788
+ return this.parseTickers(tickers, symbols);
789
+ }
790
+ /**
791
+ * @method
792
+ * @name apex#fetchOHLCV
793
+ * @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
794
+ * @see https://api-docs.pro.apex.exchange/#publicapi-v3-for-omni-get-candlestick-chart-data-v3
795
+ * @param {string} symbol unified symbol of the market to fetch OHLCV data for
796
+ * @param {string} timeframe the length of time each candle represents
797
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
798
+ * @param {int} [limit] the maximum amount of candles to fetch
799
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
800
+ * @param {int} [params.until] timestamp in ms of the latest candle to fetch
801
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
802
+ */
803
+ async fetchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
804
+ await this.loadMarkets();
805
+ const market = this.market(symbol);
806
+ let request = {
807
+ 'interval': this.safeString(this.timeframes, timeframe, timeframe),
808
+ 'symbol': market['id2'],
809
+ };
810
+ if (limit === undefined) {
811
+ limit = 200; // default is 200 when requested with `since`
812
+ }
813
+ request['limit'] = limit; // max 200, default 200
814
+ [request, params] = this.handleUntilOption('end', request, params);
815
+ if (since !== undefined) {
816
+ request['start'] = since;
817
+ }
818
+ const response = await this.publicGetV3Klines(this.extend(request, params));
819
+ const data = this.safeDict(response, 'data', {});
820
+ const OHLCVs = this.safeList(data, market['id2'], []);
821
+ return this.parseOHLCVs(OHLCVs, market, timeframe, since, limit);
822
+ }
823
+ parseOHLCV(ohlcv, market = undefined) {
824
+ //
825
+ // {
826
+ // "start": 1647511440000,
827
+ // "symbol": "BTC-USD",
828
+ // "interval": "1",
829
+ // "low": "40000",
830
+ // "high": "45000",
831
+ // "open": "45000",
832
+ // "close": "40000",
833
+ // "volume": "1.002",
834
+ // "turnover": "3"
835
+ // } {"s":"BTCUSDT","i":"1","t":1741265880000,"c":"90235","h":"90235","l":"90156","o":"90156","v":"0.052","tr":"4690.4466"}
836
+ //
837
+ return [
838
+ this.safeIntegerN(ohlcv, ['start', 't']),
839
+ this.safeNumberN(ohlcv, ['open', 'o']),
840
+ this.safeNumberN(ohlcv, ['high', 'h']),
841
+ this.safeNumberN(ohlcv, ['low', 'l']),
842
+ this.safeNumberN(ohlcv, ['close', 'c']),
843
+ this.safeNumberN(ohlcv, ['volume', 'v']),
844
+ ];
845
+ }
846
+ /**
847
+ * @method
848
+ * @name apex#fetchOrderBook
849
+ * @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
850
+ * @see https://api-docs.pro.apex.exchange/#publicapi-v3-for-omni-get-market-depth-v3
851
+ * @param {string} symbol unified symbol of the market to fetch the order book for
852
+ * @param {int} [limit] the maximum amount of order book entries to return
853
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
854
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
855
+ */
856
+ async fetchOrderBook(symbol, limit = undefined, params = {}) {
857
+ await this.loadMarkets();
858
+ const market = this.market(symbol);
859
+ const request = {
860
+ 'symbol': market['id2'],
861
+ };
862
+ if (limit === undefined) {
863
+ limit = 100; // default is 200 when requested with `since`
864
+ }
865
+ request['limit'] = limit; // max 100, default 100
866
+ const response = await this.publicGetV3Depth(this.extend(request, params));
867
+ //
868
+ // {
869
+ // "a": [
870
+ // [
871
+ // "96576.3",
872
+ // "0.399"
873
+ // ],
874
+ // [
875
+ // "96577.6",
876
+ // "0.106"
877
+ // ]
878
+ // ],
879
+ // "b": [
880
+ // [
881
+ // "96565.2",
882
+ // "0.131"
883
+ // ],
884
+ // [
885
+ // "96565.1",
886
+ // "0.038"
887
+ // ]
888
+ // ],
889
+ // "s": "BTCUSDT",
890
+ // "u": 18665465
891
+ // }
892
+ //
893
+ const data = this.safeDict(response, 'data', {});
894
+ const timestamp = this.milliseconds();
895
+ const orderbook = this.parseOrderBook(data, market['symbol'], timestamp, 'b', 'a');
896
+ orderbook['nonce'] = this.safeInteger(data, 'u');
897
+ return orderbook;
898
+ }
899
+ /**
900
+ * @method
901
+ * @name apex#fetchTrades
902
+ * @description get the list of most recent trades for a particular symbol
903
+ * @see https://api-docs.pro.apex.exchange/#publicapi-v3-for-omni-get-newest-trading-data-v3
904
+ * @param {string} symbol unified symbol of the market to fetch trades for
905
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
906
+ * @param {int} [limit] the maximum amount of trades to fetch
907
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
908
+ * @param {int} [params.until] the latest time in ms to fetch trades for
909
+ * @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times
910
+ * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
911
+ */
912
+ async fetchTrades(symbol, since = undefined, limit = undefined, params = {}) {
913
+ await this.loadMarkets();
914
+ const market = this.market(symbol);
915
+ const request = {
916
+ 'symbol': market['id2'],
917
+ };
918
+ if (limit === undefined) {
919
+ limit = 500; // default is 50
920
+ }
921
+ request['limit'] = limit;
922
+ const response = await this.publicGetV3Trades(this.extend(request, params));
923
+ //
924
+ // [
925
+ // {
926
+ // "i": "993f7f85-9215-5723-9078-2186ae140847",
927
+ // "p": "96534.3",
928
+ // "S": "Sell",
929
+ // "v": "0.261",
930
+ // "s": "BTCUSDT",
931
+ // "T": 1739118072710
932
+ // },
933
+ // {
934
+ // "i": "c947c9cf-8c18-5784-89c3-91bdf86ddde8",
935
+ // "p": "96513.5",
936
+ // "S": "Sell",
937
+ // "v": "0.042",
938
+ // "s": "BTCUSDT",
939
+ // "T": 1739118075944
940
+ // }
941
+ // ]
942
+ //
943
+ const trades = this.safeList(response, 'data', []);
944
+ return this.parseTrades(trades, market, since, limit);
945
+ }
946
+ parseTrade(trade, market = undefined) {
947
+ //
948
+ // [
949
+ // {
950
+ // "i": "993f7f85-9215-5723-9078-2186ae140847",
951
+ // "p": "96534.3",
952
+ // "S": "Sell",
953
+ // "v": "0.261",
954
+ // "s": "BTCUSDT",
955
+ // "T": 1739118072710
956
+ // }
957
+ // ]
958
+ //
959
+ const marketId = this.safeStringN(trade, ['s', 'symbol']);
960
+ market = this.safeMarket(marketId, market);
961
+ const id = this.safeStringN(trade, ['i', 'id']);
962
+ const timestamp = this.safeIntegerN(trade, ['t', 'T', 'createdAt']);
963
+ const priceString = this.safeStringN(trade, ['p', 'price']);
964
+ const amountString = this.safeStringN(trade, ['v', 'size']);
965
+ const side = this.safeStringLowerN(trade, ['S', 'side']);
966
+ const type = this.safeStringN(trade, ['type']);
967
+ const fee = this.safeStringN(trade, ['fee']);
968
+ return this.safeTrade({
969
+ 'info': trade,
970
+ 'id': id,
971
+ 'order': undefined,
972
+ 'timestamp': timestamp,
973
+ 'datetime': this.iso8601(timestamp),
974
+ 'symbol': market['symbol'],
975
+ 'type': type,
976
+ 'takerOrMaker': undefined,
977
+ 'side': side,
978
+ 'price': priceString,
979
+ 'amount': amountString,
980
+ 'cost': undefined,
981
+ 'fee': fee,
982
+ }, market);
983
+ }
984
+ /**
985
+ * @method
986
+ * @name apex#fetchOpenInterest
987
+ * @description retrieves the open interest of a contract trading pair
988
+ * @see https://api-docs.pro.apex.exchange/#publicapi-v3-for-omni-get-ticker-data-v3
989
+ * @param {string} symbol unified CCXT market symbol
990
+ * @param {object} [params] exchange specific parameters
991
+ * @returns {object} an open interest structure{@link https://docs.ccxt.com/#/?id=open-interest-structure}
992
+ */
993
+ async fetchOpenInterest(symbol, params = {}) {
994
+ await this.loadMarkets();
995
+ const market = this.market(symbol);
996
+ const request = {
997
+ 'symbol': market['id2'],
998
+ };
999
+ const response = await this.publicGetV3Ticker(this.extend(request, params));
1000
+ const tickers = this.safeList(response, 'data', []);
1001
+ const rawTicker = this.safeDict(tickers, 0, {});
1002
+ return this.parseOpenInterest(rawTicker, market);
1003
+ }
1004
+ parseOpenInterest(interest, market = undefined) {
1005
+ //
1006
+ // {
1007
+ // "symbol": "BTCUSDT",
1008
+ // "price24hPcnt": "0.450141",
1009
+ // "lastPrice": "43511.50",
1010
+ // "highPrice24h": "43513.50",
1011
+ // "lowPrice24h": "29996.00",
1012
+ // "markPrice": "43513.50",
1013
+ // "indexPrice": "40828.94",
1014
+ // "openInterest": "2036854775808",
1015
+ // "turnover24h": "5626085.23749999",
1016
+ // "volume24h": "169.317",
1017
+ // "fundingRate": "0",
1018
+ // "predictedFundingRate": "0",
1019
+ // "nextFundingTime": "10:00:00",
1020
+ // "tradeCount": 100
1021
+ // }
1022
+ //
1023
+ const timestamp = this.milliseconds();
1024
+ const marketId = this.safeString(interest, 'symbol');
1025
+ market = this.safeMarket(marketId, market);
1026
+ const symbol = this.safeSymbol(marketId, market);
1027
+ return this.safeOpenInterest({
1028
+ 'symbol': symbol,
1029
+ 'openInterestAmount': this.safeString(interest, 'openInterest'),
1030
+ 'openInterestValue': undefined,
1031
+ 'timestamp': timestamp,
1032
+ 'datetime': this.iso8601(timestamp),
1033
+ 'info': interest,
1034
+ }, market);
1035
+ }
1036
+ /**
1037
+ * @method
1038
+ * @name apex#fetchFundingRateHistory
1039
+ * @description fetches historical funding rate prices
1040
+ * @see https://api-docs.pro.apex.exchange/#publicapi-v3-for-omni-get-funding-rate-history-v3
1041
+ * @param {string} symbol unified symbol of the market to fetch the funding rate history for
1042
+ * @param {int} [since] timestamp in ms of the earliest funding rate to fetch
1043
+ * @param {int} [limit] the maximum amount of [funding rate structures]{@link https://docs.ccxt.com/#/?id=funding-rate-history-structure} to fetch
1044
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1045
+ * @param {int} [params.until] timestamp in ms of the latest funding rate
1046
+ * @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
1047
+ * @returns {object[]} a list of [funding rate structures]{@link https://docs.ccxt.com/#/?id=funding-rate-history-structure}
1048
+ */
1049
+ async fetchFundingRateHistory(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1050
+ if (symbol === undefined) {
1051
+ throw new ArgumentsRequired(this.id + ' fetchFundingRateHistory() requires a symbol argument');
1052
+ }
1053
+ await this.loadMarkets();
1054
+ const request = {};
1055
+ const market = this.market(symbol);
1056
+ request['symbol'] = market['id'];
1057
+ if (since !== undefined) {
1058
+ request['beginTimeInclusive'] = since;
1059
+ }
1060
+ if (limit !== undefined) {
1061
+ request['limit'] = limit;
1062
+ }
1063
+ const page = this.safeInteger(params, 'page');
1064
+ if (page !== undefined) {
1065
+ request['page'] = page;
1066
+ }
1067
+ const endTimeExclusive = this.safeIntegerN(params, ['endTime', 'endTimeExclusive', 'until']);
1068
+ if (endTimeExclusive !== undefined) {
1069
+ request['endTimeExclusive'] = endTimeExclusive;
1070
+ }
1071
+ const response = await this.publicGetV3HistoryFunding(this.extend(request, params));
1072
+ //
1073
+ // {
1074
+ // "historyFunds": [
1075
+ // {
1076
+ // "symbol": "BTC-USD",
1077
+ // "rate": "0.0000125000",
1078
+ // "price": "31297.5000008009374142",
1079
+ // "fundingTime": 12315555,
1080
+ // "fundingTimestamp": 12315555
1081
+ // }
1082
+ // ],
1083
+ // "totalSize": 11
1084
+ // }
1085
+ //
1086
+ const rates = [];
1087
+ const data = this.safeDict(response, 'data', {});
1088
+ const resultList = this.safeList(data, 'historyFunds', []);
1089
+ for (let i = 0; i < resultList.length; i++) {
1090
+ const entry = resultList[i];
1091
+ const timestamp = this.safeInteger(entry, 'fundingTimestamp');
1092
+ rates.push({
1093
+ 'info': entry,
1094
+ 'symbol': this.safeString(entry, 'symbol'),
1095
+ 'fundingRate': this.safeNumber(entry, 'rate'),
1096
+ 'timestamp': timestamp,
1097
+ 'datetime': this.iso8601(timestamp),
1098
+ });
1099
+ }
1100
+ const sorted = this.sortBy(rates, 'timestamp');
1101
+ return this.filterBySymbolSinceLimit(sorted, symbol, since, limit);
1102
+ }
1103
+ parseOrder(order, market = undefined) {
1104
+ //
1105
+ // {
1106
+ // "id": "1234",
1107
+ // "clientId": "1234",
1108
+ // "accountId": "12345",
1109
+ // "symbol": "BTC-USD",
1110
+ // "side": "SELL",
1111
+ // "price": "18000",
1112
+ // "limitFee": "100",
1113
+ // "fee": "100",
1114
+ // "triggerPrice": "1.2",
1115
+ // "trailingPercent": "0.12",
1116
+ // "size": "100",
1117
+ // "remainingSize": "100",
1118
+ // "type": "LIMIT",
1119
+ // "createdAt": 1647502440973,
1120
+ // "updatedTime": 1647502440973,
1121
+ // "expiresAt": 1647502440973,
1122
+ // "status": "PENDING",
1123
+ // "timeInForce": "GOOD_TIL_CANCEL",
1124
+ // "postOnly": false,
1125
+ // "reduceOnly": false,
1126
+ // "stopPnl": false,
1127
+ // "latestMatchFillPrice": "reason",
1128
+ // "cumMatchFillSize": "0.1",
1129
+ // "cumMatchFillValue": "1000",
1130
+ // "cumMatchFillFee": "1",
1131
+ // "cumSuccessFillSize": "0.1",
1132
+ // "cumSuccessFillValue": "1000",
1133
+ // "cumSuccessFillFee": "1",
1134
+ // "triggerPriceType": "INDEX",
1135
+ // "isOpenTpslOrder": true,
1136
+ // "isSetOpenTp": true,
1137
+ // "isSetOpenSl": false,
1138
+ // "openTpParam": {
1139
+ // "side": "SELL",
1140
+ // "price": "18000",
1141
+ // "limitFee": "100",
1142
+ // "clientOrderId": "111100",
1143
+ // "triggerPrice": "1.2",
1144
+ // "trailingPercent": "0.12",
1145
+ // "size": "100"
1146
+ // },
1147
+ // "openSlParam": {
1148
+ // "side": "SELL",
1149
+ // "price": "18000",
1150
+ // "limitFee": "100",
1151
+ // "clientOrderId": "111100",
1152
+ // "triggerPrice": "1.2",
1153
+ // "trailingPercent": "0.12",
1154
+ // "size": "100"
1155
+ // }
1156
+ // }
1157
+ //
1158
+ const timestamp = this.safeInteger(order, 'createdAt');
1159
+ const orderId = this.safeString(order, 'id');
1160
+ const clientOrderId = this.safeString(order, 'clientId');
1161
+ const marketId = this.safeString(order, 'symbol');
1162
+ market = this.safeMarket(marketId, market);
1163
+ const symbol = market['symbol'];
1164
+ const price = this.safeString(order, 'price');
1165
+ const amount = this.safeString(order, 'size');
1166
+ const orderType = this.safeString(order, 'type');
1167
+ const status = this.safeString(order, 'status');
1168
+ const side = this.safeStringLower(order, 'side');
1169
+ // const average = this.omitZero (this.safeString (order, 'avg_fill_price'));
1170
+ const remaining = this.omitZero(this.safeString(order, 'remainingSize'));
1171
+ const lastUpdateTimestamp = this.safeInteger(order, 'updatedTime');
1172
+ return this.safeOrder({
1173
+ 'id': orderId,
1174
+ 'clientOrderId': clientOrderId,
1175
+ 'timestamp': timestamp,
1176
+ 'datetime': this.iso8601(timestamp),
1177
+ 'lastTradeTimestamp': undefined,
1178
+ 'lastUpdateTimestamp': lastUpdateTimestamp,
1179
+ 'status': this.parseOrderStatus(status),
1180
+ 'symbol': symbol,
1181
+ 'type': this.parseOrderType(orderType),
1182
+ 'timeInForce': this.parseTimeInForce(this.safeString(order, 'timeInForce')),
1183
+ 'postOnly': this.safeBool(order, 'postOnly'),
1184
+ 'reduceOnly': this.safeBool(order, 'reduceOnly'),
1185
+ 'side': side,
1186
+ 'price': price,
1187
+ 'triggerPrice': this.safeString(order, 'triggerPrice'),
1188
+ 'takeProfitPrice': undefined,
1189
+ 'stopLossPrice': undefined,
1190
+ 'average': undefined,
1191
+ 'amount': amount,
1192
+ 'filled': undefined,
1193
+ 'remaining': remaining,
1194
+ 'cost': undefined,
1195
+ 'trades': undefined,
1196
+ 'fee': {
1197
+ 'cost': this.safeString(order, 'fee'),
1198
+ 'currency': market['settleId'],
1199
+ },
1200
+ 'info': order,
1201
+ }, market);
1202
+ }
1203
+ parseTimeInForce(timeInForce) {
1204
+ const timeInForces = {
1205
+ 'GOOD_TIL_CANCEL': 'GOOD_TIL_CANCEL',
1206
+ 'FILL_OR_KILL': 'FILL_OR_KILL',
1207
+ 'IMMEDIATE_OR_CANCEL': 'IMMEDIATE_OR_CANCEL',
1208
+ 'POST_ONLY': 'POST_ONLY',
1209
+ };
1210
+ return this.safeString(timeInForces, timeInForce, undefined);
1211
+ }
1212
+ parseOrderStatus(status) {
1213
+ if (status !== undefined) {
1214
+ const statuses = {
1215
+ 'PENDING': 'open',
1216
+ 'OPEN': 'open',
1217
+ 'FILLED': 'filled',
1218
+ 'CANCELING': 'canceled',
1219
+ 'CANCELED': 'canceled',
1220
+ 'UNTRIGGERED': 'open',
1221
+ };
1222
+ return this.safeString(statuses, status, status);
1223
+ }
1224
+ return status;
1225
+ }
1226
+ parseOrderType(type) {
1227
+ const types = {
1228
+ 'LIMIT': 'LIMIT',
1229
+ 'MARKET': 'MARKET',
1230
+ 'STOP_LIMIT': 'STOP_LIMIT',
1231
+ 'STOP_MARKET': 'STOP_MARKET',
1232
+ 'TAKE_PROFIT_LIMIT': 'TAKE_PROFIT_LIMIT',
1233
+ 'TAKE_PROFIT_MARKET': 'TAKE_PROFIT_MARKET',
1234
+ };
1235
+ return this.safeStringUpper(types, type, type);
1236
+ }
1237
+ safeMarket(marketId = undefined, market = undefined, delimiter = undefined, marketType = undefined) {
1238
+ if (market === undefined && marketId !== undefined) {
1239
+ if (marketId in this.markets) {
1240
+ market = this.markets[marketId];
1241
+ }
1242
+ else if (marketId in this.markets_by_id) {
1243
+ market = this.markets_by_id[marketId];
1244
+ }
1245
+ else {
1246
+ const newMarketId = this.addHyphenBeforeUsdt(marketId);
1247
+ if (newMarketId in this.markets_by_id) {
1248
+ const markets = this.markets_by_id[newMarketId];
1249
+ const numMarkets = markets.length;
1250
+ if (numMarkets > 0) {
1251
+ if (this.markets_by_id[newMarketId][0]['id2'] === marketId) {
1252
+ market = this.markets_by_id[newMarketId][0];
1253
+ }
1254
+ }
1255
+ }
1256
+ }
1257
+ }
1258
+ return super.safeMarket(marketId, market, delimiter, marketType);
1259
+ }
1260
+ generateRandomClientIdOmni(_accountId) {
1261
+ const accountId = _accountId || this.randNumber(12).toString();
1262
+ return 'apexomni-' + accountId + '-' + this.milliseconds().toString() + '-' + this.randNumber(6).toString();
1263
+ }
1264
+ addHyphenBeforeUsdt(symbol) {
1265
+ const uppercaseSymbol = symbol.toUpperCase();
1266
+ const index = uppercaseSymbol.indexOf('USDT');
1267
+ const symbolChar = this.safeString(symbol, index - 1);
1268
+ if (index > 0 && symbolChar !== '-') {
1269
+ return symbol.slice(0, index) + '-' + symbol.slice(index);
1270
+ }
1271
+ return symbol;
1272
+ }
1273
+ getSeeds() {
1274
+ const seeds = this.safeString(this.options, 'seeds');
1275
+ if (seeds === undefined) {
1276
+ throw new ArgumentsRequired(this.id + ' the "seeds" key is required in the options to access private endpoints. You can find it in API Management > Omni Key, and then set it as exchange.options["seeds"] = XXXX');
1277
+ }
1278
+ return seeds;
1279
+ }
1280
+ async getAccountId() {
1281
+ const accountId = this.safeString(this.options, 'accountId', '0');
1282
+ if (accountId === '0') {
1283
+ const accountData = await this.fetchAccount();
1284
+ this.options['accountId'] = this.safeString(accountData, 'id', '0');
1285
+ }
1286
+ return this.options['accountId'];
1287
+ }
1288
+ /**
1289
+ * @method
1290
+ * @name apex#createOrder
1291
+ * @description create a trade order
1292
+ * @see https://api-docs.pro.apex.exchange/#privateapi-v3-for-omni-post-creating-orders
1293
+ * @param {string} symbol unified symbol of the market to create an order in
1294
+ * @param {string} type 'market' or 'limit'
1295
+ * @param {string} side 'buy' or 'sell'
1296
+ * @param {float} amount how much of currency you want to trade in units of base currency
1297
+ * @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
1298
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1299
+ * @param {float} [params.triggerPrice] The price a trigger order is triggered at
1300
+ * @param {string} [params.timeInForce] "GTC", "IOC", or "POST_ONLY"
1301
+ * @param {bool} [params.postOnly] true or false
1302
+ * @param {bool} [params.reduceOnly] Ensures that the executed order does not flip the opened position.
1303
+ * @param {string} [params.clientOrderId] a unique id for the order
1304
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
1305
+ */
1306
+ async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
1307
+ await this.loadMarkets();
1308
+ const market = this.market(symbol);
1309
+ const orderType = type.toUpperCase();
1310
+ const orderSide = side.toUpperCase();
1311
+ const orderSize = this.amountToPrecision(symbol, amount);
1312
+ let orderPrice = '0';
1313
+ if (price !== undefined) {
1314
+ orderPrice = this.priceToPrecision(symbol, price);
1315
+ }
1316
+ const fees = this.safeDict(this.fees, 'swap', {});
1317
+ const taker = this.safeNumber(fees, 'taker', 0.0005);
1318
+ const maker = this.safeNumber(fees, 'maker', 0.0002);
1319
+ const limitFee = this.decimalToPrecision(Precise.stringAdd(Precise.stringMul(Precise.stringMul(orderPrice, orderSize), taker.toString()), market['precision']['price'].toString()), TRUNCATE, market['precision']['price'], this.precisionMode, this.paddingMode);
1320
+ const timeNow = this.milliseconds();
1321
+ // const triggerPrice = this.safeString2 (params, 'triggerPrice', 'stopPrice');
1322
+ const isMarket = orderType === 'MARKET';
1323
+ if (isMarket && (price === undefined)) {
1324
+ throw new ArgumentsRequired(this.id + ' createOrder() requires a price argument for market orders');
1325
+ }
1326
+ let timeInForce = this.safeStringUpper(params, 'timeInForce');
1327
+ const postOnly = this.isPostOnly(isMarket, undefined, params);
1328
+ if (timeInForce === undefined) {
1329
+ timeInForce = 'GOOD_TIL_CANCEL';
1330
+ }
1331
+ if (!isMarket) {
1332
+ if (postOnly) {
1333
+ timeInForce = 'POST_ONLY';
1334
+ }
1335
+ else if (timeInForce === 'ioc') {
1336
+ timeInForce = 'IMMEDIATE_OR_CANCEL';
1337
+ }
1338
+ }
1339
+ params = this.omit(params, 'timeInForce');
1340
+ params = this.omit(params, 'postOnly');
1341
+ let clientOrderId = this.safeStringN(params, ['clientId', 'clientOrderId', 'client_order_id']);
1342
+ const accountId = await this.getAccountId();
1343
+ if (clientOrderId === undefined) {
1344
+ clientOrderId = this.generateRandomClientIdOmni(accountId);
1345
+ }
1346
+ params = this.omit(params, ['clientId', 'clientOrderId', 'client_order_id']);
1347
+ const orderToSign = {
1348
+ 'accountId': accountId,
1349
+ 'slotId': clientOrderId,
1350
+ 'nonce': clientOrderId,
1351
+ 'pairId': market['quoteId'],
1352
+ 'size': orderSize,
1353
+ 'price': orderPrice,
1354
+ 'direction': orderSide,
1355
+ 'makerFeeRate': maker.toString(),
1356
+ 'takerFeeRate': taker.toString(),
1357
+ };
1358
+ const signature = await this.getZKContractSignatureObj(this.remove0xPrefix(this.getSeeds()), orderToSign);
1359
+ const request = {
1360
+ 'symbol': market['id'],
1361
+ 'side': orderSide,
1362
+ 'type': orderType,
1363
+ 'size': orderSize,
1364
+ 'price': orderPrice,
1365
+ 'limitFee': limitFee,
1366
+ 'expiration': Math.floor(timeNow / 1000 + 30 * 24 * 60 * 60),
1367
+ 'timeInForce': timeInForce,
1368
+ 'clientId': clientOrderId,
1369
+ 'brokerId': this.safeString(this.options, 'brokerId', '6956'),
1370
+ };
1371
+ request['signature'] = signature;
1372
+ const response = await this.privatePostV3Order(this.extend(request, params));
1373
+ const data = this.safeDict(response, 'data', {});
1374
+ return this.parseOrder(data, market);
1375
+ }
1376
+ /**
1377
+ * @method
1378
+ * @name apex#transfer
1379
+ * @description transfer currency internally between wallets on the same account
1380
+ * @param {string} code unified currency code
1381
+ * @param {float} amount amount to transfer
1382
+ * @param {string} fromAccount account to transfer from
1383
+ * @param {string} toAccount account to transfer to
1384
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1385
+ * @param {string} [params.transferId] UUID, which is unique across the platform
1386
+ * @returns {object} a [transfer structure]{@link https://docs.ccxt.com/#/?id=transfer-structure}
1387
+ */
1388
+ async transfer(code, amount, fromAccount, toAccount, params = {}) {
1389
+ await this.loadMarkets();
1390
+ const configResponse = await this.publicGetV3Symbols(params);
1391
+ const configData = this.safeDict(configResponse, 'data', {});
1392
+ const contractConfig = this.safeDict(configData, 'contractConfig', {});
1393
+ const contractAssets = this.safeList(contractConfig, 'assets', []);
1394
+ const spotConfig = this.safeDict(configData, 'spotConfig', {});
1395
+ const spotAssets = this.safeList(spotConfig, 'assets', []);
1396
+ const globalConfig = this.safeDict(spotConfig, 'global', {});
1397
+ const receiverAddress = this.safeString(globalConfig, 'contractAssetPoolEthAddress', '');
1398
+ const receiverZkAccountId = this.safeString(globalConfig, 'contractAssetPoolZkAccountId', '');
1399
+ const receiverSubAccountId = this.safeString(globalConfig, 'contractAssetPoolSubAccount', '');
1400
+ const receiverAccountId = this.safeString(globalConfig, 'contractAssetPoolAccountId', '');
1401
+ const accountResponse = await this.privateGetV3Account(params);
1402
+ const accountData = this.safeDict(accountResponse, 'data', {});
1403
+ const spotAccount = this.safeDict(accountData, 'spotAccount', {});
1404
+ const zkAccountId = this.safeString(spotAccount, 'zkAccountId', '');
1405
+ const subAccountId = this.safeString(spotAccount, 'defaultSubAccountId', '0');
1406
+ const subAccounts = this.safeList(spotAccount, 'subAccounts', []);
1407
+ let nonce = '0';
1408
+ if (subAccounts.length > 0) {
1409
+ nonce = this.safeString(subAccounts[0], 'nonce', '0');
1410
+ }
1411
+ const ethAddress = this.safeString(accountData, 'ethereumAddress', '');
1412
+ const accountId = this.safeString(accountData, 'id', '');
1413
+ let currency = {};
1414
+ let assets = [];
1415
+ if (fromAccount !== undefined && fromAccount.toLowerCase() === 'contract') {
1416
+ assets = contractAssets;
1417
+ }
1418
+ else {
1419
+ assets = spotAssets;
1420
+ }
1421
+ for (let i = 0; i < assets.length; i++) {
1422
+ if (this.safeString(assets[i], 'token', '') === code) {
1423
+ currency = assets[i];
1424
+ }
1425
+ }
1426
+ const tokenId = this.safeString(currency, 'tokenId', '');
1427
+ const amountNumber = this.parseToInt(amount * (Math.pow(10, this.safeNumber(currency, 'decimals', 0))));
1428
+ const timestampSeconds = this.parseToInt(this.milliseconds() / 1000);
1429
+ let clientOrderId = this.safeStringN(params, ['clientId', 'clientOrderId', 'client_order_id']);
1430
+ if (clientOrderId === undefined) {
1431
+ clientOrderId = this.generateRandomClientIdOmni(this.safeString(this.options, 'accountId'));
1432
+ }
1433
+ params = this.omit(params, ['clientId', 'clientOrderId', 'client_order_id']);
1434
+ if (fromAccount !== undefined && fromAccount.toLowerCase() === 'contract') {
1435
+ const formattedUint32 = '4294967295';
1436
+ const zkSignAccountId = Precise.stringMod(accountId, formattedUint32);
1437
+ const expireTime = timestampSeconds + 3600 * 24 * 28;
1438
+ const orderToSign = {
1439
+ 'zkAccountId': zkSignAccountId,
1440
+ 'receiverAddress': ethAddress,
1441
+ 'subAccountId': subAccountId,
1442
+ 'receiverSubAccountId': subAccountId,
1443
+ 'tokenId': tokenId,
1444
+ 'amount': amountNumber.toString(),
1445
+ 'fee': '0',
1446
+ 'nonce': clientOrderId,
1447
+ 'timestampSeconds': expireTime,
1448
+ 'isContract': true,
1449
+ };
1450
+ const signature = await this.getZKTransferSignatureObj(this.remove0xPrefix(this.getSeeds()), orderToSign);
1451
+ const request = {
1452
+ 'amount': amount,
1453
+ 'expireTime': expireTime,
1454
+ 'clientWithdrawId': clientOrderId,
1455
+ 'signature': signature,
1456
+ 'token': code,
1457
+ 'ethAddress': ethAddress,
1458
+ };
1459
+ const response = await this.privatePostV3ContractTransferOut(this.extend(request, params));
1460
+ const data = this.safeDict(response, 'data', {});
1461
+ const currentTime = this.milliseconds();
1462
+ return this.extend(this.parseTransfer(data, this.currency(code)), {
1463
+ 'timestamp': currentTime,
1464
+ 'datetime': this.iso8601(currentTime),
1465
+ 'amount': this.parseNumber(amount),
1466
+ 'fromAccount': 'contract',
1467
+ 'toAccount': 'spot',
1468
+ });
1469
+ }
1470
+ else {
1471
+ const orderToSign = {
1472
+ 'zkAccountId': zkAccountId,
1473
+ 'receiverAddress': receiverAddress,
1474
+ 'subAccountId': subAccountId,
1475
+ 'receiverSubAccountId': receiverSubAccountId,
1476
+ 'tokenId': tokenId,
1477
+ 'amount': amountNumber.toString(),
1478
+ 'fee': '0',
1479
+ 'nonce': nonce,
1480
+ 'timestampSeconds': timestampSeconds,
1481
+ };
1482
+ const signature = await this.getZKTransferSignatureObj(this.remove0xPrefix(this.getSeeds()), orderToSign);
1483
+ const request = {
1484
+ 'amount': amount.toString(),
1485
+ 'timestamp': timestampSeconds,
1486
+ 'clientTransferId': clientOrderId,
1487
+ 'signature': signature,
1488
+ 'zkAccountId': zkAccountId,
1489
+ 'subAccountId': subAccountId,
1490
+ 'fee': '0',
1491
+ 'token': code,
1492
+ 'tokenId': tokenId,
1493
+ 'receiverAccountId': receiverAccountId,
1494
+ 'receiverZkAccountId': receiverZkAccountId,
1495
+ 'receiverSubAccountId': receiverSubAccountId,
1496
+ 'receiverAddress': receiverAddress,
1497
+ 'nonce': nonce,
1498
+ };
1499
+ const response = await this.privatePostV3TransferOut(this.extend(request, params));
1500
+ const data = this.safeDict(response, 'data', {});
1501
+ const currentTime = this.milliseconds();
1502
+ return this.extend(this.parseTransfer(data, this.currency(code)), {
1503
+ 'timestamp': currentTime,
1504
+ 'datetime': this.iso8601(currentTime),
1505
+ 'amount': this.parseNumber(amount),
1506
+ 'fromAccount': 'spot',
1507
+ 'toAccount': 'contract',
1508
+ });
1509
+ }
1510
+ }
1511
+ parseTransfer(transfer, currency = undefined) {
1512
+ const currencyId = this.safeString(transfer, 'coin');
1513
+ const timestamp = this.safeInteger(transfer, 'timestamp');
1514
+ const fromAccount = this.safeString(transfer, 'fromAccount');
1515
+ const toAccount = this.safeString(transfer, 'toAccount');
1516
+ return {
1517
+ 'info': transfer,
1518
+ 'id': this.safeStringN(transfer, ['transferId', 'id']),
1519
+ 'timestamp': timestamp,
1520
+ 'datetime': this.iso8601(timestamp),
1521
+ 'currency': this.safeCurrencyCode(currencyId, currency),
1522
+ 'amount': this.safeNumber(transfer, 'amount'),
1523
+ 'fromAccount': fromAccount,
1524
+ 'toAccount': toAccount,
1525
+ 'status': this.safeString(transfer, 'status'),
1526
+ };
1527
+ }
1528
+ /**
1529
+ * @method
1530
+ * @name apex#cancelAllOrders
1531
+ * @description cancel all open orders in a market
1532
+ * @see https://api-docs.pro.apex.exchange/#privateapi-v3-for-omni-post-cancel-all-open-orders
1533
+ * @param {string} symbol unified market symbol of the market to cancel orders in
1534
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1535
+ * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
1536
+ */
1537
+ async cancelAllOrders(symbol = undefined, params = {}) {
1538
+ await this.loadMarkets();
1539
+ let market = undefined;
1540
+ const request = {};
1541
+ if (symbol !== undefined) {
1542
+ market = this.market(symbol);
1543
+ request['symbol'] = market['id'];
1544
+ }
1545
+ const response = await this.privatePostV3DeleteOpenOrders(this.extend(request, params));
1546
+ const data = this.safeDict(response, 'data', {});
1547
+ return data;
1548
+ }
1549
+ /**
1550
+ * @method
1551
+ * @name apex#cancelOrder
1552
+ * @description cancels an open order
1553
+ * @see https://api-docs.pro.apex.exchange/#privateapi-v3-for-omni-post-cancel-order
1554
+ * @param {string} id order id
1555
+ * @param symbol
1556
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1557
+ * @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
1558
+ */
1559
+ async cancelOrder(id, symbol = undefined, params = {}) {
1560
+ const request = {};
1561
+ const clientOrderId = this.safeStringN(params, ['clientId', 'clientOrderId', 'client_order_id']);
1562
+ let response = undefined;
1563
+ if (clientOrderId !== undefined) {
1564
+ request['id'] = clientOrderId;
1565
+ params = this.omit(params, ['clientId', 'clientOrderId', 'client_order_id']);
1566
+ response = await this.privatePostV3DeleteClientOrderId(this.extend(request, params));
1567
+ }
1568
+ else {
1569
+ request['id'] = id;
1570
+ response = await this.privatePostV3DeleteOrder(this.extend(request, params));
1571
+ }
1572
+ const data = this.safeDict(response, 'data', {});
1573
+ return data;
1574
+ }
1575
+ /**
1576
+ * @method
1577
+ * @name apex#fetchOrder
1578
+ * @description fetches information on an order made by the user
1579
+ * @see https://api-docs.pro.apex.exchange/#privateapi-v3-for-omni-get-order-id
1580
+ * @see https://api-docs.pro.apex.exchange/#privateapi-v3-for-omni-get-order-by-clientorderid
1581
+ * @param {string} id the order id
1582
+ * @param {string} symbol unified symbol of the market the order was made in
1583
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1584
+ * @param {string} [params.clientOrderId] a unique id for the order
1585
+ * @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
1586
+ */
1587
+ async fetchOrder(id, symbol = undefined, params = {}) {
1588
+ await this.loadMarkets();
1589
+ const request = {};
1590
+ const clientOrderId = this.safeStringN(params, ['clientId', 'clientOrderId', 'client_order_id']);
1591
+ let response = undefined;
1592
+ if (clientOrderId !== undefined) {
1593
+ request['id'] = clientOrderId;
1594
+ params = this.omit(params, ['clientId', 'clientOrderId', 'client_order_id']);
1595
+ response = await this.privateGetV3OrderByClientOrderId(this.extend(request, params));
1596
+ }
1597
+ else {
1598
+ request['id'] = id;
1599
+ response = await this.privateGetV3Order(this.extend(request, params));
1600
+ }
1601
+ const data = this.safeDict(response, 'data', {});
1602
+ return this.parseOrder(data);
1603
+ }
1604
+ /**
1605
+ * @method
1606
+ * @name apex#fetchOpenOrders
1607
+ * @description fetches information on multiple orders made by the user
1608
+ * @see https://api-docs.pro.apex.exchange/#privateapi-v3-for-omni-get-open-orders
1609
+ * @param {string} symbol unified market symbol of the market orders were made in
1610
+ * @param {int} [since] the earliest time in ms to fetch orders for
1611
+ * @param {int} [limit] the maximum number of order structures to retrieve
1612
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1613
+ * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
1614
+ */
1615
+ async fetchOpenOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1616
+ await this.loadMarkets();
1617
+ const response = await this.privateGetV3OpenOrders(params);
1618
+ const orders = this.safeList(response, 'data', []);
1619
+ return this.parseOrders(orders, undefined, since, limit);
1620
+ }
1621
+ /**
1622
+ * @method
1623
+ * @name apex#fetchOrders
1624
+ * @description fetches information on multiple orders made by the user *classic accounts only*
1625
+ * @see https://api-docs.pro.apex.exchange/#privateapi-v3-for-omni-get-all-order-history
1626
+ * @param {string} symbol unified market symbol of the market orders were made in
1627
+ * @param {int} [since] the earliest time in ms to fetch orders for
1628
+ * @param {int} [limit] the maximum number of order structures to retrieve, default 100
1629
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1630
+ * @param {object} [params.until] end time, ms
1631
+ * @param {boolean} [params.status] "PENDING", "OPEN", "FILLED", "CANCELED", "EXPIRED", "UNTRIGGERED"
1632
+ * @param {boolean} [params.side] BUY or SELL
1633
+ * @param {string} [params.type] "LIMIT", "MARKET","STOP_LIMIT", "STOP_MARKET", "TAKE_PROFIT_LIMIT","TAKE_PROFIT_MARKET"
1634
+ * @param {string} [params.orderType] "ACTIVE","CONDITION","HISTORY"
1635
+ * @param {boolean} [params.page] Page numbers start from 0
1636
+ * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
1637
+ */
1638
+ async fetchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1639
+ await this.loadMarkets();
1640
+ const request = {};
1641
+ let market = undefined;
1642
+ if (symbol !== undefined) {
1643
+ market = this.market(symbol);
1644
+ request['symbol'] = market['id'];
1645
+ }
1646
+ if (since !== undefined) {
1647
+ request['beginTimeInclusive'] = since;
1648
+ }
1649
+ if (limit !== undefined) {
1650
+ request['limit'] = limit;
1651
+ }
1652
+ const endTimeExclusive = this.safeIntegerN(params, ['endTime', 'endTimeExclusive', 'until']);
1653
+ if (endTimeExclusive !== undefined) {
1654
+ request['endTimeExclusive'] = endTimeExclusive;
1655
+ params = this.omit(params, ['endTime', 'endTimeExclusive', 'until']);
1656
+ }
1657
+ const response = await this.privateGetV3HistoryOrders(this.extend(request, params));
1658
+ const data = this.safeDict(response, 'data', {});
1659
+ const orders = this.safeList(data, 'orders', []);
1660
+ return this.parseOrders(orders, market, since, limit);
1661
+ }
1662
+ /**
1663
+ * @method
1664
+ * @name apex#fetchOrderTrades
1665
+ * @description fetch all the trades made from a single order
1666
+ * @see https://api-docs.pro.apex.exchange/#privateapi-v3-for-omni-get-trade-history
1667
+ * @param {string} id order id
1668
+ * @param {string} symbol unified market symbol
1669
+ * @param {int} [since] the earliest time in ms to fetch trades for
1670
+ * @param {int} [limit] the maximum number of trades to retrieve
1671
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1672
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
1673
+ */
1674
+ async fetchOrderTrades(id, symbol = undefined, since = undefined, limit = undefined, params = {}) {
1675
+ await this.loadMarkets();
1676
+ const request = {};
1677
+ const clientOrderId = this.safeString2(params, 'clientOrderId', 'clientId');
1678
+ if (clientOrderId !== undefined) {
1679
+ request['clientOrderId'] = clientOrderId;
1680
+ }
1681
+ else {
1682
+ request['orderId'] = id;
1683
+ }
1684
+ params = this.omit(params, ['clientOrderId', 'clientId']);
1685
+ const response = await this.privateGetV3OrderFills(this.extend(request, params));
1686
+ const data = this.safeDict(response, 'data', {});
1687
+ const orders = this.safeList(data, 'orders', []);
1688
+ return this.parseTrades(orders, undefined, since, limit);
1689
+ }
1690
+ /**
1691
+ * @method
1692
+ * @name apex#fetchMyTrades
1693
+ * @description fetches information on multiple orders made by the user *classic accounts only*
1694
+ * @see https://api-docs.pro.apex.exchange/#privateapi-v3-for-omni-get-trade-history
1695
+ * @param {string} symbol unified market symbol of the market orders were made in
1696
+ * @param {int} [since] the earliest time in ms to fetch orders for
1697
+ * @param {int} [limit] the maximum number of order structures to retrieve, default 100
1698
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1699
+ * @param {object} [params.until] end time
1700
+ * @param {boolean} [params.side] BUY or SELL
1701
+ * @param {string} [params.orderType] "LIMIT", "MARKET","STOP_LIMIT", "STOP_MARKET", "TAKE_PROFIT_LIMIT","TAKE_PROFIT_MARKET"
1702
+ * @param {boolean} [params.page] Page numbers start from 0
1703
+ * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
1704
+ */
1705
+ async fetchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1706
+ await this.loadMarkets();
1707
+ const request = {};
1708
+ let market = undefined;
1709
+ if (symbol !== undefined) {
1710
+ market = this.market(symbol);
1711
+ request['symbol'] = market['id'];
1712
+ }
1713
+ if (since !== undefined) {
1714
+ request['beginTimeInclusive'] = since;
1715
+ }
1716
+ if (limit !== undefined) {
1717
+ request['limit'] = limit;
1718
+ }
1719
+ const endTimeExclusive = this.safeIntegerN(params, ['endTime', 'endTimeExclusive', 'until']);
1720
+ if (endTimeExclusive !== undefined) {
1721
+ request['endTimeExclusive'] = endTimeExclusive;
1722
+ params = this.omit(params, ['endTime', 'endTimeExclusive', 'until']);
1723
+ }
1724
+ const response = await this.privateGetV3Fills(this.extend(request, params));
1725
+ const data = this.safeDict(response, 'data', {});
1726
+ const orders = this.safeList(data, 'orders', []);
1727
+ return this.parseTrades(orders, market, since, limit);
1728
+ }
1729
+ /**
1730
+ * @method
1731
+ * @name apex#fetchFundingHistory
1732
+ * @description fetches information on multiple orders made by the user *classic accounts only*
1733
+ * @see https://api-docs.pro.apex.exchange/#privateapi-v3-for-omni-get-funding-rate
1734
+ * @param {string} symbol unified market symbol of the market orders were made in
1735
+ * @param {int} [since] the earliest time in ms to fetch orders for
1736
+ * @param {int} [limit] the maximum number of order structures to retrieve, default 100
1737
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1738
+ * @param {object} [params.until] end time, ms
1739
+ * @param {boolean} [params.side] BUY or SELL
1740
+ * @param {boolean} [params.page] Page numbers start from 0
1741
+ * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=funding-history-structure}
1742
+ */
1743
+ async fetchFundingHistory(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1744
+ await this.loadMarkets();
1745
+ const request = {};
1746
+ let market = undefined;
1747
+ if (symbol !== undefined) {
1748
+ market = this.market(symbol);
1749
+ request['symbol'] = market['id'];
1750
+ }
1751
+ if (since !== undefined) {
1752
+ request['beginTimeInclusive'] = since;
1753
+ }
1754
+ if (limit !== undefined) {
1755
+ request['limit'] = limit;
1756
+ }
1757
+ const endTimeExclusive = this.safeIntegerN(params, ['endTime', 'endTimeExclusive', 'until']);
1758
+ if (endTimeExclusive !== undefined) {
1759
+ params = this.omit(params, ['endTime', 'endTimeExclusive', 'until']);
1760
+ request['endTimeExclusive'] = endTimeExclusive;
1761
+ }
1762
+ const response = await this.privateGetV3Funding(this.extend(request, params));
1763
+ const data = this.safeDict(response, 'data', {});
1764
+ const fundingValues = this.safeList(data, 'fundingValues', []);
1765
+ return this.parseIncomes(fundingValues, market, since, limit);
1766
+ }
1767
+ parseIncome(income, market = undefined) {
1768
+ //
1769
+ // {
1770
+ // "id": "1234",
1771
+ // "symbol": "BTC-USDT",
1772
+ // "fundingValue": "10000",
1773
+ // "rate": "0.0000125000",
1774
+ // "positionSize": "500",
1775
+ // "price": "90",
1776
+ // "side": "LONG",
1777
+ // "status": "SUCCESS",
1778
+ // "fundingTime": 1647502440973,
1779
+ // "transactionId": "1234556"
1780
+ // }
1781
+ //
1782
+ const marketId = this.safeString(income, 'symbol');
1783
+ market = this.safeMarket(marketId, market, undefined, 'contract');
1784
+ const code = 'USDT';
1785
+ const timestamp = this.safeInteger(income, 'fundingTime');
1786
+ return {
1787
+ 'info': income,
1788
+ 'symbol': this.safeSymbol(marketId, market),
1789
+ 'code': code,
1790
+ 'timestamp': timestamp,
1791
+ 'datetime': this.iso8601(timestamp),
1792
+ 'id': this.safeString(income, 'id'),
1793
+ 'amount': this.safeNumber(income, 'fundingValue'),
1794
+ 'rate': this.safeNumber(income, 'rate'),
1795
+ };
1796
+ }
1797
+ /**
1798
+ * @method
1799
+ * @name apex#setLeverage
1800
+ * @description set the level of leverage for a market
1801
+ * @see https://api-docs.pro.apex.exchange/#privateapi-v3-for-omni-post-sets-the-initial-margin-rate-of-a-contract
1802
+ * @param {float} leverage the rate of leverage
1803
+ * @param {string} symbol unified market symbol
1804
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1805
+ * @returns {object} response from the exchange
1806
+ */
1807
+ async setLeverage(leverage, symbol = undefined, params = {}) {
1808
+ if (symbol === undefined) {
1809
+ throw new ArgumentsRequired(this.id + ' setLeverage() requires a symbol argument');
1810
+ }
1811
+ await this.loadMarkets();
1812
+ const market = this.market(symbol);
1813
+ const leverageString = this.numberToString(leverage);
1814
+ const initialMarginRate = Precise.stringDiv('1', leverageString, 4);
1815
+ const request = {
1816
+ 'symbol': market['id'],
1817
+ 'initialMarginRate': initialMarginRate,
1818
+ };
1819
+ const response = await this.privatePostV3SetInitialMarginRate(this.extend(request, params));
1820
+ const data = this.safeDict(response, 'data', {});
1821
+ return data;
1822
+ }
1823
+ /**
1824
+ * @method
1825
+ * @name apex#fetchPositions
1826
+ * @description fetch all open positions
1827
+ * @see https://api-docs.pro.apex.exchange/#privateapi-v3-for-omni-get-retrieve-user-account-data
1828
+ * @param {string[]} [symbols] list of unified market symbols
1829
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1830
+ * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/#/?id=position-structure}
1831
+ */
1832
+ async fetchPositions(symbols = undefined, params = {}) {
1833
+ await this.loadMarkets();
1834
+ const response = await this.privateGetV3Account(params);
1835
+ const data = this.safeDict(response, 'data', {});
1836
+ const positions = this.safeList(data, 'positions', []);
1837
+ return this.parsePositions(positions, symbols);
1838
+ }
1839
+ parsePosition(position, market = undefined) {
1840
+ //
1841
+ // {
1842
+ // "symbol": "BTC-USDT",
1843
+ // "status": "",
1844
+ // "side": "LONG",
1845
+ // "size": "0.000",
1846
+ // "entryPrice": "0.00",
1847
+ // "exitPrice": "",
1848
+ // "createdAt": 1690366452416,
1849
+ // "updatedTime": 1690366452416,
1850
+ // "fee": "0.000000",
1851
+ // "fundingFee": "0.000000",
1852
+ // "lightNumbers": "",
1853
+ // "customInitialMarginRate": "0"
1854
+ // }
1855
+ const marketId = this.safeString(position, 'symbol');
1856
+ market = this.safeMarket(marketId, market);
1857
+ const symbol = market['symbol'];
1858
+ const side = this.safeStringLower(position, 'side');
1859
+ const quantity = this.safeString(position, 'size');
1860
+ const timestamp = this.safeInteger(position, 'updatedTime');
1861
+ let leverage = 20;
1862
+ const customInitialMarginRate = this.safeStringN(position, ['customInitialMarginRate', 'customImr'], '0');
1863
+ if (this.precisionFromString(customInitialMarginRate) !== 0) {
1864
+ leverage = this.parseToInt(Precise.stringDiv('1', customInitialMarginRate, 4));
1865
+ }
1866
+ return this.safePosition({
1867
+ 'info': position,
1868
+ 'id': this.safeString(position, 'id'),
1869
+ 'symbol': symbol,
1870
+ 'entryPrice': this.safeString(position, 'entryPrice'),
1871
+ 'markPrice': undefined,
1872
+ 'notional': undefined,
1873
+ 'collateral': undefined,
1874
+ 'unrealizedPnl': undefined,
1875
+ 'side': side,
1876
+ 'contracts': this.parseNumber(quantity),
1877
+ 'contractSize': undefined,
1878
+ 'timestamp': timestamp,
1879
+ 'datetime': this.iso8601(timestamp),
1880
+ 'hedged': undefined,
1881
+ 'maintenanceMargin': undefined,
1882
+ 'maintenanceMarginPercentage': undefined,
1883
+ 'initialMargin': undefined,
1884
+ 'initialMarginPercentage': undefined,
1885
+ 'leverage': leverage,
1886
+ 'liquidationPrice': undefined,
1887
+ 'marginRatio': undefined,
1888
+ 'marginMode': undefined,
1889
+ 'percentage': undefined,
1890
+ });
1891
+ }
1892
+ sign(path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
1893
+ let url = this.implodeHostname(this.urls['api'][api]) + '/' + path;
1894
+ headers = {
1895
+ 'User-Agent': 'apex-CCXT',
1896
+ 'Accept': 'application/json',
1897
+ 'Content-Type': 'application/x-www-form-urlencoded',
1898
+ };
1899
+ let signPath = '/api/' + path;
1900
+ let signBody = body;
1901
+ if (method.toUpperCase() !== 'POST') {
1902
+ if (Object.keys(params).length) {
1903
+ signPath += '?' + this.rawencode(params);
1904
+ url += '?' + this.rawencode(params);
1905
+ }
1906
+ }
1907
+ else {
1908
+ const sortedQuery = this.keysort(params);
1909
+ signBody = this.rawencode(sortedQuery);
1910
+ }
1911
+ if (api === 'private') {
1912
+ this.checkRequiredCredentials();
1913
+ const timestamp = this.milliseconds().toString();
1914
+ let messageString = timestamp + method.toUpperCase() + signPath;
1915
+ if (signBody !== undefined) {
1916
+ messageString = messageString + signBody;
1917
+ }
1918
+ const signature = this.hmac(this.encode(messageString), this.encode(this.stringToBase64(this.secret)), sha256, 'base64');
1919
+ headers['APEX-SIGNATURE'] = signature;
1920
+ headers['APEX-API-KEY'] = this.apiKey;
1921
+ headers['APEX-TIMESTAMP'] = timestamp;
1922
+ headers['APEX-PASSPHRASE'] = this.password;
1923
+ }
1924
+ return { 'url': url, 'method': method, 'body': signBody, 'headers': headers };
1925
+ }
1926
+ handleErrors(code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
1927
+ //
1928
+ // {"code":3,"msg":"Order price must be greater than 0. Order price is 0.","key":"ORDER_PRICE_MUST_GREETER_ZERO","detail":{"price":"0"}}
1929
+ // {"code":400,"msg":"strconv.ParseInt: parsing \"dsfdfsd\": invalid syntax","timeCost":5320995}
1930
+ //
1931
+ if (response === undefined) {
1932
+ return undefined;
1933
+ }
1934
+ const errorCode = this.safeInteger(response, 'code');
1935
+ if (errorCode !== undefined && errorCode !== 0) {
1936
+ const feedback = this.id + ' ' + body;
1937
+ const message = this.safeString2(response, 'key', 'msg');
1938
+ this.throwBroadlyMatchedException(this.exceptions['broad'], message, feedback);
1939
+ const status = code.toString();
1940
+ this.throwExactlyMatchedException(this.exceptions['exact'], status, feedback);
1941
+ throw new ExchangeError(feedback);
1942
+ }
1943
+ return undefined;
1944
+ }
1945
+ }