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/latoken.js ADDED
@@ -0,0 +1,1445 @@
1
+ 'use strict';
2
+
3
+ // ---------------------------------------------------------------------------
4
+
5
+ const Exchange = require ('./base/Exchange');
6
+ const { ExchangeError, AuthenticationError, ArgumentsRequired, InvalidNonce, BadRequest, ExchangeNotAvailable, PermissionDenied, AccountSuspended, RateLimitExceeded, InsufficientFunds, BadSymbol, InvalidOrder } = require ('./base/errors');
7
+ const { TICK_SIZE } = require ('./base/functions/number');
8
+
9
+ // ---------------------------------------------------------------------------
10
+
11
+ module.exports = class latoken extends Exchange {
12
+ describe () {
13
+ return this.deepExtend (super.describe (), {
14
+ 'id': 'latoken',
15
+ 'name': 'Latoken',
16
+ 'countries': [ 'KY' ], // Cayman Islands
17
+ 'version': 'v2',
18
+ 'rateLimit': 1000,
19
+ 'has': {
20
+ 'CORS': undefined,
21
+ 'spot': true,
22
+ 'margin': false,
23
+ 'swap': undefined, // has but unimplemented
24
+ 'future': undefined,
25
+ 'option': false,
26
+ 'cancelAllOrders': true,
27
+ 'cancelOrder': true,
28
+ 'createOrder': true,
29
+ 'fetchBalance': true,
30
+ 'fetchBorrowRate': false,
31
+ 'fetchBorrowRateHistories': false,
32
+ 'fetchBorrowRateHistory': false,
33
+ 'fetchBorrowRates': false,
34
+ 'fetchBorrowRatesPerSymbol': false,
35
+ 'fetchCurrencies': true,
36
+ 'fetchMarkets': true,
37
+ 'fetchMyTrades': true,
38
+ 'fetchOpenOrders': true,
39
+ 'fetchOrder': true,
40
+ 'fetchOrderBook': true,
41
+ 'fetchOrders': true,
42
+ 'fetchTicker': true,
43
+ 'fetchTickers': true,
44
+ 'fetchTime': true,
45
+ 'fetchTrades': true,
46
+ 'fetchTradingFee': true,
47
+ 'fetchTradingFees': false,
48
+ 'fetchTransactions': true,
49
+ 'fetchTransfer': false,
50
+ 'fetchTransfers': true,
51
+ 'transfer': true,
52
+ },
53
+ 'urls': {
54
+ 'logo': 'https://user-images.githubusercontent.com/1294454/61511972-24c39f00-aa01-11e9-9f7c-471f1d6e5214.jpg',
55
+ 'api': 'https://api.latoken.com',
56
+ 'www': 'https://latoken.com',
57
+ 'doc': [
58
+ 'https://api.latoken.com',
59
+ ],
60
+ 'fees': 'https://latoken.com/fees',
61
+ 'referral': 'https://latoken.com/invite?r=mvgp2djk',
62
+ },
63
+ 'api': {
64
+ 'public': {
65
+ 'get': {
66
+ 'book/{currency}/{quote}': 1,
67
+ 'chart/week': 1,
68
+ 'chart/week/{currency}/{quote}': 1,
69
+ 'currency': 1,
70
+ 'currency/available': 1,
71
+ 'currency/quotes': 1,
72
+ 'currency/{currency}': 1,
73
+ 'pair': 1,
74
+ 'pair/available': 1,
75
+ 'ticker': 1,
76
+ 'ticker/{base}/{quote}': 1,
77
+ 'time': 1,
78
+ 'trade/history/{currency}/{quote}': 1,
79
+ 'trade/fee/{currency}/{quote}': 1,
80
+ 'trade/feeLevels': 1,
81
+ 'transaction/bindings': 1,
82
+ },
83
+ },
84
+ 'private': {
85
+ 'get': {
86
+ 'auth/account': 1,
87
+ 'auth/account/currency/{currency}/{type}': 1,
88
+ 'auth/order': 1,
89
+ 'auth/order/getOrder/{id}': 1,
90
+ 'auth/order/pair/{currency}/{quote}': 1,
91
+ 'auth/order/pair/{currency}/{quote}/active': 1,
92
+ 'auth/stopOrder': 1,
93
+ 'auth/stopOrder/getOrder/{id}': 1,
94
+ 'auth/stopOrder/pair/{currency}/{quote}': 1,
95
+ 'auth/stopOrder/pair/{currency}/{quote}/active': 1,
96
+ 'auth/trade': 1,
97
+ 'auth/trade/pair/{currency}/{quote}': 1,
98
+ 'auth/trade/fee/{currency}/{quote}': 1,
99
+ 'auth/transaction': 1,
100
+ 'auth/transaction/bindings': 1,
101
+ 'auth/transaction/bindings/{currency}': 1,
102
+ 'auth/transaction/{id}': 1,
103
+ 'auth/transfer': 1,
104
+ },
105
+ 'post': {
106
+ 'auth/order/cancel': 1,
107
+ 'auth/order/cancelAll': 1,
108
+ 'auth/order/cancelAll/{currency}/{quote}': 1,
109
+ 'auth/order/place': 1,
110
+ 'auth/spot/deposit': 1,
111
+ 'auth/spot/withdraw': 1,
112
+ 'auth/stopOrder/cancel': 1,
113
+ 'auth/stopOrder/cancelAll': 1,
114
+ 'auth/stopOrder/cancelAll/{currency}/{quote}': 1,
115
+ 'auth/stopOrder/place': 1,
116
+ 'auth/transaction/depositAddress': 1,
117
+ 'auth/transaction/withdraw': 1,
118
+ 'auth/transaction/withdraw/cancel': 1,
119
+ 'auth/transaction/withdraw/confirm': 1,
120
+ 'auth/transaction/withdraw/resendCode': 1,
121
+ 'auth/transfer/email': 1,
122
+ 'auth/transfer/id': 1,
123
+ 'auth/transfer/phone': 1,
124
+ },
125
+ },
126
+ },
127
+ 'precisionMode': TICK_SIZE,
128
+ 'fees': {
129
+ 'trading': {
130
+ 'feeSide': 'get',
131
+ 'tierBased': false,
132
+ 'percentage': true,
133
+ 'maker': this.parseNumber ('0.0049'),
134
+ 'taker': this.parseNumber ('0.0049'),
135
+ },
136
+ },
137
+ 'commonCurrencies': {
138
+ 'BUX': 'Buxcoin',
139
+ 'CBT': 'Community Business Token',
140
+ 'CTC': 'CyberTronchain',
141
+ 'DMD': 'Diamond Coin',
142
+ 'FREN': 'Frenchie',
143
+ 'GDX': 'GoldenX',
144
+ 'GEC': 'Geco One',
145
+ 'GEM': 'NFTmall',
146
+ 'GMT': 'GMT Token',
147
+ 'IMC': 'IMCoin',
148
+ 'MT': 'Monarch',
149
+ 'TPAY': 'Tetra Pay',
150
+ 'TRADE': 'Smart Trade Coin',
151
+ 'TSL': 'Treasure SL',
152
+ 'UNO': 'Unobtanium',
153
+ 'WAR': 'Warrior Token',
154
+ },
155
+ 'exceptions': {
156
+ 'exact': {
157
+ 'INTERNAL_ERROR': ExchangeError, // internal server error. You can contact our support to solve this problem. {"message":"Internal Server Error","error":"INTERNAL_ERROR","status":"FAILURE"}
158
+ 'SERVICE_UNAVAILABLE': ExchangeNotAvailable, // requested information currently not available. You can contact our support to solve this problem or retry later.
159
+ 'NOT_AUTHORIZED': AuthenticationError, // user's query not authorized. Check if you are logged in.
160
+ 'FORBIDDEN': PermissionDenied, // you don't have enough access rights.
161
+ 'BAD_REQUEST': BadRequest, // some bad request, for example bad fields values or something else. Read response message for more information.
162
+ 'NOT_FOUND': ExchangeError, // entity not found. Read message for more information.
163
+ 'ACCESS_DENIED': PermissionDenied, // access is denied. Probably you don't have enough access rights, you contact our support.
164
+ 'REQUEST_REJECTED': ExchangeError, // user's request rejected for some reasons. Check error message.
165
+ 'HTTP_MEDIA_TYPE_NOT_SUPPORTED': BadRequest, // http media type not supported.
166
+ 'MEDIA_TYPE_NOT_ACCEPTABLE': BadRequest, // media type not acceptable
167
+ 'METHOD_ARGUMENT_NOT_VALID': BadRequest, // one of method argument is invalid. Check argument types and error message for more information.
168
+ 'VALIDATION_ERROR': BadRequest, // check errors field to get reasons.
169
+ 'ACCOUNT_EXPIRED': AccountSuspended, // restore your account or create a new one.
170
+ 'BAD_CREDENTIALS': AuthenticationError, // invalid username or password.
171
+ 'COOKIE_THEFT': AuthenticationError, // cookie has been stolen. Let's try reset your cookies.
172
+ 'CREDENTIALS_EXPIRED': AccountSuspended, // credentials expired.
173
+ 'INSUFFICIENT_AUTHENTICATION': AuthenticationError, // for example, 2FA required.
174
+ 'UNKNOWN_LOCATION': AuthenticationError, // user logged from unusual location, email confirmation required.
175
+ 'TOO_MANY_REQUESTS': RateLimitExceeded, // too many requests at the time. A response header X-Rate-Limit-Remaining indicates the number of allowed request per a period.
176
+ 'INSUFFICIENT_FUNDS': InsufficientFunds, // {"message":"not enough balance on the spot account for currency (USDT), need (20.000)","error":"INSUFFICIENT_FUNDS","status":"FAILURE"}
177
+ 'ORDER_VALIDATION': InvalidOrder, // {"message":"Quantity (0) is not positive","error":"ORDER_VALIDATION","status":"FAILURE"}
178
+ },
179
+ 'broad': {
180
+ 'invalid API key, signature or digest': AuthenticationError, // {"result":false,"message":"invalid API key, signature or digest","error":"BAD_REQUEST","status":"FAILURE"}
181
+ 'request expired or bad': InvalidNonce, // {"result":false,"message":"request expired or bad <timeAlive>/<timestamp> format","error":"BAD_REQUEST","status":"FAILURE"}
182
+ 'For input string': BadRequest, // {"result":false,"message":"Internal error","error":"For input string: \"NaN\"","status":"FAILURE"}
183
+ 'Unable to resolve currency by tag': BadSymbol, // {"message":"Unable to resolve currency by tag (undefined)","error":"NOT_FOUND","status":"FAILURE"}
184
+ 'Unable to place order because pair is in inactive state': BadSymbol, // {"message":"Unable to place order because pair is in inactive state (PAIR_STATUS_INACTIVE)","error":"ORDER_VALIDATION","status":"FAILURE"}
185
+ },
186
+ },
187
+ 'options': {
188
+ 'defaultType': 'spot',
189
+ 'types': {
190
+ 'wallet': 'ACCOUNT_TYPE_WALLET',
191
+ 'spot': 'ACCOUNT_TYPE_SPOT',
192
+ },
193
+ 'accounts': {
194
+ 'ACCOUNT_TYPE_WALLET': 'wallet',
195
+ 'ACCOUNT_TYPE_SPOT': 'spot',
196
+ },
197
+ 'fetchTradingFee': {
198
+ 'method': 'fetchPrivateTradingFee', // or 'fetchPublicTradingFee'
199
+ },
200
+ },
201
+ });
202
+ }
203
+
204
+ nonce () {
205
+ return this.milliseconds () - this.options['timeDifference'];
206
+ }
207
+
208
+ async fetchTime (params = {}) {
209
+ const response = await this.publicGetTime (params);
210
+ //
211
+ // {
212
+ // "serverTime": 1570615577321
213
+ // }
214
+ //
215
+ return this.safeInteger (response, 'serverTime');
216
+ }
217
+
218
+ async fetchMarkets (params = {}) {
219
+ const currencies = await this.fetchCurrenciesFromCache (params);
220
+ //
221
+ // [
222
+ // {
223
+ // "id":"1a075819-9e0b-48fc-8784-4dab1d186d6d",
224
+ // "status":"CURRENCY_STATUS_ACTIVE",
225
+ // "type":"CURRENCY_TYPE_ALTERNATIVE", // CURRENCY_TYPE_CRYPTO, CURRENCY_TYPE_IEO
226
+ // "name":"MyCryptoBank",
227
+ // "tag":"MCB",
228
+ // "description":"",
229
+ // "logo":"",
230
+ // "decimals":18,
231
+ // "created":1572912000000,
232
+ // "tier":1,
233
+ // "assetClass":"ASSET_CLASS_UNKNOWN",
234
+ // "minTransferAmount":0
235
+ // },
236
+ // {
237
+ // "id":"db02758e-2507-46a5-a805-7bc60355b3eb",
238
+ // "status":"CURRENCY_STATUS_ACTIVE",
239
+ // "type":"CURRENCY_TYPE_FUTURES_CONTRACT",
240
+ // "name":"BTC USDT Futures Contract",
241
+ // "tag":"BTCUSDT",
242
+ // "description":"",
243
+ // "logo":"",
244
+ // "decimals":8,
245
+ // "created":1589459984395,
246
+ // "tier":1,
247
+ // "assetClass":"ASSET_CLASS_UNKNOWN",
248
+ // "minTransferAmount":0
249
+ // },
250
+ // ]
251
+ //
252
+ const response = await this.publicGetPair (params);
253
+ //
254
+ // [
255
+ // {
256
+ // "id":"dba4289b-6b46-4d94-bf55-49eec9a163ad",
257
+ // "status":"PAIR_STATUS_ACTIVE", // CURRENCY_STATUS_INACTIVE
258
+ // "baseCurrency":"fb9b53d6-bbf6-472f-b6ba-73cc0d606c9b",
259
+ // "quoteCurrency":"620f2019-33c0-423b-8a9d-cde4d7f8ef7f",
260
+ // "priceTick":"0.000000100000000000",
261
+ // "priceDecimals":7,
262
+ // "quantityTick":"0.010000000",
263
+ // "quantityDecimals":2,
264
+ // "costDisplayDecimals":7,
265
+ // "created":1572957210501,
266
+ // "minOrderQuantity":"0",
267
+ // "maxOrderCostUsd":"999999999999999999",
268
+ // "minOrderCostUsd":"0",
269
+ // "externalSymbol":""
270
+ // }
271
+ // ]
272
+ //
273
+ if (this.safeValue (this.options, 'adjustForTimeDifference', true)) {
274
+ await this.loadTimeDifference ();
275
+ }
276
+ const currenciesById = this.indexBy (currencies, 'id');
277
+ const result = [];
278
+ for (let i = 0; i < response.length; i++) {
279
+ const market = response[i];
280
+ const id = this.safeString (market, 'id');
281
+ // the exchange shows them inverted
282
+ const baseId = this.safeString (market, 'baseCurrency');
283
+ const quoteId = this.safeString (market, 'quoteCurrency');
284
+ const baseCurrency = this.safeValue (currenciesById, baseId);
285
+ const quoteCurrency = this.safeValue (currenciesById, quoteId);
286
+ if (baseCurrency !== undefined && quoteCurrency !== undefined) {
287
+ const base = this.safeCurrencyCode (this.safeString (baseCurrency, 'tag'));
288
+ const quote = this.safeCurrencyCode (this.safeString (quoteCurrency, 'tag'));
289
+ const lowercaseQuote = quote.toLowerCase ();
290
+ const capitalizedQuote = this.capitalize (lowercaseQuote);
291
+ const status = this.safeString (market, 'status');
292
+ result.push ({
293
+ 'id': id,
294
+ 'symbol': base + '/' + quote,
295
+ 'base': base,
296
+ 'quote': quote,
297
+ 'settle': undefined,
298
+ 'baseId': baseId,
299
+ 'quoteId': quoteId,
300
+ 'settleId': undefined,
301
+ 'type': 'spot',
302
+ 'spot': true,
303
+ 'margin': false,
304
+ 'swap': false,
305
+ 'future': false,
306
+ 'option': false,
307
+ 'active': (status === 'PAIR_STATUS_ACTIVE'), // assuming true
308
+ 'contract': false,
309
+ 'linear': undefined,
310
+ 'inverse': undefined,
311
+ 'contractSize': undefined,
312
+ 'expiry': undefined,
313
+ 'expiryDatetime': undefined,
314
+ 'strike': undefined,
315
+ 'optionType': undefined,
316
+ 'precision': {
317
+ 'amount': this.safeNumber (market, 'quantityTick'),
318
+ 'price': this.safeNumber (market, 'priceTick'),
319
+ },
320
+ 'limits': {
321
+ 'leverage': {
322
+ 'min': undefined,
323
+ 'max': undefined,
324
+ },
325
+ 'amount': {
326
+ 'min': this.safeNumber (market, 'minOrderQuantity'),
327
+ 'max': undefined,
328
+ },
329
+ 'price': {
330
+ 'min': undefined,
331
+ 'max': undefined,
332
+ },
333
+ 'cost': {
334
+ 'min': this.safeNumber (market, 'minOrderCost' + capitalizedQuote),
335
+ 'max': this.safeNumber (market, 'maxOrderCost' + capitalizedQuote),
336
+ },
337
+ },
338
+ 'info': market,
339
+ });
340
+ }
341
+ }
342
+ return result;
343
+ }
344
+
345
+ async fetchCurrenciesFromCache (params = {}) {
346
+ // this method is now redundant
347
+ // currencies are now fetched before markets
348
+ const options = this.safeValue (this.options, 'fetchCurrencies', {});
349
+ const timestamp = this.safeInteger (options, 'timestamp');
350
+ const expires = this.safeInteger (options, 'expires', 1000);
351
+ const now = this.milliseconds ();
352
+ if ((timestamp === undefined) || ((now - timestamp) > expires)) {
353
+ const response = await this.publicGetCurrency (params);
354
+ this.options['fetchCurrencies'] = this.extend (options, {
355
+ 'response': response,
356
+ 'timestamp': now,
357
+ });
358
+ }
359
+ return this.safeValue (this.options['fetchCurrencies'], 'response');
360
+ }
361
+
362
+ async fetchCurrencies (params = {}) {
363
+ const response = await this.fetchCurrenciesFromCache (params);
364
+ //
365
+ // [
366
+ // {
367
+ // "id":"1a075819-9e0b-48fc-8784-4dab1d186d6d",
368
+ // "status":"CURRENCY_STATUS_ACTIVE",
369
+ // "type":"CURRENCY_TYPE_ALTERNATIVE", // CURRENCY_TYPE_CRYPTO, CURRENCY_TYPE_IEO
370
+ // "name":"MyCryptoBank",
371
+ // "tag":"MCB",
372
+ // "description":"",
373
+ // "logo":"",
374
+ // "decimals":18,
375
+ // "created":1572912000000,
376
+ // "tier":1,
377
+ // "assetClass":"ASSET_CLASS_UNKNOWN",
378
+ // "minTransferAmount":0
379
+ // },
380
+ // {
381
+ // "id":"db02758e-2507-46a5-a805-7bc60355b3eb",
382
+ // "status":"CURRENCY_STATUS_ACTIVE",
383
+ // "type":"CURRENCY_TYPE_FUTURES_CONTRACT",
384
+ // "name":"BTC USDT Futures Contract",
385
+ // "tag":"BTCUSDT",
386
+ // "description":"",
387
+ // "logo":"",
388
+ // "decimals":8,
389
+ // "created":1589459984395,
390
+ // "tier":1,
391
+ // "assetClass":"ASSET_CLASS_UNKNOWN",
392
+ // "minTransferAmount":0
393
+ // },
394
+ // ]
395
+ //
396
+ const result = {};
397
+ for (let i = 0; i < response.length; i++) {
398
+ const currency = response[i];
399
+ const id = this.safeString (currency, 'id');
400
+ const tag = this.safeString (currency, 'tag');
401
+ const code = this.safeCurrencyCode (tag);
402
+ const decimals = this.safeString (currency, 'decimals');
403
+ const precision = this.parseNumber ('1e-' + decimals);
404
+ const fee = this.safeNumber (currency, 'fee');
405
+ const currencyType = this.safeString (currency, 'type');
406
+ const parts = currencyType.split ('_');
407
+ const numParts = parts.length;
408
+ const lastPart = this.safeValue (parts, numParts - 1);
409
+ const type = lastPart.toLowerCase ();
410
+ const status = this.safeString (currency, 'status');
411
+ const active = (status === 'CURRENCY_STATUS_ACTIVE');
412
+ const name = this.safeString (currency, 'name');
413
+ result[code] = {
414
+ 'id': id,
415
+ 'code': code,
416
+ 'info': currency,
417
+ 'name': name,
418
+ 'type': type,
419
+ 'active': active,
420
+ 'deposit': undefined,
421
+ 'withdraw': undefined,
422
+ 'fee': fee,
423
+ 'precision': precision,
424
+ 'limits': {
425
+ 'amount': {
426
+ 'min': this.safeNumber (currency, 'minTransferAmount'),
427
+ 'max': undefined,
428
+ },
429
+ 'withdraw': {
430
+ 'min': undefined,
431
+ 'max': undefined,
432
+ },
433
+ },
434
+ };
435
+ }
436
+ return result;
437
+ }
438
+
439
+ async fetchBalance (params = {}) {
440
+ await this.loadMarkets ();
441
+ const response = await this.privateGetAuthAccount (params);
442
+ //
443
+ // [
444
+ // {
445
+ // id: "e5852e02-8711-431c-9749-a6f5503c6dbe",
446
+ // status: "ACCOUNT_STATUS_ACTIVE",
447
+ // type: "ACCOUNT_TYPE_WALLET",
448
+ // timestamp: "1635920106506",
449
+ // currency: "0c3a106d-bde3-4c13-a26e-3fd2394529e5",
450
+ // available: "100.000000",
451
+ // blocked: "0.000000"
452
+ // },
453
+ // {
454
+ // id: "369df204-acbc-467e-a25e-b16e3cc09cf6",
455
+ // status: "ACCOUNT_STATUS_ACTIVE",
456
+ // type: "ACCOUNT_TYPE_SPOT",
457
+ // timestamp: "1635920106504",
458
+ // currency: "0c3a106d-bde3-4c13-a26e-3fd2394529e5",
459
+ // available: "100.000000",
460
+ // blocked: "0.000000"
461
+ // }
462
+ // ]
463
+ //
464
+ const result = {
465
+ 'info': response,
466
+ 'timestamp': undefined,
467
+ 'datetime': undefined,
468
+ };
469
+ let maxTimestamp = undefined;
470
+ const defaultType = this.safeString2 (this.options, 'fetchBalance', 'defaultType', 'spot');
471
+ const type = this.safeString (params, 'type', defaultType);
472
+ const types = this.safeValue (this.options, 'types', {});
473
+ const accountType = this.safeString (types, type, type);
474
+ const balancesByType = this.groupBy (response, 'type');
475
+ const balances = this.safeValue (balancesByType, accountType, []);
476
+ for (let i = 0; i < balances.length; i++) {
477
+ const balance = balances[i];
478
+ const currencyId = this.safeString (balance, 'currency');
479
+ const timestamp = this.safeInteger (balance, 'timestamp');
480
+ if (timestamp !== undefined) {
481
+ if (maxTimestamp === undefined) {
482
+ maxTimestamp = timestamp;
483
+ } else {
484
+ maxTimestamp = Math.max (maxTimestamp, timestamp);
485
+ }
486
+ }
487
+ const code = this.safeCurrencyCode (currencyId);
488
+ const account = this.account ();
489
+ account['free'] = this.safeString (balance, 'available');
490
+ account['used'] = this.safeString (balance, 'blocked');
491
+ result[code] = account;
492
+ }
493
+ result['timestamp'] = maxTimestamp;
494
+ result['datetime'] = this.iso8601 (maxTimestamp);
495
+ return this.safeBalance (result);
496
+ }
497
+
498
+ async fetchOrderBook (symbol, limit = undefined, params = {}) {
499
+ await this.loadMarkets ();
500
+ const market = this.market (symbol);
501
+ const request = {
502
+ 'currency': market['baseId'],
503
+ 'quote': market['quoteId'],
504
+ };
505
+ if (limit !== undefined) {
506
+ request['limit'] = limit; // max 1000
507
+ }
508
+ const response = await this.publicGetBookCurrencyQuote (this.extend (request, params));
509
+ //
510
+ // {
511
+ // "ask":[
512
+ // {"price":"4428.76","quantity":"0.08136","cost":"360.3239136","accumulated":"360.3239136"},
513
+ // {"price":"4429.77","quantity":"1.11786","cost":"4951.8626922","accumulated":"5312.1866058"},
514
+ // {"price":"4430.94","quantity":"1.78418","cost":"7905.5945292","accumulated":"13217.781135"},
515
+ // ],
516
+ // "bid":[
517
+ // {"price":"4428.43","quantity":"0.13675","cost":"605.5878025","accumulated":"605.5878025"},
518
+ // {"price":"4428.19","quantity":"0.03619","cost":"160.2561961","accumulated":"765.8439986"},
519
+ // {"price":"4428.15","quantity":"0.02926","cost":"129.567669","accumulated":"895.4116676"},
520
+ // ],
521
+ // "totalAsk":"53.14814",
522
+ // "totalBid":"112216.9029791"
523
+ // }
524
+ //
525
+ return this.parseOrderBook (response, symbol, undefined, 'bid', 'ask', 'price', 'quantity');
526
+ }
527
+
528
+ parseTicker (ticker, market = undefined) {
529
+ //
530
+ // {
531
+ // "symbol":"620f2019-33c0-423b-8a9d-cde4d7f8ef7f/0c3a106d-bde3-4c13-a26e-3fd2394529e5",
532
+ // "baseCurrency":"620f2019-33c0-423b-8a9d-cde4d7f8ef7f",
533
+ // "quoteCurrency":"0c3a106d-bde3-4c13-a26e-3fd2394529e5",
534
+ // "volume24h":"76411867.852585600000000000",
535
+ // "volume7d":"637809926.759451100000000000",
536
+ // "change24h":"2.5300",
537
+ // "change7d":"5.1300",
538
+ // "lastPrice":"4426.9"
539
+ // }
540
+ //
541
+ const marketId = this.safeString (ticker, 'symbol');
542
+ const symbol = this.safeSymbol (marketId, market);
543
+ const last = this.safeString (ticker, 'lastPrice');
544
+ const change = this.safeString (ticker, 'change24h');
545
+ const timestamp = this.nonce ();
546
+ return this.safeTicker ({
547
+ 'symbol': symbol,
548
+ 'timestamp': timestamp,
549
+ 'datetime': this.iso8601 (timestamp),
550
+ 'low': this.safeString (ticker, 'low'),
551
+ 'high': this.safeString (ticker, 'high'),
552
+ 'bid': undefined,
553
+ 'bidVolume': undefined,
554
+ 'ask': undefined,
555
+ 'askVolume': undefined,
556
+ 'vwap': undefined,
557
+ 'open': undefined,
558
+ 'close': last,
559
+ 'last': last,
560
+ 'previousClose': undefined,
561
+ 'change': change,
562
+ 'percentage': undefined,
563
+ 'average': undefined,
564
+ 'baseVolume': undefined,
565
+ 'quoteVolume': this.safeString (ticker, 'volume24h'),
566
+ 'info': ticker,
567
+ }, market, false);
568
+ }
569
+
570
+ async fetchTicker (symbol, params = {}) {
571
+ await this.loadMarkets ();
572
+ const market = this.market (symbol);
573
+ const request = {
574
+ 'base': market['baseId'],
575
+ 'quote': market['quoteId'],
576
+ };
577
+ const response = await this.publicGetTickerBaseQuote (this.extend (request, params));
578
+ //
579
+ // {
580
+ // "symbol":"620f2019-33c0-423b-8a9d-cde4d7f8ef7f/0c3a106d-bde3-4c13-a26e-3fd2394529e5",
581
+ // "baseCurrency":"620f2019-33c0-423b-8a9d-cde4d7f8ef7f",
582
+ // "quoteCurrency":"0c3a106d-bde3-4c13-a26e-3fd2394529e5",
583
+ // "volume24h":"76411867.852585600000000000",
584
+ // "volume7d":"637809926.759451100000000000",
585
+ // "change24h":"2.5300",
586
+ // "change7d":"5.1300",
587
+ // "lastPrice":"4426.9"
588
+ // }
589
+ //
590
+ return this.parseTicker (response, market);
591
+ }
592
+
593
+ async fetchTickers (symbols = undefined, params = {}) {
594
+ await this.loadMarkets ();
595
+ const response = await this.publicGetTicker (params);
596
+ //
597
+ // [
598
+ // {
599
+ // "symbol":"DASH/BTC",
600
+ // "baseCurrency":"ed75c263-4ab9-494b-8426-031dab1c7cc1",
601
+ // "quoteCurrency":"92151d82-df98-4d88-9a4d-284fa9eca49f",
602
+ // "volume24h":"1.977753278000000000",
603
+ // "volume7d":"18.964342670000000000",
604
+ // "change24h":"-1.4800",
605
+ // "change7d":"-5.5200",
606
+ // "lastPrice":"0.003066"
607
+ // },
608
+ // ]
609
+ //
610
+ return this.parseTickers (response, symbols);
611
+ }
612
+
613
+ parseTrade (trade, market = undefined) {
614
+ //
615
+ // fetchTrades (public)
616
+ //
617
+ // {
618
+ // "id":"c152f814-8eeb-44f0-8f3f-e5c568f2ffcf",
619
+ // "isMakerBuyer":false,
620
+ // "baseCurrency":"620f2019-33c0-423b-8a9d-cde4d7f8ef7f",
621
+ // "quoteCurrency":"0c3a106d-bde3-4c13-a26e-3fd2394529e5",
622
+ // "price":"4435.56",
623
+ // "quantity":"0.32534",
624
+ // "cost":"1443.0650904",
625
+ // "timestamp":1635854642725,
626
+ // "makerBuyer":false
627
+ // }
628
+ //
629
+ // fetchMyTrades (private)
630
+ //
631
+ // {
632
+ // "id":"02e02533-b4bf-4ba9-9271-24e2108dfbf7",
633
+ // "isMakerBuyer":false,
634
+ // "direction":"TRADE_DIRECTION_BUY",
635
+ // "baseCurrency":"620f2019-33c0-423b-8a9d-cde4d7f8ef7f",
636
+ // "quoteCurrency":"0c3a106d-bde3-4c13-a26e-3fd2394529e5",
637
+ // "price":"4564.32",
638
+ // "quantity":"0.01000",
639
+ // "cost":"45.6432",
640
+ // "fee":"0.223651680000000000",
641
+ // "order":"c9cac6a0-484c-4892-88e7-ad51b39f2ce1",
642
+ // "timestamp":1635921580399,
643
+ // "makerBuyer":false
644
+ // }
645
+ //
646
+ const type = undefined;
647
+ const timestamp = this.safeInteger (trade, 'timestamp');
648
+ const priceString = this.safeString (trade, 'price');
649
+ const amountString = this.safeString (trade, 'quantity');
650
+ const costString = this.safeString (trade, 'cost');
651
+ const makerBuyer = this.safeValue (trade, 'makerBuyer');
652
+ let side = this.safeString (trade, 'direction');
653
+ if (side === undefined) {
654
+ side = makerBuyer ? 'sell' : 'buy';
655
+ } else {
656
+ if (side === 'TRADE_DIRECTION_BUY') {
657
+ side = 'buy';
658
+ } else if (side === 'TRADE_DIRECTION_SELL') {
659
+ side = 'sell';
660
+ }
661
+ }
662
+ const isBuy = (side === 'buy');
663
+ const takerOrMaker = (makerBuyer && isBuy) ? 'maker' : 'taker';
664
+ const baseId = this.safeString (trade, 'baseCurrency');
665
+ const quoteId = this.safeString (trade, 'quoteCurrency');
666
+ const base = this.safeCurrencyCode (baseId);
667
+ const quote = this.safeCurrencyCode (quoteId);
668
+ const symbol = base + '/' + quote;
669
+ if (symbol in this.markets) {
670
+ market = this.market (symbol);
671
+ }
672
+ const id = this.safeString (trade, 'id');
673
+ const orderId = this.safeString (trade, 'order');
674
+ const feeCost = this.safeString (trade, 'fee');
675
+ let fee = undefined;
676
+ if (feeCost !== undefined) {
677
+ fee = {
678
+ 'cost': feeCost,
679
+ 'currency': quote,
680
+ };
681
+ }
682
+ return this.safeTrade ({
683
+ 'info': trade,
684
+ 'timestamp': timestamp,
685
+ 'datetime': this.iso8601 (timestamp),
686
+ 'symbol': symbol,
687
+ 'id': id,
688
+ 'order': orderId,
689
+ 'type': type,
690
+ 'takerOrMaker': takerOrMaker,
691
+ 'side': side,
692
+ 'price': priceString,
693
+ 'amount': amountString,
694
+ 'cost': costString,
695
+ 'fee': fee,
696
+ }, market);
697
+ }
698
+
699
+ async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
700
+ await this.loadMarkets ();
701
+ const market = this.market (symbol);
702
+ const request = {
703
+ 'currency': market['baseId'],
704
+ 'quote': market['quoteId'],
705
+ // 'from': since.toString (), // milliseconds
706
+ // 'limit': limit, // default 100, max 1000
707
+ };
708
+ if (limit !== undefined) {
709
+ request['limit'] = limit; // default 100, max 1000
710
+ }
711
+ const response = await this.publicGetTradeHistoryCurrencyQuote (this.extend (request, params));
712
+ //
713
+ // [
714
+ // {"id":"c152f814-8eeb-44f0-8f3f-e5c568f2ffcf","isMakerBuyer":false,"baseCurrency":"620f2019-33c0-423b-8a9d-cde4d7f8ef7f","quoteCurrency":"0c3a106d-bde3-4c13-a26e-3fd2394529e5","price":"4435.56","quantity":"0.32534","cost":"1443.0650904","timestamp":1635854642725,"makerBuyer":false},
715
+ // {"id":"cfecbefb-3d11-43d7-b9d4-fa16211aad8a","isMakerBuyer":false,"baseCurrency":"620f2019-33c0-423b-8a9d-cde4d7f8ef7f","quoteCurrency":"0c3a106d-bde3-4c13-a26e-3fd2394529e5","price":"4435.13","quantity":"0.26540","cost":"1177.083502","timestamp":1635854641114,"makerBuyer":false},
716
+ // {"id":"f43d3ec8-db94-49f3-b534-91dbc2779296","isMakerBuyer":true,"baseCurrency":"620f2019-33c0-423b-8a9d-cde4d7f8ef7f","quoteCurrency":"0c3a106d-bde3-4c13-a26e-3fd2394529e5","price":"4435.00","quantity":"0.41738","cost":"1851.0803","timestamp":1635854640323,"makerBuyer":true},
717
+ // ]
718
+ //
719
+ return this.parseTrades (response, market, since, limit);
720
+ }
721
+
722
+ async fetchTradingFee (symbol, params = {}) {
723
+ let method = this.safeString (params, 'method');
724
+ params = this.omit (params, 'method');
725
+ if (method === undefined) {
726
+ const options = this.safeValue (this.options, 'fetchTradingFee', {});
727
+ method = this.safeString (options, 'method', 'fetchPrivateTradingFee');
728
+ }
729
+ return await this[method] (symbol, params);
730
+ }
731
+
732
+ async fetchPublicTradingFee (symbol, params = {}) {
733
+ await this.loadMarkets ();
734
+ const market = this.market (symbol);
735
+ const request = {
736
+ 'currency': market['baseId'],
737
+ 'quote': market['quoteId'],
738
+ };
739
+ const response = await this.publicGetTradeFeeCurrencyQuote (this.extend (request, params));
740
+ //
741
+ // {
742
+ // makerFee: '0.004900000000000000',
743
+ // takerFee: '0.004900000000000000',
744
+ // type: 'FEE_SCHEME_TYPE_PERCENT_QUOTE',
745
+ // take: 'FEE_SCHEME_TAKE_PROPORTION'
746
+ // }
747
+ //
748
+ return {
749
+ 'info': response,
750
+ 'symbol': symbol,
751
+ 'maker': this.safeNumber (response, 'makerFee'),
752
+ 'taker': this.safeNumber (response, 'takerFee'),
753
+ };
754
+ }
755
+
756
+ async fetchPrivateTradingFee (symbol, params = {}) {
757
+ await this.loadMarkets ();
758
+ const market = this.market (symbol);
759
+ const request = {
760
+ 'currency': market['baseId'],
761
+ 'quote': market['quoteId'],
762
+ };
763
+ const response = await this.privateGetAuthTradeFeeCurrencyQuote (this.extend (request, params));
764
+ //
765
+ // {
766
+ // makerFee: '0.004900000000000000',
767
+ // takerFee: '0.004900000000000000',
768
+ // type: 'FEE_SCHEME_TYPE_PERCENT_QUOTE',
769
+ // take: 'FEE_SCHEME_TAKE_PROPORTION'
770
+ // }
771
+ //
772
+ return {
773
+ 'info': response,
774
+ 'symbol': symbol,
775
+ 'maker': this.safeNumber (response, 'makerFee'),
776
+ 'taker': this.safeNumber (response, 'takerFee'),
777
+ };
778
+ }
779
+
780
+ async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
781
+ await this.loadMarkets ();
782
+ const request = {
783
+ // 'currency': market['baseId'],
784
+ // 'quote': market['quoteId'],
785
+ // 'from': this.milliseconds (),
786
+ // 'limit': limit, // default '100'
787
+ };
788
+ let method = 'privateGetAuthTrade';
789
+ let market = undefined;
790
+ if (symbol !== undefined) {
791
+ market = this.market (symbol);
792
+ request['currency'] = market['baseId'];
793
+ request['quote'] = market['quoteId'];
794
+ method = 'privateGetAuthTradePairCurrencyQuote';
795
+ }
796
+ if (limit !== undefined) {
797
+ request['limit'] = limit; // default 100
798
+ }
799
+ const response = await this[method] (this.extend (request, params));
800
+ //
801
+ // [
802
+ // {
803
+ // "id":"02e02533-b4bf-4ba9-9271-24e2108dfbf7",
804
+ // "isMakerBuyer":false,
805
+ // "direction":"TRADE_DIRECTION_BUY",
806
+ // "baseCurrency":"620f2019-33c0-423b-8a9d-cde4d7f8ef7f",
807
+ // "quoteCurrency":"0c3a106d-bde3-4c13-a26e-3fd2394529e5",
808
+ // "price":"4564.32",
809
+ // "quantity":"0.01000",
810
+ // "cost":"45.6432",
811
+ // "fee":"0.223651680000000000",
812
+ // "order":"c9cac6a0-484c-4892-88e7-ad51b39f2ce1",
813
+ // "timestamp":1635921580399,
814
+ // "makerBuyer":false
815
+ // }
816
+ // ]
817
+ //
818
+ return this.parseTrades (response, market, since, limit);
819
+ }
820
+
821
+ parseOrderStatus (status) {
822
+ const statuses = {
823
+ 'ORDER_STATUS_PLACED': 'open',
824
+ 'ORDER_STATUS_CLOSED': 'closed',
825
+ 'ORDER_STATUS_CANCELLED': 'canceled',
826
+ };
827
+ return this.safeString (statuses, status, status);
828
+ }
829
+
830
+ parseOrderType (status) {
831
+ const statuses = {
832
+ 'ORDER_TYPE_MARKET': 'market',
833
+ 'ORDER_TYPE_LIMIT': 'limit',
834
+ };
835
+ return this.safeString (statuses, status, status);
836
+ }
837
+
838
+ parseTimeInForce (timeInForce) {
839
+ const timeInForces = {
840
+ 'ORDER_CONDITION_GOOD_TILL_CANCELLED': 'GTC',
841
+ 'ORDER_CONDITION_IMMEDIATE_OR_CANCEL': 'IOC',
842
+ 'ORDER_CONDITION_FILL_OR_KILL': 'FOK',
843
+ };
844
+ return this.safeString (timeInForces, timeInForce, timeInForce);
845
+ }
846
+
847
+ parseOrder (order, market = undefined) {
848
+ //
849
+ // createOrder
850
+ //
851
+ // {
852
+ // "orderId":"1563460093.134037.704945@0370:2",
853
+ // "cliOrdId":"",
854
+ // "pairId":370,
855
+ // "symbol":"ETHBTC",
856
+ // "side":"sell",
857
+ // "orderType":"limit",
858
+ // "price":1.0,
859
+ // "amount":1.0
860
+ // }
861
+ //
862
+ // fetchOrder, fetchOpenOrders, fetchOrders
863
+ //
864
+ // {
865
+ // "id":"a76bd262-3560-4bfb-98ac-1cedd394f4fc",
866
+ // "status":"ORDER_STATUS_PLACED",
867
+ // "side":"ORDER_SIDE_BUY",
868
+ // "condition":"ORDER_CONDITION_GOOD_TILL_CANCELLED",
869
+ // "type":"ORDER_TYPE_LIMIT",
870
+ // "baseCurrency":"620f2019-33c0-423b-8a9d-cde4d7f8ef7f",
871
+ // "quoteCurrency":"0c3a106d-bde3-4c13-a26e-3fd2394529e5",
872
+ // "clientOrderId":"web-macos_chrome_1a6a6659-6f7c-4fac-be0b-d1d7ac06d",
873
+ // "price":"4000.00",
874
+ // "quantity":"0.01",
875
+ // "cost":"40.000000000000000000",
876
+ // "filled":"0",
877
+ // "trader":"7244bb3a-b6b2-446a-ac78-fa4bce5b59a9",
878
+ // "creator":"ORDER_CREATOR_USER",
879
+ // "creatorId":"",
880
+ // "timestamp":1635920767648
881
+ // }
882
+ //
883
+ // cancelOrder
884
+ //
885
+ // {
886
+ // "message":"cancellation request successfully submitted",
887
+ // "status":"SUCCESS",
888
+ // "id":"a631426d-3543-45ba-941e-75f7825afb0f"
889
+ // }
890
+ //
891
+ const id = this.safeString (order, 'id');
892
+ const timestamp = this.safeInteger (order, 'timestamp');
893
+ const baseId = this.safeString (order, 'baseCurrency');
894
+ const quoteId = this.safeString (order, 'quoteCurrency');
895
+ const base = this.safeCurrencyCode (baseId);
896
+ const quote = this.safeCurrencyCode (quoteId);
897
+ let symbol = undefined;
898
+ if ((base !== undefined) && (quote !== undefined)) {
899
+ symbol = base + '/' + quote;
900
+ if (symbol in this.markets) {
901
+ market = this.market (symbol);
902
+ }
903
+ }
904
+ const orderSide = this.safeString (order, 'side');
905
+ let side = undefined;
906
+ if (orderSide !== undefined) {
907
+ const parts = orderSide.split ('_');
908
+ const partsLength = parts.length;
909
+ side = this.safeStringLower (parts, partsLength - 1);
910
+ }
911
+ const type = this.parseOrderType (this.safeString (order, 'type'));
912
+ const price = this.safeString (order, 'price');
913
+ const amount = this.safeString (order, 'quantity');
914
+ const filled = this.safeString (order, 'filled');
915
+ const cost = this.safeString (order, 'cost');
916
+ let status = this.parseOrderStatus (this.safeString (order, 'status'));
917
+ const message = this.safeString (order, 'message');
918
+ if (message !== undefined) {
919
+ if (message.indexOf ('cancel') >= 0) {
920
+ status = 'canceled';
921
+ } else if (message.indexOf ('accept') >= 0) {
922
+ status = 'open';
923
+ }
924
+ }
925
+ const clientOrderId = this.safeString (order, 'clientOrderId');
926
+ const timeInForce = this.parseTimeInForce (this.safeString (order, 'condition'));
927
+ return this.safeOrder ({
928
+ 'id': id,
929
+ 'clientOrderId': clientOrderId,
930
+ 'info': order,
931
+ 'timestamp': timestamp,
932
+ 'datetime': this.iso8601 (timestamp),
933
+ 'lastTradeTimestamp': undefined,
934
+ 'status': status,
935
+ 'symbol': symbol,
936
+ 'type': type,
937
+ 'timeInForce': timeInForce,
938
+ 'postOnly': undefined,
939
+ 'side': side,
940
+ 'price': price,
941
+ 'stopPrice': undefined,
942
+ 'cost': cost,
943
+ 'amount': amount,
944
+ 'filled': filled,
945
+ 'average': undefined,
946
+ 'remaining': undefined,
947
+ 'fee': undefined,
948
+ 'trades': undefined,
949
+ }, market);
950
+ }
951
+
952
+ async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
953
+ if (symbol === undefined) {
954
+ throw new ArgumentsRequired (this.id + ' fetchOpenOrders() requires a symbol argument');
955
+ }
956
+ await this.loadMarkets ();
957
+ const market = this.market (symbol);
958
+ const request = {
959
+ 'currency': market['baseId'],
960
+ 'quote': market['quoteId'],
961
+ };
962
+ const response = await this.privateGetAuthOrderPairCurrencyQuoteActive (this.extend (request, params));
963
+ //
964
+ // [
965
+ // {
966
+ // "id":"a76bd262-3560-4bfb-98ac-1cedd394f4fc",
967
+ // "status":"ORDER_STATUS_PLACED",
968
+ // "side":"ORDER_SIDE_BUY",
969
+ // "condition":"ORDER_CONDITION_GOOD_TILL_CANCELLED",
970
+ // "type":"ORDER_TYPE_LIMIT",
971
+ // "baseCurrency":"620f2019-33c0-423b-8a9d-cde4d7f8ef7f",
972
+ // "quoteCurrency":"0c3a106d-bde3-4c13-a26e-3fd2394529e5",
973
+ // "clientOrderId":"web-macos_chrome_1a6a6659-6f7c-4fac-be0b-d1d7ac06d",
974
+ // "price":"4000.00",
975
+ // "quantity":"0.01000",
976
+ // "cost":"40.00",
977
+ // "filled":"0.00000",
978
+ // "trader":"7244bb3a-b6b2-446a-ac78-fa4bce5b59a9",
979
+ // "creator":"USER",
980
+ // "creatorId":"",
981
+ // "timestamp":1635920767648
982
+ // }
983
+ // ]
984
+ //
985
+ return this.parseOrders (response, market, since, limit);
986
+ }
987
+
988
+ async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
989
+ await this.loadMarkets ();
990
+ const request = {
991
+ // 'currency': market['baseId'],
992
+ // 'quote': market['quoteId'],
993
+ // 'from': this.milliseconds (),
994
+ // 'limit': limit, // default '100'
995
+ };
996
+ let method = 'privateGetAuthOrder';
997
+ let market = undefined;
998
+ if (symbol !== undefined) {
999
+ market = this.market (symbol);
1000
+ request['currency'] = market['baseId'];
1001
+ request['quote'] = market['quoteId'];
1002
+ method = 'privateGetAuthOrderPairCurrencyQuote';
1003
+ }
1004
+ if (limit !== undefined) {
1005
+ request['limit'] = limit; // default 100
1006
+ }
1007
+ const response = await this[method] (this.extend (request, params));
1008
+ //
1009
+ // [
1010
+ // {
1011
+ // "id":"a76bd262-3560-4bfb-98ac-1cedd394f4fc",
1012
+ // "status":"ORDER_STATUS_PLACED",
1013
+ // "side":"ORDER_SIDE_BUY",
1014
+ // "condition":"ORDER_CONDITION_GOOD_TILL_CANCELLED",
1015
+ // "type":"ORDER_TYPE_LIMIT",
1016
+ // "baseCurrency":"620f2019-33c0-423b-8a9d-cde4d7f8ef7f",
1017
+ // "quoteCurrency":"0c3a106d-bde3-4c13-a26e-3fd2394529e5",
1018
+ // "clientOrderId":"web-macos_chrome_1a6a6659-6f7c-4fac-be0b-d1d7ac06d",
1019
+ // "price":"4000.00",
1020
+ // "quantity":"0.01000",
1021
+ // "cost":"40.00",
1022
+ // "filled":"0.00000",
1023
+ // "trader":"7244bb3a-b6b2-446a-ac78-fa4bce5b59a9",
1024
+ // "creator":"USER",
1025
+ // "creatorId":"",
1026
+ // "timestamp":1635920767648
1027
+ // }
1028
+ // ]
1029
+ //
1030
+ return this.parseOrders (response, market, since, limit);
1031
+ }
1032
+
1033
+ async fetchOrder (id, symbol = undefined, params = {}) {
1034
+ await this.loadMarkets ();
1035
+ const request = {
1036
+ 'id': id,
1037
+ };
1038
+ const response = await this.privateGetAuthOrderGetOrderId (this.extend (request, params));
1039
+ //
1040
+ // {
1041
+ // "id":"a76bd262-3560-4bfb-98ac-1cedd394f4fc",
1042
+ // "status":"ORDER_STATUS_PLACED",
1043
+ // "side":"ORDER_SIDE_BUY",
1044
+ // "condition":"ORDER_CONDITION_GOOD_TILL_CANCELLED",
1045
+ // "type":"ORDER_TYPE_LIMIT",
1046
+ // "baseCurrency":"620f2019-33c0-423b-8a9d-cde4d7f8ef7f",
1047
+ // "quoteCurrency":"0c3a106d-bde3-4c13-a26e-3fd2394529e5",
1048
+ // "clientOrderId":"web-macos_chrome_1a6a6659-6f7c-4fac-be0b-d1d7ac06d",
1049
+ // "price":"4000.00",
1050
+ // "quantity":"0.01",
1051
+ // "cost":"40.000000000000000000",
1052
+ // "filled":"0",
1053
+ // "trader":"7244bb3a-b6b2-446a-ac78-fa4bce5b59a9",
1054
+ // "creator":"ORDER_CREATOR_USER",
1055
+ // "creatorId":"",
1056
+ // "timestamp":1635920767648
1057
+ // }
1058
+ //
1059
+ return this.parseOrder (response);
1060
+ }
1061
+
1062
+ async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
1063
+ await this.loadMarkets ();
1064
+ const market = this.market (symbol);
1065
+ const uppercaseType = type.toUpperCase ();
1066
+ const request = {
1067
+ 'baseCurrency': market['baseId'],
1068
+ 'quoteCurrency': market['quoteId'],
1069
+ 'side': side.toUpperCase (), // "BUY", "BID", "SELL", "ASK"
1070
+ 'condition': 'GTC', // "GTC", "GOOD_TILL_CANCELLED", "IOC", "IMMEDIATE_OR_CANCEL", "FOK", "FILL_OR_KILL"
1071
+ 'type': uppercaseType, // "LIMIT", "MARKET"
1072
+ 'clientOrderId': this.uuid (), // 50 characters max
1073
+ // 'price': this.priceToPrecision (symbol, price),
1074
+ // 'quantity': this.amountToPrecision (symbol, amount),
1075
+ };
1076
+ if (uppercaseType === 'LIMIT') {
1077
+ request['price'] = this.priceToPrecision (symbol, price);
1078
+ }
1079
+ request['quantity'] = this.amountToPrecision (symbol, amount);
1080
+ request['timestamp'] = this.seconds ();
1081
+ const response = await this.privatePostAuthOrderPlace (this.extend (request, params));
1082
+ //
1083
+ // {
1084
+ // "orderId":"1563460093.134037.704945@0370:2",
1085
+ // "cliOrdId":"",
1086
+ // "pairId":370,
1087
+ // "symbol":"ETHBTC",
1088
+ // "side":"sell",
1089
+ // "orderType":"limit",
1090
+ // "price":1.0,
1091
+ // "amount":1.0
1092
+ // }
1093
+ //
1094
+ return this.parseOrder (response, market);
1095
+ }
1096
+
1097
+ async cancelOrder (id, symbol = undefined, params = {}) {
1098
+ await this.loadMarkets ();
1099
+ const request = {
1100
+ 'id': id,
1101
+ };
1102
+ const response = await this.privatePostAuthOrderCancel (this.extend (request, params));
1103
+ //
1104
+ // {
1105
+ // "id": "12345678-1234-1244-1244-123456789012",
1106
+ // "message": "cancellation request successfully submitted",
1107
+ // "status": "SUCCESS",
1108
+ // "error": "",
1109
+ // "errors": { }
1110
+ // }
1111
+ //
1112
+ return this.parseOrder (response);
1113
+ }
1114
+
1115
+ async cancelAllOrders (symbol = undefined, params = {}) {
1116
+ await this.loadMarkets ();
1117
+ const request = {
1118
+ // 'currency': market['baseId'],
1119
+ // 'quote': market['quoteId'],
1120
+ };
1121
+ let method = 'privatePostAuthOrderCancelAll';
1122
+ let market = undefined;
1123
+ if (symbol !== undefined) {
1124
+ market = this.market (symbol);
1125
+ request['currency'] = market['baseId'];
1126
+ request['quote'] = market['quoteId'];
1127
+ method = 'privatePostAuthOrderCancelAllCurrencyQuote';
1128
+ }
1129
+ const response = await this[method] (this.extend (request, params));
1130
+ //
1131
+ // {
1132
+ // "message":"cancellation request successfully submitted",
1133
+ // "status":"SUCCESS"
1134
+ // }
1135
+ //
1136
+ return response;
1137
+ }
1138
+
1139
+ async fetchTransactions (code = undefined, since = undefined, limit = undefined, params = {}) {
1140
+ await this.loadMarkets ();
1141
+ const request = {
1142
+ // 'page': '1',
1143
+ // 'size': 100,
1144
+ };
1145
+ const response = await this.privateGetAuthTransaction (this.extend (request, params));
1146
+ //
1147
+ // {
1148
+ // "hasNext":false,
1149
+ // "content":[
1150
+ // {
1151
+ // "id":"fbf7d0d1-2629-4ad8-9def-7a1dba423362",
1152
+ // "status":"TRANSACTION_STATUS_CONFIRMED",
1153
+ // "type":"TRANSACTION_TYPE_DEPOSIT",
1154
+ // "senderAddress":"",
1155
+ // "recipientAddress":"0x3c46fa2e3f9023bc4897828ed173f8ecb3a554bc",
1156
+ // "amount":"200.000000000000000000",
1157
+ // "transactionFee":"0.000000000000000000",
1158
+ // "timestamp":1635893208404,
1159
+ // "transactionHash":"0x28bad3b74a042df13d64ddfbca855566a51bf7f190b8cd565c236a18d5cd493f#42",
1160
+ // "blockHeight":13540262,
1161
+ // "currency":"0c3a106d-bde3-4c13-a26e-3fd2394529e5",
1162
+ // "memo":null,
1163
+ // "paymentProvider":"a8d6d1cb-f84a-4e9d-aa82-c6a08b356ee1",
1164
+ // "requiresCode":false
1165
+ // }
1166
+ // ],
1167
+ // "first":true,
1168
+ // "hasContent":true,
1169
+ // "pageSize":10
1170
+ // }
1171
+ //
1172
+ let currency = undefined;
1173
+ if (code !== undefined) {
1174
+ currency = this.currency (code);
1175
+ }
1176
+ const content = this.safeValue (response, 'content', []);
1177
+ return this.parseTransactions (content, currency, since, limit);
1178
+ }
1179
+
1180
+ parseTransaction (transaction, currency = undefined) {
1181
+ //
1182
+ // {
1183
+ // "id":"fbf7d0d1-2629-4ad8-9def-7a1dba423362",
1184
+ // "status":"TRANSACTION_STATUS_CONFIRMED",
1185
+ // "type":"TRANSACTION_TYPE_DEPOSIT",
1186
+ // "senderAddress":"",
1187
+ // "recipientAddress":"0x3c46fa2e3f9023bc4897828ed173f8ecb3a554bc",
1188
+ // "amount":"200.000000000000000000",
1189
+ // "transactionFee":"0.000000000000000000",
1190
+ // "timestamp":1635893208404,
1191
+ // "transactionHash":"0x28bad3b74a042df13d64ddfbca855566a51bf7f190b8cd565c236a18d5cd493f#42",
1192
+ // "blockHeight":13540262,
1193
+ // "currency":"0c3a106d-bde3-4c13-a26e-3fd2394529e5",
1194
+ // "memo":null,
1195
+ // "paymentProvider":"a8d6d1cb-f84a-4e9d-aa82-c6a08b356ee1",
1196
+ // "requiresCode":false
1197
+ // }
1198
+ //
1199
+ const id = this.safeString (transaction, 'id');
1200
+ const timestamp = this.safeInteger (transaction, 'timestamp');
1201
+ const currencyId = this.safeString (transaction, 'currency');
1202
+ const code = this.safeCurrencyCode (currencyId, currency);
1203
+ const status = this.parseTransactionStatus (this.safeString (transaction, 'status'));
1204
+ const amount = this.safeNumber (transaction, 'amount');
1205
+ let addressFrom = this.safeString (transaction, 'senderAddress');
1206
+ if (addressFrom === '') {
1207
+ addressFrom = undefined;
1208
+ }
1209
+ let addressTo = this.safeString (transaction, 'recipientAddress');
1210
+ if (addressTo === '') {
1211
+ addressTo = undefined;
1212
+ }
1213
+ const txid = this.safeString (transaction, 'transactionHash');
1214
+ const tagTo = this.safeString (transaction, 'memo');
1215
+ let fee = undefined;
1216
+ const feeCost = this.safeNumber (transaction, 'transactionFee');
1217
+ if (feeCost !== undefined) {
1218
+ fee = {
1219
+ 'cost': feeCost,
1220
+ 'currency': code,
1221
+ };
1222
+ }
1223
+ const type = this.parseTransactionType (this.safeString (transaction, 'type'));
1224
+ return {
1225
+ 'info': transaction,
1226
+ 'id': id,
1227
+ 'txid': txid,
1228
+ 'timestamp': timestamp,
1229
+ 'datetime': this.iso8601 (timestamp),
1230
+ 'network': undefined,
1231
+ 'addressFrom': addressFrom,
1232
+ 'addressTo': addressTo,
1233
+ 'address': addressTo,
1234
+ 'tagFrom': undefined,
1235
+ 'tagTo': tagTo,
1236
+ 'tag': tagTo,
1237
+ 'type': type,
1238
+ 'amount': amount,
1239
+ 'currency': code,
1240
+ 'status': status,
1241
+ 'updated': undefined,
1242
+ 'fee': fee,
1243
+ };
1244
+ }
1245
+
1246
+ parseTransactionStatus (status) {
1247
+ const statuses = {
1248
+ 'TRANSACTION_STATUS_CONFIRMED': 'ok',
1249
+ 'TRANSACTION_STATUS_EXECUTED': 'ok',
1250
+ };
1251
+ return this.safeString (statuses, status, status);
1252
+ }
1253
+
1254
+ parseTransactionType (type) {
1255
+ const types = {
1256
+ 'TRANSACTION_TYPE_DEPOSIT': 'deposit',
1257
+ 'TRANSACTION_TYPE_WITHDRAWAL': 'withdrawal',
1258
+ };
1259
+ return this.safeString (types, type, type);
1260
+ }
1261
+
1262
+ async fetchTransfers (code = undefined, since = undefined, limit = undefined, params = {}) {
1263
+ await this.loadMarkets ();
1264
+ const currency = this.currency (code);
1265
+ const response = await this.privateGetAuthTransfer (params);
1266
+ //
1267
+ // {
1268
+ // "hasNext": true,
1269
+ // "content": [
1270
+ // {
1271
+ // "id": "ebd6312f-cb4f-45d1-9409-4b0b3027f21e",
1272
+ // "status": "TRANSFER_STATUS_COMPLETED",
1273
+ // "type": "TRANSFER_TYPE_WITHDRAW_SPOT",
1274
+ // "fromAccount": "c429c551-adbb-4078-b74b-276bea308a36",
1275
+ // "toAccount": "631c6203-bd62-4734-a04d-9b2a951f43b9",
1276
+ // "transferringFunds": 1259.0321785,
1277
+ // "usdValue": 1259.032179,
1278
+ // "rejectReason": null,
1279
+ // "timestamp": 1633515579530,
1280
+ // "direction": "INTERNAL",
1281
+ // "method": "TRANSFER_METHOD_UNKNOWN",
1282
+ // "recipient": null,
1283
+ // "sender": null,
1284
+ // "currency": "0c3a106d-bde3-4c13-a26e-3fd2394529e5",
1285
+ // "codeRequired": false,
1286
+ // "fromUser": "ce555f3f-585d-46fb-9ae6-487f66738073",
1287
+ // "toUser": "ce555f3f-585d-46fb-9ae6-487f66738073",
1288
+ // "fee": 0
1289
+ // },
1290
+ // ...
1291
+ // ],
1292
+ // "first": true,
1293
+ // "pageSize": 20,
1294
+ // "hasContent": true
1295
+ // }
1296
+ //
1297
+ const transfers = this.safeValue (response, 'content', []);
1298
+ return this.parseTransfers (transfers, currency, since, limit);
1299
+ }
1300
+
1301
+ async transfer (code, amount, fromAccount, toAccount, params = {}) {
1302
+ await this.loadMarkets ();
1303
+ const currency = this.currency (code);
1304
+ let method = undefined;
1305
+ if (toAccount.includes ('@')) {
1306
+ method = 'privatePostAuthTransferEmail';
1307
+ } else if (toAccount.length === 36) {
1308
+ method = 'privatePostAuthTransferId';
1309
+ } else {
1310
+ method = 'privatePostAuthTransferPhone';
1311
+ }
1312
+ const request = {
1313
+ 'currency': currency['id'],
1314
+ 'recipient': toAccount,
1315
+ 'value': this.currencyToPrecision (code, amount),
1316
+ };
1317
+ const response = await this[method] (this.extend (request, params));
1318
+ //
1319
+ // {
1320
+ // "id": "e6fc4ace-7750-44e4-b7e9-6af038ac7107",
1321
+ // "status": "TRANSFER_STATUS_COMPLETED",
1322
+ // "type": "TRANSFER_TYPE_DEPOSIT_SPOT",
1323
+ // "fromAccount": "3bf61015-bf32-47a6-b237-c9f70df772ad",
1324
+ // "toAccount": "355eb279-7c7e-4515-814a-575a49dc0325",
1325
+ // "transferringFunds": "500000.000000000000000000",
1326
+ // "usdValue": "0.000000000000000000",
1327
+ // "rejectReason": "",
1328
+ // "timestamp": 1576844438402,
1329
+ // "direction": "INTERNAL",
1330
+ // "method": "TRANSFER_METHOD_UNKNOWN",
1331
+ // "recipient": "",
1332
+ // "sender": "",
1333
+ // "currency": "40af7879-a8cc-4576-a42d-7d2749821b58",
1334
+ // "codeRequired": false,
1335
+ // "fromUser": "cd555555-666d-46fb-9ae6-487f66738073",
1336
+ // "toUser": "cd555555-666d-46fb-9ae6-487f66738073",
1337
+ // "fee": 0
1338
+ // }
1339
+ //
1340
+ return this.parseTransfer (response);
1341
+ }
1342
+
1343
+ parseTransfer (transfer, currency = undefined) {
1344
+ //
1345
+ // {
1346
+ // "id": "e6fc4ace-7750-44e4-b7e9-6af038ac7107",
1347
+ // "status": "TRANSFER_STATUS_COMPLETED",
1348
+ // "type": "TRANSFER_TYPE_DEPOSIT_SPOT",
1349
+ // "fromAccount": "3bf61015-bf32-47a6-b237-c9f70df772ad",
1350
+ // "toAccount": "355eb279-7c7e-4515-814a-575a49dc0325",
1351
+ // "transferringFunds": "500000.000000000000000000",
1352
+ // "usdValue": "0.000000000000000000",
1353
+ // "rejectReason": "",
1354
+ // "timestamp": 1576844438402,
1355
+ // "direction": "INTERNAL",
1356
+ // "method": "TRANSFER_METHOD_UNKNOWN",
1357
+ // "recipient": "",
1358
+ // "sender": "",
1359
+ // "currency": "40af7879-a8cc-4576-a42d-7d2749821b58",
1360
+ // "codeRequired": false,
1361
+ // "fromUser": "cd555555-666d-46fb-9ae6-487f66738073",
1362
+ // "toUser": "cd555555-666d-46fb-9ae6-487f66738073",
1363
+ // "fee": 0
1364
+ // }
1365
+ //
1366
+ const timestamp = this.safeTimestamp (transfer, 'timestamp');
1367
+ const currencyId = this.safeString (transfer, 'currency');
1368
+ const status = this.safeString (transfer, 'status');
1369
+ return {
1370
+ 'info': transfer,
1371
+ 'id': this.safeString (transfer, 'id'),
1372
+ 'timestamp': this.safeNumber (transfer),
1373
+ 'datetime': this.iso8601 (timestamp),
1374
+ 'currency': this.safeCurrencyCode (currencyId, currency),
1375
+ 'amount': this.safeNumber (transfer, 'transferringFunds'),
1376
+ 'fromAccount': this.safeString (transfer, 'fromAccount'),
1377
+ 'toAccount': this.safeString (transfer, 'toAccount'),
1378
+ 'status': this.parseTransferStatus (status),
1379
+ };
1380
+ }
1381
+
1382
+ parseTransferStatus (status) {
1383
+ const statuses = {
1384
+ 'TRANSFER_STATUS_COMPLETED': 'ok',
1385
+ 'TRANSFER_STATUS_PENDING': 'pending',
1386
+ 'TRANSFER_STATUS_REJECTED': 'failed',
1387
+ 'TRANSFER_STATUS_UNVERIFIED': 'pending',
1388
+ 'TRANSFER_STATUS_CANCELLED': 'canceled',
1389
+ };
1390
+ return this.safeString (statuses, status, status);
1391
+ }
1392
+
1393
+ sign (path, api = 'public', method = 'GET', params = undefined, headers = undefined, body = undefined) {
1394
+ const request = '/' + this.version + '/' + this.implodeParams (path, params);
1395
+ let requestString = request;
1396
+ const query = this.omit (params, this.extractParams (path));
1397
+ const urlencodedQuery = this.urlencode (query);
1398
+ if (method === 'GET') {
1399
+ if (Object.keys (query).length) {
1400
+ requestString += '?' + urlencodedQuery;
1401
+ }
1402
+ }
1403
+ if (api === 'private') {
1404
+ this.checkRequiredCredentials ();
1405
+ const auth = method + request + urlencodedQuery;
1406
+ const signature = this.hmac (this.encode (auth), this.encode (this.secret), 'sha512');
1407
+ headers = {
1408
+ 'X-LA-APIKEY': this.apiKey,
1409
+ 'X-LA-SIGNATURE': signature,
1410
+ 'X-LA-DIGEST': 'HMAC-SHA512', // HMAC-SHA384, HMAC-SHA512, optional
1411
+ };
1412
+ if (method === 'POST') {
1413
+ headers['Content-Type'] = 'application/json';
1414
+ body = this.json (query);
1415
+ }
1416
+ }
1417
+ const url = this.urls['api'] + requestString;
1418
+ return { 'url': url, 'method': method, 'body': body, 'headers': headers };
1419
+ }
1420
+
1421
+ handleErrors (code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
1422
+ if (!response) {
1423
+ return;
1424
+ }
1425
+ //
1426
+ // {"result":false,"message":"invalid API key, signature or digest","error":"BAD_REQUEST","status":"FAILURE"}
1427
+ // {"result":false,"message":"request expired or bad <timeAlive>/<timestamp> format","error":"BAD_REQUEST","status":"FAILURE"}
1428
+ // {"message":"Internal Server Error","error":"INTERNAL_ERROR","status":"FAILURE"}
1429
+ // {"result":false,"message":"Internal error","error":"For input string: \"NaN\"","status":"FAILURE"}
1430
+ //
1431
+ const message = this.safeString (response, 'message');
1432
+ const feedback = this.id + ' ' + body;
1433
+ if (message !== undefined) {
1434
+ this.throwExactlyMatchedException (this.exceptions['exact'], message, feedback);
1435
+ this.throwBroadlyMatchedException (this.exceptions['broad'], message, feedback);
1436
+ }
1437
+ const error = this.safeString (response, 'error');
1438
+ const errorMessage = this.safeString (error, 'message');
1439
+ if ((error !== undefined) || (errorMessage !== undefined)) {
1440
+ this.throwExactlyMatchedException (this.exceptions['exact'], error, feedback);
1441
+ this.throwBroadlyMatchedException (this.exceptions['broad'], body, feedback);
1442
+ throw new ExchangeError (feedback); // unknown message
1443
+ }
1444
+ }
1445
+ };