From f0a9c91bebcb3ee22b291e134c0a83fe8a6cb627 Mon Sep 17 00:00:00 2001 From: Abhishek Sinha Date: Sat, 31 Aug 2019 11:20:52 +0530 Subject: [PATCH 01/12] added bootstrap code for cash_payments_handler.html --- supernode/cash_payments_handler.html | 148 +++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 supernode/cash_payments_handler.html diff --git a/supernode/cash_payments_handler.html b/supernode/cash_payments_handler.html new file mode 100644 index 0000000..913fc85 --- /dev/null +++ b/supernode/cash_payments_handler.html @@ -0,0 +1,148 @@ + + + + + + + Handling Cash Payments For Localbitcoinplusplus + + + + + + + \ No newline at end of file From fa1f4bae61dda0e601c45a632ad90107a2101eb0 Mon Sep 17 00:00:00 2001 From: Abhishek Sinha Date: Sat, 31 Aug 2019 12:12:32 +0530 Subject: [PATCH 02/12] added bootstrap code for cash_payments_handler.html --- supernode/cash_payments_handler.html | 11 +++++++++++ supernode/index.html | 13 +++++++++++++ 2 files changed, 24 insertions(+) diff --git a/supernode/cash_payments_handler.html b/supernode/cash_payments_handler.html index 913fc85..1e7aad5 100644 --- a/supernode/cash_payments_handler.html +++ b/supernode/cash_payments_handler.html @@ -95,6 +95,17 @@ unique: false }); } + if (!db.objectStoreNames.contains('supernodesList')) { + var objectStore = db.createObjectStore("supernodesList", { + keyPath: 'id' + }); + objectStore.createIndex('trader_flo_address', 'trader_flo_address', { + unique: true + }); + objectStore.createIndex('ip', 'ip', { + unique: false + }); + } } diff --git a/supernode/index.html b/supernode/index.html index 05af928..fa9f54c 100644 --- a/supernode/index.html +++ b/supernode/index.html @@ -10975,6 +10975,7 @@ reactor.registerEvent('switchToBackupWSForSuperNodesOperations'); reactor.registerEvent('user_flo_keys_active'); reactor.registerEvent('remove_extra_backup_connections'); + reactor.registerEvent('request_to_modify_user_balance_on_successfull_fiat_deposit'); reactor.addEventListener('fireNodeWelcomeBackEvent', function(evt) { let getFLOId = bitjs.FLO_TEST.pubkey2address(evt.flo_public_key); @@ -11475,6 +11476,18 @@ } }); + /*This function is used to verify a tx denoting token transfer by trusted guy to the supernode + and to increase balance of the respective user node.*/ + reactor.addEventListener('request_to_modify_user_balance_on_successfull_fiat_deposit', + function(token_transfer_resp) { + /* + token_transfer_resp = { + tx: ec289d40069bb4db8b633133560269004a35f834c4a146560887ac87f7789d35, + user_action: 'deposit' + } + */ + }); + From bf5b8d0cdcee8e6d9b92a8ccbc79261037db8bc0 Mon Sep 17 00:00:00 2001 From: Abhishek Sinha Date: Sat, 31 Aug 2019 12:21:09 +0530 Subject: [PATCH 03/12] added bootstrap code for cash_payments_handler.html --- supernode/cash_payments_handler.html | 168 +++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) diff --git a/supernode/cash_payments_handler.html b/supernode/cash_payments_handler.html index 1e7aad5..fb251a1 100644 --- a/supernode/cash_payments_handler.html +++ b/supernode/cash_payments_handler.html @@ -109,6 +109,171 @@ } + function readDB(tablename, id) { + return new Promise((resolve, reject) => { + var transaction = db.transaction([tablename]); + var objectStore = transaction.objectStore(tablename); + var request = objectStore.get(id); + + request.onerror = function (event) { + reject("Unable to retrieve data from database!"); + }; + + request.onsuccess = function (event) { + if (request.result) { + resolve(request.result); + } else { + resolve(); + } + }; + }); + } + + function readDBbyIndex(tablename, index, indexValue) { + return new Promise((resolve, reject) => { + var transaction = db.transaction([tablename]); + var objectStore = transaction.objectStore(tablename); + let response = []; + objectStore.openCursor().onerror = function (event) { + console.error("Error fetching data"); + reject(event); + }; + objectStore.openCursor().onsuccess = function (event) { + let cursor = event.target.result; + if (cursor) { + if (cursor.value[index] == indexValue) { + response.push(cursor.value); + } + cursor.continue(); + } else { + resolve(response); + } + }; + }); + } + + function readAllDB(tablename, limit=0) { + return new Promise((resolve, reject) => { + let response = []; + var objectStore = db.transaction(tablename).objectStore(tablename); + objectStore.openCursor().onsuccess = function (event) { + let cursor = event.target.result; + if (cursor) { + response.push(cursor.value); + cursor.continue(); + } else { + resolve(response); + } + }; + }); + } + + async function addDB(tablename, dbObject) { + try { + if(typeof dbObject.vectorClock == "undefined") dbObject.vectorClock = 0; + dbObject.timestamp = + new Date(); + let request = db.transaction([tablename], "readwrite") + let store = request.objectStore(tablename) + await store.add(dbObject); + await request.complete; + console.info("Data added in " + tablename); + return dbObject; + } catch (error) { + return new Error(error); + } + } + + async function updateinDB(tablename, Obj, key, updateByVectorClock=false, increaseVectorClock=true) { + // updateByVectorClock==true will not return Obj back. + // Return value will be undefined + try { + if(typeof Obj.vectorClock == "undefined") { + Obj.vectorClock = 0; + } else if(increaseVectorClock === false) { + // leave the vector clock field unchanged + } else { + Obj.vectorClock += 1; + } + if (typeof Obj.timestamp !== "number") { + Obj.timestamp = + new Date(); + } + var request = db.transaction([tablename], "readwrite") + let store = request.objectStore(tablename) + if (updateByVectorClock===true) { + if (typeof key=="undefined") { + key = Obj[store.keyPath]; + } + let objectStoreRequest = store.get(key); + objectStoreRequest.onsuccess = + async function(event) { + var myRecord = objectStoreRequest.result; + if(typeof myRecord !=="object") { + Obj.vectorClock = 1; + await store.put(Obj); + await request.complete; + } else if (myRecord.vectorClock+1 < Obj.vectorClock) { + await store.put(Obj); + await request.complete; + } + } + + } else { + await store.put(Obj); + await request.complete; + } + return Obj; + + } catch (error) { + return new Error(error); + } + } + + async function removeinDB(tablename, id) { + try { + var request = db.transaction([tablename], "readwrite") + let store = request.objectStore(tablename) + await store.delete(id); + await request.complete; + return id; + } catch (error) { + return new Error(error); + } + } + + function removeByIndex(tablename, indexName, indexValue) { + return new Promise((resolve, reject) => { + var request = db.transaction([tablename], "readwrite") + .objectStore(tablename); + var index = request.index(indexName); + var request = index.openCursor(IDBKeyRange.only(indexValue)); + request.onsuccess = function () { + var cursor = request.result; + if (cursor) { + cursor.delete(); + cursor.continue(); + } else { + resolve(true); + } + }; + request.onerror = function (e) { + reject(e); + } + }) + } + + async function removeAllinDB(tablename) { + try { + var request = db.transaction([tablename], "readwrite") + var objectStore = request.objectStore(tablename); + var objectStoreRequest = await objectStore.clear(); + await request.complete; + console.info("All the data entry has been removed from your database " + tablename); + return tablename; + } catch (error) { + return new Error(error); + } + } + /* CODE_JUNCTION: Websockets */ function startWebSocket(wsUri) { @@ -153,6 +318,9 @@ } })(); + + + From 34d8c8d2963515aade8848fab22f78ae0ec02525 Mon Sep 17 00:00:00 2001 From: Abhishek Sinha Date: Sun, 1 Sep 2019 17:09:21 +0530 Subject: [PATCH 04/12] added localbitcoinplusplus libs in cash_payments_handler.html --- supernode/cash_payments_handler.html | 10101 ++++++++++++++++++++++++- supernode/index.html | 952 +-- 2 files changed, 10581 insertions(+), 472 deletions(-) diff --git a/supernode/cash_payments_handler.html b/supernode/cash_payments_handler.html index fb251a1..1cd5d2d 100644 --- a/supernode/cash_payments_handler.html +++ b/supernode/cash_payments_handler.html @@ -5,13 +5,9895 @@ Handling Cash Payments For Localbitcoinplusplus + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/supernode/index.html b/supernode/index.html index fa9f54c..5bbf803 100644 --- a/supernode/index.html +++ b/supernode/index.html @@ -484,13 +484,24 @@
- DEPOSIT WITHDRAW ASSET + DEPOSIT WITHDRAW CRYPTO
+ +
+
+
+ DEPOSIT WITHDRAW CASH +
+ +
+
+
+
@@ -10081,6 +10092,8 @@ 03F7493F11B8E44B9798CD434D20FBE7FA34B9779D144984889D11A17C56A18742,039B4AA00DBFC0A6631DE6DA83526611A0E6B857D3579DF840BBDEAE8B6898E3B6, 03C8E3836C9A77E2AF03D4265D034BA85732738919708EAF6A16382195AE796EDF,0349B08AA1ABDCFFB6D78CD7C949665AD2FF065EA02B3C6C47A5E9592C9A1C6BCB #!#externalFiles={"d3js":"58f54395efa8346e8e94d12609770f66b916897e7f4e05f6c98780cffa5c70a3"}, + #!#cashiers={"0315C3A20FE7096CC2E0F81A80D5F1A687B8F9EFA65242A0B0881E1BA3EE7D7D53":"johnDoe@upi", + "03F7493F11B8E44B9798CD434D20FBE7FA34B9779D144984889D11A17C56A18742":"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"}, @@ -11035,104 +11048,105 @@ readDBbyIndex('ipTable', 'temporary_ip', temp_ip).then(async op =>{ if(op.length < 1 || typeof op[0].temporary_ip !== 'string') return; let getFLOId = bitjs.FLO_TEST.pubkey2address(op[0].flo_public_key); + let msg= ''; - // Update Node availability status to true/false - const cs = await readDBbyIndex('myClosestSupernodes', 'trader_flo_address', getFLOId); - if(cs.length<1) { - console.error(`WARNING: Failed to update Supernodes ${getFLOId} status.`); - return; + // Update Node availability status to true/false + const cs = await readDBbyIndex('myClosestSupernodes', 'trader_flo_address', getFLOId); + if(cs.length<1) { + console.error(`WARNING: Failed to update Supernodes ${getFLOId} status.`); + return; + } + const switchMyWS = new backupSupernodesWebSocketObject(); + await switchMyWS.updateSupernodeAvailabilityStatus(`ws://${cs[0].ip}:${cs[0].port}`, false); + + // Wait for 10 seconds if the 'dead' supernode only refreshed the page + await localbitcoinplusplus.actions.delay(10000); + + // Get the current status now + const getStatusOfDeadSuAgain = await readDBbyIndex('myClosestSupernodes', 'trader_flo_address', getFLOId); + + // If its still dead find out if you are the next eligible backup supernode + // If true, take charge of dead supernode's operations + if (getStatusOfDeadSuAgain[0].is_live==false) { + + if(localbitcoinplusplus.master_configurations.supernodesPubKeys + .includes(op[0].flo_public_key)) { + + // Kill the connection manually to ensure connection is really closed. + /* Source of inspiration:- + https://github.com/dart-lang/sdk/issues/25536 + https://bugs.chromium.org/p/chromium/issues/detail?id=76358 + */ + if (localbitcoinplusplus.backupWS[getFLOId].ws_connection.readyState==1) { + localbitcoinplusplus.backupWS[getFLOId].ws_connection.close(); } - const switchMyWS = new backupSupernodesWebSocketObject(); - await switchMyWS.updateSupernodeAvailabilityStatus(`ws://${cs[0].ip}:${cs[0].port}`, false); - // Wait for 10 seconds if the 'dead' supernode only refreshed the page - await localbitcoinplusplus.actions.delay(10000); + // Stop yourself from serving it unless proper DB sync + localbitcoinplusplus.services[`can_serve_${getFLOId}`] = false; + + // Initiate connections with next live supernodes + reactor.dispatchEvent('resolve_backup_ws_connections'); + + const mcs = await readAllDB('myClosestSupernodes'); + const myClosestSupList = mcs.filter((k,i)=>i<=localbitcoinplusplus.master_configurations.MaxBackups); + const index = mcs.findIndex(f=>f.trader_flo_address==getFLOId); + tail = mcs.splice(0, index); + const newClosestSupernodeMasterList = mcs.concat(tail).filter((k,i)=>i<=localbitcoinplusplus.master_configurations.MaxBackups); + + const RM_RPC = new localbitcoinplusplus.rpc; + + for(i=0; i<=newClosestSupernodeMasterList.length; i++) { + + if(newClosestSupernodeMasterList[i].is_live==true + && newClosestSupernodeMasterList[i].trader_flo_address !== + localbitcoinplusplus.wallets.my_local_flo_address) break; - // Get the current status now - const getStatusOfDeadSuAgain = await readDBbyIndex('myClosestSupernodes', 'trader_flo_address', getFLOId); - - // If its still dead find out if you are the next eligible backup supernode - // If true, take charge of dead supernode's operations - if (getStatusOfDeadSuAgain[0].is_live==false) { - - if(localbitcoinplusplus.master_configurations.supernodesPubKeys - .includes(op[0].flo_public_key)) { - - // Kill the connection manually to ensure connection is really closed. - /* Source of inspiration:- - https://github.com/dart-lang/sdk/issues/25536 - https://bugs.chromium.org/p/chromium/issues/detail?id=76358 - */ - if (localbitcoinplusplus.backupWS[getFLOId].ws_connection.readyState==1) { - localbitcoinplusplus.backupWS[getFLOId].ws_connection.close(); - } + if(newClosestSupernodeMasterList[i].trader_flo_address== + localbitcoinplusplus.wallets.my_local_flo_address) { - // Stop yourself from serving it unless proper DB sync - localbitcoinplusplus.services[`can_serve_${getFLOId}`] = false; + // First check if you yourself have the right data to serve + // If not, either get the data or don't serve the users of + // that dead supernode. - // Initiate connections with next live supernodes - reactor.dispatchEvent('resolve_backup_ws_connections'); - - const mcs = await readAllDB('myClosestSupernodes'); - const myClosestSupList = mcs.filter((k,i)=>i<=localbitcoinplusplus.master_configurations.MaxBackups); - const index = mcs.findIndex(f=>f.trader_flo_address==getFLOId); - tail = mcs.splice(0, index); - const newClosestSupernodeMasterList = mcs.concat(tail).filter((k,i)=>i<=localbitcoinplusplus.master_configurations.MaxBackups); + const tableArray = ["deposit", "withdraw_cash", "withdraw_btc", "cash_balances", + "crypto_balances", "buyOrders", "sellOrders", "system_btc_reserves_private_keys"]; - const RM_RPC = new localbitcoinplusplus.rpc; + const su_db_data = await localbitcoinplusplus.actions.get_sharable_db_data(tableArray, getFLOId); - for(i=0; i<=newClosestSupernodeMasterList.length; i++) { + const dbHashData = await localbitcoinplusplus.actions.getDBTablesLatestHashAndTimestamp(getFLOId, su_db_data); - if(newClosestSupernodeMasterList[i].is_live==true - && newClosestSupernodeMasterList[i].trader_flo_address !== - localbitcoinplusplus.wallets.my_local_flo_address) break; - - if(newClosestSupernodeMasterList[i].trader_flo_address== - localbitcoinplusplus.wallets.my_local_flo_address) { + // Now you have db tables timestamp and tables hashes. Send it to other supernodes to check + // if you have the latest data. If you don't have the latest data, someone + // will send you the latest data which you can verify before updating. - // First check if you yourself have the right data to serve - // If not, either get the data or don't serve the users of - // that dead supernode. + RM_RPC + .send_rpc + .call(this, "do_you_have_latest_data_for_this_supernode", dbHashData) + .then(server_sync_response=>doSend(server_sync_response)); + + // Send dead supernode's data to all your backup supernodes + // which are not dead supernode's backup supernodes to sync + // data from you - const tableArray = ["deposit", "withdraw_cash", "withdraw_btc", "cash_balances", - "crypto_balances", "buyOrders", "sellOrders", "system_btc_reserves_private_keys"]; + const nonBackUpSusForDeadSu = myClosestSupList + .filter(obj=>newClosestSupernodeMasterList.indexOf(obj) == -1); - const su_db_data = await localbitcoinplusplus.actions.get_sharable_db_data(tableArray, getFLOId); + console.log(nonBackUpSusForDeadSu); - const dbHashData = await localbitcoinplusplus.actions.getDBTablesLatestHashAndTimestamp(getFLOId, su_db_data); - - // Now you have db tables timestamp and tables hashes. Send it to other supernodes to check - // if you have the latest data. If you don't have the latest data, someone - // will send you the latest data which you can verify before updating. + if (typeof su_db_data == "object") { + nonBackUpSusForDeadSu.map(nbs=>{ + su_db_data.trader_flo_address = getFLOId; + su_db_data.receiver_flo_address = nbs.trader_flo_address; RM_RPC .send_rpc - .call(this, "do_you_have_latest_data_for_this_supernode", dbHashData) - .then(server_sync_response=>doSend(server_sync_response)); - - // Send dead supernode's data to all your backup supernodes - // which are not dead supernode's backup supernodes to sync - // data from you - - const nonBackUpSusForDeadSu = myClosestSupList - .filter(obj=>newClosestSupernodeMasterList.indexOf(obj) == -1); - - console.log(nonBackUpSusForDeadSu); - - if (typeof su_db_data == "object") { - nonBackUpSusForDeadSu.map(nbs=>{ - su_db_data.trader_flo_address = getFLOId; - su_db_data.receiver_flo_address = nbs.trader_flo_address; - - RM_RPC - .send_rpc - .call(this, "sync_backup_supernode_from_backup_supernode_response", su_db_data) - .then(server_sync_response=>doSend(server_sync_response, nbs.trader_flo_address)); - }); - } - break; + .call(this, "sync_backup_supernode_from_backup_supernode_response", su_db_data) + .then(server_sync_response=>doSend(server_sync_response, nbs.trader_flo_address)); + }); } + break; } + } msg = `INFO: Supernode ${getFLOId} left.`; } else { @@ -11447,17 +11461,17 @@ }) .map(backup_id=>{ if (!localbitcoinplusplus.backupWS.hasOwnProperty(backup_id)) { - const backup_conns = localbitcoinplusplus.backupWS[backup_id]; + const backup_conns = localbitcoinplusplus.backupWS[backup_id.trader_flo_address]; if(typeof backup_conns.ws_connection == "object") { let max_conns = 0; if(backup_conns.ws_connection.readyState < 2) { max_conns++; if(max_conns>localbitcoinplusplus.master_configurations.MaxBackups) { - localbitcoinplusplus.backupWS[backup_id].ws_connection.close(); + localbitcoinplusplus.backupWS[backup_id.trader_flo_address].ws_connection.close(); delete localbitcoinplusplus.backupWS[backup_id]; } } else { - localbitcoinplusplus.backupWS[backup_id].ws_connection.close(); + localbitcoinplusplus.backupWS[backup_id.trader_flo_address].ws_connection.close(); delete localbitcoinplusplus.backupWS[backup_id]; } } @@ -12163,35 +12177,6 @@ } } }); - - // Check if user id is in deposit or withdraw. If true prevent him from trading - await readAllDB('withdraw_cash').then(function (res) { - if (typeof res == "object") { - let check_deposit_withdraw_id_array = res.filter(f => f.status === 2) - .map(m => { - if (m.trader_flo_address == respective_trader_id || m.deposit_withdraw_id_array == - respective_trader_id) { - let server_msg = - `Trader id ${respective_trader_id} is not clear for trade currently. - You must finish your previous pending deposit/withdraw action to qualify again to trade.`; - - const RM_RPC = new localbitcoinplusplus.rpc; - RM_RPC - .send_rpc - .call(this, "supernode_message", { - "trader_flo_address": respective_trader_id, - "receiver_flo_address": respective_trader_id, - "server_msg": server_msg - }).then(server_response=>doSend(server_response)); - - showMessage(server_msg); - throw new Error( - "User has not finished previous pending actions." - ); - } - }); - } - }); } catch (error) { throw new Error(error); } @@ -12482,166 +12467,12 @@ } catch (error) { throw new Error(error); } - - // Send the address to the requester - // let deposit_response_object = { - // error: false, - // method: "deposit_asset_request_response", - // msg: `Please send the ${params.product} to ${generate_btc_keys_for_requester.address}.`, - // data: receivedTradeInfo, - // receiver_flo_address: params.trader_flo_address, - // trader_flo_address: params.trader_flo_address, - // }; - - // RM_RPC.send_rpc - // .call(this, - // "deposit_asset_request_response", - // deposit_response_object - // ).then(deposit_request_response=> - // doSend(deposit_request_response)); return true; } }); return false; - } else if (!localbitcoinplusplus.master_configurations - .tradableAsset1.includes(params.product)) { - params.id = helper_functions.unique_id(); - params.status = 1; - // IMPORTANT - If deposit is a fiat make sure product and currency are both same - params.currency = params.product; - let receivedTradeInfo = { ...params }; - - readDB("localbitcoinUser", "00-01").then( - function (su_data) { - if (typeof su_data == "object" && - typeof su_data.myLocalFLOPublicKey == - "string" && - su_data.myLocalFLOPublicKey.length > - 0 && - localbitcoinplusplus.master_configurations - .supernodesPubKeys - .includes(su_data.myLocalFLOPublicKey) - ) { - let receivedTradeInfoHash = - Crypto.SHA256(JSON.stringify( - receivedTradeInfo)); - - receivedTradeInfo["depositDataHash"] = - receivedTradeInfoHash; - receivedTradeInfo["order_validator_sign"] = - RM_WALLET.sign( - receivedTradeInfoHash, - localbitcoinplusplus.wallets - .MY_SUPERNODE_PRIVATE_KEY - ); - receivedTradeInfo[ - "order_validator_public_key" - ] = su_data.myLocalFLOPublicKey; - - // YOU NEED TO DETERMINE A BANK ACCOUNT HERE IF NO ONE IS WITHDRAWING - try { - addDB("deposit", receivedTradeInfo); - readDBbyIndex( - "withdraw_cash", - "status", 1).then( - async function ( - withdrawers_list - ) { - if (typeof withdrawers_list == - "object") { - if ( - withdrawers_list.length > 0) { - withdrawers_list.filter( - wd => wd.currency == - params.currency).map( - async function (withdrawer) { - if ( - withdrawer.withdraw_amount == - params.depositing_amount && - withdrawer.currency == - params.currency - ) { - withdrawer.status = 2; // A depositor has been asked to deposit money - withdrawer.depositor_found_at = + new Date(); - withdrawer.depositor_flo_id = receivedTradeInfo.trader_flo_address; - const withdraw_resp = await updateinDB ("withdraw_cash", withdrawer, withdrawer.trader_flo_address); - - receivedTradeInfo.status = 2; // withdrawer found. Now deposit money to his account - const receivedTradeInfo_resp = await updateinDB( - "deposit", - receivedTradeInfo, - receivedTradeInfo.trader_flo_address - ); - - let withdrawer_bank_account = withdrawer.receivinAddress; - - let deposit_response_object = { - error: false, - method: "deposit_asset_request_response", - msg: `Please send the money to following bank address: "${withdrawer_bank_account}"`, - data: receivedTradeInfo_resp, - withdrawer_data: withdraw_resp, - receiver_flo_address: receivedTradeInfo.trader_flo_address, - trader_flo_address: receivedTradeInfo.trader_flo_address, - }; - - RM_RPC.send_rpc.call( - this, - "deposit_asset_request_response", - deposit_response_object - ).then(deposit_request_response=> - doSend(deposit_request_response)); - return true; - } else { - err_msg = "Deposit request failed: We could not find a withdrawer."; - showMessage(err_msg); - throw new Error(err_msg); - } - } - ); - } else { - //No one is withdrawing so provide your bank details - - receivedTradeInfo.status = 2; // withdrawer found. Now deposit money to his account - const receivedTradeInfo_resp = await updateinDB - ( - "deposit", - receivedTradeInfo, - receivedTradeInfo - .trader_flo_address - ); - - let deposit_response_object = { - error: false, - method: "deposit_asset_request_response", - msg: `Please send the money to following bank address: "System determined bank".`, - data: receivedTradeInfo_resp, - receiver_flo_address: receivedTradeInfo.trader_flo_address, - trader_flo_address: receivedTradeInfo.trader_flo_address, - }; - - RM_RPC - .send_rpc - .call( - this, - "deposit_asset_request_response", - deposit_response_object - ).then(deposit_request_response=> - doSend(deposit_request_response)); - return true; - } - } - }); - } catch (error) { - err_msg = "Deposit request failed: We could not find a withdrawer. Come again later."; - showMessage(err_msg); - throw new Error(err_msg); - } - - } - }); } }); @@ -12652,6 +12483,75 @@ } }); break; + case "deposit_cash_request": + RM_RPC.filter_legit_requests(params.trader_flo_address, async function (is_valid_request) { + + if (is_valid_request !== true) return false; + + // This code will only run for supernodes + if (typeof params.depositing_amount !== "undefined" + && localbitcoinplusplus.master_configurations.tradableAsset2.includes(params.currency) + && typeof localbitcoinplusplus.master_configurations.validTradingAmount !== 'undefined' + && localbitcoinplusplus.master_configurations.validTradingAmount + .includes(parseFloat(params.depositing_amount)) + && typeof params.trader_flo_address == "string" + && params.trader_flo_address.length > 0 + ) { + + params.id = helper_functions.unique_id(); + params.status = 1; + let receivedTradeInfo = { ...params }; + + const su_data = await readDB("localbitcoinUser", "00-01"); + + if (typeof su_data == "object" + && typeof su_data.myLocalFLOPublicKey == "string" + && su_data.myLocalFLOPublicKey.length > 0 + && localbitcoinplusplus.master_configurations + .supernodesPubKeys + .includes(su_data.myLocalFLOPublicKey) + ) { + let receivedTradeInfoHash = + Crypto.SHA256(JSON.stringify(receivedTradeInfo)); + + receivedTradeInfo["depositDataHash"] = receivedTradeInfoHash; + receivedTradeInfo["order_validator_sign"] = + RM_WALLET.sign( + receivedTradeInfoHash, + localbitcoinplusplus.wallets + .MY_SUPERNODE_PRIVATE_KEY + ); + receivedTradeInfo["order_validator_public_key"]= su_data.myLocalFLOPublicKey; + + try { + const receivedTradeInfoResp = await addDB("cash_deposits", receivedTradeInfo); + const cashiersList = JSON.parse(localbitcoinplusplus.master_configurations.cashiers); + const getAPaymentHandler = randomNoRepeats(Object.keys(cashiersList))(); + + let deposit_response_object = { + error: false, + method: "deposit_cash_request_response", + msg: cashiersList[getAPaymentHandler], + data: receivedTradeInfoResp, + receiver_flo_address: receivedTradeInfo.trader_flo_address, + trader_flo_address: receivedTradeInfo.trader_flo_address, + }; + + RM_RPC.send_rpc.call( + this, + "deposit_cash_request_response", + deposit_response_object + ).then(deposit_request_response=> + doSend(deposit_request_response)); + return true; + + } catch(e) { + console.error(e); + } + } + } + }); + break; case "withdraw_request_method": RM_RPC.filter_legit_requests(params.trader_flo_address, async function (is_valid_request) { @@ -13437,34 +13337,6 @@ } }); - // Check if user id is in deposit or withdraw. If true prevent him from trading - await backup_server_db_instance.backup_readAllDB('withdraw_cash').then(function (res) { - if (typeof res == "object") { - let check_deposit_withdraw_id_array = res.filter(f => f.status === 2) - .map(m => { - if (m.trader_flo_address == respective_trader_id || m.deposit_withdraw_id_array == - respective_trader_id) { - let server_msg = - `Trader id ${respective_trader_id} is not clear for trade currently. - You must finish your previous pending deposit/withdraw action to qualify again to trade.`; - - const RM_RPC = new localbitcoinplusplus.rpc; - RM_RPC - .send_rpc - .call(this, "supernode_message", { - "trader_flo_address": respective_trader_id, - "receiver_flo_address": respective_trader_id, - "server_msg": server_msg - }).then(server_response=> - doSend(server_response)); - showMessage(server_msg); - throw new Error( - "User has not finished previous pending actions." - ); - } - }); - } - }); } catch (error) { throw new Error(error); } @@ -13778,167 +13650,12 @@ throw new Error(error); } - // Send the address to the requester - // let deposit_response_object = { - // error: false, - // method: "deposit_asset_request_response", - // msg: `Please send the ${params.product} to ${generate_btc_keys_for_requester.address}.`, - // data: deposit_res, - // receiver_flo_address: params.trader_flo_address, - // trader_flo_address: params.trader_flo_address, - // }; - - // RM_RPC.send_rpc - // .call(this, - // "deposit_asset_request_response", - // deposit_response_object - // ).then(deposit_request_response=> - // doSend(deposit_request_response)); return true; } }); return false; - - } else if (!localbitcoinplusplus.master_configurations - .tradableAsset1.includes(params.product)) { - params.id = helper_functions.unique_id(); - params.status = 1; - // IMPORTANT - If deposit is a fiat make sure product and currency are both same - params.currency = params.product; - let receivedTradeInfo = { ...params }; - - backup_server_db_instance.backup_readDB("localbitcoinUser", "00-01").then( - function (su_data) { - if (typeof su_data == "object" && - typeof su_data.myLocalFLOPublicKey == - "string" && - su_data.myLocalFLOPublicKey.length > - 0 && - localbitcoinplusplus.master_configurations - .supernodesPubKeys - .includes(su_data.myLocalFLOPublicKey) - ) { - let receivedTradeInfoHash = - Crypto.SHA256(JSON.stringify( - receivedTradeInfo)); - - receivedTradeInfo[ - "depositDataHash"] = - receivedTradeInfoHash; - receivedTradeInfo[ - "order_validator_sign"] = - RM_WALLET.sign( - receivedTradeInfoHash, - localbitcoinplusplus.wallets - .MY_SUPERNODE_PRIVATE_KEY - ); - receivedTradeInfo[ - "order_validator_public_key" - ] = su_data.myLocalFLOPublicKey; - - // YOU NEED TO DETERMINE A BANK ACCOUNT HERE IF NO ONE IS WITHDRAWING - try { - backup_server_db_instance.backup_addDB("deposit", - receivedTradeInfo); - backup_server_db_instance.backup_readDBbyIndex( - "withdraw_cash", "status", 1) - .then(async function (withdrawers_list) { - if (typeof withdrawers_list == - "object") { - if ( - withdrawers_list.length > 0) { - withdrawers_list.filter( - wd => wd.currency == - params.currency).map( - async function (withdrawer) { - if ( - withdrawer.withdraw_amount == - params.depositing_amount && - withdrawer.currency == - params.currency - ) { - withdrawer.status = 2; // A depositor has been asked to deposit money - withdrawer.depositor_found_at = + new Date(); - withdrawer.depositor_flo_id = receivedTradeInfo.trader_flo_address; - const withdraw_resp = await backup_server_db_instance - .backup_updateinDB ("withdraw_cash", withdrawer, withdrawer.trader_flo_address); - - receivedTradeInfo.status = 2; // withdrawer found. Now deposit money to his account - const receivedTradeInfo_resp = await backup_server_db_instance.backup_updateinDB( - "deposit", - receivedTradeInfo, - receivedTradeInfo.trader_flo_address - ); - - let withdrawer_bank_account = withdrawer.receivinAddress; - - let deposit_response_object = { - error: false, - method: "deposit_asset_request_response", - msg: `Please send the money to following bank address: "${withdrawer_bank_account}"`, - data: receivedTradeInfo_resp, - withdrawer_data: withdraw_resp, - receiver_flo_address: receivedTradeInfo.trader_flo_address, - trader_flo_address: receivedTradeInfo.trader_flo_address, - }; - - RM_RPC.send_rpc.call( - this, - "deposit_asset_request_response", - deposit_response_object - ).then(deposit_request_response=> - doSend(deposit_request_response)); - return true; - } else { - err_msg = "Deposit request failed: We could not find a withdrawer."; - showMessage(err_msg); - throw new Error(err_msg); - } - } - ); - } else { - //No one is withdrawing so provide your bank details - - receivedTradeInfo.status = 2; // withdrawer found. Now deposit money to his account - const receivedTradeInfo_resp = await updateinDB - ( - "deposit", - receivedTradeInfo, - receivedTradeInfo - .trader_flo_address - ); - - let deposit_response_object = { - error: false, - method: "deposit_asset_request_response", - msg: `Please send the money to following bank address: "System determined bank".`, - data: receivedTradeInfo_resp, - receiver_flo_address: receivedTradeInfo.trader_flo_address, - trader_flo_address: receivedTradeInfo.trader_flo_address, - }; - - RM_RPC - .send_rpc - .call( - this, - "deposit_asset_request_response", - deposit_response_object - ).then(deposit_request_response=> - doSend(deposit_request_response)); - return true; - } - } - }); - } catch (error) { - err_msg = "Deposit request failed: We could not find a withdrawer. Come again later."; - showMessage(err_msg); - throw new Error(err_msg); - } - - } - }); - } + } } else { err_msg = "deposit asset request error"; @@ -13947,6 +13664,75 @@ } }); break; + case "deposit_cash_request": + RM_RPC.filter_legit_requests(params.trader_flo_address, async function (is_valid_request) { + + if (is_valid_request !== true) return false; + + // This code will only run for supernodes + if (typeof params.depositing_amount !== "undefined" + && localbitcoinplusplus.master_configurations.tradableAsset2.includes(params.currency) + && typeof localbitcoinplusplus.master_configurations.validTradingAmount !== 'undefined' + && localbitcoinplusplus.master_configurations.validTradingAmount + .includes(parseFloat(params.depositing_amount)) + && typeof params.trader_flo_address == "string" + && params.trader_flo_address.length > 0 + ) { + + params.id = helper_functions.unique_id(); + params.status = 1; + let receivedTradeInfo = { ...params }; + + const su_data = await readDB("localbitcoinUser", "00-01"); + + if (typeof su_data == "object" + && typeof su_data.myLocalFLOPublicKey == "string" + && su_data.myLocalFLOPublicKey.length > 0 + && localbitcoinplusplus.master_configurations + .supernodesPubKeys + .includes(su_data.myLocalFLOPublicKey) + ) { + let receivedTradeInfoHash = + Crypto.SHA256(JSON.stringify(receivedTradeInfo)); + + receivedTradeInfo["depositDataHash"] = receivedTradeInfoHash; + receivedTradeInfo["order_validator_sign"] = + RM_WALLET.sign( + receivedTradeInfoHash, + localbitcoinplusplus.wallets + .MY_SUPERNODE_PRIVATE_KEY + ); + receivedTradeInfo["order_validator_public_key"]= su_data.myLocalFLOPublicKey; + + try { + const receivedTradeInfoResp = await addDB("cash_deposits", receivedTradeInfo); + const cashiersList = JSON.parse(localbitcoinplusplus.master_configurations.cashiers); + const getAPaymentHandler = randomNoRepeats(Object.keys(cashiersList))(); + + let deposit_response_object = { + error: false, + method: "deposit_cash_request_response", + msg: cashiersList[getAPaymentHandler], + data: receivedTradeInfoResp, + receiver_flo_address: receivedTradeInfo.trader_flo_address, + trader_flo_address: receivedTradeInfo.trader_flo_address, + }; + + RM_RPC.send_rpc.call( + this, + "deposit_cash_request_response", + deposit_response_object + ).then(deposit_request_response=> + doSend(deposit_request_response)); + return true; + + } catch(e) { + console.error(e); + } + } + } + }); + break; case "withdraw_request_method": RM_RPC.filter_legit_backup_requests(params.trader_flo_address, async function (is_valid_request) { @@ -14943,6 +14729,39 @@ "deposit_asset_request", deposit_request_object) .then(deposit_request=>doSend(deposit_request)); }, + depositCash(amount, currency, userFLOaddress) { + if (typeof localbitcoinplusplus.master_configurations.tradableAsset2 == 'undefined' || + (!localbitcoinplusplus.master_configurations.tradableAsset2 + .includes(currency))) { + err_msg = "Invalid asset error"; + showMessage(err_msg); + throw new Error(err_msg); + } else if (parseFloat(amount) <= 0) { + err_msg = "Invalid amount error."; + showMessage(err_msg); + throw new Error(err_msg); + } else if (userFLOaddress.length <= 0) { + err_msg = "User address required."; + showMessage(err_msg); + throw new Error(err_msg); + } else if (!localbitcoinplusplus.master_configurations + .validTradingAmount.includes(amount)) { + err_msg = "Error: Invalid deposit amount."; + showMessage(err_msg); + throw new Error(err_msg); + } + let deposit_request_object = { + trader_flo_address: userFLOaddress, + depositing_amount: amount, + currency: currency, + operation_type: "deposit_cash", + receiver_flo_address:localbitcoinplusplus.MY_SUPERNODE_FLO_ADDRESS, + } + const RM_RPC = new localbitcoinplusplus.rpc; + RM_RPC.send_rpc.call(this, + "deposit_cash_request", deposit_request_object) + .then(deposit_request=>doSend(deposit_request)); + }, withdrawAsset(assetType, amount, receivinAddress, userFLOaddress, currency, callback) { let err_msg; if (typeof localbitcoinplusplus.master_configurations.tradableAsset1 == 'undefined' || @@ -16787,6 +16606,7 @@ case "deposit_asset_request": response_from_sever = RM_RPC.receive_rpc_response.call(this, JSON.stringify(res_obj)); + break; case "deposit_asset_request_response": if (typeof res_obj.params == "object" && typeof res_obj.params[0] == "object" && typeof res_obj .params[0].data == "object") { @@ -16810,6 +16630,31 @@ } } break; + case "deposit_cash_request": + response_from_sever = RM_RPC.receive_rpc_response.call(this, + JSON.stringify(res_obj)); + break; + case "deposit_cash_request_response": + if (typeof res_obj.params == "object" && typeof res_obj.params[0] == "object" && typeof res_obj + .params[0].data == "object") { + let resp = res_obj.params[0]; + if (RM_WALLET + .verify(resp.data.depositDataHash, resp.data.order_validator_sign, resp.data.order_validator_public_key) + ) { + addDB('cash_deposits', resp.data); + + readDB("localbitcoinUser", "00-01").then(function (user) { + if (typeof user == "object" && user.myLocalFLOAddress == resp.data.trader_flo_address) { + let counterTraderAccountAddress = + `Please pay the amount to following UPI ID: + ${resp.msg}`; + showMessage(counterTraderAccountAddress); + modalWindow(counterTraderAccountAddress); + } + }); + } + } + break; case "withdraw_request_method": response_from_sever = RM_RPC.receive_rpc_response.call(this, JSON.stringify(res_obj)); @@ -18163,6 +18008,31 @@ } } break; + case "deposit_cash_request": + response_from_sever = RM_RPC.receive_rpc_response.call(this, + JSON.stringify(res_obj)); + break; + case "deposit_cash_request_response": + if (typeof res_obj.params == "object" && typeof res_obj.params[0] == "object" && typeof res_obj + .params[0].data == "object") { + let resp = res_obj.params[0]; + if (RM_WALLET + .verify(resp.data.depositDataHash, resp.data.order_validator_sign, resp.data.order_validator_public_key) + ) { + addDB('cash_deposits', resp.data); + + readDB("localbitcoinUser", "00-01").then(function (user) { + if (typeof user == "object" && user.myLocalFLOAddress == resp.data.trader_flo_address) { + let counterTraderAccountAddress = + `Please pay the amount to following UPI ID: + ${resp.msg}`; + showMessage(counterTraderAccountAddress); + modalWindow(counterTraderAccountAddress); + } + }); + } + } + break; case "withdraw_request_method": response_from_sever = RM_RPC.backup_receive_rpc_response.call(this, JSON.stringify(res_obj)); // send response to client @@ -20863,7 +20733,7 @@ var db; const DBName = "localbitcoinDB"; - const request = window.indexedDB.open(DBName, 1); + const request = window.indexedDB.open(DBName, 3); request.onerror = function (event) { //https://stackoverflow.com/questions/13972385/invalidstateerror-while-opening-indexeddb-in-firefox @@ -20916,14 +20786,6 @@ unique: false }); } - if (!db.objectStoreNames.contains('withdraw_cash')) { - var objectStore = db.createObjectStore("withdraw_cash", { - keyPath: 'id' - }); - objectStore.createIndex('trader_flo_address', 'trader_flo_address', { - unique: true - }); - } if (!db.objectStoreNames.contains('crypto_balances')) { var objectStore = db.createObjectStore("crypto_balances", { keyPath: 'id', @@ -21047,6 +20909,34 @@ unique: false }); } + if (!db.objectStoreNames.contains('cash_deposits')) { + var objectStore = db.createObjectStore("cash_deposits", { + keyPath: 'id' + }); + objectStore.createIndex('trader_flo_address', 'trader_flo_address', { + unique: false + }); + objectStore.createIndex('currency', 'currency', { + unique: false + }); + objectStore.createIndex('depositing_amount', 'depositing_amount', { + unique: false + }); + } + if (!db.objectStoreNames.contains('cash_withdraws')) { + var objectStore = db.createObjectStore("cash_withdraws", { + keyPath: 'id' + }); + objectStore.createIndex('trader_flo_address', 'trader_flo_address', { + unique: false + }); + objectStore.createIndex('currency', 'currency', { + unique: false + }); + objectStore.createIndex('withdrawing_amount', 'withdrawing_amount', { + unique: false + }); + } } function readDB(tablename, id, filter_deletables=true) { @@ -21308,14 +21198,6 @@ unique: false }); } - if (!this.db.objectStoreNames.contains('withdraw_cash')) { - var objectStore = this.db.createObjectStore("withdraw_cash", { - keyPath: 'id' - }); - objectStore.createIndex('trader_flo_address', 'trader_flo_address', { - unique: true - }); - } if (!this.db.objectStoreNames.contains('crypto_balances')) { var objectStore = this.db.createObjectStore("crypto_balances", { keyPath: 'id', @@ -21421,7 +21303,7 @@ unique: false }); } - if (!db.objectStoreNames.contains('crypto_fiat_rates')) { + if (!this.db.objectStoreNames.contains('crypto_fiat_rates')) { var objectStore = db.createObjectStore("crypto_fiat_rates", { keyPath: 'id' }); @@ -21432,6 +21314,34 @@ unique: false }); } + if (!this.db.objectStoreNames.contains('cash_deposits')) { + var objectStore = this.db.createObjectStore("cash_deposits", { + keyPath: 'id' + }); + objectStore.createIndex('trader_flo_address', 'trader_flo_address', { + unique: false + }); + objectStore.createIndex('currency', 'currency', { + unique: false + }); + objectStore.createIndex('depositing_amount', 'depositing_amount', { + unique: false + }); + } + if (!this.db.objectStoreNames.contains('cash_withdraws')) { + var objectStore = this.db.createObjectStore("cash_withdraws", { + keyPath: 'id' + }); + objectStore.createIndex('trader_flo_address', 'trader_flo_address', { + unique: false + }); + objectStore.createIndex('currency', 'currency', { + unique: false + }); + objectStore.createIndex('withdrawing_amount', 'withdrawing_amount', { + unique: false + }); + } }.bind(this) @@ -22143,7 +22053,7 @@ } - + + + + + + + @@ -9722,7 +9941,7 @@ return false; }, manually_assign_my_private_key: function() { - readDB('localbitcoinUser', '00-01').then(usr=>{ + readDB('paymentsHandlerDetails', '00-01').then(usr=>{ if (typeof usr=="object" && usr.myLocalFLOAddress.length>0) { const RM_WALLET = new localbitcoinplusplus.wallets; const pk_manual = prompt("Please enter your private key: "); @@ -9751,6 +9970,112 @@ Promise.reject(mes); }); }, + reset_flo_keys: () => { + updateinDB('paymentsHandlerDetails', { + id: "00-01", + myLocalFLOAddress: "", + myLocalFLOPublicKey: "", + }, "00-01").then(() => true).catch(e => false); + return Promise.resolve(true); + }, + } + + /* CODE_JUNCTION: RPC */ + + var Rpc = localbitcoinplusplus.rpc = function () { + this.rpc_req_id; + this.valid_job = ["trade_buy", "trade_sell", "sync"]; + } + Rpc.prototype = { + + send_rpc(method, ...params) { + + return new Promise((resolve, reject)=>{ + var request = new JSON_RPC.Request(method, params); + var id = request.id; + this.rpc_req_id = id; + request.globalParams.rpc_protocol = '__FOR__CASHIER__'; + + (async function(request) { + + if (typeof localbitcoinplusplus.wallets.my_local_flo_address == "string") { + request.globalParams.senderFloId = localbitcoinplusplus.wallets.my_local_flo_address; + } + + if (typeof params[0].receiver_flo_address == "string") { + request.globalParams.receiverFloId = params[0].receiver_flo_address; + if (typeof request.globalParams.receiversList == "object") { + if(typeof request.globalParams["receiversList"] !== "object") request.globalParams["receiversList"] = []; + if (!request.globalParams.receiversList.includes(params[0].receiver_flo_address)) { + request.globalParams.receiversList.push(params[0].receiver_flo_address); + } + } + } + + return resolve(request.toString()); + + })(request); + }) + + }, + + filter_legit_requests: function (flo_id=null, callback) { + if (typeof localbitcoinplusplus.wallets.MY_SUPERNODE_PRIVATE_KEY === "string" && + localbitcoinplusplus.wallets.MY_SUPERNODE_PRIVATE_KEY.length > 0 + ) { + const RM_WALLET = new localbitcoinplusplus.wallets; + let user_keys = RM_WALLET.generateFloKeys(localbitcoinplusplus.wallets.MY_SUPERNODE_PRIVATE_KEY); + if (typeof user_keys == "object" && typeof user_keys.pubKeyHex == "string") { + if (localbitcoinplusplus.master_configurations.supernodesPubKeys.includes(user_keys.pubKeyHex)) { + if (typeof flo_id !== null || typeof flo_id !== 'undefined') { + localbitcoinplusplus.kademlia.determineClosestSupernode(flo_id, 4) + .then(my_closest_su=>{ + if (user_keys.address === my_closest_su[0].data.id) { + return callback(true); + } else { + let su_arr = my_closest_su.map(m=>m.data.id); + if(su_arr.includes(flo_id)) { + return callback(true); + } else { + return callback(false); + } + } + }); + } else { + return callback(false); + } + } + } + } else { + return callback(false); + } + }, + + async receive_rpc_response(request) { + var request = JSON.parse(request); + var params = request.params[0]; + var method = request.method; + + if (typeof params == "object" && typeof method == "string") { + + const RM_WALLET = new localbitcoinplusplus.wallets; + const RM_RPC = new localbitcoinplusplus.rpc; + + let respective_trader_id = ''; + if (typeof params.trader_flo_address == "string") respective_trader_id = params.trader_flo_address; + request.response = {}; + let err_msg; + + let recvr_flo_id = params.receiver_flo_address || request.globalParams.receiverFloId; + if (typeof recvr_flo_id == "string" + && recvr_flo_id.length > 0 + && recvr_flo_id !== localbitcoinplusplus.wallets.my_local_flo_address) return; + + console.log(request); + + } + }, + } // kbucket functions @@ -9762,22 +10087,21 @@ k.splice(-4, 4) return Crypto.util.bytesToHex(k) }, - launchSupernodesKBucket: function() { - - localbitcoinplusplus.master_configurations.supernodesPubKeys.map(pubKey=>{ - return new Promise((resolve, reject)=>{ - try { - let flo_id = bitjs.FLO_TEST.pubkey2address(pubKey); - let kname = `SKBucket_${pubKey}`; - const KBucketId = localbitcoinplusplus.kademlia.floIdToKbucketId('FLO_TEST', flo_id); - const kbOptions = { localNodeId: KBucketId } - window[kname] = new BuildKBucket(kbOptions); - resolve(true); - } catch (error) { - reject(error); - } - }) - }) + launchKBucket: function() { + return new Promise((resolve, reject)=>{ + try { + const master_flo_pubKey = localbitcoinplusplus.master_configurations.masterFLOPubKey; + const master_flo_addr = bitjs.FLO_TEST.pubkey2address(master_flo_pubKey); + if(typeof master_flo_addr !== "string") return reject(false); + const SuKBucketId = localbitcoinplusplus.kademlia.floIdToKbucketId('FLO_TEST', master_flo_addr); + const SukbOptions = { localNodeId: SuKBucketId } + window.supernodeKBucket = new BuildKBucket(SukbOptions); + + resolve(true); + } catch (error) { + reject(error); + } + }); }, addContact: function (id, data, KB=KBucket) { const contact = { @@ -9843,7 +10167,10 @@ if (typeof supernodeSeeds !== "object") reject("Failed to get supernode seeds."); let supernodeSeedsObj = JSON.parse(supernodeSeeds); nearestSupernodeAddresslist = Object.values(supernodeSeedsObj); - nearestSupernodeAddresslist.map(m=>updateinDB('supernodesList', m)); + nearestSupernodeAddresslist.map((m, i)=>{ + m.id = i+1; + updateinDB('supernodesList', m).catch(e=>{throw new Error(e)}); + }); } resolve(nearestSupernodeAddresslist); }); @@ -9892,7 +10219,6 @@ }) }, - } /* CODE_JUNCTION: Indexed DB */ @@ -9938,6 +10264,8 @@ unique: true }); objectStore.put({ + id: "00-01", + myLocalFLOAddress: "", myLocalFLOPublicKey: "", upiID: "", last_tx_time: "", @@ -9982,7 +10310,7 @@ var objectStore = db.createObjectStore("supernodesList", { keyPath: 'id' }); - objectStore.createIndex('trader_flo_address', 'trader_flo_address', { + objectStore.createIndex('kbucketId', 'kbucketId', { unique: true }); objectStore.createIndex('ip', 'ip', { @@ -10179,6 +10507,14 @@ } 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}.`) } @@ -10192,14 +10528,147 @@ } } - function onMessage(evt) { - console.log(evt); + async function onMessage(evt) { + var response = evt.data || evt; + console.log('RESPONSE: ' + response); + + let is_message_for_cashier = response.search('__FOR__CASHIER__'); + if (!is_message_for_cashier) return; + + var res_pos = response.indexOf('{'); + if (res_pos >= 0) { + var res = response.substr(res_pos); + 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 (typeof res_obj.globalParams.receiverFloId=="string" + && res_obj.globalParams.receiverFloId !== + localbitcoinplusplus.wallets.my_local_flo_address) 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 (typeof res_obj.method !== "undefined") { + let response_from_sever; + + const RM_WALLET = new localbitcoinplusplus.wallets; + const RM_RPC = new localbitcoinplusplus.rpc; + + switch (res_obj.method) { + case "": + + break; + + default: + break; + } + } + + } catch(e) { + throw new Error(e); + } + } } function onError(evt) { console.error(`ERROR: Websocket Connection to ${evt.srcElement.url} returned error.`); } + function doSend(message="") { + + let finalMessage = message; + + const msgObj = JSON.parse(message); + + const RM_WALLET = new localbitcoinplusplus.wallets; + + message = JSON.stringify(msgObj); + const message256hash = Crypto.SHA256(message); + + if(typeof localbitcoinplusplus.wallets.MY_SUPERNODE_PRIVATE_KEY !== "string") + throw new Error(`WARNING: Private key could not be found.`); + + const nodeSignedMessage = RM_WALLET.sign(message256hash, localbitcoinplusplus.wallets.MY_SUPERNODE_PRIVATE_KEY); + + msgObj.nodeMessage256hash = message256hash; + msgObj.nodeSignedMessage = nodeSignedMessage; + msgObj.nodePubKey = localbitcoinplusplus.wallets.my_local_flo_public_key; + + finalMessage = JSON.stringify(msgObj); + + // The message is for usernodes and all backup supernodes + try { + websocket.send(finalMessage); + + } catch(error) { + throw new Error(error); + } + + console.log("SENT: " + finalMessage); + + } + + function validateIncomingMessage(message) { + return new Promise((resolve, reject)=>{ + if(message.length <1) { + showMessage(`WARNING: The incoming websocket message on was empty.`); + reject(false)}; + const request_array = ['send_back_shamirs_secret_supernode_pvtkey', + 'retrieve_shamirs_secret_supernode_pvtkey', + 'store_shamirs_secret_pvtkey_shares']; + + try { + const msgObj = JSON.parse(message); + + if (request_array.includes(msgObj.method)) return resolve(true); + + const getFloId = bitjs.FLO_TEST.pubkey2address(msgObj.nodePubKey); + + // Check if the public key belongs to real sender + if (getFloId !== msgObj.globalParams.senderFloId) { + showMessage(`Sender FLO address did not match signer FLO address.`); + reject(false) + } + const initialMsgObj = { + jsonrpc:msgObj.jsonrpc, + id:msgObj.id, + method:msgObj.method, + params:msgObj.params, + 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)) { + resolve(true); + } else { + showMessage(`WARNING: Incoming Websocket message verification failed.`) + reject(false); + } + + } catch (error) { + reject(error); + } + }) + } + + /*CODE_JUNCTION: Random functions*/ // log event in the console @@ -10211,11 +10680,12 @@ function showMessage(msg='', t=10000) { if (msg.length>0) LogEvent(msg); - displayMessages(); - setTimeout(function(){ - closeMessage(); - clearTimeout(); - }, t); + console.info(msg); + //displayMessages(); + // setTimeout(function(){ + // closeMessage(); + // clearTimeout(); + // }, t); } function displayMessages() { @@ -10273,8 +10743,10 @@ try { var rm_configs = localbitcoinplusplus.actions.fetch_configs(async function (...fetch_configs_res) { localbitcoinplusplus.is_ui_loaded = false; - showMessage(`Connecting to Supernode server. Please wait...`); + window.bitjs = []; // Launch bitjs + localbitcoinplusplus.master_configurations.tradableAsset1.map(asset => bitjslib(asset)); kickInit(); + loadResetFloBtnUi(); }); } catch (error) { showMessage(`WARNING: System failed to collect configurations. @@ -10291,22 +10763,113 @@ console.info('Load pending withdrawals'); } + // Connect to Supernode function loadSupernodesConnectUi() { - //wsUri = await localbitcoinplusplus.kademlia.getSupernodeSeed(); + const supernodeSeeds = localbitcoinplusplus.master_configurations.supernodeSeeds; + if (typeof supernodeSeeds !== "object") return showMessage("Failed to get supernode list."); + let supernodeSeedsObj = JSON.parse(supernodeSeeds); + let supernodeSeedsArray = Object.values(supernodeSeedsObj); - // Connect with primary supernodes - //await startWebSocket(`ws://${wsUri[0].ip}:${wsUri[0].port}`); + let supernode_seedsInput = ``; + supernode_seedsInput += `
+ +
+ +
+
`; + + 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; + } + }); } - // localbitcoinUser Database + // Ask Connected Supernode to give pending deposits/withdrawals + function AskSupernodeForLatestDepositsAndWithdrawalsData() { + + const fetch_deposits_btn = document.getElementById('fetch_deposits'); + fetch_deposits_btn.addEventListener("click", function(evt) { + + console.log(localbitcoinplusplus); + console.log(localbitcoinplusplus.MY_UPI_ID); + console.log(localbitcoinplusplus.CONNECTED_SUPERNODE_FLO_ADDRESS); + + if (localbitcoinplusplus.MY_UPI_ID.length < 1 + || localbitcoinplusplus.CONNECTED_SUPERNODE_FLO_ADDRESS.length < 1) { + showMessage(`WARNING: Your UPI Id or connected Supernode is not set.`); + return false; + } + + const RM_RPC = new localbitcoinplusplus.rpc; + RM_RPC + .send_rpc + .call(this, "give_cashier_latest_pending_cash_deposits", { + 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)); + + }); + } + + // Reset Flo Id + function loadResetFloBtnUi() { + // RESET KEYS + const reset_flo_keys_div = document.getElementById('flo_keys_div'); + const reset_flo_keys_btn = document.createElement('button'); + reset_flo_keys_btn.className += ` button bg-purple mg-5 `; + const reset_flo_keys_btn_text = document.createTextNode(`Reset FLO Keys`); + reset_flo_keys_btn.appendChild(reset_flo_keys_btn_text); + reset_flo_keys_div.appendChild(reset_flo_keys_btn); + + reset_flo_keys_btn.onclick = function () { + if (confirm( + `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; + RM_WALLET.reset_flo_keys().then(reset_success => { + if (reset_success) { + showMessage("INFO: FLO keys have been reset successfully."); + } else { + showMessage(`INFO: Failed to reset FLO keys.`); + } + }); + } + } + } + + // paymentsHandlerDetails Database const dataBaseUIOperations = async function () { localbitcoinplusplus.is_ui_loaded = true; const RM_WALLET = new localbitcoinplusplus.wallets; - const RM_TRADE = new localbitcoinplusplus.trade; const RM_RPC = new localbitcoinplusplus.rpc; try { @@ -10316,10 +10879,7 @@ idbData.myLocalFLOAddress; const MY_LOCAL_FLO_PUBLIC_KEY = localbitcoinplusplus.wallets.my_local_flo_public_key = idbData.myLocalFLOPublicKey; - - // Build Supernodes KBuckets - launchSupernodesKBuckects = await localbitcoinplusplus.kademlia.launchSupernodesKBucket(); - + // Load Supernodes Connection Select UI loadSupernodesConnectUi(); @@ -10329,14 +10889,17 @@ // Load Pending Withdrawals UI loadPendingWithdrawals(); + // Fetch Deposits + AskSupernodeForLatestDepositsAndWithdrawalsData(); + showMessage(`Connection successfull. Welocome to Local Bitcoin Plus Plus Cash Handling platform.`); }); } catch (e) { - showMessage("ERROR: Failed to initialise the localbitcoinUser database. You are unable to trade at the moment."); + showMessage("ERROR: Failed to initialise the paymentsHandlerDetails database. You are unable to trade at the moment."); throw new Error( - "ERROR: Failed to initialise the localbitcoinUser database. You are unable to trade at the moment." + "ERROR: Failed to initialise the paymentsHandlerDetails database. You are unable to trade at the moment." ); } @@ -10348,27 +10911,54 @@ return new Promise(resolve => { readDB("paymentsHandlerDetails", "00-01").then(async function (idbData) { - + let localbitcoinplusplusObj = { + id: "00-01", + myLocalFLOAddress: "", + myLocalFLOPublicKey: "", + upiID: "", + last_tx_time: "", + last_active_time: + new Date() + } if (typeof idbData.myLocalFLOPublicKey == "undefined" || idbData.myLocalFLOPublicKey .trim() == '') { let user_pvt_key = prompt( "Please Enter a valid FLO private key if you have any. Else leave blank." ); + const user_upi = prompt("Please Enter a valid UPI id!"); if (user_pvt_key.trim() == "" || user_pvt_key.length < 1) user_pvt_key = null; + if (user_upi.trim() == "" || user_upi.length < 1) return showMessage(`Warning: You must provide a valid UPI id.`); let newKeys = RM_WALLET.generateFloKeys(user_pvt_key); if (typeof newKeys == 'object' && newKeys.privateKeyWIF.length > 0 && newKeys.address.length > 0) { - localbitcoinplusplusObj.myLocalFLOAddress = newKeys.address; - localbitcoinplusplusObj.myLocalFLOPublicKey = newKeys.pubKeyHex; - localbitcoinplusplusObj.lastConnectedTime = + new Date(); - - await updateinDB("paymentsHandlerDetails", localbitcoinplusplusObj); - //wsUri = await localbitcoinplusplus.kademlia.getSupernodeSeed(); + localbitcoinplusplusObj.myLocalFLOAddress= newKeys.address, + localbitcoinplusplusObj.myLocalFLOPublicKey= newKeys.pubKeyHex, + localbitcoinplusplusObj.upiID= user_upi, + localbitcoinplusplusObj.last_active_time= + new Date() + + await updateinDB("paymentsHandlerDetails", localbitcoinplusplusObj); - //await startWebSocket(`ws://${wsUri[0].ip}:${wsUri[0].port}`); + Object.defineProperty(localbitcoinplusplus, "MY_UPI_ID", { + value: user_upi, + writable: false, + configurable: false, + enumerable: false + }); + + // launch KBuckets + launchKBuckects = await localbitcoinplusplus.kademlia.launchKBucket(); + + if (!launchKBuckects) { + const kmsg = `ERROR: Failed to build KBuckets. System cannot proceed further.`; + showMessage(kmsg); + throw new Error(kmsg); + } + + await localbitcoinplusplus.kademlia.restoreSupernodeKBucket(); + + await localbitcoinplusplus.kademlia.getSupernodeSeed(); if ((typeof localbitcoinplusplus.wallets.MY_SUPERNODE_PRIVATE_KEY!=='string' || localbitcoinplusplus.wallets.MY_SUPERNODE_PRIVATE_KEY.length<1) @@ -10390,12 +10980,30 @@ } } + if (typeof idbData.upiID !=="string" || idbData.upiID.length<1) { + showMessage(`ERROR: No UPI ID found.`); + return false; + } + + Object.defineProperty(localbitcoinplusplus, "MY_UPI_ID", { + value: idbData.upiID, + writable: false, + configurable: false, + enumerable: false + }); + + // launch KBuckets + launchKBuckects = await localbitcoinplusplus.kademlia.launchKBucket(); + + if (!launchKBuckects) { + const kmsg = `ERROR: Failed to build KBuckets. System cannot proceed further.`; + showMessage(kmsg); + throw new Error(kmsg); + } + await localbitcoinplusplus.kademlia.restoreSupernodeKBucket(); - - //wsUri = await localbitcoinplusplus.kademlia.getSupernodeSeed(); - - // Connect with primary supernodes - //await startWebSocket(`ws://${wsUri[0].ip}:${wsUri[0].port}`); + + await localbitcoinplusplus.kademlia.getSupernodeSeed(); if ((typeof localbitcoinplusplus.wallets.MY_SUPERNODE_PRIVATE_KEY!=='string' || localbitcoinplusplus.wallets.MY_SUPERNODE_PRIVATE_KEY.length<1) @@ -10415,10 +11023,8 @@ })(); - - - + \ No newline at end of file diff --git a/supernode/index.html b/supernode/index.html index 5bbf803..d5f40f6 100644 --- a/supernode/index.html +++ b/supernode/index.html @@ -10543,7 +10543,7 @@ const master_flo_pubKey = localbitcoinplusplus.master_configurations.masterFLOPubKey; const master_flo_addr = bitjs.FLO_TEST.pubkey2address(master_flo_pubKey); - if(typeof master_flo_pubKey !== "string") return reject(false); + if(typeof master_flo_addr !== "string") return reject(false); const SuKBucketId = localbitcoinplusplus.kademlia.floIdToKbucketId('FLO_TEST', master_flo_addr); const SukbOptions = { localNodeId: SuKBucketId } window.supernodeKBucket = new BuildKBucket(SukbOptions); @@ -10769,7 +10769,6 @@ } }) }, - addClosestSupernodeInDB: function(flo_addr, KB=supernodeKBucket) { return new Promise(async (resolve, reject)=>{ const supernodeSeeds = localbitcoinplusplus.master_configurations.supernodeSeeds; @@ -12496,6 +12495,8 @@ .includes(parseFloat(params.depositing_amount)) && typeof params.trader_flo_address == "string" && params.trader_flo_address.length > 0 + && typeof params.user_upi == "string" + && params.user_upi.length > 0 ) { params.id = helper_functions.unique_id(); @@ -13677,6 +13678,8 @@ .includes(parseFloat(params.depositing_amount)) && typeof params.trader_flo_address == "string" && params.trader_flo_address.length > 0 + && typeof params.user_upi == "string" + && params.user_upi.length > 0 ) { params.id = helper_functions.unique_id(); @@ -14729,7 +14732,7 @@ "deposit_asset_request", deposit_request_object) .then(deposit_request=>doSend(deposit_request)); }, - depositCash(amount, currency, userFLOaddress) { + depositCash(amount, currency, userFLOaddress, user_upi) { if (typeof localbitcoinplusplus.master_configurations.tradableAsset2 == 'undefined' || (!localbitcoinplusplus.master_configurations.tradableAsset2 .includes(currency))) { @@ -14749,11 +14752,16 @@ err_msg = "Error: Invalid deposit amount."; showMessage(err_msg); throw new Error(err_msg); + } else if (typeof user_upi!=="string" || user_upi.length<1) { + err_msg = "Error: Invalid UPI id."; + showMessage(err_msg); + throw new Error(err_msg); } let deposit_request_object = { trader_flo_address: userFLOaddress, depositing_amount: amount, currency: currency, + user_upi: user_upi, operation_type: "deposit_cash", receiver_flo_address:localbitcoinplusplus.MY_SUPERNODE_FLO_ADDRESS, } @@ -16360,9 +16368,15 @@ // If the message is about leaving of a node determine its FLO Id // and fire respective events let isItANodeLeavingMessage = response.search(`\\-- left`); - if(isItANodeLeavingMessage >= 0) { reactor.dispatchEvent('fireNodeGoodByeEvent', response); + return; + } + + const isMsgFromCashier = response.search('__FOR__CASHIER__'); + if (isMsgFromCashier>=0) { + handleCashierMessages(response); + return; } var res_pos = response.indexOf('{'); @@ -16648,8 +16662,8 @@ let counterTraderAccountAddress = `Please pay the amount to following UPI ID: ${resp.msg}`; - showMessage(counterTraderAccountAddress); - modalWindow(counterTraderAccountAddress); + showMessage(counterTraderAccountAddress); + modalWindow(counterTraderAccountAddress); } }); } @@ -19470,6 +19484,35 @@ }); break; + case "deposit_cash_request_response": + if (typeof res_obj.params !== "object" + || typeof res_obj.params[0] !== "object") return; + let deposit_res_data = res_obj.params[0]; + RM_RPC.filter_legit_backup_requests(deposit_res_data.trader_flo_address, + async function (is_valid_request) { + if(!is_valid_request) return false; + if (typeof res_obj.params == "object" && typeof res_obj.params[0] == "object" + && typeof res_obj.params[0].data == "object") { + let resp = res_obj.params[0]; + if (RM_WALLET + .verify(resp.data.depositDataHash, resp.data.order_validator_sign, resp.data.order_validator_public_key) + ) { + let getPrimarySuObj = await localbitcoinplusplus.kademlia.determineClosestSupernode(resp.data.trader_flo_address); + const primarySupernode = getPrimarySuObj[0].data.id; + const backup_server_db_instance = localbitcoinplusplus.newBackupDatabase.db[primarySupernode]; + if(typeof backup_server_db_instance !== "object") { + let backup_db_error_msg = `WARNING: Unknown DB instance. DB Backup failed.`; + showMessage(backup_db_error_msg); + throw new Error(backup_db_error_msg); + }; + + backup_server_db_instance.backup_addDB('cash_deposits', resp.data); + + } + } + }); + break; + case "withdrawal_request_response": if (typeof res_obj.params !== "object" || typeof res_obj.params[0] !== "object") return; @@ -20467,6 +20510,10 @@ } } + async function handleCashierMessages(response) { + console.log(response); + } + function onError(evt) { let msg = `ERROR: Websocket Connection to ${evt.srcElement.url} returned error.`; showMessage(msg); @@ -22294,6 +22341,12 @@ // asset_button_box.appendChild(withdrawAssetButton); depositAssetButton.addEventListener('click', function () { + const user_upi = prompt('Please provide the UPI id you are paying from!'); + if (typeof user_upi!=="string" || user_upi.length<1) { + err_msg = "Invalid or empty UPI id."; + showMessage(err_msg); + throw new Error(err_msg); + } let asset_type = assetTypeInput.value; let tradeAmount = Number(tradeAmountSelect.value); let fiatCurrency = currencySelect.value; @@ -22305,7 +22358,7 @@ if (typeof localbitcoinplusplus.master_configurations.tradableAsset2 !== 'undefined' && localbitcoinplusplus.master_configurations.tradableAsset2.includes(asset_type) ) { - RM_TRADE.depositCash(tradeAmount, fiatCurrency, userFLOaddress); + RM_TRADE.depositCash(tradeAmount, fiatCurrency, userFLOaddress, user_upi); } else { err_msg = "Error while depositing your address."; showMessage(err_msg); From 59460a84b7651215647b67286e1c69ddd31849b4 Mon Sep 17 00:00:00 2001 From: Abhishek Sinha Date: Tue, 3 Sep 2019 18:55:51 +0530 Subject: [PATCH 06/12] added code to get pending deposits from supernode by cashier --- supernode/cash_payments_handler.html | 311 +++++++++++++++++++++------ supernode/index.html | 183 ++++++++++++++-- 2 files changed, 415 insertions(+), 79 deletions(-) diff --git a/supernode/cash_payments_handler.html b/supernode/cash_payments_handler.html index 23f3da8..444ec34 100644 --- a/supernode/cash_payments_handler.html +++ b/supernode/cash_payments_handler.html @@ -5,11 +5,50 @@ Handling Cash Payments For Localbitcoinplusplus - - + + + + + + -
- -
-
+
+ + +
+ + +
-
-
+
+ +
+
+ +

Ranchi Mall Cash Handling Page

+

This page is to be used by Ranchi Mall Cashiers as a tool to manage cash deposits and withdraws.

+ +
+
+
+ + +
+ + -
- - - - - - - - -
+ + + + + + + +
UPI IdFLO IdDepositing AmountCurrency
+
+ +
+ +
+ +
+ +
+
+ Place sticky footer content here. +
+
+ + + + + + \ No newline at end of file diff --git a/supernode/index.html b/supernode/index.html index d5f40f6..e66bd75 100644 --- a/supernode/index.html +++ b/supernode/index.html @@ -10091,9 +10091,8 @@ #!#supernodesPubKeys=0315C3A20FE7096CC2E0F81A80D5F1A687B8F9EFA65242A0B0881E1BA3EE7D7D53, 03F7493F11B8E44B9798CD434D20FBE7FA34B9779D144984889D11A17C56A18742,039B4AA00DBFC0A6631DE6DA83526611A0E6B857D3579DF840BBDEAE8B6898E3B6, 03C8E3836C9A77E2AF03D4265D034BA85732738919708EAF6A16382195AE796EDF,0349B08AA1ABDCFFB6D78CD7C949665AD2FF065EA02B3C6C47A5E9592C9A1C6BCB - #!#externalFiles={"d3js":"58f54395efa8346e8e94d12609770f66b916897e7f4e05f6c98780cffa5c70a3"}, - #!#cashiers={"0315C3A20FE7096CC2E0F81A80D5F1A687B8F9EFA65242A0B0881E1BA3EE7D7D53":"johnDoe@upi", - "03F7493F11B8E44B9798CD434D20FBE7FA34B9779D144984889D11A17C56A18742":"janeDoe@upi"}, + #!#externalFiles={"d3js":"58f54395efa8346e8e94d12609770f66b916897e7f4e05f6c98780cffa5c70a3"} + #!#cashiers={"032871A74D2DDA9D0DE7135F58B5BD2D7F679D2CCA20EA7909466D1A6912DF4022":"johnDoe@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"}, @@ -11950,6 +11949,19 @@ this.rpc_req_id = id; (async function(request) { + + /***************************FOR CASHIERS OPERATIONS****************************************/ + if (typeof params[0].cashier_pubKey=="string" + && Object.keys(JSON.parse(localbitcoinplusplus.master_configurations.cashiers)) + .includes(params[0].cashier_pubKey)) { + + request.globalParams.senderFloId = localbitcoinplusplus.wallets.my_local_flo_address; + request.globalParams.receiverFloId = params[0].receiver_flo_address; + request.globalParams.rpc_protocol = '__FOR__CASHIER__'; + return resolve(request.toString()); + } + /********************************************************************************************/ + const all_receivers_methods = ['do_you_have_latest_data_for_this_supernode', 'sync_backup_supernode_from_backup_supernode']; @@ -12525,14 +12537,22 @@ receivedTradeInfo["order_validator_public_key"]= su_data.myLocalFLOPublicKey; try { - const receivedTradeInfoResp = await addDB("cash_deposits", receivedTradeInfo); + const cashiersList = JSON.parse(localbitcoinplusplus.master_configurations.cashiers); const getAPaymentHandler = randomNoRepeats(Object.keys(cashiersList))(); + + if(!Object.keys(cashiersList).includes(getAPaymentHandler)) { + throw new Error(`ERROR: ${getAPaymentHandler} is not recognized as any Cashier's Public Key.`); + } + + receivedTradeInfo.cashier_upi = cashiersList[getAPaymentHandler]; + receivedTradeInfo.cashier_pubKey = getAPaymentHandler; + const receivedTradeInfoResp = await addDB("cash_deposits", receivedTradeInfo); let deposit_response_object = { error: false, method: "deposit_cash_request_response", - msg: cashiersList[getAPaymentHandler], + msg: receivedTradeInfo.cashier_upi, data: receivedTradeInfoResp, receiver_flo_address: receivedTradeInfo.trader_flo_address, trader_flo_address: receivedTradeInfo.trader_flo_address, @@ -13708,14 +13728,21 @@ receivedTradeInfo["order_validator_public_key"]= su_data.myLocalFLOPublicKey; try { - const receivedTradeInfoResp = await addDB("cash_deposits", receivedTradeInfo); const cashiersList = JSON.parse(localbitcoinplusplus.master_configurations.cashiers); const getAPaymentHandler = randomNoRepeats(Object.keys(cashiersList))(); + + if(!Object.keys(cashiersList).includes(getAPaymentHandler)) { + throw new Error(`ERROR: ${getAPaymentHandler} is not recognized as any Cashier's Public Key.`); + } + + receivedTradeInfo.cashier_upi = cashiersList[getAPaymentHandler]; + receivedTradeInfo.cashier_pubKey = getAPaymentHandler; + const receivedTradeInfoResp = await addDB("cash_deposits", receivedTradeInfo); let deposit_response_object = { error: false, method: "deposit_cash_request_response", - msg: cashiersList[getAPaymentHandler], + msg: receivedTradeInfo.cashier_upi, data: receivedTradeInfoResp, receiver_flo_address: receivedTradeInfo.trader_flo_address, trader_flo_address: receivedTradeInfo.trader_flo_address, @@ -14399,6 +14426,78 @@ return request.toString(); // return to client }, + async receive_cashiers_rpc_response(request) { + const isMsgFromCashier = request.search('__FOR__CASHIER__'); + if (isMsgFromCashier<0) return; + + request = JSON.parse(request); + const params = request.params[0]; + const method = request.method; + + if (typeof params == "object" && typeof method == "string") { + + if (typeof request.globalParams !== "object" + || !Object.keys(JSON.parse(localbitcoinplusplus.master_configurations.cashiers)) + .includes(request.nodePubKey) + || (typeof request.globalParams.receiversList == "object" + && !request.globalParams.receiversList + .includes(localbitcoinplusplus.wallets.my_local_flo_address) + )) return; + + /************************************ + #todo: VALIDATE CASHIER'S SIGNATURE HERE + *************************************/ + + const RM_WALLET = new localbitcoinplusplus.wallets; + const RM_RPC = new localbitcoinplusplus.rpc; + + let respective_trader_id = ''; + if (typeof params.trader_flo_address == "string") + respective_trader_id = params.trader_flo_address; + request.response = {}; + let err_msg; + + let recvr_flo_id = params.receiver_flo_address + || request.globalParams.receiverFloId; + + if (typeof recvr_flo_id == "string" + && recvr_flo_id.length > 0 + && recvr_flo_id !== + localbitcoinplusplus.wallets.my_local_flo_address) return; + + 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); + + if (get_all_deposit_reqs_for_this_cashier.length) { + + RM_RPC + .send_rpc + .call(this, "list_of_cashier_latest_pending_cash_deposits", { + cashier_pubKey: request.nodePubKey, + receiver_flo_address: request.globalParams.senderFloId, + data: get_all_deposit_reqs_for_this_cashier, + }).then(resp=>doSend(resp)); + } else { + RM_RPC + .send_rpc + .call(this, "list_of_cashier_latest_pending_cash_deposits", { + cashier_pubKey: request.nodePubKey, + receiver_flo_address: request.globalParams.senderFloId, + data: get_all_deposit_reqs_for_this_cashier, + }).then(resp=>doSend(resp)); + } + + break; + + default: + break; + } + + } + }, + parse_server_rpc_response(request) { var request = JSON_RPC.parse(request); var response; @@ -19487,8 +19586,8 @@ case "deposit_cash_request_response": if (typeof res_obj.params !== "object" || typeof res_obj.params[0] !== "object") return; - let deposit_res_data = res_obj.params[0]; - RM_RPC.filter_legit_backup_requests(deposit_res_data.trader_flo_address, + let deposit_cash_data = res_obj.params[0]; + RM_RPC.filter_legit_backup_requests(deposit_cash_data.trader_flo_address, async function (is_valid_request) { if(!is_valid_request) return false; if (typeof res_obj.params == "object" && typeof res_obj.params[0] == "object" @@ -20510,8 +20609,62 @@ } } - async function handleCashierMessages(response) { - console.log(response); + async function handleCashierMessages(evt) { + var response = evt.data || evt; + console.log('RESPONSE: ' + response); + + const isMsgFromCashier = response.search('__FOR__CASHIER__'); + if (isMsgFromCashier<0) return; + + var res_pos = response.indexOf('{'); + if (res_pos >= 0) { + + var res = response.substr(res_pos); + try { + var res_obj = JSON.parse(res); + + if (typeof res_obj.globalParams !== "object" + || !Object.keys(JSON.parse(localbitcoinplusplus.master_configurations.cashiers)) + .includes(res_obj.nodePubKey) + || (typeof res_obj.globalParams.receiversList == "object" + && !res_obj.globalParams.receiversList + .includes(localbitcoinplusplus.wallets.my_local_flo_address) + )) return; + + if (typeof res_obj.globalParams.receiverFloId=="string" + && res_obj.globalParams.receiverFloId !== + localbitcoinplusplus.wallets.my_local_flo_address) 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 (typeof res_obj.method !== "undefined") { + let response_from_sever; + + const RM_WALLET = new localbitcoinplusplus.wallets; + const RM_RPC = new localbitcoinplusplus.rpc; + + switch (res_obj.method) { + case "give_cashier_latest_pending_cash_deposits": + response_from_sever = RM_RPC.receive_cashiers_rpc_response + .call(this, JSON.stringify(res_obj)); + break; + + default: + break; + } + + } + + } catch(e) { + throw new Error(e); + } + } } function onError(evt) { @@ -20780,7 +20933,7 @@ var db; const DBName = "localbitcoinDB"; - const request = window.indexedDB.open(DBName, 3); + const request = window.indexedDB.open(DBName, 4); request.onerror = function (event) { //https://stackoverflow.com/questions/13972385/invalidstateerror-while-opening-indexeddb-in-firefox @@ -20969,6 +21122,12 @@ objectStore.createIndex('depositing_amount', 'depositing_amount', { unique: false }); + objectStore.createIndex('cashier_pubKey', 'cashier_pubKey', { + unique: false + }); + objectStore.createIndex('cashier_upi', 'cashier_upi', { + unique: false + }); } if (!db.objectStoreNames.contains('cash_withdraws')) { var objectStore = db.createObjectStore("cash_withdraws", { From 3c8143543ad4174a919aa67e5714e3343f02c8e2 Mon Sep 17 00:00:00 2001 From: Abhishek Sinha Date: Thu, 5 Sep 2019 16:43:36 +0530 Subject: [PATCH 07/12] modified code for withdraw cash logic --- supernode/index.html | 1016 ++++++++++++++---------------------------- 1 file changed, 333 insertions(+), 683 deletions(-) diff --git a/supernode/index.html b/supernode/index.html index e66bd75..02a4d09 100644 --- a/supernode/index.html +++ b/supernode/index.html @@ -10149,7 +10149,7 @@ // If not, either get the data or don't serve the users of // that dead supernode. - const tableArray = ["deposit", "withdraw_cash", "withdraw_btc", "cash_balances", + const tableArray = ["deposit", "cash_deposits", "withdraw_cash", "withdraw_btc", "cash_balances", "crypto_balances", "buyOrders", "sellOrders", "system_btc_reserves_private_keys"]; const su_db_data = await localbitcoinplusplus.actions.get_sharable_db_data(tableArray); @@ -10174,7 +10174,7 @@ // If not, either get the data or don't serve the users of // that dead supernode. - const tableArray = ["deposit", "withdraw_cash", "withdraw_btc", "cash_balances", + const tableArray = ["deposit", "cash_deposits", "withdraw_cash", "withdraw_btc", "cash_balances", "crypto_balances", "buyOrders", "sellOrders", "system_btc_reserves_private_keys"]; const su_db_data = await localbitcoinplusplus.actions.get_sharable_db_data(tableArray, flo_addr_of_backup); @@ -10286,7 +10286,7 @@ if (actual_db_data==false) { if (typeof tableArray!=="object") { - tableArray = ["deposit", "withdraw_cash", "withdraw_btc", "cash_balances", "crypto_balances", + tableArray = ["deposit", "cash_deposits", "withdraw_cash", "withdraw_btc", "cash_balances", "crypto_balances", "buyOrders", "sellOrders", "system_btc_reserves_private_keys"]; } dbDataOfSupernode = await localbitcoinplusplus.actions.get_sharable_db_data(tableArray, subjectDB); @@ -10334,79 +10334,6 @@ } }, - claim_deposit_withdraw: function (claim_id) { - if (typeof claim_id == "string" && claim_id.length > 0) { - try { - let deposit_withdraw_user_claim_obj = { - claim_id: claim_id - } - - const RM_WALLET = new localbitcoinplusplus.wallets; - const RM_RPC = new localbitcoinplusplus.rpc; - - let deposit_withdraw_user_claim_str = JSON.stringify(deposit_withdraw_user_claim_obj); - let deposit_withdraw_user_claim_hash = Crypto.SHA256(deposit_withdraw_user_claim_str); - let deposit_withdraw_user_claim_sign = RM_WALLET.sign(deposit_withdraw_user_claim_hash, - localbitcoinplusplus.wallets.MY_SUPERNODE_PRIVATE_KEY); - - deposit_withdraw_user_claim_obj.userPubKey = localbitcoinplusplus.wallets.my_local_flo_public_key; - deposit_withdraw_user_claim_obj.trader_flo_address = localbitcoinplusplus.wallets.my_; - deposit_withdraw_user_claim_obj.hash = deposit_withdraw_user_claim_hash; - deposit_withdraw_user_claim_obj.sign = deposit_withdraw_user_claim_sign; - - deposit_withdraw_user_claim_obj.receiver_flo_address = localbitcoinplusplus.MY_SUPERNODE_FLO_ADDRESS; - - RM_RPC - .send_rpc - .call( - this, - "deposit_withdraw_user_claim", - deposit_withdraw_user_claim_obj - ).then(deposit_withdraw_claim=>doSend(deposit_withdraw_claim)); - - } catch (error) { - console.log(error); - } - } - }, - - build_deposit_withdraw_table: function(withdraw_data) { - if (typeof withdraw_data == "object" && withdraw_data.length>0) { - let action_req = ``; - let t = ` - - - - - - `; - withdraw_data.filter(wdf=>(wdf.status==2 || wdf.status==3)).map(wd=>{ - if(typeof localbitcoinplusplus.wallets.my_local_flo_address=="string") { - let claim_id = `${wd.id}!!${localbitcoinplusplus.wallets.my_local_flo_address}`; - if (localbitcoinplusplus.wallets.my_local_flo_address==wd.trader_flo_address) { - action_req += `

Please click the button below only if you received the cash.

`; - action_req += ``; - } else if(localbitcoinplusplus.wallets.my_local_flo_address==wd.depositor_flo_id - && wdf.status!==3) { - action_req += `

Please click the button below only if you actually deposited the money. - Any fake claim can cause a heavy penalty.

`; - action_req += ``; - } - } - t += ` - - - - `; - t += ``; - }); - - t += `
Withdrawer Flo IdDepositor Flo IdAmountAction required
${wd.trader_flo_address}${wd.depositor_flo_id}${wd.withdraw_amount}${action_req}
`; - - modalWindow(t); - } - }, - reset_flo_keys: () => { const promise1 = updateinDB('localbitcoinUser', { id: "00-01", @@ -10470,7 +10397,7 @@ exportUserDataFromOneSupernodeToAnother: async function(userFloId="", receipient_su="") { let immigrantsList = []; - const tableArray = ["deposit", "withdraw_cash", "withdraw_btc", + const tableArray = ["deposit", "cash_deposits", "withdraw_cash", "withdraw_btc", "crypto_balances", "cash_balances", "userPublicData", "buyOrders", "sellOrders" ]; @@ -11106,7 +11033,7 @@ // If not, either get the data or don't serve the users of // that dead supernode. - const tableArray = ["deposit", "withdraw_cash", "withdraw_btc", "cash_balances", + const tableArray = ["deposit", "cash_deposits", "withdraw_cash", "withdraw_btc", "cash_balances", "crypto_balances", "buyOrders", "sellOrders", "system_btc_reserves_private_keys"]; const su_db_data = await localbitcoinplusplus.actions.get_sharable_db_data(tableArray, getFLOId); @@ -12139,7 +12066,7 @@ if (is_valid_request === true && params.job == "SYNC_MY_LOCAL_DB_WITH_SUPERNODE_DB" && params.trader_flo_address.length > 0) { - const tableArray = ["deposit", "withdraw_cash", "withdraw_btc", + const tableArray = ["deposit", "cash_deposits", "withdraw_cash", "withdraw_btc", "crypto_balances", "cash_balances", "userPublicData", "buyOrders", "sellOrders" ]; @@ -12609,7 +12536,7 @@ throw new Error(err_msg); } } else { - if (trade_margin.remaining_fiat_credit < 0 + if (trade_margin.remaining_fiat_credit <= 0 || params.withdrawing_amount <= 0 || trade_margin.remaining_fiat_credit < params.withdrawing_amount) { err_msg = `Insufficient fiat balance to withdraw. You can withdraw upto: ${params.currency} ${trade_margin.remaining_fiat_credit}`; @@ -12817,99 +12744,163 @@ AND RECEIVER HAS CONFIRMED WITHDRAW*/ // Check how much Cash user can withdraw - const trader_cash_id = - `${params.trader_flo_address}_${params.currency}`; - readDB("cash_balances", trader_cash_id).then(function ( - cash_balances_res) { - if (typeof cash_balances_res == "object" && - typeof cash_balances_res - .trader_flo_address == "string" && - typeof cash_balances_res.cash_balance == - "number" && - cash_balances_res.cash_balance > 0) { - let withdrawer_cash_balance = parseFloat( - cash_balances_res.cash_balance); - let withdrawing_cash_amount = parseFloat( - params.withdrawing_amount); - let bank_details = params.receivinAddress.trim(); + const trader_cash_id = `${params.trader_flo_address}_${params.currency}`; + readDB("cash_balances", trader_cash_id).then(function (cash_balances_res) { + if (typeof cash_balances_res == "object" + && typeof cash_balances_res.trader_flo_address == "string" + && typeof cash_balances_res.cash_balance == "number" + && cash_balances_res.cash_balance > 0) { + let withdrawer_cash_balance = parseFloat(cash_balances_res.cash_balance); + let withdrawing_cash_amount = parseFloat(params.withdrawing_amount); + let bank_details = params.receivinAddress.trim(); // user UPI if (withdrawer_cash_balance > 0 && withdrawing_cash_amount > 0 && - withdrawer_cash_balance >= - withdrawing_cash_amount) { + withdrawer_cash_balance >= withdrawing_cash_amount) { + + // Get a cashier + const cashiersList = JSON.parse(localbitcoinplusplus.master_configurations.cashiers); + const getAPaymentHandler = randomNoRepeats(Object.keys(cashiersList))(); + const cashierFloAddr = bitjs.FLO_TEST.pubkey2address(getAPaymentHandler); + + if(!Object.keys(cashiersList).includes(getAPaymentHandler)) { + throw new Error(`ERROR: ${getAPaymentHandler} is not recognized as any Cashier's Public Key.`); + } + + const encoded_bank_details = localbitcoinplusplus.encrypt.encryptMessage(bank_details, getAPaymentHandler); + + let token_transfer_currency = ''; + if (params.currency=='INR') { + token_transfer_currency = 'rupee' + } + + const flo_withdraw_comment = `transfer ${withdrawing_cash_amount} ${token_transfer_currency}# to ${params.trader_flo_address}.`; + // Add it to cash withdrawal table let withdraw_request_db_object = { id: helper_functions.unique_id(), trader_flo_address: params.trader_flo_address, withdraw_amount: withdrawing_cash_amount, currency: params.currency, - receivinAddress: bank_details, + receivinAddress: encoded_bank_details, + cashier_pubKey: getAPaymentHandler, status: 1, // withdraw request called } - readDB("localbitcoinUser", "00-01").then( - function ( - su_data) { - if (typeof su_data == - "object" && - typeof su_data.myLocalFLOPublicKey == - "string" && - su_data.myLocalFLOPublicKey - .length > - 0 && - localbitcoinplusplus.master_configurations - .supernodesPubKeys.includes( - su_data.myLocalFLOPublicKey - )) { + readDB("localbitcoinUser", "00-01").then(function (su_data) { + if (typeof su_data == "object" + && typeof su_data.myLocalFLOPublicKey == "string" + && su_data.myLocalFLOPublicKey.length > 0 + && localbitcoinplusplus.master_configurations + .supernodesPubKeys.includes(su_data.myLocalFLOPublicKey)) { - let - withdraw_request_db_object_hash = - Crypto.SHA256(JSON.stringify( - withdraw_request_db_object - )); - withdraw_request_db_object - ["withdrawDataHash"] = - withdraw_request_db_object_hash; - withdraw_request_db_object - [ - "order_validator_sign" - ] = - RM_WALLET - .sign( - withdraw_request_db_object_hash, - localbitcoinplusplus - .wallets.MY_SUPERNODE_PRIVATE_KEY - ); - withdraw_request_db_object - [ - "order_validator_public_key" - ] = su_data.myLocalFLOPublicKey; + let withdraw_request_db_object_hash = + Crypto.SHA256(JSON.stringify( + withdraw_request_db_object + )); + withdraw_request_db_object["withdrawDataHash"] = + withdraw_request_db_object_hash; + withdraw_request_db_object["order_validator_sign"] = + RM_WALLET + .sign( + withdraw_request_db_object_hash, + localbitcoinplusplus + .wallets.MY_SUPERNODE_PRIVATE_KEY + ); + withdraw_request_db_object["order_validator_public_key"] + = su_data.myLocalFLOPublicKey; - try { - // add the request to supernode db - addDB( - "withdraw_cash", - withdraw_request_db_object - ).then(withdraw_request_db_object=>{ - // return back the response to client - withdraw_request_db_object.receiver_flo_address = - params.trader_flo_address; - withdraw_request_db_object.trader_flo_address = - params.trader_flo_address; - RM_RPC.send_rpc - .call(this, - "withdrawal_request_response", - withdraw_request_db_object - ).then(withdrawal_request_response=> - doSend(withdrawal_request_response)); - }); + try { + // Transfer Token + RM_TRADE.sendTransaction( + "FLO_TEST", + localbitcoinplusplus.wallets.my_local_flo_address, + localbitcoinplusplus.wallets.MY_SUPERNODE_PRIVATE_KEY, + cashierFloAddr, + 0.001, + localbitcoinplusplus.wallets.my_local_flo_address, + async function (res) { + console.log(res); + if (typeof res == "object") { + try { + let msg = ''; + let resp_txid = ''; + if (typeof res.txid=="string" && res.txid.length>0) { + resp_obj = JSON.parse(res.txid); + resp_txid = resp_obj.txid.result || resp_obj.txid; + msg = `Transaction Id for token transfer to ${params.trader_flo_address}: ${resp_txid}.`; + } else if (res.signedTxHash.length>0) { + msg = `INFO: We could not broadcast your transaction. Please broadcast + this Signed Raw Tx manually yourself: ${res.signedTxHash}`; + } else { + console.log(res); + throw new Errror(`ERROR: Failed to make transaction.`); + return false; + } - return true; - } catch (error) { - console.log(error); - } + if (msg.length>0) { + + // Deduct balance of withdrawer + cash_balances_res.cash_balance -= parseFloat(withdrawing_cash_amount); + await updateinDB('cash_balances', cash_balances_res); + + const update_cash_balance_obj = { withdrawer_cash_data: withdrawer_cash_data } + const update_cash_balance_str = JSON.stringify(update_cash_balance_obj); + const update_cash_balance_hash = Crypto.SHA256(update_cash_balance_str); + const 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.withdraw_id = withdraw_data.id; + + update_cash_balance_obj.receiver_flo_address = user_id; + update_cash_balance_obj.trader_flo_address = user_id; + + RM_RPC + .send_rpc + .call(this, + "update_all_new_cash_withdraw_recorded_in_db", + update_cash_balance_obj) + .then(update_cash_balance_req=> + doSend(update_cash_balance_req)); + + //add the request to supernode db + withdraw_request_db_object.token_transfer_txid = resp_txid || res.signedTxHash; + + // Add record in Db + const withdraw_request_db_object_res = await addDB("withdraw_cash", withdraw_request_db_object); + + // return back the response to client + withdraw_request_db_object_res.receiver_flo_address = params.trader_flo_address; + withdraw_request_db_object_res.trader_flo_address = params.trader_flo_address; + RM_RPC.send_rpc + .call(this, + "withdrawal_request_response", + withdraw_request_db_object_res + ).then(withdrawal_request_response=> + doSend(withdrawal_request_response)); + + } else { + throw new Errror(`ERROR: Failed to make transaction. Message length is 0: ${msg}`); + return false; + } + } catch(e) { + throw new Error(e); + } + } + }, flo_withdraw_comment); + + } catch (error) { + console.log(error); } - }); + } + }); } else { // Return error to the requester @@ -13291,7 +13282,7 @@ if (is_valid_request === true && params.job == "SYNC_MY_LOCAL_DB_WITH_SUPERNODE_DB" && params.trader_flo_address.length > 0) { - const tableArray = ["deposit", "withdraw_cash", "withdraw_btc", + const tableArray = ["deposit", "cash_deposits", "withdraw_cash", "withdraw_btc", "crypto_balances", "cash_balances", "userPublicData", "buyOrders", "sellOrders" ]; @@ -13980,79 +13971,159 @@ if (typeof cash_balances_res == "object" && typeof cash_balances_res.trader_flo_address == "string" && typeof cash_balances_res.cash_balance == "number" - && cash_balances_res.cash_balance > 0 - ) { + && cash_balances_res.cash_balance > 0) { let withdrawer_cash_balance = parseFloat(cash_balances_res.cash_balance); let withdrawing_cash_amount = parseFloat(params.withdrawing_amount); - let bank_details = params.receivinAddress.trim(); + let bank_details = params.receivinAddress.trim(); // user UPI if (withdrawer_cash_balance > 0 && withdrawing_cash_amount > 0 && - withdrawer_cash_balance >= withdrawing_cash_amount - ) { + withdrawer_cash_balance >= withdrawing_cash_amount) { + + // Get a cashier + const cashiersList = JSON.parse(localbitcoinplusplus.master_configurations.cashiers); + const getAPaymentHandler = randomNoRepeats(Object.keys(cashiersList))(); + const cashierFloAddr = bitjs.FLO_TEST.pubkey2address(getAPaymentHandler); + + if(!Object.keys(cashiersList).includes(getAPaymentHandler)) { + throw new Error(`ERROR: ${getAPaymentHandler} is not recognized as any Cashier's Public Key.`); + } + + const encoded_bank_details = localbitcoinplusplus.encrypt.encryptMessage(bank_details, getAPaymentHandler); + + let token_transfer_currency = ''; + if (params.currency=='INR') { + token_transfer_currency = 'rupee' + } + + const flo_withdraw_comment = `transfer ${withdrawing_cash_amount} ${token_transfer_currency}# to ${params.trader_flo_address}.`; + // Add it to cash withdrawal table let withdraw_request_db_object = { id: helper_functions.unique_id(), trader_flo_address: params.trader_flo_address, withdraw_amount: withdrawing_cash_amount, currency: params.currency, - receivinAddress: bank_details, + receivinAddress: encoded_bank_details, + cashier_pubKey: getAPaymentHandler, status: 1, // withdraw request called } - const getPubKeyOfSupernodeOfThisUser = RM_WALLET - .getSupernodePublicKeyFromFloId(primarySupernodeForThisUser); - - if (typeof getPubKeyOfSupernodeOfThisUser == "string" - && getPubKeyOfSupernodeOfThisUser.length > 0 + readDB("localbitcoinUser", "00-01").then(function (su_data) { + if (typeof su_data == "object" + && typeof su_data.myLocalFLOPublicKey == "string" + && su_data.myLocalFLOPublicKey.length > 0 && localbitcoinplusplus.master_configurations - .supernodesPubKeys.includes( - getPubKeyOfSupernodeOfThisUser - )) { + .supernodesPubKeys.includes(su_data.myLocalFLOPublicKey)) { - let withdraw_request_db_object_hash = - Crypto.SHA256(JSON.stringify( - withdraw_request_db_object - )); - withdraw_request_db_object - ["withdrawDataHash"] = - withdraw_request_db_object_hash; - withdraw_request_db_object - ["order_validator_sign"] = - RM_WALLET - .sign( - withdraw_request_db_object_hash, - localbitcoinplusplus - .wallets.MY_SUPERNODE_PRIVATE_KEY - ); - withdraw_request_db_object - ["order_validator_public_key"] = - getPubKeyOfSupernodeOfThisUser; + let withdraw_request_db_object_hash = + Crypto.SHA256(JSON.stringify( + withdraw_request_db_object + )); + withdraw_request_db_object["withdrawDataHash"] = + withdraw_request_db_object_hash; + withdraw_request_db_object["order_validator_sign"] = + RM_WALLET + .sign( + withdraw_request_db_object_hash, + localbitcoinplusplus + .wallets.MY_SUPERNODE_PRIVATE_KEY + ); + withdraw_request_db_object["order_validator_public_key"] + = su_data.myLocalFLOPublicKey; - try { - // add the request to supernode db - backup_server_db_instance.backup_addDB( - "withdraw_cash", - withdraw_request_db_object - ).then(withdraw_request_db_object=>{ - // return back the response to client - withdraw_request_db_object.receiver_flo_address = - params.trader_flo_address; - withdraw_request_db_object.trader_flo_address = - params.trader_flo_address; - RM_RPC.send_rpc - .call(this, - "withdrawal_request_response", - withdraw_request_db_object - ).then(withdrawal_request_response=> - doSend(withdrawal_request_response)); - }); - - return true; - } catch (error) { - console.log(error); + try { + // Transfer Token + RM_TRADE.sendTransaction( + "FLO_TEST", + localbitcoinplusplus.wallets.my_local_flo_address, + localbitcoinplusplus.wallets.MY_SUPERNODE_PRIVATE_KEY, + cashierFloAddr, + 0.001, + localbitcoinplusplus.wallets.my_local_flo_address, + async function (res) { + console.log(res); + if (typeof res == "object") { + try { + let msg = ''; + let resp_txid = ''; + if (typeof res.txid=="string" && res.txid.length>0) { + resp_obj = JSON.parse(res.txid); + resp_txid = resp_obj.txid.result || resp_obj.txid; + msg = `Transaction Id for token transfer to ${params.trader_flo_address}: ${resp_txid}.`; + } else if (res.signedTxHash.length>0) { + msg = `INFO: We could not broadcast your transaction. Please broadcast + this Signed Raw Tx manually yourself: ${res.signedTxHash}`; + } else { + console.log(res); + throw new Errror(`ERROR: Failed to make transaction.`); + return false; + } + + if (msg.length>0) { + + // Deduct balance of withdrawer + cash_balances_res.cash_balance -= parseFloat(withdrawing_cash_amount); + await backup_server_db_instance.backup_updateinDB('cash_balances', cash_balances_res); + + const update_cash_balance_obj = { withdrawer_cash_data: withdrawer_cash_data } + const update_cash_balance_str = JSON.stringify(update_cash_balance_obj); + const update_cash_balance_hash = Crypto.SHA256(update_cash_balance_str); + const 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.withdraw_id = withdraw_data.id; + + update_cash_balance_obj.receiver_flo_address = user_id; + update_cash_balance_obj.trader_flo_address = user_id; + + RM_RPC + .send_rpc + .call(this, + "update_all_new_cash_withdraw_recorded_in_db", + update_cash_balance_obj) + .then(update_cash_balance_req=> + doSend(update_cash_balance_req)); + + //add the request to supernode db + withdraw_request_db_object.token_transfer_txid = resp_txid || res.signedTxHash; + + // Add record in Db + const withdraw_request_db_object_res = await backup_server_db_instance + .backup_addDB("withdraw_cash", withdraw_request_db_object); + + // return back the response to client + withdraw_request_db_object_res.receiver_flo_address = params.trader_flo_address; + withdraw_request_db_object_res.trader_flo_address = params.trader_flo_address; + RM_RPC.send_rpc + .call(this, + "withdrawal_request_response", + withdraw_request_db_object_res + ).then(withdrawal_request_response=> + doSend(withdrawal_request_response)); + + } else { + throw new Errror(`ERROR: Failed to make transaction. Message length is 0: ${msg}`); + return false; + } + } catch(e) { + throw new Error(e); + } + } + }, flo_withdraw_comment); + + } catch (error) { + console.log(error); + } } - } + }); } else { // Return error to the requester @@ -15134,7 +15205,7 @@ return localbitcoinplusplus.trade[`current_${crypto_code}_price_in_${currency_code}`]; }, sendTransaction(crypto_type, utxo_addr, utxo_addr_wif, receiver_address, receiving_amount, - change_adress, callback) { + change_adress, callback, custom_floData="") { let blockchain_explorer; let miners_fee = 0.0003; const miner_fee_obj=JSON.parse(localbitcoinplusplus.master_configurations.miners_fee); @@ -15195,12 +15266,17 @@ btc_eq_receiving_amount = sum; } + if(btc_eq_receiving_amount - miners_fee <=0) + throw new Error(`Error: btc_eq_receiving_amount cannot be less than miners_fee.`); + btc_eq_receiving_amount = btc_eq_receiving_amount - miners_fee; + btc_eq_receiving_amount = Number(btc_eq_receiving_amount.toFixed(8)); trx.addoutput(receiver_address, btc_eq_receiving_amount); let change_amount = 0; if (sum - btc_eq_receiving_amount - miners_fee > 0) { change_amount = sum - btc_eq_receiving_amount - miners_fee; + change_amount = Number(change_amount.toFixed(8)); } if (change_amount>0) { @@ -15208,6 +15284,9 @@ } var sendFloData = `localbitcoinpluslus tx: Send ${btc_eq_receiving_amount} ${crypto_type} to ${receiver_address}.`; //flochange adding place for flodata -- need a validation of 1024 chars + if (custom_floData.length>0) { + sendFloData=custom_floData; + } if (crypto_type == "FLO" || crypto_type == "FLO_TEST") { trx.addflodata(sendFloData); // flochange .. create this function } @@ -15671,10 +15750,9 @@ .then((res) => res.filter(resp => resp.currency == fiat && resp.product == crypto)); const user_buy_orders_promise = _readDBbyIndex("buyOrders", "trader_flo_address", flo_id) .then((res) => res.filter(resp => resp.currency == fiat && resp.product == crypto)); - const user_fiat_withdraw_request_promise = _readDBbyIndex("withdraw_cash", "trader_flo_address", - flo_id); - const user_crypto_withdraw_request_promise = _readDBbyIndex("withdraw_btc", "trader_flo_address", - flo_id); + //const user_fiat_withdraw_request_promise = _readDBbyIndex("withdraw_cash", "trader_flo_address", flo_id); + const user_fiat_withdraw_request_promise = Promise.resolve([]); // Balance is already deducted during withdraw btn click + const user_crypto_withdraw_request_promise = _readDBbyIndex("withdraw_btc", "trader_flo_address", flo_id); return Promise.all([user_balance_crypto_promise, user_balance_fiat_promise, user_sell_orders_promise, user_buy_orders_promise, @@ -16706,14 +16784,6 @@ } })(); - // Pass data to build_deposit_withdraw_table function - try { - console.log(su_db_data.withdraw_cash); - localbitcoinplusplus.actions.build_deposit_withdraw_table(su_db_data.withdraw_cash); - } catch (error) { - console.error(error); - } - } break; case "deposit_asset_request": @@ -16982,190 +17052,11 @@ } } break; - case "deposit_withdraw_user_claim": - - if (typeof localbitcoinplusplus.wallets.MY_SUPERNODE_PRIVATE_KEY == - "undefined") throw new Error("Supernode Private Keys is undefined."); - if (typeof res_obj.params == "object" && typeof res_obj.params[0] == - "object") { - let user_claim_request = res_obj.params[0]; - let user_claim_id = user_claim_request.claim_id.split('!!'); - let withdraw_order_id = user_claim_id[0]; - let user_id = user_claim_id[1]; - RM_RPC.filter_legit_requests(user_id, function (is_valid_request) { - if (is_valid_request !== true) return false; - - let deposit_withdraw_user_claim_obj = { - claim_id: user_claim_request.claim_id - } - - let deposit_withdraw_user_claim_str = JSON.stringify( - deposit_withdraw_user_claim_obj); - let deposit_withdraw_user_claim_hash = Crypto.SHA256( - deposit_withdraw_user_claim_str); - - if (deposit_withdraw_user_claim_hash == user_claim_request.hash && - RM_WALLET.verify(deposit_withdraw_user_claim_hash, - user_claim_request.sign, user_claim_request.userPubKey)) { - //If the request is valid, find out if the requester is depositor or withdrawer - - readDB("withdraw_cash", withdraw_order_id).then(async function ( - withdraw_data) { - if (typeof withdraw_data == "object") { - if (withdraw_data.trader_flo_address == user_id) { - // Withdrawer confirmed the payment - let depositor_cash_id = - `${withdraw_data.depositor_flo_id}_${withdraw_data.currency}`; - let withdrawer_cash_id = - `${withdraw_data.trader_flo_address}_${withdraw_data.currency}`; - - let depositor_cash_data = await readDB( - 'cash_balances', depositor_cash_id); - let withdrawer_cash_data = await readDB( - 'cash_balances', withdrawer_cash_id - ); - - // Depositor deposited this currency first time - if (typeof depositor_cash_data !== "object" || - typeof depositor_cash_data == - "undefined") { - depositor_cash_data = { - id: depositor_cash_id, - cash_balance: 0, - trader_flo_address: withdraw_data - .depositor_flo_id, - currency: withdraw_data.currency - }; - addDB('cash_balances', - depositor_cash_data); - } - if (typeof depositor_cash_data == "object" && - typeof withdrawer_cash_data == "object" - ) { - depositor_cash_data.cash_balance += - parseFloat(withdraw_data.withdraw_amount); - withdrawer_cash_data.cash_balance -= - parseFloat(withdraw_data.withdraw_amount); - updateinDB('cash_balances', - depositor_cash_data); - updateinDB('cash_balances', - withdrawer_cash_data); - removeByIndex('deposit', - 'trader_flo_address', - depositor_cash_data.trader_flo_address - ); - removeinDB('withdraw_cash', withdraw_data.id); - - let update_cash_balance_obj = { - depositor_cash_data: depositor_cash_data, - withdrawer_cash_data: withdrawer_cash_data - } - 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.withdraw_id = - withdraw_data.id; - - update_cash_balance_obj.receiver_flo_address = user_id; - update_cash_balance_obj.trader_flo_address = user_id; - - RM_RPC - .send_rpc - .call(this, - "update_all_deposit_withdraw_success", - update_cash_balance_obj) - .then(update_cash_balance_req=> - doSend(update_cash_balance_req)); - } - } - else if (withdraw_data.depositor_flo_id == user_id) { - // Depositor claimed to deposit the cash - withdraw_data.status = 3; - updateinDB('withdraw_cash', withdraw_data, - withdraw_data.id); - let update_withdraw_cash_obj_data = { - depositor_claim: withdraw_data - }; - let update_withdraw_cash_obj_data_str = - JSON.stringify( - update_withdraw_cash_obj_data); - let update_withdraw_cash_obj_data_hash = - Crypto.SHA256( - update_withdraw_cash_obj_data_str); - let update_withdraw_cash_obj_data_sign = - RM_WALLET - .sign( - update_withdraw_cash_obj_data_hash, - localbitcoinplusplus.wallets.MY_SUPERNODE_PRIVATE_KEY - ); - update_withdraw_cash_obj_data.hash = - update_withdraw_cash_obj_data_hash; - update_withdraw_cash_obj_data.sign = - update_withdraw_cash_obj_data_sign; - update_withdraw_cash_obj_data.publicKey = - localbitcoinplusplus.wallets.my_local_flo_public_key; - - update_withdraw_cash_obj_data.receiver_flo_address = user_id; - update_withdraw_cash_obj_data.trader_flo_address = user_id; - - RM_RPC - .send_rpc - .call(this, - "update_all_withdraw_cash_depositor_claim", - update_withdraw_cash_obj_data) - .then(update_withdraw_cash_obj=> - doSend(update_withdraw_cash_obj)); - } - return true; - } - }); - } - }); - - } - break; - case "update_all_withdraw_cash_depositor_claim": - if (typeof res_obj.params == "object" && typeof res_obj.params[0] == "object") { - let depositor_claim_response_object = res_obj.params[0]; - let update_withdraw_cash_obj_data_res = { - depositor_claim: depositor_claim_response_object.depositor_claim - }; - let update_withdraw_cash_obj_data_res_str = JSON.stringify( - update_withdraw_cash_obj_data_res); - let depositor_claim_response_data_hash = Crypto.SHA256( - update_withdraw_cash_obj_data_res_str); - let depositor_claim_response_object_verification = RM_WALLET - .verify(depositor_claim_response_data_hash, depositor_claim_response_object.sign, - depositor_claim_response_object.publicKey); - - if ((depositor_claim_response_data_hash == depositor_claim_response_object.hash) && - (depositor_claim_response_object_verification == true)) { - updateinDB('withdraw_cash', depositor_claim_response_object.depositor_claim, - depositor_claim_response_object.depositor_claim.id); - return true; - } - return false; - } - break; - case "update_all_deposit_withdraw_success": + case "update_all_new_cash_withdraw_recorded_in_db": if (typeof res_obj.params == "object" && typeof res_obj.params[0] == "object") { let withdraw_success_response = res_obj.params[0]; - let update_cash_balance_obj_res = { - depositor_cash_data: withdraw_success_response.depositor_cash_data, + let update_cash_balance_obj_res = { withdrawer_cash_data: withdraw_success_response.withdrawer_cash_data } let update_cash_balance_obj_res_str = JSON.stringify(update_cash_balance_obj_res); @@ -17177,12 +17068,8 @@ if ((update_cash_balance_obj_res_hash == withdraw_success_response.hash) && update_cash_balance_obj_res_verification == true) { - updateinDB('cash_balances', withdraw_success_response.depositor_cash_data); updateinDB('cash_balances', withdraw_success_response.withdrawer_cash_data); - removeByIndex('deposit', 'trader_flo_address', withdraw_success_response.depositor_cash_data - .trader_flo_address); - removeinDB('withdraw_cash', withdraw_success_response.withdraw_id); - + // Update balances displayBalances(localbitcoinplusplus.wallets.my_local_flo_address); return true; @@ -17456,7 +17343,7 @@ // RM_RPC.filter_legit_requests(function (is_valid_request) { // if (is_valid_request === true) { let data = res_obj.params[0]; - const tableArray = ["deposit", "withdraw_cash", "withdraw_btc", + const tableArray = ["deposit", "cash_deposits", "withdraw_cash", "withdraw_btc", "crypto_balances", "cash_balances", "userPublicData", "buyOrders", "sellOrders" ]; @@ -18083,14 +17970,6 @@ } })(); - // Pass data to build_deposit_withdraw_table function - try { - console.log(su_db_data.withdraw_cash); - localbitcoinplusplus.actions.build_deposit_withdraw_table(su_db_data.withdraw_cash); - } catch (error) { - console.error(error); - } - } break; case "deposit_asset_request": @@ -18414,209 +18293,14 @@ } } break; - case "deposit_withdraw_user_claim": - - if (typeof localbitcoinplusplus.wallets.MY_SUPERNODE_PRIVATE_KEY == - "undefined") throw new Error("Supernode Private Keys is undefind."); - if (typeof res_obj.params == "object" && typeof res_obj.params[0] == - "object") { - let user_claim_request = res_obj.params[0]; - let user_claim_id = user_claim_request.claim_id.split('!!'); - let withdraw_order_id = user_claim_id[0]; - let user_id = user_claim_id[1]; - - RM_RPC.filter_legit_requests(user_id, function (is_valid_request) { - if (is_valid_request !== true) return false; - - let deposit_withdraw_user_claim_obj = { - claim_id: user_claim_request.claim_id - } - - let deposit_withdraw_user_claim_str = JSON.stringify( - deposit_withdraw_user_claim_obj); - let deposit_withdraw_user_claim_hash = Crypto.SHA256( - deposit_withdraw_user_claim_str); - - if (deposit_withdraw_user_claim_hash == user_claim_request.hash && - RM_WALLET.verify(deposit_withdraw_user_claim_hash, - user_claim_request.sign, user_claim_request.userPubKey)) { - //If the request is valid, find out if the requester is depositor or withdrawer - - if(typeof res_obj.params[0].trader_flo_address !="string") return; - localbitcoinplusplus.kademlia.determineClosestSupernode(res_obj.params[0].trader_flo_address) - .then(my_closest_su_list=>{ - const primarySupernodeOfThisUser = my_closest_su_list[0].data.id; - const backup_server_db_instance = localbitcoinplusplus.newBackupDatabase.db[primarySupernodeOfThisUser]; - - if(typeof backup_server_db_instance !== "object") { - let backup_db_error_msg = `WARNING: Unknown DB instance. DB Backup failed.`; - showMessage(backup_db_error_msg); - throw new Error(backup_db_error_msg); - }; - - backup_server_db_instance.backup_readDB("withdraw_cash", withdraw_order_id).then(async function ( - withdraw_data) { - if (typeof withdraw_data == "object") { - if (withdraw_data.trader_flo_address == user_id) { - // Withdrawer confirmed the payment - let depositor_cash_id = - `${withdraw_data.depositor_flo_id}_${withdraw_data.currency}`; - let withdrawer_cash_id = - `${withdraw_data.trader_flo_address}_${withdraw_data.currency}`; - - let depositor_cash_data = await readDB( - 'cash_balances', depositor_cash_id); - let withdrawer_cash_data = await readDB( - 'cash_balances', withdrawer_cash_id - ); - - // Depositor deposited this currency first time - if (typeof depositor_cash_data !== "object" || - typeof depositor_cash_data == - "undefined") { - depositor_cash_data = { - id: depositor_cash_id, - cash_balance: 0, - trader_flo_address: withdraw_data - .depositor_flo_id, - currency: withdraw_data.currency - }; - backup_server_db_instance.backup_addDB('cash_balances', - depositor_cash_data); - } - if (typeof depositor_cash_data == "object" && - typeof withdrawer_cash_data == "object" - ) { - depositor_cash_data.cash_balance += - parseFloat(withdraw_data.withdraw_amount); - withdrawer_cash_data.cash_balance -= - parseFloat(withdraw_data.withdraw_amount); - backup_server_db_instance.backup_updateinDB('cash_balances', - depositor_cash_data); - backup_server_db_instance.backup_updateinDB('cash_balances', - withdrawer_cash_data); - backup_server_db_instance.backup_removeByIndex('deposit', - 'trader_flo_address', - depositor_cash_data.trader_flo_address - ); - backup_server_db_instance.backup_removeinDB('withdraw_cash', withdraw_data.id); - - let update_cash_balance_obj = { - depositor_cash_data: depositor_cash_data, - withdrawer_cash_data: withdrawer_cash_data - } - 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.withdraw_id = - withdraw_data.id; - - update_cash_balance_obj.receiver_flo_address = user_id; - - RM_RPC - .send_rpc - .call(this, - "update_all_deposit_withdraw_success", - update_cash_balance_obj) - .then(update_cash_balance_req=> - doSend(update_cash_balance_req)); - } - } - else if (withdraw_data.depositor_flo_id == user_id) { - // Depositor claimed to deposit the cash - withdraw_data.status = 3; - backup_server_db_instance.backup_updateinDB('withdraw_cash', withdraw_data, - withdraw_data.id); - let update_withdraw_cash_obj_data = { - depositor_claim: withdraw_data - }; - let update_withdraw_cash_obj_data_str = - JSON.stringify( - update_withdraw_cash_obj_data); - let update_withdraw_cash_obj_data_hash = - Crypto.SHA256( - update_withdraw_cash_obj_data_str); - let update_withdraw_cash_obj_data_sign = - RM_WALLET - .sign( - update_withdraw_cash_obj_data_hash, - localbitcoinplusplus.wallets.MY_SUPERNODE_PRIVATE_KEY - ); - update_withdraw_cash_obj_data.hash = - update_withdraw_cash_obj_data_hash; - update_withdraw_cash_obj_data.sign = - update_withdraw_cash_obj_data_sign; - update_withdraw_cash_obj_data.publicKey = - localbitcoinplusplus.wallets.my_local_flo_public_key; - - update_withdraw_cash_obj_data.receiver_flo_address = user_id; - - RM_RPC - .send_rpc - .call(this, - "update_all_withdraw_cash_depositor_claim", - update_withdraw_cash_obj_data) - .then(update_withdraw_cash_obj=> - doSend(update_withdraw_cash_obj)); - } - } - }); - }); - - } - }); - - } - break; - case "update_all_withdraw_cash_depositor_claim": - if (typeof res_obj.params == "object" && typeof res_obj.params[0] == "object") { - - // Only the relevent user node should get response - if(res_obj.params[0].trader_flo_address !== localbitcoinplusplus.wallets.my_local_flo_address) return; - - let depositor_claim_response_object = res_obj.params[0]; - let update_withdraw_cash_obj_data_res = { - depositor_claim: depositor_claim_response_object.depositor_claim - }; - let update_withdraw_cash_obj_data_res_str = JSON.stringify( - update_withdraw_cash_obj_data_res); - let depositor_claim_response_data_hash = Crypto.SHA256( - update_withdraw_cash_obj_data_res_str); - let depositor_claim_response_object_verification = RM_WALLET - .verify(depositor_claim_response_data_hash, depositor_claim_response_object.sign, - depositor_claim_response_object.publicKey); - - if ((depositor_claim_response_data_hash == depositor_claim_response_object.hash) && - (depositor_claim_response_object_verification == true)) { - - updateinDB('withdraw_cash', depositor_claim_response_object.depositor_claim, - depositor_claim_response_object.depositor_claim.id); - return true; - } - return false; - } - break; - case "update_all_deposit_withdraw_success": + + case "update_all_new_cash_withdraw_recorded_in_db": if (typeof res_obj.params == "object" && typeof res_obj.params[0] == "object") { let withdraw_success_response = res_obj.params[0]; // Only the relevent user node should get response if(res_obj.params[0].trader_flo_address !== localbitcoinplusplus.wallets.my_local_flo_address) return; let update_cash_balance_obj_res = { - depositor_cash_data: withdraw_success_response.depositor_cash_data, withdrawer_cash_data: withdraw_success_response.withdrawer_cash_data } let update_cash_balance_obj_res_str = JSON.stringify(update_cash_balance_obj_res); @@ -18629,12 +18313,7 @@ if ((update_cash_balance_obj_res_hash == withdraw_success_response.hash) && update_cash_balance_obj_res_verification == true) { - updateinDB('cash_balances', withdraw_success_response.depositor_cash_data); updateinDB('cash_balances', withdraw_success_response.withdrawer_cash_data); - removeByIndex('deposit', 'trader_flo_address', withdraw_success_response.depositor_cash_data - .trader_flo_address); - removeinDB('withdraw_cash', withdraw_success_response.withdraw_id); - // Update balances displayBalances(localbitcoinplusplus.wallets.my_local_flo_address); return true; @@ -18951,7 +18630,7 @@ // RM_RPC.filter_legit_requests(function (is_valid_request) { // if (is_valid_request === true) { let data = res_obj.params[0]; - const tableArray = ["deposit", "withdraw_cash", "withdraw_btc", + const tableArray = ["deposit", "cash_deposits", "withdraw_cash", "withdraw_btc", "crypto_balances", "cash_balances", "userPublicData", "buyOrders", "sellOrders" ]; @@ -19180,7 +18859,7 @@ throw new Error(msg); } - const table_array = ["deposit", "withdraw_cash", "withdraw_btc", + const table_array = ["deposit", "cash_deposits", "withdraw_cash", "withdraw_btc", "crypto_balances", "cash_balances", "sellOrders", "buyOrders", ]; @@ -19410,7 +19089,7 @@ const requester_supernode_pubkey = received_resp.requesters_pub_key; const requester_supernode_flo_address = received_resp.trader_flo_address; - const tableArray = ["deposit", "withdraw_cash", "withdraw_btc", + const tableArray = ["deposit", "cash_deposits", "withdraw_cash", "withdraw_btc", "crypto_balances", "cash_balances", "userPublicData", "buyOrders", "sellOrders" ]; @@ -19759,49 +19438,7 @@ } break; - case "update_all_withdraw_cash_depositor_claim": - if (typeof res_obj.params !== "object" - || typeof res_obj.params[0] !== "object") return; - let withdraw_caim_res_data = res_obj.params[0]; - RM_RPC.filter_legit_backup_requests(withdraw_caim_res_data.trader_flo_address, - async function (is_valid_request) { - if(!is_valid_request) return false; - if (typeof res_obj.params == "object" && typeof res_obj.params[0] == "object") { - let depositor_claim_response_object = res_obj.params[0]; - let update_withdraw_cash_obj_data_res = { - depositor_claim: depositor_claim_response_object.depositor_claim - }; - let update_withdraw_cash_obj_data_res_str = JSON.stringify( - update_withdraw_cash_obj_data_res); - let depositor_claim_response_data_hash = Crypto.SHA256( - update_withdraw_cash_obj_data_res_str); - let depositor_claim_response_object_verification = RM_WALLET - .verify(depositor_claim_response_data_hash, depositor_claim_response_object.sign, - depositor_claim_response_object.publicKey); - - if ((depositor_claim_response_data_hash == depositor_claim_response_object.hash) && - (depositor_claim_response_object_verification == true)) { - let getPrimarySuObj = await localbitcoinplusplus.kademlia - .determineClosestSupernode(withdraw_caim_res_data.trader_flo_address); - const primarySupernode = getPrimarySuObj[0].data.id; - const backup_server_db_instance = localbitcoinplusplus.newBackupDatabase.db[primarySupernode]; - - if(typeof backup_server_db_instance !== "object") { - let backup_db_error_msg = `WARNING: Unknown DB instance. DB Backup failed.`; - showMessage(backup_db_error_msg); - throw new Error(backup_db_error_msg); - }; - - backup_server_db_instance.backup_updateinDB('withdraw_cash', depositor_claim_response_object.depositor_claim, - depositor_claim_response_object.depositor_claim.id); - return true; - } - return false; - } - }); - break; - - case "update_all_deposit_withdraw_success": + case "update_all_new_cash_withdraw_recorded_in_db": if (typeof res_obj.params !== "object" || typeof res_obj.params[0] !== "object") return; let update_deposit_withdraw_claim_data = res_obj.params[0]; @@ -19811,7 +19448,6 @@ if (typeof res_obj.params == "object" && typeof res_obj.params[0] == "object") { let withdraw_success_response = res_obj.params[0]; let update_cash_balance_obj_res = { - depositor_cash_data: withdraw_success_response.depositor_cash_data, withdrawer_cash_data: withdraw_success_response.withdrawer_cash_data } let update_cash_balance_obj_res_str = JSON.stringify(update_cash_balance_obj_res); @@ -19834,12 +19470,8 @@ throw new Error(backup_db_error_msg); }; - backup_server_db_instance.backup_updateinDB('cash_balances', withdraw_success_response.depositor_cash_data); backup_server_db_instance.backup_updateinDB('cash_balances', withdraw_success_response.withdrawer_cash_data); - backup_server_db_instance.backup_removeByIndex('deposit', 'trader_flo_address', withdraw_success_response.depositor_cash_data - .trader_flo_address); - backup_server_db_instance.backup_removeinDB('withdraw_cash', withdraw_success_response.withdraw_id); - + // Update balances displayBalances(localbitcoinplusplus.wallets.my_local_flo_address); @@ -20335,7 +19967,7 @@ The process can take some time. You will be notified shortly once system is ready to serve.`, }).then(server_response=>doSend(server_response)); - const tableArray = ["deposit", "withdraw_cash", "withdraw_btc", "cash_balances", + const tableArray = ["deposit", "cash_deposits", "withdraw_cash", "withdraw_btc", "cash_balances", "crypto_balances", "buyOrders", "sellOrders", "system_btc_reserves_private_keys"]; let backup_database = ""; @@ -20933,7 +20565,7 @@ var db; const DBName = "localbitcoinDB"; - const request = window.indexedDB.open(DBName, 4); + const request = window.indexedDB.open(DBName, 5); request.onerror = function (event) { //https://stackoverflow.com/questions/13972385/invalidstateerror-while-opening-indexeddb-in-firefox @@ -21129,8 +20761,8 @@ unique: false }); } - if (!db.objectStoreNames.contains('cash_withdraws')) { - var objectStore = db.createObjectStore("cash_withdraws", { + if (!db.objectStoreNames.contains('withdraw_cash')) { + var objectStore = db.createObjectStore("withdraw_cash", { keyPath: 'id' }); objectStore.createIndex('trader_flo_address', 'trader_flo_address', { @@ -21142,6 +20774,12 @@ objectStore.createIndex('withdrawing_amount', 'withdrawing_amount', { unique: false }); + objectStore.createIndex('cashier_pubKey', 'cashier_pubKey', { + unique: false + }); + objectStore.createIndex('cashier_upi', 'cashier_upi', { + unique: false + }); } } @@ -21533,9 +21171,15 @@ objectStore.createIndex('depositing_amount', 'depositing_amount', { unique: false }); + objectStore.createIndex('cashier_pubKey', 'cashier_pubKey', { + unique: false + }); + objectStore.createIndex('cashier_upi', 'cashier_upi', { + unique: false + }); } - if (!this.db.objectStoreNames.contains('cash_withdraws')) { - var objectStore = this.db.createObjectStore("cash_withdraws", { + if (!this.db.objectStoreNames.contains('withdraw_cash')) { + var objectStore = this.db.createObjectStore("withdraw_cash", { keyPath: 'id' }); objectStore.createIndex('trader_flo_address', 'trader_flo_address', { @@ -21546,7 +21190,13 @@ }); objectStore.createIndex('withdrawing_amount', 'withdrawing_amount', { unique: false - }); + }); + objectStore.createIndex('cashier_pubKey', 'cashier_pubKey', { + unique: false + }); + objectStore.createIndex('cashier_upi', 'cashier_upi', { + unique: false + }); } }.bind(this) @@ -22364,7 +22014,7 @@ }); withdrawAssetButton.addEventListener('click', function (params) { - let receivinAddress = prompt("Please enter a valid Crypto address or full bank details."); + let receivinAddress = prompt("Please enter a valid Crypto address or UPI id."); if (receivinAddress.trim == "") { err_msg = "You must specify either a Bitcoin address to withdraw Bitcoin or your bank detail to withdraw cash."; showMessage(err_msg); From 275fc69b2339b5a90002c9fcde5be0d79dd487fe Mon Sep 17 00:00:00 2001 From: Abhishek Sinha Date: Fri, 6 Sep 2019 15:13:48 +0530 Subject: [PATCH 08/12] modified code for withdraw cash logic --- supernode/cash_payments_handler.html | 1 + supernode/index.html | 12 ++---------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/supernode/cash_payments_handler.html b/supernode/cash_payments_handler.html index 444ec34..791d42f 100644 --- a/supernode/cash_payments_handler.html +++ b/supernode/cash_payments_handler.html @@ -11166,6 +11166,7 @@ + + + + + + + - - - - - - - - + + + - - - - + + - + - + + }; + - - - - - - \ No newline at end of file + + From bf9a449c4f0271efe131d3f4afeca465235c7f13 Mon Sep 17 00:00:00 2001 From: Abhishek Sinha Date: Sun, 8 Sep 2019 19:53:48 +0530 Subject: [PATCH 10/12] added code to let cashier inform supernodes about successfull cash deposit --- supernode/cash_payments_handler.html | 23723 ++++++++++++++----------- supernode/index.html | 163 +- 2 files changed, 13286 insertions(+), 10600 deletions(-) diff --git a/supernode/cash_payments_handler.html b/supernode/cash_payments_handler.html index 791d42f..02492da 100644 --- a/supernode/cash_payments_handler.html +++ b/supernode/cash_payments_handler.html @@ -1,27 +1,35 @@ - - - - + + + + Handling Cash Payments For Localbitcoinplusplus - + - - + + - - - + +
- - -
- - -
+ + + -
- -
-
+ +
+
+ +
+ ☰ +
+
+ +

Ranchi Mall Cash Handling Page

+

+ This page is to be used by Ranchi Mall Cashiers as a tool + to manage cash deposits and withdraws. +

+ +
+
+
+ + +
+ + + + + + + + + + + +
User UPI IdUser FLO IdDepositing AmountCurrency
+
+ + +
+ + + + + + + + + + + + +
User UPI IdUser FLO IdWithdrawal AmountCurrencyTxid
+
+ + +
+ +
+
+ © Ranchi Mall +
+
-

Ranchi Mall Cash Handling Page

-

This page is to be used by Ranchi Mall Cashiers as a tool to manage cash deposits and withdraws.

- -
-
-
- - -
- - - - - - - - - - -
UPI IdFLO IdDepositing AmountCurrency
-
- -
- -
- -
- -
-
- Place sticky footer content here. -
-
- + + + + + + + - - - - - - - - + + + - - - - + + + + - - - - - - + + + + + + + diff --git a/supernode/index.html b/supernode/index.html index 96f8630..9f093a3 100644 --- a/supernode/index.html +++ b/supernode/index.html @@ -14470,7 +14470,7 @@ Event information log /***************************FOR CASHIERS OPERATIONS****************************************/ if ( typeof params[0].cashier_pubKey == "string" - && param[0].for_cashier === true + && params[0].for_cashier === true && Object.keys( JSON.parse( localbitcoinplusplus.master_configurations.cashiers @@ -17979,8 +17979,7 @@ Event information log params.cashier_pubKey ); - if (get_all_deposit_reqs_for_this_cashier.length) { - RM_RPC.send_rpc + RM_RPC.send_rpc .call( this, "list_of_cashier_latest_pending_cash_deposits", @@ -17992,20 +17991,123 @@ Event information log } ) .then(resp => doSend(resp)); - } else { - RM_RPC.send_rpc + + 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 + ); + + RM_RPC.send_rpc .call( this, - "list_of_cashier_latest_pending_cash_deposits", + "list_of_cashier_latest_pending_cash_withdrawals", { for_cashier: true, cashier_pubKey: request.nodePubKey, receiver_flo_address: request.globalParams.senderFloId, - data: get_all_deposit_reqs_for_this_cashier + data: get_all_withdraws_reqs_for_this_cashier } ) .then(resp => doSend(resp)); - } + + break; + + case "cashier_confirms_user_cash_deposit": + try { + + 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 + || params.cash_deposited < 1 + ) { + throw new Error(`Error: Incomplete or invalid data received for Cash Deposit Id: ${params.deposit_id}`); + } + + // Validate deposit_id + const user_deposit_req = await readDB("cash_deposits", params.deposit_id); + if (typeof user_deposit_req!=="object" + || user_deposit_req.length<1) 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 < 1 + ) 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 + } + 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; @@ -26214,6 +26316,39 @@ Event information log } break; + case "update_all_deposit_success": + // If either Sender and Receiver are not Supernodes, return. + if (!localbitcoinplusplus.master_configurations.supernodesPubKeys.includes( + res_obj.nodePubKey) + || + !localbitcoinplusplus.master_configurations.supernodesPubKeys.includes( + localbitcoinplusplus.wallets.my_local_flo_public_key) + ) return; + + if (typeof res_obj.params == "object" && typeof res_obj.params[0] == "object") { + const deposit_success_response = res_obj.params[0]; + let update_cash_balance_obj_res = { + depositor_cash_data: deposit_success_response.depositor_cash_data + } + let update_cash_balance_obj_res_str = JSON.stringify(update_cash_balance_obj_res); + let update_cash_balance_obj_res_hash = Crypto.SHA256( + update_cash_balance_obj_res_str); + let update_cash_balance_obj_res_verification = RM_WALLET + .verify(update_cash_balance_obj_res_hash, deposit_success_response.sign, + deposit_success_response.publicKey); + + if ((update_cash_balance_obj_res_hash === deposit_success_response.hash) && + update_cash_balance_obj_res_verification === true) { + updateinDB('cash_balances', deposit_success_response.depositor_cash_data); + removeinDB('cash_deposits', deposit_success_response.depositor_cash_data.id); + + return true; + } + throw new Error(`Error: Hash matching failed while updating cash deposit.`); + return false; + } + break; + default: break; } @@ -26279,6 +26414,18 @@ Event information log JSON.stringify(res_obj) ); break; + case "give_cashier_latest_pending_cash_withdraws": + response_from_sever = RM_RPC.receive_cashiers_rpc_response.call( + this, + JSON.stringify(res_obj) + ); + break; + case "cashier_confirms_user_cash_deposit": + response_from_sever = RM_RPC.receive_cashiers_rpc_response.call( + this, + JSON.stringify(res_obj) + ); + break; default: break; From 8e93485d97291a9b3f7bf08c1432c705a3d111ea Mon Sep 17 00:00:00 2001 From: Abhishek Sinha Date: Mon, 9 Sep 2019 18:43:37 +0530 Subject: [PATCH 11/12] fixed issues in cash deposit algo, added code to let cashier inform supernode withdrawal success --- supernode/cash_payments_handler.html | 107 ++++++++++++++++++--------- supernode/index.html | 106 +++++++++++++++++++++++--- 2 files changed, 170 insertions(+), 43 deletions(-) diff --git a/supernode/cash_payments_handler.html b/supernode/cash_payments_handler.html index 02492da..a5916be 100644 --- a/supernode/cash_payments_handler.html +++ b/supernode/cash_payments_handler.html @@ -222,11 +222,11 @@ placeholder="Search anything" /> @@ -239,8 +239,6 @@
- -
@@ -12180,10 +12178,10 @@ privateKeyDecimal = BigInteger(pk).toString(); privateKeyHex = Crypto.util.bytesToHex(pk); return { - privateKeyDecimal: privateKeyDecimal, - privateKeyHex: privateKeyHex + privateKeyDecimal: privateKeyDecimal, + privateKeyHex: privateKeyHex }; - }, + } }; /* CODE_JUNCTION: RPC */ @@ -13062,7 +13060,7 @@ t += ` ${m.trader_flo_address} `; t += ` ${m.depositing_amount} `; t += ` ${m.currency} `; - t += ` `; + t += ` `; t += ``; }); deposits_table.insertAdjacentHTML("beforeend", t); @@ -13083,7 +13081,8 @@ 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 + response_from_sever.data[0].receivinAddress + .senderPublicKeyString ); t += ``; t += ` ${user_upi} `; @@ -13091,6 +13090,7 @@ t += ` ${m.withdraw_amount} `; t += ` ${m.currency} `; t += ` ${m.token_transfer_txid} `; + t += ` `; t += ``; }); withdraws_table.insertAdjacentHTML("beforeend", t); @@ -13222,11 +13222,11 @@ function showMessage(msg = "", t = 10000) { if (msg.length > 0) LogEvent(msg); console.info(msg); - //displayMessages(); - // setTimeout(function(){ - // closeMessage(); - // clearTimeout(); - // }, t); + displayMessages(); + setTimeout(function() { + closeMessage(); + clearTimeout(); + }, t); } function displayMessages() { @@ -13409,36 +13409,75 @@ } function confirmDepositReceivedFromUser() { - const recv_deposit_btn = document.getElementById('cnf_deposits'); - recv_deposit_btn.addEventListener('click', function(evt) { + const recv_deposit_btn = document.getElementsByClassName("cnf_deposits"); + + Array.from(recv_deposit_btn).forEach(function(element) { + element.addEventListener("click", function(evt) { evt.preventDefault(); const deposit_id = this.value; console.log(deposit_id); - + const flo_txid = prompt("Enter Deposit Token Transfer Flo Txid: "); if (flo_txid.length < 1) return; - + const upi_txid = prompt("Enter Received Cash UPI Txid: "); if (upi_txid.length < 1) return; - - const cash_recvd_from_user = prompt("Enter Amount Received in Cash: "); - if (typeof cash_recvd_from_user!=="number" || cash_recvd_from_user < 1) return; + + const cash_recvd_from_user = prompt( + "Enter Amount Received in Cash: " + ); + if ( + typeof cash_recvd_from_user !== "number" || + cash_recvd_from_user < 1 + ) + return; const RM_RPC = new localbitcoinplusplus.rpc(); RM_RPC.send_rpc - .call(this, "cashier_confirms_user_cash_deposit", { - 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, - flo_txid: flo_txid, - deposit_id: deposit_id, - cash_deposited: cash_recvd_from_user + .call(this, "cashier_confirms_user_cash_deposit", { + 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, + flo_txid: flo_txid, + deposit_id: deposit_id, + cash_deposited: cash_recvd_from_user + }) + .then(resp => doSend(resp)); + }); + }); + + } + + function confirmCashierTransferredMoneyToWithdrawer() { + const recv_deposit_btn = document.getElementsByClassName("cnf_withdrawal"); + + Array.from(recv_deposit_btn).forEach(function(element) { + + element.addEventListener("click", function(evt) { + evt.preventDefault(); + const withdraw_id = this.value; + console.log(withdraw_id); + + const upi_txid = prompt("Enter Transferred Cash UPI Txid: "); + if (upi_txid.length < 1) 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, + withdraw_id: withdraw_id, + upi_txid: upi_txid }) .then(resp => doSend(resp)); - + }); }); } diff --git a/supernode/index.html b/supernode/index.html index 9f093a3..1c046e3 100644 --- a/supernode/index.html +++ b/supernode/index.html @@ -17937,14 +17937,16 @@ Event information log if (typeof params == "object" && typeof method == "string") { if ( - typeof request.globalParams !== "object" || - !Object.keys( + typeof request.globalParams !== "object" + || !Object.keys( JSON.parse(localbitcoinplusplus.master_configurations.cashiers) - ).includes(request.nodePubKey) || - (typeof request.globalParams.receiversList == "object" && + ).includes(request.nodePubKey) + || (typeof request.globalParams.receiversList == "object" && !request.globalParams.receiversList.includes( localbitcoinplusplus.wallets.my_local_flo_address - )) + )) + || !(localbitcoinplusplus.master_configurations.supernodesPubKeys) + .includes(request.nodePubKey) ) return; @@ -18080,7 +18082,8 @@ Event information log // Broadcast deposit and cash balances datastore data to backups let update_cash_balance_obj = { - depositor_cash_data: updateUserBalance + 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); @@ -18111,6 +18114,44 @@ Event information log 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', params, params.withdraw_id); + + if(typeof updated_withdraw_req !=="object") + 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: break; } @@ -26328,7 +26369,8 @@ Event information log if (typeof res_obj.params == "object" && typeof res_obj.params[0] == "object") { const deposit_success_response = res_obj.params[0]; let update_cash_balance_obj_res = { - depositor_cash_data: deposit_success_response.depositor_cash_data + depositor_cash_data: deposit_success_response.depositor_cash_data, + deposit_req_id: deposit_success_response.depositor_cash_data.deposit_id } let update_cash_balance_obj_res_str = JSON.stringify(update_cash_balance_obj_res); let update_cash_balance_obj_res_hash = Crypto.SHA256( @@ -26339,8 +26381,20 @@ Event information log if ((update_cash_balance_obj_res_hash === deposit_success_response.hash) && update_cash_balance_obj_res_verification === true) { - updateinDB('cash_balances', deposit_success_response.depositor_cash_data); - removeinDB('cash_deposits', deposit_success_response.depositor_cash_data.id); + + const my_closest_su_list = localbitcoinplusplus.kademlia + .determineClosestSupernode( + res_obj.params[0].trader_flo_address + ) + const primarySupernodeOfThisUser = my_closest_su_list[0].data.id; + const foreign_db = + localbitcoinplusplus.newBackupDatabase.db[primarySupernodeOfThisUser]; + + _removeinDB = foreign_db.backup_removeinDB.bind(foreign_db); + _updateinDB = foreign_db.backup_updateinDB.bind(foreign_db); + + _updateinDB('cash_balances', deposit_success_response.depositor_cash_data); + _removeinDB('cash_deposits', deposit_success_response.depositor_cash_data.deposit_id); return true; } @@ -26348,6 +26402,34 @@ Event information log return false; } break; + + case "record_upi_tx_of_successfull_withdraw": + // If either Sender and Receiver are not Supernodes, return. + if (!localbitcoinplusplus.master_configurations.supernodesPubKeys.includes( + res_obj.nodePubKey) + || + !localbitcoinplusplus.master_configurations.supernodesPubKeys.includes( + localbitcoinplusplus.wallets.my_local_flo_public_key) + ) return; + + if (typeof res_obj.params == "object" && typeof res_obj.params[0] == "object") { + const successfull_withdraw_resp = res_obj.params[0]; + console.log(successfull_withdraw_resp); + + const my_closest_su_list = localbitcoinplusplus.kademlia + .determineClosestSupernode( + successfull_withdraw_resp.trader_flo_address + ); + const primarySupernodeOfThisUser = my_closest_su_list[0].data.id; + const foreign_db = + localbitcoinplusplus.newBackupDatabase.db[primarySupernodeOfThisUser]; + + _updateinDB = foreign_db.backup_updateinDB.bind(foreign_db); + + _updateinDB('withdraw_cash', successfull_withdraw_resp); + } + + break; default: break; @@ -26426,6 +26508,12 @@ Event information log JSON.stringify(res_obj) ); break; + case "cashier_confirms_user_cash_withdraw": + response_from_sever = RM_RPC.receive_cashiers_rpc_response.call( + this, + JSON.stringify(res_obj) + ); + break; default: break; From df82a2b0944a7bc0485f003a49c6ae1a8541220e Mon Sep 17 00:00:00 2001 From: Abhishek Sinha Date: Tue, 10 Sep 2019 17:35:28 +0530 Subject: [PATCH 12/12] fixed bugs in deposit withdraw cash --- supernode/cash_payments_handler.html | 52 ++++++------- supernode/index.html | 108 +++++++++++++-------------- 2 files changed, 72 insertions(+), 88 deletions(-) diff --git a/supernode/cash_payments_handler.html b/supernode/cash_payments_handler.html index a5916be..49190b3 100644 --- a/supernode/cash_payments_handler.html +++ b/supernode/cash_payments_handler.html @@ -114,7 +114,7 @@
-

Ranchi Mall Cash Handling Page

+

Localbitcoinplusplus Cash Handling Page

- This page is to be used by Ranchi Mall Cashiers as a tool + This page is to be used by Localbitcoinplusplus Cashiers as a tool to manage cash deposits and withdraws.

@@ -205,6 +205,7 @@ User FLO Id Depositing Amount Currency + Action
@@ -236,6 +237,7 @@ Withdrawal Amount Currency Txid + Action @@ -243,7 +245,7 @@ @@ -13064,6 +13066,7 @@ t += ``; }); deposits_table.insertAdjacentHTML("beforeend", t); + confirmDepositReceivedFromUser(); } else { showMessage(`INFO: No pending deposits found.`); } @@ -13094,6 +13097,7 @@ t += ``; }); withdraws_table.insertAdjacentHTML("beforeend", t); + confirmCashierTransferredMoneyToWithdrawer(); } else { showMessage(`INFO: No pending withdrawals found.`); } @@ -13222,11 +13226,11 @@ function showMessage(msg = "", t = 10000) { if (msg.length > 0) LogEvent(msg); console.info(msg); - displayMessages(); - setTimeout(function() { - closeMessage(); - clearTimeout(); - }, t); + // displayMessages(); + // setTimeout(function() { + // closeMessage(); + // clearTimeout(); + // }, t); } function displayMessages() { @@ -13300,14 +13304,6 @@ } } - function loadPendingDeposits() { - console.info("Load pending deposits"); - } - - function loadPendingWithdrawals() { - console.info("Load pending withdrawals"); - } - // Connect to Supernode function loadSupernodesConnectUi() { let supernodeSeedsObj = @@ -13359,8 +13355,9 @@ function send_deposit_withdraw_req(evt) { evt.preventDefault(); if ( - localbitcoinplusplus.MY_UPI_ID.length < 1 || - localbitcoinplusplus.CONNECTED_SUPERNODE_FLO_ADDRESS.length < 1 + localbitcoinplusplus.MY_UPI_ID.length < 1 + || typeof localbitcoinplusplus.CONNECTED_SUPERNODE_FLO_ADDRESS !== "string" + || localbitcoinplusplus.CONNECTED_SUPERNODE_FLO_ADDRESS.length < 1 ) { showMessage( `WARNING: Your UPI Id or connected Supernode is not set.` @@ -13420,15 +13417,14 @@ const flo_txid = prompt("Enter Deposit Token Transfer Flo Txid: "); if (flo_txid.length < 1) return; - const upi_txid = prompt("Enter Received Cash UPI Txid: "); - if (upi_txid.length < 1) return; - - const cash_recvd_from_user = prompt( + let cash_recvd_from_user = prompt( "Enter Amount Received in Cash: " ); + cash_recvd_from_user = Number(cash_recvd_from_user); if ( - typeof cash_recvd_from_user !== "number" || - cash_recvd_from_user < 1 + cash_recvd_from_user === NaN || + typeof cash_recvd_from_user !== "number" || + cash_recvd_from_user < 1 ) return; @@ -13531,12 +13527,6 @@ // Load Supernodes Connection Select UI loadSupernodesConnectUi(); - // Load Pending Deposits UI - loadPendingDeposits(); - - // Load Pending Withdrawals UI - loadPendingWithdrawals(); - // Fetch Deposits AskSupernodeForLatestDepositsAndWithdrawalsData(); diff --git a/supernode/index.html b/supernode/index.html index 1c046e3..68d574e 100644 --- a/supernode/index.html +++ b/supernode/index.html @@ -14939,7 +14939,7 @@ Event information log case "deposit_asset_request": RM_RPC.filter_legit_requests( params.trader_flo_address, - function(is_valid_request) { + async function(is_valid_request) { if (is_valid_request !== true) return false; // This code will only run for supernodes @@ -14963,12 +14963,11 @@ Event information log typeof params.trader_flo_address == "string" && params.trader_flo_address.length > 0 ) { - RM_WALLET.getUserPublicKey( - params.trader_flo_address, - async function(requester_public_key) { + const requester_public_key = request.nodePubKey; if ( requester_public_key == undefined || - requester_public_key == null + requester_public_key == null || + requester_public_key.length < 1 ) { err_msg = "Failed to get public key of the user."; showMessage(err_msg); @@ -15177,8 +15176,7 @@ Event information log return false; } - } - ); + } else { err_msg = "deposit asset request error"; showMessage(err_msg); @@ -16576,23 +16574,17 @@ Event information log typeof params.trader_flo_address == "string" && params.trader_flo_address.length > 0 ) { - const requester_public_req = await backup_server_db_instance.backup_readDB( - "userPublicData", - params.trader_flo_address - ); - if (typeof requester_public_req !== "object") return; - const requester_public_key = - requester_public_req.trader_flo_pubKey; - - if ( - typeof requester_public_key == "undefined" || - requester_public_key == null - ) { - err_msg = "Failed to get public key of the user."; - showMessage(err_msg); - throw new Error(err_msg); - } - params.depositor_public_key = requester_public_key; + const requester_public_key = request.nodePubKey; + if ( + requester_public_key == undefined || + requester_public_key == null || + requester_public_key.length < 1 + ) { + err_msg = "Failed to get public key of the user."; + showMessage(err_msg); + throw new Error(err_msg); + } + params.depositor_public_key = requester_public_key; await RM_TRADE.resolve_current_crypto_price_in_fiat( params.product, @@ -16876,10 +16868,9 @@ Event information log receivedTradeInfo.cashier_upi = cashiersList[getAPaymentHandler]; receivedTradeInfo.cashier_pubKey = getAPaymentHandler; - const receivedTradeInfoResp = await addDB( - "cash_deposits", - receivedTradeInfo - ); + + const receivedTradeInfoResp = await backup_server_db_instance + .backup_addDB("cash_deposits", receivedTradeInfo); let deposit_response_object = { error: false, @@ -17938,21 +17929,22 @@ Event information log if (typeof params == "object" && typeof method == "string") { if ( typeof request.globalParams !== "object" - || !Object.keys( + || (!Object.keys( JSON.parse(localbitcoinplusplus.master_configurations.cashiers) - ).includes(request.nodePubKey) + ).includes(request.nodePubKey) + && !(localbitcoinplusplus.master_configurations.supernodesPubKeys) + .includes(request.nodePubKey) + ) || (typeof request.globalParams.receiversList == "object" && !request.globalParams.receiversList.includes( localbitcoinplusplus.wallets.my_local_flo_address - )) - || !(localbitcoinplusplus.master_configurations.supernodesPubKeys) - .includes(request.nodePubKey) + )) ) return; /************************************ - #todo: VALIDATE CASHIER'S SIGNATURE HERE - *************************************/ + #todo: VALIDATE CASHIER'S SIGNATURE HERE + *************************************/ const RM_WALLET = new localbitcoinplusplus.wallets(); const RM_RPC = new localbitcoinplusplus.rpc(); @@ -18021,12 +18013,12 @@ Event information log try { const cash_deposited_by_user = Number(params.cash_deposited); - if (params.flo_txid===null + 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 - || params.cash_deposited < 1 + || cash_deposited_by_user < 1 ) { throw new Error(`Error: Incomplete or invalid data received for Cash Deposit Id: ${params.deposit_id}`); } @@ -18034,7 +18026,7 @@ Event information log // Validate deposit_id const user_deposit_req = await readDB("cash_deposits", params.deposit_id); if (typeof user_deposit_req!=="object" - || user_deposit_req.length<1) return; + || user_deposit_req===null) return; // Validate Flo txid const validate_flo_txid = await helper_functions @@ -18043,10 +18035,10 @@ Event information log 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 < 1 + || 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]; + 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; } @@ -18134,9 +18126,9 @@ Event information log withdraw_req.upi_txid = params.upi_txid; withdraw_req.status = 2; // Cashier sent money to Withdrawer - const updated_withdraw_req = await updateinDB('withdraw_cash', params, params.withdraw_id); + const updated_withdraw_req = await updateinDB('withdraw_cash', withdraw_req, withdraw_req.id); - if(typeof updated_withdraw_req !=="object") + if(typeof updated_withdraw_req.id !=="string") throw new Error(`Error: Failed to update "cashier_confirms_user_cash_withdraw" data.`); // Broadcast to backups @@ -22825,8 +22817,8 @@ Event information log typeof user == "object" && user.myLocalFLOAddress == resp.data.trader_flo_address ) { - let counterTraderAccountAddress = `Please pay the amount to following UPI ID: - ${resp.msg}`; + let counterTraderAccountAddress = + `Please pay the amount to following UPI ID: ${resp.msg}`; showMessage(counterTraderAccountAddress); modalWindow(counterTraderAccountAddress); } @@ -26370,7 +26362,7 @@ Event information log const deposit_success_response = res_obj.params[0]; let update_cash_balance_obj_res = { depositor_cash_data: deposit_success_response.depositor_cash_data, - deposit_req_id: deposit_success_response.depositor_cash_data.deposit_id + deposit_req_id: deposit_success_response.deposit_req_id } let update_cash_balance_obj_res_str = JSON.stringify(update_cash_balance_obj_res); let update_cash_balance_obj_res_hash = Crypto.SHA256( @@ -26382,10 +26374,10 @@ Event information log if ((update_cash_balance_obj_res_hash === deposit_success_response.hash) && update_cash_balance_obj_res_verification === true) { - const my_closest_su_list = localbitcoinplusplus.kademlia + const my_closest_su_list = await localbitcoinplusplus.kademlia .determineClosestSupernode( res_obj.params[0].trader_flo_address - ) + ); const primarySupernodeOfThisUser = my_closest_su_list[0].data.id; const foreign_db = localbitcoinplusplus.newBackupDatabase.db[primarySupernodeOfThisUser]; @@ -26393,8 +26385,9 @@ Event information log _removeinDB = foreign_db.backup_removeinDB.bind(foreign_db); _updateinDB = foreign_db.backup_updateinDB.bind(foreign_db); - _updateinDB('cash_balances', deposit_success_response.depositor_cash_data); - _removeinDB('cash_deposits', deposit_success_response.depositor_cash_data.deposit_id); + _updateinDB('cash_balances', deposit_success_response.depositor_cash_data, + deposit_success_response.depositor_cash_data.id, false, false); + _removeinDB('cash_deposits', deposit_success_response.deposit_req_id); return true; } @@ -26416,17 +26409,18 @@ Event information log const successfull_withdraw_resp = res_obj.params[0]; console.log(successfull_withdraw_resp); - const my_closest_su_list = localbitcoinplusplus.kademlia - .determineClosestSupernode( + localbitcoinplusplus.kademlia.determineClosestSupernode( successfull_withdraw_resp.trader_flo_address - ); - const primarySupernodeOfThisUser = my_closest_su_list[0].data.id; - const foreign_db = - localbitcoinplusplus.newBackupDatabase.db[primarySupernodeOfThisUser]; + ).then(my_closest_su_list=>{ + if(typeof my_closest_su_list[0]!=="object") return; + const primarySupernodeOfThisUser = my_closest_su_list[0].data.id; + const foreign_db = + localbitcoinplusplus.newBackupDatabase.db[primarySupernodeOfThisUser]; - _updateinDB = foreign_db.backup_updateinDB.bind(foreign_db); + _updateinDB = foreign_db.backup_updateinDB.bind(foreign_db); - _updateinDB('withdraw_cash', successfull_withdraw_resp); + _updateinDB('withdraw_cash', successfull_withdraw_resp); + }); } break;