ccxt 4.5.29 → 4.5.31

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 (85) hide show
  1. package/README.md +4 -4
  2. package/dist/ccxt.browser.min.js +18 -18
  3. package/dist/cjs/ccxt.js +6 -4
  4. package/dist/cjs/src/base/Exchange.js +16 -1
  5. package/dist/cjs/src/base/ws/WsClient.js +1 -0
  6. package/dist/cjs/src/bingx.js +1 -1
  7. package/dist/cjs/src/bullish.js +1 -1
  8. package/dist/cjs/src/bybit.js +2 -0
  9. package/dist/cjs/src/bydfi.js +2907 -0
  10. package/dist/cjs/src/coinbase.js +34 -1
  11. package/dist/cjs/src/dydx.js +3 -3
  12. package/dist/cjs/src/gate.js +55 -8
  13. package/dist/cjs/src/hyperliquid.js +19 -4
  14. package/dist/cjs/src/kucoin.js +175 -68
  15. package/dist/cjs/src/pro/apex.js +7 -5
  16. package/dist/cjs/src/pro/ascendex.js +1 -1
  17. package/dist/cjs/src/pro/binance.js +10 -6
  18. package/dist/cjs/src/pro/bingx.js +6 -4
  19. package/dist/cjs/src/pro/bitmart.js +5 -3
  20. package/dist/cjs/src/pro/bybit.js +6 -4
  21. package/dist/cjs/src/pro/bydfi.js +1077 -0
  22. package/dist/cjs/src/pro/cryptocom.js +6 -4
  23. package/dist/cjs/src/pro/gate.js +5 -3
  24. package/dist/cjs/src/pro/hashkey.js +5 -3
  25. package/dist/cjs/src/pro/htx.js +1 -1
  26. package/dist/cjs/src/pro/hyperliquid.js +1 -1
  27. package/dist/cjs/src/pro/kucoinfutures.js +5 -3
  28. package/dist/cjs/src/pro/modetrade.js +5 -3
  29. package/dist/cjs/src/pro/p2b.js +1 -1
  30. package/dist/cjs/src/pro/toobit.js +12 -8
  31. package/dist/cjs/src/pro/woo.js +5 -3
  32. package/dist/cjs/src/pro/woofipro.js +5 -3
  33. package/dist/cjs/src/pro/xt.js +5 -3
  34. package/dist/cjs/src/toobit.js +2 -1
  35. package/js/ccxt.d.ts +8 -5
  36. package/js/ccxt.js +6 -4
  37. package/js/src/abstract/bydfi.d.ts +52 -0
  38. package/js/src/abstract/kucoin.d.ts +2 -0
  39. package/js/src/abstract/kucoinfutures.d.ts +2 -0
  40. package/js/src/base/Exchange.d.ts +3 -0
  41. package/js/src/base/Exchange.js +16 -1
  42. package/js/src/base/ws/WsClient.js +1 -0
  43. package/js/src/binance.d.ts +1 -1
  44. package/js/src/bingx.js +1 -1
  45. package/js/src/bullish.js +1 -1
  46. package/js/src/bybit.js +2 -0
  47. package/js/src/bydfi.d.ts +472 -0
  48. package/js/src/bydfi.js +2905 -0
  49. package/js/src/coinbase.d.ts +11 -0
  50. package/js/src/coinbase.js +34 -1
  51. package/js/src/dydx.js +3 -3
  52. package/js/src/exmo.d.ts +1 -1
  53. package/js/src/gate.js +55 -8
  54. package/js/src/hyperliquid.d.ts +1 -0
  55. package/js/src/hyperliquid.js +19 -4
  56. package/js/src/kucoin.d.ts +19 -3
  57. package/js/src/kucoin.js +175 -68
  58. package/js/src/pro/apex.js +7 -5
  59. package/js/src/pro/ascendex.js +1 -1
  60. package/js/src/pro/binance.js +10 -6
  61. package/js/src/pro/bingx.js +6 -4
  62. package/js/src/pro/bitmart.js +5 -3
  63. package/js/src/pro/bybit.js +6 -4
  64. package/js/src/pro/bydfi.d.ts +206 -0
  65. package/js/src/pro/bydfi.js +1076 -0
  66. package/js/src/pro/cryptocom.js +6 -4
  67. package/js/src/pro/gate.js +5 -3
  68. package/js/src/pro/hashkey.js +5 -3
  69. package/js/src/pro/htx.js +1 -1
  70. package/js/src/pro/hyperliquid.js +1 -1
  71. package/js/src/pro/kucoinfutures.js +5 -3
  72. package/js/src/pro/modetrade.js +5 -3
  73. package/js/src/pro/p2b.js +1 -1
  74. package/js/src/pro/toobit.js +12 -8
  75. package/js/src/pro/woo.js +5 -3
  76. package/js/src/pro/woofipro.js +5 -3
  77. package/js/src/pro/xt.js +5 -3
  78. package/js/src/toobit.js +2 -1
  79. package/package.json +1 -1
  80. package/dist/cjs/src/oceanex.js +0 -1125
  81. package/js/src/abstract/oceanex.d.ts +0 -30
  82. package/js/src/oceanex.d.ts +0 -231
  83. package/js/src/oceanex.js +0 -1124
  84. /package/dist/cjs/src/abstract/{oceanex.js → bydfi.js} +0 -0
  85. /package/js/src/abstract/{oceanex.js → bydfi.js} +0 -0
@@ -0,0 +1,2905 @@
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/bydfi.js';
9
+ import { ArgumentsRequired, AuthenticationError, BadRequest, ExchangeError, InsufficientFunds, NotSupported, PermissionDenied, RateLimitExceeded } from '../ccxt.js';
10
+ import { Precise } from './base/Precise.js';
11
+ import { sha256 } from './static_dependencies/noble-hashes/sha256.js';
12
+ import { TICK_SIZE } from './base/functions/number.js';
13
+ // ---------------------------------------------------------------------------
14
+ /**
15
+ * @class bydfi
16
+ * @augments Exchange
17
+ */
18
+ export default class bydfi extends Exchange {
19
+ describe() {
20
+ return this.deepExtend(super.describe(), {
21
+ 'id': 'bydfi',
22
+ 'name': 'BYDFi',
23
+ 'countries': ['SG'],
24
+ 'rateLimit': 50,
25
+ 'version': 'v1',
26
+ 'certified': false,
27
+ 'pro': true,
28
+ 'has': {
29
+ 'CORS': undefined,
30
+ 'spot': false,
31
+ 'margin': false,
32
+ 'swap': true,
33
+ 'future': false,
34
+ 'option': false,
35
+ 'addMargin': false,
36
+ 'borrowCrossMargin': false,
37
+ 'borrowIsolatedMargin': false,
38
+ 'borrowMargin': false,
39
+ 'cancelAllOrders': true,
40
+ 'cancelOrder': false,
41
+ 'cancelOrders': false,
42
+ 'cancelOrdersWithClientOrderId': false,
43
+ 'cancelOrderWithClientOrderId': false,
44
+ 'closeAllPositions': false,
45
+ 'closePosition': false,
46
+ 'createDepositAddress': false,
47
+ 'createLimitBuyOrder': false,
48
+ 'createLimitOrder': true,
49
+ 'createLimitSellOrder': false,
50
+ 'createMarketBuyOrder': false,
51
+ 'createMarketBuyOrderWithCost': false,
52
+ 'createMarketOrder': true,
53
+ 'createMarketOrderWithCost': false,
54
+ 'createMarketSellOrder': false,
55
+ 'createMarketSellOrderWithCost': false,
56
+ 'createOrder': true,
57
+ 'createOrders': true,
58
+ 'createOrderWithTakeProfitAndStopLoss': false,
59
+ 'createPostOnlyOrder': true,
60
+ 'createReduceOnlyOrder': true,
61
+ 'createStopLimitOrder': true,
62
+ 'createStopLossOrder': true,
63
+ 'createStopMarketOrder': false,
64
+ 'createStopOrder': false,
65
+ 'createTakeProfitOrder': true,
66
+ 'createTrailingAmountOrder': false,
67
+ 'createTrailingPercentOrder': true,
68
+ 'createTriggerOrder': false,
69
+ 'deposit': false,
70
+ 'editOrder': true,
71
+ 'editOrders': true,
72
+ 'editOrderWithClientOrderId': true,
73
+ 'fetchAccounts': false,
74
+ 'fetchBalance': true,
75
+ 'fetchBidsAsks': false,
76
+ 'fetchBorrowInterest': false,
77
+ 'fetchBorrowRate': false,
78
+ 'fetchBorrowRateHistories': false,
79
+ 'fetchBorrowRateHistory': false,
80
+ 'fetchBorrowRates': false,
81
+ 'fetchBorrowRatesPerSymbol': false,
82
+ 'fetchCanceledAndClosedOrders': true,
83
+ 'fetchCanceledOrders': false,
84
+ 'fetchClosedOrder': false,
85
+ 'fetchClosedOrders': false,
86
+ 'fetchConvertCurrencies': false,
87
+ 'fetchConvertQuote': false,
88
+ 'fetchConvertTrade': false,
89
+ 'fetchConvertTradeHistory': false,
90
+ 'fetchCrossBorrowRate': false,
91
+ 'fetchCrossBorrowRates': false,
92
+ 'fetchCurrencies': false,
93
+ 'fetchDeposit': false,
94
+ 'fetchDepositAddress': false,
95
+ 'fetchDepositAddresses': false,
96
+ 'fetchDepositAddressesByNetwork': false,
97
+ 'fetchDeposits': true,
98
+ 'fetchDepositsWithdrawals': false,
99
+ 'fetchDepositWithdrawFee': false,
100
+ 'fetchDepositWithdrawFees': false,
101
+ 'fetchFundingHistory': false,
102
+ 'fetchFundingInterval': false,
103
+ 'fetchFundingIntervals': false,
104
+ 'fetchFundingRate': true,
105
+ 'fetchFundingRateHistory': true,
106
+ 'fetchFundingRates': false,
107
+ 'fetchGreeks': false,
108
+ 'fetchIndexOHLCV': false,
109
+ 'fetchIsolatedBorrowRate': false,
110
+ 'fetchIsolatedBorrowRates': false,
111
+ 'fetchIsolatedPositions': false,
112
+ 'fetchL2OrderBook': true,
113
+ 'fetchL3OrderBook': false,
114
+ 'fetchLastPrices': false,
115
+ 'fetchLedger': false,
116
+ 'fetchLedgerEntry': false,
117
+ 'fetchLeverage': true,
118
+ 'fetchLeverages': false,
119
+ 'fetchLeverageTiers': false,
120
+ 'fetchLiquidations': false,
121
+ 'fetchLongShortRatio': false,
122
+ 'fetchLongShortRatioHistory': false,
123
+ 'fetchMarginAdjustmentHistory': false,
124
+ 'fetchMarginMode': true,
125
+ 'fetchMarginModes': false,
126
+ 'fetchMarketLeverageTiers': false,
127
+ 'fetchMarkets': true,
128
+ 'fetchMarkOHLCV': false,
129
+ 'fetchMarkPrices': false,
130
+ 'fetchMyLiquidations': false,
131
+ 'fetchMySettlementHistory': false,
132
+ 'fetchMyTrades': true,
133
+ 'fetchOHLCV': true,
134
+ 'fetchOpenInterest': false,
135
+ 'fetchOpenInterestHistory': false,
136
+ 'fetchOpenInterests': false,
137
+ 'fetchOpenOrder': false,
138
+ 'fetchOpenOrders': true,
139
+ 'fetchOption': false,
140
+ 'fetchOptionChain': false,
141
+ 'fetchOrder': false,
142
+ 'fetchOrderBook': true,
143
+ 'fetchOrderBooks': false,
144
+ 'fetchOrders': false,
145
+ 'fetchOrdersByStatus': false,
146
+ 'fetchOrderTrades': false,
147
+ 'fetchOrderWithClientOrderId': false,
148
+ 'fetchPosition': false,
149
+ 'fetchPositionHistory': true,
150
+ 'fetchPositionMode': true,
151
+ 'fetchPositions': true,
152
+ 'fetchPositionsForSymbol': true,
153
+ 'fetchPositionsHistory': true,
154
+ 'fetchPositionsRisk': false,
155
+ 'fetchPremiumIndexOHLCV': false,
156
+ 'fetchSettlementHistory': false,
157
+ 'fetchStatus': false,
158
+ 'fetchTicker': true,
159
+ 'fetchTickers': true,
160
+ 'fetchTime': false,
161
+ 'fetchTrades': true,
162
+ 'fetchTradingFee': false,
163
+ 'fetchTradingFees': false,
164
+ 'fetchTradingLimits': false,
165
+ 'fetchTransactionFee': false,
166
+ 'fetchTransactionFees': false,
167
+ 'fetchTransactions': false,
168
+ 'fetchTransfer': false,
169
+ 'fetchTransfers': true,
170
+ 'fetchUnderlyingAssets': false,
171
+ 'fetchVolatilityHistory': false,
172
+ 'fetchWithdrawAddresses': false,
173
+ 'fetchWithdrawal': false,
174
+ 'fetchWithdrawals': true,
175
+ 'fetchWithdrawalWhitelist': false,
176
+ 'reduceMargin': false,
177
+ 'repayCrossMargin': false,
178
+ 'repayIsolatedMargin': false,
179
+ 'setLeverage': true,
180
+ 'setMargin': false,
181
+ 'setMarginMode': true,
182
+ 'setPositionMode': true,
183
+ 'signIn': false,
184
+ 'transfer': true,
185
+ 'watchMyLiquidationsForSymbols': false,
186
+ 'withdraw': false,
187
+ 'ws': true,
188
+ },
189
+ 'urls': {
190
+ 'logo': 'https://github.com/user-attachments/assets/bfffb73d-29bd-465d-b75b-98e210491769',
191
+ 'api': {
192
+ 'public': 'https://api.bydfi.com/api',
193
+ 'private': 'https://api.bydfi.com/api',
194
+ },
195
+ 'www': 'https://bydfi.com/',
196
+ 'doc': 'https://developers.bydfi.com/en/',
197
+ 'referral': 'https://partner.bydfi.com/j/DilWutCI',
198
+ },
199
+ 'fees': {},
200
+ 'api': {
201
+ 'public': {
202
+ 'get': {
203
+ 'v1/public/api_limits': 1,
204
+ 'v1/swap/market/exchange_info': 1,
205
+ 'v1/swap/market/depth': 1,
206
+ 'v1/swap/market/trades': 1,
207
+ 'v1/swap/market/klines': 1,
208
+ 'v1/swap/market/ticker/24hr': 1,
209
+ 'v1/swap/market/ticker/price': 1,
210
+ 'v1/swap/market/mark_price': 1,
211
+ 'v1/swap/market/funding_rate': 1,
212
+ 'v1/swap/market/funding_rate_history': 1,
213
+ 'v1/swap/market/risk_limit': 1, // https://developers.bydfi.com/en/swap/market#risk-limit
214
+ },
215
+ },
216
+ 'private': {
217
+ 'get': {
218
+ 'v1/account/assets': 1,
219
+ 'v1/account/transfer_records': 1,
220
+ 'v1/spot/deposit_records': 1,
221
+ 'v1/spot/withdraw_records': 1,
222
+ 'v1/swap/trade/open_order': 1,
223
+ 'v1/swap/trade/plan_order': 1,
224
+ 'v1/swap/trade/leverage': 1,
225
+ 'v1/swap/trade/history_order': 1,
226
+ 'v1/swap/trade/history_trade': 1,
227
+ 'v1/swap/trade/position_history': 1,
228
+ 'v1/swap/trade/positions': 1,
229
+ 'v1/swap/account/balance': 1,
230
+ 'v1/swap/user_data/assets_margin': 1,
231
+ 'v1/swap/user_data/position_side/dual': 1,
232
+ 'v1/agent/teams': 1,
233
+ 'v1/agent/agent_links': 1,
234
+ 'v1/agent/regular_overview': 1,
235
+ 'v1/agent/agent_sub_overview': 1,
236
+ 'v1/agent/partener_user_deposit': 1,
237
+ 'v1/agent/partener_users_data': 1,
238
+ 'v1/agent/affiliate_uids': 1,
239
+ 'v1/agent/affiliate_commission': 1,
240
+ 'v1/agent/internal_withdrawal_status': 1, // https://developers.bydfi.com/en/agent/#get-internal-withdrawal-status
241
+ },
242
+ 'post': {
243
+ 'v1/account/transfer': 1,
244
+ 'v1/swap/trade/place_order': 1,
245
+ 'v1/swap/trade/batch_place_order': 1,
246
+ 'v1/swap/trade/edit_order': 1,
247
+ 'v1/swap/trade/batch_edit_order': 1,
248
+ 'v1/swap/trade/cancel_all_order': 1,
249
+ 'v1/swap/trade/leverage': 1,
250
+ 'v1/swap/trade/batch_leverage_margin': 1,
251
+ 'v1/swap/user_data/margin_type': 1,
252
+ 'v1/swap/user_data/position_side/dual': 1,
253
+ 'v1/agent/internal_withdrawal': 1, // https://developers.bydfi.com/en/agent/#internal-withdrawal
254
+ },
255
+ },
256
+ },
257
+ 'features': {
258
+ 'spot': undefined,
259
+ 'swap': {
260
+ 'linear': {
261
+ 'sandbox': false,
262
+ 'createOrder': {
263
+ 'marginMode': false,
264
+ 'triggerPrice': false,
265
+ 'triggerPriceType': {
266
+ 'mark': true,
267
+ 'last': true,
268
+ 'index': false,
269
+ },
270
+ 'stopLossPrice': true,
271
+ 'takeProfitPrice': true,
272
+ 'attachedStopLossTakeProfit': undefined,
273
+ 'timeInForce': {
274
+ 'IOC': true,
275
+ 'FOK': true,
276
+ 'PO': true,
277
+ 'GTD': false,
278
+ },
279
+ 'hedged': true,
280
+ 'selfTradePrevention': false,
281
+ 'trailing': true,
282
+ 'iceberg': false,
283
+ 'leverage': false,
284
+ 'marketBuyRequiresPrice': false,
285
+ 'marketBuyByCost': false,
286
+ },
287
+ 'createOrders': {
288
+ 'max': 5,
289
+ },
290
+ 'fetchMyTrades': {
291
+ 'marginMode': false,
292
+ 'daysBack': 182,
293
+ 'limit': 500,
294
+ 'untilDays': 7,
295
+ 'symbolRequired': false,
296
+ },
297
+ 'fetchOrder': undefined,
298
+ 'fetchOpenOrder': {
299
+ 'marginMode': false,
300
+ 'trigger': true,
301
+ 'trailing': false,
302
+ 'symbolRequired': true,
303
+ },
304
+ 'fetchOpenOrders': {
305
+ 'marginMode': false,
306
+ 'limit': 500,
307
+ 'trigger': true,
308
+ 'trailing': false,
309
+ 'symbolRequired': true,
310
+ },
311
+ 'fetchOrders': undefined,
312
+ 'fetchCanceledAndClosedOrders': {
313
+ 'marginMode': false,
314
+ 'limit': 500,
315
+ 'daysBack': 182,
316
+ 'untilDays': 7,
317
+ 'trigger': false,
318
+ 'trailing': false,
319
+ 'symbolRequired': false,
320
+ },
321
+ 'fetchClosedOrders': undefined,
322
+ 'fetchOHLCV': {
323
+ 'limit': 500,
324
+ },
325
+ },
326
+ 'inverse': undefined,
327
+ },
328
+ 'future': {
329
+ 'linear': undefined,
330
+ 'inverse': undefined,
331
+ },
332
+ },
333
+ 'timeframes': {
334
+ '1m': '1m',
335
+ '3m': '3m',
336
+ '5m': '5m',
337
+ '15m': '15m',
338
+ '30m': '30m',
339
+ '1h': '1h',
340
+ '2h': '2h',
341
+ '4h': '4h',
342
+ '6h': '6h',
343
+ '12h': '12h',
344
+ '1d': '1d',
345
+ },
346
+ 'precisionMode': TICK_SIZE,
347
+ 'exceptions': {
348
+ 'exact': {
349
+ '101001': AuthenticationError,
350
+ '101103': AuthenticationError,
351
+ '102001': BadRequest,
352
+ '102002': PermissionDenied,
353
+ '401': AuthenticationError,
354
+ '500': ExchangeError,
355
+ '501': ExchangeError,
356
+ '506': ExchangeError,
357
+ '510': RateLimitExceeded,
358
+ '511': AuthenticationError,
359
+ '513': BadRequest,
360
+ '514': BadRequest,
361
+ '600': BadRequest,
362
+ 'Position does not exist': BadRequest,
363
+ 'Requires transaction permissions': PermissionDenied,
364
+ 'Service error': ExchangeError,
365
+ 'transfer failed': InsufficientFunds, // {"code":500,"message":"transfer failed","success":false}
366
+ },
367
+ 'broad': {
368
+ 'is missing': ArgumentsRequired, // {"code":600,"message":"The parameter 'startTime' is missing"}
369
+ },
370
+ },
371
+ 'commonCurrencies': {},
372
+ 'options': {
373
+ 'networks': {
374
+ 'ERC20': 'ETH', // todo add more networks
375
+ },
376
+ 'timeInForce': {
377
+ 'GTC': 'GTC',
378
+ 'FOK': 'FOK',
379
+ 'IOC': 'IOC',
380
+ 'PO': 'POST_ONLY', // Post Only
381
+ },
382
+ 'accountsByType': {
383
+ 'spot': 'SPOT',
384
+ 'swap': 'SWAP',
385
+ 'funding': 'FUND',
386
+ },
387
+ 'accountsById': {
388
+ 'SPOT': 'spot',
389
+ 'SWAP': 'swap',
390
+ 'FUND': 'funding',
391
+ },
392
+ },
393
+ });
394
+ }
395
+ /**
396
+ * @method
397
+ * @name bydfi#fetchMarkets
398
+ * @description retrieves data on all markets for bydfi
399
+ * @see https://developers.bydfi.com/en/swap/market#fetching-trading-rules-and-pairs
400
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
401
+ * @returns {object[]} an array of objects representing market data
402
+ */
403
+ async fetchMarkets(params = {}) {
404
+ const response = await this.publicGetV1SwapMarketExchangeInfo(params);
405
+ //
406
+ // {
407
+ // "code": "200",
408
+ // "message": "success",
409
+ // "data": [
410
+ // {
411
+ // "symbol": "CLANKER-USDT",
412
+ // "baseAsset": "CLANKER",
413
+ // "marginAsset": "USDT",
414
+ // "quoteAsset": "USDT",
415
+ // "contractFactor": "0.01",
416
+ // "limitMaxQty": "50000",
417
+ // "limitMinQty": "1",
418
+ // "marketMaxQty": "10000",
419
+ // "marketMinQty": "1",
420
+ // "pricePrecision": "8",
421
+ // "basePrecision": "8",
422
+ // "feeRateTaker": "0.0006",
423
+ // "feeRateMaker": "0.0002",
424
+ // "liqFeeRate": "0.0006",
425
+ // "openBuyLimitRateMax": "0.05",
426
+ // "openSellLimitRateMax": "100",
427
+ // "openBuyLimitRateMin": "0.98",
428
+ // "openSellLimitRateMin": "0.05",
429
+ // "priceOrderPrecision": "2",
430
+ // "baseShowPrecision": "2",
431
+ // "maxLeverageLevel": "20",
432
+ // "volumePrecision": "2",
433
+ // "maxLimitOrderNum": "200",
434
+ // "maxPlanOrderNum": "10",
435
+ // "reverse": false,
436
+ // "onboardTime": "1763373600000",
437
+ // "status": "NORMAL"
438
+ // },
439
+ // ...
440
+ // ],
441
+ // "success": true
442
+ // }
443
+ const data = this.safeList(response, 'data', []);
444
+ return this.parseMarkets(data);
445
+ }
446
+ parseMarket(market) {
447
+ //
448
+ // {
449
+ // "symbol": "CLANKER-USDT",
450
+ // "baseAsset": "CLANKER",
451
+ // "marginAsset": "USDT",
452
+ // "quoteAsset": "USDT",
453
+ // "contractFactor": "0.01",
454
+ // "limitMaxQty": "50000",
455
+ // "limitMinQty": "1",
456
+ // "marketMaxQty": "10000",
457
+ // "marketMinQty": "1",
458
+ // "pricePrecision": "8",
459
+ // "basePrecision": "8",
460
+ // "feeRateTaker": "0.0006",
461
+ // "feeRateMaker": "0.0002",
462
+ // "liqFeeRate": "0.0006",
463
+ // "openBuyLimitRateMax": "0.05",
464
+ // "openSellLimitRateMax": "100",
465
+ // "openBuyLimitRateMin": "0.98",
466
+ // "openSellLimitRateMin": "0.05",
467
+ // "priceOrderPrecision": "2",
468
+ // "baseShowPrecision": "2",
469
+ // "maxLeverageLevel": "20",
470
+ // "volumePrecision": "2",
471
+ // "maxLimitOrderNum": "200",
472
+ // "maxPlanOrderNum": "10",
473
+ // "reverse": false,
474
+ // "onboardTime": "1763373600000",
475
+ // "status": "NORMAL"
476
+ // }
477
+ //
478
+ const id = this.safeString(market, 'symbol');
479
+ const baseId = this.safeString(market, 'baseAsset');
480
+ const quoteId = this.safeString(market, 'quoteAsset');
481
+ const settleId = this.safeString(market, 'marginAsset');
482
+ const base = this.safeCurrencyCode(baseId);
483
+ const quote = this.safeCurrencyCode(quoteId);
484
+ const settle = this.safeCurrencyCode(settleId);
485
+ const symbol = base + '/' + quote + ':' + settle;
486
+ const inverse = this.safeBool(market, 'reverse');
487
+ const limitMaxQty = this.safeString(market, 'limitMaxQty');
488
+ const marketMaxQty = this.safeString(market, 'marketMaxQty');
489
+ const maxAmountString = Precise.stringMax(limitMaxQty, marketMaxQty);
490
+ const marketMinQty = this.safeString(market, 'marketMinQty');
491
+ const limitMinQty = this.safeString(market, 'limitMinQty');
492
+ const minAmountString = Precise.stringMin(marketMinQty, limitMinQty);
493
+ const contractSize = this.safeString(market, 'contractFactor');
494
+ const pricePrecision = this.parsePrecision(this.safeString(market, 'priceOrderPrecision'));
495
+ const rawAmountPrecision = this.parsePrecision(this.safeString(market, 'volumePrecision'));
496
+ const amountPrecision = Precise.stringDiv(rawAmountPrecision, contractSize);
497
+ const basePrecision = this.parsePrecision(this.safeString(market, 'basePrecision'));
498
+ const taker = this.safeNumber(market, 'feeRateTaker');
499
+ const maker = this.safeNumber(market, 'feeRateMaker');
500
+ const maxLeverage = this.safeNumber(market, 'maxLeverageLevel');
501
+ const status = this.safeString(market, 'status');
502
+ return this.safeMarketStructure({
503
+ 'id': id,
504
+ 'symbol': symbol,
505
+ 'base': base,
506
+ 'quote': quote,
507
+ 'settle': settle,
508
+ 'baseId': baseId,
509
+ 'quoteId': quoteId,
510
+ 'settleId': settleId,
511
+ 'type': 'swap',
512
+ 'spot': false,
513
+ 'margin': undefined,
514
+ 'swap': true,
515
+ 'future': false,
516
+ 'option': false,
517
+ 'active': status === 'NORMAL',
518
+ 'contract': true,
519
+ 'linear': !inverse,
520
+ 'inverse': inverse,
521
+ 'taker': taker,
522
+ 'maker': maker,
523
+ 'contractSize': this.parseNumber(contractSize),
524
+ 'expiry': undefined,
525
+ 'expiryDatetime': undefined,
526
+ 'strike': undefined,
527
+ 'optionType': undefined,
528
+ 'precision': {
529
+ 'amount': this.parseNumber(amountPrecision),
530
+ 'price': this.parseNumber(pricePrecision),
531
+ 'base': this.parseNumber(basePrecision),
532
+ },
533
+ 'limits': {
534
+ 'leverage': {
535
+ 'min': undefined,
536
+ 'max': maxLeverage,
537
+ },
538
+ 'amount': {
539
+ 'min': this.parseNumber(minAmountString),
540
+ 'max': this.parseNumber(maxAmountString),
541
+ },
542
+ 'price': {
543
+ 'min': undefined,
544
+ 'max': undefined,
545
+ },
546
+ 'cost': {
547
+ 'min': undefined,
548
+ 'max': undefined,
549
+ },
550
+ },
551
+ 'created': this.parse8601(this.safeString(market, 'createdAt')),
552
+ 'info': market,
553
+ });
554
+ }
555
+ /**
556
+ * @method
557
+ * @name bydfi#fetchOrderBook
558
+ * @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
559
+ * @see https://developers.bydfi.com/en/swap/market#depth-information
560
+ * @param {string} symbol unified symbol of the market to fetch the order book for
561
+ * @param {int} [limit] the maximum amount of order book entries to return, could be 5, 10, 20, 50, 100, 500 or 1000 (default 500)
562
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
563
+ * @param {string} [params.loc] crypto location, default: us
564
+ * @returns {object} A dictionary of [order book structures]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-book-structure} indexed by market symbols
565
+ */
566
+ async fetchOrderBook(symbol, limit = undefined, params = {}) {
567
+ await this.loadMarkets();
568
+ const market = this.market(symbol);
569
+ const request = {
570
+ 'symbol': market['id'],
571
+ };
572
+ if (limit !== undefined) {
573
+ request['limit'] = this.getClosestLimit(limit);
574
+ }
575
+ const response = await this.publicGetV1SwapMarketDepth(this.extend(request, params));
576
+ //
577
+ // {
578
+ // "code": 200,
579
+ // "message": "success",
580
+ // "data": {
581
+ // "lastUpdateId": "221780076",
582
+ // "symbol": "ETH-USDT",
583
+ // "asks": [
584
+ // {
585
+ // "price": "2958.21",
586
+ // "amount": "39478"
587
+ // },
588
+ // ...
589
+ // ],
590
+ // "bids": [
591
+ // {
592
+ // "price": "2958.19",
593
+ // "amount": "174498"
594
+ // },
595
+ // ...
596
+ // ],
597
+ // "e": "221780076"
598
+ // },
599
+ // "success": true
600
+ // }
601
+ //
602
+ const data = this.safeDict(response, 'data', {});
603
+ const timestamp = this.milliseconds();
604
+ const orderBook = this.parseOrderBook(data, market['symbol'], timestamp, 'bids', 'asks', 'price', 'amount');
605
+ orderBook['nonce'] = this.safeInteger(data, 'lastUpdateId');
606
+ return orderBook;
607
+ }
608
+ getClosestLimit(limit) {
609
+ const limits = [5, 10, 20, 50, 100, 500, 1000];
610
+ let result = 1000;
611
+ for (let i = 0; i < limits.length; i++) {
612
+ if (limit <= limits[i]) {
613
+ result = limits[i];
614
+ break;
615
+ }
616
+ }
617
+ return result;
618
+ }
619
+ /**
620
+ * @method
621
+ * @name bydfi#fetchTrades
622
+ * @description get the list of most recent trades for a particular symbol
623
+ * @see https://developers.bydfi.com/en/swap/market#recent-trades
624
+ * @param {string} symbol unified symbol of the market to fetch trades for
625
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
626
+ * @param {int} [limit] the maximum amount of trades to fetch (default 500, max 1000)
627
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
628
+ * @param {int} [params.fromId] retrieve from which trade ID to start. Default to retrieve the most recent trade records
629
+ * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/?id=public-trades}
630
+ */
631
+ async fetchTrades(symbol, since = undefined, limit = undefined, params = {}) {
632
+ await this.loadMarkets();
633
+ const market = this.market(symbol);
634
+ const request = {
635
+ 'symbol': market['id'],
636
+ };
637
+ if (limit !== undefined) {
638
+ request['limit'] = limit;
639
+ }
640
+ const response = await this.publicGetV1SwapMarketTrades(this.extend(request, params));
641
+ //
642
+ // {
643
+ // "code": 200,
644
+ // "message": "success",
645
+ // "data": [
646
+ // {
647
+ // "id": "7407825178362667008",
648
+ // "symbol": "ETH-USDT",
649
+ // "price": "2970.49",
650
+ // "quantity": "63",
651
+ // "side": "SELL",
652
+ // "time": 1766163153218
653
+ // }
654
+ // ],
655
+ // "success": true
656
+ // }
657
+ //
658
+ const data = this.safeList(response, 'data', []);
659
+ return this.parseTrades(data, market, since, limit);
660
+ }
661
+ /**
662
+ * @method
663
+ * @name bydfi#fetchMyTrades
664
+ * @description fetch all trades made by the user
665
+ * @see https://developers.bydfi.com/en/swap/trade#historical-trades-query
666
+ * @param {string} symbol unified market symbol
667
+ * @param {int} [since] the earliest time in ms to fetch trades for
668
+ * @param {int} [limit] the maximum number of trades structures to retrieve
669
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
670
+ * @param {int} [params.until] the latest time in ms to fetch trades for
671
+ * @param {string} [params.contractType] FUTURE or DELIVERY, default is FUTURE
672
+ * @param {string} [params.wallet] The unique code of a sub-wallet
673
+ * @param {string} [params.orderType] order type ('LIMIT', 'MARKET', 'LIQ', 'LIMIT_CLOSE', 'MARKET_CLOSE', 'STOP', 'TAKE_PROFIT', 'STOP_MARKET', 'TAKE_PROFIT_MARKET' or 'TRAILING_STOP_MARKET')
674
+ * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/?id=trade-structure}
675
+ */
676
+ async fetchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
677
+ await this.loadMarkets();
678
+ const paginate = this.safeBool(params, 'paginate', false);
679
+ if (paginate) {
680
+ const maxLimit = 500;
681
+ params = this.omit(params, 'paginate');
682
+ params = this.extend(params, { 'paginationDirection': 'backward' });
683
+ const paginatedResponse = await this.fetchPaginatedCallDynamic('fetchMyTrades', symbol, since, limit, params, maxLimit, true);
684
+ return this.sortBy(paginatedResponse, 'timestamp');
685
+ }
686
+ let contractType = 'FUTURE';
687
+ [contractType, params] = this.handleOptionAndParams(params, 'fetchMyTrades', 'contractType', contractType);
688
+ const request = {
689
+ 'contractType': contractType,
690
+ };
691
+ let market = undefined;
692
+ if (symbol !== undefined) {
693
+ market = this.market(symbol);
694
+ request['symbol'] = market['id'];
695
+ }
696
+ params = this.handleSinceAndUntil('fetchMyTrades', since, params);
697
+ if (limit !== undefined) {
698
+ request['limit'] = limit;
699
+ }
700
+ const response = await this.privateGetV1SwapTradeHistoryTrade(this.extend(request, params));
701
+ //
702
+ // {
703
+ // "code": 200,
704
+ // "message": "success",
705
+ // "data": [
706
+ // {
707
+ // "orderId": "7408919189505597440",
708
+ // "wallet": "W001",
709
+ // "symbol": "ETH-USDC",
710
+ // "time": "1766423985842",
711
+ // "dealPrice": "3032.45",
712
+ // "dealVolume": "1",
713
+ // "fee": "0",
714
+ // "side": "BUY",
715
+ // "type": "2",
716
+ // "liqPrice": null,
717
+ // "basePrecision": "8",
718
+ // "baseShowPrecision": "2",
719
+ // "tradePnl": "0",
720
+ // "marginType": "CROSS",
721
+ // "leverageLevel": 1
722
+ // }
723
+ // ],
724
+ // "success": true
725
+ // }
726
+ //
727
+ const data = this.safeList(response, 'data', []);
728
+ return this.parseTrades(data, market, since, limit);
729
+ }
730
+ parseTrade(trade, market = undefined) {
731
+ //
732
+ // fetchTrades
733
+ // {
734
+ // "id": "7407825178362667008",
735
+ // "symbol": "ETH-USDT",
736
+ // "price": "2970.49",
737
+ // "quantity": "63",
738
+ // "side": "SELL",
739
+ // "time": 1766163153218
740
+ // }
741
+ //
742
+ // fetchMyTrades
743
+ // {
744
+ // "orderId": "7408919189505597440",
745
+ // "wallet": "W001",
746
+ // "symbol": "ETH-USDC",
747
+ // "time": "1766423985842",
748
+ // "dealPrice": "3032.45",
749
+ // "dealVolume": "1",
750
+ // "fee": "0",
751
+ // "side": "BUY",
752
+ // "type": "2",
753
+ // "liqPrice": null,
754
+ // "basePrecision": "8",
755
+ // "baseShowPrecision": "2",
756
+ // "tradePnl": "0",
757
+ // "marginType": "CROSS",
758
+ // "leverageLevel": 1
759
+ // }
760
+ //
761
+ const marketId = this.safeString(trade, 'symbol');
762
+ market = this.safeMarket(marketId, market);
763
+ const timestamp = this.safeInteger(trade, 'time');
764
+ let fee = undefined;
765
+ const rawType = this.safeString(trade, 'type');
766
+ const feeCost = this.safeString(trade, 'fee');
767
+ if (feeCost !== undefined) {
768
+ fee = {
769
+ 'cost': feeCost,
770
+ 'currency': market['settle'],
771
+ };
772
+ }
773
+ const orderId = this.safeString(trade, 'orderId');
774
+ let side = undefined; // fetchMyTrades always returns side BUY
775
+ if (orderId === undefined) {
776
+ // from fetchTrades
777
+ side = this.safeStringLower(trade, 'side');
778
+ }
779
+ return this.safeTrade({
780
+ 'info': trade,
781
+ 'timestamp': timestamp,
782
+ 'datetime': this.iso8601(timestamp),
783
+ 'symbol': market['symbol'],
784
+ 'id': this.safeString(trade, 'id'),
785
+ 'order': orderId,
786
+ 'type': this.parseTradeType(rawType),
787
+ 'side': side,
788
+ 'takerOrMaker': undefined,
789
+ 'price': this.safeString2(trade, 'price', 'dealPrice'),
790
+ 'amount': this.safeString2(trade, 'quantity', 'dealVolume'),
791
+ 'cost': undefined,
792
+ 'fee': fee,
793
+ }, market);
794
+ }
795
+ parseTradeType(type) {
796
+ const types = {
797
+ '1': 'limit',
798
+ '2': 'market',
799
+ '3': 'liquidation',
800
+ };
801
+ return this.safeString(types, type, type);
802
+ }
803
+ /**
804
+ * @method
805
+ * @name bydfi#fetchOHLCV
806
+ * @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
807
+ * @see https://developers.bydfi.com/en/swap/market#candlestick-data
808
+ * @param {string} symbol unified symbol of the market to fetch OHLCV data for
809
+ * @param {string} timeframe the length of time each candle represents
810
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
811
+ * @param {int} [limit] the maximum amount of candles to fetch (max 500)
812
+ * @param {object} [params] extra parameters specific to the bitteam api endpoint
813
+ * @param {int} [params.until] timestamp in ms of the latest candle to fetch
814
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
815
+ */
816
+ async fetchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
817
+ await this.loadMarkets();
818
+ const maxLimit = 500; // docs says max 1500, but in practice only 500 works
819
+ let paginate = false;
820
+ [paginate, params] = this.handleOptionAndParams(params, 'fetchOHLCV', 'paginate');
821
+ if (paginate) {
822
+ return this.fetchPaginatedCallDeterministic('fetchOHLCV', symbol, since, limit, timeframe, params, maxLimit);
823
+ }
824
+ const market = this.market(symbol);
825
+ const interval = this.safeString(this.timeframes, timeframe, timeframe);
826
+ const request = {
827
+ 'symbol': market['id'],
828
+ 'interval': interval,
829
+ };
830
+ let startTime = since;
831
+ const numberOfCandles = limit ? limit : maxLimit;
832
+ let until = undefined;
833
+ [until, params] = this.handleOptionAndParams(params, 'fetchOHLCV', 'until');
834
+ const now = this.milliseconds();
835
+ const duration = this.parseTimeframe(timeframe) * 1000;
836
+ const timeDelta = duration * numberOfCandles;
837
+ if (startTime === undefined && until === undefined) {
838
+ startTime = now - timeDelta;
839
+ until = now;
840
+ }
841
+ else if (until === undefined) {
842
+ until = startTime + timeDelta;
843
+ if (until > now) {
844
+ until = now;
845
+ }
846
+ }
847
+ else if (startTime === undefined) {
848
+ startTime = until - timeDelta;
849
+ }
850
+ request['startTime'] = startTime;
851
+ request['endTime'] = until;
852
+ if (limit !== undefined) {
853
+ request['limit'] = limit;
854
+ }
855
+ const response = await this.publicGetV1SwapMarketKlines(this.extend(request, params));
856
+ //
857
+ // {
858
+ // "code": 200,
859
+ // "message": "success",
860
+ // "data": [
861
+ // {
862
+ // "s": "ETH-USDT",
863
+ // "t": "1766166000000",
864
+ // "c": "2964.990000000000000000",
865
+ // "o": "2967.830000000000000000",
866
+ // "h": "2967.830000000000000000",
867
+ // "l": "2964.130000000000000000",
868
+ // "v": "20358.000000000000000000"
869
+ // }
870
+ // ],
871
+ // "success": true
872
+ // }
873
+ //
874
+ const data = this.safeList(response, 'data', []);
875
+ const result = this.parseOHLCVs(data, market, timeframe, since, limit);
876
+ return result;
877
+ }
878
+ parseOHLCV(ohlcv, market = undefined) {
879
+ //
880
+ // {
881
+ // "s": "ETH-USDT",
882
+ // "t": "1766166000000",
883
+ // "c": "2964.990000000000000000",
884
+ // "o": "2967.830000000000000000",
885
+ // "h": "2967.830000000000000000",
886
+ // "l": "2964.130000000000000000",
887
+ // "v": "20358.000000000000000000"
888
+ // }
889
+ //
890
+ return [
891
+ this.safeInteger(ohlcv, 't'),
892
+ this.safeNumber(ohlcv, 'o'),
893
+ this.safeNumber(ohlcv, 'h'),
894
+ this.safeNumber(ohlcv, 'l'),
895
+ this.safeNumber(ohlcv, 'c'),
896
+ this.safeNumber(ohlcv, 'v'),
897
+ ];
898
+ }
899
+ /**
900
+ * @method
901
+ * @name bydfi#fetchTickers
902
+ * @see https://developers.bydfi.com/en/swap/market#24hr-price-change-statistics
903
+ * @description fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
904
+ * @param {string[]|undefined} symbols unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
905
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
906
+ * @returns {object} a dictionary of [ticker structures]{@link https://docs.ccxt.com/?id=ticker-structure}
907
+ */
908
+ async fetchTickers(symbols = undefined, params = {}) {
909
+ await this.loadMarkets();
910
+ const response = await this.publicGetV1SwapMarketTicker24hr(params);
911
+ //
912
+ // {
913
+ // "code": 200,
914
+ // "message": "success",
915
+ // "data": [
916
+ // {
917
+ // "symbol": "BTC-USDT",
918
+ // "open": "86452.9",
919
+ // "high": "89371.2",
920
+ // "low": "84418.5",
921
+ // "last": "87050.3",
922
+ // "vol": "12938783",
923
+ // "time": 1766169423872
924
+ // }
925
+ // ],
926
+ // "success": true
927
+ // }
928
+ //
929
+ const data = this.safeList(response, 'data', []);
930
+ return this.parseTickers(data, symbols);
931
+ }
932
+ /**
933
+ * @method
934
+ * @name bydfi#fetchTicker
935
+ * @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
936
+ * @see https://developers.bydfi.com/en/swap/market#24hr-price-change-statistics
937
+ * @param {string} symbol unified symbol of the market to fetch the ticker for
938
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
939
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/?id=ticker-structure}
940
+ */
941
+ async fetchTicker(symbol, params = {}) {
942
+ await this.loadMarkets();
943
+ const market = this.market(symbol);
944
+ const request = {
945
+ 'symbol': market['id'],
946
+ };
947
+ const response = await this.publicGetV1SwapMarketTicker24hr(this.extend(request, params));
948
+ const data = this.safeList(response, 'data', []);
949
+ const ticker = this.safeDict(data, 0, {});
950
+ return this.parseTicker(ticker, market);
951
+ }
952
+ parseTicker(ticker, market = undefined) {
953
+ //
954
+ // fetchTicker/fetchTickers
955
+ // {
956
+ // "symbol": "BTC-USDT",
957
+ // "open": "86452.9",
958
+ // "high": "89371.2",
959
+ // "low": "84418.5",
960
+ // "last": "87050.3",
961
+ // "vol": "12938783",
962
+ // "time": 1766169423872
963
+ // }
964
+ //
965
+ const marketId = this.safeString2(ticker, 'symbol', 's');
966
+ market = this.safeMarket(marketId, market);
967
+ const timestamp = this.safeInteger2(ticker, 'time', 'E');
968
+ const last = this.safeString2(ticker, 'last', 'c');
969
+ return this.safeTicker({
970
+ 'symbol': this.safeSymbol(marketId, market),
971
+ 'timestamp': timestamp,
972
+ 'datetime': this.iso8601(timestamp),
973
+ 'high': this.safeString2(ticker, 'high', 'h'),
974
+ 'low': this.safeString2(ticker, 'low', 'l'),
975
+ 'bid': undefined,
976
+ 'bidVolume': undefined,
977
+ 'ask': undefined,
978
+ 'askVolume': undefined,
979
+ 'vwap': undefined,
980
+ 'open': this.safeString2(ticker, 'open', 'o'),
981
+ 'close': last,
982
+ 'last': last,
983
+ 'previousClose': undefined,
984
+ 'change': undefined,
985
+ 'percentage': undefined,
986
+ 'average': undefined,
987
+ 'baseVolume': this.safeString2(ticker, 'vol', 'v'),
988
+ 'quoteVolume': undefined,
989
+ 'markPrice': undefined,
990
+ 'indexPrice': undefined,
991
+ 'info': ticker,
992
+ }, market);
993
+ }
994
+ /**
995
+ * @method
996
+ * @name bydfi#fetchFundingRate
997
+ * @description fetch the current funding rate
998
+ * @see https://developers.bydfi.com/en/swap/market#recent-funding-rate
999
+ * @param {string} symbol unified market symbol
1000
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1001
+ * @returns {object} a [funding rate structure]{@link https://docs.ccxt.com/?id=funding-rate-structure}
1002
+ */
1003
+ async fetchFundingRate(symbol, params = {}) {
1004
+ await this.loadMarkets();
1005
+ const market = this.market(symbol);
1006
+ const request = {
1007
+ 'symbol': market['id'],
1008
+ };
1009
+ const response = await this.publicGetV1SwapMarketFundingRate(this.extend(request, params));
1010
+ //
1011
+ // {
1012
+ // "code": 200,
1013
+ // "message": "success",
1014
+ // "data": {
1015
+ // "symbol": "BTC-USDT",
1016
+ // "lastFundingRate": "0.0001",
1017
+ // "nextFundingTime": "1766188800000",
1018
+ // "time": "1766170665007"
1019
+ // },
1020
+ // "success": true
1021
+ // }
1022
+ //
1023
+ const data = this.safeDict(response, 'data');
1024
+ return this.parseFundingRate(data, market);
1025
+ }
1026
+ parseFundingRate(contract, market = undefined) {
1027
+ //
1028
+ // {
1029
+ // "symbol": "BTC-USDT",
1030
+ // "lastFundingRate": "0.0001",
1031
+ // "nextFundingTime": "1766188800000",
1032
+ // "time": "1766170665007"
1033
+ // }
1034
+ //
1035
+ const marketId = this.safeString(contract, 'symbol');
1036
+ const symbol = this.safeSymbol(marketId, market);
1037
+ const timestamp = this.safeInteger(contract, 'time');
1038
+ const nextFundingTimestamp = this.safeInteger(contract, 'nextFundingTime');
1039
+ return {
1040
+ 'info': contract,
1041
+ 'symbol': symbol,
1042
+ 'markPrice': undefined,
1043
+ 'indexPrice': undefined,
1044
+ 'interestRate': undefined,
1045
+ 'estimatedSettlePrice': undefined,
1046
+ 'timestamp': timestamp,
1047
+ 'datetime': this.iso8601(timestamp),
1048
+ 'fundingRate': this.safeNumber(contract, 'lastFundingRate'),
1049
+ 'fundingTimestamp': undefined,
1050
+ 'fundingDatetime': undefined,
1051
+ 'nextFundingRate': undefined,
1052
+ 'nextFundingTimestamp': nextFundingTimestamp,
1053
+ 'nextFundingDatetime': this.iso8601(nextFundingTimestamp),
1054
+ 'previousFundingRate': undefined,
1055
+ 'previousFundingTimestamp': undefined,
1056
+ 'previousFundingDatetime': undefined,
1057
+ 'interval': undefined,
1058
+ };
1059
+ }
1060
+ /**
1061
+ * @method
1062
+ * @name bydfi#fetchFundingRateHistory
1063
+ * @description fetches historical funding rate prices
1064
+ * @see https://developers.bydfi.com/en/swap/market#historical-funding-rates
1065
+ * @param {string} symbol unified symbol of the market to fetch the funding rate history for
1066
+ * @param {int} [since] timestamp in ms of the earliest funding rate to fetch
1067
+ * @param {int} [limit] the maximum amount of [funding rate structures]{@link https://docs.ccxt.com/?id=funding-rate-history-structure} to fetch
1068
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1069
+ * @param {int} [params.until] timestamp in ms of the latest funding rate to fetch
1070
+ * @returns {object[]} a list of [funding rate structures]{@link https://docs.ccxt.com/?id=funding-rate-history-structure}
1071
+ */
1072
+ async fetchFundingRateHistory(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1073
+ if (symbol === undefined) {
1074
+ throw new ArgumentsRequired(this.id + ' fetchFundingRateHistory() requires a symbol argument');
1075
+ }
1076
+ await this.loadMarkets();
1077
+ const market = this.market(symbol);
1078
+ const request = {
1079
+ 'symbol': market['id'],
1080
+ };
1081
+ if (since !== undefined) {
1082
+ request['startTime'] = since;
1083
+ }
1084
+ if (limit !== undefined) {
1085
+ request['limit'] = limit;
1086
+ }
1087
+ let until = undefined;
1088
+ [until, params] = this.handleOptionAndParams(params, 'fetchFundingRateHistory', 'until');
1089
+ if (until !== undefined) {
1090
+ request['endTime'] = until;
1091
+ }
1092
+ const response = await this.publicGetV1SwapMarketFundingRateHistory(this.extend(request, params));
1093
+ //
1094
+ // {
1095
+ // "code": 200,
1096
+ // "message": "success",
1097
+ // "data": [
1098
+ // {
1099
+ // "symbol": "ETH-USDT",
1100
+ // "fundingRate": "0.00000025",
1101
+ // "fundingTime": "1765584000000",
1102
+ // "markPrice": "3083.2"
1103
+ // }
1104
+ // ],
1105
+ // "success": true
1106
+ // }
1107
+ //
1108
+ const data = this.safeList(response, 'data', []);
1109
+ return this.parseFundingRateHistories(data, market, since, limit);
1110
+ }
1111
+ parseFundingRateHistory(contract, market = undefined) {
1112
+ //
1113
+ // {
1114
+ // "symbol": "ETH-USDT",
1115
+ // "fundingRate": "0.00000025",
1116
+ // "fundingTime": "1765584000000",
1117
+ // "markPrice": "3083.2"
1118
+ // }
1119
+ //
1120
+ const marketId = this.safeString(contract, 'symbol');
1121
+ const timestamp = this.safeInteger(contract, 'fundingTime');
1122
+ return {
1123
+ 'info': contract,
1124
+ 'symbol': this.safeSymbol(marketId, market),
1125
+ 'fundingRate': this.safeNumber(contract, 'fundingRate'),
1126
+ 'timestamp': timestamp,
1127
+ 'datetime': this.iso8601(timestamp),
1128
+ };
1129
+ }
1130
+ /**
1131
+ * @method
1132
+ * @name bydfi#createOrder
1133
+ * @description create a trade order
1134
+ * @see https://developers.bydfi.com/en/swap/trade#placing-an-order
1135
+ * @param {string} symbol unified symbol of the market to create an order in
1136
+ * @param {string} type 'market' or 'limit'
1137
+ * @param {string} side 'buy' or 'sell'
1138
+ * @param {float} amount how much of currency you want to trade in units of base currency
1139
+ * @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
1140
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1141
+ * @param {string} [params.wallet] The unique code of a sub-wallet. W001 is the default wallet and the main wallet code of the contract
1142
+ * @param {bool} [params.hedged] true for hedged mode, false for one way mode, default is false
1143
+ * @param {string} [params.clientOrderId] Custom order ID, must be unique for open orders
1144
+ * @param {string} [params.timeInForce] 'GTC' (Good Till Cancelled), 'FOK' (Fill Or Kill), 'IOC' (Immediate Or Cancel), 'PO' (Post Only)
1145
+ * @param {bool} [params.postOnly] true or false, whether the order is post-only
1146
+ * @param {bool} [params.reduceOnly] true or false, true or false whether the order is reduce-only
1147
+ * @param {float} [params.stopLossPrice] The price a stop loss order is triggered at
1148
+ * @param {float} [params.takeProfitPrice] The price a take profit order is triggered at
1149
+ * @param {float} [params.trailingTriggerPrice] the price to activate a trailing order, default uses the price argument or market price if price is not provided
1150
+ * @param {float} [params.trailingPercent] the percent to trail away from the current market price
1151
+ * @param {string} [params.triggerPriceType] 'MARK_PRICE' or 'CONTRACT_PRICE', default is 'CONTRACT_PRICE', the price type used to trigger stop orders
1152
+ * @param {bool} [params.closePosition] true or false, whether to close all positions after triggering, only supported in STOP_MARKET and TAKE_PROFIT_MARKET; not used with quantity;
1153
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/?id=order-structure}
1154
+ */
1155
+ async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
1156
+ await this.loadMarkets();
1157
+ const market = this.market(symbol);
1158
+ let orderRequest = this.createOrderRequest(symbol, type, side, amount, price, params);
1159
+ let wallet = 'W001';
1160
+ [wallet, params] = this.handleOptionAndParams(params, 'createOrder', 'wallet', wallet);
1161
+ orderRequest = this.extend(orderRequest, { 'wallet': wallet });
1162
+ const response = await this.privatePostV1SwapTradePlaceOrder(orderRequest);
1163
+ //
1164
+ // {
1165
+ // "code": 200,
1166
+ // "message": "success",
1167
+ // "data": {
1168
+ // "wallet": "W001",
1169
+ // "symbol": "ETH-USDT",
1170
+ // "orderId": "7408875768086683648",
1171
+ // "clientOrderId": "7408875768086683648",
1172
+ // "price": "1000",
1173
+ // "origQty": "10",
1174
+ // "avgPrice": null,
1175
+ // "executedQty": "0",
1176
+ // "orderType": "LIMIT",
1177
+ // "side": "BUY",
1178
+ // "status": "NEW",
1179
+ // "stopPrice": null,
1180
+ // "activatePrice": null,
1181
+ // "timeInForce": null,
1182
+ // "workingType": "CONTRACT_PRICE",
1183
+ // "positionSide": "BOTH",
1184
+ // "priceProtect": false,
1185
+ // "reduceOnly": false,
1186
+ // "closePosition": false,
1187
+ // "createTime": "1766413633367",
1188
+ // "updateTime": "1766413633367"
1189
+ // },
1190
+ // "success": true
1191
+ // }
1192
+ //
1193
+ const data = this.safeDict(response, 'data', {});
1194
+ return this.parseOrder(data, market);
1195
+ }
1196
+ createOrderRequest(symbol, type, side, amount, price = undefined, params = {}) {
1197
+ const market = this.market(symbol);
1198
+ const request = {
1199
+ 'symbol': market['id'],
1200
+ 'side': side.toUpperCase(),
1201
+ // 'positionSide': STRING Position direction, not required in single position mode, default and can only be BOTH; required in dual position mode, and can only choose LONG or SHORT
1202
+ // 'type': STRING Order type LIMIT / MARKET / STOP / TAKE_PROFIT / STOP_MARKET / TAKE_PROFIT_MARKET / TRAILING_STOP_MARKET
1203
+ // 'reduceOnly': BOOL true, false; defaults to false in non-dual mode; not accepted in dual mode; not supported when using closePosition.
1204
+ // 'quantity': DECIMAL Order quantity, not supported with closePosition.
1205
+ // 'price': DECIMAL Order price
1206
+ // 'clientOrderId': STRING User-defined order number, must not be repeated in pending orders. If blank, the system will assign automatically
1207
+ // 'stopPrice': DECIMAL Trigger price, only required for STOP, STOP_MARKET, TAKE_PROFIT, TAKE_PROFIT_MARKET
1208
+ // 'closePosition': BOOL true, false; all positions closed after triggering, only supported in STOP_MARKET and TAKE_PROFIT_MARKET; not used with quantity; has a self-closing effect, not used with reduceOnly
1209
+ // 'activationPrice': DECIMAL Trailing stop activation price, required for TRAILING_STOP_MARKET, default to current market price upon order (supports different workingType)
1210
+ // 'callbackRate': DECIMAL Trailing stop callback rate, can range from [0.1, 5], where 1 represents 1%, only required for TRAILING_STOP_MARKET
1211
+ // 'timeInForce': STRING Validity method GTC / FOK / POST_ONLY / IOC / TRAILING_STOP
1212
+ // 'workingType': STRING stopPrice trigger type: MARK_PRICE(marking price), CONTRACT_PRICE(latest contract price). Default CONTRACT_PRICE
1213
+ };
1214
+ const stopLossPrice = this.safeString(params, 'stopLossPrice');
1215
+ const isStopLossOrder = (stopLossPrice !== undefined);
1216
+ const takeProfitPrice = this.safeString(params, 'takeProfitPrice');
1217
+ const isTakeProfitOrder = (takeProfitPrice !== undefined);
1218
+ const trailingPercent = this.safeString(params, 'trailingPercent');
1219
+ const isTailingStopOrder = (trailingPercent !== undefined);
1220
+ let stopPrice = undefined;
1221
+ if (isStopLossOrder || isTakeProfitOrder) {
1222
+ stopPrice = isStopLossOrder ? stopLossPrice : takeProfitPrice;
1223
+ params = this.omit(params, ['stopLossPrice', 'takeProfitPrice']);
1224
+ request['stopPrice'] = this.priceToPrecision(symbol, stopPrice);
1225
+ }
1226
+ else if (isTailingStopOrder) {
1227
+ params = this.omit(params, ['trailingPercent']);
1228
+ request['callbackRate'] = trailingPercent;
1229
+ let trailingTriggerPrice = this.numberToString(price);
1230
+ [trailingTriggerPrice, params] = this.handleParamString(params, 'trailingTriggerPrice', trailingTriggerPrice);
1231
+ if (trailingTriggerPrice !== undefined) {
1232
+ request['activationPrice'] = this.priceToPrecision(symbol, trailingTriggerPrice);
1233
+ params = this.omit(params, ['trailingTriggerPrice']);
1234
+ }
1235
+ }
1236
+ type = type.toUpperCase();
1237
+ const isMarketOrder = ((type === 'MARKET') || (type === 'STOP_MARKET') || (type === 'TAKE_PROFIT_MARKET') || (type === 'TRAILING_STOP_MARKET'));
1238
+ if (isMarketOrder) {
1239
+ if (type === 'MARKET') {
1240
+ if (isStopLossOrder) {
1241
+ type = 'STOP_MARKET';
1242
+ }
1243
+ else if (isTakeProfitOrder) {
1244
+ type = 'TAKE_PROFIT_MARKET';
1245
+ }
1246
+ else if (isTailingStopOrder) {
1247
+ type = 'TRAILING_STOP_MARKET';
1248
+ }
1249
+ }
1250
+ }
1251
+ else {
1252
+ if (price === undefined) {
1253
+ throw new ArgumentsRequired(this.id + ' createOrder() requires a price argument for a ' + type + ' order');
1254
+ }
1255
+ request['price'] = this.priceToPrecision(symbol, price);
1256
+ if (isStopLossOrder) {
1257
+ type = 'STOP';
1258
+ }
1259
+ else if (isTakeProfitOrder) {
1260
+ type = 'TAKE_PROFIT';
1261
+ }
1262
+ }
1263
+ request['type'] = type;
1264
+ let hedged = false;
1265
+ [hedged, params] = this.handleOptionAndParams(params, 'createOrder', 'hedged', hedged);
1266
+ const reduceOnly = this.safeBool(params, 'reduceOnly', false);
1267
+ if (hedged) {
1268
+ params = this.omit(params, 'reduceOnly');
1269
+ if (side === 'buy') {
1270
+ request['positionSide'] = reduceOnly ? 'SHORT' : 'LONG';
1271
+ }
1272
+ else if (side === 'sell') {
1273
+ request['positionSide'] = reduceOnly ? 'LONG' : 'SHORT';
1274
+ }
1275
+ }
1276
+ const closePosition = this.safeBool(params, 'closePosition', false);
1277
+ if (!closePosition) {
1278
+ params = this.omit(params, 'closePosition');
1279
+ request['quantity'] = this.amountToPrecision(symbol, amount);
1280
+ }
1281
+ else if ((type !== 'STOP_MARKET') && (type !== 'TAKE_PROFIT_MARKET')) {
1282
+ throw new NotSupported(this.id + ' createOrder() closePosition is only supported for stopLoss and takeProfit market orders');
1283
+ }
1284
+ let timeInForce = this.handleTimeInForce(params);
1285
+ let postOnly = false;
1286
+ [postOnly, params] = this.handlePostOnly(isMarketOrder, timeInForce === 'POST_ONLY', params);
1287
+ if (postOnly) {
1288
+ timeInForce = 'POST_ONLY';
1289
+ }
1290
+ if (timeInForce !== undefined) {
1291
+ request['timeInForce'] = timeInForce;
1292
+ params = this.omit(params, 'timeInForce');
1293
+ }
1294
+ if (isStopLossOrder || isTakeProfitOrder || isTailingStopOrder) {
1295
+ let workingType = 'CONTRACT_PRICE';
1296
+ [workingType, params] = this.handleOptionAndParams(params, 'createOrder', 'triggerPriceType', workingType);
1297
+ request['workingType'] = this.encodeWorkingType(workingType);
1298
+ }
1299
+ return this.extend(request, params);
1300
+ }
1301
+ encodeWorkingType(workingType) {
1302
+ const types = {
1303
+ 'markPrice': 'MARK_PRICE',
1304
+ 'mark': 'MARK_PRICE',
1305
+ 'contractPrice': 'CONTRACT_PRICE',
1306
+ 'contract': 'CONTRACT_PRICE',
1307
+ 'last': 'CONTRACT_PRICE',
1308
+ };
1309
+ return this.safeString(types, workingType, workingType);
1310
+ }
1311
+ /**
1312
+ * @method
1313
+ * @name bydfi#createOrders
1314
+ * @description create a list of trade orders
1315
+ * @see https://developers.bydfi.com/en/swap/trade#batch-order-placement
1316
+ * @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
1317
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1318
+ * @param {string} [params.wallet] The unique code of a sub-wallet. W001 is the default wallet and the main wallet code of the contract
1319
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/?id=order-structure}
1320
+ */
1321
+ async createOrders(orders, params = {}) {
1322
+ await this.loadMarkets();
1323
+ const length = orders.length;
1324
+ if (length > 5) {
1325
+ throw new BadRequest(this.id + ' createOrders() accepts a maximum of 5 orders');
1326
+ }
1327
+ const ordersRequests = [];
1328
+ for (let i = 0; i < orders.length; i++) {
1329
+ const rawOrder = orders[i];
1330
+ const symbol = this.safeString(rawOrder, 'symbol');
1331
+ const type = this.safeString(rawOrder, 'type');
1332
+ const side = this.safeString(rawOrder, 'side');
1333
+ const amount = this.safeNumber(rawOrder, 'amount');
1334
+ const price = this.safeNumber(rawOrder, 'price');
1335
+ const orderParams = this.safeDict(rawOrder, 'params', {});
1336
+ const orderRequest = this.createOrderRequest(symbol, type, side, amount, price, orderParams);
1337
+ ordersRequests.push(orderRequest);
1338
+ }
1339
+ let wallet = 'W001';
1340
+ [wallet, params] = this.handleOptionAndParams(params, 'createOrder', 'wallet', wallet);
1341
+ const request = {
1342
+ 'wallet': wallet,
1343
+ 'orders': ordersRequests,
1344
+ };
1345
+ const response = await this.privatePostV1SwapTradeBatchPlaceOrder(this.extend(request, params));
1346
+ const data = this.safeList(response, 'data', []);
1347
+ return this.parseOrders(data);
1348
+ }
1349
+ /**
1350
+ * @method
1351
+ * @name bydfi#editOrder
1352
+ * @description edit a trade order
1353
+ * @see https://developers.bydfi.com/en/swap/trade#order-modification
1354
+ * @param {string} id order id (mandatory if params.clientOrderId is not provided)
1355
+ * @param {string} [symbol] unified symbol of the market to create an order in
1356
+ * @param {string} [type] not used by bydfi editOrder
1357
+ * @param {string} [side] 'buy' or 'sell'
1358
+ * @param {float} [amount] how much of the currency you want to trade in units of the base currency
1359
+ * @param {float} [price] the price for the order, in units of the quote currency, ignored in market orders
1360
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1361
+ * @param {string} [params.clientOrderId] a unique identifier for the order (could be alternative to id)
1362
+ * @param {string} [params.wallet] The unique code of a sub-wallet. W001 is the default wallet and the main wallet code of the contract
1363
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/?id=order-structure}
1364
+ */
1365
+ async editOrder(id, symbol, type, side, amount = undefined, price = undefined, params = {}) {
1366
+ await this.loadMarkets();
1367
+ const request = this.createEditOrderRequest(id, symbol, 'limit', side, amount, price, params);
1368
+ let wallet = 'W001';
1369
+ [wallet, params] = this.handleOptionAndParams(params, 'editOrder', 'wallet', wallet);
1370
+ request['wallet'] = wallet;
1371
+ const response = await this.privatePostV1SwapTradeEditOrder(request);
1372
+ const data = this.safeDict(response, 'data', {});
1373
+ return this.parseOrder(data);
1374
+ }
1375
+ /**
1376
+ * @method
1377
+ * @name bydfi#editOrders
1378
+ * @description edit a list of trade orders
1379
+ * @see https://developers.bydfi.com/en/swap/trade#batch-order-modification
1380
+ * @param {Array} orders list of orders to edit, each object should contain the parameters required by editOrder, namely id, symbol, amount, price and params
1381
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1382
+ * @param {string} [params.wallet] The unique code of a sub-wallet. W001 is the default wallet and the main wallet code of the contract
1383
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/?id=order-structure}
1384
+ */
1385
+ async editOrders(orders, params = {}) {
1386
+ await this.loadMarkets();
1387
+ const length = orders.length;
1388
+ if (length > 5) {
1389
+ throw new BadRequest(this.id + ' editOrders() accepts a maximum of 5 orders');
1390
+ }
1391
+ const ordersRequests = [];
1392
+ for (let i = 0; i < orders.length; i++) {
1393
+ const rawOrder = orders[i];
1394
+ const id = this.safeString(rawOrder, 'id');
1395
+ const symbol = this.safeString(rawOrder, 'symbol');
1396
+ const side = this.safeString(rawOrder, 'side');
1397
+ const amount = this.safeNumber(rawOrder, 'amount');
1398
+ const price = this.safeNumber(rawOrder, 'price');
1399
+ const orderParams = this.safeDict(rawOrder, 'params', {});
1400
+ const orderRequest = this.createEditOrderRequest(id, symbol, 'limit', side, amount, price, orderParams);
1401
+ ordersRequests.push(orderRequest);
1402
+ }
1403
+ let wallet = 'W001';
1404
+ [wallet, params] = this.handleOptionAndParams(params, 'editOrder', 'wallet', wallet);
1405
+ const request = {
1406
+ 'wallet': wallet,
1407
+ 'editOrders': ordersRequests,
1408
+ };
1409
+ const response = await this.privatePostV1SwapTradeBatchEditOrder(this.extend(request, params));
1410
+ const data = this.safeList(response, 'data', []);
1411
+ return this.parseOrders(data);
1412
+ }
1413
+ createEditOrderRequest(id, symbol, type, side, amount = undefined, price = undefined, params = {}) {
1414
+ const clientOrderId = this.safeString(params, 'clientOrderId');
1415
+ const request = {};
1416
+ if ((id === undefined) && (clientOrderId === undefined)) {
1417
+ throw new ArgumentsRequired(this.id + ' editOrder() requires an id argument or a clientOrderId parameter');
1418
+ }
1419
+ else if (id !== undefined) {
1420
+ request['orderId'] = id;
1421
+ }
1422
+ const market = this.market(symbol);
1423
+ request['symbol'] = market['id'];
1424
+ if (side !== undefined) {
1425
+ request['side'] = side.toUpperCase();
1426
+ }
1427
+ if (amount !== undefined) {
1428
+ request['quantity'] = this.amountToPrecision(symbol, amount);
1429
+ }
1430
+ if (price !== undefined) {
1431
+ request['price'] = this.priceToPrecision(symbol, price);
1432
+ }
1433
+ return this.extend(request, params);
1434
+ }
1435
+ /**
1436
+ * @method
1437
+ * @name bydfi#cancelAllOrders
1438
+ * @description cancel all open orders in a market
1439
+ * @see https://developers.bydfi.com/en/swap/trade#complete-order-cancellation
1440
+ * @param {string} symbol unified market symbol of the market to cancel orders in
1441
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1442
+ * @param {string} [params.wallet] The unique code of a sub-wallet. W001 is the default wallet and the main wallet code of the contract
1443
+ * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/?id=order-structure}
1444
+ */
1445
+ async cancelAllOrders(symbol = undefined, params = {}) {
1446
+ if (symbol === undefined) {
1447
+ throw new ArgumentsRequired(this.id + ' cancelAllOrders() requires a symbol argument');
1448
+ }
1449
+ await this.loadMarkets();
1450
+ const market = this.market(symbol);
1451
+ let wallet = 'W001';
1452
+ [wallet, params] = this.handleOptionAndParams(params, 'cancelAllOrders', 'wallet', wallet);
1453
+ const request = {
1454
+ 'symbol': market['id'],
1455
+ 'wallet': wallet,
1456
+ };
1457
+ const response = await this.privatePostV1SwapTradeCancelAllOrder(this.extend(request, params));
1458
+ //
1459
+ // {
1460
+ // "code": 200,
1461
+ // "message": "success",
1462
+ // "data": [
1463
+ // {
1464
+ // "wallet": "W001",
1465
+ // "symbol": "ETH-USDT",
1466
+ // "orderId": "7408875768086683648",
1467
+ // "clientOrderId": "7408875768086683648",
1468
+ // "price": "1000",
1469
+ // "origQty": "10",
1470
+ // "avgPrice": "0",
1471
+ // "executedQty": "0",
1472
+ // "orderType": "LIMIT",
1473
+ // "side": "BUY",
1474
+ // "status": "CANCELED",
1475
+ // "stopPrice": null,
1476
+ // "activatePrice": null,
1477
+ // "timeInForce": null,
1478
+ // "workingType": "CONTRACT_PRICE",
1479
+ // "positionSide": "BOTH",
1480
+ // "priceProtect": false,
1481
+ // "reduceOnly": false,
1482
+ // "closePosition": false,
1483
+ // "createTime": "1766413633367",
1484
+ // "updateTime": "1766413633370"
1485
+ // }
1486
+ // ],
1487
+ // "success": true
1488
+ // }
1489
+ //
1490
+ const data = this.safeList(response, 'data', []);
1491
+ return this.parseOrders(data, market);
1492
+ }
1493
+ /**
1494
+ * @method
1495
+ * @name bydfi#fetchOpenOrders
1496
+ * @description fetch all unfilled currently open orders
1497
+ * @see https://developers.bydfi.com/en/swap/trade#pending-order-query
1498
+ * @see https://developers.bydfi.com/en/swap/trade#planned-order-query
1499
+ * @param {string} symbol unified market symbol of the market orders were made in
1500
+ * @param {int} [since] the earliest time in ms to fetch orders for
1501
+ * @param {int} [limit] the maximum number of order structures to retrieve
1502
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1503
+ * @param {bool} [params.trigger] true or false, whether to fetch conditional orders only
1504
+ * @param {string} [params.wallet] The unique code of a sub-wallet. W001 is the default wallet and the main wallet code of the contract
1505
+ * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/?id=order-structure}
1506
+ */
1507
+ async fetchOpenOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1508
+ if (symbol === undefined) {
1509
+ throw new ArgumentsRequired(this.id + ' fetchOpenOrders() requires a symbol argument');
1510
+ }
1511
+ await this.loadMarkets();
1512
+ const market = this.market(symbol);
1513
+ let wallet = 'W001';
1514
+ [wallet, params] = this.handleOptionAndParams(params, 'fetchOpenOrders', 'wallet', wallet);
1515
+ const request = {
1516
+ 'symbol': market['id'],
1517
+ 'wallet': wallet,
1518
+ };
1519
+ let response = undefined;
1520
+ let trigger = false;
1521
+ [trigger, params] = this.handleOptionAndParams(params, 'fetchOpenOrders', 'trigger', trigger);
1522
+ if (!trigger) {
1523
+ //
1524
+ // {
1525
+ // "code": 200,
1526
+ // "message": "success",
1527
+ // "data": [
1528
+ // {
1529
+ // "wallet": "W001",
1530
+ // "symbol": "ETH-USDC",
1531
+ // "orderId": "7408896083240091648",
1532
+ // "clientOrderId": "7408896083240091648",
1533
+ // "price": "999",
1534
+ // "origQty": "1",
1535
+ // "avgPrice": "0",
1536
+ // "executedQty": "0",
1537
+ // "orderType": "LIMIT",
1538
+ // "side": "BUY",
1539
+ // "status": "NEW",
1540
+ // "stopPrice": null,
1541
+ // "activatePrice": null,
1542
+ // "timeInForce": null,
1543
+ // "workingType": "CONTRACT_PRICE",
1544
+ // "positionSide": "BOTH",
1545
+ // "priceProtect": false,
1546
+ // "reduceOnly": false,
1547
+ // "closePosition": false,
1548
+ // "createTime": "1766418476877",
1549
+ // "updateTime": "1766418476880"
1550
+ // }
1551
+ // ],
1552
+ // "success": true
1553
+ // }
1554
+ //
1555
+ response = await this.privateGetV1SwapTradeOpenOrder(this.extend(request, params));
1556
+ }
1557
+ else {
1558
+ response = await this.privateGetV1SwapTradePlanOrder(this.extend(request, params));
1559
+ }
1560
+ const data = this.safeList(response, 'data', []);
1561
+ return this.parseOrders(data, market, since, limit);
1562
+ }
1563
+ /**
1564
+ * @method
1565
+ * @name bydfi#fetchOpenOrder
1566
+ * @description fetch an open order by the id
1567
+ * @see https://developers.bydfi.com/en/swap/trade#pending-order-query
1568
+ * @see https://developers.bydfi.com/en/swap/trade#planned-order-query
1569
+ * @param {string} id order id (mandatory if params.clientOrderId is not provided)
1570
+ * @param {string} symbol unified market symbol
1571
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1572
+ * @param {bool} [params.trigger] true or false, whether to fetch conditional orders only
1573
+ * @param {string} [params.clientOrderId] a unique identifier for the order (could be alternative to id)
1574
+ * @param {string} [params.wallet] The unique code of a sub-wallet. W001 is the default wallet and the main wallet code of the contract
1575
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/?id=order-structure}
1576
+ */
1577
+ async fetchOpenOrder(id, symbol = undefined, params = {}) {
1578
+ if (symbol === undefined) {
1579
+ throw new ArgumentsRequired(this.id + ' fetchOpenOrder() requires a symbol argument');
1580
+ }
1581
+ await this.loadMarkets();
1582
+ const market = this.market(symbol);
1583
+ const request = {
1584
+ 'symbol': market['id'],
1585
+ };
1586
+ const clientOrderId = this.safeString(params, 'clientOrderId');
1587
+ if ((id === undefined) && (clientOrderId === undefined)) {
1588
+ throw new ArgumentsRequired(this.id + ' fetchOpenOrder() requires an id argument or a clientOrderId parameter');
1589
+ }
1590
+ else if (id !== undefined) {
1591
+ request['orderId'] = id;
1592
+ }
1593
+ let wallet = 'W001';
1594
+ [wallet, params] = this.handleOptionAndParams(params, 'fetchOpenOrder', 'wallet', wallet);
1595
+ request['wallet'] = wallet;
1596
+ let response = undefined;
1597
+ let trigger = false;
1598
+ [trigger, params] = this.handleOptionAndParams(params, 'fetchOpenOrder', 'trigger', trigger);
1599
+ if (!trigger) {
1600
+ response = await this.privateGetV1SwapTradeOpenOrder(this.extend(request, params));
1601
+ }
1602
+ else {
1603
+ response = await this.privateGetV1SwapTradePlanOrder(this.extend(request, params));
1604
+ }
1605
+ const data = this.safeList(response, 'data', []);
1606
+ const order = this.safeDict(data, 0, {});
1607
+ return this.parseOrder(order, market);
1608
+ }
1609
+ /**
1610
+ * @method
1611
+ * @name bydfi#fetchCanceledAndClosedOrders
1612
+ * @description fetches information on multiple canceled and closed orders made by the user
1613
+ * @see https://developers.bydfi.com/en/swap/trade#historical-orders-query
1614
+ * @param {string} symbol unified market symbol of the closed orders
1615
+ * @param {int} [since] timestamp in ms of the earliest order
1616
+ * @param {int} [limit] the max number of closed orders to return
1617
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1618
+ * @param {int} [params.until] timestamp in ms of the latest order
1619
+ * @param {string} [params.contractType] FUTURE or DELIVERY, default is FUTURE
1620
+ * @param {string} [params.wallet] The unique code of a sub-wallet
1621
+ * @param {string} [params.orderType] order type ('LIMIT', 'MARKET', 'LIQ', 'LIMIT_CLOSE', 'MARKET_CLOSE', 'STOP', 'TAKE_PROFIT', 'STOP_MARKET', 'TAKE_PROFIT_MARKET' or 'TRAILING_STOP_MARKET')
1622
+ * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/?id=order-structure}
1623
+ */
1624
+ async fetchCanceledAndClosedOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1625
+ await this.loadMarkets();
1626
+ const paginate = this.safeBool(params, 'paginate', false);
1627
+ if (paginate) {
1628
+ const maxLimit = 500;
1629
+ params = this.omit(params, 'paginate');
1630
+ params = this.extend(params, { 'paginationDirection': 'backward' });
1631
+ const paginatedResponse = await this.fetchPaginatedCallDynamic('fetchCanceledAndClosedOrders', symbol, since, limit, params, maxLimit, true);
1632
+ return this.sortBy(paginatedResponse, 'timestamp');
1633
+ }
1634
+ let contractType = 'FUTURE';
1635
+ [contractType, params] = this.handleOptionAndParams(params, 'fetchCanceledAndClosedOrders', 'contractType', contractType);
1636
+ const request = {
1637
+ 'contractType': contractType,
1638
+ };
1639
+ let market = undefined;
1640
+ if (symbol !== undefined) {
1641
+ market = this.market(symbol);
1642
+ request['symbol'] = market['id'];
1643
+ }
1644
+ params = this.handleSinceAndUntil('fetchCanceledAndClosedOrders', since, params);
1645
+ if (limit !== undefined) {
1646
+ request['limit'] = limit;
1647
+ }
1648
+ const response = await this.privateGetV1SwapTradeHistoryOrder(this.extend(request, params));
1649
+ //
1650
+ // {
1651
+ // "code": 200,
1652
+ // "message": "success",
1653
+ // "data": [
1654
+ // {
1655
+ // "orderId": "7408919189505597440",
1656
+ // "orderType": "MARKET",
1657
+ // "symbol": "ETH-USDC",
1658
+ // "origQty": "1",
1659
+ // "side": "BUY",
1660
+ // "positionSide": "BOTH",
1661
+ // "positionAvgPrice": null,
1662
+ // "positionVolume": null,
1663
+ // "positionType": null,
1664
+ // "reduceOnly": false,
1665
+ // "closePosition": false,
1666
+ // "action": null,
1667
+ // "price": "3032.45",
1668
+ // "avgPrice": "3032.45",
1669
+ // "brkPrice": null,
1670
+ // "dealVolume": null,
1671
+ // "status": "2",
1672
+ // "wallet": "W001",
1673
+ // "alias": null,
1674
+ // "contractId": null,
1675
+ // "mtime": "1766423985842",
1676
+ // "ctime": "1766423985840",
1677
+ // "fixedPrice": null,
1678
+ // "direction": null,
1679
+ // "triggerPrice": null,
1680
+ // "priceType": null,
1681
+ // "basePrecision": "8",
1682
+ // "baseShowPrecision": "2",
1683
+ // "strategyType": null,
1684
+ // "leverageLevel": 1,
1685
+ // "marginType": "CROSS",
1686
+ // "remark": null,
1687
+ // "callbackRate": null,
1688
+ // "activationPrice": null
1689
+ // }
1690
+ // ],
1691
+ // "success": true
1692
+ // }
1693
+ //
1694
+ const data = this.safeList(response, 'data', []);
1695
+ return this.parseOrders(data, market, since, limit);
1696
+ }
1697
+ handleSinceAndUntil(methodName, since = undefined, params = {}) {
1698
+ let until = undefined;
1699
+ [until, params] = this.handleOptionAndParams2(params, methodName, 'until', 'endTime');
1700
+ const now = this.milliseconds();
1701
+ const sevenDays = 7 * 24 * 60 * 60 * 1000; // the maximum range is 7 days
1702
+ let startTime = since;
1703
+ if (startTime === undefined) {
1704
+ if (until === undefined) {
1705
+ // both since and until are undefined
1706
+ startTime = now - sevenDays;
1707
+ until = now;
1708
+ }
1709
+ else {
1710
+ // since is undefined but until is defined
1711
+ startTime = until - sevenDays;
1712
+ }
1713
+ }
1714
+ else if (until === undefined) {
1715
+ // until is undefined but since is defined
1716
+ const delta = now - startTime;
1717
+ if (delta > sevenDays) {
1718
+ until = startTime + sevenDays;
1719
+ }
1720
+ else {
1721
+ until = now;
1722
+ }
1723
+ }
1724
+ const request = {
1725
+ 'startTime': startTime,
1726
+ 'endTime': until,
1727
+ };
1728
+ return this.extend(request, params);
1729
+ }
1730
+ parseOrder(order, market = undefined) {
1731
+ //
1732
+ // createOrder, fetchOpenOrders, fetchOpenOrder
1733
+ // {
1734
+ // "wallet": "W001",
1735
+ // "symbol": "ETH-USDT",
1736
+ // "orderId": "7408875768086683648",
1737
+ // "clientOrderId": "7408875768086683648",
1738
+ // "price": "1000",
1739
+ // "origQty": "10",
1740
+ // "avgPrice": "0",
1741
+ // "executedQty": "0",
1742
+ // "orderType": "LIMIT",
1743
+ // "side": "BUY",
1744
+ // "status": "CANCELED",
1745
+ // "stopPrice": null,
1746
+ // "activatePrice": null,
1747
+ // "timeInForce": null,
1748
+ // "workingType": "CONTRACT_PRICE",
1749
+ // "positionSide": "BOTH",
1750
+ // "priceProtect": false,
1751
+ // "reduceOnly": false,
1752
+ // "closePosition": false,
1753
+ // "createTime": "1766413633367",
1754
+ // "updateTime": "1766413633370"
1755
+ // }
1756
+ //
1757
+ // fetchCanceledAndClosedOrders
1758
+ // {
1759
+ // "orderId": "7408919189505597440",
1760
+ // "orderType": "MARKET",
1761
+ // "symbol": "ETH-USDC",
1762
+ // "origQty": "1",
1763
+ // "side": "BUY",
1764
+ // "positionSide": "BOTH",
1765
+ // "positionAvgPrice": null,
1766
+ // "positionVolume": null,
1767
+ // "positionType": null,
1768
+ // "reduceOnly": false,
1769
+ // "closePosition": false,
1770
+ // "action": null,
1771
+ // "price": "3032.45",
1772
+ // "avgPrice": "3032.45",
1773
+ // "brkPrice": null,
1774
+ // "dealVolume": null,
1775
+ // "status": "2",
1776
+ // "wallet": "W001",
1777
+ // "alias": null,
1778
+ // "contractId": null,
1779
+ // "mtime": "1766423985842",
1780
+ // "ctime": "1766423985840",
1781
+ // "fixedPrice": null,
1782
+ // "direction": null,
1783
+ // "triggerPrice": null,
1784
+ // "priceType": null,
1785
+ // "basePrecision": "8",
1786
+ // "baseShowPrecision": "2",
1787
+ // "strategyType": null,
1788
+ // "leverageLevel": 1,
1789
+ // "marginType": "CROSS",
1790
+ // "remark": null,
1791
+ // "callbackRate": null,
1792
+ // "activationPrice": null
1793
+ // }
1794
+ //
1795
+ const marketId = this.safeString(order, 'symbol');
1796
+ market = this.safeMarket(marketId, market);
1797
+ const timestamp = this.safeInteger2(order, 'createTime', 'ctime');
1798
+ const rawType = this.safeString(order, 'orderType');
1799
+ const stopPrice = this.safeStringN(order, ['stopPrice', 'activatePrice', 'triggerPrice']);
1800
+ const isStopLossOrder = (rawType === 'STOP') || (rawType === 'STOP_MARKET') || (rawType === 'TRAILING_STOP_MARKET');
1801
+ const isTakeProfitOrder = (rawType === 'TAKE_PROFIT') || (rawType === 'TAKE_PROFIT_MARKET');
1802
+ const rawTimeInForce = this.safeString(order, 'timeInForce');
1803
+ const timeInForce = this.parseOrderTimeInForce(rawTimeInForce);
1804
+ let postOnly = undefined;
1805
+ if (timeInForce === 'PO') {
1806
+ postOnly = true;
1807
+ }
1808
+ const rawStatus = this.safeString(order, 'status');
1809
+ const fee = {};
1810
+ const quoteFee = this.safeNumber(order, 'quoteFee');
1811
+ if (quoteFee !== undefined) {
1812
+ fee['cost'] = quoteFee;
1813
+ fee['currency'] = market['quote'];
1814
+ }
1815
+ return this.safeOrder({
1816
+ 'info': order,
1817
+ 'id': this.safeString(order, 'orderId'),
1818
+ 'clientOrderId': this.safeString(order, 'clientOrderId'),
1819
+ 'timestamp': timestamp,
1820
+ 'datetime': this.iso8601(timestamp),
1821
+ 'lastTradeTimestamp': undefined,
1822
+ 'lastUpdateTimestamp': this.safeInteger2(order, 'updateTime', 'mtime'),
1823
+ 'status': this.parseOrderStatus(rawStatus),
1824
+ 'symbol': market['symbol'],
1825
+ 'type': this.parseOrderType(rawType),
1826
+ 'timeInForce': timeInForce,
1827
+ 'postOnly': postOnly,
1828
+ 'reduceOnly': this.safeBool(order, 'reduceOnly'),
1829
+ 'side': this.safeStringLower(order, 'side'),
1830
+ 'price': this.safeString(order, 'price'),
1831
+ 'triggerPrice': stopPrice,
1832
+ 'stopLossPrice': isStopLossOrder ? stopPrice : undefined,
1833
+ 'takeProfitPrice': isTakeProfitOrder ? stopPrice : undefined,
1834
+ 'amount': this.safeString(order, 'origQty'),
1835
+ 'filled': this.safeString(order, 'executedQty'),
1836
+ 'remaining': undefined,
1837
+ 'cost': undefined,
1838
+ 'trades': undefined,
1839
+ 'fee': fee,
1840
+ 'average': this.omitZero(this.safeString(order, 'avgPrice')),
1841
+ }, market);
1842
+ }
1843
+ parseOrderType(type) {
1844
+ const types = {
1845
+ 'LIMIT': 'limit',
1846
+ 'MARKET': 'market',
1847
+ 'STOP': 'limit',
1848
+ 'STOP_MARKET': 'market',
1849
+ 'TAKE_PROFIT': 'limit',
1850
+ 'TAKE_PROFIT_MARKET': 'market',
1851
+ 'TRAILING_STOP_MARKET': 'market',
1852
+ };
1853
+ return this.safeString(types, type, type);
1854
+ }
1855
+ parseOrderTimeInForce(timeInForce) {
1856
+ const timeInForces = {
1857
+ 'GTC': 'GTC',
1858
+ 'FOK': 'FOK',
1859
+ 'IOC': 'IOC',
1860
+ 'POST_ONLY': 'PO',
1861
+ 'TRAILING_STOP': 'IOC',
1862
+ };
1863
+ return this.safeString(timeInForces, timeInForce, timeInForce);
1864
+ }
1865
+ parseOrderStatus(status) {
1866
+ const statuses = {
1867
+ 'NEW': 'open',
1868
+ 'PARTIALLY_FILLED': 'open',
1869
+ 'FILLED': 'closed',
1870
+ 'EXPIRED': 'canceled',
1871
+ 'PART_FILLED_CANCELLED': 'canceled',
1872
+ 'CANCELED': 'canceled',
1873
+ '2': 'closed',
1874
+ '4': 'canceled',
1875
+ };
1876
+ return this.safeString(statuses, status, status);
1877
+ }
1878
+ /**
1879
+ * @method
1880
+ * @name bydfi#setLeverage
1881
+ * @description set the level of leverage for a market
1882
+ * @see https://developers.bydfi.com/en/swap/trade#set-leverage-for-single-trading-pair
1883
+ * @param {float} leverage the rate of leverage
1884
+ * @param {string} symbol unified market symbol
1885
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1886
+ * @param {string} [params.wallet] The unique code of a sub-wallet. W001 is the default wallet and the main wallet code of the contract
1887
+ * @returns {object} response from the exchange
1888
+ */
1889
+ async setLeverage(leverage, symbol = undefined, params = {}) {
1890
+ if (symbol === undefined) {
1891
+ throw new ArgumentsRequired(this.id + ' setLeverage() requires a symbol argument');
1892
+ }
1893
+ await this.loadMarkets();
1894
+ const market = this.market(symbol);
1895
+ let wallet = 'W001';
1896
+ [wallet, params] = this.handleOptionAndParams(params, 'setLeverage', 'wallet', wallet);
1897
+ const request = {
1898
+ 'symbol': market['id'],
1899
+ 'leverage': leverage,
1900
+ 'wallet': wallet,
1901
+ };
1902
+ const response = await this.privatePostV1SwapTradeLeverage(this.extend(request, params));
1903
+ const data = this.safeDict(response, 'data', {});
1904
+ return data;
1905
+ }
1906
+ /**
1907
+ * @method
1908
+ * @name bydfi#fetchLeverage
1909
+ * @description fetch the set leverage for a market
1910
+ * @see https://developers.bydfi.com/en/swap/trade#get-leverage-for-single-trading-pair
1911
+ * @param {string} symbol unified market symbol
1912
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1913
+ * @param {string} [params.wallet] The unique code of a sub-wallet. W001 is the default wallet and the main wallet code of the contract
1914
+ * @returns {object} a [leverage structure]{@link https://docs.ccxt.com/?id=leverage-structure}
1915
+ */
1916
+ async fetchLeverage(symbol, params = {}) {
1917
+ if (symbol === undefined) {
1918
+ throw new ArgumentsRequired(this.id + ' fetchLeverage() requires a symbol argument');
1919
+ }
1920
+ await this.loadMarkets();
1921
+ const market = this.market(symbol);
1922
+ let wallet = 'W001';
1923
+ [wallet, params] = this.handleOptionAndParams(params, 'fetchLeverage', 'wallet', wallet);
1924
+ const request = {
1925
+ 'symbol': market['id'],
1926
+ 'wallet': wallet,
1927
+ };
1928
+ const response = await this.privateGetV1SwapTradeLeverage(this.extend(request, params));
1929
+ //
1930
+ // {
1931
+ // "code": 200,
1932
+ // "message": "success",
1933
+ // "data": {
1934
+ // "symbol": "ETH-USDC",
1935
+ // "leverage": 1,
1936
+ // "maxNotionalValue": "100000000"
1937
+ // },
1938
+ // "success": true
1939
+ // }
1940
+ //
1941
+ const data = this.safeDict(response, 'data', {});
1942
+ return this.parseLeverage(data, market);
1943
+ }
1944
+ parseLeverage(leverage, market = undefined) {
1945
+ const marketId = this.safeString(leverage, 'symbol');
1946
+ return {
1947
+ 'info': leverage,
1948
+ 'symbol': this.safeSymbol(marketId, market),
1949
+ 'marginMode': undefined,
1950
+ 'longLeverage': this.safeInteger(leverage, 'leverage'),
1951
+ 'shortLeverage': this.safeInteger(leverage, 'leverage'),
1952
+ };
1953
+ }
1954
+ /**
1955
+ * @method
1956
+ * @name bydfi#fetchPositions
1957
+ * @description fetch all open positions
1958
+ * @see https://developers.bydfi.com/en/swap/trade#positions-query
1959
+ * @param {string[]} [symbols] list of unified market symbols
1960
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1961
+ * @param {string} [params.contractType] FUTURE or DELIVERY, default is FUTURE
1962
+ * @param {string} [params.settleCoin] the settlement currency (USDT or USDC or USD)
1963
+ * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/?id=position-structure}
1964
+ */
1965
+ async fetchPositions(symbols = undefined, params = {}) {
1966
+ await this.loadMarkets();
1967
+ let contractType = 'FUTURE';
1968
+ [contractType, params] = this.handleOptionAndParams(params, 'fetchPositions', 'contractType', contractType);
1969
+ const request = {
1970
+ 'contractType': contractType,
1971
+ };
1972
+ const response = await this.privateGetV1SwapTradePositions(this.extend(request, params));
1973
+ //
1974
+ // {
1975
+ // "code": 200,
1976
+ // "message": "success",
1977
+ // "data": [
1978
+ // {
1979
+ // "symbol": "ETH-USDC",
1980
+ // "side": "BUY",
1981
+ // "volume": "0.001",
1982
+ // "avgPrice": "3032.45",
1983
+ // "liqPrice": "0",
1984
+ // "markPrice": "3032.37",
1985
+ // "unPnl": "-0.00008",
1986
+ // "positionMargin": "0",
1987
+ // "settleCoin": "USDC",
1988
+ // "im": "3.03245",
1989
+ // "mm": "0.007581125"
1990
+ // }
1991
+ // ],
1992
+ // "success": true
1993
+ // }
1994
+ //
1995
+ const data = this.safeList(response, 'data', []);
1996
+ return this.parsePositions(data, symbols);
1997
+ }
1998
+ /**
1999
+ * @method
2000
+ * @name bydfi#fetchPositionsForSymbol
2001
+ * @description fetch open positions for a single market
2002
+ * @see https://developers.bydfi.com/en/swap/trade#positions-query
2003
+ * @description fetch all open positions for specific symbol
2004
+ * @param {string} symbol unified market symbol
2005
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2006
+ * @param {string} [params.contractType] FUTURE or DELIVERY, default is FUTURE
2007
+ * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/?id=position-structure}
2008
+ */
2009
+ async fetchPositionsForSymbol(symbol, params = {}) {
2010
+ await this.loadMarkets();
2011
+ const market = this.market(symbol);
2012
+ let contractType = 'FUTURE';
2013
+ [contractType, params] = this.handleOptionAndParams(params, 'fetchPositions', 'contractType', contractType);
2014
+ const request = {
2015
+ 'contractType': contractType,
2016
+ 'symbol': market['id'],
2017
+ };
2018
+ const response = await this.privateGetV1SwapTradePositions(this.extend(request, params));
2019
+ const data = this.safeList(response, 'data', []);
2020
+ return this.parsePositions(data, [market['symbol']]);
2021
+ }
2022
+ parsePosition(position, market = undefined) {
2023
+ //
2024
+ // fetchPositions, fetchPositionsForSymbol
2025
+ // {
2026
+ // "symbol": "ETH-USDC",
2027
+ // "side": "BUY",
2028
+ // "volume": "0.001",
2029
+ // "avgPrice": "3032.45",
2030
+ // "liqPrice": "0",
2031
+ // "markPrice": "3032.37",
2032
+ // "unPnl": "-0.00008",
2033
+ // "positionMargin": "0",
2034
+ // "settleCoin": "USDC",
2035
+ // "im": "3.03245",
2036
+ // "mm": "0.007581125"
2037
+ // }
2038
+ //
2039
+ // fetchPositionsHistory
2040
+ // {
2041
+ // "id": "16788366",
2042
+ // "wallet": "W001",
2043
+ // "currency": "USDC",
2044
+ // "symbol": "ETH-USDC",
2045
+ // "side": "BUY",
2046
+ // "positionSide": "BOTH",
2047
+ // "leverage": 1,
2048
+ // "avgOpenPositionPrice": "3032.45",
2049
+ // "openPositionVolume": "1",
2050
+ // "openCount": 1,
2051
+ // "highPrice": "3032.45",
2052
+ // "lowPrice": "2953.67",
2053
+ // "avgClosePositionPrice": "2953.67",
2054
+ // "closePositionVolume": "1",
2055
+ // "closePositionCost": "2.95367",
2056
+ // "closeCount": 1,
2057
+ // "positionProfits": "-0.07878",
2058
+ // "lossBonus": "0",
2059
+ // "capitalFeeTotal": "-0.00026361",
2060
+ // "capitalFeeOutCash": "-0.00026361",
2061
+ // "capitalFeeInCash": "0",
2062
+ // "capitalFeeBonus": "0",
2063
+ // "openFeeTotal": "-0.00181947",
2064
+ // "openFeeBonus": "0",
2065
+ // "closeFeeTotal": "-0.00177221",
2066
+ // "closeFeeBonus": "0",
2067
+ // "liqLoss": "0",
2068
+ // "liqClosed": false,
2069
+ // "sequence": "53685341336",
2070
+ // "updateTime": "1766494929423",
2071
+ // "createTime": "1766423985842"
2072
+ // }
2073
+ //
2074
+ const marketId = this.safeString(position, 'symbol');
2075
+ market = this.safeMarket(marketId, market);
2076
+ const buyOrSell = this.safeString(position, 'side');
2077
+ const rawPositionSide = this.safeStringLower(position, 'positionSide');
2078
+ let positionSide = this.parsePositionSide(buyOrSell);
2079
+ let hedged = undefined;
2080
+ let isFetchPositionsHistory = false;
2081
+ if (rawPositionSide !== undefined) {
2082
+ isFetchPositionsHistory = true;
2083
+ if (rawPositionSide !== 'both') {
2084
+ positionSide = rawPositionSide;
2085
+ hedged = true;
2086
+ }
2087
+ else {
2088
+ hedged = false;
2089
+ }
2090
+ }
2091
+ const contractSize = this.safeString(market, 'contractSize');
2092
+ let contracts = this.safeString2(position, 'volume', 'openPositionVolume');
2093
+ if (!isFetchPositionsHistory) {
2094
+ // in fetchPositions, the 'volume' is in base currency units, need to convert to contracts
2095
+ contracts = Precise.stringDiv(contracts, contractSize);
2096
+ }
2097
+ const timestamp = this.safeInteger(position, 'createTime');
2098
+ return this.safePosition({
2099
+ 'info': position,
2100
+ 'id': this.safeString(position, 'id'),
2101
+ 'symbol': market['symbol'],
2102
+ 'entryPrice': this.parseNumber(this.safeString2(position, 'avgOpenPositionPrice', 'avgPrice')),
2103
+ 'markPrice': this.parseNumber(this.safeString(position, 'markPrice')),
2104
+ 'lastPrice': this.parseNumber(this.safeString(position, 'avgClosePositionPrice')),
2105
+ 'notional': this.parseNumber(this.safeString(position, 'closePositionCost')),
2106
+ 'collateral': undefined,
2107
+ 'unrealizedPnl': this.parseNumber(this.safeString(position, 'unPnl')),
2108
+ 'realizedPnl': this.parseNumber(this.safeString(position, 'positionProfits')),
2109
+ 'side': positionSide,
2110
+ 'contracts': this.parseNumber(contracts),
2111
+ 'contractSize': this.parseNumber(contractSize),
2112
+ 'timestamp': timestamp,
2113
+ 'datetime': this.iso8601(timestamp),
2114
+ 'lastUpdateTimestamp': this.safeInteger(position, 'updateTime'),
2115
+ 'hedged': hedged,
2116
+ 'maintenanceMargin': this.parseNumber(this.safeString(position, 'mm')),
2117
+ 'maintenanceMarginPercentage': undefined,
2118
+ 'initialMargin': this.parseNumber(this.safeString(position, 'im')),
2119
+ 'initialMarginPercentage': undefined,
2120
+ 'leverage': this.parseNumber(this.safeString(position, 'leverage')),
2121
+ 'liquidationPrice': this.parseNumber(this.safeString(position, 'liqPrice')),
2122
+ 'marginRatio': undefined,
2123
+ 'marginMode': undefined,
2124
+ 'percentage': undefined,
2125
+ });
2126
+ }
2127
+ parsePositionSide(side) {
2128
+ const sides = {
2129
+ 'BUY': 'long',
2130
+ 'SELL': 'short',
2131
+ };
2132
+ return this.safeString(sides, side, side);
2133
+ }
2134
+ /**
2135
+ * @method
2136
+ * @name bydfi#fetchPositionHistory
2137
+ * @description fetches historical positions
2138
+ * @see https://developers.bydfi.com/en/swap/trade#query-historical-position-profit-and-loss-records
2139
+ * @param {string} symbol a unified market symbol
2140
+ * @param {int} [since] timestamp in ms of the earliest position to fetch , params["until"] - since <= 7 days
2141
+ * @param {int} [limit] the maximum amount of records to fetch (default 500, max 500)
2142
+ * @param {object} params extra parameters specific to the exchange api endpoint
2143
+ * @param {int} [params.until] timestamp in ms of the latest position to fetch , params["until"] - since <= 7 days
2144
+ * @param {string} [params.contractType] FUTURE or DELIVERY, default is FUTURE
2145
+ * @param {string} [params.wallet] The unique code of a sub-wallet. W001 is the default wallet and the main wallet code of the contract
2146
+ * @returns {object[]} a list of [position structures]{@link https://docs.ccxt.com/?id=position-structure}
2147
+ */
2148
+ async fetchPositionHistory(symbol, since = undefined, limit = undefined, params = {}) {
2149
+ await this.loadMarkets();
2150
+ const market = this.market(symbol);
2151
+ let contractType = 'FUTURE';
2152
+ [contractType, params] = this.handleOptionAndParams(params, 'fetchPositionsHistory', 'contractType', contractType);
2153
+ const request = {
2154
+ 'symbol': market['id'],
2155
+ 'contractType': contractType,
2156
+ };
2157
+ params = this.handleSinceAndUntil('fetchPositionsHistory', since, params);
2158
+ if (limit !== undefined) {
2159
+ request['limit'] = limit;
2160
+ }
2161
+ const response = await this.privateGetV1SwapTradePositionHistory(this.extend(request, params));
2162
+ //
2163
+ //
2164
+ const data = this.safeList(response, 'data', []);
2165
+ const positions = this.parsePositions(data);
2166
+ return this.filterBySinceLimit(positions, since, limit);
2167
+ }
2168
+ /**
2169
+ * @method
2170
+ * @name bydfi#fetchPositionsHistory
2171
+ * @description fetches historical positions
2172
+ * @see https://developers.bydfi.com/en/swap/trade#query-historical-position-profit-and-loss-records
2173
+ * @param {string[]} symbols a list of unified market symbols
2174
+ * @param {int} [since] timestamp in ms of the earliest position to fetch , params["until"] - since <= 7 days
2175
+ * @param {int} [limit] the maximum amount of records to fetch (default 500, max 500)
2176
+ * @param {object} params extra parameters specific to the exchange api endpoint
2177
+ * @param {int} [params.until] timestamp in ms of the latest position to fetch , params["until"] - since <= 7 days
2178
+ * @param {string} [params.contractType] FUTURE or DELIVERY, default is FUTURE
2179
+ * @param {string} [params.wallet] The unique code of a sub-wallet. W001 is the default wallet and the main wallet code of the contract
2180
+ * @returns {object[]} a list of [position structures]{@link https://docs.ccxt.com/?id=position-structure}
2181
+ */
2182
+ async fetchPositionsHistory(symbols = undefined, since = undefined, limit = undefined, params = {}) {
2183
+ await this.loadMarkets();
2184
+ let contractType = 'FUTURE';
2185
+ [contractType, params] = this.handleOptionAndParams(params, 'fetchPositionsHistory', 'contractType', contractType);
2186
+ const request = {
2187
+ 'contractType': contractType,
2188
+ };
2189
+ params = this.handleSinceAndUntil('fetchPositionsHistory', since, params);
2190
+ if (limit !== undefined) {
2191
+ request['limit'] = limit;
2192
+ }
2193
+ const response = await this.privateGetV1SwapTradePositionHistory(this.extend(request, params));
2194
+ //
2195
+ // {
2196
+ // "code": 200,
2197
+ // "message": "success",
2198
+ // "data": [
2199
+ // {
2200
+ // "id": "16788366",
2201
+ // "wallet": "W001",
2202
+ // "currency": "USDC",
2203
+ // "symbol": "ETH-USDC",
2204
+ // "side": "BUY",
2205
+ // "positionSide": "BOTH",
2206
+ // "leverage": 1,
2207
+ // "avgOpenPositionPrice": "3032.45",
2208
+ // "openPositionVolume": "1",
2209
+ // "openCount": 1,
2210
+ // "highPrice": "3032.45",
2211
+ // "lowPrice": "2953.67",
2212
+ // "avgClosePositionPrice": "2953.67",
2213
+ // "closePositionVolume": "1",
2214
+ // "closePositionCost": "2.95367",
2215
+ // "closeCount": 1,
2216
+ // "positionProfits": "-0.07878",
2217
+ // "lossBonus": "0",
2218
+ // "capitalFeeTotal": "-0.00026361",
2219
+ // "capitalFeeOutCash": "-0.00026361",
2220
+ // "capitalFeeInCash": "0",
2221
+ // "capitalFeeBonus": "0",
2222
+ // "openFeeTotal": "-0.00181947",
2223
+ // "openFeeBonus": "0",
2224
+ // "closeFeeTotal": "-0.00177221",
2225
+ // "closeFeeBonus": "0",
2226
+ // "liqLoss": "0",
2227
+ // "liqClosed": false,
2228
+ // "sequence": "53685341336",
2229
+ // "updateTime": "1766494929423",
2230
+ // "createTime": "1766423985842"
2231
+ // }
2232
+ // ],
2233
+ // "success": true
2234
+ // }
2235
+ //
2236
+ const data = this.safeList(response, 'data', []);
2237
+ const positions = this.parsePositions(data, symbols);
2238
+ return this.filterBySinceLimit(positions, since, limit);
2239
+ }
2240
+ /**
2241
+ * @method
2242
+ * @name bydfi#fetchMarginMode
2243
+ * @description fetches the margin mode of a trading pair
2244
+ * @see https://developers.bydfi.com/en/swap/user#margin-mode-query
2245
+ * @param {string} symbol unified symbol of the market to fetch the margin mode for
2246
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2247
+ * @param {string} [params.contractType] FUTURE or DELIVERY, default is FUTURE
2248
+ * @param {string} [params.wallet] The unique code of a sub-wallet. W001 is the default wallet and the main wallet code of the contract
2249
+ * @returns {object} a [margin mode structure]{@link https://docs.ccxt.com/?id=margin-mode-structure}
2250
+ */
2251
+ async fetchMarginMode(symbol, params = {}) {
2252
+ await this.loadMarkets();
2253
+ const market = this.market(symbol);
2254
+ let contractType = 'FUTURE';
2255
+ [contractType, params] = this.handleOptionAndParams(params, 'fetchMarginMode', 'contractType', contractType);
2256
+ let wallet = 'W001';
2257
+ [wallet, params] = this.handleOptionAndParams(params, 'fetchMarginMode', 'wallet', wallet);
2258
+ const request = {
2259
+ 'contractType': contractType,
2260
+ 'symbol': market['id'],
2261
+ 'wallet': wallet,
2262
+ };
2263
+ const response = await this.privateGetV1SwapUserDataAssetsMargin(this.extend(request, params));
2264
+ //
2265
+ // {
2266
+ // "code": 200,
2267
+ // "message": "success",
2268
+ // "data": {
2269
+ // "wallet": "W001",
2270
+ // "symbol": "ETH-USDC",
2271
+ // "marginType": "CROSS"
2272
+ // },
2273
+ // "success": true
2274
+ // }
2275
+ //
2276
+ const data = this.safeDict(response, 'data', {});
2277
+ return this.parseMarginMode(data, market);
2278
+ }
2279
+ parseMarginMode(marginMode, market = undefined) {
2280
+ const marketId = this.safeString(marginMode, 'symbol');
2281
+ return {
2282
+ 'info': marginMode,
2283
+ 'symbol': this.safeSymbol(marketId, market),
2284
+ 'marginMode': this.safeStringLower(marginMode, 'marginType'),
2285
+ };
2286
+ }
2287
+ /**
2288
+ * @method
2289
+ * @name bydfi#setMarginMode
2290
+ * @description set margin mode to 'cross' or 'isolated'
2291
+ * @see https://developers.bydfi.com/en/swap/user#change-margin-type-cross-margin
2292
+ * @param {string} marginMode 'cross' or 'isolated'
2293
+ * @param {string} symbol unified market symbol
2294
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2295
+ * @param {string} [params.contractType] FUTURE or DELIVERY, default is FUTURE
2296
+ * @param {string} [params.wallet] The unique code of a sub-wallet. W001 is the default wallet and the main wallet code of the contract
2297
+ * @returns {object} response from the exchange
2298
+ */
2299
+ async setMarginMode(marginMode, symbol = undefined, params = {}) {
2300
+ if (symbol === undefined) {
2301
+ throw new ArgumentsRequired(this.id + ' setMarginMode() requires a symbol argument');
2302
+ }
2303
+ marginMode = marginMode.toLowerCase();
2304
+ if (marginMode !== 'isolated' && marginMode !== 'cross') {
2305
+ throw new BadRequest(this.id + ' setMarginMode() marginMode argument should be isolated or cross');
2306
+ }
2307
+ await this.loadMarkets();
2308
+ const market = this.market(symbol);
2309
+ let contractType = 'FUTURE';
2310
+ [contractType, params] = this.handleOptionAndParams(params, 'fetchMarginMode', 'contractType', contractType);
2311
+ let wallet = 'W001';
2312
+ [wallet, params] = this.handleOptionAndParams(params, 'fetchMarginMode', 'wallet', wallet);
2313
+ const request = {
2314
+ 'contractType': contractType,
2315
+ 'symbol': market['id'],
2316
+ 'marginType': marginMode.toUpperCase(),
2317
+ 'wallet': wallet,
2318
+ };
2319
+ return await this.privatePostV1SwapUserDataMarginType(this.extend(request, params));
2320
+ }
2321
+ /**
2322
+ * @method
2323
+ * @name bydfi#setPositionMode
2324
+ * @description set hedged to true or false for a market, hedged for bydfi is set identically for all markets with same settle currency
2325
+ * @see https://developers.bydfi.com/en/swap/user#change-position-mode-dual
2326
+ * @param {bool} hedged set to true to use dualSidePosition
2327
+ * @param {string} [symbol] not used by bydfi setPositionMode ()
2328
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2329
+ * @param {string} [params.contractType] FUTURE or DELIVERY, default is FUTURE
2330
+ * @param {string} [params.wallet] The unique code of a sub-wallet. W001 is the default wallet and the main wallet code of the contract
2331
+ * @param {string} [params.settleCoin] The settlement currency - USDT or USDC or USD (default is USDT)
2332
+ * @returns {object} response from the exchange
2333
+ */
2334
+ async setPositionMode(hedged, symbol = undefined, params = {}) {
2335
+ if (symbol !== undefined) {
2336
+ throw new NotSupported(this.id + ' setPositionMode() does not support a symbol argument. The position mode is set identically for all markets with same settle currency');
2337
+ }
2338
+ await this.loadMarkets();
2339
+ const positionType = hedged ? 'HEDGE' : 'ONEWAY';
2340
+ let wallet = 'W001';
2341
+ [wallet, params] = this.handleOptionAndParams(params, 'setPositionMode', 'wallet', wallet);
2342
+ let contractType = 'FUTURE';
2343
+ [contractType, params] = this.handleOptionAndParams(params, 'setPositionMode', 'contractType', contractType);
2344
+ let settleCoin = 'USDT';
2345
+ [settleCoin, params] = this.handleOptionAndParams(params, 'setPositionMode', 'settleCoin', settleCoin);
2346
+ const request = {
2347
+ 'contractType': contractType,
2348
+ 'wallet': wallet,
2349
+ 'positionType': positionType,
2350
+ 'settleCoin': settleCoin,
2351
+ };
2352
+ //
2353
+ // {
2354
+ // "code": 200,
2355
+ // "message": "success",
2356
+ // "success": true
2357
+ // }
2358
+ //
2359
+ return await this.privatePostV1SwapUserDataPositionSideDual(this.extend(request, params));
2360
+ }
2361
+ /**
2362
+ * @method
2363
+ * @name bydfi#fetchPositionMode
2364
+ * @description fetchs the position mode, hedged or one way, hedged for bydfi is set identically for all markets with same settle currency
2365
+ * @see https://developers.bydfi.com/en/swap/user#get-position-mode
2366
+ * @param {string} [symbol] unified symbol of the market to fetch the order book for
2367
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2368
+ * @param {string} [params.contractType] FUTURE or DELIVERY, default is FUTURE
2369
+ * @param {string} [params.wallet] The unique code of a sub-wallet. W001 is the default wallet and the main wallet code of the contract
2370
+ * @param {string} [params.settleCoin] The settlement currency - USDT or USDC or USD (default is USDT or settle currency of the market if market is provided)
2371
+ * @returns {object} an object detailing whether the market is in hedged or one-way mode
2372
+ */
2373
+ async fetchPositionMode(symbol = undefined, params = {}) {
2374
+ await this.loadMarkets();
2375
+ let wallet = 'W001';
2376
+ [wallet, params] = this.handleOptionAndParams(params, 'fetchPositionMode', 'wallet', wallet);
2377
+ let contractType = 'FUTURE';
2378
+ [contractType, params] = this.handleOptionAndParams(params, 'fetchPositionMode', 'contractType', contractType);
2379
+ let settleCoin = 'USDT';
2380
+ if (symbol === undefined) {
2381
+ [settleCoin, params] = this.handleOptionAndParams(params, 'fetchPositionMode', 'settleCoin', settleCoin);
2382
+ }
2383
+ else {
2384
+ const market = this.market(symbol);
2385
+ settleCoin = market['settleId'];
2386
+ }
2387
+ const request = {
2388
+ 'contractType': contractType,
2389
+ 'settleCoin': settleCoin,
2390
+ 'wallet': wallet,
2391
+ };
2392
+ const response = await this.privateGetV1SwapUserDataPositionSideDual(this.extend(request, params));
2393
+ //
2394
+ // {
2395
+ // "code": 200,
2396
+ // "message": "success",
2397
+ // "data": {
2398
+ // "wallet": "W001",
2399
+ // "contractType": "FUTURE",
2400
+ // "settleCoin": "USDT",
2401
+ // "positionType": "HEDGE",
2402
+ // "unitModel": 2,
2403
+ // "pricingModel": "FLAG",
2404
+ // "priceProtection": "CLOSE",
2405
+ // "totalWallet": 2
2406
+ // },
2407
+ // "success": true
2408
+ // }
2409
+ //
2410
+ const data = this.safeDict(response, 'data', {});
2411
+ const hedged = this.safeString(data, 'positionType') === 'HEDGE';
2412
+ return {
2413
+ 'info': response,
2414
+ 'hedged': hedged,
2415
+ };
2416
+ }
2417
+ /**
2418
+ * @method
2419
+ * @name bydfi#fetchBalance
2420
+ * @description query for balance and get the amount of funds available for trading or funds locked in orders
2421
+ * @see https://developers.bydfi.com/en/account#asset-inquiry
2422
+ * @see https://developers.bydfi.com/en/swap/user#asset-query
2423
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2424
+ * @param {string} [params.accountType] the type of account to fetch the balance for, either 'spot' or 'swap' or 'funding' (default is 'spot')
2425
+ * @param {string} [params.wallet] *swap only* The unique code of a sub-wallet. W001 is the default wallet and the main wallet code of the contract
2426
+ * @param {string} [params.asset] currency id for the balance to fetch
2427
+ * @returns {object} a [balance structure]{@link https://docs.ccxt.com/?id=balance-structure}
2428
+ */
2429
+ async fetchBalance(params = {}) {
2430
+ await this.loadMarkets();
2431
+ let accountType = 'spot';
2432
+ [accountType, params] = this.handleOptionAndParams2(params, 'fetchBalance', 'accountType', 'type', accountType);
2433
+ const request = {};
2434
+ let response = undefined;
2435
+ if (accountType !== 'swap') {
2436
+ const options = this.safeDict(this.options, 'accountsByType', {});
2437
+ const parsedAccountType = this.safeString(options, accountType, accountType);
2438
+ request['walletType'] = parsedAccountType;
2439
+ //
2440
+ // {
2441
+ // "code": 200,
2442
+ // "message": "success",
2443
+ // "data": [
2444
+ // {
2445
+ // "walletType": "spot",
2446
+ // "asset": "USDC",
2447
+ // "total": "100",
2448
+ // "available": "100",
2449
+ // "frozen": "0"
2450
+ // }
2451
+ // ],
2452
+ // "success": true
2453
+ // }
2454
+ //
2455
+ response = await this.privateGetV1AccountAssets(this.extend(request, params));
2456
+ }
2457
+ else {
2458
+ let wallet = 'W001';
2459
+ [wallet, params] = this.handleOptionAndParams(params, 'fetchBalance', 'wallet', wallet);
2460
+ request['wallet'] = wallet;
2461
+ //
2462
+ // {
2463
+ // "code": 200,
2464
+ // "message": "success",
2465
+ // "data": [
2466
+ // {
2467
+ // "wallet": "W001",
2468
+ // "asset": "USDT",
2469
+ // "balance": "0",
2470
+ // "frozen": "0",
2471
+ // "positionMargin": "0",
2472
+ // "availableBalance": "0",
2473
+ // "canWithdrawAmount": "0",
2474
+ // "bonusAmount": "0"
2475
+ // },
2476
+ // {
2477
+ // "wallet": "W001",
2478
+ // "asset": "USDC",
2479
+ // "balance": "99.99505828",
2480
+ // "frozen": "4.0024",
2481
+ // "positionMargin": "2.95342",
2482
+ // "availableBalance": "92.96020828",
2483
+ // "canWithdrawAmount": "92.96020828",
2484
+ // "bonusAmount": "0"
2485
+ // }
2486
+ // ],
2487
+ // "success": true
2488
+ // }
2489
+ response = await this.privateGetV1SwapAccountBalance(this.extend(request, params));
2490
+ }
2491
+ const data = this.safeList(response, 'data', []);
2492
+ return this.parseBalance(data);
2493
+ }
2494
+ parseBalance(response) {
2495
+ const timestamp = this.milliseconds();
2496
+ const result = {
2497
+ 'info': response,
2498
+ 'timestamp': timestamp,
2499
+ 'datetime': this.iso8601(timestamp),
2500
+ };
2501
+ for (let i = 0; i < response.length; i++) {
2502
+ const balance = response[i];
2503
+ const symbol = this.safeString(balance, 'asset');
2504
+ const code = this.safeCurrencyCode(symbol);
2505
+ const account = this.account();
2506
+ account['total'] = this.safeString2(balance, 'total', 'balance');
2507
+ account['free'] = this.safeString2(balance, 'available', 'availableBalance');
2508
+ result[code] = account;
2509
+ }
2510
+ return this.safeBalance(result);
2511
+ }
2512
+ /**
2513
+ * @method
2514
+ * @name budfi#transfer
2515
+ * @description transfer currency internally between wallets on the same account
2516
+ * @see https://developers.bydfi.com/en/account#asset-transfer-between-accounts
2517
+ * @param {string} code unified currency code
2518
+ * @param {float} amount amount to transfer
2519
+ * @param {string} fromAccount 'spot', 'funding', or 'swap'
2520
+ * @param {string} toAccount 'spot', 'funding', or 'swap'
2521
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2522
+ * @returns {object} a [transfer structure]{@link https://docs.ccxt.com/?id=transfer-structure}
2523
+ */
2524
+ async transfer(code, amount, fromAccount, toAccount, params = {}) {
2525
+ await this.loadMarkets();
2526
+ const currency = this.currency(code);
2527
+ const accountsByType = this.safeDict(this.options, 'accountsByType', {});
2528
+ const fromId = this.safeString(accountsByType, fromAccount, fromAccount);
2529
+ const toId = this.safeString(accountsByType, toAccount, toAccount);
2530
+ const request = {
2531
+ 'asset': currency['id'],
2532
+ 'amount': this.currencyToPrecision(code, amount),
2533
+ 'fromType': fromId,
2534
+ 'toType': toId,
2535
+ };
2536
+ const response = await this.privatePostV1AccountTransfer(this.extend(request, params));
2537
+ //
2538
+ // {
2539
+ // "code": 200,
2540
+ // "message": "success",
2541
+ // "success": true
2542
+ // }
2543
+ //
2544
+ const transfer = this.parseTransfer(response, currency);
2545
+ const transferOptions = this.safeDict(this.options, 'transfer', {});
2546
+ const fillResponseFromRequest = this.safeBool(transferOptions, 'fillResponseFromRequest', true);
2547
+ if (fillResponseFromRequest) {
2548
+ const timestamp = this.milliseconds();
2549
+ transfer['timestamp'] = timestamp;
2550
+ transfer['datetime'] = this.iso8601(timestamp);
2551
+ transfer['currency'] = code;
2552
+ transfer['fromAccount'] = fromAccount;
2553
+ transfer['toAccount'] = toAccount;
2554
+ transfer['amount'] = amount;
2555
+ }
2556
+ return transfer;
2557
+ }
2558
+ /**
2559
+ * @method
2560
+ * @name bydfi#fetchTransfers
2561
+ * @description fetch a history of internal transfers made on an account
2562
+ * @see https://developers.bydfi.com/en/account#query-wallet-transfer-records
2563
+ * @param {string} code unified currency code of the currency transferred
2564
+ * @param {int} [since] the earliest time in ms to fetch transfers for
2565
+ * @param {int} [limit] the maximum number of transfers structures to retrieve (default 10)
2566
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2567
+ * @param {int} [params.until] the latest time in ms to fetch entries for
2568
+ * @returns {object[]} a list of [transfer structures]{@link https://docs.ccxt.com/?id=transfer-structure}
2569
+ */
2570
+ async fetchTransfers(code = undefined, since = undefined, limit = undefined, params = {}) {
2571
+ if (code === undefined) {
2572
+ throw new ArgumentsRequired(this.id + ' fetchTransfers() requires a code argument');
2573
+ }
2574
+ await this.loadMarkets();
2575
+ const currency = this.currency(code);
2576
+ const paginate = this.safeBool(params, 'paginate', false);
2577
+ if (paginate) {
2578
+ const maxLimit = 50;
2579
+ params = this.omit(params, 'paginate');
2580
+ params = this.extend(params, { 'paginationDirection': 'backward' });
2581
+ const paginatedResponse = await this.fetchPaginatedCallDynamic('fetchTransfers', currency['code'], since, limit, params, maxLimit, true);
2582
+ return this.sortBy(paginatedResponse, 'timestamp');
2583
+ }
2584
+ const request = {
2585
+ 'asset': currency['id'],
2586
+ };
2587
+ let until = undefined;
2588
+ [until, params] = this.handleOptionAndParams2(params, 'fetchTransfers', 'until', 'endTime');
2589
+ if (until === undefined) {
2590
+ until = this.milliseconds(); // exchange requires endTime
2591
+ }
2592
+ if (since === undefined) {
2593
+ since = 1; // exchange requires startTime but allows any value
2594
+ }
2595
+ request['startTime'] = since;
2596
+ request['endTime'] = until;
2597
+ if (limit !== undefined) {
2598
+ request['rows'] = limit;
2599
+ }
2600
+ const response = await this.privateGetV1AccountTransferRecords(this.extend(request, params));
2601
+ //
2602
+ // {
2603
+ // "code": 200,
2604
+ // "message": "success",
2605
+ // "data": [
2606
+ // {
2607
+ // "orderId": "1209991065294581760",
2608
+ // "txId": "6km5fRK83Gwdp43HA479DW1Colh2pKyS",
2609
+ // "sourceWallet": "SPOT",
2610
+ // "targetWallet": "SWAP",
2611
+ // "asset": "USDC",
2612
+ // "amount": "100",
2613
+ // "status": "SUCCESS",
2614
+ // "timestamp": 1766413950000
2615
+ // }
2616
+ // ],
2617
+ // "success": true
2618
+ // }
2619
+ //
2620
+ const data = this.safeList(response, 'data', []);
2621
+ return this.parseTransfers(data, currency, since, limit);
2622
+ }
2623
+ parseTransfer(transfer, currency = undefined) {
2624
+ //
2625
+ // transfer
2626
+ // {
2627
+ // "code": 200,
2628
+ // "message": "success",
2629
+ // "success": true
2630
+ // }
2631
+ //
2632
+ // fetchTransfers
2633
+ // {
2634
+ // "orderId": "1209991065294581760",
2635
+ // "txId": "6km5fRK83Gwdp43HA479DW1Colh2pKyS",
2636
+ // "sourceWallet": "SPOT",
2637
+ // "targetWallet": "SWAP",
2638
+ // "asset": "USDC",
2639
+ // "amount": "100",
2640
+ // "status": "SUCCESS",
2641
+ // "timestamp": 1766413950000
2642
+ // }
2643
+ //
2644
+ const status = this.safeStringUpper2(transfer, 'message', 'status');
2645
+ const accountsById = this.safeDict(this.options, 'accountsById', {});
2646
+ const fromId = this.safeStringUpper(transfer, 'sourceWallet');
2647
+ const toId = this.safeStringUpper(transfer, 'targetWallet');
2648
+ const fromAccount = this.safeString(accountsById, fromId, fromId);
2649
+ const toAccount = this.safeString(accountsById, toId, toId);
2650
+ const timestamp = this.safeInteger(transfer, 'timestamp');
2651
+ const currencyId = this.safeString(transfer, 'asset');
2652
+ return {
2653
+ 'info': transfer,
2654
+ 'id': this.safeString(transfer, 'txId'),
2655
+ 'timestamp': timestamp,
2656
+ 'datetime': this.iso8601(timestamp),
2657
+ 'currency': this.safeCurrencyCode(currencyId, currency),
2658
+ 'amount': this.safeNumber(transfer, 'amount'),
2659
+ 'fromAccount': fromAccount,
2660
+ 'toAccount': toAccount,
2661
+ 'status': this.paraseTransferStatus(status),
2662
+ };
2663
+ }
2664
+ paraseTransferStatus(status) {
2665
+ const statuses = {
2666
+ 'SUCCESS': 'ok',
2667
+ 'WAIT': 'pending',
2668
+ 'FAILED': 'failed',
2669
+ };
2670
+ return this.safeString(statuses, status, status);
2671
+ }
2672
+ /**
2673
+ * @method
2674
+ * @name bydfi#fetchDeposits
2675
+ * @description fetch all deposits made to an account
2676
+ * @see https://developers.bydfi.com/en/spot/account#query-deposit-records
2677
+ * @param {string} code unified currency code (mandatory)
2678
+ * @param {int} [since] the earliest time in ms to fetch deposits for
2679
+ * @param {int} [limit] the maximum number of deposits structures to retrieve
2680
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2681
+ * @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/?id=transaction-structure}
2682
+ */
2683
+ async fetchDeposits(code = undefined, since = undefined, limit = undefined, params = {}) {
2684
+ return await this.fetchTransactionsHelper('deposit', code, since, limit, params);
2685
+ }
2686
+ /**
2687
+ * @method
2688
+ * @name bydfi#fetchWithdrawals
2689
+ * @description fetch all withdrawals made from an account
2690
+ * @see https://developers.bydfi.com/en/spot/account#query-withdrawal-records
2691
+ * @param {string} code unified currency code (mandatory)
2692
+ * @param {int} [since] the earliest time in ms to fetch withdrawals for
2693
+ * @param {int} [limit] the maximum number of withdrawal structures to retrieve
2694
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2695
+ * @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/?id=transaction-structure}
2696
+ */
2697
+ async fetchWithdrawals(code = undefined, since = undefined, limit = undefined, params = {}) {
2698
+ return await this.fetchTransactionsHelper('withdrawal', code, since, limit, params);
2699
+ }
2700
+ async fetchTransactionsHelper(type, code, since, limit, params) {
2701
+ const methodName = (type === 'deposit') ? 'fetchDeposits' : 'fetchWithdrawals';
2702
+ if (code === undefined) {
2703
+ throw new ArgumentsRequired(this.id + ' ' + methodName + '() requires a code argument');
2704
+ }
2705
+ await this.loadMarkets();
2706
+ const currency = this.currency(code);
2707
+ const paginate = this.safeBool(params, 'paginate', false);
2708
+ if (paginate) {
2709
+ const maxLimit = 50;
2710
+ params = this.omit(params, 'paginate');
2711
+ params = this.extend(params, { 'paginationDirection': 'backward' });
2712
+ const paginatedResponse = await this.fetchPaginatedCallDynamic(methodName, currency['code'], since, limit, params, maxLimit, true);
2713
+ return this.sortBy(paginatedResponse, 'timestamp');
2714
+ }
2715
+ const request = {
2716
+ 'asset': currency['id'],
2717
+ };
2718
+ let until = undefined;
2719
+ [until, params] = this.handleOptionAndParams2(params, 'fetchTransfers', 'until', 'endTime');
2720
+ const now = this.milliseconds();
2721
+ const sevenDays = 7 * 24 * 60 * 60 * 1000; // the maximum range is 7 days
2722
+ let startTime = since;
2723
+ if (startTime === undefined) {
2724
+ if (until === undefined) {
2725
+ // both since and until are undefined
2726
+ startTime = now - sevenDays;
2727
+ until = now;
2728
+ }
2729
+ else {
2730
+ // since is undefined but until is defined
2731
+ startTime = until - sevenDays;
2732
+ }
2733
+ }
2734
+ else if (until === undefined) {
2735
+ // until is undefined but since is defined
2736
+ const delta = now - startTime;
2737
+ if (delta > sevenDays) {
2738
+ until = startTime + sevenDays;
2739
+ }
2740
+ else {
2741
+ until = now;
2742
+ }
2743
+ }
2744
+ request['startTime'] = startTime;
2745
+ request['endTime'] = until;
2746
+ if (limit !== undefined) {
2747
+ request['limit'] = limit;
2748
+ }
2749
+ let response = undefined;
2750
+ if (type === 'deposit') {
2751
+ //
2752
+ // {
2753
+ // "code": 200,
2754
+ // "message": "success",
2755
+ // "data": [
2756
+ // {
2757
+ // "orderId": "1208864446987255809",
2758
+ // "asset": "USDC",
2759
+ // "amount": "200",
2760
+ // "status": "SUCCESS",
2761
+ // "txId": "0xd059a82a55ffc737722bd23c1ef3db2884ce8525b72ff0b3c038b430ce0c8ca5",
2762
+ // "network": "ETH",
2763
+ // "address": "0x8346b46f6aa9843c09f79f1c170a37aca83c8fcd",
2764
+ // "addressTag": null,
2765
+ // "finishTime": 1766145475000,
2766
+ // "createTime": 1766145344000
2767
+ // }
2768
+ // ],
2769
+ // "success": true
2770
+ // }
2771
+ //
2772
+ response = await this.privateGetV1SpotDepositRecords(this.extend(request, params));
2773
+ }
2774
+ else {
2775
+ //
2776
+ // todo check after withdrawal
2777
+ //
2778
+ response = await this.privateGetV1SpotWithdrawRecords(this.extend(request, params));
2779
+ }
2780
+ const data = this.safeList(response, 'data', []);
2781
+ const transactionParams = {
2782
+ 'type': type,
2783
+ };
2784
+ params = this.extend(params, transactionParams);
2785
+ return this.parseTransactions(data, currency, since, limit, params);
2786
+ }
2787
+ parseTransaction(transaction, currency = undefined) {
2788
+ //
2789
+ // fetchDeposits
2790
+ // {
2791
+ // "orderId": "1208864446987255809",
2792
+ // "asset": "USDC",
2793
+ // "amount": "200",
2794
+ // "status": "SUCCESS",
2795
+ // "txId": "0xd059a82a55ffc737722bd23c1ef3db2884ce8525b72ff0b3c038b430ce0c8ca5",
2796
+ // "network": "ETH",
2797
+ // "address": "0x8346b46f6aa9843c09f79f1c170a37aca83c8fcd",
2798
+ // "addressTag": null,
2799
+ // "finishTime": 1766145475000,
2800
+ // "createTime": 1766145344000
2801
+ // }
2802
+ //
2803
+ const currencyId = this.safeString(transaction, 'asset');
2804
+ const code = this.safeCurrencyCode(currencyId, currency);
2805
+ const rawStatus = this.safeStringLower(transaction, 'status');
2806
+ const timestamp = this.safeInteger(transaction, 'createTime');
2807
+ let fee = undefined;
2808
+ const feeCost = this.safeNumber(transaction, 'fee');
2809
+ if (feeCost !== undefined) {
2810
+ fee = {
2811
+ 'cost': feeCost,
2812
+ 'currency': undefined,
2813
+ };
2814
+ }
2815
+ return {
2816
+ 'info': transaction,
2817
+ 'id': this.safeString(transaction, 'orderId'),
2818
+ 'txid': this.safeString(transaction, 'txId'),
2819
+ 'type': undefined,
2820
+ 'currency': code,
2821
+ 'network': this.networkIdToCode(this.safeString(transaction, 'network')),
2822
+ 'amount': this.safeNumber(transaction, 'amount'),
2823
+ 'status': this.parseTransactionStatus(rawStatus),
2824
+ 'timestamp': timestamp,
2825
+ 'datetime': this.iso8601(timestamp),
2826
+ 'address': this.safeString(transaction, 'address'),
2827
+ 'addressFrom': undefined,
2828
+ 'addressTo': undefined,
2829
+ 'tag': this.safeString(transaction, 'addressTag'),
2830
+ 'tagFrom': undefined,
2831
+ 'tagTo': undefined,
2832
+ 'updated': this.safeInteger(transaction, 'finishTime'),
2833
+ 'comment': undefined,
2834
+ 'fee': fee,
2835
+ 'internal': false,
2836
+ };
2837
+ }
2838
+ parseTransactionStatus(status) {
2839
+ const statuses = {
2840
+ 'success': 'ok',
2841
+ 'wait': 'pending',
2842
+ 'failed': 'failed',
2843
+ };
2844
+ return this.safeString(statuses, status, status);
2845
+ }
2846
+ sign(path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
2847
+ let url = this.urls['api'][api];
2848
+ let endpoint = '/' + path;
2849
+ let query = '';
2850
+ const sortedParams = this.keysort(params);
2851
+ if (method === 'GET') {
2852
+ query = this.urlencode(sortedParams);
2853
+ if (query.length !== 0) {
2854
+ endpoint += '?' + query;
2855
+ }
2856
+ }
2857
+ if (api === 'private') {
2858
+ this.checkRequiredCredentials();
2859
+ const timestamp = this.milliseconds().toString();
2860
+ if (method === 'GET') {
2861
+ const payload = this.apiKey + timestamp + query;
2862
+ const signature = this.hmac(this.encode(payload), this.encode(this.secret), sha256, 'hex');
2863
+ headers = {
2864
+ 'X-API-KEY': this.apiKey,
2865
+ 'X-API-TIMESTAMP': timestamp,
2866
+ 'X-API-SIGNATURE': signature,
2867
+ };
2868
+ }
2869
+ else {
2870
+ body = this.json(sortedParams);
2871
+ const payload = this.apiKey + timestamp + body;
2872
+ const signature = this.hmac(this.encode(payload), this.encode(this.secret), sha256, 'hex');
2873
+ headers = {
2874
+ 'Content-Type': 'application/json',
2875
+ 'X-API-KEY': this.apiKey,
2876
+ 'X-API-TIMESTAMP': timestamp,
2877
+ 'X-API-SIGNATURE': signature,
2878
+ };
2879
+ }
2880
+ }
2881
+ url += endpoint;
2882
+ return { 'url': url, 'method': method, 'body': body, 'headers': headers };
2883
+ }
2884
+ handleErrors(httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) {
2885
+ if (response === undefined) {
2886
+ return undefined; // fallback to default error handler
2887
+ }
2888
+ //
2889
+ // {
2890
+ // "code": 101107,
2891
+ // "message": "Requires transaction permissions"
2892
+ // }
2893
+ //
2894
+ const code = this.safeString(response, 'code');
2895
+ const message = this.safeString(response, 'message');
2896
+ if (code !== '200') {
2897
+ const feedback = this.id + ' ' + body;
2898
+ this.throwExactlyMatchedException(this.exceptions['exact'], message, feedback);
2899
+ this.throwBroadlyMatchedException(this.exceptions['broad'], message, feedback);
2900
+ this.throwExactlyMatchedException(this.exceptions['exact'], code, feedback);
2901
+ throw new ExchangeError(feedback); // unknown message
2902
+ }
2903
+ return undefined;
2904
+ }
2905
+ }