ccxt-look 1.81.50

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (264) hide show
  1. package/.cache/eslintcache +1 -0
  2. package/.dockerignore +6 -0
  3. package/.eslintignore +1 -0
  4. package/.gitattributes +5 -0
  5. package/.readthedocs.yaml +16 -0
  6. package/CONTRIBUTING.md +1049 -0
  7. package/LICENSE.txt +21 -0
  8. package/README.md +537 -0
  9. package/SECURITY.md +5 -0
  10. package/build/cleanup-old-tags.js +94 -0
  11. package/build/countries.js +256 -0
  12. package/build/export-exchanges.js +520 -0
  13. package/build/fs.js +51 -0
  14. package/build/transpile.js +1772 -0
  15. package/build/vss.js +78 -0
  16. package/ccxt.browser.js +7 -0
  17. package/ccxt.d.ts +692 -0
  18. package/ccxt.js +171 -0
  19. package/cleanup.sh +2 -0
  20. package/composer-install.sh +20 -0
  21. package/dist/ccxt.browser.js +208383 -0
  22. package/gource.sh +3 -0
  23. package/index.html +7 -0
  24. package/js/.eslintrc +87 -0
  25. package/js/aax.js +2686 -0
  26. package/js/ascendex.js +2584 -0
  27. package/js/base/.eslintrc.js +43 -0
  28. package/js/base/Exchange.js +2371 -0
  29. package/js/base/Precise.js +283 -0
  30. package/js/base/errorHierarchy.js +47 -0
  31. package/js/base/errors.js +55 -0
  32. package/js/base/functions/crypto.js +158 -0
  33. package/js/base/functions/encode.js +118 -0
  34. package/js/base/functions/generic.js +270 -0
  35. package/js/base/functions/misc.js +138 -0
  36. package/js/base/functions/number.js +329 -0
  37. package/js/base/functions/platform.js +38 -0
  38. package/js/base/functions/string.js +21 -0
  39. package/js/base/functions/throttle.js +79 -0
  40. package/js/base/functions/time.js +210 -0
  41. package/js/base/functions/type.js +66 -0
  42. package/js/base/functions.js +28 -0
  43. package/js/bequant.js +32 -0
  44. package/js/bibox.js +1407 -0
  45. package/js/bigone.js +1366 -0
  46. package/js/binance.js +5652 -0
  47. package/js/binancecoinm.js +46 -0
  48. package/js/binanceus.js +46 -0
  49. package/js/binanceusdm.js +49 -0
  50. package/js/bit2c.js +535 -0
  51. package/js/bitbank.js +842 -0
  52. package/js/bitbay.js +16 -0
  53. package/js/bitbns.js +1073 -0
  54. package/js/bitcoincom.js +15 -0
  55. package/js/bitfinex.js +1433 -0
  56. package/js/bitfinex2.js +2025 -0
  57. package/js/bitflyer.js +840 -0
  58. package/js/bitforex.js +614 -0
  59. package/js/bitget.js +2397 -0
  60. package/js/bithumb.js +980 -0
  61. package/js/bitmart.js +2516 -0
  62. package/js/bitmex.js +1809 -0
  63. package/js/bitopro.js +1443 -0
  64. package/js/bitpanda.js +1782 -0
  65. package/js/bitrue.js +1747 -0
  66. package/js/bitso.js +1062 -0
  67. package/js/bitstamp.js +1757 -0
  68. package/js/bitstamp1.js +343 -0
  69. package/js/bittrex.js +1876 -0
  70. package/js/bitvavo.js +1579 -0
  71. package/js/bkex.js +1233 -0
  72. package/js/bl3p.js +346 -0
  73. package/js/blockchaincom.js +969 -0
  74. package/js/btcalpha.js +680 -0
  75. package/js/btcbox.js +477 -0
  76. package/js/btcmarkets.js +1022 -0
  77. package/js/btctradeua.js +466 -0
  78. package/js/btcturk.js +734 -0
  79. package/js/buda.js +946 -0
  80. package/js/bw.js +1265 -0
  81. package/js/bybit.js +3372 -0
  82. package/js/bytetrade.js +1336 -0
  83. package/js/cdax.js +1646 -0
  84. package/js/cex.js +1410 -0
  85. package/js/coinbase.js +1342 -0
  86. package/js/coinbaseprime.js +31 -0
  87. package/js/coinbasepro.js +1466 -0
  88. package/js/coincheck.js +755 -0
  89. package/js/coinex.js +3400 -0
  90. package/js/coinfalcon.js +880 -0
  91. package/js/coinmate.js +794 -0
  92. package/js/coinone.js +816 -0
  93. package/js/coinspot.js +345 -0
  94. package/js/crex24.js +1636 -0
  95. package/js/cryptocom.js +1832 -0
  96. package/js/currencycom.js +1748 -0
  97. package/js/delta.js +1547 -0
  98. package/js/deribit.js +2148 -0
  99. package/js/digifinex.js +1585 -0
  100. package/js/eqonex.js +1660 -0
  101. package/js/exmo.js +1670 -0
  102. package/js/fairdesk.js +1231 -0
  103. package/js/flowbtc.js +35 -0
  104. package/js/fmfwio.js +34 -0
  105. package/js/ftx.js +2751 -0
  106. package/js/ftxus.js +38 -0
  107. package/js/gateio.js +4174 -0
  108. package/js/gemini.js +1397 -0
  109. package/js/hitbtc.js +1343 -0
  110. package/js/hitbtc3.js +2329 -0
  111. package/js/hollaex.js +1486 -0
  112. package/js/huobi.js +5706 -0
  113. package/js/huobijp.js +1710 -0
  114. package/js/huobipro.js +18 -0
  115. package/js/idex.js +1439 -0
  116. package/js/independentreserve.js +649 -0
  117. package/js/indodax.js +742 -0
  118. package/js/itbit.js +722 -0
  119. package/js/kraken.js +2179 -0
  120. package/js/kucoin.js +2571 -0
  121. package/js/kucoinfutures.js +1771 -0
  122. package/js/kuna.js +809 -0
  123. package/js/latoken.js +1445 -0
  124. package/js/lbank.js +760 -0
  125. package/js/liquid.js +1432 -0
  126. package/js/luno.js +873 -0
  127. package/js/lykke.js +1147 -0
  128. package/js/mercado.js +771 -0
  129. package/js/mexc.js +3151 -0
  130. package/js/ndax.js +2233 -0
  131. package/js/novadax.js +1318 -0
  132. package/js/oceanex.js +816 -0
  133. package/js/okcoin.js +3841 -0
  134. package/js/okex.js +16 -0
  135. package/js/okex5.js +16 -0
  136. package/js/okx.js +4795 -0
  137. package/js/paymium.js +498 -0
  138. package/js/phemex.js +2957 -0
  139. package/js/poloniex.js +1674 -0
  140. package/js/probit.js +1346 -0
  141. package/js/qtrade.js +1588 -0
  142. package/js/ripio.js +1061 -0
  143. package/js/static_dependencies/BN/bn.js +3526 -0
  144. package/js/static_dependencies/README.md +1 -0
  145. package/js/static_dependencies/crypto-js/crypto-js.js +5988 -0
  146. package/js/static_dependencies/elliptic/lib/elliptic/curve/base.js +375 -0
  147. package/js/static_dependencies/elliptic/lib/elliptic/curve/edwards.js +433 -0
  148. package/js/static_dependencies/elliptic/lib/elliptic/curve/index.js +8 -0
  149. package/js/static_dependencies/elliptic/lib/elliptic/curve/mont.js +180 -0
  150. package/js/static_dependencies/elliptic/lib/elliptic/curve/short.js +938 -0
  151. package/js/static_dependencies/elliptic/lib/elliptic/curves.js +204 -0
  152. package/js/static_dependencies/elliptic/lib/elliptic/ec/index.js +240 -0
  153. package/js/static_dependencies/elliptic/lib/elliptic/ec/key.js +119 -0
  154. package/js/static_dependencies/elliptic/lib/elliptic/ec/signature.js +24 -0
  155. package/js/static_dependencies/elliptic/lib/elliptic/eddsa/index.js +145 -0
  156. package/js/static_dependencies/elliptic/lib/elliptic/eddsa/key.js +100 -0
  157. package/js/static_dependencies/elliptic/lib/elliptic/eddsa/signature.js +65 -0
  158. package/js/static_dependencies/elliptic/lib/elliptic/precomputed/secp256k1.js +780 -0
  159. package/js/static_dependencies/elliptic/lib/elliptic/utils.js +214 -0
  160. package/js/static_dependencies/elliptic/lib/elliptic.js +22 -0
  161. package/js/static_dependencies/elliptic/lib/hmac-drbg/hmac-drbg.js +114 -0
  162. package/js/static_dependencies/fetch-ponyfill/fetch-node.js +39 -0
  163. package/js/static_dependencies/node-fetch/index.js +1564 -0
  164. package/js/static_dependencies/node-rsa/NodeRSA.js +223 -0
  165. package/js/static_dependencies/node-rsa/asn1/ber/errors.js +13 -0
  166. package/js/static_dependencies/node-rsa/asn1/ber/index.js +21 -0
  167. package/js/static_dependencies/node-rsa/asn1/ber/reader.js +262 -0
  168. package/js/static_dependencies/node-rsa/asn1/ber/types.js +36 -0
  169. package/js/static_dependencies/node-rsa/asn1/index.js +17 -0
  170. package/js/static_dependencies/node-rsa/encryptEngines/js.js +34 -0
  171. package/js/static_dependencies/node-rsa/formats/components.js +71 -0
  172. package/js/static_dependencies/node-rsa/formats/formats.js +31 -0
  173. package/js/static_dependencies/node-rsa/formats/pkcs1.js +148 -0
  174. package/js/static_dependencies/node-rsa/formats/pkcs8.js +187 -0
  175. package/js/static_dependencies/node-rsa/libs/jsbn.js +1252 -0
  176. package/js/static_dependencies/node-rsa/libs/rsa.js +147 -0
  177. package/js/static_dependencies/node-rsa/schemes/pkcs1.js +176 -0
  178. package/js/static_dependencies/node-rsa/schemes/schemes.js +21 -0
  179. package/js/static_dependencies/node-rsa/utils.js +98 -0
  180. package/js/static_dependencies/qs/formats.js +18 -0
  181. package/js/static_dependencies/qs/index.js +11 -0
  182. package/js/static_dependencies/qs/parse.js +242 -0
  183. package/js/static_dependencies/qs/stringify.js +269 -0
  184. package/js/static_dependencies/qs/utils.js +230 -0
  185. package/js/stex.js +1925 -0
  186. package/js/test/.eslintrc.js +42 -0
  187. package/js/test/Exchange/test.balance.js +61 -0
  188. package/js/test/Exchange/test.borrowRate.js +32 -0
  189. package/js/test/Exchange/test.currency.js +52 -0
  190. package/js/test/Exchange/test.fetchBalance.js +23 -0
  191. package/js/test/Exchange/test.fetchBorrowInterest.js +59 -0
  192. package/js/test/Exchange/test.fetchBorrowRate.js +32 -0
  193. package/js/test/Exchange/test.fetchBorrowRates.js +28 -0
  194. package/js/test/Exchange/test.fetchClosedOrders.js +32 -0
  195. package/js/test/Exchange/test.fetchCurrencies.js +35 -0
  196. package/js/test/Exchange/test.fetchDeposits.js +31 -0
  197. package/js/test/Exchange/test.fetchFundingFees.js +19 -0
  198. package/js/test/Exchange/test.fetchFundingRateHistory.js +40 -0
  199. package/js/test/Exchange/test.fetchL2OrderBook.js +23 -0
  200. package/js/test/Exchange/test.fetchLedger.js +42 -0
  201. package/js/test/Exchange/test.fetchLeverageTiers.js +33 -0
  202. package/js/test/Exchange/test.fetchMarketLeverageTiers.js +22 -0
  203. package/js/test/Exchange/test.fetchMarkets.js +33 -0
  204. package/js/test/Exchange/test.fetchMyTrades.js +42 -0
  205. package/js/test/Exchange/test.fetchOHLCV.js +46 -0
  206. package/js/test/Exchange/test.fetchOpenOrders.js +36 -0
  207. package/js/test/Exchange/test.fetchOrderBook.js +25 -0
  208. package/js/test/Exchange/test.fetchOrderBooks.js +35 -0
  209. package/js/test/Exchange/test.fetchOrders.js +41 -0
  210. package/js/test/Exchange/test.fetchPositions.js +47 -0
  211. package/js/test/Exchange/test.fetchStatus.js +35 -0
  212. package/js/test/Exchange/test.fetchTicker.js +38 -0
  213. package/js/test/Exchange/test.fetchTickers.js +49 -0
  214. package/js/test/Exchange/test.fetchTrades.js +39 -0
  215. package/js/test/Exchange/test.fetchTradingFee.js +18 -0
  216. package/js/test/Exchange/test.fetchTradingFees.js +22 -0
  217. package/js/test/Exchange/test.fetchTransactions.js +31 -0
  218. package/js/test/Exchange/test.fetchWithdrawals.js +31 -0
  219. package/js/test/Exchange/test.ledgerItem.js +46 -0
  220. package/js/test/Exchange/test.leverageTier.js +33 -0
  221. package/js/test/Exchange/test.loadMarkets.js +35 -0
  222. package/js/test/Exchange/test.market.js +129 -0
  223. package/js/test/Exchange/test.ohlcv.js +33 -0
  224. package/js/test/Exchange/test.order.js +62 -0
  225. package/js/test/Exchange/test.orderbook.js +61 -0
  226. package/js/test/Exchange/test.position.js +21 -0
  227. package/js/test/Exchange/test.throttle.js +94 -0
  228. package/js/test/Exchange/test.ticker.js +95 -0
  229. package/js/test/Exchange/test.trade.js +68 -0
  230. package/js/test/Exchange/test.tradingFee.js +34 -0
  231. package/js/test/Exchange/test.transaction.js +35 -0
  232. package/js/test/base/.eslintrc +38 -0
  233. package/js/test/base/functions/test.crypto.js +110 -0
  234. package/js/test/base/functions/test.datetime.js +62 -0
  235. package/js/test/base/functions/test.generic.js +152 -0
  236. package/js/test/base/functions/test.number.js +362 -0
  237. package/js/test/base/functions/test.time.js +56 -0
  238. package/js/test/base/functions/test.type.js +53 -0
  239. package/js/test/base/test.base.js +193 -0
  240. package/js/test/errors/test.InsufficientFunds.js +86 -0
  241. package/js/test/errors/test.InvalidNonce.js +64 -0
  242. package/js/test/errors/test.InvalidOrder.js +35 -0
  243. package/js/test/errors/test.OrderNotFound.js +39 -0
  244. package/js/test/test.js +426 -0
  245. package/js/test/test.timeout_hang.js +12 -0
  246. package/js/therock.js +1431 -0
  247. package/js/tidebit.js +632 -0
  248. package/js/tidex.js +939 -0
  249. package/js/timex.js +1283 -0
  250. package/js/upbit.js +1622 -0
  251. package/js/vcc.js +1353 -0
  252. package/js/wavesexchange.js +2185 -0
  253. package/js/wazirx.js +732 -0
  254. package/js/whitebit.js +1352 -0
  255. package/js/woo.js +1577 -0
  256. package/js/xena.js +1948 -0
  257. package/js/yobit.js +1129 -0
  258. package/js/zaif.js +647 -0
  259. package/js/zb.js +4088 -0
  260. package/js/zipmex.js +40 -0
  261. package/js/zonda.js +1497 -0
  262. package/multilang.sh +159 -0
  263. package/package.json +591 -0
  264. package/postinstall.js +103 -0
package/js/ascendex.js ADDED
@@ -0,0 +1,2584 @@
1
+ 'use strict';
2
+
3
+ // ---------------------------------------------------------------------------
4
+
5
+ const Exchange = require ('./base/Exchange');
6
+ const { ArgumentsRequired, AuthenticationError, ExchangeError, InsufficientFunds, InvalidOrder, BadSymbol, PermissionDenied, BadRequest } = require ('./base/errors');
7
+ const { TICK_SIZE } = require ('./base/functions/number');
8
+ const Precise = require ('./base/Precise');
9
+
10
+ // ---------------------------------------------------------------------------
11
+
12
+ module.exports = class ascendex extends Exchange {
13
+ describe () {
14
+ return this.deepExtend (super.describe (), {
15
+ 'id': 'ascendex',
16
+ 'name': 'AscendEX',
17
+ 'countries': [ 'SG' ], // Singapore
18
+ // 8 requests per minute = 0.13333 per second => rateLimit = 750
19
+ // testing 400 works
20
+ 'rateLimit': 400,
21
+ 'certified': true,
22
+ 'pro': true,
23
+ // new metainfo interface
24
+ 'has': {
25
+ 'CORS': undefined,
26
+ 'spot': true,
27
+ 'margin': true,
28
+ 'swap': true,
29
+ 'future': true,
30
+ 'option': false,
31
+ 'addMargin': true,
32
+ 'cancelAllOrders': true,
33
+ 'cancelOrder': true,
34
+ 'createOrder': true,
35
+ 'createReduceOnlyOrder': true,
36
+ 'createStopLimitOrder': true,
37
+ 'createStopMarketOrder': true,
38
+ 'createStopOrder': true,
39
+ 'fetchAccounts': true,
40
+ 'fetchBalance': true,
41
+ 'fetchClosedOrders': true,
42
+ 'fetchCurrencies': true,
43
+ 'fetchDepositAddress': true,
44
+ 'fetchDepositAddresses': false,
45
+ 'fetchDepositAddressesByNetwork': false,
46
+ 'fetchDeposits': true,
47
+ 'fetchFundingFee': false,
48
+ 'fetchFundingFees': false,
49
+ 'fetchFundingHistory': false,
50
+ 'fetchFundingRate': false,
51
+ 'fetchFundingRateHistory': false,
52
+ 'fetchFundingRates': true,
53
+ 'fetchIndexOHLCV': false,
54
+ 'fetchLeverage': false,
55
+ 'fetchLeverageTiers': true,
56
+ 'fetchMarketLeverageTiers': 'emulated',
57
+ 'fetchMarkets': true,
58
+ 'fetchMarkOHLCV': false,
59
+ 'fetchOHLCV': true,
60
+ 'fetchOpenOrders': true,
61
+ 'fetchOrder': true,
62
+ 'fetchOrderBook': true,
63
+ 'fetchOrders': false,
64
+ 'fetchPosition': false,
65
+ 'fetchPositions': true,
66
+ 'fetchPositionsRisk': false,
67
+ 'fetchPremiumIndexOHLCV': false,
68
+ 'fetchTicker': true,
69
+ 'fetchTickers': true,
70
+ 'fetchTrades': true,
71
+ 'fetchTradingFee': false,
72
+ 'fetchTradingFees': true,
73
+ 'fetchTransactions': true,
74
+ 'fetchTransfer': false,
75
+ 'fetchTransfers': false,
76
+ 'fetchWithdrawal': false,
77
+ 'fetchWithdrawals': true,
78
+ 'reduceMargin': true,
79
+ 'setLeverage': true,
80
+ 'setMarginMode': true,
81
+ 'setPositionMode': false,
82
+ 'transfer': true,
83
+ },
84
+ 'timeframes': {
85
+ '1m': '1',
86
+ '5m': '5',
87
+ '15m': '15',
88
+ '30m': '30',
89
+ '1h': '60',
90
+ '2h': '120',
91
+ '4h': '240',
92
+ '6h': '360',
93
+ '12h': '720',
94
+ '1d': '1d',
95
+ '1w': '1w',
96
+ '1M': '1m',
97
+ },
98
+ 'version': 'v2',
99
+ 'urls': {
100
+ 'logo': 'https://user-images.githubusercontent.com/1294454/112027508-47984600-8b48-11eb-9e17-d26459cc36c6.jpg',
101
+ 'api': {
102
+ 'rest': 'https://ascendex.com',
103
+ },
104
+ 'test': {
105
+ 'rest': 'https://api-test.ascendex-sandbox.com',
106
+ },
107
+ 'www': 'https://ascendex.com',
108
+ 'doc': [
109
+ 'https://ascendex.github.io/ascendex-pro-api/#ascendex-pro-api-documentation',
110
+ ],
111
+ 'fees': 'https://ascendex.com/en/feerate/transactionfee-traderate',
112
+ 'referral': {
113
+ 'url': 'https://ascendex.com/en-us/register?inviteCode=EL6BXBQM',
114
+ 'discount': 0.25,
115
+ },
116
+ },
117
+ 'api': {
118
+ 'v1': {
119
+ 'public': {
120
+ 'get': {
121
+ 'assets': 1,
122
+ 'products': 1,
123
+ 'ticker': 1,
124
+ 'barhist/info': 1,
125
+ 'barhist': 1,
126
+ 'depth': 1,
127
+ 'trades': 1,
128
+ 'cash/assets': 1, // not documented
129
+ 'cash/products': 1, // not documented
130
+ 'margin/assets': 1, // not documented
131
+ 'margin/products': 1, // not documented
132
+ 'futures/collateral': 1,
133
+ 'futures/contracts': 1,
134
+ 'futures/ref-px': 1,
135
+ 'futures/market-data': 1,
136
+ 'futures/funding-rates': 1,
137
+ 'risk-limit-info': 1,
138
+ },
139
+ },
140
+ 'private': {
141
+ 'get': {
142
+ 'info': 1,
143
+ 'wallet/transactions': 1,
144
+ 'wallet/deposit/address': 1, // not documented
145
+ 'data/balance/snapshot': 1,
146
+ 'data/balance/history': 1,
147
+ },
148
+ 'accountCategory': {
149
+ 'get': {
150
+ 'balance': 1,
151
+ 'order/open': 1,
152
+ 'order/status': 1,
153
+ 'order/hist/current': 1,
154
+ 'risk': 1,
155
+ },
156
+ 'post': {
157
+ 'order': 1,
158
+ 'order/batch': 1,
159
+ },
160
+ 'delete': {
161
+ 'order': 1,
162
+ 'order/all': 1,
163
+ 'order/batch': 1,
164
+ },
165
+ },
166
+ 'accountGroup': {
167
+ 'get': {
168
+ 'cash/balance': 1,
169
+ 'margin/balance': 1,
170
+ 'margin/risk': 1,
171
+ 'futures/collateral-balance': 1,
172
+ 'futures/position': 1,
173
+ 'futures/risk': 1,
174
+ 'futures/funding-payments': 1,
175
+ 'order/hist': 1,
176
+ 'spot/fee': 1,
177
+ },
178
+ 'post': {
179
+ 'transfer': 1,
180
+ 'futures/transfer/deposit': 1,
181
+ 'futures/transfer/withdraw': 1,
182
+ },
183
+ },
184
+ },
185
+ },
186
+ 'v2': {
187
+ 'public': {
188
+ 'get': {
189
+ 'assets': 1,
190
+ 'futures/contract': 1,
191
+ 'futures/collateral': 1,
192
+ 'futures/pricing-data': 1,
193
+ },
194
+ },
195
+ 'private': {
196
+ 'get': {
197
+ 'account/info': 1,
198
+ },
199
+ 'accountGroup': {
200
+ 'get': {
201
+ 'order/hist': 1,
202
+ 'futures/position': 1,
203
+ 'futures/free-margin': 1,
204
+ 'futures/order/hist/current': 1,
205
+ 'futures/order/open': 1,
206
+ 'futures/order/status': 1,
207
+ },
208
+ 'post': {
209
+ 'futures/isolated-position-margin': 1,
210
+ 'futures/margin-type': 1,
211
+ 'futures/leverage': 1,
212
+ 'futures/transfer/deposit': 1,
213
+ 'futures/transfer/withdraw': 1,
214
+ 'futures/order': 1,
215
+ 'futures/order/batch': 1,
216
+ 'futures/order/open': 1,
217
+ 'subuser/subuser-transfer': 1,
218
+ 'subuser/subuser-transfer-hist': 1,
219
+ },
220
+ 'delete': {
221
+ 'futures/order': 1,
222
+ 'futures/order/batch': 1,
223
+ 'futures/order/all': 1,
224
+ },
225
+ },
226
+ },
227
+ },
228
+ },
229
+ 'fees': {
230
+ 'trading': {
231
+ 'feeSide': 'get',
232
+ 'tierBased': true,
233
+ 'percentage': true,
234
+ 'taker': this.parseNumber ('0.002'),
235
+ 'maker': this.parseNumber ('0.002'),
236
+ },
237
+ },
238
+ 'precisionMode': TICK_SIZE,
239
+ 'options': {
240
+ 'account-category': 'cash', // 'cash', 'margin', 'futures' // obsolete
241
+ 'account-group': undefined,
242
+ 'fetchClosedOrders': {
243
+ 'method': 'v1PrivateAccountGroupGetOrderHist', // 'v1PrivateAccountGroupGetAccountCategoryOrderHistCurrent'
244
+ },
245
+ 'defaultType': 'spot', // 'spot', 'margin', 'swap'
246
+ 'accountsByType': {
247
+ 'spot': 'cash',
248
+ 'future': 'futures',
249
+ 'margin': 'margin',
250
+ },
251
+ 'transfer': {
252
+ 'fillResponseFromRequest': true,
253
+ },
254
+ },
255
+ 'exceptions': {
256
+ 'exact': {
257
+ // not documented
258
+ '1900': BadRequest, // {"code":1900,"message":"Invalid Http Request Input"}
259
+ '2100': AuthenticationError, // {"code":2100,"message":"ApiKeyFailure"}
260
+ '5002': BadSymbol, // {"code":5002,"message":"Invalid Symbol"}
261
+ '6001': BadSymbol, // {"code":6001,"message":"Trading is disabled on symbol."}
262
+ '6010': InsufficientFunds, // {'code': 6010, 'message': 'Not enough balance.'}
263
+ '60060': InvalidOrder, // { 'code': 60060, 'message': 'The order is already filled or canceled.' }
264
+ '600503': InvalidOrder, // {"code":600503,"message":"Notional is too small."}
265
+ // documented
266
+ '100001': BadRequest, // INVALID_HTTP_INPUT Http request is invalid
267
+ '100002': BadRequest, // DATA_NOT_AVAILABLE Some required data is missing
268
+ '100003': BadRequest, // KEY_CONFLICT The same key exists already
269
+ '100004': BadRequest, // INVALID_REQUEST_DATA The HTTP request contains invalid field or argument
270
+ '100005': BadRequest, // INVALID_WS_REQUEST_DATA Websocket request contains invalid field or argument
271
+ '100006': BadRequest, // INVALID_ARGUMENT The arugment is invalid
272
+ '100007': BadRequest, // ENCRYPTION_ERROR Something wrong with data encryption
273
+ '100008': BadSymbol, // SYMBOL_ERROR Symbol does not exist or not valid for the request
274
+ '100009': AuthenticationError, // AUTHORIZATION_NEEDED Authorization is require for the API access or request
275
+ '100010': BadRequest, // INVALID_OPERATION The action is invalid or not allowed for the account
276
+ '100011': BadRequest, // INVALID_TIMESTAMP Not a valid timestamp
277
+ '100012': BadRequest, // INVALID_STR_FORMAT String format does not
278
+ '100013': BadRequest, // INVALID_NUM_FORMAT Invalid number input
279
+ '100101': ExchangeError, // UNKNOWN_ERROR Some unknown error
280
+ '150001': BadRequest, // INVALID_JSON_FORMAT Require a valid json object
281
+ '200001': AuthenticationError, // AUTHENTICATION_FAILED Authorization failed
282
+ '200002': ExchangeError, // TOO_MANY_ATTEMPTS Tried and failed too many times
283
+ '200003': ExchangeError, // ACCOUNT_NOT_FOUND Account not exist
284
+ '200004': ExchangeError, // ACCOUNT_NOT_SETUP Account not setup properly
285
+ '200005': ExchangeError, // ACCOUNT_ALREADY_EXIST Account already exist
286
+ '200006': ExchangeError, // ACCOUNT_ERROR Some error related with error
287
+ '200007': ExchangeError, // CODE_NOT_FOUND
288
+ '200008': ExchangeError, // CODE_EXPIRED Code expired
289
+ '200009': ExchangeError, // CODE_MISMATCH Code does not match
290
+ '200010': AuthenticationError, // PASSWORD_ERROR Wrong assword
291
+ '200011': ExchangeError, // CODE_GEN_FAILED Do not generate required code promptly
292
+ '200012': ExchangeError, // FAKE_COKE_VERIFY
293
+ '200013': ExchangeError, // SECURITY_ALERT Provide security alert message
294
+ '200014': PermissionDenied, // RESTRICTED_ACCOUNT Account is restricted for certain activity, such as trading, or withdraw.
295
+ '200015': PermissionDenied, // PERMISSION_DENIED No enough permission for the operation
296
+ '300001': InvalidOrder, // INVALID_PRICE Order price is invalid
297
+ '300002': InvalidOrder, // INVALID_QTY Order size is invalid
298
+ '300003': InvalidOrder, // INVALID_SIDE Order side is invalid
299
+ '300004': InvalidOrder, // INVALID_NOTIONAL Notional is too small or too large
300
+ '300005': InvalidOrder, // INVALID_TYPE Order typs is invalid
301
+ '300006': InvalidOrder, // INVALID_ORDER_ID Order id is invalid
302
+ '300007': InvalidOrder, // INVALID_TIME_IN_FORCE Time In Force in order request is invalid
303
+ '300008': InvalidOrder, // INVALID_ORDER_PARAMETER Some order parameter is invalid
304
+ '300009': InvalidOrder, // TRADING_VIOLATION Trading violation on account or asset
305
+ '300011': InsufficientFunds, // INVALID_BALANCE No enough account or asset balance for the trading
306
+ '300012': BadSymbol, // INVALID_PRODUCT Not a valid product supported by exchange
307
+ '300013': InvalidOrder, // INVALID_BATCH_ORDER Some or all orders are invalid in batch order request
308
+ '300014': InvalidOrder, // {"code":300014,"message":"Order price doesn't conform to the required tick size: 0.1","reason":"TICK_SIZE_VIOLATION"}
309
+ '300020': InvalidOrder, // TRADING_RESTRICTED There is some trading restriction on account or asset
310
+ '300021': InvalidOrder, // TRADING_DISABLED Trading is disabled on account or asset
311
+ '300031': InvalidOrder, // NO_MARKET_PRICE No market price for market type order trading
312
+ '310001': InsufficientFunds, // INVALID_MARGIN_BALANCE No enough margin balance
313
+ '310002': InvalidOrder, // INVALID_MARGIN_ACCOUNT Not a valid account for margin trading
314
+ '310003': InvalidOrder, // MARGIN_TOO_RISKY Leverage is too high
315
+ '310004': BadSymbol, // INVALID_MARGIN_ASSET This asset does not support margin trading
316
+ '310005': InvalidOrder, // INVALID_REFERENCE_PRICE There is no valid reference price
317
+ '510001': ExchangeError, // SERVER_ERROR Something wrong with server.
318
+ '900001': ExchangeError, // HUMAN_CHALLENGE Human change do not pass
319
+ },
320
+ 'broad': {},
321
+ },
322
+ 'commonCurrencies': {
323
+ 'BOND': 'BONDED',
324
+ 'BTCBEAR': 'BEAR',
325
+ 'BTCBULL': 'BULL',
326
+ 'BYN': 'BeyondFi',
327
+ 'PLN': 'Pollen',
328
+ },
329
+ });
330
+ }
331
+
332
+ getAccount (params = {}) {
333
+ // get current or provided bitmax sub-account
334
+ const account = this.safeValue (params, 'account', this.options['account']);
335
+ return account.toLowerCase ().capitalize ();
336
+ }
337
+
338
+ async fetchCurrencies (params = {}) {
339
+ const assets = await this.v1PublicGetAssets (params);
340
+ //
341
+ // {
342
+ // "code":0,
343
+ // "data":[
344
+ // {
345
+ // "assetCode" : "LTCBULL",
346
+ // "assetName" : "3X Long LTC Token",
347
+ // "precisionScale" : 9,
348
+ // "nativeScale" : 4,
349
+ // "withdrawalFee" : "0.2",
350
+ // "minWithdrawalAmt" : "1.0",
351
+ // "status" : "Normal"
352
+ // },
353
+ // ]
354
+ // }
355
+ //
356
+ const margin = await this.v1PublicGetMarginAssets (params);
357
+ //
358
+ // {
359
+ // "code":0,
360
+ // "data":[
361
+ // {
362
+ // "assetCode":"BTT",
363
+ // "borrowAssetCode":"BTT-B",
364
+ // "interestAssetCode":"BTT-I",
365
+ // "nativeScale":0,
366
+ // "numConfirmations":1,
367
+ // "withdrawFee":"100.0",
368
+ // "minWithdrawalAmt":"1000.0",
369
+ // "statusCode":"Normal",
370
+ // "statusMessage":"",
371
+ // "interestRate":"0.001"
372
+ // }
373
+ // ]
374
+ // }
375
+ //
376
+ const cash = await this.v1PublicGetCashAssets (params);
377
+ //
378
+ // {
379
+ // "code":0,
380
+ // "data":[
381
+ // {
382
+ // "assetCode":"LTCBULL",
383
+ // "nativeScale":4,
384
+ // "numConfirmations":20,
385
+ // "withdrawFee":"0.2",
386
+ // "minWithdrawalAmt":"1.0",
387
+ // "statusCode":"Normal",
388
+ // "statusMessage":""
389
+ // }
390
+ // ]
391
+ // }
392
+ //
393
+ const assetsData = this.safeValue (assets, 'data', []);
394
+ const marginData = this.safeValue (margin, 'data', []);
395
+ const cashData = this.safeValue (cash, 'data', []);
396
+ const assetsById = this.indexBy (assetsData, 'assetCode');
397
+ const marginById = this.indexBy (marginData, 'assetCode');
398
+ const cashById = this.indexBy (cashData, 'assetCode');
399
+ const dataById = this.deepExtend (assetsById, marginById, cashById);
400
+ const ids = Object.keys (dataById);
401
+ const result = {};
402
+ for (let i = 0; i < ids.length; i++) {
403
+ const id = ids[i];
404
+ const currency = dataById[id];
405
+ const code = this.safeCurrencyCode (id);
406
+ const scale = this.safeString2 (currency, 'precisionScale', 'nativeScale');
407
+ const precision = this.parseNumber (this.parsePrecision (scale));
408
+ // why would the exchange API have different names for the same field
409
+ const fee = this.safeNumber2 (currency, 'withdrawFee', 'withdrawalFee');
410
+ const status = this.safeString2 (currency, 'status', 'statusCode');
411
+ const active = (status === 'Normal');
412
+ const margin = ('borrowAssetCode' in currency);
413
+ result[code] = {
414
+ 'id': id,
415
+ 'code': code,
416
+ 'info': currency,
417
+ 'type': undefined,
418
+ 'margin': margin,
419
+ 'name': this.safeString (currency, 'assetName'),
420
+ 'active': active,
421
+ 'deposit': undefined,
422
+ 'withdraw': undefined,
423
+ 'fee': fee,
424
+ 'precision': precision,
425
+ 'limits': {
426
+ 'amount': {
427
+ 'min': precision,
428
+ 'max': undefined,
429
+ },
430
+ 'withdraw': {
431
+ 'min': this.safeNumber (currency, 'minWithdrawalAmt'),
432
+ 'max': undefined,
433
+ },
434
+ },
435
+ };
436
+ }
437
+ return result;
438
+ }
439
+
440
+ async fetchMarkets (params = {}) {
441
+ const products = await this.v1PublicGetProducts (params);
442
+ //
443
+ // {
444
+ // "code":0,
445
+ // "data":[
446
+ // {
447
+ // "symbol":"LBA/BTC",
448
+ // "baseAsset":"LBA",
449
+ // "quoteAsset":"BTC",
450
+ // "status":"Normal",
451
+ // "minNotional":"0.000625",
452
+ // "maxNotional":"6.25",
453
+ // "marginTradable":false,
454
+ // "commissionType":"Quote",
455
+ // "commissionReserveRate":"0.001",
456
+ // "tickSize":"0.000000001",
457
+ // "lotSize":"1"
458
+ // },
459
+ // ]
460
+ // }
461
+ //
462
+ const cash = await this.v1PublicGetCashProducts (params);
463
+ //
464
+ // {
465
+ // "code":0,
466
+ // "data":[
467
+ // {
468
+ // "symbol":"QTUM/BTC",
469
+ // "domain":"BTC",
470
+ // "tradingStartTime":1569506400000,
471
+ // "collapseDecimals":"0.0001,0.000001,0.00000001",
472
+ // "minQty":"0.000000001",
473
+ // "maxQty":"1000000000",
474
+ // "minNotional":"0.000625",
475
+ // "maxNotional":"12.5",
476
+ // "statusCode":"Normal",
477
+ // "statusMessage":"",
478
+ // "tickSize":"0.00000001",
479
+ // "useTick":false,
480
+ // "lotSize":"0.1",
481
+ // "useLot":false,
482
+ // "commissionType":"Quote",
483
+ // "commissionReserveRate":"0.001",
484
+ // "qtyScale":1,
485
+ // "priceScale":8,
486
+ // "notionalScale":4
487
+ // }
488
+ // ]
489
+ // }
490
+ //
491
+ const perpetuals = await this.v2PublicGetFuturesContract (params);
492
+ //
493
+ // {
494
+ // "code":0,
495
+ // "data":[
496
+ // {
497
+ // "symbol":"BTC-PERP",
498
+ // "status":"Normal",
499
+ // "displayName":"BTCUSDT",
500
+ // "settlementAsset":"USDT",
501
+ // "underlying":"BTC/USDT",
502
+ // "tradingStartTime":1579701600000,
503
+ // "priceFilter":{"minPrice":"1","maxPrice":"1000000","tickSize":"1"},
504
+ // "lotSizeFilter":{"minQty":"0.0001","maxQty":"1000000000","lotSize":"0.0001"},
505
+ // "commissionType":"Quote",
506
+ // "commissionReserveRate":"0.001",
507
+ // "marketOrderPriceMarkup":"0.03",
508
+ // "marginRequirements":[
509
+ // {"positionNotionalLowerBound":"0","positionNotionalUpperBound":"50000","initialMarginRate":"0.01","maintenanceMarginRate":"0.006"},
510
+ // {"positionNotionalLowerBound":"50000","positionNotionalUpperBound":"200000","initialMarginRate":"0.02","maintenanceMarginRate":"0.012"},
511
+ // {"positionNotionalLowerBound":"200000","positionNotionalUpperBound":"2000000","initialMarginRate":"0.04","maintenanceMarginRate":"0.024"},
512
+ // {"positionNotionalLowerBound":"2000000","positionNotionalUpperBound":"20000000","initialMarginRate":"0.1","maintenanceMarginRate":"0.06"},
513
+ // {"positionNotionalLowerBound":"20000000","positionNotionalUpperBound":"40000000","initialMarginRate":"0.2","maintenanceMarginRate":"0.12"},
514
+ // {"positionNotionalLowerBound":"40000000","positionNotionalUpperBound":"1000000000","initialMarginRate":"0.333333","maintenanceMarginRate":"0.2"}
515
+ // ]
516
+ // }
517
+ // ]
518
+ // }
519
+ //
520
+ const productsData = this.safeValue (products, 'data', []);
521
+ const productsById = this.indexBy (productsData, 'symbol');
522
+ const cashData = this.safeValue (cash, 'data', []);
523
+ const perpetualsData = this.safeValue (perpetuals, 'data', []);
524
+ const cashAndPerpetualsData = this.arrayConcat (cashData, perpetualsData);
525
+ const cashAndPerpetualsById = this.indexBy (cashAndPerpetualsData, 'symbol');
526
+ const dataById = this.deepExtend (productsById, cashAndPerpetualsById);
527
+ const ids = Object.keys (dataById);
528
+ const result = [];
529
+ for (let i = 0; i < ids.length; i++) {
530
+ const id = ids[i];
531
+ const market = dataById[id];
532
+ let baseId = this.safeString (market, 'baseAsset');
533
+ let quoteId = this.safeString (market, 'quoteAsset');
534
+ const settleId = this.safeValue (market, 'settlementAsset');
535
+ let base = this.safeCurrencyCode (baseId);
536
+ let quote = this.safeCurrencyCode (quoteId);
537
+ const settle = this.safeCurrencyCode (settleId);
538
+ const status = this.safeString (market, 'status');
539
+ const spot = settle === undefined;
540
+ const swap = !spot;
541
+ const linear = swap ? true : undefined;
542
+ let minQty = this.safeNumber (market, 'minQty');
543
+ let maxQty = this.safeNumber (market, 'maxQty');
544
+ let minPrice = this.safeNumber (market, 'tickSize');
545
+ let maxPrice = undefined;
546
+ let symbol = base + '/' + quote;
547
+ if (swap) {
548
+ const lotSizeFilter = this.safeValue (market, 'lotSizeFilter');
549
+ minQty = this.safeNumber (lotSizeFilter, 'minQty');
550
+ maxQty = this.safeNumber (lotSizeFilter, 'maxQty');
551
+ const priceFilter = this.safeValue (market, 'priceFilter');
552
+ minPrice = this.safeNumber (priceFilter, 'minPrice');
553
+ maxPrice = this.safeNumber (priceFilter, 'maxPrice');
554
+ const underlying = this.safeString (market, 'underlying');
555
+ const parts = underlying.split ('/');
556
+ baseId = this.safeString (parts, 0);
557
+ quoteId = this.safeString (parts, 1);
558
+ base = this.safeCurrencyCode (baseId);
559
+ quote = this.safeCurrencyCode (quoteId);
560
+ symbol = base + '/' + quote + ':' + settle;
561
+ }
562
+ const fee = this.safeNumber (market, 'commissionReserveRate');
563
+ const marginTradable = this.safeValue (market, 'marginTradable', false);
564
+ result.push ({
565
+ 'id': id,
566
+ 'symbol': symbol,
567
+ 'base': base,
568
+ 'quote': quote,
569
+ 'settle': settle,
570
+ 'baseId': baseId,
571
+ 'quoteId': quoteId,
572
+ 'settleId': settleId,
573
+ 'type': swap ? 'swap' : 'spot',
574
+ 'spot': spot,
575
+ 'margin': spot ? marginTradable : undefined,
576
+ 'swap': swap,
577
+ 'future': false,
578
+ 'option': false,
579
+ 'active': (status === 'Normal'),
580
+ 'contract': swap,
581
+ 'linear': linear,
582
+ 'inverse': swap ? !linear : undefined,
583
+ 'taker': fee,
584
+ 'maker': fee,
585
+ 'contractSize': swap ? this.parseNumber ('1') : undefined,
586
+ 'expiry': undefined,
587
+ 'expiryDatetime': undefined,
588
+ 'strike': undefined,
589
+ 'optionType': undefined,
590
+ 'precision': {
591
+ 'amount': this.safeNumber (market, 'lotSize'),
592
+ 'price': this.safeNumber (market, 'tickSize'),
593
+ },
594
+ 'limits': {
595
+ 'leverage': {
596
+ 'min': undefined,
597
+ 'max': undefined,
598
+ },
599
+ 'amount': {
600
+ 'min': minQty,
601
+ 'max': maxQty,
602
+ },
603
+ 'price': {
604
+ 'min': minPrice,
605
+ 'max': maxPrice,
606
+ },
607
+ 'cost': {
608
+ 'min': this.safeNumber (market, 'minNotional'),
609
+ 'max': this.safeNumber (market, 'maxNotional'),
610
+ },
611
+ },
612
+ 'info': market,
613
+ });
614
+ }
615
+ return result;
616
+ }
617
+
618
+ async fetchAccounts (params = {}) {
619
+ let accountGroup = this.safeString (this.options, 'account-group');
620
+ let response = undefined;
621
+ if (accountGroup === undefined) {
622
+ response = await this.v1PrivateGetInfo (params);
623
+ //
624
+ // {
625
+ // "code":0,
626
+ // "data":{
627
+ // "email":"igor.kroitor@gmail.com",
628
+ // "accountGroup":8,
629
+ // "viewPermission":true,
630
+ // "tradePermission":true,
631
+ // "transferPermission":true,
632
+ // "cashAccount":["cshrHKLZCjlZ2ejqkmvIHHtPmLYqdnda"],
633
+ // "marginAccount":["martXoh1v1N3EMQC5FDtSj5VHso8aI2Z"],
634
+ // "futuresAccount":["futc9r7UmFJAyBY2rE3beA2JFxav2XFF"],
635
+ // "userUID":"U6491137460"
636
+ // }
637
+ // }
638
+ //
639
+ const data = this.safeValue (response, 'data', {});
640
+ accountGroup = this.safeString (data, 'accountGroup');
641
+ this.options['account-group'] = accountGroup;
642
+ }
643
+ return [
644
+ {
645
+ 'id': accountGroup,
646
+ 'type': undefined,
647
+ 'currency': undefined,
648
+ 'info': response,
649
+ },
650
+ ];
651
+ }
652
+
653
+ parseBalance (response) {
654
+ const result = {
655
+ 'info': response,
656
+ 'timestamp': undefined,
657
+ 'datetime': undefined,
658
+ };
659
+ const balances = this.safeValue (response, 'data', []);
660
+ for (let i = 0; i < balances.length; i++) {
661
+ const balance = balances[i];
662
+ const code = this.safeCurrencyCode (this.safeString (balance, 'asset'));
663
+ const account = this.account ();
664
+ account['free'] = this.safeString (balance, 'availableBalance');
665
+ account['total'] = this.safeString (balance, 'totalBalance');
666
+ result[code] = account;
667
+ }
668
+ return this.safeBalance (result);
669
+ }
670
+
671
+ parseSwapBalance (response) {
672
+ const timestamp = this.milliseconds ();
673
+ const result = {
674
+ 'info': response,
675
+ 'timestamp': timestamp,
676
+ 'datetime': this.iso8601 (timestamp),
677
+ };
678
+ const data = this.safeValue (response, 'data', {});
679
+ const collaterals = this.safeValue (data, 'collaterals', []);
680
+ for (let i = 0; i < collaterals.length; i++) {
681
+ const balance = collaterals[i];
682
+ const code = this.safeCurrencyCode (this.safeString (balance, 'asset'));
683
+ const account = this.account ();
684
+ account['total'] = this.safeString (balance, 'balance');
685
+ result[code] = account;
686
+ }
687
+ return this.safeBalance (result);
688
+ }
689
+
690
+ async fetchBalance (params = {}) {
691
+ await this.loadMarkets ();
692
+ await this.loadAccounts ();
693
+ const [ marketType, query ] = this.handleMarketTypeAndParams ('fetchBalance', undefined, params);
694
+ const options = this.safeValue (this.options, 'fetchBalance', {});
695
+ const accountsByType = this.safeValue (this.options, 'accountsByType', {});
696
+ const accountCategory = this.safeString (accountsByType, marketType, 'cash');
697
+ const account = this.safeValue (this.accounts, 0, {});
698
+ const accountGroup = this.safeString (account, 'id');
699
+ const request = {
700
+ 'account-group': accountGroup,
701
+ };
702
+ const defaultMethod = this.safeString (options, 'method', 'v1PrivateAccountCategoryGetBalance');
703
+ const method = this.getSupportedMapping (marketType, {
704
+ 'spot': defaultMethod,
705
+ 'margin': defaultMethod,
706
+ 'swap': 'v2PrivateAccountGroupGetFuturesPosition',
707
+ });
708
+ if (accountCategory === 'cash') {
709
+ request['account-category'] = accountCategory;
710
+ }
711
+ const response = await this[method] (this.extend (request, query));
712
+ //
713
+ // cash
714
+ //
715
+ // {
716
+ // 'code': 0,
717
+ // 'data': [
718
+ // {
719
+ // 'asset': 'BCHSV',
720
+ // 'totalBalance': '64.298000048',
721
+ // 'availableBalance': '64.298000048',
722
+ // },
723
+ // ]
724
+ // }
725
+ //
726
+ // margin
727
+ //
728
+ // {
729
+ // 'code': 0,
730
+ // 'data': [
731
+ // {
732
+ // 'asset': 'BCHSV',
733
+ // 'totalBalance': '64.298000048',
734
+ // 'availableBalance': '64.298000048',
735
+ // 'borrowed': '0',
736
+ // 'interest': '0',
737
+ // },
738
+ // ]
739
+ // }
740
+ //
741
+ // swap
742
+ //
743
+ // {
744
+ // "code": 0,
745
+ // "data": {
746
+ // "accountId": "fut2ODPhGiY71Pl4vtXnOZ00ssgD7QGn",
747
+ // "ac": "FUTURES",
748
+ // "collaterals": [
749
+ // {"asset":"ADA","balance":"0.355803","referencePrice":"1.05095","discountFactor":"0.9"},
750
+ // {"asset":"USDT","balance":"0.000014519","referencePrice":"1","discountFactor":"1"}
751
+ // ],
752
+ // }j
753
+ // }
754
+ //
755
+ if (marketType === 'swap') {
756
+ return this.parseSwapBalance (response);
757
+ } else {
758
+ return this.parseBalance (response);
759
+ }
760
+ }
761
+
762
+ async fetchOrderBook (symbol, limit = undefined, params = {}) {
763
+ await this.loadMarkets ();
764
+ const market = this.market (symbol);
765
+ const request = {
766
+ 'symbol': market['id'],
767
+ };
768
+ const response = await this.v1PublicGetDepth (this.extend (request, params));
769
+ //
770
+ // {
771
+ // "code":0,
772
+ // "data":{
773
+ // "m":"depth-snapshot",
774
+ // "symbol":"BTC-PERP",
775
+ // "data":{
776
+ // "ts":1590223998202,
777
+ // "seqnum":115444921,
778
+ // "asks":[
779
+ // ["9207.5","18.2383"],
780
+ // ["9207.75","18.8235"],
781
+ // ["9208","10.7873"],
782
+ // ],
783
+ // "bids":[
784
+ // ["9207.25","0.4009"],
785
+ // ["9207","0.003"],
786
+ // ["9206.5","0.003"],
787
+ // ]
788
+ // }
789
+ // }
790
+ // }
791
+ //
792
+ const data = this.safeValue (response, 'data', {});
793
+ const orderbook = this.safeValue (data, 'data', {});
794
+ const timestamp = this.safeInteger (orderbook, 'ts');
795
+ const result = this.parseOrderBook (orderbook, symbol, timestamp);
796
+ result['nonce'] = this.safeInteger (orderbook, 'seqnum');
797
+ return result;
798
+ }
799
+
800
+ parseTicker (ticker, market = undefined) {
801
+ //
802
+ // {
803
+ // "symbol":"QTUM/BTC",
804
+ // "open":"0.00016537",
805
+ // "close":"0.00019077",
806
+ // "high":"0.000192",
807
+ // "low":"0.00016537",
808
+ // "volume":"846.6",
809
+ // "ask":["0.00018698","26.2"],
810
+ // "bid":["0.00018408","503.7"],
811
+ // "type":"spot"
812
+ // }
813
+ //
814
+ const timestamp = undefined;
815
+ const marketId = this.safeString (ticker, 'symbol');
816
+ const type = this.safeString (ticker, 'type');
817
+ const delimiter = (type === 'spot') ? '/' : undefined;
818
+ const symbol = this.safeSymbol (marketId, market, delimiter);
819
+ const close = this.safeString (ticker, 'close');
820
+ const bid = this.safeValue (ticker, 'bid', []);
821
+ const ask = this.safeValue (ticker, 'ask', []);
822
+ const open = this.safeString (ticker, 'open');
823
+ return this.safeTicker ({
824
+ 'symbol': symbol,
825
+ 'timestamp': timestamp,
826
+ 'datetime': undefined,
827
+ 'high': this.safeString (ticker, 'high'),
828
+ 'low': this.safeString (ticker, 'low'),
829
+ 'bid': this.safeString (bid, 0),
830
+ 'bidVolume': this.safeString (bid, 1),
831
+ 'ask': this.safeString (ask, 0),
832
+ 'askVolume': this.safeString (ask, 1),
833
+ 'vwap': undefined,
834
+ 'open': open,
835
+ 'close': close,
836
+ 'last': close,
837
+ 'previousClose': undefined, // previous day close
838
+ 'change': undefined,
839
+ 'percentage': undefined,
840
+ 'average': undefined,
841
+ 'baseVolume': this.safeString (ticker, 'volume'),
842
+ 'quoteVolume': undefined,
843
+ 'info': ticker,
844
+ }, market, false);
845
+ }
846
+
847
+ async fetchTicker (symbol, params = {}) {
848
+ await this.loadMarkets ();
849
+ const market = this.market (symbol);
850
+ const request = {
851
+ 'symbol': market['id'],
852
+ };
853
+ const response = await this.v1PublicGetTicker (this.extend (request, params));
854
+ //
855
+ // {
856
+ // "code":0,
857
+ // "data":{
858
+ // "symbol":"BTC-PERP", // or "BTC/USDT"
859
+ // "open":"9073",
860
+ // "close":"9185.75",
861
+ // "high":"9185.75",
862
+ // "low":"9185.75",
863
+ // "volume":"576.8334",
864
+ // "ask":["9185.75","15.5863"],
865
+ // "bid":["9185.5","0.003"],
866
+ // "type":"derivatives", // or "spot"
867
+ // }
868
+ // }
869
+ //
870
+ const data = this.safeValue (response, 'data', {});
871
+ return this.parseTicker (data, market);
872
+ }
873
+
874
+ async fetchTickers (symbols = undefined, params = {}) {
875
+ await this.loadMarkets ();
876
+ const request = {};
877
+ if (symbols !== undefined) {
878
+ const marketIds = this.marketIds (symbols);
879
+ request['symbol'] = marketIds.join (',');
880
+ }
881
+ const response = await this.v1PublicGetTicker (this.extend (request, params));
882
+ //
883
+ // {
884
+ // "code":0,
885
+ // "data":[
886
+ // {
887
+ // "symbol":"QTUM/BTC",
888
+ // "open":"0.00016537",
889
+ // "close":"0.00019077",
890
+ // "high":"0.000192",
891
+ // "low":"0.00016537",
892
+ // "volume":"846.6",
893
+ // "ask":["0.00018698","26.2"],
894
+ // "bid":["0.00018408","503.7"],
895
+ // "type":"spot"
896
+ // }
897
+ // ]
898
+ // }
899
+ //
900
+ const data = this.safeValue (response, 'data', []);
901
+ return this.parseTickers (data, symbols);
902
+ }
903
+
904
+ parseOHLCV (ohlcv, market = undefined) {
905
+ //
906
+ // {
907
+ // "m":"bar",
908
+ // "s":"BTC/USDT",
909
+ // "data":{
910
+ // "i":"1",
911
+ // "ts":1590228000000,
912
+ // "o":"9139.59",
913
+ // "c":"9131.94",
914
+ // "h":"9139.99",
915
+ // "l":"9121.71",
916
+ // "v":"25.20648"
917
+ // }
918
+ // }
919
+ //
920
+ const data = this.safeValue (ohlcv, 'data', {});
921
+ return [
922
+ this.safeInteger (data, 'ts'),
923
+ this.safeNumber (data, 'o'),
924
+ this.safeNumber (data, 'h'),
925
+ this.safeNumber (data, 'l'),
926
+ this.safeNumber (data, 'c'),
927
+ this.safeNumber (data, 'v'),
928
+ ];
929
+ }
930
+
931
+ async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
932
+ await this.loadMarkets ();
933
+ const market = this.market (symbol);
934
+ const request = {
935
+ 'symbol': market['id'],
936
+ 'interval': this.timeframes[timeframe],
937
+ };
938
+ // if since and limit are not specified
939
+ // the exchange will return just 1 last candle by default
940
+ const duration = this.parseTimeframe (timeframe);
941
+ const options = this.safeValue (this.options, 'fetchOHLCV', {});
942
+ const defaultLimit = this.safeInteger (options, 'limit', 500);
943
+ if (since !== undefined) {
944
+ request['from'] = since;
945
+ if (limit === undefined) {
946
+ limit = defaultLimit;
947
+ } else {
948
+ limit = Math.min (limit, defaultLimit);
949
+ }
950
+ request['to'] = this.sum (since, limit * duration * 1000, 1);
951
+ } else if (limit !== undefined) {
952
+ request['n'] = limit; // max 500
953
+ }
954
+ const response = await this.v1PublicGetBarhist (this.extend (request, params));
955
+ //
956
+ // {
957
+ // "code":0,
958
+ // "data":[
959
+ // {
960
+ // "m":"bar",
961
+ // "s":"BTC/USDT",
962
+ // "data":{
963
+ // "i":"1",
964
+ // "ts":1590228000000,
965
+ // "o":"9139.59",
966
+ // "c":"9131.94",
967
+ // "h":"9139.99",
968
+ // "l":"9121.71",
969
+ // "v":"25.20648"
970
+ // }
971
+ // }
972
+ // ]
973
+ // }
974
+ //
975
+ const data = this.safeValue (response, 'data', []);
976
+ return this.parseOHLCVs (data, market, timeframe, since, limit);
977
+ }
978
+
979
+ parseTrade (trade, market = undefined) {
980
+ //
981
+ // public fetchTrades
982
+ //
983
+ // {
984
+ // "p":"9128.5", // price
985
+ // "q":"0.0030", // quantity
986
+ // "ts":1590229002385, // timestamp
987
+ // "bm":false, // if true, the buyer is the market maker, we only use this field to "define the side" of a public trade
988
+ // "seqnum":180143985289898554
989
+ // }
990
+ //
991
+ const timestamp = this.safeInteger (trade, 'ts');
992
+ const priceString = this.safeString2 (trade, 'price', 'p');
993
+ const amountString = this.safeString (trade, 'q');
994
+ const buyerIsMaker = this.safeValue (trade, 'bm', false);
995
+ const makerOrTaker = buyerIsMaker ? 'maker' : 'taker';
996
+ const side = buyerIsMaker ? 'buy' : 'sell';
997
+ market = this.safeMarket (undefined, market);
998
+ return this.safeTrade ({
999
+ 'info': trade,
1000
+ 'timestamp': timestamp,
1001
+ 'datetime': this.iso8601 (timestamp),
1002
+ 'symbol': market['symbol'],
1003
+ 'id': undefined,
1004
+ 'order': undefined,
1005
+ 'type': undefined,
1006
+ 'takerOrMaker': makerOrTaker,
1007
+ 'side': side,
1008
+ 'price': priceString,
1009
+ 'amount': amountString,
1010
+ 'cost': undefined,
1011
+ 'fee': undefined,
1012
+ }, market);
1013
+ }
1014
+
1015
+ async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
1016
+ await this.loadMarkets ();
1017
+ const market = this.market (symbol);
1018
+ const request = {
1019
+ 'symbol': market['id'],
1020
+ };
1021
+ if (limit !== undefined) {
1022
+ request['n'] = limit; // max 100
1023
+ }
1024
+ const response = await this.v1PublicGetTrades (this.extend (request, params));
1025
+ //
1026
+ // {
1027
+ // "code":0,
1028
+ // "data":{
1029
+ // "m":"trades",
1030
+ // "symbol":"BTC-PERP",
1031
+ // "data":[
1032
+ // {"p":"9128.5","q":"0.0030","ts":1590229002385,"bm":false,"seqnum":180143985289898554},
1033
+ // {"p":"9129","q":"0.0030","ts":1590229002642,"bm":false,"seqnum":180143985289898587},
1034
+ // {"p":"9129.5","q":"0.0030","ts":1590229021306,"bm":false,"seqnum":180143985289899043}
1035
+ // ]
1036
+ // }
1037
+ // }
1038
+ //
1039
+ const records = this.safeValue (response, 'data', []);
1040
+ const trades = this.safeValue (records, 'data', []);
1041
+ return this.parseTrades (trades, market, since, limit);
1042
+ }
1043
+
1044
+ parseOrderStatus (status) {
1045
+ const statuses = {
1046
+ 'PendingNew': 'open',
1047
+ 'New': 'open',
1048
+ 'PartiallyFilled': 'open',
1049
+ 'Filled': 'closed',
1050
+ 'Canceled': 'canceled',
1051
+ 'Rejected': 'rejected',
1052
+ };
1053
+ return this.safeString (statuses, status, status);
1054
+ }
1055
+
1056
+ parseOrder (order, market = undefined) {
1057
+ //
1058
+ // createOrder
1059
+ //
1060
+ // {
1061
+ // "id": "16e607e2b83a8bXHbAwwoqDo55c166fa",
1062
+ // "orderId": "16e85b4d9b9a8bXHbAwwoqDoc3d66830",
1063
+ // "orderType": "Market",
1064
+ // "symbol": "BTC/USDT",
1065
+ // "timestamp": 1573576916201
1066
+ // }
1067
+ //
1068
+ // {
1069
+ // "ac": "FUTURES",
1070
+ // "accountId": "fut2ODPhGiY71Pl4vtXnOZ00ssgD7QGn",
1071
+ // "time": 1640819389454,
1072
+ // "orderId": "a17e0874ecbdU0711043490bbtcpDU5X",
1073
+ // "seqNum": -1,
1074
+ // "orderType": "Limit",
1075
+ // "execInst": "NULL_VAL",
1076
+ // "side": "Buy",
1077
+ // "symbol": "BTC-PERP",
1078
+ // "price": "30000",
1079
+ // "orderQty": "0.002",
1080
+ // "stopPrice": "0",
1081
+ // "stopBy": "ref-px",
1082
+ // "status": "Ack",
1083
+ // "lastExecTime": 1640819389454,
1084
+ // "lastQty": "0",
1085
+ // "lastPx": "0",
1086
+ // "avgFilledPx": "0",
1087
+ // "cumFilledQty": "0",
1088
+ // "fee": "0",
1089
+ // "cumFee": "0",
1090
+ // "feeAsset": "",
1091
+ // "errorCode": "",
1092
+ // "posStopLossPrice": "0",
1093
+ // "posStopLossTrigger": "market",
1094
+ // "posTakeProfitPrice": "0",
1095
+ // "posTakeProfitTrigger": "market",
1096
+ // "liquidityInd": "n"
1097
+ // }
1098
+ //
1099
+ // fetchOrder, fetchOpenOrders, fetchClosedOrders
1100
+ //
1101
+ // {
1102
+ // "symbol": "BTC/USDT",
1103
+ // "price": "8131.22",
1104
+ // "orderQty": "0.00082",
1105
+ // "orderType": "Market",
1106
+ // "avgPx": "7392.02",
1107
+ // "cumFee": "0.005152238",
1108
+ // "cumFilledQty": "0.00082",
1109
+ // "errorCode": "",
1110
+ // "feeAsset": "USDT",
1111
+ // "lastExecTime": 1575953151764,
1112
+ // "orderId": "a16eee20b6750866943712zWEDdAjt3",
1113
+ // "seqNum": 2623469,
1114
+ // "side": "Buy",
1115
+ // "status": "Filled",
1116
+ // "stopPrice": "",
1117
+ // "execInst": "NULL_VAL"
1118
+ // }
1119
+ //
1120
+ // {
1121
+ // "ac": "FUTURES",
1122
+ // "accountId": "testabcdefg",
1123
+ // "avgPx": "0",
1124
+ // "cumFee": "0",
1125
+ // "cumQty": "0",
1126
+ // "errorCode": "NULL_VAL",
1127
+ // "execInst": "NULL_VAL",
1128
+ // "feeAsset": "USDT",
1129
+ // "lastExecTime": 1584072844085,
1130
+ // "orderId": "r170d21956dd5450276356bbtcpKa74",
1131
+ // "orderQty": "1.1499",
1132
+ // "orderType": "Limit",
1133
+ // "price": "4000",
1134
+ // "sendingTime": 1584072841033,
1135
+ // "seqNum": 24105338,
1136
+ // "side": "Buy",
1137
+ // "status": "Canceled",
1138
+ // "stopPrice": "",
1139
+ // "symbol": "BTC-PERP"
1140
+ // },
1141
+ //
1142
+ const status = this.parseOrderStatus (this.safeString (order, 'status'));
1143
+ const marketId = this.safeString (order, 'symbol');
1144
+ const symbol = this.safeSymbol (marketId, market, '/');
1145
+ const timestamp = this.safeInteger2 (order, 'timestamp', 'sendingTime');
1146
+ const lastTradeTimestamp = this.safeInteger (order, 'lastExecTime');
1147
+ const price = this.safeString (order, 'price');
1148
+ const amount = this.safeString (order, 'orderQty');
1149
+ const average = this.safeString (order, 'avgPx');
1150
+ const filled = this.safeString2 (order, 'cumFilledQty', 'cumQty');
1151
+ const id = this.safeString (order, 'orderId');
1152
+ let clientOrderId = this.safeString (order, 'id');
1153
+ if (clientOrderId !== undefined) {
1154
+ if (clientOrderId.length < 1) {
1155
+ clientOrderId = undefined;
1156
+ }
1157
+ }
1158
+ const type = this.safeStringLower (order, 'orderType');
1159
+ const side = this.safeStringLower (order, 'side');
1160
+ const feeCost = this.safeNumber (order, 'cumFee');
1161
+ let fee = undefined;
1162
+ if (feeCost !== undefined) {
1163
+ const feeCurrencyId = this.safeString (order, 'feeAsset');
1164
+ const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId);
1165
+ fee = {
1166
+ 'cost': feeCost,
1167
+ 'currency': feeCurrencyCode,
1168
+ };
1169
+ }
1170
+ const stopPrice = this.safeNumber (order, 'stopPrice');
1171
+ return this.safeOrder ({
1172
+ 'info': order,
1173
+ 'id': id,
1174
+ 'clientOrderId': clientOrderId,
1175
+ 'timestamp': timestamp,
1176
+ 'datetime': this.iso8601 (timestamp),
1177
+ 'lastTradeTimestamp': lastTradeTimestamp,
1178
+ 'symbol': symbol,
1179
+ 'type': type,
1180
+ 'timeInForce': undefined,
1181
+ 'postOnly': undefined,
1182
+ 'side': side,
1183
+ 'price': price,
1184
+ 'stopPrice': stopPrice,
1185
+ 'amount': amount,
1186
+ 'cost': undefined,
1187
+ 'average': average,
1188
+ 'filled': filled,
1189
+ 'remaining': undefined,
1190
+ 'status': status,
1191
+ 'fee': fee,
1192
+ 'trades': undefined,
1193
+ }, market);
1194
+ }
1195
+
1196
+ async fetchTradingFees (params = {}) {
1197
+ await this.loadMarkets ();
1198
+ await this.loadAccounts ();
1199
+ const account = this.safeValue (this.accounts, 0, {});
1200
+ const accountGroup = this.safeString (account, 'id');
1201
+ const request = {
1202
+ 'account-group': accountGroup,
1203
+ };
1204
+ const response = await this.v1PrivateAccountGroupGetSpotFee (this.extend (request, params));
1205
+ //
1206
+ // {
1207
+ // code: '0',
1208
+ // data: {
1209
+ // domain: 'spot',
1210
+ // userUID: 'U1479576458',
1211
+ // vipLevel: '0',
1212
+ // fees: [
1213
+ // { symbol: 'HT/USDT', fee: { taker: '0.001', maker: '0.001' } },
1214
+ // { symbol: 'LAMB/BTC', fee: { taker: '0.002', maker: '0.002' } },
1215
+ // { symbol: 'STOS/USDT', fee: { taker: '0.002', maker: '0.002' } },
1216
+ // ...
1217
+ // ]
1218
+ // }
1219
+ // }
1220
+ //
1221
+ const data = this.safeValue (response, 'data', {});
1222
+ const fees = this.safeValue (data, 'fees', []);
1223
+ const result = {};
1224
+ for (let i = 0; i < fees.length; i++) {
1225
+ const fee = fees[i];
1226
+ const marketId = this.safeString (fee, 'symbol');
1227
+ const symbol = this.safeSymbol (marketId, undefined, '/');
1228
+ const takerMaker = this.safeValue (fee, 'fee', {});
1229
+ result[symbol] = {
1230
+ 'info': fee,
1231
+ 'symbol': symbol,
1232
+ 'maker': this.safeNumber (takerMaker, 'maker'),
1233
+ 'taker': this.safeNumber (takerMaker, 'taker'),
1234
+ };
1235
+ }
1236
+ return result;
1237
+ }
1238
+
1239
+ async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
1240
+ await this.loadMarkets ();
1241
+ await this.loadAccounts ();
1242
+ const market = this.market (symbol);
1243
+ let marketType = undefined;
1244
+ [ marketType, params ] = this.handleMarketTypeAndParams ('createOrder', market, params);
1245
+ const options = this.safeValue (this.options, 'createOrder', {});
1246
+ const accountsByType = this.safeValue (this.options, 'accountsByType', {});
1247
+ const accountCategory = this.safeString (accountsByType, marketType, 'cash');
1248
+ const account = this.safeValue (this.accounts, 0, {});
1249
+ const accountGroup = this.safeValue (account, 'id');
1250
+ const clientOrderId = this.safeString2 (params, 'clientOrderId', 'id');
1251
+ const reduceOnly = this.safeValue (params, 'execInst');
1252
+ if (reduceOnly !== undefined) {
1253
+ if ((marketType !== 'swap')) {
1254
+ throw new InvalidOrder (this.id + ' createOrder() does not support reduceOnly for ' + marketType + ' orders, reduceOnly orders are supported for perpetuals only');
1255
+ }
1256
+ }
1257
+ const request = {
1258
+ 'account-group': accountGroup,
1259
+ 'account-category': accountCategory,
1260
+ 'symbol': market['id'],
1261
+ 'time': this.milliseconds (),
1262
+ 'orderQty': this.amountToPrecision (symbol, amount),
1263
+ 'orderType': type, // "limit", "market", "stop_market", "stop_limit"
1264
+ 'side': side, // "buy" or "sell"
1265
+ // 'orderPrice': this.priceToPrecision (symbol, price),
1266
+ // 'stopPrice': this.priceToPrecision (symbol, stopPrice), // required for stop orders
1267
+ // 'postOnly': 'false', // 'false', 'true'
1268
+ // 'timeInForce': 'GTC', // GTC, IOC, FOK
1269
+ // 'respInst': 'ACK', // ACK, 'ACCEPT, DONE
1270
+ // 'posStopLossPrice': position stop loss price ( v2 swap orders only)
1271
+ // 'posTakeProfitPrice': position take profit price (v2 swap orders only)
1272
+ };
1273
+ if (clientOrderId !== undefined) {
1274
+ request['id'] = clientOrderId;
1275
+ params = this.omit (params, [ 'clientOrderId', 'id' ]);
1276
+ }
1277
+ if ((type === 'limit') || (type === 'stop_limit')) {
1278
+ request['orderPrice'] = this.priceToPrecision (symbol, price);
1279
+ }
1280
+ if ((type === 'stop_limit') || (type === 'stop_market')) {
1281
+ const stopPrice = this.safeNumber (params, 'stopPrice');
1282
+ if (stopPrice === undefined) {
1283
+ throw new InvalidOrder (this.id + ' createOrder() requires a stopPrice parameter for ' + type + ' orders');
1284
+ } else {
1285
+ request['stopPrice'] = this.priceToPrecision (symbol, stopPrice);
1286
+ params = this.omit (params, 'stopPrice');
1287
+ }
1288
+ }
1289
+ const timeInForce = this.safeString (params, 'timeInForce');
1290
+ const postOnly = this.safeValue (params, 'postOnly', false);
1291
+ if ((timeInForce === 'PO') || (postOnly)) {
1292
+ request['postOnly'] = true;
1293
+ params = this.omit (params, [ 'postOnly', 'timeInForce' ]);
1294
+ }
1295
+ const defaultMethod = this.safeString (options, 'method', 'v1PrivateAccountCategoryPostOrder');
1296
+ const method = this.getSupportedMapping (marketType, {
1297
+ 'spot': defaultMethod,
1298
+ 'margin': defaultMethod,
1299
+ 'swap': 'v2PrivateAccountGroupPostFuturesOrder',
1300
+ });
1301
+ if (method === 'v1PrivateAccountCategoryPostOrder') {
1302
+ if (accountCategory !== undefined) {
1303
+ request['category'] = accountCategory;
1304
+ }
1305
+ } else {
1306
+ request['account-category'] = accountCategory;
1307
+ }
1308
+ const response = await this[method] (this.extend (request, params));
1309
+ //
1310
+ // AccountCategoryPostOrder
1311
+ //
1312
+ // {
1313
+ // "code": 0,
1314
+ // "data": {
1315
+ // "ac": "MARGIN",
1316
+ // "accountId": "cshQtyfq8XLAA9kcf19h8bXHbAwwoqDo",
1317
+ // "action": "place-order",
1318
+ // "info": {
1319
+ // "id": "16e607e2b83a8bXHbAwwoqDo55c166fa",
1320
+ // "orderId": "16e85b4d9b9a8bXHbAwwoqDoc3d66830",
1321
+ // "orderType": "Market",
1322
+ // "symbol": "BTC/USDT",
1323
+ // "timestamp": 1573576916201
1324
+ // },
1325
+ // "status": "Ack"
1326
+ // }
1327
+ // }
1328
+ //
1329
+ // AccountGroupPostFuturesOrder
1330
+ //
1331
+ // {
1332
+ // "code": 0,
1333
+ // "data": {
1334
+ // "meta": {
1335
+ // "id": "",
1336
+ // "action": "place-order",
1337
+ // "respInst": "ACK"
1338
+ // },
1339
+ // "order": {
1340
+ // "ac": "FUTURES",
1341
+ // "accountId": "fut2ODPhGiY71Pl4vtXnOZ00ssgD7QGn",
1342
+ // "time": 1640819389454,
1343
+ // "orderId": "a17e0874ecbdU0711043490bbtcpDU5X",
1344
+ // "seqNum": -1,
1345
+ // "orderType": "Limit",
1346
+ // "execInst": "NULL_VAL",
1347
+ // "side": "Buy",
1348
+ // "symbol": "BTC-PERP",
1349
+ // "price": "30000",
1350
+ // "orderQty": "0.002",
1351
+ // "stopPrice": "0",
1352
+ // "stopBy": "ref-px",
1353
+ // "status": "Ack",
1354
+ // "lastExecTime": 1640819389454,
1355
+ // "lastQty": "0",
1356
+ // "lastPx": "0",
1357
+ // "avgFilledPx": "0",
1358
+ // "cumFilledQty": "0",
1359
+ // "fee": "0",
1360
+ // "cumFee": "0",
1361
+ // "feeAsset": "",
1362
+ // "errorCode": "",
1363
+ // "posStopLossPrice": "0",
1364
+ // "posStopLossTrigger": "market",
1365
+ // "posTakeProfitPrice": "0",
1366
+ // "posTakeProfitTrigger": "market",
1367
+ // "liquidityInd": "n"
1368
+ // }
1369
+ // }
1370
+ // }
1371
+ //
1372
+ const data = this.safeValue (response, 'data', {});
1373
+ const order = this.safeValue2 (data, 'order', 'info', {});
1374
+ return this.parseOrder (order, market);
1375
+ }
1376
+
1377
+ async createReduceOnlyOrder (symbol, type, side, amount, price = undefined, params = {}) {
1378
+ const request = {
1379
+ 'execInst': 'reduceOnly',
1380
+ };
1381
+ return await this.createOrder (symbol, type, side, amount, price, this.extend (request, params));
1382
+ }
1383
+
1384
+ async fetchOrder (id, symbol = undefined, params = {}) {
1385
+ await this.loadMarkets ();
1386
+ await this.loadAccounts ();
1387
+ let market = undefined;
1388
+ if (symbol !== undefined) {
1389
+ market = this.market (symbol);
1390
+ }
1391
+ const [ type, query ] = this.handleMarketTypeAndParams ('fetchOrder', market, params);
1392
+ const options = this.safeValue (this.options, 'fetchOrder', {});
1393
+ const accountsByType = this.safeValue (this.options, 'accountsByType', {});
1394
+ const accountCategory = this.safeString (accountsByType, type, 'cash');
1395
+ const account = this.safeValue (this.accounts, 0, {});
1396
+ const accountGroup = this.safeValue (account, 'id');
1397
+ const request = {
1398
+ 'account-group': accountGroup,
1399
+ 'account-category': accountCategory,
1400
+ 'orderId': id,
1401
+ };
1402
+ const defaultMethod = this.safeString (options, 'method', 'v1PrivateAccountCategoryGetOrderStatus');
1403
+ const method = this.getSupportedMapping (type, {
1404
+ 'spot': defaultMethod,
1405
+ 'margin': defaultMethod,
1406
+ 'swap': 'v2PrivateAccountGroupGetFuturesOrderStatus',
1407
+ });
1408
+ if (method === 'v1PrivateAccountCategoryGetOrderStatus') {
1409
+ if (accountCategory !== undefined) {
1410
+ request['category'] = accountCategory;
1411
+ }
1412
+ } else {
1413
+ request['account-category'] = accountCategory;
1414
+ }
1415
+ const response = await this[method] (this.extend (request, query));
1416
+ //
1417
+ // AccountCategoryGetOrderStatus
1418
+ //
1419
+ // {
1420
+ // "code": 0,
1421
+ // "accountCategory": "CASH",
1422
+ // "accountId": "cshQtyfq8XLAA9kcf19h8bXHbAwwoqDo",
1423
+ // "data": [
1424
+ // {
1425
+ // "symbol": "BTC/USDT",
1426
+ // "price": "8131.22",
1427
+ // "orderQty": "0.00082",
1428
+ // "orderType": "Market",
1429
+ // "avgPx": "7392.02",
1430
+ // "cumFee": "0.005152238",
1431
+ // "cumFilledQty": "0.00082",
1432
+ // "errorCode": "",
1433
+ // "feeAsset": "USDT",
1434
+ // "lastExecTime": 1575953151764,
1435
+ // "orderId": "a16eee20b6750866943712zWEDdAjt3",
1436
+ // "seqNum": 2623469,
1437
+ // "side": "Buy",
1438
+ // "status": "Filled",
1439
+ // "stopPrice": "",
1440
+ // "execInst": "NULL_VAL"
1441
+ // }
1442
+ // ]
1443
+ // }
1444
+ //
1445
+ // AccountGroupGetFuturesOrderStatus
1446
+ //
1447
+ // {
1448
+ // "code": 0,
1449
+ // "accountId": "fut2ODPhGiY71Pl4vtXnOZ00ssgD7QGn",
1450
+ // "ac": "FUTURES",
1451
+ // "data": {
1452
+ // "ac": "FUTURES",
1453
+ // "accountId": "fut2ODPhGiY71Pl4vtXnOZ00ssgD7QGn",
1454
+ // "time": 1640247020217,
1455
+ // "orderId": "r17de65747aeU0711043490bbtcp0cmt",
1456
+ // "seqNum": 28796162908,
1457
+ // "orderType": "Limit",
1458
+ // "execInst": "NULL_VAL",
1459
+ // "side": "Buy",
1460
+ // "symbol": "BTC-PERP",
1461
+ // "price": "30000",
1462
+ // "orderQty": "0.0021",
1463
+ // "stopPrice": "0",
1464
+ // "stopBy": "market",
1465
+ // "status": "New",
1466
+ // "lastExecTime": 1640247020232,
1467
+ // "lastQty": "0",
1468
+ // "lastPx": "0",
1469
+ // "avgFilledPx": "0",
1470
+ // "cumFilledQty": "0",
1471
+ // "fee": "0",
1472
+ // "cumFee": "0",
1473
+ // "feeAsset": "USDT",
1474
+ // "errorCode": "",
1475
+ // "posStopLossPrice": "0",
1476
+ // "posStopLossTrigger": "market",
1477
+ // "posTakeProfitPrice": "0",
1478
+ // "posTakeProfitTrigger": "market",
1479
+ // "liquidityInd": "n"
1480
+ // }
1481
+ // }
1482
+ //
1483
+ const data = this.safeValue (response, 'data', {});
1484
+ return this.parseOrder (data, market);
1485
+ }
1486
+
1487
+ async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
1488
+ await this.loadMarkets ();
1489
+ await this.loadAccounts ();
1490
+ let market = undefined;
1491
+ if (symbol !== undefined) {
1492
+ market = this.market (symbol);
1493
+ symbol = market['symbol'];
1494
+ }
1495
+ const account = this.safeValue (this.accounts, 0, {});
1496
+ const accountGroup = this.safeValue (account, 'id');
1497
+ const [ type, query ] = this.handleMarketTypeAndParams ('fetchOpenOrders', market, params);
1498
+ const accountsByType = this.safeValue (this.options, 'accountsByType', {});
1499
+ const accountCategory = this.safeString (accountsByType, type, 'cash');
1500
+ const request = {
1501
+ 'account-group': accountGroup,
1502
+ 'account-category': accountCategory,
1503
+ };
1504
+ const options = this.safeValue (this.options, 'fetchOpenOrders', {});
1505
+ const defaultMethod = this.safeString (options, 'method', 'v1PrivateAccountCategoryGetOrderOpen');
1506
+ const method = this.getSupportedMapping (type, {
1507
+ 'spot': defaultMethod,
1508
+ 'margin': defaultMethod,
1509
+ 'swap': 'v2PrivateAccountGroupGetFuturesOrderOpen',
1510
+ });
1511
+ if (method === 'v1PrivateAccountCategoryGetOrderOpen') {
1512
+ if (accountCategory !== undefined) {
1513
+ request['category'] = accountCategory;
1514
+ }
1515
+ } else {
1516
+ request['account-category'] = accountCategory;
1517
+ }
1518
+ const response = await this[method] (this.extend (request, query));
1519
+ //
1520
+ // AccountCategoryGetOrderOpen
1521
+ //
1522
+ // {
1523
+ // "ac": "CASH",
1524
+ // "accountId": "cshQtyfq8XLAA9kcf19h8bXHbAwwoqDo",
1525
+ // "code": 0,
1526
+ // "data": [
1527
+ // {
1528
+ // "avgPx": "0", // Average filled price of the order
1529
+ // "cumFee": "0", // cumulative fee paid for this order
1530
+ // "cumFilledQty": "0", // cumulative filled quantity
1531
+ // "errorCode": "", // error code; could be empty
1532
+ // "feeAsset": "USDT", // fee asset
1533
+ // "lastExecTime": 1576019723550, // The last execution time of the order
1534
+ // "orderId": "s16ef21882ea0866943712034f36d83", // server provided orderId
1535
+ // "orderQty": "0.0083", // order quantity
1536
+ // "orderType": "Limit", // order type
1537
+ // "price": "7105", // order price
1538
+ // "seqNum": 8193258, // sequence number
1539
+ // "side": "Buy", // order side
1540
+ // "status": "New", // order status on matching engine
1541
+ // "stopPrice": "", // only available for stop market and stop limit orders; otherwise empty
1542
+ // "symbol": "BTC/USDT",
1543
+ // "execInst": "NULL_VAL" // execution instruction
1544
+ // },
1545
+ // ]
1546
+ // }
1547
+ //
1548
+ // AccountGroupGetFuturesOrderOpen
1549
+ //
1550
+ // {
1551
+ // "code": 0,
1552
+ // "data": [
1553
+ // {
1554
+ // "ac": "FUTURES",
1555
+ // "accountId": "fut2ODPhGiY71Pl4vtXnOZ00ssgD7QGn",
1556
+ // "time": 1640247020217,
1557
+ // "orderId": "r17de65747aeU0711043490bbtcp0cmt",
1558
+ // "seqNum": 28796162908,
1559
+ // "orderType": "Limit",
1560
+ // "execInst": "NULL_VAL",
1561
+ // "side": "Buy",
1562
+ // "symbol": "BTC-PERP",
1563
+ // "price": "30000",
1564
+ // "orderQty": "0.0021",
1565
+ // "stopPrice": "0",
1566
+ // "stopBy": "market",
1567
+ // "status": "New",
1568
+ // "lastExecTime": 1640247020232,
1569
+ // "lastQty": "0",
1570
+ // "lastPx": "0",
1571
+ // "avgFilledPx": "0",
1572
+ // "cumFilledQty": "0",
1573
+ // "fee": "0",
1574
+ // "cumFee": "0",
1575
+ // "feeAsset": "USDT",
1576
+ // "errorCode": "",
1577
+ // "posStopLossPrice": "0",
1578
+ // "posStopLossTrigger": "market",
1579
+ // "posTakeProfitPrice": "0",
1580
+ // "posTakeProfitTrigger": "market",
1581
+ // "liquidityInd": "n"
1582
+ // }
1583
+ // ]
1584
+ // }
1585
+ //
1586
+ const data = this.safeValue (response, 'data', []);
1587
+ if (accountCategory === 'futures') {
1588
+ return this.parseOrders (data, market, since, limit);
1589
+ }
1590
+ // a workaround for https://github.com/ccxt/ccxt/issues/7187
1591
+ const orders = [];
1592
+ for (let i = 0; i < data.length; i++) {
1593
+ const order = this.parseOrder (data[i], market);
1594
+ orders.push (order);
1595
+ }
1596
+ return this.filterBySymbolSinceLimit (orders, symbol, since, limit);
1597
+ }
1598
+
1599
+ async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
1600
+ await this.loadMarkets ();
1601
+ await this.loadAccounts ();
1602
+ const account = this.safeValue (this.accounts, 0, {});
1603
+ const accountGroup = this.safeValue (account, 'id');
1604
+ const request = {
1605
+ 'account-group': accountGroup,
1606
+ // 'category': accountCategory,
1607
+ // 'symbol': market['id'],
1608
+ // 'orderType': 'market', // optional, string
1609
+ // 'side': 'buy', // or 'sell', optional, case insensitive.
1610
+ // 'status': 'Filled', // "Filled", "Canceled", or "Rejected"
1611
+ // 'startTime': exchange.milliseconds (),
1612
+ // 'endTime': exchange.milliseconds (),
1613
+ // 'page': 1,
1614
+ // 'pageSize': 100,
1615
+ };
1616
+ let market = undefined;
1617
+ if (symbol !== undefined) {
1618
+ market = this.market (symbol);
1619
+ request['symbol'] = market['id'];
1620
+ }
1621
+ const [ type, query ] = this.handleMarketTypeAndParams ('fetchCLosedOrders', market, params);
1622
+ const options = this.safeValue (this.options, 'fetchClosedOrders', {});
1623
+ const defaultMethod = this.safeString (options, 'method', 'v1PrivateAccountGroupGetOrderHist');
1624
+ const method = this.getSupportedMapping (type, {
1625
+ 'spot': defaultMethod,
1626
+ 'margin': defaultMethod,
1627
+ 'swap': 'v2PrivateAccountGroupGetFuturesOrderHistCurrent',
1628
+ });
1629
+ const accountsByType = this.safeValue (this.options, 'accountsByType', {});
1630
+ const accountCategory = this.safeString (accountsByType, type, 'cash');
1631
+ if (method === 'v1PrivateAccountGroupGetOrderHist') {
1632
+ if (accountCategory !== undefined) {
1633
+ request['category'] = accountCategory;
1634
+ }
1635
+ } else {
1636
+ request['account-category'] = accountCategory;
1637
+ }
1638
+ if (since !== undefined) {
1639
+ request['startTime'] = since;
1640
+ }
1641
+ if (limit !== undefined) {
1642
+ request['pageSize'] = limit;
1643
+ }
1644
+ const response = await this[method] (this.extend (request, query));
1645
+ //
1646
+ // accountCategoryGetOrderHistCurrent
1647
+ //
1648
+ // {
1649
+ // "code":0,
1650
+ // "accountId":"cshrHKLZCjlZ2ejqkmvIHHtPmLYqdnda",
1651
+ // "ac":"CASH",
1652
+ // "data":[
1653
+ // {
1654
+ // "seqNum":15561826728,
1655
+ // "orderId":"a17294d305c0U6491137460bethu7kw9",
1656
+ // "symbol":"ETH/USDT",
1657
+ // "orderType":"Limit",
1658
+ // "lastExecTime":1591635618200,
1659
+ // "price":"200",
1660
+ // "orderQty":"0.1",
1661
+ // "side":"Buy",
1662
+ // "status":"Canceled",
1663
+ // "avgPx":"0",
1664
+ // "cumFilledQty":"0",
1665
+ // "stopPrice":"",
1666
+ // "errorCode":"",
1667
+ // "cumFee":"0",
1668
+ // "feeAsset":"USDT",
1669
+ // "execInst":"NULL_VAL"
1670
+ // }
1671
+ // ]
1672
+ // }
1673
+ //
1674
+ // accountGroupGetOrderHist
1675
+ //
1676
+ // {
1677
+ // "code": 0,
1678
+ // "data": {
1679
+ // "data": [
1680
+ // {
1681
+ // "ac": "FUTURES",
1682
+ // "accountId": "testabcdefg",
1683
+ // "avgPx": "0",
1684
+ // "cumFee": "0",
1685
+ // "cumQty": "0",
1686
+ // "errorCode": "NULL_VAL",
1687
+ // "execInst": "NULL_VAL",
1688
+ // "feeAsset": "USDT",
1689
+ // "lastExecTime": 1584072844085,
1690
+ // "orderId": "r170d21956dd5450276356bbtcpKa74",
1691
+ // "orderQty": "1.1499",
1692
+ // "orderType": "Limit",
1693
+ // "price": "4000",
1694
+ // "sendingTime": 1584072841033,
1695
+ // "seqNum": 24105338,
1696
+ // "side": "Buy",
1697
+ // "status": "Canceled",
1698
+ // "stopPrice": "",
1699
+ // "symbol": "BTC-PERP"
1700
+ // },
1701
+ // ],
1702
+ // "hasNext": False,
1703
+ // "limit": 500,
1704
+ // "page": 1,
1705
+ // "pageSize": 20
1706
+ // }
1707
+ // }
1708
+ //
1709
+ // accountGroupGetFuturesOrderHistCurrent
1710
+ //
1711
+ // {
1712
+ // "code": 0,
1713
+ // "data": [
1714
+ // {
1715
+ // "ac": "FUTURES",
1716
+ // "accountId": "fut2ODPhGiY71Pl4vtXnOZ00ssgD7QGn",
1717
+ // "time": 1640245777002,
1718
+ // "orderId": "r17de6444fa6U0711043490bbtcpJ2lI",
1719
+ // "seqNum": 28796124902,
1720
+ // "orderType": "Limit",
1721
+ // "execInst": "NULL_VAL",
1722
+ // "side": "Buy",
1723
+ // "symbol": "BTC-PERP",
1724
+ // "price": "30000",
1725
+ // "orderQty": "0.0021",
1726
+ // "stopPrice": "0",
1727
+ // "stopBy": "market",
1728
+ // "status": "Canceled",
1729
+ // "lastExecTime": 1640246574886,
1730
+ // "lastQty": "0",
1731
+ // "lastPx": "0",
1732
+ // "avgFilledPx": "0",
1733
+ // "cumFilledQty": "0",
1734
+ // "fee": "0",
1735
+ // "cumFee": "0",
1736
+ // "feeAsset": "USDT",
1737
+ // "errorCode": "",
1738
+ // "posStopLossPrice": "0",
1739
+ // "posStopLossTrigger": "market",
1740
+ // "posTakeProfitPrice": "0",
1741
+ // "posTakeProfitTrigger": "market",
1742
+ // "liquidityInd": "n"
1743
+ // }
1744
+ // ]
1745
+ // }
1746
+ //
1747
+ let data = this.safeValue (response, 'data');
1748
+ const isArray = Array.isArray (data);
1749
+ if (!isArray) {
1750
+ data = this.safeValue (data, 'data', []);
1751
+ }
1752
+ return this.parseOrders (data, market, since, limit);
1753
+ }
1754
+
1755
+ async cancelOrder (id, symbol = undefined, params = {}) {
1756
+ if (symbol === undefined) {
1757
+ throw new ArgumentsRequired (this.id + ' cancelOrder() requires a symbol argument');
1758
+ }
1759
+ await this.loadMarkets ();
1760
+ await this.loadAccounts ();
1761
+ const market = this.market (symbol);
1762
+ const [ type, query ] = this.handleMarketTypeAndParams ('cancelOrder', market, params);
1763
+ const options = this.safeValue (this.options, 'cancelOrder', {});
1764
+ const accountsByType = this.safeValue (this.options, 'accountsByType', {});
1765
+ const accountCategory = this.safeString (accountsByType, type, 'cash');
1766
+ const account = this.safeValue (this.accounts, 0, {});
1767
+ const accountGroup = this.safeValue (account, 'id');
1768
+ const request = {
1769
+ 'account-group': accountGroup,
1770
+ 'account-category': accountCategory,
1771
+ 'symbol': market['id'],
1772
+ 'time': this.milliseconds (),
1773
+ 'id': 'foobar',
1774
+ };
1775
+ const defaultMethod = this.safeString (options, 'method', 'v1PrivateAccountCategoryDeleteOrder');
1776
+ const method = this.getSupportedMapping (type, {
1777
+ 'spot': defaultMethod,
1778
+ 'margin': defaultMethod,
1779
+ 'swap': 'v2PrivateAccountGroupDeleteFuturesOrder',
1780
+ });
1781
+ if (method === 'v1PrivateAccountCategoryDeleteOrder') {
1782
+ if (accountCategory !== undefined) {
1783
+ request['category'] = accountCategory;
1784
+ }
1785
+ } else {
1786
+ request['account-category'] = accountCategory;
1787
+ }
1788
+ const clientOrderId = this.safeString2 (params, 'clientOrderId', 'id');
1789
+ if (clientOrderId === undefined) {
1790
+ request['orderId'] = id;
1791
+ } else {
1792
+ request['id'] = clientOrderId;
1793
+ params = this.omit (params, [ 'clientOrderId', 'id' ]);
1794
+ }
1795
+ const response = await this[method] (this.extend (request, query));
1796
+ //
1797
+ // AccountCategoryDeleteOrder
1798
+ //
1799
+ // {
1800
+ // "code": 0,
1801
+ // "data": {
1802
+ // "accountId": "cshQtyfq8XLAA9kcf19h8bXHbAwwoqDo",
1803
+ // "ac": "CASH",
1804
+ // "action": "cancel-order",
1805
+ // "status": "Ack",
1806
+ // "info": {
1807
+ // "id": "wv8QGquoeamhssvQBeHOHGQCGlcBjj23",
1808
+ // "orderId": "16e6198afb4s8bXHbAwwoqDo2ebc19dc",
1809
+ // "orderType": "", // could be empty
1810
+ // "symbol": "ETH/USDT",
1811
+ // "timestamp": 1573594877822
1812
+ // }
1813
+ // }
1814
+ // }
1815
+ //
1816
+ // AccountGroupDeleteFuturesOrder
1817
+ //
1818
+ // {
1819
+ // "code": 0,
1820
+ // "data": {
1821
+ // "meta": {
1822
+ // "id": "foobar",
1823
+ // "action": "cancel-order",
1824
+ // "respInst": "ACK"
1825
+ // },
1826
+ // "order": {
1827
+ // "ac": "FUTURES",
1828
+ // "accountId": "fut2ODPhGiY71Pl4vtXnOZ00ssgD7QGn",
1829
+ // "time": 1640244480476,
1830
+ // "orderId": "r17de63086f4U0711043490bbtcpPUF4",
1831
+ // "seqNum": 28795959269,
1832
+ // "orderType": "Limit",
1833
+ // "execInst": "NULL_VAL",
1834
+ // "side": "Buy",
1835
+ // "symbol": "BTC-PERP",
1836
+ // "price": "30000",
1837
+ // "orderQty": "0.0021",
1838
+ // "stopPrice": "0",
1839
+ // "stopBy": "market",
1840
+ // "status": "New",
1841
+ // "lastExecTime": 1640244480491,
1842
+ // "lastQty": "0",
1843
+ // "lastPx": "0",
1844
+ // "avgFilledPx": "0",
1845
+ // "cumFilledQty": "0",
1846
+ // "fee": "0",
1847
+ // "cumFee": "0",
1848
+ // "feeAsset": "BTCPC",
1849
+ // "errorCode": "",
1850
+ // "posStopLossPrice": "0",
1851
+ // "posStopLossTrigger": "market",
1852
+ // "posTakeProfitPrice": "0",
1853
+ // "posTakeProfitTrigger": "market",
1854
+ // "liquidityInd": "n"
1855
+ // }
1856
+ // }
1857
+ // }
1858
+ //
1859
+ const data = this.safeValue (response, 'data', {});
1860
+ const order = this.safeValue2 (data, 'order', 'info', {});
1861
+ return this.parseOrder (order, market);
1862
+ }
1863
+
1864
+ async cancelAllOrders (symbol = undefined, params = {}) {
1865
+ await this.loadMarkets ();
1866
+ await this.loadAccounts ();
1867
+ let market = undefined;
1868
+ if (symbol !== undefined) {
1869
+ market = this.market (symbol);
1870
+ }
1871
+ const [ type, query ] = this.handleMarketTypeAndParams ('cancelAllOrders', market, params);
1872
+ const options = this.safeValue (this.options, 'cancelAllOrders', {});
1873
+ const accountsByType = this.safeValue (this.options, 'accountsByType', {});
1874
+ const accountCategory = this.safeString (accountsByType, type, 'cash');
1875
+ const account = this.safeValue (this.accounts, 0, {});
1876
+ const accountGroup = this.safeValue (account, 'id');
1877
+ const request = {
1878
+ 'account-group': accountGroup,
1879
+ 'account-category': accountCategory,
1880
+ 'time': this.milliseconds (),
1881
+ };
1882
+ if (symbol !== undefined) {
1883
+ request['symbol'] = market['id'];
1884
+ }
1885
+ const defaultMethod = this.safeString (options, 'method', 'v1PrivateAccountCategoryDeleteOrderAll');
1886
+ const method = this.getSupportedMapping (type, {
1887
+ 'spot': defaultMethod,
1888
+ 'margin': defaultMethod,
1889
+ 'swap': 'v2PrivateAccountGroupDeleteFuturesOrderAll',
1890
+ });
1891
+ if (method === 'v1PrivateAccountCategoryDeleteOrderAll') {
1892
+ if (accountCategory !== undefined) {
1893
+ request['category'] = accountCategory;
1894
+ }
1895
+ } else {
1896
+ request['account-category'] = accountCategory;
1897
+ }
1898
+ const response = await this[method] (this.extend (request, query));
1899
+ //
1900
+ // AccountCategoryDeleteOrderAll
1901
+ //
1902
+ // {
1903
+ // "code": 0,
1904
+ // "data": {
1905
+ // "ac": "CASH",
1906
+ // "accountId": "cshQtyfq8XLAA9kcf19h8bXHbAwwoqDo",
1907
+ // "action": "cancel-all",
1908
+ // "info": {
1909
+ // "id": "2bmYvi7lyTrneMzpcJcf2D7Pe9V1P9wy",
1910
+ // "orderId": "",
1911
+ // "orderType": "NULL_VAL",
1912
+ // "symbol": "",
1913
+ // "timestamp": 1574118495462
1914
+ // },
1915
+ // "status": "Ack"
1916
+ // }
1917
+ // }
1918
+ //
1919
+ // AccountGroupDeleteFuturesOrderAll
1920
+ //
1921
+ // {
1922
+ // "code": 0,
1923
+ // "data": {
1924
+ // "ac": "FUTURES",
1925
+ // "accountId": "fut2ODPhGiY71Pl4vtXnOZ00ssgD7QGn",
1926
+ // "action": "cancel-all",
1927
+ // "info": {
1928
+ // "symbol":"BTC-PERP"
1929
+ // }
1930
+ // }
1931
+ // }
1932
+ //
1933
+ return response;
1934
+ }
1935
+
1936
+ parseDepositAddress (depositAddress, currency = undefined) {
1937
+ //
1938
+ // {
1939
+ // address: "0xe7c70b4e73b6b450ee46c3b5c0f5fb127ca55722",
1940
+ // destTag: "",
1941
+ // tagType: "",
1942
+ // tagId: "",
1943
+ // chainName: "ERC20",
1944
+ // numConfirmations: 20,
1945
+ // withdrawalFee: 1,
1946
+ // nativeScale: 4,
1947
+ // tips: []
1948
+ // }
1949
+ //
1950
+ const address = this.safeString (depositAddress, 'address');
1951
+ const tagId = this.safeString (depositAddress, 'tagId');
1952
+ const tag = this.safeString (depositAddress, tagId);
1953
+ this.checkAddress (address);
1954
+ const code = (currency === undefined) ? undefined : currency['code'];
1955
+ const chainName = this.safeString (depositAddress, 'chainName');
1956
+ const network = this.safeNetwork (chainName);
1957
+ return {
1958
+ 'currency': code,
1959
+ 'address': address,
1960
+ 'tag': tag,
1961
+ 'network': network,
1962
+ 'info': depositAddress,
1963
+ };
1964
+ }
1965
+
1966
+ safeNetwork (networkId) {
1967
+ const networksById = {
1968
+ 'TRC20': 'TRC20',
1969
+ 'ERC20': 'ERC20',
1970
+ 'GO20': 'GO20',
1971
+ 'BEP2': 'BEP2',
1972
+ 'BEP20 (BSC)': 'BEP20',
1973
+ 'Bitcoin': 'BTC',
1974
+ 'Bitcoin ABC': 'BCH',
1975
+ 'Litecoin': 'LTC',
1976
+ 'Matic Network': 'MATIC',
1977
+ 'Solana': 'SOL',
1978
+ 'xDai': 'STAKE',
1979
+ 'Akash': 'AKT',
1980
+ };
1981
+ return this.safeString (networksById, networkId, networkId);
1982
+ }
1983
+
1984
+ async fetchDepositAddress (code, params = {}) {
1985
+ await this.loadMarkets ();
1986
+ const currency = this.currency (code);
1987
+ const chainName = this.safeString (params, 'chainName');
1988
+ params = this.omit (params, 'chainName');
1989
+ const request = {
1990
+ 'asset': currency['id'],
1991
+ };
1992
+ const response = await this.v1PrivateGetWalletDepositAddress (this.extend (request, params));
1993
+ //
1994
+ // {
1995
+ // "code":0,
1996
+ // "data":{
1997
+ // "asset":"USDT",
1998
+ // "assetName":"Tether",
1999
+ // "address":[
2000
+ // {
2001
+ // "address":"1N22odLHXnLPCjC8kwBJPTayarr9RtPod6",
2002
+ // "destTag":"",
2003
+ // "tagType":"",
2004
+ // "tagId":"",
2005
+ // "chainName":"Omni",
2006
+ // "numConfirmations":3,
2007
+ // "withdrawalFee":4.7,
2008
+ // "nativeScale":4,
2009
+ // "tips":[]
2010
+ // },
2011
+ // {
2012
+ // "address":"0xe7c70b4e73b6b450ee46c3b5c0f5fb127ca55722",
2013
+ // "destTag":"",
2014
+ // "tagType":"",
2015
+ // "tagId":"",
2016
+ // "chainName":"ERC20",
2017
+ // "numConfirmations":20,
2018
+ // "withdrawalFee":1.0,
2019
+ // "nativeScale":4,
2020
+ // "tips":[]
2021
+ // }
2022
+ // ]
2023
+ // }
2024
+ // }
2025
+ //
2026
+ const data = this.safeValue (response, 'data', {});
2027
+ const addresses = this.safeValue (data, 'address', []);
2028
+ const numAddresses = addresses.length;
2029
+ let address = undefined;
2030
+ if (numAddresses > 1) {
2031
+ const addressesByChainName = this.indexBy (addresses, 'chainName');
2032
+ if (chainName === undefined) {
2033
+ const chainNames = Object.keys (addressesByChainName);
2034
+ const chains = chainNames.join (', ');
2035
+ throw new ArgumentsRequired (this.id + ' fetchDepositAddress() returned more than one address, a chainName parameter is required, one of ' + chains);
2036
+ }
2037
+ address = this.safeValue (addressesByChainName, chainName, {});
2038
+ } else {
2039
+ // first address
2040
+ address = this.safeValue (addresses, 0, {});
2041
+ }
2042
+ const result = this.parseDepositAddress (address, currency);
2043
+ return this.extend (result, {
2044
+ 'info': response,
2045
+ });
2046
+ }
2047
+
2048
+ async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) {
2049
+ const request = {
2050
+ 'txType': 'deposit',
2051
+ };
2052
+ return await this.fetchTransactions (code, since, limit, this.extend (request, params));
2053
+ }
2054
+
2055
+ async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) {
2056
+ const request = {
2057
+ 'txType': 'withdrawal',
2058
+ };
2059
+ return await this.fetchTransactions (code, since, limit, this.extend (request, params));
2060
+ }
2061
+
2062
+ async fetchTransactions (code = undefined, since = undefined, limit = undefined, params = {}) {
2063
+ await this.loadMarkets ();
2064
+ const request = {
2065
+ // 'asset': currency['id'],
2066
+ // 'page': 1,
2067
+ // 'pageSize': 20,
2068
+ // 'startTs': this.milliseconds (),
2069
+ // 'endTs': this.milliseconds (),
2070
+ // 'txType': undefned, // deposit, withdrawal
2071
+ };
2072
+ let currency = undefined;
2073
+ if (code !== undefined) {
2074
+ currency = this.currency (code);
2075
+ request['asset'] = currency['id'];
2076
+ }
2077
+ if (since !== undefined) {
2078
+ request['startTs'] = since;
2079
+ }
2080
+ if (limit !== undefined) {
2081
+ request['pageSize'] = limit;
2082
+ }
2083
+ const response = await this.v1PrivateGetWalletTransactions (this.extend (request, params));
2084
+ //
2085
+ // {
2086
+ // code: 0,
2087
+ // data: {
2088
+ // data: [
2089
+ // {
2090
+ // requestId: "wuzd1Ojsqtz4bCA3UXwtUnnJDmU8PiyB",
2091
+ // time: 1591606166000,
2092
+ // asset: "USDT",
2093
+ // transactionType: "deposit",
2094
+ // amount: "25",
2095
+ // commission: "0",
2096
+ // networkTransactionId: "0xbc4eabdce92f14dbcc01d799a5f8ca1f02f4a3a804b6350ea202be4d3c738fce",
2097
+ // status: "pending",
2098
+ // numConfirmed: 8,
2099
+ // numConfirmations: 20,
2100
+ // destAddress: { address: "0xe7c70b4e73b6b450ee46c3b5c0f5fb127ca55722" }
2101
+ // }
2102
+ // ],
2103
+ // page: 1,
2104
+ // pageSize: 20,
2105
+ // hasNext: false
2106
+ // }
2107
+ // }
2108
+ //
2109
+ const data = this.safeValue (response, 'data', {});
2110
+ const transactions = this.safeValue (data, 'data', []);
2111
+ return this.parseTransactions (transactions, currency, since, limit);
2112
+ }
2113
+
2114
+ parseTransactionStatus (status) {
2115
+ const statuses = {
2116
+ 'reviewing': 'pending',
2117
+ 'pending': 'pending',
2118
+ 'confirmed': 'ok',
2119
+ 'rejected': 'rejected',
2120
+ };
2121
+ return this.safeString (statuses, status, status);
2122
+ }
2123
+
2124
+ parseTransaction (transaction, currency = undefined) {
2125
+ //
2126
+ // {
2127
+ // requestId: "wuzd1Ojsqtz4bCA3UXwtUnnJDmU8PiyB",
2128
+ // time: 1591606166000,
2129
+ // asset: "USDT",
2130
+ // transactionType: "deposit",
2131
+ // amount: "25",
2132
+ // commission: "0",
2133
+ // networkTransactionId: "0xbc4eabdce92f14dbcc01d799a5f8ca1f02f4a3a804b6350ea202be4d3c738fce",
2134
+ // status: "pending",
2135
+ // numConfirmed: 8,
2136
+ // numConfirmations: 20,
2137
+ // destAddress: {
2138
+ // address: "0xe7c70b4e73b6b450ee46c3b5c0f5fb127ca55722",
2139
+ // destTag: "..." // for currencies that have it
2140
+ // }
2141
+ // }
2142
+ //
2143
+ const id = this.safeString (transaction, 'requestId');
2144
+ const amount = this.safeNumber (transaction, 'amount');
2145
+ const destAddress = this.safeValue (transaction, 'destAddress', {});
2146
+ const address = this.safeString (destAddress, 'address');
2147
+ const tag = this.safeString (destAddress, 'destTag');
2148
+ const txid = this.safeString (transaction, 'networkTransactionId');
2149
+ const type = this.safeString (transaction, 'transactionType');
2150
+ const timestamp = this.safeInteger (transaction, 'time');
2151
+ const currencyId = this.safeString (transaction, 'asset');
2152
+ const code = this.safeCurrencyCode (currencyId, currency);
2153
+ const status = this.parseTransactionStatus (this.safeString (transaction, 'status'));
2154
+ const feeCost = this.safeNumber (transaction, 'commission');
2155
+ return {
2156
+ 'info': transaction,
2157
+ 'id': id,
2158
+ 'currency': code,
2159
+ 'amount': amount,
2160
+ 'network': undefined,
2161
+ 'address': address,
2162
+ 'addressTo': address,
2163
+ 'addressFrom': undefined,
2164
+ 'tag': tag,
2165
+ 'tagTo': tag,
2166
+ 'tagFrom': undefined,
2167
+ 'status': status,
2168
+ 'type': type,
2169
+ 'updated': undefined,
2170
+ 'txid': txid,
2171
+ 'timestamp': timestamp,
2172
+ 'datetime': this.iso8601 (timestamp),
2173
+ 'fee': {
2174
+ 'currency': code,
2175
+ 'cost': feeCost,
2176
+ },
2177
+ };
2178
+ }
2179
+
2180
+ async fetchPositions (symbols = undefined, params = {}) {
2181
+ await this.loadMarkets ();
2182
+ await this.loadAccounts ();
2183
+ const account = this.safeValue (this.accounts, 0, {});
2184
+ const accountGroup = this.safeString (account, 'id');
2185
+ const request = {
2186
+ 'account-group': accountGroup,
2187
+ };
2188
+ return await this.v2PrivateAccountGroupGetFuturesPosition (this.extend (request, params));
2189
+ }
2190
+
2191
+ parseFundingRate (fundingRate, market = undefined) {
2192
+ //
2193
+ // {
2194
+ // "time": 1640061364830,
2195
+ // "symbol": "EOS-PERP",
2196
+ // "markPrice": "3.353854865",
2197
+ // "indexPrice": "3.3542",
2198
+ // "openInterest": "14242",
2199
+ // "fundingRate": "-0.000073026",
2200
+ // "nextFundingTime": 1640073600000
2201
+ // }
2202
+ //
2203
+ const marketId = this.safeString (fundingRate, 'symbol');
2204
+ const symbol = this.safeSymbol (marketId, market);
2205
+ const currentTime = this.safeInteger (fundingRate, 'time');
2206
+ const nextFundingRate = this.safeNumber (fundingRate, 'fundingRate');
2207
+ const nextFundingRateTimestamp = this.safeInteger (fundingRate, 'nextFundingTime');
2208
+ const previousFundingTimestamp = undefined;
2209
+ return {
2210
+ 'info': fundingRate,
2211
+ 'symbol': symbol,
2212
+ 'markPrice': this.safeNumber (fundingRate, 'markPrice'),
2213
+ 'indexPrice': this.safeNumber (fundingRate, 'indexPrice'),
2214
+ 'interestRate': this.parseNumber ('0'),
2215
+ 'estimatedSettlePrice': undefined,
2216
+ 'timestamp': currentTime,
2217
+ 'datetime': this.iso8601 (currentTime),
2218
+ 'previousFundingRate': undefined,
2219
+ 'nextFundingRate': nextFundingRate,
2220
+ 'previousFundingTimestamp': previousFundingTimestamp,
2221
+ 'nextFundingTimestamp': nextFundingRateTimestamp,
2222
+ 'previousFundingDatetime': this.iso8601 (previousFundingTimestamp),
2223
+ 'nextFundingDatetime': this.iso8601 (nextFundingRateTimestamp),
2224
+ };
2225
+ }
2226
+
2227
+ async fetchFundingRates (symbols, params = {}) {
2228
+ await this.loadMarkets ();
2229
+ const response = await this.v2PublicGetFuturesPricingData (params);
2230
+ //
2231
+ // {
2232
+ // "code": 0,
2233
+ // "data": {
2234
+ // "contracts": [
2235
+ // {
2236
+ // "time": 1640061364830,
2237
+ // "symbol": "EOS-PERP",
2238
+ // "markPrice": "3.353854865",
2239
+ // "indexPrice": "3.3542",
2240
+ // "openInterest": "14242",
2241
+ // "fundingRate": "-0.000073026",
2242
+ // "nextFundingTime": 1640073600000
2243
+ // },
2244
+ // ],
2245
+ // "collaterals": [
2246
+ // {
2247
+ // "asset": "USDTR",
2248
+ // "referencePrice": "1"
2249
+ // },
2250
+ // ]
2251
+ // }
2252
+ // }
2253
+ //
2254
+ const data = this.safeValue (response, 'data', {});
2255
+ const contracts = this.safeValue (data, 'contracts', []);
2256
+ const result = this.parseFundingRates (contracts);
2257
+ return this.filterByArray (result, 'symbol', symbols);
2258
+ }
2259
+
2260
+ async modifyMarginHelper (symbol, amount, type, params = {}) {
2261
+ await this.loadMarkets ();
2262
+ await this.loadAccounts ();
2263
+ const market = this.market (symbol);
2264
+ const account = this.safeValue (this.accounts, 0, {});
2265
+ const accountGroup = this.safeString (account, 'id');
2266
+ amount = this.amountToPrecision (symbol, amount);
2267
+ const request = {
2268
+ 'account-group': accountGroup,
2269
+ 'symbol': market['id'],
2270
+ 'amount': amount, // positive value for adding margin, negative for reducing
2271
+ };
2272
+ const response = await this.v2PrivateAccountGroupPostFuturesIsolatedPositionMargin (this.extend (request, params));
2273
+ //
2274
+ // Can only change margin for perpetual futures isolated margin positions
2275
+ //
2276
+ // {
2277
+ // "code": 0
2278
+ // }
2279
+ //
2280
+ if (type === 'reduce') {
2281
+ amount = Precise.stringAbs (amount);
2282
+ }
2283
+ return this.extend (this.parseModifyMargin (response, market), {
2284
+ 'amount': this.parseNumber (amount),
2285
+ 'type': type,
2286
+ });
2287
+ }
2288
+
2289
+ parseModifyMargin (data, market = undefined) {
2290
+ const errorCode = this.safeString (data, 'code');
2291
+ const status = (errorCode === '0') ? 'ok' : 'failed';
2292
+ return {
2293
+ 'info': data,
2294
+ 'type': undefined,
2295
+ 'amount': undefined,
2296
+ 'code': market['quote'],
2297
+ 'symbol': market['symbol'],
2298
+ 'status': status,
2299
+ };
2300
+ }
2301
+
2302
+ async reduceMargin (symbol, amount, params = {}) {
2303
+ return await this.modifyMarginHelper (symbol, amount, 'reduce', params);
2304
+ }
2305
+
2306
+ async addMargin (symbol, amount, params = {}) {
2307
+ return await this.modifyMarginHelper (symbol, amount, 'add', params);
2308
+ }
2309
+
2310
+ async setLeverage (leverage, symbol = undefined, params = {}) {
2311
+ if (symbol === undefined) {
2312
+ throw new ArgumentsRequired (this.id + ' setLeverage() requires a symbol argument');
2313
+ }
2314
+ if ((leverage < 1) || (leverage > 100)) {
2315
+ throw new BadRequest (this.id + ' leverage should be between 1 and 100');
2316
+ }
2317
+ await this.loadMarkets ();
2318
+ await this.loadAccounts ();
2319
+ const market = this.market (symbol);
2320
+ if (market['type'] !== 'future') {
2321
+ throw new BadSymbol (this.id + ' setLeverage() supports futures contracts only');
2322
+ }
2323
+ const account = this.safeValue (this.accounts, 0, {});
2324
+ const accountGroup = this.safeString (account, 'id');
2325
+ const request = {
2326
+ 'account-group': accountGroup,
2327
+ 'symbol': market['id'],
2328
+ 'leverage': leverage,
2329
+ };
2330
+ return await this.v2PrivateAccountGroupPostFuturesLeverage (this.extend (request, params));
2331
+ }
2332
+
2333
+ async setMarginMode (marginType, symbol = undefined, params = {}) {
2334
+ marginType = marginType.toLowerCase ();
2335
+ if (marginType === 'cross') {
2336
+ marginType = 'crossed';
2337
+ }
2338
+ if (marginType !== 'isolated' && marginType !== 'crossed') {
2339
+ throw new BadRequest (this.id + ' setMarginMode() marginType argument should be isolated or cross');
2340
+ }
2341
+ await this.loadMarkets ();
2342
+ await this.loadAccounts ();
2343
+ const market = this.market (symbol);
2344
+ const account = this.safeValue (this.accounts, 0, {});
2345
+ const accountGroup = this.safeString (account, 'id');
2346
+ const request = {
2347
+ 'account-group': accountGroup,
2348
+ 'symbol': market['id'],
2349
+ 'marginType': marginType,
2350
+ };
2351
+ if (market['type'] !== 'future') {
2352
+ throw new BadSymbol (this.id + ' setMarginMode() supports futures contracts only');
2353
+ }
2354
+ return await this.v2PrivateAccountGroupPostFuturesMarginType (this.extend (request, params));
2355
+ }
2356
+
2357
+ async fetchLeverageTiers (symbols = undefined, params = {}) {
2358
+ await this.loadMarkets ();
2359
+ const response = await this.v2PublicGetFuturesContract (params);
2360
+ //
2361
+ // {
2362
+ // "code":0,
2363
+ // "data":[
2364
+ // {
2365
+ // "symbol":"BTC-PERP",
2366
+ // "status":"Normal",
2367
+ // "displayName":"BTCUSDT",
2368
+ // "settlementAsset":"USDT",
2369
+ // "underlying":"BTC/USDT",
2370
+ // "tradingStartTime":1579701600000,
2371
+ // "priceFilter":{"minPrice":"1","maxPrice":"1000000","tickSize":"1"},
2372
+ // "lotSizeFilter":{"minQty":"0.0001","maxQty":"1000000000","lotSize":"0.0001"},
2373
+ // "commissionType":"Quote",
2374
+ // "commissionReserveRate":"0.001",
2375
+ // "marketOrderPriceMarkup":"0.03",
2376
+ // "marginRequirements":[
2377
+ // {"positionNotionalLowerBound":"0","positionNotionalUpperBound":"50000","initialMarginRate":"0.01","maintenanceMarginRate":"0.006"},
2378
+ // {"positionNotionalLowerBound":"50000","positionNotionalUpperBound":"200000","initialMarginRate":"0.02","maintenanceMarginRate":"0.012"},
2379
+ // {"positionNotionalLowerBound":"200000","positionNotionalUpperBound":"2000000","initialMarginRate":"0.04","maintenanceMarginRate":"0.024"},
2380
+ // {"positionNotionalLowerBound":"2000000","positionNotionalUpperBound":"20000000","initialMarginRate":"0.1","maintenanceMarginRate":"0.06"},
2381
+ // {"positionNotionalLowerBound":"20000000","positionNotionalUpperBound":"40000000","initialMarginRate":"0.2","maintenanceMarginRate":"0.12"},
2382
+ // {"positionNotionalLowerBound":"40000000","positionNotionalUpperBound":"1000000000","initialMarginRate":"0.333333","maintenanceMarginRate":"0.2"}
2383
+ // ]
2384
+ // }
2385
+ // ]
2386
+ // }
2387
+ //
2388
+ const data = this.safeValue (response, 'data');
2389
+ return this.parseLeverageTiers (data, symbols, 'symbol');
2390
+ }
2391
+
2392
+ parseMarketLeverageTiers (info, market = undefined) {
2393
+ /**
2394
+ * @param {dict} info Exchange market response for 1 market
2395
+ * @param {dict} market CCXT market
2396
+ */
2397
+ //
2398
+ // {
2399
+ // "symbol":"BTC-PERP",
2400
+ // "status":"Normal",
2401
+ // "displayName":"BTCUSDT",
2402
+ // "settlementAsset":"USDT",
2403
+ // "underlying":"BTC/USDT",
2404
+ // "tradingStartTime":1579701600000,
2405
+ // "priceFilter":{"minPrice":"1","maxPrice":"1000000","tickSize":"1"},
2406
+ // "lotSizeFilter":{"minQty":"0.0001","maxQty":"1000000000","lotSize":"0.0001"},
2407
+ // "commissionType":"Quote",
2408
+ // "commissionReserveRate":"0.001",
2409
+ // "marketOrderPriceMarkup":"0.03",
2410
+ // "marginRequirements":[
2411
+ // {"positionNotionalLowerBound":"0","positionNotionalUpperBound":"50000","initialMarginRate":"0.01","maintenanceMarginRate":"0.006"},
2412
+ // {"positionNotionalLowerBound":"50000","positionNotionalUpperBound":"200000","initialMarginRate":"0.02","maintenanceMarginRate":"0.012"},
2413
+ // {"positionNotionalLowerBound":"200000","positionNotionalUpperBound":"2000000","initialMarginRate":"0.04","maintenanceMarginRate":"0.024"},
2414
+ // {"positionNotionalLowerBound":"2000000","positionNotionalUpperBound":"20000000","initialMarginRate":"0.1","maintenanceMarginRate":"0.06"},
2415
+ // {"positionNotionalLowerBound":"20000000","positionNotionalUpperBound":"40000000","initialMarginRate":"0.2","maintenanceMarginRate":"0.12"},
2416
+ // {"positionNotionalLowerBound":"40000000","positionNotionalUpperBound":"1000000000","initialMarginRate":"0.333333","maintenanceMarginRate":"0.2"}
2417
+ // ]
2418
+ // }
2419
+ //
2420
+ const marginRequirements = this.safeValue (info, 'marginRequirements');
2421
+ const id = this.safeString (info, 'symbol');
2422
+ market = this.safeMarket (id, market);
2423
+ const tiers = [];
2424
+ for (let i = 0; i < marginRequirements.length; i++) {
2425
+ const tier = marginRequirements[i];
2426
+ const initialMarginRate = this.safeString (tier, 'initialMarginRate');
2427
+ tiers.push ({
2428
+ 'tier': this.sum (i, 1),
2429
+ 'currency': market['quote'],
2430
+ 'minNotional': this.safeNumber (tier, 'positionNotionalLowerBound'),
2431
+ 'maxNotional': this.safeNumber (tier, 'positionNotionalUpperBound'),
2432
+ 'maintenanceMarginRate': this.safeNumber (tier, 'maintenanceMarginRate'),
2433
+ 'maxLeverage': this.parseNumber (Precise.stringDiv ('1', initialMarginRate)),
2434
+ 'info': tier,
2435
+ });
2436
+ }
2437
+ return tiers;
2438
+ }
2439
+
2440
+ async transfer (code, amount, fromAccount, toAccount, params = {}) {
2441
+ await this.loadMarkets ();
2442
+ await this.loadAccounts ();
2443
+ const account = this.safeValue (this.accounts, 0, {});
2444
+ const accountGroup = this.safeString (account, 'id');
2445
+ const currency = this.currency (code);
2446
+ amount = this.currencyToPrecision (code, amount);
2447
+ const accountsByType = this.safeValue (this.options, 'accountsByType', {});
2448
+ const fromId = this.safeString (accountsByType, fromAccount, fromAccount);
2449
+ const toId = this.safeString (accountsByType, toAccount, toAccount);
2450
+ if (fromId !== 'cash' && toId !== 'cash') {
2451
+ throw new ExchangeError (this.id + ' transfer() only supports direct balance transfer between spot and future, spot and margin');
2452
+ }
2453
+ const request = {
2454
+ 'account-group': accountGroup,
2455
+ 'amount': amount,
2456
+ 'asset': currency['id'],
2457
+ 'fromAccount': fromId,
2458
+ 'toAccount': toId,
2459
+ };
2460
+ const response = await this.v1PrivateAccountGroupPostTransfer (this.extend (request, params));
2461
+ //
2462
+ // { code: '0' }
2463
+ //
2464
+ const transferOptions = this.safeValue (this.options, 'transfer', {});
2465
+ const fillResponseFromRequest = this.safeValue (transferOptions, 'fillResponseFromRequest', true);
2466
+ const transfer = this.parseTransfer (response, currency);
2467
+ if (fillResponseFromRequest) {
2468
+ transfer['fromAccount'] = fromAccount;
2469
+ transfer['toAccount'] = toAccount;
2470
+ transfer['amount'] = amount;
2471
+ transfer['currency'] = code;
2472
+ }
2473
+ return transfer;
2474
+ }
2475
+
2476
+ parseTransfer (transfer, currency = undefined) {
2477
+ //
2478
+ // { code: '0' }
2479
+ //
2480
+ const status = this.safeInteger (transfer, 'code');
2481
+ const currencyCode = this.safeCurrencyCode (undefined, currency);
2482
+ const timestamp = this.milliseconds ();
2483
+ return {
2484
+ 'info': transfer,
2485
+ 'id': undefined,
2486
+ 'timestamp': timestamp,
2487
+ 'datetime': this.iso8601 (timestamp),
2488
+ 'currency': currencyCode,
2489
+ 'amount': undefined,
2490
+ 'fromAccount': undefined,
2491
+ 'toAccount': undefined,
2492
+ 'status': this.parseTransferStatus (status),
2493
+ };
2494
+ }
2495
+
2496
+ parseTransferStatus (status) {
2497
+ if (status === 0) {
2498
+ return 'ok';
2499
+ }
2500
+ return 'failed';
2501
+ }
2502
+
2503
+ sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
2504
+ const version = api[0];
2505
+ const access = api[1];
2506
+ const type = this.safeString (api, 2);
2507
+ let url = '';
2508
+ const accountCategory = (type === 'accountCategory');
2509
+ if (accountCategory || (type === 'accountGroup')) {
2510
+ url += this.implodeParams ('/{account-group}', params);
2511
+ params = this.omit (params, 'account-group');
2512
+ }
2513
+ let request = this.implodeParams (path, params);
2514
+ url += '/api/pro/';
2515
+ if (version === 'v2') {
2516
+ request = version + '/' + request;
2517
+ } else {
2518
+ url += version + '/';
2519
+ }
2520
+ if (accountCategory) {
2521
+ url += this.implodeParams ('{account-category}/', params);
2522
+ }
2523
+ params = this.omit (params, 'account-category');
2524
+ url += request;
2525
+ if ((version === 'v1') && (request === 'cash/balance') || (request === 'margin/balance')) {
2526
+ request = 'balance';
2527
+ }
2528
+ if ((version === 'v1') && (request === 'spot/fee')) {
2529
+ request = 'fee';
2530
+ }
2531
+ if (request.indexOf ('subuser') >= 0) {
2532
+ const parts = request.split ('/');
2533
+ request = parts[2];
2534
+ }
2535
+ params = this.omit (params, this.extractParams (path));
2536
+ if (access === 'public') {
2537
+ if (Object.keys (params).length) {
2538
+ url += '?' + this.urlencode (params);
2539
+ }
2540
+ } else {
2541
+ this.checkRequiredCredentials ();
2542
+ const timestamp = this.milliseconds ().toString ();
2543
+ const payload = timestamp + '+' + request;
2544
+ const hmac = this.hmac (this.encode (payload), this.encode (this.secret), 'sha256', 'base64');
2545
+ headers = {
2546
+ 'x-auth-key': this.apiKey,
2547
+ 'x-auth-timestamp': timestamp,
2548
+ 'x-auth-signature': hmac,
2549
+ };
2550
+ if (method === 'GET') {
2551
+ if (Object.keys (params).length) {
2552
+ url += '?' + this.urlencode (params);
2553
+ }
2554
+ } else {
2555
+ headers['Content-Type'] = 'application/json';
2556
+ body = this.json (params);
2557
+ }
2558
+ }
2559
+ url = this.urls['api']['rest'] + url;
2560
+ return { 'url': url, 'method': method, 'body': body, 'headers': headers };
2561
+ }
2562
+
2563
+ handleErrors (httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) {
2564
+ if (response === undefined) {
2565
+ return; // fallback to default error handler
2566
+ }
2567
+ //
2568
+ // {'code': 6010, 'message': 'Not enough balance.'}
2569
+ // {'code': 60060, 'message': 'The order is already filled or canceled.'}
2570
+ // {"code":2100,"message":"ApiKeyFailure"}
2571
+ // {"code":300001,"message":"Price is too low from market price.","reason":"INVALID_PRICE","accountId":"cshrHKLZCjlZ2ejqkmvIHHtPmLYqdnda","ac":"CASH","action":"place-order","status":"Err","info":{"symbol":"BTC/USDT"}}
2572
+ //
2573
+ const code = this.safeString (response, 'code');
2574
+ const message = this.safeString (response, 'message');
2575
+ const error = (code !== undefined) && (code !== '0');
2576
+ if (error || (message !== undefined)) {
2577
+ const feedback = this.id + ' ' + body;
2578
+ this.throwExactlyMatchedException (this.exceptions['exact'], code, feedback);
2579
+ this.throwExactlyMatchedException (this.exceptions['exact'], message, feedback);
2580
+ this.throwBroadlyMatchedException (this.exceptions['broad'], message, feedback);
2581
+ throw new ExchangeError (feedback); // unknown message
2582
+ }
2583
+ }
2584
+ };