Skip to content

Commit

Permalink
fix: calculate swap amount for market orders
Browse files Browse the repository at this point in the history
This fixes a bug where the calculated swap amount for a market buy order could
be infinity. This could cause the sanity capacity check to fail when checking
a market order. Market buy orders internally have a positive infinity price
value for matching logic purposes, but the final price for market orders is
not known upon first placing them.

Fixes #978.
  • Loading branch information
sangaman committed May 28, 2019
1 parent ee39430 commit 2399549
Show file tree
Hide file tree
Showing 5 changed files with 22 additions and 5 deletions.
2 changes: 1 addition & 1 deletion lib/db/models/Order.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.DataTypes)
type: DataTypes.DOUBLE,
allowNull: true,
set(this: db.OrderInstance, value: number) {
if (value === 0 || value === Number.MAX_VALUE) {
if (value === 0 || value === Number.POSITIVE_INFINITY) {
this.setDataValue('price', undefined);
} else {
this.setDataValue('price', value);
Expand Down
2 changes: 1 addition & 1 deletion lib/orderbook/OrderBook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ class OrderBook extends EventEmitter {
throw errors.MARKET_ORDERS_NOT_ALLOWED();
}

const stampedOrder = this.stampOwnOrder({ ...order, price: order.isBuy ? Number.MAX_VALUE : 0 });
const stampedOrder = this.stampOwnOrder({ ...order, price: order.isBuy ? Number.POSITIVE_INFINITY : 0 });
const addResult = await this.placeOrder(stampedOrder, true, onUpdate, Date.now() + OrderBook.MAX_PLACEORDER_ITERATIONS_TIME);
delete addResult.remainingOrder;
return addResult;
Expand Down
7 changes: 5 additions & 2 deletions lib/swaps/Swaps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,15 @@ class Swaps extends EventEmitter {
* @param quantity The quantity of the order
* @param price The price of the order
* @param isBuy Whether the order is a buy
* @returns An object with the calculated incoming and outgoing values.
* @returns An object with the calculated incoming and outgoing values. The quote currency
* amount is returned as zero if the price is 0 or infinity, indicating a market order.
*/
public static calculateInboundOutboundAmounts = (quantity: number, price: number, isBuy: boolean, pairId: string) => {
const [baseCurrency, quoteCurrency] = pairId.split('/');
const baseCurrencyAmount = Math.round(quantity * Swaps.UNITS_PER_CURRENCY[baseCurrency]);
const quoteCurrencyAmount = Math.round(quantity * price * Swaps.UNITS_PER_CURRENCY[quoteCurrency]);
const quoteCurrencyAmount = price > 0 && price < Number.POSITIVE_INFINITY ?
Math.round(quantity * price * Swaps.UNITS_PER_CURRENCY[quoteCurrency]) :
0; // if price is zero or infinity, this is a market order and we can't know the quote currency amount

const inboundCurrency = isBuy ? baseCurrency : quoteCurrency;
const inboundAmount = isBuy ? baseCurrencyAmount : quoteCurrencyAmount;
Expand Down
2 changes: 1 addition & 1 deletion test/unit/DB.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ describe('Database', () => {
});

it('should add market orders and have their price in db be null', async () => {
const buyMarketOrder = createOwnOrder(Number.MAX_VALUE, quantity, true);
const buyMarketOrder = createOwnOrder(Number.POSITIVE_INFINITY, quantity, true);
const sellMarketOrder = createOwnOrder(0, quantity, true);
await orderBookRepo.addOrderIfNotExists(buyMarketOrder);
await orderBookRepo.addOrderIfNotExists(sellMarketOrder);
Expand Down
14 changes: 14 additions & 0 deletions test/unit/Swaps.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,20 @@ describe('Swaps', () => {
expect(outboundAmount).to.equal(Swaps['UNITS_PER_CURRENCY']['LTC'] * quantity);
});

it('should calculate 0 outbound amount for a market buy order', () => {
const { outboundCurrency, outboundAmount } =
Swaps.calculateInboundOutboundAmounts(quantity, 0, true, pairId);
expect(outboundCurrency).to.equal('BTC');
expect(outboundAmount).to.equal(0);
});

it('should calculate 0 inbound amount for a market sell order', () => {
const { inboundCurrency, inboundAmount } =
Swaps.calculateInboundOutboundAmounts(quantity, Number.POSITIVE_INFINITY, false, pairId);
expect(inboundCurrency).to.equal('BTC');
expect(inboundAmount).to.equal(0);
});

it('should validate a good swap request', () => {
expect(Swaps.validateSwapRequest(swapRequest)).to.be.true;
});
Expand Down

0 comments on commit 2399549

Please sign in to comment.