validBech32 function

Result<String, String> validBech32(
  1. {required String bech32,
  2. required List<String> hrpPrefixes,
  3. int? dataPartRequiredLength}
)

if bech32 string has the correct prefix, '1' seperator, legal data characters and optionaly correct length, the normalized correct form is returned. If it's not legal, then an explanation is returned in the error message.

Implementation

Result<String, String> validBech32(
    {required String bech32,
    required List<String> hrpPrefixes,
    int? dataPartRequiredLength}) {
  if (hrpPrefixes.isEmpty) {
    throw Exception("validBech32 hrpPrefixes array must not be empty");
  }
  if (isBlank(bech32)) return Err("address missing");
  final lowerCase = bech32.toLowerCase();
  if (hrpPrefixes.length > 1) {
    hrpPrefixes.sort((a, b) => b.compareTo(a));
  } //avoid matching 'addr' for 'addr_test'
  _logger.i(hrpPrefixes);
  final prefix = hrpPrefixes
      .firstWhere((prefix) => lowerCase.startsWith(prefix), orElse: () => '');
  if (isBlank(prefix)) {
    return Err("must start with ${hrpPrefixes.join(' or ')}");
  }
  if (lowerCase.length > prefix.length &&
      lowerCase.codeUnitAt(prefix.length) != '1'.codeUnitAt(0)) {
    return Err("missing '1' after prefix");
  }
  final data = lowerCase.length > prefix.length
      ? lowerCase.substring(prefix.length + 1)
      : '';
  int invalidCharIndex = _firstIllegalDataChar(data);
  if (invalidCharIndex > -1) {
    return Err(
        "invalid character: ${data.substring(invalidCharIndex, invalidCharIndex + 1)}");
  }
  if (dataPartRequiredLength != null && data.length != dataPartRequiredLength) {
    return Err(
        "data length is ${data.length}, requires $dataPartRequiredLength");
  }
  return Ok(lowerCase);
}