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/bitso.js ADDED
@@ -0,0 +1,1062 @@
1
+ 'use strict';
2
+
3
+ // ---------------------------------------------------------------------------
4
+
5
+ const Exchange = require ('./base/Exchange');
6
+ const { ExchangeError, InvalidNonce, AuthenticationError, OrderNotFound, BadRequest } = require ('./base/errors');
7
+ const { TICK_SIZE } = require ('./base/functions/number');
8
+ const Precise = require ('./base/Precise');
9
+
10
+ // ---------------------------------------------------------------------------
11
+
12
+ module.exports = class bitso extends Exchange {
13
+ describe () {
14
+ return this.deepExtend (super.describe (), {
15
+ 'id': 'bitso',
16
+ 'name': 'Bitso',
17
+ 'countries': [ 'MX' ], // Mexico
18
+ 'rateLimit': 2000, // 30 requests per minute
19
+ 'version': 'v3',
20
+ 'has': {
21
+ 'CORS': undefined,
22
+ 'spot': true,
23
+ 'margin': false,
24
+ 'swap': false,
25
+ 'future': false,
26
+ 'option': false,
27
+ 'addMargin': false,
28
+ 'cancelOrder': true,
29
+ 'createOrder': true,
30
+ 'createReduceOnlyOrder': false,
31
+ 'fetchBalance': true,
32
+ 'fetchBorrowRate': false,
33
+ 'fetchBorrowRateHistories': false,
34
+ 'fetchBorrowRateHistory': false,
35
+ 'fetchBorrowRates': false,
36
+ 'fetchBorrowRatesPerSymbol': false,
37
+ 'fetchDepositAddress': true,
38
+ 'fetchFundingFee': false,
39
+ 'fetchFundingFees': true,
40
+ 'fetchFundingHistory': false,
41
+ 'fetchFundingRate': false,
42
+ 'fetchFundingRateHistory': false,
43
+ 'fetchFundingRates': false,
44
+ 'fetchIndexOHLCV': false,
45
+ 'fetchLeverage': false,
46
+ 'fetchMarkets': true,
47
+ 'fetchMarkOHLCV': false,
48
+ 'fetchMyTrades': true,
49
+ 'fetchOHLCV': true,
50
+ 'fetchOpenOrders': true,
51
+ 'fetchOrder': true,
52
+ 'fetchOrderBook': true,
53
+ 'fetchOrderTrades': true,
54
+ 'fetchPosition': false,
55
+ 'fetchPositions': false,
56
+ 'fetchPositionsRisk': false,
57
+ 'fetchPremiumIndexOHLCV': false,
58
+ 'fetchTicker': true,
59
+ 'fetchTrades': true,
60
+ 'fetchTradingFee': false,
61
+ 'fetchTradingFees': true,
62
+ 'fetchTransfer': false,
63
+ 'fetchTransfers': false,
64
+ 'reduceMargin': false,
65
+ 'setLeverage': false,
66
+ 'setMarginMode': false,
67
+ 'setPositionMode': false,
68
+ 'transfer': false,
69
+ 'withdraw': true,
70
+ },
71
+ 'urls': {
72
+ 'logo': 'https://user-images.githubusercontent.com/51840849/87295554-11f98280-c50e-11ea-80d6-15b3bafa8cbf.jpg',
73
+ 'api': 'https://api.bitso.com',
74
+ 'www': 'https://bitso.com',
75
+ 'doc': 'https://bitso.com/api_info',
76
+ 'fees': 'https://bitso.com/fees',
77
+ 'referral': 'https://bitso.com/?ref=itej',
78
+ },
79
+ 'precisionMode': TICK_SIZE,
80
+ 'options': {
81
+ 'precision': {
82
+ 'XRP': 0.000001,
83
+ 'MXN': 0.01,
84
+ 'TUSD': 0.01,
85
+ },
86
+ 'defaultPrecision': 0.00000001,
87
+ },
88
+ 'timeframes': {
89
+ '1m': '60',
90
+ '5m': '300',
91
+ '15m': '900',
92
+ '30m': '1800',
93
+ '1h': '3600',
94
+ '4h': '14400',
95
+ '12h': '43200',
96
+ '1d': '86400',
97
+ '1w': '604800',
98
+ },
99
+ 'api': {
100
+ 'public': {
101
+ 'get': [
102
+ 'available_books',
103
+ 'ticker',
104
+ 'order_book',
105
+ 'trades',
106
+ 'ohlc',
107
+ ],
108
+ },
109
+ 'private': {
110
+ 'get': [
111
+ 'account_status',
112
+ 'balance',
113
+ 'fees',
114
+ 'fundings',
115
+ 'fundings/{fid}',
116
+ 'funding_destination',
117
+ 'kyc_documents',
118
+ 'ledger',
119
+ 'ledger/trades',
120
+ 'ledger/fees',
121
+ 'ledger/fundings',
122
+ 'ledger/withdrawals',
123
+ 'mx_bank_codes',
124
+ 'open_orders',
125
+ 'order_trades/{oid}',
126
+ 'orders/{oid}',
127
+ 'user_trades',
128
+ 'user_trades/{tid}',
129
+ 'withdrawals/',
130
+ 'withdrawals/{wid}',
131
+ ],
132
+ 'post': [
133
+ 'bitcoin_withdrawal',
134
+ 'debit_card_withdrawal',
135
+ 'ether_withdrawal',
136
+ 'ripple_withdrawal',
137
+ 'bcash_withdrawal',
138
+ 'litecoin_withdrawal',
139
+ 'orders',
140
+ 'phone_number',
141
+ 'phone_verification',
142
+ 'phone_withdrawal',
143
+ 'spei_withdrawal',
144
+ 'ripple_withdrawal',
145
+ 'bcash_withdrawal',
146
+ 'litecoin_withdrawal',
147
+ ],
148
+ 'delete': [
149
+ 'orders/{oid}',
150
+ 'orders/all',
151
+ ],
152
+ },
153
+ },
154
+ 'exceptions': {
155
+ '0201': AuthenticationError, // Invalid Nonce or Invalid Credentials
156
+ '104': InvalidNonce, // Cannot perform request - nonce must be higher than 1520307203724237
157
+ '0304': BadRequest, // {"success":false,"error":{"code":"0304","message":"The field time_bucket () is either invalid or missing"}}
158
+ },
159
+ });
160
+ }
161
+
162
+ async fetchMarkets (params = {}) {
163
+ const response = await this.publicGetAvailableBooks (params);
164
+ //
165
+ // {
166
+ // "success":true,
167
+ // "payload":[
168
+ // {
169
+ // "book":"btc_mxn",
170
+ // "minimum_price":"500",
171
+ // "maximum_price":"10000000",
172
+ // "minimum_amount":"0.00005",
173
+ // "maximum_amount":"500",
174
+ // "minimum_value":"5",
175
+ // "maximum_value":"10000000",
176
+ // "tick_size":"0.01",
177
+ // "fees":{
178
+ // "flat_rate":{"maker":"0.500","taker":"0.650"},
179
+ // "structure":[
180
+ // {"volume":"1500000","maker":"0.00500","taker":"0.00650"},
181
+ // {"volume":"2000000","maker":"0.00490","taker":"0.00637"},
182
+ // {"volume":"5000000","maker":"0.00480","taker":"0.00624"},
183
+ // {"volume":"7000000","maker":"0.00440","taker":"0.00572"},
184
+ // {"volume":"10000000","maker":"0.00420","taker":"0.00546"},
185
+ // {"volume":"15000000","maker":"0.00400","taker":"0.00520"},
186
+ // {"volume":"35000000","maker":"0.00370","taker":"0.00481"},
187
+ // {"volume":"50000000","maker":"0.00300","taker":"0.00390"},
188
+ // {"volume":"150000000","maker":"0.00200","taker":"0.00260"},
189
+ // {"volume":"250000000","maker":"0.00100","taker":"0.00130"},
190
+ // {"volume":"9999999999","maker":"0.00000","taker":"0.00130"},
191
+ // ]
192
+ // }
193
+ // },
194
+ // ]
195
+ // }
196
+ const markets = this.safeValue (response, 'payload');
197
+ const result = [];
198
+ for (let i = 0; i < markets.length; i++) {
199
+ const market = markets[i];
200
+ const id = this.safeString (market, 'book');
201
+ const [ baseId, quoteId ] = id.split ('_');
202
+ let base = baseId.toUpperCase ();
203
+ let quote = quoteId.toUpperCase ();
204
+ base = this.safeCurrencyCode (base);
205
+ quote = this.safeCurrencyCode (quote);
206
+ const fees = this.safeValue (market, 'fees', {});
207
+ const flatRate = this.safeValue (fees, 'flat_rate', {});
208
+ const takerString = this.safeString (flatRate, 'taker');
209
+ const makerString = this.safeString (flatRate, 'maker');
210
+ const taker = this.parseNumber (Precise.stringDiv (takerString, '100'));
211
+ const maker = this.parseNumber (Precise.stringDiv (makerString, '100'));
212
+ const feeTiers = this.safeValue (fees, 'structure', []);
213
+ const fee = {
214
+ 'taker': taker,
215
+ 'maker': maker,
216
+ 'percentage': true,
217
+ 'tierBased': true,
218
+ };
219
+ const takerFees = [];
220
+ const makerFees = [];
221
+ for (let j = 0; j < feeTiers.length; j++) {
222
+ const tier = feeTiers[j];
223
+ const volume = this.safeNumber (tier, 'volume');
224
+ const takerFee = this.safeNumber (tier, 'taker');
225
+ const makerFee = this.safeNumber (tier, 'maker');
226
+ takerFees.push ([ volume, takerFee ]);
227
+ makerFees.push ([ volume, makerFee ]);
228
+ if (j === 0) {
229
+ fee['taker'] = takerFee;
230
+ fee['maker'] = makerFee;
231
+ }
232
+ }
233
+ const tiers = {
234
+ 'taker': takerFees,
235
+ 'maker': makerFees,
236
+ };
237
+ fee['tiers'] = tiers;
238
+ const defaultPricePrecision = this.safeNumber (this.options['precision'], quote, this.options['defaultPrecision']);
239
+ result.push (this.extend ({
240
+ 'id': id,
241
+ 'symbol': base + '/' + quote,
242
+ 'base': base,
243
+ 'quote': quote,
244
+ 'settle': undefined,
245
+ 'baseId': baseId,
246
+ 'quoteId': quoteId,
247
+ 'settleId': undefined,
248
+ 'type': 'spot',
249
+ 'spot': true,
250
+ 'margin': false,
251
+ 'swap': false,
252
+ 'future': false,
253
+ 'option': false,
254
+ 'active': undefined,
255
+ 'contract': false,
256
+ 'linear': undefined,
257
+ 'inverse': undefined,
258
+ 'taker': taker,
259
+ 'maker': maker,
260
+ 'contractSize': undefined,
261
+ 'expiry': undefined,
262
+ 'expiryDatetime': undefined,
263
+ 'strike': undefined,
264
+ 'optionType': undefined,
265
+ 'precision': {
266
+ 'amount': this.safeNumber (this.options['precision'], base, this.options['defaultPrecision']),
267
+ 'price': this.safeNumber (market, 'tick_size', defaultPricePrecision),
268
+ },
269
+ 'limits': {
270
+ 'leverage': {
271
+ 'min': undefined,
272
+ 'max': undefined,
273
+ },
274
+ 'amount': {
275
+ 'min': this.safeNumber (market, 'minimum_amount'),
276
+ 'max': this.safeNumber (market, 'maximum_amount'),
277
+ },
278
+ 'price': {
279
+ 'min': this.safeNumber (market, 'minimum_price'),
280
+ 'max': this.safeNumber (market, 'maximum_price'),
281
+ },
282
+ 'cost': {
283
+ 'min': this.safeNumber (market, 'minimum_value'),
284
+ 'max': this.safeNumber (market, 'maximum_value'),
285
+ },
286
+ },
287
+ 'info': market,
288
+ }, fee));
289
+ }
290
+ return result;
291
+ }
292
+
293
+ parseBalance (response) {
294
+ const payload = this.safeValue (response, 'payload', {});
295
+ const balances = this.safeValue (payload, 'balances');
296
+ const result = {
297
+ 'info': response,
298
+ 'timestamp': undefined,
299
+ 'datetime': undefined,
300
+ };
301
+ for (let i = 0; i < balances.length; i++) {
302
+ const balance = balances[i];
303
+ const currencyId = this.safeString (balance, 'currency');
304
+ const code = this.safeCurrencyCode (currencyId);
305
+ const account = this.account ();
306
+ account['free'] = this.safeString (balance, 'available');
307
+ account['used'] = this.safeString (balance, 'locked');
308
+ account['total'] = this.safeString (balance, 'total');
309
+ result[code] = account;
310
+ }
311
+ return this.safeBalance (result);
312
+ }
313
+
314
+ async fetchBalance (params = {}) {
315
+ await this.loadMarkets ();
316
+ const response = await this.privateGetBalance (params);
317
+ //
318
+ // {
319
+ // "success": true,
320
+ // "payload": {
321
+ // "balances": [
322
+ // {
323
+ // "currency": "bat",
324
+ // "available": "0.00000000",
325
+ // "locked": "0.00000000",
326
+ // "total": "0.00000000",
327
+ // "pending_deposit": "0.00000000",
328
+ // "pending_withdrawal": "0.00000000"
329
+ // },
330
+ // {
331
+ // "currency": "bch",
332
+ // "available": "0.00000000",
333
+ // "locked": "0.00000000",
334
+ // "total": "0.00000000",
335
+ // "pending_deposit": "0.00000000",
336
+ // "pending_withdrawal": "0.00000000"
337
+ // },
338
+ // ],
339
+ // },
340
+ // }
341
+ //
342
+ return this.parseBalance (response);
343
+ }
344
+
345
+ async fetchOrderBook (symbol, limit = undefined, params = {}) {
346
+ await this.loadMarkets ();
347
+ const request = {
348
+ 'book': this.marketId (symbol),
349
+ };
350
+ const response = await this.publicGetOrderBook (this.extend (request, params));
351
+ const orderbook = this.safeValue (response, 'payload');
352
+ const timestamp = this.parse8601 (this.safeString (orderbook, 'updated_at'));
353
+ return this.parseOrderBook (orderbook, symbol, timestamp, 'bids', 'asks', 'price', 'amount');
354
+ }
355
+
356
+ parseTicker (ticker, market = undefined) {
357
+ //
358
+ // {
359
+ // "high":"37446.85",
360
+ // "last":"36599.54",
361
+ // "created_at":"2022-01-28T12:06:11+00:00",
362
+ // "book":"btc_usdt",
363
+ // "volume":"7.29075419",
364
+ // "vwap":"36579.1564400307",
365
+ // "low":"35578.52",
366
+ // "ask":"36574.76",
367
+ // "bid":"36538.22",
368
+ // "change_24":"-105.64"
369
+ // }
370
+ //
371
+ const symbol = this.safeSymbol (undefined, market);
372
+ const timestamp = this.parse8601 (this.safeString (ticker, 'created_at'));
373
+ const vwap = this.safeString (ticker, 'vwap');
374
+ const baseVolume = this.safeString (ticker, 'volume');
375
+ const quoteVolume = Precise.stringMul (baseVolume, vwap);
376
+ const last = this.safeString (ticker, 'last');
377
+ return this.safeTicker ({
378
+ 'symbol': symbol,
379
+ 'timestamp': timestamp,
380
+ 'datetime': this.iso8601 (timestamp),
381
+ 'high': this.safeString (ticker, 'high'),
382
+ 'low': this.safeString (ticker, 'low'),
383
+ 'bid': this.safeString (ticker, 'bid'),
384
+ 'bidVolume': undefined,
385
+ 'ask': this.safeString (ticker, 'ask'),
386
+ 'askVolume': undefined,
387
+ 'vwap': vwap,
388
+ 'open': undefined,
389
+ 'close': last,
390
+ 'last': last,
391
+ 'previousClose': undefined,
392
+ 'change': undefined,
393
+ 'percentage': undefined,
394
+ 'average': undefined,
395
+ 'baseVolume': baseVolume,
396
+ 'quoteVolume': quoteVolume,
397
+ 'info': ticker,
398
+ }, market, false);
399
+ }
400
+
401
+ async fetchTicker (symbol, params = {}) {
402
+ await this.loadMarkets ();
403
+ const market = this.market (symbol);
404
+ const request = {
405
+ 'book': market['id'],
406
+ };
407
+ const response = await this.publicGetTicker (this.extend (request, params));
408
+ const ticker = this.safeValue (response, 'payload');
409
+ //
410
+ // {
411
+ // "success":true,
412
+ // "payload":{
413
+ // "high":"37446.85",
414
+ // "last":"37051.96",
415
+ // "created_at":"2022-01-28T17:03:29+00:00",
416
+ // "book":"btc_usdt",
417
+ // "volume":"6.16176186",
418
+ // "vwap":"36582.6293169472",
419
+ // "low":"35578.52",
420
+ // "ask":"37083.62",
421
+ // "bid":"37039.66",
422
+ // "change_24":"478.45"
423
+ // }
424
+ // }
425
+ //
426
+ return this.parseTicker (ticker, market);
427
+ }
428
+
429
+ async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
430
+ await this.loadMarkets ();
431
+ const market = this.market (symbol);
432
+ const request = {
433
+ 'book': market['id'],
434
+ 'time_bucket': this.timeframes[timeframe],
435
+ };
436
+ if (since !== undefined) {
437
+ request['start'] = since;
438
+ if (limit !== undefined) {
439
+ const duration = this.parseTimeframe (timeframe);
440
+ request['end'] = this.sum (since, duration * limit * 1000);
441
+ }
442
+ } else if (limit !== undefined) {
443
+ const now = this.milliseconds ();
444
+ request['end'] = now;
445
+ request['start'] = now - this.parseTimeframe (timeframe) * 1000 * limit;
446
+ }
447
+ const response = await this.publicGetOhlc (this.extend (request, params));
448
+ //
449
+ // {
450
+ // "success":true,
451
+ // "payload": [
452
+ // {
453
+ // "bucket_start_time":1648219140000,
454
+ // "first_trade_time":1648219154990,
455
+ // "last_trade_time":1648219189441,
456
+ // "first_rate":"44958.60",
457
+ // "last_rate":"44979.88",
458
+ // "min_rate":"44957.33",
459
+ // "max_rate":"44979.88",
460
+ // "trade_count":8,
461
+ // "volume":"0.00082814",
462
+ // "vwap":"44965.02"
463
+ // },
464
+ // ]
465
+ // }
466
+ //
467
+ const payload = this.safeValue (response, 'payload', []);
468
+ return this.parseOHLCVs (payload, market, timeframe, since, limit);
469
+ }
470
+
471
+ parseOHLCV (ohlcv, market = undefined, timeframe = '1m') {
472
+ //
473
+ // {
474
+ // "bucket_start_time":1648219140000,
475
+ // "first_trade_time":1648219154990,
476
+ // "last_trade_time":1648219189441,
477
+ // "first_rate":"44958.60",
478
+ // "last_rate":"44979.88",
479
+ // "min_rate":"44957.33",
480
+ // "max_rate":"44979.88",
481
+ // "trade_count":8,
482
+ // "volume":"0.00082814",
483
+ // "vwap":"44965.02"
484
+ // },
485
+ //
486
+ return [
487
+ this.safeInteger (ohlcv, 'bucket_start_time'),
488
+ this.safeNumber (ohlcv, 'first_rate'),
489
+ this.safeNumber (ohlcv, 'max_rate'),
490
+ this.safeNumber (ohlcv, 'min_rate'),
491
+ this.safeNumber (ohlcv, 'last_rate'),
492
+ this.safeNumber (ohlcv, 'volume'),
493
+ ];
494
+ }
495
+
496
+ parseTrade (trade, market = undefined) {
497
+ //
498
+ // fetchTrades (public)
499
+ //
500
+ // {
501
+ // "book": "btc_usdt",
502
+ // "created_at": "2021-11-24T12:14:53+0000",
503
+ // "amount": "0.00026562",
504
+ // "maker_side": "sell",
505
+ // "price": "56471.55",
506
+ // "tid": "52557338"
507
+ // }
508
+ //
509
+ // fetchMyTrades (private)
510
+ //
511
+ // {
512
+ // "book": "btc_usdt",
513
+ // "created_at": "2021-11-24T12:31:03+0000",
514
+ // "minor": "11.30356000",
515
+ // "major": "-0.00020000",
516
+ // "fees_amount": "0.01119052",
517
+ // "fees_currency": "usdt",
518
+ // "minor_currency": "usdt",
519
+ // "major_currency": "btc",
520
+ // "oid": "djTzMIWx2Vi3iMjl",
521
+ // "tid": "52559051",
522
+ // "price": "56517.80",
523
+ // "side": "sell",
524
+ // "maker_side": "buy"
525
+ // }
526
+ //
527
+ // fetchOrderTrades (private)
528
+ //
529
+ // {
530
+ // "book": "btc_usdt",
531
+ // "created_at": "2021-11-24T12:30:52+0000",
532
+ // "minor": "-11.33047916",
533
+ // "major": "0.00020020",
534
+ // "fees_amount": "0.00000020",
535
+ // "fees_currency": "btc",
536
+ // "minor_currency": "usdt",
537
+ // "major_currency": "btc",
538
+ // "oid": "O0D2zcljjjQF5xlG",
539
+ // "tid": "52559030",
540
+ // "price": "56595.80",
541
+ // "side": "buy",
542
+ // "maker_side": "sell"
543
+ // }
544
+ //
545
+ const timestamp = this.parse8601 (this.safeString (trade, 'created_at'));
546
+ const marketId = this.safeString (trade, 'book');
547
+ const symbol = this.safeSymbol (marketId, market, '_');
548
+ const side = this.safeString2 (trade, 'side', 'maker_side');
549
+ const makerSide = this.safeString (trade, 'maker_side');
550
+ let takerOrMaker = undefined;
551
+ if (side === makerSide) {
552
+ takerOrMaker = 'maker';
553
+ } else {
554
+ takerOrMaker = 'taker';
555
+ }
556
+ let amount = this.safeString2 (trade, 'amount', 'major');
557
+ if (amount !== undefined) {
558
+ amount = Precise.stringAbs (amount);
559
+ }
560
+ let fee = undefined;
561
+ const feeCost = this.safeString (trade, 'fees_amount');
562
+ if (feeCost !== undefined) {
563
+ const feeCurrencyId = this.safeString (trade, 'fees_currency');
564
+ const feeCurrency = this.safeCurrencyCode (feeCurrencyId);
565
+ fee = {
566
+ 'cost': feeCost,
567
+ 'currency': feeCurrency,
568
+ };
569
+ }
570
+ let cost = this.safeString (trade, 'minor');
571
+ if (cost !== undefined) {
572
+ cost = Precise.stringAbs (cost);
573
+ }
574
+ const price = this.safeString (trade, 'price');
575
+ const orderId = this.safeString (trade, 'oid');
576
+ const id = this.safeString (trade, 'tid');
577
+ return this.safeTrade ({
578
+ 'id': id,
579
+ 'info': trade,
580
+ 'timestamp': timestamp,
581
+ 'datetime': this.iso8601 (timestamp),
582
+ 'symbol': symbol,
583
+ 'order': orderId,
584
+ 'type': undefined,
585
+ 'side': side,
586
+ 'takerOrMaker': takerOrMaker,
587
+ 'price': price,
588
+ 'amount': amount,
589
+ 'cost': cost,
590
+ 'fee': fee,
591
+ }, market);
592
+ }
593
+
594
+ async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
595
+ await this.loadMarkets ();
596
+ const market = this.market (symbol);
597
+ const request = {
598
+ 'book': market['id'],
599
+ };
600
+ const response = await this.publicGetTrades (this.extend (request, params));
601
+ return this.parseTrades (response['payload'], market, since, limit);
602
+ }
603
+
604
+ async fetchTradingFees (params = {}) {
605
+ await this.loadMarkets ();
606
+ const response = await this.privateGetFees (params);
607
+ //
608
+ // {
609
+ // success: true,
610
+ // payload: {
611
+ // fees: [
612
+ // {
613
+ // book: 'btc_mxn',
614
+ // fee_percent: '0.6500',
615
+ // fee_decimal: '0.00650000',
616
+ // taker_fee_percent: '0.6500',
617
+ // taker_fee_decimal: '0.00650000',
618
+ // maker_fee_percent: '0.5000',
619
+ // maker_fee_decimal: '0.00500000',
620
+ // volume_currency: 'mxn',
621
+ // current_volume: '0.00',
622
+ // next_volume: '1500000.00',
623
+ // next_maker_fee_percent: '0.490',
624
+ // next_taker_fee_percent: '0.637',
625
+ // nextVolume: '1500000.00',
626
+ // nextFee: '0.490',
627
+ // nextTakerFee: '0.637'
628
+ // },
629
+ // ...
630
+ // ],
631
+ // deposit_fees: [
632
+ // {
633
+ // currency: 'btc',
634
+ // method: 'rewards',
635
+ // fee: '0.00',
636
+ // is_fixed: false
637
+ // },
638
+ // ...
639
+ // ],
640
+ // withdrawal_fees: {
641
+ // ada: '0.20958100',
642
+ // bch: '0.00009437',
643
+ // ars: '0',
644
+ // btc: '0.00001209',
645
+ // ...
646
+ // }
647
+ // }
648
+ // }
649
+ //
650
+ const payload = this.safeValue (response, 'payload', {});
651
+ const fees = this.safeValue (payload, 'fees', []);
652
+ const result = {};
653
+ for (let i = 0; i < fees.length; i++) {
654
+ const fee = fees[i];
655
+ const marketId = this.safeString (fee, 'book');
656
+ const symbol = this.safeSymbol (marketId, undefined, '_');
657
+ result[symbol] = {
658
+ 'info': fee,
659
+ 'symbol': symbol,
660
+ 'maker': this.safeNumber (fee, 'maker_fee_decimal'),
661
+ 'taker': this.safeNumber (fee, 'taker_fee_decimal'),
662
+ 'percentage': true,
663
+ 'tierBased': true,
664
+ };
665
+ }
666
+ return result;
667
+ }
668
+
669
+ async fetchMyTrades (symbol = undefined, since = undefined, limit = 25, params = {}) {
670
+ await this.loadMarkets ();
671
+ const market = this.market (symbol);
672
+ // the don't support fetching trades starting from a date yet
673
+ // use the `marker` extra param for that
674
+ // this is not a typo, the variable name is 'marker' (don't confuse with 'market')
675
+ const markerInParams = ('marker' in params);
676
+ // warn the user with an exception if the user wants to filter
677
+ // starting from since timestamp, but does not set the trade id with an extra 'marker' param
678
+ if ((since !== undefined) && !markerInParams) {
679
+ throw new ExchangeError (this.id + ' fetchMyTrades() does not support fetching trades starting from a timestamp with the `since` argument, use the `marker` extra param to filter starting from an integer trade id');
680
+ }
681
+ // convert it to an integer unconditionally
682
+ if (markerInParams) {
683
+ params = this.extend (params, {
684
+ 'marker': parseInt (params['marker']),
685
+ });
686
+ }
687
+ const request = {
688
+ 'book': market['id'],
689
+ 'limit': limit, // default = 25, max = 100
690
+ // 'sort': 'desc', // default = desc
691
+ // 'marker': id, // integer id to start from
692
+ };
693
+ const response = await this.privateGetUserTrades (this.extend (request, params));
694
+ return this.parseTrades (response['payload'], market, since, limit);
695
+ }
696
+
697
+ async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
698
+ await this.loadMarkets ();
699
+ const request = {
700
+ 'book': this.marketId (symbol),
701
+ 'side': side,
702
+ 'type': type,
703
+ 'major': this.amountToPrecision (symbol, amount),
704
+ };
705
+ if (type === 'limit') {
706
+ request['price'] = this.priceToPrecision (symbol, price);
707
+ }
708
+ const response = await this.privatePostOrders (this.extend (request, params));
709
+ const id = this.safeString (response['payload'], 'oid');
710
+ return {
711
+ 'info': response,
712
+ 'id': id,
713
+ };
714
+ }
715
+
716
+ async cancelOrder (id, symbol = undefined, params = {}) {
717
+ await this.loadMarkets ();
718
+ const request = {
719
+ 'oid': id,
720
+ };
721
+ return await this.privateDeleteOrdersOid (this.extend (request, params));
722
+ }
723
+
724
+ parseOrderStatus (status) {
725
+ const statuses = {
726
+ 'partial-fill': 'open', // this is a common substitution in ccxt
727
+ 'completed': 'closed',
728
+ };
729
+ return this.safeString (statuses, status, status);
730
+ }
731
+
732
+ parseOrder (order, market = undefined) {
733
+ const id = this.safeString (order, 'oid');
734
+ const side = this.safeString (order, 'side');
735
+ const status = this.parseOrderStatus (this.safeString (order, 'status'));
736
+ const marketId = this.safeString (order, 'book');
737
+ const symbol = this.safeSymbol (marketId, market, '_');
738
+ const orderType = this.safeString (order, 'type');
739
+ const timestamp = this.parse8601 (this.safeString (order, 'created_at'));
740
+ const price = this.safeString (order, 'price');
741
+ const amount = this.safeString (order, 'original_amount');
742
+ const remaining = this.safeString (order, 'unfilled_amount');
743
+ const clientOrderId = this.safeString (order, 'client_id');
744
+ return this.safeOrder ({
745
+ 'info': order,
746
+ 'id': id,
747
+ 'clientOrderId': clientOrderId,
748
+ 'timestamp': timestamp,
749
+ 'datetime': this.iso8601 (timestamp),
750
+ 'lastTradeTimestamp': undefined,
751
+ 'symbol': symbol,
752
+ 'type': orderType,
753
+ 'timeInForce': undefined,
754
+ 'postOnly': undefined,
755
+ 'side': side,
756
+ 'price': price,
757
+ 'stopPrice': undefined,
758
+ 'amount': amount,
759
+ 'cost': undefined,
760
+ 'remaining': remaining,
761
+ 'filled': undefined,
762
+ 'status': status,
763
+ 'fee': undefined,
764
+ 'average': undefined,
765
+ 'trades': undefined,
766
+ }, market);
767
+ }
768
+
769
+ async fetchOpenOrders (symbol = undefined, since = undefined, limit = 25, params = {}) {
770
+ await this.loadMarkets ();
771
+ const market = this.market (symbol);
772
+ // the don't support fetching trades starting from a date yet
773
+ // use the `marker` extra param for that
774
+ // this is not a typo, the variable name is 'marker' (don't confuse with 'market')
775
+ const markerInParams = ('marker' in params);
776
+ // warn the user with an exception if the user wants to filter
777
+ // starting from since timestamp, but does not set the trade id with an extra 'marker' param
778
+ if ((since !== undefined) && !markerInParams) {
779
+ throw new ExchangeError (this.id + ' fetchOpenOrders() does not support fetching orders starting from a timestamp with the `since` argument, use the `marker` extra param to filter starting from an integer trade id');
780
+ }
781
+ // convert it to an integer unconditionally
782
+ if (markerInParams) {
783
+ params = this.extend (params, {
784
+ 'marker': parseInt (params['marker']),
785
+ });
786
+ }
787
+ const request = {
788
+ 'book': market['id'],
789
+ 'limit': limit, // default = 25, max = 100
790
+ // 'sort': 'desc', // default = desc
791
+ // 'marker': id, // integer id to start from
792
+ };
793
+ const response = await this.privateGetOpenOrders (this.extend (request, params));
794
+ const orders = this.parseOrders (response['payload'], market, since, limit);
795
+ return orders;
796
+ }
797
+
798
+ async fetchOrder (id, symbol = undefined, params = {}) {
799
+ await this.loadMarkets ();
800
+ const response = await this.privateGetOrdersOid ({
801
+ 'oid': id,
802
+ });
803
+ const payload = this.safeValue (response, 'payload');
804
+ if (Array.isArray (payload)) {
805
+ const numOrders = response['payload'].length;
806
+ if (numOrders === 1) {
807
+ return this.parseOrder (payload[0]);
808
+ }
809
+ }
810
+ throw new OrderNotFound (this.id + ': The order ' + id + ' not found.');
811
+ }
812
+
813
+ async fetchOrderTrades (id, symbol = undefined, since = undefined, limit = undefined, params = {}) {
814
+ await this.loadMarkets ();
815
+ const market = this.market (symbol);
816
+ const request = {
817
+ 'oid': id,
818
+ };
819
+ const response = await this.privateGetOrderTradesOid (this.extend (request, params));
820
+ return this.parseTrades (response['payload'], market);
821
+ }
822
+
823
+ async fetchDepositAddress (code, params = {}) {
824
+ await this.loadMarkets ();
825
+ const currency = this.currency (code);
826
+ const request = {
827
+ 'fund_currency': currency['id'],
828
+ };
829
+ const response = await this.privateGetFundingDestination (this.extend (request, params));
830
+ let address = this.safeString (response['payload'], 'account_identifier');
831
+ let tag = undefined;
832
+ if (address.indexOf ('?dt=') >= 0) {
833
+ const parts = address.split ('?dt=');
834
+ address = this.safeString (parts, 0);
835
+ tag = this.safeString (parts, 1);
836
+ }
837
+ this.checkAddress (address);
838
+ return {
839
+ 'currency': code,
840
+ 'address': address,
841
+ 'tag': tag,
842
+ 'network': undefined,
843
+ 'info': response,
844
+ };
845
+ }
846
+
847
+ async fetchFundingFees (params = {}) {
848
+ await this.loadMarkets ();
849
+ const response = await this.privateGetFees (params);
850
+ //
851
+ // {
852
+ // success: true,
853
+ // payload: {
854
+ // fees: [
855
+ // {
856
+ // book: 'btc_mxn',
857
+ // fee_percent: '0.6500',
858
+ // fee_decimal: '0.00650000',
859
+ // taker_fee_percent: '0.6500',
860
+ // taker_fee_decimal: '0.00650000',
861
+ // maker_fee_percent: '0.5000',
862
+ // maker_fee_decimal: '0.00500000',
863
+ // volume_currency: 'mxn',
864
+ // current_volume: '0.00',
865
+ // next_volume: '1500000.00',
866
+ // next_maker_fee_percent: '0.490',
867
+ // next_taker_fee_percent: '0.637',
868
+ // nextVolume: '1500000.00',
869
+ // nextFee: '0.490',
870
+ // nextTakerFee: '0.637'
871
+ // },
872
+ // ...
873
+ // ],
874
+ // deposit_fees: [
875
+ // {
876
+ // currency: 'btc',
877
+ // method: 'rewards',
878
+ // fee: '0.00',
879
+ // is_fixed: false
880
+ // },
881
+ // ...
882
+ // ],
883
+ // withdrawal_fees: {
884
+ // ada: '0.20958100',
885
+ // bch: '0.00009437',
886
+ // ars: '0',
887
+ // btc: '0.00001209',
888
+ // ...
889
+ // }
890
+ // }
891
+ // }
892
+ //
893
+ const payload = this.safeValue (response, 'payload', {});
894
+ const depositFees = this.safeValue (payload, 'deposit_fees', []);
895
+ const deposit = {};
896
+ for (let i = 0; i < depositFees.length; i++) {
897
+ const depositFee = depositFees[i];
898
+ const currencyId = this.safeString (depositFee, 'currency');
899
+ const code = this.safeCurrencyCode (currencyId);
900
+ deposit[code] = this.safeNumber (depositFee, 'fee');
901
+ }
902
+ const withdraw = {};
903
+ const withdrawalFees = this.safeValue (payload, 'withdrawal_fees', []);
904
+ const currencyIds = Object.keys (withdrawalFees);
905
+ for (let i = 0; i < currencyIds.length; i++) {
906
+ const currencyId = currencyIds[i];
907
+ const code = this.safeCurrencyCode (currencyId);
908
+ withdraw[code] = this.safeNumber (withdrawalFees, currencyId);
909
+ }
910
+ return {
911
+ 'info': response,
912
+ 'deposit': deposit,
913
+ 'withdraw': withdraw,
914
+ };
915
+ }
916
+
917
+ async withdraw (code, amount, address, tag = undefined, params = {}) {
918
+ [ tag, params ] = this.handleWithdrawTagAndParams (tag, params);
919
+ this.checkAddress (address);
920
+ await this.loadMarkets ();
921
+ const methods = {
922
+ 'BTC': 'Bitcoin',
923
+ 'ETH': 'Ether',
924
+ 'XRP': 'Ripple',
925
+ 'BCH': 'Bcash',
926
+ 'LTC': 'Litecoin',
927
+ };
928
+ const currency = this.currency (code);
929
+ const method = (code in methods) ? methods[code] : undefined;
930
+ if (method === undefined) {
931
+ throw new ExchangeError (this.id + ' not valid withdraw coin: ' + code);
932
+ }
933
+ const request = {
934
+ 'amount': amount,
935
+ 'address': address,
936
+ 'destination_tag': tag,
937
+ };
938
+ const classMethod = 'privatePost' + method + 'Withdrawal';
939
+ const response = await this[classMethod] (this.extend (request, params));
940
+ //
941
+ // {
942
+ // "success": true,
943
+ // "payload": [
944
+ // {
945
+ // "wid": "c5b8d7f0768ee91d3b33bee648318688",
946
+ // "status": "pending",
947
+ // "created_at": "2016-04-08T17:52:31.000+00:00",
948
+ // "currency": "btc",
949
+ // "method": "Bitcoin",
950
+ // "amount": "0.48650929",
951
+ // "details": {
952
+ // "withdrawal_address": "18MsnATiNiKLqUHDTRKjurwMg7inCrdNEp",
953
+ // "tx_hash": "d4f28394693e9fb5fffcaf730c11f32d1922e5837f76ca82189d3bfe30ded433"
954
+ // }
955
+ // },
956
+ // ]
957
+ // }
958
+ //
959
+ const payload = this.safeValue (response, 'payload', []);
960
+ const first = this.safeValue (payload, 0);
961
+ return this.parseTransaction (first, currency);
962
+ }
963
+
964
+ parseTransaction (transaction, currency = undefined) {
965
+ //
966
+ // withdraw
967
+ //
968
+ // {
969
+ // "wid": "c5b8d7f0768ee91d3b33bee648318688",
970
+ // "status": "pending",
971
+ // "created_at": "2016-04-08T17:52:31.000+00:00",
972
+ // "currency": "btc",
973
+ // "method": "Bitcoin",
974
+ // "amount": "0.48650929",
975
+ // "details": {
976
+ // "withdrawal_address": "18MsnATiNiKLqUHDTRKjurwMg7inCrdNEp",
977
+ // "tx_hash": "d4f28394693e9fb5fffcaf730c11f32d1922e5837f76ca82189d3bfe30ded433"
978
+ // }
979
+ // }
980
+ //
981
+ currency = this.safeCurrency (undefined, currency);
982
+ return {
983
+ 'id': this.safeString (transaction, 'wid'),
984
+ 'txid': undefined,
985
+ 'timestamp': undefined,
986
+ 'datetime': undefined,
987
+ 'network': undefined,
988
+ 'addressFrom': undefined,
989
+ 'address': undefined,
990
+ 'addressTo': undefined,
991
+ 'amount': undefined,
992
+ 'type': undefined,
993
+ 'currency': currency['code'],
994
+ 'status': undefined,
995
+ 'updated': undefined,
996
+ 'tagFrom': undefined,
997
+ 'tag': undefined,
998
+ 'tagTo': undefined,
999
+ 'comment': undefined,
1000
+ 'fee': undefined,
1001
+ 'info': transaction,
1002
+ };
1003
+ }
1004
+
1005
+ sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
1006
+ let endpoint = '/' + this.version + '/' + this.implodeParams (path, params);
1007
+ const query = this.omit (params, this.extractParams (path));
1008
+ if (method === 'GET') {
1009
+ if (Object.keys (query).length) {
1010
+ endpoint += '?' + this.urlencode (query);
1011
+ }
1012
+ }
1013
+ const url = this.urls['api'] + endpoint;
1014
+ if (api === 'private') {
1015
+ this.checkRequiredCredentials ();
1016
+ const nonce = this.nonce ().toString ();
1017
+ let request = [ nonce, method, endpoint ].join ('');
1018
+ if (method !== 'GET') {
1019
+ if (Object.keys (query).length) {
1020
+ body = this.json (query);
1021
+ request += body;
1022
+ }
1023
+ }
1024
+ const signature = this.hmac (this.encode (request), this.encode (this.secret));
1025
+ const auth = this.apiKey + ':' + nonce + ':' + signature;
1026
+ headers = {
1027
+ 'Authorization': 'Bitso ' + auth,
1028
+ 'Content-Type': 'application/json',
1029
+ };
1030
+ }
1031
+ return { 'url': url, 'method': method, 'body': body, 'headers': headers };
1032
+ }
1033
+
1034
+ handleErrors (httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) {
1035
+ if (response === undefined) {
1036
+ return; // fallback to default error handler
1037
+ }
1038
+ if ('success' in response) {
1039
+ //
1040
+ // {"success":false,"error":{"code":104,"message":"Cannot perform request - nonce must be higher than 1520307203724237"}}
1041
+ //
1042
+ let success = this.safeValue (response, 'success', false);
1043
+ if (typeof success === 'string') {
1044
+ if ((success === 'true') || (success === '1')) {
1045
+ success = true;
1046
+ } else {
1047
+ success = false;
1048
+ }
1049
+ }
1050
+ if (!success) {
1051
+ const feedback = this.id + ' ' + this.json (response);
1052
+ const error = this.safeValue (response, 'error');
1053
+ if (error === undefined) {
1054
+ throw new ExchangeError (feedback);
1055
+ }
1056
+ const code = this.safeString (error, 'code');
1057
+ this.throwExactlyMatchedException (this.exceptions, code, feedback);
1058
+ throw new ExchangeError (feedback);
1059
+ }
1060
+ }
1061
+ }
1062
+ };