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