Multi asset: initial price and other improvements

- Read blockchain for asset's initial price
- Transfer all tokens to new sink on master transfer

Other Improvements:
- Slave: close existing backup sync when master WS closes
- Updated SQL schema, updated SQL syntax as required
This commit is contained in:
sairajzero 2022-02-05 20:23:36 +05:30
parent df69ee0f7b
commit 048ab0667b
14 changed files with 406 additions and 333 deletions

View File

@ -1,208 +1,224 @@
/* Main Tables */ /* Blockchain Data */
CREATE TABLE Users ( CREATE TABLE LastTx(
floID CHAR(34) NOT NULL, floID CHAR(34) NOT NULL,
pubKey CHAR(66) NOT NULL, num INT,
created DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY(floID)
PRIMARY KEY(floID)
); );
CREATE TABLE Sessions ( CREATE TABLE NodeList(
id INT NOT NULL AUTO_INCREMENT, floID CHAR(34) NOT NULL,
floID CHAR(34) NOT NULL, uri TINYTEXT,
proxyKey CHAR(66) NOT NULL, PRIMARY KEY(floID)
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 TagList ( CREATE TABLE TagList (
tag VARCHAR(50) NOT NULL, tag VARCHAR(50) NOT NULL,
sellPriority INT, sellPriority INT,
buyPriority INT, buyPriority INT,
api TINYTEXT, api TINYTEXT,
PRIMARY KEY(tag) PRIMARY KEY(tag)
); );
CREATE TABLE Tags ( CREATE TABLE AssetList (
id INT NOT NULL AUTO_INCREMENT, asset VARCHAR(64) NOT NULL,
floID CHAR(34) NOT NULL, initialPrice FLOAT,
tag VARCHAR(50) NOT NULL, PRIMARY KEY(asset)
PRIMARY KEY(floID, tag),
KEY (id),
FOREIGN KEY (floID) REFERENCES Users(floID),
FOREIGN KEY (tag) REFERENCES TagList(tag)
); );
CREATE TABLE priceHistory ( CREATE TABLE TrustedList(
rate FLOAT NOT NULL, floID CHAR(34) NOT NULL,
rec_time DATETIME DEFAULT CURRENT_TIMESTAMP PRIMARY KEY(floID)
); );
CREATE TABLE auditTransaction( /* User Data */
rec_time DATETIME DEFAULT CURRENT_TIMESTAMP,
unit_price FLOAT NOT NULL, CREATE TABLE Users (
quantity FLOAT NOT NULL, floID CHAR(34) NOT NULL,
total_cost FLOAT NOT NULL, pubKey CHAR(66) NOT NULL,
asset VARCHAR(64) NOT NULL, created DATETIME DEFAULT CURRENT_TIMESTAMP,
sellerID CHAR(34) NOT NULL, PRIMARY KEY(floID)
seller_old_asset FLOAT NOT NULL, );
seller_new_asset FLOAT NOT NULL,
seller_old_cash FLOAT NOT NULL, CREATE TABLE UserSession (
seller_new_cash FLOAT NOT NULL, id INT NOT NULL AUTO_INCREMENT,
buyerID CHAR(34) NOT NULL, floID CHAR(34) NOT NULL,
buyer_old_asset FLOAT NOT NULL, proxyKey CHAR(66) NOT NULL,
buyer_new_asset FLOAT NOT NULL, session_time DATETIME DEFAULT CURRENT_TIMESTAMP,
buyer_old_cash FLOAT NOT NULL, KEY (id),
buyer_new_cash FLOAT NOT NULL, PRIMARY KEY(floID),
FOREIGN KEY (sellerID) REFERENCES Users(floID), FOREIGN KEY (floID) REFERENCES Users(floID)
FOREIGN KEY (buyerID) 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( CREATE TABLE sinkShares(
floID CHAR(34) NOT NULL, floID CHAR(34) NOT NULL,
share TEXT, share TEXT,
time_ DATETIME DEFAULT CURRENT_TIMESTAMP, time_ DATETIME DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY(floID) PRIMARY KEY(floID)
); );
/* Backup feature (Table and Triggers) */ 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 TABLE _backup ( CREATE TRIGGER UserSession_U AFTER UPDATE ON UserSession
t_name VARCHAR(20), FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('UserSession', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT;
id INT, CREATE TRIGGER UserSession_D AFTER DELETE ON UserSession
mode BOOLEAN DEFAULT TRUE, FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('UserSession', OLD.id) ON DUPLICATE KEY UPDATE mode=NULL, timestamp=DEFAULT;
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 Cash_I AFTER INSERT ON Cash 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; 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 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; 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 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; 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 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; 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 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; 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 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; 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 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; 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 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; 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 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; 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 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; 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 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; 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 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; 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 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; 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 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; 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 CREATE TRIGGER UserTag_I AFTER INSERT ON UserTag
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('Tags', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT; FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('UserTag', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT;
CREATE TRIGGER Tags_U AFTER UPDATE ON Tags CREATE TRIGGER UserTag_U AFTER UPDATE ON UserTag
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('Tags', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT; FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('UserTag', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT;
CREATE TRIGGER Tags_D AFTER DELETE ON Tags CREATE TRIGGER UserTag_D AFTER DELETE ON UserTag
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('Tags', OLD.id) ON DUPLICATE KEY UPDATE mode=NULL, timestamp=DEFAULT; FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('UserTag', OLD.id) ON DUPLICATE KEY UPDATE mode=NULL, timestamp=DEFAULT;

View File

@ -1,23 +1,24 @@
/* Node data */ /* Node data */
TRUNCATE _backup; TRUNCATE _backup;
TRUNCATE auditTransaction; TRUNCATE AuditTransaction;
TRUNCATE BuyOrder; TRUNCATE BuyOrder;
TRUNCATE Cash; TRUNCATE Cash;
TRUNCATE inputFLO; TRUNCATE InputFLO;
TRUNCATE inputToken; TRUNCATE InputToken;
TRUNCATE outputFLO; TRUNCATE OutputFLO;
TRUNCATE outputToken; TRUNCATE OutputToken;
TRUNCATE priceHistory; TRUNCATE PriceHistory;
TRUNCATE Request_Log; TRUNCATE Request_Log;
TRUNCATE SellOrder; TRUNCATE SellOrder;
TRUNCATE Sessions; TRUNCATE UserSession;
TRUNCATE Tags; TRUNCATE UserTag;
TRUNCATE Transactions; TRUNCATE TransactionHistory;
TRUNCATE Vault; TRUNCATE Vault;
TRUNCATE Users; TRUNCATE Users;
/* Blockchain data */ /* Blockchain data */
TRUNCATE lastTx; TRUNCATE LastTx;
TRUNCATE nodeList; TRUNCATE NodeList;
TRUNCATE trustedList; TRUNCATE TrustedList;
TRUNCATE TagList; TRUNCATE TagList;
TRUNCATE AssetList;

View File

@ -53,7 +53,7 @@ const tokenAPI = {
}).catch(error => reject(error)) }).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) => { return new Promise((resolve, reject) => {
let senderID = floCrypto.getFloID(privKey); let senderID = floCrypto.getFloID(privKey);
if (typeof amount !== "number" || amount <= 0) if (typeof amount !== "number" || amount <= 0)

View File

@ -1631,6 +1631,7 @@
let floExchangeRate = 0 let floExchangeRate = 0
function updateRate() { function updateRate() {
getRates().then(rates => { getRates().then(rates => {
console.debug(rates);
let flo_rate = rates["FLO"]; let flo_rate = rates["FLO"];
floExchangeRate = parseFloat(flo_rate) floExchangeRate = parseFloat(flo_rate)
getRef('flo_rate').textContent = formatAmount(parseFloat(flo_rate)) getRef('flo_rate').textContent = formatAmount(parseFloat(flo_rate))

View File

@ -108,6 +108,10 @@ module.exports = function App(secret, DB) {
set: (ids) => Request.trustedIDs = ids set: (ids) => Request.trustedIDs = ids
}); });
Object.defineProperty(self, "assetList", {
set: (assets) => Request.assetList = assets
});
//Start (or) Stop servers //Start (or) Stop servers
self.start = (port) => new Promise(resolve => { self.start = (port) => new Promise(resolve => {
server = app.listen(port, () => { server = app.listen(port, () => {

View File

@ -5,7 +5,7 @@ const slave = require('./slave');
const WebSocket = require('ws'); const WebSocket = require('ws');
const shareThreshold = 50 / 100; 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 nodeList, nodeURL, nodeKBucket; //Container for (backup) node list
var nodeShares = null, var nodeShares = null,
nodeSinkID = null, nodeSinkID = null,
@ -104,8 +104,8 @@ function send_dataImmutable(timestamp, ws) {
const immutable_tables = { const immutable_tables = {
Users: "created", Users: "created",
Request_Log: "request_time", Request_Log: "request_time",
Transactions: "tx_time", TransactionHistory: "tx_time",
priceHistory: "rec_time" PriceHistory: "rec_time"
}; };
const sendTable = (table, timeCol) => new Promise((res, rej) => { const sendTable = (table, timeCol) => new Promise((res, rej) => {
DB.query(`SELECT * FROM ${table} WHERE ${timeCol} > ?`, [timestamp]) DB.query(`SELECT * FROM ${table} WHERE ${timeCol} > ?`, [timestamp])
@ -175,16 +175,36 @@ function storeSink(sinkID, sinkPrivKey) {
.catch(error => console.error(error)); .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) => { return new Promise((resolve, reject) => {
let newSink = generateNewSink(); console.debug("Transferring tokens to new Sink:", newSink.floID)
floBlockchainAPI.getBalance(oldSinkID).then(balFLO => { Promise.allSettled(tokenList.map(token => transferToken(token))).then(result => {
tokenAPI.getBalance(oldSinkID).then(balRupee => { let failedFlag = false;
floBlockchainAPI.sendTx(oldSinkID, newSink.floID, balFLO - floGlobals.fee, oldSinkKey, `send ${balRupee} ${floGlobals.token}# |Exchange-market New sink`) tokenList.forEach((token, i) => {
.then(result => resolve(newSink)) if (result[i].status === "fulfilled")
.catch(error => reject(error)) console.log(token, result[i].value);
}).catch(error => reject(error)); else {
}).catch(error => reject(error)) 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"); return console.error("Something is wrong! Slaves are sending different sinkID");
collectShares.shares[floID] = share; collectShares.shares[floID] = share;
try { try {
let privKey = floCrypto.retrieveShamirSecret(Object.values(collectShares.shares)); let oldSinkKey = floCrypto.retrieveShamirSecret(Object.values(collectShares.shares));
if (floCrypto.verifyPrivKey(privKey, collectShares.sinkID)) { if (floCrypto.verifyPrivKey(oldSinkKey, collectShares.sinkID)) {
transferMoneyToNewSink(collectShares.sinkID, privKey).then(newSink => { let newSink = generateNewSink();
delete collectShares.sinkID; transferMoneyToNewSink(collectShares.sinkID, oldSinkKey, newSink).then(result => {
delete collectShares.shares; console.log("Money transfer successful", result);
collectShares.active = false; delete collectShares.sinkID;
storeSink(newSink.floID, newSink.privKey); delete collectShares.shares;
sendSharesToNodes(newSink.floID, newSink.shares); collectShares.active = false;
}).catch(error => console.error(error)); sendSharesToNodes(newSink.floID, newSink.shares);
}).catch(error => console.error(error))
.finally(_ => storeSink(newSink.floID, newSink.privKey));
} }
} catch (error) { } catch (error) {
//Unable to retrive sink private key. Waiting for more shares! Do nothing for now //Unable to retrive sink private key. Waiting for more shares! Do nothing for now
@ -391,6 +413,9 @@ module.exports = {
nodeList = nodeKBucket.order; nodeList = nodeKBucket.order;
console.debug(nodeList); console.debug(nodeList);
}, },
set assetList(assets) {
tokenList = assets.filter(a => a.toUpperCase() !== "FLO");
},
set DB(db) { set DB(db) {
DB = db; DB = db;
slave.DB = db; slave.DB = db;

View File

@ -32,6 +32,7 @@ function stopSlaveProcess() {
if (masterWS !== null) { if (masterWS !== null) {
masterWS.onclose = () => null; masterWS.onclose = () => null;
masterWS.close(); masterWS.close();
requestInstance.close();
masterWS = null; masterWS = null;
} }
if (intervalID !== null) { if (intervalID !== null) {
@ -45,8 +46,8 @@ function requestBackupSync(ws) {
const tables = { const tables = {
Users: "created", Users: "created",
Request_Log: "request_time", Request_Log: "request_time",
Transactions: "tx_time", TransactionHistory: "tx_time",
//priceHistory: "rec_time", //PriceHistory: "rec_time",
_backup: "timestamp" _backup: "timestamp"
}; };
let subs = []; let subs = [];
@ -161,6 +162,9 @@ function sendSinkShare() {
} }
function processBackupData(response) { 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; const self = requestInstance;
self.last_response_time = Date.now(); self.last_response_time = Date.now();
switch (response.command) { switch (response.command) {

View File

@ -3,12 +3,7 @@
const group = require("./group"); const group = require("./group");
const price = require("./price"); const price = require("./price");
var DB, assetList; //container for database and assetList var DB; //container for database
function initiate() {
for (let asset in assetList)
startCouplingForAsset(asset);
}
function startCouplingForAsset(asset) { function startCouplingForAsset(asset) {
price.getRates(asset).then(cur_rate => { 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 //Add coins to Buyer
txQueries.push(["INSERT INTO Vault(floID, asset, base, quantity) VALUES (?, ?, ?, ?)", [buyer_best.floID, asset, cur_price, quantity]]) txQueries.push(["INSERT INTO Vault(floID, asset, base, quantity) VALUES (?, ?, ?, ?)", [buyer_best.floID, asset, cur_price, quantity]])
//Record transaction //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) { 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) { function endAudit(sellerID, buyerID, asset, old_bal, unit_price, quantity) {
auditBalance(sellerID, buyerID, asset).then(new_bal => { 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," + " 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)" + " buyerID, buyer_old_cash, buyer_old_asset, buyer_new_cash, buyer_new_asset)" +
" Value (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", [ " Value (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", [
@ -160,7 +155,7 @@ function auditBalance(sellerID, buyerID, asset) {
} }
module.exports = { module.exports = {
initiate, initiate: startCouplingForAsset,
group: { group: {
addTag: group.addTag, addTag: group.addTag,
removeTag: group.removeTag removeTag: group.removeTag
@ -170,8 +165,5 @@ module.exports = {
DB = db; DB = db;
group.DB = db; group.DB = db;
price.DB = db; price.DB = db;
},
set assetList(list) {
assetList = list;
} }
} }

View File

@ -4,7 +4,7 @@ var DB; //container for database
function addTag(floID, tag) { function addTag(floID, tag) {
return new Promise((resolve, reject) => { 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}`)) .then(result => resolve(`Added ${floID} to ${tag}`))
.catch(error => { .catch(error => {
if (error.code === "ER_DUP_ENTRY") if (error.code === "ER_DUP_ENTRY")
@ -19,7 +19,7 @@ function addTag(floID, tag) {
function removeTag(floID, tag) { function removeTag(floID, tag) {
return new Promise((resolve, reject) => { 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}`)) .then(result => resolve(`Removed ${floID} from ${tag}`))
.catch(error => reject(error)); .catch(error => reject(error));
}) })
@ -206,8 +206,8 @@ const bestPair = function(asset, cur_rate, tags_buy, tags_sell) {
function getUntaggedSellOrders(asset, cur_price) { function getUntaggedSellOrders(asset, cur_price) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
DB.query("SELECT SellOrder.id, SellOrder.floID, SellOrder.quantity FROM SellOrder" + DB.query("SELECT SellOrder.id, SellOrder.floID, SellOrder.quantity FROM SellOrder" +
" LEFT JOIN Tags ON Tags.floID = SellOrder.floID" + " LEFT JOIN UserTag ON UserTag.floID = SellOrder.floID" +
" WHERE Tags.floID IS NULL AND SellOrder.asset = ? AND SellOrder.minPrice <=?" + " WHERE UserTag.floID IS NULL AND SellOrder.asset = ? AND SellOrder.minPrice <=?" +
" ORDER BY SellOrder.time_placed DESC", [asset, cur_price]) " ORDER BY SellOrder.time_placed DESC", [asset, cur_price])
.then(orders => resolve(orders)) .then(orders => resolve(orders))
.catch(error => reject(error)) .catch(error => reject(error))
@ -217,8 +217,8 @@ function getUntaggedSellOrders(asset, cur_price) {
function getUntaggedBuyOrders(asset, cur_price) { function getUntaggedBuyOrders(asset, cur_price) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
DB.query("SELECT BuyOrder.id, BuyOrder.floID, BuyOrder.quantity FROM BuyOrder" + DB.query("SELECT BuyOrder.id, BuyOrder.floID, BuyOrder.quantity FROM BuyOrder" +
" LEFT JOIN Tags ON Tags.floID = BuyOrder.floID" + " LEFT JOIN UserTag ON UserTag.floID = BuyOrder.floID" +
" WHERE Tags.floID IS NULL AND BuyOrder.asset = ? AND BuyOrder.maxPrice >=? " + " WHERE UserTag.floID IS NULL AND BuyOrder.asset = ? AND BuyOrder.maxPrice >=? " +
" ORDER BY BuyOrder.time_placed DESC", [asset, cur_price]) " ORDER BY BuyOrder.time_placed DESC", [asset, cur_price])
.then(orders => resolve(orders)) .then(orders => resolve(orders))
.catch(error => reject(error)) .catch(error => reject(error))
@ -228,8 +228,8 @@ function getUntaggedBuyOrders(asset, cur_price) {
function getSellOrdersInTag(tag, asset, cur_price) { function getSellOrdersInTag(tag, asset, cur_price) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
DB.query("SELECT SellOrder.id, SellOrder.floID, SellOrder.quantity FROM SellOrder" + DB.query("SELECT SellOrder.id, SellOrder.floID, SellOrder.quantity FROM SellOrder" +
" INNER JOIN Tags ON Tags.floID = SellOrder.floID" + " INNER JOIN UserTag ON UserTag.floID = SellOrder.floID" +
" WHERE Tags.tag = ? AND SellOrder.asset = ? AND SellOrder.minPrice <=?" + " WHERE UserTag.tag = ? AND SellOrder.asset = ? AND SellOrder.minPrice <=?" +
" ORDER BY SellOrder.time_placed DESC", [tag, asset, cur_price]).then(orders => { " 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. if (orders.length <= 1) // No (or) Only-one order, hence priority sort not required.
resolve(orders); resolve(orders);
@ -247,8 +247,8 @@ function getSellOrdersInTag(tag, asset, cur_price) {
function getBuyOrdersInTag(tag, asset, cur_price) { function getBuyOrdersInTag(tag, asset, cur_price) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
DB.query("SELECT BuyOrder.id, BuyOrder.floID, BuyOrder.quantity FROM BuyOrder" + DB.query("SELECT BuyOrder.id, BuyOrder.floID, BuyOrder.quantity FROM BuyOrder" +
" INNER JOIN Tags ON Tags.floID = BuyOrder.floID" + " INNER JOIN UserTag ON UserTag.floID = BuyOrder.floID" +
" WHERE Tags.tag = ? AND BuyOrder.asset = ? AND BuyOrder.maxPrice >=?" + " WHERE UserTag.tag = ? AND BuyOrder.asset = ? AND BuyOrder.maxPrice >=?" +
" ORDER BY BuyOrder.time_placed DESC", [tag, asset, cur_price]).then(orders => { " 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. if (orders.length <= 1) // No (or) Only-one order, hence priority sort not required.
resolve(orders); resolve(orders);

View File

@ -25,7 +25,7 @@ function refreshData(startup = false) {
function refreshDataFromBlockchain() { function refreshDataFromBlockchain() {
return new Promise((resolve, reject) => { 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; let lastTx = result.length ? result[0].num : 0;
floBlockchainAPI.readData(floGlobals.adminID, { floBlockchainAPI.readData(floGlobals.adminID, {
ignoreOld: lastTx, ignoreOld: lastTx,
@ -34,6 +34,7 @@ function refreshDataFromBlockchain() {
}).then(result => { }).then(result => {
let promises = [], let promises = [],
nodes_change = false, nodes_change = false,
assets_change = false,
trusted_change = false; trusted_change = false;
result.data.reverse().forEach(data => { result.data.reverse().forEach(data => {
var content = JSON.parse(data)[floGlobals.application]; var content = JSON.parse(data)[floGlobals.application];
@ -42,20 +43,26 @@ function refreshDataFromBlockchain() {
nodes_change = true; nodes_change = true;
if (content.Nodes.remove) if (content.Nodes.remove)
for (let n of 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) if (content.Nodes.add)
for (let n in 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 //Trusted List
if (content.Trusted) { if (content.Trusted) {
trusted_change = true; trusted_change = true;
if (content.Trusted.remove) if (content.Trusted.remove)
for (let id of 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) if (content.Trusted.add)
for (let id of 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 //Tag List with priority and API
if (content.Tag) { 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(`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 //Check if all save process were successful
Promise.allSettled(promises).then(results => { Promise.allSettled(promises).then(results => {
console.debug(results.filter(r => r.status === "rejected")); console.debug(results.filter(r => r.status === "rejected"));
@ -80,6 +87,7 @@ function refreshDataFromBlockchain() {
}); });
resolve({ resolve({
nodes: nodes_change, nodes: nodes_change,
assets: assets_change,
trusted: trusted_change trusted: trusted_change
}); });
}).catch(error => reject(error)); }).catch(error => reject(error));
@ -92,6 +100,8 @@ function loadDataFromDB(changes, startup) {
let promises = []; let promises = [];
if (startup || changes.nodes) if (startup || changes.nodes)
promises.push(loadDataFromDB.nodeList()); promises.push(loadDataFromDB.nodeList());
if (startup || changes.assets)
promises.push(loadDataFromDB.assetList());
if (startup || changes.trusted) if (startup || changes.trusted)
promises.push(loadDataFromDB.trustedIDs()); promises.push(loadDataFromDB.trustedIDs());
Promise.all(promises) Promise.all(promises)
@ -102,7 +112,7 @@ function loadDataFromDB(changes, startup) {
loadDataFromDB.nodeList = function() { loadDataFromDB.nodeList = function() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
DB.query("SELECT * FROM nodeList").then(result => { DB.query("SELECT floID, uri FROM NodeList").then(result => {
let nodes = {} let nodes = {}
for (let i in result) for (let i in result)
nodes[result[i].floID] = result[i].uri; 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() { loadDataFromDB.trustedIDs = function() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
DB.query("SELECT * FROM trustedList").then(result => { DB.query("SELECT * FROM TrustedList").then(result => {
let trustedIDs = []; let trustedIDs = [];
for (let i in result) for (let i in result)
trustedIDs.push(result[i].floID); trustedIDs.push(result[i].floID);

View File

@ -3,7 +3,7 @@
const coupling = require('./coupling'); const coupling = require('./coupling');
const MINIMUM_BUY_REQUIREMENT = 0.1; 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) => { const getAssetBalance = (floID, asset) => new Promise((resolve, reject) => {
let promises = (asset === floGlobals.currency) ? [ let promises = (asset === floGlobals.currency) ? [
@ -63,7 +63,7 @@ function addSellOrder(floID, asset, quantity, min_price) {
return reject(INVALID(`Invalid quantity (${quantity})`)); return reject(INVALID(`Invalid quantity (${quantity})`));
else if (typeof min_price !== "number" || min_price <= 0) else if (typeof min_price !== "number" || min_price <= 0)
return reject(INVALID(`Invalid min_price (${min_price})`)); return reject(INVALID(`Invalid min_price (${min_price})`));
else if (!allowedAssets.includes(asset)) else if (!assetList.includes(asset))
return reject(INVALID(`Invalid asset (${asset})`)); return reject(INVALID(`Invalid asset (${asset})`));
getAssetBalance.check(floID, asset, quantity).then(_ => { getAssetBalance.check(floID, asset, quantity).then(_ => {
checkSellRequirement(floID).then(_ => { checkSellRequirement(floID).then(_ => {
@ -76,11 +76,11 @@ function addSellOrder(floID, asset, quantity, min_price) {
} }
const checkSellRequirement = floID => new Promise((resolve, reject) => { 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) if (result.length)
return resolve(true); return resolve(true);
//TODO: Should seller need to buy same type of asset before selling? //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) if (result[0].brought >= MINIMUM_BUY_REQUIREMENT)
resolve(true); resolve(true);
else else
@ -97,7 +97,7 @@ function addBuyOrder(floID, asset, quantity, max_price) {
return reject(INVALID(`Invalid quantity (${quantity})`)); return reject(INVALID(`Invalid quantity (${quantity})`));
else if (typeof max_price !== "number" || max_price <= 0) else if (typeof max_price !== "number" || max_price <= 0)
return reject(INVALID(`Invalid max_price (${max_price})`)); return reject(INVALID(`Invalid max_price (${max_price})`));
else if (!allowedAssets.includes(asset)) else if (!assetList.includes(asset))
return reject(INVALID(`Invalid asset (${asset})`)); return reject(INVALID(`Invalid asset (${asset})`));
getAssetBalance.check(floID, asset, quantity).then(_ => { getAssetBalance.check(floID, asset, quantity).then(_ => {
DB.query("INSERT INTO BuyOrder(floID, asset, quantity, maxPrice) VALUES (?, ?, ?, ?)", [floID, asset, quantity, max_price]) DB.query("INSERT INTO BuyOrder(floID, asset, quantity, maxPrice) VALUES (?, ?, ?, ?)", [floID, asset, quantity, max_price])
@ -163,7 +163,7 @@ function getAccountDetails(floID) {
break; 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) .then(result => response.transactions = result)
.catch(error => console.error(error)) .catch(error => console.error(error))
.finally(_ => resolve(response)); .finally(_ => resolve(response));
@ -173,7 +173,7 @@ function getAccountDetails(floID) {
function depositFLO(floID, txid) { function depositFLO(floID, txid) {
return new Promise((resolve, reject) => { 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) { if (result.length) {
switch (result[0].status) { switch (result[0].status) {
case "PENDING": case "PENDING":
@ -184,7 +184,7 @@ function depositFLO(floID, txid) {
return reject(INVALID("Transaction already used to add coins")); return reject(INVALID("Transaction already used to add coins"));
} }
} else } 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")) .then(result => resolve("Deposit request in process"))
.catch(error => reject(error)); .catch(error => reject(error));
}).catch(error => reject(error)) }).catch(error => reject(error))
@ -192,19 +192,19 @@ function depositFLO(floID, txid) {
} }
function confirmDepositFLO() { 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 => { results.forEach(req => {
confirmDepositFLO.checkTx(req.floID, req.txid).then(amount => { confirmDepositFLO.checkTx(req.floID, req.txid).then(amount => {
let txQueries = []; let txQueries = [];
txQueries.push(["INSERT INTO Vault(floID, quantity) VALUES (?, ?)", [req.floID, amount]]); 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) DB.transaction(txQueries)
.then(result => console.debug("FLO deposited:", req.floID, amount)) .then(result => console.debug("FLO deposited:", req.floID, amount))
.catch(error => console.error(error)) .catch(error => console.error(error))
}).catch(error => { }).catch(error => {
console.error(error); console.error(error);
if (error[0]) 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)); .then(_ => null).catch(error => console.error(error));
}); });
}) })
@ -247,12 +247,12 @@ function withdrawFLO(floID, amount) {
if (!txid) if (!txid)
throw Error("Transaction not successful"); throw Error("Transaction not successful");
//Transaction was successful, Add in DB //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)) .then(_ => null).catch(error => console.error(error))
.finally(_ => resolve("Withdrawal was successful")); .finally(_ => resolve("Withdrawal was successful"));
}).catch(error => { }).catch(error => {
console.debug(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)) .then(_ => null).catch(error => console.error(error))
.finally(_ => resolve("Withdrawal request is in process")); .finally(_ => resolve("Withdrawal request is in process"));
}); });
@ -263,13 +263,13 @@ function withdrawFLO(floID, amount) {
} }
function retryWithdrawalFLO() { 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 => { results.forEach(req => {
floBlockchainAPI.sendTx(global.myFloID, req.floID, req.amount, global.myPrivKey, 'Withdraw FLO Coins from Market').then(txid => { floBlockchainAPI.sendTx(global.myFloID, req.floID, req.amount, global.myPrivKey, 'Withdraw FLO Coins from Market').then(txid => {
if (!txid) if (!txid)
throw Error("Transaction not successful"); throw Error("Transaction not successful");
//Transaction was successful, Add in DB //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)); .then(_ => null).catch(error => console.error(error));
}).catch(error => console.error(error)); }).catch(error => console.error(error));
}) })
@ -277,12 +277,12 @@ function retryWithdrawalFLO() {
} }
function confirmWithdrawalFLO() { 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 => { results.forEach(req => {
floBlockchainAPI.getTx(req.txid).then(tx => { floBlockchainAPI.getTx(req.txid).then(tx => {
if (!tx.blockheight || !tx.confirmations) //Still not confirmed if (!tx.blockheight || !tx.confirmations) //Still not confirmed
return; 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)) .then(result => console.debug("FLO withdrawed:", req.floID, req.amount))
.catch(error => console.error(error)) .catch(error => console.error(error))
}).catch(error => console.error(error)); }).catch(error => console.error(error));
@ -292,7 +292,7 @@ function confirmWithdrawalFLO() {
function depositToken(floID, txid) { function depositToken(floID, txid) {
return new Promise((resolve, reject) => { 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) { if (result.length) {
switch (result[0].status) { switch (result[0].status) {
case "PENDING": case "PENDING":
@ -303,7 +303,7 @@ function depositToken(floID, txid) {
return reject(INVALID("Transaction already used to add tokens")); return reject(INVALID("Transaction already used to add tokens"));
} }
} else } 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")) .then(result => resolve("Deposit request in process"))
.catch(error => reject(error)); .catch(error => reject(error));
}).catch(error => reject(error)) }).catch(error => reject(error))
@ -311,10 +311,10 @@ function depositToken(floID, txid) {
} }
function confirmDepositToken() { 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 => { results.forEach(req => {
confirmDepositToken.checkTx(req.floID, req.txid).then(amounts => { 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 = [], let txQueries = [],
token_name = amounts[0], token_name = amounts[0],
amount_token = amounts[1]; amount_token = amounts[1];
@ -322,9 +322,9 @@ function confirmDepositToken() {
if (!result.length) { if (!result.length) {
let amount_flo = amounts[2]; let amount_flo = amounts[2];
txQueries.push(["INSERT INTO Vault(floID, asset, quantity) VALUES (?, ?, ?)", [req.floID, "FLO", amount_flo]]); 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) if (token_name === floGlobals.currency)
txQueries.push(["UPDATE Cash SET balance=balance+? WHERE floID=?", [amount_token, req.floID]]); txQueries.push(["UPDATE Cash SET balance=balance+? WHERE floID=?", [amount_token, req.floID]]);
else else
@ -336,7 +336,7 @@ function confirmDepositToken() {
}).catch(error => { }).catch(error => {
console.error(error); console.error(error);
if (error[0]) 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)); .then(_ => null).catch(error => console.error(error));
}); });
}) })
@ -353,7 +353,7 @@ confirmDepositToken.checkTx = function(sender, txid) {
return reject([true, "Transaction transfer is not 'token'"]); return reject([true, "Transaction transfer is not 'token'"]);
var token_name = tx.parsedFloData.tokenIdentification, var token_name = tx.parsedFloData.tokenIdentification,
amount_token = tx.parsedFloData.tokenAmount; 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"]); return reject([true, "Token not authorised"]);
let vin_sender = tx.transactionDetails.vin.filter(v => v.addr === sender) let vin_sender = tx.transactionDetails.vin.filter(v => v.addr === sender)
if (!vin_sender.length) if (!vin_sender.length)
@ -373,7 +373,7 @@ function withdrawToken(floID, token, amount) {
return reject(INVALID("Invalid FLO ID")); return reject(INVALID("Invalid FLO ID"));
else if (typeof amount !== "number" || amount <= 0) else if (typeof amount !== "number" || amount <= 0)
return reject(INVALID(`Invalid amount (${amount})`)); 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")); return reject(INVALID("Invalid Token"));
//Check for FLO balance (transaction fee) //Check for FLO balance (transaction fee)
const required_flo = floGlobals.sendAmt + floGlobals.fee; const required_flo = floGlobals.sendAmt + floGlobals.fee;
@ -383,15 +383,15 @@ function withdrawToken(floID, token, amount) {
consumeAsset(floID, token, amount, txQueries).then(txQueries => { consumeAsset(floID, token, amount, txQueries).then(txQueries => {
DB.transaction(txQueries).then(result => { DB.transaction(txQueries).then(result => {
//Send FLO to user via blockchain API //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"); if (!txid) throw Error("Transaction not successful");
//Transaction was successful, Add in DB //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)) .then(_ => null).catch(error => console.error(error))
.finally(_ => resolve("Withdrawal was successful")); .finally(_ => resolve("Withdrawal was successful"));
}).catch(error => { }).catch(error => {
console.debug(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)) .then(_ => null).catch(error => console.error(error))
.finally(_ => resolve("Withdrawal request is in process")); .finally(_ => resolve("Withdrawal request is in process"));
}); });
@ -404,13 +404,13 @@ function withdrawToken(floID, token, amount) {
} }
function retryWithdrawalToken() { 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 => { 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) if (!txid)
throw Error("Transaction not successful"); throw Error("Transaction not successful");
//Transaction was successful, Add in DB //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)); .then(_ => null).catch(error => console.error(error));
}).catch(error => console.error(error)); }).catch(error => console.error(error));
}); });
@ -418,10 +418,10 @@ function retryWithdrawalToken() {
} }
function confirmWithdrawalToken() { 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 => { results.forEach(req => {
tokenAPI.getTx(req.txid).then(tx => { 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)) .then(result => console.debug("Token withdrawed:", req.floID, req.token, req.amount))
.catch(error => console.error(error)); .catch(error => console.error(error));
}).catch(error => console.error(error)); }).catch(error => console.error(error));
@ -431,7 +431,7 @@ function confirmWithdrawalToken() {
function periodicProcess() { function periodicProcess() {
blockchainReCheck(); blockchainReCheck();
coupling.initiate(); assetList.forEach(asset => coupling.initiate(asset));
} }
function blockchainReCheck() { function blockchainReCheck() {
@ -461,8 +461,7 @@ module.exports = {
DB = db; DB = db;
coupling.DB = db; coupling.DB = db;
}, },
set allowedAssets(assets) { set assetList(assets) {
allowedAssets = Object.keys(assets); assetList = assets;
coupling.assetList = assets;
} }
}; };

View File

@ -19,7 +19,7 @@ const updateLastTime = asset => lastTime[asset] = Date.now();
//store FLO price in DB every 1 hr //store FLO price in DB every 1 hr
function storeRate(asset, rate) { 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)) .then(_ => null).catch(error => console.error(error))
} }
setInterval(() => { setInterval(() => {
@ -29,7 +29,7 @@ setInterval(() => {
function getPastRate(asset, hrs = 24) { function getPastRate(asset, hrs = 24) {
return new Promise((resolve, reject) => { 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')) .then(result => result.length ? resolve(result[0].rate) : reject('No records found in past 24hrs'))
.catch(error => reject(error)) .catch(error => reject(error))
}); });
@ -40,15 +40,18 @@ function loadRate(asset) {
if (typeof cur_rate[asset] !== "undefined") if (typeof cur_rate[asset] !== "undefined")
return resolve(cur_rate[asset]); return resolve(cur_rate[asset]);
updateLastTime(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) if (result.length)
resolve(cur_rate[asset] = result[0].rate); resolve(cur_rate[asset] = result[0].rate);
else 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)); }).catch(error => reject(error));
}) })
} }
/*
function fetchRates() { function fetchRates() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
fetchRates.FLO_USD().then(FLO_rate => { fetchRates.FLO_USD().then(FLO_rate => {
@ -87,6 +90,7 @@ fetchRates.USD_INR = function() {
}).catch(error => reject(error)); }).catch(error => reject(error));
}); });
} }
*/
function getRates(asset) { function getRates(asset) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -137,7 +141,7 @@ function checkForRatedSellers(asset) {
DB.query("SELECT MAX(sellPriority) as max_p FROM TagList").then(result => { DB.query("SELECT MAX(sellPriority) as max_p FROM TagList").then(result => {
let ratedMin = result[0].max_p * (1 - TOP_RANGE); let ratedMin = result[0].max_p * (1 - TOP_RANGE);
DB.query("SELECT COUNT(*) as value FROM SellOrder WHERE floID IN (" + 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 => { " WHERE TagList.sellPriority > ?)", [ratedMin]).then(result => {
resolve(result[0].value > 0); resolve(result[0].value > 0);
}).catch(error => reject(error)) }).catch(error => reject(error))

View File

@ -30,7 +30,7 @@ function validateRequestFromFloID(request, sign, floID, proxy = true) {
return reject(INVALID(INVALID_SERVER_MSG)); return reject(INVALID(INVALID_SERVER_MSG));
else if (!floCrypto.validateAddr(floID)) else if (!floCrypto.validateAddr(floID))
return reject(INVALID("Invalid 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) if (result.length < 1)
return reject(INVALID(proxy ? "Session not active" : "User not registered")); return reject(INVALID(proxy ? "Session not active" : "User not registered"));
if (proxy && result[0].session_time + maxSessionTimeout < Date.now()) if (proxy && result[0].session_time + maxSessionTimeout < Date.now())
@ -113,7 +113,7 @@ function Login(req, res) {
proxyKey: data.proxyKey, proxyKey: data.proxyKey,
timestamp: data.timestamp timestamp: data.timestamp
}, data.sign, data.floID, false).then(req_str => { }, 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", "ON DUPLICATE KEY UPDATE session_time=DEFAULT, proxyKey=new.proxyKey",
[data.floID, data.proxyKey]).then(_ => { [data.floID, data.proxyKey]).then(_ => {
storeRequest(data.floID, req_str, data.sign); storeRequest(data.floID, req_str, data.sign);
@ -138,7 +138,7 @@ function Logout(req, res) {
type: "logout", type: "logout",
timestamp: data.timestamp timestamp: data.timestamp
}, data.sign, data.floID).then(req_str => { }, 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); storeRequest(data.floID, req_str, data.sign);
res.send('Logout successful'); res.send('Logout successful');
}).catch(error => { }).catch(error => {
@ -263,7 +263,7 @@ function ListBuyOrders(req, res) {
function ListTransactions(req, res) { function ListTransactions(req, res) {
//TODO: Limit size (recent) //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)) .then(result => res.send(result))
.catch(error => res.status(INTERNAL.e_code).send("Try again later!")); .catch(error => res.status(INTERNAL.e_code).send("Try again later!"));
} }
@ -496,6 +496,9 @@ module.exports = {
set trustedIDs(ids) { set trustedIDs(ids) {
trustedIDs = ids; trustedIDs = ids;
}, },
set assetList(assets){
market.assetList = assets;
},
set DB(db) { set DB(db) {
DB = db; DB = db;
market.DB = db; market.DB = db;

View File

@ -35,7 +35,7 @@
}).catch(error => reject(error)) }).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) => { return new Promise((resolve, reject) => {
let senderID = floCrypto.getFloID(privKey); let senderID = floCrypto.getFloID(privKey);
if (typeof amount !== "number" || amount <= 0) if (typeof amount !== "number" || amount <= 0)