Adding app html and scripts

This commit is contained in:
sairajzero 2022-03-07 04:09:02 +05:30
parent 3bc37aa9ee
commit 7ce54f2f8f
3 changed files with 576 additions and 0 deletions

225
fn_pay.js Normal file
View File

@ -0,0 +1,225 @@
const TYPE_MONEY_REQUEST = "MoneyRequests",
TYPE_CASHIER_REQUEST = "CashierRequests";
const cashierUPI = {};
//https://ranchimallflo.duckdns.org/api/v1.0/getFloAddressTransactions?token=rupee&floAddress=FKAEdnPfjXLHSYwrXQu377ugN4tXU7VGdf
//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
}
}))
/*
promises.push(floCloudAPI.requestObjectData("UPI", { //Is this needed?
callback: UI_RENDER_FN
}));
*/
Promise.all(promises)
.then(result => resolve(result))
.catch(error => reject(error))
})
}
Object.defineProperty(Cashier, 'cashierRequests', {
get: function() {
let fk = floCloudAPI.util.filterKey(TYPE_CASHIER_REQUEST, {
senderID: myFloID,
receiverID: cashierID,
group: "Cashiers",
});
return floGlobals.generalData[fk];
}
});
Object.defineProperty(Cashier, '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])
online.push(c);
if (!online.length)
return null;
else
return online[floCrypto.randInt(0, online.length)];
}
User.cashToToken = function(cashier, amount, upiTxID) {
return new Promise((resolve, reject) => {
if (!floCloudAPI.subAdmins.includes(cashier))
return reject("Invalid cashier");
floCloudAPI.sendGeneralData({
mode: "cash-to-token",
amount: amount,
upi_txid: upiTxID
}, 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 (!floCloudAPI.subAdmins.includes(cashier))
return reject("Invalid cashier");
floCloudAPI.sendGeneralData({
mode: "token-to-cash",
amount: amount,
token_txid: blkTxID,
upi_id: upiID
}, TYPE_CASHIER_REQUEST, {
receiverID: cashier
}).then(result => resolve(result))
.catch(error => reject(error))
})
}
User.sendToken = function(receiverID, amount, remark = '') {
return new Promise((resolve, reject) => {
tokenAPI.sendToken(myPrivKey, amount, receiverID, remark)
.then(result => resolve(result))
.catch(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 = {};
Cashier.init = function() {
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
}));
*/
Promise.all(promises)
.then(result => resolve(result))
.catch(error => reject(error))
})
}
Object.defineProperty(Cashier, 'Requests', {
get: function() {
let fk = floCloudAPI.util.filterKey(TYPE_CASHIER_REQUEST, {
receiver: myFloID
});
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")
if (requests[r].note === 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")
if (requests[r].note === tokenTxID)
return reject([true, "Token transaction is already used for another request"]);
tokenAPI.getTx(tokenTxID).then(tx => {
let parsedTxData = tokenAPI.util.parseTxData(tx);
console.debug(parsedTxData);
if (parsedTxData.type !== "transfer" || parsedTxData.transferType !== "token")
reject([true, "Invalid token transfer type"]);
else if (parsedTxData.tokenAmount !== amount)
reject([true, "Incorrect token amount: " + parsedTxData.tokenAmount]);
else if (parsedTxData.tokenIdentification !== floGlobals.currency)
reject([true, "Incorrect token: " + parsedTxData.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]))
})
}

218
fn_ui.js Normal file
View File

@ -0,0 +1,218 @@
const userUI = {};
userUI.requestTokenFromCashier = function() {
let cashier = User.findCashier();
if (!cashier)
return alert("No cashier online");
let amount = parseFloat(document.forms['request-cashier'][amount]);
//get UPI txid from user
let upiTxID = prompt(`Send Rs. ${amount} to ${cashierUPI[cashier]} and enter UPI txid`);
if (!upiTxID)
return alert("Cancelled");
User.cashToToken(cashier, amount, upiTxID).then(result => {
console.log(result);
alert("Requested cashier. please wait!");
}).catch(error => console.error(error))
}
userUI.withdrawCashFromCashier = function() {
let cashier = User.findCashier();
if (!cashier)
return alert("No cashier online");
let amount = parseFloat(document.forms['request-cashier'][amount]);
//get confirmation from user
let upiID = prompt(`${amount} ${floGlobals.currency}# will be sent to ${cashier}. Enter UPI ID`);
if (!upiID)
return alert("Cancelled");
User.sendToken(cashier, amount, 'for token-to-cash').then(txid => {
console.log("txid", txid);
User.tokenToCash(cashier, amount, txid, upiID).then(result => {
console.log(result);
alert("Requested cashier. please wait!");
}).catch(error => console.error(error))
}).catch(error => console.error(error))
}
userUI.sendMoneyToUser = function() {
let form = document.forms['user-money'];
let floID = form['flo-id'],
amount = parseFloat(form['amount']),
remark = form['remark'];
let confirmation = prompt(`Do you want to SEND ${amount} to ${floID}?`);
if (!confirmation)
return alert("Cancelled");
User.sendToken(floID, amount, remark).then(txid => {
console.info(`Sent ${amount} to ${floID}`, txid);
alert(`Sent ${amount} to ${floID}. It may take a few mins to reflect in their wallet`);
}).catch(error => console.error(error));
}
userUI.requestMoneyFromUser = function() {
let form = document.forms['user-money'];
let floID = form['flo-id'],
amount = parseFloat(form['amount']),
remark = form['remark'];
let confirmation = prompt(`Do you want to REQUEST ${amount} from ${floID}?`);
if (!confirmation)
return alert("Cancelled");
User.requestToken(floID, amount, remark).then(result => {
console.log(`Requested ${amount} from ${floID}`, result);
alert(`Requested ${amount} from ${floID}`);
}).catch(error => console.error(error));
}
userUI.renderCashierRequests = function(requests, error = null) {
if (error)
return console.error(error);
else if (typeof requests !== "object" || request === null)
return;
let table = document.getElementById('user-cashier-requests').getElementsByTagName('tbody')[0];
for (let r in requests) {
let oldCard = document.getElementById(r);
if (oldCard) oldCard.remove();
let row = table.insertRow();
renderUser_cashierRequestCard(request[r], row);
}
}
function renderUser_cashierRequestCard(request, row) {
row.id = request.vectorClock;
row.insertCell().textContent = request.time;
row.insertCell().textContent = request.receiverID;
row.insertCell().textContent = request.message.mode;
let status = request.tag ? (status = request.tag + ":" + request.note) : (request.note || "PENDING");
row.insertCell().textContent = status; //Status
}
userUI.renderMoneyRequests = function(requests, error = null) {
if (error)
return console.error(error);
else if (typeof requests !== "object" || request === null)
return;
let table = document.getElementById('user-money-requests').getElementsByTagName('tbody')[0];
for (let r in requests) {
let oldCard = document.getElementById(r);
if (oldCard) oldCard.remove();
let row = table.insertRow();
renderUser_moneyRequestCard(request[r], row);
}
}
function renderUser_moneyRequestCard(request, row) {
row.id = request.vectorClock;
row.insertCell().textContent = request.time;
row.insertCell().textContent = request.senderID;
row.insertCell().textContent = request.message.amount;
row.insertCell().textContent = request.message.remark;
let status = request.note;
if (status)
row.insertCell().textContent = request.note;
else
row.insertCell().innerHTML =
`<input type="button" value="Accept" onclick="userUI.payRequest('${request.vectorClock}')" />` +
`<input type="button" value="Decline" onclick="userUI.declineRequest('${request.vectorClock}')" />`;
}
userUI.payRequest = function(reqID) {
let request = User.moneyRequests[reqID];
let confirmation = prompt(`Do you want to SEND ${request.message. amount} to ${request.senderID}?`);
if (!confirmation)
return alert("Cancelled");
User.sendToken(request.senderID, request.message.amount, request.message.remark).then(txid => {
console.info(`Sent ${request.message.amount} to ${request.senderID}`, txid);
alert(`Sent ${request.message.amount} to ${request.senderID}. It may take a few mins to reflect in their wallet`);
User.decideRequest(request, 'PAID: ' + txid)
.then(result => console.log(result))
.catch(error => console.error(error))
}).catch(error => console.error(error));
}
userUI.declineRequest = function(reqID) {
let request = User.moneyRequests[reqID];
User.decideRequest(request, "DECLINED").then(result => {
console.log(result);
alert("Declined request");
}).catch(error => console.error(error))
}
//Cashier
const cashierUI = {};
cashierUI.renderRequests = function(requests, error = null) {
if (error)
return console.error(error);
else if (typeof requests !== "object" || request === null)
return;
let table = document.getElementById('cashier-request-list').getElementsByTagName('tbody')[0];
for (let r in requests) {
let oldCard = document.getElementById(r);
if (oldCard) oldCard.remove();
let row = table.insertRow();
renderRequestCard(request[r], row);
}
}
function renderCashier_requestCard(request, row) {
row.id = request.vectorClock;
row.insertCell().textContent = request.senderID;
row.insertCell().textContent = request.time;
row.insertCell().textContent = request.message.mode;
let status = request.tag || request.note; //status tag for completed, note for rejected
if (status)
row.insertCell().textContent = status;
else
row.insertCell().innerHTML = `<input type="button" value="PENDING" onclick="cashierUI.completeRequest('${request.vectorClock}')" />`
}
cashierUI.completeRequest = function(reqID) {
let request = Cashier.Requests[reqID];
if (request.message.mode === "cash-to-token")
completeCashToTokenRequest(request);
else if (request.message.mode === "token-to-cash")
completeTokenToCashRequest(request);
}
function completeCashToTokenRequest(request) {
Cashier.checkIfUpiTxIsValid(request.message.upiTxID).then(_ => {
let confirmation = prompt(`Check if you have received UPI transfer\ntxid:${request.message.upi_txid}\namount:${request.message.amount}`);
if (!confirmation)
return alert("Cancelled");
User.sendToken(request.senderID, request.message.amount, 'for cash-to-token').then(txid => {
console.log("txid", txid);
Cashier.finishRequest(request, txid).then(result => {
console.log(result);
console.info('Completed cash-to-token request:', request.vectorClock);
alert("Completed request");
}).catch(error => console.error(error))
}).catch(error => console.error(error))
}).catch(error => {
console.error(error);
alert(error);
if (Array.isArray(error) && error[0] === true && typeof error[1] === 'string')
Cashier.rejectRequest(request, error[1]).then(result => {
console.log(result);
console.info('Rejected cash-to-token request:', request.vectorClock);
}).catch(error => console.error(error))
})
}
function completeTokenToCashRequest(request) {
Cashier.checkIfTokenTxIsValid(request.message.token_txid, request.senderID, request.message.amount).then(result => {
let upiTxID = prompt(`Token transfer is verified!\n Send ${request.message.amount} to ${request.message.upi_id} and Enter UPI txid`);
if (!upiTxID)
return alert("Cancelled");
Cashier.finishRequest(request, upiTxID).then(result => {
console.log(result);
console.info('Completed token-to-cash request:', request.vectorClock);
alert("Completed request");
}).catch(error => console.error(error))
}).catch(error => {
console.error(error);
alert(error);
if (Array.isArray(error) && error[0] === true && typeof error[1] === 'string')
Cashier.rejectRequest(request, error[1]).then(result => {
console.log(result);
console.info('Rejected token-to-cash request:', request.vectorClock);
}).catch(error => console.error(error))
})
}

133
new.html Normal file
View File

@ -0,0 +1,133 @@
<!DOCTYPE html>
<html>
<head>
<title>RanchiMall Pay</title>
<script id="floGlobals">
/* Constants for FLO blockchain operations !!Make sure to add this at begining!! */
const floGlobals = {
//Required for all
blockchain: "FLO",
//Required for blockchain API operators
apiURL: {
FLO: ['https://livenet.flocha.in/', 'https://flosight.duckdns.org/'],
FLO_TEST: ['https://testnet-flosight.duckdns.org/', 'https://testnet.flocha.in/']
},
adminID: "FKAEdnPfjXLHSYwrXQu377ugN4tXU7VGdf",
sendAmt: 0.001,
fee: 0.0005,
//Required for token API operations
tokenURL: "https://ranchimallflo.duckdns.org/",
currency: "rupee",
//Required for Supernode operations
SNStorageID: "FNaN9McoBAEFUjkRmNQRYLmBF8SpS7Tgfk",
supernodes: {}, //each supnernode must be stored as floID : {uri:<uri>,pubKey:<publicKey>}
//for cloud apps
subAdmins: [],
application: "TEST_MODE",
appObjects: {},
generalData: {},
lastVC: {}
}
</script>
<script src="std_op.js"></script>
<script src="fn_pay.js"></script>
<script src="fn_ui.js"></script>
<script id="onLoadStartUp">
function onLoadStartUp() {
console.log("Starting the app! Please Wait!")
floDapps.launchStartUp().then(result => {
console.log(`Welcome ${myFloID}`);
if (floGlobals.subAdmins.includes(myFloID)) {
document.getElementById('cashier-id').textContent = myFloID;
cashierUI.renderRequests(Cashier.Requests);
Cashier.init().then(result => {
console.log(result);
document.getElementById('cashier').hidden = false;
}).catch(error => console.error(error))
} else {
document.getElementById('user-id').textContent = myFloID;
userUI.renderCashierRequests(User.cashierRequests);
userUI.renderMoneyRequests(User.moneyRequests);
User.init().then(result => {
console.log(result);
document.getElementById('user').hidden = false;
}).catch(error => console.error(error))
}
}).catch(error => console.error(error))
}
</script>
</head>
<body onload="onLoadStartUp()">
<section id="user" hidden>
<div id="user-id"></div>
<div>
<form id="request-cashier">
Amount: <input type="number" name="amount" /><br />
<input type="button" value="request-token" onclick="userUI.requestTokenFromCashier()" />
<input type="button" value="withdraw-cash" onclick="userUI.withdrawCashFromCashier()" />
</form>
</div>
<div>
<form id="user-money">
FLO-ID<input type="text" name="flo-id" /><br />
Amount<input type="number" name="amount" /><br />
Remark<input type="text" name="remark" /><br />
<input type="button" value="send-money" onclick="userUI.sendMoneyToUser()" />
<input type="button" value="request-money" onclick="userUI.requestMoneyFromUser()" />
</form>
</div>
<div>
<table id="user-cashier-requests">
<thead>
<tr>
<td>Date-Time</td>
<td>Cashier</td>
<td>Mode</td>
<td>Status</td>
</tr>
</thead>
</table>
</div>
<div>
<table id="user-money-requests">
<thead>
<tr>
<td>Date-Time</td>
<td>Requestor</td>
<td>Amount</td>
<td>Remark</td>
<td>Status</td>
</tr>
</thead>
</table>
</div>
</section>
<section id="cashier" hidden>
<div id="cashier-id"></div>
<div>
<table id="cashier-request-list">
<thead>
<tr>
<td>Requestor</td>
<td>Date-Time</td>
<td>Mode</td>
<td>Status</td>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</section>
</body>
</html>