parseAbiType function

AbiType parseAbiType(
  1. String name
)

Parses an ABI type from its AbiType.name.

Implementation

AbiType parseAbiType(String name) {
  if (_easyTypes.containsKey(name)) return _easyTypes[name]!;

  final arrayMatch = array.firstMatch(name);
  if (arrayMatch != null) {
    final type = parseAbiType(arrayMatch.group(1)!);
    final length = arrayMatch.group(2)!;

    if (length.isEmpty) {
      // T[], dynamic length then
      return DynamicLengthArray(type: type);
    } else {
      return FixedLengthArray(type: type, length: int.parse(length));
    }
  }

  final tupleMatch = _tuple.firstMatch(name);
  if (tupleMatch != null) {
    final inner = tupleMatch.group(1)!;
    final types = <AbiType>[];

    // types are separated by a comma. However, we can't just inner.split(')
    // because tuples might be nested: (bool, (uint, string))
    var openParenthesises = 0;
    final typeBuffer = StringBuffer();

    for (final char in inner.codeUnits) {
      if (char == _comma && openParenthesises == 0) {
        types.add(parseAbiType(typeBuffer.toString()));
        typeBuffer.clear();
      } else {
        typeBuffer.writeCharCode(char);

        if (char == _openingParenthesis) {
          openParenthesises++;
        } else if (char == _closingParenthesis) {
          openParenthesises--;
        }
      }
    }

    if (typeBuffer.isNotEmpty) {
      if (openParenthesises != 0) {
        throw ArgumentError(
          'Could not parse abi type because of mismatched brackets: $name',
        );
      }
      types.add(parseAbiType(typeBuffer.toString()));
    }

    return TupleType(types);
  }

  if (name.startsWith('uint')) {
    return UintType(length: _trailingNumber(name))..validate();
  } else if (name.startsWith('int')) {
    return IntType(length: _trailingNumber(name))..validate();
  } else if (name.startsWith('bytes')) {
    return FixedBytes(_trailingNumber(name))..validate();
  }

  throw ArgumentError('Could not parse abi type with name: $name');
}