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/zonda.js ADDED
@@ -0,0 +1,1497 @@
1
+ 'use strict';
2
+
3
+ // ---------------------------------------------------------------------------
4
+
5
+ const Exchange = require ('./base/Exchange');
6
+ const { InvalidNonce, InsufficientFunds, AuthenticationError, InvalidOrder, ExchangeError, OrderNotFound, AccountSuspended, BadSymbol, OrderImmediatelyFillable, RateLimitExceeded, OnMaintenance, PermissionDenied } = require ('./base/errors');
7
+
8
+ // ---------------------------------------------------------------------------
9
+
10
+ module.exports = class zonda extends Exchange {
11
+ describe () {
12
+ return this.deepExtend (super.describe (), {
13
+ 'id': 'zonda',
14
+ 'name': 'Zonda',
15
+ 'countries': [ 'EE' ], // Estonia
16
+ 'rateLimit': 1000,
17
+ 'has': {
18
+ 'CORS': true,
19
+ 'spot': true,
20
+ 'margin': false,
21
+ 'swap': false,
22
+ 'future': false,
23
+ 'option': false,
24
+ 'addMargin': false,
25
+ 'cancelOrder': true,
26
+ 'createOrder': true,
27
+ 'createReduceOnlyOrder': false,
28
+ 'fetchBalance': true,
29
+ 'fetchBorrowRate': false,
30
+ 'fetchBorrowRateHistories': false,
31
+ 'fetchBorrowRateHistory': false,
32
+ 'fetchBorrowRates': false,
33
+ 'fetchBorrowRatesPerSymbol': false,
34
+ 'fetchFundingHistory': false,
35
+ 'fetchFundingRate': false,
36
+ 'fetchFundingRateHistory': false,
37
+ 'fetchFundingRates': false,
38
+ 'fetchIndexOHLCV': false,
39
+ 'fetchLedger': true,
40
+ 'fetchLeverage': false,
41
+ 'fetchLeverageTiers': false,
42
+ 'fetchMarkets': true,
43
+ 'fetchMarkOHLCV': false,
44
+ 'fetchMyTrades': true,
45
+ 'fetchOHLCV': true,
46
+ 'fetchOpenOrders': true,
47
+ 'fetchOrderBook': true,
48
+ 'fetchPosition': false,
49
+ 'fetchPositions': false,
50
+ 'fetchPositionsRisk': false,
51
+ 'fetchPremiumIndexOHLCV': false,
52
+ 'fetchTicker': true,
53
+ 'fetchTrades': true,
54
+ 'fetchTradingFee': false,
55
+ 'fetchTradingFees': false,
56
+ 'reduceMargin': false,
57
+ 'setLeverage': false,
58
+ 'setMarginMode': false,
59
+ 'setPositionMode': false,
60
+ 'transfer': true,
61
+ 'withdraw': true,
62
+ },
63
+ 'timeframes': {
64
+ '1m': '60',
65
+ '3m': '180',
66
+ '5m': '300',
67
+ '15m': '900',
68
+ '30m': '1800',
69
+ '1h': '3600',
70
+ '2h': '7200',
71
+ '4h': '14400',
72
+ '6h': '21600',
73
+ '12h': '43200',
74
+ '1d': '86400',
75
+ '3d': '259200',
76
+ '1w': '604800',
77
+ },
78
+ 'hostname': 'zonda.exchange',
79
+ 'urls': {
80
+ 'referral': 'https://auth.zondaglobal.com/ref/jHlbB4mIkdS1',
81
+ 'logo': 'https://user-images.githubusercontent.com/1294454/159202310-a0e38007-5e7c-4ba9-a32f-c8263a0291fe.jpg',
82
+ 'www': 'https://zondaglobal.com',
83
+ 'api': {
84
+ 'public': 'https://{hostname}/API/Public',
85
+ 'private': 'https://{hostname}/API/Trading/tradingApi.php',
86
+ 'v1_01Public': 'https://api.{hostname}/rest',
87
+ 'v1_01Private': 'https://api.{hostname}/rest',
88
+ },
89
+ 'doc': [
90
+ 'https://docs.zonda.exchange/',
91
+ 'https://github.com/BitBayNet/API',
92
+ ],
93
+ 'support': 'https://zondaglobal.com/en/helpdesk/zonda-exchange',
94
+ 'fees': 'https://zondaglobal.com/legal/zonda-exchange/fees',
95
+ },
96
+ 'api': {
97
+ 'public': {
98
+ 'get': [
99
+ '{id}/all',
100
+ '{id}/market',
101
+ '{id}/orderbook',
102
+ '{id}/ticker',
103
+ '{id}/trades',
104
+ ],
105
+ },
106
+ 'private': {
107
+ 'post': [
108
+ 'info',
109
+ 'trade',
110
+ 'cancel',
111
+ 'orderbook',
112
+ 'orders',
113
+ 'transfer',
114
+ 'withdraw',
115
+ 'history',
116
+ 'transactions',
117
+ ],
118
+ },
119
+ 'v1_01Public': {
120
+ 'get': [
121
+ 'trading/ticker',
122
+ 'trading/ticker/{symbol}',
123
+ 'trading/stats',
124
+ 'trading/stats/{symbol}',
125
+ 'trading/orderbook/{symbol}',
126
+ 'trading/transactions/{symbol}',
127
+ 'trading/candle/history/{symbol}/{resolution}',
128
+ ],
129
+ },
130
+ 'v1_01Private': {
131
+ 'get': [
132
+ 'payments/withdrawal/{detailId}',
133
+ 'payments/deposit/{detailId}',
134
+ 'trading/offer',
135
+ 'trading/config/{symbol}',
136
+ 'trading/history/transactions',
137
+ 'balances/BITBAY/history',
138
+ 'balances/BITBAY/balance',
139
+ 'fiat_cantor/rate/{baseId}/{quoteId}',
140
+ 'fiat_cantor/history',
141
+ ],
142
+ 'post': [
143
+ 'trading/offer/{symbol}',
144
+ 'trading/config/{symbol}',
145
+ 'balances/BITBAY/balance',
146
+ 'balances/BITBAY/balance/transfer/{source}/{destination}',
147
+ 'fiat_cantor/exchange',
148
+ ],
149
+ 'delete': [
150
+ 'trading/offer/{symbol}/{id}/{side}/{price}',
151
+ ],
152
+ 'put': [
153
+ 'balances/BITBAY/balance/{id}',
154
+ ],
155
+ },
156
+ },
157
+ 'fees': {
158
+ 'trading': {
159
+ 'maker': this.parseNumber ('0.0'),
160
+ 'taker': this.parseNumber ('0.001'),
161
+ 'percentage': true,
162
+ 'tierBased': false,
163
+ },
164
+ 'fiat': {
165
+ 'maker': 0.30 / 100,
166
+ 'taker': 0.43 / 100,
167
+ 'percentage': true,
168
+ 'tierBased': true,
169
+ 'tiers': {
170
+ 'taker': [
171
+ [ 0.0043, 0 ],
172
+ [ 0.0042, 1250 ],
173
+ [ 0.0041, 3750 ],
174
+ [ 0.0040, 7500 ],
175
+ [ 0.0039, 10000 ],
176
+ [ 0.0038, 15000 ],
177
+ [ 0.0037, 20000 ],
178
+ [ 0.0036, 25000 ],
179
+ [ 0.0035, 37500 ],
180
+ [ 0.0034, 50000 ],
181
+ [ 0.0033, 75000 ],
182
+ [ 0.0032, 100000 ],
183
+ [ 0.0031, 150000 ],
184
+ [ 0.0030, 200000 ],
185
+ [ 0.0029, 250000 ],
186
+ [ 0.0028, 375000 ],
187
+ [ 0.0027, 500000 ],
188
+ [ 0.0026, 625000 ],
189
+ [ 0.0025, 875000 ],
190
+ ],
191
+ 'maker': [
192
+ [ 0.0030, 0 ],
193
+ [ 0.0029, 1250 ],
194
+ [ 0.0028, 3750 ],
195
+ [ 0.0028, 7500 ],
196
+ [ 0.0027, 10000 ],
197
+ [ 0.0026, 15000 ],
198
+ [ 0.0025, 20000 ],
199
+ [ 0.0025, 25000 ],
200
+ [ 0.0024, 37500 ],
201
+ [ 0.0023, 50000 ],
202
+ [ 0.0023, 75000 ],
203
+ [ 0.0022, 100000 ],
204
+ [ 0.0021, 150000 ],
205
+ [ 0.0021, 200000 ],
206
+ [ 0.0020, 250000 ],
207
+ [ 0.0019, 375000 ],
208
+ [ 0.0018, 500000 ],
209
+ [ 0.0018, 625000 ],
210
+ [ 0.0017, 875000 ],
211
+ ],
212
+ },
213
+ },
214
+ 'funding': {
215
+ 'withdraw': {},
216
+ },
217
+ },
218
+ 'options': {
219
+ 'fiatCurrencies': [ 'EUR', 'USD', 'GBP', 'PLN' ],
220
+ 'transfer': {
221
+ 'fillResponseFromRequest': true,
222
+ },
223
+ },
224
+ 'exceptions': {
225
+ '400': ExchangeError, // At least one parameter wasn't set
226
+ '401': InvalidOrder, // Invalid order type
227
+ '402': InvalidOrder, // No orders with specified currencies
228
+ '403': InvalidOrder, // Invalid payment currency name
229
+ '404': InvalidOrder, // Error. Wrong transaction type
230
+ '405': InvalidOrder, // Order with this id doesn't exist
231
+ '406': InsufficientFunds, // No enough money or crypto
232
+ // code 407 not specified are not specified in their docs
233
+ '408': InvalidOrder, // Invalid currency name
234
+ '501': AuthenticationError, // Invalid public key
235
+ '502': AuthenticationError, // Invalid sign
236
+ '503': InvalidNonce, // Invalid moment parameter. Request time doesn't match current server time
237
+ '504': ExchangeError, // Invalid method
238
+ '505': AuthenticationError, // Key has no permission for this action
239
+ '506': AccountSuspended, // Account locked. Please contact with customer service
240
+ // codes 507 and 508 are not specified in their docs
241
+ '509': ExchangeError, // The BIC/SWIFT is required for this currency
242
+ '510': BadSymbol, // Invalid market name
243
+ 'FUNDS_NOT_SUFFICIENT': InsufficientFunds,
244
+ 'OFFER_FUNDS_NOT_EXCEEDING_MINIMUMS': InvalidOrder,
245
+ 'OFFER_NOT_FOUND': OrderNotFound,
246
+ 'OFFER_WOULD_HAVE_BEEN_PARTIALLY_FILLED': OrderImmediatelyFillable,
247
+ 'ACTION_LIMIT_EXCEEDED': RateLimitExceeded,
248
+ 'UNDER_MAINTENANCE': OnMaintenance,
249
+ 'REQUEST_TIMESTAMP_TOO_OLD': InvalidNonce,
250
+ 'PERMISSIONS_NOT_SUFFICIENT': PermissionDenied,
251
+ },
252
+ 'commonCurrencies': {
253
+ 'GGC': 'Global Game Coin',
254
+ },
255
+ });
256
+ }
257
+
258
+ async fetchMarkets (params = {}) {
259
+ const response = await this.v1_01PublicGetTradingTicker (params);
260
+ const fiatCurrencies = this.safeValue (this.options, 'fiatCurrencies', []);
261
+ //
262
+ // {
263
+ // status: 'Ok',
264
+ // items: {
265
+ // 'BSV-USD': {
266
+ // market: {
267
+ // code: 'BSV-USD',
268
+ // first: { currency: 'BSV', minOffer: '0.00035', scale: 8 },
269
+ // second: { currency: 'USD', minOffer: '5', scale: 2 }
270
+ // },
271
+ // time: '1557569762154',
272
+ // highestBid: '52.31',
273
+ // lowestAsk: '62.99',
274
+ // rate: '63',
275
+ // previousRate: '51.21',
276
+ // },
277
+ // },
278
+ // }
279
+ //
280
+ const result = [];
281
+ const items = this.safeValue (response, 'items');
282
+ const keys = Object.keys (items);
283
+ for (let i = 0; i < keys.length; i++) {
284
+ const id = keys[i];
285
+ const item = items[id];
286
+ const market = this.safeValue (item, 'market', {});
287
+ const first = this.safeValue (market, 'first', {});
288
+ const second = this.safeValue (market, 'second', {});
289
+ const baseId = this.safeString (first, 'currency');
290
+ const quoteId = this.safeString (second, 'currency');
291
+ const base = this.safeCurrencyCode (baseId);
292
+ const quote = this.safeCurrencyCode (quoteId);
293
+ let fees = this.safeValue (this.fees, 'trading', {});
294
+ if (this.inArray (base, fiatCurrencies) || this.inArray (quote, fiatCurrencies)) {
295
+ fees = this.safeValue (this.fees, 'fiat', {});
296
+ }
297
+ // todo: check that the limits have ben interpreted correctly
298
+ // todo: parse the fees page
299
+ result.push ({
300
+ 'id': id,
301
+ 'symbol': base + '/' + quote,
302
+ 'base': base,
303
+ 'quote': quote,
304
+ 'settle': undefined,
305
+ 'baseId': baseId,
306
+ 'quoteId': quoteId,
307
+ 'settleId': undefined,
308
+ 'type': 'spot',
309
+ 'spot': true,
310
+ 'margin': false,
311
+ 'swap': false,
312
+ 'future': false,
313
+ 'option': false,
314
+ 'active': undefined,
315
+ 'contract': false,
316
+ 'linear': undefined,
317
+ 'inverse': undefined,
318
+ 'taker': this.safeNumber (fees, 'taker'),
319
+ 'maker': this.safeNumber (fees, 'maker'),
320
+ 'contractSize': undefined,
321
+ 'expiry': undefined,
322
+ 'expiryDatetime': undefined,
323
+ 'optionType': undefined,
324
+ 'strike': undefined,
325
+ 'precision': {
326
+ 'amount': this.safeInteger (first, 'scale'),
327
+ 'price': this.safeInteger (second, 'scale'),
328
+ },
329
+ 'limits': {
330
+ 'leverage': {
331
+ 'min': undefined,
332
+ 'max': undefined,
333
+ },
334
+ 'amount': {
335
+ 'min': this.safeNumber (first, 'minOffer'),
336
+ 'max': undefined,
337
+ },
338
+ 'price': {
339
+ 'min': undefined,
340
+ 'max': undefined,
341
+ },
342
+ 'cost': {
343
+ 'min': this.safeNumber (second, 'minOffer'),
344
+ 'max': undefined,
345
+ },
346
+ },
347
+ 'info': item,
348
+ });
349
+ }
350
+ return result;
351
+ }
352
+
353
+ async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
354
+ await this.loadMarkets ();
355
+ const request = {};
356
+ const response = await this.v1_01PrivateGetTradingOffer (this.extend (request, params));
357
+ const items = this.safeValue (response, 'items', []);
358
+ return this.parseOrders (items, undefined, since, limit, { 'status': 'open' });
359
+ }
360
+
361
+ parseOrder (order, market = undefined) {
362
+ //
363
+ // {
364
+ // market: 'ETH-EUR',
365
+ // offerType: 'Sell',
366
+ // id: '93d3657b-d616-11e9-9248-0242ac110005',
367
+ // currentAmount: '0.04',
368
+ // lockedAmount: '0.04',
369
+ // rate: '280',
370
+ // startAmount: '0.04',
371
+ // time: '1568372806924',
372
+ // postOnly: false,
373
+ // hidden: false,
374
+ // mode: 'limit',
375
+ // receivedAmount: '0.0',
376
+ // firstBalanceId: '5b816c3e-437c-4e43-9bef-47814ae7ebfc',
377
+ // secondBalanceId: 'ab43023b-4079-414c-b340-056e3430a3af'
378
+ // }
379
+ //
380
+ const marketId = this.safeString (order, 'market');
381
+ const symbol = this.safeSymbol (marketId, market, '-');
382
+ const timestamp = this.safeInteger (order, 'time');
383
+ const amount = this.safeString (order, 'startAmount');
384
+ const remaining = this.safeString (order, 'currentAmount');
385
+ const postOnly = this.safeValue (order, 'postOnly');
386
+ return this.safeOrder ({
387
+ 'id': this.safeString (order, 'id'),
388
+ 'clientOrderId': undefined,
389
+ 'info': order,
390
+ 'timestamp': timestamp,
391
+ 'datetime': this.iso8601 (timestamp),
392
+ 'lastTradeTimestamp': undefined,
393
+ 'status': undefined,
394
+ 'symbol': symbol,
395
+ 'type': this.safeString (order, 'mode'),
396
+ 'timeInForce': undefined,
397
+ 'postOnly': postOnly,
398
+ 'side': this.safeStringLower (order, 'offerType'),
399
+ 'price': this.safeString (order, 'rate'),
400
+ 'stopPrice': undefined,
401
+ 'amount': amount,
402
+ 'cost': undefined,
403
+ 'filled': undefined,
404
+ 'remaining': remaining,
405
+ 'average': undefined,
406
+ 'fee': undefined,
407
+ 'trades': undefined,
408
+ }, market);
409
+ }
410
+
411
+ async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
412
+ await this.loadMarkets ();
413
+ const request = {};
414
+ if (symbol) {
415
+ const markets = [ this.marketId (symbol) ];
416
+ request['markets'] = markets;
417
+ }
418
+ const query = { 'query': this.json (this.extend (request, params)) };
419
+ const response = await this.v1_01PrivateGetTradingHistoryTransactions (query);
420
+ //
421
+ // {
422
+ // status: 'Ok',
423
+ // totalRows: '67',
424
+ // items: [
425
+ // {
426
+ // id: 'b54659a0-51b5-42a0-80eb-2ac5357ccee2',
427
+ // market: 'BTC-EUR',
428
+ // time: '1541697096247',
429
+ // amount: '0.00003',
430
+ // rate: '4341.44',
431
+ // initializedBy: 'Sell',
432
+ // wasTaker: false,
433
+ // userAction: 'Buy',
434
+ // offerId: 'bd19804a-6f89-4a69-adb8-eb078900d006',
435
+ // commissionValue: null
436
+ // },
437
+ // ]
438
+ // }
439
+ //
440
+ const items = this.safeValue (response, 'items');
441
+ const result = this.parseTrades (items, undefined, since, limit);
442
+ if (symbol === undefined) {
443
+ return result;
444
+ }
445
+ return this.filterBySymbol (result, symbol);
446
+ }
447
+
448
+ parseBalance (response) {
449
+ const balances = this.safeValue (response, 'balances');
450
+ if (balances === undefined) {
451
+ throw new ExchangeError (this.id + ' empty balance response ' + this.json (response));
452
+ }
453
+ const result = { 'info': response };
454
+ for (let i = 0; i < balances.length; i++) {
455
+ const balance = balances[i];
456
+ const currencyId = this.safeString (balance, 'currency');
457
+ const code = this.safeCurrencyCode (currencyId);
458
+ const account = this.account ();
459
+ account['used'] = this.safeString (balance, 'lockedFunds');
460
+ account['free'] = this.safeString (balance, 'availableFunds');
461
+ result[code] = account;
462
+ }
463
+ return this.safeBalance (result);
464
+ }
465
+
466
+ async fetchBalance (params = {}) {
467
+ await this.loadMarkets ();
468
+ const response = await this.v1_01PrivateGetBalancesBITBAYBalance (params);
469
+ return this.parseBalance (response);
470
+ }
471
+
472
+ async fetchOrderBook (symbol, limit = undefined, params = {}) {
473
+ await this.loadMarkets ();
474
+ const request = {
475
+ 'symbol': this.marketId (symbol),
476
+ };
477
+ const response = await this.v1_01PublicGetTradingOrderbookSymbol (this.extend (request, params));
478
+ //
479
+ // {
480
+ // "status":"Ok",
481
+ // "sell":[
482
+ // {"ra":"43988.93","ca":"0.00100525","sa":"0.00100525","pa":"0.00100525","co":1},
483
+ // {"ra":"43988.94","ca":"0.00114136","sa":"0.00114136","pa":"0.00114136","co":1},
484
+ // {"ra":"43989","ca":"0.010578","sa":"0.010578","pa":"0.010578","co":1},
485
+ // ],
486
+ // "buy":[
487
+ // {"ra":"42157.33","ca":"2.83147881","sa":"2.83147881","pa":"2.83147881","co":2},
488
+ // {"ra":"42096.0","ca":"0.00011878","sa":"0.00011878","pa":"0.00011878","co":1},
489
+ // {"ra":"42022.0","ca":"0.00011899","sa":"0.00011899","pa":"0.00011899","co":1},
490
+ // ],
491
+ // "timestamp":"1642299886122",
492
+ // "seqNo":"27641254"
493
+ // }
494
+ //
495
+ const rawBids = this.safeValue (response, 'buy', []);
496
+ const rawAsks = this.safeValue (response, 'sell', []);
497
+ const timestamp = this.safeInteger (response, 'timestamp');
498
+ return {
499
+ 'symbol': symbol,
500
+ 'bids': this.parseBidsAsks (rawBids, 'ra', 'ca'),
501
+ 'asks': this.parseBidsAsks (rawAsks, 'ra', 'ca'),
502
+ 'timestamp': timestamp,
503
+ 'datetime': this.iso8601 (timestamp),
504
+ 'nonce': this.safeInteger (response, 'seqNo'),
505
+ };
506
+ }
507
+
508
+ parseTicker (ticker, market = undefined) {
509
+ //
510
+ // {
511
+ // m: 'ETH-PLN',
512
+ // h: '13485.13',
513
+ // l: '13100.01',
514
+ // v: '126.10710939',
515
+ // r24h: '13332.72'
516
+ // }
517
+ //
518
+ const open = this.safeString (ticker, 'r24h');
519
+ const high = this.safeString (ticker, 'h');
520
+ const low = this.safeString (ticker, 'l');
521
+ const volume = this.safeString (ticker, 'v');
522
+ const marketId = this.safeString (ticker, 'm');
523
+ market = this.safeMarket (marketId, market, '-');
524
+ const symbol = market['symbol'];
525
+ return this.safeTicker ({
526
+ 'symbol': symbol,
527
+ 'timestamp': undefined,
528
+ 'datetime': undefined,
529
+ 'high': high,
530
+ 'low': low,
531
+ 'bid': undefined,
532
+ 'bidVolume': undefined,
533
+ 'ask': undefined,
534
+ 'askVolume': undefined,
535
+ 'vwap': undefined,
536
+ 'open': open,
537
+ 'close': undefined,
538
+ 'last': undefined,
539
+ 'previousClose': undefined,
540
+ 'change': undefined,
541
+ 'percentage': undefined,
542
+ 'average': undefined,
543
+ 'baseVolume': volume,
544
+ 'quoteVolume': undefined,
545
+ 'info': ticker,
546
+ }, market, false);
547
+ }
548
+
549
+ async fetchTicker (symbol, params = {}) {
550
+ await this.loadMarkets ();
551
+ const market = this.market (symbol);
552
+ const request = {
553
+ 'symbol': market['id'],
554
+ };
555
+ const response = await this.v1_01PublicGetTradingStatsSymbol (this.extend (request, params));
556
+ //
557
+ // {
558
+ // status: 'Ok',
559
+ // stats: {
560
+ // m: 'ETH-PLN',
561
+ // h: '13485.13',
562
+ // l: '13100.01',
563
+ // v: '126.10710939',
564
+ // r24h: '13332.72'
565
+ // }
566
+ // }
567
+ //
568
+ const stats = this.safeValue (response, 'stats');
569
+ return this.parseTicker (stats, market);
570
+ }
571
+
572
+ async fetchLedger (code = undefined, since = undefined, limit = undefined, params = {}) {
573
+ const balanceCurrencies = [];
574
+ if (code !== undefined) {
575
+ const currency = this.currency (code);
576
+ balanceCurrencies.push (currency['id']);
577
+ }
578
+ let request = {
579
+ 'balanceCurrencies': balanceCurrencies,
580
+ };
581
+ if (since !== undefined) {
582
+ request['fromTime'] = since;
583
+ }
584
+ if (limit !== undefined) {
585
+ request['limit'] = limit;
586
+ }
587
+ request = this.extend (request, params);
588
+ const response = await this.v1_01PrivateGetBalancesBITBAYHistory ({ 'query': this.json (request) });
589
+ const items = response['items'];
590
+ return this.parseLedger (items, undefined, since, limit);
591
+ }
592
+
593
+ parseLedgerEntry (item, currency = undefined) {
594
+ //
595
+ // FUNDS_MIGRATION
596
+ // {
597
+ // "historyId": "84ea7a29-7da5-4de5-b0c0-871e83cad765",
598
+ // "balance": {
599
+ // "id": "821ec166-cb88-4521-916c-f4eb44db98df",
600
+ // "currency": "LTC",
601
+ // "type": "CRYPTO",
602
+ // "userId": "a34d361d-7bad-49c1-888e-62473b75d877",
603
+ // "name": "LTC"
604
+ // },
605
+ // "detailId": null,
606
+ // "time": 1506128252968,
607
+ // "type": "FUNDS_MIGRATION",
608
+ // "value": 0.0009957,
609
+ // "fundsBefore": { "total": 0, "available": 0, "locked": 0 },
610
+ // "fundsAfter": { "total": 0.0009957, "available": 0.0009957, "locked": 0 },
611
+ // "change": { "total": 0.0009957, "available": 0.0009957, "locked": 0 }
612
+ // }
613
+ //
614
+ // CREATE_BALANCE
615
+ // {
616
+ // "historyId": "d0fabd8d-9107-4b5e-b9a6-3cab8af70d49",
617
+ // "balance": {
618
+ // "id": "653ffcf2-3037-4ebe-8e13-d5ea1a01d60d",
619
+ // "currency": "BTG",
620
+ // "type": "CRYPTO",
621
+ // "userId": "a34d361d-7bad-49c1-888e-62473b75d877",
622
+ // "name": "BTG"
623
+ // },
624
+ // "detailId": null,
625
+ // "time": 1508895244751,
626
+ // "type": "CREATE_BALANCE",
627
+ // "value": 0,
628
+ // "fundsBefore": { "total": null, "available": null, "locked": null },
629
+ // "fundsAfter": { "total": 0, "available": 0, "locked": 0 },
630
+ // "change": { "total": 0, "available": 0, "locked": 0 }
631
+ // }
632
+ //
633
+ // BITCOIN_GOLD_FORK
634
+ // {
635
+ // "historyId": "2b4d52d3-611c-473d-b92c-8a8d87a24e41",
636
+ // "balance": {
637
+ // "id": "653ffcf2-3037-4ebe-8e13-d5ea1a01d60d",
638
+ // "currency": "BTG",
639
+ // "type": "CRYPTO",
640
+ // "userId": "a34d361d-7bad-49c1-888e-62473b75d877",
641
+ // "name": "BTG"
642
+ // },
643
+ // "detailId": null,
644
+ // "time": 1508895244778,
645
+ // "type": "BITCOIN_GOLD_FORK",
646
+ // "value": 0.00453512,
647
+ // "fundsBefore": { "total": 0, "available": 0, "locked": 0 },
648
+ // "fundsAfter": { "total": 0.00453512, "available": 0.00453512, "locked": 0 },
649
+ // "change": { "total": 0.00453512, "available": 0.00453512, "locked": 0 }
650
+ // }
651
+ //
652
+ // ADD_FUNDS
653
+ // {
654
+ // "historyId": "3158236d-dae5-4a5d-81af-c1fa4af340fb",
655
+ // "balance": {
656
+ // "id": "3a7e7a1e-0324-49d5-8f59-298505ebd6c7",
657
+ // "currency": "BTC",
658
+ // "type": "CRYPTO",
659
+ // "userId": "a34d361d-7bad-49c1-888e-62473b75d877",
660
+ // "name": "BTC"
661
+ // },
662
+ // "detailId": "8e83a960-e737-4380-b8bb-259d6e236faa",
663
+ // "time": 1520631178816,
664
+ // "type": "ADD_FUNDS",
665
+ // "value": 0.628405,
666
+ // "fundsBefore": { "total": 0.00453512, "available": 0.00453512, "locked": 0 },
667
+ // "fundsAfter": { "total": 0.63294012, "available": 0.63294012, "locked": 0 },
668
+ // "change": { "total": 0.628405, "available": 0.628405, "locked": 0 }
669
+ // }
670
+ //
671
+ // TRANSACTION_PRE_LOCKING
672
+ // {
673
+ // "historyId": "e7d19e0f-03b3-46a8-bc72-dde72cc24ead",
674
+ // "balance": {
675
+ // "id": "3a7e7a1e-0324-49d5-8f59-298505ebd6c7",
676
+ // "currency": "BTC",
677
+ // "type": "CRYPTO",
678
+ // "userId": "a34d361d-7bad-49c1-888e-62473b75d877",
679
+ // "name": "BTC"
680
+ // },
681
+ // "detailId": null,
682
+ // "time": 1520706403868,
683
+ // "type": "TRANSACTION_PRE_LOCKING",
684
+ // "value": -0.1,
685
+ // "fundsBefore": { "total": 0.63294012, "available": 0.63294012, "locked": 0 },
686
+ // "fundsAfter": { "total": 0.63294012, "available": 0.53294012, "locked": 0.1 },
687
+ // "change": { "total": 0, "available": -0.1, "locked": 0.1 }
688
+ // }
689
+ //
690
+ // TRANSACTION_POST_OUTCOME
691
+ // {
692
+ // "historyId": "c4010825-231d-4a9c-8e46-37cde1f7b63c",
693
+ // "balance": {
694
+ // "id": "3a7e7a1e-0324-49d5-8f59-298505ebd6c7",
695
+ // "currency": "BTC",
696
+ // "type": "CRYPTO",
697
+ // "userId": "a34d361d-7bad-49c1-888e-62473b75d877",
698
+ // "name": "BTC"
699
+ // },
700
+ // "detailId": "bf2876bc-b545-4503-96c8-ef4de8233876",
701
+ // "time": 1520706404032,
702
+ // "type": "TRANSACTION_POST_OUTCOME",
703
+ // "value": -0.01771415,
704
+ // "fundsBefore": { "total": 0.63294012, "available": 0.53294012, "locked": 0.1 },
705
+ // "fundsAfter": { "total": 0.61522597, "available": 0.53294012, "locked": 0.08228585 },
706
+ // "change": { "total": -0.01771415, "available": 0, "locked": -0.01771415 }
707
+ // }
708
+ //
709
+ // TRANSACTION_POST_INCOME
710
+ // {
711
+ // "historyId": "7f18b7af-b676-4125-84fd-042e683046f6",
712
+ // "balance": {
713
+ // "id": "ab43023b-4079-414c-b340-056e3430a3af",
714
+ // "currency": "EUR",
715
+ // "type": "FIAT",
716
+ // "userId": "a34d361d-7bad-49c1-888e-62473b75d877",
717
+ // "name": "EUR"
718
+ // },
719
+ // "detailId": "f5fcb274-0cc7-4385-b2d3-bae2756e701f",
720
+ // "time": 1520706404035,
721
+ // "type": "TRANSACTION_POST_INCOME",
722
+ // "value": 628.78,
723
+ // "fundsBefore": { "total": 0, "available": 0, "locked": 0 },
724
+ // "fundsAfter": { "total": 628.78, "available": 628.78, "locked": 0 },
725
+ // "change": { "total": 628.78, "available": 628.78, "locked": 0 }
726
+ // }
727
+ //
728
+ // TRANSACTION_COMMISSION_OUTCOME
729
+ // {
730
+ // "historyId": "843177fa-61bc-4cbf-8be5-b029d856c93b",
731
+ // "balance": {
732
+ // "id": "ab43023b-4079-414c-b340-056e3430a3af",
733
+ // "currency": "EUR",
734
+ // "type": "FIAT",
735
+ // "userId": "a34d361d-7bad-49c1-888e-62473b75d877",
736
+ // "name": "EUR"
737
+ // },
738
+ // "detailId": "f5fcb274-0cc7-4385-b2d3-bae2756e701f",
739
+ // "time": 1520706404050,
740
+ // "type": "TRANSACTION_COMMISSION_OUTCOME",
741
+ // "value": -2.71,
742
+ // "fundsBefore": { "total": 766.06, "available": 766.06, "locked": 0 },
743
+ // "fundsAfter": { "total": 763.35,"available": 763.35, "locked": 0 },
744
+ // "change": { "total": -2.71, "available": -2.71, "locked": 0 }
745
+ // }
746
+ //
747
+ // TRANSACTION_OFFER_COMPLETED_RETURN
748
+ // {
749
+ // "historyId": "cac69b04-c518-4dc5-9d86-e76e91f2e1d2",
750
+ // "balance": {
751
+ // "id": "3a7e7a1e-0324-49d5-8f59-298505ebd6c7",
752
+ // "currency": "BTC",
753
+ // "type": "CRYPTO",
754
+ // "userId": "a34d361d-7bad-49c1-888e-62473b75d877",
755
+ // "name": "BTC"
756
+ // },
757
+ // "detailId": null,
758
+ // "time": 1520714886425,
759
+ // "type": "TRANSACTION_OFFER_COMPLETED_RETURN",
760
+ // "value": 0.00000196,
761
+ // "fundsBefore": { "total": 0.00941208, "available": 0.00941012, "locked": 0.00000196 },
762
+ // "fundsAfter": { "total": 0.00941208, "available": 0.00941208, "locked": 0 },
763
+ // "change": { "total": 0, "available": 0.00000196, "locked": -0.00000196 }
764
+ // }
765
+ //
766
+ // WITHDRAWAL_LOCK_FUNDS
767
+ // {
768
+ // "historyId": "03de2271-66ab-4960-a786-87ab9551fc14",
769
+ // "balance": {
770
+ // "id": "3a7e7a1e-0324-49d5-8f59-298505ebd6c7",
771
+ // "currency": "BTC",
772
+ // "type": "CRYPTO",
773
+ // "userId": "a34d361d-7bad-49c1-888e-62473b75d877",
774
+ // "name": "BTC"
775
+ // },
776
+ // "detailId": "6ad3dc72-1d6d-4ec2-8436-ca43f85a38a6",
777
+ // "time": 1522245654481,
778
+ // "type": "WITHDRAWAL_LOCK_FUNDS",
779
+ // "value": -0.8,
780
+ // "fundsBefore": { "total": 0.8, "available": 0.8, "locked": 0 },
781
+ // "fundsAfter": { "total": 0.8, "available": 0, "locked": 0.8 },
782
+ // "change": { "total": 0, "available": -0.8, "locked": 0.8 }
783
+ // }
784
+ //
785
+ // WITHDRAWAL_SUBTRACT_FUNDS
786
+ // {
787
+ // "historyId": "b0308c89-5288-438d-a306-c6448b1a266d",
788
+ // "balance": {
789
+ // "id": "3a7e7a1e-0324-49d5-8f59-298505ebd6c7",
790
+ // "currency": "BTC",
791
+ // "type": "CRYPTO",
792
+ // "userId": "a34d361d-7bad-49c1-888e-62473b75d877",
793
+ // "name": "BTC"
794
+ // },
795
+ // "detailId": "6ad3dc72-1d6d-4ec2-8436-ca43f85a38a6",
796
+ // "time": 1522246526186,
797
+ // "type": "WITHDRAWAL_SUBTRACT_FUNDS",
798
+ // "value": -0.8,
799
+ // "fundsBefore": { "total": 0.8, "available": 0, "locked": 0.8 },
800
+ // "fundsAfter": { "total": 0, "available": 0, "locked": 0 },
801
+ // "change": { "total": -0.8, "available": 0, "locked": -0.8 }
802
+ // }
803
+ //
804
+ // TRANSACTION_OFFER_ABORTED_RETURN
805
+ // {
806
+ // "historyId": "b1a3c075-d403-4e05-8f32-40512cdd88c0",
807
+ // "balance": {
808
+ // "id": "3a7e7a1e-0324-49d5-8f59-298505ebd6c7",
809
+ // "currency": "BTC",
810
+ // "type": "CRYPTO",
811
+ // "userId": "a34d361d-7bad-49c1-888e-62473b75d877",
812
+ // "name": "BTC"
813
+ // },
814
+ // "detailId": null,
815
+ // "time": 1522512298662,
816
+ // "type": "TRANSACTION_OFFER_ABORTED_RETURN",
817
+ // "value": 0.0564931,
818
+ // "fundsBefore": { "total": 0.44951311, "available": 0.39302001, "locked": 0.0564931 },
819
+ // "fundsAfter": { "total": 0.44951311, "available": 0.44951311, "locked": 0 },
820
+ // "change": { "total": 0, "available": 0.0564931, "locked": -0.0564931 }
821
+ // }
822
+ //
823
+ // WITHDRAWAL_UNLOCK_FUNDS
824
+ // {
825
+ // "historyId": "0ed569a2-c330-482e-bb89-4cb553fb5b11",
826
+ // "balance": {
827
+ // "id": "3a7e7a1e-0324-49d5-8f59-298505ebd6c7",
828
+ // "currency": "BTC",
829
+ // "type": "CRYPTO",
830
+ // "userId": "a34d361d-7bad-49c1-888e-62473b75d877",
831
+ // "name": "BTC"
832
+ // },
833
+ // "detailId": "0c7be256-c336-4111-bee7-4eb22e339700",
834
+ // "time": 1527866360785,
835
+ // "type": "WITHDRAWAL_UNLOCK_FUNDS",
836
+ // "value": 0.05045,
837
+ // "fundsBefore": { "total": 0.86001578, "available": 0.80956578, "locked": 0.05045 },
838
+ // "fundsAfter": { "total": 0.86001578, "available": 0.86001578, "locked": 0 },
839
+ // "change": { "total": 0, "available": 0.05045, "locked": -0.05045 }
840
+ // }
841
+ //
842
+ // TRANSACTION_COMMISSION_RETURN
843
+ // {
844
+ // "historyId": "07c89c27-46f1-4d7a-8518-b73798bf168a",
845
+ // "balance": {
846
+ // "id": "ab43023b-4079-414c-b340-056e3430a3af",
847
+ // "currency": "EUR",
848
+ // "type": "FIAT",
849
+ // "userId": "a34d361d-7bad-49c1-888e-62473b75d877",
850
+ // "name": "EUR"
851
+ // },
852
+ // "detailId": null,
853
+ // "time": 1528304043063,
854
+ // "type": "TRANSACTION_COMMISSION_RETURN",
855
+ // "value": 0.6,
856
+ // "fundsBefore": { "total": 0, "available": 0, "locked": 0 },
857
+ // "fundsAfter": { "total": 0.6, "available": 0.6, "locked": 0 },
858
+ // "change": { "total": 0.6, "available": 0.6, "locked": 0 }
859
+ // }
860
+ //
861
+ const timestamp = this.safeInteger (item, 'time');
862
+ const balance = this.safeValue (item, 'balance', {});
863
+ const currencyId = this.safeString (balance, 'currency');
864
+ const code = this.safeCurrencyCode (currencyId);
865
+ const change = this.safeValue (item, 'change', {});
866
+ let amount = this.safeNumber (change, 'total');
867
+ let direction = 'in';
868
+ if (amount < 0) {
869
+ direction = 'out';
870
+ amount = -amount;
871
+ }
872
+ const id = this.safeString (item, 'historyId');
873
+ // there are 2 undocumented api calls: (v1_01PrivateGetPaymentsDepositDetailId and v1_01PrivateGetPaymentsWithdrawalDetailId)
874
+ // that can be used to enrich the transfers with txid, address etc (you need to use info.detailId as a parameter)
875
+ const referenceId = this.safeString (item, 'detailId');
876
+ const type = this.parseLedgerEntryType (this.safeString (item, 'type'));
877
+ const fundsBefore = this.safeValue (item, 'fundsBefore', {});
878
+ const before = this.safeNumber (fundsBefore, 'total');
879
+ const fundsAfter = this.safeValue (item, 'fundsAfter', {});
880
+ const after = this.safeNumber (fundsAfter, 'total');
881
+ return {
882
+ 'info': item,
883
+ 'id': id,
884
+ 'direction': direction,
885
+ 'account': undefined,
886
+ 'referenceId': referenceId,
887
+ 'referenceAccount': undefined,
888
+ 'type': type,
889
+ 'currency': code,
890
+ 'amount': amount,
891
+ 'before': before,
892
+ 'after': after,
893
+ 'status': 'ok',
894
+ 'timestamp': timestamp,
895
+ 'datetime': this.iso8601 (timestamp),
896
+ 'fee': undefined,
897
+ };
898
+ }
899
+
900
+ parseLedgerEntryType (type) {
901
+ const types = {
902
+ 'ADD_FUNDS': 'transaction',
903
+ 'BITCOIN_GOLD_FORK': 'transaction',
904
+ 'CREATE_BALANCE': 'transaction',
905
+ 'FUNDS_MIGRATION': 'transaction',
906
+ 'WITHDRAWAL_LOCK_FUNDS': 'transaction',
907
+ 'WITHDRAWAL_SUBTRACT_FUNDS': 'transaction',
908
+ 'WITHDRAWAL_UNLOCK_FUNDS': 'transaction',
909
+ 'TRANSACTION_COMMISSION_OUTCOME': 'fee',
910
+ 'TRANSACTION_COMMISSION_RETURN': 'fee',
911
+ 'TRANSACTION_OFFER_ABORTED_RETURN': 'trade',
912
+ 'TRANSACTION_OFFER_COMPLETED_RETURN': 'trade',
913
+ 'TRANSACTION_POST_INCOME': 'trade',
914
+ 'TRANSACTION_POST_OUTCOME': 'trade',
915
+ 'TRANSACTION_PRE_LOCKING': 'trade',
916
+ };
917
+ return this.safeString (types, type, type);
918
+ }
919
+
920
+ parseOHLCV (ohlcv, market = undefined) {
921
+ //
922
+ // [
923
+ // '1582399800000',
924
+ // {
925
+ // o: '0.0001428',
926
+ // c: '0.0001428',
927
+ // h: '0.0001428',
928
+ // l: '0.0001428',
929
+ // v: '4',
930
+ // co: '1'
931
+ // }
932
+ // ]
933
+ //
934
+ const first = this.safeValue (ohlcv, 1, {});
935
+ return [
936
+ this.safeInteger (ohlcv, 0),
937
+ this.safeNumber (first, 'o'),
938
+ this.safeNumber (first, 'h'),
939
+ this.safeNumber (first, 'l'),
940
+ this.safeNumber (first, 'c'),
941
+ this.safeNumber (first, 'v'),
942
+ ];
943
+ }
944
+
945
+ async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
946
+ await this.loadMarkets ();
947
+ const market = this.market (symbol);
948
+ const tradingSymbol = market['baseId'] + '-' + market['quoteId'];
949
+ const request = {
950
+ 'symbol': tradingSymbol,
951
+ 'resolution': this.timeframes[timeframe],
952
+ // 'from': 1574709092000, // unix timestamp in milliseconds, required
953
+ // 'to': 1574709092000, // unix timestamp in milliseconds, required
954
+ };
955
+ if (limit === undefined) {
956
+ limit = 100;
957
+ }
958
+ const duration = this.parseTimeframe (timeframe);
959
+ const timerange = limit * duration * 1000;
960
+ if (since === undefined) {
961
+ request['to'] = this.milliseconds ();
962
+ request['from'] = request['to'] - timerange;
963
+ } else {
964
+ request['from'] = parseInt (since);
965
+ request['to'] = this.sum (request['from'], timerange);
966
+ }
967
+ const response = await this.v1_01PublicGetTradingCandleHistorySymbolResolution (this.extend (request, params));
968
+ //
969
+ // {
970
+ // "status":"Ok",
971
+ // "items":[
972
+ // ["1591503060000",{"o":"0.02509572","c":"0.02509438","h":"0.02509664","l":"0.02509438","v":"0.02082165","co":"17"}],
973
+ // ["1591503120000",{"o":"0.02509606","c":"0.02509515","h":"0.02509606","l":"0.02509487","v":"0.04971703","co":"13"}],
974
+ // ["1591503180000",{"o":"0.02509532","c":"0.02509589","h":"0.02509589","l":"0.02509454","v":"0.01332236","co":"7"}],
975
+ // ]
976
+ // }
977
+ //
978
+ const items = this.safeValue (response, 'items', []);
979
+ return this.parseOHLCVs (items, market, timeframe, since, limit);
980
+ }
981
+
982
+ parseTrade (trade, market = undefined) {
983
+ //
984
+ // createOrder trades
985
+ //
986
+ // {
987
+ // "rate": "0.02195928",
988
+ // "amount": "0.00167952"
989
+ // }
990
+ //
991
+ // fetchMyTrades (private)
992
+ //
993
+ // {
994
+ // amount: "0.29285199",
995
+ // commissionValue: "0.00125927",
996
+ // id: "11c8203a-a267-11e9-b698-0242ac110007",
997
+ // initializedBy: "Buy",
998
+ // market: "ETH-EUR",
999
+ // offerId: "11c82038-a267-11e9-b698-0242ac110007",
1000
+ // rate: "277",
1001
+ // time: "1562689917517",
1002
+ // userAction: "Buy",
1003
+ // wasTaker: true,
1004
+ // }
1005
+ //
1006
+ // fetchTrades (public)
1007
+ //
1008
+ // {
1009
+ // id: 'df00b0da-e5e0-11e9-8c19-0242ac11000a',
1010
+ // t: '1570108958831',
1011
+ // a: '0.04776653',
1012
+ // r: '0.02145854',
1013
+ // ty: 'Sell'
1014
+ // }
1015
+ //
1016
+ const timestamp = this.safeInteger2 (trade, 'time', 't');
1017
+ const side = this.safeStringLower2 (trade, 'userAction', 'ty');
1018
+ const wasTaker = this.safeValue (trade, 'wasTaker');
1019
+ let takerOrMaker = undefined;
1020
+ if (wasTaker !== undefined) {
1021
+ takerOrMaker = wasTaker ? 'taker' : 'maker';
1022
+ }
1023
+ const priceString = this.safeString2 (trade, 'rate', 'r');
1024
+ const amountString = this.safeString2 (trade, 'amount', 'a');
1025
+ const feeCostString = this.safeString (trade, 'commissionValue');
1026
+ const marketId = this.safeString (trade, 'market');
1027
+ market = this.safeMarket (marketId, market, '-');
1028
+ const symbol = market['symbol'];
1029
+ let fee = undefined;
1030
+ if (feeCostString !== undefined) {
1031
+ const feeCurrency = (side === 'buy') ? market['base'] : market['quote'];
1032
+ fee = {
1033
+ 'currency': feeCurrency,
1034
+ 'cost': feeCostString,
1035
+ };
1036
+ }
1037
+ const order = this.safeString (trade, 'offerId');
1038
+ // todo: check this logic
1039
+ let type = undefined;
1040
+ if (order !== undefined) {
1041
+ type = order ? 'limit' : 'market';
1042
+ }
1043
+ return this.safeTrade ({
1044
+ 'id': this.safeString (trade, 'id'),
1045
+ 'order': order,
1046
+ 'timestamp': timestamp,
1047
+ 'datetime': this.iso8601 (timestamp),
1048
+ 'symbol': symbol,
1049
+ 'type': type,
1050
+ 'side': side,
1051
+ 'price': priceString,
1052
+ 'amount': amountString,
1053
+ 'cost': undefined,
1054
+ 'takerOrMaker': takerOrMaker,
1055
+ 'fee': fee,
1056
+ 'info': trade,
1057
+ }, market);
1058
+ }
1059
+
1060
+ async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
1061
+ await this.loadMarkets ();
1062
+ const market = this.market (symbol);
1063
+ const tradingSymbol = market['baseId'] + '-' + market['quoteId'];
1064
+ const request = {
1065
+ 'symbol': tradingSymbol,
1066
+ };
1067
+ if (since !== undefined) {
1068
+ request['fromTime'] = since - 1; // result does not include exactly `since` time therefore decrease by 1
1069
+ }
1070
+ if (limit !== undefined) {
1071
+ request['limit'] = limit; // default - 10, max - 300
1072
+ }
1073
+ const response = await this.v1_01PublicGetTradingTransactionsSymbol (this.extend (request, params));
1074
+ const items = this.safeValue (response, 'items');
1075
+ return this.parseTrades (items, market, since, limit);
1076
+ }
1077
+
1078
+ async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
1079
+ await this.loadMarkets ();
1080
+ const market = this.market (symbol);
1081
+ const tradingSymbol = market['baseId'] + '-' + market['quoteId'];
1082
+ amount = parseFloat (this.amountToPrecision (symbol, amount));
1083
+ const request = {
1084
+ 'symbol': tradingSymbol,
1085
+ 'offerType': side,
1086
+ 'amount': amount,
1087
+ 'mode': type,
1088
+ };
1089
+ if (type === 'limit') {
1090
+ request['rate'] = price;
1091
+ price = parseFloat (this.priceToPrecision (symbol, price));
1092
+ }
1093
+ const response = await this.v1_01PrivatePostTradingOfferSymbol (this.extend (request, params));
1094
+ //
1095
+ // unfilled (open order)
1096
+ //
1097
+ // {
1098
+ // status: 'Ok',
1099
+ // completed: false, // can deduce status from here
1100
+ // offerId: 'ce9cc72e-d61c-11e9-9248-0242ac110005',
1101
+ // transactions: [], // can deduce order info from here
1102
+ // }
1103
+ //
1104
+ // filled (closed order)
1105
+ //
1106
+ // {
1107
+ // "status": "Ok",
1108
+ // "offerId": "942a4a3e-e922-11e9-8c19-0242ac11000a",
1109
+ // "completed": true,
1110
+ // "transactions": [
1111
+ // {
1112
+ // "rate": "0.02195928",
1113
+ // "amount": "0.00167952"
1114
+ // },
1115
+ // {
1116
+ // "rate": "0.02195928",
1117
+ // "amount": "0.00167952"
1118
+ // },
1119
+ // {
1120
+ // "rate": "0.02196207",
1121
+ // "amount": "0.27704177"
1122
+ // }
1123
+ // ]
1124
+ // }
1125
+ //
1126
+ // partially-filled (open order)
1127
+ //
1128
+ // {
1129
+ // "status": "Ok",
1130
+ // "offerId": "d0ebefab-f4d7-11e9-8c19-0242ac11000a",
1131
+ // "completed": false,
1132
+ // "transactions": [
1133
+ // {
1134
+ // "rate": "0.02106404",
1135
+ // "amount": "0.0019625"
1136
+ // },
1137
+ // {
1138
+ // "rate": "0.02106404",
1139
+ // "amount": "0.0019625"
1140
+ // },
1141
+ // {
1142
+ // "rate": "0.02105901",
1143
+ // "amount": "0.00975256"
1144
+ // }
1145
+ // ]
1146
+ // }
1147
+ //
1148
+ const timestamp = this.milliseconds (); // the real timestamp is missing in the response
1149
+ const id = this.safeString (response, 'offerId');
1150
+ const completed = this.safeValue (response, 'completed', false);
1151
+ const status = completed ? 'closed' : 'open';
1152
+ let filled = 0;
1153
+ let cost = undefined;
1154
+ const transactions = this.safeValue (response, 'transactions');
1155
+ let trades = undefined;
1156
+ if (transactions !== undefined) {
1157
+ trades = this.parseTrades (transactions, market, undefined, undefined, {
1158
+ 'timestamp': timestamp,
1159
+ 'datetime': this.iso8601 (timestamp),
1160
+ 'symbol': symbol,
1161
+ 'side': side,
1162
+ 'type': type,
1163
+ 'orderId': id,
1164
+ });
1165
+ cost = 0;
1166
+ for (let i = 0; i < trades.length; i++) {
1167
+ filled = this.sum (filled, trades[i]['amount']);
1168
+ cost = this.sum (cost, trades[i]['cost']);
1169
+ }
1170
+ }
1171
+ const remaining = amount - filled;
1172
+ return {
1173
+ 'id': id,
1174
+ 'info': response,
1175
+ 'timestamp': timestamp,
1176
+ 'datetime': this.iso8601 (timestamp),
1177
+ 'lastTradeTimestamp': undefined,
1178
+ 'status': status,
1179
+ 'symbol': symbol,
1180
+ 'type': type,
1181
+ 'side': side,
1182
+ 'price': price,
1183
+ 'amount': amount,
1184
+ 'cost': cost,
1185
+ 'filled': filled,
1186
+ 'remaining': remaining,
1187
+ 'average': undefined,
1188
+ 'fee': undefined,
1189
+ 'trades': trades,
1190
+ 'clientOrderId': undefined,
1191
+ };
1192
+ }
1193
+
1194
+ async cancelOrder (id, symbol = undefined, params = {}) {
1195
+ const side = this.safeString (params, 'side');
1196
+ if (side === undefined) {
1197
+ throw new ExchangeError (this.id + ' cancelOrder() requires a `side` parameter ("buy" or "sell")');
1198
+ }
1199
+ const price = this.safeValue (params, 'price');
1200
+ if (price === undefined) {
1201
+ throw new ExchangeError (this.id + ' cancelOrder() requires a `price` parameter (float or string)');
1202
+ }
1203
+ await this.loadMarkets ();
1204
+ const market = this.market (symbol);
1205
+ const tradingSymbol = market['baseId'] + '-' + market['quoteId'];
1206
+ const request = {
1207
+ 'symbol': tradingSymbol,
1208
+ 'id': id,
1209
+ 'side': side,
1210
+ 'price': price,
1211
+ };
1212
+ // { status: 'Fail', errors: [ 'NOT_RECOGNIZED_OFFER_TYPE' ] } -- if required params are missing
1213
+ // { status: 'Ok', errors: [] }
1214
+ return this.v1_01PrivateDeleteTradingOfferSymbolIdSidePrice (this.extend (request, params));
1215
+ }
1216
+
1217
+ isFiat (currency) {
1218
+ const fiatCurrencies = {
1219
+ 'USD': true,
1220
+ 'EUR': true,
1221
+ 'PLN': true,
1222
+ };
1223
+ return this.safeValue (fiatCurrencies, currency, false);
1224
+ }
1225
+
1226
+ async transfer (code, amount, fromAccount, toAccount, params = {}) {
1227
+ await this.loadMarkets ();
1228
+ const currency = this.currency (code);
1229
+ const request = {
1230
+ 'source': fromAccount,
1231
+ 'destination': toAccount,
1232
+ 'currency': code,
1233
+ 'funds': this.currencyToPrecision (code, amount),
1234
+ };
1235
+ const response = await this.v1_01PrivatePostBalancesBITBAYBalanceTransferSourceDestination (this.extend (request, params));
1236
+ //
1237
+ // {
1238
+ // "status": "Ok",
1239
+ // "from": {
1240
+ // "id": "ad9397c5-3bd9-4372-82ba-22da6a90cb56",
1241
+ // "userId": "4bc43956-423f-47fd-9faa-acd37c58ed9f",
1242
+ // "availableFunds": 0.01803472,
1243
+ // "totalFunds": 0.01804161,
1244
+ // "lockedFunds": 0.00000689,
1245
+ // "currency": "BTC",
1246
+ // "type": "CRYPTO",
1247
+ // "name": "BTC",
1248
+ // "balanceEngine": "BITBAY"
1249
+ // },
1250
+ // "to": {
1251
+ // "id": "01931d52-536b-4ca5-a9f4-be28c86d0cc3",
1252
+ // "userId": "4bc43956-423f-47fd-9faa-acd37c58ed9f",
1253
+ // "availableFunds": 0.0001,
1254
+ // "totalFunds": 0.0001,
1255
+ // "lockedFunds": 0,
1256
+ // "currency": "BTC",
1257
+ // "type": "CRYPTO",
1258
+ // "name": "Prowizja",
1259
+ // "balanceEngine": "BITBAY"
1260
+ // },
1261
+ // "errors": null
1262
+ // }
1263
+ //
1264
+ const transfer = this.parseTransfer (response, currency);
1265
+ const transferOptions = this.safeValue (this.options, 'transfer', {});
1266
+ const fillResponseFromRequest = this.safeValue (transferOptions, 'fillResponseFromRequest', true);
1267
+ if (fillResponseFromRequest) {
1268
+ transfer['amount'] = amount;
1269
+ }
1270
+ return transfer;
1271
+ }
1272
+
1273
+ parseTransfer (transfer, currency = undefined) {
1274
+ //
1275
+ // {
1276
+ // "status": "Ok",
1277
+ // "from": {
1278
+ // "id": "ad9397c5-3bd9-4372-82ba-22da6a90cb56",
1279
+ // "userId": "4bc43956-423f-47fd-9faa-acd37c58ed9f",
1280
+ // "availableFunds": 0.01803472,
1281
+ // "totalFunds": 0.01804161,
1282
+ // "lockedFunds": 0.00000689,
1283
+ // "currency": "BTC",
1284
+ // "type": "CRYPTO",
1285
+ // "name": "BTC",
1286
+ // "balanceEngine": "BITBAY"
1287
+ // },
1288
+ // "to": {
1289
+ // "id": "01931d52-536b-4ca5-a9f4-be28c86d0cc3",
1290
+ // "userId": "4bc43956-423f-47fd-9faa-acd37c58ed9f",
1291
+ // "availableFunds": 0.0001,
1292
+ // "totalFunds": 0.0001,
1293
+ // "lockedFunds": 0,
1294
+ // "currency": "BTC",
1295
+ // "type": "CRYPTO",
1296
+ // "name": "Prowizja",
1297
+ // "balanceEngine": "BITBAY"
1298
+ // },
1299
+ // "errors": null
1300
+ // }
1301
+ //
1302
+ const status = this.safeString (transfer, 'status');
1303
+ const fromAccount = this.safeValue (transfer, 'from', {});
1304
+ const fromId = this.safeString (fromAccount, 'id');
1305
+ const to = this.safeValue (transfer, 'to', {});
1306
+ const toId = this.safeString (to, 'id');
1307
+ const currencyId = this.safeString (fromAccount, 'currency');
1308
+ return {
1309
+ 'info': transfer,
1310
+ 'id': undefined,
1311
+ 'timestamp': undefined,
1312
+ 'datetime': undefined,
1313
+ 'currency': this.safeCurrencyCode (currencyId, currency),
1314
+ 'amount': undefined,
1315
+ 'fromAccount': fromId,
1316
+ 'toAccount': toId,
1317
+ 'status': this.parseTransferStatus (status),
1318
+ };
1319
+ }
1320
+
1321
+ parseTransferStatus (status) {
1322
+ const statuses = {
1323
+ 'Ok': 'ok',
1324
+ 'Fail': 'failed',
1325
+ };
1326
+ return this.safeString (statuses, status, status);
1327
+ }
1328
+
1329
+ async withdraw (code, amount, address, tag = undefined, params = {}) {
1330
+ [ tag, params ] = this.handleWithdrawTagAndParams (tag, params);
1331
+ this.checkAddress (address);
1332
+ await this.loadMarkets ();
1333
+ let method = undefined;
1334
+ const currency = this.currency (code);
1335
+ const request = {
1336
+ 'currency': currency['id'],
1337
+ 'quantity': amount,
1338
+ };
1339
+ if (this.isFiat (code)) {
1340
+ method = 'privatePostWithdraw';
1341
+ // request['account'] = params['account']; // they demand an account number
1342
+ // request['express'] = params['express']; // whatever it means, they don't explain
1343
+ // request['bic'] = '';
1344
+ } else {
1345
+ method = 'privatePostTransfer';
1346
+ if (tag !== undefined) {
1347
+ address += '?dt=' + tag.toString ();
1348
+ }
1349
+ request['address'] = address;
1350
+ }
1351
+ const response = await this[method] (this.extend (request, params));
1352
+ //
1353
+ // {
1354
+ // "status": "Ok",
1355
+ // "data": {
1356
+ // "id": "65e01087-afb0-4ab2-afdb-cc925e360296"
1357
+ // }
1358
+ // }
1359
+ //
1360
+ const data = this.safeValue (response, 'data');
1361
+ return this.parseTransaction (data, currency);
1362
+ }
1363
+
1364
+ parseTransaction (transaction, currency = undefined) {
1365
+ //
1366
+ // withdraw
1367
+ //
1368
+ // {
1369
+ // "id": "65e01087-afb0-4ab2-afdb-cc925e360296"
1370
+ // }
1371
+ //
1372
+ currency = this.safeCurrency (undefined, currency);
1373
+ return {
1374
+ 'id': this.safeString (transaction, 'id'),
1375
+ 'txid': undefined,
1376
+ 'timestamp': undefined,
1377
+ 'datetime': undefined,
1378
+ 'network': undefined,
1379
+ 'addressFrom': undefined,
1380
+ 'address': undefined,
1381
+ 'addressTo': undefined,
1382
+ 'amount': undefined,
1383
+ 'type': undefined,
1384
+ 'currency': currency['code'],
1385
+ 'status': undefined,
1386
+ 'updated': undefined,
1387
+ 'tagFrom': undefined,
1388
+ 'tag': undefined,
1389
+ 'tagTo': undefined,
1390
+ 'comment': undefined,
1391
+ 'fee': undefined,
1392
+ 'info': transaction,
1393
+ };
1394
+ }
1395
+
1396
+ sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
1397
+ let url = this.implodeHostname (this.urls['api'][api]);
1398
+ if (api === 'public') {
1399
+ const query = this.omit (params, this.extractParams (path));
1400
+ url += '/' + this.implodeParams (path, params) + '.json';
1401
+ if (Object.keys (query).length) {
1402
+ url += '?' + this.urlencode (query);
1403
+ }
1404
+ } else if (api === 'v1_01Public') {
1405
+ const query = this.omit (params, this.extractParams (path));
1406
+ url += '/' + this.implodeParams (path, params);
1407
+ if (Object.keys (query).length) {
1408
+ url += '?' + this.urlencode (query);
1409
+ }
1410
+ } else if (api === 'v1_01Private') {
1411
+ this.checkRequiredCredentials ();
1412
+ const query = this.omit (params, this.extractParams (path));
1413
+ url += '/' + this.implodeParams (path, params);
1414
+ const nonce = this.milliseconds ().toString ();
1415
+ let payload = undefined;
1416
+ if (method !== 'POST') {
1417
+ if (Object.keys (query).length) {
1418
+ url += '?' + this.urlencode (query);
1419
+ }
1420
+ payload = this.apiKey + nonce;
1421
+ } else if (body === undefined) {
1422
+ body = this.json (query);
1423
+ payload = this.apiKey + nonce + body;
1424
+ }
1425
+ headers = {
1426
+ 'Request-Timestamp': nonce,
1427
+ 'Operation-Id': this.uuid (),
1428
+ 'API-Key': this.apiKey,
1429
+ 'API-Hash': this.hmac (this.encode (payload), this.encode (this.secret), 'sha512'),
1430
+ 'Content-Type': 'application/json',
1431
+ };
1432
+ } else {
1433
+ this.checkRequiredCredentials ();
1434
+ body = this.urlencode (this.extend ({
1435
+ 'method': path,
1436
+ 'moment': this.nonce (),
1437
+ }, params));
1438
+ headers = {
1439
+ 'Content-Type': 'application/x-www-form-urlencoded',
1440
+ 'API-Key': this.apiKey,
1441
+ 'API-Hash': this.hmac (this.encode (body), this.encode (this.secret), 'sha512'),
1442
+ };
1443
+ }
1444
+ return { 'url': url, 'method': method, 'body': body, 'headers': headers };
1445
+ }
1446
+
1447
+ handleErrors (httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) {
1448
+ if (response === undefined) {
1449
+ return; // fallback to default error handler
1450
+ }
1451
+ if ('code' in response) {
1452
+ //
1453
+ // bitbay returns the integer 'success': 1 key from their private API
1454
+ // or an integer 'code' value from 0 to 510 and an error message
1455
+ //
1456
+ // { 'success': 1, ... }
1457
+ // { 'code': 502, 'message': 'Invalid sign' }
1458
+ // { 'code': 0, 'message': 'offer funds not exceeding minimums' }
1459
+ //
1460
+ // 400 At least one parameter wasn't set
1461
+ // 401 Invalid order type
1462
+ // 402 No orders with specified currencies
1463
+ // 403 Invalid payment currency name
1464
+ // 404 Error. Wrong transaction type
1465
+ // 405 Order with this id doesn't exist
1466
+ // 406 No enough money or crypto
1467
+ // 408 Invalid currency name
1468
+ // 501 Invalid public key
1469
+ // 502 Invalid sign
1470
+ // 503 Invalid moment parameter. Request time doesn't match current server time
1471
+ // 504 Invalid method
1472
+ // 505 Key has no permission for this action
1473
+ // 506 Account locked. Please contact with customer service
1474
+ // 509 The BIC/SWIFT is required for this currency
1475
+ // 510 Invalid market name
1476
+ //
1477
+ const code = this.safeString (response, 'code'); // always an integer
1478
+ const feedback = this.id + ' ' + body;
1479
+ this.throwExactlyMatchedException (this.exceptions, code, feedback);
1480
+ throw new ExchangeError (feedback);
1481
+ } else if ('status' in response) {
1482
+ //
1483
+ // {"status":"Fail","errors":["OFFER_FUNDS_NOT_EXCEEDING_MINIMUMS"]}
1484
+ //
1485
+ const status = this.safeString (response, 'status');
1486
+ if (status === 'Fail') {
1487
+ const errors = this.safeValue (response, 'errors');
1488
+ const feedback = this.id + ' ' + body;
1489
+ for (let i = 0; i < errors.length; i++) {
1490
+ const error = errors[i];
1491
+ this.throwExactlyMatchedException (this.exceptions, error, feedback);
1492
+ }
1493
+ throw new ExchangeError (feedback);
1494
+ }
1495
+ }
1496
+ }
1497
+ };