buildPresentation function
Builds a presentation for credentials
.
If not only the ownership of the dids in the credentials should be proofed a List of additionalDids
could be given and a proof section for each did is added.
Implementation
Future<String> buildPresentation(
List<dynamic>? credentials, WalletStore wallet, String challenge,
{String? holder,
String? domain,
List<String>? additionalDids,
List<dynamic>? disclosedCredentials,
Function(Uri url, LoadDocumentOptions? options) loadDocumentFunction =
loadDocumentStrict}) async {
List<Map<String, dynamic>?> credMapList = [];
List<String?> holderDids = [];
Set<String> signatureContext = {};
PresentationSubmission? submission;
if (credentials != null) {
for (var element in credentials) {
if (element is FilterResult) {
List<InputDescriptorMappingObject> mapping = [];
if (submission != null) {
mapping = submission.descriptorMap;
}
for (var cred in element.credentials) {
var credEntry = cred.toJson();
credMapList.add(credEntry);
var tmp = getHolderDidFromCredential(credEntry);
holderDids.add(tmp);
signatureContext.add(_findContext(tmp));
for (var descriptor in element.matchingDescriptorIds) {
var map = InputDescriptorMappingObject(
id: descriptor,
format: 'ldp_vc',
path: JsonPath(
'\$.verifiableCredential[${credMapList.length - 1}]'));
mapping.add(map);
}
}
submission = PresentationSubmission(
presentationDefinitionId: element.presentationDefinitionId,
descriptorMap: mapping);
} else {
Map<String, dynamic> credMap;
if (element is VerifiableCredential) {
credMap = element.toJson();
} else {
credMap = credentialToMap(element);
}
credMapList.add(credMap);
if (!VerifiableCredential.fromJson(credMap)
.type
.contains('PublicKeyCertificate')) {
var tmp = getHolderDidFromCredential(credMap);
holderDids.add(tmp);
signatureContext.add(_findContext(tmp));
}
}
}
}
if (holder != null) {
holderDids.add(holder);
}
if (holderDids.isEmpty) {
throw Exception('No holder did given. Can\'t generate Presentation');
}
//TODO dynamically build context based on proof methods
List<String> context = [
'https://www.w3.org/2018/credentials/v1',
];
context.addAll(signatureContext);
List<String> type = ['VerifiablePresentation'];
if (submission != null) {
context.add(
'https://identity.foundation/presentation-exchange/submission/v1/');
type.add('PresentationSubmission');
}
Map<String, dynamic> presentation = {'@context': context, 'type': type};
if (credMapList.isNotEmpty) {
presentation['verifiableCredential'] = credMapList;
}
if (holder != null) {
presentation['holder'] = holder;
}
if (submission != null) {
presentation['presentation_submission'] = submission.toJson();
}
if (disclosedCredentials != null) {
List<Map<String, dynamic>?> disclosedCreds = [];
for (var element in disclosedCredentials) {
var credMap = credentialToMap(element);
disclosedCreds.add(credMap);
}
presentation['disclosedCredentials'] = disclosedCreds;
var type = presentation['type'] as List<String?>;
type.add('DisclosedCredentialPresentation');
presentation['type'] = type;
}
// build signatures
List<Map<String, dynamic>> proofList = [];
Set<Type> signerTypes = {};
for (var element in holderDids) {
print(element);
var signer = _determineSignerForDid(element!, loadDocumentFunction);
signerTypes.add(signer.runtimeType);
proofList.add(await signer.buildProof(presentation, wallet, element,
challenge: challenge, proofPurpose: 'authentication', domain: domain));
}
if (additionalDids != null) {
for (var element in additionalDids) {
var signer = _determineSignerForDid(element, loadDocumentFunction);
var t = signer.runtimeType;
if (t == EcdsaRecoverySignature &&
!context.contains(ecdsaRecoveryContextIri)) {
context.add(ecdsaRecoveryContextIri);
} else if (t == EdDsaSigner && !context.contains(ed25519ContextIri)) {
context.add(ed25519ContextIri);
}
proofList.add(await signer.buildProof(presentation, wallet, element,
challenge: challenge,
proofPurpose: 'authentication',
domain: domain));
}
}
presentation['proof'] = proofList;
return jsonEncode(presentation);
}