ccxt 4.2.11 → 4.2.13

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