Minor changes and Bug fixes
- deduce BTC fee from users - If timeout rejected tx are confirmed, refund the asset - Blockchain bond and Bob's fund withdraw now sends equivalent BTC to users (via BTC blockchain) - Fixed minor bugs - Changed toFixed (fn to limit the decimal) to toStandardDecimal (set_global.js)
This commit is contained in:
parent
821de1a6d7
commit
e4adaf7ed7
@ -288,6 +288,8 @@ CREATE TABLE DirectConvert(
|
||||
CREATE TABLE RefundTransact(
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
floID CHAR(34) NOT NULL,
|
||||
asset_type TINYINT NOT NULL,
|
||||
asset VARCHAR(32) NOT NULL,
|
||||
amount DECIMAL(16, 8),
|
||||
in_txid VARCHAR(128),
|
||||
out_txid VARCHAR(128),
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
(function (EXPORTS) { //btcOperator v1.0.12
|
||||
(function (EXPORTS) { //btcOperator v1.0.13
|
||||
/* BTC Crypto and API Operator */
|
||||
const btcOperator = EXPORTS;
|
||||
|
||||
@ -307,8 +307,8 @@
|
||||
parameters.receivers.forEach(id => !validateAddress(id) ? invalids.push(id) : null);
|
||||
if (invalids.length)
|
||||
throw "Invalid receivers:" + invalids;
|
||||
if (parameters.change_addr && !validateAddress(parameters.change_addr))
|
||||
throw "Invalid change_address:" + parameters.change_addr;
|
||||
if (parameters.change_address && !validateAddress(parameters.change_address))
|
||||
throw "Invalid change_address:" + parameters.change_address;
|
||||
//fee and amounts
|
||||
if ((typeof parameters.fee !== "number" || parameters.fee <= 0) && parameters.fee !== null) //fee = null (auto calc)
|
||||
throw "Invalid fee:" + parameters.fee;
|
||||
@ -323,16 +323,29 @@
|
||||
return parameters;
|
||||
}
|
||||
|
||||
function createTransaction(senders, redeemScripts, receivers, amounts, fee, change_addr) {
|
||||
function createTransaction(senders, redeemScripts, receivers, amounts, fee, change_address, fee_from_receiver) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let total_amount = parseFloat(amounts.reduce((t, a) => t + a, 0).toFixed(8));
|
||||
const tx = coinjs.transaction();
|
||||
let output_size = addOutputs(tx, receivers, amounts, change_addr);
|
||||
let output_size = addOutputs(tx, receivers, amounts, change_address);
|
||||
addInputs(tx, senders, redeemScripts, total_amount, fee, output_size).then(result => {
|
||||
if (result.change_amount > 0)
|
||||
if (result.change_amount > 0) //add change amount if any
|
||||
tx.outs[tx.outs.length - 1].value = parseInt(result.change_amount * SATOSHI_IN_BTC); //values are in satoshi
|
||||
else
|
||||
tx.outs.pop(); //remove the change output if no change_amount
|
||||
if (fee_from_receiver) { //deduce fee from receivers if fee_from_receiver
|
||||
let fee_remaining = parseInt(result.fee * SATOSHI_IN_BTC);
|
||||
for (let i = 0; i < tx.outs.length - 1 && fee_remaining > 0; i++) {
|
||||
if (fee_remaining < tx.outs[i].value) {
|
||||
tx.outs[i].value -= fee_remaining;
|
||||
fee_remaining = 0;
|
||||
} else {
|
||||
fee_remaining -= tx.outs[i].value;
|
||||
tx.outs[i].value = 0;
|
||||
}
|
||||
}
|
||||
if (fee_remaining > 0)
|
||||
return reject("Send amount is less than fee");
|
||||
}
|
||||
tx.outs = tx.outs.filter(o => o.value !== 0); //remove all output with value 0
|
||||
result.output_size = output_size;
|
||||
result.output_amount = total_amount;
|
||||
result.total_size = BASE_TX_SIZE + output_size + result.input_size;
|
||||
@ -342,10 +355,10 @@
|
||||
})
|
||||
}
|
||||
|
||||
function addInputs(tx, senders, redeemScripts, total_amount, fee, output_size) {
|
||||
function addInputs(tx, senders, redeemScripts, total_amount, fee, output_size, fee_from_receiver) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (fee !== null) {
|
||||
addUTXOs(tx, senders, redeemScripts, total_amount + fee, false).then(result => {
|
||||
addUTXOs(tx, senders, redeemScripts, fee_from_receiver ? total_amount : total_amount + fee, false).then(result => {
|
||||
result.fee = fee;
|
||||
resolve(result);
|
||||
}).catch(error => reject(error))
|
||||
@ -353,7 +366,10 @@
|
||||
get_fee_rate().then(fee_rate => {
|
||||
let net_fee = BASE_TX_SIZE * fee_rate;
|
||||
net_fee += (output_size * fee_rate);
|
||||
addUTXOs(tx, senders, redeemScripts, total_amount + net_fee, fee_rate).then(result => {
|
||||
(fee_from_receiver ?
|
||||
addUTXOs(tx, senders, redeemScripts, total_amount, false) :
|
||||
addUTXOs(tx, senders, redeemScripts, total_amount + net_fee, fee_rate)
|
||||
).then(result => {
|
||||
result.fee = parseFloat((net_fee + (result.input_size * fee_rate)).toFixed(8));
|
||||
result.fee_rate = fee_rate;
|
||||
resolve(result);
|
||||
@ -416,14 +432,14 @@
|
||||
})
|
||||
}
|
||||
|
||||
function addOutputs(tx, receivers, amounts, change_addr) {
|
||||
function addOutputs(tx, receivers, amounts, change_address) {
|
||||
let size = 0;
|
||||
for (let i in receivers) {
|
||||
tx.addoutput(receivers[i], amounts[i]);
|
||||
size += _sizePerOutput(receivers[i]);
|
||||
}
|
||||
tx.addoutput(change_addr, 0);
|
||||
size += _sizePerOutput(change_addr);
|
||||
tx.addoutput(change_address, 0);
|
||||
size += _sizePerOutput(change_address);
|
||||
return size;
|
||||
}
|
||||
|
||||
@ -464,9 +480,9 @@
|
||||
}
|
||||
*/
|
||||
|
||||
btcOperator.sendTx = function (senders, privkeys, receivers, amounts, fee, change_addr = null) {
|
||||
btcOperator.sendTx = function (senders, privkeys, receivers, amounts, fee = null, options = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
createSignedTx(senders, privkeys, receivers, amounts, fee, change_addr).then(result => {
|
||||
createSignedTx(senders, privkeys, receivers, amounts, fee, options).then(result => {
|
||||
debugger;
|
||||
broadcastTx(result.transaction.serialize())
|
||||
.then(txid => resolve(txid))
|
||||
@ -475,7 +491,7 @@
|
||||
})
|
||||
}
|
||||
|
||||
const createSignedTx = btcOperator.createSignedTx = function (senders, privkeys, receivers, amounts, fee = null, change_addr = null) {
|
||||
const createSignedTx = btcOperator.createSignedTx = function (senders, privkeys, receivers, amounts, fee = null, options = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
({
|
||||
@ -489,7 +505,7 @@
|
||||
receivers,
|
||||
amounts,
|
||||
fee,
|
||||
change_addr
|
||||
change_address: options.change_address
|
||||
}));
|
||||
} catch (e) {
|
||||
return reject(e)
|
||||
@ -504,7 +520,7 @@
|
||||
if (redeemScripts.includes(null)) //TODO: segwit
|
||||
return reject("Unable to get redeem-script");
|
||||
//create transaction
|
||||
createTransaction(senders, redeemScripts, receivers, amounts, fee, change_addr || senders[0]).then(result => {
|
||||
createTransaction(senders, redeemScripts, receivers, amounts, fee, options.change_address || senders[0], options.fee_from_receiver).then(result => {
|
||||
let tx = result.transaction;
|
||||
console.debug("Unsigned:", tx.serialize());
|
||||
new Set(wif_keys).forEach(key => console.debug("Signing key:", key, tx.sign(key, 1 /*sighashtype*/))); //Sign the tx using private key WIF
|
||||
@ -514,7 +530,7 @@
|
||||
})
|
||||
}
|
||||
|
||||
btcOperator.createTx = function (senders, receivers, amounts, fee = null, change_addr = null) {
|
||||
btcOperator.createTx = function (senders, receivers, amounts, fee = null, options = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
({
|
||||
@ -526,7 +542,7 @@
|
||||
receivers,
|
||||
amounts,
|
||||
fee,
|
||||
change_addr
|
||||
change_address: options.change_address
|
||||
}));
|
||||
} catch (e) {
|
||||
return reject(e)
|
||||
@ -535,7 +551,7 @@
|
||||
if (redeemScripts.includes(null)) //TODO: segwit
|
||||
return reject("Unable to get redeem-script");
|
||||
//create transaction
|
||||
createTransaction(senders, redeemScripts, receivers, amounts, fee, change_addr || senders[0]).then(result => {
|
||||
createTransaction(senders, redeemScripts, receivers, amounts, fee, options.change_address || senders[0], options.fee_from_receiver).then(result => {
|
||||
result.tx_hex = result.transaction.serialize();
|
||||
delete result.transaction;
|
||||
resolve(result);
|
||||
@ -543,7 +559,7 @@
|
||||
})
|
||||
}
|
||||
|
||||
btcOperator.createMultiSigTx = function (sender, redeemScript, receivers, amounts, fee = null) {
|
||||
btcOperator.createMultiSigTx = function (sender, redeemScript, receivers, amounts, fee = null, options = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
//validate tx parameters
|
||||
if (validateAddress(sender) !== "multisig")
|
||||
@ -561,13 +577,14 @@
|
||||
} = validateTxParameters({
|
||||
receivers,
|
||||
amounts,
|
||||
fee
|
||||
fee,
|
||||
change_address: options.change_address
|
||||
}));
|
||||
} catch (e) {
|
||||
return reject(e)
|
||||
}
|
||||
//create transaction
|
||||
createTransaction([sender], [redeemScript], receivers, amounts, fee, sender).then(result => {
|
||||
createTransaction([sender], [redeemScript], receivers, amounts, fee, options.change_address || sender, options.fee_from_receiver).then(result => {
|
||||
result.tx_hex = result.transaction.serialize();
|
||||
delete result.transaction;
|
||||
resolve(result);
|
||||
|
||||
@ -152,7 +152,7 @@ function retryVaultWithdrawal() {
|
||||
} else if (r.asset_type == pCode.ASSET_TYPE_TOKEN)
|
||||
blockchain.withdrawAsset.retry(r.floID, r.asset, r.amount, r.id)
|
||||
})
|
||||
}).catch(error => reject(error))
|
||||
}).catch(error => console.error(error))
|
||||
}
|
||||
|
||||
function confirmVaultWithdraw() {
|
||||
@ -210,7 +210,16 @@ verifyTx.BTC = function (sender, txid) {
|
||||
}
|
||||
|
||||
function verifyConvert() {
|
||||
DB.query("UPDATE DirectConvert SET r_status=? WHERE r_status=? AND locktime<?", [pCode.STATUS_REJECTED, pCode.STATUS_PENDING, new Date(Date.now() - REQUEST_TIMEOUT)]).then(result => {
|
||||
//Set all timeout convert request to refund mode (thus, asset will be refund if tx gets confirmed later)
|
||||
let req_timeout = new Date(Date.now() - REQUEST_TIMEOUT),
|
||||
to_refund_sql = "INSERT INTO RefundTransact (floID, in_txid, asset_type, asset, r_status)" +
|
||||
" SELECT floID, in_txid, ? AS asset_type, ? AS asset, r_status" +
|
||||
" WHERE r_status=? AND locktime<? AND mode=?";
|
||||
let txQueries = [];
|
||||
txQueries.push([to_refund_sql, [pCode.ASSET_TYPE_TOKEN, floGlobals.currency, pCode.STATUS_PENDING, req_timeout, pCode.CONVERT_MODE_GET]]);
|
||||
txQueries.push([to_refund_sql, [pCode.ASSET_TYPE_COIN, "BTC", pCode.STATUS_PENDING, req_timeout, pCode.CONVERT_MODE_PUT]]);
|
||||
txQueries.push(["UPDATE DirectConvert SET r_status=? WHERE r_status=? AND locktime<?", [pCode.STATUS_REJECTED, pCode.STATUS_PENDING, req_timeout]]);
|
||||
DB.transaction(txQueries).then(result => {
|
||||
DB.query("SELECT id, floID, mode, in_txid, amount, quantity FROM DirectConvert WHERE r_status=? AND coin=?", [pCode.STATUS_PENDING, "BTC"]).then(results => {
|
||||
results.forEach(r => {
|
||||
if (r.mode == pCode.CONVERT_MODE_GET) {
|
||||
@ -242,7 +251,7 @@ function verifyConvert() {
|
||||
}
|
||||
})
|
||||
}).catch(error => console.error(error))
|
||||
}).catch(error => reject(error))
|
||||
}).catch(error => console.error(error))
|
||||
}
|
||||
|
||||
function retryConvert() {
|
||||
@ -345,34 +354,75 @@ function confirmConvertFundWithdraw() {
|
||||
}
|
||||
|
||||
function verifyRefund() {
|
||||
DB.query("SELECT id, floID, in_txid FROM RefundTransact WHERE r_status=?", [pCode.STATUS_PENDING]).then(results => {
|
||||
DB.query("SELECT id, floID, asset_type, asset, in_txid FROM RefundTransact WHERE r_status=?", [pCode.STATUS_PENDING]).then(results => {
|
||||
results.forEach(r => {
|
||||
verifyTx.token(r.floID, r.in_txid, true)
|
||||
.then(({ amount }) => blockchain.refundTransact.init(r.floID, amount, r.id))
|
||||
if (r.ASSET_TYPE_COIN) {
|
||||
if (r.asset == "FLO")
|
||||
verifyTx.FLO(r.floID, r.in_txid)
|
||||
.then(amount => blockchain.refundTransact.init(r.floID, r.asset, amount, r.id))
|
||||
.catch(error => {
|
||||
console.error(error);
|
||||
if (error[0])
|
||||
DB.query("UPDATE RefundTransact SET r_status=? WHERE id=?", [pCode.STATUS_REJECTED, r.id])
|
||||
.then(_ => null).catch(error => console.error(error));
|
||||
});
|
||||
else if (r.asset == "BTC")
|
||||
verifyTx.BTC(r.floID, r.in_txid)
|
||||
.then(amount => blockchain.refundTransact.init(r.floID, r.asset, amount, r.id))
|
||||
.catch(error => {
|
||||
console.error(error);
|
||||
if (error[0])
|
||||
DB.query("UPDATE RefundTransact SET r_status=? WHERE id=?", [pCode.STATUS_REJECTED, r.id])
|
||||
.then(_ => null).catch(error => console.error(error));
|
||||
});
|
||||
} else if (r.ASSET_TYPE_TOKEN)
|
||||
verifyTx.token(r.floID, r.in_txid).then(({ token, amount }) => {
|
||||
if (token !== r.asset)
|
||||
throw ([true, "Transaction token mismatched"]);
|
||||
else
|
||||
blockchain.refundTransact.init(r.floID, token, amount, r.id);
|
||||
}).catch(error => {
|
||||
console.error(error);
|
||||
if (error[0])
|
||||
DB.query("UPDATE RefundTransact SET r_status=? WHERE id=?", [pCode.STATUS_REJECTED, r.id])
|
||||
.then(_ => null).catch(error => console.error(error));
|
||||
});
|
||||
})
|
||||
}).catch(error => console.error(error))
|
||||
}
|
||||
|
||||
function retryRefund() {
|
||||
DB.query("SELECT id, floID, amount FROM RefundTransact WHERE r_status=?", [pCode.STATUS_PROCESSING]).then(results => {
|
||||
results.forEach(r => blockchain.refundTransact.retry(r.floID, r.amount, r.id))
|
||||
DB.query("SELECT id, floID, asset, amount FROM RefundTransact WHERE r_status=?", [pCode.STATUS_PROCESSING]).then(results => {
|
||||
results.forEach(r => blockchain.refundTransact.retry(r.floID, r.asset, r.amount, r.id))
|
||||
}).catch(error => console.error(error))
|
||||
}
|
||||
|
||||
function confirmRefund() {
|
||||
DB.query("SELECT * FROM RefundTransact WHERE r_status=?", [pCode.STATUS_CONFIRMATION]).then(results => {
|
||||
results.forEach(r => {
|
||||
results.forEach(r => { //TODO
|
||||
if (r.ASSET_TYPE_COIN) {
|
||||
if (r.asset == "FLO")
|
||||
floBlockchainAPI.getTx(r.out_txid).then(tx => {
|
||||
if (!tx.blockheight || !tx.confirmations) //Still not confirmed
|
||||
return;
|
||||
DB.query("UPDATE RefundTransact SET r_status=? WHERE id=?", [pCode.STATUS_SUCCESS, r.id])
|
||||
.then(result => console.info(`Refunded ${r.amount} ${r.asset} to ${r.floID}`))
|
||||
.catch(error => console.error(error))
|
||||
}).catch(error => console.error(error));
|
||||
else if (r.asset == "BTC")
|
||||
btcOperator.getTx(r.out_txid).then(tx => {
|
||||
if (!tx.blockhash || !tx.confirmations) //Still not confirmed
|
||||
return;
|
||||
DB.query("UPDATE RefundTransact SET r_status=? WHERE id=?", [pCode.STATUS_SUCCESS, r.id])
|
||||
.then(result => console.info(`Refunded ${r.amount} ${r.asset} to ${r.floID}`))
|
||||
.catch(error => console.error(error))
|
||||
}).catch(error => console.error(error));
|
||||
} else if (r.ASSET_TYPE_TOKEN)
|
||||
floTokenAPI.getTx(r.out_txid).then(tx => {
|
||||
if (!tx.transactionDetails.blockheight || !tx.transactionDetails.confirmations) //Still not confirmed
|
||||
return;
|
||||
DB.query("UPDATE RefundTransact SET r_status=? WHERE id=?", [pCode.STATUS_SUCCESS, r.id])
|
||||
.then(result => console.info(`Refunded ${r.amount} to ${r.floID}`))
|
||||
.then(result => console.info(`Refunded ${r.amount} ${r.asset} to ${r.floID}`))
|
||||
.catch(error => console.error(error));
|
||||
}).catch(error => console.error(error));
|
||||
})
|
||||
@ -380,16 +430,16 @@ function confirmRefund() {
|
||||
}
|
||||
|
||||
function retryBondClosing() {
|
||||
DB.query("SELECT id, floID, amount FROM CloseBondTransact WHERE r_status=?", [pCode.STATUS_PENDING]).then(results => {
|
||||
results.forEach(r => blockchain.bondTransact.retry(r.floID, r.amount, r.id))
|
||||
DB.query("SELECT id, floID, amount, btc_net, usd_net FROM CloseBondTransact WHERE r_status=?", [pCode.STATUS_PENDING]).then(results => {
|
||||
results.forEach(r => blockchain.bondTransact.retry(r.floID, r.amount, r.btc_net, r.usd_net, r.id))
|
||||
}).catch(error => console.error(error))
|
||||
}
|
||||
|
||||
function confirmBondClosing() {
|
||||
DB.query("SELECT * FROM CloseBondTransact WHERE r_status=?", [pCode.STATUS_CONFIRMATION]).then(results => {
|
||||
results.forEach(r => {
|
||||
floTokenAPI.getTx(r.txid).then(tx => {
|
||||
if (!tx.transactionDetails.blockheight || !tx.transactionDetails.confirmations) //Still not confirmed
|
||||
btcOperator.getTx(r.txid).then(tx => {
|
||||
if (!tx.blockhash || !tx.confirmations) //Still not confirmed
|
||||
return;
|
||||
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 => {
|
||||
@ -403,16 +453,16 @@ function confirmBondClosing() {
|
||||
}
|
||||
|
||||
function retryFundClosing() {
|
||||
DB.query("SELECT id, floID, amount FROM CloseFundTransact WHERE r_status=?", [pCode.STATUS_PENDING]).then(results => {
|
||||
results.forEach(r => blockchain.fundTransact.retry(r.floID, r.amount, r.id))
|
||||
DB.query("SELECT id, floID, amount, btc_net, usd_net FROM CloseFundTransact WHERE r_status=?", [pCode.STATUS_PENDING]).then(results => {
|
||||
results.forEach(r => blockchain.fundTransact.retry(r.floID, r.amount, r.btc_net, r.usd_net, r.id))
|
||||
}).catch(error => console.error(error))
|
||||
}
|
||||
|
||||
function confirmFundClosing() {
|
||||
DB.query("SELECT * FROM CloseFundTransact WHERE r_status=?", [pCode.STATUS_CONFIRMATION]).then(results => {
|
||||
results.forEach(r => {
|
||||
floTokenAPI.getTx(r.txid).then(tx => {
|
||||
if (!tx.transactionDetails.blockheight || !tx.transactionDetails.confirmations) //Still not confirmed
|
||||
btcOperator.getTx(r.txid).then(tx => {
|
||||
if (!tx.blockhash || !tx.confirmations) //Still not confirmed
|
||||
return;
|
||||
let closeFundString = fund_util.stringify.end(r.fund_id, r.floID, r.end_date, r.btc_net, r.usd_net, r.amount, r.ref_sign, r.txid);
|
||||
floBlockchainAPI.writeData(global.myFloID, closeFundString, global.myPrivKey, fund_util.config.adminID).then(txid => {
|
||||
|
||||
@ -79,7 +79,7 @@ function sendTx(floID, asset, quantity, sinkID, sinkKey, 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);
|
||||
return btcOperator.sendTx(btc_sinkID, sinkKey, btc_receiver, quantity, null, { fee_from_receiver: true });
|
||||
default:
|
||||
return floTokenAPI.sendToken(sinkKey, quantity, floID, message, asset);
|
||||
}
|
||||
@ -95,6 +95,7 @@ const updateSyntax = {
|
||||
};
|
||||
|
||||
function sendAsset(floID, asset, quantity, type, id) {
|
||||
quantity = global.toStandardDecimal(quantity);
|
||||
getSinkID(quantity, asset).then(sinkID => {
|
||||
let callback = (sinkKey) => {
|
||||
//Send asset to user via API
|
||||
@ -118,7 +119,7 @@ function sendAsset(floID, asset, quantity, type, id) {
|
||||
}
|
||||
|
||||
function withdrawAsset_init(floID, asset, amount) {
|
||||
amount = parseFloat(amount.toFixed(8));
|
||||
amount = global.toStandardDecimal(amount);
|
||||
let asset_type = ["FLO", "BTC"].includes(asset) ? pCode.ASSET_TYPE_COIN : pCode.ASSET_TYPE_TOKEN;
|
||||
DB.query("INSERT INTO VaultTransactions (floID, mode, asset_type, asset, amount, r_status) VALUES (?)", [[floID, pCode.VAULT_MODE_WITHDRAW, asset_type, asset, amount, pCode.STATUS_PENDING]])
|
||||
.then(result => sendAsset(floID, asset, amount, TYPE_VAULT, result.insertId))
|
||||
@ -132,7 +133,7 @@ function withdrawAsset_retry(floID, asset, amount, id) {
|
||||
}
|
||||
|
||||
function convertToCoin_init(floID, coin, currency_amount, rate, id) {
|
||||
let coin_quantity = parseFloat((currency_amount / rate).toFixed(8));
|
||||
let coin_quantity = global.toStandardDecimal(currency_amount / rate);
|
||||
DB.query("UPDATE DirectConvert SET quantity=?, r_status=?, rate=?, locktime=DEFAULT WHERE id=?", [coin_quantity, pCode.STATUS_PROCESSING, rate, id])
|
||||
.then(result => sendAsset(floID, coin, coin_quantity, TYPE_CONVERT, id))
|
||||
.catch(error => console.error(error))
|
||||
@ -145,7 +146,7 @@ function convertToCoin_retry(floID, coin, coin_quantity, id) {
|
||||
}
|
||||
|
||||
function convertFromCoin_init(floID, coin_quantity, rate, id) {
|
||||
let currency_amount = parseFloat((coin_quantity * rate).toFixed(8));
|
||||
let currency_amount = global.toStandardDecimal(coin_quantity * rate);
|
||||
DB.query("UPDATE DirectConvert SET amount=?, r_status=?, rate=?, locktime=DEFAULT WHERE id=?", [currency_amount, pCode.STATUS_PROCESSING, rate, id])
|
||||
.then(result => sendAsset(floID, floGlobals.currency, currency_amount, TYPE_CONVERT, id))
|
||||
.catch(error => console.error(error))
|
||||
@ -163,29 +164,28 @@ function convertFundWithdraw_retry(asset, amount, id) {
|
||||
else sendAsset(floGlobals.adminID, asset, amount, TYPE_CONVERT_POOL, id);
|
||||
}
|
||||
|
||||
function bondTransact_retry(floID, amount, id) {
|
||||
function bondTransact_retry(floID, amount, btc_rate, usd_rate, 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);
|
||||
else sendAsset(floID, "BTC", amount / (btc_rate * usd_rate), TYPE_BOND, id);
|
||||
}
|
||||
|
||||
function fundTransact_retry(floID, amount, id) {
|
||||
function fundTransact_retry(floID, amount, btc_rate, usd_rate, id) {
|
||||
if (id in callbackCollection[TYPE_FUND])
|
||||
console.debug("A callback is already pending for this Fund investment closing");
|
||||
else sendAsset(floID, floGlobals.currency, amount, TYPE_FUND, id);
|
||||
else sendAsset(floID, "BTC", amount / (btc_rate * usd_rate), TYPE_FUND, id);
|
||||
}
|
||||
|
||||
function refundTransact_init(floID, amount, id) {
|
||||
amount = parseFloat(amount.toFixed(8));
|
||||
function refundTransact_init(floID, asset, amount, id) {
|
||||
amount = global.toStandardDecimal(amount);
|
||||
DB.query("UPDATE RefundTransact SET amount=?, r_status=?, locktime=DEFAULT WHERE id=?", [amount, pCode.STATUS_PROCESSING, id])
|
||||
.then(result => sendAsset(floID, floGlobals.currency, amount, TYPE_REFUND, id))
|
||||
.then(result => sendAsset(floID, asset, amount, TYPE_REFUND, id))
|
||||
.catch(error => console.error(error))
|
||||
}
|
||||
|
||||
function refundTransact_retry(floID, amount, id) {
|
||||
function refundTransact_retry(floID, asset, amount, id) {
|
||||
if (id in callbackCollection[TYPE_REFUND])
|
||||
console.debug("A callback is already pending for this Refund");
|
||||
else sendAsset(floID, floGlobals.currency, amount, TYPE_REFUND, id);
|
||||
else sendAsset(floID, asset, amount, TYPE_REFUND, id);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
@ -34,7 +34,7 @@ function startCouplingForAsset(asset, updatePrice = false) {
|
||||
return;
|
||||
}
|
||||
price.getRates(asset, updatePrice).then(cur_rate => {
|
||||
cur_rate = cur_rate.toFixed(8);
|
||||
cur_rate = global.toStandardDecimal(cur_rate);
|
||||
couplingInstance[asset] = true; //set instance as running
|
||||
recursiveCoupling(asset, cur_rate, updatePrice);
|
||||
}).catch(error => console.error(error));
|
||||
|
||||
@ -71,7 +71,7 @@ getBalance.floID_token = (floID, token) => new Promise((resolve, reject) => {
|
||||
DB.query("SELECT quantity AS balance FROM UserBalance WHERE floID=? AND token=?", [floID, token]).then(result => resolve({
|
||||
floID,
|
||||
token,
|
||||
balance: result.length ? result[0].balance.toFixed(8) : 0
|
||||
balance: result.length ? global.toStandardDecimal(result[0].balance) : 0
|
||||
})).catch(error => reject(error))
|
||||
});
|
||||
|
||||
@ -82,7 +82,7 @@ getBalance.floID = (floID) => new Promise((resolve, reject) => {
|
||||
balance: {}
|
||||
};
|
||||
for (let row of result)
|
||||
response.balance[row.token] = row.balance.toFixed(8);
|
||||
response.balance[row.token] = global.toStandardDecimal(row.balance);
|
||||
resolve(response);
|
||||
}).catch(error => reject(error))
|
||||
});
|
||||
@ -94,7 +94,7 @@ getBalance.token = (token) => new Promise((resolve, reject) => {
|
||||
balance: {}
|
||||
};
|
||||
for (let row of result)
|
||||
response.balance[row.floID] = row.balance.toFixed(8);
|
||||
response.balance[row.floID] = global.toStandardDecimal(row.balance);
|
||||
resolve(response);
|
||||
}).catch(error => reject(error))
|
||||
});
|
||||
|
||||
@ -22,11 +22,11 @@ const updateLastTime = asset => lastTime[asset] = Date.now();
|
||||
|
||||
//store FLO price in DB every 1 hr
|
||||
function storeHistory(asset, rate) {
|
||||
DB.query("INSERT INTO PriceHistory (asset, rate) VALUE (?)", [[asset, rate.toFixed(8)]])
|
||||
DB.query("INSERT INTO PriceHistory (asset, rate) VALUE (?)", [[asset, global.toStandardDecimal(rate)]])
|
||||
.then(_ => null).catch(error => console.error(error))
|
||||
}
|
||||
|
||||
storeHistory.start = function() {
|
||||
storeHistory.start = function () {
|
||||
storeHistory.stop();
|
||||
storeHistory.instance = setInterval(() => {
|
||||
for (let asset in currentRate)
|
||||
@ -34,7 +34,7 @@ storeHistory.start = function() {
|
||||
}, REC_HISTORY_INTERVAL);
|
||||
}
|
||||
|
||||
storeHistory.stop = function() {
|
||||
storeHistory.stop = function () {
|
||||
if (storeHistory.instance !== undefined) {
|
||||
clearInterval(storeHistory.instance);
|
||||
delete storeHistory.instance;
|
||||
|
||||
@ -253,7 +253,7 @@ function refreshBlockchainData(nodeList = []) {
|
||||
|
||||
function closeFund(fund_id, floID, ref) {
|
||||
return new Promise((resolve, reject) => {
|
||||
DB.query("SELECT r_status, close_id FROM CloseFundTransact WHERE fund_id=?", [fund_id]).then(result => {
|
||||
DB.query("SELECT r_status, close_id FROM CloseFundTransact WHERE fund_id=? AND floID=?", [fund_id, floID]).then(result => {
|
||||
if (result.length)
|
||||
return reject(INVALID(eCode.DUPLICATE_ENTRY, result[0].r_status == pCode.STATUS_SUCCESS ? `Fund investment already closed (${result[0].close_id})` : `Fund closing already in process`));
|
||||
DB.query("SELECT * FROM BobsFund WHERE fund_id=?", [fund_id]).then(result => {
|
||||
|
||||
@ -96,7 +96,7 @@ function convertToCoin(floID, txid, coin, amount) {
|
||||
}).catch(error => {
|
||||
if (error instanceof INVALID && error.ecode === eCode.INSUFFICIENT_FUND)
|
||||
DB.query("INSERT INTO DirectConvert(floID, in_txid, mode, coin, amount, r_status) VALUES (?)", [[floID, txid, pCode.CONVERT_MODE_GET, coin, amount, pCode.STATUS_REJECTED]]).then(result => {
|
||||
DB.query("INSERT INTO RefundTransact(floID, in_txid, amount, r_status) VALUES (?)", [[floID, txid, amount, pCode.STATUS_PENDING]])
|
||||
DB.query("INSERT INTO RefundTransact(floID, in_txid, asset_type, asset, r_status) VALUES (?)", [[floID, txid, pCode.ASSET_TYPE_TOKEN, floGlobals.currency, pCode.STATUS_PENDING]])
|
||||
.then(_ => null).catch(error => console.error(error));
|
||||
}).catch(error => console.error(error))
|
||||
reject(error);
|
||||
|
||||
@ -13,6 +13,8 @@ try {
|
||||
global[p] = param[p];
|
||||
}
|
||||
|
||||
global.toStandardDecimal = num => (parseInt(num * 1e8) * 1e-8)
|
||||
|
||||
if (!process.argv.includes("--debug"))
|
||||
global.console.debug = () => null;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user