UNPKG

@proton/ccxt

Version:

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

282 lines (279 loc) 12 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 independentreserveRest from '../independentreserve.js'; import { NotSupported, InvalidNonce } from '../base/errors.js'; import { ArrayCache } from '../base/ws/Cache.js'; // --------------------------------------------------------------------------- export default class independentreserve extends independentreserveRest { describe() { return this.deepExtend(super.describe(), { 'has': { 'ws': true, 'watchBalance': false, 'watchTicker': false, 'watchTickers': false, 'watchTrades': true, 'watchMyTrades': false, 'watchOrders': false, 'watchOrderBook': true, 'watchOHLCV': false, }, 'urls': { 'api': { 'ws': 'wss://websockets.independentreserve.com', }, }, 'options': { 'checksum': false, // TODO: currently only working for snapshot }, 'streaming': {}, 'exceptions': {}, }); } async watchTrades(symbol, since = undefined, limit = undefined, params = {}) { /** * @method * @name independentreserve#watchTrades * @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 independentreserve 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); symbol = market['symbol']; const url = this.urls['api']['ws'] + '?subscribe=ticker-' + market['base'] + '-' + market['quote']; const messageHash = 'trades:' + symbol; const trades = await this.watch(url, messageHash, undefined, messageHash); return this.filterBySinceLimit(trades, since, limit, 'timestamp', true); } handleTrades(client, message) { // // { // Channel: 'ticker-btc-usd', // Nonce: 130, // Data: { // TradeGuid: '7a669f2a-d564-472b-8493-6ef982eb1e96', // Pair: 'btc-aud', // TradeDate: '2023-02-12T10:04:13.0804889+11:00', // Price: 31640, // Volume: 0.00079029, // BidGuid: 'ba8a78b5-be69-4d33-92bb-9df0daa6314e', // OfferGuid: '27d20270-f21f-4c25-9905-152e70b2f6ec', // Side: 'Buy' // }, // Time: 1676156653111, // Event: 'Trade' // } // const data = this.safeValue(message, 'Data', {}); const marketId = this.safeString(data, 'Pair'); const symbol = this.safeSymbol(marketId, undefined, '-'); const messageHash = 'trades:' + symbol; let stored = this.safeValue(this.trades, symbol); if (stored === undefined) { const limit = this.safeInteger(this.options, 'tradesLimit', 1000); stored = new ArrayCache(limit); this.trades[symbol] = stored; } const trade = this.parseWsTrade(data); stored.append(trade); this.trades[symbol] = stored; client.resolve(this.trades[symbol], messageHash); } parseWsTrade(trade, market = undefined) { // // { // "TradeGuid": "2f316718-0d0b-4e33-a30c-c2c06f3cfb34", // "Pair": "xbt-aud", // "TradeDate": "2023-02-12T09:22:35.4207494+11:00", // "Price": 31573.8, // "Volume": 0.05, // "BidGuid": "adb63d74-4c02-47f9-9cc3-f287e3b48ab6", // "OfferGuid": "b94d9bc4-addd-4633-a18f-69cf7e1b6f47", // "Side": "Buy" // } // const datetime = this.safeString(trade, 'TradeDate'); const marketId = this.safeString(market, 'Pair'); return this.safeTrade({ 'info': trade, 'id': this.safeString(trade, 'TradeGuid'), 'order': this.safeString(trade, 'orderNo'), 'symbol': this.safeSymbol(marketId, market, '-'), 'side': this.safeStringLower(trade, 'Side'), 'type': undefined, 'takerOrMaker': undefined, 'price': this.safeString(trade, 'Price'), 'amount': this.safeString(trade, 'Volume'), 'cost': undefined, 'fee': undefined, 'timestamp': this.parse8601(datetime), 'datetime': datetime, }, market); } async watchOrderBook(symbol, limit = undefined, params = {}) { /** * @method * @name independentreserve#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 independentreserve 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']; if (limit === undefined) { limit = 100; } limit = this.numberToString(limit); const url = this.urls['api']['ws'] + '/orderbook/' + limit + '?subscribe=' + market['base'] + '-' + market['quote']; const messageHash = 'orderbook:' + symbol + ':' + limit; const subscription = { 'receivedSnapshot': false, }; const orderbook = await this.watch(url, messageHash, undefined, messageHash, subscription); return orderbook.limit(); } handleOrderBook(client, message) { // // { // Channel: "orderbook/1/eth/aud", // Data: { // Bids: [ // { // Price: 2198.09, // Volume: 0.16143952, // }, // ], // Offers: [ // { // Price: 2201.25, // Volume: 15, // }, // ], // Crc32: 1519697650, // }, // Time: 1676150558254, // Event: "OrderBookSnapshot", // } // const event = this.safeString(message, 'Event'); const channel = this.safeString(message, 'Channel'); const parts = channel.split('/'); const depth = this.safeString(parts, 1); const baseId = this.safeString(parts, 2); const quoteId = this.safeString(parts, 3); const base = this.safeCurrencyCode(baseId); const quote = this.safeCurrencyCode(quoteId); const symbol = base + '/' + quote; const orderBook = this.safeValue(message, 'Data', {}); const messageHash = 'orderbook:' + symbol + ':' + depth; const subscription = this.safeValue(client.subscriptions, messageHash, {}); const receivedSnapshot = this.safeValue(subscription, 'receivedSnapshot', false); const timestamp = this.safeInteger(message, 'Time'); let storedOrderBook = this.safeValue(this.orderbooks, symbol); if (storedOrderBook === undefined) { storedOrderBook = this.orderBook({}); this.orderbooks[symbol] = storedOrderBook; } if (event === 'OrderBookSnapshot') { const snapshot = this.parseOrderBook(orderBook, symbol, timestamp, 'Bids', 'Offers', 'Price', 'Volume'); storedOrderBook.reset(snapshot); subscription['receivedSnapshot'] = true; } else { const asks = this.safeValue(orderBook, 'Offers', []); const bids = this.safeValue(orderBook, 'Bids', []); this.handleDeltas(storedOrderBook['asks'], asks); this.handleDeltas(storedOrderBook['bids'], bids); storedOrderBook['timestamp'] = timestamp; storedOrderBook['datetime'] = this.iso8601(timestamp); } const checksum = this.safeValue(this.options, 'checksum', true); if (checksum && receivedSnapshot) { const storedAsks = storedOrderBook['asks']; const storedBids = storedOrderBook['bids']; const asksLength = storedAsks.length; const bidsLength = storedBids.length; let payload = ''; for (let i = 0; i < 10; i++) { if (i < bidsLength) { payload = payload + this.valueToChecksum(storedBids[i][0]) + this.valueToChecksum(storedBids[i][1]); } } for (let i = 0; i < 10; i++) { if (i < asksLength) { payload = payload + this.valueToChecksum(storedAsks[i][0]) + this.valueToChecksum(storedAsks[i][1]); } } const calculatedChecksum = this.crc32(payload, true); const responseChecksum = this.safeInteger(orderBook, 'Crc32'); if (calculatedChecksum !== responseChecksum) { const error = new InvalidNonce(this.id + ' invalid checksum'); client.reject(error, messageHash); } } if (receivedSnapshot) { client.resolve(storedOrderBook, messageHash); } } valueToChecksum(value) { let result = value.toFixed(8); result = result.replace('.', ''); // remove leading zeros result = this.parseNumber(result); result = this.numberToString(result); return result; } handleDelta(bookside, delta) { const bidAsk = this.parseBidAsk(delta, 'Price', 'Volume'); bookside.storeArray(bidAsk); } handleDeltas(bookside, deltas) { for (let i = 0; i < deltas.length; i++) { this.handleDelta(bookside, deltas[i]); } } handleHeartbeat(client, message) { // // { // Time: 1676156208182, // Event: 'Heartbeat' // } // return message; } handleSubscriptions(client, message) { // // { // Data: [ 'ticker-btc-sgd' ], // Time: 1676157556223, // Event: 'Subscriptions' // } // return message; } handleMessage(client, message) { const event = this.safeString(message, 'Event'); const handlers = { 'Subscriptions': this.handleSubscriptions, 'Heartbeat': this.handleHeartbeat, 'Trade': this.handleTrades, 'OrderBookSnapshot': this.handleOrderBook, 'OrderBookChange': this.handleOrderBook, }; const handler = this.safeValue(handlers, event); if (handler !== undefined) { return handler.call(this, client, message); } throw new NotSupported(this.id + ' received an unsupported message: ' + this.json(message)); } }