From 0df2fb89070169f0fed3186acb05a323c7c3d1b6 Mon Sep 17 00:00:00 2001 From: Kukks Date: Thu, 13 Jul 2023 09:14:17 +0200 Subject: [PATCH] update ss --- .../SideShiftController.cs | 32 +--- .../SideShiftPlugin.cs | 1 + .../SideShiftService.cs | 148 +++++++++++++++++- .../SideShiftSettings.cs | 6 + .../UpdateSideShiftSettingsViewModel.cs | 8 - .../SideShift/CheckoutPaymentExtension.cshtml | 27 +++- .../CheckoutPaymentMethodExtension.cshtml | 33 +++- .../Shared/SideShift/PrismEnhance.cshtml | 31 ++-- .../SideShift/PullPaymentViewInsert.cshtml | 27 ++-- .../SideShift/UpdateSideShiftSettings.cshtml | 30 +++- 10 files changed, 262 insertions(+), 81 deletions(-) delete mode 100644 Plugins/BTCPayServer.Plugins.SideShift/UpdateSideShiftSettingsViewModel.cs diff --git a/Plugins/BTCPayServer.Plugins.SideShift/SideShiftController.cs b/Plugins/BTCPayServer.Plugins.SideShift/SideShiftController.cs index f400d12..61048b0 100644 --- a/Plugins/BTCPayServer.Plugins.SideShift/SideShiftController.cs +++ b/Plugins/BTCPayServer.Plugins.SideShift/SideShiftController.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Net; using System.Net.Http; using System.Threading; using System.Threading.Tasks; @@ -11,7 +10,6 @@ using BTCPayServer.Data; using BTCPayServer.HostedServices; using BTCPayServer.Payments; using BTCPayServer.Services; -using BTCPayServer.Services.Stores; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; @@ -26,29 +24,24 @@ namespace BTCPayServer.Plugins.SideShift [Route("plugins/{storeId}/SideShift")] public class SideShiftController : Controller { - private readonly BTCPayServerClient _btcPayServerClient; private readonly SideShiftService _sideShiftService; private readonly IHttpClientFactory _httpClientFactory; private readonly IEnumerable _payoutHandlers; private readonly PullPaymentHostedService _pullPaymentHostedService; - private readonly StoreRepository _storeRepository; private readonly BTCPayNetworkJsonSerializerSettings _serializerSettings; private readonly ApplicationDbContextFactory _dbContextFactory; - public SideShiftController(BTCPayServerClient btcPayServerClient, + public SideShiftController( SideShiftService sideShiftService, IHttpClientFactory httpClientFactory, IEnumerable payoutHandlers, PullPaymentHostedService pullPaymentHostedService, - StoreRepository storeRepository, BTCPayNetworkJsonSerializerSettings serializerSettings, ApplicationDbContextFactory dbContextFactory) { - _btcPayServerClient = btcPayServerClient; _sideShiftService = sideShiftService; _httpClientFactory = httpClientFactory; _payoutHandlers = payoutHandlers; _pullPaymentHostedService = pullPaymentHostedService; - _storeRepository = storeRepository; _serializerSettings = serializerSettings; _dbContextFactory = dbContextFactory; } @@ -56,10 +49,6 @@ namespace BTCPayServer.Plugins.SideShift [HttpGet("")] public async Task UpdateSideShiftSettings(string storeId) { - var store = await _btcPayServerClient.GetStore(storeId); - - UpdateSideShiftSettingsViewModel vm = new UpdateSideShiftSettingsViewModel(); - vm.StoreName = store.Name; SideShiftSettings SideShift = null; try { @@ -70,19 +59,12 @@ namespace BTCPayServer.Plugins.SideShift // ignored } - SetExistingValues(SideShift, vm); - return View(vm); + return View(SideShift??new SideShiftSettings()); } - private void SetExistingValues(SideShiftSettings existing, UpdateSideShiftSettingsViewModel vm) - { - if (existing == null) - return; - vm.Enabled = existing.Enabled; - } [HttpPost("")] - public async Task UpdateSideShiftSettings(string storeId, UpdateSideShiftSettingsViewModel vm, + public async Task UpdateSideShiftSettings(string storeId, SideShiftSettings vm, string command) { if (vm.Enabled) @@ -93,15 +75,11 @@ namespace BTCPayServer.Plugins.SideShift } } - var sideShiftSettings = new SideShiftSettings() - { - Enabled = vm.Enabled, - }; switch (command) { case "save": - await _sideShiftService.SetSideShiftForStore(storeId, sideShiftSettings); + await _sideShiftService.SetSideShiftForStore(storeId, vm); TempData["SuccessMessage"] = "SideShift settings modified"; return RedirectToAction(nameof(UpdateSideShiftSettings), new {storeId}); @@ -223,7 +201,7 @@ namespace BTCPayServer.Plugins.SideShift if (claim.Result == ClaimRequest.ClaimResult.Ok) { await using var ctx = _dbContextFactory.CreateContext(); - ppBlob.Description += $"The payout of {claim.PayoutData.Destination} will be forwarded to SideShift.ai for further conversion. Please go to the order page for support."; + ppBlob.Description += $"The payout of {claim.PayoutData.Destination} will be forwarded to SideShift.ai for further conversion. Please go to the order page for support."; pp.SetBlob(ppBlob); ctx.Attach(pp).State = EntityState.Modified; await ctx.SaveChangesAsync(); diff --git a/Plugins/BTCPayServer.Plugins.SideShift/SideShiftPlugin.cs b/Plugins/BTCPayServer.Plugins.SideShift/SideShiftPlugin.cs index 394dfe3..d895f2d 100644 --- a/Plugins/BTCPayServer.Plugins.SideShift/SideShiftPlugin.cs +++ b/Plugins/BTCPayServer.Plugins.SideShift/SideShiftPlugin.cs @@ -148,5 +148,6 @@ namespace BTCPayServer.Plugins.SideShift public bool hasMemo { get; set; } public JToken fixedOnly { get; set; } public JToken variableOnly { get; set; } + public JToken settleOffline { get; set; } } } \ No newline at end of file diff --git a/Plugins/BTCPayServer.Plugins.SideShift/SideShiftService.cs b/Plugins/BTCPayServer.Plugins.SideShift/SideShiftService.cs index 668afaa..0744722 100644 --- a/Plugins/BTCPayServer.Plugins.SideShift/SideShiftService.cs +++ b/Plugins/BTCPayServer.Plugins.SideShift/SideShiftService.cs @@ -1,8 +1,13 @@ using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; using System.Threading.Tasks; using BTCPayServer.Abstractions.Contracts; using BTCPayServer.Client; using Microsoft.Extensions.Caching.Memory; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; namespace BTCPayServer.Plugins.SideShift { @@ -11,12 +16,14 @@ namespace BTCPayServer.Plugins.SideShift private readonly ISettingsRepository _settingsRepository; private readonly IMemoryCache _memoryCache; private readonly IStoreRepository _storeRepository; + private readonly IHttpClientFactory _httpClientFactory; - public SideShiftService(ISettingsRepository settingsRepository, IMemoryCache memoryCache, IStoreRepository storeRepository) + public SideShiftService(ISettingsRepository settingsRepository, IMemoryCache memoryCache, IStoreRepository storeRepository, IHttpClientFactory httpClientFactory) { _settingsRepository = settingsRepository; _memoryCache = memoryCache; _storeRepository = storeRepository; + _httpClientFactory = httpClientFactory; } public async Task GetSideShiftForStore(string storeId) @@ -45,5 +52,144 @@ namespace BTCPayServer.Plugins.SideShift await _storeRepository.UpdateSetting(storeId, nameof(SideShiftSettings), SideShiftSettings); _memoryCache.Set(k, SideShiftSettings); } + + public async Task> GetSettleCoins() + { + return await _memoryCache.GetOrCreateAsync>("sideshift-coins", async entry => + { + var client = _httpClientFactory.CreateClient("sideshift"); + var request = new HttpRequestMessage(HttpMethod.Get, "https://sideshift.ai/api/v2/coins"); + var response = await client.SendAsync(request); + var result = new List(); + if (!response.IsSuccessStatusCode) + { + entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(2); + return result; + } + var coins = await response.Content.ReadAsStringAsync().ContinueWith(t => JsonConvert.DeserializeObject>(t.Result)); + + coins.ForEach(coin => + { + Array.ForEach (coin.networks,network => + { + if(coin.settleOffline.Type == JTokenType.Boolean && coin.settleOffline.Value()) + return; + if (coin.settleOffline is JArray settleOfflineArray && + settleOfflineArray.Any(v => v.Value() == network)) + { + return; + } + + var coinType = CoinType.Both; + if (coin.fixedOnly.Type == JTokenType.Boolean && coin.fixedOnly.Value()) + { + coinType = CoinType.FixedOnly; + } + else if (coin.fixedOnly is JArray fixedOnlyArray && + fixedOnlyArray.Any(v => v.Value() == network)) + { + coinType = CoinType.FixedOnly; + } + else if (coin.variableOnly.Type == JTokenType.Boolean && coin.variableOnly.Value()) + { + coinType = CoinType.VariableOnly; + } + else if (coin.variableOnly is JArray variableOnlyArray && + variableOnlyArray.Any(v => v.Value() == network)) + { + coinType = CoinType.VariableOnly; + } + + result.Add(new SideshiftSettleCoin() + { + Id = $"{coin.coin}_{network}", + CryptoCode = coin.coin, + Network = network, + DisplayName = coin.name, + HasMemo = coin.hasMemo, + Type = coinType, + }); + }); + }); + + entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5); + entry.Value = result; + return entry.Value as List; + }); + + + } + + public enum CoinType + { + FixedOnly, + VariableOnly, + Both + } + + public class SideshiftSettleCoin:SideshiftDepositCoin + { + public bool HasMemo { get; set; } + } + public class SideshiftDepositCoin + { + public string DisplayName { get; set; } + public string Id { get; set; } + public CoinType Type { get; set; } + public string CryptoCode { get; set; } + public string Network { get; set; } + + public override string ToString() + { + return $"{DisplayName} {(DisplayName.Equals(Network, StringComparison.InvariantCultureIgnoreCase)? string.Empty: $"({Network})")}"; + } + } + public async Task> GetDepositOptions() + { + return (List) await _memoryCache.GetOrCreateAsync("sideshift-deposit", async entry => + { + var client = _httpClientFactory.CreateClient("sideshift"); + var request = new HttpRequestMessage(HttpMethod.Get, "https://sideshift.ai/api/v1/facts"); + var response = await client.SendAsync(request); + var result = new List(); + if (!response.IsSuccessStatusCode) + { + entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(2); + return result; + } + var coins = await response.Content.ReadAsStringAsync().ContinueWith(t => JsonConvert.DeserializeObject(t.Result)); + + foreach (var asset in coins["depositMethods"].Children()) + { + if (asset.Value["enabled"].Value() is not true) + { + continue; + } + var id = asset.Name; + var displayName = asset.Value["displayName"].Value(); + var coinType = asset.Value["fixedOnly"].Value() ? CoinType.FixedOnly : asset.Value["variableOnly"].Value()? CoinType.VariableOnly : CoinType.Both; + var network = asset.Value["network"].Value(); + var cryptoCode = asset.Value["asset"].Value(); + result.Add(new SideshiftDepositCoin() + { + Id = id, + DisplayName = displayName, + Type = coinType, + Network = network, + CryptoCode = cryptoCode, + }); + } + + entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5); + entry.Value = result; + return entry.Value; + }); + + + } + + + } } + diff --git a/Plugins/BTCPayServer.Plugins.SideShift/SideShiftSettings.cs b/Plugins/BTCPayServer.Plugins.SideShift/SideShiftSettings.cs index 448e15c..645eaea 100644 --- a/Plugins/BTCPayServer.Plugins.SideShift/SideShiftSettings.cs +++ b/Plugins/BTCPayServer.Plugins.SideShift/SideShiftSettings.cs @@ -4,5 +4,11 @@ namespace BTCPayServer.Plugins.SideShift { public bool Enabled { get; set; } public decimal AmountMarkupPercentage { get; set; } = 0; + + public string? PreferredTargetPaymentMethodId { get; set; } + public string[] ExplicitMethods { get; set; } + public bool OnlyShowExplicitMethods { get; set; } = false; + + } } diff --git a/Plugins/BTCPayServer.Plugins.SideShift/UpdateSideShiftSettingsViewModel.cs b/Plugins/BTCPayServer.Plugins.SideShift/UpdateSideShiftSettingsViewModel.cs deleted file mode 100644 index 86b2418..0000000 --- a/Plugins/BTCPayServer.Plugins.SideShift/UpdateSideShiftSettingsViewModel.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace BTCPayServer.Plugins.SideShift -{ - public class UpdateSideShiftSettingsViewModel - { - public bool Enabled { get; set; } - public string StoreName { get; set; } - } -} diff --git a/Plugins/BTCPayServer.Plugins.SideShift/Views/Shared/SideShift/CheckoutPaymentExtension.cshtml b/Plugins/BTCPayServer.Plugins.SideShift/Views/Shared/SideShift/CheckoutPaymentExtension.cshtml index c19952c..1863233 100644 --- a/Plugins/BTCPayServer.Plugins.SideShift/Views/Shared/SideShift/CheckoutPaymentExtension.cshtml +++ b/Plugins/BTCPayServer.Plugins.SideShift/Views/Shared/SideShift/CheckoutPaymentExtension.cshtml @@ -3,9 +3,12 @@ @using Newtonsoft.Json.Linq @inject BTCPayServer.Security.ContentSecurityPolicies csp @inject SideShiftService SideShiftService +@model BTCPayServer.Models.InvoicingModels.PaymentModel @{ - var storeId = ((JObject)JObject.Parse(JsonConvert.SerializeObject(Model)))["StoreId"].Value(); + var storeId = Model.StoreId; var settings = await SideShiftService.GetSideShiftForStore(storeId); + var preferredTargetPaymentMethodId = string.IsNullOrEmpty(settings?.PreferredTargetPaymentMethodId) ? null : Model.AvailableCryptos.Any(crypto => crypto.PaymentMethodId == settings.PreferredTargetPaymentMethodId) ? settings.PreferredTargetPaymentMethodId : null; + } @if (settings?.Enabled is true) { @@ -22,6 +25,21 @@ Vue.component("SideShiftCheckout", { template: "#side-shift-checkout-template", props: ["model"], + data: function() { + return { + explicitId: "", + preferredToCurrency: @Json.Serialize(preferredTargetPaymentMethodId), + } + }, + created () { + const self = this; + setInterval(function() { + if ( self.explicitId === window.ssExplicitId) { + return; + } + self.explicitId = window.ssExplicitId; + },200) + }, computed: { content () { return this.$i18n.i18next.t("conversion_body", this.model).replace(/\n/ig, '
'); @@ -55,13 +73,20 @@ openDialog () { window.__SIDESHIFT__ = { parentAffiliateId: "qg0OrfHJV", + defaultDepositMethodId: this.explicitId || undefined, defaultSettleMethodId: this.settleMethodId, settleAddress: this.model.btcAddress, settleAmount: this.amountDue, type: this.type }; + console.log(window.__SIDESHIFT__); window.sideshift.show(); } + }, + watch: { + explicitId (val) { + this.openDialog(); + } } }); diff --git a/Plugins/BTCPayServer.Plugins.SideShift/Views/Shared/SideShift/CheckoutPaymentMethodExtension.cshtml b/Plugins/BTCPayServer.Plugins.SideShift/Views/Shared/SideShift/CheckoutPaymentMethodExtension.cshtml index a177fdf..0b20b27 100644 --- a/Plugins/BTCPayServer.Plugins.SideShift/Views/Shared/SideShift/CheckoutPaymentMethodExtension.cshtml +++ b/Plugins/BTCPayServer.Plugins.SideShift/Views/Shared/SideShift/CheckoutPaymentMethodExtension.cshtml @@ -1,15 +1,36 @@ @using BTCPayServer.Plugins.SideShift -@using Newtonsoft.Json -@using Newtonsoft.Json.Linq @inject SideShiftService SideShiftService +@model BTCPayServer.Models.InvoicingModels.PaymentModel @{ const string id = "SideShift"; - var storeId = ((JObject)JObject.Parse(JsonConvert.SerializeObject(Model)))["StoreId"].Value(); + var storeId = Model.StoreId; var settings = await SideShiftService.GetSideShiftForStore(storeId); if (settings?.Enabled is true) { - - @id - + + var coins = await SideShiftService.GetDepositOptions(); + if (settings.ExplicitMethods?.Any() is true) + { + foreach (var explicitMethod in settings.ExplicitMethods) + { + var s = explicitMethod.Split("_"); + var coin = s[0]; + var network = s[1]; + var coinInfo = coins.FirstOrDefault(c => c.CryptoCode == coin && c.Network == network); + if(coinInfo is null) + continue; + + @coinInfo.DisplayName @(coinInfo.DisplayName.Equals(coinInfo.Network, StringComparison.InvariantCultureIgnoreCase)? string.Empty: $"({coinInfo.Network})") + + } + } + if (!settings.OnlyShowExplicitMethods || settings.ExplicitMethods?.Any() is not true) + { + + @id + + } + + } } diff --git a/Plugins/BTCPayServer.Plugins.SideShift/Views/Shared/SideShift/PrismEnhance.cshtml b/Plugins/BTCPayServer.Plugins.SideShift/Views/Shared/SideShift/PrismEnhance.cshtml index 9738cab..e25f4f4 100644 --- a/Plugins/BTCPayServer.Plugins.SideShift/Views/Shared/SideShift/PrismEnhance.cshtml +++ b/Plugins/BTCPayServer.Plugins.SideShift/Views/Shared/SideShift/PrismEnhance.cshtml @@ -1,31 +1,24 @@ -@using System.Net.Http -@using BTCPayServer.Abstractions.TagHelpers +@using BTCPayServer.Abstractions.TagHelpers @using BTCPayServer.Plugins.SideShift @using Microsoft.AspNetCore.Mvc.TagHelpers -@using Newtonsoft.Json -@using Newtonsoft.Json.Linq -@inject IHttpClientFactory HttpClientFactory +@inject SideShiftService SideShiftService @{ - var client = HttpClientFactory.CreateClient("sideshift"); - var request = new HttpRequestMessage(HttpMethod.Get, "https://sideshift.ai/api/v2/coins"); - var response = await client.SendAsync(request); - if (!response.IsSuccessStatusCode) + + var coins = await SideShiftService.GetSettleCoins(); + coins = coins.Where(tuple => new[] {SideShiftService.CoinType.VariableOnly, SideShiftService.CoinType.Both}.Contains(tuple.Type)).ToList(); + if(coins.Any() is not true) { return; } - var coins = await response.Content.ReadAsStringAsync().ContinueWith(t => JsonConvert.DeserializeObject>(t.Result)); - var availableCoins = coins.SelectMany(coin => coin.networks.Select(s => (Coin: coin, Network: s))) - .Where(tuple => (tuple.Coin.fixedOnly.Type == JTokenType.Boolean && !tuple.Coin.fixedOnly.Value()) || ( - tuple.Coin.fixedOnly is JArray varOnlyArray && varOnlyArray.All(v => v.Value() != tuple.Network))).ToList(); }