I think I got it here. Tested with all edge cases and seems to work, at least if the min and max assumptions are correct.
I did not use BigInt because one does not always want to import a library.
function isValidAsset(asset) {
if (isValidAlphabeticAsset(asset) || isValidNumericAsset(asset)) return true;
return false;
}
function isValidAlphabeticAsset(asset) {
//4-12 chars, cannot start with A
//A few old ones have 13 or 14 chars
if (asset.match(/^[B-Z][A-Z]{3,11}$/) == null) return false;
return true;
}
function isValidNumericAsset(asset) {
//'A' followed by a really large number
//Min = 26^12+1 = 95,428,956,661,682,177
//Max = 2^64-1 = 18,446,744,073,709,551,615
while (asset.substring(0,2) == 'A0') asset = asset[0] + asset.substring(2);
if (asset.length>21) return false;
if (asset.length<18) return false;
if (asset[0] != 'A') return false;
if (asset.substring(1).match(/[^0-9]/) != null) return false;
if (asset.length==18 && asset.substring(1,9)<95428956) return false;
if (asset.length==18 && asset.substring(1,9)==95428956 && asset.substring(9)<661682177) return false;
if (asset.length==21 && asset.substring(1,10)>184467440) return false;
if (asset.length==21 && asset.substring(1,10)==184467440 && asset.substring(10)>73709551615) return false;
return true;
}