ccxt-ir 4.3.46.0.2__py2.py3-none-any.whl → 4.5.0__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (528) hide show
  1. ccxt/__init__.py +39 -35
  2. ccxt/abantether.py +9 -9
  3. ccxt/abstract/alpaca.py +4 -0
  4. ccxt/abstract/apex.py +31 -0
  5. ccxt/abstract/bigone.py +1 -1
  6. ccxt/abstract/binance.py +106 -48
  7. ccxt/abstract/binancecoinm.py +106 -48
  8. ccxt/abstract/binanceus.py +141 -83
  9. ccxt/abstract/binanceusdm.py +106 -48
  10. ccxt/abstract/bingx.py +50 -1
  11. ccxt/abstract/bitbank.py +5 -0
  12. ccxt/abstract/bitfinex.py +136 -65
  13. ccxt/abstract/bitflyer.py +1 -0
  14. ccxt/abstract/bitget.py +67 -0
  15. ccxt/abstract/bitmart.py +19 -1
  16. ccxt/abstract/bitopro.py +1 -0
  17. ccxt/abstract/bitrue.py +68 -68
  18. ccxt/abstract/bitstamp.py +1 -0
  19. ccxt/abstract/blofin.py +30 -0
  20. ccxt/abstract/btcbox.py +2 -0
  21. ccxt/abstract/bybit.py +28 -13
  22. ccxt/abstract/cex.py +28 -29
  23. ccxt/abstract/coinbaseexchange.py +1 -0
  24. ccxt/abstract/coinbaseinternational.py +1 -1
  25. ccxt/abstract/cryptocom.py +16 -0
  26. ccxt/abstract/cryptomus.py +20 -0
  27. ccxt/abstract/defx.py +69 -0
  28. ccxt/abstract/deribit.py +1 -0
  29. ccxt/abstract/derive.py +117 -0
  30. ccxt/abstract/digifinex.py +1 -0
  31. ccxt/abstract/ellipx.py +25 -0
  32. ccxt/abstract/foxbit.py +26 -0
  33. ccxt/abstract/gate.py +19 -0
  34. ccxt/abstract/gateio.py +19 -0
  35. ccxt/abstract/gemini.py +1 -0
  36. ccxt/abstract/hibachi.py +26 -0
  37. ccxt/abstract/hyperliquid.py +1 -1
  38. ccxt/abstract/independentreserve.py +6 -0
  39. ccxt/abstract/kraken.py +1 -0
  40. ccxt/abstract/krakenfutures.py +4 -0
  41. ccxt/abstract/kucoin.py +10 -0
  42. ccxt/abstract/kucoinfutures.py +18 -0
  43. ccxt/abstract/lbank.py +2 -1
  44. ccxt/abstract/luno.py +1 -0
  45. ccxt/abstract/mexc.py +2 -0
  46. ccxt/abstract/modetrade.py +119 -0
  47. ccxt/abstract/myokx.py +349 -0
  48. ccxt/abstract/oceanex.py +5 -0
  49. ccxt/abstract/okx.py +25 -0
  50. ccxt/abstract/okxus.py +349 -0
  51. ccxt/abstract/onetrading.py +0 -12
  52. ccxt/abstract/paradex.py +23 -0
  53. ccxt/abstract/phemex.py +2 -0
  54. ccxt/abstract/poloniex.py +36 -0
  55. ccxt/abstract/tradeogre.py +3 -1
  56. ccxt/abstract/upbit.py +51 -34
  57. ccxt/abstract/whitebit.py +16 -0
  58. ccxt/abstract/woo.py +64 -6
  59. ccxt/abstract/xt.py +10 -5
  60. ccxt/afratether.py +7 -7
  61. ccxt/alpaca.py +828 -51
  62. ccxt/apex.py +1875 -0
  63. ccxt/arzinja.py +7 -7
  64. ccxt/arzplus.py +9 -9
  65. ccxt/ascendex.py +501 -306
  66. ccxt/async_support/__init__.py +39 -35
  67. ccxt/async_support/abantether.py +10 -10
  68. ccxt/async_support/afratether.py +9 -9
  69. ccxt/async_support/alpaca.py +828 -51
  70. ccxt/async_support/apex.py +1875 -0
  71. ccxt/async_support/arzinja.py +10 -10
  72. ccxt/async_support/arzplus.py +12 -12
  73. ccxt/async_support/ascendex.py +502 -306
  74. ccxt/async_support/base/exchange.py +303 -89
  75. ccxt/async_support/base/ws/cache.py +9 -3
  76. ccxt/async_support/base/ws/client.py +173 -38
  77. ccxt/async_support/base/ws/future.py +25 -37
  78. ccxt/async_support/bequant.py +5 -3
  79. ccxt/async_support/bigone.py +279 -144
  80. ccxt/async_support/binance.py +2347 -1158
  81. ccxt/async_support/binancecoinm.py +9 -3
  82. ccxt/async_support/binanceus.py +17 -3
  83. ccxt/async_support/binanceusdm.py +9 -4
  84. ccxt/async_support/bingx.py +2962 -920
  85. ccxt/async_support/bit2c.py +147 -27
  86. ccxt/async_support/bitbank.py +151 -23
  87. ccxt/async_support/bitbns.py +104 -30
  88. ccxt/async_support/bitfinex.py +3291 -1113
  89. ccxt/async_support/bitflyer.py +202 -27
  90. ccxt/async_support/bitget.py +3683 -1538
  91. ccxt/async_support/bithumb.py +195 -38
  92. ccxt/async_support/bitimen.py +12 -12
  93. ccxt/async_support/bitir.py +38 -38
  94. ccxt/async_support/bitmart.py +1288 -350
  95. ccxt/async_support/bitmex.py +260 -75
  96. ccxt/async_support/bitopro.py +262 -62
  97. ccxt/async_support/bitpin.py +17 -16
  98. ccxt/async_support/bitrue.py +459 -290
  99. ccxt/async_support/bitso.py +199 -54
  100. ccxt/async_support/bitstamp.py +230 -96
  101. ccxt/async_support/bitteam.py +167 -25
  102. ccxt/async_support/{huobijp.py → bittrade.py} +158 -30
  103. ccxt/async_support/bitvavo.py +213 -49
  104. ccxt/async_support/blockchaincom.py +160 -46
  105. ccxt/async_support/blofin.py +502 -120
  106. ccxt/async_support/btcalpha.py +169 -31
  107. ccxt/async_support/btcbox.py +292 -23
  108. ccxt/async_support/btcmarkets.py +211 -58
  109. ccxt/async_support/btcturk.py +161 -38
  110. ccxt/async_support/bybit.py +1775 -1030
  111. ccxt/async_support/cex.py +1440 -1303
  112. ccxt/async_support/coinbase.py +724 -212
  113. ccxt/async_support/coinbaseadvanced.py +2 -1
  114. ccxt/async_support/coinbaseexchange.py +388 -89
  115. ccxt/async_support/coinbaseinternational.py +412 -57
  116. ccxt/async_support/coincatch.py +177 -78
  117. ccxt/async_support/coincheck.py +135 -19
  118. ccxt/async_support/coinex.py +606 -232
  119. ccxt/async_support/coinmate.py +189 -63
  120. ccxt/async_support/coinmetro.py +195 -54
  121. ccxt/async_support/coinone.py +158 -51
  122. ccxt/async_support/coinsph.py +336 -61
  123. ccxt/async_support/coinspot.py +151 -52
  124. ccxt/async_support/cryptocom.py +661 -111
  125. ccxt/async_support/cryptomus.py +1137 -0
  126. ccxt/async_support/defx.py +2071 -0
  127. ccxt/async_support/delta.py +299 -99
  128. ccxt/async_support/deribit.py +348 -126
  129. ccxt/async_support/derive.py +2572 -0
  130. ccxt/async_support/digifinex.py +430 -214
  131. ccxt/async_support/ellipx.py +2029 -0
  132. ccxt/async_support/eterex.py +10 -10
  133. ccxt/async_support/excoino.py +31 -31
  134. ccxt/async_support/exir.py +14 -14
  135. ccxt/async_support/exmo.py +344 -131
  136. ccxt/async_support/exnovin.py +10 -10
  137. ccxt/async_support/farhadexchange.py +12 -12
  138. ccxt/async_support/fmfwio.py +2 -1
  139. ccxt/async_support/foxbit.py +1935 -0
  140. ccxt/async_support/gate.py +1351 -529
  141. ccxt/async_support/gateio.py +2 -1
  142. ccxt/async_support/gemini.py +144 -39
  143. ccxt/async_support/hashkey.py +152 -109
  144. ccxt/async_support/hibachi.py +2080 -0
  145. ccxt/async_support/hitbtc.py +395 -167
  146. ccxt/async_support/hitobit.py +12 -12
  147. ccxt/async_support/hollaex.py +307 -119
  148. ccxt/async_support/htx.py +851 -383
  149. ccxt/async_support/huobi.py +2 -1
  150. ccxt/async_support/hyperliquid.py +1848 -536
  151. ccxt/async_support/independentreserve.py +288 -15
  152. ccxt/async_support/indodax.py +190 -33
  153. ccxt/async_support/jibitex.py +12 -12
  154. ccxt/async_support/kraken.py +795 -351
  155. ccxt/async_support/krakenfutures.py +214 -62
  156. ccxt/async_support/kucoin.py +715 -396
  157. ccxt/async_support/kucoinfutures.py +652 -89
  158. ccxt/async_support/latoken.py +217 -113
  159. ccxt/async_support/lbank.py +425 -97
  160. ccxt/async_support/luno.py +382 -35
  161. ccxt/async_support/mercado.py +113 -6
  162. ccxt/async_support/mexc.py +874 -437
  163. ccxt/async_support/modetrade.py +2818 -0
  164. ccxt/async_support/myokx.py +54 -0
  165. ccxt/async_support/ndax.py +221 -64
  166. ccxt/async_support/nobitex.py +31 -37
  167. ccxt/async_support/novadax.py +190 -34
  168. ccxt/async_support/oceanex.py +217 -28
  169. ccxt/async_support/okcoin.py +253 -145
  170. ccxt/async_support/okexchange.py +11 -11
  171. ccxt/async_support/okx.py +1088 -351
  172. ccxt/async_support/okxus.py +54 -0
  173. ccxt/async_support/ompfinex.py +25 -24
  174. ccxt/async_support/onetrading.py +213 -392
  175. ccxt/async_support/oxfun.py +245 -166
  176. ccxt/async_support/p2b.py +151 -29
  177. ccxt/async_support/paradex.py +562 -49
  178. ccxt/async_support/paymium.py +82 -19
  179. ccxt/async_support/phemex.py +713 -172
  180. ccxt/async_support/poloniex.py +1602 -283
  181. ccxt/async_support/probit.py +224 -95
  182. ccxt/async_support/ramzinex.py +30 -27
  183. ccxt/async_support/sarmayex.py +9 -9
  184. ccxt/async_support/sarrafex.py +13 -13
  185. ccxt/async_support/tabdeal.py +14 -13
  186. ccxt/async_support/tetherland.py +9 -9
  187. ccxt/async_support/timex.py +210 -51
  188. ccxt/async_support/tokocrypto.py +167 -47
  189. ccxt/async_support/tradeogre.py +266 -31
  190. ccxt/async_support/twox.py +9 -9
  191. ccxt/async_support/ubitex.py +12 -12
  192. ccxt/async_support/upbit.py +568 -165
  193. ccxt/async_support/vertex.py +160 -32
  194. ccxt/async_support/wallex.py +12 -12
  195. ccxt/async_support/wavesexchange.py +165 -30
  196. ccxt/async_support/whitebit.py +975 -127
  197. ccxt/async_support/woo.py +1918 -1016
  198. ccxt/async_support/woofipro.py +433 -141
  199. ccxt/async_support/xt.py +649 -193
  200. ccxt/async_support/yobit.py +195 -70
  201. ccxt/async_support/zaif.py +91 -15
  202. ccxt/async_support/zonda.py +151 -36
  203. ccxt/base/decimal_to_precision.py +14 -10
  204. ccxt/base/errors.py +49 -18
  205. ccxt/base/exchange.py +1556 -450
  206. ccxt/base/precise.py +10 -0
  207. ccxt/base/types.py +114 -6
  208. ccxt/bequant.py +5 -3
  209. ccxt/bigone.py +279 -144
  210. ccxt/binance.py +2347 -1158
  211. ccxt/binancecoinm.py +9 -3
  212. ccxt/binanceus.py +17 -3
  213. ccxt/binanceusdm.py +9 -4
  214. ccxt/bingx.py +2962 -920
  215. ccxt/bit2c.py +147 -27
  216. ccxt/bitbank.py +151 -23
  217. ccxt/bitbns.py +104 -30
  218. ccxt/bitfinex.py +3290 -1113
  219. ccxt/bitflyer.py +202 -27
  220. ccxt/bitget.py +3683 -1538
  221. ccxt/bithumb.py +194 -38
  222. ccxt/bitimen.py +9 -9
  223. ccxt/bitir.py +35 -35
  224. ccxt/bitmart.py +1288 -350
  225. ccxt/bitmex.py +260 -75
  226. ccxt/bitopro.py +262 -62
  227. ccxt/bitpin.py +15 -14
  228. ccxt/bitrue.py +459 -290
  229. ccxt/bitso.py +199 -54
  230. ccxt/bitstamp.py +230 -96
  231. ccxt/bitteam.py +167 -25
  232. ccxt/{huobijp.py → bittrade.py} +158 -30
  233. ccxt/bitvavo.py +213 -49
  234. ccxt/blockchaincom.py +160 -46
  235. ccxt/blofin.py +502 -120
  236. ccxt/btcalpha.py +169 -31
  237. ccxt/btcbox.py +291 -23
  238. ccxt/btcmarkets.py +211 -58
  239. ccxt/btcturk.py +161 -38
  240. ccxt/bybit.py +1775 -1030
  241. ccxt/cex.py +1439 -1303
  242. ccxt/coinbase.py +724 -212
  243. ccxt/coinbaseadvanced.py +2 -1
  244. ccxt/coinbaseexchange.py +388 -89
  245. ccxt/coinbaseinternational.py +412 -57
  246. ccxt/coincatch.py +177 -78
  247. ccxt/coincheck.py +135 -19
  248. ccxt/coinex.py +606 -232
  249. ccxt/coinmate.py +189 -63
  250. ccxt/coinmetro.py +194 -54
  251. ccxt/coinone.py +158 -51
  252. ccxt/coinsph.py +336 -61
  253. ccxt/coinspot.py +151 -52
  254. ccxt/cryptocom.py +661 -111
  255. ccxt/cryptomus.py +1137 -0
  256. ccxt/defx.py +2070 -0
  257. ccxt/delta.py +299 -99
  258. ccxt/deribit.py +348 -126
  259. ccxt/derive.py +2571 -0
  260. ccxt/digifinex.py +430 -214
  261. ccxt/ellipx.py +2029 -0
  262. ccxt/eterex.py +7 -7
  263. ccxt/excoino.py +29 -29
  264. ccxt/exir.py +11 -11
  265. ccxt/exmo.py +343 -131
  266. ccxt/exnovin.py +8 -8
  267. ccxt/farhadexchange.py +10 -10
  268. ccxt/fmfwio.py +2 -1
  269. ccxt/foxbit.py +1935 -0
  270. ccxt/gate.py +1351 -529
  271. ccxt/gateio.py +2 -1
  272. ccxt/gemini.py +144 -39
  273. ccxt/hashkey.py +152 -109
  274. ccxt/hibachi.py +2079 -0
  275. ccxt/hitbtc.py +395 -167
  276. ccxt/hitobit.py +9 -9
  277. ccxt/hollaex.py +307 -119
  278. ccxt/htx.py +851 -383
  279. ccxt/huobi.py +2 -1
  280. ccxt/hyperliquid.py +1848 -536
  281. ccxt/independentreserve.py +287 -15
  282. ccxt/indodax.py +190 -33
  283. ccxt/jibitex.py +9 -9
  284. ccxt/kraken.py +794 -351
  285. ccxt/krakenfutures.py +214 -62
  286. ccxt/kucoin.py +715 -396
  287. ccxt/kucoinfutures.py +652 -89
  288. ccxt/latoken.py +217 -113
  289. ccxt/lbank.py +425 -97
  290. ccxt/luno.py +382 -35
  291. ccxt/mercado.py +113 -6
  292. ccxt/mexc.py +873 -437
  293. ccxt/modetrade.py +2818 -0
  294. ccxt/myokx.py +54 -0
  295. ccxt/ndax.py +221 -64
  296. ccxt/nobitex.py +29 -35
  297. ccxt/novadax.py +190 -34
  298. ccxt/oceanex.py +217 -28
  299. ccxt/okcoin.py +253 -145
  300. ccxt/okexchange.py +9 -9
  301. ccxt/okx.py +1088 -351
  302. ccxt/okxus.py +54 -0
  303. ccxt/ompfinex.py +22 -21
  304. ccxt/onetrading.py +213 -392
  305. ccxt/oxfun.py +245 -166
  306. ccxt/p2b.py +151 -29
  307. ccxt/paradex.py +562 -49
  308. ccxt/paymium.py +82 -19
  309. ccxt/phemex.py +712 -172
  310. ccxt/poloniex.py +1601 -283
  311. ccxt/pro/__init__.py +76 -17
  312. ccxt/pro/alpaca.py +21 -6
  313. ccxt/pro/apex.py +984 -0
  314. ccxt/pro/ascendex.py +58 -10
  315. ccxt/pro/bequant.py +6 -1
  316. ccxt/pro/binance.py +728 -156
  317. ccxt/pro/binancecoinm.py +6 -2
  318. ccxt/pro/binanceus.py +8 -4
  319. ccxt/pro/binanceusdm.py +7 -2
  320. ccxt/pro/bingx.py +333 -142
  321. ccxt/pro/bitfinex.py +727 -262
  322. ccxt/pro/bitget.py +570 -79
  323. ccxt/pro/bithumb.py +20 -6
  324. ccxt/pro/bitmart.py +216 -87
  325. ccxt/pro/bitmex.py +47 -9
  326. ccxt/pro/bitopro.py +26 -14
  327. ccxt/pro/bitrue.py +22 -22
  328. ccxt/pro/bitstamp.py +54 -21
  329. ccxt/pro/{huobijp.py → bittrade.py} +7 -6
  330. ccxt/pro/bitvavo.py +191 -67
  331. ccxt/pro/blockchaincom.py +21 -8
  332. ccxt/pro/blofin.py +9 -1
  333. ccxt/pro/bybit.py +632 -245
  334. ccxt/pro/cex.py +59 -24
  335. ccxt/pro/coinbase.py +102 -73
  336. ccxt/pro/coinbaseadvanced.py +2 -1
  337. ccxt/pro/coinbaseexchange.py +8 -8
  338. ccxt/pro/coinbaseinternational.py +181 -25
  339. ccxt/pro/coincatch.py +6 -7
  340. ccxt/pro/coincheck.py +11 -6
  341. ccxt/pro/coinex.py +967 -665
  342. ccxt/pro/coinone.py +16 -9
  343. ccxt/pro/cryptocom.py +448 -45
  344. ccxt/pro/defx.py +831 -0
  345. ccxt/pro/deribit.py +150 -14
  346. ccxt/pro/derive.py +704 -0
  347. ccxt/pro/exmo.py +239 -6
  348. ccxt/pro/gate.py +623 -65
  349. ccxt/pro/gateio.py +2 -1
  350. ccxt/pro/gemini.py +27 -11
  351. ccxt/pro/hashkey.py +2 -2
  352. ccxt/pro/hitbtc.py +196 -91
  353. ccxt/pro/hollaex.py +23 -7
  354. ccxt/pro/htx.py +51 -14
  355. ccxt/pro/huobi.py +2 -1
  356. ccxt/pro/hyperliquid.py +591 -27
  357. ccxt/pro/independentreserve.py +9 -6
  358. ccxt/pro/kraken.py +640 -320
  359. ccxt/pro/krakenfutures.py +62 -35
  360. ccxt/pro/kucoin.py +267 -46
  361. ccxt/pro/kucoinfutures.py +165 -21
  362. ccxt/pro/lbank.py +102 -21
  363. ccxt/pro/luno.py +12 -8
  364. ccxt/pro/mexc.py +877 -111
  365. ccxt/pro/modetrade.py +1271 -0
  366. ccxt/pro/myokx.py +38 -0
  367. ccxt/pro/ndax.py +15 -2
  368. ccxt/pro/okcoin.py +23 -4
  369. ccxt/pro/okx.py +573 -98
  370. ccxt/pro/okxus.py +38 -0
  371. ccxt/pro/onetrading.py +30 -13
  372. ccxt/pro/oxfun.py +131 -27
  373. ccxt/pro/p2b.py +88 -22
  374. ccxt/pro/paradex.py +3 -3
  375. ccxt/pro/phemex.py +75 -21
  376. ccxt/pro/poloniex.py +124 -41
  377. ccxt/pro/probit.py +87 -80
  378. ccxt/pro/tradeogre.py +272 -0
  379. ccxt/pro/upbit.py +152 -12
  380. ccxt/pro/vertex.py +8 -3
  381. ccxt/pro/whitebit.py +58 -5
  382. ccxt/pro/woo.py +228 -37
  383. ccxt/pro/woofipro.py +106 -18
  384. ccxt/pro/xt.py +111 -5
  385. ccxt/probit.py +224 -95
  386. ccxt/protobuf/__init__.py +0 -0
  387. ccxt/protobuf/mexc/PrivateAccountV3Api_pb2.py +37 -0
  388. ccxt/protobuf/mexc/PrivateDealsV3Api_pb2.py +37 -0
  389. ccxt/protobuf/mexc/PrivateOrdersV3Api_pb2.py +37 -0
  390. ccxt/protobuf/mexc/PublicAggreBookTickerV3Api_pb2.py +37 -0
  391. ccxt/protobuf/mexc/PublicAggreDealsV3Api_pb2.py +39 -0
  392. ccxt/protobuf/mexc/PublicAggreDepthsV3Api_pb2.py +39 -0
  393. ccxt/protobuf/mexc/PublicBookTickerBatchV3Api_pb2.py +38 -0
  394. ccxt/protobuf/mexc/PublicBookTickerV3Api_pb2.py +37 -0
  395. ccxt/protobuf/mexc/PublicDealsV3Api_pb2.py +39 -0
  396. ccxt/protobuf/mexc/PublicIncreaseDepthsBatchV3Api_pb2.py +38 -0
  397. ccxt/protobuf/mexc/PublicIncreaseDepthsV3Api_pb2.py +39 -0
  398. ccxt/protobuf/mexc/PublicLimitDepthsV3Api_pb2.py +39 -0
  399. ccxt/protobuf/mexc/PublicMiniTickerV3Api_pb2.py +37 -0
  400. ccxt/protobuf/mexc/PublicMiniTickersV3Api_pb2.py +38 -0
  401. ccxt/protobuf/mexc/PublicSpotKlineV3Api_pb2.py +37 -0
  402. ccxt/protobuf/mexc/PushDataV3ApiWrapper_pb2.py +52 -0
  403. ccxt/protobuf/mexc/__init__.py +0 -0
  404. ccxt/ramzinex.py +28 -25
  405. ccxt/sarmayex.py +7 -7
  406. ccxt/sarrafex.py +10 -10
  407. ccxt/static_dependencies/__init__.py +1 -1
  408. ccxt/static_dependencies/lark/py.typed +0 -0
  409. ccxt/static_dependencies/marshmallow/py.typed +0 -0
  410. ccxt/static_dependencies/marshmallow_dataclass/py.typed +0 -0
  411. ccxt/static_dependencies/marshmallow_oneofschema/py.typed +0 -0
  412. ccxt/tabdeal.py +12 -11
  413. ccxt/test/tests_async.py +261 -57
  414. ccxt/test/tests_helpers.py +1 -3
  415. ccxt/test/tests_init.py +4 -3
  416. ccxt/test/tests_sync.py +261 -57
  417. ccxt/tetherland.py +7 -7
  418. ccxt/timex.py +210 -51
  419. ccxt/tokocrypto.py +167 -47
  420. ccxt/tradeogre.py +266 -31
  421. ccxt/twox.py +7 -7
  422. ccxt/ubitex.py +9 -9
  423. ccxt/upbit.py +568 -165
  424. ccxt/vertex.py +160 -32
  425. ccxt/wallex.py +9 -9
  426. ccxt/wavesexchange.py +165 -30
  427. ccxt/whitebit.py +975 -127
  428. ccxt/woo.py +1917 -1016
  429. ccxt/woofipro.py +432 -141
  430. ccxt/xt.py +649 -193
  431. ccxt/yobit.py +194 -70
  432. ccxt/zaif.py +91 -15
  433. ccxt/zonda.py +151 -36
  434. {ccxt_ir-4.3.46.0.2.dist-info → ccxt_ir-4.5.0.dist-info}/METADATA +225 -73
  435. ccxt_ir-4.5.0.dist-info/RECORD +743 -0
  436. {ccxt_ir-4.3.46.0.2.dist-info → ccxt_ir-4.5.0.dist-info}/WHEEL +1 -1
  437. ccxt/abstract/ace.py +0 -15
  438. ccxt/abstract/bitbay.py +0 -53
  439. ccxt/abstract/bitcoincom.py +0 -115
  440. ccxt/abstract/bitfinex2.py +0 -139
  441. ccxt/abstract/bitpanda.py +0 -35
  442. ccxt/abstract/bl3p.py +0 -19
  443. ccxt/abstract/coinlist.py +0 -54
  444. ccxt/abstract/currencycom.py +0 -68
  445. ccxt/abstract/hitbtc3.py +0 -115
  446. ccxt/abstract/idex.py +0 -26
  447. ccxt/abstract/kuna.py +0 -182
  448. ccxt/abstract/lykke.py +0 -29
  449. ccxt/abstract/poloniexfutures.py +0 -48
  450. ccxt/abstract/wazirx.py +0 -30
  451. ccxt/ace.py +0 -1012
  452. ccxt/async_support/ace.py +0 -1012
  453. ccxt/async_support/base/ws/aiohttp_client.py +0 -125
  454. ccxt/async_support/base/ws/fast_client.py +0 -96
  455. ccxt/async_support/bitbay.py +0 -17
  456. ccxt/async_support/bitcoincom.py +0 -17
  457. ccxt/async_support/bitfinex2.py +0 -3552
  458. ccxt/async_support/bitpanda.py +0 -16
  459. ccxt/async_support/bl3p.py +0 -485
  460. ccxt/async_support/coinlist.py +0 -2243
  461. ccxt/async_support/currencycom.py +0 -1950
  462. ccxt/async_support/hitbtc3.py +0 -16
  463. ccxt/async_support/idex.py +0 -1766
  464. ccxt/async_support/kuna.py +0 -1841
  465. ccxt/async_support/lykke.py +0 -1270
  466. ccxt/async_support/poloniexfutures.py +0 -1717
  467. ccxt/async_support/wazirx.py +0 -1224
  468. ccxt/bitbay.py +0 -17
  469. ccxt/bitcoincom.py +0 -17
  470. ccxt/bitfinex2.py +0 -3552
  471. ccxt/bitpanda.py +0 -16
  472. ccxt/bl3p.py +0 -485
  473. ccxt/coinlist.py +0 -2243
  474. ccxt/currencycom.py +0 -1950
  475. ccxt/hitbtc3.py +0 -16
  476. ccxt/idex.py +0 -1766
  477. ccxt/kuna.py +0 -1841
  478. ccxt/lykke.py +0 -1270
  479. ccxt/poloniexfutures.py +0 -1717
  480. ccxt/pro/bitcoincom.py +0 -34
  481. ccxt/pro/bitfinex2.py +0 -1083
  482. ccxt/pro/bitpanda.py +0 -15
  483. ccxt/pro/currencycom.py +0 -536
  484. ccxt/pro/idex.py +0 -672
  485. ccxt/pro/poloniexfutures.py +0 -990
  486. ccxt/pro/wazirx.py +0 -749
  487. ccxt/test/base/__init__.py +0 -29
  488. ccxt/test/base/test_account.py +0 -26
  489. ccxt/test/base/test_balance.py +0 -56
  490. ccxt/test/base/test_borrow_interest.py +0 -35
  491. ccxt/test/base/test_borrow_rate.py +0 -32
  492. ccxt/test/base/test_calculate_fee.py +0 -51
  493. ccxt/test/base/test_crypto.py +0 -127
  494. ccxt/test/base/test_currency.py +0 -76
  495. ccxt/test/base/test_datetime.py +0 -109
  496. ccxt/test/base/test_decimal_to_precision.py +0 -392
  497. ccxt/test/base/test_deep_extend.py +0 -68
  498. ccxt/test/base/test_deposit_withdrawal.py +0 -50
  499. ccxt/test/base/test_exchange_datetime_functions.py +0 -76
  500. ccxt/test/base/test_funding_rate_history.py +0 -29
  501. ccxt/test/base/test_last_price.py +0 -31
  502. ccxt/test/base/test_ledger_entry.py +0 -45
  503. ccxt/test/base/test_ledger_item.py +0 -48
  504. ccxt/test/base/test_leverage_tier.py +0 -33
  505. ccxt/test/base/test_liquidation.py +0 -50
  506. ccxt/test/base/test_margin_mode.py +0 -24
  507. ccxt/test/base/test_margin_modification.py +0 -35
  508. ccxt/test/base/test_market.py +0 -193
  509. ccxt/test/base/test_number.py +0 -411
  510. ccxt/test/base/test_ohlcv.py +0 -33
  511. ccxt/test/base/test_open_interest.py +0 -32
  512. ccxt/test/base/test_order.py +0 -64
  513. ccxt/test/base/test_order_book.py +0 -69
  514. ccxt/test/base/test_position.py +0 -60
  515. ccxt/test/base/test_shared_methods.py +0 -353
  516. ccxt/test/base/test_status.py +0 -24
  517. ccxt/test/base/test_throttle.py +0 -126
  518. ccxt/test/base/test_ticker.py +0 -92
  519. ccxt/test/base/test_trade.py +0 -47
  520. ccxt/test/base/test_trading_fee.py +0 -26
  521. ccxt/test/base/test_transaction.py +0 -39
  522. ccxt/test/test_async.py +0 -1649
  523. ccxt/test/test_sync.py +0 -1648
  524. ccxt/wazirx.py +0 -1224
  525. ccxt_ir-4.3.46.0.2.dist-info/RECORD +0 -772
  526. /ccxt/abstract/{huobijp.py → bittrade.py} +0 -0
  527. {ccxt_ir-4.3.46.0.2.dist-info → ccxt_ir-4.5.0.dist-info/licenses}/LICENSE.txt +0 -0
  528. {ccxt_ir-4.3.46.0.2.dist-info → ccxt_ir-4.5.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,2572 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
4
+ # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
5
+
6
+ from ccxt.async_support.base.exchange import Exchange
7
+ from ccxt.abstract.derive import ImplicitAPI
8
+ import asyncio
9
+ from ccxt.base.types import Any, Balances, Bool, Currencies, Currency, Int, Market, MarketType, Num, Order, OrderSide, OrderType, Position, Str, Strings, Ticker, FundingRate, Trade, Transaction
10
+ from typing import List
11
+ from ccxt.base.errors import ExchangeError
12
+ from ccxt.base.errors import AuthenticationError
13
+ from ccxt.base.errors import ArgumentsRequired
14
+ from ccxt.base.errors import BadRequest
15
+ from ccxt.base.errors import InsufficientFunds
16
+ from ccxt.base.errors import InvalidOrder
17
+ from ccxt.base.errors import OrderNotFound
18
+ from ccxt.base.errors import RateLimitExceeded
19
+ from ccxt.base.decimal_to_precision import TICK_SIZE
20
+ from ccxt.base.precise import Precise
21
+
22
+
23
+ class derive(Exchange, ImplicitAPI):
24
+
25
+ def describe(self) -> Any:
26
+ return self.deep_extend(super(derive, self).describe(), {
27
+ 'id': 'derive',
28
+ 'name': 'derive',
29
+ 'countries': [],
30
+ 'version': 'v1',
31
+ 'rateLimit': 50,
32
+ 'certified': False,
33
+ 'pro': True,
34
+ 'dex': True,
35
+ 'has': {
36
+ 'CORS': None,
37
+ 'spot': False,
38
+ 'margin': False,
39
+ 'swap': False,
40
+ 'future': False,
41
+ 'option': False,
42
+ 'addMargin': False,
43
+ 'borrowCrossMargin': False,
44
+ 'borrowIsolatedMargin': False,
45
+ 'cancelAllOrders': True,
46
+ 'cancelAllOrdersAfter': False,
47
+ 'cancelOrder': True,
48
+ 'cancelOrders': False,
49
+ 'cancelOrdersForSymbols': False,
50
+ 'closeAllPositions': False,
51
+ 'closePosition': False,
52
+ 'createMarketBuyOrderWithCost': False,
53
+ 'createMarketOrderWithCost': False,
54
+ 'createMarketSellOrderWithCost': False,
55
+ 'createOrder': True,
56
+ 'createOrders': False,
57
+ 'createReduceOnlyOrder': False,
58
+ 'createStopOrder': False,
59
+ 'createTriggerOrder': False,
60
+ 'editOrder': True,
61
+ 'fetchAccounts': False,
62
+ 'fetchBalance': True,
63
+ 'fetchBorrowInterest': False,
64
+ 'fetchBorrowRateHistories': False,
65
+ 'fetchBorrowRateHistory': False,
66
+ 'fetchCanceledAndClosedOrders': False,
67
+ 'fetchCanceledOrders': True,
68
+ 'fetchClosedOrders': True,
69
+ 'fetchCrossBorrowRate': False,
70
+ 'fetchCrossBorrowRates': False,
71
+ 'fetchCurrencies': True,
72
+ 'fetchDepositAddress': False,
73
+ 'fetchDepositAddresses': False,
74
+ 'fetchDeposits': True,
75
+ 'fetchDepositWithdrawFee': 'emulated',
76
+ 'fetchDepositWithdrawFees': False,
77
+ 'fetchFundingHistory': True,
78
+ 'fetchFundingRate': True,
79
+ 'fetchFundingRateHistory': True,
80
+ 'fetchFundingRates': False,
81
+ 'fetchIndexOHLCV': False,
82
+ 'fetchIsolatedBorrowRate': False,
83
+ 'fetchIsolatedBorrowRates': False,
84
+ 'fetchLedger': True,
85
+ 'fetchLeverage': False,
86
+ 'fetchLeverageTiers': False,
87
+ 'fetchLiquidations': False,
88
+ 'fetchMarginMode': None,
89
+ 'fetchMarketLeverageTiers': False,
90
+ 'fetchMarkets': True,
91
+ 'fetchMarkOHLCV': False,
92
+ 'fetchMyLiquidations': False,
93
+ 'fetchMyTrades': True,
94
+ 'fetchOHLCV': False,
95
+ 'fetchOpenInterest': False,
96
+ 'fetchOpenInterestHistory': False,
97
+ 'fetchOpenInterests': False,
98
+ 'fetchOpenOrders': True,
99
+ 'fetchOrder': False,
100
+ 'fetchOrderBook': False,
101
+ 'fetchOrders': True,
102
+ 'fetchOrderTrades': True,
103
+ 'fetchPosition': False,
104
+ 'fetchPositionMode': False,
105
+ 'fetchPositions': True,
106
+ 'fetchPositionsRisk': False,
107
+ 'fetchPremiumIndexOHLCV': False,
108
+ 'fetchTicker': True,
109
+ 'fetchTickers': False,
110
+ 'fetchTime': True,
111
+ 'fetchTrades': True,
112
+ 'fetchTradingFee': False,
113
+ 'fetchTradingFees': False,
114
+ 'fetchTransfer': False,
115
+ 'fetchTransfers': False,
116
+ 'fetchWithdrawal': False,
117
+ 'fetchWithdrawals': True,
118
+ 'reduceMargin': False,
119
+ 'repayCrossMargin': False,
120
+ 'repayIsolatedMargin': False,
121
+ 'sandbox': True,
122
+ 'setLeverage': False,
123
+ 'setMarginMode': False,
124
+ 'setPositionMode': False,
125
+ 'transfer': False,
126
+ 'withdraw': False,
127
+ },
128
+ 'timeframes': {
129
+ '1m': '1m',
130
+ '3m': '3m',
131
+ '5m': '5m',
132
+ '15m': '15m',
133
+ '30m': '30m',
134
+ '1h': '1h',
135
+ '2h': '2h',
136
+ '4h': '4h',
137
+ '8h': '8h',
138
+ '12h': '12h',
139
+ '1d': '1d',
140
+ '3d': '3d',
141
+ '1w': '1w',
142
+ '1M': '1M',
143
+ },
144
+ 'hostname': 'derive.xyz',
145
+ 'urls': {
146
+ 'logo': 'https://github.com/user-attachments/assets/f835b95f-033a-43dd-b6bb-24e698fc498c',
147
+ 'api': {
148
+ 'public': 'https://api.lyra.finance/public',
149
+ 'private': 'https://api.lyra.finance/private',
150
+ },
151
+ 'test': {
152
+ 'public': 'https://api-demo.lyra.finance/public',
153
+ 'private': 'https://api-demo.lyra.finance/private',
154
+ },
155
+ 'www': 'https://www.derive.xyz/',
156
+ 'doc': 'https://docs.derive.xyz/docs/',
157
+ 'fees': 'https://docs.derive.xyz/reference/fees-1/',
158
+ 'referral': 'https://www.derive.xyz/invite/3VB0B',
159
+ },
160
+ 'api': {
161
+ 'public': {
162
+ 'get': [
163
+ 'get_all_currencies',
164
+ ],
165
+ 'post': [
166
+ 'build_register_session_key_tx',
167
+ 'register_session_key',
168
+ 'deregister_session_key',
169
+ 'login',
170
+ 'statistics',
171
+ 'get_all_currencies',
172
+ 'get_currency',
173
+ 'get_instrument',
174
+ 'get_all_instruments',
175
+ 'get_instruments',
176
+ 'get_ticker',
177
+ 'get_latest_signed_feeds',
178
+ 'get_option_settlement_prices',
179
+ 'get_spot_feed_history',
180
+ 'get_spot_feed_history_candles',
181
+ 'get_funding_rate_history',
182
+ 'get_trade_history',
183
+ 'get_option_settlement_history',
184
+ 'get_liquidation_history',
185
+ 'get_interest_rate_history',
186
+ 'get_transaction',
187
+ 'get_margin',
188
+ 'margin_watch',
189
+ 'validate_invite_code',
190
+ 'get_points',
191
+ 'get_all_points',
192
+ 'get_points_leaderboard',
193
+ 'get_descendant_tree',
194
+ 'get_tree_roots',
195
+ 'get_swell_percent_points',
196
+ 'get_vault_assets',
197
+ 'get_etherfi_effective_balances',
198
+ 'get_kelp_effective_balances',
199
+ 'get_bridge_balances',
200
+ 'get_ethena_participants',
201
+ 'get_vault_share',
202
+ 'get_vault_statistics',
203
+ 'get_vault_balances',
204
+ 'estimate_integrator_points',
205
+ 'create_subaccount_debug',
206
+ 'deposit_debug',
207
+ 'withdraw_debug',
208
+ 'send_quote_debug',
209
+ 'execute_quote_debug',
210
+ 'get_invite_code',
211
+ 'register_invite',
212
+ 'get_time',
213
+ 'get_live_incidents',
214
+ 'get_maker_programs',
215
+ 'get_maker_program_scores',
216
+ ],
217
+ },
218
+ 'private': {
219
+ 'post': [
220
+ 'get_account',
221
+ 'create_subaccount',
222
+ 'get_subaccount',
223
+ 'get_subaccounts',
224
+ 'get_all_portfolios',
225
+ 'change_subaccount_label',
226
+ 'get_notificationsv',
227
+ 'update_notifications',
228
+ 'deposit',
229
+ 'withdraw',
230
+ 'transfer_erc20',
231
+ 'transfer_position',
232
+ 'transfer_positions',
233
+ 'order',
234
+ 'replace',
235
+ 'order_debug',
236
+ 'get_order',
237
+ 'get_orders',
238
+ 'get_open_orders',
239
+ 'cancel',
240
+ 'cancel_by_label',
241
+ 'cancel_by_nonce',
242
+ 'cancel_by_instrument',
243
+ 'cancel_all',
244
+ 'cancel_trigger_order',
245
+ 'get_order_history',
246
+ 'get_trade_history',
247
+ 'get_deposit_history',
248
+ 'get_withdrawal_history',
249
+ 'send_rfq',
250
+ 'cancel_rfq',
251
+ 'cancel_batch_rfqs',
252
+ 'get_rfqs',
253
+ 'poll_rfqs',
254
+ 'send_quote',
255
+ 'cancel_quote',
256
+ 'cancel_batch_quotes',
257
+ 'get_quotes',
258
+ 'poll_quotes',
259
+ 'execute_quote',
260
+ 'rfq_get_best_quote',
261
+ 'get_margin',
262
+ 'get_collaterals',
263
+ 'get_positions',
264
+ 'get_option_settlement_history',
265
+ 'get_subaccount_value_history',
266
+ 'expired_and_cancelled_history',
267
+ 'get_funding_history',
268
+ 'get_interest_history',
269
+ 'get_erc20_transfer_history',
270
+ 'get_liquidation_history',
271
+ 'liquidate',
272
+ 'get_liquidator_history',
273
+ 'session_keys',
274
+ 'edit_session_key',
275
+ 'register_scoped_session_key',
276
+ 'get_mmp_config',
277
+ 'set_mmp_config',
278
+ 'reset_mmp',
279
+ 'set_cancel_on_disconnect',
280
+ 'get_invite_code',
281
+ 'register_invite',
282
+ ],
283
+ },
284
+ },
285
+ 'fees': {
286
+ },
287
+ 'requiredCredentials': {
288
+ 'apiKey': False,
289
+ 'secret': False,
290
+ 'walletAddress': True,
291
+ 'privateKey': True,
292
+ },
293
+ 'exceptions': {
294
+ 'exact': {
295
+ '-32000': RateLimitExceeded, # Rate limit exceeded
296
+ '-32100': RateLimitExceeded, # Number of concurrent websocket clients limit exceeded
297
+ '-32700': BadRequest, # Parse error
298
+ '-32600': BadRequest, # Invalid Request
299
+ '-32601': BadRequest, # Method not found
300
+ '-32602': InvalidOrder, # {"id":"55e66a3d-6a4e-4a36-a23d-5cf8a91ef478","error":{"code":"","message":"Invalid params"}}
301
+ '-32603': InvalidOrder, # {"code":"-32603","message":"Internal error","data":"SubAccount matching query does not exist."}
302
+ '9000': InvalidOrder, # Order confirmation timeout
303
+ '10000': BadRequest, # Manager not found
304
+ '10001': BadRequest, # Asset is not an ERC20 token
305
+ '10002': BadRequest, # Sender and recipient wallet do not match
306
+ '10003': BadRequest, # Sender and recipient subaccount IDs are the same
307
+ '10004': InvalidOrder, # Multiple currencies not supported
308
+ '10005': BadRequest, # Maximum number of subaccounts per wallet reached
309
+ '10006': BadRequest, # Maximum number of session keys per wallet reached
310
+ '10007': BadRequest, # Maximum number of assets per subaccount reached
311
+ '10008': BadRequest, # Maximum number of expiries per subaccount reached
312
+ '10009': BadRequest, # Recipient subaccount ID of the transfer cannot be 0
313
+ '10010': InvalidOrder, # PMRM only supports USDC asset collateral. Cannot trade spot markets.
314
+ '10011': InsufficientFunds, # ERC20 allowance is insufficient
315
+ '10012': InsufficientFunds, # ERC20 balance is less than transfer amount
316
+ '10013': ExchangeError, # There is a pending deposit for self asset
317
+ '10014': ExchangeError, # There is a pending withdrawal for self asset
318
+ '11000': InsufficientFunds, # Insufficient funds
319
+ '11002': InvalidOrder, # Order rejected from queue
320
+ '11003': InvalidOrder, # Already cancelled
321
+ '11004': InvalidOrder, # Already filled
322
+ '11005': InvalidOrder, # Already expired
323
+ '11006': OrderNotFound, # {"code":"11006","message":"Does not exist","data":"Open order with id: 804018f3-b092-40a3-a933-b29574fa1ff8 does not exist."}
324
+ '11007': InvalidOrder, # Self-crossing disallowed
325
+ '11008': InvalidOrder, # Post-only reject
326
+ '11009': InvalidOrder, # Zero liquidity for market or IOC/FOK order
327
+ '11010': InvalidOrder, # Post-only invalid order type
328
+ '11011': InvalidOrder, # {"code":11011,"message":"Invalid signature expiry","data":"Order must expire in 300 sec or more"}
329
+ '11012': InvalidOrder, # {"code":"11012","message":"Invalid amount","data":"Amount must be a multiple of 0.01"}
330
+ '11013': InvalidOrder, # {"code":"11013","message":"Invalid limit price","data":{"limit":"10000","bandwidth":"92530"}}
331
+ '11014': InvalidOrder, # Fill-or-kill not filled
332
+ '11015': InvalidOrder, # MMP frozen
333
+ '11016': InvalidOrder, # Already consumed
334
+ '11017': InvalidOrder, # Non unique nonce
335
+ '11018': InvalidOrder, # Invalid nonce date
336
+ '11019': InvalidOrder, # Open orders limit exceeded
337
+ '11020': InsufficientFunds, # Negative ERC20 balance
338
+ '11021': InvalidOrder, # Instrument is not live
339
+ '11022': InvalidOrder, # Reject timestamp exceeded
340
+ '11023': InvalidOrder, # {"code":"11023","message":"Max fee order param is too low","data":"signed max_fee must be >= 194.420835871999983091712000000000000000"}
341
+ '11024': InvalidOrder, # {"code":11024,"message":"Reduce only not supported with self time in force"}
342
+ '11025': InvalidOrder, # Reduce only reject
343
+ '11026': BadRequest, # Transfer reject
344
+ '11027': InvalidOrder, # Subaccount undergoing liquidation
345
+ '11028': InvalidOrder, # Replaced order filled amount does not match expected state.
346
+ '11050': InvalidOrder, # Trigger order was cancelled between the time worker sent order and engine processed order
347
+ '11051': InvalidOrder, # {"code":"11051","message":"Trigger price must be higher than the current price for stop orders and vice versa for take orders","data":"Trigger price 9000.0 must be < or > current price 102671.2 depending on trigger type and direction."}
348
+ '11052': InvalidOrder, # Trigger order limit exceeded(separate limit from regular orders)
349
+ '11053': InvalidOrder, # Index and last-trade trigger price types not supported yet
350
+ '11054': InvalidOrder, # {"code":"11054","message":"Trigger orders cannot replace or be replaced"}
351
+ '11055': InvalidOrder, # Market order limit_price is unfillable at the given trigger price
352
+ '11100': InvalidOrder, # Leg instruments are not unique
353
+ '11101': InvalidOrder, # RFQ not found
354
+ '11102': InvalidOrder, # Quote not found
355
+ '11103': InvalidOrder, # Quote leg does not match RFQ leg
356
+ '11104': InvalidOrder, # Requested quote or RFQ is not open
357
+ '11105': InvalidOrder, # Requested quote ID references a different RFQ ID
358
+ '11106': InvalidOrder, # Invalid RFQ counterparty
359
+ '11107': InvalidOrder, # Quote maker total cost too high
360
+ '11200': InvalidOrder, # Auction not ongoing
361
+ '11201': InvalidOrder, # Open orders not allowed
362
+ '11202': InvalidOrder, # Price limit exceeded
363
+ '11203': InvalidOrder, # Last trade ID mismatch
364
+ '12000': InvalidOrder, # Asset not found
365
+ '12001': InvalidOrder, # Instrument not found
366
+ '12002': BadRequest, # Currency not found
367
+ '12003': BadRequest, # USDC does not have asset caps per manager
368
+ '13000': BadRequest, # Invalid channels
369
+ '14000': BadRequest, # {"code": 14000, "message": "Account not found"}
370
+ '14001': InvalidOrder, # {"code": 14001, "message": "Subaccount not found"}
371
+ '14002': BadRequest, # Subaccount was withdrawn
372
+ '14008': BadRequest, # Cannot reduce expiry using registerSessionKey RPC route
373
+ '14009': BadRequest, # Session key expiry must be > utc_now + 10 min
374
+ '14010': BadRequest, # Session key already registered for self account
375
+ '14011': BadRequest, # Session key already registered with another account
376
+ '14012': BadRequest, # Address must be checksummed
377
+ '14013': BadRequest, # str is not a valid ethereum address
378
+ '14014': InvalidOrder, # {"code":"14014","message":"Signature invalid for message or transaction","data":"Signature does not match data"}
379
+ '14015': BadRequest, # Transaction count for given wallet does not match provided nonce
380
+ '14016': BadRequest, # The provided signed raw transaction contains function name that does not match the expected function name
381
+ '14017': BadRequest, # The provided signed raw transaction contains contract address that does not match the expected contract address
382
+ '14018': BadRequest, # The provided signed raw transaction contains function params that do not match any expected function params
383
+ '14019': BadRequest, # The provided signed raw transaction contains function param values that do not match the expected values
384
+ '14020': BadRequest, # The X-LyraWallet header does not match the requested subaccount_id or wallet
385
+ '14021': BadRequest, # The X-LyraWallet header not provided
386
+ '14022': AuthenticationError, # Subscription to a private channel failed
387
+ '14023': InvalidOrder, # {"code":"14023","message":"Signer in on-chain related request is not wallet owner or registered session key","data":"Session key does not belong to wallet"}
388
+ '14024': BadRequest, # Chain ID must match the current roll up chain id
389
+ '14025': BadRequest, # The private request is missing a wallet or subaccount_id param
390
+ '14026': BadRequest, # Session key not found
391
+ '14027': AuthenticationError, # Unauthorized maker
392
+ '14028': BadRequest, # Cross currency RFQ not supported
393
+ '14029': AuthenticationError, # Session key IP not whitelisted
394
+ '14030': BadRequest, # Session key expired
395
+ '14031': AuthenticationError, # Unauthorized key scope
396
+ '14032': BadRequest, # Scope should not be changed
397
+ '16000': AuthenticationError, # You are in a restricted region that violates our terms of service.
398
+ '16001': AuthenticationError, # Account is disabled due to compliance violations, please contact support to enable it.
399
+ '16100': AuthenticationError, # Sentinel authorization is invalid
400
+ '17000': BadRequest, # This accoount does not have a shareable invite code
401
+ '17001': BadRequest, # Invalid invite code
402
+ '17002': BadRequest, # Invite code already registered for self account
403
+ '17003': BadRequest, # Invite code has no remaining uses
404
+ '17004': BadRequest, # Requirement for successful invite registration not met
405
+ '17005': BadRequest, # Account must register with a valid invite code to be elligible for points
406
+ '17006': BadRequest, # Point program does not exist
407
+ '17007': BadRequest, # Invalid leaderboard page number
408
+ '18000': BadRequest, # Invalid block number
409
+ '18001': BadRequest, # Failed to estimate block number. Please try again later.
410
+ '18002': BadRequest, # The provided smart contract owner does not match the wallet in LightAccountFactory.getAddress()
411
+ '18003': BadRequest, # Vault ERC20 asset does not exist
412
+ '18004': BadRequest, # Vault ERC20 pool does not exist
413
+ '18005': BadRequest, # Must add asset to pool before getting balances
414
+ '18006': BadRequest, # Invalid Swell season. Swell seasons are in the form 'swell_season_X'.
415
+ '18007': BadRequest, # Vault not found
416
+ '19000': BadRequest, # Maker program not found
417
+ },
418
+ 'broad': {
419
+ },
420
+ },
421
+ 'precisionMode': TICK_SIZE,
422
+ 'commonCurrencies': {
423
+ },
424
+ 'options': {
425
+ 'deriveWalletAddress': '', # a derive wallet address "0x"-prefixed hexstring
426
+ 'id': '0x0ad42b8e602c2d3d475ae52d678cf63d84ab2749',
427
+ },
428
+ })
429
+
430
+ def set_sandbox_mode(self, enable: bool):
431
+ super(derive, self).set_sandbox_mode(enable)
432
+ self.options['sandboxMode'] = enable
433
+
434
+ async def fetch_time(self, params={}):
435
+ """
436
+ fetches the current integer timestamp in milliseconds from the exchange server
437
+
438
+ https://docs.derive.xyz/reference/post_public-get-time
439
+
440
+ :param dict [params]: extra parameters specific to the exchange API endpoint
441
+ :returns int: the current integer timestamp in milliseconds from the exchange server
442
+ """
443
+ response = await self.publicPostGetTime(params)
444
+ #
445
+ # {
446
+ # "result": 1735846536758,
447
+ # "id": "f1c03d21-f886-4c5a-9a9d-33dd06f180f0"
448
+ # }
449
+ #
450
+ return self.safe_integer(response, 'result')
451
+
452
+ async def fetch_currencies(self, params={}) -> Currencies:
453
+ """
454
+ fetches all available currencies on an exchange
455
+
456
+ https://docs.derive.xyz/reference/post_public-get-all-currencies
457
+
458
+ :param dict [params]: extra parameters specific to the exchange API endpoint
459
+ :returns dict: an associative dictionary of currencies
460
+ """
461
+ result: dict = {}
462
+ tokenResponse = await self.publicGetGetAllCurrencies(params)
463
+ #
464
+ # {
465
+ # "result": [
466
+ # {
467
+ # "currency": "SEI",
468
+ # "instrument_types": [
469
+ # "perp"
470
+ # ],
471
+ # "protocol_asset_addresses": {
472
+ # "perp": "0x7225889B75fd34C68eA3098dAE04D50553C09840",
473
+ # "option": null,
474
+ # "spot": null,
475
+ # "underlying_erc20": null
476
+ # },
477
+ # "managers": [
478
+ # {
479
+ # "address": "0x28c9ddF9A3B29c2E6a561c1BC520954e5A33de5D",
480
+ # "margin_type": "SM",
481
+ # "currency": null
482
+ # }
483
+ # ],
484
+ # "srm_im_discount": "0",
485
+ # "srm_mm_discount": "0",
486
+ # "pm2_collateral_discounts": [],
487
+ # "borrow_apy": "0",
488
+ # "supply_apy": "0",
489
+ # "total_borrow": "0",
490
+ # "total_supply": "0",
491
+ # "asset_cap_and_supply_per_manager": {
492
+ # "perp": {
493
+ # "SM": [
494
+ # {
495
+ # "current_open_interest": "0",
496
+ # "interest_cap": "2000000",
497
+ # "manager_currency": null
498
+ # }
499
+ # ]
500
+ # },
501
+ # "option": {},
502
+ # "erc20": {}
503
+ # },
504
+ # "market_type": "SRM_PERP_ONLY",
505
+ # "spot_price": "0.2193542905042081",
506
+ # "spot_price_24h": "0.238381655533635830"
507
+ # },
508
+ # "id": "7e07fe1d-0ab4-4d2b-9e22-b65ce9e232dc"
509
+ # }
510
+ #
511
+ currencies = self.safe_list(tokenResponse, 'result', [])
512
+ for i in range(0, len(currencies)):
513
+ currency = currencies[i]
514
+ currencyId = self.safe_string(currency, 'currency')
515
+ code = self.safe_currency_code(currencyId)
516
+ result[code] = self.safe_currency_structure({
517
+ 'id': currencyId,
518
+ 'name': None,
519
+ 'code': code,
520
+ 'precision': None,
521
+ 'active': None,
522
+ 'fee': None,
523
+ 'networks': None,
524
+ 'deposit': None,
525
+ 'withdraw': None,
526
+ 'limits': {
527
+ 'deposit': {
528
+ 'min': None,
529
+ 'max': None,
530
+ },
531
+ 'withdraw': {
532
+ 'min': None,
533
+ 'max': None,
534
+ },
535
+ },
536
+ 'info': currency,
537
+ })
538
+ return result
539
+
540
+ async def fetch_markets(self, params={}) -> List[Market]:
541
+ """
542
+ retrieves data on all markets for bybit
543
+
544
+ https://docs.derive.xyz/reference/post_public-get-all-instruments
545
+
546
+ :param dict [params]: extra parameters specific to the exchange API endpoint
547
+ :returns dict[]: an array of objects representing market data
548
+ """
549
+ spotMarketsPromise = self.fetch_spot_markets(params)
550
+ swapMarketsPromise = self.fetch_swap_markets(params)
551
+ optionMarketsPromise = self.fetch_option_markets(params)
552
+ spotMarkets, swapMarkets, optionMarkets = await asyncio.gather(*[spotMarketsPromise, swapMarketsPromise, optionMarketsPromise])
553
+ #
554
+ # {
555
+ # "result": {
556
+ # "instruments": [
557
+ # {
558
+ # "instrument_type": "perp",
559
+ # "instrument_name": "BTC-PERP",
560
+ # "scheduled_activation": 1701840228,
561
+ # "scheduled_deactivation": 9223372036854776000,
562
+ # "is_active": True,
563
+ # "tick_size": "0.1",
564
+ # "minimum_amount": "0.01",
565
+ # "maximum_amount": "10000",
566
+ # "amount_step": "0.001",
567
+ # "mark_price_fee_rate_cap": "0",
568
+ # "maker_fee_rate": "0.00005",
569
+ # "taker_fee_rate": "0.0003",
570
+ # "base_fee": "0.1",
571
+ # "base_currency": "BTC",
572
+ # "quote_currency": "USD",
573
+ # "option_details": null,
574
+ # "perp_details": {
575
+ # "index": "BTC-USD",
576
+ # "max_rate_per_hour": "0.004",
577
+ # "min_rate_per_hour": "-0.004",
578
+ # "static_interest_rate": "0.0000125",
579
+ # "aggregate_funding": "10538.574363381759146829",
580
+ # "funding_rate": "0.0000125"
581
+ # },
582
+ # "erc20_details": null,
583
+ # "base_asset_address": "0xDBa83C0C654DB1cd914FA2710bA743e925B53086",
584
+ # "base_asset_sub_id": "0",
585
+ # "pro_rata_fraction": "0",
586
+ # "fifo_min_allocation": "0",
587
+ # "pro_rata_amount_step": "0.1"
588
+ # }
589
+ # ],
590
+ # "pagination": {
591
+ # "num_pages": 1,
592
+ # "count": 1
593
+ # }
594
+ # },
595
+ # "id": "a06bc0b2-8e78-4536-a21f-f785f225b5a5"
596
+ # }
597
+ #
598
+ result = self.array_concat(spotMarkets, swapMarkets)
599
+ result = self.array_concat(result, optionMarkets)
600
+ return result
601
+
602
+ async def fetch_spot_markets(self, params={}) -> List[Market]:
603
+ request: dict = {
604
+ 'expired': False,
605
+ 'instrument_type': 'erc20',
606
+ }
607
+ response = await self.publicPostGetAllInstruments(self.extend(request, params))
608
+ result = self.safe_dict(response, 'result', {})
609
+ data = self.safe_list(result, 'instruments', [])
610
+ return self.parse_markets(data)
611
+
612
+ async def fetch_swap_markets(self, params={}) -> List[Market]:
613
+ request: dict = {
614
+ 'expired': False,
615
+ 'instrument_type': 'perp',
616
+ }
617
+ response = await self.publicPostGetAllInstruments(self.extend(request, params))
618
+ result = self.safe_dict(response, 'result', {})
619
+ data = self.safe_list(result, 'instruments', [])
620
+ return self.parse_markets(data)
621
+
622
+ async def fetch_option_markets(self, params={}) -> List[Market]:
623
+ request: dict = {
624
+ 'expired': False,
625
+ 'instrument_type': 'option',
626
+ }
627
+ response = await self.publicPostGetAllInstruments(self.extend(request, params))
628
+ result = self.safe_dict(response, 'result', {})
629
+ data = self.safe_list(result, 'instruments', [])
630
+ return self.parse_markets(data)
631
+
632
+ def parse_market(self, market: dict) -> Market:
633
+ type = self.safe_string(market, 'instrument_type')
634
+ marketType: MarketType
635
+ spot = False
636
+ margin = True
637
+ swap = False
638
+ option = False
639
+ linear: Bool = None
640
+ inverse: Bool = None
641
+ baseId = self.safe_string(market, 'base_currency')
642
+ quoteId = self.safe_string(market, 'quote_currency')
643
+ base = self.safe_currency_code(baseId)
644
+ quote = self.safe_currency_code(quoteId)
645
+ marketId = self.safe_string(market, 'instrument_name')
646
+ symbol = base + '/' + quote
647
+ settleId: Str = None
648
+ settle: Str = None
649
+ expiry: Num = None
650
+ strike: Num = None
651
+ optionType: Str = None
652
+ optionLetter: Str = None
653
+ if type == 'erc20':
654
+ spot = True
655
+ marketType = 'spot'
656
+ elif type == 'perp':
657
+ margin = False
658
+ settleId = 'USDC'
659
+ settle = self.safe_currency_code(settleId)
660
+ symbol = base + '/' + quote + ':' + settle
661
+ swap = True
662
+ linear = True
663
+ inverse = False
664
+ marketType = 'swap'
665
+ elif type == 'option':
666
+ settleId = 'USDC'
667
+ settle = self.safe_currency_code(settleId)
668
+ margin = False
669
+ option = True
670
+ marketType = 'option'
671
+ optionDetails = self.safe_dict(market, 'option_details')
672
+ expiry = self.safe_timestamp(optionDetails, 'expiry')
673
+ strike = self.safe_integer(optionDetails, 'strike')
674
+ optionLetter = self.safe_string(optionDetails, 'option_type')
675
+ symbol = base + '/' + quote + ':' + settle + '-' + self.yymmdd(expiry) + '-' + self.number_to_string(strike) + '-' + optionLetter
676
+ if optionLetter == 'P':
677
+ optionType = 'put'
678
+ else:
679
+ optionType = 'call'
680
+ linear = True
681
+ inverse = False
682
+ return self.safe_market_structure({
683
+ 'id': marketId,
684
+ 'symbol': symbol,
685
+ 'base': base,
686
+ 'quote': quote,
687
+ 'settle': settle,
688
+ 'baseId': baseId,
689
+ 'quoteId': quoteId,
690
+ 'settleId': settleId,
691
+ 'type': marketType,
692
+ 'spot': spot,
693
+ 'margin': margin,
694
+ 'swap': swap,
695
+ 'future': False,
696
+ 'option': option,
697
+ 'active': self.safe_bool(market, 'is_active'),
698
+ 'contract': (swap or option),
699
+ 'linear': linear,
700
+ 'inverse': inverse,
701
+ 'contractSize': None if (spot) else 1,
702
+ 'expiry': expiry,
703
+ 'expiryDatetime': self.iso8601(expiry),
704
+ 'taker': self.safe_number(market, 'taker_fee_rate'),
705
+ 'maker': self.safe_number(market, 'maker_fee_rate'),
706
+ 'strike': strike,
707
+ 'optionType': optionType,
708
+ 'precision': {
709
+ 'amount': self.safe_number(market, 'amount_step'),
710
+ 'price': self.safe_number(market, 'tick_size'),
711
+ },
712
+ 'limits': {
713
+ 'leverage': {
714
+ 'min': None,
715
+ 'max': None,
716
+ },
717
+ 'amount': {
718
+ 'min': self.safe_number(market, 'minimum_amount'),
719
+ 'max': self.safe_number(market, 'maximum_amount'),
720
+ },
721
+ 'price': {
722
+ 'min': None,
723
+ 'max': None,
724
+ },
725
+ 'cost': {
726
+ 'min': None,
727
+ 'max': None,
728
+ },
729
+ },
730
+ 'created': None,
731
+ 'info': market,
732
+ })
733
+
734
+ async def fetch_ticker(self, symbol: str, params={}) -> Ticker:
735
+ """
736
+ fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
737
+
738
+ https://docs.derive.xyz/reference/post_public-get-ticker
739
+
740
+ :param str symbol: unified symbol of the market to fetch the ticker for
741
+ :param dict [params]: extra parameters specific to the exchange API endpoint
742
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
743
+ """
744
+ await self.load_markets()
745
+ market = self.market(symbol)
746
+ request: dict = {
747
+ 'instrument_name': market['id'],
748
+ }
749
+ response = await self.publicPostGetTicker(self.extend(request, params))
750
+ #
751
+ # spot
752
+ #
753
+ # {
754
+ # "result": {
755
+ # "instrument_type": "perp",
756
+ # "instrument_name": "BTC-PERP",
757
+ # "scheduled_activation": 1701840228,
758
+ # "scheduled_deactivation": 9223372036854776000,
759
+ # "is_active": True,
760
+ # "tick_size": "0.1",
761
+ # "minimum_amount": "0.01",
762
+ # "maximum_amount": "10000",
763
+ # "amount_step": "0.001",
764
+ # "mark_price_fee_rate_cap": "0",
765
+ # "maker_fee_rate": "0.00005",
766
+ # "taker_fee_rate": "0.0003",
767
+ # "base_fee": "0.1",
768
+ # "base_currency": "BTC",
769
+ # "quote_currency": "USD",
770
+ # "option_details": null,
771
+ # "perp_details": {
772
+ # "index": "BTC-USD",
773
+ # "max_rate_per_hour": "0.004",
774
+ # "min_rate_per_hour": "-0.004",
775
+ # "static_interest_rate": "0.0000125",
776
+ # "aggregate_funding": "10512.580833189805742522",
777
+ # "funding_rate": "-0.000022223906766867"
778
+ # },
779
+ # "erc20_details": null,
780
+ # "base_asset_address": "0xDBa83C0C654DB1cd914FA2710bA743e925B53086",
781
+ # "base_asset_sub_id": "0",
782
+ # "pro_rata_fraction": "0",
783
+ # "fifo_min_allocation": "0",
784
+ # "pro_rata_amount_step": "0.1",
785
+ # "best_ask_amount": "0.012",
786
+ # "best_ask_price": "99567.9",
787
+ # "best_bid_amount": "0.129",
788
+ # "best_bid_price": "99554.5",
789
+ # "five_percent_bid_depth": "11.208",
790
+ # "five_percent_ask_depth": "11.42",
791
+ # "option_pricing": null,
792
+ # "index_price": "99577.2",
793
+ # "mark_price": "99543.642926357933902181684970855712890625",
794
+ # "stats": {
795
+ # "contract_volume": "464.712",
796
+ # "num_trades": "10681",
797
+ # "open_interest": "72.804739389481989861",
798
+ # "high": "99519.1",
799
+ # "low": "97254.1",
800
+ # "percent_change": "0.0128",
801
+ # "usd_change": "1258.1"
802
+ # },
803
+ # "timestamp": 1736140984000,
804
+ # "min_price": "97591.2",
805
+ # "max_price": "101535.1"
806
+ # },
807
+ # "id": "bbd7c271-c2be-48f7-b93a-26cf6d4cb79f"
808
+ # }
809
+ #
810
+ data = self.safe_dict(response, 'result', {})
811
+ return self.parse_ticker(data, market)
812
+
813
+ def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
814
+ #
815
+ # {
816
+ # "instrument_type": "perp",
817
+ # "instrument_name": "BTC-PERP",
818
+ # "scheduled_activation": 1701840228,
819
+ # "scheduled_deactivation": 9223372036854776000,
820
+ # "is_active": True,
821
+ # "tick_size": "0.1",
822
+ # "minimum_amount": "0.01",
823
+ # "maximum_amount": "10000",
824
+ # "amount_step": "0.001",
825
+ # "mark_price_fee_rate_cap": "0",
826
+ # "maker_fee_rate": "0.00005",
827
+ # "taker_fee_rate": "0.0003",
828
+ # "base_fee": "0.1",
829
+ # "base_currency": "BTC",
830
+ # "quote_currency": "USD",
831
+ # "option_details": null,
832
+ # "perp_details": {
833
+ # "index": "BTC-USD",
834
+ # "max_rate_per_hour": "0.004",
835
+ # "min_rate_per_hour": "-0.004",
836
+ # "static_interest_rate": "0.0000125",
837
+ # "aggregate_funding": "10512.580833189805742522",
838
+ # "funding_rate": "-0.000022223906766867"
839
+ # },
840
+ # "erc20_details": null,
841
+ # "base_asset_address": "0xDBa83C0C654DB1cd914FA2710bA743e925B53086",
842
+ # "base_asset_sub_id": "0",
843
+ # "pro_rata_fraction": "0",
844
+ # "fifo_min_allocation": "0",
845
+ # "pro_rata_amount_step": "0.1",
846
+ # "best_ask_amount": "0.012",
847
+ # "best_ask_price": "99567.9",
848
+ # "best_bid_amount": "0.129",
849
+ # "best_bid_price": "99554.5",
850
+ # "five_percent_bid_depth": "11.208",
851
+ # "five_percent_ask_depth": "11.42",
852
+ # "option_pricing": null,
853
+ # "index_price": "99577.2",
854
+ # "mark_price": "99543.642926357933902181684970855712890625",
855
+ # "stats": {
856
+ # "contract_volume": "464.712",
857
+ # "num_trades": "10681",
858
+ # "open_interest": "72.804739389481989861",
859
+ # "high": "99519.1",
860
+ # "low": "97254.1",
861
+ # "percent_change": "0.0128",
862
+ # "usd_change": "1258.1"
863
+ # },
864
+ # "timestamp": 1736140984000,
865
+ # "min_price": "97591.2",
866
+ # "max_price": "101535.1"
867
+ # }
868
+ #
869
+ marketId = self.safe_string(ticker, 'instrument_name')
870
+ timestamp = self.safe_integer_omit_zero(ticker, 'timestamp')
871
+ symbol = self.safe_symbol(marketId, market)
872
+ stats = self.safe_dict(ticker, 'stats')
873
+ change = self.safe_string(stats, 'percent_change')
874
+ return self.safe_ticker({
875
+ 'symbol': symbol,
876
+ 'timestamp': timestamp,
877
+ 'datetime': self.iso8601(timestamp),
878
+ 'high': self.safe_string(stats, 'high'),
879
+ 'low': self.safe_string(stats, 'low'),
880
+ 'bid': self.safe_string(ticker, 'best_bid_price'),
881
+ 'bidVolume': self.safe_string(ticker, 'best_bid_amount'),
882
+ 'ask': self.safe_string(ticker, 'best_ask_price'),
883
+ 'askVolume': self.safe_string(ticker, 'best_ask_amount'),
884
+ 'vwap': None,
885
+ 'open': None,
886
+ 'close': None,
887
+ 'last': None,
888
+ 'previousClose': None,
889
+ 'change': change,
890
+ 'percentage': Precise.string_mul(change, '100'),
891
+ 'average': None,
892
+ 'baseVolume': None,
893
+ 'quoteVolume': None,
894
+ 'indexPrice': self.safe_string(ticker, 'index_price'),
895
+ 'markPrice': self.safe_string(ticker, 'mark_price'),
896
+ 'info': ticker,
897
+ }, market)
898
+
899
+ async def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
900
+ """
901
+ get the list of most recent trades for a particular symbol
902
+
903
+ https://docs.derive.xyz/reference/post_public-get-trade-history
904
+
905
+ :param str symbol: unified symbol of the market to fetch trades for
906
+ :param int [since]: timestamp in ms of the earliest trade to fetch
907
+ :param int [limit]: the maximum amount of trades to fetch
908
+ :param dict [params]: extra parameters specific to the exchange API endpoint
909
+ :param int [params.until]: the latest time in ms to fetch trades for
910
+ :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
911
+ """
912
+ await self.load_markets()
913
+ request: dict = {}
914
+ market = None
915
+ if symbol is not None:
916
+ market = self.market(symbol)
917
+ request['instrument_name'] = market['id']
918
+ if limit is not None:
919
+ if limit > 1000:
920
+ limit = 1000
921
+ request['page_size'] = limit # default 100, max 1000
922
+ if since is not None:
923
+ request['from_timestamp'] = since
924
+ until = self.safe_integer(params, 'until')
925
+ params = self.omit(params, ['until'])
926
+ if until is not None:
927
+ request['to_timestamp'] = until
928
+ response = await self.publicPostGetTradeHistory(self.extend(request, params))
929
+ #
930
+ # {
931
+ # "result": {
932
+ # "trades": [
933
+ # {
934
+ # "trade_id": "9dbc88b0-f0c4-4439-9cc1-4e6409d4eafb",
935
+ # "instrument_name": "BTC-PERP",
936
+ # "timestamp": 1736153910930,
937
+ # "trade_price": "98995.3",
938
+ # "trade_amount": "0.033",
939
+ # "mark_price": "98990.875914388161618263",
940
+ # "index_price": "99038.050611100001501184",
941
+ # "direction": "sell",
942
+ # "quote_id": null,
943
+ # "wallet": "0x88B6BB87fbFac92a34F8155aaA35c87B5b166fA9",
944
+ # "subaccount_id": 8250,
945
+ # "tx_status": "settled",
946
+ # "tx_hash": "0x020bd735b312f867f17f8cc254946d87cfe9f2c8ff3605035d8129082eb73723",
947
+ # "trade_fee": "0.980476701049890015",
948
+ # "liquidity_role": "taker",
949
+ # "realized_pnl": "-2.92952402688793509",
950
+ # "realized_pnl_excl_fees": "-1.949047325838045075"
951
+ # }
952
+ # ],
953
+ # "pagination": {
954
+ # "num_pages": 598196,
955
+ # "count": 598196
956
+ # }
957
+ # },
958
+ # "id": "b8539544-6975-4497-8163-5e51a38e4aa7"
959
+ # }
960
+ #
961
+ result = self.safe_dict(response, 'result', {})
962
+ data = self.safe_list(result, 'trades', [])
963
+ return self.parse_trades(data, market, since, limit)
964
+
965
+ def parse_trade(self, trade: dict, market: Market = None) -> Trade:
966
+ #
967
+ # {
968
+ # "subaccount_id": 130837,
969
+ # "order_id": "30c48194-8d48-43ac-ad00-0d5ba29eddc9",
970
+ # "instrument_name": "BTC-PERP",
971
+ # "direction": "sell",
972
+ # "label": "test1234",
973
+ # "quote_id": null,
974
+ # "trade_id": "f8a30740-488c-4c2d-905d-e17057bafde1",
975
+ # "timestamp": 1738065303708,
976
+ # "mark_price": "102740.137375457314192317",
977
+ # "index_price": "102741.553409299981533184",
978
+ # "trade_price": "102700.6",
979
+ # "trade_amount": "0.01",
980
+ # "liquidity_role": "taker",
981
+ # "realized_pnl": "0",
982
+ # "realized_pnl_excl_fees": "0",
983
+ # "is_transfer": False,
984
+ # "tx_status": "settled",
985
+ # "trade_fee": "1.127415534092999815",
986
+ # "tx_hash": "0xc55df1f07330faf86579bd8a6385391fbe9e73089301149d8550e9d29c9ead74",
987
+ # "transaction_id": "e18b9426-3fa5-41bb-99d3-8b54fb4d51bb"
988
+ # }
989
+ #
990
+ marketId = self.safe_string(trade, 'instrument_name')
991
+ symbol = self.safe_symbol(marketId, market)
992
+ timestamp = self.safe_integer(trade, 'timestamp')
993
+ fee = {
994
+ 'currency': 'USDC',
995
+ 'cost': self.safe_string(trade, 'trade_fee'),
996
+ }
997
+ return self.safe_trade({
998
+ 'info': trade,
999
+ 'id': self.safe_string(trade, 'trade_id'),
1000
+ 'order': self.safe_string(trade, 'order_id'),
1001
+ 'symbol': symbol,
1002
+ 'side': self.safe_string_lower(trade, 'direction'),
1003
+ 'type': None,
1004
+ 'takerOrMaker': self.safe_string(trade, 'liquidity_role'),
1005
+ 'price': self.safe_string(trade, 'trade_price'),
1006
+ 'amount': self.safe_string(trade, 'trade_amount'),
1007
+ 'cost': None,
1008
+ 'timestamp': timestamp,
1009
+ 'datetime': self.iso8601(timestamp),
1010
+ 'fee': fee,
1011
+ }, market)
1012
+
1013
+ async def fetch_funding_rate_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1014
+ """
1015
+ fetches historical funding rate prices
1016
+
1017
+ https://docs.derive.xyz/reference/post_public-get-funding-rate-history
1018
+
1019
+ :param str symbol: unified symbol of the market to fetch the funding rate history for
1020
+ :param int [since]: timestamp in ms of the earliest funding rate to fetch
1021
+ :param int [limit]: the maximum amount of funding rate structures to fetch
1022
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1023
+ :returns dict[]: a list of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-history-structure>`
1024
+ """
1025
+ await self.load_markets()
1026
+ market = self.market(symbol)
1027
+ request: dict = {
1028
+ 'instrument_name': market['id'],
1029
+ }
1030
+ if since is not None:
1031
+ request['start_timestamp'] = since
1032
+ until = self.safe_integer(params, 'until')
1033
+ params = self.omit(params, ['until'])
1034
+ if until is not None:
1035
+ request['to_timestamp'] = until
1036
+ response = await self.publicPostGetFundingRateHistory(self.extend(request, params))
1037
+ #
1038
+ # {
1039
+ # "result": {
1040
+ # "funding_rate_history": [
1041
+ # {
1042
+ # "timestamp": 1736215200000,
1043
+ # "funding_rate": "-0.000020014"
1044
+ # }
1045
+ # ]
1046
+ # },
1047
+ # "id": "3200ab8d-0080-42f0-8517-c13e3d9201d8"
1048
+ # }
1049
+ #
1050
+ result = self.safe_dict(response, 'result', {})
1051
+ data = self.safe_list(result, 'funding_rate_history', [])
1052
+ rates = []
1053
+ for i in range(0, len(data)):
1054
+ entry = data[i]
1055
+ timestamp = self.safe_integer(entry, 'timestamp')
1056
+ rates.append({
1057
+ 'info': entry,
1058
+ 'symbol': market['symbol'],
1059
+ 'fundingRate': self.safe_number(entry, 'funding_rate'),
1060
+ 'timestamp': timestamp,
1061
+ 'datetime': self.iso8601(timestamp),
1062
+ })
1063
+ sorted = self.sort_by(rates, 'timestamp')
1064
+ return self.filter_by_symbol_since_limit(sorted, market['symbol'], since, limit)
1065
+
1066
+ async def fetch_funding_rate(self, symbol: str, params={}) -> FundingRate:
1067
+ """
1068
+ fetch the current funding rate
1069
+
1070
+ https://docs.derive.xyz/reference/post_public-get-funding-rate-history
1071
+
1072
+ :param str symbol: unified market symbol
1073
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1074
+ :returns dict: a `funding rate structure <https://docs.ccxt.com/#/?id=funding-rate-structure>`
1075
+ """
1076
+ response = await self.fetch_funding_rate_history(symbol, None, 1, params)
1077
+ #
1078
+ # [
1079
+ # {
1080
+ # "info": {
1081
+ # "timestamp": 1736157600000,
1082
+ # "funding_rate": "-0.000008872"
1083
+ # },
1084
+ # "symbol": "BTC/USD:USDC",
1085
+ # "fundingRate": -0.000008872,
1086
+ # "timestamp": 1736157600000,
1087
+ # "datetime": "2025-01-06T10:00:00.000Z"
1088
+ # }
1089
+ # ]
1090
+ #
1091
+ data = self.safe_dict(response, 0)
1092
+ return self.parse_funding_rate(data)
1093
+
1094
+ def parse_funding_rate(self, contract, market: Market = None) -> FundingRate:
1095
+ symbol = self.safe_string(contract, 'symbol')
1096
+ fundingTimestamp = self.safe_integer(contract, 'timestamp')
1097
+ return {
1098
+ 'info': contract,
1099
+ 'symbol': symbol,
1100
+ 'markPrice': None,
1101
+ 'indexPrice': None,
1102
+ 'interestRate': None,
1103
+ 'estimatedSettlePrice': None,
1104
+ 'timestamp': None,
1105
+ 'datetime': None,
1106
+ 'fundingRate': self.safe_number(contract, 'fundingRate'),
1107
+ 'fundingTimestamp': fundingTimestamp,
1108
+ 'fundingDatetime': self.iso8601(fundingTimestamp),
1109
+ 'nextFundingRate': None,
1110
+ 'nextFundingTimestamp': None,
1111
+ 'nextFundingDatetime': None,
1112
+ 'previousFundingRate': None,
1113
+ 'previousFundingTimestamp': None,
1114
+ 'previousFundingDatetime': None,
1115
+ 'interval': None,
1116
+ }
1117
+
1118
+ def hash_order_message(self, order):
1119
+ accountHash = self.hash(self.eth_abi_encode([
1120
+ 'bytes32', 'uint256', 'uint256', 'address', 'bytes32', 'uint256', 'address', 'address',
1121
+ ], order), 'keccak', 'binary')
1122
+ sandboxMode = self.safe_bool(self.options, 'sandboxMode', False)
1123
+ DOMAIN_SEPARATOR = '9bcf4dc06df5d8bf23af818d5716491b995020f377d3b7b64c29ed14e3dd1105' if (sandboxMode) else 'd96e5f90797da7ec8dc4e276260c7f3f87fedf68775fbe1ef116e996fc60441b'
1124
+ binaryDomainSeparator = self.base16_to_binary(DOMAIN_SEPARATOR)
1125
+ prefix = self.base16_to_binary('1901')
1126
+ return self.hash(self.binary_concat(prefix, binaryDomainSeparator, accountHash), 'keccak', 'hex')
1127
+
1128
+ def sign_order(self, order, privateKey):
1129
+ hashOrder = self.hash_order_message(order)
1130
+ return self.sign_hash(hashOrder[-64:], privateKey[-64:])
1131
+
1132
+ def hash_message(self, message):
1133
+ binaryMessage = self.encode(message)
1134
+ binaryMessageLength = self.binary_length(binaryMessage)
1135
+ x19 = self.base16_to_binary('19')
1136
+ newline = self.base16_to_binary('0a')
1137
+ prefix = self.binary_concat(x19, self.encode('Ethereum Signed Message:'), newline, self.encode(self.number_to_string(binaryMessageLength)))
1138
+ return '0x' + self.hash(self.binary_concat(prefix, binaryMessage), 'keccak', 'hex')
1139
+
1140
+ def sign_hash(self, hash, privateKey):
1141
+ self.check_required_credentials()
1142
+ signature = self.ecdsa(hash[-64:], privateKey[-64:], 'secp256k1', None)
1143
+ r = signature['r']
1144
+ s = signature['s']
1145
+ v = self.int_to_base16(self.sum(27, signature['v']))
1146
+ return '0x' + r.rjust(64, '0') + s.rjust(64, '0') + v
1147
+
1148
+ def sign_message(self, message, privateKey):
1149
+ return self.sign_hash(self.hash_message(message), privateKey[-64:])
1150
+
1151
+ def parse_units(self, num: str, dec='1000000000000000000'):
1152
+ return Precise.string_mul(num, dec)
1153
+
1154
+ async def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
1155
+ """
1156
+ create a trade order
1157
+
1158
+ https://docs.derive.xyz/reference/post_private-order
1159
+
1160
+ :param str symbol: unified symbol of the market to create an order in
1161
+ :param str type: 'market' or 'limit'
1162
+ :param str side: 'buy' or 'sell'
1163
+ :param float amount: how much of currency you want to trade in units of base currency
1164
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
1165
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1166
+ :param str [params.subaccount_id]: *required* the subaccount id
1167
+ :param float [params.triggerPrice]: The price a trigger order is triggered at
1168
+ :param dict [params.takeProfit]: *takeProfit object in params* containing the triggerPrice at which the attached take profit order will be triggered(perpetual swap markets only)
1169
+ :param float [params.takeProfit.triggerPrice]: take profit trigger price
1170
+ :param dict [params.stopLoss]: *stopLoss object in params* containing the triggerPrice at which the attached stop loss order will be triggered(perpetual swap markets only)
1171
+ :param float [params.stopLoss.triggerPrice]: stop loss trigger price
1172
+ :param float [params.max_fee]: *required* the maximum fee you are willing to pay for the order
1173
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1174
+ """
1175
+ await self.load_markets()
1176
+ market = self.market(symbol)
1177
+ if price is None:
1178
+ raise ArgumentsRequired(self.id + ' createOrder() requires a price argument')
1179
+ subaccountId = None
1180
+ subaccountId, params = self.handle_derive_subaccount_id('createOrder', params)
1181
+ test = self.safe_bool(params, 'test', False)
1182
+ reduceOnly = self.safe_bool_2(params, 'reduceOnly', 'reduce_only')
1183
+ timeInForce = self.safe_string_lower_2(params, 'timeInForce', 'time_in_force')
1184
+ postOnly = self.safe_bool(params, 'postOnly')
1185
+ orderType = type.lower()
1186
+ orderSide = side.lower()
1187
+ nonce = self.milliseconds()
1188
+ # Order signature expiry must be between 2592000 and 7776000 sec from now
1189
+ signatureExpiry = self.safe_integer(params, 'signature_expiry_sec', self.seconds() + 7776000)
1190
+ ACTION_TYPEHASH = self.base16_to_binary('4d7a9f27c403ff9c0f19bce61d76d82f9aa29f8d6d4b0c5474607d9770d1af17')
1191
+ sandboxMode = self.safe_bool(self.options, 'sandboxMode', False)
1192
+ TRADE_MODULE_ADDRESS = '0x87F2863866D85E3192a35A73b388BD625D83f2be' if (sandboxMode) else '0xB8D20c2B7a1Ad2EE33Bc50eF10876eD3035b5e7b'
1193
+ priceString = self.number_to_string(price)
1194
+ maxFee = None
1195
+ maxFee, params = self.handle_option_and_params(params, 'createOrder', 'max_fee')
1196
+ if maxFee is None:
1197
+ raise ArgumentsRequired(self.id + ' createOrder() requires a max_fee argument in params')
1198
+ maxFeeString = self.number_to_string(maxFee)
1199
+ amountString = self.number_to_string(amount)
1200
+ tradeModuleDataHash = self.hash(self.eth_abi_encode([
1201
+ 'address', 'uint', 'int', 'int', 'uint', 'uint', 'bool',
1202
+ ], [
1203
+ market['info']['base_asset_address'],
1204
+ self.parse_to_numeric(market['info']['base_asset_sub_id']),
1205
+ self.convert_to_big_int(self.parse_units(priceString)),
1206
+ self.convert_to_big_int(self.parse_units(self.amount_to_precision(symbol, amountString))),
1207
+ self.convert_to_big_int(self.parse_units(maxFeeString)),
1208
+ subaccountId,
1209
+ orderSide == 'buy',
1210
+ ]), 'keccak', 'binary')
1211
+ deriveWalletAddress = None
1212
+ deriveWalletAddress, params = self.handle_derive_wallet_address('createOrder', params)
1213
+ signature = self.sign_order([
1214
+ ACTION_TYPEHASH,
1215
+ subaccountId,
1216
+ nonce,
1217
+ TRADE_MODULE_ADDRESS,
1218
+ tradeModuleDataHash,
1219
+ signatureExpiry,
1220
+ deriveWalletAddress,
1221
+ self.walletAddress,
1222
+ ], self.privateKey)
1223
+ request: dict = {
1224
+ 'instrument_name': market['id'],
1225
+ 'direction': orderSide,
1226
+ 'order_type': orderType,
1227
+ 'nonce': nonce,
1228
+ 'amount': amountString,
1229
+ 'limit_price': priceString,
1230
+ 'max_fee': maxFeeString,
1231
+ 'subaccount_id': subaccountId,
1232
+ 'signature_expiry_sec': signatureExpiry,
1233
+ 'referral_code': self.safe_string(self.options, 'id', '0x0ad42b8e602c2d3d475ae52d678cf63d84ab2749'),
1234
+ 'signer': self.walletAddress,
1235
+ }
1236
+ if reduceOnly is not None:
1237
+ request['reduce_only'] = reduceOnly
1238
+ if reduceOnly and postOnly:
1239
+ raise InvalidOrder(self.id + ' cannot use reduce only with post only time in force')
1240
+ if postOnly is not None:
1241
+ request['time_in_force'] = 'post_only'
1242
+ elif timeInForce is not None:
1243
+ request['time_in_force'] = timeInForce
1244
+ stopLoss = self.safe_value(params, 'stopLoss')
1245
+ takeProfit = self.safe_value(params, 'takeProfit')
1246
+ triggerPriceType = self.safe_string(params, 'trigger_price_type', 'mark')
1247
+ if stopLoss is not None:
1248
+ stopLossPrice = self.safe_string(stopLoss, 'triggerPrice', stopLoss)
1249
+ request['trigger_price'] = stopLossPrice
1250
+ request['trigger_type'] = 'stoploss'
1251
+ request['trigger_price_type'] = triggerPriceType
1252
+ elif takeProfit is not None:
1253
+ takeProfitPrice = self.safe_string(takeProfit, 'triggerPrice', takeProfit)
1254
+ request['trigger_price'] = takeProfitPrice
1255
+ request['trigger_type'] = 'takeprofit'
1256
+ request['trigger_price_type'] = triggerPriceType
1257
+ clientOrderId = self.safe_string(params, 'clientOrderId')
1258
+ if clientOrderId is not None:
1259
+ request['label'] = clientOrderId
1260
+ request['signature'] = signature
1261
+ params = self.omit(params, ['reduceOnly', 'reduce_only', 'timeInForce', 'time_in_force', 'postOnly', 'test', 'clientOrderId', 'stopPrice', 'triggerPrice', 'trigger_price', 'stopLoss', 'takeProfit', 'trigger_price_type'])
1262
+ response = None
1263
+ if test:
1264
+ response = await self.privatePostOrderDebug(self.extend(request, params))
1265
+ else:
1266
+ response = await self.privatePostOrder(self.extend(request, params))
1267
+ #
1268
+ # {
1269
+ # "result": {
1270
+ # "raw_data": {
1271
+ # "subaccount_id": 130837,
1272
+ # "nonce": 1736923517552,
1273
+ # "module": "0x87F2863866D85E3192a35A73b388BD625D83f2be",
1274
+ # "expiry": 86400,
1275
+ # "owner": "0x108b9aF9279a525b8A8AeAbE7AC2bA925Bc50075",
1276
+ # "signer": "0x108b9aF9279a525b8A8AeAbE7AC2bA925Bc50075",
1277
+ # "signature": "0xaa4f42b2f3da33c668fa703ea872d4c3a6b55aca66025b5119e3bebb6679fe2e2794638db51dcace21fc39a498047835994f07eb59f311bb956ce057e66793d1c",
1278
+ # "data": {
1279
+ # "asset": "0xAFB6Bb95cd70D5367e2C39e9dbEb422B9815339D",
1280
+ # "sub_id": 0,
1281
+ # "limit_price": "10000",
1282
+ # "desired_amount": "0.001",
1283
+ # "worst_fee": "0",
1284
+ # "recipient_id": 130837,
1285
+ # "is_bid": True,
1286
+ # "trade_id": ""
1287
+ # }
1288
+ # },
1289
+ # "encoded_data": "0x000000000000000000000000afb6bb95cd70d5367e2c39e9dbeb422b9815339d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000021e19e0c9bab240000000000000000000000000000000000000000000000000000000038d7ea4c680000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001ff150000000000000000000000000000000000000000000000000000000000000001",
1290
+ # "encoded_data_hashed": "0xe88fb416bc54dba2d288988f1a82fee40fd792ed555b3471b5f6b4b810d279b4",
1291
+ # "action_hash": "0x273a0befb3751fa991edc7ed73582456c3b50ae964d458c8f472e932fb6a0069",
1292
+ # "typed_data_hash": "0x123e2d2f3d5b2473b4e260f51c6459d6bf904e5db8f042a3ea63be8d55329ce9"
1293
+ # },
1294
+ # "id": "f851c8c4-dddf-4b77-93cf-aeddd0966f29"
1295
+ # }
1296
+ # {
1297
+ # "result": {
1298
+ # "order": {
1299
+ # "subaccount_id": 130837,
1300
+ # "order_id": "96349ebb-7d46-43ae-81c7-7ab390444293",
1301
+ # "instrument_name": "BTC-PERP",
1302
+ # "direction": "buy",
1303
+ # "label": "",
1304
+ # "quote_id": null,
1305
+ # "creation_timestamp": 1737467576257,
1306
+ # "last_update_timestamp": 1737467576257,
1307
+ # "limit_price": "10000",
1308
+ # "amount": "0.01",
1309
+ # "filled_amount": "0",
1310
+ # "average_price": "0",
1311
+ # "order_fee": "0",
1312
+ # "order_type": "limit",
1313
+ # "time_in_force": "gtc",
1314
+ # "order_status": "open",
1315
+ # "max_fee": "210",
1316
+ # "signature_expiry_sec": 1737468175989,
1317
+ # "nonce": 1737467575989,
1318
+ # "signer": "0x30CB7B06AdD6749BbE146A6827502B8f2a79269A",
1319
+ # "signature": "0xd1ca49df1fa06bd805bb59b132ff6c0de29bf973a3e01705abe0a01cc956e4945ed9eb99ab68f3df4c037908113cac5a5bfc3a954a0b7103cdab285962fa6a51c",
1320
+ # "cancel_reason": "",
1321
+ # "mmp": False,
1322
+ # "is_transfer": False,
1323
+ # "replaced_order_id": null,
1324
+ # "trigger_type": null,
1325
+ # "trigger_price_type": null,
1326
+ # "trigger_price": null,
1327
+ # "trigger_reject_message": null
1328
+ # },
1329
+ # "trades": []
1330
+ # },
1331
+ # "id": "397087fa-0125-42af-bfc3-f66166f9fb55"
1332
+ # }
1333
+ #
1334
+ result = self.safe_dict(response, 'result')
1335
+ rawOrder = self.safe_dict(result, 'raw_data')
1336
+ if rawOrder is None:
1337
+ rawOrder = self.safe_dict(result, 'order')
1338
+ order = self.parse_order(rawOrder, market)
1339
+ order['type'] = type
1340
+ return order
1341
+
1342
+ async def edit_order(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}):
1343
+ """
1344
+ edit a trade order
1345
+
1346
+ https://docs.derive.xyz/reference/post_private-replace
1347
+
1348
+ :param str id: order id
1349
+ :param str symbol: unified symbol of the market to create an order in
1350
+ :param str type: 'market' or 'limit'
1351
+ :param str side: 'buy' or 'sell'
1352
+ :param float amount: how much of currency you want to trade in units of base currency
1353
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
1354
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1355
+ :param str [params.subaccount_id]: *required* the subaccount id
1356
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1357
+ """
1358
+ await self.load_markets()
1359
+ market = self.market(symbol)
1360
+ subaccountId = None
1361
+ subaccountId, params = self.handle_derive_subaccount_id('editOrder', params)
1362
+ reduceOnly = self.safe_bool_2(params, 'reduceOnly', 'reduce_only')
1363
+ timeInForce = self.safe_string_lower_2(params, 'timeInForce', 'time_in_force')
1364
+ postOnly = self.safe_bool(params, 'postOnly')
1365
+ orderType = type.lower()
1366
+ orderSide = side.lower()
1367
+ nonce = self.milliseconds()
1368
+ signatureExpiry = self.safe_number(params, 'signature_expiry_sec', self.seconds() + 7776000)
1369
+ # TODO: subaccount id / trade module address
1370
+ ACTION_TYPEHASH = self.base16_to_binary('4d7a9f27c403ff9c0f19bce61d76d82f9aa29f8d6d4b0c5474607d9770d1af17')
1371
+ sandboxMode = self.safe_bool(self.options, 'sandboxMode', False)
1372
+ TRADE_MODULE_ADDRESS = '0x87F2863866D85E3192a35A73b388BD625D83f2be' if (sandboxMode) else '0xB8D20c2B7a1Ad2EE33Bc50eF10876eD3035b5e7b'
1373
+ priceString = self.number_to_string(price)
1374
+ maxFeeString = self.safe_string(params, 'max_fee', '0')
1375
+ amountString = self.number_to_string(amount)
1376
+ tradeModuleDataHash = self.hash(self.eth_abi_encode([
1377
+ 'address', 'uint', 'int', 'int', 'uint', 'uint', 'bool',
1378
+ ], [
1379
+ market['info']['base_asset_address'],
1380
+ self.parse_to_numeric(market['info']['base_asset_sub_id']),
1381
+ self.convert_to_big_int(self.parse_units(priceString)),
1382
+ self.convert_to_big_int(self.parse_units(self.amount_to_precision(symbol, amountString))),
1383
+ self.convert_to_big_int(self.parse_units(maxFeeString)),
1384
+ subaccountId,
1385
+ orderSide == 'buy',
1386
+ ]), 'keccak', 'binary')
1387
+ deriveWalletAddress = None
1388
+ deriveWalletAddress, params = self.handle_derive_wallet_address('editOrder', params)
1389
+ signature = self.sign_order([
1390
+ ACTION_TYPEHASH,
1391
+ subaccountId,
1392
+ nonce,
1393
+ TRADE_MODULE_ADDRESS,
1394
+ tradeModuleDataHash,
1395
+ signatureExpiry,
1396
+ deriveWalletAddress,
1397
+ self.walletAddress,
1398
+ ], self.privateKey)
1399
+ request: dict = {
1400
+ 'instrument_name': market['id'],
1401
+ 'order_id_to_cancel': id,
1402
+ 'direction': orderSide,
1403
+ 'order_type': orderType,
1404
+ 'nonce': nonce,
1405
+ 'amount': amountString,
1406
+ 'limit_price': priceString,
1407
+ 'max_fee': maxFeeString,
1408
+ 'subaccount_id': subaccountId,
1409
+ 'signature_expiry_sec': signatureExpiry,
1410
+ 'signer': self.walletAddress,
1411
+ }
1412
+ if reduceOnly is not None:
1413
+ request['reduce_only'] = reduceOnly
1414
+ if reduceOnly and postOnly:
1415
+ raise InvalidOrder(self.id + ' cannot use reduce only with post only time in force')
1416
+ if postOnly is not None:
1417
+ request['time_in_force'] = 'post_only'
1418
+ elif timeInForce is not None:
1419
+ request['time_in_force'] = timeInForce
1420
+ clientOrderId = self.safe_string(params, 'clientOrderId')
1421
+ if clientOrderId is not None:
1422
+ request['label'] = clientOrderId
1423
+ request['signature'] = signature
1424
+ params = self.omit(params, ['reduceOnly', 'reduce_only', 'timeInForce', 'time_in_force', 'postOnly', 'clientOrderId'])
1425
+ response = await self.privatePostReplace(self.extend(request, params))
1426
+ #
1427
+ # {
1428
+ # "result":
1429
+ # {
1430
+ # "cancelled_order":
1431
+ # {
1432
+ # "subaccount_id": 130837,
1433
+ # "order_id": "c2337704-f1af-437d-91c8-dddb9d6bac59",
1434
+ # "instrument_name": "BTC-PERP",
1435
+ # "direction": "buy",
1436
+ # "label": "test1234",
1437
+ # "quote_id": null,
1438
+ # "creation_timestamp": 1737539743959,
1439
+ # "last_update_timestamp": 1737539764234,
1440
+ # "limit_price": "10000",
1441
+ # "amount": "0.01",
1442
+ # "filled_amount": "0",
1443
+ # "average_price": "0",
1444
+ # "order_fee": "0",
1445
+ # "order_type": "limit",
1446
+ # "time_in_force": "post_only",
1447
+ # "order_status": "cancelled",
1448
+ # "max_fee": "211",
1449
+ # "signature_expiry_sec": 1737540343631,
1450
+ # "nonce": 1737539743631,
1451
+ # "signer": "0x30CB7B06AdD6749BbE146A6827502B8f2a79269A",
1452
+ # "signature": "0xdb669e18f407a3efa816b79c0dd3bac1c651d4dbf3caad4db67678ce9b81c76378d787a08143a30707eb0827ce4626640767c9f174358df1b90611bd6d1391711b",
1453
+ # "cancel_reason": "user_request",
1454
+ # "mmp": False,
1455
+ # "is_transfer": False,
1456
+ # "replaced_order_id": null,
1457
+ # "trigger_type": null,
1458
+ # "trigger_price_type": null,
1459
+ # "trigger_price": null,
1460
+ # "trigger_reject_message": null,
1461
+ # },
1462
+ # "order":
1463
+ # {
1464
+ # "subaccount_id": 130837,
1465
+ # "order_id": "97af0902-813f-4892-a54b-797e5689db05",
1466
+ # "instrument_name": "BTC-PERP",
1467
+ # "direction": "buy",
1468
+ # "label": "test1234",
1469
+ # "quote_id": null,
1470
+ # "creation_timestamp": 1737539764154,
1471
+ # "last_update_timestamp": 1737539764154,
1472
+ # "limit_price": "10000",
1473
+ # "amount": "0.01",
1474
+ # "filled_amount": "0",
1475
+ # "average_price": "0",
1476
+ # "order_fee": "0",
1477
+ # "order_type": "limit",
1478
+ # "time_in_force": "post_only",
1479
+ # "order_status": "open",
1480
+ # "max_fee": "211",
1481
+ # "signature_expiry_sec": 1737540363890,
1482
+ # "nonce": 1737539763890,
1483
+ # "signer": "0x30CB7B06AdD6749BbE146A6827502B8f2a79269A",
1484
+ # "signature": "0xef2c459ab4797cbbd7d97b47678ff172542af009bac912bf53e7879cf92eb1aa6b1a6cf40bf0928684f5394942fb424cc2db71eac0eaf7226a72480034332f291c",
1485
+ # "cancel_reason": "",
1486
+ # "mmp": False,
1487
+ # "is_transfer": False,
1488
+ # "replaced_order_id": "c2337704-f1af-437d-91c8-dddb9d6bac59",
1489
+ # "trigger_type": null,
1490
+ # "trigger_price_type": null,
1491
+ # "trigger_price": null,
1492
+ # "trigger_reject_message": null,
1493
+ # },
1494
+ # "trades": [],
1495
+ # "create_order_error": null,
1496
+ # },
1497
+ # "id": "fb19e991-15f6-4c80-a20c-917e762a1a38",
1498
+ # }
1499
+ #
1500
+ result = self.safe_dict(response, 'result')
1501
+ rawOrder = self.safe_dict(result, 'order')
1502
+ order = self.parse_order(rawOrder, market)
1503
+ return order
1504
+
1505
+ async def cancel_order(self, id: str, symbol: Str = None, params={}):
1506
+ """
1507
+
1508
+ https://docs.derive.xyz/reference/post_private-cancel
1509
+
1510
+ cancels an open order
1511
+ :param str id: order id
1512
+ :param str symbol: unified symbol of the market the order was made in
1513
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1514
+ :param boolean [params.trigger]: whether the order is a trigger/algo order
1515
+ :param str [params.subaccount_id]: *required* the subaccount id
1516
+ :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1517
+ """
1518
+ if symbol is None:
1519
+ raise ArgumentsRequired(self.id + ' cancelOrder() requires a symbol argument')
1520
+ await self.load_markets()
1521
+ market: Market = self.market(symbol)
1522
+ isTrigger = self.safe_bool_2(params, 'trigger', 'stop', False)
1523
+ subaccountId = None
1524
+ subaccountId, params = self.handle_derive_subaccount_id('cancelOrder', params)
1525
+ params = self.omit(params, ['trigger', 'stop'])
1526
+ request: dict = {
1527
+ 'instrument_name': market['id'],
1528
+ 'subaccount_id': subaccountId,
1529
+ }
1530
+ clientOrderIdUnified = self.safe_string(params, 'clientOrderId')
1531
+ clientOrderIdExchangeSpecific = self.safe_string(params, 'label', clientOrderIdUnified)
1532
+ isByClientOrder = clientOrderIdExchangeSpecific is not None
1533
+ response = None
1534
+ if isByClientOrder:
1535
+ request['label'] = clientOrderIdExchangeSpecific
1536
+ params = self.omit(params, ['clientOrderId', 'label'])
1537
+ response = await self.privatePostCancelByLabel(self.extend(request, params))
1538
+ else:
1539
+ request['order_id'] = id
1540
+ if isTrigger:
1541
+ response = await self.privatePostCancelTriggerOrder(self.extend(request, params))
1542
+ else:
1543
+ response = await self.privatePostCancel(self.extend(request, params))
1544
+ #
1545
+ # {
1546
+ # "result": {
1547
+ # "subaccount_id": 130837,
1548
+ # "order_id": "de4f30b6-0dcb-4df6-9222-c1a27f1ad80d",
1549
+ # "instrument_name": "BTC-PERP",
1550
+ # "direction": "buy",
1551
+ # "label": "test1234",
1552
+ # "quote_id": null,
1553
+ # "creation_timestamp": 1737540100989,
1554
+ # "last_update_timestamp": 1737540574696,
1555
+ # "limit_price": "10000",
1556
+ # "amount": "0.01",
1557
+ # "filled_amount": "0",
1558
+ # "average_price": "0",
1559
+ # "order_fee": "0",
1560
+ # "order_type": "limit",
1561
+ # "time_in_force": "post_only",
1562
+ # "order_status": "cancelled",
1563
+ # "max_fee": "211",
1564
+ # "signature_expiry_sec": 1737540700726,
1565
+ # "nonce": 1737540100726,
1566
+ # "signer": "0x30CB7B06AdD6749BbE146A6827502B8f2a79269A",
1567
+ # "signature": "0x9cd1a6e32a0699929e4e090c08c548366b1353701ec56e02d5cdf37fc89bd19b7b29e00e57e8383bb6336d73019027a7e2a4364f40859e7a949115024c7f199a1b",
1568
+ # "cancel_reason": "user_request",
1569
+ # "mmp": False,
1570
+ # "is_transfer": False,
1571
+ # "replaced_order_id": "4ccc89ba-3c3d-4047-8900-0aa5fb4ef706",
1572
+ # "trigger_type": null,
1573
+ # "trigger_price_type": null,
1574
+ # "trigger_price": null,
1575
+ # "trigger_reject_message": null
1576
+ # },
1577
+ # "id": "cef61e2a-cb13-4779-8e6b-535361981fad"
1578
+ # }
1579
+ #
1580
+ # {
1581
+ # "result": {
1582
+ # "cancelled_orders": 1
1583
+ # },
1584
+ # "id": "674e075e-1e8a-4a47-99ff-75efbdd2370f"
1585
+ # }
1586
+ #
1587
+ extendParams: dict = {'symbol': symbol}
1588
+ order = self.safe_dict(response, 'result')
1589
+ if isByClientOrder:
1590
+ extendParams['client_order_id'] = clientOrderIdExchangeSpecific
1591
+ return self.extend(self.parse_order(order, market), extendParams)
1592
+
1593
+ async def cancel_all_orders(self, symbol: Str = None, params={}):
1594
+ """
1595
+
1596
+ https://docs.derive.xyz/reference/post_private-cancel-by-instrument
1597
+ https://docs.derive.xyz/reference/post_private-cancel-all
1598
+
1599
+ cancel all open orders in a market
1600
+ :param str symbol: unified market symbol
1601
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1602
+ :param str [params.subaccount_id]: *required* the subaccount id
1603
+ :returns dict: an list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1604
+ """
1605
+ await self.load_markets()
1606
+ market: Market = None
1607
+ if symbol is not None:
1608
+ market = self.market(symbol)
1609
+ subaccountId = None
1610
+ subaccountId, params = self.handle_derive_subaccount_id('cancelAllOrders', params)
1611
+ request: dict = {
1612
+ 'subaccount_id': subaccountId,
1613
+ }
1614
+ response = None
1615
+ if market is not None:
1616
+ request['instrument_name'] = market['id']
1617
+ response = await self.privatePostCancelByInstrument(self.extend(request, params))
1618
+ else:
1619
+ response = await self.privatePostCancelAll(self.extend(request, params))
1620
+ #
1621
+ # {
1622
+ # "result": {
1623
+ # "cancelled_orders": 0
1624
+ # },
1625
+ # "id": "9d633799-2098-4559-b547-605bb6f4d8f4"
1626
+ # }
1627
+ #
1628
+ # {
1629
+ # "id": "45548646-c74f-4ca2-9de4-551e6de49afa",
1630
+ # "result": "ok"
1631
+ # }
1632
+ #
1633
+ return [self.safe_order({'info': response})]
1634
+
1635
+ async def fetch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1636
+ """
1637
+ fetches information on multiple orders made by the user
1638
+
1639
+ https://docs.derive.xyz/reference/post_private-get-orders
1640
+
1641
+ :param str symbol: unified market symbol of the market orders were made in
1642
+ :param int [since]: the earliest time in ms to fetch orders for
1643
+ :param int [limit]: the maximum number of order structures to retrieve
1644
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1645
+ :param boolean [params.paginate]: set to True if you want to fetch orders with pagination
1646
+ :param boolean [params.trigger]: whether the order is a trigger/algo order
1647
+ :param str [params.subaccount_id]: *required* the subaccount id
1648
+ :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1649
+ """
1650
+ await self.load_markets()
1651
+ paginate = False
1652
+ paginate, params = self.handle_option_and_params(params, 'fetchOrders', 'paginate')
1653
+ if paginate:
1654
+ return await self.fetch_paginated_call_incremental('fetchOrders', symbol, since, limit, params, 'page', 500)
1655
+ isTrigger = self.safe_bool_2(params, 'trigger', 'stop', False)
1656
+ params = self.omit(params, ['trigger', 'stop'])
1657
+ subaccountId = None
1658
+ subaccountId, params = self.handle_derive_subaccount_id('fetchOrders', params)
1659
+ request: dict = {
1660
+ 'subaccount_id': subaccountId,
1661
+ }
1662
+ market: Market = None
1663
+ if symbol is not None:
1664
+ market = self.market(symbol)
1665
+ request['instrument_name'] = market['id']
1666
+ if limit is not None:
1667
+ request['page_size'] = limit
1668
+ else:
1669
+ request['page_size'] = 500
1670
+ if isTrigger:
1671
+ request['status'] = 'untriggered'
1672
+ response = await self.privatePostGetOrders(self.extend(request, params))
1673
+ #
1674
+ # {
1675
+ # "result": {
1676
+ # "subaccount_id": 130837,
1677
+ # "orders": [
1678
+ # {
1679
+ # "subaccount_id": 130837,
1680
+ # "order_id": "63a80cb8-387b-472b-a838-71cd9513c365",
1681
+ # "instrument_name": "BTC-PERP",
1682
+ # "direction": "buy",
1683
+ # "label": "test1234",
1684
+ # "quote_id": null,
1685
+ # "creation_timestamp": 1737551053207,
1686
+ # "last_update_timestamp": 1737551053207,
1687
+ # "limit_price": "10000",
1688
+ # "amount": "0.01",
1689
+ # "filled_amount": "0",
1690
+ # "average_price": "0",
1691
+ # "order_fee": "0",
1692
+ # "order_type": "limit",
1693
+ # "time_in_force": "post_only",
1694
+ # "order_status": "open",
1695
+ # "max_fee": "211",
1696
+ # "signature_expiry_sec": 1737551652765,
1697
+ # "nonce": 1737551052765,
1698
+ # "signer": "0x30CB7B06AdD6749BbE146A6827502B8f2a79269A",
1699
+ # "signature": "0x35535ccb1bcad509ecc435c79e966174db6403fc9aeee1e237d08a941014c57b59279dfe4be39e081f9921a53eaad59cb2a151d9f52f2d05fc47e6280254952e1c",
1700
+ # "cancel_reason": "",
1701
+ # "mmp": False,
1702
+ # "is_transfer": False,
1703
+ # "replaced_order_id": null,
1704
+ # "trigger_type": null,
1705
+ # "trigger_price_type": null,
1706
+ # "trigger_price": null,
1707
+ # "trigger_reject_message": null
1708
+ # }
1709
+ # ],
1710
+ # "pagination": {
1711
+ # "num_pages": 1,
1712
+ # "count": 1
1713
+ # }
1714
+ # },
1715
+ # "id": "e5a88d4f-7ac7-40cd-aec9-e0e8152b8b92"
1716
+ # }
1717
+ #
1718
+ data = self.safe_value(response, 'result')
1719
+ page = self.safe_integer(params, 'page')
1720
+ if page is not None:
1721
+ pagination = self.safe_dict(data, 'pagination')
1722
+ currentPage = self.safe_integer(pagination, 'num_pages')
1723
+ if page > currentPage:
1724
+ return []
1725
+ orders = self.safe_list(data, 'orders')
1726
+ return self.parse_orders(orders, market, since, limit)
1727
+
1728
+ async def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1729
+ """
1730
+ fetches information on multiple orders made by the user
1731
+
1732
+ https://docs.derive.xyz/reference/post_private-get-orders
1733
+
1734
+ :param str symbol: unified market symbol of the market orders were made in
1735
+ :param int [since]: the earliest time in ms to fetch orders for
1736
+ :param int [limit]: the maximum number of order structures to retrieve
1737
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1738
+ :param boolean [params.paginate]: set to True if you want to fetch orders with pagination
1739
+ :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1740
+ """
1741
+ await self.load_markets()
1742
+ extendedParams = self.extend(params, {'status': 'open'})
1743
+ return await self.fetch_orders(symbol, since, limit, extendedParams)
1744
+
1745
+ async def fetch_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1746
+ """
1747
+ fetches information on multiple orders made by the user
1748
+
1749
+ https://docs.derive.xyz/reference/post_private-get-orders
1750
+
1751
+ :param str symbol: unified market symbol of the market orders were made in
1752
+ :param int [since]: the earliest time in ms to fetch orders for
1753
+ :param int [limit]: the maximum number of order structures to retrieve
1754
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1755
+ :param boolean [params.paginate]: set to True if you want to fetch orders with pagination
1756
+ :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1757
+ """
1758
+ await self.load_markets()
1759
+ extendedParams = self.extend(params, {'status': 'filled'})
1760
+ return await self.fetch_orders(symbol, since, limit, extendedParams)
1761
+
1762
+ async def fetch_canceled_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1763
+ """
1764
+ fetches information on multiple canceled orders made by the user
1765
+
1766
+ https://docs.derive.xyz/reference/post_private-get-orders
1767
+
1768
+ :param str symbol: unified market symbol of the market the orders were made in
1769
+ :param int [since]: the earliest time in ms to fetch orders for
1770
+ :param int [limit]: the maximum number of order structures to retrieve
1771
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1772
+ :param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
1773
+ :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1774
+ """
1775
+ await self.load_markets()
1776
+ extendedParams = self.extend(params, {'status': 'cancelled'})
1777
+ return await self.fetch_orders(symbol, since, limit, extendedParams)
1778
+
1779
+ def parse_time_in_force(self, timeInForce: Str):
1780
+ timeInForces: dict = {
1781
+ 'ioc': 'IOC',
1782
+ 'fok': 'FOK',
1783
+ 'gtc': 'GTC',
1784
+ 'post_only': 'PO',
1785
+ }
1786
+ return self.safe_string(timeInForces, timeInForce, None)
1787
+
1788
+ def parse_order_status(self, status: Str):
1789
+ if status is not None:
1790
+ statuses: dict = {
1791
+ 'open': 'open',
1792
+ 'untriggered': 'open',
1793
+ 'filled': 'closed',
1794
+ 'cancelled': 'canceled',
1795
+ 'expired': 'rejected',
1796
+ }
1797
+ return self.safe_string(statuses, status, status)
1798
+ return status
1799
+
1800
+ def parse_order(self, rawOrder: dict, market: Market = None) -> Order:
1801
+ #
1802
+ # {
1803
+ # "subaccount_id": 130837,
1804
+ # "nonce": 1736923517552,
1805
+ # "module": "0x87F2863866D85E3192a35A73b388BD625D83f2be",
1806
+ # "expiry": 86400,
1807
+ # "owner": "0x108b9aF9279a525b8A8AeAbE7AC2bA925Bc50075",
1808
+ # "signer": "0x108b9aF9279a525b8A8AeAbE7AC2bA925Bc50075",
1809
+ # "signature": "0xaa4f42b2f3da33c668fa703ea872d4c3a6b55aca66025b5119e3bebb6679fe2e2794638db51dcace21fc39a498047835994f07eb59f311bb956ce057e66793d1c",
1810
+ # "data": {
1811
+ # "asset": "0xAFB6Bb95cd70D5367e2C39e9dbEb422B9815339D",
1812
+ # "sub_id": 0,
1813
+ # "limit_price": "10000",
1814
+ # "desired_amount": "0.001",
1815
+ # "worst_fee": "0",
1816
+ # "recipient_id": 130837,
1817
+ # "is_bid": True,
1818
+ # "trade_id": ""
1819
+ # }
1820
+ # }
1821
+ # {
1822
+ # "subaccount_id": 130837,
1823
+ # "order_id": "96349ebb-7d46-43ae-81c7-7ab390444293",
1824
+ # "instrument_name": "BTC-PERP",
1825
+ # "direction": "buy",
1826
+ # "label": "",
1827
+ # "quote_id": null,
1828
+ # "creation_timestamp": 1737467576257,
1829
+ # "last_update_timestamp": 1737467576257,
1830
+ # "limit_price": "10000",
1831
+ # "amount": "0.01",
1832
+ # "filled_amount": "0",
1833
+ # "average_price": "0",
1834
+ # "order_fee": "0",
1835
+ # "order_type": "limit",
1836
+ # "time_in_force": "gtc",
1837
+ # "order_status": "open",
1838
+ # "max_fee": "210",
1839
+ # "signature_expiry_sec": 1737468175989,
1840
+ # "nonce": 1737467575989,
1841
+ # "signer": "0x30CB7B06AdD6749BbE146A6827502B8f2a79269A",
1842
+ # "signature": "0xd1ca49df1fa06bd805bb59b132ff6c0de29bf973a3e01705abe0a01cc956e4945ed9eb99ab68f3df4c037908113cac5a5bfc3a954a0b7103cdab285962fa6a51c",
1843
+ # "cancel_reason": "",
1844
+ # "mmp": False,
1845
+ # "is_transfer": False,
1846
+ # "replaced_order_id": null,
1847
+ # "trigger_type": null,
1848
+ # "trigger_price_type": null,
1849
+ # "trigger_price": null,
1850
+ # "trigger_reject_message": null
1851
+ # }
1852
+ order = self.safe_dict(rawOrder, 'data')
1853
+ if order is None:
1854
+ order = rawOrder
1855
+ timestamp = self.safe_integer_2(rawOrder, 'creation_timestamp', 'nonce')
1856
+ orderId = self.safe_string(order, 'order_id')
1857
+ marketId = self.safe_string(order, 'instrument_name')
1858
+ if marketId is not None:
1859
+ market = self.safe_market(marketId, market)
1860
+ symbol = market['symbol']
1861
+ price = self.safe_string(order, 'limit_price')
1862
+ average = self.safe_string(order, 'average_price')
1863
+ amount = self.safe_string(order, 'desired_amount')
1864
+ filled = self.safe_string(order, 'filled_amount')
1865
+ fee = self.safe_string(order, 'order_fee')
1866
+ orderType = self.safe_string_lower(order, 'order_type')
1867
+ isBid = self.safe_bool(order, 'is_bid')
1868
+ side = self.safe_string(order, 'direction')
1869
+ if side is None:
1870
+ if isBid:
1871
+ side = 'buy'
1872
+ else:
1873
+ side = 'sell'
1874
+ triggerType = self.safe_string(order, 'trigger_type')
1875
+ stopLossPrice = None
1876
+ takeProfitPrice = None
1877
+ triggerPrice = None
1878
+ if triggerType is not None:
1879
+ triggerPrice = self.safe_string(order, 'trigger_price')
1880
+ if triggerType == 'stoploss':
1881
+ stopLossPrice = triggerPrice
1882
+ else:
1883
+ takeProfitPrice = triggerPrice
1884
+ lastUpdateTimestamp = self.safe_integer(rawOrder, 'last_update_timestamp')
1885
+ status = self.safe_string(order, 'order_status')
1886
+ timeInForce = self.safe_string(order, 'time_in_force')
1887
+ return self.safe_order({
1888
+ 'id': orderId,
1889
+ 'clientOrderId': self.safe_string(order, 'label'),
1890
+ 'timestamp': timestamp,
1891
+ 'datetime': self.iso8601(timestamp),
1892
+ 'lastTradeTimestamp': None,
1893
+ 'lastUpdateTimestamp': lastUpdateTimestamp,
1894
+ 'status': self.parse_order_status(status),
1895
+ 'symbol': symbol,
1896
+ 'type': orderType,
1897
+ 'timeInForce': self.parse_time_in_force(timeInForce),
1898
+ 'postOnly': None, # handled in safeOrder
1899
+ 'reduceOnly': self.safe_bool(order, 'reduce_only'),
1900
+ 'side': side,
1901
+ 'price': price,
1902
+ 'triggerPrice': triggerPrice,
1903
+ 'takeProfitPrice': takeProfitPrice,
1904
+ 'stopLossPrice': stopLossPrice,
1905
+ 'average': average,
1906
+ 'amount': amount,
1907
+ 'filled': filled,
1908
+ 'remaining': None,
1909
+ 'cost': None,
1910
+ 'trades': None,
1911
+ 'fee': {
1912
+ 'cost': fee,
1913
+ 'currency': 'USDC',
1914
+ },
1915
+ 'info': order,
1916
+ }, market)
1917
+
1918
+ async def fetch_order_trades(self, id: str, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1919
+ """
1920
+ fetch all the trades made from a single order
1921
+
1922
+ https://docs.derive.xyz/reference/post_private-get-trade-history
1923
+
1924
+ :param str id: order id
1925
+ :param str symbol: unified market symbol
1926
+ :param int [since]: the earliest time in ms to fetch trades for
1927
+ :param int [limit]: the maximum number of trades to retrieve
1928
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1929
+ :param str [params.subaccount_id]: *required* the subaccount id
1930
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
1931
+ """
1932
+ await self.load_markets()
1933
+ subaccountId = None
1934
+ subaccountId, params = self.handle_derive_subaccount_id('fetchOrderTrades', params)
1935
+ request: dict = {
1936
+ 'order_id': id,
1937
+ 'subaccount_id': subaccountId,
1938
+ }
1939
+ market: Market = None
1940
+ if symbol is not None:
1941
+ market = self.market(symbol)
1942
+ request['instrument_name'] = market['id']
1943
+ if limit is not None:
1944
+ request['page_size'] = limit
1945
+ if since is not None:
1946
+ request['from_timestamp'] = since
1947
+ response = await self.privatePostGetTradeHistory(self.extend(request, params))
1948
+ #
1949
+ # {
1950
+ # "result": {
1951
+ # "subaccount_id": 130837,
1952
+ # "trades": [
1953
+ # {
1954
+ # "subaccount_id": 130837,
1955
+ # "order_id": "30c48194-8d48-43ac-ad00-0d5ba29eddc9",
1956
+ # "instrument_name": "BTC-PERP",
1957
+ # "direction": "sell",
1958
+ # "label": "test1234",
1959
+ # "quote_id": null,
1960
+ # "trade_id": "f8a30740-488c-4c2d-905d-e17057bafde1",
1961
+ # "timestamp": 1738065303708,
1962
+ # "mark_price": "102740.137375457314192317",
1963
+ # "index_price": "102741.553409299981533184",
1964
+ # "trade_price": "102700.6",
1965
+ # "trade_amount": "0.01",
1966
+ # "liquidity_role": "taker",
1967
+ # "realized_pnl": "0",
1968
+ # "realized_pnl_excl_fees": "0",
1969
+ # "is_transfer": False,
1970
+ # "tx_status": "settled",
1971
+ # "trade_fee": "1.127415534092999815",
1972
+ # "tx_hash": "0xc55df1f07330faf86579bd8a6385391fbe9e73089301149d8550e9d29c9ead74",
1973
+ # "transaction_id": "e18b9426-3fa5-41bb-99d3-8b54fb4d51bb"
1974
+ # }
1975
+ # ],
1976
+ # "pagination": {
1977
+ # "num_pages": 1,
1978
+ # "count": 1
1979
+ # }
1980
+ # },
1981
+ # "id": "a16f798c-a121-44e2-b77e-c38a063f8a99"
1982
+ # }
1983
+ #
1984
+ result = self.safe_dict(response, 'result', {})
1985
+ trades = self.safe_list(result, 'trades', [])
1986
+ return self.parse_trades(trades, market, since, limit, params)
1987
+
1988
+ async def fetch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1989
+ """
1990
+ fetch all trades made by the user
1991
+
1992
+ https://docs.derive.xyz/reference/post_private-get-trade-history
1993
+
1994
+ :param str symbol: unified market symbol
1995
+ :param int [since]: the earliest time in ms to fetch trades for
1996
+ :param int [limit]: the maximum number of trades structures to retrieve
1997
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1998
+ :param boolean [params.paginate]: set to True if you want to fetch trades with pagination
1999
+ :param str [params.subaccount_id]: *required* the subaccount id
2000
+ :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
2001
+ """
2002
+ await self.load_markets()
2003
+ paginate = False
2004
+ paginate, params = self.handle_option_and_params(params, 'fetchMyTrades', 'paginate')
2005
+ if paginate:
2006
+ return await self.fetch_paginated_call_incremental('fetchMyTrades', symbol, since, limit, params, 'page', 500)
2007
+ subaccountId = None
2008
+ subaccountId, params = self.handle_derive_subaccount_id('fetchMyTrades', params)
2009
+ request: dict = {
2010
+ 'subaccount_id': subaccountId,
2011
+ }
2012
+ market: Market = None
2013
+ if symbol is not None:
2014
+ market = self.market(symbol)
2015
+ request['instrument_name'] = market['id']
2016
+ if limit is not None:
2017
+ request['page_size'] = limit
2018
+ if since is not None:
2019
+ request['from_timestamp'] = since
2020
+ response = await self.privatePostGetTradeHistory(self.extend(request, params))
2021
+ #
2022
+ # {
2023
+ # "result": {
2024
+ # "subaccount_id": 130837,
2025
+ # "trades": [
2026
+ # {
2027
+ # "subaccount_id": 130837,
2028
+ # "order_id": "30c48194-8d48-43ac-ad00-0d5ba29eddc9",
2029
+ # "instrument_name": "BTC-PERP",
2030
+ # "direction": "sell",
2031
+ # "label": "test1234",
2032
+ # "quote_id": null,
2033
+ # "trade_id": "f8a30740-488c-4c2d-905d-e17057bafde1",
2034
+ # "timestamp": 1738065303708,
2035
+ # "mark_price": "102740.137375457314192317",
2036
+ # "index_price": "102741.553409299981533184",
2037
+ # "trade_price": "102700.6",
2038
+ # "trade_amount": "0.01",
2039
+ # "liquidity_role": "taker",
2040
+ # "realized_pnl": "0",
2041
+ # "realized_pnl_excl_fees": "0",
2042
+ # "is_transfer": False,
2043
+ # "tx_status": "settled",
2044
+ # "trade_fee": "1.127415534092999815",
2045
+ # "tx_hash": "0xc55df1f07330faf86579bd8a6385391fbe9e73089301149d8550e9d29c9ead74",
2046
+ # "transaction_id": "e18b9426-3fa5-41bb-99d3-8b54fb4d51bb"
2047
+ # }
2048
+ # ],
2049
+ # "pagination": {
2050
+ # "num_pages": 1,
2051
+ # "count": 1
2052
+ # }
2053
+ # },
2054
+ # "id": "a16f798c-a121-44e2-b77e-c38a063f8a99"
2055
+ # }
2056
+ #
2057
+ result = self.safe_dict(response, 'result', {})
2058
+ page = self.safe_integer(params, 'page')
2059
+ if page is not None:
2060
+ pagination = self.safe_dict(result, 'pagination')
2061
+ currentPage = self.safe_integer(pagination, 'num_pages')
2062
+ if page > currentPage:
2063
+ return []
2064
+ trades = self.safe_list(result, 'trades', [])
2065
+ return self.parse_trades(trades, market, since, limit, params)
2066
+
2067
+ async def fetch_positions(self, symbols: Strings = None, params={}) -> List[Position]:
2068
+ """
2069
+ fetch all open positions
2070
+
2071
+ https://docs.derive.xyz/reference/post_private-get-positions
2072
+
2073
+ :param str[] [symbols]: not used by kraken fetchPositions()
2074
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2075
+ :param str [params.subaccount_id]: *required* the subaccount id
2076
+ :returns dict[]: a list of `position structure <https://docs.ccxt.com/#/?id=position-structure>`
2077
+ """
2078
+ await self.load_markets()
2079
+ subaccountId = None
2080
+ subaccountId, params = self.handle_derive_subaccount_id('fetchPositions', params)
2081
+ request: dict = {
2082
+ 'subaccount_id': subaccountId,
2083
+ }
2084
+ params = self.omit(params, ['subaccount_id'])
2085
+ response = await self.privatePostGetPositions(self.extend(request, params))
2086
+ #
2087
+ # {
2088
+ # "result": {
2089
+ # "subaccount_id": 130837,
2090
+ # "positions": [
2091
+ # {
2092
+ # "instrument_type": "perp",
2093
+ # "instrument_name": "BTC-PERP",
2094
+ # "amount": "-0.02",
2095
+ # "average_price": "102632.9105389869500088",
2096
+ # "realized_pnl": "0",
2097
+ # "unrealized_pnl": "-2.6455959784245548835819950103759765625",
2098
+ # "total_fees": "2.255789220260999824",
2099
+ # "average_price_excl_fees": "102745.7",
2100
+ # "realized_pnl_excl_fees": "0",
2101
+ # "unrealized_pnl_excl_fees": "-0.3898067581635550595819950103759765625",
2102
+ # "net_settlements": "-4.032902047219498639",
2103
+ # "cumulative_funding": "-0.004677736347850093",
2104
+ # "pending_funding": "0",
2105
+ # "mark_price": "102765.190337908177752979099750518798828125",
2106
+ # "index_price": "102767.657193800017641472",
2107
+ # "delta": "1",
2108
+ # "gamma": "0",
2109
+ # "vega": "0",
2110
+ # "theta": "0",
2111
+ # "mark_value": "1.38730606879471451975405216217041015625",
2112
+ # "maintenance_margin": "-101.37788426911356509663164615631103515625",
2113
+ # "initial_margin": "-132.2074413704858670826070010662078857421875",
2114
+ # "open_orders_margin": "264.116085900726830004714429378509521484375",
2115
+ # "leverage": "8.6954476205089299495699106539379941746377322586618",
2116
+ # "liquidation_price": "109125.705451984322280623018741607666015625",
2117
+ # "creation_timestamp": 1738065303840
2118
+ # }
2119
+ # ]
2120
+ # },
2121
+ # "id": "167350f1-d9fc-41d4-9797-1c78f83fda8e"
2122
+ # }
2123
+ #
2124
+ result = self.safe_dict(response, 'result', {})
2125
+ positions = self.safe_list(result, 'positions', [])
2126
+ return self.parse_positions(positions, symbols)
2127
+
2128
+ def parse_position(self, position: dict, market: Market = None):
2129
+ #
2130
+ # {
2131
+ # "instrument_type": "perp",
2132
+ # "instrument_name": "BTC-PERP",
2133
+ # "amount": "-0.02",
2134
+ # "average_price": "102632.9105389869500088",
2135
+ # "realized_pnl": "0",
2136
+ # "unrealized_pnl": "-2.6455959784245548835819950103759765625",
2137
+ # "total_fees": "2.255789220260999824",
2138
+ # "average_price_excl_fees": "102745.7",
2139
+ # "realized_pnl_excl_fees": "0",
2140
+ # "unrealized_pnl_excl_fees": "-0.3898067581635550595819950103759765625",
2141
+ # "net_settlements": "-4.032902047219498639",
2142
+ # "cumulative_funding": "-0.004677736347850093",
2143
+ # "pending_funding": "0",
2144
+ # "mark_price": "102765.190337908177752979099750518798828125",
2145
+ # "index_price": "102767.657193800017641472",
2146
+ # "delta": "1",
2147
+ # "gamma": "0",
2148
+ # "vega": "0",
2149
+ # "theta": "0",
2150
+ # "mark_value": "1.38730606879471451975405216217041015625",
2151
+ # "maintenance_margin": "-101.37788426911356509663164615631103515625",
2152
+ # "initial_margin": "-132.2074413704858670826070010662078857421875",
2153
+ # "open_orders_margin": "264.116085900726830004714429378509521484375",
2154
+ # "leverage": "8.6954476205089299495699106539379941746377322586618",
2155
+ # "liquidation_price": "109125.705451984322280623018741607666015625",
2156
+ # "creation_timestamp": 1738065303840
2157
+ # }
2158
+ #
2159
+ contract = self.safe_string(position, 'instrument_name')
2160
+ market = self.safe_market(contract, market)
2161
+ size = self.safe_string(position, 'amount')
2162
+ side: Str = None
2163
+ if Precise.string_gt(size, '0'):
2164
+ side = 'long'
2165
+ else:
2166
+ side = 'short'
2167
+ contractSize = self.safe_string(market, 'contractSize')
2168
+ markPrice = self.safe_string(position, 'mark_price')
2169
+ timestamp = self.safe_integer(position, 'creation_timestamp')
2170
+ unrealisedPnl = self.safe_string(position, 'unrealized_pnl')
2171
+ size = Precise.string_abs(size)
2172
+ notional = Precise.string_mul(size, markPrice)
2173
+ return self.safe_position({
2174
+ 'info': position,
2175
+ 'id': None,
2176
+ 'symbol': self.safe_string(market, 'symbol'),
2177
+ 'timestamp': timestamp,
2178
+ 'datetime': self.iso8601(timestamp),
2179
+ 'lastUpdateTimestamp': None,
2180
+ 'initialMargin': self.safe_string(position, 'initial_margin'),
2181
+ 'initialMarginPercentage': None,
2182
+ 'maintenanceMargin': self.safe_string(position, 'maintenance_margin'),
2183
+ 'maintenanceMarginPercentage': None,
2184
+ 'entryPrice': None,
2185
+ 'notional': self.parse_number(notional),
2186
+ 'leverage': self.safe_number(position, 'leverage'),
2187
+ 'unrealizedPnl': self.parse_number(unrealisedPnl),
2188
+ 'contracts': self.parse_number(size),
2189
+ 'contractSize': self.parse_number(contractSize),
2190
+ 'marginRatio': None,
2191
+ 'liquidationPrice': self.safe_number(position, 'liquidation_price'),
2192
+ 'markPrice': self.parse_number(markPrice),
2193
+ 'lastPrice': None,
2194
+ 'collateral': None,
2195
+ 'marginMode': None,
2196
+ 'side': side,
2197
+ 'percentage': None,
2198
+ 'hedged': None,
2199
+ 'stopLossPrice': None,
2200
+ 'takeProfitPrice': None,
2201
+ })
2202
+
2203
+ async def fetch_funding_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
2204
+ """
2205
+ fetch the history of funding payments paid and received on self account
2206
+
2207
+ https://docs.derive.xyz/reference/post_private-get-funding-history
2208
+
2209
+ :param str [symbol]: unified market symbol
2210
+ :param int [since]: the earliest time in ms to fetch funding history for
2211
+ :param int [limit]: the maximum number of funding history structures to retrieve
2212
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2213
+ :param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
2214
+ :returns dict: a `funding history structure <https://docs.ccxt.com/#/?id=funding-history-structure>`
2215
+ """
2216
+ await self.load_markets()
2217
+ paginate = False
2218
+ paginate, params = self.handle_option_and_params(params, 'fetchFundingHistory', 'paginate')
2219
+ if paginate:
2220
+ return await self.fetch_paginated_call_incremental('fetchFundingHistory', symbol, since, limit, params, 'page', 500)
2221
+ subaccountId = None
2222
+ subaccountId, params = self.handle_derive_subaccount_id('fetchFundingHistory', params)
2223
+ request: dict = {
2224
+ 'subaccount_id': subaccountId,
2225
+ }
2226
+ market: Market = None
2227
+ if symbol is not None:
2228
+ market = self.market(symbol)
2229
+ request['instrument_name'] = market['id']
2230
+ if since is not None:
2231
+ request['start_timestamp'] = since
2232
+ if limit is not None:
2233
+ request['page_size'] = limit
2234
+ response = await self.privatePostGetFundingHistory(self.extend(request, params))
2235
+ #
2236
+ # {
2237
+ # "result": {
2238
+ # "events": [
2239
+ # {
2240
+ # "instrument_name": "BTC-PERP",
2241
+ # "timestamp": 1738066618272,
2242
+ # "funding": "-0.004677736347850093",
2243
+ # "pnl": "-0.944081615774632967"
2244
+ # },
2245
+ # {
2246
+ # "instrument_name": "BTC-PERP",
2247
+ # "timestamp": 1738066617964,
2248
+ # "funding": "0",
2249
+ # "pnl": "-0.437556413479249408"
2250
+ # },
2251
+ # {
2252
+ # "instrument_name": "BTC-PERP",
2253
+ # "timestamp": 1738065307565,
2254
+ # "funding": "0",
2255
+ # "pnl": "-0.39547479770461644"
2256
+ # }
2257
+ # ],
2258
+ # "pagination": {
2259
+ # "num_pages": 1,
2260
+ # "count": 3
2261
+ # }
2262
+ # },
2263
+ # "id": "524b817f-2108-467f-8795-511066f4acec"
2264
+ # }
2265
+ #
2266
+ result = self.safe_dict(response, 'result', {})
2267
+ page = self.safe_integer(params, 'page')
2268
+ if page is not None:
2269
+ pagination = self.safe_dict(result, 'pagination')
2270
+ currentPage = self.safe_integer(pagination, 'num_pages')
2271
+ if page > currentPage:
2272
+ return []
2273
+ events = self.safe_list(result, 'events', [])
2274
+ return self.parse_incomes(events, market, since, limit)
2275
+
2276
+ def parse_income(self, income, market: Market = None):
2277
+ #
2278
+ # {
2279
+ # "instrument_name": "BTC-PERP",
2280
+ # "timestamp": 1738065307565,
2281
+ # "funding": "0",
2282
+ # "pnl": "-0.39547479770461644"
2283
+ # }
2284
+ #
2285
+ marketId = self.safe_string(income, 'instrument_name')
2286
+ symbol = self.safe_symbol(marketId, market)
2287
+ rate = self.safe_string(income, 'funding')
2288
+ code = self.safe_currency_code('USDC')
2289
+ timestamp = self.safe_integer(income, 'timestamp')
2290
+ return {
2291
+ 'info': income,
2292
+ 'symbol': symbol,
2293
+ 'code': code,
2294
+ 'timestamp': timestamp,
2295
+ 'datetime': self.iso8601(timestamp),
2296
+ 'id': None,
2297
+ 'amount': None,
2298
+ 'rate': rate,
2299
+ }
2300
+
2301
+ async def fetch_balance(self, params={}) -> Balances:
2302
+ """
2303
+ query for balance and get the amount of funds available for trading or funds locked in orders
2304
+
2305
+ https://docs.derive.xyz/reference/post_private-get-all-portfolios
2306
+
2307
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2308
+ :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
2309
+ """
2310
+ await self.load_markets()
2311
+ deriveWalletAddress = None
2312
+ deriveWalletAddress, params = self.handle_derive_wallet_address('fetchBalance', params)
2313
+ request = {
2314
+ 'wallet': deriveWalletAddress,
2315
+ }
2316
+ response = await self.privatePostGetAllPortfolios(self.extend(request, params))
2317
+ #
2318
+ # {
2319
+ # "result": [{
2320
+ # "subaccount_id": 130837,
2321
+ # "label": "",
2322
+ # "currency": "all",
2323
+ # "margin_type": "SM",
2324
+ # "is_under_liquidation": False,
2325
+ # "positions_value": "0",
2326
+ # "collaterals_value": "318.0760325000001103035174310207366943359375",
2327
+ # "subaccount_value": "318.0760325000001103035174310207366943359375",
2328
+ # "positions_maintenance_margin": "0",
2329
+ # "positions_initial_margin": "0",
2330
+ # "collaterals_maintenance_margin": "238.557024375000082727638073265552520751953125",
2331
+ # "collaterals_initial_margin": "190.845619500000083235136116854846477508544921875",
2332
+ # "maintenance_margin": "238.557024375000082727638073265552520751953125",
2333
+ # "initial_margin": "190.845619500000083235136116854846477508544921875",
2334
+ # "open_orders_margin": "0",
2335
+ # "projected_margin_change": "0",
2336
+ # "open_orders": [],
2337
+ # "positions": [],
2338
+ # "collaterals": [
2339
+ # {
2340
+ # "asset_type": "erc20",
2341
+ # "asset_name": "ETH",
2342
+ # "currency": "ETH",
2343
+ # "amount": "0.1",
2344
+ # "mark_price": "3180.760325000000438272",
2345
+ # "mark_value": "318.0760325000001103035174310207366943359375",
2346
+ # "cumulative_interest": "0",
2347
+ # "pending_interest": "0",
2348
+ # "initial_margin": "190.845619500000083235136116854846477508544921875",
2349
+ # "maintenance_margin": "238.557024375000082727638073265552520751953125",
2350
+ # "realized_pnl": "0",
2351
+ # "average_price": "3184.891931",
2352
+ # "unrealized_pnl": "-0.413161",
2353
+ # "total_fees": "0",
2354
+ # "average_price_excl_fees": "3184.891931",
2355
+ # "realized_pnl_excl_fees": "0",
2356
+ # "unrealized_pnl_excl_fees": "-0.413161",
2357
+ # "open_orders_margin": "0",
2358
+ # "creation_timestamp": 1736860533493
2359
+ # }
2360
+ # ]
2361
+ # }],
2362
+ # "id": "27b9a64e-3379-4ce6-a126-9fb941c4a970"
2363
+ # }
2364
+ #
2365
+ result = self.safe_list(response, 'result')
2366
+ return self.parse_balance(result)
2367
+
2368
+ def parse_balance(self, response) -> Balances:
2369
+ result: dict = {
2370
+ 'info': response,
2371
+ }
2372
+ for i in range(0, len(response)):
2373
+ subaccount = response[i]
2374
+ collaterals = self.safe_list(subaccount, 'collaterals', [])
2375
+ for j in range(0, len(collaterals)):
2376
+ balance = collaterals[j]
2377
+ code = self.safe_currency_code(self.safe_string(balance, 'currency'))
2378
+ account = self.safe_dict(result, code)
2379
+ if account is None:
2380
+ account = self.account()
2381
+ account['total'] = self.safe_string(balance, 'amount')
2382
+ else:
2383
+ amount = self.safe_string(balance, 'amount')
2384
+ account['total'] = Precise.string_add(account['total'], amount)
2385
+ result[code] = account
2386
+ return self.safe_balance(result)
2387
+
2388
+ async def fetch_deposits(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
2389
+ """
2390
+ fetch all deposits made to an account
2391
+
2392
+ https://docs.derive.xyz/reference/post_private-get-deposit-history
2393
+
2394
+ :param str code: unified currency code
2395
+ :param int [since]: the earliest time in ms to fetch deposits for
2396
+ :param int [limit]: the maximum number of deposits structures to retrieve
2397
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2398
+ :param str [params.subaccount_id]: *required* the subaccount id
2399
+ :returns dict[]: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
2400
+ """
2401
+ await self.load_markets()
2402
+ subaccountId = None
2403
+ subaccountId, params = self.handle_derive_subaccount_id('fetchDeposits', params)
2404
+ request: dict = {
2405
+ 'subaccount_id': subaccountId,
2406
+ }
2407
+ if since is not None:
2408
+ request['start_timestamp'] = since
2409
+ response = await self.privatePostGetDepositHistory(self.extend(request, params))
2410
+ #
2411
+ # {
2412
+ # "result": {
2413
+ # "events": [
2414
+ # {
2415
+ # "timestamp": 1736860533599,
2416
+ # "transaction_id": "f2069395-ec00-49f5-925a-87202a5d240f",
2417
+ # "asset": "ETH",
2418
+ # "amount": "0.1",
2419
+ # "tx_status": "settled",
2420
+ # "tx_hash": "0xeda21a315c59302a19c42049b4cef05a10b685302b6cc3edbaf49102d91166d4",
2421
+ # "error_log": {}
2422
+ # }
2423
+ # ]
2424
+ # },
2425
+ # "id": "ceebc730-22ab-40cd-9941-33ceb2a74389"
2426
+ # }
2427
+ #
2428
+ currency = self.safe_currency(code)
2429
+ result = self.safe_dict(response, 'result', {})
2430
+ events = self.safe_list(result, 'events')
2431
+ return self.parse_transactions(events, currency, since, limit, params)
2432
+
2433
+ async def fetch_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
2434
+ """
2435
+ fetch all withdrawals made from an account
2436
+
2437
+ https://docs.derive.xyz/reference/post_private-get-withdrawal-history
2438
+
2439
+ :param str code: unified currency code
2440
+ :param int [since]: the earliest time in ms to fetch withdrawals for
2441
+ :param int [limit]: the maximum number of withdrawals structures to retrieve
2442
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2443
+ :param str [params.subaccount_id]: *required* the subaccount id
2444
+ :returns dict[]: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
2445
+ """
2446
+ await self.load_markets()
2447
+ subaccountId = None
2448
+ subaccountId, params = self.handle_derive_subaccount_id('fetchWithdrawals', params)
2449
+ request: dict = {
2450
+ 'subaccount_id': subaccountId,
2451
+ }
2452
+ if since is not None:
2453
+ request['start_timestamp'] = since
2454
+ response = await self.privatePostGetWithdrawalHistory(self.extend(request, params))
2455
+ #
2456
+ # {
2457
+ # "result": {
2458
+ # "events": [
2459
+ # {
2460
+ # "timestamp": 1736860533599,
2461
+ # "transaction_id": "f2069395-ec00-49f5-925a-87202a5d240f",
2462
+ # "asset": "ETH",
2463
+ # "amount": "0.1",
2464
+ # "tx_status": "settled",
2465
+ # "tx_hash": "0xeda21a315c59302a19c42049b4cef05a10b685302b6cc3edbaf49102d91166d4",
2466
+ # "error_log": {}
2467
+ # }
2468
+ # ]
2469
+ # },
2470
+ # "id": "ceebc730-22ab-40cd-9941-33ceb2a74389"
2471
+ # }
2472
+ #
2473
+ currency = self.safe_currency(code)
2474
+ result = self.safe_dict(response, 'result', {})
2475
+ events = self.safe_list(result, 'events')
2476
+ return self.parse_transactions(events, currency, since, limit, params)
2477
+
2478
+ def parse_transaction(self, transaction: dict, currency: Currency = None) -> Transaction:
2479
+ #
2480
+ # {
2481
+ # "timestamp": 1736860533599,
2482
+ # "transaction_id": "f2069395-ec00-49f5-925a-87202a5d240f",
2483
+ # "asset": "ETH",
2484
+ # "amount": "0.1",
2485
+ # "tx_status": "settled",
2486
+ # "tx_hash": "0xeda21a315c59302a19c42049b4cef05a10b685302b6cc3edbaf49102d91166d4",
2487
+ # "error_log": {}
2488
+ # }
2489
+ #
2490
+ code = self.safe_string(transaction, 'asset')
2491
+ timestamp = self.safe_integer(transaction, 'timestamp')
2492
+ txId = self.safe_string(transaction, 'tx_hash')
2493
+ if txId == '0x0':
2494
+ txId = None
2495
+ return {
2496
+ 'info': transaction,
2497
+ 'id': None,
2498
+ 'txid': txId,
2499
+ 'timestamp': timestamp,
2500
+ 'datetime': self.iso8601(timestamp),
2501
+ 'address': None,
2502
+ 'addressFrom': None,
2503
+ 'addressTo': None,
2504
+ 'tag': None,
2505
+ 'tagFrom': None,
2506
+ 'tagTo': None,
2507
+ 'type': None,
2508
+ 'amount': self.safe_number(transaction, 'amount'),
2509
+ 'currency': code,
2510
+ 'status': self.parse_transaction_status(self.safe_string(transaction, 'tx_status')),
2511
+ 'updated': None,
2512
+ 'comment': None,
2513
+ 'internal': None,
2514
+ 'fee': None,
2515
+ 'network': None,
2516
+ }
2517
+
2518
+ def parse_transaction_status(self, status: Str):
2519
+ statuses: dict = {
2520
+ 'settled': 'ok',
2521
+ 'reverted': 'failed',
2522
+ }
2523
+ return self.safe_string(statuses, status, status)
2524
+
2525
+ def handle_derive_subaccount_id(self, methodName: str, params: dict):
2526
+ derivesubAccountId = None
2527
+ derivesubAccountId, params = self.handle_option_and_params(params, methodName, 'subaccount_id')
2528
+ if (derivesubAccountId is not None) and (derivesubAccountId != ''):
2529
+ self.options['subaccount_id'] = derivesubAccountId # saving in options
2530
+ return [derivesubAccountId, params]
2531
+ optionsWallet = self.safe_string(self.options, 'subaccount_id')
2532
+ if optionsWallet is not None:
2533
+ return [optionsWallet, params]
2534
+ raise ArgumentsRequired(self.id + ' ' + methodName + '() requires a subaccount_id parameter inside \'params\' or exchange.options[\'subaccount_id\']=ID.')
2535
+
2536
+ def handle_derive_wallet_address(self, methodName: str, params: dict):
2537
+ deriveWalletAddress = None
2538
+ deriveWalletAddress, params = self.handle_option_and_params(params, methodName, 'deriveWalletAddress')
2539
+ if (deriveWalletAddress is not None) and (deriveWalletAddress != ''):
2540
+ self.options['deriveWalletAddress'] = deriveWalletAddress # saving in options
2541
+ return [deriveWalletAddress, params]
2542
+ optionsWallet = self.safe_string(self.options, 'deriveWalletAddress')
2543
+ if optionsWallet is not None:
2544
+ return [optionsWallet, params]
2545
+ raise ArgumentsRequired(self.id + ' ' + methodName + '() requires a deriveWalletAddress parameter inside \'params\' or exchange.options[\'deriveWalletAddress\'] = ADDRESS, the address can find in HOME => Developers tab.')
2546
+
2547
+ def handle_errors(self, httpCode: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
2548
+ if not response:
2549
+ return None # fallback to default error handler
2550
+ error = self.safe_dict(response, 'error')
2551
+ if error is not None:
2552
+ errorCode = self.safe_string(error, 'code')
2553
+ feedback = self.id + ' ' + self.json(response)
2554
+ self.throw_broadly_matched_exception(self.exceptions['broad'], body, feedback)
2555
+ self.throw_exactly_matched_exception(self.exceptions['exact'], errorCode, feedback)
2556
+ raise ExchangeError(feedback)
2557
+ return None
2558
+
2559
+ def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
2560
+ url = self.urls['api'][api] + '/' + path
2561
+ if method == 'POST':
2562
+ headers = {
2563
+ 'Content-Type': 'application/json',
2564
+ }
2565
+ if api == 'private':
2566
+ now = str(self.milliseconds())
2567
+ signature = self.sign_message(now, self.privateKey)
2568
+ headers['X-LyraWallet'] = self.safe_string(self.options, 'deriveWalletAddress')
2569
+ headers['X-LyraTimestamp'] = now
2570
+ headers['X-LyraSignature'] = signature
2571
+ body = self.json(params)
2572
+ return {'url': url, 'method': method, 'body': body, 'headers': headers}