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