modified cash handler page to work with multiple supernodes simultaneously

This commit is contained in:
Abhishek Sinha 2019-11-07 16:13:40 +05:30
parent b08e84ac34
commit 24dcc080d6
2 changed files with 597 additions and 392 deletions

View File

@ -11334,14 +11334,15 @@
<!-- CASH PAYMENTS HANDLER SCRIPT START -->
<script>
(function payments_handler() {
//(function payments_handler() {
/* CODE_JUNCTION: localbitcoinplusplus object init */
var localbitcoinplusplus = {
wallets: {},
trade: {},
rpc: {},
master_configurations: {}
master_configurations: {},
supernode_conns: {},
};
Object.defineProperty(localbitcoinplusplus, "server", {
@ -11359,6 +11360,16 @@
enumerable: false
});
Object.defineProperty(localbitcoinplusplus, "assets", {
value: {
BTC: "BTC_TEST",
FLO: "FLO_TEST"
},
writable: false,
configurable: false,
enumerable: false
});
Object.defineProperty(localbitcoinplusplus, "RM_FLO_SENDING_ADDR", {
value: "ocKKEivXC3TA8yf3ZEyh2kRMDgSh99y1a7",
writable: false,
@ -11920,6 +11931,26 @@
localbitcoinplusplus.actions = {
parse_flo_comments: async function(callback) {
text = `masterFLOPubKey=03EA5E2CAB18DA585400D6EC569438D415FAF200528E05D0E2B9BEAA2B5C3DCA90
#!#tradableAsset1=BTC,FLO,BTC_TEST,FLO_TEST#!#tradableAsset2=INR,USD,
#!#validTradingAmount=10,50,100,#!#btcTradeMargin=5000
#!#MaxBackups=1
#!#miners_fee={"btc":0.0003, "flo":0.0003}
#!#supernodesPubKeys=0315C3A20FE7096CC2E0F81A80D5F1A687B8F9EFA65242A0B0881E1BA3EE7D7D53,
03F7493F11B8E44B9798CD434D20FBE7FA34B9779D144984889D11A17C56A18742,039B4AA00DBFC0A6631DE6DA83526611A0E6B857D3579DF840BBDEAE8B6898E3B6,
03C8E3836C9A77E2AF03D4265D034BA85732738919708EAF6A16382195AE796EDF,0349B08AA1ABDCFFB6D78CD7C949665AD2FF065EA02B3C6C47A5E9592C9A1C6BCB,
026FCC6CFF6EB3A39E54BEB6E13FC2F02C3A93F4767AA80E49E7E876443F95AE5F,
#!#assets={"BTC":"BTC_TEST","FLO":"FLO_TEST"}
#!#externalFiles={"d3js":"58f54395efa8346e8e94d12609770f66b916897e7f4e05f6c98780cffa5c70a3"}
#!#cashiers={"032871A74D2DDA9D0DE7135F58B5BD2D7F679D2CCA20EA7909466D1A6912DF4022":"johnDoe@upi",
"03DB4A12EB543B293DDBB0CE314C46C36D6761294AFBB7264A6D78F710FFD97CF0":"janeDoe@upi"}
#!#ShamirsMaxShares=8#!#supernodeSeeds={"ranchimall1":{"ip":"127.0.0.1","port":"9111","kbucketId":"oZxHcbSf1JC8t5GjutopWYXs7C6Fe9p7ps"},
"ranchimall2":{"ip":"127.0.0.1","port":"9112","kbucketId":"oTWjPupy3Z7uMdPcu5uXd521HBkcsLuSuM"},
"ranchimall3":{"ip":"127.0.0.1","port":"9113","kbucketId":"odYA6KagmbokSh9GY7yAfeTUZRtZLwecY1"},
"ranchimall4":{"ip":"127.0.0.1","port":"9114","kbucketId":"oJosrve9dBv2Hj2bfncxv2oEpTysg3Wejv"},
"ranchimall5":{"ip":"127.0.0.1","port":"9115","kbucketId":"oMhv5sAzqg77sYHxmUGZWKRrVo4P4JQduS"},
"ranchimall6":{"ip":"127.0.0.1","port":"9116","kbucketId":"oV1wCeWca3VawbBTfUGKA7Vd368PATnKAx"}}`;
return callback(text);
const master_data = await helper_functions
.ajaxGet(`${localbitcoinplusplus.server.flo_testnet}/api/txs/?address=${localbitcoinplusplus.RM_FLO_SENDING_ADDR}`);
if(typeof master_data==="object" && typeof master_data.txs==="object") {
@ -12143,7 +12174,7 @@
typeof usr == "object" &&
usr.myLocalFLOAddress.length > 0
) {
const RM_WALLET = new localbitcoinplusplus.wallets();
//const RM_WALLET = new localbitcoinplusplus.wallets();
const pk_manual = prompt("Please enter your private key: ");
let gen_new_keys = this.generateFloKeys(pk_manual);
if (gen_new_keys.address == usr.myLocalFLOAddress) {
@ -12255,7 +12286,7 @@
"string" &&
localbitcoinplusplus.wallets.MY_SUPERNODE_PRIVATE_KEY.length > 0
) {
const RM_WALLET = new localbitcoinplusplus.wallets();
//const RM_WALLET = new localbitcoinplusplus.wallets();
let user_keys = RM_WALLET.generateFloKeys(
localbitcoinplusplus.wallets.MY_SUPERNODE_PRIVATE_KEY
);
@ -12299,8 +12330,8 @@
var method = request.method;
if (typeof params == "object" && typeof method == "string") {
const RM_WALLET = new localbitcoinplusplus.wallets();
const RM_RPC = new localbitcoinplusplus.rpc();
//const RM_WALLET = new localbitcoinplusplus.wallets();
//const RM_RPC = new localbitcoinplusplus.rpc();
let respective_trader_id = "";
if (typeof params.trader_flo_address == "string")
@ -12655,7 +12686,7 @@
if (typeof myPrivateKey !== "string")
throw new Error("No private key found.");
const RM_WALLET = new localbitcoinplusplus.wallets();
//const RM_WALLET = new localbitcoinplusplus.wallets();
let privateKey = RM_WALLET.wifToDecimal(myPrivateKey, true);
if (typeof privateKey.privateKeyDecimal !== "string")
throw new Error("Failed to detremine your private key.");
@ -12674,6 +12705,9 @@
}
};
const RM_WALLET = new localbitcoinplusplus.wallets();
const RM_RPC = new localbitcoinplusplus.rpc();
/* CODE_JUNCTION: Indexed DB */
//prefixes of implementation that we want to test
@ -12974,38 +13008,31 @@
/* CODE_JUNCTION: Websockets */
function startWebSocket(wsUri) {
async function initializeWebSocket(wsUri){
var websocket = new WebSocket(wsUri);
return websocket;
}
function startWebSocket(websocket_name) {
return new Promise((resolve, reject) => {
websocket = new WebSocket(wsUri);
websocket.onopen = function(evt) {
websocket_name.onopen = function(evt) {
resolve(onOpen(evt));
};
websocket.onclose = function(evt) {
websocket_name.onclose = function(evt) {
reject(onClose(evt));
};
websocket.onmessage = function(evt) {
websocket_name.onmessage = function(evt) {
resolve(onMessage(evt));
};
websocket.onerror = function(evt) {
websocket_name.onerror = function(evt) {
reject(onError(evt));
};
});
}
function onOpen(evt) {
readAllDB("supernodesList").then(list => {
list.some(m => {
let ws_res = `ws://${m.ip}:${m.port}/`;
if (ws_res == websocket.url)
localbitcoinplusplus.CONNECTED_SUPERNODE_FLO_ADDRESS =
m.kbucketId;
});
});
console.info(`INFO: Connected succesfully to ${evt.srcElement.url}.`);
let conn_info = document.getElementById("conn_info");
conn_info.innerHTML = `<div class="alert alert-success" role="alert">
INFO: Connected to ${evt.srcElement.url} Supernode.
</div>`;
}
function onClose(event) {
@ -13022,121 +13049,242 @@
}
}
function onMessageAcceptTest(testName, testParameters) {
if (testName == "whetherForCashier") {
let is_message_for_cashier = testParameters.data.search("__FOR__CASHIER__");
if (is_message_for_cashier < 0) {
return false;
} else return true;
}
if (testName == "amISuperNode") {
if (testParameters.supernodesPubKeys.includes(testParameters.my_local_flo_public_key)) {
return true;
} else return false;
}
if (testName == "meInReceiverList") {
if (testParameters.receiversList.includes(testParameters.my_local_flo_address)) {
return true;
} else return false;
}
if (testName == "checkIfObject") {
if (typeof testParameters.data !== "object") {
return false;
} else return true;
}
if (testName == "receiverIDisMine") {
return testParameters.receiverFloId === localbitcoinplusplus.wallets.my_local_flo_address;
}
if (testName == "beforePrivateKeyEntry") {
return testParameters.methodList.includes(testParameters.method);
}
if(testName == "senderAddressMatchesSignerAddress") {
return testParameters.calculatedFloId === testParameters.senderFloId;
}
if(testName == "verifyMessageSignature") {
const initialMsgObjStr = JSON.stringify(testParameters.initialMsgObj);
const initialMsgObjStrHash = Crypto.SHA256(initialMsgObjStr);
//const RM_WALLET = new [testParameters.verifierObject]();
if (RM_WALLET.verify(
initialMsgObjStrHash,
testParameters.signedMsg,
testParameters.publicKey
)
) {
return true;
} else return false;
}
if(testName == "isDataString") {
return typeof testParameters.param === "string";
}
if(testName == "isValueUnDefined") {
return typeof testParameters.param === "undefined";
}
}
//HANDLER OUTSIDE
function onMessageDataHandling(handlerName,data){
if (handlerName == "extractMainObject") {
var res_pos = data.indexOf("{");
if (res_pos >= 0) {
var res = data.substr(res_pos);
}
return res;
}
}
function onMessageResponse(responseName, responseData) {
if(responseName==="list_of_cashier_latest_pending_cash_deposits") {
let response_from_server = responseData.responseData;
if (
typeof response_from_server.data == "object" &&
response_from_server.data.length > 0
) {
onMessageDisplay("list_of_cashier_latest_pending_cash_deposits", {
responseData: response_from_server
});
} else {
showMessage(`INFO: No pending deposits found.`);
}
}
if(responseName==="list_of_cashier_latest_pending_cash_withdrawals") {
let response_from_server = responseData.responseData;
if (
typeof response_from_server.data == "object" &&
response_from_server.data.length > 0
) {
onMessageDisplay("list_of_cashier_latest_pending_cash_withdrawals", {
responseData: response_from_server
});
} else {
showMessage(`INFO: No pending withdrawals found.`);
}
}
}
function onMessageDisplay(responseName, responseData) {
switch (responseName) {
case "list_of_cashier_latest_pending_cash_deposits":
(async function() {
let t = ``;
let deposits_table = document.getElementById("deposits_list");
for (const m of responseData.responseData.data) {
let su_res = await localbitcoinplusplus.kademlia.determineClosestSupernode(m.trader_flo_address);
let closestSupernode = su_res[0].data.id;
t += `<tr>`;
t += `<td> ${m.user_upi} </td>`;
t += `<td> ${m.trader_flo_address} </td>`;
t += `<td> ${m.depositing_amount} </td>`;
t += `<td> ${m.currency} </td>`;
t += `<td> <button type="button" value="${m.id}" class="btn btn-info cnf_deposits">Deposit Received!</button>
<span id="depositSpan${m.id}">${closestSupernode}_${responseData.responseData.requesting_supernode}</span>
</td>`;
t += `</tr>`;
// Find Supernode of the user
confirmDepositReceivedFromUser();
}
deposits_table.insertAdjacentHTML("beforeend", t);
})();
break;
case "list_of_cashier_latest_pending_cash_withdrawals":
(async function() {
let v = ``;
const withdraws_table = document.getElementById("withdraws_list");
for (const m of responseData.responseData.data) {
const user_upi = localbitcoinplusplus.encrypt.decryptMessage(
response_from_sever.data[0].receivinAddress.secret,
response_from_sever.data[0].receivinAddress.senderPublicKeyString
);
let su_res = await localbitcoinplusplus.kademlia.determineClosestSupernode(m.trader_flo_address);
let closestSupernode = su_res[0].data.id;
v += `<tr>`;
v += `<td> ${user_upi} </td>`;
v += `<td> ${m.trader_flo_address} </td>`;
v += `<td> ${m.withdraw_amount} </td>`;
v += `<td> ${m.currency} </td>`;
v += `<td> ${m.token_transfer_txid} </td>`;
v += `<td> <button type="button" value="${m.id}" class="btn btn-info cnf_withdrawal">Money Transferred!</button>
<span id="withdrawSpan${m.id}">${closestSupernode}_${responseData.responseData.requesting_supernode}</span>
</td>`;
v += `</tr>`;
confirmCashierTransferredMoneyToWithdrawer();
}
withdraws_table.insertAdjacentHTML("beforeend", v);
})();
break;
default:
break;
}
}
async function onMessage(evt) {
var response = evt.data || evt;
let is_message_for_cashier = response.search("__FOR__CASHIER__");
if (is_message_for_cashier < 0) return;
console.log(response);
if (!onMessageAcceptTest("whetherForCashier", {searchString:"__FOR__CASHIER__",data:response})) return;
console.log("RESPONSE: " + response);
var res_pos = response.indexOf("{");
if (res_pos >= 0) {
var res = response.substr(res_pos);
//var res_pos = response.indexOf("{");
var res = onMessageDataHandling("extractMainObject", response);
try {
var res_obj = JSON.parse(res);
if (
typeof res_obj.globalParams !== "object" ||
(localbitcoinplusplus.master_configurations.supernodesPubKeys.includes(
localbitcoinplusplus.wallets.my_local_flo_public_key
) &&
typeof res_obj.globalParams.receiversList == "object" &&
!res_obj.globalParams.receiversList.includes(
localbitcoinplusplus.wallets.my_local_flo_address
))
)
return;
if(!onMessageAcceptTest("checkIfObject", {
data:res_obj.globalParams,
})) return;
if (
typeof res_obj.globalParams.receiverFloId == "string" &&
res_obj.globalParams.receiverFloId !==
localbitcoinplusplus.wallets.my_local_flo_address
)
return;
if(onMessageAcceptTest("amISuperNode",
{supernodesPubKeys:
localbitcoinplusplus.master_configurations.supernodesPubKeys,
my_local_flo_public_key:
localbitcoinplusplus.wallets.my_local_flo_public_key
})) return;
if(onMessageAcceptTest("checkIfObject", {
data:res_obj.globalParams.receiversList,
}) &&
!onMessageAcceptTest("meInReceiverList", {
receiversList:res_obj.globalParams.receiversList,
my_local_flo_address:localbitcoinplusplus.wallets.my_local_flo_address
})
) return;
if(!onMessageAcceptTest("receiverIDisMine", {
receiverFloId:res_obj.globalParams.receiverFloId,
})) return;
const isIncomingMessageValid = await validateIncomingMessage(res);
console.log("isIncomingMessageValid: ", isIncomingMessageValid);
if (!isIncomingMessageValid) return;
if (typeof res_obj.globalParams.senderFloId !== "string")
throw new Error(
`WARNING: The request did not contain sender FLO Id. Request Aborted.`
);
if(!onMessageAcceptTest("isDataString", {
param:res_obj.globalParams.senderFloId,
})) return;
if(onMessageAcceptTest("isValueUnDefined", {
param: res_obj.method
})) return;
if (typeof res_obj.method !== "undefined") {
let response_from_sever;
const RM_WALLET = new localbitcoinplusplus.wallets();
const RM_RPC = new localbitcoinplusplus.rpc();
// const RM_WALLET = new localbitcoinplusplus.wallets();
// const RM_RPC = new localbitcoinplusplus.rpc();
switch (res_obj.method) {
case "list_of_cashier_latest_pending_cash_deposits":
response_from_sever = res_obj.params[0];
if (
typeof response_from_sever.data == "object" &&
response_from_sever.data.length > 0
) {
const deposits_table = document.getElementById(
"deposits_list"
);
let t = ``;
response_from_sever.data.map(m => {
t += `<tr>`;
t += `<td> ${m.user_upi} </td>`;
t += `<td> ${m.trader_flo_address} </td>`;
t += `<td> ${m.depositing_amount} </td>`;
t += `<td> ${m.currency} </td>`;
t += `<td> <button type="button" value="${m.id}" class="btn btn-info cnf_deposits">Deposit Received!</button> </td>`;
t += `</tr>`;
onMessageResponse("list_of_cashier_latest_pending_cash_deposits", {
responseData: res_obj.params[0]
});
deposits_table.insertAdjacentHTML("beforeend", t);
confirmDepositReceivedFromUser();
} else {
showMessage(`INFO: No pending deposits found.`);
}
break;
case "list_of_cashier_latest_pending_cash_withdrawals":
response_from_sever = res_obj.params[0];
if (
typeof response_from_sever.data == "object" &&
response_from_sever.data.length > 0
) {
const withdraws_table = document.getElementById(
"withdraws_list"
);
let t = ``;
response_from_sever.data.map(m => {
const user_upi = localbitcoinplusplus.encrypt.decryptMessage(
response_from_sever.data[0].receivinAddress.secret,
response_from_sever.data[0].receivinAddress
.senderPublicKeyString
);
t += `<tr>`;
t += `<td> ${user_upi} </td>`;
t += `<td> ${m.trader_flo_address} </td>`;
t += `<td> ${m.withdraw_amount} </td>`;
t += `<td> ${m.currency} </td>`;
t += `<td> ${m.token_transfer_txid} </td>`;
t += `<td> <button type="button" value="${m.id}" class="btn btn-info cnf_withdrawal">Money Transferred!</button> </td>`;
t += `</tr>`;
});
withdraws_table.insertAdjacentHTML("beforeend", t);
confirmCashierTransferredMoneyToWithdrawer();
} else {
showMessage(`INFO: No pending withdrawals found.`);
}
onMessageResponse("list_of_cashier_latest_pending_cash_withdrawals", {
responseData: res_obj.params[0]
});
break;
default:
break;
}
}
} catch (e) {
throw new Error(e);
}
}
}
function onError(evt) {
@ -13145,12 +13293,12 @@
);
}
function doSend(message = "") {
function doSend(websocket_name, message = "") {
let finalMessage = message;
const msgObj = JSON.parse(message);
const RM_WALLET = new localbitcoinplusplus.wallets();
//const RM_WALLET = new localbitcoinplusplus.wallets();
message = JSON.stringify(msgObj);
const message256hash = Crypto.SHA256(message);
@ -13175,7 +13323,7 @@
// The message is for usernodes and all backup supernodes
try {
websocket.send(finalMessage);
websocket_name.send(finalMessage);
} catch (error) {
throw new Error(error);
}
@ -13196,17 +13344,19 @@
try {
const msgObj = JSON.parse(message);
if (request_array.includes(msgObj.method)) return resolve(true);
//if (request_array.includes(msgObj.method)) return resolve(true);
if (onMessageAcceptTest("beforePrivateKeyEntry", {"methodList":request_array,"method":msgObj.method})) return resolve(true);
const getFloId = bitjs.FLO_TEST.pubkey2address(msgObj.nodePubKey);
//const getFloId = bitjs.FLO_TEST.pubkey2address(msgObj.nodePubKey);
const getFloId = bitjs[localbitcoinplusplus.assets.FLO].pubkey2address(msgObj.nodePubKey);
// Check if the public key belongs to real sender
if (getFloId !== msgObj.globalParams.senderFloId) {
if (!onMessageAcceptTest("senderAddressMatchesSignerAddress", {"senderFloId":msgObj.globalParams.senderFloId,"calculatedFloId":getFloId})) {
showMessage(
`Sender FLO address did not match signer FLO address.`
`Sender FLO address did not match signer FLO address.`
);
reject(false);
}
const initialMsgObj = {
jsonrpc: msgObj.jsonrpc,
id: msgObj.id,
@ -13215,18 +13365,12 @@
globalParams: msgObj.globalParams
};
const initialMsgObjStr = JSON.stringify(initialMsgObj);
const initialMsgObjStrHash = Crypto.SHA256(initialMsgObjStr);
const RM_WALLET = new localbitcoinplusplus.wallets();
if (
RM_WALLET.verify(
initialMsgObjStrHash,
msgObj.nodeSignedMessage,
msgObj.nodePubKey
)
) {
if (onMessageAcceptTest("verifyMessageSignature", {
"initialMsgObj":initialMsgObj,
"verifierObject": localbitcoinplusplus.wallets,
"signedMsg": msgObj.nodeSignedMessage,
"publicKey": msgObj.nodePubKey
})) {
resolve(true);
} else {
showMessage(
@ -13332,102 +13476,83 @@
// Connect to Supernode
function loadSupernodesConnectUi() {
let supernodeSeedsObj =
let supernodeSeedsObj =
localbitcoinplusplus.master_configurations.supernodeSeeds;
let supernodeSeedsArray = Object.values(supernodeSeedsObj);
let supernode_seedsInput = ``;
supernode_seedsInput += `<div class="input-group">
<select class="custom-select" id="supernode_seeds">
<option selected>Choose Suprnode...</option>`;
supernodeSeedsArray.map(wsUri => {
supernode_seedsInput += `<option value="ws://${wsUri.ip}:${wsUri.port}">${wsUri.kbucketId}</option>`;
});
supernode_seedsInput += `</select>
<div class="input-group-append">
<button class="btn btn-outline-secondary" id="supn_conn_btn" type="button">Connect</button>
</div>
</div>`;
const supernode_seeds_div = document.getElementById(
"supernode_seeds_div"
);
supernode_seeds_div.innerHTML = supernode_seedsInput;
const supn_conn_btn = document.getElementById("supn_conn_btn");
supn_conn_btn.addEventListener("click", function(evt) {
const selected_su = document.getElementById("supernode_seeds");
if (
typeof websocket == "object" &&
websocket.readyState === WebSocket.OPEN
) {
if (websocket.url === `${selected_su.value}/`) {
showMessage(`INFO: Websocket already connected.`);
return;
}
websocket.close();
}
try {
startWebSocket(selected_su.value);
} catch (error) {
showMessage("Error: " + error);
return;
}
let supernodeSeedsArray = Object.values(supernodeSeedsObj);
supernodeSeedsArray.map(async wsUri => {
localbitcoinplusplus.supernode_conns[wsUri.kbucketId] = await initializeWebSocket (`ws://${wsUri.ip}:${wsUri.port}`);
startWebSocket(localbitcoinplusplus.supernode_conns[wsUri.kbucketId]);
});
}
function send_deposit_withdraw_req_loop() {
let supernodeSeedsObj =
localbitcoinplusplus.master_configurations.supernodeSeeds;
let supernodeSeedsArray = Object.values(supernodeSeedsObj);
const btn_id = this.id;
if (typeof btn_id !== "string") return;
let job = "";
if (btn_id == "fetch_deposits") {
job = "give_cashier_latest_pending_cash_deposits";
} else if (btn_id == "fetch_withdraws") {
job = "give_cashier_latest_pending_cash_withdraws";
} else return;
supernodeSeedsArray.map(async wsUri => {
send_deposit_withdraw_req(wsUri.kbucketId, job);
});
}
// Fetch Deposit or Withdraw requests
function send_deposit_withdraw_req(evt) {
evt.preventDefault();
if (
localbitcoinplusplus.MY_UPI_ID.length < 1
|| typeof localbitcoinplusplus.CONNECTED_SUPERNODE_FLO_ADDRESS !== "string"
|| localbitcoinplusplus.CONNECTED_SUPERNODE_FLO_ADDRESS.length < 1
) {
function send_deposit_withdraw_req(websocket_flo_id="", job="", parent_flo_id="") {
if (localbitcoinplusplus.MY_UPI_ID.length < 1) {
showMessage(
`WARNING: Your UPI Id or connected Supernode is not set.`
`WARNING: Your UPI Id is not set.`
);
return false;
}
const btn_id = this.id;
if (typeof btn_id !== "string") return;
let job = "";
if (btn_id == "fetch_deposits") {
job = "give_cashier_latest_pending_cash_deposits";
} else if (btn_id == "fetch_withdraws") {
job = "give_cashier_latest_pending_cash_withdraws";
} else return;
const websocket_name = localbitcoinplusplus.supernode_conns[websocket_flo_id];
if(typeof websocket_name!=="object") return;
const RM_RPC = new localbitcoinplusplus.rpc();
RM_RPC.send_rpc
.call(this, job, {
if(job.length<1) return;
let req_body = {
trader_flo_address:
localbitcoinplusplus.wallets.my_local_flo_address,
cashier_pubKey:
localbitcoinplusplus.wallets.my_local_flo_public_key,
cashier_upi: localbitcoinplusplus.MY_UPI_ID,
receiver_flo_address:
localbitcoinplusplus.CONNECTED_SUPERNODE_FLO_ADDRESS
})
.then(resp => doSend(resp));
receiver_flo_address: websocket_flo_id,
}
// For case where parent supernode is dead
if(websocket_flo_id !== parent_flo_id && parent_flo_id.length>0) {
req_body.parent_supernode = parent_flo_id;
req_body.requesting_supernode = websocket_flo_id;
}
if(parent_flo_id.length<1 || websocket_flo_id==parent_flo_id) {
req_body.parent_supernode = websocket_flo_id;
req_body.requesting_supernode = websocket_flo_id;
}
RM_RPC.send_rpc
.call(this, job, req_body)
.then(resp => doSend(websocket_name, resp));
}
// Ask Connected Supernode to give pending deposits/withdrawals
function AskSupernodeForLatestDepositsAndWithdrawalsData() {
const fetch_deposits_btn = document.getElementById("fetch_deposits");
const fetch_withdraws_btn = document.getElementById(
"fetch_withdraws"
);
const fetch_withdraws_btn = document.getElementById("fetch_withdraws");
fetch_deposits_btn.addEventListener(
"click",
send_deposit_withdraw_req
send_deposit_withdraw_req_loop
);
fetch_withdraws_btn.addEventListener(
"click",
send_deposit_withdraw_req
send_deposit_withdraw_req_loop
);
}
@ -13436,9 +13561,15 @@
Array.from(recv_deposit_btn).forEach(function(element) {
element.addEventListener("click", function(evt) {
evt.preventDefault();
//evt.preventDefault();
const deposit_id = this.value;
console.log(deposit_id);
const req_info = document.getElementById(`depositSpan${deposit_id}`);
const req_info_arr = req_info.innerText.split("_");
const websocket_name = req_info_arr[0];
const requesting_supernode = req_info_arr[1];
if(typeof websocket_name!=="string" || typeof requesting_supernode!=="string") return;
const flo_txid = prompt("Enter Deposit Token Transfer Flo Txid: ");
if (flo_txid.length < 1) return;
@ -13454,20 +13585,26 @@
)
return;
const RM_RPC = new localbitcoinplusplus.rpc();
RM_RPC.send_rpc
.call(this, "cashier_confirms_user_cash_deposit", {
//const RM_RPC = new localbitcoinplusplus.rpc();
let req_body = {
trader_flo_address:
localbitcoinplusplus.wallets.my_local_flo_address,
cashier_pubKey:
localbitcoinplusplus.wallets.my_local_flo_public_key,
receiver_flo_address:
localbitcoinplusplus.CONNECTED_SUPERNODE_FLO_ADDRESS,
receiver_flo_address: requesting_supernode,
flo_txid: flo_txid,
deposit_id: deposit_id,
cash_deposited: cash_recvd_from_user
})
.then(resp => doSend(resp));
cash_deposited: cash_recvd_from_user,
parent_supernode: websocket_name,
}
const websocket_conn = localbitcoinplusplus.supernode_conns[requesting_supernode];
if(typeof websocket_conn!=="object") return;
RM_RPC.send_rpc
.call(this, "cashier_confirms_user_cash_deposit", req_body)
.then(resp => doSend(websocket_conn, resp));
});
});
@ -13481,24 +13618,31 @@
element.addEventListener("click", function(evt) {
evt.preventDefault();
const withdraw_id = this.value;
console.log(withdraw_id);
const req_info = document.getElementById(`withdrawSpan${deposit_id}`);
const req_info_arr = req_info.innerText.split("_");
const websocket_name = req_info_arr[0];
const requesting_supernode = req_info_arr[1];
if(typeof websocket_name!=="string" || typeof requesting_supernode!=="string") return;
const upi_txid = prompt("Enter Transferred Cash UPI Txid: ");
if (upi_txid.length < 1) return;
const websocket_conn = localbitcoinplusplus.supernode_conns[requesting_supernode];
if(typeof websocket_conn!=="object") return;
const RM_RPC = new localbitcoinplusplus.rpc();
RM_RPC.send_rpc
.call(this, "cashier_confirms_user_cash_withdraw", {
trader_flo_address:
localbitcoinplusplus.wallets.my_local_flo_address,
cashier_pubKey:
localbitcoinplusplus.wallets.my_local_flo_public_key,
receiver_flo_address:
localbitcoinplusplus.CONNECTED_SUPERNODE_FLO_ADDRESS,
receiver_flo_address: requesting_supernode,
withdraw_id: withdraw_id,
upi_txid: upi_txid
upi_txid: upi_txid,
parent_supernode: websocket_name,
})
.then(resp => doSend(resp));
.then(resp => doSend(websocket_conn, resp));
});
});
}
@ -13521,7 +13665,7 @@
`This will reset your old keys along with data associated with it. Are you sure you want to continue?`
)
) {
const RM_WALLET = new localbitcoinplusplus.wallets();
//const RM_WALLET = new localbitcoinplusplus.wallets();
RM_WALLET.reset_flo_keys().then(reset_success => {
if (reset_success) {
showMessage("INFO: FLO keys have been reset successfully.");
@ -13537,8 +13681,8 @@
const dataBaseUIOperations = async function() {
localbitcoinplusplus.is_ui_loaded = true;
const RM_WALLET = new localbitcoinplusplus.wallets();
const RM_RPC = new localbitcoinplusplus.rpc();
//const RM_WALLET = new localbitcoinplusplus.wallets();
//const RM_RPC = new localbitcoinplusplus.rpc();
try {
readDB("paymentsHandlerDetails", "00-01").then(async function(
@ -13572,7 +13716,7 @@
function kickInit() {
output = document.getElementById("output_div");
const RM_WALLET = new localbitcoinplusplus.wallets();
//const RM_WALLET = new localbitcoinplusplus.wallets();
return new Promise(resolve => {
readDB("paymentsHandlerDetails", "00-01").then(async function(
idbData
@ -13710,7 +13854,7 @@
});
});
}
})();
//})();
</script>
<script>
@ -13783,20 +13927,5 @@
}
</script>
<script
src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
crossorigin="anonymous"
></script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
crossorigin="anonymous"
></script>
<script
src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
crossorigin="anonymous"
></script>
</body>
</html>

View File

@ -12077,7 +12077,7 @@
026FCC6CFF6EB3A39E54BEB6E13FC2F02C3A93F4767AA80E49E7E876443F95AE5F,
#!#externalFiles={"d3js":"58f54395efa8346e8e94d12609770f66b916897e7f4e05f6c98780cffa5c70a3"}
#!#cashiers={"032871A74D2DDA9D0DE7135F58B5BD2D7F679D2CCA20EA7909466D1A6912DF4022":"johnDoe@upi",
"janeDoe@upi":"03DB4A12EB543B293DDBB0CE314C46C36D6761294AFBB7264A6D78F710FFD97CF0"}
"03DB4A12EB543B293DDBB0CE314C46C36D6761294AFBB7264A6D78F710FFD97CF0":"janeDoe@upi"}
#!#ShamirsMaxShares=8#!#supernodeSeeds={"ranchimall1":{"ip":"127.0.0.1","port":"9111","kbucketId":"oZxHcbSf1JC8t5GjutopWYXs7C6Fe9p7ps"},
"ranchimall2":{"ip":"127.0.0.1","port":"9112","kbucketId":"oTWjPupy3Z7uMdPcu5uXd521HBkcsLuSuM"},
"ranchimall3":{"ip":"127.0.0.1","port":"9113","kbucketId":"odYA6KagmbokSh9GY7yAfeTUZRtZLwecY1"},
@ -12465,8 +12465,9 @@
);
const promise2 = removeAllinDB("my_supernode_private_key_chunks");
return Promise.all([promise1, promise2])
const promise3 = removeAllinDB("myClosestSupernodes");
return Promise.all([promise1, promise2, promise3])
.then(() => true)
.catch(e => false);
},
@ -14115,6 +14116,8 @@
localbitcoinplusplus.master_configurations.supernodesPubKeys.length)
return;
if(typeof localbitcoinplusplus.myClosestSupernodes==="object") return;
const idbData = await readDB("localbitcoinUser", "00-01");
if (getClosestSuList.length < 1) {
@ -14378,6 +14381,9 @@
<!-- Misc functions -->
<script>
function removeWhiteSpaces(text='') {
return text.replace(/\s/g,'');
}
// log event in the console
function LogEvent(msg) {
log.textContent += "> " + msg + "\n";
@ -18408,181 +18414,251 @@
switch (method) {
case "give_cashier_latest_pending_cash_deposits":
const get_all_deposit_reqs_for_this_cashier = await readDBbyIndex(
"cash_deposits",
"cashier_pubKey",
params.cashier_pubKey
);
(async function() {
let _readDBbyIndex = readDBbyIndex;
if(typeof params.parent_supernode==="string"
&& params.parent_supernode.length
&& localbitcoinplusplus.wallets.my_local_flo_address
!== params.parent_supernode ) {
const foreign_db =
localbitcoinplusplus.newBackupDatabase.db[params.parent_supernode];
if(typeof foreign_db !== "object") return;
_readDBbyIndex = foreign_db.backup_readDBbyIndex.bind(foreign_db);
}
const get_all_deposit_reqs_for_this_cashier = await _readDBbyIndex(
"cash_deposits",
"cashier_pubKey",
params.cashier_pubKey
);
RM_RPC.send_rpc
.call(
this,
"list_of_cashier_latest_pending_cash_deposits",
{
for_cashier: true,
cashier_pubKey: request.nodePubKey,
receiver_flo_address: request.globalParams.senderFloId,
data: get_all_deposit_reqs_for_this_cashier
}
)
.then(resp => doSend(resp));
RM_RPC.send_rpc
.call(
this,
"list_of_cashier_latest_pending_cash_deposits",
{
for_cashier: true,
cashier_pubKey: request.nodePubKey,
receiver_flo_address: request.globalParams.senderFloId,
data: get_all_deposit_reqs_for_this_cashier,
requesting_supernode: params.requesting_supernode,
parent_supernode: params.parent_supernode
}
)
.then(resp => doSend(resp));
})();
break;
case "give_cashier_latest_pending_cash_withdraws":
const get_all_withdraws_reqs_for_this_cashier = await readDBbyIndex(
"withdraw_cash",
"cashier_pubKey",
params.cashier_pubKey
);
(async function() {
let _readDBbyIndex = readDBbyIndex;
if(typeof params.parent_supernode==="string"
&& params.string.length
&& localbitcoinplusplus.wallets.my_local_flo_address
!== params.parent_supernode ) {
const foreign_db =
localbitcoinplusplus.newBackupDatabase.db[params.parent_supernode];
if(typeof foreign_db !== "object") return;
_readDBbyIndex = foreign_db.backup_readDBbyIndex.bind(foreign_db);
}
const get_all_withdraws_reqs_for_this_cashier = await _readDBbyIndex(
"withdraw_cash",
"cashier_pubKey",
params.cashier_pubKey
);
RM_RPC.send_rpc
.call(
this,
"list_of_cashier_latest_pending_cash_withdrawals",
{
for_cashier: true,
cashier_pubKey: request.nodePubKey,
receiver_flo_address: request.globalParams.senderFloId,
data: get_all_withdraws_reqs_for_this_cashier
}
)
.then(resp => doSend(resp));
RM_RPC.send_rpc
.call(
this,
"list_of_cashier_latest_pending_cash_withdrawals",
{
for_cashier: true,
cashier_pubKey: request.nodePubKey,
receiver_flo_address: request.globalParams.senderFloId,
data: get_all_withdraws_reqs_for_this_cashier,
requesting_supernode: params.requesting_supernode,
parent_supernode: params.parent_supernode
})
.then(resp => doSend(resp));
})();
break;
case "cashier_confirms_user_cash_deposit":
try {
(async function() {
const cash_deposited_by_user = Number(params.cash_deposited);
if (params.flo_txid===null
|| params.flo_txid.length<1
|| params.deposit_id==null
|| params.deposit_id.length<1
|| typeof cash_deposited_by_user == NaN
|| cash_deposited_by_user < 1
) {
throw new Error(`Error: Incomplete or invalid data received for Cash Deposit Id: ${params.deposit_id}`);
}
try {
// Validate deposit_id
const user_deposit_req = await readDB("cash_deposits", params.deposit_id);
if (typeof user_deposit_req!=="object"
|| user_deposit_req===null) return;
const cash_deposited_by_user = Number(params.cash_deposited);
if (params.flo_txid===null
|| params.flo_txid.length<1
|| params.deposit_id==null
|| params.deposit_id.length<1
|| typeof cash_deposited_by_user == NaN
|| cash_deposited_by_user < 1
) {
throw new Error(`Error: Incomplete or invalid data received for Cash Deposit Id: ${params.deposit_id}`);
}
const parent_supernode = params.parent_supernode;
// Validate Flo txid
const validate_flo_txid = await helper_functions
.ajaxGet(`https://ranchimallflo-testnet.duckdns.org/api/v1.0/getTransactionDetails/${params.flo_txid}`);
if(localbitcoinplusplus.wallets.my_local_flo_address!==params.receiver_flo_address) return;
if(typeof validate_flo_txid !== "object"
|| typeof validate_flo_txid.transactionDetails !== "object"
|| typeof validate_flo_txid.transactionDetails.floData !== "string"
|| validate_flo_txid.transactionDetails.floData.length < 5 // without ':text'
) throw new Error(`Error: Txid ${params.flo_txid} not found in Blockchain.`);
let _readDB = readDB;
let _updateinDB = updateinDB;
let _removeinDB = removeinDB;
let amount_deposited = Number(validate_flo_txid.transactionDetails.floData.match(/\d+/g)[0]);
if(typeof amount_deposited !== "number" || amount_deposited < 1 || amount_deposited===NaN) {
amount_deposited = cash_deposited_by_user;
}
amount_deposited = Number(amount_deposited);
// Update balances datastore
const user_cash_id = `${user_deposit_req.trader_flo_address}_${user_deposit_req.currency}`;
const get_user_balance = await readDB('cash_balances',user_cash_id);
let updateUserBalance;
if(typeof get_user_balance=="object"
&& typeof get_user_balance.cash_balance==="number"
) {
get_user_balance.cash_balance += amount_deposited;
updateUserBalance = await updateinDB("cash_balances", get_user_balance);
} else {
let cash_obj = {
cash_balance: amount_deposited,
currency: user_deposit_req.currency,
id: user_cash_id,
trader_flo_address: user_deposit_req.trader_flo_address,
if (localbitcoinplusplus.wallets.my_local_flo_address!==parent_supernode &&
typeof localbitcoinplusplus.newBackupDatabase.db[parent_supernode] ==
"object"
) {
const foreign_db =
localbitcoinplusplus.newBackupDatabase.db[parent_supernode];
_readDB = foreign_db.backup_readDB.bind(foreign_db);
_updateinDB = foreign_db.backup_updateinDB.bind(foreign_db);
_removeinDB = foreign_db.backup_removeinDB.bind(foreign_db);
}
updateUserBalance = await updateinDB("cash_balances", cash_obj);
// Validate deposit_id
const user_deposit_req = await _readDB("cash_deposits", params.deposit_id);
if (typeof user_deposit_req!=="object"
|| user_deposit_req===null) return;
// Validate Flo txid
const validate_flo_txid = await helper_functions
.ajaxGet(`https://ranchimallflo-testnet.duckdns.org/api/v1.0/getTransactionDetails/${params.flo_txid}`);
if(typeof validate_flo_txid !== "object"
|| typeof validate_flo_txid.transactionDetails !== "object"
|| typeof validate_flo_txid.transactionDetails.floData !== "string"
|| validate_flo_txid.transactionDetails.floData.length < 5 // without ':text'
) throw new Error(`Error: Txid ${params.flo_txid} not found in Blockchain.`);
let amount_deposited = Number(validate_flo_txid.transactionDetails.floData.match(/\d+/g)[0]);
if(typeof amount_deposited !== "number" || amount_deposited < 1 || amount_deposited===NaN) {
amount_deposited = cash_deposited_by_user;
}
amount_deposited = Number(amount_deposited);
// Update balances datastore
const user_cash_id = `${user_deposit_req.trader_flo_address}_${user_deposit_req.currency}`;
const get_user_balance = await _readDB('cash_balances',user_cash_id);
let updateUserBalance;
if(typeof get_user_balance=="object"
&& typeof get_user_balance.cash_balance==="number"
) {
get_user_balance.cash_balance += amount_deposited;
updateUserBalance = await _updateinDB("cash_balances", get_user_balance);
} else {
let cash_obj = {
cash_balance: amount_deposited,
currency: user_deposit_req.currency,
id: user_cash_id,
trader_flo_address: user_deposit_req.trader_flo_address,
}
updateUserBalance = await _updateinDB("cash_balances", cash_obj);
}
// Delete data from deposits
if (typeof updateUserBalance!=="object" && updateUserBalance==null)
throw new Error(`Error: Failed to update balance of User Cash Id: ${user_cash_id}.`);
_removeinDB("cash_deposits", params.deposit_id);
// Broadcast deposit and cash balances datastore data to backups
let update_cash_balance_obj = {
depositor_cash_data: updateUserBalance,
deposit_req_id: params.deposit_id
}
let update_cash_balance_str = JSON.stringify(update_cash_balance_obj);
let update_cash_balance_hash = Crypto.SHA256(update_cash_balance_str);
let update_cash_balance_sign =
RM_WALLET
.sign(update_cash_balance_hash,
localbitcoinplusplus.wallets.MY_SUPERNODE_PRIVATE_KEY
);
update_cash_balance_obj.publicKey =
localbitcoinplusplus.wallets.my_local_flo_public_key;
update_cash_balance_obj.sign = update_cash_balance_sign;
update_cash_balance_obj.hash = update_cash_balance_hash;
update_cash_balance_obj.trader_flo_address
= user_deposit_req.trader_flo_address;
RM_RPC
.send_rpc
.call(this,
"update_all_deposit_success",
update_cash_balance_obj)
.then(update_cash_balance_req=>
doSend(update_cash_balance_req));
} catch (error) {
throw new Error(error);
}
// Delete data from deposits
if (typeof updateUserBalance!=="object" && updateUserBalance==null)
throw new Error(`Error: Failed to update balance of User Cash Id: ${user_cash_id}.`);
removeinDB("cash_deposits", params.deposit_id);
// Broadcast deposit and cash balances datastore data to backups
let update_cash_balance_obj = {
depositor_cash_data: updateUserBalance,
deposit_req_id: params.deposit_id
}
let update_cash_balance_str = JSON.stringify(update_cash_balance_obj);
let update_cash_balance_hash = Crypto.SHA256(update_cash_balance_str);
let update_cash_balance_sign =
RM_WALLET
.sign(update_cash_balance_hash,
localbitcoinplusplus.wallets.MY_SUPERNODE_PRIVATE_KEY
);
update_cash_balance_obj.publicKey =
localbitcoinplusplus.wallets.my_local_flo_public_key;
update_cash_balance_obj.sign = update_cash_balance_sign;
update_cash_balance_obj.hash = update_cash_balance_hash;
update_cash_balance_obj.trader_flo_address
= user_deposit_req.trader_flo_address;
RM_RPC
.send_rpc
.call(this,
"update_all_deposit_success",
update_cash_balance_obj)
.then(update_cash_balance_req=>
doSend(update_cash_balance_req));
} catch (error) {
throw new Error(error);
}
})()
break;
case "cashier_confirms_user_cash_withdraw":
try {
if (typeof params.withdraw_id!=="string"
|| params.withdraw_id.length<1
|| typeof params.upi_txid!=="string"
|| params.upi_txid.length<1)
throw new Error(`Error: Invalid/Incomplete message sent by cashier.`);
// Fetch and update withdraw request from db
// #todo
// Note: Remove withdraw requests older than 1 week using
// window.requestIdleCallback function
const withdraw_req = await readDB('withdraw_cash', params.withdraw_id);
if(typeof withdraw_req!=="object"
|| withdraw_req.id.length<=0) return;
withdraw_req.upi_txid = params.upi_txid;
withdraw_req.status = 2; // Cashier sent money to Withdrawer
const updated_withdraw_req = await updateinDB('withdraw_cash', withdraw_req, withdraw_req.id);
(async function() {
try {
if (typeof params.withdraw_id!=="string"
|| params.withdraw_id.length<1
|| typeof params.upi_txid!=="string"
|| params.upi_txid.length<1)
throw new Error(`Error: Invalid/Incomplete message sent by cashier.`);
// Fetch and update withdraw request from db
// #todo
// Note: Remove withdraw requests older than 1 week using
// window.requestIdleCallback function
if(localbitcoinplusplus.wallets.my_local_flo_address!==params.receiver_flo_address) return;
let _readDB = readDB;
let _updateinDB = updateinDB;
let _removeinDB = removeinDB;
const parent_supernode = params.parent_supernode;
if (localbitcoinplusplus.wallets.my_local_flo_address!==parent_supernode &&
typeof localbitcoinplusplus.newBackupDatabase.db[parent_supernode] ==
"object"
) {
const foreign_db =
localbitcoinplusplus.newBackupDatabase.db[parent_supernode];
_readDB = foreign_db.backup_readDB.bind(foreign_db);
_updateinDB = foreign_db.backup_updateinDB.bind(foreign_db);
_removeinDB = foreign_db.backup_removeinDB.bind(foreign_db);
}
const withdraw_req = await _readDB('withdraw_cash', params.withdraw_id);
if(typeof withdraw_req!=="object"
|| withdraw_req.id.length<=0) return;
withdraw_req.upi_txid = params.upi_txid;
withdraw_req.status = 2; // Cashier sent money to Withdrawer
const updated_withdraw_req = await _updateinDB('withdraw_cash', withdraw_req, withdraw_req.id);
if(typeof updated_withdraw_req.id !=="string")
throw new Error(`Error: Failed to update "cashier_confirms_user_cash_withdraw" data.`);
// Broadcast to backups
RM_RPC
.send_rpc
.call(this,
"record_upi_tx_of_successfull_withdraw",
updated_withdraw_req)
.then(resp=> doSend(resp));
} catch (error) {
throw new Error(error);
}
})()
if(typeof updated_withdraw_req.id !=="string")
throw new Error(`Error: Failed to update "cashier_confirms_user_cash_withdraw" data.`);
// Broadcast to backups
RM_RPC
.send_rpc
.call(this,
"record_upi_tx_of_successfull_withdraw",
updated_withdraw_req)
.then(resp=> doSend(resp));
} catch (error) {
throw new Error(error);
}
break;
default:
@ -29550,7 +29626,7 @@
}
let asset_type = assetTypeInput.value;
let tradeAmount = Number(tradeAmountSelect.value);
let fiatCurrency = currencySelect.value;
let fiatCurrency = assetTypeInput.value;
if (
typeof userFLOaddress == undefined ||
userFLOaddress.trim().length < 1