diff --git a/FLO_webWallet_mainnet.html b/FLO_webWallet_mainnet.html
index e6dc981..e06014a 100644
--- a/FLO_webWallet_mainnet.html
+++ b/FLO_webWallet_mainnet.html
@@ -8361,7 +8361,7 @@
},
//Write Data into blockchain
- writeData: function (senderAddr, Data, PrivKey, receiverAddr = floGlobals.adminID) {
+ writeData: function (senderAddr, Data, PrivKey, receiverAddr) {
return new Promise((resolve, reject) => {
this.sendTx(senderAddr, receiverAddr, floGlobals.sendAmt, PrivKey, Data)
.then(txid => resolve(txid))
@@ -8409,12 +8409,234 @@
}
});
},
-
+
+
+ //merge all UTXOs of a given floID into a single UTXO
+ mergeUTXOs: function (floID, privKey, floData = '') {
+ return new Promise((resolve, reject) => {
+ if (!floCrypto.validateAddr(floID))
+ return reject(`Invalid floID`);
+ if (!floCrypto.verifyPrivKey(privKey, floID))
+ return reject("Invalid Private Key")
+
+ var trx = bitjs.transaction();
+ var utxoAmt = 0.0;
+ var fee = floGlobals.fee;
+ this.promisedAPI(`api/addr/${floID}/utxo`).then(utxos => {
+ for (var i = utxos.length - 1; i >= 0; i--) {
+ if (utxos[i].confirmations) {
+ trx.addinput(utxos[i].txid, utxos[i].vout, utxos[i]
+ .scriptPubKey)
+ utxoAmt += utxos[i].amount;
+ }
+ }
+ trx.addoutput(floID, utxoAmt - fee);
+ trx.addflodata(floData);
+ var signedTxHash = trx.sign(privKey, 1);
+ this.broadcastTx(signedTxHash)
+ .then(txid => resolve(txid))
+ .catch(error => reject(error))
+ }).catch(error => reject(error))
+ })
+ },
+
+ /**Write data into blockchain from (and/or) to multiple floID
+ * @param {Array} senderPrivKeys List of sender private-keys
+ * @param {string} data FLO data of the txn
+ * @param {Array} receivers List of receivers
+ * @param {float} sendAmt (optional) amount to be sent to receivers (default value: floGlobals.sendAmt)
+ * @return {Promise}
+ */
+ writeDataMultiple: function (senderPrivKeys, data, receivers, preserveRatio = true){
+ return new Promise((resolve, reject) => {
+ if (!Array.isArray(senderPrivKeys))
+ return reject("Invalid senderPrivKeys: SenderPrivKeys must be Array")
+ if(!preserveRatio){
+ let tmp = {};
+ let amount = (floGlobals.sendAmt * receivers.length) / senderPrivKeys.length;
+ senderPrivKeys.forEach(key => tmp[key] = amount);
+ senderPrivKeys = tmp
+ }
+ if (!Array.isArray(receivers))
+ return reject("Invalid receivers: Receivers must be Array")
+ else {
+ let tmp = {};
+ let amount = floGlobals.sendAmt;
+ receivers.forEach(floID => tmp[floID] = amount);
+ receivers = tmp
+ }
+ if (typeof data != "string")
+ data = JSON.stringify(data);
+ this.sendTxMultiple(senderPrivKeys, receivers, data)
+ .then(txid => resolve(txid))
+ .catch(error => reject(error))
+ })
+ },
+
+ /**Send Tx from (and/or) to multiple floID
+ * @param {Array or Object} senderPrivKeys List of sender private-key (optional: with coins to be sent)
+ * @param {Object} receivers List of receivers with respective amount to be sent
+ * @param {string} floData FLO data of the txn
+ * @return {Promise}
+ */
+ sendTxMultiple: function (senderPrivKeys, receivers, floData = '') {
+ return new Promise((resolve, reject) => {
+
+ let senders = {}, preserveRatio;
+ //check for argument validations
+ try{
+ let invalids = {
+ InvalidSenderPrivKeys: [],
+ InvalidSenderAmountFor: [],
+ InvalidReceiverIDs: [],
+ InvalidReceiveAmountFor: []
+ }
+ let inputVal = 0, outputVal = 0;
+ //Validate sender privatekeys (and send amount if passed)
+ //conversion when only privateKeys are passed (preserveRatio mode)
+ if(Array.isArray(senderPrivKeys)){
+ senderPrivKeys.forEach(key => {
+ try{
+ if(!key)
+ invalids.InvalidSenderPrivKeys.push(key);
+ else{
+ let floID = floCrypto.getFloIDfromPubkeyHex(floCrypto.getPubKeyHex(key));
+ senders[floID] = {
+ wif: key
+ }
+ }
+ }catch(error){
+ invalids.InvalidSenderPrivKeys.push(key)
+ }
+ })
+ preserveRatio = true;
+ }
+ //conversion when privatekeys are passed with send amount
+ else{
+ for(let key in senderPrivKeys){
+ try{
+ if(!key)
+ invalids.InvalidSenderPrivKeys.push(key);
+ else{
+ if(typeof senderPrivKeys[key] !== 'number' || senderPrivKeys[key] <= 0)
+ invalids.InvalidSenderAmountFor.push(key)
+ else
+ inputVal += senderPrivKeys[key];
+ let floID = floCrypto.getFloIDfromPubkeyHex(floCrypto.getPubKeyHex(key));
+ senders[floID] = {
+ wif: key,
+ coins: senderPrivKeys[key]
+ }
+ }
+ }catch(error){
+ invalids.InvalidSenderPrivKeys.push(key)
+ }
+ }
+ preserveRatio = false;
+ }
+ //Validate the receiver IDs and receive amount
+ for (let floID in receivers) {
+ if (!floCrypto.validateAddr(floID))
+ invalids.InvalidReceiverIDs.push(floID)
+ if (typeof receivers[floID] !== 'number' || receivers[floID] <= 0)
+ invalids.InvalidReceiveAmountFor.push(floID)
+ else
+ outputVal += receivers[floID];
+ }
+ //Reject if any invalids are found
+ for (let i in invalids)
+ if (!invalids[i].length)
+ delete invalids[i];
+ if (Object.keys(invalids).length)
+ return reject(invalids);
+ //Reject if given inputVal and outputVal are not equal
+ if(!preserveRatio && inputVal != outputVal)
+ return reject(`Input Amount (${inputVal}) not equal to Output Amount (${outputVal})`)
+ }catch(error){
+ return reject(error)
+ }
+ //Get balance of senders
+ let promises = []
+ for (let floID in senders)
+ promises.push(this.getBalance(floID))
+ Promise.all(promises).then(results => {
+ let totalBalance = 0,
+ totalFee = floGlobals.fee,
+ balance = {};
+ //Divide fee among sender if not for preserveRatio
+ if(!preserveRatio)
+ var dividedFee = totalFee / Object.keys(senders).length;
+ //Check if balance of each sender is sufficient enough
+ let insufficient = [];
+ for (let floID in senders) {
+ balance[floID] = parseFloat(results.shift());
+ if (isNaN(balance[floID]) || (preserveRatio && balance[floID] <= totalFee) || (!preserveRatio && balance[floID] < senders[floID].coins + dividedFee))
+ insufficient.push(floID)
+ totalBalance += balance[floID];
+ }
+ if (insufficient.length)
+ return reject({InsufficientBalance: insufficient})
+ //Calculate totalSentAmount and check if totalBalance is sufficient
+ let totalSendAmt = totalFee;
+ for (floID in receivers)
+ totalSendAmt += receivers[floID];
+ if (totalBalance < totalSendAmt)
+ return reject("Insufficient total Balance")
+ //Get the UTXOs of the senders
+ let promises = []
+ for (floID in senders)
+ promises.push(this.promisedAPI(`api/addr/${floID}/utxo`))
+ Promise.all(promises).then(results => {
+ let wifSeq = [];
+ var trx = bitjs.transaction();
+ for (floID in senders) {
+ let utxos = results.shift();
+ let sendAmt;
+ if(preserveRatio){
+ let ratio = (balance[floID] / totalBalance);
+ sendAmt = totalSendAmt * ratio;
+ } else
+ sendAmt = senders[floID].coins + dividedFee;
+ let wif = senders[floID].wif;
+ let utxoAmt = 0.0;
+ for (let i = utxos.length - 1;
+ (i >= 0) && (utxoAmt < sendAmt); i--) {
+ if (utxos[i].confirmations) {
+ trx.addinput(utxos[i].txid, utxos[i].vout, utxos[i]
+ .scriptPubKey)
+ wifSeq.push(wif);
+ utxoAmt += utxos[i].amount;
+ }
+ }
+ if (utxoAmt < sendAmt)
+ return reject("Insufficient balance:" + floID);
+ let change = (utxoAmt - sendAmt);
+ if (change > 0)
+ trx.addoutput(floID, change);
+ }
+ for (floID in receivers)
+ trx.addoutput(floID, receivers[floID]);
+ trx.addflodata(floData);
+ for (let i = 0; i < wifSeq.length; i++)
+ trx.signinput(i, wifSeq[i], 1);
+ var signedTxHash = trx.serialize();
+ this.broadcastTx(signedTxHash)
+ .then(txid => resolve(txid))
+ .catch(error => reject(error))
+ }).catch(error => reject(error))
+ }).catch(error => reject(error))
+ })
+ },
+
+
+
+
//Broadcast signed Tx in blockchain using API
broadcastTx: function (signedTxHash) {
return new Promise((resolve, reject) => {
var request = new XMLHttpRequest();
var url = this.util.serverList[this.util.curPos] + 'api/tx/send';
+ console.log(url)
if (signedTxHash.length < 1)
reject("Empty Signature");
else {