From 43f596020bedfd0153a8fdaaadb8d6f6ac58c757 Mon Sep 17 00:00:00 2001 From: Abhishek Sinha Date: Sun, 24 Nov 2019 19:48:56 +0530 Subject: [PATCH] simplified cashiers deposit logic --- supernode/cash_payments_handler.html | 246 ++++++++++++++++++++++----- supernode/index.html | 21 +-- 2 files changed, 216 insertions(+), 51 deletions(-) diff --git a/supernode/cash_payments_handler.html b/supernode/cash_payments_handler.html index aad4039..9a377c3 100644 --- a/supernode/cash_payments_handler.html +++ b/supernode/cash_payments_handler.html @@ -12233,7 +12233,171 @@ privateKeyDecimal: privateKeyDecimal, privateKeyHex: privateKeyHex }; - } + }, + sendTransaction( + crypto_type, + utxo_addr, + utxo_addr_wif, + receiver_address, + receiving_amount, + change_adress, + custom_floData = "" + ) { + return new promise((resolve, reject)=>{ + + let blockchain_explorer; + let miners_fee = 0.0003; + const miner_fee_obj = JSON.parse( + localbitcoinplusplus.master_configurations.miners_fee + ); + if (crypto_type == "BTC") { + blockchain_explorer = localbitcoinplusplus.server.btc_mainnet; + miners_fee = miner_fee_obj.btc; + } else if (crypto_type == "BTC_TEST") { + blockchain_explorer = localbitcoinplusplus.server.btc_testnet; + miners_fee = miner_fee_obj.btc; + } else if (crypto_type == "FLO") { + blockchain_explorer = localbitcoinplusplus.server.flo_mainnet; + miners_fee = miner_fee_obj.flo; + } else if (crypto_type == "FLO_TEST") { + blockchain_explorer = localbitcoinplusplus.server.flo_testnet; + miners_fee = miner_fee_obj.flo; + } + + if (typeof blockchain_explorer !== "string") { + showMessage( + `WARNING: Please select cryptocurrency/fiat value from select bar.` + ); + return false; + } + + let url = `${blockchain_explorer}/api/addr/${utxo_addr}/utxo`; + console.log(url); + let err_msg; + + helper_functions + .ajaxGet(url) + .then(utxo_list => { + if (utxo_list.length > 0) { + try { + let btc_eq_receiving_amount = Number(receiving_amount); + btc_eq_receiving_amount = Number( + btc_eq_receiving_amount.toFixed(8) + ); + + let trx = bitjs[crypto_type].transaction(); + let sum = 0; + + for (var key in utxo_list) { + if (utxo_list[key].confirmations !== 0) { + var obj = utxo_list[key]; + sum += obj.amount; + + if (btc_eq_receiving_amount <= sum) { + trx.addinput(obj.txid, obj.vout, obj.scriptPubKey); + break; + } else { + trx.addinput(obj.txid, obj.vout, obj.scriptPubKey); + } + } + } + + if (sum <= 0) { + console.log(utxo_list); + throw new Error("ERROR: No amount found in UTXO."); + } + + // Output cannot be greater than input + if (sum < btc_eq_receiving_amount) { + 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) { + trx.addoutput(change_adress, change_amount); + } + 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 + } + + try { + console.log(trx); + + let signedTxHash = trx.sign(utxo_addr_wif, 1); //SIGHASH_ALL DEFAULT 1 + showMessage(`Signed Transaction Hash: ${signedTxHash}`); + console.log(signedTxHash); + + var http = new XMLHttpRequest(); + var tx_send_url = `${blockchain_explorer}/api/tx/send`; + var params = `{"rawtx":"${signedTxHash}"}`; + http.open("POST", tx_send_url, true); + http.setRequestHeader("Content-type", "application/json"); + http.onreadystatechange = function () { + //Call a function when the state changes. + if (http.readyState == 4) { + if (http.status == 200) { + console.log(http.responseText); + let response_obj = { + signedTxHash: signedTxHash, + txid: http.responseText + }; + resolve(response_obj); + } else { + let response_obj = { + signedTxHash: signedTxHash, + txid: "" + }; + resolve(response_obj); + } + } + }; + http.onerror = function () { + let response_obj = { + signedTxHash: signedTxHash, + txid: "" + }; + resolve(response_obj); + }; + http.send(params); + } catch (error) { + showMessage(error); + reject(error); + throw new Error(error); + } + } catch (error) { + reject(error); + throw new Error(error); + } + } + }) + .catch(e => + console.error( + `ERROR: Failed to send tx from utxo ${utxo_addr}: ${e}` + ) + ); + }); + }, }; /* CODE_JUNCTION: RPC */ @@ -13157,20 +13321,19 @@ for (const m of responseData.responseData.data) { let su_res = await localbitcoinplusplus.kademlia.determineClosestSupernode(m.trader_flo_address); let closestSupernode = su_res[0].data.id; - t += ``; + t += ``; t += ` ${m.user_upi} `; t += ` ${m.trader_flo_address} `; t += ` ${m.depositing_amount} `; t += ` ${m.currency} `; t += ` - ${closestSupernode}_${responseData.responseData.requesting_supernode} + + `; t += ``; - // Find Supernode of the user - confirmDepositReceivedFromUser(); } - deposits_table.insertAdjacentHTML("beforeend", t); + confirmDepositReceivedFromUser(); })(); break; @@ -13193,12 +13356,12 @@ v += ` ${m.currency} `; v += ` ${m.token_transfer_txid} `; v += ` - ${closestSupernode}_${responseData.responseData.requesting_supernode} + `; v += ``; - confirmCashierTransferredMoneyToWithdrawer(); } withdraws_table.insertAdjacentHTML("beforeend", v); + confirmCashierTransferredMoneyToWithdrawer(); })(); break; @@ -13209,7 +13372,7 @@ async function onMessage(evt) { var response = evt.data || evt; - console.log(response); + console.log(response); if (!onMessageAcceptTest("whetherForCashier", {searchString:"__FOR__CASHIER__",data:response})) return; console.log("RESPONSE: " + response); @@ -13233,21 +13396,22 @@ if(onMessageAcceptTest("checkIfObject", { data:res_obj.globalParams.receiversList, - }) && - !onMessageAcceptTest("meInReceiverList", { + }) + ) { + if(!onMessageAcceptTest("meInReceiverList", { receiversList:res_obj.globalParams.receiversList, my_local_flo_address:localbitcoinplusplus.wallets.my_local_flo_address - }) - ) return; + })) return; + } if(!onMessageAcceptTest("receiverIDisMine", { receiverFloId:res_obj.globalParams.receiverFloId, })) return; - const isIncomingMessageValid = await validateIncomingMessage(res); - console.log("isIncomingMessageValid: ", isIncomingMessageValid); + const isIncomingMessageValid = await validateIncomingMessage(res); + console.log("isIncomingMessageValid: ", isIncomingMessageValid); - if (!isIncomingMessageValid) return; + if (!isIncomingMessageValid) return; if(!onMessageAcceptTest("isDataString", { param:res_obj.globalParams.senderFloId, @@ -13259,9 +13423,6 @@ let response_from_sever; - // const RM_WALLET = new localbitcoinplusplus.wallets(); - // const RM_RPC = new localbitcoinplusplus.rpc(); - switch (res_obj.method) { case "list_of_cashier_latest_pending_cash_deposits": @@ -13558,34 +13719,44 @@ function confirmDepositReceivedFromUser() { const recv_deposit_btn = document.getElementsByClassName("cnf_deposits"); - + const RM_WALLET = new localbitcoinplusplus.wallets; Array.from(recv_deposit_btn).forEach(function(element) { - element.addEventListener("click", function(evt) { + element.addEventListener("click", async function(evt) { //evt.preventDefault(); const deposit_id = this.value; - const req_info = document.getElementById(`depositSpan${deposit_id}`); - const req_info_arr = req_info.innerText.split("_"); + const req_info_arr = req_info.value.split("_"); const websocket_name = req_info_arr[0]; const requesting_supernode = req_info_arr[1]; + const depositorInfo = document.getElementById(`depositorInfoSpan${deposit_id}`); + const depositorInfoVals = depositorInfo.getElementsByTagName('td'); + const token_transfer_statement = `transfer ${depositorInfoVals[2].innerText} rupee# on behalf of ${depositorInfoVals[1].innerText}`; + const tx_amount = 0.001; + if(typeof websocket_name!=="string" || typeof requesting_supernode!=="string") return; - const flo_txid = prompt("Enter Deposit Token Transfer Flo Txid: "); - if (flo_txid.length < 1) return; + const confirmTx = confirm(token_transfer_statement); + if(!confirmTx) return; - let cash_recvd_from_user = prompt( - "Enter Amount Received in Cash: " + let flo_txid = ''; + + const flo_tx = await RM_WALLET.sendTransaction( + localbitcoinplusplus.assets.FLO, + localbitcoinplusplus.wallets.my_local_flo_address, + localbitcoinplusplus.wallets.MY_SUPERNODE_PRIVATE_KEY, + requesting_supernode, + tx_amount, + localbitcoinplusplus.wallets.my_local_flo_address, + token_transfer_statement ); - cash_recvd_from_user = Number(cash_recvd_from_user); - if ( - cash_recvd_from_user === NaN || - typeof cash_recvd_from_user !== "number" || - cash_recvd_from_user < 1 - ) - return; - - //const RM_RPC = new localbitcoinplusplus.rpc(); + if (typeof flo_tx.txid == "string" && + flo_tx.txid.length > 0 + ) { + resp_obj = JSON.parse(flo_tx.txid); + flo_txid = resp_obj.txid.result || resp_obj.txid; + } + if (typeof flo_txid!=="string" || flo_txid.length < 1) return; let req_body = { trader_flo_address: @@ -13595,7 +13766,6 @@ receiver_flo_address: requesting_supernode, flo_txid: flo_txid, deposit_id: deposit_id, - cash_deposited: cash_recvd_from_user, parent_supernode: websocket_name, } @@ -13619,7 +13789,7 @@ evt.preventDefault(); const withdraw_id = this.value; const req_info = document.getElementById(`withdrawSpan${deposit_id}`); - const req_info_arr = req_info.innerText.split("_"); + const req_info_arr = req_info.value.split("_"); const websocket_name = req_info_arr[0]; const requesting_supernode = req_info_arr[1]; diff --git a/supernode/index.html b/supernode/index.html index 7affdb0..c7211b9 100644 --- a/supernode/index.html +++ b/supernode/index.html @@ -18468,13 +18468,10 @@ 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 - || cash_deposited_by_user < 1 ) { throw new Error(`Error: Incomplete or invalid data received for Cash Deposit Id: ${params.deposit_id}`); } @@ -18504,9 +18501,8 @@ // Validate Flo txid const validate_flo_txid = await helper_functions - .ajaxGet(`${flo_api_testnet}/api/v1.0/getTransactionDetails/${params.flo_txid}`); - - /** IMP: CHECK WHETHER VIN IS A VALID SUPERNODE FLO ID HERE **/ + .ajaxGet(`${localbitcoinplusplus.server + .flo_api_testnet}/api/v1.0/getTransactionDetails/${params.flo_txid}`); if(typeof validate_flo_txid !== "object" || typeof validate_flo_txid.transactionDetails !== "object" @@ -18514,14 +18510,13 @@ || validate_flo_txid.transactionDetails.floData.length < 5 // without ':text' ) throw new Error(`Error: Txid ${params.flo_txid} not found in Blockchain.`); - let amount_deposited = Number(validate_flo_txid.transactionDetails.floData.match(/\d+/g)[0]); - - // if(typeof amount_deposited !== "number" || amount_deposited < 1 || amount_deposited===NaN) { - // amount_deposited = cash_deposited_by_user; - // } + /** IMP: CHECK WHETHER VIN IS A VALID SUPERNODE FLO ID HERE **/ + const cashiers_pub_keys = Object.keys(JSON.parse(localbitcoinplusplus.master_configurations.cashiers)); + const cashiers_flo_keys = Object.keys(cashiers_pub_keys).map(m=>bitjs["FLO_TEST"].pubkey2address(m)); + if(!cashiers_flo_keys.includes(validate_flo_txid.transactionDetails.vin[0].addr)) return; - amount_deposited = Number(amount_deposited); - + let amount_deposited = Number(validate_flo_txid.transactionDetails.floData.match(/\d+/g)[0]); + // 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);