UNPKG

sfccxt

Version:

A JavaScript / Python / PHP cryptocurrency trading library with support for 130+ exchanges

1,159 lines (1,130 loc) 67.4 kB
'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, AuthenticationError, InsufficientFunds, PermissionDenied, BadRequest, BadSymbol, RateLimitExceeded, InvalidOrder } = require ('./base/errors'); const { TICK_SIZE } = require ('./base/functions/number'); // --------------------------------------------------------------------------- module.exports = class bigone extends Exchange { describe () { return this.deepExtend (super.describe (), { 'id': 'bigone', 'name': 'BigONE', 'countries': [ 'CN' ], 'version': 'v3', 'rateLimit': 1200, // 500 request per 10 minutes 'has': { 'CORS': undefined, 'spot': true, 'margin': undefined, // has but unimplemented 'swap': undefined, // has but unimplemented 'future': undefined, // has but unimplemented 'option': undefined, 'cancelAllOrders': true, 'cancelOrder': true, 'createOrder': true, 'createStopLimitOrder': true, 'createStopMarketOrder': true, 'createStopOrder': true, 'fetchBalance': true, 'fetchClosedOrders': true, 'fetchDepositAddress': true, 'fetchDeposits': true, 'fetchMarkets': true, 'fetchMyTrades': true, 'fetchOHLCV': true, 'fetchOpenOrders': true, 'fetchOrder': true, 'fetchOrderBook': true, 'fetchOrders': true, 'fetchTicker': true, 'fetchTickers': true, 'fetchTime': true, 'fetchTrades': true, 'fetchTradingFee': false, 'fetchTradingFees': false, 'fetchTransactionFees': false, 'fetchWithdrawals': true, 'transfer': true, 'withdraw': true, }, 'timeframes': { '1m': 'min1', '5m': 'min5', '15m': 'min15', '30m': 'min30', '1h': 'hour1', '3h': 'hour3', '4h': 'hour4', '6h': 'hour6', '12h': 'hour12', '1d': 'day1', '1w': 'week1', '1M': 'month1', }, 'hostname': 'big.one', // or 'bigone.com' 'urls': { 'logo': 'https://user-images.githubusercontent.com/1294454/69354403-1d532180-0c91-11ea-88ed-44c06cefdf87.jpg', 'api': { 'public': 'https://{hostname}/api/v3', 'private': 'https://{hostname}/api/v3/viewer', }, 'www': 'https://big.one', 'doc': 'https://open.big.one/docs/api.html', 'fees': 'https://bigone.zendesk.com/hc/en-us/articles/115001933374-BigONE-Fee-Policy', 'referral': 'https://b1.run/users/new?code=D3LLBVFT', }, 'api': { 'public': { 'get': [ 'ping', 'asset_pairs', 'asset_pairs/{asset_pair_name}/depth', 'asset_pairs/{asset_pair_name}/trades', 'asset_pairs/{asset_pair_name}/ticker', 'asset_pairs/{asset_pair_name}/candles', 'asset_pairs/tickers', ], }, 'private': { 'get': [ 'accounts', 'fund/accounts', 'assets/{asset_symbol}/address', 'orders', 'orders/{id}', 'orders/multi', 'trades', 'withdrawals', 'deposits', ], 'post': [ 'orders', 'orders/{id}/cancel', 'orders/cancel', 'withdrawals', 'transfer', ], }, }, 'fees': { 'trading': { 'maker': this.parseNumber ('0.001'), 'taker': this.parseNumber ('0.001'), }, 'funding': { 'withdraw': {}, }, }, 'options': { 'accountsByType': { 'spot': 'SPOT', 'funding': 'FUND', 'future': 'CONTRACT', 'swap': 'CONTRACT', }, 'transfer': { 'fillResponseFromRequest': true, }, 'exchangeMillisecondsCorrection': -100, }, 'precisionMode': TICK_SIZE, 'exceptions': { 'exact': { '10001': BadRequest, // syntax error '10005': ExchangeError, // internal error "Amount's scale must greater than AssetPair's base scale": InvalidOrder, "Price mulit with amount should larger than AssetPair's min_quote_value": InvalidOrder, '10007': BadRequest, // parameter error, {"code":10007,"message":"Amount's scale must greater than AssetPair's base scale"} '10011': ExchangeError, // system error '10013': BadSymbol, // {"code":10013,"message":"Resource not found"} '10014': InsufficientFunds, // {"code":10014,"message":"Insufficient funds"} '10403': PermissionDenied, // permission denied '10429': RateLimitExceeded, // too many requests '40004': AuthenticationError, // {"code":40004,"message":"invalid jwt"} '40103': AuthenticationError, // invalid otp code '40104': AuthenticationError, // invalid asset pin code '40301': PermissionDenied, // {"code":40301,"message":"Permission denied withdrawal create"} '40302': ExchangeError, // already requested '40601': ExchangeError, // resource is locked '40602': ExchangeError, // resource is depleted '40603': InsufficientFunds, // insufficient resource '40604': InvalidOrder, // {"code":40604,"message":"Price exceed the maximum order price"} '40605': InvalidOrder, // {"code":40605,"message":"Price less than the minimum order price"} '40120': InvalidOrder, // Order is in trading '40121': InvalidOrder, // Order is already cancelled or filled '60100': BadSymbol, // {"code":60100,"message":"Asset pair is suspended"} }, 'broad': { }, }, 'commonCurrencies': { 'CRE': 'Cybereits', 'FXT': 'FXTTOKEN', 'FREE': 'FreeRossDAO', 'MBN': 'Mobilian Coin', 'ONE': 'BigONE Token', }, }); } async fetchMarkets (params = {}) { /** * @method * @name bigone#fetchMarkets * @description retrieves data on all markets for bigone * @param {object} params extra parameters specific to the exchange api endpoint * @returns {[object]} an array of objects representing market data */ const response = await this.publicGetAssetPairs (params); // // { // "code":0, // "data":[ // { // "id":"01e48809-b42f-4a38-96b1-c4c547365db1", // "name":"PCX-BTC", // "quote_scale":7, // "quote_asset":{ // "id":"0df9c3c3-255a-46d7-ab82-dedae169fba9", // "symbol":"BTC", // "name":"Bitcoin", // }, // "base_asset":{ // "id":"405484f7-4b03-4378-a9c1-2bd718ecab51", // "symbol":"PCX", // "name":"ChainX", // }, // "base_scale":3, // "min_quote_value":"0.0001", // "max_quote_value":"35" // }, // ] // } // const markets = this.safeValue (response, 'data', []); const result = []; for (let i = 0; i < markets.length; i++) { const market = markets[i]; const id = this.safeString (market, 'name'); const uuid = this.safeString (market, 'id'); const baseAsset = this.safeValue (market, 'base_asset', {}); const quoteAsset = this.safeValue (market, 'quote_asset', {}); const baseId = this.safeString (baseAsset, 'symbol'); const quoteId = this.safeString (quoteAsset, 'symbol'); const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); const entry = { 'id': id, 'uuid': uuid, 'symbol': base + '/' + quote, 'base': base, 'quote': quote, 'settle': undefined, 'baseId': baseId, 'quoteId': quoteId, 'settleId': undefined, 'type': 'spot', 'spot': true, 'margin': false, 'swap': false, 'future': false, 'option': false, 'active': true, 'contract': false, 'linear': undefined, 'inverse': undefined, 'contractSize': undefined, 'expiry': undefined, 'expiryDatetime': undefined, 'strike': undefined, 'optionType': undefined, 'precision': { 'amount': this.parseNumber (this.parsePrecision (this.safeString (market, 'base_scale'))), 'price': this.parseNumber (this.parsePrecision (this.safeString (market, 'quote_scale'))), }, 'limits': { 'leverage': { 'min': undefined, 'max': undefined, }, 'amount': { 'min': undefined, 'max': undefined, }, 'price': { 'min': undefined, 'max': undefined, }, 'cost': { 'min': this.safeNumber (market, 'min_quote_value'), 'max': this.safeNumber (market, 'max_quote_value'), }, }, 'info': market, }; result.push (entry); } return result; } async loadMarkets (reload = false, params = {}) { const markets = await super.loadMarkets (reload, params); let marketsByUuid = this.safeValue (this.options, 'marketsByUuid'); if ((marketsByUuid === undefined) || reload) { marketsByUuid = {}; for (let i = 0; i < this.symbols.length; i++) { const symbol = this.symbols[i]; const market = this.markets[symbol]; const uuid = this.safeString (market, 'uuid'); marketsByUuid[uuid] = market; } this.options['marketsByUuid'] = marketsByUuid; } return markets; } parseTicker (ticker, market = undefined) { // // { // "asset_pair_name":"ETH-BTC", // "bid":{"price":"0.021593","order_count":1,"quantity":"0.20936"}, // "ask":{"price":"0.021613","order_count":1,"quantity":"2.87064"}, // "open":"0.021795", // "high":"0.021795", // "low":"0.021471", // "close":"0.021613", // "volume":"117078.90431", // "daily_change":"-0.000182" // } // const marketId = this.safeString (ticker, 'asset_pair_name'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = undefined; const close = this.safeString (ticker, 'close'); const bid = this.safeValue (ticker, 'bid', {}); const ask = this.safeValue (ticker, 'ask', {}); return this.safeTicker ({ 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'high': this.safeString (ticker, 'high'), 'low': this.safeString (ticker, 'low'), 'bid': this.safeString (bid, 'price'), 'bidVolume': this.safeString (bid, 'quantity'), 'ask': this.safeString (ask, 'price'), 'askVolume': this.safeString (ask, 'quantity'), 'vwap': undefined, 'open': this.safeString (ticker, 'open'), 'close': close, 'last': close, 'previousClose': undefined, 'change': this.safeString (ticker, 'daily_change'), 'percentage': undefined, 'average': undefined, 'baseVolume': this.safeString (ticker, 'volume'), 'quoteVolume': undefined, 'info': ticker, }, market); } async fetchTicker (symbol, params = {}) { /** * @method * @name bigone#fetchTicker * @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market * @param {string} symbol unified symbol of the market to fetch the ticker for * @param {object} params extra parameters specific to the bigone api endpoint * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/en/latest/manual.html#ticker-structure} */ await this.loadMarkets (); const market = this.market (symbol); const request = { 'asset_pair_name': market['id'], }; const response = await this.publicGetAssetPairsAssetPairNameTicker (this.extend (request, params)); // // { // "code":0, // "data":{ // "asset_pair_name":"ETH-BTC", // "bid":{"price":"0.021593","order_count":1,"quantity":"0.20936"}, // "ask":{"price":"0.021613","order_count":1,"quantity":"2.87064"}, // "open":"0.021795", // "high":"0.021795", // "low":"0.021471", // "close":"0.021613", // "volume":"117078.90431", // "daily_change":"-0.000182" // } // } // const ticker = this.safeValue (response, 'data', {}); return this.parseTicker (ticker, market); } async fetchTickers (symbols = undefined, params = {}) { /** * @method * @name bigone#fetchTickers * @description fetches price tickers for multiple markets, statistical calculations with the information calculated over the past 24 hours each market * @param {[string]|undefined} symbols unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned * @param {object} params extra parameters specific to the bigone api endpoint * @returns {object} an array of [ticker structures]{@link https://docs.ccxt.com/en/latest/manual.html#ticker-structure} */ await this.loadMarkets (); const request = {}; symbols = this.marketSymbols (symbols); if (symbols !== undefined) { const ids = this.marketIds (symbols); request['pair_names'] = ids.join (','); } const response = await this.publicGetAssetPairsTickers (this.extend (request, params)); // // { // "code":0, // "data":[ // { // "asset_pair_name":"PCX-BTC", // "bid":{"price":"0.000234","order_count":1,"quantity":"0.518"}, // "ask":{"price":"0.0002348","order_count":1,"quantity":"2.348"}, // "open":"0.0002343", // "high":"0.0002348", // "low":"0.0002162", // "close":"0.0002348", // "volume":"12887.016", // "daily_change":"0.0000005" // }, // { // "asset_pair_name":"GXC-USDT", // "bid":{"price":"0.5054","order_count":1,"quantity":"40.53"}, // "ask":{"price":"0.5055","order_count":1,"quantity":"38.53"}, // "open":"0.5262", // "high":"0.5323", // "low":"0.5055", // "close":"0.5055", // "volume":"603963.05", // "daily_change":"-0.0207" // } // ] // } // const tickers = this.safeValue (response, 'data', []); const result = {}; for (let i = 0; i < tickers.length; i++) { const ticker = this.parseTicker (tickers[i]); const symbol = ticker['symbol']; result[symbol] = ticker; } return this.filterByArray (result, 'symbol', symbols); } async fetchTime (params = {}) { /** * @method * @name bigone#fetchTime * @description fetches the current integer timestamp in milliseconds from the exchange server * @param {object} params extra parameters specific to the bigone api endpoint * @returns {int} the current integer timestamp in milliseconds from the exchange server */ const response = await this.publicGetPing (params); // // { // "data": { // "timestamp": 1527665262168391000 // } // } // const data = this.safeValue (response, 'data', {}); const timestamp = this.safeInteger (data, 'timestamp'); return parseInt (timestamp / 1000000); } async fetchOrderBook (symbol, limit = undefined, params = {}) { /** * @method * @name bigone#fetchOrderBook * @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data * @param {string} symbol unified symbol of the market to fetch the order book for * @param {int|undefined} limit the maximum amount of order book entries to return * @param {object} params extra parameters specific to the bigone api endpoint * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/en/latest/manual.html#order-book-structure} indexed by market symbols */ await this.loadMarkets (); const market = this.market (symbol); const request = { 'asset_pair_name': market['id'], }; if (limit !== undefined) { request['limit'] = limit; // default 50, max 200 } const response = await this.publicGetAssetPairsAssetPairNameDepth (this.extend (request, params)); // // { // "code":0, // "data": { // "asset_pair_name": "EOS-BTC", // "bids": [ // { "price": "42", "order_count": 4, "quantity": "23.33363711" } // ], // "asks": [ // { "price": "45", "order_count": 2, "quantity": "4193.3283464" } // ] // } // } // const orderbook = this.safeValue (response, 'data', {}); return this.parseOrderBook (orderbook, market['symbol'], undefined, 'bids', 'asks', 'price', 'quantity'); } parseTrade (trade, market = undefined) { // // fetchTrades (public) // // { // "id": 38199941, // "price": "3378.67", // "amount": "0.019812", // "taker_side": "ASK", // "created_at": "2019-01-29T06:05:56Z" // } // // fetchMyTrades (private) // // { // "id": 10854280, // "asset_pair_name": "XIN-USDT", // "price": "70", // "amount": "1", // "taker_side": "ASK", // "maker_order_id": 58284908, // "taker_order_id": 58284909, // "maker_fee": "0.0008", // "taker_fee": "0.07", // "side": "SELF_TRADING", // "inserted_at": "2019-04-16T12:00:01Z" // }, // // { // "id": 10854263, // "asset_pair_name": "XIN-USDT", // "price": "75.7", // "amount": "12.743149", // "taker_side": "BID", // "maker_order_id": null, // "taker_order_id": 58284888, // "maker_fee": null, // "taker_fee": "0.0025486298", // "side": "BID", // "inserted_at": "2019-04-15T06:20:57Z" // } // const timestamp = this.parse8601 (this.safeString2 (trade, 'created_at', 'inserted_at')); const priceString = this.safeString (trade, 'price'); const amountString = this.safeString (trade, 'amount'); const marketId = this.safeString (trade, 'asset_pair_name'); market = this.safeMarket (marketId, market, '-'); let side = this.safeString (trade, 'side'); const takerSide = this.safeString (trade, 'taker_side'); let takerOrMaker = undefined; if ((takerSide !== undefined) && (side !== undefined) && (side !== 'SELF_TRADING')) { takerOrMaker = (takerSide === side) ? 'taker' : 'maker'; } if (side === undefined) { // taker side is not related to buy/sell side // the following code is probably a mistake side = (takerSide === 'ASK') ? 'sell' : 'buy'; } else { if (side === 'BID') { side = 'buy'; } else if (side === 'ASK') { side = 'sell'; } } const makerOrderId = this.safeString (trade, 'maker_order_id'); const takerOrderId = this.safeString (trade, 'taker_order_id'); let orderId = undefined; if (makerOrderId !== undefined) { if (takerOrderId !== undefined) { orderId = [ makerOrderId, takerOrderId ]; } else { orderId = makerOrderId; } } else if (takerOrderId !== undefined) { orderId = takerOrderId; } const id = this.safeString (trade, 'id'); const result = { 'id': id, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'symbol': market['symbol'], 'order': orderId, 'type': 'limit', 'side': side, 'takerOrMaker': takerOrMaker, 'price': priceString, 'amount': amountString, 'cost': undefined, 'info': trade, }; let makerCurrencyCode = undefined; let takerCurrencyCode = undefined; if (takerOrMaker !== undefined) { if (side === 'buy') { if (takerOrMaker === 'maker') { makerCurrencyCode = market['base']; takerCurrencyCode = market['quote']; } else { makerCurrencyCode = market['quote']; takerCurrencyCode = market['base']; } } else { if (takerOrMaker === 'maker') { makerCurrencyCode = market['quote']; takerCurrencyCode = market['base']; } else { makerCurrencyCode = market['base']; takerCurrencyCode = market['quote']; } } } else if (side === 'SELF_TRADING') { if (takerSide === 'BID') { makerCurrencyCode = market['quote']; takerCurrencyCode = market['base']; } else if (takerSide === 'ASK') { makerCurrencyCode = market['base']; takerCurrencyCode = market['quote']; } } const makerFeeCost = this.safeString (trade, 'maker_fee'); const takerFeeCost = this.safeString (trade, 'taker_fee'); if (makerFeeCost !== undefined) { if (takerFeeCost !== undefined) { result['fees'] = [ { 'cost': makerFeeCost, 'currency': makerCurrencyCode }, { 'cost': takerFeeCost, 'currency': takerCurrencyCode }, ]; } else { result['fee'] = { 'cost': makerFeeCost, 'currency': makerCurrencyCode }; } } else if (takerFeeCost !== undefined) { result['fee'] = { 'cost': takerFeeCost, 'currency': takerCurrencyCode }; } else { result['fee'] = undefined; } return this.safeTrade (result, market); } async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { /** * @method * @name bigone#fetchTrades * @description get the list of most recent trades for a particular symbol * @param {string} symbol unified symbol of the market to fetch trades for * @param {int|undefined} since timestamp in ms of the earliest trade to fetch * @param {int|undefined} limit the maximum amount of trades to fetch * @param {object} params extra parameters specific to the bigone api endpoint * @returns {[object]} a list of [trade structures]{@link https://docs.ccxt.com/en/latest/manual.html?#public-trades} */ await this.loadMarkets (); const market = this.market (symbol); const request = { 'asset_pair_name': market['id'], }; const response = await this.publicGetAssetPairsAssetPairNameTrades (this.extend (request, params)); // // { // "code": 0, // "data": [ // { // "id": 38199941, // "price": "3378.67", // "amount": "0.019812", // "taker_side": "ASK", // "created_at": "2019-01-29T06:05:56Z" // }, // { // "id": 38199934, // "price": "3376.14", // "amount": "0.019384", // "taker_side": "ASK", // "created_at": "2019-01-29T06:05:40Z" // } // ] // } // const trades = this.safeValue (response, 'data', []); return this.parseTrades (trades, market, since, limit); } parseOHLCV (ohlcv, market = undefined) { // // { // close: '0.021562', // high: '0.021563', // low: '0.02156', // open: '0.021563', // time: '2019-11-21T07:54:00Z', // volume: '59.84376' // } // return [ this.parse8601 (this.safeString (ohlcv, 'time')), this.safeNumber (ohlcv, 'open'), this.safeNumber (ohlcv, 'high'), this.safeNumber (ohlcv, 'low'), this.safeNumber (ohlcv, 'close'), this.safeNumber (ohlcv, 'volume'), ]; } async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) { /** * @method * @name bigone#fetchOHLCV * @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market * @param {string} symbol unified symbol of the market to fetch OHLCV data for * @param {string} timeframe the length of time each candle represents * @param {int|undefined} since timestamp in ms of the earliest candle to fetch * @param {int|undefined} limit the maximum amount of candles to fetch * @param {object} params extra parameters specific to the bigone api endpoint * @returns {[[int]]} A list of candles ordered as timestamp, open, high, low, close, volume */ await this.loadMarkets (); const market = this.market (symbol); if (limit === undefined) { limit = 100; // default 100, max 500 } const request = { 'asset_pair_name': market['id'], 'period': this.timeframes[timeframe], 'limit': limit, }; if (since !== undefined) { // const start = parseInt (since / 1000); const duration = this.parseTimeframe (timeframe); const end = this.sum (since, limit * duration * 1000); request['time'] = this.iso8601 (end); } const response = await this.publicGetAssetPairsAssetPairNameCandles (this.extend (request, params)); // // { // code: 0, // data: [ // { // close: '0.021656', // high: '0.021658', // low: '0.021652', // open: '0.021652', // time: '2019-11-21T09:30:00Z', // volume: '53.08664' // }, // { // close: '0.021652', // high: '0.021656', // low: '0.021652', // open: '0.021656', // time: '2019-11-21T09:29:00Z', // volume: '88.39861' // }, // ] // } // const data = this.safeValue (response, 'data', []); return this.parseOHLCVs (data, market, timeframe, since, limit); } parseBalance (response) { const result = { 'info': response, 'timestamp': undefined, 'datetime': undefined, }; const balances = this.safeValue (response, 'data', []); for (let i = 0; i < balances.length; i++) { const balance = balances[i]; const symbol = this.safeString (balance, 'asset_symbol'); const code = this.safeCurrencyCode (symbol); const account = this.account (); account['total'] = this.safeString (balance, 'balance'); account['used'] = this.safeString (balance, 'locked_balance'); result[code] = account; } return this.safeBalance (result); } async fetchBalance (params = {}) { /** * @method * @name bigone#fetchBalance * @description query for balance and get the amount of funds available for trading or funds locked in orders * @param {object} params extra parameters specific to the bigone api endpoint * @returns {object} a [balance structure]{@link https://docs.ccxt.com/en/latest/manual.html?#balance-structure} */ await this.loadMarkets (); const type = this.safeString (params, 'type', ''); params = this.omit (params, 'type'); const method = 'privateGet' + this.capitalize (type) + 'Accounts'; const response = await this[method] (params); // // { // "code":0, // "data":[ // {"asset_symbol":"NKC","balance":"0","locked_balance":"0"}, // {"asset_symbol":"UBTC","balance":"0","locked_balance":"0"}, // {"asset_symbol":"READ","balance":"0","locked_balance":"0"}, // ], // } // return this.parseBalance (response); } parseOrder (order, market = undefined) { // // { // "id": 10, // "asset_pair_name": "EOS-BTC", // "price": "10.00", // "amount": "10.00", // "filled_amount": "9.0", // "avg_deal_price": "12.0", // "side": "ASK", // "state": "FILLED", // "created_at":"2019-01-29T06:05:56Z", // "updated_at":"2019-01-29T06:05:56Z", // } // const id = this.safeString (order, 'id'); const marketId = this.safeString (order, 'asset_pair_name'); const symbol = this.safeSymbol (marketId, market, '-'); const timestamp = this.parse8601 (this.safeString (order, 'created_at')); const price = this.safeString (order, 'price'); const amount = this.safeString (order, 'amount'); const average = this.safeString (order, 'avg_deal_price'); const filled = this.safeString (order, 'filled_amount'); const status = this.parseOrderStatus (this.safeString (order, 'state')); let side = this.safeString (order, 'side'); if (side === 'BID') { side = 'buy'; } else { side = 'sell'; } const lastTradeTimestamp = this.parse8601 (this.safeString (order, 'updated_at')); return this.safeOrder ({ 'info': order, 'id': id, 'clientOrderId': undefined, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'lastTradeTimestamp': lastTradeTimestamp, 'symbol': symbol, 'type': undefined, 'timeInForce': undefined, 'postOnly': undefined, 'side': side, 'price': price, 'stopPrice': undefined, 'amount': amount, 'cost': undefined, 'average': average, 'filled': filled, 'remaining': undefined, 'status': status, 'fee': undefined, 'trades': undefined, }, market); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { /** * @method * @name bigone#createOrder * @description create a trade 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|undefined} price the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders * @param {object} params extra parameters specific to the bigone api endpoint * @returns {object} an [order structure]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure} */ await this.loadMarkets (); const market = this.market (symbol); side = (side === 'buy') ? 'BID' : 'ASK'; const uppercaseType = type.toUpperCase (); const request = { 'asset_pair_name': market['id'], // asset pair name BTC-USDT, required 'side': side, // order side one of "ASK"/"BID", required 'amount': this.amountToPrecision (symbol, amount), // order amount, string, required // 'price': this.priceToPrecision (symbol, price), // order price, string, required 'type': uppercaseType, // 'operator': 'GTE', // stop orders only, GTE greater than and equal, LTE less than and equal // 'immediate_or_cancel': false, // limit orders only, must be false when post_only is true // 'post_only': false, // limit orders only, must be false when immediate_or_cancel is true }; if (uppercaseType === 'LIMIT') { request['price'] = this.priceToPrecision (symbol, price); } else { const isStopLimit = (uppercaseType === 'STOP_LIMIT'); const isStopMarket = (uppercaseType === 'STOP_MARKET'); if (isStopLimit || isStopMarket) { const stopPrice = this.safeNumber2 (params, 'stop_price', 'stopPrice'); if (stopPrice === undefined) { throw new ArgumentsRequired (this.id + ' createOrder() requires a stop_price parameter'); } request['stop_price'] = this.priceToPrecision (symbol, stopPrice); params = this.omit (params, [ 'stop_price', 'stopPrice' ]); } if (isStopLimit) { request['price'] = this.priceToPrecision (symbol, price); } } const response = await this.privatePostOrders (this.extend (request, params)); // // { // "id": 10, // "asset_pair_name": "EOS-BTC", // "price": "10.00", // "amount": "10.00", // "filled_amount": "9.0", // "avg_deal_price": "12.0", // "side": "ASK", // "state": "FILLED", // "created_at":"2019-01-29T06:05:56Z", // "updated_at":"2019-01-29T06:05:56Z" // } // const order = this.safeValue (response, 'data'); return this.parseOrder (order, market); } async cancelOrder (id, symbol = undefined, params = {}) { /** * @method * @name bigone#cancelOrder * @description cancels an open order * @param {string} id order id * @param {string|undefined} symbol Not used by bigone cancelOrder () * @param {object} params extra parameters specific to the bigone api endpoint * @returns {object} An [order structure]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure} */ await this.loadMarkets (); const request = { 'id': id }; const response = await this.privatePostOrdersIdCancel (this.extend (request, params)); // { // "id": 10, // "asset_pair_name": "EOS-BTC", // "price": "10.00", // "amount": "10.00", // "filled_amount": "9.0", // "avg_deal_price": "12.0", // "side": "ASK", // "state": "CANCELLED", // "created_at":"2019-01-29T06:05:56Z", // "updated_at":"2019-01-29T06:05:56Z" // } const order = this.safeValue (response, 'data'); return this.parseOrder (order); } async cancelAllOrders (symbol = undefined, params = {}) { /** * @method * @name bigone#cancelAllOrders * @description cancel all open orders * @param {string|undefined} symbol unified market symbol, only orders in the market of this symbol are cancelled when symbol is not undefined * @param {object} params extra parameters specific to the bigone api endpoint * @returns {[object]} a list of [order structures]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure} */ await this.loadMarkets (); const market = this.market (symbol); const request = { 'asset_pair_name': market['id'], }; const response = await this.privatePostOrdersCancel (this.extend (request, params)); // // { // "code":0, // "data": { // "cancelled":[ // 58272370, // 58272377 // ], // "failed": [] // } // } // return response; } async fetchOrder (id, symbol = undefined, params = {}) { /** * @method * @name bigone#fetchOrder * @description fetches information on an order made by the user * @param {string|undefined} symbol not used by bigone fetchOrder * @param {object} params extra parameters specific to the bigone api endpoint * @returns {object} An [order structure]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure} */ await this.loadMarkets (); const request = { 'id': id }; const response = await this.privateGetOrdersId (this.extend (request, params)); const order = this.safeValue (response, 'data', {}); return this.parseOrder (order); } async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { /** * @method * @name bigone#fetchOrders * @description fetches information on multiple orders made by the user * @param {string} symbol unified market symbol of the market orders were made in * @param {int|undefined} since the earliest time in ms to fetch orders for * @param {int|undefined} limit the maximum number of orde structures to retrieve * @param {object} params extra parameters specific to the bigone api endpoint * @returns {[object]} a list of [order structures]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure} */ if (symbol === undefined) { throw new ArgumentsRequired (this.id + ' fetchOrders() requires a symbol argument'); } await this.loadMarkets (); const market = this.market (symbol); const request = { 'asset_pair_name': market['id'], // 'page_token': 'dxzef', // request page after this page token // 'side': 'ASK', // 'ASK' or 'BID', optional // 'state': 'FILLED', // 'CANCELLED', 'FILLED', 'PENDING' // 'limit' 20, // default 20, max 200 }; if (limit !== undefined) { request['limit'] = limit; // default 20, max 200 } const response = await this.privateGetOrders (this.extend (request, params)); // // { // "code":0, // "data": [ // { // "id": 10, // "asset_pair_name": "ETH-BTC", // "price": "10.00", // "amount": "10.00", // "filled_amount": "9.0", // "avg_deal_price": "12.0", // "side": "ASK", // "state": "FILLED", // "created_at":"2019-01-29T06:05:56Z", // "updated_at":"2019-01-29T06:05:56Z", // }, // ], // "page_token":"dxzef", // } // const orders = this.safeValue (response, 'data', []); return this.parseOrders (orders, market, since, limit); } async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { /** * @method * @name bigone#fetchMyTrades * @description fetch all trades made by the user * @param {string} symbol unified market symbol * @param {int|undefined} since the earliest time in ms to fetch trades for * @param {int|undefined} limit the maximum number of trades structures to retrieve * @param {object} params extra parameters specific to the bigone api endpoint * @returns {[object]} a list of [trade structures]{@link https://docs.ccxt.com/en/latest/manual.html#trade-structure} */ await this.loadMarkets (); if (symbol === undefined) { throw new ArgumentsRequired (this.id + ' fetchMyTrades() requires a symbol argument'); } const market = this.market (symbol); const request = { 'asset_pair_name': market['id'], // 'page_token': 'dxzef', // request page after this page token }; if (limit !== undefined) { request['limit'] = limit; // default 20, max 200 } const response = await this.privateGetTrades (this.extend (request, params)); // // { // "code": 0, // "data": [ // { // "id": 10854280, // "asset_pair_name": "XIN-USDT", // "price": "70", // "amount": "1", // "taker_side": "ASK", // "maker_order_id": 58284908, // "taker_order_id": 58284909, // "maker_fee": "0.0008", // "taker_fee": "0.07", // "side": "SELF_TRADING", // "inserted_at": "2019-04-16T12:00:01Z" // }, // { // "id": 10854263, // "asset_pair_name": "XIN-USDT", // "price": "75.7", // "amount": "12.743149", // "taker_side": "BID", // "maker_order_id": null, // "taker_order_id": 58284888, // "maker_fee": null, // "taker_fee": "0.0025486298", // "side": "BID", // "inserted_at": "2019-04-15T06:20:57Z" // } // ], // "page_token":"dxfv" // } // const trades = this.safeValue (response, 'data', []); return this.parseTrades (trades, market, since, limit); } parseOrderStatus (status) { const statuses = { 'PENDING': 'open', 'FILLED': 'closed', 'CANCELLED': 'canceled', }; return this.safeString (statuses, status); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { /** * @method * @name bigone#fetchOpenOrders * @description fetch all unfilled currently open orders * @param {string} symbol unified market symbol * @param {int|undefined} since the earliest time in ms to fetch open orders for * @param {int|undefined} limit the maximum number of open orders structures to retrieve * @param {object} params extra parameters specific to the bigone api endpoint * @returns {[object]} a list of [order structures]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure} */ const request = { 'state': 'PENDING', }; return await this.fetchOrders (symbol, since, limit, this.extend (request, params)); } async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { /** * @method * @name bigone#fetchClosedOrders * @description fetches information on multiple closed orders made by the user * @param {string} symbol unified market symbol of the market orders were made in * @param {int|undefined} since the earliest time in ms to fetch orders for * @param {int|undefined} limit the maximum number of orde structures to retrieve * @param {object} params extra parameters specific to the bigone api endpoint * @returns {[object]} a list of [order structures]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure} */ const request = { 'state': 'FILLED', }; return await this.fetchOrders (symbol, since, limit, this.extend (request, params)); } nonce () { const exchangeTimeCorrection = this.safeInteger (this.options, 'exchangeMillisecondsCorrection', 0) * 1000000; return this.microseconds () * 1000 + exchangeTimeCorrection; } sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) { const query = this.omit (params, this.extractParams (path)); const baseUrl = this.implodeHostname (this.urls['api'][api]); let url = baseUrl + '/' + this.implodeParams (path, params); headers = {}; if (api === 'public') { if (Object.keys (query).length) { url += '?' + this.urlencode (query); } } else { this.checkRequiredCredentials (); const nonce = this.nonce ().toString (); const request = { 'type': 'OpenAPIV2', 'sub': this.apiKey, 'nonce': nonce, // 'recv_window': '30', // default 30 }; const jwt = this.jwt (request, this.encode