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