UNPKG

ccxt

Version:

A cryptocurrency trading API with more than 100 exchanges in JavaScript / TypeScript / Python / C# / PHP / Go

1,147 lines (1,143 loc) • 199 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var aster$1 = require('./abstract/aster.js'); var errors = require('./base/errors.js'); var number = require('./base/functions/number.js'); var Precise = require('./base/Precise.js'); var crypto = require('./base/functions/crypto.js'); var sha3 = require('./static_dependencies/noble-hashes/sha3.js'); var secp256k1 = require('./static_dependencies/noble-curves/secp256k1.js'); // --------------------------------------------------------------------------- // ---------------------------------------------------------------------------xs /** * @class aster * @augments Exchange */ class aster extends aster$1["default"] { describe() { return this.deepExtend(super.describe(), { 'id': 'aster', 'name': 'Aster', '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', 'certified': false, 'pro': true, 'dex': 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': true, 'transfer': true, 'withdraw': true, }, 'api': { 'fapiPublic': { 'get': { 'v1/ping': 1, 'v3/ping': 1, 'v1/time': 1, 'v3/time': 1, 'v1/exchangeInfo': 1, 'v3/exchangeInfo': 1, 'v1/depth': 1, 'v3/depth': 2, 'v1/trades': 1, 'v3/trades': 1, 'v1/historicalTrades': 1, 'v3/historicalTrades': 20, 'v1/aggTrades': 1, 'v3/aggTrades': 20, 'v1/klines': 1, 'v3/klines': 1, 'v1/indexPriceKlines': 1, 'v3/indexPriceKlines': 1, 'v1/markPriceKlines': 1, 'v3/markPriceKlines': 1, 'v1/premiumIndex': 1, 'v3/premiumIndex': 1, 'v1/fundingRate': 1, 'v3/fundingRate': 1, 'v1/fundingInfo': 1, 'v3/fundingInfo': 1, 'v1/ticker/24hr': 1, 'v3/ticker/24hr': 1, 'v1/ticker/price': 1, 'v3/ticker/price': 1, 'v1/ticker/bookTicker': 1, 'v3/ticker/bookTicker': 1, // different endpoints 'v1/adlQuantile': 1, 'v1/forceOrders': 1, 'v3/indexreferences': 1, }, }, 'fapiPrivate': { 'get': { 'v1/positionSide/dual': 1, 'v3/positionSide/dual': 30, 'v1/multiAssetsMargin': 1, 'v3/multiAssetsMargin': 1, 'v1/order': 1, 'v3/order': 1, 'v1/openOrder': 1, 'v3/openOrder': 1, 'v1/openOrders': 1, 'v3/openOrders': 1, 'v1/allOrders': 1, 'v3/allOrders': 1, 'v2/balance': 1, 'v3/balance': 1, 'v3/account': 1, 'v1/positionMargin/history': 1, 'v3/positionMargin/history': 1, 'v2/positionRisk': 1, 'v3/positionRisk': 1, 'v1/userTrades': 1, 'v3/userTrades': 5, 'v1/income': 1, 'v3/income': 1, 'v1/leverageBracket': 1, 'v3/leverageBracket': 1, 'v1/commissionRate': 1, 'v3/commissionRate': 1, // others 'v3/adlQuantile': 1, 'v3/forceOrders': 1, 'v3/mmp': 1, 'v3/accountWithJoinMargin': 1, 'v4/account': 1, // builder 'v3/agent': 1, 'v3/builder': 1, }, 'post': { 'v1/positionSide/dual': 1, 'v3/positionSide/dual': 1, 'v1/multiAssetsMargin': 1, 'v3/multiAssetsMargin': 1, 'v1/order': 1, 'v3/order': 1, 'v1/order/test': 1, 'v3/order/test': 1, 'v1/batchOrders': 1, 'v3/batchOrders': 1, 'v1/asset/wallet/transfer': 1, 'v3/asset/wallet/transfer': 1, 'v1/countdownCancelAll': 1, 'v3/countdownCancelAll': 1, 'v1/leverage': 1, 'v3/leverage': 1, 'v1/marginType': 1, 'v3/marginType': 1, 'v1/positionMargin': 1, 'v3/positionMargin': 1, 'v1/listenKey': 1, 'v3/listenKey': 1, // others 'v3/mmp': 1, 'v3/mmpReset': 1, 'v3/noop': 1, // builder 'v3/approveAgent': 1, 'v3/updateAgent': 1, 'v3/approveBuilder': 1, 'v3/updateBuilder': 1, }, 'put': { 'v1/listenKey': 1, 'v3/listenKey': 1, }, 'delete': { 'v1/order': 1, 'v3/order': 1, 'v1/allOpenOrders': 1, 'v3/allOpenOrders': 1, 'v1/batchOrders': 1, 'v3/batchOrders': 1, 'v3/mmp': 1, 'v1/listenKey': 1, 'v3/listenKey': 1, // builder 'v3/agent': 1, 'v3/builder': 1, }, }, 'sapiPublic': { 'get': { // v1 'v1/ping': 1, 'v1/time': 1, 'v1/exchangeInfo': 1, 'v1/depth': 1, 'v1/trades': 1, 'v1/historicalTrades': 1, 'v1/aggTrades': 1, 'v1/klines': 1, 'v1/ticker/24hr': 1, 'v1/ticker/price': 1, 'v1/ticker/bookTicker': 1, 'v1/aster/withdraw/estimateFee': 1, // v3 'v3/ping': 1, 'v3/time': 1, 'v3/exchangeInfo': 1, 'v3/depth': { 'cost': 2, 'byLimit': [[50, 2], [100, 5], [500, 10], [1000, 20]] }, 'v3/trades': 1, 'v3/historicalTrades': 20, 'v3/aggTrades': 20, 'v3/klines': { 'cost': 1, 'byLimit': [[99, 1], [499, 2], [1000, 5], [10000, 10]] }, 'v3/ticker/24hr': { 'cost': 1, 'noSymbol': 40 }, 'v3/ticker/price': { 'cost': 1, 'noSymbol': 2 }, 'v3/ticker/bookTicker': { 'cost': 1, 'noSymbol': 2 }, 'v3/aster/withdraw/estimateFee': 1, }, }, 'sapiPrivate': { 'get': { // v1 'v1/commissionRate': 1, 'v1/order': 1, 'v1/openOrders': 1, 'v1/allOrders': 1, 'v1/transactionHistory': 1, 'v1/account': 1, 'v1/userTrades': 1, // v3 'v3/commissionRate': { 'cost': 1, 'noSymbol': 2 }, 'v3/order': 1, 'v3/openOrders': 1, 'v3/allOrders': 5, 'v3/account': 5, 'v3/userTrades': 5, 'v3/openOrder': 1, }, 'post': { // v1 'v1/order': 1, 'v1/asset/wallet/transfer': 5, 'v1/asset/sendToAddress': 1, 'v1/listenKey': 1, // v3 'v3/order': 1, 'v3/asset/wallet/transfer': 5, 'v3/aster/user-withdraw': 1, 'v3/listenKey': 1, }, 'put': [ 'v1/listenKey', 'v3/listenKey', ], 'delete': { // v1 'v1/order': 1, 'v1/allOpenOrders': 1, 'v1/listenKey': 1, // v3 'v3/allOpenOrders': 1, 'v3/order': 1, 'v3/listenKey': 1, }, }, }, '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': number.TICK_SIZE, 'requiredCredentials': { 'apiKey': false, 'secret': false, 'privateKey': true, }, 'fees': { 'trading': { 'tierBased': true, 'percentage': true, 'maker': this.parseNumber('0.0001'), 'taker': this.parseNumber('0.00035'), }, }, 'options': { 'defaultType': 'spot', 'recvWindow': 10 * 1000, 'defaultTimeInForce': 'GTC', 'zeroAddress': '0x0000000000000000000000000000000000000000', 'v3ChainId': 1666, 'quoteOrderQty': true, 'accountsByType': { 'spot': 'SPOT', 'swap': 'FUTURE', 'future': 'FUTURE', 'linear': 'FUTURE', }, 'networks': { 'ERC20': 'ETH', 'BEP20': 'BSC', 'ARBONE': 'Arbitrum', }, 'networksToChainId': { 'ETH': 1, 'BSC': 56, 'Arbitrum': 42161, }, 'fetchOpenOrders': { 'warnIfNoSymbol': true, // set to false to suppress warning when calling fetchOpenOrders without symbol }, 'builderFee': true, 'builder': '0x1F5877C19e3777Cfd15F9d57253eA4aA5254Ec39', 'builderRate': '0.001', }, 'exceptions': { 'exact': { // 10xx - General Server or Network issues '-1000': errors.OperationRejected, '-1001': errors.NetworkError, '-1002': errors.AuthenticationError, '-1003': errors.RateLimitExceeded, '-1004': errors.DuplicateOrderId, '-1005': errors.BadRequest, '-1006': errors.BadResponse, '-1007': errors.RequestTimeout, '-1010': errors.OperationRejected, '-1011': errors.PermissionDenied, '-1013': errors.BadRequest, '-1014': errors.OrderNotFillable, '-1015': errors.RateLimitExceeded, '-1016': errors.ExchangeClosedByUser, '-1020': errors.NotSupported, '-1021': errors.InvalidNonce, '-1022': errors.AuthenticationError, '-1023': errors.BadRequest, // 11xx - Request issues '-1100': errors.BadRequest, '-1101': errors.BadRequest, '-1102': errors.ArgumentsRequired, '-1103': errors.BadRequest, '-1104': errors.BadRequest, '-1105': errors.ArgumentsRequired, '-1106': errors.BadRequest, '-1108': errors.BadRequest, '-1109': errors.BadRequest, '-1110': errors.BadSymbol, '-1111': errors.BadRequest, '-1112': errors.BadRequest, '-1113': errors.BadRequest, '-1114': errors.BadRequest, '-1115': errors.InvalidOrder, '-1116': errors.InvalidOrder, '-1117': errors.InvalidOrder, '-1118': errors.InvalidOrder, '-1119': errors.InvalidOrder, '-1120': errors.BadRequest, '-1121': errors.BadSymbol, '-1125': errors.AuthenticationError, '-1127': errors.BadRequest, '-1128': errors.BadRequest, '-1130': errors.BadRequest, '-1136': errors.InvalidOrder, // 20xx - Processing Issues '-2010': errors.InvalidOrder, '-2011': errors.OrderNotFound, '-2013': errors.OrderNotFound, '-2014': errors.AuthenticationError, '-2015': errors.AuthenticationError, '-2016': errors.MarketClosed, '-2018': errors.InsufficientFunds, '-2019': errors.InsufficientFunds, '-2020': errors.OrderNotFillable, '-2021': errors.OrderImmediatelyFillable, '-2022': errors.OperationRejected, '-2023': errors.AccountSuspended, '-2024': errors.InsufficientFunds, '-2025': errors.RateLimitExceeded, '-2026': errors.NotSupported, '-2027': errors.BadRequest, '-2028': errors.BadRequest, // 40xx - Filters and other Issues '-4000': errors.InvalidOrder, '-4001': errors.InvalidOrder, '-4002': errors.InvalidOrder, '-4003': errors.InvalidOrder, '-4004': errors.InvalidOrder, '-4005': errors.InvalidOrder, '-4006': errors.InvalidOrder, '-4007': errors.InvalidOrder, '-4008': errors.InvalidOrder, '-4009': errors.InvalidOrder, '-4010': errors.InvalidOrder, '-4011': errors.InvalidOrder, '-4012': errors.RateLimitExceeded, '-4013': errors.InvalidOrder, '-4014': errors.InvalidOrder, '-4015': errors.InvalidOrder, '-4016': errors.InvalidOrder, '-4017': errors.InvalidOrder, '-4018': errors.InvalidOrder, '-4019': errors.BadRequest, '-4020': errors.BadRequest, '-4021': errors.BadRequest, '-4022': errors.MarketClosed, '-4023': errors.InvalidOrder, '-4024': errors.InvalidOrder, '-4025': errors.BadRequest, '-4026': errors.BadRequest, '-4027': errors.BadRequest, '-4028': errors.BadRequest, '-4029': errors.BadRequest, '-4030': errors.BadRequest, '-4031': errors.BadRequest, '-4032': errors.RateLimitExceeded, '-4033': errors.AccountNotEnabled, '-4044': errors.BadRequest, '-4045': errors.RateLimitExceeded, '-4046': errors.NoChange, '-4047': errors.OperationRejected, '-4048': errors.OperationRejected, '-4049': errors.OperationRejected, '-4050': errors.InsufficientFunds, '-4051': errors.InsufficientFunds, '-4052': errors.NoChange, '-4053': errors.OperationRejected, '-4054': errors.OperationRejected, '-4055': errors.ArgumentsRequired, '-4056': errors.AuthenticationError, '-4057': errors.AuthenticationError, '-4058': errors.InvalidOrder, '-4059': errors.NoChange, '-4060': errors.InvalidOrder, '-4061': errors.InvalidOrder, '-4062': errors.OperationRejected, '-4063': errors.BadRequest, '-4064': errors.BadRequest, '-4065': errors.BadRequest, '-4066': errors.BadRequest, '-4067': errors.OperationRejected, '-4068': errors.OperationRejected, '-4069': errors.BadRequest, '-4070': errors.InvalidOrder, '-4071': errors.InvalidOrder, '-4072': errors.NoChange, '-4073': errors.BadRequest, '-4074': errors.InvalidOrder, '-4075': errors.OperationRejected, '-4076': errors.OperationRejected, '-4077': errors.RateLimitExceeded, '-4078': errors.BadRequest, '-4079': errors.BadRequest, '-4080': errors.BadRequest, '-4081': errors.BadRequest, '-4082': errors.RateLimitExceeded, '-4083': errors.OperationFailed, '-4084': errors.NotSupported, '-4085': errors.BadRequest, '-4086': errors.BadRequest, '-4087': errors.PermissionDenied, '-4088': errors.PermissionDenied, '-4104': errors.BadSymbol, '-4114': errors.InvalidOrder, '-4115': errors.DuplicateOrderId, '-4118': errors.InsufficientFunds, '-4131': errors.InvalidOrder, '-4135': errors.InvalidOrder, '-4137': errors.InvalidOrder, '-4138': errors.OperationRejected, '-4139': errors.InvalidOrder, '-4140': errors.OperationRejected, '-4141': errors.MarketClosed, '-4142': errors.InvalidOrder, '-4144': errors.BadSymbol, '-4161': errors.OperationRejected, '-4164': errors.InvalidOrder, '-4165': errors.BadRequest, '-4183': errors.InvalidOrder, '-4184': errors.InvalidOrder, '-5060': errors.OperationRejected, '-5076': errors.OperationRejected, // occured errors: '-4168': errors.OperationRejected, // Unable to adjust to isolated-margin mode under the Multi-Assets mode. }, '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://asterdex.github.io/aster-api-website/spot-v3/market-data/#trading-specification-information * @see https://asterdex.github.io/aster-api-website/futures-v3/market-data/#exchange-information * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} an associative dictionary of currencies */ async fetchCurrencies(params = {}) { const sapiResult = await this.sapiPublicGetV3ExchangeInfo(params); const sapiRows = this.safeList(sapiResult, 'assets', []); // // [ // { // "asset": "USDT", // "marginAvailable": true, // only in PERP // "autoAssetExchange": "-10000" // only in PERP // } // ] // return this.parseCurrencies(sapiRows); } parseCurrency(rawCurrency) { const currencyId = this.safeString(rawCurrency, 'asset'); const code = this.safeCurrencyCode(currencyId); return this.safeCurrencyStructure({ 'info': rawCurrency, 'code': code, 'id': currencyId, 'name': code, 'active': undefined, 'deposit': undefined, 'withdraw': undefined, 'fee': undefined, 'precision': undefined, 'margin': this.safeBool(rawCurrency, 'marginAvailable'), '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 }); } /** * @method * @name aster#fetchMarkets * @description retrieves data on all markets for bigone * @see https://asterdex.github.io/aster-api-website/spot-v3/market-data/#trading-specification-information * @see https://asterdex.github.io/aster-api-website/futures-v3/market-data/#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.sapiPublicGetV3ExchangeInfo(params), this.fapiPublicGetV3ExchangeInfo(params), ]; promises.push(this.signIn()); 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', []); // // example: // // [ // { // symbol: "TESTUSDT", // status: "TRADING", // baseAsset: "TEST", // quoteAsset: "USDT", // pricePrecision: "2", // quantityPrecision: "5", // baseAssetPrecision: "8", // quotePrecision: "8", // listingTime: "1756289680210", // only in SPOT // baseAssetAddress: null, // only in SPOT // ocoAllowed: false, // only in SPOT // pair: "ASTERUSDT", // only in PERP // contractType: "PERPETUAL", // only in PERP // deliveryDate: "4133404800000", // only in PERP // onboardDate: "1758178800000", // only in PERP // maintMarginPercent: "12.5000", // only in PERP // requiredMarginPercent: "25.0000", // only in PERP // marginAsset: "USDT", // only in PERP // underlyingType: "COIN", // only in PERP // underlyingSubType: [ "Top", ], // only in PERP // symbolType: "0", // only in PERP // tradingMode: "0", // only in PERP // name: "", // only in PERP // channel: "{}", // only in PERP // sequenceNo: "100", // only in PERP // twapMinNotional: "1000", // only in PERP // imn: "4000.00", // only in PERP // tags: [], // only in PERP // settlePlan: "0", // only in PERP // triggerProtect: "0.1500", // only in PERP // liquidationFee: "0.025000", // only in PERP // marketTakeBound: "0.05", // only in PERP // createTime: "1758215451058", // only in PERP // filters: [ // { // minPrice: "0.01", // maxPrice: "1000000", // filterType: "PRICE_FILTER", // tickSize: "0.01", // }, // { // stepSize: "0.00001", // filterType: "LOT_SIZE", // maxQty: "9000", // minQty: "0.00001", // }, // { // stepSize: "0.00001", // filterType: "MARKET_LOT_SIZE", // maxQty: "9000", // minQty: "0.00001", // }, // { // limit: "200", // filterType: "MAX_NUM_ORDERS", // }, // { // minNotional: "5", // filterType: "MIN_NOTIONAL", // }, // { // minNotional: "5", // avgPriceMins: "5", // applyMinToMarket: true, // filterType: "NOTIONAL", // only in SPOT // applyMaxToMarket: true, // }, // { // multiplierDown: "0.2", // multiplierUp: "5", // multiplierDecimal: "1", // filterType: "PERCENT_PRICE", // }, // { // bidMultiplierUp: "5", // askMultiplierUp: "5", // bidMultiplierDown: "0.2", // avgPriceMins: "5", // multiplierDecimal: "1", // filterType: "PERCENT_PRICE_BY_SIDE", // only in SPOT // askMultiplierDown: "0.2", // }, // ], // orderTypes: [ "LIMIT", "MARKET", "STOP", "STOP_MARKET", "TAKE_PROFIT", "TAKE_PROFIT_MARKET", "TRAILING_STOP_MARKET", ], // timeInForce: [ "GTC", "IOC", "FOK", "GTX", "HIDDEN", ], // } // ] // // const fapiRowsFiltered = []; for (let i = 0; i < fapiRows.length; i++) { const market = fapiRows[i]; // tmp skip some markets with base = undefined if (this.safeString(market, 'baseAsset')) { fapiRowsFiltered.push(market); } } const rows = this.arrayConcat(sapiRows, fapiRowsFiltered); return this.parseMarkets(rows); } parseMarket(market) { 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 active = this.safeString(market, 'status') === 'TRADING'; let spot = undefined; let symbol = undefined; let settle = undefined; let settleId = undefined; let swap = undefined; let linear = undefined; let inverse = undefined; let contractSize = undefined; const contractType = this.safeString(market, 'contractType'); const isContract = contractType !== undefined; if (isContract) { // currently, there is only perpetuals, not futures spot = false; swap = true; settleId = this.safeString(market, 'marginAsset'); settle = this.safeCurrencyCode(settleId); symbol = base + '/' + quote + ':' + settle; linear = settle === quote; inverse = settle === base; contractSize = this.safeNumber2(market, 'contractSize', 'unit', this.parseNumber('1')); } else { spot = true; swap = false; symbol = base + '/' + quote; } // filters const filters = this.safeList(market, 'filters', []); const filtersByType = this.indexBy(filters, 'filterType'); const filterNotional = this.safeDict2(filtersByType, 'MIN_NOTIONAL', 'NOTIONAL'); const filterPrice = this.safeDict(filtersByType, 'PRICE_FILTER'); const filterLotSize = this.safeDict(filtersByType, 'LOT_SIZE'); const filterMarketLotSize = this.safeDict(filtersByType, 'MARKET_LOT_SIZE', {}); let pricePrecision = this.safeNumber(filterPrice, 'tickSize'); if (pricePrecision === undefined) { pricePrecision = this.parseNumber(this.parsePrecision(this.safeString(market, 'pricePrecision'))); } const amountPrecision = (filterLotSize !== undefined) ? this.safeNumber(filterLotSize, 'stepSize') : this.parseNumber(this.parsePrecision(this.safeString(market, 'quantityPrecision'))); return this.safeMarketStructure({ 'id': id, 'symbol': symbol, 'base': base, 'quote': quote, 'settle': settle, 'baseId': baseId, 'quoteId': quoteId, 'settleId': settleId, 'type': isContract ? 'swap' : 'spot', 'spot': spot, 'margin': false, 'swap': swap, 'future': false, 'option': false, 'active': active, 'contract': isContract, 'linear': linear, 'inverse': inverse, 'taker': this.fees['trading']['taker'], 'maker': this.fees['trading']['maker'], 'contractSize': contractSize, 'expiry': undefined, 'expiryDatetime': undefined, 'strike': undefined, 'optionType': undefined, 'precision': { 'amount': amountPrecision, 'price': 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': this.safeNumber(filterLotSize, 'minQty'), 'max': this.safeNumber(filterLotSize, 'maxQty'), }, 'price': { 'min': this.safeNumber(filterPrice, 'minPrice'), 'max': this.safeNumber(filterPrice, 'maxPrice'), }, 'cost': { 'min': this.safeNumber2(filterNotional, 'notional', 'minNotional'), 'max': undefined, }, 'market': { 'min': this.safeNumber(filterMarketLotSize, 'minQty'), 'max': this.safeNumber(filterMarketLotSize, 'maxQty'), }, }, 'created': this.safeInteger2(market, 'listingTime', 'createTime'), 'info': market, }); } /** * @method * @name aster#fetchTime * @description fetches the current integer timestamp in milliseconds from the exchange server * @see https://asterdex.github.io/aster-api-website/spot-v3/market-data/#get-server-time * @see https://asterdex.github.io/aster-api-website/futures-v3/market-data/#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 = {}) { let marketType = undefined; [marketType, params] = this.handleMarketTypeAndParams('fetchTime', undefined, params); let response = undefined; if (marketType === 'swap') { response = await this.fapiPublicGetV3Time(params); } else { response = await this.sapiPublicGetV3Time(params); } // // both SPOT & PERP has same format // // { // "serverTime": 1499827319559 // } // return this.safeInteger(response, 'serverTime'); } parseOHLCV(ohlcv, market = undefined) { // // spot: // // [ // 1499040000000, // Open time // "0.01634790", // Open // "0.80000000", // High // "0.01575800", // Low // "0.01577100", // Close // "148976.11427815", // Volume // 1499644799999, // Close time // "2434.19055334", // Quote asset volume // 308, // Number of trades // "1756.87402397", // Taker buy base asset volume // "28.46694368", // Taker buy quote asset volume // "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://asterdex.github.io/aster-api-website/spot-v3/market-data/#k-line-data * @see https://asterdex.github.io/aster-api-website/futures-v3/market-data/#klinecandlestick-data * @see https://asterdex.github.io/aster-api-website/futures-v3/market-data/#index-price-klinecandlestick-data * @see https://asterdex.github.io/aster-api-website/futures-v3/market-data/#mark-price-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 = {}) { await this.loadMarkets(); const market = this.market(symbol); let request = {}; if (since !== undefined) { request['startTime'] = since; } if (limit !== undefined) { request['limit'] = Math.min(limit, 1500); } [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.fapiPublicGetV3MarkPriceKlines(this.extend(request, params)); } else if (isIndex) { request['pair'] = market['id']; response = await this.fapiPublicGetV3IndexPriceKlines(this.extend(request, params)); } else { request['symbol'] = market['id']; if (market['linear']) { response = await this.fapiPublicGetV3Klines(this.extend(request, params)); } else { response = await this.sapiPublicGetV3Klines(this.extend(request, params)); } // // both SPOT & PERP has same format // // [ // [ // 1499040000000, // Open time // "0.01634790", // Open // "0.80000000", // High // "0.01575800", // Low // "0.01577100", // Close // "148976.11427815", // Volume // 1499644799999, // Close time // "2434.19055334", // Quote asset volume // 308, // Number of trades // "1756.87402397", // Taker buy base asset volume // "28.46694368", // Taker buy quote asset volume, // "0" // ] // ] // } return this.parseOHLCVs(response, market, timeframe, since, limit); } parseTrade(trade, market = undefined) { // // fetchTrades // // recent trades: // // { // "id": 3913206, // "price": "644.100", // "qty": "0.08", // "quoteQty": "51.528", // present in PERP // "baseQty": "4.95049505", // present in SPOT // "time": 1749784506633, // "isBuyerMaker": true // } // // aggrTrades // // { // "a": 26129, // Aggregate tradeId // "p": "0.01633102", // Price // "q": "4.70443515", // Quantity // "f": 27781, // First tradeId // "l": 27781, // Last tradeId // "T": 1498793709153, // Timestamp // "m": true, // Was the buyer the maker? // } // // fetchMyTrades (SPOT & PERP have similar format) // // { // "symbol": "ETHUSDT", // "id": 2583152, // "orderId": 418588675, // "side": "SELL", // "price": "2330.04", // "qty": "0.0030", // "quoteQty": "6.99000000", // "commission": "0.00279605", // "commissionAsset": "USDT", // "time": 1776409179230, // "counterpartyId": 5143150, // only in SPOT // "createUpdateId": null, // only in SPOT // "maker": false, // only in SPOT // "buyer": false, // only in SPOT // "realizedPnl": "0.00029999", // only in PERP // "marginAsset": "USDT", // only in PERP // "positionSide": "BOTH", // only in PERP // } // const id = this.safeString2(trade, 'id', 'a'); const marketId = this.safeString(trade, 'symbol'); const marketType = ('positionSide' in trade) ? 'swap' : 'spot'; market = this.safeMarket(marketId, market, undefined, marketType); const currencyId = this.safeString2(trade, 'commissionAsset', 'marginAsset'); const currencyCode = this.safeCurrencyCode(currencyId); const amountString = this.safeString2(trade, 'qty', 'q'); const priceString = this.safeString2(trade, 'price', 'p'); const costString = this.safeString2(trade, 'quoteQty', 'baseQty'); const timestamp = this.safeInteger2(trade, 'time', 'T'); let side = this.safeStringLower(trade, 'side'); const isMaker = this.safeBool(trade, 'maker'); let takerOrMaker = undefined; if (isMaker !== undefined) { takerOrMaker = isMaker ? 'maker' : 'taker'; if (side === undefined) { const isBuyer = this.safeBool(trade, 'buyer'); if (isBuyer !== undefined) { side = isBuyer ? 'buy' : 'sell'; } } } const isBuyerMaker = this.safeBool2(trade, 'isBuyerMaker', 'm'); if (isBuyerMaker !== undefined) { side = isBuyerMaker ? 'sell' : 'buy'; } return this.safeTrade({ 'id': id, 'info': trade, 'timestamp': timestamp, 'datetime': this.iso8601(timestamp), 'symbol': market['symbol'],