ccxt 4.3.18 → 4.3.20

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 (173) hide show
  1. package/README.md +7 -5
  2. package/dist/cjs/ccxt.js +6 -1
  3. package/dist/cjs/src/abstract/woofipro.js +9 -0
  4. package/dist/cjs/src/ascendex.js +3 -4
  5. package/dist/cjs/src/base/Exchange.js +45 -2
  6. package/dist/cjs/src/base/functions/crypto.js +10 -3
  7. package/dist/cjs/src/base/functions/encode.js +6 -3
  8. package/dist/cjs/src/base/functions/number.js +8 -5
  9. package/dist/cjs/src/base/functions/rsa.js +5 -5
  10. package/dist/cjs/src/bigone.js +1 -1
  11. package/dist/cjs/src/bitfinex.js +25 -1
  12. package/dist/cjs/src/bitfinex2.js +59 -51
  13. package/dist/cjs/src/bitget.js +4 -5
  14. package/dist/cjs/src/bitmart.js +3 -3
  15. package/dist/cjs/src/bitstamp.js +1 -3
  16. package/dist/cjs/src/bybit.js +39 -9
  17. package/dist/cjs/src/coinex.js +360 -560
  18. package/dist/cjs/src/coinlist.js +1 -2
  19. package/dist/cjs/src/deribit.js +1 -1
  20. package/dist/cjs/src/hollaex.js +3 -3
  21. package/dist/cjs/src/indodax.js +1 -1
  22. package/dist/cjs/src/latoken.js +1 -1
  23. package/dist/cjs/src/mexc.js +1 -1
  24. package/dist/cjs/src/novadax.js +0 -1
  25. package/dist/cjs/src/okx.js +17 -0
  26. package/dist/cjs/src/phemex.js +17 -6
  27. package/dist/cjs/src/poloniex.js +1 -2
  28. package/dist/cjs/src/pro/bitget.js +136 -192
  29. package/dist/cjs/src/pro/coinbaseinternational.js +9 -1
  30. package/dist/cjs/src/pro/htx.js +12 -7
  31. package/dist/cjs/src/pro/okx.js +85 -0
  32. package/dist/cjs/src/pro/woofipro.js +1263 -0
  33. package/dist/cjs/src/wavesexchange.js +2 -2
  34. package/dist/cjs/src/woo.js +17 -3
  35. package/dist/cjs/src/woofipro.js +2698 -0
  36. package/js/ccxt.d.ts +8 -2
  37. package/js/ccxt.js +6 -2
  38. package/js/src/abstract/bitget.d.ts +3 -0
  39. package/js/src/abstract/bybit.d.ts +1 -0
  40. package/js/src/abstract/okx.d.ts +1 -0
  41. package/js/src/abstract/woofipro.d.ts +122 -0
  42. package/js/src/abstract/woofipro.js +11 -0
  43. package/js/src/ace.d.ts +2 -2
  44. package/js/src/ascendex.d.ts +5 -15
  45. package/js/src/ascendex.js +3 -4
  46. package/js/src/base/Exchange.d.ts +26 -17
  47. package/js/src/base/Exchange.js +45 -2
  48. package/js/src/base/functions/crypto.d.ts +1 -1
  49. package/js/src/base/functions/crypto.js +10 -3
  50. package/js/src/base/functions/encode.d.ts +1 -1
  51. package/js/src/base/functions/encode.js +6 -3
  52. package/js/src/base/functions/number.d.ts +1 -1
  53. package/js/src/base/functions/number.js +8 -5
  54. package/js/src/base/functions/rsa.js +6 -6
  55. package/js/src/base/types.d.ts +4 -0
  56. package/js/src/bigone.d.ts +4 -14
  57. package/js/src/bigone.js +1 -1
  58. package/js/src/binance.d.ts +13 -71
  59. package/js/src/binancecoinm.d.ts +2 -22
  60. package/js/src/binanceusdm.d.ts +2 -22
  61. package/js/src/bingx.d.ts +4 -14
  62. package/js/src/bit2c.d.ts +2 -2
  63. package/js/src/bitbank.d.ts +2 -2
  64. package/js/src/bitbns.d.ts +2 -2
  65. package/js/src/bitfinex.d.ts +6 -16
  66. package/js/src/bitfinex.js +25 -1
  67. package/js/src/bitfinex2.d.ts +6 -16
  68. package/js/src/bitfinex2.js +59 -51
  69. package/js/src/bitflyer.d.ts +2 -2
  70. package/js/src/bitget.d.ts +7 -17
  71. package/js/src/bitget.js +4 -5
  72. package/js/src/bithumb.d.ts +3 -3
  73. package/js/src/bitmart.d.ts +5 -14
  74. package/js/src/bitmart.js +3 -3
  75. package/js/src/bitmex.d.ts +4 -4
  76. package/js/src/bitopro.d.ts +2 -2
  77. package/js/src/bitrue.d.ts +5 -5
  78. package/js/src/bitso.d.ts +2 -2
  79. package/js/src/bitstamp.d.ts +3 -3
  80. package/js/src/bitstamp.js +1 -3
  81. package/js/src/bitteam.d.ts +2 -2
  82. package/js/src/bitvavo.d.ts +5 -5
  83. package/js/src/bl3p.d.ts +2 -2
  84. package/js/src/blockchaincom.d.ts +2 -2
  85. package/js/src/blofin.d.ts +4 -14
  86. package/js/src/btcalpha.d.ts +2 -2
  87. package/js/src/btcbox.d.ts +2 -2
  88. package/js/src/btcmarkets.d.ts +2 -2
  89. package/js/src/btcturk.d.ts +2 -2
  90. package/js/src/bybit.d.ts +9 -56
  91. package/js/src/bybit.js +39 -9
  92. package/js/src/cex.d.ts +2 -2
  93. package/js/src/coinbase.d.ts +4 -4
  94. package/js/src/coinbasepro.d.ts +3 -3
  95. package/js/src/coincheck.d.ts +2 -2
  96. package/js/src/coinex.d.ts +7 -17
  97. package/js/src/coinex.js +360 -560
  98. package/js/src/coinlist.d.ts +5 -15
  99. package/js/src/coinlist.js +1 -2
  100. package/js/src/coinmate.d.ts +2 -2
  101. package/js/src/coinmetro.d.ts +3 -3
  102. package/js/src/coinone.d.ts +2 -2
  103. package/js/src/coinsph.d.ts +2 -2
  104. package/js/src/coinspot.d.ts +2 -2
  105. package/js/src/cryptocom.d.ts +2 -2
  106. package/js/src/currencycom.d.ts +3 -3
  107. package/js/src/delta.d.ts +5 -43
  108. package/js/src/deribit.d.ts +7 -55
  109. package/js/src/deribit.js +1 -1
  110. package/js/src/digifinex.d.ts +5 -15
  111. package/js/src/exmo.d.ts +2 -2
  112. package/js/src/gate.d.ts +6 -54
  113. package/js/src/gemini.d.ts +2 -2
  114. package/js/src/hitbtc.d.ts +4 -14
  115. package/js/src/hollaex.d.ts +3 -3
  116. package/js/src/hollaex.js +3 -3
  117. package/js/src/htx.d.ts +4 -14
  118. package/js/src/huobijp.d.ts +4 -4
  119. package/js/src/hyperliquid.d.ts +1 -1
  120. package/js/src/idex.d.ts +3 -3
  121. package/js/src/independentreserve.d.ts +2 -2
  122. package/js/src/indodax.d.ts +2 -2
  123. package/js/src/indodax.js +1 -1
  124. package/js/src/kraken.d.ts +4 -14
  125. package/js/src/krakenfutures.d.ts +4 -14
  126. package/js/src/kucoin.d.ts +5 -15
  127. package/js/src/kucoinfutures.d.ts +4 -14
  128. package/js/src/kuna.d.ts +2 -2
  129. package/js/src/latoken.d.ts +5 -15
  130. package/js/src/latoken.js +1 -1
  131. package/js/src/lbank.d.ts +2 -2
  132. package/js/src/luno.d.ts +2 -2
  133. package/js/src/lykke.d.ts +2 -2
  134. package/js/src/mercado.d.ts +2 -2
  135. package/js/src/mexc.d.ts +8 -28
  136. package/js/src/mexc.js +1 -1
  137. package/js/src/ndax.d.ts +2 -2
  138. package/js/src/novadax.d.ts +4 -15
  139. package/js/src/novadax.js +0 -1
  140. package/js/src/okcoin.d.ts +4 -14
  141. package/js/src/okx.d.ts +10 -68
  142. package/js/src/okx.js +17 -0
  143. package/js/src/onetrading.d.ts +2 -2
  144. package/js/src/paymium.d.ts +4 -14
  145. package/js/src/phemex.d.ts +5 -15
  146. package/js/src/phemex.js +17 -6
  147. package/js/src/poloniex.d.ts +3 -13
  148. package/js/src/poloniex.js +1 -2
  149. package/js/src/poloniexfutures.d.ts +2 -2
  150. package/js/src/pro/bitget.js +137 -193
  151. package/js/src/pro/coinbaseinternational.d.ts +3 -3
  152. package/js/src/pro/coinbaseinternational.js +9 -1
  153. package/js/src/pro/htx.js +12 -7
  154. package/js/src/pro/okx.d.ts +4 -1
  155. package/js/src/pro/okx.js +85 -0
  156. package/js/src/pro/woofipro.d.ts +47 -0
  157. package/js/src/pro/woofipro.js +1264 -0
  158. package/js/src/probit.d.ts +3 -3
  159. package/js/src/timex.d.ts +2 -2
  160. package/js/src/tokocrypto.d.ts +3 -3
  161. package/js/src/upbit.d.ts +2 -2
  162. package/js/src/wavesexchange.d.ts +3 -3
  163. package/js/src/wavesexchange.js +2 -2
  164. package/js/src/wazirx.d.ts +2 -2
  165. package/js/src/whitebit.d.ts +3 -13
  166. package/js/src/woo.d.ts +7 -17
  167. package/js/src/woo.js +17 -3
  168. package/js/src/woofipro.d.ts +131 -0
  169. package/js/src/woofipro.js +2699 -0
  170. package/js/src/yobit.d.ts +2 -2
  171. package/js/src/zaif.d.ts +2 -2
  172. package/js/src/zonda.d.ts +4 -14
  173. package/package.json +1 -1
@@ -0,0 +1,2698 @@
1
+ 'use strict';
2
+
3
+ var woofipro$1 = require('./abstract/woofipro.js');
4
+ var errors = require('./base/errors.js');
5
+ var number = require('./base/functions/number.js');
6
+ var Precise = require('./base/Precise.js');
7
+ var crypto = require('./base/functions/crypto.js');
8
+ var ed25519 = require('./static_dependencies/noble-curves/ed25519.js');
9
+ var sha3 = require('./static_dependencies/noble-hashes/sha3.js');
10
+ var secp256k1 = require('./static_dependencies/noble-curves/secp256k1.js');
11
+
12
+ // ---------------------------------------------------------------------------
13
+ // ---------------------------------------------------------------------------
14
+ /**
15
+ * @class woofipro
16
+ * @augments Exchange
17
+ */
18
+ class woofipro extends woofipro$1 {
19
+ describe() {
20
+ return this.deepExtend(super.describe(), {
21
+ 'id': 'woofipro',
22
+ 'name': 'WOOFI PRO',
23
+ 'countries': ['KY'],
24
+ 'rateLimit': 100,
25
+ 'version': 'v1',
26
+ 'certified': true,
27
+ 'pro': true,
28
+ 'hostname': 'dex.woo.org',
29
+ 'has': {
30
+ 'CORS': undefined,
31
+ 'spot': false,
32
+ 'margin': false,
33
+ 'swap': true,
34
+ 'future': false,
35
+ 'option': false,
36
+ 'addMargin': false,
37
+ 'cancelAllOrders': true,
38
+ 'cancelOrder': true,
39
+ 'cancelOrders': true,
40
+ 'cancelWithdraw': false,
41
+ 'closeAllPositions': false,
42
+ 'closePosition': false,
43
+ 'createConvertTrade': false,
44
+ 'createDepositAddress': false,
45
+ 'createMarketBuyOrderWithCost': false,
46
+ 'createMarketOrder': false,
47
+ 'createMarketOrderWithCost': false,
48
+ 'createMarketSellOrderWithCost': false,
49
+ 'createOrder': true,
50
+ 'createOrderWithTakeProfitAndStopLoss': true,
51
+ 'createReduceOnlyOrder': true,
52
+ 'createStopLimitOrder': false,
53
+ 'createStopLossOrder': true,
54
+ 'createStopMarketOrder': false,
55
+ 'createStopOrder': false,
56
+ 'createTakeProfitOrder': true,
57
+ 'createTrailingAmountOrder': false,
58
+ 'createTrailingPercentOrder': false,
59
+ 'createTriggerOrder': true,
60
+ 'fetchAccounts': false,
61
+ 'fetchBalance': true,
62
+ 'fetchCanceledOrders': false,
63
+ 'fetchClosedOrder': false,
64
+ 'fetchClosedOrders': true,
65
+ 'fetchConvertCurrencies': false,
66
+ 'fetchConvertQuote': false,
67
+ 'fetchCurrencies': true,
68
+ 'fetchDepositAddress': false,
69
+ 'fetchDeposits': true,
70
+ 'fetchDepositsWithdrawals': true,
71
+ 'fetchFundingHistory': true,
72
+ 'fetchFundingRate': true,
73
+ 'fetchFundingRateHistory': true,
74
+ 'fetchFundingRates': true,
75
+ 'fetchIndexOHLCV': false,
76
+ 'fetchLedger': true,
77
+ 'fetchLeverage': true,
78
+ 'fetchMarginAdjustmentHistory': false,
79
+ 'fetchMarginMode': false,
80
+ 'fetchMarkets': true,
81
+ 'fetchMarkOHLCV': false,
82
+ 'fetchMyTrades': true,
83
+ 'fetchOHLCV': true,
84
+ 'fetchOpenInterestHistory': false,
85
+ 'fetchOpenOrder': false,
86
+ 'fetchOpenOrders': true,
87
+ 'fetchOrder': true,
88
+ 'fetchOrderBook': true,
89
+ 'fetchOrders': true,
90
+ 'fetchOrderTrades': true,
91
+ 'fetchPosition': true,
92
+ 'fetchPositionMode': false,
93
+ 'fetchPositions': true,
94
+ 'fetchPremiumIndexOHLCV': false,
95
+ 'fetchStatus': true,
96
+ 'fetchTicker': false,
97
+ 'fetchTickers': false,
98
+ 'fetchTime': true,
99
+ 'fetchTrades': true,
100
+ 'fetchTradingFee': false,
101
+ 'fetchTradingFees': true,
102
+ 'fetchTransactions': 'emulated',
103
+ 'fetchTransfers': false,
104
+ 'fetchWithdrawals': true,
105
+ 'reduceMargin': false,
106
+ 'setLeverage': true,
107
+ 'setMargin': false,
108
+ 'setPositionMode': false,
109
+ 'transfer': false,
110
+ 'withdraw': true, // exchange have that endpoint disabled atm, but was once implemented in ccxt per old docs: https://kronosresearch.github.io/wootrade-documents/#token-withdraw
111
+ },
112
+ 'timeframes': {
113
+ '1m': '1m',
114
+ '5m': '5m',
115
+ '15m': '15m',
116
+ '30m': '30m',
117
+ '1h': '1h',
118
+ '4h': '4h',
119
+ '12h': '12h',
120
+ '1d': '1d',
121
+ '1w': '1w',
122
+ '1M': '1mon',
123
+ '1y': '1y',
124
+ },
125
+ 'urls': {
126
+ 'logo': 'https://github.com/ccxt/ccxt/assets/43336371/b1e7b348-a0fc-4605-8b7f-91176958fd69',
127
+ 'api': {
128
+ 'public': 'https://api-evm.orderly.org',
129
+ 'private': 'https://api-evm.orderly.org',
130
+ },
131
+ 'test': {
132
+ 'public': 'https://testnet-api-evm.orderly.org',
133
+ 'private': 'https://testnet-api-evm.orderly.org',
134
+ },
135
+ 'www': 'https://dex.woo.org',
136
+ 'doc': [
137
+ 'https://orderly.network/docs/build-on-evm/building-on-evm',
138
+ ],
139
+ 'fees': [
140
+ 'https://dex.woo.org/en/orderly',
141
+ ],
142
+ 'referral': {
143
+ 'url': 'https://dex.woo.org/en/trade?ref=CCXT',
144
+ 'discount': 0.05,
145
+ },
146
+ },
147
+ 'api': {
148
+ 'v1': {
149
+ 'public': {
150
+ 'get': {
151
+ 'public/volume/stats': 1,
152
+ 'public/broker/name': 1,
153
+ 'public/chain_info/{broker_id}': 1,
154
+ 'public/system_info': 1,
155
+ 'public/vault_balance': 1,
156
+ 'public/insurancefund': 1,
157
+ 'public/chain_info': 1,
158
+ 'faucet/usdc': 1,
159
+ 'public/account': 1,
160
+ 'get_account': 1,
161
+ 'registration_nonce': 1,
162
+ 'get_orderly_key': 1,
163
+ 'public/liquidation': 1,
164
+ 'public/liquidated_positions': 1,
165
+ 'public/config': 1,
166
+ 'public/campaign/ranking': 10,
167
+ 'public/campaign/stats': 10,
168
+ 'public/campaign/user': 10,
169
+ 'public/campaign/stats/details': 10,
170
+ 'public/campaigns': 10,
171
+ 'public/points/leaderboard': 1,
172
+ 'client/points': 1,
173
+ 'public/points/epoch': 1,
174
+ 'public/points/epoch_dates': 1,
175
+ 'public/referral/check_ref_code': 1,
176
+ 'public/referral/verify_ref_code': 1,
177
+ 'referral/admin_info': 1,
178
+ 'referral/info': 1,
179
+ 'referral/referee_info': 1,
180
+ 'referral/referee_rebate_summary': 1,
181
+ 'referral/referee_history': 1,
182
+ 'referral/referral_history': 1,
183
+ 'referral/rebate_summary': 1,
184
+ 'client/distribution_history': 1,
185
+ 'tv/config': 1,
186
+ 'tv/history': 1,
187
+ 'tv/symbol_info': 1,
188
+ 'public/funding_rate_history': 1,
189
+ 'public/funding_rate/{symbol}': 0.33,
190
+ 'public/funding_rates': 1,
191
+ 'public/info': 1,
192
+ 'public/info/{symbol}': 1,
193
+ 'public/market_trades': 1,
194
+ 'public/token': 1,
195
+ 'public/futures': 1,
196
+ 'public/futures/{symbol}': 1,
197
+ },
198
+ 'post': {
199
+ 'register_account': 1,
200
+ },
201
+ },
202
+ 'private': {
203
+ 'get': {
204
+ 'client/key_info': 6,
205
+ 'client/orderly_key_ip_restriction': 6,
206
+ 'order/{oid}': 1,
207
+ 'client/order/{client_order_id}': 1,
208
+ 'algo/order/{oid}': 1,
209
+ 'algo/client/order/{client_order_id}': 1,
210
+ 'orders': 1,
211
+ 'algo/orders': 1,
212
+ 'trade/{tid}': 1,
213
+ 'trades': 1,
214
+ 'order/{oid}/trades': 1,
215
+ 'client/liquidator_liquidations': 1,
216
+ 'liquidations': 1,
217
+ 'asset/history': 60,
218
+ 'client/holding': 1,
219
+ 'withdraw_nonce': 1,
220
+ 'settle_nonce': 1,
221
+ 'pnl_settlement/history': 1,
222
+ 'volume/user/daily': 60,
223
+ 'volume/user/stats': 60,
224
+ 'client/statistics': 60,
225
+ 'client/info': 60,
226
+ 'client/statistics/daily': 60,
227
+ 'positions': 3.33,
228
+ 'position/{symbol}': 3.33,
229
+ 'funding_fee/history': 30,
230
+ 'notification/inbox/notifications': 60,
231
+ 'notification/inbox/unread': 60,
232
+ 'volume/broker/daily': 60,
233
+ 'broker/fee_rate/default': 10,
234
+ 'broker/user_info': 10,
235
+ 'orderbook/{symbol}': 1,
236
+ 'kline': 1,
237
+ },
238
+ 'post': {
239
+ 'orderly_key': 1,
240
+ 'client/set_orderly_key_ip_restriction': 6,
241
+ 'client/reset_orderly_key_ip_restriction': 6,
242
+ 'order': 1,
243
+ 'batch-order': 10,
244
+ 'algo/order': 1,
245
+ 'liquidation': 1,
246
+ 'claim_insurance_fund': 1,
247
+ 'withdraw_request': 1,
248
+ 'settle_pnl': 1,
249
+ 'notification/inbox/mark_read': 60,
250
+ 'notification/inbox/mark_read_all': 60,
251
+ 'client/leverage': 120,
252
+ 'client/maintenance_config': 60,
253
+ 'delegate_signer': 10,
254
+ 'delegate_orderly_key': 10,
255
+ 'delegate_settle_pnl': 10,
256
+ 'delegate_withdraw_request': 10,
257
+ 'broker/fee_rate/set': 10,
258
+ 'broker/fee_rate/set_default': 10,
259
+ 'broker/fee_rate/default': 10,
260
+ 'referral/create': 10,
261
+ 'referral/update': 10,
262
+ 'referral/bind': 10,
263
+ 'referral/edit_split': 10,
264
+ },
265
+ 'put': {
266
+ 'order': 1,
267
+ 'algo/order': 1,
268
+ },
269
+ 'delete': {
270
+ 'order': 1,
271
+ 'algo/order': 1,
272
+ 'client/order': 1,
273
+ 'algo/client/order': 1,
274
+ 'algo/orders': 1,
275
+ 'orders': 1,
276
+ 'batch-order': 1,
277
+ 'client/batch-order': 1,
278
+ },
279
+ },
280
+ },
281
+ },
282
+ 'requiredCredentials': {
283
+ 'apiKey': true,
284
+ 'secret': true,
285
+ 'accountId': true,
286
+ 'privateKey': false,
287
+ },
288
+ 'fees': {
289
+ 'trading': {
290
+ 'tierBased': true,
291
+ 'percentage': true,
292
+ 'maker': this.parseNumber('0.0002'),
293
+ 'taker': this.parseNumber('0.0005'),
294
+ },
295
+ },
296
+ 'options': {
297
+ 'sandboxMode': false,
298
+ 'brokerId': 'CCXT',
299
+ 'verifyingContractAddress': '0x6F7a338F2aA472838dEFD3283eB360d4Dff5D203',
300
+ },
301
+ 'commonCurrencies': {},
302
+ 'exceptions': {
303
+ 'exact': {
304
+ '-1000': errors.ExchangeError,
305
+ '-1001': errors.AuthenticationError,
306
+ '-1002': errors.AuthenticationError,
307
+ '-1003': errors.RateLimitExceeded,
308
+ '-1004': errors.BadRequest,
309
+ '-1005': errors.BadRequest,
310
+ '-1006': errors.InvalidOrder,
311
+ '-1007': errors.BadRequest,
312
+ '-1008': errors.InvalidOrder,
313
+ '-1009': errors.InsufficientFunds,
314
+ '-1011': errors.NetworkError,
315
+ '-1012': errors.BadRequest,
316
+ '-1101': errors.InsufficientFunds,
317
+ '-1102': errors.InvalidOrder,
318
+ '-1103': errors.InvalidOrder,
319
+ '-1104': errors.InvalidOrder,
320
+ '-1105': errors.InvalidOrder,
321
+ '-1201': errors.BadRequest,
322
+ '-1202': errors.BadRequest,
323
+ '29': errors.BadRequest,
324
+ '9': errors.AuthenticationError,
325
+ '3': errors.AuthenticationError,
326
+ '2': errors.BadRequest,
327
+ '15': errors.BadRequest, // {"success":false,"code":15,"message":"BrokerId is not exist"}
328
+ },
329
+ 'broad': {},
330
+ },
331
+ 'precisionMode': number.TICK_SIZE,
332
+ });
333
+ }
334
+ setSandboxMode(enable) {
335
+ super.setSandboxMode(enable);
336
+ this.options['sandboxMode'] = enable;
337
+ }
338
+ async fetchStatus(params = {}) {
339
+ /**
340
+ * @method
341
+ * @name woofipro#fetchStatus
342
+ * @description the latest known information on the availability of the exchange API
343
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/public/get-system-maintenance-status
344
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
345
+ * @returns {object} a [status structure]{@link https://docs.ccxt.com/#/?id=exchange-status-structure}
346
+ */
347
+ const response = await this.v1PublicGetPublicSystemInfo(params);
348
+ //
349
+ // {
350
+ // "success": true,
351
+ // "data": {
352
+ // "status": 0,
353
+ // "msg": "System is functioning properly."
354
+ // },
355
+ // "timestamp": "1709274106602"
356
+ // }
357
+ //
358
+ const data = this.safeDict(response, 'data', {});
359
+ let status = this.safeString(data, 'status');
360
+ if (status === undefined) {
361
+ status = 'error';
362
+ }
363
+ else if (status === '0') {
364
+ status = 'ok';
365
+ }
366
+ else {
367
+ status = 'maintenance';
368
+ }
369
+ return {
370
+ 'status': status,
371
+ 'updated': undefined,
372
+ 'eta': undefined,
373
+ 'url': undefined,
374
+ 'info': response,
375
+ };
376
+ }
377
+ async fetchTime(params = {}) {
378
+ /**
379
+ * @method
380
+ * @name woofipro#fetchTime
381
+ * @description fetches the current integer timestamp in milliseconds from the exchange server
382
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/public/get-system-maintenance-status
383
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
384
+ * @returns {int} the current integer timestamp in milliseconds from the exchange server
385
+ */
386
+ const response = await this.v1PublicGetPublicSystemInfo(params);
387
+ //
388
+ // {
389
+ // "success": true,
390
+ // "data": {
391
+ // "status": 0,
392
+ // "msg": "System is functioning properly."
393
+ // },
394
+ // "timestamp": "1709274106602"
395
+ // }
396
+ //
397
+ return this.safeInteger(response, 'timestamp');
398
+ }
399
+ parseMarket(market) {
400
+ //
401
+ // {
402
+ // "symbol": "PERP_BTC_USDC",
403
+ // "quote_min": 123,
404
+ // "quote_max": 100000,
405
+ // "quote_tick": 0.1,
406
+ // "base_min": 0.00001,
407
+ // "base_max": 20,
408
+ // "base_tick": 0.00001,
409
+ // "min_notional": 1,
410
+ // "price_range": 0.02,
411
+ // "price_scope": 0.4,
412
+ // "std_liquidation_fee": 0.03,
413
+ // "liquidator_fee": 0.015,
414
+ // "claim_insurance_fund_discount": 0.0075,
415
+ // "funding_period": 8,
416
+ // "cap_funding": 0.000375,
417
+ // "floor_funding": -0.000375,
418
+ // "interest_rate": 0.0001,
419
+ // "created_time": 1684140107326,
420
+ // "updated_time": 1685345968053,
421
+ // "base_mmr": 0.05,
422
+ // "base_imr": 0.1,
423
+ // "imr_factor": 0.0002512,
424
+ // "liquidation_tier": "1"
425
+ // }
426
+ //
427
+ const marketId = this.safeString(market, 'symbol');
428
+ const parts = marketId.split('_');
429
+ const marketType = 'swap';
430
+ const baseId = this.safeString(parts, 1);
431
+ const quoteId = this.safeString(parts, 2);
432
+ const base = this.safeCurrencyCode(baseId);
433
+ const quote = this.safeCurrencyCode(quoteId);
434
+ const settleId = this.safeString(parts, 2);
435
+ const settle = this.safeCurrencyCode(settleId);
436
+ const symbol = base + '/' + quote + ':' + settle;
437
+ return {
438
+ 'id': marketId,
439
+ 'symbol': symbol,
440
+ 'base': base,
441
+ 'quote': quote,
442
+ 'settle': settle,
443
+ 'baseId': baseId,
444
+ 'quoteId': quoteId,
445
+ 'settleId': settleId,
446
+ 'type': marketType,
447
+ 'spot': false,
448
+ 'margin': false,
449
+ 'swap': true,
450
+ 'future': false,
451
+ 'option': false,
452
+ 'active': undefined,
453
+ 'contract': true,
454
+ 'linear': true,
455
+ 'inverse': undefined,
456
+ 'contractSize': this.parseNumber('1'),
457
+ 'expiry': undefined,
458
+ 'expiryDatetime': undefined,
459
+ 'strike': undefined,
460
+ 'optionType': undefined,
461
+ 'precision': {
462
+ 'amount': this.safeNumber(market, 'base_tick'),
463
+ 'price': this.safeNumber(market, 'quote_tick'),
464
+ },
465
+ 'limits': {
466
+ 'leverage': {
467
+ 'min': undefined,
468
+ 'max': undefined,
469
+ },
470
+ 'amount': {
471
+ 'min': this.safeNumber(market, 'base_min'),
472
+ 'max': this.safeNumber(market, 'base_max'),
473
+ },
474
+ 'price': {
475
+ 'min': this.safeNumber(market, 'quote_min'),
476
+ 'max': this.safeNumber(market, 'quote_max'),
477
+ },
478
+ 'cost': {
479
+ 'min': this.safeNumber(market, 'min_notional'),
480
+ 'max': undefined,
481
+ },
482
+ },
483
+ 'created': this.safeInteger(market, 'created_time'),
484
+ 'info': market,
485
+ };
486
+ }
487
+ async fetchMarkets(params = {}) {
488
+ /**
489
+ * @method
490
+ * @name woofipro#fetchMarkets
491
+ * @description retrieves data on all markets for woofipro
492
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/public/get-available-symbols
493
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
494
+ * @returns {object[]} an array of objects representing market data
495
+ */
496
+ const response = await this.v1PublicGetPublicInfo(params);
497
+ //
498
+ // {
499
+ // "success": true,
500
+ // "timestamp": 1702989203989,
501
+ // "data": {
502
+ // "rows": [
503
+ // {
504
+ // "symbol": "PERP_BTC_USDC",
505
+ // "quote_min": 123,
506
+ // "quote_max": 100000,
507
+ // "quote_tick": 0.1,
508
+ // "base_min": 0.00001,
509
+ // "base_max": 20,
510
+ // "base_tick": 0.00001,
511
+ // "min_notional": 1,
512
+ // "price_range": 0.02,
513
+ // "price_scope": 0.4,
514
+ // "std_liquidation_fee": 0.03,
515
+ // "liquidator_fee": 0.015,
516
+ // "claim_insurance_fund_discount": 0.0075,
517
+ // "funding_period": 8,
518
+ // "cap_funding": 0.000375,
519
+ // "floor_funding": -0.000375,
520
+ // "interest_rate": 0.0001,
521
+ // "created_time": 1684140107326,
522
+ // "updated_time": 1685345968053,
523
+ // "base_mmr": 0.05,
524
+ // "base_imr": 0.1,
525
+ // "imr_factor": 0.0002512,
526
+ // "liquidation_tier": "1"
527
+ // }
528
+ // ]
529
+ // }
530
+ // }
531
+ //
532
+ const data = this.safeDict(response, 'data', {});
533
+ const rows = this.safeList(data, 'rows', []);
534
+ return this.parseMarkets(rows);
535
+ }
536
+ async fetchCurrencies(params = {}) {
537
+ /**
538
+ * @method
539
+ * @name woofipro#fetchCurrencies
540
+ * @description fetches all available currencies on an exchange
541
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/public/get-token-info
542
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
543
+ * @returns {object} an associative dictionary of currencies
544
+ */
545
+ const result = {};
546
+ const response = await this.v1PublicGetPublicToken(params);
547
+ //
548
+ // {
549
+ // "success": true,
550
+ // "timestamp": 1702989203989,
551
+ // "data": {
552
+ // "rows": [{
553
+ // "token": "USDC",
554
+ // "decimals": 6,
555
+ // "minimum_withdraw_amount": 0.000001,
556
+ // "token_hash": "0xd6aca1be9729c13d677335161321649cccae6a591554772516700f986f942eaa",
557
+ // "chain_details": [{
558
+ // "chain_id": 43113,
559
+ // "contract_address": "0x5d64c9cfb0197775b4b3ad9be4d3c7976e0d8dc3",
560
+ // "cross_chain_withdrawal_fee": 123,
561
+ // "decimals": 6,
562
+ // "withdraw_fee": 2
563
+ // }]
564
+ // }
565
+ // ]
566
+ // }
567
+ // }
568
+ //
569
+ const data = this.safeDict(response, 'data', {});
570
+ const tokenRows = this.safeList(data, 'rows', []);
571
+ for (let i = 0; i < tokenRows.length; i++) {
572
+ const token = tokenRows[i];
573
+ const currencyId = this.safeString(token, 'token');
574
+ const networks = this.safeList(token, 'chain_details');
575
+ const code = this.safeCurrencyCode(currencyId);
576
+ let minPrecision = undefined;
577
+ const resultingNetworks = {};
578
+ for (let j = 0; j < networks.length; j++) {
579
+ const network = networks[j];
580
+ // TODO: transform chain id to human readable name
581
+ const networkId = this.safeString(network, 'chain_id');
582
+ const precision = this.parsePrecision(this.safeString(network, 'decimals'));
583
+ if (precision !== undefined) {
584
+ minPrecision = (minPrecision === undefined) ? precision : Precise["default"].stringMin(precision, minPrecision);
585
+ }
586
+ resultingNetworks[networkId] = {
587
+ 'id': networkId,
588
+ 'network': networkId,
589
+ 'limits': {
590
+ 'withdraw': {
591
+ 'min': undefined,
592
+ 'max': undefined,
593
+ },
594
+ 'deposit': {
595
+ 'min': undefined,
596
+ 'max': undefined,
597
+ },
598
+ },
599
+ 'active': undefined,
600
+ 'deposit': undefined,
601
+ 'withdraw': undefined,
602
+ 'fee': this.safeNumber(network, 'withdrawal_fee'),
603
+ 'precision': this.parseNumber(precision),
604
+ 'info': network,
605
+ };
606
+ }
607
+ result[code] = {
608
+ 'id': currencyId,
609
+ 'name': currencyId,
610
+ 'code': code,
611
+ 'precision': this.parseNumber(minPrecision),
612
+ 'active': undefined,
613
+ 'fee': undefined,
614
+ 'networks': resultingNetworks,
615
+ 'deposit': undefined,
616
+ 'withdraw': undefined,
617
+ 'limits': {
618
+ 'deposit': {
619
+ 'min': undefined,
620
+ 'max': undefined,
621
+ },
622
+ 'withdraw': {
623
+ 'min': this.safeNumber(token, 'minimum_withdraw_amount'),
624
+ 'max': undefined,
625
+ },
626
+ },
627
+ 'info': token,
628
+ };
629
+ }
630
+ return result;
631
+ }
632
+ parseTokenAndFeeTemp(item, feeTokenKey, feeAmountKey) {
633
+ const feeCost = this.safeString(item, feeAmountKey);
634
+ let fee = undefined;
635
+ if (feeCost !== undefined) {
636
+ const feeCurrencyId = this.safeString(item, feeTokenKey);
637
+ const feeCurrencyCode = this.safeCurrencyCode(feeCurrencyId);
638
+ fee = {
639
+ 'cost': feeCost,
640
+ 'currency': feeCurrencyCode,
641
+ };
642
+ }
643
+ return fee;
644
+ }
645
+ parseTrade(trade, market = undefined) {
646
+ //
647
+ // public/market_trades
648
+ //
649
+ // {
650
+ // "symbol": "SPOT_BTC_USDT",
651
+ // "side": "SELL",
652
+ // "executed_price": 46222.35,
653
+ // "executed_quantity": 0.0012,
654
+ // "executed_timestamp": "1683878609166"
655
+ // }
656
+ //
657
+ // fetchOrderTrades, fetchOrder
658
+ //
659
+ // {
660
+ // "id": "99119876",
661
+ // "symbol": "SPOT_WOO_USDT",
662
+ // "fee": "0.0024",
663
+ // "side": "BUY",
664
+ // "executed_timestamp": "1641481113084",
665
+ // "order_id": "87001234",
666
+ // "order_tag": "default", <-- this param only in "fetchOrderTrades"
667
+ // "executed_price": "1",
668
+ // "executed_quantity": "12",
669
+ // "fee_asset": "WOO",
670
+ // "is_maker": "1"
671
+ // }
672
+ //
673
+ const isFromFetchOrder = ('id' in trade);
674
+ const timestamp = this.safeInteger(trade, 'executed_timestamp');
675
+ const marketId = this.safeString(trade, 'symbol');
676
+ market = this.safeMarket(marketId, market);
677
+ const symbol = market['symbol'];
678
+ const price = this.safeString(trade, 'executed_price');
679
+ const amount = this.safeString(trade, 'executed_quantity');
680
+ const order_id = this.safeString(trade, 'order_id');
681
+ const fee = this.parseTokenAndFeeTemp(trade, 'fee_asset', 'fee');
682
+ const cost = Precise["default"].stringMul(price, amount);
683
+ const side = this.safeStringLower(trade, 'side');
684
+ const id = this.safeString(trade, 'id');
685
+ let takerOrMaker = undefined;
686
+ if (isFromFetchOrder) {
687
+ const isMaker = this.safeString(trade, 'is_maker') === '1';
688
+ takerOrMaker = isMaker ? 'maker' : 'taker';
689
+ }
690
+ return this.safeTrade({
691
+ 'id': id,
692
+ 'timestamp': timestamp,
693
+ 'datetime': this.iso8601(timestamp),
694
+ 'symbol': symbol,
695
+ 'side': side,
696
+ 'price': price,
697
+ 'amount': amount,
698
+ 'cost': cost,
699
+ 'order': order_id,
700
+ 'takerOrMaker': takerOrMaker,
701
+ 'type': undefined,
702
+ 'fee': fee,
703
+ 'info': trade,
704
+ }, market);
705
+ }
706
+ async fetchTrades(symbol, since = undefined, limit = undefined, params = {}) {
707
+ /**
708
+ * @method
709
+ * @name woofipro#fetchTrades
710
+ * @description get the list of most recent trades for a particular symbol
711
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/public/get-market-trades
712
+ * @param {string} symbol unified symbol of the market to fetch trades for
713
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
714
+ * @param {int} [limit] the maximum amount of trades to fetch
715
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
716
+ * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
717
+ */
718
+ await this.loadMarkets();
719
+ const market = this.market(symbol);
720
+ const request = {
721
+ 'symbol': market['id'],
722
+ };
723
+ if (limit !== undefined) {
724
+ request['limit'] = limit;
725
+ }
726
+ const response = await this.v1PublicGetPublicMarketTrades(this.extend(request, params));
727
+ //
728
+ // {
729
+ // "success": true,
730
+ // "timestamp": 1702989203989,
731
+ // "data": {
732
+ // "rows": [{
733
+ // "symbol": "PERP_ETH_USDC",
734
+ // "side": "BUY",
735
+ // "executed_price": 2050,
736
+ // "executed_quantity": 1,
737
+ // "executed_timestamp": 1683878609166
738
+ // }]
739
+ // }
740
+ // }
741
+ //
742
+ const data = this.safeDict(response, 'data', {});
743
+ const rows = this.safeList(data, 'rows', []);
744
+ return this.parseTrades(rows, market, since, limit);
745
+ }
746
+ parseFundingRate(fundingRate, market = undefined) {
747
+ //
748
+ // {
749
+ // "symbol":"PERP_AAVE_USDT",
750
+ // "est_funding_rate":-0.00003447,
751
+ // "est_funding_rate_timestamp":1653633959001,
752
+ // "last_funding_rate":-0.00002094,
753
+ // "last_funding_rate_timestamp":1653631200000,
754
+ // "next_funding_time":1653634800000,
755
+ // "sum_unitary_funding": 521.367
756
+ // }
757
+ //
758
+ //
759
+ const symbol = this.safeString(fundingRate, 'symbol');
760
+ market = this.market(symbol);
761
+ const nextFundingTimestamp = this.safeInteger(fundingRate, 'next_funding_time');
762
+ const estFundingRateTimestamp = this.safeInteger(fundingRate, 'est_funding_rate_timestamp');
763
+ const lastFundingRateTimestamp = this.safeInteger(fundingRate, 'last_funding_rate_timestamp');
764
+ return {
765
+ 'info': fundingRate,
766
+ 'symbol': market['symbol'],
767
+ 'markPrice': undefined,
768
+ 'indexPrice': undefined,
769
+ 'interestRate': this.parseNumber('0'),
770
+ 'estimatedSettlePrice': undefined,
771
+ 'timestamp': estFundingRateTimestamp,
772
+ 'datetime': this.iso8601(estFundingRateTimestamp),
773
+ 'fundingRate': this.safeNumber(fundingRate, 'est_funding_rate'),
774
+ 'fundingTimestamp': nextFundingTimestamp,
775
+ 'fundingDatetime': this.iso8601(nextFundingTimestamp),
776
+ 'nextFundingRate': undefined,
777
+ 'nextFundingTimestamp': undefined,
778
+ 'nextFundingDatetime': undefined,
779
+ 'previousFundingRate': this.safeNumber(fundingRate, 'last_funding_rate'),
780
+ 'previousFundingTimestamp': lastFundingRateTimestamp,
781
+ 'previousFundingDatetime': this.iso8601(lastFundingRateTimestamp),
782
+ };
783
+ }
784
+ async fetchFundingRate(symbol, params = {}) {
785
+ /**
786
+ * @method
787
+ * @name woofipro#fetchFundingRate
788
+ * @description fetch the current funding rate
789
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/public/get-predicted-funding-rate-for-one-market
790
+ * @param {string} symbol unified market symbol
791
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
792
+ * @returns {object} a [funding rate structure]{@link https://docs.ccxt.com/#/?id=funding-rate-structure}
793
+ */
794
+ await this.loadMarkets();
795
+ const market = this.market(symbol);
796
+ const request = {
797
+ 'symbol': market['id'],
798
+ };
799
+ const response = await this.v1PublicGetPublicFundingRateSymbol(this.extend(request, params));
800
+ //
801
+ // {
802
+ // "success": true,
803
+ // "timestamp": 1702989203989,
804
+ // "data": {
805
+ // "symbol": "PERP_ETH_USDC",
806
+ // "est_funding_rate": 123,
807
+ // "est_funding_rate_timestamp": 1683880020000,
808
+ // "last_funding_rate": 0.0001,
809
+ // "last_funding_rate_timestamp": 1683878400000,
810
+ // "next_funding_time": 1683907200000,
811
+ // "sum_unitary_funding": 521.367
812
+ // }
813
+ // }
814
+ //
815
+ const data = this.safeDict(response, 'data', {});
816
+ return this.parseFundingRate(data, market);
817
+ }
818
+ async fetchFundingRates(symbols = undefined, params = {}) {
819
+ /**
820
+ * @method
821
+ * @name woofipro#fetchFundingRates
822
+ * @description fetch the current funding rates
823
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/public/get-predicted-funding-rates-for-all-markets
824
+ * @param {string[]} symbols unified market symbols
825
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
826
+ * @returns {object[]} an array of [funding rate structures]{@link https://docs.ccxt.com/#/?id=funding-rate-structure}
827
+ */
828
+ await this.loadMarkets();
829
+ symbols = this.marketSymbols(symbols);
830
+ const response = await this.v1PublicGetPublicFundingRates(params);
831
+ //
832
+ // {
833
+ // "success": true,
834
+ // "timestamp": 1702989203989,
835
+ // "data": {
836
+ // "rows": [{
837
+ // "symbol": "PERP_ETH_USDC",
838
+ // "est_funding_rate": 123,
839
+ // "est_funding_rate_timestamp": 1683880020000,
840
+ // "last_funding_rate": 0.0001,
841
+ // "last_funding_rate_timestamp": 1683878400000,
842
+ // "next_funding_time": 1683907200000,
843
+ // "sum_unitary_funding": 521.367
844
+ // }]
845
+ // }
846
+ // }
847
+ //
848
+ const data = this.safeDict(response, 'data', {});
849
+ const rows = this.safeList(data, 'rows', []);
850
+ const result = this.parseFundingRates(rows);
851
+ return this.filterByArray(result, 'symbol', symbols);
852
+ }
853
+ async fetchFundingRateHistory(symbol = undefined, since = undefined, limit = undefined, params = {}) {
854
+ /**
855
+ * @method
856
+ * @name woofipro#fetchFundingRateHistory
857
+ * @description fetches historical funding rate prices
858
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/public/get-funding-rate-history-for-one-market
859
+ * @param {string} symbol unified symbol of the market to fetch the funding rate history for
860
+ * @param {int} [since] timestamp in ms of the earliest funding rate to fetch
861
+ * @param {int} [limit] the maximum amount of [funding rate structures]{@link https://docs.ccxt.com/#/?id=funding-rate-history-structure} to fetch
862
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
863
+ * @param {int} [params.until] timestamp in ms of the latest funding rate
864
+ * @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)
865
+ * @returns {object[]} a list of [funding rate structures]{@link https://docs.ccxt.com/#/?id=funding-rate-history-structure}
866
+ */
867
+ await this.loadMarkets();
868
+ let paginate = false;
869
+ [paginate, params] = this.handleOptionAndParams(params, 'fetchFundingRateHistory', 'paginate');
870
+ if (paginate) {
871
+ return await this.fetchPaginatedCallIncremental('fetchFundingRateHistory', symbol, since, limit, params, 'page', 25);
872
+ }
873
+ let request = {};
874
+ if (symbol !== undefined) {
875
+ const market = this.market(symbol);
876
+ symbol = market['symbol'];
877
+ request['symbol'] = market['id'];
878
+ }
879
+ if (since !== undefined) {
880
+ request['start_t'] = since;
881
+ }
882
+ [request, params] = this.handleUntilOption('end_t', request, params, 0.001);
883
+ const response = await this.v1PublicGetPublicFundingRateHistory(this.extend(request, params));
884
+ //
885
+ // {
886
+ // "success": true,
887
+ // "timestamp": 1702989203989,
888
+ // "data": {
889
+ // "rows": [{
890
+ // "symbol": "PERP_ETH_USDC",
891
+ // "funding_rate": 0.0001,
892
+ // "funding_rate_timestamp": 1684224000000,
893
+ // "next_funding_time": 1684252800000
894
+ // }],
895
+ // "meta": {
896
+ // "total": 9,
897
+ // "records_per_page": 25,
898
+ // "current_page": 1
899
+ // }
900
+ // }
901
+ // }
902
+ //
903
+ const data = this.safeDict(response, 'data', {});
904
+ const result = this.safeList(data, 'rows', []);
905
+ const rates = [];
906
+ for (let i = 0; i < result.length; i++) {
907
+ const entry = result[i];
908
+ const marketId = this.safeString(entry, 'symbol');
909
+ const timestamp = this.safeInteger(entry, 'funding_rate_timestamp');
910
+ rates.push({
911
+ 'info': entry,
912
+ 'symbol': this.safeSymbol(marketId),
913
+ 'fundingRate': this.safeNumber(entry, 'funding_rate'),
914
+ 'timestamp': timestamp,
915
+ 'datetime': this.iso8601(timestamp),
916
+ });
917
+ }
918
+ const sorted = this.sortBy(rates, 'timestamp');
919
+ return this.filterBySymbolSinceLimit(sorted, symbol, since, limit);
920
+ }
921
+ async fetchTradingFees(params = {}) {
922
+ /**
923
+ * @method
924
+ * @name woofipro#fetchTradingFees
925
+ * @description fetch the trading fees for multiple markets
926
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/get-account-information
927
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
928
+ * @returns {object} a dictionary of [fee structures]{@link https://docs.ccxt.com/#/?id=fee-structure} indexed by market symbols
929
+ */
930
+ await this.loadMarkets();
931
+ const response = await this.v1PrivateGetClientInfo(params);
932
+ //
933
+ // {
934
+ // "success": true,
935
+ // "timestamp": 1702989203989,
936
+ // "data": {
937
+ // "account_id": "<string>",
938
+ // "email": "test@test.com",
939
+ // "account_mode": "FUTURES",
940
+ // "max_leverage": 20,
941
+ // "taker_fee_rate": 123,
942
+ // "maker_fee_rate": 123,
943
+ // "futures_taker_fee_rate": 123,
944
+ // "futures_maker_fee_rate": 123,
945
+ // "maintenance_cancel_orders": true,
946
+ // "imr_factor": {
947
+ // "PERP_BTC_USDC": 123,
948
+ // "PERP_ETH_USDC": 123,
949
+ // "PERP_NEAR_USDC": 123
950
+ // },
951
+ // "max_notional": {
952
+ // "PERP_BTC_USDC": 123,
953
+ // "PERP_ETH_USDC": 123,
954
+ // "PERP_NEAR_USDC": 123
955
+ // }
956
+ // }
957
+ // }
958
+ //
959
+ const data = this.safeDict(response, 'data', {});
960
+ const maker = this.safeString(data, 'futures_maker_fee_rate');
961
+ const taker = this.safeString(data, 'futures_taker_fee_rate');
962
+ const result = {};
963
+ for (let i = 0; i < this.symbols.length; i++) {
964
+ const symbol = this.symbols[i];
965
+ result[symbol] = {
966
+ 'info': response,
967
+ 'symbol': symbol,
968
+ 'maker': this.parseNumber(Precise["default"].stringDiv(maker, '10000')),
969
+ 'taker': this.parseNumber(Precise["default"].stringDiv(taker, '10000')),
970
+ 'percentage': true,
971
+ 'tierBased': true,
972
+ };
973
+ }
974
+ return result;
975
+ }
976
+ async fetchOrderBook(symbol, limit = undefined, params = {}) {
977
+ /**
978
+ * @method
979
+ * @name woofipro#fetchOrderBook
980
+ * @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
981
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/orderbook-snapshot
982
+ * @param {string} symbol unified symbol of the market to fetch the order book for
983
+ * @param {int} [limit] the maximum amount of order book entries to return
984
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
985
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
986
+ */
987
+ await this.loadMarkets();
988
+ const market = this.market(symbol);
989
+ const request = {
990
+ 'symbol': market['id'],
991
+ };
992
+ if (limit !== undefined) {
993
+ limit = Math.min(limit, 1000);
994
+ request['max_level'] = limit;
995
+ }
996
+ const response = await this.v1PrivateGetOrderbookSymbol(this.extend(request, params));
997
+ //
998
+ // {
999
+ // "success": true,
1000
+ // "timestamp": 1702989203989,
1001
+ // "data": {
1002
+ // "asks": [{
1003
+ // "price": 10669.4,
1004
+ // "quantity": 1.56263218
1005
+ // }],
1006
+ // "bids": [{
1007
+ // "price": 10669.4,
1008
+ // "quantity": 1.56263218
1009
+ // }],
1010
+ // "timestamp": 123
1011
+ // }
1012
+ // }
1013
+ //
1014
+ const data = this.safeDict(response, 'data', {});
1015
+ const timestamp = this.safeInteger(data, 'timestamp');
1016
+ return this.parseOrderBook(data, symbol, timestamp, 'bids', 'asks', 'price', 'quantity');
1017
+ }
1018
+ parseOHLCV(ohlcv, market = undefined) {
1019
+ return [
1020
+ this.safeInteger(ohlcv, 'start_timestamp'),
1021
+ this.safeNumber(ohlcv, 'open'),
1022
+ this.safeNumber(ohlcv, 'high'),
1023
+ this.safeNumber(ohlcv, 'low'),
1024
+ this.safeNumber(ohlcv, 'close'),
1025
+ this.safeNumber(ohlcv, 'volume'),
1026
+ ];
1027
+ }
1028
+ async fetchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
1029
+ /**
1030
+ * @method
1031
+ * @name woofipro#fetchOHLCV
1032
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/get-kline
1033
+ * @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1034
+ * @param {string} symbol unified symbol of the market to fetch OHLCV data for
1035
+ * @param {string} timeframe the length of time each candle represents
1036
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
1037
+ * @param {int} [limit] max=1000, max=100 when since is defined and is less than (now - (999 * (timeframe in ms)))
1038
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1039
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
1040
+ */
1041
+ await this.loadMarkets();
1042
+ const market = this.market(symbol);
1043
+ const request = {
1044
+ 'symbol': market['id'],
1045
+ 'type': this.safeString(this.timeframes, timeframe, timeframe),
1046
+ };
1047
+ if (limit !== undefined) {
1048
+ request['limit'] = Math.min(limit, 1000);
1049
+ }
1050
+ const response = await this.v1PrivateGetKline(this.extend(request, params));
1051
+ const data = this.safeDict(response, 'data', {});
1052
+ //
1053
+ // {
1054
+ // "success": true,
1055
+ // "timestamp": 1702989203989,
1056
+ // "data": {
1057
+ // "rows": [{
1058
+ // "open": 66166.23,
1059
+ // "close": 66124.56,
1060
+ // "low": 66038.06,
1061
+ // "high": 66176.97,
1062
+ // "volume": 23.45528526,
1063
+ // "amount": 1550436.21725288,
1064
+ // "symbol": "PERP_BTC_USDC",
1065
+ // "type": "1m",
1066
+ // "start_timestamp": 1636388220000,
1067
+ // "end_timestamp": 1636388280000
1068
+ // }]
1069
+ // }
1070
+ // }
1071
+ //
1072
+ const rows = this.safeList(data, 'rows', []);
1073
+ return this.parseOHLCVs(rows, market, timeframe, since, limit);
1074
+ }
1075
+ parseOrder(order, market = undefined) {
1076
+ //
1077
+ // Possible input functions:
1078
+ // * createOrder
1079
+ // * createOrders
1080
+ // * cancelOrder
1081
+ // * fetchOrder
1082
+ // * fetchOrders
1083
+ // const isFromFetchOrder = ('order_tag' in order); TO_DO
1084
+ //
1085
+ // stop order after creating it:
1086
+ // {
1087
+ // "orderId": "1578938",
1088
+ // "clientOrderId": "0",
1089
+ // "algoType": "STOP_LOSS",
1090
+ // "quantity": "0.1"
1091
+ // }
1092
+ // stop order after fetching it:
1093
+ // {
1094
+ // "algoOrderId": "1578958",
1095
+ // "clientOrderId": "0",
1096
+ // "rootAlgoOrderId": "1578958",
1097
+ // "parentAlgoOrderId": "0",
1098
+ // "symbol": "SPOT_LTC_USDT",
1099
+ // "orderTag": "default",
1100
+ // "algoType": "STOP_LOSS",
1101
+ // "side": "BUY",
1102
+ // "quantity": "0.1",
1103
+ // "isTriggered": false,
1104
+ // "triggerPrice": "100",
1105
+ // "triggerStatus": "USELESS",
1106
+ // "type": "LIMIT",
1107
+ // "rootAlgoStatus": "CANCELLED",
1108
+ // "algoStatus": "CANCELLED",
1109
+ // "triggerPriceType": "MARKET_PRICE",
1110
+ // "price": "75",
1111
+ // "triggerTime": "0",
1112
+ // "totalExecutedQuantity": "0",
1113
+ // "averageExecutedPrice": "0",
1114
+ // "totalFee": "0",
1115
+ // "feeAsset": '',
1116
+ // "reduceOnly": false,
1117
+ // "createdTime": "1686149609.744",
1118
+ // "updatedTime": "1686149903.362"
1119
+ // }
1120
+ //
1121
+ const timestamp = this.safeIntegerN(order, ['timestamp', 'created_time', 'createdTime']);
1122
+ const orderId = this.safeStringN(order, ['order_id', 'orderId', 'algoOrderId']);
1123
+ const clientOrderId = this.omitZero(this.safeString2(order, 'client_order_id', 'clientOrderId')); // Somehow, this always returns 0 for limit order
1124
+ const marketId = this.safeString(order, 'symbol');
1125
+ market = this.safeMarket(marketId, market);
1126
+ const symbol = market['symbol'];
1127
+ const price = this.safeString2(order, 'order_price', 'price');
1128
+ const amount = this.safeString2(order, 'order_quantity', 'quantity'); // This is base amount
1129
+ const cost = this.safeString2(order, 'order_amount', 'amount'); // This is quote amount
1130
+ const orderType = this.safeStringLower2(order, 'order_type', 'type');
1131
+ let status = this.safeValue2(order, 'status', 'algoStatus');
1132
+ const success = this.safeBool(order, 'success');
1133
+ if (success !== undefined) {
1134
+ status = (success) ? 'NEW' : 'REJECTED';
1135
+ }
1136
+ const side = this.safeStringLower(order, 'side');
1137
+ const filled = this.omitZero(this.safeValue2(order, 'executed', 'totalExecutedQuantity'));
1138
+ const average = this.omitZero(this.safeString2(order, 'average_executed_price', 'averageExecutedPrice'));
1139
+ const remaining = Precise["default"].stringSub(cost, filled);
1140
+ const fee = this.safeValue2(order, 'total_fee', 'totalFee');
1141
+ const feeCurrency = this.safeString2(order, 'fee_asset', 'feeAsset');
1142
+ const transactions = this.safeValue(order, 'Transactions');
1143
+ const stopPrice = this.safeNumber(order, 'triggerPrice');
1144
+ let takeProfitPrice = undefined;
1145
+ let stopLossPrice = undefined;
1146
+ const childOrders = this.safeValue(order, 'childOrders');
1147
+ if (childOrders !== undefined) {
1148
+ const first = this.safeValue(childOrders, 0);
1149
+ const innerChildOrders = this.safeValue(first, 'childOrders', []);
1150
+ const innerChildOrdersLength = innerChildOrders.length;
1151
+ if (innerChildOrdersLength > 0) {
1152
+ const takeProfitOrder = this.safeValue(innerChildOrders, 0);
1153
+ const stopLossOrder = this.safeValue(innerChildOrders, 1);
1154
+ takeProfitPrice = this.safeNumber(takeProfitOrder, 'triggerPrice');
1155
+ stopLossPrice = this.safeNumber(stopLossOrder, 'triggerPrice');
1156
+ }
1157
+ }
1158
+ const lastUpdateTimestamp = this.safeInteger2(order, 'updatedTime', 'updated_time');
1159
+ return this.safeOrder({
1160
+ 'id': orderId,
1161
+ 'clientOrderId': clientOrderId,
1162
+ 'timestamp': timestamp,
1163
+ 'datetime': this.iso8601(timestamp),
1164
+ 'lastTradeTimestamp': undefined,
1165
+ 'lastUpdateTimestamp': lastUpdateTimestamp,
1166
+ 'status': this.parseOrderStatus(status),
1167
+ 'symbol': symbol,
1168
+ 'type': this.parseOrderType(orderType),
1169
+ 'timeInForce': this.parseTimeInForce(orderType),
1170
+ 'postOnly': undefined,
1171
+ 'reduceOnly': this.safeBool(order, 'reduce_only'),
1172
+ 'side': side,
1173
+ 'price': price,
1174
+ 'stopPrice': stopPrice,
1175
+ 'triggerPrice': stopPrice,
1176
+ 'takeProfitPrice': takeProfitPrice,
1177
+ 'stopLossPrice': stopLossPrice,
1178
+ 'average': average,
1179
+ 'amount': amount,
1180
+ 'filled': filled,
1181
+ 'remaining': remaining,
1182
+ 'cost': cost,
1183
+ 'trades': transactions,
1184
+ 'fee': {
1185
+ 'cost': fee,
1186
+ 'currency': feeCurrency,
1187
+ },
1188
+ 'info': order,
1189
+ }, market);
1190
+ }
1191
+ parseTimeInForce(timeInForce) {
1192
+ const timeInForces = {
1193
+ 'ioc': 'IOC',
1194
+ 'fok': 'FOK',
1195
+ 'post_only': 'PO',
1196
+ };
1197
+ return this.safeString(timeInForces, timeInForce, undefined);
1198
+ }
1199
+ parseOrderStatus(status) {
1200
+ if (status !== undefined) {
1201
+ const statuses = {
1202
+ 'NEW': 'open',
1203
+ 'FILLED': 'closed',
1204
+ 'CANCEL_SENT': 'canceled',
1205
+ 'CANCEL_ALL_SENT': 'canceled',
1206
+ 'CANCELLED': 'canceled',
1207
+ 'PARTIAL_FILLED': 'open',
1208
+ 'REJECTED': 'rejected',
1209
+ 'INCOMPLETE': 'open',
1210
+ 'COMPLETED': 'closed',
1211
+ };
1212
+ return this.safeString(statuses, status, status);
1213
+ }
1214
+ return status;
1215
+ }
1216
+ parseOrderType(type) {
1217
+ const types = {
1218
+ 'LIMIT': 'limit',
1219
+ 'MARKET': 'market',
1220
+ 'POST_ONLY': 'limit',
1221
+ };
1222
+ return this.safeStringLower(types, type, type);
1223
+ }
1224
+ createOrderRequest(symbol, type, side, amount, price = undefined, params = {}) {
1225
+ /**
1226
+ * @method
1227
+ * @ignore
1228
+ * @name woofipro#createOrderRequest
1229
+ * @description helper function to build the request
1230
+ * @param {string} symbol unified symbol of the market to create an order in
1231
+ * @param {string} type 'market' or 'limit'
1232
+ * @param {string} side 'buy' or 'sell'
1233
+ * @param {float} amount how much you want to trade in units of the base currency
1234
+ * @param {float} [price] the price that the order is to be fullfilled, in units of the quote currency, ignored in market orders
1235
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1236
+ * @returns {object} request to be sent to the exchange
1237
+ */
1238
+ const reduceOnly = this.safeBool2(params, 'reduceOnly', 'reduce_only');
1239
+ const orderType = type.toUpperCase();
1240
+ const market = this.market(symbol);
1241
+ const orderSide = side.toUpperCase();
1242
+ const request = {
1243
+ 'symbol': market['id'],
1244
+ 'side': orderSide,
1245
+ };
1246
+ const stopPrice = this.safeString2(params, 'triggerPrice', 'stopPrice');
1247
+ const stopLoss = this.safeValue(params, 'stopLoss');
1248
+ const takeProfit = this.safeValue(params, 'takeProfit');
1249
+ const algoType = this.safeString(params, 'algoType');
1250
+ const isStop = stopPrice !== undefined || stopLoss !== undefined || takeProfit !== undefined || (this.safeValue(params, 'childOrders') !== undefined);
1251
+ const isMarket = orderType === 'MARKET';
1252
+ const timeInForce = this.safeStringLower(params, 'timeInForce');
1253
+ const postOnly = this.isPostOnly(isMarket, undefined, params);
1254
+ const orderQtyKey = isStop ? 'quantity' : 'order_quantity';
1255
+ const priceKey = isStop ? 'price' : 'order_price';
1256
+ const typeKey = isStop ? 'type' : 'order_type';
1257
+ request[typeKey] = orderType; // LIMIT/MARKET/IOC/FOK/POST_ONLY/ASK/BID
1258
+ if (!isStop) {
1259
+ if (postOnly) {
1260
+ request['order_type'] = 'POST_ONLY';
1261
+ }
1262
+ else if (timeInForce === 'fok') {
1263
+ request['order_type'] = 'FOK';
1264
+ }
1265
+ else if (timeInForce === 'ioc') {
1266
+ request['order_type'] = 'IOC';
1267
+ }
1268
+ }
1269
+ if (reduceOnly) {
1270
+ request['reduce_only'] = reduceOnly;
1271
+ }
1272
+ if (price !== undefined) {
1273
+ request[priceKey] = this.priceToPrecision(symbol, price);
1274
+ }
1275
+ if (isMarket && !isStop) {
1276
+ request[orderQtyKey] = this.amountToPrecision(symbol, amount);
1277
+ }
1278
+ else if (algoType !== 'POSITIONAL_TP_SL') {
1279
+ request[orderQtyKey] = this.amountToPrecision(symbol, amount);
1280
+ }
1281
+ const clientOrderId = this.safeStringN(params, ['clOrdID', 'clientOrderId', 'client_order_id']);
1282
+ if (clientOrderId !== undefined) {
1283
+ request['client_order_id'] = clientOrderId;
1284
+ }
1285
+ if (stopPrice !== undefined) {
1286
+ request['trigger_price'] = this.priceToPrecision(symbol, stopPrice);
1287
+ request['algo_type'] = 'STOP';
1288
+ }
1289
+ else if ((stopLoss !== undefined) || (takeProfit !== undefined)) {
1290
+ request['algo_type'] = 'TP_SL';
1291
+ const outterOrder = {
1292
+ 'symbol': market['id'],
1293
+ 'reduce_only': false,
1294
+ 'algo_type': 'POSITIONAL_TP_SL',
1295
+ 'child_orders': [],
1296
+ };
1297
+ const closeSide = (orderSide === 'BUY') ? 'SELL' : 'BUY';
1298
+ if (stopLoss !== undefined) {
1299
+ const stopLossPrice = this.safeNumber2(stopLoss, 'triggerPrice', 'price', stopLoss);
1300
+ const stopLossOrder = {
1301
+ 'side': closeSide,
1302
+ 'algo_type': 'TP_SL',
1303
+ 'trigger_price': this.priceToPrecision(symbol, stopLossPrice),
1304
+ 'type': 'LIMIT',
1305
+ 'reduce_only': true,
1306
+ };
1307
+ outterOrder['child_orders'].push(stopLossOrder);
1308
+ }
1309
+ if (takeProfit !== undefined) {
1310
+ const takeProfitPrice = this.safeNumber2(takeProfit, 'triggerPrice', 'price', takeProfit);
1311
+ const takeProfitOrder = {
1312
+ 'side': closeSide,
1313
+ 'algo_type': 'TP_SL',
1314
+ 'trigger_price': this.priceToPrecision(symbol, takeProfitPrice),
1315
+ 'type': 'LIMIT',
1316
+ 'reduce_only': true,
1317
+ };
1318
+ outterOrder['child_orders'].push(takeProfitOrder);
1319
+ }
1320
+ request['child_orders'] = [outterOrder];
1321
+ }
1322
+ params = this.omit(params, ['reduceOnly', 'reduce_only', 'clOrdID', 'clientOrderId', 'client_order_id', 'postOnly', 'timeInForce', 'stopPrice', 'triggerPrice', 'stopLoss', 'takeProfit']);
1323
+ return this.extend(request, params);
1324
+ }
1325
+ async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
1326
+ /**
1327
+ * @method
1328
+ * @name woofipro#createOrder
1329
+ * @description create a trade order
1330
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/create-order
1331
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/create-algo-order
1332
+ * @param {string} symbol unified symbol of the market to create an order in
1333
+ * @param {string} type 'market' or 'limit'
1334
+ * @param {string} side 'buy' or 'sell'
1335
+ * @param {float} amount how much of currency you want to trade in units of base currency
1336
+ * @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
1337
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1338
+ * @param {float} [params.triggerPrice] The price a trigger order is triggered at
1339
+ * @param {object} [params.takeProfit] *takeProfit object in params* containing the triggerPrice at which the attached take profit order will be triggered (perpetual swap markets only)
1340
+ * @param {float} [params.takeProfit.triggerPrice] take profit trigger price
1341
+ * @param {object} [params.stopLoss] *stopLoss object in params* containing the triggerPrice at which the attached stop loss order will be triggered (perpetual swap markets only)
1342
+ * @param {float} [params.stopLoss.triggerPrice] stop loss trigger price
1343
+ * @param {float} [params.algoType] 'STOP'or 'TP_SL' or 'POSITIONAL_TP_SL'
1344
+ * @param {float} [params.cost] *spot market buy only* the quote quantity that can be used as an alternative for the amount
1345
+ * @param {string} [params.clientOrderId] a unique id for the order
1346
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
1347
+ */
1348
+ await this.loadMarkets();
1349
+ const market = this.market(symbol);
1350
+ const request = this.createOrderRequest(symbol, type, side, amount, price, params);
1351
+ const stopPrice = this.safeString2(params, 'triggerPrice', 'stopPrice');
1352
+ const stopLoss = this.safeValue(params, 'stopLoss');
1353
+ const takeProfit = this.safeValue(params, 'takeProfit');
1354
+ const isStop = stopPrice !== undefined || stopLoss !== undefined || takeProfit !== undefined || (this.safeValue(params, 'childOrders') !== undefined);
1355
+ let response = undefined;
1356
+ if (isStop) {
1357
+ response = await this.v1PrivatePostAlgoOrder(request);
1358
+ //
1359
+ // {
1360
+ // "success": true,
1361
+ // "timestamp": 1702989203989,
1362
+ // "data": {
1363
+ // "order_id": 13,
1364
+ // "client_order_id": "testclientid",
1365
+ // "algo_type": "STOP",
1366
+ // "quantity": 100.12
1367
+ // }
1368
+ // }
1369
+ //
1370
+ }
1371
+ else {
1372
+ response = await this.v1PrivatePostOrder(request);
1373
+ //
1374
+ // {
1375
+ // "success": true,
1376
+ // "timestamp": 1702989203989,
1377
+ // "data": {
1378
+ // "order_id": 13,
1379
+ // "client_order_id": "testclientid",
1380
+ // "order_type": "LIMIT",
1381
+ // "order_price": 100.12,
1382
+ // "order_quantity": 0.987654,
1383
+ // "order_amount": 0.8,
1384
+ // "error_message": "none"
1385
+ // }
1386
+ // }
1387
+ //
1388
+ }
1389
+ const data = this.safeDict(response, 'data');
1390
+ data['timestamp'] = this.safeInteger(response, 'timestamp');
1391
+ const order = this.parseOrder(data, market);
1392
+ order['type'] = type;
1393
+ return order;
1394
+ }
1395
+ async createOrders(orders, params = {}) {
1396
+ /**
1397
+ * @method
1398
+ * @name woofipro#createOrders
1399
+ * @description *contract only* create a list of trade orders
1400
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/batch-create-order
1401
+ * @param {Array} orders list of orders to create, each object should contain the parameters required by createOrder, namely symbol, type, side, amount, price and params
1402
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
1403
+ */
1404
+ await this.loadMarkets();
1405
+ const ordersRequests = [];
1406
+ for (let i = 0; i < orders.length; i++) {
1407
+ const rawOrder = orders[i];
1408
+ const marketId = this.safeString(rawOrder, 'symbol');
1409
+ const type = this.safeString(rawOrder, 'type');
1410
+ const side = this.safeString(rawOrder, 'side');
1411
+ const amount = this.safeValue(rawOrder, 'amount');
1412
+ const price = this.safeValue(rawOrder, 'price');
1413
+ const orderParams = this.safeDict(rawOrder, 'params', {});
1414
+ const stopPrice = this.safeString2(orderParams, 'triggerPrice', 'stopPrice');
1415
+ const stopLoss = this.safeValue(orderParams, 'stopLoss');
1416
+ const takeProfit = this.safeValue(orderParams, 'takeProfit');
1417
+ const isStop = stopPrice !== undefined || stopLoss !== undefined || takeProfit !== undefined || (this.safeValue(orderParams, 'childOrders') !== undefined);
1418
+ if (isStop) {
1419
+ throw new errors.NotSupported(this.id + 'createOrders() only support non-stop order');
1420
+ }
1421
+ const orderRequest = this.createOrderRequest(marketId, type, side, amount, price, orderParams);
1422
+ ordersRequests.push(orderRequest);
1423
+ }
1424
+ const request = {
1425
+ 'orders': ordersRequests,
1426
+ };
1427
+ const response = await this.v1PrivatePostBatchOrder(this.extend(request, params));
1428
+ //
1429
+ // {
1430
+ // "success": true,
1431
+ // "timestamp": 1702989203989,
1432
+ // "data": {
1433
+ // "rows": [{
1434
+ // "order_id": 13,
1435
+ // "client_order_id": "testclientid",
1436
+ // "order_type": "LIMIT",
1437
+ // "order_price": 100.12,
1438
+ // "order_quantity": 0.987654,
1439
+ // "order_amount": 0.8,
1440
+ // "error_message": "none"
1441
+ // }]
1442
+ // }
1443
+ // }
1444
+ //
1445
+ const data = this.safeDict(response, 'data', {});
1446
+ const rows = this.safeList(data, 'rows', []);
1447
+ return this.parseOrders(rows);
1448
+ }
1449
+ async editOrder(id, symbol, type, side, amount = undefined, price = undefined, params = {}) {
1450
+ /**
1451
+ * @method
1452
+ * @name woofipro#editOrder
1453
+ * @description edit a trade order
1454
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/edit-order
1455
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/edit-algo-order
1456
+ * @param {string} id order id
1457
+ * @param {string} symbol unified symbol of the market to create an order in
1458
+ * @param {string} type 'market' or 'limit'
1459
+ * @param {string} side 'buy' or 'sell'
1460
+ * @param {float} amount how much of currency you want to trade in units of base currency
1461
+ * @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
1462
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1463
+ * @param {float} [params.triggerPrice] The price a trigger order is triggered at
1464
+ * @param {float} [params.stopLossPrice] price to trigger stop-loss orders
1465
+ * @param {float} [params.takeProfitPrice] price to trigger take-profit orders
1466
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
1467
+ */
1468
+ await this.loadMarkets();
1469
+ const market = this.market(symbol);
1470
+ const request = {
1471
+ 'order_id': id,
1472
+ };
1473
+ const stopPrice = this.safeStringN(params, ['triggerPrice', 'stopPrice', 'takeProfitPrice', 'stopLossPrice']);
1474
+ if (stopPrice !== undefined) {
1475
+ request['triggerPrice'] = this.priceToPrecision(symbol, stopPrice);
1476
+ }
1477
+ const isStop = (stopPrice !== undefined) || (this.safeValue(params, 'childOrders') !== undefined);
1478
+ const orderQtyKey = isStop ? 'quantity' : 'order_quantity';
1479
+ const priceKey = isStop ? 'price' : 'order_price';
1480
+ if (price !== undefined) {
1481
+ request[priceKey] = this.priceToPrecision(symbol, price);
1482
+ }
1483
+ if (amount !== undefined) {
1484
+ request[orderQtyKey] = this.amountToPrecision(symbol, amount);
1485
+ }
1486
+ params = this.omit(params, ['stopPrice', 'triggerPrice', 'takeProfitPrice', 'stopLossPrice', 'trailingTriggerPrice', 'trailingAmount', 'trailingPercent']);
1487
+ let response = undefined;
1488
+ if (isStop) {
1489
+ response = await this.v1PrivatePutAlgoOrder(this.extend(request, params));
1490
+ }
1491
+ else {
1492
+ request['symbol'] = market['id'];
1493
+ request['side'] = side.toUpperCase();
1494
+ const orderType = type.toUpperCase();
1495
+ const timeInForce = this.safeStringLower(params, 'timeInForce');
1496
+ const isMarket = orderType === 'MARKET';
1497
+ const postOnly = this.isPostOnly(isMarket, undefined, params);
1498
+ if (postOnly) {
1499
+ request['order_type'] = 'POST_ONLY';
1500
+ }
1501
+ else if (timeInForce === 'fok') {
1502
+ request['order_type'] = 'FOK';
1503
+ }
1504
+ else if (timeInForce === 'ioc') {
1505
+ request['order_type'] = 'IOC';
1506
+ }
1507
+ else {
1508
+ request['order_type'] = orderType;
1509
+ }
1510
+ const clientOrderId = this.safeStringN(params, ['clOrdID', 'clientOrderId', 'client_order_id']);
1511
+ params = this.omit(params, ['clOrdID', 'clientOrderId', 'client_order_id', 'postOnly', 'timeInForce']);
1512
+ if (clientOrderId !== undefined) {
1513
+ request['client_order_id'] = clientOrderId;
1514
+ }
1515
+ // request['side'] = side.toUpperCase ();
1516
+ // request['symbol'] = market['id'];
1517
+ response = await this.v1PrivatePutOrder(this.extend(request, params));
1518
+ }
1519
+ //
1520
+ // {
1521
+ // "success": true,
1522
+ // "timestamp": 1702989203989,
1523
+ // "data": {
1524
+ // "status": "EDIT_SENT"
1525
+ // }
1526
+ // }
1527
+ //
1528
+ const data = this.safeDict(response, 'data', {});
1529
+ data['timestamp'] = this.safeInteger(response, 'timestamp');
1530
+ return this.parseOrder(data, market);
1531
+ }
1532
+ async cancelOrder(id, symbol = undefined, params = {}) {
1533
+ /**
1534
+ * @method
1535
+ * @name woofipro#cancelOrder
1536
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/cancel-order
1537
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/cancel-order-by-client_order_id
1538
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/cancel-algo-order
1539
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/cancel-algo-order-by-client_order_id
1540
+ * @description cancels an open order
1541
+ * @param {string} id order id
1542
+ * @param {string} symbol unified symbol of the market the order was made in
1543
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1544
+ * @param {boolean} [params.trigger] whether the order is a stop/algo order
1545
+ * @param {string} [params.clientOrderId] a unique id for the order
1546
+ * @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
1547
+ */
1548
+ const stop = this.safeBool2(params, 'stop', 'trigger', false);
1549
+ params = this.omit(params, ['stop', 'trigger']);
1550
+ if (!stop && (symbol === undefined)) {
1551
+ throw new errors.ArgumentsRequired(this.id + ' cancelOrder() requires a symbol argument');
1552
+ }
1553
+ await this.loadMarkets();
1554
+ let market = undefined;
1555
+ if (symbol !== undefined) {
1556
+ market = this.market(symbol);
1557
+ }
1558
+ const request = {
1559
+ 'symbol': market['id'],
1560
+ };
1561
+ const clientOrderIdUnified = this.safeString2(params, 'clOrdID', 'clientOrderId');
1562
+ const clientOrderIdExchangeSpecific = this.safeString(params, 'client_order_id', clientOrderIdUnified);
1563
+ const isByClientOrder = clientOrderIdExchangeSpecific !== undefined;
1564
+ let response = undefined;
1565
+ if (stop) {
1566
+ if (isByClientOrder) {
1567
+ request['client_order_id'] = clientOrderIdExchangeSpecific;
1568
+ params = this.omit(params, ['clOrdID', 'clientOrderId', 'client_order_id']);
1569
+ response = await this.v1PrivateDeleteAlgoClientOrder(this.extend(request, params));
1570
+ }
1571
+ else {
1572
+ request['order_id'] = id;
1573
+ response = await this.v1PrivateDeleteAlgoOrder(this.extend(request, params));
1574
+ }
1575
+ }
1576
+ else {
1577
+ if (isByClientOrder) {
1578
+ request['client_order_id'] = clientOrderIdExchangeSpecific;
1579
+ params = this.omit(params, ['clOrdID', 'clientOrderId', 'client_order_id']);
1580
+ response = await this.v1PrivateDeleteClientOrder(this.extend(request, params));
1581
+ }
1582
+ else {
1583
+ request['order_id'] = id;
1584
+ response = await this.v1PrivateDeleteOrder(this.extend(request, params));
1585
+ }
1586
+ }
1587
+ //
1588
+ // {
1589
+ // "success": true,
1590
+ // "timestamp": 1702989203989,
1591
+ // "data": {
1592
+ // "status": "CANCEL_SENT"
1593
+ // }
1594
+ // }
1595
+ //
1596
+ // {
1597
+ // "success": true,
1598
+ // "timestamp": 1702989203989,
1599
+ // "status": "CANCEL_SENT"
1600
+ // }
1601
+ //
1602
+ const extendParams = { 'symbol': symbol };
1603
+ if (isByClientOrder) {
1604
+ extendParams['client_order_id'] = clientOrderIdExchangeSpecific;
1605
+ }
1606
+ else {
1607
+ extendParams['id'] = id;
1608
+ }
1609
+ if (stop) {
1610
+ return this.extend(this.parseOrder(response), extendParams);
1611
+ }
1612
+ const data = this.safeDict(response, 'data', {});
1613
+ return this.extend(this.parseOrder(data), extendParams);
1614
+ }
1615
+ async cancelOrders(ids, symbol = undefined, params = {}) {
1616
+ /**
1617
+ * @method
1618
+ * @name woofipro#cancelOrders
1619
+ * @description cancel multiple orders
1620
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/batch-cancel-orders
1621
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/batch-cancel-orders-by-client_order_id
1622
+ * @param {string[]} ids order ids
1623
+ * @param {string} [symbol] unified market symbol
1624
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1625
+ * @param {string[]} [params.client_order_ids] max length 10 e.g. ["my_id_1","my_id_2"], encode the double quotes. No space after comma
1626
+ * @returns {object} an list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
1627
+ */
1628
+ await this.loadMarkets();
1629
+ const clientOrderIds = this.safeListN(params, ['clOrdIDs', 'clientOrderIds', 'client_order_ids']);
1630
+ params = this.omit(params, ['clOrdIDs', 'clientOrderIds', 'client_order_ids']);
1631
+ const request = {};
1632
+ let response = undefined;
1633
+ if (clientOrderIds) {
1634
+ request['client_order_ids'] = clientOrderIds.join(',');
1635
+ response = await this.v1PrivateDeleteClientBatchOrder(this.extend(request, params));
1636
+ }
1637
+ else {
1638
+ request['order_ids'] = ids.join(',');
1639
+ response = await this.v1PrivateDeleteBatchOrder(this.extend(request, params));
1640
+ }
1641
+ //
1642
+ // {
1643
+ // "success": true,
1644
+ // "timestamp": 1702989203989,
1645
+ // "data": {
1646
+ // "status": "CANCEL_ALL_SENT"
1647
+ // }
1648
+ // }
1649
+ //
1650
+ return response;
1651
+ }
1652
+ async cancelAllOrders(symbol = undefined, params = {}) {
1653
+ /**
1654
+ * @method
1655
+ * @name woofipro#cancelAllOrders
1656
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/cancel-all-pending-algo-orders
1657
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/cancel-orders-in-bulk
1658
+ * @description cancel all open orders in a market
1659
+ * @param {string} symbol unified market symbol
1660
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1661
+ * @param {boolean} [params.trigger] whether the order is a stop/algo order
1662
+ * @returns {object} an list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
1663
+ */
1664
+ await this.loadMarkets();
1665
+ const stop = this.safeBool2(params, 'stop', 'trigger');
1666
+ params = this.omit(params, ['stop', 'trigger']);
1667
+ const request = {};
1668
+ if (symbol !== undefined) {
1669
+ const market = this.market(symbol);
1670
+ request['symbol'] = market['id'];
1671
+ }
1672
+ let response = undefined;
1673
+ if (stop) {
1674
+ response = await this.v1PrivateDeleteAlgoOrders(this.extend(request, params));
1675
+ }
1676
+ else {
1677
+ response = await this.v1PrivateDeleteOrders(this.extend(request, params));
1678
+ }
1679
+ // stop
1680
+ // {
1681
+ // "success": true,
1682
+ // "timestamp": 1702989203989,
1683
+ // "status": "CANCEL_ALL_SENT"
1684
+ // }
1685
+ //
1686
+ // {
1687
+ // "success": true,
1688
+ // "timestamp": 1702989203989,
1689
+ // "data": {
1690
+ // "status": "CANCEL_ALL_SENT"
1691
+ // }
1692
+ // }
1693
+ //
1694
+ return response;
1695
+ }
1696
+ async fetchOrder(id, symbol = undefined, params = {}) {
1697
+ /**
1698
+ * @method
1699
+ * @name woofipro#fetchOrder
1700
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/get-order-by-order_id
1701
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/get-order-by-client_order_id
1702
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/get-algo-order-by-order_id
1703
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/get-algo-order-by-client_order_id
1704
+ * @description fetches information on an order made by the user
1705
+ * @param {string} symbol unified symbol of the market the order was made in
1706
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1707
+ * @param {boolean} [params.trigger] whether the order is a stop/algo order
1708
+ * @param {string} [params.clientOrderId] a unique id for the order
1709
+ * @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
1710
+ */
1711
+ await this.loadMarkets();
1712
+ const market = (symbol !== undefined) ? this.market(symbol) : undefined;
1713
+ const stop = this.safeBool2(params, 'stop', 'trigger', false);
1714
+ const request = {};
1715
+ const clientOrderId = this.safeStringN(params, ['clOrdID', 'clientOrderId', 'client_order_id']);
1716
+ params = this.omit(params, ['stop', 'trigger', 'clOrdID', 'clientOrderId', 'client_order_id']);
1717
+ let response = undefined;
1718
+ if (stop) {
1719
+ if (clientOrderId) {
1720
+ request['client_order_id'] = clientOrderId;
1721
+ response = await this.v1PrivateGetAlgoClientOrderClientOrderId(this.extend(request, params));
1722
+ }
1723
+ else {
1724
+ request['oid'] = id;
1725
+ response = await this.v1PrivateGetAlgoOrderOid(this.extend(request, params));
1726
+ }
1727
+ }
1728
+ else {
1729
+ if (clientOrderId) {
1730
+ request['client_order_id'] = clientOrderId;
1731
+ response = await this.v1PrivateGetClientOrderClientOrderId(this.extend(request, params));
1732
+ }
1733
+ else {
1734
+ request['oid'] = id;
1735
+ response = await this.v1PrivateGetOrderOid(this.extend(request, params));
1736
+ }
1737
+ }
1738
+ //
1739
+ // {
1740
+ // "success": true,
1741
+ // "timestamp": 1702989203989,
1742
+ // "data": {
1743
+ // "order_id": 78151,
1744
+ // "user_id": 12345,
1745
+ // "price": 0.67772,
1746
+ // "type": "LIMIT",
1747
+ // "quantity": 20,
1748
+ // "amount": 10,
1749
+ // "executed_quantity": 20,
1750
+ // "total_executed_quantity": 20,
1751
+ // "visible_quantity": 1,
1752
+ // "symbol": "PERP_WOO_USDC",
1753
+ // "side": "BUY",
1754
+ // "status": "FILLED",
1755
+ // "total_fee": 0.5,
1756
+ // "fee_asset": "WOO",
1757
+ // "client_order_id": 1,
1758
+ // "average_executed_price": 0.67772,
1759
+ // "created_time": 1653563963000,
1760
+ // "updated_time": 1653564213000,
1761
+ // "realized_pnl": 123
1762
+ // }
1763
+ // }
1764
+ //
1765
+ const orders = this.safeDict(response, 'data', response);
1766
+ return this.parseOrder(orders, market);
1767
+ }
1768
+ async fetchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1769
+ /**
1770
+ * @method
1771
+ * @name woofipro#fetchOrders
1772
+ * @description fetches information on multiple orders made by the user
1773
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/get-orders
1774
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/get-algo-orders
1775
+ * @param {string} symbol unified market symbol of the market orders were made in
1776
+ * @param {int} [since] the earliest time in ms to fetch orders for
1777
+ * @param {int} [limit] the maximum number of order structures to retrieve
1778
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1779
+ * @param {boolean} [params.trigger] whether the order is a stop/algo order
1780
+ * @param {boolean} [params.is_triggered] whether the order has been triggered (false by default)
1781
+ * @param {string} [params.side] 'buy' or 'sell'
1782
+ * @param {boolean} [params.paginate] set to true if you want to fetch orders with pagination
1783
+ * @param {int} params.until timestamp in ms of the latest order to fetch
1784
+ * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
1785
+ */
1786
+ await this.loadMarkets();
1787
+ let paginate = false;
1788
+ const isTrigger = this.safeBool2(params, 'stop', 'trigger', false);
1789
+ const maxLimit = (isTrigger) ? 100 : 500;
1790
+ [paginate, params] = this.handleOptionAndParams(params, 'fetchOrders', 'paginate');
1791
+ if (paginate) {
1792
+ return await this.fetchPaginatedCallIncremental('fetchOrders', symbol, since, limit, params, 'page', maxLimit);
1793
+ }
1794
+ let request = {};
1795
+ let market = undefined;
1796
+ params = this.omit(params, ['stop', 'trigger']);
1797
+ if (symbol !== undefined) {
1798
+ market = this.market(symbol);
1799
+ request['symbol'] = market['id'];
1800
+ }
1801
+ if (since !== undefined) {
1802
+ request['start_t'] = since;
1803
+ }
1804
+ if (limit !== undefined) {
1805
+ request['size'] = limit;
1806
+ }
1807
+ else {
1808
+ request['size'] = maxLimit;
1809
+ }
1810
+ if (isTrigger) {
1811
+ request['algo_type'] = 'STOP';
1812
+ }
1813
+ [request, params] = this.handleUntilOption('end_t', request, params);
1814
+ let response = undefined;
1815
+ if (isTrigger) {
1816
+ response = await this.v1PrivateGetAlgoOrders(this.extend(request, params));
1817
+ }
1818
+ else {
1819
+ response = await this.v1PrivateGetOrders(this.extend(request, params));
1820
+ }
1821
+ //
1822
+ // {
1823
+ // "success": true,
1824
+ // "timestamp": 1702989203989,
1825
+ // "data": {
1826
+ // "meta": {
1827
+ // "total": 9,
1828
+ // "records_per_page": 25,
1829
+ // "current_page": 1
1830
+ // },
1831
+ // "rows": [{
1832
+ // "order_id": 78151,
1833
+ // "user_id": 12345,
1834
+ // "price": 0.67772,
1835
+ // "type": "LIMIT",
1836
+ // "quantity": 20,
1837
+ // "amount": 10,
1838
+ // "executed_quantity": 20,
1839
+ // "total_executed_quantity": 20,
1840
+ // "visible_quantity": 1,
1841
+ // "symbol": "PERP_WOO_USDC",
1842
+ // "side": "BUY",
1843
+ // "status": "FILLED",
1844
+ // "total_fee": 0.5,
1845
+ // "fee_asset": "WOO",
1846
+ // "client_order_id": 1,
1847
+ // "average_executed_price": 0.67772,
1848
+ // "created_time": 1653563963000,
1849
+ // "updated_time": 1653564213000,
1850
+ // "realized_pnl": 123
1851
+ // }]
1852
+ // }
1853
+ // }
1854
+ //
1855
+ const data = this.safeValue(response, 'data', response);
1856
+ const orders = this.safeList(data, 'rows');
1857
+ return this.parseOrders(orders, market, since, limit);
1858
+ }
1859
+ async fetchOpenOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1860
+ /**
1861
+ * @method
1862
+ * @name woofipro#fetchOpenOrders
1863
+ * @description fetches information on multiple orders made by the user
1864
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/get-orders
1865
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/get-algo-orders
1866
+ * @param {string} symbol unified market symbol of the market orders were made in
1867
+ * @param {int} [since] the earliest time in ms to fetch orders for
1868
+ * @param {int} [limit] the maximum number of order structures to retrieve
1869
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1870
+ * @param {boolean} [params.trigger] whether the order is a stop/algo order
1871
+ * @param {boolean} [params.is_triggered] whether the order has been triggered (false by default)
1872
+ * @param {string} [params.side] 'buy' or 'sell'
1873
+ * @param {int} params.until timestamp in ms of the latest order to fetch
1874
+ * @param {boolean} [params.paginate] set to true if you want to fetch orders with pagination
1875
+ * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
1876
+ */
1877
+ await this.loadMarkets();
1878
+ const extendedParams = this.extend(params, { 'status': 'INCOMPLETE' });
1879
+ return await this.fetchOrders(symbol, since, limit, extendedParams);
1880
+ }
1881
+ async fetchClosedOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1882
+ /**
1883
+ * @method
1884
+ * @name woofipro#fetchClosedOrders
1885
+ * @description fetches information on multiple orders made by the user
1886
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/get-orders
1887
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/get-algo-orders
1888
+ * @param {string} symbol unified market symbol of the market orders were made in
1889
+ * @param {int} [since] the earliest time in ms to fetch orders for
1890
+ * @param {int} [limit] the maximum number of order structures to retrieve
1891
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1892
+ * @param {boolean} [params.trigger] whether the order is a stop/algo order
1893
+ * @param {boolean} [params.is_triggered] whether the order has been triggered (false by default)
1894
+ * @param {string} [params.side] 'buy' or 'sell'
1895
+ * @param {int} params.until timestamp in ms of the latest order to fetch
1896
+ * @param {boolean} [params.paginate] set to true if you want to fetch orders with pagination
1897
+ * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
1898
+ */
1899
+ await this.loadMarkets();
1900
+ const extendedParams = this.extend(params, { 'status': 'COMPLETED' });
1901
+ return await this.fetchOrders(symbol, since, limit, extendedParams);
1902
+ }
1903
+ async fetchOrderTrades(id, symbol = undefined, since = undefined, limit = undefined, params = {}) {
1904
+ /**
1905
+ * @method
1906
+ * @name woofipro#fetchOrderTrades
1907
+ * @description fetch all the trades made from a single order
1908
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/get-all-trades-of-specific-order
1909
+ * @param {string} id order id
1910
+ * @param {string} symbol unified market symbol
1911
+ * @param {int} [since] the earliest time in ms to fetch trades for
1912
+ * @param {int} [limit] the maximum number of trades to retrieve
1913
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1914
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
1915
+ */
1916
+ await this.loadMarkets();
1917
+ let market = undefined;
1918
+ if (symbol !== undefined) {
1919
+ market = this.market(symbol);
1920
+ }
1921
+ const request = {
1922
+ 'oid': id,
1923
+ };
1924
+ const response = await this.v1PrivateGetOrderOidTrades(this.extend(request, params));
1925
+ //
1926
+ // {
1927
+ // "success": true,
1928
+ // "timestamp": 1702989203989,
1929
+ // "data": {
1930
+ // "rows": [{
1931
+ // "id": 2,
1932
+ // "symbol": "PERP_BTC_USDC",
1933
+ // "fee": 0.0001,
1934
+ // "fee_asset": "USDC",
1935
+ // "side": "BUY",
1936
+ // "order_id": 1,
1937
+ // "executed_price": 123,
1938
+ // "executed_quantity": 0.05,
1939
+ // "executed_timestamp": 1567382401000,
1940
+ // "is_maker": 1,
1941
+ // "realized_pnl": 123
1942
+ // }]
1943
+ // }
1944
+ // }
1945
+ //
1946
+ const data = this.safeDict(response, 'data', {});
1947
+ const trades = this.safeList(data, 'rows', []);
1948
+ return this.parseTrades(trades, market, since, limit, params);
1949
+ }
1950
+ async fetchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1951
+ /**
1952
+ * @method
1953
+ * @name woofipro#fetchMyTrades
1954
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/get-trades
1955
+ * @description fetch all trades made by the user
1956
+ * @param {string} symbol unified market symbol
1957
+ * @param {int} [since] the earliest time in ms to fetch trades for
1958
+ * @param {int} [limit] the maximum number of trades structures to retrieve
1959
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1960
+ * @param {boolean} [params.paginate] set to true if you want to fetch trades with pagination
1961
+ * @param {int} params.until timestamp in ms of the latest trade to fetch
1962
+ * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
1963
+ */
1964
+ await this.loadMarkets();
1965
+ let paginate = false;
1966
+ [paginate, params] = this.handleOptionAndParams(params, 'fetchMyTrades', 'paginate');
1967
+ if (paginate) {
1968
+ return await this.fetchPaginatedCallIncremental('fetchMyTrades', symbol, since, limit, params, 'page', 500);
1969
+ }
1970
+ let request = {};
1971
+ let market = undefined;
1972
+ if (symbol !== undefined) {
1973
+ market = this.market(symbol);
1974
+ request['symbol'] = market['id'];
1975
+ }
1976
+ if (since !== undefined) {
1977
+ request['start_t'] = since;
1978
+ }
1979
+ if (limit !== undefined) {
1980
+ request['size'] = limit;
1981
+ }
1982
+ else {
1983
+ request['size'] = 500;
1984
+ }
1985
+ [request, params] = this.handleUntilOption('end_t', request, params);
1986
+ const response = await this.v1PrivateGetTrades(this.extend(request, params));
1987
+ //
1988
+ // {
1989
+ // "success": true,
1990
+ // "timestamp": 1702989203989,
1991
+ // "data": {
1992
+ // "meta": {
1993
+ // "total": 9,
1994
+ // "records_per_page": 25,
1995
+ // "current_page": 1
1996
+ // },
1997
+ // "rows": [{
1998
+ // "id": 2,
1999
+ // "symbol": "PERP_BTC_USDC",
2000
+ // "fee": 0.0001,
2001
+ // "fee_asset": "USDC",
2002
+ // "side": "BUY",
2003
+ // "order_id": 1,
2004
+ // "executed_price": 123,
2005
+ // "executed_quantity": 0.05,
2006
+ // "executed_timestamp": 1567382401000,
2007
+ // "is_maker": 1,
2008
+ // "realized_pnl": 123
2009
+ // }]
2010
+ // }
2011
+ // }
2012
+ //
2013
+ const data = this.safeDict(response, 'data', {});
2014
+ const trades = this.safeList(data, 'rows', []);
2015
+ return this.parseTrades(trades, market, since, limit, params);
2016
+ }
2017
+ parseBalance(response) {
2018
+ const result = {
2019
+ 'info': response,
2020
+ };
2021
+ const balances = this.safeList(response, 'holding', []);
2022
+ for (let i = 0; i < balances.length; i++) {
2023
+ const balance = balances[i];
2024
+ const code = this.safeCurrencyCode(this.safeString(balance, 'token'));
2025
+ const account = this.account();
2026
+ account['total'] = this.safeString(balance, 'holding');
2027
+ account['frozen'] = this.safeString(balance, 'frozen');
2028
+ result[code] = account;
2029
+ }
2030
+ return this.safeBalance(result);
2031
+ }
2032
+ async fetchBalance(params = {}) {
2033
+ /**
2034
+ * @method
2035
+ * @name woofipro#fetchBalance
2036
+ * @description query for balance and get the amount of funds available for trading or funds locked in orders
2037
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/get-current-holding
2038
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2039
+ * @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
2040
+ */
2041
+ await this.loadMarkets();
2042
+ const response = await this.v1PrivateGetClientHolding(params);
2043
+ //
2044
+ // {
2045
+ // "success": true,
2046
+ // "timestamp": 1702989203989,
2047
+ // "data": {
2048
+ // "holding": [{
2049
+ // "updated_time": 1580794149000,
2050
+ // "token": "BTC",
2051
+ // "holding": -28.000752,
2052
+ // "frozen": 123,
2053
+ // "pending_short": -2000
2054
+ // }]
2055
+ // }
2056
+ // }
2057
+ //
2058
+ const data = this.safeDict(response, 'data');
2059
+ return this.parseBalance(data);
2060
+ }
2061
+ async getAssetHistoryRows(code = undefined, since = undefined, limit = undefined, params = {}) {
2062
+ await this.loadMarkets();
2063
+ const request = {};
2064
+ let currency = undefined;
2065
+ if (code !== undefined) {
2066
+ currency = this.currency(code);
2067
+ request['balance_token'] = currency['id'];
2068
+ }
2069
+ if (since !== undefined) {
2070
+ request['start_t'] = since;
2071
+ }
2072
+ if (limit !== undefined) {
2073
+ request['pageSize'] = limit;
2074
+ }
2075
+ const transactionType = this.safeString(params, 'type');
2076
+ params = this.omit(params, 'type');
2077
+ if (transactionType !== undefined) {
2078
+ request['type'] = transactionType;
2079
+ }
2080
+ const response = await this.v1PrivateGetAssetHistory(this.extend(request, params));
2081
+ //
2082
+ // {
2083
+ // "success": true,
2084
+ // "timestamp": 1702989203989,
2085
+ // "data": {
2086
+ // "meta": {
2087
+ // "total": 9,
2088
+ // "records_per_page": 25,
2089
+ // "current_page": 1
2090
+ // },
2091
+ // "rows": [{
2092
+ // "id": "230707030600002",
2093
+ // "tx_id": "0x4b0714c63cc7abae72bf68e84e25860b88ca651b7d27dad1e32bf4c027fa5326",
2094
+ // "side": "WITHDRAW",
2095
+ // "token": "USDC",
2096
+ // "amount": 555,
2097
+ // "fee": 123,
2098
+ // "trans_status": "FAILED",
2099
+ // "created_time": 1688699193034,
2100
+ // "updated_time": 1688699193096,
2101
+ // "chain_id": "986532"
2102
+ // }]
2103
+ // }
2104
+ // }
2105
+ //
2106
+ const data = this.safeDict(response, 'data', {});
2107
+ return [currency, this.safeList(data, 'rows', [])];
2108
+ }
2109
+ parseLedgerEntry(item, currency = undefined) {
2110
+ const code = this.safeString(item, 'token');
2111
+ const amount = this.safeNumber(item, 'amount');
2112
+ const side = this.safeString(item, 'token_side');
2113
+ const direction = (side === 'DEPOSIT') ? 'in' : 'out';
2114
+ const timestamp = this.safeInteger(item, 'created_time');
2115
+ const fee = this.parseTokenAndFeeTemp(item, 'fee_token', 'fee_amount');
2116
+ return {
2117
+ 'id': this.safeString(item, 'id'),
2118
+ 'currency': code,
2119
+ 'account': this.safeString(item, 'account'),
2120
+ 'referenceAccount': undefined,
2121
+ 'referenceId': this.safeString(item, 'tx_id'),
2122
+ 'status': this.parseTransactionStatus(this.safeString(item, 'status')),
2123
+ 'amount': amount,
2124
+ 'before': undefined,
2125
+ 'after': undefined,
2126
+ 'fee': fee,
2127
+ 'direction': direction,
2128
+ 'timestamp': timestamp,
2129
+ 'datetime': this.iso8601(timestamp),
2130
+ 'type': this.parseLedgerEntryType(this.safeString(item, 'type')),
2131
+ 'info': item,
2132
+ };
2133
+ }
2134
+ parseLedgerEntryType(type) {
2135
+ const types = {
2136
+ 'BALANCE': 'transaction',
2137
+ 'COLLATERAL': 'transfer', // Funds moved between portfolios
2138
+ };
2139
+ return this.safeString(types, type, type);
2140
+ }
2141
+ async fetchLedger(code = undefined, since = undefined, limit = undefined, params = {}) {
2142
+ /**
2143
+ * @method
2144
+ * @name woofipro#fetchLedger
2145
+ * @description fetch the history of changes, actions done by the user or operations that altered balance of the user
2146
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/get-asset-history
2147
+ * @param {string} code unified currency code, default is undefined
2148
+ * @param {int} [since] timestamp in ms of the earliest ledger entry, default is undefined
2149
+ * @param {int} [limit] max number of ledger entrys to return, default is undefined
2150
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2151
+ * @returns {object} a [ledger structure]{@link https://docs.ccxt.com/#/?id=ledger-structure}
2152
+ */
2153
+ const [currency, rows] = await this.getAssetHistoryRows(code, since, limit, params);
2154
+ return this.parseLedger(rows, currency, since, limit, params);
2155
+ }
2156
+ parseTransaction(transaction, currency = undefined) {
2157
+ // example in fetchLedger
2158
+ const code = this.safeString(transaction, 'token');
2159
+ let movementDirection = this.safeStringLower(transaction, 'token_side');
2160
+ if (movementDirection === 'withdraw') {
2161
+ movementDirection = 'withdrawal';
2162
+ }
2163
+ const fee = this.parseTokenAndFeeTemp(transaction, 'fee_token', 'fee_amount');
2164
+ const addressTo = this.safeString(transaction, 'target_address');
2165
+ const addressFrom = this.safeString(transaction, 'source_address');
2166
+ const timestamp = this.safeInteger(transaction, 'created_time');
2167
+ return {
2168
+ 'info': transaction,
2169
+ 'id': this.safeString2(transaction, 'id', 'withdraw_id'),
2170
+ 'txid': this.safeString(transaction, 'tx_id'),
2171
+ 'timestamp': timestamp,
2172
+ 'datetime': this.iso8601(timestamp),
2173
+ 'address': undefined,
2174
+ 'addressFrom': addressFrom,
2175
+ 'addressTo': addressTo,
2176
+ 'tag': this.safeString(transaction, 'extra'),
2177
+ 'tagFrom': undefined,
2178
+ 'tagTo': undefined,
2179
+ 'type': movementDirection,
2180
+ 'amount': this.safeNumber(transaction, 'amount'),
2181
+ 'currency': code,
2182
+ 'status': this.parseTransactionStatus(this.safeString(transaction, 'status')),
2183
+ 'updated': this.safeInteger(transaction, 'updated_time'),
2184
+ 'comment': undefined,
2185
+ 'internal': undefined,
2186
+ 'fee': fee,
2187
+ 'network': undefined,
2188
+ };
2189
+ }
2190
+ parseTransactionStatus(status) {
2191
+ const statuses = {
2192
+ 'NEW': 'pending',
2193
+ 'CONFIRMING': 'pending',
2194
+ 'PROCESSING': 'pending',
2195
+ 'COMPLETED': 'ok',
2196
+ 'CANCELED': 'canceled',
2197
+ };
2198
+ return this.safeString(statuses, status, status);
2199
+ }
2200
+ async fetchDeposits(code = undefined, since = undefined, limit = undefined, params = {}) {
2201
+ /**
2202
+ * @method
2203
+ * @name woofipro#fetchDeposits
2204
+ * @description fetch all deposits made to an account
2205
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/get-asset-history
2206
+ * @param {string} code unified currency code
2207
+ * @param {int} [since] the earliest time in ms to fetch deposits for
2208
+ * @param {int} [limit] the maximum number of deposits structures to retrieve
2209
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2210
+ * @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure}
2211
+ */
2212
+ const request = {
2213
+ 'side': 'DEPOSIT',
2214
+ };
2215
+ return await this.fetchDepositsWithdrawals(code, since, limit, this.extend(request, params));
2216
+ }
2217
+ async fetchWithdrawals(code = undefined, since = undefined, limit = undefined, params = {}) {
2218
+ /**
2219
+ * @method
2220
+ * @name woofipro#fetchWithdrawals
2221
+ * @description fetch all withdrawals made from an account
2222
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/get-asset-history
2223
+ * @param {string} code unified currency code
2224
+ * @param {int} [since] the earliest time in ms to fetch withdrawals for
2225
+ * @param {int} [limit] the maximum number of withdrawals structures to retrieve
2226
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2227
+ * @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure}
2228
+ */
2229
+ const request = {
2230
+ 'side': 'WITHDRAW',
2231
+ };
2232
+ return await this.fetchDepositsWithdrawals(code, since, limit, this.extend(request, params));
2233
+ }
2234
+ async fetchDepositsWithdrawals(code = undefined, since = undefined, limit = undefined, params = {}) {
2235
+ /**
2236
+ * @method
2237
+ * @name woofipro#fetchDepositsWithdrawals
2238
+ * @description fetch history of deposits and withdrawals
2239
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/get-asset-history
2240
+ * @param {string} [code] unified currency code for the currency of the deposit/withdrawals, default is undefined
2241
+ * @param {int} [since] timestamp in ms of the earliest deposit/withdrawal, default is undefined
2242
+ * @param {int} [limit] max number of deposit/withdrawals to return, default is undefined
2243
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2244
+ * @returns {object} a list of [transaction structure]{@link https://docs.ccxt.com/#/?id=transaction-structure}
2245
+ */
2246
+ const request = {};
2247
+ const [currency, rows] = await this.getAssetHistoryRows(code, since, limit, this.extend(request, params));
2248
+ //
2249
+ // {
2250
+ // "rows":[],
2251
+ // "meta":{
2252
+ // "total":0,
2253
+ // "records_per_page":25,
2254
+ // "current_page":1
2255
+ // },
2256
+ // "success":true
2257
+ // }
2258
+ //
2259
+ return this.parseTransactions(rows, currency, since, limit, params);
2260
+ }
2261
+ async getWithdrawNonce(params = {}) {
2262
+ const response = await this.v1PrivateGetWithdrawNonce(params);
2263
+ //
2264
+ // {
2265
+ // "success": true,
2266
+ // "timestamp": 1702989203989,
2267
+ // "data": {
2268
+ // "withdraw_nonce": 1
2269
+ // }
2270
+ // }
2271
+ //
2272
+ const data = this.safeDict(response, 'data', {});
2273
+ return this.safeNumber(data, 'withdraw_nonce');
2274
+ }
2275
+ hashMessage(message) {
2276
+ return '0x' + this.hash(message, sha3.keccak_256, 'hex');
2277
+ }
2278
+ signHash(hash, privateKey) {
2279
+ const signature = crypto.ecdsa(hash.slice(-64), privateKey.slice(-64), secp256k1.secp256k1, undefined);
2280
+ const v = this.intToBase16(this.sum(27, signature['v']));
2281
+ return '0x' + signature['r'].padStart(64, '0') + signature['s'].padStart(64, '0') + v;
2282
+ }
2283
+ signMessage(message, privateKey) {
2284
+ return this.signHash(this.hashMessage(message), privateKey.slice(-64));
2285
+ }
2286
+ async withdraw(code, amount, address, tag = undefined, params = {}) {
2287
+ /**
2288
+ * @method
2289
+ * @name woofipro#withdraw
2290
+ * @description make a withdrawal
2291
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/create-withdraw-request
2292
+ * @param {string} code unified currency code
2293
+ * @param {float} amount the amount to withdraw
2294
+ * @param {string} address the address to withdraw to
2295
+ * @param {string} tag
2296
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2297
+ * @returns {object} a [transaction structure]{@link https://docs.ccxt.com/#/?id=transaction-structure}
2298
+ */
2299
+ await this.loadMarkets();
2300
+ this.checkAddress(address);
2301
+ if (code !== undefined) {
2302
+ code = code.toUpperCase();
2303
+ if (code !== 'USDC') {
2304
+ throw new errors.NotSupported(this.id + 'withdraw() only support USDC');
2305
+ }
2306
+ }
2307
+ const currency = this.currency(code);
2308
+ const verifyingContractAddress = this.safeString(this.options, 'verifyingContractAddress');
2309
+ const chainId = this.safeString(params, 'chainId');
2310
+ const currencyNetworks = this.safeDict(currency, 'networks', {});
2311
+ const coinNetwork = this.safeDict(currencyNetworks, chainId, {});
2312
+ const coinNetworkId = this.safeNumber(coinNetwork, 'id');
2313
+ if (coinNetworkId === undefined) {
2314
+ throw new errors.BadRequest(this.id + ' withdraw() require chainId parameter');
2315
+ }
2316
+ const withdrawNonce = await this.getWithdrawNonce(params);
2317
+ const nonce = this.nonce();
2318
+ const domain = {
2319
+ 'chainId': chainId,
2320
+ 'name': 'Orderly',
2321
+ 'verifyingContract': verifyingContractAddress,
2322
+ 'version': '1',
2323
+ };
2324
+ const messageTypes = {
2325
+ 'Withdraw': [
2326
+ { 'name': 'brokerId', 'type': 'string' },
2327
+ { 'name': 'chainId', 'type': 'uint256' },
2328
+ { 'name': 'receiver', 'type': 'address' },
2329
+ { 'name': 'token', 'type': 'string' },
2330
+ { 'name': 'amount', 'type': 'uint256' },
2331
+ { 'name': 'withdrawNonce', 'type': 'uint64' },
2332
+ { 'name': 'timestamp', 'type': 'uint64' },
2333
+ ],
2334
+ };
2335
+ const withdrawRequest = {
2336
+ 'brokerId': this.safeString(this.options, 'keyBrokerId', 'woofi_pro'),
2337
+ 'chainId': this.parseToInt(chainId),
2338
+ 'receiver': address,
2339
+ 'token': code,
2340
+ 'amount': amount.toString(),
2341
+ 'withdrawNonce': withdrawNonce,
2342
+ 'timestamp': nonce,
2343
+ };
2344
+ const msg = this.ethEncodeStructuredData(domain, messageTypes, withdrawRequest);
2345
+ const signature = this.signMessage(msg, this.privateKey);
2346
+ const request = {
2347
+ 'signature': signature,
2348
+ 'userAddress': address,
2349
+ 'verifyingContract': verifyingContractAddress,
2350
+ 'message': withdrawRequest,
2351
+ };
2352
+ params = this.omit(params, 'chainId');
2353
+ const response = await this.v1PrivatePostWithdrawRequest(this.extend(request, params));
2354
+ //
2355
+ // {
2356
+ // "success": true,
2357
+ // "timestamp": 1702989203989,
2358
+ // "data": {
2359
+ // "withdraw_id": 123
2360
+ // }
2361
+ // }
2362
+ //
2363
+ const data = this.safeDict(response, 'data', {});
2364
+ return this.parseTransaction(data, currency);
2365
+ }
2366
+ parseLeverage(leverage, market = undefined) {
2367
+ const leverageValue = this.safeInteger(leverage, 'max_leverage');
2368
+ return {
2369
+ 'info': leverage,
2370
+ 'symbol': market['symbol'],
2371
+ 'marginMode': undefined,
2372
+ 'longLeverage': leverageValue,
2373
+ 'shortLeverage': leverageValue,
2374
+ };
2375
+ }
2376
+ async fetchLeverage(symbol, params = {}) {
2377
+ /**
2378
+ * @method
2379
+ * @name woofipro#fetchLeverage
2380
+ * @description fetch the set leverage for a market
2381
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/get-account-information
2382
+ * @param {string} symbol unified market symbol
2383
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2384
+ * @returns {object} a [leverage structure]{@link https://docs.ccxt.com/#/?id=leverage-structure}
2385
+ */
2386
+ await this.loadMarkets();
2387
+ const market = this.market(symbol);
2388
+ const response = await this.v1PrivateGetClientInfo(params);
2389
+ //
2390
+ // {
2391
+ // "success": true,
2392
+ // "timestamp": 1702989203989,
2393
+ // "data": {
2394
+ // "account_id": "<string>",
2395
+ // "email": "test@test.com",
2396
+ // "account_mode": "FUTURES",
2397
+ // "max_leverage": 20,
2398
+ // "taker_fee_rate": 123,
2399
+ // "maker_fee_rate": 123,
2400
+ // "futures_taker_fee_rate": 123,
2401
+ // "futures_maker_fee_rate": 123,
2402
+ // "maintenance_cancel_orders": true,
2403
+ // "imr_factor": {
2404
+ // "PERP_BTC_USDC": 123,
2405
+ // "PERP_ETH_USDC": 123,
2406
+ // "PERP_NEAR_USDC": 123
2407
+ // },
2408
+ // "max_notional": {
2409
+ // "PERP_BTC_USDC": 123,
2410
+ // "PERP_ETH_USDC": 123,
2411
+ // "PERP_NEAR_USDC": 123
2412
+ // }
2413
+ // }
2414
+ // }
2415
+ //
2416
+ const data = this.safeDict(response, 'data', {});
2417
+ return this.parseLeverage(data, market);
2418
+ }
2419
+ async setLeverage(leverage, symbol = undefined, params = {}) {
2420
+ /**
2421
+ * @method
2422
+ * @name woofipro#setLeverage
2423
+ * @description set the level of leverage for a market
2424
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/update-leverage-setting
2425
+ * @param {string} symbol unified market symbol
2426
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2427
+ * @returns {object} response from the exchange
2428
+ */
2429
+ await this.loadMarkets();
2430
+ if ((leverage < 1) || (leverage > 50)) {
2431
+ throw new errors.BadRequest(this.id + ' leverage should be between 1 and 50');
2432
+ }
2433
+ const request = {
2434
+ 'leverage': leverage,
2435
+ };
2436
+ return await this.v1PrivatePostClientLeverage(this.extend(request, params));
2437
+ }
2438
+ parsePosition(position, market = undefined) {
2439
+ //
2440
+ // {
2441
+ // "IMR_withdraw_orders": 0.1,
2442
+ // "MMR_with_orders": 0.05,
2443
+ // "average_open_price": 27908.14386047,
2444
+ // "cost_position": -139329.358492,
2445
+ // "est_liq_price": 117335.92899428,
2446
+ // "fee_24_h": 123,
2447
+ // "imr": 0.1,
2448
+ // "last_sum_unitary_funding": 70.38,
2449
+ // "mark_price": 27794.9,
2450
+ // "mmr": 0.05,
2451
+ // "pending_long_qty": 123,
2452
+ // "pending_short_qty": 123,
2453
+ // "pnl_24_h": 123,
2454
+ // "position_qty": -5,
2455
+ // "settle_price": 27865.8716984,
2456
+ // "symbol": "PERP_BTC_USDC",
2457
+ // "timestamp": 1685429350571,
2458
+ // "unsettled_pnl": 354.858492
2459
+ // }
2460
+ //
2461
+ const contract = this.safeString(position, 'symbol');
2462
+ market = this.safeMarket(contract, market);
2463
+ let size = this.safeString(position, 'position_qty');
2464
+ let side = undefined;
2465
+ if (Precise["default"].stringGt(size, '0')) {
2466
+ side = 'long';
2467
+ }
2468
+ else {
2469
+ side = 'short';
2470
+ }
2471
+ const contractSize = this.safeString(market, 'contractSize');
2472
+ const markPrice = this.safeString(position, 'mark_price');
2473
+ const timestamp = this.safeInteger(position, 'timestamp');
2474
+ const entryPrice = this.safeString(position, 'average_open_price');
2475
+ const unrealisedPnl = this.safeString(position, 'unsettled_pnl');
2476
+ size = Precise["default"].stringAbs(size);
2477
+ const notional = Precise["default"].stringMul(size, markPrice);
2478
+ return this.safePosition({
2479
+ 'info': position,
2480
+ 'id': undefined,
2481
+ 'symbol': this.safeString(market, 'symbol'),
2482
+ 'timestamp': timestamp,
2483
+ 'datetime': this.iso8601(timestamp),
2484
+ 'lastUpdateTimestamp': undefined,
2485
+ 'initialMargin': undefined,
2486
+ 'initialMarginPercentage': undefined,
2487
+ 'maintenanceMargin': undefined,
2488
+ 'maintenanceMarginPercentage': undefined,
2489
+ 'entryPrice': this.parseNumber(entryPrice),
2490
+ 'notional': this.parseNumber(notional),
2491
+ 'leverage': undefined,
2492
+ 'unrealizedPnl': this.parseNumber(unrealisedPnl),
2493
+ 'contracts': this.parseNumber(size),
2494
+ 'contractSize': this.parseNumber(contractSize),
2495
+ 'marginRatio': undefined,
2496
+ 'liquidationPrice': this.safeNumber(position, 'est_liq_price'),
2497
+ 'markPrice': this.parseNumber(markPrice),
2498
+ 'lastPrice': undefined,
2499
+ 'collateral': undefined,
2500
+ 'marginMode': 'cross',
2501
+ 'marginType': undefined,
2502
+ 'side': side,
2503
+ 'percentage': undefined,
2504
+ 'hedged': undefined,
2505
+ 'stopLossPrice': undefined,
2506
+ 'takeProfitPrice': undefined,
2507
+ });
2508
+ }
2509
+ async fetchPosition(symbol = undefined, params = {}) {
2510
+ /**
2511
+ * @method
2512
+ * @name woofipro#fetchPosition
2513
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/get-one-position-info
2514
+ * @description fetch data on an open position
2515
+ * @param {string} symbol unified market symbol of the market the position is held in
2516
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2517
+ * @returns {object} a [position structure]{@link https://docs.ccxt.com/#/?id=position-structure}
2518
+ */
2519
+ await this.loadMarkets();
2520
+ const market = this.market(symbol);
2521
+ const request = {
2522
+ 'symbol': market['id'],
2523
+ };
2524
+ const response = await this.v1PrivateGetPositionSymbol(this.extend(request, params));
2525
+ //
2526
+ // {
2527
+ // "success": true,
2528
+ // "timestamp": 1702989203989,
2529
+ // "data": {
2530
+ // "IMR_withdraw_orders": 0.1,
2531
+ // "MMR_with_orders": 0.05,
2532
+ // "average_open_price": 27908.14386047,
2533
+ // "cost_position": -139329.358492,
2534
+ // "est_liq_price": 117335.92899428,
2535
+ // "fee_24_h": 123,
2536
+ // "imr": 0.1,
2537
+ // "last_sum_unitary_funding": 70.38,
2538
+ // "mark_price": 27794.9,
2539
+ // "mmr": 0.05,
2540
+ // "pending_long_qty": 123,
2541
+ // "pending_short_qty": 123,
2542
+ // "pnl_24_h": 123,
2543
+ // "position_qty": -5,
2544
+ // "settle_price": 27865.8716984,
2545
+ // "symbol": "PERP_BTC_USDC",
2546
+ // "timestamp": 1685429350571,
2547
+ // "unsettled_pnl": 354.858492
2548
+ // }
2549
+ // }
2550
+ //
2551
+ const data = this.safeDict(response, 'data');
2552
+ return this.parsePosition(data, market);
2553
+ }
2554
+ async fetchPositions(symbols = undefined, params = {}) {
2555
+ /**
2556
+ * @method
2557
+ * @name woofipro#fetchPositions
2558
+ * @description fetch all open positions
2559
+ * @see https://orderly.network/docs/build-on-evm/evm-api/restful-api/private/get-all-positions-info
2560
+ * @param {string[]} [symbols] list of unified market symbols
2561
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2562
+ * @param {string} [method] method name to call, "positionRisk", "account" or "option", default is "positionRisk"
2563
+ * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/#/?id=position-structure}
2564
+ */
2565
+ await this.loadMarkets();
2566
+ const response = await this.v1PrivateGetPositions(params);
2567
+ //
2568
+ // {
2569
+ // "success": true,
2570
+ // "timestamp": 1702989203989,
2571
+ // "data": {
2572
+ // "current_margin_ratio_with_orders": 1.2385,
2573
+ // "free_collateral": 450315.09115,
2574
+ // "initial_margin_ratio": 0.1,
2575
+ // "initial_margin_ratio_with_orders": 0.1,
2576
+ // "maintenance_margin_ratio": 0.05,
2577
+ // "maintenance_margin_ratio_with_orders": 0.05,
2578
+ // "margin_ratio": 1.2385,
2579
+ // "open_margin_ratio": 1.2102,
2580
+ // "total_collateral_value": 489865.71329,
2581
+ // "total_pnl_24_h": 123,
2582
+ // "rows": [{
2583
+ // "IMR_withdraw_orders": 0.1,
2584
+ // "MMR_with_orders": 0.05,
2585
+ // "average_open_price": 27908.14386047,
2586
+ // "cost_position": -139329.358492,
2587
+ // "est_liq_price": 117335.92899428,
2588
+ // "fee_24_h": 123,
2589
+ // "imr": 0.1,
2590
+ // "last_sum_unitary_funding": 70.38,
2591
+ // "mark_price": 27794.9,
2592
+ // "mmr": 0.05,
2593
+ // "pending_long_qty": 123,
2594
+ // "pending_short_qty": 123,
2595
+ // "pnl_24_h": 123,
2596
+ // "position_qty": -5,
2597
+ // "settle_price": 27865.8716984,
2598
+ // "symbol": "PERP_BTC_USDC",
2599
+ // "timestamp": 1685429350571,
2600
+ // "unsettled_pnl": 354.858492
2601
+ // }]
2602
+ // }
2603
+ // }
2604
+ //
2605
+ const result = this.safeDict(response, 'data', {});
2606
+ const positions = this.safeList(result, 'rows', []);
2607
+ return this.parsePositions(positions, symbols);
2608
+ }
2609
+ nonce() {
2610
+ return this.milliseconds();
2611
+ }
2612
+ sign(path, section = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
2613
+ const version = section[0];
2614
+ const access = section[1];
2615
+ const pathWithParams = this.implodeParams(path, params);
2616
+ let url = this.implodeHostname(this.urls['api'][access]);
2617
+ url += '/' + version + '/';
2618
+ params = this.omit(params, this.extractParams(path));
2619
+ params = this.keysort(params);
2620
+ if (access === 'public') {
2621
+ url += pathWithParams;
2622
+ if (Object.keys(params).length) {
2623
+ url += '?' + this.urlencode(params);
2624
+ }
2625
+ }
2626
+ else {
2627
+ this.checkRequiredCredentials();
2628
+ if ((method === 'POST' || method === 'PUT') && (path === 'algo/order' || path === 'order' || path === 'batch-order')) {
2629
+ const isSandboxMode = this.safeBool(this.options, 'sandboxMode', false);
2630
+ if (!isSandboxMode) {
2631
+ const brokerId = this.safeString(this.options, 'brokerId', 'CCXT');
2632
+ if (path === 'batch-order') {
2633
+ const ordersList = this.safeList(params, 'orders', []);
2634
+ for (let i = 0; i < ordersList.length; i++) {
2635
+ params['orders'][i]['order_tag'] = brokerId;
2636
+ }
2637
+ }
2638
+ else {
2639
+ params['order_tag'] = brokerId;
2640
+ }
2641
+ }
2642
+ params = this.keysort(params);
2643
+ }
2644
+ let auth = '';
2645
+ const ts = this.nonce().toString();
2646
+ url += pathWithParams;
2647
+ headers = {
2648
+ 'orderly-account-id': this.accountId,
2649
+ 'orderly-key': this.apiKey,
2650
+ 'orderly-timestamp': ts,
2651
+ };
2652
+ auth = ts + method + '/' + version + '/' + pathWithParams;
2653
+ if (method === 'POST' || method === 'PUT') {
2654
+ body = this.json(params);
2655
+ auth += body;
2656
+ headers['content-type'] = 'application/json';
2657
+ }
2658
+ else {
2659
+ if (Object.keys(params).length) {
2660
+ url += '?' + this.urlencode(params);
2661
+ auth += '?' + this.rawencode(params);
2662
+ }
2663
+ headers['content-type'] = 'application/x-www-form-urlencoded';
2664
+ if (method === 'DELETE') {
2665
+ body = '';
2666
+ }
2667
+ }
2668
+ let secret = this.secret;
2669
+ if (secret.indexOf('ed25519:') >= 0) {
2670
+ const parts = secret.split('ed25519:');
2671
+ secret = parts[1];
2672
+ }
2673
+ const signature = crypto.eddsa(this.encode(auth), this.base58ToBinary(secret), ed25519.ed25519);
2674
+ headers['orderly-signature'] = this.urlencodeBase64(this.base64ToBinary(signature));
2675
+ }
2676
+ return { 'url': url, 'method': method, 'body': body, 'headers': headers };
2677
+ }
2678
+ handleErrors(httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) {
2679
+ if (!response) {
2680
+ return undefined; // fallback to default error handler
2681
+ }
2682
+ //
2683
+ // 400 Bad Request {"success":false,"code":-1012,"message":"Amount is required for buy market orders when margin disabled."}
2684
+ // {"code":"-1011","message":"The system is under maintenance.","success":false}
2685
+ //
2686
+ const success = this.safeBool(response, 'success');
2687
+ const errorCode = this.safeString(response, 'code');
2688
+ if (!success) {
2689
+ const feedback = this.id + ' ' + this.json(response);
2690
+ this.throwBroadlyMatchedException(this.exceptions['broad'], body, feedback);
2691
+ this.throwExactlyMatchedException(this.exceptions['exact'], errorCode, feedback);
2692
+ throw new errors.ExchangeError(feedback);
2693
+ }
2694
+ return undefined;
2695
+ }
2696
+ }
2697
+
2698
+ module.exports = woofipro;