function ibanMod97(iban) { const rearranged = iban.slice(4) + iban.slice(0, 4) const expanded = rearranged .split('') .map((char) => { const code = char.charCodeAt(0) if (code >= 65 && code <= 90) return String(code - 55) return char }) .join('') let remainder = expanded while (remainder.length > 2) { const block = remainder.slice(0, 9) remainder = String(parseInt(block, 10) % 97) + remainder.slice(block.length) } return parseInt(remainder, 10) % 97 } /** digits24: the 24 digits after the "IR" prefix */ function isValidIranSheba(digits24) { if (!/^\d{24}$/.test(String(digits24 || ''))) return false return ibanMod97(`IR${digits24}`) === 1 } /** Standard Iranian national-code (کد ملی) checksum */ function isValidIranNationalCode(code) { const value = String(code || '') if (!/^\d{10}$/.test(value)) return false if (/^(\d)\1{9}$/.test(value)) return false const digits = value.split('').map(Number) const sum = digits .slice(0, 9) .reduce((acc, digit, index) => acc + digit * (10 - index), 0) const remainder = sum % 11 const checkDigit = remainder < 2 ? remainder : 11 - remainder return checkDigit === digits[9] } module.exports = { isValidIranSheba, isValidIranNationalCode, }