buildW3cCredentialwithHashes function

String buildW3cCredentialwithHashes(
  1. dynamic credential,
  2. String? issuerDid, {
  3. dynamic type,
  4. dynamic context,
  5. dynamic issuerInformation,
  6. DateTime? validUntil,
  7. String? revocationRegistryAddress,
})

Builds a credential conform to W3C-Standard, which includes all hashes a plaintext-credential credential contains.

issuerInformation is a valid json Object (dart string or map) containing additional Information about the issuer, e.g its homepage or name.

revocationRegistryAddress is a valid Ethereum-Address of a SmartContract capable of showing the revocation Status of the credential.

Implementation

String buildW3cCredentialwithHashes(dynamic credential, String? issuerDid,
    {dynamic type,
    dynamic context,
    dynamic issuerInformation,
    DateTime? validUntil,
    String? revocationRegistryAddress}) {
  var plaintextMap = credentialToMap(credential);
  var hashCred =
      _collectHashes(credential, id: plaintextMap['id'], firstLevel: true);

  List<String> credTypes = [];
  credTypes.add('VerifiableCredential');
  if (type != null) {
    if (type is String) {
      if (type != 'VerifiableCredential') credTypes.add(type);
    } else if (type is List<String>) {
      type.remove('VerifiableCredential');
      credTypes.addAll(type);
    } else {
      throw Exception('type has unknown datatype');
    }
  }

  List<dynamic> credContext = [];
  credContext.add('https://www.w3.org/2018/credentials/v1');
  if (context != null) {
    if (context is String) {
      if (context != 'https://www.w3.org/2018/credentials/v1') {
        credContext.add(context);
      }
    } else if (context is List<String>) {
      if (context.contains('https://www.w3.org/2018/credentials/v1')) {
        context.remove('https://www.w3.org/2018/credentials/v1');
      }
      credContext += context;
    } else if (context is Map) {
      credContext.add(context);
    } else if (context is List) {
      credContext += context;
    } else {
      throw Exception('context has unknown datatype');
    }
  }
  // adding context of Plaintext-credential
  var plaintextCredMap = credentialToMap(credential);
  if (plaintextCredMap.containsKey('@context')) {
    var context = plaintextCredMap['@context'];
    if (context is List) {
      for (var element in context) {
        if (!credContext.contains(element)) {
          credContext.add(element);
        }
      }
    } else if (context is String) {
      if (!credContext.contains(context)) credContext.add(context);
    } else {
      throw Exception('@context has unsupported type');
    }
  }

  var issuerInfo = {};
  if (issuerInformation != null) {
    issuerInfo = credentialToMap(issuerInformation);
    issuerInfo['id'] = issuerDid;
  }

  var w3cCred = {
    '@context': credContext,
    'type': credTypes,
    'credentialSubject': jsonDecode(hashCred),
    'issuer': issuerInfo.isEmpty ? issuerDid : issuerInfo,
    'issuanceDate': DateTime.now().toUtc().toIso8601String()
  };

  if (validUntil != null) {
    w3cCred['expirationDate'] = validUntil.toIso8601String();
  }

  if (revocationRegistryAddress != null) {
    var credStatus = {
      'id': revocationRegistryAddress,
      'type': 'EthereumRevocationList'
    };
    w3cCred['credentialStatus'] = credStatus;
  }

  return jsonEncode(w3cCred);
}