Compare commits

...

13 Commits

17 changed files with 131 additions and 41 deletions

17
.gitattributes vendored Normal file

@ -0,0 +1,17 @@
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto
# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
*.c text
*.h text
# Declare files that will always have CRLF line endings on checkout.
*.sln text eol=crlf
# Declare files that will always have CRLF line endings on checkout.
*.sh text eol=lf
# Denote all files that are truly binary and should not be modified.
*.png binary
*.jpg binary

@ -40,7 +40,7 @@ services:
- lightning-charged
nbxplorer:
image: nicolasdorier/nbxplorer:1.0.1.17
image: nicolasdorier/nbxplorer:1.0.1.19
ports:
- "32838:32838"
expose:

@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
<Version>1.0.1.43</Version>
<Version>1.0.1.45</Version>
<NoWarn>NU1701,CA1816,CA1308,CA1810,CA2208</NoWarn>
</PropertyGroup>
<ItemGroup>
@ -31,10 +31,10 @@
<PackageReference Include="Meziantou.AspNetCore.BundleTagHelpers" Version="1.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Filter" Version="1.1.2" />
<PackageReference Include="Microsoft.NetCore.Analyzers" Version="2.6.0" />
<PackageReference Include="NBitcoin" Version="4.0.0.59" />
<PackageReference Include="NBitcoin" Version="4.0.0.60" />
<PackageReference Include="NBitpayClient" Version="1.0.0.18" />
<PackageReference Include="DBreeze" Version="1.87.0" />
<PackageReference Include="NBXplorer.Client" Version="1.0.1.10" />
<PackageReference Include="NBXplorer.Client" Version="1.0.1.14" />
<PackageReference Include="NicolasDorier.CommandLine" Version="1.0.0.1" />
<PackageReference Include="NicolasDorier.CommandLine.Configuration" Version="1.0.0.2" />
<PackageReference Include="NicolasDorier.StandardConfiguration" Version="1.0.0.13" />

@ -68,11 +68,11 @@ namespace BTCPayServer.Controllers
{
var cryptoInfo = dto.CryptoInfo.First(o => o.GetpaymentMethodId() == data.GetId());
var accounting = data.Calculate();
var paymentNetwork = _NetworkProvider.GetNetwork(data.GetId().CryptoCode);
var paymentMethodId = data.GetId();
var cryptoPayment = new InvoiceDetailsModel.CryptoPayment();
cryptoPayment.CryptoCode = paymentNetwork.CryptoCode;
cryptoPayment.Due = accounting.Due.ToString() + $" {paymentNetwork.CryptoCode}";
cryptoPayment.Paid = accounting.CryptoPaid.ToString() + $" {paymentNetwork.CryptoCode}";
cryptoPayment.PaymentMethod = ToString(paymentMethodId);
cryptoPayment.Due = accounting.Due.ToString() + $" {paymentMethodId.CryptoCode}";
cryptoPayment.Paid = accounting.CryptoPaid.ToString() + $" {paymentMethodId.CryptoCode}";
var onchainMethod = data.GetPaymentMethodDetails() as Payments.Bitcoin.BitcoinLikeOnChainPaymentMethod;
if(onchainMethod != null)
@ -86,13 +86,13 @@ namespace BTCPayServer.Controllers
var payments = invoice
.GetPayments()
.Where(p => p.GetpaymentMethodId().PaymentType == PaymentTypes.BTCLike)
.Where(p => p.GetPaymentMethodId().PaymentType == PaymentTypes.BTCLike)
.Select(async payment =>
{
var paymentData = (Payments.Bitcoin.BitcoinLikePaymentData)payment.GetCryptoPaymentData();
var m = new InvoiceDetailsModel.Payment();
var paymentNetwork = _NetworkProvider.GetNetwork(payment.GetCryptoCode());
m.CryptoCode = payment.GetCryptoCode();
m.PaymentMethod = ToString(payment.GetPaymentMethodId());
m.DepositAddress = paymentData.Output.ScriptPubKey.GetDestinationAddress(paymentNetwork.NBitcoinNetwork);
int confirmationCount = 0;
@ -121,12 +121,32 @@ namespace BTCPayServer.Controllers
})
.ToArray();
await Task.WhenAll(payments);
model.Addresses = invoice.HistoricalAddresses;
model.Addresses = invoice.HistoricalAddresses.Select(h=> new InvoiceDetailsModel.AddressModel
{
Destination = h.GetAddress(),
PaymentMethod = ToString(h.GetPaymentMethodId()),
Current = !h.UnAssigned.HasValue
}).ToArray();
model.Payments = payments.Select(p => p.GetAwaiter().GetResult()).ToList();
model.StatusMessage = StatusMessage;
return View(model);
}
private string ToString(PaymentMethodId paymentMethodId)
{
var type = paymentMethodId.PaymentType.ToString();
switch (paymentMethodId.PaymentType)
{
case PaymentTypes.BTCLike:
type = "On-Chain";
break;
case PaymentTypes.LightningLike:
type = "Off-Chain";
break;
}
return $"{paymentMethodId.CryptoCode} ({type})";
}
[HttpGet]
[Route("i/{invoiceId}")]
[Route("i/{invoiceId}/{paymentMethodId}")]
@ -220,7 +240,7 @@ namespace BTCPayServer.Controllers
.ToList()
};
var isMultiCurrency = invoice.GetPayments().Select(p=>p.GetpaymentMethodId()).Concat(new[] { paymentMethod.GetId() }).Distinct().Count() > 1;
var isMultiCurrency = invoice.GetPayments().Select(p=>p.GetPaymentMethodId()).Concat(new[] { paymentMethod.GetId() }).Distinct().Count() > 1;
if (isMultiCurrency)
model.NetworkFeeDescription = $"{accounting.NetworkFee} {network.CryptoCode}";

@ -27,9 +27,10 @@ namespace BTCPayServer.Data
public string CryptoCode { get; set; }
#pragma warning disable CS0618
public string GetCryptoCode()
public Payments.PaymentMethodId GetPaymentMethodId()
{
return string.IsNullOrEmpty(CryptoCode) ? "BTC" : CryptoCode;
return string.IsNullOrEmpty(CryptoCode) ? new Payments.PaymentMethodId("BTC", Payments.PaymentTypes.BTCLike)
: Payments.PaymentMethodId.Parse(CryptoCode);
}
public string GetAddress()
{

@ -12,16 +12,22 @@ namespace BTCPayServer.Models.InvoicingModels
{
public class CryptoPayment
{
public string CryptoCode { get; set; }
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 class AddressModel
{
public string PaymentMethod { get; set; }
public string Destination { get; set; }
public bool Current { get; set; }
}
public class Payment
{
public string CryptoCode { get; set; }
public string PaymentMethod { get; set; }
public string Confirmations
{
get; set;
@ -126,7 +132,7 @@ namespace BTCPayServer.Models.InvoicingModels
get;
internal set;
}
public HistoricalAddressInvoiceData[] Addresses { get; set; }
public AddressModel[] Addresses { get; set; }
public DateTimeOffset MonitoringDate { get; internal set; }
public List<Data.InvoiceEventData> Events { get; internal set; }
}

@ -213,7 +213,7 @@ namespace BTCPayServer.Payments.Bitcoin
IEnumerable<BitcoinLikePaymentData> GetAllBitcoinPaymentData(InvoiceEntity invoice)
{
return invoice.GetPayments()
.Where(p => p.GetpaymentMethodId().PaymentType == PaymentTypes.BTCLike)
.Where(p => p.GetPaymentMethodId().PaymentType == PaymentTypes.BTCLike)
.Select(p => (BitcoinLikePaymentData)p.GetCryptoPaymentData());
}
@ -227,7 +227,7 @@ namespace BTCPayServer.Payments.Bitcoin
var conflicts = GetConflicts(transactions.Select(t => t.Value));
foreach (var payment in invoice.GetPayments(wallet.Network))
{
if (payment.GetpaymentMethodId().PaymentType != PaymentTypes.BTCLike)
if (payment.GetPaymentMethodId().PaymentType != PaymentTypes.BTCLike)
continue;
var paymentData = (BitcoinLikePaymentData)payment.GetCryptoPaymentData();
if (!transactions.TryGetValue(paymentData.Outpoint.Hash, out TransactionResult tx))

@ -655,7 +655,7 @@ namespace BTCPayServer.Services.Invoices
.OrderBy(p => p.ReceivedTime)
.Select(_ =>
{
var txFee = _.GetValue(paymentMethods, GetId(), paymentMethods[_.GetpaymentMethodId()].GetTxFee());
var txFee = _.GetValue(paymentMethods, GetId(), paymentMethods[_.GetPaymentMethodId()].GetTxFee());
paid += _.GetValue(paymentMethods, GetId());
if (!paidEnough)
{
@ -663,7 +663,7 @@ namespace BTCPayServer.Services.Invoices
paidTxFee += txFee;
}
paidEnough |= paid >= RoundUp(totalDue, 8);
if (GetId() == _.GetpaymentMethodId())
if (GetId() == _.GetPaymentMethodId())
{
cryptoPaid += _.GetCryptoPaymentData().GetValue();
txRequired++;
@ -766,7 +766,7 @@ namespace BTCPayServer.Services.Invoices
paymentData.Legacy = true;
return paymentData;
}
if (GetpaymentMethodId().PaymentType == PaymentTypes.BTCLike)
if (GetPaymentMethodId().PaymentType == PaymentTypes.BTCLike)
{
var paymentData = JsonConvert.DeserializeObject<Payments.Bitcoin.BitcoinLikePaymentData>(CryptoPaymentData);
// legacy
@ -774,7 +774,7 @@ namespace BTCPayServer.Services.Invoices
paymentData.Outpoint = Outpoint;
return paymentData;
}
if(GetpaymentMethodId().PaymentType== PaymentTypes.LightningLike)
if(GetPaymentMethodId().PaymentType== PaymentTypes.LightningLike)
{
return JsonConvert.DeserializeObject<Payments.Lightning.LightningLikePaymentData>(CryptoPaymentData);
}
@ -802,7 +802,7 @@ namespace BTCPayServer.Services.Invoices
{
value = value ?? this.GetCryptoPaymentData().GetValue();
var to = paymentMethodId;
var from = this.GetpaymentMethodId();
var from = this.GetPaymentMethodId();
if (to == from)
return decimal.Round(value.Value, 8);
var fromRate = paymentMethods[from].Rate;
@ -813,7 +813,7 @@ namespace BTCPayServer.Services.Invoices
return otherCurrencyValue;
}
public PaymentMethodId GetpaymentMethodId()
public PaymentMethodId GetPaymentMethodId()
{
#pragma warning disable CS0618 // Type or member is obsolete
return new PaymentMethodId(CryptoCode ?? "BTC", string.IsNullOrEmpty(CryptoPaymentDataType) ? PaymentTypes.BTCLike : Enum.Parse<PaymentTypes>(CryptoPaymentDataType));

@ -169,8 +169,9 @@
<div adjust-height="" class="payment-box">
<div class="bp-view payment scan" id="scan">
<div class="payment__scan">
<img :src="srvModel.cryptoImage" style="position: absolute; height:64px; width:64px; left:118px; top:96px;" />
<qrcode :val="srvModel.invoiceBitcoinUrlQR" :size="256" bg-color="#f5f5f7" fg-color="#000" />
<img v-bind:src="srvModel.cryptoImage" style="position: absolute; height:64px; width:64px; left:118px; top:96px;" />
<qrcode v-bind:val="srvModel.invoiceBitcoinUrlQR" v-bind:size="256" bg-color="#f5f5f7" fg-color="#000">
</qrcode>
</div>
<div class="payment__details__instruction__open-wallet">
<a class="payment__details__instruction__open-wallet__btn action-button" v-bind:href="srvModel.invoiceBitcoinUrl">

@ -153,7 +153,7 @@
<table class="table">
<thead class="thead-inverse">
<tr>
<th>Crypto</th>
<th style="white-space:nowrap;">Payment method</th>
<th>Rate</th>
<th>Paid</th>
<th>Due</th>
@ -164,7 +164,7 @@
@foreach(var payment in Model.CryptoPayments)
{
<tr>
<td>@payment.CryptoCode</td>
<td>@payment.PaymentMethod</td>
<td>@payment.Rate</td>
<td>@payment.Paid</td>
<td>@payment.Due</td>
@ -181,8 +181,7 @@
<table class="table">
<thead class="thead-inverse">
<tr>
<th>Crypto</th>
<th>Date</th>
<th style="white-space:nowrap;">Payment method</th>
<th>Deposit address</th>
<th>Transaction Id</th>
<th>Confirmations</th>
@ -193,8 +192,7 @@
@foreach(var payment in Model.Payments)
{
<tr>
<td>@payment.CryptoCode</td>
<td>@payment.ReceivedTime</td>
<td>@payment.PaymentMethod</td>
<td>@payment.DepositAddress</td>
<td><a href="@payment.TransactionLink" target="_blank">@payment.TransactionId</a></td>
<td>@payment.Confirmations</td>
@ -211,7 +209,7 @@
<table class="table">
<thead class="thead-inverse">
<tr>
<th>Crypto</th>
<th style="white-space:nowrap;">Payment method</th>
<th>Address</th>
<th>Current</th>
</tr>
@ -220,11 +218,11 @@
@foreach(var address in Model.Addresses)
{
<tr>
<td>@address.GetCryptoCode()</td>
<td>@address.GetAddress()</td>
<td>@(!address.UnAssigned.HasValue)</td>
<td style="width:100px;">@address.PaymentMethod</td>
<td style="max-width:100px;overflow:hidden;">@address.Destination</td>
<td>@address.Current.ToString()</td>
</tr>
}
}
</tbody>
</table>
</div>

@ -1,6 +1,10 @@
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
<g transform="translate(0.00630876,-0.00301984) scale(0.25,0.25)">
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="64" width="64" version="1.1"
x="0px" y="0px"
viewBox="0 0 64 64"
xml:space="preserve"
xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
<g transform="translate(0.00630876,-0.00301984)">
<path fill="#f7931a" d="m63.033,39.744c-4.274,17.143-21.637,27.576-38.782,23.301-17.138-4.274-27.571-21.638-23.295-38.78,4.272-17.145,21.635-27.579,38.775-23.305,17.144,4.274,27.576,21.64,23.302,38.784z"/>
<path fill="#FFF" d="m46.103,27.444c0.637-4.258-2.605-6.547-7.038-8.074l1.438-5.768-3.511-0.875-1.4,5.616c-0.923-0.23-1.871-0.447-2.813-0.662l1.41-5.653-3.509-0.875-1.439,5.766c-0.764-0.174-1.514-0.346-2.242-0.527l0.004-0.018-4.842-1.209-0.934,3.75s2.605,0.597,2.55,0.634c1.422,0.355,1.679,1.296,1.636,2.042l-1.638,6.571c0.098,0.025,0.225,0.061,0.365,0.117-0.117-0.029-0.242-0.061-0.371-0.092l-2.296,9.205c-0.174,0.432-0.615,1.08-1.609,0.834,0.035,0.051-2.552-0.637-2.552-0.637l-1.743,4.019,4.569,1.139c0.85,0.213,1.683,0.436,2.503,0.646l-1.453,5.834,3.507,0.875,1.439-5.772c0.958,0.26,1.888,0.5,2.798,0.726l-1.434,5.745,3.511,0.875,1.453-5.823c5.987,1.133,10.489,0.676,12.384-4.739,1.527-4.36-0.076-6.875-3.226-8.515,2.294-0.529,4.022-2.038,4.483-5.155zm-8.022,11.249c-1.085,4.36-8.426,2.003-10.806,1.412l1.928-7.729c2.38,0.594,10.012,1.77,8.878,6.317zm1.086-11.312c-0.99,3.966-7.1,1.951-9.082,1.457l1.748-7.01c1.982,0.494,8.365,1.416,7.334,5.553z"/>
</g>

Before

(image error) Size: 1.5 KiB

After

(image error) Size: 1.5 KiB

@ -71,7 +71,8 @@ function fetchStatus() {
var path = srvModel.serverUrl + "/i/" + srvModel.invoiceId + "/" + srvModel.paymentMethodId + "/status";
$.ajax({
url: path,
type: "GET"
type: "GET",
cache: false
}).done(function (data) {
onDataCallback(data);
}).fail(function (jqXHR, textStatus, errorThrown) {

@ -25,3 +25,37 @@ This solution is for you if:
Please check out our [complete documentation](https://github.com/btcpayserver/btcpayserver-doc) for more details.
You can also checkout [The Merchants Guide to accepting Bitcoin directly with no intermediates through BTCPay](https://www.reddit.com/r/Bitcoin/comments/81h1oy/the_merchants_guide_to_accepting_bitcoin_directly/).
## How to build
While the documentation advise using docker-compose, you may want to build yourself outside of development purpose.
First install .NET Core SDK as specified by [Microsoft website](https://www.microsoft.com/net/download).
On Powershell:
```
.\build.ps1
```
On linux:
```
./build.sh
```
## How to run
Use the `run` scripts to run BTCPayServer, this example show how to print the available command line arguments of BTCPayServer.
On Powershell:
```
.\run.ps1 --help
```
On linux:
```
./run.sh --help
```
## Other dependencies
For more information see the documentation [How to deploy a BTCPay server instance](https://github.com/btcpayserver/btcpayserver-doc/blob/master/Deployment.md).

1
build.ps1 Executable file

@ -0,0 +1 @@
dotnet build -c Release .\BTCPayServer\BTCPayServer.csproj

3
build.sh Executable file

@ -0,0 +1,3 @@
#!/bin/bash
dotnet build -c Release BTCPayServer/BTCPayServer.csproj

1
run.ps1 Executable file

@ -0,0 +1 @@
dotnet run --no-launch-profile --no-build -c Release -p .\BTCPayServer\BTCPayServer.csproj -- $args

3
run.sh Executable file

@ -0,0 +1,3 @@
#!/bin/bash
dotnet run --no-launch-profile --no-build -c Release -p "BTCPayServer/BTCPayServer.csproj" -- "$@"