ccxt 4.3.69 → 4.3.71

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 (187) hide show
  1. package/README.md +7 -6
  2. package/dist/ccxt.browser.min.js +13 -10
  3. package/dist/cjs/ccxt.js +8 -1
  4. package/dist/cjs/src/abstract/paradex.js +9 -0
  5. package/dist/cjs/src/ascendex.js +1 -1
  6. package/dist/cjs/src/base/Exchange.js +55 -0
  7. package/dist/cjs/src/binance.js +1 -1
  8. package/dist/cjs/src/blofin.js +63 -6
  9. package/dist/cjs/src/bybit.js +1 -1
  10. package/dist/cjs/src/coinbaseinternational.js +168 -2
  11. package/dist/cjs/src/cryptocom.js +9 -1
  12. package/dist/cjs/src/hitbtc.js +1 -1
  13. package/dist/cjs/src/paradex.js +2075 -0
  14. package/dist/cjs/src/poloniex.js +1 -0
  15. package/dist/cjs/src/pro/bequant.js +4 -0
  16. package/dist/cjs/src/pro/blofin.js +665 -0
  17. package/dist/cjs/src/pro/coinbaseinternational.js +154 -9
  18. package/dist/cjs/src/pro/cryptocom.js +3 -1
  19. package/dist/cjs/src/pro/hitbtc.js +26 -8
  20. package/dist/cjs/src/pro/okx.js +7 -0
  21. package/dist/cjs/src/pro/paradex.js +365 -0
  22. package/dist/cjs/src/pro/poloniex.js +37 -12
  23. package/dist/cjs/src/pro/woo.js +5 -4
  24. package/dist/cjs/src/static_dependencies/noble-curves/abstract/poseidon.js +100 -0
  25. package/dist/cjs/src/static_dependencies/noble-curves/abstract/weierstrass.js +1 -0
  26. package/dist/cjs/src/static_dependencies/scure-starknet/index.js +284 -0
  27. package/dist/cjs/src/static_dependencies/starknet/constants.js +60 -0
  28. package/dist/cjs/src/static_dependencies/starknet/types/calldata.js +26 -0
  29. package/dist/cjs/src/static_dependencies/starknet/types/lib/contract/abi.js +8 -0
  30. package/dist/cjs/src/static_dependencies/starknet/types/lib/contract/index.js +13 -0
  31. package/dist/cjs/src/static_dependencies/starknet/types/lib/index.js +56 -0
  32. package/dist/cjs/src/static_dependencies/starknet/types/typedData.js +19 -0
  33. package/dist/cjs/src/static_dependencies/starknet/utils/assert.js +15 -0
  34. package/dist/cjs/src/static_dependencies/starknet/utils/cairoDataTypes/felt.js +44 -0
  35. package/dist/cjs/src/static_dependencies/starknet/utils/cairoDataTypes/uint256.js +122 -0
  36. package/dist/cjs/src/static_dependencies/starknet/utils/cairoDataTypes/uint512.js +137 -0
  37. package/dist/cjs/src/static_dependencies/starknet/utils/calldata/byteArray.js +61 -0
  38. package/dist/cjs/src/static_dependencies/starknet/utils/calldata/cairo.js +218 -0
  39. package/dist/cjs/src/static_dependencies/starknet/utils/calldata/enum/CairoCustomEnum.js +57 -0
  40. package/dist/cjs/src/static_dependencies/starknet/utils/calldata/enum/CairoOption.js +64 -0
  41. package/dist/cjs/src/static_dependencies/starknet/utils/calldata/enum/CairoResult.js +63 -0
  42. package/dist/cjs/src/static_dependencies/starknet/utils/calldata/formatter.js +66 -0
  43. package/dist/cjs/src/static_dependencies/starknet/utils/calldata/index.js +281 -0
  44. package/dist/cjs/src/static_dependencies/starknet/utils/calldata/parser/index.js +33 -0
  45. package/dist/cjs/src/static_dependencies/starknet/utils/calldata/parser/parser-0-1.1.0.js +37 -0
  46. package/dist/cjs/src/static_dependencies/starknet/utils/calldata/parser/parser-2.0.0.js +40 -0
  47. package/dist/cjs/src/static_dependencies/starknet/utils/calldata/propertyOrder.js +156 -0
  48. package/dist/cjs/src/static_dependencies/starknet/utils/calldata/requestParser.js +250 -0
  49. package/dist/cjs/src/static_dependencies/starknet/utils/calldata/responseParser.js +215 -0
  50. package/dist/cjs/src/static_dependencies/starknet/utils/calldata/tuple.js +112 -0
  51. package/dist/cjs/src/static_dependencies/starknet/utils/calldata/validate.js +206 -0
  52. package/dist/cjs/src/static_dependencies/starknet/utils/encode.js +58 -0
  53. package/dist/cjs/src/static_dependencies/starknet/utils/hash/classHash.js +57 -0
  54. package/dist/cjs/src/static_dependencies/starknet/utils/merkle.js +76 -0
  55. package/dist/cjs/src/static_dependencies/starknet/utils/num.js +92 -0
  56. package/dist/cjs/src/static_dependencies/starknet/utils/selector.js +48 -0
  57. package/dist/cjs/src/static_dependencies/starknet/utils/shortString.js +101 -0
  58. package/dist/cjs/src/static_dependencies/starknet/utils/typedData.js +334 -0
  59. package/dist/cjs/src/woo.js +4 -2
  60. package/js/ccxt.d.ts +11 -2
  61. package/js/ccxt.js +8 -2
  62. package/js/src/abstract/coinbaseinternational.d.ts +1 -1
  63. package/js/src/abstract/paradex.d.ts +43 -0
  64. package/js/src/abstract/paradex.js +11 -0
  65. package/js/src/ascendex.js +1 -1
  66. package/js/src/base/Exchange.d.ts +8 -0
  67. package/js/src/base/Exchange.js +51 -0
  68. package/js/src/binance.js +1 -1
  69. package/js/src/blofin.d.ts +1 -1
  70. package/js/src/blofin.js +63 -6
  71. package/js/src/bybit.js +1 -1
  72. package/js/src/coinbaseinternational.d.ts +6 -1
  73. package/js/src/coinbaseinternational.js +168 -2
  74. package/js/src/cryptocom.js +10 -2
  75. package/js/src/hitbtc.js +1 -1
  76. package/js/src/paradex.d.ts +76 -0
  77. package/js/src/paradex.js +2075 -0
  78. package/js/src/poloniex.js +1 -0
  79. package/js/src/pro/bequant.js +4 -0
  80. package/js/src/pro/blofin.d.ts +39 -0
  81. package/js/src/pro/blofin.js +668 -0
  82. package/js/src/pro/coinbaseinternational.d.ts +5 -1
  83. package/js/src/pro/coinbaseinternational.js +155 -10
  84. package/js/src/pro/cryptocom.js +4 -2
  85. package/js/src/pro/hitbtc.d.ts +1 -1
  86. package/js/src/pro/hitbtc.js +26 -8
  87. package/js/src/pro/okx.js +7 -0
  88. package/js/src/pro/paradex.d.ts +15 -0
  89. package/js/src/pro/paradex.js +366 -0
  90. package/js/src/pro/poloniex.js +37 -12
  91. package/js/src/pro/woo.js +5 -4
  92. package/js/src/static_dependencies/noble-curves/abstract/weierstrass.d.ts +24 -0
  93. package/js/src/static_dependencies/noble-curves/abstract/weierstrass.js +1 -1
  94. package/js/src/static_dependencies/scure-starknet/index.d.ts +79 -0
  95. package/js/src/static_dependencies/scure-starknet/index.js +323 -0
  96. package/js/src/static_dependencies/starknet/constants.d.ts +61 -0
  97. package/js/src/static_dependencies/starknet/constants.js +67 -0
  98. package/js/src/static_dependencies/starknet/index.d.ts +7 -0
  99. package/js/src/static_dependencies/starknet/index.js +50 -0
  100. package/js/src/static_dependencies/starknet/types/cairoEnum.d.ts +2 -0
  101. package/js/src/static_dependencies/starknet/types/cairoEnum.js +7 -0
  102. package/js/src/static_dependencies/starknet/types/calldata.d.ts +19 -0
  103. package/js/src/static_dependencies/starknet/types/calldata.js +28 -0
  104. package/js/src/static_dependencies/starknet/types/index.d.ts +13 -0
  105. package/js/src/static_dependencies/starknet/types/index.js +16 -0
  106. package/js/src/static_dependencies/starknet/types/lib/contract/abi.d.ts +71 -0
  107. package/js/src/static_dependencies/starknet/types/lib/contract/abi.js +13 -0
  108. package/js/src/static_dependencies/starknet/types/lib/contract/index.d.ts +24 -0
  109. package/js/src/static_dependencies/starknet/types/lib/contract/index.js +16 -0
  110. package/js/src/static_dependencies/starknet/types/lib/contract/legacy.d.ts +33 -0
  111. package/js/src/static_dependencies/starknet/types/lib/contract/legacy.js +7 -0
  112. package/js/src/static_dependencies/starknet/types/lib/contract/sierra.d.ts +52 -0
  113. package/js/src/static_dependencies/starknet/types/lib/contract/sierra.js +7 -0
  114. package/js/src/static_dependencies/starknet/types/lib/index.d.ts +248 -0
  115. package/js/src/static_dependencies/starknet/types/lib/index.js +52 -0
  116. package/js/src/static_dependencies/starknet/types/typedData.d.ts +44 -0
  117. package/js/src/static_dependencies/starknet/types/typedData.js +19 -0
  118. package/js/src/static_dependencies/starknet/utils/address.d.ts +53 -0
  119. package/js/src/static_dependencies/starknet/utils/address.js +89 -0
  120. package/js/src/static_dependencies/starknet/utils/assert.d.ts +7 -0
  121. package/js/src/static_dependencies/starknet/utils/assert.js +17 -0
  122. package/js/src/static_dependencies/starknet/utils/cairoDataTypes/felt.d.ts +6 -0
  123. package/js/src/static_dependencies/starknet/utils/cairoDataTypes/felt.js +43 -0
  124. package/js/src/static_dependencies/starknet/utils/cairoDataTypes/uint256.d.ts +72 -0
  125. package/js/src/static_dependencies/starknet/utils/cairoDataTypes/uint256.js +117 -0
  126. package/js/src/static_dependencies/starknet/utils/cairoDataTypes/uint512.d.ts +76 -0
  127. package/js/src/static_dependencies/starknet/utils/cairoDataTypes/uint512.js +136 -0
  128. package/js/src/static_dependencies/starknet/utils/calldata/byteArray.d.ts +32 -0
  129. package/js/src/static_dependencies/starknet/utils/calldata/byteArray.js +59 -0
  130. package/js/src/static_dependencies/starknet/utils/calldata/cairo.d.ts +183 -0
  131. package/js/src/static_dependencies/starknet/utils/calldata/cairo.js +229 -0
  132. package/js/src/static_dependencies/starknet/utils/calldata/enum/CairoCustomEnum.d.ts +38 -0
  133. package/js/src/static_dependencies/starknet/utils/calldata/enum/CairoCustomEnum.js +57 -0
  134. package/js/src/static_dependencies/starknet/utils/calldata/enum/CairoOption.d.ts +35 -0
  135. package/js/src/static_dependencies/starknet/utils/calldata/enum/CairoOption.js +64 -0
  136. package/js/src/static_dependencies/starknet/utils/calldata/enum/CairoResult.d.ts +34 -0
  137. package/js/src/static_dependencies/starknet/utils/calldata/enum/CairoResult.js +63 -0
  138. package/js/src/static_dependencies/starknet/utils/calldata/enum/index.d.ts +3 -0
  139. package/js/src/static_dependencies/starknet/utils/calldata/enum/index.js +9 -0
  140. package/js/src/static_dependencies/starknet/utils/calldata/formatter.d.ts +9 -0
  141. package/js/src/static_dependencies/starknet/utils/calldata/formatter.js +67 -0
  142. package/js/src/static_dependencies/starknet/utils/calldata/index.d.ts +89 -0
  143. package/js/src/static_dependencies/starknet/utils/calldata/index.js +280 -0
  144. package/js/src/static_dependencies/starknet/utils/calldata/parser/index.d.ts +5 -0
  145. package/js/src/static_dependencies/starknet/utils/calldata/parser/index.js +30 -0
  146. package/js/src/static_dependencies/starknet/utils/calldata/parser/interface.d.ts +20 -0
  147. package/js/src/static_dependencies/starknet/utils/calldata/parser/interface.js +8 -0
  148. package/js/src/static_dependencies/starknet/utils/calldata/parser/parser-0-1.1.0.d.ts +24 -0
  149. package/js/src/static_dependencies/starknet/utils/calldata/parser/parser-0-1.1.0.js +36 -0
  150. package/js/src/static_dependencies/starknet/utils/calldata/parser/parser-2.0.0.d.ts +23 -0
  151. package/js/src/static_dependencies/starknet/utils/calldata/parser/parser-2.0.0.js +40 -0
  152. package/js/src/static_dependencies/starknet/utils/calldata/propertyOrder.d.ts +2 -0
  153. package/js/src/static_dependencies/starknet/utils/calldata/propertyOrder.js +155 -0
  154. package/js/src/static_dependencies/starknet/utils/calldata/requestParser.d.ts +11 -0
  155. package/js/src/static_dependencies/starknet/utils/calldata/requestParser.js +248 -0
  156. package/js/src/static_dependencies/starknet/utils/calldata/responseParser.d.ts +11 -0
  157. package/js/src/static_dependencies/starknet/utils/calldata/responseParser.js +214 -0
  158. package/js/src/static_dependencies/starknet/utils/calldata/tuple.d.ts +6 -0
  159. package/js/src/static_dependencies/starknet/utils/calldata/tuple.js +113 -0
  160. package/js/src/static_dependencies/starknet/utils/calldata/validate.d.ts +6 -0
  161. package/js/src/static_dependencies/starknet/utils/calldata/validate.js +208 -0
  162. package/js/src/static_dependencies/starknet/utils/encode.d.ts +207 -0
  163. package/js/src/static_dependencies/starknet/utils/encode.js +282 -0
  164. package/js/src/static_dependencies/starknet/utils/hash/classHash.d.ts +57 -0
  165. package/js/src/static_dependencies/starknet/utils/hash/classHash.js +224 -0
  166. package/js/src/static_dependencies/starknet/utils/hash/index.d.ts +6 -0
  167. package/js/src/static_dependencies/starknet/utils/hash/index.js +13 -0
  168. package/js/src/static_dependencies/starknet/utils/json.d.ts +24 -0
  169. package/js/src/static_dependencies/starknet/utils/json.js +43 -0
  170. package/js/src/static_dependencies/starknet/utils/merkle.d.ts +35 -0
  171. package/js/src/static_dependencies/starknet/utils/merkle.js +84 -0
  172. package/js/src/static_dependencies/starknet/utils/num.d.ts +182 -0
  173. package/js/src/static_dependencies/starknet/utils/num.js +244 -0
  174. package/js/src/static_dependencies/starknet/utils/selector.d.ts +48 -0
  175. package/js/src/static_dependencies/starknet/utils/selector.js +85 -0
  176. package/js/src/static_dependencies/starknet/utils/shortString.d.ts +57 -0
  177. package/js/src/static_dependencies/starknet/utils/shortString.js +96 -0
  178. package/js/src/static_dependencies/starknet/utils/starknetId.d.ts +113 -0
  179. package/js/src/static_dependencies/starknet/utils/starknetId.js +265 -0
  180. package/js/src/static_dependencies/starknet/utils/typedData.d.ts +54 -0
  181. package/js/src/static_dependencies/starknet/utils/typedData.js +321 -0
  182. package/js/src/static_dependencies/starknet/utils/uint256.d.ts +21 -0
  183. package/js/src/static_dependencies/starknet/utils/uint256.js +32 -0
  184. package/js/src/static_dependencies/starknet/utils/url.d.ts +29 -0
  185. package/js/src/static_dependencies/starknet/utils/url.js +70 -0
  186. package/js/src/woo.js +4 -2
  187. package/package.json +1 -1
@@ -0,0 +1,2075 @@
1
+ 'use strict';
2
+
3
+ require('../ccxt.js');
4
+ var paradex$1 = require('./abstract/paradex.js');
5
+ var errors = require('./base/errors.js');
6
+ var number = require('./base/functions/number.js');
7
+ var crypto = require('./base/functions/crypto.js');
8
+ var sha3 = require('./static_dependencies/noble-hashes/sha3.js');
9
+ var secp256k1 = require('./static_dependencies/noble-curves/secp256k1.js');
10
+ var Precise = require('./base/Precise.js');
11
+
12
+ // ---------------------------------------------------------------------------
13
+ // ---------------------------------------------------------------------------
14
+ /**
15
+ * @class paradex
16
+ * @augments Exchange
17
+ */
18
+ class paradex extends paradex$1 {
19
+ describe() {
20
+ return this.deepExtend(super.describe(), {
21
+ 'id': 'paradex',
22
+ 'name': 'Paradex',
23
+ 'countries': [],
24
+ 'version': 'v1',
25
+ 'rateLimit': 50,
26
+ 'certified': false,
27
+ 'pro': true,
28
+ 'dex': true,
29
+ 'has': {
30
+ 'CORS': undefined,
31
+ 'spot': false,
32
+ 'margin': false,
33
+ 'swap': true,
34
+ 'future': false,
35
+ 'option': false,
36
+ 'addMargin': false,
37
+ 'borrowCrossMargin': false,
38
+ 'borrowIsolatedMargin': false,
39
+ 'cancelAllOrders': true,
40
+ 'cancelAllOrdersAfter': false,
41
+ 'cancelOrder': false,
42
+ 'cancelOrders': false,
43
+ 'cancelOrdersForSymbols': false,
44
+ 'closeAllPositions': false,
45
+ 'closePosition': false,
46
+ 'createMarketBuyOrderWithCost': false,
47
+ 'createMarketOrderWithCost': false,
48
+ 'createMarketSellOrderWithCost': false,
49
+ 'createOrder': true,
50
+ 'createOrders': false,
51
+ 'createReduceOnlyOrder': false,
52
+ 'editOrder': false,
53
+ 'fetchAccounts': false,
54
+ 'fetchBalance': true,
55
+ 'fetchBorrowInterest': false,
56
+ 'fetchBorrowRateHistories': false,
57
+ 'fetchBorrowRateHistory': false,
58
+ 'fetchCanceledOrders': false,
59
+ 'fetchClosedOrders': false,
60
+ 'fetchCrossBorrowRate': false,
61
+ 'fetchCrossBorrowRates': false,
62
+ 'fetchCurrencies': false,
63
+ 'fetchDepositAddress': false,
64
+ 'fetchDepositAddresses': false,
65
+ 'fetchDeposits': true,
66
+ 'fetchDepositWithdrawFee': false,
67
+ 'fetchDepositWithdrawFees': false,
68
+ 'fetchFundingHistory': false,
69
+ 'fetchFundingRate': false,
70
+ 'fetchFundingRateHistory': false,
71
+ 'fetchFundingRates': false,
72
+ 'fetchIndexOHLCV': false,
73
+ 'fetchIsolatedBorrowRate': false,
74
+ 'fetchIsolatedBorrowRates': false,
75
+ 'fetchLedger': false,
76
+ 'fetchLeverage': false,
77
+ 'fetchLeverageTiers': false,
78
+ 'fetchLiquidations': true,
79
+ 'fetchMarginMode': undefined,
80
+ 'fetchMarketLeverageTiers': false,
81
+ 'fetchMarkets': true,
82
+ 'fetchMarkOHLCV': false,
83
+ 'fetchMyLiquidations': false,
84
+ 'fetchMyTrades': true,
85
+ 'fetchOHLCV': true,
86
+ 'fetchOpenInterest': true,
87
+ 'fetchOpenInterestHistory': false,
88
+ 'fetchOpenOrders': true,
89
+ 'fetchOrder': true,
90
+ 'fetchOrderBook': true,
91
+ 'fetchOrders': true,
92
+ 'fetchOrderTrades': false,
93
+ 'fetchPosition': true,
94
+ 'fetchPositionMode': false,
95
+ 'fetchPositions': true,
96
+ 'fetchPositionsRisk': false,
97
+ 'fetchPremiumIndexOHLCV': false,
98
+ 'fetchStatus': true,
99
+ 'fetchTicker': true,
100
+ 'fetchTickers': true,
101
+ 'fetchTime': true,
102
+ 'fetchTrades': true,
103
+ 'fetchTradingFee': false,
104
+ 'fetchTradingFees': false,
105
+ 'fetchTransfer': false,
106
+ 'fetchTransfers': false,
107
+ 'fetchWithdrawal': false,
108
+ 'fetchWithdrawals': true,
109
+ 'reduceMargin': false,
110
+ 'repayCrossMargin': false,
111
+ 'repayIsolatedMargin': false,
112
+ 'sandbox': true,
113
+ 'setLeverage': false,
114
+ 'setMarginMode': false,
115
+ 'setPositionMode': false,
116
+ 'transfer': false,
117
+ 'withdraw': false,
118
+ },
119
+ 'timeframes': {
120
+ '1m': 1,
121
+ '3m': 3,
122
+ '5m': 5,
123
+ '15m': 15,
124
+ '30m': 30,
125
+ '1h': 60,
126
+ },
127
+ 'hostname': 'paradex.trade',
128
+ 'urls': {
129
+ 'logo': 'https://github.com/user-attachments/assets/5dadc09a-74ba-466a-a8f2-3f55c7e4654a',
130
+ 'api': {
131
+ 'v1': 'https://api.prod.{hostname}/v1',
132
+ },
133
+ 'test': {
134
+ 'v1': 'https://api.testnet.{hostname}/v1',
135
+ },
136
+ 'www': 'https://www.paradex.trade/',
137
+ 'doc': 'https://docs.api.testnet.paradex.trade/',
138
+ 'fees': 'https://docs.paradex.trade/getting-started/trading-fees',
139
+ 'referral': 'https://app.paradex.trade/r/ccxt24',
140
+ },
141
+ 'api': {
142
+ 'public': {
143
+ 'get': {
144
+ 'bbo/{market}': 1,
145
+ 'funding/data': 1,
146
+ 'markets': 1,
147
+ 'markets/klines': 1,
148
+ 'markets/summary': 1,
149
+ 'orderbook/{market}': 1,
150
+ 'insurance': 1,
151
+ 'referrals/config': 1,
152
+ 'system/config': 1,
153
+ 'system/state': 1,
154
+ 'system/time': 1,
155
+ 'trades': 1,
156
+ },
157
+ },
158
+ 'private': {
159
+ 'get': {
160
+ 'account': 1,
161
+ 'account/profile': 1,
162
+ 'balance': 1,
163
+ 'fills': 1,
164
+ 'funding/payments': 1,
165
+ 'positions': 1,
166
+ 'tradebusts': 1,
167
+ 'transactions': 1,
168
+ 'liquidations': 1,
169
+ 'orders': 1,
170
+ 'orders-history': 1,
171
+ 'orders/by_client_id/{client_id}': 1,
172
+ 'orders/{order_id}': 1,
173
+ 'points_data/{market}/{program}': 1,
174
+ 'referrals/summary': 1,
175
+ 'transfers': 1,
176
+ },
177
+ 'post': {
178
+ 'account/profile/referral_code': 1,
179
+ 'account/profile/username': 1,
180
+ 'auth': 1,
181
+ 'onboarding': 1,
182
+ 'orders': 1,
183
+ },
184
+ 'delete': {
185
+ 'orders': 1,
186
+ 'orders/by_client_id/{client_id}': 1,
187
+ 'orders/{order_id}': 1,
188
+ },
189
+ },
190
+ },
191
+ 'fees': {
192
+ 'swap': {
193
+ 'taker': this.parseNumber('0.0002'),
194
+ 'maker': this.parseNumber('0.0002'),
195
+ },
196
+ 'spot': {
197
+ 'taker': this.parseNumber('0.0002'),
198
+ 'maker': this.parseNumber('0.0002'),
199
+ },
200
+ },
201
+ 'requiredCredentials': {
202
+ 'apiKey': false,
203
+ 'secret': false,
204
+ 'walletAddress': true,
205
+ 'privateKey': true,
206
+ },
207
+ 'exceptions': {
208
+ 'exact': {
209
+ 'VALIDATION_ERROR': errors.AuthenticationError,
210
+ 'BINDING_ERROR': errors.OperationRejected,
211
+ 'INTERNAL_ERROR': errors.ExchangeError,
212
+ 'NOT_FOUND': errors.BadRequest,
213
+ 'SERVICE_UNAVAILABLE': errors.ExchangeError,
214
+ 'INVALID_REQUEST_PARAMETER': errors.BadRequest,
215
+ 'ORDER_ID_NOT_FOUND': errors.InvalidOrder,
216
+ 'ORDER_IS_CLOSED': errors.InvalidOrder,
217
+ 'ORDER_IS_NOT_OPEN_YET': errors.InvalidOrder,
218
+ 'CLIENT_ORDER_ID_NOT_FOUND': errors.InvalidOrder,
219
+ 'DUPLICATED_CLIENT_ID': errors.InvalidOrder,
220
+ 'INVALID_PRICE_PRECISION': errors.OperationRejected,
221
+ 'INVALID_SYMBOL': errors.OperationRejected,
222
+ 'INVALID_TOKEN': errors.OperationRejected,
223
+ 'INVALID_ETHEREUM_ADDRESS': errors.OperationRejected,
224
+ 'INVALID_ETHEREUM_SIGNATURE': errors.OperationRejected,
225
+ 'INVALID_STARKNET_ADDRESS': errors.OperationRejected,
226
+ 'INVALID_STARKNET_SIGNATURE': errors.OperationRejected,
227
+ 'STARKNET_SIGNATURE_VERIFICATION_FAILED': errors.AuthenticationError,
228
+ 'BAD_STARKNET_REQUEST': errors.BadRequest,
229
+ 'ETHEREUM_SIGNER_MISMATCH': errors.BadRequest,
230
+ 'ETHEREUM_HASH_MISMATCH': errors.BadRequest,
231
+ 'NOT_ONBOARDED': errors.BadRequest,
232
+ 'INVALID_TIMESTAMP': errors.BadRequest,
233
+ 'INVALID_SIGNATURE_EXPIRATION': errors.AuthenticationError,
234
+ 'ACCOUNT_NOT_FOUND': errors.AuthenticationError,
235
+ 'INVALID_ORDER_SIGNATURE': errors.AuthenticationError,
236
+ 'PUBLIC_KEY_INVALID': errors.BadRequest,
237
+ 'UNAUTHORIZED_ETHEREUM_ADDRESS': errors.BadRequest,
238
+ 'ETHEREUM_ADDRESS_ALREADY_ONBOARDED': errors.BadRequest,
239
+ 'MARKET_NOT_FOUND': errors.BadRequest,
240
+ 'ALLOWLIST_ENTRY_NOT_FOUND': errors.BadRequest,
241
+ 'USERNAME_IN_USE': errors.AuthenticationError,
242
+ 'GEO_IP_BLOCK': errors.PermissionDenied,
243
+ 'ETHEREUM_ADDRESS_BLOCKED': errors.PermissionDenied,
244
+ 'PROGRAM_NOT_FOUND': errors.BadRequest,
245
+ 'INVALID_DASHBOARD': errors.OperationRejected,
246
+ 'MARKET_NOT_OPEN': errors.BadRequest,
247
+ 'INVALID_REFERRAL_CODE': errors.OperationRejected,
248
+ 'PARENT_ADDRESS_ALREADY_ONBOARDED': errors.BadRequest,
249
+ 'INVALID_PARENT_ACCOUNT': errors.OperationRejected,
250
+ 'INVALID_VAULT_OPERATOR_CHAIN': errors.OperationRejected,
251
+ 'VAULT_OPERATOR_ALREADY_ONBOARDED': errors.OperationRejected,
252
+ 'VAULT_NAME_IN_USE': errors.OperationRejected,
253
+ 'BATCH_SIZE_OUT_OF_RANGE': errors.OperationRejected,
254
+ 'ISOLATED_MARKET_ACCOUNT_MISMATCH': errors.OperationRejected,
255
+ 'POINTS_SUMMARY_NOT_FOUND': errors.OperationRejected,
256
+ '-32700': errors.BadRequest,
257
+ '-32600': errors.BadRequest,
258
+ '-32601': errors.BadRequest,
259
+ '-32602': errors.BadRequest,
260
+ '-32603': errors.ExchangeError,
261
+ '100': errors.BadRequest,
262
+ '40110': errors.AuthenticationError,
263
+ '40111': errors.AuthenticationError,
264
+ '40112': errors.PermissionDenied, // Geo IP blocked
265
+ },
266
+ 'broad': {},
267
+ },
268
+ 'precisionMode': number.TICK_SIZE,
269
+ 'commonCurrencies': {},
270
+ 'options': {
271
+ 'broker': 'CCXT',
272
+ },
273
+ });
274
+ }
275
+ async fetchTime(params = {}) {
276
+ /**
277
+ * @method
278
+ * @name paradex#fetchTime
279
+ * @description fetches the current integer timestamp in milliseconds from the exchange server
280
+ * @see https://docs.api.testnet.paradex.trade/#get-system-time-unix-milliseconds
281
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
282
+ * @returns {int} the current integer timestamp in milliseconds from the exchange server
283
+ */
284
+ const response = await this.publicGetSystemTime(params);
285
+ //
286
+ // {
287
+ // "server_time": "1681493415023"
288
+ // }
289
+ //
290
+ return this.safeInteger(response, 'server_time');
291
+ }
292
+ async fetchStatus(params = {}) {
293
+ /**
294
+ * @method
295
+ * @name paradex#fetchStatus
296
+ * @description the latest known information on the availability of the exchange API
297
+ * @see https://docs.api.testnet.paradex.trade/#get-system-state
298
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
299
+ * @returns {object} a [status structure]{@link https://docs.ccxt.com/#/?id=exchange-status-structure}
300
+ */
301
+ const response = await this.publicGetSystemState(params);
302
+ //
303
+ // {
304
+ // "status": "ok"
305
+ // }
306
+ //
307
+ const status = this.safeString(response, 'status');
308
+ return {
309
+ 'status': (status === 'ok') ? 'ok' : 'maintenance',
310
+ 'updated': undefined,
311
+ 'eta': undefined,
312
+ 'url': undefined,
313
+ 'info': response,
314
+ };
315
+ }
316
+ async fetchMarkets(params = {}) {
317
+ /**
318
+ * @method
319
+ * @name paradex#fetchMarkets
320
+ * @description retrieves data on all markets for bitget
321
+ * @see https://docs.api.testnet.paradex.trade/#list-available-markets
322
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
323
+ * @returns {object[]} an array of objects representing market data
324
+ */
325
+ const response = await this.publicGetMarkets(params);
326
+ //
327
+ // {
328
+ // "results": [
329
+ // {
330
+ // "symbol": "BODEN-USD-PERP",
331
+ // "base_currency": "BODEN",
332
+ // "quote_currency": "USD",
333
+ // "settlement_currency": "USDC",
334
+ // "order_size_increment": "1",
335
+ // "price_tick_size": "0.00001",
336
+ // "min_notional": "200",
337
+ // "open_at": 1717065600000,
338
+ // "expiry_at": 0,
339
+ // "asset_kind": "PERP",
340
+ // "position_limit": "2000000",
341
+ // "price_bands_width": "0.2",
342
+ // "max_open_orders": 50,
343
+ // "max_funding_rate": "0.05",
344
+ // "delta1_cross_margin_params": {
345
+ // "imf_base": "0.2",
346
+ // "imf_shift": "180000",
347
+ // "imf_factor": "0.00071",
348
+ // "mmf_factor": "0.5"
349
+ // },
350
+ // "price_feed_id": "9LScEHse1ioZt2rUuhwiN6bmYnqpMqvZkQJDNUpxVHN5",
351
+ // "oracle_ewma_factor": "0.14999987905913592",
352
+ // "max_order_size": "520000",
353
+ // "max_funding_rate_change": "0.0005",
354
+ // "max_tob_spread": "0.2"
355
+ // }
356
+ // ]
357
+ // }
358
+ //
359
+ const data = this.safeList(response, 'results');
360
+ return this.parseMarkets(data);
361
+ }
362
+ parseMarket(market) {
363
+ //
364
+ // {
365
+ // "symbol": "BODEN-USD-PERP",
366
+ // "base_currency": "BODEN",
367
+ // "quote_currency": "USD",
368
+ // "settlement_currency": "USDC",
369
+ // "order_size_increment": "1",
370
+ // "price_tick_size": "0.00001",
371
+ // "min_notional": "200",
372
+ // "open_at": 1717065600000,
373
+ // "expiry_at": 0,
374
+ // "asset_kind": "PERP",
375
+ // "position_limit": "2000000",
376
+ // "price_bands_width": "0.2",
377
+ // "max_open_orders": 50,
378
+ // "max_funding_rate": "0.05",
379
+ // "delta1_cross_margin_params": {
380
+ // "imf_base": "0.2",
381
+ // "imf_shift": "180000",
382
+ // "imf_factor": "0.00071",
383
+ // "mmf_factor": "0.5"
384
+ // },
385
+ // "price_feed_id": "9LScEHse1ioZt2rUuhwiN6bmYnqpMqvZkQJDNUpxVHN5",
386
+ // "oracle_ewma_factor": "0.14999987905913592",
387
+ // "max_order_size": "520000",
388
+ // "max_funding_rate_change": "0.0005",
389
+ // "max_tob_spread": "0.2"
390
+ // }
391
+ //
392
+ const marketId = this.safeString(market, 'symbol');
393
+ const quoteId = this.safeString(market, 'quote_currency');
394
+ const baseId = this.safeString(market, 'base_currency');
395
+ const quote = this.safeCurrencyCode(quoteId);
396
+ const base = this.safeCurrencyCode(baseId);
397
+ const settleId = this.safeString(market, 'settlement_currency');
398
+ const settle = this.safeCurrencyCode(settleId);
399
+ const symbol = base + '/' + quote + ':' + settle;
400
+ const expiry = this.safeInteger(market, 'expiry_at');
401
+ const takerFee = this.parseNumber('0.0003');
402
+ const makerFee = this.parseNumber('-0.00005');
403
+ return this.safeMarketStructure({
404
+ 'id': marketId,
405
+ 'symbol': symbol,
406
+ 'base': base,
407
+ 'quote': quote,
408
+ 'settle': settle,
409
+ 'baseId': baseId,
410
+ 'quoteId': quoteId,
411
+ 'settleId': settleId,
412
+ 'type': 'swap',
413
+ 'spot': false,
414
+ 'margin': undefined,
415
+ 'swap': true,
416
+ 'future': false,
417
+ 'option': false,
418
+ 'active': this.safeBool(market, 'enableTrading'),
419
+ 'contract': true,
420
+ 'linear': true,
421
+ 'inverse': undefined,
422
+ 'taker': takerFee,
423
+ 'maker': makerFee,
424
+ 'contractSize': this.parseNumber('1'),
425
+ 'expiry': (expiry === 0) ? undefined : expiry,
426
+ 'expiryDatetime': (expiry === 0) ? undefined : this.iso8601(expiry),
427
+ 'strike': undefined,
428
+ 'optionType': undefined,
429
+ 'precision': {
430
+ 'amount': this.safeNumber(market, 'order_size_increment'),
431
+ 'price': this.safeNumber(market, 'price_tick_size'),
432
+ },
433
+ 'limits': {
434
+ 'leverage': {
435
+ 'min': undefined,
436
+ 'max': undefined,
437
+ },
438
+ 'amount': {
439
+ 'min': undefined,
440
+ 'max': this.safeNumber(market, 'max_order_size'),
441
+ },
442
+ 'price': {
443
+ 'min': undefined,
444
+ 'max': undefined,
445
+ },
446
+ 'cost': {
447
+ 'min': this.safeNumber(market, 'min_notional'),
448
+ 'max': undefined,
449
+ },
450
+ },
451
+ 'created': undefined,
452
+ 'info': market,
453
+ });
454
+ }
455
+ async fetchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
456
+ /**
457
+ * @method
458
+ * @name paradex#fetchOHLCV
459
+ * @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
460
+ * @see https://docs.api.testnet.paradex.trade/#ohlcv-for-a-symbol
461
+ * @param {string} symbol unified symbol of the market to fetch OHLCV data for
462
+ * @param {string} timeframe the length of time each candle represents
463
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
464
+ * @param {int} [limit] the maximum amount of candles to fetch
465
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
466
+ * @param {int} [params.until] timestamp in ms of the latest candle to fetch
467
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
468
+ */
469
+ await this.loadMarkets();
470
+ const market = this.market(symbol);
471
+ const request = {
472
+ 'resolution': this.safeString(this.timeframes, timeframe, timeframe),
473
+ 'symbol': market['id'],
474
+ };
475
+ const now = this.milliseconds();
476
+ const duration = this.parseTimeframe(timeframe);
477
+ const until = this.safeInteger2(params, 'until', 'till', now);
478
+ params = this.omit(params, ['until', 'till']);
479
+ if (since !== undefined) {
480
+ request['start_at'] = since;
481
+ if (limit !== undefined) {
482
+ request['end_at'] = this.sum(since, duration * (limit + 1) * 1000) - 1;
483
+ }
484
+ else {
485
+ request['end_at'] = until;
486
+ }
487
+ }
488
+ else {
489
+ request['end_at'] = until;
490
+ if (limit !== undefined) {
491
+ request['start_at'] = until - duration * (limit + 1) * 1000 + 1;
492
+ }
493
+ else {
494
+ request['start_at'] = until - duration * 101 * 1000 + 1;
495
+ }
496
+ }
497
+ const response = await this.publicGetMarketsKlines(this.extend(request, params));
498
+ //
499
+ // {
500
+ // "results": [
501
+ // [
502
+ // 1720071900000,
503
+ // 58961.3,
504
+ // 58961.3,
505
+ // 58961.3,
506
+ // 58961.3,
507
+ // 1591
508
+ // ]
509
+ // ]
510
+ // }
511
+ //
512
+ const data = this.safeList(response, 'results', []);
513
+ return this.parseOHLCVs(data, market, timeframe, since, limit);
514
+ }
515
+ parseOHLCV(ohlcv, market = undefined) {
516
+ //
517
+ // [
518
+ // 1720071900000,
519
+ // 58961.3,
520
+ // 58961.3,
521
+ // 58961.3,
522
+ // 58961.3,
523
+ // 1591
524
+ // ]
525
+ //
526
+ return [
527
+ this.safeInteger(ohlcv, 0),
528
+ this.safeNumber(ohlcv, 1),
529
+ this.safeNumber(ohlcv, 2),
530
+ this.safeNumber(ohlcv, 3),
531
+ this.safeNumber(ohlcv, 4),
532
+ this.safeNumber(ohlcv, 5),
533
+ ];
534
+ }
535
+ async fetchTickers(symbols = undefined, params = {}) {
536
+ /**
537
+ * @method
538
+ * @name paradex#fetchTickers
539
+ * @description fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
540
+ * @see https://docs.api.testnet.paradex.trade/#list-available-markets-summary
541
+ * @param {string[]|undefined} symbols unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
542
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
543
+ * @returns {object} a dictionary of [ticker structures]{@link https://docs.ccxt.com/#/?id=ticker-structure}
544
+ */
545
+ await this.loadMarkets();
546
+ symbols = this.marketSymbols(symbols);
547
+ const request = {};
548
+ if (symbols !== undefined) {
549
+ if (Array.isArray(symbols)) {
550
+ request['market'] = this.marketId(symbols[0]);
551
+ }
552
+ else {
553
+ request['market'] = this.marketId(symbols);
554
+ }
555
+ }
556
+ else {
557
+ request['market'] = 'ALL';
558
+ }
559
+ const response = await this.publicGetMarketsSummary(this.extend(request, params));
560
+ //
561
+ // {
562
+ // "results": [
563
+ // {
564
+ // "symbol": "BTC-USD-PERP",
565
+ // "oracle_price": "68465.17449906",
566
+ // "mark_price": "68465.17449906",
567
+ // "last_traded_price": "68495.1",
568
+ // "bid": "68477.6",
569
+ // "ask": "69578.2",
570
+ // "volume_24h": "5815541.397939004",
571
+ // "total_volume": "584031465.525259686",
572
+ // "created_at": 1718170156580,
573
+ // "underlying_price": "67367.37268422",
574
+ // "open_interest": "162.272",
575
+ // "funding_rate": "0.01629574927887",
576
+ // "price_change_rate_24h": "0.009032"
577
+ // }
578
+ // ]
579
+ // }
580
+ //
581
+ const data = this.safeList(response, 'results', []);
582
+ return this.parseTickers(data, symbols);
583
+ }
584
+ async fetchTicker(symbol, params = {}) {
585
+ /**
586
+ * @method
587
+ * @name paradex#fetchTicker
588
+ * @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
589
+ * @see https://docs.api.testnet.paradex.trade/#list-available-markets-summary
590
+ * @param {string} symbol unified symbol of the market to fetch the ticker for
591
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
592
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
593
+ */
594
+ await this.loadMarkets();
595
+ const market = this.market(symbol);
596
+ const request = {
597
+ 'market': market['id'],
598
+ };
599
+ const response = await this.publicGetMarketsSummary(this.extend(request, params));
600
+ //
601
+ // {
602
+ // "results": [
603
+ // {
604
+ // "symbol": "BTC-USD-PERP",
605
+ // "oracle_price": "68465.17449906",
606
+ // "mark_price": "68465.17449906",
607
+ // "last_traded_price": "68495.1",
608
+ // "bid": "68477.6",
609
+ // "ask": "69578.2",
610
+ // "volume_24h": "5815541.397939004",
611
+ // "total_volume": "584031465.525259686",
612
+ // "created_at": 1718170156580,
613
+ // "underlying_price": "67367.37268422",
614
+ // "open_interest": "162.272",
615
+ // "funding_rate": "0.01629574927887",
616
+ // "price_change_rate_24h": "0.009032"
617
+ // }
618
+ // ]
619
+ // }
620
+ //
621
+ const data = this.safeList(response, 'results', []);
622
+ const ticker = this.safeDict(data, 0, {});
623
+ return this.parseTicker(ticker, market);
624
+ }
625
+ parseTicker(ticker, market = undefined) {
626
+ //
627
+ // {
628
+ // "symbol": "BTC-USD-PERP",
629
+ // "oracle_price": "68465.17449906",
630
+ // "mark_price": "68465.17449906",
631
+ // "last_traded_price": "68495.1",
632
+ // "bid": "68477.6",
633
+ // "ask": "69578.2",
634
+ // "volume_24h": "5815541.397939004",
635
+ // "total_volume": "584031465.525259686",
636
+ // "created_at": 1718170156580,
637
+ // "underlying_price": "67367.37268422",
638
+ // "open_interest": "162.272",
639
+ // "funding_rate": "0.01629574927887",
640
+ // "price_change_rate_24h": "0.009032"
641
+ // }
642
+ //
643
+ let percentage = this.safeString(ticker, 'price_change_rate_24h');
644
+ if (percentage !== undefined) {
645
+ percentage = Precise["default"].stringMul(percentage, '100');
646
+ }
647
+ const last = this.safeString(ticker, 'last_traded_price');
648
+ const marketId = this.safeString(ticker, 'symbol');
649
+ market = this.safeMarket(marketId, market);
650
+ const symbol = market['symbol'];
651
+ const timestamp = this.safeInteger(ticker, 'created_at');
652
+ return this.safeTicker({
653
+ 'symbol': symbol,
654
+ 'timestamp': timestamp,
655
+ 'datetime': this.iso8601(timestamp),
656
+ 'high': undefined,
657
+ 'low': undefined,
658
+ 'bid': this.safeString(ticker, 'bid'),
659
+ 'bidVolume': undefined,
660
+ 'ask': this.safeString(ticker, 'sdk'),
661
+ 'askVolume': undefined,
662
+ 'vwap': undefined,
663
+ 'open': undefined,
664
+ 'close': last,
665
+ 'last': last,
666
+ 'previousClose': undefined,
667
+ 'change': undefined,
668
+ 'percentage': percentage,
669
+ 'average': undefined,
670
+ 'baseVolume': undefined,
671
+ 'quoteVolume': this.safeString(ticker, 'volume_24h'),
672
+ 'info': ticker,
673
+ }, market);
674
+ }
675
+ async fetchOrderBook(symbol, limit = undefined, params = {}) {
676
+ /**
677
+ * @method
678
+ * @name paradex#fetchOrderBook
679
+ * @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
680
+ * @see https://docs.api.testnet.paradex.trade/#get-market-orderbook
681
+ * @param {string} symbol unified symbol of the market to fetch the order book for
682
+ * @param {int} [limit] the maximum amount of order book entries to return
683
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
684
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
685
+ */
686
+ await this.loadMarkets();
687
+ const market = this.market(symbol);
688
+ const request = { 'market': market['id'] };
689
+ const response = await this.publicGetOrderbookMarket(this.extend(request, params));
690
+ //
691
+ // {
692
+ // "market": "BTC-USD-PERP",
693
+ // "seq_no": 14115975,
694
+ // "last_updated_at": 1718172538340,
695
+ // "asks": [
696
+ // [
697
+ // "69578.2",
698
+ // "3.019"
699
+ // ]
700
+ // ],
701
+ // "bids": [
702
+ // [
703
+ // "68477.6",
704
+ // "0.1"
705
+ // ]
706
+ // ]
707
+ // }
708
+ //
709
+ if (limit !== undefined) {
710
+ request['depth'] = limit;
711
+ }
712
+ const timestamp = this.safeInteger(response, 'last_updated_at');
713
+ const orderbook = this.parseOrderBook(response, market['symbol'], timestamp);
714
+ orderbook['nonce'] = this.safeInteger(response, 'seq_no');
715
+ return orderbook;
716
+ }
717
+ async fetchTrades(symbol, since = undefined, limit = undefined, params = {}) {
718
+ /**
719
+ * @method
720
+ * @name paradex#fetchTrades
721
+ * @description get the list of most recent trades for a particular symbol
722
+ * @see https://docs.api.testnet.paradex.trade/#trade-tape
723
+ * @param {string} symbol unified symbol of the market to fetch trades for
724
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
725
+ * @param {int} [limit] the maximum amount of trades to fetch
726
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
727
+ * @param {int} [params.until] the latest time in ms to fetch trades for
728
+ * @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times
729
+ * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
730
+ */
731
+ await this.loadMarkets();
732
+ let paginate = false;
733
+ [paginate, params] = this.handleOptionAndParams(params, 'fetchTrades', 'paginate');
734
+ if (paginate) {
735
+ return await this.fetchPaginatedCallCursor('fetchTrades', symbol, since, limit, params, 'next', 'cursor', undefined, 100);
736
+ }
737
+ const market = this.market(symbol);
738
+ let request = {
739
+ 'market': market['id'],
740
+ };
741
+ if (limit !== undefined) {
742
+ request['page_size'] = limit;
743
+ }
744
+ if (since !== undefined) {
745
+ request['start_at'] = since;
746
+ }
747
+ [request, params] = this.handleUntilOption('end_at', request, params);
748
+ const response = await this.publicGetTrades(this.extend(request, params));
749
+ //
750
+ // {
751
+ // "next": "...",
752
+ // "prev": "...",
753
+ // "results": [
754
+ // {
755
+ // "id": "1718154353750201703989430001",
756
+ // "market": "BTC-USD-PERP",
757
+ // "side": "BUY",
758
+ // "size": "0.026",
759
+ // "price": "69578.2",
760
+ // "created_at": 1718154353750,
761
+ // "trade_type": "FILL"
762
+ // }
763
+ // ]
764
+ // }
765
+ //
766
+ const trades = this.safeList(response, 'results', []);
767
+ for (let i = 0; i < trades.length; i++) {
768
+ trades[i]['next'] = this.safeString(response, 'next');
769
+ }
770
+ return this.parseTrades(trades, market, since, limit);
771
+ }
772
+ parseTrade(trade, market = undefined) {
773
+ //
774
+ // fetchTrades (public)
775
+ //
776
+ // {
777
+ // "id": "1718154353750201703989430001",
778
+ // "market": "BTC-USD-PERP",
779
+ // "side": "BUY",
780
+ // "size": "0.026",
781
+ // "price": "69578.2",
782
+ // "created_at": 1718154353750,
783
+ // "trade_type": "FILL"
784
+ // }
785
+ //
786
+ // fetchMyTrades (private)
787
+ //
788
+ // {
789
+ // "id": "1718947571560201703986670001",
790
+ // "side": "BUY",
791
+ // "liquidity": "TAKER",
792
+ // "market": "BTC-USD-PERP",
793
+ // "order_id": "1718947571540201703992340000",
794
+ // "price": "64852.9",
795
+ // "size": "0.01",
796
+ // "fee": "0.1945587",
797
+ // "fee_currency": "USDC",
798
+ // "created_at": 1718947571569,
799
+ // "remaining_size": "0",
800
+ // "client_id": "",
801
+ // "fill_type": "FILL"
802
+ // }
803
+ //
804
+ const marketId = this.safeString(trade, 'market');
805
+ market = this.safeMarket(marketId, market);
806
+ const id = this.safeString(trade, 'id');
807
+ const timestamp = this.safeInteger(trade, 'created_at');
808
+ const priceString = this.safeString(trade, 'price');
809
+ const amountString = this.safeString(trade, 'size');
810
+ const side = this.safeStringLower(trade, 'side');
811
+ const liability = this.safeStringLower(trade, 'liquidity', 'taker');
812
+ const isTaker = liability === 'taker';
813
+ const takerOrMaker = (isTaker) ? 'taker' : 'maker';
814
+ const currencyId = this.safeString(trade, 'fee_currency');
815
+ const code = this.safeCurrencyCode(currencyId);
816
+ return this.safeTrade({
817
+ 'info': trade,
818
+ 'id': id,
819
+ 'order': this.safeString(trade, 'order_id'),
820
+ 'timestamp': timestamp,
821
+ 'datetime': this.iso8601(timestamp),
822
+ 'symbol': market['symbol'],
823
+ 'type': undefined,
824
+ 'takerOrMaker': takerOrMaker,
825
+ 'side': side,
826
+ 'price': priceString,
827
+ 'amount': amountString,
828
+ 'cost': undefined,
829
+ 'fee': {
830
+ 'cost': this.safeString(trade, 'fee'),
831
+ 'currency': code,
832
+ 'rate': undefined,
833
+ },
834
+ }, market);
835
+ }
836
+ async fetchOpenInterest(symbol, params = {}) {
837
+ /**
838
+ * @method
839
+ * @name paradex#fetchOpenInterest
840
+ * @description retrieves the open interest of a contract trading pair
841
+ * @see https://docs.api.testnet.paradex.trade/#list-available-markets-summary
842
+ * @param {string} symbol unified CCXT market symbol
843
+ * @param {object} [params] exchange specific parameters
844
+ * @returns {object} an open interest structure{@link https://docs.ccxt.com/#/?id=open-interest-structure}
845
+ */
846
+ await this.loadMarkets();
847
+ const market = this.market(symbol);
848
+ if (!market['contract']) {
849
+ throw new errors.BadRequest(this.id + ' fetchOpenInterest() supports contract markets only');
850
+ }
851
+ const request = {
852
+ 'market': market['id'],
853
+ };
854
+ const response = await this.publicGetMarketsSummary(this.extend(request, params));
855
+ //
856
+ // {
857
+ // "results": [
858
+ // {
859
+ // "symbol": "BTC-USD-PERP",
860
+ // "oracle_price": "68465.17449906",
861
+ // "mark_price": "68465.17449906",
862
+ // "last_traded_price": "68495.1",
863
+ // "bid": "68477.6",
864
+ // "ask": "69578.2",
865
+ // "volume_24h": "5815541.397939004",
866
+ // "total_volume": "584031465.525259686",
867
+ // "created_at": 1718170156580,
868
+ // "underlying_price": "67367.37268422",
869
+ // "open_interest": "162.272",
870
+ // "funding_rate": "0.01629574927887",
871
+ // "price_change_rate_24h": "0.009032"
872
+ // }
873
+ // ]
874
+ // }
875
+ //
876
+ const data = this.safeList(response, 'results', []);
877
+ const interest = this.safeDict(data, 0, {});
878
+ return this.parseOpenInterest(interest, market);
879
+ }
880
+ parseOpenInterest(interest, market = undefined) {
881
+ //
882
+ // {
883
+ // "symbol": "BTC-USD-PERP",
884
+ // "oracle_price": "68465.17449906",
885
+ // "mark_price": "68465.17449906",
886
+ // "last_traded_price": "68495.1",
887
+ // "bid": "68477.6",
888
+ // "ask": "69578.2",
889
+ // "volume_24h": "5815541.397939004",
890
+ // "total_volume": "584031465.525259686",
891
+ // "created_at": 1718170156580,
892
+ // "underlying_price": "67367.37268422",
893
+ // "open_interest": "162.272",
894
+ // "funding_rate": "0.01629574927887",
895
+ // "price_change_rate_24h": "0.009032"
896
+ // }
897
+ //
898
+ const timestamp = this.safeInteger(interest, 'created_at');
899
+ const marketId = this.safeString(interest, 'symbol');
900
+ market = this.safeMarket(marketId, market);
901
+ const symbol = market['symbol'];
902
+ return this.safeOpenInterest({
903
+ 'symbol': symbol,
904
+ 'openInterestAmount': this.safeString(interest, 'open_interest'),
905
+ 'openInterestValue': undefined,
906
+ 'timestamp': timestamp,
907
+ 'datetime': this.iso8601(timestamp),
908
+ 'info': interest,
909
+ }, market);
910
+ }
911
+ hashMessage(message) {
912
+ return '0x' + this.hash(message, sha3.keccak_256, 'hex');
913
+ }
914
+ signHash(hash, privateKey) {
915
+ const signature = crypto.ecdsa(hash.slice(-64), privateKey.slice(-64), secp256k1.secp256k1, undefined);
916
+ const r = signature['r'];
917
+ const s = signature['s'];
918
+ const v = this.intToBase16(this.sum(27, signature['v']));
919
+ return '0x' + r.padStart(64, '0') + s.padStart(64, '0') + v;
920
+ }
921
+ signMessage(message, privateKey) {
922
+ return this.signHash(this.hashMessage(message), privateKey.slice(-64));
923
+ }
924
+ async getSystemConfig() {
925
+ const cachedConfig = this.safeDict(this.options, 'systemConfig');
926
+ if (cachedConfig !== undefined) {
927
+ return cachedConfig;
928
+ }
929
+ const response = await this.publicGetSystemConfig();
930
+ //
931
+ // {
932
+ // "starknet_gateway_url": "https://potc-testnet-sepolia.starknet.io",
933
+ // "starknet_fullnode_rpc_url": "https://pathfinder.api.testnet.paradex.trade/rpc/v0_7",
934
+ // "starknet_chain_id": "PRIVATE_SN_POTC_SEPOLIA",
935
+ // "block_explorer_url": "https://voyager.testnet.paradex.trade/",
936
+ // "paraclear_address": "0x286003f7c7bfc3f94e8f0af48b48302e7aee2fb13c23b141479ba00832ef2c6",
937
+ // "paraclear_decimals": 8,
938
+ // "paraclear_account_proxy_hash": "0x3530cc4759d78042f1b543bf797f5f3d647cde0388c33734cf91b7f7b9314a9",
939
+ // "paraclear_account_hash": "0x41cb0280ebadaa75f996d8d92c6f265f6d040bb3ba442e5f86a554f1765244e",
940
+ // "oracle_address": "0x2c6a867917ef858d6b193a0ff9e62b46d0dc760366920d631715d58baeaca1f",
941
+ // "bridged_tokens": [
942
+ // {
943
+ // "name": "TEST USDC",
944
+ // "symbol": "USDC",
945
+ // "decimals": 6,
946
+ // "l1_token_address": "0x29A873159D5e14AcBd63913D4A7E2df04570c666",
947
+ // "l1_bridge_address": "0x8586e05adc0C35aa11609023d4Ae6075Cb813b4C",
948
+ // "l2_token_address": "0x6f373b346561036d98ea10fb3e60d2f459c872b1933b50b21fe6ef4fda3b75e",
949
+ // "l2_bridge_address": "0x46e9237f5408b5f899e72125dd69bd55485a287aaf24663d3ebe00d237fc7ef"
950
+ // }
951
+ // ],
952
+ // "l1_core_contract_address": "0x582CC5d9b509391232cd544cDF9da036e55833Af",
953
+ // "l1_operator_address": "0x11bACdFbBcd3Febe5e8CEAa75E0Ef6444d9B45FB",
954
+ // "l1_chain_id": "11155111",
955
+ // "liquidation_fee": "0.2"
956
+ // }
957
+ //
958
+ this.options['systemConfig'] = response;
959
+ return response;
960
+ }
961
+ async prepareParadexDomain(l1 = false) {
962
+ const systemConfig = await this.getSystemConfig();
963
+ if (l1 === true) {
964
+ return {
965
+ 'name': 'Paradex',
966
+ 'chainId': systemConfig['l1_chain_id'],
967
+ 'version': '1',
968
+ };
969
+ }
970
+ return {
971
+ 'name': 'Paradex',
972
+ 'chainId': systemConfig['starknet_chain_id'],
973
+ 'version': 1,
974
+ };
975
+ }
976
+ async retrieveAccount() {
977
+ this.checkRequiredCredentials();
978
+ const cachedAccount = this.safeDict(this.options, 'paradexAccount');
979
+ if (cachedAccount !== undefined) {
980
+ return cachedAccount;
981
+ }
982
+ const systemConfig = await this.getSystemConfig();
983
+ const domain = await this.prepareParadexDomain(true);
984
+ const messageTypes = {
985
+ 'Constant': [
986
+ { 'name': 'action', 'type': 'string' },
987
+ ],
988
+ };
989
+ const message = {
990
+ 'action': 'STARK Key',
991
+ };
992
+ const msg = this.ethEncodeStructuredData(domain, messageTypes, message);
993
+ const signature = this.signMessage(msg, this.privateKey);
994
+ const account = this.retrieveStarkAccount(signature, systemConfig['paraclear_account_hash'], systemConfig['paraclear_account_proxy_hash']);
995
+ this.options['paradexAccount'] = account;
996
+ return account;
997
+ }
998
+ async onboarding(params = {}) {
999
+ const account = await this.retrieveAccount();
1000
+ const req = {
1001
+ 'action': 'Onboarding',
1002
+ };
1003
+ const domain = await this.prepareParadexDomain();
1004
+ const messageTypes = {
1005
+ 'Constant': [
1006
+ { 'name': 'action', 'type': 'felt' },
1007
+ ],
1008
+ };
1009
+ const msg = this.starknetEncodeStructuredData(domain, messageTypes, req, account['address']);
1010
+ const signature = this.starknetSign(msg, account['privateKey']);
1011
+ params['signature'] = signature;
1012
+ params['account'] = account['address'];
1013
+ params['public_key'] = account['publicKey'];
1014
+ const response = await this.privatePostOnboarding(params);
1015
+ return response;
1016
+ }
1017
+ async authenticateRest(params = {}) {
1018
+ const cachedToken = this.safeString(this.options, 'authToken');
1019
+ if (cachedToken !== undefined) {
1020
+ return cachedToken;
1021
+ }
1022
+ const account = await this.retrieveAccount();
1023
+ const now = this.nonce();
1024
+ const req = {
1025
+ 'method': 'POST',
1026
+ 'path': '/v1/auth',
1027
+ 'body': '',
1028
+ 'timestamp': now,
1029
+ 'expiration': now + 86400 * 7,
1030
+ };
1031
+ const domain = await this.prepareParadexDomain();
1032
+ const messageTypes = {
1033
+ 'Request': [
1034
+ { 'name': 'method', 'type': 'felt' },
1035
+ { 'name': 'path', 'type': 'felt' },
1036
+ { 'name': 'body', 'type': 'felt' },
1037
+ { 'name': 'timestamp', 'type': 'felt' },
1038
+ { 'name': 'expiration', 'type': 'felt' },
1039
+ ],
1040
+ };
1041
+ const msg = this.starknetEncodeStructuredData(domain, messageTypes, req, account['address']);
1042
+ const signature = this.starknetSign(msg, account['privateKey']);
1043
+ params['signature'] = signature;
1044
+ params['account'] = account['address'];
1045
+ params['timestamp'] = req['timestamp'];
1046
+ params['expiration'] = req['expiration'];
1047
+ const response = await this.privatePostAuth(params);
1048
+ //
1049
+ // {
1050
+ // jwt_token: "ooooccxtooootoooootheoooomoonooooo"
1051
+ // }
1052
+ //
1053
+ const token = this.safeString(response, 'jwt_token');
1054
+ this.options['authToken'] = token;
1055
+ return token;
1056
+ }
1057
+ parseOrder(order, market = undefined) {
1058
+ //
1059
+ // {
1060
+ // "account": "0x4638e3041366aa71720be63e32e53e1223316c7f0d56f7aa617542ed1e7512x",
1061
+ // "avg_fill_price": "26000",
1062
+ // "client_id": "x1234",
1063
+ // "cancel_reason": "NOT_ENOUGH_MARGIN",
1064
+ // "created_at": 1681493746016,
1065
+ // "flags": [
1066
+ // "REDUCE_ONLY"
1067
+ // ],
1068
+ // "id": "123456",
1069
+ // "instruction": "GTC",
1070
+ // "last_updated_at": 1681493746016,
1071
+ // "market": "BTC-USD-PERP",
1072
+ // "price": "26000",
1073
+ // "published_at": 1681493746016,
1074
+ // "received_at": 1681493746016,
1075
+ // "remaining_size": "0",
1076
+ // "seq_no": 1681471234972000000,
1077
+ // "side": "BUY",
1078
+ // "size": "0.05",
1079
+ // "status": "NEW",
1080
+ // "stp": "EXPIRE_MAKER",
1081
+ // "timestamp": 1681493746016,
1082
+ // "trigger_price": "26000",
1083
+ // "type": "MARKET"
1084
+ // }
1085
+ //
1086
+ const timestamp = this.safeInteger(order, 'created_at');
1087
+ const orderId = this.safeString(order, 'id');
1088
+ const clientOrderId = this.omitZero(this.safeString(order, 'client_id'));
1089
+ const marketId = this.safeString(order, 'market');
1090
+ market = this.safeMarket(marketId, market);
1091
+ const symbol = market['symbol'];
1092
+ const price = this.safeString(order, 'price');
1093
+ const amount = this.safeString(order, 'size');
1094
+ const orderType = this.safeString(order, 'type');
1095
+ const status = this.safeString(order, 'status');
1096
+ const side = this.safeStringLower(order, 'side');
1097
+ const average = this.omitZero(this.safeString(order, 'avg_fill_price'));
1098
+ const remaining = this.omitZero(this.safeString(order, 'remaining_size'));
1099
+ const stopPrice = this.safeString(order, 'trigger_price');
1100
+ const lastUpdateTimestamp = this.safeInteger(order, 'last_updated_at');
1101
+ return this.safeOrder({
1102
+ 'id': orderId,
1103
+ 'clientOrderId': clientOrderId,
1104
+ 'timestamp': timestamp,
1105
+ 'datetime': this.iso8601(timestamp),
1106
+ 'lastTradeTimestamp': undefined,
1107
+ 'lastUpdateTimestamp': lastUpdateTimestamp,
1108
+ 'status': this.parseOrderStatus(status),
1109
+ 'symbol': symbol,
1110
+ 'type': this.parseOrderType(orderType),
1111
+ 'timeInForce': this.parseTimeInForce(this.safeString(order, 'instrunction')),
1112
+ 'postOnly': undefined,
1113
+ 'reduceOnly': undefined,
1114
+ 'side': side,
1115
+ 'price': price,
1116
+ 'stopPrice': stopPrice,
1117
+ 'triggerPrice': stopPrice,
1118
+ 'takeProfitPrice': undefined,
1119
+ 'stopLossPrice': undefined,
1120
+ 'average': average,
1121
+ 'amount': amount,
1122
+ 'filled': undefined,
1123
+ 'remaining': remaining,
1124
+ 'cost': undefined,
1125
+ 'trades': undefined,
1126
+ 'fee': {
1127
+ 'cost': undefined,
1128
+ 'currency': undefined,
1129
+ },
1130
+ 'info': order,
1131
+ }, market);
1132
+ }
1133
+ parseTimeInForce(timeInForce) {
1134
+ const timeInForces = {
1135
+ 'IOC': 'IOC',
1136
+ 'GTC': 'GTC',
1137
+ 'POST_ONLY': 'PO',
1138
+ };
1139
+ return this.safeString(timeInForces, timeInForce, undefined);
1140
+ }
1141
+ parseOrderStatus(status) {
1142
+ if (status !== undefined) {
1143
+ const statuses = {
1144
+ 'NEW': 'open',
1145
+ 'UNTRIGGERED': 'open',
1146
+ 'OPEN': 'open',
1147
+ 'CLOSED': 'closed',
1148
+ };
1149
+ return this.safeString(statuses, status, status);
1150
+ }
1151
+ return status;
1152
+ }
1153
+ parseOrderType(type) {
1154
+ const types = {
1155
+ 'LIMIT': 'limit',
1156
+ 'MARKET': 'market',
1157
+ 'STOP_LIMIT': 'limit',
1158
+ 'STOP_MARKET': 'market',
1159
+ };
1160
+ return this.safeStringLower(types, type, type);
1161
+ }
1162
+ convertShortString(str) {
1163
+ // TODO: add stringToBase16 in exchange
1164
+ return '0x' + this.binaryToBase16(this.base64ToBinary(this.stringToBase64(str)));
1165
+ }
1166
+ scaleNumber(num) {
1167
+ return Precise["default"].stringMul(num, '100000000');
1168
+ }
1169
+ async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
1170
+ /**
1171
+ * @method
1172
+ * @name paradex#createOrder
1173
+ * @description create a trade order
1174
+ * @see https://docs.api.prod.paradex.trade/#create-order
1175
+ * @param {string} symbol unified symbol of the market to create an order in
1176
+ * @param {string} type 'market' or 'limit'
1177
+ * @param {string} side 'buy' or 'sell'
1178
+ * @param {float} amount how much of currency you want to trade in units of base currency
1179
+ * @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
1180
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1181
+ * @param {float} [params.stopPrice] The price a trigger order is triggered at
1182
+ * @param {float} [params.triggerPrice] The price a trigger order is triggered at
1183
+ * @param {string} [params.timeInForce] "GTC", "IOC", or "POST_ONLY"
1184
+ * @param {bool} [params.postOnly] true or false
1185
+ * @param {bool} [params.reduceOnly] Ensures that the executed order does not flip the opened position.
1186
+ * @param {string} [params.clientOrderId] a unique id for the order
1187
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
1188
+ */
1189
+ await this.authenticateRest();
1190
+ await this.loadMarkets();
1191
+ const market = this.market(symbol);
1192
+ const reduceOnly = this.safeBool2(params, 'reduceOnly', 'reduce_only');
1193
+ const orderType = type.toUpperCase();
1194
+ const orderSide = side.toUpperCase();
1195
+ const request = {
1196
+ 'market': market['id'],
1197
+ 'side': orderSide,
1198
+ 'type': orderType,
1199
+ 'size': this.amountToPrecision(symbol, amount),
1200
+ };
1201
+ const stopPrice = this.safeString2(params, 'triggerPrice', 'stopPrice');
1202
+ const isMarket = orderType === 'MARKET';
1203
+ const timeInForce = this.safeStringUpper(params, 'timeInForce');
1204
+ const postOnly = this.isPostOnly(isMarket, undefined, params);
1205
+ if (!isMarket) {
1206
+ if (postOnly) {
1207
+ request['instruction'] = 'POST_ONLY';
1208
+ }
1209
+ else if (timeInForce === 'ioc') {
1210
+ request['instruction'] = 'IOC';
1211
+ }
1212
+ }
1213
+ if (reduceOnly) {
1214
+ request['flags'] = [
1215
+ 'REDUCE_ONLY',
1216
+ ];
1217
+ }
1218
+ if (price !== undefined) {
1219
+ request['price'] = this.priceToPrecision(symbol, price);
1220
+ }
1221
+ const clientOrderId = this.safeStringN(params, ['clOrdID', 'clientOrderId', 'client_order_id']);
1222
+ if (clientOrderId !== undefined) {
1223
+ request['client_id'] = clientOrderId;
1224
+ }
1225
+ if (stopPrice !== undefined) {
1226
+ if (isMarket) {
1227
+ request['type'] = 'STOP_MARKET';
1228
+ }
1229
+ else {
1230
+ request['type'] = 'STOP_LIMIT';
1231
+ }
1232
+ request['trigger_price'] = this.priceToPrecision(symbol, stopPrice);
1233
+ }
1234
+ params = this.omit(params, ['reduceOnly', 'reduce_only', 'clOrdID', 'clientOrderId', 'client_order_id', 'postOnly', 'timeInForce', 'stopPrice', 'triggerPrice']);
1235
+ const account = await this.retrieveAccount();
1236
+ const now = this.nonce();
1237
+ const orderReq = {
1238
+ 'timestamp': now * 1000,
1239
+ 'market': this.convertShortString(request['market']),
1240
+ 'side': (orderSide === 'BUY') ? '1' : '2',
1241
+ 'orderType': this.convertShortString(request['type']),
1242
+ 'size': this.scaleNumber(request['size']),
1243
+ 'price': (isMarket) ? '0' : this.scaleNumber(request['price']),
1244
+ };
1245
+ const domain = await this.prepareParadexDomain();
1246
+ const messageTypes = {
1247
+ 'Order': [
1248
+ { 'name': 'timestamp', 'type': 'felt' },
1249
+ { 'name': 'market', 'type': 'felt' },
1250
+ { 'name': 'side', 'type': 'felt' },
1251
+ { 'name': 'orderType', 'type': 'felt' },
1252
+ { 'name': 'size', 'type': 'felt' },
1253
+ { 'name': 'price', 'type': 'felt' },
1254
+ ],
1255
+ };
1256
+ const msg = this.starknetEncodeStructuredData(domain, messageTypes, orderReq, account['address']);
1257
+ const signature = this.starknetSign(msg, account['privateKey']);
1258
+ request['signature'] = signature;
1259
+ request['signature_timestamp'] = orderReq['timestamp'];
1260
+ const response = await this.privatePostOrders(this.extend(request, params));
1261
+ //
1262
+ // {
1263
+ // "account": "0x4638e3041366aa71720be63e32e53e1223316c7f0d56f7aa617542ed1e7512x",
1264
+ // "avg_fill_price": "26000",
1265
+ // "cancel_reason": "NOT_ENOUGH_MARGIN",
1266
+ // "client_id": "x1234",
1267
+ // "created_at": 1681493746016,
1268
+ // "flags": [
1269
+ // "REDUCE_ONLY"
1270
+ // ],
1271
+ // "id": "123456",
1272
+ // "instruction": "GTC",
1273
+ // "last_updated_at": 1681493746016,
1274
+ // "market": "BTC-USD-PERP",
1275
+ // "price": "26000",
1276
+ // "published_at": 1681493746016,
1277
+ // "received_at": 1681493746016,
1278
+ // "remaining_size": "0",
1279
+ // "seq_no": 1681471234972000000,
1280
+ // "side": "BUY",
1281
+ // "size": "0.05",
1282
+ // "status": "NEW",
1283
+ // "stp": "EXPIRE_MAKER",
1284
+ // "timestamp": 1681493746016,
1285
+ // "trigger_price": "26000",
1286
+ // "type": "MARKET"
1287
+ // }
1288
+ //
1289
+ const order = this.parseOrder(response, market);
1290
+ return order;
1291
+ }
1292
+ async cancelOrder(id, symbol = undefined, params = {}) {
1293
+ /**
1294
+ * @method
1295
+ * @name paradex#cancelOrder
1296
+ * @description cancels an open order
1297
+ * @see https://docs.api.prod.paradex.trade/#cancel-order
1298
+ * @see https://docs.api.prod.paradex.trade/#cancel-open-order-by-client-order-id
1299
+ * @param {string} id order id
1300
+ * @param {string} symbol unified symbol of the market the order was made in
1301
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1302
+ * @param {string} [params.clientOrderId] a unique id for the order
1303
+ * @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
1304
+ */
1305
+ await this.authenticateRest();
1306
+ await this.loadMarkets();
1307
+ const request = {};
1308
+ const clientOrderId = this.safeStringN(params, ['clOrdID', 'clientOrderId', 'client_order_id']);
1309
+ let response = undefined;
1310
+ if (clientOrderId !== undefined) {
1311
+ request['client_id'] = clientOrderId;
1312
+ response = await this.privateDeleteOrdersByClientIdClientId(this.extend(request, params));
1313
+ }
1314
+ else {
1315
+ request['order_id'] = id;
1316
+ response = await this.privateDeleteOrdersOrderId(this.extend(request, params));
1317
+ }
1318
+ //
1319
+ // if success, no response...
1320
+ //
1321
+ return this.parseOrder(response);
1322
+ }
1323
+ async cancelAllOrders(symbol = undefined, params = {}) {
1324
+ /**
1325
+ * @method
1326
+ * @name paradex#cancelAllOrders
1327
+ * @description cancel all open orders in a market
1328
+ * @see https://docs.api.prod.paradex.trade/#cancel-all-open-orders
1329
+ * @param {string} symbol unified market symbol of the market to cancel orders in
1330
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1331
+ * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
1332
+ */
1333
+ if (symbol === undefined) {
1334
+ throw new errors.ArgumentsRequired(this.id + ' cancelAllOrders() requires a symbol argument');
1335
+ }
1336
+ await this.authenticateRest();
1337
+ await this.loadMarkets();
1338
+ const market = this.market(symbol);
1339
+ const request = {
1340
+ 'market': market['id'],
1341
+ };
1342
+ const response = await this.privateDeleteOrders(this.extend(request, params));
1343
+ //
1344
+ // if success, no response...
1345
+ //
1346
+ return response;
1347
+ }
1348
+ async fetchOrder(id, symbol = undefined, params = {}) {
1349
+ /**
1350
+ * @method
1351
+ * @name paradex#fetchOrder
1352
+ * @description fetches information on an order made by the user
1353
+ * @see https://docs.api.prod.paradex.trade/#get-order
1354
+ * @see https://docs.api.prod.paradex.trade/#get-order-by-client-id
1355
+ * @param {string} id the order id
1356
+ * @param {string} symbol unified symbol of the market the order was made in
1357
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1358
+ * @param {string} [params.clientOrderId] a unique id for the order
1359
+ * @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
1360
+ */
1361
+ await this.authenticateRest();
1362
+ await this.loadMarkets();
1363
+ const request = {};
1364
+ const clientOrderId = this.safeStringN(params, ['clOrdID', 'clientOrderId', 'client_order_id']);
1365
+ params = this.omit(params, ['clOrdID', 'clientOrderId', 'client_order_id']);
1366
+ let response = undefined;
1367
+ if (clientOrderId !== undefined) {
1368
+ request['client_id'] = clientOrderId;
1369
+ response = await this.privateGetOrdersByClientIdClientId(this.extend(request, params));
1370
+ }
1371
+ else {
1372
+ request['order_id'] = id;
1373
+ response = await this.privateGetOrdersOrderId(this.extend(request, params));
1374
+ }
1375
+ //
1376
+ // {
1377
+ // "id": "1718941725080201704028870000",
1378
+ // "account": "0x49ddd7a564c978f6e4089ff8355b56a42b7e2d48ba282cb5aad60f04bea0ec3",
1379
+ // "market": "BTC-USD-PERP",
1380
+ // "side": "SELL",
1381
+ // "type": "LIMIT",
1382
+ // "size": "10.153",
1383
+ // "remaining_size": "10.153",
1384
+ // "price": "70784.5",
1385
+ // "status": "CLOSED",
1386
+ // "created_at": 1718941725082,
1387
+ // "last_updated_at": 1718958002991,
1388
+ // "timestamp": 1718941724678,
1389
+ // "cancel_reason": "USER_CANCELED",
1390
+ // "client_id": "",
1391
+ // "seq_no": 1718958002991595738,
1392
+ // "instruction": "GTC",
1393
+ // "avg_fill_price": "",
1394
+ // "stp": "EXPIRE_TAKER",
1395
+ // "received_at": 1718958510959,
1396
+ // "published_at": 1718958510960,
1397
+ // "flags": [],
1398
+ // "trigger_price": "0"
1399
+ // }
1400
+ //
1401
+ return this.parseOrder(response);
1402
+ }
1403
+ async fetchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1404
+ /**
1405
+ * @method
1406
+ * @name paradex#fetchOrders
1407
+ * @description fetches information on multiple orders made by the user
1408
+ * @see https://docs.api.prod.paradex.trade/#get-orders
1409
+ * @param {string} symbol unified market symbol of the market orders were made in
1410
+ * @param {int} [since] the earliest time in ms to fetch orders for
1411
+ * @param {int} [limit] the maximum number of order structures to retrieve
1412
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1413
+ * @param {string} [params.side] 'buy' or 'sell'
1414
+ * @param {boolean} [params.paginate] set to true if you want to fetch orders with pagination
1415
+ * @param {int} params.until timestamp in ms of the latest order to fetch
1416
+ * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
1417
+ */
1418
+ await this.authenticateRest();
1419
+ await this.loadMarkets();
1420
+ let paginate = false;
1421
+ [paginate, params] = this.handleOptionAndParams(params, 'fetchOrders', 'paginate');
1422
+ if (paginate) {
1423
+ return await this.fetchPaginatedCallCursor('fetchOrders', symbol, since, limit, params, 'next', 'cursor', undefined, 50);
1424
+ }
1425
+ let request = {};
1426
+ let market = undefined;
1427
+ if (symbol !== undefined) {
1428
+ market = this.market(symbol);
1429
+ request['market'] = market['id'];
1430
+ }
1431
+ if (since !== undefined) {
1432
+ request['start_at'] = since;
1433
+ }
1434
+ if (limit !== undefined) {
1435
+ request['page_size'] = limit;
1436
+ }
1437
+ [request, params] = this.handleUntilOption('end_at', request, params);
1438
+ const response = await this.privateGetOrdersHistory(this.extend(request, params));
1439
+ //
1440
+ // {
1441
+ // "next": "eyJmaWx0ZXIiMsIm1hcmtlciI6eyJtYXJrZXIiOiIxNjc1NjUwMDE3NDMxMTAxNjk5N=",
1442
+ // "prev": "eyJmaWx0ZXIiOnsiTGltaXQiOjkwfSwidGltZSI6MTY4MTY3OTgzNzk3MTMwOTk1MywibWFya2VyIjp7Im1zMjExMD==",
1443
+ // "results": [
1444
+ // {
1445
+ // "account": "0x4638e3041366aa71720be63e32e53e1223316c7f0d56f7aa617542ed1e7512x",
1446
+ // "avg_fill_price": "26000",
1447
+ // "cancel_reason": "NOT_ENOUGH_MARGIN",
1448
+ // "client_id": "x1234",
1449
+ // "created_at": 1681493746016,
1450
+ // "flags": [
1451
+ // "REDUCE_ONLY"
1452
+ // ],
1453
+ // "id": "123456",
1454
+ // "instruction": "GTC",
1455
+ // "last_updated_at": 1681493746016,
1456
+ // "market": "BTC-USD-PERP",
1457
+ // "price": "26000",
1458
+ // "published_at": 1681493746016,
1459
+ // "received_at": 1681493746016,
1460
+ // "remaining_size": "0",
1461
+ // "seq_no": 1681471234972000000,
1462
+ // "side": "BUY",
1463
+ // "size": "0.05",
1464
+ // "status": "NEW",
1465
+ // "stp": "EXPIRE_MAKER",
1466
+ // "timestamp": 1681493746016,
1467
+ // "trigger_price": "26000",
1468
+ // "type": "MARKET"
1469
+ // }
1470
+ // ]
1471
+ // }
1472
+ //
1473
+ const orders = this.safeList(response, 'results', []);
1474
+ const paginationCursor = this.safeString(response, 'next');
1475
+ const ordersLength = orders.length;
1476
+ if ((paginationCursor !== undefined) && (ordersLength > 0)) {
1477
+ const first = orders[0];
1478
+ first['next'] = paginationCursor;
1479
+ orders[0] = first;
1480
+ }
1481
+ return this.parseOrders(orders, market, since, limit);
1482
+ }
1483
+ async fetchOpenOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1484
+ /**
1485
+ * @method
1486
+ * @name paradex#fetchOpenOrders
1487
+ * @description fetches information on multiple orders made by the user
1488
+ * @see https://docs.api.prod.paradex.trade/#paradex-rest-api-orders
1489
+ * @param {string} symbol unified market symbol of the market orders were made in
1490
+ * @param {int} [since] the earliest time in ms to fetch orders for
1491
+ * @param {int} [limit] the maximum number of order structures to retrieve
1492
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1493
+ * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
1494
+ */
1495
+ await this.authenticateRest();
1496
+ await this.loadMarkets();
1497
+ const request = {};
1498
+ let market = undefined;
1499
+ if (symbol !== undefined) {
1500
+ market = this.market(symbol);
1501
+ request['market'] = market['id'];
1502
+ }
1503
+ const response = await this.privateGetOrders(this.extend(request, params));
1504
+ //
1505
+ // {
1506
+ // "results": [
1507
+ // {
1508
+ // "account": "0x4638e3041366aa71720be63e32e53e1223316c7f0d56f7aa617542ed1e7512x",
1509
+ // "avg_fill_price": "26000",
1510
+ // "client_id": "x1234",
1511
+ // "cancel_reason": "NOT_ENOUGH_MARGIN",
1512
+ // "created_at": 1681493746016,
1513
+ // "flags": [
1514
+ // "REDUCE_ONLY"
1515
+ // ],
1516
+ // "id": "123456",
1517
+ // "instruction": "GTC",
1518
+ // "last_updated_at": 1681493746016,
1519
+ // "market": "BTC-USD-PERP",
1520
+ // "price": "26000",
1521
+ // "published_at": 1681493746016,
1522
+ // "received_at": 1681493746016,
1523
+ // "remaining_size": "0",
1524
+ // "seq_no": 1681471234972000000,
1525
+ // "side": "BUY",
1526
+ // "size": "0.05",
1527
+ // "status": "NEW",
1528
+ // "stp": "EXPIRE_MAKER",
1529
+ // "timestamp": 1681493746016,
1530
+ // "trigger_price": "26000",
1531
+ // "type": "MARKET"
1532
+ // }
1533
+ // ]
1534
+ // }
1535
+ //
1536
+ const orders = this.safeList(response, 'results', []);
1537
+ return this.parseOrders(orders, market, since, limit);
1538
+ }
1539
+ async fetchBalance(params = {}) {
1540
+ /**
1541
+ * @method
1542
+ * @name paradex#fetchBalance
1543
+ * @description query for balance and get the amount of funds available for trading or funds locked in orders
1544
+ * @see https://docs.api.prod.paradex.trade/#list-balances
1545
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1546
+ * @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
1547
+ */
1548
+ await this.authenticateRest();
1549
+ await this.loadMarkets();
1550
+ const response = await this.privateGetBalance();
1551
+ //
1552
+ // {
1553
+ // "results": [
1554
+ // {
1555
+ // "token": "USDC",
1556
+ // "size": "99980.2382266290601",
1557
+ // "last_updated_at": 1718529757240
1558
+ // }
1559
+ // ]
1560
+ // }
1561
+ //
1562
+ const data = this.safeList(response, 'results', []);
1563
+ return this.parseBalance(data);
1564
+ }
1565
+ parseBalance(response) {
1566
+ const result = { 'info': response };
1567
+ for (let i = 0; i < response.length; i++) {
1568
+ const balance = this.safeDict(response, i, {});
1569
+ const currencyId = this.safeString(balance, 'token');
1570
+ const code = this.safeCurrencyCode(currencyId);
1571
+ const account = this.account();
1572
+ account['total'] = this.safeString(balance, 'size');
1573
+ result[code] = account;
1574
+ }
1575
+ return this.safeBalance(result);
1576
+ }
1577
+ async fetchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1578
+ /**
1579
+ * @method
1580
+ * @name paradex#fetchMyTrades
1581
+ * @description fetch all trades made by the user
1582
+ * @see https://docs.api.prod.paradex.trade/#list-fills
1583
+ * @param {string} symbol unified market symbol
1584
+ * @param {int} [since] the earliest time in ms to fetch trades for
1585
+ * @param {int} [limit] the maximum number of trades structures to retrieve
1586
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1587
+ * @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
1588
+ * @param {int} [params.until] the latest time in ms to fetch entries for
1589
+ * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
1590
+ */
1591
+ await this.authenticateRest();
1592
+ await this.loadMarkets();
1593
+ let paginate = false;
1594
+ [paginate, params] = this.handleOptionAndParams(params, 'fetchMyTrades', 'paginate');
1595
+ if (paginate) {
1596
+ return await this.fetchPaginatedCallCursor('fetchMyTrades', symbol, since, limit, params, 'next', 'cursor', undefined, 100);
1597
+ }
1598
+ let request = {};
1599
+ let market = undefined;
1600
+ if (symbol !== undefined) {
1601
+ market = this.market(symbol);
1602
+ request['market'] = market['id'];
1603
+ }
1604
+ if (limit !== undefined) {
1605
+ request['page_size'] = limit;
1606
+ }
1607
+ if (since !== undefined) {
1608
+ request['start_at'] = since;
1609
+ }
1610
+ [request, params] = this.handleUntilOption('end_at', request, params);
1611
+ const response = await this.privateGetFills(this.extend(request, params));
1612
+ //
1613
+ // {
1614
+ // "next": null,
1615
+ // "prev": null,
1616
+ // "results": [
1617
+ // {
1618
+ // "id": "1718947571560201703986670001",
1619
+ // "side": "BUY",
1620
+ // "liquidity": "TAKER",
1621
+ // "market": "BTC-USD-PERP",
1622
+ // "order_id": "1718947571540201703992340000",
1623
+ // "price": "64852.9",
1624
+ // "size": "0.01",
1625
+ // "fee": "0.1945587",
1626
+ // "fee_currency": "USDC",
1627
+ // "created_at": 1718947571569,
1628
+ // "remaining_size": "0",
1629
+ // "client_id": "",
1630
+ // "fill_type": "FILL"
1631
+ // }
1632
+ // ]
1633
+ // }
1634
+ //
1635
+ const trades = this.safeList(response, 'results', []);
1636
+ for (let i = 0; i < trades.length; i++) {
1637
+ trades[i]['next'] = this.safeString(response, 'next');
1638
+ }
1639
+ return this.parseTrades(trades, market, since, limit);
1640
+ }
1641
+ async fetchPosition(symbol, params = {}) {
1642
+ /**
1643
+ * @method
1644
+ * @name paradex#fetchPositions
1645
+ * @description fetch data on an open position
1646
+ * @see https://docs.api.prod.paradex.trade/#list-open-positions
1647
+ * @param {string} symbol unified market symbol of the market the position is held in
1648
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1649
+ * @returns {object} a [position structure]{@link https://docs.ccxt.com/#/?id=position-structure}
1650
+ */
1651
+ await this.authenticateRest();
1652
+ await this.loadMarkets();
1653
+ const market = this.market(symbol);
1654
+ const positions = await this.fetchPositions([market['symbol']], params);
1655
+ return this.safeDict(positions, 0, {});
1656
+ }
1657
+ async fetchPositions(symbols = undefined, params = {}) {
1658
+ /**
1659
+ * @method
1660
+ * @name paradex#fetchPositions
1661
+ * @description fetch all open positions
1662
+ * @see https://docs.api.prod.paradex.trade/#list-open-positions
1663
+ * @param {string[]} [symbols] list of unified market symbols
1664
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1665
+ * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/#/?id=position-structure}
1666
+ */
1667
+ await this.authenticateRest();
1668
+ await this.loadMarkets();
1669
+ symbols = this.marketSymbols(symbols);
1670
+ const response = await this.privateGetPositions();
1671
+ //
1672
+ // {
1673
+ // "results": [
1674
+ // {
1675
+ // "id": "0x49ddd7a564c978f6e4089ff8355b56a42b7e2d48ba282cb5aad60f04bea0ec3-BTC-USD-PERP",
1676
+ // "market": "BTC-USD-PERP",
1677
+ // "status": "OPEN",
1678
+ // "side": "LONG",
1679
+ // "size": "0.01",
1680
+ // "average_entry_price": "64839.96053748",
1681
+ // "average_entry_price_usd": "64852.9",
1682
+ // "realized_pnl": "0",
1683
+ // "unrealized_pnl": "-2.39677214",
1684
+ // "unrealized_funding_pnl": "-0.11214013",
1685
+ // "cost": "648.39960537",
1686
+ // "cost_usd": "648.529",
1687
+ // "cached_funding_index": "35202.1002351",
1688
+ // "last_updated_at": 1718950074249,
1689
+ // "last_fill_id": "1718947571560201703986670001",
1690
+ // "seq_no": 1718950074249176253,
1691
+ // "liquidation_price": ""
1692
+ // }
1693
+ // ]
1694
+ // }
1695
+ //
1696
+ const data = this.safeList(response, 'results', []);
1697
+ return this.parsePositions(data, symbols);
1698
+ }
1699
+ parsePosition(position, market = undefined) {
1700
+ //
1701
+ // {
1702
+ // "id": "0x49ddd7a564c978f6e4089ff8355b56a42b7e2d48ba282cb5aad60f04bea0ec3-BTC-USD-PERP",
1703
+ // "market": "BTC-USD-PERP",
1704
+ // "status": "OPEN",
1705
+ // "side": "LONG",
1706
+ // "size": "0.01",
1707
+ // "average_entry_price": "64839.96053748",
1708
+ // "average_entry_price_usd": "64852.9",
1709
+ // "realized_pnl": "0",
1710
+ // "unrealized_pnl": "-2.39677214",
1711
+ // "unrealized_funding_pnl": "-0.11214013",
1712
+ // "cost": "648.39960537",
1713
+ // "cost_usd": "648.529",
1714
+ // "cached_funding_index": "35202.1002351",
1715
+ // "last_updated_at": 1718950074249,
1716
+ // "last_fill_id": "1718947571560201703986670001",
1717
+ // "seq_no": 1718950074249176253,
1718
+ // "liquidation_price": ""
1719
+ // }
1720
+ //
1721
+ const marketId = this.safeString(position, 'market');
1722
+ market = this.safeMarket(marketId, market);
1723
+ const symbol = market['symbol'];
1724
+ const side = this.safeStringLower(position, 'side');
1725
+ let quantity = this.safeString(position, 'size');
1726
+ if (side !== 'long') {
1727
+ quantity = Precise["default"].stringMul('-1', quantity);
1728
+ }
1729
+ const timestamp = this.safeInteger(position, 'time');
1730
+ return this.safePosition({
1731
+ 'info': position,
1732
+ 'id': this.safeString(position, 'id'),
1733
+ 'symbol': symbol,
1734
+ 'entryPrice': this.safeString(position, 'average_entry_price'),
1735
+ 'markPrice': undefined,
1736
+ 'notional': undefined,
1737
+ 'collateral': this.safeString(position, 'cost'),
1738
+ 'unrealizedPnl': this.safeString(position, 'unrealized_pnl'),
1739
+ 'side': side,
1740
+ 'contracts': this.parseNumber(quantity),
1741
+ 'contractSize': undefined,
1742
+ 'timestamp': timestamp,
1743
+ 'datetime': this.iso8601(timestamp),
1744
+ 'hedged': undefined,
1745
+ 'maintenanceMargin': undefined,
1746
+ 'maintenanceMarginPercentage': undefined,
1747
+ 'initialMargin': undefined,
1748
+ 'initialMarginPercentage': undefined,
1749
+ 'leverage': undefined,
1750
+ 'liquidationPrice': undefined,
1751
+ 'marginRatio': undefined,
1752
+ 'marginMode': undefined,
1753
+ 'percentage': undefined,
1754
+ });
1755
+ }
1756
+ async fetchLiquidations(symbol, since = undefined, limit = undefined, params = {}) {
1757
+ /**
1758
+ * @method
1759
+ * @name paradex#fetchLiquidations
1760
+ * @description retrieves the public liquidations of a trading pair
1761
+ * @see https://docs.api.prod.paradex.trade/#list-liquidations
1762
+ * @param {string} symbol unified CCXT market symbol
1763
+ * @param {int} [since] the earliest time in ms to fetch liquidations for
1764
+ * @param {int} [limit] the maximum number of liquidation structures to retrieve
1765
+ * @param {object} [params] exchange specific parameters for the huobi api endpoint
1766
+ * @param {int} [params.until] timestamp in ms of the latest liquidation
1767
+ * @returns {object} an array of [liquidation structures]{@link https://docs.ccxt.com/#/?id=liquidation-structure}
1768
+ */
1769
+ await this.authenticateRest();
1770
+ let request = {};
1771
+ if (since !== undefined) {
1772
+ request['from'] = since;
1773
+ }
1774
+ else {
1775
+ request['from'] = 1;
1776
+ }
1777
+ const market = this.market(symbol);
1778
+ [request, params] = this.handleUntilOption('to', request, params);
1779
+ const response = await this.privateGetLiquidations(this.extend(request, params));
1780
+ //
1781
+ // {
1782
+ // "results": [
1783
+ // {
1784
+ // "created_at": 1697213130097,
1785
+ // "id": "0x123456789"
1786
+ // }
1787
+ // ]
1788
+ // }
1789
+ //
1790
+ const data = this.safeList(response, 'results', []);
1791
+ return this.parseLiquidations(data, market, since, limit);
1792
+ }
1793
+ parseLiquidation(liquidation, market = undefined) {
1794
+ //
1795
+ // {
1796
+ // "created_at": 1697213130097,
1797
+ // "id": "0x123456789"
1798
+ // }
1799
+ //
1800
+ const timestamp = this.safeInteger(liquidation, 'created_at');
1801
+ return this.safeLiquidation({
1802
+ 'info': liquidation,
1803
+ 'symbol': undefined,
1804
+ 'contracts': undefined,
1805
+ 'contractSize': undefined,
1806
+ 'price': undefined,
1807
+ 'baseValue': undefined,
1808
+ 'quoteValue': undefined,
1809
+ 'timestamp': timestamp,
1810
+ 'datetime': this.iso8601(timestamp),
1811
+ });
1812
+ }
1813
+ async fetchDeposits(code = undefined, since = undefined, limit = undefined, params = {}) {
1814
+ /**
1815
+ * @method
1816
+ * @name paradex#fetchTransfers
1817
+ * @description fetch all deposits made to an account
1818
+ * @see https://docs.api.prod.paradex.trade/#paradex-rest-api-transfers
1819
+ * @param {string} code unified currency code
1820
+ * @param {int} [since] the earliest time in ms to fetch deposits for
1821
+ * @param {int} [limit] the maximum number of deposits structures to retrieve
1822
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1823
+ * @param {int} [params.until] the latest time in ms to fetch entries for
1824
+ * @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
1825
+ * @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure}
1826
+ */
1827
+ await this.authenticateRest();
1828
+ await this.loadMarkets();
1829
+ let paginate = false;
1830
+ [paginate, params] = this.handleOptionAndParams(params, 'fetchDeposits', 'paginate');
1831
+ if (paginate) {
1832
+ return await this.fetchPaginatedCallCursor('fetchDeposits', code, since, limit, params, 'next', 'cursor', undefined, 100);
1833
+ }
1834
+ let request = {};
1835
+ if (limit !== undefined) {
1836
+ request['page_size'] = limit;
1837
+ }
1838
+ if (since !== undefined) {
1839
+ request['start_at'] = since;
1840
+ }
1841
+ [request, params] = this.handleUntilOption('end_at', request, params);
1842
+ const response = await this.privateGetTransfers(this.extend(request, params));
1843
+ //
1844
+ // {
1845
+ // "next": null,
1846
+ // "prev": null,
1847
+ // "results": [
1848
+ // {
1849
+ // "id": "1718940471200201703989430000",
1850
+ // "account": "0x49ddd7a564c978f6e4089ff8355b56a42b7e2d48ba282cb5aad60f04bea0ec3",
1851
+ // "kind": "DEPOSIT",
1852
+ // "status": "COMPLETED",
1853
+ // "amount": "100000",
1854
+ // "token": "USDC",
1855
+ // "created_at": 1718940471208,
1856
+ // "last_updated_at": 1718941455546,
1857
+ // "txn_hash": "0x73a415ca558a97bbdcd1c43e52b45f1e0486a0a84b3bb4958035ad6c59cb866",
1858
+ // "external_txn_hash": "",
1859
+ // "socialized_loss_factor": ""
1860
+ // }
1861
+ // ]
1862
+ // }
1863
+ //
1864
+ const rows = this.safeList(response, 'results', []);
1865
+ const deposits = [];
1866
+ for (let i = 0; i < rows.length; i++) {
1867
+ const row = rows[i];
1868
+ if (row['kind'] === 'DEPOSIT') {
1869
+ deposits.push(row);
1870
+ }
1871
+ }
1872
+ return this.parseTransactions(deposits, undefined, since, limit);
1873
+ }
1874
+ async fetchWithdrawals(code = undefined, since = undefined, limit = undefined, params = {}) {
1875
+ /**
1876
+ * @method
1877
+ * @name paradex#fetchWithdrawals
1878
+ * @description fetch all withdrawals made from an account
1879
+ * @see https://docs.api.prod.paradex.trade/#paradex-rest-api-transfers
1880
+ * @param {string} code unified currency code
1881
+ * @param {int} [since] the earliest time in ms to fetch withdrawals for
1882
+ * @param {int} [limit] the maximum number of withdrawals structures to retrieve
1883
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1884
+ * @param {int} [params.until] the latest time in ms to fetch withdrawals for
1885
+ * @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
1886
+ * @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure}
1887
+ */
1888
+ await this.authenticateRest();
1889
+ await this.loadMarkets();
1890
+ let paginate = false;
1891
+ [paginate, params] = this.handleOptionAndParams(params, 'fetchWithdrawals', 'paginate');
1892
+ if (paginate) {
1893
+ return await this.fetchPaginatedCallCursor('fetchWithdrawals', code, since, limit, params, 'next', 'cursor', undefined, 100);
1894
+ }
1895
+ let request = {};
1896
+ if (limit !== undefined) {
1897
+ request['page_size'] = limit;
1898
+ }
1899
+ if (since !== undefined) {
1900
+ request['start_at'] = since;
1901
+ }
1902
+ [request, params] = this.handleUntilOption('end_at', request, params);
1903
+ const response = await this.privateGetTransfers(this.extend(request, params));
1904
+ //
1905
+ // {
1906
+ // "next": null,
1907
+ // "prev": null,
1908
+ // "results": [
1909
+ // {
1910
+ // "id": "1718940471200201703989430000",
1911
+ // "account": "0x49ddd7a564c978f6e4089ff8355b56a42b7e2d48ba282cb5aad60f04bea0ec3",
1912
+ // "kind": "DEPOSIT",
1913
+ // "status": "COMPLETED",
1914
+ // "amount": "100000",
1915
+ // "token": "USDC",
1916
+ // "created_at": 1718940471208,
1917
+ // "last_updated_at": 1718941455546,
1918
+ // "txn_hash": "0x73a415ca558a97bbdcd1c43e52b45f1e0486a0a84b3bb4958035ad6c59cb866",
1919
+ // "external_txn_hash": "",
1920
+ // "socialized_loss_factor": ""
1921
+ // }
1922
+ // ]
1923
+ // }
1924
+ //
1925
+ const rows = this.safeList(response, 'results', []);
1926
+ const deposits = [];
1927
+ for (let i = 0; i < rows.length; i++) {
1928
+ const row = rows[i];
1929
+ if (row['kind'] === 'WITHDRAWAL') {
1930
+ deposits.push(row);
1931
+ }
1932
+ }
1933
+ return this.parseTransactions(deposits, undefined, since, limit);
1934
+ }
1935
+ parseTransaction(transaction, currency = undefined) {
1936
+ //
1937
+ // fetchDeposits & fetchWithdrawals
1938
+ //
1939
+ // {
1940
+ // "id": "1718940471200201703989430000",
1941
+ // "account": "0x49ddd7a564c978f6e4089ff8355b56a42b7e2d48ba282cb5aad60f04bea0ec3",
1942
+ // "kind": "DEPOSIT",
1943
+ // "status": "COMPLETED",
1944
+ // "amount": "100000",
1945
+ // "token": "USDC",
1946
+ // "created_at": 1718940471208,
1947
+ // "last_updated_at": 1718941455546,
1948
+ // "txn_hash": "0x73a415ca558a97bbdcd1c43e52b45f1e0486a0a84b3bb4958035ad6c59cb866",
1949
+ // "external_txn_hash": "",
1950
+ // "socialized_loss_factor": ""
1951
+ // }
1952
+ //
1953
+ const id = this.safeString(transaction, 'id');
1954
+ const address = this.safeString(transaction, 'account');
1955
+ const txid = this.safeString(transaction, 'txn_hash');
1956
+ const currencyId = this.safeString(transaction, 'token');
1957
+ const code = this.safeCurrencyCode(currencyId, currency);
1958
+ const timestamp = this.safeInteger(transaction, 'created_at');
1959
+ const updated = this.safeInteger(transaction, 'last_updated_at');
1960
+ let type = this.safeString(transaction, 'kind');
1961
+ type = (type === 'DEPOSIT') ? 'deposit' : 'withdrawal';
1962
+ const status = this.parseTransactionStatus(this.safeString(transaction, 'status'));
1963
+ const amount = this.safeNumber(transaction, 'amount');
1964
+ return {
1965
+ 'info': transaction,
1966
+ 'id': id,
1967
+ 'txid': txid,
1968
+ 'timestamp': timestamp,
1969
+ 'datetime': this.iso8601(timestamp),
1970
+ 'network': undefined,
1971
+ 'address': address,
1972
+ 'addressTo': address,
1973
+ 'addressFrom': undefined,
1974
+ 'tag': undefined,
1975
+ 'tagTo': undefined,
1976
+ 'tagFrom': undefined,
1977
+ 'type': type,
1978
+ 'amount': amount,
1979
+ 'currency': code,
1980
+ 'status': status,
1981
+ 'updated': updated,
1982
+ 'internal': undefined,
1983
+ 'comment': undefined,
1984
+ 'fee': undefined,
1985
+ };
1986
+ }
1987
+ parseTransactionStatus(status) {
1988
+ const statuses = {
1989
+ 'PENDING': 'pending',
1990
+ 'AVAILABLE': 'pending',
1991
+ 'COMPLETED': 'ok',
1992
+ 'FAILED': 'failed',
1993
+ };
1994
+ return this.safeString(statuses, status, status);
1995
+ }
1996
+ sign(path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
1997
+ let url = this.implodeHostname(this.urls['api'][this.version]) + '/' + this.implodeParams(path, params);
1998
+ const query = this.omit(params, this.extractParams(path));
1999
+ if (api === 'public') {
2000
+ if (Object.keys(query).length) {
2001
+ url += '?' + this.urlencode(query);
2002
+ }
2003
+ }
2004
+ else if (api === 'private') {
2005
+ this.checkRequiredCredentials();
2006
+ headers = {
2007
+ 'Accept': 'application/json',
2008
+ 'PARADEX-PARTNER': this.safeString(this.options, 'broker', 'CCXT'),
2009
+ };
2010
+ // TODO: optimize
2011
+ if (path === 'auth') {
2012
+ headers['PARADEX-STARKNET-ACCOUNT'] = query['account'];
2013
+ headers['PARADEX-STARKNET-SIGNATURE'] = query['signature'];
2014
+ headers['PARADEX-TIMESTAMP'] = query['timestamp'].toString();
2015
+ headers['PARADEX-SIGNATURE-EXPIRATION'] = query['expiration'].toString();
2016
+ }
2017
+ else if (path === 'onboarding') {
2018
+ headers['PARADEX-ETHEREUM-ACCOUNT'] = this.walletAddress;
2019
+ headers['PARADEX-STARKNET-ACCOUNT'] = query['account'];
2020
+ headers['PARADEX-STARKNET-SIGNATURE'] = query['signature'];
2021
+ headers['PARADEX-TIMESTAMP'] = this.nonce().toString();
2022
+ headers['Content-Type'] = 'application/json';
2023
+ body = this.json({
2024
+ 'public_key': query['public_key'],
2025
+ });
2026
+ }
2027
+ else {
2028
+ const token = this.options['authToken'];
2029
+ headers['Authorization'] = 'Bearer ' + token;
2030
+ if (method === 'POST') {
2031
+ headers['Content-Type'] = 'application/json';
2032
+ body = this.json(query);
2033
+ }
2034
+ else {
2035
+ url = url + '?' + this.urlencode(query);
2036
+ }
2037
+ }
2038
+ // headers = {
2039
+ // 'Accept': 'application/json',
2040
+ // 'Authorization': 'Bearer ' + this.apiKey,
2041
+ // };
2042
+ // if (method === 'POST') {
2043
+ // body = this.json (query);
2044
+ // headers['Content-Type'] = 'application/json';
2045
+ // } else {
2046
+ // if (Object.keys (query).length) {
2047
+ // url += '?' + this.urlencode (query);
2048
+ // }
2049
+ // }
2050
+ }
2051
+ return { 'url': url, 'method': method, 'body': body, 'headers': headers };
2052
+ }
2053
+ handleErrors(httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) {
2054
+ if (!response) {
2055
+ return undefined; // fallback to default error handler
2056
+ }
2057
+ //
2058
+ // {
2059
+ // "data": null,
2060
+ // "error": "NOT_ONBOARDED",
2061
+ // "message": "User has never called /onboarding endpoint"
2062
+ // }
2063
+ //
2064
+ const errorCode = this.safeString(response, 'error');
2065
+ if (errorCode !== undefined) {
2066
+ const feedback = this.id + ' ' + body;
2067
+ this.throwBroadlyMatchedException(this.exceptions['broad'], body, feedback);
2068
+ this.throwExactlyMatchedException(this.exceptions['exact'], errorCode, feedback);
2069
+ throw new errors.ExchangeError(feedback); // unknown message
2070
+ }
2071
+ return undefined;
2072
+ }
2073
+ }
2074
+
2075
+ module.exports = paradex;