From 946087481aac8ff551e8e2b6d87302ed400f4f2c Mon Sep 17 00:00:00 2001 From: sairajzero Date: Mon, 6 Dec 2021 20:55:35 +0530 Subject: [PATCH] Move transaction process to coupling.js --- src/coupling.js | 123 ++++++++++++++++++++++++++++++++++++++++++++++++ src/market.js | 122 +++-------------------------------------------- src/request.js | 2 +- 3 files changed, 131 insertions(+), 116 deletions(-) create mode 100644 src/coupling.js diff --git a/src/coupling.js b/src/coupling.js new file mode 100644 index 0000000..6fc9f4e --- /dev/null +++ b/src/coupling.js @@ -0,0 +1,123 @@ +'use strict'; + +const group = require("./group"); +const price = require("./price"); + +var DB; //container for database + +function initiate() { + price.getRates().then(cur_rate => { + group.getBestPairs(cur_rate) + .then(bestPairQueue => processCoupling(bestPairQueue)) + .catch(error => console.error("initiateCoupling", error)) + }).catch(error => console.error(error)); +} + +function processCoupling(bestPairQueue) { + bestPairQueue.get().then(pair_result => { + let buyer_best = pair_result.buyOrder, + seller_best = pair_result.sellOrder; + console.debug("Sell:", seller_best); + console.debug("Buy:", buyer_best); + spendFLO(buyer_best, seller_best, pair_result.null_base).then(spend_result => { + let tx_quantity = spend_result.quantity, + txQueries = spend_result.txQueries, + clear_sell = spend_result.incomplete && !spend_result.flag_baseNull; //clear_sell can be true only if an order is placed without enough FLO + processOrders(seller_best, buyer_best, txQueries, tx_quantity, clear_sell); + updateBalance(seller_best, buyer_best, txQueries, bestPairQueue.cur_rate, tx_quantity); + //process txn query in SQL + DB.transaction(txQueries).then(_ => { + bestPairQueue.next(tx_quantity, spend_result.incomplete, spend_result.flag_baseNull); + console.log(`Transaction was successful! BuyOrder:${buyer_best.id}| SellOrder:${seller_best.id}`); + price.updateLastTime(); + //Since a tx was successful, match again + processCoupling(bestPairQueue); + }).catch(error => console.error(error)); + }).catch(error => console.error(error)); + }).catch(error => { + let noBuy, noSell; + if (error.buy === undefined) + noBuy = false; + else if (error.buy !== false) { + console.error(error.buy); + noBuy = null; + } else { + console.log("No valid buyOrders."); + noBuy = true; + } + if (error.sell === undefined) + noSell = false; + else if (error.sell !== false) { + console.error(error.sell); + noSell = null; + } else { + console.log("No valid sellOrders."); + noSell = true; + } + price.noOrder(noBuy, noSell); + }); +} + +function spendFLO(buyOrder, sellOrder, null_base) { + return new Promise((resolve, reject) => { + DB.query("SELECT id, quantity, base FROM Vault WHERE floID=? ORDER BY base", [sellOrder.floID]).then(result => { + let rem = Math.min(buyOrder.quantity, sellOrder.quantity), + txQueries = [], + flag_baseNull = false; + for (let i = 0; i < result.length && rem > 0; i++) + if (result[i].base || null_base) { + if (rem < result[i].quantity) { + txQueries.push(["UPDATE Vault SET quantity=quantity-? WHERE id=?", [rem, result[i].id]]); + rem = 0; + } else { + txQueries.push(["DELETE FROM Vault WHERE id=?", [result[i].id]]); + rem -= result[i].quantity; + } + } else + flag_baseNull = true; + resolve({ + quantity: Math.min(buyOrder.quantity, sellOrder.quantity) - rem, + txQueries, + incomplete: rem > 0, + flag_baseNull + }); + }).catch(error => reject(error)); + }) +} + +function processOrders(seller_best, buyer_best, txQueries, quantity, clear_sell) { + 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 || clear_sell) + txQueries.push(["DELETE FROM SellOrder WHERE id=?", [seller_best.id]]); + else + txQueries.push(["UPDATE SellOrder SET quantity=quantity-? WHERE id=?", [quantity, seller_best.id]]); +} + +function updateBalance(seller_best, buyer_best, txQueries, cur_price, quantity) { + //Update rupee balance for seller and buyer + let totalAmount = cur_price * quantity; + txQueries.push(["UPDATE Cash SET rupeeBalance=rupeeBalance+? WHERE floID=?", [totalAmount, seller_best.floID]]); + txQueries.push(["UPDATE Cash SET rupeeBalance=rupeeBalance-? WHERE floID=?", [totalAmount, buyer_best.floID]]); + //Add coins to Buyer + txQueries.push(["INSERT INTO Vault(floID, base, quantity) VALUES (?, ?, ?)", [buyer_best.floID, cur_price, quantity]]) + //Record transaction + txQueries.push(["INSERT INTO Transactions (seller, buyer, quantity, unitValue) VALUES (?, ?, ?, ?)", [seller_best.floID, buyer_best.floID, quantity, cur_price]]); +} + +module.exports = { + initiate, + group, + price, + set DB(db) { + DB = db; + group.DB = db; + price.DB = db; + } +} \ No newline at end of file diff --git a/src/market.js b/src/market.js index a167449..3fe915d 100644 --- a/src/market.js +++ b/src/market.js @@ -1,7 +1,6 @@ 'use strict'; -const group = require("./group"); -const price = require("./price"); +const coupling = require('./coupling'); const MINIMUM_BUY_REQUIREMENT = 0.1; var DB; //container for database @@ -56,7 +55,7 @@ const tokenAPI = { } function returnRates() { - return price.currentRate; + return coupling.price.currentRate; } function addSellOrder(floID, quantity, min_price) { @@ -152,112 +151,6 @@ function cancelOrder(type, id, floID) { }); } -function initiateCoupling() { - price.getRates().then(cur_rate => { - group.getBestPairs(cur_rate) - .then(bestPairQueue => processCoupling(bestPairQueue)) - .catch(error => console.error("initiateCoupling", error)) - }).catch(error => console.error(error)); -} - -function processCoupling(bestPairQueue) { - bestPairQueue.get().then(pair_result => { - let buyer_best = pair_result.buyOrder, - seller_best = pair_result.sellOrder; - console.debug("Sell:", seller_best); - console.debug("Buy:", buyer_best); - spendFLO(buyer_best, seller_best, pair_result.null_base).then(spend_result => { - let tx_quantity = spend_result.quantity, - txQueries = spend_result.txQueries, - clear_sell = spend_result.incomplete && !spend_result.flag_baseNull; //clear_sell can be true only if an order is placed without enough FLO - processOrders(seller_best, buyer_best, txQueries, tx_quantity, clear_sell); - updateBalance(seller_best, buyer_best, txQueries, bestPairQueue.cur_rate, tx_quantity); - //process txn query in SQL - DB.transaction(txQueries).then(_ => { - bestPairQueue.next(tx_quantity, spend_result.incomplete, spend_result.flag_baseNull); - console.log(`Transaction was successful! BuyOrder:${buyer_best.id}| SellOrder:${seller_best.id}`); - price.updateLastTime(); - //Since a tx was successful, match again - processCoupling(bestPairQueue); - }).catch(error => console.error(error)); - }).catch(error => console.error(error)); - }).catch(error => { - let noBuy, noSell; - if (error.buy === undefined) - noBuy = false; - else if (error.buy !== false) { - console.error(error.buy); - noBuy = null; - } else { - console.log("No valid buyOrders."); - noBuy = true; - } - if (error.sell === undefined) - noSell = false; - else if (error.sell !== false) { - console.error(error.sell); - noSell = null; - } else { - console.log("No valid sellOrders."); - noSell = true; - } - price.noOrder(noBuy, noSell); - }); -} - -function spendFLO(buyOrder, sellOrder, null_base) { - return new Promise((resolve, reject) => { - DB.query("SELECT id, quantity, base FROM Vault WHERE floID=? ORDER BY base", [sellOrder.floID]).then(result => { - let rem = Math.min(buyOrder.quantity, sellOrder.quantity), - txQueries = [], - flag_baseNull = false; - for (let i = 0; i < result.length && rem > 0; i++) - if (result[i].base || null_base) { - if (rem < result[i].quantity) { - txQueries.push(["UPDATE Vault SET quantity=quantity-? WHERE id=?", [rem, result[i].id]]); - rem = 0; - } else { - txQueries.push(["DELETE FROM Vault WHERE id=?", [result[i].id]]); - rem -= result[i].quantity; - } - } else - flag_baseNull = true; - resolve({ - quantity: Math.min(buyOrder.quantity, sellOrder.quantity) - rem, - txQueries, - incomplete: rem > 0, - flag_baseNull - }); - }).catch(error => reject(error)); - }) -} - -function processOrders(seller_best, buyer_best, txQueries, quantity, clear_sell) { - 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 || clear_sell) - txQueries.push(["DELETE FROM SellOrder WHERE id=?", [seller_best.id]]); - else - txQueries.push(["UPDATE SellOrder SET quantity=quantity-? WHERE id=?", [quantity, seller_best.id]]); -} - -function updateBalance(seller_best, buyer_best, txQueries, cur_price, quantity) { - //Update rupee balance for seller and buyer - let totalAmount = cur_price * quantity; - txQueries.push(["UPDATE Cash SET rupeeBalance=rupeeBalance+? WHERE floID=?", [totalAmount, seller_best.floID]]); - txQueries.push(["UPDATE Cash SET rupeeBalance=rupeeBalance-? WHERE floID=?", [totalAmount, buyer_best.floID]]); - //Add coins to Buyer - txQueries.push(["INSERT INTO Vault(floID, base, quantity) VALUES (?, ?, ?)", [buyer_best.floID, cur_price, quantity]]) - //Record transaction - txQueries.push(["INSERT INTO Transactions (seller, buyer, quantity, unitValue) VALUES (?, ?, ?, ?)", [seller_best.floID, buyer_best.floID, quantity, cur_price]]); -} - function getAccountDetails(floID) { return new Promise((resolve, reject) => { let select = []; @@ -598,11 +491,11 @@ function confirmWithdrawalRupee() { } function periodicProcess() { - transactionReCheck(); - initiateCoupling(); + blockchainReCheck(); + coupling.initiate(); } -function transactionReCheck() { +function blockchainReCheck() { confirmDepositFLO(); confirmDepositRupee(); retryWithdrawalFLO(); @@ -622,10 +515,9 @@ module.exports = { depositRupee, withdrawRupee, periodicProcess, - group, + group: coupling.group, set DB(db) { DB = db; - group.DB = db; - price.DB = db; + coupling.DB = db; } }; \ No newline at end of file diff --git a/src/request.js b/src/request.js index 64d35f4..ccf0511 100644 --- a/src/request.js +++ b/src/request.js @@ -68,7 +68,7 @@ function SignUp(req, res) { return res.status(INVALID.e_code).send(req_str.message); let txQueries = []; txQueries.push(["INSERT INTO Users(floID, pubKey) VALUES (?, ?)", [data.floID, data.pubKey]]); - txQueries.push(["INSERT INTO Cash (floID) Values (?)", data.floID]); + txQueries.push(["INSERT INTO Cash (floID) Values (?)", [data.floID]]); DB.transaction(txQueries).then(_ => { storeRequest(data.floID, req_str, data.sign); res.send("Account Created");