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/poloniex.js ADDED
@@ -0,0 +1,1674 @@
1
+ 'use strict';
2
+
3
+ // ---------------------------------------------------------------------------
4
+
5
+ const Exchange = require ('./base/Exchange');
6
+ const { ExchangeError, ExchangeNotAvailable, RequestTimeout, AuthenticationError, PermissionDenied, RateLimitExceeded, InsufficientFunds, OrderNotFound, InvalidOrder, AccountSuspended, CancelPending, InvalidNonce, OnMaintenance, BadSymbol } = require ('./base/errors');
7
+ const Precise = require ('./base/Precise');
8
+
9
+ // ---------------------------------------------------------------------------
10
+
11
+ module.exports = class poloniex extends Exchange {
12
+ describe () {
13
+ return this.deepExtend (super.describe (), {
14
+ 'id': 'poloniex',
15
+ 'name': 'Poloniex',
16
+ 'countries': [ 'US' ],
17
+ 'rateLimit': 166.667, // 6 calls per second, 1000ms / 6 = 166.667ms between requests
18
+ 'certified': false,
19
+ 'pro': true,
20
+ 'has': {
21
+ 'CORS': undefined,
22
+ 'spot': true,
23
+ 'margin': undefined, // has but not fully implemented
24
+ 'swap': undefined, // has but not fully implemented
25
+ 'future': undefined, // has but not fully implemented
26
+ 'option': undefined,
27
+ 'cancelAllOrders': true,
28
+ 'cancelOrder': true,
29
+ 'createDepositAddress': true,
30
+ 'createMarketOrder': undefined,
31
+ 'createOrder': true,
32
+ 'editOrder': true,
33
+ 'fetchBalance': true,
34
+ 'fetchClosedOrder': 'emulated',
35
+ 'fetchCurrencies': true,
36
+ 'fetchDepositAddress': true,
37
+ 'fetchDeposits': true,
38
+ 'fetchMarkets': true,
39
+ 'fetchMyTrades': true,
40
+ 'fetchOHLCV': true,
41
+ 'fetchOpenOrder': true, // true endpoint for a single open order
42
+ 'fetchOpenOrders': true, // true endpoint for open orders
43
+ 'fetchOrderBook': true,
44
+ 'fetchOrderBooks': true,
45
+ 'fetchOrderTrades': true, // true endpoint for trades of a single open or closed order
46
+ 'fetchPosition': true,
47
+ 'fetchTicker': true,
48
+ 'fetchTickers': true,
49
+ 'fetchTrades': true,
50
+ 'fetchTradingFee': false,
51
+ 'fetchTradingFees': true,
52
+ 'fetchTransactions': true,
53
+ 'fetchTransfer': false,
54
+ 'fetchTransfers': false,
55
+ 'fetchWithdrawals': true,
56
+ 'transfer': true,
57
+ 'withdraw': true,
58
+ },
59
+ 'timeframes': {
60
+ '5m': 300,
61
+ '15m': 900,
62
+ '30m': 1800,
63
+ '2h': 7200,
64
+ '4h': 14400,
65
+ '1d': 86400,
66
+ },
67
+ 'urls': {
68
+ 'logo': 'https://user-images.githubusercontent.com/1294454/27766817-e9456312-5ee6-11e7-9b3c-b628ca5626a5.jpg',
69
+ 'api': {
70
+ 'public': 'https://poloniex.com/public',
71
+ 'private': 'https://poloniex.com/tradingApi',
72
+ },
73
+ 'www': 'https://www.poloniex.com',
74
+ 'doc': 'https://docs.poloniex.com',
75
+ 'fees': 'https://poloniex.com/fees',
76
+ 'referral': 'https://poloniex.com/signup?c=UBFZJRPJ',
77
+ },
78
+ 'api': {
79
+ 'public': {
80
+ 'get': {
81
+ 'return24hVolume': 1,
82
+ 'returnChartData': 1,
83
+ 'returnCurrencies': 1,
84
+ 'returnLoanOrders': 1,
85
+ 'returnOrderBook': 1,
86
+ 'returnTicker': 1,
87
+ 'returnTradeHistory': 1,
88
+ },
89
+ },
90
+ 'private': {
91
+ 'post': {
92
+ 'buy': 1,
93
+ 'cancelLoanOffer': 1,
94
+ 'cancelOrder': 1,
95
+ 'cancelAllOrders': 1,
96
+ 'closeMarginPosition': 1,
97
+ 'createLoanOffer': 1,
98
+ 'generateNewAddress': 1,
99
+ 'getMarginPosition': 1,
100
+ 'marginBuy': 1,
101
+ 'marginSell': 1,
102
+ 'moveOrder': 1,
103
+ 'returnActiveLoans': 1,
104
+ 'returnAvailableAccountBalances': 1,
105
+ 'returnBalances': 1,
106
+ 'returnCompleteBalances': 1,
107
+ 'returnDepositAddresses': 1,
108
+ 'returnDepositsWithdrawals': 1,
109
+ 'returnFeeInfo': 1,
110
+ 'returnLendingHistory': 1,
111
+ 'returnMarginAccountSummary': 1,
112
+ 'returnOpenLoanOffers': 1,
113
+ 'returnOpenOrders': 1,
114
+ 'returnOrderTrades': 1,
115
+ 'returnOrderStatus': 1,
116
+ 'returnTradableBalances': 1,
117
+ 'returnTradeHistory': 1,
118
+ 'sell': 1,
119
+ 'toggleAutoRenew': 1,
120
+ 'transferBalance': 1,
121
+ 'withdraw': 1,
122
+ },
123
+ },
124
+ },
125
+ 'fees': {
126
+ 'trading': {
127
+ 'feeSide': 'get',
128
+ // starting from Jan 8 2020
129
+ 'maker': this.parseNumber ('0.0009'),
130
+ 'taker': this.parseNumber ('0.0009'),
131
+ },
132
+ 'funding': {},
133
+ },
134
+ 'limits': {
135
+ 'amount': {
136
+ 'min': 0.000001,
137
+ 'max': undefined,
138
+ },
139
+ 'price': {
140
+ 'min': 0.00000001,
141
+ 'max': 1000000000,
142
+ },
143
+ 'cost': {
144
+ 'min': 0.00000000,
145
+ 'max': 1000000000,
146
+ },
147
+ },
148
+ 'precision': {
149
+ 'amount': 8,
150
+ 'price': 8,
151
+ },
152
+ 'commonCurrencies': {
153
+ 'AIR': 'AirCoin',
154
+ 'APH': 'AphroditeCoin',
155
+ 'BCC': 'BTCtalkcoin',
156
+ 'BCHABC': 'BCHABC',
157
+ 'BDG': 'Badgercoin',
158
+ 'BTM': 'Bitmark',
159
+ 'CON': 'Coino',
160
+ 'GOLD': 'GoldEagles',
161
+ 'GPUC': 'GPU',
162
+ 'HOT': 'Hotcoin',
163
+ 'ITC': 'Information Coin',
164
+ 'KEY': 'KEYCoin',
165
+ 'MASK': 'NFTX Hashmasks Index', // conflict with Mask Network
166
+ 'MEME': 'Degenerator Meme', // Degenerator Meme migrated to Meme Inu, this exchange still has the old price
167
+ 'PLX': 'ParallaxCoin',
168
+ 'REPV2': 'REP',
169
+ 'STR': 'XLM',
170
+ 'SOC': 'SOCC',
171
+ 'TRADE': 'Unitrade',
172
+ 'XAP': 'API Coin',
173
+ // this is not documented in the API docs for Poloniex
174
+ // https://github.com/ccxt/ccxt/issues/7084
175
+ // when the user calls withdraw ('USDT', amount, address, tag, params)
176
+ // with params = { 'currencyToWithdrawAs': 'USDTTRON' }
177
+ // or params = { 'currencyToWithdrawAs': 'USDTETH' }
178
+ // fetchWithdrawals ('USDT') returns the corresponding withdrawals
179
+ // with a USDTTRON or a USDTETH currency id, respectfully
180
+ // therefore we have map them back to the original code USDT
181
+ // otherwise the returned withdrawals are filtered out
182
+ 'USDTTRON': 'USDT',
183
+ 'USDTETH': 'USDT',
184
+ },
185
+ 'options': {
186
+ 'networks': {
187
+ 'ERC20': 'ETH',
188
+ 'TRX': 'TRON',
189
+ 'TRC20': 'TRON',
190
+ },
191
+ 'limits': {
192
+ 'cost': {
193
+ 'min': {
194
+ 'BTC': 0.0001,
195
+ 'ETH': 0.0001,
196
+ 'USDT': 1.0,
197
+ 'TRX': 100,
198
+ 'BNB': 0.06,
199
+ 'USDC': 1.0,
200
+ 'USDJ': 1.0,
201
+ 'TUSD': 0.0001,
202
+ 'DAI': 1.0,
203
+ 'PAX': 1.0,
204
+ 'BUSD': 1.0,
205
+ },
206
+ },
207
+ },
208
+ 'accountsByType': {
209
+ 'spot': 'exchange',
210
+ 'margin': 'margin',
211
+ 'future': 'futures',
212
+ 'lending': 'lending',
213
+ },
214
+ 'accountsById': {
215
+ 'exchange': 'spot',
216
+ 'margin': 'margin',
217
+ 'futures': 'future',
218
+ 'lending': 'lending',
219
+ },
220
+ },
221
+ 'exceptions': {
222
+ 'exact': {
223
+ 'You may only place orders that reduce your position.': InvalidOrder,
224
+ 'Invalid order number, or you are not the person who placed the order.': OrderNotFound,
225
+ 'Permission denied': PermissionDenied,
226
+ 'Permission denied.': PermissionDenied,
227
+ 'Connection timed out. Please try again.': RequestTimeout,
228
+ 'Internal error. Please try again.': ExchangeNotAvailable,
229
+ 'Currently in maintenance mode.': OnMaintenance,
230
+ 'Order not found, or you are not the person who placed it.': OrderNotFound,
231
+ 'Invalid API key/secret pair.': AuthenticationError,
232
+ 'Please do not make more than 8 API calls per second.': RateLimitExceeded,
233
+ 'This IP has been temporarily throttled. Please ensure your requests are valid and try again in one minute.': RateLimitExceeded,
234
+ 'Rate must be greater than zero.': InvalidOrder, // {"error":"Rate must be greater than zero."}
235
+ 'Invalid currency pair.': BadSymbol, // {"error":"Invalid currency pair."}
236
+ 'Invalid currencyPair parameter.': BadSymbol, // {"error":"Invalid currencyPair parameter."}
237
+ 'Trading is disabled in this market.': BadSymbol, // {"error":"Trading is disabled in this market."}
238
+ 'Invalid orderNumber parameter.': OrderNotFound,
239
+ 'Order is beyond acceptable bounds.': InvalidOrder, // {"error":"Order is beyond acceptable bounds.","fee":"0.00155000","currencyPair":"USDT_BOBA"}
240
+ 'This account is closed.': AccountSuspended, // {"error":"This account is closed."}
241
+ },
242
+ 'broad': {
243
+ 'Total must be at least': InvalidOrder, // {"error":"Total must be at least 0.0001."}
244
+ 'This account is frozen': AccountSuspended, // {"error":"This account is frozen for trading."} || {"error":"This account is frozen."}
245
+ 'This account is locked.': AccountSuspended, // {"error":"This account is locked."}
246
+ 'Not enough': InsufficientFunds,
247
+ 'Nonce must be greater': InvalidNonce,
248
+ 'You have already called cancelOrder or moveOrder on this order.': CancelPending,
249
+ 'Amount must be at least': InvalidOrder, // {"error":"Amount must be at least 0.000001."}
250
+ 'is either completed or does not exist': OrderNotFound, // {"error":"Order 587957810791 is either completed or does not exist."}
251
+ 'Error pulling ': ExchangeError, // {"error":"Error pulling order book"}
252
+ },
253
+ },
254
+ });
255
+ }
256
+
257
+ parseOHLCV (ohlcv, market = undefined) {
258
+ //
259
+ // {
260
+ // "date":1590913773,
261
+ // "high":0.02491611,
262
+ // "low":0.02491611,
263
+ // "open":0.02491611,
264
+ // "close":0.02491611,
265
+ // "volume":0,
266
+ // "quoteVolume":0,
267
+ // "weightedAverage":0.02491611
268
+ // }
269
+ //
270
+ return [
271
+ this.safeTimestamp (ohlcv, 'date'),
272
+ this.safeNumber (ohlcv, 'open'),
273
+ this.safeNumber (ohlcv, 'high'),
274
+ this.safeNumber (ohlcv, 'low'),
275
+ this.safeNumber (ohlcv, 'close'),
276
+ this.safeNumber (ohlcv, 'quoteVolume'),
277
+ ];
278
+ }
279
+
280
+ async fetchOHLCV (symbol, timeframe = '5m', since = undefined, limit = undefined, params = {}) {
281
+ await this.loadMarkets ();
282
+ const market = this.market (symbol);
283
+ const request = {
284
+ 'currencyPair': market['id'],
285
+ 'period': this.timeframes[timeframe],
286
+ };
287
+ if (since === undefined) {
288
+ request['end'] = this.seconds ();
289
+ if (limit === undefined) {
290
+ request['start'] = request['end'] - this.parseTimeframe ('1w'); // max range = 1 week
291
+ } else {
292
+ request['start'] = request['end'] - limit * this.parseTimeframe (timeframe);
293
+ }
294
+ } else {
295
+ request['start'] = parseInt (since / 1000);
296
+ if (limit !== undefined) {
297
+ const end = this.sum (request['start'], limit * this.parseTimeframe (timeframe));
298
+ request['end'] = end;
299
+ }
300
+ }
301
+ const response = await this.publicGetReturnChartData (this.extend (request, params));
302
+ //
303
+ // [
304
+ // {"date":1590913773,"high":0.02491611,"low":0.02491611,"open":0.02491611,"close":0.02491611,"volume":0,"quoteVolume":0,"weightedAverage":0.02491611},
305
+ // {"date":1590913800,"high":0.02495324,"low":0.02489501,"open":0.02491797,"close":0.02493693,"volume":0.0927415,"quoteVolume":3.7227869,"weightedAverage":0.02491185},
306
+ // {"date":1590914100,"high":0.02498596,"low":0.02488503,"open":0.02493033,"close":0.02497896,"volume":0.21196348,"quoteVolume":8.50291888,"weightedAverage":0.02492832},
307
+ // ]
308
+ //
309
+ return this.parseOHLCVs (response, market, timeframe, since, limit);
310
+ }
311
+
312
+ async loadMarkets (reload = false, params = {}) {
313
+ const markets = await super.loadMarkets (reload, params);
314
+ const currenciesByNumericId = this.safeValue (this.options, 'currenciesByNumericId');
315
+ if ((currenciesByNumericId === undefined) || reload) {
316
+ this.options['currenciesByNumericId'] = this.indexBy (this.currencies, 'numericId');
317
+ }
318
+ return markets;
319
+ }
320
+
321
+ async fetchMarkets (params = {}) {
322
+ const markets = await this.publicGetReturnTicker (params);
323
+ const keys = Object.keys (markets);
324
+ const result = [];
325
+ for (let i = 0; i < keys.length; i++) {
326
+ const id = keys[i];
327
+ const market = markets[id];
328
+ const [ quoteId, baseId ] = id.split ('_');
329
+ const base = this.safeCurrencyCode (baseId);
330
+ const quote = this.safeCurrencyCode (quoteId);
331
+ const isFrozen = this.safeString (market, 'isFrozen');
332
+ const marginEnabled = this.safeInteger (market, 'marginTradingEnabled');
333
+ // these are known defaults
334
+ result.push ({
335
+ 'id': id,
336
+ 'numericId': this.safeInteger (market, 'id'),
337
+ 'symbol': base + '/' + quote,
338
+ 'base': base,
339
+ 'quote': quote,
340
+ 'settle': undefined,
341
+ 'baseId': baseId,
342
+ 'quoteId': quoteId,
343
+ 'settleId': undefined,
344
+ 'type': 'spot',
345
+ 'spot': true,
346
+ 'margin': (marginEnabled === 1),
347
+ 'swap': false,
348
+ 'future': false,
349
+ 'option': false,
350
+ 'active': (isFrozen !== '1'),
351
+ 'contract': false,
352
+ 'linear': undefined,
353
+ 'inverse': undefined,
354
+ 'contractSize': undefined,
355
+ 'expiry': undefined,
356
+ 'expiryDatetime': undefined,
357
+ 'strike': undefined,
358
+ 'optionType': undefined,
359
+ 'precision': {
360
+ 'amount': parseInt ('8'),
361
+ 'price': parseInt ('8'),
362
+ },
363
+ 'limits': this.extend (this.limits, {
364
+ 'leverage': {
365
+ 'min': undefined,
366
+ 'max': undefined,
367
+ },
368
+ 'cost': {
369
+ 'min': this.safeValue (this.options['limits']['cost']['min'], quote),
370
+ 'max': undefined,
371
+ },
372
+ }),
373
+ 'info': market,
374
+ });
375
+ }
376
+ return result;
377
+ }
378
+
379
+ parseBalance (response) {
380
+ const result = {
381
+ 'info': response,
382
+ 'timestamp': undefined,
383
+ 'datetime': undefined,
384
+ };
385
+ const currencyIds = Object.keys (response);
386
+ for (let i = 0; i < currencyIds.length; i++) {
387
+ const currencyId = currencyIds[i];
388
+ const balance = this.safeValue (response, currencyId, {});
389
+ const code = this.safeCurrencyCode (currencyId);
390
+ const account = this.account ();
391
+ account['free'] = this.safeString (balance, 'available');
392
+ account['used'] = this.safeString (balance, 'onOrders');
393
+ result[code] = account;
394
+ }
395
+ return this.safeBalance (result);
396
+ }
397
+
398
+ async fetchBalance (params = {}) {
399
+ await this.loadMarkets ();
400
+ const request = {
401
+ 'account': 'all',
402
+ };
403
+ const response = await this.privatePostReturnCompleteBalances (this.extend (request, params));
404
+ //
405
+ // {
406
+ // "1CR":{"available":"0.00000000","onOrders":"0.00000000","btcValue":"0.00000000"},
407
+ // "ABY":{"available":"0.00000000","onOrders":"0.00000000","btcValue":"0.00000000"},
408
+ // "AC":{"available":"0.00000000","onOrders":"0.00000000","btcValue":"0.00000000"},
409
+ // }
410
+ //
411
+ return this.parseBalance (response);
412
+ }
413
+
414
+ async fetchTradingFees (params = {}) {
415
+ await this.loadMarkets ();
416
+ const response = await this.privatePostReturnFeeInfo (params);
417
+ //
418
+ // {
419
+ // makerFee: '0.00100000',
420
+ // takerFee: '0.00200000',
421
+ // marginMakerFee: '0.00100000',
422
+ // marginTakerFee: '0.00200000',
423
+ // thirtyDayVolume: '106.08463302',
424
+ // nextTier: 500000,
425
+ // }
426
+ //
427
+ const result = {};
428
+ for (let i = 0; i < this.symbols.length; i++) {
429
+ const symbol = this.symbols[i];
430
+ result[symbol] = {
431
+ 'info': response,
432
+ 'symbol': symbol,
433
+ 'maker': this.safeNumber (response, 'makerFee'),
434
+ 'taker': this.safeNumber (response, 'takerFee'),
435
+ 'percentage': true,
436
+ 'tierBased': true,
437
+ };
438
+ }
439
+ return result;
440
+ }
441
+
442
+ async fetchOrderBook (symbol, limit = undefined, params = {}) {
443
+ await this.loadMarkets ();
444
+ const request = {
445
+ 'currencyPair': this.marketId (symbol),
446
+ };
447
+ if (limit !== undefined) {
448
+ request['depth'] = limit; // 100
449
+ }
450
+ const response = await this.publicGetReturnOrderBook (this.extend (request, params));
451
+ const orderbook = this.parseOrderBook (response, symbol);
452
+ orderbook['nonce'] = this.safeInteger (response, 'seq');
453
+ return orderbook;
454
+ }
455
+
456
+ async fetchOrderBooks (symbols = undefined, limit = undefined, params = {}) {
457
+ await this.loadMarkets ();
458
+ const request = {
459
+ 'currencyPair': 'all',
460
+ };
461
+ if (limit !== undefined) {
462
+ request['depth'] = limit; // 100
463
+ }
464
+ const response = await this.publicGetReturnOrderBook (this.extend (request, params));
465
+ const marketIds = Object.keys (response);
466
+ const result = {};
467
+ for (let i = 0; i < marketIds.length; i++) {
468
+ const marketId = marketIds[i];
469
+ let symbol = undefined;
470
+ if (marketId in this.markets_by_id) {
471
+ symbol = this.markets_by_id[marketId]['symbol'];
472
+ } else {
473
+ const [ quoteId, baseId ] = marketId.split ('_');
474
+ const base = this.safeCurrencyCode (baseId);
475
+ const quote = this.safeCurrencyCode (quoteId);
476
+ symbol = base + '/' + quote;
477
+ }
478
+ const orderbook = this.parseOrderBook (response[marketId], symbol);
479
+ orderbook['nonce'] = this.safeInteger (response[marketId], 'seq');
480
+ result[symbol] = orderbook;
481
+ }
482
+ return result;
483
+ }
484
+
485
+ parseTicker (ticker, market = undefined) {
486
+ // {
487
+ // id: '121',
488
+ // last: '43196.31469670',
489
+ // lowestAsk: '43209.61843169',
490
+ // highestBid: '43162.41965234',
491
+ // percentChange: '0.00963340',
492
+ // baseVolume: '13444643.33799658',
493
+ // quoteVolume: '315.84780115',
494
+ // isFrozen: '0',
495
+ // postOnly: '0',
496
+ // marginTradingEnabled: '1',
497
+ // high24hr: '43451.84481934',
498
+ // low24hr: '41749.89529736'
499
+ // }
500
+ const timestamp = this.milliseconds ();
501
+ const symbol = this.safeSymbol (undefined, market);
502
+ const last = this.safeString (ticker, 'last');
503
+ const relativeChange = this.safeString (ticker, 'percentChange');
504
+ const percentage = Precise.stringMul (relativeChange, '100');
505
+ return this.safeTicker ({
506
+ 'symbol': symbol,
507
+ 'timestamp': timestamp,
508
+ 'datetime': this.iso8601 (timestamp),
509
+ 'high': this.safeString (ticker, 'high24hr'),
510
+ 'low': this.safeString (ticker, 'low24hr'),
511
+ 'bid': this.safeString (ticker, 'highestBid'),
512
+ 'bidVolume': undefined,
513
+ 'ask': this.safeString (ticker, 'lowestAsk'),
514
+ 'askVolume': undefined,
515
+ 'vwap': undefined,
516
+ 'open': undefined,
517
+ 'close': last,
518
+ 'last': last,
519
+ 'previousClose': undefined,
520
+ 'change': undefined,
521
+ 'percentage': percentage,
522
+ 'average': undefined,
523
+ 'baseVolume': this.safeString (ticker, 'quoteVolume'),
524
+ 'quoteVolume': this.safeString (ticker, 'baseVolume'),
525
+ 'info': ticker,
526
+ }, market, false);
527
+ }
528
+
529
+ async fetchTickers (symbols = undefined, params = {}) {
530
+ await this.loadMarkets ();
531
+ const response = await this.publicGetReturnTicker (params);
532
+ const ids = Object.keys (response);
533
+ const result = {};
534
+ for (let i = 0; i < ids.length; i++) {
535
+ const id = ids[i];
536
+ let symbol = undefined;
537
+ let market = undefined;
538
+ if (id in this.markets_by_id) {
539
+ market = this.markets_by_id[id];
540
+ symbol = market['symbol'];
541
+ } else {
542
+ const [ quoteId, baseId ] = id.split ('_');
543
+ const base = this.safeCurrencyCode (baseId);
544
+ const quote = this.safeCurrencyCode (quoteId);
545
+ symbol = base + '/' + quote;
546
+ market = { 'symbol': symbol };
547
+ }
548
+ const ticker = response[id];
549
+ result[symbol] = this.parseTicker (ticker, market);
550
+ }
551
+ return this.filterByArray (result, 'symbol', symbols);
552
+ }
553
+
554
+ async fetchCurrencies (params = {}) {
555
+ const response = await this.publicGetReturnCurrencies (params);
556
+ //
557
+ // {
558
+ // "id": "293",
559
+ // "name": "0x",
560
+ // "humanType": "Sweep to Main Account",
561
+ // "currencyType": "address",
562
+ // "txFee": "17.21877546",
563
+ // "minConf": "12",
564
+ // "depositAddress": null,
565
+ // "disabled": "0",
566
+ // "frozen": "0",
567
+ // "hexColor": "003831",
568
+ // "blockchain": "ETH",
569
+ // "delisted": "0",
570
+ // "isGeofenced": 0
571
+ // }
572
+ //
573
+ const ids = Object.keys (response);
574
+ const result = {};
575
+ for (let i = 0; i < ids.length; i++) {
576
+ const id = ids[i];
577
+ const currency = response[id];
578
+ const precision = 8; // default precision, todo: fix "magic constants"
579
+ const amountLimit = '1e-8';
580
+ const code = this.safeCurrencyCode (id);
581
+ const delisted = this.safeInteger (currency, 'delisted', 0);
582
+ const disabled = this.safeInteger (currency, 'disabled', 0);
583
+ const listed = !delisted;
584
+ const enabled = !disabled;
585
+ const active = enabled && listed;
586
+ const numericId = this.safeInteger (currency, 'id');
587
+ const fee = this.safeNumber (currency, 'txFee');
588
+ result[code] = {
589
+ 'id': id,
590
+ 'numericId': numericId,
591
+ 'code': code,
592
+ 'info': currency,
593
+ 'name': currency['name'],
594
+ 'active': active,
595
+ 'deposit': undefined,
596
+ 'withdraw': undefined,
597
+ 'fee': fee,
598
+ 'precision': precision,
599
+ 'limits': {
600
+ 'amount': {
601
+ 'min': this.parseNumber (amountLimit),
602
+ 'max': undefined,
603
+ },
604
+ 'withdraw': {
605
+ 'min': fee,
606
+ 'max': undefined,
607
+ },
608
+ },
609
+ };
610
+ }
611
+ return result;
612
+ }
613
+
614
+ async fetchTicker (symbol, params = {}) {
615
+ await this.loadMarkets ();
616
+ const market = this.market (symbol);
617
+ const response = await this.publicGetReturnTicker (params);
618
+ // {
619
+ // "BTC_BTS":{
620
+ // "id":14,
621
+ // "last":"0.00000073",
622
+ // "lowestAsk":"0.00000075",
623
+ // "highestBid":"0.00000073",
624
+ // "percentChange":"0.01388888",
625
+ // "baseVolume":"0.01413528",
626
+ // "quoteVolume":"19431.16872167",
627
+ // "isFrozen":"0",
628
+ // "postOnly":"0",
629
+ // "marginTradingEnabled":"0",
630
+ // "high24hr":"0.00000074",
631
+ // "low24hr":"0.00000071"
632
+ // },
633
+ // ...
634
+ // }
635
+ const ticker = response[market['id']];
636
+ return this.parseTicker (ticker, market);
637
+ }
638
+
639
+ parseTrade (trade, market = undefined) {
640
+ //
641
+ // fetchTrades
642
+ //
643
+ // {
644
+ // globalTradeID: "667563407",
645
+ // tradeID: "1984256",
646
+ // date: "2022-03-01 20:06:06",
647
+ // type: "buy",
648
+ // rate: "0.13361871",
649
+ // amount: "28.40841257",
650
+ // total: "3.79589544",
651
+ // orderNumber: "159992152911"
652
+ // }
653
+ //
654
+ // fetchMyTrades
655
+ //
656
+ // {
657
+ // globalTradeID: 471030550,
658
+ // tradeID: '42582',
659
+ // date: '2020-06-16 09:47:50',
660
+ // rate: '0.000079980000',
661
+ // amount: '75215.00000000',
662
+ // total: '6.01569570',
663
+ // fee: '0.00095000',
664
+ // feeDisplay: '0.26636100 TRX (0.07125%)',
665
+ // orderNumber: '5963454848',
666
+ // type: 'sell',
667
+ // category: 'exchange'
668
+ // }
669
+ //
670
+ // createOrder (taker trades)
671
+ //
672
+ // {
673
+ // 'amount': '200.00000000',
674
+ // 'date': '2019-12-15 16:04:10',
675
+ // 'rate': '0.00000355',
676
+ // 'total': '0.00071000',
677
+ // 'tradeID': '119871',
678
+ // 'type': 'buy',
679
+ // 'takerAdjustment': '200.00000000'
680
+ // }
681
+ //
682
+ const id = this.safeString2 (trade, 'globalTradeID', 'tradeID');
683
+ const orderId = this.safeString (trade, 'orderNumber');
684
+ const timestamp = this.parse8601 (this.safeString (trade, 'date'));
685
+ const marketId = this.safeString (trade, 'currencyPair');
686
+ market = this.safeMarket (marketId, market, '_');
687
+ const symbol = market['symbol'];
688
+ const side = this.safeString (trade, 'type');
689
+ let fee = undefined;
690
+ const priceString = this.safeString (trade, 'rate');
691
+ const amountString = this.safeString (trade, 'amount');
692
+ const costString = this.safeString (trade, 'total');
693
+ const feeDisplay = this.safeString (trade, 'feeDisplay');
694
+ if (feeDisplay !== undefined) {
695
+ const parts = feeDisplay.split (' ');
696
+ const feeCostString = this.safeString (parts, 0);
697
+ if (feeCostString !== undefined) {
698
+ const feeCurrencyId = this.safeString (parts, 1);
699
+ const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId);
700
+ let feeRateString = this.safeString (parts, 2);
701
+ if (feeRateString !== undefined) {
702
+ feeRateString = feeRateString.replace ('(', '');
703
+ const feeRateParts = feeRateString.split ('%');
704
+ feeRateString = this.safeString (feeRateParts, 0);
705
+ feeRateString = Precise.stringDiv (feeRateString, '100');
706
+ }
707
+ fee = {
708
+ 'cost': feeCostString,
709
+ 'currency': feeCurrencyCode,
710
+ 'rate': feeRateString,
711
+ };
712
+ }
713
+ } else {
714
+ const feeCostString = this.safeString (trade, 'fee');
715
+ if (feeCostString !== undefined && market !== undefined) {
716
+ const feeCurrencyCode = (side === 'buy') ? market['base'] : market['quote'];
717
+ const feeBase = (side === 'buy') ? amountString : costString;
718
+ const feeRateString = Precise.stringDiv (feeCostString, feeBase);
719
+ fee = {
720
+ 'cost': feeCostString,
721
+ 'currency': feeCurrencyCode,
722
+ 'rate': feeRateString,
723
+ };
724
+ }
725
+ }
726
+ let takerOrMaker = undefined;
727
+ const takerAdjustment = this.safeNumber (trade, 'takerAdjustment');
728
+ if (takerAdjustment !== undefined) {
729
+ takerOrMaker = 'taker';
730
+ }
731
+ return this.safeTrade ({
732
+ 'id': id,
733
+ 'info': trade,
734
+ 'timestamp': timestamp,
735
+ 'datetime': this.iso8601 (timestamp),
736
+ 'symbol': symbol,
737
+ 'order': orderId,
738
+ 'type': 'limit',
739
+ 'side': side,
740
+ 'takerOrMaker': takerOrMaker,
741
+ 'price': priceString,
742
+ 'amount': amountString,
743
+ 'cost': costString,
744
+ 'fee': fee,
745
+ }, market);
746
+ }
747
+
748
+ async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
749
+ await this.loadMarkets ();
750
+ const market = this.market (symbol);
751
+ const request = {
752
+ 'currencyPair': market['id'],
753
+ };
754
+ if (since !== undefined) {
755
+ request['start'] = parseInt (since / 1000);
756
+ request['end'] = this.seconds (); // last 50000 trades by default
757
+ }
758
+ const trades = await this.publicGetReturnTradeHistory (this.extend (request, params));
759
+ return this.parseTrades (trades, market, since, limit);
760
+ }
761
+
762
+ async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
763
+ await this.loadMarkets ();
764
+ let market = undefined;
765
+ if (symbol !== undefined) {
766
+ market = this.market (symbol);
767
+ }
768
+ const pair = market ? market['id'] : 'all';
769
+ const request = { 'currencyPair': pair };
770
+ if (since !== undefined) {
771
+ request['start'] = parseInt (since / 1000);
772
+ request['end'] = this.sum (this.seconds (), 1); // adding 1 is a fix for #3411
773
+ }
774
+ // limit is disabled (does not really work as expected)
775
+ if (limit !== undefined) {
776
+ request['limit'] = parseInt (limit);
777
+ }
778
+ const response = await this.privatePostReturnTradeHistory (this.extend (request, params));
779
+ //
780
+ // specific market (symbol defined)
781
+ //
782
+ // [
783
+ // {
784
+ // globalTradeID: 470912587,
785
+ // tradeID: '42543',
786
+ // date: '2020-06-15 17:31:22',
787
+ // rate: '0.000083840000',
788
+ // amount: '95237.60321429',
789
+ // total: '7.98472065',
790
+ // fee: '0.00095000',
791
+ // feeDisplay: '0.36137761 TRX (0.07125%)',
792
+ // orderNumber: '5926344995',
793
+ // type: 'sell',
794
+ // category: 'exchange'
795
+ // },
796
+ // {
797
+ // globalTradeID: 470974497,
798
+ // tradeID: '42560',
799
+ // date: '2020-06-16 00:41:23',
800
+ // rate: '0.000078220000',
801
+ // amount: '1000000.00000000',
802
+ // total: '78.22000000',
803
+ // fee: '0.00095000',
804
+ // feeDisplay: '3.48189819 TRX (0.07125%)',
805
+ // orderNumber: '5945490830',
806
+ // type: 'sell',
807
+ // category: 'exchange'
808
+ // }
809
+ // ]
810
+ //
811
+ // all markets (symbol undefined)
812
+ //
813
+ // {
814
+ // BTC_GNT: [{
815
+ // globalTradeID: 470839947,
816
+ // tradeID: '4322347',
817
+ // date: '2020-06-15 12:25:24',
818
+ // rate: '0.000005810000',
819
+ // amount: '1702.04429303',
820
+ // total: '0.00988887',
821
+ // fee: '0.00095000',
822
+ // feeDisplay: '4.18235294 TRX (0.07125%)',
823
+ // orderNumber: '102290272520',
824
+ // type: 'buy',
825
+ // category: 'exchange'
826
+ // }, {
827
+ // globalTradeID: 470895902,
828
+ // tradeID: '4322413',
829
+ // date: '2020-06-15 16:19:00',
830
+ // rate: '0.000005980000',
831
+ // amount: '18.66879219',
832
+ // total: '0.00011163',
833
+ // fee: '0.00095000',
834
+ // feeDisplay: '0.04733727 TRX (0.07125%)',
835
+ // orderNumber: '102298304480',
836
+ // type: 'buy',
837
+ // category: 'exchange'
838
+ // }],
839
+ // }
840
+ //
841
+ let result = [];
842
+ if (market !== undefined) {
843
+ result = this.parseTrades (response, market);
844
+ } else {
845
+ if (response) {
846
+ const ids = Object.keys (response);
847
+ for (let i = 0; i < ids.length; i++) {
848
+ const id = ids[i];
849
+ let market = undefined;
850
+ if (id in this.markets_by_id) {
851
+ market = this.markets_by_id[id];
852
+ const trades = this.parseTrades (response[id], market);
853
+ for (let j = 0; j < trades.length; j++) {
854
+ result.push (trades[j]);
855
+ }
856
+ } else {
857
+ const [ quoteId, baseId ] = id.split ('_');
858
+ const base = this.safeCurrencyCode (baseId);
859
+ const quote = this.safeCurrencyCode (quoteId);
860
+ const symbol = base + '/' + quote;
861
+ const trades = response[id];
862
+ for (let j = 0; j < trades.length; j++) {
863
+ const market = {
864
+ 'symbol': symbol,
865
+ 'base': base,
866
+ 'quote': quote,
867
+ };
868
+ result.push (this.parseTrade (trades[j], market));
869
+ }
870
+ }
871
+ }
872
+ }
873
+ }
874
+ return this.filterBySinceLimit (result, since, limit);
875
+ }
876
+
877
+ parseOrderStatus (status) {
878
+ const statuses = {
879
+ 'Open': 'open',
880
+ 'Partially filled': 'open',
881
+ };
882
+ return this.safeString (statuses, status, status);
883
+ }
884
+
885
+ parseOrder (order, market = undefined) {
886
+ //
887
+ // fetchOpenOrder
888
+ //
889
+ // {
890
+ // status: 'Open',
891
+ // rate: '0.40000000',
892
+ // amount: '1.00000000',
893
+ // currencyPair: 'BTC_ETH',
894
+ // date: '2018-10-17 17:04:50',
895
+ // total: '0.40000000',
896
+ // type: 'buy',
897
+ // startingAmount: '1.00000',
898
+ // }
899
+ //
900
+ // fetchOpenOrders
901
+ //
902
+ // {
903
+ // orderNumber: '514514894224',
904
+ // type: 'buy',
905
+ // rate: '0.00001000',
906
+ // startingAmount: '100.00000000',
907
+ // amount: '100.00000000',
908
+ // total: '0.00100000',
909
+ // date: '2018-10-23 17:38:53',
910
+ // margin: 0,
911
+ // }
912
+ //
913
+ // createOrder
914
+ //
915
+ // {
916
+ // 'orderNumber': '9805453960',
917
+ // 'resultingTrades': [
918
+ // {
919
+ // 'amount': '200.00000000',
920
+ // 'date': '2019-12-15 16:04:10',
921
+ // 'rate': '0.00000355',
922
+ // 'total': '0.00071000',
923
+ // 'tradeID': '119871',
924
+ // 'type': 'buy',
925
+ // 'takerAdjustment': '200.00000000',
926
+ // },
927
+ // ],
928
+ // 'fee': '0.00000000',
929
+ // 'clientOrderId': '12345',
930
+ // 'currencyPair': 'BTC_MANA',
931
+ // // 'resultingTrades' in editOrder
932
+ // 'resultingTrades': {
933
+ // 'BTC_MANA': [],
934
+ // }
935
+ // }
936
+ //
937
+ let timestamp = this.safeInteger (order, 'timestamp');
938
+ if (timestamp === undefined) {
939
+ timestamp = this.parse8601 (this.safeString (order, 'date'));
940
+ }
941
+ const marketId = this.safeString (order, 'currencyPair');
942
+ market = this.safeMarket (marketId, market, '_');
943
+ const symbol = market['symbol'];
944
+ let resultingTrades = this.safeValue (order, 'resultingTrades');
945
+ if (!Array.isArray (resultingTrades)) {
946
+ resultingTrades = this.safeValue (resultingTrades, this.safeString (market, 'id', marketId));
947
+ }
948
+ const price = this.safeString2 (order, 'price', 'rate');
949
+ const remaining = this.safeString (order, 'amount');
950
+ const amount = this.safeString (order, 'startingAmount');
951
+ const status = this.parseOrderStatus (this.safeString (order, 'status'));
952
+ const side = this.safeString (order, 'type');
953
+ const id = this.safeString (order, 'orderNumber');
954
+ let fee = undefined;
955
+ const feeCurrency = this.safeString (order, 'tokenFeeCurrency');
956
+ let feeCost = undefined;
957
+ let feeCurrencyCode = undefined;
958
+ const rate = this.safeString (order, 'fee');
959
+ if (feeCurrency === undefined) {
960
+ feeCurrencyCode = (side === 'buy') ? market['base'] : market['quote'];
961
+ } else {
962
+ // poloniex accepts a 30% discount to pay fees in TRX
963
+ feeCurrencyCode = this.safeCurrencyCode (feeCurrency);
964
+ feeCost = this.safeString (order, 'tokenFee');
965
+ }
966
+ if (feeCost !== undefined) {
967
+ fee = {
968
+ 'rate': rate,
969
+ 'cost': feeCost,
970
+ 'currency': feeCurrencyCode,
971
+ };
972
+ }
973
+ const clientOrderId = this.safeString (order, 'clientOrderId');
974
+ return this.safeOrder ({
975
+ 'info': order,
976
+ 'id': id,
977
+ 'clientOrderId': clientOrderId,
978
+ 'timestamp': timestamp,
979
+ 'datetime': this.iso8601 (timestamp),
980
+ 'lastTradeTimestamp': undefined,
981
+ 'status': status,
982
+ 'symbol': symbol,
983
+ 'type': 'limit',
984
+ 'timeInForce': undefined,
985
+ 'postOnly': undefined,
986
+ 'side': side,
987
+ 'price': price,
988
+ 'stopPrice': undefined,
989
+ 'cost': undefined,
990
+ 'average': undefined,
991
+ 'amount': amount,
992
+ 'filled': undefined,
993
+ 'remaining': remaining,
994
+ 'trades': resultingTrades,
995
+ 'fee': fee,
996
+ }, market);
997
+ }
998
+
999
+ parseOpenOrders (orders, market, result) {
1000
+ for (let i = 0; i < orders.length; i++) {
1001
+ const order = orders[i];
1002
+ const extended = this.extend (order, {
1003
+ 'status': 'open',
1004
+ 'type': 'limit',
1005
+ 'side': order['type'],
1006
+ 'price': order['rate'],
1007
+ });
1008
+ result.push (this.parseOrder (extended, market));
1009
+ }
1010
+ return result;
1011
+ }
1012
+
1013
+ async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
1014
+ await this.loadMarkets ();
1015
+ let market = undefined;
1016
+ if (symbol !== undefined) {
1017
+ market = this.market (symbol);
1018
+ }
1019
+ const pair = market ? market['id'] : 'all';
1020
+ const request = {
1021
+ 'currencyPair': pair,
1022
+ };
1023
+ const response = await this.privatePostReturnOpenOrders (this.extend (request, params));
1024
+ const extension = { 'status': 'open' };
1025
+ if (market === undefined) {
1026
+ const marketIds = Object.keys (response);
1027
+ let openOrders = [];
1028
+ for (let i = 0; i < marketIds.length; i++) {
1029
+ const marketId = marketIds[i];
1030
+ const orders = response[marketId];
1031
+ const m = this.markets_by_id[marketId];
1032
+ openOrders = this.arrayConcat (openOrders, this.parseOrders (orders, m, undefined, undefined, extension));
1033
+ }
1034
+ return this.filterBySinceLimit (openOrders, since, limit);
1035
+ } else {
1036
+ return this.parseOrders (response, market, since, limit, extension);
1037
+ }
1038
+ }
1039
+
1040
+ async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
1041
+ if (type === 'market') {
1042
+ throw new ExchangeError (this.id + ' createOrder() does not accept market orders');
1043
+ }
1044
+ await this.loadMarkets ();
1045
+ const method = 'privatePost' + this.capitalize (side);
1046
+ const market = this.market (symbol);
1047
+ amount = this.amountToPrecision (symbol, amount);
1048
+ const request = {
1049
+ 'currencyPair': market['id'],
1050
+ 'rate': this.priceToPrecision (symbol, price),
1051
+ 'amount': amount,
1052
+ };
1053
+ const clientOrderId = this.safeString (params, 'clientOrderId');
1054
+ if (clientOrderId !== undefined) {
1055
+ request['clientOrderId'] = clientOrderId;
1056
+ params = this.omit (params, 'clientOrderId');
1057
+ }
1058
+ // remember the timestamp before issuing the request
1059
+ let response = await this[method] (this.extend (request, params));
1060
+ //
1061
+ // {
1062
+ // 'orderNumber': '9805453960',
1063
+ // 'resultingTrades': [
1064
+ // {
1065
+ // 'amount': '200.00000000',
1066
+ // 'date': '2019-12-15 16:04:10',
1067
+ // 'rate': '0.00000355',
1068
+ // 'total': '0.00071000',
1069
+ // 'tradeID': '119871',
1070
+ // 'type': 'buy',
1071
+ // 'takerAdjustment': '200.00000000',
1072
+ // },
1073
+ // ],
1074
+ // 'fee': '0.00000000',
1075
+ // 'currencyPair': 'BTC_MANA',
1076
+ // }
1077
+ //
1078
+ response = this.extend (response, {
1079
+ 'type': side,
1080
+ });
1081
+ return this.parseOrder (response, market);
1082
+ }
1083
+
1084
+ async editOrder (id, symbol, type, side, amount, price = undefined, params = {}) {
1085
+ await this.loadMarkets ();
1086
+ price = parseFloat (price);
1087
+ const request = {
1088
+ 'orderNumber': id,
1089
+ 'rate': this.priceToPrecision (symbol, price),
1090
+ };
1091
+ if (amount !== undefined) {
1092
+ request['amount'] = this.amountToPrecision (symbol, amount);
1093
+ }
1094
+ const response = await this.privatePostMoveOrder (this.extend (request, params));
1095
+ return this.parseOrder (response);
1096
+ }
1097
+
1098
+ async cancelOrder (id, symbol = undefined, params = {}) {
1099
+ await this.loadMarkets ();
1100
+ const request = {};
1101
+ const clientOrderId = this.safeValue (params, 'clientOrderId');
1102
+ if (clientOrderId === undefined) {
1103
+ request['orderNumber'] = id;
1104
+ } else {
1105
+ request['clientOrderId'] = clientOrderId;
1106
+ }
1107
+ params = this.omit (params, 'clientOrderId');
1108
+ return await this.privatePostCancelOrder (this.extend (request, params));
1109
+ }
1110
+
1111
+ async cancelAllOrders (symbol = undefined, params = {}) {
1112
+ const request = {};
1113
+ let market = undefined;
1114
+ if (symbol !== undefined) {
1115
+ market = this.market (symbol);
1116
+ request['currencyPair'] = market['id'];
1117
+ }
1118
+ const response = await this.privatePostCancelAllOrders (this.extend (request, params));
1119
+ //
1120
+ // {
1121
+ // "success": 1,
1122
+ // "message": "Orders canceled",
1123
+ // "orderNumbers": [
1124
+ // 503749,
1125
+ // 888321,
1126
+ // 7315825,
1127
+ // 7316824
1128
+ // ]
1129
+ // }
1130
+ //
1131
+ return response;
1132
+ }
1133
+
1134
+ async fetchOpenOrder (id, symbol = undefined, params = {}) {
1135
+ await this.loadMarkets ();
1136
+ id = id.toString ();
1137
+ const request = {
1138
+ 'orderNumber': id,
1139
+ };
1140
+ const response = await this.privatePostReturnOrderStatus (this.extend (request, params));
1141
+ //
1142
+ // {
1143
+ // success: 1,
1144
+ // result: {
1145
+ // '6071071': {
1146
+ // status: 'Open',
1147
+ // rate: '0.40000000',
1148
+ // amount: '1.00000000',
1149
+ // currencyPair: 'BTC_ETH',
1150
+ // date: '2018-10-17 17:04:50',
1151
+ // total: '0.40000000',
1152
+ // type: 'buy',
1153
+ // startingAmount: '1.00000',
1154
+ // },
1155
+ // },
1156
+ // }
1157
+ //
1158
+ const result = this.safeValue (response['result'], id);
1159
+ if (result === undefined) {
1160
+ throw new OrderNotFound (this.id + ' order id ' + id + ' not found');
1161
+ }
1162
+ return this.extend (this.parseOrder (result), {
1163
+ 'id': id,
1164
+ });
1165
+ }
1166
+
1167
+ async fetchClosedOrder (id, symbol = undefined, params = {}) {
1168
+ await this.loadMarkets ();
1169
+ const request = {
1170
+ 'orderNumber': id,
1171
+ };
1172
+ const response = await this.privatePostReturnOrderTrades (this.extend (request, params));
1173
+ //
1174
+ // [
1175
+ // {
1176
+ // "globalTradeID":570264000,
1177
+ // "tradeID":8026283,
1178
+ // "currencyPair":"USDT_LTC",
1179
+ // "type":"sell",
1180
+ // "rate":"144.73833409",
1181
+ // "amount":"0.18334460",
1182
+ // "total":"26.53699196",
1183
+ // "fee":"0.00155000",
1184
+ // "date":"2021-07-04 15:16:20"
1185
+ // }
1186
+ // ]
1187
+ //
1188
+ const firstTrade = this.safeValue (response, 0);
1189
+ if (firstTrade === undefined) {
1190
+ throw new OrderNotFound (this.id + ' order id ' + id + ' not found');
1191
+ }
1192
+ id = this.safeValue (firstTrade, 'globalTradeID', id);
1193
+ return this.safeOrder ({
1194
+ 'info': response,
1195
+ 'id': id,
1196
+ 'clientOrderId': this.safeValue (firstTrade, 'clientOrderId'),
1197
+ 'timestamp': undefined,
1198
+ 'datetime': undefined,
1199
+ 'lastTradeTimestamp': undefined,
1200
+ 'status': 'closed',
1201
+ 'symbol': undefined,
1202
+ 'type': undefined,
1203
+ 'timeInForce': undefined,
1204
+ 'postOnly': undefined,
1205
+ 'side': undefined,
1206
+ 'price': undefined,
1207
+ 'stopPrice': undefined,
1208
+ 'cost': undefined,
1209
+ 'average': undefined,
1210
+ 'amount': undefined,
1211
+ 'filled': undefined,
1212
+ 'remaining': undefined,
1213
+ 'trades': response,
1214
+ 'fee': undefined,
1215
+ });
1216
+ }
1217
+
1218
+ async fetchOrderStatus (id, symbol = undefined, params = {}) {
1219
+ await this.loadMarkets ();
1220
+ const orders = await this.fetchOpenOrders (symbol, undefined, undefined, params);
1221
+ const indexed = this.indexBy (orders, 'id');
1222
+ return (id in indexed) ? 'open' : 'closed';
1223
+ }
1224
+
1225
+ async fetchOrderTrades (id, symbol = undefined, since = undefined, limit = undefined, params = {}) {
1226
+ await this.loadMarkets ();
1227
+ const request = {
1228
+ 'orderNumber': id,
1229
+ };
1230
+ const trades = await this.privatePostReturnOrderTrades (this.extend (request, params));
1231
+ return this.parseTrades (trades);
1232
+ }
1233
+
1234
+ async createDepositAddress (code, params = {}) {
1235
+ await this.loadMarkets ();
1236
+ // USDT, USDTETH, USDTTRON
1237
+ let currencyId = undefined;
1238
+ let currency = undefined;
1239
+ if (code in this.currencies) {
1240
+ currency = this.currency (code);
1241
+ currencyId = currency['id'];
1242
+ } else {
1243
+ currencyId = code;
1244
+ }
1245
+ const request = {
1246
+ 'currency': currencyId,
1247
+ };
1248
+ const response = await this.privatePostGenerateNewAddress (this.extend (request, params));
1249
+ let address = undefined;
1250
+ let tag = undefined;
1251
+ const success = this.safeString (response, 'success');
1252
+ if (success === '1') {
1253
+ address = this.safeString (response, 'response');
1254
+ }
1255
+ this.checkAddress (address);
1256
+ if (currency !== undefined) {
1257
+ const depositAddress = this.safeString (currency['info'], 'depositAddress');
1258
+ if (depositAddress !== undefined) {
1259
+ tag = address;
1260
+ address = depositAddress;
1261
+ }
1262
+ }
1263
+ return {
1264
+ 'currency': code,
1265
+ 'address': address,
1266
+ 'tag': tag,
1267
+ 'info': response,
1268
+ };
1269
+ }
1270
+
1271
+ async fetchDepositAddress (code, params = {}) {
1272
+ await this.loadMarkets ();
1273
+ const response = await this.privatePostReturnDepositAddresses (params);
1274
+ // USDT, USDTETH, USDTTRON
1275
+ let currencyId = undefined;
1276
+ let currency = undefined;
1277
+ if (code in this.currencies) {
1278
+ currency = this.currency (code);
1279
+ currencyId = currency['id'];
1280
+ } else {
1281
+ currencyId = code;
1282
+ }
1283
+ let address = this.safeString (response, currencyId);
1284
+ let tag = undefined;
1285
+ this.checkAddress (address);
1286
+ if (currency !== undefined) {
1287
+ const depositAddress = this.safeString (currency['info'], 'depositAddress');
1288
+ if (depositAddress !== undefined) {
1289
+ tag = address;
1290
+ address = depositAddress;
1291
+ }
1292
+ }
1293
+ return {
1294
+ 'currency': code,
1295
+ 'address': address,
1296
+ 'tag': tag,
1297
+ 'network': undefined,
1298
+ 'info': response,
1299
+ };
1300
+ }
1301
+
1302
+ async transfer (code, amount, fromAccount, toAccount, params = {}) {
1303
+ await this.loadMarkets ();
1304
+ const currency = this.currency (code);
1305
+ amount = this.currencyToPrecision (code, amount);
1306
+ const accountsByType = this.safeValue (this.options, 'accountsByType', {});
1307
+ const fromId = this.safeString (accountsByType, fromAccount, fromAccount);
1308
+ const toId = this.safeString (accountsByType, toAccount, fromAccount);
1309
+ const request = {
1310
+ 'amount': amount,
1311
+ 'currency': currency['id'],
1312
+ 'fromAccount': fromId,
1313
+ 'toAccount': toId,
1314
+ };
1315
+ const response = await this.privatePostTransferBalance (this.extend (request, params));
1316
+ //
1317
+ // {
1318
+ // success: '1',
1319
+ // message: 'Transferred 1.00000000 USDT from exchange to lending account.'
1320
+ // }
1321
+ //
1322
+ return this.parseTransfer (response, currency);
1323
+ }
1324
+
1325
+ parseTransferStatus (status) {
1326
+ const statuses = {
1327
+ '1': 'ok',
1328
+ };
1329
+ return this.safeString (statuses, status, status);
1330
+ }
1331
+
1332
+ parseTransfer (transfer, currency = undefined) {
1333
+ //
1334
+ // {
1335
+ // success: '1',
1336
+ // message: 'Transferred 1.00000000 USDT from exchange to lending account.'
1337
+ // }
1338
+ //
1339
+ const message = this.safeString (transfer, 'message');
1340
+ const words = message.split (' ');
1341
+ const amount = this.safeNumber (words, 1);
1342
+ const currencyId = this.safeString (words, 2);
1343
+ const fromAccountId = this.safeString (words, 4);
1344
+ const toAccountId = this.safeString (words, 6);
1345
+ const accountsById = this.safeValue (this.options, 'accountsById', {});
1346
+ return {
1347
+ 'info': transfer,
1348
+ 'id': undefined,
1349
+ 'timestamp': undefined,
1350
+ 'datetime': undefined,
1351
+ 'currency': this.safeCurrencyCode (currencyId, currency),
1352
+ 'amount': amount,
1353
+ 'fromAccount': this.safeString (accountsById, fromAccountId),
1354
+ 'toAccount': this.safeString (accountsById, toAccountId),
1355
+ 'status': this.parseOrderStatus (this.safeString (transfer, 'success', 'failed')),
1356
+ };
1357
+ }
1358
+
1359
+ async withdraw (code, amount, address, tag = undefined, params = {}) {
1360
+ [ tag, params ] = this.handleWithdrawTagAndParams (tag, params);
1361
+ this.checkAddress (address);
1362
+ await this.loadMarkets ();
1363
+ const currency = this.currency (code);
1364
+ const request = {
1365
+ 'currency': currency['id'],
1366
+ 'amount': amount,
1367
+ 'address': address,
1368
+ };
1369
+ if (tag !== undefined) {
1370
+ request['paymentId'] = tag;
1371
+ }
1372
+ const networks = this.safeValue (this.options, 'networks', {});
1373
+ let network = this.safeStringUpper (params, 'network'); // this line allows the user to specify either ERC20 or ETH
1374
+ network = this.safeString (networks, network, network); // handle ERC20>ETH alias
1375
+ if (network !== undefined) {
1376
+ request['currency'] += network; // when network the currency need to be changed to currency+network https://docs.poloniex.com/#withdraw on MultiChain Currencies section
1377
+ params = this.omit (params, 'network');
1378
+ }
1379
+ const response = await this.privatePostWithdraw (this.extend (request, params));
1380
+ //
1381
+ // {
1382
+ // response: 'Withdrew 1.00000000 USDT.',
1383
+ // email2FA: false,
1384
+ // withdrawalNumber: 13449869
1385
+ // }
1386
+ //
1387
+ return this.parseTransaction (response, currency);
1388
+ }
1389
+
1390
+ async fetchTransactionsHelper (code = undefined, since = undefined, limit = undefined, params = {}) {
1391
+ await this.loadMarkets ();
1392
+ const year = 31104000; // 60 * 60 * 24 * 30 * 12 = one year of history, why not
1393
+ const now = this.seconds ();
1394
+ const start = (since !== undefined) ? parseInt (since / 1000) : now - 10 * year;
1395
+ const request = {
1396
+ 'start': start, // UNIX timestamp, required
1397
+ 'end': now, // UNIX timestamp, required
1398
+ };
1399
+ if (limit !== undefined) {
1400
+ request['limit'] = limit;
1401
+ }
1402
+ const response = await this.privatePostReturnDepositsWithdrawals (this.extend (request, params));
1403
+ //
1404
+ // {
1405
+ // "adjustments":[],
1406
+ // "deposits":[
1407
+ // {
1408
+ // currency: "BTC",
1409
+ // address: "1MEtiqJWru53FhhHrfJPPvd2tC3TPDVcmW",
1410
+ // amount: "0.01063000",
1411
+ // confirmations: 1,
1412
+ // txid: "952b0e1888d6d491591facc0d37b5ebec540ac1efb241fdbc22bcc20d1822fb6",
1413
+ // timestamp: 1507916888,
1414
+ // status: "COMPLETE"
1415
+ // },
1416
+ // {
1417
+ // currency: "ETH",
1418
+ // address: "0x20108ba20b65c04d82909e91df06618107460197",
1419
+ // amount: "4.00000000",
1420
+ // confirmations: 38,
1421
+ // txid: "0x4be260073491fe63935e9e0da42bd71138fdeb803732f41501015a2d46eb479d",
1422
+ // timestamp: 1525060430,
1423
+ // status: "COMPLETE"
1424
+ // }
1425
+ // ],
1426
+ // "withdrawals":[
1427
+ // {
1428
+ // "withdrawalNumber":13449869,
1429
+ // "currency":"USDTTRON", // not documented in API docs, see commonCurrencies in describe()
1430
+ // "address":"TXGaqPW23JdRWhsVwS2mRsGsegbdnAd3Rw",
1431
+ // "amount":"1.00000000",
1432
+ // "fee":"0.00000000",
1433
+ // "timestamp":1591573420,
1434
+ // "status":"COMPLETE: dadf427224b3d44b38a2c13caa4395e4666152556ca0b2f67dbd86a95655150f",
1435
+ // "ipAddress":"x.x.x.x",
1436
+ // "canCancel":0,
1437
+ // "canResendEmail":0,
1438
+ // "paymentID":null,
1439
+ // "scope":"crypto"
1440
+ // },
1441
+ // {
1442
+ // withdrawalNumber: 8224394,
1443
+ // currency: "EMC2",
1444
+ // address: "EYEKyCrqTNmVCpdDV8w49XvSKRP9N3EUyF",
1445
+ // amount: "63.10796020",
1446
+ // fee: "0.01000000",
1447
+ // timestamp: 1510819838,
1448
+ // status: "COMPLETE: d37354f9d02cb24d98c8c4fc17aa42f475530b5727effdf668ee5a43ce667fd6",
1449
+ // ipAddress: "x.x.x.x"
1450
+ // },
1451
+ // {
1452
+ // withdrawalNumber: 9290444,
1453
+ // currency: "ETH",
1454
+ // address: "0x191015ff2e75261d50433fbd05bd57e942336149",
1455
+ // amount: "0.15500000",
1456
+ // fee: "0.00500000",
1457
+ // timestamp: 1514099289,
1458
+ // status: "COMPLETE: 0x12d444493b4bca668992021fd9e54b5292b8e71d9927af1f076f554e4bea5b2d",
1459
+ // ipAddress: "x.x.x.x"
1460
+ // },
1461
+ // {
1462
+ // withdrawalNumber: 11518260,
1463
+ // currency: "BTC",
1464
+ // address: "8JoDXAmE1GY2LRK8jD1gmAmgRPq54kXJ4t",
1465
+ // amount: "0.20000000",
1466
+ // fee: "0.00050000",
1467
+ // timestamp: 1527918155,
1468
+ // status: "COMPLETE: 1864f4ebb277d90b0b1ff53259b36b97fa1990edc7ad2be47c5e0ab41916b5ff",
1469
+ // ipAddress: "x.x.x.x"
1470
+ // }
1471
+ // ]
1472
+ // }
1473
+ //
1474
+ return response;
1475
+ }
1476
+
1477
+ async fetchTransactions (code = undefined, since = undefined, limit = undefined, params = {}) {
1478
+ await this.loadMarkets ();
1479
+ const response = await this.fetchTransactionsHelper (code, since, limit, params);
1480
+ let currency = undefined;
1481
+ if (code !== undefined) {
1482
+ currency = this.currency (code);
1483
+ }
1484
+ const withdrawals = this.safeValue (response, 'withdrawals', []);
1485
+ const deposits = this.safeValue (response, 'deposits', []);
1486
+ const withdrawalTransactions = this.parseTransactions (withdrawals, currency, since, limit);
1487
+ const depositTransactions = this.parseTransactions (deposits, currency, since, limit);
1488
+ const transactions = this.arrayConcat (depositTransactions, withdrawalTransactions);
1489
+ return this.filterByCurrencySinceLimit (this.sortBy (transactions, 'timestamp'), code, since, limit);
1490
+ }
1491
+
1492
+ async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) {
1493
+ const response = await this.fetchTransactionsHelper (code, since, limit, params);
1494
+ let currency = undefined;
1495
+ if (code !== undefined) {
1496
+ currency = this.currency (code);
1497
+ }
1498
+ const withdrawals = this.safeValue (response, 'withdrawals', []);
1499
+ const transactions = this.parseTransactions (withdrawals, currency, since, limit);
1500
+ return this.filterByCurrencySinceLimit (transactions, code, since, limit);
1501
+ }
1502
+
1503
+ async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) {
1504
+ const response = await this.fetchTransactionsHelper (code, since, limit, params);
1505
+ let currency = undefined;
1506
+ if (code !== undefined) {
1507
+ currency = this.currency (code);
1508
+ }
1509
+ const deposits = this.safeValue (response, 'deposits', []);
1510
+ const transactions = this.parseTransactions (deposits, currency, since, limit);
1511
+ return this.filterByCurrencySinceLimit (transactions, code, since, limit);
1512
+ }
1513
+
1514
+ parseTransactionStatus (status) {
1515
+ const statuses = {
1516
+ 'COMPLETE': 'ok',
1517
+ 'AWAITING APPROVAL': 'pending',
1518
+ 'PENDING': 'pending',
1519
+ 'PROCESSING': 'pending',
1520
+ 'COMPLETE ERROR': 'failed',
1521
+ };
1522
+ return this.safeString (statuses, status, status);
1523
+ }
1524
+
1525
+ parseTransaction (transaction, currency = undefined) {
1526
+ //
1527
+ // deposits
1528
+ //
1529
+ // {
1530
+ // "txid": "f49d489616911db44b740612d19464521179c76ebe9021af85b6de1e2f8d68cd",
1531
+ // "type": "deposit",
1532
+ // "amount": "49798.01987021",
1533
+ // "status": "COMPLETE",
1534
+ // "address": "DJVJZ58tJC8UeUv9Tqcdtn6uhWobouxFLT",
1535
+ // "currency": "DOGE",
1536
+ // "timestamp": 1524321838,
1537
+ // "confirmations": 3371,
1538
+ // "depositNumber": 134587098
1539
+ // }
1540
+ //
1541
+ // withdrawals
1542
+ //
1543
+ // {
1544
+ // "fee": "0.00050000",
1545
+ // "type": "withdrawal",
1546
+ // "amount": "0.40234387",
1547
+ // "status": "COMPLETE: fbabb2bf7d81c076f396f3441166d5f60f6cea5fdfe69e02adcc3b27af8c2746",
1548
+ // "address": "1EdAqY4cqHoJGAgNfUFER7yZpg1Jc9DUa3",
1549
+ // "currency": "BTC",
1550
+ // "canCancel": 0,
1551
+ // "ipAddress": "x.x.x.x",
1552
+ // "paymentID": null,
1553
+ // "timestamp": 1523834337,
1554
+ // "canResendEmail": 0,
1555
+ // "withdrawalNumber": 11162900
1556
+ // }
1557
+ //
1558
+ // withdraw
1559
+ //
1560
+ // {
1561
+ // response: 'Withdrew 1.00000000 USDT.',
1562
+ // email2FA: false,
1563
+ // withdrawalNumber: 13449869
1564
+ // }
1565
+ //
1566
+ const timestamp = this.safeTimestamp (transaction, 'timestamp');
1567
+ const currencyId = this.safeString (transaction, 'currency');
1568
+ const code = this.safeCurrencyCode (currencyId);
1569
+ let status = this.safeString (transaction, 'status', 'pending');
1570
+ let txid = this.safeString (transaction, 'txid');
1571
+ if (status !== undefined) {
1572
+ const parts = status.split (': ');
1573
+ const numParts = parts.length;
1574
+ status = parts[0];
1575
+ if ((numParts > 1) && (txid === undefined)) {
1576
+ txid = parts[1];
1577
+ }
1578
+ status = this.parseTransactionStatus (status);
1579
+ }
1580
+ const defaultType = ('withdrawalNumber' in transaction) ? 'withdrawal' : 'deposit';
1581
+ const type = this.safeString (transaction, 'type', defaultType);
1582
+ const id = this.safeString2 (transaction, 'withdrawalNumber', 'depositNumber');
1583
+ let amount = this.safeNumber (transaction, 'amount');
1584
+ const address = this.safeString (transaction, 'address');
1585
+ const tag = this.safeString (transaction, 'paymentID');
1586
+ // according to https://poloniex.com/fees/
1587
+ const feeCost = this.safeNumber (transaction, 'fee', 0);
1588
+ if (type === 'withdrawal') {
1589
+ // poloniex withdrawal amount includes the fee
1590
+ amount = amount - feeCost;
1591
+ }
1592
+ return {
1593
+ 'info': transaction,
1594
+ 'id': id,
1595
+ 'currency': code,
1596
+ 'amount': amount,
1597
+ 'network': undefined,
1598
+ 'address': address,
1599
+ 'addressTo': undefined,
1600
+ 'addressFrom': undefined,
1601
+ 'tag': tag,
1602
+ 'tagTo': undefined,
1603
+ 'tagFrom': undefined,
1604
+ 'status': status,
1605
+ 'type': type,
1606
+ 'updated': undefined,
1607
+ 'txid': txid,
1608
+ 'timestamp': timestamp,
1609
+ 'datetime': this.iso8601 (timestamp),
1610
+ 'fee': {
1611
+ 'currency': code,
1612
+ 'cost': feeCost,
1613
+ },
1614
+ };
1615
+ }
1616
+
1617
+ async fetchPosition (symbol, params = {}) {
1618
+ await this.loadMarkets ();
1619
+ const market = this.market (symbol);
1620
+ const request = {
1621
+ 'currencyPair': market['id'],
1622
+ };
1623
+ const response = await this.privatePostGetMarginPosition (this.extend (request, params));
1624
+ //
1625
+ // {
1626
+ // type: "none",
1627
+ // amount: "0.00000000",
1628
+ // total: "0.00000000",
1629
+ // basePrice: "0.00000000",
1630
+ // liquidationPrice: -1,
1631
+ // pl: "0.00000000",
1632
+ // lendingFees: "0.00000000"
1633
+ // }
1634
+ //
1635
+ // todo unify parsePosition/parsePositions
1636
+ return response;
1637
+ }
1638
+
1639
+ nonce () {
1640
+ return this.milliseconds ();
1641
+ }
1642
+
1643
+ sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
1644
+ let url = this.urls['api'][api];
1645
+ const query = this.extend ({ 'command': path }, params);
1646
+ if (api === 'public') {
1647
+ url += '?' + this.urlencode (query);
1648
+ } else {
1649
+ this.checkRequiredCredentials ();
1650
+ query['nonce'] = this.nonce ();
1651
+ body = this.urlencode (query);
1652
+ headers = {
1653
+ 'Content-Type': 'application/x-www-form-urlencoded',
1654
+ 'Key': this.apiKey,
1655
+ 'Sign': this.hmac (this.encode (body), this.encode (this.secret), 'sha512'),
1656
+ };
1657
+ }
1658
+ return { 'url': url, 'method': method, 'body': body, 'headers': headers };
1659
+ }
1660
+
1661
+ handleErrors (code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
1662
+ if (response === undefined) {
1663
+ return;
1664
+ }
1665
+ // {"error":"Permission denied."}
1666
+ if ('error' in response) {
1667
+ const message = response['error'];
1668
+ const feedback = this.id + ' ' + body;
1669
+ this.throwExactlyMatchedException (this.exceptions['exact'], message, feedback);
1670
+ this.throwBroadlyMatchedException (this.exceptions['broad'], message, feedback);
1671
+ throw new ExchangeError (feedback); // unknown message
1672
+ }
1673
+ }
1674
+ };