// NibblePoker - IBAN // Author: Herwin Bozet (@NibblePoker) // License: Public Domain (This code, except for the data) // Sources: // * https://www.swift.com/standards/data-standards/iban-international-bank-account-number (Updated December 2024) /** * Parent class extended by all IBAN-related errors. */ export class IbanError extends Error {} export class UnknownIbanCountryError extends IbanError {} export class IncorrectIbanLengthError extends IbanError {} export class IncorrectIbanFormatError extends IbanError {} export class InvalidIbanChecksumError extends IbanError {} /** * ... * @param countryCode {string} * @returns {boolean} `true` if the given country code is known to have IBAN, `false` otherwise. */ export function doesCountryHaveIban(countryCode) { try { return getCountrySpec(countryCode, true) !== null; } catch (e) { return false; } } /** * * @param countryCode {string} * @param errorOnUnknown {boolean} * @returns {IbanSpecification|null} The desired specification, or `null` if none could be found. * @throws TypeError If the given `countryCode` is `null`, `undefined`, or not a `string`. * @throws Error If the given `countryCode` isn't exactly 2 characters long. * @throws UnknownIbanCountryError If `errorOnNotFound` is set to `true`, and no linked IBAN specification could be found. */ export function getCountrySpec(countryCode, errorOnUnknown = false) { if (countryCode === undefined || countryCode === null) { throw new TypeError("The given countryCode is null or undefined !"); } if (!(typeof countryCode === 'string' || countryCode instanceof String)) { throw new TypeError("The given countryCode is not a string !"); } if (countryCode.length !== 2) { throw new Error(`The given countryCode '${countryCode}' isn't exactly 2 characters long !`); } let desiredSpec = countriesSpecs[countryCode]; if(desiredSpec === undefined || desiredSpec === null) { if(errorOnUnknown) { throw new UnknownIbanCountryError(`The given countryCode '${countryCode}' isn't linked to any IBAN specification !`); } return null; } else { return desiredSpec; } } /** * Calculates the checksum for a given `countryCode` and `bban` * @param countryCode * @param bban * @returns {number} */ export function getIbanChecksumFromParts(countryCode, bban) { if (countryCode === undefined || countryCode === null || bban === undefined || bban === null) { throw new TypeError("The given countryCode or bban is null or undefined !"); } if (!(typeof countryCode === 'string' || countryCode instanceof String) || !(typeof bban === 'string' || bban instanceof String)) { throw new TypeError("The given countryCode or bban is not a string !"); } let ibanStep1 = bban + countryCode + "00"; let ibanStep2 = ""; for (let iChar = 0; iChar < ibanStep1.length; iChar++) { let charCode = ibanStep1.charCodeAt(iChar); if(charCode <= 57 && charCode >= 48) { // Numbers //console.log(`NB - ${ibanStep1[iChar]} - ${charCode} - ${(charCode - 48)}`); ibanStep2 += (charCode - 48).toString(); } else if(charCode <= 90 && charCode >= 65) { // Uppercase letters //console.log(`UC - ${ibanStep1[iChar]} - ${charCode} - ${(charCode - 55)}`); ibanStep2 += (charCode - 55).toString(); } else if(charCode <= 122 && charCode >= 97) { // Lowercase letters //console.log(`LC - ${ibanStep1[iChar]} - ${charCode} - ${(charCode - 87)}`); ibanStep2 += (charCode - 87).toString(); } else { throw new IncorrectIbanFormatError(`The character at position '${iChar}' in '${ibanStep1}' is invalid !`) } } //console.log(ibanStep1); //console.log(ibanStep2); //console.log(BigInt(ibanStep2)); // We cannot use the regular `number` type, the lack of precision will mess with the result. //console.log(98n - (BigInt(ibanStep2) % 97n)); return Number(98n - (BigInt(ibanStep2) % 97n)); } /** * * @param iban * @returns {StandardIban} * @throws TypeError If the given iban is `null`, `undefined`, or not a `string`. * @throws IncorrectIbanLengthError If the given `iban` has an invalid length. * @throws IncorrectIbanFormatError If the given `iban` didn't pass the regex and format checks. */ export function parseStandardIban(iban) { if (iban === undefined || iban === null) { throw new TypeError("The given iban is null or undefined !"); } if (!(typeof iban === 'string' || iban instanceof String)) { throw new TypeError("The given countryCode is not a string !"); } if (iban.length <= 4) { throw new IncorrectIbanLengthError(`The given iban '${iban}' has an invalid BBAN length !`); } /** @type {IbanSpecification} */ let countrySpec; try { countrySpec = getCountrySpec(iban.substring(0, 2), true); } catch (e) { throw new UnknownIbanCountryError(e.message); } // Quickly checking the regex, and extracting some groups for later if all goes well. let ibanRegexResult = countrySpec.ibanRegex.exec(iban); if(ibanRegexResult === undefined || ibanRegexResult === null) { throw new IncorrectIbanFormatError(`The given IBAN '${iban}' didn't match the '${countrySpec.ibanRegex}' regex`); } let actualChecksum = getIbanChecksumFromParts(ibanRegexResult.groups["prefix"], ibanRegexResult.groups["bban"]); if(actualChecksum !== parseInt(ibanRegexResult.groups["checksum"])) { throw new InvalidIbanChecksumError( `The IBAN's checksum is invalid, expected '${actualChecksum}', got '${ibanRegexResult.groups["checksum"]}' !`); } return new StandardIban( ibanRegexResult.groups["prefix"], ibanRegexResult.groups["bban"], countrySpec ); } /** * Models the most basic components required for an IBAN.
* This class should either be extended or used for quick-and-dirty checksum calculations. */ export class SimpleIban { /** @type {string} */ countryCode; /** @type {string} */ bban; constructor(countryCode, bban) { this.countryCode = countryCode; this.bban = bban; } getChecksumNumber() { return getIbanChecksumFromParts(this.countryCode, this.bban); } getChecksumString() { return this.getChecksumNumber().toString().padStart(2, "0"); } toString() { return `${this.countryCode}${this.getChecksumString()}${this.bban}`; } } export class StandardIban extends SimpleIban { /** @type {IbanSpecification} */ relevantSpec; constructor(countryCode, bban, relevantSpec) { super(countryCode, bban); this.relevantSpec = relevantSpec; } } export const charsN = "0123456789"; export const charsA = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; export const charsC = charsN + charsA; export class IbanSpecification { /** * ISO-3166 Country Code * @type {string} */ countryCode; /** @type {string} */ countryName; /** @type {number} */ ibanLength; /** @type {string} */ ibanFormat; /** @type {number} */ bbanLength; /** @type {string} */ bbanFormat; /** @type {RegExp} */ ibanRegex; /** @type {boolean} */ isSepa; /** * @param countryCode {string} * @param countryName {string} * @param ibanLength {number} * @param ibanFormat {string} * @param bbanLength {number} * @param bbanFormat {string} * @param ibanRegex {RegExp} * @param isSepa {boolean} */ constructor(countryCode, countryName, ibanLength, ibanFormat, bbanLength, bbanFormat, ibanRegex, isSepa) { this.countryCode = countryCode; this.countryName = countryName; this.ibanLength = ibanLength; this.ibanFormat = ibanFormat; this.bbanLength = bbanLength; this.bbanFormat = bbanFormat; this.ibanRegex = ibanRegex; this.isSepa = isSepa; } /** * Returns the Bank Identifier from the given IBAN. * The Bank Identifier may or may not include the Branch Identifier. * @param iban {string} * @returns {string} */ getFormattedBankId(iban) { return ""; } /** * @param iban {string} * @returns {string} */ getFormattedBranchId(iban) { return ""; } /** * Formats the IBAN by adding spaces and other characters where necessary. * @param iban {string} * @returns {string} */ getFormattedIban(iban) { return iban.match(/.{1,4}/g).join(' '); } generateRandomBban(preferNumbers = false) { let returnedBban = ""; let patternParts = ("_" + this.bbanFormat + "0").split("!"); for(let i = 0; i < patternParts.length; i++) { let elementCount = parseInt(patternParts[i].substring(1)); if(elementCount === 0) { continue; } let elementType = patternParts[i + 1].substring(0, 1); let elementChoices; switch(elementType) { case 'n': case 'N': elementChoices = charsN; break; case 'c': case 'C': if(preferNumbers) { elementChoices = charsN; } else { elementChoices = charsC; } break; case 'a': case 'A': elementChoices = charsA; break; } if(elementChoices === undefined || elementChoices === null) { throw new IncorrectIbanFormatError( `The format '${this.bbanFormat}' contains an unhandled element type '${elementType}' !`) } for (let i = 0; i < elementCount; i++) { returnedBban += elementChoices.charAt(Math.floor(Math.random() * elementChoices.length)); } } return returnedBban; } } export const countriesSpecs = { AD: new IbanSpecification( "AD", 'Andorra', 24, "AD2!n4!n4!n12!c", 20, "4!n4!n12!c", new RegExp( "^(?AD)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{4})" + "(?[0-9]{4})" + "([0-9a-zA-Z]{12})" + ")$", "g"), true ), AE: new IbanSpecification( "AE", 'United Arab Emirates (The)', 23, "AE2!n3!n16!n", 19, "3!n16!n", new RegExp( "^(?AE)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{3})" + "([0-9]{16})" + ")$", "g"), false ), AL: new IbanSpecification( "AL", 'Albania', 28, "AL2!n8!n16!c", 24, "8!n16!c", new RegExp( "^(?AL)" + "(?[0-9]{2})" + "(?" + "(?" + "[0-9]{3}" + "(?[0-9]{4})" + "[0-9]{1}" + ")" + "([0-9a-zA-Z]{16})" + ")$", "g"), false // FIXME: Has a special bank id format "212-1100-9" ), AT: new IbanSpecification( "AT", 'Austria', 20, "AT2!n5!n11!n", 16, "5!n11!n", new RegExp( "^(?AT)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{5})" + "([0-9]{11})" + ")$", "g"), true ), AZ: new IbanSpecification( "AZ", 'Azerbaijan', 28, "AZ2!n4!a20!c", 24, "4!a20!c", new RegExp( "^(?AZ)" + "(?[0-9]{2})" + "(?" + "(?[A-Z]{4})" + "([0-9a-zA-Z]{20})" + ")$", "g"), false ), BA: new IbanSpecification( "BA", 'Bosnia and Herzegovina', 20, "BA2!n3!n3!n8!n2!n", 16, "3!n3!n8!n2!n", new RegExp( "^(?BA)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{3})" + "(?[0-9]{3})" + "([0-9]{8})" + "([0-9]{2})" + ")$", "g"), false ), BE: new IbanSpecification( "BE", 'Belgium', 16, "BE2!n3!n7!n2!n", 12, "3!n7!n2!n", new RegExp( "^(?BE)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{3})" + "([0-9]{7})" + "([0-9]{2})" + ")$", "g"), true ), BG: new IbanSpecification( "BG", 'Bulgaria', 22, "BG2!n4!a4!n2!n8!c", 18, "4!a4!n2!n8!c", new RegExp( "^(?BG)" + "(?[0-9]{2})" + "(?" + "(?[A-Z]{4})" + "(?[0-9]{4})" + "([0-9]{2})" + "([0-9a-zA-Z]{8})" + ")$", "g"), true ), BH: new IbanSpecification( "BH", 'Bahrain', 22, "BH2!n4!a14!c", 18, "4!a14!c", new RegExp( "^(?BH)" + "(?[0-9]{2})" + "(?" + "(?[A-Z]{4})" + "([0-9a-zA-Z]{14})" + ")$", "g"), false ), BI: Object.assign(new IbanSpecification( "BI", 'Burundi', 27, "BI2!n5!n5!n11!n2!n", 23, "5!n5!n11!n2!n", new RegExp( "^(?BI)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{5})" + "(?[0-9]{5})" + "([0-9]{11})" + "([0-9]{2})" + ")$", "g"), false ), { getFormattedIban(iban) { return [ iban.substring(0, 4), iban.substring(4, 9), iban.substring(9, 14), iban.substring(14, 25), iban.substring(25, 27), ].join(' '); } }), BR: new IbanSpecification( "BR", 'Brazil', 29, "BR2!n8!n5!n10!n1!a1!c", 25, "8!n5!n10!n1!a1!c", new RegExp( "^(?BR)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{8})" + "(?[0-9]{5})" + "([0-9]{10})" + "([A-Z])" + "([0-9a-zA-Z])" + ")$", "g"), false ), BY: new IbanSpecification( "BY", 'Republic of Belarus\n', 28, "BY2!n4!c4!n16!c", 24, "4!c4!n16!c", new RegExp( "^(?BY)" + "(?[0-9]{2})" + "(?" + "(?[0-9a-zA-Z]{4})" + "([0-9]{4})" + "([0-9a-zA-Z]{16})" + ")$", "g"), false ), CH: new IbanSpecification( "CH", 'Switzerland', 21, "CH2!n5!n12!c", 17, "5!n12!c", new RegExp( "^(?CH)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{5})" + "([0-9a-zA-Z]{12})" + ")$", "g"), true ), CR: new IbanSpecification( "CR", 'Costa Rica', 22, "CR2!n4!n14!n", 18, "4!n14!n", new RegExp( "^(?CR)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{4})" + "([0-9]{14})" + ")$", "g"), false ), CY: new IbanSpecification( "CY", 'Cyprus', 28, "CY2!n3!n5!n16!c", 24, "3!n5!n16!c", new RegExp( "^(?CY)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{3})" + "(?[0-9]{5})" + "([0-9a-zA-Z]{16})" + ")$", "g"), true ), CZ: new IbanSpecification( "CZ", 'Czech Republic', 24, "CZ2!n4!n6!n10!n\n", 20, "4!n6!n10!n", new RegExp( "^(?CZ)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{4})" + "([0-9]{6})" + "([0-9]{10})" + ")$", "g"), true ), DE: new IbanSpecification( "DE", 'Germany', 22, "DE2!n8!n10!n\n", 18, "8!n10!n", new RegExp( "^(?DE)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{8})" + "([0-9]{10})" + ")$", "g"), true ), DJ: new IbanSpecification( "DJ", 'Djibouti', 27, "DJ2!n5!n5!n11!n2!n\n", 23, "5!n5!n11!n2!n\n", new RegExp( "^(?DJ)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{5})" + "(?[0-9]{5})" + "([0-9]{11})" + "([0-9]{2})" + ")$", "g"), false ), DK: new IbanSpecification( "DK", 'Denmark', 18, "DK2!n4!n9!n1!n", 14, "4!n9!n1!n", new RegExp( "^(?DK)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{4})" + "([0-9]{9})" + "([0-9])" + ")$", "g"), true ), DO: new IbanSpecification( "DO", 'Dominican Republic', 28, "DO2!n4!c20!n", 24, "4!c20!n", new RegExp( "^(?DO)" + "(?[0-9]{2})" + "(?" + "(?[A-Z]{4})" + "([0-9]{20})" + ")$", "g"), false ), EE: new IbanSpecification( "EE", 'Estonia', 20, "EE2!n2!n14!n", 16, "2!n14!n", new RegExp( "^(?EE)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{2})" + "([0-9]{14})" + ")$", "g"), true ), EG: Object.assign(new IbanSpecification( "EG", 'Egypt', 29, "EG2!n4!n4!n17!n", 25, "4!n4!n17!n", new RegExp( "^(?EG)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{4})" + "(?[0-9]{4})" + "([0-9]{17})" + ")$", "g"), false ), { getFormattedIban(iban) { return iban; } }), ES: new IbanSpecification( "ES", 'Spain', 24, "4!n4!n1!n1!n10!n", 20, "ES2!n4!n4!n1!n1!n10!n", new RegExp( "^(?ES)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{4})" + "(?[0-9]{4})" + "([0-9])" + "([0-9])" + "([0-9]{10})" + ")$", "g"), true ), FI: new IbanSpecification( "FI", 'Finland', 18, "3!n11!n", 14, "FI2!n3!n11!n", new RegExp( "^(?FI)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{3})" + "([0-9]{11})" + ")$", "g"), true // FIXME: Includes AX ), FK: new IbanSpecification( "FK", 'Falkland Islands', 18, "2!a12!n", 14, "FK2!n2!a12!n", new RegExp( "^(?FK)" + "(?[0-9]{2})" + "(?" + "(?[A-Z]{1})" + "([0-9]{12})" + ")$", "g"), false ), FO: new IbanSpecification( "FO", 'Faroe Islands', 18, "FO2!n4!n9!n1!n", 14, "4!n9!n1!n", new RegExp( "^(?FO)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{4})" + "([0-9]{9})" + "([0-9])" + ")$", "g"), false ), FR: new IbanSpecification( "FR", 'France', 27, "FR2!n5!n5!n11!c2!n", 23, "5!n5!n11!c2!n", new RegExp( "^(?FR)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{5})" + "([0-9]{5})" + "([0-9a-zA-Z]{11})" + "([0-9]{2})" + ")$", "g"), true // FIXME: Includes a ton of extra countries ), GB: new IbanSpecification( "GB", 'United Kingdom', 22, "GB2!n4!a6!n8!n", 18, "4!a6!n8!n", new RegExp( "^(?GB)" + "(?[0-9]{2})" + "(?" + "(?[A-Z]{4})" + "(?[0-9]{6})" + "([0-9]{8})" + ")$", "g"), true // FIXME: Includes extra countries ), GE: new IbanSpecification( "GE", 'Georgia', 22, "GE2!n2!a16!n", 18, "2!a16!n", new RegExp( "^(?GE)" + "(?[0-9]{2})" + "(?" + "(?[A-Z]{2})" + "([0-9]{16})" + ")$", "g"), false ), GI: new IbanSpecification( "GI", 'Gibraltar', 23, "GI2!n4!a15!c", 19, "4!a15!c", new RegExp( "^(?GI)" + "(?[0-9]{2})" + "(?" + "(?[A-Z]{4})" + "([0-9a-zA-Z]{15})" + ")$", "g"), true ), GL: new IbanSpecification( "GL", 'Greenland', 18, "GL2!n4!n9!n1!n", 14, "4!n9!n1!n", new RegExp( "^(?GL)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{4})" + "([0-9]{9})" + "([0-9])" + ")$", "g"), false ), GR: new IbanSpecification( "GR", 'Greece', 27, "GR2!n3!n4!n16!c", 23, "3!n4!n16!c", new RegExp( "^(?GR)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{3})" + "(?[0-9]{4})" + "([0-9a-zA-Z]{16})" + ")$", "g"), true ), GT: new IbanSpecification( "GT", 'Guatemala', 28, "GT2!n4!c20!c", 24, "4!c20!c", new RegExp( "^(?GT)" + "(?[0-9]{2})" + "(?" + "(?[0-9a-zA-Z]{4})" + "([0-9a-zA-Z]{20})" + ")$", "g"), false ), HN: new IbanSpecification( "HN", 'Honduras', 28, "HN2!n4!a20!n", 24, "4!a20!n", new RegExp( "^(?HN)" + "(?[0-9]{2})" + "(?" + "(?[A-Z]{4})" + "([0-9]{20})" + ")$", "g"), false ), HR: new IbanSpecification( "HR", 'Croatia', 21, "HR2!n7!n10!n", 17, "7!n10!n", new RegExp( "^(?HR)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{7})" + "([0-9]{10})" + ")$", "g"), true ), HU: new IbanSpecification( "HU", 'Hungary', 28, "HU2!n3!n4!n1!n15!n1!n", 24, "3!n4!n1!n15!n1!n", new RegExp( "^(?HU)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{3})" + "(?[0-9]{4})" + "([0-9])" + "([0-9]{15})" + "([0-9])" + ")$", "g"), true ), IE: new IbanSpecification( "IE", 'Ireland', 22, "IE2!n4!a6!n8!n", 18, "4!a6!n8!n", new RegExp( "^(?IE)" + "(?[0-9]{2})" + "(?" + "(?[A-Z]{4})" + "(?[0-9]{6})" + "([0-9]{8})" + ")$", "g"), true ), IL: new IbanSpecification( "IL", 'Israel', 23, "IL2!n3!n3!n13!n", 19, "3!n3!n13!n", new RegExp( "^(?IL)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{3})" + "(?[0-9]{3})" + "([0-9]{13})" + ")$", "g"), false ), IQ: new IbanSpecification( "IQ", 'Iraq', 23, "IQ2!n4!a3!n12!n", 19, "4!a3!n12!n", new RegExp( "^(?IQ)" + "(?[0-9]{2})" + "(?" + "(?[A-Z]{4})" + "(?[0-9]{3})" + "([0-9]{12})" + ")$", "g"), false ), IS: new IbanSpecification( "IS", 'Iceland', 26, "IS2!n4!n2!n6!n10!n", 22, "4!n2!n6!n10!n", new RegExp( "^(?IS)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{2})" + "(?[0-9]{2})" + "([0-9]{2})" + "([0-9]{6})" + "([0-9]{10})" + ")$", "g"), true ), IT: new IbanSpecification( "IT", 'Italy', 27, "IT2!n1!a5!n5!n12!c", 23, "1!a5!n5!n12!c", new RegExp( "^(?IT)" + "(?[0-9]{2})" + "(?" + "([A-Z])" + "(?[0-9]{5})" + "(?[0-9]{5})" + "([0-9a-zA-Z]{12})" + ")$", "g"), true ), JO: new IbanSpecification( "JO", 'Jordan', 30, "JO2!n4!a4!n18!c", 26, "4!a4!n18!c", new RegExp( "^(?JO)" + "(?[0-9]{2})" + "(?" + "([A-Z]{4})" + "(?[0-9]{4})" + "([0-9a-zA-Z]{18})" + ")$", "g"), false ), KW: new IbanSpecification( "KW", 'Kuwait', 30, "KW2!n4!a22!c", 26, "4!a22!c", new RegExp( "^(?KW)" + "(?[0-9]{2})" + "(?" + "(?[A-Z]{4})" + "([0-9a-zA-Z]{22})" + ")$", "g"), false ), KZ: new IbanSpecification( "KZ", 'Kazakhstan', 20, "KZ2!n3!n13!c", 16, "3!n13!c", new RegExp( "^(?KZ)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{3})" + "([0-9a-zA-Z]{13})" + ")$", "g"), false ), LB: new IbanSpecification( "LB", 'Lebanon', 28, "LB2!n4!n20!c", 24, "4!n20!c", new RegExp( "^(?LB)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{4})" + "([0-9a-zA-Z]{20})" + ")$", "g"), false ), LC: new IbanSpecification( "LC", 'Saint Lucia', 32, "LC2!n4!a24!c", 28, "4!a24!c", new RegExp( "^(?LC)" + "(?[0-9]{2})" + "(?" + "(?[A-Z]{4})" + "([0-9a-zA-Z]{24})" + ")$", "g"), false ), LI: new IbanSpecification( "LI", 'Liechtenstein', 21, "LI2!n5!n12!c", 17, "5!n12!c", new RegExp( "^(?LI)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{5})" + "([0-9a-zA-Z]{12})" + ")$", "g"), true ), LT: new IbanSpecification( "LT", 'Lithuania', 20, "LT2!n5!n11!n", 16, "5!n11!n", new RegExp( "^(?LT)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{5})" + "([0-9]{11})" + ")$", "g"), true ), LU: new IbanSpecification( "LU", 'Luxembourg', 20, "LU2!n3!n13!c", 16, "3!n13!c", new RegExp( "^(?LU)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{3})" + "([0-9a-zA-Z]{13})" + ")$", "g"), true ), LV: new IbanSpecification( "LV", 'Latvia', 21, "LV2!n4!a13!c", 17, "4!a13!c", new RegExp( "^(?LV)" + "(?[0-9]{2})" + "(?" + "(?[A-Z]{4})" + "([0-9a-zA-Z]{13})" + ")$", "g"), true ), LY: new IbanSpecification( "LY", 'Libya', 25, "LY2!n3!n3!n15!n", 21, "3!n3!n15!n", new RegExp( "^(?MC)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{3})" + "(?[0-9]{3})" + "([0-9]{15})" + ")$", "g"), true // FIXME: Has special format ), MC: new IbanSpecification( "MC", 'Monaco', 27, "MC2!n5!n5!n11!c2!n", 23, "5!n5!n11!c2!n", new RegExp( "^(?MC)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{5})" + "(?[0-9]{5})" + "([0-9a-zA-Z]{11})" + "([0-9]{2})" + ")$", "g"), true ), MD: new IbanSpecification( "MD", 'Moldova', 24, "MD2!n2!c18!c", 20, "2!c18!c", new RegExp( "^(?MD)" + "(?[0-9]{2})" + "(?" + "(?[0-9a-zA-Z]{2})" + "([0-9a-zA-Z]{18})" + ")$", "g"), false ), ME: new IbanSpecification( "ME", 'Montenegro', 22, "ME2!n3!n13!n2!n", 18, "3!n13!n2!n", new RegExp( "^(?ME)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{3})" + "([0-9]{13})" + "([0-9]{2})" + ")$", "g"), false ), MK: new IbanSpecification( "MK", 'Macedonia', 19, "MK2!n3!n10!c2!n", 15, "3!n10!c2!n", new RegExp( "^(?MK)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{3})" + "([0-9a-zA-Z]{10})" + "([0-9]{2})" + ")$", "g"), false ), MN: new IbanSpecification( "MN", 'Mongolia', 20, "MN2!n4!n12!n", 16, "4!n12!n", new RegExp( "^(?MN)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{4})" + "([0-9]{12})" + ")$", "g"), false ), MR: new IbanSpecification( "MR", 'Mauritania', 27, "MR2!n5!n5!n11!n2!n", 23, "5!n5!n11!n2!n", new RegExp( "^(?MR)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{5})" + "(?[0-9]{5})" + "([0-9]{11})" + "([0-9]{2})" + ")$", "g"), false ), MT: new IbanSpecification( "MT", 'Malta', 31, "MT2!n4!a5!n18!c", 27, "4!a5!n18!c", new RegExp( "^(?MT)" + "(?[0-9]{2})" + "(?" + "(?[A-Z]{4})" + "(?[0-9]{5})" + "([0-9a-zA-Z]{18})" + ")$", "g"), true ), MU: new IbanSpecification( "MU", 'Mauritius', 30, "MU2!n4!a2!n2!n12!n3!n3!a", 26, "4!a2!n2!n12!n3!n3!a", new RegExp( "^(?MU)" + "(?[0-9]{2})" + "(?" + "(?[A-Z]{4}[0-9]{2})" + "(?[0-9]{2})" + "([0-9]{12})" + "([0-9]{3})" + "([A-Z]{3})" + ")$", "g"), false ), NI: new IbanSpecification( "NI", 'Nicaragua', 28, "NI2!n4!a20!n", 24, "4!a20!n", new RegExp( "^(?NI)" + "(?[0-9]{2})" + "(?" + "(?[A-Z]{4})" + "([0-9]{20})" + ")$", "g"), false ), NL: new IbanSpecification( "NL", 'Netherlands', 18, "NL2!n4!a10!n", 14, "4!a10!n", new RegExp( "^(?NL)" + "(?[0-9]{2})" + "(?" + "(?[A-Z]{4})" + "([0-9]{10})" + ")$", "g"), true ), NO: new IbanSpecification( "NO", 'Norway', 15, "NO2!n4!n6!n1!n", 11, "4!n6!n1!n", new RegExp( "^(?NO)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{4})" + "([0-9]{6})" + "([0-9])" + ")$", "g"), true ), OM: new IbanSpecification( "OM", 'Oman', 23, "OM2!n3!n16!c", 19, "3!n16!c", new RegExp( "^(?OM)" + "(?[0-9]{2})" + "(?" + "(?[A-Z]{3})" + "([0-9a-zA-Z]{16})" + ")$", "g"), false ), PK: new IbanSpecification( "PK", 'Pakistan', 24, "PK2!n4!a16!c", 20, "4!a16!c", new RegExp( "^(?PK)" + "(?[0-9]{2})" + "(?" + "(?[A-Z]{4})" + "([0-9a-zA-Z]{16})" + ")$", "g"), false ), PL: new IbanSpecification( "PL", 'Poland', 28, "PL2!n8!n16!n", 24, "8!n16!n", new RegExp( "^(?PL)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{8})" + "([0-9]{16})" + ")$", "g"), true ), PS: new IbanSpecification( "PS", 'Palestine', 29, "PS2!n4!a21!c\n", 25, "4!a21!c", new RegExp( "^(?PS)" + "(?[0-9]{2})" + "(?" + "(?[A-Z]{4})" + "([0-9a-zA-Z]{21})" + ")$", "g"), false ), PT: new IbanSpecification( "PT", 'Portugal', 25, "PT2!n4!n4!n11!n2!n", 21, "4!n4!n11!n2!n\n", new RegExp( "^(?PT)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{4})" + "(?[0-9]{4})" + "([0-9]{11})" + "([0-9]{2})" + ")$", "g"), true // FIXME: Includes extra zones ), QA: new IbanSpecification( "QA", 'Qatar', 29, "QA2!n4!a21!c", 25, "4!a21!c", new RegExp( "^(?QA)" + "(?[0-9]{2})" + "(?" + "(?[A-Z]{4})" + "([0-9a-zA-Z]{21})" + ")$", "g"), false ), RO: new IbanSpecification( "RO", 'Romania', 24, "RO2!n4!a16!c", 20, "4!a16!c", new RegExp( "^(?RO)" + "(?[0-9]{2})" + "(?" + "(?[A-Z]{4})" + "([0-9a-zA-Z]{16})" + ")$", "g"), true ), RS: new IbanSpecification( "RS", 'Serbia', 22, "RS2!n3!n13!n2!n", 18, "3!n13!n2!n", new RegExp( "^(?RS)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{3})" + "([0-9]{13})" + "([0-9]{2})" + ")$", "g"), false ), RU: new IbanSpecification( "RU", 'Russia', 33, "RU2!n9!n5!n15!c", 29, "9!n5!n15!c", new RegExp( "^(?RU)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{9})" + "(?[0-9]{5})" + "([0-9a-zA-Z]{15})" + ")$", "g"), false ), SA: new IbanSpecification( "SA", 'Saudi Arabia', 24, "SA2!n2!n18!c", 20, "2!n18!c", new RegExp( "^(?SA)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{2})" + "([0-9a-zA-Z]{18})" + ")$", "g"), false ), SC: new IbanSpecification( "SC", 'Seychelles', 31, "SC2!n4!a2!n2!n16!n3!a", 27, "4!a2!n2!n16!n3!a", new RegExp( "^(?SC)" + "(?[0-9]{2})" + "(?" + "(?[A-Z]{4}[0-9]{2})" + "(?[0-9]{2})" + "([0-9]{16})" + "([A-Z]{3})" + ")$", "g"), false ), SD: new IbanSpecification( "SD", 'Sudan', 18, "SD2!n2!n12!n", 14, "2!n12!n", new RegExp( "^(?SD)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{2})" + "([0-9]{12})" + ")$", "g"), false ), SE: new IbanSpecification( "SE", 'Sweden', 24, "SE2!n3!n16!n1!n", 20, "3!n16!n1!n", new RegExp( "^(?SE)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{3})" + "([0-9]{16})" + "([0-9])" + ")$", "g"), true ), SI: new IbanSpecification( "SI", 'Slovenia', 19, "SI2!n5!n8!n2!n", 15, "5!n8!n2!n", new RegExp( "^(?SI)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{5})" + "([0-9]{8})" + "([0-9]{2})" + ")$", "g"), true ), SK: new IbanSpecification( "SK", 'Slovakia', 24, "SK2!n4!n6!n10!n", 20, "4!n6!n10!n", new RegExp( "^(?SK)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{4})" + "([0-9]{6})" + "([0-9]{10})" + ")$", "g"), true ), SM: new IbanSpecification( "SM", 'San Marino', 27, "SM2!n1!a5!n5!n12!c", 23, "1!a5!n5!n12!c", new RegExp( "^(?SM)" + "(?[0-9]{2})" + "(?" + "([A-Z])" + "(?[0-9]{5})" + "(?[0-9]{5})" + "([0-9a-zA-Z]{12})" + ")$", "g"), true ), SO: new IbanSpecification( "SO", 'Somalia', 23, "SO2!n4!n3!n12!n", 19, "4!n3!n12!n", new RegExp( "^(?SO)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{4})" + "(?[0-9]{3})" + "([0-9]{12})" + ")$", "g"), false ), ST: new IbanSpecification( "ST", 'Sao Tome and Principe', 25, "ST2!n4!n4!n11!n2!n", 21, "8!n11!n2!n", new RegExp( "^(?ST)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{4})" + "(?[0-9]{4})" + "([0-9]{11})" + "([0-9]{2})" + ")$", "g"), false ), SV: new IbanSpecification( "SV", 'El Salvador', 28, "SV2!n4!a20!n", 24, "4!a20!n", new RegExp( "^(?SV)" + "(?[0-9]{2})" + "(?" + "(?[A-Z]{4})" + "([0-9]{20})" + ")$", "g"), false // FIXME: Special format !!! ), TL: new IbanSpecification( "TL", 'Timor-Leste', 23, "TL2!n3!n14!n2!n", 19, "3!n14!n2!n", new RegExp( "^(?TL)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{3})" + "([0-9]{14})" + "([0-9]{2})" + ")$", "g"), false ), TN: new IbanSpecification( "TN", 'Tunisia', 24, "TN2!n2!n3!n13!n2!n", 20, "2!n3!n13!n2!n\n", new RegExp( "^(?TN)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{2})" + "(?[0-9]{3})" + "([0-9]{13})" + "([0-9]{2})" + ")$", "g"), false ), TR: new IbanSpecification( "TR", 'Turkey', 26, "TR2!n5!n1!n16!c", 22, "5!n1!n16!c", new RegExp( "^(?TR)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{5})" + "([0-9a-zA-Z])" + "([0-9a-zA-Z]{16})" + ")$", "g"), false ), UA: new IbanSpecification( "UA", 'Ukraine', 29, "UA2!n6!n19!c", 25, "6!n19!c", new RegExp( "^(?UA)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{6})" + "([0-9a-zA-Z]{19})" + ")$", "g"), false ), VA: new IbanSpecification( "VA", 'Vatican City State\n', 22, "VA2!n3!n15!n", 18, "3!n15!n", new RegExp( "^(?VA)" + "(?[0-9]{2})" + "(?" + "(?[A-Z]{3})" + "([0-9]{15})" + ")$", "g"), false // FIXME: Has empty data for SEPA !!! ), VG: new IbanSpecification( "VG", 'Virgin Islands', 24, "VG2!n4!a16!n", 20, "4!a16!n", new RegExp( "^(?VG)" + "(?[0-9]{2})" + "(?" + "(?[A-Z]{4})" + "([0-9]{16})" + ")$", "g"), false ), XK: new IbanSpecification( "XK", 'Kosovo', 20, "XK2!n4!n10!n2!n", 16, "4!n10!n2!n", new RegExp( "^(?XK)" + "(?[0-9]{2})" + "(?" + "(?[0-9]{2})" + "(?[0-9]{2})" + "([0-9]{10})" + "([0-9]{2})" + ")$", "g"), false ), YE: new IbanSpecification( "YE", 'Yemen', 30, "YE2!n4!a4!n18!c", 26, "4!a4!n18!c", new RegExp( "^(?YE)" + "(?[0-9]{2})" + "(?" + "(?[A-Z]{4})" + "(?[0-9]{4})" + "([0-9a-zA-Z]{18})" + ")$", "g"), false ), };