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/bkex.js ADDED
@@ -0,0 +1,1233 @@
1
+ 'use strict';
2
+
3
+ // ---------------------------------------------------------------------------
4
+
5
+ const Exchange = require ('./base/Exchange');
6
+ const { ExchangeError, BadRequest, ArgumentsRequired, InsufficientFunds, InvalidOrder } = require ('./base/errors');
7
+
8
+ // ---------------------------------------------------------------------------
9
+
10
+ module.exports = class bkex extends Exchange {
11
+ describe () {
12
+ return this.deepExtend (super.describe (), {
13
+ 'id': 'bkex',
14
+ 'name': 'BKEX',
15
+ 'countries': [ 'BVI' ], // British Virgin Islands
16
+ 'rateLimit': 100,
17
+ 'version': 'v2',
18
+ 'certified': false,
19
+ 'has': {
20
+ 'CORS': undefined,
21
+ 'spot': undefined,
22
+ 'margin': undefined,
23
+ 'swap': undefined,
24
+ 'future': undefined,
25
+ 'option': undefined,
26
+ 'addMargin': undefined,
27
+ 'cancelAllOrders': undefined,
28
+ 'cancelOrder': true,
29
+ 'cancelOrders': true,
30
+ 'createDepositAddress': undefined,
31
+ 'createLimitOrder': undefined,
32
+ 'createMarketOrder': undefined,
33
+ 'createOrder': true,
34
+ 'editOrder': undefined,
35
+ 'fetchAccounts': undefined,
36
+ 'fetchBalance': true,
37
+ 'fetchBidsAsks': undefined,
38
+ 'fetchBorrowRate': undefined,
39
+ 'fetchBorrowRateHistory': undefined,
40
+ 'fetchBorrowRates': undefined,
41
+ 'fetchBorrowRatesPerSymbol': undefined,
42
+ 'fetchCanceledOrders': undefined,
43
+ 'fetchClosedOrder': undefined,
44
+ 'fetchClosedOrders': true,
45
+ 'fetchCurrencies': true,
46
+ 'fetchDeposit': false,
47
+ 'fetchDepositAddress': true,
48
+ 'fetchDepositAddresses': undefined,
49
+ 'fetchDepositAddressesByNetwork': undefined,
50
+ 'fetchDeposits': true,
51
+ 'fetchFundingFee': undefined,
52
+ 'fetchFundingFees': undefined,
53
+ 'fetchFundingHistory': undefined,
54
+ 'fetchFundingRate': undefined,
55
+ 'fetchFundingRateHistory': undefined,
56
+ 'fetchFundingRates': undefined,
57
+ 'fetchIndexOHLCV': undefined,
58
+ 'fetchL2OrderBook': undefined,
59
+ 'fetchLedger': undefined,
60
+ 'fetchLedgerEntry': undefined,
61
+ 'fetchLeverageTiers': undefined,
62
+ 'fetchMarketLeverageTiers': undefined,
63
+ 'fetchMarkets': true,
64
+ 'fetchMarkOHLCV': undefined,
65
+ 'fetchMyTrades': undefined,
66
+ 'fetchOHLCV': true,
67
+ 'fetchOpenOrder': true,
68
+ 'fetchOpenOrders': true,
69
+ 'fetchOrder': false,
70
+ 'fetchOrderBook': true,
71
+ 'fetchOrderBooks': undefined,
72
+ 'fetchOrders': undefined,
73
+ 'fetchOrderTrades': undefined,
74
+ 'fetchPosition': undefined,
75
+ 'fetchPositions': undefined,
76
+ 'fetchPositionsRisk': undefined,
77
+ 'fetchPremiumIndexOHLCV': undefined,
78
+ 'fetchStatus': undefined,
79
+ 'fetchTicker': true,
80
+ 'fetchTickers': true,
81
+ 'fetchTime': true,
82
+ 'fetchTrades': true,
83
+ 'fetchTradingFee': false,
84
+ 'fetchTradingFees': false,
85
+ 'fetchTradingLimits': undefined,
86
+ 'fetchTransactions': undefined,
87
+ 'fetchTransfer': false,
88
+ 'fetchTransfers': false,
89
+ 'fetchWithdrawal': false,
90
+ 'fetchWithdrawals': true,
91
+ 'loadMarkets': true,
92
+ 'privateAPI': true,
93
+ 'publicAPI': true,
94
+ 'reduceMargin': undefined,
95
+ 'setLeverage': undefined,
96
+ 'setMarginMode': undefined,
97
+ 'setPositionMode': undefined,
98
+ 'signIn': undefined,
99
+ 'transfer': false,
100
+ 'withdraw': false,
101
+ },
102
+ 'timeframes': {
103
+ '1m': '1m',
104
+ '5m': '5m',
105
+ '15m': '15m',
106
+ '30m': '30m',
107
+ '1h': '1h',
108
+ '4h': '4h',
109
+ '6h': '6h',
110
+ '12h': '12h',
111
+ '1d': '1d',
112
+ '1w': '1w',
113
+ },
114
+ 'urls': {
115
+ 'logo': 'https://user-images.githubusercontent.com/1294454/158043180-bb079a65-69e8-45a2-b393-f094d334e610.jpg',
116
+ 'api': {
117
+ 'public': 'https://api.bkex.com',
118
+ 'private': 'https://api.bkex.com',
119
+ },
120
+ 'www': 'https://www.bkex.com/',
121
+ 'doc': [
122
+ 'https://bkexapi.github.io/docs/api_en.htm',
123
+ ],
124
+ 'fees': [
125
+ 'https://www.bkex.com/help/instruction/33',
126
+ ],
127
+ },
128
+ 'api': {
129
+ 'public': {
130
+ 'get': {
131
+ '/common/symbols': 1,
132
+ '/common/currencys': 1,
133
+ '/common/timestamp': 1,
134
+ '/q/kline': 1,
135
+ '/q/tickers': 1,
136
+ '/q/ticker/price': 1,
137
+ '/q/depth': 1,
138
+ '/q/deals': 1,
139
+ // contracts:
140
+ '/contract/common/brokerInfo': 1,
141
+ '/contract/q/index': 1,
142
+ '/contract/q/depth': 1,
143
+ '/contract/q/depthMerged': 1,
144
+ '/contract/q/trades': 1,
145
+ '/contract/q/kline': 1,
146
+ '/contract/q/ticker24hr': 1,
147
+ },
148
+ },
149
+ 'private': {
150
+ 'get': {
151
+ '/u/api/info': 1,
152
+ '/u/account/balance': 1,
153
+ '/u/wallet/address': 1,
154
+ '/u/wallet/depositRecord': 1,
155
+ '/u/wallet/withdrawRecord': 1,
156
+ '/u/order/openOrders': 1,
157
+ '/u/order/openOrder/detail': 1,
158
+ '/u/order/historyOrders': 1,
159
+ // contracts:
160
+ '/contract/trade/getOrder': 1,
161
+ '/contract/trade/openOrders': 1,
162
+ '/contract/trade/historyOrders': 1,
163
+ '/contract/trade/myTrades': 1,
164
+ '/contract/trade/positions': 1,
165
+ '/contract/u/account': 1,
166
+ },
167
+ 'post': {
168
+ '/u/account/transfer': 1,
169
+ '/u/wallet/withdraw': 1,
170
+ '/u/order/create': 1,
171
+ '/u/order/cancel': 1,
172
+ '/u/order/batchCreate': 1,
173
+ '/u/order/batchCancel': 1,
174
+ // contracts:
175
+ '/contract/trade/order': 1,
176
+ '/contract/trade/orderCancel': 1,
177
+ '/contract/trade/modifyMargin': 1,
178
+ '/contract/ws/dataStream/create': 1,
179
+ '/contract/ws/dataStream/update': 1,
180
+ '/contract/ws/dataStream/delete': 1,
181
+ },
182
+ 'delete': {
183
+ },
184
+ },
185
+ },
186
+ 'fees': {
187
+ 'trading': {
188
+ 'tierBased': false,
189
+ 'percentage': true,
190
+ 'maker': this.parseNumber ('0.0015'),
191
+ 'taker': this.parseNumber ('0.002'),
192
+ },
193
+ },
194
+ 'options': {
195
+ 'timeframes': {
196
+ 'spot': {
197
+ },
198
+ 'contract': {
199
+ },
200
+ },
201
+ 'defaultType': 'spot', // spot, swap
202
+ 'networks': {
203
+ 'TRX': 'TRC-20',
204
+ 'TRC20': 'TRC-20',
205
+ 'ETH': 'ERC-20',
206
+ 'ERC20': 'ERC-20',
207
+ 'BEP20': 'BEP-20(BSC)',
208
+ },
209
+ },
210
+ 'commonCurrencies': {
211
+ },
212
+ 'exceptions': {
213
+ 'exact': {
214
+ '1005': InsufficientFunds,
215
+ },
216
+ 'broad': {
217
+ 'Not Enough balance': InsufficientFunds,
218
+ 'Order does not exist': InvalidOrder,
219
+ 'System busy, please try again later': BadRequest, // in my tests, this was thrown mostly when request was bad, not the problem of exchange. It is easily reproduced in 'cancelOrders'
220
+ },
221
+ },
222
+ });
223
+ }
224
+
225
+ async fetchMarkets (params = {}) {
226
+ const response = await this.publicGetCommonSymbols (params);
227
+ //
228
+ // {
229
+ // "code": "0",
230
+ // "data": [
231
+ // {
232
+ // "minimumOrderSize": "0",
233
+ // "minimumTradeVolume": "0E-18",
234
+ // "pricePrecision": "11",
235
+ // "supportTrade": true,
236
+ // "symbol": "COMT_USDT",
237
+ // "volumePrecision": 0
238
+ // },
239
+ // ],
240
+ // "msg": "success",
241
+ // "status": 0
242
+ // }
243
+ //
244
+ const data = this.safeValue (response, 'data');
245
+ const result = [];
246
+ for (let i = 0; i < data.length; i++) {
247
+ const market = data[i];
248
+ const id = this.safeString (market, 'symbol');
249
+ const [ baseId, quoteId ] = id.split ('_');
250
+ const base = this.safeCurrencyCode (baseId);
251
+ const quote = this.safeCurrencyCode (quoteId);
252
+ result.push ({
253
+ 'id': id,
254
+ 'symbol': base + '/' + quote,
255
+ 'base': base,
256
+ 'quote': quote,
257
+ 'settle': undefined,
258
+ 'baseId': baseId,
259
+ 'quoteId': quoteId,
260
+ 'settleId': undefined,
261
+ 'type': 'spot',
262
+ 'spot': true,
263
+ 'margin': false,
264
+ 'future': false,
265
+ 'swap': false,
266
+ 'option': false,
267
+ 'active': this.safeValue (market, 'supportTrade'),
268
+ 'contract': false,
269
+ 'linear': undefined,
270
+ 'inverse': undefined,
271
+ 'contractSize': undefined,
272
+ 'expiry': undefined,
273
+ 'expiryDatetime': undefined,
274
+ 'strike': undefined,
275
+ 'optionType': undefined,
276
+ 'precision': {
277
+ 'amount': this.safeInteger (market, 'volumePrecision'),
278
+ 'price': this.safeInteger (market, 'pricePrecision'),
279
+ },
280
+ 'limits': {
281
+ 'leverage': {
282
+ 'min': undefined,
283
+ 'max': undefined,
284
+ },
285
+ 'amount': {
286
+ 'min': this.safeNumber (market, 'minimumOrderSize'),
287
+ 'max': undefined,
288
+ },
289
+ 'price': {
290
+ 'min': undefined,
291
+ 'max': undefined,
292
+ },
293
+ 'cost': {
294
+ 'min': this.safeNumber (market, 'minimumTradeVolume'),
295
+ 'max': undefined,
296
+ },
297
+ },
298
+ 'info': market,
299
+ });
300
+ }
301
+ return result;
302
+ }
303
+
304
+ async fetchCurrencies (params = {}) {
305
+ const response = await this.publicGetCommonCurrencys (params);
306
+ //
307
+ // {
308
+ // "code": "0",
309
+ // "data": [
310
+ // {
311
+ // "currency": "ETH",
312
+ // "maxWithdrawOneDay": "100.000000000000000000",
313
+ // "maxWithdrawSingle": "50.000000000000000000",
314
+ // "minWithdrawSingle": "0.005000000000000000",
315
+ // "supportDeposit": true,
316
+ // "supportTrade": true,
317
+ // "supportWithdraw": true,
318
+ // "withdrawFee": 0.01
319
+ // },
320
+ // ],
321
+ // "msg": "success",
322
+ // "status": 0
323
+ // }
324
+ //
325
+ const data = this.safeValue (response, 'data', {});
326
+ const result = {};
327
+ for (let i = 0; i < data.length; i++) {
328
+ const currency = data[i];
329
+ const id = this.safeString (currency, 'currency');
330
+ const code = this.safeCurrencyCode (id);
331
+ const name = this.safeString (currency, 'name');
332
+ const withdrawEnabled = this.safeValue (currency, 'supportWithdraw');
333
+ const depositEnabled = this.safeValue (currency, 'supportDeposit');
334
+ const tradeEnabled = this.safeValue (currency, 'supportTrade');
335
+ const active = withdrawEnabled && depositEnabled && tradeEnabled;
336
+ result[code] = {
337
+ 'id': id,
338
+ 'code': code,
339
+ 'name': name,
340
+ 'deposit': depositEnabled,
341
+ 'withdraw': withdrawEnabled,
342
+ 'active': active,
343
+ 'fee': this.safeNumber (currency, 'withdrawFee'),
344
+ 'precision': undefined,
345
+ 'limits': {
346
+ 'amount': { 'min': undefined, 'max': undefined },
347
+ 'price': { 'min': undefined, 'max': undefined },
348
+ 'cost': { 'min': undefined, 'max': undefined },
349
+ 'withdraw': { 'min': this.safeNumber (currency, 'minWithdrawSingle'), 'max': this.safeNumber (currency, 'maxWithdrawSingle') },
350
+ },
351
+ 'info': currency,
352
+ };
353
+ }
354
+ return result;
355
+ }
356
+
357
+ async fetchTime (params = {}) {
358
+ const response = await this.publicGetCommonTimestamp (params);
359
+ //
360
+ // {
361
+ // "code": '0',
362
+ // "data": 1573542445411,
363
+ // "msg": "success",
364
+ // "status": 0
365
+ // }
366
+ //
367
+ return this.safeInteger (response, 'data');
368
+ }
369
+
370
+ async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
371
+ await this.loadMarkets ();
372
+ const market = this.market (symbol);
373
+ const request = {
374
+ 'symbol': market['id'],
375
+ 'period': this.timeframes[timeframe],
376
+ };
377
+ if (limit !== undefined) {
378
+ request['size'] = limit;
379
+ }
380
+ // their docs says that 'from/to' arguments are mandatory, however that's not true in reality
381
+ if (since !== undefined) {
382
+ request['from'] = since;
383
+ // when 'since' [from] argument is set, then exchange also requires 'to' value to be set. So we have to set 'to' argument depending 'limit' amount (if limit was not provided, then exchange-default 500).
384
+ if (limit === undefined) {
385
+ limit = 500;
386
+ }
387
+ const duration = this.parseTimeframe (timeframe);
388
+ const timerange = limit * duration * 1000;
389
+ request['to'] = this.sum (request['from'], timerange);
390
+ }
391
+ const response = await this.publicGetQKline (request);
392
+ //
393
+ // {
394
+ // "code": "0",
395
+ // "data": [
396
+ // {
397
+ // "close": "43414.68",
398
+ // "high": "43446.47",
399
+ // "low": "43403.05",
400
+ // "open": "43406.05",
401
+ // "quoteVolume": "61500.40099",
402
+ // "symbol": "BTC_USDT",
403
+ // "ts": "1646152440000",
404
+ // "volume": 1.41627
405
+ // },
406
+ // ],
407
+ // "msg": "success",
408
+ // "status": 0
409
+ // }
410
+ //
411
+ const data = this.safeValue (response, 'data', []);
412
+ return this.parseOHLCVs (data, market, timeframe, since, limit);
413
+ }
414
+
415
+ parseOHLCV (ohlcv, market = undefined) {
416
+ return [
417
+ this.safeInteger (ohlcv, 'ts'),
418
+ this.safeFloat (ohlcv, 'open'),
419
+ this.safeFloat (ohlcv, 'high'),
420
+ this.safeFloat (ohlcv, 'low'),
421
+ this.safeFloat (ohlcv, 'close'),
422
+ this.safeFloat (ohlcv, 'volume'),
423
+ ];
424
+ }
425
+
426
+ async fetchTicker (symbol, params = {}) {
427
+ await this.loadMarkets ();
428
+ const market = this.market (symbol);
429
+ const request = {
430
+ 'symbol': market['id'],
431
+ };
432
+ const response = await this.publicGetQTickers (this.extend (request, params));
433
+ //
434
+ // {
435
+ // "code": "0",
436
+ // "data": [
437
+ // {
438
+ // "change": "6.52",
439
+ // "close": "43573.470000",
440
+ // "high": "44940.540000",
441
+ // "low": "40799.840000",
442
+ // "open": "40905.780000",
443
+ // "quoteVolume": "225621691.5991",
444
+ // "symbol": "BTC_USDT",
445
+ // "ts": "1646156490781",
446
+ // "volume": 5210.349
447
+ // }
448
+ // ],
449
+ // "msg": "success",
450
+ // "status": 0
451
+ // }
452
+ //
453
+ const tickers = this.safeValue (response, 'data');
454
+ const ticker = this.safeValue (tickers, 0);
455
+ return this.parseTicker (ticker, market);
456
+ }
457
+
458
+ async fetchTickers (symbols = undefined, params = {}) {
459
+ await this.loadMarkets ();
460
+ const request = {};
461
+ if (symbols !== undefined) {
462
+ if (!Array.isArray (symbols)) {
463
+ throw new BadRequest (this.id + ' fetchTickers() symbols argument should be an array');
464
+ }
465
+ }
466
+ if (symbols !== undefined) {
467
+ const marketIds = this.marketIds (symbols);
468
+ request['symbol'] = marketIds.join (',');
469
+ }
470
+ const response = await this.publicGetQTickers (this.extend (request, params));
471
+ const tickers = this.safeValue (response, 'data');
472
+ return this.parseTickers (tickers, symbols, params);
473
+ }
474
+
475
+ parseTicker (ticker, market = undefined) {
476
+ const marketId = this.safeString (ticker, 'symbol');
477
+ const symbol = this.safeSymbol (marketId, market);
478
+ const timestamp = this.safeInteger (ticker, 'ts');
479
+ const last = this.safeString (ticker, 'close');
480
+ return this.safeTicker ({
481
+ 'symbol': symbol,
482
+ 'timestamp': timestamp,
483
+ 'datetime': this.iso8601 (timestamp),
484
+ 'high': this.safeString (ticker, 'high'),
485
+ 'low': this.safeString (ticker, 'low'),
486
+ 'bid': undefined,
487
+ 'bidVolume': undefined,
488
+ 'ask': undefined,
489
+ 'askVolume': undefined,
490
+ 'vwap': undefined,
491
+ 'open': this.safeString (ticker, 'open'),
492
+ 'close': last,
493
+ 'last': last,
494
+ 'previousClose': undefined,
495
+ 'change': this.safeString (ticker, 'change'),
496
+ 'percentage': undefined,
497
+ 'average': undefined,
498
+ 'baseVolume': this.safeString (ticker, 'volume'),
499
+ 'quoteVolume': this.safeString (ticker, 'quoteVolume'),
500
+ 'info': ticker,
501
+ }, market, false);
502
+ }
503
+
504
+ async fetchOrderBook (symbol, limit = undefined, params = {}) {
505
+ await this.loadMarkets ();
506
+ const market = this.market (symbol);
507
+ const request = {
508
+ 'symbol': market['id'],
509
+ };
510
+ if (limit !== undefined) {
511
+ request['depth'] = Math.min (limit, 50);
512
+ }
513
+ const response = await this.publicGetQDepth (this.extend (request, params));
514
+ //
515
+ // {
516
+ // "code": "0",
517
+ // "data": {
518
+ // "ask": [
519
+ // ["43820.07","0.86947"],
520
+ // ["43820.25","0.07503"],
521
+ // ],
522
+ // "bid": [
523
+ // ["43815.94","0.43743"],
524
+ // ["43815.72","0.08901"],
525
+ // ],
526
+ // "symbol": "BTC_USDT",
527
+ // "timestamp": 1646161595841
528
+ // },
529
+ // "msg": "success",
530
+ // "status": 0
531
+ // }
532
+ //
533
+ const data = this.safeValue (response, 'data');
534
+ return this.parseOrderBook (data, symbol, undefined, 'bid', 'ask');
535
+ }
536
+
537
+ async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
538
+ await this.loadMarkets ();
539
+ const market = this.market (symbol);
540
+ const request = {
541
+ 'symbol': market['id'],
542
+ };
543
+ if (limit !== undefined) {
544
+ request['size'] = Math.min (limit, 50);
545
+ }
546
+ const response = await this.publicGetQDeals (this.extend (request, params));
547
+ //
548
+ // {
549
+ // "code": "0",
550
+ // "data": [
551
+ // {
552
+ // "direction": "S",
553
+ // "price": "43930.63",
554
+ // "symbol": "BTC_USDT",
555
+ // "ts": "1646224171992",
556
+ // "volume": 0.030653
557
+ // }, // first item is most recent
558
+ // ],
559
+ // "msg": "success",
560
+ // "status": 0
561
+ // }
562
+ //
563
+ const trades = this.safeValue (response, 'data');
564
+ return this.parseTrades (trades, market, since, limit);
565
+ }
566
+
567
+ parseTrade (trade, market = undefined) {
568
+ const timestamp = this.safeInteger (trade, 'ts');
569
+ const marketId = this.safeString (trade, 'symbol');
570
+ market = this.safeMarket (marketId, market);
571
+ const side = this.parseTradeSide (this.safeString (trade, 'direction'));
572
+ const amount = this.safeNumber (trade, 'volume');
573
+ const price = this.safeNumber (trade, 'price');
574
+ const type = undefined;
575
+ const takerOrMaker = 'taker';
576
+ let id = this.safeString (trade, 'tid');
577
+ if (id === undefined) {
578
+ id = this.syntheticTradeId (market, timestamp, side, amount, price, type, takerOrMaker);
579
+ }
580
+ return this.safeTrade ({
581
+ 'id': id,
582
+ 'timestamp': timestamp,
583
+ 'datetime': this.iso8601 (timestamp),
584
+ 'symbol': market['symbol'],
585
+ 'order': undefined,
586
+ 'type': type,
587
+ 'side': side,
588
+ 'takerOrMaker': takerOrMaker,
589
+ 'price': price,
590
+ 'amount': amount,
591
+ 'cost': undefined,
592
+ 'fee': undefined,
593
+ 'info': trade,
594
+ }, market);
595
+ }
596
+
597
+ parseTradeSide (side) {
598
+ const sides = {
599
+ 'B': 'buy',
600
+ 'S': 'sell',
601
+ };
602
+ return this.safeString (sides, side, side);
603
+ }
604
+
605
+ syntheticTradeId (market = undefined, timestamp = undefined, side = undefined, amount = undefined, price = undefined, orderType = undefined, takerOrMaker = undefined) {
606
+ // TODO: can be unified method? this approach is being used by multiple exchanges (mexc, woo-coinsbit, dydx, ...)
607
+ let id = '';
608
+ if (timestamp !== undefined) {
609
+ id = this.numberToString (timestamp) + '-' + this.safeString (market, 'id', '_');
610
+ if (side !== undefined) {
611
+ id += '-' + side;
612
+ }
613
+ if (orderType !== undefined) {
614
+ id += '-' + orderType;
615
+ }
616
+ if (takerOrMaker !== undefined) {
617
+ id += '-' + takerOrMaker;
618
+ }
619
+ if (amount !== undefined) {
620
+ id += '-' + this.numberToString (amount);
621
+ }
622
+ if (price !== undefined) {
623
+ id += '-' + this.numberToString (price);
624
+ }
625
+ }
626
+ return id;
627
+ }
628
+
629
+ async fetchBalance (params = {}) {
630
+ await this.loadMarkets ();
631
+ const query = this.omit (params, 'type');
632
+ const response = await this.privateGetUAccountBalance (query);
633
+ //
634
+ // {
635
+ // "code": "0",
636
+ // "data": {
637
+ // "WALLET": [
638
+ // {
639
+ // "available": "0.221212121000000000",
640
+ // "currency": "PHX",
641
+ // "frozen": "0E-18",
642
+ // "total": 0.221212121
643
+ // },
644
+ // {
645
+ // "available": "44.959577229600000000",
646
+ // "currency": "USDT",
647
+ // "frozen": "0E-18",
648
+ // "total": 44.9595772296
649
+ // }
650
+ // ]
651
+ // },
652
+ // "msg": "success",
653
+ // "status": 0
654
+ // }
655
+ //
656
+ const balances = this.safeValue (response, 'data');
657
+ const wallets = this.safeValue (balances, 'WALLET');
658
+ const result = { 'info': wallets };
659
+ for (let i = 0; i < wallets.length; i++) {
660
+ const wallet = wallets[i];
661
+ const currencyId = wallet['currency'];
662
+ const code = this.safeCurrencyCode (currencyId);
663
+ const account = this.account ();
664
+ account['free'] = this.safeNumber (wallet, 'available');
665
+ account['used'] = this.safeNumber (wallet, 'frozen');
666
+ account['total'] = this.safeNumber (wallet, 'total');
667
+ result[code] = account;
668
+ }
669
+ return this.safeBalance (result);
670
+ }
671
+
672
+ async fetchDepositAddress (code, params = {}) {
673
+ await this.loadMarkets ();
674
+ const currency = this.currency (code);
675
+ const request = {
676
+ 'currency': currency['id'],
677
+ };
678
+ const response = await this.privateGetUWalletAddress (this.extend (request, params));
679
+ // NOTE: You can only retrieve addresses of already generated wallets - so should already have generated that COIN deposit address in UI. Otherwise, it seems from API you can't create/obtain addresses for those coins.
680
+ //
681
+ // {
682
+ // "code": "0",
683
+ // "data": [
684
+ // {
685
+ // "currency": "BTC",
686
+ // "address": "1m4k2yUKTSrX6SM9FGgvwMyxQbYtRVi2N",
687
+ // "memo": ""
688
+ // }
689
+ // ],
690
+ // "msg": "success",
691
+ // "status": 0
692
+ // }
693
+ //
694
+ const data = this.safeValue (response, 'data', {});
695
+ return this.parseDepositAddress (data, currency);
696
+ }
697
+
698
+ parseDepositAddress (data, currency = undefined) {
699
+ const depositObject = this.safeValue (data, 0);
700
+ const address = this.safeString (depositObject, 'address');
701
+ const tag = this.safeString (depositObject, 'memo');
702
+ const currencyId = this.safeString (depositObject, 'currency');
703
+ currency = this.safeCurrency (currencyId, currency);
704
+ return {
705
+ 'currency': currency['code'],
706
+ 'address': address,
707
+ 'tag': tag,
708
+ 'network': undefined,
709
+ 'info': data,
710
+ };
711
+ }
712
+
713
+ async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) {
714
+ if (code === undefined) {
715
+ throw new ArgumentsRequired (this.id + ' fetchDeposits() requires code argument');
716
+ }
717
+ await this.loadMarkets ();
718
+ const currency = this.currency (code);
719
+ const request = {
720
+ 'currency': currency['id'],
721
+ };
722
+ if (since !== undefined) {
723
+ request['startTime'] = since;
724
+ const endTime = this.milliseconds ();
725
+ request['endTime'] = endTime;
726
+ }
727
+ if (limit !== undefined) {
728
+ request['Size'] = limit; // Todo: id api-docs, 'size' is incorrectly required to be in Uppercase
729
+ }
730
+ const response = await this.privateGetUWalletDepositRecord (this.extend (request, params));
731
+ //
732
+ // {
733
+ // "code": "0",
734
+ // "data": {
735
+ // "data": [
736
+ // {
737
+ // "createTime": "1622274255000",
738
+ // "currency": "BNB",
739
+ // "fromAddress": "bnb10af52w77pkehgxhnwgeca50q2t2354q4xexa5y",
740
+ // "hash": "97B982F497782C2777C0F6AD16CEAAC65A93A364B684A23A71CFBB8C010DEEA6",
741
+ // "id": "2021052923441510234383337",
742
+ // "status": "0",
743
+ // "toAddress": "bnb13w64gkc42c0l45m2p5me4qn35z0a3ej9ldks3j_82784659",
744
+ // "volume": 0.073
745
+ // }
746
+ // ],
747
+ // "total": 1
748
+ // },
749
+ // "msg": "success",
750
+ // "status": 0
751
+ // }
752
+ //
753
+ const data = this.safeValue (response, 'data', {});
754
+ const dataInner = this.safeValue (data, 'data', []);
755
+ for (let i = 0; i < dataInner.length; i++) {
756
+ dataInner[i]['transactType'] = 'deposit';
757
+ }
758
+ return this.parseTransactions (dataInner, currency, since, limit, params);
759
+ }
760
+
761
+ async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) {
762
+ if (code === undefined) {
763
+ throw new ArgumentsRequired (this.id + ' fetchDeposits() requires code argument');
764
+ }
765
+ await this.loadMarkets ();
766
+ const currency = this.currency (code);
767
+ const request = {
768
+ 'currency': currency['id'],
769
+ };
770
+ if (since !== undefined) {
771
+ request['startTime'] = since;
772
+ const endTime = this.milliseconds ();
773
+ request['endTime'] = endTime;
774
+ }
775
+ if (limit !== undefined) {
776
+ request['Size'] = limit; // Todo: id api-docs, 'size' is incorrectly required to be in Uppercase
777
+ }
778
+ const response = await this.privateGetUWalletWithdrawRecord (this.extend (request, params));
779
+ //
780
+ // {
781
+ // "code": "0",
782
+ // "data": {
783
+ // "data": [
784
+ // {
785
+ // ...
786
+ // }
787
+ // ],
788
+ // "total": 1
789
+ // },
790
+ // "msg": "success",
791
+ // "status": 0
792
+ // }
793
+ //
794
+ const data = this.safeValue (response, 'data', {});
795
+ const dataInner = this.safeValue (data, 'data', []);
796
+ for (let i = 0; i < dataInner.length; i++) {
797
+ dataInner[i]['transactType'] = 'withdrawal';
798
+ }
799
+ return this.parseTransactions (dataInner, currency, since, limit, params);
800
+ }
801
+
802
+ parseTransaction (transaction, currency = undefined) {
803
+ //
804
+ // fetchDeposits
805
+ //
806
+ // {
807
+ // "createTime": "1622274255000",
808
+ // "currency": "BNB",
809
+ // "fromAddress": "bnb10af52w77pkehgxhnwgeca50q2t2354q4xexa5y",
810
+ // "hash": "97B982F497782C2777C0F6AD16CEAAC65A93A364B684A23A71CFBB8C010DEEA6",
811
+ // "id": "2021052923441510234383337",
812
+ // "status": "0",
813
+ // "toAddress": "bnb13w64gkc42c0l45m2p5me4qn35z0a3ej9ldks3j_82784659",
814
+ // "volume": 0.073
815
+ // }
816
+ //
817
+ const id = this.safeString (transaction, 'id');
818
+ const amount = this.safeNumber (transaction, 'volume');
819
+ const addressTo = this.safeValue (transaction, 'toAddress', {});
820
+ const addressFrom = this.safeString (transaction, 'fromAddress');
821
+ const txid = this.safeString (transaction, 'hash');
822
+ const type = this.safeString (transaction, 'transactType');
823
+ const timestamp = this.safeInteger (transaction, 'createTime');
824
+ const currencyId = this.safeString (transaction, 'currency');
825
+ const code = this.safeCurrencyCode (currencyId, currency);
826
+ const status = this.parseTransactionStatus (this.safeString (transaction, 'status'));
827
+ return {
828
+ 'id': id,
829
+ 'currency': code,
830
+ 'amount': amount,
831
+ 'network': undefined,
832
+ 'address': addressTo,
833
+ 'addressTo': addressTo,
834
+ 'addressFrom': addressFrom,
835
+ 'tag': undefined,
836
+ 'tagTo': undefined,
837
+ 'tagFrom': undefined,
838
+ 'status': status,
839
+ 'type': type,
840
+ 'updated': undefined,
841
+ 'txid': txid,
842
+ 'timestamp': timestamp,
843
+ 'datetime': this.iso8601 (timestamp),
844
+ 'fee': {
845
+ 'currency': code,
846
+ 'cost': undefined,
847
+ },
848
+ 'info': transaction,
849
+ };
850
+ }
851
+
852
+ parseTransactionStatus (status) {
853
+ const statuses = {
854
+ '-1': 'failed',
855
+ '0': 'ok',
856
+ '3': 'pending',
857
+ '5': 'pending',
858
+ };
859
+ return this.safeString (statuses, status, status);
860
+ }
861
+
862
+ async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
863
+ await this.loadMarkets ();
864
+ const market = this.market (symbol);
865
+ const direction = (side === 'buy') ? 'BID' : 'ASK';
866
+ const request = {
867
+ 'symbol': market['id'],
868
+ 'type': type.toUpperCase (),
869
+ 'volume': this.amountToPrecision (symbol, amount),
870
+ 'direction': direction,
871
+ };
872
+ if ((type !== 'market') && (price !== undefined)) {
873
+ request['price'] = this.priceToPrecision (symbol, price);
874
+ }
875
+ const response = await this.privatePostUOrderCreate (this.extend (request, params));
876
+ //
877
+ // {
878
+ // "code": "0",
879
+ // "data": "2022030302410146630023187",
880
+ // "msg": "Create Order Successfully",
881
+ // "status": 0
882
+ // }
883
+ //
884
+ return this.parseOrder (response, market);
885
+ }
886
+
887
+ async cancelOrder (id, symbol = undefined, params = {}) {
888
+ await this.loadMarkets ();
889
+ const market = (symbol !== undefined) ? this.market (symbol) : undefined;
890
+ const request = {
891
+ 'orderId': id,
892
+ };
893
+ const response = await this.privatePostUOrderCancel (this.extend (request, params));
894
+ //
895
+ // {
896
+ // "code": "0",
897
+ // "data": "2022030303032700030025325",
898
+ // "status": 0
899
+ // }
900
+ //
901
+ return this.parseOrder (response, market);
902
+ }
903
+
904
+ async cancelOrders (ids, symbol = undefined, params = {}) {
905
+ if (!Array.isArray (ids)) {
906
+ throw new ArgumentsRequired (this.id + ' cancelOrders() ids argument should be an array');
907
+ }
908
+ await this.loadMarkets ();
909
+ const request = {
910
+ 'orders': this.json (ids),
911
+ };
912
+ const response = await this.privatePostUOrderBatchCancel (this.extend (request, params));
913
+ // {
914
+ // "code": 0,
915
+ // "msg": "success",
916
+ // "data": {
917
+ // "success": 2,
918
+ // "fail": 0,
919
+ // "results": ["2019062312313131231"," 2019063123131312313"]
920
+ // }
921
+ // }
922
+ const data = this.safeValue (response, 'data');
923
+ const results = this.safeValue (data, 'results');
924
+ const market = (symbol !== undefined) ? this.market (symbol) : undefined;
925
+ return this.parseOrders (results, market, undefined, undefined, params);
926
+ }
927
+
928
+ async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
929
+ if (symbol === undefined) {
930
+ throw new ArgumentsRequired (this.id + ' fetchOrders() requires a symbol argument');
931
+ }
932
+ await this.loadMarkets ();
933
+ const market = this.market (symbol);
934
+ const request = {
935
+ 'symbol': market['id'],
936
+ };
937
+ if (limit !== undefined) {
938
+ request['size'] = limit; // Todo: id api-docs, 'size' is incorrectly required to be in Uppercase
939
+ }
940
+ const response = await this.privateGetUOrderOpenOrders (this.extend (request, params));
941
+ //
942
+ // {
943
+ // "code": "0",
944
+ // "data": {
945
+ // "data": [
946
+ // {
947
+ // "createdTime": "1646248301418",
948
+ // "dealVolume": "0E-18",
949
+ // "direction": "BID",
950
+ // "frozenVolumeByOrder": "2.421300000000000000",
951
+ // "id": "2022030303114141830007699",
952
+ // "price": "0.150000000000000000",
953
+ // "source": "WALLET",
954
+ // "status": "0",
955
+ // "symbol": "BKK_USDT",
956
+ // "totalVolume": "16.142000000000000000",
957
+ // "type": "LIMIT"
958
+ // }
959
+ // ],
960
+ // "pageRequest": {
961
+ // "asc": false,
962
+ // "orderBy": "id",
963
+ // "page": "1",
964
+ // "size": 10
965
+ // },
966
+ // "total": 1
967
+ // },
968
+ // "msg": "success",
969
+ // "status": 0
970
+ // }
971
+ //
972
+ const result = this.safeValue (response, 'data');
973
+ const innerData = this.safeValue (result, 'data');
974
+ return this.parseOrders (innerData, market, since, limit, params);
975
+ }
976
+
977
+ async fetchOpenOrder (id, symbol = undefined, params = {}) {
978
+ const request = {
979
+ 'orderId': id,
980
+ };
981
+ const response = await this.privateGetUOrderOpenOrderDetail (this.extend (request, params));
982
+ //
983
+ // {
984
+ // "code": "0",
985
+ // "data": {
986
+ // "createdTime": "1646248301418",
987
+ // "dealAvgPrice": "0",
988
+ // "dealVolume": "0E-18",
989
+ // "direction": "BID",
990
+ // "frozenVolumeByOrder": "2.421300000000000000",
991
+ // "id": "2022030303114141830002452",
992
+ // "price": "0.150000000000000000",
993
+ // "source": "WALLET",
994
+ // "status": "0",
995
+ // "symbol": "BKK_USDT",
996
+ // "totalVolume": "16.142000000000000000",
997
+ // "type": "LIMIT",
998
+ // "updateTime": 1646248301418
999
+ // },
1000
+ // "msg": "success",
1001
+ // "status": 0
1002
+ // }
1003
+ //
1004
+ const data = this.safeValue (response, 'data');
1005
+ const market = (symbol !== undefined) ? this.market (symbol) : undefined;
1006
+ return this.parseOrder (data, market);
1007
+ }
1008
+
1009
+ async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
1010
+ if (symbol === undefined) {
1011
+ throw new ArgumentsRequired (this.id + ' fetchOrders() requires a symbol argument');
1012
+ }
1013
+ await this.loadMarkets ();
1014
+ const market = this.market (symbol);
1015
+ const request = {
1016
+ 'symbol': market['id'],
1017
+ };
1018
+ if (limit !== undefined) {
1019
+ request['size'] = limit; // Todo: id api-docs, 'size' is incorrectly required to be in Uppercase
1020
+ }
1021
+ if (since !== undefined) {
1022
+ request['startTime'] = since;
1023
+ }
1024
+ const response = await this.privateGetUOrderHistoryOrders (this.extend (request, params));
1025
+ //
1026
+ // {
1027
+ // "code": "0",
1028
+ // "data": {
1029
+ // "data": [
1030
+ // {
1031
+ // "createdTime": "1646247807000",
1032
+ // "dealAvgPrice": "0",
1033
+ // "dealVolume": "0",
1034
+ // "direction": "BID",
1035
+ // "frozenVolumeByOrder": "1.65",
1036
+ // "id": "2022030303032700030025943",
1037
+ // "price": "0.15",
1038
+ // "source": "WALLET",
1039
+ // "status": "2",
1040
+ // "symbol": "BKK_USDT",
1041
+ // "totalVolume": "11",
1042
+ // "type": "LIMIT",
1043
+ // "updateTime": 1646247852558
1044
+ // },
1045
+ // ],
1046
+ // "pageRequest": {
1047
+ // "asc": false,
1048
+ // "orderBy": "id",
1049
+ // "page": "1",
1050
+ // "size": 10
1051
+ // },
1052
+ // "total": 6
1053
+ // },
1054
+ // "msg": "success",
1055
+ // "status": 0
1056
+ // }
1057
+ //
1058
+ const result = this.safeValue (response, 'data');
1059
+ const innerData = this.safeValue (result, 'data');
1060
+ return this.parseOrders (innerData, market, since, limit, params);
1061
+ }
1062
+
1063
+ parseOrder (order, market = undefined) {
1064
+ //
1065
+ // fetchOpenOrders
1066
+ //
1067
+ // {
1068
+ // "createdTime": "1646248301418",
1069
+ // "dealVolume": "0E-18",
1070
+ // "direction": "BID",
1071
+ // "frozenVolumeByOrder": "2.421300000000000000",
1072
+ // "id": "2022030303114141830007699",
1073
+ // "price": "0.150000000000000000",
1074
+ // "source": "WALLET",
1075
+ // "status": "0",
1076
+ // "symbol": "BKK_USDT",
1077
+ // "totalVolume": "16.142000000000000000",
1078
+ // "type": "LIMIT"
1079
+ // "stopPrice": "0.14", // present only for 'stop' order types
1080
+ // "operator": ">=" // present only for 'stop' order types
1081
+ // "dealAvgPrice": "0", // only present in 'fetchOrder' & 'fetchClosedOrders'
1082
+ // "updateTime": 1646248301418 // only present in 'fetchOrder' & 'fetchClosedOrders'
1083
+ // }
1084
+ //
1085
+ const timestamp = this.safeInteger (order, 'createdTime');
1086
+ const updateTime = this.safeInteger (order, 'updateTime');
1087
+ const filled = this.safeString (order, 'dealVolume');
1088
+ const side = this.parseOrderSide (this.safeString (order, 'direction'));
1089
+ const id = this.safeString2 (order, 'id', 'data');
1090
+ const price = this.safeString (order, 'price');
1091
+ const rawStatus = this.safeString (order, 'status');
1092
+ const rawType = this.safeString (order, 'type');
1093
+ const type = this.parseOrderType (rawType);
1094
+ let postOnly = false;
1095
+ if (rawType === 'LIMIT_MAKER') {
1096
+ postOnly = true;
1097
+ }
1098
+ let status = undefined;
1099
+ if (timestamp !== undefined) {
1100
+ // cancelOrder handling
1101
+ status = this.parseOrderStatus (rawStatus);
1102
+ }
1103
+ const marketId = this.safeString (order, 'symbol');
1104
+ market = this.safeMarket (marketId, market);
1105
+ const amount = this.safeString (order, 'totalVolume');
1106
+ const stopPrice = this.safeNumber (order, 'stopPrice');
1107
+ const average = this.safeString (order, 'dealAvgPrice');
1108
+ return this.safeOrder ({
1109
+ 'id': id,
1110
+ 'clientOrderId': undefined,
1111
+ 'timestamp': timestamp,
1112
+ 'datetime': this.iso8601 (timestamp),
1113
+ 'lastTradeTimestamp': updateTime,
1114
+ 'status': status,
1115
+ 'symbol': market['symbol'],
1116
+ 'type': type,
1117
+ 'timeInForce': undefined,
1118
+ 'postOnly': postOnly,
1119
+ 'side': side,
1120
+ 'price': price,
1121
+ 'stopPrice': stopPrice,
1122
+ 'average': average,
1123
+ 'amount': amount,
1124
+ 'filled': filled,
1125
+ 'remaining': undefined,
1126
+ 'cost': undefined,
1127
+ 'trades': undefined,
1128
+ 'fee': undefined,
1129
+ 'info': order,
1130
+ }, market);
1131
+ }
1132
+
1133
+ parseOrderSide (side) {
1134
+ const sides = {
1135
+ 'BID': 'buy',
1136
+ 'ASK': 'sell',
1137
+ };
1138
+ return this.safeString (sides, side, side);
1139
+ }
1140
+
1141
+ parseOrderStatus (status) {
1142
+ const statuses = {
1143
+ '0': 'open',
1144
+ '1': 'closed',
1145
+ '2': 'canceled',
1146
+ '3': 'open',
1147
+ };
1148
+ return this.safeString (statuses, status, status);
1149
+ }
1150
+
1151
+ parseOrderType (status) {
1152
+ const statuses = {
1153
+ 'MARKET': 'market',
1154
+ 'LIMIT': 'limit',
1155
+ 'LIMIT_MAKER': 'limit',
1156
+ 'STOP_LIMIT': 'limit',
1157
+ };
1158
+ return this.safeString (statuses, status, status);
1159
+ }
1160
+
1161
+ sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
1162
+ let url = this.urls['api'][api] + '/' + this.version + this.implodeParams (path, params);
1163
+ params = this.omit (params, this.extractParams (path));
1164
+ let paramsSortedEncoded = '';
1165
+ if (Object.keys (params).length) {
1166
+ paramsSortedEncoded = this.rawencode (this.keysort (params));
1167
+ if (method === 'GET') {
1168
+ url += '?' + paramsSortedEncoded;
1169
+ }
1170
+ }
1171
+ if (api === 'private') {
1172
+ this.checkRequiredCredentials ();
1173
+ const signature = this.hmac (this.encode (paramsSortedEncoded), this.encode (this.secret), 'sha256');
1174
+ headers = {
1175
+ 'Cache-Control': 'no-cache',
1176
+ 'Content-type': 'application/x-www-form-urlencoded',
1177
+ 'X_ACCESS_KEY': this.apiKey,
1178
+ 'X_SIGNATURE': signature,
1179
+ };
1180
+ if (method !== 'GET') {
1181
+ body = paramsSortedEncoded;
1182
+ }
1183
+ }
1184
+ return { 'url': url, 'method': method, 'body': body, 'headers': headers };
1185
+ }
1186
+
1187
+ handleErrors (code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
1188
+ if (response === undefined) {
1189
+ return;
1190
+ }
1191
+ //
1192
+ // success
1193
+ //
1194
+ // {
1195
+ // "code": "0",
1196
+ // "msg": "success",
1197
+ // "status": 0,
1198
+ // "data": [...],
1199
+ // }
1200
+ //
1201
+ //
1202
+ // action error
1203
+ //
1204
+ // {
1205
+ // "code":1005,
1206
+ // "msg":"BKK:Not Enough balance",
1207
+ // "status":0
1208
+ // }
1209
+ //
1210
+ //
1211
+ // HTTP error
1212
+ //
1213
+ // {
1214
+ // "timestamp": "1646041085490",
1215
+ // "status": "403",
1216
+ // "error": "Forbidden",
1217
+ // "message": "签名错误",
1218
+ // "path": "/whatever/incorrect/path"
1219
+ // }
1220
+ //
1221
+ const message = this.safeValue (response, 'msg');
1222
+ if (message === 'success') {
1223
+ return;
1224
+ }
1225
+ const responseCode = this.safeString (response, 'code');
1226
+ if (responseCode !== '0') {
1227
+ const feedback = this.id + ' ' + body;
1228
+ this.throwExactlyMatchedException (this.exceptions['exact'], responseCode, feedback);
1229
+ this.throwBroadlyMatchedException (this.exceptions['broad'], body, feedback);
1230
+ throw new ExchangeError (feedback);
1231
+ }
1232
+ }
1233
+ };