ccxt-ir 4.3.46.0.1__py2.py3-none-any.whl

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 (772) hide show
  1. ccxt/__init__.py +358 -0
  2. ccxt/abantether.py +316 -0
  3. ccxt/abstract/__init__.py +0 -0
  4. ccxt/abstract/abantether.py +5 -0
  5. ccxt/abstract/ace.py +15 -0
  6. ccxt/abstract/afratether.py +6 -0
  7. ccxt/abstract/alpaca.py +70 -0
  8. ccxt/abstract/arzinja.py +5 -0
  9. ccxt/abstract/arzplus.py +7 -0
  10. ccxt/abstract/ascendex.py +77 -0
  11. ccxt/abstract/bequant.py +115 -0
  12. ccxt/abstract/bigone.py +45 -0
  13. ccxt/abstract/binance.py +712 -0
  14. ccxt/abstract/binancecoinm.py +712 -0
  15. ccxt/abstract/binanceus.py +764 -0
  16. ccxt/abstract/binanceusdm.py +712 -0
  17. ccxt/abstract/bingx.py +113 -0
  18. ccxt/abstract/bit2c.py +27 -0
  19. ccxt/abstract/bitbank.py +27 -0
  20. ccxt/abstract/bitbay.py +53 -0
  21. ccxt/abstract/bitbns.py +40 -0
  22. ccxt/abstract/bitcoincom.py +115 -0
  23. ccxt/abstract/bitfinex.py +69 -0
  24. ccxt/abstract/bitfinex2.py +139 -0
  25. ccxt/abstract/bitflyer.py +38 -0
  26. ccxt/abstract/bitget.py +508 -0
  27. ccxt/abstract/bithumb.py +32 -0
  28. ccxt/abstract/bitimen.py +7 -0
  29. ccxt/abstract/bitir.py +7 -0
  30. ccxt/abstract/bitmart.py +99 -0
  31. ccxt/abstract/bitmex.py +97 -0
  32. ccxt/abstract/bitopro.py +29 -0
  33. ccxt/abstract/bitpanda.py +35 -0
  34. ccxt/abstract/bitpin.py +7 -0
  35. ccxt/abstract/bitrue.py +72 -0
  36. ccxt/abstract/bitso.py +43 -0
  37. ccxt/abstract/bitstamp.py +258 -0
  38. ccxt/abstract/bitteam.py +29 -0
  39. ccxt/abstract/bitvavo.py +27 -0
  40. ccxt/abstract/bl3p.py +19 -0
  41. ccxt/abstract/blockchaincom.py +28 -0
  42. ccxt/abstract/blofin.py +37 -0
  43. ccxt/abstract/btcalpha.py +18 -0
  44. ccxt/abstract/btcbox.py +13 -0
  45. ccxt/abstract/btcmarkets.py +39 -0
  46. ccxt/abstract/btcturk.py +20 -0
  47. ccxt/abstract/bybit.py +298 -0
  48. ccxt/abstract/cex.py +33 -0
  49. ccxt/abstract/coinbase.py +94 -0
  50. ccxt/abstract/coinbaseadvanced.py +94 -0
  51. ccxt/abstract/coinbaseexchange.py +67 -0
  52. ccxt/abstract/coinbaseinternational.py +39 -0
  53. ccxt/abstract/coincatch.py +94 -0
  54. ccxt/abstract/coincheck.py +33 -0
  55. ccxt/abstract/coinex.py +237 -0
  56. ccxt/abstract/coinlist.py +54 -0
  57. ccxt/abstract/coinmate.py +62 -0
  58. ccxt/abstract/coinmetro.py +34 -0
  59. ccxt/abstract/coinone.py +67 -0
  60. ccxt/abstract/coinsph.py +54 -0
  61. ccxt/abstract/coinspot.py +28 -0
  62. ccxt/abstract/cryptocom.py +107 -0
  63. ccxt/abstract/currencycom.py +68 -0
  64. ccxt/abstract/delta.py +50 -0
  65. ccxt/abstract/deribit.py +125 -0
  66. ccxt/abstract/digifinex.py +91 -0
  67. ccxt/abstract/eterex.py +5 -0
  68. ccxt/abstract/excoino.py +7 -0
  69. ccxt/abstract/exir.py +8 -0
  70. ccxt/abstract/exmo.py +55 -0
  71. ccxt/abstract/exnovin.py +6 -0
  72. ccxt/abstract/farhadexchange.py +5 -0
  73. ccxt/abstract/fmfwio.py +115 -0
  74. ccxt/abstract/gate.py +265 -0
  75. ccxt/abstract/gateio.py +265 -0
  76. ccxt/abstract/gemini.py +58 -0
  77. ccxt/abstract/hashkey.py +67 -0
  78. ccxt/abstract/hitbtc.py +115 -0
  79. ccxt/abstract/hitbtc3.py +115 -0
  80. ccxt/abstract/hitobit.py +8 -0
  81. ccxt/abstract/hollaex.py +33 -0
  82. ccxt/abstract/htx.py +548 -0
  83. ccxt/abstract/huobi.py +548 -0
  84. ccxt/abstract/huobijp.py +114 -0
  85. ccxt/abstract/hyperliquid.py +6 -0
  86. ccxt/abstract/idex.py +26 -0
  87. ccxt/abstract/independentreserve.py +37 -0
  88. ccxt/abstract/indodax.py +26 -0
  89. ccxt/abstract/jibitex.py +7 -0
  90. ccxt/abstract/kraken.py +57 -0
  91. ccxt/abstract/krakenfutures.py +38 -0
  92. ccxt/abstract/kucoin.py +214 -0
  93. ccxt/abstract/kucoinfutures.py +233 -0
  94. ccxt/abstract/kuna.py +182 -0
  95. ccxt/abstract/latoken.py +56 -0
  96. ccxt/abstract/lbank.py +61 -0
  97. ccxt/abstract/luno.py +37 -0
  98. ccxt/abstract/lykke.py +29 -0
  99. ccxt/abstract/mercado.py +25 -0
  100. ccxt/abstract/mexc.py +178 -0
  101. ccxt/abstract/ndax.py +97 -0
  102. ccxt/abstract/nobitex.py +7 -0
  103. ccxt/abstract/novadax.py +29 -0
  104. ccxt/abstract/oceanex.py +22 -0
  105. ccxt/abstract/okcoin.py +74 -0
  106. ccxt/abstract/okexchange.py +8 -0
  107. ccxt/abstract/okx.py +324 -0
  108. ccxt/abstract/ompfinex.py +7 -0
  109. ccxt/abstract/onetrading.py +35 -0
  110. ccxt/abstract/oxfun.py +34 -0
  111. ccxt/abstract/p2b.py +22 -0
  112. ccxt/abstract/paradex.py +40 -0
  113. ccxt/abstract/paymium.py +28 -0
  114. ccxt/abstract/phemex.py +115 -0
  115. ccxt/abstract/poloniex.py +69 -0
  116. ccxt/abstract/poloniexfutures.py +48 -0
  117. ccxt/abstract/probit.py +23 -0
  118. ccxt/abstract/ramzinex.py +7 -0
  119. ccxt/abstract/sarmayex.py +5 -0
  120. ccxt/abstract/sarrafex.py +7 -0
  121. ccxt/abstract/tabdeal.py +7 -0
  122. ccxt/abstract/tetherland.py +5 -0
  123. ccxt/abstract/timex.py +62 -0
  124. ccxt/abstract/tokocrypto.py +37 -0
  125. ccxt/abstract/tradeogre.py +16 -0
  126. ccxt/abstract/twox.py +5 -0
  127. ccxt/abstract/ubitex.py +7 -0
  128. ccxt/abstract/upbit.py +38 -0
  129. ccxt/abstract/vertex.py +19 -0
  130. ccxt/abstract/wallex.py +8 -0
  131. ccxt/abstract/wavesexchange.py +154 -0
  132. ccxt/abstract/wazirx.py +30 -0
  133. ccxt/abstract/whitebit.py +98 -0
  134. ccxt/abstract/woo.py +83 -0
  135. ccxt/abstract/woofipro.py +119 -0
  136. ccxt/abstract/xt.py +152 -0
  137. ccxt/abstract/yobit.py +16 -0
  138. ccxt/abstract/zaif.py +38 -0
  139. ccxt/abstract/zonda.py +53 -0
  140. ccxt/ace.py +1012 -0
  141. ccxt/afratether.py +293 -0
  142. ccxt/alpaca.py +1083 -0
  143. ccxt/arzinja.py +285 -0
  144. ccxt/arzplus.py +412 -0
  145. ccxt/ascendex.py +3330 -0
  146. ccxt/async_support/__init__.py +337 -0
  147. ccxt/async_support/abantether.py +316 -0
  148. ccxt/async_support/ace.py +1012 -0
  149. ccxt/async_support/afratether.py +293 -0
  150. ccxt/async_support/alpaca.py +1083 -0
  151. ccxt/async_support/arzinja.py +285 -0
  152. ccxt/async_support/arzplus.py +412 -0
  153. ccxt/async_support/ascendex.py +3330 -0
  154. ccxt/async_support/base/__init__.py +1 -0
  155. ccxt/async_support/base/exchange.py +1966 -0
  156. ccxt/async_support/base/throttler.py +50 -0
  157. ccxt/async_support/base/ws/__init__.py +38 -0
  158. ccxt/async_support/base/ws/aiohttp_client.py +125 -0
  159. ccxt/async_support/base/ws/cache.py +212 -0
  160. ccxt/async_support/base/ws/client.py +193 -0
  161. ccxt/async_support/base/ws/fast_client.py +96 -0
  162. ccxt/async_support/base/ws/functions.py +59 -0
  163. ccxt/async_support/base/ws/future.py +58 -0
  164. ccxt/async_support/base/ws/order_book.py +78 -0
  165. ccxt/async_support/base/ws/order_book_side.py +174 -0
  166. ccxt/async_support/bequant.py +33 -0
  167. ccxt/async_support/bigone.py +2113 -0
  168. ccxt/async_support/binance.py +12234 -0
  169. ccxt/async_support/binancecoinm.py +45 -0
  170. ccxt/async_support/binanceus.py +211 -0
  171. ccxt/async_support/binanceusdm.py +58 -0
  172. ccxt/async_support/bingx.py +4325 -0
  173. ccxt/async_support/bit2c.py +866 -0
  174. ccxt/async_support/bitbank.py +1001 -0
  175. ccxt/async_support/bitbay.py +17 -0
  176. ccxt/async_support/bitbns.py +1154 -0
  177. ccxt/async_support/bitcoincom.py +17 -0
  178. ccxt/async_support/bitfinex.py +1617 -0
  179. ccxt/async_support/bitfinex2.py +3552 -0
  180. ccxt/async_support/bitflyer.py +995 -0
  181. ccxt/async_support/bitget.py +8273 -0
  182. ccxt/async_support/bithumb.py +1061 -0
  183. ccxt/async_support/bitimen.py +401 -0
  184. ccxt/async_support/bitir.py +490 -0
  185. ccxt/async_support/bitmart.py +4415 -0
  186. ccxt/async_support/bitmex.py +2756 -0
  187. ccxt/async_support/bitopro.py +1630 -0
  188. ccxt/async_support/bitpanda.py +16 -0
  189. ccxt/async_support/bitpin.py +454 -0
  190. ccxt/async_support/bitrue.py +3027 -0
  191. ccxt/async_support/bitso.py +1670 -0
  192. ccxt/async_support/bitstamp.py +2203 -0
  193. ccxt/async_support/bitteam.py +2239 -0
  194. ccxt/async_support/bitvavo.py +1968 -0
  195. ccxt/async_support/bl3p.py +485 -0
  196. ccxt/async_support/blockchaincom.py +1104 -0
  197. ccxt/async_support/blofin.py +2066 -0
  198. ccxt/async_support/btcalpha.py +891 -0
  199. ccxt/async_support/btcbox.py +544 -0
  200. ccxt/async_support/btcmarkets.py +1221 -0
  201. ccxt/async_support/btcturk.py +911 -0
  202. ccxt/async_support/bybit.py +8159 -0
  203. ccxt/async_support/cex.py +1605 -0
  204. ccxt/async_support/coinbase.py +4475 -0
  205. ccxt/async_support/coinbaseadvanced.py +17 -0
  206. ccxt/async_support/coinbaseexchange.py +1734 -0
  207. ccxt/async_support/coinbaseinternational.py +1899 -0
  208. ccxt/async_support/coincatch.py +5069 -0
  209. ccxt/async_support/coincheck.py +815 -0
  210. ccxt/async_support/coinex.py +5526 -0
  211. ccxt/async_support/coinlist.py +2243 -0
  212. ccxt/async_support/coinmate.py +1067 -0
  213. ccxt/async_support/coinmetro.py +1797 -0
  214. ccxt/async_support/coinone.py +1127 -0
  215. ccxt/async_support/coinsph.py +1850 -0
  216. ccxt/async_support/coinspot.py +534 -0
  217. ccxt/async_support/cryptocom.py +2822 -0
  218. ccxt/async_support/currencycom.py +1950 -0
  219. ccxt/async_support/delta.py +3376 -0
  220. ccxt/async_support/deribit.py +3437 -0
  221. ccxt/async_support/digifinex.py +3960 -0
  222. ccxt/async_support/eterex.py +286 -0
  223. ccxt/async_support/excoino.py +399 -0
  224. ccxt/async_support/exir.py +375 -0
  225. ccxt/async_support/exmo.py +2462 -0
  226. ccxt/async_support/exnovin.py +360 -0
  227. ccxt/async_support/farhadexchange.py +266 -0
  228. ccxt/async_support/fmfwio.py +34 -0
  229. ccxt/async_support/gate.py +6976 -0
  230. ccxt/async_support/gateio.py +16 -0
  231. ccxt/async_support/gemini.py +1825 -0
  232. ccxt/async_support/hashkey.py +4150 -0
  233. ccxt/async_support/hitbtc.py +3423 -0
  234. ccxt/async_support/hitbtc3.py +16 -0
  235. ccxt/async_support/hitobit.py +391 -0
  236. ccxt/async_support/hollaex.py +1813 -0
  237. ccxt/async_support/htx.py +8506 -0
  238. ccxt/async_support/huobi.py +16 -0
  239. ccxt/async_support/huobijp.py +1801 -0
  240. ccxt/async_support/hyperliquid.py +2431 -0
  241. ccxt/async_support/idex.py +1766 -0
  242. ccxt/async_support/independentreserve.py +784 -0
  243. ccxt/async_support/indodax.py +1247 -0
  244. ccxt/async_support/jibitex.py +395 -0
  245. ccxt/async_support/kraken.py +2894 -0
  246. ccxt/async_support/krakenfutures.py +2601 -0
  247. ccxt/async_support/kucoin.py +4602 -0
  248. ccxt/async_support/kucoinfutures.py +2698 -0
  249. ccxt/async_support/kuna.py +1841 -0
  250. ccxt/async_support/latoken.py +1664 -0
  251. ccxt/async_support/lbank.py +2683 -0
  252. ccxt/async_support/luno.py +1067 -0
  253. ccxt/async_support/lykke.py +1270 -0
  254. ccxt/async_support/mercado.py +842 -0
  255. ccxt/async_support/mexc.py +5369 -0
  256. ccxt/async_support/ndax.py +2354 -0
  257. ccxt/async_support/nobitex.py +419 -0
  258. ccxt/async_support/novadax.py +1484 -0
  259. ccxt/async_support/oceanex.py +903 -0
  260. ccxt/async_support/okcoin.py +2936 -0
  261. ccxt/async_support/okexchange.py +349 -0
  262. ccxt/async_support/okx.py +7827 -0
  263. ccxt/async_support/ompfinex.py +472 -0
  264. ccxt/async_support/onetrading.py +1911 -0
  265. ccxt/async_support/oxfun.py +2773 -0
  266. ccxt/async_support/p2b.py +1194 -0
  267. ccxt/async_support/paradex.py +2015 -0
  268. ccxt/async_support/paymium.py +564 -0
  269. ccxt/async_support/phemex.py +4473 -0
  270. ccxt/async_support/poloniex.py +2232 -0
  271. ccxt/async_support/poloniexfutures.py +1717 -0
  272. ccxt/async_support/probit.py +1734 -0
  273. ccxt/async_support/ramzinex.py +476 -0
  274. ccxt/async_support/sarmayex.py +357 -0
  275. ccxt/async_support/sarrafex.py +478 -0
  276. ccxt/async_support/tabdeal.py +364 -0
  277. ccxt/async_support/tetherland.py +349 -0
  278. ccxt/async_support/timex.py +1593 -0
  279. ccxt/async_support/tokocrypto.py +2405 -0
  280. ccxt/async_support/tradeogre.py +608 -0
  281. ccxt/async_support/twox.py +326 -0
  282. ccxt/async_support/ubitex.py +409 -0
  283. ccxt/async_support/upbit.py +1833 -0
  284. ccxt/async_support/vertex.py +2922 -0
  285. ccxt/async_support/wallex.py +445 -0
  286. ccxt/async_support/wavesexchange.py +2473 -0
  287. ccxt/async_support/wazirx.py +1224 -0
  288. ccxt/async_support/whitebit.py +2469 -0
  289. ccxt/async_support/woo.py +3114 -0
  290. ccxt/async_support/woofipro.py +2533 -0
  291. ccxt/async_support/xt.py +4454 -0
  292. ccxt/async_support/yobit.py +1283 -0
  293. ccxt/async_support/zaif.py +725 -0
  294. ccxt/async_support/zonda.py +1828 -0
  295. ccxt/base/__init__.py +27 -0
  296. ccxt/base/decimal_to_precision.py +174 -0
  297. ccxt/base/errors.py +242 -0
  298. ccxt/base/exchange.py +5941 -0
  299. ccxt/base/precise.py +287 -0
  300. ccxt/base/types.py +502 -0
  301. ccxt/bequant.py +33 -0
  302. ccxt/bigone.py +2112 -0
  303. ccxt/binance.py +12233 -0
  304. ccxt/binancecoinm.py +45 -0
  305. ccxt/binanceus.py +211 -0
  306. ccxt/binanceusdm.py +58 -0
  307. ccxt/bingx.py +4324 -0
  308. ccxt/bit2c.py +866 -0
  309. ccxt/bitbank.py +1001 -0
  310. ccxt/bitbay.py +17 -0
  311. ccxt/bitbns.py +1154 -0
  312. ccxt/bitcoincom.py +17 -0
  313. ccxt/bitfinex.py +1617 -0
  314. ccxt/bitfinex2.py +3552 -0
  315. ccxt/bitflyer.py +995 -0
  316. ccxt/bitget.py +8272 -0
  317. ccxt/bithumb.py +1061 -0
  318. ccxt/bitimen.py +401 -0
  319. ccxt/bitir.py +490 -0
  320. ccxt/bitmart.py +4415 -0
  321. ccxt/bitmex.py +2756 -0
  322. ccxt/bitopro.py +1630 -0
  323. ccxt/bitpanda.py +16 -0
  324. ccxt/bitpin.py +454 -0
  325. ccxt/bitrue.py +3026 -0
  326. ccxt/bitso.py +1670 -0
  327. ccxt/bitstamp.py +2203 -0
  328. ccxt/bitteam.py +2239 -0
  329. ccxt/bitvavo.py +1968 -0
  330. ccxt/bl3p.py +485 -0
  331. ccxt/blockchaincom.py +1104 -0
  332. ccxt/blofin.py +2066 -0
  333. ccxt/btcalpha.py +891 -0
  334. ccxt/btcbox.py +544 -0
  335. ccxt/btcmarkets.py +1221 -0
  336. ccxt/btcturk.py +911 -0
  337. ccxt/bybit.py +8158 -0
  338. ccxt/cex.py +1605 -0
  339. ccxt/coinbase.py +4474 -0
  340. ccxt/coinbaseadvanced.py +17 -0
  341. ccxt/coinbaseexchange.py +1734 -0
  342. ccxt/coinbaseinternational.py +1899 -0
  343. ccxt/coincatch.py +5069 -0
  344. ccxt/coincheck.py +815 -0
  345. ccxt/coinex.py +5525 -0
  346. ccxt/coinlist.py +2243 -0
  347. ccxt/coinmate.py +1067 -0
  348. ccxt/coinmetro.py +1797 -0
  349. ccxt/coinone.py +1127 -0
  350. ccxt/coinsph.py +1850 -0
  351. ccxt/coinspot.py +534 -0
  352. ccxt/cryptocom.py +2822 -0
  353. ccxt/currencycom.py +1950 -0
  354. ccxt/delta.py +3376 -0
  355. ccxt/deribit.py +3437 -0
  356. ccxt/digifinex.py +3959 -0
  357. ccxt/eterex.py +286 -0
  358. ccxt/excoino.py +399 -0
  359. ccxt/exir.py +375 -0
  360. ccxt/exmo.py +2462 -0
  361. ccxt/exnovin.py +360 -0
  362. ccxt/farhadexchange.py +266 -0
  363. ccxt/fmfwio.py +34 -0
  364. ccxt/gate.py +6975 -0
  365. ccxt/gateio.py +16 -0
  366. ccxt/gemini.py +1824 -0
  367. ccxt/hashkey.py +4150 -0
  368. ccxt/hitbtc.py +3423 -0
  369. ccxt/hitbtc3.py +16 -0
  370. ccxt/hitobit.py +391 -0
  371. ccxt/hollaex.py +1813 -0
  372. ccxt/htx.py +8505 -0
  373. ccxt/huobi.py +16 -0
  374. ccxt/huobijp.py +1801 -0
  375. ccxt/hyperliquid.py +2430 -0
  376. ccxt/idex.py +1766 -0
  377. ccxt/independentreserve.py +784 -0
  378. ccxt/indodax.py +1247 -0
  379. ccxt/jibitex.py +395 -0
  380. ccxt/kraken.py +2894 -0
  381. ccxt/krakenfutures.py +2601 -0
  382. ccxt/kucoin.py +4601 -0
  383. ccxt/kucoinfutures.py +2698 -0
  384. ccxt/kuna.py +1841 -0
  385. ccxt/latoken.py +1664 -0
  386. ccxt/lbank.py +2682 -0
  387. ccxt/luno.py +1067 -0
  388. ccxt/lykke.py +1270 -0
  389. ccxt/mercado.py +842 -0
  390. ccxt/mexc.py +5369 -0
  391. ccxt/ndax.py +2354 -0
  392. ccxt/nobitex.py +419 -0
  393. ccxt/novadax.py +1484 -0
  394. ccxt/oceanex.py +903 -0
  395. ccxt/okcoin.py +2936 -0
  396. ccxt/okexchange.py +349 -0
  397. ccxt/okx.py +7826 -0
  398. ccxt/ompfinex.py +472 -0
  399. ccxt/onetrading.py +1911 -0
  400. ccxt/oxfun.py +2772 -0
  401. ccxt/p2b.py +1194 -0
  402. ccxt/paradex.py +2015 -0
  403. ccxt/paymium.py +564 -0
  404. ccxt/phemex.py +4473 -0
  405. ccxt/poloniex.py +2232 -0
  406. ccxt/poloniexfutures.py +1717 -0
  407. ccxt/pro/__init__.py +149 -0
  408. ccxt/pro/alpaca.py +685 -0
  409. ccxt/pro/ascendex.py +916 -0
  410. ccxt/pro/bequant.py +38 -0
  411. ccxt/pro/binance.py +3488 -0
  412. ccxt/pro/binancecoinm.py +28 -0
  413. ccxt/pro/binanceus.py +48 -0
  414. ccxt/pro/binanceusdm.py +31 -0
  415. ccxt/pro/bingx.py +1264 -0
  416. ccxt/pro/bitcoincom.py +34 -0
  417. ccxt/pro/bitfinex.py +621 -0
  418. ccxt/pro/bitfinex2.py +1083 -0
  419. ccxt/pro/bitget.py +1692 -0
  420. ccxt/pro/bithumb.py +368 -0
  421. ccxt/pro/bitmart.py +1449 -0
  422. ccxt/pro/bitmex.py +1656 -0
  423. ccxt/pro/bitopro.py +445 -0
  424. ccxt/pro/bitpanda.py +15 -0
  425. ccxt/pro/bitrue.py +447 -0
  426. ccxt/pro/bitstamp.py +522 -0
  427. ccxt/pro/bitvavo.py +1270 -0
  428. ccxt/pro/blockchaincom.py +738 -0
  429. ccxt/pro/blofin.py +692 -0
  430. ccxt/pro/bybit.py +2000 -0
  431. ccxt/pro/cex.py +1440 -0
  432. ccxt/pro/coinbase.py +678 -0
  433. ccxt/pro/coinbaseadvanced.py +16 -0
  434. ccxt/pro/coinbaseexchange.py +895 -0
  435. ccxt/pro/coinbaseinternational.py +620 -0
  436. ccxt/pro/coincatch.py +1464 -0
  437. ccxt/pro/coincheck.py +199 -0
  438. ccxt/pro/coinex.py +1061 -0
  439. ccxt/pro/coinone.py +395 -0
  440. ccxt/pro/cryptocom.py +947 -0
  441. ccxt/pro/currencycom.py +536 -0
  442. ccxt/pro/deribit.py +892 -0
  443. ccxt/pro/exmo.py +629 -0
  444. ccxt/pro/gate.py +1416 -0
  445. ccxt/pro/gateio.py +15 -0
  446. ccxt/pro/gemini.py +865 -0
  447. ccxt/pro/hashkey.py +802 -0
  448. ccxt/pro/hitbtc.py +1216 -0
  449. ccxt/pro/hollaex.py +563 -0
  450. ccxt/pro/htx.py +2215 -0
  451. ccxt/pro/huobi.py +15 -0
  452. ccxt/pro/huobijp.py +570 -0
  453. ccxt/pro/hyperliquid.py +525 -0
  454. ccxt/pro/idex.py +672 -0
  455. ccxt/pro/independentreserve.py +270 -0
  456. ccxt/pro/kraken.py +1356 -0
  457. ccxt/pro/krakenfutures.py +1492 -0
  458. ccxt/pro/kucoin.py +1133 -0
  459. ccxt/pro/kucoinfutures.py +1081 -0
  460. ccxt/pro/lbank.py +843 -0
  461. ccxt/pro/luno.py +303 -0
  462. ccxt/pro/mexc.py +1122 -0
  463. ccxt/pro/ndax.py +506 -0
  464. ccxt/pro/okcoin.py +698 -0
  465. ccxt/pro/okx.py +1851 -0
  466. ccxt/pro/onetrading.py +1275 -0
  467. ccxt/pro/oxfun.py +950 -0
  468. ccxt/pro/p2b.py +419 -0
  469. ccxt/pro/paradex.py +352 -0
  470. ccxt/pro/phemex.py +1441 -0
  471. ccxt/pro/poloniex.py +1166 -0
  472. ccxt/pro/poloniexfutures.py +990 -0
  473. ccxt/pro/probit.py +551 -0
  474. ccxt/pro/upbit.py +520 -0
  475. ccxt/pro/vertex.py +943 -0
  476. ccxt/pro/wazirx.py +749 -0
  477. ccxt/pro/whitebit.py +864 -0
  478. ccxt/pro/woo.py +1078 -0
  479. ccxt/pro/woofipro.py +1183 -0
  480. ccxt/pro/xt.py +1067 -0
  481. ccxt/probit.py +1734 -0
  482. ccxt/ramzinex.py +476 -0
  483. ccxt/sarmayex.py +357 -0
  484. ccxt/sarrafex.py +478 -0
  485. ccxt/static_dependencies/__init__.py +1 -0
  486. ccxt/static_dependencies/ecdsa/__init__.py +14 -0
  487. ccxt/static_dependencies/ecdsa/_version.py +520 -0
  488. ccxt/static_dependencies/ecdsa/curves.py +56 -0
  489. ccxt/static_dependencies/ecdsa/der.py +221 -0
  490. ccxt/static_dependencies/ecdsa/ecdsa.py +310 -0
  491. ccxt/static_dependencies/ecdsa/ellipticcurve.py +197 -0
  492. ccxt/static_dependencies/ecdsa/keys.py +332 -0
  493. ccxt/static_dependencies/ecdsa/numbertheory.py +531 -0
  494. ccxt/static_dependencies/ecdsa/rfc6979.py +100 -0
  495. ccxt/static_dependencies/ecdsa/util.py +266 -0
  496. ccxt/static_dependencies/ethereum/__init__.py +7 -0
  497. ccxt/static_dependencies/ethereum/abi/__init__.py +16 -0
  498. ccxt/static_dependencies/ethereum/abi/abi.py +19 -0
  499. ccxt/static_dependencies/ethereum/abi/base.py +152 -0
  500. ccxt/static_dependencies/ethereum/abi/codec.py +217 -0
  501. ccxt/static_dependencies/ethereum/abi/constants.py +3 -0
  502. ccxt/static_dependencies/ethereum/abi/decoding.py +565 -0
  503. ccxt/static_dependencies/ethereum/abi/encoding.py +720 -0
  504. ccxt/static_dependencies/ethereum/abi/exceptions.py +139 -0
  505. ccxt/static_dependencies/ethereum/abi/grammar.py +443 -0
  506. ccxt/static_dependencies/ethereum/abi/packed.py +13 -0
  507. ccxt/static_dependencies/ethereum/abi/py.typed +0 -0
  508. ccxt/static_dependencies/ethereum/abi/registry.py +643 -0
  509. ccxt/static_dependencies/ethereum/abi/tools/__init__.py +3 -0
  510. ccxt/static_dependencies/ethereum/abi/tools/_strategies.py +230 -0
  511. ccxt/static_dependencies/ethereum/abi/utils/__init__.py +0 -0
  512. ccxt/static_dependencies/ethereum/abi/utils/numeric.py +83 -0
  513. ccxt/static_dependencies/ethereum/abi/utils/padding.py +27 -0
  514. ccxt/static_dependencies/ethereum/abi/utils/string.py +19 -0
  515. ccxt/static_dependencies/ethereum/account/__init__.py +3 -0
  516. ccxt/static_dependencies/ethereum/account/encode_typed_data/__init__.py +4 -0
  517. ccxt/static_dependencies/ethereum/account/encode_typed_data/encoding_and_hashing.py +239 -0
  518. ccxt/static_dependencies/ethereum/account/encode_typed_data/helpers.py +40 -0
  519. ccxt/static_dependencies/ethereum/account/messages.py +263 -0
  520. ccxt/static_dependencies/ethereum/account/py.typed +0 -0
  521. ccxt/static_dependencies/ethereum/hexbytes/__init__.py +5 -0
  522. ccxt/static_dependencies/ethereum/hexbytes/_utils.py +54 -0
  523. ccxt/static_dependencies/ethereum/hexbytes/main.py +65 -0
  524. ccxt/static_dependencies/ethereum/hexbytes/py.typed +0 -0
  525. ccxt/static_dependencies/ethereum/typing/__init__.py +63 -0
  526. ccxt/static_dependencies/ethereum/typing/abi.py +6 -0
  527. ccxt/static_dependencies/ethereum/typing/bls.py +7 -0
  528. ccxt/static_dependencies/ethereum/typing/discovery.py +5 -0
  529. ccxt/static_dependencies/ethereum/typing/encoding.py +7 -0
  530. ccxt/static_dependencies/ethereum/typing/enums.py +17 -0
  531. ccxt/static_dependencies/ethereum/typing/ethpm.py +9 -0
  532. ccxt/static_dependencies/ethereum/typing/evm.py +20 -0
  533. ccxt/static_dependencies/ethereum/typing/networks.py +1122 -0
  534. ccxt/static_dependencies/ethereum/typing/py.typed +0 -0
  535. ccxt/static_dependencies/ethereum/utils/__init__.py +115 -0
  536. ccxt/static_dependencies/ethereum/utils/abi.py +72 -0
  537. ccxt/static_dependencies/ethereum/utils/address.py +171 -0
  538. ccxt/static_dependencies/ethereum/utils/applicators.py +151 -0
  539. ccxt/static_dependencies/ethereum/utils/conversions.py +190 -0
  540. ccxt/static_dependencies/ethereum/utils/currency.py +107 -0
  541. ccxt/static_dependencies/ethereum/utils/curried/__init__.py +269 -0
  542. ccxt/static_dependencies/ethereum/utils/debug.py +20 -0
  543. ccxt/static_dependencies/ethereum/utils/decorators.py +132 -0
  544. ccxt/static_dependencies/ethereum/utils/encoding.py +6 -0
  545. ccxt/static_dependencies/ethereum/utils/exceptions.py +4 -0
  546. ccxt/static_dependencies/ethereum/utils/functional.py +75 -0
  547. ccxt/static_dependencies/ethereum/utils/hexadecimal.py +74 -0
  548. ccxt/static_dependencies/ethereum/utils/humanize.py +188 -0
  549. ccxt/static_dependencies/ethereum/utils/logging.py +159 -0
  550. ccxt/static_dependencies/ethereum/utils/module_loading.py +31 -0
  551. ccxt/static_dependencies/ethereum/utils/numeric.py +43 -0
  552. ccxt/static_dependencies/ethereum/utils/py.typed +0 -0
  553. ccxt/static_dependencies/ethereum/utils/toolz.py +76 -0
  554. ccxt/static_dependencies/ethereum/utils/types.py +54 -0
  555. ccxt/static_dependencies/ethereum/utils/typing/__init__.py +18 -0
  556. ccxt/static_dependencies/ethereum/utils/typing/misc.py +14 -0
  557. ccxt/static_dependencies/ethereum/utils/units.py +31 -0
  558. ccxt/static_dependencies/keccak/__init__.py +3 -0
  559. ccxt/static_dependencies/keccak/keccak.py +197 -0
  560. ccxt/static_dependencies/lark/__init__.py +38 -0
  561. ccxt/static_dependencies/lark/__pyinstaller/__init__.py +6 -0
  562. ccxt/static_dependencies/lark/__pyinstaller/hook-lark.py +14 -0
  563. ccxt/static_dependencies/lark/ast_utils.py +59 -0
  564. ccxt/static_dependencies/lark/common.py +86 -0
  565. ccxt/static_dependencies/lark/exceptions.py +292 -0
  566. ccxt/static_dependencies/lark/grammar.py +130 -0
  567. ccxt/static_dependencies/lark/grammars/__init__.py +0 -0
  568. ccxt/static_dependencies/lark/indenter.py +143 -0
  569. ccxt/static_dependencies/lark/lark.py +658 -0
  570. ccxt/static_dependencies/lark/lexer.py +678 -0
  571. ccxt/static_dependencies/lark/load_grammar.py +1428 -0
  572. ccxt/static_dependencies/lark/parse_tree_builder.py +391 -0
  573. ccxt/static_dependencies/lark/parser_frontends.py +257 -0
  574. ccxt/static_dependencies/lark/parsers/__init__.py +0 -0
  575. ccxt/static_dependencies/lark/parsers/cyk.py +340 -0
  576. ccxt/static_dependencies/lark/parsers/earley.py +314 -0
  577. ccxt/static_dependencies/lark/parsers/earley_common.py +42 -0
  578. ccxt/static_dependencies/lark/parsers/earley_forest.py +801 -0
  579. ccxt/static_dependencies/lark/parsers/grammar_analysis.py +203 -0
  580. ccxt/static_dependencies/lark/parsers/lalr_analysis.py +332 -0
  581. ccxt/static_dependencies/lark/parsers/lalr_interactive_parser.py +158 -0
  582. ccxt/static_dependencies/lark/parsers/lalr_parser.py +122 -0
  583. ccxt/static_dependencies/lark/parsers/lalr_parser_state.py +110 -0
  584. ccxt/static_dependencies/lark/parsers/xearley.py +165 -0
  585. ccxt/static_dependencies/lark/reconstruct.py +107 -0
  586. ccxt/static_dependencies/lark/tools/__init__.py +70 -0
  587. ccxt/static_dependencies/lark/tools/nearley.py +202 -0
  588. ccxt/static_dependencies/lark/tools/serialize.py +32 -0
  589. ccxt/static_dependencies/lark/tools/standalone.py +196 -0
  590. ccxt/static_dependencies/lark/tree.py +267 -0
  591. ccxt/static_dependencies/lark/tree_matcher.py +186 -0
  592. ccxt/static_dependencies/lark/tree_templates.py +180 -0
  593. ccxt/static_dependencies/lark/utils.py +343 -0
  594. ccxt/static_dependencies/lark/visitors.py +596 -0
  595. ccxt/static_dependencies/marshmallow/__init__.py +81 -0
  596. ccxt/static_dependencies/marshmallow/base.py +65 -0
  597. ccxt/static_dependencies/marshmallow/class_registry.py +94 -0
  598. ccxt/static_dependencies/marshmallow/decorators.py +231 -0
  599. ccxt/static_dependencies/marshmallow/error_store.py +60 -0
  600. ccxt/static_dependencies/marshmallow/exceptions.py +71 -0
  601. ccxt/static_dependencies/marshmallow/fields.py +2114 -0
  602. ccxt/static_dependencies/marshmallow/orderedset.py +89 -0
  603. ccxt/static_dependencies/marshmallow/schema.py +1228 -0
  604. ccxt/static_dependencies/marshmallow/types.py +12 -0
  605. ccxt/static_dependencies/marshmallow/utils.py +378 -0
  606. ccxt/static_dependencies/marshmallow/validate.py +678 -0
  607. ccxt/static_dependencies/marshmallow/warnings.py +2 -0
  608. ccxt/static_dependencies/marshmallow_dataclass/__init__.py +1047 -0
  609. ccxt/static_dependencies/marshmallow_dataclass/collection_field.py +51 -0
  610. ccxt/static_dependencies/marshmallow_dataclass/lazy_class_attribute.py +45 -0
  611. ccxt/static_dependencies/marshmallow_dataclass/mypy.py +71 -0
  612. ccxt/static_dependencies/marshmallow_dataclass/typing.py +14 -0
  613. ccxt/static_dependencies/marshmallow_dataclass/union_field.py +82 -0
  614. ccxt/static_dependencies/marshmallow_oneofschema/__init__.py +1 -0
  615. ccxt/static_dependencies/marshmallow_oneofschema/one_of_schema.py +193 -0
  616. ccxt/static_dependencies/msgpack/__init__.py +55 -0
  617. ccxt/static_dependencies/msgpack/exceptions.py +48 -0
  618. ccxt/static_dependencies/msgpack/ext.py +168 -0
  619. ccxt/static_dependencies/msgpack/fallback.py +951 -0
  620. ccxt/static_dependencies/parsimonious/__init__.py +10 -0
  621. ccxt/static_dependencies/parsimonious/exceptions.py +105 -0
  622. ccxt/static_dependencies/parsimonious/expressions.py +479 -0
  623. ccxt/static_dependencies/parsimonious/grammar.py +487 -0
  624. ccxt/static_dependencies/parsimonious/nodes.py +325 -0
  625. ccxt/static_dependencies/parsimonious/utils.py +40 -0
  626. ccxt/static_dependencies/starknet/__init__.py +0 -0
  627. ccxt/static_dependencies/starknet/cairo/__init__.py +0 -0
  628. ccxt/static_dependencies/starknet/cairo/data_types.py +123 -0
  629. ccxt/static_dependencies/starknet/cairo/deprecated_parse/__init__.py +0 -0
  630. ccxt/static_dependencies/starknet/cairo/deprecated_parse/cairo_types.py +77 -0
  631. ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser.py +46 -0
  632. ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser_transformer.py +138 -0
  633. ccxt/static_dependencies/starknet/cairo/felt.py +64 -0
  634. ccxt/static_dependencies/starknet/cairo/type_parser.py +121 -0
  635. ccxt/static_dependencies/starknet/cairo/v1/__init__.py +0 -0
  636. ccxt/static_dependencies/starknet/cairo/v1/type_parser.py +59 -0
  637. ccxt/static_dependencies/starknet/cairo/v2/__init__.py +0 -0
  638. ccxt/static_dependencies/starknet/cairo/v2/type_parser.py +77 -0
  639. ccxt/static_dependencies/starknet/ccxt_utils.py +7 -0
  640. ccxt/static_dependencies/starknet/common.py +15 -0
  641. ccxt/static_dependencies/starknet/constants.py +39 -0
  642. ccxt/static_dependencies/starknet/hash/__init__.py +0 -0
  643. ccxt/static_dependencies/starknet/hash/address.py +79 -0
  644. ccxt/static_dependencies/starknet/hash/compiled_class_hash_objects.py +111 -0
  645. ccxt/static_dependencies/starknet/hash/selector.py +16 -0
  646. ccxt/static_dependencies/starknet/hash/storage.py +12 -0
  647. ccxt/static_dependencies/starknet/hash/utils.py +78 -0
  648. ccxt/static_dependencies/starknet/models/__init__.py +0 -0
  649. ccxt/static_dependencies/starknet/models/typed_data.py +45 -0
  650. ccxt/static_dependencies/starknet/serialization/__init__.py +24 -0
  651. ccxt/static_dependencies/starknet/serialization/_calldata_reader.py +40 -0
  652. ccxt/static_dependencies/starknet/serialization/_context.py +142 -0
  653. ccxt/static_dependencies/starknet/serialization/data_serializers/__init__.py +10 -0
  654. ccxt/static_dependencies/starknet/serialization/data_serializers/_common.py +82 -0
  655. ccxt/static_dependencies/starknet/serialization/data_serializers/array_serializer.py +43 -0
  656. ccxt/static_dependencies/starknet/serialization/data_serializers/bool_serializer.py +37 -0
  657. ccxt/static_dependencies/starknet/serialization/data_serializers/byte_array_serializer.py +66 -0
  658. ccxt/static_dependencies/starknet/serialization/data_serializers/cairo_data_serializer.py +71 -0
  659. ccxt/static_dependencies/starknet/serialization/data_serializers/enum_serializer.py +71 -0
  660. ccxt/static_dependencies/starknet/serialization/data_serializers/felt_serializer.py +50 -0
  661. ccxt/static_dependencies/starknet/serialization/data_serializers/named_tuple_serializer.py +58 -0
  662. ccxt/static_dependencies/starknet/serialization/data_serializers/option_serializer.py +43 -0
  663. ccxt/static_dependencies/starknet/serialization/data_serializers/output_serializer.py +40 -0
  664. ccxt/static_dependencies/starknet/serialization/data_serializers/payload_serializer.py +72 -0
  665. ccxt/static_dependencies/starknet/serialization/data_serializers/struct_serializer.py +36 -0
  666. ccxt/static_dependencies/starknet/serialization/data_serializers/tuple_serializer.py +36 -0
  667. ccxt/static_dependencies/starknet/serialization/data_serializers/uint256_serializer.py +76 -0
  668. ccxt/static_dependencies/starknet/serialization/data_serializers/uint_serializer.py +100 -0
  669. ccxt/static_dependencies/starknet/serialization/data_serializers/unit_serializer.py +32 -0
  670. ccxt/static_dependencies/starknet/serialization/errors.py +10 -0
  671. ccxt/static_dependencies/starknet/serialization/factory.py +229 -0
  672. ccxt/static_dependencies/starknet/serialization/function_serialization_adapter.py +110 -0
  673. ccxt/static_dependencies/starknet/serialization/tuple_dataclass.py +59 -0
  674. ccxt/static_dependencies/starknet/utils/__init__.py +0 -0
  675. ccxt/static_dependencies/starknet/utils/constructor_args_translator.py +86 -0
  676. ccxt/static_dependencies/starknet/utils/iterable.py +13 -0
  677. ccxt/static_dependencies/starknet/utils/schema.py +13 -0
  678. ccxt/static_dependencies/starknet/utils/typed_data.py +182 -0
  679. ccxt/static_dependencies/starkware/__init__.py +0 -0
  680. ccxt/static_dependencies/starkware/crypto/__init__.py +0 -0
  681. ccxt/static_dependencies/starkware/crypto/fast_pedersen_hash.py +50 -0
  682. ccxt/static_dependencies/starkware/crypto/math_utils.py +78 -0
  683. ccxt/static_dependencies/starkware/crypto/signature.py +2344 -0
  684. ccxt/static_dependencies/starkware/crypto/utils.py +63 -0
  685. ccxt/static_dependencies/sympy/__init__.py +0 -0
  686. ccxt/static_dependencies/sympy/core/__init__.py +0 -0
  687. ccxt/static_dependencies/sympy/core/intfunc.py +35 -0
  688. ccxt/static_dependencies/sympy/external/__init__.py +0 -0
  689. ccxt/static_dependencies/sympy/external/gmpy.py +345 -0
  690. ccxt/static_dependencies/sympy/external/importtools.py +187 -0
  691. ccxt/static_dependencies/sympy/external/ntheory.py +637 -0
  692. ccxt/static_dependencies/sympy/external/pythonmpq.py +341 -0
  693. ccxt/static_dependencies/toolz/__init__.py +26 -0
  694. ccxt/static_dependencies/toolz/_signatures.py +784 -0
  695. ccxt/static_dependencies/toolz/_version.py +520 -0
  696. ccxt/static_dependencies/toolz/compatibility.py +30 -0
  697. ccxt/static_dependencies/toolz/curried/__init__.py +101 -0
  698. ccxt/static_dependencies/toolz/curried/exceptions.py +22 -0
  699. ccxt/static_dependencies/toolz/curried/operator.py +22 -0
  700. ccxt/static_dependencies/toolz/dicttoolz.py +339 -0
  701. ccxt/static_dependencies/toolz/functoolz.py +1049 -0
  702. ccxt/static_dependencies/toolz/itertoolz.py +1057 -0
  703. ccxt/static_dependencies/toolz/recipes.py +46 -0
  704. ccxt/static_dependencies/toolz/utils.py +9 -0
  705. ccxt/static_dependencies/typing_inspect/__init__.py +0 -0
  706. ccxt/static_dependencies/typing_inspect/typing_inspect.py +851 -0
  707. ccxt/tabdeal.py +364 -0
  708. ccxt/test/__init__.py +3 -0
  709. ccxt/test/base/__init__.py +29 -0
  710. ccxt/test/base/test_account.py +26 -0
  711. ccxt/test/base/test_balance.py +56 -0
  712. ccxt/test/base/test_borrow_interest.py +35 -0
  713. ccxt/test/base/test_borrow_rate.py +32 -0
  714. ccxt/test/base/test_calculate_fee.py +51 -0
  715. ccxt/test/base/test_crypto.py +127 -0
  716. ccxt/test/base/test_currency.py +76 -0
  717. ccxt/test/base/test_datetime.py +109 -0
  718. ccxt/test/base/test_decimal_to_precision.py +392 -0
  719. ccxt/test/base/test_deep_extend.py +68 -0
  720. ccxt/test/base/test_deposit_withdrawal.py +50 -0
  721. ccxt/test/base/test_exchange_datetime_functions.py +76 -0
  722. ccxt/test/base/test_funding_rate_history.py +29 -0
  723. ccxt/test/base/test_last_price.py +31 -0
  724. ccxt/test/base/test_ledger_entry.py +45 -0
  725. ccxt/test/base/test_ledger_item.py +48 -0
  726. ccxt/test/base/test_leverage_tier.py +33 -0
  727. ccxt/test/base/test_liquidation.py +50 -0
  728. ccxt/test/base/test_margin_mode.py +24 -0
  729. ccxt/test/base/test_margin_modification.py +35 -0
  730. ccxt/test/base/test_market.py +193 -0
  731. ccxt/test/base/test_number.py +411 -0
  732. ccxt/test/base/test_ohlcv.py +33 -0
  733. ccxt/test/base/test_open_interest.py +32 -0
  734. ccxt/test/base/test_order.py +64 -0
  735. ccxt/test/base/test_order_book.py +69 -0
  736. ccxt/test/base/test_position.py +60 -0
  737. ccxt/test/base/test_shared_methods.py +353 -0
  738. ccxt/test/base/test_status.py +24 -0
  739. ccxt/test/base/test_throttle.py +126 -0
  740. ccxt/test/base/test_ticker.py +92 -0
  741. ccxt/test/base/test_trade.py +47 -0
  742. ccxt/test/base/test_trading_fee.py +26 -0
  743. ccxt/test/base/test_transaction.py +39 -0
  744. ccxt/test/test_async.py +1649 -0
  745. ccxt/test/test_sync.py +1648 -0
  746. ccxt/test/tests_async.py +1558 -0
  747. ccxt/test/tests_helpers.py +287 -0
  748. ccxt/test/tests_init.py +39 -0
  749. ccxt/test/tests_sync.py +1555 -0
  750. ccxt/tetherland.py +349 -0
  751. ccxt/timex.py +1593 -0
  752. ccxt/tokocrypto.py +2405 -0
  753. ccxt/tradeogre.py +608 -0
  754. ccxt/twox.py +326 -0
  755. ccxt/ubitex.py +409 -0
  756. ccxt/upbit.py +1833 -0
  757. ccxt/vertex.py +2922 -0
  758. ccxt/wallex.py +445 -0
  759. ccxt/wavesexchange.py +2472 -0
  760. ccxt/wazirx.py +1224 -0
  761. ccxt/whitebit.py +2469 -0
  762. ccxt/woo.py +3114 -0
  763. ccxt/woofipro.py +2533 -0
  764. ccxt/xt.py +4453 -0
  765. ccxt/yobit.py +1283 -0
  766. ccxt/zaif.py +725 -0
  767. ccxt/zonda.py +1828 -0
  768. ccxt_ir-4.3.46.0.1.dist-info/LICENSE.txt +21 -0
  769. ccxt_ir-4.3.46.0.1.dist-info/METADATA +655 -0
  770. ccxt_ir-4.3.46.0.1.dist-info/RECORD +772 -0
  771. ccxt_ir-4.3.46.0.1.dist-info/WHEEL +6 -0
  772. ccxt_ir-4.3.46.0.1.dist-info/top_level.txt +1 -0
ccxt/ndax.py ADDED
@@ -0,0 +1,2354 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
4
+ # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
5
+
6
+ from ccxt.base.exchange import Exchange
7
+ from ccxt.abstract.ndax import ImplicitAPI
8
+ import hashlib
9
+ import json
10
+ from ccxt.base.types import Account, Balances, Currencies, Currency, IndexType, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Ticker, Trade, Transaction
11
+ from typing import List
12
+ from ccxt.base.errors import ExchangeError
13
+ from ccxt.base.errors import AuthenticationError
14
+ from ccxt.base.errors import BadSymbol
15
+ from ccxt.base.errors import InsufficientFunds
16
+ from ccxt.base.errors import OrderNotFound
17
+ from ccxt.base.decimal_to_precision import TICK_SIZE
18
+ from ccxt.base.precise import Precise
19
+
20
+
21
+ class ndax(Exchange, ImplicitAPI):
22
+
23
+ def describe(self):
24
+ return self.deep_extend(super(ndax, self).describe(), {
25
+ 'id': 'ndax',
26
+ 'name': 'NDAX',
27
+ 'countries': ['CA'], # Canada
28
+ 'rateLimit': 1000,
29
+ 'pro': True,
30
+ 'has': {
31
+ 'CORS': None,
32
+ 'spot': True,
33
+ 'margin': False,
34
+ 'swap': False,
35
+ 'future': False,
36
+ 'option': False,
37
+ 'addMargin': False,
38
+ 'cancelAllOrders': True,
39
+ 'cancelOrder': True,
40
+ 'closeAllPositions': False,
41
+ 'closePosition': False,
42
+ 'createDepositAddress': True,
43
+ 'createOrder': True,
44
+ 'createReduceOnlyOrder': False,
45
+ 'createStopLimitOrder': True,
46
+ 'createStopMarketOrder': True,
47
+ 'createStopOrder': True,
48
+ 'editOrder': True,
49
+ 'fetchAccounts': True,
50
+ 'fetchBalance': True,
51
+ 'fetchBorrowRateHistories': False,
52
+ 'fetchBorrowRateHistory': False,
53
+ 'fetchCrossBorrowRate': False,
54
+ 'fetchCrossBorrowRates': False,
55
+ 'fetchCurrencies': True,
56
+ 'fetchDepositAddress': True,
57
+ 'fetchDeposits': True,
58
+ 'fetchFundingHistory': False,
59
+ 'fetchFundingRate': False,
60
+ 'fetchFundingRateHistory': False,
61
+ 'fetchFundingRates': False,
62
+ 'fetchIndexOHLCV': False,
63
+ 'fetchIsolatedBorrowRate': False,
64
+ 'fetchIsolatedBorrowRates': False,
65
+ 'fetchLedger': True,
66
+ 'fetchLeverage': False,
67
+ 'fetchLeverageTiers': False,
68
+ 'fetchMarkets': True,
69
+ 'fetchMarkOHLCV': False,
70
+ 'fetchMyTrades': True,
71
+ 'fetchOHLCV': True,
72
+ 'fetchOpenInterestHistory': False,
73
+ 'fetchOpenOrders': True,
74
+ 'fetchOrder': True,
75
+ 'fetchOrderBook': True,
76
+ 'fetchOrders': True,
77
+ 'fetchOrderTrades': True,
78
+ 'fetchPosition': False,
79
+ 'fetchPositionHistory': False,
80
+ 'fetchPositionMode': False,
81
+ 'fetchPositions': False,
82
+ 'fetchPositionsForSymbol': False,
83
+ 'fetchPositionsHistory': False,
84
+ 'fetchPositionsRisk': False,
85
+ 'fetchPremiumIndexOHLCV': False,
86
+ 'fetchTicker': True,
87
+ 'fetchTickers': False,
88
+ 'fetchTime': False,
89
+ 'fetchTrades': True,
90
+ 'fetchTradingFee': False,
91
+ 'fetchTradingFees': False,
92
+ 'fetchWithdrawals': True,
93
+ 'reduceMargin': False,
94
+ 'sandbox': True,
95
+ 'setLeverage': False,
96
+ 'setMarginMode': False,
97
+ 'setPositionMode': False,
98
+ 'signIn': True,
99
+ 'transfer': False,
100
+ 'withdraw': True,
101
+ },
102
+ 'timeframes': {
103
+ '1m': '60',
104
+ '5m': '300',
105
+ '15m': '900',
106
+ '30m': '1800',
107
+ '1h': '3600',
108
+ '2h': '7200',
109
+ '4h': '14400',
110
+ '6h': '21600',
111
+ '12h': '43200',
112
+ '1d': '86400',
113
+ '1w': '604800',
114
+ '1M': '2419200',
115
+ '4M': '9676800',
116
+ },
117
+ 'urls': {
118
+ 'logo': 'https://user-images.githubusercontent.com/1294454/108623144-67a3ef00-744e-11eb-8140-75c6b851e945.jpg',
119
+ 'test': {
120
+ 'public': 'https://ndaxmarginstaging.cdnhop.net:8443/AP',
121
+ 'private': 'https://ndaxmarginstaging.cdnhop.net:8443/AP',
122
+ },
123
+ 'api': {
124
+ 'public': 'https://api.ndax.io:8443/AP',
125
+ 'private': 'https://api.ndax.io:8443/AP',
126
+ },
127
+ 'www': 'https://ndax.io',
128
+ 'doc': [
129
+ 'https://apidoc.ndax.io/',
130
+ ],
131
+ 'fees': 'https://ndax.io/fees',
132
+ 'referral': 'https://one.ndax.io/bfQiSL',
133
+ },
134
+ 'api': {
135
+ 'public': {
136
+ 'get': {
137
+ 'Activate2FA': 1,
138
+ 'Authenticate2FA': 1,
139
+ 'AuthenticateUser': 1,
140
+ 'GetL2Snapshot': 1,
141
+ 'GetLevel1': 1,
142
+ 'GetValidate2FARequiredEndpoints': 1,
143
+ 'LogOut': 1,
144
+ 'GetTickerHistory': 1,
145
+ 'GetProduct': 1,
146
+ 'GetProducts': 1,
147
+ 'GetInstrument': 1,
148
+ 'GetInstruments': 1,
149
+ 'Ping': 1,
150
+ 'trades': 1, # undocumented
151
+ 'GetLastTrades': 1, # undocumented
152
+ 'SubscribeLevel1': 1,
153
+ 'SubscribeLevel2': 1,
154
+ 'SubscribeTicker': 1,
155
+ 'SubscribeTrades': 1,
156
+ 'SubscribeBlockTrades': 1,
157
+ 'UnsubscribeBlockTrades': 1,
158
+ 'UnsubscribeLevel1': 1,
159
+ 'UnsubscribeLevel2': 1,
160
+ 'UnsubscribeTicker': 1,
161
+ 'UnsubscribeTrades': 1,
162
+ 'Authenticate': 1, # undocumented
163
+ },
164
+ },
165
+ 'private': {
166
+ 'get': {
167
+ 'GetUserAccountInfos': 1,
168
+ 'GetUserAccounts': 1,
169
+ 'GetUserAffiliateCount': 1,
170
+ 'GetUserAffiliateTag': 1,
171
+ 'GetUserConfig': 1,
172
+ 'GetAllUnredactedUserConfigsForUser': 1,
173
+ 'GetUnredactedUserConfigByKey': 1,
174
+ 'GetUserDevices': 1,
175
+ 'GetUserReportTickets': 1,
176
+ 'GetUserReportWriterResultRecords': 1,
177
+ 'GetAccountInfo': 1,
178
+ 'GetAccountPositions': 1,
179
+ 'GetAllAccountConfigs': 1,
180
+ 'GetTreasuryProductsForAccount': 1,
181
+ 'GetAccountTrades': 1,
182
+ 'GetAccountTransactions': 1,
183
+ 'GetOpenTradeReports': 1,
184
+ 'GetAllOpenTradeReports': 1,
185
+ 'GetTradesHistory': 1,
186
+ 'GetOpenOrders': 1,
187
+ 'GetOpenQuotes': 1,
188
+ 'GetOrderFee': 1,
189
+ 'GetOrderHistory': 1,
190
+ 'GetOrdersHistory': 1,
191
+ 'GetOrderStatus': 1,
192
+ 'GetOmsFeeTiers': 1,
193
+ 'GetAccountDepositTransactions': 1,
194
+ 'GetAccountWithdrawTransactions': 1,
195
+ 'GetAllDepositRequestInfoTemplates': 1,
196
+ 'GetDepositInfo': 1,
197
+ 'GetDepositRequestInfoTemplate': 1,
198
+ 'GetDeposits': 1,
199
+ 'GetDepositTicket': 1,
200
+ 'GetDepositTickets': 1,
201
+ 'GetOMSWithdrawFees': 1,
202
+ 'GetWithdrawFee': 1,
203
+ 'GetWithdraws': 1,
204
+ 'GetWithdrawTemplate': 1,
205
+ 'GetWithdrawTemplateTypes': 1,
206
+ 'GetWithdrawTicket': 1,
207
+ 'GetWithdrawTickets': 1,
208
+ },
209
+ 'post': {
210
+ 'AddUserAffiliateTag': 1,
211
+ 'CancelUserReport': 1,
212
+ 'RegisterNewDevice': 1,
213
+ 'SubscribeAccountEvents': 1,
214
+ 'UpdateUserAffiliateTag': 1,
215
+ 'GenerateTradeActivityReport': 1,
216
+ 'GenerateTransactionActivityReport': 1,
217
+ 'GenerateTreasuryActivityReport': 1,
218
+ 'ScheduleTradeActivityReport': 1,
219
+ 'ScheduleTransactionActivityReport': 1,
220
+ 'ScheduleTreasuryActivityReport': 1,
221
+ 'CancelAllOrders': 1,
222
+ 'CancelOrder': 1,
223
+ 'CancelQuote': 1,
224
+ 'CancelReplaceOrder': 1,
225
+ 'CreateQuote': 1,
226
+ 'ModifyOrder': 1,
227
+ 'SendOrder': 1,
228
+ 'SubmitBlockTrade': 1,
229
+ 'UpdateQuote': 1,
230
+ 'CancelWithdraw': 1,
231
+ 'CreateDepositTicket': 1,
232
+ 'CreateWithdrawTicket': 1,
233
+ 'SubmitDepositTicketComment': 1,
234
+ 'SubmitWithdrawTicketComment': 1,
235
+ 'GetOrderHistoryByOrderId': 1,
236
+ },
237
+ },
238
+ },
239
+ 'fees': {
240
+ 'trading': {
241
+ 'tierBased': False,
242
+ 'percentage': True,
243
+ 'maker': self.parse_number('0.002'),
244
+ 'taker': self.parse_number('0.0025'),
245
+ },
246
+ },
247
+ 'requiredCredentials': {
248
+ 'apiKey': True,
249
+ 'secret': True,
250
+ 'uid': True,
251
+ # these credentials are required for signIn() and withdraw()
252
+ 'login': True,
253
+ 'password': True,
254
+ # 'twofa': True,
255
+ },
256
+ 'precisionMode': TICK_SIZE,
257
+ 'exceptions': {
258
+ 'exact': {
259
+ 'Not_Enough_Funds': InsufficientFunds, # {"status":"Rejected","errormsg":"Not_Enough_Funds","errorcode":101}
260
+ 'Server Error': ExchangeError, # {"result":false,"errormsg":"Server Error","errorcode":102,"detail":null}
261
+ 'Resource Not Found': OrderNotFound, # {"result":false,"errormsg":"Resource Not Found","errorcode":104,"detail":null}
262
+ },
263
+ 'broad': {
264
+ 'Invalid InstrumentId': BadSymbol, # {"result":false,"errormsg":"Invalid InstrumentId: 10000","errorcode":100,"detail":null}
265
+ 'This endpoint requires 2FACode along with the payload': AuthenticationError,
266
+ },
267
+ },
268
+ 'options': {
269
+ 'omsId': 1,
270
+ 'orderTypes': {
271
+ 'Market': 1,
272
+ 'Limit': 2,
273
+ 'StopMarket': 3,
274
+ 'StopLimit': 4,
275
+ 'TrailingStopMarket': 5,
276
+ 'TrailingStopLimit': 6,
277
+ 'BlockTrade': 7,
278
+ '1': 1,
279
+ '2': 2,
280
+ '3': 3,
281
+ '4': 4,
282
+ '5': 5,
283
+ '6': 6,
284
+ '7': 7,
285
+ },
286
+ },
287
+ })
288
+
289
+ def sign_in(self, params={}):
290
+ """
291
+ sign in, must be called prior to using other authenticated methods
292
+ :see: https://apidoc.ndax.io/#authenticate2fa
293
+ :param dict [params]: extra parameters specific to the exchange API endpoint
294
+ :returns: response from exchange
295
+ """
296
+ self.check_required_credentials()
297
+ if self.login is None or self.password is None:
298
+ raise AuthenticationError(self.id + ' signIn() requires exchange.login, exchange.password')
299
+ request: dict = {
300
+ 'grant_type': 'client_credentials', # the only supported value
301
+ }
302
+ response = self.publicGetAuthenticate(self.extend(request, params))
303
+ #
304
+ # {
305
+ # "Authenticated":true,
306
+ # "Requires2FA":true,
307
+ # "AuthType":"Google",
308
+ # "AddtlInfo":"",
309
+ # "Pending2FaToken": "6f5c4e66-f3ee-493e-9227-31cc0583b55f"
310
+ # }
311
+ #
312
+ sessionToken = self.safe_string(response, 'SessionToken')
313
+ if sessionToken is not None:
314
+ self.options['sessionToken'] = sessionToken
315
+ return response
316
+ pending2faToken = self.safe_string(response, 'Pending2FaToken')
317
+ if pending2faToken is not None:
318
+ if self.twofa is None:
319
+ raise AuthenticationError(self.id + ' signIn() requires exchange.twofa credentials')
320
+ self.options['pending2faToken'] = pending2faToken
321
+ request = {
322
+ 'Code': self.totp(self.twofa),
323
+ }
324
+ responseInner = self.publicGetAuthenticate2FA(self.extend(request, params))
325
+ #
326
+ # {
327
+ # "Authenticated": True,
328
+ # "UserId":57765,
329
+ # "SessionToken":"4a2a5857-c4e5-4fac-b09e-2c4c30b591a0"
330
+ # }
331
+ #
332
+ sessionToken = self.safe_string(responseInner, 'SessionToken')
333
+ self.options['sessionToken'] = sessionToken
334
+ return responseInner
335
+ return response
336
+
337
+ def fetch_currencies(self, params={}) -> Currencies:
338
+ """
339
+ fetches all available currencies on an exchange
340
+ :see: https://apidoc.ndax.io/#getproduct
341
+ :param dict [params]: extra parameters specific to the exchange API endpoint
342
+ :returns dict: an associative dictionary of currencies
343
+ """
344
+ omsId = self.safe_integer(self.options, 'omsId', 1)
345
+ request: dict = {
346
+ 'omsId': omsId,
347
+ }
348
+ response = self.publicGetGetProducts(self.extend(request, params))
349
+ #
350
+ # [
351
+ # {
352
+ # "OMSId":1,
353
+ # "ProductId":1,
354
+ # "Product":"BTC",
355
+ # "ProductFullName":"Bitcoin",
356
+ # "ProductType":"CryptoCurrency",
357
+ # "DecimalPlaces":8,
358
+ # "TickSize":0.0000000100000000000000000000,
359
+ # "NoFees":false,
360
+ # "IsDisabled":false,
361
+ # "MarginEnabled":false
362
+ # },
363
+ # ]
364
+ #
365
+ result: dict = {}
366
+ for i in range(0, len(response)):
367
+ currency = response[i]
368
+ id = self.safe_string(currency, 'ProductId')
369
+ name = self.safe_string(currency, 'ProductFullName')
370
+ ProductType = self.safe_string(currency, 'ProductType')
371
+ type = 'fiat' if (ProductType == 'NationalCurrency') else 'crypto'
372
+ if ProductType == 'Unknown':
373
+ # such currency is just a blanket entry
374
+ type = 'other'
375
+ code = self.safe_currency_code(self.safe_string(currency, 'Product'))
376
+ isDisabled = self.safe_value(currency, 'IsDisabled')
377
+ active = not isDisabled
378
+ result[code] = {
379
+ 'id': id,
380
+ 'name': name,
381
+ 'code': code,
382
+ 'type': type,
383
+ 'precision': self.safe_number(currency, 'TickSize'),
384
+ 'info': currency,
385
+ 'active': active,
386
+ 'deposit': None,
387
+ 'withdraw': None,
388
+ 'fee': None,
389
+ 'limits': {
390
+ 'amount': {
391
+ 'min': None,
392
+ 'max': None,
393
+ },
394
+ 'withdraw': {
395
+ 'min': None,
396
+ 'max': None,
397
+ },
398
+ },
399
+ 'networks': {},
400
+ }
401
+ return result
402
+
403
+ def fetch_markets(self, params={}) -> List[Market]:
404
+ """
405
+ retrieves data on all markets for ndax
406
+ :see: https://apidoc.ndax.io/#getinstruments
407
+ :param dict [params]: extra parameters specific to the exchange API endpoint
408
+ :returns dict[]: an array of objects representing market data
409
+ """
410
+ omsId = self.safe_integer(self.options, 'omsId', 1)
411
+ request: dict = {
412
+ 'omsId': omsId,
413
+ }
414
+ response = self.publicGetGetInstruments(self.extend(request, params))
415
+ #
416
+ # [
417
+ # {
418
+ # "OMSId":1,
419
+ # "InstrumentId":3,
420
+ # "Symbol":"LTCBTC",
421
+ # "Product1":3,
422
+ # "Product1Symbol":"LTC",
423
+ # "Product2":1,
424
+ # "Product2Symbol":"BTC",
425
+ # "InstrumentType":"Standard",
426
+ # "VenueInstrumentId":3,
427
+ # "VenueId":1,
428
+ # "SortIndex":0,
429
+ # "SessionStatus":"Running",
430
+ # "PreviousSessionStatus":"Stopped",
431
+ # "SessionStatusDateTime":"2020-11-25T19:42:15.245Z",
432
+ # "SelfTradePrevention":true,
433
+ # "QuantityIncrement":0.0000000100000000000000000000,
434
+ # "PriceIncrement":0.0000000100000000000000000000,
435
+ # "MinimumQuantity":0.0100000000000000000000000000,
436
+ # "MinimumPrice":0.0000010000000000000000000000,
437
+ # "VenueSymbol":"LTCBTC",
438
+ # "IsDisable":false,
439
+ # "MasterDataId":0,
440
+ # "PriceCollarThreshold":0.0000000000000000000000000000,
441
+ # "PriceCollarPercent":0.0000000000000000000000000000,
442
+ # "PriceCollarEnabled":false,
443
+ # "PriceFloorLimit":0.0000000000000000000000000000,
444
+ # "PriceFloorLimitEnabled":false,
445
+ # "PriceCeilingLimit":0.0000000000000000000000000000,
446
+ # "PriceCeilingLimitEnabled":false,
447
+ # "CreateWithMarketRunning":true,
448
+ # "AllowOnlyMarketMakerCounterParty":false,
449
+ # "PriceCollarIndexDifference":0.0000000000000000000000000000,
450
+ # "PriceCollarConvertToOtcEnabled":false,
451
+ # "PriceCollarConvertToOtcClientUserId":0,
452
+ # "PriceCollarConvertToOtcAccountId":0,
453
+ # "PriceCollarConvertToOtcThreshold":0.0000000000000000000000000000,
454
+ # "OtcConvertSizeThreshold":0.0000000000000000000000000000,
455
+ # "OtcConvertSizeEnabled":false,
456
+ # "OtcTradesPublic":true,
457
+ # "PriceTier":0
458
+ # },
459
+ # ]
460
+ #
461
+ return self.parse_markets(response)
462
+
463
+ def parse_market(self, market: dict) -> Market:
464
+ id = self.safe_string(market, 'InstrumentId')
465
+ # lowercaseId = self.safe_string_lower(market, 'symbol')
466
+ baseId = self.safe_string(market, 'Product1')
467
+ quoteId = self.safe_string(market, 'Product2')
468
+ base = self.safe_currency_code(self.safe_string(market, 'Product1Symbol'))
469
+ quote = self.safe_currency_code(self.safe_string(market, 'Product2Symbol'))
470
+ sessionStatus = self.safe_string(market, 'SessionStatus')
471
+ isDisable = self.safe_value(market, 'IsDisable')
472
+ sessionRunning = (sessionStatus == 'Running')
473
+ return {
474
+ 'id': id,
475
+ 'symbol': base + '/' + quote,
476
+ 'base': base,
477
+ 'quote': quote,
478
+ 'settle': None,
479
+ 'baseId': baseId,
480
+ 'quoteId': quoteId,
481
+ 'settleId': None,
482
+ 'type': 'spot',
483
+ 'spot': True,
484
+ 'margin': False,
485
+ 'swap': False,
486
+ 'future': False,
487
+ 'option': False,
488
+ 'active': (sessionRunning and not isDisable),
489
+ 'contract': False,
490
+ 'linear': None,
491
+ 'inverse': None,
492
+ 'contractSize': None,
493
+ 'expiry': None,
494
+ 'expiryDatetime': None,
495
+ 'strike': None,
496
+ 'optionType': None,
497
+ 'precision': {
498
+ 'amount': self.safe_number(market, 'QuantityIncrement'),
499
+ 'price': self.safe_number(market, 'PriceIncrement'),
500
+ },
501
+ 'limits': {
502
+ 'leverage': {
503
+ 'min': None,
504
+ 'max': None,
505
+ },
506
+ 'amount': {
507
+ 'min': self.safe_number(market, 'MinimumQuantity'),
508
+ 'max': None,
509
+ },
510
+ 'price': {
511
+ 'min': self.safe_number(market, 'MinimumPrice'),
512
+ 'max': None,
513
+ },
514
+ 'cost': {
515
+ 'min': None,
516
+ 'max': None,
517
+ },
518
+ },
519
+ 'created': None,
520
+ 'info': market,
521
+ }
522
+
523
+ def parse_order_book(self, orderbook, symbol, timestamp=None, bidsKey='bids', asksKey='asks', priceKey: IndexType = 6, amountKey: IndexType = 8, countOrIdKey: IndexType = 2):
524
+ nonce = None
525
+ result: dict = {
526
+ 'symbol': symbol,
527
+ 'bids': [],
528
+ 'asks': [],
529
+ 'timestamp': None,
530
+ 'datetime': None,
531
+ 'nonce': None,
532
+ }
533
+ for i in range(0, len(orderbook)):
534
+ level = orderbook[i]
535
+ if timestamp is None:
536
+ timestamp = self.safe_integer(level, 2)
537
+ else:
538
+ newTimestamp = self.safe_integer(level, 2)
539
+ timestamp = max(timestamp, newTimestamp)
540
+ if nonce is None:
541
+ nonce = self.safe_integer(level, 0)
542
+ else:
543
+ newNonce = self.safe_integer(level, 0)
544
+ nonce = max(nonce, newNonce)
545
+ bidask = self.parse_bid_ask(level, priceKey, amountKey)
546
+ levelSide = self.safe_integer(level, 9)
547
+ side = asksKey if levelSide else bidsKey
548
+ result[side].append(bidask)
549
+ result['bids'] = self.sort_by(result['bids'], 0, True)
550
+ result['asks'] = self.sort_by(result['asks'], 0)
551
+ result['timestamp'] = timestamp
552
+ result['datetime'] = self.iso8601(timestamp)
553
+ result['nonce'] = nonce
554
+ return result
555
+
556
+ def fetch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
557
+ """
558
+ fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
559
+ :see: https://apidoc.ndax.io/#getl2snapshot
560
+ :param str symbol: unified symbol of the market to fetch the order book for
561
+ :param int [limit]: the maximum amount of order book entries to return
562
+ :param dict [params]: extra parameters specific to the exchange API endpoint
563
+ :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
564
+ """
565
+ omsId = self.safe_integer(self.options, 'omsId', 1)
566
+ self.load_markets()
567
+ market = self.market(symbol)
568
+ limit = 100 if (limit is None) else limit # default 100
569
+ request: dict = {
570
+ 'omsId': omsId,
571
+ 'InstrumentId': market['id'],
572
+ 'Depth': limit, # default 100
573
+ }
574
+ response = self.publicGetGetL2Snapshot(self.extend(request, params))
575
+ #
576
+ # [
577
+ # [
578
+ # 0, # 0 MDUpdateId
579
+ # 1, # 1 Number of Unique Accounts
580
+ # 123, # 2 ActionDateTime in Posix format X 1000
581
+ # 0, # 3 ActionType 0(New), 1(Update), 2(Delete)
582
+ # 0.0, # 4 LastTradePrice
583
+ # 0, # 5 Number of Orders
584
+ # 0.0, # 6 Price
585
+ # 0, # 7 ProductPairCode
586
+ # 0.0, # 8 Quantity
587
+ # 0, # 9 Side
588
+ # ],
589
+ # [97244115,1,1607456142963,0,19069.32,1,19069.31,8,0.140095,0],
590
+ # [97244115,0,1607456142963,0,19069.32,1,19068.64,8,0.0055,0],
591
+ # [97244115,0,1607456142963,0,19069.32,1,19068.26,8,0.021291,0],
592
+ # [97244115,1,1607456142964,0,19069.32,1,19069.32,8,0.099636,1],
593
+ # [97244115,0,1607456142964,0,19069.32,1,19069.98,8,0.1,1],
594
+ # [97244115,0,1607456142964,0,19069.32,1,19069.99,8,0.141604,1],
595
+ # ]
596
+ #
597
+ return self.parse_order_book(response, symbol)
598
+
599
+ def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
600
+ #
601
+ # fetchTicker
602
+ #
603
+ # {
604
+ # "OMSId":1,
605
+ # "InstrumentId":8,
606
+ # "BestBid":19069.31,
607
+ # "BestOffer":19069.32,
608
+ # "LastTradedPx":19069.32,
609
+ # "LastTradedQty":0.0001,
610
+ # "LastTradeTime":1607040406424,
611
+ # "SessionOpen":19069.32,
612
+ # "SessionHigh":19069.32,
613
+ # "SessionLow":19069.32,
614
+ # "SessionClose":19069.32,
615
+ # "Volume":0.0001,
616
+ # "CurrentDayVolume":0.0001,
617
+ # "CurrentDayNotional":1.906932,
618
+ # "CurrentDayNumTrades":1,
619
+ # "CurrentDayPxChange":0.00,
620
+ # "Rolling24HrVolume":0.000000000000000000000000000,
621
+ # "Rolling24HrNotional":0.00000000000000000000000,
622
+ # "Rolling24NumTrades":0,
623
+ # "Rolling24HrPxChange":0,
624
+ # "TimeStamp":"1607040406425",
625
+ # "BidQty":0,
626
+ # "AskQty":0,
627
+ # "BidOrderCt":0,
628
+ # "AskOrderCt":0,
629
+ # "Rolling24HrPxChangePercent":0,
630
+ # }
631
+ #
632
+ timestamp = self.safe_integer(ticker, 'TimeStamp')
633
+ marketId = self.safe_string(ticker, 'InstrumentId')
634
+ market = self.safe_market(marketId, market)
635
+ symbol = self.safe_symbol(marketId, market)
636
+ last = self.safe_string(ticker, 'LastTradedPx')
637
+ percentage = self.safe_string(ticker, 'Rolling24HrPxChangePercent')
638
+ change = self.safe_string(ticker, 'Rolling24HrPxChange')
639
+ open = self.safe_string(ticker, 'SessionOpen')
640
+ baseVolume = self.safe_string(ticker, 'Rolling24HrVolume')
641
+ quoteVolume = self.safe_string(ticker, 'Rolling24HrNotional')
642
+ return self.safe_ticker({
643
+ 'symbol': symbol,
644
+ 'timestamp': timestamp,
645
+ 'datetime': self.iso8601(timestamp),
646
+ 'high': self.safe_string(ticker, 'SessionHigh'),
647
+ 'low': self.safe_string(ticker, 'SessionLow'),
648
+ 'bid': self.safe_string(ticker, 'BestBid'),
649
+ 'bidVolume': None, # self.safe_number(ticker, 'BidQty'), always shows 0
650
+ 'ask': self.safe_string(ticker, 'BestOffer'),
651
+ 'askVolume': None, # self.safe_number(ticker, 'AskQty'), always shows 0
652
+ 'vwap': None,
653
+ 'open': open,
654
+ 'close': last,
655
+ 'last': last,
656
+ 'previousClose': None,
657
+ 'change': change,
658
+ 'percentage': percentage,
659
+ 'average': None,
660
+ 'baseVolume': baseVolume,
661
+ 'quoteVolume': quoteVolume,
662
+ 'info': ticker,
663
+ }, market)
664
+
665
+ def fetch_ticker(self, symbol: str, params={}) -> Ticker:
666
+ """
667
+ fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
668
+ :see: https://apidoc.ndax.io/#getlevel1
669
+ :param str symbol: unified symbol of the market to fetch the ticker for
670
+ :param dict [params]: extra parameters specific to the exchange API endpoint
671
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
672
+ """
673
+ omsId = self.safe_integer(self.options, 'omsId', 1)
674
+ self.load_markets()
675
+ market = self.market(symbol)
676
+ request: dict = {
677
+ 'omsId': omsId,
678
+ 'InstrumentId': market['id'],
679
+ }
680
+ response = self.publicGetGetLevel1(self.extend(request, params))
681
+ #
682
+ # {
683
+ # "OMSId":1,
684
+ # "InstrumentId":8,
685
+ # "BestBid":19069.31,
686
+ # "BestOffer":19069.32,
687
+ # "LastTradedPx":19069.32,
688
+ # "LastTradedQty":0.0001,
689
+ # "LastTradeTime":1607040406424,
690
+ # "SessionOpen":19069.32,
691
+ # "SessionHigh":19069.32,
692
+ # "SessionLow":19069.32,
693
+ # "SessionClose":19069.32,
694
+ # "Volume":0.0001,
695
+ # "CurrentDayVolume":0.0001,
696
+ # "CurrentDayNotional":1.906932,
697
+ # "CurrentDayNumTrades":1,
698
+ # "CurrentDayPxChange":0.00,
699
+ # "Rolling24HrVolume":0.000000000000000000000000000,
700
+ # "Rolling24HrNotional":0.00000000000000000000000,
701
+ # "Rolling24NumTrades":0,
702
+ # "Rolling24HrPxChange":0,
703
+ # "TimeStamp":"1607040406425",
704
+ # "BidQty":0,
705
+ # "AskQty":0,
706
+ # "BidOrderCt":0,
707
+ # "AskOrderCt":0,
708
+ # "Rolling24HrPxChangePercent":0,
709
+ # }
710
+ #
711
+ return self.parse_ticker(response, market)
712
+
713
+ def parse_ohlcv(self, ohlcv, market: Market = None) -> list:
714
+ #
715
+ # [
716
+ # 1501603632000, # 0 DateTime
717
+ # 2700.33, # 1 High
718
+ # 2687.01, # 2 Low
719
+ # 2687.01, # 3 Open
720
+ # 2687.01, # 4 Close
721
+ # 24.86100992, # 5 Volume
722
+ # 0, # 6 Inside Bid Price
723
+ # 2870.95, # 7 Inside Ask Price
724
+ # 1 # 8 InstrumentId
725
+ # ]
726
+ #
727
+ return [
728
+ self.safe_integer(ohlcv, 0),
729
+ self.safe_number(ohlcv, 3),
730
+ self.safe_number(ohlcv, 1),
731
+ self.safe_number(ohlcv, 2),
732
+ self.safe_number(ohlcv, 4),
733
+ self.safe_number(ohlcv, 5),
734
+ ]
735
+
736
+ def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
737
+ """
738
+ fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
739
+ :see: https://apidoc.ndax.io/#gettickerhistory
740
+ :param str symbol: unified symbol of the market to fetch OHLCV data for
741
+ :param str timeframe: the length of time each candle represents
742
+ :param int [since]: timestamp in ms of the earliest candle to fetch
743
+ :param int [limit]: the maximum amount of candles to fetch
744
+ :param dict [params]: extra parameters specific to the exchange API endpoint
745
+ :returns int[][]: A list of candles ordered, open, high, low, close, volume
746
+ """
747
+ omsId = self.safe_integer(self.options, 'omsId', 1)
748
+ self.load_markets()
749
+ market = self.market(symbol)
750
+ request: dict = {
751
+ 'omsId': omsId,
752
+ 'InstrumentId': market['id'],
753
+ 'Interval': self.safe_string(self.timeframes, timeframe, timeframe),
754
+ }
755
+ duration = self.parse_timeframe(timeframe)
756
+ now = self.milliseconds()
757
+ if since is None:
758
+ if limit is not None:
759
+ request['FromDate'] = self.ymdhms(now - duration * limit * 1000)
760
+ request['ToDate'] = self.ymdhms(now)
761
+ else:
762
+ request['FromDate'] = self.ymdhms(since)
763
+ if limit is None:
764
+ request['ToDate'] = self.ymdhms(now)
765
+ else:
766
+ request['ToDate'] = self.ymdhms(self.sum(since, duration * limit * 1000))
767
+ response = self.publicGetGetTickerHistory(self.extend(request, params))
768
+ #
769
+ # [
770
+ # [1607299260000,19069.32,19069.32,19069.32,19069.32,0,19069.31,19069.32,8,1607299200000],
771
+ # [1607299320000,19069.32,19069.32,19069.32,19069.32,0,19069.31,19069.32,8,1607299260000],
772
+ # [1607299380000,19069.32,19069.32,19069.32,19069.32,0,19069.31,19069.32,8,1607299320000],
773
+ # ]
774
+ #
775
+ return self.parse_ohlcvs(response, market, timeframe, since, limit)
776
+
777
+ def parse_trade(self, trade: dict, market: Market = None) -> Trade:
778
+ #
779
+ # fetchTrades(public)
780
+ #
781
+ # [
782
+ # 6913253, # 0 TradeId
783
+ # 8, # 1 ProductPairCode
784
+ # 0.03340802, # 2 Quantity
785
+ # 19116.08, # 3 Price
786
+ # 2543425077, # 4 Order1
787
+ # 2543425482, # 5 Order2
788
+ # 1606935922416, # 6 Tradetime
789
+ # 0, # 7 Direction
790
+ # 1, # 8 TakerSide
791
+ # 0, # 9 BlockTrade
792
+ # 0, # 10 Either Order1ClientId or Order2ClientId
793
+ # ]
794
+ #
795
+ # fetchMyTrades(private)
796
+ #
797
+ # {
798
+ # "OMSId":1,
799
+ # "ExecutionId":16916567,
800
+ # "TradeId":14476351,
801
+ # "OrderId":2543565231,
802
+ # "AccountId":449,
803
+ # "AccountName":"igor@ccxt.trade",
804
+ # "SubAccountId":0,
805
+ # "ClientOrderId":0,
806
+ # "InstrumentId":8,
807
+ # "Side":"Sell",
808
+ # "OrderType":"Market",
809
+ # "Quantity":0.1230000000000000000000000000,
810
+ # "RemainingQuantity":0.0000000000000000000000000000,
811
+ # "Price":19069.310000000000000000000000,
812
+ # "Value":2345.5251300000000000000000000,
813
+ # "CounterParty":"7",
814
+ # "OrderTradeRevision":1,
815
+ # "Direction":"NoChange",
816
+ # "IsBlockTrade":false,
817
+ # "Fee":1.1727625650000000000000000000,
818
+ # "FeeProductId":8,
819
+ # "OrderOriginator":446,
820
+ # "UserName":"igor@ccxt.trade",
821
+ # "TradeTimeMS":1607565031569,
822
+ # "MakerTaker":"Taker",
823
+ # "AdapterTradeId":0,
824
+ # "InsideBid":19069.310000000000000000000000,
825
+ # "InsideBidSize":0.2400950000000000000000000000,
826
+ # "InsideAsk":19069.320000000000000000000000,
827
+ # "InsideAskSize":0.0997360000000000000000000000,
828
+ # "IsQuote":false,
829
+ # "CounterPartyClientUserId":1,
830
+ # "NotionalProductId":2,
831
+ # "NotionalRate":1.0000000000000000000000000000,
832
+ # "NotionalValue":2345.5251300000000000000000000,
833
+ # "NotionalHoldAmount":0,
834
+ # "TradeTime":637431618315686826
835
+ # }
836
+ #
837
+ # fetchOrderTrades
838
+ #
839
+ # {
840
+ # "Side":"Sell",
841
+ # "OrderId":2543565235,
842
+ # "Price":18600.000000000000000000000000,
843
+ # "Quantity":0.0000000000000000000000000000,
844
+ # "DisplayQuantity":0.0000000000000000000000000000,
845
+ # "Instrument":8,
846
+ # "Account":449,
847
+ # "AccountName":"igor@ccxt.trade",
848
+ # "OrderType":"Limit",
849
+ # "ClientOrderId":0,
850
+ # "OrderState":"FullyExecuted",
851
+ # "ReceiveTime":1607585844956,
852
+ # "ReceiveTimeTicks":637431826449564182,
853
+ # "LastUpdatedTime":1607585844959,
854
+ # "LastUpdatedTimeTicks":637431826449593893,
855
+ # "OrigQuantity":0.1230000000000000000000000000,
856
+ # "QuantityExecuted":0.1230000000000000000000000000,
857
+ # "GrossValueExecuted":2345.3947500000000000000000000,
858
+ # "ExecutableValue":0.0000000000000000000000000000,
859
+ # "AvgPrice":19068.250000000000000000000000,
860
+ # "CounterPartyId":0,
861
+ # "ChangeReason":"Trade",
862
+ # "OrigOrderId":2543565235,
863
+ # "OrigClOrdId":0,
864
+ # "EnteredBy":446,
865
+ # "UserName":"igor@ccxt.trade",
866
+ # "IsQuote":false,
867
+ # "InsideAsk":19069.320000000000000000000000,
868
+ # "InsideAskSize":0.0997360000000000000000000000,
869
+ # "InsideBid":19068.250000000000000000000000,
870
+ # "InsideBidSize":1.3300010000000000000000000000,
871
+ # "LastTradePrice":19068.250000000000000000000000,
872
+ # "RejectReason":"",
873
+ # "IsLockedIn":false,
874
+ # "CancelReason":"",
875
+ # "OrderFlag":"0",
876
+ # "UseMargin":false,
877
+ # "StopPrice":0.0000000000000000000000000000,
878
+ # "PegPriceType":"Unknown",
879
+ # "PegOffset":0.0000000000000000000000000000,
880
+ # "PegLimitOffset":0.0000000000000000000000000000,
881
+ # "IpAddress":"x.x.x.x",
882
+ # "ClientOrderIdUuid":null,
883
+ # "OMSId":1
884
+ # }
885
+ #
886
+ priceString = None
887
+ amountString = None
888
+ costString = None
889
+ timestamp = None
890
+ id = None
891
+ marketId = None
892
+ side = None
893
+ orderId = None
894
+ takerOrMaker = None
895
+ fee = None
896
+ type = None
897
+ if isinstance(trade, list):
898
+ priceString = self.safe_string(trade, 3)
899
+ amountString = self.safe_string(trade, 2)
900
+ timestamp = self.safe_integer(trade, 6)
901
+ id = self.safe_string(trade, 0)
902
+ marketId = self.safe_string(trade, 1)
903
+ takerSide = self.safe_value(trade, 8)
904
+ side = 'sell' if takerSide else 'buy'
905
+ orderId = self.safe_string(trade, 4)
906
+ else:
907
+ timestamp = self.safe_integer_2(trade, 'TradeTimeMS', 'ReceiveTime')
908
+ id = self.safe_string(trade, 'TradeId')
909
+ orderId = self.safe_string_2(trade, 'OrderId', 'OrigOrderId')
910
+ marketId = self.safe_string_2(trade, 'InstrumentId', 'Instrument')
911
+ priceString = self.safe_string(trade, 'Price')
912
+ amountString = self.safe_string(trade, 'Quantity')
913
+ costString = self.safe_string_2(trade, 'Value', 'GrossValueExecuted')
914
+ takerOrMaker = self.safe_string_lower(trade, 'MakerTaker')
915
+ side = self.safe_string_lower(trade, 'Side')
916
+ type = self.safe_string_lower(trade, 'OrderType')
917
+ feeCostString = self.safe_string(trade, 'Fee')
918
+ if feeCostString is not None:
919
+ feeCurrencyId = self.safe_string(trade, 'FeeProductId')
920
+ feeCurrencyCode = self.safe_currency_code(feeCurrencyId)
921
+ fee = {
922
+ 'cost': feeCostString,
923
+ 'currency': feeCurrencyCode,
924
+ }
925
+ symbol = self.safe_symbol(marketId, market)
926
+ return self.safe_trade({
927
+ 'info': trade,
928
+ 'id': id,
929
+ 'symbol': symbol,
930
+ 'timestamp': timestamp,
931
+ 'datetime': self.iso8601(timestamp),
932
+ 'order': orderId,
933
+ 'type': type,
934
+ 'side': side,
935
+ 'takerOrMaker': takerOrMaker,
936
+ 'price': priceString,
937
+ 'amount': amountString,
938
+ 'cost': costString,
939
+ 'fee': fee,
940
+ }, market)
941
+
942
+ def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
943
+ """
944
+ get the list of most recent trades for a particular symbol
945
+ :param str symbol: unified symbol of the market to fetch trades for
946
+ :param int [since]: timestamp in ms of the earliest trade to fetch
947
+ :param int [limit]: the maximum amount of trades to fetch
948
+ :param dict [params]: extra parameters specific to the exchange API endpoint
949
+ :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
950
+ """
951
+ omsId = self.safe_integer(self.options, 'omsId', 1)
952
+ self.load_markets()
953
+ market = self.market(symbol)
954
+ request: dict = {
955
+ 'omsId': omsId,
956
+ 'InstrumentId': market['id'],
957
+ }
958
+ if limit is not None:
959
+ request['Count'] = limit
960
+ response = self.publicGetGetLastTrades(self.extend(request, params))
961
+ #
962
+ # [
963
+ # [6913253,8,0.03340802,19116.08,2543425077,2543425482,1606935922416,0,1,0,0],
964
+ # [6913254,8,0.01391671,19117.42,2543427510,2543427811,1606935927998,1,1,0,0],
965
+ # [6913255,8,0.000006,19107.81,2543430495,2543430793,1606935933881,2,0,0,0],
966
+ # ]
967
+ #
968
+ return self.parse_trades(response, market, since, limit)
969
+
970
+ def fetch_accounts(self, params={}) -> List[Account]:
971
+ """
972
+ fetch all the accounts associated with a profile
973
+ :see: https://apidoc.ndax.io/#getuseraccounts
974
+ :param dict [params]: extra parameters specific to the exchange API endpoint
975
+ :returns dict: a dictionary of `account structures <https://docs.ccxt.com/#/?id=account-structure>` indexed by the account type
976
+ """
977
+ if not self.login:
978
+ raise AuthenticationError(self.id + ' fetchAccounts() requires exchange.login email credential')
979
+ omsId = self.safe_integer(self.options, 'omsId', 1)
980
+ self.check_required_credentials()
981
+ request: dict = {
982
+ 'omsId': omsId,
983
+ 'UserId': self.uid,
984
+ 'UserName': self.login,
985
+ }
986
+ response = self.privateGetGetUserAccounts(self.extend(request, params))
987
+ #
988
+ # [449] # comma-separated list of account ids
989
+ #
990
+ result = []
991
+ for i in range(0, len(response)):
992
+ accountId = self.safe_string(response, i)
993
+ result.append({
994
+ 'id': accountId,
995
+ 'type': None,
996
+ 'currency': None,
997
+ 'info': accountId,
998
+ })
999
+ return result
1000
+
1001
+ def parse_balance(self, response) -> Balances:
1002
+ result: dict = {
1003
+ 'info': response,
1004
+ 'timestamp': None,
1005
+ 'datetime': None,
1006
+ }
1007
+ for i in range(0, len(response)):
1008
+ balance = response[i]
1009
+ currencyId = self.safe_string(balance, 'ProductId')
1010
+ if currencyId in self.currencies_by_id:
1011
+ code = self.safe_currency_code(currencyId)
1012
+ account = self.account()
1013
+ account['total'] = self.safe_string(balance, 'Amount')
1014
+ account['used'] = self.safe_string(balance, 'Hold')
1015
+ result[code] = account
1016
+ return self.safe_balance(result)
1017
+
1018
+ def fetch_balance(self, params={}) -> Balances:
1019
+ """
1020
+ query for balance and get the amount of funds available for trading or funds locked in orders
1021
+ :see: https://apidoc.ndax.io/#getaccountpositions
1022
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1023
+ :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
1024
+ """
1025
+ omsId = self.safe_integer(self.options, 'omsId', 1)
1026
+ self.load_markets()
1027
+ self.load_accounts()
1028
+ defaultAccountId = self.safe_integer_2(self.options, 'accountId', 'AccountId', int(self.accounts[0]['id']))
1029
+ accountId = self.safe_integer_2(params, 'accountId', 'AccountId', defaultAccountId)
1030
+ params = self.omit(params, ['accountId', 'AccountId'])
1031
+ request: dict = {
1032
+ 'omsId': omsId,
1033
+ 'AccountId': accountId,
1034
+ }
1035
+ response = self.privateGetGetAccountPositions(self.extend(request, params))
1036
+ #
1037
+ # [
1038
+ # {
1039
+ # "OMSId":1,
1040
+ # "AccountId":449,
1041
+ # "ProductSymbol":"BTC",
1042
+ # "ProductId":1,
1043
+ # "Amount":10.000000000000000000000000000,
1044
+ # "Hold":0,
1045
+ # "PendingDeposits":0.0000000000000000000000000000,
1046
+ # "PendingWithdraws":0.0000000000000000000000000000,
1047
+ # "TotalDayDeposits":10.000000000000000000000000000,
1048
+ # "TotalMonthDeposits":10.000000000000000000000000000,
1049
+ # "TotalYearDeposits":10.000000000000000000000000000,
1050
+ # "TotalDayDepositNotional":10.000000000000000000000000000,
1051
+ # "TotalMonthDepositNotional":10.000000000000000000000000000,
1052
+ # "TotalYearDepositNotional":10.000000000000000000000000000,
1053
+ # "TotalDayWithdraws":0,
1054
+ # "TotalMonthWithdraws":0,
1055
+ # "TotalYearWithdraws":0,
1056
+ # "TotalDayWithdrawNotional":0,
1057
+ # "TotalMonthWithdrawNotional":0,
1058
+ # "TotalYearWithdrawNotional":0,
1059
+ # "NotionalProductId":8,
1060
+ # "NotionalProductSymbol":"USDT",
1061
+ # "NotionalValue":10.000000000000000000000000000,
1062
+ # "NotionalHoldAmount":0,
1063
+ # "NotionalRate":1
1064
+ # },
1065
+ # ]
1066
+ #
1067
+ return self.parse_balance(response)
1068
+
1069
+ def parse_ledger_entry_type(self, type):
1070
+ types: dict = {
1071
+ 'Trade': 'trade',
1072
+ 'Deposit': 'transaction',
1073
+ 'Withdraw': 'transaction',
1074
+ 'Transfer': 'transfer',
1075
+ 'OrderHold': 'trade',
1076
+ 'WithdrawHold': 'transaction',
1077
+ 'DepositHold': 'transaction',
1078
+ 'MarginHold': 'trade',
1079
+ 'ManualHold': 'trade',
1080
+ 'ManualEntry': 'trade',
1081
+ 'MarginAcquisition': 'trade',
1082
+ 'MarginRelinquish': 'trade',
1083
+ 'MarginQuoteHold': 'trade',
1084
+ }
1085
+ return self.safe_string(types, type, type)
1086
+
1087
+ def parse_ledger_entry(self, item: dict, currency: Currency = None):
1088
+ #
1089
+ # {
1090
+ # "TransactionId": 2663709493,
1091
+ # "ReferenceId": 68,
1092
+ # "OMSId": 1,
1093
+ # "AccountId": 449,
1094
+ # "CR": 10.000000000000000000000000000,
1095
+ # "DR": 0.0000000000000000000000000000,
1096
+ # "Counterparty": 3,
1097
+ # "TransactionType": "Other",
1098
+ # "ReferenceType": "Deposit",
1099
+ # "ProductId": 1,
1100
+ # "Balance": 10.000000000000000000000000000,
1101
+ # "TimeStamp": 1607532331591
1102
+ # }
1103
+ #
1104
+ currencyId = self.safe_string(item, 'ProductId')
1105
+ credit = self.safe_string(item, 'CR')
1106
+ debit = self.safe_string(item, 'DR')
1107
+ amount = None
1108
+ direction = None
1109
+ if Precise.string_lt(credit, '0'):
1110
+ amount = credit
1111
+ direction = 'in'
1112
+ elif Precise.string_lt(debit, '0'):
1113
+ amount = debit
1114
+ direction = 'out'
1115
+ before = None
1116
+ after = self.safe_string(item, 'Balance')
1117
+ if direction == 'out':
1118
+ before = Precise.string_add(after, amount)
1119
+ elif direction == 'in':
1120
+ before = Precise.string_max('0', Precise.string_sub(after, amount))
1121
+ timestamp = self.safe_integer(item, 'TimeStamp')
1122
+ return {
1123
+ 'info': item,
1124
+ 'id': self.safe_string(item, 'TransactionId'),
1125
+ 'direction': direction,
1126
+ 'account': self.safe_string(item, 'AccountId'),
1127
+ 'referenceId': self.safe_string(item, 'ReferenceId'),
1128
+ 'referenceAccount': self.safe_string(item, 'Counterparty'),
1129
+ 'type': self.parse_ledger_entry_type(self.safe_string(item, 'ReferenceType')),
1130
+ 'currency': self.safe_currency_code(currencyId, currency),
1131
+ 'amount': self.parse_number(amount),
1132
+ 'before': self.parse_number(before),
1133
+ 'after': self.parse_number(after),
1134
+ 'status': 'ok',
1135
+ 'timestamp': timestamp,
1136
+ 'datetime': self.iso8601(timestamp),
1137
+ 'fee': None,
1138
+ }
1139
+
1140
+ def fetch_ledger(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
1141
+ """
1142
+ fetch the history of changes, actions done by the user or operations that altered balance of the user
1143
+ :see: https://apidoc.ndax.io/#getaccounttransactions
1144
+ :param str code: unified currency code, default is None
1145
+ :param int [since]: timestamp in ms of the earliest ledger entry, default is None
1146
+ :param int [limit]: max number of ledger entrys to return, default is None
1147
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1148
+ :returns dict: a `ledger structure <https://docs.ccxt.com/#/?id=ledger-structure>`
1149
+ """
1150
+ omsId = self.safe_integer(self.options, 'omsId', 1)
1151
+ self.load_markets()
1152
+ self.load_accounts()
1153
+ defaultAccountId = self.safe_integer_2(self.options, 'accountId', 'AccountId', int(self.accounts[0]['id']))
1154
+ accountId = self.safe_integer_2(params, 'accountId', 'AccountId', defaultAccountId)
1155
+ params = self.omit(params, ['accountId', 'AccountId'])
1156
+ request: dict = {
1157
+ 'omsId': omsId,
1158
+ 'AccountId': accountId,
1159
+ }
1160
+ if limit is not None:
1161
+ request['Depth'] = limit
1162
+ response = self.privateGetGetAccountTransactions(self.extend(request, params))
1163
+ #
1164
+ # [
1165
+ # {
1166
+ # "TransactionId":2663709493,
1167
+ # "ReferenceId":68,
1168
+ # "OMSId":1,
1169
+ # "AccountId":449,
1170
+ # "CR":10.000000000000000000000000000,
1171
+ # "DR":0.0000000000000000000000000000,
1172
+ # "Counterparty":3,
1173
+ # "TransactionType":"Other",
1174
+ # "ReferenceType":"Deposit",
1175
+ # "ProductId":1,
1176
+ # "Balance":10.000000000000000000000000000,
1177
+ # "TimeStamp":1607532331591
1178
+ # },
1179
+ # ]
1180
+ #
1181
+ currency = None
1182
+ if code is not None:
1183
+ currency = self.currency(code)
1184
+ return self.parse_ledger(response, currency, since, limit)
1185
+
1186
+ def parse_order_status(self, status: Str):
1187
+ statuses: dict = {
1188
+ 'Accepted': 'open',
1189
+ 'Rejected': 'rejected',
1190
+ 'Working': 'open',
1191
+ 'Canceled': 'canceled',
1192
+ 'Expired': 'expired',
1193
+ 'FullyExecuted': 'closed',
1194
+ }
1195
+ return self.safe_string(statuses, status, status)
1196
+
1197
+ def parse_order(self, order: dict, market: Market = None) -> Order:
1198
+ #
1199
+ # createOrder
1200
+ #
1201
+ # {
1202
+ # "status":"Accepted",
1203
+ # "errormsg":"",
1204
+ # "OrderId": 2543565231
1205
+ # }
1206
+ #
1207
+ # editOrder
1208
+ #
1209
+ # {
1210
+ # "ReplacementOrderId": 1234,
1211
+ # "ReplacementClOrdId": 1561,
1212
+ # "OrigOrderId": 5678,
1213
+ # "OrigClOrdId": 91011,
1214
+ # }
1215
+ #
1216
+ # fetchOpenOrders, fetchClosedOrders
1217
+ #
1218
+ # {
1219
+ # "Side":"Buy",
1220
+ # "OrderId":2543565233,
1221
+ # "Price":19010,
1222
+ # "Quantity":0.345,
1223
+ # "DisplayQuantity":0.345,
1224
+ # "Instrument":8,
1225
+ # "Account":449,
1226
+ # "AccountName":"igor@ccxt.trade",
1227
+ # "OrderType":"Limit",
1228
+ # "ClientOrderId":0,
1229
+ # "OrderState":"Working",
1230
+ # "ReceiveTime":1607579326003,
1231
+ # "ReceiveTimeTicks":637431761260028981,
1232
+ # "LastUpdatedTime":1607579326005,
1233
+ # "LastUpdatedTimeTicks":637431761260054714,
1234
+ # "OrigQuantity":0.345,
1235
+ # "QuantityExecuted":0,
1236
+ # "GrossValueExecuted":0,
1237
+ # "ExecutableValue":0,
1238
+ # "AvgPrice":0,
1239
+ # "CounterPartyId":0,
1240
+ # "ChangeReason":"NewInputAccepted",
1241
+ # "OrigOrderId":2543565233,
1242
+ # "OrigClOrdId":0,
1243
+ # "EnteredBy":446,
1244
+ # "UserName":"igor@ccxt.trade",
1245
+ # "IsQuote":false,
1246
+ # "InsideAsk":19069.32,
1247
+ # "InsideAskSize":0.099736,
1248
+ # "InsideBid":19068.25,
1249
+ # "InsideBidSize":1.330001,
1250
+ # "LastTradePrice":19068.25,
1251
+ # "RejectReason":"",
1252
+ # "IsLockedIn":false,
1253
+ # "CancelReason":"",
1254
+ # "OrderFlag":"AddedToBook",
1255
+ # "UseMargin":false,
1256
+ # "StopPrice":0,
1257
+ # "PegPriceType":"Unknown",
1258
+ # "PegOffset":0,
1259
+ # "PegLimitOffset":0,
1260
+ # "IpAddress":null,
1261
+ # "ClientOrderIdUuid":null,
1262
+ # "OMSId":1
1263
+ # }
1264
+ #
1265
+ timestamp = self.safe_integer(order, 'ReceiveTime')
1266
+ marketId = self.safe_string(order, 'Instrument')
1267
+ return self.safe_order({
1268
+ 'id': self.safe_string_2(order, 'ReplacementOrderId', 'OrderId'),
1269
+ 'clientOrderId': self.safe_string_2(order, 'ReplacementClOrdId', 'ClientOrderId'),
1270
+ 'info': order,
1271
+ 'timestamp': timestamp,
1272
+ 'datetime': self.iso8601(timestamp),
1273
+ 'lastTradeTimestamp': self.safe_integer(order, 'LastUpdatedTime'),
1274
+ 'status': self.parse_order_status(self.safe_string(order, 'OrderState')),
1275
+ 'symbol': self.safe_symbol(marketId, market),
1276
+ 'type': self.safe_string_lower(order, 'OrderType'),
1277
+ 'timeInForce': None,
1278
+ 'postOnly': None,
1279
+ 'side': self.safe_string_lower(order, 'Side'),
1280
+ 'price': self.safe_string(order, 'Price'),
1281
+ 'stopPrice': self.parse_number(self.omit_zero(self.safe_string(order, 'StopPrice'))),
1282
+ 'cost': self.safe_string(order, 'GrossValueExecuted'),
1283
+ 'amount': self.safe_string(order, 'OrigQuantity'),
1284
+ 'filled': self.safe_string(order, 'QuantityExecuted'),
1285
+ 'average': self.safe_string(order, 'AvgPrice'),
1286
+ 'remaining': None,
1287
+ 'fee': None,
1288
+ 'trades': None,
1289
+ }, market)
1290
+
1291
+ def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
1292
+ """
1293
+ create a trade order
1294
+ :see: https://apidoc.ndax.io/#sendorder
1295
+ :param str symbol: unified symbol of the market to create an order in
1296
+ :param str type: 'market' or 'limit'
1297
+ :param str side: 'buy' or 'sell'
1298
+ :param float amount: how much of currency you want to trade in units of base currency
1299
+ :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
1300
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1301
+ :param float [params.triggerPrice]: the price at which a trigger order would be triggered
1302
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1303
+ """
1304
+ omsId = self.safe_integer(self.options, 'omsId', 1)
1305
+ self.load_markets()
1306
+ self.load_accounts()
1307
+ defaultAccountId = self.safe_integer_2(self.options, 'accountId', 'AccountId', int(self.accounts[0]['id']))
1308
+ accountId = self.safe_integer_2(params, 'accountId', 'AccountId', defaultAccountId)
1309
+ clientOrderId = self.safe_integer_2(params, 'ClientOrderId', 'clientOrderId')
1310
+ orderType = self.safe_integer(self.options['orderTypes'], self.capitalize(type))
1311
+ triggerPrice = self.safe_string(params, 'triggerPrice')
1312
+ if triggerPrice is not None:
1313
+ if type == 'market':
1314
+ orderType = 3
1315
+ elif type == 'limit':
1316
+ orderType = 4
1317
+ params = self.omit(params, ['accountId', 'AccountId', 'clientOrderId', 'ClientOrderId', 'triggerPrice'])
1318
+ market = self.market(symbol)
1319
+ orderSide = 0 if (side == 'buy') else 1
1320
+ request: dict = {
1321
+ 'InstrumentId': int(market['id']),
1322
+ 'omsId': omsId,
1323
+ 'AccountId': accountId,
1324
+ 'TimeInForce': 1, # 0 Unknown, 1 GTC by default, 2 OPG execute to opening price, 3 IOC immediate or canceled, 4 FOK fill-or-kill, 5 GTX good 'til executed, 6 GTD good 'til date
1325
+ # 'ClientOrderId': clientOrderId, # defaults to 0
1326
+ # If self order is order A, OrderIdOCO refers to the order ID of an order B(which is not the order being created by self call).
1327
+ # If order B executes, then order A created by self call is canceled.
1328
+ # 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 self one, which could have implications for priority in the order book.
1329
+ # See CancelReplaceOrder and ModifyOrder.
1330
+ # 'OrderIdOCO': 0, # The order ID if One Cancels the Other.
1331
+ # 'UseDisplayQuantity': False, # If you enter a Limit order with a reserve, you must set UseDisplayQuantity to True
1332
+ 'Side': orderSide, # 0 Buy, 1 Sell, 2 Short, 3 unknown an error condition
1333
+ 'Quantity': float(self.amount_to_precision(symbol, amount)),
1334
+ 'OrderType': orderType, # 0 Unknown, 1 Market, 2 Limit, 3 StopMarket, 4 StopLimit, 5 TrailingStopMarket, 6 TrailingStopLimit, 7 BlockTrade
1335
+ # 'PegPriceType': 3, # 1 Last, 2 Bid, 3 Ask, 4 Midpoint
1336
+ # 'LimitPrice': float(self.price_to_precision(symbol, price)),
1337
+ }
1338
+ # If OrderType=1(Market), Side=0(Buy), and LimitPrice is supplied, the Market order will execute up to the value specified
1339
+ if price is not None:
1340
+ request['LimitPrice'] = float(self.price_to_precision(symbol, price))
1341
+ if clientOrderId is not None:
1342
+ request['ClientOrderId'] = clientOrderId
1343
+ if triggerPrice is not None:
1344
+ request['StopPrice'] = triggerPrice
1345
+ response = self.privatePostSendOrder(self.extend(request, params))
1346
+ #
1347
+ # {
1348
+ # "status":"Accepted",
1349
+ # "errormsg":"",
1350
+ # "OrderId": 2543565231
1351
+ # }
1352
+ #
1353
+ return self.parse_order(response, market)
1354
+
1355
+ def edit_order(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}):
1356
+ omsId = self.safe_integer(self.options, 'omsId', 1)
1357
+ self.load_markets()
1358
+ self.load_accounts()
1359
+ defaultAccountId = self.safe_integer_2(self.options, 'accountId', 'AccountId', int(self.accounts[0]['id']))
1360
+ accountId = self.safe_integer_2(params, 'accountId', 'AccountId', defaultAccountId)
1361
+ clientOrderId = self.safe_integer_2(params, 'ClientOrderId', 'clientOrderId')
1362
+ params = self.omit(params, ['accountId', 'AccountId', 'clientOrderId', 'ClientOrderId'])
1363
+ market = self.market(symbol)
1364
+ orderSide = 0 if (side == 'buy') else 1
1365
+ request: dict = {
1366
+ 'OrderIdToReplace': int(id),
1367
+ 'InstrumentId': int(market['id']),
1368
+ 'omsId': omsId,
1369
+ 'AccountId': accountId,
1370
+ 'TimeInForce': 1, # 0 Unknown, 1 GTC by default, 2 OPG execute to opening price, 3 IOC immediate or canceled, 4 FOK fill-or-kill, 5 GTX good 'til executed, 6 GTD good 'til date
1371
+ # 'ClientOrderId': clientOrderId, # defaults to 0
1372
+ # If self order is order A, OrderIdOCO refers to the order ID of an order B(which is not the order being created by self call).
1373
+ # If order B executes, then order A created by self call is canceled.
1374
+ # 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 self one, which could have implications for priority in the order book.
1375
+ # See CancelReplaceOrder and ModifyOrder.
1376
+ # 'OrderIdOCO': 0, # The order ID if One Cancels the Other.
1377
+ # 'UseDisplayQuantity': False, # If you enter a Limit order with a reserve, you must set UseDisplayQuantity to True
1378
+ 'Side': orderSide, # 0 Buy, 1 Sell, 2 Short, 3 unknown an error condition
1379
+ 'Quantity': float(self.amount_to_precision(symbol, amount)),
1380
+ 'OrderType': self.safe_integer(self.options['orderTypes'], self.capitalize(type)), # 0 Unknown, 1 Market, 2 Limit, 3 StopMarket, 4 StopLimit, 5 TrailingStopMarket, 6 TrailingStopLimit, 7 BlockTrade
1381
+ # 'PegPriceType': 3, # 1 Last, 2 Bid, 3 Ask, 4 Midpoint
1382
+ # 'LimitPrice': float(self.price_to_precision(symbol, price)),
1383
+ }
1384
+ # If OrderType=1(Market), Side=0(Buy), and LimitPrice is supplied, the Market order will execute up to the value specified
1385
+ if price is not None:
1386
+ request['LimitPrice'] = float(self.price_to_precision(symbol, price))
1387
+ if clientOrderId is not None:
1388
+ request['ClientOrderId'] = clientOrderId
1389
+ response = self.privatePostCancelReplaceOrder(self.extend(request, params))
1390
+ #
1391
+ # {
1392
+ # "replacementOrderId": 1234,
1393
+ # "replacementClOrdId": 1561,
1394
+ # "origOrderId": 5678,
1395
+ # "origClOrdId": 91011,
1396
+ # }
1397
+ #
1398
+ return self.parse_order(response, market)
1399
+
1400
+ def fetch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1401
+ """
1402
+ fetch all trades made by the user
1403
+ :see: https://apidoc.ndax.io/#gettradeshistory
1404
+ :param str symbol: unified market symbol
1405
+ :param int [since]: the earliest time in ms to fetch trades for
1406
+ :param int [limit]: the maximum number of trades structures to retrieve
1407
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1408
+ :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
1409
+ """
1410
+ omsId = self.safe_integer(self.options, 'omsId', 1)
1411
+ self.load_markets()
1412
+ self.load_accounts()
1413
+ defaultAccountId = self.safe_integer_2(self.options, 'accountId', 'AccountId', int(self.accounts[0]['id']))
1414
+ accountId = self.safe_integer_2(params, 'accountId', 'AccountId', defaultAccountId)
1415
+ params = self.omit(params, ['accountId', 'AccountId'])
1416
+ request: dict = {
1417
+ 'omsId': omsId,
1418
+ 'AccountId': accountId,
1419
+ # 'InstrumentId': market['id'],
1420
+ # 'TradeId': 123, # If you specify TradeId, GetTradesHistory can return all states for a single trade
1421
+ # 'OrderId': 456, # If specified, the call returns all trades associated with the order
1422
+ # '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 self OMS.
1423
+ # '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 self account on the trading venue.
1424
+ # 'EndTimeStamp': long integer. Date at which to end the trade report, in POSIX format.
1425
+ # 'Depth': integer. In self 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.
1426
+ # 'StartIndex': 0 # from the most recent trade 0 and moving backwards in time
1427
+ # 'ExecutionId': 123, # The ID of the individual buy or sell execution. If not specified, returns all.
1428
+ }
1429
+ market = None
1430
+ if symbol is not None:
1431
+ market = self.market(symbol)
1432
+ request['InstrumentId'] = market['id']
1433
+ if since is not None:
1434
+ request['StartTimeStamp'] = self.parse_to_int(since / 1000)
1435
+ if limit is not None:
1436
+ request['Depth'] = limit
1437
+ response = self.privateGetGetTradesHistory(self.extend(request, params))
1438
+ #
1439
+ # [
1440
+ # {
1441
+ # "OMSId":1,
1442
+ # "ExecutionId":16916567,
1443
+ # "TradeId":14476351,
1444
+ # "OrderId":2543565231,
1445
+ # "AccountId":449,
1446
+ # "AccountName":"igor@ccxt.trade",
1447
+ # "SubAccountId":0,
1448
+ # "ClientOrderId":0,
1449
+ # "InstrumentId":8,
1450
+ # "Side":"Sell",
1451
+ # "OrderType":"Market",
1452
+ # "Quantity":0.1230000000000000000000000000,
1453
+ # "RemainingQuantity":0.0000000000000000000000000000,
1454
+ # "Price":19069.310000000000000000000000,
1455
+ # "Value":2345.5251300000000000000000000,
1456
+ # "CounterParty":"7",
1457
+ # "OrderTradeRevision":1,
1458
+ # "Direction":"NoChange",
1459
+ # "IsBlockTrade":false,
1460
+ # "Fee":1.1727625650000000000000000000,
1461
+ # "FeeProductId":8,
1462
+ # "OrderOriginator":446,
1463
+ # "UserName":"igor@ccxt.trade",
1464
+ # "TradeTimeMS":1607565031569,
1465
+ # "MakerTaker":"Taker",
1466
+ # "AdapterTradeId":0,
1467
+ # "InsideBid":19069.310000000000000000000000,
1468
+ # "InsideBidSize":0.2400950000000000000000000000,
1469
+ # "InsideAsk":19069.320000000000000000000000,
1470
+ # "InsideAskSize":0.0997360000000000000000000000,
1471
+ # "IsQuote":false,
1472
+ # "CounterPartyClientUserId":1,
1473
+ # "NotionalProductId":2,
1474
+ # "NotionalRate":1.0000000000000000000000000000,
1475
+ # "NotionalValue":2345.5251300000000000000000000,
1476
+ # "NotionalHoldAmount":0,
1477
+ # "TradeTime":637431618315686826
1478
+ # }
1479
+ # ]
1480
+ #
1481
+ return self.parse_trades(response, market, since, limit)
1482
+
1483
+ def cancel_all_orders(self, symbol: Str = None, params={}):
1484
+ """
1485
+ cancel all open orders
1486
+ :see: https://apidoc.ndax.io/#cancelallorders
1487
+ :param str symbol: unified market symbol, only orders in the market of self symbol are cancelled when symbol is not None
1488
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1489
+ :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1490
+ """
1491
+ omsId = self.safe_integer(self.options, 'omsId', 1)
1492
+ self.load_markets()
1493
+ self.load_accounts()
1494
+ defaultAccountId = self.safe_integer_2(self.options, 'accountId', 'AccountId', int(self.accounts[0]['id']))
1495
+ accountId = self.safe_integer_2(params, 'accountId', 'AccountId', defaultAccountId)
1496
+ params = self.omit(params, ['accountId', 'AccountId'])
1497
+ request: dict = {
1498
+ 'omsId': omsId,
1499
+ 'AccountId': accountId,
1500
+ }
1501
+ if symbol is not None:
1502
+ market = self.market(symbol)
1503
+ request['IntrumentId'] = market['id']
1504
+ response = self.privatePostCancelAllOrders(self.extend(request, params))
1505
+ #
1506
+ # {
1507
+ # "result":true,
1508
+ # "errormsg":null,
1509
+ # "errorcode":0,
1510
+ # "detail":null
1511
+ # }
1512
+ #
1513
+ return [
1514
+ self.safe_order({
1515
+ 'info': response,
1516
+ }),
1517
+ ]
1518
+
1519
+ def cancel_order(self, id: str, symbol: Str = None, params={}):
1520
+ """
1521
+ cancels an open order
1522
+ :see: https://apidoc.ndax.io/#cancelorder
1523
+ :param str id: order id
1524
+ :param str symbol: unified symbol of the market the order was made in
1525
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1526
+ :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1527
+ """
1528
+ omsId = self.safe_integer(self.options, 'omsId', 1)
1529
+ self.load_markets()
1530
+ self.load_accounts()
1531
+ # defaultAccountId = self.safe_integer_2(self.options, 'accountId', 'AccountId', int(self.accounts[0]['id']))
1532
+ # accountId = self.safe_integer_2(params, 'accountId', 'AccountId', defaultAccountId)
1533
+ # params = self.omit(params, ['accountId', 'AccountId'])
1534
+ market = None
1535
+ if symbol is not None:
1536
+ market = self.market(symbol)
1537
+ request: dict = {
1538
+ 'omsId': omsId,
1539
+ # 'AccountId': accountId,
1540
+ }
1541
+ clientOrderId = self.safe_integer_2(params, 'clientOrderId', 'ClOrderId')
1542
+ if clientOrderId is not None:
1543
+ request['ClOrderId'] = clientOrderId
1544
+ else:
1545
+ request['OrderId'] = int(id)
1546
+ params = self.omit(params, ['clientOrderId', 'ClOrderId'])
1547
+ response = self.privatePostCancelOrder(self.extend(request, params))
1548
+ order = self.parse_order(response, market)
1549
+ return self.extend(order, {
1550
+ 'id': id,
1551
+ 'clientOrderId': clientOrderId,
1552
+ })
1553
+
1554
+ def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1555
+ """
1556
+ fetch all unfilled currently open orders
1557
+ :see: https://apidoc.ndax.io/#getopenorders
1558
+ :param str symbol: unified market symbol
1559
+ :param int [since]: the earliest time in ms to fetch open orders for
1560
+ :param int [limit]: the maximum number of open orders structures to retrieve
1561
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1562
+ :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1563
+ """
1564
+ omsId = self.safe_integer(self.options, 'omsId', 1)
1565
+ self.load_markets()
1566
+ self.load_accounts()
1567
+ defaultAccountId = self.safe_integer_2(self.options, 'accountId', 'AccountId', int(self.accounts[0]['id']))
1568
+ accountId = self.safe_integer_2(params, 'accountId', 'AccountId', defaultAccountId)
1569
+ params = self.omit(params, ['accountId', 'AccountId'])
1570
+ market = None
1571
+ if symbol is not None:
1572
+ market = self.market(symbol)
1573
+ request: dict = {
1574
+ 'omsId': omsId,
1575
+ 'AccountId': accountId,
1576
+ }
1577
+ response = self.privateGetGetOpenOrders(self.extend(request, params))
1578
+ #
1579
+ # [
1580
+ # {
1581
+ # "Side":"Buy",
1582
+ # "OrderId":2543565233,
1583
+ # "Price":19010,
1584
+ # "Quantity":0.345,
1585
+ # "DisplayQuantity":0.345,
1586
+ # "Instrument":8,
1587
+ # "Account":449,
1588
+ # "AccountName":"igor@ccxt.trade",
1589
+ # "OrderType":"Limit",
1590
+ # "ClientOrderId":0,
1591
+ # "OrderState":"Working",
1592
+ # "ReceiveTime":1607579326003,
1593
+ # "ReceiveTimeTicks":637431761260028981,
1594
+ # "LastUpdatedTime":1607579326005,
1595
+ # "LastUpdatedTimeTicks":637431761260054714,
1596
+ # "OrigQuantity":0.345,
1597
+ # "QuantityExecuted":0,
1598
+ # "GrossValueExecuted":0,
1599
+ # "ExecutableValue":0,
1600
+ # "AvgPrice":0,
1601
+ # "CounterPartyId":0,
1602
+ # "ChangeReason":"NewInputAccepted",
1603
+ # "OrigOrderId":2543565233,
1604
+ # "OrigClOrdId":0,
1605
+ # "EnteredBy":446,
1606
+ # "UserName":"igor@ccxt.trade",
1607
+ # "IsQuote":false,
1608
+ # "InsideAsk":19069.32,
1609
+ # "InsideAskSize":0.099736,
1610
+ # "InsideBid":19068.25,
1611
+ # "InsideBidSize":1.330001,
1612
+ # "LastTradePrice":19068.25,
1613
+ # "RejectReason":"",
1614
+ # "IsLockedIn":false,
1615
+ # "CancelReason":"",
1616
+ # "OrderFlag":"AddedToBook",
1617
+ # "UseMargin":false,
1618
+ # "StopPrice":0,
1619
+ # "PegPriceType":"Unknown",
1620
+ # "PegOffset":0,
1621
+ # "PegLimitOffset":0,
1622
+ # "IpAddress":null,
1623
+ # "ClientOrderIdUuid":null,
1624
+ # "OMSId":1
1625
+ # }
1626
+ # ]
1627
+ #
1628
+ return self.parse_orders(response, market, since, limit)
1629
+
1630
+ def fetch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1631
+ """
1632
+ fetches information on multiple orders made by the user
1633
+ :see: https://apidoc.ndax.io/#getorderhistory
1634
+ :param str symbol: unified market symbol of the market orders were made in
1635
+ :param int [since]: the earliest time in ms to fetch orders for
1636
+ :param int [limit]: the maximum number of order structures to retrieve
1637
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1638
+ :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1639
+ """
1640
+ omsId = self.safe_integer(self.options, 'omsId', 1)
1641
+ self.load_markets()
1642
+ self.load_accounts()
1643
+ defaultAccountId = self.safe_integer_2(self.options, 'accountId', 'AccountId', int(self.accounts[0]['id']))
1644
+ accountId = self.safe_integer_2(params, 'accountId', 'AccountId', defaultAccountId)
1645
+ params = self.omit(params, ['accountId', 'AccountId'])
1646
+ request: dict = {
1647
+ 'omsId': omsId,
1648
+ 'AccountId': accountId,
1649
+ # 'ClientOrderId': clientOrderId,
1650
+ # 'OriginalOrderId': id,
1651
+ # 'OriginalClientOrderId': long integer,
1652
+ # 'UserId': integer,
1653
+ # 'InstrumentId': market['id'],
1654
+ # 'StartTimestamp': since,
1655
+ # 'EndTimestamp': self.milliseconds(),
1656
+ # 'Depth': limit,
1657
+ # 'StartIndex': 0,
1658
+ }
1659
+ market = None
1660
+ if symbol is not None:
1661
+ market = self.market(symbol)
1662
+ request['InstrumentId'] = market['id']
1663
+ if since is not None:
1664
+ request['StartTimeStamp'] = self.parse_to_int(since / 1000)
1665
+ if limit is not None:
1666
+ request['Depth'] = limit
1667
+ response = self.privateGetGetOrdersHistory(self.extend(request, params))
1668
+ #
1669
+ # [
1670
+ # {
1671
+ # "Side":"Buy",
1672
+ # "OrderId":2543565233,
1673
+ # "Price":19010.000000000000000000000000,
1674
+ # "Quantity":0.0000000000000000000000000000,
1675
+ # "DisplayQuantity":0.3450000000000000000000000000,
1676
+ # "Instrument":8,
1677
+ # "Account":449,
1678
+ # "AccountName":"igor@ccxt.trade",
1679
+ # "OrderType":"Limit",
1680
+ # "ClientOrderId":0,
1681
+ # "OrderState":"Canceled",
1682
+ # "ReceiveTime":1607579326003,
1683
+ # "ReceiveTimeTicks":637431761260028981,
1684
+ # "LastUpdatedTime":1607580965346,
1685
+ # "LastUpdatedTimeTicks":637431777653463754,
1686
+ # "OrigQuantity":0.3450000000000000000000000000,
1687
+ # "QuantityExecuted":0.0000000000000000000000000000,
1688
+ # "GrossValueExecuted":0.0000000000000000000000000000,
1689
+ # "ExecutableValue":0.0000000000000000000000000000,
1690
+ # "AvgPrice":0.0000000000000000000000000000,
1691
+ # "CounterPartyId":0,
1692
+ # "ChangeReason":"UserModified",
1693
+ # "OrigOrderId":2543565233,
1694
+ # "OrigClOrdId":0,
1695
+ # "EnteredBy":446,
1696
+ # "UserName":"igor@ccxt.trade",
1697
+ # "IsQuote":false,
1698
+ # "InsideAsk":19069.320000000000000000000000,
1699
+ # "InsideAskSize":0.0997360000000000000000000000,
1700
+ # "InsideBid":19068.250000000000000000000000,
1701
+ # "InsideBidSize":1.3300010000000000000000000000,
1702
+ # "LastTradePrice":19068.250000000000000000000000,
1703
+ # "RejectReason":"",
1704
+ # "IsLockedIn":false,
1705
+ # "CancelReason":"UserModified",
1706
+ # "OrderFlag":"AddedToBook, RemovedFromBook",
1707
+ # "UseMargin":false,
1708
+ # "StopPrice":0.0000000000000000000000000000,
1709
+ # "PegPriceType":"Unknown",
1710
+ # "PegOffset":0.0000000000000000000000000000,
1711
+ # "PegLimitOffset":0.0000000000000000000000000000,
1712
+ # "IpAddress":"x.x.x.x",
1713
+ # "ClientOrderIdUuid":null,
1714
+ # "OMSId":1
1715
+ # },
1716
+ # ]
1717
+ #
1718
+ return self.parse_orders(response, market, since, limit)
1719
+
1720
+ def fetch_order(self, id: str, symbol: Str = None, params={}):
1721
+ """
1722
+ fetches information on an order made by the user
1723
+ :see: https://apidoc.ndax.io/#getorderstatus
1724
+ :param str symbol: unified symbol of the market the order was made in
1725
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1726
+ :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1727
+ """
1728
+ omsId = self.safe_integer(self.options, 'omsId', 1)
1729
+ self.load_markets()
1730
+ self.load_accounts()
1731
+ defaultAccountId = self.safe_integer_2(self.options, 'accountId', 'AccountId', int(self.accounts[0]['id']))
1732
+ accountId = self.safe_integer_2(params, 'accountId', 'AccountId', defaultAccountId)
1733
+ params = self.omit(params, ['accountId', 'AccountId'])
1734
+ market = None
1735
+ if symbol is not None:
1736
+ market = self.market(symbol)
1737
+ request: dict = {
1738
+ 'omsId': omsId,
1739
+ 'AccountId': accountId,
1740
+ 'OrderId': int(id),
1741
+ }
1742
+ response = self.privateGetGetOrderStatus(self.extend(request, params))
1743
+ #
1744
+ # {
1745
+ # "Side":"Sell",
1746
+ # "OrderId":2543565232,
1747
+ # "Price":0.0000000000000000000000000000,
1748
+ # "Quantity":0.0000000000000000000000000000,
1749
+ # "DisplayQuantity":0.0000000000000000000000000000,
1750
+ # "Instrument":8,
1751
+ # "Account":449,
1752
+ # "AccountName":"igor@ccxt.trade",
1753
+ # "OrderType":"Market",
1754
+ # "ClientOrderId":0,
1755
+ # "OrderState":"FullyExecuted",
1756
+ # "ReceiveTime":1607569475591,
1757
+ # "ReceiveTimeTicks":637431662755912377,
1758
+ # "LastUpdatedTime":1607569475596,
1759
+ # "LastUpdatedTimeTicks":637431662755960902,
1760
+ # "OrigQuantity":1.0000000000000000000000000000,
1761
+ # "QuantityExecuted":1.0000000000000000000000000000,
1762
+ # "GrossValueExecuted":19068.270478610000000000000000,
1763
+ # "ExecutableValue":0.0000000000000000000000000000,
1764
+ # "AvgPrice":19068.270478610000000000000000,
1765
+ # "CounterPartyId":0,
1766
+ # "ChangeReason":"Trade",
1767
+ # "OrigOrderId":2543565232,
1768
+ # "OrigClOrdId":0,
1769
+ # "EnteredBy":446,
1770
+ # "UserName":"igor@ccxt.trade",
1771
+ # "IsQuote":false,
1772
+ # "InsideAsk":19069.320000000000000000000000,
1773
+ # "InsideAskSize":0.0997360000000000000000000000,
1774
+ # "InsideBid":19069.310000000000000000000000,
1775
+ # "InsideBidSize":0.2400950000000000000000000000,
1776
+ # "LastTradePrice":19069.310000000000000000000000,
1777
+ # "RejectReason":"",
1778
+ # "IsLockedIn":false,
1779
+ # "CancelReason":"",
1780
+ # "OrderFlag":"0",
1781
+ # "UseMargin":false,
1782
+ # "StopPrice":0.0000000000000000000000000000,
1783
+ # "PegPriceType":"Unknown",
1784
+ # "PegOffset":0.0000000000000000000000000000,
1785
+ # "PegLimitOffset":0.0000000000000000000000000000,
1786
+ # "IpAddress":"x.x.x.x",
1787
+ # "ClientOrderIdUuid":null,
1788
+ # "OMSId":1
1789
+ # }
1790
+ #
1791
+ return self.parse_order(response, market)
1792
+
1793
+ def fetch_order_trades(self, id: str, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1794
+ """
1795
+ fetch all the trades made from a single order
1796
+ :see: https://apidoc.ndax.io/#getorderhistorybyorderid
1797
+ :param str id: order id
1798
+ :param str symbol: unified market symbol
1799
+ :param int [since]: the earliest time in ms to fetch trades for
1800
+ :param int [limit]: the maximum number of trades to retrieve
1801
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1802
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
1803
+ """
1804
+ omsId = self.safe_integer(self.options, 'omsId', 1)
1805
+ self.load_markets()
1806
+ self.load_accounts()
1807
+ # defaultAccountId = self.safe_integer_2(self.options, 'accountId', 'AccountId', int(self.accounts[0]['id']))
1808
+ # accountId = self.safe_integer_2(params, 'accountId', 'AccountId', defaultAccountId)
1809
+ # params = self.omit(params, ['accountId', 'AccountId'])
1810
+ market = None
1811
+ if symbol is not None:
1812
+ market = self.market(symbol)
1813
+ request: dict = {
1814
+ 'OMSId': self.parse_to_int(omsId),
1815
+ # 'AccountId': accountId,
1816
+ 'OrderId': int(id),
1817
+ }
1818
+ response = self.privatePostGetOrderHistoryByOrderId(self.extend(request, params))
1819
+ #
1820
+ # [
1821
+ # {
1822
+ # "Side":"Sell",
1823
+ # "OrderId":2543565235,
1824
+ # "Price":18600.000000000000000000000000,
1825
+ # "Quantity":0.0000000000000000000000000000,
1826
+ # "DisplayQuantity":0.0000000000000000000000000000,
1827
+ # "Instrument":8,
1828
+ # "Account":449,
1829
+ # "AccountName":"igor@ccxt.trade",
1830
+ # "OrderType":"Limit",
1831
+ # "ClientOrderId":0,
1832
+ # "OrderState":"FullyExecuted",
1833
+ # "ReceiveTime":1607585844956,
1834
+ # "ReceiveTimeTicks":637431826449564182,
1835
+ # "LastUpdatedTime":1607585844959,
1836
+ # "LastUpdatedTimeTicks":637431826449593893,
1837
+ # "OrigQuantity":0.1230000000000000000000000000,
1838
+ # "QuantityExecuted":0.1230000000000000000000000000,
1839
+ # "GrossValueExecuted":2345.3947500000000000000000000,
1840
+ # "ExecutableValue":0.0000000000000000000000000000,
1841
+ # "AvgPrice":19068.250000000000000000000000,
1842
+ # "CounterPartyId":0,
1843
+ # "ChangeReason":"Trade",
1844
+ # "OrigOrderId":2543565235,
1845
+ # "OrigClOrdId":0,
1846
+ # "EnteredBy":446,
1847
+ # "UserName":"igor@ccxt.trade",
1848
+ # "IsQuote":false,
1849
+ # "InsideAsk":19069.320000000000000000000000,
1850
+ # "InsideAskSize":0.0997360000000000000000000000,
1851
+ # "InsideBid":19068.250000000000000000000000,
1852
+ # "InsideBidSize":1.3300010000000000000000000000,
1853
+ # "LastTradePrice":19068.250000000000000000000000,
1854
+ # "RejectReason":"",
1855
+ # "IsLockedIn":false,
1856
+ # "CancelReason":"",
1857
+ # "OrderFlag":"0",
1858
+ # "UseMargin":false,
1859
+ # "StopPrice":0.0000000000000000000000000000,
1860
+ # "PegPriceType":"Unknown",
1861
+ # "PegOffset":0.0000000000000000000000000000,
1862
+ # "PegLimitOffset":0.0000000000000000000000000000,
1863
+ # "IpAddress":"x.x.x.x",
1864
+ # "ClientOrderIdUuid":null,
1865
+ # "OMSId":1
1866
+ # },
1867
+ # ]
1868
+ #
1869
+ grouped = self.group_by(response, 'ChangeReason')
1870
+ trades = self.safe_list(grouped, 'Trade', [])
1871
+ return self.parse_trades(trades, market, since, limit)
1872
+
1873
+ def fetch_deposit_address(self, code: str, params={}):
1874
+ """
1875
+ fetch the deposit address for a currency associated with self account
1876
+ :param str code: unified currency code
1877
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1878
+ :returns dict: an `address structure <https://docs.ccxt.com/#/?id=address-structure>`
1879
+ """
1880
+ omsId = self.safe_integer(self.options, 'omsId', 1)
1881
+ self.load_markets()
1882
+ self.load_accounts()
1883
+ defaultAccountId = self.safe_integer_2(self.options, 'accountId', 'AccountId', int(self.accounts[0]['id']))
1884
+ accountId = self.safe_integer_2(params, 'accountId', 'AccountId', defaultAccountId)
1885
+ params = self.omit(params, ['accountId', 'AccountId'])
1886
+ currency = self.currency(code)
1887
+ request: dict = {
1888
+ 'omsId': omsId,
1889
+ 'AccountId': accountId,
1890
+ 'ProductId': currency['id'],
1891
+ 'GenerateNewKey': False,
1892
+ }
1893
+ response = self.privateGetGetDepositInfo(self.extend(request, params))
1894
+ #
1895
+ # {
1896
+ # "result":true,
1897
+ # "errormsg":null,
1898
+ # "statuscode":0,
1899
+ # "AssetManagerId":1,
1900
+ # "AccountId":57922,
1901
+ # "AssetId":16,
1902
+ # "ProviderId":23,
1903
+ # "DepositInfo":"[\"0x8A27564b5c30b91C93B1591821642420F323a210\"]"
1904
+ # }
1905
+ #
1906
+ return self.parse_deposit_address(response, currency)
1907
+
1908
+ def parse_deposit_address(self, depositAddress, currency: Currency = None):
1909
+ #
1910
+ # fetchDepositAddress, createDepositAddress
1911
+ #
1912
+ # {
1913
+ # "result":true,
1914
+ # "errormsg":null,
1915
+ # "statuscode":0,
1916
+ # "AssetManagerId":1,
1917
+ # "AccountId":449,
1918
+ # "AssetId":1,
1919
+ # "ProviderId":1,
1920
+ # "DepositInfo":"[\"r3e95RwVsLH7yCbnMfyh7SA8FdwUJCB4S2?memo=241452010\"]"
1921
+ # }
1922
+ #
1923
+ depositInfoString = self.safe_string(depositAddress, 'DepositInfo')
1924
+ depositInfo = json.loads(depositInfoString)
1925
+ depositInfoLength = len(depositInfo)
1926
+ lastString = self.safe_string(depositInfo, depositInfoLength - 1)
1927
+ parts = lastString.split('?memo=')
1928
+ address = self.safe_string(parts, 0)
1929
+ tag = self.safe_string(parts, 1)
1930
+ code = None
1931
+ if currency is not None:
1932
+ code = currency['code']
1933
+ self.check_address(address)
1934
+ return {
1935
+ 'currency': code,
1936
+ 'address': address,
1937
+ 'tag': tag,
1938
+ 'network': None,
1939
+ 'info': depositAddress,
1940
+ }
1941
+
1942
+ def create_deposit_address(self, code: str, params={}):
1943
+ """
1944
+ create a currency deposit address
1945
+ :param str code: unified currency code of the currency for the deposit address
1946
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1947
+ :returns dict: an `address structure <https://docs.ccxt.com/#/?id=address-structure>`
1948
+ """
1949
+ request: dict = {
1950
+ 'GenerateNewKey': True,
1951
+ }
1952
+ return self.fetch_deposit_address(code, self.extend(request, params))
1953
+
1954
+ def fetch_deposits(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
1955
+ """
1956
+ fetch all deposits made to an account
1957
+ :see: https://apidoc.ndax.io/#getdeposits
1958
+ :param str code: unified currency code
1959
+ :param int [since]: not used by ndax fetchDeposits
1960
+ :param int [limit]: the maximum number of deposits structures to retrieve
1961
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1962
+ :returns dict[]: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
1963
+ """
1964
+ omsId = self.safe_integer(self.options, 'omsId', 1)
1965
+ self.load_markets()
1966
+ self.load_accounts()
1967
+ defaultAccountId = self.safe_integer_2(self.options, 'accountId', 'AccountId', int(self.accounts[0]['id']))
1968
+ accountId = self.safe_integer_2(params, 'accountId', 'AccountId', defaultAccountId)
1969
+ params = self.omit(params, ['accountId', 'AccountId'])
1970
+ currency = None
1971
+ if code is not None:
1972
+ currency = self.currency(code)
1973
+ request: dict = {
1974
+ 'omsId': omsId,
1975
+ 'AccountId': accountId,
1976
+ }
1977
+ response = self.privateGetGetDeposits(self.extend(request, params))
1978
+ #
1979
+ # "[
1980
+ # {
1981
+ # "OMSId": 1,
1982
+ # "DepositId": 44,
1983
+ # "AccountId": 449,
1984
+ # "SubAccountId": 0,
1985
+ # "ProductId": 4,
1986
+ # "Amount": 200.00000000000000000000000000,
1987
+ # "LastUpdateTimeStamp": 637431291261187806,
1988
+ # "ProductType": "CryptoCurrency",
1989
+ # "TicketStatus": "FullyProcessed",
1990
+ # "DepositInfo": "{
1991
+ # "AccountProviderId":42,
1992
+ # "AccountProviderName":"USDT_BSC",
1993
+ # "TXId":"0x3879b02632c69482646409e991149290bc9a58e4603be63c7c2c90a843f45d2b",
1994
+ # "FromAddress":"0x8894E0a0c962CB723c1976a4421c95949bE2D4E3",
1995
+ # "ToAddress":"0x5428EcEB1F7Ee058f64158589e27D087149230CB"
1996
+ # },",
1997
+ # "DepositCode": "ab0e23d5-a9ce-4d94-865f-9ab464fb1de3",
1998
+ # "TicketNumber": 71,
1999
+ # "NotionalProductId": 13,
2000
+ # "NotionalValue": 200.00000000000000000000000000,
2001
+ # "FeeAmount": 0.0000000000000000000000000000,
2002
+ # },
2003
+ # ...
2004
+ # ]"
2005
+ #
2006
+ if isinstance(response, str):
2007
+ return self.parse_transactions(json.loads(response), currency, since, limit)
2008
+ return self.parse_transactions(response, currency, since, limit)
2009
+
2010
+ def fetch_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
2011
+ """
2012
+ fetch all withdrawals made from an account
2013
+ :see: https://apidoc.ndax.io/#getwithdraws
2014
+ :param str code: unified currency code
2015
+ :param int [since]: the earliest time in ms to fetch withdrawals for
2016
+ :param int [limit]: the maximum number of withdrawals structures to retrieve
2017
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2018
+ :returns dict[]: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
2019
+ """
2020
+ omsId = self.safe_integer(self.options, 'omsId', 1)
2021
+ self.load_markets()
2022
+ self.load_accounts()
2023
+ defaultAccountId = self.safe_integer_2(self.options, 'accountId', 'AccountId', int(self.accounts[0]['id']))
2024
+ accountId = self.safe_integer_2(params, 'accountId', 'AccountId', defaultAccountId)
2025
+ params = self.omit(params, ['accountId', 'AccountId'])
2026
+ currency = None
2027
+ if code is not None:
2028
+ currency = self.currency(code)
2029
+ request: dict = {
2030
+ 'omsId': omsId,
2031
+ 'AccountId': accountId,
2032
+ }
2033
+ response = self.privateGetGetWithdraws(self.extend(request, params))
2034
+ #
2035
+ # [
2036
+ # {
2037
+ # "Amount": 0.0,
2038
+ # "FeeAmount": 0.0,
2039
+ # "NotionalValue": 0.0,
2040
+ # "WithdrawId": 0,
2041
+ # "AssetManagerId": 0,
2042
+ # "AccountId": 0,
2043
+ # "AssetId": 0,
2044
+ # "TemplateForm": "{\"TemplateType\": \"TetherRPCWithdraw\",\"Comment\": \"TestWithdraw\",\"ExternalAddress\": \"ms6C3pKAAr8gRCcnVebs8VRkVrjcvqNYv3\"}",
2045
+ # "TemplateFormType": "TetherRPCWithdraw",
2046
+ # "omsId": 0,
2047
+ # "TicketStatus": 0,
2048
+ # "TicketNumber": 0,
2049
+ # "WithdrawTransactionDetails": "",
2050
+ # "WithdrawType": "",
2051
+ # "WithdrawCode": "490b4fa3-53fc-44f4-bd29-7e16be86fba3",
2052
+ # "AssetType": 0,
2053
+ # "Reaccepted": True,
2054
+ # "NotionalProductId": 0
2055
+ # },
2056
+ # ]
2057
+ #
2058
+ return self.parse_transactions(response, currency, since, limit)
2059
+
2060
+ def parse_transaction_status_by_type(self, status, type=None):
2061
+ statusesByType: dict = {
2062
+ 'deposit': {
2063
+ 'New': 'pending', # new ticket awaiting operator review
2064
+ 'AdminProcessing': 'pending', # an admin is looking at the ticket
2065
+ 'Accepted': 'pending', # an admin accepts the ticket
2066
+ 'Rejected': 'rejected', # admin rejects the ticket
2067
+ 'SystemProcessing': 'pending', # automatic processing; an unlikely status for a deposit
2068
+ 'FullyProcessed': 'ok', # the deposit has concluded
2069
+ 'Failed': 'failed', # the deposit has failed for some reason
2070
+ 'Pending': 'pending', # Account Provider has set status to pending
2071
+ 'Confirmed': 'pending', # Account Provider confirms the deposit
2072
+ 'AmlProcessing': 'pending', # anti-money-laundering process underway
2073
+ 'AmlAccepted': 'pending', # anti-money-laundering process successful
2074
+ 'AmlRejected': 'rejected', # deposit did not stand up to anti-money-laundering process
2075
+ 'AmlFailed': 'failed', # anti-money-laundering process failed/did not complete
2076
+ 'LimitsAccepted': 'pending', # deposit meets limits for fiat or crypto asset
2077
+ 'LimitsRejected': 'rejected', # deposit does not meet limits for fiat or crypto asset
2078
+ },
2079
+ 'withdrawal': {
2080
+ 'New': 'pending', # awaiting operator review
2081
+ 'AdminProcessing': 'pending', # An admin is looking at the ticket
2082
+ 'Accepted': 'pending', # withdrawal will proceed
2083
+ 'Rejected': 'rejected', # admin or automatic rejection
2084
+ 'SystemProcessing': 'pending', # automatic processing underway
2085
+ 'FullyProcessed': 'ok', # the withdrawal has concluded
2086
+ 'Failed': 'failed', # the withdrawal failed for some reason
2087
+ 'Pending': 'pending', # the admin has placed the withdrawal in pending status
2088
+ 'Pending2Fa': 'pending', # user must click 2-factor authentication confirmation link
2089
+ 'AutoAccepted': 'pending', # withdrawal will be automatically processed
2090
+ 'Delayed': 'pending', # waiting for funds to be allocated for the withdrawal
2091
+ 'UserCanceled': 'canceled', # withdraw canceled by user or Superuser
2092
+ 'AdminCanceled': 'canceled', # withdraw canceled by Superuser
2093
+ 'AmlProcessing': 'pending', # anti-money-laundering process underway
2094
+ 'AmlAccepted': 'pending', # anti-money-laundering process complete
2095
+ 'AmlRejected': 'rejected', # withdrawal did not stand up to anti-money-laundering process
2096
+ 'AmlFailed': 'failed', # withdrawal did not complete anti-money-laundering process
2097
+ 'LimitsAccepted': 'pending', # withdrawal meets limits for fiat or crypto asset
2098
+ 'LimitsRejected': 'rejected', # withdrawal does not meet limits for fiat or crypto asset
2099
+ 'Submitted': 'pending', # withdrawal sent to Account Provider; awaiting blockchain confirmation
2100
+ 'Confirmed': 'pending', # Account Provider confirms that withdrawal is on the blockchain
2101
+ 'ManuallyConfirmed': 'pending', # admin has sent withdrawal via wallet or admin function directly; marks ticket; debits account
2102
+ 'Confirmed2Fa': 'pending', # user has confirmed withdraw via 2-factor authentication.
2103
+ },
2104
+ }
2105
+ statuses = self.safe_value(statusesByType, type, {})
2106
+ return self.safe_string(statuses, status, status)
2107
+
2108
+ def parse_transaction(self, transaction: dict, currency: Currency = None) -> Transaction:
2109
+ #
2110
+ # fetchDeposits
2111
+ #
2112
+ # {
2113
+ # "OMSId": 1,
2114
+ # "DepositId": 44,
2115
+ # "AccountId": 449,
2116
+ # "SubAccountId": 0,
2117
+ # "ProductId": 4,
2118
+ # "Amount": 200.00000000000000000000000000,
2119
+ # "LastUpdateTimeStamp": 637431291261187806,
2120
+ # "ProductType": "CryptoCurrency",
2121
+ # "TicketStatus": "FullyProcessed",
2122
+ # "DepositInfo": "{
2123
+ # "AccountProviderId":42,
2124
+ # "AccountProviderName":"USDT_BSC",
2125
+ # "TXId":"0x3879b02632c69482646409e991149290bc9a58e4603be63c7c2c90a843f45d2b",
2126
+ # "FromAddress":"0x8894E0a0c962CB723c1976a4421c95949bE2D4E3",
2127
+ # "ToAddress":"0x5428EcEB1F7Ee058f64158589e27D087149230CB"
2128
+ # }",
2129
+ # "DepositCode": "ab0e23d5-a9ce-4d94-865f-9ab464fb1de3",
2130
+ # "TicketNumber": 71,
2131
+ # "NotionalProductId": 13,
2132
+ # "NotionalValue": 200.00000000000000000000000000,
2133
+ # "FeeAmount": 0.0000000000000000000000000000,
2134
+ # }
2135
+ #
2136
+ # fetchWithdrawals
2137
+ #
2138
+ # {
2139
+ # "Amount": 0.0,
2140
+ # "FeeAmount": 0.0,
2141
+ # "NotionalValue": 0.0,
2142
+ # "WithdrawId": 0,
2143
+ # "AssetManagerId": 0,
2144
+ # "AccountId": 0,
2145
+ # "AssetId": 0,
2146
+ # "TemplateForm": "{\"TemplateType\": \"TetherRPCWithdraw\",\"Comment\": \"TestWithdraw\",\"ExternalAddress\": \"ms6C3pKAAr8gRCcnVebs8VRkVrjcvqNYv3\"}",
2147
+ # "TemplateFormType": "TetherRPCWithdraw",
2148
+ # "omsId": 0,
2149
+ # "TicketStatus": 0,
2150
+ # "TicketNumber": 0,
2151
+ # "WithdrawTransactionDetails": "",
2152
+ # "WithdrawType": "",
2153
+ # "WithdrawCode": "490b4fa3-53fc-44f4-bd29-7e16be86fba3",
2154
+ # "AssetType": 0,
2155
+ # "Reaccepted": True,
2156
+ # "NotionalProductId": 0
2157
+ # }
2158
+ #
2159
+ id = None
2160
+ currencyId = self.safe_string(transaction, 'ProductId')
2161
+ code = self.safe_currency_code(currencyId, currency)
2162
+ type = None
2163
+ if 'DepositId' in transaction:
2164
+ id = self.safe_string(transaction, 'DepositId')
2165
+ type = 'deposit'
2166
+ elif 'WithdrawId' in transaction:
2167
+ id = self.safe_string(transaction, 'WithdrawId')
2168
+ type = 'withdrawal'
2169
+ templateForm = self.parse_json(self.safe_value_2(transaction, 'TemplateForm', 'DepositInfo'))
2170
+ updated = self.safe_integer(transaction, 'LastUpdateTimeStamp')
2171
+ if templateForm is not None:
2172
+ updated = self.safe_integer(templateForm, 'LastUpdated', updated)
2173
+ address = self.safe_string_2(templateForm, 'ExternalAddress', 'ToAddress')
2174
+ timestamp = self.safe_integer(templateForm, 'TimeSubmitted')
2175
+ feeCost = self.safe_number(transaction, 'FeeAmount')
2176
+ transactionStatus = self.safe_string(transaction, 'TicketStatus')
2177
+ fee = None
2178
+ if feeCost is not None:
2179
+ fee = {'currency': code, 'cost': feeCost}
2180
+ return {
2181
+ 'info': transaction,
2182
+ 'id': id,
2183
+ 'txid': self.safe_string_2(templateForm, 'TxId', 'TXId'),
2184
+ 'timestamp': timestamp,
2185
+ 'datetime': self.iso8601(timestamp),
2186
+ 'address': address,
2187
+ 'addressTo': address,
2188
+ 'addressFrom': self.safe_string(templateForm, 'FromAddress'),
2189
+ 'tag': None,
2190
+ 'tagTo': None,
2191
+ 'tagFrom': None,
2192
+ 'type': type,
2193
+ 'amount': self.safe_number(transaction, 'Amount'),
2194
+ 'currency': code,
2195
+ 'status': self.parse_transaction_status_by_type(transactionStatus, type),
2196
+ 'updated': updated,
2197
+ 'fee': fee,
2198
+ 'internal': None,
2199
+ 'comment': None,
2200
+ 'network': None,
2201
+ }
2202
+
2203
+ def withdraw(self, code: str, amount: float, address: str, tag=None, params={}):
2204
+ """
2205
+ make a withdrawal
2206
+ :param str code: unified currency code
2207
+ :param float amount: the amount to withdraw
2208
+ :param str address: the address to withdraw to
2209
+ :param str tag:
2210
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2211
+ :returns dict: a `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
2212
+ """
2213
+ tag, params = self.handle_withdraw_tag_and_params(tag, params)
2214
+ # self method required login, password and twofa key
2215
+ sessionToken = self.safe_string(self.options, 'sessionToken')
2216
+ if sessionToken is None:
2217
+ raise AuthenticationError(self.id + ' call signIn() method to obtain a session token')
2218
+ if self.twofa is None:
2219
+ raise AuthenticationError(self.id + ' withdraw() requires exchange.twofa credentials')
2220
+ self.check_address(address)
2221
+ omsId = self.safe_integer(self.options, 'omsId', 1)
2222
+ self.load_markets()
2223
+ self.load_accounts()
2224
+ defaultAccountId = self.safe_integer_2(self.options, 'accountId', 'AccountId', int(self.accounts[0]['id']))
2225
+ accountId = self.safe_integer_2(params, 'accountId', 'AccountId', defaultAccountId)
2226
+ params = self.omit(params, ['accountId', 'AccountId'])
2227
+ currency = self.currency(code)
2228
+ withdrawTemplateTypesRequest: dict = {
2229
+ 'omsId': omsId,
2230
+ 'AccountId': accountId,
2231
+ 'ProductId': currency['id'],
2232
+ }
2233
+ withdrawTemplateTypesResponse = self.privateGetGetWithdrawTemplateTypes(withdrawTemplateTypesRequest)
2234
+ #
2235
+ # {
2236
+ # "result": True,
2237
+ # "errormsg": null,
2238
+ # "statuscode": "0",
2239
+ # "TemplateTypes": [
2240
+ # {AccountProviderId: "14", TemplateName: "ToExternalBitcoinAddress", AccountProviderName: "BitgoRPC-BTC"},
2241
+ # {AccountProviderId: "20", TemplateName: "ToExternalBitcoinAddress", AccountProviderName: "TrezorBTC"},
2242
+ # {AccountProviderId: "31", TemplateName: "BTC", AccountProviderName: "BTC Fireblocks 1"}
2243
+ # ]
2244
+ # }
2245
+ #
2246
+ templateTypes = self.safe_value(withdrawTemplateTypesResponse, 'TemplateTypes', [])
2247
+ firstTemplateType = self.safe_value(templateTypes, 0)
2248
+ if firstTemplateType is None:
2249
+ raise ExchangeError(self.id + ' withdraw() could not find a withdraw template type for ' + currency['code'])
2250
+ templateName = self.safe_string(firstTemplateType, 'TemplateName')
2251
+ withdrawTemplateRequest: dict = {
2252
+ 'omsId': omsId,
2253
+ 'AccountId': accountId,
2254
+ 'ProductId': currency['id'],
2255
+ 'TemplateType': templateName,
2256
+ 'AccountProviderId': firstTemplateType['AccountProviderId'],
2257
+ }
2258
+ withdrawTemplateResponse = self.privateGetGetWithdrawTemplate(withdrawTemplateRequest)
2259
+ #
2260
+ # {
2261
+ # "result": True,
2262
+ # "errormsg": null,
2263
+ # "statuscode": "0",
2264
+ # "Template": "{\"TemplateType\":\"ToExternalBitcoinAddress\",\"Comment\":\"\",\"ExternalAddress\":\"\"}"
2265
+ # }
2266
+ #
2267
+ template = self.safe_string(withdrawTemplateResponse, 'Template')
2268
+ if template is None:
2269
+ raise ExchangeError(self.id + ' withdraw() could not find a withdraw template for ' + currency['code'])
2270
+ withdrawTemplate = json.loads(template)
2271
+ withdrawTemplate['ExternalAddress'] = address
2272
+ if tag is not None:
2273
+ if 'Memo' in withdrawTemplate:
2274
+ withdrawTemplate['Memo'] = tag
2275
+ withdrawPayload: dict = {
2276
+ 'omsId': omsId,
2277
+ 'AccountId': accountId,
2278
+ 'ProductId': currency['id'],
2279
+ 'TemplateForm': self.json(withdrawTemplate),
2280
+ 'TemplateType': templateName,
2281
+ }
2282
+ withdrawRequest: dict = {
2283
+ 'TfaType': 'Google',
2284
+ 'TFaCode': self.totp(self.twofa),
2285
+ 'Payload': self.json(withdrawPayload),
2286
+ }
2287
+ response = self.privatePostCreateWithdrawTicket(self.deep_extend(withdrawRequest, params))
2288
+ return self.parse_transaction(response, currency)
2289
+
2290
+ def nonce(self):
2291
+ return self.milliseconds()
2292
+
2293
+ def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
2294
+ url = self.urls['api'][api] + '/' + self.implode_params(path, params)
2295
+ query = self.omit(params, self.extract_params(path))
2296
+ if api == 'public':
2297
+ if path == 'Authenticate':
2298
+ auth = self.login + ':' + self.password
2299
+ auth64 = self.string_to_base64(auth)
2300
+ headers = {
2301
+ 'Authorization': 'Basic ' + auth64,
2302
+ # 'Content-Type': 'application/json',
2303
+ }
2304
+ elif path == 'Authenticate2FA':
2305
+ pending2faToken = self.safe_string(self.options, 'pending2faToken')
2306
+ if pending2faToken is not None:
2307
+ headers = {
2308
+ 'Pending2FaToken': pending2faToken,
2309
+ # 'Content-Type': 'application/json',
2310
+ }
2311
+ query = self.omit(query, 'pending2faToken')
2312
+ if query:
2313
+ url += '?' + self.urlencode(query)
2314
+ elif api == 'private':
2315
+ self.check_required_credentials()
2316
+ sessionToken = self.safe_string(self.options, 'sessionToken')
2317
+ if sessionToken is None:
2318
+ nonce = str(self.nonce())
2319
+ auth = nonce + self.uid + self.apiKey
2320
+ signature = self.hmac(self.encode(auth), self.encode(self.secret), hashlib.sha256)
2321
+ headers = {
2322
+ 'Nonce': nonce,
2323
+ 'APIKey': self.apiKey,
2324
+ 'Signature': signature,
2325
+ 'UserId': self.uid,
2326
+ }
2327
+ else:
2328
+ headers = {
2329
+ 'APToken': sessionToken,
2330
+ }
2331
+ if method == 'POST':
2332
+ headers['Content-Type'] = 'application/json'
2333
+ body = self.json(query)
2334
+ else:
2335
+ if query:
2336
+ url += '?' + self.urlencode(query)
2337
+ return {'url': url, 'method': method, 'body': body, 'headers': headers}
2338
+
2339
+ def handle_errors(self, code: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
2340
+ if code == 404:
2341
+ raise AuthenticationError(self.id + ' ' + body)
2342
+ if response is None:
2343
+ return None
2344
+ #
2345
+ # {"status":"Rejected","errormsg":"Not_Enough_Funds","errorcode":101}
2346
+ # {"result":false,"errormsg":"Server Error","errorcode":102,"detail":null}
2347
+ #
2348
+ message = self.safe_string(response, 'errormsg')
2349
+ if (message is not None) and (message != ''):
2350
+ feedback = self.id + ' ' + body
2351
+ self.throw_exactly_matched_exception(self.exceptions['exact'], message, feedback)
2352
+ self.throw_broadly_matched_exception(self.exceptions['broad'], body, feedback)
2353
+ raise ExchangeError(feedback)
2354
+ return None