diff --git a/src/js/services/bitcoin-uri.service.js b/src/js/services/bitcoin-uri.service.js index dcb3fc5a8..48464cb27 100644 --- a/src/js/services/bitcoin-uri.service.js +++ b/src/js/services/bitcoin-uri.service.js @@ -108,6 +108,7 @@ address: '', amount: '', coin: '', + copayInvitation: '', isValid: false, label: '', legacyAddress: '', @@ -120,7 +121,8 @@ "req-param1": "" }, testnet: false, - url: '' + url: '', + wifPrivateKey: '' } @@ -244,18 +246,22 @@ parsed.req = req; - // Need to do bitpay format as well? Probably if (address) { var addressLowerCase = address.toLowerCase(); - var bch = bitcoinCashJsService.getBitcoinCashJs(); // Just a rough validation to exclude half-pasted addresses, or things obviously not bitcoin addresses - var cashAddrRe = /^((?:q|p)[a-z0-9]{41})|((?:Q|P)[A-Z0-9]{41})$/; - + //var cashAddrRe = /^((?:q|p)[a-z0-9]{41})|((?:Q|P)[A-Z0-9]{41})$/; + var copayRe = /^[0-9A-HJ-NP-Za-km-z]{70,80}$/; //var legacyRe = /^[13][a-km-zA-HJ-NP-Z1-9]{25,34}$/; //var legacyTestnetRe = /^[mn][a-km-zA-HJ-NP-Z1-9]{25,34}$/; + var privateKeyUncompressedRe = /^5[1-9A-HJ-NP-Za-km-z]{50}$/; + var privateKeyUncompressedTestnetRe = /^9[1-9A-HJ-NP-Za-km-z]{50}$/; + var privateKeyCompressedRe = /^[KL][1-9A-HJ-NP-Za-km-z]{51}$/; + var privateKeyCompressedTestnetRe = /^[c][1-9A-HJ-NP-Za-km-z]{51}$/; + var bitpayAddrMainnet = bitpayAddrOnMainnet(address); var cashAddrTestnet = cashAddrOnTestnet(addressLowerCase); var cashAddrMainnet = cashAddrOnMainnet(addressLowerCase); + var privateKey = ''; if (parsed.testnet && cashAddrTestnet) { parsed.address = addressLowerCase; @@ -282,18 +288,32 @@ parsed.address = address; parsed.coin = 'bch'; parsed.legacyAddress = bitpayAddrMainnet.toString(); - parsed.testnet = false; + parsed.testnet = false; + + } else if (copayRe.test(address) ) { + parsed.copayInvitation = address; + + } else if (privateKeyUncompressedRe.test(address) || privateKeyCompressedRe.test(address)) { + privateKey = address; + try { + new bitcore.PrivateKey(privateKey, 'livenet'); + parsed.wifPrivateKey = privateKey; + parsed.testnet = false; + } catch (e) {} + + } else if (privateKeyUncompressedTestnetRe.test(address) || privateKeyCompressedTestnetRe.test(address)) { + privateKey = address; + try { + new bitcore.PrivateKey(privateKey, 'testnet'); + parsed.wifPrivateKey = privateKey; + parsed.testnet = true; + } catch (e) {} } } - - - // TODO: Check for a private key here too, including WIF format, etc. - - // If has no address, must have Url. - parsed.isValid = !!(parsed.address || parsed.url); + parsed.isValid = !!(parsed.address || parsed.url || parsed.copayInvitation || parsed.wifPrivateKey); return parsed; } diff --git a/src/js/services/bitcoin-uri.service.spec.js b/src/js/services/bitcoin-uri.service.spec.js index c2a2571c4..c37d708d6 100644 --- a/src/js/services/bitcoin-uri.service.spec.js +++ b/src/js/services/bitcoin-uri.service.spec.js @@ -140,6 +140,17 @@ fdescribe('bitcoinUriService', function() { expect(parsed.testnet).toBe(false); }); + it('Bitpay without prefix', function() { + + var parsed = bitcoinUriService.parse('CJoRov8TirekvajiimQpb5Hk95evA7H2Yz'); + + expect(parsed.isValid).toBe(true); + expect(parsed.address).toBe('CJoRov8TirekvajiimQpb5Hk95evA7H2Yz'); + expect(parsed.coin).toBe('bch'); + expect(parsed.legacyAddress).toBe('13LYEsnPqogE2SqJ325u1ZfiWxSWEo6uyo'); + expect(parsed.testnet).toBe(false); + }); + it('legacy address', function() { var parsed = bitcoinUriService.parse('1JXeGEu7bNEAYu6URT6dU6g1Ys6ffSAWYW'); @@ -195,20 +206,14 @@ fdescribe('bitcoinUriService', function() { expect(parsed.testnet).toBe(false); }); + it('copay invitation', function() { - it('Bitpay without prefix', function() { - - var parsed = bitcoinUriService.parse('CJoRov8TirekvajiimQpb5Hk95evA7H2Yz'); + var parsed = bitcoinUriService.parse('PD5B7rEEj72st9d5nFszyuKxJP6FAGS7idVC2SMqiMxUcWVd8JifZDJw1UgjUctxefUFE3Sz6qLbch'); expect(parsed.isValid).toBe(true); - expect(parsed.address).toBe('CJoRov8TirekvajiimQpb5Hk95evA7H2Yz'); - expect(parsed.coin).toBe('bch'); - expect(parsed.legacyAddress).toBe('13LYEsnPqogE2SqJ325u1ZfiWxSWEo6uyo'); - expect(parsed.testnet).toBe(false); + expect(parsed.copayInvitation).toBe('PD5B7rEEj72st9d5nFszyuKxJP6FAGS7idVC2SMqiMxUcWVd8JifZDJw1UgjUctxefUFE3Sz6qLbch'); }); - - // Invalid addresses from https://github.com/bitcoincashorg/bitcoincash.org/blob/master/spec/cashaddr.md it('invalid cashAddr style 1', function() { var parsed = bitcoinUriService.parse('prefix:x64nx6hz'); @@ -234,4 +239,20 @@ fdescribe('bitcoinUriService', function() { var parsed = bitcoinUriService.parse('bchreg:555555555555555555555555555555555555555555555udxmlmrz'); expect(parsed.isValid).toBe(false); }); + + it('private key compressed mainnet', function() { + + var parsed = bitcoinUriService.parse('5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ'); + + expect(parsed.isValid).toBe(true); + expect(parsed.wifPrivateKey).toBe('5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ'); + }); + + it('private key compressed mainnet with wrong checksum', function() { + + var parsed = bitcoinUriService.parse('5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTu'); + + expect(parsed.isValid).toBe(false); + }); + }); \ No newline at end of file