UNPKG

ccxt

Version:

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

396 lines (393 loc) 18.6 kB
// ---------------------------------------------------------------------------- // PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN: // https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code // EDIT THE CORRESPONDENT .ts FILE INSTEAD // --------------------------------------------------------------------------- import bithumbRest from '../bithumb.js'; import { ArrayCache } from '../base/ws/Cache.js'; import { ExchangeError } from '../base/errors.js'; // --------------------------------------------------------------------------- export default class bithumb extends bithumbRest { describe() { return this.deepExtend(super.describe(), { 'has': { 'ws': true, 'watchBalance': false, 'watchTicker': true, 'watchTickers': true, 'watchTrades': true, 'watchOrderBook': true, 'watchOHLCV': false, }, 'urls': { 'api': { 'ws': 'wss://pubwss.bithumb.com/pub/ws', }, }, 'options': {}, 'streaming': {}, 'exceptions': {}, }); } /** * @method * @name bithumb#watchTicker * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market * @see https://apidocs.bithumb.com/v1.2.0/reference/%EB%B9%97%EC%8D%B8-%EA%B1%B0%EB%9E%98%EC%86%8C-%EC%A0%95%EB%B3%B4-%EC%88%98%EC%8B%A0 * @param {string} symbol unified symbol of the market to fetch the ticker for * @param {object} [params] extra parameters specific to the exchange API endpoint * @param {string} [params.channel] the channel to subscribe to, tickers by default. Can be tickers, sprd-tickers, index-tickers, block-tickers * @returns {object} a [ticker structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#ticker-structure} */ async watchTicker(symbol, params = {}) { const url = this.urls['api']['ws']; await this.loadMarkets(); const market = this.market(symbol); const messageHash = 'ticker:' + market['symbol']; const request = { 'type': 'ticker', 'symbols': [market['base'] + '_' + market['quote']], 'tickTypes': [this.safeString(params, 'tickTypes', '24H')], }; return await this.watch(url, messageHash, this.extend(request, params), messageHash); } /** * @method * @name bithumb#watchTickers * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list * @see https://apidocs.bithumb.com/v1.2.0/reference/%EB%B9%97%EC%8D%B8-%EA%B1%B0%EB%9E%98%EC%86%8C-%EC%A0%95%EB%B3%B4-%EC%88%98%EC%8B%A0 * @param {string[]} symbols unified symbol of the market to fetch the ticker for * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure} */ async watchTickers(symbols = undefined, params = {}) { await this.loadMarkets(); const url = this.urls['api']['ws']; const marketIds = []; const messageHashes = []; symbols = this.marketSymbols(symbols, undefined, false, true, true); for (let i = 0; i < symbols.length; i++) { const symbol = symbols[i]; const market = this.market(symbol); marketIds.push(market['base'] + '_' + market['quote']); messageHashes.push('ticker:' + market['symbol']); } const request = { 'type': 'ticker', 'symbols': marketIds, 'tickTypes': [this.safeString(params, 'tickTypes', '24H')], }; const message = this.extend(request, params); const newTicker = await this.watchMultiple(url, messageHashes, message, messageHashes); if (this.newUpdates) { const result = {}; result[newTicker['symbol']] = newTicker; return result; } return this.filterByArray(this.tickers, 'symbol', symbols); } handleTicker(client, message) { // // { // "type" : "ticker", // "content" : { // "symbol" : "BTC_KRW", // 통화코드 // "tickType" : "24H", // 변동 기준시간- 30M, 1H, 12H, 24H, MID // "date" : "20200129", // 일자 // "time" : "121844", // 시간 // "openPrice" : "2302", // 시가 // "closePrice" : "2317", // 종가 // "lowPrice" : "2272", // 저가 // "highPrice" : "2344", // 고가 // "value" : "2831915078.07065789", // 누적거래금액 // "volume" : "1222314.51355788", // 누적거래량 // "sellVolume" : "760129.34079004", // 매도누적거래량 // "buyVolume" : "462185.17276784", // 매수누적거래량 // "prevClosePrice" : "2326", // 전일종가 // "chgRate" : "0.65", // 변동률 // "chgAmt" : "15", // 변동금액 // "volumePower" : "60.80" // 체결강도 // } // } // const content = this.safeDict(message, 'content', {}); const marketId = this.safeString(content, 'symbol'); const symbol = this.safeSymbol(marketId, undefined, '_'); const ticker = this.parseWsTicker(content); const messageHash = 'ticker:' + symbol; this.tickers[symbol] = ticker; client.resolve(this.tickers[symbol], messageHash); } parseWsTicker(ticker, market = undefined) { // // { // "symbol" : "BTC_KRW", // 통화코드 // "tickType" : "24H", // 변동 기준시간- 30M, 1H, 12H, 24H, MID // "date" : "20200129", // 일자 // "time" : "121844", // 시간 // "openPrice" : "2302", // 시가 // "closePrice" : "2317", // 종가 // "lowPrice" : "2272", // 저가 // "highPrice" : "2344", // 고가 // "value" : "2831915078.07065789", // 누적거래금액 // "volume" : "1222314.51355788", // 누적거래량 // "sellVolume" : "760129.34079004", // 매도누적거래량 // "buyVolume" : "462185.17276784", // 매수누적거래량 // "prevClosePrice" : "2326", // 전일종가 // "chgRate" : "0.65", // 변동률 // "chgAmt" : "15", // 변동금액 // "volumePower" : "60.80" // 체결강도 // } // const date = this.safeString(ticker, 'date', ''); const time = this.safeString(ticker, 'time', ''); const datetime = date.slice(0, 4) + '-' + date.slice(4, 6) + '-' + date.slice(6, 8) + 'T' + time.slice(0, 2) + ':' + time.slice(2, 4) + ':' + time.slice(4, 6); const marketId = this.safeString(ticker, 'symbol'); return this.safeTicker({ 'symbol': this.safeSymbol(marketId, market, '_'), 'timestamp': this.parse8601(datetime), 'datetime': datetime, 'high': this.safeString(ticker, 'highPrice'), 'low': this.safeString(ticker, 'lowPrice'), 'bid': undefined, 'bidVolume': this.safeString(ticker, 'buyVolume'), 'ask': undefined, 'askVolume': this.safeString(ticker, 'sellVolume'), 'vwap': undefined, 'open': this.safeString(ticker, 'openPrice'), 'close': this.safeString(ticker, 'closePrice'), 'last': undefined, 'previousClose': this.safeString(ticker, 'prevClosePrice'), 'change': this.safeString(ticker, 'chgAmt'), 'percentage': this.safeString(ticker, 'chgRate'), 'average': undefined, 'baseVolume': this.safeString(ticker, 'volume'), 'quoteVolume': this.safeString(ticker, 'value'), 'info': ticker, }, market); } /** * @method * @name bithumb#watchOrderBook * @see https://apidocs.bithumb.com/v1.2.0/reference/%EB%B9%97%EC%8D%B8-%EA%B1%B0%EB%9E%98%EC%86%8C-%EC%A0%95%EB%B3%B4-%EC%88%98%EC%8B%A0 * @description watches 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} [limit] the maximum amount of order book entries to return * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} A dictionary of [order book structures]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-book-structure} indexed by market symbols */ async watchOrderBook(symbol, limit = undefined, params = {}) { await this.loadMarkets(); const url = this.urls['api']['ws']; const market = this.market(symbol); symbol = market['symbol']; const messageHash = 'orderbook' + ':' + symbol; const request = { 'type': 'orderbookdepth', 'symbols': [market['base'] + '_' + market['quote']], }; const orderbook = await this.watch(url, messageHash, this.extend(request, params), messageHash); return orderbook.limit(); } handleOrderBook(client, message) { // // { // "type" : "orderbookdepth", // "content" : { // "list" : [ // { // "symbol" : "BTC_KRW", // "orderType" : "ask", // 주문타입 – bid / ask // "price" : "10593000", // 호가 // "quantity" : "1.11223318", // 잔량 // "total" : "3" // 건수 // }, // {"symbol" : "BTC_KRW", "orderType" : "ask", "price" : "10596000", "quantity" : "0.5495", "total" : "8"}, // {"symbol" : "BTC_KRW", "orderType" : "ask", "price" : "10598000", "quantity" : "18.2085", "total" : "10"}, // {"symbol" : "BTC_KRW", "orderType" : "bid", "price" : "10532000", "quantity" : "0", "total" : "0"}, // {"symbol" : "BTC_KRW", "orderType" : "bid", "price" : "10572000", "quantity" : "2.3324", "total" : "4"}, // {"symbol" : "BTC_KRW", "orderType" : "bid", "price" : "10571000", "quantity" : "1.469", "total" : "3"}, // {"symbol" : "BTC_KRW", "orderType" : "bid", "price" : "10569000", "quantity" : "0.5152", "total" : "2"} // ], // "datetime":1580268255864325 // 일시 // } // } // const content = this.safeDict(message, 'content', {}); const list = this.safeList(content, 'list', []); const first = this.safeDict(list, 0, {}); const marketId = this.safeString(first, 'symbol'); const symbol = this.safeSymbol(marketId, undefined, '_'); const timestampStr = this.safeString(content, 'datetime'); const timestamp = this.parseToInt(timestampStr.slice(0, 13)); if (!(symbol in this.orderbooks)) { const ob = this.orderBook(); ob['symbol'] = symbol; this.orderbooks[symbol] = ob; } const orderbook = this.orderbooks[symbol]; this.handleDeltas(orderbook, list); orderbook['timestamp'] = timestamp; orderbook['datetime'] = this.iso8601(timestamp); const messageHash = 'orderbook' + ':' + symbol; client.resolve(orderbook, messageHash); } handleDelta(orderbook, delta) { // // { // symbol: "ETH_BTC", // orderType: "bid", // price: "0.07349517", // quantity: "0", // total: "0", // } // const sideId = this.safeString(delta, 'orderType'); const side = (sideId === 'bid') ? 'bids' : 'asks'; const bidAsk = this.parseBidAsk(delta, 'price', 'quantity'); const orderbookSide = orderbook[side]; orderbookSide.storeArray(bidAsk); } handleDeltas(orderbook, deltas) { for (let i = 0; i < deltas.length; i++) { this.handleDelta(orderbook, deltas[i]); } } /** * @method * @name bithumb#watchTrades * @description get the list of most recent trades for a particular symbol * @see https://apidocs.bithumb.com/v1.2.0/reference/%EB%B9%97%EC%8D%B8-%EA%B1%B0%EB%9E%98%EC%86%8C-%EC%A0%95%EB%B3%B4-%EC%88%98%EC%8B%A0 * @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 {object[]} a list of [trade structures]{@link https://github.com/ccxt/ccxt/wiki/Manual#public-trades} */ async watchTrades(symbol, since = undefined, limit = undefined, params = {}) { await this.loadMarkets(); const url = this.urls['api']['ws']; const market = this.market(symbol); symbol = market['symbol']; const messageHash = 'trade:' + symbol; const request = { 'type': 'transaction', 'symbols': [market['base'] + '_' + market['quote']], }; const trades = await this.watch(url, messageHash, this.extend(request, params), messageHash); if (this.newUpdates) { limit = trades.getLimit(symbol, limit); } return this.filterBySinceLimit(trades, since, limit, 'timestamp', true); } handleTrades(client, message) { // // { // "type" : "transaction", // "content" : { // "list" : [ // { // "symbol" : "BTC_KRW", // "buySellGb" : "1", // "contPrice" : "10579000", // "contQty" : "0.01", // "contAmt" : "105790.00", // "contDtm" : "2020-01-29 12:24:18.830039", // "updn" : "dn" // } // ] // } // } // const content = this.safeDict(message, 'content', {}); const rawTrades = this.safeList(content, 'list', []); for (let i = 0; i < rawTrades.length; i++) { const rawTrade = rawTrades[i]; const marketId = this.safeString(rawTrade, 'symbol'); const symbol = this.safeSymbol(marketId, undefined, '_'); if (!(symbol in this.trades)) { const limit = this.safeInteger(this.options, 'tradesLimit', 1000); const stored = new ArrayCache(limit); this.trades[symbol] = stored; } const trades = this.trades[symbol]; const parsed = this.parseWsTrade(rawTrade); trades.append(parsed); const messageHash = 'trade' + ':' + symbol; client.resolve(trades, messageHash); } } parseWsTrade(trade, market = undefined) { // // { // "symbol" : "BTC_KRW", // "buySellGb" : "1", // "contPrice" : "10579000", // "contQty" : "0.01", // "contAmt" : "105790.00", // "contDtm" : "2020-01-29 12:24:18.830038", // "updn" : "dn" // } // const marketId = this.safeString(trade, 'symbol'); const datetime = this.safeString(trade, 'contDtm'); // that date is not UTC iso8601, but exchange's local time, -9hr difference const timestamp = this.parse8601(datetime) - 32400000; const sideId = this.safeString(trade, 'buySellGb'); return this.safeTrade({ 'id': undefined, 'info': trade, 'timestamp': timestamp, 'datetime': this.iso8601(timestamp), 'symbol': this.safeSymbol(marketId, market, '_'), 'order': undefined, 'type': undefined, 'side': (sideId === '1') ? 'buy' : 'sell', 'takerOrMaker': undefined, 'price': this.safeString(trade, 'contPrice'), 'amount': this.safeString(trade, 'contQty'), 'cost': this.safeString(trade, 'contAmt'), 'fee': undefined, }, market); } handleErrorMessage(client, message) { // // { // "status" : "5100", // "resmsg" : "Invalid Filter Syntax" // } // if (!('status' in message)) { return true; } const errorCode = this.safeString(message, 'status'); try { if (errorCode !== '0000') { const msg = this.safeString(message, 'resmsg'); throw new ExchangeError(this.id + ' ' + msg); } return true; } catch (e) { client.reject(e); } return true; } handleMessage(client, message) { if (!this.handleErrorMessage(client, message)) { return; } const topic = this.safeString(message, 'type'); if (topic !== undefined) { const methods = { 'ticker': this.handleTicker, 'orderbookdepth': this.handleOrderBook, 'transaction': this.handleTrades, }; const method = this.safeValue(methods, topic); if (method !== undefined) { method.call(this, client, message); } } } }