// Copyright (c) 2014-2015, MyMonero.com // // All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other // materials provided with the distribution. // // 3. Neither the name of the copyright holder nor the names of its contributors may be // used to endorse or promote products derived from this software without specific // prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. thinwalletCtrls.controller('AccountCtrl', function($scope, $rootScope, $http, $q, $interval, AccountService, EVENT_CODES) { "use strict"; $scope.loggedIn = AccountService.loggedIn; $scope.logout = AccountService.logout; $scope.balance = JSBigInt.ZERO; $scope.locked_balance = JSBigInt.ZERO; $scope.total_received = JSBigInt.ZERO; $scope.total_sent = JSBigInt.ZERO; $scope.address = AccountService.getAddress(); $scope.view_key = $scope.viewkey = AccountService.getViewKey(); $scope.spend_key = AccountService.getSpendKey(); $scope.mnemonic = AccountService.getMnemonic(); $scope.testnet = config.testnet; $scope.transactions = []; $scope.blockchain_height = 0; $scope.tx_is_confirmed = function(tx) { // return ($scope.blockchain_height - tx.height) > config.txMinConfirms; if (!tx.coinbase) { // for regular txs, by defalut 10 blocks is required for it to // be confirmed/spendable return ($scope.blockchain_height - tx.height) > config.txMinConfirms; } else { // coinbase txs require much more blocks (default 60) // for it to be confirmed/spendable return ($scope.blockchain_height - tx.height) > config.txCoinbaseMinConfirms; } }; $scope.tx_is_unlocked = function(tx) { return cnUtil.is_tx_unlocked(tx.unlock_time || 0, $scope.blockchain_height); //return false; }; $scope.tx_is_mempool = function(tx) { //console.log(tx.mempool); return tx.mempool; }; $scope.tx_locked_reason = function(tx) { return cnUtil.tx_locked_reason(tx.unlock_time || 0, $scope.blockchain_height); }; $scope.set_locked_balance = function(locked_balance) { $scope.locked_balance = locked_balance; }; $scope.set_total_received = function(total_received) { $scope.total_received = total_received; }; $scope.set_total_sent = function(total_sent) { $scope.total_sent = total_sent; }; $scope.$on(EVENT_CODES.authStatusChanged, function() { $scope.address = AccountService.getAddress(); $scope.view_key = $scope.viewkey = AccountService.getViewKey(); $scope.spend_key = AccountService.getSpendKey(); $scope.mnemonic = AccountService.getMnemonic(); if (!AccountService.loggedIn()) { $scope.transactions = []; $scope.blockchain_height = 0; $scope.balance = JSBigInt.ZERO; $scope.locked_balance = JSBigInt.ZERO; $scope.total_received = JSBigInt.ZERO; $scope.total_sent = JSBigInt.ZERO; } }); $scope.fetchAddressInfo = function() { if (AccountService.loggedIn()) { $http.post(config.apiUrl + "get_address_info", { address: AccountService.getAddress(), view_key: AccountService.getViewKey() }).success(function(data) { var promises = []; for (var i = 0; i < (data.spent_outputs || []).length; ++i) { var deferred = $q.defer(); promises.push(deferred.promise); (function(deferred, spent_output) { setTimeout(function() { var key_image = AccountService.cachedKeyImage( spent_output.tx_pub_key, spent_output.out_index ); if (spent_output.key_image !== key_image) { data.total_sent = new JSBigInt(data.total_sent).subtract(spent_output.amount); } deferred.resolve(); }, 0); })(deferred, data.spent_outputs[i]); } $q.all(promises).then(function() { $scope.locked_balance = new JSBigInt(data.locked_funds || 0); $scope.total_sent = new JSBigInt(data.total_sent || 0); //$scope.account_scanned_tx_height = data.scanned_height || 0; $scope.account_scanned_block_height = data.scanned_block_height || 0; $scope.account_scan_start_height = data.start_height || 0; //$scope.transaction_height = data.transaction_height || 0; $scope.blockchain_height = data.blockchain_height || 0; }); }); } }; $scope.fetchTransactions = function() { if (AccountService.loggedIn()) { $http.post(config.apiUrl + 'get_address_txs', AccountService.getAddressAndViewKey()) .success(function(data) { $scope.account_scanned_height = data.scanned_height || 0; $scope.account_scanned_block_height = data.scanned_block_height || 0; $scope.account_scan_start_height = data.start_height || 0; //$scope.transaction_height = data.transaction_height || 0; $scope.blockchain_height = data.blockchain_height || 0; var transactions = data.transactions || []; for (var i = 0; i < transactions.length; ++i) { if ((transactions[i].spent_outputs || []).length > 0) { for (var j = 0; j < transactions[i].spent_outputs.length; ++j) { var key_image = AccountService.cachedKeyImage( transactions[i].spent_outputs[j].tx_pub_key, transactions[i].spent_outputs[j].out_index ); if (transactions[i].spent_outputs[j].key_image !== key_image) { transactions[i].total_sent = new JSBigInt(transactions[i].total_sent).subtract(transactions[i].spent_outputs[j].amount).toString(); transactions[i].spent_outputs.splice(j, 1); j--; } } } if (new JSBigInt(transactions[i].total_received || 0).add(transactions[i].total_sent || 0).compare(0) <= 0) { transactions.splice(i, 1); i--; continue; } //console.log(transactions[i].total_received, transactions[i].total_sent); transactions[i].amount = new JSBigInt(transactions[i].total_received || 0).subtract(transactions[i].total_sent || 0).toString(); transactions[i].approx_float_amount = parseFloat(cnUtil.formatMoney(transactions[i].amount)); transactions[i].timestamp = new Date(transactions[i].timestamp); } transactions.sort(function(a, b) { return b.id - a.id; // sort by id in database //var t1 = b.timestamp; //var t2 = a.timestamp; //return ((t1 < t2) ? -1 : ((t1 > t2) ? 1 : 0)); }); $scope.transactions = transactions; $scope.total_received = new JSBigInt(data.total_received || 0); $scope.total_received_unlocked = new JSBigInt(data.total_received_unlocked || 0); }); } }; $scope.isAccountCatchingUp = function() { return ($scope.blockchain_height - $scope.account_scanned_block_height) >= 10; }; $scope.$watch( function(scope) { return { sent: scope.total_sent, received: scope.total_received, received_unlocked: scope.total_received_unlocked }; }, function(data) { $scope.balance = data.received.subtract(data.sent); $scope.balance_unlocked = data.received_unlocked.subtract(data.sent); }, true ); $rootScope.$watch('account', $scope.fetchAddressInfo); var fetchInterval = $interval($scope.fetchAddressInfo, 10 * 1000); $scope.fetchAddressInfo(); $scope.$on('$destroy', function() { $interval.cancel(fetchInterval); }); });