ccxt 4.2.77__py2.py3-none-any.whl → 4.4.48__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 (546) hide show
  1. ccxt/__init__.py +36 -14
  2. ccxt/abstract/alpaca.py +4 -0
  3. ccxt/abstract/bigone.py +1 -1
  4. ccxt/abstract/binance.py +112 -48
  5. ccxt/abstract/binancecoinm.py +112 -48
  6. ccxt/abstract/binanceus.py +147 -83
  7. ccxt/abstract/binanceusdm.py +112 -48
  8. ccxt/abstract/bingx.py +133 -78
  9. ccxt/abstract/bitbank.py +5 -0
  10. ccxt/abstract/bitfinex.py +136 -65
  11. ccxt/abstract/bitfinex1.py +69 -0
  12. ccxt/abstract/bitflyer.py +1 -0
  13. ccxt/abstract/bitget.py +8 -1
  14. ccxt/abstract/bitmart.py +13 -1
  15. ccxt/abstract/bitopro.py +1 -0
  16. ccxt/abstract/bitpanda.py +0 -12
  17. ccxt/abstract/bitrue.py +3 -3
  18. ccxt/abstract/bitstamp.py +26 -3
  19. ccxt/abstract/blofin.py +24 -0
  20. ccxt/abstract/btcbox.py +1 -0
  21. ccxt/abstract/bybit.py +29 -14
  22. ccxt/abstract/cex.py +28 -29
  23. ccxt/abstract/coinbase.py +6 -0
  24. ccxt/abstract/coinbaseadvanced.py +94 -0
  25. ccxt/abstract/{coinbasepro.py → coinbaseexchange.py} +1 -0
  26. ccxt/abstract/coinbaseinternational.py +1 -1
  27. ccxt/abstract/coincatch.py +94 -0
  28. ccxt/abstract/coinex.py +233 -123
  29. ccxt/abstract/coinmetro.py +1 -0
  30. ccxt/abstract/cryptocom.py +14 -0
  31. ccxt/abstract/defx.py +69 -0
  32. ccxt/abstract/deribit.py +1 -0
  33. ccxt/abstract/digifinex.py +1 -0
  34. ccxt/abstract/ellipx.py +25 -0
  35. ccxt/abstract/gate.py +20 -0
  36. ccxt/abstract/gateio.py +20 -0
  37. ccxt/abstract/gemini.py +1 -0
  38. ccxt/abstract/hashkey.py +67 -0
  39. ccxt/abstract/hyperliquid.py +1 -1
  40. ccxt/abstract/independentreserve.py +6 -0
  41. ccxt/abstract/kraken.py +4 -3
  42. ccxt/abstract/krakenfutures.py +4 -0
  43. ccxt/abstract/kucoin.py +24 -0
  44. ccxt/abstract/kucoinfutures.py +34 -0
  45. ccxt/abstract/luno.py +2 -0
  46. ccxt/abstract/mexc.py +4 -0
  47. ccxt/abstract/myokx.py +340 -0
  48. ccxt/abstract/oceanex.py +5 -0
  49. ccxt/abstract/okx.py +30 -0
  50. ccxt/abstract/onetrading.py +0 -12
  51. ccxt/abstract/oxfun.py +34 -0
  52. ccxt/abstract/paradex.py +40 -0
  53. ccxt/abstract/phemex.py +1 -0
  54. ccxt/abstract/upbit.py +4 -0
  55. ccxt/abstract/vertex.py +19 -0
  56. ccxt/abstract/whitebit.py +31 -1
  57. ccxt/abstract/woo.py +6 -2
  58. ccxt/abstract/woofipro.py +119 -0
  59. ccxt/abstract/xt.py +153 -0
  60. ccxt/abstract/zonda.py +6 -0
  61. ccxt/ace.py +164 -60
  62. ccxt/alpaca.py +727 -63
  63. ccxt/ascendex.py +395 -249
  64. ccxt/async_support/__init__.py +36 -14
  65. ccxt/async_support/ace.py +164 -60
  66. ccxt/async_support/alpaca.py +727 -63
  67. ccxt/async_support/ascendex.py +396 -249
  68. ccxt/async_support/base/exchange.py +531 -155
  69. ccxt/async_support/base/ws/aiohttp_client.py +28 -5
  70. ccxt/async_support/base/ws/cache.py +3 -2
  71. ccxt/async_support/base/ws/client.py +26 -5
  72. ccxt/async_support/base/ws/fast_client.py +4 -3
  73. ccxt/async_support/base/ws/functions.py +1 -1
  74. ccxt/async_support/base/ws/future.py +40 -31
  75. ccxt/async_support/base/ws/order_book_side.py +3 -0
  76. ccxt/async_support/bequant.py +1 -1
  77. ccxt/async_support/bigone.py +329 -202
  78. ccxt/async_support/binance.py +3030 -1087
  79. ccxt/async_support/binancecoinm.py +2 -1
  80. ccxt/async_support/binanceus.py +12 -1
  81. ccxt/async_support/binanceusdm.py +3 -1
  82. ccxt/async_support/bingx.py +3104 -880
  83. ccxt/async_support/bit2c.py +119 -38
  84. ccxt/async_support/bitbank.py +215 -76
  85. ccxt/async_support/bitbns.py +124 -53
  86. ccxt/async_support/bitfinex.py +3236 -1078
  87. ccxt/async_support/bitfinex1.py +1711 -0
  88. ccxt/async_support/bitflyer.py +238 -49
  89. ccxt/async_support/bitget.py +1513 -563
  90. ccxt/async_support/bithumb.py +199 -65
  91. ccxt/async_support/bitmart.py +1320 -435
  92. ccxt/async_support/bitmex.py +308 -111
  93. ccxt/async_support/bitopro.py +256 -96
  94. ccxt/async_support/bitrue.py +365 -233
  95. ccxt/async_support/bitso.py +201 -89
  96. ccxt/async_support/bitstamp.py +438 -269
  97. ccxt/async_support/bitteam.py +179 -73
  98. ccxt/async_support/bitvavo.py +180 -70
  99. ccxt/async_support/bl3p.py +92 -25
  100. ccxt/async_support/blockchaincom.py +193 -79
  101. ccxt/async_support/blofin.py +392 -148
  102. ccxt/async_support/btcalpha.py +161 -55
  103. ccxt/async_support/btcbox.py +250 -34
  104. ccxt/async_support/btcmarkets.py +232 -85
  105. ccxt/async_support/btcturk.py +159 -60
  106. ccxt/async_support/bybit.py +2231 -1193
  107. ccxt/async_support/cex.py +1409 -1329
  108. ccxt/async_support/coinbase.py +1454 -287
  109. ccxt/async_support/coinbaseadvanced.py +17 -0
  110. ccxt/async_support/{coinbasepro.py → coinbaseexchange.py} +233 -99
  111. ccxt/async_support/coinbaseinternational.py +428 -88
  112. ccxt/async_support/coincatch.py +5152 -0
  113. ccxt/async_support/coincheck.py +121 -38
  114. ccxt/async_support/coinex.py +4020 -3339
  115. ccxt/async_support/coinlist.py +273 -116
  116. ccxt/async_support/coinmate.py +204 -97
  117. ccxt/async_support/coinmetro.py +203 -110
  118. ccxt/async_support/coinone.py +142 -68
  119. ccxt/async_support/coinsph.py +206 -89
  120. ccxt/async_support/coinspot.py +137 -62
  121. ccxt/async_support/cryptocom.py +515 -185
  122. ccxt/async_support/currencycom.py +203 -85
  123. ccxt/async_support/defx.py +2066 -0
  124. ccxt/async_support/delta.py +404 -109
  125. ccxt/async_support/deribit.py +557 -323
  126. ccxt/async_support/digifinex.py +340 -223
  127. ccxt/async_support/ellipx.py +1826 -0
  128. ccxt/async_support/exmo.py +259 -128
  129. ccxt/async_support/gate.py +1472 -463
  130. ccxt/async_support/gemini.py +206 -84
  131. ccxt/async_support/hashkey.py +4164 -0
  132. ccxt/async_support/hitbtc.py +334 -178
  133. ccxt/async_support/hollaex.py +134 -83
  134. ccxt/async_support/htx.py +1095 -563
  135. ccxt/async_support/huobijp.py +105 -56
  136. ccxt/async_support/hyperliquid.py +1633 -268
  137. ccxt/async_support/idex.py +148 -95
  138. ccxt/async_support/independentreserve.py +236 -31
  139. ccxt/async_support/indodax.py +165 -62
  140. ccxt/async_support/kraken.py +871 -354
  141. ccxt/async_support/krakenfutures.py +324 -100
  142. ccxt/async_support/kucoin.py +917 -357
  143. ccxt/async_support/kucoinfutures.py +1004 -149
  144. ccxt/async_support/kuna.py +138 -106
  145. ccxt/async_support/latoken.py +135 -79
  146. ccxt/async_support/lbank.py +290 -113
  147. ccxt/async_support/luno.py +112 -62
  148. ccxt/async_support/lykke.py +104 -55
  149. ccxt/async_support/mercado.py +36 -29
  150. ccxt/async_support/mexc.py +995 -429
  151. ccxt/async_support/myokx.py +43 -0
  152. ccxt/async_support/ndax.py +163 -82
  153. ccxt/async_support/novadax.py +121 -75
  154. ccxt/async_support/oceanex.py +175 -59
  155. ccxt/async_support/okcoin.py +222 -163
  156. ccxt/async_support/okx.py +1776 -454
  157. ccxt/async_support/onetrading.py +132 -414
  158. ccxt/async_support/oxfun.py +2832 -0
  159. ccxt/async_support/p2b.py +79 -51
  160. ccxt/async_support/paradex.py +2017 -0
  161. ccxt/async_support/paymium.py +56 -32
  162. ccxt/async_support/phemex.py +572 -196
  163. ccxt/async_support/poloniex.py +218 -95
  164. ccxt/async_support/poloniexfutures.py +260 -92
  165. ccxt/async_support/probit.py +143 -110
  166. ccxt/async_support/timex.py +123 -70
  167. ccxt/async_support/tokocrypto.py +129 -93
  168. ccxt/async_support/tradeogre.py +39 -25
  169. ccxt/async_support/upbit.py +322 -113
  170. ccxt/async_support/vertex.py +2983 -0
  171. ccxt/async_support/wavesexchange.py +227 -173
  172. ccxt/async_support/wazirx.py +145 -65
  173. ccxt/async_support/whitebit.py +533 -138
  174. ccxt/async_support/woo.py +1137 -296
  175. ccxt/async_support/woofipro.py +2716 -0
  176. ccxt/async_support/xt.py +4628 -0
  177. ccxt/async_support/yobit.py +160 -92
  178. ccxt/async_support/zaif.py +80 -33
  179. ccxt/async_support/zonda.py +140 -69
  180. ccxt/base/errors.py +51 -20
  181. ccxt/base/exchange.py +1722 -480
  182. ccxt/base/precise.py +10 -0
  183. ccxt/base/types.py +223 -4
  184. ccxt/bequant.py +1 -1
  185. ccxt/bigone.py +329 -202
  186. ccxt/binance.py +3030 -1087
  187. ccxt/binancecoinm.py +2 -1
  188. ccxt/binanceus.py +12 -1
  189. ccxt/binanceusdm.py +3 -1
  190. ccxt/bingx.py +3104 -880
  191. ccxt/bit2c.py +119 -38
  192. ccxt/bitbank.py +215 -76
  193. ccxt/bitbns.py +124 -53
  194. ccxt/bitfinex.py +3235 -1078
  195. ccxt/bitfinex1.py +1710 -0
  196. ccxt/bitflyer.py +238 -49
  197. ccxt/bitget.py +1513 -563
  198. ccxt/bithumb.py +198 -65
  199. ccxt/bitmart.py +1320 -435
  200. ccxt/bitmex.py +308 -111
  201. ccxt/bitopro.py +256 -96
  202. ccxt/bitrue.py +365 -233
  203. ccxt/bitso.py +201 -89
  204. ccxt/bitstamp.py +438 -269
  205. ccxt/bitteam.py +179 -73
  206. ccxt/bitvavo.py +180 -70
  207. ccxt/bl3p.py +92 -25
  208. ccxt/blockchaincom.py +193 -79
  209. ccxt/blofin.py +392 -148
  210. ccxt/btcalpha.py +161 -55
  211. ccxt/btcbox.py +250 -34
  212. ccxt/btcmarkets.py +232 -85
  213. ccxt/btcturk.py +159 -60
  214. ccxt/bybit.py +2231 -1193
  215. ccxt/cex.py +1408 -1329
  216. ccxt/coinbase.py +1454 -287
  217. ccxt/coinbaseadvanced.py +17 -0
  218. ccxt/{coinbasepro.py → coinbaseexchange.py} +233 -99
  219. ccxt/coinbaseinternational.py +428 -88
  220. ccxt/coincatch.py +5152 -0
  221. ccxt/coincheck.py +121 -38
  222. ccxt/coinex.py +4020 -3339
  223. ccxt/coinlist.py +273 -116
  224. ccxt/coinmate.py +204 -97
  225. ccxt/coinmetro.py +203 -110
  226. ccxt/coinone.py +142 -68
  227. ccxt/coinsph.py +206 -89
  228. ccxt/coinspot.py +137 -62
  229. ccxt/cryptocom.py +515 -185
  230. ccxt/currencycom.py +203 -85
  231. ccxt/defx.py +2065 -0
  232. ccxt/delta.py +404 -109
  233. ccxt/deribit.py +557 -323
  234. ccxt/digifinex.py +340 -223
  235. ccxt/ellipx.py +1826 -0
  236. ccxt/exmo.py +259 -128
  237. ccxt/gate.py +1472 -463
  238. ccxt/gemini.py +206 -84
  239. ccxt/hashkey.py +4164 -0
  240. ccxt/hitbtc.py +334 -178
  241. ccxt/hollaex.py +134 -83
  242. ccxt/htx.py +1095 -563
  243. ccxt/huobijp.py +105 -56
  244. ccxt/hyperliquid.py +1632 -268
  245. ccxt/idex.py +148 -95
  246. ccxt/independentreserve.py +235 -31
  247. ccxt/indodax.py +165 -62
  248. ccxt/kraken.py +871 -354
  249. ccxt/krakenfutures.py +324 -100
  250. ccxt/kucoin.py +917 -357
  251. ccxt/kucoinfutures.py +1004 -149
  252. ccxt/kuna.py +138 -106
  253. ccxt/latoken.py +135 -79
  254. ccxt/lbank.py +290 -113
  255. ccxt/luno.py +112 -62
  256. ccxt/lykke.py +104 -55
  257. ccxt/mercado.py +36 -29
  258. ccxt/mexc.py +994 -429
  259. ccxt/myokx.py +43 -0
  260. ccxt/ndax.py +163 -82
  261. ccxt/novadax.py +121 -75
  262. ccxt/oceanex.py +175 -59
  263. ccxt/okcoin.py +222 -163
  264. ccxt/okx.py +1776 -454
  265. ccxt/onetrading.py +132 -414
  266. ccxt/oxfun.py +2831 -0
  267. ccxt/p2b.py +79 -51
  268. ccxt/paradex.py +2017 -0
  269. ccxt/paymium.py +56 -32
  270. ccxt/phemex.py +572 -196
  271. ccxt/poloniex.py +218 -95
  272. ccxt/poloniexfutures.py +260 -92
  273. ccxt/pro/__init__.py +29 -5
  274. ccxt/pro/alpaca.py +32 -17
  275. ccxt/pro/ascendex.py +62 -14
  276. ccxt/pro/bequant.py +4 -0
  277. ccxt/pro/binance.py +1596 -329
  278. ccxt/pro/binancecoinm.py +1 -0
  279. ccxt/pro/binanceus.py +2 -9
  280. ccxt/pro/binanceusdm.py +2 -0
  281. ccxt/pro/bingx.py +527 -134
  282. ccxt/pro/bitcoincom.py +4 -1
  283. ccxt/pro/bitfinex.py +731 -266
  284. ccxt/pro/bitfinex1.py +635 -0
  285. ccxt/pro/bitget.py +726 -357
  286. ccxt/pro/bithumb.py +380 -0
  287. ccxt/pro/bitmart.py +138 -39
  288. ccxt/pro/bitmex.py +199 -40
  289. ccxt/pro/bitopro.py +25 -13
  290. ccxt/pro/bitrue.py +31 -32
  291. ccxt/pro/bitstamp.py +7 -6
  292. ccxt/pro/bitvavo.py +203 -81
  293. ccxt/pro/blockchaincom.py +30 -17
  294. ccxt/pro/blofin.py +692 -0
  295. ccxt/pro/bybit.py +791 -82
  296. ccxt/pro/cex.py +99 -51
  297. ccxt/pro/coinbase.py +220 -30
  298. ccxt/{async_support/hitbtc3.py → pro/coinbaseadvanced.py} +5 -5
  299. ccxt/pro/{coinbasepro.py → coinbaseexchange.py} +19 -19
  300. ccxt/pro/coinbaseinternational.py +193 -30
  301. ccxt/pro/coincatch.py +1464 -0
  302. ccxt/pro/coincheck.py +11 -6
  303. ccxt/pro/coinex.py +965 -665
  304. ccxt/pro/coinone.py +17 -10
  305. ccxt/pro/cryptocom.py +446 -66
  306. ccxt/pro/currencycom.py +11 -10
  307. ccxt/pro/defx.py +832 -0
  308. ccxt/pro/deribit.py +167 -31
  309. ccxt/pro/exmo.py +252 -20
  310. ccxt/pro/gate.py +729 -64
  311. ccxt/pro/gemini.py +44 -26
  312. ccxt/pro/hashkey.py +802 -0
  313. ccxt/pro/hitbtc.py +208 -103
  314. ccxt/pro/hollaex.py +25 -9
  315. ccxt/pro/htx.py +83 -39
  316. ccxt/pro/huobijp.py +17 -16
  317. ccxt/pro/hyperliquid.py +502 -31
  318. ccxt/pro/idex.py +28 -13
  319. ccxt/pro/independentreserve.py +21 -16
  320. ccxt/pro/kraken.py +298 -51
  321. ccxt/pro/krakenfutures.py +166 -75
  322. ccxt/pro/kucoin.py +395 -77
  323. ccxt/pro/kucoinfutures.py +400 -99
  324. ccxt/pro/lbank.py +52 -31
  325. ccxt/pro/luno.py +12 -10
  326. ccxt/pro/mexc.py +400 -50
  327. ccxt/pro/myokx.py +28 -0
  328. ccxt/pro/ndax.py +25 -12
  329. ccxt/pro/okcoin.py +28 -9
  330. ccxt/pro/okx.py +935 -124
  331. ccxt/pro/onetrading.py +41 -24
  332. ccxt/pro/oxfun.py +1054 -0
  333. ccxt/pro/p2b.py +100 -24
  334. ccxt/pro/paradex.py +352 -0
  335. ccxt/pro/phemex.py +92 -33
  336. ccxt/pro/poloniex.py +128 -49
  337. ccxt/pro/poloniexfutures.py +53 -32
  338. ccxt/pro/probit.py +92 -85
  339. ccxt/pro/upbit.py +401 -8
  340. ccxt/pro/vertex.py +943 -0
  341. ccxt/pro/wazirx.py +46 -28
  342. ccxt/pro/whitebit.py +65 -12
  343. ccxt/pro/woo.py +437 -65
  344. ccxt/pro/woofipro.py +1271 -0
  345. ccxt/pro/xt.py +1067 -0
  346. ccxt/probit.py +143 -110
  347. ccxt/static_dependencies/__init__.py +1 -1
  348. ccxt/static_dependencies/lark/__init__.py +38 -0
  349. ccxt/static_dependencies/lark/__pyinstaller/__init__.py +6 -0
  350. ccxt/static_dependencies/lark/__pyinstaller/hook-lark.py +14 -0
  351. ccxt/static_dependencies/lark/ast_utils.py +59 -0
  352. ccxt/static_dependencies/lark/common.py +86 -0
  353. ccxt/static_dependencies/lark/exceptions.py +292 -0
  354. ccxt/static_dependencies/lark/grammar.py +130 -0
  355. ccxt/static_dependencies/lark/grammars/__init__.py +0 -0
  356. ccxt/static_dependencies/lark/indenter.py +143 -0
  357. ccxt/static_dependencies/lark/lark.py +658 -0
  358. ccxt/static_dependencies/lark/lexer.py +678 -0
  359. ccxt/static_dependencies/lark/load_grammar.py +1428 -0
  360. ccxt/static_dependencies/lark/parse_tree_builder.py +391 -0
  361. ccxt/static_dependencies/lark/parser_frontends.py +257 -0
  362. ccxt/static_dependencies/lark/parsers/__init__.py +0 -0
  363. ccxt/static_dependencies/lark/parsers/cyk.py +340 -0
  364. ccxt/static_dependencies/lark/parsers/earley.py +314 -0
  365. ccxt/static_dependencies/lark/parsers/earley_common.py +42 -0
  366. ccxt/static_dependencies/lark/parsers/earley_forest.py +801 -0
  367. ccxt/static_dependencies/lark/parsers/grammar_analysis.py +203 -0
  368. ccxt/static_dependencies/lark/parsers/lalr_analysis.py +332 -0
  369. ccxt/static_dependencies/lark/parsers/lalr_interactive_parser.py +158 -0
  370. ccxt/static_dependencies/lark/parsers/lalr_parser.py +122 -0
  371. ccxt/static_dependencies/lark/parsers/lalr_parser_state.py +110 -0
  372. ccxt/static_dependencies/lark/parsers/xearley.py +165 -0
  373. ccxt/static_dependencies/lark/py.typed +0 -0
  374. ccxt/static_dependencies/lark/reconstruct.py +107 -0
  375. ccxt/static_dependencies/lark/tools/__init__.py +70 -0
  376. ccxt/static_dependencies/lark/tools/nearley.py +202 -0
  377. ccxt/static_dependencies/lark/tools/serialize.py +32 -0
  378. ccxt/static_dependencies/lark/tools/standalone.py +196 -0
  379. ccxt/static_dependencies/lark/tree.py +267 -0
  380. ccxt/static_dependencies/lark/tree_matcher.py +186 -0
  381. ccxt/static_dependencies/lark/tree_templates.py +180 -0
  382. ccxt/static_dependencies/lark/utils.py +343 -0
  383. ccxt/static_dependencies/lark/visitors.py +596 -0
  384. ccxt/static_dependencies/marshmallow/__init__.py +81 -0
  385. ccxt/static_dependencies/marshmallow/base.py +65 -0
  386. ccxt/static_dependencies/marshmallow/class_registry.py +94 -0
  387. ccxt/static_dependencies/marshmallow/decorators.py +231 -0
  388. ccxt/static_dependencies/marshmallow/error_store.py +60 -0
  389. ccxt/static_dependencies/marshmallow/exceptions.py +71 -0
  390. ccxt/static_dependencies/marshmallow/fields.py +2114 -0
  391. ccxt/static_dependencies/marshmallow/orderedset.py +89 -0
  392. ccxt/static_dependencies/marshmallow/py.typed +0 -0
  393. ccxt/static_dependencies/marshmallow/schema.py +1228 -0
  394. ccxt/static_dependencies/marshmallow/types.py +12 -0
  395. ccxt/static_dependencies/marshmallow/utils.py +378 -0
  396. ccxt/static_dependencies/marshmallow/validate.py +678 -0
  397. ccxt/static_dependencies/marshmallow/warnings.py +2 -0
  398. ccxt/static_dependencies/marshmallow_dataclass/__init__.py +1047 -0
  399. ccxt/static_dependencies/marshmallow_dataclass/collection_field.py +51 -0
  400. ccxt/static_dependencies/marshmallow_dataclass/lazy_class_attribute.py +45 -0
  401. ccxt/static_dependencies/marshmallow_dataclass/mypy.py +71 -0
  402. ccxt/static_dependencies/marshmallow_dataclass/py.typed +0 -0
  403. ccxt/static_dependencies/marshmallow_dataclass/typing.py +14 -0
  404. ccxt/static_dependencies/marshmallow_dataclass/union_field.py +82 -0
  405. ccxt/static_dependencies/marshmallow_oneofschema/__init__.py +1 -0
  406. ccxt/static_dependencies/marshmallow_oneofschema/one_of_schema.py +193 -0
  407. ccxt/static_dependencies/marshmallow_oneofschema/py.typed +0 -0
  408. ccxt/static_dependencies/starknet/__init__.py +0 -0
  409. ccxt/static_dependencies/starknet/cairo/__init__.py +0 -0
  410. ccxt/static_dependencies/starknet/cairo/data_types.py +123 -0
  411. ccxt/static_dependencies/starknet/cairo/deprecated_parse/__init__.py +0 -0
  412. ccxt/static_dependencies/starknet/cairo/deprecated_parse/cairo_types.py +77 -0
  413. ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser.py +46 -0
  414. ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser_transformer.py +138 -0
  415. ccxt/static_dependencies/starknet/cairo/felt.py +64 -0
  416. ccxt/static_dependencies/starknet/cairo/type_parser.py +121 -0
  417. ccxt/static_dependencies/starknet/cairo/v1/__init__.py +0 -0
  418. ccxt/static_dependencies/starknet/cairo/v1/type_parser.py +59 -0
  419. ccxt/static_dependencies/starknet/cairo/v2/__init__.py +0 -0
  420. ccxt/static_dependencies/starknet/cairo/v2/type_parser.py +77 -0
  421. ccxt/static_dependencies/starknet/ccxt_utils.py +7 -0
  422. ccxt/static_dependencies/starknet/common.py +15 -0
  423. ccxt/static_dependencies/starknet/constants.py +39 -0
  424. ccxt/static_dependencies/starknet/hash/__init__.py +0 -0
  425. ccxt/static_dependencies/starknet/hash/address.py +79 -0
  426. ccxt/static_dependencies/starknet/hash/compiled_class_hash_objects.py +111 -0
  427. ccxt/static_dependencies/starknet/hash/selector.py +16 -0
  428. ccxt/static_dependencies/starknet/hash/storage.py +12 -0
  429. ccxt/static_dependencies/starknet/hash/utils.py +78 -0
  430. ccxt/static_dependencies/starknet/models/__init__.py +0 -0
  431. ccxt/static_dependencies/starknet/models/typed_data.py +45 -0
  432. ccxt/static_dependencies/starknet/serialization/__init__.py +24 -0
  433. ccxt/static_dependencies/starknet/serialization/_calldata_reader.py +40 -0
  434. ccxt/static_dependencies/starknet/serialization/_context.py +142 -0
  435. ccxt/static_dependencies/starknet/serialization/data_serializers/__init__.py +10 -0
  436. ccxt/static_dependencies/starknet/serialization/data_serializers/_common.py +82 -0
  437. ccxt/static_dependencies/starknet/serialization/data_serializers/array_serializer.py +43 -0
  438. ccxt/static_dependencies/starknet/serialization/data_serializers/bool_serializer.py +37 -0
  439. ccxt/static_dependencies/starknet/serialization/data_serializers/byte_array_serializer.py +66 -0
  440. ccxt/static_dependencies/starknet/serialization/data_serializers/cairo_data_serializer.py +71 -0
  441. ccxt/static_dependencies/starknet/serialization/data_serializers/enum_serializer.py +71 -0
  442. ccxt/static_dependencies/starknet/serialization/data_serializers/felt_serializer.py +50 -0
  443. ccxt/static_dependencies/starknet/serialization/data_serializers/named_tuple_serializer.py +58 -0
  444. ccxt/static_dependencies/starknet/serialization/data_serializers/option_serializer.py +43 -0
  445. ccxt/static_dependencies/starknet/serialization/data_serializers/output_serializer.py +40 -0
  446. ccxt/static_dependencies/starknet/serialization/data_serializers/payload_serializer.py +72 -0
  447. ccxt/static_dependencies/starknet/serialization/data_serializers/struct_serializer.py +36 -0
  448. ccxt/static_dependencies/starknet/serialization/data_serializers/tuple_serializer.py +36 -0
  449. ccxt/static_dependencies/starknet/serialization/data_serializers/uint256_serializer.py +76 -0
  450. ccxt/static_dependencies/starknet/serialization/data_serializers/uint_serializer.py +100 -0
  451. ccxt/static_dependencies/starknet/serialization/data_serializers/unit_serializer.py +32 -0
  452. ccxt/static_dependencies/starknet/serialization/errors.py +10 -0
  453. ccxt/static_dependencies/starknet/serialization/factory.py +229 -0
  454. ccxt/static_dependencies/starknet/serialization/function_serialization_adapter.py +110 -0
  455. ccxt/static_dependencies/starknet/serialization/tuple_dataclass.py +59 -0
  456. ccxt/static_dependencies/starknet/utils/__init__.py +0 -0
  457. ccxt/static_dependencies/starknet/utils/constructor_args_translator.py +86 -0
  458. ccxt/static_dependencies/starknet/utils/iterable.py +13 -0
  459. ccxt/static_dependencies/starknet/utils/schema.py +13 -0
  460. ccxt/static_dependencies/starknet/utils/typed_data.py +182 -0
  461. ccxt/static_dependencies/starkware/__init__.py +0 -0
  462. ccxt/static_dependencies/starkware/crypto/__init__.py +0 -0
  463. ccxt/static_dependencies/starkware/crypto/fast_pedersen_hash.py +50 -0
  464. ccxt/static_dependencies/starkware/crypto/math_utils.py +78 -0
  465. ccxt/static_dependencies/starkware/crypto/signature.py +2344 -0
  466. ccxt/static_dependencies/starkware/crypto/utils.py +63 -0
  467. ccxt/static_dependencies/sympy/__init__.py +0 -0
  468. ccxt/static_dependencies/sympy/core/__init__.py +0 -0
  469. ccxt/static_dependencies/sympy/core/intfunc.py +35 -0
  470. ccxt/static_dependencies/sympy/external/__init__.py +0 -0
  471. ccxt/static_dependencies/sympy/external/gmpy.py +345 -0
  472. ccxt/static_dependencies/sympy/external/importtools.py +187 -0
  473. ccxt/static_dependencies/sympy/external/ntheory.py +637 -0
  474. ccxt/static_dependencies/sympy/external/pythonmpq.py +341 -0
  475. ccxt/static_dependencies/typing_inspect/__init__.py +0 -0
  476. ccxt/static_dependencies/typing_inspect/typing_inspect.py +851 -0
  477. ccxt/test/{test_async.py → tests_async.py} +456 -391
  478. ccxt/test/tests_helpers.py +285 -0
  479. ccxt/test/tests_init.py +39 -0
  480. ccxt/test/{test_sync.py → tests_sync.py} +456 -393
  481. ccxt/timex.py +123 -70
  482. ccxt/tokocrypto.py +129 -93
  483. ccxt/tradeogre.py +39 -25
  484. ccxt/upbit.py +322 -113
  485. ccxt/vertex.py +2983 -0
  486. ccxt/wavesexchange.py +227 -173
  487. ccxt/wazirx.py +145 -65
  488. ccxt/whitebit.py +533 -138
  489. ccxt/woo.py +1137 -296
  490. ccxt/woofipro.py +2716 -0
  491. ccxt/xt.py +4627 -0
  492. ccxt/yobit.py +159 -92
  493. ccxt/zaif.py +80 -33
  494. ccxt/zonda.py +140 -69
  495. ccxt-4.4.48.dist-info/LICENSE.txt +21 -0
  496. ccxt-4.4.48.dist-info/METADATA +646 -0
  497. ccxt-4.4.48.dist-info/RECORD +669 -0
  498. {ccxt-4.2.77.dist-info → ccxt-4.4.48.dist-info}/WHEEL +1 -1
  499. ccxt/abstract/bitbay.py +0 -47
  500. ccxt/abstract/bitfinex2.py +0 -139
  501. ccxt/abstract/hitbtc3.py +0 -115
  502. ccxt/async_support/bitbay.py +0 -17
  503. ccxt/async_support/bitfinex2.py +0 -3496
  504. ccxt/async_support/flowbtc.py +0 -34
  505. ccxt/bitbay.py +0 -17
  506. ccxt/bitfinex2.py +0 -3496
  507. ccxt/flowbtc.py +0 -34
  508. ccxt/hitbtc3.py +0 -16
  509. ccxt/pro/bitfinex2.py +0 -1081
  510. ccxt/test/base/__init__.py +0 -28
  511. ccxt/test/base/test_account.py +0 -26
  512. ccxt/test/base/test_balance.py +0 -56
  513. ccxt/test/base/test_borrow_interest.py +0 -35
  514. ccxt/test/base/test_borrow_rate.py +0 -32
  515. ccxt/test/base/test_calculate_fee.py +0 -51
  516. ccxt/test/base/test_crypto.py +0 -127
  517. ccxt/test/base/test_currency.py +0 -76
  518. ccxt/test/base/test_datetime.py +0 -103
  519. ccxt/test/base/test_decimal_to_precision.py +0 -392
  520. ccxt/test/base/test_deep_extend.py +0 -68
  521. ccxt/test/base/test_deposit_withdrawal.py +0 -50
  522. ccxt/test/base/test_exchange_datetime_functions.py +0 -76
  523. ccxt/test/base/test_funding_rate_history.py +0 -29
  524. ccxt/test/base/test_last_price.py +0 -32
  525. ccxt/test/base/test_ledger_entry.py +0 -45
  526. ccxt/test/base/test_ledger_item.py +0 -48
  527. ccxt/test/base/test_leverage_tier.py +0 -33
  528. ccxt/test/base/test_margin_mode.py +0 -24
  529. ccxt/test/base/test_margin_modification.py +0 -35
  530. ccxt/test/base/test_market.py +0 -190
  531. ccxt/test/base/test_number.py +0 -411
  532. ccxt/test/base/test_ohlcv.py +0 -32
  533. ccxt/test/base/test_open_interest.py +0 -32
  534. ccxt/test/base/test_order.py +0 -64
  535. ccxt/test/base/test_order_book.py +0 -63
  536. ccxt/test/base/test_position.py +0 -60
  537. ccxt/test/base/test_shared_methods.py +0 -345
  538. ccxt/test/base/test_status.py +0 -24
  539. ccxt/test/base/test_throttle.py +0 -126
  540. ccxt/test/base/test_ticker.py +0 -86
  541. ccxt/test/base/test_trade.py +0 -47
  542. ccxt/test/base/test_trading_fee.py +0 -26
  543. ccxt/test/base/test_transaction.py +0 -39
  544. ccxt-4.2.77.dist-info/METADATA +0 -626
  545. ccxt-4.2.77.dist-info/RECORD +0 -534
  546. {ccxt-4.2.77.dist-info → ccxt-4.4.48.dist-info}/top_level.txt +0 -0
ccxt/ellipx.py ADDED
@@ -0,0 +1,1826 @@
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.ellipx import ImplicitAPI
8
+ import math
9
+ from ccxt.base.types import Any, Balances, Currencies, Currency, DepositAddress, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Ticker, Trade, TradingFeeInterface, Transaction
10
+ from typing import List
11
+ from ccxt.base.errors import ExchangeError
12
+ from ccxt.base.errors import AuthenticationError
13
+ from ccxt.base.errors import PermissionDenied
14
+ from ccxt.base.errors import ArgumentsRequired
15
+ from ccxt.base.errors import BadRequest
16
+ from ccxt.base.errors import NotSupported
17
+ from ccxt.base.errors import DDoSProtection
18
+ from ccxt.base.decimal_to_precision import TICK_SIZE
19
+ from ccxt.base.precise import Precise
20
+
21
+
22
+ class ellipx(Exchange, ImplicitAPI):
23
+
24
+ def describe(self):
25
+ return self.deep_extend(super(ellipx, self).describe(), {
26
+ 'id': 'ellipx',
27
+ 'name': 'Ellipx',
28
+ 'countries': ['PL'],
29
+ 'rateLimit': 200, # todo check
30
+ 'version': 'v1',
31
+ 'certified': False,
32
+ 'pro': False,
33
+ 'has': {
34
+ 'CORS': None,
35
+ 'spot': True,
36
+ 'margin': False,
37
+ 'swap': False,
38
+ 'future': False,
39
+ 'option': False,
40
+ 'addMargin': False,
41
+ 'cancelAllOrders': False,
42
+ 'cancelAllOrdersAfter': False,
43
+ 'cancelOrder': True,
44
+ 'cancelOrders': False,
45
+ 'cancelWithdraw': False,
46
+ 'closePosition': False,
47
+ 'createConvertTrade': False,
48
+ 'createDepositAddress': False,
49
+ 'createMarketBuyOrderWithCost': False,
50
+ 'createMarketOrder': False,
51
+ 'createMarketOrderWithCost': False,
52
+ 'createMarketSellOrderWithCost': False,
53
+ 'createOrder': True,
54
+ 'createOrderWithTakeProfitAndStopLoss': False,
55
+ 'createReduceOnlyOrder': False,
56
+ 'createStopLimitOrder': False,
57
+ 'createStopLossOrder': False,
58
+ 'createStopMarketOrder': False,
59
+ 'createStopOrder': False,
60
+ 'createTakeProfitOrder': False,
61
+ 'createTrailingAmountOrder': False,
62
+ 'createTrailingPercentOrder': False,
63
+ 'createTriggerOrder': False,
64
+ 'fetchAccounts': False,
65
+ 'fetchBalance': True,
66
+ 'fetchCanceledAndClosedOrders': False,
67
+ 'fetchCanceledOrders': False,
68
+ 'fetchClosedOrder': False,
69
+ 'fetchClosedOrders': False,
70
+ 'fetchConvertCurrencies': False,
71
+ 'fetchConvertQuote': False,
72
+ 'fetchConvertTrade': False,
73
+ 'fetchConvertTradeHistory': False,
74
+ 'fetchCurrencies': True,
75
+ 'fetchDepositAddress': True,
76
+ 'fetchDeposits': False,
77
+ 'fetchDepositsWithdrawals': False,
78
+ 'fetchFundingHistory': False,
79
+ 'fetchFundingRate': False,
80
+ 'fetchFundingRateHistory': False,
81
+ 'fetchFundingRates': False,
82
+ 'fetchIndexOHLCV': False,
83
+ 'fetchLedger': False,
84
+ 'fetchLeverage': False,
85
+ 'fetchLeverageTiers': False,
86
+ 'fetchMarginAdjustmentHistory': False,
87
+ 'fetchMarginMode': False,
88
+ 'fetchMarkets': True,
89
+ 'fetchMarkOHLCV': False,
90
+ 'fetchMyTrades': False,
91
+ 'fetchOHLCV': True,
92
+ 'fetchOpenInterestHistory': False,
93
+ 'fetchOpenOrder': False,
94
+ 'fetchOpenOrders': True,
95
+ 'fetchOrder': True,
96
+ 'fetchOrderBook': True,
97
+ 'fetchOrders': True,
98
+ 'fetchOrderTrades': True,
99
+ 'fetchPosition': False,
100
+ 'fetchPositionHistory': False,
101
+ 'fetchPositionMode': False,
102
+ 'fetchPositions': False,
103
+ 'fetchPositionsForSymbol': False,
104
+ 'fetchPositionsHistory': False,
105
+ 'fetchPremiumIndexOHLCV': False,
106
+ 'fetchStatus': False,
107
+ 'fetchTicker': True,
108
+ 'fetchTickers': False,
109
+ 'fetchTime': False,
110
+ 'fetchTrades': True,
111
+ 'fetchTradingFee': True,
112
+ 'fetchTradingFees': False,
113
+ 'fetchTransactions': False,
114
+ 'fetchTransfers': False,
115
+ 'fetchWithdrawals': False,
116
+ 'reduceMargin': False,
117
+ 'sandbox': False,
118
+ 'setLeverage': False,
119
+ 'setMargin': False,
120
+ 'setPositionMode': False,
121
+ 'transfer': False,
122
+ 'withdraw': True,
123
+ },
124
+ 'timeframes': {
125
+ '1m': '1m',
126
+ '5m': '5m',
127
+ '10m': '10m',
128
+ '1h': '1h',
129
+ '6h': '6h',
130
+ '12h': '12h',
131
+ '1d': '1d',
132
+ },
133
+ 'urls': {
134
+ 'logo': 'https://github.com/user-attachments/assets/e07c3f40-281c-4cdf-bacf-fa1c58218a2c',
135
+ 'api': {
136
+ 'public': 'https://data.ellipx.com',
137
+ 'private': 'https://app.ellipx.com/_rest',
138
+ '_rest': 'https://app.ellipx.com/_rest',
139
+ },
140
+ 'www': 'https://www.ellipx.com',
141
+ 'doc': 'https://docs.google.com/document/d/1ZXzTQYffKE_EglTaKptxGQERRnunuLHEMmar7VC9syM',
142
+ 'fees': 'https://www.ellipx.com/pages/pricing',
143
+ 'referral': '', # todo
144
+ },
145
+ 'api': {
146
+ '_rest': {
147
+ 'get': {
148
+ 'Market': 1,
149
+ 'Market/{currencyPair}': 1,
150
+ 'Crypto/Token/Info': 1,
151
+ },
152
+ },
153
+ 'public': {
154
+ 'get': {
155
+ 'Market/{currencyPair}:getDepth': 1,
156
+ 'Market/{currencyPair}:ticker': 1,
157
+ 'Market/{currencyPair}:getTrades': 1,
158
+ 'Market/{currencyPair}:getGraph': 1,
159
+ 'CMC:summary': 1,
160
+ 'CMC/{currencyPair}:ticker': 1,
161
+ },
162
+ },
163
+ 'private': {
164
+ 'get': {
165
+ 'User/Wallet': 1,
166
+ 'Market/{currencyPair}/Order': 1,
167
+ 'Market/Order/{orderUuid}': 1,
168
+ 'Market/{currencyPair}/Trade': 1,
169
+ 'Market/TradeFee:query': 1,
170
+ 'Unit/{currency}': 1,
171
+ 'Crypto/Token/{currency}': 1,
172
+ 'Crypto/Token/{currency}:chains': 1,
173
+ },
174
+ 'post': {
175
+ 'Market/{currencyPair}/Order': 1,
176
+ 'Crypto/Address:fetch': 1,
177
+ 'Crypto/Disbursement:withdraw': 1,
178
+ },
179
+ 'delete': {
180
+ 'Market/Order/{orderUuid}': 1,
181
+ },
182
+ },
183
+ },
184
+ 'fees': {
185
+ 'trading': {
186
+ 'tierBased': True,
187
+ 'feeSide': 'get',
188
+ 'percentage': True,
189
+ 'maker': self.parse_number('0.0025'), # default 25bps
190
+ 'taker': self.parse_number('0.0030'), # default 30bps
191
+ 'tiers': {
192
+ # volume in USDT
193
+ 'maker': [
194
+ [self.parse_number('0'), self.parse_number('0.0025')], # 0-10k: 25bps
195
+ [self.parse_number('10000'), self.parse_number('0.0020')], # 10k-50k: 20bps
196
+ [self.parse_number('50000'), self.parse_number('0.0015')], # 50k-100k: 15bps
197
+ [self.parse_number('100000'), self.parse_number('0.0010')], # 100k-1M: 10bps
198
+ [self.parse_number('1000000'), self.parse_number('0.0008')], # 1M-5M: 8bps
199
+ [self.parse_number('5000000'), self.parse_number('0.0003')], # 5M-15M: 3bps
200
+ [self.parse_number('15000000'), self.parse_number('0.0000')], # 15M-75M: 0bps
201
+ [self.parse_number('75000000'), self.parse_number('0.0000')], # 75M-100M: 0bps
202
+ [self.parse_number('100000000'), self.parse_number('0.0000')], # 100M+: 0bps
203
+ ],
204
+ 'taker': [
205
+ [self.parse_number('0'), self.parse_number('0.0030')], # 0-10k: 30bps
206
+ [self.parse_number('10000'), self.parse_number('0.0025')], # 10k-50k: 25bps
207
+ [self.parse_number('50000'), self.parse_number('0.0020')], # 50k-100k: 20bps
208
+ [self.parse_number('100000'), self.parse_number('0.0015')], # 100k-1M: 15bps
209
+ [self.parse_number('1000000'), self.parse_number('0.0012')], # 1M-5M: 12bps
210
+ [self.parse_number('5000000'), self.parse_number('0.0010')], # 5M-15M: 10bps
211
+ [self.parse_number('15000000'), self.parse_number('0.0008')], # 15M-75M: 8bps
212
+ [self.parse_number('75000000'), self.parse_number('0.0005')], # 75M-100M: 5bps
213
+ [self.parse_number('100000000'), self.parse_number('0.0003')], # 100M+: 3bps
214
+ ],
215
+ },
216
+ },
217
+ 'stablecoin': {
218
+ 'tierBased': False,
219
+ 'percentage': True,
220
+ 'maker': self.parse_number('0.0000'), # 0%
221
+ 'taker': self.parse_number('0.000015'), # 0.0015%
222
+ },
223
+ },
224
+ 'options': {
225
+ 'defaultType': 'spot',
226
+ 'recvWindow': 5 * 1000,
227
+ 'broker': 'CCXT',
228
+ 'networks': {
229
+ 'Bitcoin': 'Bitcoin',
230
+ 'Ethereum': 'ERC20',
231
+ },
232
+ 'defaultNetwork': 'defaultNetwork',
233
+ 'defaultNetworkCodeReplacements': {
234
+ 'BTC': 'Bitcoin',
235
+ 'ETH': 'Ethereum',
236
+ },
237
+ },
238
+ 'commonCurrencies': {},
239
+ 'exceptions': {
240
+ 'exact': {
241
+ # todo
242
+ '400': BadRequest,
243
+ '401': AuthenticationError,
244
+ '403': PermissionDenied,
245
+ '404': BadRequest,
246
+ '429': DDoSProtection,
247
+ '418': PermissionDenied,
248
+ '500': ExchangeError,
249
+ '504': ExchangeError,
250
+ },
251
+ 'broad': {},
252
+ },
253
+ 'precisionMode': TICK_SIZE,
254
+ })
255
+
256
+ def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
257
+ path = self.implode_params(path, params)
258
+ url = self.urls['api'][api] + '/' + path
259
+ if api == 'private':
260
+ self.check_required_credentials()
261
+ nonce = self.uuid()
262
+ timestamp = str(self.seconds())
263
+ if method == 'GET':
264
+ body = ''
265
+ else:
266
+ body = self.json(params)
267
+ params = self.extend({
268
+ '_key': self.apiKey,
269
+ '_time': timestamp,
270
+ '_nonce': nonce,
271
+ }, params)
272
+ query = self.urlencode(params)
273
+ bodyHash = self.hash(self.encode(body), 'sha256')
274
+ # Create sign string components
275
+ bodyHashBytes = self.base16_to_binary(bodyHash)
276
+ nulByte = self.number_to_be(0, 1)
277
+ components = [
278
+ self.encode(method),
279
+ nulByte,
280
+ self.encode(path),
281
+ nulByte,
282
+ self.encode(query),
283
+ nulByte,
284
+ bodyHashBytes,
285
+ ]
286
+ # Join with null byte separator using encode
287
+ signString = self.binary_concat_array(components)
288
+ sec = self.secret
289
+ remainder = self.calculate_mod(len(sec), 4)
290
+ paddingLength = 4 - remainder if remainder else 0
291
+ secretWithPadding = self.secret.replace('-', '+')
292
+ secretWithPadding = secretWithPadding.replace('_', '/')
293
+ secretWithPadding = secretWithPadding.ljust(len(self.secret) + paddingLength, '=')
294
+ secretBytes = self.base64_to_binary(secretWithPadding)
295
+ seed = self.array_slice(secretBytes, 0, 32) # Extract first 32 bytes
296
+ signature = self.eddsa(signString, seed, 'ed25519')
297
+ params['_sign'] = signature
298
+ if params:
299
+ url += '?' + self.urlencode(params)
300
+ if method == 'GET':
301
+ body = None
302
+ else:
303
+ headers = {
304
+ 'Content-Type': 'application/json',
305
+ }
306
+ return {'url': url, 'method': method, 'body': body, 'headers': headers}
307
+
308
+ def calculate_mod(self, a, b):
309
+ # trick to fix php transpiling error
310
+ return a % b
311
+
312
+ def fetch_markets(self, params={}) -> List[Market]:
313
+ """
314
+ Fetches market information from the exchange.
315
+
316
+ https://docs.ccxt.com/en/latest/manual.html#markets
317
+ https://docs.google.com/document/d/1ZXzTQYffKE_EglTaKptxGQERRnunuLHEMmar7VC9syM/edit?tab=t.0#heading=h.1a1t05wpgfof
318
+
319
+ :param dict [params]: - Extra parameters specific to the exchange API endpoint
320
+ :returns Promise<Market[]>: An array of market structures.
321
+ """
322
+ response = self._restGetMarket(params)
323
+ # {
324
+ # Market__: "mkt-lrnp2e-eaor-eobj-ua73-75j6sjxe",
325
+ # Primary_Unit__: "unit-aebkye-u35b-e5zm-zt22-2qvwhsqa",
326
+ # Secondary_Unit__: "unit-jcevlk-soxf-fepb-yjwm-b32q5bom",
327
+ # Primary_Step: null,
328
+ # Secondary_Step: null,
329
+ # Status: "active",
330
+ # Default_Scale: "5",
331
+ # Priority: "100",
332
+ # Created: {
333
+ # unix: "1728113809",
334
+ # us: "0",
335
+ # iso: "2024-10-05 07:36:49.000000",
336
+ # tz: "UTC",
337
+ # full: "1728113809000000",
338
+ # unixms: "1728113809000",
339
+ # },
340
+ # Start: {
341
+ # unix: "1728295200",
342
+ # us: "0",
343
+ # iso: "2024-10-07 10:00:00.000000",
344
+ # tz: "UTC",
345
+ # full: "1728295200000000",
346
+ # unixms: "1728295200000",
347
+ # },
348
+ # Key: "BTC_USDC",
349
+ # Primary: {
350
+ # Unit__: "unit-aebkye-u35b-e5zm-zt22-2qvwhsqa",
351
+ # Currency__: "BTC",
352
+ # Crypto_Token__: "crtok-c5v3mh-grfn-hl5d-lmel-fvggbf4i",
353
+ # Key: "BTC",
354
+ # Symbol: "BTC",
355
+ # Symbol_Position: "after",
356
+ # Name: "Bitcoin",
357
+ # Decimals: "8",
358
+ # Display_Decimals: "8",
359
+ # Legacy_Decimals: null,
360
+ # Type: "crypto_token",
361
+ # Visible: "Y",
362
+ # Created: {
363
+ # unix: "1495247415",
364
+ # us: "0",
365
+ # iso: "2017-05-20 02:30:15.000000",
366
+ # tz: "UTC",
367
+ # full: "1495247415000000",
368
+ # unixms: "1495247415000",
369
+ # },
370
+ # },
371
+ # Secondary: {
372
+ # Unit__: "unit-jcevlk-soxf-fepb-yjwm-b32q5bom",
373
+ # Currency__: null,
374
+ # Crypto_Token__: "crtok-ptabkh-ra4r-anbd-cqra-bqfbtnba",
375
+ # Key: "USDC",
376
+ # Symbol: null,
377
+ # Symbol_Position: "before",
378
+ # Name: "Circle USD",
379
+ # Decimals: "6",
380
+ # Display_Decimals: "6",
381
+ # Legacy_Decimals: null,
382
+ # Type: "crypto_token",
383
+ # Visible: "Y",
384
+ # Created: {
385
+ # unix: "1694859829",
386
+ # us: "0",
387
+ # iso: "2023-09-16 10:23:49.000000",
388
+ # tz: "UTC",
389
+ # full: "1694859829000000",
390
+ # unixms: "1694859829000",
391
+ # },
392
+ # },
393
+ # }
394
+ markets = self.safe_value(response, 'data', [])
395
+ return self.parse_markets(markets)
396
+
397
+ def parse_market(self, market: dict) -> Market:
398
+ id = self.safe_string(market, 'Key')
399
+ base = self.safe_string(market['Primary'], 'Key')
400
+ quote = self.safe_string(market['Secondary'], 'Key')
401
+ baseId = self.safe_string(market['Primary'], 'Crypto_Token__')
402
+ quoteId = self.safe_string(market['Secondary'], 'Crypto_Token__')
403
+ status = self.safe_string(market, 'Status') == 'active'
404
+ created = self.safe_timestamp(market['Created'], 'unix')
405
+ amountPrecision = self.parse_number(self.parse_precision(self.safe_string(market['Primary'], 'Decimals')))
406
+ pricePrecision = self.parse_number(self.parse_precision(self.safe_string(market['Secondary'], 'Decimals')))
407
+ fees = self.fees # should use fetchTradingFees
408
+ return self.safe_market_structure({
409
+ 'id': id,
410
+ 'symbol': base + '/' + quote,
411
+ 'base': base,
412
+ 'quote': quote,
413
+ 'settle': None,
414
+ 'baseId': baseId,
415
+ 'quoteId': quoteId,
416
+ 'settleId': None,
417
+ 'type': 'spot',
418
+ 'spot': True,
419
+ 'margin': False,
420
+ 'swap': False,
421
+ 'future': False,
422
+ 'option': False,
423
+ 'active': status,
424
+ 'contract': False,
425
+ 'linear': None,
426
+ 'inverse': None,
427
+ 'taker': fees['trading']['taker'],
428
+ 'maker': fees['trading']['maker'],
429
+ 'contractSize': None,
430
+ 'expiry': None,
431
+ 'expiryDatetime': None,
432
+ 'strike': None,
433
+ 'optionType': None,
434
+ 'precision': {
435
+ 'amount': amountPrecision,
436
+ 'price': pricePrecision,
437
+ },
438
+ 'limits': {
439
+ 'amount': {
440
+ 'min': None,
441
+ 'max': None,
442
+ },
443
+ 'price': {
444
+ 'min': None,
445
+ 'max': None,
446
+ },
447
+ 'cost': {
448
+ 'min': None,
449
+ 'max': None,
450
+ },
451
+ },
452
+ 'info': market,
453
+ 'created': created,
454
+ })
455
+
456
+ def fetch_ticker(self, symbol: str, params={}) -> Ticker:
457
+ """
458
+ fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
459
+
460
+ https://docs.google.com/document/d/1ZXzTQYffKE_EglTaKptxGQERRnunuLHEMmar7VC9syM/edit?tab=t.0#heading=h.d2jylz4u6pmu
461
+
462
+ :param str symbol: unified symbol of the market to fetch the ticker for
463
+ :param dict [params]: extra parameters specific to the exchange API endpoint
464
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
465
+ """
466
+ self.load_markets()
467
+ market = self.market(symbol)
468
+ marketId = market['id']
469
+ request = {
470
+ 'currencyPair': marketId,
471
+ }
472
+ response = self.publicGetMarketCurrencyPairTicker(self.extend(request, params))
473
+ #
474
+ # {
475
+ # "data": {
476
+ # "market": "BTC_USDC",
477
+ # "ticker": {
478
+ # "time": 1730814600,
479
+ # "count": 2135,
480
+ # "high": {
481
+ # "v": "74766990000",
482
+ # "e": 6,
483
+ # "f": 74766.99
484
+ # },
485
+ # "low": {
486
+ # "v": "68734020000",
487
+ # "e": 6,
488
+ # "f": 68734.02
489
+ # },
490
+ # "avg": {
491
+ # "v": "72347941430",
492
+ # "e": 6,
493
+ # "f": 72347.94143
494
+ # },
495
+ # "vwap": {
496
+ # "v": "73050064447",
497
+ # "e": 6,
498
+ # "f": 73050.064447
499
+ # },
500
+ # "vol": {
501
+ # "v": "4885361",
502
+ # "e": 8,
503
+ # "f": 0.04885361
504
+ # },
505
+ # "secvol": {
506
+ # "v": "3568759346",
507
+ # "e": 6,
508
+ # "f": 3568.759346
509
+ # },
510
+ # "open": {
511
+ # "v": "68784020000",
512
+ # "e": 6,
513
+ # "f": 68784.02
514
+ # },
515
+ # "close": {
516
+ # "v": "73955570000",
517
+ # "e": 6,
518
+ # "f": 73955.57
519
+ # }
520
+ # }
521
+ # },
522
+ # "request_id": "cbf183e0-7a62-4674-838c-6693031fa240",
523
+ # "result": "success",
524
+ # "time": 0.015463566
525
+ # }
526
+ #
527
+ ticker = self.safe_value(response['data'], 'ticker', {})
528
+ return self.parse_ticker(ticker, market)
529
+
530
+ def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
531
+ timestamp = self.safe_integer_product(ticker, 'time', 1000)
532
+ open = self.parse_amount(self.safe_value(ticker, 'open'))
533
+ high = self.parse_amount(self.safe_value(ticker, 'high'))
534
+ low = self.parse_amount(self.safe_value(ticker, 'low'))
535
+ close = self.parse_amount(self.safe_value(ticker, 'close'))
536
+ avg = self.parse_amount(self.safe_value(ticker, 'avg'))
537
+ vwap = self.parse_amount(self.safe_value(ticker, 'vwap'))
538
+ baseVolume = self.parse_amount(self.safe_value(ticker, 'vol'))
539
+ quoteVolume = self.parse_amount(self.safe_value(ticker, 'secvol'))
540
+ # count = self.safe_integer(ticker, 'count'); not used
541
+ return self.safe_ticker({
542
+ 'symbol': self.safe_symbol(None, market),
543
+ 'timestamp': timestamp,
544
+ 'datetime': self.iso8601(timestamp),
545
+ 'high': high,
546
+ 'low': low,
547
+ 'bid': None,
548
+ 'bidVolume': None,
549
+ 'ask': None,
550
+ 'askVolume': None,
551
+ 'vwap': vwap,
552
+ 'open': open,
553
+ 'close': close,
554
+ 'last': close,
555
+ 'previousClose': None,
556
+ 'change': None,
557
+ 'percentage': None,
558
+ 'average': avg,
559
+ 'baseVolume': baseVolume,
560
+ 'quoteVolume': quoteVolume,
561
+ 'info': ticker,
562
+ }, market)
563
+
564
+ def fetch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
565
+ """
566
+ fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
567
+
568
+ https://docs.google.com/document/d/1ZXzTQYffKE_EglTaKptxGQERRnunuLHEMmar7VC9syM/edit?tab=t.0#heading=h.bqmucewhkpdz
569
+
570
+ :param str symbol: unified symbol of the market to fetch the order book for
571
+ :param int [limit]: the maximum amount of order book entries to return the exchange not supported yet.
572
+ :param dict [params]: extra parameters specific to the exchange API endpoint
573
+ :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
574
+ """
575
+ self.load_markets()
576
+ market = self.market(symbol)
577
+ marketId = market['id']
578
+ request = {
579
+ 'currencyPair': marketId,
580
+ }
581
+ response = self.publicGetMarketCurrencyPairGetDepth(self.extend(request, params))
582
+ # {
583
+ # "data": {
584
+ # "asks": [
585
+ # {
586
+ # "price": {
587
+ # "v": "74941875231",
588
+ # "e": 6,
589
+ # "f": 74941.875231
590
+ # },
591
+ # "amount": {
592
+ # "v": "149",
593
+ # "e": 8,
594
+ # "f": 0.00000149
595
+ # }
596
+ # },
597
+ # {
598
+ # "price": {
599
+ # "v": "75063426037",
600
+ # "e": 6,
601
+ # "f": 75063.426037
602
+ # },
603
+ # "amount": {
604
+ # "v": "335",
605
+ # "e": 8,
606
+ # "f": 0.00000335
607
+ # }
608
+ # }
609
+ # ],
610
+ # "bids": [
611
+ # {
612
+ # "price": {
613
+ # "v": "64518711040",
614
+ # "e": 6,
615
+ # "f": 64518.71104
616
+ # },
617
+ # "amount": {
618
+ # "v": "132",
619
+ # "e": 8,
620
+ # "f": 0.00000132
621
+ # }
622
+ # },
623
+ # {
624
+ # "price": {
625
+ # "v": "64263569273",
626
+ # "e": 6,
627
+ # "f": 64263.569273
628
+ # },
629
+ # "amount": {
630
+ # "v": "210",
631
+ # "e": 8,
632
+ # "f": 0.0000021
633
+ # }
634
+ # }
635
+ # ],
636
+ # "market": "BTC_USDC"
637
+ # },
638
+ # "request_id": "71b7dffc-3120-4e46-a0bb-49ece5aea7e1",
639
+ # "result": "success",
640
+ # "time": 0.000074661
641
+ # }
642
+ data = self.safe_value(response, 'data', {}) # exchange specific v e f params
643
+ timestamp = self.milliseconds() # the exchange does not provide timestamp for self.
644
+ dataBidsLength = len(data['bids'])
645
+ dataAsksLength = len(data['asks'])
646
+ for i in range(0, dataBidsLength):
647
+ data['bids'][i]['price'] = self.parse_amount(data['bids'][i]['price'])
648
+ data['bids'][i]['amount'] = self.parse_amount(data['bids'][i]['amount'])
649
+ for i in range(0, dataAsksLength):
650
+ data['asks'][i]['price'] = self.parse_amount(data['asks'][i]['price'])
651
+ data['asks'][i]['amount'] = self.parse_amount(data['asks'][i]['amount'])
652
+ return self.parse_order_book(data, symbol, timestamp, 'bids', 'asks', 'price', 'amount')
653
+
654
+ def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}):
655
+ """
656
+ fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market, default will return the last 24h period.
657
+
658
+ https://docs.google.com/document/d/1ZXzTQYffKE_EglTaKptxGQERRnunuLHEMmar7VC9syM/edit?tab=t.0#heading=h.w65baeuhxwt8
659
+
660
+ :param str symbol: unified symbol of the market to fetch OHLCV data for
661
+ :param str timeframe: the length of time each candle represents
662
+ :param int [since]: timestamp in ms of the earliest candle to fetch
663
+ :param int [limit]: the maximum amount of candles to fetch
664
+ :param dict [params]: extra parameters specific to the API endpoint
665
+ :returns OHLCV[]: A list of candles ordered, open, high, low, close, volume
666
+ """
667
+ self.load_markets()
668
+ methodName = 'fetchOHLCV'
669
+ paginate = False
670
+ paginate, params = self.handle_option_and_params(params, methodName, 'paginate')
671
+ if paginate:
672
+ return self.fetch_paginated_call_deterministic('fetchOHLCV', symbol, since, limit, timeframe, params, 1000)
673
+ market = self.market(symbol)
674
+ marketId = market['id']
675
+ time_frame = self.safe_string(self.timeframes, timeframe, None)
676
+ request: dict = {
677
+ 'currencyPair': marketId,
678
+ 'interval': time_frame,
679
+ }
680
+ if since is not None:
681
+ request['start'] = int(math.floor(since / 1000))
682
+ until: Int = None
683
+ until, params = self.handle_option_and_params(params, methodName, 'until')
684
+ if until is not None:
685
+ request['end'] = until
686
+ # {
687
+ # "data": {
688
+ # "market": "BTC_USDC",
689
+ # "real_end": 1730970780,
690
+ # "requested_end": 1730970784,
691
+ # "start": 1730884200,
692
+ # "stats": [
693
+ # {
694
+ # "time": 1730884200,
695
+ # "count": 48,
696
+ # "high": {"v": "73898950000", "e": 6, "f": 73898.95},
697
+ # "low": {"v": "73642930000", "e": 6, "f": 73642.93},
698
+ # "open": {"v": "73830990000", "e": 6, "f": 73830.99},
699
+ # "close": {"v": "73682510000", "e": 6, "f": 73682.51},
700
+ # "vol": {"v": "88159", "e": 8, "f": 0.00088159}
701
+ # }
702
+ # ]
703
+ # }
704
+ # }
705
+ # No limit parameter supported by the API
706
+ response = self.publicGetMarketCurrencyPairGetGraph(self.extend(request, params))
707
+ data = self.safe_dict(response, 'data', {})
708
+ ohlcv = self.safe_list(data, 'stats', [])
709
+ return self.parse_ohlcvs(ohlcv, market, timeframe, since, limit)
710
+
711
+ def parse_ohlcv(self, ohlcv, market: Market = None) -> list:
712
+ return [
713
+ self.safe_integer(ohlcv, 'time') * 1000, # timestamp
714
+ self.parse_number(self.parse_amount(self.safe_dict(ohlcv, 'open'))), # open
715
+ self.parse_number(self.parse_amount(self.safe_dict(ohlcv, 'high'))), # high
716
+ self.parse_number(self.parse_amount(self.safe_dict(ohlcv, 'low'))), # low
717
+ self.parse_number(self.parse_amount(self.safe_dict(ohlcv, 'close'))), # close
718
+ self.parse_number(self.parse_amount(self.safe_dict(ohlcv, 'vol'))), # volume
719
+ ]
720
+
721
+ def fetch_currencies(self, params={}) -> Currencies:
722
+ """
723
+ fetches information on all currencies from the exchange, including deposit/withdrawal details and available chains
724
+
725
+ https://docs.google.com/document/d/1ZXzTQYffKE_EglTaKptxGQERRnunuLHEMmar7VC9syM/edit?tab=t.0#heading=h.x65f9s9j74jf
726
+
727
+ :param dict [params]: extra parameters specific to the ellipx API endpoint
728
+ :param str [params.Can_Deposit]: filter currencies by deposit availability, Y for available
729
+ :param number [params.results_per_page]: number of results per page, default 100
730
+ :param str [params._expand]: additional fields to expand in response, default '/Crypto_Token,/Crypto_Chain'
731
+ :returns Promise<Currencies>: An object of currency structures indexed by currency codes
732
+ """
733
+ response = self._restGetCryptoTokenInfo(self.extend({
734
+ 'Can_Deposit': 'Y',
735
+ 'results_per_page': 100,
736
+ '_expand': '/Crypto_Token,/Crypto_Chain',
737
+ }, params))
738
+ currencies = {}
739
+ data = self.safe_value(response, 'data', [])
740
+ for i in range(0, len(data)):
741
+ currency = self.parse_currency(data[i])
742
+ code = self.safe_string(currency, 'code')
743
+ if code is not None:
744
+ currencies[code] = currency
745
+ return currencies
746
+
747
+ def parse_currency(self, currency) -> Currency:
748
+ id = self.safe_string(currency, 'Crypto_Token__')
749
+ token = self.safe_value(currency, 'Crypto_Token', {})
750
+ code = self.safe_currency_code(self.safe_string(token, 'Symbol'))
751
+ name = self.safe_string(token, 'Name')
752
+ active = self.safe_string(currency, 'Status') == 'valid'
753
+ deposit = self.safe_string(currency, 'Can_Deposit') == 'Y'
754
+ withdraw = self.safe_string(currency, 'Status') == 'valid'
755
+ fee = None
756
+ if currency['Withdraw_Fee'] is not None:
757
+ fee = self.parse_number(self.parse_amount(currency['Withdraw_Fee']))
758
+ precision = self.parse_number(self.parse_precision(self.safe_string(token, 'Decimals')))
759
+ minDeposit = None
760
+ if currency['Minimum_Deposit'] is not None:
761
+ minDeposit = self.parse_amount(currency['Minimum_Deposit'])
762
+ minWithdraw = None
763
+ if currency['Minimum_Withdraw'] is not None:
764
+ minWithdraw = self.parse_amount(currency['Minimum_Withdraw'])
765
+ networkId = self.safe_string(currency, 'Crypto_Chain__')
766
+ networkData = self.safe_value(currency, 'Crypto_Chain', {})
767
+ networkCode = self.safe_string(networkData, 'Type', 'default')
768
+ networks = {
769
+ 'string': None,
770
+ 'info': networkCode == {} if 'default' else networkData,
771
+ 'id': networkId or id or '',
772
+ 'network': networkCode,
773
+ 'active': active,
774
+ 'deposit': deposit,
775
+ 'withdraw': withdraw,
776
+ 'fee': fee,
777
+ 'precision': precision,
778
+ 'limits': {
779
+ 'deposit': {
780
+ 'min': minDeposit,
781
+ 'max': None,
782
+ },
783
+ 'withdraw': {
784
+ 'min': minWithdraw,
785
+ 'max': None,
786
+ },
787
+ },
788
+ }
789
+ result: Currency = {
790
+ 'info': currency,
791
+ 'id': id,
792
+ 'code': code,
793
+ 'name': name,
794
+ 'active': active,
795
+ 'deposit': deposit,
796
+ 'withdraw': withdraw,
797
+ 'fee': fee,
798
+ 'precision': precision,
799
+ 'type': None,
800
+ 'limits': {
801
+ 'amount': {
802
+ 'min': None,
803
+ 'max': None,
804
+ },
805
+ 'withdraw': {
806
+ 'min': minWithdraw,
807
+ 'max': None,
808
+ },
809
+ },
810
+ 'networks': networks,
811
+ }
812
+ return result
813
+
814
+ def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
815
+ """
816
+ fetches all completed trades for a particular market/symbol
817
+ :param str symbol: unified market symbol(e.g. 'BTC/USDT')
818
+ :param int [since]: timestamp in ms of the earliest trade to fetch
819
+ :param int [limit]: the maximum amount of trades to fetch
820
+ :param dict [params]: extra parameters specific to the EllipX API endpoint
821
+ :param str [params.before]: get trades before the given trade ID
822
+ :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
823
+ """
824
+ self.load_markets()
825
+ market = self.market(symbol)
826
+ marketId = market['id']
827
+ request = {
828
+ 'currencyPair': marketId,
829
+ }
830
+ # endpoint support before trade id.
831
+ # The actual endpoint URL will be: https://data.ellipx.com/Market/{currencyPair}:getTrades
832
+ # {
833
+ # "id": "BTC_USDC:1731053859:914141972:0",
834
+ # "pair": [
835
+ # "BTC",
836
+ # "USDC"
837
+ # ],
838
+ # "bid": {
839
+ # "id": "mktor-swishf-uv6n-hrzj-63ye-bdqnk33q",
840
+ # "iss": "ellipx:beta",
841
+ # "uniq": "order:1731053859:914141972:0"
842
+ # },
843
+ # "ask": {
844
+ # "id": "mktor-p3ozvt-qurz-gmzo-bf5n-g4rcuy6u",
845
+ # "iss": "ellipx:beta",
846
+ # "uniq": "order:1731053859:874659786:0"
847
+ # },
848
+ # "type": "bid",
849
+ # "amount": {
850
+ # "v": "412",
851
+ # "e": 8,
852
+ # "f": 0.00000412
853
+ # },
854
+ # "price": {
855
+ # "v": "75878090000",
856
+ # "e": 6,
857
+ # "f": 75878.09
858
+ # },
859
+ # "date": "2024-11-08T08:17:39.914141972Z"
860
+ # }
861
+ response = self.publicGetMarketCurrencyPairGetTrades(self.extend(request, params))
862
+ data = self.safe_dict(response, 'data', {})
863
+ trades = self.safe_list(data, 'trades', [])
864
+ return self.parse_trades(trades, market, since, limit)
865
+
866
+ def parse_trade(self, trade, market=None) -> Trade:
867
+ # Format of trade ID: "BTC_USDC:1731053859:914141972:0"
868
+ id = self.safe_string(trade, 'id')
869
+ # fetchTrades and fetchMyTrades return different trade structures
870
+ date = self.safe_dict(trade, 'date')
871
+ timestamp = None
872
+ if date is None:
873
+ timestamp = self.parse8601(self.safe_string(trade, 'date'))
874
+ else:
875
+ timestamp = self.safe_integer(date, 'unixms')
876
+ type = self.safe_string(trade, 'type')
877
+ side = 'buy' if (type == 'bid') else 'sell'
878
+ amount = self.safe_dict(trade, 'amount')
879
+ price = self.safe_dict(trade, 'price')
880
+ amountFloat = self.parse_amount(amount)
881
+ priceFloat = self.parse_amount(price)
882
+ # fetchTrades and fetchMyTrades return different trade structures
883
+ pair = self.safe_list(trade, 'pair')
884
+ marketSymbol = None
885
+ if pair is None:
886
+ symbol = self.safe_string(trade, 'pair')
887
+ base, quote = symbol.split('_')
888
+ marketSymbol = base + '/' + quote
889
+ else:
890
+ marketSymbol = self.safe_string(pair, 0) + '/' + self.safe_string(pair, 1)
891
+ bidOrder = self.safe_dict(trade, 'bid')
892
+ askOrder = self.safe_dict(trade, 'ask')
893
+ isBuy = (side == 'buy')
894
+ orderId = self.safe_string(bidOrder, 'id') if isBuy else self.safe_string(askOrder, 'id')
895
+ return self.safe_trade({
896
+ 'id': id,
897
+ 'info': trade,
898
+ 'timestamp': timestamp,
899
+ 'datetime': self.iso8601(timestamp),
900
+ 'symbol': marketSymbol,
901
+ 'type': None,
902
+ 'side': side,
903
+ 'order': orderId,
904
+ 'takerOrMaker': None,
905
+ 'price': priceFloat,
906
+ 'amount': amountFloat,
907
+ 'cost': None,
908
+ 'fee': None,
909
+ })
910
+
911
+ def fetch_balance(self, params={}) -> Balances:
912
+ """
913
+ query for balance and get the amount of funds available for trading or funds locked in orders
914
+
915
+ https://docs.google.com/document/d/1ZXzTQYffKE_EglTaKptxGQERRnunuLHEMmar7VC9syM/edit?tab=t.0#heading=h.ihrjov144txg
916
+
917
+ :param dict [params]: extra parameters specific to the exchange API endpoint
918
+ :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
919
+ """
920
+ self.load_markets()
921
+ response = self.privateGetUserWallet(params)
922
+ # {
923
+ # "User_Wallet__": "usw-vv7hzo-qel5-gupk-neqi-7f3wz5pq",
924
+ # "User__": "usr-...",
925
+ # "Realm__": "usrr-cb3c7n-qvxv-fdrb-uc2q-gpja2foi",
926
+ # "Unit__": "unit-aebkye-u35b-e5zm-zt22-2qvwhsqa",
927
+ # "Balance": {
928
+ # "value": "0.00006394",
929
+ # "value_int": "6394",
930
+ # "value_disp": "0.00006394",
931
+ # "value_xint": {
932
+ # "v": "6394",
933
+ # "e": 8,
934
+ # "f": 0.00006394
935
+ # },
936
+ # "display": "0.00006394BTC",
937
+ # "display_short": "0.00006394BTC",
938
+ # "currency": "BTC",
939
+ # "unit": "BTC",
940
+ # "has_vat": False,
941
+ # "tax_profile": null
942
+ # },
943
+ # "Balance_Date": {
944
+ # "unix": 1731128270,
945
+ # "us": 426208,
946
+ # "iso": "2024-11-09 04:57:50.426208",
947
+ # "tz": "UTC",
948
+ # "full": "1731128270426208",
949
+ # "unixms": "1731128270426"
950
+ # },
951
+ # "Liabilities": {
952
+ # "value": "0.00000000",
953
+ # "value_int": "0",
954
+ # "value_disp": "0.00000000",
955
+ # "value_xint": {
956
+ # "v": "0",
957
+ # "e": 8,
958
+ # "f": 0
959
+ # },
960
+ # "display": "0.00000000BTC",
961
+ # "display_short": "0.00000000BTC",
962
+ # "currency": "BTC",
963
+ # "unit": "BTC",
964
+ # "has_vat": False,
965
+ # "tax_profile": null
966
+ # },
967
+ # "Index": "5",
968
+ # "Backend": "virtual",
969
+ # "Disable_Limits": "N",
970
+ # "Unencumbered_Balance": {
971
+ # "value": "0.00006394",
972
+ # "value_int": "6394",
973
+ # "value_disp": "0.00006394",
974
+ # "value_xint": {
975
+ # "v": "6394",
976
+ # "e": 8,
977
+ # "f": 0.00006394
978
+ # },
979
+ # "display": "0.00006394BTC",
980
+ # "display_short": "0.00006394BTC",
981
+ # "currency": "BTC",
982
+ # "unit": "BTC",
983
+ # "has_vat": False,
984
+ # "tax_profile": null
985
+ # }
986
+ # }
987
+ result: dict = {
988
+ 'info': response,
989
+ 'timestamp': None,
990
+ 'datetime': None,
991
+ }
992
+ dataArray = self.safe_list(response, 'data', [])
993
+ # Use first item's timestamp if available
994
+ dataArrayLength = len(dataArray)
995
+ if dataArrayLength > 0:
996
+ firstItem = dataArray[0]
997
+ balanceDate = self.safe_dict(firstItem, 'Balance_Date', {})
998
+ result['timestamp'] = self.safe_integer(balanceDate, 'unixms')
999
+ result['datetime'] = self.iso8601(result['timestamp'])
1000
+ # Process each balance entry
1001
+ for i in range(0, len(dataArray)):
1002
+ entry = dataArray[i]
1003
+ balance = self.safe_dict(entry, 'Balance', {})
1004
+ currency = self.safe_string(balance, 'currency')
1005
+ if currency is not None:
1006
+ account = {
1007
+ 'free': self.parse_amount(entry['Unencumbered_Balance']['value_xint']),
1008
+ 'used': self.parse_amount(entry['Liabilities']['value_xint']),
1009
+ 'total': self.parse_amount(balance['value_xint']),
1010
+ }
1011
+ result[currency] = account
1012
+ return self.safe_balance(result)
1013
+
1014
+ def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
1015
+ """
1016
+ create a new order in a market
1017
+
1018
+ https://docs.google.com/document/d/1ZXzTQYffKE_EglTaKptxGQERRnunuLHEMmar7VC9syM/edit?tab=t.0#heading=h.yzfak2n2bwpo
1019
+
1020
+ :param str symbol: unified market symbol(e.g. 'BTC/USDT')
1021
+ :param str type: order type - the exchange automatically sets type to 'limit' if price defined, 'market' if None
1022
+ :param str side: 'buy' or 'sell'
1023
+ :param float [amount]: amount of base currency to trade(can be None if using Spend_Limit)
1024
+ :param float [price]: price per unit of base currency for limit orders
1025
+ :param dict [params]: extra parameters specific to the EllipX API endpoint
1026
+ :param float [params.cost]: maximum amount to spend in quote currency(required for market orders if amount None)
1027
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1028
+ """
1029
+ self.load_markets()
1030
+ market = self.market(symbol)
1031
+ # the exchange automatically sets the type to 'limit' if the price is defined and to 'market' if it is not
1032
+ marketId = market['id']
1033
+ orderType = 'bid'
1034
+ if side == 'buy':
1035
+ orderType = 'bid'
1036
+ else:
1037
+ orderType = 'ask'
1038
+ request: Any = {
1039
+ 'currencyPair': marketId,
1040
+ 'Type': orderType,
1041
+ }
1042
+ if amount is not None:
1043
+ request['Amount'] = self.amount_to_precision(symbol, amount)
1044
+ if price is not None:
1045
+ request['Price'] = self.price_to_precision(symbol, price)
1046
+ cost = self.safe_string(params, 'cost')
1047
+ if cost is not None:
1048
+ params = self.omit(params, 'cost')
1049
+ request['Spend_Limit'] = self.price_to_precision(symbol, cost)
1050
+ response = self.privatePostMarketCurrencyPairOrder(self.extend(request, params))
1051
+ # {
1052
+ # "result": "success",
1053
+ # "data": {
1054
+ # "Market_Order__": "mktor-x2grmu-zwo5-fyxc-4gue-vd4ouvsa",
1055
+ # "Market__": "mkt-lrnp2e-eaor-eobj-ua73-75j6sjxe",
1056
+ # "User__": "usr-...",
1057
+ # "Uniq": "order:1728719021:583795548:0",
1058
+ # "Type": "bid",
1059
+ # "Status": "pending",
1060
+ # "Flags": {},
1061
+ # "Amount": {
1062
+ # "v": "100000000",
1063
+ # "e": 8,
1064
+ # "f": 1
1065
+ # },
1066
+ # "Price": null,
1067
+ # "Spend_Limit": {
1068
+ # "v": "1000000",
1069
+ # "e": 6,
1070
+ # "f": 1
1071
+ # },
1072
+ # "Executed": {
1073
+ # "v": "0",
1074
+ # "e": 0,
1075
+ # "f": 0
1076
+ # },
1077
+ # "Secured": {
1078
+ # "v": "1000000",
1079
+ # "e": 6,
1080
+ # "f": 1
1081
+ # },
1082
+ # "Version": "0",
1083
+ # "Created": {
1084
+ # "unix": 1728719020,
1085
+ # "us": 315195,
1086
+ # "iso": "2024-10-12 07:43:40.315195",
1087
+ # "tz": "UTC",
1088
+ # "full": "1728719020315195",
1089
+ # "unixms": "1728719020315"
1090
+ # },
1091
+ # "Updated": {
1092
+ # "unix": 1728719020,
1093
+ # "us": 315195,
1094
+ # "iso": "2024-10-12 07:43:40.315195",
1095
+ # "tz": "UTC",
1096
+ # "full": "1728719020315195",
1097
+ # "unixms": "1728719020315"
1098
+ # }
1099
+ # }
1100
+ # }
1101
+ order = self.safe_dict(response, 'data', {})
1102
+ return self.parse_order(order, market)
1103
+
1104
+ def fetch_order(self, id: str, symbol: Str = None, params={}) -> Order:
1105
+ """
1106
+ fetches information on an order made by the user
1107
+ :param str id: the order ID by createOrder or fetchOrders
1108
+ :param str|None symbol: not used by ellipx.fetchOrder
1109
+ :param dict [params]: extra parameters specific to the EllipX API endpoint
1110
+ :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1111
+ """
1112
+ self.load_markets()
1113
+ request = {
1114
+ 'orderUuid': id,
1115
+ }
1116
+ response = self.privateGetMarketOrderOrderUuid(self.extend(request, params))
1117
+ data = self.safe_dict(response, 'data', {})
1118
+ return self.parse_order(data, None)
1119
+
1120
+ def fetch_orders_by_status(self, status, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1121
+ """
1122
+ fetches a list of orders placed on the exchange
1123
+
1124
+ https://docs.google.com/document/d/1ZXzTQYffKE_EglTaKptxGQERRnunuLHEMmar7VC9syM/edit?tab=t.0#heading=h.5z2nh2b5s81n
1125
+
1126
+ :param str status: 'open' or 'closed', omit for all orders
1127
+ :param str symbol: unified market symbol
1128
+ :param int [since]: timestamp in ms of the earliest order
1129
+ :param int [limit]: the maximum amount of orders to fetch
1130
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1131
+ :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1132
+ """
1133
+ self.load_markets()
1134
+ market = None
1135
+ request: Any = {}
1136
+ if symbol is not None:
1137
+ market = self.market(symbol)
1138
+ marketId = market['id']
1139
+ request['currencyPair'] = marketId
1140
+ if status is not None:
1141
+ request['Status'] = status
1142
+ response = self.privateGetMarketCurrencyPairOrder(self.extend(request, params))
1143
+ # {
1144
+ # "result": "success",
1145
+ # "data": [
1146
+ # {
1147
+ # "Market_Order__": "mktor-aglvd2-iy5v-enbj-nwrb-scqsnosa",
1148
+ # "Market__": "mkt-lrnp2e-eaor-eobj-ua73-75j6sjxe",
1149
+ # "User__": "usr-...",
1150
+ # "Uniq": "order:1728712511:964332600:0",
1151
+ # "Type": "ask",
1152
+ # "Status": "open",
1153
+ # "Flags": {},
1154
+ # "Amount": {
1155
+ # "v": "1",
1156
+ # "e": 8,
1157
+ # "f": 1.0e-8
1158
+ # },
1159
+ # "Price": {
1160
+ # "v": "63041306872",
1161
+ # "e": 6,
1162
+ # "f": 63041.306872
1163
+ # },
1164
+ # "Spend_Limit": null,
1165
+ # "Executed": {
1166
+ # "v": "892",
1167
+ # "e": 8,
1168
+ # "f": 8.92e-6
1169
+ # },
1170
+ # "Secured": null,
1171
+ # "Version": "3",
1172
+ # "Created": {
1173
+ # "unix": 1728712510,
1174
+ # "us": 669096,
1175
+ # "iso": "2024-10-12 05:55:10.669096",
1176
+ # "tz": "UTC",
1177
+ # "full": "1728712510669096",
1178
+ # "unixms": "1728712510669"
1179
+ # },
1180
+ # "Updated": {
1181
+ # "unix": 1728712510,
1182
+ # "us": 669096,
1183
+ # "iso": "2024-10-12 05:55:10.669096",
1184
+ # "tz": "UTC",
1185
+ # "full": "1728712510669096",
1186
+ # "unixms": "1728712510669"
1187
+ # }
1188
+ # }
1189
+ # ],
1190
+ # "paging": {
1191
+ # "page_no": 1,
1192
+ # "count": "1",
1193
+ # "page_max": 1,
1194
+ # "results_per_page": 20
1195
+ # }
1196
+ # }
1197
+ data = self.safe_value(response, 'data', [])
1198
+ return self.parse_orders(data, market, since, limit)
1199
+
1200
+ def fetch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1201
+ """
1202
+ fetches information on multiple orders made by the user
1203
+
1204
+ https://docs.google.com/document/d/1ZXzTQYffKE_EglTaKptxGQERRnunuLHEMmar7VC9syM/edit?tab=t.0#heading=h.5z2nh2b5s81n
1205
+
1206
+ :param str symbol: unified market symbol of the market orders were made in
1207
+ :param int|None since: timestamp in ms of the earliest order
1208
+ :param int|None limit: the maximum amount of orders to fetch
1209
+ :param dict params: extra parameters specific to the exchange API endpoint
1210
+ :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1211
+ """
1212
+ if symbol is None:
1213
+ raise ArgumentsRequired(self.id + ' fetchOrders requires a symbol parameter')
1214
+ return self.fetch_orders_by_status(None, symbol, since, limit, params)
1215
+
1216
+ def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1217
+ """
1218
+ fetches information on open orders made by the user
1219
+
1220
+ https://docs.google.com/document/d/1ZXzTQYffKE_EglTaKptxGQERRnunuLHEMmar7VC9syM/edit?tab=t.0#heading=h.5z2nh2b5s81n
1221
+
1222
+ :param str symbol: unified market symbol of the market orders were made in
1223
+ :param int|None since: timestamp in ms of the earliest order
1224
+ :param int|None limit: the maximum amount of orders to fetch
1225
+ :param dict params: extra parameters specific to the exchange API endpoint
1226
+ :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1227
+ """
1228
+ if symbol is None:
1229
+ raise ArgumentsRequired(self.id + ' fetchOpenOrders requires a symbol parameter')
1230
+ return self.fetch_orders_by_status('open', symbol, since, limit, params)
1231
+
1232
+ def parse_order(self, order, market=None) -> Order:
1233
+ id = self.safe_string(order, 'Market_Order__')
1234
+ timestamp = self.safe_integer(self.safe_dict(order, 'Created'), 'unixms')
1235
+ orderType = self.safe_string(order, 'Type')
1236
+ side = 'sell'
1237
+ if orderType == 'bid':
1238
+ side = 'buy'
1239
+ status = self.parse_order_status(self.safe_string(order, 'Status'))
1240
+ amount = self.parse_number(self.parse_amount(self.safe_dict(order, 'Amount')))
1241
+ price = self.parse_number(self.parse_amount(self.safe_dict(order, 'Price')))
1242
+ type = 'market' if (price is None) else 'limit'
1243
+ executed = self.parse_number(self.parse_amount(self.safe_dict(order, 'Executed')))
1244
+ filled = executed
1245
+ remaining = self.parse_number(self.parse_amount(self.safe_dict(order, 'Secured')))
1246
+ cost = self.parse_number(self.parse_amount(self.safe_dict(order, 'Total_Spent')))
1247
+ symbol = market['symbol'] if market else None
1248
+ clientOrderId = None
1249
+ timeInForce = 'GTC' # default to Good Till Cancelled
1250
+ postOnly = False
1251
+ updated = self.safe_dict(order, 'Updated', {})
1252
+ lastTradeTimestamp = self.safe_integer(updated, 'unixms', None)
1253
+ return self.safe_order({
1254
+ 'id': id,
1255
+ 'clientOrderId': clientOrderId,
1256
+ 'info': order,
1257
+ 'timestamp': timestamp,
1258
+ 'datetime': self.iso8601(timestamp),
1259
+ 'lastTradeTimestamp': lastTradeTimestamp,
1260
+ 'status': self.parse_order_status(status),
1261
+ 'symbol': symbol,
1262
+ 'type': type,
1263
+ 'timeInForce': timeInForce,
1264
+ 'postOnly': postOnly,
1265
+ 'side': side,
1266
+ 'price': price,
1267
+ 'triggerPrice': None,
1268
+ 'average': None,
1269
+ 'cost': cost,
1270
+ 'amount': amount,
1271
+ 'filled': filled,
1272
+ 'remaining': remaining,
1273
+ 'fee': None,
1274
+ 'trades': None,
1275
+ }, market)
1276
+
1277
+ def cancel_order(self, id: str, symbol: Str = None, params={}) -> Order:
1278
+ """
1279
+ Cancels an open order on the exchange
1280
+
1281
+ https://docs.google.com/document/d/1ZXzTQYffKE_EglTaKptxGQERRnunuLHEMmar7VC9syM/edit?tab=t.0#heading=h.f1qu1pb1rebn
1282
+
1283
+ :param str id: - The order ID to cancel(format: mktor-xxxxx-xxxx-xxxx-xxxx-xxxxxxxx)
1284
+ :param str [symbol]: - ellipx.cancelOrder does not use the symbol parameter
1285
+ :param dict [params]: - Extra parameters specific to the exchange API
1286
+ :returns Promise<dict>: A Promise that resolves to the canceled order info
1287
+ """
1288
+ self.load_markets()
1289
+ request = {
1290
+ 'orderUuid': id,
1291
+ }
1292
+ response = self.privateDeleteMarketOrderOrderUuid(self.extend(request, params))
1293
+ # {
1294
+ # result: "success",
1295
+ # request_id: "887dba33-d11b-43f0-8034-dd7890882cc5",
1296
+ # time: "0.8975801467895508",
1297
+ # data: True,
1298
+ # access: {
1299
+ # "mktor-rf5k5b-5fhf-dmde-wxqj-3y23jeii": {
1300
+ # required: "A",
1301
+ # available: "O",
1302
+ # },
1303
+ # },
1304
+ # }
1305
+ # self endpoint always returns True and a warning message if the order cancelled before.
1306
+ warningResponse = self.safe_value(response, 'warning', None)
1307
+ statusResponse = self.safe_bool(response, 'data')
1308
+ status = 'canceled'
1309
+ if statusResponse is not True or warningResponse is not None:
1310
+ status = 'closed'
1311
+ return self.safe_order({
1312
+ 'id': id,
1313
+ 'clientOrderId': None,
1314
+ 'info': self.json(response), # original response
1315
+ 'timestamp': None,
1316
+ 'datetime': None,
1317
+ 'lastTradeTimestamp': None,
1318
+ 'status': status,
1319
+ 'symbol': None,
1320
+ 'type': None,
1321
+ 'timeInForce': None,
1322
+ 'postOnly': None,
1323
+ 'side': None,
1324
+ 'price': None,
1325
+ 'triggerPrice': None,
1326
+ 'average': None,
1327
+ 'cost': None,
1328
+ 'amount': None,
1329
+ 'filled': None,
1330
+ 'remaining': None,
1331
+ 'fee': None,
1332
+ 'trades': None,
1333
+ }, None)
1334
+
1335
+ def fetch_order_trades(self, id: str, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
1336
+ """
1337
+ fetch all the trades made from a single order
1338
+ :param str id: order id
1339
+ :param str symbol: unified market symbol
1340
+ :param int [since]: the earliest time in ms to fetch trades for
1341
+ :param int [limit]: the maximum number of trades to retrieve
1342
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1343
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
1344
+ """
1345
+ if symbol is None:
1346
+ raise ArgumentsRequired('fetchMyTrades requires a symbol parameter')
1347
+ self.load_markets()
1348
+ market = self.market(symbol)
1349
+ currencyPair = market['id']
1350
+ request = {
1351
+ 'Market_Order__': id,
1352
+ 'currencyPair': currencyPair,
1353
+ }
1354
+ response = self.privateGetMarketCurrencyPairTrade(self.extend(request, params))
1355
+ # {
1356
+ # "result": "success",
1357
+ # "request_id": "fc5be99d-d085-46f8-9228-e46d0996f112",
1358
+ # "time": 0.030913114547729492,
1359
+ # "data": [
1360
+ # {
1361
+ # "id": "DOGE_USDC:1731505789:911642994:0",
1362
+ # "pair": "DOGE_USDC",
1363
+ # "bid": {
1364
+ # "id": "mktor-xb3ne5-emm5-fx7e-xggk-fyfoiye4"
1365
+ # },
1366
+ # "ask": {
1367
+ # "id": "mktor-oxmac4-mtkf-gi3o-mamg-u2cboqe4"
1368
+ # },
1369
+ # "type": "bid",
1370
+ # "amount": {
1371
+ # "v": "334609419",
1372
+ # "e": 8,
1373
+ # "f": 3.34609419
1374
+ # },
1375
+ # "price": {
1376
+ # "v": "410673",
1377
+ # "e": 6,
1378
+ # "f": 0.410673
1379
+ # },
1380
+ # "date": {
1381
+ # "unix": 1731505789,
1382
+ # "us": 911642,
1383
+ # "iso": "2024-11-13 13:49:49.911642",
1384
+ # "tz": "UTC",
1385
+ # "full": "1731505789911642",
1386
+ # "unixms": "1731505789911"
1387
+ # }
1388
+ # },
1389
+ # {
1390
+ # "id": "DOGE_USDC:1731505789:911642994:4",
1391
+ # "pair": "DOGE_USDC",
1392
+ # "bid": {
1393
+ # "id": "mktor-xb3ne5-emm5-fx7e-xggk-fyfoiye4"
1394
+ # },
1395
+ # "ask": {
1396
+ # "id": "mktor-cmtztk-3z3n-gupp-uqdg-74g4wjfq"
1397
+ # },
1398
+ # "type": "bid",
1399
+ # "amount": {
1400
+ # "v": "145453950",
1401
+ # "e": 8,
1402
+ # "f": 1.4545395
1403
+ # },
1404
+ # "price": {
1405
+ # "v": "412589",
1406
+ # "e": 6,
1407
+ # "f": 0.412589
1408
+ # },
1409
+ # "date": {
1410
+ # "unix": 1731505789,
1411
+ # "us": 911642,
1412
+ # "iso": "2024-11-13 13:49:49.911642",
1413
+ # "tz": "UTC",
1414
+ # "full": "1731505789911642",
1415
+ # "unixms": "1731505789911"
1416
+ # }
1417
+ # },
1418
+ # {
1419
+ # "id": "DOGE_USDC:1731505789:911642994:2",
1420
+ # "pair": "DOGE_USDC",
1421
+ # "bid": {
1422
+ # "id": "mktor-xb3ne5-emm5-fx7e-xggk-fyfoiye4"
1423
+ # },
1424
+ # "ask": {
1425
+ # "id": "mktor-6tyslh-b33b-flnm-2ata-acjkco4y"
1426
+ # },
1427
+ # "type": "bid",
1428
+ # "amount": {
1429
+ # "v": "587627076",
1430
+ # "e": 8,
1431
+ # "f": 5.87627076
1432
+ # },
1433
+ # "price": {
1434
+ # "v": "411005",
1435
+ # "e": 6,
1436
+ # "f": 0.411005
1437
+ # },
1438
+ # "date": {
1439
+ # "unix": 1731505789,
1440
+ # "us": 911642,
1441
+ # "iso": "2024-11-13 13:49:49.911642",
1442
+ # "tz": "UTC",
1443
+ # "full": "1731505789911642",
1444
+ # "unixms": "1731505789911"
1445
+ # }
1446
+ # },
1447
+ # {
1448
+ # "id": "DOGE_USDC:1731505789:911642994:1",
1449
+ # "pair": "DOGE_USDC",
1450
+ # "bid": {
1451
+ # "id": "mktor-xb3ne5-emm5-fx7e-xggk-fyfoiye4"
1452
+ # },
1453
+ # "ask": {
1454
+ # "id": "mktor-ihpjlj-5ufj-dm5l-fmud-oftkqcgu"
1455
+ # },
1456
+ # "type": "bid",
1457
+ # "amount": {
1458
+ # "v": "475845734",
1459
+ # "e": 8,
1460
+ # "f": 4.75845734
1461
+ # },
1462
+ # "price": {
1463
+ # "v": "410830",
1464
+ # "e": 6,
1465
+ # "f": 0.41083
1466
+ # },
1467
+ # "date": {
1468
+ # "unix": 1731505789,
1469
+ # "us": 911642,
1470
+ # "iso": "2024-11-13 13:49:49.911642",
1471
+ # "tz": "UTC",
1472
+ # "full": "1731505789911642",
1473
+ # "unixms": "1731505789911"
1474
+ # }
1475
+ # },
1476
+ # {
1477
+ # "id": "DOGE_USDC:1731505789:911642994:3",
1478
+ # "pair": "DOGE_USDC",
1479
+ # "bid": {
1480
+ # "id": "mktor-xb3ne5-emm5-fx7e-xggk-fyfoiye4"
1481
+ # },
1482
+ # "ask": {
1483
+ # "id": "mktor-d2uyb3-nzsj-aevn-dikr-tq3sxhre"
1484
+ # },
1485
+ # "type": "bid",
1486
+ # "amount": {
1487
+ # "v": "641013461",
1488
+ # "e": 8,
1489
+ # "f": 6.41013461
1490
+ # },
1491
+ # "price": {
1492
+ # "v": "411846",
1493
+ # "e": 6,
1494
+ # "f": 0.411846
1495
+ # },
1496
+ # "date": {
1497
+ # "unix": 1731505789,
1498
+ # "us": 911642,
1499
+ # "iso": "2024-11-13 13:49:49.911642",
1500
+ # "tz": "UTC",
1501
+ # "full": "1731505789911642",
1502
+ # "unixms": "1731505789911"
1503
+ # }
1504
+ # }
1505
+ # ],
1506
+ # "access": {
1507
+ # "mkt-xrkg5l-akjz-cxxl-3a2e-mul5gfo4": {
1508
+ # "required": "r",
1509
+ # "available": "?"
1510
+ # },
1511
+ # "mktor-xb3ne5-emm5-fx7e-xggk-fyfoiye4": {
1512
+ # "required": "R",
1513
+ # "available": "O"
1514
+ # }
1515
+ # },
1516
+ # "paging": {
1517
+ # "page_no": 1,
1518
+ # "count": "5",
1519
+ # "page_max": 1,
1520
+ # "results_per_page": 20
1521
+ # }
1522
+ # }
1523
+ data = self.safe_list(response, 'data')
1524
+ return self.parse_trades(data, market, since, limit)
1525
+
1526
+ def fetch_deposit_address(self, code: str, params={}) -> DepositAddress:
1527
+ """
1528
+ fetches a crypto deposit address for a specific currency
1529
+
1530
+ https://docs.google.com/document/d/1ZXzTQYffKE_EglTaKptxGQERRnunuLHEMmar7VC9syM/edit?tab=t.0#heading=h.k7qe5aricayh
1531
+
1532
+ :param str code: unified currency code(e.g. "BTC", "ETH", "USDT")
1533
+ :param dict [params]: extra parameters specific to the EllipX API endpoint
1534
+ :returns dict: an address structure {
1535
+ 'currency': string, # unified currency code
1536
+ 'address': string, # the address for deposits
1537
+ 'tag': string|None, # tag/memo for deposits if needed
1538
+ 'network': object, # network object from currency info
1539
+ 'info': object # raw response from exchange
1540
+ }
1541
+ :throws ExchangeError if: currency does not support deposits
1542
+ """
1543
+ self.load_markets()
1544
+ currency = self.currency(code)
1545
+ network = self.safe_value(currency['info'], 'Crypto_Chain', None)
1546
+ request = {
1547
+ 'Crypto_Token__': self.safe_string(network, 'Crypto_Token__'),
1548
+ 'Crypto_Chain__': self.safe_string(network, 'Crypto_Chain__'),
1549
+ }
1550
+ response = self.privatePostCryptoAddressFetch(self.extend(request, params))
1551
+ data = self.safe_value(response, 'data', {})
1552
+ address = self.safe_string(data, 'Address')
1553
+ tag = self.safe_string(data, 'memo')
1554
+ self.check_address(address)
1555
+ return {
1556
+ 'currency': code,
1557
+ 'address': address,
1558
+ 'tag': tag,
1559
+ 'network': network,
1560
+ 'info': response,
1561
+ }
1562
+
1563
+ def fetch_trading_fee(self, symbol: str = None, params={}) -> TradingFeeInterface:
1564
+ """
1565
+ Fetches the current trading fees(maker and taker) applicable to the user.
1566
+
1567
+ https://docs.google.com/document/d/1ZXzTQYffKE_EglTaKptxGQERRnunuLHEMmar7VC9syM/edit?tab=t.0#heading=h.kki5jay2c8it
1568
+
1569
+ :param str [symbol]: Not used by EllipX are not symbol-specific.
1570
+ :param dict [params]: Extra parameters specific to the EllipX API endpoint.
1571
+ :returns Promise<dict>: A promise resolving to a unified trading fee structure:
1572
+ {
1573
+ 'info': object, # the raw response from the exchange
1574
+ 'symbol': None, # symbol is not used for self exchange
1575
+ 'maker': number, # maker fee rate in decimal form
1576
+ 'taker': number, # taker fee rate in decimal form
1577
+ 'percentage': True, # indicates fees are in percentage
1578
+ 'tierBased': False, # indicates fees do not vary by volume tiers
1579
+ }
1580
+ """
1581
+ self.load_markets()
1582
+ response = self.privateGetMarketTradeFeeQuery(params)
1583
+ #
1584
+ # Example response:
1585
+ # {
1586
+ # "result": "success",
1587
+ # "data": {
1588
+ # "maker": 15.0, # in basis points
1589
+ # "taker": 25.0, # in basis points
1590
+ # "volume": 123456.78,
1591
+ # "promo": {
1592
+ # # promotional discounts if any
1593
+ # }
1594
+ # }
1595
+ # }
1596
+ #
1597
+ data = self.safe_value(response, 'data', {})
1598
+ maker = self.safe_number(data, 'maker') # in basis points
1599
+ taker = self.safe_number(data, 'taker') # in basis points
1600
+ makerFee = maker / 10000 if (maker is not None) else None
1601
+ takerFee = taker / 10000 if (taker is not None) else None
1602
+ return {
1603
+ 'info': response,
1604
+ 'symbol': None, # the exchange only have separate fees for stablecoin pairs
1605
+ 'maker': makerFee,
1606
+ 'taker': takerFee,
1607
+ 'percentage': True, # fees are expressed in percentages
1608
+ 'tierBased': True, # fees can vary based on volume tiers
1609
+ }
1610
+
1611
+ def withdraw(self, code: str, amount: float, address: str, tag=None, params={}) -> Transaction:
1612
+ """
1613
+ Make a withdrawal request
1614
+
1615
+ https://docs.google.com/document/d/1ZXzTQYffKE_EglTaKptxGQERRnunuLHEMmar7VC9syM/edit?tab=t.0#heading=h.zegupoa8g4t9
1616
+
1617
+ :param str code: Currency code
1618
+ :param number amount: Amount to withdraw
1619
+ :param str address: Destination wallet address
1620
+ :param str [tag]: Additional tag/memo for currencies that require it
1621
+ :param dict params: Extra parameters specific to the EllipX API endpoint(Crypto_Chain__, Unit__)
1622
+ :returns dict: a `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
1623
+ """
1624
+ self.check_address(address)
1625
+ self.load_markets()
1626
+ currency = self.currency(code)
1627
+ networks = self.safe_value(currency, 'networks')
1628
+ if networks is None:
1629
+ raise NotSupported(self.id + ' withdraw() for ' + code + ' is not supported')
1630
+ chainsResponse = self.privateGetUnitCurrency({'currency': currency['code']}) # fetch Unit__ params for currency
1631
+ chainsData = self.safe_value(chainsResponse, 'data', [])
1632
+ unit = self.safe_string(chainsData, 'Unit__')
1633
+ # check params again and omit params
1634
+ self.omit(params, 'Unit__')
1635
+ self.omit(params, 'Crypto_Chain__')
1636
+ amountString = str(amount)
1637
+ request = {
1638
+ 'Unit__': unit,
1639
+ 'amount': amountString,
1640
+ 'address': address,
1641
+ 'Crypto_Chain__': networks['id'],
1642
+ }
1643
+ if tag is not None:
1644
+ request['memo'] = tag
1645
+ response = self.privatePostCryptoDisbursementWithdraw(self.extend(request, params))
1646
+ # {
1647
+ # Crypto_Disbursement__: "crdsb-4pw3kg-ipn5-amvb-da4n-6xncy4r4",
1648
+ # Crypto_Token__: "crtok-dnehz4-wbgv-bunf-iyd3-m7gtsz2q",
1649
+ # Crypto_Chain__: "chain-kjfvwn-l2xn-eclc-ul5d-mb6fu5hm",
1650
+ # User__: "usr-5oint6-ozpr-alfp-2wxi-zgbm4osy",
1651
+ # Value: {
1652
+ # v: "1000000000",
1653
+ # e: "8",
1654
+ # f: "10",
1655
+ # },
1656
+ # Value_USD: "4.08723",
1657
+ # Address: "D6z62LUwyNBi3QbPkzW8C4m7VDAgu9wb2Z",
1658
+ # Status: "pending",
1659
+ # Transaction: null,
1660
+ # Requested: {
1661
+ # unix: "1731570982",
1662
+ # us: "203569",
1663
+ # iso: "2024-11-14 07:56:22.203569",
1664
+ # tz: "UTC",
1665
+ # full: "1731570982203569",
1666
+ # unixms: "1731570982203",
1667
+ # },
1668
+ # Scheduled: null,
1669
+ # Processed: null,
1670
+ # Amount: {
1671
+ # value: "10.00000000",
1672
+ # value_int: "1000000000",
1673
+ # value_disp: "10.00000000",
1674
+ # value_xint: {
1675
+ # v: "1000000000",
1676
+ # e: "8",
1677
+ # f: "10",
1678
+ # },
1679
+ # display: "10.00000000DOGE",
1680
+ # display_short: "10.00000000DOGE",
1681
+ # currency: "DOGE",
1682
+ # unit: "DOGE",
1683
+ # has_vat: False,
1684
+ # tax_profile: null,
1685
+ # raw: {
1686
+ # value: "10.00000000",
1687
+ # value_int: "1000000000",
1688
+ # value_disp: "10.00000000",
1689
+ # value_xint: {
1690
+ # v: "1000000000",
1691
+ # e: "8",
1692
+ # f: "10",
1693
+ # },
1694
+ # display: "10.00000000DOGE",
1695
+ # display_short: "10.00000000DOGE",
1696
+ # currency: "DOGE",
1697
+ # unit: "DOGE",
1698
+ # has_vat: False,
1699
+ # tax_profile: null,
1700
+ # },
1701
+ # tax: {
1702
+ # value: "10.00000000",
1703
+ # value_int: "1000000000",
1704
+ # value_disp: "10.00000000",
1705
+ # value_xint: {
1706
+ # v: "1000000000",
1707
+ # e: "8",
1708
+ # f: "10",
1709
+ # },
1710
+ # display: "10.00000000DOGE",
1711
+ # display_short: "10.00000000DOGE",
1712
+ # currency: "DOGE",
1713
+ # unit: "DOGE",
1714
+ # has_vat: True,
1715
+ # tax_profile: null,
1716
+ # },
1717
+ # tax_only: {
1718
+ # value: "0.000",
1719
+ # value_int: "0",
1720
+ # value_disp: "0",
1721
+ # value_xint: {
1722
+ # v: "0",
1723
+ # e: "3",
1724
+ # f: "0",
1725
+ # },
1726
+ # display: "¥0",
1727
+ # display_short: "¥0",
1728
+ # currency: "JPY",
1729
+ # unit: "JPY",
1730
+ # has_vat: False,
1731
+ # tax_profile: null,
1732
+ # },
1733
+ # tax_rate: "0",
1734
+ # },
1735
+ # }
1736
+ data = self.safe_dict(response, 'data')
1737
+ amountResponse = self.safe_dict(data, 'Amount')
1738
+ requested = self.safe_dict(data, 'Requested')
1739
+ processed = self.safe_dict(data, 'Processed')
1740
+ withdrawId = self.safe_string(data, 'Crypto_Disbursement__')
1741
+ timestamp = self.safe_integer(requested, 'unixms')
1742
+ return {
1743
+ 'info': response,
1744
+ 'id': withdrawId,
1745
+ 'txid': None,
1746
+ 'timestamp': timestamp,
1747
+ 'datetime': self.iso8601(timestamp),
1748
+ 'network': self.safe_string(data, 'Crypto_Chain__'),
1749
+ 'address': self.safe_string(data, 'Address'),
1750
+ 'addressTo': self.safe_string(data, 'Address'),
1751
+ 'addressFrom': None,
1752
+ 'tag': tag,
1753
+ 'tagTo': tag,
1754
+ 'tagFrom': None,
1755
+ 'type': 'withdrawal',
1756
+ 'amount': self.safe_number(amountResponse, 'value'),
1757
+ 'currency': code,
1758
+ 'status': self.parse_transaction_status(self.safe_string(data, 'Status')),
1759
+ 'updated': self.safe_timestamp(processed, 'unix'),
1760
+ 'internal': False,
1761
+ 'comment': None,
1762
+ 'fee': {
1763
+ 'currency': code,
1764
+ 'cost': None, # Fee information not provided in response
1765
+ 'rate': None,
1766
+ },
1767
+ }
1768
+
1769
+ def parse_transaction_status(self, status: str) -> str:
1770
+ statuses = {
1771
+ 'pending': 'pending',
1772
+ 'completed': 'ok',
1773
+ 'failed': 'failed',
1774
+ 'cancelled': 'canceled',
1775
+ }
1776
+ return self.safe_string(statuses, status, status)
1777
+
1778
+ def parse_order_status(self, status):
1779
+ statuses = {
1780
+ 'pending': 'open', # starting state of all orders
1781
+ 'running': 'open', # when order is being executed
1782
+ 'post-pending': 'open', # post-only order waiting to be placed
1783
+ 'open': 'open', # active order in the orderbook
1784
+ 'stop': 'open', # when stop order not yet triggered
1785
+ 'invalid': 'rejected', # order rejected
1786
+ 'done': 'closed', # order fully executed
1787
+ 'cancel': 'canceled', # order canceled by user
1788
+ 'canceled': 'canceled', # alternative spelling
1789
+ }
1790
+ return self.safe_string(statuses, status, status)
1791
+
1792
+ def parse_amount(self, amount) -> Str:
1793
+ v = self.safe_string(amount, 'v', None)
1794
+ e = self.safe_integer(amount, 'e', None)
1795
+ if v is None or e is None:
1796
+ return None
1797
+ preciseAmount = Precise(v)
1798
+ preciseAmount.decimals = e
1799
+ preciseAmount.reduce()
1800
+ return str(preciseAmount)
1801
+
1802
+ def to_amount(self, amount: float, precision: float) -> dict:
1803
+ v = str(amount)
1804
+ e = precision
1805
+ return {
1806
+ 'v': v,
1807
+ 'e': e,
1808
+ }
1809
+
1810
+ def handle_errors(self, code: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
1811
+ # {
1812
+ # "code": 404,
1813
+ # "error": "Not Found: Crypto\\Token(US)",
1814
+ # "exception": "Exception\\NotFound",
1815
+ # "message": "[I18N:error_not_found]",
1816
+ # "request": "cc83738a-2438-4f53-ae44-f15306c07f32",
1817
+ # "result": "error",
1818
+ # "time": 0.0089569091796875,
1819
+ # "token": "error_not_found"
1820
+ # }
1821
+ errorCode = self.safe_string(response, 'code')
1822
+ message = self.safe_string(response, 'message')
1823
+ if errorCode is not None:
1824
+ self.throw_exactly_matched_exception(self.exceptions['exact'], errorCode, message)
1825
+ raise ExchangeError(self.id + ' ' + message)
1826
+ return None