From bbbb18f8cb0ad248a853c93f5924a2d0d3863d43 Mon Sep 17 00:00:00 2001
From: blavenie <benoit.lavenier@e-is.pro>
Date: Fri, 21 Oct 2016 16:58:43 +0200
Subject: [PATCH] - fix #126 - TX chainning + bad sources selection -
 Certification : add missing refresh button on wide screens - Wallet : add
 missing refresh button on wide screens

---
 www/js/app.js                                 |   2 +-
 www/js/services/wallet-services.js            | 128 +++++++++++-------
 www/templates/wallet/view_wallet.html         |   7 +-
 www/templates/wot/view_certifications_lg.html |   5 +-
 4 files changed, 89 insertions(+), 53 deletions(-)

diff --git a/www/js/app.js b/www/js/app.js
index 50f4eb410..341540e33 100644
--- a/www/js/app.js
+++ b/www/js/app.js
@@ -31,7 +31,7 @@ angular.module('cesium', ['ionic', 'ionic-material', 'ngMessages', 'pascalprecht
       //  return '∞';
       //}
       if (Math.abs(input) < 0.0001) return '~ 0';
-      return numeral(input-0.00005).format('0,0.0000');
+      return numeral(input/*-0.00005*/).format('0,0.0000');
     };
   })
 
diff --git a/www/js/services/wallet-services.js b/www/js/services/wallet-services.js
index fe337fdb2..db313b192 100644
--- a/www/js/services/wallet-services.js
+++ b/www/js/services/wallet-services.js
@@ -112,7 +112,7 @@ angular.module('cesium.wallet.services', ['ngResource', 'ngApi', 'cesium.bma.ser
           var pubkey = amount > 0 ? otherIssuer : otherReceiver;
           var time = tx.time;
           if (tx.block_number === null) {
-            time = txPendingsTimeByKey[amount + ':' + tx.hash];
+            time = tx.blockstampTime || txPendingsTimeByKey[amount + ':' + tx.hash];
           }
 
           // Avoid duplicated tx, or tx to him self
@@ -136,6 +136,25 @@ angular.module('cesium.wallet.services', ['ngResource', 'ngApi', 'cesium.bma.ser
       });
     },
 
+    resetSources = function(){
+      data.sources = [];
+      data.sourcesIndexByKey = {};
+    };
+
+    addSource = function(src, sources, sourcesIndexByKey) {
+      var srcKey = src.type+':'+src.identifier+':'+src.noffset;
+      if (angular.isUndefined(sourcesIndexByKey[srcKey])) {
+        sources.push(src);
+        sourcesIndexByKey[srcKey] = sources.length - 1;
+      }
+    },
+
+    addSources = function(sources) {
+      _(sources).forEach(function(src) {
+        addSource(src, data.sources, data.sourcesIndexByKey);
+      });
+    },
+
     login = function(salt, password) {
       return CryptoUtils.connect(salt, password)
         .then(function(keypair) {
@@ -336,26 +355,20 @@ angular.module('cesium.wallet.services', ['ngResource', 'ngApi', 'cesium.bma.ser
         // Get transactions
         BMA.tx.sources({pubkey: data.pubkey})
         .then(function(res){
-          var sources = [];
-          var sourcesIndexByKey = [];
+          resetSources();
           var balance = 0;
           if (res.sources) {
             _.forEach(res.sources, function(src) {
-              var srcKey = src.type+':'+src.identifier+':'+src.noffset;
               src.consumed = false;
               balance += (src.base > 0) ? (src.amount * Math.pow(10, src.base)) : src.amount;
-              sources.push(src);
-              sourcesIndexByKey[srcKey] = sources.length -1 ;
             });
+            addSources(res.sources);
           }
-          data.sources = sources;
-          data.sourcesIndexByKey = sourcesIndexByKey;
           data.balance = balance;
           resolve();
         })
         .catch(function(err) {
-          data.sources = [];
-          data.sourcesIndexByKey = [];
+          resetSources();
           reject(err);
         });
       });
@@ -457,47 +470,63 @@ angular.module('cesium.wallet.services', ['ngResource', 'ngApi', 'cesium.bma.ser
           var txErrors = [];
           var balance = data.balance;
 
-          _.forEach(data.tx.history, function(tx) { // process TX history
+          // process TX history
+          _.forEach(data.tx.history, function(tx) {
              tx.uid = uids[tx.pubkey] || null;
           });
 
-          _.forEach(data.tx.pendings, function(tx) { // process TX pendings
-            tx.uid = uids[tx.pubkey] || null;
-
-            var sources = [];
-            var valid = true;
-            if (tx.amount > 0) { // do not check sources from received TX
-              valid = false;
-              // TODO get sources from the issuer ?
-            }
-            else {
-              _.forEach(tx.inputs, function(input) {
-                var inputKey = input.split(':').slice(2).join(':');
-                var srcIndex = data.sourcesIndexByKey[inputKey];
-                if (!angular.isUndefined(srcIndex)) {
-                  sources.push(data.sources[srcIndex]);
-                }
-                else {
-                  valid = false;
-                  return false; // break
+          var txs = data.tx.pendings;
+          var retry = true;
+          while(txs && txs.length > 0) {
+            // process TX pendings
+            _.forEach(txs, function(tx) {
+              tx.uid = uids[tx.pubkey] || null;
+
+              var consumedSources = [];
+              var valid = true;
+              if (tx.amount > 0) { // do not check sources from received TX
+                valid = false;
+                // TODO get sources from the issuer ?
+              }
+              else {
+                _.forEach(tx.inputs, function(input) {
+                  var inputKey = input.split(':').slice(2).join(':');
+                  var srcIndex = data.sourcesIndexByKey[inputKey];
+                  if (angular.isDefined(srcIndex)) {
+                    consumedSources.push(data.sources[srcIndex]);
+                  }
+                  else {
+                    valid = false;
+                    return false; // break
+                  }
+                });
+                if (tx.sources) { // add source output
+                  addSources(tx.sources);
+                  delete tx.sources;
                 }
-              });
-              if (tx.sources) { // add TX output to source
-                data.sources = data.sources.concat(tx.sources);
-                delete tx.sources;
               }
-            }
-            if (valid) {
-              balance += tx.amount; // update balance
-              txPendings.push(tx);
-              _.forEach(sources, function(src) {
-                src.consumed=true;
-              });
+              if (valid) {
+                balance += tx.amount; // update balance
+                txPendings.push(tx);
+                _.forEach(consumedSources, function(src) {
+                  src.consumed=true;
+                });
+              }
+              else {
+                txErrors.push(tx);
+              }
+            });
+
+            // Retry once (TX could be chained and processed in a wrong order)
+            if (txErrors.length > 0 && txPendings.length > 0 && retry) {
+              txs = txErrors;
+              txErrors = [];
+              retry = false;
             }
             else {
-              txErrors.push(tx);
+              txs = null;
             }
-          });
+          }
 
           data.tx.pendings = txPendings;
           data.tx.errors = txErrors;
@@ -712,16 +741,14 @@ angular.module('cesium.wallet.services', ['ngResource', 'ngApi', 'cesium.bma.ser
       var minBase = filterBase;
       var maxBase = filterBase;
       var i = 0;
-      _.forEach(data.sources, function(source) {
+      _.find(data.sources, function(source) {
         var skip = source.consumed || (source.base !== filterBase);
         if (!skip){
           sourcesAmount += (source.base > 0) ? (source.amount * Math.pow(10, source.base)) : source.amount;
           sources.push(source);
-          // Stop if enough sources
-          if (sourcesAmount >= amount) {
-            return false;
-          }
         }
+        // Stop if enough sources
+        return (sourcesAmount >= amount);
       });
 
       // IF not enough sources, get add inputs from lower base (recursively)
@@ -841,8 +868,9 @@ angular.module('cesium.wallet.services', ['ngResource', 'ngApi', 'cesium.bma.ser
                 source.consumed=true;
               });
 
+              // Add new sources
               if (res && res.sources.length) {
-                data.sources = data.sources.concat(res.sources);
+                addSources(res.sources);
               }
 
               // Add TX to pendings
@@ -860,7 +888,7 @@ angular.module('cesium.wallet.services', ['ngResource', 'ngApi', 'cesium.bma.ser
                     block_number: null
                   });
                   store(); // save pendings in local storage
-                  resolve(result);
+                  resolve();
                 }).catch(function(err){reject(err);});
             }).catch(function(err){reject(err);});
         });
diff --git a/www/templates/wallet/view_wallet.html b/www/templates/wallet/view_wallet.html
index 9c651829b..bf1c43ed9 100644
--- a/www/templates/wallet/view_wallet.html
+++ b/www/templates/wallet/view_wallet.html
@@ -48,8 +48,12 @@
     <div class="hidden-xs hidden-sm padding text-center" ng-if="!loading">
       <button class="button button-stable icon ion-android-share ink"
               ng-click="showSharePopover($event)">
-        {{'COMMON.BTN_SHARE' | translate}}
       </button>
+
+      <button class="button button-raised icon ion-loop ink"
+              ng-click="doUpdate()">
+      </button>
+
       <button class="button button-calm ink"
               ng-if="convertedBalance"
               ng-click="showTransferModal()">
@@ -67,6 +71,7 @@
               ng-click="actionsPopover.show($event)">
         <i class="icon ion-android-more-vertical"></i>
       </button>
+
     </div>
 
     <div class="row no-padding">
diff --git a/www/templates/wot/view_certifications_lg.html b/www/templates/wot/view_certifications_lg.html
index c5e809f6b..d6f051f96 100644
--- a/www/templates/wot/view_certifications_lg.html
+++ b/www/templates/wot/view_certifications_lg.html
@@ -9,7 +9,7 @@
     </ion-nav-title>
 
     <ion-nav-buttons side="secondary">
-        <button class="button button-icon button-clear icon ion-loop" ng-click="doUpdate()">
+        <button class="button button-icon button-clear icon ion-loop visible-xs visible-sm" ng-click="doUpdate()">
         </button>
     </ion-nav-buttons>
 
@@ -23,6 +23,9 @@
       <!-- Buttons bar -->
       <div class="hidden-xs hidden-sm text-center padding"
            ng-if="canCertify || canSelectAndCertify">
+        <button class="button button-raised icon ion-loop ink"
+                ng-click="doUpdate()">
+        </button>
         <button id="helptip-certs-certify"
                 class="button button-raised button-calm icon-left ion-ribbon-b"
                 ng-if="canCertify"
-- 
GitLab