serum-vial
Advanced tools
Comparing version 1.3.1 to 1.3.2
@@ -28,3 +28,2 @@ import { Market } from '@project-serum/serum'; | ||
private _addChangedOrderItemsToL3Diff; | ||
private _addOpenOrdersForImmediateMakerFills; | ||
reset(): void; | ||
@@ -31,0 +30,0 @@ private _validateL3DiffCorrectness; |
@@ -34,5 +34,44 @@ "use strict"; | ||
const l3Diff = []; | ||
const newAsksSlabItems = accountsData.asks !== undefined | ||
? [...serum_1.Orderbook.decode(this._options.market, accountsData.asks).slab.items(false)] | ||
: this._asksAccountSlabItems; | ||
const newAsksOrders = accountsData.asks !== undefined && newAsksSlabItems !== undefined | ||
? newAsksSlabItems.map(this._mapAskSlabItemToOrder) | ||
: this._asksAccountOrders; | ||
const newBidsSlabItems = accountsData.bids !== undefined | ||
? [...serum_1.Orderbook.decode(this._options.market, accountsData.bids).slab.items(true)] | ||
: this._bidsAccountSlabItems; | ||
const newBidsOrders = accountsData.bids !== undefined && newBidsSlabItems !== undefined | ||
? newBidsSlabItems.map(this._mapBidSlabItemToOrder) | ||
: this._bidsAccountOrders; | ||
if (this._initialized && accountsData.eventQueue !== undefined) { | ||
let fillsIds = new Map(); | ||
for (const event of this._getNewlyAddedEvents(accountsData.eventQueue)) { | ||
// for maker fills check first if there's existing open order for it | ||
// as it may not exist in scenario where order was added to the order book and matched in the same slot | ||
if (event.eventFlags.fill === true && event.eventFlags.maker === true) { | ||
const makerFill = this._mapEventToDataMessage(event, timestamp, slot, fillsIds); | ||
const currentOpenOrders = makerFill.side === 'buy' ? newBidsOrders : newAsksOrders; | ||
const lastOpenOrders = makerFill.side === 'buy' ? this._bidsAccountOrders : this._asksAccountOrders; | ||
const hasMatchingOpenOrder = currentOpenOrders.some((o) => o.orderId === makerFill.orderId) || | ||
lastOpenOrders.some((o) => o.orderId === makerFill.orderId); | ||
if (hasMatchingOpenOrder === false) { | ||
const openMessage = { | ||
type: 'open', | ||
market: this._options.symbol, | ||
timestamp, | ||
slot, | ||
version: this._version, | ||
orderId: makerFill.orderId, | ||
clientId: makerFill.clientId, | ||
side: makerFill.side, | ||
price: makerFill.price, | ||
size: makerFill.size, | ||
account: makerFill.account, | ||
accountSlot: makerFill.accountSlot, | ||
feeTier: makerFill.feeTier | ||
}; | ||
l3Diff.push(openMessage); | ||
} | ||
} | ||
const message = this._mapEventToDataMessage(event, timestamp, slot, fillsIds); | ||
@@ -49,4 +88,2 @@ if (message === undefined) { | ||
if (accountsData.asks !== undefined) { | ||
const newAsksSlabItems = [...serum_1.Orderbook.decode(this._options.market, accountsData.asks).slab.items(false)]; | ||
const newAsksOrders = newAsksSlabItems.map(this._mapAskSlabItemToOrder); | ||
if (this._initialized) { | ||
@@ -63,4 +100,2 @@ const currentAsksMap = new Map(this._asksAccountOrders.map(this._toMapConstructorStructure)); | ||
if (accountsData.bids !== undefined) { | ||
const newBidsSlabItems = [...serum_1.Orderbook.decode(this._options.market, accountsData.bids).slab.items(true)]; | ||
const newBidsOrders = newBidsSlabItems.map(this._mapBidSlabItemToOrder); | ||
if (this._initialized) { | ||
@@ -77,3 +112,2 @@ const currentBidsMap = new Map(this._bidsAccountOrders.map(this._toMapConstructorStructure)); | ||
if (this._initialized) { | ||
this._addOpenOrdersForImmediateMakerFills(l3Diff, timestamp, slot); | ||
const diffIsValid = this._validateL3DiffCorrectness(l3Diff); | ||
@@ -310,42 +344,2 @@ if (diffIsValid === false) { | ||
} | ||
_addOpenOrdersForImmediateMakerFills(l3Diff, timestamp, slot) { | ||
const openOrdersToAdd = []; | ||
for (const item of l3Diff) { | ||
// for maker fills check first if there's existing open order for it | ||
// as it may not exist in scenario where order was added to the order book and matched in the same slot | ||
if (item.type === 'fill' && item.maker === true) { | ||
const openOrders = item.side === 'buy' ? this._bidsAccountOrders : this._asksAccountOrders; | ||
const hasMatchingOpenOrder = openOrders.some((o) => o.orderId === item.orderId); | ||
if (hasMatchingOpenOrder === false) { | ||
const openMessage = { | ||
type: 'open', | ||
market: this._options.symbol, | ||
timestamp, | ||
slot, | ||
version: this._version, | ||
orderId: item.orderId, | ||
clientId: item.clientId, | ||
side: item.side, | ||
price: item.price, | ||
size: item.size, | ||
account: item.account, | ||
accountSlot: item.accountSlot, | ||
feeTier: item.feeTier | ||
}; | ||
openOrdersToAdd.push(openMessage); | ||
} | ||
} | ||
} | ||
for (const openOrder of openOrdersToAdd) { | ||
const matchingL3Index = l3Diff.findIndex((i) => i.type === 'fill' && i.maker === true && i.orderId === openOrder.orderId); | ||
// insert open order before first matching l3 index if it exists | ||
if (matchingL3Index !== -1) { | ||
l3Diff.splice(matchingL3Index, 0, openOrder); | ||
} | ||
else { | ||
// if there's not matching fill/done l3 add open order at the end | ||
l3Diff.push(openOrder); | ||
} | ||
} | ||
} | ||
reset() { | ||
@@ -405,2 +399,17 @@ if (this._initialized === false) { | ||
if (item.type === 'done') { | ||
if (item.reason === 'canceled') { | ||
const matchingOrder = ordersMap.get(item.orderId); | ||
if (matchingOrder !== undefined) { | ||
if (matchingOrder.size !== item.sizeRemaining) { | ||
logger_1.logger.log('warn', 'Done(cancel) message with incorrect sizeRemaining', { | ||
market: this._options.symbol, | ||
doneMessage: item, | ||
matchingOrder, | ||
slot: item.slot, | ||
l3Diff | ||
}); | ||
return false; | ||
} | ||
} | ||
} | ||
ordersMap.delete(item.orderId); | ||
@@ -575,10 +584,3 @@ } | ||
accountSlot: openOrdersSlot, | ||
sizeRemaining: undefined, | ||
price: undefined | ||
// sizeRemaining: | ||
// reason === 'canceled' ? this._getDoneSize(event).toFixed(this._options.sizeDecimalPlaces) : undefined, | ||
// price: | ||
// reason === 'canceled' | ||
// ? this._options.market.priceLotsToNumber(event.orderId.ushrn(64)).toFixed(this._options.priceDecimalPlaces) | ||
// : undefined | ||
sizeRemaining: reason === 'canceled' ? this._getDoneSize(event).toFixed(this._options.sizeDecimalPlaces) : undefined | ||
}; | ||
@@ -585,0 +587,0 @@ return doneMessage; |
@@ -74,3 +74,2 @@ import { Op, Channel, MessageType } from './consts'; | ||
readonly reason: 'filled' | 'canceled'; | ||
readonly price: string | undefined; | ||
readonly sizeRemaining: string | undefined; | ||
@@ -77,0 +76,0 @@ readonly side: 'buy' | 'sell'; |
{ | ||
"name": "serum-vial", | ||
"version": "1.3.1", | ||
"version": "1.3.2", | ||
"engines": { | ||
@@ -5,0 +5,0 @@ "node": ">=15" |
@@ -795,3 +795,3 @@ <img src="https://raw.githubusercontent.com/tardis-dev/serum-vial/master/logo.svg"> | ||
- `price` and `sizeRemaining` fields are available only since v1.3.0 and only for canceled orders (`reason="canceled"`) | ||
- `sizeRemaining` field is available only since v1.3.2 and only for canceled orders (`reason="canceled"`) | ||
@@ -809,3 +809,2 @@ ```ts | ||
"reason" : "canceled" | "filled", | ||
"price": string | undefined | ||
"sizeRemaining": string | undefined | ||
@@ -832,4 +831,3 @@ "account": string, | ||
"accountSlot": 0, | ||
"sizeRemaining": "508.5", | ||
"price": "6.364" | ||
"sizeRemaining": "508.5" | ||
} | ||
@@ -836,0 +834,0 @@ ``` |
@@ -79,6 +79,60 @@ import { EVENT_QUEUE_LAYOUT, Market, Orderbook, getLayoutVersion } from '@project-serum/serum' | ||
const newAsksSlabItems = | ||
accountsData.asks !== undefined | ||
? [...Orderbook.decode(this._options.market, accountsData.asks).slab.items(false)] | ||
: this._asksAccountSlabItems | ||
const newAsksOrders = | ||
accountsData.asks !== undefined && newAsksSlabItems !== undefined | ||
? newAsksSlabItems.map(this._mapAskSlabItemToOrder) | ||
: this._asksAccountOrders | ||
const newBidsSlabItems = | ||
accountsData.bids !== undefined | ||
? [...Orderbook.decode(this._options.market, accountsData.bids).slab.items(true)] | ||
: this._bidsAccountSlabItems | ||
const newBidsOrders = | ||
accountsData.bids !== undefined && newBidsSlabItems !== undefined | ||
? newBidsSlabItems.map(this._mapBidSlabItemToOrder) | ||
: this._bidsAccountOrders | ||
if (this._initialized && accountsData.eventQueue !== undefined) { | ||
let fillsIds: Map<string, Fill> = new Map() | ||
for (const event of this._getNewlyAddedEvents(accountsData.eventQueue)) { | ||
// for maker fills check first if there's existing open order for it | ||
// as it may not exist in scenario where order was added to the order book and matched in the same slot | ||
if (event.eventFlags.fill === true && event.eventFlags.maker === true) { | ||
const makerFill: Fill = this._mapEventToDataMessage(event, timestamp, slot, fillsIds)! as Fill | ||
const currentOpenOrders = makerFill.side === 'buy' ? newBidsOrders! : newAsksOrders! | ||
const lastOpenOrders = makerFill.side === 'buy' ? this._bidsAccountOrders! : this._asksAccountOrders! | ||
const hasMatchingOpenOrder = | ||
currentOpenOrders.some((o) => o.orderId === makerFill.orderId) || | ||
lastOpenOrders.some((o) => o.orderId === makerFill.orderId) | ||
if (hasMatchingOpenOrder === false) { | ||
const openMessage: Open = { | ||
type: 'open', | ||
market: this._options.symbol, | ||
timestamp, | ||
slot, | ||
version: this._version, | ||
orderId: makerFill.orderId, | ||
clientId: makerFill.clientId, | ||
side: makerFill.side, | ||
price: makerFill.price, | ||
size: makerFill.size, | ||
account: makerFill.account, | ||
accountSlot: makerFill.accountSlot, | ||
feeTier: makerFill.feeTier | ||
} | ||
l3Diff.push(openMessage) | ||
} | ||
} | ||
const message = this._mapEventToDataMessage(event, timestamp, slot, fillsIds) | ||
if (message === undefined) { | ||
@@ -96,9 +150,6 @@ continue | ||
if (accountsData.asks !== undefined) { | ||
const newAsksSlabItems = [...Orderbook.decode(this._options.market, accountsData.asks).slab.items(false)] | ||
const newAsksOrders = newAsksSlabItems.map(this._mapAskSlabItemToOrder) | ||
if (this._initialized) { | ||
const currentAsksMap = new Map(this._asksAccountOrders!.map(this._toMapConstructorStructure)) | ||
for (const ask of newAsksOrders) { | ||
for (const ask of newAsksOrders!) { | ||
const matchingExistingOrder = currentAsksMap.get(ask.orderId) | ||
@@ -114,9 +165,6 @@ this._addChangedOrderItemsToL3Diff(matchingExistingOrder, ask, timestamp, slot, l3Diff) | ||
if (accountsData.bids !== undefined) { | ||
const newBidsSlabItems = [...Orderbook.decode(this._options.market, accountsData.bids).slab.items(true)] | ||
const newBidsOrders = newBidsSlabItems.map(this._mapBidSlabItemToOrder) | ||
if (this._initialized) { | ||
const currentBidsMap = new Map(this._bidsAccountOrders!.map(this._toMapConstructorStructure)) | ||
for (const bid of newBidsOrders) { | ||
for (const bid of newBidsOrders!) { | ||
const matchingExistingOrder = currentBidsMap.get(bid.orderId) | ||
@@ -132,4 +180,2 @@ this._addChangedOrderItemsToL3Diff(matchingExistingOrder, bid, timestamp, slot, l3Diff) | ||
if (this._initialized) { | ||
this._addOpenOrdersForImmediateMakerFills(l3Diff, timestamp, slot) | ||
const diffIsValid = this._validateL3DiffCorrectness(l3Diff) | ||
@@ -432,51 +478,2 @@ | ||
private _addOpenOrdersForImmediateMakerFills( | ||
l3Diff: (Open | Fill | Done | Change)[], | ||
timestamp: string, | ||
slot: number | ||
) { | ||
const openOrdersToAdd: Open[] = [] | ||
for (const item of l3Diff) { | ||
// for maker fills check first if there's existing open order for it | ||
// as it may not exist in scenario where order was added to the order book and matched in the same slot | ||
if (item.type === 'fill' && item.maker === true) { | ||
const openOrders = item.side === 'buy' ? this._bidsAccountOrders! : this._asksAccountOrders! | ||
const hasMatchingOpenOrder = openOrders.some((o) => o.orderId === item.orderId) | ||
if (hasMatchingOpenOrder === false) { | ||
const openMessage: Open = { | ||
type: 'open', | ||
market: this._options.symbol, | ||
timestamp, | ||
slot, | ||
version: this._version, | ||
orderId: item.orderId, | ||
clientId: item.clientId, | ||
side: item.side, | ||
price: item.price, | ||
size: item.size, | ||
account: item.account, | ||
accountSlot: item.accountSlot, | ||
feeTier: item.feeTier | ||
} | ||
openOrdersToAdd.push(openMessage) | ||
} | ||
} | ||
} | ||
for (const openOrder of openOrdersToAdd) { | ||
const matchingL3Index = l3Diff.findIndex( | ||
(i) => i.type === 'fill' && i.maker === true && i.orderId === openOrder.orderId | ||
) | ||
// insert open order before first matching l3 index if it exists | ||
if (matchingL3Index !== -1) { | ||
l3Diff.splice(matchingL3Index, 0, openOrder) | ||
} else { | ||
// if there's not matching fill/done l3 add open order at the end | ||
l3Diff.push(openOrder) | ||
} | ||
} | ||
} | ||
public reset() { | ||
@@ -546,2 +543,19 @@ if (this._initialized === false) { | ||
if (item.type === 'done') { | ||
if (item.reason === 'canceled') { | ||
const matchingOrder = ordersMap.get(item.orderId) | ||
if (matchingOrder !== undefined) { | ||
if (matchingOrder.size !== item.sizeRemaining) { | ||
logger.log('warn', 'Done(cancel) message with incorrect sizeRemaining', { | ||
market: this._options.symbol, | ||
doneMessage: item, | ||
matchingOrder, | ||
slot: item.slot, | ||
l3Diff | ||
}) | ||
return false | ||
} | ||
} | ||
} | ||
ordersMap.delete(item.orderId) | ||
@@ -754,10 +768,4 @@ } | ||
accountSlot: openOrdersSlot, | ||
sizeRemaining: undefined, | ||
price: undefined | ||
// sizeRemaining: | ||
// reason === 'canceled' ? this._getDoneSize(event).toFixed(this._options.sizeDecimalPlaces) : undefined, | ||
// price: | ||
// reason === 'canceled' | ||
// ? this._options.market.priceLotsToNumber(event.orderId.ushrn(64)).toFixed(this._options.priceDecimalPlaces) | ||
// : undefined | ||
sizeRemaining: | ||
reason === 'canceled' ? this._getDoneSize(event).toFixed(this._options.sizeDecimalPlaces) : undefined | ||
} | ||
@@ -764,0 +772,0 @@ return doneMessage |
@@ -89,3 +89,2 @@ import { Op, Channel, MessageType } from './consts' | ||
readonly reason: 'filled' | 'canceled' | ||
readonly price: string | undefined | ||
readonly sizeRemaining: string | undefined | ||
@@ -92,0 +91,0 @@ readonly side: 'buy' | 'sell' |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
303037
4486
905