public async Task <ProofRecord> ProcessProposalAsync(IAgentContext agentContext, ProposePresentationMessage proposePresentationMessage, ConnectionRecord connection)
        {
            // save in wallet

            var proofProposal = new ProofProposal
            {
                Comment            = proposePresentationMessage.Comment,
                ProposedAttributes = proposePresentationMessage.PresentationPreviewMessage.ProposedAttributes.ToList <ProposedAttribute>(),
                ProposedPredicates = proposePresentationMessage.PresentationPreviewMessage.ProposedPredicates.ToList <ProposedPredicate>()
            };

            var proofRecord = new ProofRecord
            {
                Id           = Guid.NewGuid().ToString(),
                ProposalJson = proofProposal.ToJson(),
                ConnectionId = connection?.Id,
                State        = ProofState.Proposed
            };

            proofRecord.SetTag(TagConstants.LastThreadId, proposePresentationMessage.GetThreadId());
            proofRecord.SetTag(TagConstants.Role, TagConstants.Requestor);
            await RecordService.AddAsync(agentContext.Wallet, proofRecord);

            EventAggregator.Publish(new ServiceMessageProcessingEvent
            {
                RecordId    = proofRecord.Id,
                MessageType = proposePresentationMessage.Type,
                ThreadId    = proposePresentationMessage.GetThreadId()
            });

            return(proofRecord);
        }
        private void CheckProofProposalParameters(ProofProposal proofProposal)
        {
            if (proofProposal.ProposedAttributes.Count > 1)
            {
                var attrList  = proofProposal.ProposedAttributes;
                var referents = new Dictionary <string, ProposedAttribute>();

                // Check if all attributes that share referent have same requirements
                for (int i = 0; i < attrList.Count; i++)
                {
                    var attr = attrList[i];
                    if (referents.ContainsKey(attr.Referent))
                    {
                        if (referents[attr.Referent].IssuerDid != attr.IssuerDid ||
                            referents[attr.Referent].SchemaId != attr.SchemaId ||
                            referents[attr.Referent].CredentialDefinitionId != attr.CredentialDefinitionId)
                        {
                            throw new AriesFrameworkException(ErrorCode.InvalidParameterFormat, "All attributes that share a referent must have identical requirements");
                        }
                        else
                        {
                            continue;
                        }
                    }
                    else
                    {
                        referents.Add(attr.Referent, attr);
                    }
                }
            }
            if (proofProposal.ProposedPredicates.Count > 1)
            {
                var predList  = proofProposal.ProposedPredicates;
                var referents = new Dictionary <string, ProposedPredicate>();

                for (int i = 0; i < predList.Count; i++)
                {
                    var pred = predList[i];
                    if (referents.ContainsKey(pred.Referent))
                    {
                        throw new AriesFrameworkException(ErrorCode.InvalidParameterFormat, "Proposed Predicates must all have unique referents");
                    }
                    else
                    {
                        referents.Add(pred.Referent, pred);
                    }
                }
            }
        }
        /// <inheritdoc />
        public async Task <(ProposePresentationMessage, ProofRecord)> CreateProposalAsync(IAgentContext agentContext, ProofProposal proofProposal, string connectionId)
        {
            Logger.LogInformation(LoggingEvents.CreateProofRequest, "ConnectionId {0}", connectionId);

            if (proofProposal == null)
            {
                throw new ArgumentNullException(nameof(proofProposal), "You must provide a presentation preview");;
            }
            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}'");
                }
            }
            this.CheckProofProposalParameters(proofProposal);


            var threadId    = Guid.NewGuid().ToString();
            var proofRecord = new ProofRecord
            {
                Id           = Guid.NewGuid().ToString(),
                ConnectionId = connectionId,
                ProposalJson = proofProposal.ToJson(),
                State        = ProofState.Proposed
            };

            proofRecord.SetTag(TagConstants.Role, TagConstants.Holder);
            proofRecord.SetTag(TagConstants.LastThreadId, threadId);

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

            var message = new ProposePresentationMessage
            {
                Id      = threadId,
                Comment = proofProposal.Comment,
                PresentationPreviewMessage = new PresentationPreviewMessage()
                {
                    ProposedAttributes = proofProposal.ProposedAttributes.ToArray(),
                    ProposedPredicates = proofProposal.ProposedPredicates.ToArray()
                }
            };

            message.ThreadFrom(threadId);
            return(message, proofRecord);
        }