This commit is contained in:
Jean-Baptiste Dominguez 2018-08-31 16:11:58 +09:00
commit 7fa2ab7ff4
6 changed files with 107 additions and 23 deletions

View file

@ -3865,4 +3865,12 @@ msgstr ""
#: src/js/controllers/tab-scan.js:121 #: src/js/controllers/tab-scan.js:121
msgid "Testnet is not supported." msgid "Testnet is not supported."
msgstr ""
#: www/views/includes/incomingDataMenu.html:81
msgid "URL"
msgstr ""
#: www/views/includes/incomingDataMenu.html:90
msgid "Open in web browser"
msgstr "" msgstr ""

View file

@ -93,6 +93,7 @@
returns: returns:
{ {
amount: '', amount: '',
bareUrl: '',
coin: '', coin: '',
copayInvitation: '', copayInvitation: '',
isValid: false, isValid: false,
@ -143,26 +144,29 @@
var preColonLower = colonSplit[1].toLowerCase(); var preColonLower = colonSplit[1].toLowerCase();
if (preColonLower === 'bitcoin') { if (preColonLower === 'bitcoin') {
parsed.coin = 'btc'; parsed.coin = 'btc';
addressAndParams = colonSplit[2]; addressAndParams = colonSplit[2].trim();
console.log('Is btc'); console.log('Is btc');
} else if (/^(?:bitcoincash)|(?:bitcoin-cash)$/.test(preColonLower)) { } else if (/^(?:bitcoincash)|(?:bitcoin-cash)$/.test(preColonLower)) {
parsed.coin = 'bch'; parsed.coin = 'bch';
parsed.test = false; parsed.test = false;
addressAndParams = colonSplit[2]; addressAndParams = colonSplit[2].trim();
console.log('Is bch'); console.log('Is bch');
} else if (/^(?:bchtest)$/.test(preColonLower)) { } else if (/^(?:bchtest)$/.test(preColonLower)) {
parsed.coin = 'bch'; parsed.coin = 'bch';
parsed.testnet = true; parsed.testnet = true;
addressAndParams = colonSplit[2]; addressAndParams = colonSplit[2].trim();
console.log('Is bch'); console.log('Is bch');
} else if (colonSplit[2] === '') { } else if (colonSplit[2] === '') {
// No colon and no coin specifier. // No colon and no coin specifier.
addressAndParams = colonSplit[1]; addressAndParams = colonSplit[1].trim();
console.log('No prefix.'); console.log('No prefix.');
} else if (/^https?$/.test(colonSplit[1])) {
addressAndParams = trimmed;
} else { } else {
// Something with a colon in the middle that we don't recognise // Something with a colon in the middle that we don't recognise
return parsed; return parsed;
@ -253,6 +257,7 @@
var privateKeyForUncompressedPublicKeyTestnetRe = /^9[1-9A-HJ-NP-Za-km-z]{50}$/; var privateKeyForUncompressedPublicKeyTestnetRe = /^9[1-9A-HJ-NP-Za-km-z]{50}$/;
var privateKeyForCompressedPublicKeyRe = /^[KL][1-9A-HJ-NP-Za-km-z]{51}$/; var privateKeyForCompressedPublicKeyRe = /^[KL][1-9A-HJ-NP-Za-km-z]{51}$/;
var privateKeyForCompressedPublicKeyTestnetRe = /^[c][1-9A-HJ-NP-Za-km-z]{51}$/; var privateKeyForCompressedPublicKeyTestnetRe = /^[c][1-9A-HJ-NP-Za-km-z]{51}$/;
var urlRe = /^https?:\/\/.+/;
var bitpayAddrMainnet = bitpayAddrOnMainnet(address); var bitpayAddrMainnet = bitpayAddrOnMainnet(address);
var cashAddrTestnet = cashAddrOnTestnet(addressLowerCase); var cashAddrTestnet = cashAddrOnTestnet(addressLowerCase);
@ -322,6 +327,10 @@
} else if (privateKeyEncryptedRe.test(address)) { } else if (privateKeyEncryptedRe.test(address)) {
parsed.privateKey = { encrypted: address }; parsed.privateKey = { encrypted: address };
parsed.isValid = true; parsed.isValid = true;
} else if (urlRe.test(address)) {
parsed.bareUrl = trimmed;
parsed.isValid = true;
} }
} else { } else {

View file

@ -140,6 +140,16 @@ fdescribe('bitcoinUriService', function() {
expect(parsed.testnet).toBe(false); expect(parsed.testnet).toBe(false);
}); });
it('Bitcoin uri with space', function() {
var parsed = bitcoinUriService.parse('bitcoin: 19cPoKU5ZazY8NkLEsxK7drBqJnpGkax3d');
expect(parsed.isValid).toBe(true);
expect(parsed.coin).toBe('btc');
expect(parsed.publicAddress.legacy).toBe('19cPoKU5ZazY8NkLEsxK7drBqJnpGkax3d');
expect(parsed.testnet).toBe(false);
});
it('Bitpay without prefix', function() { it('Bitpay without prefix', function() {
var parsed = bitcoinUriService.parse('CJoRov8TirekvajiimQpb5Hk95evA7H2Yz'); var parsed = bitcoinUriService.parse('CJoRov8TirekvajiimQpb5Hk95evA7H2Yz');
@ -220,6 +230,27 @@ fdescribe('bitcoinUriService', function() {
expect(parsed.testnet).toBe(false); expect(parsed.testnet).toBe(false);
}); });
it('cashAddr with space', function() {
var parsed = bitcoinUriService.parse('bitcoincash: qpar9ldle8z6alcwgclejdhc24ha2xrg0szs5802ce');
expect(parsed.isValid).toBe(true);
expect(parsed.coin).toBe('bch');
expect(parsed.publicAddress.cashAddr).toBe('qpar9ldle8z6alcwgclejdhc24ha2xrg0szs5802ce');
expect(parsed.testnet).toBe(false);
});
it('cashAddr with space on testnet', function() {
var parsed = bitcoinUriService.parse('bchtest: qqjxkmtaxk4nv6w9h5ht2fjcj9c7ruh0fu7cnxsx5j');
expect(parsed.isValid).toBe(true);
expect(parsed.coin).toBe('bch');
expect(parsed.publicAddress.cashAddr).toBe('qqjxkmtaxk4nv6w9h5ht2fjcj9c7ruh0fu7cnxsx5j');
expect(parsed.testnet).toBe(true);
});
it('cashAddr without prefix', function() { it('cashAddr without prefix', function() {
var parsed = bitcoinUriService.parse('qqen2y3l28dpk0dzsag8w027ds96u7z4pc0uxtl0nq'); var parsed = bitcoinUriService.parse('qqen2y3l28dpk0dzsag8w027ds96u7z4pc0uxtl0nq');
@ -343,11 +374,20 @@ fdescribe('bitcoinUriService', function() {
expect(parsed.isValid).toBe(false); expect(parsed.isValid).toBe(false);
}); });
it('URL only', function() { it('URL only, http', function() {
var parsed = bitcoinUriService.parse('https://www.google.com'); var parsed = bitcoinUriService.parse('http://paperwallet.bitcoin.com');
expect(parsed.isValid).toBe(false); expect(parsed.isValid).toBe(true);
expect(parsed.bareUrl).toBe('http://paperwallet.bitcoin.com');
});
it('URL only, https with query', function() {
var parsed = bitcoinUriService.parse('https://purse.io/?one=two&three=four');
expect(parsed.isValid).toBe(true);
expect(parsed.bareUrl).toBe('https://purse.io/?one=two&three=four');
}); });
}); });

View file

@ -1,6 +1,6 @@
'use strict'; 'use strict';
angular.module('copayApp.services').factory('incomingData', function(bitcoinUriService, $log, $state, $timeout, $ionicHistory, bitcore, bitcoreCash, $rootScope, payproService, scannerService, sendFlowService, appConfigService, popupService, gettextCatalog, bitcoinCashJsService) { angular.module('copayApp.services').factory('incomingData', function(externalLinkService, bitcoinUriService, $log, $state, $timeout, $ionicHistory, bitcore, bitcoreCash, $rootScope, payproService, scannerService, sendFlowService, appConfigService, popupService, gettextCatalog, bitcoinCashJsService) {
var root = {}; var root = {};
@ -227,20 +227,23 @@ angular.module('copayApp.services').factory('incomingData', function(bitcoinUriS
); );
return true; return true;
// Plain URL // Plain URL
} else if (/^https?:\/\//.test(data)) { } else if (allParsed.bareUrl) {
payproService.getPayProDetails(data, coin, function(err, details) {
if (err) { if ($state.includes('tabs.scan')) {
if ($state.includes('tabs.scan')) { root.showMenu({
root.showMenu({ data: allParsed.bareUrl,
data: data, type: 'url'
type: 'url' });
}); } else {
} externalLinkService.open(
return; allParsed.bareUrl,
} true,
handlePayPro(details); gettextCatalog.getString('Open in web browser'),
return true; allParsed.bareUrl
}); );
}
return true;
// Plain Address // Plain Address
} else if (bitcore.Address.isValid(data, 'livenet') || bitcore.Address.isValid(data, 'testnet')) { } else if (bitcore.Address.isValid(data, 'livenet') || bitcore.Address.isValid(data, 'testnet')) {
if ($state.includes('tabs.scan')) { if ($state.includes('tabs.scan')) {

View file

@ -9,7 +9,7 @@ angular
function sendFlowService( function sendFlowService(
sendFlowStateService, sendFlowRouterService sendFlowStateService, sendFlowRouterService
, bitcoinUriService, payproService, bitcoinCashJsService , bitcoinUriService, payproService, bitcoinCashJsService
, popupService , popupService, gettextCatalog
, $state , $state
) { ) {

View file

@ -76,4 +76,28 @@
</a> </a>
</div> </div>
<div ng-if="type === 'url'">
<div class="incoming-data-menu__item head">
<div class="incoming-data-menu__header" translate>URL</div>
<div class="incoming-data-menu__url">
<div class="incoming-data-menu__url__text" style="border: 0;">
{{data}}
</div>
</div>
</div>
<a class="incoming-data-menu__item item item-icon-right" ng-click="goToUrl(data)">
<img src="img/icon-link-external.svg">
<div class="incoming-data-menu__item__text" translate>Open in web browser</div>
<i class="icon bp-arrow-right"></i>
</a>
<a class="incoming-data-menu__item item item-icon-right" copy-to-clipboard="data">
<img src="img/icon-paperclip.svg">
<div class="incoming-data-menu__item__text" translate>Copy to clipboard</div>
<i class="icon bp-arrow-right"></i>
</a>
<a class="incoming-data-menu__cancel item" ng-click="hide()" translate>
Cancel
</a>
</div>
</action-sheet> </action-sheet>