UNPKG

ccxt

Version:

A JavaScript / TypeScript / Python / C# / PHP cryptocurrency trading library with support for 100+ exchanges

1,147 lines (1,145 loc) • 166 kB
'use strict'; var woo$1 = require('./abstract/woo.js'); var errors = require('./base/errors.js'); var Precise = require('./base/Precise.js'); var number = require('./base/functions/number.js'); var sha256 = require('./static_dependencies/noble-hashes/sha256.js'); // ---------------------------------------------------------------------------- // --------------------------------------------------------------------------- /** * @class woo * @augments Exchange */ class woo extends woo$1 { describe() { return this.deepExtend(super.describe(), { 'id': 'woo', 'name': 'WOO X', 'countries': ['KY'], 'rateLimit': 100, 'version': 'v1', 'certified': true, 'pro': true, 'hostname': 'woox.io', 'has': { 'CORS': undefined, 'spot': true, 'margin': true, 'swap': true, 'future': false, 'option': false, 'addMargin': true, 'cancelAllOrders': true, 'cancelAllOrdersAfter': true, 'cancelOrder': true, 'cancelWithdraw': false, 'closeAllPositions': false, 'closePosition': false, 'createConvertTrade': true, 'createDepositAddress': false, 'createMarketBuyOrderWithCost': true, 'createMarketOrder': false, 'createMarketOrderWithCost': false, 'createMarketSellOrderWithCost': true, 'createOrder': true, 'createOrderWithTakeProfitAndStopLoss': true, 'createReduceOnlyOrder': true, 'createStopLimitOrder': false, 'createStopLossOrder': true, 'createStopMarketOrder': false, 'createStopOrder': false, 'createTakeProfitOrder': true, 'createTrailingAmountOrder': true, 'createTrailingPercentOrder': true, 'createTriggerOrder': true, 'fetchAccounts': true, 'fetchBalance': true, 'fetchCanceledOrders': false, 'fetchClosedOrder': false, 'fetchClosedOrders': true, 'fetchConvertCurrencies': true, 'fetchConvertQuote': true, 'fetchConvertTrade': true, 'fetchConvertTradeHistory': true, 'fetchCurrencies': true, 'fetchDepositAddress': true, 'fetchDepositAddresses': false, 'fetchDepositAddressesByNetwork': false, 'fetchDeposits': true, 'fetchDepositsWithdrawals': true, 'fetchFundingHistory': true, 'fetchFundingInterval': true, 'fetchFundingIntervals': false, 'fetchFundingRate': true, 'fetchFundingRateHistory': true, 'fetchFundingRates': true, 'fetchIndexOHLCV': false, 'fetchLedger': true, 'fetchLeverage': true, 'fetchMarginAdjustmentHistory': false, 'fetchMarginMode': false, 'fetchMarkets': true, 'fetchMarkOHLCV': false, 'fetchMyTrades': true, 'fetchOHLCV': true, 'fetchOpenInterestHistory': false, 'fetchOpenOrder': false, 'fetchOpenOrders': true, 'fetchOrder': true, 'fetchOrderBook': true, 'fetchOrders': true, 'fetchOrderTrades': true, 'fetchPosition': true, 'fetchPositionHistory': false, 'fetchPositionMode': false, 'fetchPositions': true, 'fetchPositionsHistory': false, 'fetchPremiumIndexOHLCV': false, 'fetchStatus': true, 'fetchTicker': false, 'fetchTickers': false, 'fetchTime': true, 'fetchTrades': true, 'fetchTradingFee': false, 'fetchTradingFees': true, 'fetchTransactions': 'emulated', 'fetchTransfers': true, 'fetchWithdrawals': true, 'reduceMargin': false, 'sandbox': true, 'setLeverage': true, 'setMargin': false, 'setPositionMode': true, 'transfer': true, 'withdraw': true, // exchange have that endpoint disabled atm, but was once implemented in ccxt per old docs: https://docx.woo.io/wootrade-documents/#token-withdraw }, 'timeframes': { '1m': '1m', '5m': '5m', '15m': '15m', '30m': '30m', '1h': '1h', '4h': '4h', '12h': '12h', '1d': '1d', '1w': '1w', '1M': '1mon', '1y': '1y', }, 'urls': { 'logo': 'https://user-images.githubusercontent.com/1294454/150730761-1a00e5e0-d28c-480f-9e65-089ce3e6ef3b.jpg', 'api': { 'pub': 'https://api-pub.woox.io', 'public': 'https://api.{hostname}', 'private': 'https://api.{hostname}', }, 'test': { 'pub': 'https://api-pub.staging.woox.io', 'public': 'https://api.staging.woox.io', 'private': 'https://api.staging.woox.io', }, 'www': 'https://woox.io/', 'doc': [ 'https://docs.woox.io/', ], 'fees': [ 'https://support.woox.io/hc/en-001/articles/4404611795353--Trading-Fees', ], 'referral': { 'url': 'https://woox.io/register?ref=DIJT0CNL', 'discount': 0.35, }, }, 'api': { 'v1': { 'pub': { 'get': { 'hist/kline': 10, 'hist/trades': 10, }, }, 'public': { 'get': { 'info': 1, 'info/{symbol}': 1, 'system_info': 1, 'market_trades': 1, 'token': 1, 'token_network': 1, 'funding_rates': 1, 'funding_rate/{symbol}': 1, 'funding_rate_history': 1, 'futures': 1, 'futures/{symbol}': 1, 'orderbook/{symbol}': 1, 'kline': 1, }, }, 'private': { 'get': { 'client/token': 1, 'order/{oid}': 1, 'client/order/{client_order_id}': 1, 'orders': 1, 'client/trade/{tid}': 1, 'order/{oid}/trades': 1, 'client/trades': 1, 'client/hist_trades': 1, 'staking/yield_history': 1, 'client/holding': 1, 'asset/deposit': 10, 'asset/history': 60, 'sub_account/all': 60, 'sub_account/assets': 60, 'sub_account/asset_detail': 60, 'sub_account/ip_restriction': 10, 'asset/main_sub_transfer_history': 30, 'token_interest': 60, 'token_interest/{token}': 60, 'interest/history': 60, 'interest/repay': 60, 'funding_fee/history': 30, 'positions': 3.33, 'position/{symbol}': 3.33, 'client/transaction_history': 60, 'client/futures_leverage': 60, }, 'post': { 'order': 1, 'order/cancel_all_after': 1, 'asset/main_sub_transfer': 30, 'asset/ltv': 30, 'asset/withdraw': 30, 'asset/internal_withdraw': 30, 'interest/repay': 60, 'client/account_mode': 120, 'client/position_mode': 5, 'client/leverage': 120, 'client/futures_leverage': 30, 'client/isolated_margin': 30, }, 'delete': { 'order': 1, 'client/order': 1, 'orders': 1, 'asset/withdraw': 120, // implemented in ccxt, disabled on the exchange side https://docx.woo.io/wootrade-documents/#cancel-withdraw-request }, }, }, 'v2': { 'private': { 'get': { 'client/holding': 1, }, }, }, 'v3': { 'public': { 'get': { 'insuranceFund': 3, }, }, 'private': { 'get': { 'algo/order/{oid}': 1, 'algo/orders': 1, 'balances': 1, 'accountinfo': 60, 'positions': 3.33, 'buypower': 1, 'referrals': 60, 'referral_rewards': 60, 'convert/exchangeInfo': 1, 'convert/assetInfo': 1, 'convert/rfq': 60, 'convert/trade': 1, 'convert/trades': 1, }, 'post': { 'algo/order': 5, 'convert/rft': 60, }, 'put': { 'order/{oid}': 2, 'order/client/{client_order_id}': 2, 'algo/order/{oid}': 2, 'algo/order/client/{client_order_id}': 2, }, 'delete': { 'algo/order/{order_id}': 1, 'algo/orders/pending': 1, 'algo/orders/pending/{symbol}': 1, 'orders/pending': 1, }, }, }, }, 'fees': { 'trading': { 'tierBased': true, 'percentage': true, 'maker': this.parseNumber('0.0002'), 'taker': this.parseNumber('0.0005'), }, }, 'options': { 'timeDifference': 0, 'adjustForTimeDifference': false, 'sandboxMode': false, 'createMarketBuyOrderRequiresPrice': true, // these network aliases require manual mapping here 'network-aliases-for-tokens': { 'HT': 'ERC20', 'OMG': 'ERC20', 'UATOM': 'ATOM', 'ZRX': 'ZRX', }, 'networks': { 'TRX': 'TRON', 'TRC20': 'TRON', 'ERC20': 'ETH', 'BEP20': 'BSC', }, // override defaultNetworkCodePriorities for a specific currency 'defaultNetworkCodeForCurrencies': { // 'USDT': 'TRC20', // 'BTC': 'BTC', }, 'transfer': { 'fillResponseFromRequest': true, }, 'brokerId': 'bc830de7-50f3-460b-9ee0-f430f83f9dad', }, 'features': { 'default': { 'sandbox': true, 'createOrder': { 'marginMode': true, 'triggerPrice': true, 'triggerPriceType': { 'last': true, 'mark': true, 'index': false, }, 'triggerDirection': false, 'stopLossPrice': false, 'takeProfitPrice': false, 'attachedStopLossTakeProfit': undefined, 'timeInForce': { 'IOC': true, 'FOK': true, 'PO': true, 'GTD': true, }, 'hedged': false, 'trailing': true, 'leverage': false, 'marketBuyByCost': true, 'marketBuyRequiresPrice': false, 'selfTradePrevention': false, 'iceberg': true, // todo implement }, 'createOrders': undefined, 'fetchMyTrades': { 'marginMode': false, 'limit': 500, 'daysBack': 90, 'untilDays': 10000, 'symbolRequired': false, }, 'fetchOrder': { 'marginMode': false, 'trigger': true, 'trailing': false, 'symbolRequired': false, }, 'fetchOpenOrders': { 'marginMode': false, 'limit': 500, 'trigger': true, 'trailing': true, 'symbolRequired': false, }, 'fetchOrders': { 'marginMode': false, 'limit': 500, 'daysBack': undefined, 'untilDays': 100000, 'trigger': true, 'trailing': true, 'symbolRequired': false, }, 'fetchClosedOrders': { 'marginMode': false, 'limit': 500, 'daysBack': undefined, 'daysBackCanceled': undefined, 'untilDays': 100000, 'trigger': true, 'trailing': true, 'symbolRequired': false, }, 'fetchOHLCV': { 'limit': 1000, }, }, 'spot': { 'extends': 'default', }, 'forSwap': { 'extends': 'default', 'createOrder': { 'hedged': true, }, }, 'swap': { 'linear': { 'extends': 'forSwap', }, 'inverse': undefined, }, 'future': { 'linear': undefined, 'inverse': undefined, }, }, 'commonCurrencies': {}, 'exceptions': { 'exact': { '-1000': errors.OperationFailed, '-1001': errors.AuthenticationError, '-1002': errors.AuthenticationError, '-1003': errors.RateLimitExceeded, '-1004': errors.BadRequest, '-1005': errors.BadRequest, '-1006': errors.BadRequest, '-1007': errors.BadRequest, '-1008': errors.InvalidOrder, '-1009': errors.BadRequest, '-1012': errors.BadRequest, '-1101': errors.InvalidOrder, '-1102': errors.InvalidOrder, '-1103': errors.InvalidOrder, '-1104': errors.InvalidOrder, '-1105': errors.InvalidOrder, // { "code": -1105, "message": "Price is X% too high or X% too low from the mid price." } }, 'broad': { 'Can not place': errors.ExchangeError, 'maintenance': errors.OnMaintenance, 'symbol must not be blank': errors.BadRequest, 'The token is not supported': errors.BadRequest, 'Your order and symbol are not valid or already canceled': errors.BadRequest, 'Insufficient WOO. Please enable margin trading for leverage trading': errors.BadRequest, // when selling insufficent token [-1012] }, }, 'precisionMode': number.TICK_SIZE, }); } /** * @method * @name woo#fetchStatus * @description the latest known information on the availability of the exchange API * @see https://docs.woox.io/#get-system-maintenance-status-public * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} a [status structure]{@link https://docs.ccxt.com/#/?id=exchange-status-structure} */ async fetchStatus(params = {}) { const response = await this.v1PublicGetSystemInfo(params); // // { // "success": true, // "data": { // "status": "0", // "msg": "System is functioning properly." // }, // "timestamp": "1709274106602" // } // const data = this.safeDict(response, 'data', {}); let status = this.safeString(data, 'status'); if (status === undefined) { status = 'error'; } else if (status === '0') { status = 'ok'; } else { status = 'maintenance'; } return { 'status': status, 'updated': undefined, 'eta': undefined, 'url': undefined, 'info': response, }; } /** * @method * @name woo#fetchTime * @description fetches the current integer timestamp in milliseconds from the exchange server * @see https://docs.woox.io/#get-system-maintenance-status-public * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {int} the current integer timestamp in milliseconds from the exchange server */ async fetchTime(params = {}) { const response = await this.v1PublicGetSystemInfo(params); // // { // "success": true, // "data": { // "status": "0", // "msg": "System is functioning properly." // }, // "timestamp": "1709274106602" // } // return this.safeInteger(response, 'timestamp'); } /** * @method * @name woo#fetchMarkets * @description retrieves data on all markets for woo * @see https://docs.woox.io/#exchange-information * @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 response = await this.v1PublicGetInfo(params); // // { // "rows": [ // { // "symbol": "SPOT_AAVE_USDT", // "quote_min": 0, // "quote_max": 100000, // "quote_tick": 0.01, // "base_min": 0.01, // "base_max": 7284, // "base_tick": 0.0001, // "min_notional": 10, // "price_range": 0.1, // "created_time": "0", // "updated_time": "1639107647.988", // "is_stable": 0 // }, // ... // "success": true // } // const data = this.safeList(response, 'rows', []); return this.parseMarkets(data); } parseMarket(market) { const marketId = this.safeString(market, 'symbol'); const parts = marketId.split('_'); const first = this.safeString(parts, 0); let marketType; let spot = false; let swap = false; if (first === 'SPOT') { spot = true; marketType = 'spot'; } else if (first === 'PERP') { swap = true; marketType = 'swap'; } const baseId = this.safeString(parts, 1); const quoteId = this.safeString(parts, 2); const base = this.safeCurrencyCode(baseId); const quote = this.safeCurrencyCode(quoteId); let settleId = undefined; let settle = undefined; let symbol = base + '/' + quote; let contractSize = undefined; let linear = undefined; let margin = true; const contract = swap; if (contract) { margin = false; settleId = this.safeString(parts, 2); settle = this.safeCurrencyCode(settleId); symbol = base + '/' + quote + ':' + settle; contractSize = this.parseNumber('1'); linear = true; } return { 'id': marketId, 'symbol': symbol, 'base': base, 'quote': quote, 'settle': settle, 'baseId': baseId, 'quoteId': quoteId, 'settleId': settleId, 'type': marketType, 'spot': spot, 'margin': margin, 'swap': swap, 'future': false, 'option': false, 'active': this.safeString(market, 'is_trading') === '1', 'contract': contract, 'linear': linear, 'inverse': undefined, 'contractSize': contractSize, 'expiry': undefined, 'expiryDatetime': undefined, 'strike': undefined, 'optionType': undefined, 'precision': { 'amount': this.safeNumber(market, 'base_tick'), 'price': this.safeNumber(market, 'quote_tick'), }, 'limits': { 'leverage': { 'min': undefined, 'max': undefined, }, 'amount': { 'min': this.safeNumber(market, 'base_min'), 'max': this.safeNumber(market, 'base_max'), }, 'price': { 'min': this.safeNumber(market, 'quote_min'), 'max': this.safeNumber(market, 'quote_max'), }, 'cost': { 'min': this.safeNumber(market, 'min_notional'), 'max': undefined, }, }, 'created': this.safeTimestamp(market, 'created_time'), 'info': market, }; } /** * @method * @name woo#fetchTrades * @description get the list of most recent trades for a particular symbol * @see https://docs.woox.io/#market-trades-public * @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 * @param {object} [params] extra parameters specific to the exchange API endpoint * @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.v1PublicGetMarketTrades(this.extend(request, params)); // // { // "success": true, // "rows": [ // { // "symbol": "SPOT_BTC_USDT", // "side": "SELL", // "executed_price": 46222.35, // "executed_quantity": 0.0012, // "executed_timestamp": "1641241162.329" // }, // { // "symbol": "SPOT_BTC_USDT", // "side": "SELL", // "executed_price": 46222.35, // "executed_quantity": 0.0012, // "executed_timestamp": "1641241162.329" // }, // { // "symbol": "SPOT_BTC_USDT", // "side": "BUY", // "executed_price": 46224.32, // "executed_quantity": 0.00039, // "executed_timestamp": "1641241162.287" // }, // ... // ] // } // const resultResponse = this.safeList(response, 'rows', []); return this.parseTrades(resultResponse, market, since, limit); } parseTrade(trade, market = undefined) { // // public/market_trades // // { // "symbol": "SPOT_BTC_USDT", // "side": "SELL", // "executed_price": 46222.35, // "executed_quantity": 0.0012, // "executed_timestamp": "1641241162.329" // } // // fetchOrderTrades, fetchOrder // // { // "id": "99119876", // "symbol": "SPOT_WOO_USDT", // "fee": "0.0024", // "side": "BUY", // "executed_timestamp": "1641481113.084", // "order_id": "87001234", // "order_tag": "default", <-- this param only in "fetchOrderTrades" // "executed_price": "1", // "executed_quantity": "12", // "fee_asset": "WOO", // "is_maker": "1" // } // const isFromFetchOrder = ('id' in trade); const timestamp = this.safeTimestamp(trade, 'executed_timestamp'); const marketId = this.safeString(trade, 'symbol'); market = this.safeMarket(marketId, market); const symbol = market['symbol']; const price = this.safeString(trade, 'executed_price'); const amount = this.safeString(trade, 'executed_quantity'); const order_id = this.safeString(trade, 'order_id'); const fee = this.parseTokenAndFeeTemp(trade, 'fee_asset', 'fee'); const feeCost = this.safeString(fee, 'cost'); if (feeCost !== undefined) { fee['cost'] = feeCost; } const cost = Precise["default"].stringMul(price, amount); const side = this.safeStringLower(trade, 'side'); const id = this.safeString(trade, 'id'); let takerOrMaker = undefined; if (isFromFetchOrder) { const isMaker = this.safeString(trade, 'is_maker') === '1'; takerOrMaker = isMaker ? 'maker' : 'taker'; } return this.safeTrade({ 'id': id, 'timestamp': timestamp, 'datetime': this.iso8601(timestamp), 'symbol': symbol, 'side': side, 'price': price, 'amount': amount, 'cost': cost, 'order': order_id, 'takerOrMaker': takerOrMaker, 'type': undefined, 'fee': fee, 'info': trade, }, market); } parseTokenAndFeeTemp(item, feeTokenKey, feeAmountKey) { const feeCost = this.safeString(item, feeAmountKey); let fee = undefined; if (feeCost !== undefined) { const feeCurrencyId = this.safeString(item, feeTokenKey); const feeCurrencyCode = this.safeCurrencyCode(feeCurrencyId); fee = { 'cost': feeCost, 'currency': feeCurrencyCode, }; } return fee; } /** * @method * @name woo#fetchTradingFees * @description fetch the trading fees for multiple markets * @see https://docs.woox.io/#get-account-information-new * @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.v3PrivateGetAccountinfo(params); // // { // "success": true, // "data": { // "applicationId": "dsa", // "account": "dsa", // "alias": "haha", // "accountMode": "MARGIN", // "leverage": 1, // "takerFeeRate": 1, // "makerFeeRate": 1, // "interestRate": 1, // "futuresTakerFeeRate": 1, // "futuresMakerFeeRate": 1, // "otpauth": true, // "marginRatio": 1, // "openMarginRatio": 1, // "initialMarginRatio": 1, // "maintenanceMarginRatio": 1, // "totalCollateral": 1, // "freeCollateral": 1, // "totalAccountValue": 1, // "totalVaultValue": 1, // "totalStakingValue": 1 // }, // "timestamp": 1673323685109 // } // const data = this.safeDict(response, 'data', {}); const maker = this.safeString(data, 'makerFeeRate'); const taker = this.safeString(data, 'takerFeeRate'); const result = {}; for (let i = 0; i < this.symbols.length; i++) { const symbol = this.symbols[i]; result[symbol] = { 'info': response, 'symbol': symbol, 'maker': this.parseNumber(Precise["default"].stringDiv(maker, '10000')), 'taker': this.parseNumber(Precise["default"].stringDiv(taker, '10000')), 'percentage': true, 'tierBased': true, }; } return result; } /** * @method * @name woo#fetchCurrencies * @description fetches all available currencies on an exchange * @see https://docs.woox.io/#available-token-public * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} an associative dictionary of currencies */ async fetchCurrencies(params = {}) { const result = {}; const tokenResponse = await this.v1PublicGetToken(params); // // { // "rows": [ // { // "token": "ETH_USDT", // "fullname": "Tether", // "decimals": 6, // "balance_token": "USDT", // "created_time": "0", // "updated_time": "0" // }, // { // "token": "BSC_USDT", // "fullname": "Tether", // "decimals": 18, // "balance_token": "USDT", // "created_time": "0", // "updated_time": "0" // }, // { // "token": "ZEC", // "fullname": "ZCash", // "decimals": 8, // "balance_token": "ZEC", // "created_time": "0", // "updated_time": "0" // }, // ... // ], // "success": true // } // // only make one request for currrencies... // const tokenNetworkResponse = await this.v1PublicGetTokenNetwork (params); // // { // "rows": [ // { // "protocol": "ERC20", // "token": "USDT", // "name": "Ethereum", // "minimum_withdrawal": 30, // "withdrawal_fee": 25, // "allow_deposit": 1, // "allow_withdraw": 1 // }, // { // "protocol": "TRC20", // "token": "USDT", // "name": "Tron", // "minimum_withdrawal": 30, // "withdrawal_fee": 1, // "allow_deposit": 1, // "allow_withdraw": 1 // }, // ... // ], // "success": true // } // const tokenRows = this.safeList(tokenResponse, 'rows', []); const networksByCurrencyId = this.groupBy(tokenRows, 'balance_token'); const currencyIds = Object.keys(networksByCurrencyId); for (let i = 0; i < currencyIds.length; i++) { const currencyId = currencyIds[i]; const networks = networksByCurrencyId[currencyId]; const code = this.safeCurrencyCode(currencyId); let name = undefined; let minPrecision = undefined; const resultingNetworks = {}; for (let j = 0; j < networks.length; j++) { const network = networks[j]; name = this.safeString(network, 'fullname'); const networkId = this.safeString(network, 'token'); const splitted = networkId.split('_'); const unifiedNetwork = splitted[0]; const precision = this.parsePrecision(this.safeString(network, 'decimals')); if (precision !== undefined) { minPrecision = (minPrecision === undefined) ? precision : Precise["default"].stringMin(precision, minPrecision); } resultingNetworks[unifiedNetwork] = { 'id': networkId, 'network': unifiedNetwork, 'limits': { 'withdraw': { 'min': undefined, 'max': undefined, }, 'deposit': { 'min': undefined, 'max': undefined, }, }, 'active': undefined, 'deposit': undefined, 'withdraw': undefined, 'fee': undefined, 'precision': this.parseNumber(precision), 'info': network, }; } result[code] = { 'id': currencyId, 'name': name, 'code': code, 'precision': this.parseNumber(minPrecision), 'active': undefined, 'fee': undefined, 'networks': resultingNetworks, 'deposit': undefined, 'withdraw': undefined, 'limits': { 'deposit': { 'min': undefined, 'max': undefined, }, 'withdraw': { 'min': undefined, 'max': undefined, }, }, 'info': networks, }; } return result; } /** * @method * @name woo#createMarketBuyOrderWithCost * @description create a market buy order by providing the symbol and cost * @see https://docs.woox.io/#send-order * @param {string} symbol unified symbol of the market to create an order in * @param {float} cost how much you want to trade in units of the quote currency * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure} */ async createMarketBuyOrderWithCost(symbol, cost, params = {}) { await this.loadMarkets(); const market = this.market(symbol); if (!market['spot']) { throw new errors.NotSupported(this.id + ' createMarketBuyOrderWithCost() supports spot orders only'); } return await this.createOrder(symbol, 'market', 'buy', cost, 1, params); } /** * @method * @name woo#createMarketSellOrderWithCost * @description create a market sell order by providing the symbol and cost * @see https://docs.woox.io/#send-order * @param {string} symbol unified symbol of the market to create an order in * @param {float} cost how much you want to trade in units of the quote currency * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure} */ async createMarketSellOrderWithCost(symbol, cost, params = {}) { await this.loadMarkets(); const market = this.market(symbol); if (!market['spot']) { throw new errors.NotSupported(this.id + ' createMarketSellOrderWithCost() supports spot orders only'); } return await this.createOrder(symbol, 'market', 'sell', cost, 1, params); } /** * @method * @name woo#createTrailingAmountOrder * @description create a trailing order by providing the symbol, type, side, amount, price and trailingAmount * @see https://docs.woox.io/#send-algo-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 you want to trade in units of the base currency, or number of contracts * @param {float} [price] the price for the order to be filled at, in units of the quote currency, ignored in market orders * @param {float} trailingAmount the quote amount to trail away from the current market price * @param {float} trailingTriggerPrice the price to activate a trailing order, default uses the price argument * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure} */ async createTrailingAmountOrder(symbol, type, side, amount, price = undefined, trailingAmount = undefined, trailingTriggerPrice = undefined, params = {}) { if (trailingAmount === undefined) { throw new errors.ArgumentsRequired(this.id + ' createTrailingAmountOrder() requires a trailingAmount argument'); } if (trailingTriggerPrice === undefined) { throw new errors.ArgumentsRequired(this.id + ' createTrailingAmountOrder() requires a trailingTriggerPrice argument'); } params['trailingAmount'] = trailingAmount; params['trailingTriggerPrice'] = trailingTriggerPrice; return await this.createOrder(symbol, type, side, amount, price, params); } /** * @method * @name woo#createTrailingPercentOrder * @description create a trailing order by providing the symbol, type, side, amount, price and trailingPercent * @see https://docs.woox.io/#send-algo-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 you want to trade in units of the base currency, or number of contracts * @param {float} [price] the price for the order to be filled at, in units of the quote currency, ignored in market orders * @param {float} trailingPercent the percent to trail away from the current market price * @param {float} trailingTriggerPrice the price to activate a trailing order, default uses the price argument * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure} */ async createTrailingPercentOrder(symbol, type, side, amount, price = undefined, trailingPercent = undefined, trailingTriggerPrice = undefined, params = {}) { if (trailingPercent === undefined) { throw new errors.ArgumentsRequired(this.id + ' createTrailingPercentOrder() requires a trailingPercent argument'); } if (trailingTriggerPrice === undefined) { throw new errors.ArgumentsRequired(this.id + ' createTrailingPercentOrder() requires a trailingTriggerPrice argument'); } params['trailingPercent'] = trailingPercent; params['trailingTriggerPrice'] = trailingTriggerPrice; return await this.createOrder(symbol, type, side, amount, price, params); } /** * @method * @name woo#createOrder * @description create a trade order * @see https://docs.woox.io/#send-order * @see https://docs.woox.io/#send-algo-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 fulfilled, in units of the quote currency, ignored in market orders * @param {object} [params] extra parameters specific to the exchange API endpoint * @param {string} [params.marginMode] *for swap markets only* 'cross' or 'isolated', default 'cross' * @param {float} [params.triggerPrice] The price a trigger order is triggered at * @param {object} [params.takeProfit] *takeProfit object in params* containing the triggerPrice at which the attached take profit order will be triggered (perpetual swap markets only) * @param {float} [params.takeProfit.triggerPrice] take profit trigger price * @param {object} [params.stopLoss] *stopLoss object in params* containing the triggerPrice at which the attached stop loss order will be triggered (perpetual swap markets only) * @param {float} [params.stopLoss.triggerPrice] stop loss trigger price * @param {float} [params.algoType] 'STOP' or 'TRAILING_STOP' or 'OCO' or 'CLOSE_POSITION' * @param {float} [params.cost] *spot market buy only* the quote quantity that can be used as an alternative for the amount * @param {string} [params.trailingAmount] the quote amount to trail away from the current market price * @param {string} [params.trailingPercent] the percent to trail away from the current market price * @param {string} [params.trailingTriggerPrice] the price to trigger a trailing order, default uses the price argument * @param {string} [params.position_side] 'SHORT' or 'LONG' - if position mode is HEDGE_MODE and the trading involves futures, then is required, otherwise this parameter is not required * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure} */ async createOrder(symbol, type, side, amount, price = undefined, params = {}) { const reduceOnly = this.safeBool2(params, 'reduceOnly', 'reduce_only'); params = this.omit(params, ['reduceOnly', 'reduce_only']); const orderType = type.toUpperCase(); await this.loadMarkets(); const market = this.market(symbol); const orderSide = side.toUpperCase(); const request = { 'symbol': market['id'], 'side': orderSide, }; let marginMode = undefined; [marginMode, params] = this.handleMarginModeAndParams('createOrder', params); if (marginMode !== undefined) { request['margin_mode'] = this.encodeMarginMode(marginMode); } const triggerPrice = this.safeString2(params, 'triggerPrice', 'stopPrice'); const stopLoss = this.safeValue(params, 'stopLoss'); const takeProfit = this.safeValue(params, 'takeProfit'); const algoType = this.safeString(params, 'algoType'); const trailingTriggerPrice = this.safeString2(params, 'trailingTriggerPrice', 'activatedPrice', this.numberToString(price)); const trailingAmount = this.safeString2(params, 'trailingAmount', 'callbackValue'); const trailingPercent = this.safeString2(params, 'trailingPercent', 'callbackRate'); const isTrailingAmountOrder = trailingAmount !== undefined; const isTrailingPercentOrder = trailingPercent !== undefined; const isTrailing = isTrailingAmountOrder || isTrailingPercentOrder; const isConditional = isTrailing || triggerPrice !== undefined || stopLoss !== undefined || takeProfit !== undefined || (this.safeValue(params, 'childOrders') !== undefined); const isMarket = orderType === 'MARKET'; const timeInForce = this.safeStringLower(params, 'timeInForce'); const postOnly = this.isPostOnly(isMarket, undefined, params); const reduceOnlyKey = isConditional ? 'reduceOnly' : 'reduce_only'; const clientOrderIdKey = isConditional ? 'clientOrderId' : 'client_order_id'; const orderQtyKey = isConditional ? 'quantity' : 'order_quantity'; const priceKey = isConditional ? 'price' : 'order_price'; const typeKey = isConditional ? 'type' : 'order_type'; request[typeKey] = orderType; // LIMIT/MARKET/IOC/FOK/POST_ONLY/ASK/BID if (!isConditional) { if (postOnly) { request['order_type'] = 'POST_ONLY'; } else if (timeInForce === 'fok') { request['order_type'] = 'FOK'; } else if (timeInForce === 'ioc') { request['order_type'] = 'IOC'; } } if (reduceOnly) { request[reduceOnlyKey] = reduceOnly; } if (!isMarket && price !== undefined) { request[priceKey] = this.priceToPrecision(symbol, price); } if (isMarket && !isConditional) { // for market buy it requires the amount of quote currency to spend const cost = this.safeString2(params, 'cost', 'order_amount'); params = this.omit(params, ['cost', 'order_amount']); const isPriceProvided = price !== undefined; if (market['spot'] && (isPriceProvided || (cost !== undefined))) { let quoteAmount = undefined; if (cost !== undefined) { quoteAmount = this.costToPrecision(symbol, cost); } else { const amountString = this.numberToString(amount); const priceString = this.numberToString(price); const costRequest = Precise["default"].stringMul(amountString, priceString); quoteAmount = this.costToPrecision(symbol, costRequest); } request['order_amount'] = quoteAmount; } else { request['order_quantity'] = this.amountToPrecision(symbol, amount); } } else if (algoType !== 'POSITIONAL_TP_SL') { request[orderQtyKey] = this.amountToPrecision(symbol, amount); } const clientOrderId = this.safeStringN(params, ['clOrdID', 'clientOrderId', 'client_order_id']); if (clientOrderId !== undefined) { request[clientOrderIdKey] = clientOrderId; } if (isTrailing) { if (trailingTriggerPrice === undefined) { throw new errors.ArgumentsRequired(this.id + ' createOrder() requires a trailingTriggerPrice parameter for trailing orders'); } request['activatedPrice'] = this.priceToPrecision(symbol, trailingTriggerPrice); request['algoType'] = 'TRAILING