nip24client
Version:
NIP24 Client for JavaScript
165 lines (147 loc) • 4.37 kB
JavaScript
/**
* Copyright 2015-2025 NETCAT (www.netcat.pl)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @author NETCAT <firma@netcat.pl>
* @copyright 2015-2025 NETCAT (www.netcat.pl)
* @license http://www.apache.org/licenses/LICENSE-2.0
*/
;
/**
* Normalizes form of the IBAN number
* @param {string} iban input string
* @return {string} normalized number
*/
function normalize(iban)
{
if (!iban) {
return undefined;
}
iban = iban.replace(/[ -]/g, '').trim().toUpperCase();
if (iban.search(/^[A-Z]{2}[0-9A-Z]{13,30}$/) === -1) {
return undefined;
}
return iban;
}
/**
* Checks if specified IBAN is valid
* @param {string} iban input number
* @return {boolean} true if number is valid
*/
function isValid(iban)
{
if (!(iban = normalize(iban))) {
return false;
}
const map = {
'AD': /^AD\d{10}[A-Z0-9]{12}$/,
'AE': /^AE\d{21}$/,
'AL': /^AL\d{10}[A-Z0-9]{16}$/,
'AT': /^AT\d{18}$/,
'AZ': /^AZ\d{2}[A-Z]{4}[A-Z0-9]{20}$/,
'BA': /^BA\d{18}$/,
'BE': /^BE\d{14}$/,
'BG': /^BG\d{2}[A-Z]{4}\d{6}[A-Z0-9]{8}$/,
'BH': /^BH\d{2}[A-Z]{4}[A-Z0-9]{14}$/,
'BR': /^BR\d{25}[A-Z]{1}[A-Z0-9]{1}$/,
'BY': /^BY\d{2}[A-Z0-9]{4}\d{4}[A-Z0-9]{16}$/,
'CH': /^CH\d{7}[A-Z0-9]{12}$/,
'CR': /^CR\d{20}$/,
'CY': /^CY\d{10}[A-Z0-9]{16}$/,
'CZ': /^CZ\d{22}$/,
'DE': /^DE\d{20}$/,
'DK': /^DK\d{16}$/,
'DO': /^DO\d{2}[A-Z0-9]{4}\d{20}$/,
'EE': /^EE\d{18}$/,
'ES': /^ES\d{22}$/,
'FI': /^FI\d{16}$/,
'FO': /^FO\d{16}$/,
'FR': /^FR\d{12}[A-Z0-9]{11}\d{2}$/,
'GB': /^GB\d{2}[A-Z]{4}\d{14}$/,
'GE': /^GE\d{2}[A-Z]{2}\d{16}$/,
'GI': /^GI\d{2}[A-Z]{4}[A-Z0-9]{15}$/,
'GL': /^GL\d{16}$/,
'GR': /^GR\d{9}[A-Z0-9]{16}$/,
'GT': /^GT\d{2}[A-Z0-9]{24}$/,
'HR': /^HR\d{19}$/,
'HU': /^HU\d{26}$/,
'IE': /^IE\d{2}[A-Z]{4}\d{14}$/,
'IL': /^IL\d{21}$/,
'IQ': /^IQ\d{2}[A-Z]{4}\d{15}$/,
'IS': /^IS\d{24}$/,
'IT': /^IT\d{2}[A-Z]{1}\d{10}[A-Z0-9]{12}$/,
'JO': /^JO\d{2}[A-Z]{4}\d{4}[A-Z0-9]{18}$/,
'KW': /^KW\d{2}[A-Z]{4}[A-Z0-9]{22}$/,
'KZ': /^KZ\d{5}[A-Z0-9]{13}$/,
'LB': /^LB\d{6}[A-Z0-9]{20}$/,
'LC': /^LC\d{2}[A-Z]{4}[A-Z0-9]{24}$/,
'LI': /^LI\d{7}[A-Z0-9]{12}$/,
'LT': /^LT\d{18}$/,
'LU': /^LU\d{5}[A-Z0-9]{13}$/,
'LV': /^LV\d{2}[A-Z]{4}[A-Z0-9]{13}$/,
'MC': /^MC\d{12}[A-Z0-9]{11}\d{2}$/,
'MD': /^MD\d{2}[A-Z0-9]{20}$/,
'ME': /^ME\d{20}$/,
'MK': /^MK\d{5}[A-Z0-9]{10}\d{2}$/,
'MR': /^MR\d{25}$/,
'MT': /^MT\d{2}[A-Z]{4}\d{5}[A-Z0-9]{18}$/,
'MU': /^MU\d{2}[A-Z]{4}\d{19}[A-Z]{3}$/,
'NL': /^NL\d{2}[A-Z]{4}\d{10}$/,
'NO': /^NO\d{13}$/,
'PK': /^PK\d{2}[A-Z]{4}[A-Z0-9]{16}$/,
'PL': /^PL\d{26}$/,
'PS': /^PS\d{2}[A-Z]{4}[A-Z0-9]{21}$/,
'PT': /^PT\d{23}$/,
'QA': /^QA\d{2}[A-Z]{4}[A-Z0-9]{21}$/,
'RO': /^RO\d{2}[A-Z]{4}[A-Z0-9]{16}$/,
'RS': /^RS\d{20}$/,
'SA': /^SA\d{4}[A-Z0-9]{18}$/,
'SC': /^SC\d{2}[A-Z]{4}\d{20}[A-Z]{3}$/,
'SE': /^SE\d{22}$/,
'SI': /^SI\d{17}$/,
'SK': /^SK\d{22}$/,
'SM': /^SM\d{2}[A-Z]{1}\d{10}[A-Z0-9]{12}$/,
'ST': /^ST\d{23}$/,
'SV': /^SV\d{2}[A-Z]{4}\d{20}$/,
'TL': /^TL\d{21}$/,
'TN': /^TN\d{22}$/,
'TR': /^TR\d{8}[A-Z0-9]{16}$/,
'UA': /^UA\d{8}[A-Z0-9]{19}$/,
'VG': /^VG\d{2}[A-Z]{4}\d{16}$/,
'XK': /^XK\d{18}$/
};
const cc = iban.substring(0, 2);
if (!(cc in map)) {
return false;
}
if (iban.search(map[cc]) === -1) {
return false;
}
iban = iban.substring(4) + iban.substring(0, 4);
let sb = '';
for (let i = 0; i < iban.length; i++) {
const ord = iban.charCodeAt(i);
if (ord >= 65 && ord <= 90) {
sb += (ord - 55);
}
else if (ord >= 48 && ord <= 57) {
sb += (ord - 48);
}
}
return (BigInt(sb) % BigInt(97)) === BigInt(1);
}
module.exports = {
normalize: normalize,
isValid: isValid
};