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,4722 @@
1
+ 'use strict';
2
+
3
+ var phemex$1 = require('./abstract/phemex.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 sha256 = require('./static_dependencies/noble-hashes/sha256.js');
8
+
9
+ // ----------------------------------------------------------------------------
10
+ // ----------------------------------------------------------------------------
11
+ /**
12
+ * @class phemex
13
+ * @augments Exchange
14
+ */
15
+ class phemex extends phemex$1 {
16
+ describe() {
17
+ return this.deepExtend(super.describe(), {
18
+ 'id': 'phemex',
19
+ 'name': 'Phemex',
20
+ 'countries': ['CN'],
21
+ 'rateLimit': 120.5,
22
+ 'version': 'v1',
23
+ 'certified': false,
24
+ 'pro': true,
25
+ 'hostname': 'api.phemex.com',
26
+ 'has': {
27
+ 'CORS': undefined,
28
+ 'spot': true,
29
+ 'margin': false,
30
+ 'swap': true,
31
+ 'future': false,
32
+ 'option': false,
33
+ 'addMargin': false,
34
+ 'cancelAllOrders': true,
35
+ 'cancelOrder': true,
36
+ 'createOrder': true,
37
+ 'createReduceOnlyOrder': true,
38
+ 'createStopLimitOrder': true,
39
+ 'createStopMarketOrder': true,
40
+ 'createStopOrder': true,
41
+ 'editOrder': true,
42
+ 'fetchBalance': true,
43
+ 'fetchBorrowRateHistories': false,
44
+ 'fetchBorrowRateHistory': false,
45
+ 'fetchClosedOrders': true,
46
+ 'fetchCrossBorrowRate': false,
47
+ 'fetchCrossBorrowRates': false,
48
+ 'fetchCurrencies': true,
49
+ 'fetchDepositAddress': true,
50
+ 'fetchDeposits': true,
51
+ 'fetchFundingHistory': true,
52
+ 'fetchFundingRate': true,
53
+ 'fetchFundingRateHistories': false,
54
+ 'fetchFundingRateHistory': true,
55
+ 'fetchFundingRates': false,
56
+ 'fetchIndexOHLCV': false,
57
+ 'fetchIsolatedBorrowRate': false,
58
+ 'fetchIsolatedBorrowRates': false,
59
+ 'fetchLeverage': false,
60
+ 'fetchLeverageTiers': true,
61
+ 'fetchMarketLeverageTiers': 'emulated',
62
+ 'fetchMarkets': true,
63
+ 'fetchMarkOHLCV': false,
64
+ 'fetchMyTrades': true,
65
+ 'fetchOHLCV': true,
66
+ 'fetchOpenOrders': true,
67
+ 'fetchOrder': true,
68
+ 'fetchOrderBook': true,
69
+ 'fetchOrders': true,
70
+ 'fetchPositions': true,
71
+ 'fetchPositionsRisk': false,
72
+ 'fetchPremiumIndexOHLCV': false,
73
+ 'fetchTicker': true,
74
+ 'fetchTickers': true,
75
+ 'fetchTrades': true,
76
+ 'fetchTradingFee': false,
77
+ 'fetchTradingFees': false,
78
+ 'fetchTransfers': true,
79
+ 'fetchWithdrawals': true,
80
+ 'reduceMargin': false,
81
+ 'setLeverage': true,
82
+ 'setMargin': true,
83
+ 'setMarginMode': true,
84
+ 'setPositionMode': true,
85
+ 'transfer': true,
86
+ 'withdraw': true,
87
+ },
88
+ 'urls': {
89
+ 'logo': 'https://user-images.githubusercontent.com/1294454/85225056-221eb600-b3d7-11ea-930d-564d2690e3f6.jpg',
90
+ 'test': {
91
+ 'v1': 'https://testnet-api.phemex.com/v1',
92
+ 'v2': 'https://testnet-api.phemex.com',
93
+ 'public': 'https://testnet-api.phemex.com/exchange/public',
94
+ 'private': 'https://testnet-api.phemex.com',
95
+ },
96
+ 'api': {
97
+ 'v1': 'https://{hostname}/v1',
98
+ 'v2': 'https://{hostname}',
99
+ 'public': 'https://{hostname}/exchange/public',
100
+ 'private': 'https://{hostname}',
101
+ },
102
+ 'www': 'https://phemex.com',
103
+ 'doc': 'https://github.com/phemex/phemex-api-docs',
104
+ 'fees': 'https://phemex.com/fees-conditions',
105
+ 'referral': {
106
+ 'url': 'https://phemex.com/register?referralCode=EDNVJ',
107
+ 'discount': 0.1,
108
+ },
109
+ },
110
+ 'timeframes': {
111
+ '1m': '60',
112
+ '3m': '180',
113
+ '5m': '300',
114
+ '15m': '900',
115
+ '30m': '1800',
116
+ '1h': '3600',
117
+ '2h': '7200',
118
+ '3h': '10800',
119
+ '4h': '14400',
120
+ '6h': '21600',
121
+ '12h': '43200',
122
+ '1d': '86400',
123
+ '1w': '604800',
124
+ '1M': '2592000',
125
+ '3M': '7776000',
126
+ '1Y': '31104000',
127
+ },
128
+ 'api': {
129
+ 'public': {
130
+ 'get': {
131
+ 'cfg/v2/products': 5,
132
+ 'cfg/fundingRates': 5,
133
+ 'products': 5,
134
+ 'nomics/trades': 5,
135
+ 'md/kline': 5,
136
+ 'md/v2/kline/list': 5,
137
+ 'md/v2/kline': 5,
138
+ 'md/v2/kline/last': 5,
139
+ 'md/orderbook': 5,
140
+ 'md/trade': 5,
141
+ 'md/spot/ticker/24hr': 5,
142
+ 'exchange/public/cfg/chain-settings': 5, // ?currency=<currency>
143
+ },
144
+ },
145
+ 'v1': {
146
+ 'get': {
147
+ 'md/fullbook': 5,
148
+ 'md/orderbook': 5,
149
+ 'md/trade': 5,
150
+ 'md/ticker/24hr': 5,
151
+ 'md/ticker/24hr/all': 5,
152
+ 'md/spot/ticker/24hr': 5,
153
+ 'md/spot/ticker/24hr/all': 5,
154
+ 'exchange/public/products': 5,
155
+ 'api-data/public/data/funding-rate-history': 5,
156
+ },
157
+ },
158
+ 'v2': {
159
+ 'get': {
160
+ 'public/products': 5,
161
+ 'md/v2/orderbook': 5,
162
+ 'md/v2/trade': 5,
163
+ 'md/v2/ticker/24hr': 5,
164
+ 'md/v2/ticker/24hr/all': 5,
165
+ 'api-data/public/data/funding-rate-history': 5,
166
+ },
167
+ },
168
+ 'private': {
169
+ 'get': {
170
+ // spot
171
+ 'spot/orders/active': 1,
172
+ // 'spot/orders/active': 5, // ?symbol=<symbol>&clOrDID=<clOrdID>
173
+ 'spot/orders': 1,
174
+ 'spot/wallets': 5,
175
+ 'exchange/spot/order': 5,
176
+ 'exchange/spot/order/trades': 5,
177
+ 'exchange/order/v2/orderList': 5,
178
+ 'exchange/order/v2/tradingList': 5,
179
+ // swap
180
+ 'accounts/accountPositions': 1,
181
+ 'g-accounts/accountPositions': 1,
182
+ 'accounts/positions': 25,
183
+ 'api-data/futures/funding-fees': 5,
184
+ 'api-data/g-futures/funding-fees': 5,
185
+ 'api-data/futures/orders': 5,
186
+ 'api-data/g-futures/orders': 5,
187
+ 'api-data/futures/orders/by-order-id': 5,
188
+ 'api-data/g-futures/orders/by-order-id': 5,
189
+ 'api-data/futures/trades': 5,
190
+ 'api-data/g-futures/trades': 5,
191
+ 'api-data/futures/trading-fees': 5,
192
+ 'api-data/g-futures/trading-fees': 5,
193
+ 'g-orders/activeList': 1,
194
+ 'orders/activeList': 1,
195
+ 'exchange/order/list': 5,
196
+ 'exchange/order': 5,
197
+ // 'exchange/order': 5, // ?symbol=<symbol>&clOrdID=<clOrdID5,clOrdID2>
198
+ 'exchange/order/trade': 5,
199
+ 'phemex-user/users/children': 5,
200
+ 'phemex-user/wallets/v2/depositAddress': 5,
201
+ 'phemex-user/wallets/tradeAccountDetail': 5,
202
+ 'phemex-deposit/wallets/api/depositAddress': 5,
203
+ 'phemex-deposit/wallets/api/depositHist': 5,
204
+ 'phemex-deposit/wallets/api/chainCfg': 5,
205
+ 'phemex-withdraw/wallets/api/withdrawHist': 5,
206
+ 'phemex-withdraw/wallets/api/asset/info': 5,
207
+ 'phemex-user/order/closedPositionList': 5,
208
+ 'exchange/margins/transfer': 5,
209
+ 'exchange/wallets/confirm/withdraw': 5,
210
+ 'exchange/wallets/withdrawList': 5,
211
+ 'exchange/wallets/depositList': 5,
212
+ 'exchange/wallets/v2/depositAddress': 5,
213
+ 'api-data/spots/funds': 5,
214
+ 'api-data/spots/orders': 5,
215
+ 'api-data/spots/orders/by-order-id': 5,
216
+ 'api-data/spots/pnls': 5,
217
+ 'api-data/spots/trades': 5,
218
+ 'api-data/spots/trades/by-order-id': 5,
219
+ 'assets/convert': 5,
220
+ // transfer
221
+ 'assets/transfer': 5,
222
+ 'assets/spots/sub-accounts/transfer': 5,
223
+ 'assets/futures/sub-accounts/transfer': 5,
224
+ 'assets/quote': 5, // ?fromCurrency=<currency>&toCurrency=<currency>&amountEv=<amount>
225
+ // deposit/withdraw
226
+ },
227
+ 'post': {
228
+ // spot
229
+ 'spot/orders': 1,
230
+ // swap
231
+ 'orders': 1,
232
+ 'g-orders': 1,
233
+ 'positions/assign': 5,
234
+ 'exchange/wallets/transferOut': 5,
235
+ 'exchange/wallets/transferIn': 5,
236
+ 'exchange/margins': 5,
237
+ 'exchange/wallets/createWithdraw': 5,
238
+ 'exchange/wallets/cancelWithdraw': 5,
239
+ 'exchange/wallets/createWithdrawAddress': 5,
240
+ // transfer
241
+ 'assets/transfer': 5,
242
+ 'assets/spots/sub-accounts/transfer': 5,
243
+ 'assets/futures/sub-accounts/transfer': 5,
244
+ 'assets/universal-transfer': 5,
245
+ 'assets/convert': 5,
246
+ // withdraw
247
+ 'phemex-withdraw/wallets/api/createWithdraw': 5,
248
+ 'phemex-withdraw/wallets/api/cancelWithdraw': 5, // ?id=<id>
249
+ },
250
+ 'put': {
251
+ // spot
252
+ 'spot/orders/create': 1,
253
+ 'spot/orders': 1,
254
+ // swap
255
+ 'orders/replace': 1,
256
+ 'g-orders/replace': 1,
257
+ 'positions/leverage': 5,
258
+ 'g-positions/leverage': 5,
259
+ 'g-positions/switch-pos-mode-sync': 5,
260
+ 'positions/riskLimit': 5, // ?symbol=<symbol>&riskLimit=<riskLimit>&riskLimitEv=<riskLimitEv>
261
+ },
262
+ 'delete': {
263
+ // spot
264
+ 'spot/orders': 2,
265
+ 'spot/orders/all': 2,
266
+ // 'spot/orders': 5, // ?symbol=<symbol>&clOrdID=<clOrdID>
267
+ // swap
268
+ 'orders/cancel': 1,
269
+ 'orders': 1,
270
+ 'orders/all': 3,
271
+ 'g-orders/cancel': 1,
272
+ 'g-orders': 1,
273
+ 'g-orders/all': 3, // ?symbol=<symbol>&untriggered=<untriggered>&text=<text>
274
+ },
275
+ },
276
+ },
277
+ 'precisionMode': number.TICK_SIZE,
278
+ 'fees': {
279
+ 'trading': {
280
+ 'tierBased': false,
281
+ 'percentage': true,
282
+ 'taker': this.parseNumber('0.001'),
283
+ 'maker': this.parseNumber('0.001'),
284
+ },
285
+ },
286
+ 'requiredCredentials': {
287
+ 'apiKey': true,
288
+ 'secret': true,
289
+ },
290
+ 'exceptions': {
291
+ 'exact': {
292
+ // not documented
293
+ '401': errors.AuthenticationError,
294
+ '412': errors.BadRequest,
295
+ '6001': errors.BadRequest,
296
+ // documented
297
+ '19999': errors.BadRequest,
298
+ '10001': errors.DuplicateOrderId,
299
+ '10002': errors.OrderNotFound,
300
+ '10003': errors.CancelPending,
301
+ '10004': errors.CancelPending,
302
+ '10005': errors.CancelPending,
303
+ '11001': errors.InsufficientFunds,
304
+ '11002': errors.InvalidOrder,
305
+ '11003': errors.InsufficientFunds,
306
+ '11004': errors.InvalidOrder,
307
+ '11005': errors.InsufficientFunds,
308
+ '11006': errors.ExchangeError,
309
+ '11007': errors.ExchangeError,
310
+ '11008': errors.ExchangeError,
311
+ '11009': errors.ExchangeError,
312
+ '11010': errors.InsufficientFunds,
313
+ '11011': errors.InvalidOrder,
314
+ '11012': errors.InvalidOrder,
315
+ '11013': errors.InvalidOrder,
316
+ '11014': errors.InvalidOrder,
317
+ '11015': errors.InvalidOrder,
318
+ '11016': errors.BadRequest,
319
+ '11017': errors.ExchangeError,
320
+ '11018': errors.ExchangeError,
321
+ '11019': errors.ExchangeError,
322
+ '11020': errors.ExchangeError,
323
+ '11021': errors.ExchangeError,
324
+ '11022': errors.AccountSuspended,
325
+ '11023': errors.ExchangeError,
326
+ '11024': errors.ExchangeError,
327
+ '11025': errors.BadRequest,
328
+ '11026': errors.ExchangeError,
329
+ '11027': errors.BadSymbol,
330
+ '11028': errors.BadSymbol,
331
+ '11029': errors.ExchangeError,
332
+ '11030': errors.ExchangeError,
333
+ '11031': errors.DDoSProtection,
334
+ '11032': errors.DDoSProtection,
335
+ '11033': errors.DuplicateOrderId,
336
+ '11034': errors.InvalidOrder,
337
+ '11035': errors.InvalidOrder,
338
+ '11036': errors.InvalidOrder,
339
+ '11037': errors.InvalidOrder,
340
+ '11038': errors.InvalidOrder,
341
+ '11039': errors.InvalidOrder,
342
+ '11040': errors.InvalidOrder,
343
+ '11041': errors.InvalidOrder,
344
+ '11042': errors.InvalidOrder,
345
+ '11043': errors.InvalidOrder,
346
+ '11044': errors.InvalidOrder,
347
+ '11045': errors.InvalidOrder,
348
+ '11046': errors.InvalidOrder,
349
+ '11047': errors.InvalidOrder,
350
+ '11048': errors.InvalidOrder,
351
+ '11049': errors.InvalidOrder,
352
+ '11050': errors.InvalidOrder,
353
+ '11051': errors.InvalidOrder,
354
+ '11052': errors.InvalidOrder,
355
+ '11053': errors.InvalidOrder,
356
+ '11054': errors.InvalidOrder,
357
+ '11055': errors.InvalidOrder,
358
+ '11056': errors.InvalidOrder,
359
+ '11057': errors.InvalidOrder,
360
+ '11058': errors.InvalidOrder,
361
+ '11059': errors.InvalidOrder,
362
+ '11060': errors.InvalidOrder,
363
+ '11061': errors.CancelPending,
364
+ '11062': errors.InvalidOrder,
365
+ '11063': errors.InvalidOrder,
366
+ '11064': errors.InvalidOrder,
367
+ '11065': errors.InvalidOrder,
368
+ '11066': errors.InvalidOrder,
369
+ '11067': errors.InvalidOrder,
370
+ '11068': errors.InvalidOrder,
371
+ '11069': errors.ExchangeError,
372
+ '11070': errors.BadSymbol,
373
+ '11071': errors.InvalidOrder,
374
+ '11072': errors.InvalidOrder,
375
+ '11073': errors.InvalidOrder,
376
+ '11074': errors.InvalidOrder,
377
+ '11075': errors.InvalidOrder,
378
+ '11076': errors.InvalidOrder,
379
+ '11077': errors.InvalidOrder,
380
+ '11078': errors.InvalidOrder,
381
+ '11079': errors.InvalidOrder,
382
+ '11080': errors.InvalidOrder,
383
+ '11081': errors.InvalidOrder,
384
+ '11082': errors.InsufficientFunds,
385
+ '11083': errors.InvalidOrder,
386
+ '11084': errors.InvalidOrder,
387
+ '11085': errors.DuplicateOrderId,
388
+ '11086': errors.InvalidOrder,
389
+ '11087': errors.InvalidOrder,
390
+ '11088': errors.InvalidOrder,
391
+ '11089': errors.InvalidOrder,
392
+ '11090': errors.InvalidOrder,
393
+ '11091': errors.InvalidOrder,
394
+ '11092': errors.InvalidOrder,
395
+ '11093': errors.InvalidOrder,
396
+ '11094': errors.InvalidOrder,
397
+ '11095': errors.InvalidOrder,
398
+ '11096': errors.InvalidOrder,
399
+ '11097': errors.BadRequest,
400
+ '11098': errors.BadRequest,
401
+ '11099': errors.ExchangeError,
402
+ '11100': errors.InsufficientFunds,
403
+ '11101': errors.InsufficientFunds,
404
+ '11102': errors.BadRequest,
405
+ '11103': errors.BadRequest,
406
+ '11104': errors.BadRequest,
407
+ '11105': errors.InsufficientFunds,
408
+ '11106': errors.InsufficientFunds,
409
+ '11107': errors.ExchangeError,
410
+ '11108': errors.InvalidOrder,
411
+ '11109': errors.InvalidOrder,
412
+ '11110': errors.InvalidOrder,
413
+ '11111': errors.InvalidOrder,
414
+ '11112': errors.InvalidOrder,
415
+ '11113': errors.BadRequest,
416
+ '11114': errors.InvalidOrder,
417
+ '11115': errors.InvalidOrder,
418
+ '11116': errors.InvalidOrder,
419
+ '11117': errors.InvalidOrder,
420
+ '11118': errors.InvalidOrder,
421
+ '11119': errors.InvalidOrder,
422
+ '11120': errors.InvalidOrder,
423
+ '11121': errors.InvalidOrder,
424
+ '11122': errors.InvalidOrder,
425
+ '11123': errors.InvalidOrder,
426
+ '11124': errors.InvalidOrder,
427
+ '11125': errors.InvalidOrder,
428
+ '11126': errors.InvalidOrder,
429
+ '11128': errors.InvalidOrder,
430
+ '11129': errors.InvalidOrder,
431
+ '11130': errors.InvalidOrder,
432
+ '11131': errors.InvalidOrder,
433
+ '11132': errors.InvalidOrder,
434
+ '11133': errors.InvalidOrder,
435
+ '11134': errors.InvalidOrder,
436
+ // not documented
437
+ '30000': errors.BadRequest,
438
+ '30018': errors.BadRequest,
439
+ '34003': errors.PermissionDenied,
440
+ '35104': errors.InsufficientFunds,
441
+ '39995': errors.RateLimitExceeded,
442
+ '39996': errors.PermissionDenied,
443
+ '39997': errors.BadSymbol, // {"code":39997,"msg":"Symbol not listed sMOVRUSDT","data":null}
444
+ },
445
+ 'broad': {
446
+ '401 Insufficient privilege': errors.PermissionDenied,
447
+ '401 Request IP mismatch': errors.PermissionDenied,
448
+ 'Failed to find api-key': errors.AuthenticationError,
449
+ 'Missing required parameter': errors.BadRequest,
450
+ 'API Signature verification failed': errors.AuthenticationError,
451
+ 'Api key not found': errors.AuthenticationError, // {"msg":"Api key not found 698dc9e3-6faa-4910-9476-12857e79e198","code":"10500"}
452
+ },
453
+ },
454
+ 'options': {
455
+ 'brokerId': 'CCXT123456',
456
+ 'x-phemex-request-expiry': 60,
457
+ 'createOrderByQuoteRequiresPrice': true,
458
+ 'networks': {
459
+ 'TRC20': 'TRX',
460
+ 'ERC20': 'ETH',
461
+ 'BEP20': 'BNB',
462
+ },
463
+ 'defaultNetworks': {
464
+ 'USDT': 'ETH',
465
+ },
466
+ 'defaultSubType': 'linear',
467
+ 'accountsByType': {
468
+ 'spot': 'spot',
469
+ 'swap': 'future',
470
+ },
471
+ 'stableCoins': [
472
+ 'BUSD',
473
+ 'FEI',
474
+ 'TUSD',
475
+ 'USD',
476
+ 'USDC',
477
+ 'USDD',
478
+ 'USDP',
479
+ 'USDT',
480
+ ],
481
+ 'transfer': {
482
+ 'fillResponseFromRequest': true,
483
+ },
484
+ },
485
+ });
486
+ }
487
+ parseSafeNumber(value = undefined) {
488
+ if (value === undefined) {
489
+ return value;
490
+ }
491
+ let parts = value.split(',');
492
+ value = parts.join('');
493
+ parts = value.split(' ');
494
+ return this.safeNumber(parts, 0);
495
+ }
496
+ parseSwapMarket(market) {
497
+ //
498
+ // {
499
+ // "symbol":"BTCUSD",
500
+ // "code":"1",
501
+ // "type":"Perpetual",
502
+ // "displaySymbol":"BTC / USD",
503
+ // "indexSymbol":".BTC",
504
+ // "markSymbol":".MBTC",
505
+ // "fundingRateSymbol":".BTCFR",
506
+ // "fundingRate8hSymbol":".BTCFR8H",
507
+ // "contractUnderlyingAssets":"USD",
508
+ // "settleCurrency":"BTC",
509
+ // "quoteCurrency":"USD",
510
+ // "contractSize":"1 USD",
511
+ // "lotSize":1,
512
+ // "tickSize":0.5,
513
+ // "priceScale":4,
514
+ // "ratioScale":8,
515
+ // "pricePrecision":1,
516
+ // "minPriceEp":5000,
517
+ // "maxPriceEp":10000000000,
518
+ // "maxOrderQty":1000000,
519
+ // "status":"Listed",
520
+ // "tipOrderQty":1000000,
521
+ // "listTime":"1574650800000",
522
+ // "majorSymbol":true,
523
+ // "steps":"50",
524
+ // "riskLimits":[
525
+ // {"limit":100,"initialMargin":"1.0%","initialMarginEr":1000000,"maintenanceMargin":"0.5%","maintenanceMarginEr":500000},
526
+ // {"limit":150,"initialMargin":"1.5%","initialMarginEr":1500000,"maintenanceMargin":"1.0%","maintenanceMarginEr":1000000},
527
+ // {"limit":200,"initialMargin":"2.0%","initialMarginEr":2000000,"maintenanceMargin":"1.5%","maintenanceMarginEr":1500000},
528
+ // ],
529
+ // "underlyingSymbol":".BTC",
530
+ // "baseCurrency":"BTC",
531
+ // "settlementCurrency":"BTC",
532
+ // "valueScale":8,
533
+ // "defaultLeverage":0,
534
+ // "maxLeverage":100,
535
+ // "initMarginEr":"1000000",
536
+ // "maintMarginEr":"500000",
537
+ // "defaultRiskLimitEv":10000000000,
538
+ // "deleverage":true,
539
+ // "makerFeeRateEr":-250000,
540
+ // "takerFeeRateEr":750000,
541
+ // "fundingInterval":8,
542
+ // "marketUrl":"https://phemex.com/trade/BTCUSD",
543
+ // "description":"BTCUSD is a BTC/USD perpetual contract priced on the .BTC Index. Each contract is worth 1 USD of Bitcoin. Funding is paid and received every 8 hours. At UTC time: 00:00, 08:00, 16:00.",
544
+ // }
545
+ //
546
+ const id = this.safeString(market, 'symbol');
547
+ const baseId = this.safeString2(market, 'baseCurrency', 'contractUnderlyingAssets');
548
+ const quoteId = this.safeString(market, 'quoteCurrency');
549
+ const settleId = this.safeString(market, 'settleCurrency');
550
+ const base = this.safeCurrencyCode(baseId);
551
+ const quote = this.safeCurrencyCode(quoteId);
552
+ const settle = this.safeCurrencyCode(settleId);
553
+ let inverse = false;
554
+ if (settleId !== quoteId) {
555
+ inverse = true;
556
+ }
557
+ const priceScale = this.safeInteger(market, 'priceScale');
558
+ const ratioScale = this.safeInteger(market, 'ratioScale');
559
+ const valueScale = this.safeInteger(market, 'valueScale');
560
+ const minPriceEp = this.safeString(market, 'minPriceEp');
561
+ const maxPriceEp = this.safeString(market, 'maxPriceEp');
562
+ const makerFeeRateEr = this.safeString(market, 'makerFeeRateEr');
563
+ const takerFeeRateEr = this.safeString(market, 'takerFeeRateEr');
564
+ const status = this.safeString(market, 'status');
565
+ const contractSizeString = this.safeString(market, 'contractSize', ' ');
566
+ let contractSize = undefined;
567
+ if (settle === 'USDT') {
568
+ contractSize = this.parseNumber('1');
569
+ }
570
+ else if (contractSizeString.indexOf(' ')) {
571
+ // "1 USD"
572
+ // "0.005 ETH"
573
+ const parts = contractSizeString.split(' ');
574
+ contractSize = this.parseNumber(parts[0]);
575
+ }
576
+ else {
577
+ // "1.0"
578
+ contractSize = this.parseNumber(contractSizeString);
579
+ }
580
+ return this.safeMarketStructure({
581
+ 'id': id,
582
+ 'symbol': base + '/' + quote + ':' + settle,
583
+ 'base': base,
584
+ 'quote': quote,
585
+ 'settle': settle,
586
+ 'baseId': baseId,
587
+ 'quoteId': quoteId,
588
+ 'settleId': settleId,
589
+ 'type': 'swap',
590
+ 'spot': false,
591
+ 'margin': false,
592
+ 'swap': true,
593
+ 'future': false,
594
+ 'option': false,
595
+ 'active': status === 'Listed',
596
+ 'contract': true,
597
+ 'linear': !inverse,
598
+ 'inverse': inverse,
599
+ 'taker': this.parseNumber(this.fromEn(takerFeeRateEr, ratioScale)),
600
+ 'maker': this.parseNumber(this.fromEn(makerFeeRateEr, ratioScale)),
601
+ 'contractSize': contractSize,
602
+ 'expiry': undefined,
603
+ 'expiryDatetime': undefined,
604
+ 'strike': undefined,
605
+ 'optionType': undefined,
606
+ 'priceScale': priceScale,
607
+ 'valueScale': valueScale,
608
+ 'ratioScale': ratioScale,
609
+ 'precision': {
610
+ 'amount': this.safeNumber2(market, 'lotSize', 'qtyStepSize'),
611
+ 'price': this.safeNumber(market, 'tickSize'),
612
+ },
613
+ 'limits': {
614
+ 'leverage': {
615
+ 'min': this.parseNumber('1'),
616
+ 'max': this.safeNumber(market, 'maxLeverage'),
617
+ },
618
+ 'amount': {
619
+ 'min': undefined,
620
+ 'max': undefined,
621
+ },
622
+ 'price': {
623
+ 'min': this.parseNumber(this.fromEn(minPriceEp, priceScale)),
624
+ 'max': this.parseNumber(this.fromEn(maxPriceEp, priceScale)),
625
+ },
626
+ 'cost': {
627
+ 'min': undefined,
628
+ 'max': this.parseNumber(this.safeString(market, 'maxOrderQty')),
629
+ },
630
+ },
631
+ 'created': undefined,
632
+ 'info': market,
633
+ });
634
+ }
635
+ parseSpotMarket(market) {
636
+ //
637
+ // {
638
+ // "symbol":"sBTCUSDT",
639
+ // "code":1001,
640
+ // "type":"Spot",
641
+ // "displaySymbol":"BTC / USDT",
642
+ // "quoteCurrency":"USDT",
643
+ // "priceScale":8,
644
+ // "ratioScale":8,
645
+ // "pricePrecision":2,
646
+ // "baseCurrency":"BTC",
647
+ // "baseTickSize":"0.000001 BTC",
648
+ // "baseTickSizeEv":100,
649
+ // "quoteTickSize":"0.01 USDT",
650
+ // "quoteTickSizeEv":1000000,
651
+ // "baseQtyPrecision":6,
652
+ // "quoteQtyPrecision":2,
653
+ // "minOrderValue":"10 USDT",
654
+ // "minOrderValueEv":1000000000,
655
+ // "maxBaseOrderSize":"1000 BTC",
656
+ // "maxBaseOrderSizeEv":100000000000,
657
+ // "maxOrderValue":"5,000,000 USDT",
658
+ // "maxOrderValueEv":500000000000000,
659
+ // "defaultTakerFee":"0.001",
660
+ // "defaultTakerFeeEr":100000,
661
+ // "defaultMakerFee":"0.001",
662
+ // "defaultMakerFeeEr":100000,
663
+ // "description":"BTCUSDT is a BTC/USDT spot trading pair. Minimum order value is 1 USDT",
664
+ // "status":"Listed",
665
+ // "tipOrderQty":2,
666
+ // "listTime":1589338800000,
667
+ // "buyPriceUpperLimitPct":110,
668
+ // "sellPriceLowerLimitPct":90,
669
+ // "leverage":5
670
+ // },
671
+ //
672
+ const type = this.safeStringLower(market, 'type');
673
+ const id = this.safeString(market, 'symbol');
674
+ const quoteId = this.safeString(market, 'quoteCurrency');
675
+ const baseId = this.safeString(market, 'baseCurrency');
676
+ const base = this.safeCurrencyCode(baseId);
677
+ const quote = this.safeCurrencyCode(quoteId);
678
+ const status = this.safeString(market, 'status');
679
+ const precisionAmount = this.parseSafeNumber(this.safeString(market, 'baseTickSize'));
680
+ const precisionPrice = this.parseSafeNumber(this.safeString(market, 'quoteTickSize'));
681
+ return this.safeMarketStructure({
682
+ 'id': id,
683
+ 'symbol': base + '/' + quote,
684
+ 'base': base,
685
+ 'quote': quote,
686
+ 'settle': undefined,
687
+ 'baseId': baseId,
688
+ 'quoteId': quoteId,
689
+ 'settleId': undefined,
690
+ 'type': type,
691
+ 'spot': true,
692
+ 'margin': false,
693
+ 'swap': false,
694
+ 'future': false,
695
+ 'option': false,
696
+ 'active': status === 'Listed',
697
+ 'contract': false,
698
+ 'linear': undefined,
699
+ 'inverse': undefined,
700
+ 'taker': this.safeNumber(market, 'defaultTakerFee'),
701
+ 'maker': this.safeNumber(market, 'defaultMakerFee'),
702
+ 'contractSize': undefined,
703
+ 'expiry': undefined,
704
+ 'expiryDatetime': undefined,
705
+ 'strike': undefined,
706
+ 'optionType': undefined,
707
+ 'priceScale': this.safeInteger(market, 'priceScale'),
708
+ 'valueScale': this.safeInteger(market, 'valueScale'),
709
+ 'ratioScale': this.safeInteger(market, 'ratioScale'),
710
+ 'precision': {
711
+ 'amount': precisionAmount,
712
+ 'price': precisionPrice,
713
+ },
714
+ 'limits': {
715
+ 'leverage': {
716
+ 'min': undefined,
717
+ 'max': undefined,
718
+ },
719
+ 'amount': {
720
+ 'min': precisionAmount,
721
+ 'max': this.parseSafeNumber(this.safeString(market, 'maxBaseOrderSize')),
722
+ },
723
+ 'price': {
724
+ 'min': precisionPrice,
725
+ 'max': undefined,
726
+ },
727
+ 'cost': {
728
+ 'min': this.parseSafeNumber(this.safeString(market, 'minOrderValue')),
729
+ 'max': this.parseSafeNumber(this.safeString(market, 'maxOrderValue')),
730
+ },
731
+ },
732
+ 'created': undefined,
733
+ 'info': market,
734
+ });
735
+ }
736
+ async fetchMarkets(params = {}) {
737
+ /**
738
+ * @method
739
+ * @name phemex#fetchMarkets
740
+ * @description retrieves data on all markets for phemex
741
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
742
+ * @returns {object[]} an array of objects representing market data
743
+ */
744
+ const v2Products = await this.v2GetPublicProducts(params);
745
+ //
746
+ // {
747
+ // "code":0,
748
+ // "msg":"",
749
+ // "data":{
750
+ // "currencies":[
751
+ // {"currency":"BTC","name":"Bitcoin","code":1,"valueScale":8,"minValueEv":1,"maxValueEv":5000000000000000000,"needAddrTag":0,"status":"Listed","displayCurrency":"BTC","inAssetsDisplay":1,"perpetual":0,"stableCoin":0,"assetsPrecision":8},
752
+ // {"currency":"USD","name":"USD","code":2,"valueScale":4,"minValueEv":1,"maxValueEv":5000000000000000000,"needAddrTag":0,"status":"Listed","displayCurrency":"USD","inAssetsDisplay":1,"perpetual":0,"stableCoin":0,"assetsPrecision":2},
753
+ // {"currency":"USDT","name":"TetherUS","code":3,"valueScale":8,"minValueEv":1,"maxValueEv":5000000000000000000,"needAddrTag":0,"status":"Listed","displayCurrency":"USDT","inAssetsDisplay":1,"perpetual":2,"stableCoin":1,"assetsPrecision":8},
754
+ // ],
755
+ // "products":[
756
+ // {
757
+ // "symbol":"BTCUSD",
758
+ // "code":1,
759
+ // "type":"Perpetual"
760
+ // "displaySymbol":"BTC / USD",
761
+ // "indexSymbol":".BTC",
762
+ // "markSymbol":".MBTC",
763
+ // "fundingRateSymbol":".BTCFR",
764
+ // "fundingRate8hSymbol":".BTCFR8H",
765
+ // "contractUnderlyingAssets":"USD",
766
+ // "settleCurrency":"BTC",
767
+ // "quoteCurrency":"USD",
768
+ // "contractSize":1.0,
769
+ // "lotSize":1,
770
+ // "tickSize":0.5,
771
+ // "priceScale":4,
772
+ // "ratioScale":8,
773
+ // "pricePrecision":1,
774
+ // "minPriceEp":5000,
775
+ // "maxPriceEp":10000000000,
776
+ // "maxOrderQty":1000000,
777
+ // "description":"BTC/USD perpetual contracts are priced on the .BTC Index. Each contract is worth 1 USD. Funding fees are paid and received every 8 hours at UTC time: 00:00, 08:00 and 16:00.",
778
+ // "status":"Listed",
779
+ // "tipOrderQty":1000000,
780
+ // "listTime":1574650800000,
781
+ // "majorSymbol":true,
782
+ // "defaultLeverage":"-10",
783
+ // "fundingInterval":28800,
784
+ // "maxLeverage":100
785
+ // },
786
+ // {
787
+ // "symbol":"sBTCUSDT",
788
+ // "code":1001,
789
+ // "type":"Spot",
790
+ // "displaySymbol":"BTC / USDT",
791
+ // "quoteCurrency":"USDT",
792
+ // "priceScale":8,
793
+ // "ratioScale":8,
794
+ // "pricePrecision":2,
795
+ // "baseCurrency":"BTC",
796
+ // "baseTickSize":"0.000001 BTC",
797
+ // "baseTickSizeEv":100,
798
+ // "quoteTickSize":"0.01 USDT",
799
+ // "quoteTickSizeEv":1000000,
800
+ // "baseQtyPrecision":6,
801
+ // "quoteQtyPrecision":2,
802
+ // "minOrderValue":"10 USDT",
803
+ // "minOrderValueEv":1000000000,
804
+ // "maxBaseOrderSize":"1000 BTC",
805
+ // "maxBaseOrderSizeEv":100000000000,
806
+ // "maxOrderValue":"5,000,000 USDT",
807
+ // "maxOrderValueEv":500000000000000,
808
+ // "defaultTakerFee":"0.001",
809
+ // "defaultTakerFeeEr":100000,
810
+ // "defaultMakerFee":"0.001",
811
+ // "defaultMakerFeeEr":100000,
812
+ // "description":"BTCUSDT is a BTC/USDT spot trading pair. Minimum order value is 1 USDT",
813
+ // "status":"Listed",
814
+ // "tipOrderQty":2,
815
+ // "listTime":1589338800000,
816
+ // "buyPriceUpperLimitPct":110,
817
+ // "sellPriceLowerLimitPct":90,
818
+ // "leverage":5
819
+ // },
820
+ // ],
821
+ // "perpProductsV2":[
822
+ // {
823
+ // "symbol":"BTCUSDT",
824
+ // "code":41541,
825
+ // "type":"PerpetualV2",
826
+ // "displaySymbol":"BTC / USDT",
827
+ // "indexSymbol":".BTCUSDT",
828
+ // "markSymbol":".MBTCUSDT",
829
+ // "fundingRateSymbol":".BTCUSDTFR",
830
+ // "fundingRate8hSymbol":".BTCUSDTFR8H",
831
+ // "contractUnderlyingAssets":"BTC",
832
+ // "settleCurrency":"USDT",
833
+ // "quoteCurrency":"USDT",
834
+ // "tickSize":"0.1",
835
+ // "priceScale":0,
836
+ // "ratioScale":0,
837
+ // "pricePrecision":1,
838
+ // "baseCurrency":"BTC",
839
+ // "description":"BTC/USDT perpetual contracts are priced on the .BTCUSDT Index. Each contract is worth 1 BTC. Funding fees are paid and received every 8 hours at UTC time: 00:00, 08:00 and 16:00.",
840
+ // "status":"Listed",
841
+ // "tipOrderQty":0,
842
+ // "listTime":1668225600000,
843
+ // "majorSymbol":true,
844
+ // "defaultLeverage":"-10",
845
+ // "fundingInterval":28800,
846
+ // "maxLeverage":100,
847
+ // "maxOrderQtyRq":"1000",
848
+ // "maxPriceRp":"2000000000",
849
+ // "minOrderValueRv":"1",
850
+ // "minPriceRp":"1000.0",
851
+ // "qtyPrecision":3,
852
+ // "qtyStepSize":"0.001",
853
+ // "tipOrderQtyRq":"200",
854
+ // "maxOpenPosLeverage":100.0
855
+ // },
856
+ // ],
857
+ // "riskLimits":[
858
+ // {
859
+ // "symbol":"BTCUSD",
860
+ // "steps":"50",
861
+ // "riskLimits":[
862
+ // {"limit":100,"initialMargin":"1.0%","initialMarginEr":1000000,"maintenanceMargin":"0.5%","maintenanceMarginEr":500000},
863
+ // {"limit":150,"initialMargin":"1.5%","initialMarginEr":1500000,"maintenanceMargin":"1.0%","maintenanceMarginEr":1000000},
864
+ // {"limit":200,"initialMargin":"2.0%","initialMarginEr":2000000,"maintenanceMargin":"1.5%","maintenanceMarginEr":1500000},
865
+ // ]
866
+ // },
867
+ // ],
868
+ // "leverages":[
869
+ // {"initialMargin":"1.0%","initialMarginEr":1000000,"options":[1,2,3,5,10,25,50,100]},
870
+ // {"initialMargin":"1.5%","initialMarginEr":1500000,"options":[1,2,3,5,10,25,50,66]},
871
+ // {"initialMargin":"2.0%","initialMarginEr":2000000,"options":[1,2,3,5,10,25,33,50]},
872
+ // ],
873
+ // "riskLimitsV2":[
874
+ // {
875
+ // "symbol":"BTCUSDT",
876
+ // "steps":"2000K",
877
+ // "riskLimits":[
878
+ // {"limit":2000000,"initialMarginRr":"0.01","maintenanceMarginRr":"0.005"},,
879
+ // {"limit":4000000,"initialMarginRr":"0.015","maintenanceMarginRr":"0.0075"},
880
+ // {"limit":6000000,"initialMarginRr":"0.02","maintenanceMarginRr":"0.01"},
881
+ // ]
882
+ // },
883
+ // ],
884
+ // "leveragesV2":[
885
+ // {"options":[1.0,2.0,3.0,5.0,10.0,25.0,50.0,100.0],"initialMarginRr":"0.01"},
886
+ // {"options":[1.0,2.0,3.0,5.0,10.0,25.0,50.0,66.67],"initialMarginRr":"0.015"},
887
+ // {"options":[1.0,2.0,3.0,5.0,10.0,25.0,33.0,50.0],"initialMarginRr":"0.02"},
888
+ // ],
889
+ // "ratioScale":8,
890
+ // "md5Checksum":"5c6604814d3c1bafbe602c3d11a7e8bf",
891
+ // }
892
+ // }
893
+ //
894
+ const v1Products = await this.v1GetExchangePublicProducts(params);
895
+ const v1ProductsData = this.safeValue(v1Products, 'data', []);
896
+ //
897
+ // {
898
+ // "code":0,
899
+ // "msg":"OK",
900
+ // "data":[
901
+ // {
902
+ // "symbol":"BTCUSD",
903
+ // "underlyingSymbol":".BTC",
904
+ // "quoteCurrency":"USD",
905
+ // "baseCurrency":"BTC",
906
+ // "settlementCurrency":"BTC",
907
+ // "maxOrderQty":1000000,
908
+ // "maxPriceEp":100000000000000,
909
+ // "lotSize":1,
910
+ // "tickSize":"0.5",
911
+ // "contractSize":"1 USD",
912
+ // "priceScale":4,
913
+ // "ratioScale":8,
914
+ // "valueScale":8,
915
+ // "defaultLeverage":0,
916
+ // "maxLeverage":100,
917
+ // "initMarginEr":"1000000",
918
+ // "maintMarginEr":"500000",
919
+ // "defaultRiskLimitEv":10000000000,
920
+ // "deleverage":true,
921
+ // "makerFeeRateEr":-250000,
922
+ // "takerFeeRateEr":750000,
923
+ // "fundingInterval":8,
924
+ // "marketUrl":"https://phemex.com/trade/BTCUSD",
925
+ // "description":"BTCUSD is a BTC/USD perpetual contract priced on the .BTC Index. Each contract is worth 1 USD of Bitcoin. Funding is paid and received every 8 hours. At UTC time: 00:00, 08:00, 16:00.",
926
+ // "type":"Perpetual"
927
+ // },
928
+ // ]
929
+ // }
930
+ //
931
+ const v2ProductsData = this.safeValue(v2Products, 'data', {});
932
+ let products = this.safeValue(v2ProductsData, 'products', []);
933
+ const perpetualProductsV2 = this.safeValue(v2ProductsData, 'perpProductsV2', []);
934
+ products = this.arrayConcat(products, perpetualProductsV2);
935
+ let riskLimits = this.safeValue(v2ProductsData, 'riskLimits', []);
936
+ const riskLimitsV2 = this.safeValue(v2ProductsData, 'riskLimitsV2', []);
937
+ riskLimits = this.arrayConcat(riskLimits, riskLimitsV2);
938
+ const currencies = this.safeValue(v2ProductsData, 'currencies', []);
939
+ const riskLimitsById = this.indexBy(riskLimits, 'symbol');
940
+ const v1ProductsById = this.indexBy(v1ProductsData, 'symbol');
941
+ const currenciesByCode = this.indexBy(currencies, 'currency');
942
+ const result = [];
943
+ for (let i = 0; i < products.length; i++) {
944
+ let market = products[i];
945
+ const type = this.safeStringLower(market, 'type');
946
+ if ((type === 'perpetual') || (type === 'perpetualv2')) {
947
+ const id = this.safeString(market, 'symbol');
948
+ const riskLimitValues = this.safeValue(riskLimitsById, id, {});
949
+ market = this.extend(market, riskLimitValues);
950
+ const v1ProductsValues = this.safeValue(v1ProductsById, id, {});
951
+ market = this.extend(market, v1ProductsValues);
952
+ market = this.parseSwapMarket(market);
953
+ }
954
+ else {
955
+ const baseCurrency = this.safeString(market, 'baseCurrency');
956
+ const currencyValues = this.safeValue(currenciesByCode, baseCurrency, {});
957
+ const valueScale = this.safeString(currencyValues, 'valueScale', '8');
958
+ market = this.extend(market, { 'valueScale': valueScale });
959
+ market = this.parseSpotMarket(market);
960
+ }
961
+ result.push(market);
962
+ }
963
+ return result;
964
+ }
965
+ async fetchCurrencies(params = {}) {
966
+ /**
967
+ * @method
968
+ * @name phemex#fetchCurrencies
969
+ * @description fetches all available currencies on an exchange
970
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
971
+ * @returns {object} an associative dictionary of currencies
972
+ */
973
+ const response = await this.v2GetPublicProducts(params);
974
+ //
975
+ // {
976
+ // "code":0,
977
+ // "msg":"OK",
978
+ // "data":{
979
+ // ...,
980
+ // "currencies":[
981
+ // {"currency":"BTC","name":"Bitcoin","code":1,"valueScale":8,"minValueEv":1,"maxValueEv":5000000000000000000,"needAddrTag":0,"status":"Listed","displayCurrency":"BTC","inAssetsDisplay":1,"perpetual":0,"stableCoin":0,"assetsPrecision":8},
982
+ // {"currency":"USD","name":"USD","code":2,"valueScale":4,"minValueEv":1,"maxValueEv":5000000000000000000,"needAddrTag":0,"status":"Listed","displayCurrency":"USD","inAssetsDisplay":1,"perpetual":0,"stableCoin":0,"assetsPrecision":2},
983
+ // {"currency":"USDT","name":"TetherUS","code":3,"valueScale":8,"minValueEv":1,"maxValueEv":5000000000000000000,"needAddrTag":0,"status":"Listed","displayCurrency":"USDT","inAssetsDisplay":1,"perpetual":2,"stableCoin":1,"assetsPrecision":8},
984
+ // ],
985
+ // ...
986
+ // }
987
+ // }
988
+ const data = this.safeValue(response, 'data', {});
989
+ const currencies = this.safeValue(data, 'currencies', []);
990
+ const result = {};
991
+ for (let i = 0; i < currencies.length; i++) {
992
+ const currency = currencies[i];
993
+ const id = this.safeString(currency, 'currency');
994
+ const name = this.safeString(currency, 'name');
995
+ const code = this.safeCurrencyCode(id);
996
+ const status = this.safeString(currency, 'status');
997
+ const valueScaleString = this.safeString(currency, 'valueScale');
998
+ const valueScale = parseInt(valueScaleString);
999
+ const minValueEv = this.safeString(currency, 'minValueEv');
1000
+ const maxValueEv = this.safeString(currency, 'maxValueEv');
1001
+ let minAmount = undefined;
1002
+ let maxAmount = undefined;
1003
+ let precision = undefined;
1004
+ if (valueScale !== undefined) {
1005
+ const precisionString = this.parsePrecision(valueScaleString);
1006
+ precision = this.parseNumber(precisionString);
1007
+ minAmount = this.parseNumber(Precise["default"].stringMul(minValueEv, precisionString));
1008
+ maxAmount = this.parseNumber(Precise["default"].stringMul(maxValueEv, precisionString));
1009
+ }
1010
+ result[code] = {
1011
+ 'id': id,
1012
+ 'info': currency,
1013
+ 'code': code,
1014
+ 'name': name,
1015
+ 'active': status === 'Listed',
1016
+ 'deposit': undefined,
1017
+ 'withdraw': undefined,
1018
+ 'fee': undefined,
1019
+ 'precision': precision,
1020
+ 'limits': {
1021
+ 'amount': {
1022
+ 'min': minAmount,
1023
+ 'max': maxAmount,
1024
+ },
1025
+ 'withdraw': {
1026
+ 'min': undefined,
1027
+ 'max': undefined,
1028
+ },
1029
+ },
1030
+ 'valueScale': valueScale,
1031
+ 'networks': {},
1032
+ };
1033
+ }
1034
+ return result;
1035
+ }
1036
+ customParseBidAsk(bidask, priceKey = 0, amountKey = 1, market = undefined) {
1037
+ if (market === undefined) {
1038
+ throw new errors.ArgumentsRequired(this.id + ' customParseBidAsk() requires a market argument');
1039
+ }
1040
+ let amount = this.safeString(bidask, amountKey);
1041
+ if (market['spot']) {
1042
+ amount = this.fromEv(amount, market);
1043
+ }
1044
+ return [
1045
+ this.parseNumber(this.fromEp(this.safeString(bidask, priceKey), market)),
1046
+ this.parseNumber(amount),
1047
+ ];
1048
+ }
1049
+ customParseOrderBook(orderbook, symbol, timestamp = undefined, bidsKey = 'bids', asksKey = 'asks', priceKey = 0, amountKey = 1, market = undefined) {
1050
+ const result = {
1051
+ 'symbol': symbol,
1052
+ 'timestamp': timestamp,
1053
+ 'datetime': this.iso8601(timestamp),
1054
+ 'nonce': undefined,
1055
+ };
1056
+ const sides = [bidsKey, asksKey];
1057
+ for (let i = 0; i < sides.length; i++) {
1058
+ const side = sides[i];
1059
+ const orders = [];
1060
+ const bidasks = this.safeValue(orderbook, side);
1061
+ for (let k = 0; k < bidasks.length; k++) {
1062
+ orders.push(this.customParseBidAsk(bidasks[k], priceKey, amountKey, market));
1063
+ }
1064
+ result[side] = orders;
1065
+ }
1066
+ result[bidsKey] = this.sortBy(result[bidsKey], 0, true);
1067
+ result[asksKey] = this.sortBy(result[asksKey], 0);
1068
+ return result;
1069
+ }
1070
+ async fetchOrderBook(symbol, limit = undefined, params = {}) {
1071
+ /**
1072
+ * @method
1073
+ * @name phemex#fetchOrderBook
1074
+ * @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
1075
+ * @see https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#queryorderbook
1076
+ * @param {string} symbol unified symbol of the market to fetch the order book for
1077
+ * @param {int} [limit] the maximum amount of order book entries to return
1078
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1079
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
1080
+ */
1081
+ await this.loadMarkets();
1082
+ const market = this.market(symbol);
1083
+ const request = {
1084
+ 'symbol': market['id'],
1085
+ // 'id': 123456789, // optional request id
1086
+ };
1087
+ let response = undefined;
1088
+ if (market['linear'] && market['settle'] === 'USDT') {
1089
+ response = await this.v2GetMdV2Orderbook(this.extend(request, params));
1090
+ }
1091
+ else {
1092
+ if ((limit !== undefined) && (limit <= 30)) {
1093
+ response = await this.v1GetMdOrderbook(this.extend(request, params));
1094
+ }
1095
+ else {
1096
+ response = await this.v1GetMdFullbook(this.extend(request, params));
1097
+ }
1098
+ }
1099
+ //
1100
+ // {
1101
+ // "error": null,
1102
+ // "id": 0,
1103
+ // "result": {
1104
+ // "book": {
1105
+ // "asks": [
1106
+ // [ 23415000000, 105262000 ],
1107
+ // [ 23416000000, 147914000 ],
1108
+ // [ 23419000000, 160914000 ],
1109
+ // ],
1110
+ // "bids": [
1111
+ // [ 23360000000, 32995000 ],
1112
+ // [ 23359000000, 221887000 ],
1113
+ // [ 23356000000, 284599000 ],
1114
+ // ],
1115
+ // },
1116
+ // "depth": 30,
1117
+ // "sequence": 1592059928,
1118
+ // "symbol": "sETHUSDT",
1119
+ // "timestamp": 1592387340020000955,
1120
+ // "type": "snapshot"
1121
+ // }
1122
+ // }
1123
+ //
1124
+ const result = this.safeValue(response, 'result', {});
1125
+ const book = this.safeValue2(result, 'book', 'orderbook_p', {});
1126
+ const timestamp = this.safeIntegerProduct(result, 'timestamp', 0.000001);
1127
+ const orderbook = this.customParseOrderBook(book, symbol, timestamp, 'bids', 'asks', 0, 1, market);
1128
+ orderbook['nonce'] = this.safeInteger(result, 'sequence');
1129
+ return orderbook;
1130
+ }
1131
+ toEn(n, scale) {
1132
+ const stringN = n.toString();
1133
+ const precise = new Precise["default"](stringN);
1134
+ precise.decimals = precise.decimals - scale;
1135
+ precise.reduce();
1136
+ const preciseString = precise.toString();
1137
+ return this.parseToInt(preciseString);
1138
+ }
1139
+ toEv(amount, market = undefined) {
1140
+ if ((amount === undefined) || (market === undefined)) {
1141
+ return amount;
1142
+ }
1143
+ return this.toEn(amount, market['valueScale']);
1144
+ }
1145
+ toEp(price, market = undefined) {
1146
+ if ((price === undefined) || (market === undefined)) {
1147
+ return price;
1148
+ }
1149
+ return this.toEn(price, market['priceScale']);
1150
+ }
1151
+ fromEn(en, scale) {
1152
+ if (en === undefined) {
1153
+ return undefined;
1154
+ }
1155
+ const precise = new Precise["default"](en);
1156
+ precise.decimals = this.sum(precise.decimals, scale);
1157
+ precise.reduce();
1158
+ return precise.toString();
1159
+ }
1160
+ fromEp(ep, market = undefined) {
1161
+ if ((ep === undefined) || (market === undefined)) {
1162
+ return ep;
1163
+ }
1164
+ return this.fromEn(ep, this.safeInteger(market, 'priceScale'));
1165
+ }
1166
+ fromEv(ev, market = undefined) {
1167
+ if ((ev === undefined) || (market === undefined)) {
1168
+ return ev;
1169
+ }
1170
+ return this.fromEn(ev, this.safeInteger(market, 'valueScale'));
1171
+ }
1172
+ fromEr(er, market = undefined) {
1173
+ if ((er === undefined) || (market === undefined)) {
1174
+ return er;
1175
+ }
1176
+ return this.fromEn(er, this.safeInteger(market, 'ratioScale'));
1177
+ }
1178
+ parseOHLCV(ohlcv, market = undefined) {
1179
+ //
1180
+ // [
1181
+ // 1592467200, // timestamp
1182
+ // 300, // interval
1183
+ // 23376000000, // last
1184
+ // 23322000000, // open
1185
+ // 23381000000, // high
1186
+ // 23315000000, // low
1187
+ // 23367000000, // close
1188
+ // 208671000, // base volume
1189
+ // 48759063370, // quote volume
1190
+ // ]
1191
+ //
1192
+ let baseVolume;
1193
+ if ((market !== undefined) && market['spot']) {
1194
+ baseVolume = this.parseNumber(this.fromEv(this.safeString(ohlcv, 7), market));
1195
+ }
1196
+ else {
1197
+ baseVolume = this.safeNumber(ohlcv, 7);
1198
+ }
1199
+ return [
1200
+ this.safeTimestamp(ohlcv, 0),
1201
+ this.parseNumber(this.fromEp(this.safeString(ohlcv, 3), market)),
1202
+ this.parseNumber(this.fromEp(this.safeString(ohlcv, 4), market)),
1203
+ this.parseNumber(this.fromEp(this.safeString(ohlcv, 5), market)),
1204
+ this.parseNumber(this.fromEp(this.safeString(ohlcv, 6), market)),
1205
+ baseVolume,
1206
+ ];
1207
+ }
1208
+ async fetchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
1209
+ /**
1210
+ * @method
1211
+ * @name phemex#fetchOHLCV
1212
+ * @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1213
+ * @see https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#querykline
1214
+ * @see https://github.com/phemex/phemex-api-docs/blob/master/Public-Contract-API-en.md#query-kline
1215
+ * @param {string} symbol unified symbol of the market to fetch OHLCV data for
1216
+ * @param {string} timeframe the length of time each candle represents
1217
+ * @param {int} [since] *only used for USDT settled contracts, otherwise is emulated and not supported by the exchange* timestamp in ms of the earliest candle to fetch
1218
+ * @param {int} [limit] the maximum amount of candles to fetch
1219
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1220
+ * @param {int} [params.until] *USDT settled/ linear swaps only* end time in ms
1221
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
1222
+ */
1223
+ await this.loadMarkets();
1224
+ const market = this.market(symbol);
1225
+ const userLimit = limit;
1226
+ const request = {
1227
+ 'symbol': market['id'],
1228
+ 'resolution': this.safeString(this.timeframes, timeframe, timeframe),
1229
+ };
1230
+ const until = this.safeInteger2(params, 'until', 'to');
1231
+ params = this.omit(params, ['until']);
1232
+ const usesSpecialFromToEndpoint = ((market['linear'] || market['settle'] === 'USDT')) && ((since !== undefined) || (until !== undefined));
1233
+ let maxLimit = 1000;
1234
+ if (usesSpecialFromToEndpoint) {
1235
+ maxLimit = 2000;
1236
+ }
1237
+ if (limit === undefined) {
1238
+ limit = maxLimit;
1239
+ }
1240
+ request['limit'] = Math.min(limit, maxLimit);
1241
+ let response = undefined;
1242
+ if (market['linear'] || market['settle'] === 'USDT') {
1243
+ if ((until !== undefined) || (since !== undefined)) {
1244
+ const candleDuration = this.parseTimeframe(timeframe);
1245
+ if (since !== undefined) {
1246
+ since = Math.round(since / 1000);
1247
+ request['from'] = since;
1248
+ }
1249
+ else {
1250
+ // when 'to' is defined since is mandatory
1251
+ since = (until / 100) - (maxLimit * candleDuration);
1252
+ }
1253
+ if (until !== undefined) {
1254
+ request['to'] = Math.round(until / 1000);
1255
+ }
1256
+ else {
1257
+ // when since is defined 'to' is mandatory
1258
+ let to = since + (maxLimit * candleDuration);
1259
+ const now = this.seconds();
1260
+ if (to > now) {
1261
+ to = now;
1262
+ }
1263
+ request['to'] = to;
1264
+ }
1265
+ response = await this.publicGetMdV2KlineList(this.extend(request, params));
1266
+ }
1267
+ else {
1268
+ response = await this.publicGetMdV2KlineLast(this.extend(request, params));
1269
+ }
1270
+ }
1271
+ else {
1272
+ if (since !== undefined) {
1273
+ // phemex also provides kline query with from/to, however, this interface is NOT recommended and does not work properly.
1274
+ // we do not send since param to the exchange, instead we calculate appropriate limit param
1275
+ const duration = this.parseTimeframe(timeframe) * 1000;
1276
+ const timeDelta = this.milliseconds() - since;
1277
+ limit = this.parseToInt(timeDelta / duration); // setting limit to the number of candles after since
1278
+ }
1279
+ response = await this.publicGetMdV2Kline(this.extend(request, params));
1280
+ }
1281
+ //
1282
+ // {
1283
+ // "code":0,
1284
+ // "msg":"OK",
1285
+ // "data":{
1286
+ // "total":-1,
1287
+ // "rows":[
1288
+ // [1592467200,300,23376000000,23322000000,23381000000,23315000000,23367000000,208671000,48759063370],
1289
+ // [1592467500,300,23367000000,23314000000,23390000000,23311000000,23331000000,234820000,54848948710],
1290
+ // [1592467800,300,23331000000,23385000000,23391000000,23326000000,23387000000,152931000,35747882250],
1291
+ // ]
1292
+ // }
1293
+ // }
1294
+ //
1295
+ const data = this.safeValue(response, 'data', {});
1296
+ const rows = this.safeValue(data, 'rows', []);
1297
+ return this.parseOHLCVs(rows, market, timeframe, since, userLimit);
1298
+ }
1299
+ parseTicker(ticker, market = undefined) {
1300
+ //
1301
+ // spot
1302
+ //
1303
+ // {
1304
+ // "askEp": 943836000000,
1305
+ // "bidEp": 943601000000,
1306
+ // "highEp": 955946000000,
1307
+ // "lastEp": 943803000000,
1308
+ // "lowEp": 924973000000,
1309
+ // "openEp": 948693000000,
1310
+ // "symbol": "sBTCUSDT",
1311
+ // "timestamp": 1592471203505728630,
1312
+ // "turnoverEv": 111822826123103,
1313
+ // "volumeEv": 11880532281
1314
+ // }
1315
+ //
1316
+ // swap
1317
+ //
1318
+ // {
1319
+ // "askEp": 2332500,
1320
+ // "bidEp": 2331000,
1321
+ // "fundingRateEr": 10000,
1322
+ // "highEp": 2380000,
1323
+ // "indexEp": 2329057,
1324
+ // "lastEp": 2331500,
1325
+ // "lowEp": 2274000,
1326
+ // "markEp": 2329232,
1327
+ // "openEp": 2337500,
1328
+ // "openInterest": 1298050,
1329
+ // "predFundingRateEr": 19921,
1330
+ // "symbol": "ETHUSD",
1331
+ // "timestamp": 1592474241582701416,
1332
+ // "turnoverEv": 47228362330,
1333
+ // "volume": 4053863
1334
+ // }
1335
+ // linear swap v2
1336
+ //
1337
+ // {
1338
+ // "closeRp":"16820.5",
1339
+ // "fundingRateRr":"0.0001",
1340
+ // "highRp":"16962.1",
1341
+ // "indexPriceRp":"16830.15651565",
1342
+ // "lowRp":"16785",
1343
+ // "markPriceRp":"16830.97534951",
1344
+ // "openInterestRv":"1323.596",
1345
+ // "openRp":"16851.7",
1346
+ // "predFundingRateRr":"0.0001",
1347
+ // "symbol":"BTCUSDT",
1348
+ // "timestamp":"1672142789065593096",
1349
+ // "turnoverRv":"124835296.0538",
1350
+ // "volumeRq":"7406.95"
1351
+ // }
1352
+ //
1353
+ const marketId = this.safeString(ticker, 'symbol');
1354
+ market = this.safeMarket(marketId, market);
1355
+ const symbol = market['symbol'];
1356
+ const timestamp = this.safeIntegerProduct(ticker, 'timestamp', 0.000001);
1357
+ const last = this.fromEp(this.safeString2(ticker, 'lastEp', 'closeRp'), market);
1358
+ const quoteVolume = this.fromEr(this.safeString2(ticker, 'turnoverEv', 'turnoverRv'), market);
1359
+ let baseVolume = this.safeString(ticker, 'volume');
1360
+ if (baseVolume === undefined) {
1361
+ baseVolume = this.fromEv(this.safeString2(ticker, 'volumeEv', 'volumeRq'), market);
1362
+ }
1363
+ const open = this.fromEp(this.safeString(ticker, 'openEp'), market);
1364
+ return this.safeTicker({
1365
+ 'symbol': symbol,
1366
+ 'timestamp': timestamp,
1367
+ 'datetime': this.iso8601(timestamp),
1368
+ 'high': this.fromEp(this.safeString2(ticker, 'highEp', 'highRp'), market),
1369
+ 'low': this.fromEp(this.safeString2(ticker, 'lowEp', 'lowRp'), market),
1370
+ 'bid': this.fromEp(this.safeString(ticker, 'bidEp'), market),
1371
+ 'bidVolume': undefined,
1372
+ 'ask': this.fromEp(this.safeString(ticker, 'askEp'), market),
1373
+ 'askVolume': undefined,
1374
+ 'vwap': undefined,
1375
+ 'open': open,
1376
+ 'close': last,
1377
+ 'last': last,
1378
+ 'previousClose': undefined,
1379
+ 'change': undefined,
1380
+ 'percentage': undefined,
1381
+ 'average': undefined,
1382
+ 'baseVolume': baseVolume,
1383
+ 'quoteVolume': quoteVolume,
1384
+ 'info': ticker,
1385
+ }, market);
1386
+ }
1387
+ async fetchTicker(symbol, params = {}) {
1388
+ /**
1389
+ * @method
1390
+ * @name phemex#fetchTicker
1391
+ * @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
1392
+ * @see https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#query24hrsticker
1393
+ * @param {string} symbol unified symbol of the market to fetch the ticker for
1394
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1395
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
1396
+ */
1397
+ await this.loadMarkets();
1398
+ const market = this.market(symbol);
1399
+ const request = {
1400
+ 'symbol': market['id'],
1401
+ // 'id': 123456789, // optional request id
1402
+ };
1403
+ let response = undefined;
1404
+ if (market['swap']) {
1405
+ if (market['inverse'] || market['settle'] === 'USD') {
1406
+ response = await this.v1GetMdTicker24hr(this.extend(request, params));
1407
+ }
1408
+ else {
1409
+ response = await this.v2GetMdV2Ticker24hr(this.extend(request, params));
1410
+ }
1411
+ }
1412
+ else {
1413
+ response = await this.v1GetMdSpotTicker24hr(this.extend(request, params));
1414
+ }
1415
+ //
1416
+ // spot
1417
+ //
1418
+ // {
1419
+ // "error": null,
1420
+ // "id": 0,
1421
+ // "result": {
1422
+ // "askEp": 943836000000,
1423
+ // "bidEp": 943601000000,
1424
+ // "highEp": 955946000000,
1425
+ // "lastEp": 943803000000,
1426
+ // "lowEp": 924973000000,
1427
+ // "openEp": 948693000000,
1428
+ // "symbol": "sBTCUSDT",
1429
+ // "timestamp": 1592471203505728630,
1430
+ // "turnoverEv": 111822826123103,
1431
+ // "volumeEv": 11880532281
1432
+ // }
1433
+ // }
1434
+ //
1435
+ // swap
1436
+ //
1437
+ // {
1438
+ // "error": null,
1439
+ // "id": 0,
1440
+ // "result": {
1441
+ // "askEp": 2332500,
1442
+ // "bidEp": 2331000,
1443
+ // "fundingRateEr": 10000,
1444
+ // "highEp": 2380000,
1445
+ // "indexEp": 2329057,
1446
+ // "lastEp": 2331500,
1447
+ // "lowEp": 2274000,
1448
+ // "markEp": 2329232,
1449
+ // "openEp": 2337500,
1450
+ // "openInterest": 1298050,
1451
+ // "predFundingRateEr": 19921,
1452
+ // "symbol": "ETHUSD",
1453
+ // "timestamp": 1592474241582701416,
1454
+ // "turnoverEv": 47228362330,
1455
+ // "volume": 4053863
1456
+ // }
1457
+ // }
1458
+ //
1459
+ const result = this.safeValue(response, 'result', {});
1460
+ return this.parseTicker(result, market);
1461
+ }
1462
+ async fetchTickers(symbols = undefined, params = {}) {
1463
+ /**
1464
+ * @method
1465
+ * @name phemex#fetchTickers
1466
+ * @description fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
1467
+ * @see https://phemex-docs.github.io/#query-24-hours-ticker-for-all-symbols-2 // spot
1468
+ * @see https://phemex-docs.github.io/#query-24-ticker-for-all-symbols // linear
1469
+ * @see https://phemex-docs.github.io/#query-24-hours-ticker-for-all-symbols // inverse
1470
+ * @param {string[]|undefined} symbols unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
1471
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1472
+ * @returns {object} a dictionary of [ticker structures]{@link https://docs.ccxt.com/#/?id=ticker-structure}
1473
+ */
1474
+ await this.loadMarkets();
1475
+ let market = undefined;
1476
+ if (symbols !== undefined) {
1477
+ const first = this.safeValue(symbols, 0);
1478
+ market = this.market(first);
1479
+ }
1480
+ let type = undefined;
1481
+ [type, params] = this.handleMarketTypeAndParams('fetchTickers', market, params);
1482
+ let subType = undefined;
1483
+ [subType, params] = this.handleSubTypeAndParams('fetchTickers', market, params);
1484
+ const query = this.omit(params, 'type');
1485
+ let response = undefined;
1486
+ if (type === 'spot') {
1487
+ response = await this.v1GetMdSpotTicker24hrAll(query);
1488
+ }
1489
+ else if (subType === 'inverse' || this.safeString(market, 'settle') === 'USD') {
1490
+ response = await this.v1GetMdTicker24hrAll(query);
1491
+ }
1492
+ else {
1493
+ response = await this.v2GetMdV2Ticker24hrAll(query);
1494
+ }
1495
+ const result = this.safeValue(response, 'result', []);
1496
+ return this.parseTickers(result, symbols);
1497
+ }
1498
+ async fetchTrades(symbol, since = undefined, limit = undefined, params = {}) {
1499
+ /**
1500
+ * @method
1501
+ * @name phemex#fetchTrades
1502
+ * @description get the list of most recent trades for a particular symbol
1503
+ * @see https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#querytrades
1504
+ * @param {string} symbol unified symbol of the market to fetch trades for
1505
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
1506
+ * @param {int} [limit] the maximum amount of trades to fetch
1507
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1508
+ * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
1509
+ */
1510
+ await this.loadMarkets();
1511
+ const market = this.market(symbol);
1512
+ const request = {
1513
+ 'symbol': market['id'],
1514
+ // 'id': 123456789, // optional request id
1515
+ };
1516
+ let response = undefined;
1517
+ if (market['linear'] && market['settle'] === 'USDT') {
1518
+ response = await this.v2GetMdV2Trade(this.extend(request, params));
1519
+ }
1520
+ else {
1521
+ response = await this.v1GetMdTrade(this.extend(request, params));
1522
+ }
1523
+ //
1524
+ // {
1525
+ // "error": null,
1526
+ // "id": 0,
1527
+ // "result": {
1528
+ // "sequence": 1315644947,
1529
+ // "symbol": "BTCUSD",
1530
+ // "trades": [
1531
+ // [ 1592541746712239749, 13156448570000, "Buy", 93070000, 40173 ],
1532
+ // [ 1592541740434625085, 13156447110000, "Sell", 93065000, 5000 ],
1533
+ // [ 1592541732958241616, 13156441390000, "Buy", 93070000, 3460 ],
1534
+ // ],
1535
+ // "type": "snapshot"
1536
+ // }
1537
+ // }
1538
+ //
1539
+ const result = this.safeValue(response, 'result', {});
1540
+ const trades = this.safeValue2(result, 'trades', 'trades_p', []);
1541
+ return this.parseTrades(trades, market, since, limit);
1542
+ }
1543
+ parseTrade(trade, market = undefined) {
1544
+ //
1545
+ // fetchTrades (public) spot & contract
1546
+ //
1547
+ // [
1548
+ // 1592541746712239749,
1549
+ // 13156448570000,
1550
+ // "Buy",
1551
+ // 93070000,
1552
+ // 40173
1553
+ // ]
1554
+ //
1555
+ // fetchTrades (public) perp
1556
+ //
1557
+ // [
1558
+ // 1675690986063435800,
1559
+ // "Sell",
1560
+ // "22857.4",
1561
+ // "0.269"
1562
+ // ]
1563
+ //
1564
+ // fetchMyTrades (private)
1565
+ //
1566
+ // spot
1567
+ //
1568
+ // {
1569
+ // "qtyType": "ByQuote",
1570
+ // "transactTimeNs": 1589450974800550100,
1571
+ // "clOrdID": "8ba59d40-df25-d4b0-14cf-0703f44e9690",
1572
+ // "orderID": "b2b7018d-f02f-4c59-b4cf-051b9c2d2e83",
1573
+ // "symbol": "sBTCUSDT",
1574
+ // "side": "Buy",
1575
+ // "priceEP": 970056000000,
1576
+ // "baseQtyEv": 0,
1577
+ // "quoteQtyEv": 1000000000,
1578
+ // "action": "New",
1579
+ // "execStatus": "MakerFill",
1580
+ // "ordStatus": "Filled",
1581
+ // "ordType": "Limit",
1582
+ // "execInst": "None",
1583
+ // "timeInForce": "GoodTillCancel",
1584
+ // "stopDirection": "UNSPECIFIED",
1585
+ // "tradeType": "Trade",
1586
+ // "stopPxEp": 0,
1587
+ // "execId": "c6bd8979-07ba-5946-b07e-f8b65135dbb1",
1588
+ // "execPriceEp": 970056000000,
1589
+ // "execBaseQtyEv": 103000,
1590
+ // "execQuoteQtyEv": 999157680,
1591
+ // "leavesBaseQtyEv": 0,
1592
+ // "leavesQuoteQtyEv": 0,
1593
+ // "execFeeEv": 0,
1594
+ // "feeRateEr": 0
1595
+ // "baseCurrency": "BTC",
1596
+ // "quoteCurrency": "USDT",
1597
+ // "feeCurrency": "BTC"
1598
+ // }
1599
+ //
1600
+ // swap
1601
+ //
1602
+ // {
1603
+ // "transactTimeNs": 1578026629824704800,
1604
+ // "symbol": "BTCUSD",
1605
+ // "currency": "BTC",
1606
+ // "action": "Replace",
1607
+ // "side": "Sell",
1608
+ // "tradeType": "Trade",
1609
+ // "execQty": 700,
1610
+ // "execPriceEp": 71500000,
1611
+ // "orderQty": 700,
1612
+ // "priceEp": 71500000,
1613
+ // "execValueEv": 9790209,
1614
+ // "feeRateEr": -25000,
1615
+ // "execFeeEv": -2447,
1616
+ // "ordType": "Limit",
1617
+ // "execID": "b01671a1-5ddc-5def-b80a-5311522fd4bf",
1618
+ // "orderID": "b63bc982-be3a-45e0-8974-43d6375fb626",
1619
+ // "clOrdID": "uuid-1577463487504",
1620
+ // "execStatus": "MakerFill"
1621
+ // }
1622
+ // perpetual
1623
+ // {
1624
+ // "accountID": 9328670003,
1625
+ // "action": "New",
1626
+ // "actionBy": "ByUser",
1627
+ // "actionTimeNs": 1666858780876924611,
1628
+ // "addedSeq": 77751555,
1629
+ // "apRp": "0",
1630
+ // "bonusChangedAmountRv": "0",
1631
+ // "bpRp": "0",
1632
+ // "clOrdID": "c0327a7d-9064-62a9-28f6-2db9aaaa04e0",
1633
+ // "closedPnlRv": "0",
1634
+ // "closedSize": "0",
1635
+ // "code": 0,
1636
+ // "cumFeeRv": "0",
1637
+ // "cumQty": "0",
1638
+ // "cumValueRv": "0",
1639
+ // "curAccBalanceRv": "1508.489893982237",
1640
+ // "curAssignedPosBalanceRv": "24.62786650928",
1641
+ // "curBonusBalanceRv": "0",
1642
+ // "curLeverageRr": "-10",
1643
+ // "curPosSide": "Buy",
1644
+ // "curPosSize": "0.043",
1645
+ // "curPosTerm": 1,
1646
+ // "curPosValueRv": "894.0689",
1647
+ // "curRiskLimitRv": "1000000",
1648
+ // "currency": "USDT",
1649
+ // "cxlRejReason": 0,
1650
+ // "displayQty": "0.003",
1651
+ // "execFeeRv": "0",
1652
+ // "execID": "00000000-0000-0000-0000-000000000000",
1653
+ // "execPriceRp": "20723.7",
1654
+ // "execQty": "0",
1655
+ // "execSeq": 77751555,
1656
+ // "execStatus": "New",
1657
+ // "execValueRv": "0",
1658
+ // "feeRateRr": "0",
1659
+ // "leavesQty": "0.003",
1660
+ // "leavesValueRv": "63.4503",
1661
+ // "message": "No error",
1662
+ // "ordStatus": "New",
1663
+ // "ordType": "Market",
1664
+ // "orderID": "fa64c6f2-47a4-4929-aab4-b7fa9bbc4323",
1665
+ // "orderQty": "0.003",
1666
+ // "pegOffsetValueRp": "0",
1667
+ // "posSide": "Long",
1668
+ // "priceRp": "21150.1",
1669
+ // "relatedPosTerm": 1,
1670
+ // "relatedReqNum": 11,
1671
+ // "side": "Buy",
1672
+ // "slTrigger": "ByMarkPrice",
1673
+ // "stopLossRp": "0",
1674
+ // "stopPxRp": "0",
1675
+ // "symbol": "BTCUSDT",
1676
+ // "takeProfitRp": "0",
1677
+ // "timeInForce": "ImmediateOrCancel",
1678
+ // "tpTrigger": "ByLastPrice",
1679
+ // "tradeType": "Amend",
1680
+ // "transactTimeNs": 1666858780881545305,
1681
+ // "userID": 932867
1682
+ // }
1683
+ //
1684
+ // swap - USDT
1685
+ //
1686
+ // {
1687
+ // "createdAt": 1666226932259,
1688
+ // "symbol": "ETHUSDT",
1689
+ // "currency": "USDT",
1690
+ // "action": 1,
1691
+ // "tradeType": 1,
1692
+ // "execQtyRq": "0.01",
1693
+ // "execPriceRp": "1271.9",
1694
+ // "side": 1,
1695
+ // "orderQtyRq": "0.78",
1696
+ // "priceRp": "1271.9",
1697
+ // "execValueRv": "12.719",
1698
+ // "feeRateRr": "0.0001",
1699
+ // "execFeeRv": "0.0012719",
1700
+ // "ordType": 2,
1701
+ // "execId": "8718cae",
1702
+ // "execStatus": 6
1703
+ // }
1704
+ //
1705
+ let priceString;
1706
+ let amountString;
1707
+ let timestamp;
1708
+ let id = undefined;
1709
+ let side = undefined;
1710
+ let costString = undefined;
1711
+ let type = undefined;
1712
+ let fee = undefined;
1713
+ let feeCostString = undefined;
1714
+ let feeRateString = undefined;
1715
+ let feeCurrencyCode = undefined;
1716
+ const marketId = this.safeString(trade, 'symbol');
1717
+ market = this.safeMarket(marketId, market);
1718
+ const symbol = market['symbol'];
1719
+ let orderId = undefined;
1720
+ let takerOrMaker = undefined;
1721
+ if (Array.isArray(trade)) {
1722
+ const tradeLength = trade.length;
1723
+ timestamp = this.safeIntegerProduct(trade, 0, 0.000001);
1724
+ if (tradeLength > 4) {
1725
+ id = this.safeString(trade, tradeLength - 4);
1726
+ }
1727
+ side = this.safeStringLower(trade, tradeLength - 3);
1728
+ priceString = this.safeString(trade, tradeLength - 2);
1729
+ amountString = this.safeString(trade, tradeLength - 1);
1730
+ if (typeof trade[tradeLength - 2] === 'number') {
1731
+ priceString = this.fromEp(priceString, market);
1732
+ amountString = this.fromEv(amountString, market);
1733
+ }
1734
+ }
1735
+ else {
1736
+ timestamp = this.safeIntegerProduct(trade, 'transactTimeNs', 0.000001);
1737
+ if (timestamp === undefined) {
1738
+ timestamp = this.safeInteger(trade, 'createdAt');
1739
+ }
1740
+ id = this.safeString2(trade, 'execId', 'execID');
1741
+ orderId = this.safeString(trade, 'orderID');
1742
+ if (market['settle'] === 'USDT') {
1743
+ const sideId = this.safeStringLower(trade, 'side');
1744
+ if ((sideId === 'buy') || (sideId === 'sell')) {
1745
+ side = sideId;
1746
+ }
1747
+ else if (sideId !== undefined) {
1748
+ side = (sideId === '1') ? 'buy' : 'sell';
1749
+ }
1750
+ const ordType = this.safeString(trade, 'ordType');
1751
+ if (ordType === '1') {
1752
+ type = 'market';
1753
+ }
1754
+ else if (ordType === '2') {
1755
+ type = 'limit';
1756
+ }
1757
+ priceString = this.safeString(trade, 'execPriceRp');
1758
+ amountString = this.safeString(trade, 'execQtyRq');
1759
+ costString = this.safeString(trade, 'execValueRv');
1760
+ feeCostString = this.safeString(trade, 'execFeeRv');
1761
+ feeRateString = this.safeString(trade, 'feeRateRr');
1762
+ const currencyId = this.safeString(trade, 'currency');
1763
+ feeCurrencyCode = this.safeCurrencyCode(currencyId);
1764
+ }
1765
+ else {
1766
+ side = this.safeStringLower(trade, 'side');
1767
+ type = this.parseOrderType(this.safeString(trade, 'ordType'));
1768
+ const execStatus = this.safeString(trade, 'execStatus');
1769
+ if (execStatus === 'MakerFill') {
1770
+ takerOrMaker = 'maker';
1771
+ }
1772
+ priceString = this.fromEp(this.safeString(trade, 'execPriceEp'), market);
1773
+ amountString = this.fromEv(this.safeString(trade, 'execBaseQtyEv'), market);
1774
+ amountString = this.safeString(trade, 'execQty', amountString);
1775
+ costString = this.fromEr(this.safeString2(trade, 'execQuoteQtyEv', 'execValueEv'), market);
1776
+ feeCostString = this.fromEr(this.safeString(trade, 'execFeeEv'), market);
1777
+ if (feeCostString !== undefined) {
1778
+ feeRateString = this.fromEr(this.safeString(trade, 'feeRateEr'), market);
1779
+ if (market['spot']) {
1780
+ feeCurrencyCode = this.safeCurrencyCode(this.safeString(trade, 'feeCurrency'));
1781
+ }
1782
+ else {
1783
+ const info = this.safeValue(market, 'info');
1784
+ if (info !== undefined) {
1785
+ const settlementCurrencyId = this.safeString(info, 'settlementCurrency');
1786
+ feeCurrencyCode = this.safeCurrencyCode(settlementCurrencyId);
1787
+ }
1788
+ }
1789
+ }
1790
+ }
1791
+ fee = {
1792
+ 'cost': feeCostString,
1793
+ 'rate': feeRateString,
1794
+ 'currency': feeCurrencyCode,
1795
+ };
1796
+ }
1797
+ return this.safeTrade({
1798
+ 'info': trade,
1799
+ 'id': id,
1800
+ 'symbol': symbol,
1801
+ 'timestamp': timestamp,
1802
+ 'datetime': this.iso8601(timestamp),
1803
+ 'order': orderId,
1804
+ 'type': type,
1805
+ 'side': side,
1806
+ 'takerOrMaker': takerOrMaker,
1807
+ 'price': priceString,
1808
+ 'amount': amountString,
1809
+ 'cost': costString,
1810
+ 'fee': fee,
1811
+ }, market);
1812
+ }
1813
+ parseSpotBalance(response) {
1814
+ //
1815
+ // {
1816
+ // "code":0,
1817
+ // "msg":"",
1818
+ // "data":[
1819
+ // {
1820
+ // "currency":"USDT",
1821
+ // "balanceEv":0,
1822
+ // "lockedTradingBalanceEv":0,
1823
+ // "lockedWithdrawEv":0,
1824
+ // "lastUpdateTimeNs":1592065834511322514,
1825
+ // "walletVid":0
1826
+ // },
1827
+ // {
1828
+ // "currency":"ETH",
1829
+ // "balanceEv":0,
1830
+ // "lockedTradingBalanceEv":0,
1831
+ // "lockedWithdrawEv":0,
1832
+ // "lastUpdateTimeNs":1592065834511322514,
1833
+ // "walletVid":0
1834
+ // }
1835
+ // ]
1836
+ // }
1837
+ //
1838
+ let timestamp = undefined;
1839
+ const result = { 'info': response };
1840
+ const data = this.safeValue(response, 'data', []);
1841
+ for (let i = 0; i < data.length; i++) {
1842
+ const balance = data[i];
1843
+ const currencyId = this.safeString(balance, 'currency');
1844
+ const code = this.safeCurrencyCode(currencyId);
1845
+ const currency = this.safeValue(this.currencies, code, {});
1846
+ const scale = this.safeInteger(currency, 'valueScale', 8);
1847
+ const account = this.account();
1848
+ const balanceEv = this.safeString(balance, 'balanceEv');
1849
+ const lockedTradingBalanceEv = this.safeString(balance, 'lockedTradingBalanceEv');
1850
+ const lockedWithdrawEv = this.safeString(balance, 'lockedWithdrawEv');
1851
+ const total = this.fromEn(balanceEv, scale);
1852
+ const lockedTradingBalance = this.fromEn(lockedTradingBalanceEv, scale);
1853
+ const lockedWithdraw = this.fromEn(lockedWithdrawEv, scale);
1854
+ const used = Precise["default"].stringAdd(lockedTradingBalance, lockedWithdraw);
1855
+ const lastUpdateTimeNs = this.safeIntegerProduct(balance, 'lastUpdateTimeNs', 0.000001);
1856
+ timestamp = (timestamp === undefined) ? lastUpdateTimeNs : Math.max(timestamp, lastUpdateTimeNs);
1857
+ account['total'] = total;
1858
+ account['used'] = used;
1859
+ result[code] = account;
1860
+ }
1861
+ result['timestamp'] = timestamp;
1862
+ result['datetime'] = this.iso8601(timestamp);
1863
+ return this.safeBalance(result);
1864
+ }
1865
+ parseSwapBalance(response) {
1866
+ // usdt
1867
+ // {
1868
+ // "info": {
1869
+ // "code": "0",
1870
+ // "msg": '',
1871
+ // "data": {
1872
+ // "account": {
1873
+ // "userID": "940666",
1874
+ // "accountId": "9406660003",
1875
+ // "currency": "USDT",
1876
+ // "accountBalanceRv": "99.93143972",
1877
+ // "totalUsedBalanceRv": "0.40456",
1878
+ // "bonusBalanceRv": "0"
1879
+ // },
1880
+ // }
1881
+ //
1882
+ // {
1883
+ // "code":0,
1884
+ // "msg":"",
1885
+ // "data":{
1886
+ // "account":{
1887
+ // "accountId":6192120001,
1888
+ // "currency":"BTC",
1889
+ // "accountBalanceEv":1254744,
1890
+ // "totalUsedBalanceEv":0,
1891
+ // "bonusBalanceEv":1254744
1892
+ // }
1893
+ // }
1894
+ // }
1895
+ //
1896
+ const result = { 'info': response };
1897
+ const data = this.safeValue(response, 'data', {});
1898
+ const balance = this.safeValue(data, 'account', {});
1899
+ const currencyId = this.safeString(balance, 'currency');
1900
+ const code = this.safeCurrencyCode(currencyId);
1901
+ const currency = this.currency(code);
1902
+ const valueScale = this.safeInteger(currency, 'valueScale', 8);
1903
+ const account = this.account();
1904
+ const accountBalanceEv = this.safeString2(balance, 'accountBalanceEv', 'accountBalanceRv');
1905
+ const totalUsedBalanceEv = this.safeString2(balance, 'totalUsedBalanceEv', 'totalUsedBalanceRv');
1906
+ const needsConversion = (code !== 'USDT');
1907
+ account['total'] = needsConversion ? this.fromEn(accountBalanceEv, valueScale) : accountBalanceEv;
1908
+ account['used'] = needsConversion ? this.fromEn(totalUsedBalanceEv, valueScale) : totalUsedBalanceEv;
1909
+ result[code] = account;
1910
+ return this.safeBalance(result);
1911
+ }
1912
+ async fetchBalance(params = {}) {
1913
+ /**
1914
+ * @method
1915
+ * @name phemex#fetchBalance
1916
+ * @description query for balance and get the amount of funds available for trading or funds locked in orders
1917
+ * @see https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#query-account-positions
1918
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1919
+ * @param {string} [params.type] spot or swap
1920
+ * @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
1921
+ */
1922
+ await this.loadMarkets();
1923
+ let type = undefined;
1924
+ [type, params] = this.handleMarketTypeAndParams('fetchBalance', undefined, params);
1925
+ const code = this.safeString(params, 'code');
1926
+ params = this.omit(params, ['type', 'code']);
1927
+ let response = undefined;
1928
+ const request = {};
1929
+ if ((type !== 'spot') && (type !== 'swap')) {
1930
+ throw new errors.BadRequest(this.id + ' does not support ' + type + ' markets, only spot and swap');
1931
+ }
1932
+ if (type === 'swap') {
1933
+ let settle = undefined;
1934
+ [settle, params] = this.handleOptionAndParams(params, 'fetchBalance', 'settle');
1935
+ if (code !== undefined || settle !== undefined) {
1936
+ let coin = undefined;
1937
+ if (code !== undefined) {
1938
+ coin = code;
1939
+ }
1940
+ else {
1941
+ coin = settle;
1942
+ }
1943
+ const currency = this.currency(coin);
1944
+ request['currency'] = currency['id'];
1945
+ if (currency['id'] === 'USDT') {
1946
+ response = await this.privateGetGAccountsAccountPositions(this.extend(request, params));
1947
+ }
1948
+ else {
1949
+ response = await this.privateGetAccountsAccountPositions(this.extend(request, params));
1950
+ }
1951
+ }
1952
+ else {
1953
+ const currency = this.safeString(params, 'currency');
1954
+ if (currency === undefined) {
1955
+ throw new errors.ArgumentsRequired(this.id + ' fetchBalance() requires a code parameter or a currency or settle parameter for ' + type + ' type');
1956
+ }
1957
+ response = await this.privateGetSpotWallets(this.extend(request, params));
1958
+ }
1959
+ }
1960
+ else {
1961
+ response = await this.privateGetSpotWallets(this.extend(request, params));
1962
+ }
1963
+ //
1964
+ // usdt
1965
+ // {
1966
+ // "info": {
1967
+ // "code": "0",
1968
+ // "msg": '',
1969
+ // "data": {
1970
+ // "account": {
1971
+ // "userID": "940666",
1972
+ // "accountId": "9406660003",
1973
+ // "currency": "USDT",
1974
+ // "accountBalanceRv": "99.93143972",
1975
+ // "totalUsedBalanceRv": "0.40456",
1976
+ // "bonusBalanceRv": "0"
1977
+ // },
1978
+ // }
1979
+ //
1980
+ // spot
1981
+ //
1982
+ // {
1983
+ // "code":0,
1984
+ // "msg":"",
1985
+ // "data":[
1986
+ // {
1987
+ // "currency":"USDT",
1988
+ // "balanceEv":0,
1989
+ // "lockedTradingBalanceEv":0,
1990
+ // "lockedWithdrawEv":0,
1991
+ // "lastUpdateTimeNs":1592065834511322514,
1992
+ // "walletVid":0
1993
+ // },
1994
+ // {
1995
+ // "currency":"ETH",
1996
+ // "balanceEv":0,
1997
+ // "lockedTradingBalanceEv":0,
1998
+ // "lockedWithdrawEv":0,
1999
+ // "lastUpdateTimeNs":1592065834511322514,
2000
+ // "walletVid":0
2001
+ // }
2002
+ // ]
2003
+ // }
2004
+ //
2005
+ // swap
2006
+ //
2007
+ // {
2008
+ // "code":0,
2009
+ // "msg":"",
2010
+ // "data":{
2011
+ // "account":{
2012
+ // "accountId":6192120001,
2013
+ // "currency":"BTC",
2014
+ // "accountBalanceEv":1254744,
2015
+ // "totalUsedBalanceEv":0,
2016
+ // "bonusBalanceEv":1254744
2017
+ // },
2018
+ // "positions":[
2019
+ // {
2020
+ // "accountID":6192120001,
2021
+ // "symbol":"BTCUSD",
2022
+ // "currency":"BTC",
2023
+ // "side":"None",
2024
+ // "positionStatus":"Normal",
2025
+ // "crossMargin":false,
2026
+ // "leverageEr":0,
2027
+ // "leverage":0E-8,
2028
+ // "initMarginReqEr":1000000,
2029
+ // "initMarginReq":0.01000000,
2030
+ // "maintMarginReqEr":500000,
2031
+ // "maintMarginReq":0.00500000,
2032
+ // "riskLimitEv":10000000000,
2033
+ // "riskLimit":100.00000000,
2034
+ // "size":0,
2035
+ // "value":0E-8,
2036
+ // "valueEv":0,
2037
+ // "avgEntryPriceEp":0,
2038
+ // "avgEntryPrice":0E-8,
2039
+ // "posCostEv":0,
2040
+ // "posCost":0E-8,
2041
+ // "assignedPosBalanceEv":0,
2042
+ // "assignedPosBalance":0E-8,
2043
+ // "bankruptCommEv":0,
2044
+ // "bankruptComm":0E-8,
2045
+ // "bankruptPriceEp":0,
2046
+ // "bankruptPrice":0E-8,
2047
+ // "positionMarginEv":0,
2048
+ // "positionMargin":0E-8,
2049
+ // "liquidationPriceEp":0,
2050
+ // "liquidationPrice":0E-8,
2051
+ // "deleveragePercentileEr":0,
2052
+ // "deleveragePercentile":0E-8,
2053
+ // "buyValueToCostEr":1150750,
2054
+ // "buyValueToCost":0.01150750,
2055
+ // "sellValueToCostEr":1149250,
2056
+ // "sellValueToCost":0.01149250,
2057
+ // "markPriceEp":96359083,
2058
+ // "markPrice":9635.90830000,
2059
+ // "markValueEv":0,
2060
+ // "markValue":null,
2061
+ // "unRealisedPosLossEv":0,
2062
+ // "unRealisedPosLoss":null,
2063
+ // "estimatedOrdLossEv":0,
2064
+ // "estimatedOrdLoss":0E-8,
2065
+ // "usedBalanceEv":0,
2066
+ // "usedBalance":0E-8,
2067
+ // "takeProfitEp":0,
2068
+ // "takeProfit":null,
2069
+ // "stopLossEp":0,
2070
+ // "stopLoss":null,
2071
+ // "realisedPnlEv":0,
2072
+ // "realisedPnl":null,
2073
+ // "cumRealisedPnlEv":0,
2074
+ // "cumRealisedPnl":null
2075
+ // }
2076
+ // ]
2077
+ // }
2078
+ // }
2079
+ //
2080
+ const result = (type === 'swap') ? this.parseSwapBalance(response) : this.parseSpotBalance(response);
2081
+ return result;
2082
+ }
2083
+ parseOrderStatus(status) {
2084
+ const statuses = {
2085
+ 'Created': 'open',
2086
+ 'Untriggered': 'open',
2087
+ 'Deactivated': 'closed',
2088
+ 'Triggered': 'open',
2089
+ 'Rejected': 'rejected',
2090
+ 'New': 'open',
2091
+ 'PartiallyFilled': 'open',
2092
+ 'Filled': 'closed',
2093
+ 'Canceled': 'canceled',
2094
+ '1': 'open',
2095
+ '2': 'canceled',
2096
+ '3': 'closed',
2097
+ '4': 'canceled',
2098
+ '5': 'open',
2099
+ '6': 'open',
2100
+ '7': 'closed',
2101
+ '8': 'canceled',
2102
+ };
2103
+ return this.safeString(statuses, status, status);
2104
+ }
2105
+ parseOrderType(type) {
2106
+ const types = {
2107
+ '1': 'market',
2108
+ '2': 'limit',
2109
+ '3': 'stop',
2110
+ '4': 'stopLimit',
2111
+ '5': 'market',
2112
+ '6': 'limit',
2113
+ '7': 'market',
2114
+ '8': 'market',
2115
+ '9': 'stopLimit',
2116
+ '10': 'market',
2117
+ 'Limit': 'limit',
2118
+ 'Market': 'market',
2119
+ };
2120
+ return this.safeString(types, type, type);
2121
+ }
2122
+ parseTimeInForce(timeInForce) {
2123
+ const timeInForces = {
2124
+ 'GoodTillCancel': 'GTC',
2125
+ 'PostOnly': 'PO',
2126
+ 'ImmediateOrCancel': 'IOC',
2127
+ 'FillOrKill': 'FOK',
2128
+ };
2129
+ return this.safeString(timeInForces, timeInForce, timeInForce);
2130
+ }
2131
+ parseSpotOrder(order, market = undefined) {
2132
+ //
2133
+ // spot
2134
+ //
2135
+ // {
2136
+ // "orderID": "d1d09454-cabc-4a23-89a7-59d43363f16d",
2137
+ // "clOrdID": "309bcd5c-9f6e-4a68-b775-4494542eb5cb",
2138
+ // "priceEp": 0,
2139
+ // "action": "New",
2140
+ // "trigger": "UNSPECIFIED",
2141
+ // "pegPriceType": "UNSPECIFIED",
2142
+ // "stopDirection": "UNSPECIFIED",
2143
+ // "bizError": 0,
2144
+ // "symbol": "sBTCUSDT",
2145
+ // "side": "Buy",
2146
+ // "baseQtyEv": 0,
2147
+ // "ordType": "Limit",
2148
+ // "timeInForce": "GoodTillCancel",
2149
+ // "ordStatus": "Created",
2150
+ // "cumFeeEv": 0,
2151
+ // "cumBaseQtyEv": 0,
2152
+ // "cumQuoteQtyEv": 0,
2153
+ // "leavesBaseQtyEv": 0,
2154
+ // "leavesQuoteQtyEv": 0,
2155
+ // "avgPriceEp": 0,
2156
+ // "cumBaseAmountEv": 0,
2157
+ // "cumQuoteAmountEv": 0,
2158
+ // "quoteQtyEv": 0,
2159
+ // "qtyType": "ByBase",
2160
+ // "stopPxEp": 0,
2161
+ // "pegOffsetValueEp": 0
2162
+ // }
2163
+ //
2164
+ // {
2165
+ // "orderID":"99232c3e-3d6a-455f-98cc-2061cdfe91bc",
2166
+ // "stopPxEp":0,
2167
+ // "avgPriceEp":0,
2168
+ // "qtyType":"ByBase",
2169
+ // "leavesBaseQtyEv":0,
2170
+ // "leavesQuoteQtyEv":0,
2171
+ // "baseQtyEv":"1000000000",
2172
+ // "feeCurrency":"4",
2173
+ // "stopDirection":"UNSPECIFIED",
2174
+ // "symbol":"sETHUSDT",
2175
+ // "side":"Buy",
2176
+ // "quoteQtyEv":250000000000,
2177
+ // "priceEp":25000000000,
2178
+ // "ordType":"Limit",
2179
+ // "timeInForce":"GoodTillCancel",
2180
+ // "ordStatus":"Rejected",
2181
+ // "execStatus":"NewRejected",
2182
+ // "createTimeNs":1592675305266037130,
2183
+ // "cumFeeEv":0,
2184
+ // "cumBaseValueEv":0,
2185
+ // "cumQuoteValueEv":0
2186
+ // }
2187
+ //
2188
+ const id = this.safeString(order, 'orderID');
2189
+ let clientOrderId = this.safeString(order, 'clOrdID');
2190
+ if ((clientOrderId !== undefined) && (clientOrderId.length < 1)) {
2191
+ clientOrderId = undefined;
2192
+ }
2193
+ const marketId = this.safeString(order, 'symbol');
2194
+ market = this.safeMarket(marketId, market);
2195
+ const symbol = market['symbol'];
2196
+ const price = this.fromEp(this.safeString(order, 'priceEp'), market);
2197
+ const amount = this.fromEv(this.safeString(order, 'baseQtyEv'), market);
2198
+ const remaining = this.omitZero(this.fromEv(this.safeString(order, 'leavesBaseQtyEv'), market));
2199
+ const filled = this.fromEv(this.safeString2(order, 'cumBaseQtyEv', 'cumBaseValueEv'), market);
2200
+ const cost = this.fromEr(this.safeString2(order, 'cumQuoteValueEv', 'quoteQtyEv'), market);
2201
+ const average = this.fromEp(this.safeString(order, 'avgPriceEp'), market);
2202
+ const status = this.parseOrderStatus(this.safeString(order, 'ordStatus'));
2203
+ const side = this.safeStringLower(order, 'side');
2204
+ const type = this.parseOrderType(this.safeString(order, 'ordType'));
2205
+ const timestamp = this.safeIntegerProduct2(order, 'actionTimeNs', 'createTimeNs', 0.000001);
2206
+ let fee = undefined;
2207
+ const feeCost = this.fromEv(this.safeString(order, 'cumFeeEv'), market);
2208
+ if (feeCost !== undefined) {
2209
+ fee = {
2210
+ 'cost': feeCost,
2211
+ 'currency': undefined,
2212
+ };
2213
+ }
2214
+ const timeInForce = this.parseTimeInForce(this.safeString(order, 'timeInForce'));
2215
+ const stopPrice = this.parseNumber(this.omitZero(this.fromEp(this.safeString(order, 'stopPxEp'))));
2216
+ const postOnly = (timeInForce === 'PO');
2217
+ return this.safeOrder({
2218
+ 'info': order,
2219
+ 'id': id,
2220
+ 'clientOrderId': clientOrderId,
2221
+ 'timestamp': timestamp,
2222
+ 'datetime': this.iso8601(timestamp),
2223
+ 'lastTradeTimestamp': undefined,
2224
+ 'symbol': symbol,
2225
+ 'type': type,
2226
+ 'timeInForce': timeInForce,
2227
+ 'postOnly': postOnly,
2228
+ 'side': side,
2229
+ 'price': price,
2230
+ 'stopPrice': stopPrice,
2231
+ 'triggerPrice': stopPrice,
2232
+ 'amount': amount,
2233
+ 'cost': cost,
2234
+ 'average': average,
2235
+ 'filled': filled,
2236
+ 'remaining': remaining,
2237
+ 'status': status,
2238
+ 'fee': fee,
2239
+ 'trades': undefined,
2240
+ }, market);
2241
+ }
2242
+ parseOrderSide(side) {
2243
+ const sides = {
2244
+ '1': 'buy',
2245
+ '2': 'sell',
2246
+ };
2247
+ return this.safeString(sides, side, side);
2248
+ }
2249
+ parseSwapOrder(order, market = undefined) {
2250
+ //
2251
+ // {
2252
+ // "bizError":0,
2253
+ // "orderID":"7a1ad384-44a3-4e54-a102-de4195a29e32",
2254
+ // "clOrdID":"",
2255
+ // "symbol":"ETHUSD",
2256
+ // "side":"Buy",
2257
+ // "actionTimeNs":1592668973945065381,
2258
+ // "transactTimeNs":0,
2259
+ // "orderType":"Market",
2260
+ // "priceEp":2267500,
2261
+ // "price":226.75000000,
2262
+ // "orderQty":1,
2263
+ // "displayQty":0,
2264
+ // "timeInForce":"ImmediateOrCancel",
2265
+ // "reduceOnly":false,
2266
+ // "closedPnlEv":0,
2267
+ // "closedPnl":0E-8,
2268
+ // "closedSize":0,
2269
+ // "cumQty":0,
2270
+ // "cumValueEv":0,
2271
+ // "cumValue":0E-8,
2272
+ // "leavesQty":1,
2273
+ // "leavesValueEv":11337,
2274
+ // "leavesValue":1.13370000,
2275
+ // "stopDirection":"UNSPECIFIED",
2276
+ // "stopPxEp":0,
2277
+ // "stopPx":0E-8,
2278
+ // "trigger":"UNSPECIFIED",
2279
+ // "pegOffsetValueEp":0,
2280
+ // "execStatus":"PendingNew",
2281
+ // "pegPriceType":"UNSPECIFIED",
2282
+ // "ordStatus":"Created",
2283
+ // "execInst": "ReduceOnly"
2284
+ // }
2285
+ //
2286
+ // usdt
2287
+ // {
2288
+ // "bizError":"0",
2289
+ // "orderID":"bd720dff-5647-4596-aa4e-656bac87aaad",
2290
+ // "clOrdID":"ccxt2022843dffac9477b497",
2291
+ // "symbol":"LTCUSDT",
2292
+ // "side":"Buy",
2293
+ // "actionTimeNs":"1677667878751724052",
2294
+ // "transactTimeNs":"1677667878754017434",
2295
+ // "orderType":"Limit",
2296
+ // "priceRp":"40",
2297
+ // "orderQtyRq":"0.1",
2298
+ // "displayQtyRq":"0.1",
2299
+ // "timeInForce":"GoodTillCancel",
2300
+ // "reduceOnly":false,
2301
+ // "closedPnlRv":"0",
2302
+ // "closedSizeRq":"0",
2303
+ // "cumQtyRq":"0",
2304
+ // "cumValueRv":"0",
2305
+ // "leavesQtyRq":"0.1",
2306
+ // "leavesValueRv":"4",
2307
+ // "stopDirection":"UNSPECIFIED",
2308
+ // "stopPxRp":"0",
2309
+ // "trigger":"UNSPECIFIED",
2310
+ // "pegOffsetValueRp":"0",
2311
+ // "pegOffsetProportionRr":"0",
2312
+ // "execStatus":"New",
2313
+ // "pegPriceType":"UNSPECIFIED",
2314
+ // "ordStatus":"New",
2315
+ // "execInst":"None",
2316
+ // "takeProfitRp":"0",
2317
+ // "stopLossRp":"0"
2318
+ // }
2319
+ //
2320
+ // v2 orderList
2321
+ // {
2322
+ // "createdAt":"1677686231301",
2323
+ // "symbol":"LTCUSDT",
2324
+ // "orderQtyRq":"0.2",
2325
+ // "side":"1",
2326
+ // "posSide":"3",
2327
+ // "priceRp":"50",
2328
+ // "execQtyRq":"0",
2329
+ // "leavesQtyRq":"0.2",
2330
+ // "execPriceRp":"0",
2331
+ // "orderValueRv":"10",
2332
+ // "leavesValueRv":"10",
2333
+ // "cumValueRv":"0",
2334
+ // "stopDirection":"0",
2335
+ // "stopPxRp":"0",
2336
+ // "trigger":"0",
2337
+ // "actionBy":"1",
2338
+ // "execFeeRv":"0",
2339
+ // "ordType":"2",
2340
+ // "ordStatus":"5",
2341
+ // "clOrdId":"4b3b188",
2342
+ // "orderId":"4b3b1884-87cf-4897-b596-6693b7ed84d1",
2343
+ // "execStatus":"5",
2344
+ // "bizError":"0",
2345
+ // "totalPnlRv":null,
2346
+ // "avgTransactPriceRp":null,
2347
+ // "orderDetailsVos":null,
2348
+ // "tradeType":"0"
2349
+ // }
2350
+ //
2351
+ const id = this.safeString2(order, 'orderID', 'orderId');
2352
+ let clientOrderId = this.safeString2(order, 'clOrdID', 'clOrdId');
2353
+ if ((clientOrderId !== undefined) && (clientOrderId.length < 1)) {
2354
+ clientOrderId = undefined;
2355
+ }
2356
+ const marketId = this.safeString(order, 'symbol');
2357
+ const symbol = this.safeSymbol(marketId, market);
2358
+ const status = this.parseOrderStatus(this.safeString(order, 'ordStatus'));
2359
+ const side = this.parseOrderSide(this.safeStringLower(order, 'side'));
2360
+ const type = this.parseOrderType(this.safeString(order, 'orderType'));
2361
+ let price = this.safeString(order, 'priceRp');
2362
+ if (price === undefined) {
2363
+ price = this.fromEp(this.safeString(order, 'priceEp'), market);
2364
+ }
2365
+ const amount = this.safeNumber2(order, 'orderQty', 'orderQtyRq');
2366
+ const filled = this.safeNumber2(order, 'cumQty', 'cumQtyRq');
2367
+ const remaining = this.safeNumber2(order, 'leavesQty', 'leavesQtyRq');
2368
+ let timestamp = this.safeIntegerProduct(order, 'actionTimeNs', 0.000001);
2369
+ if (timestamp === undefined) {
2370
+ timestamp = this.safeInteger(order, 'createdAt');
2371
+ }
2372
+ const cost = this.safeNumber2(order, 'cumValue', 'cumValueRv');
2373
+ let lastTradeTimestamp = this.safeIntegerProduct(order, 'transactTimeNs', 0.000001);
2374
+ if (lastTradeTimestamp === 0) {
2375
+ lastTradeTimestamp = undefined;
2376
+ }
2377
+ const timeInForce = this.parseTimeInForce(this.safeString(order, 'timeInForce'));
2378
+ const stopPrice = this.omitZero(this.safeNumber2(order, 'stopPx', 'stopPxRp'));
2379
+ const postOnly = (timeInForce === 'PO');
2380
+ let reduceOnly = this.safeValue(order, 'reduceOnly');
2381
+ const execInst = this.safeString(order, 'execInst');
2382
+ if (execInst === 'ReduceOnly') {
2383
+ reduceOnly = true;
2384
+ }
2385
+ const takeProfit = this.safeString(order, 'takeProfitRp');
2386
+ const stopLoss = this.safeString(order, 'stopLossRp');
2387
+ return this.safeOrder({
2388
+ 'info': order,
2389
+ 'id': id,
2390
+ 'clientOrderId': clientOrderId,
2391
+ 'datetime': this.iso8601(timestamp),
2392
+ 'timestamp': timestamp,
2393
+ 'lastTradeTimestamp': lastTradeTimestamp,
2394
+ 'symbol': symbol,
2395
+ 'type': type,
2396
+ 'timeInForce': timeInForce,
2397
+ 'postOnly': postOnly,
2398
+ 'reduceOnly': reduceOnly,
2399
+ 'side': side,
2400
+ 'price': price,
2401
+ 'stopPrice': stopPrice,
2402
+ 'triggerPrice': stopPrice,
2403
+ 'takeProfitPrice': takeProfit,
2404
+ 'stopLossPrice': stopLoss,
2405
+ 'amount': amount,
2406
+ 'filled': filled,
2407
+ 'remaining': remaining,
2408
+ 'cost': cost,
2409
+ 'average': undefined,
2410
+ 'status': status,
2411
+ 'fee': undefined,
2412
+ 'trades': undefined,
2413
+ });
2414
+ }
2415
+ parseOrder(order, market = undefined) {
2416
+ const isSwap = this.safeValue(market, 'swap', false);
2417
+ const hasPnl = ('closedPnl' in order);
2418
+ if (isSwap || hasPnl) {
2419
+ return this.parseSwapOrder(order, market);
2420
+ }
2421
+ return this.parseSpotOrder(order, market);
2422
+ }
2423
+ async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
2424
+ /**
2425
+ * @method
2426
+ * @name phemex#createOrder
2427
+ * @description create a trade order
2428
+ * @see https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#place-order
2429
+ * @param {string} symbol unified symbol of the market to create an order in
2430
+ * @param {string} type 'market' or 'limit'
2431
+ * @param {string} side 'buy' or 'sell'
2432
+ * @param {float} amount how much of currency you want to trade in units of base currency
2433
+ * @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
2434
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2435
+ * @param {object} [params.takeProfit] *swap only* *takeProfit object in params* containing the triggerPrice at which the attached take profit order will be triggered (perpetual swap markets only)
2436
+ * @param {float} [params.takeProfit.triggerPrice] take profit trigger price
2437
+ * @param {object} [params.stopLoss] *swap only* *stopLoss object in params* containing the triggerPrice at which the attached stop loss order will be triggered (perpetual swap markets only)
2438
+ * @param {float} [params.stopLoss.triggerPrice] stop loss trigger price
2439
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
2440
+ */
2441
+ await this.loadMarkets();
2442
+ const market = this.market(symbol);
2443
+ const requestSide = this.capitalize(side);
2444
+ type = this.capitalize(type);
2445
+ const reduceOnly = this.safeValue(params, 'reduceOnly');
2446
+ const request = {
2447
+ // common
2448
+ 'symbol': market['id'],
2449
+ 'side': requestSide,
2450
+ 'ordType': type, // Market, Limit, Stop, StopLimit, MarketIfTouched, LimitIfTouched (additionally for contract-markets: MarketAsLimit, StopAsLimit, MarketIfTouchedAsLimit)
2451
+ // 'stopPxEp': this.toEp (stopPx, market), // for conditional orders
2452
+ // 'priceEp': this.toEp (price, market), // required for limit orders
2453
+ // 'timeInForce': 'GoodTillCancel', // GoodTillCancel, PostOnly, ImmediateOrCancel, FillOrKill
2454
+ // ----------------------------------------------------------------
2455
+ // spot
2456
+ // 'qtyType': 'ByBase', // ByBase, ByQuote
2457
+ // 'quoteQtyEv': this.toEp (cost, market),
2458
+ // 'baseQtyEv': this.toEv (amount, market),
2459
+ // 'trigger': 'ByLastPrice', // required for conditional orders
2460
+ // ----------------------------------------------------------------
2461
+ // swap
2462
+ // 'clOrdID': this.uuid (), // max length 40
2463
+ // 'orderQty': this.amountToPrecision (amount, symbol),
2464
+ // 'reduceOnly': false,
2465
+ // 'closeOnTrigger': false, // implicit reduceOnly and cancel other orders in the same direction
2466
+ // 'takeProfitEp': this.toEp (takeProfit, market),
2467
+ // 'stopLossEp': this.toEp (stopLossEp, market),
2468
+ // 'triggerType': 'ByMarkPrice', // ByMarkPrice, ByLastPrice
2469
+ // 'pegOffsetValueEp': integer, // Trailing offset from current price. Negative value when position is long, positive when position is short
2470
+ // 'pegPriceType': 'TrailingStopPeg', // TrailingTakeProfitPeg
2471
+ // 'text': 'comment',
2472
+ // 'posSide': Position direction - "Merged" for oneway mode , "Long" / "Short" for hedge mode
2473
+ };
2474
+ const clientOrderId = this.safeString2(params, 'clOrdID', 'clientOrderId');
2475
+ const stopLoss = this.safeValue(params, 'stopLoss');
2476
+ const stopLossDefined = (stopLoss !== undefined);
2477
+ const takeProfit = this.safeValue(params, 'takeProfit');
2478
+ const takeProfitDefined = (takeProfit !== undefined);
2479
+ if (clientOrderId === undefined) {
2480
+ const brokerId = this.safeString(this.options, 'brokerId', 'CCXT123456');
2481
+ if (brokerId !== undefined) {
2482
+ request['clOrdID'] = brokerId + this.uuid16();
2483
+ }
2484
+ }
2485
+ else {
2486
+ request['clOrdID'] = clientOrderId;
2487
+ params = this.omit(params, ['clOrdID', 'clientOrderId']);
2488
+ }
2489
+ const stopPrice = this.safeStringN(params, ['stopPx', 'stopPrice', 'triggerPrice']);
2490
+ if (stopPrice !== undefined) {
2491
+ if (market['settle'] === 'USDT') {
2492
+ request['stopPxRp'] = this.priceToPrecision(symbol, stopPrice);
2493
+ }
2494
+ else {
2495
+ request['stopPxEp'] = this.toEp(stopPrice, market);
2496
+ }
2497
+ }
2498
+ params = this.omit(params, ['stopPx', 'stopPrice', 'stopLoss', 'takeProfit', 'triggerPrice']);
2499
+ if (market['spot']) {
2500
+ let qtyType = this.safeValue(params, 'qtyType', 'ByBase');
2501
+ if ((type === 'Market') || (type === 'Stop') || (type === 'MarketIfTouched')) {
2502
+ if (price !== undefined) {
2503
+ qtyType = 'ByQuote';
2504
+ }
2505
+ }
2506
+ request['qtyType'] = qtyType;
2507
+ if (qtyType === 'ByQuote') {
2508
+ let cost = this.safeNumber(params, 'cost');
2509
+ params = this.omit(params, 'cost');
2510
+ if (this.options['createOrderByQuoteRequiresPrice']) {
2511
+ if (price !== undefined) {
2512
+ const amountString = this.numberToString(amount);
2513
+ const priceString = this.numberToString(price);
2514
+ const quoteAmount = Precise["default"].stringMul(amountString, priceString);
2515
+ cost = this.parseNumber(quoteAmount);
2516
+ }
2517
+ else if (cost === undefined) {
2518
+ throw new errors.ArgumentsRequired(this.id + ' createOrder() ' + qtyType + ' requires a price argument or a cost parameter');
2519
+ }
2520
+ }
2521
+ cost = (cost === undefined) ? amount : cost;
2522
+ const costString = cost.toString();
2523
+ request['quoteQtyEv'] = this.toEv(costString, market);
2524
+ }
2525
+ else {
2526
+ const amountString = amount.toString();
2527
+ request['baseQtyEv'] = this.toEv(amountString, market);
2528
+ }
2529
+ }
2530
+ else if (market['swap']) {
2531
+ let posSide = this.safeStringLower(params, 'posSide');
2532
+ if (posSide === undefined) {
2533
+ posSide = 'Merged';
2534
+ }
2535
+ posSide = this.capitalize(posSide);
2536
+ request['posSide'] = posSide;
2537
+ if (reduceOnly !== undefined) {
2538
+ request['reduceOnly'] = reduceOnly;
2539
+ }
2540
+ if (market['settle'] === 'USDT') {
2541
+ request['orderQtyRq'] = amount;
2542
+ }
2543
+ else {
2544
+ request['orderQty'] = parseInt(amount);
2545
+ }
2546
+ if (stopPrice !== undefined) {
2547
+ const triggerType = this.safeString(params, 'triggerType', 'ByMarkPrice');
2548
+ request['triggerType'] = triggerType;
2549
+ }
2550
+ if (stopLossDefined || takeProfitDefined) {
2551
+ if (stopLossDefined) {
2552
+ const stopLossTriggerPrice = this.safeValue2(stopLoss, 'triggerPrice', 'stopPrice');
2553
+ if (stopLossTriggerPrice === undefined) {
2554
+ throw new errors.InvalidOrder(this.id + ' createOrder() requires a trigger price in params["stopLoss"]["triggerPrice"], or params["stopLoss"]["stopPrice"] for a stop loss order');
2555
+ }
2556
+ if (market['settle'] === 'USDT') {
2557
+ request['stopLossRp'] = this.priceToPrecision(symbol, stopLossTriggerPrice);
2558
+ }
2559
+ else {
2560
+ request['stopLossEp'] = this.toEp(stopLossTriggerPrice, market);
2561
+ }
2562
+ const stopLossTriggerPriceType = this.safeString2(stopLoss, 'triggerPriceType', 'slTrigger');
2563
+ if (stopLossTriggerPriceType !== undefined) {
2564
+ if (market['settle'] === 'USDT') {
2565
+ if ((stopLossTriggerPriceType !== 'ByMarkPrice') && (stopLossTriggerPriceType !== 'ByLastPrice') && (stopLossTriggerPriceType !== 'ByIndexPrice') && (stopLossTriggerPriceType !== 'ByAskPrice') && (stopLossTriggerPriceType !== 'ByBidPrice') && (stopLossTriggerPriceType !== 'ByMarkPriceLimit') && (stopLossTriggerPriceType !== 'ByLastPriceLimit')) {
2566
+ throw new errors.InvalidOrder(this.id + ' createOrder() take profit trigger price type must be one of "ByMarkPrice", "ByIndexPrice", "ByAskPrice", "ByBidPrice", "ByMarkPriceLimit", "ByLastPriceLimit" or "ByLastPrice"');
2567
+ }
2568
+ }
2569
+ else {
2570
+ if ((stopLossTriggerPriceType !== 'ByMarkPrice') && (stopLossTriggerPriceType !== 'ByLastPrice')) {
2571
+ throw new errors.InvalidOrder(this.id + ' createOrder() take profit trigger price type must be one of "ByMarkPrice", or "ByLastPrice"');
2572
+ }
2573
+ }
2574
+ request['slTrigger'] = stopLossTriggerPriceType;
2575
+ }
2576
+ }
2577
+ if (takeProfitDefined) {
2578
+ const takeProfitTriggerPrice = this.safeValue2(takeProfit, 'triggerPrice', 'stopPrice');
2579
+ if (takeProfitTriggerPrice === undefined) {
2580
+ throw new errors.InvalidOrder(this.id + ' createOrder() requires a trigger price in params["takeProfit"]["triggerPrice"], or params["takeProfit"]["stopPrice"] for a take profit order');
2581
+ }
2582
+ if (market['settle'] === 'USDT') {
2583
+ request['takeProfitRp'] = this.priceToPrecision(symbol, takeProfitTriggerPrice);
2584
+ }
2585
+ else {
2586
+ request['takeProfitEp'] = this.toEp(takeProfitTriggerPrice, market);
2587
+ }
2588
+ const takeProfitTriggerPriceType = this.safeString2(stopLoss, 'triggerPriceType', 'tpTrigger');
2589
+ if (takeProfitTriggerPriceType !== undefined) {
2590
+ if (market['settle'] === 'USDT') {
2591
+ if ((takeProfitTriggerPriceType !== 'ByMarkPrice') && (takeProfitTriggerPriceType !== 'ByLastPrice') && (takeProfitTriggerPriceType !== 'ByIndexPrice') && (takeProfitTriggerPriceType !== 'ByAskPrice') && (takeProfitTriggerPriceType !== 'ByBidPrice') && (takeProfitTriggerPriceType !== 'ByMarkPriceLimit') && (takeProfitTriggerPriceType !== 'ByLastPriceLimit')) {
2592
+ throw new errors.InvalidOrder(this.id + ' createOrder() take profit trigger price type must be one of "ByMarkPrice", "ByIndexPrice", "ByAskPrice", "ByBidPrice", "ByMarkPriceLimit", "ByLastPriceLimit" or "ByLastPrice"');
2593
+ }
2594
+ }
2595
+ else {
2596
+ if ((takeProfitTriggerPriceType !== 'ByMarkPrice') && (takeProfitTriggerPriceType !== 'ByLastPrice')) {
2597
+ throw new errors.InvalidOrder(this.id + ' createOrder() take profit trigger price type must be one of "ByMarkPrice", or "ByLastPrice"');
2598
+ }
2599
+ }
2600
+ request['tpTrigger'] = takeProfitTriggerPriceType;
2601
+ }
2602
+ }
2603
+ }
2604
+ }
2605
+ if ((type === 'Limit') || (type === 'StopLimit') || (type === 'LimitIfTouched')) {
2606
+ if (market['settle'] === 'USDT') {
2607
+ request['priceRp'] = this.priceToPrecision(symbol, price);
2608
+ }
2609
+ else {
2610
+ const priceString = this.numberToString(price);
2611
+ request['priceEp'] = this.toEp(priceString, market);
2612
+ }
2613
+ }
2614
+ const takeProfitPrice = this.safeString(params, 'takeProfitPrice');
2615
+ if (takeProfitPrice !== undefined) {
2616
+ if (market['settle'] === 'USDT') {
2617
+ request['takeProfitRp'] = this.priceToPrecision(symbol, takeProfitPrice);
2618
+ }
2619
+ else {
2620
+ request['takeProfitEp'] = this.toEp(takeProfitPrice, market);
2621
+ }
2622
+ params = this.omit(params, 'takeProfitPrice');
2623
+ }
2624
+ const stopLossPrice = this.safeString(params, 'stopLossPrice');
2625
+ if (stopLossPrice !== undefined) {
2626
+ if (market['settle'] === 'USDT') {
2627
+ request['stopLossRp'] = this.priceToPrecision(symbol, stopLossPrice);
2628
+ }
2629
+ else {
2630
+ request['stopLossEp'] = this.toEp(stopLossPrice, market);
2631
+ }
2632
+ params = this.omit(params, 'stopLossPrice');
2633
+ }
2634
+ params = this.omit(params, 'reduceOnly');
2635
+ let response = undefined;
2636
+ if (market['settle'] === 'USDT') {
2637
+ response = await this.privatePostGOrders(this.extend(request, params));
2638
+ }
2639
+ else if (market['contract']) {
2640
+ response = await this.privatePostOrders(this.extend(request, params));
2641
+ }
2642
+ else {
2643
+ response = await this.privatePostSpotOrders(this.extend(request, params));
2644
+ }
2645
+ //
2646
+ // spot
2647
+ //
2648
+ // {
2649
+ // "code": 0,
2650
+ // "msg": "",
2651
+ // "data": {
2652
+ // "orderID": "d1d09454-cabc-4a23-89a7-59d43363f16d",
2653
+ // "clOrdID": "309bcd5c-9f6e-4a68-b775-4494542eb5cb",
2654
+ // "priceEp": 0,
2655
+ // "action": "New",
2656
+ // "trigger": "UNSPECIFIED",
2657
+ // "pegPriceType": "UNSPECIFIED",
2658
+ // "stopDirection": "UNSPECIFIED",
2659
+ // "bizError": 0,
2660
+ // "symbol": "sBTCUSDT",
2661
+ // "side": "Buy",
2662
+ // "baseQtyEv": 0,
2663
+ // "ordType": "Limit",
2664
+ // "timeInForce": "GoodTillCancel",
2665
+ // "ordStatus": "Created",
2666
+ // "cumFeeEv": 0,
2667
+ // "cumBaseQtyEv": 0,
2668
+ // "cumQuoteQtyEv": 0,
2669
+ // "leavesBaseQtyEv": 0,
2670
+ // "leavesQuoteQtyEv": 0,
2671
+ // "avgPriceEp": 0,
2672
+ // "cumBaseAmountEv": 0,
2673
+ // "cumQuoteAmountEv": 0,
2674
+ // "quoteQtyEv": 0,
2675
+ // "qtyType": "ByBase",
2676
+ // "stopPxEp": 0,
2677
+ // "pegOffsetValueEp": 0
2678
+ // }
2679
+ // }
2680
+ //
2681
+ // swap
2682
+ //
2683
+ // {
2684
+ // "code":0,
2685
+ // "msg":"",
2686
+ // "data":{
2687
+ // "bizError":0,
2688
+ // "orderID":"7a1ad384-44a3-4e54-a102-de4195a29e32",
2689
+ // "clOrdID":"",
2690
+ // "symbol":"ETHUSD",
2691
+ // "side":"Buy",
2692
+ // "actionTimeNs":1592668973945065381,
2693
+ // "transactTimeNs":0,
2694
+ // "orderType":"Market",
2695
+ // "priceEp":2267500,
2696
+ // "price":226.75000000,
2697
+ // "orderQty":1,
2698
+ // "displayQty":0,
2699
+ // "timeInForce":"ImmediateOrCancel",
2700
+ // "reduceOnly":false,
2701
+ // "closedPnlEv":0,
2702
+ // "closedPnl":0E-8,
2703
+ // "closedSize":0,
2704
+ // "cumQty":0,
2705
+ // "cumValueEv":0,
2706
+ // "cumValue":0E-8,
2707
+ // "leavesQty":1,
2708
+ // "leavesValueEv":11337,
2709
+ // "leavesValue":1.13370000,
2710
+ // "stopDirection":"UNSPECIFIED",
2711
+ // "stopPxEp":0,
2712
+ // "stopPx":0E-8,
2713
+ // "trigger":"UNSPECIFIED",
2714
+ // "pegOffsetValueEp":0,
2715
+ // "execStatus":"PendingNew",
2716
+ // "pegPriceType":"UNSPECIFIED",
2717
+ // "ordStatus":"Created"
2718
+ // }
2719
+ // }
2720
+ //
2721
+ const data = this.safeValue(response, 'data', {});
2722
+ return this.parseOrder(data, market);
2723
+ }
2724
+ async editOrder(id, symbol, type = undefined, side = undefined, amount = undefined, price = undefined, params = {}) {
2725
+ /**
2726
+ * @method
2727
+ * @name phemex#editOrder
2728
+ * @description edit a trade order
2729
+ * @see https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#amend-order-by-orderid
2730
+ * @param {string} id cancel order id
2731
+ * @param {string} symbol unified symbol of the market to create an order in
2732
+ * @param {string} type 'market' or 'limit'
2733
+ * @param {string} side 'buy' or 'sell'
2734
+ * @param {float} amount how much of currency you want to trade in units of base currency
2735
+ * @param {float} [price] the price at which the order is to be fullfilled, in units of the base currency, ignored in market orders
2736
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2737
+ * @param {string} [params.posSide] either 'Merged' or 'Long' or 'Short'
2738
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
2739
+ */
2740
+ await this.loadMarkets();
2741
+ const market = this.market(symbol);
2742
+ const request = {
2743
+ 'symbol': market['id'],
2744
+ };
2745
+ const clientOrderId = this.safeString2(params, 'clientOrderId', 'clOrdID');
2746
+ params = this.omit(params, ['clientOrderId', 'clOrdID']);
2747
+ const isUSDTSettled = (market['settle'] === 'USDT');
2748
+ if (clientOrderId !== undefined) {
2749
+ request['clOrdID'] = clientOrderId;
2750
+ }
2751
+ else {
2752
+ request['orderID'] = id;
2753
+ }
2754
+ if (price !== undefined) {
2755
+ if (isUSDTSettled) {
2756
+ request['priceRp'] = this.priceToPrecision(market['symbol'], price);
2757
+ }
2758
+ else {
2759
+ request['priceEp'] = this.toEp(price, market);
2760
+ }
2761
+ }
2762
+ // Note the uppercase 'V' in 'baseQtyEV' request. that is exchange's requirement at this moment. However, to avoid mistakes from user side, let's support lowercased 'baseQtyEv' too
2763
+ const finalQty = this.safeString(params, 'baseQtyEv');
2764
+ params = this.omit(params, ['baseQtyEv']);
2765
+ if (finalQty !== undefined) {
2766
+ request['baseQtyEV'] = finalQty;
2767
+ }
2768
+ else if (amount !== undefined) {
2769
+ if (isUSDTSettled) {
2770
+ request['baseQtyEV'] = this.amountToPrecision(market['symbol'], amount);
2771
+ }
2772
+ else {
2773
+ request['baseQtyEV'] = this.toEv(amount, market);
2774
+ }
2775
+ }
2776
+ const stopPrice = this.safeString2(params, 'stopPx', 'stopPrice');
2777
+ if (stopPrice !== undefined) {
2778
+ if (isUSDTSettled) {
2779
+ request['stopPxRp'] = this.priceToPrecision(symbol, stopPrice);
2780
+ }
2781
+ else {
2782
+ request['stopPxEp'] = this.toEp(stopPrice, market);
2783
+ }
2784
+ }
2785
+ params = this.omit(params, ['stopPx', 'stopPrice']);
2786
+ let response = undefined;
2787
+ if (isUSDTSettled) {
2788
+ const posSide = this.safeString(params, 'posSide');
2789
+ if (posSide === undefined) {
2790
+ request['posSide'] = 'Merged';
2791
+ }
2792
+ response = await this.privatePutGOrdersReplace(this.extend(request, params));
2793
+ }
2794
+ else if (market['swap']) {
2795
+ response = await this.privatePutOrdersReplace(this.extend(request, params));
2796
+ }
2797
+ else {
2798
+ response = await this.privatePutSpotOrders(this.extend(request, params));
2799
+ }
2800
+ const data = this.safeValue(response, 'data', {});
2801
+ return this.parseOrder(data, market);
2802
+ }
2803
+ async cancelOrder(id, symbol = undefined, params = {}) {
2804
+ /**
2805
+ * @method
2806
+ * @name phemex#cancelOrder
2807
+ * @description cancels an open order
2808
+ * @see https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#cancel-single-order-by-orderid
2809
+ * @param {string} id order id
2810
+ * @param {string} symbol unified symbol of the market the order was made in
2811
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2812
+ * @param {string} [params.posSide] either 'Merged' or 'Long' or 'Short'
2813
+ * @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
2814
+ */
2815
+ if (symbol === undefined) {
2816
+ throw new errors.ArgumentsRequired(this.id + ' cancelOrder() requires a symbol argument');
2817
+ }
2818
+ await this.loadMarkets();
2819
+ const market = this.market(symbol);
2820
+ const request = {
2821
+ 'symbol': market['id'],
2822
+ };
2823
+ const clientOrderId = this.safeString2(params, 'clientOrderId', 'clOrdID');
2824
+ params = this.omit(params, ['clientOrderId', 'clOrdID']);
2825
+ if (clientOrderId !== undefined) {
2826
+ request['clOrdID'] = clientOrderId;
2827
+ }
2828
+ else {
2829
+ request['orderID'] = id;
2830
+ }
2831
+ let response = undefined;
2832
+ if (market['settle'] === 'USDT') {
2833
+ const posSide = this.safeString(params, 'posSide');
2834
+ if (posSide === undefined) {
2835
+ request['posSide'] = 'Merged';
2836
+ }
2837
+ response = await this.privateDeleteGOrdersCancel(this.extend(request, params));
2838
+ }
2839
+ else if (market['swap']) {
2840
+ response = await this.privateDeleteOrdersCancel(this.extend(request, params));
2841
+ }
2842
+ else {
2843
+ response = await this.privateDeleteSpotOrders(this.extend(request, params));
2844
+ }
2845
+ const data = this.safeValue(response, 'data', {});
2846
+ return this.parseOrder(data, market);
2847
+ }
2848
+ async cancelAllOrders(symbol = undefined, params = {}) {
2849
+ /**
2850
+ * @method
2851
+ * @name phemex#cancelAllOrders
2852
+ * @description cancel all open orders in a market
2853
+ * @see https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#cancelall
2854
+ * @param {string} symbol unified market symbol of the market to cancel orders in
2855
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2856
+ * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
2857
+ */
2858
+ if (symbol === undefined) {
2859
+ throw new errors.ArgumentsRequired(this.id + ' cancelAllOrders() requires a symbol argument');
2860
+ }
2861
+ await this.loadMarkets();
2862
+ const market = this.market(symbol);
2863
+ const request = {
2864
+ 'symbol': market['id'],
2865
+ // 'untriggerred': false, // false to cancel non-conditional orders, true to cancel conditional orders
2866
+ // 'text': 'up to 40 characters max',
2867
+ };
2868
+ let response = undefined;
2869
+ if (market['settle'] === 'USDT') {
2870
+ response = await this.privateDeleteGOrdersAll(this.extend(request, params));
2871
+ }
2872
+ else if (market['swap']) {
2873
+ response = await this.privateDeleteOrdersAll(this.extend(request, params));
2874
+ }
2875
+ else {
2876
+ response = await this.privateDeleteSpotOrdersAll(this.extend(request, params));
2877
+ }
2878
+ return response;
2879
+ }
2880
+ async fetchOrder(id, symbol = undefined, params = {}) {
2881
+ /**
2882
+ * @method
2883
+ * @name phemex#fetchOrder
2884
+ * @description fetches information on an order made by the user
2885
+ * @param {string} symbol unified symbol of the market the order was made in
2886
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2887
+ * @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
2888
+ */
2889
+ if (symbol === undefined) {
2890
+ throw new errors.ArgumentsRequired(this.id + ' fetchOrder() requires a symbol argument');
2891
+ }
2892
+ await this.loadMarkets();
2893
+ const market = this.market(symbol);
2894
+ if (market['settle'] === 'USDT') {
2895
+ throw new errors.NotSupported(this.id + 'fetchOrder() is not supported yet for USDT settled swap markets'); // https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#query-user-order-by-orderid-or-query-user-order-by-client-order-id
2896
+ }
2897
+ const request = {
2898
+ 'symbol': market['id'],
2899
+ };
2900
+ const clientOrderId = this.safeString2(params, 'clientOrderId', 'clOrdID');
2901
+ params = this.omit(params, ['clientOrderId', 'clOrdID']);
2902
+ if (clientOrderId !== undefined) {
2903
+ request['clOrdID'] = clientOrderId;
2904
+ }
2905
+ else {
2906
+ request['orderID'] = id;
2907
+ }
2908
+ let response = undefined;
2909
+ if (market['spot']) {
2910
+ response = await this.privateGetSpotOrdersActive(this.extend(request, params));
2911
+ }
2912
+ else {
2913
+ response = await this.privateGetExchangeOrder(this.extend(request, params));
2914
+ }
2915
+ const data = this.safeValue(response, 'data', {});
2916
+ let order = data;
2917
+ if (Array.isArray(data)) {
2918
+ const numOrders = data.length;
2919
+ if (numOrders < 1) {
2920
+ if (clientOrderId !== undefined) {
2921
+ throw new errors.OrderNotFound(this.id + ' fetchOrder() ' + symbol + ' order with clientOrderId ' + clientOrderId + ' not found');
2922
+ }
2923
+ else {
2924
+ throw new errors.OrderNotFound(this.id + ' fetchOrder() ' + symbol + ' order with id ' + id + ' not found');
2925
+ }
2926
+ }
2927
+ order = this.safeValue(data, 0, {});
2928
+ }
2929
+ return this.parseOrder(order, market);
2930
+ }
2931
+ async fetchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
2932
+ /**
2933
+ * @method
2934
+ * @name phemex#fetchOrders
2935
+ * @description fetches information on multiple orders made by the user
2936
+ * @see https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#queryorder
2937
+ * @param {string} symbol unified market symbol of the market orders were made in
2938
+ * @param {int} [since] the earliest time in ms to fetch orders for
2939
+ * @param {int} [limit] the maximum number of order structures to retrieve
2940
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2941
+ * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
2942
+ */
2943
+ if (symbol === undefined) {
2944
+ throw new errors.ArgumentsRequired(this.id + ' fetchOrders() requires a symbol argument');
2945
+ }
2946
+ await this.loadMarkets();
2947
+ const market = this.market(symbol);
2948
+ const request = {
2949
+ 'symbol': market['id'],
2950
+ };
2951
+ if (since !== undefined) {
2952
+ request['start'] = since;
2953
+ }
2954
+ if (limit !== undefined) {
2955
+ request['limit'] = limit;
2956
+ }
2957
+ let response = undefined;
2958
+ if (market['settle'] === 'USDT') {
2959
+ request['currency'] = market['settle'];
2960
+ response = await this.privateGetExchangeOrderV2OrderList(this.extend(request, params));
2961
+ }
2962
+ else if (market['swap']) {
2963
+ response = await this.privateGetExchangeOrderList(this.extend(request, params));
2964
+ }
2965
+ else {
2966
+ response = await this.privateGetSpotOrders(this.extend(request, params));
2967
+ }
2968
+ const data = this.safeValue(response, 'data', {});
2969
+ const rows = this.safeValue(data, 'rows', data);
2970
+ return this.parseOrders(rows, market, since, limit);
2971
+ }
2972
+ async fetchOpenOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
2973
+ /**
2974
+ * @method
2975
+ * @name phemex#fetchOpenOrders
2976
+ * @description fetch all unfilled currently open orders
2977
+ * @see https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#queryopenorder
2978
+ * @see https://github.com/phemex/phemex-api-docs/blob/master/Public-Contract-API-en.md
2979
+ * @param {string} symbol unified market symbol
2980
+ * @param {int} [since] the earliest time in ms to fetch open orders for
2981
+ * @param {int} [limit] the maximum number of open order structures to retrieve
2982
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2983
+ * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
2984
+ */
2985
+ if (symbol === undefined) {
2986
+ throw new errors.ArgumentsRequired(this.id + ' fetchOpenOrders() requires a symbol argument');
2987
+ }
2988
+ await this.loadMarkets();
2989
+ const market = this.market(symbol);
2990
+ const request = {
2991
+ 'symbol': market['id'],
2992
+ };
2993
+ let response = undefined;
2994
+ try {
2995
+ if (market['settle'] === 'USDT') {
2996
+ response = await this.privateGetGOrdersActiveList(this.extend(request, params));
2997
+ }
2998
+ else if (market['swap']) {
2999
+ response = await this.privateGetOrdersActiveList(this.extend(request, params));
3000
+ }
3001
+ else {
3002
+ response = await this.privateGetSpotOrders(this.extend(request, params));
3003
+ }
3004
+ }
3005
+ catch (e) {
3006
+ if (e instanceof errors.OrderNotFound) {
3007
+ return [];
3008
+ }
3009
+ throw e;
3010
+ }
3011
+ const data = this.safeValue(response, 'data', {});
3012
+ if (Array.isArray(data)) {
3013
+ return this.parseOrders(data, market, since, limit);
3014
+ }
3015
+ else {
3016
+ const rows = this.safeValue(data, 'rows', []);
3017
+ return this.parseOrders(rows, market, since, limit);
3018
+ }
3019
+ }
3020
+ async fetchClosedOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
3021
+ /**
3022
+ * @method
3023
+ * @name phemex#fetchClosedOrders
3024
+ * @description fetches information on multiple closed orders made by the user
3025
+ * @see https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#queryorder
3026
+ * @param {string} symbol unified market symbol of the market orders were made in
3027
+ * @param {int} [since] the earliest time in ms to fetch orders for
3028
+ * @param {int} [limit] the maximum number of order structures to retrieve
3029
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3030
+ * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
3031
+ */
3032
+ if (symbol === undefined) {
3033
+ throw new errors.ArgumentsRequired(this.id + ' fetchClosedOrders() requires a symbol argument');
3034
+ }
3035
+ await this.loadMarkets();
3036
+ const market = this.market(symbol);
3037
+ const request = {
3038
+ 'symbol': market['id'],
3039
+ };
3040
+ if (since !== undefined) {
3041
+ request['start'] = since;
3042
+ }
3043
+ if (limit !== undefined) {
3044
+ request['limit'] = limit;
3045
+ }
3046
+ let response = undefined;
3047
+ if (market['settle'] === 'USDT') {
3048
+ request['currency'] = market['settle'];
3049
+ response = await this.privateGetExchangeOrderV2OrderList(this.extend(request, params));
3050
+ }
3051
+ else if (market['swap']) {
3052
+ response = await this.privateGetExchangeOrderList(this.extend(request, params));
3053
+ }
3054
+ else {
3055
+ response = await this.privateGetExchangeSpotOrder(this.extend(request, params));
3056
+ }
3057
+ //
3058
+ // spot
3059
+ //
3060
+ // {
3061
+ // "code":0,
3062
+ // "msg":"OK",
3063
+ // "data":{
3064
+ // "total":8,
3065
+ // "rows":[
3066
+ // {
3067
+ // "orderID":"99232c3e-3d6a-455f-98cc-2061cdfe91bc",
3068
+ // "stopPxEp":0,
3069
+ // "avgPriceEp":0,
3070
+ // "qtyType":"ByBase",
3071
+ // "leavesBaseQtyEv":0,
3072
+ // "leavesQuoteQtyEv":0,
3073
+ // "baseQtyEv":"1000000000",
3074
+ // "feeCurrency":"4",
3075
+ // "stopDirection":"UNSPECIFIED",
3076
+ // "symbol":"sETHUSDT",
3077
+ // "side":"Buy",
3078
+ // "quoteQtyEv":250000000000,
3079
+ // "priceEp":25000000000,
3080
+ // "ordType":"Limit",
3081
+ // "timeInForce":"GoodTillCancel",
3082
+ // "ordStatus":"Rejected",
3083
+ // "execStatus":"NewRejected",
3084
+ // "createTimeNs":1592675305266037130,
3085
+ // "cumFeeEv":0,
3086
+ // "cumBaseValueEv":0,
3087
+ // "cumQuoteValueEv":0
3088
+ // },
3089
+ // ]
3090
+ // }
3091
+ // }
3092
+ //
3093
+ const data = this.safeValue(response, 'data', {});
3094
+ if (Array.isArray(data)) {
3095
+ return this.parseOrders(data, market, since, limit);
3096
+ }
3097
+ else {
3098
+ const rows = this.safeValue(data, 'rows', []);
3099
+ return this.parseOrders(rows, market, since, limit);
3100
+ }
3101
+ }
3102
+ async fetchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
3103
+ /**
3104
+ * @method
3105
+ * @name phemex#fetchMyTrades
3106
+ * @description fetch all trades made by the user
3107
+ * @see https://github.com/phemex/phemex-api-docs/blob/master/Public-Contract-API-en.md#query-user-trade
3108
+ * @see https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#query-user-trade
3109
+ * @param {string} symbol unified market symbol
3110
+ * @param {int} [since] the earliest time in ms to fetch trades for
3111
+ * @param {int} [limit] the maximum number of trades structures to retrieve
3112
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3113
+ * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
3114
+ */
3115
+ if (symbol === undefined) {
3116
+ throw new errors.ArgumentsRequired(this.id + ' fetchMyTrades() requires a symbol argument');
3117
+ }
3118
+ await this.loadMarkets();
3119
+ const market = this.market(symbol);
3120
+ const request = {};
3121
+ if (limit !== undefined) {
3122
+ limit = Math.min(200, limit);
3123
+ request['limit'] = limit;
3124
+ }
3125
+ if (market['settle'] === 'USDT') {
3126
+ request['currency'] = 'USDT';
3127
+ request['offset'] = 0;
3128
+ if (limit === undefined) {
3129
+ request['limit'] = 200;
3130
+ }
3131
+ }
3132
+ else {
3133
+ request['symbol'] = market['id'];
3134
+ }
3135
+ if (since !== undefined) {
3136
+ request['start'] = since;
3137
+ }
3138
+ if (market['swap'] && (limit !== undefined)) {
3139
+ request['limit'] = limit;
3140
+ }
3141
+ const isUSDTSettled = market['settle'] === 'USDT';
3142
+ let response = undefined;
3143
+ if (market['swap']) {
3144
+ if (isUSDTSettled) {
3145
+ response = await this.privateGetExchangeOrderV2TradingList(this.extend(request, params));
3146
+ }
3147
+ else {
3148
+ response = await this.privateGetExchangeOrderTrade(this.extend(request, params));
3149
+ }
3150
+ }
3151
+ else {
3152
+ response = await this.privateGetExchangeSpotOrderTrades(this.extend(request, params));
3153
+ }
3154
+ //
3155
+ // spot
3156
+ //
3157
+ // {
3158
+ // "code": 0,
3159
+ // "msg": "OK",
3160
+ // "data": {
3161
+ // "total": 1,
3162
+ // "rows": [
3163
+ // {
3164
+ // "qtyType": "ByQuote",
3165
+ // "transactTimeNs": 1589450974800550100,
3166
+ // "clOrdID": "8ba59d40-df25-d4b0-14cf-0703f44e9690",
3167
+ // "orderID": "b2b7018d-f02f-4c59-b4cf-051b9c2d2e83",
3168
+ // "symbol": "sBTCUSDT",
3169
+ // "side": "Buy",
3170
+ // "priceEP": 970056000000,
3171
+ // "baseQtyEv": 0,
3172
+ // "quoteQtyEv": 1000000000,
3173
+ // "action": "New",
3174
+ // "execStatus": "MakerFill",
3175
+ // "ordStatus": "Filled",
3176
+ // "ordType": "Limit",
3177
+ // "execInst": "None",
3178
+ // "timeInForce": "GoodTillCancel",
3179
+ // "stopDirection": "UNSPECIFIED",
3180
+ // "tradeType": "Trade",
3181
+ // "stopPxEp": 0,
3182
+ // "execId": "c6bd8979-07ba-5946-b07e-f8b65135dbb1",
3183
+ // "execPriceEp": 970056000000,
3184
+ // "execBaseQtyEv": 103000,
3185
+ // "execQuoteQtyEv": 999157680,
3186
+ // "leavesBaseQtyEv": 0,
3187
+ // "leavesQuoteQtyEv": 0,
3188
+ // "execFeeEv": 0,
3189
+ // "feeRateEr": 0
3190
+ // }
3191
+ // ]
3192
+ // }
3193
+ // }
3194
+ //
3195
+ //
3196
+ // swap
3197
+ //
3198
+ // {
3199
+ // "code": 0,
3200
+ // "msg": "OK",
3201
+ // "data": {
3202
+ // "total": 79,
3203
+ // "rows": [
3204
+ // {
3205
+ // "transactTimeNs": 1606054879331565300,
3206
+ // "symbol": "BTCUSD",
3207
+ // "currency": "BTC",
3208
+ // "action": "New",
3209
+ // "side": "Buy",
3210
+ // "tradeType": "Trade",
3211
+ // "execQty": 5,
3212
+ // "execPriceEp": 182990000,
3213
+ // "orderQty": 5,
3214
+ // "priceEp": 183870000,
3215
+ // "execValueEv": 27323,
3216
+ // "feeRateEr": 75000,
3217
+ // "execFeeEv": 21,
3218
+ // "ordType": "Market",
3219
+ // "execID": "5eee56a4-04a9-5677-8eb0-c2fe22ae3645",
3220
+ // "orderID": "ee0acb82-f712-4543-a11d-d23efca73197",
3221
+ // "clOrdID": "",
3222
+ // "execStatus": "TakerFill"
3223
+ // },
3224
+ // ]
3225
+ // }
3226
+ // }
3227
+ //
3228
+ // swap - usdt
3229
+ //
3230
+ // {
3231
+ // "code": 0,
3232
+ // "msg": "OK",
3233
+ // "data": {
3234
+ // "total": 4,
3235
+ // "rows": [
3236
+ // {
3237
+ // "createdAt": 1666226932259,
3238
+ // "symbol": "ETHUSDT",
3239
+ // "currency": "USDT",
3240
+ // "action": 1,
3241
+ // "tradeType": 1,
3242
+ // "execQtyRq": "0.01",
3243
+ // "execPriceRp": "1271.9",
3244
+ // "side": 1,
3245
+ // "orderQtyRq": "0.78",
3246
+ // "priceRp": "1271.9",
3247
+ // "execValueRv": "12.719",
3248
+ // "feeRateRr": "0.0001",
3249
+ // "execFeeRv": "0.0012719",
3250
+ // "ordType": 2,
3251
+ // "execId": "8718cae",
3252
+ // "execStatus": 6
3253
+ // },
3254
+ // ]
3255
+ // }
3256
+ // }
3257
+ //
3258
+ let data = undefined;
3259
+ if (isUSDTSettled) {
3260
+ data = this.safeValue(response, 'data', []);
3261
+ }
3262
+ else {
3263
+ data = this.safeValue(response, 'data', {});
3264
+ data = this.safeValue(data, 'rows', []);
3265
+ }
3266
+ return this.parseTrades(data, market, since, limit);
3267
+ }
3268
+ async fetchDepositAddress(code, params = {}) {
3269
+ /**
3270
+ * @method
3271
+ * @name phemex#fetchDepositAddress
3272
+ * @description fetch the deposit address for a currency associated with this account
3273
+ * @param {string} code unified currency code
3274
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3275
+ * @returns {object} an [address structure]{@link https://docs.ccxt.com/#/?id=address-structure}
3276
+ */
3277
+ await this.loadMarkets();
3278
+ const currency = this.currency(code);
3279
+ const request = {
3280
+ 'currency': currency['id'],
3281
+ };
3282
+ const defaultNetworks = this.safeValue(this.options, 'defaultNetworks');
3283
+ const defaultNetwork = this.safeStringUpper(defaultNetworks, code);
3284
+ const networks = this.safeValue(this.options, 'networks', {});
3285
+ let network = this.safeStringUpper(params, 'network', defaultNetwork);
3286
+ network = this.safeString(networks, network, network);
3287
+ if (network === undefined) {
3288
+ request['chainName'] = currency['id'];
3289
+ }
3290
+ else {
3291
+ request['chainName'] = network;
3292
+ params = this.omit(params, 'network');
3293
+ }
3294
+ const response = await this.privateGetPhemexUserWalletsV2DepositAddress(this.extend(request, params));
3295
+ // {
3296
+ // "code":0,
3297
+ // "msg":"OK",
3298
+ // "data":{
3299
+ // "address":"0x5bfbf60e0fa7f63598e6cfd8a7fd3ffac4ccc6ad",
3300
+ // "tag":null
3301
+ // }
3302
+ // }
3303
+ //
3304
+ const data = this.safeValue(response, 'data', {});
3305
+ const address = this.safeString(data, 'address');
3306
+ const tag = this.safeString(data, 'tag');
3307
+ this.checkAddress(address);
3308
+ return {
3309
+ 'currency': code,
3310
+ 'address': address,
3311
+ 'tag': tag,
3312
+ 'network': undefined,
3313
+ 'info': response,
3314
+ };
3315
+ }
3316
+ async fetchDeposits(code = undefined, since = undefined, limit = undefined, params = {}) {
3317
+ /**
3318
+ * @method
3319
+ * @name phemex#fetchDeposits
3320
+ * @description fetch all deposits made to an account
3321
+ * @param {string} code unified currency code
3322
+ * @param {int} [since] the earliest time in ms to fetch deposits for
3323
+ * @param {int} [limit] the maximum number of deposits structures to retrieve
3324
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3325
+ * @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure}
3326
+ */
3327
+ await this.loadMarkets();
3328
+ let currency = undefined;
3329
+ if (code !== undefined) {
3330
+ currency = this.currency(code);
3331
+ }
3332
+ const response = await this.privateGetExchangeWalletsDepositList(params);
3333
+ //
3334
+ // {
3335
+ // "code":0,
3336
+ // "msg":"OK",
3337
+ // "data":[
3338
+ // {
3339
+ // "id":29200,
3340
+ // "currency":"USDT",
3341
+ // "currencyCode":3,
3342
+ // "txHash":"0x0bdbdc47807769a03b158d5753f54dfc58b92993d2f5e818db21863e01238e5d",
3343
+ // "address":"0x5bfbf60e0fa7f63598e6cfd8a7fd3ffac4ccc6ad",
3344
+ // "amountEv":3000000000,
3345
+ // "confirmations":13,
3346
+ // "type":"Deposit",
3347
+ // "status":"Success",
3348
+ // "createdAt":1592722565000
3349
+ // }
3350
+ // ]
3351
+ // }
3352
+ //
3353
+ const data = this.safeValue(response, 'data', {});
3354
+ return this.parseTransactions(data, currency, since, limit);
3355
+ }
3356
+ async fetchWithdrawals(code = undefined, since = undefined, limit = undefined, params = {}) {
3357
+ /**
3358
+ * @method
3359
+ * @name phemex#fetchWithdrawals
3360
+ * @description fetch all withdrawals made from an account
3361
+ * @param {string} code unified currency code
3362
+ * @param {int} [since] the earliest time in ms to fetch withdrawals for
3363
+ * @param {int} [limit] the maximum number of withdrawals structures to retrieve
3364
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3365
+ * @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure}
3366
+ */
3367
+ await this.loadMarkets();
3368
+ let currency = undefined;
3369
+ if (code !== undefined) {
3370
+ currency = this.currency(code);
3371
+ }
3372
+ const response = await this.privateGetExchangeWalletsWithdrawList(params);
3373
+ //
3374
+ // {
3375
+ // "code":0,
3376
+ // "msg":"OK",
3377
+ // "data":[
3378
+ // {
3379
+ // "address": "1Lxxxxxxxxxxx"
3380
+ // "amountEv": 200000
3381
+ // "currency": "BTC"
3382
+ // "currencyCode": 1
3383
+ // "expiredTime": 0
3384
+ // "feeEv": 50000
3385
+ // "rejectReason": null
3386
+ // "status": "Succeed"
3387
+ // "txHash": "44exxxxxxxxxxxxxxxxxxxxxx"
3388
+ // "withdrawStatus: ""
3389
+ // }
3390
+ // ]
3391
+ // }
3392
+ //
3393
+ const data = this.safeValue(response, 'data', {});
3394
+ return this.parseTransactions(data, currency, since, limit);
3395
+ }
3396
+ parseTransactionStatus(status) {
3397
+ const statuses = {
3398
+ 'Success': 'ok',
3399
+ 'Succeed': 'ok',
3400
+ 'Rejected': 'failed',
3401
+ 'Security check failed': 'failed',
3402
+ 'SecurityCheckFailed': 'failed',
3403
+ 'Expired': 'failed',
3404
+ 'Address Risk': 'failed',
3405
+ 'Security Checking': 'pending',
3406
+ 'SecurityChecking': 'pending',
3407
+ 'Pending Review': 'pending',
3408
+ 'Pending Transfer': 'pending',
3409
+ 'AmlCsApporve': 'pending',
3410
+ 'New': 'pending',
3411
+ 'Confirmed': 'pending',
3412
+ 'Cancelled': 'canceled',
3413
+ };
3414
+ return this.safeString(statuses, status, status);
3415
+ }
3416
+ parseTransaction(transaction, currency = undefined) {
3417
+ //
3418
+ // withdraw
3419
+ //
3420
+ // {
3421
+ // "id": "10000001",
3422
+ // "freezeId": null,
3423
+ // "address": "44exxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
3424
+ // "amountRv": "100",
3425
+ // "chainCode": "11",
3426
+ // "chainName": "TRX",
3427
+ // "currency": "USDT",
3428
+ // "currencyCode": 3,
3429
+ // "email": "abc@gmail.com",
3430
+ // "expiredTime": "0",
3431
+ // "feeRv": "1",
3432
+ // "nickName": null,
3433
+ // "phone": null,
3434
+ // "rejectReason": "",
3435
+ // "submitedAt": "1670000000000",
3436
+ // "submittedAt": "1670000000000",
3437
+ // "txHash": null,
3438
+ // "userId": "10000001",
3439
+ // "status": "Success"
3440
+ //
3441
+ // fetchDeposits
3442
+ //
3443
+ // {
3444
+ // "id": "29200",
3445
+ // "currency": "USDT",
3446
+ // "currencyCode": "3",
3447
+ // "chainName": "ETH",
3448
+ // "chainCode": "4",
3449
+ // "txHash": "0x0bdbdc47807769a03b158d5753f54dfc58b92993d2f5e818db21863e01238e5d",
3450
+ // "address": "0x5bfbf60e0fa7f63598e6cfd8a7fd3ffac4ccc6ad",
3451
+ // "amountEv": "3000000000",
3452
+ // "confirmations": "13",
3453
+ // "type": "Deposit",
3454
+ // "status": "Success",
3455
+ // "createdAt": "1592722565000",
3456
+ // }
3457
+ //
3458
+ // fetchWithdrawals
3459
+ //
3460
+ // {
3461
+ // "id": "10000001",
3462
+ // "userId": "10000001",
3463
+ // "freezeId": "10000002",
3464
+ // "phone": null,
3465
+ // "email": "abc@gmail.com",
3466
+ // "nickName": null,
3467
+ // "currency": "USDT",
3468
+ // "currencyCode": "3",
3469
+ // "status": "Succeed",
3470
+ // "withdrawStatus": "Succeed",
3471
+ // "amountEv": "8800000000",
3472
+ // "feeEv": "1200000000",
3473
+ // "address": "0x5xxxad",
3474
+ // "txHash: "0x0xxxx5d",
3475
+ // "submitedAt": "1702571922000",
3476
+ // "submittedAt": "1702571922000",
3477
+ // "expiredTime": "0",
3478
+ // "rejectReason": null,
3479
+ // "chainName": "ETH",
3480
+ // "chainCode": "4",
3481
+ // "proxyAddress": null
3482
+ // }
3483
+ //
3484
+ const id = this.safeString(transaction, 'id');
3485
+ const address = this.safeString(transaction, 'address');
3486
+ const tag = undefined;
3487
+ const txid = this.safeString(transaction, 'txHash');
3488
+ const currencyId = this.safeString(transaction, 'currency');
3489
+ currency = this.safeCurrency(currencyId, currency);
3490
+ const code = currency['code'];
3491
+ const networkId = this.safeString(transaction, 'chainName');
3492
+ const timestamp = this.safeIntegerN(transaction, ['createdAt', 'submitedAt', 'submittedAt']);
3493
+ let type = this.safeStringLower(transaction, 'type');
3494
+ let feeCost = this.parseNumber(this.fromEn(this.safeString(transaction, 'feeEv'), currency['valueScale']));
3495
+ if (feeCost === undefined) {
3496
+ feeCost = this.safeNumber(transaction, 'feeRv');
3497
+ }
3498
+ let fee = undefined;
3499
+ if (feeCost !== undefined) {
3500
+ type = 'withdrawal';
3501
+ fee = {
3502
+ 'cost': feeCost,
3503
+ 'currency': code,
3504
+ };
3505
+ }
3506
+ const status = this.parseTransactionStatus(this.safeString(transaction, 'status'));
3507
+ let amount = this.parseNumber(this.fromEn(this.safeString(transaction, 'amountEv'), currency['valueScale']));
3508
+ if (amount === undefined) {
3509
+ amount = this.safeNumber(transaction, 'amountRv');
3510
+ }
3511
+ return {
3512
+ 'info': transaction,
3513
+ 'id': id,
3514
+ 'txid': txid,
3515
+ 'timestamp': timestamp,
3516
+ 'datetime': this.iso8601(timestamp),
3517
+ 'network': this.networkIdToCode(networkId),
3518
+ 'address': address,
3519
+ 'addressTo': address,
3520
+ 'addressFrom': undefined,
3521
+ 'tag': tag,
3522
+ 'tagTo': tag,
3523
+ 'tagFrom': undefined,
3524
+ 'type': type,
3525
+ 'amount': amount,
3526
+ 'currency': code,
3527
+ 'status': status,
3528
+ 'updated': undefined,
3529
+ 'comment': undefined,
3530
+ 'internal': undefined,
3531
+ 'fee': fee,
3532
+ };
3533
+ }
3534
+ async fetchPositions(symbols = undefined, params = {}) {
3535
+ /**
3536
+ * @method
3537
+ * @name phemex#fetchPositions
3538
+ * @description fetch all open positions
3539
+ * @see https://github.com/phemex/phemex-api-docs/blob/master/Public-Contract-API-en.md#query-trading-account-and-positions
3540
+ * @see https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#query-account-positions
3541
+ * @param {string[]|undefined} symbols list of unified market symbols
3542
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3543
+ * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/#/?id=position-structure}
3544
+ */
3545
+ await this.loadMarkets();
3546
+ symbols = this.marketSymbols(symbols);
3547
+ let subType = undefined;
3548
+ let code = this.safeString(params, 'currency');
3549
+ let settle = undefined;
3550
+ let market = undefined;
3551
+ const firstSymbol = this.safeString(symbols, 0);
3552
+ if (firstSymbol !== undefined) {
3553
+ market = this.market(firstSymbol);
3554
+ settle = market['settle'];
3555
+ code = market['settle'];
3556
+ }
3557
+ else {
3558
+ [settle, params] = this.handleOptionAndParams(params, 'fetchPositions', 'settle', 'USD');
3559
+ }
3560
+ [subType, params] = this.handleSubTypeAndParams('fetchPositions', market, params);
3561
+ const isUSDTSettled = settle === 'USDT';
3562
+ if (isUSDTSettled) {
3563
+ code = 'USDT';
3564
+ }
3565
+ else if (code === undefined) {
3566
+ code = (subType === 'linear') ? 'USD' : 'BTC';
3567
+ }
3568
+ else {
3569
+ params = this.omit(params, 'code');
3570
+ }
3571
+ const currency = this.currency(code);
3572
+ const request = {
3573
+ 'currency': currency['id'],
3574
+ };
3575
+ let response = undefined;
3576
+ if (isUSDTSettled) {
3577
+ response = await this.privateGetGAccountsAccountPositions(this.extend(request, params));
3578
+ }
3579
+ else {
3580
+ response = await this.privateGetAccountsAccountPositions(this.extend(request, params));
3581
+ }
3582
+ //
3583
+ // {
3584
+ // "code":0,"msg":"",
3585
+ // "data":{
3586
+ // "account":{
3587
+ // "accountId":6192120001,
3588
+ // "currency":"BTC",
3589
+ // "accountBalanceEv":1254744,
3590
+ // "totalUsedBalanceEv":0,
3591
+ // "bonusBalanceEv":1254744
3592
+ // },
3593
+ // "positions":[
3594
+ // {
3595
+ // "accountID":6192120001,
3596
+ // "symbol":"BTCUSD",
3597
+ // "currency":"BTC",
3598
+ // "side":"None",
3599
+ // "positionStatus":"Normal",
3600
+ // "crossMargin":false,
3601
+ // "leverageEr":100000000,
3602
+ // "leverage":1.00000000,
3603
+ // "initMarginReqEr":100000000,
3604
+ // "initMarginReq":1.00000000,
3605
+ // "maintMarginReqEr":500000,
3606
+ // "maintMarginReq":0.00500000,
3607
+ // "riskLimitEv":10000000000,
3608
+ // "riskLimit":100.00000000,
3609
+ // "size":0,
3610
+ // "value":0E-8,
3611
+ // "valueEv":0,
3612
+ // "avgEntryPriceEp":0,
3613
+ // "avgEntryPrice":0E-8,
3614
+ // "posCostEv":0,
3615
+ // "posCost":0E-8,
3616
+ // "assignedPosBalanceEv":0,
3617
+ // "assignedPosBalance":0E-8,
3618
+ // "bankruptCommEv":0,
3619
+ // "bankruptComm":0E-8,
3620
+ // "bankruptPriceEp":0,
3621
+ // "bankruptPrice":0E-8,
3622
+ // "positionMarginEv":0,
3623
+ // "positionMargin":0E-8,
3624
+ // "liquidationPriceEp":0,
3625
+ // "liquidationPrice":0E-8,
3626
+ // "deleveragePercentileEr":0,
3627
+ // "deleveragePercentile":0E-8,
3628
+ // "buyValueToCostEr":100225000,
3629
+ // "buyValueToCost":1.00225000,
3630
+ // "sellValueToCostEr":100075000,
3631
+ // "sellValueToCost":1.00075000,
3632
+ // "markPriceEp":135736070,
3633
+ // "markPrice":13573.60700000,
3634
+ // "markValueEv":0,
3635
+ // "markValue":null,
3636
+ // "unRealisedPosLossEv":0,
3637
+ // "unRealisedPosLoss":null,
3638
+ // "estimatedOrdLossEv":0,
3639
+ // "estimatedOrdLoss":0E-8,
3640
+ // "usedBalanceEv":0,
3641
+ // "usedBalance":0E-8,
3642
+ // "takeProfitEp":0,
3643
+ // "takeProfit":null,
3644
+ // "stopLossEp":0,
3645
+ // "stopLoss":null,
3646
+ // "cumClosedPnlEv":0,
3647
+ // "cumFundingFeeEv":0,
3648
+ // "cumTransactFeeEv":0,
3649
+ // "realisedPnlEv":0,
3650
+ // "realisedPnl":null,
3651
+ // "cumRealisedPnlEv":0,
3652
+ // "cumRealisedPnl":null
3653
+ // }
3654
+ // ]
3655
+ // }
3656
+ // }
3657
+ //
3658
+ const data = this.safeValue(response, 'data', {});
3659
+ const positions = this.safeValue(data, 'positions', []);
3660
+ const result = [];
3661
+ for (let i = 0; i < positions.length; i++) {
3662
+ const position = positions[i];
3663
+ result.push(this.parsePosition(position));
3664
+ }
3665
+ return this.filterByArrayPositions(result, 'symbol', symbols, false);
3666
+ }
3667
+ parsePosition(position, market = undefined) {
3668
+ //
3669
+ // {
3670
+ // "userID": "811370",
3671
+ // "accountID": "8113700002",
3672
+ // "symbol": "ETHUSD",
3673
+ // "currency": "USD",
3674
+ // "side": "Buy",
3675
+ // "positionStatus": "Normal",
3676
+ // "crossMargin": false,
3677
+ // "leverageEr": "200000000",
3678
+ // "leverage": "2.00000000",
3679
+ // "initMarginReqEr": "50000000",
3680
+ // "initMarginReq": "0.50000000",
3681
+ // "maintMarginReqEr": "1000000",
3682
+ // "maintMarginReq": "0.01000000",
3683
+ // "riskLimitEv": "5000000000",
3684
+ // "riskLimit": "500000.00000000",
3685
+ // "size": "1",
3686
+ // "value": "22.22370000",
3687
+ // "valueEv": "222237",
3688
+ // "avgEntryPriceEp": "44447400",
3689
+ // "avgEntryPrice": "4444.74000000",
3690
+ // "posCostEv": "111202",
3691
+ // "posCost": "11.12020000",
3692
+ // "assignedPosBalanceEv": "111202",
3693
+ // "assignedPosBalance": "11.12020000",
3694
+ // "bankruptCommEv": "84",
3695
+ // "bankruptComm": "0.00840000",
3696
+ // "bankruptPriceEp": "22224000",
3697
+ // "bankruptPrice": "2222.40000000",
3698
+ // "positionMarginEv": "111118",
3699
+ // "positionMargin": "11.11180000",
3700
+ // "liquidationPriceEp": "22669000",
3701
+ // "liquidationPrice": "2266.90000000",
3702
+ // "deleveragePercentileEr": "0",
3703
+ // "deleveragePercentile": "0E-8",
3704
+ // "buyValueToCostEr": "50112500",
3705
+ // "buyValueToCost": "0.50112500",
3706
+ // "sellValueToCostEr": "50187500",
3707
+ // "sellValueToCost": "0.50187500",
3708
+ // "markPriceEp": "31332499",
3709
+ // "markPrice": "3133.24990000",
3710
+ // "markValueEv": "0",
3711
+ // "markValue": null,
3712
+ // "unRealisedPosLossEv": "0",
3713
+ // "unRealisedPosLoss": null,
3714
+ // "estimatedOrdLossEv": "0",
3715
+ // "estimatedOrdLoss": "0E-8",
3716
+ // "usedBalanceEv": "111202",
3717
+ // "usedBalance": "11.12020000",
3718
+ // "takeProfitEp": "0",
3719
+ // "takeProfit": null,
3720
+ // "stopLossEp": "0",
3721
+ // "stopLoss": null,
3722
+ // "cumClosedPnlEv": "-1546",
3723
+ // "cumFundingFeeEv": "1605",
3724
+ // "cumTransactFeeEv": "8438",
3725
+ // "realisedPnlEv": "0",
3726
+ // "realisedPnl": null,
3727
+ // "cumRealisedPnlEv": "0",
3728
+ // "cumRealisedPnl": null,
3729
+ // "transactTimeNs": "1641571200001885324",
3730
+ // "takerFeeRateEr": "0",
3731
+ // "makerFeeRateEr": "0",
3732
+ // "term": "6",
3733
+ // "lastTermEndTimeNs": "1607711882505745356",
3734
+ // "lastFundingTimeNs": "1641571200000000000",
3735
+ // "curTermRealisedPnlEv": "-1567",
3736
+ // "execSeq": "12112761561"
3737
+ // }
3738
+ //
3739
+ const marketId = this.safeString(position, 'symbol');
3740
+ market = this.safeMarket(marketId, market);
3741
+ const symbol = market['symbol'];
3742
+ const collateral = this.safeString2(position, 'positionMargin', 'positionMarginRv');
3743
+ const notionalString = this.safeString2(position, 'value', 'valueRv');
3744
+ const maintenanceMarginPercentageString = this.safeString2(position, 'maintMarginReq', 'maintMarginReqRr');
3745
+ const maintenanceMarginString = Precise["default"].stringMul(notionalString, maintenanceMarginPercentageString);
3746
+ const initialMarginString = this.safeString2(position, 'assignedPosBalance', 'assignedPosBalanceRv');
3747
+ const initialMarginPercentageString = Precise["default"].stringDiv(initialMarginString, notionalString);
3748
+ const liquidationPrice = this.safeNumber2(position, 'liquidationPrice', 'liquidationPriceRp');
3749
+ const markPriceString = this.safeString2(position, 'markPrice', 'markPriceRp');
3750
+ const contracts = this.safeString(position, 'size');
3751
+ const contractSize = this.safeValue(market, 'contractSize');
3752
+ const contractSizeString = this.numberToString(contractSize);
3753
+ const leverage = this.safeNumber2(position, 'leverage', 'leverageRr');
3754
+ const entryPriceString = this.safeString2(position, 'avgEntryPrice', 'avgEntryPriceRp');
3755
+ const rawSide = this.safeString(position, 'side');
3756
+ let side = undefined;
3757
+ if (rawSide !== undefined) {
3758
+ side = (rawSide === 'Buy') ? 'long' : 'short';
3759
+ }
3760
+ let priceDiff = undefined;
3761
+ const currency = this.safeString(position, 'currency');
3762
+ if (currency === 'USD') {
3763
+ if (side === 'long') {
3764
+ priceDiff = Precise["default"].stringSub(markPriceString, entryPriceString);
3765
+ }
3766
+ else {
3767
+ priceDiff = Precise["default"].stringSub(entryPriceString, markPriceString);
3768
+ }
3769
+ }
3770
+ else {
3771
+ // inverse
3772
+ if (side === 'long') {
3773
+ priceDiff = Precise["default"].stringSub(Precise["default"].stringDiv('1', entryPriceString), Precise["default"].stringDiv('1', markPriceString));
3774
+ }
3775
+ else {
3776
+ priceDiff = Precise["default"].stringSub(Precise["default"].stringDiv('1', markPriceString), Precise["default"].stringDiv('1', entryPriceString));
3777
+ }
3778
+ }
3779
+ const unrealizedPnl = Precise["default"].stringMul(Precise["default"].stringMul(priceDiff, contracts), contractSizeString);
3780
+ const marginRatio = Precise["default"].stringDiv(maintenanceMarginString, collateral);
3781
+ const isCross = this.safeValue(position, 'crossMargin');
3782
+ return this.safePosition({
3783
+ 'info': position,
3784
+ 'id': undefined,
3785
+ 'symbol': symbol,
3786
+ 'contracts': this.parseNumber(contracts),
3787
+ 'contractSize': contractSize,
3788
+ 'unrealizedPnl': this.parseNumber(unrealizedPnl),
3789
+ 'leverage': leverage,
3790
+ 'liquidationPrice': liquidationPrice,
3791
+ 'collateral': this.parseNumber(collateral),
3792
+ 'notional': this.parseNumber(notionalString),
3793
+ 'markPrice': this.parseNumber(markPriceString),
3794
+ 'lastPrice': undefined,
3795
+ 'entryPrice': this.parseNumber(entryPriceString),
3796
+ 'timestamp': undefined,
3797
+ 'lastUpdateTimestamp': undefined,
3798
+ 'initialMargin': this.parseNumber(initialMarginString),
3799
+ 'initialMarginPercentage': this.parseNumber(initialMarginPercentageString),
3800
+ 'maintenanceMargin': this.parseNumber(maintenanceMarginString),
3801
+ 'maintenanceMarginPercentage': this.parseNumber(maintenanceMarginPercentageString),
3802
+ 'marginRatio': this.parseNumber(marginRatio),
3803
+ 'datetime': undefined,
3804
+ 'marginMode': isCross ? 'cross' : 'isolated',
3805
+ 'side': side,
3806
+ 'hedged': false,
3807
+ 'percentage': undefined,
3808
+ 'stopLossPrice': undefined,
3809
+ 'takeProfitPrice': undefined,
3810
+ });
3811
+ }
3812
+ async fetchFundingHistory(symbol = undefined, since = undefined, limit = undefined, params = {}) {
3813
+ /**
3814
+ * @method
3815
+ * @name phemex#fetchFundingHistory
3816
+ * @description fetch the history of funding payments paid and received on this account
3817
+ * @see https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#futureDataFundingFeesHist
3818
+ * @param {string} symbol unified market symbol
3819
+ * @param {int} [since] the earliest time in ms to fetch funding history for
3820
+ * @param {int} [limit] the maximum number of funding history structures to retrieve
3821
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3822
+ * @returns {object} a [funding history structure]{@link https://docs.ccxt.com/#/?id=funding-history-structure}
3823
+ */
3824
+ if (symbol === undefined) {
3825
+ throw new errors.ArgumentsRequired(this.id + ' fetchFundingHistory() requires a symbol argument');
3826
+ }
3827
+ await this.loadMarkets();
3828
+ const market = this.market(symbol);
3829
+ const request = {
3830
+ 'symbol': market['id'],
3831
+ // 'limit': 20, // Page size default 20, max 200
3832
+ // 'offset': 0, // Page start default 0
3833
+ };
3834
+ if (limit !== undefined) {
3835
+ if (limit > 200) {
3836
+ throw new errors.BadRequest(this.id + ' fetchFundingHistory() limit argument cannot exceed 200');
3837
+ }
3838
+ request['limit'] = limit;
3839
+ }
3840
+ let response = undefined;
3841
+ if (market['settle'] === 'USDT') {
3842
+ response = await this.privateGetApiDataGFuturesFundingFees(this.extend(request, params));
3843
+ }
3844
+ else {
3845
+ response = await this.privateGetApiDataFuturesFundingFees(this.extend(request, params));
3846
+ }
3847
+ //
3848
+ // {
3849
+ // "code": 0,
3850
+ // "msg": "OK",
3851
+ // "data": {
3852
+ // "rows": [
3853
+ // {
3854
+ // "symbol": "BTCUSD",
3855
+ // "currency": "BTC",
3856
+ // "execQty": 18,
3857
+ // "side": "Buy",
3858
+ // "execPriceEp": 360086455,
3859
+ // "execValueEv": 49987,
3860
+ // "fundingRateEr": 10000,
3861
+ // "feeRateEr": 10000,
3862
+ // "execFeeEv": 5,
3863
+ // "createTime": 1651881600000
3864
+ // }
3865
+ // ]
3866
+ // }
3867
+ // }
3868
+ //
3869
+ const data = this.safeValue(response, 'data', {});
3870
+ const rows = this.safeValue(data, 'rows', []);
3871
+ const result = [];
3872
+ for (let i = 0; i < rows.length; i++) {
3873
+ const entry = rows[i];
3874
+ const timestamp = this.safeInteger(entry, 'createTime');
3875
+ result.push({
3876
+ 'info': entry,
3877
+ 'symbol': this.safeString(entry, 'symbol'),
3878
+ 'code': this.safeCurrencyCode(this.safeString(entry, 'currency')),
3879
+ 'timestamp': timestamp,
3880
+ 'datetime': this.iso8601(timestamp),
3881
+ 'id': undefined,
3882
+ 'amount': this.fromEv(this.safeString(entry, 'execFeeEv'), market),
3883
+ });
3884
+ }
3885
+ return result;
3886
+ }
3887
+ async fetchFundingRate(symbol, params = {}) {
3888
+ /**
3889
+ * @method
3890
+ * @name phemex#fetchFundingRate
3891
+ * @description fetch the current funding rate
3892
+ * @param {string} symbol unified market symbol
3893
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3894
+ * @returns {object} a [funding rate structure]{@link https://docs.ccxt.com/#/?id=funding-rate-structure}
3895
+ */
3896
+ await this.loadMarkets();
3897
+ const market = this.market(symbol);
3898
+ if (!market['swap']) {
3899
+ throw new errors.BadSymbol(this.id + ' fetchFundingRate() supports swap contracts only');
3900
+ }
3901
+ const request = {
3902
+ 'symbol': market['id'],
3903
+ };
3904
+ let response = {};
3905
+ if (!market['linear']) {
3906
+ response = await this.v1GetMdTicker24hr(this.extend(request, params));
3907
+ }
3908
+ else {
3909
+ response = await this.v2GetMdV2Ticker24hr(this.extend(request, params));
3910
+ }
3911
+ //
3912
+ // {
3913
+ // "error": null,
3914
+ // "id": 0,
3915
+ // "result": {
3916
+ // "askEp": 2332500,
3917
+ // "bidEp": 2331000,
3918
+ // "fundingRateEr": 10000,
3919
+ // "highEp": 2380000,
3920
+ // "indexEp": 2329057,
3921
+ // "lastEp": 2331500,
3922
+ // "lowEp": 2274000,
3923
+ // "markEp": 2329232,
3924
+ // "openEp": 2337500,
3925
+ // "openInterest": 1298050,
3926
+ // "predFundingRateEr": 19921,
3927
+ // "symbol": "ETHUSD",
3928
+ // "timestamp": 1592474241582701416,
3929
+ // "turnoverEv": 47228362330,
3930
+ // "volume": 4053863
3931
+ // }
3932
+ // }
3933
+ //
3934
+ const result = this.safeValue(response, 'result', {});
3935
+ return this.parseFundingRate(result, market);
3936
+ }
3937
+ parseFundingRate(contract, market = undefined) {
3938
+ //
3939
+ // {
3940
+ // "askEp": 2332500,
3941
+ // "bidEp": 2331000,
3942
+ // "fundingRateEr": 10000,
3943
+ // "highEp": 2380000,
3944
+ // "indexEp": 2329057,
3945
+ // "lastEp": 2331500,
3946
+ // "lowEp": 2274000,
3947
+ // "markEp": 2329232,
3948
+ // "openEp": 2337500,
3949
+ // "openInterest": 1298050,
3950
+ // "predFundingRateEr": 19921,
3951
+ // "symbol": "ETHUSD",
3952
+ // "timestamp": 1592474241582701416,
3953
+ // "turnoverEv": 47228362330,
3954
+ // "volume": 4053863
3955
+ // }
3956
+ //
3957
+ // linear swap v2
3958
+ //
3959
+ // {
3960
+ // "closeRp":"16820.5",
3961
+ // "fundingRateRr":"0.0001",
3962
+ // "highRp":"16962.1",
3963
+ // "indexPriceRp":"16830.15651565",
3964
+ // "lowRp":"16785",
3965
+ // "markPriceRp":"16830.97534951",
3966
+ // "openInterestRv":"1323.596",
3967
+ // "openRp":"16851.7",
3968
+ // "predFundingRateRr":"0.0001",
3969
+ // "symbol":"BTCUSDT",
3970
+ // "timestamp":"1672142789065593096",
3971
+ // "turnoverRv":"124835296.0538",
3972
+ // "volumeRq":"7406.95"
3973
+ // }
3974
+ //
3975
+ const marketId = this.safeString(contract, 'symbol');
3976
+ const symbol = this.safeSymbol(marketId, market);
3977
+ const timestamp = this.safeIntegerProduct(contract, 'timestamp', 0.000001);
3978
+ return {
3979
+ 'info': contract,
3980
+ 'symbol': symbol,
3981
+ 'markPrice': this.fromEp(this.safeString2(contract, 'markEp', 'markPriceRp'), market),
3982
+ 'indexPrice': this.fromEp(this.safeString2(contract, 'indexEp', 'indexPriceRp'), market),
3983
+ 'interestRate': undefined,
3984
+ 'estimatedSettlePrice': undefined,
3985
+ 'timestamp': timestamp,
3986
+ 'datetime': this.iso8601(timestamp),
3987
+ 'fundingRate': this.fromEr(this.safeString(contract, 'fundingRateEr'), market),
3988
+ 'fundingTimestamp': undefined,
3989
+ 'fundingDatetime': undefined,
3990
+ 'nextFundingRate': this.fromEr(this.safeString2(contract, 'predFundingRateEr', 'predFundingRateRr'), market),
3991
+ 'nextFundingTimestamp': undefined,
3992
+ 'nextFundingDatetime': undefined,
3993
+ 'previousFundingRate': undefined,
3994
+ 'previousFundingTimestamp': undefined,
3995
+ 'previousFundingDatetime': undefined,
3996
+ };
3997
+ }
3998
+ async setMargin(symbol, amount, params = {}) {
3999
+ /**
4000
+ * @method
4001
+ * @name phemex#setMargin
4002
+ * @description Either adds or reduces margin in an isolated position in order to set the margin to a specific value
4003
+ * @see https://github.com/phemex/phemex-api-docs/blob/master/Public-Contract-API-en.md#assign-position-balance-in-isolated-marign-mode
4004
+ * @param {string} symbol unified market symbol of the market to set margin in
4005
+ * @param {float} amount the amount to set the margin to
4006
+ * @param {object} [params] parameters specific to the exchange API endpoint
4007
+ * @returns {object} A [margin structure]{@link https://docs.ccxt.com/#/?id=add-margin-structure}
4008
+ */
4009
+ await this.loadMarkets();
4010
+ const market = this.market(symbol);
4011
+ const request = {
4012
+ 'symbol': market['id'],
4013
+ 'posBalanceEv': this.toEv(amount, market),
4014
+ };
4015
+ const response = await this.privatePostPositionsAssign(this.extend(request, params));
4016
+ //
4017
+ // {
4018
+ // "code": 0,
4019
+ // "msg": "",
4020
+ // "data": "OK"
4021
+ // }
4022
+ //
4023
+ return this.extend(this.parseMarginModification(response, market), {
4024
+ 'amount': amount,
4025
+ });
4026
+ }
4027
+ parseMarginStatus(status) {
4028
+ const statuses = {
4029
+ '0': 'ok',
4030
+ };
4031
+ return this.safeString(statuses, status, status);
4032
+ }
4033
+ parseMarginModification(data, market = undefined) {
4034
+ //
4035
+ // {
4036
+ // "code": 0,
4037
+ // "msg": "",
4038
+ // "data": "OK"
4039
+ // }
4040
+ //
4041
+ market = this.safeMarket(undefined, market);
4042
+ const inverse = this.safeValue(market, 'inverse');
4043
+ const codeCurrency = inverse ? 'base' : 'quote';
4044
+ return {
4045
+ 'info': data,
4046
+ 'type': 'set',
4047
+ 'amount': undefined,
4048
+ 'total': undefined,
4049
+ 'code': market[codeCurrency],
4050
+ 'symbol': this.safeSymbol(undefined, market),
4051
+ 'status': this.parseMarginStatus(this.safeString(data, 'code')),
4052
+ };
4053
+ }
4054
+ async setMarginMode(marginMode, symbol = undefined, params = {}) {
4055
+ /**
4056
+ * @method
4057
+ * @name phemex#setMarginMode
4058
+ * @description set margin mode to 'cross' or 'isolated'
4059
+ * @param {string} marginMode 'cross' or 'isolated'
4060
+ * @param {string} symbol unified market symbol
4061
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
4062
+ * @returns {object} response from the exchange
4063
+ */
4064
+ if (symbol === undefined) {
4065
+ throw new errors.ArgumentsRequired(this.id + ' setMarginMode() requires a symbol argument');
4066
+ }
4067
+ await this.loadMarkets();
4068
+ const market = this.market(symbol);
4069
+ if (!market['swap'] || market['settle'] === 'USDT') {
4070
+ throw new errors.BadSymbol(this.id + ' setMarginMode() supports swap (non USDT based) contracts only');
4071
+ }
4072
+ marginMode = marginMode.toLowerCase();
4073
+ if (marginMode !== 'isolated' && marginMode !== 'cross') {
4074
+ throw new errors.BadRequest(this.id + ' setMarginMode() marginMode argument should be isolated or cross');
4075
+ }
4076
+ let leverage = this.safeInteger(params, 'leverage');
4077
+ if (marginMode === 'cross') {
4078
+ leverage = 0;
4079
+ }
4080
+ if (leverage === undefined) {
4081
+ throw new errors.ArgumentsRequired(this.id + ' setMarginMode() requires a leverage parameter');
4082
+ }
4083
+ const request = {
4084
+ 'symbol': market['id'],
4085
+ 'leverage': leverage,
4086
+ };
4087
+ return await this.privatePutPositionsLeverage(this.extend(request, params));
4088
+ }
4089
+ async setPositionMode(hedged, symbol = undefined, params = {}) {
4090
+ /**
4091
+ * @method
4092
+ * @name phemex#setPositionMode
4093
+ * @description set hedged to true or false for a market
4094
+ * @see https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#switch-position-mode-synchronously
4095
+ * @param {bool} hedged set to true to use dualSidePosition
4096
+ * @param {string} symbol not used by binance setPositionMode ()
4097
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
4098
+ * @returns {object} response from the exchange
4099
+ */
4100
+ this.checkRequiredArgument('setPositionMode', symbol, 'symbol');
4101
+ await this.loadMarkets();
4102
+ const market = this.market(symbol);
4103
+ if (market['settle'] !== 'USDT') {
4104
+ throw new errors.BadSymbol(this.id + ' setPositionMode() supports USDT settled markets only');
4105
+ }
4106
+ const request = {
4107
+ 'symbol': market['id'],
4108
+ };
4109
+ if (hedged) {
4110
+ request['targetPosMode'] = 'Hedged';
4111
+ }
4112
+ else {
4113
+ request['targetPosMode'] = 'OneWay';
4114
+ }
4115
+ return await this.privatePutGPositionsSwitchPosModeSync(this.extend(request, params));
4116
+ }
4117
+ async fetchLeverageTiers(symbols = undefined, params = {}) {
4118
+ /**
4119
+ * @method
4120
+ * @name phemex#fetchLeverageTiers
4121
+ * @description retrieve information on the maximum leverage, and maintenance margin for trades of varying trade sizes
4122
+ * @param {string[]|undefined} symbols list of unified market symbols
4123
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
4124
+ * @returns {object} a dictionary of [leverage tiers structures]{@link https://docs.ccxt.com/#/?id=leverage-tiers-structure}, indexed by market symbols
4125
+ */
4126
+ await this.loadMarkets();
4127
+ if (symbols !== undefined) {
4128
+ const first = this.safeValue(symbols, 0);
4129
+ const market = this.market(first);
4130
+ if (market['settle'] !== 'USD') {
4131
+ throw new errors.BadSymbol(this.id + ' fetchLeverageTiers() supports USD settled markets only');
4132
+ }
4133
+ }
4134
+ const response = await this.publicGetCfgV2Products(params);
4135
+ //
4136
+ // {
4137
+ // "code":0,
4138
+ // "msg":"OK",
4139
+ // "data":{
4140
+ // "ratioScale":8,
4141
+ // "currencies":[
4142
+ // {"currency":"BTC","valueScale":8,"minValueEv":1,"maxValueEv":5000000000000000000,"name":"Bitcoin"},
4143
+ // {"currency":"USD","valueScale":4,"minValueEv":1,"maxValueEv":500000000000000,"name":"USD"},
4144
+ // {"currency":"USDT","valueScale":8,"minValueEv":1,"maxValueEv":5000000000000000000,"name":"TetherUS"},
4145
+ // ],
4146
+ // "products":[
4147
+ // {
4148
+ // "symbol":"BTCUSD",
4149
+ // "displaySymbol":"BTC / USD",
4150
+ // "indexSymbol":".BTC",
4151
+ // "markSymbol":".MBTC",
4152
+ // "fundingRateSymbol":".BTCFR",
4153
+ // "fundingRate8hSymbol":".BTCFR8H",
4154
+ // "contractUnderlyingAssets":"USD",
4155
+ // "settleCurrency":"BTC",
4156
+ // "quoteCurrency":"USD",
4157
+ // "contractSize":1.0,
4158
+ // "lotSize":1,
4159
+ // "tickSize":0.5,
4160
+ // "priceScale":4,
4161
+ // "ratioScale":8,
4162
+ // "pricePrecision":1,
4163
+ // "minPriceEp":5000,
4164
+ // "maxPriceEp":10000000000,
4165
+ // "maxOrderQty":1000000,
4166
+ // "type":"Perpetual"
4167
+ // },
4168
+ // {
4169
+ // "symbol":"sBTCUSDT",
4170
+ // "displaySymbol":"BTC / USDT",
4171
+ // "quoteCurrency":"USDT",
4172
+ // "pricePrecision":2,
4173
+ // "type":"Spot",
4174
+ // "baseCurrency":"BTC",
4175
+ // "baseTickSize":"0.000001 BTC",
4176
+ // "baseTickSizeEv":100,
4177
+ // "quoteTickSize":"0.01 USDT",
4178
+ // "quoteTickSizeEv":1000000,
4179
+ // "minOrderValue":"10 USDT",
4180
+ // "minOrderValueEv":1000000000,
4181
+ // "maxBaseOrderSize":"1000 BTC",
4182
+ // "maxBaseOrderSizeEv":100000000000,
4183
+ // "maxOrderValue":"5,000,000 USDT",
4184
+ // "maxOrderValueEv":500000000000000,
4185
+ // "defaultTakerFee":"0.001",
4186
+ // "defaultTakerFeeEr":100000,
4187
+ // "defaultMakerFee":"0.001",
4188
+ // "defaultMakerFeeEr":100000,
4189
+ // "baseQtyPrecision":6,
4190
+ // "quoteQtyPrecision":2
4191
+ // },
4192
+ // ],
4193
+ // "riskLimits":[
4194
+ // {
4195
+ // "symbol":"BTCUSD",
4196
+ // "steps":"50",
4197
+ // "riskLimits":[
4198
+ // {"limit":100,"initialMargin":"1.0%","initialMarginEr":1000000,"maintenanceMargin":"0.5%","maintenanceMarginEr":500000},
4199
+ // {"limit":150,"initialMargin":"1.5%","initialMarginEr":1500000,"maintenanceMargin":"1.0%","maintenanceMarginEr":1000000},
4200
+ // {"limit":200,"initialMargin":"2.0%","initialMarginEr":2000000,"maintenanceMargin":"1.5%","maintenanceMarginEr":1500000},
4201
+ // ]
4202
+ // },
4203
+ // ],
4204
+ // "leverages":[
4205
+ // {"initialMargin":"1.0%","initialMarginEr":1000000,"options":[1,2,3,5,10,25,50,100]},
4206
+ // {"initialMargin":"1.5%","initialMarginEr":1500000,"options":[1,2,3,5,10,25,50,66]},
4207
+ // {"initialMargin":"2.0%","initialMarginEr":2000000,"options":[1,2,3,5,10,25,33,50]},
4208
+ // ]
4209
+ // }
4210
+ // }
4211
+ //
4212
+ //
4213
+ const data = this.safeValue(response, 'data', {});
4214
+ const riskLimits = this.safeValue(data, 'riskLimits');
4215
+ return this.parseLeverageTiers(riskLimits, symbols, 'symbol');
4216
+ }
4217
+ parseMarketLeverageTiers(info, market = undefined) {
4218
+ /**
4219
+ * @param {object} info Exchange market response for 1 market
4220
+ * @param {object} market CCXT market
4221
+ */
4222
+ //
4223
+ // {
4224
+ // "symbol":"BTCUSD",
4225
+ // "steps":"50",
4226
+ // "riskLimits":[
4227
+ // {"limit":100,"initialMargin":"1.0%","initialMarginEr":1000000,"maintenanceMargin":"0.5%","maintenanceMarginEr":500000},
4228
+ // {"limit":150,"initialMargin":"1.5%","initialMarginEr":1500000,"maintenanceMargin":"1.0%","maintenanceMarginEr":1000000},
4229
+ // {"limit":200,"initialMargin":"2.0%","initialMarginEr":2000000,"maintenanceMargin":"1.5%","maintenanceMarginEr":1500000},
4230
+ // ]
4231
+ // },
4232
+ //
4233
+ market = this.safeMarket(undefined, market);
4234
+ const riskLimits = (market['info']['riskLimits']);
4235
+ const tiers = [];
4236
+ let minNotional = 0;
4237
+ for (let i = 0; i < riskLimits.length; i++) {
4238
+ const tier = riskLimits[i];
4239
+ const maxNotional = this.safeInteger(tier, 'limit');
4240
+ tiers.push({
4241
+ 'tier': this.sum(i, 1),
4242
+ 'currency': market['settle'],
4243
+ 'minNotional': minNotional,
4244
+ 'maxNotional': maxNotional,
4245
+ 'maintenanceMarginRate': this.safeString(tier, 'maintenanceMargin'),
4246
+ 'maxLeverage': undefined,
4247
+ 'info': tier,
4248
+ });
4249
+ minNotional = maxNotional;
4250
+ }
4251
+ return tiers;
4252
+ }
4253
+ sign(path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
4254
+ const query = this.omit(params, this.extractParams(path));
4255
+ const requestPath = '/' + this.implodeParams(path, params);
4256
+ let url = requestPath;
4257
+ let queryString = '';
4258
+ if ((method === 'GET') || (method === 'DELETE') || (method === 'PUT') || (url === '/positions/assign')) {
4259
+ if (Object.keys(query).length) {
4260
+ queryString = this.urlencodeWithArrayRepeat(query);
4261
+ url += '?' + queryString;
4262
+ }
4263
+ }
4264
+ if (api === 'private') {
4265
+ this.checkRequiredCredentials();
4266
+ const timestamp = this.seconds();
4267
+ const xPhemexRequestExpiry = this.safeInteger(this.options, 'x-phemex-request-expiry', 60);
4268
+ const expiry = this.sum(timestamp, xPhemexRequestExpiry);
4269
+ const expiryString = expiry.toString();
4270
+ headers = {
4271
+ 'x-phemex-access-token': this.apiKey,
4272
+ 'x-phemex-request-expiry': expiryString,
4273
+ };
4274
+ let payload = '';
4275
+ if (method === 'POST') {
4276
+ const isOrderPlacement = (path === 'g-orders') || (path === 'spot/orders') || (path === 'orders');
4277
+ if (isOrderPlacement) {
4278
+ if (this.safeString(params, 'clOrdID') === undefined) {
4279
+ const id = this.safeString(this.options, 'brokerId', 'CCXT123456');
4280
+ params['clOrdID'] = id + this.uuid16();
4281
+ }
4282
+ }
4283
+ payload = this.json(params);
4284
+ body = payload;
4285
+ headers['Content-Type'] = 'application/json';
4286
+ }
4287
+ const auth = requestPath + queryString + expiryString + payload;
4288
+ headers['x-phemex-request-signature'] = this.hmac(this.encode(auth), this.encode(this.secret), sha256.sha256);
4289
+ }
4290
+ url = this.implodeHostname(this.urls['api'][api]) + url;
4291
+ return { 'url': url, 'method': method, 'body': body, 'headers': headers };
4292
+ }
4293
+ async setLeverage(leverage, symbol = undefined, params = {}) {
4294
+ /**
4295
+ * @method
4296
+ * @name phemex#setLeverage
4297
+ * @description set the level of leverage for a market
4298
+ * @see https://github.com/phemex/phemex-api-docs/blob/master/Public-Hedged-Perpetual-API.md#set-leverage
4299
+ * @param {float} leverage the rate of leverage, 100 > leverage > -100 excluding numbers between -1 to 1
4300
+ * @param {string} symbol unified market symbol
4301
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
4302
+ * @param {bool} [params.hedged] set to true if hedged position mode is enabled (by default long and short leverage are set to the same value)
4303
+ * @param {float} [params.longLeverageRr] *hedged mode only* set the leverage for long positions
4304
+ * @param {float} [params.shortLeverageRr] *hedged mode only* set the leverage for short positions
4305
+ * @returns {object} response from the exchange
4306
+ */
4307
+ // WARNING: THIS WILL INCREASE LIQUIDATION PRICE FOR OPEN ISOLATED LONG POSITIONS
4308
+ // AND DECREASE LIQUIDATION PRICE FOR OPEN ISOLATED SHORT POSITIONS
4309
+ if (symbol === undefined) {
4310
+ throw new errors.ArgumentsRequired(this.id + ' setLeverage() requires a symbol argument');
4311
+ }
4312
+ if ((leverage < -100) || (leverage > 100)) {
4313
+ throw new errors.BadRequest(this.id + ' setLeverage() leverage should be between -100 and 100');
4314
+ }
4315
+ await this.loadMarkets();
4316
+ const isHedged = this.safeValue(params, 'hedged', false);
4317
+ const longLeverageRr = this.safeInteger(params, 'longLeverageRr');
4318
+ const shortLeverageRr = this.safeInteger(params, 'shortLeverageRr');
4319
+ const market = this.market(symbol);
4320
+ const request = {
4321
+ 'symbol': market['id'],
4322
+ };
4323
+ let response = undefined;
4324
+ if (market['settle'] === 'USDT') {
4325
+ if (!isHedged && longLeverageRr === undefined && shortLeverageRr === undefined) {
4326
+ request['leverageRr'] = leverage;
4327
+ }
4328
+ else {
4329
+ const long = (longLeverageRr !== undefined) ? longLeverageRr : leverage;
4330
+ const short = (shortLeverageRr !== undefined) ? shortLeverageRr : leverage;
4331
+ request['longLeverageRr'] = long;
4332
+ request['shortLeverageRr'] = short;
4333
+ }
4334
+ response = await this.privatePutGPositionsLeverage(this.extend(request, params));
4335
+ }
4336
+ else {
4337
+ request['leverage'] = leverage;
4338
+ response = await this.privatePutPositionsLeverage(this.extend(request, params));
4339
+ }
4340
+ return response;
4341
+ }
4342
+ async transfer(code, amount, fromAccount, toAccount, params = {}) {
4343
+ /**
4344
+ * @method
4345
+ * @name phemex#transfer
4346
+ * @description transfer currency internally between wallets on the same account
4347
+ * @param {string} code unified currency code
4348
+ * @param {float} amount amount to transfer
4349
+ * @param {string} fromAccount account to transfer from
4350
+ * @param {string} toAccount account to transfer to
4351
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
4352
+ * @param {string} [params.bizType] for transferring between main and sub-acounts either 'SPOT' or 'PERPETUAL' default is 'SPOT'
4353
+ * @returns {object} a [transfer structure]{@link https://docs.ccxt.com/#/?id=transfer-structure}
4354
+ */
4355
+ await this.loadMarkets();
4356
+ const currency = this.currency(code);
4357
+ const accountsByType = this.safeValue(this.options, 'accountsByType', {});
4358
+ const fromId = this.safeString(accountsByType, fromAccount, fromAccount);
4359
+ const toId = this.safeString(accountsByType, toAccount, toAccount);
4360
+ const scaledAmmount = this.toEv(amount, currency);
4361
+ let direction = undefined;
4362
+ let transfer = undefined;
4363
+ if (fromId === 'spot' && toId === 'future') {
4364
+ direction = 2;
4365
+ }
4366
+ else if (fromId === 'future' && toId === 'spot') {
4367
+ direction = 1;
4368
+ }
4369
+ if (direction !== undefined) {
4370
+ const request = {
4371
+ 'currency': currency['id'],
4372
+ 'moveOp': direction,
4373
+ 'amountEv': scaledAmmount,
4374
+ };
4375
+ const response = await this.privatePostAssetsTransfer(this.extend(request, params));
4376
+ //
4377
+ // {
4378
+ // "code": "0",
4379
+ // "msg": "OK",
4380
+ // "data": {
4381
+ // "linkKey": "8564eba4-c9ec-49d6-9b8c-2ec5001a0fb9",
4382
+ // "userId": "4018340",
4383
+ // "currency": "USD",
4384
+ // "amountEv": "10",
4385
+ // "side": "2",
4386
+ // "status": "10"
4387
+ // }
4388
+ // }
4389
+ //
4390
+ const data = this.safeValue(response, 'data', {});
4391
+ transfer = this.parseTransfer(data, currency);
4392
+ }
4393
+ else { // sub account transfer
4394
+ const request = {
4395
+ 'fromUserId': fromId,
4396
+ 'toUserId': toId,
4397
+ 'amountEv': scaledAmmount,
4398
+ 'currency': currency['id'],
4399
+ 'bizType': this.safeString(params, 'bizType', 'SPOT'),
4400
+ };
4401
+ const response = await this.privatePostAssetsUniversalTransfer(this.extend(request, params));
4402
+ //
4403
+ // {
4404
+ // "code": "0",
4405
+ // "msg": "OK",
4406
+ // "data": "API-923db826-aaaa-aaaa-aaaa-4d98c3a7c9fd"
4407
+ // }
4408
+ //
4409
+ transfer = this.parseTransfer(response);
4410
+ }
4411
+ const transferOptions = this.safeValue(this.options, 'transfer', {});
4412
+ const fillResponseFromRequest = this.safeValue(transferOptions, 'fillResponseFromRequest', true);
4413
+ if (fillResponseFromRequest) {
4414
+ if (transfer['fromAccount'] === undefined) {
4415
+ transfer['fromAccount'] = fromAccount;
4416
+ }
4417
+ if (transfer['toAccount'] === undefined) {
4418
+ transfer['toAccount'] = toAccount;
4419
+ }
4420
+ if (transfer['amount'] === undefined) {
4421
+ transfer['amount'] = amount;
4422
+ }
4423
+ if (transfer['currency'] === undefined) {
4424
+ transfer['currency'] = code;
4425
+ }
4426
+ }
4427
+ return transfer;
4428
+ }
4429
+ async fetchTransfers(code = undefined, since = undefined, limit = undefined, params = {}) {
4430
+ /**
4431
+ * @method
4432
+ * @name phemex#fetchTransfers
4433
+ * @description fetch a history of internal transfers made on an account
4434
+ * @param {string} code unified currency code of the currency transferred
4435
+ * @param {int} [since] the earliest time in ms to fetch transfers for
4436
+ * @param {int} [limit] the maximum number of transfers structures to retrieve
4437
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
4438
+ * @returns {object[]} a list of [transfer structures]{@link https://docs.ccxt.com/#/?id=transfer-structure}
4439
+ */
4440
+ await this.loadMarkets();
4441
+ if (code === undefined) {
4442
+ throw new errors.ArgumentsRequired(this.id + ' fetchTransfers() requires a code argument');
4443
+ }
4444
+ const currency = this.currency(code);
4445
+ const request = {
4446
+ 'currency': currency['id'],
4447
+ };
4448
+ if (since !== undefined) {
4449
+ request['start'] = since;
4450
+ }
4451
+ if (limit !== undefined) {
4452
+ request['limit'] = limit;
4453
+ }
4454
+ const response = await this.privateGetAssetsTransfer(this.extend(request, params));
4455
+ //
4456
+ // {
4457
+ // "code": 0,
4458
+ // "msg": "OK",
4459
+ // "data": {
4460
+ // "rows": [
4461
+ // {
4462
+ // "linkKey": "87c071a3-8628-4ac2-aca1-6ce0d1fad66c",
4463
+ // "userId": 4148428,
4464
+ // "currency": "BTC",
4465
+ // "amountEv": 67932,
4466
+ // "side": 2,
4467
+ // "status": 10,
4468
+ // "createTime": 1652832467000,
4469
+ // "bizType": 10
4470
+ // }
4471
+ // ]
4472
+ // }
4473
+ // }
4474
+ //
4475
+ const data = this.safeValue(response, 'data', {});
4476
+ const transfers = this.safeValue(data, 'rows', []);
4477
+ return this.parseTransfers(transfers, currency, since, limit);
4478
+ }
4479
+ parseTransfer(transfer, currency = undefined) {
4480
+ //
4481
+ // transfer
4482
+ //
4483
+ // {
4484
+ // "linkKey": "8564eba4-c9ec-49d6-9b8c-2ec5001a0fb9",
4485
+ // "userId": "4018340",
4486
+ // "currency": "USD",
4487
+ // "amountEv": "10",
4488
+ // "side": "2",
4489
+ // "status": "10"
4490
+ // }
4491
+ //
4492
+ // fetchTransfers
4493
+ //
4494
+ // {
4495
+ // "linkKey": "87c071a3-8628-4ac2-aca1-6ce0d1fad66c",
4496
+ // "userId": 4148428,
4497
+ // "currency": "BTC",
4498
+ // "amountEv": 67932,
4499
+ // "side": 2,
4500
+ // "status": 10,
4501
+ // "createTime": 1652832467000,
4502
+ // "bizType": 10
4503
+ // }
4504
+ //
4505
+ const id = this.safeString(transfer, 'linkKey');
4506
+ const status = this.safeString(transfer, 'status');
4507
+ const amountEv = this.safeString(transfer, 'amountEv');
4508
+ const amountTransfered = this.fromEv(amountEv);
4509
+ const currencyId = this.safeString(transfer, 'currency');
4510
+ const code = this.safeCurrencyCode(currencyId, currency);
4511
+ const side = this.safeInteger(transfer, 'side');
4512
+ let fromId = undefined;
4513
+ let toId = undefined;
4514
+ if (side === 1) {
4515
+ fromId = 'swap';
4516
+ toId = 'spot';
4517
+ }
4518
+ else if (side === 2) {
4519
+ fromId = 'spot';
4520
+ toId = 'swap';
4521
+ }
4522
+ const timestamp = this.safeInteger(transfer, 'createTime');
4523
+ return {
4524
+ 'info': transfer,
4525
+ 'id': id,
4526
+ 'timestamp': timestamp,
4527
+ 'datetime': this.iso8601(timestamp),
4528
+ 'currency': code,
4529
+ 'amount': amountTransfered,
4530
+ 'fromAccount': fromId,
4531
+ 'toAccount': toId,
4532
+ 'status': this.parseTransferStatus(status),
4533
+ };
4534
+ }
4535
+ parseTransferStatus(status) {
4536
+ const statuses = {
4537
+ '3': 'rejected',
4538
+ '6': 'canceled',
4539
+ '10': 'ok',
4540
+ '11': 'failed', // 'Failed',
4541
+ };
4542
+ return this.safeString(statuses, status, status);
4543
+ }
4544
+ async fetchFundingRateHistory(symbol = undefined, since = undefined, limit = undefined, params = {}) {
4545
+ /**
4546
+ * @method
4547
+ * @name phemex#fetchFundingRateHistory
4548
+ * @description fetches historical funding rate prices
4549
+ * @see https://phemex-docs.github.io/#query-funding-rate-history-2
4550
+ * @param {string} symbol unified symbol of the market to fetch the funding rate history for
4551
+ * @param {int} [since] timestamp in ms of the earliest funding rate to fetch
4552
+ * @param {int} [limit] the maximum amount of [funding rate structures]{@link https://docs.ccxt.com/#/?id=funding-rate-history-structure} to fetch
4553
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
4554
+ * @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
4555
+ * @param {int} [params.until] timestamp in ms of the latest funding rate
4556
+ * @returns {object[]} a list of [funding rate structures]{@link https://docs.ccxt.com/#/?id=funding-rate-history-structure}
4557
+ */
4558
+ if (symbol === undefined) {
4559
+ throw new errors.ArgumentsRequired(this.id + ' fetchFundingRateHistory() requires a symbol argument');
4560
+ }
4561
+ await this.loadMarkets();
4562
+ const market = this.market(symbol);
4563
+ const isUsdtSettled = market['settle'] === 'USDT';
4564
+ if (!market['swap']) {
4565
+ throw new errors.BadRequest(this.id + ' fetchFundingRateHistory() supports swap contracts only');
4566
+ }
4567
+ let paginate = false;
4568
+ [paginate, params] = this.handleOptionAndParams(params, 'fetchFundingRateHistory', 'paginate');
4569
+ if (paginate) {
4570
+ return await this.fetchPaginatedCallDeterministic('fetchFundingRateHistory', symbol, since, limit, '8h', params, 100);
4571
+ }
4572
+ let customSymbol = undefined;
4573
+ if (isUsdtSettled) {
4574
+ customSymbol = '.' + market['id'] + 'FR8H'; // phemex requires a custom symbol for funding rate history
4575
+ }
4576
+ else {
4577
+ customSymbol = '.' + market['baseId'] + 'FR8H';
4578
+ }
4579
+ let request = {
4580
+ 'symbol': customSymbol,
4581
+ };
4582
+ if (since !== undefined) {
4583
+ request['start'] = since;
4584
+ }
4585
+ if (limit !== undefined) {
4586
+ request['limit'] = limit;
4587
+ }
4588
+ [request, params] = this.handleUntilOption('end', request, params);
4589
+ let response = undefined;
4590
+ if (isUsdtSettled) {
4591
+ response = await this.v2GetApiDataPublicDataFundingRateHistory(this.extend(request, params));
4592
+ }
4593
+ else {
4594
+ response = await this.v1GetApiDataPublicDataFundingRateHistory(this.extend(request, params));
4595
+ }
4596
+ //
4597
+ // {
4598
+ // "code":"0",
4599
+ // "msg":"OK",
4600
+ // "data":{
4601
+ // "rows":[
4602
+ // {
4603
+ // "symbol":".BTCUSDTFR8H",
4604
+ // "fundingRate":"0.0001",
4605
+ // "fundingTime":"1682064000000",
4606
+ // "intervalSeconds":"28800"
4607
+ // }
4608
+ // ]
4609
+ // }
4610
+ // }
4611
+ //
4612
+ const data = this.safeValue(response, 'data', {});
4613
+ const rates = this.safeValue(data, 'rows');
4614
+ const result = [];
4615
+ for (let i = 0; i < rates.length; i++) {
4616
+ const item = rates[i];
4617
+ const timestamp = this.safeInteger(item, 'fundingTime');
4618
+ result.push({
4619
+ 'info': item,
4620
+ 'symbol': symbol,
4621
+ 'fundingRate': this.safeNumber(item, 'fundingRate'),
4622
+ 'timestamp': timestamp,
4623
+ 'datetime': this.iso8601(timestamp),
4624
+ });
4625
+ }
4626
+ const sorted = this.sortBy(result, 'timestamp');
4627
+ return this.filterBySymbolSinceLimit(sorted, symbol, since, limit);
4628
+ }
4629
+ async withdraw(code, amount, address, tag = undefined, params = {}) {
4630
+ /**
4631
+ * @method
4632
+ * @name phemex#withdraw
4633
+ * @description make a withdrawal
4634
+ * @see https://phemex-docs.github.io/#create-withdraw-request
4635
+ * @param {string} code unified currency code
4636
+ * @param {float} amount the amount to withdraw
4637
+ * @param {string} address the address to withdraw to
4638
+ * @param {string} tag
4639
+ * @param {object} [params] extra parameters specific to the phemex api endpoint
4640
+ * @param {string} [params.network] unified network code
4641
+ * @returns {object} a [transaction structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#transaction-structure}
4642
+ */
4643
+ [tag, params] = this.handleWithdrawTagAndParams(tag, params);
4644
+ await this.loadMarkets();
4645
+ this.checkAddress(address);
4646
+ const currency = this.currency(code);
4647
+ let networkCode = undefined;
4648
+ [networkCode, params] = this.handleNetworkCodeAndParams(params);
4649
+ let networkId = this.networkCodeToId(networkCode);
4650
+ const stableCoins = this.safeValue(this.options, 'stableCoins');
4651
+ if (networkId === undefined) {
4652
+ if (!(this.inArray(code, stableCoins))) {
4653
+ networkId = currency['id'];
4654
+ }
4655
+ else {
4656
+ throw new errors.ArgumentsRequired(this.id + ' withdraw () requires an extra argument params["network"]');
4657
+ }
4658
+ }
4659
+ const request = {
4660
+ 'currency': currency['id'],
4661
+ 'address': address,
4662
+ 'amount': amount,
4663
+ 'chainName': networkId.toUpperCase(),
4664
+ };
4665
+ if (tag !== undefined) {
4666
+ request['addressTag'] = tag;
4667
+ }
4668
+ const response = await this.privatePostPhemexWithdrawWalletsApiCreateWithdraw(this.extend(request, params));
4669
+ //
4670
+ // {
4671
+ // "code": 0,
4672
+ // "msg": "OK",
4673
+ // "data": {
4674
+ // "id": "10000001",
4675
+ // "freezeId": null,
4676
+ // "address": "44exxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
4677
+ // "amountRv": "100",
4678
+ // "chainCode": "11",
4679
+ // "chainName": "TRX",
4680
+ // "currency": "USDT",
4681
+ // "currencyCode": 3,
4682
+ // "email": "abc@gmail.com",
4683
+ // "expiredTime": "0",
4684
+ // "feeRv": "1",
4685
+ // "nickName": null,
4686
+ // "phone": null,
4687
+ // "rejectReason": "",
4688
+ // "submitedAt": "1670000000000",
4689
+ // "submittedAt": "1670000000000",
4690
+ // "txHash": null,
4691
+ // "userId": "10000001",
4692
+ // "status": "Success"
4693
+ // }
4694
+ // }
4695
+ //
4696
+ const data = this.safeValue(response, 'data', {});
4697
+ return this.parseTransaction(data, currency);
4698
+ }
4699
+ handleErrors(httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) {
4700
+ if (response === undefined) {
4701
+ return undefined; // fallback to default error handler
4702
+ }
4703
+ //
4704
+ // {"code":30018,"msg":"phemex.data.size.uplimt","data":null}
4705
+ // {"code":412,"msg":"Missing parameter - resolution","data":null}
4706
+ // {"code":412,"msg":"Missing parameter - to","data":null}
4707
+ // {"error":{"code":6001,"message":"invalid argument"},"id":null,"result":null}
4708
+ //
4709
+ const error = this.safeValue(response, 'error', response);
4710
+ const errorCode = this.safeString(error, 'code');
4711
+ const message = this.safeString(error, 'msg');
4712
+ if ((errorCode !== undefined) && (errorCode !== '0')) {
4713
+ const feedback = this.id + ' ' + body;
4714
+ this.throwExactlyMatchedException(this.exceptions['exact'], errorCode, feedback);
4715
+ this.throwBroadlyMatchedException(this.exceptions['broad'], message, feedback);
4716
+ throw new errors.ExchangeError(feedback); // unknown message
4717
+ }
4718
+ return undefined;
4719
+ }
4720
+ }
4721
+
4722
+ module.exports = phemex;