encodeData static method

Uint8List encodeData(
  1. String primaryType,
  2. dynamic data,
  3. Map<String, List<TypedDataField>> types,
  4. String version,
)

Implementation

static Uint8List encodeData(String primaryType, dynamic data,
    Map<String, List<TypedDataField>> types, String version) {
  if (!(data is Map<String, dynamic>) && !(data is EIP712Domain)) {
    throw ArgumentError("Unsupported data type");
  }

  final encodedTypes = <String>['bytes32'];
  List<dynamic> encodedValues = [];
  encodedValues.add(hashType(primaryType, types));

  if (version == 'V4') {
    List<dynamic> encodeField(String name, String type, dynamic value) {
      if (types[type] != null) {
        return [
          'bytes32',
          value == null // eslint-disable-line no-eq-null
              ? '0x0000000000000000000000000000000000000000000000000000000000000000'
              : keccak256((encodeData(type, value, types, version))),
        ];
      }

      if (value == null) {
        throw ArgumentError(
            'missing value for field ${name} of type ${type}');
      }

      if (type == 'bytes') {
        if (value is String) {
          if (isHexString(value)) {
            value = keccak256(hexToBytes(value));
          } else {
            value = keccak256(Uint8List.fromList(utf8.encode(value)));
          }
        } else if (value is List) {
          value = keccak256(Uint8List.fromList(List<int>.from(value)));
        } else {
          throw new ArgumentError('Not supported type for bytes');
        }
        return ['bytes32', value];
      }

      if (type == 'string') {
        // convert string to buffer - prevents ethUtil from interpreting strings like '0xabcd' as hex
        if (value is String) {
          value = Uint8List.fromList(utf8.encode(value));
        }
        return ['bytes32', keccak256(value)];
      }

      if (type.lastIndexOf(']') == type.length - 1) {
        final parsedType = type.substring(0, type.lastIndexOf('['));
        final typeValuePairs = value
            .map(
              (item) => encodeField(name, parsedType, item),
            )
            .toList();

        final List<String> tList =
            (typeValuePairs as List).map((l) => l[0].toString()).toList();
        final List<dynamic> vList = typeValuePairs.map((l) => l[1]).toList();
        return [
          'bytes32',
          keccak256(
            AbiUtil.rawEncode(
              tList,
              vList,
            ),
          ),
        ];
      }

      return [type, value];
    }

    final fields = types[primaryType];
    fields?.forEach((field) {
      final List<dynamic> result = encodeField(
        field.name,
        field.type,
        data[field.name],
      );
      encodedTypes.add(result[0]);
      encodedValues.add(result[1]);
    });
  } else {
    types[primaryType]?.forEach((TypedDataField field) {
      var value = data[field.name];
      if (value != null) {
        if (field.type == 'bytes') {
          encodedTypes.add('bytes32');
          if (value is String) {
            if (isHexString(value)) {
              value = keccak256(hexToBytes(value));
            } else {
              value = keccak256(Uint8List.fromList(utf8.encode(value)));
            }
          }
          encodedValues.add(value);
        } else if (field.type == 'string') {
          encodedTypes.add('bytes32');
          // convert string to buffer - prevents ethUtil from interpreting strings like '0xabcd' as hex
          if (value is String) {
            value = Uint8List.fromList(utf8.encode(value));
          }
          value = keccak256(value);
          encodedValues.add(value);
        } else if (types[field.type] != null) {
          encodedTypes.add('bytes32');
          value = keccak256(encodeData(field.type, value, types, version));
          encodedValues.add(value);
        } else if (field.type.lastIndexOf(']') == field.type.length - 1) {
          throw new ArgumentError(
              'Arrays are unimplemented in encodeData; use V4 extension');
        } else {
          encodedTypes.add(field.type);
          encodedValues.add(value);
        }
      }
    });
  }

  return AbiUtil.rawEncode(encodedTypes, encodedValues);
}