311 lines
11 KiB
JavaScript
311 lines
11 KiB
JavaScript
/*jshint esversion: 6 */
|
|
const TYPE_MONEY_REQUEST = "MoneyRequests",
|
|
TYPE_CASHIER_REQUEST = "CashierRequests",
|
|
TYPE_CASHIER_UPI = "CashierUPI";
|
|
|
|
const cashierUPI = {};
|
|
const cashierPubKeys = {};
|
|
|
|
//For regular users
|
|
const User = {};
|
|
const cashierStatus = {};
|
|
|
|
User.init = function () {
|
|
return new Promise((resolve, reject) => {
|
|
let promises;
|
|
//Request cashier for token-cash exchange
|
|
promises = floGlobals.subAdmins.map(cashierID => floCloudAPI.requestGeneralData(TYPE_CASHIER_REQUEST, {
|
|
senderID: myFloID,
|
|
receiverID: cashierID,
|
|
group: "Cashiers",
|
|
callback: userUI.renderCashierRequests //UI_fn
|
|
}));
|
|
//Request received from other Users for token
|
|
promises.push(floCloudAPI.requestGeneralData(TYPE_MONEY_REQUEST, {
|
|
receiverID: myFloID,
|
|
callback: userUI.renderMoneyRequests //UI_fn
|
|
}));
|
|
//Check online status of cashiers
|
|
promises.push(floCloudAPI.requestStatus(Array.from(floGlobals.subAdmins), {
|
|
callback: (d, e) => {
|
|
if (e) return console.error(e);
|
|
for (let i in d)
|
|
cashierStatus[i] = d[i];
|
|
//Add any UI_fn if any
|
|
if (User.findCashier()) {
|
|
getRef('topup_wallet_process').classList.remove('hide')
|
|
getRef('withdraw_wallet_process').classList.remove('hide')
|
|
document.querySelectorAll('.cashier-status').forEach(elem => elem.classList.add('hide'))
|
|
} else {
|
|
getRef('topup_wallet_process').classList.add('hide')
|
|
getRef('withdraw_wallet_process').classList.add('hide')
|
|
document.querySelectorAll('.cashier-status').forEach(elem => elem.classList.remove('hide'))
|
|
}
|
|
}
|
|
}))
|
|
/*
|
|
promises.push(floCloudAPI.requestObjectData("UPI", { //Is this needed?
|
|
callback: UI_RENDER_FN
|
|
}));
|
|
*/
|
|
promises.push(User.getCashierUPI());
|
|
promises.push(organizeSyncedData('savedUserData'));
|
|
Promise.all(promises)
|
|
.then(result => resolve(result))
|
|
.catch(error => reject(error))
|
|
})
|
|
}
|
|
|
|
User.getCashierUPI = function () {
|
|
return new Promise((resolve) => {
|
|
Promise.allSettled(floGlobals.subAdmins.map(cashierID => floCloudAPI.requestApplicationData(TYPE_CASHIER_UPI, {
|
|
senderID: cashierID,
|
|
mostRecent: true
|
|
}))).then(result => {
|
|
for (let r of result)
|
|
if (r.status === "fulfilled" && Object.keys(r.value).length) {
|
|
let vc = Object.keys(r.value).sort().pop()
|
|
cashierUPI[r.value[vc].senderID] = r.value[vc].message.upi;
|
|
cashierPubKeys[r.value[vc].senderID] = r.value[vc].pubKey; //get pubKey of cashier from messages for encryption
|
|
}
|
|
resolve(cashierUPI);
|
|
})
|
|
})
|
|
}
|
|
|
|
Object.defineProperty(User, 'cashierRequests', {
|
|
get: function () {
|
|
let fk = floCloudAPI.util.filterKey(TYPE_CASHIER_REQUEST, {
|
|
senderID: myFloID,
|
|
group: "Cashiers",
|
|
});
|
|
return floGlobals.generalData[fk];
|
|
}
|
|
});
|
|
|
|
Object.defineProperty(User, 'moneyRequests', {
|
|
get: function () {
|
|
let fk = floCloudAPI.util.filterKey(TYPE_MONEY_REQUEST, {
|
|
receiverID: myFloID,
|
|
});
|
|
return floGlobals.generalData[fk];
|
|
}
|
|
});
|
|
|
|
User.findCashier = function () {
|
|
let online = [];
|
|
for (let c in cashierStatus)
|
|
if (cashierStatus[c] && cashierUPI[c])
|
|
online.push(c);
|
|
if (!online.length) {
|
|
if (floGlobals.settings.default_cashier && floGlobals.settings.default_cashier in cashierUPI)
|
|
return floGlobals.settings.default_cashier;
|
|
else
|
|
return null;
|
|
} else {
|
|
const random = floCrypto.randInt(0, online.length - 1)
|
|
return online[random];
|
|
}
|
|
}
|
|
|
|
User.cashToToken = function (cashier, amount, txCode, upiID) {
|
|
return new Promise((resolve, reject) => {
|
|
if (!floGlobals.subAdmins.includes(cashier))
|
|
return reject("Invalid cashier");
|
|
floCloudAPI.sendGeneralData({
|
|
mode: "cash-to-token",
|
|
amount: amount,
|
|
// upi_txid: upiTxID,
|
|
upiID,
|
|
txCode
|
|
}, TYPE_CASHIER_REQUEST, {
|
|
receiverID: cashier
|
|
}).then(result => resolve(result))
|
|
.catch(error => reject(error))
|
|
})
|
|
}
|
|
|
|
User.tokenToCash = function (cashier, amount, blkTxID, upiID) {
|
|
return new Promise((resolve, reject) => {
|
|
if (!floGlobals.subAdmins.includes(cashier))
|
|
return reject("Invalid cashier");
|
|
floCloudAPI.sendGeneralData({
|
|
mode: "token-to-cash",
|
|
amount: amount,
|
|
token_txid: blkTxID,
|
|
upi_id: floCrypto.encryptData(upiID, cashierPubKeys[cashier])
|
|
}, TYPE_CASHIER_REQUEST, {
|
|
receiverID: cashier
|
|
}).then(result => resolve(result))
|
|
.catch(error => reject(error))
|
|
})
|
|
}
|
|
|
|
User.sendToken = function (receiverID, amount, remark = '', options = {}) {
|
|
return new Promise((resolve, reject) => {
|
|
floDapps.user.private.then(privateKey => {
|
|
floTokenAPI.sendToken(privateKey, amount, receiverID, remark, floTokenAPI.currency, options)
|
|
.then(result => resolve(result))
|
|
.catch(error => reject(error))
|
|
}).catch(error => {
|
|
console.log(error);
|
|
notify('Invalid password', 'error');
|
|
reject(error);
|
|
})
|
|
})
|
|
}
|
|
|
|
User.requestToken = function (floID, amount, remark = '') {
|
|
return new Promise((resolve, reject) => {
|
|
floCloudAPI.sendGeneralData({
|
|
amount: amount,
|
|
remark: remark
|
|
}, TYPE_MONEY_REQUEST, {
|
|
receiverID: floID
|
|
}).then(result => resolve(result))
|
|
.catch(error => reject(error))
|
|
})
|
|
}
|
|
|
|
User.decideRequest = function (request, note) {
|
|
return new Promise((resolve, reject) => {
|
|
floCloudAPI.noteApplicationData(request.vectorClock, note, {
|
|
receiverID: myFloID
|
|
}).then(result => resolve(result))
|
|
.catch(error => reject(error))
|
|
})
|
|
}
|
|
|
|
const Cashier = {};
|
|
|
|
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 => {
|
|
const requestID = e.delegateTarget.closest('.cashier-request').dataset.vc;
|
|
cashierUI.completeRequest(requestID)
|
|
})
|
|
getRef('cashier_requests_selector').addEventListener('change', e => {
|
|
showChildElement('cashier_requests_wrapper', e.target.value === 'pending' ? 0 : 1)
|
|
})
|
|
return new Promise((resolve, reject) => {
|
|
let promises = [];
|
|
//Requests from user to cashier(self) for token-cash exchange
|
|
promises.push(floCloudAPI.requestGeneralData(TYPE_CASHIER_REQUEST, {
|
|
receiverID: myFloID,
|
|
callback: cashierUI.renderRequests //UI_fn
|
|
}));
|
|
//Set online status of cashier(self)
|
|
//promises.push(floCloudAPI.setStatus());
|
|
/*
|
|
promises.push(floCloudAPI.requestObjectData("UPI", { //Is this needed?
|
|
callback: UI_RENDER_FN
|
|
}));
|
|
*/
|
|
promises.push(User.getCashierUPI());
|
|
Promise.all(promises).then(result => {
|
|
startStatusInterval(); //Set online status of cashier(self) [connection refreshes on interval]
|
|
resolve(result)
|
|
}).catch(error => reject(error));
|
|
})
|
|
}
|
|
|
|
Cashier.updateUPI = function (upi_id) {
|
|
return new Promise((resolve, reject) => {
|
|
floCloudAPI.sendApplicationData({
|
|
upi: upi_id
|
|
}, TYPE_CASHIER_UPI)
|
|
.then(result => resolve(result))
|
|
.catch(error => reject(error))
|
|
})
|
|
}
|
|
Object.defineProperty(Cashier, 'Requests', {
|
|
get: function () {
|
|
let fk = floCloudAPI.util.filterKey(TYPE_CASHIER_REQUEST, {
|
|
receiverID: myFloID
|
|
});
|
|
console.debug(fk, floGlobals.generalData[fk]);
|
|
return floGlobals.generalData[fk];
|
|
}
|
|
});
|
|
|
|
Cashier.finishRequest = function (request, txid) {
|
|
return new Promise((resolve, reject) => {
|
|
floCloudAPI.tagApplicationData(request.vectorClock, 'COMPLETED', {
|
|
receiverID: myFloID
|
|
}).then(result => {
|
|
floCloudAPI.noteApplicationData(request.vectorClock, txid, {
|
|
receiverID: myFloID
|
|
}).then(result => resolve(result))
|
|
.catch(error => reject(error))
|
|
}).catch(error => reject(error))
|
|
})
|
|
}
|
|
|
|
Cashier.rejectRequest = function (request, reason) {
|
|
return new Promise((resolve, reject) => {
|
|
floCloudAPI.noteApplicationData(request.vectorClock, "REJECTED:" + reason, {
|
|
receiverID: myFloID
|
|
}).then(result => resolve(result))
|
|
.catch(error => reject(error))
|
|
})
|
|
}
|
|
|
|
Cashier.checkIfUpiTxIsValid = function (upiTxID) {
|
|
return new Promise((resolve, reject) => {
|
|
let requests = Cashier.Requests;
|
|
for (let r in requests)
|
|
if (requests[r].message.mode === "cash-to-token" && requests[r].note)
|
|
if (requests[r].message.upi_txid === upiTxID)
|
|
return reject([true, "UPI transaction is already used for another request"]);
|
|
return resolve(true);
|
|
})
|
|
}
|
|
|
|
Cashier.checkIfTokenTxIsValid = function (tokenTxID, sender, amount) {
|
|
return new Promise((resolve, reject) => {
|
|
let requests = Cashier.Requests;
|
|
for (let r in requests)
|
|
if (requests[r].message.mode === "token-to-cash" && requests[r].note)
|
|
if (requests[r].message.token_txid === tokenTxID)
|
|
return reject([true, "Token transaction is already used for another request"]);
|
|
floTokenAPI.getTx(tokenTxID).then(tx => {
|
|
let parsedTxData = floTokenAPI.util.parseTxData(tx);
|
|
console.debug(parsedTxData);
|
|
|
|
if (tx.type !== "transfer" || tx.transferType !== "token")
|
|
reject([true, "Invalid token transfer type"]);
|
|
else if (tx.tokenAmount !== amount)
|
|
reject([true, "Incorrect token amount: " + tx.tokenAmount]);
|
|
else if (tx.tokenIdentification !== floGlobals.currency)
|
|
reject([true, "Incorrect token: " + tx.tokenIdentification]);
|
|
else if (parsedTxData.sender !== sender)
|
|
reject([true, "Incorrect senderID: " + parsedTxData.sender]);
|
|
else if (parsedTxData.receiver !== myFloID)
|
|
reject([true, "Incorrect receiverID: " + parsedTxData.receive])
|
|
else resolve(true);
|
|
|
|
|
|
}).catch(error => reject([null, error]))
|
|
})
|
|
} |