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.
- package/README.md +4 -4
- package/dist/ccxt.browser.min.js +15 -15
- package/dist/cjs/ccxt.js +6 -6
- package/dist/cjs/src/abstract/toobit.js +11 -0
- package/dist/cjs/src/abstract/tradeogre.js +1 -1
- package/dist/cjs/src/apex.js +2 -2
- package/dist/cjs/src/backpack.js +1 -1
- package/dist/cjs/src/base/Exchange.js +129 -2
- package/dist/cjs/src/bigone.js +4 -4
- package/dist/cjs/src/binance.js +82 -20
- package/dist/cjs/src/bingx.js +5 -2
- package/dist/cjs/src/bitbank.js +1 -0
- package/dist/cjs/src/bitbns.js +1 -0
- package/dist/cjs/src/bitflyer.js +1 -0
- package/dist/cjs/src/bitget.js +16 -9
- package/dist/cjs/src/bithumb.js +1 -0
- package/dist/cjs/src/bitso.js +1 -0
- package/dist/cjs/src/bitvavo.js +26 -40
- package/dist/cjs/src/blockchaincom.js +1 -0
- package/dist/cjs/src/btcalpha.js +1 -0
- package/dist/cjs/src/btcbox.js +1 -0
- package/dist/cjs/src/btcmarkets.js +1 -0
- package/dist/cjs/src/btcturk.js +1 -0
- package/dist/cjs/src/bybit.js +186 -127
- package/dist/cjs/src/coinsph.js +4 -1
- package/dist/cjs/src/cryptocom.js +6 -3
- package/dist/cjs/src/deribit.js +3 -2
- package/dist/cjs/src/digifinex.js +1 -1
- package/dist/cjs/src/gate.js +9 -13
- package/dist/cjs/src/gemini.js +5 -5
- package/dist/cjs/src/htx.js +11 -1
- package/dist/cjs/src/hyperliquid.js +3 -0
- package/dist/cjs/src/independentreserve.js +1 -0
- package/dist/cjs/src/indodax.js +17 -6
- package/dist/cjs/src/kraken.js +31 -8
- package/dist/cjs/src/krakenfutures.js +1 -0
- package/dist/cjs/src/kucoin.js +1 -2
- package/dist/cjs/src/luno.js +4 -1
- package/dist/cjs/src/mercado.js +1 -0
- package/dist/cjs/src/mexc.js +84 -37
- package/dist/cjs/src/novadax.js +1 -0
- package/dist/cjs/src/oceanex.js +1 -0
- package/dist/cjs/src/okcoin.js +4 -1
- package/dist/cjs/src/okx.js +52 -8
- package/dist/cjs/src/phemex.js +1 -1
- package/dist/cjs/src/pro/apex.js +8 -4
- package/dist/cjs/src/pro/backpack.js +7 -5
- package/dist/cjs/src/pro/binance.js +150 -19
- package/dist/cjs/src/pro/bingx.js +206 -220
- package/dist/cjs/src/pro/bitget.js +332 -76
- package/dist/cjs/src/pro/cex.js +1 -0
- package/dist/cjs/src/pro/htx.js +1 -1
- package/dist/cjs/src/pro/independentreserve.js +1 -0
- package/dist/cjs/src/pro/mexc.js +23 -23
- package/dist/cjs/src/pro/okx.js +46 -10
- package/dist/cjs/src/pro/toobit.js +1163 -0
- package/dist/cjs/src/pro/tradeogre.js +1 -1
- package/dist/cjs/src/toobit.js +2999 -0
- package/dist/cjs/src/tradeogre.js +1 -1
- package/dist/cjs/src/upbit.js +1 -0
- package/dist/cjs/src/wavesexchange.js +1 -0
- package/dist/cjs/src/yobit.js +1 -0
- package/dist/cjs/src/zaif.js +1 -0
- package/dist/cjs/src/zonda.js +1 -0
- package/js/ccxt.d.ts +8 -8
- package/js/ccxt.js +6 -6
- package/js/src/abstract/mexc.d.ts +1 -0
- package/js/src/abstract/myokx.d.ts +1 -0
- package/js/src/abstract/okx.d.ts +1 -0
- package/js/src/abstract/okxus.d.ts +1 -0
- package/js/src/abstract/toobit.d.ts +66 -0
- package/js/src/apex.js +2 -2
- package/js/src/backpack.js +1 -1
- package/js/src/base/Exchange.d.ts +9 -0
- package/js/src/base/Exchange.js +129 -2
- package/js/src/bigone.js +4 -4
- package/js/src/binance.d.ts +9 -0
- package/js/src/binance.js +82 -20
- package/js/src/bingx.js +5 -2
- package/js/src/bitbank.js +1 -0
- package/js/src/bitbns.js +1 -0
- package/js/src/bitflyer.js +1 -0
- package/js/src/bitget.js +16 -9
- package/js/src/bithumb.js +1 -0
- package/js/src/bitso.js +1 -0
- package/js/src/bitvavo.d.ts +0 -2
- package/js/src/bitvavo.js +27 -41
- package/js/src/blockchaincom.js +1 -0
- package/js/src/btcalpha.js +1 -0
- package/js/src/btcbox.js +1 -0
- package/js/src/btcmarkets.js +1 -0
- package/js/src/btcturk.js +1 -0
- package/js/src/bybit.d.ts +8 -0
- package/js/src/bybit.js +186 -127
- package/js/src/coinsph.js +4 -1
- package/js/src/cryptocom.js +6 -3
- package/js/src/deribit.js +3 -2
- package/js/src/digifinex.js +1 -1
- package/js/src/gate.d.ts +2 -2
- package/js/src/gate.js +9 -13
- package/js/src/gemini.js +5 -5
- package/js/src/htx.js +11 -1
- package/js/src/hyperliquid.js +3 -0
- package/js/src/independentreserve.js +1 -0
- package/js/src/indodax.js +17 -6
- package/js/src/kraken.d.ts +2 -2
- package/js/src/kraken.js +31 -8
- package/js/src/krakenfutures.js +1 -0
- package/js/src/kucoin.js +1 -2
- package/js/src/luno.js +4 -1
- package/js/src/mercado.js +1 -0
- package/js/src/mexc.d.ts +4 -1
- package/js/src/mexc.js +84 -37
- package/js/src/novadax.js +1 -0
- package/js/src/oceanex.js +1 -0
- package/js/src/okcoin.js +4 -1
- package/js/src/okx.js +52 -8
- package/js/src/phemex.js +1 -1
- package/js/src/pro/apex.js +8 -4
- package/js/src/pro/backpack.d.ts +1 -1
- package/js/src/pro/backpack.js +7 -5
- package/js/src/pro/binance.d.ts +24 -0
- package/js/src/pro/binance.js +150 -19
- package/js/src/pro/bingx.d.ts +53 -33
- package/js/src/pro/bingx.js +207 -221
- package/js/src/pro/bitget.d.ts +6 -0
- package/js/src/pro/bitget.js +332 -76
- package/js/src/pro/cex.js +1 -0
- package/js/src/pro/htx.js +1 -1
- package/js/src/pro/independentreserve.js +1 -0
- package/js/src/pro/mexc.js +23 -23
- package/js/src/pro/okx.d.ts +7 -1
- package/js/src/pro/okx.js +46 -10
- package/js/src/pro/toobit.d.ts +174 -0
- package/js/src/pro/toobit.js +1162 -0
- package/js/src/toobit.d.ts +456 -0
- package/js/src/toobit.js +2992 -0
- package/js/src/upbit.js +1 -0
- package/js/src/wavesexchange.js +1 -0
- package/js/src/yobit.js +1 -0
- package/js/src/zaif.js +1 -0
- package/js/src/zonda.js +1 -0
- package/package.json +1 -1
- package/dist/373.ccxt.browser.js +0 -7630
- package/dist/373.ccxt.browser.min.js +0 -1
- package/js/src/abstract/tradeogre.d.ts +0 -21
- package/js/src/pro/tradeogre.d.ts +0 -49
- package/js/src/pro/tradeogre.js +0 -278
- package/js/src/tradeogre.d.ts +0 -149
- package/js/src/tradeogre.js +0 -872
- /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;
|