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/fairdesk.js ADDED
@@ -0,0 +1,1231 @@
1
+ 'use strict';
2
+
3
+ // ----------------------------------------------------------------------------
4
+
5
+ const Exchange = require ('./base/Exchange');
6
+ const { ExchangeError, AuthenticationError, ArgumentsRequired, OrderNotFound, BadRequest, PermissionDenied, RateLimitExceeded } = require ('./base/errors');
7
+ const { TICK_SIZE } = require ('./base/functions/number');
8
+ const Precise = require ('./base/Precise');
9
+
10
+ // ----------------------------------------------------------------------------
11
+
12
+ module.exports = class fairdesk extends Exchange {
13
+ describe () {
14
+ return this.deepExtend (super.describe (), {
15
+ 'id': 'fairdesk',
16
+ 'name': 'Fairdesk',
17
+ 'countries': [ 'CN' ], // China
18
+ 'rateLimit': 100,
19
+ 'version': 'v1',
20
+ 'certified': false,
21
+ 'pro': true,
22
+ 'hostname': 'api.fairdesk.com',
23
+ 'has': {
24
+ 'CORS': undefined,
25
+ 'spot': false,
26
+ 'margin': false,
27
+ 'swap': undefined, // has but not fully implemented
28
+ 'future': false,
29
+ 'option': false,
30
+ 'cancelAllOrders': true,
31
+ 'cancelOrder': true,
32
+ 'createOrder': true,
33
+ 'editOrder': false,
34
+ 'fetchBalance': true,
35
+ 'fetchBorrowRate': false,
36
+ 'fetchBorrowRateHistories': false,
37
+ 'fetchBorrowRateHistory': false,
38
+ 'fetchBorrowRates': false,
39
+ 'fetchBorrowRatesPerSymbol': false,
40
+ 'fetchClosedOrders': true,
41
+ 'fetchCurrencies': false,
42
+ 'fetchDepositAddress': true,
43
+ 'fetchDeposits': true,
44
+ 'fetchIndexOHLCV': false,
45
+ 'fetchLeverageTiers': false,
46
+ 'fetchMarkets': true,
47
+ 'fetchMarkOHLCV': false,
48
+ 'fetchMyTrades': true,
49
+ 'fetchOHLCV': true,
50
+ 'fetchOpenOrders': true,
51
+ 'fetchOrder': true,
52
+ 'fetchOrderBook': true,
53
+ 'fetchOrders': true,
54
+ 'fetchPositions': true,
55
+ 'fetchPremiumIndexOHLCV': false,
56
+ 'fetchTicker': true,
57
+ 'fetchTrades': true,
58
+ 'fetchTradingFee': false,
59
+ 'fetchTradingFees': false,
60
+ 'fetchWithdrawals': false,
61
+ 'setLeverage': true,
62
+ 'transfer': false,
63
+ 'withdraw': false,
64
+ },
65
+ 'urls': {
66
+ 'logo': 'https://static.fairdesk.com/font/fairdesklogo.png',
67
+ 'test': {
68
+ 'public': 'https://api-testnet.fairdesk.com/api/v1/public',
69
+ 'private': 'https://api-testnet.fairdesk.com/api/v1/private',
70
+ },
71
+ 'api': {
72
+ 'public': 'https://{hostname}/api/v1/public',
73
+ 'private': 'https://{hostname}/api/v1/private',
74
+ },
75
+ 'www': 'https://www.fairdesk.com',
76
+ 'doc': 'https://github.com/fairdesk/fairdesk-api-docs',
77
+ 'fees': 'https://www.fairdesk.com/fees',
78
+ 'referral': 'https://www.fairdesk.com/signup?ref=URIJD5NI',
79
+ },
80
+ 'timeframes': {
81
+ '1m': '60',
82
+ '3m': '180',
83
+ '5m': '300',
84
+ '15m': '900',
85
+ '30m': '1800',
86
+ '1h': '3600',
87
+ '2h': '7200',
88
+ '3h': '10800',
89
+ '4h': '14400',
90
+ '6h': '21600',
91
+ '12h': '43200',
92
+ '1d': '86400',
93
+ '1w': '604800',
94
+ '1M': '2592000',
95
+ },
96
+ 'api': {
97
+ 'public': {
98
+ 'get': [
99
+ 'products', // contracts only
100
+ 'md/orderbook', // ?symbol=BTCUSDT
101
+ 'md/ticker24h', // ?symbol=BTCUSDT
102
+ 'md/trade-recent', // ?symbol=BTCUSDT
103
+ 'md/trade-history', // ?symbol=BTCUSDT&from=1651382628000
104
+ 'md/kline', // ?symbol=BTCUSDT&interval=5m&from=1651382628000&to=1651469028000
105
+ ],
106
+ },
107
+ 'private': {
108
+ 'get': [
109
+ // swap
110
+ 'account/order-detail', // orderId=571643709
111
+ 'account/order-histories', // ?symbol=&type=&pageIndex=1&pageSize=1000
112
+ 'account/balance',
113
+ 'account/symbol-config',
114
+ 'account/open-orders',
115
+ 'account/positions',
116
+ 'account/trade-histories',
117
+ // wallet
118
+ 'wallet/deposit-address', // ?currency=ETH
119
+ 'wallet/deposit-records', // ?startTime=0&currency=USDT&pageIndex=1&pageSize=20
120
+ ],
121
+ 'post': [
122
+ // swap
123
+ 'trade/place-order',
124
+ 'trade/cancel-all-order',
125
+ ],
126
+ 'put': [
127
+ // swap
128
+ 'account/config/adjust-leverage',
129
+ ],
130
+ 'delete': [
131
+ // swap
132
+ 'trade/cancel-order',
133
+ ],
134
+ },
135
+ },
136
+ 'precisionMode': TICK_SIZE,
137
+ 'fees': {
138
+ 'trading': {
139
+ 'tierBased': false,
140
+ 'percentage': true,
141
+ 'taker': this.parseNumber ('0.001'),
142
+ 'maker': this.parseNumber ('0.001'),
143
+ },
144
+ },
145
+ 'requiredCredentials': {
146
+ 'apiKey': true,
147
+ 'secret': true,
148
+ },
149
+ 'exceptions': {
150
+ 'exact': {
151
+ // not documented
152
+ '412': BadRequest, // {"code":412,"msg":"Missing parameter - resolution","data":null}
153
+ '6001': BadRequest, // {"error":{"code":6001,"message":"invalid argument"},"id":null,"result":null}
154
+ // documented
155
+ '19999': BadRequest, // REQUEST_IS_DUPLICATED Duplicated request ID
156
+ // not documented
157
+ '30000': BadRequest, // {"code":30000,"msg":"Please double check input arguments","data":null}
158
+ '39995': RateLimitExceeded, // {"code": "39995","msg": "Too many requests."}
159
+ '39996': PermissionDenied, // {"code": "39996","msg": "Access denied."}
160
+ },
161
+ 'broad': {
162
+ '401 Insufficient privilege': PermissionDenied, // {"code": "401","msg": "401 Insufficient privilege."}
163
+ '401 Request IP mismatch': PermissionDenied, // {"code": "401","msg": "401 Request IP mismatch."}
164
+ 'Failed to find api-key': AuthenticationError, // {"msg":"Failed to find api-key 1c5ec63fd-660d-43ea-847a-0d3ba69e106e","code":10500}
165
+ 'Missing required parameter': BadRequest, // {"msg":"Missing required parameter","code":10500}
166
+ 'API Signature verification failed': AuthenticationError, // {"msg":"API Signature verification failed.","code":10500}
167
+ 'Api key not found': AuthenticationError, // {"msg":"Api key not found 698dc9e3-6faa-4910-9476-12857e79e198","code":"10500"}
168
+ },
169
+ },
170
+ 'options': {
171
+ 'x-fairdesk-request-expiry': 60, // in seconds
172
+ 'createOrderByQuoteRequiresPrice': true,
173
+ 'networks': {
174
+ 'ERC20': 'ETH',
175
+ 'TRC20': 'TRX',
176
+ },
177
+ 'defaultNetworks': {
178
+ 'USDT': 'ETH',
179
+ },
180
+ 'defaultSubType': 'linear',
181
+ 'accountsByType': {
182
+ 'future': 'future',
183
+ },
184
+ },
185
+ });
186
+ }
187
+
188
+ parseSafeNumber (value = undefined) {
189
+ if (value === undefined) {
190
+ return value;
191
+ }
192
+ let parts = value.split (',');
193
+ value = parts.join ('');
194
+ parts = value.split (' ');
195
+ return this.safeNumber (parts, 0);
196
+ }
197
+
198
+ parseMaxLevel (symbolName) {
199
+ const hh = [ 'BTCUSDT' ];
200
+ const h = [ 'ETHUSDT' ];
201
+ const m = [ 'ADAUSDT', 'BNBUSDT', 'DOTUSDT' ];
202
+ const l = [ 'XRPUSDT', 'UNIUSDT', 'DOGEUSDT' ];
203
+ symbolName = symbolName.toLocaleUpperCase ();
204
+ const hhLeverages = [ 50000, 125, 100, 80, 60, 40, 20, 10, 5 ];
205
+ const hLeverages = [ 30000, 80, 60, 40, 20, 10, 5 ];
206
+ const mLeverages = [ 20000, 50, 30, 20, 10, 5, 4 ];
207
+ const lLeverages = [ 10000, 25, 20, 15, 10, 5, 4 ];
208
+ if (hh.indexOf (symbolName) >= 0) {
209
+ return hhLeverages;
210
+ }
211
+ if (h.indexOf (symbolName) >= 0) {
212
+ return hLeverages;
213
+ }
214
+ if (m.indexOf (symbolName) >= 0) {
215
+ return mLeverages;
216
+ }
217
+ if (l.indexOf (symbolName) >= 0) {
218
+ return lLeverages;
219
+ }
220
+ return lLeverages;
221
+ }
222
+
223
+ parseSwapMarket (market) {
224
+ // {
225
+ // amountDecimal: 3
226
+ // baseCurrency: "BTC"
227
+ // defaultLeverage: 20
228
+ // displayName: "BTC/USDT"
229
+ // fundingInterval: "Every 8 hours"
230
+ // limitPriceDiffRate: 0.1
231
+ // liquidationFeeRate: 0.01
232
+ // logUrl: "https://sgtnstatic-1306519353.file.myqcloud.com/currency/BTC.png"
233
+ // makerFeeRate: "0.0001"
234
+ // marketMaxQty: "0.000000"
235
+ // marketPriceDiffRate: 0.1
236
+ // maxOrderQty: "100.000000"
237
+ // maxPrice: "500000.000000"
238
+ // minOrderQty: "0.000000"
239
+ // minPrice: "0.500000"
240
+ // priceDecimal: 1
241
+ // priceScale: 6
242
+ // productType: "Perpetual"
243
+ // quoteCurrency: "USDT"
244
+ // ratioScale: 8
245
+ // settleCurrency: "USDT"
246
+ // status: "TRADING"
247
+ // stepSize: "0.001000"
248
+ // strategyPriceDiffRate: 0.075
249
+ // symbol: "btcusdt"
250
+ // symbolId: 1211
251
+ // takerFeeRate: "0.00015"
252
+ // tickSize: "0.500000"
253
+ // type: "FUTURE_PERPETUAL"
254
+ // valueScale: 6
255
+ // }
256
+ const id = this.safeString (market, 'symbol');
257
+ const baseId = this.safeString (market, 'baseCurrency');
258
+ const quoteId = this.safeString (market, 'quoteCurrency');
259
+ const settleId = this.safeString (market, 'settleCurrency');
260
+ const base = this.safeCurrencyCode (baseId);
261
+ const quote = this.safeCurrencyCode (quoteId);
262
+ const settle = this.safeCurrencyCode (settleId);
263
+ let inverse = false;
264
+ if (settleId !== quoteId) {
265
+ inverse = true;
266
+ }
267
+ const priceScale = this.safeInteger (market, 'priceScale');
268
+ const ratioScale = this.safeInteger (market, 'ratioScale');
269
+ const minPriceEp = this.safeString (market, 'minPrice');
270
+ const maxPriceEp = this.safeString (market, 'maxPrice');
271
+ const makerFeeRateEr = this.safeString (market, 'makerFeeRate');
272
+ const takerFeeRateEr = this.safeString (market, 'takerFeeRate');
273
+ const status = this.safeString (market, 'status');
274
+ // the size of one contract, only used if `contract` is true
275
+ const contractSize = this.parseNumber (this.safeString (market, 'stepSize'));
276
+ const maxLevel = this.parseMaxLevel (id)[1];
277
+ return {
278
+ 'id': id,
279
+ 'symbol': base + '/' + quote,
280
+ 'base': base,
281
+ 'quote': quote,
282
+ 'settle': settle,
283
+ 'baseId': baseId,
284
+ 'quoteId': quoteId,
285
+ 'settleId': settleId,
286
+ 'type': 'swap',
287
+ 'spot': false,
288
+ 'margin': false,
289
+ 'swap': true,
290
+ 'future': false,
291
+ 'option': false,
292
+ 'active': status === 'TRADING',
293
+ 'contract': true,
294
+ 'linear': !inverse,
295
+ 'inverse': inverse,
296
+ 'taker': this.parseNumber (takerFeeRateEr),
297
+ 'maker': this.parseNumber (makerFeeRateEr),
298
+ 'contractSize': contractSize,
299
+ 'expiry': undefined,
300
+ 'expiryDatetime': undefined,
301
+ 'strike': undefined,
302
+ 'optionType': undefined,
303
+ 'priceScale': priceScale,
304
+ 'ratioScale': ratioScale,
305
+ 'precision': {
306
+ 'amount': this.safeNumber (market, 'stepSize'),
307
+ 'price': this.safeNumber (market, 'tickSize'),
308
+ },
309
+ 'limits': {
310
+ 'leverage': {
311
+ 'min': this.parseNumber ('1'),
312
+ 'max': this.parseNumber (maxLevel),
313
+ },
314
+ 'amount': {
315
+ 'min': undefined,
316
+ 'max': undefined,
317
+ },
318
+ 'price': {
319
+ 'min': this.parseNumber (minPriceEp),
320
+ 'max': this.parseNumber (maxPriceEp),
321
+ },
322
+ 'cost': {
323
+ 'min': this.parseNumber (this.safeString (market, 'minOrderQty')),
324
+ 'max': this.parseNumber (this.safeString (market, 'maxOrderQty')),
325
+ },
326
+ },
327
+ 'info': market,
328
+ };
329
+ }
330
+
331
+ async fetchMarkets (params = {}) {
332
+ const res = await this.publicGetProducts (params);
333
+ const products = res.data;
334
+ const result = [];
335
+ for (let i = 0; i < products.length; i++) {
336
+ let market = products[i];
337
+ market = this.parseSwapMarket (market);
338
+ result.push (market);
339
+ }
340
+ return result;
341
+ }
342
+
343
+ async fetchCurrencies (params = {}) {
344
+ const response = await this.userGetPublicInstrumentChainCurrency (params);
345
+ const currencies = this.safeValue (response, 'data', {});
346
+ const result = {};
347
+ for (let i = 0; i < currencies.length; i++) {
348
+ const currency = currencies[i];
349
+ const id = this.safeString (currency, 'currency');
350
+ const name = this.safeString (currency, 'currency');
351
+ const code = this.safeCurrencyCode (id);
352
+ const valueScaleString = this.safeString (currency, 'valueScale');
353
+ const valueScale = parseInt (valueScaleString);
354
+ const minValueEv = this.safeString (currency, 'minValueEv');
355
+ const maxValueEv = this.safeString (currency, 'maxValueEv');
356
+ let minAmount = undefined;
357
+ let maxAmount = undefined;
358
+ let precision = undefined;
359
+ if (valueScale !== undefined) {
360
+ const precisionString = this.parsePrecision (valueScaleString);
361
+ precision = this.parseNumber (precisionString);
362
+ minAmount = this.parseNumber (Precise.stringMul (minValueEv, precisionString));
363
+ maxAmount = this.parseNumber (Precise.stringMul (maxValueEv, precisionString));
364
+ }
365
+ result[code] = {
366
+ 'id': id,
367
+ 'info': currency,
368
+ 'code': code,
369
+ 'name': name,
370
+ 'active': undefined,
371
+ 'deposit': undefined,
372
+ 'withdraw': undefined,
373
+ 'fee': undefined,
374
+ 'precision': precision,
375
+ 'limits': {
376
+ 'amount': {
377
+ 'min': minAmount,
378
+ 'max': maxAmount,
379
+ },
380
+ 'withdraw': {
381
+ 'min': undefined,
382
+ 'max': undefined,
383
+ },
384
+ },
385
+ 'valueScale': valueScale,
386
+ };
387
+ }
388
+ return result;
389
+ }
390
+
391
+ parseBidAsk (bidask, priceKey = 0, amountKey = 1, market = undefined) {
392
+ if (market === undefined) {
393
+ throw new ArgumentsRequired (this.id + ' parseBidAsk() requires a market argument');
394
+ }
395
+ const amount = this.safeString (bidask, amountKey);
396
+ return [
397
+ this.parseNumber (this.safeString (bidask, priceKey)),
398
+ this.parseNumber (amount),
399
+ ];
400
+ }
401
+
402
+ parseOrderBook (orderbook, symbol, timestamp = undefined, bidsKey = 'bids', asksKey = 'asks', priceKey = 0, amountKey = 1, market = undefined) {
403
+ const result = {
404
+ 'symbol': symbol,
405
+ 'timestamp': timestamp,
406
+ 'datetime': this.iso8601 (timestamp),
407
+ 'nonce': undefined,
408
+ };
409
+ const sides = [ bidsKey, asksKey ];
410
+ for (let i = 0; i < sides.length; i++) {
411
+ const side = sides[i];
412
+ const orders = [];
413
+ const bidasks = this.safeValue (orderbook, side);
414
+ for (let k = 0; k < bidasks.length; k++) {
415
+ orders.push (this.parseBidAsk (bidasks[k], priceKey, amountKey, market));
416
+ }
417
+ result[side] = orders;
418
+ }
419
+ result[bidsKey] = this.sortBy (result[bidsKey], 0, true);
420
+ result[asksKey] = this.sortBy (result[asksKey], 0);
421
+ return result;
422
+ }
423
+
424
+ async fetchOrderBook (symbol, limit = undefined, params = {}) {
425
+ await this.loadMarkets ();
426
+ const symbolId = this.parseSymbol (symbol);
427
+ const market = this.market (symbolId);
428
+ const request = {
429
+ 'symbol': market['id'],
430
+ };
431
+ const response = await this.publicGetMdOrderbook (this.extend (request, params));
432
+ const result = this.safeValue (response, 'data', {});
433
+ const timestamp = this.safeIntegerProduct (result, 'timestamp', 0.000001);
434
+ const orderbook = this.parseOrderBook (result, symbol, timestamp, 'bids', 'asks', 0, 1, market);
435
+ orderbook['nonce'] = this.safeInteger (result, 'sequence');
436
+ return orderbook;
437
+ }
438
+
439
+ parseOHLCV (ohlcv, market = undefined) {
440
+ return [
441
+ this.parseNumber (this.safeString (ohlcv, 'closeTime')),
442
+ this.parseNumber (this.safeString (ohlcv, 'open')),
443
+ this.parseNumber (this.safeString (ohlcv, 'high')),
444
+ this.parseNumber (this.safeString (ohlcv, 'low')),
445
+ this.parseNumber (this.safeString (ohlcv, 'close')),
446
+ this.parseNumber (this.safeString (ohlcv, 'volume')),
447
+ ];
448
+ }
449
+
450
+ async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
451
+ const request = {
452
+ 'interval': timeframe,
453
+ };
454
+ let startTime = 0;
455
+ let endTime = 0;
456
+ const duration = this.parseTimeframe (timeframe);
457
+ const now = this.seconds ();
458
+ if (since !== undefined) {
459
+ if (limit === undefined) {
460
+ limit = 1000; // max 1000
461
+ }
462
+ since = parseInt (since / 1000);
463
+ startTime = since;
464
+ // time ranges ending in the future are not accepted
465
+ // https://github.com/ccxt/ccxt/issues/8050
466
+ endTime = Math.min (now, this.sum (since, duration * limit));
467
+ } else if (limit !== undefined) {
468
+ limit = Math.min (limit, 1000);
469
+ startTime = now - duration * this.sum (limit, 1);
470
+ endTime = now;
471
+ } else {
472
+ throw new ArgumentsRequired (this.id + ' fetchOHLCV() requires a since argument, or a limit argument, or both');
473
+ }
474
+ request['from'] = startTime * 1000;
475
+ request['to'] = endTime * 1000;
476
+ await this.loadMarkets ();
477
+ const symbolId = this.parseSymbol (symbol);
478
+ const market = this.market (symbolId);
479
+ request['symbol'] = market['id'];
480
+ const response = await this.publicGetMdKline (this.extend (request, params));
481
+ const rows = this.safeValue (response, 'data', {});
482
+ return this.parseOHLCVs (rows, market, timeframe, since, limit);
483
+ }
484
+
485
+ parseTicker (ticker, market = undefined) {
486
+ const marketId = this.safeString (ticker, 'symbol');
487
+ market = this.safeMarket (marketId, market);
488
+ const symbol = market['symbol'];
489
+ const timestamp = this.safeIntegerProduct (ticker, 'timestamp', 0.000001);
490
+ const last = this.safeString (ticker, 'close');
491
+ const open = this.safeString (ticker, 'open');
492
+ return this.safeTicker ({
493
+ 'symbol': symbol,
494
+ 'timestamp': timestamp,
495
+ 'datetime': this.iso8601 (timestamp),
496
+ 'high': this.safeString (ticker, 'high'),
497
+ 'low': this.safeString (ticker, 'low'),
498
+ 'bid': this.safeString (ticker, 'bid'),
499
+ 'bidVolume': undefined,
500
+ 'ask': this.safeString (ticker, 'askEp'),
501
+ 'askVolume': undefined,
502
+ 'vwap': undefined,
503
+ 'open': open,
504
+ 'close': last,
505
+ 'last': last,
506
+ 'previousClose': undefined, // previous day close
507
+ 'change': undefined,
508
+ 'percentage': undefined,
509
+ 'average': undefined,
510
+ 'baseVolume': this.safeString (ticker, 'baseVolume'),
511
+ 'quoteVolume': this.safeString (ticker, 'quoteVolume'),
512
+ 'info': ticker,
513
+ }, market, false);
514
+ }
515
+
516
+ parseSymbol (symbol) {
517
+ const str = symbol.replace ('/', '');
518
+ const res = str.toLowerCase ();
519
+ return res;
520
+ }
521
+
522
+ async fetchTicker (symbol, params = {}) {
523
+ await this.loadMarkets ();
524
+ const symbolId = this.parseSymbol (symbol);
525
+ const market = this.market (symbolId);
526
+ const request = {
527
+ 'symbol': market['id'],
528
+ };
529
+ const method = 'publicGetMdTicker24h';
530
+ const response = await this[method] (this.extend (request, params));
531
+ const result = this.safeValue (response, 'data', {});
532
+ return this.parseTicker (result, market);
533
+ }
534
+
535
+ async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
536
+ const symbolId = this.parseSymbol (symbol);
537
+ await this.loadMarkets ();
538
+ const market = this.market (symbolId);
539
+ const request = {
540
+ 'symbol': market['id'],
541
+ };
542
+ let method = 'publicGetMdTradeRecent';
543
+ if (since) {
544
+ method = 'publicGetMdTradeHistory';
545
+ request['from'] = since;
546
+ }
547
+ const response = await this[method] (this.extend (request, params));
548
+ const result = this.safeValue (response, 'data', {});
549
+ const trades = this.safeValue (result, 'trades', []);
550
+ return this.parseTrades (trades, market, since, limit);
551
+ }
552
+
553
+ parseTrade (trade, market = undefined) {
554
+ let priceString = undefined;
555
+ let amountString = undefined;
556
+ let timestamp = undefined;
557
+ let id = undefined;
558
+ let side = undefined;
559
+ let costString = undefined;
560
+ let type = undefined;
561
+ let fee = undefined;
562
+ const marketId = this.safeString (trade, 'symbol');
563
+ market = this.safeMarket (marketId, market);
564
+ const symbol = market['symbol'];
565
+ let orderId = undefined;
566
+ let takerOrMaker = undefined;
567
+ if (Array.isArray (trade)) {
568
+ const tradeLength = trade.length;
569
+ timestamp = this.safeIntegerProduct (trade, 0, 0.001);
570
+ if (tradeLength > 4) {
571
+ id = this.safeString (trade, tradeLength - 4);
572
+ }
573
+ side = this.safeStringLower (trade, tradeLength - 3);
574
+ priceString = this.safeString (trade, tradeLength - 2);
575
+ amountString = this.safeString (trade, tradeLength - 1);
576
+ } else {
577
+ timestamp = this.safeNumber (trade, 'timestamp');
578
+ id = this.safeString2 (trade, 'execId', 'execID');
579
+ orderId = this.safeString (trade, 'orderID');
580
+ side = this.safeStringLower (trade, 'side');
581
+ type = this.parseOrderType (this.safeString (trade, 'ordType'));
582
+ const execStatus = this.safeString (trade, 'execStatus');
583
+ if (execStatus === 'MakerFill') {
584
+ takerOrMaker = 'maker';
585
+ }
586
+ priceString = this.safeString (trade, 'price');
587
+ amountString = this.safeString (trade, 'qty');
588
+ costString = this.safeString2 (trade, 'price', 'qty');
589
+ const feeCostString = this.safeString (trade, 'execFeeEv');
590
+ if (feeCostString !== undefined) {
591
+ const feeRateString = this.safeString (trade, 'feeRateEr');
592
+ let feeCurrencyCode = undefined;
593
+ if (market['spot']) {
594
+ feeCurrencyCode = (side === 'buy') ? market['base'] : market['quote'];
595
+ } else {
596
+ const info = this.safeValue (market, 'info');
597
+ if (info !== undefined) {
598
+ const settlementCurrencyId = this.safeString (info, 'settlementCurrency');
599
+ feeCurrencyCode = this.safeCurrencyCode (settlementCurrencyId);
600
+ }
601
+ }
602
+ fee = {
603
+ 'cost': this.parseNumber (feeCostString),
604
+ 'rate': this.parseNumber (feeRateString),
605
+ 'currency': feeCurrencyCode,
606
+ };
607
+ }
608
+ }
609
+ return this.safeTrade ({
610
+ 'info': trade,
611
+ 'id': id,
612
+ 'symbol': symbol,
613
+ 'timestamp': timestamp,
614
+ 'datetime': this.iso8601 (timestamp),
615
+ 'order': orderId,
616
+ 'type': type,
617
+ 'side': side,
618
+ 'takerOrMaker': takerOrMaker,
619
+ 'price': priceString,
620
+ 'amount': amountString,
621
+ 'cost': costString,
622
+ 'fee': fee,
623
+ }, market);
624
+ }
625
+
626
+ parseSwapBalance (response) {
627
+ const result = { 'info': response };
628
+ const data = this.safeValue (response, 'data', {});
629
+ const balance = this.safeValue (data, 'accounts', {})[0];
630
+ const currencyId = this.safeString (balance, 'currency');
631
+ const code = this.safeCurrencyCode (currencyId);
632
+ const account = this.account ();
633
+ const accountBalanceEv = this.safeString (balance, 'accountBalance');
634
+ const totalUsedBalanceEv = this.safeString (balance, 'availBalance');
635
+ account['total'] = accountBalanceEv;
636
+ account['used'] = totalUsedBalanceEv;
637
+ result[code] = account;
638
+ return this.safeBalance (result);
639
+ }
640
+
641
+ async fetchBalance (params = {}) {
642
+ await this.loadMarkets ();
643
+ const method = 'privateGetAccountBalance';
644
+ const request = {};
645
+ params = this.omit (params, 'type');
646
+ const response = await this[method] (this.extend (request, params));
647
+ const result = this.parseSwapBalance (response);
648
+ return result;
649
+ }
650
+
651
+ parseOrderStatus (status) {
652
+ const statuses = {
653
+ 'Created': 'open',
654
+ 'Untriggered': 'open',
655
+ 'Deactivated': 'closed',
656
+ 'Triggered': 'open',
657
+ 'Rejected': 'rejected',
658
+ 'New': 'open',
659
+ 'PartiallyFilled': 'open',
660
+ 'Filled': 'closed',
661
+ 'Canceled': 'canceled',
662
+ };
663
+ return this.safeString (statuses, status, status);
664
+ }
665
+
666
+ parseOrderType (type) {
667
+ const types = {
668
+ 'Limit': 'limit',
669
+ 'Market': 'market',
670
+ };
671
+ return this.safeString (types, type, type);
672
+ }
673
+
674
+ parseTimeInForce (timeInForce) {
675
+ const timeInForces = {
676
+ 'GoodTillCancel': 'GTC',
677
+ 'PostOnly': 'PO',
678
+ 'ImmediateOrCancel': 'IOC',
679
+ 'FillOrKill': 'FOK',
680
+ };
681
+ return this.safeString (timeInForces, timeInForce, timeInForce);
682
+ }
683
+
684
+ parseSwapOrder (order, market = undefined) {
685
+ const id = this.safeString (order, 'orderId');
686
+ const state = () => {
687
+ let value = '';
688
+ if (this.safeString (order, 'status') === 'FILLED') {
689
+ const displayStr = `${this.safeString (order, 'side')}_${this.safeString (order, 'positionSide')}`;
690
+ switch (displayStr) {
691
+ case 'BUY_LONG':
692
+ value = 'open';
693
+ break;
694
+ case 'BUY_SHORT':
695
+ value = 'closed';
696
+ break;
697
+ case 'SELL_SHORT':
698
+ value = 'open';
699
+ break;
700
+ case 'SELL_LONG':
701
+ value = 'closed';
702
+ break;
703
+ default:
704
+ break;
705
+ }
706
+ return value;
707
+ }
708
+ if (this.safeString (order, 'status') === 'CANCELED') {
709
+ value = 'canceled';
710
+ return value;
711
+ }
712
+ if (this.safeString (order, 'status') === 'EXPIRED') {
713
+ value = 'expired';
714
+ return value;
715
+ }
716
+ return value;
717
+ };
718
+ let clientOrderId = this.safeString (order, 'clientOrderId');
719
+ if ((clientOrderId !== undefined) && (clientOrderId.length < 1)) {
720
+ clientOrderId = undefined;
721
+ }
722
+ const marketId = this.safeString (order, 'symbol');
723
+ const symbol = this.safeSymbol (marketId, market);
724
+ const status = state (); // 'open', 'closed', 'canceled', 'expired', 'rejected'
725
+ const side = (this.safeStringLower (order, 'side')).toLowerCase ();
726
+ const type = (this.parseOrderType (this.safeString (order, 'type'))).toLowerCase ();
727
+ const price = this.parseNumber (this.safeString (order, 'price') === '--' ? '' : this.safeString (order, 'price'));
728
+ const amount = this.safeNumber (order, 'origQty');
729
+ const filled = this.safeNumber (order, 'origQty') - this.safeNumber (order, 'executedQty');
730
+ // const remaining = this.safeNumber (order, 'leavesQty');
731
+ const remaining = undefined;
732
+ const timestamp = this.safeNumber (order, 'transactTime');
733
+ // const cost = this.safeNumber (order, 'cumValue');
734
+ const cost = undefined;
735
+ let lastTradeTimestamp = this.safeNumber (order, 'transactTimeNs');
736
+ if (lastTradeTimestamp === 0) {
737
+ lastTradeTimestamp = undefined;
738
+ }
739
+ const timeInForce = this.parseTimeInForce (this.safeString (order, 'timeInForce'));
740
+ const stopPrice = this.safeNumber (order, 'avlPrice');
741
+ const postOnly = (timeInForce === 'POST_ONLY');
742
+ return {
743
+ 'info': order,
744
+ 'id': id,
745
+ 'clientOrderId': clientOrderId,
746
+ 'datetime': this.iso8601 (timestamp),
747
+ 'timestamp': timestamp,
748
+ 'lastTradeTimestamp': lastTradeTimestamp,
749
+ 'symbol': symbol,
750
+ 'type': type,
751
+ 'timeInForce': timeInForce,
752
+ 'postOnly': postOnly,
753
+ 'side': side,
754
+ 'price': price,
755
+ 'stopPrice': stopPrice,
756
+ 'amount': amount,
757
+ 'filled': filled,
758
+ 'remaining': remaining,
759
+ 'cost': cost,
760
+ 'average': undefined,
761
+ 'status': status,
762
+ 'fee': undefined,
763
+ 'trades': undefined,
764
+ };
765
+ }
766
+
767
+ parseOrder (order, market = undefined) {
768
+ return this.parseSwapOrder (order, market);
769
+ }
770
+
771
+ async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
772
+ await this.loadMarkets ();
773
+ const symbolId = this.parseSymbol (symbol);
774
+ const market = this.market (symbolId);
775
+ side = this.capitalize (side);
776
+ type = this.capitalize (type);
777
+ const request = {
778
+ // common
779
+ 'symbol': market['id'],
780
+ 'side': side.toLocaleUpperCase (), // Sell, Buy
781
+ 'type': type.toLocaleUpperCase (), // Market, Limit, Stop, StopLimit, MarketIfTouched, LimitIfTouched or Pegged for swap orders
782
+ // swap
783
+ 'clientOrderId': `CCXT_${this.uuid ()}`,
784
+ 'orderRespType': 'ACK',
785
+ 'positionSide': side === 'Buy' ? 'LONG' : 'SHORT',
786
+ 'isolated': params.isolated || false,
787
+ };
788
+ const stopPrice = this.safeString2 (params, 'stopPx', 'stopPrice');
789
+ if (stopPrice !== undefined) {
790
+ request['stopPrice'] = stopPrice;
791
+ }
792
+ params = this.omit (params, [ 'stopPx', 'stopPrice' ]);
793
+ if (market['swap']) {
794
+ request['quantity'] = amount;
795
+ if (stopPrice !== undefined) {
796
+ const triggerType = this.safeString (params, 'triggerType', 'ByMarkPrice');
797
+ request['triggerType'] = triggerType;
798
+ }
799
+ }
800
+ if ((type === 'Limit') || (type === 'StopLimit') || (type === 'LimitIfTouched')) {
801
+ const priceString = price.toString ();
802
+ request['timeInForce'] = 'GTC';
803
+ request['price'] = priceString;
804
+ }
805
+ const takeProfitPrice = this.safeString (params, 'takeProfitPrice');
806
+ if (takeProfitPrice !== undefined) {
807
+ request['tpPrice'] = takeProfitPrice;
808
+ params = this.omit (params, 'tpPrice');
809
+ }
810
+ const stopLossPrice = this.safeString (params, 'stopLossPrice');
811
+ if (stopLossPrice !== undefined) {
812
+ request['slPrice'] = stopLossPrice;
813
+ params = this.omit (params, 'slPrice');
814
+ }
815
+ const method = market['spot'] ? 'privatePostSpotOrders' : 'privatePostTradePlaceOrder';
816
+ const response = await this[method] (this.extend (request, params));
817
+ const data = this.safeValue (response, 'data', {});
818
+ return this.parseOrder (data, market);
819
+ }
820
+
821
+ async cancelOrder (id, symbol = undefined, params = {}) {
822
+ if (symbol === undefined) {
823
+ throw new ArgumentsRequired (this.id + ' cancelOrder() requires a symbol argument');
824
+ }
825
+ const symbolId = this.parseSymbol (symbol);
826
+ await this.loadMarkets ();
827
+ const market = this.market (symbolId);
828
+ const request = {
829
+ 'symbol': market['id'],
830
+ 'orderId': id,
831
+ };
832
+ const method = 'privateDeleteTradeCancelOrder';
833
+ const response = await this[method] (this.extend (request, params));
834
+ if (response.status !== 0) {
835
+ return response;
836
+ }
837
+ const data = this.safeValue (response, 'data', {});
838
+ return this.parseOrder (data, market);
839
+ }
840
+
841
+ async cancelAllOrders (symbol = undefined, params = {}) {
842
+ await this.loadMarkets ();
843
+ const request = {
844
+ 'settleCcy': 'USDT',
845
+ };
846
+ const method = 'privatePostTradeCancelAllOrder';
847
+ return await this[method] (this.extend (request, params));
848
+ }
849
+
850
+ async fetchOrder (id, symbol = undefined, params = {}) {
851
+ if (symbol === undefined) {
852
+ throw new ArgumentsRequired (this.id + ' fetchOrder() requires a symbol argument');
853
+ }
854
+ await this.loadMarkets ();
855
+ const market = this.market (symbol);
856
+ const method = market['spot'] ? 'privateGetSpotOrdersActive' : 'privateGetAccountOrderDetail';
857
+ const request = {
858
+ 'symbol': market['id'],
859
+ };
860
+ const clientOrderId = this.safeString2 (params, 'clientOrderId', 'clOrdID');
861
+ params = this.omit (params, [ 'clientOrderId', 'clOrdID' ]);
862
+ if (clientOrderId !== undefined) {
863
+ request['clOrdID'] = clientOrderId;
864
+ } else {
865
+ request['orderID'] = id;
866
+ }
867
+ const response = await this[method] (this.extend (request, params));
868
+ const data = this.safeValue (response, 'data', {});
869
+ let order = data;
870
+ if (Array.isArray (data)) {
871
+ const numOrders = data.length;
872
+ if (numOrders < 1) {
873
+ if (clientOrderId !== undefined) {
874
+ throw new OrderNotFound (this.id + ' fetchOrder ' + symbol + ' order with clientOrderId ' + clientOrderId + ' not found');
875
+ } else {
876
+ throw new OrderNotFound (this.id + ' fetchOrder ' + symbol + ' order with id ' + id + ' not found');
877
+ }
878
+ }
879
+ order = this.safeValue (data, 0, {});
880
+ }
881
+ return this.parseOrder (order, market);
882
+ }
883
+
884
+ async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
885
+ if (symbol === undefined) {
886
+ throw new ArgumentsRequired (this.id + ' fetchOrders() requires a symbol argument');
887
+ }
888
+ const symbolId = this.parseSymbol (symbol);
889
+ await this.loadMarkets ();
890
+ const market = this.market (symbolId);
891
+ const method = market['spot'] ? 'privateGetSpotOrders' : 'privateGetAccountOrderHistories';
892
+ const request = {
893
+ 'symbol': market['id'],
894
+ };
895
+ if (since !== undefined) {
896
+ request['start'] = since;
897
+ }
898
+ if (limit !== undefined) {
899
+ request['limit'] = limit;
900
+ }
901
+ const response = await this[method] (this.extend (request, params));
902
+ const data = this.safeValue (response, 'data', {});
903
+ const rows = this.safeValue (data, 'rows', []);
904
+ return this.parseOrders (rows, market, since, limit);
905
+ }
906
+
907
+ async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
908
+ if (symbol === undefined) {
909
+ throw new ArgumentsRequired (this.id + ' fetchOpenOrders() requires a symbol argument');
910
+ }
911
+ await this.loadMarkets ();
912
+ const symbolId = this.parseSymbol (symbol);
913
+ const market = this.market (symbolId);
914
+ const method = market['spot'] ? 'privateGetSpotOrders' : 'privateGetAccountOpenOrders';
915
+ const request = {
916
+ 'symbol': market['id'],
917
+ };
918
+ let response = undefined;
919
+ try {
920
+ response = await this[method] (this.extend (request, params));
921
+ } catch (e) {
922
+ if (e instanceof OrderNotFound) {
923
+ return [];
924
+ }
925
+ }
926
+ const data = this.safeValue (response, 'data', {});
927
+ if (Array.isArray (data)) {
928
+ return this.parseOrders (data, market, since, limit);
929
+ } else {
930
+ const rows = this.safeValue (data, 'rows', []);
931
+ return this.parseOrders (rows, market, since, limit);
932
+ }
933
+ }
934
+
935
+ async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
936
+ if (symbol === undefined) {
937
+ throw new ArgumentsRequired (this.id + ' fetchClosedOrders() requires a symbol argument');
938
+ }
939
+ const symbolId = this.parseSymbol (symbol);
940
+ await this.loadMarkets ();
941
+ const market = this.market (symbolId);
942
+ const method = market['spot'] ? 'privateGetExchangeSpotOrder' : 'privateGetAccountOrderHistories';
943
+ const request = {
944
+ 'symbol': market['id'],
945
+ 'status': 'CANCELED',
946
+ };
947
+ if (since !== undefined) {
948
+ request['start'] = since;
949
+ }
950
+ if (limit !== undefined) {
951
+ request['limit'] = limit;
952
+ }
953
+ const response = await this[method] (this.extend (request, params));
954
+ const data = this.safeValue (response, 'data', {});
955
+ if (Array.isArray (data)) {
956
+ return this.parseOrders (data, market, since, limit);
957
+ } else {
958
+ const rows = this.safeValue (data, 'rows', []);
959
+ return this.parseOrders (rows, market, since, limit);
960
+ }
961
+ }
962
+
963
+ async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
964
+ if (symbol === undefined) {
965
+ throw new ArgumentsRequired (this.id + ' fetchMyTrades() requires a symbol argument');
966
+ }
967
+ await this.loadMarkets ();
968
+ const symbolId = this.parseSymbol (symbol);
969
+ const market = this.market (symbolId);
970
+ const method = 'privateGetAccountTradeHistories';
971
+ const request = {
972
+ 'symbol': market['id'],
973
+ };
974
+ if (since !== undefined) {
975
+ request['start'] = since;
976
+ }
977
+ if (market['swap'] && (limit !== undefined)) {
978
+ request['limit'] = limit;
979
+ }
980
+ const response = await this[method] (this.extend (request, params));
981
+ const data = this.safeValue (response, 'data', {});
982
+ const rows = this.safeValue (data, 'rows', []);
983
+ return this.parseTrades (rows, market, since, limit);
984
+ }
985
+
986
+ async fetchDepositAddress (code, params = {}) {
987
+ await this.loadMarkets ();
988
+ const currency = this.currency (code);
989
+ const request = {
990
+ 'currency': currency['id'],
991
+ };
992
+ const defaultNetworks = this.safeValue (this.options, 'defaultNetworks');
993
+ const defaultNetwork = this.safeStringUpper (defaultNetworks, code);
994
+ const networks = this.safeValue (this.options, 'networks', {});
995
+ let network = this.safeStringUpper (params, 'network', defaultNetwork);
996
+ network = this.safeString (networks, network, network);
997
+ if (network === undefined) {
998
+ request['chainName'] = currency['id'];
999
+ } else {
1000
+ request['chainName'] = network;
1001
+ params = this.omit (params, 'network');
1002
+ }
1003
+ const response = await this.privateGetWalletDepositAddress (this.extend (request, params));
1004
+ const data = this.safeValue (response, 'data', {})[0];
1005
+ const address = this.safeString (data, 'address');
1006
+ const tag = this.safeString (data, 'chain');
1007
+ this.checkAddress (address);
1008
+ return {
1009
+ 'currency': code,
1010
+ 'address': address,
1011
+ 'tag': tag,
1012
+ 'network': undefined,
1013
+ 'info': data,
1014
+ };
1015
+ }
1016
+
1017
+ async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) {
1018
+ await this.loadMarkets ();
1019
+ let currency = undefined;
1020
+ if (code !== undefined) {
1021
+ currency = this.currency (code);
1022
+ }
1023
+ const response = await this.privateGetWalletDepositRecords (params);
1024
+ const data = this.safeValue (response, 'data', {});
1025
+ const rows = this.safeValue (data, 'rows', {});
1026
+ return this.parseTransactions (rows, currency, since, limit);
1027
+ }
1028
+
1029
+ parseTransactionStatus (status) {
1030
+ const statuses = {
1031
+ 'Success': 'ok',
1032
+ 'Succeed': 'ok',
1033
+ };
1034
+ return this.safeString (statuses, status, status);
1035
+ }
1036
+
1037
+ parseTransaction (transaction, currency = undefined) {
1038
+ const id = this.safeString (transaction, 'id');
1039
+ const address = this.safeString (transaction, 'address');
1040
+ const tag = undefined;
1041
+ const txid = this.safeString (transaction, 'txId');
1042
+ const currencyId = this.safeString (transaction, 'currency');
1043
+ currency = this.safeCurrency (currencyId, currency);
1044
+ const code = currency['code'];
1045
+ const timestamp = this.safeInteger (transaction, 'time');
1046
+ let type = this.safeStringLower (transaction, 'type');
1047
+ const feeCost = this.parseNumber (this.safeString (transaction, 'fee'));
1048
+ let fee = undefined;
1049
+ if (feeCost !== undefined) {
1050
+ type = 'withdrawal';
1051
+ fee = {
1052
+ 'cost': feeCost,
1053
+ 'currency': code,
1054
+ };
1055
+ }
1056
+ const status = this.parseTransactionStatus (this.safeString (transaction, 'status'));
1057
+ const amount = this.parseNumber (this.safeString (transaction, 'amount'));
1058
+ return {
1059
+ 'info': transaction,
1060
+ 'id': id,
1061
+ 'txid': txid,
1062
+ 'timestamp': timestamp,
1063
+ 'datetime': this.iso8601 (timestamp),
1064
+ 'network': this.safeString (transaction, 'chain'),
1065
+ 'address': address,
1066
+ 'addressTo': address,
1067
+ 'addressFrom': undefined,
1068
+ 'tag': tag,
1069
+ 'tagTo': tag,
1070
+ 'tagFrom': undefined,
1071
+ 'type': type,
1072
+ 'amount': amount,
1073
+ 'currency': code,
1074
+ 'status': status,
1075
+ 'updated': undefined,
1076
+ 'fee': fee,
1077
+ };
1078
+ }
1079
+
1080
+ async fetchPositions (symbols = undefined, params = {}) {
1081
+ await this.loadMarkets ();
1082
+ const request = {};
1083
+ const response = await this.privateGetAccountPositions (this.extend (request, params));
1084
+ const positions = this.safeValue (response, 'data', {});
1085
+ const result = [];
1086
+ for (let i = 0; i < positions.length; i++) {
1087
+ const position = positions[i];
1088
+ result.push (this.parsePosition (position));
1089
+ }
1090
+ return this.filterByArray (result, 'symbol', symbols, false);
1091
+ }
1092
+
1093
+ parsePosition (position, market = undefined) {
1094
+ const marketId = this.safeString (position, 'symbol');
1095
+ market = this.safeMarket (marketId, market);
1096
+ const symbol = market['symbol'];
1097
+ const collateral = this.safeString (position, 'positionMargin');
1098
+ const notionalString = this.safeString (position, 'value');
1099
+ const maintenanceMarginPercentageString = this.safeString (position, 'maintMarginReq');
1100
+ const maintenanceMarginString = Precise.stringMul (notionalString, maintenanceMarginPercentageString);
1101
+ const initialMarginString = this.safeString (position, 'assignedPosBalance');
1102
+ const initialMarginPercentageString = Precise.stringDiv (initialMarginString, notionalString);
1103
+ const liquidationPrice = this.safeNumber (position, 'liquidationPrice');
1104
+ const markPriceString = this.safeString (position, 'markPrice');
1105
+ const contracts = this.safeString (position, 'size');
1106
+ const contractSize = this.safeValue (market, 'contractSize');
1107
+ const contractSizeString = this.numberToString (contractSize);
1108
+ const leverage = this.safeNumber (position, 'leverage');
1109
+ const entryPriceString = this.safeString (position, 'avgEntryPrice');
1110
+ const rawSide = this.safeString (position, 'positionSide');
1111
+ const side = (rawSide === 'Buy') ? 'long' : 'short';
1112
+ let priceDiff = undefined;
1113
+ const currency = this.safeString (position, 'baseCurrency');
1114
+ if (currency === 'USD') {
1115
+ if (side === 'long') {
1116
+ priceDiff = Precise.stringSub (markPriceString, entryPriceString);
1117
+ } else {
1118
+ priceDiff = Precise.stringSub (entryPriceString, markPriceString);
1119
+ }
1120
+ } else {
1121
+ // inverse
1122
+ if (side === 'long') {
1123
+ priceDiff = Precise.stringSub (Precise.stringDiv ('1', entryPriceString), Precise.stringDiv ('1', markPriceString));
1124
+ } else {
1125
+ priceDiff = Precise.stringSub (Precise.stringDiv ('1', markPriceString), Precise.stringDiv ('1', entryPriceString));
1126
+ }
1127
+ }
1128
+ const unrealizedPnl = Precise.stringMul (Precise.stringMul (priceDiff, contracts), contractSizeString);
1129
+ const percentage = Precise.stringMul (Precise.stringDiv (unrealizedPnl, initialMarginString), '100');
1130
+ const marginRatio = Precise.stringDiv (maintenanceMarginString, collateral);
1131
+ return {
1132
+ 'info': position,
1133
+ 'symbol': symbol,
1134
+ 'contracts': this.parseNumber (contracts),
1135
+ 'contractSize': contractSize,
1136
+ 'unrealizedPnl': this.parseNumber (unrealizedPnl),
1137
+ 'leverage': leverage,
1138
+ 'liquidationPrice': liquidationPrice,
1139
+ 'collateral': this.parseNumber (collateral),
1140
+ 'notional': this.parseNumber (notionalString),
1141
+ 'markPrice': this.parseNumber (markPriceString), // markPrice lags a bit ¯\_(ツ)_/¯
1142
+ 'entryPrice': this.parseNumber (entryPriceString),
1143
+ 'timestamp': undefined,
1144
+ 'initialMargin': this.parseNumber (initialMarginString),
1145
+ 'initialMarginPercentage': this.parseNumber (initialMarginPercentageString),
1146
+ 'maintenanceMargin': this.parseNumber (maintenanceMarginString),
1147
+ 'maintenanceMarginPercentage': this.parseNumber (maintenanceMarginPercentageString),
1148
+ 'marginRatio': this.parseNumber (marginRatio),
1149
+ 'datetime': undefined,
1150
+ 'marginType': undefined,
1151
+ 'side': side,
1152
+ 'hedged': false,
1153
+ 'percentage': this.parseNumber (percentage),
1154
+ };
1155
+ }
1156
+
1157
+ sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
1158
+ const query = this.omit (params, this.extractParams (path));
1159
+ const requestPath = '/' + this.implodeParams (path, params);
1160
+ let url = requestPath;
1161
+ let queryString = '';
1162
+ if (method === 'GET') {
1163
+ if (Object.keys (query).length) {
1164
+ queryString = this.urlencodeWithArrayRepeat (query);
1165
+ url += '?' + queryString;
1166
+ }
1167
+ }
1168
+ if (api === 'private') {
1169
+ this.checkRequiredCredentials ();
1170
+ const timestamp = this.milliseconds ();
1171
+ const xFairdeskRequestExpiry = this.safeInteger (this.options, 'x-fairdesk-request-expiry', 60);
1172
+ const expiry = this.sum (timestamp, xFairdeskRequestExpiry * 1000);
1173
+ const expiryString = expiry.toString ();
1174
+ headers = {
1175
+ 'x-fairdesk-access-key': this.apiKey,
1176
+ 'x-fairdesk-request-expiry': expiryString,
1177
+ };
1178
+ let payload = '';
1179
+ if (method === 'POST' || method === 'PUT' || method === 'DELETE') {
1180
+ payload = this.json (params);
1181
+ body = payload;
1182
+ headers['Content-Type'] = 'application/json';
1183
+ }
1184
+ const auth = '/api/v1/private' + requestPath + queryString + expiryString + payload;
1185
+ headers['x-fairdesk-request-signature'] = this.hmac (this.encode (auth), this.encode (this.secret));
1186
+ }
1187
+ url = this.implodeHostname (this.urls['api'][api]) + url;
1188
+ return { 'url': url, 'method': method, 'body': body, 'headers': headers };
1189
+ }
1190
+
1191
+ async setLeverage (leverage, symbol = undefined, params = {}) {
1192
+ // WARNING: THIS WILL INCREASE LIQUIDATION PRICE FOR OPEN ISOLATED LONG POSITIONS
1193
+ // AND DECREASE LIQUIDATION PRICE FOR OPEN ISOLATED SHORT POSITIONS
1194
+ if (symbol === undefined) {
1195
+ throw new ArgumentsRequired (this.id + ' setLeverage() requires a symbol argument');
1196
+ }
1197
+ const symbolId = this.parseSymbol (symbol);
1198
+ if ((leverage < 1) || (leverage > 125)) {
1199
+ throw new BadRequest (this.id + ' leverage should be between 1 and 125');
1200
+ }
1201
+ await this.loadMarkets ();
1202
+ const market = this.market (symbolId);
1203
+ const request = {
1204
+ 'symbol': market['id'],
1205
+ 'leverage': leverage,
1206
+ 'isolated': params.isolated || false,
1207
+ };
1208
+ const res = await this.privatePutAccountConfigAdjustLeverage (this.extend (request, params));
1209
+ return res;
1210
+ }
1211
+
1212
+ handleErrors (httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) {
1213
+ if (response === undefined) {
1214
+ return; // fallback to default error handler
1215
+ }
1216
+ //
1217
+ // {"code":412,"msg":"Missing parameter - resolution","data":null}
1218
+ // {"code":412,"msg":"Missing parameter - to","data":null}
1219
+ // {"error":{"code":6001,"message":"invalid argument"},"id":null,"result":null}
1220
+ //
1221
+ const error = this.safeValue (response, 'error', response);
1222
+ const errorCode = this.safeString (error, 'code');
1223
+ const message = this.safeString (error, 'msg');
1224
+ if ((errorCode !== undefined) && (errorCode !== '0')) {
1225
+ const feedback = this.id + ' ' + body;
1226
+ this.throwExactlyMatchedException (this.exceptions['exact'], errorCode, feedback);
1227
+ this.throwBroadlyMatchedException (this.exceptions['broad'], message, feedback);
1228
+ throw new ExchangeError (feedback); // unknown message
1229
+ }
1230
+ }
1231
+ };