UNPKG

@kraken-crypto/ccxt

Version:

A cryptocurrency trading API with more than 100 exchanges in JavaScript / TypeScript / Python / C# / PHP / Go

1,126 lines (1,123 loc) 185 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var whitebit$1 = require('./abstract/whitebit.js'); var errors = require('./base/errors.js'); var Precise = require('./base/Precise.js'); var number = require('./base/functions/number.js'); var sha512 = require('./static_dependencies/noble-hashes/sha512.js'); // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- /** * @class whitebit * @augments Exchange */ class whitebit extends whitebit$1["default"] { describe() { return this.deepExtend(super.describe(), { 'id': 'whitebit', 'name': 'WhiteBit', 'version': 'v4', 'countries': ['EE'], 'rateLimit': 50, 'pro': true, 'has': { 'CORS': undefined, 'spot': true, 'margin': true, 'swap': true, 'future': false, 'option': false, 'cancelAllOrders': true, 'cancelAllOrdersAfter': true, 'cancelOrder': true, 'cancelOrders': false, 'createConvertTrade': true, 'createDepositAddress': true, 'createMarketBuyOrderWithCost': true, 'createMarketOrderWithCost': false, 'createMarketSellOrderWithCost': false, 'createOrder': true, 'createPostOnlyOrder': true, 'createStopLimitOrder': true, 'createStopMarketOrder': true, 'createStopOrder': true, 'createTriggerOrder': true, 'editOrder': true, 'fetchAccounts': true, 'fetchBalance': true, 'fetchBorrowRateHistories': false, 'fetchBorrowRateHistory': false, 'fetchClosedOrders': true, 'fetchConvertQuote': true, 'fetchConvertTrade': false, 'fetchConvertTradeHistory': true, 'fetchCrossBorrowRate': true, 'fetchCrossBorrowRates': false, 'fetchCurrencies': true, 'fetchDeposit': true, 'fetchDepositAddress': true, 'fetchDepositAddresses': false, 'fetchDepositAddressesByNetwork': false, 'fetchDeposits': true, 'fetchDepositsWithdrawals': true, 'fetchDepositWithdrawFee': 'emulated', 'fetchDepositWithdrawFees': true, 'fetchFundingHistory': true, 'fetchFundingLimits': true, 'fetchFundingRate': true, 'fetchFundingRateHistory': false, 'fetchFundingRates': true, 'fetchIndexOHLCV': false, 'fetchIsolatedBorrowRate': false, 'fetchIsolatedBorrowRates': false, 'fetchLedger': false, 'fetchMarginMode': false, 'fetchMarkets': true, 'fetchMarkOHLCV': false, 'fetchMyTrades': true, 'fetchOHLCV': true, 'fetchOpenInterestHistory': false, 'fetchOpenOrders': true, 'fetchOrder': true, 'fetchOrderBook': true, 'fetchOrders': true, 'fetchOrderTrades': true, 'fetchPosition': true, 'fetchPositionHistory': true, 'fetchPositionMode': false, 'fetchPositions': true, 'fetchPremiumIndexOHLCV': false, 'fetchStatus': true, 'fetchTicker': true, 'fetchTickers': true, 'fetchTime': true, 'fetchTrades': true, 'fetchTradingFee': false, 'fetchTradingFees': true, 'fetchTradingLimits': true, 'fetchTransactionFees': true, 'fetchTransactions': true, 'fetchWithdrawals': true, 'repayCrossMargin': false, 'repayIsolatedMargin': false, 'setLeverage': true, 'transfer': true, 'withdraw': true, }, 'timeframes': { '1m': '1m', '3m': '3m', '5m': '5m', '15m': '15m', '30m': '30m', '1h': '1h', '2h': '2h', '4h': '4h', '6h': '6h', '8h': '8h', '12h': '12h', '1d': '1d', '3d': '3d', '1w': '1w', '1M': '1M', }, 'urls': { 'logo': 'https://user-images.githubusercontent.com/1294454/66732963-8eb7dd00-ee66-11e9-849b-10d9282bb9e0.jpg', 'api': { 'v1': { 'public': 'https://whitebit.com/api/v1/public', 'private': 'https://whitebit.com/api/v1', }, 'v2': { 'public': 'https://whitebit.com/api/v2/public', }, 'v4': { 'public': 'https://whitebit.com/api/v4/public', 'private': 'https://whitebit.com/api/v4', }, }, 'www': 'https://www.whitebit.com', 'doc': 'https://github.com/whitebit-exchange/api-docs', 'fees': 'https://whitebit.com/fee-schedule', 'referral': 'https://whitebit.com/referral/d9bdf40e-28f2-4b52-b2f9-cd1415d82963', }, 'api': { 'web': { 'get': [ 'v1/healthcheck', ], }, 'v1': { 'public': { 'get': [ 'markets', 'tickers', 'ticker', 'symbols', 'depth/result', 'history', 'kline', ], }, 'private': { 'post': [ 'account/balance', 'order/new', 'order/cancel', 'orders', 'account/order_history', 'account/executed_history', 'account/executed_history/all', 'account/order', ], }, }, 'v2': { 'public': { 'get': [ 'markets', 'ticker', 'assets', 'fee', 'depth/{market}', 'trades/{market}', ], }, }, 'v4': { 'public': { 'get': [ 'assets', 'collateral/markets', 'fee', 'orderbook/depth/{market}', 'orderbook/{market}', 'ticker', 'trades/{market}', 'time', 'ping', 'markets', 'futures', 'platform/status', 'mining-pool', ], }, 'private': { 'post': [ 'collateral-account/balance', 'collateral-account/balance-summary', 'collateral-account/positions/history', 'collateral-account/leverage', 'collateral-account/positions/open', 'collateral-account/summary', 'collateral-account/funding-history', 'main-account/address', 'main-account/balance', 'main-account/create-new-address', 'main-account/codes', 'main-account/codes/apply', 'main-account/codes/my', 'main-account/codes/history', 'main-account/fiat-deposit-url', 'main-account/history', 'main-account/withdraw', 'main-account/withdraw-pay', 'main-account/transfer', 'main-account/smart/plans', 'main-account/smart/investment', 'main-account/smart/investment/close', 'main-account/smart/investments', 'main-account/fee', 'main-account/smart/interest-payment-history', 'trade-account/balance', 'trade-account/executed-history', 'trade-account/order/history', 'trade-account/order', 'order/collateral/limit', 'order/collateral/market', 'order/collateral/stop-limit', 'order/collateral/trigger-market', 'order/collateral/bulk', 'order/new', 'order/market', 'order/stock_market', 'order/stop_limit', 'order/stop_market', 'order/cancel', 'order/cancel/all', 'order/kill-switch', 'order/kill-switch/status', 'order/bulk', 'order/modify', 'order/conditional-cancel', 'orders', 'oco-orders', 'order/collateral/oco', 'order/oco-cancel', 'order/oto-cancel', 'profile/websocket_token', 'convert/estimate', 'convert/confirm', 'convert/history', 'sub-account/create', 'sub-account/delete', 'sub-account/edit', 'sub-account/list', 'sub-account/transfer', 'sub-account/block', 'sub-account/unblock', 'sub-account/balances', 'sub-account/transfer/history', 'sub-account/api-key/create', 'sub-account/api-key/edit', 'sub-account/api-key/delete', 'sub-account/api-key/list', 'sub-account/api-key/reset', 'sub-account/api-key/ip-address/list', 'sub-account/api-key/ip-address/create', 'sub-account/api-key/ip-address/delete', 'mining/rewards', 'market/fee', 'conditional-orders', ], }, }, }, 'fees': { 'trading': { 'tierBased': false, 'percentage': true, 'taker': this.parseNumber('0.001'), 'maker': this.parseNumber('0.001'), }, }, 'options': { 'timeDifference': 0, 'adjustForTimeDifference': false, 'fiatCurrencies': ['EUR', 'USD', 'RUB', 'UAH'], 'fetchBalance': { 'account': 'spot', }, 'accountsByType': { 'funding': 'main', 'main': 'main', 'spot': 'spot', 'margin': 'collateral', 'trade': 'spot', }, 'networksById': { 'BEP20': 'BSC', }, 'defaultType': 'spot', 'brokerId': 'ccxt', }, 'features': { 'default': { 'sandbox': false, 'createOrder': { 'marginMode': true, 'triggerPrice': true, 'triggerDirection': false, 'triggerPriceType': undefined, 'stopLossPrice': false, 'takeProfitPrice': false, 'attachedStopLossTakeProfit': undefined, 'timeInForce': { 'IOC': true, 'FOK': false, 'PO': true, 'GTD': false, }, 'hedged': false, 'trailing': false, 'leverage': false, 'marketBuyByCost': true, 'marketBuyRequiresPrice': false, 'selfTradePrevention': false, 'iceberg': false, }, 'createOrders': undefined, 'fetchMyTrades': { 'marginMode': false, 'limit': 100, 'daysBack': undefined, 'untilDays': undefined, 'symbolRequired': false, }, 'fetchOrder': { 'checkActive': true, 'checkExecuted': true, 'symbolRequired': false, 'marginMode': false, 'trigger': false, 'trailing': false, }, 'fetchOpenOrders': { 'marginMode': false, 'limit': 100, 'trigger': false, 'trailing': false, 'symbolRequired': false, }, 'fetchOrders': { 'marginMode': false, 'limit': 100, 'daysBack': undefined, 'untilDays': undefined, 'trigger': false, 'trailing': false, 'symbolRequired': false, }, 'fetchClosedOrders': { 'marginMode': false, 'limit': 100, 'daysBack': undefined, 'daysBackCanceled': undefined, 'untilDays': undefined, 'trigger': false, 'trailing': false, 'symbolRequired': false, }, 'fetchOHLCV': { 'limit': 1440, }, 'fetchWithdrawals': { 'marginMode': false, 'limit': 100, 'daysBack': undefined, 'untilDays': undefined, 'symbolRequired': false, }, }, 'spot': { 'extends': 'default', }, 'swap': { 'linear': { 'extends': 'default', }, 'inverse': { 'extends': 'default', }, }, 'future': { 'linear': undefined, 'inverse': undefined, }, }, 'precisionMode': number.TICK_SIZE, 'exceptions': { 'exact': { 'Unauthorized request.': errors.AuthenticationError, 'The market format is invalid.': errors.BadSymbol, 'Market is not available': errors.BadSymbol, 'Invalid payload.': errors.BadRequest, 'Amount must be greater than 0': errors.InvalidOrder, 'Not enough balance.': errors.InsufficientFunds, 'The order id field is required.': errors.InvalidOrder, 'Not enough balance': errors.InsufficientFunds, 'This action is unauthorized.': errors.PermissionDenied, 'This API Key is not authorized to perform this action.': errors.PermissionDenied, 'Unexecuted order was not found.': errors.OrderNotFound, 'The selected from is invalid.': errors.BadRequest, '503': errors.ExchangeNotAvailable, '422': errors.OrderNotFound, // {"response":null,"status":422,"errors":{"orderId":["Finished order id 1295772653 not found on your account"]},"notification":null,"warning":"Finished order id 1295772653 not found on your account","_token":null} }, 'broad': { 'This action is unauthorized': errors.PermissionDenied, 'Given amount is less than min amount': errors.InvalidOrder, 'Min amount step': errors.InvalidOrder, 'Total is less than': errors.InvalidOrder, 'fee must be no less than': errors.InvalidOrder, 'Enable your key in API settings': errors.PermissionDenied, 'You don\'t have such amount for transfer': errors.InsufficientFunds, // {"code":3,"message":"Inner validation failed","errors":{"amount":["You don't have such amount for transfer (available 0.44523433, in amount: 2)"]}} }, }, }); } /** * @method * @name whitebit#fetchMarkets * @description retrieves data on all markets for whitebit * @see https://docs.whitebit.com/public/http-v4/#market-info * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object[]} an array of objects representing market data */ async fetchMarkets(params = {}) { if (this.options['adjustForTimeDifference']) { await this.loadTimeDifference(); } const markets = await this.v4PublicGetMarkets(); // // [ // { // "name": "SON_USD", // Market pair name // "stock": "SON", // Ticker of stock currency // "money": "USD", // Ticker of money currency // "stockPrec": "3", // Stock currency precision // "moneyPrec": "2", // Precision of money currency // "feePrec": "4", // Fee precision // "makerFee": "0.1", // Default maker fee ratio // "takerFee": "0.1", // Default taker fee ratio // "minAmount": "0.001", // Minimal amount of stock to trade // "minTotal": "0.001", // Minimal amount of money to trade // "tradesEnabled": true, // Is trading enabled // "isCollateral": true, // Is margin trading enabled // "type": "spot", // Market type. Possible values: "spot", "futures" // "maxTotal": "1000000000" // Maximum total(amount * price) of money to trade // }, // { // ... // } // ] // return this.parseMarkets(markets); } parseMarket(market) { const id = this.safeString(market, 'name'); const baseId = this.safeString(market, 'stock'); let quoteId = this.safeString(market, 'money'); quoteId = (quoteId === 'PERP') ? 'USDT' : quoteId; const base = this.safeCurrencyCode(baseId); const quote = this.safeCurrencyCode(quoteId); const active = this.safeValue(market, 'tradesEnabled'); const isCollateral = this.safeValue(market, 'isCollateral'); const typeId = this.safeString(market, 'type'); let type; let settle = undefined; let settleId = undefined; let symbol = base + '/' + quote; const swap = typeId === 'futures'; const margin = isCollateral && !swap; let contract = false; const amountPrecision = this.parseNumber(this.parsePrecision(this.safeString(market, 'stockPrec'))); const contractSize = amountPrecision; let linear = undefined; let inverse = undefined; if (swap) { settleId = quoteId; settle = this.safeCurrencyCode(settleId); symbol = symbol + ':' + settle; type = 'swap'; contract = true; linear = true; inverse = false; } else { type = 'spot'; } const takerFeeRate = this.safeString(market, 'takerFee'); const taker = Precise["default"].stringDiv(takerFeeRate, '100'); const makerFeeRate = this.safeString(market, 'makerFee'); const maker = Precise["default"].stringDiv(makerFeeRate, '100'); return { 'id': id, 'symbol': symbol, 'base': base, 'quote': quote, 'settle': settle, 'baseId': baseId, 'quoteId': quoteId, 'settleId': settleId, 'type': type, 'spot': !swap, 'margin': margin, 'swap': swap, 'future': false, 'option': false, 'active': active, 'contract': contract, 'linear': linear, 'inverse': inverse, 'taker': this.parseNumber(taker), 'maker': this.parseNumber(maker), 'contractSize': contractSize, 'expiry': undefined, 'expiryDatetime': undefined, 'strike': undefined, 'optionType': undefined, 'precision': { 'amount': amountPrecision, 'price': this.parseNumber(this.parsePrecision(this.safeString(market, 'moneyPrec'))), }, 'limits': { 'leverage': { 'min': undefined, 'max': undefined, }, 'amount': { 'min': this.safeNumber(market, 'minAmount'), 'max': undefined, }, 'price': { 'min': undefined, 'max': undefined, }, 'cost': { 'min': this.safeNumber(market, 'minTotal'), 'max': this.safeNumber(market, 'maxTotal'), }, }, 'created': undefined, 'info': market, }; } /** * @method * @name whitebit#fetchCurrencies * @description fetches all available currencies on an exchange * @see https://docs.whitebit.com/public/http-v4/#asset-status-list * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} an associative dictionary of currencies */ async fetchCurrencies(params = {}) { const response = await this.v4PublicGetAssets(params); // // { // BTC: { // name: "Bitcoin", // unified_cryptoasset_id: "1", // can_withdraw: true, // can_deposit: true, // min_withdraw: "0.0003", // max_withdraw: "0", // maker_fee: "0.1", // taker_fee: "0.1", // min_deposit: "0.0001", // max_deposit: "0", // networks: { // deposits: [ "BTC", ], // withdraws: [ "BTC", ], // default: "BTC", // }, // confirmations: { // BTC: "2", // }, // limits: { // deposit: { // BTC: { min: "0.0001", }, // }, // withdraw: { // BTC: { min: "0.0003", }, // }, // }, // currency_precision: "8", // is_memo: false, // }, // USD: { // name: "United States Dollar", // unified_cryptoasset_id: "6955", // can_withdraw: true, // can_deposit: true, // min_withdraw: "10", // max_withdraw: "10000", // maker_fee: "0.1", // taker_fee: "0.1", // min_deposit: "10", // max_deposit: "10000", // networks: { // deposits: [ "USD", ], // withdraws: [ "USD", ], // default: "USD", // }, // providers: { // deposits: [ "ADVCASH", ], // withdraws: [ "ADVCASH", ], // }, // limits: { // deposit: { // USD: { max: "10000", min: "10", }, // }, // withdraw: { // USD: { max: "10000", min: "10", }, // }, // }, // currency_precision: "2", // is_memo: false, // } // } // const ids = Object.keys(response); const result = {}; for (let i = 0; i < ids.length; i++) { const id = ids[i]; const currency = response[id]; // const name = this.safeString (currency, 'name'); // breaks down in Python due to utf8 encoding issues on the exchange side const code = this.safeCurrencyCode(id); const hasProvider = ('providers' in currency); const rawNetworks = this.safeDict(currency, 'networks', {}); const depositsNetworks = this.safeList(rawNetworks, 'deposits', []); const withdrawsNetworks = this.safeList(rawNetworks, 'withdraws', []); const networkLimits = this.safeDict(currency, 'limits', {}); const depositLimits = this.safeDict(networkLimits, 'deposit', {}); const withdrawLimits = this.safeDict(networkLimits, 'withdraw', {}); const allNetworks = this.arrayConcat(depositsNetworks, withdrawsNetworks); for (let j = 0; j < allNetworks.length; j++) { const networkId = allNetworks[j]; const networkCode = this.networkIdToCode(networkId); ({ 'id': networkId, 'network': networkCode, 'active': undefined, 'deposit': this.inArray(networkId, depositsNetworks), 'withdraw': this.inArray(networkId, withdrawsNetworks), 'fee': undefined, 'precision': undefined, 'limits': { 'deposit': { 'min': this.safeNumber(depositLimits, 'min', undefined), 'max': this.safeNumber(depositLimits, 'max', undefined), }, 'withdraw': { 'min': this.safeNumber(withdrawLimits, 'min', undefined), 'max': this.safeNumber(withdrawLimits, 'max', undefined), }, }, }); } result[code] = this.safeCurrencyStructure({ 'id': id, 'code': code, 'info': currency, 'name': undefined, 'active': undefined, 'deposit': this.safeBool(currency, 'can_deposit'), 'withdraw': this.safeBool(currency, 'can_withdraw'), 'fee': undefined, 'networks': undefined, 'type': hasProvider ? 'fiat' : 'crypto', 'precision': this.parseNumber(this.parsePrecision(this.safeString(currency, 'currency_precision'))), 'limits': { 'amount': { 'min': undefined, 'max': undefined, }, 'withdraw': { 'min': this.safeNumber(currency, 'min_withdraw'), 'max': this.safeNumber(currency, 'max_withdraw'), }, 'deposit': { 'min': this.safeNumber(currency, 'min_deposit'), 'max': this.safeNumber(currency, 'max_deposit'), }, }, }); } return result; } /** * @method * @name whitebit#fetchTransactionFees * @deprecated * @description please use fetchDepositWithdrawFees instead * @see https://docs.whitebit.com/public/http-v4/#fee * @param {string[]|undefined} codes not used by fetchTransactionFees () * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} a list of [fee structures]{@link https://docs.ccxt.com/#/?id=fee-structure} */ async fetchTransactionFees(codes = undefined, params = {}) { await this.loadMarkets(); const response = await this.v4PublicGetFee(params); // // { // "1INCH":{ // "is_depositable":true, // "is_withdrawal":true, // "ticker":"1INCH", // "name":"1inch", // "providers":[ // ], // "withdraw":{ // "max_amount":"0", // "min_amount":"21.5", // "fixed":"17.5", // "flex":null // }, // "deposit":{ // "max_amount":"0", // "min_amount":"19.5", // "fixed":null, // "flex":null // } // }, // {...} // } // const currenciesIds = Object.keys(response); const withdrawFees = {}; const depositFees = {}; for (let i = 0; i < currenciesIds.length; i++) { const currency = currenciesIds[i]; const data = response[currency]; const code = this.safeCurrencyCode(currency); const withdraw = this.safeValue(data, 'withdraw', {}); withdrawFees[code] = this.safeString(withdraw, 'fixed'); const deposit = this.safeValue(data, 'deposit', {}); depositFees[code] = this.safeString(deposit, 'fixed'); } return { 'withdraw': withdrawFees, 'deposit': depositFees, 'info': response, }; } /** * @method * @name whitebit#fetchDepositWithdrawFees * @description fetch deposit and withdraw fees * @see https://docs.whitebit.com/public/http-v4/#fee * @param {string[]|undefined} codes not used by fetchDepositWithdrawFees () * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} a list of [fee structures]{@link https://docs.ccxt.com/#/?id=fee-structure} */ async fetchDepositWithdrawFees(codes = undefined, params = {}) { await this.loadMarkets(); const response = await this.v4PublicGetFee(params); // // { // "1INCH": { // "is_depositable": true, // "is_withdrawal": true, // "ticker": "1INCH", // "name": "1inch", // "providers": [], // "withdraw": { // "max_amount": "0", // "min_amount": "21.5", // "fixed": "17.5", // "flex": null // }, // "deposit": { // "max_amount": "0", // "min_amount": "19.5", // "fixed": null, // "flex": null // } // }, // "WBT (ERC20)": { // "is_depositable": true, // "is_withdrawal": true, // "ticker": "WBT", // "name": "WhiteBIT Token", // "providers": [], // "withdraw": { max_amount: "0", min_amount: '0.7', fixed: "0.253", flex: null }, // "deposit": { max_amount: "0", min_amount: "0.35", fixed: null, flex: null } // }, // "WBT (TRC20)": { // "is_depositable": true, // "is_withdrawal": true, // "ticker": "WBT", // "name": "WhiteBIT Token", // "providers": [], // "withdraw": { max_amount: "0", min_amount: "1.5", fixed: "0.075", flex: null }, // "deposit": { max_amount: "0", min_amount: "0.75", fixed: null, flex: null } // }, // ... // } // return this.parseDepositWithdrawFees(response, codes); } parseDepositWithdrawFees(response, codes = undefined, currencyIdKey = undefined) { // // { // "1INCH": { // "is_depositable": true, // "is_withdrawal": true, // "ticker": "1INCH", // "name": "1inch", // "providers": [], // "withdraw": { // "max_amount": "0", // "min_amount": "21.5", // "fixed": "17.5", // "flex": null // }, // "deposit": { // "max_amount": "0", // "min_amount": "19.5", // "fixed": null, // "flex": null // } // }, // "WBT (ERC20)": { // "is_depositable": true, // "is_withdrawal": true, // "ticker": "WBT", // "name": "WhiteBIT Token", // "providers": [], // "withdraw": { max_amount: "0", min_amount: "0.7", fixed: "0.253", flex: null }, // "deposit": { max_amount: "0", min_amount: "0.35", fixed: null, flex: null } // }, // "WBT (TRC20)": { // "is_depositable": true, // "is_withdrawal": true, // "ticker": "WBT", // "name": "WhiteBIT Token", // "providers": [], // "withdraw": { max_amount: "0", min_amount: "1.5", fixed: "0.075", flex: null }, // "deposit": { max_amount: "0", min_amount: "0.75", fixed: null, flex: null } // }, // ... // } // const depositWithdrawFees = {}; codes = this.marketCodes(codes); const currencyIds = Object.keys(response); for (let i = 0; i < currencyIds.length; i++) { const entry = currencyIds[i]; const splitEntry = entry.split(' '); const currencyId = splitEntry[0]; const feeInfo = response[entry]; const code = this.safeCurrencyCode(currencyId); if ((codes === undefined) || (this.inArray(code, codes))) { const depositWithdrawFee = this.safeValue(depositWithdrawFees, code); if (depositWithdrawFee === undefined) { depositWithdrawFees[code] = this.depositWithdrawFee({}); } depositWithdrawFees[code]['info'][entry] = feeInfo; let networkId = this.safeString(splitEntry, 1); const withdraw = this.safeValue(feeInfo, 'withdraw'); const deposit = this.safeValue(feeInfo, 'deposit'); const withdrawFee = this.safeNumber(withdraw, 'fixed'); const depositFee = this.safeNumber(deposit, 'fixed'); const withdrawResult = { 'fee': withdrawFee, 'percentage': (withdrawFee !== undefined) ? false : undefined, }; const depositResult = { 'fee': depositFee, 'percentage': (depositFee !== undefined) ? false : undefined, }; if (networkId !== undefined) { const networkLength = networkId.length; networkId = networkId.slice(1, networkLength - 1); const networkCode = this.networkIdToCode(networkId); depositWithdrawFees[code]['networks'][networkCode] = { 'withdraw': withdrawResult, 'deposit': depositResult, }; } else { depositWithdrawFees[code]['withdraw'] = withdrawResult; depositWithdrawFees[code]['deposit'] = depositResult; } } } const depositWithdrawCodes = Object.keys(depositWithdrawFees); for (let i = 0; i < depositWithdrawCodes.length; i++) { const code = depositWithdrawCodes[i]; const currency = this.currency(code); depositWithdrawFees[code] = this.assignDefaultDepositWithdrawFees(depositWithdrawFees[code], currency); } return depositWithdrawFees; } /** * @method * @name whitebit#fetchTradingFees * @description fetch the trading fees for multiple markets * @see https://docs.whitebit.com/public/http-v4/#asset-status-list * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} a dictionary of [fee structures]{@link https://docs.ccxt.com/#/?id=fee-structure} indexed by market symbols */ async fetchTradingFees(params = {}) { await this.loadMarkets(); const response = await this.v4PublicGetAssets(params); // // { // "1INCH": { // "name": "1inch", // "unified_cryptoasset_id": "8104", // "can_withdraw": true, // "can_deposit": true, // "min_withdraw": "33", // "max_withdraw": "0", // "maker_fee": "0.1", // "taker_fee": "0.1", // "min_deposit": "30", // "max_deposit": "0" // }, // ... // } // const result = {}; for (let i = 0; i < this.symbols.length; i++) { const symbol = this.symbols[i]; const market = this.market(symbol); const fee = this.safeValue(response, market['baseId'], {}); let makerFee = this.safeString(fee, 'maker_fee'); let takerFee = this.safeString(fee, 'taker_fee'); makerFee = Precise["default"].stringDiv(makerFee, '100'); takerFee = Precise["default"].stringDiv(takerFee, '100'); result[symbol] = { 'info': fee, 'symbol': market['symbol'], 'percentage': true, 'tierBased': false, 'maker': this.parseNumber(makerFee), 'taker': this.parseNumber(takerFee), }; } return result; } /** * @method * @name whitebit#fetchTradingLimits * @description fetch the trading limits for a market * @see https://docs.whitebit.com/public/http-v4/#market-info * @param {string[]|undefined} symbols unified market symbol * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} a [trading limits structure]{@link https://docs.ccxt.com/#/?id=trading-limits-structure} */ async fetchTradingLimits(symbols = undefined, params = {}) { await this.loadMarkets(); // // Trading limits are derived from market information already loaded by loadMarkets() // Market structure includes: // { // "id": "BTC_USDT", // Market ID // "symbol": "BTC/USDT", // Unified symbol // "base": "BTC", // Base currency // "quote": "USDT", // Quote currency // "active": true, // Market active status // "type": "spot", // Market type // "spot": true, // Spot trading enabled // "margin": false, // Margin trading enabled // "future": false, // Futures trading enabled // "option": false, // Options trading enabled // "contract": false, // Contract trading enabled // "settle": undefined, // Settlement currency // "settleId": undefined, // Settlement currency ID // "contractSize": undefined, // Contract size // "linear": undefined, // Linear contract // "inverse": undefined, // Inverse contract // "limits": { // Trading limits // "amount": { // Amount limits // "min": 0.00001, // Minimum amount // "max": 1000000 // Maximum amount // }, // "price": { // Price limits // "min": 0.01, // Minimum price // "max": 1000000 // Maximum price // }, // "cost": { // Cost limits // "min": 5.0, // Minimum cost // "max": 10000000 // Maximum cost // } // }, // "precision": { // Precision settings // "amount": 5, // Amount precision // "price": 2 // Price precision // }, // "taker": 0.001, // Taker fee // "maker": 0.001, // Maker fee // "percentage": true, // Fee percentage // "tierBased": false // Tier-based fees // } // const result = {}; // Process all markets from the loaded markets cache const marketIds = Object.keys(this.markets); for (let i = 0; i < marketIds.length; i++) { const marketId = marketIds[i]; const market = this.markets[marketId]; if (!market || !market['symbol']) { continue; // Skip invalid markets silently } const symbol = market['symbol']; // Filter by symbols if specified if (symbols) { let symbolFound = false; for (let j = 0; j < symbols.length; j++) { if (symbols[j] === symbol) { symbolFound = true; break; } } if (!symbolFound) { continue; // Skip symbols not in requested list } } // Extract trading limits const limits = this.safeDict(market, 'limits'); const amountLimits = this.safeDict(limits, 'amount'); const priceLimits = this.safeDict(limits, 'price'); const costLimits = this.safeDict(limits, 'cost'); // Validate that all required limits exist and are valid numbers const hasAmountLimits = amountLimits && this.safeNumber(amountLimits, 'min') !== undefined && this.safeNumber(amountLimits, 'max') !== undefined; const hasPriceLimits = priceLimits && this.safeNumber(priceLimits, 'min') !== undefined && this.safeNumber(priceLimits, 'max') !== undefined; const hasCostLimits = costLimits && this.safeNumber(costLimits, 'min') !== undefined && this.safeNumber(costLimits, 'max') !== undefined; if (hasAmountLimits && hasPriceLimits && hasCostLimits) { result[symbol] = { 'info': market, 'limits': { 'amount': { 'min': this.safeNumber(amountLimits, 'min'), 'max': this.safeNumber(amountLimits, 'max'), }, 'price': { 'min': this.safeNumber(priceLimits, 'min'), 'max': this.safeNumber(priceLimits, 'max'), }, 'cost': { 'min': this.safeNumber(costLimits, 'min'), 'max': this.safeNumber(costLimits, 'max'), }, }, }; } } return result; } /** * @method * @name whitebit#fetchFundingLimits * @description fetch the deposit and withdrawal limits for a currency * @see https://docs.whitebit.com/public/http-v4/#asset-status-list * @see https://docs.whitebit.com/public/http-v4/#fee * @param {string[]|undefined} codes unified currency codes * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} a [funding limits structure]{@link https://docs.ccxt.com/#/?id=funding-limits-structure} */ async fetchFundingLimits(codes = undefined, params = {}) { await this.loadMarkets(); // Fetch both currencies and fees data for comprehensive funding limits const [currenciesData, feesData] = await Promise.all([ this.fetchCurrencies(), this.v4PublicGetFee(params), ]); // // Currencies response structure (from fetchCurrencies): // { // "BTC": { // "id": "BTC", // Currency ID // "code": "BTC", // Currency code // "name": "Bitcoin", // Currency name // "active": true, // Currency active status // "type": "crypto", // Currency type // "precision": 8, // Currency precision // "limits": { // Currency limits // "deposit": { // Deposit limits // "min": 0.00001, // Minimum deposit // "max": 1000000 // Maximum deposit // }, // "withdraw": { // Withdrawal limits // "min": 0.00001, // Minimum withdrawal // "max": 1000000 // Maximum withdrawal // } // }, // "networks": { // Network-specific limits // "BTC": { // "limits": { // "deposit": { "min": "0.001" }, // "withdraw": { "min": "0.002" } // } // } // }, // "info": { ... } // Original API response // } // } // // Fees response structure (from /api/v4/public/fee): // { // "USDT (ERC20)": { // "tick