ccxt-xigua
Version:
3,143 lines • 138 kB
JavaScript
'use strict';
// ----------------------------------------------------------------------------
const Exchange = require ('./base/Exchange');
const { ArgumentsRequired, AuthenticationError, ExchangeError, ExchangeNotAvailable, OrderNotFound, InvalidOrder, CancelPending, RateLimitExceeded, InsufficientFunds, BadRequest, BadSymbol, PermissionDenied } = require ('./base/errors');
const { TICK_SIZE } = require ('./base/functions/number');
const Precise = require ('./base/Precise');
// ----------------------------------------------------------------------------
module.exports = class aax extends Exchange {
describe () {
return this.deepExtend (super.describe (), {
'id': 'aax',
'name': 'AAX',
'countries': [ 'MT' ], // Malta
// 6000 / hour => 100 per minute => 1.66 requests per second => rateLimit = 600
// market endpoints ratelimits arent mentioned in docs so they are also set to "all other authenticated endpoints"
// 5000 / hour => weight = 1.2 ("all other authenticated endpoints")
// 600 / hour => weight = 10
// 200 / hour => weight = 30
'rateLimit': 600,
'version': 'v2',
'hostname': 'aaxpro.com', // aax.com
'pro': true,
'has': {
'CORS': undefined,
'spot': true,
'margin': true,
'swap': true,
'future': false,
'option': false,
'addMargin': false,
'cancelAllOrders': true,
'cancelOrder': true,
'cancelOrders': false,
'createDepositAddress': false,
'createOrder': true,
'createReduceOnlyOrder': false,
'createStopLimitOrder': true,
'createStopMarketOrder': true,
'createStopOrder': true,
'editOrder': true,
'fetchAccounts': true,
'fetchBalance': true,
'fetchBidsAsks': undefined,
'fetchBorrowRate': false,
'fetchBorrowRateHistories': false,
'fetchBorrowRateHistory': false,
'fetchBorrowRates': false,
'fetchBorrowRatesPerSymbol': false,
'fetchCanceledOrders': true,
'fetchClosedOrder': undefined,
'fetchClosedOrders': true,
'fetchCurrencies': true,
'fetchDeposit': false,
'fetchDepositAddress': true,
'fetchDepositAddresses': false,
'fetchDepositAddressesByNetwork': undefined,
'fetchDeposits': true,
'fetchFundingHistory': true,
'fetchFundingRate': true,
'fetchFundingRateHistory': true,
'fetchFundingRates': false,
'fetchIndexOHLCV': false,
'fetchL3OrderBook': undefined,
'fetchLedger': undefined,
'fetchLedgerEntry': undefined,
'fetchLeverage': undefined,
'fetchLeverageTiers': false,
'fetchMarginMode': false,
'fetchMarketLeverageTiers': false,
'fetchMarkets': true,
'fetchMarkOHLCV': false,
'fetchMyTrades': true,
'fetchOHLCV': true,
'fetchOpenOrder': undefined,
'fetchOpenOrders': true,
'fetchOrder': true,
'fetchOrderBook': true,
'fetchOrderBooks': false,
'fetchOrders': true,
'fetchOrderTrades': undefined,
'fetchPosition': true,
'fetchPositionMode': false,
'fetchPositions': true,
'fetchPositionsRisk': false,
'fetchPremiumIndexOHLCV': false,
'fetchStatus': true,
'fetchTicker': 'emulated',
'fetchTickers': true,
'fetchTime': true,
'fetchTrades': true,
'fetchTradingFee': false,
'fetchTradingFees': false,
'fetchTradingLimits': undefined,
'fetchTransactionFee': undefined,
'fetchTransactionFees': undefined,
'fetchTransactions': undefined,
'fetchTransfer': false,
'fetchTransfers': true,
'fetchWithdrawal': false,
'fetchWithdrawals': true,
'fetchWithdrawalWhitelist': false,
'reduceMargin': false,
'setLeverage': true,
'setMargin': true,
'setMarginMode': false,
'setPositionMode': undefined,
'signIn': undefined,
'transfer': true,
'withdraw': false,
},
'timeframes': {
'1m': '1m',
'5m': '5m',
'15m': '15m',
'30m': '30m',
'1h': '1h',
'2h': '2h',
'4h': '4h',
'12h': '12h',
'1d': '1d',
'3d': '3d',
'1w': '1w',
},
'urls': {
'logo': 'https://user-images.githubusercontent.com/1294454/104140087-a27f2580-53c0-11eb-87c1-5d9e81208fe9.jpg',
'test': {
'v1': 'https://api.testnet.{hostname}/marketdata/v1',
'public': 'https://api.testnet.{hostname}',
'private': 'https://api.testnet.{hostname}',
},
'api': {
'v1': 'https://api.{hostname}/marketdata/v1',
'public': 'https://api.{hostname}',
'private': 'https://api.{hostname}',
},
'www': 'https://www.aaxpro.com', // string website URL
'doc': 'https://www.aaxpro.com/apidoc/index.html',
'fees': 'https://www.aaxpro.com/en-US/fees/',
'referral': 'https://www.aaxpro.com/invite/sign-up?inviteCode=JXGm5Fy7R2MB',
},
'api': {
'v1': {
'get': [
'getHistMarketData', // Get OHLC k line of specific market
],
},
'public': {
// these endpoints are not documented
// 'get': [
// 'order_book', // Get the order book of specified market
// 'order_book/{market}',
// 'trades', // Get recent trades on market, each trade is included only once Trades are sorted in reverse creation order.
// 'trades/{market}',
// 'tickers', // Get ticker of all markets
// 'tickers/{market}', // Get ticker of specific market
// ],
'get': {
'currencies': 1.2,
'announcement/maintenance': 1.2, // System Maintenance Notice
'time': 1.2,
'instruments': 1.2, // Retrieve all trading pairs information
'market/orderbook': 1.2, // Order Book
'futures/position/openInterest': 1.2, // Open Interest
'market/tickers': 1.2, // Get the Last 24h Market Summary
'market/candles': 1.2, // Get Current Candlestick
'market/history/candles': 1.2, // Get Current Candlestick
'market/trades': 1.2, // Get the Most Recent Trades
'market/markPrice': 1.2, // Get Current Mark Price
'futures/funding/predictedFunding/{symbol}': 1.2, // Get Predicted Funding Rate
'futures/funding/prevFundingRate/{symbol}': 1.2, // Get Last Funding Rate
'futures/funding/fundingRate': 1.2,
'market/candles/index': 1.2, // * Deprecated
'market/index/candles': 1.2,
},
},
'private': {
'get': {
'user/info': 1.2, // Retrieve user information
'account/balances': 1.2, // Get Account Balances
'account/deposit/address': 1.2, // undocumented
'account/deposits': 1.2, // Get account deposits history
'account/transfer': 1.2,
'account/withdraws': 1.2, // Get account withdrawals history
'spot/trades': 1.2, // Retrieve trades details for a spot order
'spot/openOrders': 1.2, // Retrieve spot open orders
'spot/orders': 1.2, // Retrieve historical spot orders
'futures/position': 1.2, // Get positions for all contracts
'futures/position/closed': 1.2, // Get closed positions
'futures/trades': 1.2, // Retrieve trade details for a futures order
'futures/openOrders': 1.2, // Retrieve futures open orders
'futures/orders': 1.2, // Retrieve historical futures orders
'futures/funding/fundingFee': 1.2,
'futures/funding/predictedFundingFee/{symbol}': 1.2, // Get predicted funding fee
},
'post': {
'account/transfer': 1.2, // Asset Transfer
'spot/orders': 1.2, // Create a new spot order
'spot/orders/cancelAllOnTimeout': 10, // Automatically cancel all your spot orders after a specified timeout.
'futures/orders': 1.2, // Create a new futures order
'futures/orders/cancelAllOnTimeout': 10, // Automatically cancel all your futures orders after a specified timeout.
'futures/position/sltp': 1.2, // Set take profit and stop loss orders for an opening position
'futures/position/close': 1.2, // Close position
'futures/position/leverage': 30, // Update leverage for position
'futures/position/margin': 1.2, // Modify Isolated Position Margin
},
'put': {
'spot/orders': 1.2, // Amend spot order
'futures/orders': 1.2, // Amend the quantity of an open futures order
},
'delete': {
'spot/orders/cancel/{orderID}': 1, // Cancel a spot order
'spot/orders/cancel/all': 10, // Batch cancel spot orders
'futures/orders/cancel/{orderID}': 1, // Cancel a futures order
'futures/orders/cancel/all': 10, // Batch cancel futures orders
},
},
},
'fees': {
'trading': {
'tierBased': false,
'percentage': true,
'maker': this.parseNumber ('0.0006'),
'taker': this.parseNumber ('0.001'),
},
'funding': {
'tierBased': false,
'percentage': true,
'withdraw': {}, // There is only 1% fee on withdrawals to your bank account.
},
},
'commonCurrencies': {
'XBT': 'XBT',
},
'exceptions': {
'exact': {
'2002': InsufficientFunds,
'2003': OrderNotFound,
'10003': BadRequest, // Parameter validation error
'10006': AuthenticationError, // Session expired, please relogin
'10007': AuthenticationError, // Invalid authentication key or token
'11007': AuthenticationError, // Invalid key format
'20001': InsufficientFunds, // Insufficient balance. Please deposit to trade.
'20009': InvalidOrder, // Order amount must be positive
'30000': OrderNotFound, // {"code":30000,"data":null,"message":"The order does not exist","ts":1610259732263}
'30001': InvalidOrder, // The order is being submitted, please try again later
'30004': InvalidOrder, // Minimum quantity is {0}
'30005': InvalidOrder, // Quantity maximum precision is {0} decimal places
'30006': InvalidOrder, // Price maximum precision is {0} decimal places
'30007': InvalidOrder, // Minimum price is {0}
'30008': InvalidOrder, // Stop price maximum precision is {0} decimal places
'30009': InvalidOrder, // Stop Price cannot be less than {0}
'30010': InvalidOrder, // Market price cannot be empty
'30011': CancelPending, // The order is being cancelled, please wait.
'30012': BadRequest, // Unknown currency
'30013': BadSymbol, // Unknown symbol
'30014': OrderNotFound, // Futures order cannot be found
'30015': InvalidOrder, // This is not an open order and cannot modified
'30016': ExchangeError, // No position found
'30017': InvalidOrder, // The current close position is 0. It is recommended that you cancel the current order closing order.
'30018': InvalidOrder, // Order price cannot be greater than {0}
'30019': InvalidOrder, // Order quantity cannot be greater than {0}
'30020': InvalidOrder, // Order price must be a multiple of {0}
'30021': InvalidOrder, // Margin adjustement must be greater than 0
'30022': InvalidOrder, // New quantity must be greater than filled quantity
'30023': InvalidOrder, // Order failed, please try again
'30024': InvalidOrder, // TimeInForce error, only GTC or IOC are allowed
'30025': InvalidOrder, // TimeInForce error, only GTC is allowed
'30026': InvalidOrder, // Quantity is not a multiple of {0}
'30027': InvalidOrder, // Close position failed, it is recommended that you cancel the current order and then close the position.
'30028': BadSymbol, // Symbol cannot be traded at this time
'30029': InvalidOrder, // Modified quantity or price cannot be empty
'30030': InvalidOrder, // Price cannot be specified for market orders
'30031': InvalidOrder, // Liquidation orders cannot be modified
'30032': InvalidOrder, // Leverage cannot be greater than {0}
'30033': InvalidOrder, // Leverage cannot be smaller than {0}
'30034': RateLimitExceeded, // The max number of open orders is {0}. To place a new order, please cancel a previous one
'30035': RateLimitExceeded, // The max number of {0} open orders is {1}. To place a new order, please cancel a previous one
'30036': ExchangeNotAvailable, // Liquidation is in progress, please try again later
'30037': InvalidOrder, // Once stop limit order triggered, stop price cannot be amended
'30038': ExchangeError, // The total value of your orders has exceeded the current risk limit. Please adjust the risk limit
'30039': InsufficientFunds, // Your risk limit has now been changed to {0}, your maximum leverage less than 1, please readjust accordingly
'30040': InvalidOrder, // Order status has changed, please try again later
'30041': InvalidOrder, // Liquidation orders cannot be cancelled
'30042': InvalidOrder, // Order cannot be placed as you will be breaching you max limit value of {1} BTC for {0}
'30043': InvalidOrder, // The risk limit cannot be less than 0
'30044': BadRequest, // Timeout cannot be greater than 60 minutes
'30045': InvalidOrder, // Side is not valid, it should be BUY or SELL
'30046': InvalidOrder, // Order type is not valid, it should be MARKET or LIMIT or STOP-LIMIT or STOP
'30047': InvalidOrder, // The order is closed. Can't cancel
'30048': InvalidOrder, // Market orders cannot be modified
'30049': InvalidOrder, // The order is being modified, please wait
'30050': InvalidOrder, // Maximum 10 orders
'40004': BadRequest, // Requested resource doesn't exist
'40009': RateLimitExceeded, // Too many requests
'40102': AuthenticationError, // {"code":40102,"message":"Unauthorized(invalid key)"}
'40103': AuthenticationError, // {"code":40103,"message":"Unauthorized(invalid sign)"}
'40303': PermissionDenied, // {"code":40303,"message":"Forbidden(invalid scopes)"}
'41001': BadRequest, // Incorrect HTTP request
'41002': BadRequest, // Unsupported HTTP request method
'42001': ExchangeNotAvailable, // Duplicated data entry, please check and try again
'50001': ExchangeError, // Server side exception, please try again later
'50002': ExchangeError, // Server is busy, please try again later
},
'broad': {},
},
'precisionMode': TICK_SIZE,
'options': {
'defaultType': 'spot', // 'spot', 'future'
'accountsByType': {
'spot': 'SPTP',
'future': 'FUTP',
'otc': 'F2CP',
'saving': 'VLTP',
},
'accountsById': {
'SPTP': 'spot',
'FUTP': 'future',
'F2CP': 'otc',
'VLTP': 'saving',
},
'networks': {
'ETH': 'ERC20',
'TRX': 'TRC20',
'SOL': 'SPL',
},
'transfer': {
'fillResponseFromRequest': true,
},
},
});
}
async fetchTime (params = {}) {
/**
* @method
* @name aax#fetchTime
* @description fetches the current integer timestamp in milliseconds from the exchange server
* @param {dict} params extra parameters specific to the aax api endpoint
* @returns {int} the current integer timestamp in milliseconds from the exchange server
*/
const response = await this.publicGetTime (params);
//
// {
// "code": 1,
// "data": 1573542445411, // unit: millisecond
// "message": "success",
// "ts": 1573542445411
// }
//
return this.safeInteger (response, 'data');
}
async fetchStatus (params = {}) {
/**
* @method
* @name aax#fetchStatus
* @description the latest known information on the availability of the exchange API
* @param {dict} params extra parameters specific to the aax api endpoint
* @returns {dict} a [status structure]{@link https://docs.ccxt.com/en/latest/manual.html#exchange-status-structure}
*/
const response = await this.publicGetAnnouncementMaintenance (params);
//
// note, when there is no maintenance, then data is `null`
//
// {
// "code": 1,
// "data": {
// "startTime":"2020-06-25T02:15:00.000Z",
// "endTime":"2020-06-25T02:45:00.000Z",
// "description":"Spot Trading :UTC Jun 25, 2020 02:15 to 02:45 (HKT Jun 25 10:15 to 10:45),Futures Trading: UTC Jun 25, 2020 02:15 to 02:45 (HKT Jun 25 10:15 to 10:45).We apologize for any inconvenience caused. Thank you for your patience and understanding.Should you have any enquiries, please do not hesitate our live chat support or via email at cs@aax.com.",
// "haltReason":1,
// "systemStatus":{
// "spotTrading":"readOnly",
// "futuresTreading":"closeOnly",
// "walletOperating":"enable",
// "otcTrading":"disable"
// },
// },
// "message":"success",
// "ts":1593043237000
// }
//
const timestamp = this.milliseconds ();
const updated = this.safeInteger (response, 'ts', timestamp);
const data = this.safeValue (response, 'data', {});
let status = undefined;
let eta = undefined;
if (data) {
const startTime = this.parse8601 (this.safeString (data, 'startTime'));
const endTime = this.parse8601 (this.safeString (data, 'endTime'));
if (endTime !== undefined) {
const startTimeIsOk = (startTime === undefined) ? true : (updated < startTime);
const isOk = (updated > endTime) || startTimeIsOk;
eta = endTime;
status = isOk ? 'ok' : 'maintenance';
} else {
status = data;
}
} else {
eta = undefined;
status = 'ok';
}
return {
'status': status,
'updated': updated,
'eta': eta,
'url': undefined,
'info': response,
};
}
async fetchMarkets (params = {}) {
/**
* @method
* @name aax#fetchMarkets
* @description retrieves data on all markets for aax
* @param {dict} params extra parameters specific to the exchange api endpoint
* @returns {[dict]} an array of objects representing market data
*/
const response = await this.publicGetInstruments (params);
//
// {
// "code":1,
// "message":"success",
// "ts":1610159448962,
// "data":[
// {
// "tickSize":"0.01",
// "lotSize":"1",
// "base":"BTC",
// "quote":"USDT",
// "minQuantity":"1.0000000000",
// "maxQuantity":"30000",
// "minPrice":"0.0100000000",
// "maxPrice":"999999.0000000000",
// "status":"readOnly",
// "symbol":"BTCUSDTFP",
// "code":"FP",
// "takerFee":"0.00040",
// "makerFee":"0.00020",
// "multiplier":"0.001000000000",
// "mmRate":"0.00500",
// "imRate":"0.01000",
// "type":"futures",
// "settleType":"Vanilla",
// "settleCurrency":"USDT"
// },
// {
// "tickSize":"0.5",
// "lotSize":"10",
// "base":"BTC",
// "quote":"USD",
// "minQuantity":"10.0000000000",
// "maxQuantity":"300000",
// "minPrice":"0.5000000000",
// "maxPrice":"999999.0000000000",
// "status":"readOnly",
// "symbol":"BTCUSDFP",
// "code":"FP",
// "takerFee":"0.00040",
// "makerFee":"0.00020",
// "multiplier":"1.000000000000",
// "mmRate":"0.00500",
// "imRate":"0.01000",
// "type":"futures",
// "settleType":"Inverse",
// "settleCurrency":"BTC"
// },
// {
// "tickSize":"0.0001",
// "lotSize":"0.01",
// "base":"AAB",
// "quote":"USDT",
// "minQuantity":"5.0000000000",
// "maxQuantity":"50000.0000000000",
// "minPrice":"0.0001000000",
// "maxPrice":"999999.0000000000",
// "status":"readOnly",
// "symbol":"AABUSDT",
// "code":null,
// "takerFee":"0.00100",
// "makerFee":"0.00100",
// "multiplier":"1.000000000000",
// "mmRate":"0.02500",
// "imRate":"0.05000",
// "type":"spot",
// "settleType":null,
// "settleCurrency":null
// },
// ]
// }
//
const data = this.safeValue (response, 'data', []);
const result = [];
for (let i = 0; i < data.length; i++) {
const market = data[i];
const id = this.safeString (market, 'symbol');
const baseId = this.safeString (market, 'base');
const quoteId = this.safeString (market, 'quote');
const settleId = this.safeString (market, 'settleCurrency');
const base = this.safeCurrencyCode (baseId);
const quote = this.safeCurrencyCode (quoteId);
const settle = this.safeCurrencyCode (settleId);
const status = this.safeString (market, 'status');
const marketType = this.safeString (market, 'type');
let inverse = undefined;
let linear = undefined;
let quanto = undefined;
const spot = (marketType === 'spot');
const swap = (marketType === 'futures');
const settleType = this.safeStringLower (market, 'settleType');
if (settleType !== undefined) {
inverse = (settleType === 'inverse');
linear = (settleType === 'vanilla');
quanto = (settleType === 'quanto');
}
let symbol = base + '/' + quote;
let type = 'spot';
let contractSize = undefined;
let minLeverage = undefined;
let maxLeverage = undefined;
if (swap) {
symbol = symbol + ':' + settle;
type = 'swap';
contractSize = this.safeNumber (market, 'multiplier');
minLeverage = '1';
const imRate = this.safeString (market, 'imRate');
maxLeverage = Precise.stringDiv ('1', imRate);
}
result.push ({
'id': id,
'symbol': symbol,
'base': base,
'quote': quote,
'settle': settle,
'baseId': baseId,
'quoteId': quoteId,
'settleId': settleId,
'type': type,
'spot': spot,
'margin': false,
'swap': swap,
'future': false,
'option': false,
'active': (status === 'enable'),
'contract': swap,
'linear': linear,
'inverse': inverse,
'quanto': quanto,
'taker': this.safeNumber (market, 'takerFee'),
'maker': this.safeNumber (market, 'makerFee'),
'contractSize': contractSize,
'expiry': undefined,
'expiryDatetime': undefined,
'strike': undefined,
'optionType': undefined,
'precision': {
'amount': this.safeNumber (market, 'lotSize'),
'price': this.safeNumber (market, 'tickSize'),
},
'limits': {
'leverage': {
'min': this.parseNumber (minLeverage),
'max': this.parseNumber (maxLeverage),
},
'amount': {
'min': this.safeNumber (market, 'minQuantity'),
'max': this.safeNumber (market, 'maxQuantity'),
},
'price': {
'min': this.safeNumber (market, 'minPrice'),
'max': this.safeNumber (market, 'maxPrice'),
},
'cost': {
'min': undefined,
'max': undefined,
},
},
'info': market,
});
}
return result;
}
async fetchCurrencies (params = {}) {
/**
* @method
* @name aax#fetchCurrencies
* @description fetches all available currencies on an exchange
* @param {dict} params extra parameters specific to the aax api endpoint
* @returns {dict} an associative dictionary of currencies
*/
const response = await this.publicGetCurrencies (params);
//
// {
// "code":1,
// "data":[
// {
// "chain":"BTC",
// "displayName":"Bitcoin",
// "withdrawFee":"0.0004",
// "withdrawMin":"0.001",
// "otcFee":"0",
// "enableOTC":true,
// "visible":true,
// "enableTransfer":true,
// "transferMin":"0.00001",
// "depositMin":"0.0005",
// "enableWithdraw":true,
// "enableDeposit":true,
// "addrWithMemo":false,
// "withdrawPrecision":"0.00000001",
// "currency":"BTC",
// "network":"BTC", // ETH, ERC20, TRX, TRC20, OMNI, LTC, XRP, XLM, ...
// "minConfirm":"2"
// },
// ],
// "message":"success",
// "ts":1624330530697
// }
//
const result = {};
const data = this.safeValue (response, 'data', []);
for (let i = 0; i < data.length; i++) {
const currency = data[i];
const id = this.safeString (currency, 'chain');
const name = this.safeString (currency, 'displayName');
const code = this.safeCurrencyCode (id);
const enableWithdraw = this.safeValue (currency, 'enableWithdraw');
const enableDeposit = this.safeValue (currency, 'enableDeposit');
const fee = this.safeNumber (currency, 'withdrawFee');
const visible = this.safeValue (currency, 'visible');
const active = (enableWithdraw && enableDeposit && visible);
const deposit = (enableDeposit && visible);
const withdraw = (enableWithdraw && visible);
const network = this.safeString (currency, 'network');
result[code] = {
'id': id,
'name': name,
'code': code,
'precision': this.safeNumber (currency, 'withdrawPrecision'),
'info': currency,
'active': active,
'deposit': deposit,
'withdraw': withdraw,
'fee': fee,
'network': network,
'limits': {
'deposit': {
'min': this.safeNumber (currency, 'depositMin'),
'max': undefined,
},
'withdraw': {
'min': this.safeNumber (currency, 'withdrawMin'),
'max': undefined,
},
},
};
}
return result;
}
parseTicker (ticker, market = undefined) {
//
// {
// "t":1610162685342, // timestamp
// "a":"0.00000000", // trading volume in USD in the last 24 hours, futures only
// "c":"435.20000000", // close
// "d":"4.22953489", // change
// "h":"455.04000000", // high
// "l":"412.78000000", // low
// "o":"417.54000000", // open
// "s":"BCHUSDTFP", // market id
// "v":"2031068.00000000", // trading volume in quote currency of last 24 hours
// }
//
const timestamp = this.safeInteger (ticker, 't');
const marketId = this.safeString (ticker, 's');
const symbol = this.safeSymbol (marketId, market);
const last = this.safeString (ticker, 'c');
const open = this.safeString (ticker, 'o');
const quoteVolume = this.safeString (ticker, 'v');
return this.safeTicker ({
'symbol': symbol,
'timestamp': timestamp,
'datetime': undefined,
'high': this.safeString (ticker, 'h'),
'low': this.safeString (ticker, 'l'),
'bid': undefined,
'bidVolume': undefined,
'ask': undefined,
'askVolume': undefined,
'vwap': undefined,
'open': open,
'close': last,
'last': last,
'previousClose': undefined,
'change': undefined,
'percentage': undefined,
'average': undefined,
'baseVolume': undefined,
'quoteVolume': quoteVolume,
'info': ticker,
}, market);
}
async setMargin (symbol, amount, params = {}) {
/**
* @method
* @name aax#setMargin
* @description Either adds or reduces margin in an isolated position in order to set the margin to a specific value
* @see https://www.aax.com/apidoc/index.html#modify-isolated-position-margin
* @param {str} symbol unified market symbol of the market to set margin in
* @param {float} amount the amount to set the margin to
* @param {dict} params parameters specific to the aax api endpoint
* @returns {dict} A [margin structure]{@link https://docs.ccxt.com/en/latest/manual.html#add-margin-structure}
*/
await this.loadMarkets ();
const market = this.market (symbol);
const request = {
'symbol': market['id'],
'margin': amount,
};
const response = await this.privatePostFuturesPositionMargin (this.extend (request, params));
//
// {
// code: '1',
// data: {
// autoMarginCall: false,
// avgEntryPrice: '0.52331',
// bankruptPrice: '0.3185780400',
// base: 'ADA',
// code: 'FP',
// commission: '0.00031399',
// currentQty: '1',
// funding: '0',
// fundingStatus: null,
// id: '447888550222172160',
// leverage: '5.25',
// liquidationPrice: '0.324007',
// marketPrice: '0',
// openTime: '2022-05-20T14:30:42.759Z',
// posLeverage: '2.56',
// posMargin: '0.20473196',
// quote: 'USDT',
// realisedPnl: '0',
// riskLimit: '10000000',
// riskyPrice: '0.403728',
// settleType: 'VANILLA',
// stopLossPrice: '0',
// stopLossSource: '0',
// symbol: 'ADAUSDTFP',
// takeProfitPrice: '0',
// takeProfitSource: '0',
// unrealisedPnl: '-0.00151000',
// userID: '3311296'
// },
// message: 'success',
// ts: '1653057280756'
// }
//
const data = this.safeValue (response, 'data', {});
return this.parseModifyMargin (data, market);
}
parseModifyMargin (data, market = undefined) {
//
// {
// autoMarginCall: false,
// avgEntryPrice: '0.52331',
// bankruptPrice: '0.3185780400',
// base: 'ADA',
// code: 'FP',
// commission: '0.00031399',
// currentQty: '1',
// funding: '0',
// fundingStatus: null,
// id: '447888550222172160',
// leverage: '5.25',
// liquidationPrice: '0.324007',
// marketPrice: '0',
// openTime: '2022-05-20T14:30:42.759Z',
// posLeverage: '2.56',
// posMargin: '0.20473196',
// quote: 'USDT',
// realisedPnl: '0',
// riskLimit: '10000000',
// riskyPrice: '0.403728',
// settleType: 'VANILLA',
// stopLossPrice: '0',
// stopLossSource: '0',
// symbol: 'ADAUSDTFP',
// takeProfitPrice: '0',
// takeProfitSource: '0',
// unrealisedPnl: '-0.00151000',
// userID: '3315296'
// }
//
const marketId = this.safeString (data, 'symbol');
const quote = this.safeString (data, 'quote');
return {
'info': data,
'type': 'set',
'amount': undefined,
'total': this.safeNumber (data, 'posMargin'),
'code': this.safeCurrencyCode (quote),
'symbol': this.safeSymbol (marketId, market),
'status': undefined,
};
}
async fetchTickers (symbols = undefined, params = {}) {
/**
* @method
* @name aax#fetchTickers
* @description fetches price tickers for multiple markets, statistical calculations with the information calculated over the past 24 hours each market
* @param {[str]|undefined} symbols unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
* @param {dict} params extra parameters specific to the aax api endpoint
* @returns {dict} an array of [ticker structures]{@link https://docs.ccxt.com/en/latest/manual.html#ticker-structure}
*/
await this.loadMarkets ();
const response = await this.publicGetMarketTickers (params);
//
// {
// "e":"tickers",
// "t":1610162685342,
// "tickers":[
// {
// "a":"0.00000000",
// "c":"435.20000000",
// "d":"4.22953489",
// "h":"455.04000000",
// "l":"412.78000000",
// "o":"417.54000000",
// "s":"BCHUSDTFP",
// "v":"2031068.00000000",
// },
// ],
// }
//
const tickers = this.safeValue (response, 'tickers', []);
const result = [];
const timestamp = this.safeInteger (response, 't');
for (let i = 0; i < tickers.length; i++) {
const ticker = this.parseTicker (this.extend (tickers[i], { 't': timestamp }));
result.push (ticker);
}
return this.filterByArray (result, 'symbol', symbols);
}
async fetchOrderBook (symbol, limit = undefined, params = {}) {
/**
* @method
* @name aax#fetchOrderBook
* @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
* @param {str} symbol unified symbol of the market to fetch the order book for
* @param {int|undefined} limit the maximum amount of order book entries to return
* @param {dict} params extra parameters specific to the aax api endpoint
* @returns {dict} A dictionary of [order book structures]{@link https://docs.ccxt.com/en/latest/manual.html#order-book-structure} indexed by market symbols
*/
await this.loadMarkets ();
const market = this.market (symbol);
if (limit === undefined) {
limit = 20;
} else {
if ((limit !== 20) && (limit !== 50)) {
throw new BadRequest (this.id + ' fetchOrderBook() limit argument must be undefined, 20 or 50');
}
}
const request = {
'symbol': market['id'],
'level': limit, // required
};
//
const response = await this.publicGetMarketOrderbook (this.extend (request, params));
//
// {
// "asks":[
// ["10823.00000000","0.004000"],
// ["10823.10000000","0.100000"],
// ["10823.20000000","0.010000"]
// ],
// "bids":[
// ["10821.20000000","0.002000"],
// ["10821.10000000","0.005000"],
// ["10820.40000000","0.013000"]
// ],
// "e":"BTCUSDT@book_50",
// "t":1561543614756
// }
//
const timestamp = this.safeInteger (response, 't'); // need unix type
return this.parseOrderBook (response, symbol, timestamp);
}
parseTrade (trade, market = undefined) {
//
// public fetchTrades
//
// {
// "i":"T1qzQeZG9g",
// "p":"-61348.81000000",
// "q":"0.045400",
// "s":"sell",
// "t":1635731102731
// }
//
// private fetchMyTrades
//
// {
// "avgPrice":"1199.8",
// "base":"ETH",
// "clOrdID":null,
// "commission":"0.00002",
// "createTime":"2021-01-11T02:47:51.512Z",
// "cumQty":"0.02",
// "filledOrderID":"1eUD4F5rwK",
// "filledPrice":"1199.8",
// "filledQty":"0.02",
// "leavesQty":"0",
// "oCreateTime":"2021-01-11T02:47:51.377Z",
// "orderID":"1eUD4EHfdU",
// "orderQty":"0.02",
// "orderStatus":3,
// "orderType":1,
// "price":"1198.25",
// "quote":"USDT",
// "rejectCode":null,
// "rejectReason":null,
// "side":1,
// "stopPrice":"0",
// "symbol":"ETHUSDT",
// "taker":true,
// "tradeID":"E04WTIgfmULU",
// "transactTime":"2021-01-11T02:47:51.389Z",
// "updateTime":null,
// "userID":"1362494"
// }
//
let timestamp = this.safeInteger (trade, 't');
if (timestamp === undefined) {
timestamp = this.parse8601 (this.safeString (trade, 'createTime'));
}
let id = this.safeString2 (trade, 'tid', 'tradeID');
id = this.safeString (trade, 'i', id);
const marketId = this.safeString (trade, 'symbol');
market = this.safeMarket (marketId, market);
let priceString = this.safeString2 (trade, 'p', 'filledPrice');
const amountString = this.safeString2 (trade, 'q', 'filledQty');
const orderId = this.safeString (trade, 'orderID');
const isTaker = this.safeValue (trade, 'taker');
let takerOrMaker = undefined;
if (isTaker !== undefined) {
takerOrMaker = isTaker ? 'taker' : 'maker';
}
let side = this.safeString (trade, 'side');
if (side === '1') {
side = 'buy';
} else if (side === '2') {
side = 'sell';
}
if (side === undefined) {
side = (priceString[0] === '-') ? 'sell' : 'buy';
}
priceString = Precise.stringAbs (priceString);
const orderType = this.parseOrderType (this.safeString (trade, 'orderType'));
let fee = undefined;
const feeCost = this.safeString (trade, 'commission');
if (feeCost !== undefined) {
let feeCurrency = undefined;
if (side === 'buy') {
feeCurrency = market['base'];
} else if (side === 'sell') {
feeCurrency = market['quote'];
}
fee = {
'currency': feeCurrency,
'cost': feeCost,
};
}
return this.safeTrade ({
'info': trade,
'id': id,
'timestamp': timestamp,
'datetime': this.iso8601 (timestamp),
'symbol': market['symbol'],
'type': orderType,
'side': side,
'order': orderId,
'takerOrMaker': takerOrMaker,
'price': priceString,
'amount': amountString,
'cost': undefined,
'fee': fee,
}, market);
}
async fetchTransfers (code = undefined, since = undefined, limit = undefined, params = {}) {
/**
* @method
* @name aax#fetchTransfers
* @description fetch a history of internal transfers made on an account
* @param {str|undefined} code unified currency code of the currency transferred
* @param {int|undefined} since the earliest time in ms to fetch transfers for
* @param {int|undefined} limit the maximum number of transfers structures to retrieve
* @param {dict} params extra parameters specific to the aax api endpoint
* @returns {[dict]} a list of [transfer structures]{@link https://docs.ccxt.com/en/latest/manual.html#transfer-structure}
*/
await this.loadMarkets ();
let currency = undefined;
const request = {};
if (code !== undefined) {
currency = this.currency (code);
request['currency'] = currency['id'];
}
if (since !== undefined) {
request['startTime'] = since;
}
const response = await this.privateGetAccountTransfer (this.extend (request, params));
//
// {
// code: '1',
// data: [{
// quantity: '0.000010000000',
// transferID: '480975741034369024',
// transferTime: '2022-03-24T13:53:07.042Z',
// fromPurse: 'VLTP',
// toPurse: 'SPTP',
// currency: 'ETH'
// },
// ],
// message: 'success',
// ts: '1648338516932'
// }
//
const transfers = this.safeValue (response, 'data', []);
return this.parseTransfers (transfers, currency, since, limit);
}
async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
/**
* @method
* @name aax#fetchTrades
* @description get the list of most recent trades for a particular symbol
* @param {str} symbol unified symbol of the market to fetch trades for
* @param {int|undefined} since timestamp in ms of the earliest trade to fetch
* @param {int|undefined} limit the maximum amount of trades to fetch
* @param {dict} params extra parameters specific to the aax api endpoint
* @returns {[dict]} a list of [trade structures]{@link https://docs.ccxt.com/en/latest/manual.html?#public-trades}
*/
await this.loadMarkets ();
const market = this.market (symbol);
limit = (limit === undefined) ? 2000 : limit;
limit = Math.min (limit, 2000);
const request = {
'symbol': market['id'],
'limit': limit,
};
const response = await this.publicGetMarketTrades (request);
//
// {
// "e":"BTCUSDT@trades",
// "trades":[
// {"i":"T1qzQeZG9g","p":"-61348.81000000","q":"0.045400","s":"sell","t":1635731102731},
// {"i":"T1qzQeU6UK","p":"61343.10000000","q":"0.179300","s":"buy","t":1635731102133},
// {"i":"T1qzQe5BQm","p":"-61346.02000000","q":"0.021100","s":"sell","t":1635731099231},
// ]
// }
//
const trades = this.safeValue (response, 'trades', []);
return this.parseTrades (trades, market, since, limit);
}
parseOHLCV (ohlcv, market = undefined) {
//
// [
// 0.042398, // 0 open
// 0.042684, // 1 high
// 0.042366, // 2 low
// 0.042386, // 3 close
// 0.93734243, // 4 volume
// 1611514800, // 5 timestamp
// ]
//
return [
this.safeTimestamp (ohlcv, 5),
this.safeNumber (ohlcv, 0),
this.safeNumber (ohlcv, 1),
this.safeNumber (ohlcv, 2),
this.safeNumber (ohlcv, 3),
this.safeNumber (ohlcv, 4),
];
}
async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
/**
* @method
* @name aax#fetchOHLCV
* @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
* @param {str} symbol unified symbol of the market to fetch OHLCV data for
* @param {str} timeframe the length of time each candle represents
* @param {int|undefined} since timestamp in ms of the earliest candle to fetch
* @param {int|undefined} limit the maximum amount of candles to fetch
* @param {dict} params extra parameters specific to the aax api endpoint
* @returns {[[int]]} A list of candles ordered as timestamp, open, high, low, close, volume
*/
await this.loadMarkets ();
const market = this.market (symbol);
const request = {
// 'limit': limit, // if set counts from now into the past
'symbol': market['id'],
'timeFrame': this.timeframes[timeframe],
};
limit = (limit === undefined) ? 500 : limit;
const duration = this.parseTimeframe (timeframe);
if (since === undefined) {
const end = this.seconds ();
request['start'] = end - duration * limit;
request['end'] = end;
} else {
const start = parseInt (since / 1000);
request['start'] = start;
request['end'] = this.sum (start, duration * limit);
}
const response = await this.publicGetMarketHistoryCandles (this.extend (request, params));
//
// {
// "data":[
// [0.042398,0.042684,0.042366,0.042386,0.93734243,1611514800],
// [0.042386,0.042602,0.042234,0.042373,1.01925239,1611518400],
// [0.042373,0.042558,0.042362,0.042389,0.93801705,1611522000],
// ],
// "success":true,
// "t":1611875157
// }
//
const data = this.safeValue (response, 'data', []);
return this.parseOHLCVs (data, market, timeframe, since, limit);
}
async fetchAccounts (params = {}) {
/**
* @method
* @name aax#fetchAccounts
* @description fetch all the accounts associated with a profile
* @param {dict} params extra parameters specific to the aax api endpoint
* @returns {dict} a dictionary of [account structures]{@link https://docs.ccxt.com/en/latest/manual.html#account-structure} indexed by the account type
*/
const response = await this.privateGetAccountBalances (params);
//
// {
// "code":1,
// "data":[
// {
// "purseType":"FUTP",
// "currency":"BTC",
// "available":"0.41000000",
// "unavailable":"0.00000000"
// },
// {
// "purseType":"FUTP",
// "currency":"USDT",
// "available":"0.21000000",
// "unvaliable":"0.00000000"
// }
// ]
// "message":"success",
// "ts":1573530401020
// }
//
const data = this.safeValue (response, 'data', {});
return this.parseAccounts (data);
}
parseAccount (account) {
//
// {
// "purseType":"FUTP",
// "currency":"USDT",
// "available":"0.21000000",
// "unvaliable":"0.00000000"
// }
//
const currencyId = this.safeString (account, 'currency');
const accountId = this.safeString (account, 'purseType');
const accountsById = this.safeValue (this.options, 'accountsById', {});
return {
'info': account,
'id': undefined,
'code': this.safeCurrencyCode (currencyId),
'type': this.safeString (accountsById, accountId, accountId),
};
}
async fetchBalance (params = {}) {
/**
* @method
* @name aax#fetchBalance
* @description query for balance and get the amount of funds available for trading or funds locked in orders
* @param {dict} params extra parameters specific to the aax api endpoint
* @returns {dict} a [balance structure]{@link https://docs.ccxt.com/en/latest/manual.html?#balance-structure}
*/
await this.loadMarkets ();
const defaultType = this.safeString2 (this.options, 'fetchBalance', 'defaultType', 'spot');
const type = this.safeString (params, 'type', defaultType);
const types = this.safeValue (this.options, 'accountsByType', {});
const purseType = this.safeString (types, type, type);
const request = {
'purseType': purseType,
};
params = this.omit (params, 'type');
const response = await this.privateGetAccountBalances (this.extend (request, params));
//
// {
// "code":1,
// "data":[
// {
// "purseType":"FUTP",
// "currency":"BTC",
// "available":"0.41000000",
// "unavailable":"0.00000000"
// },
// {
// "purseType":"FUTP",
// "currency":"USDT",
// "available":"0.21000000",
// "unvaliable":"0.00000000"
// }
// ]
// "message":"success",
// "ts":1573530401020
// }
//
const data = this.safeValue (response, 'data', []);
const timestamp = this.safeInteger (response, 'ts');
const result = {
'info': response,
'timestamp': timestamp,
'datetime': this.iso8601 (timestamp),
};
for (let i = 0; i < data.length; i++) {
const balance = data[i];
const balanceType = this.safeString (balance, 'purseType');
if (balanceType === purseType) {
const currencyId = this.safeString (balance, 'currency');
const code = this.safeCurrencyCode (currencyId);
const account = this.account ();
account['free'] = this.safeString (balance, 'available');
account['used'] = this.safeString (balance, 'unavailable');
result[code] = account;
}
}
return this.safeBalance (result);
}
async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
/**
* @method
* @name aax#createOrder
* @description create a trade order
* @param {str} symbol unified symbol of the market to create an order in
* @param {str} type 'market' or 'limit'
* @param {str} side 'buy' or 'sell'
* @param {float} amount how much of currency you want to trade in units of base currency
* @param {float|undefined} price the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
* @param {dict} params extra parameters specific to the aax api endpoint
* @returns {dict} an [order structure]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure}
*/
let orderType = type.toUpperCase ();
const orderSide = side.toUpperCase ();
await this.loadMarkets ();
const market = this.market (symbol);
const request = {
// 'orderType': orderType, // MARKET, LIMIT, STOP, STOP-LIMIT
'symbol': market['id'],
'orderQty': this.amountToPrecision (symbol, amount),
'side': orderSide,
// 'stopPrice': this.priceToPrecision (symbol, stopPrice),
// 'clOrdID': clientOrderId, // up to 20 chars, lowercase and uppercase letters only
// 'timeInForce': 'GTC', // GTC, IOC, FOK, default is GTC
// 'execInst': 'Post-Only', // the only value supported by the exchange, futures and spot
};
const clientOrderId = this.safeString2 (params, 'clOrdID', 'clientOrderId');
if (clientOrderId !== undefined) {
request['clOrdID'] = clientOrderId;
}
const postOnly = this.safeValue (params, 'postOnly', false);
if (postOnly !== undefined) {
request['execInst'] = 'Post-Only';
}
params = this.omit (params, [ 'clOrdID', 'clientOrderId', 'postOnly' ]);
const stopPrice = this.safeNumber (params, 'stopPrice');
if (stopPrice === undefined) {
if ((orderType === 'STOP-LIMIT') || (orderType === 'STOP')) {
throw new ArgumentsRequired (this.id + ' createOrder() requires a stopPrice parameter for ' + orderType + ' orders');
}
} else {
if (orderType === 'LIMIT') {
orderType = 'STOP-LIMIT';
} else if (orderType === 'MARKET') {
orderType = 'STOP';
}
request['stopPrice'] = this.priceToPrecision (symbol, stopPrice);
params = this.omit (params, 'stopPrice');
}
if (orderType === 'LIMIT' || orderType === 'STOP-LIMIT') {
request['price'] = this.priceToPrecision (symbol, price);
}
request['orderType'] = orderType;
let method = undefined;
if (market['spot']) {
method = 'privatePostSpotOrders';
} else if (market['contract']) {
method = 'privatePostFuturesOrders';
}
const response = await this[method] (this.extend (request, params));
//
// spot
//
// {
// "code":1,
// "data":{
// "symbol":"ETHUSDT",
// "orderType":2,
// "avgPrice":"0",
// "execInst":null,
// "orderStatus":0,
// "userID":"1362494",
// "quote":"USDT",
// "rejectReason":null,
// "rejectCode":null,
// "price":"1500",
// "orderQty":"1",
// "commission":"0",
// "id":"268323430253735936",
// "timeInForce":1,
// "isTriggered":false,
// "side":2,
// "orderID":"1eO51MDSpQ",
// "leavesQty":"0",
// "cumQty":"0",
// "updateTime":null,
// "lastQty":"0",
// "clOrdID":null,
// "stopPrice":null,
// "createTime":null,
// "transactTime":null,
// "base":"ETH",
// "lastPrice":"0"
// },
// "message":"success",
// "ts":1610245290980
// }
//
// futures
//
// {
// "code":1,
// "data":{
// "liqType":0,
// "symbol":"ETHUSDTFP",
// "orderType":2,
// "leverage":"1",
// "marketPrice":"1318.3150000000",
// "code":"FP",
// "avgPrice":"0",
// "execInst":null,
// "orderStatus":0,
// "userID":"1362494",
// "quote":"USDT",
// "rejectReason":null,
// "rejectCode":null,
// "price":"500",
// "orderQty":"1",
// "commission":"0",
// "id":"268346885133053953",
// "timeInForce":1,
// "isTriggered":false,
// "side":1,
// "orderID":"1eOuPUAAkq",
// "leavesQty":"1",
// "cumQty":"0",
// "updateTime":null,
// "lastQty":null,
// "clOrdID":null,
// "stopPrice":null,
// "createTime":null,
// "transactTime":null,
// "settleType":"VANILLA",
// "base":"ETH",
// "lastPrice":"0"
// },
// "message":"success",
// "ts":1610250883059
// }
//
const data = this.safeValue (response, 'data', {});
return this.parseOrder (data, market);
}
async editOrder (id, symbol, type, side, amount, price = undefined, params = {}) {
await this.loadMarkets ();
const market = this.market (symbol);
const request = {
'orderID': id,
// 'orderQty': this.amountToPrecision (symbol, amount),
// 'price': this.priceToPrecision (symbol, price),
// 'stopPrice': this.priceToPrecision (symbol, stopPrice),
};
const stopPrice = this.safeNumber (params, 'stopPrice');
if (stopPrice !== undefined) {
request['stopPrice'] = this.priceToPrecision (symbol, stopPrice);
params = this.omit (params, 'stopPrice');
}
if (price !== undefined) {
request['price'] = this.priceToPrecision (symbol, price);
}
if (amount !== undefined) {
request['orderQty'] = this.amountToPrecision (symbol, amount);
}
let method = undefined;
if (market['spot']) {
method = 'privatePutSpotOrders';
} else if (market['contract']) {
method = 'privatePutFuturesOrders';
}
const response = await this[method] (this.extend (request, params));
//
// spot
//
// {
// "code":1,
// "data":{
// "symbol":"ETHUSDT",
// "orderType":2,
// "avgPrice":"0",
// "execInst":null,
// "orderStatus":0,
// "userID":"1362494",
// "quote":"USDT",
// "rejectReason":null,
// "rejectCode":null,
// "price":"1500",
// "orderQty":"1",
// "commission":"0",
// "id":"268323430253735936",
// "timeInForce":1,
// "isTriggered":false,
// "side":2,
// "orderID":"1eO51MDSpQ",
// "leavesQty":"0",
// "cumQty":"0",
// "updateTime":null,
// "lastQty":"0",
// "clOrdID":null,
// "stopPrice":null,
// "createTime":null,
// "transactTime":null,
// "base":"ETH",
// "lastPrice":"0"
// },
// "message":"success",
// "ts":1610245290980
// }
//
// futures
//
// {
// "code":1,
// "data":{
// "liqType":0,
// "symbol":"ETHUSDTFP",
// "orderType":2,
// "leverage":"1",
// "marketPrice":"1318.3150000000",
// "code":"FP",
// "avgPrice":"0",
// "execInst":null,
// "orderStatus":0,
// "userID":"1362494",
// "quote":"USDT",
// "rejectReason":null,
// "rejectCode":null,
// "price":"500",
// "orderQty":"1",
// "commission":"0",
// "id":"268346885133053953",
// "timeInForce":1,
// "isTriggered":false,
// "side":1,
// "orderID":"1eOuPUAAkq",
// "leavesQty":"1",
// "cumQty":"0",
// "updateTime":null,
// "lastQty":null,
// "clOrdID":null,
// "stopPrice":null,
// "createTime":null,
// "transactTime":null,
// "settleType":"VANILLA",
// "base":"ETH",
// "lastPrice":"0"
// },
// "message":"success",
// "ts":1610250883059
// }
//
const data = this.safeValue (response, 'data', {});
return this.parseOrder (data, market);
}
async cancelOrder (id, symbol = undefined, params = {}) {
/**
* @method
* @name aax#cancelOrder
* @description cancels an open order
* @param {str} id order id
* @param {str|undefined} symbol unified symbol of the market the order was made in
* @param {dict} params extra parameters specific to the aax api endpoint
* @returns {dict} An [order structure]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure}
*/
await this.loadMarkets ();
const request = {
'orderID': id,
};
let market = undefined;
if (symbol !== undefined) {
market = this.market (symbol);
}
const [ marketType, query ] = this.handleMarketTypeAndParams ('cancelOrder', market, params);
const method = this.getSupportedMapping (marketType, {
'spot': 'privateDeleteSpotOrdersCancelOrderID',
'swap': 'privateDeleteFuturesOrdersCancelOrderID',
'future': 'privateDeleteFuturesOrdersCancelOrderID',
});
const response = await this[method] (this.extend (request, query));
//
// spot
//
// {
// "code":1,
// "data":{
// "avgPrice":"0",
// "base":"BTC",
// "clOrdID":"aax",
// "commission":"0",
// "createTime":"2019-11-12T03:46:41Z",
// "cumQty":"0",
// "id":"114330021504606208",
// "isTriggered":false,
// "lastPrice":"0",
// "lastQty":"0",
// "leavesQty":"0",
// "orderID":"wJ4L366KB",
// "orderQty":"0.05",
// "orderStatus":1,
// "orderType":2,
// "price":"8000",
// "quote":"USDT",
// "rejectCode":0,
// "rejectReason":null,
// "side":1,
// "stopPrice":"0",
// "symbol":"BTCUSDT",
// "transactTime":null,
// "updateTime":"2019-11-12T03:46:41Z",
// "timeInForce":1,
// "userID":"216214"
// },
// "message":"success",
// "ts":1573530402029
// }
//
// futures
//
// {
// "code":1,
// "data":{
// "avgPrice":"0",
// "base":"BTC",
// "clOrdID":"aax_futures",
// "code":"FP",
// "commission":"0",
// "createTime":"2019-11-12T06:48:58Z",
// "cumQty":"0",
// "id":"114375893764395008",
// "isTriggered":false,
// "lastPrice":"0",
// "lastQty":null,
// "leavesQty":"300",
// "leverage":"1",
// "liqType":0,
// "marketPrice":"8760.75",
// "orderID":"wJTewQc81",
// "orderQty":"300",
// "orderStatus":1,
// "orderType":2,
// "price":"8000",
// "quote":"USD",
// "rejectCode":0,
// "rejectReason":null,
// "settleType":"INVERSE",
// "side":1,
// "stopPrice":"0",
// "symbol":"BTCUSDFP",
// "transactTime":"2019-11-12T06:48:58Z",
// "updateTime":"2019-11-12T06:48:58Z",
// "timeInForce":1,
// "execInst": "",
// "userID":"216214"
// },
// "message":"success",
// "ts":1573541642970
// }
//
const data = this.safeValue (response, 'data', {});
return this.parseOrder (data, market);
}
async cancelAllOrders (symbol = undefined, params = {}) {
/**
* @method
* @name aax#cancelAllOrders
* @description cancel all open orders in a market
* @param {str} symbol unified market symbol
* @param {dict} params extra parameters specific to the aax api endpoint
* @returns {[dict]} a list of [order structures]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure}
*/
if (symbol === undefined) {
throw new ArgumentsRequired (this.id + ' cancelAllOrders() requires a symbol argument');
}
await this.loadMarkets ();
const market = this.market (symbol);
const request = {
'symbol': market['id'],
};
let method = undefined;
if (market['spot']) {
method = 'privateDeleteSpotOrdersCancelAll';
} else if (market['contract']) {
method = 'privateDeleteFuturesOrdersCancelAll';
}
const response = await this[method] (this.extend (request, params));
//
// {
// "code":1,
// "data":[
// "vBC9rXsEE",
// "vBCc46OI0"
// ],
// "message":"success",
// "ts":1572597435470
// }
//
return response;
}
async fetchOrder (id, symbol = undefined, params = {}) {
/**
* @method
* @name aax#fetchOrder
* @description fetches information on an order made by the user
* @param {str|undefined} symbol unified symbol of the market the order was made in
* @param {dict} params extra parameters specific to the aax api endpoint
* @returns {dict} An [order structure]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure}
*/
await this.loadMarkets ();
const defaultType = this.safeString2 (this.options, 'fetchOrder', 'defaultType', 'spot');
params['type'] = this.safeString (params, 'type', defaultType);
const request = {};
const clientOrderId = this.safeString2 (params, 'clOrdID', 'clientOrderId');
if (clientOrderId === undefined) {
request['orderID'] = id;
} else {
request['clOrdID'] = clientOrderId;
params = this.omit (params, [ 'clOrdID', 'clientOrderId' ]);
}
const orders = await this.fetchOrders (symbol, undefined, undefined, this.extend (request, params));
const order = this.safeValue (orders, 0);
if (order === undefined) {
if (clientOrderId === undefined) {
throw new OrderNotFound (this.id + ' fetchOrder() could not find order id ' + id);
} else {
throw new OrderNotFound (this.id + ' fetchOrder() could not find order clientOrderID ' + clientOrderId);
}
}
return order;
}
async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
/**
* @method
* @name aax#fetchOpenOrders
* @description fetch all unfilled currently open orders
* @param {str|undefined} symbol unified market symbol
* @param {int|undefined} since the earliest time in ms to fetch open orders for
* @param {int|undefined} limit the maximum number of open orders structures to retrieve
* @param {dict} params extra parameters specific to the aax api endpoint
* @returns {[dict]} a list of [order structures]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure}
*/
await this.loadMarkets ();
const request = {
// 'pageNum': '1',
// 'pageSize': '10',
// 'symbol': market['id'],
// 'orderID': id,
// 'side': 'undefined', // BUY, SELL
// 'clOrdID': clientOrderId,
};
let market = undefined;
if (symbol !== undefined) {
market = this.market (symbol);
request['symbol'] = market['id'];
}
const [ marketType, query ] = this.handleMarketTypeAndParams ('fetchOpenOrders', market, params);
const method = this.getSupportedMapping (marketType, {
'spot': 'privateGetSpotOpenOrders',
'swap': 'privateGetFuturesOpenOrders',
'future': 'privateGetFuturesOpenOrders',
});
const clientOrderId = this.safeString2 (params, 'clOrdID', 'clientOrderId');
if (clientOrderId !== undefined) {
request['clOrdID'] = clientOrderId;
params = this.omit (params, [ 'clOrdID', 'clientOrderId' ]);
}
if (limit !== undefined) {
request['pageSize'] = limit; // default 10
}
const response = await this[method] (this.extend (request, query));
//
// spot
//
// {
// "code":1,
// "data":{
// "total":19,
// "pageSize":10,
// "list":[
// {
// "orderType":2,
// "symbol":"BTCUSDT",
// "avgPrice":"0",
// "orderStatus":0,
// "userID":"7225",
// "quote":"USDT",
// "rejectReason":null,
// "rejectCode":null,
// "price":"0",
// "orderQty":"0.002",
// "commission":"0",
// "id":"110419975166304256",
// "isTriggered":null,
// "side":1,
// "orderID":"vBGlDcLwk",
// "cumQty":"0",
// "leavesQty":"0",
// "updateTime":null,
// "clOrdID":"0001",
// "lastQty":"0",
// "stopPrice":"0",
// "createTime":"2019-11-01T08:49:33Z",
// "transactTime":null,
// "timeInForce":1,
// "base":"BTC",
// "lastPrice":"0"
// }
// ],
// "pageNum":1
// },
// "message":"success",
// "ts":1572598173682
// }
//
// futures
//
// {
// "code":1,
// "data":{
// "list":[
// {
// "avgPrice":"8768.99999999484997",
// "base":"BTC",
// "clOrdID":null,
// "code":"FP",
// "commission":"0.00000913",
// "createTime":"2019-11-12T07:05:52.000Z,
// "cumQty":"100",
// "id":"114380149603028993",
// "isTriggered":false,
// "lastPrice":"8769",
// "lastQty":"100",
// "leavesQty":"0",
// "leverage":"1",
// "liqType":1,
// "marketPrice":"8769.75",
// "orderID":"wJXURIFBT",
// "orderQty":"100",
// "orderStatus":3,
// "orderType":1,
// "price":"8769.75",
// "quote":"USD",
// "rejectCode":0,
// "rejectReason":null,
// "settleType":"INVERSE",
// "side":2,
// "stopPrice":"0",
// "symbol":"BTCUSDFP",
// "transactTime":"2019-11-12T07:05:52.000Z,
// "updateTime":"2019-11-12T07:05:52.000Z,
// "timeInForce":1,
// "execInst": "",
// "userID":"216214"
// },
// ],
// "pageNum":1,
// "pageSize":10,
// "total":21
// },
// "message":"success",
// "ts":1573546960172
// }
//
const data = this.safeValue (response, 'data', {});
const orders = this.safeValue (data, 'list', []);
return this.parseOrders (orders, market, since, limit);
}
async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
/**
* @method
* @name aax#fetchClosedOrders
* @description fetches information on multiple closed orders made by the user
* @param {str|undefined} symbol unified market symbol of the market orders were made in
* @param {int|undefined} since the earliest time in ms to fetch orders for
* @param {int|undefined} limit the maximum number of orde structures to retrieve
* @param {dict} params extra parameters specific to the aax api endpoint
* @returns {[dict]} a list of [order structures]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure
*/
const request = {
'orderStatus': '2', // 1 new, 2 filled, 3 canceled
};
return await this.fetchOrders (symbol, since, limit, this.extend (request, params));
}
async fetchCanceledOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
/**
* @method
* @name aax#fetchCanceledOrders
* @description fetches information on multiple canceled orders made by the user
* @param {str|undefined} symbol unified market symbol of the market orders were made in
* @param {int|undefined} since timestamp in ms of the earliest order, default is undefined
* @param {int|undefined} limit max number of orders to return, default is undefined
* @param {dict} params extra parameters specific to the aax api endpoint
* @returns {dict} a list of [order structures]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure}
*/
const request = {
'orderStatus': '3', // 1 new, 2 filled, 3 canceled
};
return await this.fetchOrders (symbol, since, limit, this.extend (request, params));
}
async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
/**
* @method
* @name aax#fetchOrders
* @description fetches information on multiple orders made by the user
* @param {str|undefined} symbol unified market symbol of the market orders were made in
* @param {int|undefined} since the earliest time in ms to fetch orders for
* @param {int|undefined} limit the maximum number of orde structures to retrieve
* @param {dict} params extra parameters specific to the aax api endpoint
* @returns {[dict]} a list of [order structures]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure
*/
await this.loadMarkets ();
const request = {
// 'pageNum': '1',
// 'pageSize': '10',
// 'symbol': market['id'],
// 'orderID': id,
// 'base': market['baseId'],
// 'quote': market['quoteId'],
// 'orderStatus': undefined, // 1 new, 2 filled, 3 canceled
// 'startDate': this.yyyymmdd (since),
// 'endDate': this.yyyymmdd (this.milliseconds()),
// 'orderType': undefined, // MARKET, LIMIT, STOP, STOP-LIMIT
// 'side': 'undefined', // BUY, SELL
// 'clOrdID': clientOrderId,
};
let market = undefined;
if (symbol !== undefined) {
market = this.market (symbol);
request['symbol'] = market['id'];
}
const [ marketType, query ] = this.handleMarketTypeAndParams ('fetchOrders', market, params);
const method = this.getSupportedMapping (marketType, {
'spot': 'privateGetSpotOrders',
'swap': 'privateGetFuturesOrders',
'future': 'privateGetFuturesOrders',
});
const clientOrderId = this.safeString2 (params, 'clOrdID', 'clientOrderId');
if (clientOrderId !== undefined) {
request['clOrdID'] = clientOrderId;
params = this.omit (params, [ 'clOrdID', 'clientOrderId' ]);
}
if (limit !== undefined) {
request['pageSize'] = limit; // default 10
}
if (since !== undefined) {
request['startDate'] = this.yyyymmdd (since);
}
const response = await this[method] (this.extend (request, query));
//
// spot
//
// {
// "code":1,
// "data":{
// "total":19,
// "pageSize":10,
// "list":[
// {
// "orderType":2,
// "symbol":"BTCUSDT",
// "avgPrice":"0",
// "orderStatus":0,
// "userID":"7225",
// "quote":"USDT",
// "rejectReason":null,
// "rejectCode":null,
// "price":"0",
// "orderQty":"0.002",
// "commission":"0",
// "id":"110419975166304256",
// "isTriggered":null,
// "side":1,
// "orderID":"vBGlDcLwk",
// "cumQty":"0",
// "leavesQty":"0",
// "updateTime":null,
// "clOrdID":"0001",
// "lastQty":"0",
// "stopPrice":"0",
// "createTime":"2019-11-01T08:49:33Z",
// "transactTime":null,
// "timeInForce":1,
// "base":"BTC",
// "lastPrice":"0"
// }
// ],
// "pageNum":1
// },
// "message":"success",
// "ts":1572598173682
// }
//
// futures
//
// {
// "code":1,
// "data":{
// "list":[
// {
// "avgPrice":"8768.99999999484997",
// "base":"BTC",
// "clOrdID":null,
// "code":"FP",
// "commission":"0.00000913",
// "createTime":"2019-11-12T07:05:52.000Z,
// "cumQty":"100",
// "id":"114380149603028993",
// "isTriggered":false,
// "lastPrice":"8769",
// "lastQty":"100",
// "leavesQty":"0",
// "leverage":"1",
// "liqType":1,
// "marketPrice":"8769.75",
// "orderID":"wJXURIFBT",
// "orderQty":"100",
// "orderStatus":3,
// "orderType":1,
// "price":"8769.75",
// "quote":"USD",
// "rejectCode":0,
// "rejectReason":null,
// "settleType":"INVERSE",
// "side":2,
// "stopPrice":"0",
// "symbol":"BTCUSDFP",
// "transactTime":"2019-11-12T07:05:52.000Z,
// "updateTime":"2019-11-12T07:05:52.000Z,
// "timeInForce":1,
// "execInst": "",
// "userID":"216214"
// },
// ],
// "pageNum":1,
// "pageSize":10,
// "total":21
// },
// "message":"success",
// "ts":1573546960172
// }
//
const data = this.safeValue (response, 'data', {});
const orders = this.safeValue (data, 'list', []);
return this.parseOrders (orders, market, since, limit);
}
parseOrderStatus (status) {
const statuses = {
'0': 'open', // pending new
'1': 'open', // new
'2': 'open', // partially-filled
'3': 'closed', // filled
'4': 'canceled', // cancel-reject
'5': 'canceled', // canceled
'6': 'rejected', // rejected
'10': 'expired', // expired
'11': 'rejected', // business-reject
};
return this.safeString (statuses, status, status);
}
parseOrderType (status) {
const statuses = {
'1': 'market',
'2': 'limit',
'3': 'stop',
'4': 'stop-limit',
'7': 'stop-loss',
'8': 'take-profit',
};
return this.safeString (statuses, status, status);
}
parseTimeInForce (timeInForce) {
const timeInForces = {
'1': 'GTC',
'3': 'IOC',
'4': 'FOK',
};
return this.safeString (timeInForces, timeInForce, timeInForce);
}
parseOrder (order, market = undefined) {
//
// {
// "avgPrice":"8768.99999999484997",
// "base":"BTC",
// "clOrdID":null,
// "code":"FP", // futures only
// "commission":"0.00000913",
// "createTime":"2019-11-12T07:05:52.000Z,
// "cumQty":"100",
// "id":"114380149603028993", // futures only
// "isTriggered":false,
// "lastPrice":"8769",
// "lastQty":"100",
// "leavesQty":"0",
// "leverage":"1", // futures only
// "liqType":1, // futures only
// "marketPrice":"8769.75", // futures only
// "orderID":"wJXURIFBT",
// "orderQty":"100",
// "orderStatus":3,
// "orderType":1,
// "price":"8769.75",
// "quote":"USD",
// "rejectCode":0,
// "rejectReason":null,
// "settleType":"INVERSE", // futures only
// "side":2,
// "stopPrice":"0",
// "symbol":"BTCUSDFP",
// "transactTime":"2019-11-12T07:05:52.000Z,
// "updateTime":"2019-11-12T07:05:52.000Z,
// "timeInForce":1,
// "execInst": "",
// "userID":"216214"
// }
//
// sometimes the timestamp is returned in milliseconds
let timestamp = this.safeValue (order, 'createTime');
if (typeof timestamp === 'string') {
timestamp = this.parse8601 (timestamp);
}
const status = this.parseOrderStatus (this.safeString (order, 'orderStatus'));
const type = this.parseOrderType (this.safeString (order, 'orderType'));
let side = this.safeString (order, 'side');
if (side === '1') {
side = 'buy';
} else if (side === '2') {
side = 'sell';
}
const id = this.safeString (order, 'orderID');
const clientOrderId = this.safeString (order, 'clOrdID');
const marketId = this.safeString (order, 'symbol');
market = this.safeMarket (marketId, market);
const price = this.safeString (order, 'price');
const stopPrice = this.safeNumber (order, 'stopPrice');
const timeInForce = this.parseTimeInForce (this.safeString (order, 'timeInForce'));
const execInst = this.safeString (order, 'execInst');
const postOnly = (execInst === 'Post-Only');
const average = this.safeString (order, 'avgPrice');
const amount = this.safeString (order, 'orderQty');
const filled = this.safeString (order, 'cumQty');
let remaining = this.safeString (order, 'leavesQty');
if ((Precise.stringEquals (filled, '0')) && (Precise.stringEquals (remaining, '0'))) {
remaining = undefined;
}
let lastTradeTimestamp = this.safeValue (order, 'transactTime');
if (typeof lastTradeTimestamp === 'string') {
lastTradeTimestamp = this.parse8601 (lastTradeTimestamp);
}
let fee = undefined;
const feeCost = this.safeNumber (order, 'commission');
if (feeCost !== undefined) {
let feeCurrency = undefined;
if (side === 'buy') {
feeCurrency = market['base'];
} else if (side === 'sell') {
feeCurrency = market['quote'];
}
fee = {
'currency': feeCurrency,
'cost': feeCost,
};
}
return this.safeOrder ({
'id': id,
'info': order,
'clientOrderId': clientOrderId,
'timestamp': timestamp,
'datetime': this.iso8601 (timestamp),
'lastTradeTimestamp': lastTradeTimestamp,
'status': status,
'symbol': market['symbol'],
'type': type,
'timeInForce': timeInForce,
'postOnly': postOnly,
'side': side,
'price': price,
'stopPrice': stopPrice,
'average': average,
'amount': amount,
'filled': filled,
'remaining': remaining,
'cost': undefined,
'trades': undefined,
'fee': fee,
}, market);
}
async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
/**
* @method
* @name aax#fetchMyTrades
* @description fetch all trades made by the user
* @param {str|undefined} symbol unified market symbol
* @param {int|undefined} since the earliest time in ms to fetch trades for
* @param {int|undefined} limit the maximum number of trades structures to retrieve
* @param {dict} params extra parameters specific to the aax api endpoint
* @returns {[dict]} a list of [trade structures]{@link https://docs.ccxt.com/en/latest/manual.html#trade-structure}
*/
await this.loadMarkets ();
const request = {
// 'pageNum': '1',
// 'pageSize': '10',
// 'symbol': market['id'],
// 'orderID': id,
// 'base': market['baseId'],
// 'quote': market['quoteId'],
// 'startDate': this.yyyymmdd (since),
// 'endDate': this.yyyymmdd (this.milliseconds()),
// 'orderType': undefined, // MARKET, LIMIT, STOP, STOP-LIMIT
// 'side': 'undefined', // BUY, SELL
};
let market = undefined;
if (symbol !== undefined) {
market = this.market (symbol);
request['symbol'] = market['id'];
}
const [ marketType, query ] = this.handleMarketTypeAndParams ('fetchMyTrades', market, params);
const method = this.getSupportedMapping (marketType, {
'spot': 'privateGetSpotTrades',
'swap': 'privateGetFuturesTrades',
'future': 'privateGetFuturesTrades',
});
if (limit !== undefined) {
request['pageSize'] = limit; // default 10
}
if (since !== undefined) {
request['startDate'] = this.yyyymmdd (since);
}
const response = await this[method] (this.extend (request, query));
//
// {
// "code":1,
// "data":{
// "list":[
// {
// "avgPrice":"1199.8",
// "base":"ETH",
// "clOrdID":null,
// "commission":"0.00002",
// "createTime":"2021-01-11T02:47:51.512Z",
// "cumQty":"0.02",
// "filledOrderID":"1eUD4F5rwK",
// "filledPrice":"1199.8",
// "filledQty":"0.02",
// "leavesQty":"0",
// "oCreateTime":"2021-01-11T02:47:51.377Z",
// "orderID":"1eUD4EHfdU",
// "orderQty":"0.02",
// "orderStatus":3,
// "orderType":1,
// "price":"1198.25",
// "quote":"USDT",
// "rejectCode":null,
// "rejectReason":null,
// "side":1,
// "stopPrice":"0",
// "symbol":"ETHUSDT",
// "taker":true,
// "tradeID":"E04WTIgfmULU",
// "transactTime":"2021-01-11T02:47:51.389Z",
// "updateTime":null,
// "userID":"1362494"
// }
// ],
// "pageNum":1,
// "pageSize":10,
// "total":1
// },
// "message":"success",
// "ts":1610333278042
// }
//
const data = this.safeValue (response, 'data', {});
const trades = this.safeValue (data, 'list', []);
return this.parseTrades (trades, market, since, limit);
}
async fetchDepositAddress (code, params = {}) {
/**
* @method
* @name aax#fetchDepositAddress
* @description fetch the deposit address for a currency associated with this account
* @param {str} code unified currency code
* @param {dict} params extra parameters specific to the aax api endpoint
* @returns {dict} an [address structure]{@link https://docs.ccxt.com/en/latest/manual.html#address-structure}
*/
await this.loadMarkets ();
const currency = this.currency (code);
const request = {
'currency': currency['id'],
// 'network': undefined, // 'ERC20
};
if ('network' in params) {
const networks = this.safeValue (this.options, 'networks', {});
const network = this.safeStringUpper (params, 'network');
params = this.omit (params, 'network');
request['network'] = this.safeStringUpper (networks, network, network);
}
const response = await this.privateGetAccountDepositAddress (this.extend (request, params));
//
// {
// "code":1,
// "data":{
// "address":"0x080c5c667381404cca9be0be9a04b2e47691ff86",
// "tag":null,
// "currency":"USDT",
// "network":"ERC20"
// },
// "message":"success",
// "ts":1610270465132
// }
//
const data = this.safeValue (response, 'data', {});
return this.parseDepositAddress (data, currency);
}
async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) {
/**
* @method
* @name aax#fetchDeposits
* @description fetch all deposits made to an account
* @param {str|undefined} code unified currency code
* @param {int|undefined} since the earliest time in ms to fetch deposits for
* @param {int|undefined} limit the maximum number of deposits structures to retrieve
* @param {dict} params extra parameters specific to the aax api endpoint
* @returns {[dict]} a list of [transaction structures]{@link https://docs.ccxt.com/en/latest/manual.html#transaction-structure}
*/
await this.loadMarkets ();
const request = {
// status Not required - Deposit status, "1: pending,2: confirmed, 3:failed"
// currency: Not required - String Currency
// startTime Not required Integer Default: 90 days from current timestamp.
// endTime Not required Integer Default: present timestamp.
};
let currency = undefined;
if (code !== undefined) {
currency = this.currency (code);
request['currency'] = currency['id'];
}
if (since !== undefined) {
const startTime = parseInt (since / 1000);
request['startTime'] = startTime;
request['endTime'] = this.sum (startTime, 90 * 24 * 60 * 60); // Only allows a 90 day window between start and end
}
const response = await this.privateGetAccountDeposits (this.extend (request, params));
// { "code": 1,
// "data": [{
// "currency": "USDT",
// "network": "USDT",
// "quantity": "19.000000000000",
// "txHash": "75eb2e5f037b025c535664c49a0f7cc8f601dae218a5f4fe82290ff652c43f3d",
// "address": "1GkB7Taf7uttcguKEb2DmmyRTnihskJ9Le",
// "status": "2",
// "createdTime": "2021-01-08T19:45:01.354Z",
// "updatedTime": "2021-01-08T20:03:05.000Z",
// }]
// "message": "success",
// "ts": 1573561743499
// }
const data = this.safeValue (response, 'data', []);
return this.parseTransactions (data, code, since, limit);
}
async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) {
/**
* @method
* @name aax#fetchWithdrawals
* @description fetch all withdrawals made from an account
* @param {str|undefined} code unified currency code
* @param {int|undefined} since the earliest time in ms to fetch withdrawals for
* @param {int|undefined} limit the maximum number of withdrawals structures to retrieve
* @param {dict} params extra parameters specific to the aax api endpoint
* @returns {[dict]} a list of [transaction structures]{@link https://docs.ccxt.com/en/latest/manual.html#transaction-structure}
*/
await this.loadMarkets ();
const request = {
// status Not required : "0: Under Review, 1: Manual Review, 2: On Chain, 3: Review Failed, 4: On Chain, 5: Completed, 6: Failed"
// currency: Not required - String Currency
// startTime Not required Integer Default: 30 days from current timestamp.
// endTime Not required Integer Default: present timestamp.
// Note difference between endTime and startTime must be 90 days or less
};
let currency = undefined;
if (code !== undefined) {
currency = this.currency (code);
request['currency'] = currency['id'];
}
if (since !== undefined) {
const startTime = parseInt (since / 1000);
request['startTime'] = startTime;
request['endTime'] = this.sum (startTime, 90 * 24 * 60 * 60); // Only allows a 90 day window between start and end
}
const response = await this.privateGetAccountWithdraws (this.extend (request, params));
// {
// "code":1,
// "data": [
// {
// "currency":"USDT",
// "network":"USDT",
// "quantity":"19.000000000000",
// "fee":"0.10000"
// "txHash":"75eb2e5f037b025c535664c49a0f7cc8f601dae218a5f4fe82290ff652c43f3d",
// "address":"1GkB7Taf7uttcguKEb2DmmyRTnihskJ9Le",
// "addressTag": "",
// "status":"2",
// "createdTime":"2021-01-08T19:45:01.354Z",
// "updatedTime":"2021-01-08T20:03:05.000Z",
// }
// ]
// "message":"success",
// "ts":1573561743499
// }
const data = this.safeValue (response, 'data', []);
return this.parseTransactions (data, code, since, limit);
}
parseTransactionStatusByType (status, type = undefined) {
const statuses = {
'deposit': {
'1': 'pending',
'2': 'ok',
'3': 'failed',
},
'withdrawal': {
'0': 'pending', // under review
'1': 'pending', // manual review
'2': 'pending', // on chain
'3': 'failed', // failed
'4': 'pending', // on chain
'5': 'ok', // completed
'6': 'failed', // failed
},
};
return this.safeString (this.safeValue (statuses, type, {}), status, status);
}
parseAddressByType (address, tag, type = undefined) {
let addressFrom = undefined;
let addressTo = undefined;
let tagFrom = undefined;
let tagTo = undefined;
if (type === 'deposit') {
addressFrom = address;
tagFrom = tag;
} else if (type === 'withdrawal') {
addressTo = address;
tagTo = tag;
}
return [ addressFrom, tagFrom, addressTo, tagTo ];
}
parseTransaction (transaction, currency = undefined) {
//
// fetchDeposits
//
// {
// "currency": "USDT",
// "network": "USDT",
// "quantity": "19.000000000000",
// "txHash": "75eb2e5f037b025c535664c49a0f7cc8f601dae218a5f4fe82290ff652c43f3d",
// "address": "1GkB7Taf7uttcguKEb2DmmyRTnihskJ9Le",
// "status": "2",
// "createdTime": "2021-01-08T19:45:01.354Z",
// "updatedTime": "2021-01-08T20:03:05.000Z",
// }
//
// fetchWithdrawals
//
// {
// "currency":"USDT",
// "network":"USDT",
// "quantity":"19.000000000000",
// "fee":"0.10000"
// "txHash":"75eb2e5f037b025c535664c49a0f7cc8f601dae218a5f4fe82290ff652c43f3d",
// "address":"1GkB7Taf7uttcguKEb2DmmyRTnihskJ9Le",
// "addressTag": "",
// "status":"2",
// "createdTime":"2021-01-08T19:45:01.354Z",
// "updatedTime":"2021-01-08T20:03:05.000Z",
// }
//
const fee = this.safeString (transaction, 'fee');
let type = 'withdrawal';
if (fee === undefined) {
type = 'deposit';
}
const code = this.safeCurrencyCode (this.safeString (transaction, 'currency'));
const txid = this.safeString (transaction, 'txHash');
const address = this.safeString (transaction, 'address');
const tag = this.safeString (transaction, 'addressTag'); // withdrawals only
const [ addressFrom, tagFrom, addressTo, tagTo ] = this.parseAddressByType (address, tag, type);
const amountString = this.safeString (transaction, 'quantity');
const timestamp = this.parse8601 (this.safeString (transaction, 'createdTime'));
const updated = this.parse8601 (this.safeString (transaction, 'updatedTime'));
const status = this.parseTransactionStatusByType (this.safeString (transaction, 'status'), type);
const network = this.safeString (transaction, 'network');
return {
'id': undefined,
'info': transaction,
'txid': txid,
'timestamp': timestamp,
'datetime': this.iso8601 (timestamp),
'network': network,
'addressFrom': addressFrom,
'address': address,
'addressTo': addressTo,
'amount': this.parseNumber (amountString),
'type': type,
'currency': code,
'status': status,
'updated': updated,
'tagFrom': tagFrom,
'tag': tag,
'tagTo': tagTo,
'comment': undefined,
'fee': fee,
};
}
async fetchFundingRate (symbol, params = {}) {
/**
* @method
* @name aax#fetchFundingRate
* @description fetch the current funding rate
* @param {str} symbol unified market symbol
* @param {dict} params extra parameters specific to the aax api endpoint
* @returns {dict} a [funding rate structure]{@link https://docs.ccxt.com/en/latest/manual.html#funding-rate-structure}
*/
await this.loadMarkets ();
const market = this.market (symbol);
if (!market['swap']) {
throw new BadRequest ('Funding rates only exist for swap contracts');
}
const request = {
'symbol': market['id'],
};
const response = await this.publicGetFuturesFundingPrevFundingRateSymbol (this.extend (request, params));
//
// {
// "code": 1,
// "data": {
// "symbol": "BTCUSDFP",
// "markPrice": "11192.5",
// "fundingRate": "0.001",
// "fundingTime": "2020-08-12T08:00:00Z",
// "nextFundingTime": "2020-08-12T16:00:00Z"
// },
// "message": "success",
// "ts": 1573542445411
// }
//
const data = this.safeValue (response, 'data');
return this.parseFundingRate (data);
}
parseFundingRate (contract, market = undefined) {
//
// {
// "symbol": "BTCUSDFP",
// "markPrice": "11192.5",
// "fundingRate": "0.001",
// "fundingTime": "2020-08-12T08:00:00Z",
// "nextFundingTime": "2020-08-12T16:00:00Z"
// }
//
const marketId = this.safeString (contract, 'symbol');
const symbol = this.safeSymbol (marketId, market);
const markPrice = this.safeNumber (contract, 'markPrice');
const fundingRate = this.safeNumber (contract, 'fundingRate');
const fundingDatetime = this.safeString (contract, 'fundingTime');
const nextFundingDatetime = this.safeString (contract, 'nextFundingTime');
return {
'info': contract,
'symbol': symbol,
'markPrice': markPrice,
'indexPrice': undefined,
'interestRate': undefined,
'estimatedSettlePrice': undefined,
'timestamp': undefined,
'datetime': undefined,
'fundingRate': fundingRate,
'fundingTimestamp': this.parse8601 (fundingDatetime),
'fundingDatetime': fundingDatetime,
'nextFundingRate': undefined,
'nextFundingTimestamp': this.parse8601 (nextFundingDatetime),
'nextFundingDatetime': nextFundingDatetime,
'previousFundingRate': undefined,
'previousFundingTimestamp': undefined,
'previousFundingDatetime': undefined,
};
}
parseDepositAddress (depositAddress, currency = undefined) {
//
// {
// "address":"0x080c5c667381404cca9be0be9a04b2e47691ff86",
// "tag":null,
// "currency":"USDT",
// "network":"ERC20"
// }
//
const address = this.safeString (depositAddress, 'address');
const tag = this.safeString (depositAddress, 'tag');
let currencyId = this.safeString (depositAddress, 'currency');
const network = this.safeString (depositAddress, 'network');
if (network !== undefined) {
currencyId = currencyId.replace (network, '');
}
const code = this.safeCurrencyCode (currencyId);
return {
'info': depositAddress,
'currency': code,
'address': address,
'tag': tag,
'network': network,
};
}
async fetchFundingRateHistory (symbol = undefined, since = undefined, limit = undefined, params = {}) {
/**
* @method
* @name aax#fetchFundingRateHistory
* @description fetches historical funding rate prices
* @param {str|undefined} symbol unified symbol of the market to fetch the funding rate history for
* @param {int|undefined} since timestamp in ms of the earliest funding rate to fetch
* @param {int|undefined} limit the maximum amount of [funding rate structures]{@link https://docs.ccxt.com/en/latest/manual.html?#funding-rate-history-structure} to fetch
* @param {dict} params extra parameters specific to the aax api endpoint
* @param {int|undefined} params.until timestamp in ms of the latest funding rate to fetch
* @returns {[dict]} a list of [funding rate structures]{@link https://docs.ccxt.com/en/latest/manual.html?#funding-rate-history-structure}
*/
if (symbol === undefined) {
throw new ArgumentsRequired (this.id + ' fetchFundingRateHistory() requires a symbol argument');
}
await this.loadMarkets ();
const market = this.market (symbol);
const request = {
'symbol': market['id'],
};
if (since !== undefined) {
request['startTime'] = parseInt (since / 1000);
}
const till = this.safeInteger2 (params, 'until', 'till'); // unified in milliseconds
params = this.omit (params, [ 'till', 'until' ]);
if (till !== undefined) {
request['endTime'] = parseInt (till / 1000);
}
if (limit !== undefined) {
request['limit'] = limit;
}
const response = await this.publicGetFuturesFundingFundingRate (this.extend (request, params));
//
// {
// "code": 1,
// "data": [
// {
// "fundingRate": "0.00033992",
// "fundingTime": "2021-12-31T00:00:00.000Z",
// "symbol": "ETHUSDTFP"
// },
// ]
// }
//
const data = this.safeValue (response, 'data', []);
const rates = [];
for (let i = 0; i < data.length; i++) {
const entry = data[i];
const marketId = this.safeString (entry, 'symbol');
const symbol = this.safeSymbol (marketId);
const datetime = this.safeString (entry, 'fundingTime');
rates.push ({
'info': entry,
'symbol': symbol,
'fundingRate': this.safeNumber (entry, 'fundingRate'),
'timestamp': this.parse8601 (datetime),
'datetime': datetime,
});
}
const sorted = this.sortBy (rates, 'timestamp');
return this.filterBySymbolSinceLimit (sorted, market['symbol'], since, limit);
}
async fetchFundingHistory (symbol = undefined, since = undefined, limit = undefined, params = {}) {
/**
* @method
* @name aax#fetchFundingHistory
* @description fetch the history of funding payments paid and received on this account
* @param {str} symbol unified market symbol
* @param {int|undefined} since the earliest time in ms to fetch funding history for
* @param {int|undefined} limit the maximum number of funding history structures to retrieve
* @param {dict} params extra parameters specific to the aax api endpoint
* @returns {dict} a [funding history structure]{@link https://docs.ccxt.com/en/latest/manual.html#funding-history-structure}
*/
await this.loadMarkets ();
if (symbol === undefined) {
throw new ArgumentsRequired (this.id + ' fetchFundingHistory() requires a symbol argument');
}
if (limit === undefined) {
limit = 100; // Default
} else if (limit > 1000) {
throw new BadRequest (this.id + ' fetchFundingHistory() limit argument cannot exceed 1000');
}
const market = this.market (symbol);
const request = {
'symbol': market['id'],
'limit': limit,
};
if (since !== undefined) {
request['startTime'] = since;
}
const response = await this.privateGetFuturesFundingFundingFee (this.extend (request, params));
//
// {
// "code": 1,
// "data": [
// {
// "symbol": "BTCUSDTFP",
// "fundingRate":"0.001",
// "fundingFee":"100",
// "currency":"USDT",
// "fundingTime": "2020-08-12T08:00:00Z",
// "markPrice": "11192.5",
// }
// ],
// "message": "success",
// "ts": 1573542445411
// }
//
const data = this.safeValue (response, 'data', []);
const result = [];
for (let i = 0; i < data.length; i++) {
const entry = data[i];
const datetime = this.safeString (entry, 'fundingTime');
result.push ({
'info': entry,
'symbol': symbol,
'code': this.safeCurrencyCode (this.safeString (entry, 'currency')),
'timestamp': this.parse8601 (datetime),
'datetime': datetime,
'id': undefined,
'amount': this.safeNumber (entry, 'fundingFee'),
});
}
return result;
}
async setLeverage (leverage, symbol = undefined, params = {}) {
/**
* @method
* @name aax#setLeverage
* @description set the level of leverage for a market
* @param {float} leverage the rate of leverage
* @param {str} symbol unified market symbol
* @param {dict} params extra parameters specific to the aax api endpoint
* @returns {dict} response from the exchange
*/
await this.loadMarkets ();
if (symbol === undefined) {
throw new ArgumentsRequired (this.id + ' setLeverage() requires a symbol argument');
}
if ((leverage < 1) || (leverage > 100)) {
throw new BadRequest (this.id + ' leverage should be between 1 and 100');
}
const market = this.market (symbol);
if (market['type'] !== 'swap') {
throw new BadSymbol (this.id + ' setLeverage() supports swap contracts only');
}
const request = {
'symbol': market['id'],
'leverage': leverage,
};
return await this.privatePostFuturesPositionLeverage (this.extend (request, params));
}
parseTransfer (transfer, currency = undefined) {
// {
// quantity: '0.000010000000',
// transferID: '480975741034369024',
// transferTime: '2022-03-24T13:53:07.042Z',
// fromPurse: 'VLTP',
// toPurse: 'SPTP',
// currency: 'ETH'
// },
const id = this.safeString (transfer, 'transferID');
const amount = this.safeNumber (transfer, 'quantity');
const timestamp = this.parse8601 (this.safeString (transfer, 'transferTime'));
const accounts = this.safeValue (this.options, 'accounts', {});
const fromId = this.safeString (transfer, 'fromPurse');
const toId = this.safeString (transfer, 'toPurse');
const fromAccount = this.safeString (accounts, fromId);
const toAccount = this.safeString (accounts, toId);
const currencyId = this.safeString (transfer, 'currency');
const currencyCode = this.safeCurrencyCode (currencyId, currency);
return {
'info': transfer,
'id': id,
'timestamp': timestamp,
'datetime': this.iso8601 (timestamp),
'currency': currencyCode,
'amount': amount,
'fromAccount': fromAccount,
'toAccount': toAccount,
'status': undefined,
};
}
parseTransferStatus (status) {
const statuses = {
'1': 'ok',
};
return this.safeString (statuses, status, 'canceled');
}
async transfer (code, amount, fromAccount, toAccount, params = {}) {
/**
* @method
* @name aax#transfer
* @description transfer currency internally between wallets on the same account
* @param {str} code unified currency code
* @param {float} amount amount to transfer
* @param {str} fromAccount account to transfer from
* @param {str} toAccount account to transfer to
* @param {dict} params extra parameters specific to the aax api endpoint
* @returns {dict} a [transfer structure]{@link https://docs.ccxt.com/en/latest/manual.html#transfer-structure}
*/
await this.loadMarkets ();
const currency = this.currency (code);
const accountTypes = this.safeValue (this.options, 'accountsByType', {});
const fromId = this.safeString (accountTypes, fromAccount, fromAccount);
const toId = this.safeString (accountTypes, toAccount, toAccount);
const request = {
'currency': currency['id'],
'fromPurse': fromId,
'toPurse': toId,
'quantity': amount,
};
const response = await this.privatePostAccountTransfer (this.extend (request, params));
//
// {
// "code": 1,
// "data": {
// "transferID": 888561,
// "transferTime": "2022-03-22T15:29:05.197Z"
// },
// "message": "success",
// "ts": 1647962945151
// }
//
const data = this.safeValue (response, 'data', {});
const transfer = this.parseTransfer (data, currency);
const transferOptions = this.safeValue (this.options, 'transfer', {});
const fillResponseFromRequest = this.safeValue (transferOptions, 'fillResponseFromRequest', true);
if (fillResponseFromRequest) {
if (transfer['fromAccount'] === undefined) {
transfer['fromAccount'] = fromAccount;
}
if (transfer['toAccount'] === undefined) {
transfer['toAccount'] = toAccount;
}
if (transfer['amount'] === undefined) {
transfer['amount'] = amount;
}
}
transfer['status'] = this.parseTransferStatus (this.safeString (response, 'code'));
return transfer;
}
parsePosition (position, market = undefined) {
//
// {
// "autoMarginCall": false,
// "avgEntryPrice": "3706.03",
// "bankruptPrice": "2963.3415880000",
// "base": "ETH",
// "code": "FP",
// "commission": "0.02964824",
// "currentQty": "2",
// "funding": "-0.04827355",
// "fundingStatus": null,
// "id": "385839395735639395",
// "leverage": "5",
// "liquidationPrice": "2983.07",
// "marketPrice": "3731.84",
// "openTime": "2021-12-31T18:57:25.930Z",
// "posLeverage": "5.00",
// "posMargin": "14.85376824",
// "quote": "USDT",
// "realisedPnl": "-0.07792179",
// "riskLimit": "10000000",
// "riskyPrice": "3272.25",
// "settleType": "VANILLA",
// "stopLossPrice": "0",
// "stopLossSource": 1,
// "symbol": "ETHUSDTFP",
// "takeProfitPrice": "0",
// "takeProfitSource": 1,
// "unrealisedPnl": "0.51620000",
// "userID": "3829384",
// "ts": 1641027194500
// }
//
const contract = this.safeString (position, 'symbol');
market = this.safeMarket (contract, market);
const size = this.safeString (position, 'currentQty');
let side = undefined;
if (Precise.stringGt (size, '0')) {
side = 'long';
} else if (Precise.stringLt (size, '0')) {
side = 'short';
}
const leverage = this.safeString (position, 'leverage');
const unrealisedPnl = this.safeString (position, 'unrealisedPnl');
const currentQty = this.safeString (position, 'currentQty');
const contractSize = this.safeString (market, 'contractSize');
const initialQuote = Precise.stringMul (currentQty, contractSize);
const marketPrice = this.safeString (position, 'marketPrice');
const timestamp = this.safeInteger (position, 'ts');
const liquidationPrice = this.safeString (position, 'liquidationPrice');
const marketInfo = this.safeValue (market, 'info');
const multiplier = this.safeString (marketInfo, 'multiplier');
const settleType = this.safeString (position, 'settleType');
const avgEntryPrice = this.safeString (position, 'avgEntryPrice');
const commission = this.safeString (position, 'commission');
let initialMargin = undefined;
let maintenanceMargin = undefined;
let notional = undefined;
// https://support.aax.com/en/articles/5295653-what-is-margin
if (settleType === 'VANILLA') {
notional = Precise.stringMul (initialQuote, marketPrice);
// Initial Margin (Limit order) = Number of contracts * Price * Multiplier / Leverage
initialMargin = Precise.stringDiv (Precise.stringMul (Precise.stringMul (currentQty, avgEntryPrice), multiplier), leverage);
// Maintenance Margin = (Number of contracts/ Entry Price * Multiplier / Leverage) + Commission fees
const tmp = Precise.stringDiv (Precise.stringMul (currentQty, multiplier), Precise.stringMul (avgEntryPrice, leverage));
maintenanceMargin = Precise.stringAdd (tmp, commission);
} else {
// inverse contracts
notional = Precise.stringDiv (initialQuote, marketPrice);
// Initial Margin (Limit Order) = Number of contracts / Entry Price / Leverage
// ^ no brackets /<::>\
initialMargin = Precise.stringDiv (currentQty, Precise.stringMul (leverage, avgEntryPrice));
// Maintenance Margin = Number of contracts / Entry price / Leverage
maintenanceMargin = initialMargin;
}
const collateral = this.safeString (position, 'posMargin');
const percentage = Precise.stringDiv (unrealisedPnl, initialMargin);
const marginRatio = Precise.stringDiv (maintenanceMargin, collateral);
return {
'info': position,
'symbol': this.safeString (market, 'symbol'),
'timestamp': timestamp,
'datetime': this.iso8601 (timestamp),
'initialMargin': this.parseNumber (initialMargin),
'initialMarginPercentage': this.parseNumber (Precise.stringDiv (initialMargin, notional)),
'maintenanceMargin': this.parseNumber (maintenanceMargin),
'maintenanceMarginPercentage': this.parseNumber (Precise.stringDiv (maintenanceMargin, notional)),
'entryPrice': this.parseNumber (avgEntryPrice),
'notional': this.parseNumber (notional),
'leverage': this.parseNumber (leverage),
'unrealizedPnl': this.parseNumber (unrealisedPnl),
'contracts': this.parseNumber (size),
'contractSize': this.parseNumber (contractSize),
'marginRatio': this.parseNumber (marginRatio),
'liquidationPrice': liquidationPrice,
'markPrice': this.safeNumber (position, 'marketPrice'),
'collateral': this.parseNumber (collateral),
'marginMode': 'isolated',
'side': side,
'percentage': this.parseNumber (percentage),
};
}
async fetchPosition (symbol = undefined, params = {}) {
/**
* @method
* @name aax#fetchPosition
* @description fetch data on a single open contract trade position
* @param {str} symbol unified market symbol of the market the position is held in, default is undefined
* @param {dict} params extra parameters specific to the aax api endpoint
* @returns {dict} a [position structure]{@link https://docs.ccxt.com/en/latest/manual.html#position-structure}
*/
await this.loadMarkets ();
const market = this.market (symbol);
const request = {
'symbol': market['id'],
};
const response = await this.privateGetFuturesPosition (this.extend (request, params));
//
// {
// "code": 1,
// "data": [
// {
// "autoMarginCall": false,
// "avgEntryPrice": "3706.03",
// "bankruptPrice": "2963.3415880000",
// "base": "ETH",
// "code": "FP",
// "commission": "0.02964824",
// "currentQty": "2",
// "funding": "-0.04827355",
// "fundingStatus": null,
// "id": "385839395735639395",
// "leverage": "5",
// "liquidationPrice": "2983.07",
// "marketPrice": "3731.84",
// "openTime": "2021-12-31T18:57:25.930Z",
// "posLeverage": "5.00",
// "posMargin": "14.85376824",
// "quote": "USDT",
// "realisedPnl": "-0.07792179",
// "riskLimit": "10000000",
// "riskyPrice": "3272.25",
// "settleType": "VANILLA",
// "stopLossPrice": "0",
// "stopLossSource": 1,
// "symbol": "ETHUSDTFP",
// "takeProfitPrice": "0",
// "takeProfitSource": 1,
// "unrealisedPnl": "0.51620000",
// "userID": "3829384"
// }
// ...
// ],
// "message": "success",
// "ts": 1641026778068
// }
//
const positions = this.safeValue (response, 'data', []);
const timestamp = this.safeInteger (response, 'ts');
const first = this.safeValue (positions, 0);
const position = this.parsePosition (first);
return this.extend (position, {
'timestamp': timestamp,
'datetime': this.iso8601 (timestamp),
});
}
async fetchPositions (symbols = undefined, params = {}) {
/**
* @method
* @name aax#fetchPositions
* @description fetch all open positions
* @param {[str]|undefined} symbols list of unified market symbols
* @param {dict} params extra parameters specific to the aax api endpoint
* @returns {[dict]} a list of [position structure]{@link https://docs.ccxt.com/en/latest/manual.html#position-structure}
*/
await this.loadMarkets ();
const request = {};
if (symbols !== undefined) {
let symbol = undefined;
if (Array.isArray (symbols)) {
const symbolsLength = symbols.length;
if (symbolsLength > 1) {
throw new BadRequest (this.id + ' fetchPositions() symbols argument cannot contain more than 1 symbol');
}
symbol = symbols[0];
} else {
symbol = symbols;
}
const market = this.market (symbol);
request['symbol'] = market['id'];
}
const response = await this.privateGetFuturesPosition (this.extend (request, params));
//
// {
// "code": 1,
// "data": [
// {
// "autoMarginCall": false,
// "avgEntryPrice": "3706.03",
// "bankruptPrice": "2963.3415880000",
// "base": "ETH",
// "code": "FP",
// "commission": "0.02964824",
// "currentQty": "2",
// "funding": "-0.04827355",
// "fundingStatus": null,
// "id": "385839395735639395",
// "leverage": "5",
// "liquidationPrice": "2983.07",
// "marketPrice": "3731.84",
// "openTime": "2021-12-31T18:57:25.930Z",
// "posLeverage": "5.00",
// "posMargin": "14.85376824",
// "quote": "USDT",
// "realisedPnl": "-0.07792179",
// "riskLimit": "10000000",
// "riskyPrice": "3272.25",
// "settleType": "VANILLA",
// "stopLossPrice": "0",
// "stopLossSource": 1,
// "symbol": "ETHUSDTFP",
// "takeProfitPrice": "0",
// "takeProfitSource": 1,
// "unrealisedPnl": "0.51620000",
// "userID": "3829384"
// }
// ...
// ],
// "message": "success",
// "ts": 1641026778068
// }
//
const result = [];
const positions = this.safeValue (response, 'data', []);
const timestamp = this.safeInteger (response, 'ts');
for (let i = 0; i < positions.length; i++) {
const position = this.parsePosition (positions[i]);
result.push (this.extend (position, {
'timestamp': timestamp,
'datetime': this.iso8601 (timestamp),
}));
}
return this.filterByArray (result, 'symbol', symbols, false);
}
nonce () {
return this.milliseconds ();
}
sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
let url = '/' + this.implodeParams (path, params);
const query = this.omit (params, this.extractParams (path));
if (api === 'v1') {
if (Object.keys (query).length) {
url += '?' + this.urlencode (query);
}
} else {
url = '/' + this.version + url;
if (api === 'public') {
if (Object.keys (query).length) {
url += '?' + this.urlencode (query);
}
} else if (api === 'private') {
this.checkRequiredCredentials ();
const nonce = this.nonce ().toString ();
headers = {
'X-ACCESS-KEY': this.apiKey,
'X-ACCESS-NONCE': nonce,
};
let auth = nonce + ':' + method;
if (method === 'GET') {
if (Object.keys (query).length) {
url += '?' + this.urlencode (query);
}
auth += url;
} else {
headers['Content-Type'] = 'application/json';
body = this.json (query);
auth += url + body;
}
const signature = this.hmac (this.encode (auth), this.encode (this.secret));
headers['X-ACCESS-SIGN'] = signature;
}
}
url = this.implodeHostname (this.urls['api'][api]) + url;
return { 'url': url, 'method': method, 'body': body, 'headers': headers };
}
handleErrors (code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
if (response === undefined) {
return; // fallback to default error handler
}
//
// {"code":40102,"message":"Unauthorized(invalid key)"}
//
const errorCode = this.safeString (response, 'code');
if ((errorCode !== undefined) && (errorCode !== '1')) {
const feedback = this.id + ' ' + this.json (response);
this.throwExactlyMatchedException (this.exceptions['exact'], errorCode, feedback);
this.throwBroadlyMatchedException (this.exceptions['broad'], body, feedback);
}
}
};