/// <inheritdoc />
        public async Task <ProofRecord> CreatePresentationAsync(IAgentContext agentContext, RequestPresentationMessage requestPresentation, RequestedCredentials requestedCredentials)
        {
            var service = requestPresentation.GetDecorator <ServiceDecorator>(DecoratorNames.ServiceDecorator);

            var record = await ProcessRequestAsync(agentContext, requestPresentation, null);

            var(presentationMessage, proofRecord) = await CreatePresentationAsync(agentContext, record.Id, requestedCredentials);

            await MessageService.SendAsync(
                wallet : agentContext.Wallet,
                message : presentationMessage,
                recipientKey : service.RecipientKeys.First(),
                endpointUri : service.ServiceEndpoint,
                routingKeys : service.RoutingKeys?.ToArray());

            return(proofRecord);
        }
        /// <inheritdoc />
        public async Task <(RequestPresentationMessage, ProofRecord)> CreateRequestFromProposalAsync(IAgentContext agentContext, ProofRequestParameters requestParams,
                                                                                                     string proofRecordId, string connectionId)
        {
            Logger.LogInformation(LoggingEvents.CreateProofRequest, "ConnectionId {0}", connectionId);

            if (proofRecordId == null)
            {
                throw new ArgumentNullException(nameof(proofRecordId), "You must provide proof record Id");
            }
            if (connectionId != null)
            {
                var connection = await ConnectionService.GetAsync(agentContext, connectionId);

                if (connection.State != ConnectionState.Connected)
                {
                    throw new AriesFrameworkException(ErrorCode.RecordInInvalidState,
                                                      $"Connection state was invalid. Expected '{ConnectionState.Connected}', found '{connection.State}'");
                }
            }

            var proofRecord = await RecordService.GetAsync <ProofRecord>(agentContext.Wallet, proofRecordId);

            var proofProposal = proofRecord.ProposalJson.ToObject <ProofProposal>();


            // Build Proof Request from Proposal info
            var proofRequest = new ProofRequest
            {
                Name                = requestParams.Name,
                Version             = requestParams.Version,
                Nonce               = await AnonCreds.GenerateNonceAsync(),
                RequestedAttributes = new Dictionary <string, ProofAttributeInfo>(),
                NonRevoked          = requestParams.NonRevoked
            };

            var attributesByReferent = new Dictionary <string, List <ProposedAttribute> >();

            foreach (var proposedAttribute in proofProposal.ProposedAttributes)
            {
                if (proposedAttribute.Referent == null)
                {
                    proposedAttribute.Referent = Guid.NewGuid().ToString();
                }

                if (attributesByReferent.TryGetValue(proposedAttribute.Referent, out var referentAttributes))
                {
                    referentAttributes.Add(proposedAttribute);
                }
                else
                {
                    attributesByReferent.Add(proposedAttribute.Referent, new List <ProposedAttribute> {
                        proposedAttribute
                    });
                }
            }

            foreach (var referent in attributesByReferent.AsEnumerable())
            {
                var proposedAttributes = referent.Value;
                var attributeName      = proposedAttributes.Count() == 1 ? proposedAttributes.Single().Name : null;
                var attributeNames     = proposedAttributes.Count() > 1 ? proposedAttributes.ConvertAll <string>(r => r.Name).ToArray() : null;


                var requestedAttribute = new ProofAttributeInfo()
                {
                    Name         = attributeName,
                    Names        = attributeNames,
                    Restrictions = new List <AttributeFilter>
                    {
                        new AttributeFilter {
                            CredentialDefinitionId = proposedAttributes.First().CredentialDefinitionId,
                            SchemaId  = proposedAttributes.First().SchemaId,
                            IssuerDid = proposedAttributes.First().IssuerDid
                        }
                    }
                };
                proofRequest.RequestedAttributes.Add(referent.Key, requestedAttribute);
                Console.WriteLine($"Added Attribute to Proof Request \n {proofRequest.ToString()}");
            }

            foreach (var pred in proofProposal.ProposedPredicates)
            {
                if (pred.Referent == null)
                {
                    pred.Referent = Guid.NewGuid().ToString();
                }
                var predicate = new ProofPredicateInfo()
                {
                    Name           = pred.Name,
                    PredicateType  = pred.Predicate,
                    PredicateValue = pred.Threshold,
                    Restrictions   = new List <AttributeFilter>
                    {
                        new AttributeFilter {
                            CredentialDefinitionId = pred.CredentialDefinitionId,
                            SchemaId  = pred.SchemaId,
                            IssuerDid = pred.IssuerDid
                        }
                    }
                };
                proofRequest.RequestedPredicates.Add(pred.Referent, predicate);
            }

            proofRecord.RequestJson = proofRequest.ToJson();
            await proofRecord.TriggerAsync(ProofTrigger.Request);

            await RecordService.UpdateAsync(agentContext.Wallet, proofRecord);

            var message = new RequestPresentationMessage
            {
                Id       = proofRecord.Id,
                Requests = new[]
                {
                    new Attachment
                    {
                        Id       = "libindy-request-presentation-0",
                        MimeType = CredentialMimeTypes.ApplicationJsonMimeType,
                        Data     = new AttachmentContent
                        {
                            Base64 = proofRequest
                                     .ToJson()
                                     .GetUTF8Bytes()
                                     .ToBase64String()
                        }
                    }
                }
            };

            message.ThreadFrom(proofRecord.GetTag(TagConstants.LastThreadId));
            return(message, proofRecord);
        }