Merge pull request #689 from rockstardev/rock-lnsats

Allowing for lightning payment amounts to be displayed in Satoshis
This commit is contained in:
Nicolas Dorier 2019-03-17 12:26:13 +09:00 committed by GitHub
commit 6f50ac50ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 60 additions and 31 deletions

View File

@ -284,6 +284,7 @@ namespace BTCPayServer.Controllers
HtmlTitle = storeBlob.HtmlTitle ?? "BTCPay Invoice", HtmlTitle = storeBlob.HtmlTitle ?? "BTCPay Invoice",
CustomCSSLink = storeBlob.CustomCSS?.AbsoluteUri, CustomCSSLink = storeBlob.CustomCSS?.AbsoluteUri,
CustomLogoLink = storeBlob.CustomLogo?.AbsoluteUri, CustomLogoLink = storeBlob.CustomLogo?.AbsoluteUri,
LightningAmountInSatoshi = storeBlob.LightningAmountInSatoshi,
BtcAddress = paymentMethodDetails.GetPaymentDestination(), BtcAddress = paymentMethodDetails.GetPaymentDestination(),
BtcDue = accounting.Due.ToString(), BtcDue = accounting.Due.ToString(),
OrderAmount = (accounting.TotalDue - accounting.NetworkFee).ToString(), OrderAmount = (accounting.TotalDue - accounting.NetworkFee).ToString(),

View File

@ -348,13 +348,14 @@ namespace BTCPayServer.Controllers
var storeBlob = StoreData.GetStoreBlob(); var storeBlob = StoreData.GetStoreBlob();
var vm = new CheckoutExperienceViewModel(); var vm = new CheckoutExperienceViewModel();
SetCryptoCurrencies(vm, StoreData); SetCryptoCurrencies(vm, StoreData);
vm.SetLanguages(_LangService, storeBlob.DefaultLang);
vm.LightningMaxValue = storeBlob.LightningMaxValue?.ToString() ?? "";
vm.OnChainMinValue = storeBlob.OnChainMinValue?.ToString() ?? "";
vm.RequiresRefundEmail = storeBlob.RequiresRefundEmail;
vm.CustomCSS = storeBlob.CustomCSS?.AbsoluteUri; vm.CustomCSS = storeBlob.CustomCSS?.AbsoluteUri;
vm.CustomLogo = storeBlob.CustomLogo?.AbsoluteUri; vm.CustomLogo = storeBlob.CustomLogo?.AbsoluteUri;
vm.HtmlTitle = storeBlob.HtmlTitle; vm.HtmlTitle = storeBlob.HtmlTitle;
vm.SetLanguages(_LangService, storeBlob.DefaultLang);
vm.RequiresRefundEmail = storeBlob.RequiresRefundEmail;
vm.OnChainMinValue = storeBlob.OnChainMinValue?.ToString() ?? "";
vm.LightningMaxValue = storeBlob.LightningMaxValue?.ToString() ?? "";
vm.LightningAmountInSatoshi = storeBlob.LightningAmountInSatoshi;
return View(vm); return View(vm);
} }
void SetCryptoCurrencies(CheckoutExperienceViewModel vm, Data.StoreData storeData) void SetCryptoCurrencies(CheckoutExperienceViewModel vm, Data.StoreData storeData)
@ -411,13 +412,14 @@ namespace BTCPayServer.Controllers
{ {
return View(model); return View(model);
} }
blob.DefaultLang = model.DefaultLang;
blob.RequiresRefundEmail = model.RequiresRefundEmail;
blob.LightningMaxValue = lightningMaxValue;
blob.OnChainMinValue = onchainMinValue;
blob.CustomLogo = string.IsNullOrWhiteSpace(model.CustomLogo) ? null : new Uri(model.CustomLogo, UriKind.Absolute); blob.CustomLogo = string.IsNullOrWhiteSpace(model.CustomLogo) ? null : new Uri(model.CustomLogo, UriKind.Absolute);
blob.CustomCSS = string.IsNullOrWhiteSpace(model.CustomCSS) ? null : new Uri(model.CustomCSS, UriKind.Absolute); blob.CustomCSS = string.IsNullOrWhiteSpace(model.CustomCSS) ? null : new Uri(model.CustomCSS, UriKind.Absolute);
blob.HtmlTitle = string.IsNullOrWhiteSpace(model.HtmlTitle) ? null : model.HtmlTitle; blob.HtmlTitle = string.IsNullOrWhiteSpace(model.HtmlTitle) ? null : model.HtmlTitle;
blob.DefaultLang = model.DefaultLang;
blob.RequiresRefundEmail = model.RequiresRefundEmail;
blob.OnChainMinValue = onchainMinValue;
blob.LightningMaxValue = lightningMaxValue;
blob.LightningAmountInSatoshi = model.LightningAmountInSatoshi;
if (StoreData.SetStoreBlob(blob)) if (StoreData.SetStoreBlob(blob))
{ {
needUpdate = true; needUpdate = true;

View File

@ -349,10 +349,11 @@ namespace BTCPayServer.Data
public List<RateRule_Obsolete> RateRules { get; set; } = new List<RateRule_Obsolete>(); public List<RateRule_Obsolete> RateRules { get; set; } = new List<RateRule_Obsolete>();
public string PreferredExchange { get; set; } public string PreferredExchange { get; set; }
[JsonConverter(typeof(CurrencyValueJsonConverter))]
public CurrencyValue LightningMaxValue { get; set; }
[JsonConverter(typeof(CurrencyValueJsonConverter))] [JsonConverter(typeof(CurrencyValueJsonConverter))]
public CurrencyValue OnChainMinValue { get; set; } public CurrencyValue OnChainMinValue { get; set; }
[JsonConverter(typeof(CurrencyValueJsonConverter))]
public CurrencyValue LightningMaxValue { get; set; }
public bool LightningAmountInSatoshi { get; set; }
[JsonConverter(typeof(UriJsonConverter))] [JsonConverter(typeof(UriJsonConverter))]
public Uri CustomLogo { get; set; } public Uri CustomLogo { get; set; }

View File

@ -20,6 +20,7 @@ namespace BTCPayServer.Models.InvoicingModels
public string CustomCSSLink { get; set; } public string CustomCSSLink { get; set; }
public string CustomLogoLink { get; set; } public string CustomLogoLink { get; set; }
public string DefaultLang { get; set; } public string DefaultLang { get; set; }
public bool LightningAmountInSatoshi { get; set; }
public List<AvailableCrypto> AvailableCryptos { get; set; } = new List<AvailableCrypto>(); public List<AvailableCrypto> AvailableCryptos { get; set; } = new List<AvailableCrypto>();
public bool IsModal { get; set; } public bool IsModal { get; set; }
public bool IsLightning { get; set; } public bool IsLightning { get; set; }

View File

@ -25,19 +25,6 @@ namespace BTCPayServer.Models.StoreViewModels
public string DefaultPaymentMethod { get; set; } public string DefaultPaymentMethod { get; set; }
[Display(Name = "Default language on checkout")] [Display(Name = "Default language on checkout")]
public string DefaultLang { get; set; } public string DefaultLang { get; set; }
[Display(Name = "Do not propose lightning payment if value of the invoice is above...")]
[MaxLength(20)]
public string LightningMaxValue { get; set; }
[Display(Name = "Requires a refund email")]
public bool RequiresRefundEmail
{
get; set;
}
[Display(Name = "Do not propose on chain payment if the value of the invoice is below...")]
[MaxLength(20)]
public string OnChainMinValue { get; set; }
[Display(Name = "Link to a custom CSS stylesheet")] [Display(Name = "Link to a custom CSS stylesheet")]
[Uri] [Uri]
@ -49,9 +36,23 @@ namespace BTCPayServer.Models.StoreViewModels
[Display(Name = "Custom HTML title to display on Checkout page")] [Display(Name = "Custom HTML title to display on Checkout page")]
public string HtmlTitle { get; set; } public string HtmlTitle { get; set; }
[Display(Name = "Requires a refund email")]
public bool RequiresRefundEmail { get; set; }
[Display(Name = "Do not propose on chain payment if the value of the invoice is below...")]
[MaxLength(20)]
public string OnChainMinValue { get; set; }
[Display(Name = "Do not propose lightning payment if value of the invoice is above...")]
[MaxLength(20)]
public string LightningMaxValue { get; set; }
[Display(Name = "Display lightning payment amounts in Satoshis")]
public bool LightningAmountInSatoshi { get; set; }
public void SetLanguages(LanguageService langService, string defaultLang) public void SetLanguages(LanguageService langService, string defaultLang)
{ {
defaultLang = langService.GetLanguages().Any(language => language.Code == defaultLang)? defaultLang : "en"; defaultLang = langService.GetLanguages().Any(language => language.Code == defaultLang) ? defaultLang : "en";
var choices = langService.GetLanguages().Select(o => new Format() { Name = o.DisplayName, Value = o.Code }).ToArray(); var choices = langService.GetLanguages().Select(o => new Format() { Name = o.DisplayName, Value = o.Code }).ToArray();
var chosen = choices.FirstOrDefault(f => f.Value == defaultLang) ?? choices.FirstOrDefault(); var chosen = choices.FirstOrDefault(f => f.Value == defaultLang) ?? choices.FirstOrDefault();
Languages = new SelectList(choices, nameof(chosen.Value), nameof(chosen.Name), chosen); Languages = new SelectList(choices, nameof(chosen.Value), nameof(chosen.Name), chosen);

View File

@ -48,7 +48,7 @@
<div class="paywithRowRight cursorPointer" onclick="openPaymentMethodDialog()"> <div class="paywithRowRight cursorPointer" onclick="openPaymentMethodDialog()">
<span class="payment__currencies "> <span class="payment__currencies ">
<img v-bind:src="srvModel.cryptoImage" /> <img v-bind:src="srvModel.cryptoImage" />
<span>{{srvModel.paymentMethodName}} ({{srvModel.cryptoCode}})</span> <span>{{srvModel.paymentMethodName}} ({{srvModel.cryptoCodeSrv}})</span>
<span v-show="srvModel.isLightning">&#9889;</span> <span v-show="srvModel.isLightning">&#9889;</span>
<span class="clickable_indicator fa fa-angle-right"></span> <span class="clickable_indicator fa fa-angle-right"></span>
</span> </span>
@ -73,7 +73,7 @@
{ {
<div class="payment__currencies_noborder"> <div class="payment__currencies_noborder">
<img v-bind:src="srvModel.cryptoImage" /> <img v-bind:src="srvModel.cryptoImage" />
<span>{{srvModel.paymentMethodName}} ({{srvModel.cryptoCode}})</span> <span>{{srvModel.paymentMethodName}} ({{srvModel.cryptoCodeSrv}})</span>
<span v-show="srvModel.isLightning">&#9889;</span> <span v-show="srvModel.isLightning">&#9889;</span>
</div> </div>
} }
@ -101,7 +101,7 @@
</div> </div>
<div class="single-item-order__right__ex-rate" v-if="srvModel.orderAmountFiat"> <div class="single-item-order__right__ex-rate" v-if="srvModel.orderAmountFiat">
1 {{ srvModel.cryptoCode }} = {{ srvModel.rate }} 1 {{ srvModel.cryptoCodeSrv }} = {{ srvModel.rate }}
</div> </div>
</div> </div>

View File

@ -176,6 +176,7 @@
scanDisplayQr: "", scanDisplayQr: "",
expiringSoon: false, expiringSoon: false,
isModal: srvModel.isModal, isModal: srvModel.isModal,
lightningAmountInSatoshi: srvModel.lightningAmountInSatoshi,
selectedThirdPartyProcessor: "" selectedThirdPartyProcessor: ""
} }
}); });

View File

@ -42,6 +42,12 @@
<label asp-for="RequiresRefundEmail"></label> <label asp-for="RequiresRefundEmail"></label>
<input asp-for="RequiresRefundEmail" type="checkbox" class="form-check" /> <input asp-for="RequiresRefundEmail" type="checkbox" class="form-check" />
</div> </div>
<div class="form-group">
<label asp-for="OnChainMinValue"></label>
<input asp-for="OnChainMinValue" class="form-control" />
<span asp-validation-for="OnChainMinValue" class="text-danger"></span>
<p class="form-text text-muted">Example: 5.50 USD</p>
</div>
<div class="form-group"> <div class="form-group">
<label asp-for="LightningMaxValue"></label> <label asp-for="LightningMaxValue"></label>
<input asp-for="LightningMaxValue" class="form-control" /> <input asp-for="LightningMaxValue" class="form-control" />
@ -49,11 +55,10 @@
<p class="form-text text-muted">Example: 5.50 USD</p> <p class="form-text text-muted">Example: 5.50 USD</p>
</div> </div>
<div class="form-group"> <div class="form-group">
<label asp-for="OnChainMinValue"></label> <label asp-for="LightningAmountInSatoshi"></label>
<input asp-for="OnChainMinValue" class="form-control" /> <input asp-for="LightningAmountInSatoshi" type="checkbox" class="form-check" />
<span asp-validation-for="OnChainMinValue" class="text-danger"></span>
<p class="form-text text-muted">Example: 5.50 USD</p>
</div> </div>
<br />
<button name="command" type="submit" class="btn btn-primary" value="Save">Save</button> <button name="command" type="submit" class="btn btn-primary" value="Save">Save</button>
</form> </form>
</div> </div>

View File

@ -90,10 +90,27 @@ function onDataCallback(jsonData) {
checkoutCtrl.lndModel = null; checkoutCtrl.lndModel = null;
} }
// displaying satoshis for lightning payments
jsonData.cryptoCodeSrv = jsonData.cryptoCode;
if (jsonData.isLightning && checkoutCtrl.lightningAmountInSatoshi && jsonData.cryptoCode === "BTC") {
var SATOSHIME = 100000000;
jsonData.cryptoCode = "Sats";
jsonData.btcDue = numberFormatted(jsonData.btcDue * SATOSHIME);
jsonData.btcPaid = numberFormatted(jsonData.btcPaid * SATOSHIME);
jsonData.networkFee = numberFormatted(jsonData.networkFee * SATOSHIME);
jsonData.orderAmount = numberFormatted(jsonData.orderAmount * SATOSHIME);
}
// updating ui // updating ui
checkoutCtrl.srvModel = jsonData; checkoutCtrl.srvModel = jsonData;
} }
function numberFormatted(x) {
var parts = x.toString().split(".");
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, " ");
return parts.join(".");
}
function fetchStatus() { function fetchStatus() {
$.ajax({ $.ajax({
url: window.location.pathname + "/status?invoiceId=" + srvModel.invoiceId + "&paymentMethodId=" + srvModel.paymentMethodId, url: window.location.pathname + "/status?invoiceId=" + srvModel.invoiceId + "&paymentMethodId=" + srvModel.paymentMethodId,