Skip to content

Commit

Permalink
Use CCXT for BittrexAPI
Browse files Browse the repository at this point in the history
  • Loading branch information
Cayle Sharrock committed Nov 11, 2017
1 parent fa8ff4f commit 2895761
Show file tree
Hide file tree
Showing 3 changed files with 167 additions and 219 deletions.
145 changes: 6 additions & 139 deletions src/exchanges/bittrex/BittrexAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,153 +12,20 @@
* License for the specific language governing permissions and limitations under the License. *
***************************************************************************************************************************/

///<reference path="../../../types/node.bittrex.api.d.ts"/>

import { Product, PublicExchangeAPI, Ticker } from '../PublicExchangeAPI';
import * as Bittrex from 'node.bittrex.api';
import CCXTExchangeWrapper from '../ccxt/index';
import { ExchangeAuthConfig } from '../AuthConfig';
import { AuthenticatedExchangeAPI, Balances } from '../AuthenticatedExchangeAPI';
import { Big } from '../../lib/types';
import { BookBuilder } from '../../lib/BookBuilder';
import { bittrex } from 'ccxt';
import { Logger } from '../../utils/Logger';
import { PlaceOrderMessage } from '../../core/Messages';
import { LiveOrder } from '../../lib/Orderbook';

export class BittrexAPI implements PublicExchangeAPI, AuthenticatedExchangeAPI {
export class BittrexAPI extends CCXTExchangeWrapper {
static normalizeProduct(gdaxProduct: string): string {
const [base, quote] = gdaxProduct.split('-');
return `${quote}-${base}`;
}

readonly owner: string;
readonly logger: Logger;

constructor(auth: ExchangeAuthConfig, logger: Logger) {
this.owner = 'Bittrex';
this.logger = logger;
Bittrex.options({
apikey: auth.key || 'APIKEY',
apisecret: auth.secret || 'APISECRET',
inverse_callback_arguments: true,
stream: false,
cleartext: false,
verbose: false
});
}

loadProducts(): Promise<Product[]> {
return new Promise((resolve, reject) => {
Bittrex.getmarkets((err, data) => {
if (err) {
return reject(err);
}
if (!data.success || !data.result) {
return reject(new Error('Unexpected response from Bittrex: ' + JSON.stringify(data)));
}
const result: Product[] = data.result.map((market: any) => {
return {
id: market.MarketName, // same format as GDAX, so no need to map
sourceId: market.MarketName,
baseCurrency: market.BaseCurrency,
quoteCurrency: market.MarketCurrency,
baseMinSize: Big(market.MinTradeSize),
baseMaxSize: Big('1e18'),
quoteIncrement: Big(market.MinTradeSize),
sourceData: market
};
});
return resolve(result);
});
});
}

loadMidMarketPrice(gdaxProduct: string): Promise<BigNumber.BigNumber> {
return this.loadTicker(gdaxProduct).then((ticker: Ticker) => {
return ticker.bid.plus(ticker.ask).times(0.5);
});
}

loadOrderbook(gdaxProduct: string): Promise<BookBuilder> {
const product = BittrexAPI.normalizeProduct(gdaxProduct);
return new Promise((resolve, reject) => {
Bittrex.getorderbook({
market: product,
type: 'both',
depth: 5000
}, (err, data) => {
if (err) {
return reject(err);
}
if (!data.success || !data.result) {
return reject(new Error('Unexpected response from Bittrex: ' + JSON.stringify(data)));
}
const bids: any = data.result.buy;
const asks: any = data.result.sell;
const book: BookBuilder = new BookBuilder(this.logger);
bids.forEach((order: any) => {
book.add({
id: order.Rate,
price: Big(order.Rate),
size: Big(order.Quantity),
side: 'buy'
});
});
asks.forEach((order: any) => {
book.add({
id: order.Rate,
price: Big(order.Rate),
size: Big(order.Quantity),
side: 'sell'
});
});
return resolve(book);
});
});
}

loadTicker(gdaxProduct: string): Promise<Ticker> {
const product = BittrexAPI.normalizeProduct(gdaxProduct);
return new Promise((resolve, reject) => {
Bittrex.getticker({ market: product }, (err, data) => {
if (err) {
return reject(err);
}
if (!data.success || !data.result) {
return reject(new Error('Unexpected response from Bittrex: ' + JSON.stringify(data)));
}
const result: Ticker = {
productId: gdaxProduct,
ask: Big(data.result.Ask),
bid: Big(data.result.Bid),
price: Big(data.result.Last),
time: new Date()
};
return resolve(result);
});
});
}

placeOrder(order: PlaceOrderMessage): Promise<LiveOrder> {
throw new Error('Method not implemented.');
}

cancelOrder(id: string): Promise<string> {
throw new Error('Method not implemented.');
}

cancelAllOrders(product: string): Promise<string[]> {
throw new Error('Method not implemented.');
}

loadOrder(id: string): Promise<LiveOrder> {
throw new Error('Method not implemented.');
}

loadAllOrders(gdaxProduct: string): Promise<LiveOrder[]> {
throw new Error('Method not implemented.');
}

loadBalances(): Promise<Balances> {
throw new Error('Method not implemented.');
const options = { apiKey: auth.key, secret: auth.secret };
const ccxtInstance = new bittrex(options);
super('Bittrex', options, ccxtInstance, logger);
}
}
6 changes: 3 additions & 3 deletions src/exchanges/ccxt/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,15 @@ const exchanges: { [index: string]: ExchangeDefinition } = {
bitbay: ['Bitbay', ccxt.bitbay],
bitbays: ['Bitbays', ccxt.bitbays],
bitcoincoid: ['Bitcoincoid', ccxt.bitcoincoid],
// bitfinex: ['bitfinex', ccxt.bitfinex],
// bitfinex2: ['bitfinex2', ccxt.bitfinex2],
bitfinex: ['bitfinex', ccxt.bitfinex],
bitfinex2: ['bitfinex2', ccxt.bitfinex2],
bitflyer: ['Bitflyer', ccxt.bitflyer],
bitlish: ['Bitlish', ccxt.bitlish],
bitmarket: ['Bitmarket', ccxt.bitmarket],
bitmex: ['Bitmex', ccxt.bitmex],
bitso: ['Bitso', ccxt.bitso],
bitstamp: ['Bitstamp', ccxt.bitstamp],
// bittRex: ['bittrex', ccxt.bittrex],
bittrex: ['bittrex', ccxt.bittrex],
bl3p: ['BL3P', ccxt.bl3p],
btcchina: ['BTCchina', ccxt.btcchina],
btce: ['BTC-e', ccxt.btce],
Expand Down
Loading

0 comments on commit 2895761

Please sign in to comment.