Merge https://github.com/bitpay/copay into copay-cash
This commit is contained in:
commit
a0261a6c9f
146 changed files with 16800 additions and 5578 deletions
|
|
@ -1,8 +1,19 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.services').factory('addressbookService', function(bitcore, storageService, lodash) {
|
||||
angular.module('copayApp.services').factory('addressbookService', function($log, bitcore, bitcoreCash, storageService, lodash) {
|
||||
var root = {};
|
||||
|
||||
var getNetwork = function(address) {
|
||||
var network;
|
||||
try {
|
||||
network = (new bitcore.Address(address)).network.name;
|
||||
} catch(e) {
|
||||
$log.warn('No valid bitcoin address. Trying bitcoin cash...');
|
||||
network = (new bitcoreCash.Address(address)).network.name;
|
||||
}
|
||||
return network;
|
||||
};
|
||||
|
||||
root.get = function(addr, cb) {
|
||||
storageService.getAddressbook('testnet', function(err, ab) {
|
||||
if (err) return cb(err);
|
||||
|
|
@ -35,7 +46,8 @@ angular.module('copayApp.services').factory('addressbookService', function(bitco
|
|||
};
|
||||
|
||||
root.add = function(entry, cb) {
|
||||
var network = (new bitcore.Address(entry.address)).network.name;
|
||||
var network = getNetwork(entry.address);
|
||||
if (lodash.isEmpty(network)) return cb('Not valid bitcoin address');
|
||||
storageService.getAddressbook(network, function(err, ab) {
|
||||
if (err) return cb(err);
|
||||
if (ab) ab = JSON.parse(ab);
|
||||
|
|
@ -53,7 +65,8 @@ angular.module('copayApp.services').factory('addressbookService', function(bitco
|
|||
};
|
||||
|
||||
root.remove = function(addr, cb) {
|
||||
var network = (new bitcore.Address(addr)).network.name;
|
||||
var network = getNetwork(addr);
|
||||
if (lodash.isEmpty(network)) return cb('Not valid bitcoin address');
|
||||
storageService.getAddressbook(network, function(err, ab) {
|
||||
if (err) return cb(err);
|
||||
if (ab) ab = JSON.parse(ab);
|
||||
|
|
|
|||
6
src/js/services/bitcoreCash.js
Normal file
6
src/js/services/bitcoreCash.js
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
'use strict';
|
||||
angular.module('copayApp.services')
|
||||
.factory('bitcoreCash', function bitcoreFactory(bwcService) {
|
||||
var bitcoreCash = bwcService.getBitcoreCash();
|
||||
return bitcoreCash;
|
||||
});
|
||||
|
|
@ -53,6 +53,7 @@ angular.module('copayApp.services').factory('coinbaseService', function($http, $
|
|||
'wallet:sells:create,' +
|
||||
'wallet:transactions:read,' +
|
||||
'wallet:transactions:send,' +
|
||||
'wallet:transactions:send:bypass-2fa,' +
|
||||
'wallet:payment-methods:read';
|
||||
|
||||
// NW has a bug with Window Object
|
||||
|
|
@ -169,9 +170,9 @@ angular.module('copayApp.services').factory('coinbaseService', function($http, $
|
|||
var _getNetAmount = function(amount, cb) {
|
||||
// Fee Normal for a single transaction (450 bytes)
|
||||
var txNormalFeeKB = 450 / 1000;
|
||||
feeService.getFeeRate(null, 'normal', function(err, feePerKB) {
|
||||
feeService.getFeeRate('btc', 'livenet', 'normal', function(err, feePerKb) {
|
||||
if (err) return cb(err);
|
||||
var feeBTC = (feePerKB * txNormalFeeKB / 100000000).toFixed(8);
|
||||
var feeBTC = (feePerKb * txNormalFeeKB / 100000000).toFixed(8);
|
||||
|
||||
return cb(null, amount - feeBTC, feeBTC);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -69,7 +69,8 @@ angular.module('copayApp.services').factory('configService', function(storageSer
|
|||
bannedUntil: null,
|
||||
},
|
||||
|
||||
// External services
|
||||
cashSupport: false,
|
||||
|
||||
recentTransactions: {
|
||||
enabled: true,
|
||||
},
|
||||
|
|
@ -141,6 +142,11 @@ angular.module('copayApp.services').factory('configService', function(storageSer
|
|||
configCache.hideNextSteps = defaultConfig.hideNextSteps;
|
||||
}
|
||||
|
||||
|
||||
if (!configCache.cashSupport) {
|
||||
configCache.cashSupport = defaultConfig.cashSupport;
|
||||
}
|
||||
|
||||
if (!configCache.recentTransactions) {
|
||||
configCache.recentTransactions = defaultConfig.recentTransactions;
|
||||
}
|
||||
|
|
@ -151,6 +157,14 @@ angular.module('copayApp.services').factory('configService', function(storageSer
|
|||
configCache.bitpayAccount = defaultConfig.bitpayAccount;
|
||||
}
|
||||
|
||||
if (configCache.wallet.settings.unitCode == 'bit') {
|
||||
// Convert to BTC. Bits will be disabled
|
||||
configCache.wallet.settings.unitName = defaultConfig.wallet.settings.unitName;
|
||||
configCache.wallet.settings.unitToSatoshi = defaultConfig.wallet.settings.unitToSatoshi;
|
||||
configCache.wallet.settings.unitDecimals = defaultConfig.wallet.settings.unitDecimals;
|
||||
configCache.wallet.settings.unitCode = defaultConfig.wallet.settings.unitCode;
|
||||
}
|
||||
|
||||
} else {
|
||||
configCache = lodash.clone(defaultConfig);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ angular.module('copayApp.services').factory('feeService', function($log, $timeou
|
|||
|
||||
var cache = {
|
||||
updateTs: 0,
|
||||
coin: ''
|
||||
};
|
||||
|
||||
root.getCurrentFeeLevel = function() {
|
||||
|
|
@ -24,20 +25,20 @@ angular.module('copayApp.services').factory('feeService', function($log, $timeou
|
|||
};
|
||||
|
||||
|
||||
root.getFeeRate = function(network, feeLevel, cb) {
|
||||
root.getFeeRate = function(coin, network, feeLevel, cb) {
|
||||
|
||||
if (feeLevel == 'custom') return cb();
|
||||
|
||||
network = network || 'livenet';
|
||||
|
||||
root.getFeeLevels(function(err, levels, fromCache) {
|
||||
root.getFeeLevels(coin, function(err, levels, fromCache) {
|
||||
if (err) return cb(err);
|
||||
|
||||
var feeLevelRate = lodash.find(levels[network], {
|
||||
level: feeLevel
|
||||
});
|
||||
|
||||
if (!feeLevelRate || !feeLevelRate.feePerKB) {
|
||||
if (!feeLevelRate || !feeLevelRate.feePerKb) {
|
||||
return cb({
|
||||
message: gettextCatalog.getString("Could not get dynamic fee for level: {{feeLevel}}", {
|
||||
feeLevel: feeLevel
|
||||
|
|
@ -45,34 +46,35 @@ angular.module('copayApp.services').factory('feeService', function($log, $timeou
|
|||
});
|
||||
}
|
||||
|
||||
var feeRate = feeLevelRate.feePerKB;
|
||||
var feeRate = feeLevelRate.feePerKb;
|
||||
|
||||
if (!fromCache) $log.debug('Dynamic fee: ' + feeLevel + '/' + network + ' ' + (feeLevelRate.feePerKB / 1000).toFixed() + ' SAT/B');
|
||||
if (!fromCache) $log.debug('Dynamic fee: ' + feeLevel + '/' + network + ' ' + (feeLevelRate.feePerKb / 1000).toFixed() + ' SAT/B');
|
||||
|
||||
return cb(null, feeRate);
|
||||
});
|
||||
};
|
||||
|
||||
root.getCurrentFeeRate = function(network, cb) {
|
||||
return root.getFeeRate(network, root.getCurrentFeeLevel(), cb);
|
||||
root.getCurrentFeeRate = function(coin, network, cb) {
|
||||
return root.getFeeRate(coin, network, root.getCurrentFeeLevel(), cb);
|
||||
};
|
||||
|
||||
root.getFeeLevels = function(cb) {
|
||||
root.getFeeLevels = function(coin, cb) {
|
||||
coin = coin || 'btc';
|
||||
|
||||
if (cache.updateTs > Date.now() - CACHE_TIME_TS * 1000) {
|
||||
if (cache.coin == coin && cache.updateTs > Date.now() - CACHE_TIME_TS * 1000) {
|
||||
return cb(null, cache.data, true);
|
||||
}
|
||||
|
||||
var walletClient = bwcService.getClient();
|
||||
var unitName = configService.getSync().wallet.settings.unitName;
|
||||
|
||||
walletClient.getFeeLevels('livenet', function(errLivenet, levelsLivenet) {
|
||||
walletClient.getFeeLevels('testnet', function(errTestnet, levelsTestnet) {
|
||||
walletClient.getFeeLevels(coin, 'livenet', function(errLivenet, levelsLivenet) {
|
||||
walletClient.getFeeLevels('btc', 'testnet', function(errTestnet, levelsTestnet) {
|
||||
if (errLivenet || errTestnet) {
|
||||
return cb(gettextCatalog.getString('Could not get dynamic fee'));
|
||||
}
|
||||
|
||||
cache.updateTs = Date.now();
|
||||
cache.coin = coin;
|
||||
cache.data = {
|
||||
'livenet': levelsLivenet,
|
||||
'testnet': levelsTestnet
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ angular.module('copayApp.services')
|
|||
};
|
||||
|
||||
root.add = function(level, msg) {
|
||||
msg = msg.replace('/xpriv.*/', 'xpriv[Hidden]');
|
||||
logs.push({
|
||||
timestamp: new Date().toISOString(),
|
||||
level: level,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.services').factory('incomingData', function($log, $state, $timeout, $ionicHistory, bitcore, $rootScope, payproService, scannerService, appConfigService, popupService, gettextCatalog) {
|
||||
angular.module('copayApp.services').factory('incomingData', function($log, $state, $timeout, $ionicHistory, bitcore, bitcoreCash, $rootScope, payproService, scannerService, appConfigService, popupService, gettextCatalog) {
|
||||
|
||||
var root = {};
|
||||
|
||||
|
|
@ -46,7 +46,7 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat
|
|||
return true;
|
||||
}
|
||||
|
||||
function goSend(addr, amount, message) {
|
||||
function goSend(addr, amount, message, coin) {
|
||||
$state.go('tabs.send', {}, {
|
||||
'reload': true,
|
||||
'notify': $state.current.name == 'tabs.send' ? false : true
|
||||
|
|
@ -57,18 +57,20 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat
|
|||
$state.transitionTo('tabs.send.confirm', {
|
||||
toAmount: amount,
|
||||
toAddress: addr,
|
||||
description: message
|
||||
description: message,
|
||||
coin: coin
|
||||
});
|
||||
} else {
|
||||
$state.transitionTo('tabs.send.amount', {
|
||||
toAddress: addr
|
||||
toAddress: addr,
|
||||
coin: coin
|
||||
});
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
// data extensions for Payment Protocol with non-backwards-compatible request
|
||||
if ((/^bitcoin:\?r=[\w+]/).exec(data)) {
|
||||
data = decodeURIComponent(data.replace('bitcoin:?r=', ''));
|
||||
if ((/^bitcoin(cash)?:\?r=[\w+]/).exec(data)) {
|
||||
data = decodeURIComponent(data.replace(/bitcoin(cash)?:\?r=/, ''));
|
||||
$state.go('tabs.send', {}, {
|
||||
'reload': true,
|
||||
'notify': $state.current.name == 'tabs.send' ? false : true
|
||||
|
|
@ -82,27 +84,97 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat
|
|||
|
||||
data = sanitizeUri(data);
|
||||
|
||||
// BIP21
|
||||
// Bitcoin URL
|
||||
if (bitcore.URI.isValid(data)) {
|
||||
var parsed = new bitcore.URI(data);
|
||||
var coin = 'btc';
|
||||
var parsed = new bitcore.URI(data);
|
||||
|
||||
var addr = parsed.address ? parsed.address.toString() : '';
|
||||
var message = parsed.message;
|
||||
var addr = parsed.address ? parsed.address.toString() : '';
|
||||
var message = parsed.message;
|
||||
|
||||
var amount = parsed.amount ? parsed.amount : '';
|
||||
var amount = parsed.amount ? parsed.amount : '';
|
||||
|
||||
if (parsed.r) {
|
||||
payproService.getPayProDetails(parsed.r, function(err, details) {
|
||||
if (err) {
|
||||
if (addr && amount) goSend(addr, amount, message);
|
||||
else popupService.showAlert(gettextCatalog.getString('Error'), err);
|
||||
} else handlePayPro(details);
|
||||
});
|
||||
} else {
|
||||
goSend(addr, amount, message);
|
||||
}
|
||||
if (parsed.r) {
|
||||
payproService.getPayProDetails(parsed.r, function(err, details) {
|
||||
if (err) {
|
||||
if (addr && amount) goSend(addr, amount, message, coin);
|
||||
else popupService.showAlert(gettextCatalog.getString('Error'), err);
|
||||
} else handlePayPro(details);
|
||||
});
|
||||
} else {
|
||||
goSend(addr, amount, message, coin);
|
||||
}
|
||||
return true;
|
||||
// Cash URI
|
||||
} else if (bitcoreCash.URI.isValid(data)) {
|
||||
var coin = 'bch';
|
||||
var parsed = new bitcoreCash.URI(data);
|
||||
|
||||
var addr = parsed.address ? parsed.address.toString() : '';
|
||||
var message = parsed.message;
|
||||
|
||||
var amount = parsed.amount ? parsed.amount : '';
|
||||
|
||||
// paypro not yet supported on cash
|
||||
if (parsed.r) {
|
||||
payproService.getPayProDetails(parsed.r, function(err, details) {
|
||||
if (err) {
|
||||
if (addr && amount)
|
||||
goSend(addr, amount, message, coin);
|
||||
else
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), err);
|
||||
}
|
||||
handlePayPro(details, coin);
|
||||
});
|
||||
} else {
|
||||
goSend(addr, amount, message, coin);
|
||||
}
|
||||
return true;
|
||||
|
||||
// Cash URI with bitcoin core address version number?
|
||||
} else if (bitcore.URI.isValid(data.replace(/^bitcoincash:/,'bitcoin:'))) {
|
||||
$log.debug('Handling bitcoincash URI with legacy address');
|
||||
var coin = 'bch';
|
||||
var parsed = new bitcore.URI(data.replace(/^bitcoincash:/,'bitcoin:'));
|
||||
|
||||
var oldAddr = parsed.address ? parsed.address.toString() : '';
|
||||
if (!oldAddr) return false;
|
||||
|
||||
var addr = '';
|
||||
|
||||
var a = bitcore.Address(oldAddr).toObject();
|
||||
addr = bitcoreCash.Address.fromObject(a).toString();
|
||||
|
||||
// Translate address
|
||||
$log.debug('address transalated to:' + addr);
|
||||
popupService.showConfirm(
|
||||
gettextCatalog.getString('Bitcoin cash Payment'),
|
||||
gettextCatalog.getString('Payment address was translated to new Bitcoin Cash address format: ' + addr),
|
||||
gettextCatalog.getString('OK'),
|
||||
gettextCatalog.getString('Cancel'),
|
||||
function(ret) {
|
||||
if (!ret) return false;
|
||||
|
||||
var message = parsed.message;
|
||||
var amount = parsed.amount ? parsed.amount : '';
|
||||
|
||||
// paypro not yet supported on cash
|
||||
if (parsed.r) {
|
||||
payproService.getPayProDetails(parsed.r, function(err, details) {
|
||||
if (err) {
|
||||
if (addr && amount)
|
||||
goSend(addr, amount, message, coin);
|
||||
else
|
||||
popupService.showAlert(gettextCatalog.getString('Error'), err);
|
||||
}
|
||||
handlePayPro(details, coin);
|
||||
});
|
||||
} else {
|
||||
goSend(addr, amount, message, coin);
|
||||
}
|
||||
}
|
||||
);
|
||||
return true;
|
||||
|
||||
// Plain URL
|
||||
} else if (/^https?:\/\//.test(data)) {
|
||||
|
||||
|
|
@ -127,6 +199,16 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat
|
|||
} else {
|
||||
goToAmountPage(data);
|
||||
}
|
||||
} else if (bitcoreCash.Address.isValid(data, 'livenet')) {
|
||||
if ($state.includes('tabs.scan')) {
|
||||
root.showMenu({
|
||||
data: data,
|
||||
type: 'bitcoinAddress',
|
||||
coin: 'bch',
|
||||
});
|
||||
} else {
|
||||
goToAmountPage(data, 'bch');
|
||||
}
|
||||
} else if (data && data.indexOf(appConfigService.name + '://glidera') === 0) {
|
||||
var code = getParameterByName('code', data);
|
||||
$ionicHistory.nextViewOptions({
|
||||
|
|
@ -236,29 +318,29 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
};
|
||||
|
||||
function goToAmountPage(toAddress) {
|
||||
function goToAmountPage(toAddress, coin) {
|
||||
$state.go('tabs.send', {}, {
|
||||
'reload': true,
|
||||
'notify': $state.current.name == 'tabs.send' ? false : true
|
||||
});
|
||||
$timeout(function() {
|
||||
$state.transitionTo('tabs.send.amount', {
|
||||
toAddress: toAddress
|
||||
toAddress: toAddress,
|
||||
coin: coin,
|
||||
});
|
||||
}, 100);
|
||||
}
|
||||
|
||||
function handlePayPro(payProDetails) {
|
||||
function handlePayPro(payProDetails, coin) {
|
||||
var stateParams = {
|
||||
toAmount: payProDetails.amount,
|
||||
toAddress: payProDetails.toAddress,
|
||||
description: payProDetails.memo,
|
||||
paypro: payProDetails
|
||||
paypro: payProDetails,
|
||||
coin: coin,
|
||||
};
|
||||
scannerService.pausePreview();
|
||||
$state.go('tabs.send', {}, {
|
||||
|
|
|
|||
183
src/js/services/mercadoLibreService.js
Normal file
183
src/js/services/mercadoLibreService.js
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
'use strict';
|
||||
angular.module('copayApp.services').factory('mercadoLibreService', function($http, $log, lodash, moment, storageService, configService, platformInfo, nextStepsService, homeIntegrationsService) {
|
||||
var root = {};
|
||||
var credentials = {};
|
||||
|
||||
// Not used yet
|
||||
var availableCountries = [{
|
||||
'country': 'Brazil',
|
||||
'currency': 'BRL',
|
||||
'name': 'Mercado Livre',
|
||||
'url': 'https://www.mercadolivre.com.br'
|
||||
}];
|
||||
|
||||
/*
|
||||
* Development: 'testnet'
|
||||
* Production: 'livenet'
|
||||
*/
|
||||
credentials.NETWORK = 'livenet';
|
||||
//credentials.NETWORK = 'testnet';
|
||||
|
||||
if (credentials.NETWORK == 'testnet') {
|
||||
credentials.BITPAY_API_URL = "https://test.bitpay.com";
|
||||
} else {
|
||||
credentials.BITPAY_API_URL = "https://bitpay.com";
|
||||
};
|
||||
|
||||
var homeItem = {
|
||||
name: 'mercadoLibre',
|
||||
title: 'Vales-Presente do Mercado Livre Brasil',
|
||||
icon: 'icon-ml',
|
||||
sref: 'tabs.giftcards.mercadoLibre',
|
||||
};
|
||||
|
||||
var nextStepItem = {
|
||||
name: 'mercadoLibre',
|
||||
title: 'Comprar um Vale-Presente Mercado Livre',
|
||||
icon: 'icon-ml',
|
||||
sref: 'tabs.giftcards.mercadoLibre',
|
||||
};
|
||||
|
||||
var _getBitPay = function(endpoint) {
|
||||
return {
|
||||
method: 'GET',
|
||||
url: credentials.BITPAY_API_URL + endpoint,
|
||||
headers: {
|
||||
'content-type': 'application/json'
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
var _postBitPay = function(endpoint, data) {
|
||||
return {
|
||||
method: 'POST',
|
||||
url: credentials.BITPAY_API_URL + endpoint,
|
||||
headers: {
|
||||
'content-type': 'application/json'
|
||||
},
|
||||
data: data
|
||||
};
|
||||
};
|
||||
|
||||
root.getNetwork = function() {
|
||||
return credentials.NETWORK;
|
||||
};
|
||||
|
||||
root.savePendingGiftCard = function(gc, opts, cb) {
|
||||
var network = root.getNetwork();
|
||||
storageService.getMercadoLibreGiftCards(network, function(err, oldGiftCards) {
|
||||
if (lodash.isString(oldGiftCards)) {
|
||||
oldGiftCards = JSON.parse(oldGiftCards);
|
||||
}
|
||||
if (lodash.isString(gc)) {
|
||||
gc = JSON.parse(gc);
|
||||
}
|
||||
var inv = oldGiftCards || {};
|
||||
inv[gc.invoiceId] = gc;
|
||||
if (opts && (opts.error || opts.status)) {
|
||||
inv[gc.invoiceId] = lodash.assign(inv[gc.invoiceId], opts);
|
||||
}
|
||||
if (opts && opts.remove) {
|
||||
delete(inv[gc.invoiceId]);
|
||||
}
|
||||
|
||||
inv = JSON.stringify(inv);
|
||||
|
||||
|
||||
storageService.setMercadoLibreGiftCards(network, inv, function(err) {
|
||||
|
||||
homeIntegrationsService.register(homeItem);
|
||||
nextStepsService.unregister(nextStepItem.name);
|
||||
return cb(err);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
root.getPendingGiftCards = function(cb) {
|
||||
var network = root.getNetwork();
|
||||
storageService.getMercadoLibreGiftCards(network, function(err, giftCards) {
|
||||
var _gcds = giftCards ? JSON.parse(giftCards) : null;
|
||||
return cb(err, _gcds);
|
||||
});
|
||||
};
|
||||
|
||||
root.createBitPayInvoice = function(data, cb) {
|
||||
var dataSrc = {
|
||||
currency: data.currency,
|
||||
amount: data.amount,
|
||||
clientId: data.uuid
|
||||
};
|
||||
|
||||
$http(_postBitPay('/mercado-libre-gift/pay', dataSrc)).then(function(data) {
|
||||
$log.info('BitPay Create Invoice: SUCCESS');
|
||||
return cb(null, data.data);
|
||||
}, function(data) {
|
||||
$log.error('BitPay Create Invoice: ERROR', JSON.stringify(data.data));
|
||||
return cb(data.data);
|
||||
});
|
||||
};
|
||||
|
||||
root.getBitPayInvoice = function(id, cb) {
|
||||
$http(_getBitPay('/invoices/' + id)).then(function(data) {
|
||||
$log.info('BitPay Get Invoice: SUCCESS');
|
||||
return cb(null, data.data.data);
|
||||
}, function(data) {
|
||||
$log.error('BitPay Get Invoice: ERROR', JSON.stringify(data.data));
|
||||
return cb(data.data);
|
||||
});
|
||||
};
|
||||
|
||||
root.createGiftCard = function(data, cb) {
|
||||
var dataSrc = {
|
||||
"clientId": data.uuid,
|
||||
"invoiceId": data.invoiceId,
|
||||
"accessKey": data.accessKey
|
||||
};
|
||||
|
||||
$http(_postBitPay('/mercado-libre-gift/redeem', dataSrc)).then(function(data) {
|
||||
var status = data.data.status == 'new' ? 'PENDING' : (data.data.status == 'paid') ? 'PENDING' : data.data.status;
|
||||
data.data.status = status;
|
||||
$log.info('Mercado Libre Gift Card Create/Update: ' + status);
|
||||
return cb(null, data.data);
|
||||
}, function(data) {
|
||||
$log.error('Mercado Libre Gift Card Create/Update: ERROR', JSON.stringify(data.data));
|
||||
return cb(data.data);
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* Disabled for now *
|
||||
*/
|
||||
/*
|
||||
root.cancelGiftCard = function(data, cb) {
|
||||
|
||||
var dataSrc = {
|
||||
"clientId": data.uuid,
|
||||
"invoiceId": data.invoiceId,
|
||||
"accessKey": data.accessKey
|
||||
};
|
||||
|
||||
$http(_postBitPay('/mercado-libre-gift/cancel', dataSrc)).then(function(data) {
|
||||
$log.info('Mercado Libre Gift Card Cancel: SUCCESS');
|
||||
return cb(null, data.data);
|
||||
}, function(data) {
|
||||
$log.error('Mercado Libre Gift Card Cancel: ' + data.data.message);
|
||||
return cb(data.data);
|
||||
});
|
||||
};
|
||||
*/
|
||||
|
||||
var register = function() {
|
||||
storageService.getMercadoLibreGiftCards(root.getNetwork(), function(err, giftCards) {
|
||||
if (giftCards) {
|
||||
homeIntegrationsService.register(homeItem);
|
||||
} else {
|
||||
nextStepsService.register(nextStepItem);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Hide Mercado Libre
|
||||
// register();
|
||||
return root;
|
||||
});
|
||||
|
|
@ -45,7 +45,8 @@ angular.module('copayApp.services').factory('ongoingProcess', function($log, $ti
|
|||
'cancelingGiftCard': 'Canceling Gift Card...',
|
||||
'creatingGiftCard': 'Creating Gift Card...',
|
||||
'buyingGiftCard': 'Buying Gift Card...',
|
||||
'topup': gettext('Top up in progress...')
|
||||
'topup': gettext('Top up in progress...'),
|
||||
'duplicatingWallet': gettext('Duplicating wallet...'),
|
||||
};
|
||||
|
||||
root.clear = function() {
|
||||
|
|
|
|||
|
|
@ -57,10 +57,10 @@ angular.module('copayApp.services').factory('openURLService', function($rootScop
|
|||
|
||||
// This event is sent to an existent instance of Copay (only for standalone apps)
|
||||
gui.App.on('open', function(pathData) {
|
||||
if (pathData.indexOf('bitcoin:') != -1) {
|
||||
if (pathData.indexOf(/^bitcoin(cash)?:/) != -1) {
|
||||
$log.debug('Bitcoin URL found');
|
||||
handleOpenURL({
|
||||
url: pathData.substring(pathData.indexOf('bitcoin:'))
|
||||
url: pathData.substring(pathData.indexOf(/^bitcoin(cash)?:/))
|
||||
});
|
||||
} else if (pathData.indexOf(appConfigService.name + '://') != -1) {
|
||||
$log.debug(appConfigService.name + ' URL found');
|
||||
|
|
@ -84,6 +84,7 @@ angular.module('copayApp.services').factory('openURLService', function($rootScop
|
|||
if (navigator.registerProtocolHandler) {
|
||||
$log.debug('Registering Browser handlers base:' + base);
|
||||
navigator.registerProtocolHandler('bitcoin', url, 'Copay Bitcoin Handler');
|
||||
navigator.registerProtocolHandler('web+bitcoincash', url, 'Copay Bitcoin Cash Handler');
|
||||
navigator.registerProtocolHandler('web+copay', url, 'Copay Wallet Handler');
|
||||
navigator.registerProtocolHandler('web+bitpay', url, 'BitPay Wallet Handler');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
'use strict';
|
||||
angular.module('copayApp.services')
|
||||
.factory('profileService', function profileServiceFactory($rootScope, $timeout, $filter, $log, sjcl, lodash, storageService, bwcService, configService, gettextCatalog, bwcError, uxLanguage, platformInfo, txFormatService, $state) {
|
||||
.factory('profileService', function profileServiceFactory($rootScope, $timeout, $filter, $log, $state, sjcl, lodash, storageService, bwcService, configService, gettextCatalog, bwcError, uxLanguage, platformInfo, txFormatService, appConfigService) {
|
||||
|
||||
|
||||
var isChromeApp = platformInfo.isChromeApp;
|
||||
|
|
@ -89,6 +89,7 @@ angular.module('copayApp.services')
|
|||
wallet.copayerId = wallet.credentials.copayerId;
|
||||
wallet.m = wallet.credentials.m;
|
||||
wallet.n = wallet.credentials.n;
|
||||
wallet.coin = wallet.credentials.coin;
|
||||
|
||||
root.updateWalletSettings(wallet);
|
||||
root.wallet[walletId] = wallet;
|
||||
|
|
@ -222,11 +223,12 @@ angular.module('copayApp.services')
|
|||
return ((config.bwsFor && config.bwsFor[walletId]) || defaults.bws.url);
|
||||
};
|
||||
|
||||
|
||||
var client = bwcService.getClient(JSON.stringify(credentials), {
|
||||
bwsurl: getBWSURL(credentials.walletId),
|
||||
});
|
||||
|
||||
|
||||
|
||||
var skipKeyValidation = shouldSkipValidation(credentials.walletId);
|
||||
if (!skipKeyValidation)
|
||||
root.runValidation(client, 500);
|
||||
|
|
@ -328,6 +330,7 @@ angular.module('copayApp.services')
|
|||
passphrase: opts.passphrase,
|
||||
account: opts.account || 0,
|
||||
derivationStrategy: opts.derivationStrategy || 'BIP44',
|
||||
coin: opts.coin
|
||||
});
|
||||
|
||||
} catch (ex) {
|
||||
|
|
@ -336,7 +339,12 @@ angular.module('copayApp.services')
|
|||
}
|
||||
} else if (opts.extendedPrivateKey) {
|
||||
try {
|
||||
walletClient.seedFromExtendedPrivateKey(opts.extendedPrivateKey);
|
||||
walletClient.seedFromExtendedPrivateKey(opts.extendedPrivateKey, {
|
||||
network: network,
|
||||
account: opts.account || 0,
|
||||
derivationStrategy: opts.derivationStrategy || 'BIP44',
|
||||
coin: opts.coin,
|
||||
});
|
||||
} catch (ex) {
|
||||
$log.warn(ex);
|
||||
return cb(gettextCatalog.getString('Could not create using the specified extended private key'));
|
||||
|
|
@ -346,6 +354,7 @@ angular.module('copayApp.services')
|
|||
walletClient.seedFromExtendedPublicKey(opts.extendedPublicKey, opts.externalSource, opts.entropySource, {
|
||||
account: opts.account || 0,
|
||||
derivationStrategy: opts.derivationStrategy || 'BIP44',
|
||||
coin: opts.coin
|
||||
});
|
||||
walletClient.credentials.hwInfo = opts.hwInfo;
|
||||
} catch (ex) {
|
||||
|
|
@ -360,6 +369,7 @@ angular.module('copayApp.services')
|
|||
passphrase: opts.passphrase,
|
||||
language: lang,
|
||||
account: 0,
|
||||
coin: opts.coin
|
||||
});
|
||||
} catch (e) {
|
||||
$log.info('Error creating recovery phrase: ' + e.message);
|
||||
|
|
@ -369,6 +379,7 @@ angular.module('copayApp.services')
|
|||
network: network,
|
||||
passphrase: opts.passphrase,
|
||||
account: 0,
|
||||
coin: opts.coin
|
||||
});
|
||||
} else {
|
||||
return cb(e);
|
||||
|
|
@ -380,7 +391,11 @@ angular.module('copayApp.services')
|
|||
|
||||
// Creates a wallet on BWC/BWS
|
||||
var doCreateWallet = function(opts, cb) {
|
||||
$log.debug('Creating Wallet:', opts);
|
||||
var showOpts = lodash.clone(opts);
|
||||
if (showOpts.extendedPrivateKey) showOpts.extendedPrivateKey='[hidden]';
|
||||
if (showOpts.mnemonic) showOpts.mnemonic='[hidden]';
|
||||
|
||||
$log.debug('Creating Wallet:', showOpts);
|
||||
$timeout(function() {
|
||||
seedWallet(opts, function(err, walletClient) {
|
||||
if (err) return cb(err);
|
||||
|
|
@ -392,6 +407,7 @@ angular.module('copayApp.services')
|
|||
network: opts.networkName,
|
||||
singleAddress: opts.singleAddress,
|
||||
walletPrivKey: opts.walletPrivKey,
|
||||
coin: opts.coin
|
||||
}, function(err, secret) {
|
||||
if (err) return bwcError.cb(err, gettextCatalog.getString('Error creating wallet'), cb);
|
||||
return cb(null, walletClient, secret);
|
||||
|
|
@ -435,7 +451,9 @@ angular.module('copayApp.services')
|
|||
seedWallet(opts, function(err, walletClient) {
|
||||
if (err) return cb(err);
|
||||
|
||||
walletClient.joinWallet(opts.secret, opts.myName || 'me', {}, function(err) {
|
||||
walletClient.joinWallet(opts.secret, opts.myName || 'me', {
|
||||
coin: opts.coin
|
||||
}, function(err) {
|
||||
if (err) return bwcError.cb(err, gettextCatalog.getString('Could not join wallet'), cb);
|
||||
addAndBindWalletClient(walletClient, {
|
||||
bwsurl: opts.bwsurl
|
||||
|
|
@ -495,7 +513,9 @@ angular.module('copayApp.services')
|
|||
var walletId = client.credentials.walletId
|
||||
|
||||
if (!root.profile.addWallet(JSON.parse(client.export())))
|
||||
return cb(gettextCatalog.getString('Wallet already in Copay'));
|
||||
return cb(gettextCatalog.getString("Wallet already in {{appName}}", {
|
||||
appName: appConfigService.nameCase
|
||||
}));
|
||||
|
||||
|
||||
var skipKeyValidation = shouldSkipValidation(walletId);
|
||||
|
|
@ -621,6 +641,7 @@ angular.module('copayApp.services')
|
|||
entropySourcePath: opts.entropySourcePath,
|
||||
derivationStrategy: opts.derivationStrategy || 'BIP44',
|
||||
account: opts.account || 0,
|
||||
coin: opts.coin
|
||||
}, function(err) {
|
||||
if (err) {
|
||||
if (err instanceof errors.NOT_AUTHORIZED)
|
||||
|
|
@ -642,6 +663,7 @@ angular.module('copayApp.services')
|
|||
walletClient.importFromExtendedPublicKey(opts.extendedPublicKey, opts.externalSource, opts.entropySource, {
|
||||
account: opts.account || 0,
|
||||
derivationStrategy: opts.derivationStrategy || 'BIP44',
|
||||
coin: opts.coin
|
||||
}, function(err) {
|
||||
if (err) {
|
||||
|
||||
|
|
@ -682,6 +704,7 @@ angular.module('copayApp.services')
|
|||
opts.m = 1;
|
||||
opts.n = 1;
|
||||
opts.networkName = 'livenet';
|
||||
opts.coin = 'btc';
|
||||
root.createWallet(opts, cb);
|
||||
};
|
||||
|
||||
|
|
@ -747,6 +770,12 @@ angular.module('copayApp.services')
|
|||
|
||||
var ret = lodash.values(root.wallet);
|
||||
|
||||
if (opts.coin) {
|
||||
ret = lodash.filter(ret, function(x) {
|
||||
return (x.credentials.coin == opts.coin);
|
||||
});
|
||||
}
|
||||
|
||||
if (opts.network) {
|
||||
ret = lodash.filter(ret, function(x) {
|
||||
return (x.credentials.network == opts.network);
|
||||
|
|
@ -767,12 +796,14 @@ angular.module('copayApp.services')
|
|||
|
||||
if (opts.hasFunds) {
|
||||
ret = lodash.filter(ret, function(w) {
|
||||
if (!w.status) return;
|
||||
return (w.status.availableBalanceSat > 0);
|
||||
});
|
||||
}
|
||||
|
||||
if (opts.minAmount) {
|
||||
ret = lodash.filter(ret, function(w) {
|
||||
if (!w.status) return;
|
||||
return (w.status.availableBalanceSat > opts.minAmount);
|
||||
});
|
||||
}
|
||||
|
|
@ -857,7 +888,7 @@ angular.module('copayApp.services')
|
|||
x.types = [x.type];
|
||||
|
||||
if (x.data && x.data.amount)
|
||||
x.amountStr = txFormatService.formatAmountStr(x.data.amount);
|
||||
x.amountStr = txFormatService.formatAmountStr(x.wallet.coin, x.data.amount);
|
||||
|
||||
x.action = function() {
|
||||
// TODO?
|
||||
|
|
|
|||
|
|
@ -25,9 +25,10 @@ var RateService = function(opts) {
|
|||
self._isAvailable = false;
|
||||
self._rates = {};
|
||||
self._alternatives = [];
|
||||
self._ratesBCH = {};
|
||||
self._queued = [];
|
||||
|
||||
self._fetchCurrencies();
|
||||
self.updateRates();
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -39,14 +40,20 @@ RateService.singleton = function(opts) {
|
|||
return _instance;
|
||||
};
|
||||
|
||||
RateService.prototype._fetchCurrencies = function() {
|
||||
RateService.prototype.updateRates = function() {
|
||||
var self = this;
|
||||
|
||||
var backoffSeconds = 5;
|
||||
var updateFrequencySeconds = 5 * 60;
|
||||
var rateServiceUrl = 'https://bitpay.com/api/rates';
|
||||
var bchRateServiceUrl = 'https://api.kraken.com/0/public/Ticker?pair=BCHUSD,BCHEUR';
|
||||
|
||||
|
||||
function getBTC(cb, tries) {
|
||||
tries = tries || 0;
|
||||
if (!self.httprequest) return;
|
||||
if (tries > 5) return cb('could not get BTC rates');
|
||||
|
||||
var retrieve = function() {
|
||||
//log.info('Fetching exchange rates');
|
||||
self.httprequest.get(rateServiceUrl).success(function(res) {
|
||||
self.lodash.each(res, function(currency) {
|
||||
|
|
@ -57,27 +64,64 @@ RateService.prototype._fetchCurrencies = function() {
|
|||
rate: currency.rate
|
||||
});
|
||||
});
|
||||
|
||||
return cb();
|
||||
}).error(function() {
|
||||
//log.debug('Error fetching exchange rates', err);
|
||||
setTimeout(function() {
|
||||
backoffSeconds *= 1.5;
|
||||
getBTC(cb, tries++);
|
||||
}, backoffSeconds * 1000);
|
||||
return;
|
||||
})
|
||||
}
|
||||
|
||||
function getBCH(cb, tries) {
|
||||
tries = tries || 0;
|
||||
if (!self.httprequest) return;
|
||||
if (tries > 5) return cb('could not get BCH rates');
|
||||
|
||||
function retry(tries) {
|
||||
//log.debug('Error fetching exchange rates', err);
|
||||
setTimeout(function() {
|
||||
backoffSeconds *= 1.5;
|
||||
getBTC(cb, tries++);
|
||||
}, backoffSeconds * 1000);
|
||||
return;
|
||||
}
|
||||
|
||||
self.httprequest.get(bchRateServiceUrl).success(function(res) {
|
||||
self.lodash.each(res.result, function(data, paircode) {
|
||||
var code = paircode.substr(3,3);
|
||||
var rate =data.c[0];
|
||||
self._ratesBCH[code] = rate;
|
||||
})
|
||||
return cb();
|
||||
}).error(function() {
|
||||
return retry(tries);
|
||||
})
|
||||
}
|
||||
|
||||
getBTC(function(err) {
|
||||
if (err) return;
|
||||
getBCH(function(err) {
|
||||
if (err) return;
|
||||
|
||||
self._isAvailable = true;
|
||||
self.lodash.each(self._queued, function(callback) {
|
||||
setTimeout(callback, 1);
|
||||
});
|
||||
setTimeout(retrieve, updateFrequencySeconds * 1000);
|
||||
}).error(function(err) {
|
||||
//log.debug('Error fetching exchange rates', err);
|
||||
setTimeout(function() {
|
||||
backoffSeconds *= 1.5;
|
||||
retrieve();
|
||||
}, backoffSeconds * 1000);
|
||||
return;
|
||||
});
|
||||
setTimeout( self.updateRates , updateFrequencySeconds * 1000);
|
||||
})
|
||||
})
|
||||
|
||||
};
|
||||
|
||||
retrieve();
|
||||
};
|
||||
|
||||
RateService.prototype.getRate = function(code) {
|
||||
return this._rates[code];
|
||||
RateService.prototype.getRate = function(code, chain) {
|
||||
if (chain == 'bch')
|
||||
return this._ratesBCH[code];
|
||||
else
|
||||
return this._rates[code];
|
||||
};
|
||||
|
||||
RateService.prototype.getAlternatives = function() {
|
||||
|
|
@ -90,25 +134,25 @@ RateService.prototype.isAvailable = function() {
|
|||
|
||||
RateService.prototype.whenAvailable = function(callback) {
|
||||
if (this.isAvailable()) {
|
||||
setTimeout(callback, 1);
|
||||
setTimeout(callback, 10);
|
||||
} else {
|
||||
this._queued.push(callback);
|
||||
}
|
||||
};
|
||||
|
||||
RateService.prototype.toFiat = function(satoshis, code) {
|
||||
RateService.prototype.toFiat = function(satoshis, code, chain) {
|
||||
if (!this.isAvailable()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return satoshis * this.SAT_TO_BTC * this.getRate(code);
|
||||
return satoshis * this.SAT_TO_BTC * this.getRate(code, chain);
|
||||
};
|
||||
|
||||
RateService.prototype.fromFiat = function(amount, code) {
|
||||
RateService.prototype.fromFiat = function(amount, code, chain) {
|
||||
if (!this.isAvailable()) {
|
||||
return null;
|
||||
}
|
||||
return amount / this.getRate(code) * this.BTC_TO_SAT;
|
||||
return amount / this.getRate(code, chain) * this.BTC_TO_SAT;
|
||||
};
|
||||
|
||||
RateService.prototype.listAlternatives = function(sort) {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ angular.module('copayApp.services').service('sendMaxService', function(feeServic
|
|||
*
|
||||
*/
|
||||
this.getInfo = function(wallet, cb) {
|
||||
feeService.getCurrentFeeRate(wallet.credentials.network, function(err, feePerKb) {
|
||||
feeService.getCurrentFeeRate(wallet.coin, wallet.credentials.network, function(err, feePerKb) {
|
||||
if (err) return cb(err);
|
||||
|
||||
var config = configService.getSync().wallet;
|
||||
|
|
|
|||
|
|
@ -610,5 +610,17 @@ angular.module('copayApp.services')
|
|||
storage.remove('txConfirmNotif-' + txid, cb);
|
||||
};
|
||||
|
||||
root.setMercadoLibreGiftCards = function(network, gcs, cb) {
|
||||
storage.set('mercadoLibreGiftCards-' + network, gcs, cb);
|
||||
};
|
||||
|
||||
root.getMercadoLibreGiftCards = function(network, cb) {
|
||||
storage.get('mercadoLibreGiftCards-' + network, cb);
|
||||
};
|
||||
|
||||
root.removeMercadoLibreGiftCards = function(network, cb) {
|
||||
storage.remove('MercadoLibreGiftCards-' + network, cb);
|
||||
};
|
||||
|
||||
return root;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ angular.module('copayApp.services').factory('txFormatService', function($filter,
|
|||
|
||||
|
||||
root.formatAmount = function(satoshis, fullPrecision) {
|
||||
var config = configService.getSync().wallet.settings;
|
||||
var config = configService.getDefaults().wallet.settings;
|
||||
if (config.unitCode == 'sat') return satoshis;
|
||||
|
||||
//TODO : now only works for english, specify opts to change thousand separator and decimal separator
|
||||
|
|
@ -17,16 +17,15 @@ angular.module('copayApp.services').factory('txFormatService', function($filter,
|
|||
return this.Utils.formatAmount(satoshis, config.unitCode, opts);
|
||||
};
|
||||
|
||||
root.formatAmountStr = function(satoshis) {
|
||||
root.formatAmountStr = function(coin, satoshis) {
|
||||
if (isNaN(satoshis)) return;
|
||||
var config = configService.getSync().wallet.settings;
|
||||
return root.formatAmount(satoshis) + ' ' + config.unitName;
|
||||
return root.formatAmount(satoshis) + ' ' + (coin).toUpperCase();
|
||||
};
|
||||
|
||||
root.toFiat = function(satoshis, code, cb) {
|
||||
root.toFiat = function(coin, satoshis, code, cb) {
|
||||
if (isNaN(satoshis)) return;
|
||||
var val = function() {
|
||||
var v1 = rateService.toFiat(satoshis, code);
|
||||
var v1 = rateService.toFiat(satoshis, code, coin);
|
||||
if (!v1) return null;
|
||||
|
||||
return v1.toFixed(2);
|
||||
|
|
@ -43,10 +42,10 @@ angular.module('copayApp.services').factory('txFormatService', function($filter,
|
|||
};
|
||||
};
|
||||
|
||||
root.formatToUSD = function(satoshis, cb) {
|
||||
root.formatToUSD = function(coin, satoshis, cb) {
|
||||
if (isNaN(satoshis)) return;
|
||||
var val = function() {
|
||||
var v1 = rateService.toFiat(satoshis, 'USD');
|
||||
var v1 = rateService.toFiat(satoshis, 'USD', coin);
|
||||
if (!v1) return null;
|
||||
|
||||
return v1.toFixed(2);
|
||||
|
|
@ -63,12 +62,12 @@ angular.module('copayApp.services').factory('txFormatService', function($filter,
|
|||
};
|
||||
};
|
||||
|
||||
root.formatAlternativeStr = function(satoshis, cb) {
|
||||
root.formatAlternativeStr = function(coin, satoshis, cb) {
|
||||
if (isNaN(satoshis)) return;
|
||||
var config = configService.getSync().wallet.settings;
|
||||
|
||||
var val = function() {
|
||||
var v1 = parseFloat((rateService.toFiat(satoshis, config.alternativeIsoCode)).toFixed(2));
|
||||
var v1 = parseFloat((rateService.toFiat(satoshis, config.alternativeIsoCode, coin)).toFixed(2));
|
||||
v1 = $filter('formatFiatAmount')(v1);
|
||||
if (!v1) return null;
|
||||
|
||||
|
|
@ -86,7 +85,7 @@ angular.module('copayApp.services').factory('txFormatService', function($filter,
|
|||
};
|
||||
};
|
||||
|
||||
root.processTx = function(tx) {
|
||||
root.processTx = function(coin, tx) {
|
||||
if (!tx || tx.action == 'invalid')
|
||||
return tx;
|
||||
|
||||
|
|
@ -101,17 +100,17 @@ angular.module('copayApp.services').factory('txFormatService', function($filter,
|
|||
tx.hasMultiplesOutputs = true;
|
||||
}
|
||||
tx.amount = lodash.reduce(tx.outputs, function(total, o) {
|
||||
o.amountStr = root.formatAmountStr(o.amount);
|
||||
o.alternativeAmountStr = root.formatAlternativeStr(o.amount);
|
||||
o.amountStr = root.formatAmountStr(coin, o.amount);
|
||||
o.alternativeAmountStr = root.formatAlternativeStr(coin, o.amount);
|
||||
return total + o.amount;
|
||||
}, 0);
|
||||
}
|
||||
tx.toAddress = tx.outputs[0].toAddress;
|
||||
}
|
||||
|
||||
tx.amountStr = root.formatAmountStr(tx.amount);
|
||||
tx.alternativeAmountStr = root.formatAlternativeStr(tx.amount);
|
||||
tx.feeStr = root.formatAmountStr(tx.fee || tx.fees);
|
||||
tx.amountStr = root.formatAmountStr(coin, tx.amount);
|
||||
tx.alternativeAmountStr = root.formatAlternativeStr(coin, tx.amount);
|
||||
tx.feeStr = root.formatAmountStr(coin, tx.fee || tx.fees);
|
||||
|
||||
if (tx.amountStr) {
|
||||
tx.amountValueStr = tx.amountStr.split(' ')[0];
|
||||
|
|
@ -145,8 +144,6 @@ angular.module('copayApp.services').factory('txFormatService', function($filter,
|
|||
|
||||
lodash.each(txps, function(tx) {
|
||||
|
||||
tx = txFormatService.processTx(tx);
|
||||
|
||||
// no future transactions...
|
||||
if (tx.createdOn > now)
|
||||
tx.createdOn = now;
|
||||
|
|
@ -157,6 +154,8 @@ angular.module('copayApp.services').factory('txFormatService', function($filter,
|
|||
return;
|
||||
}
|
||||
|
||||
tx = txFormatService.processTx(tx.wallet.coin, tx);
|
||||
|
||||
var action = lodash.find(tx.actions, {
|
||||
copayerId: tx.wallet.copayerId
|
||||
});
|
||||
|
|
@ -180,7 +179,7 @@ angular.module('copayApp.services').factory('txFormatService', function($filter,
|
|||
return txps;
|
||||
};
|
||||
|
||||
root.parseAmount = function(amount, currency) {
|
||||
root.parseAmount = function(coin, amount, currency) {
|
||||
var config = configService.getSync().wallet.settings;
|
||||
var satToBtc = 1 / 100000000;
|
||||
var unitToSatoshi = config.unitToSatoshi;
|
||||
|
|
@ -189,21 +188,21 @@ angular.module('copayApp.services').factory('txFormatService', function($filter,
|
|||
var alternativeIsoCode = config.alternativeIsoCode;
|
||||
|
||||
// If fiat currency
|
||||
if (currency != 'bits' && currency != 'BTC' && currency != 'sat') {
|
||||
if (currency != 'BCH' && currency != 'BTC' && currency != 'sat') {
|
||||
amountUnitStr = $filter('formatFiatAmount')(amount) + ' ' + currency;
|
||||
amountSat = rateService.fromFiat(amount, currency).toFixed(0);
|
||||
amountSat = rateService.fromFiat(amount, currency, coin).toFixed(0);
|
||||
} else if (currency == 'sat') {
|
||||
amountSat = amount;
|
||||
amountUnitStr = root.formatAmountStr(amountSat);
|
||||
// convert sat to BTC
|
||||
amountUnitStr = root.formatAmountStr(coin, amountSat);
|
||||
// convert sat to BTC or BCH
|
||||
amount = (amountSat * satToBtc).toFixed(8);
|
||||
currency = 'BTC';
|
||||
currency = (coin).toUpperCase();
|
||||
} else {
|
||||
amountSat = parseInt((amount * unitToSatoshi).toFixed(0));
|
||||
amountUnitStr = root.formatAmountStr(amountSat);
|
||||
// convert unit to BTC
|
||||
amountUnitStr = root.formatAmountStr(coin, amountSat);
|
||||
// convert unit to BTC or BCH
|
||||
amount = (amountSat * satToBtc).toFixed(8);
|
||||
currency = 'BTC';
|
||||
currency = (coin).toUpperCase();
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@ angular.module('copayApp.services')
|
|||
}, {
|
||||
name: 'Italiano',
|
||||
isoCode: 'it',
|
||||
}, {
|
||||
name: 'Nederlands',
|
||||
isoCode: 'nl',
|
||||
}, {
|
||||
name: 'Polski',
|
||||
isoCode: 'pl',
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
angular.module('copayApp.services').factory('walletService', function($log, $timeout, lodash, trezor, ledger, intelTEE, storageService, configService, rateService, uxLanguage, $filter, gettextCatalog, bwcError, $ionicPopup, fingerprintService, ongoingProcess, gettext, $rootScope, txFormatService, $ionicModal, $state, bwcService, bitcore, popupService) {
|
||||
|
||||
// Ratio low amount warning (fee/amount) in incoming TX
|
||||
var LOW_AMOUNT_RATIO = 0.15;
|
||||
// Ratio low amount warning (fee/amount) in incoming TX
|
||||
var LOW_AMOUNT_RATIO = 0.15;
|
||||
|
||||
// Ratio of "many utxos" warning in total balance (fee/amount)
|
||||
var TOTAL_LOW_WARNING_RATIO = .3;
|
||||
|
|
@ -104,7 +104,7 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
|
||||
root.getStatus = function(wallet, opts, cb) {
|
||||
opts = opts || {};
|
||||
|
||||
var walletId = wallet.id;
|
||||
|
||||
function processPendingTxps(status) {
|
||||
var txps = status.pendingTxps;
|
||||
|
|
@ -130,7 +130,7 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
|
||||
lodash.each(txps, function(tx) {
|
||||
|
||||
tx = txFormatService.processTx(tx);
|
||||
tx = txFormatService.processTx(wallet.coin, tx);
|
||||
|
||||
// no future transactions...
|
||||
if (tx.createdOn > now)
|
||||
|
|
@ -213,14 +213,13 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
// Selected unit
|
||||
cache.unitToSatoshi = config.settings.unitToSatoshi;
|
||||
cache.satToUnit = 1 / cache.unitToSatoshi;
|
||||
cache.unitName = config.settings.unitName;
|
||||
|
||||
//STR
|
||||
cache.totalBalanceStr = txFormatService.formatAmount(cache.totalBalanceSat) + ' ' + cache.unitName;
|
||||
cache.lockedBalanceStr = txFormatService.formatAmount(cache.lockedBalanceSat) + ' ' + cache.unitName;
|
||||
cache.availableBalanceStr = txFormatService.formatAmount(cache.availableBalanceSat) + ' ' + cache.unitName;
|
||||
cache.spendableBalanceStr = txFormatService.formatAmount(cache.spendableAmount) + ' ' + cache.unitName;
|
||||
cache.pendingBalanceStr = txFormatService.formatAmount(cache.pendingAmount) + ' ' + cache.unitName;
|
||||
cache.totalBalanceStr = txFormatService.formatAmountStr(wallet.coin, cache.totalBalanceSat);
|
||||
cache.lockedBalanceStr = txFormatService.formatAmountStr(wallet.coin, cache.lockedBalanceSat);
|
||||
cache.availableBalanceStr = txFormatService.formatAmountStr(wallet.coin, cache.availableBalanceSat);
|
||||
cache.spendableBalanceStr = txFormatService.formatAmountStr(wallet.coin, cache.spendableAmount);
|
||||
cache.pendingBalanceStr = txFormatService.formatAmountStr(wallet.coin, cache.pendingAmount);
|
||||
|
||||
cache.alternativeName = config.settings.alternativeName;
|
||||
cache.alternativeIsoCode = config.settings.alternativeIsoCode;
|
||||
|
|
@ -238,11 +237,11 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
|
||||
rateService.whenAvailable(function() {
|
||||
|
||||
var totalBalanceAlternative = rateService.toFiat(cache.totalBalanceSat, cache.alternativeIsoCode);
|
||||
var pendingBalanceAlternative = rateService.toFiat(cache.pendingAmount, cache.alternativeIsoCode);
|
||||
var lockedBalanceAlternative = rateService.toFiat(cache.lockedBalanceSat, cache.alternativeIsoCode);
|
||||
var spendableBalanceAlternative = rateService.toFiat(cache.spendableAmount, cache.alternativeIsoCode);
|
||||
var alternativeConversionRate = rateService.toFiat(100000000, cache.alternativeIsoCode);
|
||||
var totalBalanceAlternative = rateService.toFiat(cache.totalBalanceSat, cache.alternativeIsoCode, wallet.coin);
|
||||
var pendingBalanceAlternative = rateService.toFiat(cache.pendingAmount, cache.alternativeIsoCode, wallet.coin);
|
||||
var lockedBalanceAlternative = rateService.toFiat(cache.lockedBalanceSat, cache.alternativeIsoCode, wallet.coin);
|
||||
var spendableBalanceAlternative = rateService.toFiat(cache.spendableAmount, cache.alternativeIsoCode, wallet.coin);
|
||||
var alternativeConversionRate = rateService.toFiat(100000000, cache.alternativeIsoCode, wallet.coin);
|
||||
|
||||
cache.totalBalanceAlternative = $filter('formatFiatAmount')(totalBalanceAlternative);
|
||||
cache.pendingBalanceAlternative = $filter('formatFiatAmount')(pendingBalanceAlternative);
|
||||
|
|
@ -260,6 +259,8 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
};
|
||||
|
||||
function cacheStatus(status) {
|
||||
if (status.wallet && status.wallet.scanStatus == 'running') return;
|
||||
|
||||
wallet.cachedStatus = status || {};
|
||||
var cache = wallet.cachedStatus;
|
||||
cache.statusUpdatedOn = Date.now();
|
||||
|
|
@ -304,6 +305,8 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
|
||||
cacheStatus(status);
|
||||
|
||||
wallet.scanning = status.wallet && status.wallet.scanStatus == 'running';
|
||||
|
||||
return cb(null, status);
|
||||
});
|
||||
};
|
||||
|
|
@ -366,7 +369,7 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
wallet.hasUnsafeConfirmed = false;
|
||||
|
||||
lodash.each(txs, function(tx) {
|
||||
tx = txFormatService.processTx(tx);
|
||||
tx = txFormatService.processTx(wallet.coin, tx);
|
||||
|
||||
// no future transactions...
|
||||
if (tx.time > now)
|
||||
|
|
@ -400,7 +403,6 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
var LIMIT = 50;
|
||||
var requestLimit = FIRST_LIMIT;
|
||||
var walletId = wallet.credentials.walletId;
|
||||
var config = configService.getSync().wallet.settings;
|
||||
|
||||
var opts = opts || {};
|
||||
var progressFn = opts.progressFn || function() {};
|
||||
|
|
@ -414,18 +416,16 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
var fixTxsUnit = function(txs) {
|
||||
if (!txs || !txs[0] || !txs[0].amountStr) return;
|
||||
|
||||
var cacheUnit = txs[0].amountStr.split(' ')[1];
|
||||
var cacheCoin = txs[0].amountStr.split(' ')[1];
|
||||
|
||||
if (cacheUnit == config.unitName)
|
||||
return;
|
||||
if (cacheCoin == 'bits') {
|
||||
|
||||
var name = ' ' + config.unitName;
|
||||
|
||||
$log.debug('Fixing Tx Cache Unit to:' + name)
|
||||
lodash.each(txs, function(tx) {
|
||||
tx.amountStr = txFormatService.formatAmount(tx.amount) + name;
|
||||
tx.feeStr = txFormatService.formatAmount(tx.fees) + name;
|
||||
});
|
||||
$log.debug('Fixing Tx Cache Unit to: ' + wallet.coin)
|
||||
lodash.each(txs, function(tx) {
|
||||
tx.amountStr = txFormatService.formatAmountStr(wallet.coin, tx.amount);
|
||||
tx.feeStr = txFormatService.formatAmountStr(wallet.coin, tx.fees);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
getSavedTxs(walletId, function(err, txsFromLocal) {
|
||||
|
|
@ -788,7 +788,7 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
//prefs.email (may come from arguments)
|
||||
prefs.email = config.emailNotifications.email;
|
||||
prefs.language = uxLanguage.getCurrentLanguage();
|
||||
prefs.unit = walletSettings.unitCode;
|
||||
// prefs.unit = walletSettings.unitCode; // TODO: remove, not used
|
||||
|
||||
updateRemotePreferencesFor(lodash.clone(clients), prefs, function(err) {
|
||||
if (err) return cb(err);
|
||||
|
|
@ -820,13 +820,10 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
$log.debug('Scanning wallet ' + wallet.id);
|
||||
if (!wallet.isComplete()) return;
|
||||
|
||||
wallet.updating = true;
|
||||
ongoingProcess.set('scanning', true);
|
||||
wallet.scanning = true;
|
||||
wallet.startScan({
|
||||
includeCopayerBranches: true,
|
||||
}, function(err) {
|
||||
wallet.updating = false;
|
||||
ongoingProcess.set('scanning', false);
|
||||
return cb(err);
|
||||
});
|
||||
};
|
||||
|
|
@ -922,28 +919,30 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
};
|
||||
|
||||
|
||||
// Approx utxo amount, from which the uxto is economically redeemable
|
||||
// Approx utxo amount, from which the uxto is economically redeemable
|
||||
root.getMinFee = function(wallet, feeLevels, nbOutputs) {
|
||||
var lowLevelRate = (lodash.find(feeLevels[wallet.network], {
|
||||
level: 'normal',
|
||||
}).feePerKB / 1000).toFixed(0);
|
||||
}).feePerKb / 1000).toFixed(0);
|
||||
|
||||
var size = root.getEstimatedTxSize(wallet, nbOutputs);
|
||||
return size * lowLevelRate;
|
||||
};
|
||||
|
||||
|
||||
// Approx utxo amount, from which the uxto is economically redeemable
|
||||
// Approx utxo amount, from which the uxto is economically redeemable
|
||||
root.getLowAmount = function(wallet, feeLevels, nbOutputs) {
|
||||
var minFee = root.getMinFee(wallet,feeLevels, nbOutputs);
|
||||
return parseInt( minFee / LOW_AMOUNT_RATIO);
|
||||
var minFee = root.getMinFee(wallet, feeLevels, nbOutputs);
|
||||
return parseInt(minFee / LOW_AMOUNT_RATIO);
|
||||
};
|
||||
|
||||
|
||||
|
||||
root.getLowUtxos = function(wallet, levels, cb) {
|
||||
|
||||
wallet.getUtxos({}, function(err, resp) {
|
||||
wallet.getUtxos({
|
||||
coin: wallet.coin
|
||||
}, function(err, resp) {
|
||||
if (err || !resp || !resp.length) return cb();
|
||||
|
||||
var minFee = root.getMinFee(wallet, levels, resp.length);
|
||||
|
|
@ -959,7 +958,7 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
var totalLow = lodash.sum(lowUtxos, 'satoshis');
|
||||
|
||||
return cb(err, {
|
||||
allUtxos: resp || [],
|
||||
allUtxos: resp || [],
|
||||
lowUtxos: lowUtxos || [],
|
||||
warning: minFee / balance > TOTAL_LOW_WARNING_RATIO,
|
||||
minFee: minFee,
|
||||
|
|
@ -1236,5 +1235,38 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
|||
});
|
||||
};
|
||||
|
||||
root.getProtocolHandler = function(wallet) {
|
||||
if (wallet.coin== 'bch') return 'bitcoincash';
|
||||
else return 'bitcoin';
|
||||
}
|
||||
|
||||
|
||||
root.copyCopayers = function(wallet, newWallet, cb) {
|
||||
var c = wallet.credentials;
|
||||
|
||||
var walletPrivKey = bitcore.PrivateKey.fromString(c.walletPrivKey);
|
||||
|
||||
var copayer = 1,
|
||||
i = 0,
|
||||
l = c.publicKeyRing.length;
|
||||
var mainErr = null;
|
||||
|
||||
lodash.each(c.publicKeyRing, function(item) {
|
||||
var name = item.copayerName || ('copayer ' + copayer++);
|
||||
newWallet._doJoinWallet(newWallet.credentials.walletId, walletPrivKey, item.xPubKey, item.requestPubKey, name, {
|
||||
coin: newWallet.credentials.coin,
|
||||
}, function(err) {
|
||||
//Ignore error is copayer already in wallet
|
||||
if (err && !(err instanceof errors.COPAYER_IN_WALLET)) {
|
||||
mainErr = err;
|
||||
}
|
||||
|
||||
if (++i == l) {
|
||||
return cb(mainErr);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
return root;
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue