ccxt 4.5.5 → 4.5.7

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 (151) hide show
  1. package/README.md +4 -4
  2. package/dist/ccxt.browser.min.js +15 -15
  3. package/dist/cjs/ccxt.js +6 -6
  4. package/dist/cjs/src/abstract/toobit.js +11 -0
  5. package/dist/cjs/src/abstract/tradeogre.js +1 -1
  6. package/dist/cjs/src/apex.js +2 -2
  7. package/dist/cjs/src/backpack.js +1 -1
  8. package/dist/cjs/src/base/Exchange.js +129 -2
  9. package/dist/cjs/src/bigone.js +4 -4
  10. package/dist/cjs/src/binance.js +82 -20
  11. package/dist/cjs/src/bingx.js +5 -2
  12. package/dist/cjs/src/bitbank.js +1 -0
  13. package/dist/cjs/src/bitbns.js +1 -0
  14. package/dist/cjs/src/bitflyer.js +1 -0
  15. package/dist/cjs/src/bitget.js +16 -9
  16. package/dist/cjs/src/bithumb.js +1 -0
  17. package/dist/cjs/src/bitso.js +1 -0
  18. package/dist/cjs/src/bitvavo.js +26 -40
  19. package/dist/cjs/src/blockchaincom.js +1 -0
  20. package/dist/cjs/src/btcalpha.js +1 -0
  21. package/dist/cjs/src/btcbox.js +1 -0
  22. package/dist/cjs/src/btcmarkets.js +1 -0
  23. package/dist/cjs/src/btcturk.js +1 -0
  24. package/dist/cjs/src/bybit.js +186 -127
  25. package/dist/cjs/src/coinsph.js +4 -1
  26. package/dist/cjs/src/cryptocom.js +6 -3
  27. package/dist/cjs/src/deribit.js +3 -2
  28. package/dist/cjs/src/digifinex.js +1 -1
  29. package/dist/cjs/src/gate.js +9 -13
  30. package/dist/cjs/src/gemini.js +5 -5
  31. package/dist/cjs/src/htx.js +11 -1
  32. package/dist/cjs/src/hyperliquid.js +3 -0
  33. package/dist/cjs/src/independentreserve.js +1 -0
  34. package/dist/cjs/src/indodax.js +17 -6
  35. package/dist/cjs/src/kraken.js +31 -8
  36. package/dist/cjs/src/krakenfutures.js +1 -0
  37. package/dist/cjs/src/kucoin.js +1 -2
  38. package/dist/cjs/src/luno.js +4 -1
  39. package/dist/cjs/src/mercado.js +1 -0
  40. package/dist/cjs/src/mexc.js +84 -37
  41. package/dist/cjs/src/novadax.js +1 -0
  42. package/dist/cjs/src/oceanex.js +1 -0
  43. package/dist/cjs/src/okcoin.js +4 -1
  44. package/dist/cjs/src/okx.js +52 -8
  45. package/dist/cjs/src/phemex.js +1 -1
  46. package/dist/cjs/src/pro/apex.js +8 -4
  47. package/dist/cjs/src/pro/backpack.js +7 -5
  48. package/dist/cjs/src/pro/binance.js +150 -19
  49. package/dist/cjs/src/pro/bingx.js +206 -220
  50. package/dist/cjs/src/pro/bitget.js +332 -76
  51. package/dist/cjs/src/pro/cex.js +1 -0
  52. package/dist/cjs/src/pro/htx.js +1 -1
  53. package/dist/cjs/src/pro/independentreserve.js +1 -0
  54. package/dist/cjs/src/pro/mexc.js +23 -23
  55. package/dist/cjs/src/pro/okx.js +46 -10
  56. package/dist/cjs/src/pro/toobit.js +1163 -0
  57. package/dist/cjs/src/pro/tradeogre.js +1 -1
  58. package/dist/cjs/src/toobit.js +2999 -0
  59. package/dist/cjs/src/tradeogre.js +1 -1
  60. package/dist/cjs/src/upbit.js +1 -0
  61. package/dist/cjs/src/wavesexchange.js +1 -0
  62. package/dist/cjs/src/yobit.js +1 -0
  63. package/dist/cjs/src/zaif.js +1 -0
  64. package/dist/cjs/src/zonda.js +1 -0
  65. package/js/ccxt.d.ts +8 -8
  66. package/js/ccxt.js +6 -6
  67. package/js/src/abstract/mexc.d.ts +1 -0
  68. package/js/src/abstract/myokx.d.ts +1 -0
  69. package/js/src/abstract/okx.d.ts +1 -0
  70. package/js/src/abstract/okxus.d.ts +1 -0
  71. package/js/src/abstract/toobit.d.ts +66 -0
  72. package/js/src/apex.js +2 -2
  73. package/js/src/backpack.js +1 -1
  74. package/js/src/base/Exchange.d.ts +9 -0
  75. package/js/src/base/Exchange.js +129 -2
  76. package/js/src/bigone.js +4 -4
  77. package/js/src/binance.d.ts +9 -0
  78. package/js/src/binance.js +82 -20
  79. package/js/src/bingx.js +5 -2
  80. package/js/src/bitbank.js +1 -0
  81. package/js/src/bitbns.js +1 -0
  82. package/js/src/bitflyer.js +1 -0
  83. package/js/src/bitget.js +16 -9
  84. package/js/src/bithumb.js +1 -0
  85. package/js/src/bitso.js +1 -0
  86. package/js/src/bitvavo.d.ts +0 -2
  87. package/js/src/bitvavo.js +27 -41
  88. package/js/src/blockchaincom.js +1 -0
  89. package/js/src/btcalpha.js +1 -0
  90. package/js/src/btcbox.js +1 -0
  91. package/js/src/btcmarkets.js +1 -0
  92. package/js/src/btcturk.js +1 -0
  93. package/js/src/bybit.d.ts +8 -0
  94. package/js/src/bybit.js +186 -127
  95. package/js/src/coinsph.js +4 -1
  96. package/js/src/cryptocom.js +6 -3
  97. package/js/src/deribit.js +3 -2
  98. package/js/src/digifinex.js +1 -1
  99. package/js/src/gate.d.ts +2 -2
  100. package/js/src/gate.js +9 -13
  101. package/js/src/gemini.js +5 -5
  102. package/js/src/htx.js +11 -1
  103. package/js/src/hyperliquid.js +3 -0
  104. package/js/src/independentreserve.js +1 -0
  105. package/js/src/indodax.js +17 -6
  106. package/js/src/kraken.d.ts +2 -2
  107. package/js/src/kraken.js +31 -8
  108. package/js/src/krakenfutures.js +1 -0
  109. package/js/src/kucoin.js +1 -2
  110. package/js/src/luno.js +4 -1
  111. package/js/src/mercado.js +1 -0
  112. package/js/src/mexc.d.ts +4 -1
  113. package/js/src/mexc.js +84 -37
  114. package/js/src/novadax.js +1 -0
  115. package/js/src/oceanex.js +1 -0
  116. package/js/src/okcoin.js +4 -1
  117. package/js/src/okx.js +52 -8
  118. package/js/src/phemex.js +1 -1
  119. package/js/src/pro/apex.js +8 -4
  120. package/js/src/pro/backpack.d.ts +1 -1
  121. package/js/src/pro/backpack.js +7 -5
  122. package/js/src/pro/binance.d.ts +24 -0
  123. package/js/src/pro/binance.js +150 -19
  124. package/js/src/pro/bingx.d.ts +53 -33
  125. package/js/src/pro/bingx.js +207 -221
  126. package/js/src/pro/bitget.d.ts +6 -0
  127. package/js/src/pro/bitget.js +332 -76
  128. package/js/src/pro/cex.js +1 -0
  129. package/js/src/pro/htx.js +1 -1
  130. package/js/src/pro/independentreserve.js +1 -0
  131. package/js/src/pro/mexc.js +23 -23
  132. package/js/src/pro/okx.d.ts +7 -1
  133. package/js/src/pro/okx.js +46 -10
  134. package/js/src/pro/toobit.d.ts +174 -0
  135. package/js/src/pro/toobit.js +1162 -0
  136. package/js/src/toobit.d.ts +456 -0
  137. package/js/src/toobit.js +2992 -0
  138. package/js/src/upbit.js +1 -0
  139. package/js/src/wavesexchange.js +1 -0
  140. package/js/src/yobit.js +1 -0
  141. package/js/src/zaif.js +1 -0
  142. package/js/src/zonda.js +1 -0
  143. package/package.json +1 -1
  144. package/dist/373.ccxt.browser.js +0 -7630
  145. package/dist/373.ccxt.browser.min.js +0 -1
  146. package/js/src/abstract/tradeogre.d.ts +0 -21
  147. package/js/src/pro/tradeogre.d.ts +0 -49
  148. package/js/src/pro/tradeogre.js +0 -278
  149. package/js/src/tradeogre.d.ts +0 -149
  150. package/js/src/tradeogre.js +0 -872
  151. /package/js/src/abstract/{tradeogre.js → toobit.js} +0 -0
@@ -0,0 +1,2999 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var toobit$1 = require('./abstract/toobit.js');
6
+ var errors = require('./base/errors.js');
7
+ var Precise = require('./base/Precise.js');
8
+ var number = require('./base/functions/number.js');
9
+ var sha256 = require('./static_dependencies/noble-hashes/sha256.js');
10
+
11
+ // ---------------------------------------------------------------------------
12
+ // ---------------------------------------------------------------------------
13
+ /**
14
+ * @class toobit
15
+ * @augments Exchange
16
+ */
17
+ class toobit extends toobit$1["default"] {
18
+ describe() {
19
+ return this.deepExtend(super.describe(), {
20
+ 'id': 'toobit',
21
+ 'name': 'Toobit',
22
+ 'countries': ['KY'],
23
+ 'version': 'v1',
24
+ 'rateLimit': 20,
25
+ 'certified': false,
26
+ 'pro': false,
27
+ 'has': {
28
+ 'CORS': undefined,
29
+ 'spot': true,
30
+ 'margin': false,
31
+ 'swap': true,
32
+ 'future': false,
33
+ 'option': false,
34
+ 'cancelAllOrders': true,
35
+ 'cancelOrder': true,
36
+ 'cancelOrders': true,
37
+ 'createOrder': true,
38
+ 'fetchBalance': true,
39
+ 'fetchBidsAsks': true,
40
+ 'fetchCurrencies': true,
41
+ 'fetchDepositAddress': true,
42
+ 'fetchDeposits': true,
43
+ 'fetchFundingRateHistory': true,
44
+ 'fetchFundingRates': true,
45
+ 'fetchIndexOHLCV': true,
46
+ 'fetchLastPrices': true,
47
+ 'fetchLedger': true,
48
+ 'fetchMarkets': true,
49
+ 'fetchMarkOHLCV': true,
50
+ 'fetchMyTrades': true,
51
+ 'fetchOHLCV': true,
52
+ 'fetchOpenOrders': true,
53
+ 'fetchOrder': true,
54
+ 'fetchOrderBook': true,
55
+ 'fetchOrders': true,
56
+ 'fetchStatus': true,
57
+ 'fetchTickers': true,
58
+ 'fetchTime': true,
59
+ 'fetchTrades': true,
60
+ 'fetchWithdrawals': true,
61
+ 'setMarginMode': true,
62
+ 'transfer': true,
63
+ 'withdraw': true,
64
+ },
65
+ 'urls': {
66
+ 'logo': 'https://github.com/user-attachments/assets/3fc13870-5406-431b-8be0-2aab69c4f225',
67
+ 'api': {
68
+ 'common': 'https://api.toobit.com',
69
+ 'private': 'https://api.toobit.com',
70
+ },
71
+ 'www': 'https://www.toobit.com/',
72
+ 'doc': [
73
+ 'https://toobit-docs.github.io/apidocs/spot/v1/en/',
74
+ 'https://toobit-docs.github.io/apidocs/usdt_swap/v1/en/',
75
+ ],
76
+ 'referral': {
77
+ 'url': 'https://www.toobit.com/en-US/r?i=IFFPy0',
78
+ 'discount': 0.1,
79
+ },
80
+ 'fees': 'https://www.toobit.com/fee',
81
+ },
82
+ 'api': {
83
+ 'common': {
84
+ 'get': {
85
+ 'api/v1/time': 1,
86
+ 'api/v1/ping': 1,
87
+ 'api/v1/exchangeInfo': 1,
88
+ 'quote/v1/depth': 1,
89
+ 'quote/v1/depth/merged': 1,
90
+ 'quote/v1/trades': 1,
91
+ 'quote/v1/klines': 1,
92
+ 'quote/v1/index/klines': 1,
93
+ 'quote/v1/markPrice/klines': 1,
94
+ 'quote/v1/markPrice': 1,
95
+ 'quote/v1/index': 1,
96
+ 'quote/v1/ticker/24hr': 40,
97
+ 'quote/v1/contract/ticker/24hr': 40,
98
+ 'quote/v1/ticker/price': 1,
99
+ 'quote/v1/ticker/bookTicker': 1,
100
+ 'api/v1/futures/fundingRate': 1,
101
+ 'api/v1/futures/historyFundingRate': 1,
102
+ },
103
+ },
104
+ 'private': {
105
+ 'get': {
106
+ 'api/v1/account': 5,
107
+ 'api/v1/account/checkApiKey': 1,
108
+ 'api/v1/spot/order': 1 * 1.67,
109
+ 'api/v1/spot/openOrders': 1 * 1.67,
110
+ 'api/v1/futures/openOrders': 1 * 1.67,
111
+ 'api/v1/spot/tradeOrders': 5 * 1.67,
112
+ 'api/v1/futures/historyOrders': 5 * 1.67,
113
+ 'api/v1/account/trades': 5 * 1.67,
114
+ 'api/v1/account/balanceFlow': 5,
115
+ 'api/v1/account/depositOrders': 5,
116
+ 'api/v1/account/withdrawOrders': 5,
117
+ 'api/v1/account/deposit/address': 1,
118
+ // contracts
119
+ 'api/v1/subAccount': 5,
120
+ 'api/v1/futures/accountLeverage': 1,
121
+ 'api/v1/futures/order': 1 * 1.67,
122
+ 'api/v1/futures/positions': 5 * 1.67,
123
+ 'api/v1/futures/balance': 5,
124
+ 'api/v1/futures/userTrades': 5 * 1.67,
125
+ 'api/v1/futures/balanceFlow': 5,
126
+ 'api/v1/futures/commissionRate': 5,
127
+ 'api/v1/futures/todayPnl': 5,
128
+ },
129
+ 'post': {
130
+ 'api/v1/spot/orderTest': 1 * 1.67,
131
+ 'api/v1/spot/order': 1 * 1.67,
132
+ 'api/v1/futures/order': 1 * 1.67,
133
+ 'api/v1/spot/batchOrders': 2 * 1.67,
134
+ 'api/v1/subAccount/transfer': 1,
135
+ 'api/v1/account/withdraw': 1,
136
+ // contracts
137
+ 'api/v1/futures/marginType': 1,
138
+ 'api/v1/futures/leverage': 1,
139
+ 'api/v1/futures/batchOrders': 2 * 1.67,
140
+ 'api/v1/futures/position/trading-stop': 3 * 1.67,
141
+ 'api/v1/futures/positionMargin': 1,
142
+ 'api/v1/userDataStream': 1,
143
+ 'api/v1/listenKey': 1,
144
+ },
145
+ 'delete': {
146
+ 'api/v1/spot/order': 1 * 1.67,
147
+ 'api/v1/futures/order': 1 * 1.67,
148
+ 'api/v1/spot/openOrders': 5 * 1.67,
149
+ 'api/v1/futures/batchOrders': 5 * 1.67,
150
+ 'api/v1/spot/cancelOrderByIds': 5 * 1.67,
151
+ 'api/v1/futures/cancelOrderByIds': 5 * 1.67,
152
+ 'api/v1/listenKey': 1,
153
+ },
154
+ 'put': {
155
+ 'api/v1/listenKey': 1,
156
+ },
157
+ },
158
+ },
159
+ 'timeframes': {
160
+ '1m': '1m',
161
+ '3m': '3m',
162
+ '5m': '5m',
163
+ '15m': '15m',
164
+ '30m': '30m',
165
+ '1h': '1h',
166
+ '2h': '2h',
167
+ '4h': '4h',
168
+ '6h': '6h',
169
+ '8h': '8h',
170
+ '12h': '12h',
171
+ '1d': '1d',
172
+ '1w': '1w',
173
+ '1M': '1M',
174
+ },
175
+ 'precisionMode': number.TICK_SIZE,
176
+ 'exceptions': {
177
+ 'exact': {
178
+ '-1000': errors.OperationFailed,
179
+ '-1001': errors.OperationFailed,
180
+ '-1002': errors.PermissionDenied,
181
+ '-1003': errors.RateLimitExceeded,
182
+ '-1004': errors.BadRequest,
183
+ '-1006': errors.OperationFailed,
184
+ '-1007': errors.OperationFailed,
185
+ '-1014': errors.OperationFailed,
186
+ '-1015': errors.RateLimitExceeded,
187
+ '-1016': errors.OperationRejected,
188
+ '-1020': errors.OperationRejected,
189
+ '-1021': errors.OperationRejected,
190
+ '-1022': errors.OperationRejected,
191
+ '-1100': errors.BadRequest,
192
+ '-1101': errors.BadRequest,
193
+ '-1102': errors.BadRequest,
194
+ '-1103': errors.BadRequest,
195
+ '-1104': errors.BadRequest,
196
+ '-1105': errors.BadRequest,
197
+ '-1106': errors.BadRequest,
198
+ '-1111': errors.BadRequest,
199
+ '-1112': errors.OperationRejected,
200
+ '-1114': errors.BadRequest,
201
+ '-1115': errors.BadRequest,
202
+ '-1116': errors.BadRequest,
203
+ '-1117': errors.BadRequest,
204
+ '-1118': errors.InvalidOrder,
205
+ '-1119': errors.InvalidOrder,
206
+ '-1120': errors.BadRequest,
207
+ '-1121': errors.BadRequest,
208
+ '-1125': errors.OperationRejected,
209
+ '-1127': errors.OperationRejected,
210
+ '-1128': errors.BadRequest,
211
+ '-1130': errors.BadRequest,
212
+ '-1132': errors.OperationRejected,
213
+ '-1133': errors.OperationRejected,
214
+ '-1134': errors.OperationRejected,
215
+ '-1135': errors.OperationRejected,
216
+ '-1136': errors.OperationRejected,
217
+ '-1137': errors.OperationRejected,
218
+ '-1138': errors.OperationRejected,
219
+ '-1139': errors.OperationRejected,
220
+ '-1140': errors.OperationRejected,
221
+ '-1141': errors.InvalidOrder,
222
+ '-1142': errors.InvalidOrder,
223
+ '-1143': errors.InvalidOrder,
224
+ '-1144': errors.OperationRejected,
225
+ '-1145': errors.OperationRejected,
226
+ '-1146': errors.OperationFailed,
227
+ '-1147': errors.OperationFailed,
228
+ '-1193': errors.OperationRejected,
229
+ '-1194': errors.OperationRejected,
230
+ '-1195': errors.OperationRejected,
231
+ '-1196': errors.OperationRejected,
232
+ '-1197': errors.OperationRejected,
233
+ '-1198': errors.OperationRejected,
234
+ '-1199': errors.OperationRejected,
235
+ '-1200': errors.OperationRejected,
236
+ '-1201': errors.OperationRejected,
237
+ '-1202': errors.OperationRejected,
238
+ '-1203': errors.OperationRejected,
239
+ '-1206': errors.OperationRejected,
240
+ '-2010': errors.OperationFailed,
241
+ '-2011': errors.OperationFailed,
242
+ '-2013': errors.InvalidOrder,
243
+ '-2014': errors.PermissionDenied,
244
+ '-2015': errors.PermissionDenied,
245
+ '-2016': errors.BadRequest,
246
+ // errors above 3xxx are from swap API
247
+ '-3050': errors.ExchangeError,
248
+ '-3101': errors.OperationRejected,
249
+ '-3102': errors.OperationRejected,
250
+ '-3103': errors.BadRequest,
251
+ '-3105': errors.OperationRejected,
252
+ '-3107': errors.OperationRejected,
253
+ '-3108': errors.OperationRejected,
254
+ '-3109': errors.OperationRejected,
255
+ '-3110': errors.InsufficientFunds,
256
+ '-3116': errors.OperationRejected,
257
+ '-3117': errors.OperationRejected,
258
+ '-3120': errors.OperationRejected,
259
+ '-3124': errors.OperationRejected,
260
+ '-3125': errors.OperationRejected,
261
+ '-3126': errors.OperationRejected,
262
+ '-3127': errors.OperationFailed,
263
+ '-3128': errors.OperationRejected,
264
+ '-3129': errors.BadRequest,
265
+ '-3130': errors.OperationRejected,
266
+ '-3131': errors.NotSupported, // Leverage reduction is not supported in Isolated Margin Mode with open positions.
267
+ },
268
+ 'broad': {
269
+ 'Unknown order sent': errors.OrderNotFound,
270
+ 'Duplicate order sent': errors.InvalidOrder,
271
+ 'Market is closed': errors.OperationRejected,
272
+ 'Account has insufficient balance for requested action': errors.InsufficientFunds,
273
+ 'Market orders are not supported for this symbol': errors.OperationRejected,
274
+ 'Iceberg orders are not supported for this symbol': errors.OperationRejected,
275
+ 'Stop loss orders are not supported for this symbol': errors.OperationRejected,
276
+ 'Stop loss limit orders are not supported for this symbol': errors.OperationRejected,
277
+ 'Take profit orders are not supported for this symbol': errors.OperationRejected,
278
+ 'Take profit limit orders are not supported for this symbol': errors.OperationRejected,
279
+ 'QTY is zero or less': errors.BadRequest,
280
+ 'IcebergQty exceeds QTY': errors.OperationRejected,
281
+ 'This action disabled is on this account': errors.PermissionDenied,
282
+ 'Unsupported order combination': errors.BadRequest,
283
+ 'Order would trigger immediately': errors.OperationRejected,
284
+ 'Cancel order is invalid. Check origClOrdId and orderId': errors.OperationRejected,
285
+ 'Order would immediately match and take': errors.OperationRejected,
286
+ },
287
+ },
288
+ 'commonCurrencies': {},
289
+ 'options': {
290
+ 'defaultType': 'spot',
291
+ 'accountsByType': {
292
+ 'spot': 'MAIN',
293
+ 'swap': 'FUTURES',
294
+ },
295
+ 'networks': {
296
+ 'BTC': 'BTC',
297
+ 'ERC20': 'ETH',
298
+ 'ETH': 'ETH',
299
+ 'BEP20': 'BSC',
300
+ 'TRC20': 'TRX',
301
+ 'SOL': 'SOL',
302
+ 'MATIC': 'MATIC',
303
+ 'ARBONE': 'ARBITRUM',
304
+ 'BASE': 'BASE',
305
+ 'TON': 'TON',
306
+ 'AVAXC': 'AVAXC',
307
+ 'DOGE': 'DOGE',
308
+ 'XRP': 'XRP',
309
+ 'DOT': 'DOT',
310
+ 'ADA': 'ADA',
311
+ 'LTC': 'LTC',
312
+ 'APT': 'APT',
313
+ 'ATOM': 'ATOM',
314
+ 'ALGO': 'ALGO',
315
+ 'NEAR': 'NEAR',
316
+ 'XLM': 'XLM',
317
+ 'SUI': 'SUI',
318
+ 'ETC': 'ETC',
319
+ 'EOS': 'EOS',
320
+ 'WAVES': 'WAVES',
321
+ 'ICP': 'ICP',
322
+ 'ONE': 'ONE',
323
+ // 'CHZ2': 'CHZ2',
324
+ },
325
+ 'networksById': {
326
+ 'ETH': 'ERC20',
327
+ 'ERC20': 'ERC20',
328
+ },
329
+ },
330
+ 'features': {
331
+ 'spot': {
332
+ 'sandbox': false,
333
+ 'createOrder': {
334
+ 'marginMode': false,
335
+ 'triggerPrice': true,
336
+ 'triggerPriceType': undefined,
337
+ 'triggerDirection': false,
338
+ 'stopLossPrice': false,
339
+ 'takeProfitPrice': false,
340
+ 'attachedStopLossTakeProfit': undefined,
341
+ 'timeInForce': {
342
+ 'IOC': true,
343
+ 'FOK': true,
344
+ 'PO': true,
345
+ 'GTD': false,
346
+ },
347
+ 'hedged': false,
348
+ 'trailing': false,
349
+ 'leverage': false,
350
+ 'marketBuyRequiresPrice': false,
351
+ 'marketBuyByCost': false,
352
+ 'selfTradePrevention': false,
353
+ 'iceberg': false,
354
+ },
355
+ 'createOrders': undefined,
356
+ 'fetchOHLCV': {
357
+ 'limit': 1000,
358
+ },
359
+ 'fetchMyTrades': {
360
+ 'marginMode': false,
361
+ 'limit': 1000,
362
+ 'daysBack': 100000,
363
+ 'untilDays': 100000,
364
+ 'symbolRequired': true,
365
+ },
366
+ 'fetchOrder': {
367
+ 'marginMode': false,
368
+ 'trigger': false,
369
+ 'trailing': false,
370
+ 'symbolRequired': false,
371
+ },
372
+ 'fetchOpenOrders': {
373
+ 'marginMode': false,
374
+ 'limit': 1000,
375
+ 'trigger': false,
376
+ 'trailing': false,
377
+ 'symbolRequired': false,
378
+ },
379
+ 'fetchOrders': {
380
+ 'marginMode': false,
381
+ 'limit': 500,
382
+ 'daysBack': 100000,
383
+ 'untilDays': 100000,
384
+ 'trigger': false,
385
+ 'trailing': false,
386
+ 'symbolRequired': false,
387
+ },
388
+ 'fetchClosedOrders': undefined,
389
+ },
390
+ 'forDerivatives': {
391
+ 'createOrders': undefined,
392
+ },
393
+ 'swap': {
394
+ 'linear': undefined,
395
+ 'inverse': undefined,
396
+ },
397
+ 'future': {
398
+ 'linear': undefined,
399
+ 'inverse': undefined,
400
+ },
401
+ },
402
+ });
403
+ }
404
+ /**
405
+ * @method
406
+ * @name toobit#fetchStatus
407
+ * @description the latest known information on the availability of the exchange API
408
+ * @see https://toobit-docs.github.io/apidocs/spot/v1/en/#test-connectivity
409
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
410
+ * @returns {object} a [status structure]{@link https://docs.ccxt.com/#/?id=exchange-status-structure}
411
+ */
412
+ async fetchStatus(params = {}) {
413
+ const response = await this.commonGetApiV1Ping(params);
414
+ return {
415
+ 'status': 'ok',
416
+ 'updated': undefined,
417
+ 'eta': undefined,
418
+ 'url': undefined,
419
+ 'info': response,
420
+ };
421
+ }
422
+ /**
423
+ * @method
424
+ * @name toobit#fetchTime
425
+ * @description fetches the current integer timestamp in milliseconds from the exchange server
426
+ * @see https://toobit-docs.github.io/apidocs/spot/v1/en/#check-server-time
427
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
428
+ * @returns {int} the current integer timestamp in milliseconds from the exchange server
429
+ */
430
+ async fetchTime(params = {}) {
431
+ const response = await this.commonGetApiV1Time(params);
432
+ //
433
+ // {
434
+ // "serverTime": 1699827319559
435
+ // }
436
+ //
437
+ return this.safeInteger(response, 'serverTime');
438
+ }
439
+ /**
440
+ * @method
441
+ * @name toobit#fetchCurrencies
442
+ * @description fetches all available currencies on an exchange
443
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
444
+ * @returns {object} an associative dictionary of currencies
445
+ */
446
+ async fetchCurrencies(params = {}) {
447
+ const response = await this.commonGetApiV1ExchangeInfo(params);
448
+ this.options['exchangeInfo'] = response; // we store it in options for later use in fetchMarkets
449
+ //
450
+ // {
451
+ // "timezone": "UTC",
452
+ // "serverTime": "1755583099926",
453
+ // "brokerFilters": [],
454
+ // "symbols": [
455
+ // {
456
+ // "filters": [
457
+ // {
458
+ // "minPrice": "0.01",
459
+ // "maxPrice": "10000000.00000000",
460
+ // "tickSize": "0.01",
461
+ // "filterType": "PRICE_FILTER"
462
+ // },
463
+ // {
464
+ // "minQty": "0.0001",
465
+ // "maxQty": "4000",
466
+ // "stepSize": "0.0001",
467
+ // "filterType": "LOT_SIZE"
468
+ // },
469
+ // {
470
+ // "minNotional": "5",
471
+ // "filterType": "MIN_NOTIONAL"
472
+ // },
473
+ // {
474
+ // "minAmount": "5",
475
+ // "maxAmount": "6600000",
476
+ // "minBuyPrice": "0.01",
477
+ // "filterType": "TRADE_AMOUNT"
478
+ // },
479
+ // {
480
+ // "maxSellPrice": "99999999",
481
+ // "buyPriceUpRate": "0.1",
482
+ // "sellPriceDownRate": "0.1",
483
+ // "filterType": "LIMIT_TRADING"
484
+ // },
485
+ // {
486
+ // "buyPriceUpRate": "0.1",
487
+ // "sellPriceDownRate": "0.1",
488
+ // "filterType": "MARKET_TRADING"
489
+ // },
490
+ // {
491
+ // "noAllowMarketStartTime": "0",
492
+ // "noAllowMarketEndTime": "0",
493
+ // "limitOrderStartTime": "0",
494
+ // "limitOrderEndTime": "0",
495
+ // "limitMinPrice": "0",
496
+ // "limitMaxPrice": "0",
497
+ // "filterType": "OPEN_QUOTE"
498
+ // }
499
+ // ],
500
+ // "exchangeId": "301",
501
+ // "symbol": "ETHUSDT",
502
+ // "symbolName": "ETHUSDT",
503
+ // "status": "TRADING",
504
+ // "baseAsset": "ETH",
505
+ // "baseAssetName": "ETH",
506
+ // "baseAssetPrecision": "0.0001",
507
+ // "quoteAsset": "USDT",
508
+ // "quoteAssetName": "USDT",
509
+ // "quotePrecision": "0.01",
510
+ // "icebergAllowed": false,
511
+ // "isAggregate": false,
512
+ // "allowMargin": true,
513
+ // }
514
+ // ],
515
+ // "options": [],
516
+ // "contracts": [
517
+ // {
518
+ // "filters": [ ... ],
519
+ // "exchangeId": "301",
520
+ // "symbol": "BTC-SWAP-USDT",
521
+ // "symbolName": "BTC-SWAP-USDTUSDT",
522
+ // "status": "TRADING",
523
+ // "baseAsset": "BTC-SWAP-USDT",
524
+ // "baseAssetPrecision": "0.001",
525
+ // "quoteAsset": "USDT",
526
+ // "quoteAssetPrecision": "0.1",
527
+ // "icebergAllowed": false,
528
+ // "inverse": false,
529
+ // "index": "BTC",
530
+ // "indexToken": "BTCUSDT",
531
+ // "marginToken": "USDT",
532
+ // "marginPrecision": "0.0001",
533
+ // "contractMultiplier": "0.001",
534
+ // "underlying": "BTC",
535
+ // "riskLimits": [
536
+ // {
537
+ // "riskLimitId": "200020911",
538
+ // "quantity": "42000.0",
539
+ // "initialMargin": "0.02",
540
+ // "maintMargin": "0.01",
541
+ // "isWhite": false
542
+ // },
543
+ // {
544
+ // "riskLimitId": "200020912",
545
+ // "quantity": "84000.0",
546
+ // "initialMargin": "0.04",
547
+ // "maintMargin": "0.02",
548
+ // "isWhite": false
549
+ // },
550
+ // ...
551
+ // ]
552
+ // },
553
+ // ],
554
+ // "coins": [
555
+ // {
556
+ // "orgId": "9001",
557
+ // "coinId": "TCOM",
558
+ // "coinName": "TCOM",
559
+ // "coinFullName": "TCOM",
560
+ // "allowWithdraw": true,
561
+ // "allowDeposit": true,
562
+ // "chainTypes": [
563
+ // {
564
+ // "chainType": "BSC",
565
+ // "withdrawFee": "49.55478",
566
+ // "minWithdrawQuantity": "77",
567
+ // "maxWithdrawQuantity": "0",
568
+ // "minDepositQuantity": "48",
569
+ // "allowDeposit": true,
570
+ // "allowWithdraw": false
571
+ // }
572
+ // ],
573
+ // "isVirtual": false
574
+ // },
575
+ // ...
576
+ //
577
+ const coins = this.safeList(response, 'coins', []);
578
+ const result = {};
579
+ for (let i = 0; i < coins.length; i++) {
580
+ const coin = coins[i];
581
+ const parsed = this.parseCurrency(coin);
582
+ const code = parsed['code'];
583
+ result[code] = parsed;
584
+ }
585
+ return result;
586
+ }
587
+ parseCurrency(rawCurrency) {
588
+ const id = this.safeString(rawCurrency, 'coinId');
589
+ const code = this.safeCurrencyCode(id);
590
+ const networks = {};
591
+ const rawNetworks = this.safeList(rawCurrency, 'chainTypes');
592
+ for (let j = 0; j < rawNetworks.length; j++) {
593
+ const rawNetwork = rawNetworks[j];
594
+ const networkId = this.safeString(rawNetwork, 'chainType');
595
+ const networkCode = this.networkIdToCode(networkId);
596
+ networks[networkCode] = {
597
+ 'id': networkId,
598
+ 'network': networkCode,
599
+ 'margin': undefined,
600
+ 'deposit': this.safeBool(rawNetwork, 'allowDeposit'),
601
+ 'withdraw': this.safeBool(rawNetwork, 'allowWithdraw'),
602
+ 'active': undefined,
603
+ 'fee': this.safeNumber(rawNetwork, 'withdrawFee'),
604
+ 'precision': undefined,
605
+ 'limits': {
606
+ 'deposit': {
607
+ 'min': this.safeNumber(rawNetwork, 'minDepositQuantity'),
608
+ 'max': undefined,
609
+ },
610
+ 'withdraw': {
611
+ 'min': this.safeNumber(rawNetwork, 'minWithdrawQuantity'),
612
+ 'max': this.safeNumber(rawNetwork, 'maxWithdrawQuantity'),
613
+ },
614
+ },
615
+ 'info': rawNetwork,
616
+ };
617
+ }
618
+ return this.safeCurrencyStructure({
619
+ 'id': id,
620
+ 'code': code,
621
+ 'name': this.safeString(rawCurrency, 'coinFullName'),
622
+ 'type': undefined,
623
+ 'active': undefined,
624
+ 'deposit': this.safeBool(rawCurrency, 'allowDeposit'),
625
+ 'withdraw': this.safeBool(rawCurrency, 'allowWithdraw'),
626
+ 'fee': undefined,
627
+ 'precision': undefined,
628
+ 'limits': {
629
+ 'amount': {
630
+ 'min': undefined,
631
+ 'max': undefined,
632
+ },
633
+ 'withdraw': {
634
+ 'min': undefined,
635
+ 'max': undefined,
636
+ },
637
+ },
638
+ 'networks': networks,
639
+ 'info': rawCurrency,
640
+ });
641
+ }
642
+ /**
643
+ * @method
644
+ * @name toobit#fetchMarkets
645
+ * @description retrieves data on all markets for toobit
646
+ * @see https://toobit-docs.github.io/apidocs/spot/v1/en/#exchange-information
647
+ * @see https://toobit-docs.github.io/apidocs/usdt_swap/v1/en/#exchange-information
648
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
649
+ * @returns {object[]} an array of objects representing market data
650
+ */
651
+ async fetchMarkets(params = {}) {
652
+ let response = this.safeDict(this.options, 'exchangeInfo');
653
+ if (response !== undefined) {
654
+ this.options['exchangeInfo'] = undefined; // reset it to avoid using old cached data
655
+ }
656
+ else {
657
+ response = await this.commonGetApiV1ExchangeInfo(params);
658
+ }
659
+ //
660
+ // {
661
+ // "timezone": "UTC",
662
+ // "serverTime": "1755583099926",
663
+ // "brokerFilters": [],
664
+ // "symbols": [
665
+ // {
666
+ // "filters": [
667
+ // {
668
+ // "minPrice": "0.01",
669
+ // "maxPrice": "10000000.00000000",
670
+ // "tickSize": "0.01",
671
+ // "filterType": "PRICE_FILTER"
672
+ // },
673
+ // {
674
+ // "minQty": "0.0001",
675
+ // "maxQty": "4000",
676
+ // "stepSize": "0.0001",
677
+ // "filterType": "LOT_SIZE"
678
+ // },
679
+ // {
680
+ // "minNotional": "5",
681
+ // "filterType": "MIN_NOTIONAL"
682
+ // },
683
+ // {
684
+ // "minAmount": "5",
685
+ // "maxAmount": "6600000",
686
+ // "minBuyPrice": "0.01",
687
+ // "filterType": "TRADE_AMOUNT"
688
+ // },
689
+ // {
690
+ // "maxSellPrice": "99999999",
691
+ // "buyPriceUpRate": "0.1",
692
+ // "sellPriceDownRate": "0.1",
693
+ // "filterType": "LIMIT_TRADING"
694
+ // },
695
+ // {
696
+ // "buyPriceUpRate": "0.1",
697
+ // "sellPriceDownRate": "0.1",
698
+ // "filterType": "MARKET_TRADING"
699
+ // },
700
+ // {
701
+ // "noAllowMarketStartTime": "0",
702
+ // "noAllowMarketEndTime": "0",
703
+ // "limitOrderStartTime": "0",
704
+ // "limitOrderEndTime": "0",
705
+ // "limitMinPrice": "0",
706
+ // "limitMaxPrice": "0",
707
+ // "filterType": "OPEN_QUOTE"
708
+ // }
709
+ // ],
710
+ // "exchangeId": "301",
711
+ // "symbol": "ETHUSDT",
712
+ // "symbolName": "ETHUSDT",
713
+ // "status": "TRADING",
714
+ // "baseAsset": "ETH",
715
+ // "baseAssetName": "ETH",
716
+ // "baseAssetPrecision": "0.0001",
717
+ // "quoteAsset": "USDT",
718
+ // "quoteAssetName": "USDT",
719
+ // "quotePrecision": "0.01",
720
+ // "icebergAllowed": false,
721
+ // "isAggregate": false,
722
+ // "allowMargin": true,
723
+ // }
724
+ // ],
725
+ // "options": [],
726
+ // "contracts": [
727
+ // {
728
+ // "filters": [ ... ],
729
+ // "exchangeId": "301",
730
+ // "symbol": "BTC-SWAP-USDT",
731
+ // "symbolName": "BTC-SWAP-USDTUSDT",
732
+ // "status": "TRADING",
733
+ // "baseAsset": "BTC-SWAP-USDT",
734
+ // "baseAssetPrecision": "0.001",
735
+ // "quoteAsset": "USDT",
736
+ // "quoteAssetPrecision": "0.1",
737
+ // "icebergAllowed": false,
738
+ // "inverse": false,
739
+ // "index": "BTC",
740
+ // "indexToken": "BTCUSDT",
741
+ // "marginToken": "USDT",
742
+ // "marginPrecision": "0.0001",
743
+ // "contractMultiplier": "0.001",
744
+ // "underlying": "BTC",
745
+ // "riskLimits": [
746
+ // {
747
+ // "riskLimitId": "200020911",
748
+ // "quantity": "42000.0",
749
+ // "initialMargin": "0.02",
750
+ // "maintMargin": "0.01",
751
+ // "isWhite": false
752
+ // },
753
+ // {
754
+ // "riskLimitId": "200020912",
755
+ // "quantity": "84000.0",
756
+ // "initialMargin": "0.04",
757
+ // "maintMargin": "0.02",
758
+ // "isWhite": false
759
+ // },
760
+ // ...
761
+ // ]
762
+ // },
763
+ // ],
764
+ // "coins": [
765
+ // {
766
+ // "orgId": "9001",
767
+ // "coinId": "TCOM",
768
+ // "coinName": "TCOM",
769
+ // "coinFullName": "TCOM",
770
+ // "allowWithdraw": true,
771
+ // "allowDeposit": true,
772
+ // "chainTypes": [
773
+ // {
774
+ // "chainType": "BSC",
775
+ // "withdrawFee": "49.55478",
776
+ // "minWithdrawQuantity": "77",
777
+ // "maxWithdrawQuantity": "0",
778
+ // "minDepositQuantity": "48",
779
+ // "allowDeposit": true,
780
+ // "allowWithdraw": false
781
+ // }
782
+ // ],
783
+ // "isVirtual": false
784
+ // },
785
+ // ...
786
+ //
787
+ const symbols = this.safeList(response, 'symbols', []);
788
+ const contracts = this.safeList(response, 'contracts', []);
789
+ const all = this.arrayConcat(symbols, contracts);
790
+ const result = [];
791
+ for (let i = 0; i < all.length; i++) {
792
+ const market = all[i];
793
+ const parsed = this.parseMarket(market);
794
+ result.push(parsed);
795
+ }
796
+ return result;
797
+ }
798
+ parseMarket(market) {
799
+ const id = this.safeString(market, 'symbol');
800
+ const baseId = this.safeString(market, 'baseAsset');
801
+ const quoteId = this.safeString(market, 'quoteAsset');
802
+ const baseParts = baseId.split('-');
803
+ const baseIdClean = baseParts[0];
804
+ const base = this.safeCurrencyCode(baseIdClean);
805
+ const quote = this.safeCurrencyCode(quoteId);
806
+ const settleId = this.safeString(market, 'marginToken');
807
+ const settle = this.safeCurrencyCode(settleId);
808
+ const status = this.safeString(market, 'status');
809
+ const active = (status === 'TRADING');
810
+ const filters = this.safeList(market, 'filters', []);
811
+ const filtersByType = this.indexBy(filters, 'filterType');
812
+ const priceFilter = this.safeDict(filtersByType, 'PRICE_FILTER', {});
813
+ const lotSizeFilter = this.safeDict(filtersByType, 'LOT_SIZE', {});
814
+ const minNotionalFilter = this.safeDict(filtersByType, 'MIN_NOTIONAL', {});
815
+ let symbol = base + '/' + quote;
816
+ const isContract = ('contractMultiplier' in market);
817
+ const inverse = this.safeBool2(market, 'isInverse', 'inverse');
818
+ if (isContract) {
819
+ symbol += ':' + settle;
820
+ }
821
+ return this.safeMarketStructure({
822
+ 'id': id,
823
+ 'symbol': symbol,
824
+ 'base': base,
825
+ 'quote': quote,
826
+ 'settle': settle,
827
+ 'baseId': baseId,
828
+ 'quoteId': quoteId,
829
+ 'settleId': settleId,
830
+ 'type': isContract ? 'swap' : 'spot',
831
+ 'spot': !isContract,
832
+ 'margin': false,
833
+ 'swap': isContract,
834
+ 'future': false,
835
+ 'option': false,
836
+ 'active': active,
837
+ 'contract': isContract,
838
+ 'linear': isContract ? !inverse : undefined,
839
+ 'inverse': isContract ? inverse : undefined,
840
+ 'contractSize': this.safeNumber(market, 'contractMultiplier'),
841
+ 'expiry': undefined,
842
+ 'expiryDatetime': undefined,
843
+ 'strike': undefined,
844
+ 'optionType': undefined,
845
+ 'precision': {
846
+ 'amount': this.safeNumber(lotSizeFilter, 'stepSize'),
847
+ 'price': this.safeNumber(priceFilter, 'tickSize'),
848
+ },
849
+ 'limits': {
850
+ 'leverage': {
851
+ 'min': undefined,
852
+ 'max': undefined,
853
+ },
854
+ 'amount': {
855
+ 'min': this.safeNumber(lotSizeFilter, 'minQty'),
856
+ 'max': this.safeNumber(lotSizeFilter, 'maxQty'),
857
+ },
858
+ 'price': {
859
+ 'min': this.safeNumber(priceFilter, 'minPrice'),
860
+ 'max': this.safeNumber(priceFilter, 'maxPrice'),
861
+ },
862
+ 'cost': {
863
+ 'min': this.safeNumber(minNotionalFilter, 'minNotional'),
864
+ 'max': undefined,
865
+ },
866
+ },
867
+ 'created': undefined,
868
+ 'info': market,
869
+ });
870
+ }
871
+ /**
872
+ * @method
873
+ * @name toobit#fetchOrderBook
874
+ * @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
875
+ * @see https://toobit-docs.github.io/apidocs/spot/v1/en/#order-book
876
+ * @see https://toobit-docs.github.io/apidocs/usdt_swap/v1/en/#order-book
877
+ * @param {string} symbol unified symbol of the market to fetch the order book for
878
+ * @param {int} [limit] the maximum amount of order book entries to return
879
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
880
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
881
+ */
882
+ async fetchOrderBook(symbol, limit = undefined, params = {}) {
883
+ await this.loadMarkets();
884
+ const market = this.market(symbol);
885
+ const request = {
886
+ 'symbol': market['id'],
887
+ };
888
+ if (limit !== undefined) {
889
+ request['limit'] = limit;
890
+ }
891
+ const response = await this.commonGetQuoteV1Depth(this.extend(request, params));
892
+ //
893
+ // {
894
+ // "t": "1755593995237",
895
+ // "b": [
896
+ // [
897
+ // "115186.47",
898
+ // "4.184864"
899
+ // ],
900
+ // [
901
+ // "115186.46",
902
+ // "0.002756"
903
+ // ],
904
+ // ...
905
+ // ],
906
+ // "a": [
907
+ // [
908
+ // "115186.48",
909
+ // "6.137369"
910
+ // ],
911
+ // [
912
+ // "115186.49",
913
+ // "0.002914"
914
+ // ],
915
+ // ...
916
+ // ]
917
+ // }
918
+ //
919
+ const timestamp = this.safeInteger(response, 't');
920
+ return this.parseOrderBook(response, market['symbol'], timestamp, 'b', 'a');
921
+ }
922
+ /**
923
+ * @method
924
+ * @name toobit#fetchTrades
925
+ * @description get a list of the most recent trades for a particular symbol
926
+ * @see https://toobit-docs.github.io/apidocs/spot/v1/en/#recent-trades-list
927
+ * @see https://toobit-docs.github.io/apidocs/usdt_swap/v1/en/#recent-trades-list
928
+ * @param {string} symbol unified symbol of the market to fetch trades for
929
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
930
+ * @param {int} [limit] the maximum number of trades to fetch
931
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
932
+ * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
933
+ */
934
+ async fetchTrades(symbol, since = undefined, limit = undefined, params = {}) {
935
+ await this.loadMarkets();
936
+ const market = this.market(symbol);
937
+ const request = {
938
+ 'symbol': market['id'],
939
+ };
940
+ if (limit !== undefined) {
941
+ request['limit'] = limit;
942
+ }
943
+ const response = await this.commonGetQuoteV1Trades(this.extend(request, params));
944
+ //
945
+ // [
946
+ // {
947
+ // "t": "1755594277287",
948
+ // "p": "115276.99",
949
+ // "q": "0.001508",
950
+ // "ibm": true
951
+ // },
952
+ // ]
953
+ //
954
+ return this.parseTrades(response, market, since, limit);
955
+ }
956
+ parseTrade(trade, market = undefined) {
957
+ //
958
+ // fetchTrades
959
+ //
960
+ // {
961
+ // "t": "1755594277287",
962
+ // "p": "115276.99",
963
+ // "q": "0.001508",
964
+ // "ibm": true
965
+ // },
966
+ // // watchTrades have also an additional fields:
967
+ // "v": "4864732022868004630", // trade id
968
+ // "m": true, // is the buyer taker
969
+ //
970
+ // fetchMyTrades
971
+ //
972
+ // {
973
+ // "id": "2024934575206059008",
974
+ // "symbol": "ETHUSDT",
975
+ // "orderId": "2024934575097029888",
976
+ // "ticketId": "4864450547563401875",
977
+ // "price": "4641.21",
978
+ // "qty": "0.001",
979
+ // "time": "1756127012094",
980
+ // "isMaker": false,
981
+ // "commission": "0.00464121",
982
+ // "commissionAsset": "USDT",
983
+ // "makerRebate": "0",
984
+ // "symbolName": "ETHUSDT", // only in SPOT
985
+ // "isBuyer": false, // only in SPOT
986
+ // "feeAmount": "0.00464121", // only in SPOT
987
+ // "feeCoinId": "USDT", // only in SPOT
988
+ // "fee": { // only in SPOT
989
+ // "feeCoinId": "USDT",
990
+ // "feeCoinName": "USDT",
991
+ // "fee": "0.00464121"
992
+ // },
993
+ // "type": "LIMIT", // only in CONTRACT
994
+ // "side": "BUY_OPEN", // only in CONTRACT
995
+ // "realizedPnl": "0", // only in CONTRACT
996
+ // },
997
+ //
998
+ const timestamp = this.safeInteger2(trade, 't', 'time');
999
+ const priceString = this.safeString2(trade, 'p', 'price');
1000
+ const amountString = this.safeString2(trade, 'q', 'qty');
1001
+ const isBuyer = this.safeBool(trade, 'isBuyer');
1002
+ let side = undefined;
1003
+ let isBuyerMaker = this.safeBool(trade, 'ibm');
1004
+ if (isBuyerMaker === undefined) {
1005
+ const isBuyerTaker = this.safeBool(trade, 'm');
1006
+ if (isBuyerTaker !== undefined) {
1007
+ isBuyerMaker = !isBuyerTaker;
1008
+ }
1009
+ }
1010
+ if (isBuyerMaker !== undefined) {
1011
+ if (isBuyerMaker) {
1012
+ side = 'sell';
1013
+ }
1014
+ else {
1015
+ side = 'buy';
1016
+ }
1017
+ }
1018
+ else {
1019
+ if (isBuyer) {
1020
+ side = 'buy';
1021
+ }
1022
+ else {
1023
+ side = 'sell';
1024
+ }
1025
+ }
1026
+ const feeCurrencyId = this.safeString(trade, 'feeCoinId');
1027
+ const feeAmount = this.safeString(trade, 'feeAmount');
1028
+ let fee = undefined;
1029
+ if (feeAmount !== undefined) {
1030
+ fee = {
1031
+ 'currency': this.safeCurrencyCode(feeCurrencyId),
1032
+ 'cost': feeAmount,
1033
+ };
1034
+ }
1035
+ const isMaker = this.safeBool(trade, 'isMaker');
1036
+ let takerOrMaker = undefined;
1037
+ if (isMaker !== undefined) {
1038
+ takerOrMaker = isMaker ? 'maker' : 'taker';
1039
+ }
1040
+ market = this.safeMarket(undefined, market);
1041
+ const symbol = market['symbol'];
1042
+ return this.safeTrade({
1043
+ 'info': trade,
1044
+ 'timestamp': timestamp,
1045
+ 'datetime': this.iso8601(timestamp),
1046
+ 'symbol': symbol,
1047
+ 'id': this.safeString2(trade, 'id', 'v'),
1048
+ 'order': this.safeString(trade, 'orderId'),
1049
+ 'type': undefined,
1050
+ 'side': side,
1051
+ 'amount': amountString,
1052
+ 'price': priceString,
1053
+ 'cost': undefined,
1054
+ 'takerOrMaker': takerOrMaker,
1055
+ 'fee': fee,
1056
+ }, market);
1057
+ }
1058
+ /**
1059
+ * @method
1060
+ * @name toobit#fetchOHLCV
1061
+ * @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1062
+ * @see https://toobit-docs.github.io/apidocs/spot/v1/en/#kline-candlestick-data
1063
+ * @see https://toobit-docs.github.io/apidocs/usdt_swap/v1/en/#kline-candlestick-data
1064
+ * @param {string} symbol unified symbol of the market to fetch OHLCV data for
1065
+ * @param {string} timeframe the length of time each candle represents
1066
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
1067
+ * @param {int} [limit] the maximum amount of candles to fetch
1068
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1069
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
1070
+ */
1071
+ async fetchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
1072
+ await this.loadMarkets();
1073
+ const market = this.market(symbol);
1074
+ const request = {
1075
+ 'symbol': market['id'],
1076
+ 'interval': this.safeString(this.timeframes, timeframe, timeframe),
1077
+ };
1078
+ if (since !== undefined) {
1079
+ request['startTime'] = since;
1080
+ }
1081
+ const until = this.safeInteger(params, 'until');
1082
+ if (until !== undefined) {
1083
+ params = this.omit(params, 'until');
1084
+ request['endTime'] = until;
1085
+ }
1086
+ if (limit !== undefined) {
1087
+ request['limit'] = limit;
1088
+ }
1089
+ let response = undefined;
1090
+ let endpoint = undefined;
1091
+ [endpoint, params] = this.handleOptionAndParams(params, 'fetchOHLCV', 'price');
1092
+ if (endpoint === 'index') {
1093
+ response = await this.commonGetQuoteV1IndexKlines(this.extend(request, params));
1094
+ //
1095
+ // {
1096
+ // "code": 200,
1097
+ // "data": [
1098
+ // {
1099
+ // "t": 1669155300000,//time
1100
+ // "s": "ETHUSDT",// symbol
1101
+ // "sn": "ETHUSDT",//symbol name
1102
+ // "c": "1127.1",//Close price
1103
+ // "h": "1130.81",//High price
1104
+ // "l": "1126.17",//Low price
1105
+ // "o": "1130.8",//Open price
1106
+ // "v": "0"//Volume
1107
+ // },
1108
+ // {
1109
+ // "t": 1669156200000,
1110
+ // "s": "ETHUSDT",
1111
+ // "sn": "ETHUSDT",
1112
+ // "c": "1129.44",
1113
+ // "h": "1129.54",
1114
+ // "l": "1127.1",
1115
+ // "o": "1127.1",
1116
+ // "v": "0"
1117
+ // }
1118
+ // ]
1119
+ // }
1120
+ //
1121
+ }
1122
+ else if (endpoint === 'mark') {
1123
+ response = await this.commonGetQuoteV1MarkPriceKlines(this.extend(request, params));
1124
+ //
1125
+ // {
1126
+ // "code": 200,
1127
+ // "data": [
1128
+ // {
1129
+ // "symbol": "BTCUSDT",// Symbol
1130
+ // "time": 1670157900000,// time
1131
+ // "low": "16991.14096",//Low price
1132
+ // "open": "16991.78288",//Open price
1133
+ // "high": "16996.30641",// High prce
1134
+ // "close": "16996.30641",// Close price
1135
+ // "volume": "0",// Volume
1136
+ // "curId": 1670157900000
1137
+ // }
1138
+ // ]
1139
+ // }
1140
+ //
1141
+ }
1142
+ else {
1143
+ response = await this.commonGetQuoteV1Klines(this.extend(request, params));
1144
+ //
1145
+ // [
1146
+ // [
1147
+ // 1755540660000,
1148
+ // "116399.99",
1149
+ // "116399.99",
1150
+ // "116360.09",
1151
+ // "116360.1",
1152
+ // "2.236869",
1153
+ // 0,
1154
+ // "260303.79722607",
1155
+ // 22,
1156
+ // "2.221061",
1157
+ // "258464.10338267"
1158
+ // ],
1159
+ // ...
1160
+ //
1161
+ }
1162
+ return this.parseOHLCVs(response, market, timeframe, since, limit);
1163
+ }
1164
+ parseOHLCV(ohlcv, market = undefined) {
1165
+ return [
1166
+ this.safeIntegerN(ohlcv, [0, 'time', 't']),
1167
+ this.safeNumberN(ohlcv, [1, 'open', 'o']),
1168
+ this.safeNumberN(ohlcv, [2, 'high', 'h']),
1169
+ this.safeNumberN(ohlcv, [3, 'low', 'l']),
1170
+ this.safeNumberN(ohlcv, [4, 'close', 'c']),
1171
+ this.safeNumberN(ohlcv, [5, 'volume', 'v']),
1172
+ ];
1173
+ }
1174
+ /**
1175
+ * @method
1176
+ * @name toobit#fetchTickers
1177
+ * @description fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
1178
+ * @see https://toobit-docs.github.io/apidocs/spot/v1/en/#24hr-ticker-price-change-statistics
1179
+ * @see https://toobit-docs.github.io/apidocs/usdt_swap/v1/en/#24hr-ticker-price-change-statistics
1180
+ * @param {string[]|undefined} symbols unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
1181
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1182
+ * @returns {object} a dictionary of [ticker structures]{@link https://docs.ccxt.com/#/?id=ticker-structure}
1183
+ */
1184
+ async fetchTickers(symbols = undefined, params = {}) {
1185
+ await this.loadMarkets();
1186
+ symbols = this.marketSymbols(symbols);
1187
+ let type = undefined;
1188
+ let market = undefined;
1189
+ const request = {};
1190
+ if (symbols !== undefined) {
1191
+ const symbol = this.safeString(symbols, 0);
1192
+ market = this.market(symbol);
1193
+ const length = symbols.length;
1194
+ if (length === 1) {
1195
+ request['symbol'] = market['id'];
1196
+ }
1197
+ }
1198
+ [type, params] = this.handleMarketTypeAndParams('fetchTickers', market, params);
1199
+ let response = undefined;
1200
+ if (type === 'spot') {
1201
+ response = await this.commonGetQuoteV1Ticker24hr(this.extend(request, params));
1202
+ }
1203
+ else {
1204
+ response = await this.commonGetQuoteV1ContractTicker24hr(this.extend(request, params));
1205
+ }
1206
+ //
1207
+ // [
1208
+ // {
1209
+ // "t": "1755601440162",
1210
+ // "s": "GRDRUSDT",
1211
+ // "o": "0.38",
1212
+ // "h": "0.38",
1213
+ // "l": "0.38",
1214
+ // "c": "0.38",
1215
+ // "v": "0",
1216
+ // "qv": "0",
1217
+ // "pc": "0",
1218
+ // "pcp": "0"
1219
+ // },
1220
+ // ...
1221
+ //
1222
+ return this.parseTickers(response, symbols, params);
1223
+ }
1224
+ parseTicker(ticker, market = undefined) {
1225
+ const marketId = this.safeString(ticker, 's');
1226
+ market = this.safeMarket(marketId, market);
1227
+ const timestamp = this.safeInteger(ticker, 't');
1228
+ const last = this.safeString(ticker, 'c');
1229
+ return this.safeTicker({
1230
+ 'symbol': market['symbol'],
1231
+ 'timestamp': timestamp,
1232
+ 'datetime': this.iso8601(timestamp),
1233
+ 'high': this.safeString(ticker, 'h'),
1234
+ 'low': this.safeString(ticker, 'l'),
1235
+ 'bid': undefined,
1236
+ 'bidVolume': undefined,
1237
+ 'ask': undefined,
1238
+ 'askVolume': undefined,
1239
+ 'vwap': undefined,
1240
+ 'open': this.safeString(ticker, 'o'),
1241
+ 'close': last,
1242
+ 'last': last,
1243
+ 'previousClose': undefined,
1244
+ 'change': this.safeString(ticker, 'pc'),
1245
+ 'percentage': this.safeString(ticker, 'pcp'),
1246
+ 'average': undefined,
1247
+ 'baseVolume': this.safeString(ticker, 'v'),
1248
+ 'quoteVolume': this.safeString(ticker, 'qv'),
1249
+ 'info': ticker,
1250
+ }, market);
1251
+ }
1252
+ /**
1253
+ * @method
1254
+ * @name toobit#fetchLastPrices
1255
+ * @description fetches the last price for multiple markets
1256
+ * @see https://toobit-docs.github.io/apidocs/spot/v1/en/#symbol-price-ticker
1257
+ * @see https://toobit-docs.github.io/apidocs/usdt_swap/v1/en/#symbol-price-ticker
1258
+ * @param {string[]|undefined} symbols unified symbols of the markets to fetch the last prices
1259
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1260
+ * @returns {object} a dictionary of lastprices structures
1261
+ */
1262
+ async fetchLastPrices(symbols = undefined, params = {}) {
1263
+ await this.loadMarkets();
1264
+ symbols = this.marketSymbols(symbols);
1265
+ const request = {};
1266
+ if (symbols !== undefined) {
1267
+ const length = symbols.length;
1268
+ if (length === 1) {
1269
+ const market = this.market(symbols[0]);
1270
+ request['symbol'] = market['id'];
1271
+ }
1272
+ }
1273
+ const response = await this.commonGetQuoteV1TickerPrice(this.extend(request, params));
1274
+ //
1275
+ // [
1276
+ // {
1277
+ // "s": "BNTUSDT",
1278
+ // "si": "BNTUSDT",
1279
+ // "p": "0.823"
1280
+ // },
1281
+ //
1282
+ return this.parseLastPrices(response, symbols);
1283
+ }
1284
+ parseLastPrice(entry, market = undefined) {
1285
+ const marketId = this.safeString(entry, 's');
1286
+ market = this.safeMarket(marketId, market);
1287
+ return {
1288
+ 'symbol': market['symbol'],
1289
+ 'timestamp': undefined,
1290
+ 'datetime': undefined,
1291
+ 'price': this.safeNumberOmitZero(entry, 'price'),
1292
+ 'side': undefined,
1293
+ 'info': entry,
1294
+ };
1295
+ }
1296
+ /**
1297
+ * @method
1298
+ * @name toobit#fetchBidsAsks
1299
+ * @description fetches the bid and ask price and volume for multiple markets
1300
+ * @see https://toobit-docs.github.io/apidocs/spot/v1/en/#symbol-order-book-ticker
1301
+ * @see https://toobit-docs.github.io/apidocs/usdt_swap/v1/en/#symbol-order-book-ticker
1302
+ * @param {string[]} [symbols] unified symbols of the markets to fetch the bids and asks for, all markets are returned if not assigned
1303
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1304
+ * @returns {object} a dictionary of [ticker structures]{@link https://docs.ccxt.com/#/?id=ticker-structure}
1305
+ */
1306
+ async fetchBidsAsks(symbols = undefined, params = {}) {
1307
+ await this.loadMarkets();
1308
+ symbols = this.marketSymbols(symbols);
1309
+ const request = {};
1310
+ if (symbols !== undefined) {
1311
+ const length = symbols.length;
1312
+ if (length === 1) {
1313
+ const market = this.market(symbols[0]);
1314
+ request['symbol'] = market['id'];
1315
+ }
1316
+ }
1317
+ const response = await this.commonGetQuoteV1TickerBookTicker(this.extend(request, params));
1318
+ //
1319
+ // [
1320
+ // {
1321
+ // "s": "GRDRUSDT",
1322
+ // "b": "0",
1323
+ // "bq": "0",
1324
+ // "a": "0",
1325
+ // "aq": "0",
1326
+ // "t": "1755936610506"
1327
+ // }, ...
1328
+ //
1329
+ return this.parseBidsAsksCustom(response, symbols);
1330
+ }
1331
+ parseBidsAsksCustom(tickers, symbols = undefined, params = {}) {
1332
+ const results = [];
1333
+ for (let i = 0; i < tickers.length; i++) {
1334
+ const parsedTicker = this.parseBidAskCustom(tickers[i]);
1335
+ const ticker = this.extend(parsedTicker, params);
1336
+ results.push(ticker);
1337
+ }
1338
+ symbols = this.marketSymbols(symbols);
1339
+ return this.filterByArray(results, 'symbol', symbols);
1340
+ }
1341
+ parseBidAskCustom(ticker) {
1342
+ return {
1343
+ 'timestamp': this.safeString(ticker, 't'),
1344
+ 'symbol': this.safeString(ticker, 's'),
1345
+ 'bid': this.safeNumber(ticker, 'b'),
1346
+ 'bidVolume': this.safeNumber(ticker, 'bq'),
1347
+ 'ask': this.safeNumber(ticker, 'a'),
1348
+ 'askVolume': this.safeNumber(ticker, 'aq'),
1349
+ 'info': ticker,
1350
+ };
1351
+ }
1352
+ /**
1353
+ * @method
1354
+ * @name toobit#fetchFundingRates
1355
+ * @description fetch the funding rate for multiple markets
1356
+ * @see https://toobit-docs.github.io/apidocs/usdt_swap/v1/en/#funding-rate
1357
+ * @param {string[]|undefined} symbols list of unified market symbols
1358
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1359
+ * @returns {object[]} a list of [funding rates structures]{@link https://docs.ccxt.com/#/?id=funding-rates-structure}, indexe by market symbols
1360
+ */
1361
+ async fetchFundingRates(symbols = undefined, params = {}) {
1362
+ await this.loadMarkets();
1363
+ symbols = this.marketSymbols(symbols);
1364
+ const request = {};
1365
+ if (symbols !== undefined) {
1366
+ const length = symbols.length;
1367
+ if (length === 1) {
1368
+ const market = this.market(symbols[0]);
1369
+ request['symbol'] = market['id'];
1370
+ }
1371
+ }
1372
+ const response = await this.commonGetApiV1FuturesFundingRate(this.extend(request, params));
1373
+ //
1374
+ // [
1375
+ // {
1376
+ // "symbol": "BTC-SWAP-USDT",
1377
+ // "rate": "0.0001071148112848",
1378
+ // "nextFundingTime": "1755964800000"
1379
+ // },...
1380
+ //
1381
+ return this.parseFundingRates(response, symbols);
1382
+ }
1383
+ parseFundingRate(contract, market = undefined) {
1384
+ const marketId = this.safeString(contract, 'symbol');
1385
+ const symbol = this.safeSymbol(marketId, market);
1386
+ const nextFundingRate = this.safeNumber(contract, 'rate');
1387
+ const nextFundingRateTimestamp = this.safeInteger(contract, 'nextFundingTime');
1388
+ return {
1389
+ 'info': contract,
1390
+ 'symbol': symbol,
1391
+ 'markPrice': undefined,
1392
+ 'indexPrice': undefined,
1393
+ 'interestRate': undefined,
1394
+ 'estimatedSettlePrice': undefined,
1395
+ 'timestamp': undefined,
1396
+ 'datetime': undefined,
1397
+ 'previousFundingRate': undefined,
1398
+ 'nextFundingRate': undefined,
1399
+ 'previousFundingTimestamp': undefined,
1400
+ 'nextFundingTimestamp': undefined,
1401
+ 'previousFundingDatetime': undefined,
1402
+ 'nextFundingDatetime': undefined,
1403
+ 'fundingRate': nextFundingRate,
1404
+ 'fundingTimestamp': nextFundingRateTimestamp,
1405
+ 'fundingDatetime': this.iso8601(nextFundingRateTimestamp),
1406
+ 'interval': undefined,
1407
+ };
1408
+ }
1409
+ /**
1410
+ * @method
1411
+ * @name toobit#fetchFundingRateHistory
1412
+ * @description fetches historical funding rate prices
1413
+ * @see https://toobit-docs.github.io/apidocs/usdt_swap/v1/en/#get-funding-rate-history
1414
+ * @param {string} symbol unified symbol of the market to fetch the funding rate history for
1415
+ * @param {int} [since] timestamp in ms of the earliest funding rate to fetch
1416
+ * @param {int} [limit] the maximum amount of [funding rate structures]{@link https://docs.ccxt.com/#/?id=funding-rate-history-structure} to fetch
1417
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1418
+ * @param {int} [params.until] timestamp in ms of the latest funding rate to fetch
1419
+ * @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)
1420
+ * @returns {object[]} a list of [funding rate structures]{@link https://docs.ccxt.com/#/?id=funding-rate-history-structure}
1421
+ */
1422
+ async fetchFundingRateHistory(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1423
+ await this.loadMarkets();
1424
+ let paginate = false;
1425
+ [paginate, params] = this.handleOptionAndParams(params, 'fetchFundingRateHistory', 'paginate');
1426
+ if (paginate) {
1427
+ return await this.fetchPaginatedCallDeterministic('fetchFundingRateHistory', symbol, since, limit, '8h', params);
1428
+ }
1429
+ const market = this.market(symbol);
1430
+ const request = {
1431
+ 'symbol': market['id'],
1432
+ };
1433
+ if (limit !== undefined) {
1434
+ request['limit'] = limit;
1435
+ }
1436
+ const response = await this.commonGetApiV1FuturesHistoryFundingRate(this.extend(request, params));
1437
+ //
1438
+ // [
1439
+ // {
1440
+ // "id": "869931",
1441
+ // "symbol": "BTC-SWAP-USDT",
1442
+ // "settleTime": "1755936000000",
1443
+ // "settleRate": "0.0001"
1444
+ // }, ...
1445
+ //
1446
+ return this.parseFundingRateHistories(response, market, since, limit);
1447
+ }
1448
+ parseFundingRateHistory(contract, market = undefined) {
1449
+ const timestamp = this.safeInteger(contract, 'settleTime');
1450
+ const marketId = this.safeString(contract, 'symbol');
1451
+ return {
1452
+ 'info': contract,
1453
+ 'symbol': this.safeSymbol(marketId, market),
1454
+ 'fundingRate': this.safeNumber(contract, 'settleRate'),
1455
+ 'timestamp': timestamp,
1456
+ 'datetime': this.iso8601(timestamp),
1457
+ };
1458
+ }
1459
+ /**
1460
+ * @method
1461
+ * @name toobit#fetchBalance
1462
+ * @description query for balance and get the amount of funds available for trading or funds locked in orders
1463
+ * @see https://toobit-docs.github.io/apidocs/spot/v1/en/#account-information-user_data
1464
+ * @see https://toobit-docs.github.io/apidocs/usdt_swap/v1/en/#futures-account-balance-user_data
1465
+ * @param {object} [params] extra parameters specific to the exchange API endpointinvalid
1466
+ * @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
1467
+ */
1468
+ async fetchBalance(params = {}) {
1469
+ await this.loadMarkets();
1470
+ let response = undefined;
1471
+ let marketType = undefined;
1472
+ [marketType, params] = this.handleMarketTypeAndParams('fetchBalance', undefined, params);
1473
+ if (this.inArray(marketType, ['swap', 'future'])) {
1474
+ response = await this.privateGetApiV1FuturesBalance();
1475
+ //
1476
+ // [
1477
+ // {
1478
+ // "asset": "USDT", // asset
1479
+ // "balance": "999999999999.982", // total
1480
+ // "availableBalance": "1899999999978.4995", // available balance Include unrealized pnl
1481
+ // "positionMargin": "11.9825", //position Margin
1482
+ // "orderMargin": "9.5", //order Margin
1483
+ // "crossUnRealizedPnl": "10.01" //The unrealized profit and loss of cross position
1484
+ // }
1485
+ // ]
1486
+ //
1487
+ }
1488
+ else {
1489
+ response = await this.privateGetApiV1Account();
1490
+ //
1491
+ // {
1492
+ // "userId": "912902020",
1493
+ // "balances": [
1494
+ // {
1495
+ // "asset": "ETH",
1496
+ // "assetId": "ETH",
1497
+ // "assetName": "ETH",
1498
+ // "total": "0.025",
1499
+ // "free": "0.025",
1500
+ // "locked": "0"
1501
+ // }
1502
+ // ]
1503
+ // }
1504
+ //
1505
+ }
1506
+ return this.parseBalance(response);
1507
+ }
1508
+ parseBalance(response) {
1509
+ const result = {
1510
+ 'info': response,
1511
+ 'timestamp': undefined,
1512
+ 'datetime': undefined,
1513
+ };
1514
+ const balances = this.safeList(response, 'balances', response);
1515
+ for (let i = 0; i < balances.length; i++) {
1516
+ const balance = balances[i];
1517
+ const code = this.safeCurrencyCode(this.safeString(balance, 'asset'));
1518
+ const account = this.account();
1519
+ account['free'] = this.safeString2(balance, 'free', 'availableBalance');
1520
+ account['total'] = this.safeString2(balance, 'total', 'balance');
1521
+ account['used'] = this.safeString(balance, 'locked');
1522
+ result[code] = account;
1523
+ }
1524
+ return this.safeBalance(result);
1525
+ }
1526
+ /**
1527
+ * @method
1528
+ * @name toobit#createOrder
1529
+ * @description create a trade order
1530
+ * @see https://toobit-docs.github.io/apidocs/spot/v1/en/#new-order-trade
1531
+ * @see https://toobit-docs.github.io/apidocs/usdt_swap/v1/en/#new-order-trade
1532
+ * @param {string} symbol unified symbol of the market to create an order in
1533
+ * @param {string} type 'market', 'limit'
1534
+ * @param {string} side 'buy' or 'sell'
1535
+ * @param {float} amount how much of currency you want to trade in units of base currency
1536
+ * @param {float} [price] the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
1537
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1538
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
1539
+ */
1540
+ async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
1541
+ await this.loadMarkets();
1542
+ const market = this.market(symbol);
1543
+ let request = {};
1544
+ let response = undefined;
1545
+ if (market['spot']) {
1546
+ [request, params] = this.createOrderRequest(symbol, type, side, amount, price, params);
1547
+ response = await this.privatePostApiV1SpotOrder(this.extend(request, params));
1548
+ }
1549
+ else {
1550
+ [request, params] = this.createContractOrderRequest(symbol, type, side, amount, price, params);
1551
+ response = await this.privatePostApiV1FuturesOrder(this.extend(request, params));
1552
+ }
1553
+ //
1554
+ // {
1555
+ // "symbol": "ETHUSDT",
1556
+ // "price": "0",
1557
+ // "origQty": "0.001",
1558
+ // "orderId": "2024837825254460160",
1559
+ // "clientOrderId": "1756115478113679",
1560
+ // "executedQty": "0",
1561
+ // "status": "PENDING_NEW",
1562
+ // "timeInForce": "GTC",
1563
+ // "type": "MARKET",
1564
+ // "side": "SELL"
1565
+ // "accountId": "1783404067076253952", // only in spot
1566
+ // "symbolName": "ETHUSDT", // only in spot
1567
+ // "transactTime": "1756115478604", // only in spot
1568
+ // "time": "1668418485058", // only in contract
1569
+ // "updateTime": "1668418485058", // only in contract
1570
+ // "leverage": "2", // only in contract
1571
+ // "avgPrice": "0", // only in contract
1572
+ // "marginLocked": "9.5", // only in contract
1573
+ // "priceType": "INPUT" // only in contract
1574
+ // }
1575
+ //
1576
+ return this.parseOrder(response, market);
1577
+ }
1578
+ createOrderRequest(symbol, type, side, amount, price = undefined, params = {}) {
1579
+ const market = this.market(symbol);
1580
+ const id = market['id'];
1581
+ const request = {
1582
+ 'symbol': id,
1583
+ 'side': side.toUpperCase(),
1584
+ };
1585
+ if (price !== undefined) {
1586
+ request['price'] = this.priceToPrecision(symbol, price);
1587
+ }
1588
+ let cost = undefined;
1589
+ [cost, params] = this.handleParamString(params, 'cost');
1590
+ if (type === 'market') {
1591
+ if (cost === undefined && side === 'buy') {
1592
+ throw new errors.ArgumentsRequired(this.id + ' createOrder() requires params["cost"] for market buy order');
1593
+ }
1594
+ else {
1595
+ request['quantity'] = this.costToPrecision(symbol, cost);
1596
+ }
1597
+ }
1598
+ else {
1599
+ request['quantity'] = this.amountToPrecision(symbol, amount);
1600
+ }
1601
+ let isPostOnly = undefined;
1602
+ [isPostOnly, params] = this.handlePostOnly(type === 'market', false, params);
1603
+ if (isPostOnly) {
1604
+ request['type'] = 'LIMIT_MAKER';
1605
+ }
1606
+ else {
1607
+ request['type'] = type.toUpperCase();
1608
+ }
1609
+ return [request, params];
1610
+ }
1611
+ createContractOrderRequest(symbol, type, side, amount, price = undefined, params = {}) {
1612
+ const market = this.market(symbol);
1613
+ const request = {
1614
+ 'symbol': market['id'],
1615
+ 'quantity': this.amountToPrecision(symbol, amount),
1616
+ };
1617
+ let reduceOnly = undefined;
1618
+ [reduceOnly, params] = this.handleParamBool(params, 'reduceOnly');
1619
+ if (side === 'buy') {
1620
+ side = reduceOnly ? 'SELL_CLOSE' : 'BUY_OPEN';
1621
+ }
1622
+ else if (side === 'sell') {
1623
+ side = reduceOnly ? 'BUY_CLOSE' : 'SELL_OPEN';
1624
+ }
1625
+ request['side'] = side;
1626
+ if (price !== undefined) {
1627
+ request['price'] = this.priceToPrecision(symbol, price);
1628
+ }
1629
+ if (this.inArray(type, ['limit', 'LIMIT'])) {
1630
+ request['type'] = type.toUpperCase();
1631
+ request['price'] = this.priceToPrecision(symbol, price);
1632
+ }
1633
+ else if (type === 'market') {
1634
+ request['type'] = 'LIMIT'; // weird, but exchange works this way
1635
+ request['priceType'] = 'MARKET';
1636
+ }
1637
+ let isPostOnly = undefined;
1638
+ [isPostOnly, params] = this.handlePostOnly(type === 'market', false, params);
1639
+ if (isPostOnly) {
1640
+ request['timeInForce'] = 'LIMIT_MAKER';
1641
+ }
1642
+ const values = this.handleTriggerPricesAndParams(symbol, params);
1643
+ const triggerPrice = values[0];
1644
+ params = values[3];
1645
+ if (triggerPrice !== undefined) {
1646
+ request['stopPrice'] = triggerPrice;
1647
+ }
1648
+ const stopLoss = this.safeDict(params, 'stopLoss');
1649
+ const takeProfit = this.safeDict(params, 'takeProfit');
1650
+ const triggerPriceTypes = {
1651
+ 'mark': 'MARK_PRICE',
1652
+ 'last': 'CONTRACT_PRICE',
1653
+ };
1654
+ if (stopLoss !== undefined) {
1655
+ request['stopLoss'] = this.safeValue(stopLoss, 'triggerPrice');
1656
+ const limitPrice = this.safeValue(stopLoss, 'price');
1657
+ if (limitPrice !== undefined) {
1658
+ request['slOrderType'] = 'LIMIT';
1659
+ request['slLimitPrice'] = this.priceToPrecision(symbol, limitPrice);
1660
+ }
1661
+ const triggerPriceType = this.safeString(stopLoss, 'triggerPriceType');
1662
+ if (triggerPriceType !== undefined) {
1663
+ request['slTriggerBy'] = this.safeString(triggerPriceTypes, triggerPriceType, triggerPriceType);
1664
+ }
1665
+ params = this.omit(params, 'stopLoss');
1666
+ }
1667
+ if (takeProfit !== undefined) {
1668
+ request['takeProfit'] = this.safeValue(takeProfit, 'triggerPrice');
1669
+ const limitPrice = this.safeValue(takeProfit, 'price');
1670
+ if (limitPrice !== undefined) {
1671
+ request['tpOrderType'] = 'LIMIT';
1672
+ request['tpLimitPrice'] = this.priceToPrecision(symbol, limitPrice);
1673
+ }
1674
+ const triggerPriceType = this.safeString(takeProfit, 'triggerPriceType');
1675
+ if (triggerPriceType !== undefined) {
1676
+ request['tpTriggerBy'] = this.safeString(triggerPriceTypes, triggerPriceType, triggerPriceType);
1677
+ }
1678
+ params = this.omit(params, 'takeProfit');
1679
+ }
1680
+ if (!('newClientOrderId' in params)) {
1681
+ request['newClientOrderId'] = this.uuid();
1682
+ }
1683
+ return [request, params];
1684
+ }
1685
+ parseOrder(order, market = undefined) {
1686
+ //
1687
+ // createOrder, cancelOrder
1688
+ //
1689
+ // {
1690
+ // "symbol": "ETHUSDT",
1691
+ // "price": "0",
1692
+ // "origQty": "0.001",
1693
+ // "orderId": "2024837825254460160",
1694
+ // "clientOrderId": "1756115478113679",
1695
+ // "executedQty": "0",
1696
+ // "status": "PENDING_NEW",
1697
+ // "timeInForce": "GTC",
1698
+ // "type": "MARKET",
1699
+ // "side": "SELL"
1700
+ // "accountId": "1783404067076253952", // only in spot
1701
+ // "symbolName": "ETHUSDT", // only in spot
1702
+ // "transactTime": "1756115478604", // only in spot
1703
+ // "time": "1668418485058", // only in contract
1704
+ // "updateTime": "1668418485058", // only in contract
1705
+ // "leverage": "2", // only in contract
1706
+ // "avgPrice": "0", // only in contract
1707
+ // "marginLocked": "9.5", // only in contract
1708
+ // "priceType": "INPUT" // only in contract
1709
+ // }
1710
+ //
1711
+ //
1712
+ // fetchOrder, fetchOrders, fetchOpenOrders
1713
+ //
1714
+ // {
1715
+ // "time": "1756140208069",
1716
+ // "updateTime": "1756140208078",
1717
+ // "orderId": "2025045271033977089",
1718
+ // "clientOrderId": "17561402075722006",
1719
+ // "symbol": "ETHUSDT",
1720
+ // "price": "3000",
1721
+ // "origQty": "0.002",
1722
+ // "executedQty": "0",
1723
+ // "avgPrice": "0",
1724
+ // "type": "LIMIT",
1725
+ // "side": "BUY",
1726
+ // "timeInForce": "GTC",
1727
+ // "status": "NEW",
1728
+ // "accountId": "1783404067076253952", // only in SPOT
1729
+ // "exchangeId": "301", // only in SPOT
1730
+ // "symbolName": "ETHUSDT", // only in SPOT
1731
+ // "cummulativeQuoteQty": "0", // only in SPOT
1732
+ // "cumulativeQuoteQty": "0", // only in SPOT
1733
+ // "stopPrice": "0.0", // only in SPOT
1734
+ // "icebergQty": "0.0", // only in SPOT
1735
+ // "isWorking": true // only in SPOT
1736
+ // "leverage": "2", // only in CONTRACT
1737
+ // "marginLocked": "9.5", // only in CONTRACT
1738
+ // "priceType": "INPUT" // only in CONTRACT
1739
+ // "triggerType": "0", // only in CONTRACT fetchClosedOrders
1740
+ // "fallType": "0", // only in CONTRACT fetchClosedOrders
1741
+ // "activeStatus": "0" // only in CONTRACT fetchClosedOrders
1742
+ // }
1743
+ //
1744
+ const timestamp = this.safeInteger2(order, 'transactTime', 'time');
1745
+ const marketId = this.safeString(order, 'symbol');
1746
+ market = this.safeMarket(marketId, market);
1747
+ const rawType = this.safeString(order, 'type');
1748
+ const rawSideLower = this.safeStringLower(order, 'side');
1749
+ let triggerPrice = this.omitZero(this.safeString(order, 'stopPrice'));
1750
+ if (triggerPrice === '0.0') {
1751
+ triggerPrice = undefined;
1752
+ }
1753
+ return this.safeOrder({
1754
+ 'info': order,
1755
+ 'id': this.safeString(order, 'orderId'),
1756
+ 'clientOrderId': this.safeString(order, 'clientOrderId'),
1757
+ 'timestamp': timestamp,
1758
+ 'datetime': this.iso8601(timestamp),
1759
+ 'lastTradeTimestamp': undefined,
1760
+ 'lastUpdateTimestamp': this.safeInteger(order, 'updateTime'),
1761
+ 'status': this.parseOrderStatus(this.safeString(order, 'status')),
1762
+ 'symbol': market['symbol'],
1763
+ 'type': this.parseOrderType(rawType),
1764
+ 'timeInForce': this.safeString(order, 'timeInForce'),
1765
+ 'postOnly': (rawType === 'LIMIT_MAKER'),
1766
+ 'side': rawSideLower,
1767
+ 'price': this.omitZero(this.safeString(order, 'price')),
1768
+ 'triggerPrice': triggerPrice,
1769
+ 'cost': this.omitZero(this.safeString(order, 'cumulativeQuoteQty')),
1770
+ 'average': this.safeString(order, 'avgPrice'),
1771
+ 'amount': this.safeString(order, 'origQty'),
1772
+ 'filled': this.safeString(order, 'executedQty'),
1773
+ 'remaining': undefined,
1774
+ 'trades': undefined,
1775
+ 'fee': undefined,
1776
+ 'marginMode': undefined,
1777
+ 'reduceOnly': undefined,
1778
+ 'leverage': undefined,
1779
+ 'hedged': undefined,
1780
+ }, market);
1781
+ }
1782
+ parseOrderStatus(status) {
1783
+ const statuses = {
1784
+ 'PENDING_NEW': 'open',
1785
+ 'NEW': 'open',
1786
+ 'PARTIALLY_FILLED': 'open',
1787
+ 'FILLED': 'closed',
1788
+ 'PENDING_CANCEL': 'canceled',
1789
+ 'CANCELED': 'canceled',
1790
+ 'REJECTED': 'canceled',
1791
+ };
1792
+ return this.safeString(statuses, status, status);
1793
+ }
1794
+ parseOrderType(status) {
1795
+ const statuses = {
1796
+ 'MARKET': 'market',
1797
+ 'LIMIT': 'limit',
1798
+ 'LIMIT_MAKER': 'limit',
1799
+ };
1800
+ return this.safeString(statuses, status, status);
1801
+ }
1802
+ /**
1803
+ * @method
1804
+ * @name toobit#cancelOrder
1805
+ * @description cancels an open order
1806
+ * @see https://toobit-docs.github.io/apidocs/spot/v1/en/#cancel-order-trade
1807
+ * @see https://toobit-docs.github.io/apidocs/usdt_swap/v1/en/#cancel-order-trade
1808
+ * @param {string} id order id
1809
+ * @param {string} symbol unified symbol of the market the order was made in
1810
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1811
+ * @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
1812
+ */
1813
+ async cancelOrder(id, symbol = undefined, params = {}) {
1814
+ const request = {};
1815
+ if (this.safeString(params, 'clientOrderId') === undefined) {
1816
+ request['orderId'] = id;
1817
+ }
1818
+ let market = undefined;
1819
+ if (symbol !== undefined) {
1820
+ market = this.market(symbol);
1821
+ request['symbol'] = market['id'];
1822
+ }
1823
+ let marketType = undefined;
1824
+ [marketType, params] = this.handleMarketTypeAndParams('cancelOrder', market, params, 'none');
1825
+ if (marketType === 'none') {
1826
+ throw new errors.ArgumentsRequired(this.id + ' cancelOrder() requires a symbol argument or the "defaultType" parameter to be set to "spot" or "swap"');
1827
+ }
1828
+ let response = undefined;
1829
+ if (marketType === 'spot') {
1830
+ response = await this.privateDeleteApiV1SpotOrder(this.extend(request, params));
1831
+ }
1832
+ else {
1833
+ response = await this.privateDeleteApiV1FuturesOrder(this.extend(request, params));
1834
+ }
1835
+ // response same as in `createOrder`
1836
+ const status = this.parseOrderStatus(this.safeString(response, 'status'));
1837
+ if (status !== 'open') {
1838
+ throw new errors.OrderNotFound(this.id + ' order ' + id + ' can not be canceled, ' + this.json(response));
1839
+ }
1840
+ return this.parseOrder(response, market);
1841
+ }
1842
+ /**
1843
+ * @method
1844
+ * @name toobit#cancelAllOrders
1845
+ * @description cancel all open orders in a market
1846
+ * @see https://toobit-docs.github.io/apidocs/spot/v1/en/#cancel-all-open-orders-trade
1847
+ * @see https://toobit-docs.github.io/apidocs/usdt_swap/v1/en/#cancel-orders-trade
1848
+ * @param {string} symbol unified symbol
1849
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1850
+ * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
1851
+ */
1852
+ async cancelAllOrders(symbol = undefined, params = {}) {
1853
+ await this.loadMarkets();
1854
+ const request = {};
1855
+ let market = undefined;
1856
+ if (symbol !== undefined) {
1857
+ market = this.market(symbol);
1858
+ request['symbol'] = market['id'];
1859
+ }
1860
+ let marketType = undefined;
1861
+ [marketType, params] = this.handleMarketTypeAndParams('cancelAllOrders', market, params, 'none');
1862
+ if (marketType === 'none') {
1863
+ throw new errors.ArgumentsRequired(this.id + ' cancelAllOrders() requires a symbol argument or the "defaultType" parameter to be set to "spot" or "swap"');
1864
+ }
1865
+ let response = undefined;
1866
+ if (marketType === 'spot') {
1867
+ response = await this.privateDeleteApiV1SpotOpenOrders(this.extend(request, params));
1868
+ //
1869
+ // {"success":true} // always same response
1870
+ //
1871
+ }
1872
+ else {
1873
+ response = await this.privateDeleteApiV1FuturesBatchOrders(this.extend(request, params));
1874
+ //
1875
+ // { "code": 200, "message":"success", "timestamp":1541161088303 }
1876
+ //
1877
+ }
1878
+ return [
1879
+ this.safeOrder({
1880
+ 'info': response,
1881
+ }),
1882
+ ];
1883
+ }
1884
+ /**
1885
+ * @method
1886
+ * @name toobit#cancelOrders
1887
+ * @description cancel multiple orders
1888
+ * @see https://toobit-docs.github.io/apidocs/spot/v1/en/#cancel-multiple-orders-trade
1889
+ * @see https://toobit-docs.github.io/apidocs/usdt_swap/v1/en/#cancel-multiple-orders-trade
1890
+ * @param {string[]} ids order ids
1891
+ * @param {string} [symbol] unified market symbol
1892
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1893
+ * @returns {object} an list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
1894
+ */
1895
+ async cancelOrders(ids, symbol = undefined, params = {}) {
1896
+ await this.loadMarkets();
1897
+ const idsString = ids.join(',');
1898
+ const request = {
1899
+ 'ids': idsString,
1900
+ };
1901
+ let market = undefined;
1902
+ if (symbol !== undefined) {
1903
+ market = this.market(symbol);
1904
+ }
1905
+ let marketType = undefined;
1906
+ [marketType, params] = this.handleMarketTypeAndParams('cancelOrders', market, params, 'none');
1907
+ if (marketType === 'none') {
1908
+ throw new errors.ArgumentsRequired(this.id + ' cancelOrders() requires a symbol argument or the "defaultType" parameter to be set to "spot" or "swap"');
1909
+ }
1910
+ let response = undefined;
1911
+ if (marketType === 'spot') {
1912
+ response = await this.privateDeleteApiV1SpotCancelOrderByIds(this.extend(request, params));
1913
+ //
1914
+ // {"success":true} // always same response
1915
+ //
1916
+ }
1917
+ else {
1918
+ response = await this.privateDeleteApiV1FuturesCancelOrderByIds(this.extend(request, params));
1919
+ //
1920
+ // {
1921
+ // "code":200,
1922
+ // "result":[
1923
+ // {
1924
+ // "orderId":"1327047813809448704",
1925
+ // "code":-2013
1926
+ // },
1927
+ // {
1928
+ // "orderId":"1327047814212101888",
1929
+ // "code":-2013
1930
+ // }
1931
+ // ]
1932
+ // }
1933
+ //
1934
+ // or empty array if no orders were canceled
1935
+ }
1936
+ const result = this.safeList(response, 'result', []);
1937
+ return this.parseOrders(result, market);
1938
+ }
1939
+ /**
1940
+ * @method
1941
+ * @name toobit#fetchOrder
1942
+ * @description fetches information on an order made by the user
1943
+ * @see https://toobit-docs.github.io/apidocs/spot/v1/en/#query-order-user_data
1944
+ * @see https://toobit-docs.github.io/apidocs/usdt_swap/v1/en/#query-order-user_data
1945
+ * @param {string} id the order id
1946
+ * @param {string} symbol unified symbol of the market the order was made in
1947
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1948
+ * @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
1949
+ */
1950
+ async fetchOrder(id, symbol = undefined, params = {}) {
1951
+ if (symbol === undefined) {
1952
+ throw new errors.ArgumentsRequired(this.id + ' fetchOrder() requires a symbol argument');
1953
+ }
1954
+ await this.loadMarkets();
1955
+ const request = {
1956
+ 'orderId': id,
1957
+ };
1958
+ const market = this.market(symbol);
1959
+ let response = undefined;
1960
+ if (market['spot']) {
1961
+ response = await this.privateGetApiV1SpotOrder(this.extend(request, params));
1962
+ }
1963
+ else {
1964
+ response = await this.privateGetApiV1FuturesOrder(this.extend(request, params));
1965
+ }
1966
+ //
1967
+ // {
1968
+ // "time": "1756140208069",
1969
+ // "updateTime": "1756140208078",
1970
+ // "orderId": "2025045271033977089",
1971
+ // "clientOrderId": "17561402075722006",
1972
+ // "symbol": "ETHUSDT",
1973
+ // "price": "3000",
1974
+ // "origQty": "0.002",
1975
+ // "executedQty": "0",
1976
+ // "avgPrice": "0",
1977
+ // "type": "LIMIT",
1978
+ // "side": "BUY",
1979
+ // "timeInForce": "GTC",
1980
+ // "status": "NEW",
1981
+ // "accountId": "1783404067076253952", // only in SPOT
1982
+ // "exchangeId": "301", // only in SPOT
1983
+ // "symbolName": "ETHUSDT", // only in SPOT
1984
+ // "cummulativeQuoteQty": "0", // only in SPOT
1985
+ // "cumulativeQuoteQty": "0", // only in SPOT
1986
+ // "stopPrice": "0.0", // only in SPOT
1987
+ // "icebergQty": "0.0", // only in SPOT
1988
+ // "isWorking": true // only in SPOT
1989
+ // "leverage": "2", // only in CONTRACT
1990
+ // "marginLocked": "9.5", // only in CONTRACT
1991
+ // "priceType": "INPUT" // only in CONTRACT
1992
+ // }
1993
+ //
1994
+ return this.parseOrder(response, market);
1995
+ }
1996
+ /**
1997
+ * @method
1998
+ * @name toobit#fetchOpenOrders
1999
+ * @description fetches information on multiple orders made by the user
2000
+ * @see https://toobit-docs.github.io/apidocs/spot/v1/en/#current-open-orders-user_data
2001
+ * @see https://toobit-docs.github.io/apidocs/usdt_swap/v1/en/#query-current-open-order-user_data
2002
+ * @param {string} symbol unified market symbol of the market orders were made in
2003
+ * @param {int} [since] the earliest time in ms to fetch orders for
2004
+ * @param {int} [limit] the maximum number of order structures to retrieve
2005
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2006
+ * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
2007
+ */
2008
+ async fetchOpenOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
2009
+ await this.loadMarkets();
2010
+ const request = {};
2011
+ let market = undefined;
2012
+ if (symbol !== undefined) {
2013
+ market = this.market(symbol);
2014
+ request['symbol'] = market['id'];
2015
+ }
2016
+ if (limit !== undefined) {
2017
+ request['limit'] = limit;
2018
+ }
2019
+ let marketType = undefined;
2020
+ [marketType, params] = this.handleMarketTypeAndParams('fetchOrders', market, params);
2021
+ let response = undefined;
2022
+ if (marketType === 'spot') {
2023
+ response = await this.privateGetApiV1SpotOpenOrders(this.extend(request, params));
2024
+ //
2025
+ // [
2026
+ // {
2027
+ // "accountId": "1783404067076253952",
2028
+ // "exchangeId": "301",
2029
+ // "symbol": "ETHUSDT",
2030
+ // "symbolName": "ETHUSDT",
2031
+ // "clientOrderId": "17561415157172008",
2032
+ // "orderId": "2025056244339984384",
2033
+ // "price": "3000",
2034
+ // "origQty": "0.002",
2035
+ // "executedQty": "0",
2036
+ // "cummulativeQuoteQty": "0",
2037
+ // "cumulativeQuoteQty": "0",
2038
+ // "avgPrice": "0",
2039
+ // "status": "NEW",
2040
+ // "timeInForce": "GTC",
2041
+ // "type": "LIMIT",
2042
+ // "side": "BUY",
2043
+ // "stopPrice": "0.0",
2044
+ // "icebergQty": "0.0",
2045
+ // "time": "1756141516189",
2046
+ // "updateTime": "1756141516198",
2047
+ // "isWorking": true
2048
+ // }, ...
2049
+ // ]
2050
+ //
2051
+ }
2052
+ else {
2053
+ response = await this.privateGetApiV1FuturesOpenOrders(this.extend(request, params));
2054
+ }
2055
+ return this.parseOrders(response, market, since, limit);
2056
+ }
2057
+ /**
2058
+ * @method
2059
+ * @name toobit#fetchOrders
2060
+ * @description fetches information on multiple orders made by the user
2061
+ * @see https://toobit-docs.github.io/apidocs/spot/v1/en/#all-orders-user_data
2062
+ * @param {string} symbol unified market symbol of the market orders were made in
2063
+ * @param {int} [since] the earliest time in ms to fetch orders for
2064
+ * @param {int} [limit] the maximum number of order structures to retrieve
2065
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2066
+ * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
2067
+ */
2068
+ async fetchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
2069
+ await this.loadMarkets();
2070
+ let request = {};
2071
+ if (limit !== undefined) {
2072
+ request['limit'] = limit;
2073
+ }
2074
+ if (since !== undefined) {
2075
+ request['startTime'] = since;
2076
+ }
2077
+ [request, params] = this.handleUntilOption('endTime', request, params);
2078
+ let market = undefined;
2079
+ if (symbol !== undefined) {
2080
+ market = this.market(symbol);
2081
+ request['symbol'] = market['id'];
2082
+ }
2083
+ let marketType = undefined;
2084
+ [marketType, params] = this.handleMarketTypeAndParams('fetchOrders', market, params);
2085
+ let response = undefined;
2086
+ if (marketType === 'spot') {
2087
+ response = await this.privateGetApiV1SpotTradeOrders(request);
2088
+ //
2089
+ // [
2090
+ // {
2091
+ // "accountId": "1783404067076253952",
2092
+ // "exchangeId": "301",
2093
+ // "symbol": "ETHUSDT",
2094
+ // "symbolName": "ETHUSDT",
2095
+ // "clientOrderId": "17561415157172008",
2096
+ // "orderId": "2025056244339984384",
2097
+ // "price": "3000",
2098
+ // "origQty": "0.002",
2099
+ // "executedQty": "0",
2100
+ // "cummulativeQuoteQty": "0",
2101
+ // "cumulativeQuoteQty": "0",
2102
+ // "avgPrice": "0",
2103
+ // "status": "NEW",
2104
+ // "timeInForce": "GTC",
2105
+ // "type": "LIMIT",
2106
+ // "side": "BUY",
2107
+ // "stopPrice": "0.0",
2108
+ // "icebergQty": "0.0",
2109
+ // "time": "1756141516189",
2110
+ // "updateTime": "1756141516198",
2111
+ // "isWorking": true
2112
+ // }, ...
2113
+ // ]
2114
+ //
2115
+ }
2116
+ else {
2117
+ throw new errors.NotSupported(this.id + ' fetchOrders() is not supported for ' + marketType + ' markets');
2118
+ }
2119
+ return this.parseOrders(response, market, since, limit);
2120
+ }
2121
+ /**
2122
+ * @method
2123
+ * @name toobit#fetchClosedOrders
2124
+ * @description fetches information on multiple closed orders made by the user
2125
+ * @see https://toobit-docs.github.io/apidocs/usdt_swap/v1/en/#query-history-orders-user_data
2126
+ * @param {string} symbol unified market symbol of the market orders were made in
2127
+ * @param {int} [since] the earliest time in ms to fetch orders for
2128
+ * @param {int} [limit] the maximum number of order structures to retrieve
2129
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2130
+ * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
2131
+ */
2132
+ async fetchClosedOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
2133
+ // returns the most recent closed or canceled orders up to circa two weeks ago
2134
+ await this.loadMarkets();
2135
+ let request = {};
2136
+ let market = undefined;
2137
+ if (symbol !== undefined) {
2138
+ market = this.market(symbol);
2139
+ request['symbol'] = market['id'];
2140
+ }
2141
+ if (since !== undefined) {
2142
+ request['startTime'] = since;
2143
+ }
2144
+ [request, params] = this.handleUntilOption('endTime', request, params);
2145
+ let marketType = undefined;
2146
+ [marketType, params] = this.handleMarketTypeAndParams('fetchClosedOrders', market, params);
2147
+ let response = undefined;
2148
+ if (marketType === 'spot') {
2149
+ throw new errors.NotSupported(this.id + ' fetchOrders() is not supported for ' + marketType + ' markets');
2150
+ }
2151
+ else {
2152
+ response = await this.privateGetApiV1FuturesHistoryOrders(request);
2153
+ //
2154
+ // [
2155
+ // {
2156
+ // "time": "1756756879360",
2157
+ // "updateTime": "1756757165956",
2158
+ // "orderId": "2030218284767504128",
2159
+ // "clientOrderId": "1756756876002",
2160
+ // "symbol": "SOL-SWAP-USDT",
2161
+ // "price": "144",
2162
+ // "leverage": "50",
2163
+ // "origQty": "1",
2164
+ // "executedQty": "0",
2165
+ // "executeQty": "0",
2166
+ // "avgPrice": "0",
2167
+ // "marginLocked": "0",
2168
+ // "type": "LIMIT",
2169
+ // "side": "BUY_OPEN",
2170
+ // "timeInForce": "GTC",
2171
+ // "status": "CANCELED",
2172
+ // "priceType": "INPUT",
2173
+ // "triggerType": "0",
2174
+ // "fallType": "0",
2175
+ // "activeStatus": "0"
2176
+ // }
2177
+ // ]
2178
+ //
2179
+ }
2180
+ const ordersList = [];
2181
+ for (let i = 0; i < response.length; i++) {
2182
+ ordersList.push({ 'result': response[i] });
2183
+ }
2184
+ return this.parseOrders(ordersList, market, since, limit);
2185
+ }
2186
+ /**
2187
+ * @method
2188
+ * @name toobit#fetchMyTrades
2189
+ * @description fetch all trades made by the user
2190
+ * @see https://toobit-docs.github.io/apidocs/spot/v1/en/#account-trade-list-user_data
2191
+ * @see https://toobit-docs.github.io/apidocs/usdt_swap/v1/en/#account-trade-list-user_data
2192
+ * @param {string} [symbol] unified market symbol
2193
+ * @param {int} [since] the earliest time in ms to fetch trades for
2194
+ * @param {int} [limit] the maximum number of trade structures to retrieve
2195
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2196
+ * @param {int} [params.until] the latest time in ms to fetch trades for
2197
+ * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
2198
+ */
2199
+ async fetchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
2200
+ if (symbol === undefined) {
2201
+ throw new errors.ArgumentsRequired(this.id + ' fetchMyTrades() requires a symbol argument');
2202
+ }
2203
+ await this.loadMarkets();
2204
+ let request = {};
2205
+ if (since !== undefined) {
2206
+ request['startTime'] = since;
2207
+ }
2208
+ if (limit !== undefined) {
2209
+ request['limit'] = limit;
2210
+ }
2211
+ const market = this.market(symbol);
2212
+ request['symbol'] = market['id'];
2213
+ let marketType = undefined;
2214
+ [marketType, params] = this.handleMarketTypeAndParams('fetchMyTrades', market, params);
2215
+ [request, params] = this.handleUntilOption('endTime', request, params);
2216
+ let response = undefined;
2217
+ if (marketType === 'spot') {
2218
+ response = await this.privateGetApiV1AccountTrades(this.extend(request, params));
2219
+ //
2220
+ // [
2221
+ // {
2222
+ // "id": "2024934575206059008",
2223
+ // "symbol": "ETHUSDT",
2224
+ // "symbolName": "ETHUSDT",
2225
+ // "orderId": "2024934575097029888",
2226
+ // "price": "4641.21",
2227
+ // "qty": "0.001",
2228
+ // "commission": "0.00464121",
2229
+ // "commissionAsset": "USDT",
2230
+ // "time": "1756127012094",
2231
+ // "isBuyer": false,
2232
+ // "isMaker": false,
2233
+ // "fee": {
2234
+ // "feeCoinId": "USDT",
2235
+ // "feeCoinName": "USDT",
2236
+ // "fee": "0.00464121"
2237
+ // },
2238
+ // "feeCoinId": "USDT",
2239
+ // "feeAmount": "0.00464121",
2240
+ // "makerRebate": "0",
2241
+ // "ticketId": "4864450547563401875"
2242
+ // }, ...
2243
+ //
2244
+ }
2245
+ else {
2246
+ response = await this.privateGetApiV1FuturesUserTrades(request);
2247
+ //
2248
+ // [
2249
+ // {
2250
+ // "time": "1756758426899",
2251
+ // "id": "2030231266499116032",
2252
+ // "orderId": "2030231266373265152",
2253
+ // "symbol": "DOGE-SWAP-USDT",
2254
+ // "price": "0.21191",
2255
+ // "qty": "63",
2256
+ // "commissionAsset": "USDT",
2257
+ // "commission": "0.00801019",
2258
+ // "makerRebate": "0",
2259
+ // "type": "LIMIT",
2260
+ // "side": "BUY_OPEN",
2261
+ // "realizedPnl": "0",
2262
+ // "ticketId": "4900760819871364854",
2263
+ // "isMaker": false
2264
+ // }
2265
+ // ]
2266
+ //
2267
+ }
2268
+ return this.parseTrades(response, market, since, limit);
2269
+ }
2270
+ /**
2271
+ * @method
2272
+ * @name toobit#transfer
2273
+ * @description transfer currency internally between wallets on the same account
2274
+ * @see https://open.big.one/docs/spot_transfer.html#transfer-of-user
2275
+ * @param {string} code unified currency code
2276
+ * @param {float} amount amount to transfer
2277
+ * @param {string} fromAccount 'spot', 'swap'
2278
+ * @param {string} toAccount 'spot', 'swap'
2279
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2280
+ * @returns {object} a [transfer structure]{@link https://docs.ccxt.com/#/?id=transfer-structure}
2281
+ */
2282
+ async transfer(code, amount, fromAccount, toAccount, params = {}) {
2283
+ await this.loadMarkets();
2284
+ const currency = this.currency(code);
2285
+ const accountsByType = this.safeDict(this.options, 'accountsByType', {});
2286
+ const fromId = this.safeString(accountsByType, fromAccount, fromAccount);
2287
+ const toId = this.safeString(accountsByType, toAccount, toAccount);
2288
+ const request = {
2289
+ 'asset': currency['id'],
2290
+ 'quantity': this.currencyToPrecision(code, amount),
2291
+ 'fromAccountType': fromId,
2292
+ 'toAccountType': toId,
2293
+ };
2294
+ const response = await this.privatePostApiV1SubAccountTransfer(this.extend(request, params));
2295
+ //
2296
+ // {
2297
+ // "code": 200, // 200 = success
2298
+ // "msg": "success" // response message
2299
+ // }
2300
+ //
2301
+ return this.parseTransfer(response, currency);
2302
+ }
2303
+ parseTransfer(transfer, currency = undefined) {
2304
+ //
2305
+ // {
2306
+ // "code": 200, // 200 = success
2307
+ // "msg": "success" // response message
2308
+ // }
2309
+ //
2310
+ return {
2311
+ 'info': transfer,
2312
+ 'id': undefined,
2313
+ 'timestamp': undefined,
2314
+ 'datetime': undefined,
2315
+ 'currency': undefined,
2316
+ 'amount': undefined,
2317
+ 'fromAccount': undefined,
2318
+ 'toAccount': undefined,
2319
+ 'status': undefined,
2320
+ };
2321
+ }
2322
+ /**
2323
+ * @method
2324
+ * @name toobit#fetchLedger
2325
+ * @description fetch the history of changes, actions done by the user or operations that altered the balance of the user
2326
+ * @see https://toobit-docs.github.io/apidocs/spot/v1/en/#get-account-transaction-history-list-user_data
2327
+ * @see https://toobit-docs.github.io/apidocs/usdt_swap/v1/en/#get-future-account-transaction-history-list-user_data
2328
+ * @param {string} [code] unified currency code, default is undefined
2329
+ * @param {int} [since] timestamp in ms of the earliest ledger entry, default is undefined
2330
+ * @param {int} [limit] max number of ledger entries to return, default is undefined
2331
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2332
+ * @param {int} [params.until] end time in ms
2333
+ * @returns {object} a [ledger structure]{@link https://docs.ccxt.com/#/?id=ledger}
2334
+ */
2335
+ async fetchLedger(code = undefined, since = undefined, limit = undefined, params = {}) {
2336
+ await this.loadMarkets();
2337
+ let currency = undefined;
2338
+ let request = {};
2339
+ if (code !== undefined) {
2340
+ currency = this.currency(code);
2341
+ request['coin'] = currency['id'];
2342
+ }
2343
+ if (since !== undefined) {
2344
+ request['startTime'] = since;
2345
+ }
2346
+ [request, params] = this.handleUntilOption('endTime', request, params);
2347
+ if (limit !== undefined) {
2348
+ request['limit'] = limit;
2349
+ }
2350
+ let marketType = undefined;
2351
+ [marketType, params] = this.handleMarketTypeAndParams('cancelAllOrders', undefined, params);
2352
+ let response = undefined;
2353
+ if (marketType === 'spot') {
2354
+ response = await this.privateGetApiV1AccountBalanceFlow(this.extend(request, params));
2355
+ }
2356
+ else {
2357
+ response = await this.privateGetApiV1FuturesBalanceFlow(this.extend(request, params));
2358
+ }
2359
+ //
2360
+ // both answers are same format
2361
+ //
2362
+ // [
2363
+ // {
2364
+ // "id": "539870570957903104",
2365
+ // "accountId": "122216245228131",
2366
+ // "coin": "BTC",
2367
+ // "coinId": "BTC",
2368
+ // "coinName": "BTC",
2369
+ // "flowTypeValue": 51,
2370
+ // "flowType": "USER_ACCOUNT_TRANSFER",
2371
+ // "flowName": "Transfer",
2372
+ // "change": "-12.5",
2373
+ // "total": "379.624059937852365",
2374
+ // "created": "1579093587214"
2375
+ // },
2376
+ //
2377
+ return this.parseLedger(response, currency, since, limit);
2378
+ }
2379
+ parseLedgerEntry(item, currency = undefined) {
2380
+ const currencyId = this.safeString(item, 'coinId');
2381
+ currency = this.safeCurrency(currencyId, currency);
2382
+ const timestamp = this.safeInteger(item, 'created');
2383
+ const after = this.safeNumber(item, 'total');
2384
+ const amountRaw = this.safeString(item, 'change');
2385
+ const amount = this.parseNumber(Precise["default"].stringAbs(amountRaw));
2386
+ let direction = 'in';
2387
+ if (amountRaw.startsWith('-')) {
2388
+ direction = 'out';
2389
+ }
2390
+ return this.safeLedgerEntry({
2391
+ 'info': item,
2392
+ 'id': this.safeString(item, 'id'),
2393
+ 'timestamp': timestamp,
2394
+ 'datetime': this.iso8601(timestamp),
2395
+ 'direction': direction,
2396
+ 'account': undefined,
2397
+ 'referenceId': undefined,
2398
+ 'referenceAccount': undefined,
2399
+ 'type': this.parseLedgerType(this.safeString(item, 'flowType')),
2400
+ 'currency': currency['code'],
2401
+ 'amount': amount,
2402
+ 'before': undefined,
2403
+ 'after': after,
2404
+ 'status': undefined,
2405
+ 'fee': undefined,
2406
+ }, currency);
2407
+ }
2408
+ parseLedgerType(type) {
2409
+ const types = {
2410
+ 'USER_ACCOUNT_TRANSFER': 'transfer',
2411
+ 'AIRDROP': 'rebate',
2412
+ };
2413
+ return this.safeString(types, type, type);
2414
+ }
2415
+ /**
2416
+ * @method
2417
+ * @name toobit#fetchTradingFees
2418
+ * @description fetch the trading fees for multiple markets
2419
+ * @see https://toobit-docs.github.io/apidocs/usdt_swap/v1/en/#user-trade-fee-rate-user_data
2420
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2421
+ * @returns {object} a dictionary of [fee structures]{@link https://docs.ccxt.com/#/?id=fee-structure} indexed by market symbols
2422
+ */
2423
+ async fetchTradingFees(params = {}) {
2424
+ await this.loadMarkets();
2425
+ let response = undefined;
2426
+ let marketType = undefined;
2427
+ let market = undefined;
2428
+ [marketType, params] = this.handleMarketTypeAndParams('fetchTradingFees', undefined, params);
2429
+ if (marketType === 'spot') {
2430
+ throw new errors.NotSupported(this.id + ' fetchTradingFees(): does not support ' + marketType + ' markets');
2431
+ }
2432
+ else if (this.inArray(marketType, ['swap', 'future'])) {
2433
+ let symbol = undefined;
2434
+ [symbol, params] = this.handleParamString(params, 'symbol');
2435
+ if (symbol === undefined) {
2436
+ throw new errors.BadRequest(this.id + ' fetchTradingFees requires a params["symbol"]');
2437
+ }
2438
+ market = this.market(symbol);
2439
+ const request = {
2440
+ 'symbol': market['id'],
2441
+ };
2442
+ response = await this.privateGetApiV1FuturesCommissionRate(this.extend(request, params));
2443
+ }
2444
+ //
2445
+ // {
2446
+ // "openMakerFee": "0.000006", // The trade fee rate for opening pending orders
2447
+ // "openTakerFee": "0.0001", // The trade fee rate for open position taker
2448
+ // "closeMakerFee": "0.0002", // The trade fee rate for closing pending orders
2449
+ // "closeTakerFee": "0.0004" // The trade fee rate for closing a taker order
2450
+ // }
2451
+ //
2452
+ const result = {};
2453
+ const entry = response;
2454
+ const marketId = this.safeString(entry, 'symbol');
2455
+ market = this.safeMarket(marketId, market);
2456
+ const fee = this.parseTradingFee(entry, market);
2457
+ result[market['symbol']] = fee;
2458
+ return result;
2459
+ }
2460
+ parseTradingFee(data, market = undefined) {
2461
+ const marketId = this.safeString(data, 'symbol');
2462
+ return {
2463
+ 'info': data,
2464
+ 'symbol': this.safeSymbol(marketId, market),
2465
+ 'maker': this.safeNumber(data, 'closeMakerFee'),
2466
+ 'taker': this.safeNumber(data, 'closeTakerFee'),
2467
+ 'percentage': undefined,
2468
+ 'tierBased': undefined,
2469
+ };
2470
+ }
2471
+ /**
2472
+ * @method
2473
+ * @name toobit#fetchDeposits
2474
+ * @description fetch all deposits made to an account
2475
+ * @see https://toobit-docs.github.io/apidocs/spot/v1/en/#deposit-history-user_data
2476
+ * @param {string} [code] unified currency code
2477
+ * @param {int} [since] the earliest time in ms to fetch deposits for
2478
+ * @param {int} [limit] the maximum number of deposit structures to retrieve
2479
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2480
+ * @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure}
2481
+ */
2482
+ async fetchDeposits(code = undefined, since = undefined, limit = undefined, params = {}) {
2483
+ return await this.fetchDepositsOrWithdrawalsHelper('deposits', code, since, limit, params);
2484
+ }
2485
+ /**
2486
+ * @method
2487
+ * @name toobit#fetchWithdrawals
2488
+ * @description fetch all withdrawals made from an account
2489
+ * @see https://toobit-docs.github.io/apidocs/spot/v1/en/#withdrawal-records-user_data
2490
+ * @param {string} [code] unified currency code
2491
+ * @param {int} [since] the earliest time in ms to fetch withdrawals for
2492
+ * @param {int} [limit] the maximum number of withdrawal structures to retrieve
2493
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2494
+ * @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure}
2495
+ */
2496
+ async fetchWithdrawals(code = undefined, since = undefined, limit = undefined, params = {}) {
2497
+ return await this.fetchDepositsOrWithdrawalsHelper('withdrawals', code, since, limit, params);
2498
+ }
2499
+ async fetchDepositsOrWithdrawalsHelper(type, code, since, limit, params) {
2500
+ await this.loadMarkets();
2501
+ let currency = undefined;
2502
+ let request = {};
2503
+ if (code !== undefined) {
2504
+ currency = this.currency(code);
2505
+ request['coin'] = currency['id'];
2506
+ }
2507
+ if (since !== undefined) {
2508
+ request['startTime'] = since;
2509
+ }
2510
+ [request, params] = this.handleUntilOption('endTime', request, params);
2511
+ if (limit !== undefined) {
2512
+ request['limit'] = limit;
2513
+ }
2514
+ let response = undefined;
2515
+ if (type === 'deposits') {
2516
+ response = await this.privateGetApiV1AccountDepositOrders(this.extend(request, params));
2517
+ //
2518
+ // [
2519
+ // {
2520
+ // "time": 1499865549590,
2521
+ // "id": 100234,
2522
+ // "coinName": "EOS",
2523
+ // "statusCode": "DEPOSIT_CAN_WITHDRAW",
2524
+ // "status": "2", // 2=SUCCESS, 11=REJECT, 12=AUDIT
2525
+ // "address": "deposit2bb",
2526
+ // "txId": "98A3EA560C6B3336D348B6C83F0F95ECE4F1F5919E94BD006E5BF3BF264FACFC",
2527
+ // "txIdUrl": "",
2528
+ // "requiredConfirmTimes": "5",
2529
+ // "confirmTimes": "5",
2530
+ // "quantity": "1.01",
2531
+ // "coin": "EOS",
2532
+ // "fromAddress": "clarkkent",
2533
+ // "fromAddressTag": "19029901"
2534
+ // "addressTag": "19012584",
2535
+ // }
2536
+ // ]
2537
+ //
2538
+ }
2539
+ else if (type === 'withdrawals') {
2540
+ response = await this.privateGetApiV1AccountWithdrawOrders(this.extend(request, params));
2541
+ //
2542
+ // [
2543
+ // {
2544
+ // "time":"1536232111669",
2545
+ // "id ":"90161227158286336",
2546
+ // "accountId":"517256161325920",
2547
+ // "coinName":"BHC",
2548
+ // "statusCode":"PROCESSING_STATUS",
2549
+ // "status":3,
2550
+ // "address":"0x815bF1c3cc0f49b8FC66B21A7e48fCb476051209",
2551
+ // "txId ":"",
2552
+ // "txIdUrl ":"",
2553
+ // "requiredConfirmTimes ":0, // Number of confirmation requests
2554
+ // "confirmTimes ":0, // number of confirmations
2555
+ // "quantity":"14", // Withdrawal amount
2556
+ // "coinId ":"BHC",
2557
+ // "addressExt":"address tag",
2558
+ // "arriveQuantity":"14",
2559
+ // "walletHandleTime":"1536232111669",
2560
+ // "feeCoinId ":"BHC",
2561
+ // "feeCoinName ":"BHC",
2562
+ // "fee":"0.1",
2563
+ // "kernelId":"", // Exclusive to BEAM and GRIN
2564
+ // "isInternalTransfer": false // Whether internal transfer
2565
+ // }
2566
+ // ]
2567
+ //
2568
+ }
2569
+ return this.parseTransactions(response, currency, since, limit, params);
2570
+ }
2571
+ parseTransaction(transaction, currency = undefined) {
2572
+ //
2573
+ // fetchDeposits & fetchWithdrawals
2574
+ //
2575
+ // {
2576
+ // "time": 1499865549590,
2577
+ // "id": 100234,
2578
+ // "coinName": "EOS",
2579
+ // "statusCode": "DEPOSIT_CAN_WITHDRAW",
2580
+ // "status": "2", // 2=SUCCESS, 11=REJECT, 12=AUDIT
2581
+ // "address": "deposit2bb",
2582
+ // "txId": "98A3EA560C6B3336D348B6C83F0F95ECE4F1F5919E94BD006E5BF3BF264FACFC",
2583
+ // "txIdUrl": "",
2584
+ // "requiredConfirmTimes": "5",
2585
+ // "confirmTimes": "5",
2586
+ // "quantity": "1.01",
2587
+ // "coin": "EOS", // present in "fetchDeposits"
2588
+ // "coinId ":"BHC", // present in "fetchWithdrawals"
2589
+ // "addressTag": "19012584", // present in "fetchDeposits"
2590
+ // "addressExt":"address tag", // present in "fetchWithdrawals"
2591
+ // "fromAddress": "clarkkent", // present in "fetchDeposits"
2592
+ // "fromAddressTag": "19029901" // present in "fetchDeposits"
2593
+ // "arriveQuantity":"14", // present in "fetchWithdrawals"
2594
+ // "walletHandleTime":"1536232111669",// present in "fetchWithdrawals"
2595
+ // "feeCoinId ":"BHC", // present in "fetchWithdrawals"
2596
+ // "feeCoinName ":"BHC", // present in "fetchWithdrawals"
2597
+ // "fee":"0.1", // present in "fetchWithdrawals"
2598
+ // "kernelId":"", // present in "fetchWithdrawals"
2599
+ // "isInternalTransfer": false // present in "fetchWithdrawals"
2600
+ // }
2601
+ //
2602
+ // withdraw
2603
+ //
2604
+ // {
2605
+ // "status": 0,
2606
+ // "success": true,
2607
+ // "needBrokerAudit": false, // Do you need a brokerage review?
2608
+ // "id": "423885103582776064",
2609
+ // "refuseReason":"" // failure rejection reason
2610
+ // }
2611
+ //
2612
+ const timestamp = this.safeInteger(transaction, 'time');
2613
+ const currencyId = this.safeString2(transaction, 'coin', 'coinId');
2614
+ const code = this.safeCurrencyCode(currencyId, currency);
2615
+ const feeString = this.safeString(transaction, 'fee');
2616
+ const feeCoin = this.safeString(transaction, 'feeCoinName');
2617
+ let fee = undefined;
2618
+ if (feeString !== undefined) {
2619
+ fee = {
2620
+ 'cost': this.parseNumber(feeString),
2621
+ 'currency': this.safeCurrencyCode(feeCoin),
2622
+ };
2623
+ }
2624
+ const tagTo = this.safeString2(transaction, 'addressTag', 'addressExt');
2625
+ const tagFrom = this.safeString(transaction, 'fromAddressTag');
2626
+ const addressTo = this.safeString(transaction, 'address');
2627
+ const addressFrom = this.safeString(transaction, 'fromAddress');
2628
+ const isWithdraw = ('arriveQuantity' in transaction);
2629
+ const type = isWithdraw ? 'withdrawal' : 'deposit';
2630
+ return {
2631
+ 'info': transaction,
2632
+ 'id': this.safeString(transaction, 'id'),
2633
+ 'txid': this.safeString(transaction, 'txId'),
2634
+ 'timestamp': timestamp,
2635
+ 'datetime': this.iso8601(timestamp),
2636
+ 'network': undefined,
2637
+ 'address': undefined,
2638
+ 'addressTo': addressTo,
2639
+ 'addressFrom': addressFrom,
2640
+ 'tag': undefined,
2641
+ 'tagTo': tagTo,
2642
+ 'tagFrom': tagFrom,
2643
+ 'type': type,
2644
+ 'amount': this.safeNumber(transaction, 'quantity'),
2645
+ 'currency': code,
2646
+ 'status': this.parseTransactionStatus(this.safeString(transaction, 'status')),
2647
+ 'updated': undefined,
2648
+ 'fee': fee,
2649
+ 'comment': undefined,
2650
+ 'internal': undefined,
2651
+ };
2652
+ }
2653
+ parseTransactionStatus(status) {
2654
+ const statuses = {
2655
+ '2': 'pending',
2656
+ '12': 'pending',
2657
+ '11': 'failed',
2658
+ '3': 'ok',
2659
+ };
2660
+ return this.safeString(statuses, status, status);
2661
+ }
2662
+ /**
2663
+ * @method
2664
+ * @name toobit#fetchDepositAddress
2665
+ * @description fetch the deposit address for a currency associated with this account
2666
+ * @see https://toobit-docs.github.io/apidocs/spot/v1/en/#deposit-address-user_data
2667
+ * @param {string} code unified currency code
2668
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2669
+ * @returns {object} an [address structure]{@link https://docs.ccxt.com/#/?id=address-structure}
2670
+ */
2671
+ async fetchDepositAddress(code, params = {}) {
2672
+ await this.loadMarkets();
2673
+ const currency = this.currency(code);
2674
+ const request = {
2675
+ 'coin': currency['id'],
2676
+ };
2677
+ const [networkCode, paramsOmitted] = this.handleNetworkCodeAndParams(this.extend(request, params));
2678
+ if (networkCode === undefined) {
2679
+ throw new errors.ArgumentsRequired(this.id + ' fetchDepositAddress() : param["network"] is required');
2680
+ }
2681
+ request['chainType'] = this.networkCodeToId(networkCode);
2682
+ const response = await this.privateGetApiV1AccountDepositAddress(this.extend(request, paramsOmitted));
2683
+ //
2684
+ // {
2685
+ // "canDeposit":false,//Is it possible to recharge
2686
+ // "address":"0x815bF1c3cc0f49b8FC66B21A7e48fCb476051209",
2687
+ // "addressExt":"address tag",
2688
+ // "minQuantity":"100",//minimum amount
2689
+ // "requiredConfirmTimes ":1,//Arrival confirmation number
2690
+ // "canWithdrawConfirmNum ":12,//Withdrawal confirmation number
2691
+ // "coinType":"ERC20_TOKEN"
2692
+ // }
2693
+ //
2694
+ return this.parseDepositAddress(response, currency);
2695
+ }
2696
+ parseDepositAddress(depositAddress, currency = undefined) {
2697
+ const address = this.safeString(depositAddress, 'address');
2698
+ this.checkAddress(address);
2699
+ return {
2700
+ 'info': depositAddress,
2701
+ 'currency': this.safeString(currency, 'code'),
2702
+ 'network': undefined,
2703
+ 'address': address,
2704
+ 'tag': this.safeString(depositAddress, 'addressExt'),
2705
+ };
2706
+ }
2707
+ /**
2708
+ * @method
2709
+ * @name toobit#withdraw
2710
+ * @description make a withdrawal
2711
+ * @see https://toobit-docs.github.io/apidocs/spot/v1/en/#withdraw-user_data
2712
+ * @param {string} code unified currency code
2713
+ * @param {float} amount the amount to withdraw
2714
+ * @param {string} address the address to withdraw to
2715
+ * @param {string} tag a memo for the transaction
2716
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2717
+ * @returns {object} a [transaction structure]{@link https://docs.ccxt.com/#/?id=transaction-structure}
2718
+ */
2719
+ async withdraw(code, amount, address, tag = undefined, params = {}) {
2720
+ this.checkAddress(address);
2721
+ let networkCode = undefined;
2722
+ [networkCode, params] = this.handleNetworkCodeAndParams(params);
2723
+ if (networkCode === undefined) {
2724
+ throw new errors.ArgumentsRequired(this.id + ' withdraw() : param["network"] is required');
2725
+ }
2726
+ await this.loadMarkets();
2727
+ const currency = this.currency(code);
2728
+ const request = {
2729
+ 'coin': currency['id'],
2730
+ 'address': address,
2731
+ 'quantity': this.currencyToPrecision(currency['code'], amount),
2732
+ 'network': networkCode,
2733
+ };
2734
+ if (tag !== undefined) {
2735
+ request['addressExt'] = tag;
2736
+ }
2737
+ const response = await this.privatePostApiV1AccountWithdraw(this.extend(request, params));
2738
+ //
2739
+ // {
2740
+ // "status": 0,
2741
+ // "success": true,
2742
+ // "needBrokerAudit": false, // Do you need a brokerage review?
2743
+ // "id": "423885103582776064", // Withdrawal successful order id
2744
+ // "refuseReason":"" // failure rejection reason
2745
+ // }
2746
+ //
2747
+ return this.parseTransaction(response, currency);
2748
+ }
2749
+ /**
2750
+ * @method
2751
+ * @name toobit#setMarginMode
2752
+ * @description set margin mode to 'cross' or 'isolated'
2753
+ * @see https://toobit-docs.github.io/apidocs/usdt_swap/v1/en/#change-margin-type-trade
2754
+ * @param {string} marginMode 'cross' or 'isolated'
2755
+ * @param {string} symbol unified market symbol
2756
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2757
+ * @returns {object} response from the exchange
2758
+ */
2759
+ async setMarginMode(marginMode, symbol = undefined, params = {}) {
2760
+ if (symbol === undefined) {
2761
+ throw new errors.ArgumentsRequired(this.id + ' setMarginMode() requires a symbol argument');
2762
+ }
2763
+ await this.loadMarkets();
2764
+ const market = this.market(symbol);
2765
+ if (market['type'] !== 'swap') {
2766
+ throw new errors.BadSymbol(this.id + ' setMarginMode() supports swap contracts only');
2767
+ }
2768
+ marginMode = marginMode.toUpperCase();
2769
+ const request = {
2770
+ 'symbol': market['id'],
2771
+ 'marginType': marginMode,
2772
+ };
2773
+ const response = await this.privatePostApiV1FuturesMarginType(this.extend(request, params));
2774
+ //
2775
+ // {"code":200,"symbolId":"BTC-SWAP-USDT","marginType":"ISOLATED"}
2776
+ //
2777
+ return response;
2778
+ }
2779
+ /**
2780
+ * @method
2781
+ * @name toobit#setLeverage
2782
+ * @description set the level of leverage for a market
2783
+ * @see https://toobit-docs.github.io/apidocs/usdt_swap/v1/en/#change-initial-leverage-trade
2784
+ * @param {float} leverage the rate of leverage
2785
+ * @param {string} symbol unified market symbol
2786
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2787
+ * @returns {object} response from the exchange
2788
+ */
2789
+ async setLeverage(leverage, symbol = undefined, params = {}) {
2790
+ if (symbol === undefined) {
2791
+ throw new errors.ArgumentsRequired(this.id + ' setLeverage() requires a symbol argument');
2792
+ }
2793
+ await this.loadMarkets();
2794
+ const market = this.market(symbol);
2795
+ const request = {
2796
+ 'symbol': market['id'],
2797
+ 'leverage': leverage,
2798
+ };
2799
+ const response = await this.privatePostApiV1FuturesLeverage(this.extend(request, params));
2800
+ //
2801
+ // {"code":200,"symbolId":"BTC-SWAP-USDT","leverage":"19"}
2802
+ //
2803
+ return response;
2804
+ }
2805
+ /**
2806
+ * @method
2807
+ * @name toobit#fetchLeverage
2808
+ * @description fetch the set leverage for a market
2809
+ * @see https://toobit-docs.github.io/apidocs/usdt_swap/v1/en/#get-the-leverage-multiple-and-position-mode-user_data
2810
+ * @param {string} symbol unified market symbol
2811
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2812
+ * @returns {object} a [leverage structure]{@link https://docs.ccxt.com/#/?id=leverage-structure}
2813
+ */
2814
+ async fetchLeverage(symbol, params = {}) {
2815
+ await this.loadMarkets();
2816
+ const market = this.market(symbol);
2817
+ const request = {
2818
+ 'symbol': market['id'],
2819
+ };
2820
+ const response = await this.privateGetApiV1FuturesAccountLeverage(this.extend(request, params));
2821
+ //
2822
+ // [
2823
+ // {
2824
+ // "symbol":"BTC-SWAP-USDT", //symbol
2825
+ // "leverage":"20", // leverage
2826
+ // "marginType":"CROSS" // CROSS;ISOLATED
2827
+ // }
2828
+ // ]
2829
+ //
2830
+ const data = this.safeDict(response, 'data', {});
2831
+ return this.parseLeverage(data, market);
2832
+ }
2833
+ parseLeverage(leverage, market = undefined) {
2834
+ const marketId = this.safeString(leverage, 'symbol');
2835
+ const leverageValue = this.safeInteger(leverage, 'leverage');
2836
+ const marginType = this.safeString(leverage, 'marginType');
2837
+ const marginMode = (marginType === 'crossed') ? 'cross' : 'isolated';
2838
+ return {
2839
+ 'info': leverage,
2840
+ 'symbol': this.safeSymbol(marketId, market),
2841
+ 'marginMode': marginMode,
2842
+ 'longLeverage': leverageValue,
2843
+ 'shortLeverage': leverageValue,
2844
+ };
2845
+ }
2846
+ /**
2847
+ * @method
2848
+ * @name toobit#fetchPositions
2849
+ * @description fetch all open positions
2850
+ * @see https://toobit-docs.github.io/apidocs/usdt_swap/v1/en/#query-position-user_data
2851
+ * @param {string[]|undefined} symbols list of unified market symbols
2852
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2853
+ * @returns {object[]} a list of [position structures]{@link https://docs.ccxt.com/#/?id=position-structure}
2854
+ */
2855
+ async fetchPositions(symbols = undefined, params = {}) {
2856
+ await this.loadMarkets();
2857
+ const request = {};
2858
+ let market = undefined;
2859
+ if (symbols !== undefined) {
2860
+ const length = symbols.length;
2861
+ if (length > 1) {
2862
+ throw new errors.BadRequest(this.id + ' fetchPositions() only accepts an array with a single symbol or without symbols argument');
2863
+ }
2864
+ const firstSymbol = this.safeString(symbols, 0);
2865
+ if (firstSymbol !== undefined) {
2866
+ market = this.market(firstSymbol);
2867
+ request['symbol'] = market['id'];
2868
+ }
2869
+ }
2870
+ const response = await this.privateGetApiV1FuturesPositions(this.extend(request, params));
2871
+ //
2872
+ // [
2873
+ // {
2874
+ // "symbol": "DOGE-SWAP-USDT",
2875
+ // "side": "LONG",
2876
+ // "avgPrice": "0.21191",
2877
+ // "position": "63",
2878
+ // "available": "63",
2879
+ // "leverage": "25",
2880
+ // "lastPrice": "0.20932",
2881
+ // "positionValue": "13.3503",
2882
+ // "flp": "0.05471",
2883
+ // "margin": "0.5262",
2884
+ // "marginRate": "",
2885
+ // "unrealizedPnL": "-0.1701",
2886
+ // "profitRate": "-0.3185",
2887
+ // "realizedPnL": "-0.008",
2888
+ // "minMargin": "0",
2889
+ // "maxNotionalValue": "10000000",
2890
+ // "markPrice": "0.20921"
2891
+ // }
2892
+ // ]
2893
+ //
2894
+ return this.parsePositions(response, symbols);
2895
+ }
2896
+ parsePosition(position, market = undefined) {
2897
+ const marketId = this.safeString(position, 'symbol');
2898
+ market = this.safeMarket(marketId, market);
2899
+ const side = this.safeStringLower(position, 'side');
2900
+ const quantity = this.safeString(position, 'position');
2901
+ const leverage = this.safeInteger(position, 'leverage');
2902
+ return this.safePosition({
2903
+ 'info': position,
2904
+ 'id': this.safeString(position, 'id'),
2905
+ 'symbol': market['symbol'],
2906
+ 'entryPrice': this.safeString(position, 'avgPrice'),
2907
+ 'markPrice': this.safeString(position, 'markPrice'),
2908
+ 'lastPrice': this.safeString(position, 'lastPrice'),
2909
+ 'notional': this.safeString(position, 'positionValue'),
2910
+ 'collateral': undefined,
2911
+ 'unrealizedPnl': this.safeString(position, 'unrealizedPnL'),
2912
+ 'side': side,
2913
+ 'contracts': this.parseNumber(quantity),
2914
+ 'contractSize': undefined,
2915
+ 'timestamp': undefined,
2916
+ 'datetime': undefined,
2917
+ 'hedged': undefined,
2918
+ 'maintenanceMargin': undefined,
2919
+ 'maintenanceMarginPercentage': undefined,
2920
+ 'initialMargin': this.safeString(position, 'margin'),
2921
+ 'initialMarginPercentage': undefined,
2922
+ 'leverage': leverage,
2923
+ 'liquidationPrice': undefined,
2924
+ 'marginRatio': undefined,
2925
+ 'marginMode': undefined,
2926
+ 'percentage': undefined,
2927
+ });
2928
+ }
2929
+ sign(path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
2930
+ let url = this.urls['api'][api] + '/' + this.implodeParams(path, params);
2931
+ const isPost = method === 'POST';
2932
+ const isDelete = method === 'DELETE';
2933
+ const extraQuery = {};
2934
+ const query = this.omit(params, this.extractParams(path));
2935
+ if (api !== 'private') {
2936
+ // Public endpoints
2937
+ if (!isPost) {
2938
+ if (Object.keys(query).length) {
2939
+ url += '?' + this.urlencode(query);
2940
+ }
2941
+ }
2942
+ }
2943
+ else {
2944
+ this.checkRequiredCredentials();
2945
+ const timestamp = this.milliseconds();
2946
+ // Add timestamp to parameters for signed endpoints
2947
+ extraQuery['recvWindow'] = this.safeString(this.options, 'recvWindow', '5000');
2948
+ extraQuery['timestamp'] = timestamp.toString();
2949
+ const queryExtended = this.extend(query, extraQuery);
2950
+ let queryString = '';
2951
+ if (isPost || isDelete) {
2952
+ // everything else except Batch-Orders
2953
+ if (!Array.isArray(params)) {
2954
+ body = this.urlencode(queryExtended);
2955
+ }
2956
+ else {
2957
+ queryString = this.urlencode(extraQuery);
2958
+ body = this.json(query);
2959
+ }
2960
+ }
2961
+ else {
2962
+ queryString = this.urlencode(queryExtended);
2963
+ }
2964
+ let payload = queryString;
2965
+ if (body !== undefined) {
2966
+ payload = body + payload;
2967
+ }
2968
+ const signature = this.hmac(this.encode(payload), this.encode(this.secret), sha256.sha256, 'hex');
2969
+ if (queryString !== '') {
2970
+ queryString += '&signature=' + signature;
2971
+ url += '?' + queryString;
2972
+ }
2973
+ else {
2974
+ body += '&signature=' + signature;
2975
+ }
2976
+ headers = {
2977
+ 'X-BB-APIKEY': this.apiKey,
2978
+ 'Content-Type': 'application/x-www-form-urlencoded',
2979
+ };
2980
+ }
2981
+ return { 'url': url, 'method': method, 'body': body, 'headers': headers };
2982
+ }
2983
+ handleErrors(code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
2984
+ if (response === undefined) {
2985
+ return undefined;
2986
+ }
2987
+ const errorCode = this.safeString(response, 'code');
2988
+ const message = this.safeString(response, 'msg');
2989
+ if (errorCode && errorCode !== '200' && errorCode !== '0') {
2990
+ const feedback = this.id + ' ' + body;
2991
+ this.throwExactlyMatchedException(this.exceptions['exact'], errorCode, feedback);
2992
+ this.throwBroadlyMatchedException(this.exceptions['broad'], message, feedback);
2993
+ throw new errors.ExchangeError(feedback);
2994
+ }
2995
+ return undefined;
2996
+ }
2997
+ }
2998
+
2999
+ exports["default"] = toobit;