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/hitbtc3.js ADDED
@@ -0,0 +1,2329 @@
1
+ const Exchange = require ('./base/Exchange');
2
+ const { TICK_SIZE } = require ('./base/functions/number');
3
+ const Precise = require ('./base/Precise');
4
+ const { BadSymbol, BadRequest, OnMaintenance, AccountSuspended, PermissionDenied, ExchangeError, RateLimitExceeded, ExchangeNotAvailable, OrderNotFound, InsufficientFunds, InvalidOrder, AuthenticationError, ArgumentsRequired } = require ('./base/errors');
5
+
6
+ module.exports = class hitbtc3 extends Exchange {
7
+ describe () {
8
+ return this.deepExtend (super.describe (), {
9
+ 'id': 'hitbtc3',
10
+ 'name': 'HitBTC',
11
+ 'countries': [ 'HK' ],
12
+ // 300 requests per second => 1000ms / 300 = 3.333 (Trading: placing, replacing, deleting)
13
+ // 30 requests per second => ( 1000ms / rateLimit ) / 30 = cost = 10 (Market Data and other Public Requests)
14
+ // 20 requests per second => ( 1000ms / rateLimit ) / 20 = cost = 15 (All Other)
15
+ 'rateLimit': 3.333, // TODO: optimize https://api.hitbtc.com/#rate-limiting
16
+ 'version': '3',
17
+ 'pro': true,
18
+ 'has': {
19
+ 'CORS': false,
20
+ 'spot': true,
21
+ 'margin': true,
22
+ 'swap': true,
23
+ 'future': false,
24
+ 'option': undefined,
25
+ 'addMargin': true,
26
+ 'cancelAllOrders': true,
27
+ 'cancelOrder': true,
28
+ 'createOrder': true,
29
+ 'createReduceOnlyOrder': true,
30
+ 'createStopLimitOrder': true,
31
+ 'createStopMarketOrder': true,
32
+ 'createStopOrder': true,
33
+ 'editOrder': true,
34
+ 'fetchBalance': true,
35
+ 'fetchBorrowRate': undefined,
36
+ 'fetchBorrowRateHistories': undefined,
37
+ 'fetchBorrowRateHistory': undefined,
38
+ 'fetchBorrowRates': undefined,
39
+ 'fetchClosedOrders': true,
40
+ 'fetchCurrencies': true,
41
+ 'fetchDepositAddress': true,
42
+ 'fetchDeposits': true,
43
+ 'fetchFundingHistory': undefined,
44
+ 'fetchFundingRate': true,
45
+ 'fetchFundingRateHistory': true,
46
+ 'fetchFundingRates': false,
47
+ 'fetchIndexOHLCV': true,
48
+ 'fetchLeverage': true,
49
+ 'fetchLeverageTiers': undefined,
50
+ 'fetchMarketLeverageTiers': undefined,
51
+ 'fetchMarkets': true,
52
+ 'fetchMarkOHLCV': true,
53
+ 'fetchMyTrades': true,
54
+ 'fetchOHLCV': true,
55
+ 'fetchOpenOrder': true,
56
+ 'fetchOpenOrders': true,
57
+ 'fetchOrder': true,
58
+ 'fetchOrderBook': true,
59
+ 'fetchOrderBooks': true,
60
+ 'fetchOrders': false,
61
+ 'fetchOrderTrades': true,
62
+ 'fetchPosition': true,
63
+ 'fetchPositions': true,
64
+ 'fetchPremiumIndexOHLCV': true,
65
+ 'fetchTicker': true,
66
+ 'fetchTickers': true,
67
+ 'fetchTrades': true,
68
+ 'fetchTradingFee': true,
69
+ 'fetchTradingFees': true,
70
+ 'fetchTransactions': true,
71
+ 'fetchWithdrawals': true,
72
+ 'reduceMargin': true,
73
+ 'setLeverage': true,
74
+ 'setMarginMode': false,
75
+ 'setPositionMode': false,
76
+ 'transfer': true,
77
+ 'withdraw': true,
78
+ },
79
+ 'precisionMode': TICK_SIZE,
80
+ 'urls': {
81
+ 'logo': 'https://user-images.githubusercontent.com/1294454/27766555-8eaec20e-5edc-11e7-9c5b-6dc69fc42f5e.jpg',
82
+ 'test': {
83
+ 'public': 'https://api.demo.hitbtc.com',
84
+ 'private': 'https://api.demo.hitbtc.com',
85
+ },
86
+ 'api': {
87
+ 'public': 'https://api.hitbtc.com/api/3',
88
+ 'private': 'https://api.hitbtc.com/api/3',
89
+ },
90
+ 'www': 'https://hitbtc.com',
91
+ 'referral': 'https://hitbtc.com/?ref_id=5a5d39a65d466',
92
+ 'doc': [
93
+ 'https://api.hitbtc.com',
94
+ 'https://github.com/hitbtc-com/hitbtc-api/blob/master/APIv2.md',
95
+ ],
96
+ 'fees': [
97
+ 'https://hitbtc.com/fees-and-limits',
98
+ 'https://support.hitbtc.com/hc/en-us/articles/115005148605-Fees-and-limits',
99
+ ],
100
+ },
101
+ 'api': {
102
+ 'public': {
103
+ 'get': {
104
+ 'public/currency': 10,
105
+ 'public/symbol': 10,
106
+ 'public/ticker': 10,
107
+ 'public/price/rate': 10,
108
+ 'public/trades': 10,
109
+ 'public/orderbook': 10,
110
+ 'public/candles': 10,
111
+ 'public/futures/info': 10,
112
+ 'public/futures/history/funding': 10,
113
+ 'public/futures/candles/index_price': 10,
114
+ 'public/futures/candles/mark_price': 10,
115
+ 'public/futures/candles/premium_index': 10,
116
+ 'public/futures/candles/open_interest': 10,
117
+ },
118
+ },
119
+ 'private': {
120
+ 'get': {
121
+ 'spot/balance': 15,
122
+ 'spot/order': 15,
123
+ 'spot/order/{client_order_id}': 15,
124
+ 'spot/fee': 15,
125
+ 'spot/fee/{symbol}': 15,
126
+ 'spot/history/order': 15,
127
+ 'spot/history/trade': 15,
128
+ 'margin/account': 15,
129
+ 'margin/account/isolated/{symbol}': 15,
130
+ 'margin/order': 15,
131
+ 'margin/order/{client_order_id}': 15,
132
+ 'margin/history/clearing': 15,
133
+ 'margin/history/order': 15,
134
+ 'margin/history/positions': 15,
135
+ 'margin/history/trade': 15,
136
+ 'futures/balance': 15,
137
+ 'futures/account': 15,
138
+ 'futures/account/isolated/{symbol}': 15,
139
+ 'futures/order': 15,
140
+ 'futures/order/{client_order_id}': 15,
141
+ 'futures/fee': 15,
142
+ 'futures/fee/{symbol}': 15,
143
+ 'futures/history/clearing': 15,
144
+ 'futures/history/order': 15,
145
+ 'futures/history/positions': 15,
146
+ 'futures/history/trade': 15,
147
+ 'wallet/balance': 15,
148
+ 'wallet/crypto/address': 15,
149
+ 'wallet/crypto/address/recent-deposit': 15,
150
+ 'wallet/crypto/address/recent-withdraw': 15,
151
+ 'wallet/crypto/address/check-mine': 15,
152
+ 'wallet/transactions': 15,
153
+ 'wallet/crypto/check-offchain-available': 15,
154
+ 'wallet/crypto/fee/estimate': 15,
155
+ 'sub-account': 15,
156
+ 'sub-account/acl': 15,
157
+ 'sub-account/balance/{subAccID}': 15,
158
+ 'sub-account/crypto/address/{subAccID}/{currency}': 15,
159
+ },
160
+ 'post': {
161
+ 'spot/order': 1,
162
+ 'margin/order': 1,
163
+ 'futures/order': 1,
164
+ 'wallet/convert': 15,
165
+ 'wallet/crypto/withdraw': 15,
166
+ 'wallet/transfer': 15,
167
+ 'sub-account/freeze': 15,
168
+ 'sub-account/activate': 15,
169
+ 'sub-account/transfer': 15,
170
+ 'sub-account/acl': 15,
171
+ },
172
+ 'patch': {
173
+ 'spot/order/{client_order_id}': 1,
174
+ 'margin/order/{client_order_id}': 1,
175
+ 'futures/order/{client_order_id}': 1,
176
+ },
177
+ 'delete': {
178
+ 'spot/order': 1,
179
+ 'spot/order/{client_order_id}': 1,
180
+ 'margin/position': 1,
181
+ 'margin/position/isolated/{symbol}': 1,
182
+ 'margin/order': 1,
183
+ 'margin/order/{client_order_id}': 1,
184
+ 'futures/position': 1,
185
+ 'futures/position/isolated/{symbol}': 1,
186
+ 'futures/order': 1,
187
+ 'futures/order/{client_order_id}': 1,
188
+ 'wallet/crypto/withdraw/{id}': 1,
189
+ },
190
+ 'put': {
191
+ 'margin/account/isolated/{symbol}': 1,
192
+ 'futures/account/isolated/{symbol}': 1,
193
+ 'wallet/crypto/withdraw/{id}': 1,
194
+ },
195
+ },
196
+ },
197
+ 'fees': {
198
+ 'trading': {
199
+ 'tierBased': true,
200
+ 'percentage': true,
201
+ 'taker': this.parseNumber ('0.0009'),
202
+ 'maker': this.parseNumber ('0.0009'),
203
+ 'tiers': {
204
+ 'maker': [
205
+ [ this.parseNumber ('0'), this.parseNumber ('0.0009') ],
206
+ [ this.parseNumber ('10'), this.parseNumber ('0.0007') ],
207
+ [ this.parseNumber ('100'), this.parseNumber ('0.0006') ],
208
+ [ this.parseNumber ('500'), this.parseNumber ('0.0005') ],
209
+ [ this.parseNumber ('1000'), this.parseNumber ('0.0003') ],
210
+ [ this.parseNumber ('5000'), this.parseNumber ('0.0002') ],
211
+ [ this.parseNumber ('10000'), this.parseNumber ('0.0001') ],
212
+ [ this.parseNumber ('20000'), this.parseNumber ('0') ],
213
+ [ this.parseNumber ('50000'), this.parseNumber ('-0.0001') ],
214
+ [ this.parseNumber ('100000'), this.parseNumber ('-0.0001') ],
215
+ ],
216
+ 'taker': [
217
+ [ this.parseNumber ('0'), this.parseNumber ('0.0009') ],
218
+ [ this.parseNumber ('10'), this.parseNumber ('0.0008') ],
219
+ [ this.parseNumber ('100'), this.parseNumber ('0.0007') ],
220
+ [ this.parseNumber ('500'), this.parseNumber ('0.0007') ],
221
+ [ this.parseNumber ('1000'), this.parseNumber ('0.0006') ],
222
+ [ this.parseNumber ('5000'), this.parseNumber ('0.0006') ],
223
+ [ this.parseNumber ('10000'), this.parseNumber ('0.0005') ],
224
+ [ this.parseNumber ('20000'), this.parseNumber ('0.0004') ],
225
+ [ this.parseNumber ('50000'), this.parseNumber ('0.0003') ],
226
+ [ this.parseNumber ('100000'), this.parseNumber ('0.0002') ],
227
+ ],
228
+ },
229
+ },
230
+ },
231
+ 'timeframes': {
232
+ '1m': 'M1',
233
+ '3m': 'M3',
234
+ '5m': 'M5',
235
+ '15m': 'M15',
236
+ '30m': 'M30', // default
237
+ '1h': 'H1',
238
+ '4h': 'H4',
239
+ '1d': 'D1',
240
+ '1w': 'D7',
241
+ '1M': '1M',
242
+ },
243
+ 'exceptions': {
244
+ 'exact': {
245
+ '429': RateLimitExceeded,
246
+ '500': ExchangeError,
247
+ '503': ExchangeNotAvailable,
248
+ '504': ExchangeNotAvailable,
249
+ '600': PermissionDenied,
250
+ '800': ExchangeError,
251
+ '1002': AuthenticationError,
252
+ '1003': PermissionDenied,
253
+ '1004': AuthenticationError,
254
+ '1005': AuthenticationError,
255
+ '2001': BadSymbol,
256
+ '2002': BadRequest,
257
+ '2003': BadRequest,
258
+ '2010': BadRequest,
259
+ '2011': BadRequest,
260
+ '2012': BadRequest,
261
+ '2020': BadRequest,
262
+ '2022': BadRequest,
263
+ '10001': BadRequest,
264
+ '10021': AccountSuspended,
265
+ '10022': BadRequest,
266
+ '20001': InsufficientFunds,
267
+ '20002': OrderNotFound,
268
+ '20003': ExchangeError,
269
+ '20004': ExchangeError,
270
+ '20005': ExchangeError,
271
+ '20006': ExchangeError,
272
+ '20007': ExchangeError,
273
+ '20008': InvalidOrder,
274
+ '20009': InvalidOrder,
275
+ '20010': OnMaintenance,
276
+ '20011': ExchangeError,
277
+ '20012': ExchangeError,
278
+ '20014': ExchangeError,
279
+ '20016': ExchangeError,
280
+ '20031': ExchangeError,
281
+ '20032': ExchangeError,
282
+ '20033': ExchangeError,
283
+ '20034': ExchangeError,
284
+ '20040': ExchangeError,
285
+ '20041': ExchangeError,
286
+ '20042': ExchangeError,
287
+ '20043': ExchangeError,
288
+ '20044': PermissionDenied,
289
+ '20045': InvalidOrder,
290
+ '20080': ExchangeError,
291
+ '21001': ExchangeError,
292
+ '21003': AccountSuspended,
293
+ '21004': AccountSuspended,
294
+ },
295
+ 'broad': {},
296
+ },
297
+ 'options': {
298
+ 'networks': {
299
+ 'ETH': 'USDT20',
300
+ 'ERC20': 'USDT20',
301
+ 'TRX': 'USDTRX',
302
+ 'TRC20': 'USDTRX',
303
+ 'OMNI': 'USDT',
304
+ },
305
+ 'accountsByType': {
306
+ 'spot': 'spot',
307
+ 'funding': 'wallet',
308
+ 'future': 'derivatives',
309
+ },
310
+ },
311
+ 'commonCurrencies': {
312
+ 'AUTO': 'Cube',
313
+ 'BCC': 'BCC', // initial symbol for Bitcoin Cash, now inactive
314
+ 'BDP': 'BidiPass',
315
+ 'BET': 'DAO.Casino',
316
+ 'BIT': 'BitRewards',
317
+ 'BOX': 'BOX Token',
318
+ 'CPT': 'Cryptaur', // conflict with CPT = Contents Protocol https://github.com/ccxt/ccxt/issues/4920 and https://github.com/ccxt/ccxt/issues/6081
319
+ 'GET': 'Themis',
320
+ 'GMT': 'GMT Token',
321
+ 'HSR': 'HC',
322
+ 'IQ': 'IQ.Cash',
323
+ 'LNC': 'LinkerCoin',
324
+ 'PLA': 'PlayChip',
325
+ 'PNT': 'Penta',
326
+ 'SBTC': 'Super Bitcoin',
327
+ 'STEPN': 'GMT',
328
+ 'STX': 'STOX',
329
+ 'TV': 'Tokenville',
330
+ 'USD': 'USDT',
331
+ 'XMT': 'MTL',
332
+ 'XPNT': 'PNT',
333
+ },
334
+ });
335
+ }
336
+
337
+ nonce () {
338
+ return this.milliseconds ();
339
+ }
340
+
341
+ async fetchMarkets (params = {}) {
342
+ const response = await this.publicGetPublicSymbol (params);
343
+ //
344
+ // {
345
+ // "AAVEUSDT_PERP":{
346
+ // "type":"futures",
347
+ // "expiry":null,
348
+ // "underlying":"AAVE",
349
+ // "base_currency":null,
350
+ // "quote_currency":"USDT",
351
+ // "quantity_increment":"0.01",
352
+ // "tick_size":"0.001",
353
+ // "take_rate":"0.0005",
354
+ // "make_rate":"0.0002",
355
+ // "fee_currency":"USDT",
356
+ // "margin_trading":true,
357
+ // "max_initial_leverage":"50.00"
358
+ // },
359
+ // "MANAUSDT":{
360
+ // "type":"spot",
361
+ // "base_currency":"MANA",
362
+ // "quote_currency":"USDT",
363
+ // "quantity_increment":"1",
364
+ // "tick_size":"0.0000001",
365
+ // "take_rate":"0.0025",
366
+ // "make_rate":"0.001",
367
+ // "fee_currency":"USDT",
368
+ // "margin_trading":true,
369
+ // "max_initial_leverage":"5.00"
370
+ // },
371
+ // }
372
+ //
373
+ const result = [];
374
+ const ids = Object.keys (response);
375
+ for (let i = 0; i < ids.length; i++) {
376
+ const id = ids[i];
377
+ const market = this.safeValue (response, id);
378
+ const marketType = this.safeString (market, 'type');
379
+ const expiry = this.safeInteger (market, 'expiry');
380
+ const contract = (marketType === 'futures');
381
+ const spot = (marketType === 'spot');
382
+ const marginTrading = this.safeValue (market, 'margin_trading', false);
383
+ const margin = spot && marginTrading;
384
+ const future = (expiry !== undefined);
385
+ const swap = (contract && !future);
386
+ const option = false;
387
+ const baseId = this.safeString2 (market, 'base_currency', 'underlying');
388
+ const quoteId = this.safeString (market, 'quote_currency');
389
+ const feeCurrencyId = this.safeString (market, 'fee_currency');
390
+ const base = this.safeCurrencyCode (baseId);
391
+ const quote = this.safeCurrencyCode (quoteId);
392
+ const feeCurrency = this.safeCurrencyCode (feeCurrencyId);
393
+ let settleId = undefined;
394
+ let settle = undefined;
395
+ let symbol = base + '/' + quote;
396
+ let type = 'spot';
397
+ let contractSize = undefined;
398
+ let linear = undefined;
399
+ let inverse = undefined;
400
+ if (contract) {
401
+ contractSize = this.parseNumber ('1');
402
+ settleId = feeCurrencyId;
403
+ settle = this.safeCurrencyCode (settleId);
404
+ linear = ((quote !== undefined) && (quote === settle));
405
+ inverse = !linear;
406
+ symbol = symbol + ':' + settle;
407
+ if (future) {
408
+ symbol = symbol + '-' + expiry;
409
+ type = 'future';
410
+ } else {
411
+ type = 'swap';
412
+ }
413
+ }
414
+ const lotString = this.safeString (market, 'quantity_increment');
415
+ const stepString = this.safeString (market, 'tick_size');
416
+ const lot = this.parseNumber (lotString);
417
+ const step = this.parseNumber (stepString);
418
+ result.push ({
419
+ 'id': id,
420
+ 'symbol': symbol,
421
+ 'base': base,
422
+ 'quote': quote,
423
+ 'settle': settle,
424
+ 'baseId': baseId,
425
+ 'quoteId': quoteId,
426
+ 'settleId': settleId,
427
+ 'type': type,
428
+ 'spot': spot,
429
+ 'margin': margin,
430
+ 'swap': swap,
431
+ 'future': future,
432
+ 'option': option,
433
+ 'active': true,
434
+ 'contract': contract,
435
+ 'linear': linear,
436
+ 'inverse': inverse,
437
+ 'taker': this.safeNumber (market, 'take_rate'),
438
+ 'maker': this.safeNumber (market, 'make_rate'),
439
+ 'contractSize': contractSize,
440
+ 'expiry': expiry,
441
+ 'expiryDatetime': undefined,
442
+ 'strike': undefined,
443
+ 'optionType': undefined,
444
+ 'feeCurrency': feeCurrency,
445
+ 'precision': {
446
+ 'amount': lot,
447
+ 'price': step,
448
+ },
449
+ 'limits': {
450
+ 'leverage': {
451
+ 'min': this.parseNumber ('1'),
452
+ 'max': this.safeNumber (market, 'max_initial_leverage', 1),
453
+ },
454
+ 'amount': {
455
+ 'min': lot,
456
+ 'max': undefined,
457
+ },
458
+ 'price': {
459
+ 'min': step,
460
+ 'max': undefined,
461
+ },
462
+ 'cost': {
463
+ 'min': this.parseNumber (Precise.stringMul (lotString, stepString)),
464
+ 'max': undefined,
465
+ },
466
+ },
467
+ 'info': market,
468
+ });
469
+ }
470
+ return result;
471
+ }
472
+
473
+ async fetchCurrencies (params = {}) {
474
+ const response = await this.publicGetPublicCurrency (params);
475
+ //
476
+ // {
477
+ // "WEALTH": {
478
+ // "full_name": "ConnectWealth",
479
+ // "payin_enabled": false,
480
+ // "payout_enabled": false,
481
+ // "transfer_enabled": true,
482
+ // "precision_transfer": "0.001",
483
+ // "networks": [
484
+ // {
485
+ // "network": "ETH",
486
+ // "protocol": "ERC20",
487
+ // "default": true,
488
+ // "payin_enabled": false,
489
+ // "payout_enabled": false,
490
+ // "precision_payout": "0.001",
491
+ // "payout_fee": "0.016800000000",
492
+ // "payout_is_payment_id": false,
493
+ // "payin_payment_id": false,
494
+ // "payin_confirmations": "2"
495
+ // }
496
+ // ]
497
+ // }
498
+ // }
499
+ //
500
+ const result = {};
501
+ const currencies = Object.keys (response);
502
+ for (let i = 0; i < currencies.length; i++) {
503
+ const currencyId = currencies[i];
504
+ const code = this.safeCurrencyCode (currencyId);
505
+ const entry = response[currencyId];
506
+ const name = this.safeString (entry, 'full_name');
507
+ const precision = this.safeNumber (entry, 'precision_transfer');
508
+ const payinEnabled = this.safeValue (entry, 'payin_enabled', false);
509
+ const payoutEnabled = this.safeValue (entry, 'payout_enabled', false);
510
+ const transferEnabled = this.safeValue (entry, 'transfer_enabled', false);
511
+ const active = payinEnabled && payoutEnabled && transferEnabled;
512
+ const rawNetworks = this.safeValue (entry, 'networks', []);
513
+ const networks = {};
514
+ let fee = undefined;
515
+ let depositEnabled = undefined;
516
+ let withdrawEnabled = undefined;
517
+ for (let j = 0; j < rawNetworks.length; j++) {
518
+ const rawNetwork = rawNetworks[j];
519
+ let networkId = this.safeString (rawNetwork, 'protocol');
520
+ if (networkId.length === 0) {
521
+ networkId = this.safeString (rawNetwork, 'network');
522
+ }
523
+ const network = this.safeNetwork (networkId);
524
+ fee = this.safeNumber (rawNetwork, 'payout_fee');
525
+ const precision = this.safeNumber (rawNetwork, 'precision_payout');
526
+ const payinEnabledNetwork = this.safeValue (entry, 'payin_enabled', false);
527
+ const payoutEnabledNetwork = this.safeValue (entry, 'payout_enabled', false);
528
+ const activeNetwork = payinEnabledNetwork && payoutEnabledNetwork;
529
+ if (payinEnabledNetwork && !depositEnabled) {
530
+ depositEnabled = true;
531
+ } else if (!payinEnabledNetwork) {
532
+ depositEnabled = false;
533
+ }
534
+ if (payoutEnabledNetwork && !withdrawEnabled) {
535
+ withdrawEnabled = true;
536
+ } else if (!payoutEnabledNetwork) {
537
+ withdrawEnabled = false;
538
+ }
539
+ networks[network] = {
540
+ 'info': rawNetwork,
541
+ 'id': networkId,
542
+ 'network': network,
543
+ 'fee': fee,
544
+ 'active': activeNetwork,
545
+ 'deposit': payinEnabledNetwork,
546
+ 'withdraw': payoutEnabledNetwork,
547
+ 'precision': precision,
548
+ 'limits': {
549
+ 'withdraw': {
550
+ 'min': undefined,
551
+ 'max': undefined,
552
+ },
553
+ },
554
+ };
555
+ }
556
+ const networksKeys = Object.keys (networks);
557
+ const networksLength = networksKeys.length;
558
+ result[code] = {
559
+ 'info': entry,
560
+ 'code': code,
561
+ 'id': currencyId,
562
+ 'precision': precision,
563
+ 'name': name,
564
+ 'active': active,
565
+ 'deposit': depositEnabled,
566
+ 'withdraw': withdrawEnabled,
567
+ 'networks': networks,
568
+ 'fee': (networksLength <= 1) ? fee : undefined,
569
+ 'limits': {
570
+ 'amount': {
571
+ 'min': undefined,
572
+ 'max': undefined,
573
+ },
574
+ },
575
+ };
576
+ }
577
+ return result;
578
+ }
579
+
580
+ safeNetwork (networkId) {
581
+ if (networkId === undefined) {
582
+ return undefined;
583
+ } else {
584
+ return networkId.toUpperCase ();
585
+ }
586
+ }
587
+
588
+ async fetchDepositAddress (code, params = {}) {
589
+ await this.loadMarkets ();
590
+ const currency = this.currency (code);
591
+ const request = {
592
+ 'currency': currency['id'],
593
+ };
594
+ const network = this.safeStringUpper (params, 'network');
595
+ if ((network !== undefined) && (code === 'USDT')) {
596
+ const networks = this.safeValue (this.options, 'networks');
597
+ const parsedNetwork = this.safeString (networks, network);
598
+ if (parsedNetwork !== undefined) {
599
+ request['currency'] = parsedNetwork;
600
+ }
601
+ params = this.omit (params, 'network');
602
+ }
603
+ const response = await this.privateGetWalletCryptoAddress (this.extend (request, params));
604
+ //
605
+ // [{"currency":"ETH","address":"0xd0d9aea60c41988c3e68417e2616065617b7afd3"}]
606
+ //
607
+ const firstAddress = this.safeValue (response, 0);
608
+ const address = this.safeString (firstAddress, 'address');
609
+ const currencyId = this.safeString (firstAddress, 'currency');
610
+ const tag = this.safeString (firstAddress, 'payment_id');
611
+ const parsedCode = this.safeCurrencyCode (currencyId);
612
+ return {
613
+ 'info': response,
614
+ 'address': address,
615
+ 'tag': tag,
616
+ 'code': parsedCode,
617
+ 'network': undefined,
618
+ };
619
+ }
620
+
621
+ parseBalance (response) {
622
+ const result = { 'info': response };
623
+ for (let i = 0; i < response.length; i++) {
624
+ const entry = response[i];
625
+ const currencyId = this.safeString (entry, 'currency');
626
+ const code = this.safeCurrencyCode (currencyId);
627
+ const account = this.account ();
628
+ account['free'] = this.safeString (entry, 'available');
629
+ account['used'] = this.safeString (entry, 'reserved');
630
+ result[code] = account;
631
+ }
632
+ return this.safeBalance (result);
633
+ }
634
+
635
+ async fetchBalance (params = {}) {
636
+ const type = this.safeStringLower (params, 'type', 'spot');
637
+ params = this.omit (params, [ 'type' ]);
638
+ const accountsByType = this.safeValue (this.options, 'accountsByType', {});
639
+ const account = this.safeString (accountsByType, type, type);
640
+ let response = undefined;
641
+ if (account === 'wallet') {
642
+ response = await this.privateGetWalletBalance (params);
643
+ } else if (account === 'spot') {
644
+ response = await this.privateGetSpotBalance (params);
645
+ } else if (account === 'derivatives') {
646
+ response = await this.privateGetFuturesBalance (params);
647
+ } else {
648
+ const keys = Object.keys (accountsByType);
649
+ throw new BadRequest (this.id + ' fetchBalance() type parameter must be one of ' + keys.join (', '));
650
+ }
651
+ //
652
+ // [
653
+ // {
654
+ // "currency": "PAXG",
655
+ // "available": "0",
656
+ // "reserved": "0",
657
+ // "reserved_margin": "0",
658
+ // },
659
+ // ...
660
+ // ]
661
+ //
662
+ return this.parseBalance (response);
663
+ }
664
+
665
+ async fetchTicker (symbol, params = {}) {
666
+ const response = await this.fetchTickers ([ symbol ], params);
667
+ return this.safeValue (response, symbol);
668
+ }
669
+
670
+ async fetchTickers (symbols = undefined, params = {}) {
671
+ await this.loadMarkets ();
672
+ const request = {};
673
+ if (symbols !== undefined) {
674
+ const marketIds = this.marketIds (symbols);
675
+ const delimited = marketIds.join (',');
676
+ request['symbols'] = delimited;
677
+ }
678
+ const response = await this.publicGetPublicTicker (this.extend (request, params));
679
+ //
680
+ // {
681
+ // "BTCUSDT": {
682
+ // "ask": "63049.06",
683
+ // "bid": "63046.41",
684
+ // "last": "63048.36",
685
+ // "low": "62010.00",
686
+ // "high": "66657.99",
687
+ // "open": "64839.75",
688
+ // "volume": "15272.13278",
689
+ // "volume_quote": "976312127.6277998",
690
+ // "timestamp": "2021-10-22T04:25:47.573Z"
691
+ // }
692
+ // }
693
+ //
694
+ const result = {};
695
+ const keys = Object.keys (response);
696
+ for (let i = 0; i < keys.length; i++) {
697
+ const marketId = keys[i];
698
+ const market = this.safeMarket (marketId);
699
+ const symbol = market['symbol'];
700
+ const entry = response[marketId];
701
+ result[symbol] = this.parseTicker (entry, market);
702
+ }
703
+ return this.filterByArray (result, 'symbol', symbols);
704
+ }
705
+
706
+ parseTicker (ticker, market = undefined) {
707
+ //
708
+ // {
709
+ // "ask": "62756.01",
710
+ // "bid": "62754.09",
711
+ // "last": "62755.87",
712
+ // "low": "62010.00",
713
+ // "high": "66657.99",
714
+ // "open": "65089.27",
715
+ // "volume": "16719.50366",
716
+ // "volume_quote": "1063422878.8156828",
717
+ // "timestamp": "2021-10-22T07:29:14.585Z"
718
+ // }
719
+ //
720
+ const timestamp = this.parse8601 (ticker['timestamp']);
721
+ const symbol = this.safeSymbol (undefined, market);
722
+ const baseVolume = this.safeString (ticker, 'volume');
723
+ const quoteVolume = this.safeString (ticker, 'volume_quote');
724
+ const open = this.safeString (ticker, 'open');
725
+ const last = this.safeString (ticker, 'last');
726
+ return this.safeTicker ({
727
+ 'symbol': symbol,
728
+ 'timestamp': timestamp,
729
+ 'datetime': this.iso8601 (timestamp),
730
+ 'high': this.safeString (ticker, 'high'),
731
+ 'low': this.safeString (ticker, 'low'),
732
+ 'bid': this.safeString (ticker, 'bid'),
733
+ 'bidVolume': undefined,
734
+ 'ask': this.safeString (ticker, 'ask'),
735
+ 'askVolume': undefined,
736
+ 'vwap': undefined,
737
+ 'open': open,
738
+ 'close': last,
739
+ 'last': last,
740
+ 'previousClose': undefined,
741
+ 'change': undefined,
742
+ 'percentage': undefined,
743
+ 'average': undefined,
744
+ 'baseVolume': baseVolume,
745
+ 'quoteVolume': quoteVolume,
746
+ 'info': ticker,
747
+ }, market, false);
748
+ }
749
+
750
+ async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
751
+ await this.loadMarkets ();
752
+ let market = undefined;
753
+ const request = {};
754
+ if (symbol !== undefined) {
755
+ market = this.market (symbol);
756
+ // symbol is optional for hitbtc fetchTrades
757
+ request['symbols'] = market['id'];
758
+ }
759
+ if (limit !== undefined) {
760
+ request['limit'] = limit;
761
+ }
762
+ if (since !== undefined) {
763
+ request['from'] = since;
764
+ }
765
+ const response = await this.publicGetPublicTrades (this.extend (request, params));
766
+ const marketIds = Object.keys (response);
767
+ let trades = [];
768
+ for (let i = 0; i < marketIds.length; i++) {
769
+ const marketId = marketIds[i];
770
+ const market = this.market (marketId);
771
+ const rawTrades = response[marketId];
772
+ const parsed = this.parseTrades (rawTrades, market);
773
+ trades = this.arrayConcat (trades, parsed);
774
+ }
775
+ return trades;
776
+ }
777
+
778
+ async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
779
+ await this.loadMarkets ();
780
+ let market = undefined;
781
+ const request = {};
782
+ if (symbol !== undefined) {
783
+ market = this.market (symbol);
784
+ request['symbol'] = market['id'];
785
+ }
786
+ if (limit !== undefined) {
787
+ request['limit'] = limit;
788
+ }
789
+ if (since !== undefined) {
790
+ request['from'] = since;
791
+ }
792
+ const [ marketType, query ] = this.handleMarketTypeAndParams ('fetchMyTrades', market, params);
793
+ const method = this.getSupportedMapping (marketType, {
794
+ 'spot': 'privateGetSpotHistoryTrade',
795
+ 'swap': 'privateGetFuturesHistoryTrade',
796
+ 'margin': 'privateGetMarginHistoryTrade',
797
+ });
798
+ const response = await this[method] (this.extend (request, query));
799
+ return this.parseTrades (response, market, since, limit);
800
+ }
801
+
802
+ parseTrade (trade, market = undefined) {
803
+ //
804
+ // createOrder (market)
805
+ //
806
+ // {
807
+ // id: '1569252895',
808
+ // position_id: '0',
809
+ // quantity: '10',
810
+ // price: '0.03919424',
811
+ // fee: '0.000979856000',
812
+ // timestamp: '2022-01-25T19:38:36.153Z',
813
+ // taker: true
814
+ // }
815
+ //
816
+ // fetchTrades
817
+ //
818
+ // {
819
+ // id: 974786185,
820
+ // price: '0.032462',
821
+ // qty: '0.3673',
822
+ // side: 'buy',
823
+ // timestamp: '2020-10-16T12:57:39.846Z'
824
+ // }
825
+ //
826
+ // fetchMyTrades spot
827
+ //
828
+ // {
829
+ // id: 277210397,
830
+ // clientOrderId: '6e102f3e7f3f4e04aeeb1cdc95592f1a',
831
+ // orderId: 28102855393,
832
+ // symbol: 'ETHBTC',
833
+ // side: 'sell',
834
+ // quantity: '0.002',
835
+ // price: '0.073365',
836
+ // fee: '0.000000147',
837
+ // timestamp: '2018-04-28T18:39:55.345Z',
838
+ // taker: true
839
+ // }
840
+ //
841
+ // fetchMyTrades swap and margin
842
+ //
843
+ // {
844
+ // "id": 4718564,
845
+ // "order_id": 58730811958,
846
+ // "client_order_id": "475c47d97f867f09726186eb22b4c3d4",
847
+ // "symbol": "BTCUSDT_PERP",
848
+ // "side": "sell",
849
+ // "quantity": "0.0001",
850
+ // "price": "41118.51",
851
+ // "fee": "0.002055925500",
852
+ // "timestamp": "2022-03-17T05:23:17.795Z",
853
+ // "taker": true,
854
+ // "position_id": 2350122,
855
+ // "pnl": "0.002255000000",
856
+ // "liquidation": false
857
+ // }
858
+ //
859
+ const timestamp = this.parse8601 (trade['timestamp']);
860
+ const marketId = this.safeString (trade, 'symbol');
861
+ market = this.safeMarket (marketId, market);
862
+ const symbol = market['symbol'];
863
+ let fee = undefined;
864
+ const feeCostString = this.safeString (trade, 'fee');
865
+ const taker = this.safeValue (trade, 'taker');
866
+ let takerOrMaker = undefined;
867
+ if (taker !== undefined) {
868
+ takerOrMaker = taker ? 'taker' : 'maker';
869
+ }
870
+ if (feeCostString !== undefined) {
871
+ const info = this.safeValue (market, 'info', {});
872
+ const feeCurrency = this.safeString (info, 'fee_currency');
873
+ const feeCurrencyCode = this.safeCurrencyCode (feeCurrency);
874
+ fee = {
875
+ 'cost': feeCostString,
876
+ 'currency': feeCurrencyCode,
877
+ };
878
+ }
879
+ // we use clientOrderId as the order id with this exchange intentionally
880
+ // because most of their endpoints will require clientOrderId
881
+ // explained here: https://github.com/ccxt/ccxt/issues/5674
882
+ const orderId = this.safeString (trade, 'clientOrderId');
883
+ const priceString = this.safeString (trade, 'price');
884
+ const amountString = this.safeString2 (trade, 'quantity', 'qty');
885
+ const side = this.safeString (trade, 'side');
886
+ const id = this.safeString (trade, 'id');
887
+ return this.safeTrade ({
888
+ 'info': trade,
889
+ 'id': id,
890
+ 'order': orderId,
891
+ 'timestamp': timestamp,
892
+ 'datetime': this.iso8601 (timestamp),
893
+ 'symbol': symbol,
894
+ 'type': undefined,
895
+ 'side': side,
896
+ 'takerOrMaker': takerOrMaker,
897
+ 'price': priceString,
898
+ 'amount': amountString,
899
+ 'cost': undefined,
900
+ 'fee': fee,
901
+ }, market);
902
+ }
903
+
904
+ async fetchTransactionsHelper (types, code, since, limit, params) {
905
+ await this.loadMarkets ();
906
+ const request = {
907
+ 'types': types,
908
+ };
909
+ let currency = undefined;
910
+ if (code !== undefined) {
911
+ currency = this.currency (code);
912
+ request['currencies'] = currency['id'];
913
+ }
914
+ if (since !== undefined) {
915
+ request['from'] = this.iso8601 (since);
916
+ }
917
+ if (limit !== undefined) {
918
+ request['limit'] = limit;
919
+ }
920
+ const response = await this.privateGetWalletTransactions (this.extend (request, params));
921
+ //
922
+ // [
923
+ // {
924
+ // "id": "101609495",
925
+ // "created_at": "2018-03-06T22:05:06.507Z",
926
+ // "updated_at": "2018-03-06T22:11:45.03Z",
927
+ // "status": "SUCCESS",
928
+ // "type": "DEPOSIT",
929
+ // "subtype": "BLOCKCHAIN",
930
+ // "native": {
931
+ // "tx_id": "e20b0965-4024-44d0-b63f-7fb8996a6706",
932
+ // "index": "881652766",
933
+ // "currency": "ETH",
934
+ // "amount": "0.01418088",
935
+ // "hash": "d95dbbff3f9234114f1211ab0ba2a94f03f394866fd5749d74a1edab80e6c5d3",
936
+ // "address": "0xd9259302c32c0a0295d86a39185c9e14f6ba0a0d",
937
+ // "confirmations": "20",
938
+ // "senders": [
939
+ // "0x243bec9256c9a3469da22103891465b47583d9f1"
940
+ // ]
941
+ // }
942
+ // }
943
+ // ]
944
+ //
945
+ return this.parseTransactions (response, currency, since, limit, params);
946
+ }
947
+
948
+ parseTransactionStatus (status) {
949
+ const statuses = {
950
+ 'PENDING': 'pending',
951
+ 'FAILED': 'failed',
952
+ 'SUCCESS': 'ok',
953
+ };
954
+ return this.safeString (statuses, status, status);
955
+ }
956
+
957
+ parseTransactionType (type) {
958
+ const types = {
959
+ 'DEPOSIT': 'deposit',
960
+ 'WITHDRAW': 'withdrawal',
961
+ };
962
+ return this.safeString (types, type, type);
963
+ }
964
+
965
+ parseTransaction (transaction, currency = undefined) {
966
+ //
967
+ // transaction
968
+ //
969
+ // {
970
+ // "id": "101609495",
971
+ // "created_at": "2018-03-06T22:05:06.507Z",
972
+ // "updated_at": "2018-03-06T22:11:45.03Z",
973
+ // "status": "SUCCESS",
974
+ // "type": "DEPOSIT", // DEPOSIT, WITHDRAW, ..
975
+ // "subtype": "BLOCKCHAIN",
976
+ // "native": {
977
+ // "tx_id": "e20b0965-4024-44d0-b63f-7fb8996a6706",
978
+ // "index": "881652766",
979
+ // "currency": "ETH",
980
+ // "amount": "0.01418088",
981
+ // "hash": "d95dbbff3f9234114f1211ab0ba2a94f03f394866fd5749d74a1edab80e6c5d3",
982
+ // "address": "0xd9259302c32c0a0295d86a39185c9e14f6ba0a0d",
983
+ // "confirmations": "20",
984
+ // "senders": [
985
+ // "0x243bec9256c9a3469da22103891465b47583d9f1"
986
+ // ],
987
+ // "fee": "1.22" // only for WITHDRAW
988
+ // }
989
+ // }
990
+ //
991
+ // withdraw
992
+ //
993
+ // {
994
+ // "id":"084cfcd5-06b9-4826-882e-fdb75ec3625d"
995
+ // }
996
+ //
997
+ const id = this.safeString (transaction, 'id');
998
+ const timestamp = this.parse8601 (this.safeString (transaction, 'created_at'));
999
+ const updated = this.parse8601 (this.safeString (transaction, 'updated_at'));
1000
+ const type = this.parseTransactionType (this.safeString (transaction, 'type'));
1001
+ const status = this.parseTransactionStatus (this.safeString (transaction, 'status'));
1002
+ const native = this.safeValue (transaction, 'native', {});
1003
+ const currencyId = this.safeString (native, 'currency');
1004
+ const code = this.safeCurrencyCode (currencyId);
1005
+ const txhash = this.safeString (native, 'hash');
1006
+ const address = this.safeString (native, 'address');
1007
+ const addressTo = address;
1008
+ const tag = this.safeString (native, 'payment_id');
1009
+ const tagTo = tag;
1010
+ const sender = this.safeValue (native, 'senders');
1011
+ const addressFrom = this.safeString (sender, 0);
1012
+ const amount = this.safeNumber (native, 'amount');
1013
+ let fee = undefined;
1014
+ const feeCost = this.safeNumber (native, 'fee');
1015
+ if (feeCost !== undefined) {
1016
+ fee = {
1017
+ 'code': code,
1018
+ 'cost': feeCost,
1019
+ };
1020
+ }
1021
+ return {
1022
+ 'info': transaction,
1023
+ 'id': id,
1024
+ 'txid': txhash,
1025
+ 'code': code,
1026
+ 'amount': amount,
1027
+ 'network': undefined,
1028
+ 'address': address,
1029
+ 'addressFrom': addressFrom,
1030
+ 'addressTo': addressTo,
1031
+ 'tag': tag,
1032
+ 'tagFrom': undefined,
1033
+ 'tagTo': tagTo,
1034
+ 'timestamp': timestamp,
1035
+ 'datetime': this.iso8601 (timestamp),
1036
+ 'updated': updated,
1037
+ 'status': status,
1038
+ 'type': type,
1039
+ 'fee': fee,
1040
+ };
1041
+ }
1042
+
1043
+ async fetchTransactions (code = undefined, since = undefined, limit = undefined, params = {}) {
1044
+ return await this.fetchTransactionsHelper ('DEPOSIT,WITHDRAW', code, since, limit, params);
1045
+ }
1046
+
1047
+ async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) {
1048
+ return await this.fetchTransactionsHelper ('DEPOSIT', code, since, limit, params);
1049
+ }
1050
+
1051
+ async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) {
1052
+ return await this.fetchTransactionsHelper ('WITHDRAW', code, since, limit, params);
1053
+ }
1054
+
1055
+ async fetchOrderBooks (symbols = undefined, limit = undefined, params = {}) {
1056
+ await this.loadMarkets ();
1057
+ const request = {};
1058
+ if (symbols !== undefined) {
1059
+ const marketIds = this.marketIds (symbols);
1060
+ request['symbols'] = marketIds.join (',');
1061
+ }
1062
+ if (limit !== undefined) {
1063
+ request['depth'] = limit;
1064
+ }
1065
+ const response = await this.publicGetPublicOrderbook (this.extend (request, params));
1066
+ const result = {};
1067
+ const marketIds = Object.keys (response);
1068
+ for (let i = 0; i < marketIds.length; i++) {
1069
+ const marketId = marketIds[i];
1070
+ const orderbook = response[marketId];
1071
+ const symbol = this.safeSymbol (marketId);
1072
+ const timestamp = this.parse8601 (this.safeString (orderbook, 'timestamp'));
1073
+ result[symbol] = this.parseOrderBook (response[marketId], symbol, timestamp, 'bid', 'ask');
1074
+ }
1075
+ return result;
1076
+ }
1077
+
1078
+ async fetchOrderBook (symbol, limit = undefined, params = {}) {
1079
+ const result = await this.fetchOrderBooks ([ symbol ], limit, params);
1080
+ return result[symbol];
1081
+ }
1082
+
1083
+ parseTradingFee (fee, market = undefined) {
1084
+ //
1085
+ // {
1086
+ // "symbol":"ARVUSDT", // returned from fetchTradingFees only
1087
+ // "take_rate":"0.0009",
1088
+ // "make_rate":"0.0009"
1089
+ // }
1090
+ //
1091
+ const taker = this.safeNumber (fee, 'take_rate');
1092
+ const maker = this.safeNumber (fee, 'make_rate');
1093
+ const marketId = this.safeString (fee, 'symbol');
1094
+ const symbol = this.safeSymbol (marketId, market);
1095
+ return {
1096
+ 'info': fee,
1097
+ 'symbol': symbol,
1098
+ 'taker': taker,
1099
+ 'maker': maker,
1100
+ };
1101
+ }
1102
+
1103
+ async fetchTradingFee (symbol, params = {}) {
1104
+ await this.loadMarkets ();
1105
+ const market = this.market (symbol);
1106
+ const request = {
1107
+ 'symbol': market['id'],
1108
+ };
1109
+ const method = this.getSupportedMapping (market['type'], {
1110
+ 'spot': 'privateGetSpotFeeSymbol',
1111
+ 'swap': 'privateGetFuturesFeeSymbol',
1112
+ });
1113
+ const response = await this[method] (this.extend (request, params));
1114
+ //
1115
+ // {
1116
+ // "take_rate":"0.0009",
1117
+ // "make_rate":"0.0009"
1118
+ // }
1119
+ //
1120
+ return this.parseTradingFee (response, market);
1121
+ }
1122
+
1123
+ async fetchTradingFees (symbols = undefined, params = {}) {
1124
+ await this.loadMarkets ();
1125
+ const [ marketType, query ] = this.handleMarketTypeAndParams ('fetchTradingFees', undefined, params);
1126
+ const method = this.getSupportedMapping (marketType, {
1127
+ 'spot': 'privateGetSpotFee',
1128
+ 'swap': 'privateGetFuturesFee',
1129
+ });
1130
+ const response = await this[method] (query);
1131
+ //
1132
+ // [
1133
+ // {
1134
+ // "symbol":"ARVUSDT",
1135
+ // "take_rate":"0.0009",
1136
+ // "make_rate":"0.0009"
1137
+ // }
1138
+ // ]
1139
+ //
1140
+ const result = {};
1141
+ for (let i = 0; i < response.length; i++) {
1142
+ const fee = this.parseTradingFee (response[i]);
1143
+ const symbol = fee['symbol'];
1144
+ result[symbol] = fee;
1145
+ }
1146
+ return result;
1147
+ }
1148
+
1149
+ async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
1150
+ await this.loadMarkets ();
1151
+ const market = this.market (symbol);
1152
+ const request = {
1153
+ 'symbols': market['id'],
1154
+ 'period': this.timeframes[timeframe],
1155
+ };
1156
+ if (since !== undefined) {
1157
+ request['from'] = this.iso8601 (since);
1158
+ }
1159
+ if (limit !== undefined) {
1160
+ request['limit'] = limit;
1161
+ }
1162
+ const price = this.safeString (params, 'price');
1163
+ params = this.omit (params, 'price');
1164
+ let method = 'publicGetPublicCandles';
1165
+ if (price === 'mark') {
1166
+ method = 'publicGetPublicFuturesCandlesMarkPrice';
1167
+ } else if (price === 'index') {
1168
+ method = 'publicGetPublicFuturesCandlesIndexPrice';
1169
+ } else if (price === 'premiumIndex') {
1170
+ method = 'publicGetPublicFuturesCandlesPremiumIndex';
1171
+ }
1172
+ const response = await this[method] (this.extend (request, params));
1173
+ //
1174
+ // Spot and Swap
1175
+ //
1176
+ // {
1177
+ // "ETHUSDT": [
1178
+ // {
1179
+ // "timestamp": "2021-10-25T07:38:00.000Z",
1180
+ // "open": "4173.391",
1181
+ // "close": "4170.923",
1182
+ // "min": "4170.923",
1183
+ // "max": "4173.986",
1184
+ // "volume": "0.1879",
1185
+ // "volume_quote": "784.2517846"
1186
+ // }
1187
+ // ]
1188
+ // }
1189
+ //
1190
+ // Mark, Index and Premium Index
1191
+ //
1192
+ // {
1193
+ // "BTCUSDT_PERP": [
1194
+ // {
1195
+ // "timestamp": "2022-04-01T01:28:00.000Z",
1196
+ // "open": "45146.39",
1197
+ // "close": "45219.43",
1198
+ // "min": "45146.39",
1199
+ // "max": "45219.43"
1200
+ // },
1201
+ // ]
1202
+ // }
1203
+ //
1204
+ const ohlcvs = this.safeValue (response, market['id']);
1205
+ return this.parseOHLCVs (ohlcvs, market, timeframe, since, limit);
1206
+ }
1207
+
1208
+ async fetchMarkOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
1209
+ const request = {
1210
+ 'price': 'mark',
1211
+ };
1212
+ return await this.fetchOHLCV (symbol, timeframe, since, limit, this.extend (request, params));
1213
+ }
1214
+
1215
+ async fetchIndexOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
1216
+ const request = {
1217
+ 'price': 'index',
1218
+ };
1219
+ return await this.fetchOHLCV (symbol, timeframe, since, limit, this.extend (request, params));
1220
+ }
1221
+
1222
+ async fetchPremiumIndexOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
1223
+ const request = {
1224
+ 'price': 'premiumIndex',
1225
+ };
1226
+ return await this.fetchOHLCV (symbol, timeframe, since, limit, this.extend (request, params));
1227
+ }
1228
+
1229
+ parseOHLCV (ohlcv, market = undefined) {
1230
+ //
1231
+ // Spot and Swap
1232
+ //
1233
+ // {
1234
+ // "timestamp":"2015-08-20T19:01:00.000Z",
1235
+ // "open":"0.006",
1236
+ // "close":"0.006",
1237
+ // "min":"0.006",
1238
+ // "max":"0.006",
1239
+ // "volume":"0.003",
1240
+ // "volume_quote":"0.000018"
1241
+ // }
1242
+ //
1243
+ // Mark, Index and Premium Index
1244
+ //
1245
+ // {
1246
+ // "timestamp": "2022-04-01T01:28:00.000Z",
1247
+ // "open": "45146.39",
1248
+ // "close": "45219.43",
1249
+ // "min": "45146.39",
1250
+ // "max": "45219.43"
1251
+ // },
1252
+ //
1253
+ return [
1254
+ this.parse8601 (this.safeString (ohlcv, 'timestamp')),
1255
+ this.safeNumber (ohlcv, 'open'),
1256
+ this.safeNumber (ohlcv, 'max'),
1257
+ this.safeNumber (ohlcv, 'min'),
1258
+ this.safeNumber (ohlcv, 'close'),
1259
+ this.safeNumber (ohlcv, 'volume'),
1260
+ ];
1261
+ }
1262
+
1263
+ async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
1264
+ await this.loadMarkets ();
1265
+ let market = undefined;
1266
+ const request = {};
1267
+ if (symbol !== undefined) {
1268
+ market = this.market (symbol);
1269
+ request['symbol'] = market['id'];
1270
+ }
1271
+ if (since !== undefined) {
1272
+ request['from'] = this.iso8601 (since);
1273
+ }
1274
+ if (limit !== undefined) {
1275
+ request['limit'] = limit;
1276
+ }
1277
+ const [ marketType, query ] = this.handleMarketTypeAndParams ('fetchClosedOrders', market, params);
1278
+ const method = this.getSupportedMapping (marketType, {
1279
+ 'spot': 'privateGetSpotHistoryOrder',
1280
+ 'swap': 'privateGetFuturesHistoryOrder',
1281
+ 'margin': 'privateGetMarginHistoryOrder',
1282
+ });
1283
+ const response = await this[method] (this.extend (request, query));
1284
+ const parsed = this.parseOrders (response, market, since, limit);
1285
+ return this.filterByArray (parsed, 'status', [ 'closed', 'canceled' ], false);
1286
+ }
1287
+
1288
+ async fetchOrder (id, symbol = undefined, params = {}) {
1289
+ await this.loadMarkets ();
1290
+ let market = undefined;
1291
+ if (symbol !== undefined) {
1292
+ market = this.market (symbol);
1293
+ }
1294
+ const [ marketType, query ] = this.handleMarketTypeAndParams ('fetchOrder', market, params);
1295
+ const method = this.getSupportedMapping (marketType, {
1296
+ 'spot': 'privateGetSpotHistoryOrder',
1297
+ 'swap': 'privateGetFuturesHistoryOrder',
1298
+ 'margin': 'privateGetMarginHistoryOrder',
1299
+ });
1300
+ const request = {
1301
+ 'client_order_id': id,
1302
+ };
1303
+ const response = await this[method] (this.extend (request, query));
1304
+ //
1305
+ // [
1306
+ // {
1307
+ // "id": "685965182082",
1308
+ // "client_order_id": "B3CBm9uGg9oYQlw96bBSEt38-6gbgBO0",
1309
+ // "symbol": "BTCUSDT",
1310
+ // "side": "buy",
1311
+ // "status": "new",
1312
+ // "type": "limit",
1313
+ // "time_in_force": "GTC",
1314
+ // "quantity": "0.00010",
1315
+ // "quantity_cumulative": "0",
1316
+ // "price": "50000.00",
1317
+ // "price_average": "0",
1318
+ // "created_at": "2021-10-26T11:40:09.287Z",
1319
+ // "updated_at": "2021-10-26T11:40:09.287Z"
1320
+ // }
1321
+ // ]
1322
+ //
1323
+ const order = this.safeValue (response, 0);
1324
+ return this.parseOrder (order, market);
1325
+ }
1326
+
1327
+ async fetchOrderTrades (id, symbol = undefined, since = undefined, limit = undefined, params = {}) {
1328
+ await this.loadMarkets ();
1329
+ let market = undefined;
1330
+ if (symbol !== undefined) {
1331
+ market = this.market (symbol);
1332
+ }
1333
+ const request = {
1334
+ 'order_id': id, // exchange assigned order id as oppose to the client order id
1335
+ };
1336
+ const [ marketType, query ] = this.handleMarketTypeAndParams ('fetchOrderTrades', market, params);
1337
+ const method = this.getSupportedMapping (marketType, {
1338
+ 'spot': 'privateGetSpotHistoryTrade',
1339
+ 'swap': 'privateGetFuturesHistoryTrade',
1340
+ 'margin': 'privateGetMarginHistoryTrade',
1341
+ });
1342
+ const response = await this[method] (this.extend (request, query));
1343
+ //
1344
+ // Spot
1345
+ //
1346
+ // [
1347
+ // {
1348
+ // "id": 1393448977,
1349
+ // "order_id": 653496804534,
1350
+ // "client_order_id": "065f6f0ff9d54547848454182263d7b4",
1351
+ // "symbol": "DICEETH",
1352
+ // "side": "buy",
1353
+ // "quantity": "1.4",
1354
+ // "price": "0.00261455",
1355
+ // "fee": "0.000003294333",
1356
+ // "timestamp": "2021-09-19T05:35:56.601Z",
1357
+ // "taker": true
1358
+ // }
1359
+ // ]
1360
+ //
1361
+ // Swap and Margin
1362
+ //
1363
+ // [
1364
+ // {
1365
+ // "id": 4718551,
1366
+ // "order_id": 58730748700,
1367
+ // "client_order_id": "dcbcd8549e3445ee922665946002ef67",
1368
+ // "symbol": "BTCUSDT_PERP",
1369
+ // "side": "buy",
1370
+ // "quantity": "0.0001",
1371
+ // "price": "41095.96",
1372
+ // "fee": "0.002054798000",
1373
+ // "timestamp": "2022-03-17T05:23:02.217Z",
1374
+ // "taker": true,
1375
+ // "position_id": 2350122,
1376
+ // "pnl": "0",
1377
+ // "liquidation": false
1378
+ // }
1379
+ // ]
1380
+ //
1381
+ return this.parseTrades (response, market, since, limit);
1382
+ }
1383
+
1384
+ async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
1385
+ await this.loadMarkets ();
1386
+ let market = undefined;
1387
+ const request = {};
1388
+ if (symbol !== undefined) {
1389
+ market = this.market (symbol);
1390
+ request['symbol'] = market['id'];
1391
+ }
1392
+ const [ marketType, query ] = this.handleMarketTypeAndParams ('fetchOpenOrders', market, params);
1393
+ const method = this.getSupportedMapping (marketType, {
1394
+ 'spot': 'privateGetSpotOrder',
1395
+ 'swap': 'privateGetFuturesOrder',
1396
+ 'margin': 'privateGetMarginOrder',
1397
+ });
1398
+ const response = await this[method] (this.extend (request, query));
1399
+ //
1400
+ // [
1401
+ // {
1402
+ // "id": "488953123149",
1403
+ // "client_order_id": "103ad305301e4c3590045b13de15b36e",
1404
+ // "symbol": "BTCUSDT",
1405
+ // "side": "buy",
1406
+ // "status": "new",
1407
+ // "type": "limit",
1408
+ // "time_in_force": "GTC",
1409
+ // "quantity": "0.00001",
1410
+ // "quantity_cumulative": "0",
1411
+ // "price": "0.01",
1412
+ // "post_only": false,
1413
+ // "created_at": "2021-04-13T13:06:16.567Z",
1414
+ // "updated_at": "2021-04-13T13:06:16.567Z"
1415
+ // }
1416
+ // ]
1417
+ //
1418
+ return this.parseOrders (response, market, since, limit);
1419
+ }
1420
+
1421
+ async fetchOpenOrder (id, symbol = undefined, params = {}) {
1422
+ await this.loadMarkets ();
1423
+ let market = undefined;
1424
+ if (symbol !== undefined) {
1425
+ market = this.market (symbol);
1426
+ }
1427
+ const [ marketType, query ] = this.handleMarketTypeAndParams ('fetchOpenOrder', market, params);
1428
+ const method = this.getSupportedMapping (marketType, {
1429
+ 'spot': 'privateGetSpotOrderClientOrderId',
1430
+ 'swap': 'privateGetFuturesOrderClientOrderId',
1431
+ 'margin': 'privateGetMarginOrderClientOrderId',
1432
+ });
1433
+ const request = {
1434
+ 'client_order_id': id,
1435
+ };
1436
+ const response = await this[method] (this.extend (request, query));
1437
+ return this.parseOrder (response, market);
1438
+ }
1439
+
1440
+ async cancelAllOrders (symbol = undefined, params = {}) {
1441
+ await this.loadMarkets ();
1442
+ let market = undefined;
1443
+ const request = {};
1444
+ if (symbol !== undefined) {
1445
+ market = this.market (symbol);
1446
+ request['symbol'] = market['id'];
1447
+ }
1448
+ const [ marketType, query ] = this.handleMarketTypeAndParams ('cancelAllOrders', market, params);
1449
+ const method = this.getSupportedMapping (marketType, {
1450
+ 'spot': 'privateDeleteSpotOrder',
1451
+ 'swap': 'privateDeleteFuturesOrder',
1452
+ 'margin': 'privateDeleteMarginOrder',
1453
+ });
1454
+ const response = await this[method] (this.extend (request, query));
1455
+ return this.parseOrders (response, market);
1456
+ }
1457
+
1458
+ async cancelOrder (id, symbol = undefined, params = {}) {
1459
+ await this.loadMarkets ();
1460
+ let market = undefined;
1461
+ const request = {
1462
+ 'client_order_id': id,
1463
+ };
1464
+ if (symbol !== undefined) {
1465
+ market = this.market (symbol);
1466
+ }
1467
+ const [ marketType, query ] = this.handleMarketTypeAndParams ('cancelOrder', market, params);
1468
+ const method = this.getSupportedMapping (marketType, {
1469
+ 'spot': 'privateDeleteSpotOrderClientOrderId',
1470
+ 'swap': 'privateDeleteFuturesOrderClientOrderId',
1471
+ 'margin': 'privateDeleteMarginOrderClientOrderId',
1472
+ });
1473
+ const response = await this[method] (this.extend (request, query));
1474
+ return this.parseOrder (response, market);
1475
+ }
1476
+
1477
+ async editOrder (id, symbol, type, side, amount, price = undefined, params = {}) {
1478
+ await this.loadMarkets ();
1479
+ let market = undefined;
1480
+ const request = {
1481
+ 'client_order_id': id,
1482
+ 'quantity': this.amountToPrecision (symbol, amount),
1483
+ };
1484
+ if ((type === 'limit') || (type === 'stopLimit')) {
1485
+ if (price === undefined) {
1486
+ throw new ExchangeError (this.id + ' editOrder() limit order requires price');
1487
+ }
1488
+ request['price'] = this.priceToPrecision (symbol, price);
1489
+ }
1490
+ if (symbol !== undefined) {
1491
+ market = this.market (symbol);
1492
+ }
1493
+ const [ marketType, query ] = this.handleMarketTypeAndParams ('editOrder', market, params);
1494
+ const method = this.getSupportedMapping (marketType, {
1495
+ 'spot': 'privatePatchSpotOrderClientOrderId',
1496
+ 'swap': 'privatePatchFuturesOrderClientOrderId',
1497
+ 'margin': 'privatePatchMarginOrderClientOrderId',
1498
+ });
1499
+ const response = await this[method] (this.extend (request, query));
1500
+ return this.parseOrder (response, market);
1501
+ }
1502
+
1503
+ async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
1504
+ await this.loadMarkets ();
1505
+ const market = this.market (symbol);
1506
+ const reduceOnly = this.safeValue2 (params, 'reduce_only', 'reduceOnly');
1507
+ if (reduceOnly !== undefined) {
1508
+ if ((market['type'] !== 'swap') && (market['type'] !== 'margin')) {
1509
+ throw new InvalidOrder (this.id + ' createOrder() does not support reduce_only for ' + market['type'] + ' orders, reduce_only orders are supported for swap and margin markets only');
1510
+ }
1511
+ }
1512
+ const request = {
1513
+ 'type': type,
1514
+ 'side': side,
1515
+ 'quantity': this.amountToPrecision (symbol, amount),
1516
+ 'symbol': market['id'],
1517
+ // 'client_order_id': 'r42gdPjNMZN-H_xs8RKl2wljg_dfgdg4', // Optional
1518
+ // 'time_in_force': 'GTC', // Optional GTC, IOC, FOK, Day, GTD
1519
+ // 'price': this.priceToPrecision (symbol, price), // Required if type is limit, stopLimit, or takeProfitLimit
1520
+ // 'stop_price': this.safeNumber (params, 'stop_price'), // Required if type is stopLimit, stopMarket, takeProfitLimit, takeProfitMarket
1521
+ // 'expire_time': '2021-06-15T17:01:05.092Z', // Required if timeInForce is GTD
1522
+ // 'strict_validate': false,
1523
+ // 'post_only': false, // Optional
1524
+ // 'reduce_only': false, // Optional
1525
+ // 'display_quantity': '0', // Optional
1526
+ // 'take_rate': 0.001, // Optional
1527
+ // 'make_rate': 0.001, // Optional
1528
+ };
1529
+ const timeInForce = this.safeString2 (params, 'timeInForce', 'time_in_force');
1530
+ const expireTime = this.safeString (params, 'expire_time');
1531
+ const stopPrice = this.safeNumber2 (params, 'stopPrice', 'stop_price');
1532
+ if ((type === 'limit') || (type === 'stopLimit') || (type === 'takeProfitLimit')) {
1533
+ if (price === undefined) {
1534
+ throw new ExchangeError (this.id + ' createOrder() requires a price argument for limit orders');
1535
+ }
1536
+ request['price'] = this.priceToPrecision (symbol, price);
1537
+ }
1538
+ if ((timeInForce === 'GTD')) {
1539
+ if (expireTime === undefined) {
1540
+ throw new ExchangeError (this.id + ' createOrder() requires an expire_time parameter for a GTD order');
1541
+ }
1542
+ request['expire_time'] = expireTime;
1543
+ }
1544
+ if ((type === 'stopLimit') || (type === 'stopMarket') || (type === 'takeProfitLimit') || (type === 'takeProfitMarket')) {
1545
+ if (stopPrice === undefined) {
1546
+ throw new ExchangeError (this.id + ' createOrder() requires a stopPrice parameter for stop-loss and take-profit orders');
1547
+ }
1548
+ request['stop_price'] = this.priceToPrecision (symbol, stopPrice);
1549
+ }
1550
+ const [ marketType, query ] = this.handleMarketTypeAndParams ('createOrder', market, params);
1551
+ const method = this.getSupportedMapping (marketType, {
1552
+ 'spot': 'privatePostSpotOrder',
1553
+ 'swap': 'privatePostFuturesOrder',
1554
+ 'margin': 'privatePostMarginOrder',
1555
+ });
1556
+ const response = await this[method] (this.extend (request, query));
1557
+ return this.parseOrder (response, market);
1558
+ }
1559
+
1560
+ async createReduceOnlyOrder (symbol, type, side, amount, price = undefined, params = {}) {
1561
+ const request = {
1562
+ 'reduce_only': true,
1563
+ };
1564
+ return await this.createOrder (symbol, type, side, amount, price, this.extend (request, params));
1565
+ }
1566
+
1567
+ parseOrderStatus (status) {
1568
+ const statuses = {
1569
+ 'new': 'open',
1570
+ 'suspended': 'open',
1571
+ 'partiallyFilled': 'open',
1572
+ 'filled': 'closed',
1573
+ 'canceled': 'canceled',
1574
+ 'expired': 'failed',
1575
+ };
1576
+ return this.safeString (statuses, status, status);
1577
+ }
1578
+
1579
+ parseOrder (order, market = undefined) {
1580
+ //
1581
+ // limit
1582
+ // {
1583
+ // "id": 488953123149,
1584
+ // "client_order_id": "103ad305301e4c3590045b13de15b36e",
1585
+ // "symbol": "BTCUSDT",
1586
+ // "side": "buy",
1587
+ // "status": "new",
1588
+ // "type": "limit",
1589
+ // "time_in_force": "GTC",
1590
+ // "quantity": "0.00001",
1591
+ // "quantity_cumulative": "0",
1592
+ // "price": "0.01",
1593
+ // "price_average": "0.01",
1594
+ // "post_only": false,
1595
+ // "created_at": "2021-04-13T13:06:16.567Z",
1596
+ // "updated_at": "2021-04-13T13:06:16.567Z"
1597
+ // }
1598
+ //
1599
+ // market
1600
+ // {
1601
+ // "id": "685877626834",
1602
+ // "client_order_id": "Yshl7G-EjaREyXQYaGbsmdtVbW-nzQwu",
1603
+ // "symbol": "BTCUSDT",
1604
+ // "side": "buy",
1605
+ // "status": "filled",
1606
+ // "type": "market",
1607
+ // "time_in_force": "GTC",
1608
+ // "quantity": "0.00010",
1609
+ // "quantity_cumulative": "0.00010",
1610
+ // "post_only": false,
1611
+ // "created_at": "2021-10-26T08:55:55.1Z",
1612
+ // "updated_at": "2021-10-26T08:55:55.1Z",
1613
+ // "trades": [
1614
+ // {
1615
+ // "id": "1437229630",
1616
+ // "position_id": "0",
1617
+ // "quantity": "0.00010",
1618
+ // "price": "62884.78",
1619
+ // "fee": "0.005659630200",
1620
+ // "timestamp": "2021-10-26T08:55:55.1Z",
1621
+ // "taker": true
1622
+ // }
1623
+ // ]
1624
+ // }
1625
+ //
1626
+ // swap and margin
1627
+ //
1628
+ // {
1629
+ // "id": 58418961892,
1630
+ // "client_order_id": "r42gdPjNMZN-H_xs8RKl2wljg_dfgdg4",
1631
+ // "symbol": "BTCUSDT_PERP",
1632
+ // "side": "buy",
1633
+ // "status": "new",
1634
+ // "type": "limit",
1635
+ // "time_in_force": "GTC",
1636
+ // "quantity": "0.0005",
1637
+ // "quantity_cumulative": "0",
1638
+ // "price": "30000.00",
1639
+ // "post_only": false,
1640
+ // "reduce_only": false,
1641
+ // "created_at": "2022-03-16T08:16:53.039Z",
1642
+ // "updated_at": "2022-03-16T08:16:53.039Z"
1643
+ // }
1644
+ //
1645
+ const id = this.safeString (order, 'client_order_id');
1646
+ // we use clientOrderId as the order id with this exchange intentionally
1647
+ // because most of their endpoints will require clientOrderId
1648
+ // explained here: https://github.com/ccxt/ccxt/issues/5674
1649
+ const side = this.safeString (order, 'side');
1650
+ const type = this.safeString (order, 'type');
1651
+ const amount = this.safeString (order, 'quantity');
1652
+ const price = this.safeString (order, 'price');
1653
+ const average = this.safeString (order, 'price_average');
1654
+ const created = this.safeString (order, 'created_at');
1655
+ const timestamp = this.parse8601 (created);
1656
+ const updated = this.safeString (order, 'updated_at');
1657
+ let lastTradeTimestamp = undefined;
1658
+ if (updated !== created) {
1659
+ lastTradeTimestamp = this.parse8601 (updated);
1660
+ }
1661
+ const filled = this.safeString (order, 'quantity_cumulative');
1662
+ const status = this.parseOrderStatus (this.safeString (order, 'status'));
1663
+ const marketId = this.safeString (order, 'symbol');
1664
+ market = this.safeMarket (marketId, market);
1665
+ const symbol = market['symbol'];
1666
+ const postOnly = this.safeValue (order, 'post_only');
1667
+ const timeInForce = this.safeString (order, 'time_in_force');
1668
+ const rawTrades = this.safeValue (order, 'trades');
1669
+ return this.safeOrder ({
1670
+ 'info': order,
1671
+ 'id': id,
1672
+ 'clientOrderId': id,
1673
+ 'timestamp': timestamp,
1674
+ 'datetime': this.iso8601 (timestamp),
1675
+ 'lastTradeTimestamp': lastTradeTimestamp,
1676
+ 'symbol': symbol,
1677
+ 'price': price,
1678
+ 'amount': amount,
1679
+ 'type': type,
1680
+ 'side': side,
1681
+ 'timeInForce': timeInForce,
1682
+ 'postOnly': postOnly,
1683
+ 'filled': filled,
1684
+ 'remaining': undefined,
1685
+ 'cost': undefined,
1686
+ 'status': status,
1687
+ 'average': average,
1688
+ 'trades': rawTrades,
1689
+ 'fee': undefined,
1690
+ }, market);
1691
+ }
1692
+
1693
+ async transfer (code, amount, fromAccount, toAccount, params = {}) {
1694
+ // account can be "spot", "wallet", or "derivatives"
1695
+ await this.loadMarkets ();
1696
+ const currency = this.currency (code);
1697
+ const requestAmount = this.currencyToPrecision (code, amount);
1698
+ const accountsByType = this.safeValue (this.options, 'accountsByType', {});
1699
+ fromAccount = fromAccount.toLowerCase ();
1700
+ toAccount = toAccount.toLowerCase ();
1701
+ const fromId = this.safeString (accountsByType, fromAccount, fromAccount);
1702
+ const toId = this.safeString (accountsByType, toAccount, toAccount);
1703
+ if (fromId === toId) {
1704
+ throw new BadRequest (this.id + ' transfer() fromAccount and toAccount arguments cannot be the same account');
1705
+ }
1706
+ const request = {
1707
+ 'currency': currency['id'],
1708
+ 'amount': requestAmount,
1709
+ 'source': fromId,
1710
+ 'destination': toId,
1711
+ };
1712
+ const response = await this.privatePostWalletTransfer (this.extend (request, params));
1713
+ //
1714
+ // [
1715
+ // '2db6ebab-fb26-4537-9ef8-1a689472d236'
1716
+ // ]
1717
+ //
1718
+ const transfer = this.parseTransfer (response, currency);
1719
+ return this.extend (transfer, {
1720
+ 'fromAccount': fromAccount,
1721
+ 'toAccount': toAccount,
1722
+ 'amount': this.parseNumber (requestAmount),
1723
+ });
1724
+ }
1725
+
1726
+ parseTransfer (transfer, currency = undefined) {
1727
+ //
1728
+ // transfer
1729
+ //
1730
+ // [
1731
+ // '2db6ebab-fb26-4537-9ef8-1a689472d236'
1732
+ // ]
1733
+ //
1734
+ const timestamp = this.milliseconds ();
1735
+ return {
1736
+ 'id': this.safeString (transfer, 0),
1737
+ 'timestamp': timestamp,
1738
+ 'datetime': this.iso8601 (timestamp),
1739
+ 'currency': this.safeCurrencyCode (undefined, currency),
1740
+ 'amount': undefined,
1741
+ 'fromAccount': undefined,
1742
+ 'toAccount': undefined,
1743
+ 'status': undefined,
1744
+ 'info': transfer,
1745
+ };
1746
+ }
1747
+
1748
+ async convertCurrencyNetwork (code, amount, fromNetwork, toNetwork, params) {
1749
+ await this.loadMarkets ();
1750
+ if (code !== 'USDT') {
1751
+ throw new ExchangeError (this.id + ' convertCurrencyNetwork() only supports USDT currently');
1752
+ }
1753
+ const networks = this.safeValue (this.options, 'networks', {});
1754
+ fromNetwork = fromNetwork.toUpperCase ();
1755
+ toNetwork = toNetwork.toUpperCase ();
1756
+ fromNetwork = this.safeString (networks, fromNetwork); // handle ETH>ERC20 alias
1757
+ toNetwork = this.safeString (networks, toNetwork); // handle ETH>ERC20 alias
1758
+ if (fromNetwork === toNetwork) {
1759
+ throw new BadRequest (this.id + ' convertCurrencyNetwork() fromNetwork cannot be the same as toNetwork');
1760
+ }
1761
+ if ((fromNetwork === undefined) || (toNetwork === undefined)) {
1762
+ const keys = Object.keys (networks);
1763
+ throw new ArgumentsRequired (this.id + ' convertCurrencyNetwork() requires a fromNetwork parameter and a toNetwork parameter, supported networks are ' + keys.join (', '));
1764
+ }
1765
+ const request = {
1766
+ 'from_currency': fromNetwork,
1767
+ 'to_currency': toNetwork,
1768
+ 'amount': this.currencyToPrecision (code, amount),
1769
+ };
1770
+ const response = await this.privatePostWalletConvert (this.extend (request, params));
1771
+ // {"result":["587a1868-e62d-4d8e-b27c-dbdb2ee96149","e168df74-c041-41f2-b76c-e43e4fed5bc7"]}
1772
+ return {
1773
+ 'info': response,
1774
+ };
1775
+ }
1776
+
1777
+ async withdraw (code, amount, address, tag = undefined, params = {}) {
1778
+ [ tag, params ] = this.handleWithdrawTagAndParams (tag, params);
1779
+ await this.loadMarkets ();
1780
+ this.checkAddress (address);
1781
+ const currency = this.currency (code);
1782
+ const request = {
1783
+ 'currency': currency['id'],
1784
+ 'amount': amount,
1785
+ 'address': address,
1786
+ };
1787
+ if (tag !== undefined) {
1788
+ request['payment_id'] = tag;
1789
+ }
1790
+ const networks = this.safeValue (this.options, 'networks', {});
1791
+ const network = this.safeStringUpper (params, 'network');
1792
+ if ((network !== undefined) && (code === 'USDT')) {
1793
+ const parsedNetwork = this.safeString (networks, network);
1794
+ if (parsedNetwork !== undefined) {
1795
+ request['currency'] = parsedNetwork;
1796
+ }
1797
+ params = this.omit (params, 'network');
1798
+ }
1799
+ const response = await this.privatePostWalletCryptoWithdraw (this.extend (request, params));
1800
+ //
1801
+ // {
1802
+ // "id":"084cfcd5-06b9-4826-882e-fdb75ec3625d"
1803
+ // }
1804
+ //
1805
+ return this.parseTransaction (response, currency);
1806
+ }
1807
+
1808
+ async fetchFundingRateHistory (symbol = undefined, since = undefined, limit = undefined, params = {}) {
1809
+ await this.loadMarkets ();
1810
+ let market = undefined;
1811
+ const request = {
1812
+ // all arguments are optional
1813
+ // 'symbols': Comma separated list of symbol codes,
1814
+ // 'sort': 'DESC' or 'ASC'
1815
+ // 'from': 'Datetime or Number',
1816
+ // 'till': 'Datetime or Number',
1817
+ // 'limit': 100,
1818
+ // 'offset': 0,
1819
+ };
1820
+ if (symbol !== undefined) {
1821
+ market = this.market (symbol);
1822
+ symbol = market['symbol'];
1823
+ request['symbols'] = market['id'];
1824
+ }
1825
+ if (since !== undefined) {
1826
+ request['from'] = since;
1827
+ }
1828
+ if (limit !== undefined) {
1829
+ request['limit'] = limit;
1830
+ }
1831
+ const response = await this.publicGetPublicFuturesHistoryFunding (this.extend (request, params));
1832
+ //
1833
+ // {
1834
+ // "BTCUSDT_PERP": [
1835
+ // {
1836
+ // "timestamp": "2021-07-29T16:00:00.271Z",
1837
+ // "funding_rate": "0.0001",
1838
+ // "avg_premium_index": "0.000061858585213222",
1839
+ // "next_funding_time": "2021-07-30T00:00:00.000Z",
1840
+ // "interest_rate": "0.0001"
1841
+ // },
1842
+ // ...
1843
+ // ],
1844
+ // ...
1845
+ // }
1846
+ //
1847
+ const contracts = Object.keys (response);
1848
+ const rates = [];
1849
+ for (let i = 0; i < contracts.length; i++) {
1850
+ const marketId = contracts[i];
1851
+ const market = this.safeMarket (marketId);
1852
+ const fundingRateData = response[marketId];
1853
+ for (let i = 0; i < fundingRateData.length; i++) {
1854
+ const entry = fundingRateData[i];
1855
+ const symbol = this.safeSymbol (market['symbol']);
1856
+ const fundingRate = this.safeNumber (entry, 'funding_rate');
1857
+ const datetime = this.safeString (entry, 'timestamp');
1858
+ rates.push ({
1859
+ 'info': entry,
1860
+ 'symbol': symbol,
1861
+ 'fundingRate': fundingRate,
1862
+ 'timestamp': this.parse8601 (datetime),
1863
+ 'datetime': datetime,
1864
+ });
1865
+ }
1866
+ }
1867
+ const sorted = this.sortBy (rates, 'timestamp');
1868
+ return this.filterBySymbolSinceLimit (sorted, symbol, since, limit);
1869
+ }
1870
+
1871
+ async fetchPositions (symbols = undefined, params = {}) {
1872
+ await this.loadMarkets ();
1873
+ const request = {};
1874
+ const [ marketType, query ] = this.handleMarketTypeAndParams ('fetchPositions', undefined, params);
1875
+ const method = this.getSupportedMapping (marketType, {
1876
+ 'swap': 'privateGetFuturesAccount',
1877
+ 'margin': 'privateGetMarginAccount',
1878
+ });
1879
+ const response = await this[method] (this.extend (request, query));
1880
+ //
1881
+ // [
1882
+ // {
1883
+ // "symbol": "ETHUSDT_PERP",
1884
+ // "type": "isolated",
1885
+ // "leverage": "10.00",
1886
+ // "created_at": "2022-03-19T07:54:35.24Z",
1887
+ // "updated_at": "2022-03-19T07:54:58.922Z",
1888
+ // currencies": [
1889
+ // {
1890
+ // "code": "USDT",
1891
+ // "margin_balance": "7.478100643043",
1892
+ // "reserved_orders": "0",
1893
+ // "reserved_positions": "0.303530761300"
1894
+ // }
1895
+ // ],
1896
+ // "positions": [
1897
+ // {
1898
+ // "id": 2470568,
1899
+ // "symbol": "ETHUSDT_PERP",
1900
+ // "quantity": "0.001",
1901
+ // "price_entry": "2927.509",
1902
+ // "price_margin_call": "0",
1903
+ // "price_liquidation": "0",
1904
+ // "pnl": "0",
1905
+ // "created_at": "2022-03-19T07:54:35.24Z",
1906
+ // "updated_at": "2022-03-19T07:54:58.922Z"
1907
+ // }
1908
+ // ]
1909
+ // },
1910
+ // ]
1911
+ //
1912
+ const result = [];
1913
+ for (let i = 0; i < response.length; i++) {
1914
+ result.push (this.parsePosition (response[i]));
1915
+ }
1916
+ return result;
1917
+ }
1918
+
1919
+ async fetchPosition (symbol, params = {}) {
1920
+ await this.loadMarkets ();
1921
+ const market = this.market (symbol);
1922
+ const [ marketType, query ] = this.handleMarketTypeAndParams ('fetchPosition', market, params);
1923
+ const method = this.getSupportedMapping (marketType, {
1924
+ 'swap': 'privateGetFuturesAccountIsolatedSymbol',
1925
+ 'margin': 'privateGetMarginAccountIsolatedSymbol',
1926
+ });
1927
+ const request = {
1928
+ 'symbol': market['id'],
1929
+ };
1930
+ const response = await this[method] (this.extend (request, query));
1931
+ //
1932
+ // [
1933
+ // {
1934
+ // "symbol": "ETHUSDT_PERP",
1935
+ // "type": "isolated",
1936
+ // "leverage": "10.00",
1937
+ // "created_at": "2022-03-19T07:54:35.24Z",
1938
+ // "updated_at": "2022-03-19T07:54:58.922Z",
1939
+ // currencies": [
1940
+ // {
1941
+ // "code": "USDT",
1942
+ // "margin_balance": "7.478100643043",
1943
+ // "reserved_orders": "0",
1944
+ // "reserved_positions": "0.303530761300"
1945
+ // }
1946
+ // ],
1947
+ // "positions": [
1948
+ // {
1949
+ // "id": 2470568,
1950
+ // "symbol": "ETHUSDT_PERP",
1951
+ // "quantity": "0.001",
1952
+ // "price_entry": "2927.509",
1953
+ // "price_margin_call": "0",
1954
+ // "price_liquidation": "0",
1955
+ // "pnl": "0",
1956
+ // "created_at": "2022-03-19T07:54:35.24Z",
1957
+ // "updated_at": "2022-03-19T07:54:58.922Z"
1958
+ // }
1959
+ // ]
1960
+ // },
1961
+ // ]
1962
+ //
1963
+ return this.parsePosition (response, market);
1964
+ }
1965
+
1966
+ parsePosition (position, market = undefined) {
1967
+ //
1968
+ // [
1969
+ // {
1970
+ // "symbol": "ETHUSDT_PERP",
1971
+ // "type": "isolated",
1972
+ // "leverage": "10.00",
1973
+ // "created_at": "2022-03-19T07:54:35.24Z",
1974
+ // "updated_at": "2022-03-19T07:54:58.922Z",
1975
+ // currencies": [
1976
+ // {
1977
+ // "code": "USDT",
1978
+ // "margin_balance": "7.478100643043",
1979
+ // "reserved_orders": "0",
1980
+ // "reserved_positions": "0.303530761300"
1981
+ // }
1982
+ // ],
1983
+ // "positions": [
1984
+ // {
1985
+ // "id": 2470568,
1986
+ // "symbol": "ETHUSDT_PERP",
1987
+ // "quantity": "0.001",
1988
+ // "price_entry": "2927.509",
1989
+ // "price_margin_call": "0",
1990
+ // "price_liquidation": "0",
1991
+ // "pnl": "0",
1992
+ // "created_at": "2022-03-19T07:54:35.24Z",
1993
+ // "updated_at": "2022-03-19T07:54:58.922Z"
1994
+ // }
1995
+ // ]
1996
+ // },
1997
+ // ]
1998
+ //
1999
+ const marginType = this.safeString (position, 'type');
2000
+ const leverage = this.safeNumber (position, 'leverage');
2001
+ const datetime = this.safeString (position, 'updated_at');
2002
+ const positions = this.safeValue (position, 'positions', []);
2003
+ let liquidationPrice = undefined;
2004
+ let entryPrice = undefined;
2005
+ let contracts = undefined;
2006
+ for (let i = 0; i < positions.length; i++) {
2007
+ const entry = positions[i];
2008
+ liquidationPrice = this.safeNumber (entry, 'price_liquidation');
2009
+ entryPrice = this.safeNumber (entry, 'price_entry');
2010
+ contracts = this.safeNumber (entry, 'quantity');
2011
+ }
2012
+ const currencies = this.safeValue (position, 'currencies', []);
2013
+ let collateral = undefined;
2014
+ for (let i = 0; i < currencies.length; i++) {
2015
+ const entry = currencies[i];
2016
+ collateral = this.safeNumber (entry, 'margin_balance');
2017
+ }
2018
+ const marketId = this.safeString (position, 'symbol');
2019
+ market = this.safeMarket (marketId, market);
2020
+ const symbol = market['symbol'];
2021
+ return {
2022
+ 'info': position,
2023
+ 'symbol': symbol,
2024
+ 'notional': undefined,
2025
+ 'marginType': marginType,
2026
+ 'liquidationPrice': liquidationPrice,
2027
+ 'entryPrice': entryPrice,
2028
+ 'unrealizedPnl': undefined,
2029
+ 'percentage': undefined,
2030
+ 'contracts': contracts,
2031
+ 'contractSize': undefined,
2032
+ 'markPrice': undefined,
2033
+ 'side': undefined,
2034
+ 'hedged': undefined,
2035
+ 'timestamp': this.parse8601 (datetime),
2036
+ 'datetime': datetime,
2037
+ 'maintenanceMargin': undefined,
2038
+ 'maintenanceMarginPercentage': undefined,
2039
+ 'collateral': collateral,
2040
+ 'initialMargin': undefined,
2041
+ 'initialMarginPercentage': undefined,
2042
+ 'leverage': leverage,
2043
+ 'marginRatio': undefined,
2044
+ };
2045
+ }
2046
+
2047
+ async fetchFundingRate (symbol, params = {}) {
2048
+ await this.loadMarkets ();
2049
+ const market = this.market (symbol);
2050
+ if (!market['swap']) {
2051
+ throw new BadSymbol (this.id + ' fetchFundingRate() supports swap contracts only');
2052
+ }
2053
+ const request = {};
2054
+ if (symbol !== undefined) {
2055
+ symbol = market['symbol'];
2056
+ request['symbols'] = market['id'];
2057
+ }
2058
+ const response = await this.publicGetPublicFuturesInfo (this.extend (request, params));
2059
+ //
2060
+ // {
2061
+ // "BTCUSDT_PERP": {
2062
+ // "contract_type": "perpetual",
2063
+ // "mark_price": "42307.43",
2064
+ // "index_price": "42303.27",
2065
+ // "funding_rate": "0.0001",
2066
+ // "open_interest": "30.9826",
2067
+ // "next_funding_time": "2022-03-22T16:00:00.000Z",
2068
+ // "indicative_funding_rate": "0.0001",
2069
+ // "premium_index": "0",
2070
+ // "avg_premium_index": "0.000029587712038098",
2071
+ // "interest_rate": "0.0001",
2072
+ // "timestamp": "2022-03-22T08:08:26.687Z"
2073
+ // }
2074
+ // }
2075
+ //
2076
+ const data = this.safeValue (response, market['id'], {});
2077
+ return this.parseFundingRate (data, market);
2078
+ }
2079
+
2080
+ parseFundingRate (contract, market = undefined) {
2081
+ //
2082
+ // {
2083
+ // "contract_type": "perpetual",
2084
+ // "mark_price": "42307.43",
2085
+ // "index_price": "42303.27",
2086
+ // "funding_rate": "0.0001",
2087
+ // "open_interest": "30.9826",
2088
+ // "next_funding_time": "2022-03-22T16:00:00.000Z",
2089
+ // "indicative_funding_rate": "0.0001",
2090
+ // "premium_index": "0",
2091
+ // "avg_premium_index": "0.000029587712038098",
2092
+ // "interest_rate": "0.0001",
2093
+ // "timestamp": "2022-03-22T08:08:26.687Z"
2094
+ // }
2095
+ //
2096
+ const nextFundingDatetime = this.safeString (contract, 'next_funding_time');
2097
+ const datetime = this.safeString (contract, 'timestamp');
2098
+ return {
2099
+ 'info': contract,
2100
+ 'symbol': this.safeSymbol (undefined, market),
2101
+ 'markPrice': this.safeNumber (contract, 'mark_price'),
2102
+ 'indexPrice': this.safeNumber (contract, 'index_price'),
2103
+ 'interestRate': this.safeNumber (contract, 'interest_rate'),
2104
+ 'estimatedSettlePrice': undefined,
2105
+ 'timestamp': this.parse8601 (datetime),
2106
+ 'datetime': datetime,
2107
+ 'fundingRate': this.safeNumber (contract, 'funding_rate'),
2108
+ 'fundingTimestamp': undefined,
2109
+ 'fundingDatetime': undefined,
2110
+ 'nextFundingRate': this.safeNumber (contract, 'indicative_funding_rate'),
2111
+ 'nextFundingTimestamp': this.parse8601 (nextFundingDatetime),
2112
+ 'nextFundingDatetime': nextFundingDatetime,
2113
+ 'previousFundingRate': undefined,
2114
+ 'previousFundingTimestamp': undefined,
2115
+ 'previousFundingDatetime': undefined,
2116
+ };
2117
+ }
2118
+
2119
+ async modifyMarginHelper (symbol, amount, type, params = {}) {
2120
+ await this.loadMarkets ();
2121
+ const market = this.market (symbol);
2122
+ const leverage = this.safeString (params, 'leverage');
2123
+ if (market['type'] === 'swap') {
2124
+ if (leverage === undefined) {
2125
+ throw new ArgumentsRequired (this.id + ' modifyMarginHelper() requires a leverage parameter for swap markets');
2126
+ }
2127
+ }
2128
+ amount = this.amountToPrecision (symbol, amount);
2129
+ const request = {
2130
+ 'symbol': market['id'], // swap and margin
2131
+ 'margin_balance': amount, // swap and margin
2132
+ // 'leverage': '10', // swap only required
2133
+ // 'strict_validate': false, // swap and margin
2134
+ };
2135
+ if (leverage !== undefined) {
2136
+ request['leverage'] = leverage;
2137
+ }
2138
+ const [ marketType, query ] = this.handleMarketTypeAndParams ('modifyMarginHelper', market, params);
2139
+ const method = this.getSupportedMapping (marketType, {
2140
+ 'swap': 'privatePutFuturesAccountIsolatedSymbol',
2141
+ 'margin': 'privatePutMarginAccountIsolatedSymbol',
2142
+ });
2143
+ const response = await this[method] (this.extend (request, query));
2144
+ //
2145
+ // {
2146
+ // "symbol": "BTCUSDT_PERP",
2147
+ // "type": "isolated",
2148
+ // "leverage": "8.00",
2149
+ // "created_at": "2022-03-30T23:34:27.161Z",
2150
+ // "updated_at": "2022-03-30T23:34:27.161Z",
2151
+ // "currencies": [
2152
+ // {
2153
+ // "code": "USDT",
2154
+ // "margin_balance": "7.000000000000",
2155
+ // "reserved_orders": "0",
2156
+ // "reserved_positions": "0"
2157
+ // }
2158
+ // ],
2159
+ // "positions": null
2160
+ // }
2161
+ //
2162
+ return this.extend (this.parseModifyMargin (response, market), {
2163
+ 'amount': this.safeNumber (amount),
2164
+ 'type': type,
2165
+ });
2166
+ }
2167
+
2168
+ parseModifyMargin (data, market = undefined) {
2169
+ const currencies = this.safeValue (data, 'currencies', []);
2170
+ const currencyInfo = this.safeValue (currencies, 0);
2171
+ return {
2172
+ 'info': data,
2173
+ 'type': undefined,
2174
+ 'amount': undefined,
2175
+ 'code': this.safeString (currencyInfo, 'code'),
2176
+ 'symbol': market['symbol'],
2177
+ 'status': undefined,
2178
+ };
2179
+ }
2180
+
2181
+ async reduceMargin (symbol, amount, params = {}) {
2182
+ if (amount !== 0) {
2183
+ throw new BadRequest (this.id + ' reduceMargin() on hitbtc3 requires the amount to be 0 and that will remove the entire margin amount');
2184
+ }
2185
+ return await this.modifyMarginHelper (symbol, amount, 'reduce', params);
2186
+ }
2187
+
2188
+ async addMargin (symbol, amount, params = {}) {
2189
+ return await this.modifyMarginHelper (symbol, amount, 'add', params);
2190
+ }
2191
+
2192
+ async fetchLeverage (symbol, params = {}) {
2193
+ await this.loadMarkets ();
2194
+ const market = this.market (symbol);
2195
+ const request = {
2196
+ 'symbol': market['id'],
2197
+ };
2198
+ const method = this.getSupportedMapping (market['type'], {
2199
+ 'spot': 'privateGetMarginAccountIsolatedSymbol',
2200
+ 'margin': 'privateGetMarginAccountIsolatedSymbol',
2201
+ 'swap': 'privateGetFuturesAccountIsolatedSymbol',
2202
+ });
2203
+ const response = await this[method] (this.extend (request, params));
2204
+ //
2205
+ // {
2206
+ // "symbol": "BTCUSDT",
2207
+ // "type": "isolated",
2208
+ // "leverage": "12.00",
2209
+ // "created_at": "2022-03-29T22:31:29.067Z",
2210
+ // "updated_at": "2022-03-30T00:00:00.125Z",
2211
+ // "currencies": [
2212
+ // {
2213
+ // "code": "USDT",
2214
+ // "margin_balance": "20.824360374174",
2215
+ // "reserved_orders": "0",
2216
+ // "reserved_positions": "0.973330435000"
2217
+ // }
2218
+ // ],
2219
+ // "positions": [
2220
+ // {
2221
+ // "id": 631301,
2222
+ // "symbol": "BTCUSDT",
2223
+ // "quantity": "0.00022",
2224
+ // "price_entry": "47425.57",
2225
+ // "price_margin_call": "",
2226
+ // "price_liquidation": "0",
2227
+ // "pnl": "0",
2228
+ // "created_at": "2022-03-29T22:31:29.067Z",
2229
+ // "updated_at": "2022-03-30T00:00:00.125Z"
2230
+ // }
2231
+ // ]
2232
+ // }
2233
+ //
2234
+ return this.safeNumber (response, 'leverage');
2235
+ }
2236
+
2237
+ async setLeverage (leverage, symbol = undefined, params = {}) {
2238
+ await this.loadMarkets ();
2239
+ if (symbol === undefined) {
2240
+ throw new ArgumentsRequired (this.id + ' setLeverage() requires a symbol argument');
2241
+ }
2242
+ if (params['margin_balance'] === undefined) {
2243
+ throw new ArgumentsRequired (this.id + ' setLeverage() requires a margin_balance parameter that will transfer margin to the specified trading pair');
2244
+ }
2245
+ const market = this.market (symbol);
2246
+ const amount = this.safeNumber (params, 'margin_balance');
2247
+ const maxLeverage = this.safeInteger (market['limits']['leverage'], 'max', 50);
2248
+ if (market['type'] !== 'swap') {
2249
+ throw new BadSymbol (this.id + ' setLeverage() supports swap contracts only');
2250
+ }
2251
+ if ((leverage < 1) || (leverage > maxLeverage)) {
2252
+ throw new BadRequest (this.id + ' setLeverage() leverage should be between 1 and ' + maxLeverage.toString () + ' for ' + symbol);
2253
+ }
2254
+ const request = {
2255
+ 'symbol': market['id'],
2256
+ 'leverage': leverage.toString (),
2257
+ 'margin_balance': this.amountToPrecision (symbol, amount),
2258
+ // 'strict_validate': false,
2259
+ };
2260
+ return await this.privatePutFuturesAccountIsolatedSymbol (this.extend (request, params));
2261
+ }
2262
+
2263
+ handleErrors (code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
2264
+ //
2265
+ // {
2266
+ // "error": {
2267
+ // "code": 20001,
2268
+ // "message": "Insufficient funds",
2269
+ // "description": "Check that the funds are sufficient, given commissions"
2270
+ // }
2271
+ // }
2272
+ //
2273
+ // {
2274
+ // "error": {
2275
+ // "code": "600",
2276
+ // "message": "Action not allowed"
2277
+ // }
2278
+ // }
2279
+ //
2280
+ const error = this.safeValue (response, 'error');
2281
+ const errorCode = this.safeString (error, 'code');
2282
+ if (errorCode !== undefined) {
2283
+ const feedback = this.id + ' ' + body;
2284
+ const message = this.safeString2 (error, 'message', 'description');
2285
+ this.throwExactlyMatchedException (this.exceptions['exact'], errorCode, feedback);
2286
+ this.throwBroadlyMatchedException (this.exceptions['broad'], message, feedback);
2287
+ throw new ExchangeError (feedback);
2288
+ }
2289
+ }
2290
+
2291
+ sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
2292
+ const query = this.omit (params, this.extractParams (path));
2293
+ const implodedPath = this.implodeParams (path, params);
2294
+ let url = this.urls['api'][api] + '/' + implodedPath;
2295
+ let getRequest = undefined;
2296
+ const keys = Object.keys (query);
2297
+ const queryLength = keys.length;
2298
+ headers = {
2299
+ 'Content-Type': 'application/json',
2300
+ };
2301
+ if (method === 'GET') {
2302
+ if (queryLength) {
2303
+ getRequest = '?' + this.urlencode (query);
2304
+ url = url + getRequest;
2305
+ }
2306
+ } else {
2307
+ body = this.json (params);
2308
+ }
2309
+ if (api === 'private') {
2310
+ this.checkRequiredCredentials ();
2311
+ const timestamp = this.nonce ().toString ();
2312
+ const payload = [ method, '/api/3/' + implodedPath ];
2313
+ if (method === 'GET') {
2314
+ if (getRequest !== undefined) {
2315
+ payload.push (getRequest);
2316
+ }
2317
+ } else {
2318
+ payload.push (body);
2319
+ }
2320
+ payload.push (timestamp);
2321
+ const payloadString = payload.join ('');
2322
+ const signature = this.hmac (this.encode (payloadString), this.encode (this.secret), 'sha256', 'hex');
2323
+ const secondPayload = this.apiKey + ':' + signature + ':' + timestamp;
2324
+ const encoded = this.decode (this.stringToBase64 (secondPayload));
2325
+ headers['Authorization'] = 'HS256 ' + encoded;
2326
+ }
2327
+ return { 'url': url, 'method': method, 'body': body, 'headers': headers };
2328
+ }
2329
+ };