diff --git a/args/schema.sql b/args/schema.sql index 296c3b4..261c8e1 100644 --- a/args/schema.sql +++ b/args/schema.sql @@ -1,208 +1,224 @@ -/* Main Tables */ +/* Blockchain Data */ -CREATE TABLE Users ( -floID CHAR(34) NOT NULL, -pubKey CHAR(66) NOT NULL, -created DATETIME DEFAULT CURRENT_TIMESTAMP, -PRIMARY KEY(floID) +CREATE TABLE LastTx( + floID CHAR(34) NOT NULL, + num INT, + PRIMARY KEY(floID) ); -CREATE TABLE Sessions ( -id INT NOT NULL AUTO_INCREMENT, -floID CHAR(34) NOT NULL, -proxyKey CHAR(66) NOT NULL, -session_time DATETIME DEFAULT CURRENT_TIMESTAMP, -KEY (id), -PRIMARY KEY(floID), -FOREIGN KEY (floID) REFERENCES Users(floID) -); - -CREATE TABLE Request_Log( -floID CHAR(34) NOT NULL, -request TEXT NOT NULL, -sign TEXT NOT NULL, -request_time DATETIME DEFAULT CURRENT_TIMESTAMP, -FOREIGN KEY (floID) REFERENCES Users(floID) -); - -CREATE TABLE Cash ( -id INT NOT NULL AUTO_INCREMENT, -floID CHAR(34) NOT NULL UNIQUE, -balance DECIMAL(12, 2) DEFAULT 0.00, -PRIMARY KEY(id), -FOREIGN KEY (floID) REFERENCES Users(floID) -); - -CREATE TABLE Vault ( -id INT NOT NULL AUTO_INCREMENT, -floID CHAR(34) NOT NULL, -locktime DATETIME DEFAULT CURRENT_TIMESTAMP, -asset VARCHAR(64) NOT NULL, -base DECIMAL(10, 2), -quantity FLOAT NOT NULL, -PRIMARY KEY(id), -FOREIGN KEY (floID) REFERENCES Users(floID) -); - -CREATE TABLE SellOrder ( -id INT NOT NULL AUTO_INCREMENT, -floID CHAR(34) NOT NULL, -asset VARCHAR(64) NOT NULL, -quantity FLOAT NOT NULL, -minPrice DECIMAL(10, 2), -time_placed DATETIME DEFAULT CURRENT_TIMESTAMP, -PRIMARY KEY(id), -FOREIGN KEY (floID) REFERENCES Users(floID) -); - -CREATE TABLE BuyOrder ( -id INT NOT NULL AUTO_INCREMENT, -floID CHAR(34) NOT NULL, -asset VARCHAR(64) NOT NULL, -quantity FLOAT NOT NULL, -maxPrice DECIMAL(10, 2) NOT NULL, -time_placed DATETIME DEFAULT CURRENT_TIMESTAMP, -PRIMARY KEY(id), -FOREIGN KEY (floID) REFERENCES Users(floID) -); - -CREATE TABLE Transactions ( -seller CHAR(34) NOT NULL, -buyer CHAR(34) NOT NULL, -asset VARCHAR(64) NOT NULL, -quantity FLOAT NOT NULL, -unitValue DECIMAL(10, 2) NOT NULL, -tx_time DATETIME DEFAULT CURRENT_TIMESTAMP, -FOREIGN KEY (buyer) REFERENCES Users(floID), -FOREIGN KEY (seller) REFERENCES Users(floID) -); - -CREATE TABLE inputFLO ( -id INT NOT NULL AUTO_INCREMENT, -txid VARCHAR(128) NOT NULL, -floID CHAR(34) NOT NULL, -amount FLOAT, -status VARCHAR(50) NOT NULL, -PRIMARY KEY(id), -FOREIGN KEY (floID) REFERENCES Users(floID) -); - -CREATE TABLE outputFLO ( -id INT NOT NULL AUTO_INCREMENT, -txid VARCHAR(128), -floID CHAR(34) NOT NULL, -amount FLOAT NOT NULL, -status VARCHAR(50) NOT NULL, -PRIMARY KEY(id), -FOREIGN KEY (floID) REFERENCES Users(floID) -); - -CREATE TABLE inputToken ( -id INT NOT NULL AUTO_INCREMENT, -txid VARCHAR(128) NOT NULL, -floID CHAR(34) NOT NULL, -token VARCHAR(64), -amount FLOAT, -status VARCHAR(50) NOT NULL, -PRIMARY KEY(id), -FOREIGN KEY (floID) REFERENCES Users(floID) -); - -CREATE TABLE outputToken ( -id INT NOT NULL AUTO_INCREMENT, -txid VARCHAR(128), -floID CHAR(34) NOT NULL, -token VARCHAR(64), -amount FLOAT NOT NULL, -status VARCHAR(50) NOT NULL, -PRIMARY KEY(id), -FOREIGN KEY (floID) REFERENCES Users(floID) -); - -CREATE TABLE lastTx( -floID CHAR(34) NOT NULL, -num INT, -PRIMARY KEY(floID) -); - -CREATE TABLE nodeList( -floID CHAR(34) NOT NULL, -uri TINYTEXT, -PRIMARY KEY(floID) -); - -CREATE TABLE trustedList( -floID CHAR(34) NOT NULL, -PRIMARY KEY(floID), -FOREIGN KEY (floID) REFERENCES Users(floID) +CREATE TABLE NodeList( + floID CHAR(34) NOT NULL, + uri TINYTEXT, + PRIMARY KEY(floID) ); CREATE TABLE TagList ( -tag VARCHAR(50) NOT NULL, -sellPriority INT, -buyPriority INT, -api TINYTEXT, -PRIMARY KEY(tag) + tag VARCHAR(50) NOT NULL, + sellPriority INT, + buyPriority INT, + api TINYTEXT, + PRIMARY KEY(tag) ); -CREATE TABLE Tags ( -id INT NOT NULL AUTO_INCREMENT, -floID CHAR(34) NOT NULL, -tag VARCHAR(50) NOT NULL, -PRIMARY KEY(floID, tag), -KEY (id), -FOREIGN KEY (floID) REFERENCES Users(floID), -FOREIGN KEY (tag) REFERENCES TagList(tag) +CREATE TABLE AssetList ( + asset VARCHAR(64) NOT NULL, + initialPrice FLOAT, + PRIMARY KEY(asset) ); -CREATE TABLE priceHistory ( -rate FLOAT NOT NULL, -rec_time DATETIME DEFAULT CURRENT_TIMESTAMP +CREATE TABLE TrustedList( + floID CHAR(34) NOT NULL, + PRIMARY KEY(floID) ); -CREATE TABLE auditTransaction( -rec_time DATETIME DEFAULT CURRENT_TIMESTAMP, -unit_price FLOAT NOT NULL, -quantity FLOAT NOT NULL, -total_cost FLOAT NOT NULL, -asset VARCHAR(64) NOT NULL, -sellerID CHAR(34) NOT NULL, -seller_old_asset FLOAT NOT NULL, -seller_new_asset FLOAT NOT NULL, -seller_old_cash FLOAT NOT NULL, -seller_new_cash FLOAT NOT NULL, -buyerID CHAR(34) NOT NULL, -buyer_old_asset FLOAT NOT NULL, -buyer_new_asset FLOAT NOT NULL, -buyer_old_cash FLOAT NOT NULL, -buyer_new_cash FLOAT NOT NULL, -FOREIGN KEY (sellerID) REFERENCES Users(floID), -FOREIGN KEY (buyerID) REFERENCES Users(floID) +/* User Data */ + +CREATE TABLE Users ( + floID CHAR(34) NOT NULL, + pubKey CHAR(66) NOT NULL, + created DATETIME DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY(floID) +); + +CREATE TABLE UserSession ( + id INT NOT NULL AUTO_INCREMENT, + floID CHAR(34) NOT NULL, + proxyKey CHAR(66) NOT NULL, + session_time DATETIME DEFAULT CURRENT_TIMESTAMP, + KEY (id), + PRIMARY KEY(floID), + FOREIGN KEY (floID) REFERENCES Users(floID) +); + +CREATE TABLE Cash ( + id INT NOT NULL AUTO_INCREMENT, + floID CHAR(34) NOT NULL UNIQUE, + balance DECIMAL(12, 2) DEFAULT 0.00, + PRIMARY KEY(id), + FOREIGN KEY (floID) REFERENCES Users(floID) +); + +CREATE TABLE Vault ( + id INT NOT NULL AUTO_INCREMENT, + floID CHAR(34) NOT NULL, + locktime DATETIME DEFAULT CURRENT_TIMESTAMP, + asset VARCHAR(64) NOT NULL, + base DECIMAL(10, 2), + quantity FLOAT NOT NULL, + PRIMARY KEY(id), + FOREIGN KEY (floID) REFERENCES Users(floID), + FOREIGN KEY (asset) REFERENCES Users(asset) +); + +CREATE TABLE UserTag ( + id INT NOT NULL AUTO_INCREMENT, + floID CHAR(34) NOT NULL, + tag VARCHAR(50) NOT NULL, + PRIMARY KEY(floID, tag), + KEY (id), + FOREIGN KEY (floID) REFERENCES Users(floID), + FOREIGN KEY (tag) REFERENCES TagList(tag) +); + +/* User Requests */ + +CREATE TABLE Request_Log( + floID CHAR(34) NOT NULL, + request TEXT NOT NULL, + sign TEXT NOT NULL, + request_time DATETIME DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (floID) REFERENCES Users(floID) +); + +CREATE TABLE SellOrder ( + id INT NOT NULL AUTO_INCREMENT, + floID CHAR(34) NOT NULL, + asset VARCHAR(64) NOT NULL, + quantity FLOAT NOT NULL, + minPrice DECIMAL(10, 2), + time_placed DATETIME DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY(id), + FOREIGN KEY (floID) REFERENCES Users(floID), + FOREIGN KEY (asset) REFERENCES Users(asset) +); + +CREATE TABLE BuyOrder ( + id INT NOT NULL AUTO_INCREMENT, + floID CHAR(34) NOT NULL, + asset VARCHAR(64) NOT NULL, + quantity FLOAT NOT NULL, + maxPrice DECIMAL(10, 2) NOT NULL, + time_placed DATETIME DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY(id), + FOREIGN KEY (floID) REFERENCES Users(floID), + FOREIGN KEY (asset) REFERENCES Users(asset) +); + +CREATE TABLE InputFLO ( + id INT NOT NULL AUTO_INCREMENT, + txid VARCHAR(128) NOT NULL, + floID CHAR(34) NOT NULL, + amount FLOAT, + status VARCHAR(50) NOT NULL, + PRIMARY KEY(id), + FOREIGN KEY (floID) REFERENCES Users(floID) +); + +CREATE TABLE OutputFLO ( + id INT NOT NULL AUTO_INCREMENT, + txid VARCHAR(128), + floID CHAR(34) NOT NULL, + amount FLOAT NOT NULL, + status VARCHAR(50) NOT NULL, + PRIMARY KEY(id), + FOREIGN KEY (floID) REFERENCES Users(floID) +); + +CREATE TABLE InputToken ( + id INT NOT NULL AUTO_INCREMENT, + txid VARCHAR(128) NOT NULL, + floID CHAR(34) NOT NULL, + token VARCHAR(64), + amount FLOAT, + status VARCHAR(50) NOT NULL, + PRIMARY KEY(id), + FOREIGN KEY (floID) REFERENCES Users(floID) +); + +CREATE TABLE OutputToken ( + id INT NOT NULL AUTO_INCREMENT, + txid VARCHAR(128), + floID CHAR(34) NOT NULL, + token VARCHAR(64), + amount FLOAT NOT NULL, + status VARCHAR(50) NOT NULL, + PRIMARY KEY(id), + FOREIGN KEY (floID) REFERENCES Users(floID) +); + +/* Transaction Data */ + +CREATE TABLE PriceHistory ( + rate FLOAT NOT NULL, + rec_time DATETIME DEFAULT CURRENT_TIMESTAMP +); + +CREATE TABLE TransactionHistory ( + seller CHAR(34) NOT NULL, + buyer CHAR(34) NOT NULL, + asset VARCHAR(64) NOT NULL, + quantity FLOAT NOT NULL, + unitValue DECIMAL(10, 2) NOT NULL, + tx_time DATETIME DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (buyer) REFERENCES Users(floID), + FOREIGN KEY (seller) REFERENCES Users(floID), + FOREIGN KEY (asset) REFERENCES Users(asset) +); + +CREATE TABLE AuditTransaction( + rec_time DATETIME DEFAULT CURRENT_TIMESTAMP, + unit_price FLOAT NOT NULL, + quantity FLOAT NOT NULL, + total_cost FLOAT NOT NULL, + asset VARCHAR(64) NOT NULL, + sellerID CHAR(34) NOT NULL, + seller_old_asset FLOAT NOT NULL, + seller_new_asset FLOAT NOT NULL, + seller_old_cash FLOAT NOT NULL, + seller_new_cash FLOAT NOT NULL, + buyerID CHAR(34) NOT NULL, + buyer_old_asset FLOAT NOT NULL, + buyer_new_asset FLOAT NOT NULL, + buyer_old_cash FLOAT NOT NULL, + buyer_new_cash FLOAT NOT NULL, + FOREIGN KEY (sellerID) REFERENCES Users(floID), + FOREIGN KEY (buyerID) REFERENCES Users(floID), + FOREIGN KEY (asset) REFERENCES Users(asset) +); + +/* Backup Feature (Tables & Triggers) */ + +CREATE TABLE _backup ( + t_name VARCHAR(20), + id INT, + mode BOOLEAN DEFAULT TRUE, + timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY(t_name, id) ); CREATE TABLE sinkShares( -floID CHAR(34) NOT NULL, -share TEXT, -time_ DATETIME DEFAULT CURRENT_TIMESTAMP, -PRIMARY KEY(floID) + floID CHAR(34) NOT NULL, + share TEXT, + time_ DATETIME DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY(floID) ); -/* Backup feature (Table and Triggers) */ - -CREATE TABLE _backup ( -t_name VARCHAR(20), -id INT, -mode BOOLEAN DEFAULT TRUE, -timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, -PRIMARY KEY(t_name, id) -); - -CREATE TRIGGER Sessions_I AFTER INSERT ON Sessions -FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('Sessions', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT; -CREATE TRIGGER Sessions_U AFTER UPDATE ON Sessions -FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('Sessions', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT; -CREATE TRIGGER Sessions_D AFTER DELETE ON Sessions -FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('Sessions', OLD.id) ON DUPLICATE KEY UPDATE mode=NULL, timestamp=DEFAULT; +CREATE TRIGGER UserSession_I AFTER INSERT ON UserSession +FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('UserSession', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT; +CREATE TRIGGER UserSession_U AFTER UPDATE ON UserSession +FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('UserSession', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT; +CREATE TRIGGER UserSession_D AFTER DELETE ON UserSession +FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('UserSession', OLD.id) ON DUPLICATE KEY UPDATE mode=NULL, timestamp=DEFAULT; CREATE TRIGGER Cash_I AFTER INSERT ON Cash FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('Cash', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT; @@ -232,37 +248,37 @@ FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('BuyOrder', NEW.id) ON DUP CREATE TRIGGER BuyOrder_D AFTER DELETE ON BuyOrder FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('BuyOrder', OLD.id) ON DUPLICATE KEY UPDATE mode=NULL, timestamp=DEFAULT; -CREATE TRIGGER inputFLO_I AFTER INSERT ON inputFLO -FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('inputFLO', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT; -CREATE TRIGGER inputFLO_U AFTER UPDATE ON inputFLO -FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('inputFLO', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT; -CREATE TRIGGER inputFLO_D AFTER DELETE ON inputFLO -FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('inputFLO', OLD.id) ON DUPLICATE KEY UPDATE mode=NULL, timestamp=DEFAULT; +CREATE TRIGGER InputFLO_I AFTER INSERT ON InputFLO +FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('InputFLO', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT; +CREATE TRIGGER InputFLO_U AFTER UPDATE ON InputFLO +FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('InputFLO', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT; +CREATE TRIGGER InputFLO_D AFTER DELETE ON InputFLO +FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('InputFLO', OLD.id) ON DUPLICATE KEY UPDATE mode=NULL, timestamp=DEFAULT; -CREATE TRIGGER outputFLO_I AFTER INSERT ON outputFLO -FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('outputFLO', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT; -CREATE TRIGGER outputFLO_U AFTER UPDATE ON outputFLO -FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('outputFLO', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT; -CREATE TRIGGER outputFLO_D AFTER DELETE ON outputFLO -FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('outputFLO', OLD.id) ON DUPLICATE KEY UPDATE mode=NULL, timestamp=DEFAULT; +CREATE TRIGGER OutputFLO_I AFTER INSERT ON OutputFLO +FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('OutputFLO', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT; +CREATE TRIGGER OutputFLO_U AFTER UPDATE ON OutputFLO +FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('OutputFLO', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT; +CREATE TRIGGER OutputFLO_D AFTER DELETE ON OutputFLO +FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('OutputFLO', OLD.id) ON DUPLICATE KEY UPDATE mode=NULL, timestamp=DEFAULT; -CREATE TRIGGER inputToken_I AFTER INSERT ON inputToken -FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('inputToken', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT; -CREATE TRIGGER inputToken_U AFTER UPDATE ON inputToken -FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('inputToken', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT; -CREATE TRIGGER inputToken_D AFTER DELETE ON inputToken -FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('inputToken', OLD.id) ON DUPLICATE KEY UPDATE mode=NULL, timestamp=DEFAULT; +CREATE TRIGGER InputToken_I AFTER INSERT ON InputToken +FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('InputToken', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT; +CREATE TRIGGER InputToken_U AFTER UPDATE ON InputToken +FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('InputToken', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT; +CREATE TRIGGER InputToken_D AFTER DELETE ON InputToken +FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('InputToken', OLD.id) ON DUPLICATE KEY UPDATE mode=NULL, timestamp=DEFAULT; -CREATE TRIGGER outputToken_I AFTER INSERT ON outputToken -FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('outputToken', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT; -CREATE TRIGGER outputToken_U AFTER UPDATE ON outputToken -FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('outputToken', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT; -CREATE TRIGGER outputToken_D AFTER DELETE ON outputToken -FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('outputToken', OLD.id) ON DUPLICATE KEY UPDATE mode=NULL, timestamp=DEFAULT; +CREATE TRIGGER OutputToken_I AFTER INSERT ON OutputToken +FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('OutputToken', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT; +CREATE TRIGGER OutputToken_U AFTER UPDATE ON OutputToken +FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('OutputToken', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT; +CREATE TRIGGER OutputToken_D AFTER DELETE ON OutputToken +FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('OutputToken', OLD.id) ON DUPLICATE KEY UPDATE mode=NULL, timestamp=DEFAULT; -CREATE TRIGGER Tags_I AFTER INSERT ON Tags -FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('Tags', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT; -CREATE TRIGGER Tags_U AFTER UPDATE ON Tags -FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('Tags', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT; -CREATE TRIGGER Tags_D AFTER DELETE ON Tags -FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('Tags', OLD.id) ON DUPLICATE KEY UPDATE mode=NULL, timestamp=DEFAULT; \ No newline at end of file +CREATE TRIGGER UserTag_I AFTER INSERT ON UserTag +FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('UserTag', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT; +CREATE TRIGGER UserTag_U AFTER UPDATE ON UserTag +FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('UserTag', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT; +CREATE TRIGGER UserTag_D AFTER DELETE ON UserTag +FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('UserTag', OLD.id) ON DUPLICATE KEY UPDATE mode=NULL, timestamp=DEFAULT; \ No newline at end of file diff --git a/args/truncateAll.sql b/args/truncateAll.sql index b404da9..1d3dfed 100644 --- a/args/truncateAll.sql +++ b/args/truncateAll.sql @@ -1,23 +1,24 @@ /* Node data */ TRUNCATE _backup; -TRUNCATE auditTransaction; +TRUNCATE AuditTransaction; TRUNCATE BuyOrder; TRUNCATE Cash; -TRUNCATE inputFLO; -TRUNCATE inputToken; -TRUNCATE outputFLO; -TRUNCATE outputToken; -TRUNCATE priceHistory; +TRUNCATE InputFLO; +TRUNCATE InputToken; +TRUNCATE OutputFLO; +TRUNCATE OutputToken; +TRUNCATE PriceHistory; TRUNCATE Request_Log; TRUNCATE SellOrder; -TRUNCATE Sessions; -TRUNCATE Tags; -TRUNCATE Transactions; +TRUNCATE UserSession; +TRUNCATE UserTag; +TRUNCATE TransactionHistory; TRUNCATE Vault; TRUNCATE Users; /* Blockchain data */ -TRUNCATE lastTx; -TRUNCATE nodeList; -TRUNCATE trustedList; -TRUNCATE TagList; \ No newline at end of file +TRUNCATE LastTx; +TRUNCATE NodeList; +TRUNCATE TrustedList; +TRUNCATE TagList; +TRUNCATE AssetList; \ No newline at end of file diff --git a/public/fn.js b/public/fn.js index d2f939f..5fefc63 100644 --- a/public/fn.js +++ b/public/fn.js @@ -53,7 +53,7 @@ const tokenAPI = { }).catch(error => reject(error)) }) }, - sendToken: function(privKey, amount, receiverID, message = "", token = 'rupee') { + sendToken: function(privKey, amount, receiverID, message = "", token = floGlobals.currency) { return new Promise((resolve, reject) => { let senderID = floCrypto.getFloID(privKey); if (typeof amount !== "number" || amount <= 0) diff --git a/public/home.html b/public/home.html index 771ec0f..b2b77ea 100644 --- a/public/home.html +++ b/public/home.html @@ -1631,6 +1631,7 @@ let floExchangeRate = 0 function updateRate() { getRates().then(rates => { + console.debug(rates); let flo_rate = rates["FLO"]; floExchangeRate = parseFloat(flo_rate) getRef('flo_rate').textContent = formatAmount(parseFloat(flo_rate)) diff --git a/src/app.js b/src/app.js index 7281b5e..ce01d54 100644 --- a/src/app.js +++ b/src/app.js @@ -108,6 +108,10 @@ module.exports = function App(secret, DB) { set: (ids) => Request.trustedIDs = ids }); + Object.defineProperty(self, "assetList", { + set: (assets) => Request.assetList = assets + }); + //Start (or) Stop servers self.start = (port) => new Promise(resolve => { server = app.listen(port, () => { diff --git a/src/backup/head.js b/src/backup/head.js index e0f3afb..d924c25 100644 --- a/src/backup/head.js +++ b/src/backup/head.js @@ -5,7 +5,7 @@ const slave = require('./slave'); const WebSocket = require('ws'); const shareThreshold = 50 / 100; -var DB, app, wss; //Container for database and app +var DB, app, wss, tokenList; //Container for database and app var nodeList, nodeURL, nodeKBucket; //Container for (backup) node list var nodeShares = null, nodeSinkID = null, @@ -104,8 +104,8 @@ function send_dataImmutable(timestamp, ws) { const immutable_tables = { Users: "created", Request_Log: "request_time", - Transactions: "tx_time", - priceHistory: "rec_time" + TransactionHistory: "tx_time", + PriceHistory: "rec_time" }; const sendTable = (table, timeCol) => new Promise((res, rej) => { DB.query(`SELECT * FROM ${table} WHERE ${timeCol} > ?`, [timestamp]) @@ -175,16 +175,36 @@ function storeSink(sinkID, sinkPrivKey) { .catch(error => console.error(error)); } -function transferMoneyToNewSink(oldSinkID, oldSinkKey) { +function transferMoneyToNewSink(oldSinkID, oldSinkKey, newSink) { + const transferToken = token => new Promise((resolve, reject) => { + tokenAPI.getBalance(oldSinkID, token).then(tokenBalance => { + floBlockchainAPI.writeData(oldSinkID, `send ${tokenBalance} ${token}# |Exchange-market New sink`, oldSinkKey, newSink.floID, false) + .then(txid => resolve(txid)) + .catch(error => reject(error)) + }) + }); return new Promise((resolve, reject) => { - let newSink = generateNewSink(); - floBlockchainAPI.getBalance(oldSinkID).then(balFLO => { - tokenAPI.getBalance(oldSinkID).then(balRupee => { - floBlockchainAPI.sendTx(oldSinkID, newSink.floID, balFLO - floGlobals.fee, oldSinkKey, `send ${balRupee} ${floGlobals.token}# |Exchange-market New sink`) - .then(result => resolve(newSink)) - .catch(error => reject(error)) - }).catch(error => reject(error)); - }).catch(error => reject(error)) + console.debug("Transferring tokens to new Sink:", newSink.floID) + Promise.allSettled(tokenList.map(token => transferToken(token))).then(result => { + let failedFlag = false; + tokenList.forEach((token, i) => { + if (result[i].status === "fulfilled") + console.log(token, result[i].value); + else { + failedFlag = true; + console.error(token, result[i].reason); + } + }); + if (failedFlag) + return reject("Some token transfer has failed"); + floBlockchainAPI.getBalance(oldSinkID).then(floBalance => { + tokenAPI.getBalance(oldSinkID).then(cashBalance => { + floBlockchainAPI.sendTx(oldSinkID, newSink.floID, floBalance - floGlobals.fee, oldSinkKey, `send ${cashBalance} ${floGlobals.currency}# |Exchange-market New sink`) + .then(result => resolve(result)) + .catch(error => reject(error)) + }).catch(error => reject(error)); + }).catch(error => reject(error)) + }); }) } @@ -196,15 +216,17 @@ function collectShares(floID, sinkID, share) { return console.error("Something is wrong! Slaves are sending different sinkID"); collectShares.shares[floID] = share; try { - let privKey = floCrypto.retrieveShamirSecret(Object.values(collectShares.shares)); - if (floCrypto.verifyPrivKey(privKey, collectShares.sinkID)) { - transferMoneyToNewSink(collectShares.sinkID, privKey).then(newSink => { - delete collectShares.sinkID; - delete collectShares.shares; - collectShares.active = false; - storeSink(newSink.floID, newSink.privKey); - sendSharesToNodes(newSink.floID, newSink.shares); - }).catch(error => console.error(error)); + let oldSinkKey = floCrypto.retrieveShamirSecret(Object.values(collectShares.shares)); + if (floCrypto.verifyPrivKey(oldSinkKey, collectShares.sinkID)) { + let newSink = generateNewSink(); + transferMoneyToNewSink(collectShares.sinkID, oldSinkKey, newSink).then(result => { + console.log("Money transfer successful", result); + delete collectShares.sinkID; + delete collectShares.shares; + collectShares.active = false; + sendSharesToNodes(newSink.floID, newSink.shares); + }).catch(error => console.error(error)) + .finally(_ => storeSink(newSink.floID, newSink.privKey)); } } catch (error) { //Unable to retrive sink private key. Waiting for more shares! Do nothing for now @@ -391,6 +413,9 @@ module.exports = { nodeList = nodeKBucket.order; console.debug(nodeList); }, + set assetList(assets) { + tokenList = assets.filter(a => a.toUpperCase() !== "FLO"); + }, set DB(db) { DB = db; slave.DB = db; diff --git a/src/backup/slave.js b/src/backup/slave.js index ed670c0..51d9818 100644 --- a/src/backup/slave.js +++ b/src/backup/slave.js @@ -32,6 +32,7 @@ function stopSlaveProcess() { if (masterWS !== null) { masterWS.onclose = () => null; masterWS.close(); + requestInstance.close(); masterWS = null; } if (intervalID !== null) { @@ -45,8 +46,8 @@ function requestBackupSync(ws) { const tables = { Users: "created", Request_Log: "request_time", - Transactions: "tx_time", - //priceHistory: "rec_time", + TransactionHistory: "tx_time", + //PriceHistory: "rec_time", _backup: "timestamp" }; let subs = []; @@ -161,6 +162,9 @@ function sendSinkShare() { } function processBackupData(response) { + //TODO: Sync improvements needed. (2 types) + //1. Either sync has to be completed or rollback all + //2. Each table/data should be treated as independent chunks const self = requestInstance; self.last_response_time = Date.now(); switch (response.command) { diff --git a/src/coupling.js b/src/coupling.js index 8f5f63d..c3a96d5 100644 --- a/src/coupling.js +++ b/src/coupling.js @@ -3,12 +3,7 @@ const group = require("./group"); const price = require("./price"); -var DB, assetList; //container for database and assetList - -function initiate() { - for (let asset in assetList) - startCouplingForAsset(asset); -} +var DB; //container for database function startCouplingForAsset(asset) { price.getRates(asset).then(cur_rate => { @@ -117,7 +112,7 @@ function updateBalance(seller_best, buyer_best, txQueries, asset, cur_price, qua //Add coins to Buyer txQueries.push(["INSERT INTO Vault(floID, asset, base, quantity) VALUES (?, ?, ?, ?)", [buyer_best.floID, asset, cur_price, quantity]]) //Record transaction - txQueries.push(["INSERT INTO Transactions (seller, buyer, asset, quantity, unitValue) VALUES (?, ?, ?, ?, ?)", [seller_best.floID, buyer_best.floID, asset, quantity, cur_price]]); + txQueries.push(["INSERT INTO TransactionHistory (seller, buyer, asset, quantity, unitValue) VALUES (?, ?, ?, ?, ?)", [seller_best.floID, buyer_best.floID, asset, quantity, cur_price]]); } function beginAudit(sellerID, buyerID, asset, unit_price, quantity) { @@ -130,7 +125,7 @@ function beginAudit(sellerID, buyerID, asset, unit_price, quantity) { function endAudit(sellerID, buyerID, asset, old_bal, unit_price, quantity) { auditBalance(sellerID, buyerID, asset).then(new_bal => { - DB.query("INSERT INTO auditTransaction (asset, quantity, unit_price, total_cost," + + DB.query("INSERT INTO AuditTransaction (asset, quantity, unit_price, total_cost," + " sellerID, seller_old_cash, seller_old_asset, seller_new_cash, seller_new_asset," + " buyerID, buyer_old_cash, buyer_old_asset, buyer_new_cash, buyer_new_asset)" + " Value (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", [ @@ -160,7 +155,7 @@ function auditBalance(sellerID, buyerID, asset) { } module.exports = { - initiate, + initiate: startCouplingForAsset, group: { addTag: group.addTag, removeTag: group.removeTag @@ -170,8 +165,5 @@ module.exports = { DB = db; group.DB = db; price.DB = db; - }, - set assetList(list) { - assetList = list; } } \ No newline at end of file diff --git a/src/group.js b/src/group.js index d89f071..cf801b2 100644 --- a/src/group.js +++ b/src/group.js @@ -4,7 +4,7 @@ var DB; //container for database function addTag(floID, tag) { return new Promise((resolve, reject) => { - DB.query("INSERT INTO Tags (floID, tag) VALUE (?,?)", [floID, tag]) + DB.query("INSERT INTO UserTag (floID, tag) VALUE (?,?)", [floID, tag]) .then(result => resolve(`Added ${floID} to ${tag}`)) .catch(error => { if (error.code === "ER_DUP_ENTRY") @@ -19,7 +19,7 @@ function addTag(floID, tag) { function removeTag(floID, tag) { return new Promise((resolve, reject) => { - DB.query("DELETE FROM Tags WHERE floID=? AND tag=?", [floID, tag]) + DB.query("DELETE FROM UserTag WHERE floID=? AND tag=?", [floID, tag]) .then(result => resolve(`Removed ${floID} from ${tag}`)) .catch(error => reject(error)); }) @@ -206,8 +206,8 @@ const bestPair = function(asset, cur_rate, tags_buy, tags_sell) { function getUntaggedSellOrders(asset, cur_price) { return new Promise((resolve, reject) => { DB.query("SELECT SellOrder.id, SellOrder.floID, SellOrder.quantity FROM SellOrder" + - " LEFT JOIN Tags ON Tags.floID = SellOrder.floID" + - " WHERE Tags.floID IS NULL AND SellOrder.asset = ? AND SellOrder.minPrice <=?" + + " LEFT JOIN UserTag ON UserTag.floID = SellOrder.floID" + + " WHERE UserTag.floID IS NULL AND SellOrder.asset = ? AND SellOrder.minPrice <=?" + " ORDER BY SellOrder.time_placed DESC", [asset, cur_price]) .then(orders => resolve(orders)) .catch(error => reject(error)) @@ -217,8 +217,8 @@ function getUntaggedSellOrders(asset, cur_price) { function getUntaggedBuyOrders(asset, cur_price) { return new Promise((resolve, reject) => { DB.query("SELECT BuyOrder.id, BuyOrder.floID, BuyOrder.quantity FROM BuyOrder" + - " LEFT JOIN Tags ON Tags.floID = BuyOrder.floID" + - " WHERE Tags.floID IS NULL AND BuyOrder.asset = ? AND BuyOrder.maxPrice >=? " + + " LEFT JOIN UserTag ON UserTag.floID = BuyOrder.floID" + + " WHERE UserTag.floID IS NULL AND BuyOrder.asset = ? AND BuyOrder.maxPrice >=? " + " ORDER BY BuyOrder.time_placed DESC", [asset, cur_price]) .then(orders => resolve(orders)) .catch(error => reject(error)) @@ -228,8 +228,8 @@ function getUntaggedBuyOrders(asset, cur_price) { function getSellOrdersInTag(tag, asset, cur_price) { return new Promise((resolve, reject) => { DB.query("SELECT SellOrder.id, SellOrder.floID, SellOrder.quantity FROM SellOrder" + - " INNER JOIN Tags ON Tags.floID = SellOrder.floID" + - " WHERE Tags.tag = ? AND SellOrder.asset = ? AND SellOrder.minPrice <=?" + + " INNER JOIN UserTag ON UserTag.floID = SellOrder.floID" + + " WHERE UserTag.tag = ? AND SellOrder.asset = ? AND SellOrder.minPrice <=?" + " ORDER BY SellOrder.time_placed DESC", [tag, asset, cur_price]).then(orders => { if (orders.length <= 1) // No (or) Only-one order, hence priority sort not required. resolve(orders); @@ -247,8 +247,8 @@ function getSellOrdersInTag(tag, asset, cur_price) { function getBuyOrdersInTag(tag, asset, cur_price) { return new Promise((resolve, reject) => { DB.query("SELECT BuyOrder.id, BuyOrder.floID, BuyOrder.quantity FROM BuyOrder" + - " INNER JOIN Tags ON Tags.floID = BuyOrder.floID" + - " WHERE Tags.tag = ? AND BuyOrder.asset = ? AND BuyOrder.maxPrice >=?" + + " INNER JOIN UserTag ON UserTag.floID = BuyOrder.floID" + + " WHERE UserTag.tag = ? AND BuyOrder.asset = ? AND BuyOrder.maxPrice >=?" + " ORDER BY BuyOrder.time_placed DESC", [tag, asset, cur_price]).then(orders => { if (orders.length <= 1) // No (or) Only-one order, hence priority sort not required. resolve(orders); diff --git a/src/main.js b/src/main.js index 42a2b73..0c35b02 100644 --- a/src/main.js +++ b/src/main.js @@ -25,7 +25,7 @@ function refreshData(startup = false) { function refreshDataFromBlockchain() { return new Promise((resolve, reject) => { - DB.query("SELECT num FROM lastTx WHERE floID=?", [floGlobals.adminID]).then(result => { + DB.query("SELECT num FROM LastTx WHERE floID=?", [floGlobals.adminID]).then(result => { let lastTx = result.length ? result[0].num : 0; floBlockchainAPI.readData(floGlobals.adminID, { ignoreOld: lastTx, @@ -34,6 +34,7 @@ function refreshDataFromBlockchain() { }).then(result => { let promises = [], nodes_change = false, + assets_change = false, trusted_change = false; result.data.reverse().forEach(data => { var content = JSON.parse(data)[floGlobals.application]; @@ -42,20 +43,26 @@ function refreshDataFromBlockchain() { nodes_change = true; if (content.Nodes.remove) for (let n of content.Nodes.remove) - promises.push(DB.query("DELETE FROM nodeList WHERE floID=?", [n])); + promises.push(DB.query("DELETE FROM NodeList WHERE floID=?", [n])); if (content.Nodes.add) for (let n in content.Nodes.add) - promises.push(DB.query("INSERT INTO nodeList (floID, uri) VALUE (?,?) AS new ON DUPLICATE KEY UPDATE uri=new.uri", [n, content.Nodes.add[n]])); + promises.push(DB.query("INSERT INTO NodeList (floID, uri) VALUE (?,?) AS new ON DUPLICATE KEY UPDATE uri=new.uri", [n, content.Nodes.add[n]])); + } + //Asset List + if (content.Assets) { + assets_change = true; + for (let a in content.Assets) + promises.push(DB.query("INSERT INTO AssetList (asset, initialPrice) VALUE (?,?) AS new ON DUPLICATE KEY UPDATE initialPrice=new.initialPrice", [a, content.Assets[a]])); } //Trusted List if (content.Trusted) { trusted_change = true; if (content.Trusted.remove) for (let id of content.Trusted.remove) - promises.push(DB.query("DELETE FROM trustedList WHERE floID=?", [id])); + promises.push(DB.query("DELETE FROM TrustedList WHERE floID=?", [id])); if (content.Trusted.add) for (let id of content.Trusted.add) - promises.push(DB.query("INSERT INTO trustedList (floID) VALUE (?) AS new ON DUPLICATE KEY UPDATE floID=new.floID", [id])); + promises.push(DB.query("INSERT INTO TrustedList (floID) VALUE (?) AS new ON DUPLICATE KEY UPDATE floID=new.floID", [id])); } //Tag List with priority and API if (content.Tag) { @@ -71,7 +78,7 @@ function refreshDataFromBlockchain() { promises.push(`UPDATE TagList WHERE tag=? SET ${a}=?`, [t, content.Tag.update[t][a]]); } }); - promises.push(DB.query("INSERT INTO lastTx (floID, num) VALUE (?, ?) AS new ON DUPLICATE KEY UPDATE num=new.num", [floGlobals.adminID, result.totalTxs])); + promises.push(DB.query("INSERT INTO LastTx (floID, num) VALUE (?, ?) AS new ON DUPLICATE KEY UPDATE num=new.num", [floGlobals.adminID, result.totalTxs])); //Check if all save process were successful Promise.allSettled(promises).then(results => { console.debug(results.filter(r => r.status === "rejected")); @@ -80,6 +87,7 @@ function refreshDataFromBlockchain() { }); resolve({ nodes: nodes_change, + assets: assets_change, trusted: trusted_change }); }).catch(error => reject(error)); @@ -92,6 +100,8 @@ function loadDataFromDB(changes, startup) { let promises = []; if (startup || changes.nodes) promises.push(loadDataFromDB.nodeList()); + if (startup || changes.assets) + promises.push(loadDataFromDB.assetList()); if (startup || changes.trusted) promises.push(loadDataFromDB.trustedIDs()); Promise.all(promises) @@ -102,7 +112,7 @@ function loadDataFromDB(changes, startup) { loadDataFromDB.nodeList = function() { return new Promise((resolve, reject) => { - DB.query("SELECT * FROM nodeList").then(result => { + DB.query("SELECT floID, uri FROM NodeList").then(result => { let nodes = {} for (let i in result) nodes[result[i].floID] = result[i].uri; @@ -113,9 +123,23 @@ loadDataFromDB.nodeList = function() { }) } +loadDataFromDB.assetList = function() { + return new Promise((resolve, reject) => { + DB.query("SELECT asset FROM AssetList").then(result => { + let assets = []; + for (let i in result) + assets.push(result[i].asset); + //update dependents + backup.assetList = assets; + app.assetList = assets; + resolve(nodes); + }).catch(error => reject(error)) + }) +} + loadDataFromDB.trustedIDs = function() { return new Promise((resolve, reject) => { - DB.query("SELECT * FROM trustedList").then(result => { + DB.query("SELECT * FROM TrustedList").then(result => { let trustedIDs = []; for (let i in result) trustedIDs.push(result[i].floID); diff --git a/src/market.js b/src/market.js index 132a5b4..ecb1e1a 100644 --- a/src/market.js +++ b/src/market.js @@ -3,7 +3,7 @@ const coupling = require('./coupling'); const MINIMUM_BUY_REQUIREMENT = 0.1; -var DB, allowedAssets; //container for database and allowed assets +var DB, assetList; //container for database and allowed assets const getAssetBalance = (floID, asset) => new Promise((resolve, reject) => { let promises = (asset === floGlobals.currency) ? [ @@ -63,7 +63,7 @@ function addSellOrder(floID, asset, quantity, min_price) { return reject(INVALID(`Invalid quantity (${quantity})`)); else if (typeof min_price !== "number" || min_price <= 0) return reject(INVALID(`Invalid min_price (${min_price})`)); - else if (!allowedAssets.includes(asset)) + else if (!assetList.includes(asset)) return reject(INVALID(`Invalid asset (${asset})`)); getAssetBalance.check(floID, asset, quantity).then(_ => { checkSellRequirement(floID).then(_ => { @@ -76,11 +76,11 @@ function addSellOrder(floID, asset, quantity, min_price) { } const checkSellRequirement = floID => new Promise((resolve, reject) => { - DB.query("SELECT * FROM Tags WHERE floID=? AND tag=?", [floID, "MINER"]).then(result => { + DB.query("SELECT * FROM UserTag WHERE floID=? AND tag=?", [floID, "MINER"]).then(result => { if (result.length) return resolve(true); //TODO: Should seller need to buy same type of asset before selling? - DB.query("SELECT SUM(quantity) AS brought FROM Transactions WHERE buyer=?", [floID]).then(result => { + DB.query("SELECT SUM(quantity) AS brought FROM TransactionHistory WHERE buyer=?", [floID]).then(result => { if (result[0].brought >= MINIMUM_BUY_REQUIREMENT) resolve(true); else @@ -97,7 +97,7 @@ function addBuyOrder(floID, asset, quantity, max_price) { return reject(INVALID(`Invalid quantity (${quantity})`)); else if (typeof max_price !== "number" || max_price <= 0) return reject(INVALID(`Invalid max_price (${max_price})`)); - else if (!allowedAssets.includes(asset)) + else if (!assetList.includes(asset)) return reject(INVALID(`Invalid asset (${asset})`)); getAssetBalance.check(floID, asset, quantity).then(_ => { DB.query("INSERT INTO BuyOrder(floID, asset, quantity, maxPrice) VALUES (?, ?, ?, ?)", [floID, asset, quantity, max_price]) @@ -163,7 +163,7 @@ function getAccountDetails(floID) { break; } }); - DB.query("SELECT * FROM Transactions WHERE seller=? OR buyer=?", [floID, floID]) + DB.query("SELECT * FROM TransactionHistory WHERE seller=? OR buyer=?", [floID, floID]) .then(result => response.transactions = result) .catch(error => console.error(error)) .finally(_ => resolve(response)); @@ -173,7 +173,7 @@ function getAccountDetails(floID) { function depositFLO(floID, txid) { return new Promise((resolve, reject) => { - DB.query("SELECT status FROM inputFLO WHERE txid=? AND floID=?", [txid, floID]).then(result => { + DB.query("SELECT status FROM InputFLO WHERE txid=? AND floID=?", [txid, floID]).then(result => { if (result.length) { switch (result[0].status) { case "PENDING": @@ -184,7 +184,7 @@ function depositFLO(floID, txid) { return reject(INVALID("Transaction already used to add coins")); } } else - DB.query("INSERT INTO inputFLO(txid, floID, status) VALUES (?, ?, ?)", [txid, floID, "PENDING"]) + DB.query("INSERT INTO InputFLO(txid, floID, status) VALUES (?, ?, ?)", [txid, floID, "PENDING"]) .then(result => resolve("Deposit request in process")) .catch(error => reject(error)); }).catch(error => reject(error)) @@ -192,19 +192,19 @@ function depositFLO(floID, txid) { } function confirmDepositFLO() { - DB.query("SELECT id, floID, txid FROM inputFLO WHERE status=?", ["PENDING"]).then(results => { + 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(["INSERT INTO Vault(floID, quantity) VALUES (?, ?)", [req.floID, amount]]); - txQueries.push(["UPDATE inputFLO SET status=?, amount=? WHERE id=?", ["SUCCESS", amount, req.id]]); + 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)) }).catch(error => { console.error(error); if (error[0]) - DB.query("UPDATE inputFLO SET status=? WHERE id=?", ["REJECTED", req.id]) + DB.query("UPDATE InputFLO SET status=? WHERE id=?", ["REJECTED", req.id]) .then(_ => null).catch(error => console.error(error)); }); }) @@ -247,12 +247,12 @@ function withdrawFLO(floID, amount) { if (!txid) throw Error("Transaction not successful"); //Transaction was successful, Add in DB - DB.query("INSERT INTO outputFLO (floID, amount, txid, status) VALUES (?, ?, ?, ?)", [floID, amount, txid, "WAITING_CONFIRMATION"]) + DB.query("INSERT INTO OutputFLO (floID, amount, txid, status) VALUES (?, ?, ?, ?)", [floID, amount, txid, "WAITING_CONFIRMATION"]) .then(_ => null).catch(error => console.error(error)) .finally(_ => resolve("Withdrawal was successful")); }).catch(error => { console.debug(error); - DB.query("INSERT INTO outputFLO (floID, amount, status) VALUES (?, ?, ?)", [floID, amount, "PENDING"]) + DB.query("INSERT INTO OutputFLO (floID, amount, status) VALUES (?, ?, ?)", [floID, amount, "PENDING"]) .then(_ => null).catch(error => console.error(error)) .finally(_ => resolve("Withdrawal request is in process")); }); @@ -263,13 +263,13 @@ function withdrawFLO(floID, amount) { } function retryWithdrawalFLO() { - DB.query("SELECT id, floID, amount FROM outputFLO WHERE status=?", ["PENDING"]).then(results => { + DB.query("SELECT id, floID, amount FROM OutputFLO WHERE status=?", ["PENDING"]).then(results => { results.forEach(req => { floBlockchainAPI.sendTx(global.myFloID, req.floID, req.amount, global.myPrivKey, 'Withdraw FLO Coins from Market').then(txid => { if (!txid) throw Error("Transaction not successful"); //Transaction was successful, Add in DB - DB.query("UPDATE outputFLO SET status=? WHERE id=?", ["WAITING_CONFIRMATION", req.id]) + DB.query("UPDATE OutputFLO SET status=? WHERE id=?", ["WAITING_CONFIRMATION", req.id]) .then(_ => null).catch(error => console.error(error)); }).catch(error => console.error(error)); }) @@ -277,12 +277,12 @@ function retryWithdrawalFLO() { } function confirmWithdrawalFLO() { - DB.query("SELECT id, floID, amount, txid FROM outputFLO WHERE status=?", ["WAITING_CONFIRMATION"]).then(results => { + DB.query("SELECT id, floID, amount, txid FROM OutputFLO WHERE status=?", ["WAITING_CONFIRMATION"]).then(results => { results.forEach(req => { floBlockchainAPI.getTx(req.txid).then(tx => { if (!tx.blockheight || !tx.confirmations) //Still not confirmed return; - DB.query("UPDATE outputFLO SET status=? WHERE id=?", ["SUCCESS", req.id]) + DB.query("UPDATE OutputFLO SET status=? WHERE id=?", ["SUCCESS", req.id]) .then(result => console.debug("FLO withdrawed:", req.floID, req.amount)) .catch(error => console.error(error)) }).catch(error => console.error(error)); @@ -292,7 +292,7 @@ function confirmWithdrawalFLO() { function depositToken(floID, txid) { return new Promise((resolve, reject) => { - DB.query("SELECT status FROM inputToken WHERE txid=? AND floID=?", [txid, floID]).then(result => { + DB.query("SELECT status FROM InputToken WHERE txid=? AND floID=?", [txid, floID]).then(result => { if (result.length) { switch (result[0].status) { case "PENDING": @@ -303,7 +303,7 @@ function depositToken(floID, txid) { return reject(INVALID("Transaction already used to add tokens")); } } else - DB.query("INSERT INTO inputToken(txid, floID, status) VALUES (?, ?, ?)", [txid, floID, "PENDING"]) + DB.query("INSERT INTO InputToken(txid, floID, status) VALUES (?, ?, ?)", [txid, floID, "PENDING"]) .then(result => resolve("Deposit request in process")) .catch(error => reject(error)); }).catch(error => reject(error)) @@ -311,10 +311,10 @@ function depositToken(floID, txid) { } function confirmDepositToken() { - DB.query("SELECT id, floID, txid FROM inputToken WHERE status=?", ["PENDING"]).then(results => { + DB.query("SELECT id, floID, txid FROM InputToken WHERE status=?", ["PENDING"]).then(results => { results.forEach(req => { confirmDepositToken.checkTx(req.floID, req.txid).then(amounts => { - DB.query("SELECT id FROM inputFLO where floID=? AND txid=?", [req.floID, req.txid]).then(result => { + DB.query("SELECT id FROM InputFLO where floID=? AND txid=?", [req.floID, req.txid]).then(result => { let txQueries = [], token_name = amounts[0], amount_token = amounts[1]; @@ -322,9 +322,9 @@ function confirmDepositToken() { if (!result.length) { let amount_flo = amounts[2]; txQueries.push(["INSERT INTO Vault(floID, asset, quantity) VALUES (?, ?, ?)", [req.floID, "FLO", amount_flo]]); - txQueries.push(["INSERT INTO inputFLO(txid, floID, amount, status) VALUES (?, ?, ?, ?)", [req.txid, req.floID, amount_flo, "SUCCESS"]]); + txQueries.push(["INSERT INTO InputFLO(txid, floID, amount, status) VALUES (?, ?, ?, ?)", [req.txid, req.floID, amount_flo, "SUCCESS"]]); } - txQueries.push(["UPDATE inputToken SET status=?, token=?, amount=? WHERE id=?", ["SUCCESS", token_name, amount_token, req.id]]); + txQueries.push(["UPDATE InputToken SET status=?, token=?, amount=? WHERE id=?", ["SUCCESS", token_name, amount_token, req.id]]); if (token_name === floGlobals.currency) txQueries.push(["UPDATE Cash SET balance=balance+? WHERE floID=?", [amount_token, req.floID]]); else @@ -336,7 +336,7 @@ function confirmDepositToken() { }).catch(error => { console.error(error); if (error[0]) - DB.query("UPDATE inputToken SET status=? WHERE id=?", ["REJECTED", req.id]) + DB.query("UPDATE InputToken SET status=? WHERE id=?", ["REJECTED", req.id]) .then(_ => null).catch(error => console.error(error)); }); }) @@ -353,7 +353,7 @@ confirmDepositToken.checkTx = function(sender, txid) { return reject([true, "Transaction transfer is not 'token'"]); var token_name = tx.parsedFloData.tokenIdentification, amount_token = tx.parsedFloData.tokenAmount; - if (!allowedAssets.includes(token_name) || token_name === "FLO") + if (!assetList.includes(token_name) || token_name === "FLO") return reject([true, "Token not authorised"]); let vin_sender = tx.transactionDetails.vin.filter(v => v.addr === sender) if (!vin_sender.length) @@ -373,7 +373,7 @@ function withdrawToken(floID, token, amount) { return reject(INVALID("Invalid FLO ID")); else if (typeof amount !== "number" || amount <= 0) return reject(INVALID(`Invalid amount (${amount})`)); - else if (!allowedAssets.includes(token) || token === "FLO") + else if (!assetList.includes(token) || token === "FLO") return reject(INVALID("Invalid Token")); //Check for FLO balance (transaction fee) const required_flo = floGlobals.sendAmt + floGlobals.fee; @@ -383,15 +383,15 @@ function withdrawToken(floID, token, amount) { consumeAsset(floID, token, amount, txQueries).then(txQueries => { DB.transaction(txQueries).then(result => { //Send FLO to user via blockchain API - tokenAPI.sendToken(global.myPrivKey, amount, '(withdrawal from market)', floID, token).then(txid => { + tokenAPI.sendToken(global.myPrivKey, amount, floID, '(withdrawal from market)', token).then(txid => { if (!txid) throw Error("Transaction not successful"); //Transaction was successful, Add in DB - DB.query("INSERT INTO outputToken (floID, token, amount, txid, status) VALUES (?, ?, ?, ?, ?)", [floID, token, amount, txid, "WAITING_CONFIRMATION"]) + DB.query("INSERT INTO OutputToken (floID, token, amount, txid, status) VALUES (?, ?, ?, ?, ?)", [floID, token, amount, txid, "WAITING_CONFIRMATION"]) .then(_ => null).catch(error => console.error(error)) .finally(_ => resolve("Withdrawal was successful")); }).catch(error => { console.debug(error); - DB.query("INSERT INTO outputToken (floID, token, amount, status) VALUES (?, ?, ?, ?)", [floID, token, amount, "PENDING"]) + DB.query("INSERT INTO OutputToken (floID, token, amount, status) VALUES (?, ?, ?, ?)", [floID, token, amount, "PENDING"]) .then(_ => null).catch(error => console.error(error)) .finally(_ => resolve("Withdrawal request is in process")); }); @@ -404,13 +404,13 @@ function withdrawToken(floID, token, amount) { } function retryWithdrawalToken() { - DB.query("SELECT id, floID, token, amount FROM outputToken WHERE status=?", ["PENDING"]).then(results => { + DB.query("SELECT id, floID, token, amount FROM OutputToken WHERE status=?", ["PENDING"]).then(results => { results.forEach(req => { - tokenAPI.sendToken(global.myPrivKey, req.amount, '(withdrawal from market)', req.floID, req.token).then(txid => { + tokenAPI.sendToken(global.myPrivKey, req.amount, req.floID, '(withdrawal from market)', req.token).then(txid => { if (!txid) throw Error("Transaction not successful"); //Transaction was successful, Add in DB - DB.query("UPDATE outputToken SET status=?, txid=? WHERE id=?", ["WAITING_CONFIRMATION", txid, req.id]) + DB.query("UPDATE OutputToken SET status=?, txid=? WHERE id=?", ["WAITING_CONFIRMATION", txid, req.id]) .then(_ => null).catch(error => console.error(error)); }).catch(error => console.error(error)); }); @@ -418,10 +418,10 @@ function retryWithdrawalToken() { } function confirmWithdrawalToken() { - DB.query("SELECT id, floID, token, amount, txid FROM outputToken WHERE status=?", ["WAITING_CONFIRMATION"]).then(results => { + DB.query("SELECT id, floID, token, amount, txid FROM OutputToken WHERE status=?", ["WAITING_CONFIRMATION"]).then(results => { results.forEach(req => { tokenAPI.getTx(req.txid).then(tx => { - DB.query("UPDATE outputToken SET status=? WHERE id=?", ["SUCCESS", req.id]) + DB.query("UPDATE OutputToken SET status=? WHERE id=?", ["SUCCESS", req.id]) .then(result => console.debug("Token withdrawed:", req.floID, req.token, req.amount)) .catch(error => console.error(error)); }).catch(error => console.error(error)); @@ -431,7 +431,7 @@ function confirmWithdrawalToken() { function periodicProcess() { blockchainReCheck(); - coupling.initiate(); + assetList.forEach(asset => coupling.initiate(asset)); } function blockchainReCheck() { @@ -461,8 +461,7 @@ module.exports = { DB = db; coupling.DB = db; }, - set allowedAssets(assets) { - allowedAssets = Object.keys(assets); - coupling.assetList = assets; + set assetList(assets) { + assetList = assets; } }; \ No newline at end of file diff --git a/src/price.js b/src/price.js index 960f694..3b5ae0a 100644 --- a/src/price.js +++ b/src/price.js @@ -19,7 +19,7 @@ const updateLastTime = asset => lastTime[asset] = Date.now(); //store FLO price in DB every 1 hr function storeRate(asset, rate) { - DB.query("INSERT INTO priceHistory (asset, rate) VALUE (?, ?)", [asset, rate]) + DB.query("INSERT INTO PriceHistory (asset, rate) VALUE (?, ?)", [asset, rate]) .then(_ => null).catch(error => console.error(error)) } setInterval(() => { @@ -29,7 +29,7 @@ setInterval(() => { function getPastRate(asset, hrs = 24) { return new Promise((resolve, reject) => { - DB.query("SELECT rate FROM priceHistory WHERE asset=? AND rec_time >= NOW() - INTERVAL ? hour ORDER BY rec_time LIMIT 1", [asset, hrs]) + DB.query("SELECT rate FROM PriceHistory WHERE asset=? AND rec_time >= NOW() - INTERVAL ? hour ORDER BY rec_time LIMIT 1", [asset, hrs]) .then(result => result.length ? resolve(result[0].rate) : reject('No records found in past 24hrs')) .catch(error => reject(error)) }); @@ -40,15 +40,18 @@ function loadRate(asset) { if (typeof cur_rate[asset] !== "undefined") return resolve(cur_rate[asset]); updateLastTime(asset); - DB.query("SELECT rate FROM priceHistory WHERE asset=? ORDER BY rec_time DESC LIMIT 1", [asset]).then(result => { + DB.query("SELECT rate FROM PriceHistory WHERE asset=? ORDER BY rec_time DESC LIMIT 1", [asset]).then(result => { if (result.length) resolve(cur_rate[asset] = result[0].rate); else - fetchRates().then(rate => resolve(cur_rate[asset] = rate)).catch(error => reject(error)); + DB.query("SELECT initialPrice FROM AssetList WHERE asset=?", [asset]) + .then(result => resolve(result[0].initialPrice)) + .catch(error => reject(error)) }).catch(error => reject(error)); }) } +/* function fetchRates() { return new Promise((resolve, reject) => { fetchRates.FLO_USD().then(FLO_rate => { @@ -87,6 +90,7 @@ fetchRates.USD_INR = function() { }).catch(error => reject(error)); }); } +*/ function getRates(asset) { return new Promise((resolve, reject) => { @@ -137,7 +141,7 @@ function checkForRatedSellers(asset) { DB.query("SELECT MAX(sellPriority) as max_p FROM TagList").then(result => { let ratedMin = result[0].max_p * (1 - TOP_RANGE); DB.query("SELECT COUNT(*) as value FROM SellOrder WHERE floID IN (" + - " SELECT Tags.floID FROM Tags INNER JOIN TagList ON Tags.tag = TagList.tag" + + " SELECT UserTag.floID FROM UserTag INNER JOIN TagList ON UserTag.tag = TagList.tag" + " WHERE TagList.sellPriority > ?)", [ratedMin]).then(result => { resolve(result[0].value > 0); }).catch(error => reject(error)) diff --git a/src/request.js b/src/request.js index 964c38a..69c4c57 100644 --- a/src/request.js +++ b/src/request.js @@ -30,7 +30,7 @@ function validateRequestFromFloID(request, sign, floID, proxy = true) { return reject(INVALID(INVALID_SERVER_MSG)); else if (!floCrypto.validateAddr(floID)) return reject(INVALID("Invalid floID")); - DB.query("SELECT " + (proxy ? "session_time, proxyKey AS pubKey FROM Sessions" : "pubKey FROM Users") + " WHERE floID=?", [floID]).then(result => { + DB.query("SELECT " + (proxy ? "session_time, proxyKey AS pubKey FROM UserSession" : "pubKey FROM Users") + " WHERE floID=?", [floID]).then(result => { if (result.length < 1) return reject(INVALID(proxy ? "Session not active" : "User not registered")); if (proxy && result[0].session_time + maxSessionTimeout < Date.now()) @@ -113,7 +113,7 @@ function Login(req, res) { proxyKey: data.proxyKey, timestamp: data.timestamp }, data.sign, data.floID, false).then(req_str => { - DB.query("INSERT INTO Sessions (floID, proxyKey) VALUE (?, ?) AS new " + + DB.query("INSERT INTO UserSession (floID, proxyKey) VALUE (?, ?) AS new " + "ON DUPLICATE KEY UPDATE session_time=DEFAULT, proxyKey=new.proxyKey", [data.floID, data.proxyKey]).then(_ => { storeRequest(data.floID, req_str, data.sign); @@ -138,7 +138,7 @@ function Logout(req, res) { type: "logout", timestamp: data.timestamp }, data.sign, data.floID).then(req_str => { - DB.query("DELETE FROM Sessions WHERE floID=?", [data.floID]).then(_ => { + DB.query("DELETE FROM UserSession WHERE floID=?", [data.floID]).then(_ => { storeRequest(data.floID, req_str, data.sign); res.send('Logout successful'); }).catch(error => { @@ -263,7 +263,7 @@ function ListBuyOrders(req, res) { function ListTransactions(req, res) { //TODO: Limit size (recent) - DB.query("SELECT * FROM Transactions ORDER BY tx_time DESC") + DB.query("SELECT * FROM TransactionHistory ORDER BY tx_time DESC") .then(result => res.send(result)) .catch(error => res.status(INTERNAL.e_code).send("Try again later!")); } @@ -496,6 +496,9 @@ module.exports = { set trustedIDs(ids) { trustedIDs = ids; }, + set assetList(assets){ + market.assetList = assets; + }, set DB(db) { DB = db; market.DB = db; diff --git a/src/tokenAPI.js b/src/tokenAPI.js index d786fc9..4a3ccb0 100644 --- a/src/tokenAPI.js +++ b/src/tokenAPI.js @@ -35,7 +35,7 @@ }).catch(error => reject(error)) }) }, - sendToken: function(privKey, amount, message = "", receiverID = floGlobals.adminID, token = floGlobals.currency) { + sendToken: function(privKey, amount, receiverID, message = "", token = floGlobals.currency) { return new Promise((resolve, reject) => { let senderID = floCrypto.getFloID(privKey); if (typeof amount !== "number" || amount <= 0)