I have a problem. In my NodeJS API. I use the Node-Binance-API package to use the API from Binance. In this API I can subscribe to account changes using a websocket. The function to subscribe to my account looks like the following:
exports.subscribeAccount = async (agentId) => {
binance.websockets.userData((response) => {
if (eventType === "outboundAccountPosition") {
console.log("outboundAccountPosition")
}
else if (eventType === "executionReport") {
const order = Order.executionReportToOrder(response, agentId);
order.save();
}
})
}
The order.save() method looks like this:
save() {
let sql = `
INSERT INTO \`Order\` (
orderId, agentId, symbol, clientOrderId, side, orderType, timeInForce, orderQuantity, orderPrice, stopPrice, icebergQuantity, originalClientOrderId, currentExecutionType, currentOrderStatus, orderRejectReason, lastExecutedQuantity, cumulativeFilledQuantity, lastExecutedPrice, commissionAmount, commissionAsset, transactionTime, tradeId, isOrderOnBook, isTradeMakerSide, creationTime, cumulativeQuoteAssetTransactedQuantity, lastQuoteAssetTransactedQuantity, quoteOrderQuantity
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE currentExecutionType=VALUES(currentExecutionType), currentOrderStatus=VALUES(currentOrderStatus), orderRejectReason=VALUES(orderRejectReason), lastExecutedQuantity=VALUES(lastExecutedQuantity), cumulativeFilledQuantity=VALUES(cumulativeFilledQuantity), lastExecutedPrice=VALUES(lastExecutedPrice), commissionAmount=VALUES(commissionAmount), commissionAsset=VALUES(commissionAsset), transactionTime=VALUES(transactionTime), tradeId=VALUES(tradeId), isOrderOnBook=VALUES(isOrderOnBook), isTradeMakerSide=VALUES(isTradeMakerSide), creationTime=VALUES(creationTime), cumulativeQuoteAssetTransactedQuantity=VALUES(cumulativeQuoteAssetTransactedQuantity), lastQuoteAssetTransactedQuantity=VALUES(lastQuoteAssetTransactedQuantity), quoteOrderQuantity=VALUES(quoteOrderQuantity);`;
return db.execute(sql, [
this.orderId,
this.agentId,
this.symbol,
this.clientOrderId,
this.side,
this.orderType,
this.timeInForce,
this.orderQuantity,
this.orderPrice,
this.stopPrice,
this.icebergQuantity,
this.originalClientOrderId,
this.currentExecutionType,
this.currentOrderStatus,
this.orderRejectReason,
this.lastExecutedQuantity,
this.cumulativeFilledQuantity,
this.lastExecutedPrice,
this.commissionAmount,
this.commissionAsset,
this.transactionTime,
this.tradeId,
this.isOrderOnBook,
this.isTradeMakerSide,
this.creationTime,
this. cumulativeQuoteAssetTransactedQuantity,
this.lastQuoteAssetTransactedQuantity,
this.quoteOrderQuantity
]);
}
But now I have the following problem. The websocket works great and it pushes updates about orders. When I enter an order that gets executed instantly, this method gets called twice, right after each other. The first call is the NEW order and the second one is the FILLED order. the order.save() function writes the object to the database using the db.execute() function of the mysql2 package, but I can see that sometimes the second query gets executed faster than the first, so the final state of the order in my database is NEW. How can I prevent this from happening? Can I cancel the first query when I see the second one coming in or let them execute after each other?
TABLE
The SHOW CREATE TABLE Order results in:
CREATE TABLE `Order` (
`orderId` bigint(20) NOT NULL,
`agentId` int(11) NOT NULL,
`symbol` varchar(25) NOT NULL,
`clientOrderId` varchar(255) NOT NULL,
`side` enum('BUY','SELL') NOT NULL,
`orderType` enum('MARKET','LIMIT','STOP_LOSS','STOP_LOSS_LIMIT','TAKE_PROFIT','TAKE_PROFIT_LIMIT') NOT NULL,
`timeInForce` enum('GTC','IOC','FOK') NOT NULL,
`orderQuantity` decimal(16,8) NOT NULL,
`orderPrice` decimal(16,8) NOT NULL,
`stopPrice` decimal(16,8) NOT NULL,
`icebergQuantity` decimal(16,8) NOT NULL,
`originalClientOrderId` varchar(255) NOT NULL,
`currentExecutionType` enum('NEW','CANCELED','REPLACED','REJECTED','TRADE','EXPIRED') NOT NULL,
`currentOrderStatus` enum('NEW','FILLED','CANCELED','EXPIRED','PENDING_CANCEL','PARTIALLY_FILLED') NOT NULL,
`orderRejectReason` varchar(255) NOT NULL,
`lastExecutedQuantity` decimal(16,8) NOT NULL,
`cumulativeFilledQuantity` decimal(16,8) NOT NULL,
`lastExecutedPrice` decimal(16,8) NOT NULL,
`commissionAmount` decimal(16,8) NOT NULL,
`commissionAsset` varchar(15) DEFAULT NULL,
`transactionTime` bigint(20) NOT NULL,
`tradeId` bigint(20) NOT NULL,
`isOrderOnBook` tinyint(1) NOT NULL,
`isTradeMakerSide` tinyint(1) NOT NULL,
`creationTime` bigint(20) NOT NULL,
`cumulativeQuoteAssetTransactedQuantity` decimal(16,8) NOT NULL,
`lastQuoteAssetTransactedQuantity` decimal(16,8) NOT NULL,
`quoteOrderQuantity` decimal(16,8) NOT NULL,
PRIMARY KEY (`orderId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
transaction. i hope this answer can guide you to the right steps. you might want to ensure theFILLEDorder can made if and only if theNEWorder exists.SHOW CREATE TABLE. Are both queries the same IODKU? (I think I know the answer, but I need to see these to be sure.)