Default cashier and other changes
- Encrypt UPI ID of users before sending to cashier - Cashier: reconnect status ws at a regular interval to avoid timeout - return the default cashier ID if no cashier is online (configured via blockchain)
This commit is contained in:
parent
7760570c95
commit
6c17afb913
@ -4,12 +4,13 @@ const TYPE_MONEY_REQUEST = "MoneyRequests",
|
|||||||
TYPE_CASHIER_UPI = "CashierUPI";
|
TYPE_CASHIER_UPI = "CashierUPI";
|
||||||
|
|
||||||
const cashierUPI = {};
|
const cashierUPI = {};
|
||||||
|
const cashierPubKeys = {};
|
||||||
|
|
||||||
//For regular users
|
//For regular users
|
||||||
const User = {};
|
const User = {};
|
||||||
const cashierStatus = {};
|
const cashierStatus = {};
|
||||||
|
|
||||||
User.init = function () {
|
User.init = function() {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let promises;
|
let promises;
|
||||||
//Request cashier for token-cash exchange
|
//Request cashier for token-cash exchange
|
||||||
@ -55,22 +56,24 @@ User.init = function () {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
User.getCashierUPI = function () {
|
User.getCashierUPI = function() {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
Promise.allSettled(floGlobals.subAdmins.map(cashierID => floCloudAPI.requestApplicationData(TYPE_CASHIER_UPI, {
|
Promise.allSettled(floGlobals.subAdmins.map(cashierID => floCloudAPI.requestApplicationData(TYPE_CASHIER_UPI, {
|
||||||
senderID: cashierID,
|
senderID: cashierID,
|
||||||
mostRecent: true
|
mostRecent: true
|
||||||
}))).then(result => {
|
}))).then(result => {
|
||||||
for (let r of result)
|
for (let r of result)
|
||||||
if (r.status === "fulfilled" && r.value.length)
|
if (r.status === "fulfilled" && r.value.length) {
|
||||||
cashierUPI[r.value[0].senderID] = floCloudAPI.util.decodeMessage(r.value[0].message).upi;
|
cashierUPI[r.value[0].senderID] = floCloudAPI.util.decodeMessage(r.value[0].message).upi;
|
||||||
|
cashierPubKeys[r.value[0].senderID] = r.value[0].pubKey; //get pubKey of cashier from messages for encryption
|
||||||
|
}
|
||||||
resolve(cashierUPI);
|
resolve(cashierUPI);
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.defineProperty(User, 'cashierRequests', {
|
Object.defineProperty(User, 'cashierRequests', {
|
||||||
get: function () {
|
get: function() {
|
||||||
let fk = floCloudAPI.util.filterKey(TYPE_CASHIER_REQUEST, {
|
let fk = floCloudAPI.util.filterKey(TYPE_CASHIER_REQUEST, {
|
||||||
senderID: myFloID,
|
senderID: myFloID,
|
||||||
group: "Cashiers",
|
group: "Cashiers",
|
||||||
@ -80,7 +83,7 @@ Object.defineProperty(User, 'cashierRequests', {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Object.defineProperty(User, 'moneyRequests', {
|
Object.defineProperty(User, 'moneyRequests', {
|
||||||
get: function () {
|
get: function() {
|
||||||
let fk = floCloudAPI.util.filterKey(TYPE_MONEY_REQUEST, {
|
let fk = floCloudAPI.util.filterKey(TYPE_MONEY_REQUEST, {
|
||||||
receiverID: myFloID,
|
receiverID: myFloID,
|
||||||
});
|
});
|
||||||
@ -88,84 +91,110 @@ Object.defineProperty(User, 'moneyRequests', {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
User.findCashier = function () {
|
User.findCashier = function() {
|
||||||
let online = [];
|
let online = [];
|
||||||
for (let c in cashierStatus)
|
for (let c in cashierStatus)
|
||||||
if (cashierStatus[c] && cashierUPI[c])
|
if (cashierStatus[c] && cashierUPI[c])
|
||||||
online.push(c);
|
online.push(c);
|
||||||
if (!online.length)
|
if (!online.length) {
|
||||||
return null;
|
if (floGlobals.settings.defaultCashier && floGlobals.settings.defaultCashier in cashierUPI)
|
||||||
else {
|
return floGlobals.settings.defaultCashier;
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
const random = floCrypto.randInt(0, online.length - 1)
|
const random = floCrypto.randInt(0, online.length - 1)
|
||||||
return online[random];
|
return online[random];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
User.cashToToken = function (cashier, amount, upiTxID) {
|
User.cashToToken = function(cashier, amount, upiTxID) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (!floGlobals.subAdmins.includes(cashier))
|
if (!floGlobals.subAdmins.includes(cashier))
|
||||||
return reject("Invalid cashier");
|
return reject("Invalid cashier");
|
||||||
floCloudAPI.sendGeneralData({
|
floCloudAPI.sendGeneralData({
|
||||||
mode: "cash-to-token",
|
mode: "cash-to-token",
|
||||||
amount: amount,
|
amount: amount,
|
||||||
upi_txid: upiTxID
|
upi_txid: upiTxID
|
||||||
}, TYPE_CASHIER_REQUEST, {
|
}, TYPE_CASHIER_REQUEST, {
|
||||||
receiverID: cashier
|
receiverID: cashier
|
||||||
}).then(result => resolve(result))
|
}).then(result => resolve(result))
|
||||||
.catch(error => reject(error))
|
.catch(error => reject(error))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
User.tokenToCash = function (cashier, amount, blkTxID, upiID) {
|
User.tokenToCash = function(cashier, amount, blkTxID, upiID) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (!floGlobals.subAdmins.includes(cashier))
|
if (!floGlobals.subAdmins.includes(cashier))
|
||||||
return reject("Invalid cashier");
|
return reject("Invalid cashier");
|
||||||
floCloudAPI.sendGeneralData({
|
floCloudAPI.sendGeneralData({
|
||||||
mode: "token-to-cash",
|
mode: "token-to-cash",
|
||||||
amount: amount,
|
amount: amount,
|
||||||
token_txid: blkTxID,
|
token_txid: blkTxID,
|
||||||
upi_id: upiID
|
upi_id: floCrypto.encryptData(upiID, cashierPubKeys[cashier])
|
||||||
}, TYPE_CASHIER_REQUEST, {
|
}, TYPE_CASHIER_REQUEST, {
|
||||||
receiverID: cashier
|
receiverID: cashier
|
||||||
}).then(result => resolve(result))
|
}).then(result => resolve(result))
|
||||||
.catch(error => reject(error))
|
.catch(error => reject(error))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
User.sendToken = function (receiverID, amount, remark = '') {
|
User.sendToken = function(receiverID, amount, remark = '') {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
tokenAPI.sendToken(myPrivKey, amount, receiverID, remark)
|
floTokenAPI.sendToken(myPrivKey, amount, receiverID, remark)
|
||||||
.then(result => resolve(result))
|
.then(result => resolve(result))
|
||||||
.catch(error => reject(error))
|
.catch(error => reject(error))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
User.requestToken = function (floID, amount, remark = '') {
|
User.requestToken = function(floID, amount, remark = '') {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
floCloudAPI.sendGeneralData({
|
floCloudAPI.sendGeneralData({
|
||||||
amount: amount,
|
amount: amount,
|
||||||
remark: remark
|
remark: remark
|
||||||
}, TYPE_MONEY_REQUEST, {
|
}, TYPE_MONEY_REQUEST, {
|
||||||
receiverID: floID
|
receiverID: floID
|
||||||
}).then(result => resolve(result))
|
}).then(result => resolve(result))
|
||||||
.catch(error => reject(error))
|
.catch(error => reject(error))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
User.decideRequest = function (request, note) {
|
User.decideRequest = function(request, note) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
floCloudAPI.noteApplicationData(request.vectorClock, note, {
|
floCloudAPI.noteApplicationData(request.vectorClock, note, {
|
||||||
receiverID: myFloID
|
receiverID: myFloID
|
||||||
}).then(result => resolve(result))
|
}).then(result => resolve(result))
|
||||||
.catch(error => reject(error))
|
.catch(error => reject(error))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const Cashier = {};
|
const Cashier = {};
|
||||||
|
|
||||||
Cashier.init = function () {
|
var status_conn_id = null;
|
||||||
|
|
||||||
|
function statusReconnect() {
|
||||||
|
if (status_conn_id) {
|
||||||
|
floCloudAPI.closeRequest(status_conn_id)
|
||||||
|
status_conn_id = null;
|
||||||
|
}
|
||||||
|
floCloudAPI.setStatus()
|
||||||
|
.then(result => status_conn_id = result)
|
||||||
|
.catch(error => console.error(error))
|
||||||
|
}
|
||||||
|
|
||||||
|
var status_interval_instance = null;
|
||||||
|
|
||||||
|
function startStatusInterval() {
|
||||||
|
if (status_interval_instance) {
|
||||||
|
clearInterval(status_interval_instance);
|
||||||
|
status_interval_instance = null;
|
||||||
|
}
|
||||||
|
statusReconnect();
|
||||||
|
status_interval_instance = setInterval(statusReconnect, 15 * 60 * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
Cashier.init = function() {
|
||||||
delegate(getRef('cashier_pending_request_list'), 'click', '.process-cashier-request', e => {
|
delegate(getRef('cashier_pending_request_list'), 'click', '.process-cashier-request', e => {
|
||||||
const requestID = e.delegateTarget.closest('.cashier-request').dataset.vc;
|
const requestID = e.delegateTarget.closest('.cashier-request').id;
|
||||||
cashierUI.completeRequest(requestID)
|
cashierUI.completeRequest(requestID)
|
||||||
})
|
})
|
||||||
getRef('cashier_requests_selector').addEventListener('change', e => {
|
getRef('cashier_requests_selector').addEventListener('change', e => {
|
||||||
@ -179,31 +208,32 @@ Cashier.init = function () {
|
|||||||
callback: cashierUI.renderRequests //UI_fn
|
callback: cashierUI.renderRequests //UI_fn
|
||||||
}));
|
}));
|
||||||
//Set online status of cashier(self)
|
//Set online status of cashier(self)
|
||||||
promises.push(floCloudAPI.setStatus());
|
//promises.push(floCloudAPI.setStatus());
|
||||||
/*
|
/*
|
||||||
promises.push(floCloudAPI.requestObjectData("UPI", { //Is this needed?
|
promises.push(floCloudAPI.requestObjectData("UPI", { //Is this needed?
|
||||||
callback: UI_RENDER_FN
|
callback: UI_RENDER_FN
|
||||||
}));
|
}));
|
||||||
*/
|
*/
|
||||||
promises.push(User.getCashierUPI());
|
promises.push(User.getCashierUPI());
|
||||||
Promise.all(promises)
|
Promise.all(promises).then(result => {
|
||||||
.then(result => resolve(result))
|
startStatusInterval(); //Set online status of cashier(self) [connection refreshes on interval]
|
||||||
.catch(error => reject(error))
|
resolve(result)
|
||||||
|
}).catch(error => reject(error));
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
Cashier.updateUPI = function (upi_id) {
|
Cashier.updateUPI = function(upi_id) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
floCloudAPI.sendApplicationData({
|
floCloudAPI.sendApplicationData({
|
||||||
upi: upi_id
|
upi: upi_id
|
||||||
}, TYPE_CASHIER_UPI)
|
}, TYPE_CASHIER_UPI)
|
||||||
.then(result => resolve(result))
|
.then(result => resolve(result))
|
||||||
.catch(error => reject(error))
|
.catch(error => reject(error))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.defineProperty(Cashier, 'Requests', {
|
Object.defineProperty(Cashier, 'Requests', {
|
||||||
get: function () {
|
get: function() {
|
||||||
let fk = floCloudAPI.util.filterKey(TYPE_CASHIER_REQUEST, {
|
let fk = floCloudAPI.util.filterKey(TYPE_CASHIER_REQUEST, {
|
||||||
receiverID: myFloID
|
receiverID: myFloID
|
||||||
});
|
});
|
||||||
@ -212,29 +242,29 @@ Object.defineProperty(Cashier, 'Requests', {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Cashier.finishRequest = function (request, txid) {
|
Cashier.finishRequest = function(request, txid) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
floCloudAPI.tagApplicationData(request.vectorClock, 'COMPLETED', {
|
floCloudAPI.tagApplicationData(request.vectorClock, 'COMPLETED', {
|
||||||
receiverID: myFloID
|
receiverID: myFloID
|
||||||
}).then(result => {
|
}).then(result => {
|
||||||
floCloudAPI.noteApplicationData(request.vectorClock, txid, {
|
floCloudAPI.noteApplicationData(request.vectorClock, txid, {
|
||||||
receiverID: myFloID
|
receiverID: myFloID
|
||||||
}).then(result => resolve(result))
|
}).then(result => resolve(result))
|
||||||
.catch(error => reject(error))
|
.catch(error => reject(error))
|
||||||
}).catch(error => reject(error))
|
}).catch(error => reject(error))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
Cashier.rejectRequest = function (request, reason) {
|
Cashier.rejectRequest = function(request, reason) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
floCloudAPI.noteApplicationData(request.vectorClock, "REJECTED:" + reason, {
|
floCloudAPI.noteApplicationData(request.vectorClock, "REJECTED:" + reason, {
|
||||||
receiverID: myFloID
|
receiverID: myFloID
|
||||||
}).then(result => resolve(result))
|
}).then(result => resolve(result))
|
||||||
.catch(error => reject(error))
|
.catch(error => reject(error))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
Cashier.checkIfUpiTxIsValid = function (upiTxID) {
|
Cashier.checkIfUpiTxIsValid = function(upiTxID) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let requests = Cashier.Requests;
|
let requests = Cashier.Requests;
|
||||||
for (let r in requests)
|
for (let r in requests)
|
||||||
@ -245,15 +275,15 @@ Cashier.checkIfUpiTxIsValid = function (upiTxID) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
Cashier.checkIfTokenTxIsValid = function (tokenTxID, sender, amount) {
|
Cashier.checkIfTokenTxIsValid = function(tokenTxID, sender, amount) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let requests = Cashier.Requests;
|
let requests = Cashier.Requests;
|
||||||
for (let r in requests)
|
for (let r in requests)
|
||||||
if (requests[r].message.mode === "token-to-cash" && requests[r].note)
|
if (requests[r].message.mode === "token-to-cash" && requests[r].note)
|
||||||
if (requests[r].message.token_txid === tokenTxID)
|
if (requests[r].message.token_txid === tokenTxID)
|
||||||
return reject([true, "Token transaction is already used for another request"]);
|
return reject([true, "Token transaction is already used for another request"]);
|
||||||
tokenAPI.getTx(tokenTxID).then(tx => {
|
floTokenAPI.getTx(tokenTxID).then(tx => {
|
||||||
let parsedTxData = tokenAPI.util.parseTxData(tx);
|
let parsedTxData = floTokenAPI.util.parseTxData(tx);
|
||||||
console.debug(parsedTxData);
|
console.debug(parsedTxData);
|
||||||
if (parsedTxData.type !== "transfer" || parsedTxData.transferType !== "token")
|
if (parsedTxData.type !== "transfer" || parsedTxData.transferType !== "token")
|
||||||
reject([true, "Invalid token transfer type"]);
|
reject([true, "Invalid token transfer type"]);
|
||||||
|
|||||||
@ -409,6 +409,14 @@ function declineTopUp() {
|
|||||||
|
|
||||||
function completeTokenToCashRequest(request) {
|
function completeTokenToCashRequest(request) {
|
||||||
const { vectorClock, senderID, message: { token_txid, amount, upi_id } } = request
|
const { vectorClock, senderID, message: { token_txid, amount, upi_id } } = request
|
||||||
|
if (upi_id instanceof Object && "secret" in upi_id){
|
||||||
|
try {
|
||||||
|
upi_id = floCrypto.decryptData(upi_id, myPrivKey);
|
||||||
|
} catch(error) {
|
||||||
|
console.error("UPI ID is not encrypted with a proper key", error);
|
||||||
|
return notify("Invalid UPI ID", 'error');
|
||||||
|
}
|
||||||
|
}
|
||||||
Cashier.checkIfTokenTxIsValid(token_txid, senderID, amount).then(result => {
|
Cashier.checkIfTokenTxIsValid(token_txid, senderID, amount).then(result => {
|
||||||
getPromptInput('Process', `Token transfer is verified!\n Send ${formatAmount(amount)}\n to ${upi_id}\n Enter UPI transaction ID`, {
|
getPromptInput('Process', `Token transfer is verified!\n Send ${formatAmount(amount)}\n to ${upi_id}\n Enter UPI transaction ID`, {
|
||||||
placeholder: 'UPI transaction ID',
|
placeholder: 'UPI transaction ID',
|
||||||
@ -550,7 +558,7 @@ const render = {
|
|||||||
return clone;
|
return clone;
|
||||||
},
|
},
|
||||||
transactionMessage(details) {
|
transactionMessage(details) {
|
||||||
const { tokenAmount, time, sender, receiver, flodata } = tokenAPI.util.parseTxData(details)
|
const { tokenAmount, time, sender, receiver, flodata } = floTokenAPI.util.parseTxData(details)
|
||||||
let messageType = sender === receiver ? 'self' : sender === myFloID ? 'sent' : 'received';
|
let messageType = sender === receiver ? 'self' : sender === myFloID ? 'sent' : 'received';
|
||||||
const clone = getRef('transaction_message_template').content.cloneNode(true).firstElementChild;
|
const clone = getRef('transaction_message_template').content.cloneNode(true).firstElementChild;
|
||||||
clone.classList.add(messageType);
|
clone.classList.add(messageType);
|
||||||
@ -585,10 +593,10 @@ const render = {
|
|||||||
if (paymentsHistoryLoader)
|
if (paymentsHistoryLoader)
|
||||||
paymentsHistoryLoader.clear()
|
paymentsHistoryLoader.clear()
|
||||||
getRef('payments_history').innerHTML = '<sm-spinner></sm-spinner>';
|
getRef('payments_history').innerHTML = '<sm-spinner></sm-spinner>';
|
||||||
tokenAPI.getAllTxs(myFloID).then(({ transactions }) => {
|
floTokenAPI.getAllTxs(myFloID).then(({ transactions }) => {
|
||||||
for (const transactionId in transactions) {
|
for (const transactionId in transactions) {
|
||||||
paymentTransactions.push({
|
paymentTransactions.push({
|
||||||
...tokenAPI.util.parseTxData(transactions[transactionId]),
|
...floTokenAPI.util.parseTxData(transactions[transactionId]),
|
||||||
txid: transactionId
|
txid: transactionId
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -647,7 +655,7 @@ function buttonLoader(id, show) {
|
|||||||
function refreshBalance(button) {
|
function refreshBalance(button) {
|
||||||
if (button)
|
if (button)
|
||||||
buttonLoader(button, true)
|
buttonLoader(button, true)
|
||||||
tokenAPI.getBalance(myFloID).then((balance = 0) => {
|
floTokenAPI.getBalance(myFloID).then((balance = 0) => {
|
||||||
const [beforeDecimal, afterDecimal] = formatAmount(balance).split('₹')[1].split('.')
|
const [beforeDecimal, afterDecimal] = formatAmount(balance).split('₹')[1].split('.')
|
||||||
getRef('rupee_balance').innerHTML = `<span><b>${beforeDecimal}</b></span>.<span>${afterDecimal}</span>`
|
getRef('rupee_balance').innerHTML = `<span><b>${beforeDecimal}</b></span>.<span>${afterDecimal}</span>`
|
||||||
if (button)
|
if (button)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user