Compare commits

..

1 Commits

Author SHA1 Message Date
aa295d121e Fix sqlite madness
* Need to reference Microsoft.EntityFrameworkCore.Design else you can't generate migrations
* fix design time migrations issues
* update snapshot
```
Your startup project 'BTCPayServer.Data' doesn't reference Microsoft.EntityFrameworkCore.Design. This package is required for the Entity Framework Core Tools to work. Ensure your startup project is c
orrect, install the package, and try again.
```
*
2020-01-19 13:49:11 +01:00
33 changed files with 76 additions and 227 deletions

1
.gitignore vendored
View File

@ -293,4 +293,3 @@ BTCPayServer/wwwroot/bundles/*
!BTCPayServer/wwwroot/bundles/.gitignore
.vscode
BTCPayServer/testpwd

View File

@ -31,7 +31,21 @@ namespace BTCPayServer
CryptoImagePath = "imlegacy/liquid.png",
DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType),
CoinType = NetworkType == NetworkType.Mainnet ? new KeyPath("1776'") : new KeyPath("1'"),
SupportRBF = true
SupportRBF = true,
//https://github.com/spesmilo/electrum/blob/11733d6bc271646a00b69ff07657119598874da4/electrum/constants.py
ElectrumMapping = NetworkType == NetworkType.Mainnet
? new Dictionary<uint, DerivationType>()
{
{0x0488b21eU, DerivationType.Legacy }, // xpub
{0x049d7cb2U, DerivationType.SegwitP2SH }, // ypub
{0x4b24746U, DerivationType.Segwit }, //zpub
}
: new Dictionary<uint, DerivationType>()
{
{0x043587cfU, DerivationType.Legacy},
{0x044a5262U, DerivationType.SegwitP2SH},
{0x045f1cf6U, DerivationType.Segwit}
},
});
}
}

View File

@ -30,29 +30,21 @@ namespace BTCPayServer
CryptoImagePath = "imlegacy/liquid-tether.svg",
DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType),
CoinType = NetworkType == NetworkType.Mainnet ? new KeyPath("1776'") : new KeyPath("1'"),
SupportRBF = true
});
Add(new ElementsBTCPayNetwork()
{
CryptoCode = "ETB",
NetworkCryptoCode = "LBTC",
DefaultRateRules = new[]
{
"ETB_X = ETB_BTC * BTC_X",
"ETB_BTC = bitpay(ETB_BTC)"
},
Divisibility = 2,
AssetId = new uint256("ce091c998b83c78bb71a632313ba3760f1763d9cfcffae02258ffa9865a37bd2"),
DisplayName = "Ethiopian Birr",
BlockExplorerLink = NetworkType == NetworkType.Mainnet ? "https://blockstream.info/liquid/tx/{0}" : "https://blockstream.info/testnet/liquid/tx/{0}",
NBXplorerNetwork = nbxplorerNetwork,
UriScheme = "liquidnetwork",
CryptoImagePath = "imlegacy/etb.png",
DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType),
CoinType = NetworkType == NetworkType.Mainnet ? new KeyPath("1776'") : new KeyPath("1'"),
SupportRBF = true
SupportRBF = true,
//https://github.com/spesmilo/electrum/blob/11733d6bc271646a00b69ff07657119598874da4/electrum/constants.py
ElectrumMapping = NetworkType == NetworkType.Mainnet
? new Dictionary<uint, DerivationType>()
{
{0x0488b21eU, DerivationType.Legacy }, // xpub
{0x049d7cb2U, DerivationType.SegwitP2SH }, // ypub
{0x4b24746U, DerivationType.Segwit }, //zpub
}
: new Dictionary<uint, DerivationType>()
{
{0x043587cfU, DerivationType.Legacy},
{0x044a5262U, DerivationType.SegwitP2SH},
{0x045f1cf6U, DerivationType.Segwit}
}
});
}
}

View File

@ -6,16 +6,16 @@ using NBXplorer.Models;
namespace BTCPayServer
{
public class ElementsBTCPayNetwork : BTCPayNetwork
public class ElementsBTCPayNetwork:BTCPayNetwork
{
public string NetworkCryptoCode { get; set; }
public uint256 AssetId { get; set; }
public override bool ReadonlyWallet { get; set; } = true;
public int Divisibility { get; set; } = 8;
public override IEnumerable<(MatchedOutput matchedOutput, OutPoint outPoint)> GetValidOutputs(
NewTransactionEvent evtOutputs)
public override IEnumerable<(MatchedOutput matchedOutput, OutPoint outPoint)> GetValidOutputs(NewTransactionEvent evtOutputs)
{
return evtOutputs.Outputs.Where(output =>
return evtOutputs.Outputs.Where(output =>
output.Value is AssetMoney assetMoney && assetMoney.AssetId == AssetId).Select(output =>
{
var outpoint = new OutPoint(evtOutputs.TransactionData.TransactionHash, output.Index);
@ -23,7 +23,7 @@ namespace BTCPayServer
});
}
public override string GenerateBIP21(string cryptoInfoAddress, Money cryptoInfoDue)
public override string GenerateBIP21(string cryptoInfoAddress, string cryptoInfoDue)
{
return $"{base.GenerateBIP21(cryptoInfoAddress, cryptoInfoDue)}&assetid={AssetId}";
}

View File

@ -10,7 +10,6 @@ namespace BTCPayServer
{
CryptoCode = "XMR",
DisplayName = "Monero",
Divisibility = 12,
BlockExplorerLink =
NetworkType == NetworkType.Mainnet
? "https://www.exploremonero.com/transaction/{0}"

View File

@ -113,9 +113,9 @@ namespace BTCPayServer
});
}
public virtual string GenerateBIP21(string cryptoInfoAddress, Money cryptoInfoDue)
public virtual string GenerateBIP21(string cryptoInfoAddress, string cryptoInfoDue)
{
return $"{UriScheme}:{cryptoInfoAddress}?amount={cryptoInfoDue.ToString(false, true)}";
return $"{UriScheme}:{cryptoInfoAddress}?amount={cryptoInfoDue}";
}
}
@ -124,7 +124,7 @@ namespace BTCPayServer
public string CryptoCode { get; internal set; }
public string BlockExplorerLink { get; internal set; }
public string DisplayName { get; set; }
public int Divisibility { get; set; } = 8;
[Obsolete("Should not be needed")]
public bool IsBTC
{

View File

@ -432,13 +432,6 @@ namespace BTCPayServer.Tests
//let's test quickly the receive wallet page
s.Driver.FindElement(By.Id("Wallets")).Click();
s.Driver.FindElement(By.LinkText("Manage")).Click();
s.Driver.FindElement(By.Id("WalletSend")).Click();
s.Driver.ScrollTo(By.Id("SendMenu"));
s.Driver.FindElement(By.Id("SendMenu")).ForceClick();
//you cant use the Sign with NBX option without saving private keys when generating the wallet.
Assert.DoesNotContain("nbx-seed", s.Driver.PageSource);
s.Driver.FindElement(By.Id("WalletReceive")).Click();
//generate a receiving address
s.Driver.FindElement(By.CssSelector("button[value=generate-new-address]")).Click();
@ -479,19 +472,16 @@ namespace BTCPayServer.Tests
var address = invoice.EntityToDTO().Addresses["BTC"];
//wallet should have been imported to bitcoin core wallet in watch only mode.
var result = await s.Server.ExplorerNode.GetAddressInfoAsync(BitcoinAddress.Create(address, Network.RegTest));
Assert.True(result.IsWatchOnly);
s.GoToStore(storeId.storeId);
var mnemonic = s.GenerateWallet("BTC", "", true, true);
//lets import and save private keys
var root = new Mnemonic(mnemonic).DeriveExtKey();
invoiceId = s.CreateInvoice(storeId.storeId);
invoice = await s.Server.PayTester.InvoiceRepository.GetInvoice( invoiceId);
address = invoice.EntityToDTO().Addresses["BTC"];
result = await s.Server.ExplorerNode.GetAddressInfoAsync(BitcoinAddress.Create(address, Network.RegTest));
//spendable from bitcoin core wallet!
Assert.False(result.IsWatchOnly);
var tx = s.Server.ExplorerNode.SendToAddress(BitcoinAddress.Create(address, Network.RegTest), Money.Coins(3.0m));
s.Server.ExplorerNode.Generate(1);
@ -548,25 +538,7 @@ namespace BTCPayServer.Tests
checkboxElement.Click();
}
}
SignWith(mnemonic);
s.Driver.FindElement(By.Id("Wallets")).Click();
s.Driver.FindElement(By.LinkText("Manage")).Click();
s.Driver.FindElement(By.Id("WalletSend")).Click();
var jack = new Key().PubKey.Hash.GetAddress(Network.RegTest);
SetTransactionOutput(0, jack, 0.01m);
s.Driver.ScrollTo(By.Id("SendMenu"));
s.Driver.FindElement(By.Id("SendMenu")).ForceClick();
s.Driver.FindElement(By.CssSelector("button[value=nbx-seed]")).Click();
Assert.Contains(jack.ToString(), s.Driver.PageSource);
Assert.Contains("0.01000000", s.Driver.PageSource);
s.Driver.FindElement(By.CssSelector("button[value=broadcast]")).ForceClick();
Assert.Equal(walletTransactionLink, s.Driver.Url);
}
}
}

View File

@ -2887,18 +2887,6 @@ noninventoryitem:
return name;
}
[Fact(Timeout = TestTimeout)]
[Trait("Fast", "Fast")]
public async Task CanCreateSqlitedb()
{
if (File.Exists("temp.db"))
File.Delete("temp.db");
// This test sqlite can migrate
var builder = new DbContextOptionsBuilder<ApplicationDbContext>();
builder.UseSqlite("Data Source=temp.db");
await new ApplicationDbContext(builder.Options).Database.MigrateAsync();
}
[Fact(Timeout = TestTimeout)]
[Trait("Fast", "Fast")]
public void CheckRatesProvider()

View File

@ -76,7 +76,7 @@ services:
- customer_lnd
- merchant_lnd
nbxplorer:
image: nicolasdorier/nbxplorer:2.1.8
image: nicolasdorier/nbxplorer:2.1.5
restart: unless-stopped
ports:
- "32838:32838"

View File

@ -141,7 +141,6 @@ namespace BTCPayServer.Configuration
ExternalServices.Load(net.CryptoCode, conf);
}
ExternalServices.LoadNonCryptoServices(conf);
Logs.Configuration.LogInformation("Supported chains: " + String.Join(',', supportedChains.ToArray()));
var services = conf.GetOrDefault<string>("externalservices", null);

View File

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using BTCPayServer.Controllers;
@ -78,7 +77,7 @@ namespace BTCPayServer.Configuration
}
}
if (new []{ExternalServiceTypes.Charge, ExternalServiceTypes.RTL, ExternalServiceTypes.Spark, ExternalServiceTypes.Configurator}.Contains(serviceType))
if (serviceType == ExternalServiceTypes.Charge || serviceType == ExternalServiceTypes.RTL || serviceType == ExternalServiceTypes.Spark)
{
// Read access key from cookie file
if (connectionString.CookieFilePath != null)

View File

@ -41,20 +41,11 @@ namespace BTCPayServer.Configuration
$"lightning charge server: 'type=charge;server=https://charge.example.com;cookiefilepath=/root/.charge/.cookie'" + Environment.NewLine +
"Error: {1}",
"C-Lightning (Charge server)");
}
public void LoadNonCryptoServices(IConfiguration configuration)
{
Load(configuration, null, "configurator", ExternalServiceTypes.Configurator, "Invalid setting {0}, " + Environment.NewLine +
$"configurator: 'passwordfile=/etc/configurator/password'" + Environment.NewLine +
"Error: {1}",
"Configurator");
}
void Load(IConfiguration configuration, string cryptoCode, string serviceName, ExternalServiceTypes type, string errorMessage, string displayName)
{
var setting = $"{(!string.IsNullOrEmpty(cryptoCode)? $"{cryptoCode}.": string.Empty)}external.{serviceName}";
var setting = $"{cryptoCode}.external.{serviceName}";
var connStr = configuration.GetOrDefault<string>(setting, string.Empty);
if (connStr.Length != 0)
{
@ -74,11 +65,8 @@ namespace BTCPayServer.Configuration
public ExternalService GetService(string serviceName, string cryptoCode)
{
return this.FirstOrDefault(o =>
(cryptoCode == null && o.CryptoCode == null) ||
(o.CryptoCode != null && o.CryptoCode.Equals(cryptoCode, StringComparison.OrdinalIgnoreCase))
&&
o.ServiceName.Equals(serviceName, StringComparison.OrdinalIgnoreCase));
return this.FirstOrDefault(o => o.CryptoCode.Equals(cryptoCode, StringComparison.OrdinalIgnoreCase) &&
o.ServiceName.Equals(serviceName, StringComparison.OrdinalIgnoreCase));
}
}
@ -100,7 +88,6 @@ namespace BTCPayServer.Configuration
RTL,
Charge,
P2P,
RPC,
Configurator
RPC
}
}

View File

@ -104,6 +104,7 @@ namespace BTCPayServer.Controllers
cryptoPayment.Paid = _CurrencyNameTable.DisplayFormatCurrency(accounting.CryptoPaid.ToDecimal(MoneyUnit.BTC), paymentMethodId.CryptoCode);
cryptoPayment.Overpaid = _CurrencyNameTable.DisplayFormatCurrency(accounting.OverpaidHelper.ToDecimal(MoneyUnit.BTC), paymentMethodId.CryptoCode);
var paymentMethodDetails = data.GetPaymentMethodDetails();
cryptoPayment.Address = paymentMethodDetails.GetPaymentDestination();
cryptoPayment.Rate = ExchangeRate(data);
model.CryptoPayments.Add(cryptoPayment);
}

View File

@ -528,12 +528,10 @@ namespace BTCPayServer.Controllers
return null;
}
[Route("server/services/{serviceName}/{cryptoCode?}")]
[Route("server/services/{serviceName}/{cryptoCode}")]
public async Task<IActionResult> Service(string serviceName, string cryptoCode, bool showQR = false, uint? nonce = null)
{
if (!string.IsNullOrEmpty(cryptoCode) && !_dashBoard.IsFullySynched(cryptoCode, out _))
if (!_dashBoard.IsFullySynched(cryptoCode, out _))
{
TempData[WellKnownTempData.ErrorMessage] = $"{cryptoCode} is not fully synched";
return RedirectToAction(nameof(Services));
@ -544,7 +542,6 @@ namespace BTCPayServer.Controllers
try
{
if (service.Type == ExternalServiceTypes.P2P)
{
return View("P2PService", new LightningWalletServices()
@ -598,14 +595,6 @@ namespace BTCPayServer.Controllers
case ExternalServiceTypes.LNDGRPC:
case ExternalServiceTypes.LNDRest:
return LndServices(service, connectionString, nonce);
case ExternalServiceTypes.Configurator:
return View("ConfiguratorService",
new LightningWalletServices()
{
ShowQR = showQR,
WalletName = service.ServiceName,
ServiceLink = $"{connectionString.Server}?password={connectionString.AccessKey}"
});
default:
throw new NotSupportedException(service.Type.ToString());
}

View File

@ -7,7 +7,6 @@ using BTCPayServer.ModelBinders;
using BTCPayServer.Models.WalletViewModels;
using Microsoft.AspNetCore.Mvc;
using NBitcoin;
using NBXplorer;
using NBXplorer.Models;
namespace BTCPayServer.Controllers
@ -57,9 +56,6 @@ namespace BTCPayServer.Controllers
{
var network = NetworkProvider.GetNetwork<BTCPayNetwork>(walletId.CryptoCode);
vm.CryptoCode = network.CryptoCode;
vm.NBXSeedAvailable = await CanUseHotWallet() && !string.IsNullOrEmpty(await ExplorerClientProvider.GetExplorerClient(network)
.GetMetadataAsync<string>(GetDerivationSchemeSettings(walletId).AccountDerivation,
WellknownMetadataKeys.Mnemonic));
if (await vm.GetPSBT(network.NBitcoinNetwork) is PSBT psbt)
{
vm.Decoded = psbt.ToString();
@ -97,7 +93,7 @@ namespace BTCPayServer.Controllers
case "vault":
return ViewVault(walletId, psbt);
case "ledger":
return ViewWalletSendLedger(walletId, psbt);
return ViewWalletSendLedger(psbt);
case "update":
var derivationSchemeSettings = GetDerivationSchemeSettings(walletId);
psbt = await UpdatePSBT(derivationSchemeSettings, psbt, network);
@ -110,16 +106,6 @@ namespace BTCPayServer.Controllers
return RedirectToWalletPSBT(walletId, psbt, vm.FileName);
case "seed":
return SignWithSeed(walletId, psbt.ToBase64());
case "nbx-seed":
var derivationScheme = GetDerivationSchemeSettings(walletId);
var extKey = await ExplorerClientProvider.GetExplorerClient(network)
.GetMetadataAsync<string>(derivationScheme.AccountDerivation, WellknownMetadataKeys.MasterHDKey);
return await SignWithSeed(walletId, new SignWithSeedViewModel()
{
SeedOrKey = extKey,
PSBT = psbt.ToBase64()
});
case "broadcast":
{
return await WalletPSBTReady(walletId, psbt.ToBase64());

View File

@ -29,7 +29,6 @@ using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Options;
using NBitcoin;
using NBitcoin.DataEncoders;
using NBXplorer;
using NBXplorer.DerivationStrategy;
using NBXplorer.Models;
using Newtonsoft.Json;
@ -55,7 +54,6 @@ namespace BTCPayServer.Controllers
private readonly BTCPayWalletProvider _walletProvider;
private readonly WalletReceiveStateService _WalletReceiveStateService;
private readonly EventAggregator _EventAggregator;
private readonly SettingsRepository _settingsRepository;
public RateFetcher RateFetcher { get; }
CurrencyNameTable _currencyTable;
@ -72,8 +70,7 @@ namespace BTCPayServer.Controllers
IFeeProviderFactory feeRateProvider,
BTCPayWalletProvider walletProvider,
WalletReceiveStateService walletReceiveStateService,
EventAggregator eventAggregator,
SettingsRepository settingsRepository)
EventAggregator eventAggregator)
{
_currencyTable = currencyTable;
Repository = repo;
@ -89,7 +86,6 @@ namespace BTCPayServer.Controllers
_walletProvider = walletProvider;
_WalletReceiveStateService = walletReceiveStateService;
_EventAggregator = eventAggregator;
_settingsRepository = settingsRepository;
}
// Borrowed from https://github.com/ManageIQ/guides/blob/master/labels.md
@ -372,15 +368,6 @@ namespace BTCPayServer.Controllers
return RedirectToAction(nameof(WalletReceive), new {walletId});
}
private async Task<bool> CanUseHotWallet()
{
var isAdmin = (await _authorizationService.AuthorizeAsync(User, Policies.CanModifyServerSettings.Key)).Succeeded;
if (isAdmin)
return true;
var policies = await _settingsRepository.GetSettingAsync<PoliciesSettings>();
return policies?.AllowHotWalletForAll is true;
}
[HttpGet]
[Route("{walletId}/send")]
public async Task<IActionResult> WalletSend(
@ -418,9 +405,6 @@ namespace BTCPayServer.Controllers
var feeProvider = _feeRateProvider.CreateFeeProvider(network);
var recommendedFees = feeProvider.GetFeeRateAsync();
var balance = _walletProvider.GetWallet(network).GetBalance(paymentMethod.AccountDerivation);
model.NBXSeedAvailable = await CanUseHotWallet() && !string.IsNullOrEmpty(await ExplorerClientProvider.GetExplorerClient(network)
.GetMetadataAsync<string>(GetDerivationSchemeSettings(walletId).AccountDerivation,
WellknownMetadataKeys.Mnemonic));
model.CurrentBalance = await balance;
model.RecommendedSatoshiPerByte = (int)(await recommendedFees).GetFee(1).Satoshi;
model.FeeSatoshiPerByte = model.RecommendedSatoshiPerByte;
@ -570,17 +554,8 @@ namespace BTCPayServer.Controllers
{
case "vault":
return ViewVault(walletId, psbt.PSBT);
case "nbx-seed":
var extKey = await ExplorerClientProvider.GetExplorerClient(network)
.GetMetadataAsync<string>(derivationScheme.AccountDerivation, WellknownMetadataKeys.MasterHDKey, cancellation);
return await SignWithSeed(walletId, new SignWithSeedViewModel()
{
SeedOrKey = extKey,
PSBT = psbt.PSBT.ToBase64()
});
case "ledger":
return ViewWalletSendLedger(walletId, psbt.PSBT, psbt.ChangeAddress);
return ViewWalletSendLedger(psbt.PSBT, psbt.ChangeAddress);
case "seed":
return SignWithSeed(walletId, psbt.PSBT.ToBase64());
case "analyze-psbt":
@ -641,14 +616,14 @@ namespace BTCPayServer.Controllers
return null;
}
private ViewResult ViewWalletSendLedger(WalletId walletId, PSBT psbt, BitcoinAddress hintChange = null)
private ViewResult ViewWalletSendLedger(PSBT psbt, BitcoinAddress hintChange = null)
{
SetAmbientPSBT(psbt);
return View("WalletSendLedger", new WalletSendLedgerModel()
{
PSBT = psbt.ToBase64(),
HintChange = hintChange?.ToString(),
WebsocketPath = this.Url.Action(nameof(LedgerConnection), new { walletId = walletId.ToString() })
WebsocketPath = this.Url.Action(nameof(LedgerConnection))
});
}
@ -668,7 +643,7 @@ namespace BTCPayServer.Controllers
{
if (!ModelState.IsValid)
{
return View("SignWithSeed", viewModel);
return View(viewModel);
}
var network = NetworkProvider.GetNetwork<BTCPayNetwork>(walletId.CryptoCode);
if (network == null)
@ -691,7 +666,7 @@ namespace BTCPayServer.Controllers
if (!ModelState.IsValid)
{
return View("SignWithSeed", viewModel);
return View(viewModel);
}
ExtKey signingKey = null;
@ -704,7 +679,7 @@ namespace BTCPayServer.Controllers
if (rootedKeyPath == null)
{
ModelState.AddModelError(nameof(viewModel.SeedOrKey), "The master fingerprint and/or account key path of your seed are not set in the wallet settings.");
return View("SignWithSeed", viewModel);
return View(viewModel);
}
// The user gave the root key, let's try to rebase the PSBT, and derive the account private key
if (rootedKeyPath.MasterFingerprint == extKey.GetPublicKey().GetHDFingerPrint())

View File

@ -36,6 +36,7 @@ namespace BTCPayServer.Models.InvoicingModels
public string PaymentMethod { get; set; }
public string Due { get; set; }
public string Paid { get; set; }
public string Address { get; internal set; }
public string Rate { get; internal set; }
public string PaymentUrl { get; internal set; }
public string Overpaid { get; set; }

View File

@ -13,8 +13,6 @@ namespace BTCPayServer.Models.WalletViewModels
public string CryptoCode { get; set; }
public string Decoded { get; set; }
string _FileName;
public bool NBXSeedAvailable { get; set; }
public string FileName
{
get

View File

@ -45,7 +45,5 @@ namespace BTCPayServer.Models.WalletViewModels
public bool SupportRBF { get; set; }
[Display(Name = "Disable RBF")]
public bool DisableRBF { get; set; }
public bool NBXSeedAvailable { get; set; }
}
}

View File

@ -47,7 +47,7 @@ namespace BTCPayServer.Payments.Lightning
var storeBlob = store.GetStoreBlob();
var test = GetNodeInfo(paymentMethod.PreferOnion, supportedPaymentMethod, (BTCPayNetwork)network);
var invoice = paymentMethod.ParentEntity;
var due = Extensions.RoundUp(invoice.ProductInformation.Price / paymentMethod.Rate, network.Divisibility);
var due = Extensions.RoundUp(invoice.ProductInformation.Price / paymentMethod.Rate, 8);
var client = _lightningClientFactory.Create(supportedPaymentMethod.GetLightningUrl(), (BTCPayNetwork)network);
var expiry = invoice.ExpirationTime - DateTimeOffset.UtcNow;
if (expiry < TimeSpan.Zero)

View File

@ -64,6 +64,7 @@ namespace BTCPayServer.Payments
public abstract string SerializePaymentData(BTCPayNetworkBase network, CryptoPaymentData paymentData);
public abstract IPaymentMethodDetails DeserializePaymentMethodDetails(string str);
public abstract ISupportedPaymentMethod DeserializeSupportedPaymentMethod(BTCPayNetworkBase network, JToken value);
public abstract string GetTransactionLink(BTCPayNetworkBase network, string txId);
public abstract string InvoiceViewPaymentPartialName { get; }
}

View File

@ -40,7 +40,6 @@
"BTCPAY_BTCEXTERNALLNDSEEDBACKUP": "../BTCPayServer.Tests/TestData/LndSeedBackup/walletunlock.json",
"BTCPAY_BTCEXTERNALSPARK": "server=/spark/btc/;cookiefile=fake",
"BTCPAY_BTCEXTERNALCHARGE": "server=https://127.0.0.1:53280/mycharge/btc/;cookiefilepath=fake",
"BTCPAY_EXTERNALCONFIGURATOR": "passwordfile=testpwd;server=/configurator",
"BTCPAY_BTCEXPLORERURL": "http://127.0.0.1:32838/",
"BTCPAY_ALLOW-ADMIN-REGISTRATION": "true",
"BTCPAY_DISABLE-REGISTRATION": "false",

View File

@ -847,7 +847,7 @@ namespace BTCPayServer.Services.Invoices
var paid = 0m;
var cryptoPaid = 0.0m;
int precision = Network?.Divisibility ?? 8;
int precision = 8;
var totalDueNoNetworkCost = Money.Coins(Extensions.RoundUp(totalDue, precision));
bool paidEnough = paid >= Extensions.RoundUp(totalDue, precision);
int txRequired = 0;
@ -857,8 +857,8 @@ namespace BTCPayServer.Services.Invoices
.OrderBy(p => p.ReceivedTime)
.Select(_ =>
{
var txFee = _.GetValue(paymentMethods, GetId(), _.NetworkFee, precision);
paid += _.GetValue(paymentMethods, GetId(), null, precision);
var txFee = _.GetValue(paymentMethods, GetId(), _.NetworkFee);
paid += _.GetValue(paymentMethods, GetId());
if (!paidEnough)
{
totalDue += txFee;
@ -991,18 +991,18 @@ namespace BTCPayServer.Services.Invoices
#pragma warning restore CS0618
return this;
}
internal decimal GetValue(PaymentMethodDictionary paymentMethods, PaymentMethodId paymentMethodId, decimal? value, int precision)
internal decimal GetValue(PaymentMethodDictionary paymentMethods, PaymentMethodId paymentMethodId, decimal? value = null)
{
value = value ?? this.GetCryptoPaymentData().GetValue();
var to = paymentMethodId;
var from = this.GetPaymentMethodId();
if (to == from)
return decimal.Round(value.Value, precision);
return decimal.Round(value.Value, 8);
var fromRate = paymentMethods[from].Rate;
var toRate = paymentMethods[to].Rate;
var fiatValue = fromRate * decimal.Round(value.Value, precision);
var fiatValue = fromRate * decimal.Round(value.Value, 8);
var otherCurrencyValue = toRate == 0 ? 0.0m : fiatValue / toRate;
return otherCurrencyValue;
}

View File

@ -96,7 +96,7 @@ namespace BTCPayServer.Services.Rates
foreach (var network in new BTCPayNetworkProvider(NetworkType.Mainnet).GetAll())
{
AddCurrency(_CurrencyProviders, network.CryptoCode, network.Divisibility, network.CryptoCode);
AddCurrency(_CurrencyProviders, network.CryptoCode, 8, network.CryptoCode);
}
}
return _CurrencyProviders.TryGet(currency.ToUpperInvariant());
@ -180,7 +180,7 @@ namespace BTCPayServer.Services.Rates
if (!dico.TryAdd(network.CryptoCode, new CurrencyData()
{
Code = network.CryptoCode,
Divisibility = network.Divisibility,
Divisibility = 8,
Name = network.CryptoCode,
Crypto = true
}))

View File

@ -3,11 +3,12 @@
<div class="row">
<div class="col-md-12 invoice-payments">
<h3>Current status</h3>
<h3>Paid summary</h3>
<table class="table table-sm table-responsive-md">
<thead class="thead-inverse">
<tr>
<th>Payment method</th>
<th>Address</th>
<th class="text-right">Rate</th>
<th class="text-right">Paid</th>
<th class="text-right">Due</th>
@ -22,6 +23,9 @@
{
<tr>
<td>@payment.PaymentMethod</td>
<td title="@payment.Address">
<span class="text-truncate d-block" style="max-width: 400px">@payment.Address</span>
</td>
<td class="text-right">@payment.Rate</td>
<td class="text-right">@payment.Paid</td>
<td class="text-right">@payment.Due</td>

View File

@ -1,33 +0,0 @@
@model LightningWalletServices
@{
ViewData.SetActivePageAndTitle(ServerNavPages.Services);
}
<h4>BTCPay Server Configurator</h4>
<partial name="_StatusMessage" />
<div class="row">
<div class="col-md-6">
<div asp-validation-summary="All" class="text-danger"></div>
</div>
</div>
<div class="row">
<div class="col-md-8">
<div class="form-group">
<p>
<span>This page exposes information to use the configured BTCPay Server Configurator to modify this setup.</span>
</p>
</div>
<a href="@Model.ServiceLink" target="_blank" class="form-group">
<label>Service</label>
<input asp-for="ServiceLink" readonly class="form-control" />
</a>
</div>
</div>
@section Scripts {
@await Html.PartialAsync("_ValidationScriptsPartial")
}

View File

@ -29,7 +29,7 @@
</tr>
</thead>
<tbody>
@foreach (var s in Model.ExternalServices.Where(service => !string.IsNullOrEmpty(service.CryptoCode)))
@foreach (var s in Model.ExternalServices)
{
<tr>
<td>@s.CryptoCode</td>
@ -52,7 +52,7 @@
</div>
</div>
@if (Model.OtherExternalServices.Count != 0 || Model.ExternalServices.Any(service => string.IsNullOrEmpty(service.CryptoCode)))
@if (Model.OtherExternalServices.Count != 0)
{
<div class="row">
<div class="col-md-8">
@ -69,15 +69,6 @@
</tr>
</thead>
<tbody>
@foreach (var s in Model.ExternalServices.Where(service => string.IsNullOrEmpty(service.CryptoCode)))
{
<tr>
<td>@s.DisplayName</td>
<td style="text-align: right">
<a asp-action="Service" asp-route-serviceName="@s.ServiceName">See information</a>
</td>
</tr>
}
@foreach (var s in Model.OtherExternalServices)
{
<tr>

View File

@ -19,7 +19,7 @@
<div class="form-group">
<h5>Scripting</h5>
<p>Rate script allows you to express precisely how you want to calculate rates for currency pairs.</p>
<p>We are retrieving the rate of each exchange either directly, via <a href="https://www.coingecko.com/" target="_blank">CoinGecko (free)</a>.</p>
<p>We are retrieving the rate of each exchange either directly, via <a href="https://www.coingecko.com/" target="_blank">CoinGecko (free)</a> or <a href="https://bitcoinaverage.com/" target="_blank">BitcoinAverage (commercial)</a></p>
<div class="accordion" id="accordion-info">
<div class="card">
<div class="card-header" id="direct-header">

View File

@ -30,7 +30,6 @@
<div class="form-group">
<form method="post" asp-action="WalletPSBT">
<input type="hidden" asp-for="CryptoCode" />
<input type="hidden" asp-for="NBXSeedAvailable" />
<input type="hidden" asp-for="PSBT" />
<input type="hidden" asp-for="FileName" />
<div class="dropdown d-inline-block" style="margin-top:16px;">
@ -44,10 +43,6 @@
@if (Model.CryptoCode == "BTC") {
<button name="command" type="submit" class="dropdown-item" value="vault">... the vault (preview)</button>
}
@if (Model.NBXSeedAvailable)
{
<button name="command" type="submit" class="dropdown-item" value="nbx-seed">... the seed saved in NBXplorer</button>
}
</div>
</div>
<div class="dropdown d-inline-block">

View File

@ -10,7 +10,6 @@
<div class="@(Model.Outputs.Count==1? "col-lg-6 transaction-output-form": "col-lg-8")">
<form method="post">
<input type="hidden" asp-for="Divisibility" />
<input type="hidden" asp-for="NBXSeedAvailable" />
<input type="hidden" asp-for="Fiat" />
<input type="hidden" asp-for="Rate" />
<input type="hidden" asp-for="CurrentBalance" />
@ -156,10 +155,6 @@
@if (Model.CryptoCode == "BTC") {
<button name="command" type="submit" class="dropdown-item" value="vault">... the vault (preview)</button>
}
@if (Model.NBXSeedAvailable)
{
<button name="command" type="submit" class="dropdown-item" value="nbx-seed">... the seed saved in NBXplorer</button>
}
</div>
</div>
<button type="submit" name="command" value="add-output" class="ml-1 btn btn-secondary">Add another destination </button>

View File

@ -57,7 +57,7 @@
}
<div class="row">
<div class="col-md-12">
If BTCPay Server shows you an invalid balance, <a asp-action="WalletRescan" asp-route-walletId="@this.Context.GetRouteValue("walletId")">rescan your wallet</a>. <br />
If BTCPay Server shows you an invalid balance, <a asp-action="WalletRescan">rescan your wallet</a>. <br />
If some transactions appear in BTCPay Server, but are missing on Electrum or another wallet, <a href="https://docs.btcpayserver.org/faq-and-common-issues/faq-wallet#missing-payments-in-my-software-or-hardware-wallet">follow those instructions</a>.
</div>
</div>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

View File

@ -1,5 +1,5 @@
<Project>
<PropertyGroup>
<Version>1.0.3.155</Version>
<Version>1.0.3.153</Version>
</PropertyGroup>
</Project>