Adding Coin-convert support
- Convert rupee token (currency) to coin (BTC) and vise-versa
This commit is contained in:
parent
bdd79a1a76
commit
7d09babea7
@ -114,7 +114,7 @@ CREATE TABLE BuyOrder (
|
||||
FOREIGN KEY (asset) REFERENCES AssetList(asset)
|
||||
);
|
||||
|
||||
CREATE TABLE InputCoin (
|
||||
CREATE TABLE DepositCoin (
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
txid VARCHAR(128) NOT NULL,
|
||||
floID CHAR(34) NOT NULL,
|
||||
@ -124,7 +124,7 @@ CREATE TABLE InputCoin (
|
||||
PRIMARY KEY(id)
|
||||
);
|
||||
|
||||
CREATE TABLE OutputCoin (
|
||||
CREATE TABLE WithdrawCoin (
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
txid VARCHAR(128),
|
||||
floID CHAR(34) NOT NULL,
|
||||
@ -134,7 +134,7 @@ CREATE TABLE OutputCoin (
|
||||
PRIMARY KEY(id)
|
||||
);
|
||||
|
||||
CREATE TABLE InputToken (
|
||||
CREATE TABLE DepositToken (
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
txid VARCHAR(128) NOT NULL,
|
||||
floID CHAR(34) NOT NULL,
|
||||
@ -144,7 +144,7 @@ CREATE TABLE InputToken (
|
||||
PRIMARY KEY(id)
|
||||
);
|
||||
|
||||
CREATE TABLE OutputToken (
|
||||
CREATE TABLE WithdrawToken (
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
txid VARCHAR(128),
|
||||
floID CHAR(34) NOT NULL,
|
||||
@ -212,6 +212,21 @@ CREATE TABLE AuditTrade(
|
||||
FOREIGN KEY (asset) REFERENCES AssetList(asset)
|
||||
);
|
||||
|
||||
/* External Service */
|
||||
|
||||
CREATE TABLE DirectConvert(
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
floID CHAR(34) NOT NULL,
|
||||
amount DECIMAL(16, 8),
|
||||
coin VARCHAR(8) NOT NULL,
|
||||
quantity DECIMAL(16, 8),
|
||||
mode BIT NOT NULL,
|
||||
in_txid VARCHAR(128),
|
||||
out_txid VARCHAR(128),
|
||||
locktime TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
status VARCHAR(50) NOT NULL,
|
||||
);
|
||||
|
||||
/* Backup Feature (Tables & Triggers) */
|
||||
|
||||
CREATE TABLE _backup (
|
||||
@ -279,33 +294,40 @@ FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('BuyOrder', NEW.id) ON DUP
|
||||
CREATE TRIGGER BuyOrder_D AFTER DELETE ON BuyOrder
|
||||
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('BuyOrder', OLD.id) ON DUPLICATE KEY UPDATE mode=NULL, timestamp=DEFAULT;
|
||||
|
||||
CREATE TRIGGER InputCoin_I AFTER INSERT ON InputCoin
|
||||
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('InputCoin', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT;
|
||||
CREATE TRIGGER InputCoin_U AFTER UPDATE ON InputCoin
|
||||
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('InputCoin', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT;
|
||||
CREATE TRIGGER InputCoin_D AFTER DELETE ON InputCoin
|
||||
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('InputCoin', OLD.id) ON DUPLICATE KEY UPDATE mode=NULL, timestamp=DEFAULT;
|
||||
CREATE TRIGGER DepositCoin_I AFTER INSERT ON DepositCoin
|
||||
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('DepositCoin', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT;
|
||||
CREATE TRIGGER DepositCoin_U AFTER UPDATE ON DepositCoin
|
||||
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('DepositCoin', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT;
|
||||
CREATE TRIGGER DepositCoin_D AFTER DELETE ON DepositCoin
|
||||
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('DepositCoin', OLD.id) ON DUPLICATE KEY UPDATE mode=NULL, timestamp=DEFAULT;
|
||||
|
||||
CREATE TRIGGER OutputCoin_I AFTER INSERT ON OutputCoin
|
||||
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('OutputCoin', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT;
|
||||
CREATE TRIGGER OutputCoin_U AFTER UPDATE ON OutputCoin
|
||||
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('OutputCoin', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT;
|
||||
CREATE TRIGGER OutputCoin_D AFTER DELETE ON OutputCoin
|
||||
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('OutputCoin', OLD.id) ON DUPLICATE KEY UPDATE mode=NULL, timestamp=DEFAULT;
|
||||
CREATE TRIGGER WithdrawCoin_I AFTER INSERT ON WithdrawCoin
|
||||
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('WithdrawCoin', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT;
|
||||
CREATE TRIGGER WithdrawCoin_U AFTER UPDATE ON WithdrawCoin
|
||||
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('WithdrawCoin', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT;
|
||||
CREATE TRIGGER WithdrawCoin_D AFTER DELETE ON WithdrawCoin
|
||||
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('WithdrawCoin', OLD.id) ON DUPLICATE KEY UPDATE mode=NULL, timestamp=DEFAULT;
|
||||
|
||||
CREATE TRIGGER InputToken_I AFTER INSERT ON InputToken
|
||||
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('InputToken', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT;
|
||||
CREATE TRIGGER InputToken_U AFTER UPDATE ON InputToken
|
||||
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('InputToken', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT;
|
||||
CREATE TRIGGER InputToken_D AFTER DELETE ON InputToken
|
||||
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('InputToken', OLD.id) ON DUPLICATE KEY UPDATE mode=NULL, timestamp=DEFAULT;
|
||||
CREATE TRIGGER DepositToken_I AFTER INSERT ON DepositToken
|
||||
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('DepositToken', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT;
|
||||
CREATE TRIGGER DepositToken_U AFTER UPDATE ON DepositToken
|
||||
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('DepositToken', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT;
|
||||
CREATE TRIGGER DepositToken_D AFTER DELETE ON DepositToken
|
||||
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('DepositToken', OLD.id) ON DUPLICATE KEY UPDATE mode=NULL, timestamp=DEFAULT;
|
||||
|
||||
CREATE TRIGGER OutputToken_I AFTER INSERT ON OutputToken
|
||||
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('OutputToken', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT;
|
||||
CREATE TRIGGER OutputToken_U AFTER UPDATE ON OutputToken
|
||||
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('OutputToken', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT;
|
||||
CREATE TRIGGER OutputToken_D AFTER DELETE ON OutputToken
|
||||
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('OutputToken', OLD.id) ON DUPLICATE KEY UPDATE mode=NULL, timestamp=DEFAULT;
|
||||
CREATE TRIGGER WithdrawToken_I AFTER INSERT ON WithdrawToken
|
||||
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('WithdrawToken', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT;
|
||||
CREATE TRIGGER WithdrawToken_U AFTER UPDATE ON WithdrawToken
|
||||
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('WithdrawToken', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT;
|
||||
CREATE TRIGGER WithdrawToken_D AFTER DELETE ON WithdrawToken
|
||||
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('WithdrawToken', OLD.id) ON DUPLICATE KEY UPDATE mode=NULL, timestamp=DEFAULT;
|
||||
|
||||
CREATE TRIGGER DirectConvert_I AFTER INSERT ON DirectConvert
|
||||
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('DirectConvert', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT;
|
||||
CREATE TRIGGER DirectConvert_U AFTER UPDATE ON DirectConvert
|
||||
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('DirectConvert', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT;
|
||||
CREATE TRIGGER DirectConvert_D AFTER DELETE ON DirectConvert
|
||||
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('DirectConvert', OLD.id) ON DUPLICATE KEY UPDATE mode=NULL, timestamp=DEFAULT;
|
||||
|
||||
CREATE TRIGGER UserTag_I AFTER INSERT ON UserTag
|
||||
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('UserTag', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT;
|
||||
|
||||
@ -4,10 +4,11 @@ TRUNCATE _backupCache;
|
||||
TRUNCATE AuditTrade;
|
||||
TRUNCATE BuyOrder;
|
||||
TRUNCATE Distributors;
|
||||
TRUNCATE InputCoin;
|
||||
TRUNCATE InputToken;
|
||||
TRUNCATE OutputCoin;
|
||||
TRUNCATE OutputToken;
|
||||
TRUNCATE DepositCoin;
|
||||
TRUNCATE DepositToken;
|
||||
TRUNCATE WithdrawCoin;
|
||||
TRUNCATE WithdrawToken;
|
||||
TRUNCATE DirectConvert;
|
||||
TRUNCATE PriceHistory;
|
||||
TRUNCATE RequestLog;
|
||||
TRUNCATE SellOrder;
|
||||
|
||||
@ -30,5 +30,9 @@ module.exports = {
|
||||
BACKUP_INTERVAL: 5 * 60 * 1000, //5 min
|
||||
BACKUP_SYNC_TIMEOUT: 10 * 60 * 1000, //10 mins
|
||||
CHECKSUM_INTERVAL: 100, //times of BACKUP_INTERVAL
|
||||
},
|
||||
sql: {
|
||||
CONVERT_MODE_GET: 1,
|
||||
CONVERT_MODE_PUT: 0,
|
||||
}
|
||||
}
|
||||
@ -1,26 +1,25 @@
|
||||
'use strict';
|
||||
const blockchain = require('./blockchain');
|
||||
const conversion = require('./conversion');
|
||||
|
||||
const {
|
||||
LAUNCH_SELLER_TAG,
|
||||
MAXIMUM_LAUNCH_SELL_CHIPS,
|
||||
} = require('./_constants')["market"];
|
||||
|
||||
function checkTag(floID, tag) {
|
||||
return new Promise((resolve, reject) => {
|
||||
DB.query("SELECT id FROM UserTag WHERE floID=? AND tag=?", [floID, tag])
|
||||
.then(result => resolve(result.length ? true : false))
|
||||
.catch(error => reject(error))
|
||||
})
|
||||
}
|
||||
const _sql = require('./_constants').sql;
|
||||
|
||||
var updateBalance; // container for updateBalance function
|
||||
|
||||
const verifyTx = {};
|
||||
|
||||
function confirmDepositFLO() {
|
||||
DB.query("SELECT id, floID, txid FROM InputCoin WHERE coin=? AND status=?", ["FLO", "PENDING"]).then(results => {
|
||||
DB.query("SELECT id, floID, txid FROM DepositCoin WHERE coin=? AND status=?", ["FLO", "PENDING"]).then(results => {
|
||||
results.forEach(req => {
|
||||
verifyDepositFLO(req.floID, req.txid).then(amount => {
|
||||
verifyTx.FLO(req.floID, req.txid).then(amount => {
|
||||
addSellChipsIfLaunchSeller(req.floID, amount).then(txQueries => {
|
||||
txQueries.push(updateBalance.add(req.floID, "FLO", amount));
|
||||
txQueries.push(["UPDATE InputCoin SET status=?, amount=? WHERE id=?", ["SUCCESS", amount, req.id]]);
|
||||
txQueries.push(["UPDATE DepositCoin SET status=?, amount=? WHERE id=?", ["SUCCESS", amount, req.id]]);
|
||||
DB.transaction(txQueries)
|
||||
.then(result => console.debug("FLO deposited:", req.floID, amount))
|
||||
.catch(error => console.error(error))
|
||||
@ -28,14 +27,14 @@ function confirmDepositFLO() {
|
||||
}).catch(error => {
|
||||
console.error(error);
|
||||
if (error[0])
|
||||
DB.query("UPDATE InputCoin SET status=? WHERE id=?", ["REJECTED", req.id])
|
||||
DB.query("UPDATE DepositCoin SET status=? WHERE id=?", ["REJECTED", req.id])
|
||||
.then(_ => null).catch(error => console.error(error));
|
||||
});
|
||||
})
|
||||
}).catch(error => console.error(error))
|
||||
}
|
||||
|
||||
function verifyDepositFLO(sender, txid) {
|
||||
verifyTx.FLO = function (sender, txid) {
|
||||
return new Promise((resolve, reject) => {
|
||||
floBlockchainAPI.getTx(txid).then(tx => {
|
||||
let vin_sender = tx.vin.filter(v => v.addr === sender)
|
||||
@ -56,6 +55,14 @@ function verifyDepositFLO(sender, txid) {
|
||||
})
|
||||
}
|
||||
|
||||
function checkTag(floID, tag) {
|
||||
return new Promise((resolve, reject) => {
|
||||
DB.query("SELECT id FROM UserTag WHERE floID=? AND tag=?", [floID, tag])
|
||||
.then(result => resolve(result.length ? true : false))
|
||||
.catch(error => reject(error))
|
||||
})
|
||||
}
|
||||
|
||||
function addSellChipsIfLaunchSeller(floID, quantity) {
|
||||
return new Promise((resolve, reject) => {
|
||||
checkTag(floID, LAUNCH_SELLER_TAG).then(result => {
|
||||
@ -71,9 +78,7 @@ function addSellChipsIfLaunchSeller(floID, quantity) {
|
||||
let remLaunchChips = MAXIMUM_LAUNCH_SELL_CHIPS - (sold + chips) + brought;
|
||||
quantity = Math.min(quantity, remLaunchChips);
|
||||
if (quantity > 0)
|
||||
resolve([
|
||||
["INSERT INTO SellChips(floID, asset, quantity) VALUES (?, ?, ?)", [floID, 'FLO', quantity]]
|
||||
]);
|
||||
resolve([["INSERT INTO SellChips(floID, asset, quantity) VALUES (?, ?, ?)", [floID, 'FLO', quantity]]]);
|
||||
else
|
||||
resolve([]);
|
||||
}).catch(error => reject(error))
|
||||
@ -84,77 +89,76 @@ function addSellChipsIfLaunchSeller(floID, quantity) {
|
||||
}
|
||||
|
||||
function confirmDepositToken() {
|
||||
DB.query("SELECT id, floID, txid FROM InputToken WHERE status=?", ["PENDING"]).then(results => {
|
||||
DB.query("SELECT id, floID, txid FROM DepositToken WHERE status=?", ["PENDING"]).then(results => {
|
||||
results.forEach(req => {
|
||||
verifyDepositToken(req.floID, req.txid).then(amounts => {
|
||||
DB.query("SELECT id FROM InputCoin where floID=? AND coin=? AND txid=?", [req.floID, "FLO", req.txid]).then(result => {
|
||||
let txQueries = [],
|
||||
token_name = amounts[0],
|
||||
amount_token = amounts[1];
|
||||
verifyTx.token(req.floID, req.txid).then(({ token, amount, flo_amount }) => {
|
||||
DB.query("SELECT id FROM DepositCoin where floID=? AND coin=? AND txid=?", [req.floID, "FLO", req.txid]).then(result => {
|
||||
let txQueries = [];
|
||||
//Add the FLO balance if necessary
|
||||
if (!result.length) {
|
||||
let amount_flo = amounts[2];
|
||||
txQueries.push(updateBalance.add(req.floID, "FLO", amount_flo));
|
||||
txQueries.push(["INSERT INTO InputCoin(txid, floID, coin, amount, status) VALUES (?, ?, ?, ?, ?)", [req.txid, req.floID, "FLO", amount_flo, "SUCCESS"]]);
|
||||
txQueries.push(updateBalance.add(req.floID, "FLO", flo_amount));
|
||||
txQueries.push(["INSERT INTO DepositCoin(txid, floID, coin, amount, status) VALUES (?, ?, ?, ?, ?)", [req.txid, req.floID, "FLO", flo_amount, "SUCCESS"]]);
|
||||
}
|
||||
txQueries.push(["UPDATE InputToken SET status=?, token=?, amount=? WHERE id=?", ["SUCCESS", token_name, amount_token, req.id]]);
|
||||
txQueries.push(updateBalance.add(req.floID, token_name, amount_token));
|
||||
txQueries.push(["UPDATE DepositToken SET status=?, token=?, amount=? WHERE id=?", ["SUCCESS", token, amount, req.id]]);
|
||||
txQueries.push(updateBalance.add(req.floID, token, amount));
|
||||
DB.transaction(txQueries)
|
||||
.then(result => console.debug("Token deposited:", req.floID, token_name, amount_token))
|
||||
.then(result => console.debug("Token deposited:", req.floID, token, amount))
|
||||
.catch(error => console.error(error));
|
||||
}).catch(error => console.error(error));
|
||||
}).catch(error => {
|
||||
console.error(error);
|
||||
if (error[0])
|
||||
DB.query("UPDATE InputToken SET status=? WHERE id=?", ["REJECTED", req.id])
|
||||
DB.query("UPDATE DepositToken SET status=? WHERE id=?", ["REJECTED", req.id])
|
||||
.then(_ => null).catch(error => console.error(error));
|
||||
});
|
||||
})
|
||||
}).catch(error => console.error(error))
|
||||
}
|
||||
|
||||
function verifyDepositToken(sender, txid) {
|
||||
verifyTx.token = function (sender, txid, currencyOnly = false) {
|
||||
return new Promise((resolve, reject) => {
|
||||
floTokenAPI.getTx(txid).then(tx => {
|
||||
if (tx.parsedFloData.type !== "transfer")
|
||||
return reject([true, "Transaction type not 'transfer'"]);
|
||||
else if (tx.parsedFloData.transferType !== "token")
|
||||
return reject([true, "Transaction transfer is not 'token'"]);
|
||||
var token_name = tx.parsedFloData.tokenIdentification,
|
||||
amount_token = tx.parsedFloData.tokenAmount;
|
||||
if ((!assetList.includes(token_name) && token_name !== floGlobals.currency) || token_name === "FLO")
|
||||
var token = tx.parsedFloData.tokenIdentification,
|
||||
amount = tx.parsedFloData.tokenAmount;
|
||||
if (currencyOnly && token !== floGlobals.currency)
|
||||
return reject([true, "Token not currency"]);
|
||||
else if (!currencyOnly && ((!assetList.includes(token) && token !== floGlobals.currency) || token === "FLO"))
|
||||
return reject([true, "Token not authorised"]);
|
||||
let vin_sender = tx.transactionDetails.vin.filter(v => v.addr === sender)
|
||||
if (!vin_sender.length)
|
||||
return reject([true, "Transaction not sent by the sender"]);
|
||||
let amount_flo = tx.transactionDetails.vout.reduce((a, v) => blockchain.chests.includes(v.scriptPubKey.addresses[0]) ? a + v.value : a, 0);
|
||||
if (amount_flo == 0)
|
||||
let flo_amount = tx.transactionDetails.vout.reduce((a, v) => blockchain.chests.includes(v.scriptPubKey.addresses[0]) ? a + v.value : a, 0);
|
||||
if (flo_amount == 0)
|
||||
return reject([true, "Transaction receiver is not market ID"]); //Maybe reject as false? (to compensate delay in chestsList loading from other nodes)
|
||||
else
|
||||
resolve([token_name, amount_token, amount_flo]);
|
||||
resolve({ token, amount, flo_amount });
|
||||
}).catch(error => reject([false, error]))
|
||||
})
|
||||
}
|
||||
|
||||
function retryWithdrawalCoin() {
|
||||
DB.query("SELECT id, floID, coin, amount FROM OutputCoin WHERE status=?", ["PENDING"]).then(results => {
|
||||
DB.query("SELECT id, floID, coin, amount FROM WithdrawCoin WHERE status=?", ["PENDING"]).then(results => {
|
||||
results.forEach(req => blockchain.sendCoin.retry(req.floID, req.coin, req.amount, req.id));
|
||||
}).catch(error => reject(error));
|
||||
}).catch(error => console.error(error));
|
||||
}
|
||||
|
||||
function retryWithdrawalToken() {
|
||||
DB.query("SELECT id, floID, token, amount FROM OutputToken WHERE status=?", ["PENDING"]).then(results => {
|
||||
DB.query("SELECT id, floID, token, amount FROM WithdrawToken WHERE status=?", ["PENDING"]).then(results => {
|
||||
results.forEach(req => blockchain.sendToken.retry(req.floID, req.token, req.amount, req.id));
|
||||
}).catch(error => reject(error));
|
||||
}).catch(error => console.error(error));
|
||||
}
|
||||
|
||||
function confirmWithdrawalFLO() {
|
||||
DB.query("SELECT id, floID, amount, txid FROM OutputCoin WHERE coin=? AND status=?", ["FLO", "WAITING_CONFIRMATION"]).then(results => {
|
||||
DB.query("SELECT id, floID, amount, txid FROM WithdrawCoin WHERE coin=? AND status=?", ["FLO", "WAITING_CONFIRMATION"]).then(results => {
|
||||
results.forEach(req => {
|
||||
floBlockchainAPI.getTx(req.txid).then(tx => {
|
||||
if (!tx.blockheight || !tx.confirmations) //Still not confirmed
|
||||
return;
|
||||
DB.query("UPDATE OutputCoin SET status=? WHERE id=?", ["SUCCESS", req.id])
|
||||
DB.query("UPDATE WithdrawCoin SET status=? WHERE id=?", ["SUCCESS", req.id])
|
||||
.then(result => console.debug("FLO withdrawed:", req.floID, req.amount))
|
||||
.catch(error => console.error(error))
|
||||
}).catch(error => console.error(error));
|
||||
@ -163,12 +167,12 @@ function confirmWithdrawalFLO() {
|
||||
}
|
||||
|
||||
function confirmWithdrawalBTC() {
|
||||
DB.query("SELECT id, floID, amount, txid FROM OutputCoin WHERE coin=? AND status=?", ["BTC", "WAITING_CONFIRMATION"]).then(results => {
|
||||
DB.query("SELECT id, floID, amount, txid FROM WithdrawCoin WHERE coin=? AND status=?", ["BTC", "WAITING_CONFIRMATION"]).then(results => {
|
||||
results.forEach(req => {
|
||||
btcOperator.getTx(req.txid).then(tx => {
|
||||
if (!tx.blockhash || !tx.confirmations) //Still not confirmed
|
||||
return;
|
||||
DB.query("UPDATE OutputCoin SET status=? WHERE id=?", ["SUCCESS", req.id])
|
||||
DB.query("UPDATE WithdrawCoin SET status=? WHERE id=?", ["SUCCESS", req.id])
|
||||
.then(result => console.debug("BTC withdrawed:", req.floID, req.amount))
|
||||
.catch(error => console.error(error))
|
||||
}).catch(error => console.error(error));
|
||||
@ -177,10 +181,10 @@ function confirmWithdrawalBTC() {
|
||||
}
|
||||
|
||||
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 WithdrawToken WHERE status=?", ["WAITING_CONFIRMATION"]).then(results => {
|
||||
results.forEach(req => {
|
||||
floTokenAPI.getTx(req.txid).then(tx => {
|
||||
DB.query("UPDATE OutputToken SET status=? WHERE id=?", ["SUCCESS", req.id])
|
||||
DB.query("UPDATE WithdrawToken SET status=? WHERE id=?", ["SUCCESS", req.id])
|
||||
.then(result => console.debug("Token withdrawed:", req.floID, req.token, req.amount))
|
||||
.catch(error => console.error(error));
|
||||
}).catch(error => console.error(error));
|
||||
@ -188,6 +192,90 @@ function confirmWithdrawalToken() {
|
||||
}).catch(error => console.error(error));
|
||||
}
|
||||
|
||||
verifyTx.BTC = function (sender, txid) {
|
||||
return new Promise((resolve, reject) => {
|
||||
btcOperator.getTx(txid).then(tx => {
|
||||
let vin_sender = tx.inputs.filter(v => floCrypto.isSameAddr(v.address, sender))
|
||||
if (!vin_sender.length)
|
||||
return reject([true, "Transaction not sent by the sender"]);
|
||||
if (vin_sender.length !== tx.vin.length)
|
||||
return reject([true, "Transaction input containes other floIDs"]);
|
||||
if (!tx.block_no)
|
||||
return reject([false, "Transaction not included in any block yet"]);
|
||||
if (!tx.confirmations)
|
||||
return reject([false, "Transaction not confirmed yet"]);
|
||||
let amount = tx.outputs.reduce((a, v) =>
|
||||
blockchain.chests.includes(floCrypto.toFloID(v.address, { bech: [coinjs.bech32.version] })) ? a + parseFloat(v.value) : a, 0);
|
||||
if (amount == 0)
|
||||
return reject([true, "Transaction receiver is not market ID"]); //Maybe reject as false? (to compensate delay in chestsList loading from other nodes)
|
||||
else
|
||||
resolve(amount);
|
||||
}).catch(error => reject([false, error]))
|
||||
})
|
||||
}
|
||||
|
||||
function verifyConvert() {
|
||||
DB.query("SELECT id, floID, mode, in_txid FROM DirectConvert WHERE status=? AND coin=?", ["PENDING", "BTC"]).then(results => {
|
||||
results.forEach(req => {
|
||||
if (mode == _sql.CONVERT_MODE_GET) {
|
||||
verifyTx.token(req.floID, req.in_txid, true).then(({ amount }) => {
|
||||
conversion.getRate().then(rate => {
|
||||
blockchain.convertToCoin.init(req.floID, "BTC", amount, amount / rate, req.id)
|
||||
}).catch(error => console.error(error))
|
||||
}).catch(error => {
|
||||
console.error(error);
|
||||
if (error[0])
|
||||
DB.query("UPDATE DirectConvert SET status=? WHERE id=?", ["REJECTED", req.id])
|
||||
.then(_ => null).catch(error => console.error(error));
|
||||
});
|
||||
} else if (mode == _sql.CONVERT_MODE_PUT) {
|
||||
verifyTx.BTC(req.floID, req.in_txid).then(quantity => {
|
||||
conversion.getRate().then(rate => {
|
||||
blockchain.convertFromCoin.init(req.floID, quantity * rate, quantity, req.id)
|
||||
}).catch(error => console.error(error))
|
||||
}).catch(error => {
|
||||
console.error(error);
|
||||
if (error[0])
|
||||
DB.query("UPDATE DirectConvert SET status=? WHERE id=?", ["REJECTED", req.id])
|
||||
.then(_ => null).catch(error => console.error(error));
|
||||
});
|
||||
}
|
||||
})
|
||||
}).catch(error => console.error(error))
|
||||
}
|
||||
|
||||
function retryConvert() {
|
||||
DB.query("SELECT id, floID, mode, amount, quantity FROM DirectConvert WHERE status=? AND coin=?", ["PROCESSING", "BTC"]).then(results => {
|
||||
results.forEach(req => {
|
||||
if (mode == _sql.CONVERT_MODE_GET)
|
||||
blockchain.convertToCoin.retry(req.floID, "BTC", req.quantity, req.id);
|
||||
else if (mode == _sql.CONVERT_MODE_PUT)
|
||||
blockchain.convertFromCoin.retry(req.floID, req.amount, req.id)
|
||||
})
|
||||
}).catch(error => console.error(error))
|
||||
}
|
||||
|
||||
function confirmConvert() {
|
||||
DB.query("SELECT id, floID, mode, amount, quantity, out_txid FROM DirectConvert WHERE status=? AND coin=?", ["WAITING_CONFIRMATION", "BTC"]).then(results => {
|
||||
results.forEach(req => {
|
||||
if (mode == _sql.CONVERT_MODE_GET)
|
||||
btcOperator.getTx(req.out_txid).then(tx => {
|
||||
if (!tx.blockhash || !tx.confirmations) //Still not confirmed
|
||||
return;
|
||||
DB.query("UPDATE DirectConvert SET status=? WHERE id=?", ["SUCCESS", req.id])
|
||||
.then(result => console.debug(`${req.floID} converted ${amount} to ${req.quantity} BTC`))
|
||||
.catch(error => console.error(error))
|
||||
}).catch(error => console.error(error));
|
||||
else if (mode == _sql.CONVERT_MODE_PUT)
|
||||
floTokenAPI.getTx(req.out_txid).then(tx => {
|
||||
DB.query("UPDATE DirectConvert SET status=? WHERE id=?", ["SUCCESS", req.id])
|
||||
.then(result => console.debug(`${req.floID} converted ${req.quantity} BTC to ${amount}`))
|
||||
.catch(error => console.error(error));
|
||||
}).catch(error => console.error(error));
|
||||
})
|
||||
}).catch(error => console.error(error));
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
blockchain,
|
||||
confirmDepositFLO,
|
||||
@ -196,5 +284,11 @@ module.exports = {
|
||||
retryWithdrawalToken,
|
||||
confirmWithdrawalFLO,
|
||||
confirmWithdrawalBTC,
|
||||
confirmWithdrawalToken
|
||||
confirmWithdrawalToken,
|
||||
verifyConvert,
|
||||
retryConvert,
|
||||
confirmConvert,
|
||||
set updateBalance(f) {
|
||||
updateBalance = f;
|
||||
}
|
||||
}
|
||||
@ -3,13 +3,17 @@
|
||||
var collectAndCall; //container for collectAndCall function from backup module
|
||||
var chests; //container for blockchain ids (where assets are stored)
|
||||
|
||||
const WITHDRAWAL_MESSAGE = "(withdrawal from market)";
|
||||
const WITHDRAWAL_MESSAGE = "(withdrawal from market)",
|
||||
TYPE_TOKEN = "TOKEN",
|
||||
TYPE_COIN = "COIN",
|
||||
TYPE_CONVERT = "CONVERT";
|
||||
|
||||
const balance_locked = {},
|
||||
balance_cache = {},
|
||||
callbackCollection = {
|
||||
Coin: {},
|
||||
token: {}
|
||||
[TYPE_COIN]: {},
|
||||
[TYPE_TOKEN]: {},
|
||||
[TYPE_CONVERT]: {}
|
||||
};
|
||||
|
||||
function getBalance(sinkID, asset) {
|
||||
@ -24,7 +28,7 @@ function getBalance(sinkID, asset) {
|
||||
}
|
||||
}
|
||||
|
||||
function getSinkID(amount, asset, sinkList = null) {
|
||||
function getSinkID(quantity, asset, sinkList = null) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!sinkList)
|
||||
sinkList = chests.list.map(s => [s, s in balance_cache ? balance_cache[s][asset] || 0 : 0]) //TODO: improve sorting
|
||||
@ -36,99 +40,121 @@ function getSinkID(amount, asset, sinkList = null) {
|
||||
if (!(sinkID in balance_cache))
|
||||
balance_cache[sinkID] = {};
|
||||
balance_cache[sinkID][asset] = balance;
|
||||
if (balance > (amount + (sinkID in balance_locked ? balance_locked[sinkID][asset] || 0 : 0)))
|
||||
if (balance > (quantity + (sinkID in balance_locked ? balance_locked[sinkID][asset] || 0 : 0)))
|
||||
return resolve(sinkID);
|
||||
else
|
||||
getSinkID(amount, asset, sinkList)
|
||||
getSinkID(quantity, asset, sinkList)
|
||||
.then(result => resolve(result))
|
||||
.catch(error => reject(error))
|
||||
}).catch(error => {
|
||||
console.error(error);
|
||||
getSinkID(amount, asset, sinkList)
|
||||
getSinkID(quantity, asset, sinkList)
|
||||
.then(result => resolve(result))
|
||||
.catch(error => reject(error))
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
function sendTx(floID, coin, amount, sinkID, sinkKey) {
|
||||
switch (coin) {
|
||||
function sendTx(floID, asset, quantity, sinkID, sinkKey) {
|
||||
switch (asset) {
|
||||
case "FLO":
|
||||
return floBlockchainAPI.sendTx(sinkID, floID, amount, sinkKey, WITHDRAWAL_MESSAGE);
|
||||
return floBlockchainAPI.sendTx(sinkID, floID, quantity, sinkKey, WITHDRAWAL_MESSAGE);
|
||||
case "BTC":
|
||||
let btc_sinkID = btcOperator.convert.legacy2bech(sinkID),
|
||||
btc_receiver = btcOperator.convert.legacy2bech(floID);
|
||||
return btcOperator.sendTx(btc_sinkID, sinkKey, btc_receiver, quantity, null);
|
||||
default:
|
||||
return floTokenAPI.sendToken(sinkKey, quantity, floID, WITHDRAWAL_MESSAGE, asset);
|
||||
}
|
||||
}
|
||||
|
||||
function sendCoin(floID, coin, amount, id) {
|
||||
getSinkID(amount, coin).then(sinkID => {
|
||||
let callback = (sinkKey) => {
|
||||
//Send Coin to user via blockchain API
|
||||
sendTx(floID, coin, amount, sinkID, sinkKey).then(txid => {
|
||||
if (!txid)
|
||||
throw Error("Transaction not successful");
|
||||
//Transaction was successful, Add in DB
|
||||
DB.query("UPDATE OutputCoin SET status=?, txid=? WHERE id=?", ["WAITING_CONFIRMATION", txid, id])
|
||||
const tableUpdate = {
|
||||
[TYPE_COIN]: (id, txid) => {
|
||||
DB.query("UPDATE WithdrawCoin SET status=?, txid=? WHERE id=?", ["WAITING_CONFIRMATION", txid, id])
|
||||
.then(_ => null).catch(error => console.error(error))
|
||||
},
|
||||
[TYPE_TOKEN]: (id, txid) => {
|
||||
DB.query("UPDATE WithdrawToken SET status=?, txid=? WHERE id=?", ["WAITING_CONFIRMATION", txid, id])
|
||||
.then(_ => null).catch(error => console.error(error))
|
||||
},
|
||||
[TYPE_CONVERT]: (id, txid) => {
|
||||
DB.query("UPDATE DirectConvert SET status=?, out_txid=? WHERE id=?", ["WAITING_CONFIRMATION", txid, id])
|
||||
.then(_ => null).catch(error => console.error(error));
|
||||
}
|
||||
};
|
||||
|
||||
function sendAsset(floID, asset, quantity, type, id) {
|
||||
getSinkID(quantity, asset).then(sinkID => {
|
||||
let callback = (sinkKey) => {
|
||||
//Send asset to user via API
|
||||
sendTx(floID, asset, quantity, sinkID, sinkKey).then(txid => {
|
||||
if (!txid)
|
||||
console.error("Transaction not successful");
|
||||
else //Transaction was successful, Add in DB
|
||||
tableUpdate[type](id, txid);
|
||||
}).catch(error => console.error(error)).finally(_ => {
|
||||
delete callbackCollection.Coin[id];
|
||||
balance_locked[sinkID][coin] -= amount;
|
||||
delete callbackCollection[type][id];
|
||||
balance_locked[sinkID][asset] -= quantity;
|
||||
});
|
||||
}
|
||||
collectAndCall(sinkID, callback);
|
||||
callbackCollection.Coin[id] = callback;
|
||||
callbackCollection[type][id] = callback;
|
||||
if (!(sinkID in balance_locked))
|
||||
balance_locked[sinkID] = {};
|
||||
balance_locked[sinkID][coin] = (balance_locked[sinkID][coin] || 0) + amount;
|
||||
balance_locked[sinkID][asset] = (balance_locked[sinkID][asset] || 0) + quantity;
|
||||
}).catch(error => console.error(error))
|
||||
}
|
||||
|
||||
function sendCoin_init(floID, coin, amount) {
|
||||
DB.query("INSERT INTO OutputCoin (floID, coin, amount, status) VALUES (?, ?, ?, ?)", [floID, coin, amount, "PENDING"])
|
||||
.then(result => sendCoin(floID, coin, amount, result.insertId))
|
||||
function sendCoin_init(floID, coin, quantity) {
|
||||
DB.query("INSERT INTO WithdrawCoin (floID, coin, amount, status) VALUES (?, ?, ?, ?)", [floID, coin, quantity, "PENDING"])
|
||||
.then(result => sendAsset(floID, coin, quantity, TYPE_COIN, result.insertId))
|
||||
.catch(error => console.error(error))
|
||||
}
|
||||
|
||||
function sendCoin_retry(floID, coin, amount, id) {
|
||||
if (id in callbackCollection.Coin)
|
||||
console.debug("A callback is already pending for this FLO transfer");
|
||||
function sendCoin_retry(floID, coin, quantity, id) {
|
||||
if (id in callbackCollection[TYPE_COIN])
|
||||
console.debug("A callback is already pending for this Coin transfer");
|
||||
else
|
||||
sendCoin(floID, coin, amount, id);
|
||||
sendAsset(floID, coin, quantity, TYPE_COIN, id);
|
||||
}
|
||||
|
||||
function sendToken(floID, token, amount, id) {
|
||||
getSinkID(amount, token).then(sinkID => {
|
||||
let callback = (sinkKey) => {
|
||||
//Send Token to user via token API
|
||||
floTokenAPI.sendToken(sinkKey, amount, floID, WITHDRAWAL_MESSAGE, token).then(txid => {
|
||||
if (!txid)
|
||||
throw Error("Transaction not successful");
|
||||
//Transaction was successful, Add in DB
|
||||
DB.query("UPDATE OutputToken SET status=?, txid=? WHERE id=?", ["WAITING_CONFIRMATION", txid, id])
|
||||
.then(_ => null).catch(error => console.error(error));
|
||||
}).catch(error => console.error(error)).finally(_ => {
|
||||
delete callbackCollection.token[id];
|
||||
balance_locked[sinkID][token] -= amount;
|
||||
});
|
||||
}
|
||||
collectAndCall(sinkID, callback);
|
||||
callbackCollection.token[id] = callback;
|
||||
if (!(sinkID in balance_locked))
|
||||
balance_locked[sinkID] = {};
|
||||
balance_locked[sinkID][token] = (balance_locked[sinkID][token] || 0) + amount;
|
||||
}).catch(error => console.error(error))
|
||||
}
|
||||
|
||||
function sendToken_init(floID, token, amount) {
|
||||
DB.query("INSERT INTO OutputToken (floID, token, amount, status) VALUES (?, ?, ?, ?)", [floID, token, amount, "PENDING"])
|
||||
.then(result => sendToken(floID, amount, result.insertId))
|
||||
function sendToken_init(floID, token, quantity) {
|
||||
DB.query("INSERT INTO WithdrawToken (floID, token, amount, status) VALUES (?, ?, ?, ?)", [floID, token, quantity, "PENDING"])
|
||||
.then(result => sendAsset(floID, quantity, TYPE_TOKEN, result.insertId))
|
||||
.catch(error => console.error(error))
|
||||
}
|
||||
|
||||
function sendToken_retry(floID, token, amount, id) {
|
||||
if (id in callbackCollection.token)
|
||||
console.debug("A callback is already pending for this token transfer");
|
||||
function sendToken_retry(floID, token, quantity, id) {
|
||||
if (id in callbackCollection[TYPE_TOKEN])
|
||||
console.debug("A callback is already pending for this Token transfer");
|
||||
else
|
||||
sendToken(floID, token, amount, id);
|
||||
sendAsset(floID, token, quantity, TYPE_TOKEN, id);
|
||||
}
|
||||
|
||||
function convertToCoin_init(floID, coin, currency_amount, coin_quantity, id) {
|
||||
DB.query("UPDATE DirectConvert SET amount=?, quantity=?, status=?, locktime=DEFAULT WHERE id=?", [currency_amount, coin_quantity, "PROCESSING", id])
|
||||
.then(result => sendAsset(floID, coin, coin_quantity, TYPE_CONVERT, id))
|
||||
.catch(error => console.error(error))
|
||||
}
|
||||
|
||||
function convertToCoin_retry(floID, coin, coin_quantity, id) {
|
||||
if (id in callbackCollection[TYPE_CONVERT])
|
||||
console.debug("A callback is already pending for this Coin Convert");
|
||||
else
|
||||
sendAsset(floID, coin, coin_quantity, TYPE_CONVERT, id);
|
||||
}
|
||||
|
||||
function convertFromCoin_init(floID, currency_amount, coin_quantity, id) {
|
||||
DB.query("UPDATE DirectConvert SET amount=?, quantity=?, status=?, locktime=DEFAULT WHERE id=?", [currency_amount, coin_quantity, "PROCESSING", id])
|
||||
.then(result => sendAsset(floID, floGlobals.currency, currency_amount, TYPE_CONVERT, id))
|
||||
.catch(error => console.error(error))
|
||||
}
|
||||
|
||||
function convertFromCoin_retry(floID, current_amount, id) {
|
||||
if (id in callbackCollection[TYPE_CONVERT])
|
||||
console.debug("A callback is already pending for this Coin Convert");
|
||||
else
|
||||
sendAsset(floID, floGlobals.currency, current_amount, TYPE_CONVERT, id);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
@ -148,5 +174,13 @@ module.exports = {
|
||||
sendToken: {
|
||||
init: sendToken_init,
|
||||
retry: sendToken_retry
|
||||
},
|
||||
convertToCoin: {
|
||||
init: convertToCoin_init,
|
||||
retry: convertToCoin_retry
|
||||
},
|
||||
convertFromCoin: {
|
||||
init: convertFromCoin_init,
|
||||
retry: convertFromCoin_retry
|
||||
}
|
||||
}
|
||||
72
src/conversion.js
Normal file
72
src/conversion.js
Normal file
@ -0,0 +1,72 @@
|
||||
const _sql = require('./_constants').sql;
|
||||
const allowedConversion = ["BTC"];
|
||||
|
||||
function getRate() {
|
||||
return new Promise((resolve, reject) => {
|
||||
getRate.BTC_USD().then(BTC_rate => {
|
||||
getRate.USD_INR().then(INR_rate => {
|
||||
resolve(BTC_rate * INR_rate);
|
||||
}).catch(error => reject(error))
|
||||
}).catch(error => reject(error))
|
||||
})
|
||||
}
|
||||
|
||||
getRate.BTC_USD = function () {
|
||||
return new Promise((resolve, reject) => {
|
||||
fetch('https://api.coinlore.net/api/ticker/?id=90').then(response => {
|
||||
if (response.ok) {
|
||||
response.json()
|
||||
.then(result => resolve(result[0].price_usd))
|
||||
.catch(error => reject(error));
|
||||
} else
|
||||
reject(response.status);
|
||||
}).catch(error => reject(error));
|
||||
});
|
||||
}
|
||||
|
||||
getRate.USD_INR = function () {
|
||||
return new Promise((resolve, reject) => {
|
||||
fetch('https://api.exchangerate-api.com/v4/latest/usd').then(response => {
|
||||
if (response.ok) {
|
||||
response.json()
|
||||
.then(result => resolve(result.rates['INR']))
|
||||
.catch(error => reject(error));
|
||||
} else
|
||||
reject(response.status);
|
||||
}).catch(error => reject(error));
|
||||
});
|
||||
}
|
||||
|
||||
function convertToCoin(floID, txid, coin) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!allowedConversion.includes(coin))
|
||||
return reject(INVALID(eCode.INVALID_TOKEN_NAME, `Invalid coin (${coin})`));
|
||||
DB.query("SELECT status FROM DirectConvert WHERE in_txid=? AND floID=? mode=?", [txid, floID, _sql.CONVERT_MODE_GET]).then(result => {
|
||||
if (result.length)
|
||||
return reject(INVALID(eCode.DUPLICATE_ENTRY, "Transaction already in process"));
|
||||
else
|
||||
DB.query("INSERT INTO DirectConvert(floID, in_txid, mode, coin, status) VALUES (?, ?, ?, ?, ?)", [floID, txid, _sql.CONVERT_MODE_GET, coin, "PENDING"])
|
||||
.then(result => resolve("Conversion request in process"))
|
||||
.catch(error => reject(error));
|
||||
}).catch(error => reject(error))
|
||||
});
|
||||
}
|
||||
|
||||
function convertFromCoin(floID, txid, coin) {
|
||||
if (!allowedConversion.includes(coin))
|
||||
return reject(INVALID(eCode.INVALID_TOKEN_NAME, `Invalid coin (${coin})`));
|
||||
DB.query("SELECT status FROM DirectConvert WHERE in_txid=? AND floID=? mode=?", [txid, floID, _sql.CONVERT_MODE_PUT]).then(result => {
|
||||
if (result.length)
|
||||
return reject(INVALID(eCode.DUPLICATE_ENTRY, "Transaction already in process"));
|
||||
else
|
||||
DB.query("INSERT INTO DirectConvert(floID, in_txid, mode, coin, status) VALUES (?, ?, ?, ?, ?)", [floID, txid, _sql.CONVERT_MODE_PUT, coin, "PENDING"])
|
||||
.then(result => resolve("Conversion request in process"))
|
||||
.catch(error => reject(error));
|
||||
}).catch(error => reject(error))
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getRate,
|
||||
convertToCoin,
|
||||
convertFromCoin
|
||||
}
|
||||
@ -13,7 +13,7 @@ const {
|
||||
|
||||
const eCode = require('../docs/scripts/floExchangeAPI').errorCode;
|
||||
|
||||
const updateBalance = coupling.updateBalance;
|
||||
const updateBalance = background.updateBalance = coupling.updateBalance;
|
||||
|
||||
var DB, assetList; //container for database and allowed assets
|
||||
|
||||
@ -256,10 +256,10 @@ function getAccountDetails(floID) {
|
||||
|
||||
function getUserTransacts(floID) {
|
||||
return new Promise((resolve, reject) => {
|
||||
DB.query("(SELECT 'deposit' as type, txid, token, amount, status FROM InputToken WHERE floID=?)" +
|
||||
"UNION (SELECT 'deposit' as type, txid, coin as token, amount, status FROM InputCoin WHERE floID=?)" +
|
||||
"UNION (SELECT 'withdraw' as type, txid, token, amount, status FROM OutputToken WHERE floID=?)" +
|
||||
"UNION (SELECT 'withdraw' as type, txid, coin as token, amount, status FROM OutputCoin WHERE floID=?)",
|
||||
DB.query("(SELECT 'deposit' as type, txid, token, amount, status FROM DepositToken WHERE floID=?)" +
|
||||
"UNION (SELECT 'deposit' as type, txid, coin as token, amount, status FROM DepositCoin WHERE floID=?)" +
|
||||
"UNION (SELECT 'withdraw' as type, txid, token, amount, status FROM WithdrawToken WHERE floID=?)" +
|
||||
"UNION (SELECT 'withdraw' as type, txid, coin as token, amount, status FROM WithdrawCoin WHERE floID=?)",
|
||||
[floID, floID, floID, floID])
|
||||
.then(result => resolve(result))
|
||||
.catch(error => reject(error))
|
||||
@ -338,7 +338,7 @@ function transferToken(sender, receivers, token) {
|
||||
|
||||
function depositFLO(floID, txid) {
|
||||
return new Promise((resolve, reject) => {
|
||||
DB.query("SELECT status FROM InputCoin WHERE txid=? AND floID=? AND coin=?", [txid, floID, "FLO"]).then(result => {
|
||||
DB.query("SELECT status FROM DepositCoin WHERE txid=? AND floID=? AND coin=?", [txid, floID, "FLO"]).then(result => {
|
||||
if (result.length) {
|
||||
switch (result[0].status) {
|
||||
case "PENDING":
|
||||
@ -349,7 +349,7 @@ function depositFLO(floID, txid) {
|
||||
return reject(INVALID(eCode.DUPLICATE_ENTRY, "Transaction already used to add coins"));
|
||||
}
|
||||
} else
|
||||
DB.query("INSERT INTO InputCoin(txid, floID, coin, status) VALUES (?, ?, ?, ?)", [txid, floID, "FLO", "PENDING"])
|
||||
DB.query("INSERT INTO DepositCoin(txid, floID, coin, status) VALUES (?, ?, ?, ?)", [txid, floID, "FLO", "PENDING"])
|
||||
.then(result => resolve("Deposit request in process"))
|
||||
.catch(error => reject(error));
|
||||
}).catch(error => reject(error))
|
||||
@ -375,7 +375,7 @@ function withdrawFLO(floID, amount) {
|
||||
|
||||
function depositToken(floID, txid) {
|
||||
return new Promise((resolve, reject) => {
|
||||
DB.query("SELECT status FROM InputToken WHERE txid=? AND floID=?", [txid, floID]).then(result => {
|
||||
DB.query("SELECT status FROM DepositToken WHERE txid=? AND floID=?", [txid, floID]).then(result => {
|
||||
if (result.length) {
|
||||
switch (result[0].status) {
|
||||
case "PENDING":
|
||||
@ -386,7 +386,7 @@ function depositToken(floID, txid) {
|
||||
return reject(INVALID(eCode.DUPLICATE_ENTRY, "Transaction already used to add tokens"));
|
||||
}
|
||||
} else
|
||||
DB.query("INSERT INTO InputToken(txid, floID, status) VALUES (?, ?, ?)", [txid, floID, "PENDING"])
|
||||
DB.query("INSERT INTO DepositToken(txid, floID, status) VALUES (?, ?, ?)", [txid, floID, "PENDING"])
|
||||
.then(result => resolve("Deposit request in process"))
|
||||
.catch(error => reject(error));
|
||||
}).catch(error => reject(error))
|
||||
@ -472,19 +472,17 @@ function checkDistributor(floID, asset) {
|
||||
})
|
||||
}
|
||||
|
||||
function periodicProcess() {
|
||||
blockchainReCheck();
|
||||
}
|
||||
//Periodic Process
|
||||
|
||||
periodicProcess.start = function() {
|
||||
periodicProcess.stop();
|
||||
function periodicProcess_start() {
|
||||
periodicProcess_stop();
|
||||
periodicProcess();
|
||||
assetList.forEach(asset => coupling.initiate(asset, true));
|
||||
coupling.price.storeHistory.start();
|
||||
periodicProcess.instance = setInterval(periodicProcess, PERIOD_INTERVAL);
|
||||
};
|
||||
}
|
||||
|
||||
periodicProcess.stop = function() {
|
||||
function periodicProcess_stop() {
|
||||
if (periodicProcess.instance !== undefined) {
|
||||
clearInterval(periodicProcess.instance);
|
||||
delete periodicProcess.instance;
|
||||
@ -495,13 +493,13 @@ periodicProcess.stop = function() {
|
||||
|
||||
var lastSyncBlockHeight = 0;
|
||||
|
||||
function blockchainReCheck() {
|
||||
if (blockchainReCheck.timeout !== undefined) {
|
||||
clearTimeout(blockchainReCheck.timeout);
|
||||
delete blockchainReCheck.timeout;
|
||||
function periodicProcess() {
|
||||
if (periodicProcess.timeout !== undefined) {
|
||||
clearTimeout(periodicProcess.timeout);
|
||||
delete periodicProcess.timeout;
|
||||
}
|
||||
if (!blockchain.chests.list.length)
|
||||
return blockchainReCheck.timeout = setTimeout(blockchainReCheck, WAIT_TIME);
|
||||
return periodicProcess.timeout = setTimeout(periodicProcess, WAIT_TIME);
|
||||
|
||||
floBlockchainAPI.promisedAPI('api/blocks?limit=1').then(result => {
|
||||
if (lastSyncBlockHeight < result.blocks[0].height) {
|
||||
@ -513,6 +511,9 @@ function blockchainReCheck() {
|
||||
background.confirmWithdrawalFLO();
|
||||
background.confirmWithdrawalBTC();
|
||||
background.confirmWithdrawalToken();
|
||||
background.verifyConvert();
|
||||
background.retryConvert();
|
||||
background.confirmConvert();
|
||||
console.debug("Last Block :", lastSyncBlockHeight);
|
||||
}
|
||||
}).catch(error => console.error(error));
|
||||
@ -550,7 +551,10 @@ module.exports = {
|
||||
removeTag,
|
||||
addDistributor,
|
||||
removeDistributor,
|
||||
periodicProcess,
|
||||
periodicProcess: {
|
||||
start: periodicProcess_start,
|
||||
stop: periodicProcess_stop
|
||||
},
|
||||
set DB(db) {
|
||||
DB = db;
|
||||
coupling.DB = db;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user