mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-02-20 13:34:37 +01:00
Introduce Additional Data to Store Blob and move obsolete props to migration (#2065)
* Introduce Additional Data to Store Blob and move obsolete props to migration * Fixes and tests * Small adjustements to prevent tracking too many objects Co-authored-by: nicolas.dorier <nicolas.dorier@gmail.com>
This commit is contained in:
parent
5803512820
commit
ae32fdeea7
8 changed files with 262 additions and 153 deletions
|
@ -11,6 +11,7 @@ using System.Text;
|
|||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Abstractions.Contracts;
|
||||
using BTCPayServer.Abstractions.Models;
|
||||
using BTCPayServer.Client;
|
||||
using BTCPayServer.Client.Models;
|
||||
|
@ -19,6 +20,7 @@ using BTCPayServer.Controllers;
|
|||
using BTCPayServer.Data;
|
||||
using BTCPayServer.Events;
|
||||
using BTCPayServer.HostedServices;
|
||||
using BTCPayServer.Hosting;
|
||||
using BTCPayServer.Lightning;
|
||||
using BTCPayServer.Models;
|
||||
using BTCPayServer.Models.AccountViewModels;
|
||||
|
@ -45,10 +47,12 @@ using DBriize.Utils;
|
|||
using ExchangeSharp;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using NBitcoin;
|
||||
using NBitcoin.DataEncoders;
|
||||
using NBitcoin.Payment;
|
||||
using NBitpayClient;
|
||||
using NBXplorer;
|
||||
using NBXplorer.DerivationStrategy;
|
||||
using NBXplorer.Models;
|
||||
using Newtonsoft.Json;
|
||||
|
@ -2118,21 +2122,6 @@ namespace BTCPayServer.Tests
|
|||
|
||||
Assert.Single(invoice.CryptoInfo);
|
||||
Assert.Equal(PaymentTypes.BTCLike.ToString(), invoice.CryptoInfo[0].PaymentType);
|
||||
|
||||
//test backward compat
|
||||
var store = await tester.PayTester.StoreRepository.FindStore(user.StoreId);
|
||||
var blob = store.GetStoreBlob();
|
||||
blob.PaymentMethodCriteria = new List<PaymentMethodCriteria>();
|
||||
#pragma warning disable 612
|
||||
blob.OnChainMinValue = new CurrencyValue()
|
||||
#pragma warning restore 612
|
||||
{
|
||||
Currency = "USD",
|
||||
Value = 2m
|
||||
};
|
||||
var criteriaCompat = store.GetPaymentMethodCriteria(tester.NetworkProvider, blob);
|
||||
Assert.Single(criteriaCompat);
|
||||
Assert.NotNull(criteriaCompat.FirstOrDefault(methodCriteria => methodCriteria.Value.ToString() == "2 USD" && methodCriteria.Above && methodCriteria.PaymentMethod == new PaymentMethodId("BTC", BitcoinPaymentType.Instance)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2229,22 +2218,6 @@ namespace BTCPayServer.Tests
|
|||
|
||||
Assert.Single(invoice.CryptoInfo);
|
||||
Assert.Equal(PaymentTypes.LightningLike.ToString(), invoice.CryptoInfo[0].PaymentType);
|
||||
|
||||
//test backward compat
|
||||
var store = await tester.PayTester.StoreRepository.FindStore(user.StoreId);
|
||||
var blob = store.GetStoreBlob();
|
||||
blob.PaymentMethodCriteria = new List<PaymentMethodCriteria>();
|
||||
#pragma warning disable 612
|
||||
blob.LightningMaxValue = new CurrencyValue()
|
||||
#pragma warning restore 612
|
||||
{
|
||||
Currency = "USD",
|
||||
Value = 2m
|
||||
};
|
||||
var criteriaCompat = store.GetPaymentMethodCriteria(tester.NetworkProvider, blob);
|
||||
Assert.Single(criteriaCompat);
|
||||
Assert.NotNull(criteriaCompat.FirstOrDefault(methodCriteria => methodCriteria.Value.ToString() == "2 USD" && !methodCriteria.Above && methodCriteria.PaymentMethod == new PaymentMethodId("BTC", LightningPaymentType.Instance)));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3437,6 +3410,83 @@ namespace BTCPayServer.Tests
|
|||
}
|
||||
}
|
||||
|
||||
[Fact(Timeout = TestTimeout)]
|
||||
[Trait("Integration", "Integration")]
|
||||
public async Task CanDoInvoiceMigrations()
|
||||
{
|
||||
using (var tester = ServerTester.Create(newDb: true))
|
||||
{
|
||||
await tester.StartAsync();
|
||||
|
||||
var acc = tester.NewAccount();
|
||||
await acc.GrantAccessAsync(true);
|
||||
await acc.CreateStoreAsync();
|
||||
await acc.RegisterDerivationSchemeAsync("BTC");
|
||||
var store = await tester.PayTester.StoreRepository.FindStore(acc.StoreId);
|
||||
|
||||
var blob = store.GetStoreBlob();
|
||||
var serializer = new Serializer(null);
|
||||
|
||||
blob.AdditionalData = new Dictionary<string, JToken>();
|
||||
blob.AdditionalData.Add("rateRules", JToken.Parse(
|
||||
serializer.ToString(new List<MigrationStartupTask.RateRule_Obsolete>()
|
||||
{
|
||||
new MigrationStartupTask.RateRule_Obsolete()
|
||||
{
|
||||
Multiplier = 2
|
||||
}
|
||||
})));
|
||||
blob.AdditionalData.Add("walletKeyPathRoots", JToken.Parse(
|
||||
serializer.ToString(new Dictionary<string, string>()
|
||||
{
|
||||
{
|
||||
new PaymentMethodId("BTC", BitcoinPaymentType.Instance).ToString(),
|
||||
new KeyPath("44'/0'/0'").ToString()
|
||||
}
|
||||
})));
|
||||
|
||||
blob.AdditionalData.Add("networkFeeDisabled", JToken.Parse(
|
||||
serializer.ToString((bool?)true)));
|
||||
|
||||
blob.AdditionalData.Add("onChainMinValue", JToken.Parse(
|
||||
serializer.ToString(new CurrencyValue()
|
||||
{
|
||||
Currency = "USD",
|
||||
Value = 5m
|
||||
}.ToString())));
|
||||
blob.AdditionalData.Add("lightningMaxValue", JToken.Parse(
|
||||
serializer.ToString(new CurrencyValue()
|
||||
{
|
||||
Currency = "USD",
|
||||
Value = 5m
|
||||
}.ToString())));
|
||||
|
||||
store.SetStoreBlob(blob);
|
||||
await tester.PayTester.StoreRepository.UpdateStore(store);
|
||||
var settings = tester.PayTester.GetService<SettingsRepository>();
|
||||
await settings.UpdateSetting<MigrationSettings>(new MigrationSettings());
|
||||
var migrationStartupTask = tester.PayTester.GetService<IServiceProvider>().GetServices<IStartupTask>()
|
||||
.Single(task => task is MigrationStartupTask);
|
||||
await migrationStartupTask.ExecuteAsync();
|
||||
|
||||
|
||||
store = await tester.PayTester.StoreRepository.FindStore(acc.StoreId);
|
||||
|
||||
blob = store.GetStoreBlob();
|
||||
Assert.Empty(blob.AdditionalData);
|
||||
Assert.Single(blob.PaymentMethodCriteria);
|
||||
Assert.Contains(blob.PaymentMethodCriteria,
|
||||
criteria => criteria.PaymentMethod == new PaymentMethodId("BTC", BitcoinPaymentType.Instance) &&
|
||||
criteria.Above && criteria.Value.Value == 5m && criteria.Value.Currency == "USD");
|
||||
Assert.Equal(NetworkFeeMode.Never, blob.NetworkFeeMode);
|
||||
Assert.Contains(store.GetSupportedPaymentMethods(tester.NetworkProvider), method =>
|
||||
method is DerivationSchemeSettings dss &&
|
||||
method.PaymentId == new PaymentMethodId("BTC", BitcoinPaymentType.Instance) &&
|
||||
dss.AccountKeyPath == new KeyPath("44'/0'/0'"));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
[Fact(Timeout = TestTimeout)]
|
||||
[Trait("Integration", "Integration")]
|
||||
public async Task EmailSenderTests()
|
||||
|
|
|
@ -217,7 +217,7 @@ namespace BTCPayServer.Controllers
|
|||
.Where(c => c != null))
|
||||
{
|
||||
currencyPairsToFetch.Add(new CurrencyPair(network.CryptoCode, entity.Currency));
|
||||
foreach (var paymentMethodCriteria in store.GetPaymentMethodCriteria(_NetworkProvider, storeBlob))
|
||||
foreach (var paymentMethodCriteria in storeBlob.PaymentMethodCriteria)
|
||||
{
|
||||
if (paymentMethodCriteria.Value != null)
|
||||
{
|
||||
|
@ -341,7 +341,7 @@ namespace BTCPayServer.Controllers
|
|||
paymentMethod.SetPaymentMethodDetails(paymentDetails);
|
||||
}
|
||||
|
||||
var criteria = store.GetPaymentMethodCriteria(_NetworkProvider, storeBlob)?.Find(methodCriteria => methodCriteria.PaymentMethod == supportedPaymentMethod.PaymentId);
|
||||
var criteria = storeBlob.PaymentMethodCriteria?.Find(methodCriteria => methodCriteria.PaymentMethod == supportedPaymentMethod.PaymentId);
|
||||
if (criteria?.Value != null)
|
||||
{
|
||||
var currentRateToCrypto =
|
||||
|
|
|
@ -372,15 +372,31 @@ namespace BTCPayServer.Controllers
|
|||
var storeBlob = CurrentStore.GetStoreBlob();
|
||||
var vm = new CheckoutExperienceViewModel();
|
||||
SetCryptoCurrencies(vm, CurrentStore);
|
||||
vm.PaymentMethodCriteria =
|
||||
CurrentStore.GetPaymentMethodCriteria(_NetworkProvider, storeBlob).Select(criteria =>
|
||||
new PaymentMethodCriteriaViewModel()
|
||||
vm.PaymentMethodCriteria = CurrentStore.GetSupportedPaymentMethods(_NetworkProvider).Select(method =>
|
||||
{
|
||||
var existing =
|
||||
storeBlob.PaymentMethodCriteria.SingleOrDefault(criteria =>
|
||||
criteria.PaymentMethod == method.PaymentId);
|
||||
if (existing is null)
|
||||
{
|
||||
return new PaymentMethodCriteriaViewModel()
|
||||
{
|
||||
PaymentMethod = criteria.PaymentMethod.ToString(),
|
||||
Type = criteria.Above ? PaymentMethodCriteriaViewModel.CriteriaType.GreaterThan : PaymentMethodCriteriaViewModel.CriteriaType.LessThan,
|
||||
Value = criteria.Value?.ToString() ?? ""
|
||||
}).ToList();
|
||||
|
||||
PaymentMethod = method.PaymentId.ToString(),
|
||||
Value = ""
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
return new PaymentMethodCriteriaViewModel()
|
||||
{
|
||||
PaymentMethod = existing.PaymentMethod.ToString(),
|
||||
Type = existing.Above
|
||||
? PaymentMethodCriteriaViewModel.CriteriaType.GreaterThan
|
||||
: PaymentMethodCriteriaViewModel.CriteriaType.LessThan,
|
||||
Value = existing.Value?.ToString() ?? ""
|
||||
};
|
||||
}
|
||||
}).ToList();
|
||||
vm.RequiresRefundEmail = storeBlob.RequiresRefundEmail;
|
||||
vm.LightningAmountInSatoshi = storeBlob.LightningAmountInSatoshi;
|
||||
vm.LightningPrivateRouteHints = storeBlob.LightningPrivateRouteHints;
|
||||
|
@ -454,10 +470,6 @@ namespace BTCPayServer.Controllers
|
|||
CurrencyValue.TryParse(viewModel.Value, out var cv);
|
||||
return new PaymentMethodCriteria() { Above = viewModel.Type == PaymentMethodCriteriaViewModel.CriteriaType.GreaterThan, Value = cv, PaymentMethod = PaymentMethodId.Parse(viewModel.PaymentMethod) };
|
||||
}).ToList();
|
||||
#pragma warning disable 612
|
||||
blob.LightningMaxValue = null;
|
||||
blob.OnChainMinValue = null;
|
||||
#pragma warning restore 612
|
||||
|
||||
blob.RequiresRefundEmail = model.RequiresRefundEmail;
|
||||
blob.LightningAmountInSatoshi = model.LightningAmountInSatoshi;
|
||||
|
|
|
@ -11,6 +11,10 @@ namespace BTCPayServer
|
|||
public static bool TryParse(string str, out CurrencyValue value)
|
||||
{
|
||||
value = null;
|
||||
if (string.IsNullOrEmpty(str))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var match = _Regex.Match(str);
|
||||
if (!match.Success ||
|
||||
!decimal.TryParse(match.Groups[1].Value, out var v))
|
||||
|
|
|
@ -13,6 +13,7 @@ using BTCPayServer.Services.Mails;
|
|||
using BTCPayServer.Services.Rates;
|
||||
using BTCPayServer.Services.Shopify.Models;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace BTCPayServer.Data
|
||||
{
|
||||
|
@ -25,14 +26,11 @@ namespace BTCPayServer.Data
|
|||
PaymentTolerance = 0;
|
||||
ShowRecommendedFee = true;
|
||||
RecommendedFeeBlockTarget = 1;
|
||||
PaymentMethodCriteria = new List<PaymentMethodCriteria>();
|
||||
}
|
||||
|
||||
public ShopifySettings Shopify { get; set; }
|
||||
|
||||
[Obsolete("Use NetworkFeeMode instead")]
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public bool? NetworkFeeDisabled { get; set; }
|
||||
|
||||
[JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
|
||||
public NetworkFeeMode NetworkFeeMode { get; set; }
|
||||
|
||||
|
@ -80,24 +78,9 @@ namespace BTCPayServer.Data
|
|||
|
||||
public decimal Spread { get; set; } = 0.0m;
|
||||
|
||||
[Obsolete]
|
||||
public List<RateRule_Obsolete> RateRules { get; set; } = new List<RateRule_Obsolete>();
|
||||
public string PreferredExchange { get; set; }
|
||||
|
||||
public List<PaymentMethodCriteria> PaymentMethodCriteria
|
||||
{
|
||||
[Obsolete("Use GetPaymentMethodCriteria instead")]
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Obsolete]
|
||||
[JsonConverter(typeof(CurrencyValueJsonConverter))]
|
||||
public CurrencyValue OnChainMinValue { get; set; }
|
||||
[Obsolete]
|
||||
[JsonConverter(typeof(CurrencyValueJsonConverter))]
|
||||
public CurrencyValue LightningMaxValue { get; set; }
|
||||
|
||||
public List<PaymentMethodCriteria> PaymentMethodCriteria { get; set; }
|
||||
public string CustomCSS { get; set; }
|
||||
public string CustomLogo { get; set; }
|
||||
public string HtmlTitle { get; set; }
|
||||
|
@ -170,14 +153,14 @@ namespace BTCPayServer.Data
|
|||
[Obsolete("Use GetExcludedPaymentMethods instead")]
|
||||
public string[] ExcludedPaymentMethods { get; set; }
|
||||
|
||||
[Obsolete("Use DerivationSchemeSettings instead")]
|
||||
public Dictionary<string, string> WalletKeyPathRoots { get; set; }
|
||||
|
||||
public EmailSettings EmailSettings { get; set; }
|
||||
public bool PayJoinEnabled { get; set; }
|
||||
|
||||
public StoreHints Hints { get; set; }
|
||||
|
||||
[JsonExtensionData]
|
||||
public IDictionary<string, JToken> AdditionalData { get; set; } = new Dictionary<string, JToken>();
|
||||
|
||||
public class StoreHints
|
||||
{
|
||||
public bool Wallet { get; set; }
|
||||
|
@ -218,20 +201,4 @@ namespace BTCPayServer.Data
|
|||
public CurrencyValue Value { get; set; }
|
||||
public bool Above { get; set; }
|
||||
}
|
||||
|
||||
public class RateRule_Obsolete
|
||||
{
|
||||
public RateRule_Obsolete()
|
||||
{
|
||||
RuleName = "Multiplier";
|
||||
}
|
||||
public string RuleName { get; set; }
|
||||
|
||||
public double Multiplier { get; set; }
|
||||
|
||||
public decimal Apply(BTCPayNetworkBase network, decimal rate)
|
||||
{
|
||||
return rate * (decimal)Multiplier;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,46 +52,6 @@ namespace BTCPayServer.Data
|
|||
return result;
|
||||
}
|
||||
|
||||
public static List<PaymentMethodCriteria> GetPaymentMethodCriteria(this StoreData storeData, BTCPayNetworkProvider networkProvider,StoreBlob storeBlob = null)
|
||||
{
|
||||
#pragma warning disable 612
|
||||
storeBlob ??= storeData.GetStoreBlob();
|
||||
|
||||
return storeData.GetEnabledPaymentIds(networkProvider).Select(paymentMethodId=>
|
||||
{
|
||||
var matchedFromBlob =
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
storeBlob.PaymentMethodCriteria?.SingleOrDefault(criteria => criteria.PaymentMethod == paymentMethodId && criteria.Value != null);
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
if (matchedFromBlob is null && paymentMethodId.PaymentType == LightningPaymentType.Instance && storeBlob.LightningMaxValue != null)
|
||||
{
|
||||
return new PaymentMethodCriteria()
|
||||
{
|
||||
Above = false,
|
||||
PaymentMethod = paymentMethodId,
|
||||
Value = storeBlob.LightningMaxValue
|
||||
};
|
||||
}
|
||||
if (matchedFromBlob is null && paymentMethodId.PaymentType == BitcoinPaymentType.Instance && storeBlob.OnChainMinValue != null)
|
||||
{
|
||||
return new PaymentMethodCriteria()
|
||||
{
|
||||
Above = true,
|
||||
PaymentMethod = paymentMethodId,
|
||||
Value = storeBlob.OnChainMinValue
|
||||
};
|
||||
}
|
||||
|
||||
return new PaymentMethodCriteria()
|
||||
{
|
||||
PaymentMethod = paymentMethodId,
|
||||
Above = matchedFromBlob?.Above??true,
|
||||
Value = matchedFromBlob?.Value
|
||||
};
|
||||
}).ToList();
|
||||
#pragma warning restore 612
|
||||
}
|
||||
|
||||
public static bool SetStoreBlob(this StoreData storeData, StoreBlob storeBlob)
|
||||
{
|
||||
var original = new Serializer(null).ToString(storeData.GetStoreBlob());
|
||||
|
|
|
@ -10,6 +10,7 @@ using BTCPayServer.Client.Models;
|
|||
using BTCPayServer.Configuration;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.Logging;
|
||||
using BTCPayServer.Payments;
|
||||
using BTCPayServer.Services;
|
||||
using BTCPayServer.Services.Stores;
|
||||
using DBriize;
|
||||
|
@ -18,6 +19,8 @@ using Microsoft.AspNetCore.Identity;
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NBitcoin.DataEncoders;
|
||||
using NBXplorer;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace BTCPayServer.Hosting
|
||||
{
|
||||
|
@ -27,21 +30,18 @@ namespace BTCPayServer.Hosting
|
|||
private readonly StoreRepository _StoreRepository;
|
||||
private readonly BTCPayNetworkProvider _NetworkProvider;
|
||||
private readonly SettingsRepository _Settings;
|
||||
private readonly BTCPayServerOptions _btcPayServerOptions;
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
public MigrationStartupTask(
|
||||
BTCPayNetworkProvider networkProvider,
|
||||
StoreRepository storeRepository,
|
||||
ApplicationDbContextFactory dbContextFactory,
|
||||
UserManager<ApplicationUser> userManager,
|
||||
SettingsRepository settingsRepository,
|
||||
BTCPayServerOptions btcPayServerOptions)
|
||||
SettingsRepository settingsRepository)
|
||||
{
|
||||
_DBContextFactory = dbContextFactory;
|
||||
_StoreRepository = storeRepository;
|
||||
_NetworkProvider = networkProvider;
|
||||
_Settings = settingsRepository;
|
||||
_btcPayServerOptions = btcPayServerOptions;
|
||||
_userManager = userManager;
|
||||
}
|
||||
public async Task ExecuteAsync(CancellationToken cancellationToken = default)
|
||||
|
@ -50,6 +50,12 @@ namespace BTCPayServer.Hosting
|
|||
{
|
||||
await Migrate(cancellationToken);
|
||||
var settings = (await _Settings.GetSettingAsync<MigrationSettings>()) ?? new MigrationSettings();
|
||||
if (!settings.PaymentMethodCriteria)
|
||||
{
|
||||
await MigratePaymentMethodCriteria();
|
||||
settings.PaymentMethodCriteria = true;
|
||||
await _Settings.UpdateSetting(settings);
|
||||
}
|
||||
if (!settings.DeprecatedLightningConnectionStringCheck)
|
||||
{
|
||||
await DeprecatedLightningConnectionStringCheck();
|
||||
|
@ -95,6 +101,13 @@ namespace BTCPayServer.Hosting
|
|||
settings.CheckedFirstRun = true;
|
||||
await _Settings.UpdateSetting(settings);
|
||||
}
|
||||
|
||||
if (!settings.TransitionToStoreBlobAdditionalData)
|
||||
{
|
||||
await TransitionToStoreBlobAdditionalData();
|
||||
settings.TransitionToStoreBlobAdditionalData = true;
|
||||
await _Settings.UpdateSetting(settings);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -103,6 +116,23 @@ namespace BTCPayServer.Hosting
|
|||
}
|
||||
}
|
||||
|
||||
private async Task TransitionToStoreBlobAdditionalData()
|
||||
{
|
||||
await using var ctx = _DBContextFactory.CreateContext();
|
||||
foreach (var store in await ctx.Stores.AsNoTracking().ToArrayAsync())
|
||||
{
|
||||
var blob = store.GetStoreBlob();
|
||||
blob.AdditionalData.Remove("walletKeyPathRoots");
|
||||
blob.AdditionalData.Remove("onChainMinValue");
|
||||
blob.AdditionalData.Remove("lightningMaxValue");
|
||||
blob.AdditionalData.Remove("networkFeeDisabled");
|
||||
blob.AdditionalData.Remove("rateRules");
|
||||
store.SetStoreBlob(blob);
|
||||
}
|
||||
|
||||
await ctx.SaveChangesAsync();
|
||||
}
|
||||
|
||||
private async Task Migrate(CancellationToken cancellationToken)
|
||||
{
|
||||
using (CancellationTokenSource timeout = new CancellationTokenSource(10_000))
|
||||
|
@ -131,23 +161,32 @@ retry:
|
|||
bool save = false;
|
||||
using (var ctx = _DBContextFactory.CreateContext())
|
||||
{
|
||||
foreach (var store in await ctx.Stores.AsQueryable().ToArrayAsync())
|
||||
foreach (var store in await ctx.Stores.AsNoTracking().ToArrayAsync())
|
||||
{
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
var blob = store.GetStoreBlob();
|
||||
if (blob.WalletKeyPathRoots == null)
|
||||
continue;
|
||||
foreach (var scheme in store.GetSupportedPaymentMethods(_NetworkProvider).OfType<DerivationSchemeSettings>())
|
||||
|
||||
if (blob.AdditionalData.TryGetValue("walletKeyPathRoots", out var walletKeyPathRootsJToken))
|
||||
{
|
||||
if (blob.WalletKeyPathRoots.TryGetValue(scheme.PaymentId.ToString().ToLowerInvariant(), out var root))
|
||||
var walletKeyPathRoots = walletKeyPathRootsJToken.ToObject<Dictionary<string, string>>();
|
||||
|
||||
if (!(walletKeyPathRoots?.Any() is true))
|
||||
continue;
|
||||
foreach (var scheme in store.GetSupportedPaymentMethods(_NetworkProvider)
|
||||
.OfType<DerivationSchemeSettings>())
|
||||
{
|
||||
scheme.AccountKeyPath = new NBitcoin.KeyPath(root);
|
||||
store.SetSupportedPaymentMethod(scheme);
|
||||
save = true;
|
||||
if (walletKeyPathRoots.TryGetValue(scheme.PaymentId.ToString().ToLowerInvariant(),
|
||||
out var root))
|
||||
{
|
||||
scheme.AccountKeyPath = new NBitcoin.KeyPath(root);
|
||||
store.SetSupportedPaymentMethod(scheme);
|
||||
save = true;
|
||||
}
|
||||
}
|
||||
|
||||
blob.AdditionalData.Remove("walletKeyPathRoots");
|
||||
store.SetStoreBlob(blob);
|
||||
}
|
||||
blob.WalletKeyPathRoots = null;
|
||||
store.SetStoreBlob(blob);
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
}
|
||||
if (save)
|
||||
|
@ -173,6 +212,58 @@ retry:
|
|||
}
|
||||
}
|
||||
|
||||
private async Task MigratePaymentMethodCriteria()
|
||||
{
|
||||
using (var ctx = _DBContextFactory.CreateContext())
|
||||
{
|
||||
foreach (var store in await ctx.Stores.AsNoTracking().ToArrayAsync())
|
||||
{
|
||||
var blob = store.GetStoreBlob();
|
||||
|
||||
CurrencyValue onChainMinValue = null;
|
||||
CurrencyValue lightningMaxValue = null;
|
||||
if (blob.AdditionalData.TryGetValue("onChainMinValue", out var onChainMinValueJToken))
|
||||
{
|
||||
CurrencyValue.TryParse(onChainMinValueJToken.Value<string>(), out onChainMinValue);
|
||||
blob.AdditionalData.Remove("onChainMinValue");
|
||||
}
|
||||
if (blob.AdditionalData.TryGetValue("lightningMaxValue", out var lightningMaxValueJToken))
|
||||
{
|
||||
CurrencyValue.TryParse(lightningMaxValueJToken.Value<string>(), out lightningMaxValue);
|
||||
blob.AdditionalData.Remove("lightningMaxValue");
|
||||
}
|
||||
blob.PaymentMethodCriteria = store.GetEnabledPaymentIds(_NetworkProvider).Select(paymentMethodId=>
|
||||
{
|
||||
var matchedFromBlob =
|
||||
blob.PaymentMethodCriteria?.SingleOrDefault(criteria => criteria.PaymentMethod == paymentMethodId && criteria.Value != null);
|
||||
return matchedFromBlob switch
|
||||
{
|
||||
null when paymentMethodId.PaymentType == LightningPaymentType.Instance &&
|
||||
lightningMaxValue != null => new PaymentMethodCriteria()
|
||||
{
|
||||
Above = false, PaymentMethod = paymentMethodId, Value = lightningMaxValue
|
||||
},
|
||||
null when paymentMethodId.PaymentType == BitcoinPaymentType.Instance &&
|
||||
onChainMinValue != null => new PaymentMethodCriteria()
|
||||
{
|
||||
Above = true, PaymentMethod = paymentMethodId, Value = onChainMinValue
|
||||
},
|
||||
_ => new PaymentMethodCriteria()
|
||||
{
|
||||
PaymentMethod = paymentMethodId,
|
||||
Above = matchedFromBlob?.Above ?? true,
|
||||
Value = matchedFromBlob?.Value
|
||||
}
|
||||
};
|
||||
}).ToList();
|
||||
|
||||
store.SetStoreBlob(blob);
|
||||
}
|
||||
|
||||
await ctx.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ConvertNetworkFeeProperty()
|
||||
{
|
||||
using (var ctx = _DBContextFactory.CreateContext())
|
||||
|
@ -180,14 +271,17 @@ retry:
|
|||
foreach (var store in await ctx.Stores.AsQueryable().ToArrayAsync())
|
||||
{
|
||||
var blob = store.GetStoreBlob();
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
if (blob.NetworkFeeDisabled != null)
|
||||
if (blob.AdditionalData.TryGetValue("networkFeeDisabled", out var networkFeeModeJToken))
|
||||
{
|
||||
blob.NetworkFeeMode = blob.NetworkFeeDisabled.Value ? NetworkFeeMode.Never : NetworkFeeMode.Always;
|
||||
blob.NetworkFeeDisabled = null;
|
||||
var networkFeeMode = networkFeeModeJToken.ToObject<bool?>();
|
||||
if (networkFeeMode != null)
|
||||
{
|
||||
blob.NetworkFeeMode = networkFeeMode.Value ? NetworkFeeMode.Never : NetworkFeeMode.Always;
|
||||
}
|
||||
|
||||
blob.AdditionalData.Remove("networkFeeDisabled");
|
||||
store.SetStoreBlob(blob);
|
||||
}
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
}
|
||||
await ctx.SaveChangesAsync();
|
||||
}
|
||||
|
@ -197,27 +291,46 @@ retry:
|
|||
{
|
||||
using (var ctx = _DBContextFactory.CreateContext())
|
||||
{
|
||||
foreach (var store in await ctx.Stores.AsQueryable().ToArrayAsync())
|
||||
foreach (var store in await ctx.Stores.AsNoTracking().ToArrayAsync())
|
||||
{
|
||||
var blob = store.GetStoreBlob();
|
||||
#pragma warning disable CS0612 // Type or member is obsolete
|
||||
decimal multiplier = 1.0m;
|
||||
if (blob.RateRules != null && blob.RateRules.Count != 0)
|
||||
if (blob.AdditionalData.TryGetValue("rateRules", out var rateRulesJToken))
|
||||
{
|
||||
foreach (var rule in blob.RateRules)
|
||||
var rateRules = new Serializer(null).ToObject<List<RateRule_Obsolete>>(rateRulesJToken.ToString());
|
||||
if (rateRules != null && rateRules.Count != 0)
|
||||
{
|
||||
multiplier = rule.Apply(null, multiplier);
|
||||
foreach (var rule in rateRules)
|
||||
{
|
||||
multiplier = rule.Apply(null, multiplier);
|
||||
}
|
||||
}
|
||||
|
||||
blob.AdditionalData.Remove("rateRules");
|
||||
blob.Spread = Math.Min(1.0m, Math.Max(0m, -(multiplier - 1.0m)));
|
||||
store.SetStoreBlob(blob);
|
||||
}
|
||||
blob.RateRules = null;
|
||||
blob.Spread = Math.Min(1.0m, Math.Max(0m, -(multiplier - 1.0m)));
|
||||
store.SetStoreBlob(blob);
|
||||
#pragma warning restore CS0612 // Type or member is obsolete
|
||||
}
|
||||
await ctx.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public class RateRule_Obsolete
|
||||
{
|
||||
public RateRule_Obsolete()
|
||||
{
|
||||
RuleName = "Multiplier";
|
||||
}
|
||||
public string RuleName { get; set; }
|
||||
|
||||
public double Multiplier { get; set; }
|
||||
|
||||
public decimal Apply(BTCPayNetworkBase network, decimal rate)
|
||||
{
|
||||
return rate * (decimal)Multiplier;
|
||||
}
|
||||
}
|
||||
|
||||
private Task UnreachableStoreCheck()
|
||||
{
|
||||
return _StoreRepository.CleanUnreachableStores();
|
||||
|
@ -227,7 +340,7 @@ retry:
|
|||
{
|
||||
using (var ctx = _DBContextFactory.CreateContext())
|
||||
{
|
||||
foreach (var store in await ctx.Stores.AsQueryable().ToArrayAsync())
|
||||
foreach (var store in await ctx.Stores.AsNoTracking().ToArrayAsync())
|
||||
{
|
||||
foreach (var method in store.GetSupportedPaymentMethods(_NetworkProvider).OfType<Payments.Lightning.LightningSupportedPaymentMethod>())
|
||||
{
|
||||
|
|
|
@ -9,6 +9,9 @@ namespace BTCPayServer.Services
|
|||
public bool ConvertCrowdfundOldSettings { get; set; }
|
||||
public bool ConvertWalletKeyPathRoots { get; set; }
|
||||
public bool CheckedFirstRun { get; set; }
|
||||
public bool PaymentMethodCriteria { get; set; }
|
||||
public bool TransitionToStoreBlobAdditionalData { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Empty;
|
||||
|
|
Loading…
Add table
Reference in a new issue