Checkout v2 finetuning (#4276)

* Indent all JSON files with two spaces

* Upgrade Vue.js

* Cheat mode improvements

* Show payment details in case of expired invoice

* Add logo size recommendation

* Show clipboard copy hint cursor

* Improve info area and wording

* Update BIP21 wording

* Invoice details adjustments

* Remove form; switch payment methods via AJAX

* UI updates

* Decrease paddings to gain space

* Tighten up padding between logo mark and the store title text

* Add drop-shadow to the containers

* Wording

* Cheating improvements

* Improve footer spacing

* Cheating improvements

* Display addresses

* More improvements

* Expire invoices

* Customize invoice expiry

* Footer improvements

* Remove theme switch

* Remove non-existing sourcemap references

* Move inline JS to checkout.js file

* Plugin compatibility

See Kukks/btcpayserver#8

* Test fix

* Upgrade vue-i18next

* Extract translations into a separate file

* Round QR code borders

* Remove "Pay with Bitcoin" title in BIP21 case

* Add copy hint to payment details

* Cheating: Reduce margins

* Adjust dt color

* Hide addresses for first iteration

* Improve View Details button

* Make info section collapsible

* Revert original en locale file

* Checkout v2 tests

* Result view link fixes

* Fix BIP21 + lazy payment methods case

* More result page link improvements

* minor visual improvements

* Update clipboard code

Remove fallback for old browsers. https://caniuse.com/?search=navigator.clipboard

* Transition copy symbol

* Update info text color

* Invert dark neutral colors

Simplifies the dark theme quite a bit.

* copy adjustments

* updates QR border-radius

* Add option to remove logo

* More checkout v2 test cases

* JS improvements

* Remove leftovers

* Update test

* Fix links

* Update tests

* Update plugins integration

* Remove obsolete url code

* Minor view update

* Update JS to not use arrow functions

* Remove FormId from Checkout Appearance settings

* Add English-only hint and feedback link

* Checkout Appearance: Make options clearer, remove Custom CSS for v2

* Clipboard copy full URL instead of just address/BOLT11

* Upgrade JS libs, add content checks

* Add test for BIP21 setting with zero amount invoice

Co-authored-by: dstrukt <gfxdsign@gmail.com>
This commit is contained in:
d11n
2022-11-24 00:53:32 +01:00
committed by GitHub
parent bf0a8c1e62
commit a4ee1e9805
42 changed files with 1714 additions and 12984 deletions

View File

@@ -4,6 +4,7 @@ using System.Linq;
using System.Threading.Tasks;
using BTCPayServer.Data;
using BTCPayServer.Filters;
using BTCPayServer.Lightning;
using BTCPayServer.Payments;
using BTCPayServer.Services;
using Microsoft.AspNetCore.Mvc;
@@ -17,6 +18,7 @@ namespace BTCPayServer.Controllers
{
public Decimal Amount { get; set; }
public string CryptoCode { get; set; } = "BTC";
public string PaymentMethodId { get; set; } = "BTC";
}
public class MineBlocksRequest
@@ -31,31 +33,65 @@ namespace BTCPayServer.Controllers
{
var invoice = await _InvoiceRepository.GetInvoice(invoiceId);
var store = await _StoreRepository.FindStore(invoice.StoreId);
// TODO support altcoins, not just bitcoin - and make it work for LN-only invoices
var isSats = request.CryptoCode.ToUpper(CultureInfo.InvariantCulture) == "SATS";
var cryptoCode = isSats ? "BTC" : request.CryptoCode;
var network = _NetworkProvider.GetNetwork<BTCPayNetwork>(cryptoCode);
var paymentMethodId = new [] {store.GetDefaultPaymentId()}.Concat(store.GetEnabledPaymentIds(_NetworkProvider))
.FirstOrDefault(p => p != null && p.CryptoCode == cryptoCode && p.PaymentType == PaymentTypes.BTCLike);
var bitcoinAddressString = invoice.GetPaymentMethod(paymentMethodId).GetPaymentMethodDetails().GetPaymentDestination();
var bitcoinAddressObj = BitcoinAddress.Create(bitcoinAddressString, network.NBitcoinNetwork);
var amount = new Money(request.Amount, isSats ? MoneyUnit.Satoshi : MoneyUnit.BTC);
var network = _NetworkProvider.GetNetwork<BTCPayNetwork>(cryptoCode).NBitcoinNetwork;
var paymentMethodId = new [] {store.GetDefaultPaymentId()}
.Concat(store.GetEnabledPaymentIds(_NetworkProvider))
.FirstOrDefault(p => p?.ToString() == request.PaymentMethodId);
try
{
var paymentMethod = invoice.GetPaymentMethod(paymentMethodId);
var rate = paymentMethod.Rate;
var txid = (await cheater.CashCow.SendToAddressAsync(bitcoinAddressObj, amount)).ToString();
// TODO The value of totalDue is wrong. How can we get the real total due? invoice.Price is only correct if this is the 2nd payment, not for a 3rd or 4th payment.
var totalDue = invoice.Price;
return Ok(new
var destination = paymentMethod?.GetPaymentMethodDetails().GetPaymentDestination();
switch (paymentMethod?.GetId().PaymentType)
{
Txid = txid,
AmountRemaining = (totalDue - (amount.ToUnit(MoneyUnit.BTC) * rate)) / rate,
SuccessMessage = "Created transaction " + txid
});
case BitcoinPaymentType:
var address = BitcoinAddress.Create(destination, network);
var txid = (await cheater.CashCow.SendToAddressAsync(address, amount)).ToString();
return Ok(new
{
Txid = txid,
AmountRemaining = (paymentMethod.Calculate().Due - amount).ToUnit(MoneyUnit.BTC),
SuccessMessage = $"Created transaction {txid}"
});
case LightningPaymentType:
// requires the channels to be set up using the BTCPayServer.Tests/docker-lightning-channel-setup.sh script
LightningConnectionString.TryParse(Environment.GetEnvironmentVariable("BTCPAY_BTCEXTERNALLNDREST"), false, out var lnConnection);
var lnClient = LightningClientFactory.CreateClient(lnConnection, network);
var lnAmount = new LightMoney(amount.Satoshi, LightMoneyUnit.Satoshi);
var response = await lnClient.Pay(destination, new PayInvoiceParams { Amount = lnAmount });
if (response.Result == PayResult.Ok)
{
var bolt11 = BOLT11PaymentRequest.Parse(destination, network);
var paymentHash = bolt11.PaymentHash?.ToString();
var paid = new Money(response.Details.TotalAmount.ToUnit(LightMoneyUnit.Satoshi), MoneyUnit.Satoshi);
return Ok(new
{
Txid = paymentHash,
AmountRemaining = (paymentMethod.Calculate().TotalDue - paid).ToUnit(MoneyUnit.BTC),
SuccessMessage = $"Sent payment {paymentHash}"
});
}
return UnprocessableEntity(new
{
ErrorMessage = response.ErrorDetail,
AmountRemaining = invoice.Price
});
default:
return UnprocessableEntity(new
{
ErrorMessage = $"Payment method {paymentMethodId} is not supported",
AmountRemaining = invoice.Price
});
}
}
catch (Exception e)
{
@@ -71,40 +107,30 @@ namespace BTCPayServer.Controllers
[CheatModeRoute]
public IActionResult MineBlock(string invoiceId, MineBlocksRequest request, [FromServices] Cheater cheater)
{
// TODO support altcoins, not just bitcoin
var blockRewardBitcoinAddress = cheater.CashCow.GetNewAddress();
try
{
if (request.BlockCount > 0)
{
cheater.CashCow.GenerateToAddress(request.BlockCount, blockRewardBitcoinAddress);
return Ok(new
{
SuccessMessage = "Mined " + request.BlockCount + " blocks"
});
return Ok(new { SuccessMessage = $"Mined {request.BlockCount} block{(request.BlockCount == 1 ? "" : "s")} " });
}
return BadRequest(new
{
ErrorMessage = "Number of blocks should be > 0"
});
return BadRequest(new { ErrorMessage = "Number of blocks should be at least 1" });
}
catch (Exception e)
{
return BadRequest(new
{
ErrorMessage = e.Message
});
return BadRequest(new { ErrorMessage = e.Message });
}
}
[HttpPost("i/{invoiceId}/expire")]
[CheatModeRoute]
public async Task<IActionResult> TestExpireNow(string invoiceId, [FromServices] Cheater cheater)
public async Task<IActionResult> Expire(string invoiceId, int seconds, [FromServices] Cheater cheater)
{
try
{
await cheater.UpdateInvoiceExpiry(invoiceId, DateTimeOffset.Now);
return Ok(new { SuccessMessage = "Invoice is now expired." });
await cheater.UpdateInvoiceExpiry(invoiceId, TimeSpan.FromSeconds(seconds));
return Ok(new { SuccessMessage = $"Invoice set to expire in {seconds} seconds." });
}
catch (Exception e)
{