Fixed various bugs

This commit is contained in:
sairajzero 2023-08-01 20:31:59 +05:30
parent 04f466b25e
commit d1ef13b26f

View File

@ -110,11 +110,11 @@
} }
function calcAllowedLoan(collateralQuantity, loan_collateral_ratio) { function calcAllowedLoan(collateralQuantity, loan_collateral_ratio) {
return collateralQuantity * loan_collateral_ratio; return toFixedDecimal(collateralQuantity * loan_collateral_ratio);
} }
function calcRequiredCollateral(loanEquivalent, loan_collateral_ratio) { function calcRequiredCollateral(loanEquivalent, loan_collateral_ratio) {
return loanEquivalent / loan_collateral_ratio; return toFixedDecimal(loanEquivalent / loan_collateral_ratio);
} }
function calcDueAmount(loan_amount, policy_id, open_time, close_time = Date.now()) { function calcDueAmount(loan_amount, policy_id, open_time, close_time = Date.now()) {
@ -327,8 +327,7 @@
if (!PERCENT_REGEX.test(loan_collateral_ratio)) if (!PERCENT_REGEX.test(loan_collateral_ratio))
return reject("Invalid loan_collateral_ratio"); return reject("Invalid loan_collateral_ratio");
let policy_text = stringifyPolicyData(duration, interest, pre_liquidation_threshold, loan_collateral_ratio); let policy_text = stringifyPolicyData(duration, interest, pre_liquidation_threshold, loan_collateral_ratio);
console.debug(policy_text); console.log("POLICY TEXT", policy_text);
debugger;
floBlockchainAPI.writeData(BANKER_ID, policy_text, banker_privKey, BANKER_ID) floBlockchainAPI.writeData(BANKER_ID, policy_text, banker_privKey, BANKER_ID)
.then(result => resolve(result)) .then(result => resolve(result))
.catch(error => reject(error)) .catch(error => reject(error))
@ -577,7 +576,7 @@
//sign the value-data //sign the value-data
let timestamp = Date.now(); let timestamp = Date.now();
let doc_array = [timestamp, borrower_floID, coborrower_floID, lender_floID, loan_amount, policy_id]; let doc_array = [timestamp, borrower_floID, coborrower_floID, lender_floID, loan_amount, policy_id];
let sign_part = floCrypto.signData(doc_array.join("|")); let sign_part = floCrypto.signData(doc_array.join("|"), privKey);
let pubKey = floCrypto.getPubKeyHex(privKey); let pubKey = floCrypto.getPubKeyHex(privKey);
let borrower_sign = [pubKey, sign_part, timestamp].join(".") let borrower_sign = [pubKey, sign_part, timestamp].join(".")
return borrower_sign; return borrower_sign;
@ -626,7 +625,7 @@
//sign the value-data //sign the value-data
let timestamp = Date.now(); let timestamp = Date.now();
let doc_array = [timestamp, borrower_sign, collateral_rate, collateral_value, collateral_lock_id]; let doc_array = [timestamp, borrower_sign, collateral_rate, collateral_value, collateral_lock_id];
let sign_part = floCrypto.signData(doc_array.join("|")); let sign_part = floCrypto.signData(doc_array.join("|"), privKey);
let pubKey = floCrypto.getPubKeyHex(privKey); let pubKey = floCrypto.getPubKeyHex(privKey);
let coborrower_sign = [pubKey, sign_part, timestamp].join(".") let coborrower_sign = [pubKey, sign_part, timestamp].join(".")
return coborrower_sign; return coborrower_sign;
@ -664,7 +663,7 @@
//sign the value-data //sign the value-data
let timestamp = Date.now(); let timestamp = Date.now();
let doc_array = [timestamp, coborrower_sign, loan_transfer_id]; let doc_array = [timestamp, coborrower_sign, loan_transfer_id];
let sign_part = floCrypto.signData(doc_array.join("|")); let sign_part = floCrypto.signData(doc_array.join("|"), privKey);
let pubKey = floCrypto.getPubKeyHex(privKey); let pubKey = floCrypto.getPubKeyHex(privKey);
let lender_sign = [pubKey, sign_part, timestamp].join(".") let lender_sign = [pubKey, sign_part, timestamp].join(".")
return lender_sign; return lender_sign;
@ -700,7 +699,7 @@
//sign the value-data //sign the value-data
let timestamp = Date.now(); let timestamp = Date.now();
let doc_array = [timestamp, CLOSING_IDENTIFIER, loan_id, lender_sign]; let doc_array = [timestamp, CLOSING_IDENTIFIER, loan_id, lender_sign];
let sign_part = floCrypto.signData(doc_array.join("|")); let sign_part = floCrypto.signData(doc_array.join("|"), privKey);
let pubKey = floCrypto.getPubKeyHex(privKey); let pubKey = floCrypto.getPubKeyHex(privKey);
let closing_sign = [pubKey, sign_part, timestamp].join(".") let closing_sign = [pubKey, sign_part, timestamp].join(".")
return closing_sign; return closing_sign;
@ -731,7 +730,7 @@
const validateRequest = btcMortgage.validateRequest = {}; const validateRequest = btcMortgage.validateRequest = {};
const RequestValidationError = (req_type, message) => { req_type, message }; const RequestValidationError = (req_type, message) => ({ req_type, message });
/*Inbox / Board */ /*Inbox / Board */
@ -780,8 +779,7 @@
loan_amount, policy_id loan_amount, policy_id
}, TYPE_LOAN_COLLATERAL_REQUEST, { receiverID: coborrower }) }, TYPE_LOAN_COLLATERAL_REQUEST, { receiverID: coborrower })
.then(result => { .then(result => {
let vc = Object.keys(result)[0]; compactIDB.addData("outbox", result, result.vectorClock);
compactIDB.addData("outbox", result[vc], vc);
resolve(result); resolve(result);
}).catch(error => reject(error)) }).catch(error => reject(error))
}) })
@ -789,16 +787,16 @@
function validate_loanCollateral_request(loan_collateral_req_id, borrower, coborrower) { function validate_loanCollateral_request(loan_collateral_req_id, borrower, coborrower) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
floCloudAPI.requestApplicationData(TYPE_LOAN_COLLATERAL_REQUEST, { atVectorClock: loan_collateral_req_id }).then(loan_collateral_req => { floCloudAPI.requestApplicationData(TYPE_LOAN_COLLATERAL_REQUEST, { atVectorClock: loan_collateral_req_id, receiverID: coborrower }).then(loan_collateral_req => {
if (!loan_collateral_req.length) loan_collateral_req = loan_collateral_req[loan_collateral_req_id];
if (!loan_collateral_req)
return reject(RequestValidationError(TYPE_LOAN_REQUEST, "request not found")); return reject(RequestValidationError(TYPE_LOAN_REQUEST, "request not found"));
loan_collateral_req = loan_collateral_req[0];
if (!floCrypto.isSameAddr(loan_collateral_req.senderID, borrower)) if (!floCrypto.isSameAddr(loan_collateral_req.senderID, borrower))
return reject(RequestValidationError(TYPE_LOAN_COLLATERAL_REQUEST, "sender is not borrower")); return reject(RequestValidationError(TYPE_LOAN_COLLATERAL_REQUEST, "sender is not borrower"));
if (!floCrypto.isSameAddr(loan_collateral_req.receiverID, coborrower)) if (!floCrypto.isSameAddr(loan_collateral_req.receiverID, coborrower))
return reject(RequestValidationError(TYPE_LOAN_COLLATERAL_REQUEST, "receiver is not coborrower")); return reject(RequestValidationError(TYPE_LOAN_COLLATERAL_REQUEST, "receiver is not coborrower"));
let { loan_amount, policy_id } = loan_collateral_req.message; let { loan_amount, policy_id } = loan_collateral_req.message;
if (typeof loan_amount !== 'number' && loan_amount <= 0 || VALUE_REGEX.test(loan_amount)) if (typeof loan_amount !== 'number' || loan_amount <= 0 || !VALUE_REGEX.test(loan_amount))
return reject(RequestValidationError(TYPE_LOAN_COLLATERAL_REQUEST, "Invalid loan amount")); return reject(RequestValidationError(TYPE_LOAN_COLLATERAL_REQUEST, "Invalid loan amount"));
if (!(policy_id in POLICIES)) if (!(policy_id in POLICIES))
return reject(RequestValidationError(TYPE_LOAN_COLLATERAL_REQUEST, "Invalid policy")); return reject(RequestValidationError(TYPE_LOAN_COLLATERAL_REQUEST, "Invalid policy"));
@ -816,9 +814,9 @@
//validate request //validate request
validate_loanCollateral_request(loan_collateral_req_id, borrower, coborrower).then(({ loan_amount, policy_id }) => { validate_loanCollateral_request(loan_collateral_req_id, borrower, coborrower).then(({ loan_amount, policy_id }) => {
//calculate required collateral //calculate required collateral
getRate["BTC"].then(rate => { getRate["BTC"]().then(rate => {
let policy = POLICIES[policy_id]; let policy = POLICIES[policy_id];
let collateral_value = calcRequiredCollateral(loan_amount * rate, policy.loan_collateral_ratio) let collateral_value = calcRequiredCollateral(loan_amount / rate, policy.loan_collateral_ratio)
//check if collateral is available //check if collateral is available
let coborrower_floID = floCrypto.toFloID(coborrower); let coborrower_floID = floCrypto.toFloID(coborrower);
let coborrower_btcID = btcOperator.convert.legacy2bech(coborrower_floID); let coborrower_btcID = btcOperator.convert.legacy2bech(coborrower_floID);
@ -836,8 +834,7 @@
} }
}, TYPE_LOAN_REQUEST) }, TYPE_LOAN_REQUEST)
.then(result => { .then(result => {
let vc = Object.keys(result)[0]; compactIDB.addData("outbox", result, result.vectorClock);
compactIDB.addData("outbox", result[vc], vc);
resolve(result); resolve(result);
}).catch(error => reject(error)) }).catch(error => reject(error))
}).catch(error => reject(error)) }).catch(error => reject(error))
@ -849,9 +846,9 @@
function validate_loan_request(loan_req_id, borrower, coborrower) { function validate_loan_request(loan_req_id, borrower, coborrower) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
floCloudAPI.requestApplicationData(TYPE_LOAN_REQUEST, { atVectorClock: loan_req_id }).then(loan_req => { floCloudAPI.requestApplicationData(TYPE_LOAN_REQUEST, { atVectorClock: loan_req_id }).then(loan_req => {
if (!loan_req.length) loan_req = loan_req[loan_req_id];
if (!loan_req)
return reject(RequestValidationError(TYPE_LOAN_REQUEST, "request not found")); return reject(RequestValidationError(TYPE_LOAN_REQUEST, "request not found"));
loan_req = loan_req[0];
if (!floCrypto.isSameAddr(coborrower, loan_req.senderID)) if (!floCrypto.isSameAddr(coborrower, loan_req.senderID))
return reject(RequestValidationError(TYPE_LOAN_REQUEST, "request not posted by coborrower")) return reject(RequestValidationError(TYPE_LOAN_REQUEST, "request not posted by coborrower"))
let { loan_collateral_req_id, loan_amount, policy_id, collateral } = loan_req.message; let { loan_collateral_req_id, loan_amount, policy_id, collateral } = loan_req.message;
@ -862,21 +859,16 @@
return reject(RequestValidationError(TYPE_LOAN_REQUEST, "loan amount mismatch")); return reject(RequestValidationError(TYPE_LOAN_REQUEST, "loan amount mismatch"));
if (policy_id !== result.policy_id) if (policy_id !== result.policy_id)
return reject(RequestValidationError(TYPE_LOAN_REQUEST, "policy id mismatch")); return reject(RequestValidationError(TYPE_LOAN_REQUEST, "policy id mismatch"));
getRate["BTC"].then(rate => { getRate["BTC"]().then(rate => {
if (rate * ALLOWED_DEVIATION > collateral.rate) if (rate * ALLOWED_DEVIATION > collateral.rate)
return reject(RequestValidationError(TYPE_LOAN_REQUEST, "BTC rate has reduced beyond allowed threshold")) return reject(RequestValidationError(TYPE_LOAN_REQUEST, "BTC rate has reduced beyond allowed threshold"))
let policy = POLICIES[policy_id]; let policy = POLICIES[policy_id];
let required_collateral = calcRequiredCollateral(loan_amount * collateral.rate, policy.loan_collateral_ratio) let required_collateral = calcRequiredCollateral(loan_amount / collateral.rate, policy.loan_collateral_ratio)
if (required_collateral > collateral.quantity) if (required_collateral > collateral.quantity)
return reject(RequestValidationError(TYPE_LOAN_REQUEST, "Insufficient collateral value")); return reject(RequestValidationError(TYPE_LOAN_REQUEST, "Insufficient collateral value"));
//check if collateral is available result.collateral = collateral;
btcOperator.getBalance(collateral.btc_id).then(coborrower_balance => { result.coborrower_pubKey = loan_req.pubKey;
if (coborrower_balance < collateral.quantity) resolve(result)
return reject(RequestValidationError(TYPE_LOAN_REQUEST, "Insufficient collateral available"));
result.collateral = collateral;
result.coborrower_pubKey = loan_req.pubKey;
resolve(result)
}).catch(error => reject(error))
}).catch(error => reject(error)) }).catch(error => reject(error))
}).catch(error => reject(error)) }).catch(error => reject(error))
}).catch(error => reject(error)) }).catch(error => reject(error))
@ -888,21 +880,25 @@
btcMortgage.respondLoan = function (loan_req_id, borrower, coborrower) { btcMortgage.respondLoan = function (loan_req_id, borrower, coborrower) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const lender = floDapps.user.id; const lender = floDapps.user.id;
validate_loan_request(loan_req_id, borrower, coborrower).then(({ loan_amount, borrower }) => { validate_loan_request(loan_req_id, borrower, coborrower).then(({ loan_amount, borrower, collateral }) => {
//check if loan amount (token) is available to lend //check if collateral is available
let lender_floID = floCrypto.toFloID(lender); btcOperator.getBalance(collateral.btc_id).then(coborrower_balance => {
floTokenAPI.getBalance(lender_floID).then(lender_tokenBalance => { if (coborrower_balance < collateral.quantity)
if (lender_tokenBalance < loan_amount) return reject(RequestValidationError(TYPE_LOAN_REQUEST, "Insufficient collateral available"));
return reject("Insufficient tokens to lend"); //check if loan amount (token) is available to lend
floCloudAPI.sendApplicationData({ let lender_floID = floCrypto.toFloID(lender);
lender, borrower, coborrower, floTokenAPI.getBalance(lender_floID, CURRENCY).then(lender_tokenBalance => {
loan_req_id if (lender_tokenBalance < loan_amount)
}, TYPE_LENDER_RESPONSE, { receiverID: borrower }) return reject("Insufficient tokens to lend");
.then(result => { floCloudAPI.sendApplicationData({
let vc = Object.keys(result)[0]; lender, borrower, coborrower,
compactIDB.addData("outbox", result[vc], vc); loan_req_id
resolve(result); }, TYPE_LENDER_RESPONSE, { receiverID: borrower })
}).catch(error => reject(error)) .then(result => {
compactIDB.addData("outbox", result, result.vectorClock);
resolve(result);
}).catch(error => reject(error))
}).catch(error => reject(error))
}).catch(error => reject(error)) }).catch(error => reject(error))
}).catch(error => reject(error)) }).catch(error => reject(error))
}) })
@ -911,17 +907,17 @@
function validate_lender_response(lender_res_id, borrower, coborrower, lender) { function validate_lender_response(lender_res_id, borrower, coborrower, lender) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
floCloudAPI.requestApplicationData(TYPE_LENDER_RESPONSE, { atVectorClock: lender_res_id, receiverID: borrower }).then(lender_res => { floCloudAPI.requestApplicationData(TYPE_LENDER_RESPONSE, { atVectorClock: lender_res_id, receiverID: borrower }).then(lender_res => {
if (!lender_res.length) lender_res = lender_res[lender_res_id];
return reject(RequestValidationError(TYPE_LENDER_RESPONSE, "response not found")); if (!lender_res)
lender_res = lender_res[0]; return reject(RequestValidationError(TYPE_LENDER_RESPONSE, "request not found"));
if (!floCrypto.isSameAddr(lender, lender_res.senderID)) if (!floCrypto.isSameAddr(lender, lender_res.senderID))
return reject(RequestValidationError(TYPE_LENDER_RESPONSE, "response not sent by lender")) return reject(RequestValidationError(TYPE_LENDER_RESPONSE, "request not sent by lender"))
let { loan_req_id } = lender_res.message; let { loan_req_id } = lender_res.message;
validate_loan_request(loan_req_id, borrower, coborrower).then(result => { validate_loan_request(loan_req_id, borrower, coborrower).then(result => {
let { loan_amount } = result; let { loan_amount } = result;
//check if loan amount (token) is available to lend //check if loan amount (token) is available to lend
let lender_floID = floCrypto.toFloID(lender); let lender_floID = floCrypto.toFloID(lender);
floTokenAPI.getBalance(lender_floID).then(lender_tokenBalance => { floTokenAPI.getBalance(lender_floID, CURRENCY).then(lender_tokenBalance => {
if (lender_tokenBalance < loan_amount) if (lender_tokenBalance < loan_amount)
return reject(RequestValidationError(TYPE_LENDER_RESPONSE, "lender doesnot have sufficient funds to lend")); return reject(RequestValidationError(TYPE_LENDER_RESPONSE, "lender doesnot have sufficient funds to lend"));
result.lender = lender; result.lender = lender;
@ -939,33 +935,32 @@
const borrower = floDapps.user.id; const borrower = floDapps.user.id;
validate_lender_response(lender_res_id, borrower, coborrower, lender).then(({ loan_amount, policy_id }) => { validate_lender_response(lender_res_id, borrower, coborrower, lender).then(({ loan_amount, policy_id }) => {
//send request to coborrower for locking the collateral asset //send request to coborrower for locking the collateral asset
let borrower_sign = sign_borrower(privKey, loan_amount, policy_id, lender); let borrower_sign = sign_borrower(privKey, loan_amount, policy_id, coborrower, lender);
floCloudAPI.sendApplicationData({ floCloudAPI.sendApplicationData({
lender, borrower, coborrower, lender, borrower, coborrower,
lender_res_id, borrower_sign lender_res_id, borrower_sign
}, TYPE_COLLATERAL_LOCK_REQUEST, { receiverID: collateral.provider }) }, TYPE_COLLATERAL_LOCK_REQUEST, { receiverID: coborrower })
.then(result => { .then(result => {
let vc = Object.keys(result)[0]; compactIDB.addData("outbox", result, result.vectorClock);
compactIDB.addData("outbox", result[vc], vc);
resolve(result); resolve(result);
}).catch(error => reject(error)) }).catch(error => reject(error))
}).catch(error => reject(error)) }).catch(error => reject(error))
}).catch(error => reject(error)) })
} }
function validate_collateralLock_request(collateral_lock_req_id, borrower, coborrower, lender) { function validate_collateralLock_request(collateral_lock_req_id, borrower, coborrower, lender) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
floCloudAPI.requestApplicationData(TYPE_COLLATERAL_LOCK_REQUEST, { atVectorClock: collateral_lock_req_id, receiverID: coborrower }).then(collateral_lock_req => { floCloudAPI.requestApplicationData(TYPE_COLLATERAL_LOCK_REQUEST, { atVectorClock: collateral_lock_req_id, receiverID: coborrower }).then(collateral_lock_req => {
if (!collateral_lock_req.length) collateral_lock_req = collateral_lock_req[collateral_lock_req_id];
if (!collateral_lock_req)
return reject(RequestValidationError(TYPE_COLLATERAL_LOCK_REQUEST, "request not found")); return reject(RequestValidationError(TYPE_COLLATERAL_LOCK_REQUEST, "request not found"));
collateral_lock_req = collateral_lock_req[0];
if (!floCrypto.isSameAddr(borrower, collateral_lock_req.senderID)) if (!floCrypto.isSameAddr(borrower, collateral_lock_req.senderID))
return reject(RequestValidationError(TYPE_LENDER_RESPONSE, "request not sent by borrower")); return reject(RequestValidationError(TYPE_LENDER_RESPONSE, "request not sent by borrower"));
let { lender_res_id, borrower_sign } = collateral_lock_req.message; let { lender_res_id, borrower_sign } = collateral_lock_req.message;
validate_lender_response(lender_res_id, borrower, coborrower, lender).then(result => { validate_lender_response(lender_res_id, borrower, coborrower, lender).then(result => {
let { loan_amount, policy_id } = result; let { loan_amount, policy_id } = result;
//verify borrower_sign //verify borrower_sign
let borrower_sign_time = verify_borrowerSign(borrower_sign, borrower, loan_amount, policy_id, lender) let borrower_sign_time = verify_borrowerSign(borrower_sign, borrower, loan_amount, policy_id, coborrower, lender)
if (!borrower_sign_time) //MAYDO: expire signatures? if (!borrower_sign_time) //MAYDO: expire signatures?
return reject("Invalid borrower signature"); return reject("Invalid borrower signature");
result.borrower_sign = borrower_sign; result.borrower_sign = borrower_sign;
@ -990,8 +985,7 @@
coborrower_sign, collateral_lock_req_id coborrower_sign, collateral_lock_req_id
}, TYPE_COLLATERAL_LOCK_ACK, { receiverID: lender }) }, TYPE_COLLATERAL_LOCK_ACK, { receiverID: lender })
.then(result => { .then(result => {
let vc = Object.keys(result)[0]; compactIDB.addData("outbox", result, result.vectorClock);
compactIDB.addData("outbox", result[vc], vc);
resolve(result); resolve(result);
}).catch(error => reject(error)) }).catch(error => reject(error))
}).catch(error => reject(error)) }).catch(error => reject(error))
@ -1011,21 +1005,21 @@
function validate_collateralLock_ack(collateral_lock_ack_id, borrower, coborrower, lender) { function validate_collateralLock_ack(collateral_lock_ack_id, borrower, coborrower, lender) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
floCloudAPI.requestApplicationData(TYPE_COLLATERAL_LOCK_ACK, { atVectorClock: collateral_lock_ack_id, receiverID: lender }).then(collateral_lock_ack => { floCloudAPI.requestApplicationData(TYPE_COLLATERAL_LOCK_ACK, { atVectorClock: collateral_lock_ack_id, receiverID: lender }).then(collateral_lock_ack => {
if (!collateral_lock_ack.length) collateral_lock_ack = collateral_lock_ack[collateral_lock_ack_id];
if (!collateral_lock_ack)
return reject(RequestValidationError(TYPE_COLLATERAL_LOCK_REQUEST, "request not found")); return reject(RequestValidationError(TYPE_COLLATERAL_LOCK_REQUEST, "request not found"));
collateral_lock_ack = collateral_lock_ack[0];
if (!floCrypto.isSameAddr(coborrower, collateral_lock_ack.senderID)) if (!floCrypto.isSameAddr(coborrower, collateral_lock_ack.senderID))
return reject(RequestValidationError(TYPE_LENDER_RESPONSE, "request not sent by coborrower")); return reject(RequestValidationError(TYPE_LENDER_RESPONSE, "request not sent by coborrower"));
let { collateral_lock_req_id, coborrower_sign, collateral_lock_id } = collateral_lock_ack.message; let { collateral_lock_req_id, coborrower_sign, collateral_lock_id } = collateral_lock_ack.message;
validate_collateralLock_request(collateral_lock_req_id, borrower, coborrower, lender).then(result => { validate_collateralLock_request(collateral_lock_req_id, borrower, coborrower, lender).then(result => {
let { borrower_sign, collateral } = result; let { borrower_sign, collateral, lender_pubKey, coborrower_pubKey } = result;
let coborrower_sign_time = verify_coborrowerSign(coborrower_sign, coborrower, borrower_sign, collateral.rate, collateral.quantity, collateral_lock_id) let coborrower_sign_time = verify_coborrowerSign(coborrower_sign, coborrower, borrower_sign, collateral.rate, collateral.quantity, collateral_lock_id)
if (!coborrower_sign_time) //MAYDO: expire signatures? if (!coborrower_sign_time) //MAYDO: expire signatures?
return reject(RequestValidationError(TYPE_COLLATERAL_LOCK_ACK, "Invalid coborrower signature")); return reject(RequestValidationError(TYPE_COLLATERAL_LOCK_ACK, "Invalid coborrower signature"));
btcOperator.getTx(collateral_lock_id).then(collateral_tx => { btcOperator.getTx(collateral_lock_id).then(collateral_tx => {
if (!collateral_tx.confirmations) if (!collateral_tx.confirmations)
return reject(RequestValidationError(TYPE_COLLATERAL_LOCK_ACK, "Collateral lock transaction not confirmed yet")); return reject(RequestValidationError(TYPE_COLLATERAL_LOCK_ACK, "Collateral lock transaction not confirmed yet"));
let locker_id = findLocker(finalize_request.pubKey, lender_response.pubKey).address; let locker_id = findLocker(coborrower_pubKey, lender_pubKey).address;
let locked_amt = collateral_tx.outputs.filter(o => o.address == locker_id).reduce((a, o) => a += o.value, 0); let locked_amt = collateral_tx.outputs.filter(o => o.address == locker_id).reduce((a, o) => a += o.value, 0);
if (locked_amt < collateral.quantity) if (locked_amt < collateral.quantity)
return reject(RequestValidationError(TYPE_COLLATERAL_LOCK_ACK, "Insufficient Collateral locked")); return reject(RequestValidationError(TYPE_COLLATERAL_LOCK_ACK, "Insufficient Collateral locked"));
@ -1052,7 +1046,8 @@
if (collateral_lock_id in owned_collateral_locks) if (collateral_lock_id in owned_collateral_locks)
return reject("Collateral is being used for a different loan in-process"); return reject("Collateral is being used for a different loan in-process");
//transfer tokens for loan amount //transfer tokens for loan amount
floTokenAPI.sendToken(privKey, loan_amount, borrower, "as loan", CURRENCY).then(token_txid => { let borrower_floID = floCrypto.toFloID(borrower);
floTokenAPI.sendToken(privKey, loan_amount, borrower_floID, "as loan", CURRENCY).then(token_txid => {
//construct the blockchain data //construct the blockchain data
let lender_sign = sign_lender(privKey, coborrower_sign, token_txid); let lender_sign = sign_lender(privKey, coborrower_sign, token_txid);
let blockchainData = stringifyLoanOpenData( let blockchainData = stringifyLoanOpenData(
@ -1090,8 +1085,7 @@
//send message to coborrower as reminder to unlock collateral //send message to coborrower as reminder to unlock collateral
floCloudAPI.sendApplicationData({ loan_id, closing_txid }, TYPE_LOAN_CLOSED_ACK, { receiverID: loan_details.coborrower }) floCloudAPI.sendApplicationData({ loan_id, closing_txid }, TYPE_LOAN_CLOSED_ACK, { receiverID: loan_details.coborrower })
.then(result => { .then(result => {
let vc = Object.keys(result)[0]; compactIDB.addData("outbox", result, result.vectorClock);
compactIDB.addData("outbox", result[vc], vc);
resolve(result); resolve(result);
}).catch(error => reject(error)) }).catch(error => reject(error))
}).catch(error => reject(error)) }).catch(error => reject(error))
@ -1113,8 +1107,7 @@
loan_id, closing_txid, unlock_tx_hex loan_id, closing_txid, unlock_tx_hex
}, TYPE_UNLOCK_COLLATERAL_REQUEST, { receiverID: loan_details.lender }) }, TYPE_UNLOCK_COLLATERAL_REQUEST, { receiverID: loan_details.lender })
.then(result => { .then(result => {
let vc = Object.keys(result)[0]; compactIDB.addData("outbox", result, result.vectorClock);
compactIDB.addData("outbox", result[vc], vc);
resolve(result); resolve(result);
}).catch(error => reject(error)) }).catch(error => reject(error))
}).catch(error => reject(error)) }).catch(error => reject(error))
@ -1179,8 +1172,7 @@
loan_id, closing_txid, unlock_collateral_id: txid loan_id, closing_txid, unlock_collateral_id: txid
}, TYPE_UNLOCK_COLLATERAL_ACK, { receiverID: loan_details.coborrower }) }, TYPE_UNLOCK_COLLATERAL_ACK, { receiverID: loan_details.coborrower })
.then(result => { .then(result => {
let vc = Object.keys(result)[0]; compactIDB.addData("outbox", result, result.vectorClock);
compactIDB.addData("outbox", result[vc], vc);
resolve(result); resolve(result);
}).catch(error => reject(error)) }).catch(error => reject(error))
}).catch(error => reject(error)) }).catch(error => reject(error))
@ -1230,8 +1222,7 @@
collateral_lock_ack_id, unlock_tx_hex collateral_lock_ack_id, unlock_tx_hex
}, TYPE_REFUND_COLLATERAL_REQUEST) }, TYPE_REFUND_COLLATERAL_REQUEST)
.then(result => { .then(result => {
let vc = Object.keys(result)[0]; compactIDB.addData("outbox", result, result.vectorClock);
compactIDB.addData("outbox", result[vc], vc);
resolve(result); resolve(result);
}).catch(error => reject(error)) }).catch(error => reject(error))
}).catch(error => reject(error)) }).catch(error => reject(error))
@ -1253,8 +1244,7 @@
collateral_refund_req_id, refund_collateral_id: txid collateral_refund_req_id, refund_collateral_id: txid
}, TYPE_REFUND_COLLATERAL_ACK, { receiverID: coborrower }) }, TYPE_REFUND_COLLATERAL_ACK, { receiverID: coborrower })
.then(result => { .then(result => {
let vc = Object.keys(result)[0]; compactIDB.addData("outbox", result, result.vectorClock);
compactIDB.addData("outbox", result[vc], vc);
resolve(result); resolve(result);
}).catch(error => reject(error)) }).catch(error => reject(error))
}).catch(error => reject(error)) }).catch(error => reject(error))
@ -1266,9 +1256,9 @@
function validate_collateralRefund_request(collateral_refund_req_id, borrower, coborrower, lender) { function validate_collateralRefund_request(collateral_refund_req_id, borrower, coborrower, lender) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
floCloudAPI.requestApplicationData(TYPE_REFUND_COLLATERAL_REQUEST, { atVectorClock: collateral_refund_req_id }).then(collateral_refund_req => { floCloudAPI.requestApplicationData(TYPE_REFUND_COLLATERAL_REQUEST, { atVectorClock: collateral_refund_req_id }).then(collateral_refund_req => {
if (!collateral_refund_req.length) collateral_refund_req = collateral_refund_req[collateral_refund_req_id];
if (!collateral_refund_req)
return reject(RequestValidationError(TYPE_REFUND_COLLATERAL_REQUEST, "request not found")); return reject(RequestValidationError(TYPE_REFUND_COLLATERAL_REQUEST, "request not found"));
collateral_refund_req = collateral_refund_req[0];
if (!floCrypto.isSameAddr(coborrower, collateral_refund_req.senderID)) if (!floCrypto.isSameAddr(coborrower, collateral_refund_req.senderID))
return reject(RequestValidationError(TYPE_REFUND_COLLATERAL_REQUEST, "request not sent by coborrower")); return reject(RequestValidationError(TYPE_REFUND_COLLATERAL_REQUEST, "request not sent by coborrower"));
let { collateral_lock_ack_id, unlock_tx_hex } = collateral_refund_req.message; let { collateral_lock_ack_id, unlock_tx_hex } = collateral_refund_req.message;
@ -1298,8 +1288,7 @@
loan_id, liquidate_tx_hex: txHex loan_id, liquidate_tx_hex: txHex
}, TYPE_LIQUATE_COLLATERAL_REQUEST) }, TYPE_LIQUATE_COLLATERAL_REQUEST)
.then(result => { .then(result => {
let vc = Object.keys(result)[0]; compactIDB.addData("outbox", result, result.vectorClock);
compactIDB.addData("outbox", result[vc], vc);
resolve(result); resolve(result);
}).catch(error => reject(error)) }).catch(error => reject(error))
}).catch(error => reject(error)) }).catch(error => reject(error))
@ -1316,15 +1305,14 @@
//sign //sign
let coborrower_pubKey = extractPubKeyFromSign(loan_details.coborrower_sign); let coborrower_pubKey = extractPubKeyFromSign(loan_details.coborrower_sign);
let lender_pubKey = extractPubKeyFromSign(loan_details.lender_sign); let lender_pubKey = extractPubKeyFromSign(loan_details.lender_sign);
getRate["BTC"].then(rate => { getRate["BTC"]().then(rate => {
due_amount = toFixedDecimal(due_amount / rate); //USD to BTC due_amount = toFixedDecimal(due_amount / rate); //USD to BTC
signLiquidateCollateralTxHex(coborrower_pubKey, lender_pubKey, loan_details.collateral_lock_id, liquidate_tx_hex, due_amount, privKey).then(txHex => { signLiquidateCollateralTxHex(coborrower_pubKey, lender_pubKey, loan_details.collateral_lock_id, liquidate_tx_hex, due_amount, privKey).then(txHex => {
floCloudAPI.sendApplicationData({ floCloudAPI.sendApplicationData({
loan_id, liquidate_tx_hex: txHex loan_id, liquidate_tx_hex: txHex
}, TYPE_LIQUATE_COLLATERAL_ACK) }, TYPE_LIQUATE_COLLATERAL_ACK)
.then(result => { .then(result => {
let vc = Object.keys(result)[0]; compactIDB.addData("outbox", result, result.vectorClock);
compactIDB.addData("outbox", result[vc], vc);
resolve(result); resolve(result);
}).catch(error => reject(error)) }).catch(error => reject(error))
}).catch(error => reject(error)) }).catch(error => reject(error))
@ -1336,9 +1324,9 @@
function validate_liquateCollateral_request(collateral_liquate_req_id) { function validate_liquateCollateral_request(collateral_liquate_req_id) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
floCloudAPI.requestApplicationData(TYPE_LIQUATE_COLLATERAL_REQUEST, { atVectorClock: collateral_liquate_req_id }).then(collateral_liquate_req => { floCloudAPI.requestApplicationData(TYPE_LIQUATE_COLLATERAL_REQUEST, { atVectorClock: collateral_liquate_req_id }).then(collateral_liquate_req => {
if (!collateral_liquate_req.length) collateral_liquate_req = collateral_liquate_req[collateral_liquate_req_id];
if (!collateral_liquate_req)
return reject(RequestValidationError(TYPE_LIQUATE_COLLATERAL_REQUEST, "request not found")); return reject(RequestValidationError(TYPE_LIQUATE_COLLATERAL_REQUEST, "request not found"));
collateral_liquate_req = collateral_liquate_req[0];
let { loan_id, liquidate_tx_hex } = collateral_liquate_req.message; let { loan_id, liquidate_tx_hex } = collateral_liquate_req.message;
getLoanDetails(loan_id).then(loan_details => { getLoanDetails(loan_id).then(loan_details => {
if (!floCrypto.isSameAddr(loan_details.lender, collateral_liquate_req.senderID)) if (!floCrypto.isSameAddr(loan_details.lender, collateral_liquate_req.senderID))
@ -1376,8 +1364,7 @@
loan_id, liquidate_tx_hex: txHex loan_id, liquidate_tx_hex: txHex
}, TYPE_PRELIQUATE_COLLATERAL_REQUEST) }, TYPE_PRELIQUATE_COLLATERAL_REQUEST)
.then(result => { .then(result => {
let vc = Object.keys(result)[0]; compactIDB.addData("outbox", result, result.vectorClock);
compactIDB.addData("outbox", result[vc], vc);
resolve(result); resolve(result);
}).catch(error => reject(error)) }).catch(error => reject(error))
}).catch(error => reject(error)) }).catch(error => reject(error))
@ -1395,15 +1382,14 @@
//sign //sign
let coborrower_pubKey = extractPubKeyFromSign(loan_details.coborrower_sign); let coborrower_pubKey = extractPubKeyFromSign(loan_details.coborrower_sign);
let lender_pubKey = extractPubKeyFromSign(loan_details.lender_sign); let lender_pubKey = extractPubKeyFromSign(loan_details.lender_sign);
getRate["BTC"].then(rate => { getRate["BTC"]().then(rate => {
due_amount = toFixedDecimal(due_amount / rate); //USD to BTC due_amount = toFixedDecimal(due_amount / rate); //USD to BTC
signLiquidateCollateralTxHex(coborrower_pubKey, lender_pubKey, loan_details.collateral_lock_id, liquidate_tx_hex, due_amount, privKey).then(txHex => { signLiquidateCollateralTxHex(coborrower_pubKey, lender_pubKey, loan_details.collateral_lock_id, liquidate_tx_hex, due_amount, privKey).then(txHex => {
floCloudAPI.sendApplicationData({ floCloudAPI.sendApplicationData({
loan_id, liquidate_tx_hex: txHex loan_id, liquidate_tx_hex: txHex
}, TYPE_PRELIQUATE_COLLATERAL_ACK) }, TYPE_PRELIQUATE_COLLATERAL_ACK)
.then(result => { .then(result => {
let vc = Object.keys(result)[0]; compactIDB.addData("outbox", result, result.vectorClock);
compactIDB.addData("outbox", result[vc], vc);
resolve(result); resolve(result);
}).catch(error => reject(error)) }).catch(error => reject(error))
}).catch(error => reject(error)) }).catch(error => reject(error))
@ -1415,9 +1401,9 @@
function validate_preliquateCollateral_request(collateral_preliquate_req_id) { function validate_preliquateCollateral_request(collateral_preliquate_req_id) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
floCloudAPI.requestApplicationData(TYPE_PRELIQUATE_COLLATERAL_REQUEST, { atVectorClock: collateral_preliquate_req_id }).then(collateral_preliquate_req => { floCloudAPI.requestApplicationData(TYPE_PRELIQUATE_COLLATERAL_REQUEST, { atVectorClock: collateral_preliquate_req_id }).then(collateral_preliquate_req => {
if (!collateral_preliquate_req.length) collateral_preliquate_req = collateral_preliquate_req[collateral_preliquate_req_id];
if (!collateral_preliquate_req)
return reject(RequestValidationError(TYPE_PRELIQUATE_COLLATERAL_REQUEST, "request not found")); return reject(RequestValidationError(TYPE_PRELIQUATE_COLLATERAL_REQUEST, "request not found"));
collateral_preliquate_req = collateral_preliquate_req[0];
let { loan_id, liquidate_tx_hex } = collateral_preliquate_req.message; let { loan_id, liquidate_tx_hex } = collateral_preliquate_req.message;
getLoanDetails(loan_id).then(loan_details => { getLoanDetails(loan_id).then(loan_details => {
if (!floCrypto.isSameAddr(loan_details.lender, collateral_preliquate_req.senderID)) if (!floCrypto.isSameAddr(loan_details.lender, collateral_preliquate_req.senderID))