129 lines
3.7 KiB
JavaScript
129 lines
3.7 KiB
JavaScript
|
|
'use strict';
|
||
|
|
|
||
|
|
(function(){
|
||
|
|
|
||
|
|
angular
|
||
|
|
.module('bitcoincom.services')
|
||
|
|
.factory('walletHistoryService', walletHistoryService);
|
||
|
|
|
||
|
|
function walletHistoryService(configService, storageService, lodash, $log, txFormatService) {
|
||
|
|
// 8 Transactions fit on an iPhone Plus screen when in Wallet Details.
|
||
|
|
// Make it a little bit bigger so it doesn't have to load more immediately
|
||
|
|
var PAGE_SIZE = 50 / 1.5;
|
||
|
|
// How much to overlap on each end of the page, for mitigating inconsistent sort order.
|
||
|
|
var PAGE_OVERLAP_FRACTION = 0.5;
|
||
|
|
|
||
|
|
var SAFE_CONFIRMATIONS = 6;
|
||
|
|
|
||
|
|
var service = {
|
||
|
|
getCachedTxHistory: getCachedTxHistory,
|
||
|
|
updateTxHistoryByPage: updateTxHistoryByPage
|
||
|
|
};
|
||
|
|
return service;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @param {string} walletId
|
||
|
|
* @param {function(error, txs)} cb
|
||
|
|
*/
|
||
|
|
function getCachedTxHistory(walletId, cb) {
|
||
|
|
storageService.getTxHistory(walletId, function onGetTxHistory(err, txHistoryString){
|
||
|
|
if (err) {
|
||
|
|
return cb(err);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!txHistoryString) {
|
||
|
|
return cb(null, txHistoryString);
|
||
|
|
}
|
||
|
|
|
||
|
|
try {
|
||
|
|
var txHistory = JSON.parse(txHistoryString);
|
||
|
|
return cb(null, txHistory);
|
||
|
|
} catch (e) {
|
||
|
|
$log.error('Failed to parse tx history.', e);
|
||
|
|
return cb(e);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
function processNewTxs(wallet, txs) {
|
||
|
|
var now = Math.floor(Date.now() / 1000);
|
||
|
|
var txHistoryUnique = {};
|
||
|
|
var processedTxs = [];
|
||
|
|
wallet.hasUnsafeConfirmed = false;
|
||
|
|
|
||
|
|
lodash.each(txs, function(tx) {
|
||
|
|
tx = txFormatService.processTx(wallet.coin, tx);
|
||
|
|
|
||
|
|
// no future transactions...
|
||
|
|
if (tx.time > now)
|
||
|
|
tx.time = now;
|
||
|
|
|
||
|
|
if (tx.confirmations >= SAFE_CONFIRMATIONS) {
|
||
|
|
tx.safeConfirmed = SAFE_CONFIRMATIONS + '+';
|
||
|
|
} else {
|
||
|
|
tx.safeConfirmed = false;
|
||
|
|
wallet.hasUnsafeConfirmed = true;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (tx.note) {
|
||
|
|
delete tx.note.encryptedEditedByName;
|
||
|
|
delete tx.note.encryptedBody;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!txHistoryUnique[tx.txid]) {
|
||
|
|
processedTxs.push(tx);
|
||
|
|
txHistoryUnique[tx.txid] = true;
|
||
|
|
} else {
|
||
|
|
$log.debug('Ignoring duplicate TX in history: ' + tx.txid)
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
// Update notes?
|
||
|
|
|
||
|
|
return processedTxs;
|
||
|
|
};
|
||
|
|
|
||
|
|
/**
|
||
|
|
* A small cache of up to the 50 most recent transactions
|
||
|
|
*/
|
||
|
|
function saveTxHistory(processedTxs, walletId) {
|
||
|
|
storageService.setTxHistory(processedTxs, walletId, function onSetTxHistory(error){
|
||
|
|
// Looks like callback only gets called on error
|
||
|
|
$log.error('pagination Failed to save tx history.', error);
|
||
|
|
});
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
// Only clear the cache once we have received new transactions from the server.
|
||
|
|
function updateTxHistoryByPage(wallet, getLatest, flushCacheOnNew, cb) {
|
||
|
|
var skip = 0;
|
||
|
|
var limit = Math.floor(PAGE_SIZE * (1 + PAGE_OVERLAP_FRACTION));
|
||
|
|
|
||
|
|
var opts = {
|
||
|
|
skip: skip,
|
||
|
|
limit: limit
|
||
|
|
};
|
||
|
|
wallet.getTxHistory(opts, function onTxHistory(err, txsFromServer) {
|
||
|
|
if (err) {
|
||
|
|
return cb(err);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!txsFromServer.length) {
|
||
|
|
return cb(null, []);
|
||
|
|
}
|
||
|
|
|
||
|
|
var processedTxs = processNewTxs(wallet, txsFromServer);
|
||
|
|
|
||
|
|
if (getLatest) {
|
||
|
|
console.log('pagination Saving retrieved txs.');
|
||
|
|
saveTxHistory(wallet, processedTxs);
|
||
|
|
}
|
||
|
|
|
||
|
|
return cb(null, processedTxs);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
})();
|