UNPKG

shrimpy-node

Version:
930 lines (841 loc) 35.3 kB
import Decimal from "decimal.js"; import * as querystring from 'querystring'; import * as rp from 'request-promise-native'; import { AuthenticationProvider } from "./authentication-provider"; import { IAccount, IAccountBalance, IAllocation, IApiKeyPermissions, IApiKeys, IAssetInsight, IBacktestAsset, IBacktestResult, ICandlestick, IExchangeAsset, IExchangeInfo, IHistoricalCandlestick, IHistoricalCount, IHistoricalOrderBook, IHistoricalInstrument, IHistoricalTrade, ILimitOrder, ILimitOrderStatus, IManagementCredits, IManagementStatus, IManagementUsage, IMarketOrderBooks, IPredictions, IStrategy, ITicker, ITotalBalanceHistoryItem, ITrade, ITradeChanges, ITradingPair, ITrend, IUser, } from "../models"; import { IAccountBalanceDto, IAccountDto, IAllocationDto, IApiKeyPermissionsDto, IApiKeysDto, IAssetInsightDto, IBacktestResultDto, IBacktestAssetDto, ICandlestickDto, IExchangeAssetDto, IExchangeInfoDto, IGuidIdResultDto, IHistoricalCandlestickDto, IHistoricalCountDto, IHistoricalOrderBookDto, IHistoricalInstrumentDto, IHistoricalTradeDto, ILimitOrderDto, ILimitOrderStatusDto, IMarketOrderBooksDto, INumberIdResultDto, IPredictionsDto, IRebalancePeriodResultDto, IStrategyDto, ITickerDto, ITotalBalanceHistoryItemDto, ITradeChangesDto, ITradeDto, ITradingPairDto, ITrendDto, IUserDto, IWebsocketTokenDto, } from "../dtos"; import { AccountBalanceDtoConverter, AllocationDtoConverter, AssetInsightDtoConverter, BacktestAssetDtoConverter, BacktestDataPointDtoConverter, CandlestickDtoConverter, DateDtoConverter, DecimalDtoConverter, HistoricalCandlestickDtoConverter, HistoricalOrderBooksDtoConverter, HistoricalInstrumentsDtoConverter, HistoricalTradesDtoConverter, LimitOrderDtoConverter, LimitOrderStatusDtoConverter, MarketOrderBooksDtoConverter, PredictionsDtoConverter, StrategyDtoConverter, TickerDtoConverter, TotalBalanceHistoryItemDtoConverter, TradeChangesDtoConverter, TradeDtoConverter, UserDtoConverter, TrendDtoConverter, } from "../dto-converters"; export class ShrimpyApiClient { private _accountBalanceDtoConverter = new AccountBalanceDtoConverter(); private _allocationDtoConverter = new AllocationDtoConverter(); private _assetInsightDtoConverter = new AssetInsightDtoConverter(); private _backtestAssetDtoConveter = new BacktestAssetDtoConverter(); private _backtestDataPointDtoConverter = new BacktestDataPointDtoConverter(); private _candlestickDtoConverter = new CandlestickDtoConverter(); private _dateDtoConverter = new DateDtoConverter(); private _decimalDtoConverter = new DecimalDtoConverter(); private _historicalCandlestickDtoConverter = new HistoricalCandlestickDtoConverter(); private _historicalOrderBooksDtoConverter = new HistoricalOrderBooksDtoConverter(); private _historicalInstrumentsDtoConverter = new HistoricalInstrumentsDtoConverter(); private _historicalTradesDtoConverter = new HistoricalTradesDtoConverter(); private _limitOrderDtoConverter = new LimitOrderDtoConverter(); private _limitOrderStatusDtoConverter = new LimitOrderStatusDtoConverter(); private _marketOrderBooksDtoConverter = new MarketOrderBooksDtoConverter(); private _predictionsDtoConverter = new PredictionsDtoConverter(); private _strategyDtoConverter = new StrategyDtoConverter(); private _tickerDtoConverter = new TickerDtoConverter(); private _totalBalanceHistoryItemDtoConverter = new TotalBalanceHistoryItemDtoConverter(); private _tradeChangesDtoConverter = new TradeChangesDtoConverter(); private _tradeDtoConverter = new TradeDtoConverter(); private _trendDtoConverter = new TrendDtoConverter(); private _userDtoConverter = new UserDtoConverter(); private _authenticationProvider: AuthenticationProvider | null = null; constructor( publicKey?: string, privateKey?: string, ) { if (publicKey && privateKey) { // keys were supplied, use them this._setApiCredentials(publicKey, privateKey); } } /* Public */ public async getSupportedExchanges(): Promise<IExchangeInfo[]> { const endpoint = `list_exchanges`; return await this._callEndpoint<IExchangeInfoDto[]>(endpoint, 'GET', null, false); } public async getExchangeAssets(exchange: string): Promise<IExchangeAsset[]> { const endpoint = `exchanges/${exchange}/assets`; return await this._callEndpoint<IExchangeAssetDto[]>(endpoint, 'GET', null, false); } public async getTradingPairs(exchange: string): Promise<ITradingPair[]> { const endpoint = `exchanges/${exchange}/trading_pairs`; return await this._callEndpoint<ITradingPairDto[]>(endpoint, 'GET', null, false); } /* Market Data */ public async getTicker(exchange: string): Promise<ITicker[]> { const endpoint = `exchanges/${exchange}/ticker`; const tickerDtos = await this._callEndpoint<ITickerDto[]>(endpoint, 'GET', null, false); return tickerDtos.map((tickerDto) => { return this._tickerDtoConverter.convertFromDto(tickerDto); }); } public async getOrderBooks( exchange: string | string[], baseSymbol?: string | string[], quoteSymbol?: string | string[], limit?: number ): Promise<IMarketOrderBooks[]> { const endpoint = `orderbooks`; let exchangeString: string; if (Array.isArray(exchange)) { exchangeString = exchange.join(','); } else { exchangeString = exchange; } const parameters: { exchange: string, baseSymbol?: string, quoteSymbol?: string, limit?: number } = { exchange: exchangeString }; if (baseSymbol) { if (Array.isArray(baseSymbol)) { parameters.baseSymbol = baseSymbol.join(','); } else { parameters.baseSymbol = baseSymbol; } } if (quoteSymbol) { if (Array.isArray(quoteSymbol)) { parameters.quoteSymbol = quoteSymbol.join(','); } else { parameters.quoteSymbol = quoteSymbol; } } if (limit) { parameters.limit = limit; } const orderBooksListDto = await this._callEndpoint<IMarketOrderBooksDto[]>(endpoint, 'GET', parameters, false); return orderBooksListDto.map((orderBooksDto) => { return this._marketOrderBooksDtoConverter.convertFromDto(orderBooksDto); }); } public async getCandles( exchange: string, baseTradingSymbol: string, quoteTradingSymbol: string, interval: '1m' | '5m' | '15m' | '1h' | '6h' | '1d', startTime?: Date, ): Promise<ICandlestick[]> { const endpoint = `exchanges/${exchange}/candles`; const parameters: { baseTradingSymbol: string, quoteTradingSymbol: string, interval: string, startTime?: string, } = { baseTradingSymbol: baseTradingSymbol, quoteTradingSymbol: quoteTradingSymbol, interval: interval, }; if (startTime) { parameters.startTime = this._dateDtoConverter.convertToDto(startTime); } const candlestickDtos = await this._callEndpoint<ICandlestickDto[]>(endpoint, 'GET', parameters, false); const result: ICandlestick[] = candlestickDtos.map((candlestickDto) => { return this._candlestickDtoConverter.convertFromDto(candlestickDto); }); return result; } /* Users */ public async getUsers(): Promise<IUser[]> { const endpoint = 'users'; const userDtos = await this._callEndpoint<IUserDto[]>(endpoint, 'GET', null, true); return userDtos.map((userDto) => { return this._userDtoConverter.convertFromDto(userDto); }); } public async getUser(userId: string): Promise<IUser> { const endpoint = `users/${userId}`; const userDto = await this._callEndpoint<IUserDto>(endpoint, 'GET', null, true); return this._userDtoConverter.convertFromDto(userDto); } public async createUser(name?: string): Promise<string> { const endpoint = 'users'; let parameters: { [key: string]: any } | null = null; if (name) { parameters = { name: name }; } const result = await this._callEndpoint<IGuidIdResultDto>(endpoint, 'POST', parameters, true); return result.id; } public async setUserName(userId: string, name: string): Promise<void> { const endpoint = `users/${userId}/name`; const parameters: { [key: string]: any } = { name: name }; await this._callEndpoint<any>(endpoint, 'POST', parameters, true); } public async removeUser(userId: string): Promise<void> { const endpoint = `users/${userId}`; await this._callEndpoint<any>(endpoint, 'DELETE', {}, true); } public async enableUser(userId: string): Promise<void> { // Deprecated, this endpoint no longer has any functionality // It has been preserved to avoid breaking deployments from library upgrades const endpoint = `users/${userId}/enable`; await this._callEndpoint<any>(endpoint, 'POST', null, true); } public async disableUser(userId: string): Promise<void> { // Deprecated, this endpoint no longer has any functionality // It has been preserved to avoid breaking deployments from library upgrades const endpoint = `users/${userId}/disable`; await this._callEndpoint<any>(endpoint, 'POST', null, true); } /* User API Keys */ public async getApiKeys(userId: string): Promise<string[]> { const endpoint = `users/${userId}/keys`; return await this._callEndpoint<string[]>(endpoint, 'GET', null, true); } public async createApiKeys(userId: string): Promise<IApiKeys> { const endpoint = `users/${userId}/keys`; return await this._callEndpoint<IApiKeysDto>(endpoint, 'POST', null, true); } public async deleteApiKeys(userId: string, publicKey: string): Promise<void> { const endpoint = `users/${userId}/keys/${publicKey}`; return await this._callEndpoint<any>(endpoint, 'DELETE', null, true); } public async getPermissions(userId: string, publicKey: string): Promise<IApiKeyPermissions> { const endpoint = `users/${userId}/keys/${publicKey}/permissions`; return await this._callEndpoint<IApiKeyPermissionsDto>(endpoint, 'GET', null, true); } public async setPermissions( userId: string, publicKey: string, account: boolean, trade: boolean, ): Promise<void> { const endpoint = `users/${userId}/keys/${publicKey}/permissions`; const parameters: IApiKeyPermissionsDto = { account: account, trade: trade }; await this._callEndpoint<any>(endpoint, 'POST', parameters, true); } /* Accounts */ public async getAccounts(userId: string): Promise<IAccount[]> { const endpoint = `users/${userId}/accounts`; return await this._callEndpoint<IAccountDto[]>(endpoint, 'GET', null, true); } public async getAccount(userId: string, accountId: number): Promise<IAccount> { const endpoint = `users/${userId}/accounts/${accountId}`; return await this._callEndpoint<IAccountDto>(endpoint, 'GET', null, true); } public async createAccount( userId: string, exchange: string, publicKey: string, privateKey: string, passphrase?: string, ): Promise<number> { const endpoint = `users/${userId}/accounts`; const parameters: { [key: string]: any } = { exchange: exchange, publicKey: publicKey, privateKey: privateKey, passphrase: passphrase, }; const result = await this._callEndpoint<INumberIdResultDto>(endpoint, 'POST', parameters, true); return result.id; } public async deleteAccount(userId: string, accountId: number): Promise<void> { const endpoint = `users/${userId}/accounts/${accountId}`; await this._callEndpoint<any>(endpoint, 'DELETE', null, true); } public async getIpWhitelistAddresses(userId: string): Promise<string[]> { const endpoint = `users/${userId}/whitelist`; return await this._callEndpoint<string[]>(endpoint, 'GET', null, true); } /* Trading */ public async createTrade( userId: string, accountId: number, fromSymbol: string, toSymbol: string, amount: Decimal, smartRouting?: boolean, maxSpreadPercent?: Decimal, maxSlippagePercent?: Decimal, ): Promise<string> { const endpoint = `users/${userId}/accounts/${accountId}/trades`; let parameters: { fromSymbol: string, toSymbol: string, amount: string, smartRouting?: boolean, maxSpreadPercent?: string, maxSlippagePercent?: string, } = { fromSymbol: fromSymbol, toSymbol: toSymbol, amount: this._decimalDtoConverter.convertToDto(amount), }; if (smartRouting) { parameters.smartRouting = smartRouting; } if (maxSpreadPercent) { parameters.maxSpreadPercent = this._decimalDtoConverter.convertToDto(maxSpreadPercent); } if (maxSlippagePercent) { parameters.maxSlippagePercent = this._decimalDtoConverter.convertToDto(maxSlippagePercent); } const result = await this._callEndpoint<IGuidIdResultDto>(endpoint, 'POST', parameters, true); return result.id; } public async getTrade( userId: string, accountId: number, tradeId: string, ): Promise<ITradeChanges> { const endpoint = `users/${userId}/accounts/${accountId}/trades/${tradeId}`; const tradeChangesDto = await this._callEndpoint<ITradeChangesDto>(endpoint, 'GET', null, true); return this._tradeChangesDtoConverter.convertFromDto(tradeChangesDto); } public async getActiveTrades(userId: string, accountId: number): Promise<ITrade[]> { const endpoint = `users/${userId}/accounts/${accountId}/trades`; const tradeDtos = await this._callEndpoint<ITradeDto[]>(endpoint, 'GET', null, true); return tradeDtos.map((tradeDto) => { return this._tradeDtoConverter.convertFromDto(tradeDto); }); } /* Balances */ public async getBalance( userId: string, accountId: number, date?: Date ): Promise<IAccountBalance> { const endpoint = `users/${userId}/accounts/${accountId}/balance`; let parameters: { date: string } | null = null; if (date) { parameters = { date: this._dateDtoConverter.convertToDto(date) }; } const accountBalanceDto = await this._callEndpoint<IAccountBalanceDto>(endpoint, 'GET', parameters, true); return this._accountBalanceDtoConverter.convertFromDto(accountBalanceDto); } public async getTotalBalanceHistory( userId: string, accountId: number, startTime: Date | null, endTime: Date | null ): Promise<ITotalBalanceHistoryItem[]> { const endpoint = `users/${userId}/accounts/${accountId}/total_balance_history`; let parameters: { startTime?: string, endTime?: string } | null = null; if (startTime || endTime) { parameters = {}; if (startTime) { parameters.startTime = this._dateDtoConverter.convertToDto(startTime); } if (endTime) { parameters.endTime = this._dateDtoConverter.convertToDto(endTime); } } const totalBalanceHistoryDtos = await this._callEndpoint<ITotalBalanceHistoryItemDto[]>(endpoint, 'GET', parameters, true); return totalBalanceHistoryDtos.map((totalBalanceHistoryDto) => { return this._totalBalanceHistoryItemDtoConverter.convertFromDto(totalBalanceHistoryDto); }); } /* Asset Management */ public async rebalance(userId: string, accountId: number): Promise<void> { const endpoint = `users/${userId}/accounts/${accountId}/rebalance`; await this._callEndpoint<any>(endpoint, 'POST', null, true); } public async getRebalancePeriod(userId: string, accountId: number): Promise<number> { const endpoint = `users/${userId}/accounts/${accountId}/rebalance_period`; const result = await this._callEndpoint<IRebalancePeriodResultDto>(endpoint, 'GET', null, true); return result.rebalancePeriod; } public async setRebalancePeriod( userId: string, accountId: number, rebalancePeriodHours: number ): Promise<void> { // verify rebalancePeriodHours is an integer if (!Number.isInteger(rebalancePeriodHours)) { throw new Error("Invalid rebalance period. Rebalance period must be an integer"); } const endpoint = `users/${userId}/accounts/${accountId}/rebalance_period`; const parameters: { rebalancePeriod: number } = { rebalancePeriod: rebalancePeriodHours }; await this._callEndpoint<any>(endpoint, 'POST', parameters, true); } public async getStrategy( userId: string, accountId: number, ): Promise<IStrategy> { const endpoint = `users/${userId}/accounts/${accountId}/strategy`; const strategyDto = await this._callEndpoint<IStrategyDto>(endpoint, 'GET', null, true); return this._strategyDtoConverter.convertFromDto(strategyDto); } public async setStrategy( userId: string, accountId: number, strategy: IStrategy, ): Promise<void> { const endpoint = `users/${userId}/accounts/${accountId}/strategy`; let parameters: IStrategyDto = this._strategyDtoConverter.convertToDto(strategy); await this._callEndpoint<any>(endpoint, 'POST', parameters, true); } public async clearStrategy( userId: string, accountId: number, ): Promise<void> { const endpoint = `users/${userId}/accounts/${accountId}/strategy`; await this._callEndpoint<any>(endpoint, 'DELETE', null, true); } public async allocate( userId: string, accountId: number, strategy: IStrategy, ): Promise<void> { const endpoint = `users/${userId}/accounts/${accountId}/allocate`; let parameters: IStrategyDto = this._strategyDtoConverter.convertToDto(strategy); await this._callEndpoint<any>(endpoint, 'POST', parameters, true); } /* Limit Orders */ public async createOrder( userId: string, accountId: number, baseSymbol: string, quoteSymbol: string, quantity: Decimal, price: Decimal, side: "BUY" | "SELL", timeInForce: "GTC" | "IOC" ): Promise<string> { const endpoint = `users/${userId}/accounts/${accountId}/orders`; let parameters: { baseSymbol: string, quoteSymbol: string, quantity: string, price: string, side: string, timeInForce: string } = { baseSymbol: baseSymbol, quoteSymbol: quoteSymbol, quantity: this._decimalDtoConverter.convertToDto(quantity), price: this._decimalDtoConverter.convertToDto(price), side: side, timeInForce: timeInForce }; const result = await this._callEndpoint<IGuidIdResultDto>(endpoint, 'POST', parameters, true); return result.id; } public async getOrder( userId: string, accountId: number, orderId: string ): Promise<ILimitOrderStatus> { const endpoint = `users/${userId}/accounts/${accountId}/orders/${orderId}`; const limitOrderStatusDto = await this._callEndpoint<ILimitOrderStatusDto>(endpoint, 'GET', null, true); return this._limitOrderStatusDtoConverter.convertFromDto(limitOrderStatusDto); } public async getOrders( userId: string, accountId: number ): Promise<ILimitOrder[]> { const endpoint = `users/${userId}/accounts/${accountId}/orders`; const limitOrderDtos = await this._callEndpoint<ILimitOrderDto[]>(endpoint, 'GET', null, true); return limitOrderDtos.map((limitOrderDto) => { return this._limitOrderDtoConverter.convertFromDto(limitOrderDto); }); } public async cancelOrder( userId: string, accountId: number, orderId: string ): Promise<void> { const endpoint = `users/${userId}/accounts/${accountId}/orders/${orderId}`; await this._callEndpoint<any>(endpoint, 'DELETE', null, true); } /* Analytics */ public async getBacktestAssets( exchange: string, startTime?: Date, endTime?: Date ): Promise<IBacktestAsset[]> { const endpoint = `analytics/backtest/${exchange}/assets`; const parameters: { startTime?: string, endTime?: string } = {}; if (startTime) { parameters.startTime = this._dateDtoConverter.convertToDto(startTime); } if (endTime) { parameters.endTime = this._dateDtoConverter.convertToDto(endTime); } const backtestAssetDtos = await this._callEndpoint<IBacktestAssetDto[]>(endpoint, 'GET', parameters, true); const result: IBacktestAsset[] = backtestAssetDtos.map((backtestAssetDto) => { return this._backtestAssetDtoConveter.convertFromDto(backtestAssetDto); }); return result; } public async runBacktest( exchange: string, rebalancePeriodHours: number, fee: Decimal, startTime: Date, endTime: Date, initialValue: Decimal, allocations: IAllocation[] ): Promise<IBacktestResult> { const endpoint = `analytics/backtest/${exchange}/run`; const allocationsDto = allocations.map((allocation) => { return this._allocationDtoConverter.convertToDto(allocation); }); const parameters: { rebalancePeriod: number, fee: string, startTime: string, endTime: string, initialValue: string, allocations: IAllocationDto[] } = { rebalancePeriod: rebalancePeriodHours, fee: fee.toString(), startTime: this._dateDtoConverter.convertToDto(startTime), endTime: this._dateDtoConverter.convertToDto(endTime), initialValue: initialValue.toString(), allocations: allocationsDto, }; const resultDto = await this._callEndpoint<IBacktestResultDto>(endpoint, 'POST', parameters, true); const rebalanceData = resultDto.rebalanceData.map((dataPointDto) => { return this._backtestDataPointDtoConverter.convertFromDto(dataPointDto); }); const holdingData = resultDto.holdingData.map((dataPointDto) => { return this._backtestDataPointDtoConverter.convertFromDto(dataPointDto); }); const result: IBacktestResult = { rebalanceData: rebalanceData, holdingData: holdingData, }; return result; } public async getPredictions( exchange: string, baseTradingSymbol: string, quoteTradingSymbol: string ): Promise<IPredictions> { const endpoint = `analytics/predict`; const parameters: { exchange: string, baseTradingSymbol: string, quoteTradingSymbol: string } = { exchange: exchange, baseTradingSymbol: baseTradingSymbol, quoteTradingSymbol: quoteTradingSymbol } const predictionsListDto = await this._callEndpoint<IPredictionsDto>(endpoint, 'GET', parameters, true); return this._predictionsDtoConverter.convertFromDto(predictionsListDto); } public async getTrend( exchange: string, baseTradingSymbol: string, quoteTradingSymbol: string ): Promise<ITrend> { const endpoint = `analytics/trend`; const parameters: { exchange: string, baseTradingSymbol: string, quoteTradingSymbol: string } = { exchange: exchange, baseTradingSymbol: baseTradingSymbol, quoteTradingSymbol: quoteTradingSymbol } const trendDto = await this._callEndpoint<ITrendDto>(endpoint, 'GET', parameters, true); return this._trendDtoConverter.convertFromDto(trendDto); } /* Insights */ public async getAssetDominance(): Promise<IAssetInsight[]> { const endpoint = `insights/asset_dominance`; const assetInsightDtos = await this._callEndpoint<IAssetInsightDto[]>(endpoint, 'GET', null, true); return assetInsightDtos.map((assetInsightDto) => { return this._assetInsightDtoConverter.convertFromDto(assetInsightDto); }); } public async getAssetPopularity(): Promise<IAssetInsight[]> { const endpoint = `insights/asset_popularity`; const assetInsightDtos = await this._callEndpoint<IAssetInsightDto[]>(endpoint, 'GET', null, true); return assetInsightDtos.map((assetInsightDto) => { return this._assetInsightDtoConverter.convertFromDto(assetInsightDto); }); } /* Historical */ public async getHistoricalTrades( exchange: string, baseTradingSymbol: string, quoteTradingSymbol: string, startTime: Date, endTime: Date, limit: number ): Promise<IHistoricalTrade[]> { const endpoint = `historical/trades`; const parameters: { exchange: string, baseTradingSymbol: string, quoteTradingSymbol: string, startTime: string, endTime: string, limit: number, } = { exchange: exchange, baseTradingSymbol: baseTradingSymbol, quoteTradingSymbol: quoteTradingSymbol, startTime: this._dateDtoConverter.convertToDto(startTime), endTime: this._dateDtoConverter.convertToDto(endTime), limit: limit, }; const resultDto = await this._callEndpoint<IHistoricalTradeDto[]>(endpoint, 'GET', parameters, true); return this._historicalTradesDtoConverter.convertFromDto(resultDto); } public async getHistoricalOrderBooks( exchange: string, baseTradingSymbol: string, quoteTradingSymbol: string, startTime: Date, endTime: Date, limit: number ): Promise<IHistoricalOrderBook[]> { const endpoint = `historical/orderbooks`; const parameters: { exchange: string, baseTradingSymbol: string, quoteTradingSymbol: string, startTime: string, endTime: string, limit: number, } = { exchange: exchange, baseTradingSymbol: baseTradingSymbol, quoteTradingSymbol: quoteTradingSymbol, startTime: this._dateDtoConverter.convertToDto(startTime), endTime: this._dateDtoConverter.convertToDto(endTime), limit: limit, }; const resultDto = await this._callEndpoint<IHistoricalOrderBookDto[]>(endpoint, 'GET', parameters, true); return this._historicalOrderBooksDtoConverter.convertFromDto(resultDto); } public async getHistoricalCandles( exchange: string, baseTradingSymbol: string, quoteTradingSymbol: string, startTime: Date, endTime: Date, limit: number, interval: '1m' | '5m' | '15m' | '1h' | '6h' | '1d' ): Promise<IHistoricalCandlestick[]> { const endpoint = `historical/candles`; const parameters: { exchange: string, baseTradingSymbol: string, quoteTradingSymbol: string, startTime: string, endTime: string, limit: number, interval: '1m' | '5m' | '15m' | '1h' | '6h' | '1d' } = { exchange: exchange, baseTradingSymbol: baseTradingSymbol, quoteTradingSymbol: quoteTradingSymbol, startTime: this._dateDtoConverter.convertToDto(startTime), endTime: this._dateDtoConverter.convertToDto(endTime), limit: limit, interval: interval }; const resultDto = await this._callEndpoint<IHistoricalCandlestickDto[]>(endpoint, 'GET', parameters, true); const result = resultDto.map((candlestick) => { return this._historicalCandlestickDtoConverter.convertFromDto(candlestick); }); return result; } public async getHistoricalInstruments( exchange?: string, baseTradingSymbol?: string, quoteTradingSymbol?: string ): Promise<IHistoricalInstrument[]> { const endpoint = `historical/instruments`; const parameters: { exchange?: string, baseTradingSymbol?: string, quoteTradingSymbol?: string } = { exchange: exchange, baseTradingSymbol: baseTradingSymbol, quoteTradingSymbol: quoteTradingSymbol }; const resultDto = await this._callEndpoint<IHistoricalInstrumentDto[]>(endpoint, 'GET', parameters, true); return this._historicalInstrumentsDtoConverter.convertFromDto(resultDto); } public async getHistoricalCount( type: 'trade' | 'orderbook', exchange: string, baseTradingSymbol: string, quoteTradingSymbol: string, startTime: Date, endTime: Date ): Promise<IHistoricalCount> { const endpoint = `historical/count`; const parameters: { type: string, exchange: string, baseTradingSymbol: string, quoteTradingSymbol: string, startTime: string, endTime: string } = { type: type, exchange: exchange, baseTradingSymbol: baseTradingSymbol, quoteTradingSymbol: quoteTradingSymbol, startTime: this._dateDtoConverter.convertToDto(startTime), endTime: this._dateDtoConverter.convertToDto(endTime) }; const countDto = await this._callEndpoint<IHistoricalCountDto>(endpoint, 'GET', parameters, true); const result: IHistoricalCount = { count: countDto.count }; return result; } /* Management */ public async getStatus(): Promise<IManagementStatus> { const endpoint = `management/status`; return await this._callEndpoint<IManagementStatus>(endpoint, 'GET', null, true); } public async getCredits(): Promise<IManagementCredits> { const endpoint = `management/credits`; return await this._callEndpoint<IManagementCredits>(endpoint, 'GET', null, true); } public async getUsage(): Promise<IManagementUsage> { // Deprecated, this endpoint no longer has any functionality // It has been preserved to avoid breaking deployments from library upgrades const endpoint = `management/usage`; return await this._callEndpoint<IManagementUsage>(endpoint, 'GET', null, true); } /* WebSocket */ public async getToken(): Promise<string> { const endpoint = `ws/token`; const websocketTokenResult = await this._callEndpoint<IWebsocketTokenDto>(endpoint, 'GET', null, true); return websocketTokenResult.token; } /* private methods */ private _setApiCredentials(publicKey: string, privateKey: string): void { this._authenticationProvider = new AuthenticationProvider(publicKey, privateKey); } private async _callEndpoint<T>( endPoint: string, method: 'GET' | 'POST' | 'DELETE', parameters: { [key: string]: any } | null, isSignRequired: boolean ): Promise<T> { let requestPath = "/v1/" + endPoint; let options: rp.OptionsWithUri & { headers: { [key: string]: any }} = { uri: "https://dev-api.shrimpy.io" + requestPath, headers: { 'content-type': 'application/json', }, method: method }; if (method === 'GET' && parameters && Object.keys(parameters).length > 0) { const qs = '?' + querystring.stringify(parameters); options.uri += qs; requestPath += qs; } if (method === 'POST') { if (parameters) { // only attach the body if there are parameters // no parameters, send empty body options.body = JSON.stringify(parameters); } else { options.body = ""; } } if (isSignRequired && !this._authenticationProvider) { throw new Error(`Cannot send a request to ${endPoint} without api keys. Make sure to pass api keys to the ShrimpyApiClient constructor.`); } if (this._authenticationProvider) { const nonce = Date.now(); const bodyString = options.body ? options.body : ""; const prehashString = requestPath + method + nonce + bodyString; const signature = this._authenticationProvider.sign(prehashString); options.headers['DEV-SHRIMPY-API-KEY'] = this._authenticationProvider.publicKey; options.headers['DEV-SHRIMPY-API-NONCE'] = nonce; options.headers['DEV-SHRIMPY-API-SIGNATURE'] = signature; } const response: string = await rp(options); return JSON.parse(response); } }