ccxt
Version:
1,147 lines (1,145 loc) • 166 kB
JavaScript
'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