public override async Task InitializeAsync(object navigationData) { _connectionRecord = navigationData as ConnectionRecord; var context = await _agentContextProvider.GetContextAsync(); var credentialsRecords = await _credentialService.ListAsync(context); List <SchemaRecord> schemasList = new List <SchemaRecord>(); List <DefinitionRecord> definitionsList = new List <DefinitionRecord>(); foreach (var credentialRecord in credentialsRecords) { if (credentialRecord.State == CredentialState.Rejected) { continue; } var schemaResp = await _ledgerService.LookupSchemaAsync(context, credentialRecord.SchemaId); var schemaJobj = JObject.Parse(schemaResp?.ObjectJson ?? ""); schemasList.Add(new SchemaRecord { Id = schemaResp.Id, Name = schemaJobj.GetValue("name").ToString() }); var defResp = await _ledgerService.LookupDefinitionAsync(context, credentialRecord.CredentialDefinitionId); definitionsList.Add(new DefinitionRecord { Id = defResp.Id }); } Schemas.InsertRange(schemasList); CredDefinitions.InsertRange(definitionsList); //CredDefinitions = await _schemaService.ListCredentialDefinitionsAsync(context.Wallet); await base.InitializeAsync(navigationData); }
/// <inheritdoc /> public virtual async Task AcceptOfferAsync(IAgentContext agentContext, string credentialId, Dictionary <string, string> attributeValues = null) { var credential = await GetAsync(agentContext, credentialId); if (credential.State != CredentialState.Offered) { throw new AgentFrameworkException(ErrorCode.RecordInInvalidState, $"Credential state was invalid. Expected '{CredentialState.Offered}', found '{credential.State}'"); } var credentialCopy = credential.DeepCopy(); var connection = await ConnectionService.GetAsync(agentContext, credential.ConnectionId); var definition = await LedgerService.LookupDefinitionAsync(agentContext.Pool, credential.CredentialDefinitionId); var provisioning = await ProvisioningService.GetProvisioningAsync(agentContext.Wallet); var request = await AnonCreds.ProverCreateCredentialReqAsync(agentContext.Wallet, connection.MyDid, credential.OfferJson, definition.ObjectJson, provisioning.MasterSecretId); // Update local credential record with new info credential.CredentialRequestMetadataJson = request.CredentialRequestMetadataJson; await credential.TriggerAsync(CredentialTrigger.Request); await RecordService.UpdateAsync(agentContext.Wallet, credential); var msg = new CredentialRequestMessage { OfferJson = credential.OfferJson, CredentialRequestJson = request.CredentialRequestJson, CredentialValuesJson = CredentialUtils.FormatCredentialValues(attributeValues) }; try { await MessageService.SendAsync(agentContext.Wallet, msg, connection); } catch (Exception e) { await RecordService.UpdateAsync(agentContext.Wallet, credentialCopy); throw new AgentFrameworkException(ErrorCode.A2AMessageTransmissionError, "Failed to send credential request message", e); } }
/// <inheritdoc /> public virtual async Task AcceptOfferAsync(Wallet wallet, Pool pool, string credentialId, Dictionary <string, string> attributeValues = null) { var credential = await RecordService.GetAsync <CredentialRecord>(wallet, credentialId); var connection = await ConnectionService.GetAsync(wallet, credential.ConnectionId); var definition = await LedgerService.LookupDefinitionAsync(pool, connection.MyDid, credential.CredentialDefinitionId); var provisioning = await ProvisioningService.GetProvisioningAsync(wallet); var request = await AnonCreds.ProverCreateCredentialReqAsync(wallet, connection.MyDid, credential.OfferJson, definition.ObjectJson, provisioning.MasterSecretId); // Update local credential record with new info credential.CredentialRequestMetadataJson = request.CredentialRequestMetadataJson; var details = new CredentialRequestDetails { OfferJson = credential.OfferJson, CredentialRequestJson = request.CredentialRequestJson, CredentialValuesJson = CredentialUtils.FormatCredentialValues(attributeValues) }; var requestMessage = await MessageSerializer.PackSealedAsync <CredentialRequestMessage>(details, wallet, connection.MyVk, connection.TheirVk); requestMessage.Type = MessageUtils.FormatDidMessageType(connection.TheirDid, MessageTypes.CredentialRequest); await credential.TriggerAsync(CredentialTrigger.Request); await RecordService.UpdateAsync(wallet, credential); //TODO we need roll back, i.e if we fail to send the A2A message the credential record should revert to Offer phase //so the user can resend await RouterService.ForwardAsync(new ForwardEnvelopeMessage { Content = requestMessage.ToJson(), Type = MessageUtils.FormatDidMessageType(connection.TheirDid, MessageTypes.Forward) }, connection.Endpoint); }
private async Task <string> BuildCredentialDefinitionsAsync(Pool pool, IEnumerable <string> credentialDefIds) { var result = new Dictionary <string, JObject>(); foreach (var schemaId in credentialDefIds) { var ledgerDefinition = await LedgerService.LookupDefinitionAsync(pool, schemaId); result.Add(schemaId, JObject.Parse(ledgerDefinition.ObjectJson)); } return(result.ToJson()); }
/// <inheritdoc /> public virtual async Task <(CredentialRequestMessage, CredentialRecord)> CreateCredentialRequestAsync( IAgentContext agentContext, string offerId) { var credential = await GetAsync(agentContext, offerId); if (credential.State != CredentialState.Offered) { throw new AgentFrameworkException(ErrorCode.RecordInInvalidState, $"Credential state was invalid. Expected '{CredentialState.Offered}', found '{credential.State}'"); } var connection = await ConnectionService.GetAsync(agentContext, credential.ConnectionId); var definition = await LedgerService.LookupDefinitionAsync(await agentContext.Pool, credential.CredentialDefinitionId); var provisioning = await ProvisioningService.GetProvisioningAsync(agentContext.Wallet); var request = await AnonCreds.ProverCreateCredentialReqAsync(agentContext.Wallet, connection.MyDid, credential.OfferJson, definition.ObjectJson, provisioning.MasterSecretId); // Update local credential record with new info credential.CredentialRequestMetadataJson = request.CredentialRequestMetadataJson; await credential.TriggerAsync(CredentialTrigger.Request); await RecordService.UpdateAsync(agentContext.Wallet, credential); var threadId = credential.GetTag(TagConstants.LastThreadId); var response = new CredentialRequestMessage { CredentialRequestJson = request.CredentialRequestJson }; response.ThreadFrom(threadId); return(response, credential); }
/// TODO this should return a definition object /// <inheritdoc /> public virtual async Task <string> LookupCredentialDefinitionAsync(IAgentContext agentContext, string definitionId) { var result = await LedgerService.LookupDefinitionAsync(agentContext, definitionId); return(result?.ObjectJson); }
/// <inheritdoc /> public async Task <(CredentialRequestMessage, CredentialRecord)> CreateRequestAsync(IAgentContext agentContext, string credentialId) { var credential = await GetAsync(agentContext, credentialId); if (credential.State != CredentialState.Offered) { throw new AriesFrameworkException(ErrorCode.RecordInInvalidState, $"Credential state was invalid. Expected '{CredentialState.Offered}', found '{credential.State}'"); } string proverDid = null; if (credential.ConnectionId != null) { var connection = await ConnectionService.GetAsync(agentContext, credential.ConnectionId); proverDid = connection.MyDid; } else { var newDid = await Did.CreateAndStoreMyDidAsync(agentContext.Wallet, "{}"); proverDid = newDid.Did; } var definition = await LedgerService.LookupDefinitionAsync(agentContext, credential.CredentialDefinitionId); var provisioning = await ProvisioningService.GetProvisioningAsync(agentContext.Wallet); var request = await AnonCreds.ProverCreateCredentialReqAsync( wallet : agentContext.Wallet, proverDid : proverDid, credOfferJson : credential.OfferJson, credDefJson : definition.ObjectJson, masterSecretId : provisioning.MasterSecretId); // Update local credential record with new info credential.CredentialRequestMetadataJson = request.CredentialRequestMetadataJson; await credential.TriggerAsync(CredentialTrigger.Request); await RecordService.UpdateAsync(agentContext.Wallet, credential); var threadId = credential.GetTag(TagConstants.LastThreadId); var response = new CredentialRequestMessage(agentContext.UseMessageTypesHttps) { // The comment was required by Aca-py, even though it is declared optional in RFC-0036 // Was added for interoperability Comment = "", Requests = new[] { new Attachment { Id = "libindy-cred-request-0", MimeType = CredentialMimeTypes.ApplicationJsonMimeType, Data = new AttachmentContent { Base64 = request.CredentialRequestJson.GetUTF8Bytes().ToBase64String() } } } }; response.ThreadFrom(threadId); return(response, credential); }
/// TODO this should return a definition object /// <inheritdoc /> public virtual async Task <string> LookupCredentialDefinitionAsync(Pool pool, string definitionId) { var result = await LedgerService.LookupDefinitionAsync(pool, definitionId); return(result?.ObjectJson); }