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/bitopro.js ADDED
@@ -0,0 +1,1443 @@
1
+ 'use strict';
2
+
3
+ // ---------------------------------------------------------------------------
4
+
5
+ const Exchange = require ('./base/Exchange');
6
+ const { ExchangeError, ArgumentsRequired, AuthenticationError, InvalidOrder, InsufficientFunds, BadRequest } = require ('./base/errors');
7
+ const Precise = require ('./base/Precise');
8
+
9
+ // ---------------------------------------------------------------------------
10
+
11
+ module.exports = class bitopro extends Exchange {
12
+ describe () {
13
+ return this.deepExtend (super.describe (), {
14
+ 'id': 'bitopro',
15
+ 'name': 'BitoPro',
16
+ 'countries': [ 'TW' ], // Taiwan
17
+ 'version': 'v3',
18
+ 'rateLimit': 100,
19
+ 'has': {
20
+ 'CORS': undefined,
21
+ 'spot': true,
22
+ 'margin': false,
23
+ 'swap': false,
24
+ 'future': false,
25
+ 'option': false,
26
+ 'cancelAllOrders': true,
27
+ 'cancelOrder': true,
28
+ 'cancelOrders': true,
29
+ 'createOrder': true,
30
+ 'editOrder': false,
31
+ 'fetchBalance': true,
32
+ 'fetchBorrowRate': false,
33
+ 'fetchBorrowRateHistories': false,
34
+ 'fetchBorrowRateHistory': false,
35
+ 'fetchBorrowRates': false,
36
+ 'fetchClosedOrders': true,
37
+ 'fetchCurrencies': true,
38
+ 'fetchDepositAddress': false,
39
+ 'fetchDeposits': true,
40
+ 'fetchFundingFees': false,
41
+ 'fetchFundingHistory': false,
42
+ 'fetchFundingRate': false,
43
+ 'fetchFundingRateHistory': false,
44
+ 'fetchFundingRates': false,
45
+ 'fetchIndexOHLCV': false,
46
+ 'fetchMarkets': true,
47
+ 'fetchMarkOHLCV': false,
48
+ 'fetchMyTrades': true,
49
+ 'fetchOHLCV': true,
50
+ 'fetchOpenOrders': true,
51
+ 'fetchOrder': true,
52
+ 'fetchOrderBook': true,
53
+ 'fetchOrders': false,
54
+ 'fetchOrderTrades': false,
55
+ 'fetchPositions': false,
56
+ 'fetchPremiumIndexOHLCV': false,
57
+ 'fetchTicker': true,
58
+ 'fetchTickers': true,
59
+ 'fetchTime': false,
60
+ 'fetchTrades': true,
61
+ 'fetchTradingFee': false,
62
+ 'fetchTradingFees': true,
63
+ 'fetchTransactions': false,
64
+ 'fetchTransfer': false,
65
+ 'fetchTransfers': false,
66
+ 'fetchWithdrawal': true,
67
+ 'fetchWithdrawals': true,
68
+ 'setLeverage': false,
69
+ 'setMarginMode': false,
70
+ 'transfer': false,
71
+ 'withdraw': true,
72
+ },
73
+ 'timeframes': {
74
+ '1m': '1m',
75
+ '5m': '5m',
76
+ '15m': '15m',
77
+ '30m': '30m',
78
+ '1h': '1h',
79
+ '3h': '3h',
80
+ '6h': '6h',
81
+ '12h': '12h',
82
+ '1d': '1d',
83
+ '1w': '1w',
84
+ '1M': '1M',
85
+ },
86
+ 'urls': {
87
+ 'logo': 'https://user-images.githubusercontent.com/1294454/158227251-3a92a220-9222-453c-9277-977c6677fe71.jpg',
88
+ 'api': 'https://api.bitopro.com/v3',
89
+ 'www': 'https://www.bitopro.com',
90
+ 'doc': [
91
+ 'https://github.com/bitoex/bitopro-offical-api-docs/blob/master/v3-1/rest-1/rest.md',
92
+ ],
93
+ 'fees': 'https://www.bitopro.com/fees',
94
+ },
95
+ 'requiredCredentials': {
96
+ 'apiKey': true,
97
+ 'secret': true,
98
+ },
99
+ 'api': {
100
+ 'public': {
101
+ 'get': [
102
+ 'order-book/{pair}',
103
+ 'tickers',
104
+ 'tickers/{pair}',
105
+ 'trades/{pair}',
106
+ 'provisioning/currencies',
107
+ 'provisioning/trading-pairs',
108
+ 'provisioning/limitations-and-fees',
109
+ 'trading-history/{pair}',
110
+ ],
111
+ },
112
+ 'private': {
113
+ 'get': [
114
+ 'accounts/balance',
115
+ 'orders/history',
116
+ 'orders/all/{pair}',
117
+ 'orders/trades/{pair}',
118
+ 'orders/{pair}/{orderId}',
119
+ 'wallet/withdraw/{currency}/{serial}',
120
+ 'wallet/withdraw/{currency}/id/{id}',
121
+ 'wallet/depositHistory/{currency}',
122
+ 'wallet/withdrawHistory/{currency}',
123
+ ],
124
+ 'post': [
125
+ 'orders/{pair}',
126
+ 'orders/batch',
127
+ 'wallet/withdraw/{currency}',
128
+ ],
129
+ 'put': [
130
+ 'orders',
131
+ ],
132
+ 'delete': [
133
+ 'orders/{pair}/{id}',
134
+ 'orders/all',
135
+ 'orders/{pair}',
136
+ ],
137
+ },
138
+ },
139
+ 'fees': {
140
+ 'trading': {
141
+ 'tierBased': true,
142
+ 'percentage': true,
143
+ 'maker': this.parseNumber ('0.001'),
144
+ 'taker': this.parseNumber ('0.002'),
145
+ 'tiers': {
146
+ 'taker': [
147
+ [ this.parseNumber ('0'), this.parseNumber ('0.002') ],
148
+ [ this.parseNumber ('3000000'), this.parseNumber ('0.00194') ],
149
+ [ this.parseNumber ('5000000'), this.parseNumber ('0.0015') ],
150
+ [ this.parseNumber ('30000000'), this.parseNumber ('0.0014') ],
151
+ [ this.parseNumber ('300000000'), this.parseNumber ('0.0013') ],
152
+ [ this.parseNumber ('550000000'), this.parseNumber ('0.0012') ],
153
+ [ this.parseNumber ('1300000000'), this.parseNumber ('0.0011') ],
154
+ ],
155
+ 'maker': [
156
+ [ this.parseNumber ('0'), this.parseNumber ('0.001') ],
157
+ [ this.parseNumber ('3000000'), this.parseNumber ('0.00097') ],
158
+ [ this.parseNumber ('5000000'), this.parseNumber ('0.0007') ],
159
+ [ this.parseNumber ('30000000'), this.parseNumber ('0.0006') ],
160
+ [ this.parseNumber ('300000000'), this.parseNumber ('0.0005') ],
161
+ [ this.parseNumber ('550000000'), this.parseNumber ('0.0004') ],
162
+ [ this.parseNumber ('1300000000'), this.parseNumber ('0.0003') ],
163
+ ],
164
+ },
165
+ },
166
+ },
167
+ 'options': {
168
+ 'networks': {
169
+ 'ERC20': 'ERC20',
170
+ 'ETH': 'ERC20',
171
+ 'TRX': 'TRX',
172
+ 'TRC20': 'TRX',
173
+ },
174
+ },
175
+ 'exceptions': {
176
+ 'exact': {
177
+ 'Unsupported currency.': BadRequest, // {"error":"Unsupported currency."}
178
+ 'Unsupported order type': BadRequest, // {"error":"Unsupported order type"}
179
+ 'Invalid body': BadRequest, // {"error":"Invalid body"}
180
+ 'Invalid Signature': AuthenticationError, // {"error":"Invalid Signature"}
181
+ 'Address not in whitelist.': BadRequest,
182
+ },
183
+ 'broad': {
184
+ 'Invalid amount': InvalidOrder, // {"error":"Invalid amount 0.0000000001, decimal limit is 8."}
185
+ 'Balance for ': InsufficientFunds, // {"error":"Balance for eth not enough, only has 0, but ordered 0.01."}
186
+ 'Invalid ': BadRequest, // {"error":"Invalid price -1."}
187
+ 'Wrong parameter': BadRequest, // {"error":"Wrong parameter: from"}
188
+ },
189
+ },
190
+ 'commonCurrencies': {
191
+ },
192
+ });
193
+ }
194
+
195
+ async fetchCurrencies (params = {}) {
196
+ const response = await this.publicGetProvisioningCurrencies (params);
197
+ const currencies = this.safeValue (response, 'data', []);
198
+ //
199
+ // {
200
+ // "data":[
201
+ // {
202
+ // "currency":"eth",
203
+ // "withdrawFee":"0.007",
204
+ // "minWithdraw":"0.001",
205
+ // "maxWithdraw":"1000",
206
+ // "maxDailyWithdraw":"2000",
207
+ // "withdraw":true,
208
+ // "deposit":true,
209
+ // "depositConfirmation":"12"
210
+ // }
211
+ // ]
212
+ // }
213
+ //
214
+ const result = {};
215
+ for (let i = 0; i < currencies.length; i++) {
216
+ const currency = currencies[i];
217
+ const currencyId = this.safeString (currency, 'currency');
218
+ const code = this.safeCurrencyCode (currencyId);
219
+ const deposit = this.safeValue (currency, 'deposit');
220
+ const withdraw = this.safeValue (currency, 'withdraw');
221
+ const fee = this.safeNumber (currency, 'withdrawFee');
222
+ const withdrawMin = this.safeNumber (currency, 'minWithdraw');
223
+ const withdrawMax = this.safeNumber (currency, 'maxWithdraw');
224
+ const limits = {
225
+ 'withdraw': {
226
+ 'min': withdrawMin,
227
+ 'max': withdrawMax,
228
+ },
229
+ 'amount': {
230
+ 'min': undefined,
231
+ 'max': undefined,
232
+ },
233
+ };
234
+ result[code] = {
235
+ 'id': currencyId,
236
+ 'code': code,
237
+ 'info': currency,
238
+ 'type': undefined,
239
+ 'name': undefined,
240
+ 'active': deposit && withdraw,
241
+ 'deposit': deposit,
242
+ 'withdraw': withdraw,
243
+ 'fee': fee,
244
+ 'precision': undefined,
245
+ 'limits': limits,
246
+ };
247
+ }
248
+ return result;
249
+ }
250
+
251
+ async fetchMarkets (params = {}) {
252
+ const response = await this.publicGetProvisioningTradingPairs ();
253
+ const markets = this.safeValue (response, 'data', []);
254
+ //
255
+ // {
256
+ // "data":[
257
+ // {
258
+ // "pair":"shib_twd",
259
+ // "base":"shib",
260
+ // "quote":"twd",
261
+ // "basePrecision":"8",
262
+ // "quotePrecision":"6",
263
+ // "minLimitBaseAmount":"100000",
264
+ // "maxLimitBaseAmount":"5500000000",
265
+ // "minMarketBuyQuoteAmount":"1000",
266
+ // "orderOpenLimit":"200",
267
+ // "maintain":false,
268
+ // "orderBookQuotePrecision":"6",
269
+ // "orderBookQuoteScaleLevel":"5"
270
+ // }
271
+ // ]
272
+ // }
273
+ //
274
+ const result = [];
275
+ for (let i = 0; i < markets.length; i++) {
276
+ const market = markets[i];
277
+ const active = !this.safeValue (market, 'maintain');
278
+ const id = this.safeString (market, 'pair');
279
+ const uppercaseId = id.toUpperCase ();
280
+ const baseId = this.safeString (market, 'base');
281
+ const quoteId = this.safeString (market, 'quote');
282
+ const base = this.safeCurrencyCode (baseId);
283
+ const quote = this.safeCurrencyCode (quoteId);
284
+ const symbol = base + '/' + quote;
285
+ const precision = {
286
+ 'price': this.safeInteger (market, 'quotePrecision'),
287
+ 'amount': this.safeInteger (market, 'basePrecision'),
288
+ };
289
+ const limits = {
290
+ 'amount': {
291
+ 'min': this.safeNumber (market, 'minLimitBaseAmount'),
292
+ 'max': this.safeNumber (market, 'maxLimitBaseAmount'),
293
+ },
294
+ 'price': {
295
+ 'min': undefined,
296
+ 'max': undefined,
297
+ },
298
+ 'cost': {
299
+ 'min': undefined,
300
+ 'max': undefined,
301
+ },
302
+ 'leverage': {
303
+ 'min': undefined,
304
+ 'max': undefined,
305
+ },
306
+ };
307
+ result.push ({
308
+ 'id': id,
309
+ 'uppercaseId': uppercaseId,
310
+ 'symbol': symbol,
311
+ 'base': base,
312
+ 'quote': quote,
313
+ 'baseId': base,
314
+ 'quoteId': quote,
315
+ 'settle': undefined,
316
+ 'settleId': undefined,
317
+ 'type': 'spot',
318
+ 'spot': true,
319
+ 'margin': false,
320
+ 'swap': false,
321
+ 'future': false,
322
+ 'option': false,
323
+ 'derivative': false,
324
+ 'contract': false,
325
+ 'linear': undefined,
326
+ 'inverse': undefined,
327
+ 'contractSize': undefined,
328
+ 'expiry': undefined,
329
+ 'expiryDatetime': undefined,
330
+ 'strike': undefined,
331
+ 'optionType': undefined,
332
+ 'limits': limits,
333
+ 'precision': precision,
334
+ 'active': active,
335
+ 'info': market,
336
+ });
337
+ }
338
+ return result;
339
+ }
340
+
341
+ parseTicker (ticker, market = undefined) {
342
+ //
343
+ // {
344
+ // "pair":"btc_twd",
345
+ // "lastPrice":"1182449.00000000",
346
+ // "isBuyer":false,
347
+ // "priceChange24hr":"-1.99",
348
+ // "volume24hr":"9.13089740",
349
+ // "high24hr":"1226097.00000000",
350
+ // "low24hr":"1181000.00000000"
351
+ // }
352
+ //
353
+ const marketId = this.safeString (ticker, 'pair');
354
+ market = this.safeMarket (marketId, market);
355
+ const symbol = this.safeString (market, 'symbol');
356
+ return this.safeTicker ({
357
+ 'symbol': symbol,
358
+ 'timestamp': undefined,
359
+ 'datetime': undefined,
360
+ 'high': this.safeString (ticker, 'high24hr'),
361
+ 'low': this.safeString (ticker, 'low24hr'),
362
+ 'bid': undefined,
363
+ 'bidVolume': undefined,
364
+ 'ask': undefined,
365
+ 'askVolume': undefined,
366
+ 'vwap': undefined,
367
+ 'open': undefined,
368
+ 'close': this.safeString (ticker, 'lastPrice'),
369
+ 'last': this.safeString (ticker, 'lastPrice'),
370
+ 'previousClose': undefined,
371
+ 'change': undefined,
372
+ 'percentage': this.safeString (ticker, 'priceChange24hr'),
373
+ 'average': undefined,
374
+ 'baseVolume': this.safeString (ticker, 'volume24hr'),
375
+ 'quoteVolume': undefined,
376
+ 'info': ticker,
377
+ }, market, false);
378
+ }
379
+
380
+ async fetchTicker (symbol, params = {}) {
381
+ await this.loadMarkets ();
382
+ const market = this.market (symbol);
383
+ const request = {
384
+ 'pair': market['id'],
385
+ };
386
+ const response = await this.publicGetTickersPair (this.extend (request, params));
387
+ const ticker = this.safeValue (response, 'data', {});
388
+ //
389
+ // {
390
+ // "data":{
391
+ // "pair":"btc_twd",
392
+ // "lastPrice":"1182449.00000000",
393
+ // "isBuyer":false,
394
+ // "priceChange24hr":"-1.99",
395
+ // "volume24hr":"9.13089740",
396
+ // "high24hr":"1226097.00000000",
397
+ // "low24hr":"1181000.00000000"
398
+ // }
399
+ // }
400
+ //
401
+ return this.parseTicker (ticker, market);
402
+ }
403
+
404
+ async fetchTickers (symbols = undefined, params = {}) {
405
+ await this.loadMarkets ();
406
+ const response = await this.publicGetTickers ();
407
+ const tickers = this.safeValue (response, 'data', []);
408
+ //
409
+ // {
410
+ // "data":[
411
+ // {
412
+ // "pair":"xrp_twd",
413
+ // "lastPrice":"21.26110000",
414
+ // "isBuyer":false,
415
+ // "priceChange24hr":"-6.53",
416
+ // "volume24hr":"102846.47084802",
417
+ // "high24hr":"23.24460000",
418
+ // "low24hr":"21.13730000"
419
+ // }
420
+ // ]
421
+ // }
422
+ //
423
+ return this.parseTickers (tickers, symbols);
424
+ }
425
+
426
+ async fetchOrderBook (symbol, limit = undefined, params = {}) {
427
+ await this.loadMarkets ();
428
+ const request = {
429
+ 'pair': this.marketId (symbol),
430
+ };
431
+ if (limit !== undefined) {
432
+ request['limit'] = limit;
433
+ }
434
+ const response = await this.publicGetOrderBookPair (this.extend (request, params));
435
+ //
436
+ // {
437
+ // "bids":[
438
+ // {
439
+ // "price":"1175271",
440
+ // "amount":"0.00022804",
441
+ // "count":1,
442
+ // "total":"0.00022804"
443
+ // }
444
+ // ],
445
+ // "asks":[
446
+ // {
447
+ // "price":"1176906",
448
+ // "amount":"0.0496",
449
+ // "count":1,
450
+ // "total":"0.0496"
451
+ // }
452
+ // ]
453
+ // }
454
+ //
455
+ return this.parseOrderBook (response, symbol, undefined, 'bids', 'asks', 'price', 'amount');
456
+ }
457
+
458
+ parseTrade (trade, market) {
459
+ //
460
+ // fetchTrades
461
+ // {
462
+ // "timestamp":1644651458,
463
+ // "price":"1180785.00000000",
464
+ // "amount":"0.00020000",
465
+ // "isBuyer":false
466
+ // }
467
+ //
468
+ // fetchMyTrades
469
+ // {
470
+ // "tradeId":"5685030251",
471
+ // "orderId":"9669168142",
472
+ // "price":"11821.8",
473
+ // "action":"SELL",
474
+ // "baseAmount":"0.01",
475
+ // "quoteAmount":"118.218",
476
+ // "fee":"0.236436",
477
+ // "feeSymbol":"BNB",
478
+ // "isTaker":true,
479
+ // "timestamp":1644905714862,
480
+ // "createdTimestamp":1644905714862
481
+ // }
482
+ //
483
+ const id = this.safeString (trade, 'tradeId');
484
+ const orderId = this.safeString (trade, 'orderId');
485
+ let timestamp = undefined;
486
+ if (id === undefined) {
487
+ timestamp = this.safeTimestamp (trade, 'timestamp');
488
+ } else {
489
+ timestamp = this.safeInteger (trade, 'timestamp');
490
+ }
491
+ const marketId = this.safeString (trade, 'pair');
492
+ market = this.safeMarket (marketId, market);
493
+ const symbol = this.safeString (market, 'symbol');
494
+ const price = this.safeString (trade, 'price');
495
+ const type = this.safeStringLower (trade, 'type');
496
+ let side = this.safeStringLower (trade, 'action');
497
+ if (side === undefined) {
498
+ const isBuyer = this.safeValue (trade, 'isBuyer');
499
+ if (isBuyer) {
500
+ side = 'buy';
501
+ } else {
502
+ side = 'sell';
503
+ }
504
+ }
505
+ let amount = this.safeString (trade, 'amount');
506
+ if (amount === undefined) {
507
+ amount = this.safeString (trade, 'baseAmount');
508
+ }
509
+ let fee = undefined;
510
+ const feeAmount = this.safeString (trade, 'fee');
511
+ const feeSymbol = this.safeCurrencyCode (this.safeString (trade, 'feeSymbol'));
512
+ if (feeAmount !== undefined) {
513
+ fee = {
514
+ 'cost': feeAmount,
515
+ 'currency': feeSymbol,
516
+ 'rate': undefined,
517
+ };
518
+ }
519
+ const isTaker = this.safeValue (trade, 'isTaker');
520
+ let takerOrMaker = undefined;
521
+ if (isTaker !== undefined) {
522
+ if (isTaker) {
523
+ takerOrMaker = 'taker';
524
+ } else {
525
+ takerOrMaker = 'maker';
526
+ }
527
+ }
528
+ return this.safeTrade ({
529
+ 'id': id,
530
+ 'info': trade,
531
+ 'order': orderId,
532
+ 'timestamp': timestamp,
533
+ 'datetime': this.iso8601 (timestamp),
534
+ 'symbol': symbol,
535
+ 'takerOrMaker': takerOrMaker,
536
+ 'type': type,
537
+ 'side': side,
538
+ 'price': price,
539
+ 'amount': amount,
540
+ 'cost': undefined,
541
+ 'fee': fee,
542
+ }, market);
543
+ }
544
+
545
+ async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
546
+ await this.loadMarkets ();
547
+ const market = this.market (symbol);
548
+ const request = {
549
+ 'pair': market['id'],
550
+ };
551
+ const response = await this.publicGetTradesPair (this.extend (request, params));
552
+ const trades = this.safeValue (response, 'data', []);
553
+ //
554
+ // {
555
+ // "data":[
556
+ // {
557
+ // "timestamp":1644651458,
558
+ // "price":"1180785.00000000",
559
+ // "amount":"0.00020000",
560
+ // "isBuyer":false
561
+ // }
562
+ // ]
563
+ // }
564
+ //
565
+ return this.parseTrades (trades, market, since, limit);
566
+ }
567
+
568
+ async fetchTradingFees (params = {}) {
569
+ await this.loadMarkets ();
570
+ const response = await this.publicGetProvisioningLimitationsAndFees (params);
571
+ const tradingFeeRate = this.safeValue (response, 'tradingFeeRate', {});
572
+ const first = this.safeValue (tradingFeeRate, 0);
573
+ //
574
+ // {
575
+ // "tradingFeeRate":[
576
+ // {
577
+ // "rank":0,
578
+ // "twdVolumeSymbol":"\u003c",
579
+ // "twdVolume":"3000000",
580
+ // "bitoAmountSymbol":"\u003c",
581
+ // "bitoAmount":"7500",
582
+ // "makerFee":"0.001",
583
+ // "takerFee":"0.002",
584
+ // "makerBitoFee":"0.0008",
585
+ // "takerBitoFee":"0.0016"
586
+ // }
587
+ // ],
588
+ // "orderFeesAndLimitations":[
589
+ // {
590
+ // "pair":"BTC/TWD",
591
+ // "minimumOrderAmount":"0.0001",
592
+ // "minimumOrderAmountBase":"BTC",
593
+ // "minimumOrderNumberOfDigits":"0"
594
+ // }
595
+ // ],
596
+ // "restrictionsOfWithdrawalFees":[
597
+ // {
598
+ // "currency":"TWD",
599
+ // "fee":"15",
600
+ // "minimumTradingAmount":"100",
601
+ // "maximumTradingAmount":"1000000",
602
+ // "dailyCumulativeMaximumAmount":"2000000",
603
+ // "remarks":"",
604
+ // "protocol":""
605
+ // }
606
+ // ],
607
+ // "cryptocurrencyDepositFeeAndConfirmation":[
608
+ // {
609
+ // "currency":"TWD",
610
+ // "generalDepositFees":"0",
611
+ // "blockchainConfirmationRequired":""
612
+ // }
613
+ // ],
614
+ // "ttCheckFeesAndLimitationsLevel1":[
615
+ // {
616
+ // "currency":"TWD",
617
+ // "redeemDailyCumulativeMaximumAmount":"",
618
+ // "generateMinimumTradingAmount":"",
619
+ // "generateMaximumTradingAmount":"",
620
+ // "generateDailyCumulativeMaximumAmount":""
621
+ // }
622
+ // ],
623
+ // "ttCheckFeesAndLimitationsLevel2":[
624
+ // {
625
+ // "currency":"TWD",
626
+ // "redeemDailyCumulativeMaximumAmount":"20000000",
627
+ // "generateMinimumTradingAmount":"30",
628
+ // "generateMaximumTradingAmount":"10000000",
629
+ // "generateDailyCumulativeMaximumAmount":"10000000"
630
+ // }
631
+ // ]
632
+ // }
633
+ //
634
+ const result = {};
635
+ const maker = this.safeNumber (first, 'makerFee');
636
+ const taker = this.safeNumber (first, 'takerFee');
637
+ for (let i = 0; i < this.symbols.length; i++) {
638
+ const symbol = this.symbols[i];
639
+ result[symbol] = {
640
+ 'info': first,
641
+ 'symbol': symbol,
642
+ 'maker': maker,
643
+ 'taker': taker,
644
+ 'percentage': true,
645
+ 'tierBased': true,
646
+ };
647
+ }
648
+ return result;
649
+ }
650
+
651
+ parseOHLCV (ohlcv, market = undefined, timeframe = '1m', since = undefined, limit = undefined) {
652
+ return [
653
+ this.safeInteger (ohlcv, 'timestamp'),
654
+ this.safeNumber (ohlcv, 'open'),
655
+ this.safeNumber (ohlcv, 'high'),
656
+ this.safeNumber (ohlcv, 'low'),
657
+ this.safeNumber (ohlcv, 'close'),
658
+ this.safeNumber (ohlcv, 'volume'),
659
+ ];
660
+ }
661
+
662
+ async fetchOHLCV (symbol, timeframe = '5m', since = undefined, limit = undefined, params = {}) {
663
+ await this.loadMarkets ();
664
+ const market = this.market (symbol);
665
+ const resolution = this.timeframes[timeframe];
666
+ const request = {
667
+ 'pair': market['id'],
668
+ 'resolution': resolution,
669
+ };
670
+ // we need to have a limit argument because "to" and "from" are required
671
+ if (limit === undefined) {
672
+ limit = 500;
673
+ }
674
+ const timeframeInSeconds = this.parseTimeframe (timeframe);
675
+ let alignedSince = undefined;
676
+ if (since === undefined) {
677
+ request['to'] = this.seconds ();
678
+ request['from'] = request['to'] - (limit * timeframeInSeconds);
679
+ } else {
680
+ const timeframeInMilliseconds = timeframeInSeconds * 1000;
681
+ alignedSince = Math.floor (since / timeframeInMilliseconds) * timeframeInMilliseconds;
682
+ request['from'] = Math.floor (since / 1000);
683
+ request['to'] = this.sum (request['from'], limit * timeframeInSeconds);
684
+ }
685
+ const response = await this.publicGetTradingHistoryPair (this.extend (request, params));
686
+ const data = this.safeValue (response, 'data', []);
687
+ //
688
+ // {
689
+ // "data":[
690
+ // {
691
+ // "timestamp":1644581100000,
692
+ // "open":"1214737",
693
+ // "high":"1215110",
694
+ // "low":"1214737",
695
+ // "close":"1215110",
696
+ // "volume":"0.08423959"
697
+ // }
698
+ // ]
699
+ // }
700
+ //
701
+ const sparse = this.parseOHLCVs (data, market, timeframe, since, limit);
702
+ return this.insertMissingCandles (sparse, timeframeInSeconds, alignedSince, limit);
703
+ }
704
+
705
+ insertMissingCandles (candles, distance, since, limit) {
706
+ // the exchange doesn't send zero volume candles so we emulate them instead
707
+ // otherwise sending a limit arg leads to unexpected results
708
+ const length = candles.length;
709
+ if (length === 0) {
710
+ return candles;
711
+ }
712
+ const result = [];
713
+ let copyFrom = candles[0];
714
+ let timestamp = undefined;
715
+ if (since === undefined) {
716
+ timestamp = copyFrom[0];
717
+ } else {
718
+ timestamp = since;
719
+ }
720
+ let i = 0;
721
+ const candleLength = candles.length;
722
+ let resultLength = 0;
723
+ while ((resultLength < limit) && (i < candleLength)) {
724
+ const candle = candles[i];
725
+ if (candle[0] === timestamp) {
726
+ result.push (candle);
727
+ i = this.sum (i, 1);
728
+ } else {
729
+ const copy = this.arrayConcat ([], copyFrom);
730
+ copy[0] = timestamp;
731
+ // set open, high, low to close
732
+ copy[1] = copy[4];
733
+ copy[2] = copy[4];
734
+ copy[3] = copy[4];
735
+ copy[5] = this.parseNumber ('0');
736
+ result.push (copy);
737
+ }
738
+ timestamp = this.sum (timestamp, distance * 1000);
739
+ resultLength = result.length;
740
+ copyFrom = result[resultLength - 1];
741
+ }
742
+ return result;
743
+ }
744
+
745
+ parseBalance (response) {
746
+ //
747
+ // [{
748
+ // "currency":"twd",
749
+ // "amount":"0",
750
+ // "available":"0",
751
+ // "stake":"0",
752
+ // "tradable":true
753
+ // }]
754
+ //
755
+ const result = {
756
+ 'info': response,
757
+ };
758
+ for (let i = 0; i < response.length; i++) {
759
+ const balance = response[i];
760
+ const currencyId = this.safeString (balance, 'currency');
761
+ const code = this.safeCurrencyCode (currencyId);
762
+ const amount = this.safeString (balance, 'amount');
763
+ const available = this.safeString (balance, 'available');
764
+ const account = {
765
+ 'free': available,
766
+ 'total': amount,
767
+ };
768
+ result[code] = account;
769
+ }
770
+ return this.safeBalance (result);
771
+ }
772
+
773
+ async fetchBalance (params = {}) {
774
+ await this.loadMarkets ();
775
+ const response = await this.privateGetAccountsBalance (params);
776
+ const balances = this.safeValue (response, 'data', []);
777
+ //
778
+ // {
779
+ // "data":[
780
+ // {
781
+ // "currency":"twd",
782
+ // "amount":"0",
783
+ // "available":"0",
784
+ // "stake":"0",
785
+ // "tradable":true
786
+ // }
787
+ // ]
788
+ // }
789
+ //
790
+ return this.parseBalance (balances);
791
+ }
792
+
793
+ parseOrderStatus (status) {
794
+ const statuses = {
795
+ '-1': 'open',
796
+ '0': 'open',
797
+ '1': 'open',
798
+ '2': 'closed',
799
+ '3': 'closed',
800
+ '4': 'canceled',
801
+ };
802
+ return this.safeString (statuses, status, undefined);
803
+ }
804
+
805
+ parseOrder (order, market = undefined) {
806
+ //
807
+ // createOrder
808
+ // {
809
+ // orderId: '2220595581',
810
+ // timestamp: '1644896744886',
811
+ // action: 'SELL',
812
+ // amount: '0.01',
813
+ // price: '15000',
814
+ // timeInForce: 'GTC'
815
+ // }
816
+ //
817
+ // fetchOrder
818
+ // {
819
+ // "id":"8777138788",
820
+ // "pair":"bnb_twd",
821
+ // "price":"16000",
822
+ // "avgExecutionPrice":"0",
823
+ // "action":"SELL",
824
+ // "type":"LIMIT",
825
+ // "timestamp":1644899002598,
826
+ // "status":4,
827
+ // "originalAmount":"0.01",
828
+ // "remainingAmount":"0.01",
829
+ // "executedAmount":"0",
830
+ // "fee":"0",
831
+ // "feeSymbol":"twd",
832
+ // "bitoFee":"0",
833
+ // "total":"0",
834
+ // "seq":"BNBTWD548774666",
835
+ // "timeInForce":"GTC",
836
+ // "createdTimestamp":1644898944074,
837
+ // "updatedTimestamp":1644899002598
838
+ // }
839
+ //
840
+ const id = this.safeString2 (order, 'id', 'orderId');
841
+ const timestamp = this.safeInteger2 (order, 'timestamp', 'createdTimestamp');
842
+ let side = this.safeString (order, 'action');
843
+ side = side.toLowerCase ();
844
+ const amount = this.safeString2 (order, 'amount', 'originalAmount');
845
+ const price = this.safeString (order, 'price');
846
+ const marketId = this.safeString (order, 'pair');
847
+ market = this.safeMarket (marketId, market, '_');
848
+ const symbol = this.safeString (market, 'symbol');
849
+ const orderStatus = this.safeString (order, 'status');
850
+ const status = this.parseOrderStatus (orderStatus);
851
+ const type = this.safeStringLower (order, 'type');
852
+ const average = this.safeString (order, 'avgExecutionPrice');
853
+ const filled = this.safeString (order, 'executedAmount');
854
+ const remaining = this.safeString (order, 'remainingAmount');
855
+ const timeInForce = this.safeString (order, 'timeInForce');
856
+ let fee = undefined;
857
+ const feeAmount = this.safeString (order, 'fee');
858
+ const feeSymbol = this.safeCurrencyCode (this.safeString (order, 'feeSymbol'));
859
+ if (Precise.stringGt (feeAmount, '0')) {
860
+ fee = {
861
+ 'currency': feeSymbol,
862
+ 'cost': feeAmount,
863
+ };
864
+ }
865
+ return this.safeOrder ({
866
+ 'id': id,
867
+ 'clientOrderId': undefined,
868
+ 'timestamp': timestamp,
869
+ 'datetime': this.iso8601 (timestamp),
870
+ 'lastTradeTimestamp': this.safeInteger (order, 'updatedTimestamp'),
871
+ 'symbol': symbol,
872
+ 'type': type,
873
+ 'timeInForce': timeInForce,
874
+ 'postOnly': undefined,
875
+ 'side': side,
876
+ 'price': price,
877
+ 'stopPrice': undefined,
878
+ 'amount': amount,
879
+ 'cost': undefined,
880
+ 'average': average,
881
+ 'filled': filled,
882
+ 'remaining': remaining,
883
+ 'status': status,
884
+ 'fee': fee,
885
+ 'trades': undefined,
886
+ 'info': order,
887
+ }, market);
888
+ }
889
+
890
+ async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
891
+ await this.loadMarkets ();
892
+ const market = this.market (symbol);
893
+ const request = {
894
+ 'type': type,
895
+ 'pair': market['id'],
896
+ 'action': side,
897
+ 'amount': this.amountToPrecision (symbol, amount),
898
+ 'timestamp': this.milliseconds (),
899
+ };
900
+ const orderType = type.toUpperCase ();
901
+ if ((orderType === 'LIMIT') || (orderType === 'STOP_LIMIT')) {
902
+ request['price'] = this.priceToPrecision (symbol, price);
903
+ }
904
+ if (orderType === 'STOP_LIMIT') {
905
+ const stopPrice = this.safeNumber (params, 'stopPrice');
906
+ if (stopPrice === undefined) {
907
+ throw new InvalidOrder (this.id + ' createOrder() requires a stopPrice parameter for ' + orderType + ' orders');
908
+ } else {
909
+ request['stopPrice'] = this.priceToPrecision (symbol, stopPrice);
910
+ }
911
+ const condition = this.safeString (params, 'condition');
912
+ if (condition === undefined) {
913
+ throw new InvalidOrder (this.id + ' createOrder() requires a condition parameter for ' + orderType + ' orders');
914
+ } else {
915
+ request['condition'] = condition;
916
+ }
917
+ }
918
+ const response = await this.privatePostOrdersPair (this.extend (request, params), params);
919
+ //
920
+ // {
921
+ // orderId: '2220595581',
922
+ // timestamp: '1644896744886',
923
+ // action: 'SELL',
924
+ // amount: '0.01',
925
+ // price: '15000',
926
+ // timeInForce: 'GTC'
927
+ // }
928
+ //
929
+ return this.parseOrder (response, market);
930
+ }
931
+
932
+ async cancelOrder (id, symbol = undefined, params = {}) {
933
+ if (symbol === undefined) {
934
+ throw new ArgumentsRequired (this.id + ' cancelOrder() requires the symbol argument');
935
+ }
936
+ await this.loadMarkets ();
937
+ const market = this.market (symbol);
938
+ const request = {
939
+ 'id': id,
940
+ 'pair': market['id'],
941
+ };
942
+ const response = await this.privateDeleteOrdersPairId (this.extend (request, params));
943
+ //
944
+ // {
945
+ // "orderId":"8777138788",
946
+ // "action":"SELL",
947
+ // "timestamp":1644899002465,
948
+ // "price":"16000",
949
+ // "amount":"0.01"
950
+ // }
951
+ //
952
+ return this.parseOrder (response, market);
953
+ }
954
+
955
+ async cancelOrders (ids, symbol = undefined, params = {}) {
956
+ if (symbol === undefined) {
957
+ throw new ArgumentsRequired (this.id + ' cancelOrders() requires a symbol argument');
958
+ }
959
+ await this.loadMarkets ();
960
+ const market = this.market (symbol);
961
+ const id = market['uppercaseId'];
962
+ const request = {};
963
+ request[id] = ids;
964
+ const response = await this.privatePutOrders (this.extend (request, params));
965
+ //
966
+ // {
967
+ // "data":{
968
+ // "BNB_TWD":[
969
+ // "5236347105",
970
+ // "359488711"
971
+ // ]
972
+ // }
973
+ // }
974
+ //
975
+ return response;
976
+ }
977
+
978
+ async cancelAllOrders (symbol = undefined, params = {}) {
979
+ await this.loadMarkets ();
980
+ const request = {
981
+ // 'pair': market['id'], // optional
982
+ };
983
+ // privateDeleteOrdersAll or privateDeleteOrdersPair
984
+ let method = this.safeString (this.options, 'privateDeleteOrdersPair', 'privateDeleteOrdersAll');
985
+ if (symbol !== undefined) {
986
+ const market = this.market (symbol);
987
+ request['pair'] = market['id'];
988
+ method = 'privateDeleteOrdersPair';
989
+ }
990
+ const response = await this[method] (this.extend (request, params));
991
+ const result = this.safeValue (response, 'data', {});
992
+ //
993
+ // {
994
+ // "data":{
995
+ // "BNB_TWD":[
996
+ // "9515988421",
997
+ // "4639130027"
998
+ // ]
999
+ // }
1000
+ // }
1001
+ //
1002
+ return result;
1003
+ }
1004
+
1005
+ async fetchOrder (id, symbol = undefined, params = {}) {
1006
+ if (symbol === undefined) {
1007
+ throw new ArgumentsRequired (this.id + ' fetchOrder() requires the symbol argument');
1008
+ }
1009
+ await this.loadMarkets ();
1010
+ const market = this.market (symbol);
1011
+ const request = {
1012
+ 'orderId': id,
1013
+ 'pair': market['id'],
1014
+ };
1015
+ const response = await this.privateGetOrdersPairOrderId (this.extend (request, params));
1016
+ //
1017
+ // {
1018
+ // "id":"8777138788",
1019
+ // "pair":"bnb_twd",
1020
+ // "price":"16000",
1021
+ // "avgExecutionPrice":"0",
1022
+ // "action":"SELL",
1023
+ // "type":"LIMIT",
1024
+ // "timestamp":1644899002598,
1025
+ // "status":4,
1026
+ // "originalAmount":"0.01",
1027
+ // "remainingAmount":"0.01",
1028
+ // "executedAmount":"0",
1029
+ // "fee":"0",
1030
+ // "feeSymbol":"twd",
1031
+ // "bitoFee":"0",
1032
+ // "total":"0",
1033
+ // "seq":"BNBTWD548774666",
1034
+ // "timeInForce":"GTC",
1035
+ // "createdTimestamp":1644898944074,
1036
+ // "updatedTimestamp":1644899002598
1037
+ // }
1038
+ //
1039
+ return this.parseOrder (response, market);
1040
+ }
1041
+
1042
+ async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
1043
+ if (symbol === undefined) {
1044
+ throw new ArgumentsRequired (this.id + ' fetchOrders() requires the symbol argument');
1045
+ }
1046
+ await this.loadMarkets ();
1047
+ const market = this.market (symbol);
1048
+ const request = {
1049
+ 'pair': market['id'],
1050
+ // 'startTimestamp': 0,
1051
+ // 'endTimestamp': 0,
1052
+ // 'statusKind': '',
1053
+ // 'orderId': '',
1054
+ };
1055
+ if (since !== undefined) {
1056
+ request['startTimestamp'] = since;
1057
+ }
1058
+ if (limit !== undefined) {
1059
+ request['limit'] = limit;
1060
+ }
1061
+ const response = await this.privateGetOrdersAllPair (this.extend (request, params), params);
1062
+ let orders = this.safeValue (response, 'data');
1063
+ if (orders === undefined) {
1064
+ orders = [];
1065
+ }
1066
+ //
1067
+ // {
1068
+ // "data":[
1069
+ // {
1070
+ // "id":"2220595581",
1071
+ // "pair":"bnb_twd",
1072
+ // "price":"15000",
1073
+ // "avgExecutionPrice":"0",
1074
+ // "action":"SELL",
1075
+ // "type":"LIMIT",
1076
+ // "createdTimestamp":1644896744886,
1077
+ // "updatedTimestamp":1644898706236,
1078
+ // "status":4,
1079
+ // "originalAmount":"0.01",
1080
+ // "remainingAmount":"0.01",
1081
+ // "executedAmount":"0",
1082
+ // "fee":"0",
1083
+ // "feeSymbol":"twd",
1084
+ // "bitoFee":"0",
1085
+ // "total":"0",
1086
+ // "seq":"BNBTWD8540871774",
1087
+ // "timeInForce":"GTC"
1088
+ // }
1089
+ // ]
1090
+ // }
1091
+ //
1092
+ return this.parseOrders (orders, market, since, limit);
1093
+ }
1094
+
1095
+ fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
1096
+ const request = {
1097
+ 'statusKind': 'OPEN',
1098
+ };
1099
+ return this.fetchOrders (symbol, since, limit, this.extend (request, params));
1100
+ }
1101
+
1102
+ async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
1103
+ const request = {
1104
+ 'statusKind': 'DONE',
1105
+ };
1106
+ return this.fetchOrders (symbol, since, limit, this.extend (request, params));
1107
+ }
1108
+
1109
+ async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
1110
+ if (symbol === undefined) {
1111
+ throw new ArgumentsRequired (this.id + ' fetchMyTrades() requires the symbol argument');
1112
+ }
1113
+ await this.loadMarkets ();
1114
+ const market = this.market (symbol);
1115
+ const request = {
1116
+ 'pair': market['id'],
1117
+ };
1118
+ const response = await this.privateGetOrdersTradesPair (this.extend (request, params));
1119
+ const trades = this.safeValue (response, 'data', []);
1120
+ //
1121
+ // {
1122
+ // "data":[
1123
+ // {
1124
+ // "tradeId":"5685030251",
1125
+ // "orderId":"9669168142",
1126
+ // "price":"11821.8",
1127
+ // "action":"SELL",
1128
+ // "baseAmount":"0.01",
1129
+ // "quoteAmount":"118.218",
1130
+ // "fee":"0.236436",
1131
+ // "feeSymbol":"BNB",
1132
+ // "isTaker":true,
1133
+ // "timestamp":1644905714862,
1134
+ // "createdTimestamp":1644905714862
1135
+ // }
1136
+ // ]
1137
+ // }
1138
+ //
1139
+ return this.parseTrades (trades, market, since, limit);
1140
+ }
1141
+
1142
+ parseTransactionStatus (status) {
1143
+ const states = {
1144
+ 'COMPLETE': 'ok',
1145
+ 'INVALID': 'failed',
1146
+ 'PROCESSING': 'pending',
1147
+ 'WAIT_PROCESS': 'pending',
1148
+ 'FAILED': 'failed',
1149
+ 'EXPIRED': 'failed',
1150
+ 'CANCELLED': 'failed',
1151
+ 'EMAIL_VERIFICATION': 'pending',
1152
+ 'WAIT_CONFIRMATION': 'pending',
1153
+ };
1154
+ return this.safeString (states, status, status);
1155
+ }
1156
+
1157
+ parseTransaction (transaction, currency = undefined) {
1158
+ //
1159
+ // fetchDeposits
1160
+ // {
1161
+ // "serial":"20220214X766799",
1162
+ // "timestamp":"1644833015053",
1163
+ // "address":"bnb1xml62k5a9dcewgc542fha75fyxdcp0zv8eqfsh",
1164
+ // "amount":"0.20000000",
1165
+ // "fee":"0.00000000",
1166
+ // "total":"0.20000000",
1167
+ // "status":"COMPLETE",
1168
+ // "txid":"A3CC4F6828CC752B9F3737F48B5826B9EC2857040CB5141D0CC955F7E53DB6D9",
1169
+ // "message":"778553959",
1170
+ // "protocol":"MAIN",
1171
+ // "id":"2905906537"
1172
+ // }
1173
+ //
1174
+ // fetchWithdrawals || fetchWithdraw
1175
+ // {
1176
+ // "serial":"20220215BW14069838",
1177
+ // "timestamp":"1644907716044",
1178
+ // "address":"TKrwMaZaGiAvtXCFT41xHuusNcs4LPWS7w",
1179
+ // "amount":"8.00000000",
1180
+ // "fee":"2.00000000",
1181
+ // "total":"10.00000000",
1182
+ // "status":"COMPLETE",
1183
+ // "txid":"50bf250c71a582f40cf699fb58bab978437ea9bdf7259ff8072e669aab30c32b",
1184
+ // "protocol":"TRX",
1185
+ // "id":"9925310345"
1186
+ // }
1187
+ //
1188
+ // withdraw
1189
+ // {
1190
+ // "serial":"20220215BW14069838",
1191
+ // "currency":"USDT",
1192
+ // "protocol":"TRX",
1193
+ // "address":"TKrwMaZaGiAvtXCFT41xHuusNcs4LPWS7w",
1194
+ // "amount":"8",
1195
+ // "fee":"2",
1196
+ // "total":"10"
1197
+ // }
1198
+ //
1199
+ const currencyId = this.safeString (transaction, 'coin');
1200
+ const code = this.safeCurrencyCode (currencyId, currency);
1201
+ const id = this.safeString (transaction, 'serial');
1202
+ const txId = this.safeString (transaction, 'txid');
1203
+ const timestamp = this.safeInteger (transaction, 'timestamp');
1204
+ const amount = this.safeNumber (transaction, 'total');
1205
+ const address = this.safeString (transaction, 'address');
1206
+ const tag = this.safeString (transaction, 'message');
1207
+ const status = this.safeString (transaction, 'status');
1208
+ const fee = this.safeNumber (transaction, 'fee');
1209
+ return {
1210
+ 'info': transaction,
1211
+ 'id': id,
1212
+ 'txid': txId,
1213
+ 'timestamp': timestamp,
1214
+ 'datetime': this.iso8601 (timestamp),
1215
+ 'network': undefined,
1216
+ 'addressFrom': undefined,
1217
+ 'address': address,
1218
+ 'addressTo': address,
1219
+ 'tagFrom': undefined,
1220
+ 'tag': tag,
1221
+ 'tagTo': tag,
1222
+ 'type': undefined,
1223
+ 'amount': amount,
1224
+ 'currency': code,
1225
+ 'status': this.parseTransactionStatus (status),
1226
+ 'updated': undefined,
1227
+ 'fee': {
1228
+ 'currency': code,
1229
+ 'cost': fee,
1230
+ 'rate': undefined,
1231
+ },
1232
+ };
1233
+ }
1234
+
1235
+ async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) {
1236
+ if (code === undefined) {
1237
+ throw new ArgumentsRequired (this.id + ' fetchDeposits() requires the code argument');
1238
+ }
1239
+ await this.loadMarkets ();
1240
+ const currency = this.safeCurrency (code);
1241
+ const request = {
1242
+ 'currency': currency['id'],
1243
+ // 'endTimestamp': 0,
1244
+ // 'id': '',
1245
+ // 'statuses': '', // 'ROCESSING,COMPLETE,INVALID,WAIT_PROCESS,CANCELLED,FAILED'
1246
+ };
1247
+ if (since !== undefined) {
1248
+ request['startTimestamp'] = since;
1249
+ }
1250
+ if (limit !== undefined) {
1251
+ request['limit'] = limit;
1252
+ }
1253
+ const response = await this.privateGetWalletDepositHistoryCurrency (this.extend (request, params));
1254
+ const result = this.safeValue (response, 'data', []);
1255
+ //
1256
+ // {
1257
+ // "data":[
1258
+ // {
1259
+ // "serial":"20220214X766799",
1260
+ // "timestamp":"1644833015053",
1261
+ // "address":"bnb1xml62k5a9dcewgc542fha75fyxdcp0zv8eqfsh",
1262
+ // "amount":"0.20000000",
1263
+ // "fee":"0.00000000",
1264
+ // "total":"0.20000000",
1265
+ // "status":"COMPLETE",
1266
+ // "txid":"A3CC4F6828CC752B9F3737F48B5826B9EC2857040CB5141D0CC955F7E53DB6D9",
1267
+ // "message":"778553959",
1268
+ // "protocol":"MAIN",
1269
+ // "id":"2905906537"
1270
+ // }
1271
+ // ]
1272
+ // }
1273
+ //
1274
+ return this.parseTransactions (result, currency, since, limit, { 'type': 'deposit' });
1275
+ }
1276
+
1277
+ async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) {
1278
+ if (code === undefined) {
1279
+ throw new ArgumentsRequired (this.id + ' fetchWithdrawals() requires the code argument');
1280
+ }
1281
+ await this.loadMarkets ();
1282
+ const currency = this.safeCurrency (code);
1283
+ const request = {
1284
+ 'currency': currency['id'],
1285
+ // 'endTimestamp': 0,
1286
+ // 'id': '',
1287
+ // 'statuses': '', // 'PROCESSING,COMPLETE,EXPIRED,INVALID,WAIT_PROCESS,WAIT_CONFIRMATION,EMAIL_VERIFICATION,CANCELLED'
1288
+ };
1289
+ if (since !== undefined) {
1290
+ request['startTimestamp'] = since;
1291
+ }
1292
+ if (limit !== undefined) {
1293
+ request['limit'] = limit;
1294
+ }
1295
+ const response = await this.privateGetWalletWithdrawHistoryCurrency (this.extend (request, params));
1296
+ const result = this.safeValue (response, 'data', []);
1297
+ //
1298
+ // {
1299
+ // "data":[
1300
+ // {
1301
+ // "serial":"20220215BW14069838",
1302
+ // "timestamp":"1644907716044",
1303
+ // "address":"TKrwMaZaGiAvtXCFT41xHuusNcs4LPWS7w",
1304
+ // "amount":"8.00000000",
1305
+ // "fee":"2.00000000",
1306
+ // "total":"10.00000000",
1307
+ // "status":"COMPLETE",
1308
+ // "txid":"50bf250c71a582f40cf699fb58bab978437ea9bdf7259ff8072e669aab30c32b",
1309
+ // "protocol":"TRX",
1310
+ // "id":"9925310345"
1311
+ // }
1312
+ // ]
1313
+ // }
1314
+ //
1315
+ return this.parseTransactions (result, currency, since, limit, { 'type': 'withdrawal' });
1316
+ }
1317
+
1318
+ async fetchWithdrawal (id, code = undefined, params = {}) {
1319
+ if (code === undefined) {
1320
+ throw new ArgumentsRequired (this.id + ' fetchWithdrawal() requires the code argument');
1321
+ }
1322
+ await this.loadMarkets ();
1323
+ const currency = this.safeCurrency (code);
1324
+ const request = {
1325
+ 'serial': id,
1326
+ 'currency': currency['id'],
1327
+ };
1328
+ const response = await this.privateGetWalletWithdrawCurrencySerial (this.extend (request, params));
1329
+ const result = this.safeValue (response, 'data', {});
1330
+ //
1331
+ // {
1332
+ // "data":{
1333
+ // "serial":"20220215BW14069838",
1334
+ // "address":"TKrwMaZaGiAvtXCFT41xHuusNcs4LPWS7w",
1335
+ // "amount":"8.00000000",
1336
+ // "fee":"2.00000000",
1337
+ // "total":"10.00000000",
1338
+ // "status":"COMPLETE",
1339
+ // "txid":"50bf250c71a582f40cf699fb58bab978437ea9bdf7259ff8072e669aab30c32b",
1340
+ // "protocol":"TRX",
1341
+ // "id":"9925310345",
1342
+ // "timestamp":"1644907716044"
1343
+ // }
1344
+ // }
1345
+ //
1346
+ return this.parseTransaction (result, currency);
1347
+ }
1348
+
1349
+ async withdraw (code, amount, address, tag = undefined, params = {}) {
1350
+ [ tag, params ] = this.handleWithdrawTagAndParams (tag, params);
1351
+ await this.loadMarkets ();
1352
+ this.checkAddress (address);
1353
+ const currency = this.currency (code);
1354
+ const request = {
1355
+ 'currency': currency['id'],
1356
+ 'amount': this.numberToString (amount),
1357
+ 'address': address,
1358
+ };
1359
+ if ('network' in params) {
1360
+ const networks = this.safeValue (this.options, 'networks', {});
1361
+ const requestedNetwork = this.safeStringUpper (params, 'network');
1362
+ params = this.omit (params, [ 'network' ]);
1363
+ const networkId = this.safeString (networks, requestedNetwork);
1364
+ if (networkId === undefined) {
1365
+ throw new ExchangeError (this.id + ' invalid network ' + requestedNetwork);
1366
+ }
1367
+ request['protocol'] = networkId;
1368
+ }
1369
+ if (tag !== undefined) {
1370
+ request['message'] = tag;
1371
+ }
1372
+ const response = await this.privatePostWalletWithdrawCurrency (this.extend (request, params));
1373
+ const result = this.safeValue (response, 'data', {});
1374
+ //
1375
+ // {
1376
+ // "data":{
1377
+ // "serial":"20220215BW14069838",
1378
+ // "currency":"USDT",
1379
+ // "protocol":"TRX",
1380
+ // "address":"TKrwMaZaGiAvtXCFT41xHuusNcs4LPWS7w",
1381
+ // "amount":"8",
1382
+ // "fee":"2",
1383
+ // "total":"10"
1384
+ // }
1385
+ // }
1386
+ //
1387
+ return this.parseTransaction (result, currency);
1388
+ }
1389
+
1390
+ sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
1391
+ let url = '/' + this.implodeParams (path, params);
1392
+ const query = this.omit (params, this.extractParams (path));
1393
+ if (headers === undefined) {
1394
+ headers = {};
1395
+ }
1396
+ headers['X-BITOPRO-API'] = 'ccxt';
1397
+ if (api === 'private') {
1398
+ this.checkRequiredCredentials ();
1399
+ if (method === 'POST' || method === 'PUT') {
1400
+ body = this.json (params);
1401
+ const payload = this.stringToBase64 (body);
1402
+ const signature = this.hmac (payload, this.encode (this.secret), 'sha384');
1403
+ headers['X-BITOPRO-APIKEY'] = this.apiKey;
1404
+ headers['X-BITOPRO-PAYLOAD'] = payload;
1405
+ headers['X-BITOPRO-SIGNATURE'] = signature;
1406
+ } else if (method === 'GET' || method === 'DELETE') {
1407
+ if (Object.keys (query).length) {
1408
+ url += '?' + this.urlencode (query);
1409
+ }
1410
+ const nonce = this.milliseconds ();
1411
+ let rawData = {
1412
+ 'nonce': nonce,
1413
+ };
1414
+ rawData = this.json (rawData);
1415
+ const payload = this.stringToBase64 (rawData);
1416
+ const signature = this.hmac (payload, this.encode (this.secret), 'sha384');
1417
+ headers['X-BITOPRO-APIKEY'] = this.apiKey;
1418
+ headers['X-BITOPRO-PAYLOAD'] = payload;
1419
+ headers['X-BITOPRO-SIGNATURE'] = signature;
1420
+ }
1421
+ } else if (api === 'public' && method === 'GET') {
1422
+ if (Object.keys (query).length) {
1423
+ url += '?' + this.urlencode (query);
1424
+ }
1425
+ }
1426
+ url = this.urls['api'] + url;
1427
+ return { 'url': url, 'method': method, 'body': body, 'headers': headers };
1428
+ }
1429
+
1430
+ handleErrors (code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
1431
+ if (response === undefined) {
1432
+ return; // fallback to the default error handler
1433
+ }
1434
+ if (code >= 200 && code < 300) {
1435
+ return;
1436
+ }
1437
+ const feedback = this.id + ' ' + body;
1438
+ const error = this.safeString (response, 'error');
1439
+ this.throwExactlyMatchedException (this.exceptions['exact'], error, feedback);
1440
+ this.throwBroadlyMatchedException (this.exceptions['broad'], error, feedback);
1441
+ throw new ExchangeError (feedback); // unknown message
1442
+ }
1443
+ };