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/ndax.js ADDED
@@ -0,0 +1,2233 @@
1
+ 'use strict';
2
+
3
+ // ---------------------------------------------------------------------------
4
+
5
+ const Exchange = require ('./base/Exchange');
6
+ const { ExchangeError, AuthenticationError, InsufficientFunds, BadSymbol, OrderNotFound } = require ('./base/errors');
7
+ const { TICK_SIZE } = require ('./base/functions/number');
8
+
9
+ // ---------------------------------------------------------------------------
10
+
11
+ module.exports = class ndax extends Exchange {
12
+ describe () {
13
+ return this.deepExtend (super.describe (), {
14
+ 'id': 'ndax',
15
+ 'name': 'NDAX',
16
+ 'countries': [ 'CA' ], // Canada
17
+ 'rateLimit': 1000,
18
+ 'pro': true,
19
+ 'has': {
20
+ 'CORS': undefined,
21
+ 'spot': true,
22
+ 'margin': false,
23
+ 'swap': false,
24
+ 'future': false,
25
+ 'option': false,
26
+ 'addMargin': false,
27
+ 'cancelAllOrders': true,
28
+ 'cancelOrder': true,
29
+ 'createDepositAddress': true,
30
+ 'createOrder': true,
31
+ 'createReduceOnlyOrder': false,
32
+ 'editOrder': true,
33
+ 'fetchAccounts': true,
34
+ 'fetchBalance': true,
35
+ 'fetchBorrowRate': false,
36
+ 'fetchBorrowRateHistories': false,
37
+ 'fetchBorrowRateHistory': false,
38
+ 'fetchBorrowRates': false,
39
+ 'fetchBorrowRatesPerSymbol': false,
40
+ 'fetchCurrencies': true,
41
+ 'fetchDepositAddress': true,
42
+ 'fetchDeposits': true,
43
+ 'fetchFundingHistory': false,
44
+ 'fetchFundingRate': false,
45
+ 'fetchFundingRateHistory': false,
46
+ 'fetchFundingRates': false,
47
+ 'fetchIndexOHLCV': false,
48
+ 'fetchLedger': true,
49
+ 'fetchLeverage': false,
50
+ 'fetchLeverageTiers': false,
51
+ 'fetchMarkets': true,
52
+ 'fetchMarkOHLCV': false,
53
+ 'fetchMyTrades': true,
54
+ 'fetchOHLCV': true,
55
+ 'fetchOpenOrders': true,
56
+ 'fetchOrder': true,
57
+ 'fetchOrderBook': true,
58
+ 'fetchOrders': true,
59
+ 'fetchOrderTrades': true,
60
+ 'fetchPosition': false,
61
+ 'fetchPositions': false,
62
+ 'fetchPositionsRisk': false,
63
+ 'fetchPremiumIndexOHLCV': false,
64
+ 'fetchTicker': true,
65
+ 'fetchTrades': true,
66
+ 'fetchTradingFee': false,
67
+ 'fetchTradingFees': false,
68
+ 'fetchWithdrawals': true,
69
+ 'reduceMargin': false,
70
+ 'setLeverage': false,
71
+ 'setMarginMode': false,
72
+ 'setPositionMode': false,
73
+ 'signIn': true,
74
+ 'withdraw': true,
75
+ },
76
+ 'timeframes': {
77
+ '1m': '60',
78
+ '5m': '300',
79
+ '15m': '900',
80
+ '30m': '1800',
81
+ '1h': '3600',
82
+ '2h': '7200',
83
+ '4h': '14400',
84
+ '6h': '21600',
85
+ '12h': '43200',
86
+ '1d': '86400',
87
+ '1w': '604800',
88
+ '1M': '2419200',
89
+ '4M': '9676800',
90
+ },
91
+ 'urls': {
92
+ 'logo': 'https://user-images.githubusercontent.com/1294454/108623144-67a3ef00-744e-11eb-8140-75c6b851e945.jpg',
93
+ 'test': {
94
+ 'public': 'https://ndaxmarginstaging.cdnhop.net:8443/AP',
95
+ 'private': 'https://ndaxmarginstaging.cdnhop.net:8443/AP',
96
+ },
97
+ 'api': {
98
+ 'public': 'https://api.ndax.io:8443/AP',
99
+ 'private': 'https://api.ndax.io:8443/AP',
100
+ },
101
+ 'www': 'https://ndax.io',
102
+ 'doc': [
103
+ 'https://apidoc.ndax.io/',
104
+ ],
105
+ 'fees': 'https://ndax.io/fees',
106
+ 'referral': 'https://one.ndax.io/bfQiSL',
107
+ },
108
+ 'api': {
109
+ 'public': {
110
+ 'get': {
111
+ 'Activate2FA': 1,
112
+ 'Authenticate2FA': 1,
113
+ 'AuthenticateUser': 1,
114
+ 'GetL2Snapshot': 1,
115
+ 'GetLevel1': 1,
116
+ 'GetValidate2FARequiredEndpoints': 1,
117
+ 'LogOut': 1,
118
+ 'GetTickerHistory': 1,
119
+ 'GetProduct': 1,
120
+ 'GetProducts': 1,
121
+ 'GetInstrument': 1,
122
+ 'GetInstruments': 1,
123
+ 'Ping': 1,
124
+ 'trades': 1, // undocumented
125
+ 'GetLastTrades': 1, // undocumented
126
+ 'SubscribeLevel1': 1,
127
+ 'SubscribeLevel2': 1,
128
+ 'SubscribeTicker': 1,
129
+ 'SubscribeTrades': 1,
130
+ 'SubscribeBlockTrades': 1,
131
+ 'UnsubscribeBlockTrades': 1,
132
+ 'UnsubscribeLevel1': 1,
133
+ 'UnsubscribeLevel2': 1,
134
+ 'UnsubscribeTicker': 1,
135
+ 'UnsubscribeTrades': 1,
136
+ 'Authenticate': 1, // undocumented
137
+ },
138
+ },
139
+ 'private': {
140
+ 'get': {
141
+ 'GetUserAccountInfos': 1,
142
+ 'GetUserAccounts': 1,
143
+ 'GetUserAffiliateCount': 1,
144
+ 'GetUserAffiliateTag': 1,
145
+ 'GetUserConfig': 1,
146
+ 'GetAllUnredactedUserConfigsForUser': 1,
147
+ 'GetUnredactedUserConfigByKey': 1,
148
+ 'GetUserDevices': 1,
149
+ 'GetUserReportTickets': 1,
150
+ 'GetUserReportWriterResultRecords': 1,
151
+ 'GetAccountInfo': 1,
152
+ 'GetAccountPositions': 1,
153
+ 'GetAllAccountConfigs': 1,
154
+ 'GetTreasuryProductsForAccount': 1,
155
+ 'GetAccountTrades': 1,
156
+ 'GetAccountTransactions': 1,
157
+ 'GetOpenTradeReports': 1,
158
+ 'GetAllOpenTradeReports': 1,
159
+ 'GetTradesHistory': 1,
160
+ 'GetOpenOrders': 1,
161
+ 'GetOpenQuotes': 1,
162
+ 'GetOrderFee': 1,
163
+ 'GetOrderHistory': 1,
164
+ 'GetOrdersHistory': 1,
165
+ 'GetOrderStatus': 1,
166
+ 'GetOmsFeeTiers': 1,
167
+ 'GetAccountDepositTransactions': 1,
168
+ 'GetAccountWithdrawTransactions': 1,
169
+ 'GetAllDepositRequestInfoTemplates': 1,
170
+ 'GetDepositInfo': 1,
171
+ 'GetDepositRequestInfoTemplate': 1,
172
+ 'GetDeposits': 1,
173
+ 'GetDepositTicket': 1,
174
+ 'GetDepositTickets': 1,
175
+ 'GetOMSWithdrawFees': 1,
176
+ 'GetWithdrawFee': 1,
177
+ 'GetWithdraws': 1,
178
+ 'GetWithdrawTemplate': 1,
179
+ 'GetWithdrawTemplateTypes': 1,
180
+ 'GetWithdrawTicket': 1,
181
+ 'GetWithdrawTickets': 1,
182
+ },
183
+ 'post': {
184
+ 'AddUserAffiliateTag': 1,
185
+ 'CancelUserReport': 1,
186
+ 'RegisterNewDevice': 1,
187
+ 'SubscribeAccountEvents': 1,
188
+ 'UpdateUserAffiliateTag': 1,
189
+ 'GenerateTradeActivityReport': 1,
190
+ 'GenerateTransactionActivityReport': 1,
191
+ 'GenerateTreasuryActivityReport': 1,
192
+ 'ScheduleTradeActivityReport': 1,
193
+ 'ScheduleTransactionActivityReport': 1,
194
+ 'ScheduleTreasuryActivityReport': 1,
195
+ 'CancelAllOrders': 1,
196
+ 'CancelOrder': 1,
197
+ 'CancelQuote': 1,
198
+ 'CancelReplaceOrder': 1,
199
+ 'CreateQuote': 1,
200
+ 'ModifyOrder': 1,
201
+ 'SendOrder': 1,
202
+ 'SubmitBlockTrade': 1,
203
+ 'UpdateQuote': 1,
204
+ 'CancelWithdraw': 1,
205
+ 'CreateDepositTicket': 1,
206
+ 'CreateWithdrawTicket': 1,
207
+ 'SubmitDepositTicketComment': 1,
208
+ 'SubmitWithdrawTicketComment': 1,
209
+ 'GetOrderHistoryByOrderId': 1,
210
+ },
211
+ },
212
+ },
213
+ 'fees': {
214
+ 'trading': {
215
+ 'tierBased': false,
216
+ 'percentage': true,
217
+ 'maker': 0.2 / 100,
218
+ 'taker': 0.25 / 100,
219
+ },
220
+ },
221
+ 'requiredCredentials': {
222
+ 'apiKey': true,
223
+ 'secret': true,
224
+ 'uid': true,
225
+ // these credentials are required for signIn() and withdraw()
226
+ 'login': true,
227
+ 'password': true,
228
+ // 'twofa': true,
229
+ },
230
+ 'precisionMode': TICK_SIZE,
231
+ 'exceptions': {
232
+ 'exact': {
233
+ 'Not_Enough_Funds': InsufficientFunds, // {"status":"Rejected","errormsg":"Not_Enough_Funds","errorcode":101}
234
+ 'Server Error': ExchangeError, // {"result":false,"errormsg":"Server Error","errorcode":102,"detail":null}
235
+ 'Resource Not Found': OrderNotFound, // {"result":false,"errormsg":"Resource Not Found","errorcode":104,"detail":null}
236
+ },
237
+ 'broad': {
238
+ 'Invalid InstrumentId': BadSymbol, // {"result":false,"errormsg":"Invalid InstrumentId: 10000","errorcode":100,"detail":null}
239
+ 'This endpoint requires 2FACode along with the payload': AuthenticationError,
240
+ },
241
+ },
242
+ 'options': {
243
+ 'omsId': 1,
244
+ 'orderTypes': {
245
+ 'Market': 1,
246
+ 'Limit': 2,
247
+ 'StopMarket': 3,
248
+ 'StopLimit': 4,
249
+ 'TrailingStopMarket': 5,
250
+ 'TrailingStopLimit': 6,
251
+ 'BlockTrade': 7,
252
+ },
253
+ },
254
+ });
255
+ }
256
+
257
+ async signIn (params = {}) {
258
+ this.checkRequiredCredentials ();
259
+ if (this.login === undefined || this.password === undefined) {
260
+ throw new AuthenticationError (this.id + ' signIn() requires exchange.login, exchange.password');
261
+ }
262
+ let request = {
263
+ 'grant_type': 'client_credentials', // the only supported value
264
+ };
265
+ const response = await this.publicGetAuthenticate (this.extend (request, params));
266
+ //
267
+ // {
268
+ // "Authenticated":true,
269
+ // "Requires2FA":true,
270
+ // "AuthType":"Google",
271
+ // "AddtlInfo":"",
272
+ // "Pending2FaToken": "6f5c4e66-f3ee-493e-9227-31cc0583b55f"
273
+ // }
274
+ //
275
+ let sessionToken = this.safeString (response, 'SessionToken');
276
+ if (sessionToken !== undefined) {
277
+ this.options['sessionToken'] = sessionToken;
278
+ return response;
279
+ }
280
+ const pending2faToken = this.safeString (response, 'Pending2FaToken');
281
+ if (pending2faToken !== undefined) {
282
+ if (this.twofa === undefined) {
283
+ throw new AuthenticationError (this.id + ' signIn() requires exchange.twofa credentials');
284
+ }
285
+ this.options['pending2faToken'] = pending2faToken;
286
+ request = {
287
+ 'Code': this.oath (),
288
+ };
289
+ const response = await this.publicGetAuthenticate2FA (this.extend (request, params));
290
+ //
291
+ // {
292
+ // "Authenticated": true,
293
+ // "UserId":57765,
294
+ // "SessionToken":"4a2a5857-c4e5-4fac-b09e-2c4c30b591a0"
295
+ // }
296
+ //
297
+ sessionToken = this.safeString (response, 'SessionToken');
298
+ this.options['sessionToken'] = sessionToken;
299
+ return response;
300
+ }
301
+ return response;
302
+ }
303
+
304
+ async fetchCurrencies (params = {}) {
305
+ const omsId = this.safeInteger (this.options, 'omsId', 1);
306
+ const request = {
307
+ 'omsId': omsId,
308
+ };
309
+ const response = await this.publicGetGetProducts (this.extend (request, params));
310
+ //
311
+ // [
312
+ // {
313
+ // "OMSId":1,
314
+ // "ProductId":1,
315
+ // "Product":"BTC",
316
+ // "ProductFullName":"Bitcoin",
317
+ // "ProductType":"CryptoCurrency",
318
+ // "DecimalPlaces":8,
319
+ // "TickSize":0.0000000100000000000000000000,
320
+ // "NoFees":false,
321
+ // "IsDisabled":false,
322
+ // "MarginEnabled":false
323
+ // },
324
+ // ]
325
+ //
326
+ const result = {};
327
+ for (let i = 0; i < response.length; i++) {
328
+ const currency = response[i];
329
+ const id = this.safeString (currency, 'ProductId');
330
+ const name = this.safeString (currency, 'ProductFullName');
331
+ const type = this.safeString (currency, 'ProductType');
332
+ const code = this.safeCurrencyCode (this.safeString (currency, 'Product'));
333
+ const precision = this.safeNumber (currency, 'TickSize');
334
+ const isDisabled = this.safeValue (currency, 'IsDisabled');
335
+ const active = !isDisabled;
336
+ result[code] = {
337
+ 'id': id,
338
+ 'name': name,
339
+ 'code': code,
340
+ 'type': type,
341
+ 'precision': precision,
342
+ 'info': currency,
343
+ 'active': active,
344
+ 'deposit': undefined,
345
+ 'withdraw': undefined,
346
+ 'fee': undefined,
347
+ 'limits': {
348
+ 'amount': {
349
+ 'min': undefined,
350
+ 'max': undefined,
351
+ },
352
+ 'withdraw': {
353
+ 'min': undefined,
354
+ 'max': undefined,
355
+ },
356
+ },
357
+ };
358
+ }
359
+ return result;
360
+ }
361
+
362
+ async fetchMarkets (params = {}) {
363
+ const omsId = this.safeInteger (this.options, 'omsId', 1);
364
+ const request = {
365
+ 'omsId': omsId,
366
+ };
367
+ const response = await this.publicGetGetInstruments (this.extend (request, params));
368
+ //
369
+ // [
370
+ // {
371
+ // "OMSId":1,
372
+ // "InstrumentId":3,
373
+ // "Symbol":"LTCBTC",
374
+ // "Product1":3,
375
+ // "Product1Symbol":"LTC",
376
+ // "Product2":1,
377
+ // "Product2Symbol":"BTC",
378
+ // "InstrumentType":"Standard",
379
+ // "VenueInstrumentId":3,
380
+ // "VenueId":1,
381
+ // "SortIndex":0,
382
+ // "SessionStatus":"Running",
383
+ // "PreviousSessionStatus":"Stopped",
384
+ // "SessionStatusDateTime":"2020-11-25T19:42:15.245Z",
385
+ // "SelfTradePrevention":true,
386
+ // "QuantityIncrement":0.0000000100000000000000000000,
387
+ // "PriceIncrement":0.0000000100000000000000000000,
388
+ // "MinimumQuantity":0.0100000000000000000000000000,
389
+ // "MinimumPrice":0.0000010000000000000000000000,
390
+ // "VenueSymbol":"LTCBTC",
391
+ // "IsDisable":false,
392
+ // "MasterDataId":0,
393
+ // "PriceCollarThreshold":0.0000000000000000000000000000,
394
+ // "PriceCollarPercent":0.0000000000000000000000000000,
395
+ // "PriceCollarEnabled":false,
396
+ // "PriceFloorLimit":0.0000000000000000000000000000,
397
+ // "PriceFloorLimitEnabled":false,
398
+ // "PriceCeilingLimit":0.0000000000000000000000000000,
399
+ // "PriceCeilingLimitEnabled":false,
400
+ // "CreateWithMarketRunning":true,
401
+ // "AllowOnlyMarketMakerCounterParty":false,
402
+ // "PriceCollarIndexDifference":0.0000000000000000000000000000,
403
+ // "PriceCollarConvertToOtcEnabled":false,
404
+ // "PriceCollarConvertToOtcClientUserId":0,
405
+ // "PriceCollarConvertToOtcAccountId":0,
406
+ // "PriceCollarConvertToOtcThreshold":0.0000000000000000000000000000,
407
+ // "OtcConvertSizeThreshold":0.0000000000000000000000000000,
408
+ // "OtcConvertSizeEnabled":false,
409
+ // "OtcTradesPublic":true,
410
+ // "PriceTier":0
411
+ // },
412
+ // ]
413
+ //
414
+ const result = [];
415
+ for (let i = 0; i < response.length; i++) {
416
+ const market = response[i];
417
+ const id = this.safeString (market, 'InstrumentId');
418
+ // const lowercaseId = this.safeStringLower (market, 'symbol');
419
+ const baseId = this.safeString (market, 'Product1');
420
+ const quoteId = this.safeString (market, 'Product2');
421
+ const base = this.safeCurrencyCode (this.safeString (market, 'Product1Symbol'));
422
+ const quote = this.safeCurrencyCode (this.safeString (market, 'Product2Symbol'));
423
+ const sessionStatus = this.safeString (market, 'SessionStatus');
424
+ const isDisable = this.safeValue (market, 'IsDisable');
425
+ const sessionRunning = (sessionStatus === 'Running');
426
+ result.push ({
427
+ 'id': id,
428
+ 'symbol': base + '/' + quote,
429
+ 'base': base,
430
+ 'quote': quote,
431
+ 'settle': undefined,
432
+ 'baseId': baseId,
433
+ 'quoteId': quoteId,
434
+ 'settleId': undefined,
435
+ 'type': 'spot',
436
+ 'spot': true,
437
+ 'margin': false,
438
+ 'swap': false,
439
+ 'future': false,
440
+ 'option': false,
441
+ 'active': (sessionRunning && !isDisable),
442
+ 'contract': false,
443
+ 'linear': undefined,
444
+ 'inverse': undefined,
445
+ 'contractSize': undefined,
446
+ 'expiry': undefined,
447
+ 'expiryDatetime': undefined,
448
+ 'strike': undefined,
449
+ 'optionType': undefined,
450
+ 'precision': {
451
+ 'amount': this.safeNumber (market, 'QuantityIncrement'),
452
+ 'price': this.safeNumber (market, 'PriceIncrement'),
453
+ },
454
+ 'limits': {
455
+ 'leverage': {
456
+ 'min': undefined,
457
+ 'max': undefined,
458
+ },
459
+ 'amount': {
460
+ 'min': this.safeNumber (market, 'MinimumQuantity'),
461
+ 'max': undefined,
462
+ },
463
+ 'price': {
464
+ 'min': this.safeNumber (market, 'MinimumPrice'),
465
+ 'max': undefined,
466
+ },
467
+ 'cost': {
468
+ 'min': undefined,
469
+ 'max': undefined,
470
+ },
471
+ },
472
+ 'info': market,
473
+ });
474
+ }
475
+ return result;
476
+ }
477
+
478
+ parseOrderBook (orderbook, symbol, timestamp = undefined, bidsKey = 'bids', asksKey = 'asks', priceKey = 6, amountKey = 8) {
479
+ let nonce = undefined;
480
+ const result = {
481
+ 'symbol': symbol,
482
+ 'bids': [],
483
+ 'asks': [],
484
+ 'timestamp': undefined,
485
+ 'datetime': undefined,
486
+ 'nonce': undefined,
487
+ };
488
+ for (let i = 0; i < orderbook.length; i++) {
489
+ const level = orderbook[i];
490
+ if (timestamp === undefined) {
491
+ timestamp = this.safeInteger (level, 2);
492
+ } else {
493
+ const newTimestamp = this.safeInteger (level, 2);
494
+ timestamp = Math.max (timestamp, newTimestamp);
495
+ }
496
+ if (nonce === undefined) {
497
+ nonce = this.safeInteger (level, 0);
498
+ } else {
499
+ const newNonce = this.safeInteger (level, 0);
500
+ nonce = Math.max (nonce, newNonce);
501
+ }
502
+ const bidask = this.parseBidAsk (level, priceKey, amountKey);
503
+ const levelSide = this.safeInteger (level, 9);
504
+ const side = levelSide ? asksKey : bidsKey;
505
+ result[side].push (bidask);
506
+ }
507
+ result['bids'] = this.sortBy (result['bids'], 0, true);
508
+ result['asks'] = this.sortBy (result['asks'], 0);
509
+ result['timestamp'] = timestamp;
510
+ result['datetime'] = this.iso8601 (timestamp);
511
+ result['nonce'] = nonce;
512
+ return result;
513
+ }
514
+
515
+ async fetchOrderBook (symbol, limit = undefined, params = {}) {
516
+ const omsId = this.safeInteger (this.options, 'omsId', 1);
517
+ await this.loadMarkets ();
518
+ const market = this.market (symbol);
519
+ limit = (limit === undefined) ? 100 : limit; // default 100
520
+ const request = {
521
+ 'omsId': omsId,
522
+ 'InstrumentId': market['id'],
523
+ 'Depth': limit, // default 100
524
+ };
525
+ const response = await this.publicGetGetL2Snapshot (this.extend (request, params));
526
+ //
527
+ // [
528
+ // [
529
+ // 0, // 0 MDUpdateId
530
+ // 1, // 1 Number of Unique Accounts
531
+ // 123, // 2 ActionDateTime in Posix format X 1000
532
+ // 0, // 3 ActionType 0 (New), 1 (Update), 2(Delete)
533
+ // 0.0, // 4 LastTradePrice
534
+ // 0, // 5 Number of Orders
535
+ // 0.0, // 6 Price
536
+ // 0, // 7 ProductPairCode
537
+ // 0.0, // 8 Quantity
538
+ // 0, // 9 Side
539
+ // ],
540
+ // [97244115,1,1607456142963,0,19069.32,1,19069.31,8,0.140095,0],
541
+ // [97244115,0,1607456142963,0,19069.32,1,19068.64,8,0.0055,0],
542
+ // [97244115,0,1607456142963,0,19069.32,1,19068.26,8,0.021291,0],
543
+ // [97244115,1,1607456142964,0,19069.32,1,19069.32,8,0.099636,1],
544
+ // [97244115,0,1607456142964,0,19069.32,1,19069.98,8,0.1,1],
545
+ // [97244115,0,1607456142964,0,19069.32,1,19069.99,8,0.141604,1],
546
+ // ]
547
+ //
548
+ return this.parseOrderBook (response, symbol);
549
+ }
550
+
551
+ parseTicker (ticker, market = undefined) {
552
+ //
553
+ // fetchTicker
554
+ //
555
+ // {
556
+ // "OMSId":1,
557
+ // "InstrumentId":8,
558
+ // "BestBid":19069.31,
559
+ // "BestOffer":19069.32,
560
+ // "LastTradedPx":19069.32,
561
+ // "LastTradedQty":0.0001,
562
+ // "LastTradeTime":1607040406424,
563
+ // "SessionOpen":19069.32,
564
+ // "SessionHigh":19069.32,
565
+ // "SessionLow":19069.32,
566
+ // "SessionClose":19069.32,
567
+ // "Volume":0.0001,
568
+ // "CurrentDayVolume":0.0001,
569
+ // "CurrentDayNotional":1.906932,
570
+ // "CurrentDayNumTrades":1,
571
+ // "CurrentDayPxChange":0.00,
572
+ // "Rolling24HrVolume":0.000000000000000000000000000,
573
+ // "Rolling24HrNotional":0.00000000000000000000000,
574
+ // "Rolling24NumTrades":0,
575
+ // "Rolling24HrPxChange":0,
576
+ // "TimeStamp":"1607040406425",
577
+ // "BidQty":0,
578
+ // "AskQty":0,
579
+ // "BidOrderCt":0,
580
+ // "AskOrderCt":0,
581
+ // "Rolling24HrPxChangePercent":0,
582
+ // }
583
+ //
584
+ const timestamp = this.safeInteger (ticker, 'TimeStamp');
585
+ const marketId = this.safeString (ticker, 'InstrumentId');
586
+ market = this.safeMarket (marketId, market);
587
+ const symbol = this.safeSymbol (marketId, market);
588
+ const last = this.safeNumber (ticker, 'LastTradedPx');
589
+ const percentage = this.safeNumber (ticker, 'Rolling24HrPxChangePercent');
590
+ const change = this.safeNumber (ticker, 'Rolling24HrPxChange');
591
+ const open = this.safeNumber (ticker, 'SessionOpen');
592
+ const baseVolume = this.safeNumber (ticker, 'Rolling24HrVolume');
593
+ const quoteVolume = this.safeNumber (ticker, 'Rolling24HrNotional');
594
+ const vwap = this.vwap (baseVolume, quoteVolume);
595
+ return this.safeTicker ({
596
+ 'symbol': symbol,
597
+ 'timestamp': timestamp,
598
+ 'datetime': this.iso8601 (timestamp),
599
+ 'high': this.safeNumber (ticker, 'SessionHigh'),
600
+ 'low': this.safeNumber (ticker, 'SessionLow'),
601
+ 'bid': this.safeNumber (ticker, 'BestBid'),
602
+ 'bidVolume': undefined, // this.safeNumber (ticker, 'BidQty'), always shows 0
603
+ 'ask': this.safeNumber (ticker, 'BestOffer'),
604
+ 'askVolume': undefined, // this.safeNumber (ticker, 'AskQty'), always shows 0
605
+ 'vwap': vwap,
606
+ 'open': open,
607
+ 'close': last,
608
+ 'last': last,
609
+ 'previousClose': undefined,
610
+ 'change': change,
611
+ 'percentage': percentage,
612
+ 'average': undefined,
613
+ 'baseVolume': baseVolume,
614
+ 'quoteVolume': quoteVolume,
615
+ 'info': ticker,
616
+ }, market);
617
+ }
618
+
619
+ async fetchTicker (symbol, params = {}) {
620
+ const omsId = this.safeInteger (this.options, 'omsId', 1);
621
+ await this.loadMarkets ();
622
+ const market = this.market (symbol);
623
+ const request = {
624
+ 'omsId': omsId,
625
+ 'InstrumentId': market['id'],
626
+ };
627
+ const response = await this.publicGetGetLevel1 (this.extend (request, params));
628
+ //
629
+ // {
630
+ // "OMSId":1,
631
+ // "InstrumentId":8,
632
+ // "BestBid":19069.31,
633
+ // "BestOffer":19069.32,
634
+ // "LastTradedPx":19069.32,
635
+ // "LastTradedQty":0.0001,
636
+ // "LastTradeTime":1607040406424,
637
+ // "SessionOpen":19069.32,
638
+ // "SessionHigh":19069.32,
639
+ // "SessionLow":19069.32,
640
+ // "SessionClose":19069.32,
641
+ // "Volume":0.0001,
642
+ // "CurrentDayVolume":0.0001,
643
+ // "CurrentDayNotional":1.906932,
644
+ // "CurrentDayNumTrades":1,
645
+ // "CurrentDayPxChange":0.00,
646
+ // "Rolling24HrVolume":0.000000000000000000000000000,
647
+ // "Rolling24HrNotional":0.00000000000000000000000,
648
+ // "Rolling24NumTrades":0,
649
+ // "Rolling24HrPxChange":0,
650
+ // "TimeStamp":"1607040406425",
651
+ // "BidQty":0,
652
+ // "AskQty":0,
653
+ // "BidOrderCt":0,
654
+ // "AskOrderCt":0,
655
+ // "Rolling24HrPxChangePercent":0,
656
+ // }
657
+ //
658
+ return this.parseTicker (response, market);
659
+ }
660
+
661
+ parseOHLCV (ohlcv, market = undefined) {
662
+ //
663
+ // [
664
+ // 1501603632000, // 0 DateTime
665
+ // 2700.33, // 1 High
666
+ // 2687.01, // 2 Low
667
+ // 2687.01, // 3 Open
668
+ // 2687.01, // 4 Close
669
+ // 24.86100992, // 5 Volume
670
+ // 0, // 6 Inside Bid Price
671
+ // 2870.95, // 7 Inside Ask Price
672
+ // 1 // 8 InstrumentId
673
+ // ]
674
+ //
675
+ return [
676
+ this.safeInteger (ohlcv, 0),
677
+ this.safeNumber (ohlcv, 3),
678
+ this.safeNumber (ohlcv, 1),
679
+ this.safeNumber (ohlcv, 2),
680
+ this.safeNumber (ohlcv, 4),
681
+ this.safeNumber (ohlcv, 5),
682
+ ];
683
+ }
684
+
685
+ async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
686
+ const omsId = this.safeInteger (this.options, 'omsId', 1);
687
+ await this.loadMarkets ();
688
+ const market = this.market (symbol);
689
+ const request = {
690
+ 'omsId': omsId,
691
+ 'InstrumentId': market['id'],
692
+ 'Interval': this.timeframes[timeframe],
693
+ };
694
+ const duration = this.parseTimeframe (timeframe);
695
+ const now = this.milliseconds ();
696
+ if (since === undefined) {
697
+ if (limit !== undefined) {
698
+ request['FromDate'] = this.ymdhms (now - duration * limit * 1000);
699
+ request['ToDate'] = this.ymdhms (now);
700
+ }
701
+ } else {
702
+ request['FromDate'] = this.ymdhms (since);
703
+ if (limit === undefined) {
704
+ request['ToDate'] = this.ymdhms (now);
705
+ } else {
706
+ request['ToDate'] = this.ymdhms (this.sum (since, duration * limit * 1000));
707
+ }
708
+ }
709
+ const response = await this.publicGetGetTickerHistory (this.extend (request, params));
710
+ //
711
+ // [
712
+ // [1607299260000,19069.32,19069.32,19069.32,19069.32,0,19069.31,19069.32,8,1607299200000],
713
+ // [1607299320000,19069.32,19069.32,19069.32,19069.32,0,19069.31,19069.32,8,1607299260000],
714
+ // [1607299380000,19069.32,19069.32,19069.32,19069.32,0,19069.31,19069.32,8,1607299320000],
715
+ // ]
716
+ //
717
+ return this.parseOHLCVs (response, market, timeframe, since, limit);
718
+ }
719
+
720
+ parseTrade (trade, market = undefined) {
721
+ //
722
+ // fetchTrades (public)
723
+ //
724
+ // [
725
+ // 6913253, // 0 TradeId
726
+ // 8, // 1 ProductPairCode
727
+ // 0.03340802, // 2 Quantity
728
+ // 19116.08, // 3 Price
729
+ // 2543425077, // 4 Order1
730
+ // 2543425482, // 5 Order2
731
+ // 1606935922416, // 6 Tradetime
732
+ // 0, // 7 Direction
733
+ // 1, // 8 TakerSide
734
+ // 0, // 9 BlockTrade
735
+ // 0, // 10 Either Order1ClientId or Order2ClientId
736
+ // ]
737
+ //
738
+ // fetchMyTrades (private)
739
+ //
740
+ // {
741
+ // "OMSId":1,
742
+ // "ExecutionId":16916567,
743
+ // "TradeId":14476351,
744
+ // "OrderId":2543565231,
745
+ // "AccountId":449,
746
+ // "AccountName":"igor@ccxt.trade",
747
+ // "SubAccountId":0,
748
+ // "ClientOrderId":0,
749
+ // "InstrumentId":8,
750
+ // "Side":"Sell",
751
+ // "OrderType":"Market",
752
+ // "Quantity":0.1230000000000000000000000000,
753
+ // "RemainingQuantity":0.0000000000000000000000000000,
754
+ // "Price":19069.310000000000000000000000,
755
+ // "Value":2345.5251300000000000000000000,
756
+ // "CounterParty":"7",
757
+ // "OrderTradeRevision":1,
758
+ // "Direction":"NoChange",
759
+ // "IsBlockTrade":false,
760
+ // "Fee":1.1727625650000000000000000000,
761
+ // "FeeProductId":8,
762
+ // "OrderOriginator":446,
763
+ // "UserName":"igor@ccxt.trade",
764
+ // "TradeTimeMS":1607565031569,
765
+ // "MakerTaker":"Taker",
766
+ // "AdapterTradeId":0,
767
+ // "InsideBid":19069.310000000000000000000000,
768
+ // "InsideBidSize":0.2400950000000000000000000000,
769
+ // "InsideAsk":19069.320000000000000000000000,
770
+ // "InsideAskSize":0.0997360000000000000000000000,
771
+ // "IsQuote":false,
772
+ // "CounterPartyClientUserId":1,
773
+ // "NotionalProductId":2,
774
+ // "NotionalRate":1.0000000000000000000000000000,
775
+ // "NotionalValue":2345.5251300000000000000000000,
776
+ // "NotionalHoldAmount":0,
777
+ // "TradeTime":637431618315686826
778
+ // }
779
+ //
780
+ // fetchOrderTrades
781
+ //
782
+ // {
783
+ // "Side":"Sell",
784
+ // "OrderId":2543565235,
785
+ // "Price":18600.000000000000000000000000,
786
+ // "Quantity":0.0000000000000000000000000000,
787
+ // "DisplayQuantity":0.0000000000000000000000000000,
788
+ // "Instrument":8,
789
+ // "Account":449,
790
+ // "AccountName":"igor@ccxt.trade",
791
+ // "OrderType":"Limit",
792
+ // "ClientOrderId":0,
793
+ // "OrderState":"FullyExecuted",
794
+ // "ReceiveTime":1607585844956,
795
+ // "ReceiveTimeTicks":637431826449564182,
796
+ // "LastUpdatedTime":1607585844959,
797
+ // "LastUpdatedTimeTicks":637431826449593893,
798
+ // "OrigQuantity":0.1230000000000000000000000000,
799
+ // "QuantityExecuted":0.1230000000000000000000000000,
800
+ // "GrossValueExecuted":2345.3947500000000000000000000,
801
+ // "ExecutableValue":0.0000000000000000000000000000,
802
+ // "AvgPrice":19068.250000000000000000000000,
803
+ // "CounterPartyId":0,
804
+ // "ChangeReason":"Trade",
805
+ // "OrigOrderId":2543565235,
806
+ // "OrigClOrdId":0,
807
+ // "EnteredBy":446,
808
+ // "UserName":"igor@ccxt.trade",
809
+ // "IsQuote":false,
810
+ // "InsideAsk":19069.320000000000000000000000,
811
+ // "InsideAskSize":0.0997360000000000000000000000,
812
+ // "InsideBid":19068.250000000000000000000000,
813
+ // "InsideBidSize":1.3300010000000000000000000000,
814
+ // "LastTradePrice":19068.250000000000000000000000,
815
+ // "RejectReason":"",
816
+ // "IsLockedIn":false,
817
+ // "CancelReason":"",
818
+ // "OrderFlag":"0",
819
+ // "UseMargin":false,
820
+ // "StopPrice":0.0000000000000000000000000000,
821
+ // "PegPriceType":"Unknown",
822
+ // "PegOffset":0.0000000000000000000000000000,
823
+ // "PegLimitOffset":0.0000000000000000000000000000,
824
+ // "IpAddress":"x.x.x.x",
825
+ // "ClientOrderIdUuid":null,
826
+ // "OMSId":1
827
+ // }
828
+ //
829
+ let priceString = undefined;
830
+ let amountString = undefined;
831
+ let costString = undefined;
832
+ let timestamp = undefined;
833
+ let id = undefined;
834
+ let marketId = undefined;
835
+ let side = undefined;
836
+ let orderId = undefined;
837
+ let takerOrMaker = undefined;
838
+ let fee = undefined;
839
+ let type = undefined;
840
+ if (Array.isArray (trade)) {
841
+ priceString = this.safeString (trade, 3);
842
+ amountString = this.safeString (trade, 2);
843
+ timestamp = this.safeInteger (trade, 6);
844
+ id = this.safeString (trade, 0);
845
+ marketId = this.safeString (trade, 1);
846
+ const takerSide = this.safeValue (trade, 8);
847
+ side = takerSide ? 'sell' : 'buy';
848
+ orderId = this.safeString (trade, 4);
849
+ } else {
850
+ timestamp = this.safeInteger2 (trade, 'TradeTimeMS', 'ReceiveTime');
851
+ id = this.safeString (trade, 'TradeId');
852
+ orderId = this.safeString2 (trade, 'OrderId', 'OrigOrderId');
853
+ marketId = this.safeString2 (trade, 'InstrumentId', 'Instrument');
854
+ priceString = this.safeString (trade, 'Price');
855
+ amountString = this.safeString (trade, 'Quantity');
856
+ costString = this.safeString2 (trade, 'Value', 'GrossValueExecuted');
857
+ takerOrMaker = this.safeStringLower (trade, 'MakerTaker');
858
+ side = this.safeStringLower (trade, 'Side');
859
+ type = this.safeStringLower (trade, 'OrderType');
860
+ const feeCostString = this.safeString (trade, 'Fee');
861
+ if (feeCostString !== undefined) {
862
+ const feeCurrencyId = this.safeString (trade, 'FeeProductId');
863
+ const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId);
864
+ fee = {
865
+ 'cost': feeCostString,
866
+ 'currency': feeCurrencyCode,
867
+ };
868
+ }
869
+ }
870
+ const symbol = this.safeSymbol (marketId, market);
871
+ return this.safeTrade ({
872
+ 'info': trade,
873
+ 'id': id,
874
+ 'symbol': symbol,
875
+ 'timestamp': timestamp,
876
+ 'datetime': this.iso8601 (timestamp),
877
+ 'order': orderId,
878
+ 'type': type,
879
+ 'side': side,
880
+ 'takerOrMaker': takerOrMaker,
881
+ 'price': priceString,
882
+ 'amount': amountString,
883
+ 'cost': costString,
884
+ 'fee': fee,
885
+ }, market);
886
+ }
887
+
888
+ async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
889
+ const omsId = this.safeInteger (this.options, 'omsId', 1);
890
+ await this.loadMarkets ();
891
+ const market = this.market (symbol);
892
+ const request = {
893
+ 'omsId': omsId,
894
+ 'InstrumentId': market['id'],
895
+ };
896
+ if (limit !== undefined) {
897
+ request['Count'] = limit;
898
+ }
899
+ const response = await this.publicGetGetLastTrades (this.extend (request, params));
900
+ //
901
+ // [
902
+ // [6913253,8,0.03340802,19116.08,2543425077,2543425482,1606935922416,0,1,0,0],
903
+ // [6913254,8,0.01391671,19117.42,2543427510,2543427811,1606935927998,1,1,0,0],
904
+ // [6913255,8,0.000006,19107.81,2543430495,2543430793,1606935933881,2,0,0,0],
905
+ // ]
906
+ //
907
+ return this.parseTrades (response, market, since, limit);
908
+ }
909
+
910
+ async fetchAccounts (params = {}) {
911
+ if (!this.login) {
912
+ throw new AuthenticationError (this.id + ' fetchAccounts() requires exchange.login email credential');
913
+ }
914
+ const omsId = this.safeInteger (this.options, 'omsId', 1);
915
+ this.checkRequiredCredentials ();
916
+ const request = {
917
+ 'omsId': omsId,
918
+ 'UserId': this.uid,
919
+ 'UserName': this.login,
920
+ };
921
+ const response = await this.privateGetGetUserAccounts (this.extend (request, params));
922
+ //
923
+ // [ 449 ] // comma-separated list of account ids
924
+ //
925
+ const result = [];
926
+ for (let i = 0; i < response.length; i++) {
927
+ const accountId = this.safeString (response, i);
928
+ result.push ({
929
+ 'id': accountId,
930
+ 'type': undefined,
931
+ 'currency': undefined,
932
+ 'info': accountId,
933
+ });
934
+ }
935
+ return result;
936
+ }
937
+
938
+ parseBalance (response) {
939
+ const result = {
940
+ 'info': response,
941
+ 'timestamp': undefined,
942
+ 'datetime': undefined,
943
+ };
944
+ for (let i = 0; i < response.length; i++) {
945
+ const balance = response[i];
946
+ const currencyId = this.safeString (balance, 'ProductId');
947
+ if (currencyId in this.currencies_by_id) {
948
+ const code = this.safeCurrencyCode (currencyId);
949
+ const account = this.account ();
950
+ account['total'] = this.safeString (balance, 'Amount');
951
+ account['used'] = this.safeString (balance, 'Hold');
952
+ result[code] = account;
953
+ }
954
+ }
955
+ return this.safeBalance (result);
956
+ }
957
+
958
+ async fetchBalance (params = {}) {
959
+ const omsId = this.safeInteger (this.options, 'omsId', 1);
960
+ await this.loadMarkets ();
961
+ await this.loadAccounts ();
962
+ const defaultAccountId = this.safeInteger2 (this.options, 'accountId', 'AccountId', parseInt (this.accounts[0]['id']));
963
+ const accountId = this.safeInteger2 (params, 'accountId', 'AccountId', defaultAccountId);
964
+ params = this.omit (params, [ 'accountId', 'AccountId' ]);
965
+ const request = {
966
+ 'omsId': omsId,
967
+ 'AccountId': accountId,
968
+ };
969
+ const response = await this.privateGetGetAccountPositions (this.extend (request, params));
970
+ //
971
+ // [
972
+ // {
973
+ // "OMSId":1,
974
+ // "AccountId":449,
975
+ // "ProductSymbol":"BTC",
976
+ // "ProductId":1,
977
+ // "Amount":10.000000000000000000000000000,
978
+ // "Hold":0,
979
+ // "PendingDeposits":0.0000000000000000000000000000,
980
+ // "PendingWithdraws":0.0000000000000000000000000000,
981
+ // "TotalDayDeposits":10.000000000000000000000000000,
982
+ // "TotalMonthDeposits":10.000000000000000000000000000,
983
+ // "TotalYearDeposits":10.000000000000000000000000000,
984
+ // "TotalDayDepositNotional":10.000000000000000000000000000,
985
+ // "TotalMonthDepositNotional":10.000000000000000000000000000,
986
+ // "TotalYearDepositNotional":10.000000000000000000000000000,
987
+ // "TotalDayWithdraws":0,
988
+ // "TotalMonthWithdraws":0,
989
+ // "TotalYearWithdraws":0,
990
+ // "TotalDayWithdrawNotional":0,
991
+ // "TotalMonthWithdrawNotional":0,
992
+ // "TotalYearWithdrawNotional":0,
993
+ // "NotionalProductId":8,
994
+ // "NotionalProductSymbol":"USDT",
995
+ // "NotionalValue":10.000000000000000000000000000,
996
+ // "NotionalHoldAmount":0,
997
+ // "NotionalRate":1
998
+ // },
999
+ // ]
1000
+ //
1001
+ return this.parseBalance (response);
1002
+ }
1003
+
1004
+ parseLedgerEntryType (type) {
1005
+ const types = {
1006
+ 'Trade': 'trade',
1007
+ 'Deposit': 'transaction',
1008
+ 'Withdraw': 'transaction',
1009
+ 'Transfer': 'transfer',
1010
+ 'OrderHold': 'trade',
1011
+ 'WithdrawHold': 'transaction',
1012
+ 'DepositHold': 'transaction',
1013
+ 'MarginHold': 'trade',
1014
+ 'ManualHold': 'trade',
1015
+ 'ManualEntry': 'trade',
1016
+ 'MarginAcquisition': 'trade',
1017
+ 'MarginRelinquish': 'trade',
1018
+ 'MarginQuoteHold': 'trade',
1019
+ };
1020
+ return this.safeString (types, type, type);
1021
+ }
1022
+
1023
+ parseLedgerEntry (item, currency = undefined) {
1024
+ //
1025
+ // {
1026
+ // "TransactionId":2663709493,
1027
+ // "ReferenceId":68,
1028
+ // "OMSId":1,
1029
+ // "AccountId":449,
1030
+ // "CR":10.000000000000000000000000000,
1031
+ // "DR":0.0000000000000000000000000000,
1032
+ // "Counterparty":3,
1033
+ // "TransactionType":"Other",
1034
+ // "ReferenceType":"Deposit",
1035
+ // "ProductId":1,
1036
+ // "Balance":10.000000000000000000000000000,
1037
+ // "TimeStamp":1607532331591
1038
+ // }
1039
+ //
1040
+ const id = this.safeString (item, 'TransactionId');
1041
+ const account = this.safeString (item, 'AccountId');
1042
+ const referenceId = this.safeString (item, 'ReferenceId');
1043
+ const referenceAccount = this.safeString (item, 'Counterparty');
1044
+ const type = this.parseLedgerEntryType (this.safeString (item, 'ReferenceType'));
1045
+ const currencyId = this.safeString (item, 'ProductId');
1046
+ const code = this.safeCurrencyCode (currencyId, currency);
1047
+ const credit = this.safeNumber (item, 'CR');
1048
+ const debit = this.safeNumber (item, 'DR');
1049
+ let amount = undefined;
1050
+ let direction = undefined;
1051
+ if (credit > 0) {
1052
+ amount = credit;
1053
+ direction = 'in';
1054
+ } else if (debit > 0) {
1055
+ amount = debit;
1056
+ direction = 'out';
1057
+ }
1058
+ const timestamp = this.safeInteger (item, 'TimeStamp');
1059
+ let before = undefined;
1060
+ const after = this.safeNumber (item, 'Balance');
1061
+ if (direction === 'out') {
1062
+ before = this.sum (after, amount);
1063
+ } else if (direction === 'in') {
1064
+ before = Math.max (0, after - amount);
1065
+ }
1066
+ const status = 'ok';
1067
+ return {
1068
+ 'info': item,
1069
+ 'id': id,
1070
+ 'direction': direction,
1071
+ 'account': account,
1072
+ 'referenceId': referenceId,
1073
+ 'referenceAccount': referenceAccount,
1074
+ 'type': type,
1075
+ 'currency': code,
1076
+ 'amount': amount,
1077
+ 'before': before,
1078
+ 'after': after,
1079
+ 'status': status,
1080
+ 'timestamp': timestamp,
1081
+ 'datetime': this.iso8601 (timestamp),
1082
+ 'fee': undefined,
1083
+ };
1084
+ }
1085
+
1086
+ async fetchLedger (code = undefined, since = undefined, limit = undefined, params = {}) {
1087
+ const omsId = this.safeInteger (this.options, 'omsId', 1);
1088
+ await this.loadMarkets ();
1089
+ await this.loadAccounts ();
1090
+ const defaultAccountId = this.safeInteger2 (this.options, 'accountId', 'AccountId', parseInt (this.accounts[0]['id']));
1091
+ const accountId = this.safeInteger2 (params, 'accountId', 'AccountId', defaultAccountId);
1092
+ params = this.omit (params, [ 'accountId', 'AccountId' ]);
1093
+ const request = {
1094
+ 'omsId': omsId,
1095
+ 'AccountId': accountId,
1096
+ };
1097
+ if (limit !== undefined) {
1098
+ request['Depth'] = limit;
1099
+ }
1100
+ const response = await this.privateGetGetAccountTransactions (this.extend (request, params));
1101
+ //
1102
+ // [
1103
+ // {
1104
+ // "TransactionId":2663709493,
1105
+ // "ReferenceId":68,
1106
+ // "OMSId":1,
1107
+ // "AccountId":449,
1108
+ // "CR":10.000000000000000000000000000,
1109
+ // "DR":0.0000000000000000000000000000,
1110
+ // "Counterparty":3,
1111
+ // "TransactionType":"Other",
1112
+ // "ReferenceType":"Deposit",
1113
+ // "ProductId":1,
1114
+ // "Balance":10.000000000000000000000000000,
1115
+ // "TimeStamp":1607532331591
1116
+ // },
1117
+ // ]
1118
+ //
1119
+ let currency = undefined;
1120
+ if (code !== undefined) {
1121
+ currency = this.currency (code);
1122
+ }
1123
+ return this.parseLedger (response, currency, since, limit);
1124
+ }
1125
+
1126
+ parseOrderStatus (status) {
1127
+ const statuses = {
1128
+ 'Accepted': 'open',
1129
+ 'Rejected': 'rejected',
1130
+ 'Working': 'open',
1131
+ 'Canceled': 'canceled',
1132
+ 'Expired': 'expired',
1133
+ 'FullyExecuted': 'closed',
1134
+ };
1135
+ return this.safeString (statuses, status, status);
1136
+ }
1137
+
1138
+ parseOrder (order, market = undefined) {
1139
+ //
1140
+ // createOrder
1141
+ //
1142
+ // {
1143
+ // "status":"Accepted",
1144
+ // "errormsg":"",
1145
+ // "OrderId": 2543565231
1146
+ // }
1147
+ //
1148
+ // editOrder
1149
+ //
1150
+ // {
1151
+ // "ReplacementOrderId": 1234,
1152
+ // "ReplacementClOrdId": 1561,
1153
+ // "OrigOrderId": 5678,
1154
+ // "OrigClOrdId": 91011,
1155
+ // }
1156
+ //
1157
+ // fetchOpenOrders, fetchClosedOrders
1158
+ //
1159
+ // {
1160
+ // "Side":"Buy",
1161
+ // "OrderId":2543565233,
1162
+ // "Price":19010,
1163
+ // "Quantity":0.345,
1164
+ // "DisplayQuantity":0.345,
1165
+ // "Instrument":8,
1166
+ // "Account":449,
1167
+ // "AccountName":"igor@ccxt.trade",
1168
+ // "OrderType":"Limit",
1169
+ // "ClientOrderId":0,
1170
+ // "OrderState":"Working",
1171
+ // "ReceiveTime":1607579326003,
1172
+ // "ReceiveTimeTicks":637431761260028981,
1173
+ // "LastUpdatedTime":1607579326005,
1174
+ // "LastUpdatedTimeTicks":637431761260054714,
1175
+ // "OrigQuantity":0.345,
1176
+ // "QuantityExecuted":0,
1177
+ // "GrossValueExecuted":0,
1178
+ // "ExecutableValue":0,
1179
+ // "AvgPrice":0,
1180
+ // "CounterPartyId":0,
1181
+ // "ChangeReason":"NewInputAccepted",
1182
+ // "OrigOrderId":2543565233,
1183
+ // "OrigClOrdId":0,
1184
+ // "EnteredBy":446,
1185
+ // "UserName":"igor@ccxt.trade",
1186
+ // "IsQuote":false,
1187
+ // "InsideAsk":19069.32,
1188
+ // "InsideAskSize":0.099736,
1189
+ // "InsideBid":19068.25,
1190
+ // "InsideBidSize":1.330001,
1191
+ // "LastTradePrice":19068.25,
1192
+ // "RejectReason":"",
1193
+ // "IsLockedIn":false,
1194
+ // "CancelReason":"",
1195
+ // "OrderFlag":"AddedToBook",
1196
+ // "UseMargin":false,
1197
+ // "StopPrice":0,
1198
+ // "PegPriceType":"Unknown",
1199
+ // "PegOffset":0,
1200
+ // "PegLimitOffset":0,
1201
+ // "IpAddress":null,
1202
+ // "ClientOrderIdUuid":null,
1203
+ // "OMSId":1
1204
+ // }
1205
+ //
1206
+ const id = this.safeString2 (order, 'ReplacementOrderId', 'OrderId');
1207
+ const timestamp = this.safeInteger (order, 'ReceiveTime');
1208
+ const lastTradeTimestamp = this.safeInteger (order, 'LastUpdatedTime');
1209
+ const marketId = this.safeString (order, 'Instrument');
1210
+ const symbol = this.safeSymbol (marketId, market);
1211
+ const side = this.safeStringLower (order, 'Side');
1212
+ const type = this.safeStringLower (order, 'OrderType');
1213
+ const clientOrderId = this.safeString2 (order, 'ReplacementClOrdId', 'ClientOrderId');
1214
+ const price = this.safeString (order, 'Price');
1215
+ const amount = this.safeString (order, 'OrigQuantity');
1216
+ const filled = this.safeString (order, 'QuantityExecuted');
1217
+ const cost = this.safeString (order, 'GrossValueExecuted');
1218
+ const average = this.safeString (order, 'AvgPrice');
1219
+ const stopPrice = this.parseNumber (this.omitZero (this.safeString (order, 'StopPrice')));
1220
+ const status = this.parseOrderStatus (this.safeString (order, 'OrderState'));
1221
+ return this.safeOrder ({
1222
+ 'id': id,
1223
+ 'clientOrderId': clientOrderId,
1224
+ 'info': order,
1225
+ 'timestamp': timestamp,
1226
+ 'datetime': this.iso8601 (timestamp),
1227
+ 'lastTradeTimestamp': lastTradeTimestamp,
1228
+ 'status': status,
1229
+ 'symbol': symbol,
1230
+ 'type': type,
1231
+ 'timeInForce': undefined,
1232
+ 'postOnly': undefined,
1233
+ 'side': side,
1234
+ 'price': price,
1235
+ 'stopPrice': stopPrice,
1236
+ 'cost': cost,
1237
+ 'amount': amount,
1238
+ 'filled': filled,
1239
+ 'average': average,
1240
+ 'remaining': undefined,
1241
+ 'fee': undefined,
1242
+ 'trades': undefined,
1243
+ }, market);
1244
+ }
1245
+
1246
+ async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
1247
+ const omsId = this.safeInteger (this.options, 'omsId', 1);
1248
+ await this.loadMarkets ();
1249
+ await this.loadAccounts ();
1250
+ const defaultAccountId = this.safeInteger2 (this.options, 'accountId', 'AccountId', parseInt (this.accounts[0]['id']));
1251
+ const accountId = this.safeInteger2 (params, 'accountId', 'AccountId', defaultAccountId);
1252
+ const clientOrderId = this.safeInteger2 (params, 'ClientOrderId', 'clientOrderId');
1253
+ params = this.omit (params, [ 'accountId', 'AccountId', 'clientOrderId', 'ClientOrderId' ]);
1254
+ const market = this.market (symbol);
1255
+ const orderSide = (side === 'buy') ? 0 : 1;
1256
+ const request = {
1257
+ 'InstrumentId': parseInt (market['id']),
1258
+ 'omsId': omsId,
1259
+ 'AccountId': accountId,
1260
+ 'TimeInForce': 1, // 0 Unknown, 1 GTC by default, 2 OPG execute as close to opening price as possible, 3 IOC immediate or canceled, 4 FOK fill-or-kill, 5 GTX good 'til executed, 6 GTD good 'til date
1261
+ // 'ClientOrderId': clientOrderId, // defaults to 0
1262
+ // If this order is order A, OrderIdOCO refers to the order ID of an order B (which is not the order being created by this call).
1263
+ // If order B executes, then order A created by this call is canceled.
1264
+ // You can also set up order B to watch order A in the same way, but that may require an update to order B to make it watch this one, which could have implications for priority in the order book.
1265
+ // See CancelReplaceOrder and ModifyOrder.
1266
+ // 'OrderIdOCO': 0, // The order ID if One Cancels the Other.
1267
+ // 'UseDisplayQuantity': false, // If you enter a Limit order with a reserve, you must set UseDisplayQuantity to true
1268
+ 'Side': orderSide, // 0 Buy, 1 Sell, 2 Short, 3 unknown an error condition
1269
+ 'Quantity': parseFloat (this.amountToPrecision (symbol, amount)),
1270
+ 'OrderType': this.safeInteger (this.options['orderTypes'], this.capitalize (type)), // 0 Unknown, 1 Market, 2 Limit, 3 StopMarket, 4 StopLimit, 5 TrailingStopMarket, 6 TrailingStopLimit, 7 BlockTrade
1271
+ // 'PegPriceType': 3, // 1 Last, 2 Bid, 3 Ask, 4 Midpoint
1272
+ // 'LimitPrice': parseFloat (this.priceToPrecision (symbol, price)),
1273
+ };
1274
+ // If OrderType=1 (Market), Side=0 (Buy), and LimitPrice is supplied, the Market order will execute up to the value specified
1275
+ if (price !== undefined) {
1276
+ request['LimitPrice'] = parseFloat (this.priceToPrecision (symbol, price));
1277
+ }
1278
+ if (clientOrderId !== undefined) {
1279
+ request['ClientOrderId'] = clientOrderId;
1280
+ }
1281
+ const response = await this.privatePostSendOrder (this.extend (request, params));
1282
+ //
1283
+ // {
1284
+ // "status":"Accepted",
1285
+ // "errormsg":"",
1286
+ // "OrderId": 2543565231
1287
+ // }
1288
+ //
1289
+ return this.parseOrder (response, market);
1290
+ }
1291
+
1292
+ async editOrder (id, symbol, type, side, amount, price = undefined, params = {}) {
1293
+ const omsId = this.safeInteger (this.options, 'omsId', 1);
1294
+ await this.loadMarkets ();
1295
+ await this.loadAccounts ();
1296
+ const defaultAccountId = this.safeInteger2 (this.options, 'accountId', 'AccountId', parseInt (this.accounts[0]['id']));
1297
+ const accountId = this.safeInteger2 (params, 'accountId', 'AccountId', defaultAccountId);
1298
+ const clientOrderId = this.safeInteger2 (params, 'ClientOrderId', 'clientOrderId');
1299
+ params = this.omit (params, [ 'accountId', 'AccountId', 'clientOrderId', 'ClientOrderId' ]);
1300
+ const market = this.market (symbol);
1301
+ const orderSide = (side === 'buy') ? 0 : 1;
1302
+ const request = {
1303
+ 'OrderIdToReplace': parseInt (id),
1304
+ 'InstrumentId': parseInt (market['id']),
1305
+ 'omsId': omsId,
1306
+ 'AccountId': accountId,
1307
+ 'TimeInForce': 1, // 0 Unknown, 1 GTC by default, 2 OPG execute as close to opening price as possible, 3 IOC immediate or canceled, 4 FOK fill-or-kill, 5 GTX good 'til executed, 6 GTD good 'til date
1308
+ // 'ClientOrderId': clientOrderId, // defaults to 0
1309
+ // If this order is order A, OrderIdOCO refers to the order ID of an order B (which is not the order being created by this call).
1310
+ // If order B executes, then order A created by this call is canceled.
1311
+ // You can also set up order B to watch order A in the same way, but that may require an update to order B to make it watch this one, which could have implications for priority in the order book.
1312
+ // See CancelReplaceOrder and ModifyOrder.
1313
+ // 'OrderIdOCO': 0, // The order ID if One Cancels the Other.
1314
+ // 'UseDisplayQuantity': false, // If you enter a Limit order with a reserve, you must set UseDisplayQuantity to true
1315
+ 'Side': orderSide, // 0 Buy, 1 Sell, 2 Short, 3 unknown an error condition
1316
+ 'Quantity': parseFloat (this.amountToPrecision (symbol, amount)),
1317
+ 'OrderType': this.safeInteger (this.options['orderTypes'], this.capitalize (type)), // 0 Unknown, 1 Market, 2 Limit, 3 StopMarket, 4 StopLimit, 5 TrailingStopMarket, 6 TrailingStopLimit, 7 BlockTrade
1318
+ // 'PegPriceType': 3, // 1 Last, 2 Bid, 3 Ask, 4 Midpoint
1319
+ // 'LimitPrice': parseFloat (this.priceToPrecision (symbol, price)),
1320
+ };
1321
+ // If OrderType=1 (Market), Side=0 (Buy), and LimitPrice is supplied, the Market order will execute up to the value specified
1322
+ if (price !== undefined) {
1323
+ request['LimitPrice'] = parseFloat (this.priceToPrecision (symbol, price));
1324
+ }
1325
+ if (clientOrderId !== undefined) {
1326
+ request['ClientOrderId'] = clientOrderId;
1327
+ }
1328
+ const response = await this.privatePostCancelReplaceOrder (this.extend (request, params));
1329
+ //
1330
+ // {
1331
+ // "replacementOrderId": 1234,
1332
+ // "replacementClOrdId": 1561,
1333
+ // "origOrderId": 5678,
1334
+ // "origClOrdId": 91011,
1335
+ // }
1336
+ //
1337
+ return this.parseOrder (response, market);
1338
+ }
1339
+
1340
+ async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
1341
+ const omsId = this.safeInteger (this.options, 'omsId', 1);
1342
+ await this.loadMarkets ();
1343
+ await this.loadAccounts ();
1344
+ const defaultAccountId = this.safeInteger2 (this.options, 'accountId', 'AccountId', parseInt (this.accounts[0]['id']));
1345
+ const accountId = this.safeInteger2 (params, 'accountId', 'AccountId', defaultAccountId);
1346
+ params = this.omit (params, [ 'accountId', 'AccountId' ]);
1347
+ const request = {
1348
+ 'omsId': omsId,
1349
+ 'AccountId': accountId,
1350
+ // 'InstrumentId': market['id'],
1351
+ // 'TradeId': 123, // If you specify TradeId, GetTradesHistory can return all states for a single trade
1352
+ // 'OrderId': 456, // If specified, the call returns all trades associated with the order
1353
+ // 'UserId': integer. The ID of the logged-in user. If not specified, the call returns trades associated with the users belonging to the default account for the logged-in user of this OMS.
1354
+ // 'StartTimeStamp': long integer. The historical date and time at which to begin the trade report, in POSIX format. If not specified, reverts to the start date of this account on the trading venue.
1355
+ // 'EndTimeStamp': long integer. Date at which to end the trade report, in POSIX format.
1356
+ // 'Depth': integer. In this case, the count of trades to return, counting from the StartIndex. If Depth is not specified, returns all trades between BeginTimeStamp and EndTimeStamp, beginning at StartIndex.
1357
+ // 'StartIndex': 0 // from the most recent trade 0 and moving backwards in time
1358
+ // 'ExecutionId': 123, // The ID of the individual buy or sell execution. If not specified, returns all.
1359
+ };
1360
+ let market = undefined;
1361
+ if (symbol !== undefined) {
1362
+ market = this.market (symbol);
1363
+ request['InstrumentId'] = market['id'];
1364
+ }
1365
+ if (since !== undefined) {
1366
+ request['StartTimeStamp'] = parseInt (since / 1000);
1367
+ }
1368
+ if (limit !== undefined) {
1369
+ request['Depth'] = limit;
1370
+ }
1371
+ const response = await this.privateGetGetTradesHistory (this.extend (request, params));
1372
+ //
1373
+ // [
1374
+ // {
1375
+ // "OMSId":1,
1376
+ // "ExecutionId":16916567,
1377
+ // "TradeId":14476351,
1378
+ // "OrderId":2543565231,
1379
+ // "AccountId":449,
1380
+ // "AccountName":"igor@ccxt.trade",
1381
+ // "SubAccountId":0,
1382
+ // "ClientOrderId":0,
1383
+ // "InstrumentId":8,
1384
+ // "Side":"Sell",
1385
+ // "OrderType":"Market",
1386
+ // "Quantity":0.1230000000000000000000000000,
1387
+ // "RemainingQuantity":0.0000000000000000000000000000,
1388
+ // "Price":19069.310000000000000000000000,
1389
+ // "Value":2345.5251300000000000000000000,
1390
+ // "CounterParty":"7",
1391
+ // "OrderTradeRevision":1,
1392
+ // "Direction":"NoChange",
1393
+ // "IsBlockTrade":false,
1394
+ // "Fee":1.1727625650000000000000000000,
1395
+ // "FeeProductId":8,
1396
+ // "OrderOriginator":446,
1397
+ // "UserName":"igor@ccxt.trade",
1398
+ // "TradeTimeMS":1607565031569,
1399
+ // "MakerTaker":"Taker",
1400
+ // "AdapterTradeId":0,
1401
+ // "InsideBid":19069.310000000000000000000000,
1402
+ // "InsideBidSize":0.2400950000000000000000000000,
1403
+ // "InsideAsk":19069.320000000000000000000000,
1404
+ // "InsideAskSize":0.0997360000000000000000000000,
1405
+ // "IsQuote":false,
1406
+ // "CounterPartyClientUserId":1,
1407
+ // "NotionalProductId":2,
1408
+ // "NotionalRate":1.0000000000000000000000000000,
1409
+ // "NotionalValue":2345.5251300000000000000000000,
1410
+ // "NotionalHoldAmount":0,
1411
+ // "TradeTime":637431618315686826
1412
+ // }
1413
+ // ]
1414
+ //
1415
+ return this.parseTrades (response, market, since, limit);
1416
+ }
1417
+
1418
+ async cancelAllOrders (symbol = undefined, params = {}) {
1419
+ const omsId = this.safeInteger (this.options, 'omsId', 1);
1420
+ await this.loadMarkets ();
1421
+ await this.loadAccounts ();
1422
+ const defaultAccountId = this.safeInteger2 (this.options, 'accountId', 'AccountId', parseInt (this.accounts[0]['id']));
1423
+ const accountId = this.safeInteger2 (params, 'accountId', 'AccountId', defaultAccountId);
1424
+ params = this.omit (params, [ 'accountId', 'AccountId' ]);
1425
+ const request = {
1426
+ 'omsId': omsId,
1427
+ 'AccountId': accountId,
1428
+ };
1429
+ if (symbol !== undefined) {
1430
+ const market = this.market (symbol);
1431
+ request['IntrumentId'] = market['id'];
1432
+ }
1433
+ const response = await this.privatePostCancelAllOrders (this.extend (request, params));
1434
+ //
1435
+ // {
1436
+ // "result":true,
1437
+ // "errormsg":null,
1438
+ // "errorcode":0,
1439
+ // "detail":null
1440
+ // }
1441
+ //
1442
+ return response;
1443
+ }
1444
+
1445
+ async cancelOrder (id, symbol = undefined, params = {}) {
1446
+ const omsId = this.safeInteger (this.options, 'omsId', 1);
1447
+ await this.loadMarkets ();
1448
+ await this.loadAccounts ();
1449
+ // const defaultAccountId = this.safeInteger2 (this.options, 'accountId', 'AccountId', parseInt (this.accounts[0]['id']));
1450
+ // const accountId = this.safeInteger2 (params, 'accountId', 'AccountId', defaultAccountId);
1451
+ // params = this.omit (params, [ 'accountId', 'AccountId' ]);
1452
+ let market = undefined;
1453
+ if (symbol !== undefined) {
1454
+ market = this.market (symbol);
1455
+ }
1456
+ const request = {
1457
+ 'omsId': omsId,
1458
+ // 'AccountId': accountId,
1459
+ };
1460
+ const clientOrderId = this.safeInteger2 (params, 'clientOrderId', 'ClOrderId');
1461
+ if (clientOrderId !== undefined) {
1462
+ request['ClOrderId'] = clientOrderId;
1463
+ } else {
1464
+ request['OrderId'] = parseInt (id);
1465
+ }
1466
+ params = this.omit (params, [ 'clientOrderId', 'ClOrderId' ]);
1467
+ const response = await this.privatePostCancelOrder (this.extend (request, params));
1468
+ const order = this.parseOrder (response, market);
1469
+ return this.extend (order, {
1470
+ 'id': id,
1471
+ 'clientOrderId': clientOrderId,
1472
+ });
1473
+ }
1474
+
1475
+ async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
1476
+ const omsId = this.safeInteger (this.options, 'omsId', 1);
1477
+ await this.loadMarkets ();
1478
+ await this.loadAccounts ();
1479
+ const defaultAccountId = this.safeInteger2 (this.options, 'accountId', 'AccountId', parseInt (this.accounts[0]['id']));
1480
+ const accountId = this.safeInteger2 (params, 'accountId', 'AccountId', defaultAccountId);
1481
+ params = this.omit (params, [ 'accountId', 'AccountId' ]);
1482
+ let market = undefined;
1483
+ if (symbol !== undefined) {
1484
+ market = this.market (symbol);
1485
+ }
1486
+ const request = {
1487
+ 'omsId': omsId,
1488
+ 'AccountId': accountId,
1489
+ };
1490
+ const response = await this.privateGetGetOpenOrders (this.extend (request, params));
1491
+ //
1492
+ // [
1493
+ // {
1494
+ // "Side":"Buy",
1495
+ // "OrderId":2543565233,
1496
+ // "Price":19010,
1497
+ // "Quantity":0.345,
1498
+ // "DisplayQuantity":0.345,
1499
+ // "Instrument":8,
1500
+ // "Account":449,
1501
+ // "AccountName":"igor@ccxt.trade",
1502
+ // "OrderType":"Limit",
1503
+ // "ClientOrderId":0,
1504
+ // "OrderState":"Working",
1505
+ // "ReceiveTime":1607579326003,
1506
+ // "ReceiveTimeTicks":637431761260028981,
1507
+ // "LastUpdatedTime":1607579326005,
1508
+ // "LastUpdatedTimeTicks":637431761260054714,
1509
+ // "OrigQuantity":0.345,
1510
+ // "QuantityExecuted":0,
1511
+ // "GrossValueExecuted":0,
1512
+ // "ExecutableValue":0,
1513
+ // "AvgPrice":0,
1514
+ // "CounterPartyId":0,
1515
+ // "ChangeReason":"NewInputAccepted",
1516
+ // "OrigOrderId":2543565233,
1517
+ // "OrigClOrdId":0,
1518
+ // "EnteredBy":446,
1519
+ // "UserName":"igor@ccxt.trade",
1520
+ // "IsQuote":false,
1521
+ // "InsideAsk":19069.32,
1522
+ // "InsideAskSize":0.099736,
1523
+ // "InsideBid":19068.25,
1524
+ // "InsideBidSize":1.330001,
1525
+ // "LastTradePrice":19068.25,
1526
+ // "RejectReason":"",
1527
+ // "IsLockedIn":false,
1528
+ // "CancelReason":"",
1529
+ // "OrderFlag":"AddedToBook",
1530
+ // "UseMargin":false,
1531
+ // "StopPrice":0,
1532
+ // "PegPriceType":"Unknown",
1533
+ // "PegOffset":0,
1534
+ // "PegLimitOffset":0,
1535
+ // "IpAddress":null,
1536
+ // "ClientOrderIdUuid":null,
1537
+ // "OMSId":1
1538
+ // }
1539
+ // ]
1540
+ //
1541
+ return this.parseOrders (response, market, since, limit);
1542
+ }
1543
+
1544
+ async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
1545
+ const omsId = this.safeInteger (this.options, 'omsId', 1);
1546
+ await this.loadMarkets ();
1547
+ await this.loadAccounts ();
1548
+ const defaultAccountId = this.safeInteger2 (this.options, 'accountId', 'AccountId', parseInt (this.accounts[0]['id']));
1549
+ const accountId = this.safeInteger2 (params, 'accountId', 'AccountId', defaultAccountId);
1550
+ params = this.omit (params, [ 'accountId', 'AccountId' ]);
1551
+ const request = {
1552
+ 'omsId': omsId,
1553
+ 'AccountId': accountId,
1554
+ // 'ClientOrderId': clientOrderId,
1555
+ // 'OriginalOrderId': id,
1556
+ // 'OriginalClientOrderId': long integer,
1557
+ // 'UserId': integer,
1558
+ // 'InstrumentId': market['id'],
1559
+ // 'StartTimestamp': since,
1560
+ // 'EndTimestamp': this.milliseconds (),
1561
+ // 'Depth': limit,
1562
+ // 'StartIndex': 0,
1563
+ };
1564
+ let market = undefined;
1565
+ if (symbol !== undefined) {
1566
+ market = this.market (symbol);
1567
+ request['InstrumentId'] = market['id'];
1568
+ }
1569
+ if (since !== undefined) {
1570
+ request['StartTimeStamp'] = parseInt (since / 1000);
1571
+ }
1572
+ if (limit !== undefined) {
1573
+ request['Depth'] = limit;
1574
+ }
1575
+ const response = await this.privateGetGetOrdersHistory (this.extend (request, params));
1576
+ //
1577
+ // [
1578
+ // {
1579
+ // "Side":"Buy",
1580
+ // "OrderId":2543565233,
1581
+ // "Price":19010.000000000000000000000000,
1582
+ // "Quantity":0.0000000000000000000000000000,
1583
+ // "DisplayQuantity":0.3450000000000000000000000000,
1584
+ // "Instrument":8,
1585
+ // "Account":449,
1586
+ // "AccountName":"igor@ccxt.trade",
1587
+ // "OrderType":"Limit",
1588
+ // "ClientOrderId":0,
1589
+ // "OrderState":"Canceled",
1590
+ // "ReceiveTime":1607579326003,
1591
+ // "ReceiveTimeTicks":637431761260028981,
1592
+ // "LastUpdatedTime":1607580965346,
1593
+ // "LastUpdatedTimeTicks":637431777653463754,
1594
+ // "OrigQuantity":0.3450000000000000000000000000,
1595
+ // "QuantityExecuted":0.0000000000000000000000000000,
1596
+ // "GrossValueExecuted":0.0000000000000000000000000000,
1597
+ // "ExecutableValue":0.0000000000000000000000000000,
1598
+ // "AvgPrice":0.0000000000000000000000000000,
1599
+ // "CounterPartyId":0,
1600
+ // "ChangeReason":"UserModified",
1601
+ // "OrigOrderId":2543565233,
1602
+ // "OrigClOrdId":0,
1603
+ // "EnteredBy":446,
1604
+ // "UserName":"igor@ccxt.trade",
1605
+ // "IsQuote":false,
1606
+ // "InsideAsk":19069.320000000000000000000000,
1607
+ // "InsideAskSize":0.0997360000000000000000000000,
1608
+ // "InsideBid":19068.250000000000000000000000,
1609
+ // "InsideBidSize":1.3300010000000000000000000000,
1610
+ // "LastTradePrice":19068.250000000000000000000000,
1611
+ // "RejectReason":"",
1612
+ // "IsLockedIn":false,
1613
+ // "CancelReason":"UserModified",
1614
+ // "OrderFlag":"AddedToBook, RemovedFromBook",
1615
+ // "UseMargin":false,
1616
+ // "StopPrice":0.0000000000000000000000000000,
1617
+ // "PegPriceType":"Unknown",
1618
+ // "PegOffset":0.0000000000000000000000000000,
1619
+ // "PegLimitOffset":0.0000000000000000000000000000,
1620
+ // "IpAddress":"x.x.x.x",
1621
+ // "ClientOrderIdUuid":null,
1622
+ // "OMSId":1
1623
+ // },
1624
+ // ]
1625
+ //
1626
+ return this.parseOrders (response, market, since, limit);
1627
+ }
1628
+
1629
+ async fetchOrder (id, symbol = undefined, params = {}) {
1630
+ const omsId = this.safeInteger (this.options, 'omsId', 1);
1631
+ await this.loadMarkets ();
1632
+ await this.loadAccounts ();
1633
+ const defaultAccountId = this.safeInteger2 (this.options, 'accountId', 'AccountId', parseInt (this.accounts[0]['id']));
1634
+ const accountId = this.safeInteger2 (params, 'accountId', 'AccountId', defaultAccountId);
1635
+ params = this.omit (params, [ 'accountId', 'AccountId' ]);
1636
+ let market = undefined;
1637
+ if (symbol !== undefined) {
1638
+ market = this.market (symbol);
1639
+ }
1640
+ const request = {
1641
+ 'omsId': omsId,
1642
+ 'AccountId': accountId,
1643
+ 'OrderId': parseInt (id),
1644
+ };
1645
+ const response = await this.privateGetGetOrderStatus (this.extend (request, params));
1646
+ //
1647
+ // {
1648
+ // "Side":"Sell",
1649
+ // "OrderId":2543565232,
1650
+ // "Price":0.0000000000000000000000000000,
1651
+ // "Quantity":0.0000000000000000000000000000,
1652
+ // "DisplayQuantity":0.0000000000000000000000000000,
1653
+ // "Instrument":8,
1654
+ // "Account":449,
1655
+ // "AccountName":"igor@ccxt.trade",
1656
+ // "OrderType":"Market",
1657
+ // "ClientOrderId":0,
1658
+ // "OrderState":"FullyExecuted",
1659
+ // "ReceiveTime":1607569475591,
1660
+ // "ReceiveTimeTicks":637431662755912377,
1661
+ // "LastUpdatedTime":1607569475596,
1662
+ // "LastUpdatedTimeTicks":637431662755960902,
1663
+ // "OrigQuantity":1.0000000000000000000000000000,
1664
+ // "QuantityExecuted":1.0000000000000000000000000000,
1665
+ // "GrossValueExecuted":19068.270478610000000000000000,
1666
+ // "ExecutableValue":0.0000000000000000000000000000,
1667
+ // "AvgPrice":19068.270478610000000000000000,
1668
+ // "CounterPartyId":0,
1669
+ // "ChangeReason":"Trade",
1670
+ // "OrigOrderId":2543565232,
1671
+ // "OrigClOrdId":0,
1672
+ // "EnteredBy":446,
1673
+ // "UserName":"igor@ccxt.trade",
1674
+ // "IsQuote":false,
1675
+ // "InsideAsk":19069.320000000000000000000000,
1676
+ // "InsideAskSize":0.0997360000000000000000000000,
1677
+ // "InsideBid":19069.310000000000000000000000,
1678
+ // "InsideBidSize":0.2400950000000000000000000000,
1679
+ // "LastTradePrice":19069.310000000000000000000000,
1680
+ // "RejectReason":"",
1681
+ // "IsLockedIn":false,
1682
+ // "CancelReason":"",
1683
+ // "OrderFlag":"0",
1684
+ // "UseMargin":false,
1685
+ // "StopPrice":0.0000000000000000000000000000,
1686
+ // "PegPriceType":"Unknown",
1687
+ // "PegOffset":0.0000000000000000000000000000,
1688
+ // "PegLimitOffset":0.0000000000000000000000000000,
1689
+ // "IpAddress":"x.x.x.x",
1690
+ // "ClientOrderIdUuid":null,
1691
+ // "OMSId":1
1692
+ // }
1693
+ //
1694
+ return this.parseOrder (response, market);
1695
+ }
1696
+
1697
+ async fetchOrderTrades (id, symbol = undefined, since = undefined, limit = undefined, params = {}) {
1698
+ const omsId = this.safeInteger (this.options, 'omsId', 1);
1699
+ await this.loadMarkets ();
1700
+ await this.loadAccounts ();
1701
+ // const defaultAccountId = this.safeInteger2 (this.options, 'accountId', 'AccountId', parseInt (this.accounts[0]['id']));
1702
+ // const accountId = this.safeInteger2 (params, 'accountId', 'AccountId', defaultAccountId);
1703
+ // params = this.omit (params, [ 'accountId', 'AccountId' ]);
1704
+ let market = undefined;
1705
+ if (symbol !== undefined) {
1706
+ market = this.market (symbol);
1707
+ }
1708
+ const request = {
1709
+ 'OMSId': parseInt (omsId),
1710
+ // 'AccountId': accountId,
1711
+ 'OrderId': parseInt (id),
1712
+ };
1713
+ const response = await this.privatePostGetOrderHistoryByOrderId (this.extend (request, params));
1714
+ //
1715
+ // [
1716
+ // {
1717
+ // "Side":"Sell",
1718
+ // "OrderId":2543565235,
1719
+ // "Price":18600.000000000000000000000000,
1720
+ // "Quantity":0.0000000000000000000000000000,
1721
+ // "DisplayQuantity":0.0000000000000000000000000000,
1722
+ // "Instrument":8,
1723
+ // "Account":449,
1724
+ // "AccountName":"igor@ccxt.trade",
1725
+ // "OrderType":"Limit",
1726
+ // "ClientOrderId":0,
1727
+ // "OrderState":"FullyExecuted",
1728
+ // "ReceiveTime":1607585844956,
1729
+ // "ReceiveTimeTicks":637431826449564182,
1730
+ // "LastUpdatedTime":1607585844959,
1731
+ // "LastUpdatedTimeTicks":637431826449593893,
1732
+ // "OrigQuantity":0.1230000000000000000000000000,
1733
+ // "QuantityExecuted":0.1230000000000000000000000000,
1734
+ // "GrossValueExecuted":2345.3947500000000000000000000,
1735
+ // "ExecutableValue":0.0000000000000000000000000000,
1736
+ // "AvgPrice":19068.250000000000000000000000,
1737
+ // "CounterPartyId":0,
1738
+ // "ChangeReason":"Trade",
1739
+ // "OrigOrderId":2543565235,
1740
+ // "OrigClOrdId":0,
1741
+ // "EnteredBy":446,
1742
+ // "UserName":"igor@ccxt.trade",
1743
+ // "IsQuote":false,
1744
+ // "InsideAsk":19069.320000000000000000000000,
1745
+ // "InsideAskSize":0.0997360000000000000000000000,
1746
+ // "InsideBid":19068.250000000000000000000000,
1747
+ // "InsideBidSize":1.3300010000000000000000000000,
1748
+ // "LastTradePrice":19068.250000000000000000000000,
1749
+ // "RejectReason":"",
1750
+ // "IsLockedIn":false,
1751
+ // "CancelReason":"",
1752
+ // "OrderFlag":"0",
1753
+ // "UseMargin":false,
1754
+ // "StopPrice":0.0000000000000000000000000000,
1755
+ // "PegPriceType":"Unknown",
1756
+ // "PegOffset":0.0000000000000000000000000000,
1757
+ // "PegLimitOffset":0.0000000000000000000000000000,
1758
+ // "IpAddress":"x.x.x.x",
1759
+ // "ClientOrderIdUuid":null,
1760
+ // "OMSId":1
1761
+ // },
1762
+ // ]
1763
+ //
1764
+ const grouped = this.groupBy (response, 'ChangeReason');
1765
+ const trades = this.safeValue (grouped, 'Trade', []);
1766
+ return this.parseTrades (trades, market, since, limit);
1767
+ }
1768
+
1769
+ async fetchDepositAddress (code, params = {}) {
1770
+ const omsId = this.safeInteger (this.options, 'omsId', 1);
1771
+ await this.loadMarkets ();
1772
+ await this.loadAccounts ();
1773
+ const defaultAccountId = this.safeInteger2 (this.options, 'accountId', 'AccountId', parseInt (this.accounts[0]['id']));
1774
+ const accountId = this.safeInteger2 (params, 'accountId', 'AccountId', defaultAccountId);
1775
+ params = this.omit (params, [ 'accountId', 'AccountId' ]);
1776
+ const currency = this.currency (code);
1777
+ const request = {
1778
+ 'omsId': omsId,
1779
+ 'AccountId': accountId,
1780
+ 'ProductId': currency['id'],
1781
+ 'GenerateNewKey': false,
1782
+ };
1783
+ const response = await this.privateGetGetDepositInfo (this.extend (request, params));
1784
+ //
1785
+ // {
1786
+ // "result":true,
1787
+ // "errormsg":null,
1788
+ // "statuscode":0,
1789
+ // "AssetManagerId":1,
1790
+ // "AccountId":57922,
1791
+ // "AssetId":16,
1792
+ // "ProviderId":23,
1793
+ // "DepositInfo":"[\"0x8A27564b5c30b91C93B1591821642420F323a210\"]"
1794
+ // }
1795
+ //
1796
+ return this.parseDepositAddress (response, currency);
1797
+ }
1798
+
1799
+ parseDepositAddress (depositAddress, currency = undefined) {
1800
+ //
1801
+ // fetchDepositAddress, createDepositAddress
1802
+ //
1803
+ // {
1804
+ // "result":true,
1805
+ // "errormsg":null,
1806
+ // "statuscode":0,
1807
+ // "AssetManagerId":1,
1808
+ // "AccountId":449,
1809
+ // "AssetId":1,
1810
+ // "ProviderId":1,
1811
+ // "DepositInfo":"[\"r3e95RwVsLH7yCbnMfyh7SA8FdwUJCB4S2?memo=241452010\"]"
1812
+ // }
1813
+ //
1814
+ const depositInfoString = this.safeString (depositAddress, 'DepositInfo');
1815
+ const depositInfo = JSON.parse (depositInfoString);
1816
+ const depositInfoLength = depositInfo.length;
1817
+ const lastString = this.safeString (depositInfo, depositInfoLength - 1);
1818
+ const parts = lastString.split ('?memo=');
1819
+ const address = this.safeString (parts, 0);
1820
+ const tag = this.safeString (parts, 1);
1821
+ let code = undefined;
1822
+ if (currency !== undefined) {
1823
+ code = currency['code'];
1824
+ }
1825
+ this.checkAddress (address);
1826
+ return {
1827
+ 'currency': code,
1828
+ 'address': address,
1829
+ 'tag': tag,
1830
+ 'network': undefined,
1831
+ 'info': depositAddress,
1832
+ };
1833
+ }
1834
+
1835
+ async createDepositAddress (code, params = {}) {
1836
+ const request = {
1837
+ 'GenerateNewKey': true,
1838
+ };
1839
+ return await this.fetchDepositAddress (code, this.extend (request, params));
1840
+ }
1841
+
1842
+ async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) {
1843
+ const omsId = this.safeInteger (this.options, 'omsId', 1);
1844
+ await this.loadMarkets ();
1845
+ await this.loadAccounts ();
1846
+ const defaultAccountId = this.safeInteger2 (this.options, 'accountId', 'AccountId', parseInt (this.accounts[0]['id']));
1847
+ const accountId = this.safeInteger2 (params, 'accountId', 'AccountId', defaultAccountId);
1848
+ params = this.omit (params, [ 'accountId', 'AccountId' ]);
1849
+ let currency = undefined;
1850
+ if (code !== undefined) {
1851
+ currency = this.currency (code);
1852
+ }
1853
+ const request = {
1854
+ 'omsId': omsId,
1855
+ 'AccountId': accountId,
1856
+ };
1857
+ const response = await this.privateGetGetDeposits (this.extend (request, params));
1858
+ //
1859
+ // [
1860
+ // {
1861
+ // "OMSId":1,
1862
+ // "DepositId":44,
1863
+ // "AccountId":449,
1864
+ // "SubAccountId":0,
1865
+ // "ProductId":4,
1866
+ // "Amount":200.00000000000000000000000000,
1867
+ // "LastUpdateTimeStamp":637431291261187806,
1868
+ // "ProductType":"CryptoCurrency",
1869
+ // "TicketStatus":"FullyProcessed",
1870
+ // "DepositInfo":"{}",
1871
+ // "DepositCode":"ab0e23d5-a9ce-4d94-865f-9ab464fb1de3",
1872
+ // "TicketNumber":71,
1873
+ // "NotionalProductId":13,
1874
+ // "NotionalValue":200.00000000000000000000000000,
1875
+ // "FeeAmount":0.0000000000000000000000000000,
1876
+ // },
1877
+ // ]
1878
+ //
1879
+ return this.parseTransactions (response, currency, since, limit);
1880
+ }
1881
+
1882
+ async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) {
1883
+ const omsId = this.safeInteger (this.options, 'omsId', 1);
1884
+ await this.loadMarkets ();
1885
+ await this.loadAccounts ();
1886
+ const defaultAccountId = this.safeInteger2 (this.options, 'accountId', 'AccountId', parseInt (this.accounts[0]['id']));
1887
+ const accountId = this.safeInteger2 (params, 'accountId', 'AccountId', defaultAccountId);
1888
+ params = this.omit (params, [ 'accountId', 'AccountId' ]);
1889
+ let currency = undefined;
1890
+ if (code !== undefined) {
1891
+ currency = this.currency (code);
1892
+ }
1893
+ const request = {
1894
+ 'omsId': omsId,
1895
+ 'AccountId': accountId,
1896
+ };
1897
+ const response = await this.privateGetGetWithdraws (this.extend (request, params));
1898
+ //
1899
+ // [
1900
+ // {
1901
+ // "Amount": 0.0,
1902
+ // "FeeAmount": 0.0,
1903
+ // "NotionalValue": 0.0,
1904
+ // "WithdrawId": 0,
1905
+ // "AssetManagerId": 0,
1906
+ // "AccountId": 0,
1907
+ // "AssetId": 0,
1908
+ // "TemplateForm": "{\"TemplateType\": \"TetherRPCWithdraw\",\"Comment\": \"TestWithdraw\",\"ExternalAddress\": \"ms6C3pKAAr8gRCcnVebs8VRkVrjcvqNYv3\"}",
1909
+ // "TemplateFormType": "TetherRPCWithdraw",
1910
+ // "omsId": 0,
1911
+ // "TicketStatus": 0,
1912
+ // "TicketNumber": 0,
1913
+ // "WithdrawTransactionDetails": "",
1914
+ // "WithdrawType": "",
1915
+ // "WithdrawCode": "490b4fa3-53fc-44f4-bd29-7e16be86fba3",
1916
+ // "AssetType": 0,
1917
+ // "Reaccepted": true,
1918
+ // "NotionalProductId": 0
1919
+ // },
1920
+ // ]
1921
+ //
1922
+ return this.parseTransactions (response, currency, since, limit);
1923
+ }
1924
+
1925
+ parseTransactionStatusByType (status, type = undefined) {
1926
+ const statusesByType = {
1927
+ 'deposit': {
1928
+ 'New': 'pending', // new ticket awaiting operator review
1929
+ 'AdminProcessing': 'pending', // an admin is looking at the ticket
1930
+ 'Accepted': 'pending', // an admin accepts the ticket
1931
+ 'Rejected': 'rejected', // admin rejects the ticket
1932
+ 'SystemProcessing': 'pending', // automatic processing; an unlikely status for a deposit
1933
+ 'FullyProcessed': 'ok', // the deposit has concluded
1934
+ 'Failed': 'failed', // the deposit has failed for some reason
1935
+ 'Pending': 'pending', // Account Provider has set status to pending
1936
+ 'Confirmed': 'pending', // Account Provider confirms the deposit
1937
+ 'AmlProcessing': 'pending', // anti-money-laundering process underway
1938
+ 'AmlAccepted': 'pending', // anti-money-laundering process successful
1939
+ 'AmlRejected': 'rejected', // deposit did not stand up to anti-money-laundering process
1940
+ 'AmlFailed': 'failed', // anti-money-laundering process failed/did not complete
1941
+ 'LimitsAccepted': 'pending', // deposit meets limits for fiat or crypto asset
1942
+ 'LimitsRejected': 'rejected', // deposit does not meet limits for fiat or crypto asset
1943
+ },
1944
+ 'withdrawal': {
1945
+ 'New': 'pending', // awaiting operator review
1946
+ 'AdminProcessing': 'pending', // An admin is looking at the ticket
1947
+ 'Accepted': 'pending', // withdrawal will proceed
1948
+ 'Rejected': 'rejected', // admin or automatic rejection
1949
+ 'SystemProcessing': 'pending', // automatic processing underway
1950
+ 'FullyProcessed': 'ok', // the withdrawal has concluded
1951
+ 'Failed': 'failed', // the withdrawal failed for some reason
1952
+ 'Pending': 'pending', // the admin has placed the withdrawal in pending status
1953
+ 'Pending2Fa': 'pending', // user must click 2-factor authentication confirmation link
1954
+ 'AutoAccepted': 'pending', // withdrawal will be automatically processed
1955
+ 'Delayed': 'pending', // waiting for funds to be allocated for the withdrawal
1956
+ 'UserCanceled': 'canceled', // withdraw canceled by user or Superuser
1957
+ 'AdminCanceled': 'canceled', // withdraw canceled by Superuser
1958
+ 'AmlProcessing': 'pending', // anti-money-laundering process underway
1959
+ 'AmlAccepted': 'pending', // anti-money-laundering process complete
1960
+ 'AmlRejected': 'rejected', // withdrawal did not stand up to anti-money-laundering process
1961
+ 'AmlFailed': 'failed', // withdrawal did not complete anti-money-laundering process
1962
+ 'LimitsAccepted': 'pending', // withdrawal meets limits for fiat or crypto asset
1963
+ 'LimitsRejected': 'rejected', // withdrawal does not meet limits for fiat or crypto asset
1964
+ 'Submitted': 'pending', // withdrawal sent to Account Provider; awaiting blockchain confirmation
1965
+ 'Confirmed': 'pending', // Account Provider confirms that withdrawal is on the blockchain
1966
+ 'ManuallyConfirmed': 'pending', // admin has sent withdrawal via wallet or admin function directly; marks ticket as FullyProcessed; debits account
1967
+ 'Confirmed2Fa': 'pending', // user has confirmed withdraw via 2-factor authentication.
1968
+ },
1969
+ };
1970
+ const statuses = this.safeValue (statusesByType, type, {});
1971
+ return this.safeString (statuses, status, status);
1972
+ }
1973
+
1974
+ parseTransaction (transaction, currency = undefined) {
1975
+ //
1976
+ // fetchDeposits
1977
+ //
1978
+ // {
1979
+ // "OMSId":1,
1980
+ // "DepositId":44,
1981
+ // "AccountId":449,
1982
+ // "SubAccountId":0,
1983
+ // "ProductId":4,
1984
+ // "Amount":200.00000000000000000000000000,
1985
+ // "LastUpdateTimeStamp":637431291261187806,
1986
+ // "ProductType":"CryptoCurrency",
1987
+ // "TicketStatus":"FullyProcessed",
1988
+ // "DepositInfo":"{}",
1989
+ // "DepositCode":"ab0e23d5-a9ce-4d94-865f-9ab464fb1de3",
1990
+ // "TicketNumber":71,
1991
+ // "NotionalProductId":13,
1992
+ // "NotionalValue":200.00000000000000000000000000,
1993
+ // "FeeAmount":0.0000000000000000000000000000,
1994
+ // }
1995
+ //
1996
+ // fetchWithdrawals
1997
+ //
1998
+ // {
1999
+ // "Amount": 0.0,
2000
+ // "FeeAmount": 0.0,
2001
+ // "NotionalValue": 0.0,
2002
+ // "WithdrawId": 0,
2003
+ // "AssetManagerId": 0,
2004
+ // "AccountId": 0,
2005
+ // "AssetId": 0,
2006
+ // "TemplateForm": "{\"TemplateType\": \"TetherRPCWithdraw\",\"Comment\": \"TestWithdraw\",\"ExternalAddress\": \"ms6C3pKAAr8gRCcnVebs8VRkVrjcvqNYv3\"}",
2007
+ // "TemplateFormType": "TetherRPCWithdraw",
2008
+ // "omsId": 0,
2009
+ // "TicketStatus": 0,
2010
+ // "TicketNumber": 0,
2011
+ // "WithdrawTransactionDetails": "",
2012
+ // "WithdrawType": "",
2013
+ // "WithdrawCode": "490b4fa3-53fc-44f4-bd29-7e16be86fba3",
2014
+ // "AssetType": 0,
2015
+ // "Reaccepted": true,
2016
+ // "NotionalProductId": 0
2017
+ // }
2018
+ //
2019
+ let id = undefined;
2020
+ let txid = undefined;
2021
+ const currencyId = this.safeString (transaction, 'ProductId');
2022
+ const code = this.safeCurrencyCode (currencyId, currency);
2023
+ let timestamp = undefined;
2024
+ let type = undefined;
2025
+ if ('DepositId' in transaction) {
2026
+ id = this.safeString (transaction, 'DepositId');
2027
+ type = 'deposit';
2028
+ } else if ('WithdrawId' in transaction) {
2029
+ id = this.safeString (transaction, 'WithdrawId');
2030
+ type = 'withdrawal';
2031
+ }
2032
+ const templateFormString = this.safeString (transaction, 'TemplateForm');
2033
+ let address = undefined;
2034
+ let updated = this.safeInteger (transaction, 'LastUpdateTimeStamp');
2035
+ if (templateFormString !== undefined) {
2036
+ const templateForm = JSON.parse (templateFormString);
2037
+ address = this.safeString (templateForm, 'ExternalAddress');
2038
+ txid = this.safeString (templateForm, 'TxId');
2039
+ timestamp = this.safeInteger (templateForm, 'TimeSubmitted');
2040
+ updated = this.safeInteger (templateForm, 'LastUpdated', updated);
2041
+ }
2042
+ const addressTo = address;
2043
+ const status = this.parseTransactionStatusByType (this.safeString (transaction, 'TicketStatus'), type);
2044
+ const amount = this.safeNumber (transaction, 'Amount');
2045
+ const feeCost = this.safeNumber (transaction, 'FeeAmount');
2046
+ let fee = undefined;
2047
+ if (feeCost !== undefined) {
2048
+ fee = { 'currency': code, 'cost': feeCost };
2049
+ }
2050
+ return {
2051
+ 'info': transaction,
2052
+ 'id': id,
2053
+ 'txid': txid,
2054
+ 'timestamp': timestamp,
2055
+ 'datetime': this.iso8601 (timestamp),
2056
+ 'address': address,
2057
+ 'addressTo': addressTo,
2058
+ 'addressFrom': undefined,
2059
+ 'tag': undefined,
2060
+ 'tagTo': undefined,
2061
+ 'tagFrom': undefined,
2062
+ 'type': type,
2063
+ 'amount': amount,
2064
+ 'currency': code,
2065
+ 'status': status,
2066
+ 'updated': updated,
2067
+ 'fee': fee,
2068
+ };
2069
+ }
2070
+
2071
+ async withdraw (code, amount, address, tag = undefined, params = {}) {
2072
+ [ tag, params ] = this.handleWithdrawTagAndParams (tag, params);
2073
+ // this method required login, password and twofa key
2074
+ const sessionToken = this.safeString (this.options, 'sessionToken');
2075
+ if (sessionToken === undefined) {
2076
+ throw new AuthenticationError (this.id + ' call signIn() method to obtain a session token');
2077
+ }
2078
+ if (this.twofa === undefined) {
2079
+ throw new AuthenticationError (this.id + ' withdraw() requires exchange.twofa credentials');
2080
+ }
2081
+ this.checkAddress (address);
2082
+ const omsId = this.safeInteger (this.options, 'omsId', 1);
2083
+ await this.loadMarkets ();
2084
+ await this.loadAccounts ();
2085
+ const defaultAccountId = this.safeInteger2 (this.options, 'accountId', 'AccountId', parseInt (this.accounts[0]['id']));
2086
+ const accountId = this.safeInteger2 (params, 'accountId', 'AccountId', defaultAccountId);
2087
+ params = this.omit (params, [ 'accountId', 'AccountId' ]);
2088
+ const currency = this.currency (code);
2089
+ const withdrawTemplateTypesRequest = {
2090
+ 'omsId': omsId,
2091
+ 'AccountId': accountId,
2092
+ 'ProductId': currency['id'],
2093
+ };
2094
+ const withdrawTemplateTypesResponse = await this.privateGetGetWithdrawTemplateTypes (withdrawTemplateTypesRequest);
2095
+ //
2096
+ // {
2097
+ // result: true,
2098
+ // errormsg: null,
2099
+ // statuscode: "0",
2100
+ // TemplateTypes: [
2101
+ // { AccountProviderId: "14", TemplateName: "ToExternalBitcoinAddress", AccountProviderName: "BitgoRPC-BTC" },
2102
+ // { AccountProviderId: "20", TemplateName: "ToExternalBitcoinAddress", AccountProviderName: "TrezorBTC" },
2103
+ // { AccountProviderId: "31", TemplateName: "BTC", AccountProviderName: "BTC Fireblocks 1" }
2104
+ // ]
2105
+ // }
2106
+ //
2107
+ const templateTypes = this.safeValue (withdrawTemplateTypesResponse, 'TemplateTypes', []);
2108
+ const firstTemplateType = this.safeValue (templateTypes, 0);
2109
+ if (firstTemplateType === undefined) {
2110
+ throw new ExchangeError (this.id + ' withdraw() could not find a withdraw template type for ' + currency['code']);
2111
+ }
2112
+ const templateName = this.safeString (firstTemplateType, 'TemplateName');
2113
+ const withdrawTemplateRequest = {
2114
+ 'omsId': omsId,
2115
+ 'AccountId': accountId,
2116
+ 'ProductId': currency['id'],
2117
+ 'TemplateType': templateName,
2118
+ 'AccountProviderId': firstTemplateType['AccountProviderId'],
2119
+ };
2120
+ const withdrawTemplateResponse = await this.privateGetGetWithdrawTemplate (withdrawTemplateRequest);
2121
+ //
2122
+ // {
2123
+ // result: true,
2124
+ // errormsg: null,
2125
+ // statuscode: "0",
2126
+ // Template: "{\"TemplateType\":\"ToExternalBitcoinAddress\",\"Comment\":\"\",\"ExternalAddress\":\"\"}"
2127
+ // }
2128
+ //
2129
+ const template = this.safeString (withdrawTemplateResponse, 'Template');
2130
+ if (template === undefined) {
2131
+ throw new ExchangeError (this.id + ' withdraw() could not find a withdraw template for ' + currency['code']);
2132
+ }
2133
+ const withdrawTemplate = JSON.parse (template);
2134
+ withdrawTemplate['ExternalAddress'] = address;
2135
+ if (tag !== undefined) {
2136
+ if ('Memo' in withdrawTemplate) {
2137
+ withdrawTemplate['Memo'] = tag;
2138
+ }
2139
+ }
2140
+ const withdrawPayload = {
2141
+ 'omsId': omsId,
2142
+ 'AccountId': accountId,
2143
+ 'ProductId': currency['id'],
2144
+ 'TemplateForm': this.json (withdrawTemplate),
2145
+ 'TemplateType': templateName,
2146
+ };
2147
+ const withdrawRequest = {
2148
+ 'TfaType': 'Google',
2149
+ 'TFaCode': this.oath (),
2150
+ 'Payload': this.json (withdrawPayload),
2151
+ };
2152
+ const response = await this.privatePostCreateWithdrawTicket (this.deepExtend (withdrawRequest, params));
2153
+ return this.parseTransaction (response, currency);
2154
+ }
2155
+
2156
+ nonce () {
2157
+ return this.milliseconds ();
2158
+ }
2159
+
2160
+ sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
2161
+ let url = this.urls['api'][api] + '/' + this.implodeParams (path, params);
2162
+ let query = this.omit (params, this.extractParams (path));
2163
+ if (api === 'public') {
2164
+ if (path === 'Authenticate') {
2165
+ const auth = this.login + ':' + this.password;
2166
+ const auth64 = this.stringToBase64 (auth);
2167
+ headers = {
2168
+ 'Authorization': 'Basic ' + this.decode (auth64),
2169
+ // 'Content-Type': 'application/json',
2170
+ };
2171
+ } else if (path === 'Authenticate2FA') {
2172
+ const pending2faToken = this.safeString (this.options, 'pending2faToken');
2173
+ if (pending2faToken !== undefined) {
2174
+ headers = {
2175
+ 'Pending2FaToken': pending2faToken,
2176
+ // 'Content-Type': 'application/json',
2177
+ };
2178
+ query = this.omit (query, 'pending2faToken');
2179
+ }
2180
+ }
2181
+ if (Object.keys (query).length) {
2182
+ url += '?' + this.urlencode (query);
2183
+ }
2184
+ } else if (api === 'private') {
2185
+ this.checkRequiredCredentials ();
2186
+ const sessionToken = this.safeString (this.options, 'sessionToken');
2187
+ if (sessionToken === undefined) {
2188
+ const nonce = this.nonce ().toString ();
2189
+ const auth = nonce + this.uid + this.apiKey;
2190
+ const signature = this.hmac (this.encode (auth), this.encode (this.secret));
2191
+ headers = {
2192
+ 'Nonce': nonce,
2193
+ 'APIKey': this.apiKey,
2194
+ 'Signature': signature,
2195
+ 'UserId': this.uid,
2196
+ };
2197
+ } else {
2198
+ headers = {
2199
+ 'APToken': sessionToken,
2200
+ };
2201
+ }
2202
+ if (method === 'POST') {
2203
+ headers['Content-Type'] = 'application/json';
2204
+ body = this.json (query);
2205
+ } else {
2206
+ if (Object.keys (query).length) {
2207
+ url += '?' + this.urlencode (query);
2208
+ }
2209
+ }
2210
+ }
2211
+ return { 'url': url, 'method': method, 'body': body, 'headers': headers };
2212
+ }
2213
+
2214
+ handleErrors (code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
2215
+ if (code === 404) {
2216
+ throw new AuthenticationError (this.id + ' ' + body);
2217
+ }
2218
+ if (response === undefined) {
2219
+ return;
2220
+ }
2221
+ //
2222
+ // {"status":"Rejected","errormsg":"Not_Enough_Funds","errorcode":101}
2223
+ // {"result":false,"errormsg":"Server Error","errorcode":102,"detail":null}
2224
+ //
2225
+ const message = this.safeString (response, 'errormsg');
2226
+ if ((message !== undefined) && (message !== '')) {
2227
+ const feedback = this.id + ' ' + body;
2228
+ this.throwExactlyMatchedException (this.exceptions['exact'], message, feedback);
2229
+ this.throwBroadlyMatchedException (this.exceptions['broad'], body, feedback);
2230
+ throw new ExchangeError (feedback);
2231
+ }
2232
+ }
2233
+ };