Merge branch 'sairajzero:main' into main
This commit is contained in:
commit
d7283fb13b
5
.gitignore
vendored
5
.gitignore
vendored
@ -1,7 +1,6 @@
|
||||
/node_modules/
|
||||
/package-lock.json
|
||||
/args/app-config.json
|
||||
/args/backup-config.json
|
||||
/args/config*.json
|
||||
/args/param.json
|
||||
/args/keys.json
|
||||
/args/keys*.json
|
||||
*test*
|
||||
@ -113,6 +113,12 @@ 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,
|
||||
@ -121,11 +127,11 @@ PRIMARY KEY(floID)
|
||||
|
||||
CREATE TABLE trustedList(
|
||||
floID CHAR(34) NOT NULL,
|
||||
FOREIGN KEY (floID) REFERENCES Users(floID),
|
||||
PRIMARY KEY(floID),
|
||||
FOREIGN KEY (floID) REFERENCES Users(floID)
|
||||
);
|
||||
|
||||
CREATE TABLE TagList (
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
tag VARCHAR(50) NOT NULL,
|
||||
sellPriority INT,
|
||||
buyPriority INT,
|
||||
@ -171,7 +177,7 @@ CREATE TABLE sinkShares(
|
||||
floID CHAR(34) NOT NULL,
|
||||
share TEXT,
|
||||
time_ DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY(floID, share)
|
||||
PRIMARY KEY(floID)
|
||||
);
|
||||
|
||||
/* Backup feature (Table and Triggers) */
|
||||
|
||||
@ -19,9 +19,6 @@
|
||||
"configure": "node setup/configure-settings.js",
|
||||
"reset-password": "node setup/reset-password.js",
|
||||
"create-schema": "node setup/create-schema.js",
|
||||
"configure-backup": "node setup/configure-backup.js",
|
||||
"create-backup-schema": "node setup/create-backup-schema.js",
|
||||
"backup": "node src/backup/storage.js",
|
||||
"start": "node start.js"
|
||||
},
|
||||
"repository": {
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
(function(){
|
||||
/*Kademlia DHT K-bucket implementation as a binary tree.*/
|
||||
/**
|
||||
* Implementation of a Kademlia DHT k-bucket used for storing
|
||||
@ -7,7 +8,7 @@
|
||||
*
|
||||
* @extends EventEmitter
|
||||
*/
|
||||
function BuildKBucket(options = {}) {
|
||||
function BuildKBucket(options = {}) {
|
||||
/**
|
||||
* `options`:
|
||||
* `distance`: Function
|
||||
@ -401,7 +402,7 @@ function BuildKBucket(options = {}) {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = function K_Bucket(masterID, backupList) {
|
||||
function K_Bucket(masterID, backupList) {
|
||||
const decodeID = function(floID) {
|
||||
let k = bitjs.Base58.decode(floID);
|
||||
k.shift();
|
||||
@ -457,4 +458,6 @@ module.exports = function K_Bucket(masterID, backupList) {
|
||||
return (N == 1 ? nNodes[0] : nNodes);
|
||||
};
|
||||
|
||||
}
|
||||
};
|
||||
('object' === typeof module) ? module.exports = K_Bucket : window.K_Bucket = K_Bucket;
|
||||
})();
|
||||
17
public/fn.js
17
public/fn.js
@ -6,10 +6,9 @@ function exchangeAPI(api, options) {
|
||||
let curPos = exchangeAPI.curPos || 0;
|
||||
if (curPos >= nodeList.length)
|
||||
return resolve('No Nodes online');
|
||||
let url = nodeURL[nodeList[curPos]];
|
||||
let url = "http://" + nodeURL[nodeList[curPos]];
|
||||
(options ? fetch(url + api, options) : fetch(url + api))
|
||||
.then(result => resolve(result)).catch(error => {
|
||||
console.debug(error);
|
||||
console.warn(nodeList[curPos], 'is offline');
|
||||
//try next node
|
||||
exchangeAPI.curPos = curPos + 1;
|
||||
@ -102,7 +101,7 @@ function getAccount(floID, proxySecret) {
|
||||
};
|
||||
request.sign = signRequest({
|
||||
type: "get_account",
|
||||
timestamp: data.timestamp
|
||||
timestamp: request.timestamp
|
||||
}, proxySecret);
|
||||
console.debug(request);
|
||||
|
||||
@ -168,7 +167,7 @@ function signRequest(request, privKey) {
|
||||
|
||||
function getLoginCode() {
|
||||
return new Promise((resolve, reject) => {
|
||||
exchangeAPI('/list-buyorders')
|
||||
exchangeAPI('/get-login-code')
|
||||
.then(result => responseParse(result)
|
||||
.then(result => resolve(result))
|
||||
.catch(error => reject(error)))
|
||||
@ -249,7 +248,7 @@ function logout(floID, proxySecret) {
|
||||
};
|
||||
request.sign = signRequest({
|
||||
type: "logout",
|
||||
timestamp: data.timestamp
|
||||
timestamp: request.timestamp
|
||||
}, proxySecret);
|
||||
console.debug(request);
|
||||
|
||||
@ -543,8 +542,8 @@ function refreshDataFromBlockchain() {
|
||||
return new Promise((resolve, reject) => {
|
||||
let nodes, lastTx;
|
||||
try {
|
||||
nodes = JSON.parse(localStorage.getItems('exhange-nodes'));
|
||||
if (typeof nodes !== 'object')
|
||||
nodes = JSON.parse(localStorage.getItem('exchange-nodes'));
|
||||
if (typeof nodes !== 'object' || nodes === null)
|
||||
throw Error('nodes must be an object')
|
||||
else
|
||||
lastTx = parseInt(localStorage.getItem('exchange-lastTx')) || 0;
|
||||
@ -569,8 +568,8 @@ function refreshDataFromBlockchain() {
|
||||
nodes[n] = content.Nodes.add[n];
|
||||
}
|
||||
});
|
||||
localStorage.setItem('exhange-lastTx', result.totalTxs);
|
||||
localStorage.setItem('exhange-nodes', JSON.stringify(nodes));
|
||||
localStorage.setItem('exchange-lastTx', result.totalTxs);
|
||||
localStorage.setItem('exchange-nodes', JSON.stringify(nodes));
|
||||
nodeURL = nodes;
|
||||
nodeKBucket = new K_Bucket(floGlobals.adminID, Object.keys(nodeURL));
|
||||
nodeList = nodeKBucket.order;
|
||||
|
||||
@ -12,27 +12,10 @@
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" rel="stylesheet">
|
||||
<script id="floGlobals">
|
||||
/* Constants for FLO blockchain operations !!Make sure to add this at beginning!! */
|
||||
const floGlobals = {
|
||||
|
||||
//Required for all
|
||||
blockchain: "FLO",
|
||||
|
||||
//Required for blockchain API operators
|
||||
apiURL: {
|
||||
FLO: ['https://livenet.flocha.in/', 'https://flosight.duckdns.org/'],
|
||||
FLO_TEST: ['https://testnet-flosight.duckdns.org/', 'https://testnet.flocha.in/']
|
||||
},
|
||||
tokenURL: "https://ranchimallflo.duckdns.org/",
|
||||
token: "rupee",
|
||||
adminID: "FKAEdnPfjXLHSYwrXQu377ugN4tXU7VGdf",
|
||||
sendAmt: 0.001,
|
||||
fee: 0.0005,
|
||||
}
|
||||
</script>
|
||||
<script src="floGlobals.js"></script>
|
||||
<script src="https://sairajzero.github.io/Standard_Operations/cdn/floCrypto.js"></script>
|
||||
<script src="https://github.com/sairajzero/Standard_Operations/releases/download/test/floBlockchainAPI.js"></script>
|
||||
<script src="KBucket.js"></script>
|
||||
<script src="fn.js"></script>
|
||||
</head>
|
||||
|
||||
@ -1068,9 +1051,9 @@
|
||||
showProcess('trade_button_wrapper')
|
||||
try {
|
||||
if (tradeType === 'buy') {
|
||||
await buy(quantity, price, await proxy.secret)
|
||||
await buy(quantity, price, proxy.userID, await proxy.secret)
|
||||
} else {
|
||||
await sell(quantity, price, await proxy.secret)
|
||||
await sell(quantity, price, proxy.userID, await proxy.secret)
|
||||
}
|
||||
getRef('trade_button_wrapper').append(getRef('success_template').content.cloneNode(true))
|
||||
notify(`Placed ${tradeType} order`, 'success')
|
||||
@ -1218,9 +1201,9 @@
|
||||
showWalletResult('success', `Sent ${asset} deposit request`, 'This may take upto 30 mins to reflect in your wallet.')
|
||||
} else {
|
||||
if (asset === 'FLO') {
|
||||
await withdrawFLO(quantity, proxySecret)
|
||||
await withdrawFLO(quantity, proxy.userID, proxySecret)
|
||||
} else {
|
||||
await withdrawRupee(quantity, proxySecret)
|
||||
await withdrawRupee(quantity, proxy.userID, proxySecret)
|
||||
}
|
||||
showWalletResult('success', `Sent ${asset} withdraw request`, 'This may take upto 30 mins to reflect in your wallet.')
|
||||
}
|
||||
@ -1363,7 +1346,7 @@
|
||||
const target = e.target.closest('.order-card')
|
||||
const id = target.dataset.id
|
||||
const type = target.dataset.type
|
||||
cancelOrder(type, id, await proxy.secret)
|
||||
cancelOrder(type, id, proxy.userID, await proxy.secret)
|
||||
.then(() => {
|
||||
notify('Order cancelled', 'success')
|
||||
target.animate([
|
||||
@ -1415,7 +1398,7 @@
|
||||
if (res) {
|
||||
try {
|
||||
const proxy_secret = await proxy.secret;
|
||||
const promises = [...selectedOrders].map(([id, type]) => cancelOrder(type, id, proxy_secret))
|
||||
const promises = [...selectedOrders].map(([id, type]) => cancelOrder(type, id, proxy.userID, proxy_secret))
|
||||
await Promise.all(promises)
|
||||
selectedOrders.clear()
|
||||
hideMyOrdersOptions()
|
||||
@ -1687,7 +1670,7 @@
|
||||
const balance = {}
|
||||
|
||||
let accountDetails = {}
|
||||
function account() {
|
||||
async function account() {
|
||||
getAccount(proxy.userID, await proxy.secret).then(acc => {
|
||||
getRef("login_form").classList.add('hide-completely')
|
||||
getRef('home').classList.add('signed-in')
|
||||
@ -1778,7 +1761,7 @@
|
||||
refreshDataFromBlockchain().then(nodes => {
|
||||
console.log(nodes);
|
||||
refresh(true);
|
||||
}).catch(error => reject(error))
|
||||
}).catch(error => console.error(error))
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
|
||||
@ -1,100 +0,0 @@
|
||||
const fs = require('fs');
|
||||
const getInput = require('./getInput');
|
||||
|
||||
var config, flag_new;
|
||||
try {
|
||||
config = require('../args/backup-config.json');
|
||||
flag_new = false;
|
||||
} catch (error) {
|
||||
config = {
|
||||
"sql_user": null,
|
||||
"sql_pwd": null,
|
||||
"sql_db": "exchange",
|
||||
"sql_host": "localhost",
|
||||
|
||||
"main_server_url": null,
|
||||
"private_key": null
|
||||
};
|
||||
flag_new = true;
|
||||
}
|
||||
|
||||
function flaggedYesOrNo(text) {
|
||||
return new Promise((resolve) => {
|
||||
if (flag_new)
|
||||
resolve(true);
|
||||
else
|
||||
getInput.YesOrNo(text)
|
||||
.then(result => resolve(result))
|
||||
.catch(error => reject(error))
|
||||
})
|
||||
}
|
||||
|
||||
function configureMainServerURL() {
|
||||
return new Promise(resolve => {
|
||||
getInput.Text('Enter URL of main server', config["main_server_url"]).then(url => {
|
||||
config["main_server_url"] = url;
|
||||
resolve(true);
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function configureSQL() {
|
||||
return new Promise(resolve => {
|
||||
flaggedYesOrNo('Do you want to re-configure mySQL connection').then(value => {
|
||||
if (value) {
|
||||
console.log('Enter mySQL connection values: ')
|
||||
getInput.Text('Host', config['sql_host']).then(host => {
|
||||
config['sql_host'] = host;
|
||||
getInput.Text('Database name', config['sql_db']).then(dbname => {
|
||||
config['sql_db'] = dbname;
|
||||
getInput.Text('MySQL username', config['sql_user']).then(sql_user => {
|
||||
config['sql_user'] = sql_user;
|
||||
getInput.Text('Mysql password', config['sql_pwd']).then(sql_pwd => {
|
||||
config['sql_pwd'] = sql_pwd;
|
||||
resolve(true);
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
} else
|
||||
resolve(false);
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function configure() {
|
||||
return new Promise((resolve, reject) => {
|
||||
configureMainServerURL().then(port_result => {
|
||||
configureSQL().then(sql_result => {
|
||||
fs.writeFile(__dirname + '/../args/backup-config.json', JSON.stringify(config), 'utf8', (err) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return reject(false);
|
||||
}
|
||||
console.log('Configuration successful!');
|
||||
if (sql_result) {
|
||||
getInput.YesOrNo('Do you want to create schema in the database').then(value => {
|
||||
if (value) {
|
||||
const createSchema = require('./create-schema');
|
||||
createSchema(false).then(result => resolve(result))
|
||||
.catch(error => {
|
||||
console.log('Retry using: \n' + 'npm run create-backup-schema');
|
||||
reject(error);
|
||||
});
|
||||
} else {
|
||||
console.log('To create schema, use: \n' + 'npm run create-backup-schema');
|
||||
resolve(true);
|
||||
}
|
||||
});
|
||||
} else
|
||||
resolve(true);
|
||||
})
|
||||
})
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
if (!module.parent)
|
||||
configure().then(_ => null).catch(_ => null);
|
||||
else
|
||||
module.exports = configure;
|
||||
@ -3,7 +3,7 @@ const getInput = require('./getInput');
|
||||
|
||||
var config, flag_new;
|
||||
try {
|
||||
config = require('../args/app-config.json');
|
||||
config = require(`../args/config${process.env.I || ""}.json`);
|
||||
flag_new = false;
|
||||
} catch (error) {
|
||||
config = {
|
||||
@ -13,12 +13,7 @@ try {
|
||||
"sql_user": null,
|
||||
"sql_pwd": null,
|
||||
"sql_db": "exchange",
|
||||
"sql_host": "localhost",
|
||||
|
||||
"backup-port": "8081",
|
||||
"backup-floIDs": [],
|
||||
|
||||
"trusted-floIDs": []
|
||||
"sql_host": "localhost"
|
||||
};
|
||||
flag_new = true;
|
||||
}
|
||||
@ -34,97 +29,11 @@ function flaggedYesOrNo(text) {
|
||||
})
|
||||
}
|
||||
|
||||
function get_IDs(ids) {
|
||||
return new Promise((resolve, reject) => {
|
||||
getInput.Text("", "continue").then(id => {
|
||||
if (id === "continue")
|
||||
resolve(Array.from(new Set(ids)));
|
||||
else {
|
||||
ids.push(id);
|
||||
get_IDs(ids)
|
||||
.then(result => resolve(result))
|
||||
.catch(error => reject(error));
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function configureBackup() {
|
||||
return new Promise(resolve => {
|
||||
getInput.Text('Enter backup port (N = No backup)', config["backup-port"]).then(backup_port => {
|
||||
config["backup-port"] = (backup_port === 'N' || backup_port === 'n') ? null : backup_port;
|
||||
if (!config["backup-port"])
|
||||
return resolve(true);
|
||||
getInput.YesOrNo('Do you want to add/remove backup floIDs?').then(value => {
|
||||
if (value) {
|
||||
console.log("Enter floIDs to add as backup: ");
|
||||
get_IDs(config["backup-floIDs"]).then(ids => {
|
||||
//delete backup IDs
|
||||
let tmp_obj = {};
|
||||
for (let i in ids) {
|
||||
console.log(i + 1, ":", ids[i]);
|
||||
tmp_obj[i + 1] = ids[i];
|
||||
}
|
||||
getInput.Text("Enter numbers to delete (seperated by comma)", "continue").then(ri => {
|
||||
if (ri === "continue")
|
||||
config["backup-floIDs"] = ids;
|
||||
else {
|
||||
for (let i of ri.split(","))
|
||||
delete tmp_obj[parseInt(i)];
|
||||
let tmp_array = [];
|
||||
for (let id of tmp_obj)
|
||||
tmp_array.push(id);
|
||||
config["backup-floIDs"] = tmp_array;
|
||||
}
|
||||
resolve(true);
|
||||
})
|
||||
})
|
||||
} else
|
||||
resolve(true);
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function configureTrustedIDs() {
|
||||
return new Promise((resolve, reject) => {
|
||||
getInput.YesOrNo('Do you want to add/remove trusted floIDs?').then(value => {
|
||||
if (value) {
|
||||
console.log("Enter floIDs to add as trusted: ");
|
||||
get_IDs(config["trusted-floIDs"]).then(ids => {
|
||||
//delete trusted IDs
|
||||
let tmp_obj = {};
|
||||
for (let i in ids) {
|
||||
console.log(i + 1, ":", ids[i]);
|
||||
tmp_obj[i + 1] = ids[i];
|
||||
}
|
||||
getInput.Text("Enter numbers to delete (seperated by comma)", "continue").then(ri => {
|
||||
if (ri === "continue")
|
||||
config["trusted-floIDs"] = ids;
|
||||
else {
|
||||
for (let i of ri.split(","))
|
||||
delete tmp_obj[parseInt(i)];
|
||||
let tmp_array = [];
|
||||
for (let id of tmp_obj)
|
||||
tmp_array.push(id);
|
||||
config["trusted-floIDs"] = tmp_array;
|
||||
}
|
||||
resolve(true);
|
||||
})
|
||||
})
|
||||
} else
|
||||
resolve(true);
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function configurePort() {
|
||||
return new Promise(resolve => {
|
||||
getInput.Text('Enter port', config["port"]).then(port => {
|
||||
config["port"] = port;
|
||||
configureBackup()
|
||||
.then(_ => configureTrustedIDs()
|
||||
.then(_ => resolve(true)));
|
||||
resolve(true);
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -175,7 +84,7 @@ function configure() {
|
||||
configurePort().then(port_result => {
|
||||
randomizeSessionSecret().then(secret_result => {
|
||||
configureSQL().then(sql_result => {
|
||||
fs.writeFile(__dirname + '/../args/app-config.json', JSON.stringify(config), 'utf8', (err) => {
|
||||
fs.writeFile(__dirname + `/../args/config${process.env.I || ""}.json`, JSON.stringify(config), 'utf8', (err) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return reject(false);
|
||||
@ -205,6 +114,6 @@ function configure() {
|
||||
}
|
||||
|
||||
if (!module.parent)
|
||||
configure().then(_ => null).catch(_ => null);
|
||||
configure().then(_ => null).catch(error => console.error(error));
|
||||
else
|
||||
module.exports = configure;
|
||||
@ -1,2 +0,0 @@
|
||||
const createSchema = require('./create-schema');
|
||||
createSchema(false);
|
||||
@ -1,8 +1,8 @@
|
||||
const fs = require('fs');
|
||||
let Database = require('../src/database');
|
||||
|
||||
function createSchema(app = true) {
|
||||
const config = require('../args/' + (app ? 'app' : 'backup') + "-config.json");
|
||||
function createSchema() {
|
||||
const config = require(`../args/config${process.env.I || ""}.json`);
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.readFile(__dirname + '/../args/schema.sql', 'utf8', (err, data) => {
|
||||
if (err) {
|
||||
|
||||
@ -10,10 +10,15 @@ console.log(__dirname);
|
||||
|
||||
function validateKey(privKey) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (floCrypto.verifyPrivKey(privKey, floGlobals.adminID))
|
||||
try {
|
||||
if (!privKey || privKey === "")
|
||||
throw 'Private Key cannot be empty!';
|
||||
let floID = floCrypto.getFloID(privKey);
|
||||
if (!floID || !floCrypto.verifyPrivKey(privKey, floID))
|
||||
throw 'Invalid Private Key!';
|
||||
return resolve(privKey);
|
||||
else {
|
||||
getInput.Text('Incorrect Private Key! Re-Enter: (Cancel)', 'Cancel').then(value => {
|
||||
} catch (error) {
|
||||
getInput.Text(error + ' Re-Enter: (Cancel)', 'Cancel').then(value => {
|
||||
if (value === 'Cancel')
|
||||
return reject(true);
|
||||
validateKey(value)
|
||||
@ -41,7 +46,7 @@ function getPassword() {
|
||||
getPassword()
|
||||
.then(result => resolve(result))
|
||||
.catch(error => reject(error))
|
||||
} else
|
||||
} else
|
||||
resolve(value1);
|
||||
})
|
||||
}
|
||||
@ -51,13 +56,13 @@ function getPassword() {
|
||||
|
||||
function resetPassword() {
|
||||
return new Promise((resolve, reject) => {
|
||||
getInput.Text(`Enter private key for adminID (${floGlobals.adminID})`).then(value => {
|
||||
getInput.Text(`Enter private key`).then(value => {
|
||||
validateKey(value).then(privKey => {
|
||||
getPassword().then(password => {
|
||||
let encrypted = Crypto.AES.encrypt(privKey, password);
|
||||
let randNum = floCrypto.randInt(10, 15);
|
||||
let splitShares = floCrypto.createShamirsSecretShares(encrypted, randNum, randNum);
|
||||
fs.writeFile(__dirname + '/../args/keys.json', JSON.stringify(splitShares), 'utf8', (err) => {
|
||||
fs.writeFile(__dirname + `/../args/keys${process.env.I || ""}.json`, JSON.stringify(splitShares), 'utf8', (err) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return reject(false);
|
||||
|
||||
14
src/app.js
14
src/app.js
@ -37,6 +37,16 @@ module.exports = function App(secret, DB) {
|
||||
}));
|
||||
*/
|
||||
|
||||
app.use(function(req, res, next) {
|
||||
res.setHeader('Access-Control-Allow-Origin', "*");
|
||||
// Request methods you wish to allow
|
||||
res.setHeader('Access-Control-Allow-Methods', 'GET, POST');
|
||||
// Request headers you wish to allow
|
||||
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
|
||||
// Pass to next layer of middleware
|
||||
next();
|
||||
})
|
||||
|
||||
//get code for login or signup
|
||||
app.get('/get-login-code', Request.getLoginCode);
|
||||
|
||||
@ -47,7 +57,7 @@ module.exports = function App(secret, DB) {
|
||||
app.post('/login', Request.Login);
|
||||
|
||||
//logout request
|
||||
app.get('/logout', Request.Logout);
|
||||
app.post('/logout', Request.Logout);
|
||||
|
||||
//place sell or buy order
|
||||
app.post('/buy', Request.PlaceBuyOrder);
|
||||
@ -65,7 +75,7 @@ module.exports = function App(secret, DB) {
|
||||
app.get('/get-rate', Request.getRate)
|
||||
|
||||
//get account details
|
||||
app.get('/account', Request.Account);
|
||||
app.post('/account', Request.Account);
|
||||
|
||||
//withdraw and deposit request
|
||||
app.post('/deposit-flo', Request.DepositFLO);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
const K_Bucket = require('./KBucket');
|
||||
const K_Bucket = require('../../public/KBucket');
|
||||
const slave = require('./slave');
|
||||
const WebSocket = require('ws');
|
||||
const shareThreshold = 50 / 100;
|
||||
@ -140,11 +140,13 @@ function send_dataImmutable(timestamp, ws) {
|
||||
//Shares
|
||||
function generateNewSink() {
|
||||
let sink = floCrypto.generateNewID();
|
||||
let nextNodes = KB.nextNode(global.myFloID, null);
|
||||
let shares = floCrypto.createShamirsSecretShares(sink.privKey, nextNodes.length, Math.ceil(nextNodes.length * shareThreshold));
|
||||
sink.shares = {};
|
||||
for (let i in nextNodes)
|
||||
sink.shares[nextNodes[i]] = shares[i];
|
||||
let nextNodes = nodeKBucket.nextNode(global.myFloID, null);
|
||||
if (nextNodes.length) {
|
||||
let shares = floCrypto.createShamirsSecretShares(sink.privKey, nextNodes.length, Math.ceil(nextNodes.length * shareThreshold));
|
||||
for (let i in nextNodes)
|
||||
sink.shares[nextNodes[i]] = shares[i];
|
||||
}
|
||||
return sink;
|
||||
}
|
||||
|
||||
@ -212,20 +214,20 @@ function collectShares(floID, sinkID, share) {
|
||||
function connectWS(floID) {
|
||||
let url = nodeURL[floID];
|
||||
return new Promise((resolve, reject) => {
|
||||
const ws = new WebSocket(url);
|
||||
const ws = new WebSocket('ws://' + url);
|
||||
ws.on('open', _ => resolve(ws));
|
||||
ws.on('error', _ => reject(error));
|
||||
ws.on('error', error => reject(error));
|
||||
})
|
||||
}
|
||||
|
||||
function connectToMaster(i = 0) {
|
||||
function connectToMaster(i = 0, init = false) {
|
||||
if (i >= nodeList.length) {
|
||||
console.error("No master is found, and myFloID is not in list. This should not happen!");
|
||||
process.exit(1);
|
||||
}
|
||||
let floID = nodeList[i];
|
||||
if (floID === myFloID)
|
||||
serveAsMaster();
|
||||
serveAsMaster(init);
|
||||
else
|
||||
connectWS(floID).then(ws => {
|
||||
ws.floID = floID;
|
||||
@ -233,26 +235,27 @@ function connectToMaster(i = 0) {
|
||||
serveAsSlave(ws);
|
||||
}).catch(error => {
|
||||
console.log(`Node(${floID}) is offline`);
|
||||
connectToMaster(i + 1)
|
||||
connectToMaster(i + 1, init)
|
||||
});
|
||||
}
|
||||
|
||||
//Node becomes master
|
||||
function serveAsMaster() {
|
||||
app.resume();
|
||||
function serveAsMaster(init) {
|
||||
console.debug('Starting master process');
|
||||
slave.stop();
|
||||
mod = MASTER_MODE;
|
||||
informLiveNodes();
|
||||
collectShares.active = true;
|
||||
informLiveNodes(init);
|
||||
app.resume();
|
||||
}
|
||||
|
||||
function serveAsSlave(ws) {
|
||||
console.debug('Starting slave process');
|
||||
app.pause();
|
||||
slave.start(ws);
|
||||
mod = SLAVE_MODE;
|
||||
}
|
||||
|
||||
function informLiveNodes() {
|
||||
function informLiveNodes(init) {
|
||||
let message = {
|
||||
floID: global.myFloID,
|
||||
type: "UPDATE_MASTER",
|
||||
@ -261,12 +264,34 @@ function informLiveNodes() {
|
||||
};
|
||||
message.sign = floCrypto.signData(message.type + "|" + message.req_time, global.myPrivKey);
|
||||
message = JSON.stringify(message);
|
||||
for (let n in nodeURL)
|
||||
if (n !== global.myFloID)
|
||||
connectWS(n).then(ws => {
|
||||
let nodes = nodeList.filter(n => n !== global.myFloID);
|
||||
Promise.allSettled(nodes.map(n => connectWS(n))).then(result => {
|
||||
let flag = false;
|
||||
for (let i in result)
|
||||
if (result[i].status === "fulfilled") {
|
||||
let ws = result[i].value;
|
||||
ws.send(message);
|
||||
ws.close();
|
||||
}).catch(error => console.warn(`Node ${n} is offline`));
|
||||
flag = true;
|
||||
} else
|
||||
console.warn(`Node(${nodes[i]}) is offline`);
|
||||
if (init) {
|
||||
if (flag === true)
|
||||
collectShares.active = true;
|
||||
else {
|
||||
//No other node is active (possible 1st node to start exchange)
|
||||
console.debug("Starting the exchange...")
|
||||
let newSink = generateNewSink();
|
||||
storeSink(newSink.floID, newSink.privKey);
|
||||
sendSharesToNodes(newSink.floID, newSink.shares);
|
||||
}
|
||||
} else {
|
||||
collectShares.active = true;
|
||||
DB.query("SELECT floID, share FROM sinkShares ORDER BY time_ DESC LIMIT 1")
|
||||
.then(result => collectShares(global.myFloID, result[0].floID, result[0].share))
|
||||
.catch(error => console.error(error))
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function updateMaster(floID) {
|
||||
@ -343,7 +368,7 @@ function startBackupTransmitter(server) {
|
||||
function initProcess(a) {
|
||||
app = a;
|
||||
startBackupTransmitter(app.server);
|
||||
connectToMaster();
|
||||
connectToMaster(0, true);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
@ -352,6 +377,7 @@ module.exports = {
|
||||
nodeURL = list;
|
||||
nodeKBucket = new K_Bucket(floGlobals.adminID, Object.keys(nodeURL));
|
||||
nodeList = nodeKBucket.order;
|
||||
console.debug(nodeList);
|
||||
},
|
||||
set DB(db) {
|
||||
DB = db;
|
||||
|
||||
34
src/main.js
34
src/main.js
@ -1,5 +1,4 @@
|
||||
'use strict';
|
||||
const config = require('../args/app-config.json');
|
||||
global.floGlobals = require('../public/floGlobals');
|
||||
require('./set_globals');
|
||||
require('./lib');
|
||||
@ -9,7 +8,6 @@ require('./tokenAPI');
|
||||
|
||||
const Database = require("./database");
|
||||
const App = require('./app');
|
||||
const PORT = config['port'];
|
||||
|
||||
const backup = require('./backup/head');
|
||||
|
||||
@ -47,7 +45,7 @@ function refreshDataFromBlockchain() {
|
||||
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 (?,?) 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]]));
|
||||
}
|
||||
//Trusted List
|
||||
if (content.Trusted) {
|
||||
@ -57,7 +55,7 @@ function refreshDataFromBlockchain() {
|
||||
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 (?) 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) {
|
||||
@ -66,16 +64,17 @@ function refreshDataFromBlockchain() {
|
||||
promises.push(DB.query("DELETE FROM TagList WHERE tag=?", [t]));
|
||||
if (content.Tag.add)
|
||||
for (let t in content.Tag.add)
|
||||
promises.push(DB.query("INSERT INTO TagList (tag, sellPriority, buyPriority, api) VALUE (?,?,?,?)", [t, content.Tag.add[t].sellPriority, content.Tag.add[t].buyPriority, content.Tag.add[t].api]));
|
||||
promises.push(DB.query("INSERT INTO TagList (tag, sellPriority, buyPriority, api) VALUE (?,?,?,?) AS new ON DUPLICATE KEY UPDATE tag=new.tag", [t, content.Tag.add[t].sellPriority, content.Tag.add[t].buyPriority, content.Tag.add[t].api]));
|
||||
if (content.Tag.update)
|
||||
for (let t in content.Tag.update)
|
||||
for (let a in content.Tag.update[t])
|
||||
promises.push(`UPDATE TagList WHERE tag=? SET ${a}=?`, [t, content.Tag.update[t][a]]);
|
||||
}
|
||||
});
|
||||
promises.push(DB.query("INSERT INTO lastTx (floID, num) VALUE (?, ?) 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"));
|
||||
if (results.reduce((a, r) => r.status === "rejected" ? ++a : a, 0))
|
||||
console.warn("Some data might not have been saved in database correctly");
|
||||
});
|
||||
@ -94,7 +93,7 @@ function loadDataFromDB(changes, startup) {
|
||||
if (startup || changes.nodes)
|
||||
promises.push(loadDataFromDB.nodeList());
|
||||
if (startup || changes.trusted)
|
||||
promises.push(loadDataFromDB.trustedIDs);
|
||||
promises.push(loadDataFromDB.trustedIDs());
|
||||
Promise.all(promises)
|
||||
.then(_ => resolve("Data load successful"))
|
||||
.catch(error => reject(error))
|
||||
@ -103,7 +102,7 @@ function loadDataFromDB(changes, startup) {
|
||||
|
||||
loadDataFromDB.nodeList = function() {
|
||||
return new Promise((resolve, reject) => {
|
||||
DB.query("SELECT (floID, uri) FROM nodeList").then(result => {
|
||||
DB.query("SELECT * FROM nodeList").then(result => {
|
||||
let nodes = {}
|
||||
for (let i in result)
|
||||
nodes[result[i].floID] = result[i].uri;
|
||||
@ -133,23 +132,20 @@ function setDB(db) {
|
||||
}
|
||||
|
||||
module.exports = function startServer(public_dir) {
|
||||
const config = require(`../args/config${process.env.I || ""}.json`);
|
||||
try {
|
||||
var _tmp = require('../args/keys.json');
|
||||
var _tmp = require(`../args/keys${process.env.I || ""}.json`);
|
||||
_tmp = floCrypto.retrieveShamirSecret(_tmp);
|
||||
var _pass = process.env.PASSWORD;
|
||||
if (!_pass) {
|
||||
console.error('Password not entered!');
|
||||
process.exit(1);
|
||||
}
|
||||
_tmp = Crypto.AES.decrypt(_tmp, _pass);
|
||||
if (floCrypto.verifyPrivKey(_tmp, floGlobals.adminID)) {
|
||||
global.myPrivKey = _tmp;
|
||||
global.myPubKey = floCrypto.getPubKeyHex(global.myPrivKey);
|
||||
global.myFloID = floCrypto.getFloID(global.myPubKey);
|
||||
} else {
|
||||
console.error('Loaded wrong private key!');
|
||||
process.exit(1);
|
||||
}
|
||||
global.myPrivKey = Crypto.AES.decrypt(_tmp, _pass);
|
||||
global.myPubKey = floCrypto.getPubKeyHex(global.myPrivKey);
|
||||
global.myFloID = floCrypto.getFloID(global.myPubKey);
|
||||
if (!global.myFloID || !global.myPubKey || !global.myPrivKey)
|
||||
throw "Invalid Keys";
|
||||
} catch (error) {
|
||||
console.error('Unable to load private key!');
|
||||
process.exit(1);
|
||||
@ -162,7 +158,7 @@ module.exports = function startServer(public_dir) {
|
||||
setDB(db);
|
||||
app = new App(config['secret'], DB);
|
||||
refreshData(true).then(_ => {
|
||||
app.start(PORT).then(result => {
|
||||
app.start(config['port']).then(result => {
|
||||
console.log(result);
|
||||
backup.init(app);
|
||||
}).catch(error => console.error(error))
|
||||
|
||||
@ -29,12 +29,12 @@ function validateRequestFromFloID(request, sign, floID, proxy = true) {
|
||||
if (!serving)
|
||||
return reject(INVALID(INVALID_SERVER_MSG));
|
||||
else if (!floCrypto.validateAddr(floID))
|
||||
return res.status(INVALID.e_code).send("Invalid floID");
|
||||
return reject(INVALID.e_code).send("Invalid floID");
|
||||
DB.query("SELECT " + (proxy ? "session_time, proxyKey AS pubKey FROM Sessions" : "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())
|
||||
return res.status(INVALID.e_code).send("Session Expired! Re-login required");
|
||||
return reject(INVALID.e_code).send("Session Expired! Re-login required");
|
||||
let req_str = validateRequest(request, sign, result[0].pubKey);
|
||||
req_str instanceof INVALID ? reject(req_str) : resolve(req_str);
|
||||
}).catch(error => reject(error));
|
||||
@ -64,7 +64,7 @@ function storeRequest(floID, req_str, sign) {
|
||||
function getLoginCode(req, res) {
|
||||
let randID = floCrypto.randString(8, true) + Math.round(Date.now() / 1000);
|
||||
let hash = Crypto.SHA1(randID + secret);
|
||||
res.status(INVALID.e_code).send({
|
||||
res.send({
|
||||
code: randID,
|
||||
hash: hash
|
||||
});
|
||||
@ -111,9 +111,9 @@ 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) VALUES (?, ?, ?) " +
|
||||
"ON DUPLICATE KEY UPDATE session_time=DEFAULT, proxyKey=?",
|
||||
[data.floID, data.code, data.proxyKey, data.code, data.proxyKey]).then(_ => {
|
||||
DB.query("INSERT INTO Sessions (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);
|
||||
res.send("Login Successful");
|
||||
}).catch(error => {
|
||||
@ -131,6 +131,7 @@ function Login(req, res) {
|
||||
}
|
||||
|
||||
function Logout(req, res) {
|
||||
let data = req.body;
|
||||
validateRequestFromFloID({
|
||||
type: "logout",
|
||||
timestamp: data.timestamp
|
||||
|
||||
Loading…
Reference in New Issue
Block a user