spb/os-vault Public
Self-custody, multi-chain crypto wallet for macOS. One recovery phrase, six chain families, zero API keys — nothing leaves your Mac.
Swift 96%
Shell 3.4%
Makefile 0.6%
1//2// AddressValidator.swift3// OS Vault4//5// Author: Simon-Pierre Boucher6// Mail: contact@spboucher.ai7//89import Foundation10import Web3Core1112/// Recipient address validation: hex shape + EIP-55 checksum.13/// All-lowercase (or all-uppercase) addresses carry no checksum information —14/// they are accepted with a warning, per the project security rules.15public enum AddressValidator {1617 public enum Verdict: Equatable {18 /// Mixed-case address whose EIP-55 checksum matches.19 case valid(checksummed: String)20 /// Well-formed but caseless — no checksum to verify. Warn, don't block.21 case validNoChecksum(checksummed: String)22 case invalid23 }2425 public static func validate(_ input: String) -> Verdict {26 let candidate = input.trimmingCharacters(in: .whitespacesAndNewlines)27 guard candidate.count == 42, candidate.hasPrefix("0x") else { return .invalid }28 let body = String(candidate.dropFirst(2))29 guard body.allSatisfy({ $0.isHexDigit }) else { return .invalid }30 guard let checksummed = EthereumAddress.toChecksumAddress(candidate) else { return .invalid }3132 // An exact checksum match is valid even when it happens to be all one33 // case (some EIP-55 checksums are, e.g. 0x529084…9EE7).34 if candidate == checksummed {35 return .valid(checksummed: checksummed)36 }37 let letters = body.filter { $0.isLetter }38 let caseless = letters.isEmpty39 || letters.allSatisfy { $0.isLowercase }40 || letters.allSatisfy { $0.isUppercase }41 return caseless ? .validNoChecksum(checksummed: checksummed) : .invalid42 }43}44