ccxt
Version:
983 lines (980 loc) • 52.6 kB
JavaScript
// ----------------------------------------------------------------------------
// 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 asterRest from '../aster.js';
import { ArgumentsRequired } from '../base/errors.js';
import { ArrayCache, ArrayCacheByTimestamp } from '../base/ws/Cache.js';
// ---------------------------------------------------------------------------
export default class aster extends asterRest {
describe() {
return this.deepExtend(super.describe(), {
'has': {
'ws': true,
'watchBalance': false,
'watchBidsAsks': true,
'watchTicker': true,
'watchTickers': true,
'watchMarkPrice': true,
'watchMarkPrices': true,
'watchTrades': true,
'watchTradesForSymbols': true,
'watchOrderBook': true,
'watchOrderBookForSymbols': true,
'watchOHLCV': true,
'watchOHLCVForSymbols': true,
'unWatchTicker': true,
'unWatchTickers': true,
'unWatchMarkPrice': true,
'unWatchMarkPrices': true,
'unWatchBidsAsks': true,
'unWatchTrades': true,
'unWatchTradesForSymbols': true,
'unWatchOrderBook': true,
'unWatchOrderBookForSymbols': true,
'unWatchOHLCV': true,
'unWatchOHLCVForSymbols': true,
},
'urls': {
'api': {
'ws': {
'spot': 'wss://sstream.asterdex.com/stream',
'swap': 'wss://fstream.asterdex.com/stream',
},
},
},
'options': {},
'streaming': {},
'exceptions': {},
});
}
getAccountTypeFromSubscriptions(subscriptions) {
let accountType = '';
for (let i = 0; i < subscriptions.length; i++) {
const subscription = subscriptions[i];
if ((subscription === 'spot') || (subscription === 'swap')) {
accountType = subscription;
break;
}
}
return accountType;
}
/**
* @method
* @name aster#watchTicker
* @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#full-ticker-per-symbol
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#individual-symbol-ticker-streams
* @param {string} symbol 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 watchTicker(symbol, params = {}) {
params['callerMethodName'] = 'watchTicker';
await this.loadMarkets();
symbol = this.safeSymbol(symbol);
const tickers = await this.watchTickers([symbol], params);
return tickers[symbol];
}
/**
* @method
* @name aster#unWatchTicker
* @description unWatches a price ticker
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#full-ticker-per-symbol
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#individual-symbol-ticker-streams
* @param {string} symbol 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 unWatchTicker(symbol, params = {}) {
params['callerMethodName'] = 'unWatchTicker';
return await this.unWatchTickers([symbol], params);
}
/**
* @method
* @name aster#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://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#full-ticker-per-symbol
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#individual-symbol-ticker-streams
* @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();
symbols = this.marketSymbols(symbols, undefined, true, true, true);
const firstMarket = this.getMarketFromSymbols(symbols);
const type = this.safeString(firstMarket, 'type', 'swap');
const symbolsLength = symbols.length;
let methodName = undefined;
[methodName, params] = this.handleParamString(params, 'callerMethodName', 'watchTickers');
params = this.omit(params, 'callerMethodName');
if (symbolsLength === 0) {
throw new ArgumentsRequired(this.id + ' ' + methodName + '() requires a non-empty array of symbols');
}
const url = this.urls['api']['ws'][type];
const subscriptionArgs = [];
const messageHashes = [];
const request = {
'method': 'SUBSCRIBE',
'params': subscriptionArgs,
};
for (let i = 0; i < symbols.length; i++) {
const symbol = symbols[i];
const market = this.market(symbol);
subscriptionArgs.push(this.safeStringLower(market, 'id') + '@ticker');
messageHashes.push('ticker:' + market['symbol']);
}
const newTicker = await this.watchMultiple(url, messageHashes, this.extend(request, params), [type]);
if (this.newUpdates) {
const result = {};
result[newTicker['symbol']] = newTicker;
return result;
}
return this.filterByArray(this.tickers, 'symbol', symbols);
}
/**
* @method
* @name aster#unWatchTickers
* @description unWatches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#full-ticker-per-symbol
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#individual-symbol-ticker-streams
* @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 unWatchTickers(symbols = undefined, params = {}) {
await this.loadMarkets();
symbols = this.marketSymbols(symbols, undefined, true, true, true);
const firstMarket = this.getMarketFromSymbols(symbols);
const type = this.safeString(firstMarket, 'type', 'swap');
const symbolsLength = symbols.length;
let methodName = undefined;
[methodName, params] = this.handleParamString(params, 'callerMethodName', 'unWatchTickers');
params = this.omit(params, 'callerMethodName');
if (symbolsLength === 0) {
throw new ArgumentsRequired(this.id + ' ' + methodName + '() requires a non-empty array of symbols');
}
const url = this.urls['api']['ws'][type];
const subscriptionArgs = [];
const messageHashes = [];
const request = {
'method': 'UNSUBSCRIBE',
'params': subscriptionArgs,
};
for (let i = 0; i < symbols.length; i++) {
const symbol = symbols[i];
const market = this.market(symbol);
subscriptionArgs.push(this.safeStringLower(market, 'id') + '@ticker');
messageHashes.push('unsubscribe:ticker:' + market['symbol']);
}
return await this.watchMultiple(url, messageHashes, this.extend(request, params), [type]);
}
/**
* @method
* @name aster#watchMarkPrice
* @description watches a mark price for a specific market
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#mark-price-stream
* @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 {boolean} [params.use1sFreq] *default is true* if set to true, the mark price will be updated every second, otherwise every 3 seconds
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
*/
async watchMarkPrice(symbol, params = {}) {
params['callerMethodName'] = 'watchMarkPrice';
await this.loadMarkets();
symbol = this.safeSymbol(symbol);
const tickers = await this.watchMarkPrices([symbol], params);
return tickers[symbol];
}
/**
* @method
* @name aster#unWatchMarkPrice
* @description unWatches a mark price for a specific market
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#mark-price-stream
* @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 {boolean} [params.use1sFreq] *default is true* if set to true, the mark price will be updated every second, otherwise every 3 seconds
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
*/
async unWatchMarkPrice(symbol, params = {}) {
params['callerMethodName'] = 'unWatchMarkPrice';
return await this.unWatchMarkPrices([symbol], params);
}
/**
* @method
* @name aster#watchMarkPrices
* @description watches the mark price for all markets
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#mark-price-stream
* @param {string[]} symbols unified symbol of the market to fetch the ticker for
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {boolean} [params.use1sFreq] *default is true* if set to true, the mark price will be updated every second, otherwise every 3 seconds
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
*/
async watchMarkPrices(symbols = undefined, params = {}) {
await this.loadMarkets();
symbols = this.marketSymbols(symbols, undefined, true, true, true);
const firstMarket = this.getMarketFromSymbols(symbols);
const type = this.safeString(firstMarket, 'type', 'swap');
const symbolsLength = symbols.length;
let methodName = undefined;
[methodName, params] = this.handleParamString(params, 'callerMethodName', 'watchMarkPrices');
params = this.omit(params, 'callerMethodName');
if (symbolsLength === 0) {
throw new ArgumentsRequired(this.id + ' ' + methodName + '() requires a non-empty array of symbols');
}
const url = this.urls['api']['ws'][type];
const subscriptionArgs = [];
const messageHashes = [];
const request = {
'method': 'SUBSCRIBE',
'params': subscriptionArgs,
};
const use1sFreq = this.safeBool(params, 'use1sFreq', true);
for (let i = 0; i < symbols.length; i++) {
const symbol = symbols[i];
const market = this.market(symbol);
const suffix = (use1sFreq) ? '@1s' : '';
subscriptionArgs.push(this.safeStringLower(market, 'id') + '@markPrice' + suffix);
messageHashes.push('ticker:' + market['symbol']);
}
const newTicker = await this.watchMultiple(url, messageHashes, this.extend(request, params), [type]);
if (this.newUpdates) {
const result = {};
result[newTicker['symbol']] = newTicker;
return result;
}
return this.filterByArray(this.tickers, 'symbol', symbols);
}
/**
* @method
* @name aster#unWatchMarkPrices
* @description watches the mark price for all markets
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#mark-price-stream
* @param {string[]} symbols unified symbol of the market to fetch the ticker for
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {boolean} [params.use1sFreq] *default is true* if set to true, the mark price will be updated every second, otherwise every 3 seconds
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
*/
async unWatchMarkPrices(symbols = undefined, params = {}) {
await this.loadMarkets();
symbols = this.marketSymbols(symbols, undefined, true, true, true);
const firstMarket = this.getMarketFromSymbols(symbols);
const type = this.safeString(firstMarket, 'type', 'swap');
const symbolsLength = symbols.length;
let methodName = undefined;
[methodName, params] = this.handleParamString(params, 'callerMethodName', 'unWatchMarkPrices');
params = this.omit(params, 'callerMethodName');
if (symbolsLength === 0) {
throw new ArgumentsRequired(this.id + ' ' + methodName + '() requires a non-empty array of symbols');
}
const url = this.urls['api']['ws'][type];
const subscriptionArgs = [];
const messageHashes = [];
const request = {
'method': 'UNSUBSCRIBE',
'params': subscriptionArgs,
};
const use1sFreq = this.safeBool(params, 'use1sFreq', true);
for (let i = 0; i < symbols.length; i++) {
const symbol = symbols[i];
const market = this.market(symbol);
const suffix = (use1sFreq) ? '@1s' : '';
subscriptionArgs.push(this.safeStringLower(market, 'id') + '@markPrice' + suffix);
messageHashes.push('unsubscribe:ticker:' + market['symbol']);
}
return await this.watchMultiple(url, messageHashes, this.extend(request, params), [type]);
}
handleTicker(client, message) {
//
// {
// "stream": "trumpusdt@ticker",
// "data": {
// "e": "24hrTicker",
// "E": 1754451187277,
// "s": "CAKEUSDT",
// "p": "-0.08800",
// "P": "-3.361",
// "w": "2.58095",
// "c": "2.53000",
// "Q": "5",
// "o": "2.61800",
// "h": "2.64700",
// "l": "2.52400",
// "v": "15775",
// "q": "40714.46000",
// "O": 1754364780000,
// "C": 1754451187274,
// "F": 6571389,
// "L": 6574507,
// "n": 3119
// }
// }
// {
// "stream": "btcusdt@markPrice",
// "data": {
// "e": "markPriceUpdate",
// "E": 1754660466000,
// "s": "BTCUSDT",
// "p": "116809.60000000",
// "P": "116595.54012838",
// "i": "116836.93534884",
// "r": "0.00010000",
// "T": 1754668800000
// }
// }
//
const subscriptions = client.subscriptions;
const subscriptionsKeys = Object.keys(subscriptions);
const marketType = this.getAccountTypeFromSubscriptions(subscriptionsKeys);
const ticker = this.safeDict(message, 'data');
const parsed = this.parseWsTicker(ticker, marketType);
const symbol = parsed['symbol'];
const messageHash = 'ticker:' + symbol;
this.tickers[symbol] = parsed;
client.resolve(this.tickers[symbol], messageHash);
}
parseWsTicker(message, marketType) {
const event = this.safeString(message, 'e');
const part = event.split('@');
const channel = this.safeString(part, 1);
const marketId = this.safeString(message, 's');
const timestamp = this.safeInteger(message, 'E');
const market = this.safeMarket(marketId, undefined, undefined, marketType);
const last = this.safeString(message, 'c');
if (channel === 'markPriceUpdate') {
return this.safeTicker({
'symbol': market['symbol'],
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
'info': message,
'markPrice': this.safeString(message, 'p'),
'indexPrice': this.safeString(message, 'i'),
});
}
return this.safeTicker({
'symbol': market['symbol'],
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
'high': this.safeString(message, 'h'),
'low': this.safeString(message, 'l'),
'bid': undefined,
'bidVolume': undefined,
'ask': undefined,
'askVolume': undefined,
'vwap': this.safeString(message, 'w'),
'open': this.safeString(message, 'o'),
'close': last,
'last': last,
'previousClose': undefined,
'change': this.safeString(message, 'p'),
'percentage': this.safeString(message, 'P'),
'average': undefined,
'baseVolume': this.safeString(message, 'v'),
'quoteVolume': this.safeString(message, 'q'),
'info': message,
}, market);
}
/**
* @method
* @name aster#watchBidsAsks
* @description watches best bid & ask for symbols
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#best-order-book-information-by-symbol
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#individual-symbol-book-ticker-streams
* @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 watchBidsAsks(symbols = undefined, params = {}) {
await this.loadMarkets();
symbols = this.marketSymbols(symbols, undefined, true, true, true);
const firstMarket = this.getMarketFromSymbols(symbols);
const type = this.safeString(firstMarket, 'type', 'swap');
const symbolsLength = symbols.length;
if (symbolsLength === 0) {
throw new ArgumentsRequired(this.id + ' watchBidsAsks() requires a non-empty array of symbols');
}
const url = this.urls['api']['ws'][type];
const subscriptionArgs = [];
const messageHashes = [];
const request = {
'method': 'SUBSCRIBE',
'params': subscriptionArgs,
};
for (let i = 0; i < symbols.length; i++) {
const symbol = symbols[i];
const market = this.market(symbol);
subscriptionArgs.push(this.safeStringLower(market, 'id') + '@bookTicker');
messageHashes.push('bidask:' + market['symbol']);
}
const newTicker = await this.watchMultiple(url, messageHashes, this.extend(request, params), [type]);
if (this.newUpdates) {
const result = {};
result[newTicker['symbol']] = newTicker;
return result;
}
return this.filterByArray(this.bidsasks, 'symbol', symbols);
}
/**
* @method
* @name aster#unWatchBidsAsks
* @description unWatches best bid & ask for symbols
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#best-order-book-information-by-symbol
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#individual-symbol-book-ticker-streams
* @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 unWatchBidsAsks(symbols = undefined, params = {}) {
await this.loadMarkets();
symbols = this.marketSymbols(symbols, undefined, true, true, true);
const firstMarket = this.getMarketFromSymbols(symbols);
const type = this.safeString(firstMarket, 'type', 'swap');
const symbolsLength = symbols.length;
if (symbolsLength === 0) {
throw new ArgumentsRequired(this.id + ' unWatchBidsAsks() requires a non-empty array of symbols');
}
const url = this.urls['api']['ws'][type];
const subscriptionArgs = [];
const messageHashes = [];
const request = {
'method': 'UNSUBSCRIBE',
'params': subscriptionArgs,
};
for (let i = 0; i < symbols.length; i++) {
const symbol = symbols[i];
const market = this.market(symbol);
subscriptionArgs.push(this.safeStringLower(market, 'id') + '@bookTicker');
messageHashes.push('unsubscribe:bidask:' + market['symbol']);
}
return await this.watchMultiple(url, messageHashes, this.extend(request, params), [type]);
}
handleBidAsk(client, message) {
//
// {
// "stream": "btcusdt@bookTicker",
// "data": {
// "e": "bookTicker",
// "u": 157240846459,
// "s": "BTCUSDT",
// "b": "122046.7",
// "B": "1.084",
// "a": "122046.8",
// "A": "0.001",
// "T": 1754896692922,
// "E": 1754896692926
// }
// }
//
const subscriptions = client.subscriptions;
const subscriptionsKeys = Object.keys(subscriptions);
const marketType = this.getAccountTypeFromSubscriptions(subscriptionsKeys);
const data = this.safeDict(message, 'data', {});
const marketId = this.safeString(data, 's');
const market = this.safeMarket(marketId, undefined, undefined, marketType);
const ticker = this.parseWsBidAsk(data, market);
const symbol = ticker['symbol'];
this.bidsasks[symbol] = ticker;
const messageHash = 'bidask:' + symbol;
client.resolve(ticker, messageHash);
}
parseWsBidAsk(message, market = undefined) {
const timestamp = this.safeInteger(message, 'T');
return this.safeTicker({
'symbol': market['symbol'],
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
'ask': this.safeString(message, 'a'),
'askVolume': this.safeString(message, 'A'),
'bid': this.safeString(message, 'b'),
'bidVolume': this.safeString(message, 'B'),
'info': message,
}, market);
}
/**
* @method
* @name aster#watchTrades
* @description watches information on multiple trades made in a market
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#collection-transaction-flow
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#aggregate-trade-streams
* @param {string} symbol unified market symbol of the market trades were made in
* @param {int} [since] the earliest time in ms to fetch trades for
* @param {int} [limit] the maximum number of trade structures to retrieve
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
*/
async watchTrades(symbol, since = undefined, limit = undefined, params = {}) {
params['callerMethodName'] = 'watchTrades';
return await this.watchTradesForSymbols([symbol], since, limit, params);
}
/**
* @method
* @name aster#unWatchTrades
* @description unsubscribe from the trades channel
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#collection-transaction-flow
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#aggregate-trade-streams
* @param {string} symbol unified market symbol of the market trades were made in
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
*/
async unWatchTrades(symbol, params = {}) {
params['callerMethodName'] = 'unWatchTrades';
return await this.unWatchTradesForSymbols([symbol], params);
}
/**
* @method
* @name aster#watchTradesForSymbols
* @description get the list of most recent trades for a list of symbols
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#collection-transaction-flow
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#aggregate-trade-streams
* @param {string[]} symbols 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://docs.ccxt.com/#/?id=public-trades}
*/
async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
await this.loadMarkets();
symbols = this.marketSymbols(symbols, undefined, true, true, true);
const firstMarket = this.getMarketFromSymbols(symbols);
const type = this.safeString(firstMarket, 'type', 'swap');
const symbolsLength = symbols.length;
let methodName = undefined;
[methodName, params] = this.handleParamString(params, 'callerMethodName', 'watchTradesForSymbols');
params = this.omit(params, 'callerMethodName');
if (symbolsLength === 0) {
throw new ArgumentsRequired(this.id + ' ' + methodName + '() requires a non-empty array of symbols');
}
const url = this.urls['api']['ws'][type];
const subscriptionArgs = [];
const messageHashes = [];
const request = {
'method': 'SUBSCRIBE',
'params': subscriptionArgs,
};
for (let i = 0; i < symbols.length; i++) {
const symbol = symbols[i];
const market = this.market(symbol);
subscriptionArgs.push(this.safeStringLower(market, 'id') + '@aggTrade');
messageHashes.push('trade:' + market['symbol']);
}
const trades = await this.watchMultiple(url, messageHashes, this.extend(request, params), [type]);
if (this.newUpdates) {
const first = this.safeValue(trades, 0);
const tradeSymbol = this.safeString(first, 'symbol');
limit = trades.getLimit(tradeSymbol, limit);
}
return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
}
/**
* @method
* @name aster#unWatchTradesForSymbols
* @description unsubscribe from the trades channel
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#collection-transaction-flow
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#aggregate-trade-streams
* @param {string[]} symbols unified symbol of the market to fetch trades for
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
*/
async unWatchTradesForSymbols(symbols, params = {}) {
await this.loadMarkets();
symbols = this.marketSymbols(symbols, undefined, true, true, true);
const firstMarket = this.getMarketFromSymbols(symbols);
const type = this.safeString(firstMarket, 'type', 'swap');
const symbolsLength = symbols.length;
let methodName = undefined;
[methodName, params] = this.handleParamString(params, 'callerMethodName', 'unWatchTradesForSymbols');
params = this.omit(params, 'callerMethodName');
if (symbolsLength === 0) {
throw new ArgumentsRequired(this.id + ' ' + methodName + '() requires a non-empty array of symbols');
}
const url = this.urls['api']['ws'][type];
const subscriptionArgs = [];
const messageHashes = [];
const request = {
'method': 'UNSUBSCRIBE',
'params': subscriptionArgs,
};
for (let i = 0; i < symbols.length; i++) {
const symbol = symbols[i];
const market = this.market(symbol);
subscriptionArgs.push(this.safeStringLower(market, 'id') + '@aggTrade');
messageHashes.push('unsubscribe:trade:' + market['symbol']);
}
return await this.watchMultiple(url, messageHashes, this.extend(request, params), [type]);
}
handleTrade(client, message) {
//
// {
// "stream": "btcusdt@aggTrade",
// "data": {
// "e": "aggTrade",
// "E": 1754551358681,
// "a": 20505890,
// "s": "BTCUSDT",
// "p": "114783.7",
// "q": "0.020",
// "f": 26024678,
// "l": 26024682,
// "T": 1754551358528,
// "m": false
// }
// }
//
const subscriptions = client.subscriptions;
const subscriptionsKeys = Object.keys(subscriptions);
const marketType = this.getAccountTypeFromSubscriptions(subscriptionsKeys);
const trade = this.safeDict(message, 'data');
const marketId = this.safeString(trade, 's');
const market = this.safeMarket(marketId, undefined, undefined, marketType);
const parsed = this.parseWsTrade(trade, market);
const symbol = parsed['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;
}
stored.append(parsed);
const messageHash = 'trade' + ':' + symbol;
client.resolve(stored, messageHash);
}
parseWsTrade(trade, market = undefined) {
const timestamp = this.safeInteger(trade, 'T');
const symbol = market['symbol'];
const amountString = this.safeString(trade, 'q');
const priceString = this.safeString(trade, 'p');
const isMaker = this.safeBool(trade, 'm');
let takerOrMaker = undefined;
if (isMaker !== undefined) {
takerOrMaker = isMaker ? 'maker' : 'taker';
}
return this.safeTrade({
'id': this.safeString(trade, 'a'),
'info': trade,
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
'symbol': symbol,
'order': undefined,
'type': undefined,
'side': undefined,
'takerOrMaker': takerOrMaker,
'price': priceString,
'amount': amountString,
'cost': undefined,
'fee': undefined,
}, market);
}
/**
* @method
* @name aster#watchOrderBook
* @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#limited-depth-information
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#partial-book-depth-streams
* @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://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
*/
async watchOrderBook(symbol, limit = undefined, params = {}) {
params['callerMethodName'] = 'watchOrderBook';
return await this.watchOrderBookForSymbols([symbol], limit, params);
}
/**
* @method
* @name aster#unWatchOrderBook
* @description unsubscribe from the orderbook channel
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#limited-depth-information
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#partial-book-depth-streams
* @param {string} symbol symbol of the market to unwatch the trades for
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {int} [params.limit] orderbook limit, default is undefined
* @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
*/
async unWatchOrderBook(symbol, params = {}) {
params['callerMethodName'] = 'unWatchOrderBook';
return await this.unWatchOrderBookForSymbols([symbol], params);
}
/**
* @method
* @name aster#watchOrderBookForSymbols
* @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#limited-depth-information
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#partial-book-depth-streams
* @param {string[]} symbols unified array of symbols
* @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://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
*/
async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
await this.loadMarkets();
symbols = this.marketSymbols(symbols, undefined, true, true, true);
const firstMarket = this.getMarketFromSymbols(symbols);
const type = this.safeString(firstMarket, 'type', 'swap');
const symbolsLength = symbols.length;
let methodName = undefined;
[methodName, params] = this.handleParamString(params, 'callerMethodName', 'watchOrderBookForSymbols');
params = this.omit(params, 'callerMethodName');
if (symbolsLength === 0) {
throw new ArgumentsRequired(this.id + ' ' + methodName + '() requires a non-empty array of symbols');
}
const url = this.urls['api']['ws'][type];
const subscriptionArgs = [];
const messageHashes = [];
const request = {
'method': 'SUBSCRIBE',
'params': subscriptionArgs,
};
if (limit === undefined || (limit !== 5 && limit !== 10 && limit !== 20)) {
limit = 20;
}
for (let i = 0; i < symbols.length; i++) {
const symbol = symbols[i];
const market = this.market(symbol);
subscriptionArgs.push(this.safeStringLower(market, 'id') + '@depth' + limit);
messageHashes.push('orderbook:' + market['symbol']);
}
const orderbook = await this.watchMultiple(url, messageHashes, this.extend(request, params), [type]);
return orderbook.limit();
}
/**
* @method
* @name aster#unWatchOrderBookForSymbols
* @description unsubscribe from the orderbook channel
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#limited-depth-information
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#partial-book-depth-streams
* @param {string[]} symbols unified symbol of the market to unwatch the trades for
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {int} [params.limit] orderbook limit, default is undefined
* @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
*/
async unWatchOrderBookForSymbols(symbols, params = {}) {
await this.loadMarkets();
symbols = this.marketSymbols(symbols, undefined, true, true, true);
const firstMarket = this.getMarketFromSymbols(symbols);
const type = this.safeString(firstMarket, 'type', 'swap');
const symbolsLength = symbols.length;
let methodName = undefined;
[methodName, params] = this.handleParamString(params, 'callerMethodName', 'unWatchOrderBookForSymbols');
params = this.omit(params, 'callerMethodName');
if (symbolsLength === 0) {
throw new ArgumentsRequired(this.id + ' ' + methodName + '() requires a non-empty array of symbols');
}
const url = this.urls['api']['ws'][type];
const subscriptionArgs = [];
const messageHashes = [];
const request = {
'method': 'UNSUBSCRIBE',
'params': subscriptionArgs,
};
let limit = this.safeNumber(params, 'limit');
params = this.omit(params, 'limit');
if (limit === undefined || (limit !== 5 && limit !== 10 && limit !== 20)) {
limit = 20;
}
for (let i = 0; i < symbols.length; i++) {
const symbol = symbols[i];
const market = this.market(symbol);
subscriptionArgs.push(this.safeStringLower(market, 'id') + '@depth' + limit);
messageHashes.push('unsubscribe:orderbook:' + market['symbol']);
}
return await this.watchMultiple(url, messageHashes, this.extend(request, params), [type]);
}
handleOrderBook(client, message) {
//
// {
// "stream": "btcusdt@depth20",
// "data": {
// "e": "depthUpdate",
// "E": 1754556878284,
// "T": 1754556878031,
// "s": "BTCUSDT",
// "U": 156391349814,
// "u": 156391349814,
// "pu": 156391348236,
// "b": [
// [
// "114988.3",
// "0.147"
// ]
// ],
// "a": [
// [
// "114988.4",
// "1.060"
// ]
// ]
// }
// }
//
const subscriptions = client.subscriptions;
const subscriptionsKeys = Object.keys(subscriptions);
const marketType = this.getAccountTypeFromSubscriptions(subscriptionsKeys);
const data = this.safeDict(message, 'data');
const marketId = this.safeString(data, 's');
const timestamp = this.safeInteger(data, 'T');
const market = this.safeMarket(marketId, undefined, undefined, marketType);
const symbol = market['symbol'];
if (!(symbol in this.orderbooks)) {
this.orderbooks[symbol] = this.orderBook();
}
const orderbook = this.orderbooks[symbol];
const snapshot = this.parseOrderBook(data, symbol, timestamp, 'b', 'a');
orderbook.reset(snapshot);
const messageHash = 'orderbook' + ':' + symbol;
this.orderbooks[symbol] = orderbook;
client.resolve(orderbook, messageHash);
}
/**
* @method
* @name aster#watchOHLCV
* @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#k-line-streams
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#klinecandlestick-streams
* @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} [since] timestamp in ms of the earliest candle to fetch
* @param {int} [limit] the maximum amount of candles to fetch
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
*/
async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
params['callerMethodName'] = 'watchOHLCV';
await this.loadMarkets();
symbol = this.safeSymbol(symbol);
const result = await this.watchOHLCVForSymbols([[symbol, timeframe]], since, limit, params);
return result[symbol][timeframe];
}
/**
* @method
* @name aster#unWatchOHLCV
* @description unWatches historical candlestick data containing the open, high, low, and close price, and the volume of a market
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#k-line-streams
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#klinecandlestick-streams
* @param {string} symbol unified symbol of the market to fetch OHLCV data for
* @param {string} timeframe the length of time each candle represents
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
*/
async unWatchOHLCV(symbol, timeframe = '1m', params = {}) {
params['callerMethodName'] = 'unWatchOHLCV';
return await this.unWatchOHLCVForSymbols([[symbol, timeframe]], params);
}
/**
* @method
* @name aster#watchOHLCVForSymbols
* @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#k-line-streams
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#klinecandlestick-streams
* @param {string[][]} symbolsAndTimeframes array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
* @param {int} [since] timestamp in ms of the earliest candle to fetch
* @param {int} [limit] the maximum amount of candles to fetch
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} A list of candles ordered as timestamp, open, high, low, close, volume
*/
async watchOHLCVForSymbols(symbolsAndTimeframes, since = undefined, limit = undefined, params = {}) {
await this.loadMarkets();
const symbolsLength = symbolsAndTimeframes.length;
let methodName = undefined;
[methodName, params] = this.handleParamString(params, 'callerMethodName', 'watchOHLCVForSymbols');
params = this.omit(params, 'callerMethodName');
if (symbolsLength === 0) {
throw new ArgumentsRequired(this.id + ' ' + methodName + '() requires a non-empty array of symbols');
}
const symbols = this.getListFromObjectValues(symbolsAndTimeframes, 0);
const marketSymbols = this.marketSymbols(symbols, undefined, false, true, true);
const firstMarket = this.market(marketSymbols[0]);
const type = this.safeString(firstMarket, 'type', 'swap');
const url = this.urls['api']['ws'][type];
const subscriptionArgs = [];
const messageHashes = [];
const request = {
'method': 'SUBSCRIBE',
'params': subscriptionArgs,
};
for (let i = 0; i < symbolsAndTimeframes.length; i++) {
const data = symbolsAndTimeframes[i];
let symbolString = this.safeString(data, 0);
const market = this.market(symbolString);
symbolString = market['symbol'];
const unfiedTimeframe = this.safeString(data, 1);
const timeframeId = this.safeString(this.timeframes, unfiedTimeframe, unfiedTimeframe);
subscriptionArgs.push(this.safeStringLower(market, 'id') + '@kline_' + timeframeId);
messageHashes.push('ohlcv:' + market['symbol'] + ':' + unfiedTimeframe);
}
const [symbol, timeframe, stored] = await this.watchMultiple(url, messageHashes, this.extend(request, params), [type]);
if (this.newUpdates) {
limit = stored.getLimit(symbol, limit);
}
const filtered = this.filterBySinceLimit(stored, since, limit, 0, true);
return this.createOHLCVObject(symbol, timeframe, filtered);
}
/**
* @method
* @name aster#unWatchOHLCVForSymbols
* @description unWatches historical candlestick data containing the open, high, low, and close price, and the volume of a market
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#k-line-streams
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#klinecandlestick-streams
* @param {string[][]} symbolsAndTimeframes array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
*/
async unWatchOHLCVForSymbols(symbolsAndTimeframes, params = {}) {
await this.loadMarkets();
const symbolsLength = symbolsAndTimeframes.length;
let methodName = undefined;
[methodName, params] = this.handleParamString(params, 'callerMethodName', 'unWatchOHLCVForSymbols');
params = this.omit(params, 'callerMethodName');
if (symbolsLength === 0) {
throw new ArgumentsRequired(this.id + ' ' + methodName + '() requires a non-empty array of symbols');
}
const symbols = this.getListFromObjectValues(symbolsAndTimeframes, 0);
const marketSymbols = this.marketSymbols(symbols, undefined, false, true, true);
const firstMarket = this.market(marketSymbols[0]);
const type = this.safeString(firstMarket, 'type', 'swap');
const url = this.urls['api']['ws'][type];
const subscriptionArgs = [];
const messageHashes = [];
const request = {
'method': 'UNSUBSCRIBE',
'params': subscriptionArgs,
};
for (let i = 0; i < symbolsAndTimeframes.length; i++) {
const data = symbolsAndTimeframes[i];
let symbolString = this.safeString(data, 0);
const market = this.market(symbolString);
symbolString = market['symbol'];
const unfiedTimeframe = this.safeString(data, 1);
const timeframeId = this.safeString(this.timeframes, unfiedTimeframe, unfiedTimeframe);
subscriptionArgs.push(this.safeStringLower(market, 'id') + '@kline_' + timeframeId);
messageHashes.push('unsubscribe:ohlcv:' + market['symbol'] + ':' + unfiedTimeframe);
}
return await this.watchMultiple(url, messageHashes, this.extend(request, params), [type]);
}
handleOHLCV(client, message) {
//
// {
// "stream": "btcusdt@kline_1m",
// "data": {
// "e": "kline",
// "E": 1754655777119,
// "s": "BTCUSDT",
// "k": {
// "t": 1754655720000,
// "T": 1754655779999,
// "s": "BTCUSDT",
// "i": "1m",
// "f": 26032629,
// "L": 26032629,
// "o": "116546.9",
// "c": "116546.9",
// "h": "116546.9",
// "l": "116546.9",
// "v": "0.011",
// "n": 1,
// "x": false,
// "q": "1282.0159",
// "V": "0.000",
// "Q": "0.0000",
// "B": "0"