ccxt
Version:
1,146 lines (1,144 loc) • 134 kB
JavaScript
// ----------------------------------------------------------------------------
// PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
// https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
// EDIT THE CORRESPONDENT .ts FILE INSTEAD
// ---------------------------------------------------------------------------
import Exchange from './abstract/bydfi.js';
import { ArgumentsRequired, AuthenticationError, BadRequest, ExchangeError, InsufficientFunds, NotSupported, PermissionDenied, RateLimitExceeded } from '../ccxt.js';
import { Precise } from './base/Precise.js';
import { sha256 } from './static_dependencies/noble-hashes/sha256.js';
import { TICK_SIZE } from './base/functions/number.js';
// ---------------------------------------------------------------------------
/**
* @class bydfi
* @augments Exchange
*/
export default class bydfi extends Exchange {
describe() {
return this.deepExtend(super.describe(), {
'id': 'bydfi',
'name': 'BYDFi',
'countries': ['SG'],
'rateLimit': 50,
'version': 'v1',
'certified': false,
'pro': true,
'has': {
'CORS': undefined,
'spot': false,
'margin': false,
'swap': true,
'future': false,
'option': false,
'addMargin': false,
'borrowCrossMargin': false,
'borrowIsolatedMargin': false,
'borrowMargin': false,
'cancelAllOrders': true,
'cancelOrder': false,
'cancelOrders': false,
'cancelOrdersWithClientOrderId': false,
'cancelOrderWithClientOrderId': false,
'closeAllPositions': false,
'closePosition': false,
'createDepositAddress': false,
'createLimitBuyOrder': false,
'createLimitOrder': true,
'createLimitSellOrder': false,
'createMarketBuyOrder': false,
'createMarketBuyOrderWithCost': false,
'createMarketOrder': true,
'createMarketOrderWithCost': false,
'createMarketSellOrder': false,
'createMarketSellOrderWithCost': false,
'createOrder': true,
'createOrders': true,
'createOrderWithTakeProfitAndStopLoss': false,
'createPostOnlyOrder': true,
'createReduceOnlyOrder': true,
'createStopLimitOrder': true,
'createStopLossOrder': true,
'createStopMarketOrder': false,
'createStopOrder': false,
'createTakeProfitOrder': true,
'createTrailingAmountOrder': false,
'createTrailingPercentOrder': true,
'createTriggerOrder': false,
'deposit': false,
'editOrder': true,
'editOrders': true,
'editOrderWithClientOrderId': true,
'fetchAccounts': false,
'fetchBalance': true,
'fetchBidsAsks': false,
'fetchBorrowInterest': false,
'fetchBorrowRate': false,
'fetchBorrowRateHistories': false,
'fetchBorrowRateHistory': false,
'fetchBorrowRates': false,
'fetchBorrowRatesPerSymbol': false,
'fetchCanceledAndClosedOrders': true,
'fetchCanceledOrders': false,
'fetchClosedOrder': false,
'fetchClosedOrders': false,
'fetchConvertCurrencies': false,
'fetchConvertQuote': false,
'fetchConvertTrade': false,
'fetchConvertTradeHistory': false,
'fetchCrossBorrowRate': false,
'fetchCrossBorrowRates': false,
'fetchCurrencies': false,
'fetchDeposit': false,
'fetchDepositAddress': false,
'fetchDepositAddresses': false,
'fetchDepositAddressesByNetwork': false,
'fetchDeposits': true,
'fetchDepositsWithdrawals': false,
'fetchDepositWithdrawFee': false,
'fetchDepositWithdrawFees': false,
'fetchFundingHistory': false,
'fetchFundingInterval': false,
'fetchFundingIntervals': false,
'fetchFundingRate': true,
'fetchFundingRateHistory': true,
'fetchFundingRates': false,
'fetchGreeks': false,
'fetchIndexOHLCV': false,
'fetchIsolatedBorrowRate': false,
'fetchIsolatedBorrowRates': false,
'fetchIsolatedPositions': false,
'fetchL2OrderBook': true,
'fetchL3OrderBook': false,
'fetchLastPrices': false,
'fetchLedger': false,
'fetchLedgerEntry': false,
'fetchLeverage': true,
'fetchLeverages': false,
'fetchLeverageTiers': false,
'fetchLiquidations': false,
'fetchLongShortRatio': false,
'fetchLongShortRatioHistory': false,
'fetchMarginAdjustmentHistory': false,
'fetchMarginMode': true,
'fetchMarginModes': false,
'fetchMarketLeverageTiers': false,
'fetchMarkets': true,
'fetchMarkOHLCV': false,
'fetchMarkPrices': false,
'fetchMyLiquidations': false,
'fetchMySettlementHistory': false,
'fetchMyTrades': true,
'fetchOHLCV': true,
'fetchOpenInterest': false,
'fetchOpenInterestHistory': false,
'fetchOpenInterests': false,
'fetchOpenOrder': false,
'fetchOpenOrders': true,
'fetchOption': false,
'fetchOptionChain': false,
'fetchOrder': false,
'fetchOrderBook': true,
'fetchOrderBooks': false,
'fetchOrders': false,
'fetchOrdersByStatus': false,
'fetchOrderTrades': false,
'fetchOrderWithClientOrderId': false,
'fetchPosition': false,
'fetchPositionHistory': true,
'fetchPositionMode': true,
'fetchPositions': true,
'fetchPositionsForSymbol': true,
'fetchPositionsHistory': true,
'fetchPositionsRisk': false,
'fetchPremiumIndexOHLCV': false,
'fetchSettlementHistory': false,
'fetchStatus': false,
'fetchTicker': true,
'fetchTickers': true,
'fetchTime': false,
'fetchTrades': true,
'fetchTradingFee': false,
'fetchTradingFees': false,
'fetchTradingLimits': false,
'fetchTransactionFee': false,
'fetchTransactionFees': false,
'fetchTransactions': false,
'fetchTransfer': false,
'fetchTransfers': true,
'fetchUnderlyingAssets': false,
'fetchVolatilityHistory': false,
'fetchWithdrawAddresses': false,
'fetchWithdrawal': false,
'fetchWithdrawals': true,
'fetchWithdrawalWhitelist': false,
'reduceMargin': false,
'repayCrossMargin': false,
'repayIsolatedMargin': false,
'setLeverage': true,
'setMargin': false,
'setMarginMode': true,
'setPositionMode': true,
'signIn': false,
'transfer': true,
'watchMyLiquidationsForSymbols': false,
'withdraw': false,
'ws': true,
},
'urls': {
'logo': 'https://github.com/user-attachments/assets/bfffb73d-29bd-465d-b75b-98e210491769',
'api': {
'public': 'https://api.bydfi.com/api',
'private': 'https://api.bydfi.com/api',
},
'www': 'https://bydfi.com/',
'doc': 'https://developers.bydfi.com/en/',
'referral': 'https://partner.bydfi.com/j/DilWutCI',
},
'fees': {},
'api': {
'public': {
'get': {
'v1/public/api_limits': 1,
'v1/swap/market/exchange_info': 1,
'v1/swap/market/depth': 1,
'v1/swap/market/trades': 1,
'v1/swap/market/klines': 1,
'v1/swap/market/ticker/24hr': 1,
'v1/swap/market/ticker/price': 1,
'v1/swap/market/mark_price': 1,
'v1/swap/market/funding_rate': 1,
'v1/swap/market/funding_rate_history': 1,
'v1/swap/market/risk_limit': 1, // https://developers.bydfi.com/en/swap/market#risk-limit
},
},
'private': {
'get': {
'v1/account/assets': 1,
'v1/account/transfer_records': 1,
'v1/spot/deposit_records': 1,
'v1/spot/withdraw_records': 1,
'v1/swap/trade/open_order': 1,
'v1/swap/trade/plan_order': 1,
'v1/swap/trade/leverage': 1,
'v1/swap/trade/history_order': 1,
'v1/swap/trade/history_trade': 1,
'v1/swap/trade/position_history': 1,
'v1/swap/trade/positions': 1,
'v1/swap/account/balance': 1,
'v1/swap/user_data/assets_margin': 1,
'v1/swap/user_data/position_side/dual': 1,
'v1/agent/teams': 1,
'v1/agent/agent_links': 1,
'v1/agent/regular_overview': 1,
'v1/agent/agent_sub_overview': 1,
'v1/agent/partener_user_deposit': 1,
'v1/agent/partener_users_data': 1,
'v1/agent/affiliate_uids': 1,
'v1/agent/affiliate_commission': 1,
'v1/agent/internal_withdrawal_status': 1, // https://developers.bydfi.com/en/agent/#get-internal-withdrawal-status
},
'post': {
'v1/account/transfer': 1,
'v1/swap/trade/place_order': 1,
'v1/swap/trade/batch_place_order': 1,
'v1/swap/trade/edit_order': 1,
'v1/swap/trade/batch_edit_order': 1,
'v1/swap/trade/cancel_all_order': 1,
'v1/swap/trade/leverage': 1,
'v1/swap/trade/batch_leverage_margin': 1,
'v1/swap/user_data/margin_type': 1,
'v1/swap/user_data/position_side/dual': 1,
'v1/agent/internal_withdrawal': 1, // https://developers.bydfi.com/en/agent/#internal-withdrawal
},
},
},
'features': {
'spot': undefined,
'swap': {
'linear': {
'sandbox': false,
'createOrder': {
'marginMode': false,
'triggerPrice': false,
'triggerPriceType': {
'mark': true,
'last': true,
'index': false,
},
'stopLossPrice': true,
'takeProfitPrice': true,
'attachedStopLossTakeProfit': undefined,
'timeInForce': {
'IOC': true,
'FOK': true,
'PO': true,
'GTD': false,
},
'hedged': true,
'selfTradePrevention': false,
'trailing': true,
'iceberg': false,
'leverage': false,
'marketBuyRequiresPrice': false,
'marketBuyByCost': false,
},
'createOrders': {
'max': 5,
},
'fetchMyTrades': {
'marginMode': false,
'daysBack': 182,
'limit': 500,
'untilDays': 7,
'symbolRequired': false,
},
'fetchOrder': undefined,
'fetchOpenOrder': {
'marginMode': false,
'trigger': true,
'trailing': false,
'symbolRequired': true,
},
'fetchOpenOrders': {
'marginMode': false,
'limit': 500,
'trigger': true,
'trailing': false,
'symbolRequired': true,
},
'fetchOrders': undefined,
'fetchCanceledAndClosedOrders': {
'marginMode': false,
'limit': 500,
'daysBack': 182,
'untilDays': 7,
'trigger': false,
'trailing': false,
'symbolRequired': false,
},
'fetchClosedOrders': undefined,
'fetchOHLCV': {
'limit': 500,
},
},
'inverse': undefined,
},
'future': {
'linear': undefined,
'inverse': undefined,
},
},
'timeframes': {
'1m': '1m',
'3m': '3m',
'5m': '5m',
'15m': '15m',
'30m': '30m',
'1h': '1h',
'2h': '2h',
'4h': '4h',
'6h': '6h',
'12h': '12h',
'1d': '1d',
},
'precisionMode': TICK_SIZE,
'exceptions': {
'exact': {
'101001': AuthenticationError,
'101103': AuthenticationError,
'102001': BadRequest,
'102002': PermissionDenied,
'401': AuthenticationError,
'500': ExchangeError,
'501': ExchangeError,
'506': ExchangeError,
'510': RateLimitExceeded,
'511': AuthenticationError,
'513': BadRequest,
'514': BadRequest,
'600': BadRequest,
'Position does not exist': BadRequest,
'Requires transaction permissions': PermissionDenied,
'Service error': ExchangeError,
'transfer failed': InsufficientFunds, // {"code":500,"message":"transfer failed","success":false}
},
'broad': {
'is missing': ArgumentsRequired, // {"code":600,"message":"The parameter 'startTime' is missing"}
},
},
'commonCurrencies': {},
'options': {
'networks': {
'ERC20': 'ETH', // todo add more networks
},
'timeInForce': {
'GTC': 'GTC',
'FOK': 'FOK',
'IOC': 'IOC',
'PO': 'POST_ONLY', // Post Only
},
'accountsByType': {
'spot': 'SPOT',
'swap': 'SWAP',
'funding': 'FUND',
},
'accountsById': {
'SPOT': 'spot',
'SWAP': 'swap',
'FUND': 'funding',
},
},
});
}
/**
* @method
* @name bydfi#fetchMarkets
* @description retrieves data on all markets for bydfi
* @see https://developers.bydfi.com/en/swap/market#fetching-trading-rules-and-pairs
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object[]} an array of objects representing market data
*/
async fetchMarkets(params = {}) {
const response = await this.publicGetV1SwapMarketExchangeInfo(params);
//
// {
// "code": "200",
// "message": "success",
// "data": [
// {
// "symbol": "CLANKER-USDT",
// "baseAsset": "CLANKER",
// "marginAsset": "USDT",
// "quoteAsset": "USDT",
// "contractFactor": "0.01",
// "limitMaxQty": "50000",
// "limitMinQty": "1",
// "marketMaxQty": "10000",
// "marketMinQty": "1",
// "pricePrecision": "8",
// "basePrecision": "8",
// "feeRateTaker": "0.0006",
// "feeRateMaker": "0.0002",
// "liqFeeRate": "0.0006",
// "openBuyLimitRateMax": "0.05",
// "openSellLimitRateMax": "100",
// "openBuyLimitRateMin": "0.98",
// "openSellLimitRateMin": "0.05",
// "priceOrderPrecision": "2",
// "baseShowPrecision": "2",
// "maxLeverageLevel": "20",
// "volumePrecision": "2",
// "maxLimitOrderNum": "200",
// "maxPlanOrderNum": "10",
// "reverse": false,
// "onboardTime": "1763373600000",
// "status": "NORMAL"
// },
// ...
// ],
// "success": true
// }
const data = this.safeList(response, 'data', []);
return this.parseMarkets(data);
}
parseMarket(market) {
//
// {
// "symbol": "CLANKER-USDT",
// "baseAsset": "CLANKER",
// "marginAsset": "USDT",
// "quoteAsset": "USDT",
// "contractFactor": "0.01",
// "limitMaxQty": "50000",
// "limitMinQty": "1",
// "marketMaxQty": "10000",
// "marketMinQty": "1",
// "pricePrecision": "8",
// "basePrecision": "8",
// "feeRateTaker": "0.0006",
// "feeRateMaker": "0.0002",
// "liqFeeRate": "0.0006",
// "openBuyLimitRateMax": "0.05",
// "openSellLimitRateMax": "100",
// "openBuyLimitRateMin": "0.98",
// "openSellLimitRateMin": "0.05",
// "priceOrderPrecision": "2",
// "baseShowPrecision": "2",
// "maxLeverageLevel": "20",
// "volumePrecision": "2",
// "maxLimitOrderNum": "200",
// "maxPlanOrderNum": "10",
// "reverse": false,
// "onboardTime": "1763373600000",
// "status": "NORMAL"
// }
//
const id = this.safeString(market, 'symbol');
const baseId = this.safeString(market, 'baseAsset');
const quoteId = this.safeString(market, 'quoteAsset');
const settleId = this.safeString(market, 'marginAsset');
const base = this.safeCurrencyCode(baseId);
const quote = this.safeCurrencyCode(quoteId);
const settle = this.safeCurrencyCode(settleId);
const symbol = base + '/' + quote + ':' + settle;
const inverse = this.safeBool(market, 'reverse');
const limitMaxQty = this.safeString(market, 'limitMaxQty');
const marketMaxQty = this.safeString(market, 'marketMaxQty');
const maxAmountString = Precise.stringMax(limitMaxQty, marketMaxQty);
const marketMinQty = this.safeString(market, 'marketMinQty');
const limitMinQty = this.safeString(market, 'limitMinQty');
const minAmountString = Precise.stringMin(marketMinQty, limitMinQty);
const contractSize = this.safeString(market, 'contractFactor');
const pricePrecision = this.parsePrecision(this.safeString(market, 'priceOrderPrecision'));
const rawAmountPrecision = this.parsePrecision(this.safeString(market, 'volumePrecision'));
const amountPrecision = Precise.stringDiv(rawAmountPrecision, contractSize);
const basePrecision = this.parsePrecision(this.safeString(market, 'basePrecision'));
const taker = this.safeNumber(market, 'feeRateTaker');
const maker = this.safeNumber(market, 'feeRateMaker');
const maxLeverage = this.safeNumber(market, 'maxLeverageLevel');
const status = this.safeString(market, 'status');
return this.safeMarketStructure({
'id': id,
'symbol': symbol,
'base': base,
'quote': quote,
'settle': settle,
'baseId': baseId,
'quoteId': quoteId,
'settleId': settleId,
'type': 'swap',
'spot': false,
'margin': undefined,
'swap': true,
'future': false,
'option': false,
'active': status === 'NORMAL',
'contract': true,
'linear': !inverse,
'inverse': inverse,
'taker': taker,
'maker': maker,
'contractSize': this.parseNumber(contractSize),
'expiry': undefined,
'expiryDatetime': undefined,
'strike': undefined,
'optionType': undefined,
'precision': {
'amount': this.parseNumber(amountPrecision),
'price': this.parseNumber(pricePrecision),
'base': this.parseNumber(basePrecision),
},
'limits': {
'leverage': {
'min': undefined,
'max': maxLeverage,
},
'amount': {
'min': this.parseNumber(minAmountString),
'max': this.parseNumber(maxAmountString),
},
'price': {
'min': undefined,
'max': undefined,
},
'cost': {
'min': undefined,
'max': undefined,
},
},
'created': this.parse8601(this.safeString(market, 'createdAt')),
'info': market,
});
}
/**
* @method
* @name bydfi#fetchOrderBook
* @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
* @see https://developers.bydfi.com/en/swap/market#depth-information
* @param {string} symbol unified symbol of the market to fetch the order book for
* @param {int} [limit] the maximum amount of order book entries to return, could be 5, 10, 20, 50, 100, 500 or 1000 (default 500)
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {string} [params.loc] crypto location, default: us
* @returns {object} A dictionary of [order book structures]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-book-structure} indexed by market symbols
*/
async fetchOrderBook(symbol, limit = undefined, params = {}) {
await this.loadMarkets();
const market = this.market(symbol);
const request = {
'symbol': market['id'],
};
if (limit !== undefined) {
request['limit'] = this.getClosestLimit(limit);
}
const response = await this.publicGetV1SwapMarketDepth(this.extend(request, params));
//
// {
// "code": 200,
// "message": "success",
// "data": {
// "lastUpdateId": "221780076",
// "symbol": "ETH-USDT",
// "asks": [
// {
// "price": "2958.21",
// "amount": "39478"
// },
// ...
// ],
// "bids": [
// {
// "price": "2958.19",
// "amount": "174498"
// },
// ...
// ],
// "e": "221780076"
// },
// "success": true
// }
//
const data = this.safeDict(response, 'data', {});
const timestamp = this.milliseconds();
const orderBook = this.parseOrderBook(data, market['symbol'], timestamp, 'bids', 'asks', 'price', 'amount');
orderBook['nonce'] = this.safeInteger(data, 'lastUpdateId');
return orderBook;
}
getClosestLimit(limit) {
const limits = [5, 10, 20, 50, 100, 500, 1000];
let result = 1000;
for (let i = 0; i < limits.length; i++) {
if (limit <= limits[i]) {
result = limits[i];
break;
}
}
return result;
}
/**
* @method
* @name bydfi#fetchTrades
* @description get the list of most recent trades for a particular symbol
* @see https://developers.bydfi.com/en/swap/market#recent-trades
* @param {string} symbol unified symbol of the market to fetch trades for
* @param {int} [since] timestamp in ms of the earliest trade to fetch
* @param {int} [limit] the maximum amount of trades to fetch (default 500, max 1000)
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {int} [params.fromId] retrieve from which trade ID to start. Default to retrieve the most recent trade records
* @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/?id=public-trades}
*/
async fetchTrades(symbol, since = undefined, limit = undefined, params = {}) {
await this.loadMarkets();
const market = this.market(symbol);
const request = {
'symbol': market['id'],
};
if (limit !== undefined) {
request['limit'] = limit;
}
const response = await this.publicGetV1SwapMarketTrades(this.extend(request, params));
//
// {
// "code": 200,
// "message": "success",
// "data": [
// {
// "id": "7407825178362667008",
// "symbol": "ETH-USDT",
// "price": "2970.49",
// "quantity": "63",
// "side": "SELL",
// "time": 1766163153218
// }
// ],
// "success": true
// }
//
const data = this.safeList(response, 'data', []);
return this.parseTrades(data, market, since, limit);
}
/**
* @method
* @name bydfi#fetchMyTrades
* @description fetch all trades made by the user
* @see https://developers.bydfi.com/en/swap/trade#historical-trades-query
* @param {string} symbol unified market symbol
* @param {int} [since] the earliest time in ms to fetch trades for
* @param {int} [limit] the maximum number of trades structures to retrieve
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {int} [params.until] the latest time in ms to fetch trades for
* @param {string} [params.contractType] FUTURE or DELIVERY, default is FUTURE
* @param {string} [params.wallet] The unique code of a sub-wallet
* @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')
* @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/?id=trade-structure}
*/
async fetchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
await this.loadMarkets();
const paginate = this.safeBool(params, 'paginate', false);
if (paginate) {
const maxLimit = 500;
params = this.omit(params, 'paginate');
params = this.extend(params, { 'paginationDirection': 'backward' });
const paginatedResponse = await this.fetchPaginatedCallDynamic('fetchMyTrades', symbol, since, limit, params, maxLimit, true);
return this.sortBy(paginatedResponse, 'timestamp');
}
let contractType = 'FUTURE';
[contractType, params] = this.handleOptionAndParams(params, 'fetchMyTrades', 'contractType', contractType);
const request = {
'contractType': contractType,
};
let market = undefined;
if (symbol !== undefined) {
market = this.market(symbol);
request['symbol'] = market['id'];
}
params = this.handleSinceAndUntil('fetchMyTrades', since, params);
if (limit !== undefined) {
request['limit'] = limit;
}
const response = await this.privateGetV1SwapTradeHistoryTrade(this.extend(request, params));
//
// {
// "code": 200,
// "message": "success",
// "data": [
// {
// "orderId": "7408919189505597440",
// "wallet": "W001",
// "symbol": "ETH-USDC",
// "time": "1766423985842",
// "dealPrice": "3032.45",
// "dealVolume": "1",
// "fee": "0",
// "side": "BUY",
// "type": "2",
// "liqPrice": null,
// "basePrecision": "8",
// "baseShowPrecision": "2",
// "tradePnl": "0",
// "marginType": "CROSS",
// "leverageLevel": 1
// }
// ],
// "success": true
// }
//
const data = this.safeList(response, 'data', []);
return this.parseTrades(data, market, since, limit);
}
parseTrade(trade, market = undefined) {
//
// fetchTrades
// {
// "id": "7407825178362667008",
// "symbol": "ETH-USDT",
// "price": "2970.49",
// "quantity": "63",
// "side": "SELL",
// "time": 1766163153218
// }
//
// fetchMyTrades
// {
// "orderId": "7408919189505597440",
// "wallet": "W001",
// "symbol": "ETH-USDC",
// "time": "1766423985842",
// "dealPrice": "3032.45",
// "dealVolume": "1",
// "fee": "0",
// "side": "BUY",
// "type": "2",
// "liqPrice": null,
// "basePrecision": "8",
// "baseShowPrecision": "2",
// "tradePnl": "0",
// "marginType": "CROSS",
// "leverageLevel": 1
// }
//
const marketId = this.safeString(trade, 'symbol');
market = this.safeMarket(marketId, market);
const timestamp = this.safeInteger(trade, 'time');
let fee = undefined;
const rawType = this.safeString(trade, 'type');
const feeCost = this.safeString(trade, 'fee');
if (feeCost !== undefined) {
fee = {
'cost': feeCost,
'currency': market['settle'],
};
}
const orderId = this.safeString(trade, 'orderId');
let side = undefined; // fetchMyTrades always returns side BUY
if (orderId === undefined) {
// from fetchTrades
side = this.safeStringLower(trade, 'side');
}
return this.safeTrade({
'info': trade,
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
'symbol': market['symbol'],
'id': this.safeString(trade, 'id'),
'order': orderId,
'type': this.parseTradeType(rawType),
'side': side,
'takerOrMaker': undefined,
'price': this.safeString2(trade, 'price', 'dealPrice'),
'amount': this.safeString2(trade, 'quantity', 'dealVolume'),
'cost': undefined,
'fee': fee,
}, market);
}
parseTradeType(type) {
const types = {
'1': 'limit',
'2': 'market',
'3': 'liquidation',
};
return this.safeString(types, type, type);
}
/**
* @method
* @name bydfi#fetchOHLCV
* @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
* @see https://developers.bydfi.com/en/swap/market#candlestick-data
* @param {string} symbol unified symbol of the market to fetch OHLCV data for
* @param {string} timeframe the length of time each candle represents
* @param {int} [since] timestamp in ms of the earliest candle to fetch
* @param {int} [limit] the maximum amount of candles to fetch (max 500)
* @param {object} [params] extra parameters specific to the bitteam api endpoint
* @param {int} [params.until] timestamp in ms of the latest candle to fetch
* @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
*/
async fetchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
await this.loadMarkets();
const maxLimit = 500; // docs says max 1500, but in practice only 500 works
let paginate = false;
[paginate, params] = this.handleOptionAndParams(params, 'fetchOHLCV', 'paginate');
if (paginate) {
return this.fetchPaginatedCallDeterministic('fetchOHLCV', symbol, since, limit, timeframe, params, maxLimit);
}
const market = this.market(symbol);
const interval = this.safeString(this.timeframes, timeframe, timeframe);
const request = {
'symbol': market['id'],
'interval': interval,
};
let startTime = since;
const numberOfCandles = limit ? limit : maxLimit;
let until = undefined;
[until, params] = this.handleOptionAndParams(params, 'fetchOHLCV', 'until');
const now = this.milliseconds();
const duration = this.parseTimeframe(timeframe) * 1000;
const timeDelta = duration * numberOfCandles;
if (startTime === undefined && until === undefined) {
startTime = now - timeDelta;
until = now;
}
else if (until === undefined) {
until = startTime + timeDelta;
if (until > now) {
until = now;
}
}
else if (startTime === undefined) {
startTime = until - timeDelta;
}
request['startTime'] = startTime;
request['endTime'] = until;
if (limit !== undefined) {
request['limit'] = limit;
}
const response = await this.publicGetV1SwapMarketKlines(this.extend(request, params));
//
// {
// "code": 200,
// "message": "success",
// "data": [
// {
// "s": "ETH-USDT",
// "t": "1766166000000",
// "c": "2964.990000000000000000",
// "o": "2967.830000000000000000",
// "h": "2967.830000000000000000",
// "l": "2964.130000000000000000",
// "v": "20358.000000000000000000"
// }
// ],
// "success": true
// }
//
const data = this.safeList(response, 'data', []);
const result = this.parseOHLCVs(data, market, timeframe, since, limit);
return result;
}
parseOHLCV(ohlcv, market = undefined) {
//
// {
// "s": "ETH-USDT",
// "t": "1766166000000",
// "c": "2964.990000000000000000",
// "o": "2967.830000000000000000",
// "h": "2967.830000000000000000",
// "l": "2964.130000000000000000",
// "v": "20358.000000000000000000"
// }
//
return [
this.safeInteger(ohlcv, 't'),
this.safeNumber(ohlcv, 'o'),
this.safeNumber(ohlcv, 'h'),
this.safeNumber(ohlcv, 'l'),
this.safeNumber(ohlcv, 'c'),
this.safeNumber(ohlcv, 'v'),
];
}
/**
* @method
* @name bydfi#fetchTickers
* @see https://developers.bydfi.com/en/swap/market#24hr-price-change-statistics
* @description fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
* @param {string[]|undefined} symbols unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a dictionary of [ticker structures]{@link https://docs.ccxt.com/?id=ticker-structure}
*/
async fetchTickers(symbols = undefined, params = {}) {
await this.loadMarkets();
const response = await this.publicGetV1SwapMarketTicker24hr(params);
//
// {
// "code": 200,
// "message": "success",
// "data": [
// {
// "symbol": "BTC-USDT",
// "open": "86452.9",
// "high": "89371.2",
// "low": "84418.5",
// "last": "87050.3",
// "vol": "12938783",
// "time": 1766169423872
// }
// ],
// "success": true
// }
//
const data = this.safeList(response, 'data', []);
return this.parseTickers(data, symbols);
}
/**
* @method
* @name bydfi#fetchTicker
* @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
* @see https://developers.bydfi.com/en/swap/market#24hr-price-change-statistics
* @param {string} symbol unified symbol of the market to fetch the ticker for
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/?id=ticker-structure}
*/
async fetchTicker(symbol, params = {}) {
await this.loadMarkets();
const market = this.market(symbol);
const request = {
'symbol': market['id'],
};
const response = await this.publicGetV1SwapMarketTicker24hr(this.extend(request, params));
const data = this.safeList(response, 'data', []);
const ticker = this.safeDict(data, 0, {});
return this.parseTicker(ticker, market);
}
parseTicker(ticker, market = undefined) {
//
// fetchTicker/fetchTickers
// {
// "symbol": "BTC-USDT",
// "open": "86452.9",
// "high": "89371.2",
// "low": "84418.5",
// "last": "87050.3",
// "vol": "12938783",
// "time": 1766169423872
// }
//
const marketId = this.safeString2(ticker, 'symbol', 's');
market = this.safeMarket(marketId, market);
const timestamp = this.safeInteger2(ticker, 'time', 'E');
const last = this.safeString2(ticker, 'last', 'c');
return this.safeTicker({
'symbol': this.safeSymbol(marketId, market),
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
'high': this.safeString2(ticker, 'high', 'h'),
'low': this.safeString2(ticker, 'low', 'l'),
'bid': undefined,
'bidVolume': undefined,
'ask': undefined,
'askVolume': undefined,
'vwap': undefined,
'open': this.safeString2(ticker, 'open', 'o'),
'close': last,
'last': last,
'previousClose': undefined,
'change': undefined,
'percentage': undefined,
'average': undefined,
'baseVolume': this.safeString2(ticker, 'vol', 'v'),
'quoteVolume': undefined,
'markPrice': undefined,
'indexPrice': undefined,
'info': ticker,
}, market);
}
/**
* @method
* @name bydfi#fetchFundingRate
* @description fetch the current funding rate
* @see https://developers.bydfi.com/en/swap/market#recent-funding-rate
* @param {string} symbol unified market symbol
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [funding rate structure]{@link https://docs.ccxt.com/?id=funding-rate-structure}
*/
async fetchFundingRate(symbol, params = {}) {
await this.loadMarkets();
const market = this.market(symbol);
const request = {
'symbol': market['id'],
};
const response = await this.publicGetV1SwapMarketFundingRate(this.extend(request, params));
//
// {
// "code": 200,
// "message": "success",
// "data": {
// "symbol": "BTC-USDT",
// "lastFundingRate": "0.0001",
// "nextFundingTime": "1766188800000",
// "time": "1766170665007"
// },
// "success": true
// }
//
const data = this.safeDict(response, 'data');
return this.parseFundingRate(data, market);
}
parseFundingRate(contract, market = undefined) {
//
// {
// "symbol": "BTC-USDT",
// "lastFundingRate": "0.0001",
// "nextFundingTime": "1766188800000",
// "time": "1766170665007"
// }
//
const marketId = this.safeString(contract, 'symbol');
const symbol = this.safeSymbol(marketId, market);
const timestamp = this.safeInteger(contract, 'time');
const nextFundingTimestamp = this.safeInteger(contract, 'nextFundingTime');
return {
'info': contract,
'symbol': symbol,
'markPrice': undefined,
'indexPrice': undefined,
'interestRate': undefined,
'estimatedSettlePrice': undefined,
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
'fundingRate': this.safeNumber(contract, 'lastFundingRate'),
'fundingTimestamp': undefined,
'fundingDatetime': undefined,
'nextFundingRate': undefined,
'nextFundingTimestamp': nextFundingTimestamp,
'nextFundingDatetime': this.iso8601(nextFundingTimestamp),
'previousFundingRate': undefined,
'previousFundingTimestamp': undefined,
'previousFundingDatetime': undefined,
'interval': undefined,
};
}
/**
* @method
* @name bydfi#fetchFundingRateHistory
* @description fetches historical funding rate prices
* @see https://developers.bydfi.com/en/swap/market#historical-funding-rates
* @param {string} symbol unified symbol of the market to fetch the funding rate history for
* @param {int} [since] timestamp in ms of the earliest funding rate to fetch
* @param {int} [limit] the maximum amount of [funding rate structures]{@link https://docs.ccxt.com/?id=funding-rate-history-structure} to fetch
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {int} [params.until] timestamp in ms of the latest funding rate to fetch
* @returns {object[]} a list of [funding rate structures]{@link https://docs.ccxt.com/?id=funding-rate-history-structure}
*/
async fetchFundingRateHistory(symbol = undefined, since = undefined, limit = undefined, params = {}) {
if (symbol === undefined) {
throw new ArgumentsRequired(this.id + ' fetchFundingRateHistory() requires a symbol argument');
}
await this.loadMarkets();
const market = this.market(symbol);
const request = {
'symbol': market['id'],
};
if (since !== undefined) {
request['startTime'] = since;
}
if (limit !== undefined) {
request['limit'] = limit;
}
let until = undefined;
[until, params] = this.handleOptionAndParams(params, 'fetchFundingRateHistory', 'until');
if (until !== undefined) {
request['endTime'] = until;
}
const response = await this.publicGetV1SwapMarketFundingRateHistory(this.extend(request, params));
//
// {
// "code": 200,
// "message": "success",
// "data": [
// {
// "symbol": "ETH-USDT",
// "fundingRate": "0.00000025",
// "fundingTime": "1765584000000",
// "markPrice": "3083.2"
// }
// ],
// "success": true
// }
//
const data = this.safeList(response, 'data', []);
return this.parseFundingRateHistories(data, market, since, limit);
}
parseFundingRateHistory(contract, market = undefined) {
//
// {
// "symbol": "ETH-USDT",
// "fundingRate": "0.00000025",
// "fundingTime": "1765584000000",
// "markPrice": "3083.2"
// }
//
const marketId = this.safeString(contract, 'symbol');
const timestamp = this.safeInteger(contract, 'fundingTime');
return {
'info': contract,
'symbol': this.safeSymbol(marketId, market),
'fundingRate': this.safeNumber(contract, 'fundingRate'),
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
};
}
/**
* @method
* @name bydfi#createOrder
* @description create a trade order
* @see https://developers.bydfi.com/en/swap/trade#placing-an-order
* @param {string} symbol unified symbol of the market to create an order in
* @param {string} type 'market' or 'limit'
* @param {string} side 'buy' or 'sell'
* @param {float} amount how much of currency you want to trade in units of base currency
* @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {string} [params.wallet] The unique code of a sub-wallet. W001 is the default wallet and the main wallet code of the contract
* @param {bool} [params.hedged] true for hedged mode, false for one way mode, default is false
* @param {string} [params.clientOrderId] Custom order ID, must be unique for open orders
* @param {string} [params.timeInForce] 'GTC' (Good Till Cancelled), 'FOK' (Fill Or Kill), 'IOC' (Immediate Or Cancel), 'PO' (Post Only)
* @param {bool} [params.postOnly] true or false, whether the order is post-only
* @param {bool} [params.reduceOnly] true or false, true or fal