Returning legacy address for cashAddr.

This commit is contained in:
Brendon Duncan 2018-08-23 12:47:47 +12:00
commit ab0b8b19b0
2 changed files with 137 additions and 8 deletions

View file

@ -6,7 +6,7 @@
.module('bitcoincom.services')
.factory('bitcoinUriService', bitcoinUriService);
function bitcoinUriService() {
function bitcoinUriService(bitcoinCashJsService) {
var service = {
parse: parse
};
@ -38,18 +38,136 @@
}
*/
// bitcoincash:?r=https://bitpay.com/i/GLRoZMZxaWBqLqpoXexzoD
function parse(uri) {
var address;
var isValid = false;
var legacyAddress;
var parsed = {
isValid: false
};
parsed.address = '1JXeGEu7bNEAYu6URT6dU6g1Ys6ffSAWYW';
parsed.isValid = true;
parsed.legacyAddress = '1JXeGEu7bNEAYu6URT6dU6g1Ys6ffSAWYW';
// Identify prefix
var trimmed = uri.trim();
var colonSplit = /^([\w-]*):?(.*)$/.exec(trimmed);
if (!colonSplit) {
return parsed;
}
var addressAndParams = '';
var preColonLower = colonSplit[1].toLowerCase();
if (preColonLower === 'bitcoin') {
parsed.coin = 'btc';
addressAndParams = colonSplit[2];
console.log('Is btc');
} else if (/^(?:bitcoincash)|(?:bitcoin-cash)$/.test(preColonLower)) {
parsed.coin = 'bch';
addressAndParams = colonSplit[2];
console.log('Is bch');
} else if (colonSplit[2] === '') {
// No colon and no coin specifier.
addressAndParams = colonSplit[1];
console.log('No prefix.');
} else {
// Something with a colon in the middle that we don't recognise
return parsed;
}
// Remove erroneous leading slashes
var leadingSlashes = /^\/*([^\/]+(?:.*))$/.exec(addressAndParams);
if (!leadingSlashes) {
return parsed;
}
addressAndParams = leadingSlashes[1];
var questionMarkSplit = /^([^\?]*)\??([^\?]*)$/.exec(addressAndParams);
if (!questionMarkSplit) {
return parsed;
}
var address = questionMarkSplit[1];
var params = questionMarkSplit[2];
var paramsSplit = params.split('&');
var others;
var req;
paramsSplit.forEach(function onParam(param){
var valueSplit = param.split('=');
if (valueSplit.length !== 2) {
return parsed;
}
var key = valueSplit[0];
var value = valueSplit[1];
switch(key) {
case 'amount':
if (parseFloat(value)) {
parsed.amount = value;
} else {
return parsed;
}
break;
case 'label':
parsed.label = value;
break;
case 'message':
parsed.message = value;
break;
case 'r':
// Could use a more comprehesive regex to test URL validity, but then how would we know
// which part of the validatiion it failed?
if (value.startsWith('https://')) {
parsed.url = value;
} else {
return parsed;
}
break;
default:
if (key.startsWith('req-')) {
req = req || {};
req[key] = value;
} else {
others = others || {};
others[key] = value;
}
}
});
parsed.others = others;
parsed.req = req;
// Need to do bitpay format as well? Probably
if (address) {
// 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 legacyRe = /^[13][a-km-zA-HJ-NP-Z1-9]{25,34}$/;
if (legacyRe.test(address)) {
parsed.address = address;
parsed.legacyAddress = address;
} else if (cashAddrRe.test(address)) {
parsed.address = address;
parsed.coin = 'bch';
var bchAddresses = bitcoinCashJsService.readAddress('bitcoincash:' + address);
parsed.legacyAddress = bchAddresses['legacy'];
} // TODO: Check for private key
// TODO: identify different types of addresses
// TODO: Check for a private key here too
}
// If has no address, must have Url.
parsed.isValid = !!(parsed.address || parsed.url);
return parsed;
}

View file

@ -2,6 +2,7 @@ fdescribe('bitcoinUriService', function() {
var bitcoinUriService;
beforeEach(function() {
module('bitcoinCashJsModule');
module('bitcoincom.services');
inject(function($injector){
@ -18,4 +19,14 @@ fdescribe('bitcoinUriService', function() {
expect(parsed.coin).toBeUndefined();
expect(parsed.legacyAddress).toBe('1JXeGEu7bNEAYu6URT6dU6g1Ys6ffSAWYW');
});
it('cashAddr', function() {
var parsed = bitcoinUriService.parse('qqen2y3l28dpk0dzsag8w027ds96u7z4pc0uxtl0nq');
expect(parsed.isValid).toBe(true);
expect(parsed.address).toBe('qqen2y3l28dpk0dzsag8w027ds96u7z4pc0uxtl0nq');
expect(parsed.coin).toBe('bch');
expect(parsed.legacyAddress).toBe('15fm3EwqgBYcxkndALBfforueps5yWKReJ');
});
});