From 7092213826897a5a9522135870ad6dd337df14d6 Mon Sep 17 00:00:00 2001 From: sairajzero Date: Wed, 27 Apr 2022 00:29:51 +0530 Subject: [PATCH] Bug fixes - Fixed: Trade balance not updated correctly - Fixed: sell-chips were not checked correctly on placing sell orders - Fixed: sell-chips not added when distributed - Fixed: sell-chips (FLO) not added when deposited by launch-seller - Fixed various bugs - initialPrice will be added to priceHistory table (initially) --- args/schema.sql | 8 ++++---- args/truncateAll.sql | 6 ++++-- src/coupling.js | 32 +++++++++++++++++------------- src/market.js | 47 +++++++++++++++++++++++--------------------- src/price.js | 8 +++++--- 5 files changed, 56 insertions(+), 45 deletions(-) diff --git a/args/schema.sql b/args/schema.sql index a07a8a3..8d677c9 100644 --- a/args/schema.sql +++ b/args/schema.sql @@ -48,7 +48,7 @@ CREATE TABLE UserBalance ( quantity DECIMAL(16, 8) NOT NULL DEFAULT 0, PRIMARY KEY(floID, token), KEY(id) -) +); CREATE TABLE SellChips ( id INT NOT NULL AUTO_INCREMENT, @@ -77,7 +77,7 @@ CREATE TABLE Distributors( KEY(id), PRIMARY KEY(floID, asset), FOREIGN KEY (asset) REFERENCES AssetList(asset) -) +); /* User Requests */ @@ -213,7 +213,7 @@ CREATE TABLE AuditTrade( /* Backup Feature (Tables & Triggers) */ CREATE TABLE _backup ( - t_name TINYTEXT, + t_name VARCHAR(64), id INT, mode BOOLEAN DEFAULT TRUE, timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP, @@ -222,7 +222,7 @@ CREATE TABLE _backup ( CREATE table _backupCache( id INT AUTO_INCREMENT, - t_name TINYTEXT, + t_name VARCHAR(64), data_cache LONGTEXT, status BOOLEAN, PRIMARY KEY(id) diff --git a/args/truncateAll.sql b/args/truncateAll.sql index a0a546a..b565e79 100644 --- a/args/truncateAll.sql +++ b/args/truncateAll.sql @@ -1,8 +1,9 @@ /* Node data */ TRUNCATE _backup; +TRUNCATE _backupCache; TRUNCATE AuditTrade; TRUNCATE BuyOrder; -TRUNCATE Cash; +TRUNCATE Distributors; TRUNCATE InputFLO; TRUNCATE InputToken; TRUNCATE OutputFLO; @@ -10,11 +11,12 @@ TRUNCATE OutputToken; TRUNCATE PriceHistory; TRUNCATE RequestLog; TRUNCATE SellOrder; +TRUNCATE UserBalance; TRUNCATE UserSession; TRUNCATE UserTag; TRUNCATE TransferTransactions; TRUNCATE TradeTransactions; -TRUNCATE Vault; +TRUNCATE SellChips; /* Blockchain data */ TRUNCATE LastTx; diff --git a/src/coupling.js b/src/coupling.js index 4483c91..febdf98 100644 --- a/src/coupling.js +++ b/src/coupling.js @@ -74,9 +74,7 @@ function processCoupling(asset, cur_rate) { //console.debug("Sell:", best.sell); //console.debug("Buy:", best.buy); let quantity = Math.min(best.buy.quantity, best.sell.quantity, best.sell.chip_quantity); - let txQueries = []; - processOrders(best.sell, best.buy, txQueries, quantity); - updateBalance(best.sell, best.buy, txQueries, asset, cur_rate, quantity); + let txQueries = processOrders(best.sell, best.buy, asset, cur_rate, quantity); //begin audit beginAudit(best.sell.floID, best.buy.floID, asset, cur_rate, quantity).then(audit => { //process txn query in SQL @@ -92,7 +90,7 @@ function processCoupling(asset, cur_rate) { let noBuy, noSell; if (error.buy === undefined) noBuy = false; - else if (error.buy !== false) { + else if (error.buy !== null) { console.error(error.buy); noBuy = null; } else { @@ -101,7 +99,7 @@ function processCoupling(asset, cur_rate) { } if (error.sell === undefined) noSell = false; - else if (error.sell !== false) { + else if (error.sell !== null) { console.error(error.sell); noSell = null; } else { @@ -112,35 +110,39 @@ function processCoupling(asset, cur_rate) { }); } -function processOrders(seller_best, buyer_best, txQueries, quantity) { +function processOrders(seller_best, buyer_best, asset, cur_rate, quantity) { + let txQueries = []; if (quantity > buyer_best.quantity || quantity > seller_best.quantity) throw Error("Tx quantity cannot be more than order quantity"); + //Process Buy Order if (quantity == buyer_best.quantity) txQueries.push(["DELETE FROM BuyOrder WHERE id=?", [buyer_best.id]]); else txQueries.push(["UPDATE BuyOrder SET quantity=quantity-? WHERE id=?", [quantity, buyer_best.id]]); + //Process Sell Order if (quantity == seller_best.quantity) txQueries.push(["DELETE FROM SellOrder WHERE id=?", [seller_best.id]]); else txQueries.push(["UPDATE SellOrder SET quantity=quantity-? WHERE id=?", [quantity, seller_best.id]]); + //Process Sell Chip if (quantity == seller_best.chip_quantity) txQueries.push(["DELETE FROM SellChips WHERE id=?", [seller_best.chip_id]]); else txQueries.push(["UPDATE SellChips SET quantity=quantity-? WHERE id=?", [quantity, seller_best.chip_id]]); -} -function updateBalance(seller_best, buyer_best, txQueries, asset, cur_price, quantity) { //Update cash/asset balance for seller and buyer - let totalAmount = cur_price * quantity; + let totalAmount = cur_rate * quantity; txQueries.push(updateBalance.add(seller_best.floID, floGlobals.currency, totalAmount)); txQueries.push(updateBalance.consume(buyer_best.floID, floGlobals.currency, totalAmount)); - txQueries.push(updateBalance.add(seller_best.floID, asset, totalAmount)); - txQueries.push(updateBalance.consume(buyer_best.floID, asset, totalAmount)); + txQueries.push(updateBalance.consume(seller_best.floID, asset, quantity)); + txQueries.push(updateBalance.add(buyer_best.floID, asset, quantity)); + //Add SellChips to Buyer - txQueries.push(["INSERT INTO SellChips(floID, asset, base, quantity) VALUES (?, ?, ?, ?)", [buyer_best.floID, asset, cur_price, quantity]]) + txQueries.push(["INSERT INTO SellChips(floID, asset, base, quantity) VALUES (?, ?, ?, ?)", [buyer_best.floID, asset, cur_rate, quantity]]) + //Record transaction let time = Date.now(); let hash = TRADE_HASH_PREFIX + Crypto.SHA256(JSON.stringify({ @@ -148,13 +150,15 @@ function updateBalance(seller_best, buyer_best, txQueries, asset, cur_price, qua buyer: buyer_best.floID, asset: asset, quantity: quantity, - unitValue: cur_price, + unitValue: cur_rate, tx_time: time, })); txQueries.push([ "INSERT INTO TradeTransactions (seller, buyer, asset, quantity, unitValue, tx_time, txid) VALUES (?, ?, ?, ?, ?, ?, ?)", - [seller_best.floID, buyer_best.floID, asset, quantity, cur_price, global.convertDateToString(time), hash] + [seller_best.floID, buyer_best.floID, asset, quantity, cur_rate, global.convertDateToString(time), hash] ]); + + return txQueries; } function beginAudit(sellerID, buyerID, asset, unit_price, quantity) { diff --git a/src/market.js b/src/market.js index d9a5476..b59b1bb 100644 --- a/src/market.js +++ b/src/market.js @@ -134,7 +134,7 @@ function addSellOrder(floID, asset, quantity, min_price) { else if (!assetList.includes(asset)) return reject(INVALID(`Invalid asset (${asset})`)); getAssetBalance.check(floID, asset, quantity).then(_ => { - checkSellRequirement(floID, asset).then(_ => { + checkSellRequirement(floID, asset, quantity).then(_ => { DB.query("INSERT INTO SellOrder(floID, asset, quantity, minPrice) VALUES (?, ?, ?, ?)", [floID, asset, quantity, min_price]) .then(result => resolve('Sell Order placed successfully')) .catch(error => reject(error)); @@ -148,9 +148,9 @@ const checkSellRequirement = (floID, asset, quantity) => new Promise((resolve, r DB.query("SELECT IFNULL(SUM(quantity), 0) AS total_chips FROM SellChips WHERE floID=? AND asset=?", [floID, asset]), DB.query("SELECT IFNULL(SUM(quantity), 0) AS locked FROM SellOrder WHERE floID=? AND asset=?", [floID, asset]) ]).then(result => { - let total = result[0].total_chips, - locked = result[1].locked; - if (total > locked + quantity) + let total = result[0][0].total_chips, + locked = result[1][0].locked; + if (total >= locked + quantity) resolve(true); else reject(INVALID(`Insufficient sell-chips for ${asset}`)); @@ -283,7 +283,7 @@ function transferToken(sender, receivers, token) { checkDistributor(sender, token).then(result => { if (result) for (let floID in receivers) - txQueries.push(["INSERT INTO Vault (floID, asset, quantity) VALUES (?, ?, ?)", [floID, token, receivers[floID]]]); + txQueries.push(["INSERT INTO SellChips (floID, asset, quantity) VALUES (?, ?, ?)", [floID, token, receivers[floID]]]); let time = Date.now(); let hash = TRANSFER_HASH_PREFIX + Crypto.SHA256(JSON.stringify({ sender: sender, @@ -329,13 +329,14 @@ function confirmDepositFLO() { DB.query("SELECT id, floID, txid FROM InputFLO WHERE status=?", ["PENDING"]).then(results => { results.forEach(req => { confirmDepositFLO.checkTx(req.floID, req.txid).then(amount => { - let txQueries = []; - txQueries.push(updateBalance.add(req.floID, "FLO", amount)); - txQueries.push(["UPDATE InputFLO SET status=?, amount=? WHERE id=?", ["SUCCESS", amount, req.id]]); - - DB.transaction(txQueries) - .then(result => console.debug("FLO deposited:", req.floID, amount)) - .catch(error => console.error(error)) + confirmDepositFLO.addSellChipsIfLaunchSeller(req.floID, amount).then(txQueries => { + txQueries.push(updateBalance.add(req.floID, "FLO", amount)); + txQueries.push(["UPDATE InputFLO SET status=?, amount=? WHERE id=?", ["SUCCESS", amount, req.id]]); + console.debug(txQueries) + DB.transaction(txQueries) + .then(result => console.debug("FLO deposited:", req.floID, amount)) + .catch(error => console.error(error)) + }).catch(error => console.error(error)) }).catch(error => { console.error(error); if (error[0]) @@ -372,20 +373,22 @@ confirmDepositFLO.checkTx = function(sender, txid) { confirmDepositFLO.addSellChipsIfLaunchSeller = function(floID, quantity) { return new Promise((resolve, reject) => { - checkTag(req.floID, LAUNCH_SELLER_TAG).then(result => { + checkTag(floID, LAUNCH_SELLER_TAG).then(result => { if (result) //floID is launch-seller Promise.all([ - DB.query("SELECT SUM(quantity) FROM TradeTransactions WHERE seller=? AND asset=?", [floID, 'FLO']), - DB.query("SELECT SUM(quantity) FROM TradeTransactions WHERE buyer=? AND asset=?", [floID, 'FLO']), - DB.query("SELECT SUM(quantity) FROM SellChips WHERE floID=? AND asset=?", [floID, 'FLO']), + DB.query("SELECT IFNULL(SUM(quantity), 0) AS sold FROM TradeTransactions WHERE seller=? AND asset=?", [floID, 'FLO']), + DB.query("SELECT IFNULL(SUM(quantity), 0) AS brought FROM TradeTransactions WHERE buyer=? AND asset=?", [floID, 'FLO']), + DB.query("SELECT IFNULL(SUM(quantity), 0) AS chips FROM SellChips WHERE floID=? AND asset=?", [floID, 'FLO']), ]).then(result => { - let sold = result[0], - brought = result[1], - chips = result[2]; + let sold = result[0][0].sold, + brought = result[1][0].brought, + chips = result[2][0].chips; let remLaunchChips = MAXIMUM_LAUNCH_SELL_CHIPS - (sold + chips) + brought; quantity = Math.min(quantity, remLaunchChips); if (quantity > 0) - resolve(["INSERT INTO SellChips(floID, asset, quantity) VALUES (?, ?, ?)", [floID, 'FLO', quantity]]); + resolve([ + ["INSERT INTO SellChips(floID, asset, quantity) VALUES (?, ?, ?)", [floID, 'FLO', quantity]] + ]); else resolve([]); }).catch(error => reject(error)) @@ -613,7 +616,7 @@ function removeTag(floID, tag) { } function checkTag(floID, tag) { - new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { DB.query("SELECT id FROM UserTag WHERE floID=? AND tag=?", [floID, tag]) .then(result => resolve(result.length ? true : false)) .catch(error => reject(error)) @@ -644,7 +647,7 @@ function removeDistributor(floID, asset) { } function checkDistributor(floID, asset) { - new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { DB.query("SELECT id FROM Distributors WHERE floID=? AND asset=?", [floID, asset]) .then(result => resolve(result.length ? true : false)) .catch(error => reject(error)) diff --git a/src/price.js b/src/price.js index 3c6e91a..eb9ef4a 100644 --- a/src/price.js +++ b/src/price.js @@ -85,9 +85,11 @@ function loadRate(asset) { if (result.length) resolve(currentRate[asset] = result[0].rate); else - DB.query("SELECT initialPrice FROM AssetList WHERE asset=?", [asset]) - .then(result => resolve(currentRate[asset] = result[0].initialPrice)) - .catch(error => reject(error)) + DB.query("SELECT initialPrice FROM AssetList WHERE asset=?", [asset]).then(result => { + currentRate[asset] = result[0].initialPrice; + storeHistory(asset, currentRate[asset]); + resolve(currentRate[asset]); + }).catch(error => reject(error)) }).catch(error => reject(error)); }) }