コード例 #1
0
        /// <inheritdoc />
        public virtual async Task <string> CreateSchemaAsync(IAgentContext context, string issuerDid, string name,
                                                             string version, string[] attributeNames)
        {
            var schema = await AnonCreds.IssuerCreateSchemaAsync(issuerDid, name, version, attributeNames.ToJson());

            var schemaRecord = new SchemaRecord
            {
                Id             = schema.SchemaId,
                Name           = name,
                Version        = version,
                AttributeNames = attributeNames
            };

            var paymentInfo = await paymentService.GetTransactionCostAsync(context, TransactionTypes.SCHEMA);

            await LedgerService.RegisterSchemaAsync(context, issuerDid, schema.SchemaJson, paymentInfo);

            await RecordService.AddAsync(context.Wallet, schemaRecord);

            if (paymentInfo != null)
            {
                await RecordService.UpdateAsync(context.Wallet, paymentInfo.PaymentAddress);
            }

            return(schemaRecord.Id);
        }
コード例 #2
0
        /// <inheritdoc />
        public virtual async Task <string> ProcessProofAsync(IAgentContext agentContext, ProofMessage proof)
        {
            var proofJson = proof.ProofJson;

            var proofRecord = await this.GetByThreadIdAsync(agentContext, proof.GetThreadId());

            if (proofRecord.State != ProofState.Requested)
            {
                throw new AgentFrameworkException(ErrorCode.RecordInInvalidState,
                                                  $"Proof state was invalid. Expected '{ProofState.Requested}', found '{proofRecord.State}'");
            }

            proofRecord.ProofJson = proofJson;
            await proofRecord.TriggerAsync(ProofTrigger.Accept);

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

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

            return(proofRecord.Id);
        }
コード例 #3
0
        /// <inheritdoc />
        public virtual async Task <string> ProcessProofAsync(IAgentContext agentContext, ProofMessage proof)
        {
            var proofJson = proof.ProofJson;

            var proofRecordSearch =
                await RecordService.SearchAsync <ProofRecord>(agentContext.Wallet,
                                                              SearchQuery.Equal(TagConstants.Nonce, proof.RequestNonce), null, 1);

            var proofRecord = proofRecordSearch.FirstOrDefault() ??
                              throw new AgentFrameworkException(ErrorCode.RecordNotFound,
                                                                "Proof record not found");

            if (proofRecord.State != ProofState.Requested)
            {
                throw new AgentFrameworkException(ErrorCode.RecordInInvalidState,
                                                  $"Proof state was invalid. Expected '{ProofState.Requested}', found '{proofRecord.State}'");
            }

            proofRecord.ProofJson = proofJson;
            await proofRecord.TriggerAsync(ProofTrigger.Accept);

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

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

            return(proofRecord.Id);
        }
コード例 #4
0
        /// <inheritdoc />
        public virtual async Task <string> ProcessProofAsync(Wallet wallet, ProofMessage proof)
        {
            var(didOrKey, _) = MessageUtils.ParseMessageType(proof.Type);

            var connectionSearch =
                await ConnectionService.ListAsync(wallet, new SearchRecordQuery { { TagConstants.MyDid, didOrKey } });

            if (!connectionSearch.Any())
            {
                throw new Exception($"Can't find connection record for type {proof.Type}");
            }
            var connection = connectionSearch.First();

            var(requestDetails, _) = await MessageSerializer.UnpackSealedAsync <ProofDetails>(
                proof.Content, wallet, connection.MyVk);

            var proofJson = requestDetails.ProofJson;

            var proofRecordSearch =
                await RecordService.SearchAsync <ProofRecord>(wallet,
                                                              new SearchRecordQuery { { TagConstants.Nonce, requestDetails.RequestNonce } }, null, 1);

            if (!proofRecordSearch.Any())
            {
                throw new Exception($"Can't find proof record");
            }
            var proofRecord = proofRecordSearch.Single();

            proofRecord.ProofJson = proofJson;
            await proofRecord.TriggerAsync(ProofTrigger.Accept);

            await RecordService.UpdateAsync(wallet, proofRecord);

            return(proofRecord.GetId());
        }
コード例 #5
0
        /// <inheritdoc />
        public async Task RefreshBalanceAsync(IAgentContext agentContext, PaymentAddressRecord paymentAddress = null)
        {
            if (paymentAddress == null)
            {
                var provisioning = await provisioningService.GetProvisioningAsync(agentContext.Wallet);

                if (provisioning.DefaultPaymentAddressId == null)
                {
                    throw new AgentFrameworkException(ErrorCode.RecordNotFound, "Default PaymentAddressRecord not found");
                }

                paymentAddress = await recordService.GetAsync <PaymentAddressRecord>(agentContext.Wallet, provisioning.DefaultPaymentAddressId);
            }

            // Cache sources data in record for one hour
            var request = await IndyPayments.BuildGetPaymentSourcesAsync(agentContext.Wallet, null, paymentAddress.Address);

            var response = await Ledger.SubmitRequestAsync(await agentContext.Pool, request.Result);

            var sourcesJson = await Indy.Payments.ParseGetPaymentSourcesAsync(paymentAddress.Method, response);

            var sources = sourcesJson.ToObject <IList <IndyPaymentInputSource> >();

            paymentAddress.Sources         = sources;
            paymentAddress.SourcesSyncedAt = DateTime.Now;

            await recordService.UpdateAsync(agentContext.Wallet, paymentAddress);
        }
コード例 #6
0
        public async Task CanUpdateRecordWithTags()
        {
            var tagName  = Guid.NewGuid().ToString();
            var tagValue = Guid.NewGuid().ToString();

            var id = Guid.NewGuid().ToString();

            var record = new ConnectionRecord {
                Id = id
            };

            record.SetTag(tagName, tagValue);

            await _recordService.AddAsync(_wallet, record);

            var retrieved = await _recordService.GetAsync <ConnectionRecord>(_wallet, id);

            retrieved.MyDid = "123";
            retrieved.SetTag(tagName, "value");

            await _recordService.UpdateAsync(_wallet, retrieved);

            var updated = await _recordService.GetAsync <ConnectionRecord>(_wallet, id);

            Assert.NotNull(updated);
            Assert.Equal(updated.Id, record.Id);
            Assert.NotNull(updated.GetTag(tagName));
            Assert.Equal("value", updated.GetTag(tagName));
            Assert.Equal("123", updated.MyDid);
        }
コード例 #7
0
        public async Task SelectPictureFromGallery()
        {
            var context = await _agentContextProvider.GetContextAsync();

            await CrossMedia.Current.Initialize();

            if (!CrossMedia.Current.IsPickPhotoSupported)
            {
                await UserDialogs.Instance.AlertAsync("Not Supported", "Your device does not currently support this functionality", "Ok");

                return;
            }

            var mediaOptions = new PickMediaOptions {
                PhotoSize = PhotoSize.MaxWidthHeight, CompressionQuality = 50, MaxWidthHeight = 200
            };
            var selectedImageFile = await CrossMedia.Current.PickPhotoAsync(mediaOptions);

            //AgentImageSource = ImageSource.FromStream(() => selectedImageFile.GetStream());

            if (selectedImageFile != null)
            {
                _provisioningRecord.Owner.ImageUrl = ImageToBase64(selectedImageFile.Path);
                await _walletRecordService.UpdateAsync(context.Wallet, _provisioningRecord);

                _eventAggregator.Publish(new ApplicationEvent()
                {
                    Type = ApplicationEventType.ProvisioningRecordUpdated
                });
            }
            PopupNavigation.Instance.PopAsync();
        }
コード例 #8
0
        public async Task <bool> CreateAgentAsync(AgentOptions options)
        {
            var discovery = await _edgeClientService.DiscoverConfigurationAsync(options.EndpointUri);

            discovery.ServiceEndpoint            = options.EndpointUri;
            discovery.Invitation.ServiceEndpoint = options.EndpointUri;

#if __ANDROID__
            WalletConfiguration.WalletStorageConfiguration _storage = new WalletConfiguration.WalletStorageConfiguration {
                Path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".indy_client")
            };
            options.WalletOptions.WalletConfiguration.StorageConfiguration = _storage;
#endif
            await _provisioningService.ProvisionAgentAsync(new AgentOptions
            {
                WalletConfiguration = options.WalletConfiguration,
                WalletCredentials   = options.WalletCredentials,
                AgentKeySeed        = options.AgentKeySeed,
                EndpointUri         = options.EndpointUri,
                AgentName           = options.AgentName == null ? "Default Agent" : options.AgentName
            });

            await _keyValueStoreService.SetDataAsync(AgentOptionsKey, options);

            _options = options;

            var agentContext = await GetContextAsync();

            var provisioning = await _provisioningService.GetProvisioningAsync(agentContext.Wallet);

            // Check if connection has been established with mediator agent
            if (provisioning.GetTag("MediatorConnectionId") == null)
            {
                var(request, record) = await _connectionService.CreateRequestAsync(agentContext, discovery.Invitation);

                //await _edgeClientService.AddRouteAsync(agentContext, record.MyVk);
                var response = await _messageService.SendReceiveAsync <ConnectionResponseMessage>(agentContext.Wallet, request, record);

                await _connectionService.ProcessResponseAsync(agentContext, response, record);

                // Remove the routing key explicitly as it won't ever be needed.
                // Messages will always be sent directly with return routing enabled
                record = await _connectionService.GetAsync(agentContext, record.Id);

                record.Endpoint = new AgentEndpoint(record.Endpoint.Uri, null, null);
                await _recordService.UpdateAsync(agentContext.Wallet, record);

                provisioning.SetTag("MediatorConnectionId", record.Id);
                await _recordService.UpdateAsync(agentContext.Wallet, provisioning);
            }

            await _edgeClientService.CreateInboxAsync(agentContext);

            //await _edgeClientService.AddRouteAsync(agentContext, record.MyVk);

            return(true);
        }
コード例 #9
0
        /// <inheritdoc />
        public async Task OnMessageAsync(IAgentContext agentContext, UnpackedMessageContext messageContext)
        {
            var message          = messageContext.GetMessage <AnyAgentMessage>();
            var requestDecorator = message.FindDecorator <PaymentRequestDecorator>("payment_request");

            if (requestDecorator != null)
            {
                var record = new PaymentRecord
                {
                    ConnectionId = messageContext.Connection.Id,
                    Details      = requestDecorator.Details,
                    ReferenceId  = requestDecorator.Details.Id,
                    Address      = requestDecorator.Method.Data.PayeeId,
                    Amount       = requestDecorator.Details.Total.Amount.Value
                };
                await record.TriggerAsync(PaymentTrigger.RequestReceived);

                await _recordService.AddAsync(agentContext.Wallet, record);

                if (messageContext.ContextRecord != null)
                {
                    messageContext.ContextRecord.SetTag("PaymentRecordId", record.Id);
                    await _recordService.UpdateAsync(agentContext.Wallet, messageContext.ContextRecord);
                }
            }

            var receiptDecorator = message.FindDecorator <PaymentReceiptDecorator>("payment_receipt");

            if (receiptDecorator != null)
            {
                var search = await _recordService.SearchAsync <PaymentRecord>(
                    wallet : agentContext.Wallet,
                    query : SearchQuery.Equal(nameof(PaymentRecord.ReferenceId), receiptDecorator.RequestId),
                    options : null,
                    count : 5);

                var record = search.FirstOrDefault() ?? new PaymentRecord();
                record.ReceiptId = receiptDecorator.TransactionId;

                await record.TriggerAsync(PaymentTrigger.ReceiptReceived);

                if (search.Any())
                {
                    await _recordService.UpdateAsync(agentContext.Wallet, record);
                }
                else
                {
                    await _recordService.AddAsync(agentContext.Wallet, record);
                }
            }
        }
コード例 #10
0
        /// <inheritdoc />
        public virtual async Task RejectOfferAsync(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}'");
            }

            await credential.TriggerAsync(CredentialTrigger.Reject);

            await RecordService.UpdateAsync(agentContext.Wallet, credential);
        }
コード例 #11
0
        /// <inheritdoc />
        public async Task AcceptTxnAuthorAgreementAsync(Wallet wallet, IndyTaa txnAuthorAgreement)
        {
            var provisioning = await GetProvisioningAsync(wallet);

            provisioning.TaaAcceptance = new IndyTaaAcceptance
            {
                Digest         = GetDigest(txnAuthorAgreement),
                Text           = txnAuthorAgreement.Text,
                Version        = txnAuthorAgreement.Version,
                AcceptanceDate = DateTimeOffset.UtcNow.ToUnixTimeSeconds()
            };

            await RecordService.UpdateAsync(wallet, provisioning);
        }
コード例 #12
0
        /// <inheritdoc />
        public async Task <string> ProcessRequestAsync(IAgentContext agentContext, ConnectionRequestMessage request)
        {
            Logger.LogInformation(LoggingEvents.ProcessConnectionRequest, "Key {0}", request.Verkey);

            var my = await Did.CreateAndStoreMyDidAsync(agentContext.Wallet, "{}");

            await Did.StoreTheirDidAsync(agentContext.Wallet, new { did = request.Did, verkey = request.Verkey }.ToJson());

            agentContext.Connection.Endpoint = request.Endpoint;
            agentContext.Connection.TheirDid = request.Did;
            agentContext.Connection.TheirVk  = request.Verkey;
            agentContext.Connection.MyDid    = my.Did;
            agentContext.Connection.MyVk     = my.VerKey;

            agentContext.Connection.Alias = new ConnectionAlias
            {
                Name     = request.Name,
                ImageUrl = request.ImageUrl
            };

            if (!agentContext.Connection.MultiPartyInvitation)
            {
                await agentContext.Connection.TriggerAsync(ConnectionTrigger.InvitationAccept);

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

                EventAggregator.Publish(new ServiceMessageProcessingEvent
                {
                    RecordId    = agentContext.Connection.Id,
                    MessageType = request.Type,
                });

                return(agentContext.Connection.Id);
            }

            var newConnection = agentContext.Connection.DeepCopy();

            newConnection.Id = Guid.NewGuid().ToString();
            await newConnection.TriggerAsync(ConnectionTrigger.InvitationAccept);

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

            EventAggregator.Publish(new ServiceMessageProcessingEvent
            {
                RecordId    = newConnection.Id,
                MessageType = request.Type,
            });

            return(newConnection.Id);
        }
コード例 #13
0
        /// <inheritdoc />
        public virtual async Task RejectProofRequestAsync(IAgentContext agentContext, string proofRequestId)
        {
            var request = await GetAsync(agentContext, proofRequestId);

            if (request.State != ProofState.Requested)
            {
                throw new AriesFrameworkException(ErrorCode.RecordInInvalidState,
                                                  $"Proof record state was invalid. Expected '{ProofState.Requested}', found '{request.State}'");
            }

            await request.TriggerAsync(ProofTrigger.Reject);

            await RecordService.UpdateAsync(agentContext.Wallet, request);
        }
コード例 #14
0
        /// <inheritdoc />
        public async Task AcceptTxnAuthorAgreementAsync(IAgentContext agentContext, IndyTaa txnAuthorAgreement, string acceptanceMechanism = "service_agreement")
        {
            var provisioning = await GetProvisioningAsync(agentContext.Wallet);

            provisioning.TaaAcceptance = new IndyTaaAcceptance
            {
                Digest              = GetDigest(txnAuthorAgreement),
                Text                = txnAuthorAgreement.Text,
                Version             = txnAuthorAgreement.Version,
                AcceptanceDate      = DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
                AcceptanceMechanism = acceptanceMechanism
            };

            await RecordService.UpdateAsync(agentContext.Wallet, provisioning);
        }
コード例 #15
0
        public async Task CanUpdateRecordWithTags()
        {
            var tagName  = Guid.NewGuid().ToString();
            var tagValue = Guid.NewGuid().ToString();

            var id = Guid.NewGuid().ToString();

            var record = new ConnectionRecord {
                ConnectionId = id
            };

            record.Tags.Add(tagName, tagValue);

            await _recordService.AddAsync(_wallet, record);

            var retrieved = await _recordService.GetAsync <ConnectionRecord>(_wallet, id);

            retrieved.MyDid         = "123";
            retrieved.Tags[tagName] = "value";

            await _recordService.UpdateAsync(_wallet, retrieved);

            var updated = await _recordService.GetAsync <ConnectionRecord>(_wallet, id);

            Assert.NotNull(updated);
            Assert.Equal(updated.GetId(), record.GetId());
            Assert.True(updated.Tags.ContainsKey(tagName));
            Assert.Equal("value", updated.Tags[tagName]);
            Assert.Equal("123", updated.MyDid);
        }
        private async void CreateDefaultPaymentAddress()
        {
            try
            {
                var context = await agentProvider.GetContextAsync();

                var provisioning = await provisioningService.GetProvisioningAsync(context.Wallet);

                if (provisioning.DefaultPaymentAddressId == null)
                {
                    var address = await paymentService.CreatePaymentAddressAsync(context,
                                                                                 new AddressOptions
                    {
                        Seed   = AgentConfiguration.AddressSeed,
                        Method = TokenConfiguration.MethodName
                    });

                    provisioning.DefaultPaymentAddressId = address.Id;
                    await recordService.UpdateAsync(context.Wallet, provisioning);
                }
            }
            catch (Exception e)
            {
                logger.LogWarning(e, "Couldn't initialize default payment address");
            }
        }
コード例 #17
0
        private async void CreateDefaultPaymentAddress()
        {
            try
            {
                var context = await agentProvider.GetContextAsync();

                var provisioning = await provisioningService.GetProvisioningAsync(context.Wallet);

                if (provisioning.DefaultPaymentAddressId == null)
                {
                    if (addressOptions.Seed == null)
                    {
                        addressOptions.Seed = CryptoUtils.GetUniqueKey(32);
                    }
                    addressOptions.Method = "sov";
                    var address = await paymentService.CreatePaymentAddressAsync(context, addressOptions);

                    provisioning.DefaultPaymentAddressId = address.Id;
                    provisioning.SetTag("AddressSeed", addressOptions.Seed);
                    await recordService.UpdateAsync(context.Wallet, provisioning);
                }
            }
            catch (Exception e)
            {
                logger.LogWarning(e, "Couldn't initialize default payment address");
            }
        }
コード例 #18
0
        /// <inheritdoc />
        public virtual async Task UpdateEndpointAsync(Wallet wallet, AgentEndpoint endpoint)
        {
            var record = await GetProvisioningAsync(wallet);

            record.Endpoint = endpoint;

            await RecordService.UpdateAsync(wallet, record);
        }
コード例 #19
0
        /// <inheritdoc />
        public virtual async Task <string> ProcessChallengeResponseAsync(IAgentContext agentContext,
                                                                         EphemeralChallengeResponseMessage challengeResponse)
        {
            var threadId = challengeResponse.GetThreadId();

            //TODO improve this
            var results = await ListChallengesAsync(agentContext, new EqSubquery(TagConstants.LastThreadId, threadId));

            var record = results.FirstOrDefault();

            if (record == null)
            {
                throw new AgentFrameworkException(ErrorCode.RecordNotFound, "Challenge not found");
            }

            if (record.State != ChallengeState.Challenged)
            {
                throw new AgentFrameworkException(ErrorCode.RecordInInvalidState,
                                                  $"Challenge state was invalid. Expected '{ChallengeState.Challenged}', found '{record.State}'");
            }

            if (record.State != ChallengeState.Challenged)
            {
                throw new AgentFrameworkException(ErrorCode.RecordNotFound, "Challenge not found");
            }

            record.Response = challengeResponse.Response;

            if (challengeResponse.Status == EphemeralChallengeResponseStatus.Accepted)
            {
                var result = await ProofService.VerifyProofAsync(agentContext, record.Challenge.Contents.ToJson(),
                                                                 record.Response.Contents.ToJson());

                if (result)
                {
                    await record.TriggerAsync(ChallengeTrigger.AcceptChallenge);
                }
                else
                {
                    await record.TriggerAsync(ChallengeTrigger.InvalidChallengeResponse);
                }
            }
            else
            {
                await record.TriggerAsync(ChallengeTrigger.RejectChallenge);
            }

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

            EventAggregator.Publish(new ServiceMessageProcessingEvent
            {
                MessageType = MessageTypes.EphemeralChallenge,
                RecordId    = record.Id,
                ThreadId    = challengeResponse.GetThreadId()
            });

            return(record.Id);
        }
コード例 #20
0
        public async Task ProvisionAsync(AgentOptions options, CancellationToken cancellationToken = default)
        {
            var discovery = await edgeClientService.DiscoverConfigurationAsync(options.EndpointUri);

            try
            {
                options.AgentKey    = discovery.RoutingKey;
                options.EndpointUri = discovery.ServiceEndpoint;

                await provisioningService.ProvisionAgentAsync(options);
            }
            catch (WalletStorageException)
            {
                // OK
            }
            catch (WalletExistsException)
            {
                // OK
            }
            var agentContext = await agentProvider.GetContextAsync();

            var provisioning = await provisioningService.GetProvisioningAsync(agentContext.Wallet);

            // Check if connection has been established with mediator agent
            if (provisioning.GetTag(MediatorConnectionIdTagName) == null)
            {
                var(request, record) = await connectionService.CreateRequestAsync(agentContext, discovery.Invitation);

                var response = await messageService.SendReceiveAsync <ConnectionResponseMessage>(agentContext, request, record);

                await connectionService.ProcessResponseAsync(agentContext, response, record);

                // Remove the routing key explicitly as it won't ever be needed.
                // Messages will always be sent directly with return routing enabled
                record = await connectionService.GetAsync(agentContext, record.Id);

                record.Endpoint = new AgentEndpoint(record.Endpoint.Uri, null, null);
                await recordService.UpdateAsync(agentContext.Wallet, record);

                provisioning.SetTag(MediatorConnectionIdTagName, record.Id);
                await recordService.UpdateAsync(agentContext.Wallet, provisioning);
            }

            await edgeClientService.CreateInboxAsync(agentContext, options.MetaData);
        }
コード例 #21
0
        private async Task ScanInvite()
        {
            var expectedFormat = ZXing.BarcodeFormat.QR_CODE;

            var opts = new ZXing.Mobile.MobileBarcodeScanningOptions {
                PossibleFormats = new List <ZXing.BarcodeFormat> {
                    expectedFormat
                }
            };

            var context = await _agentContextProvider.GetContextAsync();

            var scanner = new ZXing.Mobile.MobileBarcodeScanner();

            var result = await scanner.Scan(opts);

            if (result == null)
            {
                return;
            }

            AgentMessage message = await MessageDecoder.ParseMessageAsync(result.Text);

            switch (message)
            {
            case ConnectionInvitationMessage invitation:
                break;

            case RequestPresentationMessage presentation:
                RequestPresentationMessage proofRequest = (RequestPresentationMessage)presentation;
                var         service     = message.GetDecorator <ServiceDecorator>(DecoratorNames.ServiceDecorator);
                ProofRecord proofRecord = await _proofService.ProcessRequestAsync(context, proofRequest, null);

                proofRecord.SetTag("RecipientKey", service.RecipientKeys.ToList()[0]);
                proofRecord.SetTag("ServiceEndpoint", service.ServiceEndpoint);
                await _recordService.UpdateAsync(context.Wallet, proofRecord);

                _eventAggregator.Publish(new ApplicationEvent {
                    Type = ApplicationEventType.ProofRequestUpdated
                });
                break;

            default:
                DialogService.Alert("Invalid invitation!");
                return;
            }

            Device.BeginInvokeOnMainThread(async() =>
            {
                if (message is ConnectionInvitationMessage)
                {
                    await NavigationService.NavigateToAsync <AcceptInviteViewModel>(message as ConnectionInvitationMessage, NavigationType.Modal);
                }
            });
        }
コード例 #22
0
        /// <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);
            }
        }
コード例 #23
0
        /// <inheritdoc />
        public async Task <string> ProcessRequestAsync(Wallet wallet, ConnectionRequestMessage request)
        {
            Logger.LogInformation(LoggingEvents.StoreConnectionRequest, "Key {0}", request.Key);

            var(didOrKey, _) = MessageUtils.ParseMessageType(request.Type);

            var connectionSearch = await RecordService.SearchAsync <ConnectionRecord>(wallet,
                                                                                      new SearchRecordQuery { { TagConstants.ConnectionKey, didOrKey } }, null, 1);

            var connection = connectionSearch.Single();

            var(their, theirKey) =
                await MessageSerializer.UnpackSealedAsync <ConnectionDetails>(request.Content, wallet, request.Key);

            if (!their.Verkey.Equals(theirKey))
            {
                throw new ArgumentException("Signed and enclosed keys don't match");
            }

            await connection.TriggerAsync(ConnectionTrigger.InvitationAccept);

            var my = await Did.CreateAndStoreMyDidAsync(wallet, "{}");

            await Did.StoreTheirDidAsync(wallet, new { did = their.Did, verkey = their.Verkey }.ToJson());

            connection.Endpoint = their.Endpoint;
            connection.TheirDid = their.Did;
            connection.TheirVk  = their.Verkey;
            connection.MyDid    = my.Did;
            connection.MyVk     = my.VerKey;
            connection.Tags[TagConstants.MyDid]    = my.Did;
            connection.Tags[TagConstants.TheirDid] = their.Did;

            await RecordService.UpdateAsync(wallet, connection);

            if (connection.Tags.Any(_ => _.Key == TagConstants.AutoAcceptConnection && _.Value == "true"))
            {
                await AcceptRequestAsync(wallet, connection.ConnectionId);
            }

            return(connection.GetId());
        }
コード例 #24
0
        /// <inheritdoc/>
        public async Task <(DidExchangeResponseMessage, ConnectionRecord)> CreateResponseAsync(IAgentContext agentContext, ConnectionRecord connectionRecord)
        {
            await connectionRecord.TriggerAsync(ConnectionTrigger.Response);

            var myDid = await Did.CreateAndStoreMyDidAsync(agentContext.Wallet, "{}");

            connectionRecord.MyDid = DidUtils.ConvertVerkeyToDidKey(myDid.VerKey);
            connectionRecord.MyVk  = myDid.VerKey;

            var provisioningRecord = await _provisioningService.GetProvisioningAsync(agentContext.Wallet);

            var didDoc = new AttachmentContent
            {
                Base64 = connectionRecord.MyDidDoc(provisioningRecord).ToJson().ToBase64Url()
            };
            await didDoc.SignWithJsonWebSignature(agentContext.Wallet, myDid.VerKey);

            var attachment = new Attachment
            {
                Id       = Guid.NewGuid().ToString(),
                MimeType = "application/json",
                Data     = didDoc
            };

            var response = new DidExchangeResponseMessage
            {
                Id     = Guid.NewGuid().ToString(),
                Did    = connectionRecord.MyDid,
                DidDoc = attachment
            };
            await _recordService.UpdateAsync(agentContext.Wallet, connectionRecord);

            return(response, connectionRecord);
        }
コード例 #25
0
        private async Task UpdateAgentName()
        {
            var context = await _agentContextProvider.GetContextAsync();

            _provisioningRecord.Owner.Name = AgentName;
            await _walletRecordService.UpdateAsync(context.Wallet, _provisioningRecord);

            _eventAggregator.Publish(new ApplicationEvent()
            {
                Type = ApplicationEventType.ProvisioningRecordUpdated
            });
            await PopupNavigation.Instance.PopAsync(true);
        }
コード例 #26
0
        private async Task <CreateInboxResponseMessage> CreateInboxAsync(IAgentContext agentContext, ConnectionRecord connection, CreateInboxMessage createInboxMessage)
        {
            if (connection.State != ConnectionState.Connected)
            {
                throw new InvalidOperationException("Can't create inbox if connection is not in final state");
            }

            string inboxId  = $"Edge{Guid.NewGuid().ToString("N")}";
            string inboxKey = await Wallet.GenerateWalletKeyAsync(IndySdkDefaultOptions);

            var inboxRecord = new InboxRecord
            {
                Id = inboxId,
                WalletConfiguration = new WalletConfiguration
                {
                    Id                   = inboxId,
                    StorageType          = options.WalletConfiguration?.StorageType ?? "default",
                    StorageConfiguration = options.WalletConfiguration?.StorageConfiguration
                },
                WalletCredentials = new WalletCredentials
                {
                    Key = inboxKey,
                    KeyDerivationMethod = options.WalletCredentials?.KeyDerivationMethod,
                    StorageCredentials  = options.WalletCredentials?.StorageCredentials
                }
            };

            connection.SetTag("InboxId", inboxId);

            await walletService.CreateWalletAsync(
                configuration : inboxRecord.WalletConfiguration,
                credentials : inboxRecord.WalletCredentials);

            if (createInboxMessage.Metadata != null)
            {
                foreach (var metadata in createInboxMessage.Metadata)
                {
                    inboxRecord.SetTag(metadata.Key, metadata.Value);
                }
            }

            await recordService.AddAsync(agentContext.Wallet, inboxRecord);

            await recordService.UpdateAsync(agentContext.Wallet, connection);

            return(new CreateInboxResponseMessage
            {
                InboxId = inboxId,
                InboxKey = inboxKey
            });
        }
コード例 #27
0
        public async Task StartAsync(CancellationToken cancellationToken)
        {
            try
            {
                await provisioningService.ProvisionAgentAsync();
            }
            catch (WalletStorageException)
            {
                // OK
            }
            catch (WalletExistsException)
            {
                // OK
            }

            var agentContext = await agentProvider.GetContextAsync();

            var provsioningRecord = await provisioningService.GetProvisioningAsync(agentContext.Wallet);

            if (provsioningRecord.GetTag(EdgeInvitationTagName) != null)
            {
                return;
            }

            var(invitation, record) = await connectionService.CreateInvitationAsync(
                agentContext : agentContext,
                config : new InviteConfiguration {
                MultiPartyInvitation = true, AutoAcceptConnection = true
            });

            invitation.RoutingKeys = null;

            record.SetTag(InvitationTagName, invitation.ToJson());
            provsioningRecord.SetTag(EdgeInvitationTagName, record.Id);
            await recordService.UpdateAsync(agentContext.Wallet, provsioningRecord);

            await recordService.UpdateAsync(agentContext.Wallet, record);
        }
コード例 #28
0
        /// <inheritdoc />
        public async Task <(ConnectionRequestMessage, ConnectionRecord)> CreateRequestAsync(IAgentContext agentContext, ConnectionRecord connection)
        {
            Logger.LogInformation(LoggingEvents.AcceptInvitation, "Key {0}, Endpoint {1}",
                                  connection.Endpoint.Verkey, connection.Endpoint.Uri);

            await connection.TriggerAsync(ConnectionTrigger.Request);

            var provisioning = await ProvisioningService.GetProvisioningAsync(agentContext.Wallet);

            var request = new ConnectionRequestMessage(agentContext.UseMessageTypesHttps)
            {
                Connection = new Common.Connection
                {
                    Did    = connection.MyDid,
                    DidDoc = connection.MyDidDoc(provisioning)
                },
                Label    = provisioning.Owner?.Name,
                ImageUrl = provisioning.Owner?.ImageUrl
            };

            // also set image as attachment
            if (provisioning.Owner?.ImageUrl != null)
            {
                request.AddAttachment(new Attachment
                {
                    Nickname = "profile-image",
                    Data     = new AttachmentContent {
                        Links = new[] { provisioning.Owner.ImageUrl }
                    }
                });
            }

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

            return(request, connection);
        }
コード例 #29
0
        /// <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);
        }
コード例 #30
0
        public async Task CreateInboxAsync(IAgentContext agentContext, Dictionary <string, string> metadata = null)
        {
            var provisioning = await provisioningService.GetProvisioningAsync(agentContext.Wallet);

            if (provisioning.GetTag(MediatorInboxIdTagName) != null)
            {
                return;
            }
            var connection = await GetMediatorConnectionAsync(agentContext);

            var createInboxMessage = new CreateInboxMessage {
                Metadata = metadata
            };
            var response = await messageService.SendReceiveAsync <CreateInboxResponseMessage>(agentContext.Wallet, createInboxMessage, connection);

            provisioning.SetTag(MediatorInboxIdTagName, response.InboxId);
            provisioning.SetTag(MediatorInboxKeyTagName, response.InboxKey);
            await recordService.UpdateAsync(agentContext.Wallet, provisioning);
        }