shrimpy-node
Version:
Client for the Shrimpy API
930 lines (841 loc) • 35.3 kB
text/typescript
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);
}
}