ccxt 4.3.18 → 4.3.19

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