From 2314f50ec1b68f607a54f5a01ef02bf0366c6739 Mon Sep 17 00:00:00 2001
From: blavenie <benoit.lavenier@e-is.pro>
Date: Wed, 29 Jun 2016 23:16:57 +0200
Subject: [PATCH] - Transfer: fix infinite loop (browser freeze) - fix #85 -
 Transfer: fix "source already consumed" - fix #86

---
 www/i18n/locale-en.json                    |  5 ++-
 www/i18n/locale-fr-FR.json                 |  5 ++-
 www/js/app.js                              |  2 +-
 www/js/controllers/transfer-controllers.js |  4 +-
 www/js/controllers/wallet-controllers.js   |  2 +-
 www/js/services/wallet-services.js         | 45 +++++++++++++++++-----
 www/templates/wallet/transfer_form.html    |  2 +-
 7 files changed, 47 insertions(+), 18 deletions(-)

diff --git a/www/i18n/locale-en.json b/www/i18n/locale-en.json
index 23f27ea0..decf0954 100644
--- a/www/i18n/locale-en.json
+++ b/www/i18n/locale-en.json
@@ -204,7 +204,7 @@
     "GET_CURRENCY_FAILED": "Could not load currency.",
     "SEND_TX_FAILED": "Could not send transaction.",
     "ALL_SOURCES_USED": "Please wait the next block computation (All transaction sources has been used).",
-    "NOT_ENOUGH_SOURCES": "Please wait the next block computation (Not enough transaction sources).",
+    "NOT_ENOUGH_SOURCES": "Not enough changes to send this amount in one time.<br/>Maximum amount:  {{amount}} {{unit}}<sub>{{subUnit}}</sub>.",
     "ACCOUNT_CREATION_FAILED": "Error while creating your member account.",
     "RESTORE_WALLET_DATA_ERROR": "Error while reloading settings from local storage",
     "LOAD_WALLET_DATA_ERROR": "Error while loading wallet data.",
@@ -220,7 +220,8 @@
     "NOT_ENOUGH_CREDIT": "Not enough credit.",
     "INVALID_NODE_SUMMARY": "Unreachable node or invalid address",
     "INVALID_USER_ID": "Field 'pseudonym' must not contains spaces or special caracters.",
-    "INVALID_COMMENT": "Field 'reference' has a bad format."
+    "INVALID_COMMENT": "Field 'reference' has a bad format.",
+    "INVALID_PUBKEY": "Public key has a bad format."
   },
   "INFO": {
     "POPUP_TITLE": "Information",
diff --git a/www/i18n/locale-fr-FR.json b/www/i18n/locale-fr-FR.json
index d16aca73..aa352296 100644
--- a/www/i18n/locale-fr-FR.json
+++ b/www/i18n/locale-fr-FR.json
@@ -204,7 +204,7 @@
     "GET_CURRENCY_FAILED": "Chargement de la monnaie impossibl.e",
     "SEND_TX_FAILED": "Echec du paiement.",
     "ALL_SOURCES_USED": "Veuillez attendre le calcul du prochain bloc (Toutes vos sources de monnaie ont été utilisées).",
-    "NOT_ENOUGH_SOURCES": "Veuillez attendre le calcul du prochain bloc (Pas assez de sources de monnaie).",
+    "NOT_ENOUGH_SOURCES": "Pas assez de change pour envoyer ce montant en une seule transaction.<br/>Montant maximum : {{amount}} {{unit}}<sub>{{subUnit}}</sub>.",
     "ACCOUNT_CREATION_FAILED": "Echec de la création du compte membre.",
     "RESTORE_WALLET_DATA_ERROR": "Echec du rechargement des paramètres depuis le stockage local",
     "LOAD_WALLET_DATA_ERROR": "Echec du chargement des données du portefeuille.",
@@ -220,7 +220,8 @@
     "NOT_ENOUGH_CREDIT": "Crédit insufisant.",
     "INVALID_NODE_SUMMARY": "Noeud injoignable ou adresse invalide.",
     "INVALID_USER_ID": "Le champ 'pseudonyme' ne doit contenir ni espace ni caractère spécial ou accentué.",
-    "INVALID_COMMENT": "Le champ 'référence' ne doit pas contenir de caractères accentués."
+    "INVALID_COMMENT": "Le champ 'référence' ne doit pas contenir de caractères accentués.",
+    "INVALID_PUBKEY": "La clé publique n'a pas le format attendu."
   },
   "INFO": {
     "POPUP_TITLE": "Information",
diff --git a/www/js/app.js b/www/js/app.js
index d03a86be..5d6902bd 100644
--- a/www/js/app.js
+++ b/www/js/app.js
@@ -21,7 +21,7 @@ angular.module('cesium', ['ionic', 'ionic-material', 'ngMessages', 'ngAnimate',
       return function(input) {
         if (!input) return '0';
         if (Math.abs(input) < 0.0001) return '~ 0';
-        return numeral(input).format('0,0.0000').replace(',', ' ');
+        return numeral(input-0.00005).format('0,0.0000').replace(',', ' ');
       };
     })
 
diff --git a/www/js/controllers/transfer-controllers.js b/www/js/controllers/transfer-controllers.js
index efed00a3..49b377a7 100644
--- a/www/js/controllers/transfer-controllers.js
+++ b/www/js/controllers/transfer-controllers.js
@@ -206,7 +206,7 @@ function TransferModalController($scope, $rootScope, $ionicModal, $state, BMA, W
 
   $scope.doTransfer = function() {
     $scope.transferForm.$submitted=true;
-    if(!$scope.transferForm.$valid) {
+    if(!$scope.transferForm.$valid || !$scope.formData.destPub) {
       return;
     }
 
@@ -218,7 +218,7 @@ function TransferModalController($scope, $rootScope, $ionicModal, $state, BMA, W
       amount = $scope.walletData.currentUD *
                amount.replace(new RegExp('[.,]'), '.');
     }
-    Wallet.transfer($scope.formData.destPub, amount, $scope.formData.comment)
+    Wallet.transfer($scope.formData.destPub, amount, $scope.formData.comment, $scope.formData.useRelative)
     .then(function() {
        var callback = $scope.formData.callback;
         $scope.formData = {}; // Reset form data
diff --git a/www/js/controllers/wallet-controllers.js b/www/js/controllers/wallet-controllers.js
index 50574b27..1e16cfd0 100644
--- a/www/js/controllers/wallet-controllers.js
+++ b/www/js/controllers/wallet-controllers.js
@@ -32,12 +32,12 @@ function WalletController($scope, $rootScope, $state, $q, $ionicPopup, $ionicAct
   $scope.showDetails = false;
 
   $scope.$on('$ionicView.enter', function(e, $state) {
-    UIUtils.loading.hide();
     $scope.loadWallet()
       .then(function(wallet) {
         $scope.updateWalletView(wallet);
         $scope.showFab('fab-transfer');
         $scope.showQRCode('qrcode', wallet.pubkey, 1100);
+        UIUtils.loading.hide();
       });
 
       $timeout(function () {
diff --git a/www/js/services/wallet-services.js b/www/js/services/wallet-services.js
index f5ca4883..28d96f4c 100644
--- a/www/js/services/wallet-services.js
+++ b/www/js/services/wallet-services.js
@@ -1,7 +1,7 @@
 
 angular.module('cesium.wallet.services', ['ngResource', 'cesium.bma.services', 'cesium.crypto.services', 'cesium.utils.services'])
 
-.factory('Wallet', function($q, CryptoUtils, BMA, $translate, localStorage) {
+.factory('Wallet', function($q, CryptoUtils, BMA, $translate, localStorage, $filter) {
   'ngInject';
 
   Wallet = function(id) {
@@ -556,7 +556,7 @@ angular.module('cesium.wallet.services', ['ngResource', 'cesium.bma.services', '
       var maxBase = filterBase;
       var i = 0;
       _.forEach(data.sources, function(source) {
-        var skip = source.consumed || (source.base !== filterBase) || (offset && i++ >= offset);
+        var skip = source.consumed || (source.base !== filterBase) || (offset && i++ < offset);
         if (!skip){
           sourcesAmount += (source.base > 0) ? (source.amount * Math.pow(10, source.base)) : source.amount;
           sources.push(source);
@@ -597,11 +597,14 @@ angular.module('cesium.wallet.services', ['ngResource', 'cesium.bma.services', '
     /**
     * Send a new transaction
     */
-    transfer = function(destPub, amount, comments) {
+    transfer = function(destPub, amount, comments, useRelative) {
       return $q(function(resolve, reject) {
         BMA.blockchain.current(true/*cache*/)
         .then(function(block) {
 
+          if (!BMA.regex.PUBKEY.test(destPub)){
+            reject({message:'ERROR.INVALID_PUBKEY'}); return;
+          }
           if (!BMA.regex.COMMENT.test(comments)){
             reject({message:'ERROR.INVALID_COMMENT'}); return;
           }
@@ -636,8 +639,10 @@ angular.module('cesium.wallet.services', ['ngResource', 'cesium.bma.services', '
             intputs: []
           };
 
+          var maxAmount = 0;
           while (inputs.amount < amount && inputs.maxBase > 0) {
             inputs = getInputs(amount, inputs.maxBase - 1);
+            maxAmount =  (inputs.amount > maxAmount) ? inputs.amount : maxAmount;
           }
 
           if (inputs.amount < amount) {
@@ -645,8 +650,28 @@ angular.module('cesium.wallet.services', ['ngResource', 'cesium.bma.services', '
               reject({message:'ERROR.ALL_SOURCES_USED'});
             }
             else {
-              console.error('Maximum transaction sources has been reached: ' + (data.settings.useRelative ? (inputs.amount  / data.currentUD)+' UD' : inputs.amount));
-              reject({message:'ERROR.NOT_ENOUGH_SOURCES'});
+              $translate('COMMON.UD')
+              .then(function(UD) {
+                var params;
+                if(useRelative) {
+                  params = {
+                    amount: ($filter('formatDecimal')(maxAmount / data.currentUD)),
+                    unit: UD,
+                    subUnit: $filter('abbreviate')(data.currency)
+                  };
+                }
+                else {
+                  params = {
+                    amount: ($filter('formatInteger')(maxAmount)),
+                    unit: $filter('abbreviate')(data.currency),
+                    subUnit: ''
+                  };
+                }
+                $translate('ERROR.NOT_ENOUGH_SOURCES', params)
+                .then(function(message) {
+                  reject({message: message});
+                });
+              });
             }
             return;
           }
@@ -692,20 +717,22 @@ angular.module('cesium.wallet.services', ['ngResource', 'cesium.bma.services', '
             BMA.tx.process({transaction: signedTx})
             .then(function(result) {
               data.balance -= amount;
-              for(var i=0;i<inputs.length;i++)inputs[i].consumed=true;
+              _.forEach(inputs.sources, function(source) {
+                  source.consumed=true;
+              });
               // Add to history
-              data.history.unshift({
+              /*data.history.unshift({
                   time: block.time,
                   amount: amount,
                   issuer: data.pubkey,
                   receiver: destPub,
                   comment: comments,
                   isUD: false,
-                  /*hash: tx.hash, TODO*/
+                  hash: tx.hash, TODO
                   locktime: 0,
                   block_number: null,
                   valid: false
-                });
+                });*/
 
               resolve(result);
             }).catch(function(err){reject(err);});
diff --git a/www/templates/wallet/transfer_form.html b/www/templates/wallet/transfer_form.html
index 775d7f92..8b996e83 100644
--- a/www/templates/wallet/transfer_form.html
+++ b/www/templates/wallet/transfer_form.html
@@ -8,7 +8,7 @@
           <i class="gray icon ion-ios-arrow-right"></i>
       </a>
       <div class="form-errors"
-           ng-show="transferForm.$submitted && !dest">
+           ng-if="transferForm.$submitted && !formData.destPub">
         <div class="form-error">
           <span translate="ERROR.FIELD_REQUIRED"></span>
         </div>
-- 
GitLab