using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Threading.Tasks; using BTCPayServer.Controllers; using BTCPayServer.Data; using BTCPayServer.Models; using BTCPayServer.Models.StoreViewModels; using BTCPayServer.Payments.Changelly; using BTCPayServer.Payments.Changelly.Models; using BTCPayServer.Services.Rates; using BTCPayServer.Services.Stores; using BTCPayServer.Tests.Logging; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Xunit; using Xunit.Abstractions; namespace BTCPayServer.Tests { public class ChangellyTests { public const int TestTimeout = 60_000; public ChangellyTests(ITestOutputHelper helper) { Logs.Tester = new XUnitLog(helper) {Name = "Tests"}; Logs.LogProvider = new XUnitLogProvider(helper); } [Fact(Timeout = TestTimeout)] [Trait("Integration", "Integration")] public async void CanSetChangellyPaymentMethod() { using (var tester = ServerTester.Create()) { await tester.StartAsync(); var user = tester.NewAccount(); user.GrantAccess(); var controller = tester.PayTester.GetController(user.UserId, user.StoreId); var storeBlob = controller.CurrentStore.GetStoreBlob(); Assert.Null(storeBlob.ChangellySettings); var updateModel = new UpdateChangellySettingsViewModel() { ApiSecret = "secret", ApiKey = "key", ApiUrl = "http://gozo.com", ChangellyMerchantId = "aaa", }; Assert.Equal("UpdateStore", Assert.IsType( await controller.UpdateChangellySettings(user.StoreId, updateModel, "save")).ActionName); var store = await tester.PayTester.StoreRepository.FindStore(user.StoreId); storeBlob = controller.CurrentStore.GetStoreBlob(); Assert.NotNull(storeBlob.ChangellySettings); Assert.NotNull(storeBlob.ChangellySettings); Assert.IsType(storeBlob.ChangellySettings); Assert.Equal(storeBlob.ChangellySettings.ApiKey, updateModel.ApiKey); Assert.Equal(storeBlob.ChangellySettings.ApiSecret, updateModel.ApiSecret); Assert.Equal(storeBlob.ChangellySettings.ApiUrl, updateModel.ApiUrl); Assert.Equal(storeBlob.ChangellySettings.ChangellyMerchantId, updateModel.ChangellyMerchantId); } } [Fact(Timeout = TestTimeout)] [Trait("Integration", "Integration")] public async Task CanToggleChangellyPaymentMethod() { using (var tester = ServerTester.Create()) { await tester.StartAsync(); var user = tester.NewAccount(); user.GrantAccess(); var controller = tester.PayTester.GetController(user.UserId, user.StoreId); var updateModel = new UpdateChangellySettingsViewModel() { ApiSecret = "secret", ApiKey = "key", ApiUrl = "http://gozo.com", ChangellyMerchantId = "aaa", Enabled = true }; Assert.Equal("UpdateStore", Assert.IsType( await controller.UpdateChangellySettings(user.StoreId, updateModel, "save")).ActionName); var store = await tester.PayTester.StoreRepository.FindStore(user.StoreId); Assert.True(store.GetStoreBlob().ChangellySettings.Enabled); updateModel.Enabled = false; Assert.Equal("UpdateStore", Assert.IsType( await controller.UpdateChangellySettings(user.StoreId, updateModel, "save")).ActionName); store = await tester.PayTester.StoreRepository.FindStore(user.StoreId); Assert.False(store.GetStoreBlob().ChangellySettings.Enabled); } } [Fact(Timeout = TestTimeout)] [Trait("Integration", "Integration")] public async void CannotUseChangellyApiWithoutChangellyPaymentMethodSet() { using (var tester = ServerTester.Create()) { await tester.StartAsync(); var user = tester.NewAccount(); user.GrantAccess(); var changellyController = tester.PayTester.GetController(user.UserId, user.StoreId); changellyController.IsTest = true; //test non existing payment method Assert.IsType(Assert .IsType(await changellyController.GetCurrencyList(user.StoreId)) .Value); var updateModel = CreateDefaultChangellyParams(false); var storesController = tester.PayTester.GetController(user.UserId, user.StoreId); //set payment method but disabled Assert.Equal("UpdateStore", Assert.IsType( await storesController.UpdateChangellySettings(user.StoreId, updateModel, "save")).ActionName); Assert.IsType(Assert .IsType(await changellyController.GetCurrencyList(user.StoreId)) .Value); updateModel.Enabled = true; //test with enabled method Assert.Equal("UpdateStore", Assert.IsType( await storesController.UpdateChangellySettings(user.StoreId, updateModel, "save")).ActionName); Assert.IsNotType(Assert .IsType(await changellyController.GetCurrencyList(user.StoreId)) .Value); } } UpdateChangellySettingsViewModel CreateDefaultChangellyParams(bool enabled) { return new UpdateChangellySettingsViewModel() { ApiKey = "6ed02cdf1b614d89a8c0ceb170eebb61", ApiSecret = "8fbd66a2af5fd15a6b5f8ed0159c5842e32a18538521ffa145bd6c9e124d3483", ChangellyMerchantId = "804298eb5753", Enabled = enabled }; } [Fact(Timeout = TestTimeout)] [Trait("Integration", "Integration")] public async void CanGetCurrencyListFromChangelly() { using (var tester = ServerTester.Create()) { await tester.StartAsync(); var user = tester.NewAccount(); user.GrantAccess(); //save changelly settings var updateModel = CreateDefaultChangellyParams(true); var storesController = tester.PayTester.GetController(user.UserId, user.StoreId); //confirm saved Assert.Equal("UpdateStore", Assert.IsType( await storesController.UpdateChangellySettings(user.StoreId, updateModel, "save")).ActionName); var factory = UnitTest1.CreateBTCPayRateFactory(); var fetcher = new RateFetcher(factory); var httpClientFactory = new MockHttpClientFactory(); var changellyController = new ChangellyController( new ChangellyClientProvider(tester.PayTester.StoreRepository, httpClientFactory), tester.NetworkProvider, fetcher); changellyController.IsTest = true; var result = Assert .IsType(await changellyController.GetCurrencyList(user.StoreId)) .Value as IEnumerable; Assert.True(result.Any()); } } [Fact(Timeout = TestTimeout)] [Trait("Integration", "Integration")] public async void CanCalculateToAmountForChangelly() { using (var tester = ServerTester.Create()) { await tester.StartAsync(); var user = tester.NewAccount(); user.GrantAccess(); var updateModel = CreateDefaultChangellyParams(true); var storesController = tester.PayTester.GetController(user.UserId, user.StoreId); Assert.Equal("UpdateStore", Assert.IsType( await storesController.UpdateChangellySettings(user.StoreId, updateModel, "save")).ActionName); var factory = UnitTest1.CreateBTCPayRateFactory(); var fetcher = new RateFetcher(factory); var httpClientFactory = new MockHttpClientFactory(); var changellyController = new ChangellyController( new ChangellyClientProvider(tester.PayTester.StoreRepository, httpClientFactory), tester.NetworkProvider, fetcher); changellyController.IsTest = true; Assert.IsType(Assert .IsType(await changellyController.CalculateAmount(user.StoreId, "ltc", "btc", 1.0m, default)) .Value); } } [Fact] [Trait("Fast", "Fast")] public void CanComputeBaseAmount() { Assert.Equal(1, ChangellyCalculationHelper.ComputeBaseAmount(1, 1)); Assert.Equal(0.5m, ChangellyCalculationHelper.ComputeBaseAmount(1, 0.5m)); Assert.Equal(2, ChangellyCalculationHelper.ComputeBaseAmount(0.5m, 1)); Assert.Equal(4m, ChangellyCalculationHelper.ComputeBaseAmount(1, 4)); } [Fact] [Trait("Fast", "Fast")] public void CanComputeCorrectAmount() { Assert.Equal(1, ChangellyCalculationHelper.ComputeCorrectAmount(0.5m, 1, 2)); Assert.Equal(0.25m, ChangellyCalculationHelper.ComputeCorrectAmount(0.5m, 1, 0.5m)); Assert.Equal(20, ChangellyCalculationHelper.ComputeCorrectAmount(10, 1, 2)); } } public class MockHttpClientFactory : IHttpClientFactory { public HttpClient CreateClient(string name) { return new HttpClient(); } } }