Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
a66dae627b |
@ -27,7 +27,7 @@
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="NBitcoin" Version="6.0.7" />
|
||||
<PackageReference Include="NBitcoin" Version="6.0.4" />
|
||||
<PackageReference Include="BTCPayServer.Lightning.Common" Version="1.2.4" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
</ItemGroup>
|
||||
|
@ -9,8 +9,6 @@ namespace BTCPayServer.Client.Models
|
||||
{
|
||||
public class CreateInvoiceRequest : InvoiceDataBase
|
||||
{
|
||||
[JsonConverter(typeof(NumericStringJsonConverter))]
|
||||
public decimal? Amount { get; set; }
|
||||
public string[] AdditionalSearchTerms { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -7,15 +7,10 @@ using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace BTCPayServer.Client.Models
|
||||
{
|
||||
public enum InvoiceType
|
||||
{
|
||||
Standard,
|
||||
TopUp
|
||||
}
|
||||
public class InvoiceDataBase
|
||||
{
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public InvoiceType Type { get; set; }
|
||||
[JsonConverter(typeof(NumericStringJsonConverter))]
|
||||
public decimal Amount { get; set; }
|
||||
public string Currency { get; set; }
|
||||
public JObject Metadata { get; set; }
|
||||
public CheckoutOptions Checkout { get; set; } = new CheckoutOptions();
|
||||
@ -46,8 +41,6 @@ namespace BTCPayServer.Client.Models
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string StoreId { get; set; }
|
||||
[JsonConverter(typeof(NumericStringJsonConverter))]
|
||||
public decimal Amount { get; set; }
|
||||
public string CheckoutLink { get; set; }
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public InvoiceStatus Status { get; set; }
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
<PackageReference Include="NBXplorer.Client" Version="4.0.3" />
|
||||
<PackageReference Include="NBXplorer.Client" Version="4.0.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(Altcoins)' != 'true'">
|
||||
<Compile Remove="Altcoins\**\*.cs"></Compile>
|
||||
|
@ -6,7 +6,7 @@
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.6.0" />
|
||||
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.7" />
|
||||
<PackageReference Include="NBitcoin" Version="6.0.7" />
|
||||
<PackageReference Include="NBitcoin" Version="6.0.4" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="DigitalRuby.ExchangeSharp" Version="0.6.3" />
|
||||
</ItemGroup>
|
||||
|
@ -28,6 +28,7 @@ namespace BTCPayServer.Services.Rates
|
||||
}
|
||||
|
||||
static readonly Dictionary<string, IFormatProvider> _CurrencyProviders = new Dictionary<string, IFormatProvider>();
|
||||
|
||||
public string FormatCurrency(string price, string currency)
|
||||
{
|
||||
return FormatCurrency(decimal.Parse(price, CultureInfo.InvariantCulture), currency);
|
||||
@ -109,8 +110,9 @@ namespace BTCPayServer.Services.Rates
|
||||
/// </summary>
|
||||
/// <param name="value">The value</param>
|
||||
/// <param name="currency">Currency code</param>
|
||||
/// <param name="threeLetterSuffix">Add three letter suffix (like USD)</param>
|
||||
/// <returns></returns>
|
||||
public string DisplayFormatCurrency(decimal value, string currency)
|
||||
public string DisplayFormatCurrency(decimal value, string currency, bool threeLetterSuffix = true)
|
||||
{
|
||||
var provider = GetNumberFormatInfo(currency, true);
|
||||
var currencyData = GetCurrencyData(currency, true);
|
||||
|
@ -226,57 +226,6 @@ namespace BTCPayServer.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Selenium", "Selenium")]
|
||||
public async Task CanUsePayjoinForTopUp()
|
||||
{
|
||||
using (var s = SeleniumTester.Create())
|
||||
{
|
||||
await s.StartAsync();
|
||||
s.RegisterNewUser(true);
|
||||
var receiver = s.CreateNewStore();
|
||||
var receiverSeed = s.GenerateWallet("BTC", "", true, true, ScriptPubKeyType.Segwit);
|
||||
var receiverWalletId = new WalletId(receiver.storeId, "BTC");
|
||||
|
||||
var sender = s.CreateNewStore();
|
||||
var senderSeed = s.GenerateWallet("BTC", "", true, true, ScriptPubKeyType.Segwit);
|
||||
var senderWalletId = new WalletId(sender.storeId, "BTC");
|
||||
|
||||
await s.Server.ExplorerNode.GenerateAsync(1);
|
||||
await s.FundStoreWallet(senderWalletId);
|
||||
await s.FundStoreWallet(receiverWalletId);
|
||||
|
||||
var invoiceId = s.CreateInvoice(receiver.storeName, null, "BTC");
|
||||
s.GoToInvoiceCheckout(invoiceId);
|
||||
var bip21 = s.Driver.FindElement(By.ClassName("payment__details__instruction__open-wallet__btn"))
|
||||
.GetAttribute("href");
|
||||
Assert.Contains($"{PayjoinClient.BIP21EndpointKey}=", bip21);
|
||||
s.GoToWallet(senderWalletId, WalletsNavPages.Send);
|
||||
s.Driver.FindElement(By.Id("bip21parse")).Click();
|
||||
s.Driver.SwitchTo().Alert().SendKeys(bip21);
|
||||
s.Driver.SwitchTo().Alert().Accept();
|
||||
s.Driver.FindElement(By.Id("Outputs_0__Amount")).Clear();
|
||||
s.Driver.FindElement(By.Id("Outputs_0__Amount")).SendKeys("0.023");
|
||||
|
||||
s.Driver.FindElement(By.Id("SignTransaction")).Click();
|
||||
|
||||
await s.Server.WaitForEvent<NewOnChainTransactionEvent>(() =>
|
||||
{
|
||||
s.Driver.FindElement(By.CssSelector("button[value=payjoin]")).Click();
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
|
||||
s.FindAlertMessage(StatusMessageModel.StatusSeverity.Success);
|
||||
var invoiceRepository = s.Server.PayTester.GetService<InvoiceRepository>();
|
||||
await TestUtils.EventuallyAsync(async () =>
|
||||
{
|
||||
var invoice = await invoiceRepository.GetInvoice(invoiceId);
|
||||
Assert.Equal(InvoiceStatusLegacy.Paid, invoice.Status);
|
||||
Assert.Equal(0.023m, invoice.Price);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Selenium", "Selenium")]
|
||||
public async Task CanUsePayjoinViaUI()
|
||||
|
@ -128,7 +128,6 @@ namespace BTCPayServer.Tests
|
||||
|
||||
public Mnemonic GenerateWallet(string cryptoCode = "BTC", string seed = "", bool importkeys = false, bool privkeys = false, ScriptPubKeyType format = ScriptPubKeyType.Segwit)
|
||||
{
|
||||
var isImport = !string.IsNullOrEmpty(seed);
|
||||
Driver.FindElement(By.Id($"Modify{cryptoCode}")).Click();
|
||||
|
||||
// Replace previous wallet case
|
||||
@ -138,7 +137,14 @@ namespace BTCPayServer.Tests
|
||||
Driver.FindElement(By.Id("continue")).Click();
|
||||
}
|
||||
|
||||
if (isImport)
|
||||
if (string.IsNullOrEmpty(seed))
|
||||
{
|
||||
var option = privkeys ? "Hotwallet" : "Watchonly";
|
||||
Logs.Tester.LogInformation($"Generating new seed ({option})");
|
||||
Driver.FindElement(By.Id("GenerateWalletLink")).Click();
|
||||
Driver.FindElement(By.Id($"Generate{option}Link")).Click();
|
||||
}
|
||||
else
|
||||
{
|
||||
Logs.Tester.LogInformation("Progressing with existing seed");
|
||||
Driver.FindElement(By.Id("ImportWalletOptionsLink")).Click();
|
||||
@ -146,13 +152,6 @@ namespace BTCPayServer.Tests
|
||||
Driver.FindElement(By.Id("ExistingMnemonic")).SendKeys(seed);
|
||||
Driver.SetCheckbox(By.Id("SavePrivateKeys"), privkeys);
|
||||
}
|
||||
else
|
||||
{
|
||||
var option = privkeys ? "Hotwallet" : "Watchonly";
|
||||
Logs.Tester.LogInformation($"Generating new seed ({option})");
|
||||
Driver.FindElement(By.Id("GenerateWalletLink")).Click();
|
||||
Driver.FindElement(By.Id($"Generate{option}Link")).Click();
|
||||
}
|
||||
|
||||
Driver.FindElement(By.Id("ScriptPubKeyType")).Click();
|
||||
Driver.FindElement(By.CssSelector($"#ScriptPubKeyType option[value={format}]")).Click();
|
||||
@ -161,25 +160,17 @@ namespace BTCPayServer.Tests
|
||||
Driver.SetCheckbox(By.Id("ImportKeysToRPC"), importkeys);
|
||||
Driver.FindElement(By.Id("Continue")).Click();
|
||||
|
||||
if (isImport)
|
||||
// Seed backup page
|
||||
FindAlertMessage();
|
||||
if (string.IsNullOrEmpty(seed))
|
||||
{
|
||||
// Confirm addresses
|
||||
Driver.FindElement(By.Id("Confirm")).Click();
|
||||
seed = Driver.FindElements(By.Id("RecoveryPhrase")).First().GetAttribute("data-mnemonic");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Seed backup
|
||||
FindAlertMessage();
|
||||
if (string.IsNullOrEmpty(seed))
|
||||
{
|
||||
seed = Driver.FindElements(By.Id("RecoveryPhrase")).First().GetAttribute("data-mnemonic");
|
||||
}
|
||||
|
||||
// Confirm seed backup
|
||||
Driver.FindElement(By.Id("confirm")).Click();
|
||||
Driver.FindElement(By.Id("submit")).Click();
|
||||
}
|
||||
|
||||
// Confirm seed backup
|
||||
Driver.FindElement(By.Id("confirm")).Click();
|
||||
Driver.FindElement(By.Id("submit")).Click();
|
||||
|
||||
WalletId = new WalletId(StoreId, cryptoCode);
|
||||
return new Mnemonic(seed);
|
||||
}
|
||||
@ -331,12 +322,11 @@ namespace BTCPayServer.Tests
|
||||
Driver.Navigate().GoToUrl(new Uri(Server.PayTester.ServerUri, "/login"));
|
||||
}
|
||||
|
||||
public string CreateInvoice(string storeName, decimal? amount = 100, string currency = "USD", string refundEmail = "")
|
||||
public string CreateInvoice(string storeName, decimal amount = 100, string currency = "USD", string refundEmail = "")
|
||||
{
|
||||
GoToInvoices();
|
||||
Driver.FindElement(By.Id("CreateNewInvoice")).Click();
|
||||
if (amount is decimal v)
|
||||
Driver.FindElement(By.Id("Amount")).SendKeys(v.ToString(CultureInfo.InvariantCulture));
|
||||
Driver.FindElement(By.Id("Amount")).SendKeys(amount.ToString(CultureInfo.InvariantCulture));
|
||||
var currencyEl = Driver.FindElement(By.Id("Currency"));
|
||||
currencyEl.Clear();
|
||||
currencyEl.SendKeys(currency);
|
||||
|
@ -831,11 +831,6 @@ namespace BTCPayServer.Tests
|
||||
s.Driver.FindElement(By.LinkText("Manage")).Click();
|
||||
|
||||
s.ClickOnAllSideMenus();
|
||||
|
||||
// Make sure wallet info is correct
|
||||
s.Driver.FindElement(By.Id("WalletSettings")).Click();
|
||||
Assert.Contains(mnemonic.DeriveExtKey().GetPublicKey().GetHDFingerPrint().ToString(), s.Driver.FindElement(By.Id("AccountKeys_0__MasterFingerprint")).GetAttribute("value"));
|
||||
Assert.Contains("m/84'/1'/0'", s.Driver.FindElement(By.Id("AccountKeys_0__AccountKeyPath")).GetAttribute("value"));
|
||||
|
||||
// Make sure we can rescan, because we are admin!
|
||||
s.Driver.FindElement(By.Id("WalletRescan")).Click();
|
||||
@ -913,23 +908,6 @@ namespace BTCPayServer.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[Fact(Timeout = TestTimeout)]
|
||||
public async Task CanImportWallet()
|
||||
{
|
||||
using (var s = SeleniumTester.Create())
|
||||
{
|
||||
await s.StartAsync();
|
||||
s.RegisterNewUser(true);
|
||||
var (_, storeId) = s.CreateNewStore();
|
||||
var mnemonic = s.GenerateWallet("BTC", "click chunk owner kingdom faint steak safe evidence bicycle repeat bulb wheel");
|
||||
|
||||
// Make sure wallet info is correct
|
||||
s.GoToWallet(new WalletId(storeId, "BTC"), WalletsNavPages.Settings);
|
||||
Assert.Contains(mnemonic.DeriveExtKey().GetPublicKey().GetHDFingerPrint().ToString(), s.Driver.FindElement(By.Id("AccountKeys_0__MasterFingerprint")).GetAttribute("value"));
|
||||
Assert.Contains( "m/84'/1'/0'", s.Driver.FindElement(By.Id("AccountKeys_0__AccountKeyPath")).GetAttribute("value"));
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Selenium", "Selenium")]
|
||||
public async Task CanUsePullPaymentsViaUI()
|
||||
@ -1081,7 +1059,7 @@ namespace BTCPayServer.Tests
|
||||
Assert.Contains(PayoutState.AwaitingPayment.GetStateString(), s.Driver.PageSource);
|
||||
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($"{PayoutState.AwaitingPayment}-confirm-payment")).Click();
|
||||
s.FindAlertMessage();
|
||||
|
||||
s.Driver.FindElement(By.Id("InProgress-view")).Click();
|
||||
|
@ -13,7 +13,6 @@ using BTCPayServer.Tests.Logging;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Newtonsoft.Json;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
@ -186,23 +185,22 @@ namespace BTCPayServer.Tests
|
||||
fileList.Add(TestUtils.GetFormFile("uploadtestfile1.txt", fileContent));
|
||||
|
||||
var uploadFormFileResult = Assert.IsType<RedirectToActionResult>(await controller.CreateFiles(fileList));
|
||||
Assert.True(uploadFormFileResult.RouteValues.ContainsKey("fileIds"));
|
||||
string[] uploadFileList = (string[])uploadFormFileResult.RouteValues["fileIds"];
|
||||
var fileId = uploadFileList[0];
|
||||
Assert.True(uploadFormFileResult.RouteValues.ContainsKey("fileId"));
|
||||
var fileId = uploadFormFileResult.RouteValues["fileId"].ToString();
|
||||
Assert.Equal("Files", uploadFormFileResult.ActionName);
|
||||
|
||||
//check if file was uploaded and saved in db
|
||||
var viewFilesViewModel =
|
||||
Assert.IsType<ViewFilesViewModel>(Assert.IsType<ViewResult>(await controller.Files(new string[] { fileId })).Model);
|
||||
Assert.IsType<ViewFilesViewModel>(Assert.IsType<ViewResult>(await controller.Files(fileId)).Model);
|
||||
|
||||
Assert.NotEmpty(viewFilesViewModel.Files);
|
||||
Assert.True(viewFilesViewModel.DirectUrlByFiles.ContainsKey(fileId));
|
||||
Assert.NotEmpty(viewFilesViewModel.DirectUrlByFiles[fileId]);
|
||||
Assert.Equal(fileId, viewFilesViewModel.SelectedFileId);
|
||||
Assert.NotEmpty(viewFilesViewModel.DirectFileUrl);
|
||||
|
||||
|
||||
//verify file is available and the same
|
||||
var net = new System.Net.WebClient();
|
||||
var data = await net.DownloadStringTaskAsync(new Uri(viewFilesViewModel.DirectUrlByFiles[fileId]));
|
||||
var data = await net.DownloadStringTaskAsync(new Uri(viewFilesViewModel.DirectFileUrl));
|
||||
Assert.Equal(fileContent, data);
|
||||
|
||||
//create a temporary link to file
|
||||
@ -234,8 +232,10 @@ namespace BTCPayServer.Tests
|
||||
|
||||
//attempt to fetch deleted file
|
||||
viewFilesViewModel =
|
||||
Assert.IsType<ViewFilesViewModel>(Assert.IsType<ViewResult>(await controller.Files(new string[] { fileId })).Model);
|
||||
Assert.Null(viewFilesViewModel.DirectUrlByFiles);
|
||||
Assert.IsType<ViewFilesViewModel>(Assert.IsType<ViewResult>(await controller.Files(fileId)).Model);
|
||||
|
||||
Assert.Null(viewFilesViewModel.DirectFileUrl);
|
||||
Assert.Null(viewFilesViewModel.SelectedFileId);
|
||||
}
|
||||
|
||||
|
||||
|
@ -935,8 +935,7 @@ namespace BTCPayServer.Tests
|
||||
{
|
||||
(0.0005m, "$0.0005 (USD)", "USD"), (0.001m, "$0.001 (USD)", "USD"), (0.01m, "$0.01 (USD)", "USD"),
|
||||
(0.1m, "$0.10 (USD)", "USD"), (0.1m, "0,10 € (EUR)", "EUR"), (1000m, "¥1,000 (JPY)", "JPY"),
|
||||
(1000.0001m, "₹ 1,000.00 (INR)", "INR"),
|
||||
(0.0m, "$0.00 (USD)", "USD")
|
||||
(1000.0001m, "₹ 1,000.00 (INR)", "INR")
|
||||
})
|
||||
{
|
||||
var actual = CurrencyNameTable.Instance.DisplayFormatCurrency(test.Item1, test.Item3);
|
||||
@ -2100,90 +2099,6 @@ namespace BTCPayServer.Tests
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[Fact(Timeout = LongRunningTestTimeout)]
|
||||
[Trait("Integration", "Integration")]
|
||||
public async Task CanCreateTopupInvoices()
|
||||
{
|
||||
using (var tester = ServerTester.Create())
|
||||
{
|
||||
await tester.StartAsync();
|
||||
var user = tester.NewAccount();
|
||||
user.GrantAccess();
|
||||
user.RegisterDerivationScheme("BTC");
|
||||
|
||||
var rng = new Random();
|
||||
var seed = rng.Next();
|
||||
rng = new Random(seed);
|
||||
Logs.Tester.LogInformation("Seed: " + seed);
|
||||
foreach (var networkFeeMode in Enum.GetValues(typeof(NetworkFeeMode)).Cast<NetworkFeeMode>())
|
||||
{
|
||||
await user.SetNetworkFeeMode(networkFeeMode);
|
||||
await AssertTopUpBtcPrice(tester, user, Money.Coins(1.0m), 5000.0m, networkFeeMode);
|
||||
await AssertTopUpBtcPrice(tester, user, Money.Coins(1.23456789m), 5000.0m * 1.23456789m, networkFeeMode);
|
||||
// Check if there is no strange roundup issues
|
||||
var v = (decimal)(rng.NextDouble() + 1.0);
|
||||
v = Money.Coins(v).ToDecimal(MoneyUnit.BTC);
|
||||
await AssertTopUpBtcPrice(tester, user, Money.Coins(v), 5000.0m * v, networkFeeMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task AssertTopUpBtcPrice(ServerTester tester, TestAccount user, Money btcSent, decimal expectedPriceWithoutNetworkFee, NetworkFeeMode networkFeeMode)
|
||||
{
|
||||
var cashCow = tester.ExplorerNode;
|
||||
// First we try payment with a merchant having only BTC
|
||||
var client = await user.CreateClient();
|
||||
var invoice = await client.CreateInvoice(user.StoreId, new CreateInvoiceRequest()
|
||||
{
|
||||
Amount = null,
|
||||
Currency = "USD"
|
||||
});
|
||||
Assert.Equal(0m, invoice.Amount);
|
||||
Assert.Equal(InvoiceType.TopUp, invoice.Type);
|
||||
var btcmethod = (await client.GetInvoicePaymentMethods(user.StoreId, invoice.Id))[0];
|
||||
var paid = btcSent;
|
||||
var invoiceAddress = BitcoinAddress.Create(btcmethod.Destination, cashCow.Network);
|
||||
|
||||
|
||||
var btc = new PaymentMethodId("BTC", PaymentTypes.BTCLike);
|
||||
var networkFee = (await tester.PayTester.InvoiceRepository.GetInvoice(invoice.Id))
|
||||
.GetPaymentMethods()[btc]
|
||||
.GetPaymentMethodDetails()
|
||||
.AssertType<BitcoinLikeOnChainPaymentMethod>()
|
||||
.GetNextNetworkFee();
|
||||
if (networkFeeMode != NetworkFeeMode.Always)
|
||||
{
|
||||
networkFee = 0.0m;
|
||||
}
|
||||
|
||||
cashCow.SendToAddress(invoiceAddress, paid);
|
||||
|
||||
|
||||
await TestUtils.EventuallyAsync(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var bitpayinvoice = await user.BitPay.GetInvoiceAsync(invoice.Id);
|
||||
Assert.NotEqual(0.0m, bitpayinvoice.Price);
|
||||
var due = Money.Parse(bitpayinvoice.CryptoInfo[0].CryptoPaid);
|
||||
Assert.Equal(paid, due);
|
||||
Assert.Equal(expectedPriceWithoutNetworkFee - networkFee * bitpayinvoice.Rate, bitpayinvoice.Price);
|
||||
Assert.Equal(Money.Zero, bitpayinvoice.BtcDue);
|
||||
Assert.Equal("paid", bitpayinvoice.Status);
|
||||
Assert.Equal("False", bitpayinvoice.ExceptionStatus.ToString());
|
||||
|
||||
// Check if we index by price correctly once we know it
|
||||
var invoices = await client.GetInvoices(user.StoreId, textSearch: $"{bitpayinvoice.Price.ToString(CultureInfo.InvariantCulture)}");
|
||||
Assert.Contains(invoices, inv => inv.Id == bitpayinvoice.Id);
|
||||
}
|
||||
catch (JsonSerializationException)
|
||||
{
|
||||
Assert.False(true, "The bitpay's amount is not set");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
[Fact(Timeout = LongRunningTestTimeout)]
|
||||
[Trait("Integration", "Integration")]
|
||||
public async Task CanModifyRates()
|
||||
@ -2888,22 +2803,6 @@ namespace BTCPayServer.Tests
|
||||
var invoice = user.BitPay.CreateInvoice(
|
||||
new Invoice() { Price = -0.1m, Currency = "BTC", FullNotifications = true }, Facade.Merchant);
|
||||
Assert.Equal(0.0m, invoice.Price);
|
||||
|
||||
// Should round down to 50.51, taxIncluded should be also clipped to this value because taxIncluded can't be higher than the price.
|
||||
var invoice5 = user.BitPay.CreateInvoice(
|
||||
new Invoice() { Price = 50.513m, Currency = "USD", FullNotifications = true, TaxIncluded = 50.516m }, Facade.Merchant);
|
||||
Assert.Equal(50.51m, invoice5.Price);
|
||||
Assert.Equal(50.51m, invoice5.TaxIncluded);
|
||||
|
||||
var greenfield = await user.CreateClient();
|
||||
var invoice5g = await greenfield.CreateInvoice(user.StoreId, new CreateInvoiceRequest()
|
||||
{
|
||||
Amount = 50.513m,
|
||||
Currency = "USD",
|
||||
Metadata = new JObject() { new JProperty("taxIncluded", 50.516m) }
|
||||
});
|
||||
Assert.Equal(50.51m, invoice5g.Amount);
|
||||
Assert.Equal(50.51m, (decimal)invoice5g.Metadata["taxIncluded"]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,7 @@ services:
|
||||
- "sshd_datadir:/root/.ssh"
|
||||
|
||||
devlnd:
|
||||
image: btcpayserver/bitcoin:0.21.1
|
||||
image: btcpayserver/bitcoin:0.21.0
|
||||
environment:
|
||||
BITCOIN_NETWORK: regtest
|
||||
BITCOIN_WALLETDIR: "/data/wallets"
|
||||
@ -84,7 +84,7 @@ services:
|
||||
- customer_lnd
|
||||
- merchant_lnd
|
||||
nbxplorer:
|
||||
image: nicolasdorier/nbxplorer:2.1.56
|
||||
image: nicolasdorier/nbxplorer:2.1.53
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "32838:32838"
|
||||
@ -118,7 +118,7 @@ services:
|
||||
|
||||
bitcoind:
|
||||
restart: unless-stopped
|
||||
image: btcpayserver/bitcoin:0.21.1
|
||||
image: btcpayserver/bitcoin:0.21.0
|
||||
environment:
|
||||
BITCOIN_NETWORK: regtest
|
||||
BITCOIN_WALLETDIR: "/data/wallets"
|
||||
@ -146,7 +146,7 @@ services:
|
||||
- "bitcoin_datadir:/data"
|
||||
|
||||
customer_lightningd:
|
||||
image: btcpayserver/lightning:v0.10.1-dev
|
||||
image: btcpayserver/lightning:v0.9.3-1-dev
|
||||
stop_signal: SIGKILL
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
@ -195,7 +195,7 @@ services:
|
||||
- merchant_lightningd
|
||||
|
||||
merchant_lightningd:
|
||||
image: btcpayserver/lightning:v0.10.1-dev
|
||||
image: btcpayserver/lightning:v0.9.3-1-dev
|
||||
stop_signal: SIGKILL
|
||||
environment:
|
||||
EXPOSE_TCP: "true"
|
||||
@ -227,7 +227,7 @@ services:
|
||||
- "5432"
|
||||
|
||||
merchant_lnd:
|
||||
image: btcpayserver/lnd:v0.13.1-beta-withloop
|
||||
image: btcpayserver/lnd:v0.12.1-beta
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
LND_CHAIN: "btc"
|
||||
@ -261,7 +261,7 @@ services:
|
||||
- bitcoind
|
||||
|
||||
customer_lnd:
|
||||
image: btcpayserver/lnd:v0.13.1-beta-withloop
|
||||
image: btcpayserver/lnd:v0.12.1-beta
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
LND_CHAIN: "btc"
|
||||
|
@ -66,7 +66,7 @@ services:
|
||||
- "sshd_datadir:/root/.ssh"
|
||||
|
||||
devlnd:
|
||||
image: btcpayserver/bitcoin:0.21.1
|
||||
image: btcpayserver/bitcoin:0.21.0
|
||||
environment:
|
||||
BITCOIN_NETWORK: regtest
|
||||
BITCOIN_WALLETDIR: "/data/wallets"
|
||||
@ -81,7 +81,7 @@ services:
|
||||
- customer_lnd
|
||||
- merchant_lnd
|
||||
nbxplorer:
|
||||
image: nicolasdorier/nbxplorer:2.1.56
|
||||
image: nicolasdorier/nbxplorer:2.1.53
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "32838:32838"
|
||||
@ -105,7 +105,7 @@ services:
|
||||
|
||||
bitcoind:
|
||||
restart: unless-stopped
|
||||
image: btcpayserver/bitcoin:0.21.1
|
||||
image: btcpayserver/bitcoin:0.21.0
|
||||
environment:
|
||||
BITCOIN_NETWORK: regtest
|
||||
BITCOIN_WALLETDIR: "/data/wallets"
|
||||
@ -133,7 +133,7 @@ services:
|
||||
- "bitcoin_datadir:/data"
|
||||
|
||||
customer_lightningd:
|
||||
image: btcpayserver/lightning:v0.10.1-dev
|
||||
image: btcpayserver/lightning:v0.9.3-1-dev
|
||||
stop_signal: SIGKILL
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
@ -182,7 +182,7 @@ services:
|
||||
- merchant_lightningd
|
||||
|
||||
merchant_lightningd:
|
||||
image: btcpayserver/lightning:v0.10.1-dev
|
||||
image: btcpayserver/lightning:v0.9.3-1-dev
|
||||
stop_signal: SIGKILL
|
||||
environment:
|
||||
EXPOSE_TCP: "true"
|
||||
@ -215,7 +215,7 @@ services:
|
||||
- "5432"
|
||||
|
||||
merchant_lnd:
|
||||
image: btcpayserver/lnd:v0.13.1-beta-withloop
|
||||
image: btcpayserver/lnd:v0.12.1-beta
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
LND_CHAIN: "btc"
|
||||
@ -249,7 +249,7 @@ services:
|
||||
- bitcoind
|
||||
|
||||
customer_lnd:
|
||||
image: btcpayserver/lnd:v0.13.1-beta-withloop
|
||||
image: btcpayserver/lnd:v0.12.1-beta
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
LND_CHAIN: "btc"
|
||||
|
@ -46,7 +46,7 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BIP78.Sender" Version="0.2.0" />
|
||||
<PackageReference Include="BTCPayServer.Hwi" Version="2.0.1" />
|
||||
<PackageReference Include="BTCPayServer.Lightning.All" Version="1.2.10" />
|
||||
<PackageReference Include="BTCPayServer.Lightning.All" Version="1.2.9" />
|
||||
<PackageReference Include="BuildBundlerMinifier" Version="3.2.449" />
|
||||
<PackageReference Include="BundlerMinifier.Core" Version="3.2.435" />
|
||||
<PackageReference Include="BundlerMinifier.TagHelpers" Version="3.2.435" />
|
||||
|
@ -3,7 +3,6 @@
|
||||
@inject ISettingsRepository SettingsRepository
|
||||
@using BTCPayServer.HostedServices
|
||||
@using BTCPayServer.Views.Notifications
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@using BTCPayServer.Abstractions.Contracts
|
||||
@using BTCPayServer.Client
|
||||
@using BTCPayServer.Services
|
||||
|
@ -393,7 +393,6 @@ namespace BTCPayServer.Controllers.GreenField
|
||||
MonitoringExpiration = entity.MonitoringExpiration,
|
||||
CreatedTime = entity.InvoiceTime,
|
||||
Amount = entity.Price,
|
||||
Type = entity.Type,
|
||||
Id = entity.Id,
|
||||
CheckoutLink = _linkGenerator.CheckoutLink(entity.Id, Request.Scheme, Request.Host, Request.PathBase),
|
||||
Status = entity.Status.ToModernStatus(),
|
||||
|
@ -247,7 +247,8 @@ namespace BTCPayServer.Controllers
|
||||
cdCurrency.Divisibility);
|
||||
model.CryptoAmountThen = Math.Round(paidCurrency / paymentMethod.Rate, paymentMethodDivisibility);
|
||||
model.RateThenText =
|
||||
_CurrencyNameTable.DisplayFormatCurrency(model.CryptoAmountThen, paymentMethodId.CryptoCode);
|
||||
_CurrencyNameTable.DisplayFormatCurrency(model.CryptoAmountThen, paymentMethodId.CryptoCode,
|
||||
true);
|
||||
rules = store.GetStoreBlob().GetRateRules(_NetworkProvider);
|
||||
rateResult = await _RateProvider.FetchRate(
|
||||
new Rating.CurrencyPair(paymentMethodId.CryptoCode, invoice.Currency), rules,
|
||||
@ -262,9 +263,10 @@ namespace BTCPayServer.Controllers
|
||||
|
||||
model.CryptoAmountNow = Math.Round(paidCurrency / rateResult.BidAsk.Bid, paymentMethodDivisibility);
|
||||
model.CurrentRateText =
|
||||
_CurrencyNameTable.DisplayFormatCurrency(model.CryptoAmountNow, paymentMethodId.CryptoCode);
|
||||
_CurrencyNameTable.DisplayFormatCurrency(model.CryptoAmountNow, paymentMethodId.CryptoCode,
|
||||
true);
|
||||
model.FiatAmount = paidCurrency;
|
||||
model.FiatText = _CurrencyNameTable.DisplayFormatCurrency(model.FiatAmount, invoice.Currency);
|
||||
model.FiatText = _CurrencyNameTable.DisplayFormatCurrency(model.FiatAmount, invoice.Currency, true);
|
||||
return View(model);
|
||||
case RefundSteps.SelectRate:
|
||||
createPullPayment = new HostedServices.CreatePullPayment();
|
||||
@ -339,7 +341,7 @@ namespace BTCPayServer.Controllers
|
||||
var ppId = await _paymentHostedService.CreatePullPayment(createPullPayment);
|
||||
this.TempData.SetStatusMessageModel(new StatusMessageModel()
|
||||
{
|
||||
Html = "Refund successfully created!<br />Share the link to this page with a customer.<br />The customer needs to enter their address and claim the refund.<br />Once a customer claims the refund, you will get a notification and would need to approve and initiate it from your Wallet > Manage > Payouts.",
|
||||
Html = "Share this page with a customer so they can claim a refund <br />Once claimed you need to initiate a refund from Wallet > Payouts",
|
||||
Severity = StatusMessageModel.StatusSeverity.Success
|
||||
});
|
||||
(await ctx.Invoices.FindAsync(invoice.Id)).CurrentRefundId = ppId;
|
||||
@ -543,7 +545,7 @@ namespace BTCPayServer.Controllers
|
||||
}
|
||||
}
|
||||
lang ??= storeBlob.DefaultLang;
|
||||
|
||||
|
||||
var model = new PaymentModel()
|
||||
{
|
||||
Activated = paymentMethodDetails.Activated,
|
||||
@ -560,7 +562,6 @@ namespace BTCPayServer.Controllers
|
||||
BtcDue = accounting.Due.ShowMoney(divisibility),
|
||||
InvoiceCurrency = invoice.Currency,
|
||||
OrderAmount = (accounting.TotalDue - accounting.NetworkFee).ShowMoney(divisibility),
|
||||
IsUnsetTopUp = invoice.IsUnsetTopUp(),
|
||||
OrderAmountFiat = OrderAmountFromInvoice(network.CryptoCode, invoice),
|
||||
CustomerEmail = invoice.RefundMail,
|
||||
RequiresRefundEmail = storeBlob.RequiresRefundEmail,
|
||||
@ -845,12 +846,17 @@ namespace BTCPayServer.Controllers
|
||||
ModelState.AddModelError(nameof(model.StoreId), "You need to configure the derivation scheme in order to create an invoice");
|
||||
return View(model);
|
||||
}
|
||||
if (model.Amount is null)
|
||||
{
|
||||
ModelState.AddModelError(nameof(model.Amount), "Thhe invoice amount can't be empty");
|
||||
return View(model);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var result = await CreateInvoiceCore(new BitpayCreateInvoiceRequest()
|
||||
{
|
||||
Price = model.Amount,
|
||||
Price = model.Amount.Value,
|
||||
Currency = model.Currency,
|
||||
PosData = model.PosData,
|
||||
OrderId = model.OrderId,
|
||||
|
@ -112,23 +112,24 @@ namespace BTCPayServer.Controllers
|
||||
FillBuyerInfo(invoice, entity);
|
||||
|
||||
var taxIncluded = invoice.TaxIncluded.HasValue ? invoice.TaxIncluded.Value : 0m;
|
||||
var price = invoice.Price;
|
||||
|
||||
var currencyInfo = _CurrencyNameTable.GetNumberFormatInfo(invoice.Currency, false);
|
||||
if (currencyInfo != null)
|
||||
{
|
||||
int divisibility = currencyInfo.CurrencyDecimalDigits;
|
||||
invoice.Price = invoice.Price.RoundToSignificant(ref divisibility);
|
||||
divisibility = currencyInfo.CurrencyDecimalDigits;
|
||||
invoice.TaxIncluded = taxIncluded.RoundToSignificant(ref divisibility);
|
||||
}
|
||||
invoice.Price = Math.Max(0.0m, invoice.Price);
|
||||
invoice.TaxIncluded = Math.Max(0.0m, taxIncluded);
|
||||
invoice.TaxIncluded = Math.Min(taxIncluded, invoice.Price);
|
||||
entity.Metadata.ItemCode = invoice.ItemCode;
|
||||
entity.Metadata.ItemDesc = invoice.ItemDesc;
|
||||
entity.Metadata.Physical = invoice.Physical;
|
||||
entity.Metadata.TaxIncluded = invoice.TaxIncluded;
|
||||
entity.Currency = invoice.Currency;
|
||||
if (price is decimal vv)
|
||||
{
|
||||
entity.Price = vv;
|
||||
entity.Type = InvoiceType.Standard;
|
||||
}
|
||||
else
|
||||
{
|
||||
entity.Price = 0m;
|
||||
entity.Type = InvoiceType.TopUp;
|
||||
}
|
||||
entity.Price = invoice.Price;
|
||||
|
||||
entity.RedirectURLTemplate = invoice.RedirectURL ?? store.StoreWebsite;
|
||||
entity.RedirectAutomatically =
|
||||
@ -170,16 +171,7 @@ namespace BTCPayServer.Controllers
|
||||
invoice.Checkout ??= new CreateInvoiceRequest.CheckoutOptions();
|
||||
invoice.Currency = invoice.Currency?.Trim().ToUpperInvariant() ?? "USD";
|
||||
entity.Currency = invoice.Currency;
|
||||
if (invoice.Amount is decimal v)
|
||||
{
|
||||
entity.Price = v;
|
||||
entity.Type = InvoiceType.Standard;
|
||||
}
|
||||
else
|
||||
{
|
||||
entity.Price = 0.0m;
|
||||
entity.Type = InvoiceType.TopUp;
|
||||
}
|
||||
entity.Price = invoice.Amount;
|
||||
entity.SpeedPolicy = invoice.Checkout.SpeedPolicy ?? store.SpeedPolicy;
|
||||
entity.DefaultLanguage = invoice.Checkout.DefaultLanguage;
|
||||
entity.RedirectAutomatically = invoice.Checkout.RedirectAutomatically ?? storeBlob.RedirectAutomatically;
|
||||
@ -203,23 +195,6 @@ namespace BTCPayServer.Controllers
|
||||
InvoiceLogs logs = new InvoiceLogs();
|
||||
logs.Write("Creation of invoice starting", InvoiceEventData.EventSeverity.Info);
|
||||
|
||||
entity.Price = Math.Max(0.0m, entity.Price);
|
||||
var currencyInfo = _CurrencyNameTable.GetNumberFormatInfo(entity.Currency, false);
|
||||
if (currencyInfo != null)
|
||||
{
|
||||
entity.Price = entity.Price.RoundToSignificant(currencyInfo.CurrencyDecimalDigits);
|
||||
}
|
||||
if (entity.Metadata.TaxIncluded is decimal taxIncluded)
|
||||
{
|
||||
if (currencyInfo != null)
|
||||
{
|
||||
taxIncluded = taxIncluded.RoundToSignificant(currencyInfo.CurrencyDecimalDigits);
|
||||
}
|
||||
taxIncluded = Math.Max(0.0m, taxIncluded);
|
||||
taxIncluded = Math.Min(taxIncluded, entity.Price);
|
||||
entity.Metadata.TaxIncluded = taxIncluded;
|
||||
}
|
||||
|
||||
var getAppsTaggingStore = _InvoiceRepository.GetAppsTaggingStore(store.Id);
|
||||
var storeBlob = store.GetStoreBlob();
|
||||
|
||||
|
@ -477,7 +477,7 @@ namespace BTCPayServer.Controllers
|
||||
{$"{BTCPayServer.Client.Policies.CanModifyStoreWebhooks}:", ("Modify selected stores' webhooks", "The app will modify the webhooks of the selected stores.")},
|
||||
{BTCPayServer.Client.Policies.CanViewStoreSettings, ("View your stores", "The app will be able to view stores settings.")},
|
||||
{$"{BTCPayServer.Client.Policies.CanViewStoreSettings}:", ("View your stores", "The app will be able to view the selected stores' settings.")},
|
||||
{BTCPayServer.Client.Policies.CanModifyServerSettings, ("Manage your server", "The app will have total control on the server settings of your server.")},
|
||||
{BTCPayServer.Client.Policies.CanModifyServerSettings, ("Manage your server", "The app will have total control on the server settings of your server")},
|
||||
{BTCPayServer.Client.Policies.CanViewProfile, ("View your profile", "The app will be able to view your user profile.")},
|
||||
{BTCPayServer.Client.Policies.CanModifyProfile, ("Manage your profile", "The app will be able to view and modify your user profile.")},
|
||||
{BTCPayServer.Client.Policies.CanManageNotificationsForUser, ("Manage your notifications", "The app will be able to view and modify your user notifications.")},
|
||||
|
@ -48,7 +48,7 @@ namespace BTCPayServer.Controllers
|
||||
ModelState.AddModelError("Store", "Store has not enabled Pay Button");
|
||||
}
|
||||
|
||||
if (model == null || (model.Price is decimal v ? v <= 0 : false))
|
||||
if (model == null || model.Price <= 0)
|
||||
ModelState.AddModelError("Price", "Price must be greater than 0");
|
||||
|
||||
if (!ModelState.IsValid)
|
||||
|
@ -22,51 +22,24 @@ using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace BTCPayServer.Controllers
|
||||
{
|
||||
public partial class ServerController
|
||||
{
|
||||
[HttpGet("server/files")]
|
||||
public async Task<IActionResult> Files([FromQuery] string[] fileIds = null)
|
||||
[HttpGet("server/files/{fileId?}")]
|
||||
public async Task<IActionResult> Files(string fileId = null)
|
||||
{
|
||||
var fileUrl = string.IsNullOrEmpty(fileId) ? null : await _FileService.GetFileUrl(Request.GetAbsoluteRootUri(), fileId);
|
||||
|
||||
var model = new ViewFilesViewModel()
|
||||
{
|
||||
Files = await _StoredFileRepository.GetFiles(),
|
||||
DirectUrlByFiles = null,
|
||||
Files = await _StoredFileRepository.GetFiles(),
|
||||
SelectedFileId = string.IsNullOrEmpty(fileUrl) ? null : fileId,
|
||||
DirectFileUrl = fileUrl,
|
||||
StorageConfigured = (await _SettingsRepository.GetSettingAsync<StorageSettings>()) != null
|
||||
};
|
||||
|
||||
if (fileIds != null && fileIds.Length > 0)
|
||||
{
|
||||
bool allFilesExist = true;
|
||||
Dictionary<string, string> directUrlByFiles = new Dictionary<string, string>();
|
||||
foreach (string filename in fileIds)
|
||||
{
|
||||
string fileUrl = await _FileService.GetFileUrl(Request.GetAbsoluteRootUri(), filename);
|
||||
if (fileUrl == null)
|
||||
{
|
||||
allFilesExist = false;
|
||||
break;
|
||||
}
|
||||
directUrlByFiles.Add(filename, fileUrl);
|
||||
}
|
||||
|
||||
if (!allFilesExist)
|
||||
{
|
||||
this.TempData.SetStatusMessageModel(new StatusMessageModel()
|
||||
{
|
||||
Message = "Some of the files were not found",
|
||||
Severity = StatusMessageModel.StatusSeverity.Warning,
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
model.DirectUrlByFiles = directUrlByFiles;
|
||||
}
|
||||
}
|
||||
return View(model);
|
||||
}
|
||||
|
||||
@ -78,7 +51,7 @@ namespace BTCPayServer.Controllers
|
||||
await _FileService.RemoveFile(fileId, null);
|
||||
return RedirectToAction(nameof(Files), new
|
||||
{
|
||||
fileIds = Array.Empty<string>(),
|
||||
fileId = "",
|
||||
statusMessage = "File removed"
|
||||
});
|
||||
}
|
||||
@ -154,7 +127,7 @@ namespace BTCPayServer.Controllers
|
||||
});
|
||||
return RedirectToAction(nameof(Files), new
|
||||
{
|
||||
fileIds = new string[] { fileId }
|
||||
fileId
|
||||
});
|
||||
|
||||
}
|
||||
@ -217,10 +190,18 @@ namespace BTCPayServer.Controllers
|
||||
Severity = statusMessageSeverity
|
||||
});
|
||||
|
||||
return RedirectToAction(nameof(Files), new
|
||||
{
|
||||
fileIds = fileIds.ToArray(),
|
||||
});
|
||||
if (fileIds.Count == 1)
|
||||
{
|
||||
return RedirectToAction(nameof(Files), new
|
||||
{
|
||||
statusMessage = "File added!",
|
||||
fileId = fileIds[0]
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
return RedirectToAction(nameof(Files));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -455,7 +455,7 @@ namespace BTCPayServer.Controllers
|
||||
|
||||
|
||||
[Route("server/services/{serviceName}/{cryptoCode?}")]
|
||||
public async Task<IActionResult> Service(string serviceName, string cryptoCode, bool showQR = false, ulong? nonce = null)
|
||||
public async Task<IActionResult> Service(string serviceName, string cryptoCode, bool showQR = false, uint? nonce = null)
|
||||
{
|
||||
var service = GetService(serviceName, cryptoCode);
|
||||
if (service == null)
|
||||
@ -603,7 +603,7 @@ namespace BTCPayServer.Controllers
|
||||
return View(nameof(LightningChargeServices), vm);
|
||||
}
|
||||
|
||||
private IActionResult LndServices(ExternalService service, ExternalConnectionString connectionString, ulong? nonce, string view = nameof(LndServices))
|
||||
private IActionResult LndServices(ExternalService service, ExternalConnectionString connectionString, uint? nonce, string view = nameof(LndServices))
|
||||
{
|
||||
var model = new LndServicesViewModel();
|
||||
if (service.Type == ExternalServiceTypes.LNDGRPC)
|
||||
@ -645,14 +645,14 @@ namespace BTCPayServer.Controllers
|
||||
return View(view, model);
|
||||
}
|
||||
|
||||
private static ulong GetConfigKey(string type, string serviceName, string cryptoCode, ulong nonce)
|
||||
private static uint GetConfigKey(string type, string serviceName, string cryptoCode, uint nonce)
|
||||
{
|
||||
return ((ulong)(uint)HashCode.Combine(type, serviceName, cryptoCode, nonce) | (nonce & 0xffffffff00000000UL));
|
||||
return (uint)HashCode.Combine(type, serviceName, cryptoCode, nonce);
|
||||
}
|
||||
|
||||
[Route("lnd-config/{configKey}/lnd.config")]
|
||||
[AllowAnonymous]
|
||||
public IActionResult GetLNDConfig(ulong configKey)
|
||||
public IActionResult GetLNDConfig(uint configKey)
|
||||
{
|
||||
var conf = _LnConfigProvider.GetConfig(configKey);
|
||||
if (conf == null)
|
||||
@ -712,7 +712,7 @@ namespace BTCPayServer.Controllers
|
||||
commonConf.ReadonlyMacaroon = connectionString.Macaroons?.ReadonlyMacaroon?.Hex;
|
||||
commonConf.InvoiceMacaroon = connectionString.Macaroons?.InvoiceMacaroon?.Hex;
|
||||
|
||||
var nonce = RandomUtils.GetUInt64();
|
||||
var nonce = RandomUtils.GetUInt32();
|
||||
var configKey = GetConfigKey("lnd", serviceName, cryptoCode, nonce);
|
||||
_LnConfigProvider.KeepConfig(configKey, confs);
|
||||
return RedirectToAction(nameof(Service), new { cryptoCode = cryptoCode, serviceName = serviceName, nonce = nonce });
|
||||
|
@ -305,11 +305,9 @@ namespace BTCPayServer.Controllers
|
||||
derivationSchemeSettings.AccountOriginal = response.DerivationScheme.ToString();
|
||||
|
||||
// Set wallet properties from generate response
|
||||
vm.RootFingerprint = response.AccountKeyPath.MasterFingerprint.ToString();
|
||||
vm.AccountKey = response.AccountHDKey.Neuter().ToWif();
|
||||
vm.KeyPath = response.AccountKeyPath.KeyPath.ToString();
|
||||
vm.Config = ProtectString(derivationSchemeSettings.ToJson());
|
||||
|
||||
|
||||
var result = await UpdateWallet(vm);
|
||||
|
||||
if (!ModelState.IsValid || !(result is RedirectToActionResult))
|
||||
|
@ -999,7 +999,7 @@ namespace BTCPayServer.Controllers
|
||||
var appUrl = HttpContext.Request.GetAbsoluteRoot().WithTrailingSlash();
|
||||
var model = new PayButtonViewModel
|
||||
{
|
||||
Price = null,
|
||||
Price = 10,
|
||||
Currency = DEFAULT_CURRENCY,
|
||||
ButtonSize = 2,
|
||||
UrlRoot = appUrl,
|
||||
|
@ -135,7 +135,7 @@ namespace BTCPayServer.Controllers
|
||||
Name = store.StoreName,
|
||||
WebSite = store.StoreWebsite,
|
||||
IsOwner = store.Role == StoreRoles.Owner,
|
||||
HintWalletWarning = blob.Hints.Wallet && blob.Hints.Lightning
|
||||
HintWalletWarning = blob.Hints.Wallet
|
||||
});
|
||||
}
|
||||
return View(result);
|
||||
|
@ -204,18 +204,10 @@ namespace BTCPayServer.Controllers
|
||||
});
|
||||
}
|
||||
var command = vm.Command.Substring(vm.Command.IndexOf('-', StringComparison.InvariantCulture) + 1);
|
||||
var handler = _payoutHandlers
|
||||
.FirstOrDefault(handler => handler.CanHandle(paymentMethodId));
|
||||
if (handler != null)
|
||||
{
|
||||
var result = await handler.DoSpecificAction(command, payoutIds, walletId.StoreId);
|
||||
if (result != null)
|
||||
{
|
||||
TempData.SetStatusMessageModel(result);
|
||||
}
|
||||
}
|
||||
|
||||
switch (command)
|
||||
{
|
||||
|
||||
case "approve-pay":
|
||||
case "approve":
|
||||
{
|
||||
@ -272,7 +264,8 @@ namespace BTCPayServer.Controllers
|
||||
{
|
||||
Message = "Payouts approved", Severity = StatusMessageModel.StatusSeverity.Success
|
||||
});
|
||||
break;
|
||||
return RedirectToAction(nameof(Payouts),
|
||||
new {walletId = walletId.ToString(), pullPaymentId = vm.PullPaymentId});
|
||||
}
|
||||
|
||||
case "pay":
|
||||
@ -297,10 +290,7 @@ namespace BTCPayServer.Controllers
|
||||
|
||||
}
|
||||
if(bip21.Any())
|
||||
{
|
||||
TempData.SetStatusMessageModel(null);
|
||||
return RedirectToAction(nameof(WalletSend), new {walletId, bip21});
|
||||
}
|
||||
TempData.SetStatusMessageModel(new StatusMessageModel()
|
||||
{
|
||||
Severity = StatusMessageModel.StatusSeverity.Error,
|
||||
@ -347,7 +337,8 @@ namespace BTCPayServer.Controllers
|
||||
{
|
||||
Message = "Payouts marked as paid", Severity = StatusMessageModel.StatusSeverity.Success
|
||||
});
|
||||
break;
|
||||
return RedirectToAction(nameof(Payouts),
|
||||
new {walletId = walletId.ToString(), pullPaymentId = vm.PullPaymentId});
|
||||
}
|
||||
|
||||
case "cancel":
|
||||
@ -357,10 +348,25 @@ namespace BTCPayServer.Controllers
|
||||
{
|
||||
Message = "Payouts archived", Severity = StatusMessageModel.StatusSeverity.Success
|
||||
});
|
||||
break;
|
||||
return RedirectToAction(nameof(Payouts),
|
||||
new {walletId = walletId.ToString(), pullPaymentId = vm.PullPaymentId});
|
||||
}
|
||||
return RedirectToAction(nameof(Payouts),
|
||||
new {walletId = walletId.ToString(), pullPaymentId = vm.PullPaymentId});
|
||||
|
||||
var handler = _payoutHandlers
|
||||
.FirstOrDefault(handler => handler.CanHandle(paymentMethodId));
|
||||
|
||||
if (handler != null)
|
||||
{
|
||||
var result = await handler.DoSpecificAction(command, payoutIds, walletId.StoreId);
|
||||
TempData.SetStatusMessageModel(result);
|
||||
return RedirectToAction(nameof(Payouts), new
|
||||
{
|
||||
walletId = walletId.ToString(),
|
||||
pullPaymentId = vm.PullPaymentId
|
||||
});
|
||||
}
|
||||
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
private static async Task<List<PayoutData>> GetPayoutsForPaymentMethod(PaymentMethodId paymentMethodId,
|
||||
|
@ -489,13 +489,8 @@ namespace BTCPayServer.Controllers
|
||||
.ToArray();
|
||||
var balance = _walletProvider.GetWallet(network).GetBalance(paymentMethod.AccountDerivation);
|
||||
model.NBXSeedAvailable = await GetSeed(walletId, network) != null;
|
||||
var Balance= await balance;
|
||||
model.CurrentBalance = (Balance.Available ?? Balance.Total).GetValue(network);
|
||||
if (Balance.Immature is null)
|
||||
model.ImmatureBalance = 0;
|
||||
else
|
||||
model.ImmatureBalance = Balance.Immature.GetValue(network);
|
||||
|
||||
model.CurrentBalance = (await balance).Total.GetValue(network);
|
||||
|
||||
await Task.WhenAll(recommendedFees);
|
||||
model.RecommendedSatoshiPerByte =
|
||||
recommendedFees.Select(tuple => tuple.Result).Where(option => option != null).ToList();
|
||||
@ -630,23 +625,16 @@ namespace BTCPayServer.Controllers
|
||||
}
|
||||
transactionOutput.DestinationAddress = transactionOutput.DestinationAddress?.Trim() ?? string.Empty;
|
||||
|
||||
var inputName =
|
||||
string.Format(CultureInfo.InvariantCulture, "Outputs[{0}].", i.ToString(CultureInfo.InvariantCulture)) +
|
||||
nameof(transactionOutput.DestinationAddress);
|
||||
try
|
||||
{
|
||||
var address = BitcoinAddress.Create(transactionOutput.DestinationAddress, network.NBitcoinNetwork);
|
||||
if (address is TaprootAddress)
|
||||
{
|
||||
var supportTaproot = _dashboard.Get(network.CryptoCode)?.Status?.BitcoinStatus?.Capabilities?.CanSupportTaproot;
|
||||
if (!(supportTaproot is true))
|
||||
{
|
||||
ModelState.AddModelError(inputName, "You need to update your full node, and/or NBXplorer (Version >= 2.1.56) to be able to send to a taproot address.");
|
||||
}
|
||||
}
|
||||
BitcoinAddress.Create(transactionOutput.DestinationAddress, network.NBitcoinNetwork);
|
||||
}
|
||||
catch
|
||||
{
|
||||
var inputName =
|
||||
string.Format(CultureInfo.InvariantCulture, "Outputs[{0}].", i.ToString(CultureInfo.InvariantCulture)) +
|
||||
nameof(transactionOutput.DestinationAddress);
|
||||
|
||||
ModelState.AddModelError(inputName, "Invalid address");
|
||||
}
|
||||
|
||||
@ -1070,8 +1058,7 @@ namespace BTCPayServer.Controllers
|
||||
using CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromSeconds(10));
|
||||
try
|
||||
{
|
||||
var b = await wallet.GetBalance(derivationStrategy, cts.Token);
|
||||
return (b.Available ?? b.Total).ShowMoney(wallet.Network);
|
||||
return (await wallet.GetBalance(derivationStrategy, cts.Token)).Total.ShowMoney(wallet.Network);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
@ -70,11 +70,10 @@ public class BitcoinLikePayoutHandler : IPayoutHandler
|
||||
destination = destination.Trim();
|
||||
try
|
||||
{
|
||||
// This doesn't work properly, (payouts are not detected), we can reactivate later when we fix the bug https://github.com/btcpayserver/btcpayserver/issues/2765
|
||||
//if (destination.StartsWith($"{network.UriScheme}:", StringComparison.OrdinalIgnoreCase))
|
||||
//{
|
||||
// return Task.FromResult<IClaimDestination>(new UriClaimDestination(new BitcoinUrlBuilder(destination, network.NBitcoinNetwork)));
|
||||
//}
|
||||
if (destination.StartsWith($"{network.UriScheme}:", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return Task.FromResult<IClaimDestination>(new UriClaimDestination(new BitcoinUrlBuilder(destination, network.NBitcoinNetwork)));
|
||||
}
|
||||
|
||||
return Task.FromResult<IClaimDestination>(new AddressClaimDestination(BitcoinAddress.Create(destination, network.NBitcoinNetwork)));
|
||||
}
|
||||
@ -144,6 +143,7 @@ public class BitcoinLikePayoutHandler : IPayoutHandler
|
||||
{
|
||||
{PayoutState.AwaitingPayment, new List<(string Action, string Text)>()
|
||||
{
|
||||
("confirm-payment", "Confirm payouts as paid"),
|
||||
("reject-payment", "Reject payout transaction")
|
||||
}}
|
||||
};
|
||||
@ -153,7 +153,7 @@ public class BitcoinLikePayoutHandler : IPayoutHandler
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case "mark-paid":
|
||||
case "confirm-payment":
|
||||
await using (var context = _dbContextFactory.CreateContext())
|
||||
{
|
||||
var payouts = (await context.Payouts
|
||||
|
@ -43,13 +43,6 @@ namespace BTCPayServer.HostedServices
|
||||
|
||||
public bool Dirty => _Dirty;
|
||||
public bool Unaffect => _Unaffect;
|
||||
|
||||
bool _IsBlobUpdated;
|
||||
public bool IsBlobUpdated => _IsBlobUpdated;
|
||||
public void BlobUpdated()
|
||||
{
|
||||
_IsBlobUpdated = true;
|
||||
}
|
||||
}
|
||||
|
||||
readonly InvoiceRepository _InvoiceRepository;
|
||||
@ -90,26 +83,13 @@ namespace BTCPayServer.HostedServices
|
||||
return;
|
||||
if (invoice.Status == InvoiceStatusLegacy.New || invoice.Status == InvoiceStatusLegacy.Expired)
|
||||
{
|
||||
var isPaid = invoice.IsUnsetTopUp() ?
|
||||
accounting.Paid > Money.Zero :
|
||||
accounting.Paid >= accounting.MinimumTotalDue;
|
||||
if (isPaid)
|
||||
if (accounting.Paid >= accounting.MinimumTotalDue)
|
||||
{
|
||||
if (invoice.Status == InvoiceStatusLegacy.New)
|
||||
{
|
||||
context.Events.Add(new InvoiceEvent(invoice, InvoiceEvent.PaidInFull));
|
||||
invoice.Status = InvoiceStatusLegacy.Paid;
|
||||
if (invoice.IsUnsetTopUp())
|
||||
{
|
||||
invoice.ExceptionStatus = InvoiceExceptionStatus.None;
|
||||
invoice.Price = (accounting.Paid - accounting.NetworkFeeAlreadyPaid).ToDecimal(MoneyUnit.BTC) * paymentMethod.Rate;
|
||||
accounting = paymentMethod.Calculate();
|
||||
context.BlobUpdated();
|
||||
}
|
||||
else
|
||||
{
|
||||
invoice.ExceptionStatus = accounting.Paid > accounting.TotalDue ? InvoiceExceptionStatus.PaidOver : InvoiceExceptionStatus.None;
|
||||
}
|
||||
invoice.ExceptionStatus = accounting.Paid > accounting.TotalDue ? InvoiceExceptionStatus.PaidOver : InvoiceExceptionStatus.None;
|
||||
context.UnaffectAddresses();
|
||||
context.MarkDirty();
|
||||
}
|
||||
@ -313,10 +293,6 @@ namespace BTCPayServer.HostedServices
|
||||
await _InvoiceRepository.UpdateInvoiceStatus(invoice.Id, invoice.GetInvoiceState());
|
||||
updateContext.Events.Insert(0, new InvoiceDataChangedEvent(invoice));
|
||||
}
|
||||
if (updateContext.IsBlobUpdated)
|
||||
{
|
||||
await _InvoiceRepository.UpdateInvoicePrice(invoice.Id, invoice);
|
||||
}
|
||||
|
||||
foreach (var evt in updateContext.Events)
|
||||
{
|
||||
|
@ -150,11 +150,7 @@ namespace BTCPayServer.Hosting
|
||||
foreach (var paymentMethod in store.GetSupportedPaymentMethods(_NetworkProvider).OfType<DerivationSchemeSettings>())
|
||||
{
|
||||
paymentMethod.IsHotWallet = paymentMethod.Source == "NBXplorer";
|
||||
if (paymentMethod.IsHotWallet)
|
||||
{
|
||||
paymentMethod.Source = "NBXplorerGenerated";
|
||||
store.SetSupportedPaymentMethod(paymentMethod);
|
||||
}
|
||||
paymentMethod.Source = "NBXplorerGenerated";
|
||||
}
|
||||
}
|
||||
await ctx.SaveChangesAsync();
|
||||
|
@ -51,7 +51,7 @@ namespace BTCPayServer.ModelBinders
|
||||
// Parse() method trims the value (with common NumberStyles) then throws if the result is empty.
|
||||
model = null;
|
||||
}
|
||||
else if (type == typeof(decimal) || type == typeof(decimal?))
|
||||
else if (type == typeof(decimal))
|
||||
{
|
||||
model = decimal.Parse(value, _supportedStyles, culture);
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ namespace BTCPayServer.Models.AppViewModels
|
||||
public string NotificationUrl { get; set; }
|
||||
|
||||
[Required]
|
||||
[Display(Name = "Make Crowdfund Public")]
|
||||
[Display(Name = "Allow crowdfund to be publicly visible (still visible to you)")]
|
||||
public bool Enabled { get; set; } = false;
|
||||
|
||||
[Required]
|
||||
@ -44,13 +44,9 @@ namespace BTCPayServer.Models.AppViewModels
|
||||
[Display(Name = "Enable Disqus Comments")]
|
||||
public bool DisqusEnabled { get; set; } = true;
|
||||
|
||||
[Display(Name = "Disqus Shortname")]
|
||||
public string DisqusShortname { get; set; }
|
||||
|
||||
[Display(Name = "Start date")]
|
||||
[Display(Name = "Disqus Shortname")] public string DisqusShortname { get; set; }
|
||||
|
||||
public DateTime? StartDate { get; set; }
|
||||
|
||||
[Display(Name = "End date")]
|
||||
public DateTime? EndDate { get; set; }
|
||||
|
||||
[Required]
|
||||
@ -58,17 +54,19 @@ namespace BTCPayServer.Models.AppViewModels
|
||||
[Display(Name = "Primary currency used for targets and stats. (e.g. BTC, LTC, USD, etc.)")]
|
||||
public string TargetCurrency { get; set; } = "BTC";
|
||||
|
||||
[Display(Name = "Set a target amount")]
|
||||
[Display(Name = "Set a Target amount ")]
|
||||
[Range(0, double.PositiveInfinity)]
|
||||
public decimal? TargetAmount { get; set; }
|
||||
|
||||
|
||||
|
||||
public IEnumerable<string> ResetEveryValues = Enum.GetNames(typeof(CrowdfundResetEvery));
|
||||
|
||||
[Display(Name = "Reset goal every")]
|
||||
public string ResetEvery { get; set; } = nameof(CrowdfundResetEvery.Never);
|
||||
|
||||
public int ResetEveryAmount { get; set; } = 1;
|
||||
|
||||
|
||||
|
||||
[Display(Name = "Do not allow additional contributions after target has been reached")]
|
||||
public bool EnforceTargetAmount { get; set; }
|
||||
|
||||
@ -82,7 +80,7 @@ namespace BTCPayServer.Models.AppViewModels
|
||||
[Display(Name = "Custom CSS Code")]
|
||||
public string EmbeddedCSS { get; set; }
|
||||
|
||||
[Display(Name = "Count all invoices created on the store as part of the goal")]
|
||||
[Display(Name = "Count all invoices created on the store as part of the crowdfunding goal")]
|
||||
public bool UseAllStoreInvoices { get; set; }
|
||||
|
||||
public string AppId { get; set; }
|
||||
@ -90,13 +88,12 @@ namespace BTCPayServer.Models.AppViewModels
|
||||
|
||||
[Display(Name = "Sort contribution perks by popularity")]
|
||||
public bool SortPerksByPopularity { get; set; }
|
||||
|
||||
[Display(Name = "Display contribution ranking")]
|
||||
public bool DisplayPerksRanking { get; set; }
|
||||
|
||||
|
||||
[Display(Name = "Sounds to play when a payment is made. One sound per line")]
|
||||
public string Sounds { get; set; }
|
||||
|
||||
[Display(Name = "Colors to rotate between with animation when a payment is made. First color is the default background. One color per line. Can be any valid css color value.")]
|
||||
public string AnimationColors { get; set; }
|
||||
|
||||
|
@ -51,7 +51,7 @@ namespace BTCPayServer.Models
|
||||
[JsonProperty(PropertyName = "currency", DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public string Currency { get; set; }
|
||||
[JsonProperty(PropertyName = "price", DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public decimal? Price { get; set; }
|
||||
public decimal Price { get; set; }
|
||||
[JsonProperty(PropertyName = "notificationEmail", DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public string NotificationEmail { get; set; }
|
||||
[JsonConverter(typeof(DateTimeJsonConverter))]
|
||||
|
@ -14,6 +14,7 @@ namespace BTCPayServer.Models.InvoicingModels
|
||||
Currency = "USD";
|
||||
}
|
||||
|
||||
[Required]
|
||||
public decimal? Amount
|
||||
{
|
||||
get; set;
|
||||
|
@ -27,7 +27,6 @@ namespace BTCPayServer.Models.InvoicingModels
|
||||
public string DefaultLang { get; set; }
|
||||
public List<AvailableCrypto> AvailableCryptos { get; set; } = new List<AvailableCrypto>();
|
||||
public bool IsModal { get; set; }
|
||||
public bool IsUnsetTopUp { get; set; }
|
||||
public string CryptoCode { get; set; }
|
||||
public string InvoiceId { get; set; }
|
||||
public string BtcAddress { get; set; }
|
||||
|
@ -159,7 +159,6 @@ namespace BTCPayServer.Models.PaymentRequestViewModels
|
||||
public DateTime ReceivedDate { get; set; }
|
||||
public string Link { get; set; }
|
||||
public string Id { get; set; }
|
||||
public string Destination { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using BTCPayServer.Abstractions.Extensions;
|
||||
using BTCPayServer.Services;
|
||||
|
||||
namespace BTCPayServer.Models.ServerViewModels
|
||||
@ -24,7 +23,7 @@ namespace BTCPayServer.Models.ServerViewModels
|
||||
{
|
||||
if (Settings?.LastUpdated is DateTimeOffset date)
|
||||
{
|
||||
return ViewsRazor.ToTimeAgo(date);
|
||||
return Views.ViewsRazor.ToTimeAgo(date);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -6,7 +6,8 @@ namespace BTCPayServer.Models.ServerViewModels
|
||||
public class ViewFilesViewModel
|
||||
{
|
||||
public List<StoredFile> Files { get; set; }
|
||||
public Dictionary<string, string> DirectUrlByFiles { get; set; }
|
||||
public string DirectFileUrl { get; set; }
|
||||
public string SelectedFileId { get; set; }
|
||||
public bool StorageConfigured { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ namespace BTCPayServer.Models.StoreViewModels
|
||||
public class PayButtonViewModel
|
||||
{
|
||||
[ModelBinder(BinderType = typeof(InvariantDecimalModelBinder))]
|
||||
public decimal? Price { get; set; }
|
||||
public decimal Price { get; set; }
|
||||
public string InvoiceId { get; set; }
|
||||
[Required]
|
||||
public string Currency { get; set; }
|
||||
|
@ -1,9 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using BTCPayServer.Abstractions.Extensions;
|
||||
using BTCPayServer.Client.Models;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.Services.Rates;
|
||||
using BTCPayServer.Views;
|
||||
using PullPaymentData = BTCPayServer.Data.PullPaymentData;
|
||||
|
||||
namespace BTCPayServer.Models
|
||||
|
@ -35,7 +35,6 @@ namespace BTCPayServer.Models.WalletViewModels
|
||||
public bool SubtractFeesFromOutput { get; set; }
|
||||
}
|
||||
public decimal CurrentBalance { get; set; }
|
||||
public decimal ImmatureBalance { get; set; }
|
||||
|
||||
public string CryptoCode { get; set; }
|
||||
|
||||
|
@ -102,44 +102,6 @@ namespace BTCPayServer.PaymentRequest
|
||||
Invoices = invoices.Select(entity =>
|
||||
{
|
||||
var state = entity.GetInvoiceState();
|
||||
var payments = entity
|
||||
.GetPayments(true)
|
||||
.Select(paymentEntity =>
|
||||
{
|
||||
var paymentData = paymentEntity.GetCryptoPaymentData();
|
||||
var paymentMethodId = paymentEntity.GetPaymentMethodId();
|
||||
if (paymentData is null || paymentMethodId is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
string txId = paymentData.GetPaymentId();
|
||||
string link = GetTransactionLink(paymentMethodId, txId);
|
||||
var paymentMethod = entity.GetPaymentMethod(paymentMethodId);
|
||||
var amount = paymentData.GetValue();
|
||||
var rate = paymentMethod.Rate;
|
||||
var paid = (amount - paymentEntity.NetworkFee) * rate;
|
||||
|
||||
return new ViewPaymentRequestViewModel.PaymentRequestInvoicePayment
|
||||
{
|
||||
Amount = amount,
|
||||
Paid = paid,
|
||||
ReceivedDate = paymentEntity.ReceivedTime.DateTime,
|
||||
PaidFormatted = _currencies.FormatCurrency(paid, blob.Currency),
|
||||
RateFormatted = _currencies.FormatCurrency(rate, blob.Currency),
|
||||
PaymentMethod = paymentMethodId.ToPrettyString(),
|
||||
Link = link,
|
||||
Id = txId,
|
||||
Destination = paymentData.GetDestination()
|
||||
};
|
||||
})
|
||||
.Where(payment => payment != null)
|
||||
.ToList();
|
||||
|
||||
if (state.Status == InvoiceStatusLegacy.Invalid ||
|
||||
state.Status == InvoiceStatusLegacy.Expired && !payments.Any())
|
||||
return null;
|
||||
|
||||
return new ViewPaymentRequestViewModel.PaymentRequestInvoice
|
||||
{
|
||||
Id = entity.Id,
|
||||
@ -149,11 +111,40 @@ namespace BTCPayServer.PaymentRequest
|
||||
ExpiryDate = entity.ExpirationTime.DateTime,
|
||||
State = state,
|
||||
StateFormatted = state.ToString(),
|
||||
Payments = payments
|
||||
Payments = entity
|
||||
.GetPayments(true)
|
||||
.Select(paymentEntity =>
|
||||
{
|
||||
var paymentData = paymentEntity.GetCryptoPaymentData();
|
||||
var paymentMethodId = paymentEntity.GetPaymentMethodId();
|
||||
if (paymentData is null || paymentMethodId is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
string txId = paymentData.GetPaymentId();
|
||||
string link = GetTransactionLink(paymentMethodId, txId);
|
||||
var paymentMethod = entity.GetPaymentMethod(paymentMethodId);
|
||||
var amount = paymentData.GetValue();
|
||||
var rate = paymentMethod.Rate;
|
||||
var paid = (amount - paymentEntity.NetworkFee) * rate;
|
||||
|
||||
return new ViewPaymentRequestViewModel.PaymentRequestInvoicePayment
|
||||
{
|
||||
Amount = amount,
|
||||
Paid = paid,
|
||||
ReceivedDate = paymentEntity.ReceivedTime.DateTime,
|
||||
PaidFormatted = _currencies.FormatCurrency(paid, blob.Currency),
|
||||
RateFormatted = _currencies.FormatCurrency(rate, blob.Currency),
|
||||
PaymentMethod = paymentMethodId.ToPrettyString(),
|
||||
Link = link,
|
||||
Id = txId
|
||||
};
|
||||
})
|
||||
.Where(payment => payment != null)
|
||||
.ToList()
|
||||
};
|
||||
})
|
||||
.Where(invoice => invoice != null)
|
||||
.ToList()
|
||||
}).ToList()
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -413,7 +413,7 @@ namespace BTCPayServer.Payments.PayJoin
|
||||
if (additionalFee > Money.Zero)
|
||||
{
|
||||
// If the user overpaid, taking fee on our output (useful if sender dump a full UTXO for privacy)
|
||||
for (int i = 0; i < newTx.Outputs.Count && additionalFee > Money.Zero && due < Money.Zero && !invoice.IsUnsetTopUp(); i++)
|
||||
for (int i = 0; i < newTx.Outputs.Count && additionalFee > Money.Zero && due < Money.Zero; i++)
|
||||
{
|
||||
if (disableoutputsubstitution)
|
||||
break;
|
||||
|
@ -55,14 +55,11 @@ namespace BTCPayServer.Plugins
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
detectedPlugins = detectedPlugins.Select(plugin =>
|
||||
foreach (var btcPayServerPlugin in detectedPlugins)
|
||||
{
|
||||
plugin.SystemPlugin = true;
|
||||
return plugin;
|
||||
});
|
||||
|
||||
loadedPlugins.Add((null,systemExtension, CreateEmbeddedFileProviderForAssembly(systemExtension)));
|
||||
btcPayServerPlugin.SystemPlugin = true;
|
||||
loadedPlugins.Add((null,systemExtension, CreateEmbeddedFileProviderForAssembly(systemExtension)));
|
||||
}
|
||||
plugins.AddRange(detectedPlugins);
|
||||
}
|
||||
var orderFilePath = Path.Combine(pluginsFolder, "order");
|
||||
|
@ -13,7 +13,6 @@ using NBitcoin.DataEncoders;
|
||||
using NBitpayClient;
|
||||
using NBXplorer;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
@ -397,10 +396,6 @@ namespace BTCPayServer.Services.Invoices
|
||||
public double PaymentTolerance { get; set; }
|
||||
public bool Archived { get; set; }
|
||||
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public InvoiceType Type { get; set; }
|
||||
|
||||
public bool IsExpired()
|
||||
{
|
||||
return DateTimeOffset.UtcNow > ExpirationTime;
|
||||
@ -686,11 +681,6 @@ namespace BTCPayServer.Services.Invoices
|
||||
throw new InvalidOperationException("Not a legacy invoice");
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsUnsetTopUp()
|
||||
{
|
||||
return Type == InvoiceType.TopUp && Price == 0.0m;
|
||||
}
|
||||
}
|
||||
|
||||
public enum InvoiceStatusLegacy
|
||||
@ -875,10 +865,6 @@ namespace BTCPayServer.Services.Invoices
|
||||
/// </summary>
|
||||
public Money NetworkFee { get; set; }
|
||||
/// <summary>
|
||||
/// Total amount of network fee to pay to the invoice
|
||||
/// </summary>
|
||||
public Money NetworkFeeAlreadyPaid { get; set; }
|
||||
/// <summary>
|
||||
/// Minimum required to be paid in order to accept invoice as paid
|
||||
/// </summary>
|
||||
public Money MinimumTotalDue { get; set; }
|
||||
@ -1005,14 +991,13 @@ namespace BTCPayServer.Services.Invoices
|
||||
var totalDueNoNetworkCost = Money.Coins(Extensions.RoundUp(totalDue, precision));
|
||||
bool paidEnough = paid >= Extensions.RoundUp(totalDue, precision);
|
||||
int txRequired = 0;
|
||||
decimal networkFeeAlreadyPaid = 0.0m;
|
||||
|
||||
_ = ParentEntity.GetPayments(true)
|
||||
.Where(p => paymentPredicate(p))
|
||||
.OrderBy(p => p.ReceivedTime)
|
||||
.Select(_ =>
|
||||
{
|
||||
var txFee = _.GetValue(paymentMethods, GetId(), _.NetworkFee, precision);
|
||||
networkFeeAlreadyPaid += txFee;
|
||||
paid += _.GetValue(paymentMethods, GetId(), null, precision);
|
||||
if (!paidEnough)
|
||||
{
|
||||
@ -1044,7 +1029,6 @@ namespace BTCPayServer.Services.Invoices
|
||||
accounting.Due = Money.Max(accounting.TotalDue - accounting.Paid, Money.Zero);
|
||||
accounting.DueUncapped = accounting.TotalDue - accounting.Paid;
|
||||
accounting.NetworkFee = accounting.TotalDue - totalDueNoNetworkCost;
|
||||
accounting.NetworkFeeAlreadyPaid = Money.Coins(Extensions.RoundUp(networkFeeAlreadyPaid, precision));
|
||||
// If the total due is 0, there is no payment tolerance to calculate
|
||||
var minimumTotalDueSatoshi = accounting.TotalDue.Satoshi == 0
|
||||
? 0
|
||||
|
@ -206,8 +206,7 @@ namespace BTCPayServer.Services.Invoices
|
||||
|
||||
textSearch.Add(invoice.Id);
|
||||
textSearch.Add(invoice.InvoiceTime.ToString(CultureInfo.InvariantCulture));
|
||||
if (!invoice.IsUnsetTopUp())
|
||||
textSearch.Add(invoice.Price.ToString(CultureInfo.InvariantCulture));
|
||||
textSearch.Add(invoice.Price.ToString(CultureInfo.InvariantCulture));
|
||||
textSearch.Add(invoice.Metadata.OrderId);
|
||||
textSearch.Add(invoice.StoreId);
|
||||
textSearch.Add(invoice.Metadata.BuyerEmail);
|
||||
@ -426,22 +425,6 @@ namespace BTCPayServer.Services.Invoices
|
||||
await context.SaveChangesAsync().ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
internal async Task UpdateInvoicePrice(string invoiceId, InvoiceEntity invoice)
|
||||
{
|
||||
if (invoice.Type != InvoiceType.TopUp)
|
||||
throw new ArgumentException("The invoice type should be TopUp to be able to update invoice price", nameof(invoice));
|
||||
using (var context = _ContextFactory.CreateContext())
|
||||
{
|
||||
var invoiceData = await context.FindAsync<Data.InvoiceData>(invoiceId).ConfigureAwait(false);
|
||||
if (invoiceData == null)
|
||||
return;
|
||||
var blob = invoiceData.GetBlob(_Networks);
|
||||
blob.Price = invoice.Price;
|
||||
AddToTextSearch(context, invoiceData, new[] { invoice.Price.ToString(CultureInfo.InvariantCulture) });
|
||||
invoiceData.Blob = ToBytes(blob, null);
|
||||
await context.SaveChangesAsync().ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task MassArchive(string[] invoiceIds)
|
||||
{
|
||||
|
@ -1,10 +1,7 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Services
|
||||
{
|
||||
public class MigrationSettings
|
||||
{
|
||||
[JsonProperty("MigrateHotwalletProperty2")]
|
||||
public bool MigrateHotwalletProperty { get; set; }
|
||||
public bool MigrateU2FToFIDO2{ get; set; }
|
||||
public bool UnreachableStoreCheck { get; set; }
|
||||
|
@ -21,12 +21,11 @@
|
||||
|
||||
<h2 class="mb-4">@ViewData["PageTitle"]</h2>
|
||||
|
||||
<form method="post">
|
||||
<input type="hidden" asp-for="StoreId" />
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<form method="post">
|
||||
<input type="hidden" asp-for="StoreId" />
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Title" class="form-label" data-required></label>
|
||||
<input asp-for="Title" class="form-control" required />
|
||||
@ -37,15 +36,11 @@
|
||||
<input asp-for="Tagline" class="form-control" />
|
||||
<span asp-validation-for="Tagline" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-9">
|
||||
<div class="form-group">
|
||||
<label asp-for="Description" class="form-label" data-required></label>
|
||||
<textarea asp-for="Description" rows="20" cols="40" class="form-control richtext"></textarea>
|
||||
<span asp-validation-for="Description" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="form-group">
|
||||
<label asp-for="TargetCurrency" class="form-label" data-required></label>
|
||||
<input asp-for="TargetCurrency" class="form-control" required />
|
||||
@ -61,8 +56,7 @@
|
||||
<div class="input-group">
|
||||
<input type="datetime-local" asp-for="StartDate"
|
||||
value="@(Model.StartDate?.ToString("u", CultureInfo.InvariantCulture))"
|
||||
class="form-control flatdtpicker"
|
||||
placeholder="No start date has been set" />
|
||||
class="form-control flatdtpicker" placeholder="No start date has been set for this crowdfund" />
|
||||
<button class="btn btn-secondary input-group-clear" type="button" title="Clear">
|
||||
<span class="fa fa-times"></span>
|
||||
</button>
|
||||
@ -70,19 +64,6 @@
|
||||
<span asp-validation-for="StartDate" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="EndDate" class="form-label"></label>
|
||||
<div class="input-group">
|
||||
<input type="datetime-local" asp-for="EndDate"
|
||||
value="@(Model.EndDate?.ToString("u", CultureInfo.InvariantCulture))"
|
||||
class="form-control flatdtpicker"
|
||||
placeholder="No end date has been set" />
|
||||
<button class="btn btn-secondary input-group-clear input-group-text" type="button" title="Clear">
|
||||
<span class="fa fa-times"></span>
|
||||
</button>
|
||||
</div>
|
||||
<span asp-validation-for="EndDate" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group mb-4">
|
||||
<label asp-for="ResetEvery" class="form-label"></label>
|
||||
<div class="input-group">
|
||||
<input type="number" asp-for="ResetEveryAmount" placeholder="Amount" class="form-control">
|
||||
@ -94,156 +75,133 @@
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group mb-3">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<input asp-for="Enabled" type="checkbox" class="btcpay-toggle me-2"/>
|
||||
<label asp-for="Enabled" class="form-label mb-0"></label>
|
||||
<div class="form-group">
|
||||
<label asp-for="EndDate" class="form-label"></label>
|
||||
<div class="input-group">
|
||||
<input type="datetime-local" asp-for="EndDate"
|
||||
value="@(Model.EndDate?.ToString("u", CultureInfo.InvariantCulture))"
|
||||
class="form-control flatdtpicker"
|
||||
placeholder="No end date has been set for this crowdfund" />
|
||||
<button class="btn btn-secondary input-group-clear input-group-text" type="button" title="Clear">
|
||||
<span class="fa fa-times"></span>
|
||||
</button>
|
||||
</div>
|
||||
<span asp-validation-for="Enabled" class="text-danger"></span>
|
||||
<div class="text-muted">The crowdfund is only visible to you. To make it visible to anyone else, enable this.</div>
|
||||
<span asp-validation-for="EndDate" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-12">
|
||||
|
||||
<partial name="TemplateEditor" model="@(nameof(Model.PerksTemplate), "Perks")" />
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
|
||||
<div class="form-group">
|
||||
<label asp-for="PerksTemplate" class="form-label"></label>
|
||||
<textarea asp-for="PerksTemplate" rows="10" cols="40" class="js-product-template form-control"></textarea>
|
||||
<span asp-validation-for="PerksTemplate" class="text-danger"></span>
|
||||
</div>
|
||||
<h4 class="mt-5 mb-4">Contributions</h4>
|
||||
<div class="form-check mb-3">
|
||||
<input asp-for="SortPerksByPopularity" type="checkbox" class="form-check-input" />
|
||||
<label asp-for="SortPerksByPopularity" class="form-check-label"></label>
|
||||
<span asp-validation-for="SortPerksByPopularity" class="text-danger"></span>
|
||||
<div class="form-group">
|
||||
<label asp-for="CustomCSSLink" class="form-label"></label>
|
||||
<a href="https://docs.btcpayserver.org/Theme/#2-bootstrap-themes" target="_blank" rel="noreferrer noopener">
|
||||
<span class="fa fa-question-circle-o text-secondary" title="More information..."></span>
|
||||
</a>
|
||||
<input asp-for="CustomCSSLink" class="form-control" />
|
||||
<span asp-validation-for="CustomCSSLink" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-check mb-3">
|
||||
<input asp-for="DisplayPerksRanking" type="checkbox" class="form-check-input" />
|
||||
<label asp-for="DisplayPerksRanking" class="form-check-label"></label>
|
||||
<span asp-validation-for="DisplayPerksRanking" class="text-danger"></span>
|
||||
<div class="form-group">
|
||||
<label asp-for="MainImageUrl" class="form-label"></label>
|
||||
<input asp-for="MainImageUrl" class="form-control" />
|
||||
<span asp-validation-for="MainImageUrl" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-check mb-3">
|
||||
<input asp-for="EnforceTargetAmount" type="checkbox" class="form-check-input" />
|
||||
<label asp-for="EnforceTargetAmount" class="form-check-label"></label>
|
||||
<span asp-validation-for="EnforceTargetAmount" class="text-danger"></span>
|
||||
<div class="form-group">
|
||||
<label asp-for="EmbeddedCSS" class="form-label"></label>
|
||||
<textarea asp-for="EmbeddedCSS" rows="10" cols="40" class="form-control"></textarea>
|
||||
<span asp-validation-for="EmbeddedCSS" class="text-danger"></span>
|
||||
</div>
|
||||
<h4 class="mt-5 mb-4">Crowdfund Behavior</h4>
|
||||
<div class="form-group">
|
||||
<label asp-for="NotificationUrl" class="form-label"></label>
|
||||
<input asp-for="NotificationUrl" class="form-control" />
|
||||
<span asp-validation-for="NotificationUrl" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input asp-for="UseAllStoreInvoices" type="checkbox" class="form-check-input" />
|
||||
<label asp-for="UseAllStoreInvoices" class="form-check-label"></label>
|
||||
<span asp-validation-for="UseAllStoreInvoices" class="text-danger"></span>
|
||||
</div>
|
||||
<h4 class="mt-5 mb-4">Sound</h4>
|
||||
<div class="form-group mb-3">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<input asp-for="SoundsEnabled" type="checkbox" class="btcpay-toggle me-2" data-bs-toggle="collapse" data-bs-target="#SoundsEnabledSettings" aria-expanded="@Model.SoundsEnabled" aria-controls="SoundsEnabledSettings"/>
|
||||
<label asp-for="SoundsEnabled" class="form-label mb-0"></label>
|
||||
</div>
|
||||
<span asp-validation-for="SoundsEnabled" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="collapse @(Model.SoundsEnabled ? "show" : "")" id="SoundsEnabledSettings">
|
||||
<div class="form-group mb-0 pb-3">
|
||||
<label asp-for="Sounds" class="form-label"></label>
|
||||
<textarea asp-for="Sounds" class="form-control"></textarea>
|
||||
<span asp-validation-for="Sounds" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
<h4 class="mt-5 mb-4">Animation</h4>
|
||||
<div class="form-group mb-3">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<input asp-for="AnimationsEnabled" type="checkbox" class="btcpay-toggle me-2" data-bs-toggle="collapse" data-bs-target="#AnimationsEnabledSettings" aria-expanded="@Model.AnimationsEnabled" aria-controls="AnimationsEnabledSettings"/>
|
||||
<label asp-for="AnimationsEnabled" class="form-label mb-0"></label>
|
||||
</div>
|
||||
<span asp-validation-for="AnimationsEnabled" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="collapse @(Model.AnimationsEnabled ? "show" : "")" id="AnimationsEnabledSettings">
|
||||
<div class="form-group mb-0 pb-3">
|
||||
<label asp-for="AnimationColors" class="form-label"></label>
|
||||
<textarea asp-for="AnimationColors" class="form-control"></textarea>
|
||||
<span asp-validation-for="AnimationColors" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
<h4 class="mt-5 mb-4">Discussion</h4>
|
||||
<div class="form-group mb-3">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<input asp-for="DisqusEnabled" type="checkbox" class="btcpay-toggle me-2" data-bs-toggle="collapse" data-bs-target="#DisqusEnabledSettings" aria-expanded="@Model.DisqusEnabled" aria-controls="DisqusEnabledSettings"/>
|
||||
<label asp-for="DisqusEnabled" class="form-label mb-0"></label>
|
||||
</div>
|
||||
<span asp-validation-for="DisqusEnabled" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="collapse @(Model.DisqusEnabled ? "show" : "")" id="DisqusEnabledSettings">
|
||||
<div class="form-group mb-0 pb-3">
|
||||
<label asp-for="DisqusShortname" class="form-label"></label>
|
||||
<input asp-for="DisqusShortname" class="form-control" />
|
||||
<span asp-validation-for="DisqusShortname" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h4 class="mt-5 mb-2">Additional Options</h4>
|
||||
<div class="form-group">
|
||||
<div class="accordion" id="accordion-dev-info">
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header" id="accordion-dev-info-appearance-header">
|
||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#accordion-dev-info-appearance" aria-expanded="false" aria-controls="accordion-dev-info-appearance">
|
||||
Custom CSS
|
||||
<vc:icon symbol="caret-down" />
|
||||
</button>
|
||||
</h2>
|
||||
<div id="accordion-dev-info-appearance" class="accordion-collapse collapse" aria-labelledby="accordion-dev-info-redirect-header">
|
||||
<div class="accordion-body">
|
||||
<div class="form-group">
|
||||
<label asp-for="CustomCSSLink" class="form-label"></label>
|
||||
<a href="https://docs.btcpayserver.org/Theme/#2-bootstrap-themes" target="_blank" rel="noreferrer noopener">
|
||||
<span class="fa fa-question-circle-o text-secondary" title="More information..."></span>
|
||||
</a>
|
||||
<input asp-for="CustomCSSLink" class="form-control" />
|
||||
<span asp-validation-for="CustomCSSLink" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="MainImageUrl" class="form-label"></label>
|
||||
<input asp-for="MainImageUrl" class="form-control" />
|
||||
<span asp-validation-for="MainImageUrl" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group mb-4">
|
||||
<label asp-for="EmbeddedCSS" class="form-label"></label>
|
||||
<textarea asp-for="EmbeddedCSS" rows="10" cols="40" class="form-control"></textarea>
|
||||
<span asp-validation-for="EmbeddedCSS" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input asp-for="Enabled" type="checkbox" class="form-check-input" />
|
||||
<label asp-for="Enabled" class="form-check-label"></label>
|
||||
<span asp-validation-for="Enabled" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input asp-for="SortPerksByPopularity" type="checkbox" class="form-check-input" />
|
||||
<label asp-for="SortPerksByPopularity" class="form-check-label"></label>
|
||||
<span asp-validation-for="SortPerksByPopularity" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input asp-for="DisplayPerksRanking" type="checkbox" class="form-check-input" />
|
||||
<label asp-for="DisplayPerksRanking" class="form-check-label"></label>
|
||||
<span asp-validation-for="DisplayPerksRanking" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input asp-for="EnforceTargetAmount" type="checkbox" class="form-check-input" />
|
||||
<label asp-for="EnforceTargetAmount" class="form-check-label"></label>
|
||||
<span asp-validation-for="EnforceTargetAmount" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input asp-for="UseAllStoreInvoices" type="checkbox" class="form-check-input" />
|
||||
<label asp-for="UseAllStoreInvoices" class="form-check-label"></label>
|
||||
<span asp-validation-for="UseAllStoreInvoices" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input asp-for="SoundsEnabled" type="checkbox" class="form-check-input" />
|
||||
<label asp-for="SoundsEnabled" class="form-check-label"></label>
|
||||
<span asp-validation-for="SoundsEnabled" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-9">
|
||||
<div class="form-group">
|
||||
<label asp-for="Sounds" class="form-label"></label>
|
||||
<textarea asp-for="Sounds" class="form-control"></textarea>
|
||||
<span asp-validation-for="Sounds" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="form-check">
|
||||
<input asp-for="AnimationsEnabled" type="checkbox" class="form-check-input" />
|
||||
<label asp-for="AnimationsEnabled" class="form-check-label"></label>
|
||||
<span asp-validation-for="AnimationsEnabled" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="AnimationColors" class="form-label"></label>
|
||||
<textarea asp-for="AnimationColors" class="form-control"></textarea>
|
||||
<span asp-validation-for="AnimationColors" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="form-check">
|
||||
<input asp-for="DisqusEnabled" type="checkbox" class="form-check-input" />
|
||||
<label asp-for="DisqusEnabled" class="form-check-label"></label>
|
||||
<span asp-validation-for="DisqusEnabled" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="DisqusShortname" class="form-label"></label>
|
||||
<input asp-for="DisqusShortname" class="form-control" />
|
||||
<span asp-validation-for="DisqusShortname" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-primary" id="SaveSettings">Save Settings</button>
|
||||
<div class="btn-group ms-2">
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-outline-primary" asp-action="ListInvoices" asp-controller="Invoice" asp-route-searchterm="@Model.SearchTerm">Invoices</a>
|
||||
<a class="btn btn-outline-primary" asp-action="ListInvoices" asp-controller="Invoice" asp-route-searchterm="@Model.SearchTerm"
|
||||
target="viewinvoices_@Model.AppId"><span class="fa fa-external-link"></span></a>
|
||||
</div>
|
||||
@if (Model.ModelWithMinimumData)
|
||||
{
|
||||
<div class="btn-group ms-2">
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-outline-primary" asp-action="ViewCrowdfund" asp-controller="AppsPublic" asp-route-appId="@Model.AppId" id="ViewApp">View App</a>
|
||||
<a class="btn btn-outline-primary" asp-action="ViewCrowdfund" asp-controller="AppsPublic" asp-route-appId="@Model.AppId"
|
||||
target="viewapp_@Model.AppId"><span class="fa fa-external-link"></span></a>
|
||||
</div>
|
||||
}
|
||||
<div class="btn-group ms-2">
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-outline-primary" asp-action="ListApps">Back to the app list</a>
|
||||
<a class="btn btn-outline-primary" asp-action="ListApps" target="viewapp_@Model.AppId"><span class="fa fa-external-link"></span></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
@ -1,3 +1,2 @@
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@using BTCPayServer.Views.Apps
|
||||
@using BTCPayServer.Views.Apps
|
||||
@using BTCPayServer.Models.AppViewModels
|
||||
|
@ -1,5 +1,4 @@
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@using BTCPayServer.Views
|
||||
@using BTCPayServer.Views
|
||||
@using BTCPayServer.Views.Apps
|
||||
@{
|
||||
ViewBag.CategoryTitle = "Apps";
|
||||
|
@ -113,8 +113,10 @@
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-primary text-white border-0">
|
||||
<h5 class="modal-title">Confirmation</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" ref="close">
|
||||
<vc:icon symbol="close" />
|
||||
<button type="button" class="close text-white" data-bs-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">
|
||||
<i class="fa fa-times fa-fw"></i>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body p-0">
|
||||
@ -256,7 +258,7 @@
|
||||
</div>
|
||||
|
||||
<!-- Sidebar -->
|
||||
<nav id="sidebar">
|
||||
<nav id="sidebar" class="bg-dark text-white">
|
||||
<div class="bg-primary p-3 clearfix">
|
||||
<h3 class="text-white m-0 pull-left">Cart</h3>
|
||||
<a class="js-cart btn btn-sm bg-white text-black pull-right ms-5" href="#">
|
||||
|
@ -1,5 +1,5 @@
|
||||
@using BTCPayServer.Views.Stores
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@using Microsoft.AspNetCore.Mvc.Rendering
|
||||
@using BTCPayServer.Views.Stores
|
||||
@model UpdateCoinSwitchSettingsViewModel
|
||||
@{
|
||||
Layout = "../Shared/_NavLayout.cshtml";
|
||||
|
@ -1,5 +1,4 @@
|
||||
@using BTCPayServer.Views.Stores
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@model BTCPayServer.Services.Altcoins.Ethereum.UI.EditEthereumPaymentMethodViewModel
|
||||
|
||||
@{
|
||||
|
@ -1,6 +1,5 @@
|
||||
|
||||
@using BTCPayServer.Views.Stores
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@model BTCPayServer.Services.Altcoins.Ethereum.UI.ViewEthereumStoreOptionsViewModel
|
||||
@inject SignInManager<ApplicationUser> SignInManager;
|
||||
@inject BTCPayNetworkProvider BTCPayNetworkProvider;
|
||||
|
@ -1,2 +1 @@
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@using BTCPayServer.Views.Manage
|
||||
@using BTCPayServer.Views.Manage
|
||||
|
@ -95,10 +95,10 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="single-item-order__right">
|
||||
<div class="single-item-order__right__btc-price" v-if="srvModel.status === 'paid' && !srvModel.isUnsetTopUp">
|
||||
<div class="single-item-order__right__btc-price" v-if="srvModel.status === 'paid'">
|
||||
<span>{{ srvModel.btcPaid }} {{ srvModel.cryptoCode }}</span>
|
||||
</div>
|
||||
<div class="single-item-order__right__btc-price" v-if="srvModel.status !== 'paid' && !srvModel.isUnsetTopUp">
|
||||
<div class="single-item-order__right__btc-price" v-else>
|
||||
<span>{{ srvModel.btcDue }} {{ srvModel.cryptoCode }}</span>
|
||||
</div>
|
||||
<div class="single-item-order__right__ex-rate" v-if="srvModel.orderAmountFiat && srvModel.cryptoCode">
|
||||
@ -106,10 +106,10 @@
|
||||
<span v-else>1 {{ srvModel.cryptoCodeSrv }} = {{ srvModel.rate }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<span class="fa fa-angle-double-down" v-if="!srvModel.isUnsetTopUp"></span>
|
||||
<span class="fa fa-angle-double-up" v-if="!srvModel.isUnsetTopUp"></span>
|
||||
<span class="fa fa-angle-double-down"></span>
|
||||
<span class="fa fa-angle-double-up"></span>
|
||||
</div>
|
||||
<line-items v-if="!srvModel.isUnsetTopUp">
|
||||
<line-items>
|
||||
<div class="extraPayment" v-if="srvModel.status === 'new' && srvModel.txCount > 1">
|
||||
{{$t("NotPaid_ExtraTransaction")}}
|
||||
</div>
|
||||
|
@ -1,4 +1,4 @@
|
||||
@model BTCPayServer.Models.InvoicingModels.CreateInvoiceModel
|
||||
@model BTCPayServer.Models.InvoicingModels.CreateInvoiceModel
|
||||
@{
|
||||
ViewData.SetActivePageAndTitle(InvoiceNavPages.Create, "Create an invoice");
|
||||
}
|
||||
@ -35,8 +35,8 @@
|
||||
<form asp-action="CreateInvoice" method="post" id="create-invoice-form">
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Amount" class="form-label"></label>
|
||||
<input asp-for="Amount" class="form-control" />
|
||||
<label asp-for="Amount" class="form-label" data-required></label>
|
||||
<input asp-for="Amount" class="form-control" required />
|
||||
<span asp-validation-for="Amount" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
@ -1,3 +1,2 @@
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@using BTCPayServer.Services.Invoices
|
||||
@using BTCPayServer.Services.Invoices
|
||||
@using BTCPayServer.Views.Invoice
|
||||
|
@ -1,4 +1,3 @@
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@using BTCPayServer.Views
|
||||
@using BTCPayServer.Views.Invoice
|
||||
@{
|
||||
|
@ -1,2 +1 @@
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@using BTCPayServer.Views.Manage
|
||||
@using BTCPayServer.Views.Manage
|
||||
|
@ -1,5 +1,4 @@
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@using BTCPayServer.Views
|
||||
@using BTCPayServer.Views
|
||||
@using BTCPayServer.Views.Manage
|
||||
@{
|
||||
Layout = "../Shared/_NavLayout.cshtml";
|
||||
|
@ -1,5 +1,5 @@
|
||||
@using BTCPayServer.Controllers
|
||||
@using BTCPayServer.Views.Stores
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@model BTCPayServer.Services.Altcoins.Monero.UI.MoneroLikeStoreController.MoneroLikePaymentMethodViewModel
|
||||
|
||||
@{
|
||||
|
@ -1,5 +1,4 @@
|
||||
@using BTCPayServer.Views.Stores
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@model BTCPayServer.Services.Altcoins.Monero.UI.MoneroLikeStoreController.MoneroLikePaymentMethodListViewModel
|
||||
|
||||
@{
|
||||
|
@ -1 +1 @@
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@using BTCPayServer.Views
|
||||
@using BTCPayServer.Views
|
||||
@using BTCPayServer.Views.Notifications
|
||||
|
||||
@{
|
||||
|
@ -9,27 +9,27 @@
|
||||
ViewData["Title"] = Model.Title;
|
||||
Layout = null;
|
||||
var theme = await _settingsRepository.GetTheme();
|
||||
string StatusClass(InvoiceState state)
|
||||
string StatusTextClass(InvoiceState state)
|
||||
{
|
||||
switch (state.Status.ToModernStatus())
|
||||
{
|
||||
case InvoiceStatus.Settled:
|
||||
case InvoiceStatus.Processing:
|
||||
return "success";
|
||||
return "text-success";
|
||||
case InvoiceStatus.Expired:
|
||||
switch (state.ExceptionStatus)
|
||||
{
|
||||
case InvoiceExceptionStatus.PaidLate:
|
||||
case InvoiceExceptionStatus.PaidPartial:
|
||||
case InvoiceExceptionStatus.PaidOver:
|
||||
return "warning";
|
||||
return "text-warning";
|
||||
default:
|
||||
return "danger";
|
||||
return "text-danger";
|
||||
}
|
||||
case InvoiceStatus.Invalid:
|
||||
return "danger";
|
||||
return "text-danger";
|
||||
default:
|
||||
return "warning";
|
||||
return "text-warning";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -56,11 +56,6 @@
|
||||
@*We need to make sure btcpay.js is not bundled, else it will not work if there is a RootPath*@
|
||||
<script src="~/modal/btcpay.js" asp-append-version="true"></script>
|
||||
@Safe.Raw(Model.EmbeddedCSS)
|
||||
<style>
|
||||
.invoice { margin-top: var(--btcpay-space-s); }
|
||||
.invoice + .invoice { margin-top: var(--btcpay-space-m); }
|
||||
.invoice .badge { font-size: var(--btcpay-font-size-s); }
|
||||
</style>
|
||||
<noscript>
|
||||
<style>
|
||||
.hide-when-js, [v-cloak] { display: block !important; }
|
||||
@ -246,32 +241,30 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
@foreach (var invoice in Model.Invoices)
|
||||
{
|
||||
<table class="invoice table">
|
||||
<thead>
|
||||
<tr class="table-borderless">
|
||||
<th class="fw-normal text-secondary w-350px" scope="col">Invoice Id</th>
|
||||
<th class="fw-normal text-secondary w-175px">Expiry</th>
|
||||
<th class="fw-normal text-secondary text-end w-125px">Amount</th>
|
||||
<th class="fw-normal text-secondary text-end w-125px"></th>
|
||||
<th class="fw-normal text-secondary text-end">Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="table-borderless table-light">
|
||||
<table class="table my-0">
|
||||
<thead>
|
||||
<tr class="table-borderless">
|
||||
<th class="fw-normal text-secondary" scope="col">Invoice Id</th>
|
||||
<th class="fw-normal text-secondary w-175px">Expiry</th>
|
||||
<th class="fw-normal text-secondary text-end w-125px">Amount</th>
|
||||
<th class="fw-normal text-secondary text-end w-125px"></th>
|
||||
<th class="fw-normal text-secondary text-end">Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var invoice in Model.Invoices)
|
||||
{
|
||||
<tr>
|
||||
<td>@invoice.Id</td>
|
||||
<td>@invoice.ExpiryDate.ToString("g")</td>
|
||||
<td class="text-end">@invoice.AmountFormatted</td>
|
||||
<td class="text-end"></td>
|
||||
<td class="text-end text-print-default">
|
||||
<span class="badge bg-@StatusClass(invoice.State)">@invoice.StateFormatted</span>
|
||||
</td>
|
||||
<td class="text-end text-print-default @StatusTextClass(invoice.State)">@invoice.StateFormatted</td>
|
||||
</tr>
|
||||
@if (invoice.Payments != null && invoice.Payments.Any())
|
||||
if (invoice.Payments != null && invoice.Payments.Any())
|
||||
{
|
||||
<tr class="table-borderless table-light">
|
||||
<th class="fw-normal text-secondary">Destination</th>
|
||||
<th class="fw-normal text-secondary ps-3">Transaction Id</th>
|
||||
<th class="fw-normal text-secondary">Received</th>
|
||||
<th class="fw-normal text-secondary text-end">Paid</th>
|
||||
<th class="fw-normal text-secondary text-end">Rate</th>
|
||||
@ -280,30 +273,26 @@
|
||||
@foreach (var payment in invoice.Payments)
|
||||
{
|
||||
<tr class="table-borderless table-light">
|
||||
<td class="text-break"><code>@payment.Destination</code></td>
|
||||
<td class="ps-3 text-break">
|
||||
@if (!string.IsNullOrEmpty(payment.Link))
|
||||
{
|
||||
<a href="@payment.Link" class="text-print-default" rel="noreferrer noopener" target="_blank">@payment.Id</a>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span>@payment.Id</span>
|
||||
}
|
||||
</td>
|
||||
<td>@payment.ReceivedDate.ToString("g")</td>
|
||||
<td class="text-end">@payment.PaidFormatted</td>
|
||||
<td class="text-end">@payment.RateFormatted</td>
|
||||
<td class="text-end text-nowrap">@payment.Amount @payment.PaymentMethod</td>
|
||||
</tr>
|
||||
<tr class="table-borderless table-light">
|
||||
<td class="fw-normal" colspan="5">
|
||||
<span class="text-secondary">Transaction Id:</span>
|
||||
@if (!string.IsNullOrEmpty(payment.Link))
|
||||
{
|
||||
<a href="@payment.Link" class="text-print-default text-break" rel="noreferrer noopener" target="_blank">@payment.Id</a>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="text-break">@payment.Id</span>
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
</noscript>
|
||||
|
||||
@ -311,10 +300,10 @@
|
||||
<p class="text-muted">No payments made yet.</p>
|
||||
</template>
|
||||
<template v-else>
|
||||
<table v-for="invoice of srvModel.invoices" :key="invoice.id" class="invoice table">
|
||||
<table class="table my-0">
|
||||
<thead>
|
||||
<tr class="table-borderless">
|
||||
<th class="fw-normal text-secondary w-350px" scope="col">Invoice Id</th>
|
||||
<th class="fw-normal text-secondary" scope="col">Invoice Id</th>
|
||||
<th class="fw-normal text-secondary w-175px">Expiry</th>
|
||||
<th class="fw-normal text-secondary text-end w-125px">Amount</th>
|
||||
<th class="fw-normal text-secondary text-end w-125px"></th>
|
||||
@ -322,38 +311,32 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="table-borderless table-light">
|
||||
<td>{{invoice.id}}</td>
|
||||
<td v-text="formatDate(invoice.expiryDate)"></td>
|
||||
<td class="text-end">{{invoice.amountFormatted}}</td>
|
||||
<td class="text-end"></td>
|
||||
<td class="text-end text-print-default">
|
||||
<span class="badge" :class="`bg-${statusClass(invoice.stateFormatted)}`">{{invoice.stateFormatted}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
<template v-if="invoice.payments && invoice.payments.length > 0">
|
||||
<tr class="table-borderless table-light">
|
||||
<th class="fw-normal text-secondary">Destination</th>
|
||||
<th class="fw-normal text-secondary">Received</th>
|
||||
<th class="fw-normal text-secondary text-end">Paid</th>
|
||||
<th class="fw-normal text-secondary text-end">Rate</th>
|
||||
<th class="fw-normal text-secondary text-end">Payment</th>
|
||||
<template v-for="invoice of srvModel.invoices" :key="invoice.id">
|
||||
<tr>
|
||||
<td>{{invoice.id}}</td>
|
||||
<td v-text="formatDate(invoice.expiryDate)"></td>
|
||||
<td class="text-end">{{invoice.amountFormatted}}</td>
|
||||
<td class="text-end"></td>
|
||||
<td class="text-end text-print-default" :class="statusTextClass(invoice.stateFormatted)">{{invoice.stateFormatted}}</td>
|
||||
</tr>
|
||||
<template v-for="payment of invoice.payments">
|
||||
<template v-if="invoice.payments && invoice.payments.length > 0">
|
||||
<tr class="table-borderless table-light">
|
||||
<td class="text-break"><code>{{payment.destination}}</code></td>
|
||||
<th class="fw-normal text-secondary ps-3">Transaction Id</th>
|
||||
<th class="fw-normal text-secondary">Received</th>
|
||||
<th class="fw-normal text-secondary text-end">Paid</th>
|
||||
<th class="fw-normal text-secondary text-end">Rate</th>
|
||||
<th class="fw-normal text-secondary text-end">Payment</th>
|
||||
</tr>
|
||||
<tr v-for="payment of invoice.payments" class="table-borderless table-light">
|
||||
<td class="ps-3 text-break">
|
||||
<a v-if="payment.link" :href="payment.link" class="text-print-default" target="_blank" rel="noreferrer noopener">{{payment.id}}</a>
|
||||
<span v-else>{{payment.id}}</span>
|
||||
</td>
|
||||
<td v-text="formatDate(payment.receivedDate)"></td>
|
||||
<td class="text-end">{{payment.paidFormatted}}</td>
|
||||
<td class="text-end">{{payment.rateFormatted}}</td>
|
||||
<td class="text-end text-nowrap">{{payment.amount.noExponents()}} {{payment.paymentMethod}}</td>
|
||||
</tr>
|
||||
<tr class="table-borderless table-light">
|
||||
<td class="fw-normal" colspan="5">
|
||||
<span class="text-secondary">Transaction Id:</span>
|
||||
<a v-if="payment.link" :href="payment.link" class="text-print-default" target="_blank" rel="noreferrer noopener">{{payment.id}}</a>
|
||||
<span v-else>{{payment.id}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
</template>
|
||||
</tbody>
|
||||
|
@ -1,2 +1 @@
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@using BTCPayServer.Views.PaymentRequest
|
||||
@using BTCPayServer.Views.PaymentRequest
|
||||
|
@ -1,4 +1,3 @@
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@using BTCPayServer.Views
|
||||
@using BTCPayServer.Views.PaymentRequest
|
||||
@{
|
||||
|
@ -45,7 +45,7 @@ else
|
||||
<td>@file.Timestamp.ToBrowserDate()</td>
|
||||
<td>@file.ApplicationUser.UserName</td>
|
||||
<td class="text-end">
|
||||
<a href="@Url.Action("Files", "Server", new { fileIds = new string[] { file.Id} })">Get Link</a>
|
||||
<a asp-action="Files" asp-route-fileId="@file.Id">Get Link</a>
|
||||
- <a asp-action="CreateTemporaryFileUrl" asp-route-fileId="@file.Id">Get Temp Link</a>
|
||||
- <a asp-action="DeleteFile" asp-route-fileId="@file.Id">Remove</a>
|
||||
</td>
|
||||
@ -63,38 +63,31 @@ else
|
||||
}
|
||||
|
||||
|
||||
@if(Model.DirectUrlByFiles!=null && Model.DirectUrlByFiles.Count > 0)
|
||||
@if (!string.IsNullOrEmpty(Model.SelectedFileId))
|
||||
{
|
||||
foreach (KeyValuePair<string, string> fileUrlPair in Model.DirectUrlByFiles)
|
||||
{
|
||||
var fileId = fileUrlPair.Key;
|
||||
var fileUrl = fileUrlPair.Value;
|
||||
var file = Model.Files.Single(storedFile => storedFile.Id.Equals(fileId, StringComparison.InvariantCultureIgnoreCase));
|
||||
|
||||
|
||||
<div class="card mb-2">
|
||||
<div class="card-text">
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item">
|
||||
@file.FileName
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<strong>URL:</strong>
|
||||
<a asp-action="GetFile" asp-controller="Storage" asp-route-fileId="@fileId" target="_blank">
|
||||
@Url.Action("GetFile", "Storage", new
|
||||
{
|
||||
fileId = fileId
|
||||
}, Context.Request.Scheme, Context.Request.Host.ToString())
|
||||
</a>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<strong>Direct URL:</strong>
|
||||
<a href="@fileUrl" target="_blank" rel="noreferrer noopener">@fileUrl</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
var file = Model.Files.Single(storedFile => storedFile.Id.Equals(Model.SelectedFileId, StringComparison.InvariantCultureIgnoreCase));
|
||||
<div class="card mb-2">
|
||||
<div class="card-text">
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item">
|
||||
@file.FileName
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<strong>URL:</strong>
|
||||
<a asp-action="GetFile" asp-controller="Storage" asp-route-fileId="@Model.SelectedFileId" target="_blank">
|
||||
@Url.Action("GetFile", "Storage", new
|
||||
{
|
||||
fileId = Model.SelectedFileId
|
||||
}, Context.Request.Scheme, Context.Request.Host.ToString())
|
||||
</a>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<strong>Direct URL:</strong>
|
||||
<a href="@Model.DirectFileUrl" target="_blank" rel="noreferrer noopener">@Model.DirectFileUrl</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (Model.StorageConfigured)
|
||||
|
@ -15,6 +15,10 @@
|
||||
<div>
|
||||
@if (Model.Uri == null) // if GRPC
|
||||
{
|
||||
<a href="https://www.pebble.indiesquare.me/" target="_blank" class="d-inline-block me-3 text-center" rel="noreferrer noopener">
|
||||
<img src="~/img/pebblewallet.jpg" width="100" height="100" asp-append-version="true" alt="Pebble" />
|
||||
<div class="mt-2">Pebble</div>
|
||||
</a>
|
||||
<a href="https://zaphq.io/" target="_blank" class="d-inline-block me-3 text-center" rel="noreferrer noopener">
|
||||
<img src="~/img/zapwallet.jpg" width="100" height="100" asp-append-version="true" alt="Zap" />
|
||||
<div class="mt-2">Zap</div>
|
||||
|
@ -1,3 +1,2 @@
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@using BTCPayServer.Views.Server
|
||||
@using BTCPayServer.Views.Server
|
||||
@using BTCPayServer.Models.ServerViewModels
|
||||
|
@ -1,5 +1,4 @@
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@using BTCPayServer.Views
|
||||
@using BTCPayServer.Views
|
||||
@using BTCPayServer.Views.Server
|
||||
@{
|
||||
Layout = "../Shared/_NavLayout.cshtml";
|
||||
|
@ -19,14 +19,14 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="bp-view payment manual-flow" id="copy" v-bind:class="{ 'active': currentTab == 'copy'}">
|
||||
<div class="manual__step-two__instructions" v-if="!srvModel.isUnsetTopUp">
|
||||
<div class="manual__step-two__instructions">
|
||||
<span v-html="$t('CompletePay_Body', srvModel)"></span>
|
||||
</div>
|
||||
<div class="copyLabelPopup">
|
||||
<span>{{$t("Copied")}}</span>
|
||||
</div>
|
||||
<nav class="copyBox">
|
||||
<div class="copySectionBox bottomBorder" v-if="!srvModel.isUnsetTopUp">
|
||||
<div class="copySectionBox bottomBorder">
|
||||
<label>{{$t("Amount")}}</label>
|
||||
<div class="copyAmountText copy-cursor _copySpan">
|
||||
<span>{{srvModel.btcDue}}</span> {{ srvModel.cryptoCode }}
|
||||
|
@ -1,6 +1,6 @@
|
||||
@using BTCPayServer.Services.Altcoins.Ethereum.UI
|
||||
@using BTCPayServer.Views.Server
|
||||
@using System.Net.Http
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@model BTCPayServer.Services.Altcoins.Ethereum.Configuration.EthereumLikeConfiguration
|
||||
@inject BTCPayNetworkProvider BTCPayNetworkProvider;
|
||||
@inject IHttpClientFactory HttpClientFactory;
|
||||
|
@ -14,12 +14,6 @@
|
||||
<span class="d-block mt-3">Square Crypto</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="p-3 text-center" style="flex-basis:105px;">
|
||||
<a href="https://www.bailliegifford.com" target="_blank" class="text-muted small" rel="noreferrer noopener">
|
||||
<img src="~/img/bailliegifford.svg" alt="Sponsor Baillie Gifford" height="50" width="50" asp-append-version="true"/>
|
||||
<span class="d-block mt-3">Baillie Gifford</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="p-3 text-center" style="flex-basis:105px;">
|
||||
<a href="https://www.pnxbet.com" target="_blank" class="text-muted small" rel="noreferrer noopener">
|
||||
<img src="~/img/pnxbet.png" alt="Sponsor PNXBET" height="50" width="50" asp-append-version="true"/>
|
||||
|
@ -6,7 +6,6 @@
|
||||
@using BTCPayServer.Views.PaymentRequest
|
||||
@using BTCPayServer.Views.Wallets
|
||||
@using BTCPayServer.Abstractions.Contracts
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@inject SignInManager<ApplicationUser> SignInManager
|
||||
@inject UserManager<ApplicationUser> UserManager
|
||||
@inject RoleManager<IdentityRole> RoleManager
|
||||
|
@ -1,12 +1,13 @@
|
||||
@using BTCPayServer.Views.Stores
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@model BTCPayServer.Plugins.Shopify.Models.ShopifySettings
|
||||
@{
|
||||
|
||||
Layout = "../Shared/_NavLayout.cshtml";
|
||||
|
||||
ViewData["NavPartialName"] = "../Stores/_Nav";
|
||||
ViewData.SetActivePageAndTitle(StoreNavPages.Integrations, "Integrations");
|
||||
|
||||
|
||||
var shopifyCredsSet = Model?.IntegratedAt.HasValue is true;
|
||||
var shopifyUrl = Model?.ShopifyUrl;
|
||||
}
|
||||
|
@ -50,9 +50,6 @@
|
||||
<input asp-for="Config" type="hidden"/>
|
||||
<input asp-for="Confirmation" type="hidden"/>
|
||||
<input asp-for="DerivationScheme" type="hidden"/>
|
||||
<input asp-for="AccountKey" type="hidden" />
|
||||
<input asp-for="RootFingerprint" type="hidden" />
|
||||
<input asp-for="KeyPath" type="hidden" />
|
||||
|
||||
<div class="form-group">
|
||||
<table class="table table-sm table-responsive-md">
|
||||
|
@ -28,7 +28,7 @@
|
||||
<div class="content d-flex flex-column flex-lg-row align-items-lg-center justify-content-lg-between me-2">
|
||||
<div>
|
||||
<h4>Connect hardware wallet</h4>
|
||||
<p class="mb-0 text-secondary">Import your public keys using our Vault application</p>
|
||||
<p class="mb-0 text-secondary">Import your keys using our Vault application</p>
|
||||
</div>
|
||||
<small class="d-block text-primary mt-2 mt-lg-0">Recommended</small>
|
||||
</div>
|
||||
@ -41,7 +41,7 @@
|
||||
</div>
|
||||
<div class="content d-flex flex-column flex-lg-row align-items-lg-center justify-content-lg-between me-2">
|
||||
<div>
|
||||
<h4>Connect hardware wallet</h4>
|
||||
<h4>Connect hardware wallet</h4>
|
||||
<p class="mb-0">Please enable JavaScript for this option to be available</p>
|
||||
</div>
|
||||
<small class="d-block text-primary mt-2 mt-lg-0">Recommended</small>
|
||||
|
@ -58,9 +58,9 @@
|
||||
<div class="row">
|
||||
<div class="form-group col-md-8">
|
||||
<label class="form-label">Price</label>
|
||||
<input name="price" type="text" class="form-control" placeholder="(optional)"
|
||||
<input name="price" type="text" class="form-control"
|
||||
v-model="srvModel.price" v-on:change="inputChanges"
|
||||
v-validate="'decimal|min_value:0'" :class="{'is-invalid': errors.has('price') }">
|
||||
v-validate="'required|decimal|min_value:0'" :class="{'is-invalid': errors.has('price') }">
|
||||
<small class="text-danger">{{ errors.first('price') }}</small>
|
||||
</div>
|
||||
<div class="form-group col-md-4" v-if="!srvModel.appIdEndpoint">
|
||||
|
@ -1,3 +1,2 @@
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@using BTCPayServer.Views.Stores
|
||||
@using BTCPayServer.Views.Stores
|
||||
@using BTCPayServer.Models.StoreViewModels
|
||||
|
@ -1,5 +1,4 @@
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@using BTCPayServer.Views
|
||||
@using BTCPayServer.Views
|
||||
@using BTCPayServer.Views.Stores
|
||||
|
||||
@{
|
||||
|
@ -1,3 +1,2 @@
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@using BTCPayServer.Views.Stores
|
||||
@using BTCPayServer.Views.Stores
|
||||
@using BTCPayServer.Models.StoreViewModels
|
||||
|
@ -1,4 +1,3 @@
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@using BTCPayServer.Views
|
||||
@using BTCPayServer.Views.Stores
|
||||
|
||||
|
@ -3,7 +3,7 @@ using System.Globalization;
|
||||
using Microsoft.AspNetCore.Html;
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Extensions
|
||||
namespace BTCPayServer.Views
|
||||
{
|
||||
public static class ViewsRazor
|
||||
{
|
@ -1,4 +1,4 @@
|
||||
@addTagHelper *, BundlerMinifier.TagHelpers
|
||||
@addTagHelper *, BundlerMinifier.TagHelpers
|
||||
@using Microsoft.AspNetCore.Mvc.ModelBinding
|
||||
@model WalletSendModel
|
||||
@{
|
||||
@ -33,7 +33,6 @@
|
||||
<input type="hidden" asp-for="Fiat" />
|
||||
<input type="hidden" asp-for="Rate" />
|
||||
<input type="hidden" asp-for="CurrentBalance" />
|
||||
<input type="hidden" asp-for="ImmatureBalance" />
|
||||
<input type="hidden" asp-for="CryptoCode" />
|
||||
<input type="hidden" name="BIP21" id="BIP21" />
|
||||
|
||||
@ -64,64 +63,52 @@
|
||||
@if (Model.Outputs.Count == 1)
|
||||
{
|
||||
<div class="form-group">
|
||||
<div class="d-flex align-items-center justify-content-between">
|
||||
<label asp-for="Outputs[0].DestinationAddress" class="form-label"></label>
|
||||
<button type="submit" name="command" value="add-output" class="d-inline-block ms-2 btn text-secondary btn-link p-0 mb-2">Add another destination</button>
|
||||
</div>
|
||||
<input asp-for="Outputs[0].DestinationAddress" class="form-control font-monospace" autofocus autocomplete="off" />
|
||||
<label asp-for="Outputs[0].DestinationAddress" class="form-label"></label>
|
||||
<input asp-for="Outputs[0].DestinationAddress" class="form-control font-monospace" />
|
||||
<span asp-validation-for="Outputs[0].DestinationAddress" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Outputs[0].Amount" class="form-label"></label>
|
||||
<div class="input-group">
|
||||
<input asp-for="Outputs[0].Amount" type="number" step="any" min="0" asp-format="{0}" class="form-control output-amount hide-number-spin" />
|
||||
<input asp-for="Outputs[0].Amount" type="number" step="any" min="0" asp-format="{0}" class="form-control output-amount" />
|
||||
<div class="input-group-text fiat-value" style="display:none;">
|
||||
<span class="input-group-text p-0">=</span>
|
||||
<input type="number" class="input-group-text fiat-value-edit-input py-0 hide-number-spin" min="0" step="any" style="max-width:100px" />
|
||||
<input type="number" class="input-group-text fiat-value-edit-input py-0" min="0" step="any" style="max-width:100px" />
|
||||
<span class="input-group-text p-0">@Model.Fiat</span>
|
||||
</div>
|
||||
</div>
|
||||
<span asp-validation-for="Outputs[0].Amount" class="text-danger"></span>
|
||||
<p class="form-text text-secondary crypto-info">
|
||||
Your available balance is
|
||||
Your current balance is
|
||||
<button type="button" class="crypto-balance-link btn btn-link p-0 align-baseline">@Model.CurrentBalance</button> <span>@Model.CryptoCode</span>.
|
||||
@if (Model.ImmatureBalance > 0)
|
||||
{
|
||||
<span><br><span class="text-warning">⚠</span> @Model.ImmatureBalance @Model.CryptoCode are still immature and require additional confirmations.</span>
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="list-group list-group-flush mt-n3 mb-4">
|
||||
<div class="list-group-item">
|
||||
<h5 class="mb-0">Destinations</h5>
|
||||
</div>
|
||||
<div class="list-group mb-4">
|
||||
@for (var index = 0; index < Model.Outputs.Count; index++)
|
||||
{
|
||||
<div class="list-group-item transaction-output-form px-0 py-4">
|
||||
<div class="list-group-item transaction-output-form">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 col-lg-10">
|
||||
<div class="form-group">
|
||||
<label asp-for="Outputs[index].DestinationAddress" class="form-label"></label>
|
||||
<input asp-for="Outputs[index].DestinationAddress" class="form-control" autocomplete="off" />
|
||||
<input asp-for="Outputs[index].DestinationAddress" class="form-control" />
|
||||
<span asp-validation-for="Outputs[index].DestinationAddress" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Outputs[index].Amount" class="form-label"></label>
|
||||
<div class="input-group">
|
||||
<input asp-for="Outputs[index].Amount" type="number" min="0" step="any" asp-format="{0}" class="form-control output-amount hide-number-spin" />
|
||||
<div class="input-group-text fiat-value" style="display:none;">
|
||||
<span class="input-group-text p-0">=</span>
|
||||
<input type="number" class="input-group-text fiat-value-edit-input py-0 hide-number-spin" min="0" step="any" style="max-width:100px" />
|
||||
<span class="input-group-text p-0">@Model.Fiat</span>
|
||||
</div>
|
||||
<input asp-for="Outputs[index].Amount" type="number" step="any" asp-format="{0}" class="form-control output-amount" />
|
||||
<span class="input-group-text fiat-value" style="display:none;"></span>
|
||||
</div>
|
||||
<p class="form-text text-secondary crypto-info mb-2">
|
||||
Your available balance is
|
||||
Your current balance is
|
||||
<button type="button" class="crypto-balance-link btn btn-link p-0 align-baseline">@Model.CurrentBalance</button> <span>@Model.CryptoCode</span>.
|
||||
@if (Model.ImmatureBalance > 0)
|
||||
{
|
||||
<span><br>Note: @Model.ImmatureBalance @Model.CryptoCode are still immature and require additional confirmations.</span>
|
||||
}
|
||||
</p>
|
||||
<span asp-validation-for="Outputs[index].Amount" class="text-danger"></span>
|
||||
</div>
|
||||
@ -148,7 +135,7 @@
|
||||
}
|
||||
<div class="form-group my-4">
|
||||
<label asp-for="FeeSatoshiPerByte" class="form-label"></label>
|
||||
<input asp-for="FeeSatoshiPerByte" type="number" min="0" step="any" class="form-control" style="max-width:14ch;" />
|
||||
<input asp-for="FeeSatoshiPerByte" type="number" step="any" class="form-control" style="max-width:14ch;" />
|
||||
<span asp-validation-for="FeeSatoshiPerByte" class="text-danger"></span>
|
||||
<span id="FeeRate-Error" class="text-danger"></span>
|
||||
@if (Model.RecommendedSatoshiPerByte.Any())
|
||||
@ -236,6 +223,7 @@
|
||||
</div>
|
||||
<div class="form-group d-flex mt-2">
|
||||
<button type="submit" id="SignTransaction" name="command" value="@(Model.NBXSeedAvailable ? "nbx-seed" : "sign")" class="btn btn-primary">Sign transaction</button>
|
||||
<button type="submit" name="command" value="add-output" class="ms-2 btn btn-secondary">Add another destination</button>
|
||||
<button type="button" id="bip21parse" class="ms-2 btn btn-secondary" title="Paste BIP21/Address"><i class="fa fa-paste"></i></button>
|
||||
<button type="button" id="scanqrcode" class="ms-2 btn btn-secondary only-for-js" data-bs-toggle="modal" data-bs-target="#scanModal" title="Scan BIP21/Address with camera"><i class="fa fa-camera"></i></button>
|
||||
</div>
|
||||
|
@ -1,4 +1,3 @@
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@using BTCPayServer.Views.Wallets
|
||||
@using BTCPayServer.Views.Wallets
|
||||
@using BTCPayServer.Models.WalletViewModels
|
||||
@addTagHelper *, BundlerMinifier.TagHelpers
|
||||
|
@ -1,5 +1,4 @@
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@using BTCPayServer.Views
|
||||
@using BTCPayServer.Views
|
||||
@using BTCPayServer.Views.Wallets
|
||||
@{
|
||||
ViewBag.CategoryTitle = "Wallets";
|
||||
|
@ -192,6 +192,7 @@
|
||||
"wwwroot/vendor/vuejs/vue.min.js",
|
||||
"wwwroot/vendor/babel-polyfill/polyfill.min.js",
|
||||
"wwwroot/vendor/bc-ur/web-bundle.js",
|
||||
"wwwroot/vendor/ur-registry/urlib.min.js",
|
||||
"wwwroot/vendor/vue-qrcode-reader/VueQrcodeReader.umd.min.js",
|
||||
"wwwroot/js/wallet/**/*.js"
|
||||
],
|
||||
@ -212,6 +213,7 @@
|
||||
"wwwroot/vendor/vuejs/vue.min.js",
|
||||
"wwwroot/vendor/vue-qrcode/vue-qrcode.min.js",
|
||||
"wwwroot/vendor/bc-ur/web-bundle.js",
|
||||
"wwwroot/vendor/ur-registry/urlib.min.js",
|
||||
"wwwroot/vendor/vue-qrcode-reader/VueQrcodeReader.umd.min.js"
|
||||
],
|
||||
"minify": {
|
||||
|
@ -76,8 +76,7 @@
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
z-index: 999;
|
||||
color: var(--btcpay-white);
|
||||
background: var(--btcpay-bg-dark);
|
||||
background: #e1e6ea;
|
||||
transition: all 0.3s;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
@ -1,113 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.3.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="bdbb9e96-7dd2-4000-9304-0bf8a661aad9"
|
||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 121.9 121.9"
|
||||
style="enable-background:new 0 0 121.9 121.9;background:#FFF" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#222221;}
|
||||
.st1{fill:#272425;}
|
||||
</style>
|
||||
<polygon class="st0" points="93.4,49.9 93,51 90.7,51 90,52.5 92.2,52.5 91.8,53.6 89.6,53.6 88.6,56.1 86.5,56.1 88.9,49.9 "/>
|
||||
<path class="st0" d="M98.5,49.8c1.7,0,2.9,0.9,2.1,3.1c-0.7,2-2.6,3.3-4.7,3.3c-2.2,0-2.8-1.3-2.1-3.2
|
||||
C94.6,51.1,96.4,49.8,98.5,49.8 M96.3,55.2c0.4,0,1.1-0.2,1.8-2.2c0.7-1.8,0.6-2.2,0-2.2s-1.1,0.4-1.9,2.3
|
||||
C95.7,54.4,95.6,55.2,96.3,55.2"/>
|
||||
<path class="st0" d="M106.2,49.9c0.7-0.1,1.4,0,2,0.2c0.5,0.1,0.8,0.7,0.6,1.1c0,0.1,0,0.1-0.1,0.2c-0.4,0.8-1.2,1.4-2.1,1.6l0.9,3
|
||||
h-2.4l-0.5-2.5h-0.2l-1,2.5h-2.1l2.4-6.2H106.2z M105.6,50.9l-0.7,1.8h0.2c0.6,0.1,1.2-0.3,1.3-0.9c0.3-0.7,0.1-0.9-0.6-0.9H105.6z"
|
||||
/>
|
||||
<path class="st0" d="M113.7,49.9c0.9-0.1,1.9,0.1,2.7,0.6c0.7,0.7,0.4,1.8,0.2,2.3c-0.5,1.4-1.6,2.5-3,3c-0.8,0.2-1.6,0.3-2.4,0.3
|
||||
h-2l2.4-6.2L113.7,49.9z M113.3,50.9l-1.7,4.2h0.2c0.5,0,1.4,0.2,2.4-2.2c0.8-2,0.1-2-0.7-2L113.3,50.9z"/>
|
||||
<polygon class="st0" points="37.6,49.9 35.2,56.1 33,56.1 35.4,49.9 "/>
|
||||
<polygon class="st0" points="42.6,49.9 40.6,55 42.9,55 42.5,56.1 38,56.1 40.4,49.9 "/>
|
||||
<polygon class="st0" points="48.6,49.9 46.6,55 48.9,55 48.5,56.1 44,56.1 46.4,49.9 "/>
|
||||
<polygon class="st0" points="55.1,49.9 52.7,56.1 50.5,56.1 52.9,49.9 "/>
|
||||
<polygon class="st0" points="62.5,49.9 62.1,51 59.7,51 59.2,52.3 61.3,52.3 60.9,53.4 58.8,53.4 58.1,55 60.5,55 60.1,56.1
|
||||
55.5,56.1 57.9,49.9 "/>
|
||||
<path class="st0" d="M73.2,51.1c-0.3-0.1-0.7-0.2-1.1-0.2c-1.6,0-2.4,1.6-2.6,2.2c-0.3,0.8-0.6,1.7,0.1,2c0.2,0.1,0.4,0.1,0.7,0.1
|
||||
l0.6-1.5h-0.8l0.4-1h2.8l-1.2,2.9c-0.8,0.3-1.7,0.5-2.5,0.5c-2.3,0-3.2-1.3-2.5-3.1c0.9-2,2.9-3.3,5.1-3.2c0.6,0,1.2,0.1,1.8,0.3
|
||||
L73.2,51.1z"/>
|
||||
<polygon class="st0" points="79.3,49.9 76.9,56.1 74.7,56.1 77.1,49.9 "/>
|
||||
<polygon class="st0" points="86.7,49.9 86.3,51 83.9,51 83.3,52.5 85.5,52.5 85,53.6 82.9,53.6 81.9,56.1 79.7,56.1 82.2,49.9 "/>
|
||||
<path class="st0" d="M22.6,49.9c0.6,0,1.2,0.1,1.7,0.2c0.4,0.1,0.7,0.5,0.5,1c0,0.1,0,0.1-0.1,0.2c-0.4,0.8-1.2,1.4-2.2,1.5
|
||||
c0.4,0,0.7,0.2,1,0.3c0.4,0.3,0.5,0.8,0.3,1.2c-0.4,0.8-1.2,1.4-2.1,1.6c-0.7,0.2-1.4,0.2-2.2,0.2h-2.2l2.4-6.2H22.6z M21.2,52.4
|
||||
c0.2,0,0.5,0,0.7-0.1c0.3-0.1,0.5-0.4,0.6-0.7c0.1-0.3,0.1-0.5-0.1-0.6c-0.2-0.1-0.4-0.1-0.7-0.1h-0.3l-0.6,1.5H21.2z M20.2,55.1
|
||||
c0.3,0,0.6,0,0.8-0.1c0.3-0.2,0.6-0.5,0.7-0.8c0.2-0.4,0.1-0.6-0.1-0.7c-0.2-0.1-0.5-0.1-0.8-0.1h-0.3l-0.7,1.8H20.2z"/>
|
||||
<path class="st0" d="M30.9,49.9l0.4,6.2H29v-1.2h-2l-1,1.2h-1.6l5.2-6.2H30.9z M27.7,53.9H29v-1.7L27.7,53.9z"/>
|
||||
<path class="st0" d="M0,52.5c0-9.4,27.5-16.9,61.5-16.9c29.9,0,54.8,5.9,60.4,13.7c-6.3-6.2-28.4-10.7-54.7-10.7
|
||||
C36,38.6,10.7,45,10.7,52.9S36,67.2,67.2,67.2c23,0,42.9-3.5,51.7-8.5c-8.9,6.3-31.2,10.8-57.3,10.8C27.5,69.5,0,61.9,0,52.5"/>
|
||||
<path class="st1" d="M32.4,79l-0.5,5.8c0,0.3,0,0.5,0,0.5c0,0.1,0,0.2,0.1,0.3c0.1,0.1,0.2,0.2,0.3,0.2c0.2,0.1,0.4,0.1,0.6,0.1
|
||||
l-0.1,0.2h-2.7L30,86h0.1c0.2,0,0.4,0,0.5-0.2c0.1-0.1,0.2-0.2,0.2-0.3c0.1-0.2,0.1-0.5,0.1-0.8l0.1-0.9h-2l-0.7,1
|
||||
c-0.1,0.1-0.2,0.3-0.3,0.5c0,0.1,0,0.2,0,0.3c0,0.1,0.1,0.2,0.1,0.3c0.1,0.1,0.3,0.1,0.4,0.1l-0.1,0.2h-2.1l0-0.2
|
||||
c0.2,0,0.5-0.1,0.7-0.3c0.3-0.3,0.6-0.6,0.9-1l4.1-5.7L32.4,79z M31.4,80.8l-2,2.7h1.7L31.4,80.8z"/>
|
||||
<path class="st1" d="M37.4,85c-0.3,0.4-0.7,0.7-1.1,0.9c-0.3,0.2-0.7,0.3-1.1,0.3c-0.4,0-0.8-0.1-1.1-0.4c-0.3-0.3-0.4-0.7-0.4-1.1
|
||||
c0-0.5,0.2-1.1,0.4-1.5c0.3-0.5,0.7-0.9,1.2-1.2c0.4-0.3,0.9-0.5,1.5-0.5c0.3,0,0.6,0.1,0.8,0.2c0.2,0.1,0.3,0.3,0.3,0.6
|
||||
c0,0.2-0.1,0.4-0.2,0.5C37.6,83,37.4,83,37.3,83c-0.1,0-0.2,0-0.3-0.1c-0.1-0.1-0.1-0.2-0.1-0.3c0-0.1,0-0.1,0-0.2
|
||||
c0-0.1,0.1-0.1,0.2-0.2c0.1,0,0.1-0.1,0.2-0.2c0,0,0-0.1,0-0.1c0-0.1,0-0.1-0.1-0.2c-0.1-0.1-0.3-0.1-0.4-0.1c-0.4,0-0.7,0.1-1,0.4
|
||||
c-0.4,0.3-0.6,0.6-0.8,1c-0.3,0.5-0.4,1-0.4,1.6c0,0.3,0.1,0.6,0.3,0.8c0.2,0.2,0.5,0.3,0.8,0.3c0.3,0,0.5-0.1,0.8-0.2
|
||||
c0.3-0.2,0.6-0.4,0.9-0.7L37.4,85z"/>
|
||||
<path class="st1" d="M40.8,80.2l-0.4,1.4h0.8l-0.1,0.3h-0.8l-0.9,3c-0.1,0.2-0.1,0.4-0.2,0.6c0,0,0,0.1,0,0.1c0,0,0.1,0,0.1,0
|
||||
c0.1,0,0.2-0.1,0.3-0.2c0.2-0.2,0.4-0.4,0.5-0.6l0.2,0.1c-0.2,0.4-0.5,0.7-0.9,1c-0.2,0.1-0.4,0.2-0.6,0.2c-0.1,0-0.3,0-0.4-0.1
|
||||
c-0.1-0.1-0.2-0.2-0.2-0.4c0-0.3,0.1-0.6,0.2-0.8l0.8-3h-0.8v-0.2c0.3-0.1,0.7-0.2,0.9-0.5c0.3-0.3,0.6-0.7,0.8-1.1L40.8,80.2z"/>
|
||||
<path class="st1" d="M45.9,81.6L45,84.7c-0.1,0.3-0.2,0.6-0.2,0.9c0,0,0,0.1,0,0.1c0,0,0.1,0,0.1,0c0.1,0,0.1,0,0.2-0.1
|
||||
c0.2-0.2,0.4-0.4,0.5-0.6l0.2,0.1c-0.2,0.4-0.5,0.7-0.8,0.9c-0.2,0.1-0.3,0.2-0.5,0.2c-0.1,0-0.2,0-0.3-0.1C44,86.1,44,86,44,85.9
|
||||
c0-0.2,0-0.3,0.1-0.5c0.1-0.2,0.2-0.8,0.5-1.6c-0.4,0.7-0.9,1.4-1.5,2c-0.3,0.3-0.7,0.5-1.1,0.5c-0.1,0-0.3-0.1-0.4-0.2
|
||||
c-0.1-0.1-0.2-0.3-0.2-0.4c0-0.4,0.1-0.8,0.2-1.2l0.5-1.6c0.1-0.2,0.1-0.5,0.2-0.7c0,0,0-0.1,0-0.1c0,0-0.1,0-0.1,0
|
||||
c-0.1,0-0.2,0-0.2,0.1c-0.2,0.2-0.3,0.4-0.5,0.6l-0.2-0.2c0.2-0.3,0.5-0.6,0.8-0.9c0.2-0.1,0.4-0.2,0.6-0.2c0.1,0,0.2,0,0.3,0.1
|
||||
c0.1,0.1,0.1,0.2,0.1,0.3c0,0.3-0.1,0.7-0.2,1l-0.5,1.7c-0.1,0.3-0.2,0.6-0.2,0.8c0,0.1,0,0.1,0.1,0.2c0,0,0.1,0.1,0.2,0.1
|
||||
c0.2,0,0.3-0.1,0.4-0.2c0.3-0.2,0.5-0.5,0.7-0.8c0.3-0.3,0.5-0.7,0.8-1.1c0.3-0.5,0.5-1.1,0.6-1.6l0.1-0.4L45.9,81.6z"/>
|
||||
<path class="st1" d="M51.1,81.5l-1,3.5L50,85.5c0,0,0,0.1,0,0.2c0,0,0,0.1,0,0.2c0,0,0.1,0,0.1,0c0.1,0,0.1,0,0.2-0.1
|
||||
c0.2-0.2,0.4-0.4,0.5-0.6l0.2,0.1c-0.2,0.3-0.4,0.6-0.7,0.8c-0.2,0.2-0.4,0.3-0.7,0.3c-0.1,0-0.2,0-0.3-0.1
|
||||
c-0.1-0.1-0.1-0.2-0.1-0.3c0-0.2,0-0.4,0.1-0.7l0.1-0.4c-0.3,0.5-0.7,0.9-1.2,1.2c-0.2,0.2-0.5,0.2-0.8,0.2c-0.3,0-0.5-0.1-0.7-0.3
|
||||
c-0.2-0.2-0.3-0.5-0.3-0.8c0-0.6,0.2-1.2,0.5-1.7c0.3-0.6,0.7-1.1,1.2-1.4c0.3-0.3,0.7-0.4,1.1-0.4c0.2,0,0.4,0.1,0.5,0.2
|
||||
c0.2,0.1,0.3,0.3,0.3,0.5l0.2-0.6L51.1,81.5z M49.3,81.8c-0.3,0-0.5,0.1-0.7,0.3c-0.4,0.4-0.7,0.8-0.9,1.3c-0.3,0.5-0.4,1-0.4,1.5
|
||||
c0,0.2,0,0.4,0.2,0.6c0.1,0.1,0.2,0.2,0.4,0.2c0.4,0,0.8-0.3,1.2-0.8c0.5-0.6,0.8-1.4,0.9-2.2c0-0.2,0-0.4-0.2-0.6
|
||||
C49.6,81.8,49.5,81.8,49.3,81.8z"/>
|
||||
<path class="st1" d="M54.6,78.9L52.8,85c-0.1,0.2-0.1,0.4-0.1,0.6c0,0.1,0.1,0.2,0.2,0.2c0,0,0,0,0,0c0.1,0,0.2,0,0.2-0.1
|
||||
c0.2-0.2,0.4-0.4,0.6-0.7l0.2,0.2c-0.2,0.4-0.5,0.7-0.9,1c-0.2,0.1-0.4,0.2-0.6,0.2c-0.1,0-0.2,0-0.3-0.1c-0.1-0.1-0.1-0.2-0.1-0.3
|
||||
c0-0.3,0.1-0.5,0.2-0.8l1.4-4.8c0.1-0.2,0.1-0.4,0.2-0.7c0-0.1,0-0.2-0.1-0.2c-0.1-0.1-0.2-0.1-0.3-0.1c-0.1,0-0.2,0-0.3,0v-0.2
|
||||
L54.6,78.9z"/>
|
||||
<path class="st1" d="M59.6,86l0,0.2h-2.9l0.1-0.2c0.2,0,0.4,0,0.6-0.1c0.1,0,0.2-0.1,0.3-0.2c0.2-0.3,0.3-0.6,0.3-0.9l1.2-4.2
|
||||
c0.1-0.3,0.1-0.5,0.2-0.8c0-0.1,0-0.2-0.1-0.2c-0.1-0.1-0.1-0.1-0.2-0.1c-0.2,0-0.4-0.1-0.5,0l0.1-0.2h2.7l-0.1,0.2
|
||||
c-0.2,0-0.3,0-0.5,0.1c-0.1,0.1-0.3,0.2-0.4,0.3c-0.1,0.3-0.2,0.6-0.3,0.8l-1.2,4.2c-0.1,0.2-0.1,0.5-0.2,0.7c0,0.1,0,0.2,0.1,0.2
|
||||
c0.1,0.1,0.1,0.1,0.2,0.1C59.2,85.9,59.4,86,59.6,86z"/>
|
||||
<path class="st1" d="M62.8,81.5l-0.7,2.3c0.4-0.7,0.9-1.3,1.5-1.9c0.3-0.3,0.6-0.4,1-0.4c0.2,0,0.3,0.1,0.4,0.2
|
||||
c0.1,0.1,0.2,0.3,0.2,0.4c0,0.3-0.1,0.6-0.2,0.8l-0.6,2.2c0,0.1-0.1,0.3-0.1,0.4c0,0,0,0.1,0,0.1c0,0,0.1,0,0.1,0
|
||||
c0.1,0,0.1,0,0.2-0.1c0.2-0.2,0.4-0.4,0.6-0.7l0.2,0.1c-0.2,0.4-0.5,0.7-0.9,1c-0.2,0.1-0.3,0.2-0.5,0.2c-0.1,0-0.2,0-0.3-0.1
|
||||
c-0.1-0.1-0.1-0.2-0.1-0.3c0-0.3,0.1-0.6,0.2-0.8l0.6-2.1c0.1-0.2,0.1-0.4,0.1-0.6c0-0.1-0.1-0.2-0.2-0.2c-0.1,0-0.2,0.1-0.3,0.1
|
||||
c-0.3,0.2-0.6,0.5-0.8,0.8c-0.3,0.4-0.6,0.9-0.9,1.4c-0.2,0.3-0.3,0.7-0.4,1l-0.2,0.8h-0.8l0.9-3.2c0.1-0.2,0.1-0.5,0.2-0.7
|
||||
c0-0.1,0-0.1-0.1-0.2C61.6,82,61.5,82,61.4,82h-0.2H61v-0.2L62.8,81.5z"/>
|
||||
<path class="st1" d="M65.9,81.8l1.5-0.3c0.1,0.3,0.2,0.5,0.3,0.8c0.1,0.5,0.2,0.9,0.2,1.4c0,0.3,0.1,0.8,0.1,1.7
|
||||
c0.4-0.5,0.7-0.8,0.8-0.9l0.8-1.1c0.1-0.1,0.2-0.3,0.2-0.5c0-0.1,0.1-0.2,0.1-0.3c0-0.1-0.1-0.2-0.2-0.3c-0.1-0.1-0.2-0.2-0.2-0.4
|
||||
c0-0.1,0-0.2,0.1-0.3c0.1-0.1,0.2-0.1,0.3-0.1c0.1,0,0.3,0.1,0.4,0.2c0.1,0.1,0.2,0.3,0.2,0.4c0,0.2,0,0.3-0.1,0.5
|
||||
c-0.1,0.3-0.3,0.7-0.5,0.9c-0.4,0.5-0.8,1-1.2,1.5c-0.1,0.1-0.4,0.5-1.1,1.2h-0.2c0-1.4-0.1-2.7-0.5-4.1c-0.1-0.2-0.2-0.3-0.4-0.3
|
||||
C66.2,81.9,66.1,81.9,65.9,81.8L65.9,81.8z"/>
|
||||
<path class="st1" d="M71.6,84.2c0,0.1,0,0.3,0,0.4c0,0.3,0.1,0.6,0.3,0.8c0.2,0.2,0.5,0.3,0.8,0.3c0.2,0,0.5,0,0.7-0.1
|
||||
c0.4-0.2,0.7-0.4,1-0.7l0.1,0.2c-0.6,0.7-1.4,1.1-2.3,1.2c-0.4,0-0.8-0.1-1.1-0.5c-0.2-0.3-0.4-0.6-0.4-1c0-0.6,0.2-1.1,0.5-1.6
|
||||
c0.3-0.5,0.7-0.9,1.2-1.2c0.4-0.3,0.9-0.4,1.5-0.4c0.3,0,0.6,0.1,0.8,0.2c0.2,0.1,0.3,0.3,0.3,0.5c0,0.3-0.1,0.6-0.3,0.8
|
||||
c-0.4,0.4-0.8,0.7-1.3,0.8C72.7,84.1,72.2,84.2,71.6,84.2z M71.6,84c0.4,0,0.8-0.1,1.2-0.3c0.4-0.1,0.7-0.4,1-0.7
|
||||
c0.2-0.2,0.3-0.5,0.3-0.7c0-0.1-0.1-0.3-0.2-0.3c-0.1-0.1-0.2-0.1-0.4-0.1c-0.4,0-0.8,0.2-1.1,0.5C72.1,82.8,71.8,83.4,71.6,84
|
||||
L71.6,84z"/>
|
||||
<path class="st1" d="M78.8,81.5l-0.3,1.6h-0.2c0-0.4-0.1-0.7-0.3-1c-0.2-0.2-0.4-0.3-0.7-0.3c-0.2,0-0.4,0.1-0.5,0.2
|
||||
c-0.1,0.1-0.2,0.3-0.2,0.4c0,0.1,0,0.2,0.1,0.3c0.1,0.2,0.2,0.3,0.3,0.4c0.3,0.3,0.6,0.7,0.9,1.1c0.1,0.2,0.2,0.4,0.2,0.7
|
||||
c0,0.4-0.2,0.7-0.4,0.9c-0.3,0.3-0.7,0.4-1.1,0.4c-0.3,0-0.6-0.1-0.8-0.2c-0.1,0-0.2-0.1-0.3-0.1c-0.2,0-0.3,0.1-0.3,0.2h-0.2
|
||||
l0.3-1.7h0.2c0,0.4,0.1,0.8,0.3,1.1c0.2,0.2,0.5,0.3,0.8,0.3c0.2,0,0.4-0.1,0.6-0.2c0.1-0.1,0.2-0.3,0.2-0.5c0-0.1,0-0.3-0.1-0.4
|
||||
c-0.2-0.3-0.4-0.6-0.6-0.8c-0.2-0.2-0.4-0.5-0.6-0.8C76,83.1,76,82.9,76,82.7c0-0.3,0.1-0.6,0.4-0.8c0.3-0.3,0.8-0.4,1.2-0.3
|
||||
l0.3,0.1c0.1,0.1,0.2,0.1,0.3,0.1c0.2,0,0.3-0.1,0.4-0.2H78.8z"/>
|
||||
<path class="st1" d="M81.8,80.2l-0.4,1.4h0.8l-0.1,0.3h-0.8l-0.9,3c-0.1,0.2-0.1,0.4-0.1,0.6c0,0,0,0.1,0,0.1c0,0,0.1,0,0.1,0
|
||||
c0.1,0,0.2-0.1,0.3-0.2c0.2-0.2,0.4-0.4,0.5-0.6l0.2,0.1c-0.2,0.4-0.5,0.7-0.9,1c-0.2,0.1-0.4,0.2-0.6,0.2c-0.1,0-0.3,0-0.4-0.1
|
||||
c-0.1-0.1-0.1-0.2-0.1-0.4c0-0.3,0.1-0.6,0.2-0.8l0.9-3h-0.8v-0.2c0.3-0.1,0.7-0.2,0.9-0.5c0.3-0.3,0.6-0.7,0.8-1.1L81.8,80.2z"/>
|
||||
<path class="st1" d="M86.9,83.1c0,0.5-0.2,1-0.4,1.5c-0.3,0.5-0.7,0.9-1.1,1.2c-0.4,0.3-0.9,0.4-1.4,0.4c-0.4,0-0.8-0.1-1.2-0.5
|
||||
c-0.3-0.3-0.5-0.7-0.4-1.2c0-0.5,0.2-1.1,0.4-1.5c0.3-0.5,0.7-0.9,1.2-1.2c0.4-0.3,0.9-0.4,1.4-0.4c0.4,0,0.8,0.1,1.1,0.5
|
||||
C86.7,82.3,86.9,82.7,86.9,83.1z M86,82.8c0-0.3-0.1-0.5-0.2-0.7c-0.2-0.2-0.4-0.3-0.6-0.2c-0.5,0-1,0.4-1.4,1.1
|
||||
c-0.4,0.6-0.6,1.4-0.6,2.1c0,0.3,0.1,0.5,0.2,0.8c0.2,0.2,0.4,0.3,0.6,0.3c0.5,0,0.9-0.3,1.3-1.1C85.8,84.3,86,83.5,86,82.8z"/>
|
||||
<path class="st1" d="M87.8,81.8l1.8-0.3L88.8,84c0.4-0.8,1-1.5,1.6-2.1c0.2-0.2,0.4-0.3,0.7-0.3c0.1,0,0.2,0,0.3,0.1
|
||||
c0.1,0.1,0.1,0.2,0.1,0.3c0,0.2-0.1,0.5-0.2,0.7c-0.1,0.1-0.2,0.2-0.3,0.2c-0.1,0-0.1,0-0.2-0.1c-0.1-0.1-0.1-0.1-0.1-0.2
|
||||
c0-0.1,0-0.1-0.1-0.1c0,0-0.1,0-0.1,0c-0.1,0-0.1,0-0.2,0c-0.2,0.1-0.3,0.2-0.4,0.4c-0.3,0.4-0.6,0.8-0.9,1.3
|
||||
c-0.2,0.2-0.3,0.5-0.4,0.8c-0.2,0.4-0.2,0.6-0.2,0.7l-0.2,0.7h-0.8l1-3.2c0.1-0.3,0.1-0.5,0.2-0.8c0-0.1,0-0.1-0.1-0.2
|
||||
c-0.1-0.1-0.2-0.1-0.3-0.1h-0.4L87.8,81.8z"/>
|
||||
<path class="st1" d="M95.2,81.5l-0.3,1.6h-0.2c0-0.4-0.1-0.7-0.3-1c-0.2-0.2-0.4-0.3-0.7-0.3c-0.2,0-0.4,0.1-0.5,0.2
|
||||
c-0.1,0.1-0.2,0.3-0.2,0.4c0,0.1,0,0.2,0.1,0.3c0.1,0.2,0.2,0.3,0.3,0.4c0.3,0.3,0.6,0.7,0.9,1.1c0.1,0.2,0.2,0.4,0.2,0.7
|
||||
c0,0.4-0.2,0.7-0.4,0.9c-0.3,0.3-0.7,0.4-1.1,0.4c-0.3,0-0.6-0.1-0.8-0.2c-0.1,0-0.2-0.1-0.3-0.1c-0.2,0-0.3,0.1-0.3,0.2h-0.2
|
||||
l0.3-1.7h0.2c0,0.4,0.1,0.8,0.3,1.1c0.2,0.2,0.5,0.3,0.8,0.3c0.2,0,0.4-0.1,0.6-0.2c0.1-0.1,0.2-0.3,0.2-0.5c0-0.1,0-0.3-0.1-0.4
|
||||
c-0.2-0.3-0.4-0.6-0.6-0.8c-0.2-0.2-0.4-0.5-0.6-0.8c-0.1-0.2-0.1-0.4-0.1-0.5c0-0.3,0.1-0.6,0.4-0.8c0.3-0.2,0.6-0.4,0.9-0.3
|
||||
c0.1,0,0.2,0,0.3,0l0.3,0.1c0.1,0,0.2,0.1,0.3,0.1c0.2,0,0.3-0.1,0.4-0.2L95.2,81.5z"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 11 KiB |
@ -1,7 +1,7 @@
|
||||
{
|
||||
"NOTICE_WARN": "THIS CODE HAS BEEN AUTOMATICALLY GENERATED FROM TRANSIFEX, IF YOU WISH TO HELP TRANSLATION COME ON THE SLACK http://slack.btcpayserver.org TO REQUEST PERMISSION TO https://www.transifex.com/btcpayserver/btcpayserver/",
|
||||
"code": "bg-BG",
|
||||
"currentLanguage": "български",
|
||||
"currentLanguage": "Английски",
|
||||
"lang": "Език",
|
||||
"Awaiting Payment...": "Очаква се платеж...",
|
||||
"Pay with": "Плати с",
|
||||
@ -49,4 +49,4 @@
|
||||
"Close": "Затвори",
|
||||
"NotPaid_ExtraTransaction": "Фактурата не а платена изцяло. Моля пратете остатъка в допълнителна транзакция. ",
|
||||
"Recommended_Fee": "Препоръчена тарифа: {{feeRate}} сат/байт (sat/byte)"
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"NOTICE_WARN": "THIS CODE HAS BEEN AUTOMATICALLY GENERATED FROM TRANSIFEX, IF YOU WISH TO HELP TRANSLATION COME ON THE SLACK http://slack.btcpayserver.org TO REQUEST PERMISSION TO https://www.transifex.com/btcpayserver/btcpayserver/",
|
||||
"code": "fi-FI",
|
||||
"currentLanguage": "Suomi",
|
||||
"currentLanguage": "Englanti",
|
||||
"lang": "Kieli",
|
||||
"Awaiting Payment...": "Odotaa maksua...",
|
||||
"Pay with": "Maksa käyttämällä",
|
||||
@ -49,4 +49,4 @@
|
||||
"Close": "Sulje",
|
||||
"NotPaid_ExtraTransaction": "Laskua ei ole maksettu kokonaan. Lähetä uusi maksu erääntyvän summan kattamiseksi.",
|
||||
"Recommended_Fee": "Suositeltu siirtomaksu: {{feeRate}} sat/tavu"
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
{
|
||||
"NOTICE_WARN": "THIS CODE HAS BEEN AUTOMATICALLY GENERATED FROM TRANSIFEX, IF YOU WISH TO HELP TRANSLATION COME ON THE SLACK http://slack.btcpayserver.org TO REQUEST PERMISSION TO https://www.transifex.com/btcpayserver/btcpayserver/",
|
||||
"code": "he",
|
||||
"currentLanguage": "עברית",
|
||||
"lang": "שפה",
|
||||
"Awaiting Payment...": "ממתין לתשלום...",
|
||||
"Pay with": "תשלום עם",
|
||||
"Contact and Refund Email": "דוא\"ל ליצירת קשר והחזר",
|
||||
"Contact_Body": "נא להזין כתובת דוא\"ל למטה.\nאנחנו ניצור אתך קשר בכתובת זו במקרא של בעיה עם התשלום שלך.",
|
||||
"Your email": "הדוא\"ל שלך",
|
||||
"Continue": "המשך",
|
||||
"Please enter a valid email address": "נא להזין כתובת דוא\"ל תקינה",
|
||||
"Order Amount": "סה\"כ הזמנה",
|
||||
"Network Cost": "עלות רשת",
|
||||
"Already Paid": "כבר שולם",
|
||||
"Due": "חוב",
|
||||
"Scan": "סריקה",
|
||||
"Copy": "העתקה",
|
||||
"Conversion": "המרה",
|
||||
"Open in wallet": "פתיחת ארנק",
|
||||
"CompletePay_Body": "להשלים את התשלום, נא לשלוח {{btcDue}} {{cryptoCode}} לכתובת הבאה.",
|
||||
"Amount": "סכום",
|
||||
"Address": "כתובת",
|
||||
"Copied": "הועתק",
|
||||
"ConversionTab_BodyTop": "ניתן לשלם {{cryptoCode}} {{btcDue}} בעזרת שיטקוינים אחרים מאלו שהמוכר/ת מקבל/ת ישירות.",
|
||||
"ConversionTab_BodyDesc": "שירות זה מסופק על ידי צד שלישי. שימו לב שאין לנו שליטה על איך ספקים יעבירו את הכסף שלך. החשבונית תחשב כשולמה רק כשהכספים מתקבלים על שרשרת הבלוקים של {{cryptocode}}.",
|
||||
"ConversionTab_CalculateAmount_Error": "נסו שוב",
|
||||
"ConversionTab_LoadCurrencies_Error": "נסו שוב",
|
||||
"ConversionTab_Lightning": "לא קיימים ספקי המרה לתשלומים לרשת הברק.",
|
||||
"ConversionTab_CurrencyList_Select_Option": "נא לבחור מטבע להמיר",
|
||||
"Invoice expiring soon...": "חשבונית תפוג תוקף בקרוב...",
|
||||
"Invoice expired": "חשבונית פגה תוקף",
|
||||
"What happened?": "מה קרה?",
|
||||
"InvoiceExpired_Body_1": "חשבונית זו פגה תוקף. חשבונית תקפה רק למשך {{maxTimeMinutes}} דקות.\nניתן לחזור אל {{storeName}} אם ברצונך לשלוח את תשלומך שוב.",
|
||||
"InvoiceExpired_Body_2": "אם ניסית לשלוח תשלום, הוא תרם התקבל על ידי הרשת. עדיין לא קיבלנו את הכספים שלך.",
|
||||
"InvoiceExpired_Body_3": "אם נקבל זאת במועד מאוחר יותר, אנחנו נטפל בהזמנתך, או ניצור קשר אתך להסדיר החזר...",
|
||||
"Invoice ID": "מספר חשבונית",
|
||||
"Order ID": "מספר הזמנה",
|
||||
"Return to StoreName": "חזרה אל {{storeName}}",
|
||||
"This invoice has been paid": "החשבונית שולמה",
|
||||
"This invoice has been archived": "חשבונית זו נגנזה",
|
||||
"Archived_Body": "נא לפנות לחנות למידע על הזמנה או סיוע",
|
||||
"BOLT 11 Invoice": "חשבונית BOLT 11",
|
||||
"Node Info": "מידע צומת",
|
||||
"txCount": "{{count}} פעולה",
|
||||
"txCount_plural": "{{count}} פעולות",
|
||||
"Pay with CoinSwitch": "תשלום עם CoinSwitch",
|
||||
"Pay with Changelly": "תשלום עם Changelly",
|
||||
"Close": "סגירה",
|
||||
"NotPaid_ExtraTransaction": "החשבונית לא שולמה במלואה. נא לשלוח תשלום נוסף לכיסוי סכום החוב.",
|
||||
"Recommended_Fee": "עמלה מומלצת: {{feeRate}} סאט/בית"
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"NOTICE_WARN": "THIS CODE HAS BEEN AUTOMATICALLY GENERATED FROM TRANSIFEX, IF YOU WISH TO HELP TRANSLATION COME ON THE SLACK http://slack.btcpayserver.org TO REQUEST PERMISSION TO https://www.transifex.com/btcpayserver/btcpayserver/",
|
||||
"code": "kk-KZ",
|
||||
"currentLanguage": "қазақ",
|
||||
"currentLanguage": "Қазақша",
|
||||
"lang": "Тіл",
|
||||
"Awaiting Payment...": "Күтіп тұрған төлем…",
|
||||
"Pay with": "Төлеу",
|
||||
@ -49,4 +49,4 @@
|
||||
"Close": "Close",
|
||||
"NotPaid_ExtraTransaction": "The invoice hasn't been paid in full. Please send another transaction to cover amount Due.",
|
||||
"Recommended_Fee": "Recommended fee: {{feeRate}} sat/byte"
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
{
|
||||
"NOTICE_WARN": "THIS CODE HAS BEEN AUTOMATICALLY GENERATED FROM TRANSIFEX, IF YOU WISH TO HELP TRANSLATION COME ON THE SLACK http://slack.btcpayserver.org TO REQUEST PERMISSION TO https://www.transifex.com/btcpayserver/btcpayserver/",
|
||||
"code": "ko",
|
||||
"currentLanguage": "한국어",
|
||||
"lang": "언어",
|
||||
"Awaiting Payment...": "지불 대기 중...",
|
||||
"Pay with": "Pay with",
|
||||
"Contact and Refund Email": "연락 및 환불 이메일",
|
||||
"Contact_Body": "Please provide an email address below. We’ll contact you at this address if there is an issue with your payment.",
|
||||
"Your email": "자신의 이메일",
|
||||
"Continue": "계속하기",
|
||||
"Please enter a valid email address": "유효한 이메일 주소를 입력해주세요",
|
||||
"Order Amount": "총 주문 금액",
|
||||
"Network Cost": "네트워크 수수료",
|
||||
"Already Paid": "지불 완료",
|
||||
"Due": "지불 대기 중",
|
||||
"Scan": "스캔",
|
||||
"Copy": "복사",
|
||||
"Conversion": "환율",
|
||||
"Open in wallet": "지갑에서 열기",
|
||||
"CompletePay_Body": "To complete your payment, please send {{btcDue}} {{cryptoCode}} to the address below.",
|
||||
"Amount": "금액",
|
||||
"Address": "주소",
|
||||
"Copied": "복사 완료",
|
||||
"ConversionTab_BodyTop": "You can pay {{btcDue}} {{cryptoCode}} using altcoins other than the ones merchant directly supports.",
|
||||
"ConversionTab_BodyDesc": "This service is provided by 3rd party. Please keep in mind that we have no control over how providers will forward your funds. Invoice will only be marked paid once funds are received on {{cryptoCode}} Blockchain.",
|
||||
"ConversionTab_CalculateAmount_Error": "다시 시도",
|
||||
"ConversionTab_LoadCurrencies_Error": "다시 시도",
|
||||
"ConversionTab_Lightning": "No conversion providers available for Lightning Network payments.",
|
||||
"ConversionTab_CurrencyList_Select_Option": "환전할 화폐를 선택하세요",
|
||||
"Invoice expiring soon...": "인보이스가 곧 만료 됨...",
|
||||
"Invoice expired": "인보이스 만료",
|
||||
"What happened?": "무슨 일인가요?",
|
||||
"InvoiceExpired_Body_1": "This invoice has expired. An invoice is only valid for {{maxTimeMinutes}} minutes. \nYou can return to {{storeName}} if you would like to submit your payment again.",
|
||||
"InvoiceExpired_Body_2": "If you tried to send a payment, it has not yet been accepted by the network. We have not yet received your funds.",
|
||||
"InvoiceExpired_Body_3": "",
|
||||
"Invoice ID": "인보이스 ID",
|
||||
"Order ID": "주문 ID",
|
||||
"Return to StoreName": "{{storeName}}으로 돌아가기",
|
||||
"This invoice has been paid": "이 인보이스는 지불 완료됐습니다.",
|
||||
"This invoice has been archived": "This invoice has been archived",
|
||||
"Archived_Body": "Please contact the store for order information or assistance",
|
||||
"BOLT 11 Invoice": "BOLT 11 인보이스",
|
||||
"Node Info": "노드 정보",
|
||||
"txCount": "{{count}} 거래",
|
||||
"txCount_plural": "{{count}} 거래",
|
||||
"Pay with CoinSwitch": "CoinSwitch를 이용해 지불하기",
|
||||
"Pay with Changelly": "Changelly를 이용해 지불하기",
|
||||
"Close": "닫기",
|
||||
"NotPaid_ExtraTransaction": "The invoice hasn't been paid in full. Please send another transaction to cover amount Due.",
|
||||
"Recommended_Fee": "추천하는 수수료: {{feeRate}} sat/byte"
|
||||
}
|
@ -3,13 +3,13 @@
|
||||
"code": "nl-NL",
|
||||
"currentLanguage": "Nederlands",
|
||||
"lang": "Taal",
|
||||
"Awaiting Payment...": "Wacht op betaling...",
|
||||
"Pay with": "Betaal met",
|
||||
"Contact and Refund Email": "E-mailadres voor opvolging en terugbetaling",
|
||||
"Contact_Body": "Laat hieronder uw e-mailadres achter. We nemen contact met u op mochten er problemen zijn met uw betaling.",
|
||||
"Your email": "Uw e-mailadres",
|
||||
"Awaiting Payment...": "In afwachting van de betaling...",
|
||||
"Pay with": "Betalen met",
|
||||
"Contact and Refund Email": "Email adres voor opvolging en terugbetaling",
|
||||
"Contact_Body": "Laat hieronder uw email adres achter. We nemen contact met u op als er problemen zijn met uw betaling.",
|
||||
"Your email": "Je email adres",
|
||||
"Continue": "Verder",
|
||||
"Please enter a valid email address": "Vul een geldig e-mailadres in",
|
||||
"Please enter a valid email address": "Vul een geldig email adres in",
|
||||
"Order Amount": "Bedrag van uw bestelling",
|
||||
"Network Cost": "Netwerkkosten",
|
||||
"Already Paid": "Reeds betaald",
|
||||
@ -18,24 +18,24 @@
|
||||
"Copy": "Kopiëren",
|
||||
"Conversion": "Omzetting",
|
||||
"Open in wallet": "Wallet openen",
|
||||
"CompletePay_Body": "Om de betaling af te ronden, stuur alstublieft {{btcDue}} {{cryptoCode}} naar het hieronder vermelde adres.",
|
||||
"CompletePay_Body": "Om de betaling af te ronden, stuur alstublieft {{btcDue}} {{cryptoCode}} naar het hieronder vemelde adres.",
|
||||
"Amount": "Bedrag",
|
||||
"Address": "Adres",
|
||||
"Copied": "Gekopieerd",
|
||||
"ConversionTab_BodyTop": "U kunt altcoins gebruiken die niet ondersteund zijn door de verkoper, om {{btcDue}} {{cryptoCode}} te betalen.",
|
||||
"ConversionTab_BodyDesc": "Deze dienst wordt door een 3e partij geleverd. Wij hebben daardoor geen zicht op uw fondsen. De factuur wordt pas als betaald beschouwd, wanneer de fondsen door de {{ cryptoCode }} blockchain aanvaard zijn.",
|
||||
"ConversionTab_BodyDesc": "Deze dienst wordt door een 3e partij geleverd. Wij hebben daardoor geen zicht over uw fondsen. De factuur wordt pas als betaald beschouwd, wanneer de fondsen door de {{ cryptoCode }} blockchain aanvaard zijn.",
|
||||
"ConversionTab_CalculateAmount_Error": "Opnieuw proberen",
|
||||
"ConversionTab_LoadCurrencies_Error": "Opnieuw proberen",
|
||||
"ConversionTab_Lightning": "Geen conversie leverancier beschikbaar voor de betalingen op het Lightning Network",
|
||||
"ConversionTab_CurrencyList_Select_Option": "Selecteer een valuta om te converteren",
|
||||
"Invoice expiring soon...": "Factuur verloopt binnenkort...",
|
||||
"Invoice expired": "Factuur vervallen",
|
||||
"What happened?": "Wat is er gebeurd?",
|
||||
"InvoiceExpired_Body_1": "De factuur is vervallen. Een factuur is slechts geldig voor {{maxTimeMinutes}} minuten. \nU kan teruggaan naar {{storeName}} als u de betaling opnieuw wil proberen.",
|
||||
"InvoiceExpired_Body_2": "Als u een betaling uitvoerde, dan werd deze nog niet bevestigd door het netwerk. We hebben uw betaling nog niet ontvangen.",
|
||||
"InvoiceExpired_Body_3": "Als we uw betaling later ontvangen, zullen we uw order verwerken of nemen we contact op om een terugbetaling te regelen...",
|
||||
"Invoice expiring soon...": "De factuur verloopt binnenkort...",
|
||||
"Invoice expired": "Vervallen factuur",
|
||||
"What happened?": "Wat gebeurde er?",
|
||||
"InvoiceExpired_Body_1": "De factuur is vervallen. Een factuur is alleen geldig voor {{maxTimeMinutes}} minuten. \nJe kan terug komen naar {{storeName}} als je de betaling opnieuw wilt proberen",
|
||||
"InvoiceExpired_Body_2": "Als u een betaling uitvoerde, dan werd dit nog niet bevestigd door het netwerk. We hebben uw fondsen nog niet ontvangen.",
|
||||
"InvoiceExpired_Body_3": "Indien we het later ontvangen, zullen we uw order verwerken of nemen we contact op om een terugbetaling te regelen...",
|
||||
"Invoice ID": "Factuurnummer",
|
||||
"Order ID": "Ordernummer",
|
||||
"Order ID": "Bestllingsnummer",
|
||||
"Return to StoreName": "Terug naar {{storeName}}",
|
||||
"This invoice has been paid": "Deze factuur is betaald",
|
||||
"This invoice has been archived": "Deze factuur is gearchiveerd",
|
||||
|
@ -32,7 +32,7 @@
|
||||
"Invoice expired": "Fatura expirada",
|
||||
"What happened?": "O que aconteceu?",
|
||||
"InvoiceExpired_Body_1": "Esta fatura expirou. Uma fatura é válida por apenas {{maxTimeMinutes}} minutos. \nVocê pode voltar para {{storeName}} se quiser tentar enviar o pagamento novamente.",
|
||||
"InvoiceExpired_Body_2": "Se você tentou enviar um pagamento, ele ainda não foi aceito pela rede. Nós ainda não recebemos o valor enviado.",
|
||||
"InvoiceExpired_Body_2": "Se você tentou enviar um pagamento e ele ainda não foi aceito pela rede Bitcoin. Nós ainda não recebemos o valor enviado.",
|
||||
"InvoiceExpired_Body_3": "Se recebermos mais tarde, vamos processar o pedido ou entrar em contato para combinar o reembolso...",
|
||||
"Invoice ID": "Nº da Fatura",
|
||||
"Order ID": "Nº do Pedido",
|
||||
|
@ -217,12 +217,6 @@ h2 small .fa-question-circle-o {
|
||||
.w-150px { width: 150px; }
|
||||
.w-175px { width: 175px; }
|
||||
.w-200px { width: 200px; }
|
||||
.w-225px { width: 225px; }
|
||||
.w-250px { width: 250px; }
|
||||
.w-275px { width: 275px; }
|
||||
.w-300px { width: 300px; }
|
||||
.w-325px { width: 325px; }
|
||||
.w-350px { width: 350px; }
|
||||
|
||||
/* Print */
|
||||
@media print {
|
||||
@ -230,7 +224,7 @@ h2 small .fa-question-circle-o {
|
||||
.table th {
|
||||
background: transparent;
|
||||
}
|
||||
.bg-tile.h-100.p-3 {
|
||||
.jumbotron {
|
||||
padding: 1rem 0 !important;
|
||||
}
|
||||
.text-print-default {
|
||||
|
@ -45,8 +45,7 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
maxDate: max,
|
||||
defaultDate: defaultDate,
|
||||
time_24hr: true,
|
||||
defaultHour: 0,
|
||||
static: true
|
||||
defaultHour: 0
|
||||
});
|
||||
}
|
||||
});
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user