Compare commits
65 Commits
payment-ty
...
ext-point-
Author | SHA1 | Date | |
---|---|---|---|
7c6a0f25c1 | |||
fd6d361e1a | |||
b5f0924651 | |||
1600dd4759 | |||
c777746b69 | |||
9f5466a41f | |||
4d1e4801bf | |||
5e469ff9c0 | |||
2f3eedea5b | |||
5c5d6dc1e2 | |||
fbe31ce64f | |||
0b082138c8 | |||
966e598f10 | |||
098a36e1c1 | |||
e998340387 | |||
f6b27cc5f9 | |||
f3dbf1e139 | |||
627d84fc91 | |||
8cde8c01df | |||
3fb5e85369 | |||
983b8c1f54 | |||
d666d8ea1a | |||
3ed81c3a78 | |||
4afec2e2b6 | |||
db83d238d5 | |||
fdcf7b3b7a | |||
53aafcf86b | |||
aec84f6d67 | |||
01e9f82d24 | |||
2eff45e65c | |||
13203c3e2b | |||
82c5e0e43d | |||
a1575f404b | |||
e1509506dc | |||
0c1d0d7b05 | |||
ad70856af0 | |||
8615f120ce | |||
0d0477d661 | |||
b31dc30878 | |||
6e392f4cfb | |||
cc3bdc331e | |||
76faf77a1c | |||
d8c0e5bf3a | |||
28c4c320cc | |||
e81403ec3f | |||
f11424f73a | |||
fa8b977016 | |||
d181846339 | |||
1956919886 | |||
0f66498965 | |||
918cd152b1 | |||
d3222df396 | |||
a84ffd8c7e | |||
6d0f9120b8 | |||
aafb4a7f2a | |||
ae432ff237 | |||
cdc318c71a | |||
94d1cec8a9 | |||
c0bc19ea59 | |||
6f07714cd9 | |||
a9d2cac23c | |||
693b46126b | |||
bbff9710bf | |||
358e122775 | |||
3818468932 |
BTCPayServer.Client
BTCPayServer.Common
Altcoins
BTCPayNetworkProvider.BGold.csBTCPayNetworkProvider.Bitcore.csBTCPayNetworkProvider.Chaincoin.cs
BTCPayNetworkProvider.csBTCPayServer.Common.csprojLiquid
BTCPayServer.Rating
BTCPayServer.Tests
AltcoinTests
CheckoutUITests.csCheckoutv2Tests.csExtensions.csFastTests.csGreenfieldAPITests.csPOSTests.csPayJoinTests.csSeleniumTests.csThirdPartyTests.csUnitTest1.csdocker-compose.altcoins.ymldocker-compose.ymlBTCPayServer
BTCPayServer.csprojWalletId.cs
Components
AppTopItems
StoreLightningBalance
StoreRecentInvoices
StoreRecentTransactions
Controllers
BitpayRateController.cs
GreenField
GreenfieldCustodianAccountController.csGreenfieldInvoiceController.csGreenfieldLightningNodeApiController.Store.csGreenfieldPaymentRequestsController.csGreenfieldPullPaymentController.csGreenfieldStoreAutomatedLightningPayoutProcessorsController.csGreenfieldStoreAutomatedOnChainPayoutProcessorsController.csGreenfieldStoreLNURLPayPaymentMethodsController.csGreenfieldStoreLightningNetworkPaymentMethodsController.csGreenfieldStoreOnChainPaymentMethodsController.WalletGeneration.csGreenfieldStoreOnChainPaymentMethodsController.csGreenfieldStoreOnChainWalletsController.csGreenfieldStorePaymentMethodsController.csGreenfieldStoresController.csGreenfieldTestApiKeyController.cs
UIAppsController.csUICustodianAccountsController.csUIInvoiceController.UI.csUIInvoiceController.csUILNURLController.csUIManageController.APIKeys.csUIPaymentRequestController.csUIPublicLightningNodeInfoController.csUIPullPaymentController.csUIServerController.csUIStoresController.LightningLike.csUIStoresController.Onchain.csUIStoresController.csUIVaultController.csUIWalletsController.csData
AddressInvoiceDataExtensions.csPaymentDataExtensions.cs
DerivationSchemeSettings.csExtensions.csPayouts
StoreBlob.csStoreDataExtensions.csExtensions
HostedServices
Hosting
JsonConverters
ModelBinders
Models
Payments
Bitcoin
BitcoinLikeOnChainPaymentMethod.csBitcoinLikePaymentData.csBitcoinLikePaymentHandler.csNBXplorerListener.cs
LNURLPay
Lightning
LightningLikePaymentData.csLightningLikePaymentHandler.csLightningLikePaymentMethodDetails.csLightningListener.csLightningPendingPayoutListener.csLightningSupportedPaymentMethod.cs
PayJoin
PaymentMethodExtensions.csPaymentMethodId.csPaymentTypeRegistry.csPaymentTypes.csPlugins
Crowdfund/Controllers
NFC
PayButton/Controllers
PointOfSale
Security/GreenField
Services
Views
Shared
Crowdfund
Forms
LayoutHeadTheme.cshtmlNFC
PayButton
PointOfSale
PosData.cshtmlShowQR.cshtmlTemplateEditor.cshtml_Layout.cshtmlUIForms
UIInvoice
UIManage
UIPaymentRequest
UIPullPayment
UIServer
UIStorePullPayments
UIStores
UIWallets
wwwroot
cart
checkout-v2
js
light-pos
locales
main
paybutton
swagger/v1
vendor
Build
Changelog.md@ -12,6 +12,8 @@
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<RepositoryUrl>https://github.com/btcpayserver/btcpayserver</RepositoryUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<Configurations>Debug;Release;Altcoins-Debug;Altcoins-Release</Configurations>
|
||||
<Platforms>AnyCPU</Platforms>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<Version Condition=" '$(Version)' == '' ">1.7.2</Version>
|
||||
|
@ -16,7 +16,7 @@ namespace BTCPayServer
|
||||
DefaultRateRules = new[]
|
||||
{
|
||||
"BTG_X = BTG_BTC * BTC_X",
|
||||
"BTG_BTC = bitfinex(BTG_BTC)",
|
||||
"BTG_BTC = exmo(BTG_BTC)",
|
||||
},
|
||||
CryptoImagePath = "imlegacy/btg.svg",
|
||||
LightningImagePath = "imlegacy/btg-lightning.svg",
|
||||
|
@ -17,7 +17,7 @@ namespace BTCPayServer
|
||||
DefaultRateRules = new[]
|
||||
{
|
||||
"BTX_X = BTX_BTC * BTC_X",
|
||||
"BTX_BTC = hitbtc(BTX_BTC)"
|
||||
"BTX_BTC = graviex(BTX_BTC)"
|
||||
},
|
||||
CryptoImagePath = "imlegacy/bitcore.svg",
|
||||
LightningImagePath = "imlegacy/bitcore-lightning.svg",
|
||||
|
@ -1,32 +0,0 @@
|
||||
using NBitcoin;
|
||||
|
||||
namespace BTCPayServer
|
||||
{
|
||||
public partial class BTCPayNetworkProvider
|
||||
{
|
||||
public void InitChaincoin()
|
||||
{
|
||||
var nbxplorerNetwork = NBXplorerNetworkProvider.GetFromCryptoCode("CHC");
|
||||
Add(new BTCPayNetwork()
|
||||
{
|
||||
CryptoCode = nbxplorerNetwork.CryptoCode,
|
||||
DisplayName = "Chaincoin",
|
||||
BlockExplorerLink = NetworkType == ChainName.Mainnet
|
||||
? "https://explorer.chaincoin.org/Explorer/Transaction/{0}"
|
||||
: "https://test.explorer.chaincoin.org/Explorer/Transaction/tx/{0}",
|
||||
NBXplorerNetwork = nbxplorerNetwork,
|
||||
DefaultRateRules = new[]
|
||||
{
|
||||
"CHC_X = CHC_BTC * BTC_X",
|
||||
"CHC_BTC = txbit(CHC_X)"
|
||||
},
|
||||
CryptoImagePath = "imlegacy/chaincoin.png",
|
||||
DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType),
|
||||
//https://github.com/satoshilabs/slips/blob/master/slip-0044.md
|
||||
CoinType = NetworkType == ChainName.Mainnet ? new KeyPath("711'")
|
||||
: new KeyPath("1'")
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -63,6 +63,7 @@ namespace BTCPayServer
|
||||
"LCAD_CAD = 1",
|
||||
"LCAD_X = CAD_BTC * BTC_X",
|
||||
"LCAD_BTC = bylls(CAD_BTC)",
|
||||
"CAD_BTC = LCAD_BTC"
|
||||
},
|
||||
AssetId = new uint256("0e99c1a6da379d1f4151fb9df90449d40d0608f6cb33a5bcbfc8c265f42bab0a"),
|
||||
DisplayName = "Liquid CAD",
|
||||
|
@ -56,7 +56,6 @@ namespace BTCPayServer
|
||||
InitViacoin();
|
||||
InitMonero();
|
||||
InitZcash();
|
||||
InitChaincoin();
|
||||
// InitArgoneum();//their rate source is down 9/15/20.
|
||||
// InitMonetaryUnit(); Not supported from Bittrex from 11/23/2022, dead shitcoin
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
<PackageReference Include="NBXplorer.Client" Version="4.2.3" />
|
||||
<PackageReference Include="NBXplorer.Client" Version="4.2.5" />
|
||||
<PackageReference Include="NicolasDorier.StandardConfiguration" Version="2.0.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(Altcoins)' != 'true'">
|
||||
|
@ -15,7 +15,7 @@ namespace BTCPayServer.Rating
|
||||
while (true)
|
||||
{
|
||||
var rounded = decimal.Round(value, divisibility, MidpointRounding.AwayFromZero);
|
||||
if ((Math.Abs(rounded - value) / value) < 0.001m)
|
||||
if ((Math.Abs(rounded - value) / value) < 0.01m)
|
||||
{
|
||||
value = rounded;
|
||||
break;
|
||||
|
@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Rating;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace BTCPayServer.Services.Rates;
|
||||
|
||||
|
||||
public class ExchangeRateHostRateProvider : IRateProvider
|
||||
{
|
||||
public RateSourceInfo RateSourceInfo => new("exchangeratehost", "Yadio", "https://api.exchangerate.host/latest?base=BTC");
|
||||
private readonly HttpClient _httpClient;
|
||||
public ExchangeRateHostRateProvider(HttpClient httpClient)
|
||||
{
|
||||
_httpClient = httpClient ?? new HttpClient();
|
||||
}
|
||||
|
||||
public async Task<PairRate[]> GetRatesAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var response = await _httpClient.GetAsync(RateSourceInfo.Url, cancellationToken);
|
||||
response.EnsureSuccessStatusCode();
|
||||
var jobj = await response.Content.ReadAsAsync<JObject>(cancellationToken);
|
||||
if(jobj["success"].Value<bool>() is not true || !jobj["base"].Value<string>().Equals("BTC", StringComparison.InvariantCulture))
|
||||
throw new Exception("exchangerate.host returned a non success response or the base currency was not the requested one (BTC)");
|
||||
var results = (JObject) jobj["rates"] ;
|
||||
//key value is currency code to rate value
|
||||
var list = new List<PairRate>();
|
||||
foreach (var item in results)
|
||||
{
|
||||
string name = item.Key;
|
||||
var value = item.Value.Value<decimal>();
|
||||
list.Add(new PairRate(new CurrencyPair("BTC", name), new BidAsk(value)));
|
||||
}
|
||||
|
||||
return list.ToArray();
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Rating;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace BTCPayServer.Services.Rates;
|
||||
|
||||
public class FreeCurrencyRatesRateProvider : IRateProvider
|
||||
{
|
||||
public RateSourceInfo RateSourceInfo => new("free-currency-rates", "Free Currency Rates", "https://cdn.jsdelivr.net/gh/fawazahmed0/currency-api@1/latest/currencies/btc.min.json");
|
||||
private readonly HttpClient _httpClient;
|
||||
public FreeCurrencyRatesRateProvider(HttpClient httpClient)
|
||||
{
|
||||
_httpClient = httpClient ?? new HttpClient();
|
||||
}
|
||||
|
||||
public async Task<PairRate[]> GetRatesAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var response = await _httpClient.GetAsync(RateSourceInfo.Url, cancellationToken);
|
||||
response.EnsureSuccessStatusCode();
|
||||
var jobj = await response.Content.ReadAsAsync<JObject>(cancellationToken);
|
||||
var results = (JObject) jobj["btc"] ;
|
||||
//key value is currency code to rate value
|
||||
var list = new List<PairRate>();
|
||||
foreach (var item in results)
|
||||
{
|
||||
string name = item.Key;
|
||||
var value = item.Value.Value<decimal>();
|
||||
list.Add(new PairRate(new CurrencyPair("BTC", name), new BidAsk(value)));
|
||||
}
|
||||
|
||||
return list.ToArray();
|
||||
}
|
||||
}
|
@ -669,7 +669,7 @@ donation:
|
||||
Assert.Equal("Wanna tip?", vmview.CustomTipText);
|
||||
Assert.Equal("15,18,20", string.Join(',', vmview.CustomTipPercentages));
|
||||
Assert.IsType<RedirectToActionResult>(publicApps
|
||||
.ViewPointOfSale(app.Id, PosViewType.Cart, 0, null, null, null, null, "orange").Result);
|
||||
.ViewPointOfSale(app.Id, PosViewType.Cart, 0, choiceKey: "orange").Result);
|
||||
|
||||
//
|
||||
var invoices = await user.BitPay.GetInvoicesAsync();
|
||||
@ -678,7 +678,7 @@ donation:
|
||||
Assert.Equal("CAD", orangeInvoice.Currency);
|
||||
Assert.Equal("orange", orangeInvoice.ItemDesc);
|
||||
Assert.IsType<RedirectToActionResult>(publicApps
|
||||
.ViewPointOfSale(app.Id, PosViewType.Cart, 0, null, null, null, null, "apple").Result);
|
||||
.ViewPointOfSale(app.Id, PosViewType.Cart, 0, choiceKey: "apple").Result);
|
||||
|
||||
invoices = user.BitPay.GetInvoices();
|
||||
var appleInvoice = invoices.SingleOrDefault(invoice => invoice.ItemCode.Equals("apple"));
|
||||
@ -687,7 +687,7 @@ donation:
|
||||
|
||||
// testing custom amount
|
||||
var action = Assert.IsType<RedirectToActionResult>(publicApps
|
||||
.ViewPointOfSale(app.Id, PosViewType.Cart, 6.6m, null, null, null, null, "donation").Result);
|
||||
.ViewPointOfSale(app.Id, PosViewType.Cart, 6.6m, choiceKey: "donation").Result);
|
||||
Assert.Equal(nameof(UIInvoiceController.Checkout), action.ActionName);
|
||||
invoices = user.BitPay.GetInvoices();
|
||||
var donationInvoice = invoices.Single(i => i.Price == 6.6m);
|
||||
@ -760,20 +760,20 @@ noninventoryitem:
|
||||
await tester.WaitForEvent<AppInventoryUpdaterHostedService.UpdateAppInventory>(() =>
|
||||
{
|
||||
Assert.IsType<RedirectToActionResult>(publicApps
|
||||
.ViewPointOfSale(app.Id, PosViewType.Cart, 1, null, null, null, null, "inventoryitem").Result);
|
||||
.ViewPointOfSale(app.Id, PosViewType.Cart, 1, choiceKey: "inventoryitem").Result);
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
|
||||
//we already bought all available stock so this should fail
|
||||
await Task.Delay(100);
|
||||
Assert.IsType<RedirectToActionResult>(publicApps
|
||||
.ViewPointOfSale(app.Id, PosViewType.Cart, 1, null, null, null, null, "inventoryitem").Result);
|
||||
.ViewPointOfSale(app.Id, PosViewType.Cart, 1, choiceKey: "inventoryitem").Result);
|
||||
|
||||
//inventoryitem has unlimited items available
|
||||
Assert.IsType<RedirectToActionResult>(publicApps
|
||||
.ViewPointOfSale(app.Id, PosViewType.Cart, 1, null, null, null, null, "noninventoryitem").Result);
|
||||
.ViewPointOfSale(app.Id, PosViewType.Cart, 1, choiceKey: "noninventoryitem").Result);
|
||||
Assert.IsType<RedirectToActionResult>(publicApps
|
||||
.ViewPointOfSale(app.Id, PosViewType.Cart, 1, null, null, null, null, "noninventoryitem").Result);
|
||||
.ViewPointOfSale(app.Id, PosViewType.Cart, 1, choiceKey: "noninventoryitem").Result);
|
||||
|
||||
//verify invoices where created
|
||||
invoices = user.BitPay.GetInvoices();
|
||||
@ -809,22 +809,22 @@ normal:
|
||||
vmpos.Template = AppService.SerializeTemplate(MigrationStartupTask.ParsePOSYML(vmpos.Template));
|
||||
Assert.IsType<RedirectToActionResult>(pos.UpdatePointOfSale(app.Id, vmpos).Result);
|
||||
Assert.IsType<RedirectToActionResult>(publicApps
|
||||
.ViewPointOfSale(app.Id, PosViewType.Cart, 1, null, null, null, null, "btconly").Result);
|
||||
.ViewPointOfSale(app.Id, PosViewType.Cart, 1, choiceKey: "btconly").Result);
|
||||
Assert.IsType<RedirectToActionResult>(publicApps
|
||||
.ViewPointOfSale(app.Id, PosViewType.Cart, 1, null, null, null, null, "normal").Result);
|
||||
.ViewPointOfSale(app.Id, PosViewType.Cart, 1, choiceKey: "normal").Result);
|
||||
invoices = user.BitPay.GetInvoices();
|
||||
var normalInvoice = invoices.Single(invoice => invoice.ItemCode == "normal");
|
||||
var btcOnlyInvoice = invoices.Single(invoice => invoice.ItemCode == "btconly");
|
||||
Assert.Single(btcOnlyInvoice.CryptoInfo);
|
||||
Assert.Equal("BTC",
|
||||
btcOnlyInvoice.CryptoInfo.First().CryptoCode);
|
||||
Assert.Equal(BitcoinPaymentType.Instance.ToString(),
|
||||
Assert.Equal(PaymentTypes.BTCLike.ToString(),
|
||||
btcOnlyInvoice.CryptoInfo.First().PaymentType);
|
||||
|
||||
Assert.Equal(2, normalInvoice.CryptoInfo.Length);
|
||||
Assert.Contains(
|
||||
normalInvoice.CryptoInfo,
|
||||
s => BitcoinPaymentType.Instance.ToString() == s.PaymentType && new[] { "BTC", "LTC" }.Contains(
|
||||
s => PaymentTypes.BTCLike.ToString() == s.PaymentType && new[] { "BTC", "LTC" }.Contains(
|
||||
s.CryptoCode));
|
||||
|
||||
//test topup option
|
||||
@ -865,7 +865,7 @@ g:
|
||||
Assert.Contains(items, item => item.Id == "g" && item.PriceType == ViewPointOfSaleViewModel.ItemPriceType.Topup);
|
||||
|
||||
Assert.IsType<RedirectToActionResult>(publicApps
|
||||
.ViewPointOfSale(app.Id, PosViewType.Static, null, null, null, null, null, "g").Result);
|
||||
.ViewPointOfSale(app.Id, PosViewType.Static, choiceKey: "g").Result);
|
||||
invoices = user.BitPay.GetInvoices();
|
||||
var topupInvoice = invoices.Single(invoice => invoice.ItemCode == "g");
|
||||
Assert.Equal(0, topupInvoice.Price);
|
||||
|
@ -210,7 +210,7 @@ namespace BTCPayServer.Tests
|
||||
Assert.True(s.Driver.FindElement(By.Name("btcpay")).Displayed);
|
||||
});
|
||||
await s.Server.ExplorerNode.SendToAddressAsync(BitcoinAddress.Create(invoice
|
||||
.GetPaymentMethod(new PaymentMethodId("BTC", BitcoinPaymentType.Instance))
|
||||
.GetPaymentMethod(new PaymentMethodId("BTC", PaymentTypes.BTCLike))
|
||||
.GetPaymentMethodDetails().GetPaymentDestination(), Network.RegTest),
|
||||
new Money(0.001m, MoneyUnit.BTC));
|
||||
|
||||
|
@ -452,7 +452,7 @@ namespace BTCPayServer.Tests
|
||||
iframe.WaitUntilAvailable(By.Id("Checkout-v2"));
|
||||
|
||||
await s.Server.ExplorerNode.SendToAddressAsync(BitcoinAddress.Create(invoice
|
||||
.GetPaymentMethod(new PaymentMethodId("BTC", BitcoinPaymentType.Instance))
|
||||
.GetPaymentMethod(new PaymentMethodId("BTC", PaymentTypes.BTCLike))
|
||||
.GetPaymentMethodDetails().GetPaymentDestination(), Network.RegTest),
|
||||
new Money(0.001m, MoneyUnit.BTC));
|
||||
|
||||
|
@ -122,6 +122,13 @@ retry:
|
||||
driver.ExecuteJavaScript($"document.getElementById('{element}').{funcName}()");
|
||||
}
|
||||
|
||||
public static void WaitWalletTransactionsLoaded(this IWebDriver driver)
|
||||
{
|
||||
var wait = new WebDriverWait(driver, SeleniumTester.ImplicitWait);
|
||||
wait.UntilJsIsReady();
|
||||
wait.Until(d => d.WaitForElement(By.CssSelector("#WalletTransactions[data-loaded='true']")));
|
||||
}
|
||||
|
||||
public static IWebElement WaitForElement(this IWebDriver driver, By selector)
|
||||
{
|
||||
var wait = new WebDriverWait(driver, SeleniumTester.ImplicitWait);
|
||||
|
@ -368,7 +368,7 @@ namespace BTCPayServer.Tests
|
||||
});
|
||||
entity.Price = 5000;
|
||||
|
||||
var paymentMethod = entity.GetPaymentMethods().TryGet("BTC", BitcoinPaymentType.Instance);
|
||||
var paymentMethod = entity.GetPaymentMethods().TryGet("BTC", PaymentTypes.BTCLike);
|
||||
var accounting = paymentMethod.Calculate();
|
||||
Assert.Equal(Money.Coins(1.1m), accounting.Due);
|
||||
Assert.Equal(Money.Coins(1.1m), accounting.TotalDue);
|
||||
@ -424,11 +424,11 @@ namespace BTCPayServer.Tests
|
||||
new PaymentMethod() { CryptoCode = "LTC", Rate = 500, NextNetworkFee = Money.Coins(0.01m) });
|
||||
entity.SetPaymentMethods(paymentMethods);
|
||||
entity.Payments = new List<PaymentEntity>();
|
||||
paymentMethod = entity.GetPaymentMethod(new PaymentMethodId("BTC", BitcoinPaymentType.Instance));
|
||||
paymentMethod = entity.GetPaymentMethod(new PaymentMethodId("BTC", PaymentTypes.BTCLike));
|
||||
accounting = paymentMethod.Calculate();
|
||||
Assert.Equal(Money.Coins(5.1m), accounting.Due);
|
||||
|
||||
paymentMethod = entity.GetPaymentMethod(new PaymentMethodId("LTC", BitcoinPaymentType.Instance));
|
||||
paymentMethod = entity.GetPaymentMethod(new PaymentMethodId("LTC", PaymentTypes.BTCLike));
|
||||
accounting = paymentMethod.Calculate();
|
||||
|
||||
Assert.Equal(Money.Coins(10.01m), accounting.TotalDue);
|
||||
@ -441,7 +441,7 @@ namespace BTCPayServer.Tests
|
||||
NetworkFee = 0.1m
|
||||
});
|
||||
|
||||
paymentMethod = entity.GetPaymentMethod(new PaymentMethodId("BTC", BitcoinPaymentType.Instance));
|
||||
paymentMethod = entity.GetPaymentMethod(new PaymentMethodId("BTC", PaymentTypes.BTCLike));
|
||||
accounting = paymentMethod.Calculate();
|
||||
Assert.Equal(Money.Coins(4.2m), accounting.Due);
|
||||
Assert.Equal(Money.Coins(1.0m), accounting.CryptoPaid);
|
||||
@ -449,7 +449,7 @@ namespace BTCPayServer.Tests
|
||||
Assert.Equal(Money.Coins(5.2m), accounting.TotalDue);
|
||||
Assert.Equal(2, accounting.TxRequired);
|
||||
|
||||
paymentMethod = entity.GetPaymentMethod(new PaymentMethodId("LTC", BitcoinPaymentType.Instance));
|
||||
paymentMethod = entity.GetPaymentMethod(new PaymentMethodId("LTC", PaymentTypes.BTCLike));
|
||||
accounting = paymentMethod.Calculate();
|
||||
Assert.Equal(Money.Coins(10.01m + 0.1m * 2 - 2.0m /* 8.21m */), accounting.Due);
|
||||
Assert.Equal(Money.Coins(0.0m), accounting.CryptoPaid);
|
||||
@ -464,7 +464,7 @@ namespace BTCPayServer.Tests
|
||||
NetworkFee = 0.01m
|
||||
});
|
||||
|
||||
paymentMethod = entity.GetPaymentMethod(new PaymentMethodId("BTC", BitcoinPaymentType.Instance));
|
||||
paymentMethod = entity.GetPaymentMethod(new PaymentMethodId("BTC", PaymentTypes.BTCLike));
|
||||
accounting = paymentMethod.Calculate();
|
||||
Assert.Equal(Money.Coins(4.2m - 0.5m + 0.01m / 2), accounting.Due);
|
||||
Assert.Equal(Money.Coins(1.0m), accounting.CryptoPaid);
|
||||
@ -472,7 +472,7 @@ namespace BTCPayServer.Tests
|
||||
Assert.Equal(Money.Coins(5.2m + 0.01m / 2), accounting.TotalDue); // The fee for LTC added
|
||||
Assert.Equal(2, accounting.TxRequired);
|
||||
|
||||
paymentMethod = entity.GetPaymentMethod(new PaymentMethodId("LTC", BitcoinPaymentType.Instance));
|
||||
paymentMethod = entity.GetPaymentMethod(new PaymentMethodId("LTC", PaymentTypes.BTCLike));
|
||||
accounting = paymentMethod.Calculate();
|
||||
Assert.Equal(Money.Coins(8.21m - 1.0m + 0.01m), accounting.Due);
|
||||
Assert.Equal(Money.Coins(1.0m), accounting.CryptoPaid);
|
||||
@ -489,7 +489,7 @@ namespace BTCPayServer.Tests
|
||||
NetworkFee = 0.1m
|
||||
});
|
||||
|
||||
paymentMethod = entity.GetPaymentMethod(new PaymentMethodId("BTC", BitcoinPaymentType.Instance));
|
||||
paymentMethod = entity.GetPaymentMethod(new PaymentMethodId("BTC", PaymentTypes.BTCLike));
|
||||
accounting = paymentMethod.Calculate();
|
||||
Assert.Equal(Money.Zero, accounting.Due);
|
||||
Assert.Equal(Money.Coins(1.0m) + remaining, accounting.CryptoPaid);
|
||||
@ -498,7 +498,7 @@ namespace BTCPayServer.Tests
|
||||
Assert.Equal(accounting.Paid, accounting.TotalDue);
|
||||
Assert.Equal(2, accounting.TxRequired);
|
||||
|
||||
paymentMethod = entity.GetPaymentMethod(new PaymentMethodId("LTC", BitcoinPaymentType.Instance));
|
||||
paymentMethod = entity.GetPaymentMethod(new PaymentMethodId("LTC", PaymentTypes.BTCLike));
|
||||
accounting = paymentMethod.Calculate();
|
||||
Assert.Equal(Money.Zero, accounting.Due);
|
||||
Assert.Equal(Money.Coins(1.0m), accounting.CryptoPaid);
|
||||
@ -556,7 +556,7 @@ namespace BTCPayServer.Tests
|
||||
entity.PaymentTolerance = 0;
|
||||
|
||||
|
||||
var paymentMethod = entity.GetPaymentMethods().TryGet("BTC", BitcoinPaymentType.Instance);
|
||||
var paymentMethod = entity.GetPaymentMethods().TryGet("BTC", PaymentTypes.BTCLike);
|
||||
var accounting = paymentMethod.Calculate();
|
||||
Assert.Equal(Money.Coins(1.1m), accounting.Due);
|
||||
Assert.Equal(Money.Coins(1.1m), accounting.TotalDue);
|
||||
@ -1145,6 +1145,45 @@ namespace BTCPayServer.Tests
|
||||
Assert.Equal("000000161", m.OrderId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanParseOldPosAppData()
|
||||
{
|
||||
var data = new JObject()
|
||||
{
|
||||
["price"] = 1.64m
|
||||
}.ToString();
|
||||
Assert.Equal(1.64m, JsonConvert.DeserializeObject<PosAppCartItem>(data).Price);
|
||||
|
||||
data = new JObject()
|
||||
{
|
||||
["price"] = new JObject()
|
||||
{
|
||||
["value"] = 1.65m
|
||||
}
|
||||
}.ToString();
|
||||
Assert.Equal(1.65m, JsonConvert.DeserializeObject<PosAppCartItem>(data).Price);
|
||||
data = new JObject()
|
||||
{
|
||||
["price"] = new JObject()
|
||||
{
|
||||
["value"] = "1.6305"
|
||||
}
|
||||
}.ToString();
|
||||
Assert.Equal(1.6305m, JsonConvert.DeserializeObject<PosAppCartItem>(data).Price);
|
||||
|
||||
data = new JObject()
|
||||
{
|
||||
["price"] = new JObject()
|
||||
{
|
||||
["value"] = null
|
||||
}
|
||||
}.ToString();
|
||||
Assert.Equal(0.0m, JsonConvert.DeserializeObject<PosAppCartItem>(data).Price);
|
||||
|
||||
var o = JObject.Parse(JsonConvert.SerializeObject(new PosAppCartItem() { Price = 1.356m }));
|
||||
Assert.Equal(1.356m, o["price"].Value<decimal>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanParseCurrencyValue()
|
||||
{
|
||||
@ -1873,7 +1912,7 @@ namespace BTCPayServer.Tests
|
||||
}));
|
||||
invoiceEntity.SetPaymentMethods(paymentMethods);
|
||||
|
||||
var btc = invoiceEntity.GetPaymentMethod(new PaymentMethodId("BTC", BitcoinPaymentType.Instance));
|
||||
var btc = invoiceEntity.GetPaymentMethod(new PaymentMethodId("BTC", PaymentTypes.BTCLike));
|
||||
var accounting = btc.Calculate();
|
||||
|
||||
invoiceEntity.Payments.Add(
|
||||
@ -1907,7 +1946,7 @@ namespace BTCPayServer.Tests
|
||||
Assert.Equal(Money.Zero, accounting.Due);
|
||||
Assert.Equal(Money.Zero, accounting.DueUncapped);
|
||||
|
||||
var ltc = invoiceEntity.GetPaymentMethod(new PaymentMethodId("LTC", BitcoinPaymentType.Instance));
|
||||
var ltc = invoiceEntity.GetPaymentMethod(new PaymentMethodId("LTC", PaymentTypes.BTCLike));
|
||||
accounting = ltc.Calculate();
|
||||
|
||||
Assert.Equal(Money.Zero, accounting.Due);
|
||||
@ -2015,7 +2054,7 @@ namespace BTCPayServer.Tests
|
||||
{
|
||||
Above = true,
|
||||
Value = new CurrencyValue() {Currency = "BTC", Value = 0.1m},
|
||||
PaymentMethod = new PaymentMethodId("BTC", BitcoinPaymentType.Instance)
|
||||
PaymentMethod = new PaymentMethodId("BTC", PaymentTypes.BTCLike)
|
||||
}
|
||||
};
|
||||
var newBlob = new Serializer(null).ToString(blob).Replace("paymentMethod\":\"BTC\"", "paymentMethod\":\"ETH_ZYC\"");
|
||||
|
@ -1074,6 +1074,22 @@ namespace BTCPayServer.Tests
|
||||
var lnrURLs = await unauthenticated.GetPullPaymentLNURL(test4.Id);
|
||||
Assert.IsType<string>(lnrURLs.LNURLBech32);
|
||||
Assert.IsType<string>(lnrURLs.LNURLUri);
|
||||
Assert.Equal(12.303228134m, test4.Amount);
|
||||
Assert.Equal("BTC", test4.Currency);
|
||||
|
||||
// Test with SATS denomination values
|
||||
var testSats = await client.CreatePullPayment(storeId, new Client.Models.CreatePullPaymentRequest()
|
||||
{
|
||||
Name = "Test SATS",
|
||||
Amount = 21000,
|
||||
Currency = "SATS",
|
||||
PaymentMethods = new[] { "BTC", "BTC-LightningNetwork", "BTC_LightningLike" }
|
||||
});
|
||||
lnrURLs = await unauthenticated.GetPullPaymentLNURL(testSats.Id);
|
||||
Assert.IsType<string>(lnrURLs.LNURLBech32);
|
||||
Assert.IsType<string>(lnrURLs.LNURLUri);
|
||||
Assert.Equal(21000, testSats.Amount);
|
||||
Assert.Equal("SATS", testSats.Currency);
|
||||
|
||||
//permission test around auto approved pps and payouts
|
||||
var nonApproved = await acc.CreateClient(Policies.CanCreateNonApprovedPullPayments);
|
||||
@ -2615,7 +2631,7 @@ namespace BTCPayServer.Tests
|
||||
for (int i = 0; i < invoices.Length; i++)
|
||||
{
|
||||
pm[i] = Assert.Single(await client.GetInvoicePaymentMethods(user.StoreId, (await invoices[i]).Id));
|
||||
Assert.False(pm[i].AdditionalData.HasValues);
|
||||
Assert.True(pm[i].AdditionalData.HasValues);
|
||||
}
|
||||
|
||||
// Pay them all at once
|
||||
@ -3267,7 +3283,7 @@ namespace BTCPayServer.Tests
|
||||
|
||||
void VerifyLightning(Dictionary<string, GenericPaymentMethodData> dictionary)
|
||||
{
|
||||
Assert.True(dictionary.TryGetValue(new PaymentMethodId("BTC", LightningPaymentType.Instance).ToStringNormalized(), out var item));
|
||||
Assert.True(dictionary.TryGetValue(new PaymentMethodId("BTC", PaymentTypes.LightningLike).ToStringNormalized(), out var item));
|
||||
var lightningNetworkPaymentMethodBaseData = Assert.IsType<JObject>(item.Data).ToObject<LightningNetworkPaymentMethodBaseData>();
|
||||
Assert.Equal("Internal Node", lightningNetworkPaymentMethodBaseData.ConnectionString);
|
||||
}
|
||||
@ -3282,7 +3298,7 @@ namespace BTCPayServer.Tests
|
||||
|
||||
void VerifyOnChain(Dictionary<string, GenericPaymentMethodData> dictionary)
|
||||
{
|
||||
Assert.True(dictionary.TryGetValue(new PaymentMethodId("BTC", BitcoinPaymentType.Instance).ToStringNormalized(), out var item));
|
||||
Assert.True(dictionary.TryGetValue(new PaymentMethodId("BTC", PaymentTypes.BTCLike).ToStringNormalized(), out var item));
|
||||
var paymentMethodBaseData = Assert.IsType<JObject>(item.Data).ToObject<OnChainPaymentMethodBaseData>();
|
||||
Assert.Equal(randK, paymentMethodBaseData.DerivationScheme);
|
||||
}
|
||||
@ -3304,14 +3320,14 @@ namespace BTCPayServer.Tests
|
||||
tester.GetLightningConnectionString(LightningConnectionType.CLightning, true), true));
|
||||
methods = await viewerOnlyClient.GetStorePaymentMethods(store.Id);
|
||||
|
||||
Assert.True(methods.TryGetValue(new PaymentMethodId("BTC", LightningPaymentType.Instance).ToStringNormalized(), out var item));
|
||||
Assert.True(methods.TryGetValue(new PaymentMethodId("BTC", PaymentTypes.LightningLike).ToStringNormalized(), out var item));
|
||||
var lightningNetworkPaymentMethodBaseData = Assert.IsType<JObject>(item.Data).ToObject<LightningNetworkPaymentMethodBaseData>();
|
||||
Assert.Equal("*NEED CanModifyStoreSettings PERMISSION TO VIEW*", lightningNetworkPaymentMethodBaseData.ConnectionString);
|
||||
|
||||
|
||||
methods = await adminClient.GetStorePaymentMethods(store.Id);
|
||||
|
||||
Assert.True(methods.TryGetValue(new PaymentMethodId("BTC", LightningPaymentType.Instance).ToStringNormalized(), out item));
|
||||
Assert.True(methods.TryGetValue(new PaymentMethodId("BTC", PaymentTypes.LightningLike).ToStringNormalized(), out item));
|
||||
lightningNetworkPaymentMethodBaseData = Assert.IsType<JObject>(item.Data).ToObject<LightningNetworkPaymentMethodBaseData>();
|
||||
Assert.NotEqual("*NEED CanModifyStoreSettings PERMISSION TO VIEW*", lightningNetworkPaymentMethodBaseData.ConnectionString);
|
||||
|
||||
|
@ -135,10 +135,10 @@ donation:
|
||||
Assert.Equal("donation", vmview.Items[1].Title);
|
||||
// orange is available
|
||||
Assert.IsType<RedirectToActionResult>(publicApps
|
||||
.ViewPointOfSale(app.Id, PosViewType.Cart, 0, null, null, null, null, "orange").Result);
|
||||
.ViewPointOfSale(app.Id, PosViewType.Cart, 0, choiceKey: "orange").Result);
|
||||
// apple is not found
|
||||
Assert.IsType<NotFoundResult>(publicApps
|
||||
.ViewPointOfSale(app.Id, PosViewType.Cart, 0, null, null, null, null, "apple").Result);
|
||||
.ViewPointOfSale(app.Id, PosViewType.Cart, 0, choiceKey: "apple").Result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -930,7 +930,7 @@ retry:
|
||||
tester.ExplorerClient.Network.NBitcoinNetwork);
|
||||
|
||||
var senderStore = await tester.PayTester.StoreRepository.FindStore(senderUser.StoreId);
|
||||
var paymentMethodId = new PaymentMethodId("BTC", BitcoinPaymentType.Instance);
|
||||
var paymentMethodId = new PaymentMethodId("BTC", PaymentTypes.BTCLike);
|
||||
var derivationSchemeSettings = senderStore.GetSupportedPaymentMethods(tester.NetworkProvider)
|
||||
.OfType<DerivationSchemeSettings>().SingleOrDefault(settings =>
|
||||
settings.PaymentId == paymentMethodId);
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
@ -961,11 +962,13 @@ namespace BTCPayServer.Tests
|
||||
s.Driver.FindElement(By.CssSelector("label[for='DefaultView_Cart']")).Click();
|
||||
s.Driver.FindElement(By.CssSelector(".template-item:nth-of-type(1) .btn-primary")).Click();
|
||||
s.Driver.FindElement(By.Id("BuyButtonText")).SendKeys("Take my money");
|
||||
s.Driver.FindElement(By.Id("EditorCategories-ts-control")).SendKeys("Drinks");
|
||||
s.Driver.FindElement(By.Id("SaveItemChanges")).Click();
|
||||
s.Driver.FindElement(By.Id("ToggleRawEditor")).Click();
|
||||
|
||||
var template = s.Driver.FindElement(By.Id("Template")).GetAttribute("value");
|
||||
Assert.Contains("\"buyButtonText\":\"Take my money\"", template);
|
||||
Assert.Contains("\"buyButtonText\": \"Take my money\"", template);
|
||||
Assert.Matches("\"categories\": \\[\n\\s+\"Drinks\"\n\\s+\\]", template);
|
||||
|
||||
s.Driver.FindElement(By.Id("SaveSettings")).Click();
|
||||
Assert.Contains("App updated", s.FindAlertMessage().Text);
|
||||
@ -979,6 +982,14 @@ namespace BTCPayServer.Tests
|
||||
Assert.True(s.Driver.PageSource.Contains("Tea shop"), "Unable to create PoS");
|
||||
Assert.True(s.Driver.PageSource.Contains("Cart"), "PoS not showing correct default view");
|
||||
Assert.True(s.Driver.PageSource.Contains("Take my money"), "PoS not showing correct default view");
|
||||
Assert.Equal(5, s.Driver.FindElements(By.CssSelector(".card-deck .card:not(.d-none)")).Count);
|
||||
|
||||
var drinks = s.Driver.FindElement(By.CssSelector("label[for='Category-Drinks']"));
|
||||
Assert.Equal("Drinks", drinks.Text);
|
||||
drinks.Click();
|
||||
Assert.Single(s.Driver.FindElements(By.CssSelector(".card-deck .card:not(.d-none)")));
|
||||
s.Driver.FindElement(By.CssSelector("label[for='Category-*']")).Click();
|
||||
Assert.Equal(5, s.Driver.FindElements(By.CssSelector(".card-deck .card:not(.d-none)")).Count);
|
||||
|
||||
s.Driver.Url = posBaseUrl + "/static";
|
||||
Assert.False(s.Driver.PageSource.Contains("Cart"), "Static PoS not showing correct view");
|
||||
@ -1145,12 +1156,13 @@ namespace BTCPayServer.Tests
|
||||
s.Driver.FindElement(By.Id("ArchivePaymentRequest")).Click();
|
||||
Assert.Contains("The payment request has been archived", s.FindAlertMessage().Text);
|
||||
Assert.DoesNotContain("Pay123", s.Driver.PageSource);
|
||||
s.Driver.FindElement(By.Id("SearchDropdownToggle")).Click();
|
||||
s.Driver.FindElement(By.Id("SearchIncludeArchived")).Click();
|
||||
s.Driver.FindElement(By.Id("StatusOptionsToggle")).Click();
|
||||
s.Driver.WaitForElement(By.Id("StatusOptionsIncludeArchived")).Click();
|
||||
Assert.Contains("Pay123", s.Driver.PageSource);
|
||||
|
||||
// unarchive (from list)
|
||||
s.Driver.FindElement(By.Id($"ToggleArchival-{payReqId}")).Click();
|
||||
s.Driver.FindElement(By.Id($"ToggleActions-{payReqId}")).Click();
|
||||
s.Driver.WaitForElement(By.Id($"ToggleArchival-{payReqId}")).Click();
|
||||
Assert.Contains("The payment request has been unarchived", s.FindAlertMessage().Text);
|
||||
Assert.Contains("Pay123", s.Driver.PageSource);
|
||||
}
|
||||
@ -1441,7 +1453,7 @@ namespace BTCPayServer.Tests
|
||||
s.Driver.FindElement(By.Id("CancelWizard")).Click();
|
||||
|
||||
// Check the label is applied to the tx
|
||||
|
||||
s.Driver.WaitWalletTransactionsLoaded();
|
||||
Assert.Equal("label2", s.Driver.FindElement(By.XPath("//*[@id=\"WalletTransactionsList\"]//*[contains(@class, 'transaction-label')]")).Text);
|
||||
|
||||
//change the wallet and ensure old address is not there and generating a new one does not result in the prev one
|
||||
@ -1492,7 +1504,9 @@ namespace BTCPayServer.Tests
|
||||
|
||||
// Check the tx sent earlier arrived
|
||||
s.Driver.FindElement(By.Id($"StoreNav-Wallet{cryptoCode}")).Click();
|
||||
Assert.Contains(tx.ToString(), s.Driver.PageSource);
|
||||
s.Driver.WaitWalletTransactionsLoaded();
|
||||
s.Driver.FindElement(By.PartialLinkText(tx.ToString()));
|
||||
|
||||
var walletTransactionUri = new Uri(s.Driver.Url);
|
||||
|
||||
// Send to bob
|
||||
@ -1618,9 +1632,8 @@ namespace BTCPayServer.Tests
|
||||
|
||||
// Transactions list is empty
|
||||
s.Driver.FindElement(By.Id($"StoreNav-Wallet{cryptoCode}")).Click();
|
||||
Assert.Contains("There are no transactions yet.", s.Driver.PageSource);
|
||||
s.Driver.AssertElementNotFound(By.Id("ExportDropdownToggle"));
|
||||
s.Driver.AssertElementNotFound(By.Id("ActionsDropdownToggle"));
|
||||
s.Driver.WaitWalletTransactionsLoaded();
|
||||
Assert.Contains("There are no transactions yet", s.Driver.FindElement(By.Id("WalletTransactions")).Text);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@ -1748,7 +1761,6 @@ namespace BTCPayServer.Tests
|
||||
Assert.Contains(labels, element => element.Text == "pull-payment");
|
||||
});
|
||||
|
||||
|
||||
s.GoToStore(s.StoreId, StoreNavPages.Payouts);
|
||||
s.Driver.FindElement(By.Id($"{PayoutState.InProgress}-view")).Click();
|
||||
ReadOnlyCollection<IWebElement> txs;
|
||||
@ -1859,7 +1871,7 @@ namespace BTCPayServer.Tests
|
||||
s.Driver.FindElement(By.Id("Destination")).SendKeys(bolt);
|
||||
s.Driver.FindElement(By.Id("SelectedPaymentMethod")).Click();
|
||||
s.Driver.FindElement(By.CssSelector(
|
||||
$"#SelectedPaymentMethod option[value={new PaymentMethodId("BTC", LightningPaymentType.Instance)}]"))
|
||||
$"#SelectedPaymentMethod option[value={new PaymentMethodId("BTC", PaymentTypes.LightningLike)}]"))
|
||||
.Click();
|
||||
|
||||
s.Driver.FindElement(By.Id("ClaimedAmount")).SendKeys(Keys.Enter);
|
||||
@ -1874,7 +1886,7 @@ namespace BTCPayServer.Tests
|
||||
s.Driver.FindElement(By.Id("Destination")).SendKeys(bolt);
|
||||
s.Driver.FindElement(By.Id("SelectedPaymentMethod")).Click();
|
||||
s.Driver.FindElement(By.CssSelector(
|
||||
$"#SelectedPaymentMethod option[value={new PaymentMethodId("BTC", LightningPaymentType.Instance)}]"))
|
||||
$"#SelectedPaymentMethod option[value={new PaymentMethodId("BTC", PaymentTypes.LightningLike)}]"))
|
||||
.Click();
|
||||
|
||||
s.Driver.FindElement(By.Id("ClaimedAmount")).SendKeys(Keys.Enter);
|
||||
@ -1883,7 +1895,7 @@ namespace BTCPayServer.Tests
|
||||
Assert.Contains(PayoutState.AwaitingApproval.GetStateString(), s.Driver.PageSource);
|
||||
|
||||
s.GoToStore(newStore.storeId, StoreNavPages.Payouts);
|
||||
s.Driver.FindElement(By.Id($"{new PaymentMethodId("BTC", LightningPaymentType.Instance)}-view")).Click();
|
||||
s.Driver.FindElement(By.Id($"{new PaymentMethodId("BTC", PaymentTypes.LightningLike)}-view")).Click();
|
||||
s.Driver.FindElement(By.Id($"{PayoutState.AwaitingApproval}-view")).Click();
|
||||
s.Driver.FindElement(By.Id($"{PayoutState.AwaitingApproval}-selectAllCheckbox")).Click();
|
||||
s.Driver.FindElement(By.Id($"{PayoutState.AwaitingApproval}-actions")).Click();
|
||||
@ -1894,7 +1906,7 @@ namespace BTCPayServer.Tests
|
||||
|
||||
s.FindAlertMessage(StatusMessageModel.StatusSeverity.Success);
|
||||
s.GoToStore(newStore.storeId, StoreNavPages.Payouts);
|
||||
s.Driver.FindElement(By.Id($"{new PaymentMethodId("BTC", LightningPaymentType.Instance)}-view")).Click();
|
||||
s.Driver.FindElement(By.Id($"{new PaymentMethodId("BTC", PaymentTypes.LightningLike)}-view")).Click();
|
||||
|
||||
s.Driver.FindElement(By.Id($"{PayoutState.Completed}-view")).Click();
|
||||
if (!s.Driver.PageSource.Contains(bolt))
|
||||
@ -1905,7 +1917,7 @@ namespace BTCPayServer.Tests
|
||||
s.Driver.FindElement(By.Id($"{PayoutState.AwaitingPayment}-selectAllCheckbox")).Click();
|
||||
s.Driver.FindElement(By.Id($"{PayoutState.AwaitingPayment}-actions")).Click();
|
||||
s.Driver.FindElement(By.Id($"{PayoutState.AwaitingPayment}-mark-paid")).Click();
|
||||
s.Driver.FindElement(By.Id($"{new PaymentMethodId("BTC", LightningPaymentType.Instance)}-view")).Click();
|
||||
s.Driver.FindElement(By.Id($"{new PaymentMethodId("BTC", PaymentTypes.LightningLike)}-view")).Click();
|
||||
|
||||
s.Driver.FindElement(By.Id($"{PayoutState.Completed}-view")).Click();
|
||||
Assert.Contains(bolt, s.Driver.PageSource);
|
||||
@ -1932,8 +1944,7 @@ namespace BTCPayServer.Tests
|
||||
|
||||
Assert.Contains(PayoutState.AwaitingPayment.GetStateString(), s.Driver.PageSource);
|
||||
|
||||
//lnurl-w support check
|
||||
|
||||
// LNURL Withdraw support check with BTC denomination
|
||||
s.GoToStore(s.StoreId, StoreNavPages.PullPayments);
|
||||
s.Driver.FindElement(By.Id("NewPullPayment")).Click();
|
||||
s.Driver.FindElement(By.Id("Name")).SendKeys("PP1");
|
||||
@ -2001,6 +2012,42 @@ namespace BTCPayServer.Tests
|
||||
|
||||
Assert.Contains(PayoutState.AwaitingApproval.GetStateString(), s.Driver.PageSource);
|
||||
});
|
||||
|
||||
// LNURL Withdraw support check with SATS denomination
|
||||
s.GoToStore(s.StoreId, StoreNavPages.PullPayments);
|
||||
s.Driver.FindElement(By.Id("NewPullPayment")).Click();
|
||||
s.Driver.FindElement(By.Id("Name")).SendKeys("PP SATS");
|
||||
s.Driver.SetCheckbox(By.Id("AutoApproveClaims"), true);
|
||||
s.Driver.FindElement(By.Id("Amount")).Clear();
|
||||
s.Driver.FindElement(By.Id("Amount")).SendKeys("21021");
|
||||
s.Driver.FindElement(By.Id("Currency")).Clear();
|
||||
s.Driver.FindElement(By.Id("Currency")).SendKeys("SATS" + Keys.Enter);
|
||||
s.FindAlertMessage(StatusMessageModel.StatusSeverity.Success);
|
||||
s.Driver.FindElement(By.LinkText("View")).Click();
|
||||
s.Driver.FindElement(By.CssSelector("#lnurlwithdraw-button")).Click();
|
||||
lnurl = new Uri(LNURL.LNURL.Parse(s.Driver.FindElement(By.Id("qr-code-data-input")).GetAttribute("value"), out _).ToString().Replace("https", "http"));
|
||||
s.Driver.FindElement(By.CssSelector("button[data-bs-dismiss='modal']")).Click();
|
||||
var amount = new LightMoney(21021, LightMoneyUnit.Satoshi);
|
||||
info = Assert.IsType<LNURLWithdrawRequest>(await LNURL.LNURL.FetchInformation(lnurl, s.Server.PayTester.HttpClient));
|
||||
Assert.Equal(amount, info.MaxWithdrawable);
|
||||
Assert.Equal(amount, info.CurrentBalance);
|
||||
info = Assert.IsType<LNURLWithdrawRequest>(await LNURL.LNURL.FetchInformation(info.BalanceCheck, s.Server.PayTester.HttpClient));
|
||||
Assert.Equal(amount, info.MaxWithdrawable);
|
||||
Assert.Equal(amount, info.CurrentBalance);
|
||||
|
||||
bolt2 = (await s.Server.CustomerLightningD.CreateInvoice(
|
||||
amount,
|
||||
$"LNurl w payout test {DateTime.UtcNow.Ticks}",
|
||||
TimeSpan.FromHours(1), CancellationToken.None));
|
||||
response = await info.SendRequest(bolt2.BOLT11, s.Server.PayTester.HttpClient);
|
||||
await TestUtils.EventuallyAsync(async () =>
|
||||
{
|
||||
s.Driver.Navigate().Refresh();
|
||||
Assert.Contains(bolt2.BOLT11, s.Driver.PageSource);
|
||||
|
||||
Assert.Contains(PayoutState.Completed.GetStateString(), s.Driver.PageSource);
|
||||
Assert.Equal(LightningInvoiceStatus.Paid, (await s.Server.CustomerLightningD.GetInvoice(bolt2.Id)).Status);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@ -2040,6 +2087,145 @@ namespace BTCPayServer.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Selenium", "Selenium")]
|
||||
[Trait("Lightning", "Lightning")]
|
||||
public async Task CanUsePOSKeypad()
|
||||
{
|
||||
using var s = CreateSeleniumTester();
|
||||
s.Server.ActivateLightning();
|
||||
await s.StartAsync();
|
||||
|
||||
await s.Server.EnsureChannelsSetup();
|
||||
|
||||
s.RegisterNewUser(true);
|
||||
s.CreateNewStore();
|
||||
s.GoToStore();
|
||||
s.AddLightningNode(LightningConnectionType.CLightning, false);
|
||||
s.Driver.FindElement(By.Id("StoreNav-CreatePointOfSale")).Click();
|
||||
s.Driver.FindElement(By.Id("AppName")).SendKeys(Guid.NewGuid().ToString());
|
||||
s.Driver.FindElement(By.Id("Create")).Click();
|
||||
TestUtils.Eventually(() => Assert.Contains("App successfully created", s.FindAlertMessage().Text));
|
||||
s.Driver.FindElement(By.CssSelector("label[for='DefaultView_Light']")).Click();
|
||||
s.Driver.FindElement(By.Id("Currency")).SendKeys("EUR");
|
||||
s.Driver.FindElement(By.Id("CustomTipPercentages")).Clear();
|
||||
s.Driver.FindElement(By.Id("CustomTipPercentages")).SendKeys("10,21");
|
||||
s.Driver.FindElement(By.Id("SaveSettings")).Click();
|
||||
Assert.Contains("App updated", s.FindAlertMessage().Text);
|
||||
s.Driver.FindElement(By.Id("ViewApp")).Click();
|
||||
var windows = s.Driver.WindowHandles;
|
||||
Assert.Equal(2, windows.Count);
|
||||
s.Driver.SwitchTo().Window(windows[1]);
|
||||
s.Driver.WaitForElement(By.ClassName("keypad"));
|
||||
|
||||
// basic checks
|
||||
Assert.Contains("EUR", s.Driver.FindElement(By.Id("Currency")).Text);
|
||||
Assert.Contains("0,00", s.Driver.FindElement(By.Id("Amount")).Text);
|
||||
Assert.Equal("", s.Driver.FindElement(By.Id("Calculation")).Text);
|
||||
Assert.True(s.Driver.FindElement(By.Id("ModeTablist-amount")).Selected);
|
||||
Assert.False(s.Driver.FindElement(By.Id("ModeTablist-discount")).Enabled);
|
||||
Assert.False(s.Driver.FindElement(By.Id("ModeTablist-tip")).Enabled);
|
||||
|
||||
// Amount: 1234,56
|
||||
s.Driver.FindElement(By.CssSelector(".keypad [data-key='1']")).Click();
|
||||
s.Driver.FindElement(By.CssSelector(".keypad [data-key='2']")).Click();
|
||||
s.Driver.FindElement(By.CssSelector(".keypad [data-key='3']")).Click();
|
||||
s.Driver.FindElement(By.CssSelector(".keypad [data-key='4']")).Click();
|
||||
s.Driver.FindElement(By.CssSelector(".keypad [data-key='.']")).Click();
|
||||
s.Driver.FindElement(By.CssSelector(".keypad [data-key='5']")).Click();
|
||||
s.Driver.FindElement(By.CssSelector(".keypad [data-key='6']")).Click();
|
||||
Assert.Equal("1.234,56", s.Driver.FindElement(By.Id("Amount")).Text);
|
||||
Assert.True(s.Driver.FindElement(By.Id("ModeTablist-discount")).Enabled);
|
||||
Assert.True(s.Driver.FindElement(By.Id("ModeTablist-tip")).Enabled);
|
||||
Assert.Equal("", s.Driver.FindElement(By.Id("Calculation")).Text);
|
||||
|
||||
// Discount: 10%
|
||||
s.Driver.FindElement(By.CssSelector("label[for='ModeTablist-discount']")).Click();
|
||||
s.Driver.FindElement(By.CssSelector(".keypad [data-key='1']")).Click();
|
||||
s.Driver.FindElement(By.CssSelector(".keypad [data-key='0']")).Click();
|
||||
Assert.Contains("1.111,10", s.Driver.FindElement(By.Id("Amount")).Text);
|
||||
Assert.Contains("10% discount", s.Driver.FindElement(By.Id("Discount")).Text);
|
||||
Assert.Contains("1.234,56 € - 123,46 € (10%)", s.Driver.FindElement(By.Id("Calculation")).Text);
|
||||
|
||||
// Tip: 10%
|
||||
s.Driver.FindElement(By.CssSelector("label[for='ModeTablist-tip']")).Click();
|
||||
s.Driver.WaitForElement(By.Id("Tip-Custom"));
|
||||
s.Driver.FindElement(By.Id("Tip-10")).Click();
|
||||
Assert.Contains("1.222,21", s.Driver.FindElement(By.Id("Amount")).Text);
|
||||
Assert.Contains("1.234,56 € - 123,46 € (10%) + 111,11 € (10%)", s.Driver.FindElement(By.Id("Calculation")).Text);
|
||||
|
||||
// Pay
|
||||
s.Driver.FindElement(By.Id("pay-button")).Click();
|
||||
s.Driver.WaitUntilAvailable(By.Id("Checkout-v2"));
|
||||
s.Driver.FindElement(By.Id("DetailsToggle")).Click();
|
||||
s.Driver.WaitForElement(By.Id("PaymentDetails-TotalFiat"));
|
||||
Assert.Contains("1 222,21 €", s.Driver.FindElement(By.Id("PaymentDetails-TotalFiat")).Text);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Selenium", "Selenium")]
|
||||
[Trait("Lightning", "Lightning")]
|
||||
public async Task CanUsePOSCart()
|
||||
{
|
||||
using var s = CreateSeleniumTester();
|
||||
s.Server.ActivateLightning();
|
||||
await s.StartAsync();
|
||||
|
||||
await s.Server.EnsureChannelsSetup();
|
||||
|
||||
s.RegisterNewUser(true);
|
||||
s.CreateNewStore();
|
||||
s.GoToStore();
|
||||
s.AddLightningNode(LightningConnectionType.CLightning, false);
|
||||
s.Driver.FindElement(By.Id("StoreNav-CreatePointOfSale")).Click();
|
||||
s.Driver.FindElement(By.Id("AppName")).SendKeys(Guid.NewGuid().ToString());
|
||||
s.Driver.FindElement(By.Id("Create")).Click();
|
||||
Assert.Contains("App successfully created", s.FindAlertMessage().Text);
|
||||
s.Driver.FindElement(By.CssSelector("label[for='DefaultView_Cart']")).Click();
|
||||
s.Driver.FindElement(By.Id("Currency")).SendKeys("EUR");
|
||||
s.Driver.FindElement(By.Id("ShowCustomAmount")).Click();
|
||||
s.Driver.FindElement(By.Id("SaveSettings")).Click();
|
||||
Assert.Contains("App updated", s.FindAlertMessage().Text);
|
||||
s.Driver.FindElement(By.Id("ViewApp")).Click();
|
||||
var windows = s.Driver.WindowHandles;
|
||||
Assert.Equal(2, windows.Count);
|
||||
s.Driver.SwitchTo().Window(windows[1]);
|
||||
s.Driver.WaitForElement(By.Id("js-cart-list"));
|
||||
Assert.Empty(s.Driver.FindElements(By.CssSelector("#js-cart-list tbody tr")));
|
||||
Assert.Equal("0,00 €", s.Driver.FindElement(By.Id("CartTotal")).Text);
|
||||
Assert.False(s.Driver.FindElement(By.Id("CartClear")).Displayed);
|
||||
|
||||
// Select and clear
|
||||
s.Driver.FindElement(By.CssSelector(".card.js-add-cart:nth-child(1)")).Click();
|
||||
Assert.Single(s.Driver.FindElements(By.CssSelector("#js-cart-list tbody tr")));
|
||||
s.Driver.FindElement(By.Id("CartClear")).Click();
|
||||
Assert.Empty(s.Driver.FindElements(By.CssSelector("#js-cart-list tbody tr")));
|
||||
Thread.Sleep(250);
|
||||
|
||||
// Select items
|
||||
s.Driver.FindElement(By.CssSelector(".card.js-add-cart:nth-child(2)")).Click();
|
||||
Thread.Sleep(250);
|
||||
s.Driver.FindElement(By.CssSelector(".card.js-add-cart:nth-child(1)")).Click();
|
||||
Thread.Sleep(250);
|
||||
Assert.Equal(2, s.Driver.FindElements(By.CssSelector("#js-cart-list tbody tr")).Count);
|
||||
Assert.Equal("2,00 €", s.Driver.FindElement(By.Id("CartTotal")).Text);
|
||||
|
||||
// Custom amount
|
||||
s.Driver.FindElement(By.Id("CartCustomAmount")).SendKeys("1.5");
|
||||
s.Driver.FindElement(By.Id("CartTotal")).Click();
|
||||
Assert.Equal("3,50 €", s.Driver.FindElement(By.Id("CartTotal")).Text);
|
||||
s.Driver.FindElement(By.Id("js-cart-confirm")).Click();
|
||||
|
||||
// Pay
|
||||
Assert.Equal("3,50 €", s.Driver.FindElement(By.Id("CartSummaryTotal")).Text);
|
||||
s.Driver.FindElement(By.Id("js-cart-pay")).Click();
|
||||
|
||||
s.Driver.WaitUntilAvailable(By.Id("Checkout-v2"));
|
||||
s.Driver.FindElement(By.Id("DetailsToggle")).Click();
|
||||
s.Driver.WaitForElement(By.Id("PaymentDetails-TotalFiat"));
|
||||
Assert.Contains("3,50 €", s.Driver.FindElement(By.Id("PaymentDetails-TotalFiat")).Text);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Selenium", "Selenium")]
|
||||
[Trait("Lightning", "Lightning")]
|
||||
@ -2185,7 +2371,7 @@ namespace BTCPayServer.Tests
|
||||
// Check that pull payment has lightning option
|
||||
s.GoToStore(s.StoreId, StoreNavPages.PullPayments);
|
||||
s.Driver.FindElement(By.Id("NewPullPayment")).Click();
|
||||
Assert.Equal(new PaymentMethodId(cryptoCode, LightningPaymentType.Instance), PaymentMethodId.Parse(Assert.Single(s.Driver.FindElements(By.CssSelector("input[name='PaymentMethods']"))).GetAttribute("value")));
|
||||
Assert.Equal(new PaymentMethodId(cryptoCode, PaymentTypes.LightningLike), PaymentMethodId.Parse(Assert.Single(s.Driver.FindElements(By.CssSelector("input[name='PaymentMethods']"))).GetAttribute("value")));
|
||||
s.Driver.FindElement(By.Id("Name")).SendKeys("PP1");
|
||||
s.Driver.FindElement(By.Id("Amount")).Clear();
|
||||
s.Driver.FindElement(By.Id("Amount")).SendKeys("0.0000001");
|
||||
@ -2269,7 +2455,7 @@ namespace BTCPayServer.Tests
|
||||
|
||||
var addresses = s.Driver.FindElements(By.ClassName("lightning-address-value"));
|
||||
Assert.Equal(2, addresses.Count);
|
||||
|
||||
var callbacks = new List<Uri>();
|
||||
foreach (IWebElement webElement in addresses)
|
||||
{
|
||||
var value = webElement.GetAttribute("value");
|
||||
@ -2287,6 +2473,7 @@ namespace BTCPayServer.Tests
|
||||
lnaddress2 = m["text/identifier"];
|
||||
Assert.Equal(2, request.MinSendable.ToDecimal(LightMoneyUnit.Satoshi));
|
||||
Assert.Equal(10, request.MaxSendable.ToDecimal(LightMoneyUnit.Satoshi));
|
||||
callbacks.Add(request.Callback);
|
||||
break;
|
||||
|
||||
case { } v when v.StartsWith(lnaddress1):
|
||||
@ -2294,6 +2481,7 @@ namespace BTCPayServer.Tests
|
||||
lnaddress1 = m["text/identifier"];
|
||||
Assert.Equal(1, request.MinSendable.ToDecimal(LightMoneyUnit.Satoshi));
|
||||
Assert.Equal(6.12m, request.MaxSendable.ToDecimal(LightMoneyUnit.BTC));
|
||||
callbacks.Add(request.Callback);
|
||||
break;
|
||||
default:
|
||||
Assert.False(true, "Should have matched");
|
||||
@ -2301,12 +2489,24 @@ namespace BTCPayServer.Tests
|
||||
}
|
||||
}
|
||||
var repo = s.Server.PayTester.GetService<InvoiceRepository>();
|
||||
|
||||
var invoices = await repo.GetInvoices(new InvoiceQuery() { StoreId = new[] { s.StoreId } });
|
||||
// Resolving a ln address shouldn't create any btcpay invoice.
|
||||
// This must be done because some NOST clients resolve ln addresses preemptively without user interaction
|
||||
Assert.Empty(invoices);
|
||||
|
||||
// Calling the callbacks should create the invoices
|
||||
foreach (var callback in callbacks)
|
||||
{
|
||||
using var r = await s.Server.PayTester.HttpClient.GetAsync(callback);
|
||||
await r.Content.ReadAsStringAsync();
|
||||
}
|
||||
invoices = await repo.GetInvoices(new InvoiceQuery() { StoreId = new[] { s.StoreId } });
|
||||
Assert.Equal(2, invoices.Length);
|
||||
var emailSuffix = $"@{s.Server.PayTester.HostName}:{s.Server.PayTester.Port}";
|
||||
foreach (var i in invoices)
|
||||
{
|
||||
var lightningPaymentMethod = i.GetPaymentMethod(new PaymentMethodId("BTC", LNURLPayPaymentType.Instance));
|
||||
var lightningPaymentMethod = i.GetPaymentMethod(new PaymentMethodId("BTC", PaymentTypes.LNURLPay));
|
||||
var paymentMethodDetails =
|
||||
lightningPaymentMethod.GetPaymentMethodDetails() as LNURLPayPaymentMethodDetails;
|
||||
Assert.Contains(
|
||||
|
@ -290,9 +290,9 @@ retry:
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanGetRateCryptoCurrenciesByDefault()
|
||||
public async Task CanGetRateCryptoCurrenciesByDefault()
|
||||
{
|
||||
string[] brokenShitcoins = { "BTX_USD", "CHC_USD" };
|
||||
string[] brokenShitcoins = { };
|
||||
var provider = new BTCPayNetworkProvider(ChainName.Mainnet);
|
||||
var factory = FastTests.CreateBTCPayRateFactory();
|
||||
var fetcher = new RateFetcher(factory);
|
||||
@ -305,15 +305,37 @@ retry:
|
||||
var result = fetcher.FetchRates(pairs, rules, default);
|
||||
foreach ((CurrencyPair key, Task<RateResult> value) in result)
|
||||
{
|
||||
var rateResult = value.GetAwaiter().GetResult();
|
||||
var rateResult = await value;
|
||||
TestLogs.LogInformation($"Testing {key}");
|
||||
if (brokenShitcoins.Contains(key.ToString()))
|
||||
continue;
|
||||
Assert.True(rateResult.BidAsk != null, $"Impossible to get the rate {rateResult.EvaluatedRule}");
|
||||
}
|
||||
|
||||
var b = new StoreBlob();
|
||||
foreach (var k in StoreBlob.RecommendedExchanges)
|
||||
{
|
||||
b.DefaultCurrency = k.Key;
|
||||
rules = b.GetDefaultRateRules(provider);
|
||||
pairs =
|
||||
provider.GetAll()
|
||||
.Select(c => new CurrencyPair(c.CryptoCode, k.Key))
|
||||
.ToHashSet();
|
||||
result = fetcher.FetchRates(pairs, rules, default);
|
||||
foreach ((CurrencyPair key, Task<RateResult> value) in result)
|
||||
{
|
||||
var rateResult = await value;
|
||||
TestLogs.LogInformation($"Testing {key} when default currency is {k.Key}");
|
||||
if (brokenShitcoins.Contains(key.ToString()))
|
||||
continue;
|
||||
Assert.True(rateResult.BidAsk != null, $"Impossible to get the rate {rateResult.EvaluatedRule}");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Fast", "Fast")]
|
||||
public async Task CheckJsContent()
|
||||
{
|
||||
// This test verify that no malicious js is added in the minified files.
|
||||
@ -322,47 +344,63 @@ retry:
|
||||
var actual = GetFileContent("BTCPayServer", "wwwroot", "vendor", "bootstrap", "bootstrap.bundle.min.js").Trim();
|
||||
var version = Regex.Match(actual, "Bootstrap v([0-9]+.[0-9]+.[0-9]+)").Groups[1].Value;
|
||||
var expected = (await (await client.GetAsync($"https://cdn.jsdelivr.net/npm/bootstrap@{version}/dist/js/bootstrap.bundle.min.js")).Content.ReadAsStringAsync()).Trim();
|
||||
Assert.Equal(expected, actual);
|
||||
EqualJsContent(expected, actual);
|
||||
|
||||
actual = GetFileContent("BTCPayServer", "wwwroot", "vendor", "clipboard.js", "clipboard.js");
|
||||
expected = (await (await client.GetAsync("https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.8/clipboard.js")).Content.ReadAsStringAsync()).Trim();
|
||||
Assert.Equal(expected, actual);
|
||||
EqualJsContent(expected, actual);
|
||||
|
||||
actual = GetFileContent("BTCPayServer", "wwwroot", "vendor", "vuejs", "vue.min.js").Trim();
|
||||
version = Regex.Match(actual, "Vue\\.js v([0-9]+.[0-9]+.[0-9]+)").Groups[1].Value;
|
||||
expected = (await (await client.GetAsync($"https://cdnjs.cloudflare.com/ajax/libs/vue/{version}/vue.min.js")).Content.ReadAsStringAsync()).Trim();
|
||||
Assert.Equal(expected, actual);
|
||||
EqualJsContent(expected, actual);
|
||||
|
||||
actual = GetFileContent("BTCPayServer", "wwwroot", "vendor", "i18next", "i18next.min.js").Trim();
|
||||
expected = (await (await client.GetAsync("https://cdnjs.cloudflare.com/ajax/libs/i18next/22.0.6/i18next.min.js")).Content.ReadAsStringAsync()).Trim();
|
||||
Assert.Equal(expected, actual);
|
||||
EqualJsContent(expected, actual);
|
||||
|
||||
actual = GetFileContent("BTCPayServer", "wwwroot", "vendor", "i18next", "i18nextHttpBackend.min.js").Trim();
|
||||
expected = (await (await client.GetAsync("https://cdnjs.cloudflare.com/ajax/libs/i18next-http-backend/2.0.1/i18nextHttpBackend.min.js")).Content.ReadAsStringAsync()).Trim();
|
||||
Assert.Equal(expected, actual);
|
||||
EqualJsContent(expected, actual);
|
||||
|
||||
actual = GetFileContent("BTCPayServer", "wwwroot", "vendor", "i18next", "vue-i18next.js").Trim();
|
||||
expected = (await (await client.GetAsync("https://unpkg.com/@panter/vue-i18next@0.15.2/dist/vue-i18next.js")).Content.ReadAsStringAsync()).Trim();
|
||||
Assert.Equal(expected, actual);
|
||||
EqualJsContent(expected, actual);
|
||||
|
||||
actual = GetFileContent("BTCPayServer", "wwwroot", "vendor", "vue-qrcode", "vue-qrcode.min.js").Trim();
|
||||
version = Regex.Match(actual, "vue-qrcode v([0-9]+.[0-9]+.[0-9]+)").Groups[1].Value;
|
||||
expected = (await (await client.GetAsync($"https://unpkg.com/@chenfengyuan/vue-qrcode@{version}/dist/vue-qrcode.min.js")).Content.ReadAsStringAsync()).Trim();
|
||||
Assert.Equal(expected, actual);
|
||||
EqualJsContent(expected, actual);
|
||||
|
||||
actual = GetFileContent("BTCPayServer", "wwwroot", "vendor", "tom-select", "tom-select.complete.min.js").Trim();
|
||||
expected = (await (await client.GetAsync($"https://cdn.jsdelivr.net/npm/tom-select@2.2.2/dist/js/tom-select.complete.min.js")).Content.ReadAsStringAsync()).Trim();
|
||||
Assert.Equal(expected, actual);
|
||||
EqualJsContent(expected, actual);
|
||||
|
||||
actual = GetFileContent("BTCPayServer", "wwwroot", "vendor", "dom-confetti", "dom-confetti.min.js").Trim();
|
||||
version = Regex.Match(actual, "Original file: /npm/dom-confetti@([0-9]+.[0-9]+.[0-9]+)/lib/main.js").Groups[1].Value;
|
||||
expected = (await (await client.GetAsync($"https://cdn.jsdelivr.net/npm/dom-confetti@{version}/lib/main.min.js")).Content.ReadAsStringAsync()).Trim();
|
||||
Assert.Equal(expected, actual);
|
||||
EqualJsContent(expected, actual);
|
||||
|
||||
actual = GetFileContent("BTCPayServer", "wwwroot", "vendor", "vue-sortable", "sortable.min.js").Trim();
|
||||
version = Regex.Match(actual, "Sortable ([0-9]+.[0-9]+.[0-9]+) ").Groups[1].Value;
|
||||
expected = (await (await client.GetAsync($"https://unpkg.com/sortablejs@{version}/Sortable.min.js")).Content.ReadAsStringAsync()).Trim();
|
||||
Assert.Equal(expected, actual);
|
||||
EqualJsContent(expected, actual);
|
||||
|
||||
actual = GetFileContent("BTCPayServer", "wwwroot", "vendor", "bootstrap-vue", "bootstrap-vue.min.js").Trim();
|
||||
version = Regex.Match(actual, "BootstrapVue ([0-9]+.[0-9]+.[0-9]+)").Groups[1].Value;
|
||||
expected = (await (await client.GetAsync($"https://cdnjs.cloudflare.com/ajax/libs/bootstrap-vue/{version}/bootstrap-vue.min.js")).Content.ReadAsStringAsync()).Trim();
|
||||
EqualJsContent(expected, actual);
|
||||
|
||||
actual = GetFileContent("BTCPayServer", "wwwroot", "vendor", "vue-sanitize-directive", "vue-sanitize-directive.umd.min.js").Trim();
|
||||
version = Regex.Match(actual, "Original file: /npm/vue-sanitize-directive@([0-9]+.[0-9]+.[0-9]+)").Groups[1].Value;
|
||||
expected = (await (await client.GetAsync($"https://cdn.jsdelivr.net/npm/vue-sanitize-directive@{version}/dist/vue-sanitize-directive.umd.min.js")).Content.ReadAsStringAsync()).Trim();
|
||||
EqualJsContent(expected, actual);
|
||||
}
|
||||
|
||||
private void EqualJsContent(string expected, string actual)
|
||||
{
|
||||
if (expected != actual)
|
||||
Assert.Equal(expected, actual.ReplaceLineEndings("\n"));
|
||||
}
|
||||
|
||||
string GetFileContent(params string[] path)
|
||||
|
@ -39,6 +39,7 @@ using BTCPayServer.Plugins.PayButton;
|
||||
using BTCPayServer.Plugins.PointOfSale;
|
||||
using BTCPayServer.Plugins.PointOfSale.Controllers;
|
||||
using BTCPayServer.Security.Bitpay;
|
||||
using BTCPayServer.Security.Greenfield;
|
||||
using BTCPayServer.Services;
|
||||
using BTCPayServer.Services.Apps;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
@ -718,7 +719,7 @@ namespace BTCPayServer.Tests
|
||||
btcDerivationScheme.GetDerivation(new KeyPath("0/90")).ScriptPubKey, Money.Coins(1.0m));
|
||||
tester.ExplorerNode.Generate(1);
|
||||
var transactions = Assert.IsType<ListTransactionsViewModel>(Assert
|
||||
.IsType<ViewResult>(walletController.WalletTransactions(walletId).Result).Model);
|
||||
.IsType<ViewResult>(walletController.WalletTransactions(walletId, loadTransactions: true).Result).Model);
|
||||
Assert.Empty(transactions.Transactions);
|
||||
|
||||
Assert.IsType<RedirectToActionResult>(walletController.WalletRescan(walletId, rescan).Result);
|
||||
@ -747,7 +748,7 @@ namespace BTCPayServer.Tests
|
||||
Assert.NotNull(rescan.TimeOfScan);
|
||||
Assert.Equal(1, rescan.LastSuccess.Found);
|
||||
transactions = Assert.IsType<ListTransactionsViewModel>(Assert
|
||||
.IsType<ViewResult>(walletController.WalletTransactions(walletId).Result).Model);
|
||||
.IsType<ViewResult>(walletController.WalletTransactions(walletId, loadTransactions: true).Result).Model);
|
||||
var tx = Assert.Single(transactions.Transactions);
|
||||
Assert.Equal(tx.Id, txId.ToString());
|
||||
|
||||
@ -762,7 +763,7 @@ namespace BTCPayServer.Tests
|
||||
await walletController.ModifyTransaction(walletId, tx.Id, addcomment: "hello"));
|
||||
|
||||
transactions = Assert.IsType<ListTransactionsViewModel>(Assert
|
||||
.IsType<ViewResult>(walletController.WalletTransactions(walletId).Result).Model);
|
||||
.IsType<ViewResult>(walletController.WalletTransactions(walletId, loadTransactions: true).Result).Model);
|
||||
tx = Assert.Single(transactions.Transactions);
|
||||
|
||||
Assert.Equal("hello", tx.Comment);
|
||||
@ -774,7 +775,7 @@ namespace BTCPayServer.Tests
|
||||
await walletController.ModifyTransaction(walletId, tx.Id, removelabel: "test2"));
|
||||
|
||||
transactions = Assert.IsType<ListTransactionsViewModel>(Assert
|
||||
.IsType<ViewResult>(walletController.WalletTransactions(walletId).Result).Model);
|
||||
.IsType<ViewResult>(walletController.WalletTransactions(walletId, loadTransactions: true).Result).Model);
|
||||
tx = Assert.Single(transactions.Transactions);
|
||||
|
||||
Assert.Equal("hello", tx.Comment);
|
||||
@ -1329,7 +1330,7 @@ namespace BTCPayServer.Tests
|
||||
var invoiceAddress = BitcoinAddress.Create(btcmethod.Destination, cashCow.Network);
|
||||
|
||||
|
||||
var btc = new PaymentMethodId("BTC", BitcoinPaymentType.Instance);
|
||||
var btc = new PaymentMethodId("BTC", PaymentTypes.BTCLike);
|
||||
var networkFee = (await tester.PayTester.InvoiceRepository.GetInvoice(invoice.Id))
|
||||
.GetPaymentMethods()[btc]
|
||||
.GetPaymentMethodDetails()
|
||||
@ -1484,8 +1485,8 @@ namespace BTCPayServer.Tests
|
||||
await user.RegisterLightningNodeAsync("BTC");
|
||||
|
||||
|
||||
var lnMethod = new PaymentMethodId("BTC", LightningPaymentType.Instance).ToString();
|
||||
var btcMethod = new PaymentMethodId("BTC", BitcoinPaymentType.Instance).ToString();
|
||||
var lnMethod = new PaymentMethodId("BTC", PaymentTypes.LightningLike).ToString();
|
||||
var btcMethod = new PaymentMethodId("BTC", PaymentTypes.BTCLike).ToString();
|
||||
|
||||
// We allow BTC and LN, but not BTC under 5 USD, so only LN should be in the invoice
|
||||
var vm = Assert.IsType<CheckoutAppearanceViewModel>(Assert
|
||||
@ -1510,7 +1511,7 @@ namespace BTCPayServer.Tests
|
||||
}, Facade.Merchant);
|
||||
|
||||
Assert.Single(invoice.CryptoInfo);
|
||||
Assert.Equal(LightningPaymentType.Instance.ToString(), invoice.CryptoInfo[0].PaymentType);
|
||||
Assert.Equal(PaymentTypes.LightningLike.ToString(), invoice.CryptoInfo[0].PaymentType);
|
||||
|
||||
// Let's replicate https://github.com/btcpayserver/btcpayserver/issues/2963
|
||||
// We allow BTC for more than 5 USD, and LN for less than 150. The default is LN, so the default
|
||||
@ -1643,7 +1644,7 @@ namespace BTCPayServer.Tests
|
||||
Currency = "USD"
|
||||
}, Facade.Merchant);
|
||||
Assert.Single(invoice.CryptoInfo);
|
||||
Assert.Equal(LightningPaymentType.Instance.ToString(), invoice.CryptoInfo[0].PaymentType);
|
||||
Assert.Equal(PaymentTypes.LightningLike.ToString(), invoice.CryptoInfo[0].PaymentType);
|
||||
|
||||
// Activating LNUrl, we should still have only 1 payment criteria that can be set.
|
||||
user.RegisterLightningNode(cryptoCode);
|
||||
@ -1807,7 +1808,7 @@ namespace BTCPayServer.Tests
|
||||
public async Task CanChangeNetworkFeeMode()
|
||||
{
|
||||
using var tester = CreateServerTester();
|
||||
var btc = new PaymentMethodId("BTC", BitcoinPaymentType.Instance);
|
||||
var btc = new PaymentMethodId("BTC", PaymentTypes.BTCLike);
|
||||
await tester.StartAsync();
|
||||
var user = tester.NewAccount();
|
||||
user.GrantAccess();
|
||||
@ -1984,6 +1985,7 @@ namespace BTCPayServer.Tests
|
||||
var user = tester.NewAccount();
|
||||
user.GrantAccess(true);
|
||||
user.RegisterDerivationScheme("BTC");
|
||||
var btcpayClient = await user.CreateClient();
|
||||
|
||||
DateTimeOffset expiration = DateTimeOffset.UtcNow + TimeSpan.FromMinutes(21);
|
||||
|
||||
@ -2064,6 +2066,20 @@ namespace BTCPayServer.Tests
|
||||
|
||||
var zeroInvoicePM = await greenfield.GetInvoicePaymentMethods(user.StoreId, zeroInvoice.Id);
|
||||
Assert.Empty(zeroInvoicePM);
|
||||
|
||||
var invoice6 = await btcpayClient.CreateInvoice(user.StoreId,
|
||||
new CreateInvoiceRequest()
|
||||
{
|
||||
Amount = GreenfieldConstants.MaxAmount,
|
||||
Currency = "USD"
|
||||
});
|
||||
var repo = tester.PayTester.GetService<InvoiceRepository>();
|
||||
var entity = (await repo.GetInvoice(invoice6.Id));
|
||||
Assert.Equal((decimal)ulong.MaxValue, entity.Price);
|
||||
entity.GetPaymentMethods().First().Calculate();
|
||||
// Shouldn't be possible as we clamp the value, but existing invoice may have that
|
||||
entity.Price = decimal.MaxValue;
|
||||
entity.GetPaymentMethods().First().Calculate();
|
||||
}
|
||||
|
||||
[Fact(Timeout = LongRunningTestTimeout)]
|
||||
@ -2242,7 +2258,7 @@ namespace BTCPayServer.Tests
|
||||
c =>
|
||||
{
|
||||
Assert.False(c.AfterExpiration);
|
||||
Assert.Equal(new PaymentMethodId("BTC", BitcoinPaymentType.Instance).ToStringNormalized(), c.PaymentMethod);
|
||||
Assert.Equal(new PaymentMethodId("BTC", PaymentTypes.BTCLike).ToStringNormalized(), c.PaymentMethod);
|
||||
Assert.NotNull(c.Payment);
|
||||
Assert.Equal(invoice.BitcoinAddress, c.Payment.Destination);
|
||||
Assert.StartsWith(txId.ToString(), c.Payment.Id);
|
||||
@ -2252,7 +2268,7 @@ namespace BTCPayServer.Tests
|
||||
c =>
|
||||
{
|
||||
Assert.False(c.AfterExpiration);
|
||||
Assert.Equal(new PaymentMethodId("BTC", BitcoinPaymentType.Instance).ToStringNormalized(), c.PaymentMethod);
|
||||
Assert.Equal(new PaymentMethodId("BTC", PaymentTypes.BTCLike).ToStringNormalized(), c.PaymentMethod);
|
||||
Assert.NotNull(c.Payment);
|
||||
Assert.Equal(invoice.BitcoinAddress, c.Payment.Destination);
|
||||
Assert.StartsWith(txId.ToString(), c.Payment.Id);
|
||||
|
@ -73,7 +73,7 @@ services:
|
||||
- "sshd_datadir:/root/.ssh"
|
||||
|
||||
devlnd:
|
||||
image: btcpayserver/bitcoin:24.1-1
|
||||
image: btcpayserver/bitcoin:25.0
|
||||
environment:
|
||||
BITCOIN_NETWORK: regtest
|
||||
BITCOIN_WALLETDIR: "/data/wallets"
|
||||
@ -135,7 +135,7 @@ services:
|
||||
|
||||
bitcoind:
|
||||
restart: unless-stopped
|
||||
image: btcpayserver/bitcoin:24.1-1
|
||||
image: btcpayserver/bitcoin:25.0
|
||||
environment:
|
||||
BITCOIN_NETWORK: regtest
|
||||
BITCOIN_WALLETDIR: "/data/wallets"
|
||||
@ -224,7 +224,7 @@ services:
|
||||
- "5432"
|
||||
|
||||
merchant_lnd:
|
||||
image: btcpayserver/lnd:v0.16.2-beta
|
||||
image: btcpayserver/lnd:v0.16.4-beta
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
LND_CHAIN: "btc"
|
||||
@ -259,7 +259,7 @@ services:
|
||||
- bitcoind
|
||||
|
||||
customer_lnd:
|
||||
image: btcpayserver/lnd:v0.16.2-beta
|
||||
image: btcpayserver/lnd:v0.16.4-beta
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
LND_CHAIN: "btc"
|
||||
|
@ -70,7 +70,7 @@ services:
|
||||
- "sshd_datadir:/root/.ssh"
|
||||
|
||||
devlnd:
|
||||
image: btcpayserver/bitcoin:24.1-1
|
||||
image: btcpayserver/bitcoin:25.0
|
||||
environment:
|
||||
BITCOIN_NETWORK: regtest
|
||||
BITCOIN_WALLETDIR: "/data/wallets"
|
||||
@ -121,7 +121,7 @@ services:
|
||||
|
||||
bitcoind:
|
||||
restart: unless-stopped
|
||||
image: btcpayserver/bitcoin:24.1-1
|
||||
image: btcpayserver/bitcoin:25.0
|
||||
environment:
|
||||
BITCOIN_NETWORK: regtest
|
||||
BITCOIN_WALLETDIR: "/data/wallets"
|
||||
@ -211,7 +211,7 @@ services:
|
||||
- "5432"
|
||||
|
||||
merchant_lnd:
|
||||
image: btcpayserver/lnd:v0.16.2-beta
|
||||
image: btcpayserver/lnd:v0.16.4-beta
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
LND_CHAIN: "btc"
|
||||
@ -248,7 +248,7 @@ services:
|
||||
- bitcoind
|
||||
|
||||
customer_lnd:
|
||||
image: btcpayserver/lnd:v0.16.2-beta
|
||||
image: btcpayserver/lnd:v0.16.4-beta
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
LND_CHAIN: "btc"
|
||||
|
@ -48,7 +48,7 @@
|
||||
<PackageReference Include="YamlDotNet" Version="8.0.0" />
|
||||
<PackageReference Include="BIP78.Sender" Version="0.2.2" />
|
||||
<PackageReference Include="BTCPayServer.Hwi" Version="2.0.2" />
|
||||
<PackageReference Include="BTCPayServer.Lightning.All" Version="1.4.26" />
|
||||
<PackageReference Include="BTCPayServer.Lightning.All" Version="1.4.28" />
|
||||
<PackageReference Include="CsvHelper" Version="15.0.5" />
|
||||
<PackageReference Include="Dapper" Version="2.0.123" />
|
||||
<PackageReference Include="Fido2" Version="2.0.2" />
|
||||
|
@ -40,7 +40,7 @@ public class AppTopItems : ViewComponent
|
||||
var app = HttpContext.GetAppData();
|
||||
var entries = await _appService.GetItemStats(app);
|
||||
vm.SalesCount = entries.Select(e => e.SalesCount).ToList();
|
||||
vm.Entries = entries.ToList();
|
||||
vm.Entries = entries.Take(5).ToList();
|
||||
vm.AppType = app.AppType;
|
||||
vm.AppUrl = await appBaseType.ConfigureLink(app);
|
||||
vm.Name = app.Name;
|
||||
|
@ -88,7 +88,7 @@ public class StoreLightningBalance : ViewComponent
|
||||
private ILightningClient GetLightningClient(StoreData store, string cryptoCode)
|
||||
{
|
||||
var network = _networkProvider.GetNetwork<BTCPayNetwork>(cryptoCode);
|
||||
var id = new PaymentMethodId(cryptoCode, LightningPaymentType.Instance);
|
||||
var id = new PaymentMethodId(cryptoCode, PaymentTypes.LightningLike);
|
||||
var existing = store.GetSupportedPaymentMethods(_networkProvider)
|
||||
.OfType<LightningSupportedPaymentMethod>()
|
||||
.FirstOrDefault(d => d.PaymentId == id);
|
||||
|
@ -3,6 +3,7 @@
|
||||
@using BTCPayServer.Services
|
||||
@using BTCPayServer.Services.Invoices
|
||||
@inject DisplayFormatter DisplayFormatter
|
||||
@inject PaymentMethodHandlerDictionary PaymentMethodHandlerDictionary
|
||||
@model BTCPayServer.Components.StoreRecentInvoices.StoreRecentInvoicesViewModel
|
||||
|
||||
<div class="widget store-recent-invoices" id="StoreRecentInvoices-@Model.Store.Id">
|
||||
@ -51,19 +52,41 @@
|
||||
<a asp-controller="UIInvoice" asp-action="Invoice" asp-route-invoiceId="@invoice.InvoiceId" class="text-break">@invoice.InvoiceId</a>
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge badge-@invoice.Status.Status.ToModernStatus().ToString().ToLower()">
|
||||
@invoice.Status.Status.ToModernStatus().ToString()
|
||||
@if (invoice.Status.ExceptionStatus != InvoiceExceptionStatus.None)
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
@if (invoice.Details.Archived)
|
||||
{
|
||||
@($"({invoice.Status.ExceptionStatus.ToString()})")
|
||||
<span class="badge bg-warning">archived</span>
|
||||
}
|
||||
</span>
|
||||
@if (invoice.HasRefund)
|
||||
{
|
||||
<span class="badge bg-warning">
|
||||
Refund
|
||||
<span class="badge badge-@invoice.Status.Status.ToModernStatus().ToString().ToLower()">
|
||||
@invoice.Status.Status.ToModernStatus().ToString()
|
||||
@if (invoice.Status.ExceptionStatus != InvoiceExceptionStatus.None)
|
||||
{
|
||||
@($"({invoice.Status.ExceptionStatus.ToString()})")
|
||||
}
|
||||
</span>
|
||||
}
|
||||
@foreach (var paymentMethodId in invoice.Details.Payments.Select(payment => payment.GetPaymentMethodId()).Distinct())
|
||||
{
|
||||
var image = PaymentMethodHandlerDictionary[paymentMethodId]?.GetCryptoImage(paymentMethodId);
|
||||
var badge = paymentMethodId.PaymentType.GetBadge();
|
||||
if (!string.IsNullOrEmpty(image) || !string.IsNullOrEmpty(badge))
|
||||
{
|
||||
<span class="d-inline-flex align-items-center gap-1">
|
||||
@if (!string.IsNullOrEmpty(image))
|
||||
{
|
||||
<img src="@Context.Request.GetRelativePathOrAbsolute(image)" alt="@paymentMethodId.PaymentType.ToString()" style="height:1.5em" />
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(badge))
|
||||
{
|
||||
@badge
|
||||
}
|
||||
</span>
|
||||
}
|
||||
}
|
||||
@if (invoice.HasRefund)
|
||||
{
|
||||
<span class="badge bg-warning">Refund</span>
|
||||
}
|
||||
</div>
|
||||
</td>
|
||||
<td class="text-end">
|
||||
<span data-sensitive>@DisplayFormatter.Currency(invoice.Amount, invoice.Currency)</span>
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using BTCPayServer.Models.InvoicingModels;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
|
||||
namespace BTCPayServer.Components.StoreRecentInvoices;
|
||||
@ -11,5 +12,7 @@ public class StoreRecentInvoiceViewModel
|
||||
public string Currency { get; set; }
|
||||
public InvoiceState Status { get; set; }
|
||||
public DateTimeOffset Date { get; set; }
|
||||
|
||||
public InvoiceDetailsModel Details { get; set; }
|
||||
public bool HasRefund { get; set; }
|
||||
}
|
||||
|
@ -3,11 +3,13 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.Models.InvoicingModels;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
using BTCPayServer.Services.Rates;
|
||||
using BTCPayServer.Services.Stores;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using NBitcoin;
|
||||
|
||||
namespace BTCPayServer.Components.StoreRecentInvoices;
|
||||
|
||||
@ -53,17 +55,22 @@ public class StoreRecentInvoices : ViewComponent
|
||||
});
|
||||
|
||||
vm.Invoices = (from invoice in invoiceEntities
|
||||
let state = invoice.GetInvoiceState()
|
||||
select new StoreRecentInvoiceViewModel
|
||||
{
|
||||
Date = invoice.InvoiceTime,
|
||||
Status = state,
|
||||
HasRefund = invoice.Refunds.Any(),
|
||||
InvoiceId = invoice.Id,
|
||||
OrderId = invoice.Metadata.OrderId ?? string.Empty,
|
||||
Amount = invoice.Price,
|
||||
Currency = invoice.Currency
|
||||
}).ToList();
|
||||
let state = invoice.GetInvoiceState()
|
||||
select new StoreRecentInvoiceViewModel
|
||||
{
|
||||
Date = invoice.InvoiceTime,
|
||||
Status = state,
|
||||
HasRefund = invoice.Refunds.Any(),
|
||||
InvoiceId = invoice.Id,
|
||||
OrderId = invoice.Metadata.OrderId ?? string.Empty,
|
||||
Amount = invoice.Price,
|
||||
Currency = invoice.Currency,
|
||||
Details = new InvoiceDetailsModel
|
||||
{
|
||||
Archived = invoice.Archived,
|
||||
Payments = invoice.GetPayments(false)
|
||||
}
|
||||
}).ToList();
|
||||
|
||||
return View(vm);
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ public class StoreRecentTransactions : ViewComponent
|
||||
{
|
||||
var network = derivationSettings.Network;
|
||||
var wallet = _walletProvider.GetWallet(network);
|
||||
var allTransactions = await wallet.FetchTransactionHistory(derivationSettings.AccountDerivation, 0, 5, TimeSpan.FromDays(31.0));
|
||||
var allTransactions = await wallet.FetchTransactionHistory(derivationSettings.AccountDerivation, 0, 5, TimeSpan.FromDays(31.0), cancellationToken: this.HttpContext.RequestAborted);
|
||||
var walletTransactionsInfo = await _walletRepository.GetWalletTransactionsInfo(vm.WalletId, allTransactions.Select(t => t.TransactionId.ToString()).ToArray());
|
||||
|
||||
transactions = allTransactions
|
||||
|
@ -9,7 +9,6 @@ using BTCPayServer.Abstractions.Constants;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.Filters;
|
||||
using BTCPayServer.Models;
|
||||
using BTCPayServer.Payments;
|
||||
using BTCPayServer.Rating;
|
||||
using BTCPayServer.Security;
|
||||
using BTCPayServer.Security.Bitpay;
|
||||
@ -31,7 +30,6 @@ namespace BTCPayServer.Controllers
|
||||
readonly BTCPayNetworkProvider _networkProvider;
|
||||
readonly CurrencyNameTable _currencyNameTable;
|
||||
readonly StoreRepository _storeRepo;
|
||||
private readonly PaymentTypeRegistry _paymentTypeRegistry;
|
||||
|
||||
private StoreData CurrentStore => HttpContext.GetStoreData();
|
||||
|
||||
@ -39,13 +37,12 @@ namespace BTCPayServer.Controllers
|
||||
RateFetcher rateProviderFactory,
|
||||
BTCPayNetworkProvider networkProvider,
|
||||
StoreRepository storeRepo,
|
||||
CurrencyNameTable currencyNameTable, PaymentTypeRegistry paymentTypeRegistry)
|
||||
CurrencyNameTable currencyNameTable)
|
||||
{
|
||||
_rateProviderFactory = rateProviderFactory ?? throw new ArgumentNullException(nameof(rateProviderFactory));
|
||||
_networkProvider = networkProvider;
|
||||
_storeRepo = storeRepo;
|
||||
_currencyNameTable = currencyNameTable ?? throw new ArgumentNullException(nameof(currencyNameTable));
|
||||
_paymentTypeRegistry = paymentTypeRegistry;
|
||||
}
|
||||
|
||||
[Route("rates/{baseCurrency}")]
|
||||
@ -53,7 +50,7 @@ namespace BTCPayServer.Controllers
|
||||
[BitpayAPIConstraint]
|
||||
public async Task<IActionResult> GetBaseCurrencyRates(string baseCurrency, CancellationToken cancellationToken)
|
||||
{
|
||||
var supportedMethods = CurrentStore.GetSupportedPaymentMethods(_networkProvider, _paymentTypeRegistry);
|
||||
var supportedMethods = CurrentStore.GetSupportedPaymentMethods(_networkProvider);
|
||||
|
||||
var currencyCodes = supportedMethods.Where(method => !string.IsNullOrEmpty(method.PaymentId.CryptoCode))
|
||||
.Select(method => method.PaymentId.CryptoCode).Distinct();
|
||||
|
@ -50,17 +50,14 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
private readonly CustodianAccountRepository _custodianAccountRepository;
|
||||
private readonly IEnumerable<ICustodian> _custodianRegistry;
|
||||
private readonly IAuthorizationService _authorizationService;
|
||||
private readonly PaymentTypeRegistry _paymentTypeRegistry;
|
||||
|
||||
public GreenfieldCustodianAccountController(CustodianAccountRepository custodianAccountRepository,
|
||||
IEnumerable<ICustodian> custodianRegistry,
|
||||
IAuthorizationService authorizationService,
|
||||
PaymentTypeRegistry paymentTypeRegistry)
|
||||
IAuthorizationService authorizationService)
|
||||
{
|
||||
_custodianAccountRepository = custodianAccountRepository;
|
||||
_custodianRegistry = custodianRegistry;
|
||||
_authorizationService = authorizationService;
|
||||
_paymentTypeRegistry = paymentTypeRegistry;
|
||||
}
|
||||
|
||||
[HttpGet("~/api/v1/stores/{storeId}/custodian-accounts")]
|
||||
@ -226,8 +223,8 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
|
||||
if (custodian is ICanDeposit depositableCustodian)
|
||||
{
|
||||
var pm = _paymentTypeRegistry.TryParsePaymentMethod(paymentMethod, out _);
|
||||
if (!pm)
|
||||
var pm = PaymentMethodId.TryParse(paymentMethod);
|
||||
if (pm == null)
|
||||
{
|
||||
return this.CreateAPIError(400, "unsupported-payment-method",
|
||||
$"Unsupported payment method.");
|
||||
@ -349,7 +346,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
|
||||
if (custodian is ICanWithdraw withdrawableCustodian)
|
||||
{
|
||||
var pm = _paymentTypeRegistry.TryParsePaymentMethod(request.PaymentMethod);
|
||||
var pm = PaymentMethodId.TryParse(request.PaymentMethod);
|
||||
if (pm == null)
|
||||
{
|
||||
return this.CreateAPIError(400, "unsupported-payment-method",
|
||||
@ -388,7 +385,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
|
||||
if (custodian is ICanWithdraw withdrawableCustodian)
|
||||
{
|
||||
var pm = _paymentTypeRegistry.TryParsePaymentMethod(request.PaymentMethod);
|
||||
var pm = PaymentMethodId.TryParse(request.PaymentMethod);
|
||||
if (pm == null)
|
||||
{
|
||||
return this.CreateAPIError(400, "unsupported-payment-method",
|
||||
|
@ -12,6 +12,7 @@ using BTCPayServer.Data;
|
||||
using BTCPayServer.HostedServices;
|
||||
using BTCPayServer.Payments;
|
||||
using BTCPayServer.Rating;
|
||||
using BTCPayServer.Security.Greenfield;
|
||||
using BTCPayServer.Services;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
using BTCPayServer.Services.Rates;
|
||||
@ -40,7 +41,6 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
private readonly RateFetcher _rateProvider;
|
||||
private readonly InvoiceActivator _invoiceActivator;
|
||||
private readonly ApplicationDbContextFactory _dbContextFactory;
|
||||
private readonly PaymentTypeRegistry _paymentTypeRegistry;
|
||||
|
||||
public LanguageService LanguageService { get; }
|
||||
|
||||
@ -48,8 +48,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
LinkGenerator linkGenerator, LanguageService languageService, BTCPayNetworkProvider btcPayNetworkProvider,
|
||||
CurrencyNameTable currencyNameTable, RateFetcher rateProvider,
|
||||
InvoiceActivator invoiceActivator,
|
||||
PullPaymentHostedService pullPaymentService, ApplicationDbContextFactory dbContextFactory,
|
||||
PaymentTypeRegistry paymentTypeRegistry)
|
||||
PullPaymentHostedService pullPaymentService, ApplicationDbContextFactory dbContextFactory)
|
||||
{
|
||||
_invoiceController = invoiceController;
|
||||
_invoiceRepository = invoiceRepository;
|
||||
@ -60,7 +59,6 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
_invoiceActivator = invoiceActivator;
|
||||
_pullPaymentService = pullPaymentService;
|
||||
_dbContextFactory = dbContextFactory;
|
||||
_paymentTypeRegistry = paymentTypeRegistry;
|
||||
LanguageService = languageService;
|
||||
}
|
||||
|
||||
@ -186,12 +184,16 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
{
|
||||
ModelState.AddModelError(nameof(request.Amount), "The amount should be 0 or more.");
|
||||
}
|
||||
if (request.Amount > GreenfieldConstants.MaxAmount)
|
||||
{
|
||||
ModelState.AddModelError(nameof(request.Amount), $"The amount should less than {GreenfieldConstants.MaxAmount}.");
|
||||
}
|
||||
request.Checkout ??= new CreateInvoiceRequest.CheckoutOptions();
|
||||
if (request.Checkout.PaymentMethods?.Any() is true)
|
||||
{
|
||||
for (int i = 0; i < request.Checkout.PaymentMethods.Length; i++)
|
||||
{
|
||||
if (!_paymentTypeRegistry.TryParsePaymentMethod(request.Checkout.PaymentMethods[i], out _))
|
||||
if (!PaymentMethodId.TryParse(request.Checkout.PaymentMethods[i], out _))
|
||||
{
|
||||
request.AddModelError(invoiceRequest => invoiceRequest.Checkout.PaymentMethods[i],
|
||||
"Invalid payment method", this);
|
||||
@ -338,7 +340,8 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
{
|
||||
return InvoiceNotFound();
|
||||
}
|
||||
if (_paymentTypeRegistry.TryParsePaymentMethod(paymentMethod, out var paymentMethodId))
|
||||
|
||||
if (PaymentMethodId.TryParse(paymentMethod, out var paymentMethodId))
|
||||
{
|
||||
await _invoiceActivator.ActivateInvoicePaymentMethod(paymentMethodId, invoice, store);
|
||||
return Ok();
|
||||
@ -379,7 +382,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
}
|
||||
PaymentMethod? invoicePaymentMethod = null;
|
||||
PaymentMethodId? paymentMethodId = null;
|
||||
if (request.PaymentMethod is not null && _paymentTypeRegistry.TryParsePaymentMethod(request.PaymentMethod, out paymentMethodId))
|
||||
if (request.PaymentMethod is not null && PaymentMethodId.TryParse(request.PaymentMethod, out paymentMethodId))
|
||||
{
|
||||
invoicePaymentMethod = invoice.GetPaymentMethods().SingleOrDefault(method => method.GetId() == paymentMethodId);
|
||||
}
|
||||
|
@ -28,19 +28,17 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
private readonly IOptions<LightningNetworkOptions> _lightningNetworkOptions;
|
||||
private readonly LightningClientFactoryService _lightningClientFactory;
|
||||
private readonly BTCPayNetworkProvider _btcPayNetworkProvider;
|
||||
private readonly PaymentTypeRegistry _paymentTypeRegistry;
|
||||
|
||||
public GreenfieldStoreLightningNodeApiController(
|
||||
IOptions<LightningNetworkOptions> lightningNetworkOptions,
|
||||
LightningClientFactoryService lightningClientFactory, BTCPayNetworkProvider btcPayNetworkProvider,
|
||||
PoliciesSettings policiesSettings,
|
||||
IAuthorizationService authorizationService, PaymentTypeRegistry paymentTypeRegistry) : base(
|
||||
IAuthorizationService authorizationService) : base(
|
||||
btcPayNetworkProvider, policiesSettings, authorizationService)
|
||||
{
|
||||
_lightningNetworkOptions = lightningNetworkOptions;
|
||||
_lightningClientFactory = lightningClientFactory;
|
||||
_btcPayNetworkProvider = btcPayNetworkProvider;
|
||||
_paymentTypeRegistry = paymentTypeRegistry;
|
||||
}
|
||||
|
||||
[Authorize(Policy = Policies.CanUseLightningNodeInStore,
|
||||
@ -152,8 +150,8 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
throw new JsonHttpException(StoreNotFound());
|
||||
}
|
||||
|
||||
var id = new PaymentMethodId(cryptoCode, LightningPaymentType.Instance);
|
||||
var existing = store.GetSupportedPaymentMethods(_btcPayNetworkProvider, _paymentTypeRegistry)
|
||||
var id = new PaymentMethodId(cryptoCode, PaymentTypes.LightningLike);
|
||||
var existing = store.GetSupportedPaymentMethods(_btcPayNetworkProvider)
|
||||
.OfType<LightningSupportedPaymentMethod>()
|
||||
.FirstOrDefault(d => d.PaymentId == id);
|
||||
if (existing == null)
|
||||
|
@ -255,7 +255,9 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
Email = blob.Email,
|
||||
AllowCustomPaymentAmounts = blob.AllowCustomPaymentAmounts,
|
||||
EmbeddedCSS = blob.EmbeddedCSS,
|
||||
CustomCSSLink = blob.CustomCSSLink
|
||||
CustomCSSLink = blob.CustomCSSLink,
|
||||
FormResponse = blob.FormResponse,
|
||||
FormId = blob.FormId
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,6 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
private readonly IEnumerable<IPayoutHandler> _payoutHandlers;
|
||||
private readonly BTCPayNetworkProvider _networkProvider;
|
||||
private readonly IAuthorizationService _authorizationService;
|
||||
private readonly PaymentTypeRegistry _paymentTypeRegistry;
|
||||
|
||||
public GreenfieldPullPaymentController(PullPaymentHostedService pullPaymentService,
|
||||
LinkGenerator linkGenerator,
|
||||
@ -45,8 +44,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
Services.BTCPayNetworkJsonSerializerSettings serializerSettings,
|
||||
IEnumerable<IPayoutHandler> payoutHandlers,
|
||||
BTCPayNetworkProvider btcPayNetworkProvider,
|
||||
IAuthorizationService authorizationService,
|
||||
PaymentTypeRegistry paymentTypeRegistry)
|
||||
IAuthorizationService authorizationService)
|
||||
{
|
||||
_pullPaymentService = pullPaymentService;
|
||||
_linkGenerator = linkGenerator;
|
||||
@ -56,7 +54,6 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
_payoutHandlers = payoutHandlers;
|
||||
_networkProvider = btcPayNetworkProvider;
|
||||
_authorizationService = authorizationService;
|
||||
_paymentTypeRegistry = paymentTypeRegistry;
|
||||
}
|
||||
|
||||
[HttpGet("~/api/v1/stores/{storeId}/pull-payments")]
|
||||
@ -127,7 +124,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
{
|
||||
paymentMethods = paymentMethodsStr.Select(s =>
|
||||
{
|
||||
_paymentTypeRegistry.TryParsePaymentMethod(s, out var pmi);
|
||||
PaymentMethodId.TryParse(s, out var pmi);
|
||||
return pmi;
|
||||
}).ToArray();
|
||||
var supported = (await _payoutHandlers.GetSupportedPaymentMethods(HttpContext.GetStoreData())).ToArray();
|
||||
@ -258,16 +255,15 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
return PullPaymentNotFound();
|
||||
|
||||
var blob = pp.GetBlob();
|
||||
var pms = blob.SupportedPaymentMethods.FirstOrDefault(id => id.PaymentType == LightningPaymentType.Instance && _networkProvider.DefaultNetwork.CryptoCode == id.CryptoCode);
|
||||
if (pms is not null && blob.Currency.Equals(pms.CryptoCode, StringComparison.InvariantCultureIgnoreCase))
|
||||
if (_pullPaymentService.SupportsLNURL(blob))
|
||||
{
|
||||
var lnurlEndpoint = new Uri(Url.Action("GetLNURLForPullPayment", "UILNURL", new
|
||||
{
|
||||
cryptoCode = _networkProvider.DefaultNetwork.CryptoCode,
|
||||
pullPaymentId = pullPaymentId
|
||||
pullPaymentId
|
||||
}, Request.Scheme, Request.Host.ToString())!);
|
||||
|
||||
return base.Ok(new PullPaymentLNURL()
|
||||
return base.Ok(new PullPaymentLNURL
|
||||
{
|
||||
LNURLBech32 = LNURL.LNURL.EncodeUri(lnurlEndpoint, "withdrawRequest", true).ToString(),
|
||||
LNURLUri = LNURL.LNURL.EncodeUri(lnurlEndpoint, "withdrawRequest", false).ToString()
|
||||
@ -301,7 +297,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
[AllowAnonymous]
|
||||
public async Task<IActionResult> CreatePayout(string pullPaymentId, CreatePayoutRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
if (!_paymentTypeRegistry.TryParsePaymentMethod(request?.PaymentMethod, out var paymentMethodId))
|
||||
if (!PaymentMethodId.TryParse(request?.PaymentMethod, out var paymentMethodId))
|
||||
{
|
||||
ModelState.AddModelError(nameof(request.PaymentMethod), "Invalid payment method");
|
||||
return this.CreateValidationError(ModelState);
|
||||
@ -364,7 +360,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
}
|
||||
}
|
||||
|
||||
if (request is null || !_paymentTypeRegistry.TryParsePaymentMethod(request?.PaymentMethod, out var paymentMethodId))
|
||||
if (request is null || !PaymentMethodId.TryParse(request?.PaymentMethod, out var paymentMethodId))
|
||||
{
|
||||
ModelState.AddModelError(nameof(request.PaymentMethod), "Invalid payment method");
|
||||
return this.CreateValidationError(ModelState);
|
||||
|
8
BTCPayServer/Controllers/GreenField/GreenfieldStoreAutomatedLightningPayoutProcessorsController.cs
8
BTCPayServer/Controllers/GreenField/GreenfieldStoreAutomatedLightningPayoutProcessorsController.cs
@ -24,14 +24,12 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
{
|
||||
private readonly PayoutProcessorService _payoutProcessorService;
|
||||
private readonly EventAggregator _eventAggregator;
|
||||
private readonly PaymentTypeRegistry _paymentTypeRegistry;
|
||||
|
||||
public GreenfieldStoreAutomatedLightningPayoutProcessorsController(PayoutProcessorService payoutProcessorService,
|
||||
EventAggregator eventAggregator, PaymentTypeRegistry paymentTypeRegistry)
|
||||
EventAggregator eventAggregator)
|
||||
{
|
||||
_payoutProcessorService = payoutProcessorService;
|
||||
_eventAggregator = eventAggregator;
|
||||
_paymentTypeRegistry = paymentTypeRegistry;
|
||||
}
|
||||
|
||||
[Authorize(Policy = Policies.CanViewStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||
@ -40,7 +38,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
public async Task<IActionResult> GetStoreLightningAutomatedPayoutProcessors(
|
||||
string storeId, string? paymentMethod)
|
||||
{
|
||||
paymentMethod = !string.IsNullOrEmpty(paymentMethod) ? _paymentTypeRegistry.ParsePaymentMethod(paymentMethod).ToString() : null;
|
||||
paymentMethod = !string.IsNullOrEmpty(paymentMethod) ? PaymentMethodId.Parse(paymentMethod).ToString() : null;
|
||||
var configured =
|
||||
await _payoutProcessorService.GetProcessors(
|
||||
new PayoutProcessorService.PayoutProcessorQuery()
|
||||
@ -75,7 +73,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
AutomatedPayoutConstants.ValidateInterval(ModelState, request.IntervalSeconds, nameof(request.IntervalSeconds));
|
||||
if (!ModelState.IsValid)
|
||||
return this.CreateValidationError(ModelState);
|
||||
paymentMethod = _paymentTypeRegistry.ParsePaymentMethod(paymentMethod).ToString();
|
||||
paymentMethod = PaymentMethodId.Parse(paymentMethod).ToString();
|
||||
var activeProcessor =
|
||||
(await _payoutProcessorService.GetProcessors(
|
||||
new PayoutProcessorService.PayoutProcessorQuery()
|
||||
|
@ -25,14 +25,12 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
{
|
||||
private readonly PayoutProcessorService _payoutProcessorService;
|
||||
private readonly EventAggregator _eventAggregator;
|
||||
private readonly PaymentTypeRegistry _paymentTypeRegistry;
|
||||
|
||||
public GreenfieldStoreAutomatedOnChainPayoutProcessorsController(PayoutProcessorService payoutProcessorService,
|
||||
EventAggregator eventAggregator, PaymentTypeRegistry paymentTypeRegistry)
|
||||
EventAggregator eventAggregator)
|
||||
{
|
||||
_payoutProcessorService = payoutProcessorService;
|
||||
_eventAggregator = eventAggregator;
|
||||
_paymentTypeRegistry = paymentTypeRegistry;
|
||||
}
|
||||
|
||||
[Authorize(Policy = Policies.CanViewStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||
@ -41,7 +39,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
public async Task<IActionResult> GetStoreOnChainAutomatedPayoutProcessors(
|
||||
string storeId, string? paymentMethod)
|
||||
{
|
||||
paymentMethod = !string.IsNullOrEmpty(paymentMethod) ? _paymentTypeRegistry.ParsePaymentMethod(paymentMethod).ToString() : null;
|
||||
paymentMethod = !string.IsNullOrEmpty(paymentMethod) ? PaymentMethodId.Parse(paymentMethod).ToString() : null;
|
||||
var configured =
|
||||
await _payoutProcessorService.GetProcessors(
|
||||
new PayoutProcessorService.PayoutProcessorQuery()
|
||||
@ -84,7 +82,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
ModelState.AddModelError(nameof(request.FeeBlockTarget), "The feeBlockTarget should be between 1 and 1000");
|
||||
if (!ModelState.IsValid)
|
||||
return this.CreateValidationError(ModelState);
|
||||
paymentMethod = _paymentTypeRegistry.ParsePaymentMethod(paymentMethod).ToString();
|
||||
paymentMethod = PaymentMethodId.Parse(paymentMethod).ToString();
|
||||
var activeProcessor =
|
||||
(await _payoutProcessorService.GetProcessors(
|
||||
new PayoutProcessorService.PayoutProcessorQuery()
|
||||
|
@ -32,26 +32,23 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
private StoreData Store => HttpContext.GetStoreData();
|
||||
private readonly StoreRepository _storeRepository;
|
||||
private readonly BTCPayNetworkProvider _btcPayNetworkProvider;
|
||||
private readonly PaymentTypeRegistry _paymentTypeRegistry;
|
||||
|
||||
public GreenfieldStoreLNURLPayPaymentMethodsController(
|
||||
StoreRepository storeRepository,
|
||||
BTCPayNetworkProvider btcPayNetworkProvider,
|
||||
PaymentTypeRegistry paymentTypeRegistry)
|
||||
BTCPayNetworkProvider btcPayNetworkProvider)
|
||||
{
|
||||
_storeRepository = storeRepository;
|
||||
_btcPayNetworkProvider = btcPayNetworkProvider;
|
||||
_paymentTypeRegistry = paymentTypeRegistry;
|
||||
}
|
||||
|
||||
public static IEnumerable<LNURLPayPaymentMethodData> GetLNURLPayPaymentMethods(StoreData store,
|
||||
BTCPayNetworkProvider networkProvider, bool? enabled, PaymentTypeRegistry paymentTypeRegistry)
|
||||
BTCPayNetworkProvider networkProvider, bool? enabled)
|
||||
{
|
||||
var blob = store.GetStoreBlob();
|
||||
var excludedPaymentMethods = blob.GetExcludedPaymentMethods();
|
||||
|
||||
return store.GetSupportedPaymentMethods(networkProvider, paymentTypeRegistry)
|
||||
.Where((method) => method.PaymentId.PaymentType == LNURLPayPaymentType.Instance)
|
||||
return store.GetSupportedPaymentMethods(networkProvider)
|
||||
.Where((method) => method.PaymentId.PaymentType == PaymentTypes.LNURLPay)
|
||||
.OfType<LNURLPaySupportedPaymentMethod>()
|
||||
.Select(paymentMethod =>
|
||||
new LNURLPayPaymentMethodData(
|
||||
@ -70,7 +67,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
string storeId,
|
||||
[FromQuery] bool? enabled)
|
||||
{
|
||||
return Ok(GetLNURLPayPaymentMethods(Store, _btcPayNetworkProvider, enabled, _paymentTypeRegistry));
|
||||
return Ok(GetLNURLPayPaymentMethods(Store, _btcPayNetworkProvider, enabled));
|
||||
}
|
||||
|
||||
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||
@ -96,7 +93,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
|
||||
AssertCryptoCodeWallet(cryptoCode, out _);
|
||||
|
||||
var id = new PaymentMethodId(cryptoCode, LNURLPayPaymentType.Instance);
|
||||
var id = new PaymentMethodId(cryptoCode, PaymentTypes.LNURLPay);
|
||||
var store = Store;
|
||||
store.SetSupportedPaymentMethod(id, null);
|
||||
await _storeRepository.UpdateStore(store);
|
||||
@ -108,12 +105,12 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
public async Task<IActionResult> UpdateLNURLPayPaymentMethod(string storeId, string cryptoCode,
|
||||
[FromBody] LNURLPayPaymentMethodData paymentMethodData)
|
||||
{
|
||||
var paymentMethodId = new PaymentMethodId(cryptoCode, LNURLPayPaymentType.Instance);
|
||||
var paymentMethodId = new PaymentMethodId(cryptoCode, PaymentTypes.LNURLPay);
|
||||
|
||||
AssertCryptoCodeWallet(cryptoCode, out _);
|
||||
|
||||
var lnMethod = GreenfieldStoreLightningNetworkPaymentMethodsController.GetExistingLightningLikePaymentMethod(_btcPayNetworkProvider,
|
||||
cryptoCode, Store, _paymentTypeRegistry);
|
||||
cryptoCode, Store);
|
||||
|
||||
if ((lnMethod is null || lnMethod.Enabled is false) && paymentMethodData.Enabled)
|
||||
{
|
||||
@ -144,9 +141,9 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
{
|
||||
store ??= Store;
|
||||
var storeBlob = store.GetStoreBlob();
|
||||
var id = new PaymentMethodId(cryptoCode, LNURLPayPaymentType.Instance);
|
||||
var id = new PaymentMethodId(cryptoCode, PaymentTypes.LNURLPay);
|
||||
var paymentMethod = store
|
||||
.GetSupportedPaymentMethods(_btcPayNetworkProvider, _paymentTypeRegistry)
|
||||
.GetSupportedPaymentMethods(_btcPayNetworkProvider)
|
||||
.OfType<LNURLPaySupportedPaymentMethod>()
|
||||
.FirstOrDefault(method => method.PaymentId == id);
|
||||
|
||||
|
@ -37,31 +37,28 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
private readonly StoreRepository _storeRepository;
|
||||
private readonly BTCPayNetworkProvider _btcPayNetworkProvider;
|
||||
private readonly IAuthorizationService _authorizationService;
|
||||
private readonly PaymentTypeRegistry _paymentTypeRegistry;
|
||||
|
||||
public GreenfieldStoreLightningNetworkPaymentMethodsController(
|
||||
StoreRepository storeRepository,
|
||||
BTCPayNetworkProvider btcPayNetworkProvider,
|
||||
IAuthorizationService authorizationService,
|
||||
ISettingsRepository settingsRepository,
|
||||
PoliciesSettings policiesSettings,
|
||||
PaymentTypeRegistry paymentTypeRegistry)
|
||||
PoliciesSettings policiesSettings)
|
||||
{
|
||||
_storeRepository = storeRepository;
|
||||
_btcPayNetworkProvider = btcPayNetworkProvider;
|
||||
_authorizationService = authorizationService;
|
||||
_paymentTypeRegistry = paymentTypeRegistry;
|
||||
PoliciesSettings = policiesSettings;
|
||||
}
|
||||
|
||||
public static IEnumerable<LightningNetworkPaymentMethodData> GetLightningPaymentMethods(StoreData store,
|
||||
BTCPayNetworkProvider networkProvider, bool? enabled, PaymentTypeRegistry paymentTypeRegistry)
|
||||
BTCPayNetworkProvider networkProvider, bool? enabled)
|
||||
{
|
||||
var blob = store.GetStoreBlob();
|
||||
var excludedPaymentMethods = blob.GetExcludedPaymentMethods();
|
||||
|
||||
return store.GetSupportedPaymentMethods(networkProvider, paymentTypeRegistry )
|
||||
.Where((method) => method.PaymentId.PaymentType == LightningPaymentType.Instance)
|
||||
return store.GetSupportedPaymentMethods(networkProvider)
|
||||
.Where((method) => method.PaymentId.PaymentType == PaymentTypes.LightningLike)
|
||||
.OfType<LightningSupportedPaymentMethod>()
|
||||
.Select(paymentMethod =>
|
||||
new LightningNetworkPaymentMethodData(
|
||||
@ -82,7 +79,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
string storeId,
|
||||
[FromQuery] bool? enabled)
|
||||
{
|
||||
return Ok(GetLightningPaymentMethods(Store, _btcPayNetworkProvider, enabled, _paymentTypeRegistry));
|
||||
return Ok(GetLightningPaymentMethods(Store, _btcPayNetworkProvider, enabled));
|
||||
}
|
||||
|
||||
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||
@ -91,7 +88,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
{
|
||||
AssertSupportLightning(cryptoCode);
|
||||
|
||||
var method = GetExistingLightningLikePaymentMethod(_btcPayNetworkProvider, cryptoCode, Store, _paymentTypeRegistry);
|
||||
var method = GetExistingLightningLikePaymentMethod(_btcPayNetworkProvider, cryptoCode, Store);
|
||||
if (method is null)
|
||||
{
|
||||
throw ErrorPaymentMethodNotConfigured();
|
||||
@ -113,7 +110,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
{
|
||||
AssertSupportLightning(cryptoCode);
|
||||
|
||||
var id = new PaymentMethodId(cryptoCode, LightningPaymentType.Instance);
|
||||
var id = new PaymentMethodId(cryptoCode, PaymentTypes.LightningLike);
|
||||
var store = Store;
|
||||
store.SetSupportedPaymentMethod(id, null);
|
||||
await _storeRepository.UpdateStore(store);
|
||||
@ -125,7 +122,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
public async Task<IActionResult> UpdateLightningNetworkPaymentMethod(string storeId, string cryptoCode,
|
||||
[FromBody] UpdateLightningNetworkPaymentMethodRequest request)
|
||||
{
|
||||
var paymentMethodId = new PaymentMethodId(cryptoCode, LightningPaymentType.Instance);
|
||||
var paymentMethodId = new PaymentMethodId(cryptoCode, PaymentTypes.LightningLike);
|
||||
AssertSupportLightning(cryptoCode);
|
||||
|
||||
if (string.IsNullOrEmpty(request.ConnectionString))
|
||||
@ -140,7 +137,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
LightningSupportedPaymentMethod? paymentMethod = null;
|
||||
var store = Store;
|
||||
var storeBlob = store.GetStoreBlob();
|
||||
var existing = GetExistingLightningLikePaymentMethod(_btcPayNetworkProvider, cryptoCode, store, _paymentTypeRegistry);
|
||||
var existing = GetExistingLightningLikePaymentMethod(_btcPayNetworkProvider, cryptoCode, store);
|
||||
if (existing == null || existing.ConnectionString != request.ConnectionString)
|
||||
{
|
||||
if (request.ConnectionString == LightningSupportedPaymentMethod.InternalNode)
|
||||
@ -190,17 +187,17 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
storeBlob.SetExcluded(paymentMethodId, !request.Enabled);
|
||||
store.SetStoreBlob(storeBlob);
|
||||
await _storeRepository.UpdateStore(store);
|
||||
return Ok(GetExistingLightningLikePaymentMethod(_btcPayNetworkProvider, cryptoCode, store, _paymentTypeRegistry));
|
||||
return Ok(GetExistingLightningLikePaymentMethod(_btcPayNetworkProvider, cryptoCode, store));
|
||||
}
|
||||
|
||||
public static LightningNetworkPaymentMethodData? GetExistingLightningLikePaymentMethod(BTCPayNetworkProvider btcPayNetworkProvider, string cryptoCode,
|
||||
StoreData store, PaymentTypeRegistry paymentTypeRegistry)
|
||||
StoreData store)
|
||||
{
|
||||
|
||||
var storeBlob = store.GetStoreBlob();
|
||||
var id = new PaymentMethodId(cryptoCode, LightningPaymentType.Instance);
|
||||
var id = new PaymentMethodId(cryptoCode, PaymentTypes.LightningLike);
|
||||
var paymentMethod = store
|
||||
.GetSupportedPaymentMethods(btcPayNetworkProvider, paymentTypeRegistry)
|
||||
.GetSupportedPaymentMethods(btcPayNetworkProvider)
|
||||
.OfType<LightningSupportedPaymentMethod>()
|
||||
.FirstOrDefault(method => method.PaymentId == id);
|
||||
|
||||
|
@ -86,7 +86,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
|
||||
var store = Store;
|
||||
var storeBlob = store.GetStoreBlob();
|
||||
store.SetSupportedPaymentMethod(new PaymentMethodId(cryptoCode, BitcoinPaymentType.Instance),
|
||||
store.SetSupportedPaymentMethod(new PaymentMethodId(cryptoCode, PaymentTypes.BTCLike),
|
||||
derivationSchemeSettings);
|
||||
store.SetStoreBlob(storeBlob);
|
||||
await _storeRepository.UpdateStore(store);
|
||||
|
@ -38,7 +38,6 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
private readonly IAuthorizationService _authorizationService;
|
||||
private readonly ExplorerClientProvider _explorerClientProvider;
|
||||
private readonly EventAggregator _eventAggregator;
|
||||
private readonly PaymentTypeRegistry _paymentTypeRegistry;
|
||||
|
||||
public GreenfieldStoreOnChainPaymentMethodsController(
|
||||
StoreRepository storeRepository,
|
||||
@ -47,8 +46,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
IAuthorizationService authorizationService,
|
||||
ExplorerClientProvider explorerClientProvider,
|
||||
PoliciesSettings policiesSettings,
|
||||
EventAggregator eventAggregator,
|
||||
PaymentTypeRegistry paymentTypeRegistry)
|
||||
EventAggregator eventAggregator)
|
||||
{
|
||||
_storeRepository = storeRepository;
|
||||
_btcPayNetworkProvider = btcPayNetworkProvider;
|
||||
@ -56,18 +54,17 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
_authorizationService = authorizationService;
|
||||
_explorerClientProvider = explorerClientProvider;
|
||||
_eventAggregator = eventAggregator;
|
||||
_paymentTypeRegistry = paymentTypeRegistry;
|
||||
PoliciesSettings = policiesSettings;
|
||||
}
|
||||
|
||||
public static IEnumerable<OnChainPaymentMethodData> GetOnChainPaymentMethods(StoreData store,
|
||||
BTCPayNetworkProvider networkProvider, bool? enabled, PaymentTypeRegistry paymentTypeRegistry)
|
||||
BTCPayNetworkProvider networkProvider, bool? enabled)
|
||||
{
|
||||
var blob = store.GetStoreBlob();
|
||||
var excludedPaymentMethods = blob.GetExcludedPaymentMethods();
|
||||
|
||||
return store.GetSupportedPaymentMethods(networkProvider, paymentTypeRegistry)
|
||||
.Where((method) => method.PaymentId.PaymentType == BitcoinPaymentType.Instance)
|
||||
return store.GetSupportedPaymentMethods(networkProvider)
|
||||
.Where((method) => method.PaymentId.PaymentType == PaymentTypes.BTCLike)
|
||||
.OfType<DerivationSchemeSettings>()
|
||||
.Select(strategy =>
|
||||
new OnChainPaymentMethodData(strategy.PaymentId.CryptoCode,
|
||||
@ -84,7 +81,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
string storeId,
|
||||
[FromQuery] bool? enabled)
|
||||
{
|
||||
return Ok(GetOnChainPaymentMethods(Store, _btcPayNetworkProvider, enabled, _paymentTypeRegistry));
|
||||
return Ok(GetOnChainPaymentMethods(Store, _btcPayNetworkProvider, enabled));
|
||||
}
|
||||
|
||||
[Authorize(Policy = Policies.CanViewStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||
@ -213,7 +210,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
{
|
||||
AssertCryptoCodeWallet(cryptoCode, out _, out _);
|
||||
|
||||
var id = new PaymentMethodId(cryptoCode, BitcoinPaymentType.Instance);
|
||||
var id = new PaymentMethodId(cryptoCode, PaymentTypes.BTCLike);
|
||||
var store = Store;
|
||||
store.SetSupportedPaymentMethod(id, null);
|
||||
await _storeRepository.UpdateStore(store);
|
||||
@ -231,7 +228,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
string cryptoCode,
|
||||
[FromBody] UpdateOnChainPaymentMethodRequest request)
|
||||
{
|
||||
var id = new PaymentMethodId(cryptoCode, BitcoinPaymentType.Instance);
|
||||
var id = new PaymentMethodId(cryptoCode, PaymentTypes.BTCLike);
|
||||
AssertCryptoCodeWallet(cryptoCode, out var network, out var wallet);
|
||||
|
||||
if (string.IsNullOrEmpty(request?.DerivationScheme))
|
||||
@ -296,9 +293,9 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
{
|
||||
store ??= Store;
|
||||
var storeBlob = store.GetStoreBlob();
|
||||
var id = new PaymentMethodId(cryptoCode, BitcoinPaymentType.Instance);
|
||||
var id = new PaymentMethodId(cryptoCode, PaymentTypes.BTCLike);
|
||||
var paymentMethod = store
|
||||
.GetSupportedPaymentMethods(_btcPayNetworkProvider, _paymentTypeRegistry)
|
||||
.GetSupportedPaymentMethods(_btcPayNetworkProvider)
|
||||
.OfType<DerivationSchemeSettings>()
|
||||
.FirstOrDefault(method => method.PaymentId == id);
|
||||
|
||||
|
@ -14,7 +14,6 @@ using BTCPayServer.Client.Models;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.HostedServices;
|
||||
using BTCPayServer.Models.WalletViewModels;
|
||||
using BTCPayServer.Payments;
|
||||
using BTCPayServer.Payments.PayJoin;
|
||||
using BTCPayServer.Payments.PayJoin.Sender;
|
||||
using BTCPayServer.Services;
|
||||
@ -55,7 +54,6 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
private readonly WalletReceiveService _walletReceiveService;
|
||||
private readonly IFeeProviderFactory _feeProviderFactory;
|
||||
private readonly UTXOLocker _utxoLocker;
|
||||
private readonly PaymentTypeRegistry _paymentTypeRegistry;
|
||||
|
||||
public GreenfieldStoreOnChainWalletsController(
|
||||
IAuthorizationService authorizationService,
|
||||
@ -71,8 +69,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
EventAggregator eventAggregator,
|
||||
WalletReceiveService walletReceiveService,
|
||||
IFeeProviderFactory feeProviderFactory,
|
||||
UTXOLocker utxoLocker,
|
||||
PaymentTypeRegistry paymentTypeRegistry
|
||||
UTXOLocker utxoLocker
|
||||
)
|
||||
{
|
||||
_authorizationService = authorizationService;
|
||||
@ -89,7 +86,6 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
_walletReceiveService = walletReceiveService;
|
||||
_feeProviderFactory = feeProviderFactory;
|
||||
_utxoLocker = utxoLocker;
|
||||
_paymentTypeRegistry = paymentTypeRegistry;
|
||||
}
|
||||
|
||||
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||
@ -186,7 +182,8 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
[FromQuery] TransactionStatus[]? statusFilter = null,
|
||||
[FromQuery] string? labelFilter = null,
|
||||
[FromQuery] int skip = 0,
|
||||
[FromQuery] int limit = int.MaxValue
|
||||
[FromQuery] int limit = int.MaxValue,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
if (IsInvalidWalletRequest(cryptoCode, out var network,
|
||||
@ -201,7 +198,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
if (statusFilter?.Any() is true || !string.IsNullOrWhiteSpace(labelFilter))
|
||||
preFiltering = false;
|
||||
var txs = await wallet.FetchTransactionHistory(derivationScheme.AccountDerivation, preFiltering ? skip : 0,
|
||||
preFiltering ? limit : int.MaxValue);
|
||||
preFiltering ? limit : int.MaxValue, cancellationToken: cancellationToken);
|
||||
if (!preFiltering)
|
||||
{
|
||||
var filteredList = new List<TransactionHistoryLine>(txs.Count);
|
||||
@ -805,10 +802,10 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
private DerivationSchemeSettings? GetDerivationSchemeSettings(string cryptoCode)
|
||||
{
|
||||
var paymentMethod = Store
|
||||
.GetSupportedPaymentMethods(_btcPayNetworkProvider, _paymentTypeRegistry)
|
||||
.GetSupportedPaymentMethods(_btcPayNetworkProvider)
|
||||
.OfType<DerivationSchemeSettings>()
|
||||
.FirstOrDefault(p =>
|
||||
p.PaymentId.PaymentType == Payments.BitcoinPaymentType.Instance &&
|
||||
p.PaymentId.PaymentType == Payments.PaymentTypes.BTCLike &&
|
||||
p.PaymentId.CryptoCode.Equals(cryptoCode, StringComparison.InvariantCultureIgnoreCase));
|
||||
return paymentMethod;
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ using BTCPayServer.Abstractions.Constants;
|
||||
using BTCPayServer.Client;
|
||||
using BTCPayServer.Client.Models;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.Payments;
|
||||
using BTCPayServer.Security;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Cors;
|
||||
@ -23,13 +22,11 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
private StoreData Store => HttpContext.GetStoreData();
|
||||
private readonly BTCPayNetworkProvider _btcPayNetworkProvider;
|
||||
private readonly IAuthorizationService _authorizationService;
|
||||
private readonly PaymentTypeRegistry _paymentTypeRegistry;
|
||||
|
||||
public GreenfieldStorePaymentMethodsController(BTCPayNetworkProvider btcPayNetworkProvider, IAuthorizationService authorizationService, PaymentTypeRegistry paymentTypeRegistry)
|
||||
public GreenfieldStorePaymentMethodsController(BTCPayNetworkProvider btcPayNetworkProvider, IAuthorizationService authorizationService)
|
||||
{
|
||||
_btcPayNetworkProvider = btcPayNetworkProvider;
|
||||
_authorizationService = authorizationService;
|
||||
_paymentTypeRegistry = paymentTypeRegistry;
|
||||
}
|
||||
|
||||
[Authorize(Policy = Policies.CanViewStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||
@ -43,7 +40,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
var canModifyStore = (await _authorizationService.AuthorizeAsync(User, null,
|
||||
new PolicyRequirement(Policies.CanModifyStoreSettings))).Succeeded;
|
||||
;
|
||||
return Ok(Store.GetSupportedPaymentMethods(_btcPayNetworkProvider, _paymentTypeRegistry)
|
||||
return Ok(Store.GetSupportedPaymentMethods(_btcPayNetworkProvider)
|
||||
.Where(method =>
|
||||
enabled is null || (enabled is false && excludedPaymentMethods.Match(method.PaymentId)))
|
||||
.ToDictionary(
|
||||
|
@ -27,20 +27,18 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
{
|
||||
private readonly StoreRepository _storeRepository;
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
private readonly PaymentTypeRegistry _paymentTypeRegistry;
|
||||
|
||||
public GreenfieldStoresController(StoreRepository storeRepository, UserManager<ApplicationUser> userManager, PaymentTypeRegistry paymentTypeRegistry)
|
||||
public GreenfieldStoresController(StoreRepository storeRepository, UserManager<ApplicationUser> userManager)
|
||||
{
|
||||
_storeRepository = storeRepository;
|
||||
_userManager = userManager;
|
||||
_paymentTypeRegistry = paymentTypeRegistry;
|
||||
}
|
||||
[Authorize(Policy = Policies.CanViewStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||
[HttpGet("~/api/v1/stores")]
|
||||
public Task<ActionResult<IEnumerable<Client.Models.StoreData>>> GetStores()
|
||||
{
|
||||
var stores = HttpContext.GetStoresData();
|
||||
return Task.FromResult<ActionResult<IEnumerable<Client.Models.StoreData>>>(Ok(stores.Select(data => FromModel(data, _paymentTypeRegistry))));
|
||||
return Task.FromResult<ActionResult<IEnumerable<Client.Models.StoreData>>>(Ok(stores.Select(FromModel)));
|
||||
}
|
||||
|
||||
[Authorize(Policy = Policies.CanViewStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||
@ -52,7 +50,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
{
|
||||
return StoreNotFound();
|
||||
}
|
||||
return Ok(FromModel(store, _paymentTypeRegistry));
|
||||
return Ok(FromModel(store));
|
||||
}
|
||||
|
||||
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||
@ -86,10 +84,10 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
|
||||
var store = new Data.StoreData();
|
||||
|
||||
_paymentTypeRegistry.TryParsePaymentMethod(request.DefaultPaymentMethod, out var defaultPaymentMethodId);
|
||||
PaymentMethodId.TryParse(request.DefaultPaymentMethod, out var defaultPaymentMethodId);
|
||||
ToModel(request, store, defaultPaymentMethodId);
|
||||
await _storeRepository.CreateStore(_userManager.GetUserId(User), store);
|
||||
return Ok(FromModel(store, _paymentTypeRegistry));
|
||||
return Ok(FromModel(store));
|
||||
}
|
||||
|
||||
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||
@ -107,14 +105,14 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
return validationResult;
|
||||
}
|
||||
|
||||
_paymentTypeRegistry.TryParsePaymentMethod(request.DefaultPaymentMethod, out var defaultPaymentMethodId);
|
||||
PaymentMethodId.TryParse(request.DefaultPaymentMethod, out var defaultPaymentMethodId);
|
||||
|
||||
ToModel(request, store, defaultPaymentMethodId);
|
||||
await _storeRepository.UpdateStore(store);
|
||||
return Ok(FromModel(store, _paymentTypeRegistry));
|
||||
return Ok(FromModel(store));
|
||||
}
|
||||
|
||||
internal static Client.Models.StoreData FromModel(StoreData data, PaymentTypeRegistry paymentTypeRegistry)
|
||||
internal static Client.Models.StoreData FromModel(Data.StoreData data)
|
||||
{
|
||||
var storeBlob = data.GetStoreBlob();
|
||||
return new Client.Models.StoreData
|
||||
@ -124,13 +122,14 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
Website = data.StoreWebsite,
|
||||
SupportUrl = storeBlob.StoreSupportUrl,
|
||||
SpeedPolicy = data.SpeedPolicy,
|
||||
DefaultPaymentMethod = data.GetDefaultPaymentId(paymentTypeRegistry)?.ToStringNormalized(),
|
||||
DefaultPaymentMethod = data.GetDefaultPaymentId()?.ToStringNormalized(),
|
||||
//blob
|
||||
//we do not include DefaultCurrencyPairs,Spread, PreferredExchange, RateScripting, RateScript in this model and instead opt to set it in stores/storeid/rates endpoints
|
||||
//we do not include ExcludedPaymentMethods in this model and instead opt to set it in stores/storeid/payment-methods endpoints
|
||||
//we do not include EmailSettings in this model and instead opt to set it in stores/storeid/email endpoints
|
||||
//we do not include PaymentMethodCriteria because moving the CurrencyValueJsonConverter to the Client csproj is hard and requires a refactor (#1571 & #1572)
|
||||
NetworkFeeMode = storeBlob.NetworkFeeMode,
|
||||
DefaultCurrency = storeBlob.DefaultCurrency,
|
||||
RequiresRefundEmail = storeBlob.RequiresRefundEmail,
|
||||
CheckoutType = storeBlob.CheckoutType,
|
||||
Receipt = InvoiceDataBase.ReceiptOptions.Merge(storeBlob.ReceiptOptions, null),
|
||||
@ -208,7 +207,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
Currency = criteria.CurrencyCode,
|
||||
Value = criteria.Amount
|
||||
},
|
||||
PaymentMethod = _paymentTypeRegistry.ParsePaymentMethod(criteria.PaymentMethod)
|
||||
PaymentMethod = PaymentMethodId.Parse(criteria.PaymentMethod)
|
||||
}).ToList() ?? new List<PaymentMethodCriteria>();
|
||||
blob.NormalizeToRelativeLinks(Request);
|
||||
model.SetStoreBlob(blob);
|
||||
@ -222,7 +221,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(request.DefaultPaymentMethod) &&
|
||||
!_paymentTypeRegistry.TryParsePaymentMethod(request.DefaultPaymentMethod, out var defaultPaymentMethodId))
|
||||
!PaymentMethodId.TryParse(request.DefaultPaymentMethod, out var defaultPaymentMethodId))
|
||||
{
|
||||
ModelState.AddModelError(nameof(request.Name), "DefaultPaymentMethod is invalid");
|
||||
}
|
||||
@ -258,7 +257,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
request.AddModelError(data => data.PaymentMethodCriteria[index].CurrencyCode, "CurrencyCode is invalid", this);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(pmc.PaymentMethod) || _paymentTypeRegistry.TryParsePaymentMethod(pmc.PaymentMethod) is null)
|
||||
if (string.IsNullOrEmpty(pmc.PaymentMethod) || PaymentMethodId.TryParse(pmc.PaymentMethod) is null)
|
||||
{
|
||||
request.AddModelError(data => data.PaymentMethodCriteria[index].PaymentMethod, "Payment method was invalid", this);
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ using System.Threading.Tasks;
|
||||
using BTCPayServer.Abstractions.Constants;
|
||||
using BTCPayServer.Client;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.Payments;
|
||||
using BTCPayServer.Security;
|
||||
using BTCPayServer.Services.Stores;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
@ -23,12 +22,14 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
public class GreenfieldTestApiKeyController : ControllerBase
|
||||
{
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
private readonly PaymentTypeRegistry _paymentTypeRegistry;
|
||||
private readonly StoreRepository _storeRepository;
|
||||
private readonly BTCPayServerClient _localBTCPayServerClient;
|
||||
|
||||
public GreenfieldTestApiKeyController(UserManager<ApplicationUser> userManager, PaymentTypeRegistry paymentTypeRegistry)
|
||||
public GreenfieldTestApiKeyController(UserManager<ApplicationUser> userManager, StoreRepository storeRepository, BTCPayServerClient localBTCPayServerClient)
|
||||
{
|
||||
_userManager = userManager;
|
||||
_paymentTypeRegistry = paymentTypeRegistry;
|
||||
_storeRepository = storeRepository;
|
||||
_localBTCPayServerClient = localBTCPayServerClient;
|
||||
}
|
||||
|
||||
[HttpGet("me/id")]
|
||||
@ -56,7 +57,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
[Authorize(Policy = Policies.CanViewStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||
public BTCPayServer.Client.Models.StoreData[] GetCurrentUserStores()
|
||||
{
|
||||
return this.HttpContext.GetStoresData().Select(data => Greenfield.GreenfieldStoresController.FromModel(data, _paymentTypeRegistry)).ToArray();
|
||||
return this.HttpContext.GetStoresData().Select(Greenfield.GreenfieldStoresController.FromModel).ToArray();
|
||||
}
|
||||
|
||||
[HttpGet("me/stores/{storeId}/can-view")]
|
||||
|
@ -1,6 +1,9 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Abstractions.Constants;
|
||||
using BTCPayServer.Abstractions.Contracts;
|
||||
using BTCPayServer.Abstractions.Extensions;
|
||||
using BTCPayServer.Abstractions.Models;
|
||||
using BTCPayServer.Client;
|
||||
using BTCPayServer.Data;
|
||||
@ -8,6 +11,7 @@ using BTCPayServer.Models.AppViewModels;
|
||||
using BTCPayServer.Services.Apps;
|
||||
using BTCPayServer.Services.Stores;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
@ -21,17 +25,20 @@ namespace BTCPayServer.Controllers
|
||||
public UIAppsController(
|
||||
UserManager<ApplicationUser> userManager,
|
||||
StoreRepository storeRepository,
|
||||
IFileService fileService,
|
||||
AppService appService,
|
||||
IHtmlHelper html)
|
||||
{
|
||||
_userManager = userManager;
|
||||
_storeRepository = storeRepository;
|
||||
_fileService = fileService;
|
||||
_appService = appService;
|
||||
Html = html;
|
||||
}
|
||||
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
private readonly StoreRepository _storeRepository;
|
||||
private readonly IFileService _fileService;
|
||||
private readonly AppService _appService;
|
||||
|
||||
public string CreatedAppId { get; set; }
|
||||
@ -184,13 +191,50 @@ namespace BTCPayServer.Controllers
|
||||
return RedirectToAction(nameof(UIStoresController.Dashboard), "UIStores", new { storeId = app.StoreDataId });
|
||||
}
|
||||
|
||||
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||
[HttpPost("{appId}/upload-file")]
|
||||
[IgnoreAntiforgeryToken]
|
||||
public async Task<IActionResult> FileUpload(IFormFile file)
|
||||
{
|
||||
var app = GetCurrentApp();
|
||||
var userId = GetUserId();
|
||||
if (app is null || userId is null)
|
||||
return NotFound();
|
||||
|
||||
if (!file.ContentType.StartsWith("image/", StringComparison.InvariantCulture))
|
||||
{
|
||||
return Json(new { error = "The file needs to be an image" });
|
||||
}
|
||||
if (file.Length > 500_000)
|
||||
{
|
||||
return Json(new { error = "The image file size should be less than 0.5MB" });
|
||||
}
|
||||
var formFile = await file.Bufferize();
|
||||
if (!FileTypeDetector.IsPicture(formFile.Buffer, formFile.FileName))
|
||||
{
|
||||
return Json(new { error = "The file needs to be an image" });
|
||||
}
|
||||
try
|
||||
{
|
||||
var storedFile = await _fileService.AddFile(file, userId);
|
||||
var fileId = storedFile.Id;
|
||||
var fileUrl = await _fileService.GetFileUrl(Request.GetAbsoluteRootUri(), fileId);
|
||||
return Json(new { fileId, fileUrl });
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return Json(new { error = $"Could not save file: {e.Message}" });
|
||||
}
|
||||
}
|
||||
|
||||
async Task<string> GetStoreDefaultCurrentIfEmpty(string storeId, string currency)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(currency))
|
||||
{
|
||||
currency = (await _storeRepository.FindStore(storeId)).GetStoreBlob().DefaultCurrency;
|
||||
var store = await _storeRepository.FindStore(storeId);
|
||||
currency = store?.GetStoreBlob().DefaultCurrency;
|
||||
}
|
||||
return currency.Trim().ToUpperInvariant();
|
||||
return currency?.Trim().ToUpperInvariant();
|
||||
}
|
||||
|
||||
private string GetUserId() => _userManager.GetUserId(User);
|
||||
|
@ -40,7 +40,6 @@ namespace BTCPayServer.Controllers
|
||||
private readonly BTCPayNetworkProvider _networkProvider;
|
||||
private readonly LinkGenerator _linkGenerator;
|
||||
private readonly FormDataService _formDataService;
|
||||
private readonly PaymentTypeRegistry _paymentTypeRegistry;
|
||||
|
||||
public UICustodianAccountsController(
|
||||
DisplayFormatter displayFormatter,
|
||||
@ -50,8 +49,7 @@ namespace BTCPayServer.Controllers
|
||||
BTCPayServerClient btcPayServerClient,
|
||||
BTCPayNetworkProvider networkProvider,
|
||||
LinkGenerator linkGenerator,
|
||||
FormDataService formDataService,
|
||||
PaymentTypeRegistry paymentTypeRegistry
|
||||
FormDataService formDataService
|
||||
)
|
||||
{
|
||||
_displayFormatter = displayFormatter;
|
||||
@ -61,7 +59,6 @@ namespace BTCPayServer.Controllers
|
||||
_networkProvider = networkProvider;
|
||||
_linkGenerator = linkGenerator;
|
||||
_formDataService = formDataService;
|
||||
_paymentTypeRegistry = paymentTypeRegistry;
|
||||
}
|
||||
|
||||
public string CreatedCustodianAccountId { get; set; }
|
||||
@ -508,13 +505,13 @@ namespace BTCPayServer.Controllers
|
||||
await depositableCustodian.GetDepositAddressAsync(paymentMethod, config, default);
|
||||
vm.Address = depositAddressResult.Address;
|
||||
|
||||
var paymentMethodObj = _paymentTypeRegistry.ParsePaymentMethod(paymentMethod);
|
||||
var paymentMethodObj = PaymentMethodId.Parse(paymentMethod);
|
||||
if (paymentMethodObj.IsBTCOnChain)
|
||||
{
|
||||
var network = _networkProvider.GetNetwork<BTCPayNetwork>("BTC");
|
||||
var bip21 = network.GenerateBIP21(depositAddressResult.Address, null);
|
||||
vm.Link = bip21.ToString();
|
||||
var paymentMethodId = _paymentTypeRegistry.TryParsePaymentMethod(paymentMethod);
|
||||
var paymentMethodId = PaymentMethodId.TryParse(paymentMethod);
|
||||
if (paymentMethodId != null)
|
||||
{
|
||||
var walletId = new WalletId(storeId, paymentMethodId.CryptoCode);
|
||||
@ -555,7 +552,7 @@ namespace BTCPayServer.Controllers
|
||||
private string GetImage(PaymentMethodId paymentMethodId, BTCPayNetwork network)
|
||||
{
|
||||
// TODO this method was copy-pasted from BTCPayServer.Controllers.UIWalletsController.GetImage(). Maybe refactor this?
|
||||
var res = paymentMethodId.PaymentType == BitcoinPaymentType.Instance
|
||||
var res = paymentMethodId.PaymentType == PaymentTypes.BTCLike
|
||||
? Url.Content(network.CryptoImagePath)
|
||||
: Url.Content(network.LightningImagePath);
|
||||
return Request.GetRelativePathOrAbsolute(res);
|
||||
|
@ -172,7 +172,7 @@ namespace BTCPayServer.Controllers
|
||||
}
|
||||
|
||||
[HttpGet("i/{invoiceId}/receipt")]
|
||||
public async Task<IActionResult> InvoiceReceipt(string invoiceId)
|
||||
public async Task<IActionResult> InvoiceReceipt(string invoiceId, [FromQuery] bool print = false)
|
||||
{
|
||||
var i = await _InvoiceRepository.GetInvoice(invoiceId);
|
||||
if (i is null)
|
||||
@ -255,7 +255,7 @@ namespace BTCPayServer.Controllers
|
||||
vm.Payments = receipt.ShowPayments is false ? null : payments;
|
||||
vm.AdditionalData = PosDataParser.ParsePosData(receiptData);
|
||||
|
||||
return View(vm);
|
||||
return View(print ? "InvoiceReceiptPrint" : "InvoiceReceipt", vm);
|
||||
}
|
||||
|
||||
private string? GetTransactionLink(PaymentMethodId paymentMethodId, string txId)
|
||||
@ -358,7 +358,7 @@ namespace BTCPayServer.Controllers
|
||||
//TODO: Make this clean
|
||||
if (paymentMethod is null && paymentMethodId.PaymentType == LightningPaymentType.Instance)
|
||||
{
|
||||
paymentMethod = pms[new PaymentMethodId(paymentMethodId.CryptoCode, LNURLPayPaymentType.Instance)];
|
||||
paymentMethod = pms[new PaymentMethodId(paymentMethodId.CryptoCode, PaymentTypes.LNURLPay)];
|
||||
}
|
||||
|
||||
if (paymentMethod != null)
|
||||
@ -456,7 +456,7 @@ namespace BTCPayServer.Controllers
|
||||
model.Title = "How much to refund?";
|
||||
model.RefundStep = RefundSteps.SelectRate;
|
||||
|
||||
if (isPaidOver)
|
||||
if (!isPaidOver)
|
||||
{
|
||||
ModelState.AddModelError(nameof(model.SelectedRefundOption), "Invoice is not overpaid");
|
||||
}
|
||||
@ -466,7 +466,7 @@ namespace BTCPayServer.Controllers
|
||||
}
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return this.CreateValidationError(ModelState);
|
||||
return View("_RefundModal", model);
|
||||
}
|
||||
|
||||
createPullPayment.Currency = paymentMethodId.CryptoCode;
|
||||
@ -777,8 +777,8 @@ namespace BTCPayServer.Controllers
|
||||
}
|
||||
if (paymentMethodId is null)
|
||||
{
|
||||
paymentMethodId = displayedPaymentMethods.FirstOrDefault(e => e.CryptoCode == _NetworkProvider.DefaultNetwork.CryptoCode && e.PaymentType == BitcoinPaymentType.Instance) ??
|
||||
displayedPaymentMethods.FirstOrDefault(e => e.CryptoCode == _NetworkProvider.DefaultNetwork.CryptoCode && e.PaymentType != LNURLPayPaymentType.Instance) ??
|
||||
paymentMethodId = displayedPaymentMethods.FirstOrDefault(e => e.CryptoCode == _NetworkProvider.DefaultNetwork.CryptoCode && e.PaymentType == PaymentTypes.BTCLike) ??
|
||||
displayedPaymentMethods.FirstOrDefault(e => e.CryptoCode == _NetworkProvider.DefaultNetwork.CryptoCode && e.PaymentType != PaymentTypes.LNURLPay) ??
|
||||
displayedPaymentMethods.FirstOrDefault();
|
||||
}
|
||||
isDefaultPaymentId = true;
|
||||
@ -941,7 +941,7 @@ namespace BTCPayServer.Controllers
|
||||
? pmName
|
||||
: pmName.Replace("Bitcoin (", "").Replace(")", "").Replace("Lightning ", ""),
|
||||
IsLightning =
|
||||
kv.GetId().PaymentType == LightningPaymentType.Instance,
|
||||
kv.GetId().PaymentType == PaymentTypes.LightningLike,
|
||||
CryptoImage = Request.GetRelativePathOrAbsolute(availableCryptoHandler.GetCryptoImage(availableCryptoPaymentMethodId)),
|
||||
Link = Url.Action(nameof(Checkout),
|
||||
new
|
||||
|
@ -17,6 +17,7 @@ using BTCPayServer.Payments;
|
||||
using BTCPayServer.Payments.Bitcoin;
|
||||
using BTCPayServer.Rating;
|
||||
using BTCPayServer.Security;
|
||||
using BTCPayServer.Security.Greenfield;
|
||||
using BTCPayServer.Services;
|
||||
using BTCPayServer.Services.Apps;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
@ -58,7 +59,6 @@ namespace BTCPayServer.Controllers
|
||||
private readonly InvoiceActivator _invoiceActivator;
|
||||
private readonly LinkGenerator _linkGenerator;
|
||||
private readonly IAuthorizationService _authorizationService;
|
||||
private readonly PaymentTypeRegistry _paymentTypeRegistry;
|
||||
private readonly AppService _appService;
|
||||
|
||||
public WebhookSender WebhookNotificationManager { get; }
|
||||
@ -84,8 +84,7 @@ namespace BTCPayServer.Controllers
|
||||
InvoiceActivator invoiceActivator,
|
||||
LinkGenerator linkGenerator,
|
||||
AppService appService,
|
||||
IAuthorizationService authorizationService,
|
||||
PaymentTypeRegistry paymentTypeRegistry)
|
||||
IAuthorizationService authorizationService)
|
||||
{
|
||||
_displayFormatter = displayFormatter;
|
||||
_CurrencyNameTable = currencyNameTable ?? throw new ArgumentNullException(nameof(currencyNameTable));
|
||||
@ -106,7 +105,6 @@ namespace BTCPayServer.Controllers
|
||||
_invoiceActivator = invoiceActivator;
|
||||
_linkGenerator = linkGenerator;
|
||||
_authorizationService = authorizationService;
|
||||
_paymentTypeRegistry = paymentTypeRegistry;
|
||||
_appService = appService;
|
||||
}
|
||||
|
||||
@ -130,6 +128,14 @@ namespace BTCPayServer.Controllers
|
||||
{
|
||||
throw new BitpayHttpException(400, "The expirationTime is set too soon");
|
||||
}
|
||||
if (entity.Price < 0.0m)
|
||||
{
|
||||
throw new BitpayHttpException(400, "The price should be 0 or more.");
|
||||
}
|
||||
if (entity.Price > GreenfieldConstants.MaxAmount)
|
||||
{
|
||||
throw new BitpayHttpException(400, $"The price should less than {GreenfieldConstants.MaxAmount}.");
|
||||
}
|
||||
entity.Metadata.OrderId = invoice.OrderId;
|
||||
entity.Metadata.PosDataLegacy = invoice.PosData;
|
||||
entity.ServerUrl = serverUrl;
|
||||
@ -182,7 +188,7 @@ namespace BTCPayServer.Controllers
|
||||
{
|
||||
var supportedTransactionCurrencies = invoice.SupportedTransactionCurrencies
|
||||
.Where(c => c.Value.Enabled)
|
||||
.Select(c => _paymentTypeRegistry.TryParsePaymentMethod(c.Key, out var p) ? p : null)
|
||||
.Select(c => PaymentMethodId.TryParse(c.Key, out var p) ? p : null)
|
||||
.Where(c => c != null)
|
||||
.ToHashSet();
|
||||
excludeFilter = PaymentFilter.Where(p => !supportedTransactionCurrencies.Contains(p));
|
||||
@ -252,7 +258,7 @@ namespace BTCPayServer.Controllers
|
||||
}
|
||||
entity.SpeedPolicy = invoice.Checkout.SpeedPolicy ?? store.SpeedPolicy;
|
||||
entity.DefaultLanguage = invoice.Checkout.DefaultLanguage;
|
||||
entity.DefaultPaymentMethod = invoice.Checkout.DefaultPaymentMethod ?? store.GetDefaultPaymentId()?.ToStringNormalized() ?? new PaymentMethodId(_NetworkProvider.DefaultNetwork.CryptoCode, BitcoinPaymentType.Instance).ToStringNormalized();
|
||||
entity.DefaultPaymentMethod = invoice.Checkout.DefaultPaymentMethod ?? store.GetDefaultPaymentId()?.ToStringNormalized() ?? new PaymentMethodId(_NetworkProvider.DefaultNetwork.CryptoCode, PaymentTypes.BTCLike).ToStringNormalized();
|
||||
entity.RedirectAutomatically = invoice.Checkout.RedirectAutomatically ?? storeBlob.RedirectAutomatically;
|
||||
entity.CheckoutType = invoice.Checkout.CheckoutType;
|
||||
entity.RequiresRefundEmail = invoice.Checkout.RequiresRefundEmail;
|
||||
@ -261,7 +267,7 @@ namespace BTCPayServer.Controllers
|
||||
if (invoice.Checkout.PaymentMethods != null)
|
||||
{
|
||||
var supportedTransactionCurrencies = invoice.Checkout.PaymentMethods
|
||||
.Select(c => _paymentTypeRegistry.TryParsePaymentMethod(c, out var p) ? p : null)
|
||||
.Select(c => PaymentMethodId.TryParse(c, out var p) ? p : null)
|
||||
.ToHashSet();
|
||||
excludeFilter = PaymentFilter.Where(p => !supportedTransactionCurrencies.Contains(p));
|
||||
}
|
||||
@ -281,6 +287,7 @@ namespace BTCPayServer.Controllers
|
||||
if (string.IsNullOrEmpty(entity.Currency))
|
||||
entity.Currency = storeBlob.DefaultCurrency;
|
||||
entity.Currency = entity.Currency.Trim().ToUpperInvariant();
|
||||
entity.Price = Math.Min(GreenfieldConstants.MaxAmount, entity.Price);
|
||||
entity.Price = Math.Max(0.0m, entity.Price);
|
||||
var currencyInfo = _CurrencyNameTable.GetNumberFormatInfo(entity.Currency, false);
|
||||
if (currencyInfo != null)
|
||||
|
@ -3,6 +3,7 @@ using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Abstractions.Constants;
|
||||
@ -60,7 +61,6 @@ namespace BTCPayServer
|
||||
private readonly BTCPayNetworkJsonSerializerSettings _btcPayNetworkJsonSerializerSettings;
|
||||
private readonly IPluginHookService _pluginHookService;
|
||||
private readonly InvoiceActivator _invoiceActivator;
|
||||
private readonly PaymentTypeRegistry _paymentTypeRegistry;
|
||||
|
||||
public UILNURLController(InvoiceRepository invoiceRepository,
|
||||
EventAggregator eventAggregator,
|
||||
@ -75,8 +75,7 @@ namespace BTCPayServer
|
||||
PullPaymentHostedService pullPaymentHostedService,
|
||||
BTCPayNetworkJsonSerializerSettings btcPayNetworkJsonSerializerSettings,
|
||||
IPluginHookService pluginHookService,
|
||||
InvoiceActivator invoiceActivator,
|
||||
PaymentTypeRegistry paymentTypeRegistry)
|
||||
InvoiceActivator invoiceActivator)
|
||||
{
|
||||
_invoiceRepository = invoiceRepository;
|
||||
_eventAggregator = eventAggregator;
|
||||
@ -92,7 +91,6 @@ namespace BTCPayServer
|
||||
_btcPayNetworkJsonSerializerSettings = btcPayNetworkJsonSerializerSettings;
|
||||
_pluginHookService = pluginHookService;
|
||||
_invoiceActivator = invoiceActivator;
|
||||
_paymentTypeRegistry = paymentTypeRegistry;
|
||||
}
|
||||
|
||||
[HttpGet("withdraw/pp/{pullPaymentId}")]
|
||||
@ -104,7 +102,7 @@ namespace BTCPayServer
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var pmi = new PaymentMethodId(cryptoCode, LightningPaymentType.Instance);
|
||||
var pmi = new PaymentMethodId(cryptoCode, PaymentTypes.LightningLike);
|
||||
var pp = await _pullPaymentHostedService.GetPullPayment(pullPaymentId, true);
|
||||
if (!pp.IsRunning() || !pp.IsSupported(pmi))
|
||||
{
|
||||
@ -112,24 +110,24 @@ namespace BTCPayServer
|
||||
}
|
||||
|
||||
var blob = pp.GetBlob();
|
||||
if (!blob.Currency.Equals(cryptoCode, StringComparison.InvariantCultureIgnoreCase))
|
||||
if (!_pullPaymentHostedService.SupportsLNURL(blob))
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var unit = blob.Currency == "SATS" ? LightMoneyUnit.Satoshi : LightMoneyUnit.BTC;
|
||||
var progress = _pullPaymentHostedService.CalculatePullPaymentProgress(pp, DateTimeOffset.UtcNow);
|
||||
|
||||
var remaining = progress.Limit - progress.Completed - progress.Awaiting;
|
||||
var request = new LNURLWithdrawRequest
|
||||
{
|
||||
MaxWithdrawable = LightMoney.FromUnit(remaining, LightMoneyUnit.BTC),
|
||||
MaxWithdrawable = LightMoney.FromUnit(remaining, unit),
|
||||
K1 = pullPaymentId,
|
||||
BalanceCheck = new Uri(Request.GetCurrentUrl()),
|
||||
CurrentBalance = LightMoney.FromUnit(remaining, LightMoneyUnit.BTC),
|
||||
CurrentBalance = LightMoney.FromUnit(remaining, unit),
|
||||
MinWithdrawable =
|
||||
LightMoney.FromUnit(
|
||||
Math.Min(await _lightningLikePayoutHandler.GetMinimumPayoutAmount(pmi, null), remaining),
|
||||
LightMoneyUnit.BTC),
|
||||
unit),
|
||||
Tag = "withdrawRequest",
|
||||
Callback = new Uri(Request.GetCurrentUrl()),
|
||||
// It's not `pp.GetBlob().Description` because this would be HTML
|
||||
@ -157,13 +155,13 @@ namespace BTCPayServer
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var claimResponse = await _pullPaymentHostedService.Claim(new ClaimRequest()
|
||||
var claimResponse = await _pullPaymentHostedService.Claim(new ClaimRequest
|
||||
{
|
||||
Destination = new BoltInvoiceClaimDestination(pr, result),
|
||||
PaymentMethodId = pmi,
|
||||
PullPaymentId = pullPaymentId,
|
||||
StoreId = pp.StoreId,
|
||||
Value = result.MinimumAmount.ToDecimal(LightMoneyUnit.BTC)
|
||||
Value = result.MinimumAmount.ToDecimal(unit)
|
||||
});
|
||||
|
||||
if (claimResponse.Result != ClaimRequest.ClaimResult.Ok)
|
||||
@ -286,7 +284,7 @@ namespace BTCPayServer
|
||||
if (item is null ||
|
||||
item.Inventory <= 0 ||
|
||||
(item.PaymentMethods?.Any() is true &&
|
||||
item.PaymentMethods?.Any(s => _paymentTypeRegistry.ParsePaymentMethod(s) == pmi) is false))
|
||||
item.PaymentMethods?.Any(s => PaymentMethodId.Parse(s) == pmi) is false))
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
@ -376,13 +374,52 @@ namespace BTCPayServer
|
||||
return NotFound("Unknown username");
|
||||
|
||||
var store = await _storeRepository.FindStore(lightningAddressSettings.StoreDataId);
|
||||
var cryptoCode = "BTC";
|
||||
if (store is null)
|
||||
return NotFound("Unknown username");
|
||||
if (GetLNUrlPaymentMethodId(cryptoCode, store, out var lnUrlMethod) is null)
|
||||
return NotFound("LNUrl not available for store");
|
||||
|
||||
var blob = lightningAddressSettings.GetBlob();
|
||||
|
||||
return await GetLNURLRequest(
|
||||
"BTC",
|
||||
var lnurlRequest = new LNURLPayRequest()
|
||||
{
|
||||
Tag = "payRequest",
|
||||
MinSendable = blob?.Min is decimal min ? new LightMoney(min, LightMoneyUnit.Satoshi) : null,
|
||||
MaxSendable = blob?.Max is decimal max ? new LightMoney(max, LightMoneyUnit.Satoshi) : null,
|
||||
CommentAllowed = lnUrlMethod.LUD12Enabled ? 2000 : 0
|
||||
};
|
||||
NormalizeSendable(lnurlRequest);
|
||||
|
||||
var lnUrlMetadata = new Dictionary<string, string>()
|
||||
{
|
||||
["text/identifier"] = $"{username}@{Request.Host}"
|
||||
};
|
||||
SetLNUrlDescriptionMetadata(lnUrlMetadata, store, store.GetStoreBlob(), null);
|
||||
lnurlRequest.Metadata =
|
||||
JsonConvert.SerializeObject(lnUrlMetadata.Select(kv => new[] { kv.Key, kv.Value }));
|
||||
|
||||
lnurlRequest.Callback = new Uri(_linkGenerator.GetUriByAction(
|
||||
action: nameof(GetLNURLForLightningAddress),
|
||||
controller: "UILNURL",
|
||||
values: new { cryptoCode, username }, Request.Scheme, Request.Host, Request.PathBase));
|
||||
|
||||
lnurlRequest = await _pluginHookService.ApplyFilter("modify-lnurlp-request", lnurlRequest) as LNURLPayRequest;
|
||||
return Ok(lnurlRequest);
|
||||
}
|
||||
|
||||
[HttpGet("pay/lnaddress/{username}")]
|
||||
[EnableCors(CorsPolicies.All)]
|
||||
[IgnoreAntiforgeryToken]
|
||||
public async Task<IActionResult> GetLNURLForLightningAddress(string cryptoCode, string username, [FromQuery] long? amount = null, string comment = null)
|
||||
{
|
||||
var lightningAddressSettings = await _lightningAddressService.ResolveByAddress(username);
|
||||
if (lightningAddressSettings is null || username is null)
|
||||
return NotFound("Unknown username");
|
||||
var blob = lightningAddressSettings.GetBlob();
|
||||
var store = await _storeRepository.FindStore(lightningAddressSettings.StoreDataId);
|
||||
var result = await GetLNURLRequest(
|
||||
cryptoCode,
|
||||
store,
|
||||
store.GetStoreBlob(),
|
||||
new CreateInvoiceRequest()
|
||||
@ -399,31 +436,44 @@ namespace BTCPayServer
|
||||
{
|
||||
{ "text/identifier", $"{username}@{Request.Host}" }
|
||||
});
|
||||
if (result is not OkObjectResult ok || ok.Value is not LNURLPayRequest payRequest)
|
||||
return result;
|
||||
var invoiceId = payRequest.Callback.AbsoluteUri.Split('/').Last();
|
||||
return await GetLNURLForInvoice(invoiceId, cryptoCode, amount, comment);
|
||||
}
|
||||
|
||||
|
||||
[HttpGet("pay")]
|
||||
[HttpGet("{storeId}/pay")]
|
||||
[EnableCors(CorsPolicies.All)]
|
||||
[IgnoreAntiforgeryToken]
|
||||
public async Task<IActionResult> GetLNUrlForStore(
|
||||
string cryptoCode,
|
||||
string storeId,
|
||||
string currencyCode = null)
|
||||
string currency = null,
|
||||
string orderId = null,
|
||||
decimal? amount = null)
|
||||
{
|
||||
var store = this.HttpContext.GetStoreData();
|
||||
var store = await _storeRepository.FindStore(storeId);
|
||||
if (store is null)
|
||||
return NotFound();
|
||||
|
||||
var blob = store.GetStoreBlob();
|
||||
var blob = store.GetStoreBlob();
|
||||
if (!blob.AnyoneCanInvoice)
|
||||
return NotFound("'Anyone can invoice' is turned off");
|
||||
var metadata = new InvoiceMetadata();
|
||||
if (!string.IsNullOrEmpty(orderId))
|
||||
{
|
||||
metadata.OrderId = orderId;
|
||||
}
|
||||
return await GetLNURLRequest(
|
||||
cryptoCode,
|
||||
store,
|
||||
blob,
|
||||
new CreateInvoiceRequest
|
||||
{
|
||||
Currency = currencyCode
|
||||
Amount = amount,
|
||||
Metadata = metadata.ToJObject(),
|
||||
Currency = currency
|
||||
});
|
||||
}
|
||||
|
||||
@ -485,11 +535,7 @@ namespace BTCPayServer
|
||||
|
||||
if (!lnUrlMetadata.ContainsKey("text/plain"))
|
||||
{
|
||||
var invoiceDescription = blob.LightningDescriptionTemplate
|
||||
.Replace("{StoreName}", store.StoreName ?? "", StringComparison.OrdinalIgnoreCase)
|
||||
.Replace("{ItemDescription}", i.Metadata.ItemDesc ?? "", StringComparison.OrdinalIgnoreCase)
|
||||
.Replace("{OrderId}", i.Metadata.OrderId ?? "", StringComparison.OrdinalIgnoreCase);
|
||||
lnUrlMetadata.Add("text/plain", invoiceDescription);
|
||||
SetLNUrlDescriptionMetadata(lnUrlMetadata, store, blob, i.Metadata);
|
||||
}
|
||||
|
||||
lnurlRequest.Tag = "payRequest";
|
||||
@ -506,12 +552,7 @@ namespace BTCPayServer
|
||||
lnurlRequest.MaxSendable = lnurlRequest.MinSendable;
|
||||
}
|
||||
|
||||
// We don't think BTCPay handle well 0 sats payments, just in case make it minimum one sat.
|
||||
if (lnurlRequest.MinSendable is null || lnurlRequest.MinSendable < LightMoney.Satoshis(1.0m))
|
||||
lnurlRequest.MinSendable = LightMoney.Satoshis(1.0m);
|
||||
|
||||
if (lnurlRequest.MaxSendable is null)
|
||||
lnurlRequest.MaxSendable = LightMoney.FromUnit(6.12m, LightMoneyUnit.BTC);
|
||||
NormalizeSendable(lnurlRequest);
|
||||
|
||||
lnurlRequest = await _pluginHookService.ApplyFilter("modify-lnurlp-request", lnurlRequest) as LNURLPayRequest;
|
||||
if (paymentMethodDetails.PayRequest is null)
|
||||
@ -527,14 +568,33 @@ namespace BTCPayServer
|
||||
return lnurlRequest;
|
||||
}
|
||||
|
||||
private void SetLNUrlDescriptionMetadata(Dictionary<string, string> lnUrlMetadata, Data.StoreData store, StoreBlob blob, InvoiceMetadata invoiceMetadata)
|
||||
{
|
||||
var invoiceDescription = blob.LightningDescriptionTemplate
|
||||
.Replace("{StoreName}", store.StoreName ?? "", StringComparison.OrdinalIgnoreCase)
|
||||
.Replace("{ItemDescription}", invoiceMetadata?.ItemDesc ?? "", StringComparison.OrdinalIgnoreCase)
|
||||
.Replace("{OrderId}", invoiceMetadata?.OrderId ?? "", StringComparison.OrdinalIgnoreCase);
|
||||
lnUrlMetadata.Add("text/plain", invoiceDescription);
|
||||
}
|
||||
|
||||
private static void NormalizeSendable(LNURLPayRequest lnurlRequest)
|
||||
{
|
||||
// We don't think BTCPay handle well 0 sats payments, just in case make it minimum one sat.
|
||||
if (lnurlRequest.MinSendable is null || lnurlRequest.MinSendable < LightMoney.Satoshis(1.0m))
|
||||
lnurlRequest.MinSendable = LightMoney.Satoshis(1.0m);
|
||||
|
||||
if (lnurlRequest.MaxSendable is null)
|
||||
lnurlRequest.MaxSendable = LightMoney.FromUnit(6.12m, LightMoneyUnit.BTC);
|
||||
}
|
||||
|
||||
PaymentMethodId GetLNUrlPaymentMethodId(string cryptoCode, Data.StoreData store, out LNURLPaySupportedPaymentMethod lnUrlSettings)
|
||||
{
|
||||
lnUrlSettings = null;
|
||||
var network = _btcPayNetworkProvider.GetNetwork<BTCPayNetwork>(cryptoCode);
|
||||
if (network is null || !network.SupportLightning)
|
||||
return null;
|
||||
var pmi = new PaymentMethodId(cryptoCode, LNURLPayPaymentType.Instance);
|
||||
var lnpmi = new PaymentMethodId(cryptoCode, LightningPaymentType.Instance);
|
||||
var pmi = new PaymentMethodId(cryptoCode, PaymentTypes.LNURLPay);
|
||||
var lnpmi = new PaymentMethodId(cryptoCode, PaymentTypes.LightningLike);
|
||||
var methods = store.GetSupportedPaymentMethods(_btcPayNetworkProvider);
|
||||
var lnUrlMethod =
|
||||
methods.FirstOrDefault(method => method.PaymentId == pmi) as LNURLPaySupportedPaymentMethod;
|
||||
|
@ -506,57 +506,57 @@ namespace BTCPayServer.Controllers
|
||||
{
|
||||
public static readonly Dictionary<string, (string Title, string Description)> PermissionDescriptions = new Dictionary<string, (string Title, string Description)>()
|
||||
{
|
||||
{Policies.Unrestricted, ("Unrestricted access", "The app will have unrestricted access to your account.")},
|
||||
{Policies.CanViewUsers, ("View users", "The app will be able to see all users on this server.")},
|
||||
{Policies.CanCreateUser, ("Create new users", "The app will be able to create new users on this server.")},
|
||||
{Policies.CanManageUsers, ("Manage users", "The app will be able to create/delete API keys for users.")},
|
||||
{Policies.CanDeleteUser, ("Delete user", "The app will be able to delete the user to whom it is assigned. Admin users can delete any user without this permission.")},
|
||||
{Policies.CanModifyStoreSettings, ("Modify your stores", "The app will be able to manage invoices on all your stores and modify their settings.")},
|
||||
{$"{Policies.CanModifyStoreSettings}:", ("Manage selected stores", "The app will be able to manage invoices on the selected stores and modify their settings.")},
|
||||
{Policies.CanViewCustodianAccounts, ("View exchange accounts linked to your stores", "The app will be able to see exchange accounts linked to your stores.")},
|
||||
{$"{Policies.CanViewCustodianAccounts}:", ("View exchange accounts linked to selected stores", "The app will be able to see exchange accounts linked to the selected stores.")},
|
||||
{Policies.CanManageCustodianAccounts, ("Manage exchange accounts linked to your stores", "The app will be able to modify exchange accounts linked to your stores.")},
|
||||
{$"{Policies.CanManageCustodianAccounts}:", ("Manage exchange accounts linked to selected stores", "The app will be able to modify exchange accounts linked to selected stores.")},
|
||||
{Policies.CanDepositToCustodianAccounts, ("Deposit funds to exchange accounts linked to your stores", "The app will be able to deposit funds to your exchange accounts.")},
|
||||
{$"{Policies.CanDepositToCustodianAccounts}:", ("Deposit funds to exchange accounts linked to selected stores", "The app will be able to deposit funds to selected store's exchange accounts.")},
|
||||
{Policies.CanWithdrawFromCustodianAccounts, ("Withdraw funds from exchange accounts to your store", "The app will be able to withdraw funds from your exchange accounts to your store.")},
|
||||
{$"{Policies.CanWithdrawFromCustodianAccounts}:", ("Withdraw funds from selected store's exchange accounts", "The app will be able to withdraw funds from your selected store's exchange accounts.")},
|
||||
{Policies.CanTradeCustodianAccount, ("Trade funds on your store's exchange accounts", "The app will be able to trade funds on your store's exchange accounts.")},
|
||||
{$"{Policies.CanTradeCustodianAccount}:", ("Trade funds on selected store's exchange accounts", "The app will be able to trade funds on selected store's exchange accounts.")},
|
||||
{Policies.CanModifyStoreWebhooks, ("Modify stores webhooks", "The app will modify the webhooks of all your stores.")},
|
||||
{$"{Policies.CanModifyStoreWebhooks}:", ("Modify selected stores' webhooks", "The app will modify the webhooks of the selected stores.")},
|
||||
{Policies.CanViewStoreSettings, ("View your stores", "The app will be able to view stores settings.")},
|
||||
{$"{Policies.CanViewStoreSettings}:", ("View your stores", "The app will be able to view the selected stores' settings.")},
|
||||
{Policies.CanModifyServerSettings, ("Manage your server", "The app will have total control on the server settings of your server.")},
|
||||
{Policies.CanViewProfile, ("View your profile", "The app will be able to view your user profile.")},
|
||||
{Policies.CanModifyProfile, ("Manage your profile", "The app will be able to view and modify your user profile.")},
|
||||
{Policies.CanManageNotificationsForUser, ("Manage your notifications", "The app will be able to view and modify your user notifications.")},
|
||||
{Policies.CanViewNotificationsForUser, ("View your notifications", "The app will be able to view your user notifications.")},
|
||||
{Policies.CanCreateInvoice, ("Create an invoice", "The app will be able to create new invoices.")},
|
||||
{$"{Policies.CanCreateInvoice}:", ("Create an invoice", "The app will be able to create new invoices on the selected stores.")},
|
||||
{Policies.CanViewInvoices, ("View invoices", "The app will be able to view invoices.")},
|
||||
{Policies.CanModifyInvoices, ("Modify invoices", "The app will be able to modify and view invoices.")},
|
||||
{$"{Policies.CanViewInvoices}:", ("View invoices", "The app will be able to view invoices on the selected stores.")},
|
||||
{$"{Policies.CanModifyInvoices}:", ("Modify invoices", "The app will be able to modify and view invoices on the selected stores.")},
|
||||
{Policies.CanModifyPaymentRequests, ("Modify your payment requests", "The app will be able to view, modify, delete and create new payment requests on all your stores.")},
|
||||
{$"{Policies.CanModifyPaymentRequests}:", ("Manage selected stores' payment requests", "The app will be able to view, modify, delete and create new payment requests on the selected stores.")},
|
||||
{Policies.CanViewPaymentRequests, ("View your payment requests", "The app will be able to view payment requests.")},
|
||||
{$"{Policies.CanViewPaymentRequests}:", ("View your payment requests", "The app will be able to view the selected stores' payment requests.")},
|
||||
{Policies.CanManagePullPayments, ("Manage your pull payments", "The app will be able to view, modify, delete and create pull payments on all your stores.")},
|
||||
{$"{Policies.CanManagePullPayments}:", ("Manage selected stores' pull payments", "The app will be able to view, modify, delete and create new pull payments on the selected stores.")},
|
||||
{Policies.CanCreatePullPayments, ("Create pull payments", "The app will be able to create pull payments on all your stores.")},
|
||||
{$"{Policies.CanCreatePullPayments}:", ("Create pull payments in selected stores", "The app will be able to create new pull payments on the selected stores.")},
|
||||
{Policies.CanCreateNonApprovedPullPayments, ("Create non-approved pull payments", "The app will be able to create pull payments without automatic approval on all your stores.")},
|
||||
{$"{Policies.CanCreateNonApprovedPullPayments}:", ("Create non-approved pull payments in selected stores", "The app will be able to view, modify, delete and create pull payments without automatic approval on the selected stores.")},
|
||||
{Policies.CanUseInternalLightningNode, ("Use the internal lightning node", "The app will be able to use the internal BTCPay Server lightning node to create BOLT11 invoices, connect to other nodes, open new channels and pay BOLT11 invoices.")},
|
||||
{Policies.CanViewLightningInvoiceInternalNode, ("View invoices from internal lightning node", "The app will be able to use the internal BTCPay Server lightning node to view BOLT11 invoices.")},
|
||||
{Policies.CanCreateLightningInvoiceInternalNode, ("Create invoices with internal lightning node", "The app will be able to use the internal BTCPay Server lightning node to create BOLT11 invoices.")},
|
||||
{Policies.CanUseLightningNodeInStore, ("Use the lightning nodes associated with your stores", "The app will be able to use the lightning nodes connected to all your stores to create BOLT11 invoices, connect to other nodes, open new channels and pay BOLT11 invoices.")},
|
||||
{Policies.CanViewLightningInvoiceInStore, ("View the lightning invoices associated with your stores", "The app will be able to view the lightning invoices connected to all your stores.")},
|
||||
{Policies.CanCreateLightningInvoiceInStore, ("Create invoices from the lightning nodes associated with your stores", "The app will be able to use the lightning nodes connected to all your stores to create BOLT11 invoices.")},
|
||||
{$"{Policies.CanUseLightningNodeInStore}:", ("Use the lightning nodes associated with your stores", "The app will be able to use the lightning nodes connected to the selected stores to create BOLT11 invoices, connect to other nodes, open new channels and pay BOLT11 invoices.")},
|
||||
{$"{Policies.CanViewLightningInvoiceInStore}:", ("View the lightning invoices associated with your stores", "The app will be able to view the lightning invoices connected to the selected stores.")},
|
||||
{$"{Policies.CanCreateLightningInvoiceInStore}:", ("Create invoices from the lightning nodes associated with your stores", "The app will be able to use the lightning nodes connected to the selected stores to create BOLT11 invoices.")},
|
||||
{Policies.Unrestricted, ("Unrestricted access", "Grants unrestricted access to your account.")},
|
||||
{Policies.CanViewUsers, ("View users", "Allows seeing all users on this server.")},
|
||||
{Policies.CanCreateUser, ("Create new users", "Allows creating new users on this server.")},
|
||||
{Policies.CanManageUsers, ("Manage users", "Allows creating/deleting API keys for users.")},
|
||||
{Policies.CanDeleteUser, ("Delete user", "Allows deleting the user to whom it is assigned. Admin users can delete any user without this permission.")},
|
||||
{Policies.CanModifyStoreSettings, ("Modify your stores", "Allows managing invoices on all your stores and modify their settings.")},
|
||||
{$"{Policies.CanModifyStoreSettings}:", ("Manage selected stores", "Allows managing invoices on the selected stores and modify their settings.")},
|
||||
{Policies.CanViewCustodianAccounts, ("View exchange accounts linked to your stores", "Allows seeing exchange accounts linked to your stores.")},
|
||||
{$"{Policies.CanViewCustodianAccounts}:", ("View exchange accounts linked to selected stores", "Allows seeing exchange accounts linked to the selected stores.")},
|
||||
{Policies.CanManageCustodianAccounts, ("Manage exchange accounts linked to your stores", "Allows modifying exchange accounts linked to your stores.")},
|
||||
{$"{Policies.CanManageCustodianAccounts}:", ("Manage exchange accounts linked to selected stores", "Allows modifying exchange accounts linked to selected stores.")},
|
||||
{Policies.CanDepositToCustodianAccounts, ("Deposit funds to exchange accounts linked to your stores", "Allows depositing funds to your exchange accounts.")},
|
||||
{$"{Policies.CanDepositToCustodianAccounts}:", ("Deposit funds to exchange accounts linked to selected stores", "Allows depositing funds to selected store's exchange accounts.")},
|
||||
{Policies.CanWithdrawFromCustodianAccounts, ("Withdraw funds from exchange accounts to your store", "Allows withdrawing funds from your exchange accounts to your store.")},
|
||||
{$"{Policies.CanWithdrawFromCustodianAccounts}:", ("Withdraw funds from selected store's exchange accounts", "Allows withdrawing funds from your selected store's exchange accounts.")},
|
||||
{Policies.CanTradeCustodianAccount, ("Trade funds on your store's exchange accounts", "Allows trading funds on your store's exchange accounts.")},
|
||||
{$"{Policies.CanTradeCustodianAccount}:", ("Trade funds on selected store's exchange accounts", "Allows trading funds on selected store's exchange accounts.")},
|
||||
{Policies.CanModifyStoreWebhooks, ("Modify stores webhooks", "Allows modifying the webhooks of all your stores.")},
|
||||
{$"{Policies.CanModifyStoreWebhooks}:", ("Modify selected stores' webhooks", "Allows modifying the webhooks of the selected stores.")},
|
||||
{Policies.CanViewStoreSettings, ("View your stores", "Allows viewing stores settings.")},
|
||||
{$"{Policies.CanViewStoreSettings}:", ("View your stores", "Allows viewing the selected stores' settings.")},
|
||||
{Policies.CanModifyServerSettings, ("Manage your server", "Grants total control on the server settings of your server.")},
|
||||
{Policies.CanViewProfile, ("View your profile", "Allows viewing your user profile.")},
|
||||
{Policies.CanModifyProfile, ("Manage your profile", "Allows viewing and modifying your user profile.")},
|
||||
{Policies.CanManageNotificationsForUser, ("Manage your notifications", "Allows viewing and modifying your user notifications.")},
|
||||
{Policies.CanViewNotificationsForUser, ("View your notifications", "Allows viewing your user notifications.")},
|
||||
{Policies.CanCreateInvoice, ("Create an invoice", "Allows creating new invoices.")},
|
||||
{$"{Policies.CanCreateInvoice}:", ("Create an invoice", "Allows creating new invoices on the selected stores.")},
|
||||
{Policies.CanViewInvoices, ("View invoices", "Allows viewing invoices.")},
|
||||
{Policies.CanModifyInvoices, ("Modify invoices", "Allows viewing and modifying invoices.")},
|
||||
{$"{Policies.CanViewInvoices}:", ("View invoices", "Allows viewing invoices on the selected stores.")},
|
||||
{$"{Policies.CanModifyInvoices}:", ("Modify invoices", "Allows viewing and modifying invoices on the selected stores.")},
|
||||
{Policies.CanModifyPaymentRequests, ("Modify your payment requests", "Allows viewing, modifying, deleting and creating new payment requests on all your stores.")},
|
||||
{$"{Policies.CanModifyPaymentRequests}:", ("Manage selected stores' payment requests", "Allows viewing, modifying, deleting and creating new payment requests on the selected stores.")},
|
||||
{Policies.CanViewPaymentRequests, ("View your payment requests", "Allows viewing payment requests.")},
|
||||
{$"{Policies.CanViewPaymentRequests}:", ("View your payment requests", "Allows viewing the selected stores' payment requests.")},
|
||||
{Policies.CanManagePullPayments, ("Manage your pull payments", "Allows viewing, modifying, deleting and creating pull payments on all your stores.")},
|
||||
{$"{Policies.CanManagePullPayments}:", ("Manage selected stores' pull payments", "Allows viewing, modifying, deleting and creating pull payments on the selected stores.")},
|
||||
{Policies.CanCreatePullPayments, ("Create pull payments", "Allows creating pull payments on all your stores.")},
|
||||
{$"{Policies.CanCreatePullPayments}:", ("Create pull payments in selected stores", "Allows creating pull payments on the selected stores.")},
|
||||
{Policies.CanCreateNonApprovedPullPayments, ("Create non-approved pull payments", "Allows creating pull payments without automatic approval on all your stores.")},
|
||||
{$"{Policies.CanCreateNonApprovedPullPayments}:", ("Create non-approved pull payments in selected stores", "Allows viewing, modifying, deleting and creating pull payments without automatic approval on the selected stores.")},
|
||||
{Policies.CanUseInternalLightningNode, ("Use the internal lightning node", "Allows using the internal BTCPay Server lightning node to create BOLT11 invoices, connect to other nodes, open new channels and pay BOLT11 invoices.")},
|
||||
{Policies.CanViewLightningInvoiceInternalNode, ("View invoices from internal lightning node", "Allows using the internal BTCPay Server lightning node to view BOLT11 invoices.")},
|
||||
{Policies.CanCreateLightningInvoiceInternalNode, ("Create invoices with internal lightning node", "Allows using the internal BTCPay Server lightning node to create BOLT11 invoices.")},
|
||||
{Policies.CanUseLightningNodeInStore, ("Use the lightning nodes associated with your stores", "Allows using the lightning nodes connected to all your stores to create BOLT11 invoices, connect to other nodes, open new channels and pay BOLT11 invoices.")},
|
||||
{Policies.CanViewLightningInvoiceInStore, ("View the lightning invoices associated with your stores", "Allows viewing the lightning invoices connected to all your stores.")},
|
||||
{Policies.CanCreateLightningInvoiceInStore, ("Create invoices from the lightning nodes associated with your stores", "Allows using the lightning nodes connected to all your stores to create BOLT11 invoices.")},
|
||||
{$"{Policies.CanUseLightningNodeInStore}:", ("Use the lightning nodes associated with your stores", "Allows using the lightning nodes connected to the selected stores to create BOLT11 invoices, connect to other nodes, open new channels and pay BOLT11 invoices.")},
|
||||
{$"{Policies.CanViewLightningInvoiceInStore}:", ("View the lightning invoices associated with your stores", "Allows viewing the lightning invoices connected to the selected stores.")},
|
||||
{$"{Policies.CanCreateLightningInvoiceInStore}:", ("Create invoices from the lightning nodes associated with your stores", "Allows using the lightning nodes connected to the selected stores to create BOLT11 invoices.")},
|
||||
};
|
||||
public string Title
|
||||
{
|
||||
|
@ -78,16 +78,20 @@ namespace BTCPayServer.Controllers
|
||||
model = this.ParseListQuery(model ?? new ListPaymentRequestsViewModel());
|
||||
|
||||
var store = GetCurrentStore();
|
||||
var includeArchived = new SearchString(model.SearchTerm, model.TimezoneOffset ?? 0).GetFilterBool("includearchived") == true;
|
||||
var fs = new SearchString(model.SearchTerm, model.TimezoneOffset ?? 0);
|
||||
var result = await _PaymentRequestRepository.FindPaymentRequests(new PaymentRequestQuery
|
||||
{
|
||||
UserId = GetUserId(),
|
||||
StoreId = store.Id,
|
||||
Skip = model.Skip,
|
||||
Count = model.Count,
|
||||
IncludeArchived = includeArchived
|
||||
Status = fs.GetFilterArray("status")?.Select(s => Enum.Parse<Client.Models.PaymentRequestData.PaymentRequestStatus>(s, true)).ToArray(),
|
||||
IncludeArchived = fs.GetFilterBool("includearchived") ?? false
|
||||
});
|
||||
|
||||
|
||||
model.Search = fs;
|
||||
model.SearchText = fs.TextSearch;
|
||||
|
||||
model.Items = result.Select(data =>
|
||||
{
|
||||
var blob = data.GetBlob();
|
||||
|
@ -66,7 +66,7 @@ namespace BTCPayServer.Controllers
|
||||
|
||||
private LightningSupportedPaymentMethod GetExistingLightningSupportedPaymentMethod(string cryptoCode, StoreData store)
|
||||
{
|
||||
var id = new PaymentMethodId(cryptoCode, LightningPaymentType.Instance);
|
||||
var id = new PaymentMethodId(cryptoCode, PaymentTypes.LightningLike);
|
||||
var existing = store.GetSupportedPaymentMethods(_BtcPayNetworkProvider)
|
||||
.OfType<LightningSupportedPaymentMethod>()
|
||||
.FirstOrDefault(d => d.PaymentId == id);
|
||||
@ -76,7 +76,7 @@ namespace BTCPayServer.Controllers
|
||||
|
||||
private string GetImage(PaymentMethodId paymentMethodId, BTCPayNetwork network)
|
||||
{
|
||||
var res = paymentMethodId.PaymentType == BitcoinPaymentType.Instance
|
||||
var res = paymentMethodId.PaymentType == PaymentTypes.BTCLike
|
||||
? Url.Content(network.CryptoImagePath)
|
||||
: Url.Content(network.LightningImagePath);
|
||||
return "/" + res;
|
||||
|
@ -29,19 +29,19 @@ namespace BTCPayServer.Controllers
|
||||
private readonly CurrencyNameTable _currencyNameTable;
|
||||
private readonly DisplayFormatter _displayFormatter;
|
||||
private readonly PullPaymentHostedService _pullPaymentHostedService;
|
||||
private readonly BTCPayNetworkProvider _networkProvider;
|
||||
private readonly BTCPayNetworkJsonSerializerSettings _serializerSettings;
|
||||
private readonly IEnumerable<IPayoutHandler> _payoutHandlers;
|
||||
private readonly StoreRepository _storeRepository;
|
||||
private readonly PaymentTypeRegistry _paymentTypeRegistry;
|
||||
|
||||
public UIPullPaymentController(ApplicationDbContextFactory dbContextFactory,
|
||||
CurrencyNameTable currencyNameTable,
|
||||
DisplayFormatter displayFormatter,
|
||||
PullPaymentHostedService pullPaymentHostedService,
|
||||
BTCPayNetworkProvider networkProvider,
|
||||
BTCPayNetworkJsonSerializerSettings serializerSettings,
|
||||
IEnumerable<IPayoutHandler> payoutHandlers,
|
||||
StoreRepository storeRepository,
|
||||
PaymentTypeRegistry paymentTypeRegistry)
|
||||
StoreRepository storeRepository)
|
||||
{
|
||||
_dbContextFactory = dbContextFactory;
|
||||
_currencyNameTable = currencyNameTable;
|
||||
@ -50,7 +50,7 @@ namespace BTCPayServer.Controllers
|
||||
_serializerSettings = serializerSettings;
|
||||
_payoutHandlers = payoutHandlers;
|
||||
_storeRepository = storeRepository;
|
||||
_paymentTypeRegistry = paymentTypeRegistry;
|
||||
_networkProvider = networkProvider;
|
||||
}
|
||||
|
||||
[AllowAnonymous]
|
||||
@ -99,12 +99,19 @@ namespace BTCPayServer.Controllers
|
||||
Currency = blob.Currency,
|
||||
Status = entity.Entity.State,
|
||||
Destination = entity.Blob.Destination,
|
||||
PaymentMethod = _paymentTypeRegistry.ParsePaymentMethod(entity.Entity.PaymentMethodId),
|
||||
PaymentMethod = PaymentMethodId.Parse(entity.Entity.PaymentMethodId),
|
||||
Link = entity.ProofBlob?.Link,
|
||||
TransactionId = entity.ProofBlob?.Id
|
||||
}).ToList()
|
||||
};
|
||||
vm.IsPending &= vm.AmountDue > 0.0m;
|
||||
|
||||
if (_pullPaymentHostedService.SupportsLNURL(blob))
|
||||
{
|
||||
var url = Url.Action("GetLNURLForPullPayment", "UILNURL", new { cryptoCode = _networkProvider.DefaultNetwork.CryptoCode, pullPaymentId = vm.Id }, Request.Scheme, Request.Host.ToString());
|
||||
vm.LnurlEndpoint = url != null ? new Uri(url) : null;
|
||||
}
|
||||
|
||||
return View(nameof(ViewPullPayment), vm);
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,7 @@ using BTCPayServer.Storage.Services;
|
||||
using BTCPayServer.Storage.Services.Providers;
|
||||
using BTCPayServer.Validation;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Cors;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
@ -664,6 +665,8 @@ namespace BTCPayServer.Controllers
|
||||
|
||||
[Route("lnd-config/{configKey}/lnd.config")]
|
||||
[AllowAnonymous]
|
||||
[EnableCors(CorsPolicies.All)]
|
||||
[IgnoreAntiforgeryToken]
|
||||
public IActionResult GetLNDConfig(ulong configKey)
|
||||
{
|
||||
var conf = _LnConfigProvider.GetConfig(configKey);
|
||||
|
@ -117,7 +117,7 @@ namespace BTCPayServer.Controllers
|
||||
}
|
||||
|
||||
var network = _ExplorerProvider.GetNetwork(vm.CryptoCode);
|
||||
var paymentMethodId = new PaymentMethodId(network.CryptoCode, LightningPaymentType.Instance);
|
||||
var paymentMethodId = new PaymentMethodId(network.CryptoCode, PaymentTypes.LightningLike);
|
||||
|
||||
LightningSupportedPaymentMethod? paymentMethod = null;
|
||||
if (vm.LightningNodeType == LightningNodeType.Internal)
|
||||
@ -175,7 +175,7 @@ namespace BTCPayServer.Controllers
|
||||
switch (command)
|
||||
{
|
||||
case "save":
|
||||
var lnurl = new PaymentMethodId(vm.CryptoCode, LNURLPayPaymentType.Instance);
|
||||
var lnurl = new PaymentMethodId(vm.CryptoCode, PaymentTypes.LNURLPay);
|
||||
store.SetSupportedPaymentMethod(paymentMethodId, paymentMethod);
|
||||
store.SetSupportedPaymentMethod(lnurl, new LNURLPaySupportedPaymentMethod()
|
||||
{
|
||||
@ -275,7 +275,7 @@ namespace BTCPayServer.Controllers
|
||||
blob.LightningAmountInSatoshi = vm.LightningAmountInSatoshi;
|
||||
blob.LightningPrivateRouteHints = vm.LightningPrivateRouteHints;
|
||||
blob.OnChainWithLnInvoiceFallback = vm.OnChainWithLnInvoiceFallback;
|
||||
var lnurlId = new PaymentMethodId(vm.CryptoCode, LNURLPayPaymentType.Instance);
|
||||
var lnurlId = new PaymentMethodId(vm.CryptoCode, PaymentTypes.LNURLPay);
|
||||
blob.SetExcluded(lnurlId, !vm.LNURLEnabled);
|
||||
|
||||
var lnurl = GetExistingLNURLSupportedPaymentMethod(vm.CryptoCode, store);
|
||||
@ -323,12 +323,12 @@ namespace BTCPayServer.Controllers
|
||||
if (lightning == null)
|
||||
return NotFound();
|
||||
|
||||
var paymentMethodId = new PaymentMethodId(network.CryptoCode, LightningPaymentType.Instance);
|
||||
var paymentMethodId = new PaymentMethodId(network.CryptoCode, PaymentTypes.LightningLike);
|
||||
var storeBlob = store.GetStoreBlob();
|
||||
storeBlob.SetExcluded(paymentMethodId, !enabled);
|
||||
if (!enabled)
|
||||
{
|
||||
storeBlob.SetExcluded(new PaymentMethodId(network.CryptoCode, LNURLPayPaymentType.Instance), true);
|
||||
storeBlob.SetExcluded(new PaymentMethodId(network.CryptoCode, PaymentTypes.LNURLPay), true);
|
||||
}
|
||||
store.SetStoreBlob(storeBlob);
|
||||
await _Repo.UpdateStore(store);
|
||||
@ -360,7 +360,7 @@ namespace BTCPayServer.Controllers
|
||||
|
||||
private LightningSupportedPaymentMethod? GetExistingLightningSupportedPaymentMethod(string cryptoCode, StoreData store)
|
||||
{
|
||||
var id = new PaymentMethodId(cryptoCode, LightningPaymentType.Instance);
|
||||
var id = new PaymentMethodId(cryptoCode, PaymentTypes.LightningLike);
|
||||
var existing = store.GetSupportedPaymentMethods(_NetworkProvider)
|
||||
.OfType<LightningSupportedPaymentMethod>()
|
||||
.FirstOrDefault(d => d.PaymentId == id);
|
||||
@ -369,7 +369,7 @@ namespace BTCPayServer.Controllers
|
||||
|
||||
private LNURLPaySupportedPaymentMethod? GetExistingLNURLSupportedPaymentMethod(string cryptoCode, StoreData store)
|
||||
{
|
||||
var id = new PaymentMethodId(cryptoCode, LNURLPayPaymentType.Instance);
|
||||
var id = new PaymentMethodId(cryptoCode, PaymentTypes.LNURLPay);
|
||||
var existing = store.GetSupportedPaymentMethods(_NetworkProvider)
|
||||
.OfType<LNURLPaySupportedPaymentMethod>()
|
||||
.FirstOrDefault(d => d.PaymentId == id);
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
@ -150,7 +151,7 @@ namespace BTCPayServer.Controllers
|
||||
vm.Config = ProtectString(strategy.ToJson());
|
||||
ModelState.Remove(nameof(vm.Config));
|
||||
|
||||
PaymentMethodId paymentMethodId = new PaymentMethodId(network.CryptoCode, BitcoinPaymentType.Instance);
|
||||
PaymentMethodId paymentMethodId = new PaymentMethodId(network.CryptoCode, PaymentTypes.BTCLike);
|
||||
var storeBlob = store.GetStoreBlob();
|
||||
if (vm.Confirmation)
|
||||
{
|
||||
@ -250,7 +251,7 @@ namespace BTCPayServer.Controllers
|
||||
CryptoCode = cryptoCode,
|
||||
Method = method,
|
||||
SetupRequest = request,
|
||||
Confirmation = string.IsNullOrEmpty(request.ExistingMnemonic),
|
||||
Confirmation = !isImport,
|
||||
Network = network,
|
||||
Source = isImport ? "SeedImported" : "NBXplorerGenerated",
|
||||
IsHotWallet = isImport ? request.SavePrivateKeys : method == WalletSetupMethod.HotWallet,
|
||||
@ -311,7 +312,7 @@ namespace BTCPayServer.Controllers
|
||||
|
||||
var result = await UpdateWallet(vm);
|
||||
|
||||
if (!ModelState.IsValid || !(result is RedirectToActionResult))
|
||||
if (!ModelState.IsValid || result is not RedirectToActionResult)
|
||||
return result;
|
||||
|
||||
if (!isImport)
|
||||
@ -719,7 +720,7 @@ namespace BTCPayServer.Controllers
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
PaymentMethodId paymentMethodId = new PaymentMethodId(network.CryptoCode, BitcoinPaymentType.Instance);
|
||||
PaymentMethodId paymentMethodId = new PaymentMethodId(network.CryptoCode, PaymentTypes.BTCLike);
|
||||
store.SetSupportedPaymentMethod(paymentMethodId, null);
|
||||
|
||||
await _Repo.UpdateStore(store);
|
||||
@ -768,7 +769,7 @@ namespace BTCPayServer.Controllers
|
||||
|
||||
private DerivationSchemeSettings GetExistingDerivationStrategy(string cryptoCode, StoreData store)
|
||||
{
|
||||
var id = new PaymentMethodId(cryptoCode, BitcoinPaymentType.Instance);
|
||||
var id = new PaymentMethodId(cryptoCode, PaymentTypes.BTCLike);
|
||||
var existing = store.GetSupportedPaymentMethods(_NetworkProvider)
|
||||
.OfType<DerivationSchemeSettings>()
|
||||
.FirstOrDefault(d => d.PaymentId == id);
|
||||
|
@ -373,7 +373,7 @@ namespace BTCPayServer.Controllers
|
||||
vm.PaymentMethodCriteria = CurrentStore.GetSupportedPaymentMethods(_NetworkProvider)
|
||||
.Where(s => !storeBlob.GetExcludedPaymentMethods().Match(s.PaymentId))
|
||||
.Where(s => _NetworkProvider.GetNetwork(s.PaymentId.CryptoCode) != null)
|
||||
.Where(s => s.PaymentId.PaymentType != LNURLPayPaymentType.Instance)
|
||||
.Where(s => s.PaymentId.PaymentType != PaymentTypes.LNURLPay)
|
||||
.Select(method =>
|
||||
{
|
||||
var existing = storeBlob.PaymentMethodCriteria.SingleOrDefault(criteria =>
|
||||
@ -440,8 +440,8 @@ namespace BTCPayServer.Controllers
|
||||
var defaultChoice = defaultPaymentId is not null ? defaultPaymentId.FindNearest(enabled) : null;
|
||||
if (defaultChoice is null)
|
||||
{
|
||||
defaultChoice = enabled.FirstOrDefault(e => e.CryptoCode == _NetworkProvider.DefaultNetwork.CryptoCode && e.PaymentType == BitcoinPaymentType.Instance) ??
|
||||
enabled.FirstOrDefault(e => e.CryptoCode == _NetworkProvider.DefaultNetwork.CryptoCode && e.PaymentType == LightningPaymentType.Instance) ??
|
||||
defaultChoice = enabled.FirstOrDefault(e => e.CryptoCode == _NetworkProvider.DefaultNetwork.CryptoCode && e.PaymentType == PaymentTypes.BTCLike) ??
|
||||
enabled.FirstOrDefault(e => e.CryptoCode == _NetworkProvider.DefaultNetwork.CryptoCode && e.PaymentType == PaymentTypes.LightningLike) ??
|
||||
enabled.FirstOrDefault();
|
||||
}
|
||||
var choices = GetEnabledPaymentMethodChoices(storeData);
|
||||
@ -485,15 +485,15 @@ namespace BTCPayServer.Controllers
|
||||
foreach (var newCriteria in model.PaymentMethodCriteria.ToList())
|
||||
{
|
||||
var paymentMethodId = PaymentMethodId.Parse(newCriteria.PaymentMethod);
|
||||
if (paymentMethodId.PaymentType == LightningPaymentType.Instance)
|
||||
if (paymentMethodId.PaymentType == PaymentTypes.LightningLike)
|
||||
model.PaymentMethodCriteria.Add(new PaymentMethodCriteriaViewModel()
|
||||
{
|
||||
PaymentMethod = new PaymentMethodId(paymentMethodId.CryptoCode, LNURLPayPaymentType.Instance).ToString(),
|
||||
PaymentMethod = new PaymentMethodId(paymentMethodId.CryptoCode, PaymentTypes.LNURLPay).ToString(),
|
||||
Type = newCriteria.Type,
|
||||
Value = newCriteria.Value
|
||||
});
|
||||
// Should not be able to set LNUrlPay criteria directly in UI
|
||||
if (paymentMethodId.PaymentType == LNURLPayPaymentType.Instance)
|
||||
if (paymentMethodId.PaymentType == PaymentTypes.LNURLPay)
|
||||
model.PaymentMethodCriteria.Remove(newCriteria);
|
||||
}
|
||||
blob.PaymentMethodCriteria ??= new List<PaymentMethodCriteria>();
|
||||
|
@ -398,7 +398,7 @@ askdevice:
|
||||
var paymentMethod = CurrentStore
|
||||
.GetSupportedPaymentMethods(Networks)
|
||||
.OfType<DerivationSchemeSettings>()
|
||||
.FirstOrDefault(p => p.PaymentId.PaymentType == Payments.BitcoinPaymentType.Instance && p.PaymentId.CryptoCode == walletId.CryptoCode);
|
||||
.FirstOrDefault(p => p.PaymentId.PaymentType == Payments.PaymentTypes.BTCLike && p.PaymentId.CryptoCode == walletId.CryptoCode);
|
||||
return paymentMethod;
|
||||
}
|
||||
}
|
||||
|
@ -66,7 +66,6 @@ namespace BTCPayServer.Controllers
|
||||
private readonly DelayedTransactionBroadcaster _broadcaster;
|
||||
private readonly PayjoinClient _payjoinClient;
|
||||
private readonly LabelService _labelService;
|
||||
private readonly PaymentTypeRegistry _paymentTypeRegistry;
|
||||
private readonly PullPaymentHostedService _pullPaymentHostedService;
|
||||
private readonly WalletHistogramService _walletHistogramService;
|
||||
|
||||
@ -90,12 +89,10 @@ namespace BTCPayServer.Controllers
|
||||
PayjoinClient payjoinClient,
|
||||
IServiceProvider serviceProvider,
|
||||
PullPaymentHostedService pullPaymentHostedService,
|
||||
LabelService labelService,
|
||||
PaymentTypeRegistry paymentTypeRegistry)
|
||||
LabelService labelService)
|
||||
{
|
||||
_currencyTable = currencyTable;
|
||||
_labelService = labelService;
|
||||
_paymentTypeRegistry = paymentTypeRegistry;
|
||||
Repository = repo;
|
||||
WalletRepository = walletRepository;
|
||||
RateFetcher = rateProvider;
|
||||
@ -174,7 +171,7 @@ namespace BTCPayServer.Controllers
|
||||
var stores = await Repository.GetStoresByUserId(GetUserId());
|
||||
|
||||
var onChainWallets = stores
|
||||
.SelectMany(s => s.GetSupportedPaymentMethods(NetworkProvider, _paymentTypeRegistry)
|
||||
.SelectMany(s => s.GetSupportedPaymentMethods(NetworkProvider)
|
||||
.OfType<DerivationSchemeSettings>()
|
||||
.Select(d => ((Wallet: _walletProvider.GetWallet(d.Network),
|
||||
DerivationStrategy: d.AccountDerivation,
|
||||
@ -215,7 +212,9 @@ namespace BTCPayServer.Controllers
|
||||
WalletId walletId,
|
||||
string? labelFilter = null,
|
||||
int skip = 0,
|
||||
int count = 50
|
||||
int count = 50,
|
||||
bool loadTransactions = false,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
var paymentMethod = GetDerivationSchemeSettings(walletId);
|
||||
@ -226,25 +225,25 @@ namespace BTCPayServer.Controllers
|
||||
|
||||
// We can't filter at the database level if we need to apply label filter
|
||||
var preFiltering = string.IsNullOrEmpty(labelFilter);
|
||||
var transactions = await wallet.FetchTransactionHistory(paymentMethod.AccountDerivation, preFiltering ? skip : null, preFiltering ? count : null);
|
||||
var walletTransactionsInfo = await WalletRepository.GetWalletTransactionsInfo(walletId, transactions.Select(t => t.TransactionId.ToString()).ToArray());
|
||||
var model = new ListTransactionsViewModel { Skip = skip, Count = count };
|
||||
model.Labels.AddRange(
|
||||
(await WalletRepository.GetWalletLabels(walletId))
|
||||
.Select(c => (c.Label, c.Color, ColorPalette.Default.TextColor(c.Color))));
|
||||
|
||||
IList<TransactionHistoryLine>? transactions = null;
|
||||
Dictionary<string, WalletTransactionInfo>? walletTransactionsInfo = null;
|
||||
if (loadTransactions)
|
||||
{
|
||||
transactions = await wallet.FetchTransactionHistory(paymentMethod.AccountDerivation, preFiltering ? skip : null, preFiltering ? count : null, cancellationToken: cancellationToken);
|
||||
walletTransactionsInfo = await WalletRepository.GetWalletTransactionsInfo(walletId, transactions.Select(t => t.TransactionId.ToString()).ToArray());
|
||||
}
|
||||
|
||||
if (labelFilter != null)
|
||||
{
|
||||
model.PaginationQuery = new Dictionary<string, object> { { "labelFilter", labelFilter } };
|
||||
}
|
||||
if (transactions == null)
|
||||
if (transactions == null || walletTransactionsInfo is null)
|
||||
{
|
||||
TempData.SetStatusMessageModel(new StatusMessageModel()
|
||||
{
|
||||
Severity = StatusMessageModel.StatusSeverity.Error,
|
||||
Message =
|
||||
"There was an error retrieving the transactions list. Is NBXplorer configured correctly?"
|
||||
});
|
||||
model.Transactions = new List<ListTransactionsViewModel.TransactionViewModel>();
|
||||
}
|
||||
else
|
||||
@ -1314,7 +1313,7 @@ namespace BTCPayServer.Controllers
|
||||
[HttpGet("{walletId}/export")]
|
||||
public async Task<IActionResult> Export(
|
||||
[ModelBinder(typeof(WalletIdModelBinder))] WalletId walletId,
|
||||
string format, string? labelFilter = null)
|
||||
string format, string? labelFilter = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var paymentMethod = GetDerivationSchemeSettings(walletId);
|
||||
if (paymentMethod == null)
|
||||
@ -1322,7 +1321,7 @@ namespace BTCPayServer.Controllers
|
||||
|
||||
var wallet = _walletProvider.GetWallet(paymentMethod.Network);
|
||||
var walletTransactionsInfoAsync = WalletRepository.GetWalletTransactionsInfo(walletId, (string[]?)null);
|
||||
var input = await wallet.FetchTransactionHistory(paymentMethod.AccountDerivation);
|
||||
var input = await wallet.FetchTransactionHistory(paymentMethod.AccountDerivation, cancellationToken: cancellationToken);
|
||||
var walletTransactionsInfo = await walletTransactionsInfoAsync;
|
||||
var export = new TransactionsExport(wallet, walletTransactionsInfo);
|
||||
var res = export.Process(input, format);
|
||||
@ -1408,7 +1407,7 @@ namespace BTCPayServer.Controllers
|
||||
|
||||
private string GetImage(PaymentMethodId paymentMethodId, BTCPayNetwork network)
|
||||
{
|
||||
var res = paymentMethodId.PaymentType == BitcoinPaymentType.Instance
|
||||
var res = paymentMethodId.PaymentType == PaymentTypes.BTCLike
|
||||
? Url.Content(network.CryptoImagePath)
|
||||
: Url.Content(network.LightningImagePath);
|
||||
return Request.GetRelativePathOrAbsolute(res);
|
||||
|
@ -20,16 +20,16 @@ namespace BTCPayServer.Data
|
||||
addressInvoiceData.Address = address + "#" + paymentMethodId.ToString();
|
||||
return addressInvoiceData;
|
||||
}
|
||||
public static PaymentMethodId GetPaymentMethodId(this AddressInvoiceData addressInvoiceData, PaymentTypeRegistry paymentTypeRegistry)
|
||||
public static PaymentMethodId GetPaymentMethodId(this AddressInvoiceData addressInvoiceData)
|
||||
{
|
||||
if (addressInvoiceData.Address == null)
|
||||
return null;
|
||||
var index = addressInvoiceData.Address.LastIndexOf("#", StringComparison.InvariantCulture);
|
||||
// Legacy AddressInvoiceData does not have the paymentMethodId attached to the Address
|
||||
if (index == -1)
|
||||
return paymentTypeRegistry.ParsePaymentMethod("BTC");
|
||||
return PaymentMethodId.Parse("BTC");
|
||||
/////////////////////////
|
||||
return paymentTypeRegistry.ParsePaymentMethod(addressInvoiceData.Address.Substring(index + 1));
|
||||
return PaymentMethodId.Parse(addressInvoiceData.Address.Substring(index + 1));
|
||||
}
|
||||
#pragma warning restore CS0618
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ namespace BTCPayServer.Data
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
if (paymentData.Blob2 is not null)
|
||||
{
|
||||
if (!_paymentTypeRegistry.TryParsePaymentMethod(paymentData.Type, out var pmi))
|
||||
if (!PaymentMethodId.TryParse(paymentData.Type, out var pmi))
|
||||
return null;
|
||||
var network = networks.GetNetwork<BTCPayNetworkBase>(pmi.CryptoCode);
|
||||
if (network is null)
|
||||
|
@ -37,7 +37,6 @@ public class BitcoinLikePayoutHandler : IPayoutHandler
|
||||
private readonly ApplicationDbContextFactory _dbContextFactory;
|
||||
private readonly NotificationSender _notificationSender;
|
||||
private readonly Logs Logs;
|
||||
private readonly PaymentTypeRegistry _paymentTypeRegistry;
|
||||
|
||||
public WalletRepository WalletRepository { get; }
|
||||
|
||||
@ -47,8 +46,7 @@ public class BitcoinLikePayoutHandler : IPayoutHandler
|
||||
BTCPayNetworkJsonSerializerSettings jsonSerializerSettings,
|
||||
ApplicationDbContextFactory dbContextFactory,
|
||||
NotificationSender notificationSender,
|
||||
Logs logs,
|
||||
PaymentTypeRegistry paymentTypeRegistry)
|
||||
Logs logs)
|
||||
{
|
||||
_btcPayNetworkProvider = btcPayNetworkProvider;
|
||||
WalletRepository = walletRepository;
|
||||
@ -57,7 +55,6 @@ public class BitcoinLikePayoutHandler : IPayoutHandler
|
||||
_dbContextFactory = dbContextFactory;
|
||||
_notificationSender = notificationSender;
|
||||
this.Logs = logs;
|
||||
_paymentTypeRegistry = paymentTypeRegistry;
|
||||
}
|
||||
|
||||
|
||||
@ -218,7 +215,7 @@ public class BitcoinLikePayoutHandler : IPayoutHandler
|
||||
Stores = new[] { storeId },
|
||||
PayoutIds = payoutIds
|
||||
}, context)).Where(data =>
|
||||
_paymentTypeRegistry.TryParsePaymentMethod(data.PaymentMethodId, out var paymentMethodId) &&
|
||||
PaymentMethodId.TryParse(data.PaymentMethodId, out var paymentMethodId) &&
|
||||
CanHandle(paymentMethodId))
|
||||
.Select(data => (data, ParseProof(data) as PayoutTransactionOnChainBlob)).Where(tuple => tuple.Item2 != null && tuple.Item2.TransactionId != null && tuple.Item2.Accounted == false);
|
||||
foreach (var valueTuple in payouts)
|
||||
@ -243,7 +240,7 @@ public class BitcoinLikePayoutHandler : IPayoutHandler
|
||||
Stores = new[] { storeId },
|
||||
PayoutIds = payoutIds
|
||||
}, context)).Where(data =>
|
||||
_paymentTypeRegistry.TryParsePaymentMethod(data.PaymentMethodId, out var paymentMethodId) &&
|
||||
PaymentMethodId.TryParse(data.PaymentMethodId, out var paymentMethodId) &&
|
||||
CanHandle(paymentMethodId))
|
||||
.Select(data => (data, ParseProof(data) as PayoutTransactionOnChainBlob)).Where(tuple => tuple.Item2 != null && tuple.Item2.TransactionId != null && tuple.Item2.Accounted == true);
|
||||
foreach (var valueTuple in payouts)
|
||||
|
@ -96,7 +96,7 @@ namespace BTCPayServer.Data.Payouts.LightningLike
|
||||
{
|
||||
await SetStoreContext();
|
||||
|
||||
var pmi = new PaymentMethodId(cryptoCode, LightningPaymentType.Instance);
|
||||
var pmi = new PaymentMethodId(cryptoCode, PaymentTypes.LightningLike);
|
||||
|
||||
await using var ctx = _applicationDbContextFactory.CreateContext();
|
||||
var payouts = await GetPayouts(ctx, pmi, payoutIds);
|
||||
@ -120,7 +120,7 @@ namespace BTCPayServer.Data.Payouts.LightningLike
|
||||
{
|
||||
await SetStoreContext();
|
||||
|
||||
var pmi = new PaymentMethodId(cryptoCode, LightningPaymentType.Instance);
|
||||
var pmi = new PaymentMethodId(cryptoCode, PaymentTypes.LightningLike);
|
||||
var payoutHandler = (LightningLikePayoutHandler)_payoutHandlers.FindPayoutHandler(pmi);
|
||||
|
||||
await using var ctx = _applicationDbContextFactory.CreateContext();
|
||||
|
@ -30,7 +30,7 @@ namespace BTCPayServer.Data
|
||||
|
||||
public static PaymentMethodId GetPaymentMethodId(this PayoutData data)
|
||||
{
|
||||
return _paymentTypeRegistry.TryParsePaymentMethod(data.PaymentMethodId, out var paymentMethodId) ? paymentMethodId : null;
|
||||
return PaymentMethodId.TryParse(data.PaymentMethodId, out var paymentMethodId) ? paymentMethodId : null;
|
||||
}
|
||||
|
||||
public static PayoutBlob GetBlob(this PayoutData data, BTCPayNetworkJsonSerializerSettings serializers)
|
||||
|
@ -199,7 +199,9 @@ namespace BTCPayServer.Data
|
||||
{ "GTQ", "bitpay" },
|
||||
{ "COP", "yadio" },
|
||||
{ "JPY", "bitbank" },
|
||||
{ "TRY", "btcturk" }
|
||||
{ "TRY", "btcturk" },
|
||||
{ "UGX", "exchangeratehost"},
|
||||
{ "RSD", "bitpay"}
|
||||
};
|
||||
|
||||
public string GetRecommendedExchange() =>
|
||||
|
@ -18,25 +18,25 @@ namespace BTCPayServer.Data
|
||||
{
|
||||
|
||||
#pragma warning disable CS0618
|
||||
public static PaymentMethodId? GetDefaultPaymentId(this StoreData storeData, PaymentTypeRegistry paymentTypeRegistry)
|
||||
public static PaymentMethodId? GetDefaultPaymentId(this StoreData storeData)
|
||||
{
|
||||
paymentTypeRegistry.TryParsePaymentMethod(storeData.DefaultCrypto, out var defaultPaymentId);
|
||||
PaymentMethodId.TryParse(storeData.DefaultCrypto, out var defaultPaymentId);
|
||||
return defaultPaymentId;
|
||||
}
|
||||
|
||||
public static PaymentMethodId[] GetEnabledPaymentIds(this StoreData storeData, BTCPayNetworkProvider networks, PaymentTypeRegistry paymentTypeRegistry)
|
||||
public static PaymentMethodId[] GetEnabledPaymentIds(this StoreData storeData, BTCPayNetworkProvider networks)
|
||||
{
|
||||
return GetEnabledPaymentMethods(storeData, networks, paymentTypeRegistry).Select(method => method.PaymentId).ToArray();
|
||||
return GetEnabledPaymentMethods(storeData, networks).Select(method => method.PaymentId).ToArray();
|
||||
}
|
||||
|
||||
public static ISupportedPaymentMethod[] GetEnabledPaymentMethods(this StoreData storeData, BTCPayNetworkProvider networks, PaymentTypeRegistry paymentTypeRegistry)
|
||||
public static ISupportedPaymentMethod[] GetEnabledPaymentMethods(this StoreData storeData, BTCPayNetworkProvider networks)
|
||||
{
|
||||
var excludeFilter = storeData.GetStoreBlob().GetExcludedPaymentMethods();
|
||||
var paymentMethodIds = storeData.GetSupportedPaymentMethods(networks, paymentTypeRegistry)
|
||||
var paymentMethodIds = storeData.GetSupportedPaymentMethods(networks)
|
||||
.Where(a => !excludeFilter.Match(a.PaymentId))
|
||||
.OrderByDescending(a => a.PaymentId.CryptoCode == "BTC")
|
||||
.ThenBy(a => a.PaymentId.CryptoCode)
|
||||
.ThenBy(a => a.PaymentId.PaymentType == LightningPaymentType.Instance ? 1 : 0)
|
||||
.ThenBy(a => a.PaymentId.PaymentType == PaymentTypes.LightningLike ? 1 : 0)
|
||||
.ToArray();
|
||||
return paymentMethodIds;
|
||||
}
|
||||
@ -69,7 +69,7 @@ namespace BTCPayServer.Data
|
||||
return true;
|
||||
}
|
||||
|
||||
public static IEnumerable<ISupportedPaymentMethod> GetSupportedPaymentMethods(this StoreData storeData, BTCPayNetworkProvider networks, PaymentTypeRegistry paymentTypeRegistry)
|
||||
public static IEnumerable<ISupportedPaymentMethod> GetSupportedPaymentMethods(this StoreData storeData, BTCPayNetworkProvider networks)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(storeData);
|
||||
#pragma warning disable CS0618
|
||||
@ -80,14 +80,14 @@ namespace BTCPayServer.Data
|
||||
JObject strategies = JObject.Parse(storeData.DerivationStrategies);
|
||||
foreach (var strat in strategies.Properties())
|
||||
{
|
||||
if (!paymentTypeRegistry.TryParsePaymentMethod(strat.Name, out var paymentMethodId))
|
||||
if (!PaymentMethodId.TryParse(strat.Name, out var paymentMethodId))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var network = networks.GetNetwork<BTCPayNetworkBase>(paymentMethodId.CryptoCode);
|
||||
if (network != null)
|
||||
{
|
||||
if (network == networks.BTC && paymentMethodId.PaymentType == BitcoinPaymentType.Instance && btcReturned)
|
||||
if (network == networks.BTC && paymentMethodId.PaymentType == PaymentTypes.BTCLike && btcReturned)
|
||||
continue;
|
||||
if (strat.Value.Type == JTokenType.Null)
|
||||
continue;
|
||||
@ -127,8 +127,11 @@ namespace BTCPayServer.Data
|
||||
bool existing = false;
|
||||
foreach (var strat in strategies.Properties().ToList())
|
||||
{
|
||||
|
||||
if (strat.Name == paymentMethodId.PaymentType.GetPaymentMethodId(paymentMethodId))
|
||||
if (!PaymentMethodId.TryParse(strat.Name, out var stratId))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (stratId == paymentMethodId)
|
||||
{
|
||||
if (supportedPaymentMethod == null)
|
||||
{
|
||||
@ -148,19 +151,19 @@ namespace BTCPayServer.Data
|
||||
#pragma warning restore CS0618
|
||||
}
|
||||
|
||||
public static bool IsLightningEnabled(this StoreData storeData, BTCPayNetworkProvider networks, string cryptoCode, PaymentTypeRegistry paymentTypeRegistry)
|
||||
public static bool IsLightningEnabled(this StoreData storeData, BTCPayNetworkProvider networks, string cryptoCode)
|
||||
{
|
||||
return IsPaymentTypeEnabled(storeData, networks, cryptoCode, LightningPaymentType.Instance, paymentTypeRegistry);
|
||||
return IsPaymentTypeEnabled(storeData, networks, cryptoCode, LightningPaymentType.Instance);
|
||||
}
|
||||
|
||||
public static bool IsLNUrlEnabled(this StoreData storeData, BTCPayNetworkProvider networks, string cryptoCode, PaymentTypeRegistry paymentTypeRegistry)
|
||||
public static bool IsLNUrlEnabled(this StoreData storeData, BTCPayNetworkProvider networks, string cryptoCode)
|
||||
{
|
||||
return IsPaymentTypeEnabled(storeData, networks, cryptoCode, LNURLPayPaymentType.Instance, paymentTypeRegistry);
|
||||
return IsPaymentTypeEnabled(storeData, networks, cryptoCode, LNURLPayPaymentType.Instance);
|
||||
}
|
||||
|
||||
private static bool IsPaymentTypeEnabled(this StoreData storeData, BTCPayNetworkProvider networks, string cryptoCode, PaymentType paymentType, PaymentTypeRegistry paymentTypeRegistry)
|
||||
private static bool IsPaymentTypeEnabled(this StoreData storeData, BTCPayNetworkProvider networks, string cryptoCode, PaymentType paymentType)
|
||||
{
|
||||
var paymentMethods = storeData.GetSupportedPaymentMethods(networks, paymentTypeRegistry);
|
||||
var paymentMethods = storeData.GetSupportedPaymentMethods(networks);
|
||||
var excludeFilters = storeData.GetStoreBlob().GetExcludedPaymentMethods();
|
||||
return paymentMethods.Any(method =>
|
||||
method.PaymentId.CryptoCode == cryptoCode &&
|
||||
|
@ -388,7 +388,7 @@ namespace BTCPayServer
|
||||
public string Label { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public PaymentMethodId PaymentId => new PaymentMethodId(Network.CryptoCode, BitcoinPaymentType.Instance);
|
||||
public PaymentMethodId PaymentId => new PaymentMethodId(Network.CryptoCode, PaymentTypes.BTCLike);
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
|
@ -105,16 +105,23 @@ namespace BTCPayServer
|
||||
|
||||
public static decimal RoundUp(decimal value, int precision)
|
||||
{
|
||||
for (int i = 0; i < precision; i++)
|
||||
try
|
||||
{
|
||||
value = value * 10m;
|
||||
for (int i = 0; i < precision; i++)
|
||||
{
|
||||
value = value * 10m;
|
||||
}
|
||||
value = Math.Ceiling(value);
|
||||
for (int i = 0; i < precision; i++)
|
||||
{
|
||||
value = value / 10m;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
value = Math.Ceiling(value);
|
||||
for (int i = 0; i < precision; i++)
|
||||
catch (OverflowException)
|
||||
{
|
||||
value = value / 10m;
|
||||
return value;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public static IServiceCollection AddScheduledTask<T>(this IServiceCollection services, TimeSpan every)
|
||||
@ -125,9 +132,9 @@ namespace BTCPayServer
|
||||
return services;
|
||||
}
|
||||
|
||||
public static PaymentMethodId GetpaymentMethodId(this InvoiceCryptoInfo info, PaymentTypeRegistry paymentTypeRegistry)
|
||||
public static PaymentMethodId GetpaymentMethodId(this InvoiceCryptoInfo info)
|
||||
{
|
||||
return new PaymentMethodId(info.CryptoCode, paymentTypeRegistry.Parse(info.PaymentType));
|
||||
return new PaymentMethodId(info.CryptoCode, PaymentTypes.Parse(info.PaymentType));
|
||||
}
|
||||
|
||||
public static async Task CloseSocket(this WebSocket webSocket)
|
||||
@ -148,7 +155,7 @@ namespace BTCPayServer
|
||||
public static IEnumerable<BitcoinLikePaymentData> GetAllBitcoinPaymentData(this InvoiceEntity invoice, bool accountedOnly)
|
||||
{
|
||||
return invoice.GetPayments(accountedOnly)
|
||||
.Where(p => p.GetPaymentMethodId()?.PaymentType == BitcoinPaymentType.Instance)
|
||||
.Where(p => p.GetPaymentMethodId()?.PaymentType == PaymentTypes.BTCLike)
|
||||
.Select(p => (BitcoinLikePaymentData)p.GetCryptoPaymentData())
|
||||
.Where(data => data != null);
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ namespace BTCPayServer
|
||||
var paymentMethod = store
|
||||
.GetSupportedPaymentMethods(networkProvider)
|
||||
.OfType<DerivationSchemeSettings>()
|
||||
.FirstOrDefault(p => p.PaymentId.PaymentType == Payments.BitcoinPaymentType.Instance && p.PaymentId.CryptoCode == cryptoCode);
|
||||
.FirstOrDefault(p => p.PaymentId.PaymentType == Payments.PaymentTypes.BTCLike && p.PaymentId.CryptoCode == cryptoCode);
|
||||
return paymentMethod;
|
||||
}
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ namespace BTCPayServer.HostedServices
|
||||
|
||||
// We keep backward compatibility with bitpay by passing BTC info to the notification
|
||||
// we don't pass other info, as it is a bad idea to use IPN data for logic processing (can be faked)
|
||||
var btcCryptoInfo = dto.CryptoInfo.FirstOrDefault(c => c.GetpaymentMethodId() == new PaymentMethodId("BTC", Payments.BitcoinPaymentType.Instance) && !string.IsNullOrEmpty(c.Address));
|
||||
var btcCryptoInfo = dto.CryptoInfo.FirstOrDefault(c => c.GetpaymentMethodId() == new PaymentMethodId("BTC", Payments.PaymentTypes.BTCLike) && !string.IsNullOrEmpty(c.Address));
|
||||
if (btcCryptoInfo != null)
|
||||
{
|
||||
#pragma warning disable CS0618
|
||||
|
@ -46,6 +46,8 @@ namespace BTCPayServer.HostedServices
|
||||
|
||||
public class PullPaymentHostedService : BaseAsyncService
|
||||
{
|
||||
private readonly string[] _lnurlSupportedCurrencies = { "BTC", "SATS" };
|
||||
|
||||
public class CancelRequest
|
||||
{
|
||||
public CancelRequest(string pullPaymentId)
|
||||
@ -337,6 +339,14 @@ namespace BTCPayServer.HostedServices
|
||||
}
|
||||
}
|
||||
|
||||
public bool SupportsLNURL(PullPaymentBlob blob)
|
||||
{
|
||||
var pms = blob.SupportedPaymentMethods.FirstOrDefault(id =>
|
||||
id.PaymentType == LightningPaymentType.Instance &&
|
||||
_networkProvider.DefaultNetwork.CryptoCode == id.CryptoCode);
|
||||
return pms is not null && _lnurlSupportedCurrencies.Contains(blob.Currency);
|
||||
}
|
||||
|
||||
public Task<RateResult> GetRate(PayoutData payout, string explicitRateRule, CancellationToken cancellationToken)
|
||||
{
|
||||
var ppBlob = payout.PullPaymentData?.GetBlob();
|
||||
@ -401,7 +411,7 @@ namespace BTCPayServer.HostedServices
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_paymentTypeRegistry.TryParsePaymentMethod(payout.PaymentMethodId, out var paymentMethod))
|
||||
if (!PaymentMethodId.TryParse(payout.PaymentMethodId, out var paymentMethod))
|
||||
{
|
||||
req.Completion.SetResult(new PayoutApproval.ApprovalResult(PayoutApproval.Result.NotFound, null));
|
||||
return;
|
||||
|
@ -520,6 +520,8 @@ namespace BTCPayServer.Hosting
|
||||
services.AddRateProvider<BitflyerRateProvider>();
|
||||
services.AddRateProvider<YadioRateProvider>();
|
||||
services.AddRateProvider<BtcTurkRateProvider>();
|
||||
services.AddRateProvider<FreeCurrencyRatesRateProvider>();
|
||||
services.AddRateProvider<ExchangeRateHostRateProvider>();
|
||||
|
||||
// Broken
|
||||
// Providers.Add("argoneum", new ArgoneumRateProvider(_httpClientFactory?.CreateClient("EXCHANGE_ARGONEUM")));
|
||||
|
@ -640,8 +640,6 @@ WHERE cte.""Id""=p.""Id""
|
||||
await using var ctx = _DBContextFactory.CreateContext();
|
||||
foreach (var app in await ctx.Apps.Include(data => data.StoreData).AsQueryable().ToArrayAsync())
|
||||
{
|
||||
ViewPointOfSaleViewModel.Item[] items;
|
||||
string newTemplate;
|
||||
switch (app.AppType)
|
||||
{
|
||||
case CrowdfundAppType.AppType:
|
||||
@ -651,13 +649,6 @@ WHERE cte.""Id""=p.""Id""
|
||||
settings1.TargetCurrency = app.StoreData.GetStoreBlob().DefaultCurrency;
|
||||
app.SetSettings(settings1);
|
||||
}
|
||||
items = AppService.Parse(settings1.PerksTemplate);
|
||||
newTemplate = AppService.SerializeTemplate(items);
|
||||
if (settings1.PerksTemplate != newTemplate)
|
||||
{
|
||||
settings1.PerksTemplate = newTemplate;
|
||||
app.SetSettings(settings1);
|
||||
};
|
||||
break;
|
||||
|
||||
case PointOfSaleAppType.AppType:
|
||||
@ -668,13 +659,6 @@ WHERE cte.""Id""=p.""Id""
|
||||
settings2.Currency = app.StoreData.GetStoreBlob().DefaultCurrency;
|
||||
app.SetSettings(settings2);
|
||||
}
|
||||
items = AppService.Parse(settings2.Template);
|
||||
newTemplate = AppService.SerializeTemplate(items);
|
||||
if (settings2.Template != newTemplate)
|
||||
{
|
||||
settings2.Template = newTemplate;
|
||||
app.SetSettings(settings2);
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ namespace BTCPayServer.JsonConverters
|
||||
return null;
|
||||
if (reader.TokenType != JsonToken.String)
|
||||
throw new JsonObjectException("A payment method id should be a string", reader);
|
||||
if (_paymentTypeRegistry.TryParsePaymentMethod((string)reader.Value, out var result))
|
||||
if (PaymentMethodId.TryParse((string)reader.Value, out var result))
|
||||
return result;
|
||||
return null;
|
||||
// We need to do this gracefully as we have removed support for a payment type in the past which will throw here on your store each time it is loaded.
|
||||
|
@ -2,7 +2,6 @@ using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Payments;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace BTCPayServer.ModelBinders
|
||||
{
|
||||
@ -22,8 +21,8 @@ namespace BTCPayServer.ModelBinders
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
var paymentTypeRegistry = bindingContext.HttpContext.RequestServices.GetRequiredService<PaymentTypeRegistry>();
|
||||
if (paymentTypeRegistry.TryParsePaymentMethod(key, out var paymentId))
|
||||
|
||||
if (PaymentMethodId.TryParse(key, out var paymentId))
|
||||
{
|
||||
bindingContext.Result = ModelBindingResult.Success(paymentId);
|
||||
}
|
||||
|
@ -18,6 +18,9 @@ namespace BTCPayServer.Models.PaymentRequestViewModels
|
||||
{
|
||||
public List<ViewPaymentRequestViewModel> Items { get; set; }
|
||||
public override int CurrentPageCount => Items.Count;
|
||||
|
||||
public SearchString Search { get; set; }
|
||||
public string SearchText { get; set; }
|
||||
}
|
||||
|
||||
public class UpdatePaymentRequestViewModel
|
||||
|
@ -1,3 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using NBXplorer.Models;
|
||||
|
||||
namespace BTCPayServer.Models.StoreViewModels
|
||||
|
@ -96,6 +96,7 @@ namespace BTCPayServer.Models
|
||||
public DateTimeOffset StartDate { get; set; }
|
||||
public DateTime LastRefreshed { get; set; }
|
||||
public CurrencyData CurrencyData { get; set; }
|
||||
public Uri LnurlEndpoint { get; set; }
|
||||
public bool Archived { get; set; }
|
||||
public bool AutoApprove { get; set; }
|
||||
|
||||
|
@ -8,7 +8,7 @@ namespace BTCPayServer.Payments.Bitcoin
|
||||
{
|
||||
public class BitcoinLikeOnChainPaymentMethod : IPaymentMethodDetails
|
||||
{
|
||||
public PaymentType GetPaymentType() => BitcoinPaymentType.Instance;
|
||||
public PaymentType GetPaymentType() => PaymentTypes.BTCLike;
|
||||
|
||||
public string GetPaymentDestination()
|
||||
{
|
||||
|
@ -10,7 +10,7 @@ namespace BTCPayServer.Payments.Bitcoin
|
||||
{
|
||||
public PaymentType GetPaymentType()
|
||||
{
|
||||
return BitcoinPaymentType.Instance;
|
||||
return PaymentTypes.BTCLike;
|
||||
}
|
||||
public BitcoinLikePaymentData()
|
||||
{
|
||||
|
@ -72,7 +72,7 @@ namespace BTCPayServer.Payments.Bitcoin
|
||||
if (model.Activated && bip21Case)
|
||||
{
|
||||
var lightningInfo = invoiceResponse.CryptoInfo.FirstOrDefault(a =>
|
||||
a.GetpaymentMethodId() == new PaymentMethodId(model.CryptoCode, LightningPaymentType.Instance));
|
||||
a.GetpaymentMethodId() == new PaymentMethodId(model.CryptoCode, PaymentTypes.LightningLike));
|
||||
if (lightningInfo is not null && !string.IsNullOrEmpty(lightningInfo.PaymentUrls?.BOLT11))
|
||||
{
|
||||
lightningFallback = lightningInfo.PaymentUrls.BOLT11;
|
||||
@ -80,7 +80,7 @@ namespace BTCPayServer.Payments.Bitcoin
|
||||
else
|
||||
{
|
||||
var lnurlInfo = invoiceResponse.CryptoInfo.FirstOrDefault(a =>
|
||||
a.GetpaymentMethodId() == new PaymentMethodId(model.CryptoCode, LNURLPayPaymentType.Instance));
|
||||
a.GetpaymentMethodId() == new PaymentMethodId(model.CryptoCode, PaymentTypes.LNURLPay));
|
||||
if (lnurlInfo is not null)
|
||||
{
|
||||
lightningFallback = lnurlInfo.PaymentUrls?.AdditionalData["LNURLP"].ToObject<string>();
|
||||
@ -169,7 +169,7 @@ namespace BTCPayServer.Payments.Bitcoin
|
||||
return _networkProvider
|
||||
.GetAll()
|
||||
.OfType<BTCPayNetwork>()
|
||||
.Select(network => new PaymentMethodId(network.CryptoCode, BitcoinPaymentType.Instance));
|
||||
.Select(network => new PaymentMethodId(network.CryptoCode, PaymentTypes.BTCLike));
|
||||
}
|
||||
|
||||
private string GetPaymentMethodName(BTCPayNetworkBase network)
|
||||
@ -194,7 +194,7 @@ namespace BTCPayServer.Payments.Bitcoin
|
||||
};
|
||||
}
|
||||
|
||||
public override PaymentType PaymentType => BitcoinPaymentType.Instance;
|
||||
public override PaymentType PaymentType => PaymentTypes.BTCLike;
|
||||
|
||||
public override async Task<IPaymentMethodDetails> CreatePaymentMethodDetails(
|
||||
InvoiceLogs logs,
|
||||
|
@ -246,7 +246,7 @@ namespace BTCPayServer.Payments.Bitcoin
|
||||
var paymentEntitiesByPrevOut = new Dictionary<OutPoint, PaymentEntity>();
|
||||
foreach (var payment in invoice.GetPayments(wallet.Network, false))
|
||||
{
|
||||
if (payment.GetPaymentMethodId()?.PaymentType != BitcoinPaymentType.Instance)
|
||||
if (payment.GetPaymentMethodId()?.PaymentType != PaymentTypes.BTCLike)
|
||||
continue;
|
||||
var paymentData = (BitcoinLikePaymentData)payment.GetCryptoPaymentData();
|
||||
if (!transactions.TryGetValue(paymentData.Outpoint.Hash, out TransactionResult tx))
|
||||
@ -365,7 +365,7 @@ namespace BTCPayServer.Payments.Bitcoin
|
||||
var strategy = GetDerivationStrategy(invoice, network);
|
||||
if (strategy == null)
|
||||
continue;
|
||||
var cryptoId = new PaymentMethodId(network.CryptoCode, BitcoinPaymentType.Instance);
|
||||
var cryptoId = new PaymentMethodId(network.CryptoCode, PaymentTypes.BTCLike);
|
||||
|
||||
if (!invoice.Support(cryptoId))
|
||||
continue;
|
||||
@ -402,7 +402,7 @@ namespace BTCPayServer.Payments.Bitcoin
|
||||
|
||||
private DerivationStrategyBase GetDerivationStrategy(InvoiceEntity invoice, BTCPayNetworkBase network)
|
||||
{
|
||||
return invoice.GetSupportedPaymentMethod<DerivationSchemeSettings>(new PaymentMethodId(network.CryptoCode, BitcoinPaymentType.Instance))
|
||||
return invoice.GetSupportedPaymentMethod<DerivationSchemeSettings>(new PaymentMethodId(network.CryptoCode, PaymentTypes.BTCLike))
|
||||
.Select(d => d.AccountDerivation)
|
||||
.FirstOrDefault();
|
||||
}
|
||||
@ -413,7 +413,7 @@ namespace BTCPayServer.Payments.Bitcoin
|
||||
invoice = (await UpdatePaymentStates(wallet, invoice.Id));
|
||||
if (invoice == null)
|
||||
return null;
|
||||
var paymentMethod = invoice.GetPaymentMethod(wallet.Network, BitcoinPaymentType.Instance);
|
||||
var paymentMethod = invoice.GetPaymentMethod(wallet.Network, PaymentTypes.BTCLike);
|
||||
wallet.InvalidateCache(strategy);
|
||||
_Aggregator.Publish(new InvoiceEvent(invoice, InvoiceEvent.ReceivedPayment) { Payment = payment });
|
||||
return invoice;
|
||||
|
@ -38,7 +38,7 @@ namespace BTCPayServer.Payments.Lightning
|
||||
Options = options;
|
||||
}
|
||||
|
||||
public override PaymentType PaymentType => LightningPaymentType.Instance;
|
||||
public override PaymentType PaymentType => PaymentTypes.LightningLike;
|
||||
|
||||
private const string UriScheme = "lightning:";
|
||||
|
||||
@ -49,7 +49,7 @@ namespace BTCPayServer.Payments.Lightning
|
||||
LNURLPaySupportedPaymentMethod supportedPaymentMethod, PaymentMethod paymentMethod, Data.StoreData store,
|
||||
BTCPayNetwork network, object preparePaymentObject, IEnumerable<PaymentMethodId> invoicePaymentMethods)
|
||||
{
|
||||
var lnPmi = new PaymentMethodId(supportedPaymentMethod.CryptoCode, LightningPaymentType.Instance);
|
||||
var lnPmi = new PaymentMethodId(supportedPaymentMethod.CryptoCode, PaymentTypes.LightningLike);
|
||||
var lnSupported = store.GetSupportedPaymentMethods(_networkProvider)
|
||||
.OfType<LightningSupportedPaymentMethod>()
|
||||
.SingleOrDefault(method => method.PaymentId == lnPmi);
|
||||
@ -76,7 +76,7 @@ namespace BTCPayServer.Payments.Lightning
|
||||
.GetAll()
|
||||
.OfType<BTCPayNetwork>()
|
||||
.Where(network => network.NBitcoinNetwork.Consensus.SupportSegwit && network.SupportLightning)
|
||||
.Select(network => new PaymentMethodId(network.CryptoCode, LNURLPayPaymentType.Instance));
|
||||
.Select(network => new PaymentMethodId(network.CryptoCode, PaymentTypes.LNURLPay));
|
||||
}
|
||||
|
||||
public override void PreparePaymentModel(PaymentModel model, InvoiceResponse invoiceResponse,
|
||||
|
@ -10,7 +10,7 @@ namespace BTCPayServer.Payments.Lightning
|
||||
public string CryptoCode { get; set; } = string.Empty;
|
||||
|
||||
[JsonIgnore]
|
||||
public PaymentMethodId PaymentId => new PaymentMethodId(CryptoCode, LNURLPayPaymentType.Instance);
|
||||
public PaymentMethodId PaymentId => new PaymentMethodId(CryptoCode, PaymentTypes.LNURLPay);
|
||||
|
||||
public bool UseBech32Scheme { get; set; }
|
||||
|
||||
|
@ -41,7 +41,7 @@ namespace BTCPayServer.Payments.Lightning
|
||||
|
||||
public PaymentType GetPaymentType()
|
||||
{
|
||||
return string.IsNullOrEmpty(PaymentType) ? LightningPaymentType.Instance : PaymentTypes.Parse(PaymentType);
|
||||
return string.IsNullOrEmpty(PaymentType) ? PaymentTypes.LightningLike : PaymentTypes.Parse(PaymentType);
|
||||
}
|
||||
|
||||
public string[] GetSearchTerms()
|
||||
|
@ -9,6 +9,7 @@ using BTCPayServer.Configuration;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.HostedServices;
|
||||
using BTCPayServer.Lightning;
|
||||
using BTCPayServer.Lightning.LndHub;
|
||||
using BTCPayServer.Logging;
|
||||
using BTCPayServer.Models;
|
||||
using BTCPayServer.Models.InvoicingModels;
|
||||
@ -44,7 +45,7 @@ namespace BTCPayServer.Payments.Lightning
|
||||
Options = options;
|
||||
}
|
||||
|
||||
public override PaymentType PaymentType => LightningPaymentType.Instance;
|
||||
public override PaymentType PaymentType => PaymentTypes.LightningLike;
|
||||
|
||||
public IOptions<LightningNetworkOptions> Options { get; }
|
||||
|
||||
@ -122,11 +123,16 @@ namespace BTCPayServer.Payments.Lightning
|
||||
{
|
||||
if (!_Dashboard.IsFullySynched(network.CryptoCode, out var summary))
|
||||
throw new PaymentMethodUnavailableException("Full node not available");
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
using var cts = new CancellationTokenSource(LightningTimeout);
|
||||
var client = CreateLightningClient(supportedPaymentMethod, network);
|
||||
|
||||
// LNDhub-compatible implementations might not offer all of GetInfo data.
|
||||
// Skip checks in those cases, see https://github.com/lnbits/lnbits/issues/1182
|
||||
var isLndHub = client is LndHubLightningClient;
|
||||
|
||||
LightningNodeInformation info;
|
||||
try
|
||||
{
|
||||
@ -136,6 +142,10 @@ namespace BTCPayServer.Payments.Lightning
|
||||
{
|
||||
throw new PaymentMethodUnavailableException("The lightning node did not reply in a timely manner");
|
||||
}
|
||||
catch (NotSupportedException) when (isLndHub)
|
||||
{
|
||||
return new NodeInfo[] {};
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new PaymentMethodUnavailableException($"Error while connecting to the API: {ex.Message}" +
|
||||
@ -146,9 +156,9 @@ namespace BTCPayServer.Payments.Lightning
|
||||
var nodeInfo = preferOnion != null && info.NodeInfoList.Any(i => i.IsTor == preferOnion)
|
||||
? info.NodeInfoList.Where(i => i.IsTor == preferOnion.Value).ToArray()
|
||||
: info.NodeInfoList.Select(i => i).ToArray();
|
||||
|
||||
|
||||
var blocksGap = summary.Status.ChainHeight - info.BlockHeight;
|
||||
if (blocksGap > 10)
|
||||
if (blocksGap > 10 && !(isLndHub && info.BlockHeight == 0))
|
||||
{
|
||||
throw new PaymentMethodUnavailableException($"The lightning node is not synched ({blocksGap} blocks left)");
|
||||
}
|
||||
@ -199,7 +209,7 @@ namespace BTCPayServer.Payments.Lightning
|
||||
.GetAll()
|
||||
.OfType<BTCPayNetwork>()
|
||||
.Where(network => network.NBitcoinNetwork.Consensus.SupportSegwit && network.SupportLightning)
|
||||
.Select(network => new PaymentMethodId(network.CryptoCode, LightningPaymentType.Instance));
|
||||
.Select(network => new PaymentMethodId(network.CryptoCode, PaymentTypes.LightningLike));
|
||||
}
|
||||
|
||||
public override void PreparePaymentModel(PaymentModel model, InvoiceResponse invoiceResponse,
|
||||
|
@ -3,6 +3,7 @@ using System.Linq;
|
||||
using BTCPayServer.Lightning;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
using NBitcoin;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace BTCPayServer.Payments.Lightning
|
||||
@ -10,7 +11,9 @@ namespace BTCPayServer.Payments.Lightning
|
||||
public class LightningLikePaymentMethodDetails : IPaymentMethodDetails
|
||||
{
|
||||
public string BOLT11 { get; set; }
|
||||
[JsonConverter(typeof(NBitcoin.JsonConverters.UInt256JsonConverter))]
|
||||
public uint256 PaymentHash { get; set; }
|
||||
[JsonConverter(typeof(NBitcoin.JsonConverters.UInt256JsonConverter))]
|
||||
public uint256 Preimage { get; set; }
|
||||
public string InvoiceId { get; set; }
|
||||
public string NodeInfo { get; set; }
|
||||
@ -27,7 +30,7 @@ namespace BTCPayServer.Payments.Lightning
|
||||
|
||||
public virtual PaymentType GetPaymentType()
|
||||
{
|
||||
return LightningPaymentType.Instance;
|
||||
return PaymentTypes.LightningLike;
|
||||
}
|
||||
|
||||
public decimal GetNextNetworkFee()
|
||||
|
@ -144,7 +144,7 @@ namespace BTCPayServer.Payments.Lightning
|
||||
{
|
||||
var listenedInvoices = new List<ListenedInvoice>();
|
||||
foreach (var paymentMethod in invoice.GetPaymentMethods()
|
||||
.Where(c => new[] { LightningPaymentType.Instance, LNURLPayPaymentType.Instance }.Contains(c.GetId().PaymentType)))
|
||||
.Where(c => new[] { PaymentTypes.LightningLike, LNURLPayPaymentType.Instance }.Contains(c.GetId().PaymentType)))
|
||||
{
|
||||
LightningLikePaymentMethodDetails lightningMethod;
|
||||
LightningSupportedPaymentMethod? lightningSupportedMethod;
|
||||
@ -264,7 +264,7 @@ namespace BTCPayServer.Payments.Lightning
|
||||
private async Task CreateNewLNInvoiceForBTCPayInvoice(InvoiceEntity invoice)
|
||||
{
|
||||
var paymentMethods = invoice.GetPaymentMethods()
|
||||
.Where(method => new[] { LightningPaymentType.Instance, LNURLPayPaymentType.Instance }.Contains(method.GetId().PaymentType))
|
||||
.Where(method => new[] { PaymentTypes.LightningLike, LNURLPayPaymentType.Instance }.Contains(method.GetId().PaymentType))
|
||||
.ToArray();
|
||||
var store = await _storeRepository.FindStore(invoice.StoreId);
|
||||
if (store is null)
|
||||
|
@ -53,7 +53,7 @@ public class LightningPendingPayoutListener : BaseAsyncService
|
||||
var networks = _networkProvider.GetAll()
|
||||
.OfType<BTCPayNetwork>()
|
||||
.Where(network => network.SupportLightning)
|
||||
.ToDictionary(network => new PaymentMethodId(network.CryptoCode, LightningPaymentType.Instance));
|
||||
.ToDictionary(network => new PaymentMethodId(network.CryptoCode, PaymentTypes.LightningLike));
|
||||
|
||||
|
||||
var payouts = await PullPaymentHostedService.GetPayouts(
|
||||
|
@ -11,7 +11,7 @@ namespace BTCPayServer.Payments.Lightning
|
||||
public string CryptoCode { get; set; } = string.Empty;
|
||||
|
||||
[JsonIgnore]
|
||||
public PaymentMethodId PaymentId => new PaymentMethodId(CryptoCode, LightningPaymentType.Instance);
|
||||
public PaymentMethodId PaymentId => new PaymentMethodId(CryptoCode, PaymentTypes.LightningLike);
|
||||
|
||||
[Obsolete("Use Get/SetLightningUrl")]
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
|
@ -246,7 +246,7 @@ namespace BTCPayServer.Payments.PayJoin
|
||||
$"Provided transaction isn't mempool eligible {mempool.RPCCodeMessage}"));
|
||||
}
|
||||
var enforcedLowR = ctx.OriginalTransaction.Inputs.All(IsLowR);
|
||||
var paymentMethodId = new PaymentMethodId(network.CryptoCode, BitcoinPaymentType.Instance);
|
||||
var paymentMethodId = new PaymentMethodId(network.CryptoCode, PaymentTypes.BTCLike);
|
||||
Money? due = null;
|
||||
Dictionary<OutPoint, UTXO> selectedUTXOs = new Dictionary<OutPoint, UTXO>();
|
||||
PSBTOutput? originalPaymentOutput = null;
|
||||
|
@ -8,7 +8,7 @@ namespace BTCPayServer.Payments
|
||||
public static JToken Serialize(ISupportedPaymentMethod factory)
|
||||
{
|
||||
// Legacy
|
||||
if (factory.PaymentId.PaymentType == BitcoinPaymentType.Instance)
|
||||
if (factory.PaymentId.PaymentType == PaymentTypes.BTCLike)
|
||||
{
|
||||
var derivation = (DerivationSchemeSettings)factory;
|
||||
var str = derivation.Network.NBXplorerNetwork.Serializer.ToString(derivation);
|
||||
|
@ -30,7 +30,7 @@ namespace BTCPayServer.Payments
|
||||
{
|
||||
get
|
||||
{
|
||||
return CryptoCode == "BTC" && PaymentType == BitcoinPaymentType.Instance;
|
||||
return CryptoCode == "BTC" && PaymentType == PaymentTypes.BTCLike;
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,7 +68,7 @@ namespace BTCPayServer.Payments
|
||||
public override string ToString()
|
||||
{
|
||||
//BTCLike case is special because it is in legacy mode.
|
||||
return PaymentType == BitcoinPaymentType.Instance ? CryptoCode : $"{CryptoCode}_{PaymentType}";
|
||||
return PaymentType == PaymentTypes.BTCLike ? CryptoCode : $"{CryptoCode}_{PaymentType}";
|
||||
}
|
||||
/// <summary>
|
||||
/// A string we can expose to Greenfield API, not subjected to internal legacy
|
||||
@ -76,13 +76,54 @@ namespace BTCPayServer.Payments
|
||||
/// <returns></returns>
|
||||
public string ToStringNormalized()
|
||||
{
|
||||
return PaymentType.GetPaymentMethodId(this);
|
||||
if (PaymentType == PaymentTypes.BTCLike)
|
||||
return CryptoCode;
|
||||
#if ALTCOINS
|
||||
if (CryptoCode == "XMR" && PaymentType == PaymentTypes.MoneroLike)
|
||||
return CryptoCode;
|
||||
if ((CryptoCode == "YEC" || CryptoCode == "ZEC") && PaymentType == PaymentTypes.ZcashLike)
|
||||
return CryptoCode;
|
||||
#endif
|
||||
return $"{CryptoCode}-{PaymentType.ToStringNormalized()}";
|
||||
}
|
||||
|
||||
public string ToPrettyString()
|
||||
{
|
||||
return $"{CryptoCode} ({PaymentType.ToPrettyString()})";
|
||||
}
|
||||
|
||||
static char[] Separators = new[] { '_', '-' };
|
||||
public static PaymentMethodId? TryParse(string? str)
|
||||
{
|
||||
TryParse(str, out var r);
|
||||
return r;
|
||||
}
|
||||
public static bool TryParse(string? str, [MaybeNullWhen(false)] out PaymentMethodId paymentMethodId)
|
||||
{
|
||||
str ??= "";
|
||||
paymentMethodId = null;
|
||||
var parts = str.Split(Separators, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (parts.Length == 0 || parts.Length > 2)
|
||||
return false;
|
||||
PaymentType type = PaymentTypes.BTCLike;
|
||||
#if ALTCOINS
|
||||
if (parts[0].ToUpperInvariant() == "XMR")
|
||||
type = PaymentTypes.MoneroLike;
|
||||
if (parts[0].ToUpperInvariant() == "ZEC")
|
||||
type = PaymentTypes.ZcashLike;
|
||||
#endif
|
||||
if (parts.Length == 2)
|
||||
{
|
||||
if (!PaymentTypes.TryParse(parts[1], out type))
|
||||
return false;
|
||||
}
|
||||
paymentMethodId = new PaymentMethodId(parts[0], type);
|
||||
return true;
|
||||
}
|
||||
public static PaymentMethodId Parse(string str)
|
||||
{
|
||||
if (!TryParse(str, out var result))
|
||||
throw new FormatException("Invalid PaymentMethodId");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,57 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using AngleSharp.Common;
|
||||
|
||||
namespace BTCPayServer.Payments;
|
||||
|
||||
public class PaymentTypeRegistry
|
||||
{
|
||||
|
||||
static char[] Separators = new[] { '_', '-' };
|
||||
private readonly PaymentType[] _paymentTypes;
|
||||
|
||||
public PaymentTypeRegistry(IEnumerable<PaymentType> paymentTypes)
|
||||
{
|
||||
_paymentTypes = paymentTypes.ToArray();
|
||||
}
|
||||
|
||||
public bool TryParse(string paymentType, out PaymentType type)
|
||||
{
|
||||
type = _paymentTypes.FirstOrDefault(type1 => type1.IsPaymentType(paymentType));
|
||||
return type != null;
|
||||
}
|
||||
public PaymentType Parse(string paymentType)
|
||||
{
|
||||
if (!TryParse(paymentType, out var result))
|
||||
throw new FormatException("Invalid payment type");
|
||||
return result;
|
||||
}
|
||||
|
||||
public PaymentMethodId TryParsePaymentMethod(string? str)
|
||||
{
|
||||
return TryParsePaymentMethod(str, out var result) ? result : null;
|
||||
}
|
||||
public bool TryParsePaymentMethod(string? str, [MaybeNullWhen(false)] out PaymentMethodId paymentMethodId)
|
||||
{
|
||||
str ??= "";
|
||||
paymentMethodId = null;
|
||||
var parts = str.Split(Separators, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (parts.Length == 0 || parts.Length > 2)
|
||||
return false;
|
||||
if (TryParse(parts.Last(), out var type))
|
||||
{
|
||||
paymentMethodId = new PaymentMethodId(parts[0], type);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public PaymentMethodId ParsePaymentMethod(string str)
|
||||
{
|
||||
if (!TryParsePaymentMethod(str, out var result))
|
||||
throw new FormatException("Invalid PaymentMethodId");
|
||||
return result;
|
||||
}
|
||||
}
|
@ -10,22 +10,58 @@ using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace BTCPayServer.Payments
|
||||
{
|
||||
/// <summary>
|
||||
/// The different ways to pay an invoice
|
||||
/// </summary>
|
||||
public static class PaymentTypes
|
||||
{
|
||||
private static PaymentType[] _paymentTypes =
|
||||
{
|
||||
BTCLike, LightningLike, LNURLPay,
|
||||
#if ALTCOINS
|
||||
MoneroLike, ZcashLike,
|
||||
#endif
|
||||
};
|
||||
/// <summary>
|
||||
/// On-Chain UTXO based, bitcoin compatible
|
||||
/// </summary>
|
||||
public static BitcoinPaymentType BTCLike => BitcoinPaymentType.Instance;
|
||||
/// <summary>
|
||||
/// Lightning payment
|
||||
/// </summary>
|
||||
public static LightningPaymentType LightningLike => LightningPaymentType.Instance;
|
||||
/// <summary>
|
||||
/// Lightning payment
|
||||
/// </summary>
|
||||
public static LNURLPayPaymentType LNURLPay => LNURLPayPaymentType.Instance;
|
||||
|
||||
#if ALTCOINS
|
||||
/// <summary>
|
||||
/// Monero payment
|
||||
/// </summary>
|
||||
public static MoneroPaymentType MoneroLike => MoneroPaymentType.Instance;
|
||||
/// <summary>
|
||||
/// Zcash payment
|
||||
/// </summary>
|
||||
public static ZcashPaymentType ZcashLike => ZcashPaymentType.Instance;
|
||||
#endif
|
||||
|
||||
public static bool TryParse(string paymentType, out PaymentType type)
|
||||
{
|
||||
type = _paymentTypes.FirstOrDefault(type1 => type1.IsPaymentType(paymentType));
|
||||
return type != null;
|
||||
}
|
||||
public static PaymentType Parse(string paymentType)
|
||||
{
|
||||
if (!TryParse(paymentType, out var result))
|
||||
throw new FormatException("Invalid payment type");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class PaymentType
|
||||
{
|
||||
public abstract string ToPrettyString();
|
||||
|
||||
public virtual string GetPaymentMethodId(PaymentMethodId paymentMethodId)
|
||||
{
|
||||
if (paymentMethodId.PaymentType == BitcoinPaymentType.Instance)
|
||||
return paymentMethodId.CryptoCode;
|
||||
#if ALTCOINS
|
||||
if (paymentMethodId.CryptoCode == "XMR" && paymentMethodId.PaymentType == MoneroPaymentType.Instance)
|
||||
return paymentMethodId.CryptoCode;
|
||||
if ((paymentMethodId.CryptoCode == "YEC" || paymentMethodId.CryptoCode == "ZEC") && paymentMethodId.PaymentType == ZcashPaymentType.Instance)
|
||||
return paymentMethodId.CryptoCode;
|
||||
#endif
|
||||
return $"{paymentMethodId.CryptoCode}-{paymentMethodId.PaymentType.ToStringNormalized()}";
|
||||
}
|
||||
public override string ToString()
|
||||
{
|
||||
return GetId();
|
||||
|
@ -17,7 +17,6 @@ using BTCPayServer.Services.Rates;
|
||||
using BTCPayServer.Services.Stores;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Cors;
|
||||
using Microsoft.AspNetCore.Http.Extensions;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using NBitpayClient;
|
||||
@ -267,6 +266,7 @@ namespace BTCPayServer.Plugins.Crowdfund.Controllers
|
||||
if (app == null)
|
||||
return NotFound();
|
||||
|
||||
vm.AppId = app.Id;
|
||||
vm.TargetCurrency = await GetStoreDefaultCurrentIfEmpty(app.StoreDataId, vm.TargetCurrency);
|
||||
if (_currencies.GetCurrencyData(vm.TargetCurrency, false) == null)
|
||||
ModelState.AddModelError(nameof(vm.TargetCurrency), "Invalid currency");
|
||||
|
@ -55,8 +55,8 @@ namespace BTCPayServer.Plugins.NFC
|
||||
|
||||
var methods = invoice.GetPaymentMethods();
|
||||
PaymentMethod lnPaymentMethod = null;
|
||||
if (!methods.TryGetValue(new PaymentMethodId("BTC", LNURLPayPaymentType.Instance), out var lnurlPaymentMethod) &&
|
||||
!methods.TryGetValue(new PaymentMethodId("BTC", LightningPaymentType.Instance), out lnPaymentMethod))
|
||||
if (!methods.TryGetValue(new PaymentMethodId("BTC", PaymentTypes.LNURLPay), out var lnurlPaymentMethod) &&
|
||||
!methods.TryGetValue(new PaymentMethodId("BTC", PaymentTypes.LightningLike), out lnPaymentMethod))
|
||||
{
|
||||
return BadRequest("Destination for LNURL-Withdraw was not specified");
|
||||
}
|
||||
|
@ -60,6 +60,11 @@ namespace BTCPayServer.Plugins.PayButton.Controllers
|
||||
}
|
||||
|
||||
var apps = await _appService.GetAllApps(_userManager.GetUserId(User), false, store.Id);
|
||||
// unset app store data, because we don't need it and inclusion leads to circular references when serializing to JSON
|
||||
foreach (var app in apps)
|
||||
{
|
||||
app.App.StoreData = null;
|
||||
}
|
||||
var appUrl = HttpContext.Request.GetAbsoluteRoot().WithTrailingSlash();
|
||||
var model = new PayButtonViewModel
|
||||
{
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user