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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (772) hide show
  1. ccxt/__init__.py +358 -0
  2. ccxt/abantether.py +316 -0
  3. ccxt/abstract/__init__.py +0 -0
  4. ccxt/abstract/abantether.py +5 -0
  5. ccxt/abstract/ace.py +15 -0
  6. ccxt/abstract/afratether.py +6 -0
  7. ccxt/abstract/alpaca.py +70 -0
  8. ccxt/abstract/arzinja.py +5 -0
  9. ccxt/abstract/arzplus.py +7 -0
  10. ccxt/abstract/ascendex.py +77 -0
  11. ccxt/abstract/bequant.py +115 -0
  12. ccxt/abstract/bigone.py +45 -0
  13. ccxt/abstract/binance.py +712 -0
  14. ccxt/abstract/binancecoinm.py +712 -0
  15. ccxt/abstract/binanceus.py +764 -0
  16. ccxt/abstract/binanceusdm.py +712 -0
  17. ccxt/abstract/bingx.py +113 -0
  18. ccxt/abstract/bit2c.py +27 -0
  19. ccxt/abstract/bitbank.py +27 -0
  20. ccxt/abstract/bitbay.py +53 -0
  21. ccxt/abstract/bitbns.py +40 -0
  22. ccxt/abstract/bitcoincom.py +115 -0
  23. ccxt/abstract/bitfinex.py +69 -0
  24. ccxt/abstract/bitfinex2.py +139 -0
  25. ccxt/abstract/bitflyer.py +38 -0
  26. ccxt/abstract/bitget.py +508 -0
  27. ccxt/abstract/bithumb.py +32 -0
  28. ccxt/abstract/bitimen.py +7 -0
  29. ccxt/abstract/bitir.py +7 -0
  30. ccxt/abstract/bitmart.py +99 -0
  31. ccxt/abstract/bitmex.py +97 -0
  32. ccxt/abstract/bitopro.py +29 -0
  33. ccxt/abstract/bitpanda.py +35 -0
  34. ccxt/abstract/bitpin.py +7 -0
  35. ccxt/abstract/bitrue.py +72 -0
  36. ccxt/abstract/bitso.py +43 -0
  37. ccxt/abstract/bitstamp.py +258 -0
  38. ccxt/abstract/bitteam.py +29 -0
  39. ccxt/abstract/bitvavo.py +27 -0
  40. ccxt/abstract/bl3p.py +19 -0
  41. ccxt/abstract/blockchaincom.py +28 -0
  42. ccxt/abstract/blofin.py +37 -0
  43. ccxt/abstract/btcalpha.py +18 -0
  44. ccxt/abstract/btcbox.py +13 -0
  45. ccxt/abstract/btcmarkets.py +39 -0
  46. ccxt/abstract/btcturk.py +20 -0
  47. ccxt/abstract/bybit.py +298 -0
  48. ccxt/abstract/cex.py +33 -0
  49. ccxt/abstract/coinbase.py +94 -0
  50. ccxt/abstract/coinbaseadvanced.py +94 -0
  51. ccxt/abstract/coinbaseexchange.py +67 -0
  52. ccxt/abstract/coinbaseinternational.py +39 -0
  53. ccxt/abstract/coincatch.py +94 -0
  54. ccxt/abstract/coincheck.py +33 -0
  55. ccxt/abstract/coinex.py +237 -0
  56. ccxt/abstract/coinlist.py +54 -0
  57. ccxt/abstract/coinmate.py +62 -0
  58. ccxt/abstract/coinmetro.py +34 -0
  59. ccxt/abstract/coinone.py +67 -0
  60. ccxt/abstract/coinsph.py +54 -0
  61. ccxt/abstract/coinspot.py +28 -0
  62. ccxt/abstract/cryptocom.py +107 -0
  63. ccxt/abstract/currencycom.py +68 -0
  64. ccxt/abstract/delta.py +50 -0
  65. ccxt/abstract/deribit.py +125 -0
  66. ccxt/abstract/digifinex.py +91 -0
  67. ccxt/abstract/eterex.py +5 -0
  68. ccxt/abstract/excoino.py +7 -0
  69. ccxt/abstract/exir.py +8 -0
  70. ccxt/abstract/exmo.py +55 -0
  71. ccxt/abstract/exnovin.py +6 -0
  72. ccxt/abstract/farhadexchange.py +5 -0
  73. ccxt/abstract/fmfwio.py +115 -0
  74. ccxt/abstract/gate.py +265 -0
  75. ccxt/abstract/gateio.py +265 -0
  76. ccxt/abstract/gemini.py +58 -0
  77. ccxt/abstract/hashkey.py +67 -0
  78. ccxt/abstract/hitbtc.py +115 -0
  79. ccxt/abstract/hitbtc3.py +115 -0
  80. ccxt/abstract/hitobit.py +8 -0
  81. ccxt/abstract/hollaex.py +33 -0
  82. ccxt/abstract/htx.py +548 -0
  83. ccxt/abstract/huobi.py +548 -0
  84. ccxt/abstract/huobijp.py +114 -0
  85. ccxt/abstract/hyperliquid.py +6 -0
  86. ccxt/abstract/idex.py +26 -0
  87. ccxt/abstract/independentreserve.py +37 -0
  88. ccxt/abstract/indodax.py +26 -0
  89. ccxt/abstract/jibitex.py +7 -0
  90. ccxt/abstract/kraken.py +57 -0
  91. ccxt/abstract/krakenfutures.py +38 -0
  92. ccxt/abstract/kucoin.py +214 -0
  93. ccxt/abstract/kucoinfutures.py +233 -0
  94. ccxt/abstract/kuna.py +182 -0
  95. ccxt/abstract/latoken.py +56 -0
  96. ccxt/abstract/lbank.py +61 -0
  97. ccxt/abstract/luno.py +37 -0
  98. ccxt/abstract/lykke.py +29 -0
  99. ccxt/abstract/mercado.py +25 -0
  100. ccxt/abstract/mexc.py +178 -0
  101. ccxt/abstract/ndax.py +97 -0
  102. ccxt/abstract/nobitex.py +7 -0
  103. ccxt/abstract/novadax.py +29 -0
  104. ccxt/abstract/oceanex.py +22 -0
  105. ccxt/abstract/okcoin.py +74 -0
  106. ccxt/abstract/okexchange.py +8 -0
  107. ccxt/abstract/okx.py +324 -0
  108. ccxt/abstract/ompfinex.py +7 -0
  109. ccxt/abstract/onetrading.py +35 -0
  110. ccxt/abstract/oxfun.py +34 -0
  111. ccxt/abstract/p2b.py +22 -0
  112. ccxt/abstract/paradex.py +40 -0
  113. ccxt/abstract/paymium.py +28 -0
  114. ccxt/abstract/phemex.py +115 -0
  115. ccxt/abstract/poloniex.py +69 -0
  116. ccxt/abstract/poloniexfutures.py +48 -0
  117. ccxt/abstract/probit.py +23 -0
  118. ccxt/abstract/ramzinex.py +7 -0
  119. ccxt/abstract/sarmayex.py +5 -0
  120. ccxt/abstract/sarrafex.py +7 -0
  121. ccxt/abstract/tabdeal.py +7 -0
  122. ccxt/abstract/tetherland.py +5 -0
  123. ccxt/abstract/timex.py +62 -0
  124. ccxt/abstract/tokocrypto.py +37 -0
  125. ccxt/abstract/tradeogre.py +16 -0
  126. ccxt/abstract/twox.py +5 -0
  127. ccxt/abstract/ubitex.py +7 -0
  128. ccxt/abstract/upbit.py +38 -0
  129. ccxt/abstract/vertex.py +19 -0
  130. ccxt/abstract/wallex.py +8 -0
  131. ccxt/abstract/wavesexchange.py +154 -0
  132. ccxt/abstract/wazirx.py +30 -0
  133. ccxt/abstract/whitebit.py +98 -0
  134. ccxt/abstract/woo.py +83 -0
  135. ccxt/abstract/woofipro.py +119 -0
  136. ccxt/abstract/xt.py +152 -0
  137. ccxt/abstract/yobit.py +16 -0
  138. ccxt/abstract/zaif.py +38 -0
  139. ccxt/abstract/zonda.py +53 -0
  140. ccxt/ace.py +1012 -0
  141. ccxt/afratether.py +293 -0
  142. ccxt/alpaca.py +1083 -0
  143. ccxt/arzinja.py +285 -0
  144. ccxt/arzplus.py +412 -0
  145. ccxt/ascendex.py +3330 -0
  146. ccxt/async_support/__init__.py +337 -0
  147. ccxt/async_support/abantether.py +316 -0
  148. ccxt/async_support/ace.py +1012 -0
  149. ccxt/async_support/afratether.py +293 -0
  150. ccxt/async_support/alpaca.py +1083 -0
  151. ccxt/async_support/arzinja.py +285 -0
  152. ccxt/async_support/arzplus.py +412 -0
  153. ccxt/async_support/ascendex.py +3330 -0
  154. ccxt/async_support/base/__init__.py +1 -0
  155. ccxt/async_support/base/exchange.py +1966 -0
  156. ccxt/async_support/base/throttler.py +50 -0
  157. ccxt/async_support/base/ws/__init__.py +38 -0
  158. ccxt/async_support/base/ws/aiohttp_client.py +125 -0
  159. ccxt/async_support/base/ws/cache.py +212 -0
  160. ccxt/async_support/base/ws/client.py +193 -0
  161. ccxt/async_support/base/ws/fast_client.py +96 -0
  162. ccxt/async_support/base/ws/functions.py +59 -0
  163. ccxt/async_support/base/ws/future.py +58 -0
  164. ccxt/async_support/base/ws/order_book.py +78 -0
  165. ccxt/async_support/base/ws/order_book_side.py +174 -0
  166. ccxt/async_support/bequant.py +33 -0
  167. ccxt/async_support/bigone.py +2113 -0
  168. ccxt/async_support/binance.py +12234 -0
  169. ccxt/async_support/binancecoinm.py +45 -0
  170. ccxt/async_support/binanceus.py +211 -0
  171. ccxt/async_support/binanceusdm.py +58 -0
  172. ccxt/async_support/bingx.py +4325 -0
  173. ccxt/async_support/bit2c.py +866 -0
  174. ccxt/async_support/bitbank.py +1001 -0
  175. ccxt/async_support/bitbay.py +17 -0
  176. ccxt/async_support/bitbns.py +1154 -0
  177. ccxt/async_support/bitcoincom.py +17 -0
  178. ccxt/async_support/bitfinex.py +1617 -0
  179. ccxt/async_support/bitfinex2.py +3552 -0
  180. ccxt/async_support/bitflyer.py +995 -0
  181. ccxt/async_support/bitget.py +8273 -0
  182. ccxt/async_support/bithumb.py +1061 -0
  183. ccxt/async_support/bitimen.py +401 -0
  184. ccxt/async_support/bitir.py +490 -0
  185. ccxt/async_support/bitmart.py +4415 -0
  186. ccxt/async_support/bitmex.py +2756 -0
  187. ccxt/async_support/bitopro.py +1630 -0
  188. ccxt/async_support/bitpanda.py +16 -0
  189. ccxt/async_support/bitpin.py +454 -0
  190. ccxt/async_support/bitrue.py +3027 -0
  191. ccxt/async_support/bitso.py +1670 -0
  192. ccxt/async_support/bitstamp.py +2203 -0
  193. ccxt/async_support/bitteam.py +2239 -0
  194. ccxt/async_support/bitvavo.py +1968 -0
  195. ccxt/async_support/bl3p.py +485 -0
  196. ccxt/async_support/blockchaincom.py +1104 -0
  197. ccxt/async_support/blofin.py +2066 -0
  198. ccxt/async_support/btcalpha.py +891 -0
  199. ccxt/async_support/btcbox.py +544 -0
  200. ccxt/async_support/btcmarkets.py +1221 -0
  201. ccxt/async_support/btcturk.py +911 -0
  202. ccxt/async_support/bybit.py +8159 -0
  203. ccxt/async_support/cex.py +1605 -0
  204. ccxt/async_support/coinbase.py +4475 -0
  205. ccxt/async_support/coinbaseadvanced.py +17 -0
  206. ccxt/async_support/coinbaseexchange.py +1734 -0
  207. ccxt/async_support/coinbaseinternational.py +1899 -0
  208. ccxt/async_support/coincatch.py +5069 -0
  209. ccxt/async_support/coincheck.py +815 -0
  210. ccxt/async_support/coinex.py +5526 -0
  211. ccxt/async_support/coinlist.py +2243 -0
  212. ccxt/async_support/coinmate.py +1067 -0
  213. ccxt/async_support/coinmetro.py +1797 -0
  214. ccxt/async_support/coinone.py +1127 -0
  215. ccxt/async_support/coinsph.py +1850 -0
  216. ccxt/async_support/coinspot.py +534 -0
  217. ccxt/async_support/cryptocom.py +2822 -0
  218. ccxt/async_support/currencycom.py +1950 -0
  219. ccxt/async_support/delta.py +3376 -0
  220. ccxt/async_support/deribit.py +3437 -0
  221. ccxt/async_support/digifinex.py +3960 -0
  222. ccxt/async_support/eterex.py +286 -0
  223. ccxt/async_support/excoino.py +399 -0
  224. ccxt/async_support/exir.py +375 -0
  225. ccxt/async_support/exmo.py +2462 -0
  226. ccxt/async_support/exnovin.py +360 -0
  227. ccxt/async_support/farhadexchange.py +266 -0
  228. ccxt/async_support/fmfwio.py +34 -0
  229. ccxt/async_support/gate.py +6976 -0
  230. ccxt/async_support/gateio.py +16 -0
  231. ccxt/async_support/gemini.py +1825 -0
  232. ccxt/async_support/hashkey.py +4150 -0
  233. ccxt/async_support/hitbtc.py +3423 -0
  234. ccxt/async_support/hitbtc3.py +16 -0
  235. ccxt/async_support/hitobit.py +391 -0
  236. ccxt/async_support/hollaex.py +1813 -0
  237. ccxt/async_support/htx.py +8506 -0
  238. ccxt/async_support/huobi.py +16 -0
  239. ccxt/async_support/huobijp.py +1801 -0
  240. ccxt/async_support/hyperliquid.py +2431 -0
  241. ccxt/async_support/idex.py +1766 -0
  242. ccxt/async_support/independentreserve.py +784 -0
  243. ccxt/async_support/indodax.py +1247 -0
  244. ccxt/async_support/jibitex.py +395 -0
  245. ccxt/async_support/kraken.py +2894 -0
  246. ccxt/async_support/krakenfutures.py +2601 -0
  247. ccxt/async_support/kucoin.py +4602 -0
  248. ccxt/async_support/kucoinfutures.py +2698 -0
  249. ccxt/async_support/kuna.py +1841 -0
  250. ccxt/async_support/latoken.py +1664 -0
  251. ccxt/async_support/lbank.py +2683 -0
  252. ccxt/async_support/luno.py +1067 -0
  253. ccxt/async_support/lykke.py +1270 -0
  254. ccxt/async_support/mercado.py +842 -0
  255. ccxt/async_support/mexc.py +5369 -0
  256. ccxt/async_support/ndax.py +2354 -0
  257. ccxt/async_support/nobitex.py +419 -0
  258. ccxt/async_support/novadax.py +1484 -0
  259. ccxt/async_support/oceanex.py +903 -0
  260. ccxt/async_support/okcoin.py +2936 -0
  261. ccxt/async_support/okexchange.py +349 -0
  262. ccxt/async_support/okx.py +7827 -0
  263. ccxt/async_support/ompfinex.py +472 -0
  264. ccxt/async_support/onetrading.py +1911 -0
  265. ccxt/async_support/oxfun.py +2773 -0
  266. ccxt/async_support/p2b.py +1194 -0
  267. ccxt/async_support/paradex.py +2015 -0
  268. ccxt/async_support/paymium.py +564 -0
  269. ccxt/async_support/phemex.py +4473 -0
  270. ccxt/async_support/poloniex.py +2232 -0
  271. ccxt/async_support/poloniexfutures.py +1717 -0
  272. ccxt/async_support/probit.py +1734 -0
  273. ccxt/async_support/ramzinex.py +476 -0
  274. ccxt/async_support/sarmayex.py +357 -0
  275. ccxt/async_support/sarrafex.py +478 -0
  276. ccxt/async_support/tabdeal.py +364 -0
  277. ccxt/async_support/tetherland.py +349 -0
  278. ccxt/async_support/timex.py +1593 -0
  279. ccxt/async_support/tokocrypto.py +2405 -0
  280. ccxt/async_support/tradeogre.py +608 -0
  281. ccxt/async_support/twox.py +326 -0
  282. ccxt/async_support/ubitex.py +409 -0
  283. ccxt/async_support/upbit.py +1833 -0
  284. ccxt/async_support/vertex.py +2922 -0
  285. ccxt/async_support/wallex.py +445 -0
  286. ccxt/async_support/wavesexchange.py +2473 -0
  287. ccxt/async_support/wazirx.py +1224 -0
  288. ccxt/async_support/whitebit.py +2469 -0
  289. ccxt/async_support/woo.py +3114 -0
  290. ccxt/async_support/woofipro.py +2533 -0
  291. ccxt/async_support/xt.py +4454 -0
  292. ccxt/async_support/yobit.py +1283 -0
  293. ccxt/async_support/zaif.py +725 -0
  294. ccxt/async_support/zonda.py +1828 -0
  295. ccxt/base/__init__.py +27 -0
  296. ccxt/base/decimal_to_precision.py +174 -0
  297. ccxt/base/errors.py +242 -0
  298. ccxt/base/exchange.py +5941 -0
  299. ccxt/base/precise.py +287 -0
  300. ccxt/base/types.py +502 -0
  301. ccxt/bequant.py +33 -0
  302. ccxt/bigone.py +2112 -0
  303. ccxt/binance.py +12233 -0
  304. ccxt/binancecoinm.py +45 -0
  305. ccxt/binanceus.py +211 -0
  306. ccxt/binanceusdm.py +58 -0
  307. ccxt/bingx.py +4324 -0
  308. ccxt/bit2c.py +866 -0
  309. ccxt/bitbank.py +1001 -0
  310. ccxt/bitbay.py +17 -0
  311. ccxt/bitbns.py +1154 -0
  312. ccxt/bitcoincom.py +17 -0
  313. ccxt/bitfinex.py +1617 -0
  314. ccxt/bitfinex2.py +3552 -0
  315. ccxt/bitflyer.py +995 -0
  316. ccxt/bitget.py +8272 -0
  317. ccxt/bithumb.py +1061 -0
  318. ccxt/bitimen.py +401 -0
  319. ccxt/bitir.py +490 -0
  320. ccxt/bitmart.py +4415 -0
  321. ccxt/bitmex.py +2756 -0
  322. ccxt/bitopro.py +1630 -0
  323. ccxt/bitpanda.py +16 -0
  324. ccxt/bitpin.py +454 -0
  325. ccxt/bitrue.py +3026 -0
  326. ccxt/bitso.py +1670 -0
  327. ccxt/bitstamp.py +2203 -0
  328. ccxt/bitteam.py +2239 -0
  329. ccxt/bitvavo.py +1968 -0
  330. ccxt/bl3p.py +485 -0
  331. ccxt/blockchaincom.py +1104 -0
  332. ccxt/blofin.py +2066 -0
  333. ccxt/btcalpha.py +891 -0
  334. ccxt/btcbox.py +544 -0
  335. ccxt/btcmarkets.py +1221 -0
  336. ccxt/btcturk.py +911 -0
  337. ccxt/bybit.py +8158 -0
  338. ccxt/cex.py +1605 -0
  339. ccxt/coinbase.py +4474 -0
  340. ccxt/coinbaseadvanced.py +17 -0
  341. ccxt/coinbaseexchange.py +1734 -0
  342. ccxt/coinbaseinternational.py +1899 -0
  343. ccxt/coincatch.py +5069 -0
  344. ccxt/coincheck.py +815 -0
  345. ccxt/coinex.py +5525 -0
  346. ccxt/coinlist.py +2243 -0
  347. ccxt/coinmate.py +1067 -0
  348. ccxt/coinmetro.py +1797 -0
  349. ccxt/coinone.py +1127 -0
  350. ccxt/coinsph.py +1850 -0
  351. ccxt/coinspot.py +534 -0
  352. ccxt/cryptocom.py +2822 -0
  353. ccxt/currencycom.py +1950 -0
  354. ccxt/delta.py +3376 -0
  355. ccxt/deribit.py +3437 -0
  356. ccxt/digifinex.py +3959 -0
  357. ccxt/eterex.py +286 -0
  358. ccxt/excoino.py +399 -0
  359. ccxt/exir.py +375 -0
  360. ccxt/exmo.py +2462 -0
  361. ccxt/exnovin.py +360 -0
  362. ccxt/farhadexchange.py +266 -0
  363. ccxt/fmfwio.py +34 -0
  364. ccxt/gate.py +6975 -0
  365. ccxt/gateio.py +16 -0
  366. ccxt/gemini.py +1824 -0
  367. ccxt/hashkey.py +4150 -0
  368. ccxt/hitbtc.py +3423 -0
  369. ccxt/hitbtc3.py +16 -0
  370. ccxt/hitobit.py +391 -0
  371. ccxt/hollaex.py +1813 -0
  372. ccxt/htx.py +8505 -0
  373. ccxt/huobi.py +16 -0
  374. ccxt/huobijp.py +1801 -0
  375. ccxt/hyperliquid.py +2430 -0
  376. ccxt/idex.py +1766 -0
  377. ccxt/independentreserve.py +784 -0
  378. ccxt/indodax.py +1247 -0
  379. ccxt/jibitex.py +395 -0
  380. ccxt/kraken.py +2894 -0
  381. ccxt/krakenfutures.py +2601 -0
  382. ccxt/kucoin.py +4601 -0
  383. ccxt/kucoinfutures.py +2698 -0
  384. ccxt/kuna.py +1841 -0
  385. ccxt/latoken.py +1664 -0
  386. ccxt/lbank.py +2682 -0
  387. ccxt/luno.py +1067 -0
  388. ccxt/lykke.py +1270 -0
  389. ccxt/mercado.py +842 -0
  390. ccxt/mexc.py +5369 -0
  391. ccxt/ndax.py +2354 -0
  392. ccxt/nobitex.py +419 -0
  393. ccxt/novadax.py +1484 -0
  394. ccxt/oceanex.py +903 -0
  395. ccxt/okcoin.py +2936 -0
  396. ccxt/okexchange.py +349 -0
  397. ccxt/okx.py +7826 -0
  398. ccxt/ompfinex.py +472 -0
  399. ccxt/onetrading.py +1911 -0
  400. ccxt/oxfun.py +2772 -0
  401. ccxt/p2b.py +1194 -0
  402. ccxt/paradex.py +2015 -0
  403. ccxt/paymium.py +564 -0
  404. ccxt/phemex.py +4473 -0
  405. ccxt/poloniex.py +2232 -0
  406. ccxt/poloniexfutures.py +1717 -0
  407. ccxt/pro/__init__.py +149 -0
  408. ccxt/pro/alpaca.py +685 -0
  409. ccxt/pro/ascendex.py +916 -0
  410. ccxt/pro/bequant.py +38 -0
  411. ccxt/pro/binance.py +3488 -0
  412. ccxt/pro/binancecoinm.py +28 -0
  413. ccxt/pro/binanceus.py +48 -0
  414. ccxt/pro/binanceusdm.py +31 -0
  415. ccxt/pro/bingx.py +1264 -0
  416. ccxt/pro/bitcoincom.py +34 -0
  417. ccxt/pro/bitfinex.py +621 -0
  418. ccxt/pro/bitfinex2.py +1083 -0
  419. ccxt/pro/bitget.py +1692 -0
  420. ccxt/pro/bithumb.py +368 -0
  421. ccxt/pro/bitmart.py +1449 -0
  422. ccxt/pro/bitmex.py +1656 -0
  423. ccxt/pro/bitopro.py +445 -0
  424. ccxt/pro/bitpanda.py +15 -0
  425. ccxt/pro/bitrue.py +447 -0
  426. ccxt/pro/bitstamp.py +522 -0
  427. ccxt/pro/bitvavo.py +1270 -0
  428. ccxt/pro/blockchaincom.py +738 -0
  429. ccxt/pro/blofin.py +692 -0
  430. ccxt/pro/bybit.py +2000 -0
  431. ccxt/pro/cex.py +1440 -0
  432. ccxt/pro/coinbase.py +678 -0
  433. ccxt/pro/coinbaseadvanced.py +16 -0
  434. ccxt/pro/coinbaseexchange.py +895 -0
  435. ccxt/pro/coinbaseinternational.py +620 -0
  436. ccxt/pro/coincatch.py +1464 -0
  437. ccxt/pro/coincheck.py +199 -0
  438. ccxt/pro/coinex.py +1061 -0
  439. ccxt/pro/coinone.py +395 -0
  440. ccxt/pro/cryptocom.py +947 -0
  441. ccxt/pro/currencycom.py +536 -0
  442. ccxt/pro/deribit.py +892 -0
  443. ccxt/pro/exmo.py +629 -0
  444. ccxt/pro/gate.py +1416 -0
  445. ccxt/pro/gateio.py +15 -0
  446. ccxt/pro/gemini.py +865 -0
  447. ccxt/pro/hashkey.py +802 -0
  448. ccxt/pro/hitbtc.py +1216 -0
  449. ccxt/pro/hollaex.py +563 -0
  450. ccxt/pro/htx.py +2215 -0
  451. ccxt/pro/huobi.py +15 -0
  452. ccxt/pro/huobijp.py +570 -0
  453. ccxt/pro/hyperliquid.py +525 -0
  454. ccxt/pro/idex.py +672 -0
  455. ccxt/pro/independentreserve.py +270 -0
  456. ccxt/pro/kraken.py +1356 -0
  457. ccxt/pro/krakenfutures.py +1492 -0
  458. ccxt/pro/kucoin.py +1133 -0
  459. ccxt/pro/kucoinfutures.py +1081 -0
  460. ccxt/pro/lbank.py +843 -0
  461. ccxt/pro/luno.py +303 -0
  462. ccxt/pro/mexc.py +1122 -0
  463. ccxt/pro/ndax.py +506 -0
  464. ccxt/pro/okcoin.py +698 -0
  465. ccxt/pro/okx.py +1851 -0
  466. ccxt/pro/onetrading.py +1275 -0
  467. ccxt/pro/oxfun.py +950 -0
  468. ccxt/pro/p2b.py +419 -0
  469. ccxt/pro/paradex.py +352 -0
  470. ccxt/pro/phemex.py +1441 -0
  471. ccxt/pro/poloniex.py +1166 -0
  472. ccxt/pro/poloniexfutures.py +990 -0
  473. ccxt/pro/probit.py +551 -0
  474. ccxt/pro/upbit.py +520 -0
  475. ccxt/pro/vertex.py +943 -0
  476. ccxt/pro/wazirx.py +749 -0
  477. ccxt/pro/whitebit.py +864 -0
  478. ccxt/pro/woo.py +1078 -0
  479. ccxt/pro/woofipro.py +1183 -0
  480. ccxt/pro/xt.py +1067 -0
  481. ccxt/probit.py +1734 -0
  482. ccxt/ramzinex.py +476 -0
  483. ccxt/sarmayex.py +357 -0
  484. ccxt/sarrafex.py +478 -0
  485. ccxt/static_dependencies/__init__.py +1 -0
  486. ccxt/static_dependencies/ecdsa/__init__.py +14 -0
  487. ccxt/static_dependencies/ecdsa/_version.py +520 -0
  488. ccxt/static_dependencies/ecdsa/curves.py +56 -0
  489. ccxt/static_dependencies/ecdsa/der.py +221 -0
  490. ccxt/static_dependencies/ecdsa/ecdsa.py +310 -0
  491. ccxt/static_dependencies/ecdsa/ellipticcurve.py +197 -0
  492. ccxt/static_dependencies/ecdsa/keys.py +332 -0
  493. ccxt/static_dependencies/ecdsa/numbertheory.py +531 -0
  494. ccxt/static_dependencies/ecdsa/rfc6979.py +100 -0
  495. ccxt/static_dependencies/ecdsa/util.py +266 -0
  496. ccxt/static_dependencies/ethereum/__init__.py +7 -0
  497. ccxt/static_dependencies/ethereum/abi/__init__.py +16 -0
  498. ccxt/static_dependencies/ethereum/abi/abi.py +19 -0
  499. ccxt/static_dependencies/ethereum/abi/base.py +152 -0
  500. ccxt/static_dependencies/ethereum/abi/codec.py +217 -0
  501. ccxt/static_dependencies/ethereum/abi/constants.py +3 -0
  502. ccxt/static_dependencies/ethereum/abi/decoding.py +565 -0
  503. ccxt/static_dependencies/ethereum/abi/encoding.py +720 -0
  504. ccxt/static_dependencies/ethereum/abi/exceptions.py +139 -0
  505. ccxt/static_dependencies/ethereum/abi/grammar.py +443 -0
  506. ccxt/static_dependencies/ethereum/abi/packed.py +13 -0
  507. ccxt/static_dependencies/ethereum/abi/py.typed +0 -0
  508. ccxt/static_dependencies/ethereum/abi/registry.py +643 -0
  509. ccxt/static_dependencies/ethereum/abi/tools/__init__.py +3 -0
  510. ccxt/static_dependencies/ethereum/abi/tools/_strategies.py +230 -0
  511. ccxt/static_dependencies/ethereum/abi/utils/__init__.py +0 -0
  512. ccxt/static_dependencies/ethereum/abi/utils/numeric.py +83 -0
  513. ccxt/static_dependencies/ethereum/abi/utils/padding.py +27 -0
  514. ccxt/static_dependencies/ethereum/abi/utils/string.py +19 -0
  515. ccxt/static_dependencies/ethereum/account/__init__.py +3 -0
  516. ccxt/static_dependencies/ethereum/account/encode_typed_data/__init__.py +4 -0
  517. ccxt/static_dependencies/ethereum/account/encode_typed_data/encoding_and_hashing.py +239 -0
  518. ccxt/static_dependencies/ethereum/account/encode_typed_data/helpers.py +40 -0
  519. ccxt/static_dependencies/ethereum/account/messages.py +263 -0
  520. ccxt/static_dependencies/ethereum/account/py.typed +0 -0
  521. ccxt/static_dependencies/ethereum/hexbytes/__init__.py +5 -0
  522. ccxt/static_dependencies/ethereum/hexbytes/_utils.py +54 -0
  523. ccxt/static_dependencies/ethereum/hexbytes/main.py +65 -0
  524. ccxt/static_dependencies/ethereum/hexbytes/py.typed +0 -0
  525. ccxt/static_dependencies/ethereum/typing/__init__.py +63 -0
  526. ccxt/static_dependencies/ethereum/typing/abi.py +6 -0
  527. ccxt/static_dependencies/ethereum/typing/bls.py +7 -0
  528. ccxt/static_dependencies/ethereum/typing/discovery.py +5 -0
  529. ccxt/static_dependencies/ethereum/typing/encoding.py +7 -0
  530. ccxt/static_dependencies/ethereum/typing/enums.py +17 -0
  531. ccxt/static_dependencies/ethereum/typing/ethpm.py +9 -0
  532. ccxt/static_dependencies/ethereum/typing/evm.py +20 -0
  533. ccxt/static_dependencies/ethereum/typing/networks.py +1122 -0
  534. ccxt/static_dependencies/ethereum/typing/py.typed +0 -0
  535. ccxt/static_dependencies/ethereum/utils/__init__.py +115 -0
  536. ccxt/static_dependencies/ethereum/utils/abi.py +72 -0
  537. ccxt/static_dependencies/ethereum/utils/address.py +171 -0
  538. ccxt/static_dependencies/ethereum/utils/applicators.py +151 -0
  539. ccxt/static_dependencies/ethereum/utils/conversions.py +190 -0
  540. ccxt/static_dependencies/ethereum/utils/currency.py +107 -0
  541. ccxt/static_dependencies/ethereum/utils/curried/__init__.py +269 -0
  542. ccxt/static_dependencies/ethereum/utils/debug.py +20 -0
  543. ccxt/static_dependencies/ethereum/utils/decorators.py +132 -0
  544. ccxt/static_dependencies/ethereum/utils/encoding.py +6 -0
  545. ccxt/static_dependencies/ethereum/utils/exceptions.py +4 -0
  546. ccxt/static_dependencies/ethereum/utils/functional.py +75 -0
  547. ccxt/static_dependencies/ethereum/utils/hexadecimal.py +74 -0
  548. ccxt/static_dependencies/ethereum/utils/humanize.py +188 -0
  549. ccxt/static_dependencies/ethereum/utils/logging.py +159 -0
  550. ccxt/static_dependencies/ethereum/utils/module_loading.py +31 -0
  551. ccxt/static_dependencies/ethereum/utils/numeric.py +43 -0
  552. ccxt/static_dependencies/ethereum/utils/py.typed +0 -0
  553. ccxt/static_dependencies/ethereum/utils/toolz.py +76 -0
  554. ccxt/static_dependencies/ethereum/utils/types.py +54 -0
  555. ccxt/static_dependencies/ethereum/utils/typing/__init__.py +18 -0
  556. ccxt/static_dependencies/ethereum/utils/typing/misc.py +14 -0
  557. ccxt/static_dependencies/ethereum/utils/units.py +31 -0
  558. ccxt/static_dependencies/keccak/__init__.py +3 -0
  559. ccxt/static_dependencies/keccak/keccak.py +197 -0
  560. ccxt/static_dependencies/lark/__init__.py +38 -0
  561. ccxt/static_dependencies/lark/__pyinstaller/__init__.py +6 -0
  562. ccxt/static_dependencies/lark/__pyinstaller/hook-lark.py +14 -0
  563. ccxt/static_dependencies/lark/ast_utils.py +59 -0
  564. ccxt/static_dependencies/lark/common.py +86 -0
  565. ccxt/static_dependencies/lark/exceptions.py +292 -0
  566. ccxt/static_dependencies/lark/grammar.py +130 -0
  567. ccxt/static_dependencies/lark/grammars/__init__.py +0 -0
  568. ccxt/static_dependencies/lark/indenter.py +143 -0
  569. ccxt/static_dependencies/lark/lark.py +658 -0
  570. ccxt/static_dependencies/lark/lexer.py +678 -0
  571. ccxt/static_dependencies/lark/load_grammar.py +1428 -0
  572. ccxt/static_dependencies/lark/parse_tree_builder.py +391 -0
  573. ccxt/static_dependencies/lark/parser_frontends.py +257 -0
  574. ccxt/static_dependencies/lark/parsers/__init__.py +0 -0
  575. ccxt/static_dependencies/lark/parsers/cyk.py +340 -0
  576. ccxt/static_dependencies/lark/parsers/earley.py +314 -0
  577. ccxt/static_dependencies/lark/parsers/earley_common.py +42 -0
  578. ccxt/static_dependencies/lark/parsers/earley_forest.py +801 -0
  579. ccxt/static_dependencies/lark/parsers/grammar_analysis.py +203 -0
  580. ccxt/static_dependencies/lark/parsers/lalr_analysis.py +332 -0
  581. ccxt/static_dependencies/lark/parsers/lalr_interactive_parser.py +158 -0
  582. ccxt/static_dependencies/lark/parsers/lalr_parser.py +122 -0
  583. ccxt/static_dependencies/lark/parsers/lalr_parser_state.py +110 -0
  584. ccxt/static_dependencies/lark/parsers/xearley.py +165 -0
  585. ccxt/static_dependencies/lark/reconstruct.py +107 -0
  586. ccxt/static_dependencies/lark/tools/__init__.py +70 -0
  587. ccxt/static_dependencies/lark/tools/nearley.py +202 -0
  588. ccxt/static_dependencies/lark/tools/serialize.py +32 -0
  589. ccxt/static_dependencies/lark/tools/standalone.py +196 -0
  590. ccxt/static_dependencies/lark/tree.py +267 -0
  591. ccxt/static_dependencies/lark/tree_matcher.py +186 -0
  592. ccxt/static_dependencies/lark/tree_templates.py +180 -0
  593. ccxt/static_dependencies/lark/utils.py +343 -0
  594. ccxt/static_dependencies/lark/visitors.py +596 -0
  595. ccxt/static_dependencies/marshmallow/__init__.py +81 -0
  596. ccxt/static_dependencies/marshmallow/base.py +65 -0
  597. ccxt/static_dependencies/marshmallow/class_registry.py +94 -0
  598. ccxt/static_dependencies/marshmallow/decorators.py +231 -0
  599. ccxt/static_dependencies/marshmallow/error_store.py +60 -0
  600. ccxt/static_dependencies/marshmallow/exceptions.py +71 -0
  601. ccxt/static_dependencies/marshmallow/fields.py +2114 -0
  602. ccxt/static_dependencies/marshmallow/orderedset.py +89 -0
  603. ccxt/static_dependencies/marshmallow/schema.py +1228 -0
  604. ccxt/static_dependencies/marshmallow/types.py +12 -0
  605. ccxt/static_dependencies/marshmallow/utils.py +378 -0
  606. ccxt/static_dependencies/marshmallow/validate.py +678 -0
  607. ccxt/static_dependencies/marshmallow/warnings.py +2 -0
  608. ccxt/static_dependencies/marshmallow_dataclass/__init__.py +1047 -0
  609. ccxt/static_dependencies/marshmallow_dataclass/collection_field.py +51 -0
  610. ccxt/static_dependencies/marshmallow_dataclass/lazy_class_attribute.py +45 -0
  611. ccxt/static_dependencies/marshmallow_dataclass/mypy.py +71 -0
  612. ccxt/static_dependencies/marshmallow_dataclass/typing.py +14 -0
  613. ccxt/static_dependencies/marshmallow_dataclass/union_field.py +82 -0
  614. ccxt/static_dependencies/marshmallow_oneofschema/__init__.py +1 -0
  615. ccxt/static_dependencies/marshmallow_oneofschema/one_of_schema.py +193 -0
  616. ccxt/static_dependencies/msgpack/__init__.py +55 -0
  617. ccxt/static_dependencies/msgpack/exceptions.py +48 -0
  618. ccxt/static_dependencies/msgpack/ext.py +168 -0
  619. ccxt/static_dependencies/msgpack/fallback.py +951 -0
  620. ccxt/static_dependencies/parsimonious/__init__.py +10 -0
  621. ccxt/static_dependencies/parsimonious/exceptions.py +105 -0
  622. ccxt/static_dependencies/parsimonious/expressions.py +479 -0
  623. ccxt/static_dependencies/parsimonious/grammar.py +487 -0
  624. ccxt/static_dependencies/parsimonious/nodes.py +325 -0
  625. ccxt/static_dependencies/parsimonious/utils.py +40 -0
  626. ccxt/static_dependencies/starknet/__init__.py +0 -0
  627. ccxt/static_dependencies/starknet/cairo/__init__.py +0 -0
  628. ccxt/static_dependencies/starknet/cairo/data_types.py +123 -0
  629. ccxt/static_dependencies/starknet/cairo/deprecated_parse/__init__.py +0 -0
  630. ccxt/static_dependencies/starknet/cairo/deprecated_parse/cairo_types.py +77 -0
  631. ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser.py +46 -0
  632. ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser_transformer.py +138 -0
  633. ccxt/static_dependencies/starknet/cairo/felt.py +64 -0
  634. ccxt/static_dependencies/starknet/cairo/type_parser.py +121 -0
  635. ccxt/static_dependencies/starknet/cairo/v1/__init__.py +0 -0
  636. ccxt/static_dependencies/starknet/cairo/v1/type_parser.py +59 -0
  637. ccxt/static_dependencies/starknet/cairo/v2/__init__.py +0 -0
  638. ccxt/static_dependencies/starknet/cairo/v2/type_parser.py +77 -0
  639. ccxt/static_dependencies/starknet/ccxt_utils.py +7 -0
  640. ccxt/static_dependencies/starknet/common.py +15 -0
  641. ccxt/static_dependencies/starknet/constants.py +39 -0
  642. ccxt/static_dependencies/starknet/hash/__init__.py +0 -0
  643. ccxt/static_dependencies/starknet/hash/address.py +79 -0
  644. ccxt/static_dependencies/starknet/hash/compiled_class_hash_objects.py +111 -0
  645. ccxt/static_dependencies/starknet/hash/selector.py +16 -0
  646. ccxt/static_dependencies/starknet/hash/storage.py +12 -0
  647. ccxt/static_dependencies/starknet/hash/utils.py +78 -0
  648. ccxt/static_dependencies/starknet/models/__init__.py +0 -0
  649. ccxt/static_dependencies/starknet/models/typed_data.py +45 -0
  650. ccxt/static_dependencies/starknet/serialization/__init__.py +24 -0
  651. ccxt/static_dependencies/starknet/serialization/_calldata_reader.py +40 -0
  652. ccxt/static_dependencies/starknet/serialization/_context.py +142 -0
  653. ccxt/static_dependencies/starknet/serialization/data_serializers/__init__.py +10 -0
  654. ccxt/static_dependencies/starknet/serialization/data_serializers/_common.py +82 -0
  655. ccxt/static_dependencies/starknet/serialization/data_serializers/array_serializer.py +43 -0
  656. ccxt/static_dependencies/starknet/serialization/data_serializers/bool_serializer.py +37 -0
  657. ccxt/static_dependencies/starknet/serialization/data_serializers/byte_array_serializer.py +66 -0
  658. ccxt/static_dependencies/starknet/serialization/data_serializers/cairo_data_serializer.py +71 -0
  659. ccxt/static_dependencies/starknet/serialization/data_serializers/enum_serializer.py +71 -0
  660. ccxt/static_dependencies/starknet/serialization/data_serializers/felt_serializer.py +50 -0
  661. ccxt/static_dependencies/starknet/serialization/data_serializers/named_tuple_serializer.py +58 -0
  662. ccxt/static_dependencies/starknet/serialization/data_serializers/option_serializer.py +43 -0
  663. ccxt/static_dependencies/starknet/serialization/data_serializers/output_serializer.py +40 -0
  664. ccxt/static_dependencies/starknet/serialization/data_serializers/payload_serializer.py +72 -0
  665. ccxt/static_dependencies/starknet/serialization/data_serializers/struct_serializer.py +36 -0
  666. ccxt/static_dependencies/starknet/serialization/data_serializers/tuple_serializer.py +36 -0
  667. ccxt/static_dependencies/starknet/serialization/data_serializers/uint256_serializer.py +76 -0
  668. ccxt/static_dependencies/starknet/serialization/data_serializers/uint_serializer.py +100 -0
  669. ccxt/static_dependencies/starknet/serialization/data_serializers/unit_serializer.py +32 -0
  670. ccxt/static_dependencies/starknet/serialization/errors.py +10 -0
  671. ccxt/static_dependencies/starknet/serialization/factory.py +229 -0
  672. ccxt/static_dependencies/starknet/serialization/function_serialization_adapter.py +110 -0
  673. ccxt/static_dependencies/starknet/serialization/tuple_dataclass.py +59 -0
  674. ccxt/static_dependencies/starknet/utils/__init__.py +0 -0
  675. ccxt/static_dependencies/starknet/utils/constructor_args_translator.py +86 -0
  676. ccxt/static_dependencies/starknet/utils/iterable.py +13 -0
  677. ccxt/static_dependencies/starknet/utils/schema.py +13 -0
  678. ccxt/static_dependencies/starknet/utils/typed_data.py +182 -0
  679. ccxt/static_dependencies/starkware/__init__.py +0 -0
  680. ccxt/static_dependencies/starkware/crypto/__init__.py +0 -0
  681. ccxt/static_dependencies/starkware/crypto/fast_pedersen_hash.py +50 -0
  682. ccxt/static_dependencies/starkware/crypto/math_utils.py +78 -0
  683. ccxt/static_dependencies/starkware/crypto/signature.py +2344 -0
  684. ccxt/static_dependencies/starkware/crypto/utils.py +63 -0
  685. ccxt/static_dependencies/sympy/__init__.py +0 -0
  686. ccxt/static_dependencies/sympy/core/__init__.py +0 -0
  687. ccxt/static_dependencies/sympy/core/intfunc.py +35 -0
  688. ccxt/static_dependencies/sympy/external/__init__.py +0 -0
  689. ccxt/static_dependencies/sympy/external/gmpy.py +345 -0
  690. ccxt/static_dependencies/sympy/external/importtools.py +187 -0
  691. ccxt/static_dependencies/sympy/external/ntheory.py +637 -0
  692. ccxt/static_dependencies/sympy/external/pythonmpq.py +341 -0
  693. ccxt/static_dependencies/toolz/__init__.py +26 -0
  694. ccxt/static_dependencies/toolz/_signatures.py +784 -0
  695. ccxt/static_dependencies/toolz/_version.py +520 -0
  696. ccxt/static_dependencies/toolz/compatibility.py +30 -0
  697. ccxt/static_dependencies/toolz/curried/__init__.py +101 -0
  698. ccxt/static_dependencies/toolz/curried/exceptions.py +22 -0
  699. ccxt/static_dependencies/toolz/curried/operator.py +22 -0
  700. ccxt/static_dependencies/toolz/dicttoolz.py +339 -0
  701. ccxt/static_dependencies/toolz/functoolz.py +1049 -0
  702. ccxt/static_dependencies/toolz/itertoolz.py +1057 -0
  703. ccxt/static_dependencies/toolz/recipes.py +46 -0
  704. ccxt/static_dependencies/toolz/utils.py +9 -0
  705. ccxt/static_dependencies/typing_inspect/__init__.py +0 -0
  706. ccxt/static_dependencies/typing_inspect/typing_inspect.py +851 -0
  707. ccxt/tabdeal.py +364 -0
  708. ccxt/test/__init__.py +3 -0
  709. ccxt/test/base/__init__.py +29 -0
  710. ccxt/test/base/test_account.py +26 -0
  711. ccxt/test/base/test_balance.py +56 -0
  712. ccxt/test/base/test_borrow_interest.py +35 -0
  713. ccxt/test/base/test_borrow_rate.py +32 -0
  714. ccxt/test/base/test_calculate_fee.py +51 -0
  715. ccxt/test/base/test_crypto.py +127 -0
  716. ccxt/test/base/test_currency.py +76 -0
  717. ccxt/test/base/test_datetime.py +109 -0
  718. ccxt/test/base/test_decimal_to_precision.py +392 -0
  719. ccxt/test/base/test_deep_extend.py +68 -0
  720. ccxt/test/base/test_deposit_withdrawal.py +50 -0
  721. ccxt/test/base/test_exchange_datetime_functions.py +76 -0
  722. ccxt/test/base/test_funding_rate_history.py +29 -0
  723. ccxt/test/base/test_last_price.py +31 -0
  724. ccxt/test/base/test_ledger_entry.py +45 -0
  725. ccxt/test/base/test_ledger_item.py +48 -0
  726. ccxt/test/base/test_leverage_tier.py +33 -0
  727. ccxt/test/base/test_liquidation.py +50 -0
  728. ccxt/test/base/test_margin_mode.py +24 -0
  729. ccxt/test/base/test_margin_modification.py +35 -0
  730. ccxt/test/base/test_market.py +193 -0
  731. ccxt/test/base/test_number.py +411 -0
  732. ccxt/test/base/test_ohlcv.py +33 -0
  733. ccxt/test/base/test_open_interest.py +32 -0
  734. ccxt/test/base/test_order.py +64 -0
  735. ccxt/test/base/test_order_book.py +69 -0
  736. ccxt/test/base/test_position.py +60 -0
  737. ccxt/test/base/test_shared_methods.py +353 -0
  738. ccxt/test/base/test_status.py +24 -0
  739. ccxt/test/base/test_throttle.py +126 -0
  740. ccxt/test/base/test_ticker.py +92 -0
  741. ccxt/test/base/test_trade.py +47 -0
  742. ccxt/test/base/test_trading_fee.py +26 -0
  743. ccxt/test/base/test_transaction.py +39 -0
  744. ccxt/test/test_async.py +1649 -0
  745. ccxt/test/test_sync.py +1648 -0
  746. ccxt/test/tests_async.py +1558 -0
  747. ccxt/test/tests_helpers.py +287 -0
  748. ccxt/test/tests_init.py +39 -0
  749. ccxt/test/tests_sync.py +1555 -0
  750. ccxt/tetherland.py +349 -0
  751. ccxt/timex.py +1593 -0
  752. ccxt/tokocrypto.py +2405 -0
  753. ccxt/tradeogre.py +608 -0
  754. ccxt/twox.py +326 -0
  755. ccxt/ubitex.py +409 -0
  756. ccxt/upbit.py +1833 -0
  757. ccxt/vertex.py +2922 -0
  758. ccxt/wallex.py +445 -0
  759. ccxt/wavesexchange.py +2472 -0
  760. ccxt/wazirx.py +1224 -0
  761. ccxt/whitebit.py +2469 -0
  762. ccxt/woo.py +3114 -0
  763. ccxt/woofipro.py +2533 -0
  764. ccxt/xt.py +4453 -0
  765. ccxt/yobit.py +1283 -0
  766. ccxt/zaif.py +725 -0
  767. ccxt/zonda.py +1828 -0
  768. ccxt_ir-4.3.46.0.1.dist-info/LICENSE.txt +21 -0
  769. ccxt_ir-4.3.46.0.1.dist-info/METADATA +655 -0
  770. ccxt_ir-4.3.46.0.1.dist-info/RECORD +772 -0
  771. ccxt_ir-4.3.46.0.1.dist-info/WHEEL +6 -0
  772. ccxt_ir-4.3.46.0.1.dist-info/top_level.txt +1 -0
ccxt/gemini.py ADDED
@@ -0,0 +1,1824 @@
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.gemini import ImplicitAPI
8
+ import hashlib
9
+ from ccxt.base.types import Balances, Currencies, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFees, 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 InsufficientFunds
17
+ from ccxt.base.errors import InvalidOrder
18
+ from ccxt.base.errors import OrderNotFound
19
+ from ccxt.base.errors import NotSupported
20
+ from ccxt.base.errors import RateLimitExceeded
21
+ from ccxt.base.errors import ExchangeNotAvailable
22
+ from ccxt.base.errors import OnMaintenance
23
+ from ccxt.base.errors import InvalidNonce
24
+ from ccxt.base.decimal_to_precision import TICK_SIZE
25
+ from ccxt.base.precise import Precise
26
+
27
+
28
+ class gemini(Exchange, ImplicitAPI):
29
+
30
+ def describe(self):
31
+ return self.deep_extend(super(gemini, self).describe(), {
32
+ 'id': 'gemini',
33
+ 'name': 'Gemini',
34
+ 'countries': ['US'],
35
+ # 600 requests a minute = 10 requests per second => 1000ms / 10 = 100ms between requests(private endpoints)
36
+ # 120 requests a minute = 2 requests per second =>( 1000ms / rateLimit ) / 2 = 5(public endpoints)
37
+ 'rateLimit': 100,
38
+ 'version': 'v1',
39
+ 'pro': True,
40
+ 'has': {
41
+ 'CORS': None,
42
+ 'spot': True,
43
+ 'margin': False,
44
+ 'swap': True,
45
+ 'future': False,
46
+ 'option': False,
47
+ 'addMargin': False,
48
+ 'cancelOrder': True,
49
+ 'closeAllPositions': False,
50
+ 'closePosition': False,
51
+ 'createDepositAddress': True,
52
+ 'createMarketOrder': False,
53
+ 'createOrder': True,
54
+ 'createReduceOnlyOrder': False,
55
+ 'fetchBalance': True,
56
+ 'fetchBidsAsks': False,
57
+ 'fetchBorrowRateHistories': False,
58
+ 'fetchBorrowRateHistory': False,
59
+ 'fetchClosedOrders': False,
60
+ 'fetchCrossBorrowRate': False,
61
+ 'fetchCrossBorrowRates': False,
62
+ 'fetchCurrencies': True,
63
+ 'fetchDepositAddress': True,
64
+ 'fetchDepositAddressesByNetwork': True,
65
+ 'fetchDepositsWithdrawals': True,
66
+ 'fetchFundingHistory': False,
67
+ 'fetchFundingRate': False,
68
+ 'fetchFundingRateHistory': False,
69
+ 'fetchFundingRates': False,
70
+ 'fetchIndexOHLCV': False,
71
+ 'fetchIsolatedBorrowRate': False,
72
+ 'fetchIsolatedBorrowRates': False,
73
+ 'fetchLeverage': False,
74
+ 'fetchLeverageTiers': False,
75
+ 'fetchMarginMode': False,
76
+ 'fetchMarkets': True,
77
+ 'fetchMarkOHLCV': False,
78
+ 'fetchMyTrades': True,
79
+ 'fetchOHLCV': True,
80
+ 'fetchOpenInterestHistory': False,
81
+ 'fetchOpenOrders': True,
82
+ 'fetchOrder': True,
83
+ 'fetchOrderBook': True,
84
+ 'fetchOrders': False,
85
+ 'fetchPosition': False,
86
+ 'fetchPositionMode': False,
87
+ 'fetchPositions': False,
88
+ 'fetchPositionsRisk': False,
89
+ 'fetchPremiumIndexOHLCV': False,
90
+ 'fetchTicker': True,
91
+ 'fetchTickers': True,
92
+ 'fetchTrades': True,
93
+ 'fetchTradingFee': False,
94
+ 'fetchTradingFees': True,
95
+ 'fetchTransactions': 'emulated',
96
+ 'postOnly': True,
97
+ 'reduceMargin': False,
98
+ 'sandbox': True,
99
+ 'setLeverage': False,
100
+ 'setMarginMode': False,
101
+ 'setPositionMode': False,
102
+ 'withdraw': True,
103
+ },
104
+ 'urls': {
105
+ 'logo': 'https://user-images.githubusercontent.com/1294454/27816857-ce7be644-6096-11e7-82d6-3c257263229c.jpg',
106
+ 'api': {
107
+ 'public': 'https://api.gemini.com',
108
+ 'private': 'https://api.gemini.com',
109
+ 'web': 'https://docs.gemini.com',
110
+ 'webExchange': 'https://exchange.gemini.com',
111
+ },
112
+ 'www': 'https://gemini.com/',
113
+ 'doc': [
114
+ 'https://docs.gemini.com/rest-api',
115
+ 'https://docs.sandbox.gemini.com',
116
+ ],
117
+ 'test': {
118
+ 'public': 'https://api.sandbox.gemini.com',
119
+ 'private': 'https://api.sandbox.gemini.com',
120
+ # use the True doc instead of the sandbox doc
121
+ # since they differ in parsing
122
+ # https://github.com/ccxt/ccxt/issues/7874
123
+ # https://github.com/ccxt/ccxt/issues/7894
124
+ 'web': 'https://docs.gemini.com',
125
+ 'webExchange': 'https://exchange.gemini.com',
126
+ },
127
+ 'fees': [
128
+ 'https://gemini.com/api-fee-schedule',
129
+ 'https://gemini.com/trading-fees',
130
+ 'https://gemini.com/transfer-fees',
131
+ ],
132
+ },
133
+ 'api': {
134
+ 'webExchange': {
135
+ 'get': [
136
+ '',
137
+ ],
138
+ },
139
+ 'web': {
140
+ 'get': [
141
+ 'rest-api',
142
+ ],
143
+ },
144
+ 'public': {
145
+ 'get': {
146
+ 'v1/symbols': 5,
147
+ 'v1/symbols/details/{symbol}': 5,
148
+ 'v1/staking/rates': 5,
149
+ 'v1/pubticker/{symbol}': 5,
150
+ 'v2/ticker/{symbol}': 5,
151
+ 'v2/candles/{symbol}/{timeframe}': 5,
152
+ 'v1/trades/{symbol}': 5,
153
+ 'v1/auction/{symbol}': 5,
154
+ 'v1/auction/{symbol}/history': 5,
155
+ 'v1/pricefeed': 5,
156
+ 'v1/book/{symbol}': 5,
157
+ 'v1/earn/rates': 5,
158
+ },
159
+ },
160
+ 'private': {
161
+ 'post': {
162
+ 'v1/staking/unstake': 1,
163
+ 'v1/staking/stake': 1,
164
+ 'v1/staking/rewards': 1,
165
+ 'v1/staking/history': 1,
166
+ 'v1/order/new': 1,
167
+ 'v1/order/cancel': 1,
168
+ 'v1/wrap/{symbol}': 1,
169
+ 'v1/order/cancel/session': 1,
170
+ 'v1/order/cancel/all': 1,
171
+ 'v1/order/status': 1,
172
+ 'v1/orders': 1,
173
+ 'v1/mytrades': 1,
174
+ 'v1/notionalvolume': 1,
175
+ 'v1/tradevolume': 1,
176
+ 'v1/clearing/new': 1,
177
+ 'v1/clearing/status': 1,
178
+ 'v1/clearing/cancel': 1,
179
+ 'v1/clearing/confirm': 1,
180
+ 'v1/balances': 1,
181
+ 'v1/balances/staking': 1,
182
+ 'v1/notionalbalances/{currency}': 1,
183
+ 'v1/transfers': 1,
184
+ 'v1/addresses/{network}': 1,
185
+ 'v1/deposit/{network}/newAddress': 1,
186
+ 'v1/deposit/{currency}/newAddress': 1,
187
+ 'v1/withdraw/{currency}': 1,
188
+ 'v1/account/transfer/{currency}': 1,
189
+ 'v1/payments/addbank': 1,
190
+ 'v1/payments/methods': 1,
191
+ 'v1/payments/sen/withdraw': 1,
192
+ 'v1/balances/earn': 1,
193
+ 'v1/earn/interest': 1,
194
+ 'v1/earn/history': 1,
195
+ 'v1/approvedAddresses/{network}/request': 1,
196
+ 'v1/approvedAddresses/account/{network}': 1,
197
+ 'v1/approvedAddresses/{network}/remove': 1,
198
+ 'v1/account': 1,
199
+ 'v1/account/create': 1,
200
+ 'v1/account/list': 1,
201
+ 'v1/heartbeat': 1,
202
+ },
203
+ },
204
+ },
205
+ 'precisionMode': TICK_SIZE,
206
+ 'fees': {
207
+ 'trading': {
208
+ 'taker': 0.004,
209
+ 'maker': 0.002,
210
+ },
211
+ },
212
+ 'httpExceptions': {
213
+ '400': BadRequest, # Auction not open or paused, ineligible timing, market not open, or the request was malformed, in the case of a private API request, missing or malformed Gemini private API authentication headers
214
+ '403': PermissionDenied, # The API key is missing the role necessary to access self private API endpoint
215
+ '404': OrderNotFound, # Unknown API entry point or Order not found
216
+ '406': InsufficientFunds, # Insufficient Funds
217
+ '429': RateLimitExceeded, # Rate Limiting was applied
218
+ '500': ExchangeError, # The server encountered an error
219
+ '502': ExchangeNotAvailable, # Technical issues are preventing the request from being satisfied
220
+ '503': OnMaintenance, # The exchange is down for maintenance
221
+ },
222
+ 'timeframes': {
223
+ '1m': '1m',
224
+ '5m': '5m',
225
+ '15m': '15m',
226
+ '30m': '30m',
227
+ '1h': '1hr',
228
+ '6h': '6hr',
229
+ '1d': '1day',
230
+ },
231
+ 'exceptions': {
232
+ 'exact': {
233
+ 'AuctionNotOpen': BadRequest, # Failed to place an auction-only order because there is no current auction open for self symbol
234
+ 'ClientOrderIdTooLong': BadRequest, # The Client Order ID must be under 100 characters
235
+ 'ClientOrderIdMustBeString': BadRequest, # The Client Order ID must be a string
236
+ 'ConflictingOptions': BadRequest, # New orders using a combination of order execution options are not supported
237
+ 'EndpointMismatch': BadRequest, # The request was submitted to an endpoint different than the one in the payload
238
+ 'EndpointNotFound': BadRequest, # No endpoint was specified
239
+ 'IneligibleTiming': BadRequest, # Failed to place an auction order for the current auction on self symbol because the timing is not eligible, new orders may only be placed before the auction begins.
240
+ 'InsufficientFunds': InsufficientFunds, # The order was rejected because of insufficient funds
241
+ 'InvalidJson': BadRequest, # The JSON provided is invalid
242
+ 'InvalidNonce': InvalidNonce, # The nonce was not greater than the previously used nonce, or was not present
243
+ 'InvalidApiKey': AuthenticationError, # Invalid API key
244
+ 'InvalidOrderType': InvalidOrder, # An unknown order type was provided
245
+ 'InvalidPrice': InvalidOrder, # For new orders, the price was invalid
246
+ 'InvalidQuantity': InvalidOrder, # A negative or otherwise invalid quantity was specified
247
+ 'InvalidSide': InvalidOrder, # For new orders, and invalid side was specified
248
+ 'InvalidSignature': AuthenticationError, # The signature did not match the expected signature
249
+ 'InvalidSymbol': BadRequest, # An invalid symbol was specified
250
+ 'InvalidTimestampInPayload': BadRequest, # The JSON payload contained a timestamp parameter with an unsupported value.
251
+ 'Maintenance': OnMaintenance, # The system is down for maintenance
252
+ 'MarketNotOpen': InvalidOrder, # The order was rejected because the market is not accepting new orders
253
+ 'MissingApikeyHeader': AuthenticationError, # The X-GEMINI-APIKEY header was missing
254
+ 'MissingOrderField': InvalidOrder, # A required order_id field was not specified
255
+ 'MissingRole': AuthenticationError, # The API key used to access self endpoint does not have the required role assigned to it
256
+ 'MissingPayloadHeader': AuthenticationError, # The X-GEMINI-PAYLOAD header was missing
257
+ 'MissingSignatureHeader': AuthenticationError, # The X-GEMINI-SIGNATURE header was missing
258
+ 'NoSSL': AuthenticationError, # You must use HTTPS to access the API
259
+ 'OptionsMustBeArray': BadRequest, # The options parameter must be an array.
260
+ 'OrderNotFound': OrderNotFound, # The order specified was not found
261
+ 'RateLimit': RateLimitExceeded, # Requests were made too frequently. See Rate Limits below.
262
+ 'System': ExchangeError, # We are experiencing technical issues
263
+ 'UnsupportedOption': BadRequest, # This order execution option is not supported.
264
+ },
265
+ 'broad': {
266
+ 'The Gemini Exchange is currently undergoing maintenance.': OnMaintenance, # The Gemini Exchange is currently undergoing maintenance. Please check https://status.gemini.com/ for more information.
267
+ 'We are investigating technical issues with the Gemini Exchange.': ExchangeNotAvailable, # We are investigating technical issues with the Gemini Exchange. Please check https://status.gemini.com/ for more information.
268
+ 'Internal Server Error': ExchangeNotAvailable,
269
+ },
270
+ },
271
+ 'options': {
272
+ 'fetchMarketsMethod': 'fetch_markets_from_api', # fetch_markets_from_api, fetch_markets_from_web
273
+ 'fetchMarketFromWebRetries': 10,
274
+ 'fetchMarketsFromAPI': {
275
+ 'fetchDetailsForAllSymbols': False,
276
+ 'quoteCurrencies': ['USDT', 'GUSD', 'USD', 'DAI', 'EUR', 'GBP', 'SGD', 'BTC', 'ETH', 'LTC', 'BCH'],
277
+ },
278
+ 'fetchMarkets': {
279
+ 'webApiEnable': True, # fetches from WEB
280
+ 'webApiRetries': 10,
281
+ },
282
+ 'fetchUsdtMarkets': ['btcusdt', 'ethusdt'], # self is only used if markets-fetch is set from "web"; keep self list updated(not available trough web api)
283
+ 'fetchCurrencies': {
284
+ 'webApiEnable': True, # fetches from WEB
285
+ 'webApiRetries': 5,
286
+ 'webApiMuteFailure': True,
287
+ },
288
+ 'fetchTickerMethod': 'fetchTickerV1', # fetchTickerV1, fetchTickerV2, fetchTickerV1AndV2
289
+ 'networks': {
290
+ 'BTC': 'bitcoin',
291
+ 'ERC20': 'ethereum',
292
+ 'BCH': 'bitcoincash',
293
+ 'LTC': 'litecoin',
294
+ 'ZEC': 'zcash',
295
+ 'FIL': 'filecoin',
296
+ 'DOGE': 'dogecoin',
297
+ 'XTZ': 'tezos',
298
+ 'AVAXX': 'avalanche',
299
+ 'SOL': 'solana',
300
+ 'ATOM': 'cosmos',
301
+ 'DOT': 'polkadot',
302
+ },
303
+ 'nonce': 'milliseconds', # if getting a Network 400 error change to seconds,
304
+ 'conflictingMarkets': {
305
+ 'paxgusd': {
306
+ 'base': 'PAXG',
307
+ 'quote': 'USD',
308
+ },
309
+ },
310
+ },
311
+ })
312
+
313
+ def fetch_currencies(self, params={}) -> Currencies:
314
+ """
315
+ fetches all available currencies on an exchange
316
+ :param dict [params]: extra parameters specific to the endpoint
317
+ :returns dict: an associative dictionary of currencies
318
+ """
319
+ return self.fetch_currencies_from_web(params)
320
+
321
+ def fetch_currencies_from_web(self, params={}):
322
+ """
323
+ * @ignore
324
+ fetches all available currencies on an exchange
325
+ :param dict [params]: extra parameters specific to the endpoint
326
+ :returns dict: an associative dictionary of currencies
327
+ """
328
+ data = self.fetch_web_endpoint('fetchCurrencies', 'webExchangeGet', True, '="currencyData">', '</script>')
329
+ if data is None:
330
+ return None
331
+ #
332
+ # {
333
+ # "tradingPairs": [['BTCUSD', 2, 8, '0.00001', 10, True], ...],
334
+ # "currencies": [
335
+ # ["ORCA", "Orca", 204, 6, 0, 6, 8, False, null, "solana"], #, precisions seem to be the 5th index
336
+ # ["ATOM", "Cosmos", 44, 6, 0, 6, 8, False, null, "cosmos"],
337
+ # ["ETH", "Ether", 2, 6, 0, 18, 8, False, null, "ethereum"],
338
+ # ["GBP", "Pound Sterling", 22, 2, 2, 2, 2, True, "£", null],
339
+ # ...
340
+ # ],
341
+ # "networks": [
342
+ # ["solana", "SOL", "Solana"],
343
+ # ["zcash", "ZEC", "Zcash"],
344
+ # ["tezos", "XTZ", "Tezos"],
345
+ # ["cosmos", "ATOM", "Cosmos"],
346
+ # ["ethereum", "ETH", "Ethereum"],
347
+ # ...
348
+ # ]
349
+ # }
350
+ #
351
+ result: dict = {}
352
+ self.options['tradingPairs'] = self.safe_list(data, 'tradingPairs')
353
+ currenciesArray = self.safe_value(data, 'currencies', [])
354
+ for i in range(0, len(currenciesArray)):
355
+ currency = currenciesArray[i]
356
+ id = self.safe_string(currency, 0)
357
+ code = self.safe_currency_code(id)
358
+ type = 'fiat' if self.safe_string(currency, 7) else 'crypto'
359
+ precision = self.parse_number(self.parse_precision(self.safe_string(currency, 5)))
360
+ networks: dict = {}
361
+ networkId = self.safe_string(currency, 9)
362
+ networkCode = None
363
+ if networkId is not None:
364
+ networkCode = self.network_id_to_code(networkId)
365
+ if networkCode is not None:
366
+ networks[networkCode] = {
367
+ 'info': currency,
368
+ 'id': networkId,
369
+ 'network': networkCode,
370
+ 'active': None,
371
+ 'deposit': None,
372
+ 'withdraw': None,
373
+ 'fee': None,
374
+ 'precision': precision,
375
+ 'limits': {
376
+ 'deposit': {
377
+ 'min': None,
378
+ 'max': None,
379
+ },
380
+ 'withdraw': {
381
+ 'min': None,
382
+ 'max': None,
383
+ },
384
+ },
385
+ }
386
+ result[code] = {
387
+ 'info': currency,
388
+ 'id': id,
389
+ 'code': code,
390
+ 'name': self.safe_string(currency, 1),
391
+ 'active': None,
392
+ 'deposit': None,
393
+ 'withdraw': None,
394
+ 'fee': None,
395
+ 'type': type,
396
+ 'precision': precision,
397
+ 'limits': {
398
+ 'deposit': {
399
+ 'min': None,
400
+ 'max': None,
401
+ },
402
+ 'withdraw': {
403
+ 'min': None,
404
+ 'max': None,
405
+ },
406
+ },
407
+ 'networks': networks,
408
+ }
409
+ return result
410
+
411
+ def fetch_markets(self, params={}) -> List[Market]:
412
+ """
413
+ retrieves data on all markets for gemini
414
+ :see: https://docs.gemini.com/rest-api/#symbols
415
+ :param dict [params]: extra parameters specific to the exchange API endpoint
416
+ :returns dict[]: an array of objects representing market data
417
+ """
418
+ method = self.safe_value(self.options, 'fetchMarketsMethod', 'fetch_markets_from_api')
419
+ if method == 'fetch_markets_from_web':
420
+ promises = []
421
+ promises.append(self.fetch_markets_from_web(params)) # get usd markets
422
+ promises.append(self.fetch_usdt_markets(params)) # get usdt markets
423
+ promisesResult = promises
424
+ return self.array_concat(promisesResult[0], promisesResult[1])
425
+ return self.fetch_markets_from_api(params)
426
+
427
+ def fetch_markets_from_web(self, params={}):
428
+ data = self.fetch_web_endpoint('fetchMarkets', 'webGetRestApi', False, '<h1 id="symbols-and-minimums">Symbols and minimums</h1>')
429
+ error = self.id + ' fetchMarketsFromWeb() the API doc HTML markup has changed, breaking the parser of order limits and precision info for markets.'
430
+ tables = data.split('tbody>')
431
+ numTables = len(tables)
432
+ if numTables < 2:
433
+ raise NotSupported(error)
434
+ rows = tables[1].split("\n<tr>\n") # eslint-disable-line quotes
435
+ numRows = len(rows)
436
+ if numRows < 2:
437
+ raise NotSupported(error)
438
+ result = []
439
+ # skip the first element(empty string)
440
+ for i in range(1, numRows):
441
+ row = rows[i]
442
+ cells = row.split("</td>\n") # eslint-disable-line quotes
443
+ numCells = len(cells)
444
+ if numCells < 5:
445
+ raise NotSupported(error)
446
+ # [
447
+ # '<td>btcusd', # currency
448
+ # '<td>0.00001 BTC(1e-5)', # min order size
449
+ # '<td>0.00000001 BTC(1e-8)', # tick size
450
+ # '<td>0.01 USD', # quote currency price increment
451
+ # '</tr>'
452
+ # ]
453
+ marketId = cells[0].replace('<td>', '')
454
+ marketId = marketId.replace('*', '')
455
+ # base = self.safe_currency_code(baseId)
456
+ minAmountString = cells[1].replace('<td>', '')
457
+ minAmountParts = minAmountString.split(' ')
458
+ minAmount = self.safe_number(minAmountParts, 0)
459
+ amountPrecisionString = cells[2].replace('<td>', '')
460
+ amountPrecisionParts = amountPrecisionString.split(' ')
461
+ idLength = len(marketId) - 0
462
+ startingIndex = idLength - 3
463
+ pricePrecisionString = cells[3].replace('<td>', '')
464
+ pricePrecisionParts = pricePrecisionString.split(' ')
465
+ quoteId = self.safe_string_lower(pricePrecisionParts, 1, marketId[startingIndex:idLength])
466
+ baseId = self.safe_string_lower(amountPrecisionParts, 1, marketId.replace(quoteId, ''))
467
+ base = self.safe_currency_code(baseId)
468
+ quote = self.safe_currency_code(quoteId)
469
+ result.append({
470
+ 'id': marketId,
471
+ 'symbol': base + '/' + quote,
472
+ 'base': base,
473
+ 'quote': quote,
474
+ 'settle': None,
475
+ 'baseId': baseId,
476
+ 'quoteId': quoteId,
477
+ 'settleId': None,
478
+ 'type': 'spot',
479
+ 'spot': True,
480
+ 'margin': False,
481
+ 'swap': False,
482
+ 'future': False,
483
+ 'option': False,
484
+ 'active': None,
485
+ 'contract': False,
486
+ 'linear': None,
487
+ 'inverse': None,
488
+ 'contractSize': None,
489
+ 'expiry': None,
490
+ 'expiryDatetime': None,
491
+ 'strike': None,
492
+ 'optionType': None,
493
+ 'precision': {
494
+ 'amount': self.safe_number(amountPrecisionParts, 0),
495
+ 'price': self.safe_number(pricePrecisionParts, 0),
496
+ },
497
+ 'limits': {
498
+ 'leverage': {
499
+ 'min': None,
500
+ 'max': None,
501
+ },
502
+ 'amount': {
503
+ 'min': minAmount,
504
+ 'max': None,
505
+ },
506
+ 'price': {
507
+ 'min': None,
508
+ 'max': None,
509
+ },
510
+ 'cost': {
511
+ 'min': None,
512
+ 'max': None,
513
+ },
514
+ },
515
+ 'created': None,
516
+ 'info': row,
517
+ })
518
+ return result
519
+
520
+ def parse_market_active(self, status):
521
+ statuses: dict = {
522
+ 'open': True,
523
+ 'closed': False,
524
+ 'cancel_only': True,
525
+ 'post_only': True,
526
+ 'limit_only': True,
527
+ }
528
+ if status is None:
529
+ return True # below
530
+ return self.safe_bool(statuses, status, True)
531
+
532
+ def fetch_usdt_markets(self, params={}):
533
+ # these markets can't be scrapped and fetchMarketsFrom api does an extra call
534
+ # to load market ids which we don't need here
535
+ if 'test' in self.urls:
536
+ return [] # sandbox does not have usdt markets
537
+ fetchUsdtMarkets = self.safe_value(self.options, 'fetchUsdtMarkets', [])
538
+ result = []
539
+ for i in range(0, len(fetchUsdtMarkets)):
540
+ marketId = fetchUsdtMarkets[i]
541
+ request: dict = {
542
+ 'symbol': marketId,
543
+ }
544
+ # don't use Promise.all here, for some reason the exchange can't handle it and crashes
545
+ rawResponse = self.publicGetV1SymbolsDetailsSymbol(self.extend(request, params))
546
+ result.append(self.parse_market(rawResponse))
547
+ return result
548
+
549
+ def fetch_markets_from_api(self, params={}):
550
+ marketIdsRaw = self.publicGetV1Symbols(params)
551
+ #
552
+ # [
553
+ # "btcusd",
554
+ # "linkusd",
555
+ # ...
556
+ # ]
557
+ #
558
+ result = []
559
+ options = self.safe_dict(self.options, 'fetchMarketsFromAPI', {})
560
+ bugSymbol = 'efilfil' # we skip self inexistent test symbol, which bugs other functions
561
+ marketIds = []
562
+ for i in range(0, len(marketIdsRaw)):
563
+ if marketIdsRaw[i] != bugSymbol:
564
+ marketIds.append(marketIdsRaw[i])
565
+ if self.safe_bool(options, 'fetchDetailsForAllSymbols', False):
566
+ promises = []
567
+ for i in range(0, len(marketIds)):
568
+ marketId = marketIds[i]
569
+ request: dict = {
570
+ 'symbol': marketId,
571
+ }
572
+ promises.append(self.publicGetV1SymbolsDetailsSymbol(self.extend(request, params)))
573
+ #
574
+ # {
575
+ # "symbol": "BTCUSD",
576
+ # "base_currency": "BTC",
577
+ # "quote_currency": "USD",
578
+ # "tick_size": 1E-8,
579
+ # "quote_increment": 0.01,
580
+ # "min_order_size": "0.00001",
581
+ # "status": "open",
582
+ # "wrap_enabled": False
583
+ # }
584
+ #
585
+ responses = promises
586
+ for i in range(0, len(responses)):
587
+ result.append(self.parse_market(responses[i]))
588
+ else:
589
+ # use trading-pairs info, if it was fetched
590
+ tradingPairs = self.safe_list(self.options, 'tradingPairs')
591
+ if tradingPairs is not None:
592
+ indexedTradingPairs = self.index_by(tradingPairs, 0)
593
+ for i in range(0, len(marketIds)):
594
+ marketId = marketIds[i]
595
+ tradingPair = self.safe_list(indexedTradingPairs, marketId.upper())
596
+ if tradingPair is not None:
597
+ result.append(self.parse_market(tradingPair))
598
+ else:
599
+ for i in range(0, len(marketIds)):
600
+ result.append(self.parse_market(marketIds[i]))
601
+ return result
602
+
603
+ def parse_market(self, response) -> Market:
604
+ #
605
+ # response might be:
606
+ #
607
+ # btcusd
608
+ #
609
+ # or
610
+ #
611
+ # [
612
+ # 'BTCUSD', # symbol
613
+ # 2, # priceTickDecimalPlaces
614
+ # 8, # quantityTickDecimalPlaces
615
+ # '0.00001', # quantityMinimum
616
+ # 10, # quantityRoundDecimalPlaces
617
+ # True # minimumsAreInclusive
618
+ # ],
619
+ #
620
+ # or
621
+ #
622
+ # {
623
+ # "symbol": "BTCUSD", # perpetuals have 'PERP' suffix, i.e. DOGEUSDPERP
624
+ # "base_currency": "BTC",
625
+ # "quote_currency": "USD",
626
+ # "tick_size": 1E-8,
627
+ # "quote_increment": 0.01,
628
+ # "min_order_size": "0.00001",
629
+ # "status": "open",
630
+ # "wrap_enabled": False
631
+ # "product_type": "swap", # only in perps
632
+ # "contract_type": "linear", # only in perps
633
+ # "contract_price_currency": "GUSD" # only in perps
634
+ # }
635
+ #
636
+ marketId = None
637
+ baseId = None
638
+ quoteId = None
639
+ settleId = None
640
+ tickSize = None
641
+ amountPrecision = None
642
+ minSize = None
643
+ status = None
644
+ swap = False
645
+ contractSize = None
646
+ linear = None
647
+ inverse = None
648
+ isString = (isinstance(response, str))
649
+ isArray = (isinstance(response, list))
650
+ if not isString and not isArray:
651
+ marketId = self.safe_string_lower(response, 'symbol')
652
+ amountPrecision = self.safe_number(response, 'tick_size') # right, exchange has an imperfect naming and self turns out to be an amount-precision
653
+ tickSize = self.safe_number(response, 'quote_increment') # self is tick-size actually
654
+ minSize = self.safe_number(response, 'min_order_size')
655
+ status = self.parse_market_active(self.safe_string(response, 'status'))
656
+ baseId = self.safe_string(response, 'base_currency')
657
+ quoteId = self.safe_string(response, 'quote_currency')
658
+ settleId = self.safe_string(response, 'contract_price_currency')
659
+ else:
660
+ # if no detailed API was called, then parse either string or array
661
+ if isString:
662
+ marketId = response
663
+ else:
664
+ marketId = self.safe_string_lower(response, 0)
665
+ tickSize = self.parse_number(self.parse_precision(self.safe_string(response, 1))) # priceTickDecimalPlaces
666
+ amountPrecision = self.parse_number(self.parse_precision(self.safe_string(response, 2))) # quantityTickDecimalPlaces
667
+ minSize = self.safe_number(response, 3) # quantityMinimum
668
+ marketIdUpper = marketId.upper()
669
+ isPerp = (marketIdUpper.find('PERP') >= 0)
670
+ marketIdWithoutPerp = marketIdUpper.replace('PERP', '')
671
+ conflictingMarkets = self.safe_dict(self.options, 'conflictingMarkets', {})
672
+ lowerCaseId = marketIdWithoutPerp.lower()
673
+ if lowerCaseId in conflictingMarkets:
674
+ conflictingMarket = conflictingMarkets[lowerCaseId]
675
+ baseId = conflictingMarket['base']
676
+ quoteId = conflictingMarket['quote']
677
+ if isPerp:
678
+ settleId = conflictingMarket['quote']
679
+ else:
680
+ quoteCurrencies = self.handle_option('fetchMarketsFromAPI', 'quoteCurrencies', [])
681
+ for i in range(0, len(quoteCurrencies)):
682
+ quoteCurrency = quoteCurrencies[i]
683
+ if marketIdWithoutPerp.endswith(quoteCurrency):
684
+ quoteLength = self.parse_to_int(-1 * len(quoteCurrency))
685
+ baseId = marketIdWithoutPerp[0:quoteLength]
686
+ quoteId = quoteCurrency
687
+ if isPerp:
688
+ settleId = quoteCurrency # always same
689
+ break
690
+ base = self.safe_currency_code(baseId)
691
+ quote = self.safe_currency_code(quoteId)
692
+ settle = self.safe_currency_code(settleId)
693
+ symbol = base + '/' + quote
694
+ if settleId is not None:
695
+ symbol = symbol + ':' + settle
696
+ swap = True
697
+ contractSize = tickSize # always same
698
+ linear = True # always linear
699
+ inverse = False
700
+ type = 'swap' if swap else 'spot'
701
+ return {
702
+ 'id': marketId,
703
+ 'symbol': symbol,
704
+ 'base': base,
705
+ 'quote': quote,
706
+ 'settle': settle,
707
+ 'baseId': baseId,
708
+ 'quoteId': quoteId,
709
+ 'settleId': settleId,
710
+ 'type': type,
711
+ 'spot': not swap,
712
+ 'margin': False,
713
+ 'swap': swap,
714
+ 'future': False,
715
+ 'option': False,
716
+ 'active': status,
717
+ 'contract': swap,
718
+ 'linear': linear,
719
+ 'inverse': inverse,
720
+ 'contractSize': contractSize,
721
+ 'expiry': None,
722
+ 'expiryDatetime': None,
723
+ 'strike': None,
724
+ 'optionType': None,
725
+ 'precision': {
726
+ 'price': tickSize,
727
+ 'amount': amountPrecision,
728
+ },
729
+ 'limits': {
730
+ 'leverage': {
731
+ 'min': None,
732
+ 'max': None,
733
+ },
734
+ 'amount': {
735
+ 'min': minSize,
736
+ 'max': None,
737
+ },
738
+ 'price': {
739
+ 'min': None,
740
+ 'max': None,
741
+ },
742
+ 'cost': {
743
+ 'min': None,
744
+ 'max': None,
745
+ },
746
+ },
747
+ 'created': None,
748
+ 'info': response,
749
+ }
750
+
751
+ def fetch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
752
+ """
753
+ fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
754
+ :see: https://docs.gemini.com/rest-api/#current-order-book
755
+ :param str symbol: unified symbol of the market to fetch the order book for
756
+ :param int [limit]: the maximum amount of order book entries to return
757
+ :param dict [params]: extra parameters specific to the exchange API endpoint
758
+ :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
759
+ """
760
+ self.load_markets()
761
+ market = self.market(symbol)
762
+ request: dict = {
763
+ 'symbol': market['id'],
764
+ }
765
+ if limit is not None:
766
+ request['limit_bids'] = limit
767
+ request['limit_asks'] = limit
768
+ response = self.publicGetV1BookSymbol(self.extend(request, params))
769
+ return self.parse_order_book(response, market['symbol'], None, 'bids', 'asks', 'price', 'amount')
770
+
771
+ def fetch_ticker_v1(self, symbol: str, params={}):
772
+ self.load_markets()
773
+ market = self.market(symbol)
774
+ request: dict = {
775
+ 'symbol': market['id'],
776
+ }
777
+ response = self.publicGetV1PubtickerSymbol(self.extend(request, params))
778
+ #
779
+ # {
780
+ # "bid":"9117.95",
781
+ # "ask":"9117.96",
782
+ # "volume":{
783
+ # "BTC":"1615.46861748",
784
+ # "USD":"14727307.57545006088",
785
+ # "timestamp":1594982700000
786
+ # },
787
+ # "last":"9115.23"
788
+ # }
789
+ #
790
+ return self.parse_ticker(response, market)
791
+
792
+ def fetch_ticker_v2(self, symbol: str, params={}):
793
+ self.load_markets()
794
+ market = self.market(symbol)
795
+ request: dict = {
796
+ 'symbol': market['id'],
797
+ }
798
+ response = self.publicGetV2TickerSymbol(self.extend(request, params))
799
+ #
800
+ # {
801
+ # "symbol":"BTCUSD",
802
+ # "open":"9080.58",
803
+ # "high":"9184.53",
804
+ # "low":"9063.56",
805
+ # "close":"9116.08",
806
+ # # Hourly prices descending for past 24 hours
807
+ # "changes":["9117.33","9105.69","9106.23","9120.35","9098.57","9114.53","9113.55","9128.01","9113.63","9133.49","9133.49","9137.75","9126.73","9103.91","9119.33","9123.04","9124.44","9117.57","9114.22","9102.33","9076.67","9074.72","9074.97","9092.05"],
808
+ # "bid":"9115.86",
809
+ # "ask":"9115.87"
810
+ # }
811
+ #
812
+ return self.parse_ticker(response, market)
813
+
814
+ def fetch_ticker_v1_and_v2(self, symbol: str, params={}):
815
+ tickerA = self.fetch_ticker_v1(symbol, params)
816
+ tickerB = self.fetch_ticker_v2(symbol, params)
817
+ return self.deep_extend(tickerA, {
818
+ 'open': tickerB['open'],
819
+ 'high': tickerB['high'],
820
+ 'low': tickerB['low'],
821
+ 'change': tickerB['change'],
822
+ 'percentage': tickerB['percentage'],
823
+ 'average': tickerB['average'],
824
+ 'info': tickerB['info'],
825
+ })
826
+
827
+ def fetch_ticker(self, symbol: str, params={}) -> Ticker:
828
+ """
829
+ fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
830
+ :see: https://docs.gemini.com/rest-api/#ticker
831
+ :see: https://docs.gemini.com/rest-api/#ticker-v2
832
+ :param str symbol: unified symbol of the market to fetch the ticker for
833
+ :param dict [params]: extra parameters specific to the exchange API endpoint
834
+ :param dict [params.fetchTickerMethod]: 'fetchTickerV2', 'fetchTickerV1' or 'fetchTickerV1AndV2' - 'fetchTickerV1' for original ccxt.gemini.fetchTicker - 'fetchTickerV1AndV2' for 2 api calls to get the result of both fetchTicker methods - default = 'fetchTickerV1'
835
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
836
+ """
837
+ method = self.safe_value(self.options, 'fetchTickerMethod', 'fetchTickerV1')
838
+ if method == 'fetchTickerV1':
839
+ return self.fetch_ticker_v1(symbol, params)
840
+ if method == 'fetchTickerV2':
841
+ return self.fetch_ticker_v2(symbol, params)
842
+ return self.fetch_ticker_v1_and_v2(symbol, params)
843
+
844
+ def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
845
+ #
846
+ # fetchTickers
847
+ #
848
+ # {
849
+ # "pair": "BATUSD",
850
+ # "price": "0.20687",
851
+ # "percentChange24h": "0.0146"
852
+ # }
853
+ #
854
+ # fetchTickerV1
855
+ #
856
+ # {
857
+ # "bid":"9117.95",
858
+ # "ask":"9117.96",
859
+ # "volume":{
860
+ # "BTC":"1615.46861748",
861
+ # "USD":"14727307.57545006088",
862
+ # "timestamp":1594982700000
863
+ # },
864
+ # "last":"9115.23"
865
+ # }
866
+ #
867
+ # fetchTickerV2
868
+ #
869
+ # {
870
+ # "symbol":"BTCUSD",
871
+ # "open":"9080.58",
872
+ # "high":"9184.53",
873
+ # "low":"9063.56",
874
+ # "close":"9116.08",
875
+ # # Hourly prices descending for past 24 hours
876
+ # "changes":["9117.33","9105.69","9106.23","9120.35","9098.57","9114.53","9113.55","9128.01","9113.63","9133.49","9133.49","9137.75","9126.73","9103.91","9119.33","9123.04","9124.44","9117.57","9114.22","9102.33","9076.67","9074.72","9074.97","9092.05"],
877
+ # "bid":"9115.86",
878
+ # "ask":"9115.87"
879
+ # }
880
+ #
881
+ volume = self.safe_value(ticker, 'volume', {})
882
+ timestamp = self.safe_integer(volume, 'timestamp')
883
+ symbol = None
884
+ marketId = self.safe_string_lower(ticker, 'pair')
885
+ market = self.safe_market(marketId, market)
886
+ baseId = None
887
+ quoteId = None
888
+ base = None
889
+ quote = None
890
+ if (marketId is not None) and (market is None):
891
+ idLength = len(marketId) - 0
892
+ if idLength == 7:
893
+ baseId = marketId[0:4]
894
+ quoteId = marketId[4:7]
895
+ else:
896
+ baseId = marketId[0:3]
897
+ quoteId = marketId[3:6]
898
+ base = self.safe_currency_code(baseId)
899
+ quote = self.safe_currency_code(quoteId)
900
+ symbol = base + '/' + quote
901
+ if (symbol is None) and (market is not None):
902
+ symbol = market['symbol']
903
+ baseId = self.safe_string_upper(market, 'baseId')
904
+ quoteId = self.safe_string_upper(market, 'quoteId')
905
+ price = self.safe_string(ticker, 'price')
906
+ last = self.safe_string_2(ticker, 'last', 'close', price)
907
+ percentage = self.safe_string(ticker, 'percentChange24h')
908
+ open = self.safe_string(ticker, 'open')
909
+ baseVolume = self.safe_string(volume, baseId)
910
+ quoteVolume = self.safe_string(volume, quoteId)
911
+ return self.safe_ticker({
912
+ 'symbol': symbol,
913
+ 'timestamp': timestamp,
914
+ 'datetime': self.iso8601(timestamp),
915
+ 'high': self.safe_string(ticker, 'high'),
916
+ 'low': self.safe_string(ticker, 'low'),
917
+ 'bid': self.safe_string(ticker, 'bid'),
918
+ 'bidVolume': None,
919
+ 'ask': self.safe_string(ticker, 'ask'),
920
+ 'askVolume': None,
921
+ 'vwap': None,
922
+ 'open': open,
923
+ 'close': last,
924
+ 'last': last,
925
+ 'previousClose': None, # previous day close
926
+ 'change': None,
927
+ 'percentage': percentage,
928
+ 'average': None,
929
+ 'baseVolume': baseVolume,
930
+ 'quoteVolume': quoteVolume,
931
+ 'info': ticker,
932
+ }, market)
933
+
934
+ def fetch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
935
+ """
936
+ fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
937
+ :see: https://docs.gemini.com/rest-api/#price-feed
938
+ :param str[]|None symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
939
+ :param dict [params]: extra parameters specific to the exchange API endpoint
940
+ :returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
941
+ """
942
+ self.load_markets()
943
+ response = self.publicGetV1Pricefeed(params)
944
+ #
945
+ # [
946
+ # {
947
+ # "pair": "BATUSD",
948
+ # "price": "0.20687",
949
+ # "percentChange24h": "0.0146"
950
+ # },
951
+ # {
952
+ # "pair": "LINKETH",
953
+ # "price": "0.018",
954
+ # "percentChange24h": "0.0000"
955
+ # },
956
+ # ]
957
+ #
958
+ return self.parse_tickers(response, symbols)
959
+
960
+ def parse_trade(self, trade: dict, market: Market = None) -> Trade:
961
+ #
962
+ # public fetchTrades
963
+ #
964
+ # {
965
+ # "timestamp":1601617445,
966
+ # "timestampms":1601617445144,
967
+ # "tid":14122489752,
968
+ # "price":"0.46476",
969
+ # "amount":"28.407209",
970
+ # "exchange":"gemini",
971
+ # "type":"buy"
972
+ # }
973
+ #
974
+ # private fetchTrades
975
+ #
976
+ # {
977
+ # "price":"3900.00",
978
+ # "amount":"0.00996",
979
+ # "timestamp":1638891173,
980
+ # "timestampms":1638891173518,
981
+ # "type":"Sell",
982
+ # "aggressor":false,
983
+ # "fee_currency":"EUR",
984
+ # "fee_amount":"0.00",
985
+ # "tid":73621746145,
986
+ # "order_id":"73621746059",
987
+ # "exchange":"gemini",
988
+ # "is_auction_fill":false,
989
+ # "is_clearing_fill":false,
990
+ # "symbol":"ETHEUR",
991
+ # "client_order_id":"1638891171610"
992
+ # }
993
+ #
994
+ timestamp = self.safe_integer(trade, 'timestampms')
995
+ id = self.safe_string(trade, 'tid')
996
+ orderId = self.safe_string(trade, 'order_id')
997
+ feeCurrencyId = self.safe_string(trade, 'fee_currency')
998
+ feeCurrencyCode = self.safe_currency_code(feeCurrencyId)
999
+ fee = {
1000
+ 'cost': self.safe_string(trade, 'fee_amount'),
1001
+ 'currency': feeCurrencyCode,
1002
+ }
1003
+ priceString = self.safe_string(trade, 'price')
1004
+ amountString = self.safe_string(trade, 'amount')
1005
+ side = self.safe_string_lower(trade, 'type')
1006
+ symbol = self.safe_symbol(None, market)
1007
+ return self.safe_trade({
1008
+ 'id': id,
1009
+ 'order': orderId,
1010
+ 'info': trade,
1011
+ 'timestamp': timestamp,
1012
+ 'datetime': self.iso8601(timestamp),
1013
+ 'symbol': symbol,
1014
+ 'type': None,
1015
+ 'side': side,
1016
+ 'takerOrMaker': None,
1017
+ 'price': priceString,
1018
+ 'cost': None,
1019
+ 'amount': amountString,
1020
+ 'fee': fee,
1021
+ }, market)
1022
+
1023
+ def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
1024
+ """
1025
+ get the list of most recent trades for a particular symbol
1026
+ :see: https://docs.gemini.com/rest-api/#trade-history
1027
+ :param str symbol: unified symbol of the market to fetch trades for
1028
+ :param int [since]: timestamp in ms of the earliest trade to fetch
1029
+ :param int [limit]: the maximum amount of trades to fetch
1030
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1031
+ :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
1032
+ """
1033
+ self.load_markets()
1034
+ market = self.market(symbol)
1035
+ request: dict = {
1036
+ 'symbol': market['id'],
1037
+ }
1038
+ if limit is not None:
1039
+ request['limit_trades'] = min(limit, 500)
1040
+ if since is not None:
1041
+ request['timestamp'] = since
1042
+ response = self.publicGetV1TradesSymbol(self.extend(request, params))
1043
+ #
1044
+ # [
1045
+ # {
1046
+ # "timestamp":1601617445,
1047
+ # "timestampms":1601617445144,
1048
+ # "tid":14122489752,
1049
+ # "price":"0.46476",
1050
+ # "amount":"28.407209",
1051
+ # "exchange":"gemini",
1052
+ # "type":"buy"
1053
+ # },
1054
+ # ]
1055
+ #
1056
+ return self.parse_trades(response, market, since, limit)
1057
+
1058
+ def parse_balance(self, response) -> Balances:
1059
+ result: dict = {'info': response}
1060
+ for i in range(0, len(response)):
1061
+ balance = response[i]
1062
+ currencyId = self.safe_string(balance, 'currency')
1063
+ code = self.safe_currency_code(currencyId)
1064
+ account = self.account()
1065
+ account['free'] = self.safe_string(balance, 'available')
1066
+ account['total'] = self.safe_string(balance, 'amount')
1067
+ result[code] = account
1068
+ return self.safe_balance(result)
1069
+
1070
+ def fetch_trading_fees(self, params={}) -> TradingFees:
1071
+ """
1072
+ fetch the trading fees for multiple markets
1073
+ :see: https://docs.gemini.com/rest-api/#get-notional-volume
1074
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1075
+ :returns dict: a dictionary of `fee structures <https://docs.ccxt.com/#/?id=fee-structure>` indexed by market symbols
1076
+ """
1077
+ self.load_markets()
1078
+ response = self.privatePostV1Notionalvolume(params)
1079
+ #
1080
+ # {
1081
+ # "web_maker_fee_bps": 25,
1082
+ # "web_taker_fee_bps": 35,
1083
+ # "web_auction_fee_bps": 25,
1084
+ # "api_maker_fee_bps": 10,
1085
+ # "api_taker_fee_bps": 35,
1086
+ # "api_auction_fee_bps": 20,
1087
+ # "fix_maker_fee_bps": 10,
1088
+ # "fix_taker_fee_bps": 35,
1089
+ # "fix_auction_fee_bps": 20,
1090
+ # "block_maker_fee_bps": 0,
1091
+ # "block_taker_fee_bps": 50,
1092
+ # "notional_30d_volume": 150.00,
1093
+ # "last_updated_ms": 1551371446000,
1094
+ # "date": "2019-02-28",
1095
+ # "notional_1d_volume": [
1096
+ # {
1097
+ # "date": "2019-02-22",
1098
+ # "notional_volume": 75.00
1099
+ # },
1100
+ # {
1101
+ # "date": "2019-02-14",
1102
+ # "notional_volume": 75.00
1103
+ # }
1104
+ # ]
1105
+ # }
1106
+ #
1107
+ makerBps = self.safe_string(response, 'api_maker_fee_bps')
1108
+ takerBps = self.safe_string(response, 'api_taker_fee_bps')
1109
+ makerString = Precise.string_div(makerBps, '10000')
1110
+ takerString = Precise.string_div(takerBps, '10000')
1111
+ maker = self.parse_number(makerString)
1112
+ taker = self.parse_number(takerString)
1113
+ result: dict = {}
1114
+ for i in range(0, len(self.symbols)):
1115
+ symbol = self.symbols[i]
1116
+ result[symbol] = {
1117
+ 'info': response,
1118
+ 'symbol': symbol,
1119
+ 'maker': maker,
1120
+ 'taker': taker,
1121
+ 'percentage': True,
1122
+ 'tierBased': True,
1123
+ }
1124
+ return result
1125
+
1126
+ def fetch_balance(self, params={}) -> Balances:
1127
+ """
1128
+ query for balance and get the amount of funds available for trading or funds locked in orders
1129
+ :see: https://docs.gemini.com/rest-api/#get-available-balances
1130
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1131
+ :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
1132
+ """
1133
+ self.load_markets()
1134
+ response = self.privatePostV1Balances(params)
1135
+ return self.parse_balance(response)
1136
+
1137
+ def parse_order(self, order: dict, market: Market = None) -> Order:
1138
+ #
1139
+ # createOrder(private)
1140
+ #
1141
+ # {
1142
+ # "order_id":"106027397702",
1143
+ # "id":"106027397702",
1144
+ # "symbol":"etheur",
1145
+ # "exchange":"gemini",
1146
+ # "avg_execution_price":"2877.48",
1147
+ # "side":"sell",
1148
+ # "type":"exchange limit",
1149
+ # "timestamp":"1650398122",
1150
+ # "timestampms":1650398122308,
1151
+ # "is_live":false,
1152
+ # "is_cancelled":false,
1153
+ # "is_hidden":false,
1154
+ # "was_forced":false,
1155
+ # "executed_amount":"0.014434",
1156
+ # "client_order_id":"1650398121695",
1157
+ # "options":[],
1158
+ # "price":"2800.00",
1159
+ # "original_amount":"0.014434",
1160
+ # "remaining_amount":"0"
1161
+ # }
1162
+ #
1163
+ # fetchOrder(private)
1164
+ #
1165
+ # {
1166
+ # "order_id":"106028543717",
1167
+ # "id":"106028543717",
1168
+ # "symbol":"etheur",
1169
+ # "exchange":"gemini",
1170
+ # "avg_execution_price":"0.00",
1171
+ # "side":"buy",
1172
+ # "type":"exchange limit",
1173
+ # "timestamp":"1650398446",
1174
+ # "timestampms":1650398446375,
1175
+ # "is_live":true,
1176
+ # "is_cancelled":false,
1177
+ # "is_hidden":false,
1178
+ # "was_forced":false,
1179
+ # "executed_amount":"0",
1180
+ # "client_order_id":"1650398445709",
1181
+ # "options":[],
1182
+ # "price":"2000.00",
1183
+ # "original_amount":"0.01",
1184
+ # "remaining_amount":"0.01"
1185
+ # }
1186
+ #
1187
+ # fetchOpenOrders(private)
1188
+ #
1189
+ # {
1190
+ # "order_id":"106028543717",
1191
+ # "id":"106028543717",
1192
+ # "symbol":"etheur",
1193
+ # "exchange":"gemini",
1194
+ # "avg_execution_price":"0.00",
1195
+ # "side":"buy",
1196
+ # "type":"exchange limit",
1197
+ # "timestamp":"1650398446",
1198
+ # "timestampms":1650398446375,
1199
+ # "is_live":true,
1200
+ # "is_cancelled":false,
1201
+ # "is_hidden":false,
1202
+ # "was_forced":false,
1203
+ # "executed_amount":"0",
1204
+ # "client_order_id":"1650398445709",
1205
+ # "options":[],
1206
+ # "price":"2000.00",
1207
+ # "original_amount":"0.01",
1208
+ # "remaining_amount":"0.01"
1209
+ # }
1210
+ #
1211
+ # cancelOrder(private)
1212
+ #
1213
+ # {
1214
+ # "order_id":"106028543717",
1215
+ # "id":"106028543717",
1216
+ # "symbol":"etheur",
1217
+ # "exchange":"gemini",
1218
+ # "avg_execution_price":"0.00",
1219
+ # "side":"buy",
1220
+ # "type":"exchange limit",
1221
+ # "timestamp":"1650398446",
1222
+ # "timestampms":1650398446375,
1223
+ # "is_live":false,
1224
+ # "is_cancelled":true,
1225
+ # "is_hidden":false,
1226
+ # "was_forced":false,
1227
+ # "executed_amount":"0",
1228
+ # "client_order_id":"1650398445709",
1229
+ # "reason":"Requested",
1230
+ # "options":[],
1231
+ # "price":"2000.00",
1232
+ # "original_amount":"0.01",
1233
+ # "remaining_amount":"0.01"
1234
+ # }
1235
+ #
1236
+ timestamp = self.safe_integer(order, 'timestampms')
1237
+ amount = self.safe_string(order, 'original_amount')
1238
+ remaining = self.safe_string(order, 'remaining_amount')
1239
+ filled = self.safe_string(order, 'executed_amount')
1240
+ status = 'closed'
1241
+ if order['is_live']:
1242
+ status = 'open'
1243
+ if order['is_cancelled']:
1244
+ status = 'canceled'
1245
+ price = self.safe_string(order, 'price')
1246
+ average = self.safe_string(order, 'avg_execution_price')
1247
+ type = self.safe_string(order, 'type')
1248
+ if type == 'exchange limit':
1249
+ type = 'limit'
1250
+ elif type == 'market buy' or type == 'market sell':
1251
+ type = 'market'
1252
+ else:
1253
+ type = order['type']
1254
+ fee = None
1255
+ marketId = self.safe_string(order, 'symbol')
1256
+ symbol = self.safe_symbol(marketId, market)
1257
+ id = self.safe_string(order, 'order_id')
1258
+ side = self.safe_string_lower(order, 'side')
1259
+ clientOrderId = self.safe_string(order, 'client_order_id')
1260
+ optionsArray = self.safe_value(order, 'options', [])
1261
+ option = self.safe_string(optionsArray, 0)
1262
+ timeInForce = 'GTC'
1263
+ postOnly = False
1264
+ if option is not None:
1265
+ if option == 'immediate-or-cancel':
1266
+ timeInForce = 'IOC'
1267
+ elif option == 'fill-or-kill':
1268
+ timeInForce = 'FOK'
1269
+ elif option == 'maker-or-cancel':
1270
+ timeInForce = 'PO'
1271
+ postOnly = True
1272
+ return self.safe_order({
1273
+ 'id': id,
1274
+ 'clientOrderId': clientOrderId,
1275
+ 'info': order,
1276
+ 'timestamp': timestamp,
1277
+ 'datetime': self.iso8601(timestamp),
1278
+ 'lastTradeTimestamp': None,
1279
+ 'status': status,
1280
+ 'symbol': symbol,
1281
+ 'type': type,
1282
+ 'timeInForce': timeInForce, # default set to GTC
1283
+ 'postOnly': postOnly,
1284
+ 'side': side,
1285
+ 'price': price,
1286
+ 'stopPrice': None,
1287
+ 'triggerPrice': None,
1288
+ 'average': average,
1289
+ 'cost': None,
1290
+ 'amount': amount,
1291
+ 'filled': filled,
1292
+ 'remaining': remaining,
1293
+ 'fee': fee,
1294
+ 'trades': None,
1295
+ }, market)
1296
+
1297
+ def fetch_order(self, id: str, symbol: Str = None, params={}):
1298
+ """
1299
+ fetches information on an order made by the user
1300
+ :see: https://docs.gemini.com/rest-api/#order-status
1301
+ :param str symbol: unified symbol of the market the order was made in
1302
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1303
+ :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1304
+ """
1305
+ self.load_markets()
1306
+ request: dict = {
1307
+ 'order_id': id,
1308
+ }
1309
+ response = self.privatePostV1OrderStatus(self.extend(request, params))
1310
+ #
1311
+ # {
1312
+ # "order_id":"106028543717",
1313
+ # "id":"106028543717",
1314
+ # "symbol":"etheur",
1315
+ # "exchange":"gemini",
1316
+ # "avg_execution_price":"0.00",
1317
+ # "side":"buy",
1318
+ # "type":"exchange limit",
1319
+ # "timestamp":"1650398446",
1320
+ # "timestampms":1650398446375,
1321
+ # "is_live":true,
1322
+ # "is_cancelled":false,
1323
+ # "is_hidden":false,
1324
+ # "was_forced":false,
1325
+ # "executed_amount":"0",
1326
+ # "client_order_id":"1650398445709",
1327
+ # "options":[],
1328
+ # "price":"2000.00",
1329
+ # "original_amount":"0.01",
1330
+ # "remaining_amount":"0.01"
1331
+ # }
1332
+ #
1333
+ return self.parse_order(response)
1334
+
1335
+ def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1336
+ """
1337
+ fetch all unfilled currently open orders
1338
+ :see: https://docs.gemini.com/rest-api/#get-active-orders
1339
+ :param str symbol: unified market symbol
1340
+ :param int [since]: the earliest time in ms to fetch open orders for
1341
+ :param int [limit]: the maximum number of open orders structures to retrieve
1342
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1343
+ :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1344
+ """
1345
+ self.load_markets()
1346
+ response = self.privatePostV1Orders(params)
1347
+ #
1348
+ # [
1349
+ # {
1350
+ # "order_id":"106028543717",
1351
+ # "id":"106028543717",
1352
+ # "symbol":"etheur",
1353
+ # "exchange":"gemini",
1354
+ # "avg_execution_price":"0.00",
1355
+ # "side":"buy",
1356
+ # "type":"exchange limit",
1357
+ # "timestamp":"1650398446",
1358
+ # "timestampms":1650398446375,
1359
+ # "is_live":true,
1360
+ # "is_cancelled":false,
1361
+ # "is_hidden":false,
1362
+ # "was_forced":false,
1363
+ # "executed_amount":"0",
1364
+ # "client_order_id":"1650398445709",
1365
+ # "options":[],
1366
+ # "price":"2000.00",
1367
+ # "original_amount":"0.01",
1368
+ # "remaining_amount":"0.01"
1369
+ # }
1370
+ # ]
1371
+ #
1372
+ market = None
1373
+ if symbol is not None:
1374
+ market = self.market(symbol) # throws on non-existent symbol
1375
+ return self.parse_orders(response, market, since, limit)
1376
+
1377
+ def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
1378
+ """
1379
+ create a trade order
1380
+ :see: https://docs.gemini.com/rest-api/#new-order
1381
+ :param str symbol: unified symbol of the market to create an order in
1382
+ :param str type: must be 'limit'
1383
+ :param str side: 'buy' or 'sell'
1384
+ :param float amount: how much of currency you want to trade in units of base currency
1385
+ :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
1386
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1387
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1388
+ """
1389
+ self.load_markets()
1390
+ if type != 'limit':
1391
+ raise ExchangeError(self.id + ' createOrder() allows limit orders only')
1392
+ clientOrderId = self.safe_string_2(params, 'clientOrderId', 'client_order_id')
1393
+ params = self.omit(params, ['clientOrderId', 'client_order_id'])
1394
+ if clientOrderId is None:
1395
+ clientOrderId = str(self.milliseconds())
1396
+ market = self.market(symbol)
1397
+ amountString = self.amount_to_precision(symbol, amount)
1398
+ priceString = self.price_to_precision(symbol, price)
1399
+ request: dict = {
1400
+ 'client_order_id': clientOrderId,
1401
+ 'symbol': market['id'],
1402
+ 'amount': amountString,
1403
+ 'price': priceString,
1404
+ 'side': side,
1405
+ 'type': 'exchange limit', # gemini allows limit orders only
1406
+ # 'options': [], one of: maker-or-cancel, immediate-or-cancel, fill-or-kill, auction-only, indication-of-interest
1407
+ }
1408
+ type = self.safe_string(params, 'type', type)
1409
+ params = self.omit(params, 'type')
1410
+ rawStopPrice = self.safe_string_2(params, 'stop_price', 'stopPrice')
1411
+ params = self.omit(params, ['stop_price', 'stopPrice', 'type'])
1412
+ if type == 'stopLimit':
1413
+ raise ArgumentsRequired(self.id + ' createOrder() requires a stopPrice parameter or a stop_price parameter for ' + type + ' orders')
1414
+ if rawStopPrice is not None:
1415
+ request['stop_price'] = self.price_to_precision(symbol, rawStopPrice)
1416
+ request['type'] = 'exchange stop limit'
1417
+ else:
1418
+ # No options can be applied to stop-limit orders at self time.
1419
+ timeInForce = self.safe_string(params, 'timeInForce')
1420
+ params = self.omit(params, 'timeInForce')
1421
+ if timeInForce is not None:
1422
+ if (timeInForce == 'IOC') or (timeInForce == 'immediate-or-cancel'):
1423
+ request['options'] = ['immediate-or-cancel']
1424
+ elif (timeInForce == 'FOK') or (timeInForce == 'fill-or-kill'):
1425
+ request['options'] = ['fill-or-kill']
1426
+ elif timeInForce == 'PO':
1427
+ request['options'] = ['maker-or-cancel']
1428
+ postOnly = self.safe_bool(params, 'postOnly', False)
1429
+ params = self.omit(params, 'postOnly')
1430
+ if postOnly:
1431
+ request['options'] = ['maker-or-cancel']
1432
+ # allowing override for auction-only and indication-of-interest order options
1433
+ options = self.safe_string(params, 'options')
1434
+ if options is not None:
1435
+ request['options'] = [options]
1436
+ response = self.privatePostV1OrderNew(self.extend(request, params))
1437
+ #
1438
+ # {
1439
+ # "order_id":"106027397702",
1440
+ # "id":"106027397702",
1441
+ # "symbol":"etheur",
1442
+ # "exchange":"gemini",
1443
+ # "avg_execution_price":"2877.48",
1444
+ # "side":"sell",
1445
+ # "type":"exchange limit",
1446
+ # "timestamp":"1650398122",
1447
+ # "timestampms":1650398122308,
1448
+ # "is_live":false,
1449
+ # "is_cancelled":false,
1450
+ # "is_hidden":false,
1451
+ # "was_forced":false,
1452
+ # "executed_amount":"0.014434",
1453
+ # "client_order_id":"1650398121695",
1454
+ # "options":[],
1455
+ # "price":"2800.00",
1456
+ # "original_amount":"0.014434",
1457
+ # "remaining_amount":"0"
1458
+ # }
1459
+ #
1460
+ return self.parse_order(response)
1461
+
1462
+ def cancel_order(self, id: str, symbol: Str = None, params={}):
1463
+ """
1464
+ cancels an open order
1465
+ :see: https://docs.gemini.com/rest-api/#cancel-order
1466
+ :param str id: order id
1467
+ :param str symbol: unified symbol of the market the order was made in
1468
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1469
+ :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1470
+ """
1471
+ self.load_markets()
1472
+ request: dict = {
1473
+ 'order_id': id,
1474
+ }
1475
+ response = self.privatePostV1OrderCancel(self.extend(request, params))
1476
+ #
1477
+ # {
1478
+ # "order_id":"106028543717",
1479
+ # "id":"106028543717",
1480
+ # "symbol":"etheur",
1481
+ # "exchange":"gemini",
1482
+ # "avg_execution_price":"0.00",
1483
+ # "side":"buy",
1484
+ # "type":"exchange limit",
1485
+ # "timestamp":"1650398446",
1486
+ # "timestampms":1650398446375,
1487
+ # "is_live":false,
1488
+ # "is_cancelled":true,
1489
+ # "is_hidden":false,
1490
+ # "was_forced":false,
1491
+ # "executed_amount":"0",
1492
+ # "client_order_id":"1650398445709",
1493
+ # "reason":"Requested",
1494
+ # "options":[],
1495
+ # "price":"2000.00",
1496
+ # "original_amount":"0.01",
1497
+ # "remaining_amount":"0.01"
1498
+ # }
1499
+ #
1500
+ return self.parse_order(response)
1501
+
1502
+ def fetch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1503
+ """
1504
+ fetch all trades made by the user
1505
+ :see: https://docs.gemini.com/rest-api/#get-past-trades
1506
+ :param str symbol: unified market symbol
1507
+ :param int [since]: the earliest time in ms to fetch trades for
1508
+ :param int [limit]: the maximum number of trades structures to retrieve
1509
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1510
+ :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
1511
+ """
1512
+ if symbol is None:
1513
+ raise ArgumentsRequired(self.id + ' fetchMyTrades() requires a symbol argument')
1514
+ self.load_markets()
1515
+ market = self.market(symbol)
1516
+ request: dict = {
1517
+ 'symbol': market['id'],
1518
+ }
1519
+ if limit is not None:
1520
+ request['limit_trades'] = limit
1521
+ if since is not None:
1522
+ request['timestamp'] = self.parse_to_int(since / 1000)
1523
+ response = self.privatePostV1Mytrades(self.extend(request, params))
1524
+ return self.parse_trades(response, market, since, limit)
1525
+
1526
+ def withdraw(self, code: str, amount: float, address: str, tag=None, params={}):
1527
+ """
1528
+ make a withdrawal
1529
+ :see: https://docs.gemini.com/rest-api/#withdraw-crypto-funds
1530
+ :param str code: unified currency code
1531
+ :param float amount: the amount to withdraw
1532
+ :param str address: the address to withdraw to
1533
+ :param str tag:
1534
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1535
+ :returns dict: a `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
1536
+ """
1537
+ tag, params = self.handle_withdraw_tag_and_params(tag, params)
1538
+ self.check_address(address)
1539
+ self.load_markets()
1540
+ currency = self.currency(code)
1541
+ request: dict = {
1542
+ 'currency': currency['id'],
1543
+ 'amount': amount,
1544
+ 'address': address,
1545
+ }
1546
+ response = self.privatePostV1WithdrawCurrency(self.extend(request, params))
1547
+ #
1548
+ # for BTC
1549
+ # {
1550
+ # "address":"mi98Z9brJ3TgaKsmvXatuRahbFRUFKRUdR",
1551
+ # "amount":"1",
1552
+ # "withdrawalId":"02176a83-a6b1-4202-9b85-1c1c92dd25c4",
1553
+ # "message":"You have requested a transfer of 1 BTC to mi98Z9brJ3TgaKsmvXatuRahbFRUFKRUdR. This withdrawal will be sent to the blockchain within the next 60 seconds."
1554
+ # }
1555
+ #
1556
+ # for ETH
1557
+ # {
1558
+ # "address":"0xA63123350Acc8F5ee1b1fBd1A6717135e82dBd28",
1559
+ # "amount":"2.34567",
1560
+ # "txHash":"0x28267179f92926d85c5516bqc063b2631935573d8915258e95d9572eedcc8cc"
1561
+ # }
1562
+ #
1563
+ # for error(other variations of error messages are also expected)
1564
+ # {
1565
+ # "result":"error",
1566
+ # "reason":"CryptoAddressWhitelistsNotEnabled",
1567
+ # "message":"Cryptocurrency withdrawal address whitelists are not enabled for account 24. Please contact support@gemini.com for information on setting up a withdrawal address whitelist."
1568
+ # }
1569
+ #
1570
+ result = self.safe_string(response, 'result')
1571
+ if result == 'error':
1572
+ raise ExchangeError(self.id + ' withdraw() failed: ' + self.json(response))
1573
+ return self.parse_transaction(response, currency)
1574
+
1575
+ def nonce(self):
1576
+ nonceMethod = self.safe_string(self.options, 'nonce', 'milliseconds')
1577
+ if nonceMethod == 'milliseconds':
1578
+ return self.milliseconds()
1579
+ return self.seconds()
1580
+
1581
+ def fetch_deposits_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
1582
+ """
1583
+ fetch history of deposits and withdrawals
1584
+ :see: https://docs.gemini.com/rest-api/#transfers
1585
+ :param str [code]: unified currency code for the currency of the deposit/withdrawals, default is None
1586
+ :param int [since]: timestamp in ms of the earliest deposit/withdrawal, default is None
1587
+ :param int [limit]: max number of deposit/withdrawals to return, default is None
1588
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1589
+ :returns dict: a list of `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
1590
+ """
1591
+ self.load_markets()
1592
+ request: dict = {}
1593
+ if limit is not None:
1594
+ request['limit_transfers'] = limit
1595
+ if since is not None:
1596
+ request['timestamp'] = since
1597
+ response = self.privatePostV1Transfers(self.extend(request, params))
1598
+ return self.parse_transactions(response)
1599
+
1600
+ def parse_transaction(self, transaction: dict, currency: Currency = None) -> Transaction:
1601
+ #
1602
+ # withdraw
1603
+ #
1604
+ # for BTC
1605
+ # {
1606
+ # "address":"mi98Z9brJ3TgaKsmvXatuRahbFRUFKRUdR",
1607
+ # "amount":"1",
1608
+ # "withdrawalId":"02176a83-a6b1-4202-9b85-1c1c92dd25c4",
1609
+ # "message":"You have requested a transfer of 1 BTC to mi98Z9brJ3TgaKsmvXatuRahbFRUFKRUdR. This withdrawal will be sent to the blockchain within the next 60 seconds."
1610
+ # }
1611
+ #
1612
+ # for ETH
1613
+ # {
1614
+ # "address":"0xA63123350Acc8F5ee1b1fBd1A6717135e82dBd28",
1615
+ # "amount":"2.34567",
1616
+ # "txHash":"0x28267179f92926d85c5516bqc063b2631935573d8915258e95d9572eedcc8cc"
1617
+ # }
1618
+ #
1619
+ timestamp = self.safe_integer(transaction, 'timestampms')
1620
+ currencyId = self.safe_string(transaction, 'currency')
1621
+ code = self.safe_currency_code(currencyId, currency)
1622
+ address = self.safe_string(transaction, 'destination')
1623
+ type = self.safe_string_lower(transaction, 'type')
1624
+ # if status field is available, then it's complete
1625
+ statusRaw = self.safe_string(transaction, 'status')
1626
+ fee = None
1627
+ feeAmount = self.safe_number(transaction, 'feeAmount')
1628
+ if feeAmount is not None:
1629
+ fee = {
1630
+ 'cost': feeAmount,
1631
+ 'currency': code,
1632
+ }
1633
+ return {
1634
+ 'info': transaction,
1635
+ 'id': self.safe_string_2(transaction, 'eid', 'withdrawalId'),
1636
+ 'txid': self.safe_string(transaction, 'txHash'),
1637
+ 'timestamp': timestamp,
1638
+ 'datetime': self.iso8601(timestamp),
1639
+ 'network': None,
1640
+ 'address': address,
1641
+ 'addressTo': None,
1642
+ 'addressFrom': None,
1643
+ 'tag': None, # or is it defined?
1644
+ 'tagTo': None,
1645
+ 'tagFrom': None,
1646
+ 'type': type, # direction of the transaction,('deposit' | 'withdraw')
1647
+ 'amount': self.safe_number(transaction, 'amount'),
1648
+ 'currency': code,
1649
+ 'status': self.parse_transaction_status(statusRaw),
1650
+ 'updated': None,
1651
+ 'internal': None,
1652
+ 'comment': self.safe_string(transaction, 'message'),
1653
+ 'fee': fee,
1654
+ }
1655
+
1656
+ def parse_transaction_status(self, status: Str):
1657
+ statuses: dict = {
1658
+ 'Advanced': 'ok',
1659
+ 'Complete': 'ok',
1660
+ }
1661
+ return self.safe_string(statuses, status, status)
1662
+
1663
+ def parse_deposit_address(self, depositAddress, currency: Currency = None):
1664
+ #
1665
+ # {
1666
+ # "address": "0xed6494Fe7c1E56d1bd6136e89268C51E32d9708B",
1667
+ # "timestamp": "1636813923098",
1668
+ # "addressVersion": "eV1" }
1669
+ # }
1670
+ #
1671
+ address = self.safe_string(depositAddress, 'address')
1672
+ code = self.safe_currency_code(None, currency)
1673
+ return {
1674
+ 'currency': code,
1675
+ 'network': None,
1676
+ 'address': address,
1677
+ 'tag': None,
1678
+ 'info': depositAddress,
1679
+ }
1680
+
1681
+ def fetch_deposit_address(self, code: str, params={}):
1682
+ """
1683
+ :see: https://docs.gemini.com/rest-api/#get-deposit-addresses
1684
+ fetch the deposit address for a currency associated with self account
1685
+ :param str code: unified currency code
1686
+ :param dict [params]: extra parameters specific to the endpoint
1687
+ :param str [params.network]: *required* The chain of currency
1688
+ :returns dict: an `address structure <https://docs.ccxt.com/#/?id=address-structure>`
1689
+ """
1690
+ self.load_markets()
1691
+ groupedByNetwork = self.fetch_deposit_addresses_by_network(code, params)
1692
+ networkCode = None
1693
+ networkCode, params = self.handle_network_code_and_params(params)
1694
+ networkGroup = self.index_by(self.safe_value(groupedByNetwork, networkCode), 'currency')
1695
+ return self.safe_value(networkGroup, code)
1696
+
1697
+ def fetch_deposit_addresses_by_network(self, code: str, params={}):
1698
+ """
1699
+ fetch a dictionary of addresses for a currency, indexed by network
1700
+ :see: https://docs.gemini.com/rest-api/#get-deposit-addresses
1701
+ :param str code: unified currency code of the currency for the deposit address
1702
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1703
+ :param str [params.network]: *required* The chain of currency
1704
+ :returns dict: a dictionary of `address structures <https://docs.ccxt.com/#/?id=address-structure>` indexed by the network
1705
+ """
1706
+ self.load_markets()
1707
+ currency = self.currency(code)
1708
+ code = currency['code']
1709
+ networkCode = None
1710
+ networkCode, params = self.handle_network_code_and_params(params)
1711
+ if networkCode is None:
1712
+ raise ArgumentsRequired(self.id + ' fetchDepositAddresses() requires a network parameter')
1713
+ networkId = self.network_code_to_id(networkCode)
1714
+ request: dict = {
1715
+ 'network': networkId,
1716
+ }
1717
+ response = self.privatePostV1AddressesNetwork(self.extend(request, params))
1718
+ results = self.parse_deposit_addresses(response, [code], False, {'network': networkCode, 'currency': code})
1719
+ return self.group_by(results, 'network')
1720
+
1721
+ def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
1722
+ url = '/' + self.implode_params(path, params)
1723
+ query = self.omit(params, self.extract_params(path))
1724
+ if api == 'private':
1725
+ self.check_required_credentials()
1726
+ apiKey = self.apiKey
1727
+ if apiKey.find('account') < 0:
1728
+ raise AuthenticationError(self.id + ' sign() requires an account-key, master-keys are not-supported')
1729
+ nonce = str(self.nonce())
1730
+ request = self.extend({
1731
+ 'request': url,
1732
+ 'nonce': nonce,
1733
+ }, query)
1734
+ payload = self.json(request)
1735
+ payload = self.string_to_base64(payload)
1736
+ signature = self.hmac(self.encode(payload), self.encode(self.secret), hashlib.sha384)
1737
+ headers = {
1738
+ 'Content-Type': 'text/plain',
1739
+ 'X-GEMINI-APIKEY': self.apiKey,
1740
+ 'X-GEMINI-PAYLOAD': payload,
1741
+ 'X-GEMINI-SIGNATURE': signature,
1742
+ }
1743
+ else:
1744
+ if query:
1745
+ url += '?' + self.urlencode(query)
1746
+ url = self.urls['api'][api] + url
1747
+ if (method == 'POST') or (method == 'DELETE'):
1748
+ body = self.json(query)
1749
+ return {'url': url, 'method': method, 'body': body, 'headers': headers}
1750
+
1751
+ def handle_errors(self, httpCode: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
1752
+ if response is None:
1753
+ if isinstance(body, str):
1754
+ feedback = self.id + ' ' + body
1755
+ self.throw_broadly_matched_exception(self.exceptions['broad'], body, feedback)
1756
+ return None # fallback to default error handler
1757
+ #
1758
+ # {
1759
+ # "result": "error",
1760
+ # "reason": "BadNonce",
1761
+ # "message": "Out-of-sequence nonce <1234> precedes previously used nonce <2345>"
1762
+ # }
1763
+ #
1764
+ result = self.safe_string(response, 'result')
1765
+ if result == 'error':
1766
+ reasonInner = self.safe_string(response, 'reason')
1767
+ message = self.safe_string(response, 'message')
1768
+ feedback = self.id + ' ' + message
1769
+ self.throw_exactly_matched_exception(self.exceptions['exact'], reasonInner, feedback)
1770
+ self.throw_exactly_matched_exception(self.exceptions['exact'], message, feedback)
1771
+ self.throw_broadly_matched_exception(self.exceptions['broad'], message, feedback)
1772
+ raise ExchangeError(feedback) # unknown message
1773
+ return None
1774
+
1775
+ def create_deposit_address(self, code: str, params={}):
1776
+ """
1777
+ create a currency deposit address
1778
+ :see: https://docs.gemini.com/rest-api/#new-deposit-address
1779
+ :param str code: unified currency code of the currency for the deposit address
1780
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1781
+ :returns dict: an `address structure <https://docs.ccxt.com/#/?id=address-structure>`
1782
+ """
1783
+ self.load_markets()
1784
+ currency = self.currency(code)
1785
+ request: dict = {
1786
+ 'currency': currency['id'],
1787
+ }
1788
+ response = self.privatePostV1DepositCurrencyNewAddress(self.extend(request, params))
1789
+ address = self.safe_string(response, 'address')
1790
+ self.check_address(address)
1791
+ return {
1792
+ 'currency': code,
1793
+ 'address': address,
1794
+ 'tag': None,
1795
+ 'info': response,
1796
+ }
1797
+
1798
+ def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
1799
+ """
1800
+ fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1801
+ :see: https://docs.gemini.com/rest-api/#candles
1802
+ :param str symbol: unified symbol of the market to fetch OHLCV data for
1803
+ :param str timeframe: the length of time each candle represents
1804
+ :param int [since]: timestamp in ms of the earliest candle to fetch
1805
+ :param int [limit]: the maximum amount of candles to fetch
1806
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1807
+ :returns int[][]: A list of candles ordered, open, high, low, close, volume
1808
+ """
1809
+ self.load_markets()
1810
+ market = self.market(symbol)
1811
+ timeframeId = self.safe_string(self.timeframes, timeframe, timeframe)
1812
+ request: dict = {
1813
+ 'timeframe': timeframeId,
1814
+ 'symbol': market['id'],
1815
+ }
1816
+ response = self.publicGetV2CandlesSymbolTimeframe(self.extend(request, params))
1817
+ #
1818
+ # [
1819
+ # [1591515000000,0.02509,0.02509,0.02509,0.02509,0],
1820
+ # [1591514700000,0.02503,0.02509,0.02503,0.02509,44.6405],
1821
+ # [1591514400000,0.02503,0.02503,0.02503,0.02503,0],
1822
+ # ]
1823
+ #
1824
+ return self.parse_ohlcvs(response, market, timeframe, since, limit)