Close-Blockchain-bond support
- Adding feature to close blockchain bonds upon user requests (when lock-in period is over) - Improved some syntax and structure of coding
This commit is contained in:
parent
fef11b4712
commit
90d2a4764e
@ -214,6 +214,39 @@ CREATE TABLE AuditTrade(
|
|||||||
|
|
||||||
/* External Service */
|
/* External Service */
|
||||||
|
|
||||||
|
CREATE TABLE BlockchainBonds(
|
||||||
|
bond_id VARCHAR(128) NOT NULL,
|
||||||
|
floID CHAR(34) NOT NULL,
|
||||||
|
amount_in DECIMAL(16, 2) NOT NULL,
|
||||||
|
begin_date DATE NOT NULL,
|
||||||
|
btc_base DECIMAL(16, 2) NOT NULL,
|
||||||
|
usd_base DECIMAL(16, 2) NOT NULL,
|
||||||
|
gain_cut DECIMAL(6, 5) NOT NULL,
|
||||||
|
min_ipa DECIMAL(6, 5) NOT NULL,
|
||||||
|
max_period VARCHAR(10) NOT NULL,
|
||||||
|
lockin_period VARCHAR(10) NOT NULL,
|
||||||
|
close_id VARCHAR(128),
|
||||||
|
amount_out DECIMAL(16, 2),
|
||||||
|
PRIMARY KEY(bond_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE CloseBondTransact(
|
||||||
|
id INT NOT NULL AUTO_INCREMENT,
|
||||||
|
bond_id VARCHAR(128) NOT NULL,
|
||||||
|
floID CHAR(34) NOT NULL,
|
||||||
|
amount DECIMAL(16, 2) NOT NULL,
|
||||||
|
end_date DATE NOT NULL,
|
||||||
|
ref_sign VARCHAR(180) NOT NULL,
|
||||||
|
btc_net DECIMAL(16, 2) NOT NULL,
|
||||||
|
usd_net DECIMAL(16, 2) NOT NULL,
|
||||||
|
txid VARCHAR(128),
|
||||||
|
close_id VARCHAR(128),
|
||||||
|
status VARCHAR(50) NOT NULL,
|
||||||
|
KEY(id),
|
||||||
|
PRIMARY KEY(bond_id),
|
||||||
|
FOREIGN KEY (bond_id) REFERENCES BlockchainBonds(bond_id)
|
||||||
|
);
|
||||||
|
|
||||||
CREATE TABLE DirectConvert(
|
CREATE TABLE DirectConvert(
|
||||||
id INT NOT NULL AUTO_INCREMENT,
|
id INT NOT NULL AUTO_INCREMENT,
|
||||||
floID CHAR(34) NOT NULL,
|
floID CHAR(34) NOT NULL,
|
||||||
@ -225,6 +258,7 @@ CREATE TABLE DirectConvert(
|
|||||||
out_txid VARCHAR(128),
|
out_txid VARCHAR(128),
|
||||||
locktime TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
locktime TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
status VARCHAR(50) NOT NULL,
|
status VARCHAR(50) NOT NULL,
|
||||||
|
PRIMARY KEY(id)
|
||||||
);
|
);
|
||||||
|
|
||||||
/* Backup Feature (Tables & Triggers) */
|
/* Backup Feature (Tables & Triggers) */
|
||||||
|
|||||||
@ -1,12 +1,14 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
const blockchain = require('./blockchain');
|
const blockchain = require('./blockchain');
|
||||||
const conversion_rates = require('./services/conversion').getRate;
|
const conversion_rates = require('./services/conversion').getRate;
|
||||||
|
const bond_util = require('./services/bonds').util;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
LAUNCH_SELLER_TAG,
|
LAUNCH_SELLER_TAG,
|
||||||
MAXIMUM_LAUNCH_SELL_CHIPS,
|
MAXIMUM_LAUNCH_SELL_CHIPS,
|
||||||
} = require('./_constants')["market"];
|
} = require('./_constants')["market"];
|
||||||
|
|
||||||
|
var DB; //container for database
|
||||||
const _sql = require('./_constants').sql;
|
const _sql = require('./_constants').sql;
|
||||||
|
|
||||||
var updateBalance; // container for updateBalance function
|
var updateBalance; // container for updateBalance function
|
||||||
@ -15,19 +17,19 @@ const verifyTx = {};
|
|||||||
|
|
||||||
function confirmDepositFLO() {
|
function confirmDepositFLO() {
|
||||||
DB.query("SELECT id, floID, txid FROM DepositCoin 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 => {
|
results.forEach(r => {
|
||||||
verifyTx.FLO(req.floID, req.txid).then(amount => {
|
verifyTx.FLO(r.floID, r.txid).then(amount => {
|
||||||
addSellChipsIfLaunchSeller(req.floID, amount).then(txQueries => {
|
addSellChipsIfLaunchSeller(r.floID, amount).then(txQueries => {
|
||||||
txQueries.push(updateBalance.add(req.floID, "FLO", amount));
|
txQueries.push(updateBalance.add(r.floID, "FLO", amount));
|
||||||
txQueries.push(["UPDATE DepositCoin SET status=?, amount=? WHERE id=?", ["SUCCESS", amount, req.id]]);
|
txQueries.push(["UPDATE DepositCoin SET status=?, amount=? WHERE id=?", ["SUCCESS", amount, r.id]]);
|
||||||
DB.transaction(txQueries)
|
DB.transaction(txQueries)
|
||||||
.then(result => console.debug("FLO deposited:", req.floID, amount))
|
.then(result => console.debug("FLO deposited:", r.floID, amount))
|
||||||
.catch(error => console.error(error))
|
.catch(error => console.error(error))
|
||||||
}).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 DepositCoin SET status=? WHERE id=?", ["REJECTED", req.id])
|
DB.query("UPDATE DepositCoin SET status=? WHERE id=?", ["REJECTED", r.id])
|
||||||
.then(_ => null).catch(error => console.error(error));
|
.then(_ => null).catch(error => console.error(error));
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
@ -90,25 +92,25 @@ function addSellChipsIfLaunchSeller(floID, quantity) {
|
|||||||
|
|
||||||
function confirmDepositToken() {
|
function confirmDepositToken() {
|
||||||
DB.query("SELECT id, floID, txid FROM DepositToken WHERE status=?", ["PENDING"]).then(results => {
|
DB.query("SELECT id, floID, txid FROM DepositToken WHERE status=?", ["PENDING"]).then(results => {
|
||||||
results.forEach(req => {
|
results.forEach(r => {
|
||||||
verifyTx.token(req.floID, req.txid).then(({ token, amount, flo_amount }) => {
|
verifyTx.token(r.floID, r.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 => {
|
DB.query("SELECT id FROM DepositCoin where floID=? AND coin=? AND txid=?", [r.floID, "FLO", r.txid]).then(result => {
|
||||||
let txQueries = [];
|
let txQueries = [];
|
||||||
//Add the FLO balance if necessary
|
//Add the FLO balance if necessary
|
||||||
if (!result.length) {
|
if (!result.length) {
|
||||||
txQueries.push(updateBalance.add(req.floID, "FLO", flo_amount));
|
txQueries.push(updateBalance.add(r.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(["INSERT INTO DepositCoin(txid, floID, coin, amount, status) VALUES (?, ?, ?, ?, ?)", [r.txid, r.floID, "FLO", flo_amount, "SUCCESS"]]);
|
||||||
}
|
}
|
||||||
txQueries.push(["UPDATE DepositToken SET status=?, token=?, amount=? WHERE id=?", ["SUCCESS", token, amount, req.id]]);
|
txQueries.push(["UPDATE DepositToken SET status=?, token=?, amount=? WHERE id=?", ["SUCCESS", token, amount, r.id]]);
|
||||||
txQueries.push(updateBalance.add(req.floID, token, amount));
|
txQueries.push(updateBalance.add(r.floID, token, amount));
|
||||||
DB.transaction(txQueries)
|
DB.transaction(txQueries)
|
||||||
.then(result => console.debug("Token deposited:", req.floID, token, amount))
|
.then(result => console.debug("Token deposited:", r.floID, token, amount))
|
||||||
.catch(error => console.error(error));
|
.catch(error => console.error(error));
|
||||||
}).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 DepositToken SET status=? WHERE id=?", ["REJECTED", req.id])
|
DB.query("UPDATE DepositToken SET status=? WHERE id=?", ["REJECTED", r.id])
|
||||||
.then(_ => null).catch(error => console.error(error));
|
.then(_ => null).catch(error => console.error(error));
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
@ -142,24 +144,24 @@ verifyTx.token = function (sender, txid, currencyOnly = false) {
|
|||||||
|
|
||||||
function retryWithdrawalCoin() {
|
function retryWithdrawalCoin() {
|
||||||
DB.query("SELECT id, floID, coin, amount FROM WithdrawCoin 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));
|
results.forEach(r => blockchain.sendCoin.retry(r.floID, r.coin, r.amount, r.id));
|
||||||
}).catch(error => console.error(error));
|
}).catch(error => console.error(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
function retryWithdrawalToken() {
|
function retryWithdrawalToken() {
|
||||||
DB.query("SELECT id, floID, token, amount FROM WithdrawToken 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));
|
results.forEach(r => blockchain.sendToken.retry(r.floID, r.token, r.amount, r.id));
|
||||||
}).catch(error => console.error(error));
|
}).catch(error => console.error(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
function confirmWithdrawalFLO() {
|
function confirmWithdrawalFLO() {
|
||||||
DB.query("SELECT id, floID, amount, txid FROM WithdrawCoin 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 => {
|
results.forEach(r => {
|
||||||
floBlockchainAPI.getTx(req.txid).then(tx => {
|
floBlockchainAPI.getTx(r.txid).then(tx => {
|
||||||
if (!tx.blockheight || !tx.confirmations) //Still not confirmed
|
if (!tx.blockheight || !tx.confirmations) //Still not confirmed
|
||||||
return;
|
return;
|
||||||
DB.query("UPDATE WithdrawCoin SET status=? WHERE id=?", ["SUCCESS", req.id])
|
DB.query("UPDATE WithdrawCoin SET status=? WHERE id=?", ["SUCCESS", r.id])
|
||||||
.then(result => console.debug("FLO withdrawed:", req.floID, req.amount))
|
.then(result => console.debug("FLO withdrawed:", r.floID, r.amount))
|
||||||
.catch(error => console.error(error))
|
.catch(error => console.error(error))
|
||||||
}).catch(error => console.error(error));
|
}).catch(error => console.error(error));
|
||||||
})
|
})
|
||||||
@ -168,12 +170,12 @@ function confirmWithdrawalFLO() {
|
|||||||
|
|
||||||
function confirmWithdrawalBTC() {
|
function confirmWithdrawalBTC() {
|
||||||
DB.query("SELECT id, floID, amount, txid FROM WithdrawCoin 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 => {
|
results.forEach(r => {
|
||||||
btcOperator.getTx(req.txid).then(tx => {
|
btcOperator.getTx(r.txid).then(tx => {
|
||||||
if (!tx.blockhash || !tx.confirmations) //Still not confirmed
|
if (!tx.blockhash || !tx.confirmations) //Still not confirmed
|
||||||
return;
|
return;
|
||||||
DB.query("UPDATE WithdrawCoin SET status=? WHERE id=?", ["SUCCESS", req.id])
|
DB.query("UPDATE WithdrawCoin SET status=? WHERE id=?", ["SUCCESS", r.id])
|
||||||
.then(result => console.debug("BTC withdrawed:", req.floID, req.amount))
|
.then(result => console.debug("BTC withdrawed:", r.floID, r.amount))
|
||||||
.catch(error => console.error(error))
|
.catch(error => console.error(error))
|
||||||
}).catch(error => console.error(error));
|
}).catch(error => console.error(error));
|
||||||
})
|
})
|
||||||
@ -182,10 +184,10 @@ function confirmWithdrawalBTC() {
|
|||||||
|
|
||||||
function confirmWithdrawalToken() {
|
function confirmWithdrawalToken() {
|
||||||
DB.query("SELECT id, floID, token, amount, txid FROM WithdrawToken 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 => {
|
results.forEach(r => {
|
||||||
floTokenAPI.getTx(req.txid).then(tx => {
|
floTokenAPI.getTx(r.txid).then(tx => {
|
||||||
DB.query("UPDATE WithdrawToken SET status=? WHERE id=?", ["SUCCESS", req.id])
|
DB.query("UPDATE WithdrawToken SET status=? WHERE id=?", ["SUCCESS", r.id])
|
||||||
.then(result => console.debug("Token withdrawed:", req.floID, req.token, req.amount))
|
.then(result => console.debug("Token withdrawed:", r.floID, r.token, r.amount))
|
||||||
.catch(error => console.error(error));
|
.catch(error => console.error(error));
|
||||||
}).catch(error => console.error(error));
|
}).catch(error => console.error(error));
|
||||||
})
|
})
|
||||||
@ -216,27 +218,27 @@ verifyTx.BTC = function (sender, txid) {
|
|||||||
|
|
||||||
function verifyConvert() {
|
function verifyConvert() {
|
||||||
DB.query("SELECT id, floID, mode, in_txid FROM DirectConvert WHERE status=? AND coin=?", ["PENDING", "BTC"]).then(results => {
|
DB.query("SELECT id, floID, mode, in_txid FROM DirectConvert WHERE status=? AND coin=?", ["PENDING", "BTC"]).then(results => {
|
||||||
results.forEach(req => {
|
results.forEach(r => {
|
||||||
if (mode == _sql.CONVERT_MODE_GET) {
|
if (mode == _sql.CONVERT_MODE_GET) {
|
||||||
verifyTx.token(req.floID, req.in_txid, true).then(({ amount }) => {
|
verifyTx.token(r.floID, r.in_txid, true).then(({ amount }) => {
|
||||||
conversion_rates.BTC_INR().then(rate => {
|
conversion_rates.BTC_INR().then(rate => {
|
||||||
blockchain.convertToCoin.init(req.floID, "BTC", amount, amount / rate, req.id)
|
blockchain.convertToCoin.init(r.floID, "BTC", amount, amount / rate, r.id)
|
||||||
}).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 DirectConvert SET status=? WHERE id=?", ["REJECTED", req.id])
|
DB.query("UPDATE DirectConvert SET status=? WHERE id=?", ["REJECTED", r.id])
|
||||||
.then(_ => null).catch(error => console.error(error));
|
.then(_ => null).catch(error => console.error(error));
|
||||||
});
|
});
|
||||||
} else if (mode == _sql.CONVERT_MODE_PUT) {
|
} else if (mode == _sql.CONVERT_MODE_PUT) {
|
||||||
verifyTx.BTC(req.floID, req.in_txid).then(quantity => {
|
verifyTx.BTC(r.floID, r.in_txid).then(quantity => {
|
||||||
conversion_rates.BTC_INR().then(rate => {
|
conversion_rates.BTC_INR().then(rate => {
|
||||||
blockchain.convertFromCoin.init(req.floID, quantity * rate, quantity, req.id)
|
blockchain.convertFromCoin.init(r.floID, quantity * rate, quantity, r.id)
|
||||||
}).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 DirectConvert SET status=? WHERE id=?", ["REJECTED", req.id])
|
DB.query("UPDATE DirectConvert SET status=? WHERE id=?", ["REJECTED", r.id])
|
||||||
.then(_ => null).catch(error => console.error(error));
|
.then(_ => null).catch(error => console.error(error));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -246,48 +248,79 @@ function verifyConvert() {
|
|||||||
|
|
||||||
function retryConvert() {
|
function retryConvert() {
|
||||||
DB.query("SELECT id, floID, mode, amount, quantity FROM DirectConvert WHERE status=? AND coin=?", ["PROCESSING", "BTC"]).then(results => {
|
DB.query("SELECT id, floID, mode, amount, quantity FROM DirectConvert WHERE status=? AND coin=?", ["PROCESSING", "BTC"]).then(results => {
|
||||||
results.forEach(req => {
|
results.forEach(r => {
|
||||||
if (mode == _sql.CONVERT_MODE_GET)
|
if (mode == _sql.CONVERT_MODE_GET)
|
||||||
blockchain.convertToCoin.retry(req.floID, "BTC", req.quantity, req.id);
|
blockchain.convertToCoin.retry(r.floID, "BTC", r.quantity, r.id);
|
||||||
else if (mode == _sql.CONVERT_MODE_PUT)
|
else if (mode == _sql.CONVERT_MODE_PUT)
|
||||||
blockchain.convertFromCoin.retry(req.floID, req.amount, req.id)
|
blockchain.convertFromCoin.retry(r.floID, r.amount, r.id)
|
||||||
})
|
})
|
||||||
}).catch(error => console.error(error))
|
}).catch(error => console.error(error))
|
||||||
}
|
}
|
||||||
|
|
||||||
function confirmConvert() {
|
function confirmConvert() {
|
||||||
DB.query("SELECT id, floID, mode, amount, quantity, out_txid FROM DirectConvert WHERE status=? AND coin=?", ["WAITING_CONFIRMATION", "BTC"]).then(results => {
|
DB.query("SELECT id, floID, mode, amount, quantity, out_txid FROM DirectConvert WHERE status=? AND coin=?", ["WAITING_CONFIRMATION", "BTC"]).then(results => {
|
||||||
results.forEach(req => {
|
results.forEach(r => {
|
||||||
if (mode == _sql.CONVERT_MODE_GET)
|
if (mode == _sql.CONVERT_MODE_GET)
|
||||||
btcOperator.getTx(req.out_txid).then(tx => {
|
btcOperator.getTx(r.out_txid).then(tx => {
|
||||||
if (!tx.blockhash || !tx.confirmations) //Still not confirmed
|
if (!tx.blockhash || !tx.confirmations) //Still not confirmed
|
||||||
return;
|
return;
|
||||||
DB.query("UPDATE DirectConvert SET status=? WHERE id=?", ["SUCCESS", req.id])
|
DB.query("UPDATE DirectConvert SET status=? WHERE id=?", ["SUCCESS", r.id])
|
||||||
.then(result => console.debug(`${req.floID} converted ${amount} to ${req.quantity} BTC`))
|
.then(result => console.debug(`${r.floID} converted ${amount} to ${r.quantity} BTC`))
|
||||||
.catch(error => console.error(error))
|
.catch(error => console.error(error))
|
||||||
}).catch(error => console.error(error));
|
}).catch(error => console.error(error));
|
||||||
else if (mode == _sql.CONVERT_MODE_PUT)
|
else if (mode == _sql.CONVERT_MODE_PUT)
|
||||||
floTokenAPI.getTx(req.out_txid).then(tx => {
|
floTokenAPI.getTx(r.out_txid).then(tx => {
|
||||||
DB.query("UPDATE DirectConvert SET status=? WHERE id=?", ["SUCCESS", req.id])
|
DB.query("UPDATE DirectConvert SET status=? WHERE id=?", ["SUCCESS", r.id])
|
||||||
.then(result => console.debug(`${req.floID} converted ${req.quantity} BTC to ${amount}`))
|
.then(result => console.debug(`${r.floID} converted ${r.quantity} BTC to ${amount}`))
|
||||||
.catch(error => console.error(error));
|
.catch(error => console.error(error));
|
||||||
}).catch(error => console.error(error));
|
}).catch(error => console.error(error));
|
||||||
})
|
})
|
||||||
}).catch(error => console.error(error));
|
}).catch(error => console.error(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function retryBondClosing() {
|
||||||
|
DB.query("SELECT id, floID, amount FROM CloseBondTransact WHERE status=?", ["PENDING"]).then(results => {
|
||||||
|
results.forEach(r => blockchain.bondTransact.retry(r.floID, r.amount, r.id))
|
||||||
|
}).catch(error => console.error(error))
|
||||||
|
}
|
||||||
|
|
||||||
|
function confirmBondClosing() {
|
||||||
|
DB.query("SELECT * FROM CloseBondTransact WHERE status=?", ["WAITING_CONFIRMATION"]).then(result => {
|
||||||
|
results.forEach(r => {
|
||||||
|
floTokenAPI.getTx(r.txid).then(tx => {
|
||||||
|
let closeBondString = bond_util.stringify.end(r.bond_id, r.end_date, r.btc_net, r.usd_net, r.amount, r.ref_sign, r.txid);
|
||||||
|
floBlockchainAPI.writeData(global.myFloID, closeBondString, global.myPrivKey, bond_util.config.adminID).then(txid => {
|
||||||
|
DB.query("UPDATE CloseBondTransact SET status=?, close_id=? WHERE id=?", ["SUCCESS", txid, r.id])
|
||||||
|
.then(result => console.debug("Bond closed:", r.bond_id))
|
||||||
|
.catch(error => console.error(error));
|
||||||
|
}).catch(error => console.error(error))
|
||||||
|
}).catch(error => console.error(error));
|
||||||
|
})
|
||||||
|
}).catch(error => reject(error))
|
||||||
|
}
|
||||||
|
|
||||||
|
function processAll() {
|
||||||
|
confirmDepositFLO();
|
||||||
|
confirmDepositToken();
|
||||||
|
retryWithdrawalCoin();
|
||||||
|
retryWithdrawalToken();
|
||||||
|
confirmWithdrawalFLO();
|
||||||
|
confirmWithdrawalBTC();
|
||||||
|
confirmWithdrawalToken();
|
||||||
|
verifyConvert();
|
||||||
|
retryConvert();
|
||||||
|
confirmConvert();
|
||||||
|
retryBondClosing();
|
||||||
|
confirmBondClosing();
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
blockchain,
|
blockchain,
|
||||||
confirmDepositFLO,
|
process: processAll,
|
||||||
confirmDepositToken,
|
set DB(db) {
|
||||||
retryWithdrawalCoin,
|
DB = db;
|
||||||
retryWithdrawalToken,
|
blockchain.DB = db;
|
||||||
confirmWithdrawalFLO,
|
},
|
||||||
confirmWithdrawalBTC,
|
|
||||||
confirmWithdrawalToken,
|
|
||||||
verifyConvert,
|
|
||||||
retryConvert,
|
|
||||||
confirmConvert,
|
|
||||||
set updateBalance(f) {
|
set updateBalance(f) {
|
||||||
updateBalance = f;
|
updateBalance = f;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,18 +2,20 @@
|
|||||||
|
|
||||||
var collectAndCall; //container for collectAndCall function from backup module
|
var collectAndCall; //container for collectAndCall function from backup module
|
||||||
var chests; //container for blockchain ids (where assets are stored)
|
var chests; //container for blockchain ids (where assets are stored)
|
||||||
|
var DB; //container for database
|
||||||
|
|
||||||
const WITHDRAWAL_MESSAGE = "(withdrawal from market)",
|
const TYPE_TOKEN = "TOKEN",
|
||||||
TYPE_TOKEN = "TOKEN",
|
|
||||||
TYPE_COIN = "COIN",
|
TYPE_COIN = "COIN",
|
||||||
TYPE_CONVERT = "CONVERT";
|
TYPE_CONVERT = "CONVERT",
|
||||||
|
TYPE_BOND = "BOND";
|
||||||
|
|
||||||
const balance_locked = {},
|
const balance_locked = {},
|
||||||
balance_cache = {},
|
balance_cache = {},
|
||||||
callbackCollection = {
|
callbackCollection = {
|
||||||
[TYPE_COIN]: {},
|
[TYPE_COIN]: {},
|
||||||
[TYPE_TOKEN]: {},
|
[TYPE_TOKEN]: {},
|
||||||
[TYPE_CONVERT]: {}
|
[TYPE_CONVERT]: {},
|
||||||
|
[TYPE_BOND]: {}
|
||||||
};
|
};
|
||||||
|
|
||||||
function getBalance(sinkID, asset) {
|
function getBalance(sinkID, asset) {
|
||||||
@ -55,43 +57,43 @@ function getSinkID(quantity, asset, sinkList = null) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendTx(floID, asset, quantity, sinkID, sinkKey) {
|
const WITHDRAWAL_MESSAGE = {
|
||||||
|
[TYPE_COIN]: "(withdrawal from market)",
|
||||||
|
[TYPE_TOKEN]: "(withdrawal from market)",
|
||||||
|
[TYPE_CONVERT]: "(convert coin)",
|
||||||
|
[TYPE_BOND]: "(bond closing)"
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendTx(floID, asset, quantity, sinkID, sinkKey, message) {
|
||||||
switch (asset) {
|
switch (asset) {
|
||||||
case "FLO":
|
case "FLO":
|
||||||
return floBlockchainAPI.sendTx(sinkID, floID, quantity, sinkKey, WITHDRAWAL_MESSAGE);
|
return floBlockchainAPI.sendTx(sinkID, floID, quantity, sinkKey, message);
|
||||||
case "BTC":
|
case "BTC":
|
||||||
let btc_sinkID = btcOperator.convert.legacy2bech(sinkID),
|
let btc_sinkID = btcOperator.convert.legacy2bech(sinkID),
|
||||||
btc_receiver = btcOperator.convert.legacy2bech(floID);
|
btc_receiver = btcOperator.convert.legacy2bech(floID);
|
||||||
return btcOperator.sendTx(btc_sinkID, sinkKey, btc_receiver, quantity, null);
|
return btcOperator.sendTx(btc_sinkID, sinkKey, btc_receiver, quantity, null);
|
||||||
default:
|
default:
|
||||||
return floTokenAPI.sendToken(sinkKey, quantity, floID, WITHDRAWAL_MESSAGE, asset);
|
return floTokenAPI.sendToken(sinkKey, quantity, floID, message, asset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const tableUpdate = {
|
const updateSyntax = {
|
||||||
[TYPE_COIN]: (id, txid) => {
|
[TYPE_COIN]: "UPDATE WithdrawCoin SET status=?, txid=? WHERE id=?",
|
||||||
DB.query("UPDATE WithdrawCoin SET status=?, txid=? WHERE id=?", ["WAITING_CONFIRMATION", txid, id])
|
[TYPE_TOKEN]: "UPDATE WithdrawToken SET status=?, txid=? WHERE id=?",
|
||||||
.then(_ => null).catch(error => console.error(error))
|
[TYPE_CONVERT]: "UPDATE DirectConvert SET status=?, out_txid=? WHERE id=?",
|
||||||
},
|
[TYPE_BOND]: "UPDATE CloseBondTransact SET status=?, txid=? WHERE id=?"
|
||||||
[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) {
|
function sendAsset(floID, asset, quantity, type, id) {
|
||||||
getSinkID(quantity, asset).then(sinkID => {
|
getSinkID(quantity, asset).then(sinkID => {
|
||||||
let callback = (sinkKey) => {
|
let callback = (sinkKey) => {
|
||||||
//Send asset to user via API
|
//Send asset to user via API
|
||||||
sendTx(floID, asset, quantity, sinkID, sinkKey).then(txid => {
|
sendTx(floID, asset, quantity, sinkID, sinkKey, WITHDRAWAL_MESSAGE[type]).then(txid => {
|
||||||
if (!txid)
|
if (!txid)
|
||||||
console.error("Transaction not successful");
|
console.error("Transaction not successful");
|
||||||
else //Transaction was successful, Add in DB
|
else //Transaction was successful, Add in DB
|
||||||
tableUpdate[type](id, txid);
|
DB.query(updateSyntax[type], ["WAITING_CONFIRMATION", txid, id])
|
||||||
|
.then(_ => null).catch(error => console.error(error));
|
||||||
}).catch(error => console.error(error)).finally(_ => {
|
}).catch(error => console.error(error)).finally(_ => {
|
||||||
delete callbackCollection[type][id];
|
delete callbackCollection[type][id];
|
||||||
balance_locked[sinkID][asset] -= quantity;
|
balance_locked[sinkID][asset] -= quantity;
|
||||||
@ -114,8 +116,7 @@ function sendCoin_init(floID, coin, quantity) {
|
|||||||
function sendCoin_retry(floID, coin, quantity, id) {
|
function sendCoin_retry(floID, coin, quantity, id) {
|
||||||
if (id in callbackCollection[TYPE_COIN])
|
if (id in callbackCollection[TYPE_COIN])
|
||||||
console.debug("A callback is already pending for this Coin transfer");
|
console.debug("A callback is already pending for this Coin transfer");
|
||||||
else
|
else sendAsset(floID, coin, quantity, TYPE_COIN, id);
|
||||||
sendAsset(floID, coin, quantity, TYPE_COIN, id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendToken_init(floID, token, quantity) {
|
function sendToken_init(floID, token, quantity) {
|
||||||
@ -127,8 +128,7 @@ function sendToken_init(floID, token, quantity) {
|
|||||||
function sendToken_retry(floID, token, quantity, id) {
|
function sendToken_retry(floID, token, quantity, id) {
|
||||||
if (id in callbackCollection[TYPE_TOKEN])
|
if (id in callbackCollection[TYPE_TOKEN])
|
||||||
console.debug("A callback is already pending for this Token transfer");
|
console.debug("A callback is already pending for this Token transfer");
|
||||||
else
|
else sendAsset(floID, token, quantity, TYPE_TOKEN, id);
|
||||||
sendAsset(floID, token, quantity, TYPE_TOKEN, id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function convertToCoin_init(floID, coin, currency_amount, coin_quantity, id) {
|
function convertToCoin_init(floID, coin, currency_amount, coin_quantity, id) {
|
||||||
@ -139,9 +139,8 @@ function convertToCoin_init(floID, coin, currency_amount, coin_quantity, id) {
|
|||||||
|
|
||||||
function convertToCoin_retry(floID, coin, coin_quantity, id) {
|
function convertToCoin_retry(floID, coin, coin_quantity, id) {
|
||||||
if (id in callbackCollection[TYPE_CONVERT])
|
if (id in callbackCollection[TYPE_CONVERT])
|
||||||
console.debug("A callback is already pending for this Coin Convert");
|
console.debug("A callback is already pending for this Coin convert");
|
||||||
else
|
else sendAsset(floID, coin, coin_quantity, TYPE_CONVERT, id);
|
||||||
sendAsset(floID, coin, coin_quantity, TYPE_CONVERT, id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function convertFromCoin_init(floID, currency_amount, coin_quantity, id) {
|
function convertFromCoin_init(floID, currency_amount, coin_quantity, id) {
|
||||||
@ -153,8 +152,13 @@ function convertFromCoin_init(floID, currency_amount, coin_quantity, id) {
|
|||||||
function convertFromCoin_retry(floID, current_amount, id) {
|
function convertFromCoin_retry(floID, current_amount, id) {
|
||||||
if (id in callbackCollection[TYPE_CONVERT])
|
if (id in callbackCollection[TYPE_CONVERT])
|
||||||
console.debug("A callback is already pending for this Coin Convert");
|
console.debug("A callback is already pending for this Coin Convert");
|
||||||
else
|
else sendAsset(floID, floGlobals.currency, current_amount, TYPE_CONVERT, id);
|
||||||
sendAsset(floID, floGlobals.currency, current_amount, TYPE_CONVERT, id);
|
}
|
||||||
|
|
||||||
|
function bondTransact_retry(floID, amount, id) {
|
||||||
|
if (id in callbackCollection[TYPE_BOND])
|
||||||
|
console.debug("A callback is already pending for this Bond closing");
|
||||||
|
else sendAsset(floID, floGlobals.currency, amount, TYPE_BOND, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
@ -182,5 +186,11 @@ module.exports = {
|
|||||||
convertFromCoin: {
|
convertFromCoin: {
|
||||||
init: convertFromCoin_init,
|
init: convertFromCoin_init,
|
||||||
retry: convertFromCoin_retry
|
retry: convertFromCoin_retry
|
||||||
|
},
|
||||||
|
bondTransact: {
|
||||||
|
retry: bondTransact_retry
|
||||||
|
},
|
||||||
|
set DB(db) {
|
||||||
|
DB = db;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
const coupling = require('./coupling');
|
const coupling = require('./coupling');
|
||||||
const background = require('./background');
|
const background = require('./background');
|
||||||
|
|
||||||
const blockchain = background.blockchain;
|
const blockchain = background.blockchain;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -504,16 +505,7 @@ function periodicProcess() {
|
|||||||
floBlockchainAPI.promisedAPI('api/blocks?limit=1').then(result => {
|
floBlockchainAPI.promisedAPI('api/blocks?limit=1').then(result => {
|
||||||
if (lastSyncBlockHeight < result.blocks[0].height) {
|
if (lastSyncBlockHeight < result.blocks[0].height) {
|
||||||
lastSyncBlockHeight = result.blocks[0].height;
|
lastSyncBlockHeight = result.blocks[0].height;
|
||||||
background.confirmDepositFLO();
|
background.process();
|
||||||
background.confirmDepositToken();
|
|
||||||
background.retryWithdrawalCoin();
|
|
||||||
background.retryWithdrawalToken();
|
|
||||||
background.confirmWithdrawalFLO();
|
|
||||||
background.confirmWithdrawalBTC();
|
|
||||||
background.confirmWithdrawalToken();
|
|
||||||
background.verifyConvert();
|
|
||||||
background.retryConvert();
|
|
||||||
background.confirmConvert();
|
|
||||||
console.debug("Last Block :", lastSyncBlockHeight);
|
console.debug("Last Block :", lastSyncBlockHeight);
|
||||||
}
|
}
|
||||||
}).catch(error => console.error(error));
|
}).catch(error => console.error(error));
|
||||||
@ -558,6 +550,7 @@ module.exports = {
|
|||||||
set DB(db) {
|
set DB(db) {
|
||||||
DB = db;
|
DB = db;
|
||||||
coupling.DB = db;
|
coupling.DB = db;
|
||||||
|
blockchain.DB = db;
|
||||||
},
|
},
|
||||||
set assetList(assets) {
|
set assetList(assets) {
|
||||||
assetList = assets;
|
assetList = assets;
|
||||||
|
|||||||
255
src/services/bonds.js
Normal file
255
src/services/bonds.js
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const eCode = require('../eCode_test')// require('../../docs/scripts/floExchangeAPI').errorCode;
|
||||||
|
const getRate = require('./conversion').getRate;
|
||||||
|
|
||||||
|
var DB; //container for database
|
||||||
|
|
||||||
|
const blockchainBond = (function () {
|
||||||
|
const magnitude = m => {
|
||||||
|
switch (m) {
|
||||||
|
case "thousand": return 1000;
|
||||||
|
case "lakh": case "lakhs": return 100000;
|
||||||
|
case "million": return 1000000;
|
||||||
|
case "crore": case "crores": return 10000000;
|
||||||
|
default: return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const parseNumber = (str) => {
|
||||||
|
let n = 0,
|
||||||
|
g = 0;
|
||||||
|
str.toLowerCase().replace(/,/g, '').split(" ").forEach(s => {
|
||||||
|
if (!isNaN(s))
|
||||||
|
g = parseFloat(s);
|
||||||
|
else {
|
||||||
|
let m = magnitude(s);
|
||||||
|
if (m !== null) {
|
||||||
|
n += m * g;
|
||||||
|
g = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return n + g;
|
||||||
|
}
|
||||||
|
const parsePeriod = (str) => {
|
||||||
|
let P = '', n = 0;
|
||||||
|
str.toLowerCase().replace(/,/g, '').split(" ").forEach(s => {
|
||||||
|
if (!isNaN(s))
|
||||||
|
n = parseFloat(s);
|
||||||
|
else switch (s) {
|
||||||
|
case "year(s)": case "year": case "years": P += (n + 'Y'); n = 0; break;
|
||||||
|
case "month(s)": case "month": case "months": P += (n + 'M'); n = 0; break;
|
||||||
|
case "day(s)": case "day": case "days": P += (n + 'D'); n = 0; break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return P;
|
||||||
|
}
|
||||||
|
const dateFormat = (date = null) => {
|
||||||
|
let d = (date ? new Date(date) : new Date()).toDateString();
|
||||||
|
return [d.substring(8, 10), d.substring(4, 7), d.substring(11, 15)].join(" ");
|
||||||
|
}
|
||||||
|
const yearDiff = (d1 = null, d2 = null) => {
|
||||||
|
d1 = d1 ? new Date(d1) : new Date();
|
||||||
|
d2 = d2 ? new Date(d2) : new Date();
|
||||||
|
let y = d1.getYear() - d2.getYear(),
|
||||||
|
m = d1.getMonth() - d2.getMonth(),
|
||||||
|
d = d1.getDate() - d2.getDate()
|
||||||
|
return y + m / 12 + d / 365;
|
||||||
|
}
|
||||||
|
|
||||||
|
const dateAdder = function (start_date, duration) {
|
||||||
|
let date = new Date(start_date);
|
||||||
|
let y = parseInt(duration.match(/\d+Y/)),
|
||||||
|
m = parseInt(duration.match(/\d+M/)),
|
||||||
|
d = parseInt(duration.match(/\d+D/));
|
||||||
|
if (!isNaN(y))
|
||||||
|
date.setFullYear(date.getFullYear() + y);
|
||||||
|
if (!isNaN(m))
|
||||||
|
date.setMonth(date.getMonth() + m);
|
||||||
|
if (!isNaN(d))
|
||||||
|
date.setDate(date.getDate() + d);
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
|
||||||
|
function calcNetValue(BTC_base, BTC_net, startDate, minIpa, maxPeriod, cut, amount, USD_base, USD_net) {
|
||||||
|
let gain, duration, interest, net;
|
||||||
|
gain = (BTC_net - BTC_base) / BTC_base;
|
||||||
|
duration = yearDiff(Math.min(Date.now(), dateAdder(startDate, maxPeriod).getTime()), startDate);
|
||||||
|
interest = Math.max(cut * gain, minIpa * duration);
|
||||||
|
net = amount / USD_base;
|
||||||
|
net += net * interest;
|
||||||
|
return net * USD_net;
|
||||||
|
}
|
||||||
|
|
||||||
|
function stringify_main(BTC_base, start_date, guaranteed_interest, guarantee_period, gain_cut, amount, USD_base, lockin_period, floID) {
|
||||||
|
return [
|
||||||
|
`Product: RanchiMall Bitcoin Bond`,
|
||||||
|
`Base value: ${BTC_base} USD`,
|
||||||
|
`Date of bond start: ${start_date}`,
|
||||||
|
`Guaranteed interest: ${guaranteed_interest}% per annum simple for ${guarantee_period}`,
|
||||||
|
`Bond value: guaranteed interest or ${gain_cut}% of the gains whichever is higher`,
|
||||||
|
`Amount invested: Rs ${amount}`,
|
||||||
|
`USD INR rate at start: ${USD_base}`,
|
||||||
|
`Lockin period: ${lockin_period}`,
|
||||||
|
`FLO ID of Bond Holder: ${floID}`
|
||||||
|
].join("|");
|
||||||
|
}
|
||||||
|
|
||||||
|
function parse_main(data) {
|
||||||
|
//Data (add bond) sent by admin
|
||||||
|
let details = {};
|
||||||
|
data.split("|").forEach(d => {
|
||||||
|
d = d.split(': ');
|
||||||
|
switch (d[0].toLowerCase()) {
|
||||||
|
case "base value":
|
||||||
|
details["BTC_base"] = parseNumber(d[1].slice(0, -4)); break;
|
||||||
|
case "date of bond start":
|
||||||
|
details["startDate"] = new Date(d[1]); break;
|
||||||
|
case "guaranteed interest":
|
||||||
|
details["minIpa"] = parseFloat(d[1].match(/\d+%/)) / 100;
|
||||||
|
details["maxPeriod"] = parsePeriod(d[1].match(/for .+/).toString()); break;
|
||||||
|
case "bond value":
|
||||||
|
details["cut"] = parseFloat(d[1].match(/\d+%/)) / 100; break;
|
||||||
|
case "amount invested":
|
||||||
|
details["amount"] = parseNumber(d[1].substring(3)); break;
|
||||||
|
case "usd inr rate at start":
|
||||||
|
details["USD_base"] = parseFloat(d[1]); break;
|
||||||
|
case "lockin period":
|
||||||
|
details["lockinPeriod"] = parsePeriod(d[1]); break;
|
||||||
|
case "flo id of bond holder":
|
||||||
|
details["floID"] = d[1]; break;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return details;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function stringify_end(bond_id, end_date, BTC_net, USD_net, amount, ref_sign, payment_ref) {
|
||||||
|
return [
|
||||||
|
`Product: RanchiMall Bitcoin Bond`,
|
||||||
|
`Bond: ${bond_id}`,
|
||||||
|
`End value: ${BTC_net} USD`,
|
||||||
|
`Date of bond end: ${end_date}`,
|
||||||
|
`USD INR rate at end: ${USD_net}`,
|
||||||
|
`Amount withdrawn: Rs ${amount} via ${payment_ref}`,
|
||||||
|
`Reference: ${ref_sign}`
|
||||||
|
].join("|");
|
||||||
|
}
|
||||||
|
|
||||||
|
function parse_end(data) {
|
||||||
|
//Data (end bond) send by market nodes
|
||||||
|
let details = {};
|
||||||
|
data.split("|").forEach(d => {
|
||||||
|
d = d.split(': ');
|
||||||
|
switch (d[0].toLowerCase()) {
|
||||||
|
case "bond":
|
||||||
|
details["bondID"] = d[1];
|
||||||
|
case "end value":
|
||||||
|
details["BTC_net"] = parseNumber(d[1].slice(0, -4)); break;
|
||||||
|
case "date of bond end":
|
||||||
|
details["endDate"] = new Date(d[1]); break;
|
||||||
|
case "amount withdrawn":
|
||||||
|
details["amountFinal"] = parseNumber(d[1].match(/\d.+ via/).toString());
|
||||||
|
details["payment_refRef"] = d[1].match(/via .+/).toString().substring(4); break;
|
||||||
|
case "usd inr rate at end":
|
||||||
|
details["USD_net"] = parseFloat(d[1]); break;
|
||||||
|
case "reference":
|
||||||
|
details["refSign"] = d[1]; break;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
dateAdder,
|
||||||
|
dateFormat,
|
||||||
|
calcNetValue,
|
||||||
|
parse: {
|
||||||
|
main: parse_main,
|
||||||
|
end: parse_end
|
||||||
|
},
|
||||||
|
stringify: {
|
||||||
|
main: stringify_main,
|
||||||
|
end: stringify_end
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
blockchainBond.config = {
|
||||||
|
adminID: "FBBstZ2GretgQqDP55yt8iVd4KNZkdvEzH",
|
||||||
|
application: "BlockchainBonds",
|
||||||
|
productStr: "Product: RanchiMall Bitcoin Bond",
|
||||||
|
}
|
||||||
|
|
||||||
|
function refreshBlockchainData(nodeList = []) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
DB.query("SELECT num FROM LastTx WHERE floID=?", [blockchainBond.config.adminID]).then(result => {
|
||||||
|
let lastTx = result.length ? result[0].num : 0;
|
||||||
|
floBlockchainAPI.readData(blockchainBond.config.adminID, {
|
||||||
|
ignoreOld: lastTx,
|
||||||
|
senders: [nodeList].concat(blockchainBond.config.adminID), //sentOnly: true,
|
||||||
|
tx: true,
|
||||||
|
filter: d => d.startsWith(blockchainBond.config.productStr)
|
||||||
|
}).then(result => {
|
||||||
|
let promises = [];
|
||||||
|
result.data.forEach(d => {
|
||||||
|
let bond = d.senders.has(blockchainBond.config.adminID) ? blockchainBond.parse.main(d.data) : null;
|
||||||
|
if (bond && bond.amount)
|
||||||
|
promises.push(DB.query("INSERT INTO BlockchainBonds(bond_id, floID, amount_in, begin_date, btc_base, usd_base, gain_cut, min_ipa, max_period, lockin_period) VALUES ? ON DUPLICATE KEY UPDATE bond_id=bond_id",
|
||||||
|
[[[d.txid, bond.floID, bond.amount, bond.startDate, bond.BTC_base, bond.USD_base, bond.cut, bond.minIpa, bond.maxPeriod, bond.lockinPeriod]]]));
|
||||||
|
else {
|
||||||
|
let details = blockchainBond.parse.end(d.data);
|
||||||
|
if (details.bondID && details.amountFinal)
|
||||||
|
promises.push(DB.query("UPDATE BlockchainBonds SET close_id=? amount_out=? WHERE bond_id=?", [d.txid, details.amountFinal, details.bondID]));
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
promises.push(DB.query("INSERT INTO LastTx (floID, num) VALUE (?, ?) ON DUPLICATE KEY UPDATE num=?", [blockchainBond.config.adminID, result.totalTxs, result.totalTxs]));
|
||||||
|
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 bond data might not have been saved in database correctly");
|
||||||
|
resolve(result.totalTxs);
|
||||||
|
})
|
||||||
|
}).catch(error => reject(error))
|
||||||
|
}).catch(error => reject(error))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeBond(bond_id, floID, ref) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
DB.query("SELECT status FROM CloseBondTransact WHERE bond_id=?", [bond_id]).then(result => {
|
||||||
|
if (result.length)
|
||||||
|
return reject(INVALID(eCode.DUPLICATE_ENTRY, `Bond closing already in process`));
|
||||||
|
DB.query("SELECT * FROM BlockchainBonds WHERE bond_id=?", [bond_id]).then(result => {
|
||||||
|
if (!result.length)
|
||||||
|
return reject(INVALID(eCode.NOT_FOUND, 'Bond not found'));
|
||||||
|
let bond = result[0];
|
||||||
|
if (bond.floID !== floID)
|
||||||
|
return reject(INVALID(eCode.NOT_OWNER, 'Bond doesnot belong to the user'));
|
||||||
|
if (bond.close_id)
|
||||||
|
return reject(INVALID(eCode.DUPLICATE_ENTRY, `Bond already closed (${bond.close_id})`));
|
||||||
|
if (Date.now() < blockchainBond.dateAdder(bond.begin_date, bond.lockin_period).getTime())
|
||||||
|
return reject(INVALID(eCode.INSUFFICIENT_PERIOD, 'Bond still in lock-in period'));
|
||||||
|
getRate.BTC_USD().then(btc_rate => {
|
||||||
|
getRate.USD_INR().then(usd_rate => {
|
||||||
|
let end_date = new Date(),
|
||||||
|
net_value = blockchainBond.calcNetValue(bond.btc_base, btc_rate, bond.begin_date, bond.min_ipa, bond.max_period, bond.gain_cut, bond.amount_in, bond.usd_base, usd_rate);
|
||||||
|
DB.query("INSERT INTO CloseBondTransact(bond_id, amount, end_date, btc_net, usd_net, ref_sign, status) VALUE ?", [[bond_id, net_value, end_date, btc_rate, usd_rate, ref, "PENDING"]])
|
||||||
|
.then(result => resolve({ "USD_net": usd_rate, "BTC_net": btc_rate, "amount_out": net_value, "end_date": end_date }))
|
||||||
|
.catch(error => reject(error))
|
||||||
|
}).catch(error => reject(error))
|
||||||
|
}).catch(error => reject(error))
|
||||||
|
}).catch(error => reject(error))
|
||||||
|
}).catch(error => reject(error))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
refresh: refreshBlockchainData,
|
||||||
|
set DB(db) {
|
||||||
|
DB = db;
|
||||||
|
},
|
||||||
|
util: blockchainBond,
|
||||||
|
closeBond
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user