UNPKG

@proton/ccxt

Version:

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

296 lines (292 loc) 12.8 kB
'use strict'; var ripio$1 = require('../ripio.js'); var Cache = require('../base/ws/Cache.js'); // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- class ripio extends ripio$1 { describe() { return this.deepExtend(super.describe(), { 'has': { 'ws': true, 'watchOrderBook': true, 'watchTrades': true, 'watchTicker': true, }, 'urls': { 'api': { 'ws': 'wss://api.exchange.ripio.com/ws/v2/consumer/non-persistent/public/default/', }, }, 'options': { 'tradesLimit': 1000, 'uuid': this.uuid(), }, }); } async watchTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) { await this.loadMarkets(); const market = this.market(symbol); symbol = market['symbol']; const name = 'trades'; const messageHash = name + '_' + market['id'].toLowerCase(); const url = this.urls['api']['ws'] + messageHash + '/' + this.options['uuid']; const subscription = { 'name': name, 'symbol': symbol, 'messageHash': messageHash, 'method': this.handleTrade, }; const trades = await this.watch(url, messageHash, undefined, messageHash, subscription); if (this.newUpdates) { limit = trades.getLimit(symbol, limit); } return this.filterBySinceLimit(trades, since, limit, 'timestamp', true); } handleTrade(client, message, subscription) { // // { // messageId: 'CAAQAA==', // payload: 'eyJjcmVhdGVkX2F0IjogMTYwMTczNjI0NywgImFtb3VudCI6ICIwLjAwMjAwIiwgInByaWNlIjogIjEwNTkzLjk5MDAwMCIsICJzaWRlIjogIkJVWSIsICJwYWlyIjogIkJUQ19VU0RDIiwgInRha2VyX2ZlZSI6ICIwIiwgInRha2VyX3NpZGUiOiAiQlVZIiwgIm1ha2VyX2ZlZSI6ICIwIiwgInRha2VyIjogMjYxODU2NCwgIm1ha2VyIjogMjYxODU1N30=', // properties: {}, // publishTime: '2020-10-03T14:44:09.881Z' // } // const payload = this.safeString(message, 'payload'); if (payload === undefined) { return message; } const data = JSON.parse(this.base64ToString(payload)); // // { // created_at: 1601736247, // amount: '0.00200', // price: '10593.990000', // side: 'BUY', // pair: 'BTC_USDC', // taker_fee: '0', // taker_side: 'BUY', // maker_fee: '0', // taker: 2618564, // maker: 2618557 // } // const symbol = this.safeString(subscription, 'symbol'); const messageHash = this.safeString(subscription, 'messageHash'); const market = this.market(symbol); const trade = this.parseTrade(data, market); let tradesArray = this.safeValue(this.trades, symbol); if (tradesArray === undefined) { const limit = this.safeInteger(this.options, 'tradesLimit', 1000); tradesArray = new Cache.ArrayCache(limit); this.trades[symbol] = tradesArray; } tradesArray.append(trade); client.resolve(tradesArray, messageHash); } async watchTicker(symbol, params = {}) { /** * @method * @name ripio#watchTicker * @description watches 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 ripio api endpoint * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure} */ await this.loadMarkets(); const market = this.market(symbol); symbol = market['symbol']; const name = 'rate'; const messageHash = name + '_' + market['id'].toLowerCase(); const url = this.urls['api']['ws'] + messageHash + '/' + this.options['uuid']; const subscription = { 'name': name, 'symbol': symbol, 'messageHash': messageHash, 'method': this.handleTicker, }; return await this.watch(url, messageHash, undefined, messageHash, subscription); } handleTicker(client, message, subscription) { // // { // messageId: 'CAAQAA==', // payload: 'eyJidXkiOiBbeyJhbW91bnQiOiAiMC4wOTMxMiIsICJ0b3RhbCI6ICI4MzguMDgiLCAicHJpY2UiOiAiOTAwMC4wMCJ9XSwgInNlbGwiOiBbeyJhbW91bnQiOiAiMC4wMDAwMCIsICJ0b3RhbCI6ICIwLjAwIiwgInByaWNlIjogIjkwMDAuMDAifV0sICJ1cGRhdGVkX2lkIjogMTI0NDA0fQ==', // properties: {}, // publishTime: '2020-10-03T10:05:09.445Z' // } // const payload = this.safeString(message, 'payload'); if (payload === undefined) { return message; } const data = JSON.parse(this.base64ToString(payload)); // // { // "pair": "BTC_BRL", // "last_price": "68558.59", // "low": "54736.11", // "high": "70034.68", // "variation": "8.75", // "volume": "10.10537" // } // const ticker = this.parseTicker(data); const timestamp = this.parse8601(this.safeString(message, 'publishTime')); ticker['timestamp'] = timestamp; ticker['datetime'] = this.iso8601(timestamp); const symbol = ticker['symbol']; this.tickers[symbol] = ticker; const messageHash = this.safeString(subscription, 'messageHash'); if (messageHash !== undefined) { client.resolve(ticker, messageHash); } return message; } async watchOrderBook(symbol, limit = undefined, params = {}) { /** * @method * @name ripio#watchOrderBook * @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|undefined} limit the maximum amount of order book entries to return * @param {object} params extra parameters specific to the ripio api endpoint * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols */ await this.loadMarkets(); const market = this.market(symbol); symbol = market['symbol']; const name = 'orderbook'; const messageHash = name + '_' + market['id'].toLowerCase(); const url = this.urls['api']['ws'] + messageHash + '/' + this.options['uuid']; const client = this.client(url); const subscription = { 'name': name, 'symbol': symbol, 'messageHash': messageHash, 'method': this.handleOrderBook, }; if (!(messageHash in client.subscriptions)) { this.orderbooks[symbol] = this.orderBook({}); client.subscriptions[messageHash] = subscription; const options = this.safeValue(this.options, 'fetchOrderBookSnapshot', {}); const delay = this.safeInteger(options, 'delay', this.rateLimit); // fetch the snapshot in a separate async call after a warmup delay this.delay(delay, this.fetchOrderBookSnapshot, client, subscription); } const orderbook = await this.watch(url, messageHash, undefined, messageHash, subscription); return orderbook.limit(); } async fetchOrderBookSnapshot(client, subscription) { const symbol = this.safeString(subscription, 'symbol'); const messageHash = this.safeString(subscription, 'messageHash'); try { // todo: this is a synch blocking call in ccxt.php - make it async const snapshot = await this.fetchOrderBook(symbol); const orderbook = this.orderbooks[symbol]; const messages = orderbook.cache; orderbook.reset(snapshot); // unroll the accumulated deltas for (let i = 0; i < messages.length; i++) { const message = messages[i]; this.handleOrderBookMessage(client, message, orderbook); } this.orderbooks[symbol] = orderbook; client.resolve(orderbook, messageHash); } catch (e) { client.reject(e, messageHash); } } handleOrderBook(client, message, subscription) { const messageHash = this.safeString(subscription, 'messageHash'); const symbol = this.safeString(subscription, 'symbol'); const orderbook = this.safeValue(this.orderbooks, symbol); if (orderbook === undefined) { return message; } if (orderbook['nonce'] === undefined) { orderbook.cache.push(message); } else { this.handleOrderBookMessage(client, message, orderbook); client.resolve(orderbook, messageHash); } return message; } handleOrderBookMessage(client, message, orderbook) { // // { // messageId: 'CAAQAA==', // payload: 'eyJidXkiOiBbeyJhbW91bnQiOiAiMC4wOTMxMiIsICJ0b3RhbCI6ICI4MzguMDgiLCAicHJpY2UiOiAiOTAwMC4wMCJ9XSwgInNlbGwiOiBbeyJhbW91bnQiOiAiMC4wMDAwMCIsICJ0b3RhbCI6ICIwLjAwIiwgInByaWNlIjogIjkwMDAuMDAifV0sICJ1cGRhdGVkX2lkIjogMTI0NDA0fQ==', // properties: {}, // publishTime: '2020-10-03T10:05:09.445Z' // } // const payload = this.safeString(message, 'payload'); if (payload === undefined) { return message; } const data = JSON.parse(this.base64ToString(payload)); // // { // "buy": [ // {"amount": "0.05000", "total": "532.77", "price": "10655.41"} // ], // "sell": [ // {"amount": "0.00000", "total": "0.00", "price": "10655.41"} // ], // "updated_id": 99740 // } // const nonce = this.safeInteger(data, 'updated_id'); if (nonce > orderbook['nonce']) { const asks = this.safeValue(data, 'sell', []); const bids = this.safeValue(data, 'buy', []); this.handleDeltas(orderbook['asks'], asks); this.handleDeltas(orderbook['bids'], bids); orderbook['nonce'] = nonce; const timestamp = this.parse8601(this.safeString(message, 'publishTime')); orderbook['timestamp'] = timestamp; orderbook['datetime'] = this.iso8601(timestamp); } return orderbook; } handleDelta(bookside, delta) { const price = this.safeFloat(delta, 'price'); const amount = this.safeFloat(delta, 'amount'); bookside.store(price, amount); } handleDeltas(bookside, deltas) { for (let i = 0; i < deltas.length; i++) { this.handleDelta(bookside, deltas[i]); } } async ack(client, messageId) { // the exchange requires acknowledging each received message await client.send({ 'messageId': messageId }); } handleMessage(client, message) { // // { // messageId: 'CAAQAA==', // payload: 'eyJidXkiOiBbeyJhbW91bnQiOiAiMC4wNTAwMCIsICJ0b3RhbCI6ICI1MzIuNzciLCAicHJpY2UiOiAiMTA2NTUuNDEifV0sICJzZWxsIjogW3siYW1vdW50IjogIjAuMDAwMDAiLCAidG90YWwiOiAiMC4wMCIsICJwcmljZSI6ICIxMDY1NS40MSJ9XSwgInVwZGF0ZWRfaWQiOiA5OTc0MH0=', // properties: {}, // publishTime: '2020-09-30T17:35:27.851Z' // } // const messageId = this.safeString(message, 'messageId'); if (messageId !== undefined) { // the exchange requires acknowledging each received message this.spawn(this.ack, client, messageId); } const keys = Object.keys(client.subscriptions); const firstKey = this.safeString(keys, 0); const subscription = this.safeValue(client.subscriptions, firstKey, {}); const method = this.safeValue(subscription, 'method'); if (method !== undefined) { return method.call(this, client, message, subscription); } return message; } } module.exports = ripio;