ccxt
Version:
1,193 lines (1,191 loc) • 173 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 Exchange from './abstract/aster.js';
import { AccountNotEnabled, AccountSuspended, ArgumentsRequired, AuthenticationError, BadRequest, BadResponse, BadSymbol, DuplicateOrderId, ExchangeClosedByUser, ExchangeError, InsufficientFunds, InvalidNonce, InvalidOrder, MarketClosed, NetworkError, NoChange, NotSupported, OperationFailed, OperationRejected, OrderImmediatelyFillable, OrderNotFillable, OrderNotFound, PermissionDenied, RateLimitExceeded, RequestTimeout } from './base/errors.js';
import { TRUNCATE, TICK_SIZE } from './base/functions/number.js';
import Precise from './base/Precise.js';
import { sha256 } from './static_dependencies/noble-hashes/sha256.js';
import { ecdsa } from './base/functions/crypto.js';
import { keccak_256 as keccak } from './static_dependencies/noble-hashes/sha3.js';
import { secp256k1 } from './static_dependencies/noble-curves/secp256k1.js';
// ---------------------------------------------------------------------------xs
/**
* @class aster
* @augments Exchange
*/
export default class aster extends Exchange {
describe() {
return this.deepExtend(super.describe(), {
'id': 'aster',
'name': 'Aster',
'dex': true,
'countries': ['US'],
// 3 req/s for free
// 150 req/s for subscribers: https://aster.markets/data
// for brokers: https://aster.markets/docs/api-references/broker-api/#authentication-and-rate-limit
'rateLimit': 333,
'hostname': 'aster.markets',
'pro': true,
'urls': {
'logo': 'https://github.com/user-attachments/assets/4982201b-73cd-4d7a-8907-e69e239e9609',
'www': 'https://www.asterdex.com/en',
'api': {
'fapiPublic': 'https://fapi.asterdex.com/fapi',
'fapiPrivate': 'https://fapi.asterdex.com/fapi',
'sapiPublic': 'https://sapi.asterdex.com/api',
'sapiPrivate': 'https://sapi.asterdex.com/api',
},
'doc': 'https://github.com/asterdex/api-docs',
'fees': 'https://docs.asterdex.com/product/asterex-simple/fees-and-slippage',
'referral': {
'url': 'https://www.asterdex.com/en/referral/aA1c2B',
'discount': 0.1,
},
},
'has': {
'CORS': undefined,
'spot': false,
'margin': false,
'swap': false,
'future': false,
'option': false,
'addMargin': true,
'borrowCrossMargin': false,
'borrowIsolatedMargin': false,
'cancelAllOrders': true,
'cancelOrder': true,
'cancelOrders': true,
'closeAllPositions': false,
'closePosition': false,
'createConvertTrade': false,
'createDepositAddress': false,
'createLimitBuyOrder': false,
'createLimitSellOrder': false,
'createMarketBuyOrder': false,
'createMarketBuyOrderWithCost': false,
'createMarketOrderWithCost': false,
'createMarketSellOrder': false,
'createMarketSellOrderWithCost': false,
'createOrder': true,
'createOrders': false,
'createOrderWithTakeProfitAndStopLoss': false,
'createPostOnlyOrder': false,
'createReduceOnlyOrder': false,
'createStopLimitOrder': false,
'createStopLossOrder': false,
'createStopMarketOrder': false,
'createStopOrder': false,
'createTakeProfitOrder': false,
'createTrailingPercentOrder': false,
'createTriggerOrder': false,
'editOrder': false,
'editOrders': false,
'fetchAccounts': undefined,
'fetchBalance': true,
'fetchBidsAsks': false,
'fetchBorrowInterest': false,
'fetchBorrowRateHistories': false,
'fetchBorrowRateHistory': false,
'fetchCanceledAndClosedOrders': 'emulated',
'fetchCanceledOrders': 'emulated',
'fetchClosedOrder': false,
'fetchClosedOrders': 'emulated',
'fetchConvertCurrencies': false,
'fetchConvertQuote': false,
'fetchConvertTrade': false,
'fetchConvertTradeHistory': false,
'fetchCrossBorrowRate': false,
'fetchCrossBorrowRates': false,
'fetchCurrencies': true,
'fetchDeposit': false,
'fetchDepositAddress': false,
'fetchDepositAddresses': false,
'fetchDepositAddressesByNetwork': false,
'fetchDeposits': false,
'fetchDepositsWithdrawals': false,
'fetchDepositWithdrawFee': 'emulated',
'fetchDepositWithdrawFees': false,
'fetchFundingHistory': true,
'fetchFundingInterval': 'emulated',
'fetchFundingIntervals': true,
'fetchFundingRate': true,
'fetchFundingRateHistory': true,
'fetchFundingRates': true,
'fetchGreeks': false,
'fetchIndexOHLCV': false,
'fetchIsolatedBorrowRate': 'emulated',
'fetchIsolatedBorrowRates': false,
'fetchL3OrderBook': false,
'fetchLastPrices': false,
'fetchLedger': true,
'fetchLedgerEntry': false,
'fetchLeverage': 'emulated',
'fetchLeverages': true,
'fetchLeverageTiers': false,
'fetchLiquidations': false,
'fetchLongShortRatio': false,
'fetchLongShortRatioHistory': false,
'fetchMarginAdjustmentHistory': true,
'fetchMarginMode': 'emulated',
'fetchMarginModes': true,
'fetchMarketLeverageTiers': 'emulated',
'fetchMarkets': true,
'fetchMarkOHLCV': false,
'fetchMarkPrice': false,
'fetchMarkPrices': false,
'fetchMyLiquidations': false,
'fetchMySettlementHistory': false,
'fetchMyTrades': true,
'fetchOHLCV': true,
'fetchOpenInterest': false,
'fetchOpenInterestHistory': false,
'fetchOpenOrder': true,
'fetchOpenOrders': true,
'fetchOption': false,
'fetchOptionChain': false,
'fetchOrder': true,
'fetchOrderBook': true,
'fetchOrderBooks': false,
'fetchOrders': true,
'fetchOrderTrades': false,
'fetchPosition': false,
'fetchPositionHistory': false,
'fetchPositionMode': true,
'fetchPositions': true,
'fetchPositionsHistory': false,
'fetchPositionsRisk': true,
'fetchPremiumIndexOHLCV': false,
'fetchSettlementHistory': false,
'fetchStatus': false,
'fetchTicker': true,
'fetchTickers': true,
'fetchTime': true,
'fetchTrades': true,
'fetchTradingFee': true,
'fetchTradingFees': false,
'fetchTradingLimits': 'emulated',
'fetchTransactionFee': 'emulated',
'fetchTransactionFees': false,
'fetchTransactions': false,
'fetchTransfer': false,
'fetchTransfers': false,
'fetchUnderlyingAssets': false,
'fetchVolatilityHistory': false,
'fetchWithdrawAddresses': false,
'fetchWithdrawal': false,
'fetchWithdrawals': false,
'fetchWithdrawalWhitelist': false,
'reduceMargin': true,
'repayCrossMargin': false,
'repayIsolatedMargin': false,
'sandbox': false,
'setLeverage': true,
'setMargin': false,
'setMarginMode': true,
'setPositionMode': true,
'signIn': false,
'transfer': true,
'withdraw': true,
},
'api': {
'fapiPublic': {
'get': [
'v1/ping',
'v1/time',
'v1/exchangeInfo',
'v1/depth',
'v1/trades',
'v1/historicalTrades',
'v1/aggTrades',
'v1/klines',
'v1/indexPriceKlines',
'v1/markPriceKlines',
'v1/premiumIndex',
'v1/fundingRate',
'v1/fundingInfo',
'v1/ticker/24hr',
'v1/ticker/price',
'v1/ticker/bookTicker',
'v1/adlQuantile',
'v1/forceOrders',
],
'post': [
'v1/listenKey',
],
'put': [
'v1/listenKey',
],
'delete': [
'v1/listenKey',
],
},
'fapiPrivate': {
'get': [
'v1/positionSide/dual',
'v1/multiAssetsMargin',
'v1/order',
'v1/openOrder',
'v1/openOrders',
'v1/allOrders',
'v2/balance',
'v3/balance',
'v3/account',
'v4/account',
'v1/positionMargin/history',
'v2/positionRisk',
'v3/positionRisk',
'v1/userTrades',
'v1/income',
'v1/leverageBracket',
'v1/commissionRate',
],
'post': [
'v1/positionSide/dual',
'v1/multiAssetsMargin',
'v1/order',
'v1/order/test',
'v1/batchOrders',
'v1/asset/wallet/transfer',
'v1/countdownCancelAll',
'v1/leverage',
'v1/marginType',
'v1/positionMargin',
],
'delete': [
'v1/order',
'v1/allOpenOrders',
'v1/batchOrders',
],
},
'sapiPublic': {
'get': [
'v1/ping',
'v1/time',
'v1/exchangeInfo',
'v1/depth',
'v1/trades',
'v1/historicalTrades',
'v1/aggTrades',
'v1/klines',
'v1/ticker/24hr',
'v1/ticker/price',
'v1/ticker/bookTicker',
'v1/aster/withdraw/estimateFee',
],
'post': [
'v1/getNonce',
'v1/createApiKey',
'v1/listenKey',
],
'put': [
'v1/listenKey',
],
'delete': [
'v1/listenKey',
],
},
'sapiPrivate': {
'get': [
'v1/commissionRate',
'v1/order',
'v1/openOrders',
'v1/allOrders',
'v1/transactionHistory',
'v1/account',
'v1/userTrades',
],
'post': [
'v1/order',
'v1/asset/wallet/transfer',
'v1/asset/sendToAddress',
'v1/aster/user-withdraw',
],
'delete': [
'v1/order',
'v1/allOpenOrders',
],
},
},
'timeframes': {
'1m': '1m',
'3m': '3m',
'5m': '5m',
'15m': '15m',
'30m': '30m',
'1h': '1h',
'2h': '2h',
'4h': '4h',
'6h': '6h',
'8h': '8h',
'12h': '12h',
'1d': '1d',
'3d': '3d',
'1w': '1w',
'1M': '1M',
},
'precisionMode': TICK_SIZE,
'requiredCredentials': {
'apiKey': true,
'secret': true,
},
'fees': {
'trading': {
'tierBased': true,
'percentage': true,
'maker': this.parseNumber('0.0001'),
'taker': this.parseNumber('0.00035'),
},
},
'options': {
'recvWindow': 10 * 1000,
'defaultTimeInForce': 'GTC',
'zeroAddress': '0x0000000000000000000000000000000000000000',
'quoteOrderQty': true,
'accountsByType': {
'spot': 'SPOT',
'future': 'FUTURE',
'linear': 'FUTURE',
'swap': 'FUTURE',
},
'networks': {
'ERC20': 'ETH',
'BEP20': 'BSC',
'ARB': 'Arbitrum',
},
'networksToChainId': {
'ETH': 1,
'BSC': 56,
'Arbitrum': 42161,
},
},
'exceptions': {
'exact': {
// 10xx - General Server or Network issues
'-1000': OperationFailed,
'-1001': NetworkError,
'-1002': AuthenticationError,
'-1003': RateLimitExceeded,
'-1004': DuplicateOrderId,
'-1005': BadRequest,
'-1006': BadResponse,
'-1007': RequestTimeout,
'-1010': OperationFailed,
'-1011': PermissionDenied,
'-1013': BadRequest,
'-1014': OrderNotFillable,
'-1015': RateLimitExceeded,
'-1016': ExchangeClosedByUser,
'-1020': NotSupported,
'-1021': InvalidNonce,
'-1022': AuthenticationError,
'-1023': BadRequest,
// 11xx - Request issues
'-1100': BadRequest,
'-1101': BadRequest,
'-1102': ArgumentsRequired,
'-1103': BadRequest,
'-1104': BadRequest,
'-1105': ArgumentsRequired,
'-1106': BadRequest,
'-1108': BadRequest,
'-1109': BadRequest,
'-1110': BadSymbol,
'-1111': BadRequest,
'-1112': BadRequest,
'-1113': BadRequest,
'-1114': BadRequest,
'-1115': InvalidOrder,
'-1116': InvalidOrder,
'-1117': InvalidOrder,
'-1118': InvalidOrder,
'-1119': InvalidOrder,
'-1120': BadRequest,
'-1121': BadSymbol,
'-1125': AuthenticationError,
'-1127': BadRequest,
'-1128': BadRequest,
'-1130': BadRequest,
'-1136': InvalidOrder,
// 20xx - Processing Issues
'-2010': InvalidOrder,
'-2011': OrderNotFound,
'-2013': OrderNotFound,
'-2014': AuthenticationError,
'-2015': AuthenticationError,
'-2016': MarketClosed,
'-2018': InsufficientFunds,
'-2019': InsufficientFunds,
'-2020': OrderNotFillable,
'-2021': OrderImmediatelyFillable,
'-2022': OperationRejected,
'-2023': AccountSuspended,
'-2024': InsufficientFunds,
'-2025': RateLimitExceeded,
'-2026': NotSupported,
'-2027': BadRequest,
'-2028': BadRequest,
// 40xx - Filters and other Issues
'-4000': InvalidOrder,
'-4001': InvalidOrder,
'-4002': InvalidOrder,
'-4003': InvalidOrder,
'-4004': InvalidOrder,
'-4005': InvalidOrder,
'-4006': InvalidOrder,
'-4007': InvalidOrder,
'-4008': InvalidOrder,
'-4009': InvalidOrder,
'-4010': InvalidOrder,
'-4011': InvalidOrder,
'-4012': RateLimitExceeded,
'-4013': InvalidOrder,
'-4014': InvalidOrder,
'-4015': InvalidOrder,
'-4016': InvalidOrder,
'-4017': InvalidOrder,
'-4018': InvalidOrder,
'-4019': BadRequest,
'-4020': BadRequest,
'-4021': BadRequest,
'-4022': MarketClosed,
'-4023': InvalidOrder,
'-4024': InvalidOrder,
'-4025': BadRequest,
'-4026': BadRequest,
'-4027': BadRequest,
'-4028': BadRequest,
'-4029': BadRequest,
'-4030': BadRequest,
'-4031': BadRequest,
'-4032': RateLimitExceeded,
'-4033': AccountNotEnabled,
'-4044': BadRequest,
'-4045': RateLimitExceeded,
'-4046': NoChange,
'-4047': OperationRejected,
'-4048': OperationRejected,
'-4049': OperationRejected,
'-4050': InsufficientFunds,
'-4051': InsufficientFunds,
'-4052': NoChange,
'-4053': OperationRejected,
'-4054': OperationRejected,
'-4055': ArgumentsRequired,
'-4056': AuthenticationError,
'-4057': AuthenticationError,
'-4058': InvalidOrder,
'-4059': NoChange,
'-4060': InvalidOrder,
'-4061': InvalidOrder,
'-4062': OperationRejected,
'-4063': BadRequest,
'-4064': BadRequest,
'-4065': BadRequest,
'-4066': BadRequest,
'-4067': OperationRejected,
'-4068': OperationRejected,
'-4069': BadRequest,
'-4070': InvalidOrder,
'-4071': InvalidOrder,
'-4072': NoChange,
'-4073': BadRequest,
'-4074': InvalidOrder,
'-4075': OperationRejected,
'-4076': OperationRejected,
'-4077': RateLimitExceeded,
'-4078': BadRequest,
'-4079': BadRequest,
'-4080': BadRequest,
'-4081': BadRequest,
'-4082': RateLimitExceeded,
'-4083': OperationFailed,
'-4084': NotSupported,
'-4085': BadRequest,
'-4086': BadRequest,
'-4087': PermissionDenied,
'-4088': PermissionDenied,
'-4104': BadSymbol,
'-4114': InvalidOrder,
'-4115': DuplicateOrderId,
'-4118': InsufficientFunds,
'-4131': InvalidOrder,
'-4135': InvalidOrder,
'-4137': InvalidOrder,
'-4138': OperationRejected,
'-4139': InvalidOrder,
'-4140': OperationRejected,
'-4141': MarketClosed,
'-4142': InvalidOrder,
'-4144': BadSymbol,
'-4161': OperationRejected,
'-4164': InvalidOrder,
'-4165': BadRequest,
'-4183': InvalidOrder,
'-4184': InvalidOrder,
'-5060': OperationRejected,
'-5076': OperationRejected, // {"code":-5076,"msg":"Total order value should be more than 5 USDT"}
},
'broad': {},
},
});
}
isInverse(type, subType = undefined) {
if (subType === undefined) {
return (type === 'delivery');
}
else {
return subType === 'inverse';
}
}
isLinear(type, subType = undefined) {
if (subType === undefined) {
return (type === 'future') || (type === 'swap');
}
else {
return subType === 'linear';
}
}
/**
* @method
* @name aster#fetchCurrencies
* @description fetches all available currencies on an exchange
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#trading-specification-information
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#exchange-information
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} an associative dictionary of currencies
*/
async fetchCurrencies(params = {}) {
const promises = [
this.sapiPublicGetV1ExchangeInfo(params),
this.fapiPublicGetV1ExchangeInfo(params),
];
const results = await Promise.all(promises);
const sapiResult = this.safeDict(results, 0, {});
const sapiRows = this.safeList(sapiResult, 'assets', []);
const fapiResult = this.safeDict(results, 1, {});
const fapiRows = this.safeList(fapiResult, 'assets', []);
const rows = this.arrayConcat(sapiRows, fapiRows);
//
// [
// {
// "asset": "USDT",
// "marginAvailable": true,
// "autoAssetExchange": "-10000"
// }
// ]
//
const result = {};
for (let i = 0; i < rows.length; i++) {
const currency = rows[i];
const currencyId = this.safeString(currency, 'asset');
const code = this.safeCurrencyCode(currencyId);
result[code] = this.safeCurrencyStructure({
'info': currency,
'code': code,
'id': currencyId,
'name': code,
'active': undefined,
'deposit': undefined,
'withdraw': undefined,
'fee': undefined,
'precision': undefined,
'limits': {
'amount': {
'min': undefined,
'max': undefined,
},
'withdraw': {
'min': undefined,
'max': undefined,
},
'deposit': {
'min': undefined,
'max': undefined,
},
},
'networks': undefined,
'type': 'crypto', // atm exchange api provides only cryptos
});
}
return result;
}
/**
* @method
* @name aster#fetchMarkets
* @description retrieves data on all markets for bigone
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#trading-specification-information
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#exchange-information
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object[]} an array of objects representing market data
*/
async fetchMarkets(params = {}) {
const promises = [
this.sapiPublicGetV1ExchangeInfo(params),
this.fapiPublicGetV1ExchangeInfo(params),
];
const results = await Promise.all(promises);
const sapiResult = this.safeDict(results, 0, {});
const sapiRows = this.safeList(sapiResult, 'symbols', []);
const fapiResult = this.safeDict(results, 1, {});
const fapiRows = this.safeList(fapiResult, 'symbols', []);
const rows = this.arrayConcat(sapiRows, fapiRows);
//
// [
// {
// "symbol": "BTCUSDT",
// "pair": "BTCUSDT",
// "contractType": "PERPETUAL",
// "deliveryDate": 4133404800000,
// "onboardDate": 1627628400000,
// "status": "TRADING",
// "maintMarginPercent": "2.5000",
// "requiredMarginPercent": "5.0000",
// "baseAsset": "BTC",
// "quoteAsset": "USDT",
// "marginAsset": "USDT",
// "pricePrecision": 1,
// "quantityPrecision": 3,
// "baseAssetPrecision": 8,
// "quotePrecision": 8,
// "underlyingType": "COIN",
// "underlyingSubType": [],
// "settlePlan": 0,
// "triggerProtect": "0.0200",
// "liquidationFee": "0.025000",
// "marketTakeBound": "0.02",
// "filters": [
// {
// "minPrice": "1",
// "maxPrice": "1000000",
// "filterType": "PRICE_FILTER",
// "tickSize": "0.1"
// },
// {
// "stepSize": "0.001",
// "filterType": "LOT_SIZE",
// "maxQty": "100",
// "minQty": "0.001"
// },
// {
// "stepSize": "0.001",
// "filterType": "MARKET_LOT_SIZE",
// "maxQty": "10",
// "minQty": "0.001"
// },
// {
// "limit": 200,
// "filterType": "MAX_NUM_ORDERS"
// },
// {
// "limit": 10,
// "filterType": "MAX_NUM_ALGO_ORDERS"
// },
// {
// "notional": "5",
// "filterType": "MIN_NOTIONAL"
// },
// {
// "multiplierDown": "0.9800",
// "multiplierUp": "1.0200",
// "multiplierDecimal": "4",
// "filterType": "PERCENT_PRICE"
// }
// ],
// "orderTypes": [
// "LIMIT",
// "MARKET",
// "STOP",
// "STOP_MARKET",
// "TAKE_PROFIT",
// "TAKE_PROFIT_MARKET",
// "TRAILING_STOP_MARKET"
// ],
// "timeInForce": [
// "GTC",
// "IOC",
// "FOK",
// "GTX",
// "RPI"
// ]
// }
// ]
//
const fees = this.fees;
const result = [];
for (let i = 0; i < rows.length; i++) {
let swap = false;
const market = rows[i];
const id = this.safeString(market, 'symbol');
const baseId = this.safeString(market, 'baseAsset');
const quoteId = this.safeString(market, 'quoteAsset');
const base = this.safeCurrencyCode(baseId);
const quote = this.safeCurrencyCode(quoteId);
const contractType = this.safeString(market, 'contractType');
const contract = contractType !== undefined;
let spot = true;
if (contractType === 'PERPETUAL') {
swap = true;
spot = false;
}
let contractSize = undefined;
let linear = undefined;
let inverse = undefined;
let symbol = base + '/' + quote;
let settle = undefined;
let settleId = undefined;
if (contract) {
settleId = this.safeString(market, 'marginAsset');
settle = this.safeCurrencyCode(settleId);
if (swap) {
symbol = symbol + ':' + settle;
}
linear = settle === quote;
inverse = settle === base;
contractSize = this.safeNumber2(market, 'contractSize', 'unit', this.parseNumber('1'));
}
let unifiedType = undefined;
if (spot) {
unifiedType = 'spot';
}
else if (swap) {
unifiedType = 'swap';
}
const status = this.safeString(market, 'status');
const active = status === 'TRADING';
const filters = this.safeList(market, 'filters', []);
const filtersByType = this.indexBy(filters, 'filterType');
const entry = this.safeMarketStructure({
'id': id,
'symbol': symbol,
'base': base,
'quote': quote,
'settle': settle,
'baseId': baseId,
'quoteId': quoteId,
'settleId': settleId,
'type': unifiedType,
'spot': spot,
'margin': false,
'swap': swap,
'future': false,
'option': false,
'active': active,
'contract': contract,
'linear': linear,
'inverse': inverse,
'taker': fees['trading']['taker'],
'maker': fees['trading']['maker'],
'contractSize': contractSize,
'expiry': undefined,
'expiryDatetime': undefined,
'strike': undefined,
'optionType': undefined,
'precision': {
'amount': this.parseNumber(this.parsePrecision(this.safeString(market, 'quantityPrecision'))),
'price': this.parseNumber(this.parsePrecision(this.safeString(market, 'pricePrecision'))),
'base': this.parseNumber(this.parsePrecision(this.safeString(market, 'baseAssetPrecision'))),
'quote': this.parseNumber(this.parsePrecision(this.safeString(market, 'quotePrecision'))),
},
'limits': {
'leverage': {
'min': undefined,
'max': undefined,
},
'amount': {
'min': undefined,
'max': undefined,
},
'price': {
'min': undefined,
'max': undefined,
},
'cost': {
'min': undefined,
'max': undefined,
},
},
'created': this.safeInteger(market, 'onboardDate'),
'info': market,
});
if ('PRICE_FILTER' in filtersByType) {
const filter = this.safeDict(filtersByType, 'PRICE_FILTER', {});
entry['limits']['price'] = {
'min': this.safeNumber(filter, 'minPrice'),
'max': this.safeNumber(filter, 'maxPrice'),
};
entry['precision']['price'] = this.safeNumber(filter, 'tickSize');
}
if ('LOT_SIZE' in filtersByType) {
const filter = this.safeDict(filtersByType, 'LOT_SIZE', {});
entry['precision']['amount'] = this.safeNumber(filter, 'stepSize');
entry['limits']['amount'] = {
'min': this.safeNumber(filter, 'minQty'),
'max': this.safeNumber(filter, 'maxQty'),
};
}
if ('MARKET_LOT_SIZE' in filtersByType) {
const filter = this.safeDict(filtersByType, 'MARKET_LOT_SIZE', {});
entry['limits']['market'] = {
'min': this.safeNumber(filter, 'minQty'),
'max': this.safeNumber(filter, 'maxQty'),
};
}
if (('MIN_NOTIONAL' in filtersByType) || ('NOTIONAL' in filtersByType)) {
const filter = this.safeDict2(filtersByType, 'MIN_NOTIONAL', 'NOTIONAL', {});
entry['limits']['cost']['min'] = this.safeNumber(filter, 'notional');
}
result.push(entry);
}
return result;
}
/**
* @method
* @name aster#fetchTime
* @description fetches the current integer timestamp in milliseconds from the exchange server
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#check-server-time
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {int} the current integer timestamp in milliseconds from the exchange server
*/
async fetchTime(params = {}) {
const response = await this.fapiPublicGetV1Time(params);
//
// {
// "serverTime": 1499827319559
// }
//
return this.safeInteger(response, 'serverTime');
}
parseOHLCV(ohlcv, market = undefined) {
//
// [
// 1631158560000,
// "208.1850",
// "208.1850",
// "208.1850",
// "208.1850",
// "11.84",
// 1631158619999,
// "2464.910400",
// 1,
// "11.84",
// "2464.910400",
// "0"
// ]
//
return [
this.safeInteger(ohlcv, 0),
this.safeNumber(ohlcv, 1),
this.safeNumber(ohlcv, 2),
this.safeNumber(ohlcv, 3),
this.safeNumber(ohlcv, 4),
this.safeNumber(ohlcv, 5),
];
}
/**
* @method
* @name aster#fetchOHLCV
* @description fetches 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-data
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#klinecandlestick-data
* @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
* @param {string} [params.price] "mark" or "index" for mark price and index price candles
* @param {int} [params.until] the latest time in ms to fetch orders for
* @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
*/
async fetchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
if (symbol === undefined) {
throw new ArgumentsRequired(this.id + ' fetchOHLCV() requires a symbol argument');
}
await this.loadMarkets();
const market = this.market(symbol);
let request = {};
if (since !== undefined) {
request['startTime'] = since;
}
if (limit !== undefined) {
if (limit > 1500) {
limit = 1500; // Default 500; max 1500.
}
request['limit'] = limit;
}
[request, params] = this.handleUntilOption('endTime', request, params);
request['interval'] = this.safeString(this.timeframes, timeframe, timeframe);
const price = this.safeString(params, 'price');
const isMark = (price === 'mark');
const isIndex = (price === 'index');
params = this.omit(params, 'price');
let response = undefined;
if (isMark) {
request['symbol'] = market['id'];
response = await this.fapiPublicGetV1MarkPriceKlines(this.extend(request, params));
}
else if (isIndex) {
request['pair'] = market['id'];
response = await this.fapiPublicGetV1IndexPriceKlines(this.extend(request, params));
}
else {
request['symbol'] = market['id'];
if (market['linear']) {
response = await this.fapiPublicGetV1Klines(this.extend(request, params));
}
else {
response = await this.sapiPublicGetV1Klines(this.extend(request, params));
}
}
//
// [
// [
// 1631158560000,
// "208.1850",
// "208.1850",
// "208.1850",
// "208.1850",
// "11.84",
// 1631158619999,
// "2464.910400",
// 1,
// "11.84",
// "2464.910400",
// "0"
// ]
// ]
//
return this.parseOHLCVs(response, market, timeframe, since, limit);
}
parseTrade(trade, market = undefined) {
//
// fetchTrades
//
// {
// "id": 3913206,
// "price": "644.100",
// "qty": "0.08",
// "quoteQty": "51.528",
// "time": 1749784506633,
// "isBuyerMaker": true
// }
//
// {
// "id": 657,
// "price": "1.01000000",
// "qty": "5.00000000",
// "baseQty": "4.95049505",
// "time": 1755156533943,
// "isBuyerMaker": false
// }
//
// fetchMyTrades
//
// {
// "buyer": false,
// "commission": "-0.07819010",
// "commissionAsset": "USDT",
// "id": 698759,
// "maker": false,
// "orderId": 25851813,
// "price": "7819.01",
// "qty": "0.002",
// "quoteQty": "15.63802",
// "realizedPnl": "-0.91539999",
// "side": "SELL",
// "positionSide": "SHORT",
// "symbol": "BTCUSDT",
// "time": 1569514978020
// }
//
const id = this.safeString(trade, 'id');
const symbol = market['symbol'];
const currencyId = this.safeString(trade, 'commissionAsset');
const currencyCode = this.safeCurrencyCode(currencyId);
const amountString = this.safeString(trade, 'qty');
const priceString = this.safeString(trade, 'price');
const costString = this.safeString2(trade, 'quoteQty', 'baseQty');
const timestamp = this.safeInteger(trade, 'time');
let side = this.safeStringLower(trade, 'side');
const isMaker = this.safeBool(trade, 'maker');
let takerOrMaker = undefined;
if (isMaker !== undefined) {
takerOrMaker = isMaker ? 'maker' : 'taker';
}
const isBuyerMaker = this.safeBool(trade, 'isBuyerMaker');
if (isBuyerMaker !== undefined) {
side = isBuyerMaker ? 'sell' : 'buy';
}
return this.safeTrade({
'id': id,
'info': trade,
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
'symbol': symbol,
'order': this.safeString(trade, 'orderId'),
'type': undefined,
'side': side,
'takerOrMaker': takerOrMaker,
'price': priceString,
'amount': amountString,
'cost': costString,
'fee': {
'cost': this.parseNumber(Precise.stringAbs(this.safeString(trade, 'commission'))),
'currency': currencyCode,
},
}, market);
}
/**
* @method
* @name aster#fetchTrades
* @description get the list of most recent trades for a particular symbol
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#recent-trades-list
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#recent-trades-list
* @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 {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
*/
async fetchTrades(symbol, since = undefined, limit = undefined, params = {}) {
if (symbol === undefined) {
throw new ArgumentsRequired(this.id + ' fetchTrades() requires a symbol argument');
}
await this.loadMarkets();
const market = this.market(symbol);
const request = {
'symbol': market['id'],
};
if (limit !== undefined) {
if (limit > 1000) {
limit = 1000; // Default 500; max 1000.
}
request['limit'] = limit;
}
let response = undefined;
if (market['swap']) {
response = await this.fapiPublicGetV1Trades(this.extend(request, params));
//
// [
// {
// "id": 3913206,
// "price": "644.100",
// "qty": "0.08",
// "quoteQty": "51.528",
// "time": 1749784506633,
// "isBuyerMaker": true
// }
// ]
//
}
else {
response = await this.sapiPublicGetV1Trades(this.extend(request, params));
// [
// {
// "id": 657,
// "price": "1.01000000",
// "qty": "5.00000000",
// "baseQty": "4.95049505",
// "time": 1755156533943,
// "isBuyerMaker": false
// }
// ]
}
return this.parseTrades(response, market, since, limit);
}
/**
* @method
* @name aster#fetchMyTrades
* @description fetch all trades made by the user
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api.md#account-trade-history-user_data
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#account-trade-list-user_data
* @param {string} [symbol] unified market symbol
* @param {int} [since] the earliest time in ms to fetch trades for
* @param {int} [limit] the maximum number of trades structures to retrieve
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {int} [params.until] timestamp in ms for the ending date filter, default is undefined
* @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
*/
async fetchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
if (symbol === undefined) {
throw new ArgumentsRequired(this.id + ' fetchMyTrades() requires a symbol argument');
}
await this.loadMarkets();
const market = this.market(symbol);
let request = {
'symbol': market['id'],
};
if (since !== undefined) {
request['startTime'] = since;
}
if (limit !== undefined) {
if (limit > 1000) {
limit = 1000; // Default 500; max 1000.
}
request['limit'] = limit;
}
[request, params] = this.handleUntilOption('endTime', request, params);
let response = undefined;
if (market['swap']) {
response = await this.fapiPrivateGetV1UserTrades(this.extend(request, params));
}
else {
response = await this.sapiPrivateGetV1UserTrades(this.extend(request, params));
}
//
// [
// {
// "buyer": false,
// "commission": "-0.07819010",
// "commissionAsset": "USDT",
// "id": 698759,
// "maker": false,
// "orderId": 25851813,
// "price": "7819.01",
// "qty": "0.002",
// "quoteQty": "15.63802",
// "realizedPnl": "-0.91539999",
// "side": "SELL",
// "positionSide": "SHORT",
// "symbol": "BTCUSDT",
// "time": 1569514978020
// }
// ]
//
return this.parseTrades(response, market, since, limit, params);
}
/**
* @method
* @name aster#fetchOrderBook
* @description fetches 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#depth-information
* @see https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api.md#order-book
* @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 fetchOrderBook(symbol, limit = undefined, params = {}) {
if (symbol === undefined) {
throw new ArgumentsRequired(this.id + ' fetchOrderBook() requires a symbol argument');
}
await this.loadMarkets();
const market = this.market(symbol);
const request = {
'symbol': market['id'],
};
if (limit !== undefined) {
// limit: [5, 10, 20, 50, 100, 500, 1000]. Default: 500
if (limit > 1000) {
limit = 1000; // Default 500; max 1000.
}
request['limit'] = limit;
}
let response = undefined;
if (market['swap']) {
response = await this.fapiPublicGetV1Depth(this.extend(request, params));
}
else {
response = await this.sapiPublicGetV1Depth(this.extend(request, para